feat: auto-create default config on register + resume via session_id
This commit is contained in:
60
__init__.py
60
__init__.py
@@ -144,6 +144,49 @@ def _build_row(columns: list, session: dict, index: int = 0) -> str:
|
||||
return " ".join(parts)
|
||||
|
||||
|
||||
# ── Default config bootstrapping ─────────────────────────────────────
|
||||
|
||||
def _ensure_default_config() -> None:
|
||||
"""Create session_list_config.yaml with sensible defaults if missing."""
|
||||
config_path = _hermes_home() / "session_list_config.yaml"
|
||||
if config_path.exists():
|
||||
return
|
||||
|
||||
default_config = """\
|
||||
# Hermes Session List — Column Configuration
|
||||
#
|
||||
# columns: ordered list of columns to display.
|
||||
# field: session row key — available fields:
|
||||
# # (row index), id, source, model, title, started_at,
|
||||
# ended_at, message_count, preview, last_active,
|
||||
# input_tokens, output_tokens, total_tokens, net_input, net_total,
|
||||
# cache_read_tokens, cache_write_tokens, reasoning_tokens
|
||||
# width: column width in characters
|
||||
# (0 = free-form for the LAST column — can overflow)
|
||||
# label: header text
|
||||
#
|
||||
# NOTE: input_tokens = cache miss (Hermes already deducts cache hits).
|
||||
# net_input = max(0, input - cache) — would double-deduct.
|
||||
#
|
||||
# Used by /sl slash command. Survives `hermes update`.
|
||||
|
||||
columns:
|
||||
- {field: last_active, width: 10, label: Active}
|
||||
- {field: title, width: 42, label: Title}
|
||||
- {field: message_count, width: 4, label: Msgs}
|
||||
- {field: cache_read_tokens, width: 6, label: Hit}
|
||||
- {field: input_tokens, width: 6, label: Miss}
|
||||
- {field: output_tokens, width: 6, label: Out}
|
||||
- {field: id, width: 34, label: Session ID}
|
||||
"""
|
||||
|
||||
try:
|
||||
config_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
config_path.write_text(default_config, encoding="utf-8")
|
||||
except Exception:
|
||||
pass # Silent fail — handler falls back to hardcoded defaults
|
||||
|
||||
|
||||
# ── Slash command handler ────────────────────────────────────────────
|
||||
|
||||
def _handle_sl(raw_args: str) -> Optional[str]:
|
||||
@@ -164,11 +207,13 @@ def _handle_sl(raw_args: str) -> Optional[str]:
|
||||
|
||||
if not columns:
|
||||
columns = [
|
||||
{"field": "#", "width": 3, "label": "#"},
|
||||
{"field": "title", "width": 32, "label": "Title"},
|
||||
{"field": "preview", "width": 40, "label": "Preview"},
|
||||
{"field": "last_active", "width": 13, "label": "Last Active"},
|
||||
{"field": "id", "width": 0, "label": "ID"},
|
||||
{"field": "last_active", "width": 10, "label": "Active"},
|
||||
{"field": "title", "width": 42, "label": "Title"},
|
||||
{"field": "message_count", "width": 4, "label": "Msgs"},
|
||||
{"field": "cache_read_tokens", "width": 6, "label": "Hit"},
|
||||
{"field": "input_tokens", "width": 6, "label": "Miss"},
|
||||
{"field": "output_tokens", "width": 6, "label": "Out"},
|
||||
{"field": "id", "width": 34, "label": "Session ID"},
|
||||
]
|
||||
|
||||
# Parse limit from args
|
||||
@@ -197,7 +242,7 @@ def _handle_sl(raw_args: str) -> Optional[str]:
|
||||
|
||||
# Add hint for /resume
|
||||
lines.append("")
|
||||
lines.append("Use /resume <#> to continue a session. Example: /resume 2")
|
||||
lines.append("Use /resume <session_id> to continue. Example: /resume 20260612_222504_8a868b")
|
||||
|
||||
return "\n".join(lines)
|
||||
|
||||
@@ -205,6 +250,9 @@ def _handle_sl(raw_args: str) -> Optional[str]:
|
||||
# ── Plugin registration ──────────────────────────────────────────────
|
||||
|
||||
def register(ctx) -> None:
|
||||
# Ensure default config file exists on first load
|
||||
_ensure_default_config()
|
||||
|
||||
ctx.register_command(
|
||||
"sl",
|
||||
handler=_handle_sl,
|
||||
|
||||
Reference in New Issue
Block a user