@turmind/halo 1.5.2-alpha → 1.5.3-alpha

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/admin-out/404.html +1 -1
  2. package/admin-out/_next/static/chunks/{803-7128009ee0e1c10e.js → 133-33aa091fba853037.js} +1 -1
  3. package/admin-out/_next/static/chunks/989-c6c7772db8a50926.js +1 -0
  4. package/admin-out/_next/static/chunks/app/page-5f41b086cd5ad353.js +1 -0
  5. package/admin-out/_next/static/css/8809d33379458514.css +3 -0
  6. package/admin-out/index.html +1 -1
  7. package/admin-out/index.txt +5 -5
  8. package/bundled-docs/design/agent.md +3 -3
  9. package/bundled-docs/design/architecture.md +3 -3
  10. package/bundled-docs/design/background-dispatch.md +52 -45
  11. package/bundled-docs/design/express-self.md +1 -1
  12. package/bundled-docs/design/prompt-system.md +2 -2
  13. package/bundled-docs/design/session.md +22 -14
  14. package/bundled-docs/design/storage.md +3 -3
  15. package/bundled-docs/design/ws.md +30 -25
  16. package/bundled-docs/dev/add-model-provider.md +2 -2
  17. package/bundled-docs/dev/api.md +37 -18
  18. package/bundled-docs/dev/env.md +2 -2
  19. package/bundled-docs/guide/agents.md +2 -2
  20. package/bundled-docs/guide/chat.md +16 -9
  21. package/bundled-docs/guide/cli.md +11 -1
  22. package/bundled-docs/guide/sessions.md +7 -7
  23. package/bundled-docs/guide/testing-agents-and-skills.md +5 -6
  24. package/bundled-docs/requirements/chat.md +23 -9
  25. package/bundled-docs/requirements/command.md +1 -1
  26. package/bundled-docs/requirements/session.md +10 -7
  27. package/bundled-docs/requirements/terminal.md +2 -0
  28. package/dist/index.js +222 -211
  29. package/package.json +1 -1
  30. package/templates/agents/__apply_agent__/agent.yaml +2 -2
  31. package/templates/agents/__evo_agent__/agent.yaml +2 -2
  32. package/templates/agents/__score__/agent.yaml +2 -2
  33. package/templates/agents/deep-executor/agent.yaml +2 -2
  34. package/templates/agents/default/agent.yaml +2 -2
  35. package/templates/agents/executor/agent.yaml +2 -2
  36. package/templates/agents/goal/agent.yaml +2 -2
  37. package/templates/models/anthropic.yaml +1 -1
  38. package/templates/models/aws-bedrock-claude-invoke.yaml +10 -10
  39. package/templates/models/aws-bedrock-mantle.yaml +4 -4
  40. package/templates/models/aws-bedrock-openai.yaml +6 -6
  41. package/templates/models/deepseek.yaml +2 -2
  42. package/templates/models/kimi.yaml +1 -1
  43. package/templates/models/mimo-token-plan-china.yaml +4 -4
  44. package/templates/models/minimax.yaml +1 -1
  45. package/templates/models/qwen.yaml +2 -2
  46. package/templates/models/zhipu.yaml +4 -4
  47. package/templates/prompts/root/DELEGATION.md +17 -7
  48. package/templates/skills/agent/SKILL.md +2 -2
  49. package/admin-out/_next/static/chunks/989-7420ee650083df43.js +0 -1
  50. package/admin-out/_next/static/chunks/app/page-fa5e935dbaa74165.js +0 -1
  51. package/admin-out/_next/static/css/b8ffb5202b5a6619.css +0 -3
  52. /package/admin-out/_next/static/{DLRpRENVwZ-EHTRGc9AzB → Wqi_ugna9MYsiV7ECuawQ}/_buildManifest.js +0 -0
  53. /package/admin-out/_next/static/{DLRpRENVwZ-EHTRGc9AzB → Wqi_ugna9MYsiV7ECuawQ}/_ssgManifest.js +0 -0
@@ -88,13 +88,15 @@ If the session is currently compacting or busy when your message arrives, you'll
88
88
 
89
89
  ## Interrupt vs Stop
90
90
 
91
- Two ways to interrupt the agent:
91
+ Three ways to cut in while the agent is running:
92
92
 
93
- **Graceful interrupt**: send another message during streaming. The message is queued on the server; at the next tool-call checkpoint, the agent wraps up the current turn and then runs the queued message. Multiple messages can queue in order.
93
+ **Send another message (soft)**: the message is queued on the server; the agent finishes the tool it's on, wraps up the turn, then runs the queued message. Multiple messages can queue in order. A running command is not killed.
94
94
 
95
- **Hard stop**: click the red ⏹ button. Immediate abort, queue cleared, no checkpoint waiting.
95
+ **Esc — interrupt** (with the input box empty): aborts the turn immediately, including a tool or command mid-run, then any messages queued while it ran fold into one follow-up turn — the agent keeps going with what you said. Same as `/session interrupt`.
96
96
 
97
- **Exception — compaction.** An auto-compact (triggered mid-turn when context reaches `compressAt`) can't be interrupted: ⏹ or Esc during it only takes effect once the compact finishes, and the turn doesn't continue afterwards. A manual `/session compact` can be cancelled with ⏹ — history is rolled back and you'll see `Compact cancelled`.
97
+ **⏹ — stop**: aborts the turn immediately and nothing runs afterwards. Messages queued while it ran aren't lost — they're kept in the conversation history and the agent sees them the next time you send something. Same as `/session stop`.
98
+
99
+ **Exception — compaction.** During a manual `/session compact`, Esc and ⏹ both cancel it — history is rolled back and you'll see `Compact cancelled`. An auto-compact (triggered mid-turn when context reaches `compressAt`) can't be cancelled: Esc or ⏹ during it only takes effect once the compact finishes, and then works as above.
98
100
 
99
101
  ## Token ring
100
102
 
@@ -104,17 +106,22 @@ The ring in the bottom-right of the input shows context window usage:
104
106
  - Orange: 70–90%
105
107
  - Red: > 90%
106
108
 
107
- Reaching `compressAt` (default 70%) auto-triggers compact. If the LLM summary fails or times out, Halo falls back to a local compact (notice: `Auto-compacted N older messages (local fallback — LLM summary failed: <reason>)`) rather than retrying. An auto-compact has no overall time limit — it only times out after 10 minutes with no data from the model. While the agent is running you can't click the TokenRing (guarded by `isStreaming`).
109
+ Reaching `compressAt` (default 90%, setting `general.compact.compress_at`) auto-triggers compact. If the LLM summary fails or times out, Halo falls back to a local compact (notice: `Auto-compacted N older messages (local fallback — LLM summary failed: <reason>)`) rather than retrying. An auto-compact has no overall time limit — it only times out after 10 minutes with no data from the model. While the agent is running you can't click the TokenRing (guarded by `isStreaming`).
108
110
 
109
111
  ## Session history
110
112
 
111
- Next to the header is the session-list dropdown:
112
- - Lists every session in the current workspace
113
- - Click to switch (the current one auto-saves + detaches)
114
- - Sub-agent sessions show as indented entries
113
+ Your sessions are listed as vertical tabs on the right edge of the chat panel:
114
+ - Lists the workspace's main sessions, newest first; scroll down to load older ones
115
+ - Click a tab to show that session. The one you left keeps running and streaming in its own tab: a spinner shows while it works, and a dot means new output arrived
116
+ - **+** (or `/session new`) opens a fresh tab; the session is created when you send its first message
117
+ - Hover a tab to rename it (pencil); ✕ deletes it after a confirmation — deletion can't be undone
118
+ - Drag the list's left edge to make it wider or narrower, or collapse it to a thin strip of initials
119
+ - After a refresh, the session you were on reopens
115
120
 
116
121
  For full inspection, use the Activity Bar's "Sessions" tab — Debug mode lets you inspect tool calls, system prompts, usage, etc.
117
122
 
123
+ Long messages you sent are collapsed to a one-line header: a chevron, the send time and the first few words. Click the header to expand or collapse it. A long expanded message scrolls inside its bubble. Sub-agent reports open and close from their title line the same way.
124
+
118
125
  ## Common situations
119
126
 
120
127
  **"Queued" hint**: the previous turn hasn't finished; your message is queued and will run next turn.
@@ -76,16 +76,19 @@ To list agents or sessions without running a prompt, use the dedicated subcomman
76
76
 
77
77
  - **text format**: stdout carries the agent's **final answer** — the closing text of the last turn, not the live stream. Text the agent emits before a tool call ("let me check…") and the wrap-ups of earlier turns in the same run (e.g. a director absorbing several sub-agent reports) are omitted; if the last turn had no closing text, its full text is printed instead. When stdout is a terminal the answer is rendered as styled markdown (headings, bold, code blocks, tables); when piped or redirected it is written as raw markdown so downstream tools get the text unchanged. Tool calls, thinking, usage — and, with `-v`, the agent's text as it streams — go to stderr.
78
78
 
79
+ System notices from the root session (retries, compaction, truncated output, a model refusal, `@scope` warnings) are printed on stdout before the answer, one `ℹ️ ` line each and a blank line between them and the answer. Notices from sub-agents and the sibling-status line added when sub-agent reports arrive are left out. Notices from earlier turns in the same run are kept, so a scheduled run that hit a local-fallback compact still says so in what gets pushed to chat.
80
+
79
81
  Usage line mirrors the admin chat-panel badge format (timestamp / in / out / ctx / read / write / cache% / ttft / e2e / think / model). `ctx` is the rolled-up context size — `inputTokens + cacheRead + cacheWrite + outputTokens` — so it doesn't look misleading next to a large cache hit:
80
82
 
81
83
  ```
82
84
  [ 17:23:02 in 0.0K out 0.1K ctx 5.8K read 5.3K write 0.3K cache 94% e2e 3.3s think medium claude-sonnet-4-6 ]
83
85
  ```
84
- - **json format**: Single JSON object on stdout after completion (`text` has the same final-answer semantics as text format):
86
+ - **json format**: Single JSON object on stdout after completion (`text` has the same final-answer semantics as text format; `notices` holds the same root system notices as an array of strings, without the `ℹ️ ` prefix):
85
87
 
86
88
  ```json
87
89
  {
88
90
  "text": "...",
91
+ "notices": [],
89
92
  "sessionId": "cli_abc123",
90
93
  "toolCalls": [{ "name": "file_list", "durationMs": 1 }],
91
94
  "usage": { "inputTokens": 6, "outputTokens": 42, "cacheReadInputTokens": 10000, "modelId": "..." },
@@ -155,6 +158,13 @@ TUI-only client commands (handled locally, also visible in the completion popup)
155
158
 
156
159
  Bare `/<obj>` (or `/<obj> help`) lists the verbs you may run. Verbs gated above your access level are hidden.
157
160
 
161
+ ### Status bar
162
+
163
+ The line under the input box:
164
+
165
+ - **Left**: the agent id of the current session (`/agent switch` and `/session switch` update it) · `◯ N%` context fill (shown only after the first model response reports usage; green ≤ 50%, yellow ≤ 80%, red above) · a `v` badge while verbose is on.
166
+ - **Right**: the workspace path (`~` for your home directory) · the last 8 characters of the session id.
167
+
158
168
  ### Keybindings
159
169
 
160
170
  | Key | Action |
@@ -54,13 +54,12 @@ Use it to see exactly what context the agent was given for a given turn.
54
54
 
55
55
  ## Non-destructive /session new
56
56
 
57
- Typing `/session new` in the chat:
58
- 1. Saves the current session to disk
59
- 2. Creates a background handler to keep the old session's in-flight events flowing
60
- 3. UI resets to an empty session
61
- 4. **The old session's sub-agents keep running** (not killed)
57
+ Typing `/session new` in the chat (or clicking **+** in the session tabs):
58
+ 1. Opens a new, empty tab — the session itself is created when you send its first message
59
+ 2. The old session keeps its own tab and keeps streaming into it in the background
60
+ 3. **The old session's sub-agents keep running** (not killed)
62
61
 
63
- When you switch back, the background-finished events are already in the file and render normally.
62
+ When you switch back, everything the old session did meanwhile is already there.
64
63
 
65
64
  ## Refresh / reconnect
66
65
 
@@ -68,10 +67,11 @@ Refreshing the browser or a network blip:
68
67
  - SessionManager keeps the session alive for the grace period (5 minutes)
69
68
  - On reconnect, messageLog + in-flight streaming state are restored from disk
70
69
  - If the agent is still running, live streaming resumes; if it finished, the full history loads
70
+ - Only the chat tab on screen reconnects right away; your other session tabs reload when you click them
71
71
 
72
72
  ## Deleting a session
73
73
 
74
- Right-click a session → Delete:
74
+ Click a session's trash icon (Sessions page) or ✕ on its chat tab, then confirm:
75
75
  - Cascade delete in SQLite (parent + all descendants)
76
76
  - `.halo/sessions/{agentId}/{sid}.json` removed
77
77
  - Sidebar entry removed
@@ -12,11 +12,10 @@ Activity Bar → `👥 Agents` → click the agent you want to test.
12
12
 
13
13
  Top-right `Test` button. What it does, concretely:
14
14
 
15
- 1. Detaches any active chat session from the Explorer panel
16
- 2. Clears the selected agent override and sets it to this agent (`selectedAgentId`)
17
- 3. Dispatches a `halo:navigate` event that switches to the Explorer tab
15
+ 1. Opens a new draft chat tab in the Explorer panel with this agent selected (`newTab(agentId)` — an untouched draft tab is reused). Any session you already had open keeps its own tab, and keeps running if it was busy
16
+ 2. Dispatches a `halo:navigate` event that switches to the Explorer tab
18
17
 
19
- Source: [packages/admin/src/features/agents/agent-management-main.tsx:278-290](../../../packages/admin/src/features/agents/agent-management-main.tsx#L278-L290).
18
+ Source: `testAgent` in [packages/admin/src/features/agents/agent-management-main.tsx](../../../packages/admin/src/features/agents/agent-management-main.tsx).
20
19
 
21
20
  ### 3. Start chatting
22
21
 
@@ -123,13 +122,13 @@ Sessions → select → context menu → Delete. Or programmatically: `DELETE /a
123
122
 
124
123
  ### "Test button does something weird" — the session is orphaned
125
124
 
126
- If clicking Test sometimes shows a stale conversation instead of a new one, you might be seeing a previously-detached session that hasn't been cleared. The Test handler explicitly clears `localStorage.halo_session_<projectId>` and the in-memory `sessionId` — but an in-flight WS message can race. Refresh the page; it should settle.
125
+ Since 1.5.3-alpha, Test no longer clears any stored session: it only opens a new draft tab (the old `localStorage.halo_session_<projectId>` key is gone). The new session is created by the first message you send from that tab. If you see an old conversation instead of an empty one, the draft tab isn't the one on screen. Click **+** at the bottom of the session tabs to bring it back (an unused draft is reused).
127
126
 
128
127
  ---
129
128
 
130
129
  ## References
131
130
 
132
- - Test button implementation: [packages/admin/src/features/agents/agent-management-main.tsx:278-290](../../../packages/admin/src/features/agents/agent-management-main.tsx#L278-L290)
131
+ - Test button implementation: `testAgent` in [packages/admin/src/features/agents/agent-management-main.tsx](../../../packages/admin/src/features/agents/agent-management-main.tsx)
133
132
  - `activate_skill` runtime: [packages/server/src/agents/agent-loader.ts:111-159](../../../packages/server/src/agents/agent-loader.ts#L111-L159) (function `createSkillTool`)
134
133
  - Skill metadata → system prompt: [packages/server/src/agents/agent-loader.ts:97-102](../../../packages/server/src/agents/agent-loader.ts#L97-L102) (function `buildSkillPrompt`)
135
134
  - Chat session creation on first message: [packages/server/src/ws/handler.ts:263-344](../../../packages/server/src/ws/handler.ts#L263-L344) (function `handleChat`)
@@ -24,14 +24,20 @@ The primary surface for talking to an agent.
24
24
  - Tool-call card: expandable, shows tool name / input / output
25
25
  - Sub-agent messages carry the agent-name label (e.g. "Coder", "Researcher")
26
26
  - Streaming text has a cursor animation
27
- - The user bubble shows its send time (`HH:mm`, browser-local) at the bubble's bottom-right, right edge aligned with the Delete icon above it; hovering it gives the full date. Same bubble component as the Sessions tab, so both surfaces get it
27
+ - The user bubble shows its send time (`HH:mm`, browser-local) at the left of its header row, after the expand chevron (see [User-message actions](#user-message-actions-expand--copy--delete)); hovering it gives the full date. Same bubble component as the Sessions tab, so both surfaces get it
28
+ - In Debug mode the system-prompt `context` row stays in the list but doesn't open an exchange of its own, so there is no blank strip above the first bubble
28
29
 
29
30
  ### Debug toggle
30
- A Bug-icon **Debug** button in the composer's left control cluster (next to the session-list / new-session buttons) switches the message list into the same debug rendering as the Sessions tab — see [requirements/session.md → Debug mode](session.md#debug-mode) for what it shows (tool calls, usage lines with token counts / latency / model, sub-agent start/done markers, thinking blocks). Persists in `localStorage` under its own key `halo_chat_debug`, independent of the Sessions tab's `halo_session_debug`. No Prompt button here — the system prompt viewer stays a Sessions-tab feature.
31
+ A Bug-icon **Debug** button in the composer's left control cluster (next to the agent selector) switches the message list into the same debug rendering as the Sessions tab — see [requirements/session.md → Debug mode](session.md#debug-mode) for what it shows (tool calls, usage lines with token counts / latency / model, sub-agent start/done markers, thinking blocks). Persists in `localStorage` under its own key `halo_chat_debug`, independent of the Sessions tab's `halo_session_debug`. No Prompt button here — the system prompt viewer stays a Sessions-tab feature.
31
32
 
32
33
  ### User-message actions (Expand / Copy / Delete)
33
34
  Actions on user-role turns: the blue sticky user bubble, plus the sub-agent-report (green) and compact-summary (purple) callouts — all three share the same Copy/Delete pair. The icons are **always visible** (not hover-only). On the callouts, Copy copies the body only (the `(from: session X)` / `[Conversation Summary…]` marker line is stripped); a deleted callout greys out and gains a "deleted" badge like the bubble does:
34
- - **Expand / Collapse** — an arrow icon (chevron-down to expand, chevron-up to collapse) to the left of Copy, on the user bubble and the report callout; it appears only when the body is actually clamped, so short bodies have no arrow. (The compact-summary callout is collapsed by default and toggles from its own header instead)
35
+ - **Expand / Collapse** — from a **header row**, not an icon in the action group (the top-right expand arrow was removed in 1.5.3-alpha):
36
+ - **User bubble**: the header row holds a chevron, the send time and, while collapsed, a preview (the first 20 characters, then `…`). A long message is **collapsed by default**: the body height is 0, so only the header row shows. Clicking anywhere on the row toggles it.
37
+ - **Report callout**: its "Report from sub-session" title row toggles the same way.
38
+ - The chevron only appears when the body is actually clamped; a short body has no chevron and its row does nothing on click.
39
+ - An expanded body is capped at 40vh and scrolls inside the bubble, because the bubbles are sticky.
40
+ - The compact-summary callout is collapsed by default and toggles from its own header, as before.
35
41
  - **Copy** — copies the prompt text to the clipboard
36
42
  - **Delete** (confirm dialog) — removes the whole exchange (the user turn + all responses up to the next user turn) with **two-layer semantics**: the LLM context (`rawMessages`) drops the turn physically — the model never sees it again, freeing context; the UI keeps the messages, rendered greyed-out with a "deleted" tag, as an audit trail. No undo; a deleted exchange loses its Delete button. Rejected with an error toast while the agent is running or compacting. Root sessions only (sub-session logs don't offer Delete). If the turn was already compacted out of raw context, only the UI marking happens (silent degrade). Once a session has **archived history** the action is refused for the whole session with a plain explanatory notice (not an `Error:` bubble) — per-turn positions can no longer be mapped once older turns left the active file. Design details in [design/session.md](../design/session.md#exchange-deletion-soft-ui--hard-raw), protocol in [design/ws.md](../design/ws.md).
37
43
 
@@ -46,12 +52,20 @@ Long sessions get their older exchanges moved out of the active log on compact,
46
52
  - Archived exchanges are **read-only**: Copy still works, Delete is absent (the server refuses it for archived sessions)
47
53
  - Segments already loaded aren't re-fetched; a failed load can simply be retried with the same row
48
54
 
49
- ### Session sidebar (right side)
50
- A fixed, collapsible list of the workspace's root sessions on the right edge of the chat panel (terminal-list style, ~200px). Replaces the old popup dropdown — the History button (with count badge) left of the composer and the "N previous sessions" link in the empty state both just toggle it now. Open/collapsed state persists globally in `localStorage` (`halo_session_sidebar_open`), default open.
51
-
52
- - Each row: title, `N msgs · time-ago`, model tail; hover reveals **rename** (pencil) and **delete** buttons; infinite scroll pages older sessions; "+ New Session" footer. `N` counts the session's user turns **over its whole lifetime** — compacting or archiving history never makes it go backwards
55
+ ### Session tabs (right side)
56
+ The workspace's root sessions as **Chrome-style vertical tabs** on the right edge of the chat panel (`VerticalTabList` rows inside a `ResizableSidebar`, default 200px). The list **is** the tab list: every session is "open", clicking a row shows it, and there is no close — deleting the session is the only way a tab goes away. Since 1.5.3-alpha this replaces the top tab strip, the History and New-session buttons beside the composer, and the "N previous sessions" link in the empty state.
57
+
58
+ - **Resize / collapse**: drag the left edge to resize (120–480px). Collapse from the header; the collapsed list is a `w-10` rail of square tabs, each showing the title's first letter plus running / unread marks, with a "+" at the bottom. Both settings are global preferences in `localStorage` (`halo_session_sidebar_open`, `halo_session_sidebar_width`); the list is open by default.
59
+ - **Rows**: one line per row, 🎯 + title. Message count, time-ago and model are in the tooltip. `N msgs` counts the session's user turns **over its whole lifetime**, so compacting or archiving history never makes it go backwards.
60
+ - A spinner icon shows while the session is running. For a tab that hasn't loaded yet, this comes from the list endpoint's `status`.
61
+ - An unread dot appears when output lands while the tab isn't on screen.
62
+ - Infinite scroll pages older sessions. A "+" footer starts a new session.
63
+ - **New session**: "+", `/session new` and `/clear` open a **draft tab**. A "New session" row sits on top while it is on screen, and an untouched draft is reused rather than duplicated. The session is created by the draft's first message or command. The previous session keeps streaming in its own tab.
64
+ - **Background tabs**: one WS connection carries every loaded tab, so a session that isn't on screen keeps receiving its turn. After a reconnect only the tab on screen is reattached; the others reload when clicked. Live capture and face (`<<<SHOW>>>`) markers only act for the tab on screen.
65
+ - **Delete (✕)**: deletes the session after a confirm dialog in the UI language ("Delete this session? Its history cannot be recovered." / its Chinese counterpart). Deletion is the REST delete first, then the WS one, so sub-session files go too. The ✕ is always visible on the active tab and appears on hover for the others; hover also reveals a **rename** pencil.
53
66
  - **Inline rename**: pencil → input in place, Enter/blur commits (`PATCH /sessions/logs/:id`), Esc cancels; empty or unchanged title is a no-op. Other session-list consumers refresh via the `session:changed` WS push
54
- - **Switch loading**: clicking a row shows a spinner on that row + a "Loading session…" state in the message area, cleared only when the server's `state:snapshot` for that exact sessionId arrives (empty sessions included). Past 30s it degrades to "Slow network — still loading…" plus a Retry button (re-subscribes) — slow ≠ failed, nothing aborts on its own
67
+ - **Persistence**: only the session on screen is remembered, per workspace, as `{active}` under `halo_chat_tabs_<projectId>`. A refresh restores and loads only that tab. The pre-tabs keys `halo_session_<projectId>` / `halo_session_id` are read once to seed it and then removed.
68
+ - **Switch loading**: clicking a row that hasn't loaded yet shows a spinner on that row + a "Loading session…" state in the message area, cleared only when the server's `state:snapshot` for that exact sessionId arrives (empty sessions included). Past 30s it degrades to "Slow network — still loading…" plus a Retry button (re-subscribes) — slow ≠ failed, nothing aborts on its own. Switching to an already-loaded tab is instant, and its scroll position is restored
55
69
 
56
70
  ### Slash commands
57
71
 
@@ -116,4 +130,4 @@ A second channel beyond text: a visual space the agent drives in real time to ex
116
130
  - **Identity.** Deliberately nameless ("HELLO / A MIND / IS HERE / BEYOND WORDS") — the conversational identity is user-configurable and the model may not be Claude, so the face never hard-codes a name.
117
131
 
118
132
  ### Token usage
119
- `TokenRing` shows live context window usage. Crossing `model.compressAt` (default 80%) auto-triggers compact.
133
+ `TokenRing` shows live context window usage. Crossing `model.compressAt` (default 90%) auto-triggers compact.
@@ -24,7 +24,7 @@ The rest are noun-verb **object commands**: `/<obj> <verb> [args]`. Some verbs a
24
24
  | `/cron` | create / list / update / enable / disable / delete — all skill verbs, full |
25
25
  | `/acp` | kiro / claude (ask a local agent directly; question = rest of line) · add / list / remove (manage generated ask-* bindings) — all full |
26
26
 
27
- Session lifecycle actions (`session:clear`, `session:delete`) are handled inline by the WS handler, not as slash commands.
27
+ Session lifecycle actions (`subscribe` / `unsubscribe`, `session:delete`) are handled inline by the WS handler, not as slash commands. In the admin, a bare `/session new` (and `/clear`) is handled client-side: it opens a new draft chat tab and sends nothing; `/session new <args>` still goes to the server. The WS `session:clear` frame was removed in 1.5.3-alpha.
28
28
 
29
29
  ### `/session info`
30
30
 
@@ -11,7 +11,9 @@ Session history viewer: hierarchy tree, message playback, debug mode, system pro
11
11
  - Collapse / expand via arrow buttons
12
12
  - Clicking the count badge (e.g. "+3") shows total descendant count
13
13
  - Inline title rename (admin-only): a hover pencil on any row — root **or** sub-agent — opens an inline input (Enter commits, Escape cancels, blur commits); persists via `PATCH /api/sessions/logs/:id`
14
- - Infinite scroll loads more roots in pages; a silent reload (after streaming ends, or a delete / create / archive elsewhere) re-fetches the **same depth** already scrolled to rather than snapping back to the first page. Capped at 300 top-level rows — past that, "load more" stops (older sessions, e.g. from a busy Slack channel, aren't worth scrolling to)
14
+ - Infinite scroll loads more roots in pages; a silent reload (after streaming ends, or a delete / create / archive elsewhere) re-fetches the **same depth** already scrolled to rather than snapping back to the first page. No cap on depth: a reload deeper than the endpoint's 500-row page limit pages through with the cursor in 500s and renders once at the end (the 300-top-level cap was removed in 1.5.3-alpha)
15
+ - Viewed sessions are cached (LRU, 20 sessions; the one on screen is never evicted): switching back to a cached session shows the kept copy at once — transcript, archive position and reading position — and a stale copy (its log file changed, or the WS reconnected) is refetched in the background. Refetches are single-flight per session: at most one request in flight plus one queued re-pull. A session that is open in an Explorer chat tab shows that tab's live stream instead
16
+ - The Sessions tab mounts on first open and then stays mounted (CSS-hidden while another activity tab is up), so the cache and reading positions survive switching tabs
15
17
 
16
18
  ### Message viewer
17
19
  - All messages rendered by role
@@ -40,12 +42,13 @@ The Prompt button (FileText icon) shows the system prompt used by this session.
40
42
  - Assistant messages persist their `contentBlocks` (text / thinking / tool calls, in the order they happened) so tool-call cards survive a refresh in the right places. Sessions written before content blocks existed carry a flat `toolCalls` array instead and still render, as a fallback
41
43
 
42
44
  ### Non-destructive /session new
43
- `/session new` (session:clear) **does not** destroy the old session:
44
- 1. Save current session to disk
45
- 2. Create a background handler to keep the old session's in-flight events flowing
46
- 3. Reset client state, enter empty conversation
47
- 4. The old session's sub-agents keep running independently
48
- 5. Switching back loads from the file
45
+ `/session new` (also `/clear` and "+ New Session") **does not** destroy the old session:
46
+ 1. A new draft tab opens in the chat panel with an empty conversation; the session is created on its first message or command
47
+ 2. The old session keeps its tab and keeps streaming into it in the background (its row shows a running mark, and an unread dot once new output lands)
48
+ 3. The old session's sub-agents keep running independently
49
+ 4. Switching back shows the old tab as it is; after a reconnect it reloads from the server
50
+
51
+ (Until 1.5.3-alpha this went through the WS `session:clear` frame and reset the single chat view; that frame has been removed.)
49
52
 
50
53
  ## Session categorisation
51
54
 
@@ -9,6 +9,8 @@ xterm.js terminal with a node-pty backend, multi-tab, reconnect-resilient.
9
9
  - Every terminal has a unique `terminalId` for routing
10
10
  - Tabs close independently
11
11
  - All tabs on a client share one WebSocket connection (multiplexed by `terminalId`)
12
+ - The tab list is a column of Chrome-style **vertical tabs** on the right of the terminal (same `VerticalTabList` + `ResizableSidebar` components as the chat session tabs). Each row has a terminal icon and its name, and a ✕ to close it, shown while more than one terminal is open. A "+" at the bottom opens a new terminal
13
+ - The list can be **resized** by dragging its left edge (120–480px, default 160px), and **collapsed** to a `w-10` rail of square icons with a "+" at the bottom. Both settings persist globally in `localStorage` (`halo_terminal_sidebar_open`, `halo_terminal_sidebar_width`)
12
14
 
13
15
  ### Working directory
14
16