pantheon-opencode 1.6.0-beta.3 → 1.6.0-beta.4

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 (36) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +19 -7
  3. package/README.pt-BR.md +17 -7
  4. package/package.json +12 -10
  5. package/plugin.json +1 -1
  6. package/pyproject.toml +1 -1
  7. package/scripts/code_mode_server.py +1 -1
  8. package/scripts/cost.mjs +244 -41
  9. package/scripts/install/agents-md.mjs +2 -2
  10. package/scripts/install/health-check.mjs +9 -2
  11. package/scripts/install/shared.mjs +5 -5
  12. package/scripts/mcp_persistence_server.py +1 -1
  13. package/scripts/mcp_resources_server.py +1 -1
  14. package/scripts/memory_mcp_server.py +1 -1
  15. package/scripts/probe-context-rehydrate.mjs +6 -0
  16. package/scripts/probe-pantheon-cost.mjs +71 -15
  17. package/scripts/validate-routing.mjs +3 -3
  18. package/src/mcp/code_mode_server.py +1 -1
  19. package/src/mcp/mcp_persistence_server.py +1 -1
  20. package/src/mcp/mcp_resources_server.py +1 -1
  21. package/src/mcp/memory_mcp_server.py +1 -1
  22. package/src/mcp/pantheon_vision_server.py +1 -1
  23. package/src/mcp/requirements-mcp.txt +6 -4
  24. package/src/mcp/requirements-vision.txt +2 -2
  25. package/src/pantheon/cost-command.ts +399 -101
  26. package/src/pantheon/presets.mjs +3 -3
  27. package/src/plugin-v2.ts +131 -58
  28. package/src/plugins/tui/dist/server.d.ts +1 -2
  29. package/src/plugins/tui/dist/server.d.ts.map +1 -1
  30. package/src/plugins/tui/dist/tui.d.ts +74 -74
  31. package/src/plugins/tui/dist/tui.d.ts.map +1 -1
  32. package/src/plugins/tui/dist/tui.js +17 -20
  33. package/src/plugins/tui/package-lock.json +364 -317
  34. package/src/plugins/tui/package.json +8 -5
  35. package/src/plugins/tui/tsconfig.build.json +5 -0
  36. package/src/plugins/tui/tsdown.config.ts +3 -0
@@ -1,6 +1,6 @@
1
1
  import { TuiPluginModule } from "@opencode-ai/plugin/tui";
2
2
  //#region src/index.d.ts
3
- type DelegationEntry = {
3
+ export type DelegationEntry = {
4
4
  /** Job alias, e.g. "apo-1" (from the H1 title, falling back to filename). */
5
5
  alias: string;
6
6
  /** Parent session the job was launched from (dir name under .pantheon/delegations). */
@@ -34,13 +34,13 @@ type DelegationEntry = {
34
34
  * Linear, single-pass over `raw.split('\n')` with plain string operations
35
35
  * (startsWith/indexOf/slice) — zero regex, so worst case is O(bytes) even
36
36
  * on adversarial whitespace-heavy input (ReDoS regression, CodeQL 12x HIGH). */
37
- declare function parseDelegationMarkdown(raw: string, fileAlias?: string, sessionID?: string): DelegationEntry | null;
37
+ export declare function parseDelegationMarkdown(raw: string, fileAlias?: string, sessionID?: string): DelegationEntry | null;
38
38
  /** Read every delegation report under `<dir>/<sessionID>/<alias>.md`.
39
39
  * Fail-open: a missing/unreadable directory yields [], and each unreadable
40
40
  * or malformed file is skipped individually. Entries are sorted running
41
41
  * first, then terminal by `updatedAt` (most recent first) so the panel can
42
42
  * render them in order directly. */
43
- declare function readDelegationEntries(dir: string): Promise<DelegationEntry[]>;
43
+ export declare function readDelegationEntries(dir: string): Promise<DelegationEntry[]>;
44
44
  /** Read delegation reports from EVERY session under
45
45
  * `<root>/.pantheon/delegations/<sessionID>/<alias>.md` — the panel's
46
46
  * ENRICHMENT source. The read is deliberately unfiltered (each entry carries
@@ -49,21 +49,21 @@ declare function readDelegationEntries(dir: string): Promise<DelegationEntry[]>;
49
49
  * before rendering — only the active session's reports are shown. Entries are
50
50
  * running first, Finalized desc (the sort applied by readDelegationEntries).
51
51
  * Fail-open: a missing/unreadable directory yields []. */
52
- declare function readAllDelegationEntries(root: string): Promise<DelegationEntry[]>;
52
+ export declare function readAllDelegationEntries(root: string): Promise<DelegationEntry[]>;
53
53
  /** Resolve the PROJECT ROOT used by every pantheon file channel. `directory`
54
54
  * wins over `worktree` (the old `resolveDelegationsDir` already did this);
55
55
  * an absent/empty root or `/` (no git — e.g. the sandbox test project) falls
56
56
  * back to cwd. Standardised here so the delegations md and the panel logger
57
57
  * all read the SAME root (audit finding: the channels
58
58
  * resolved the root independently). Pure — no I/O. */
59
- declare function resolvePantheonRoot(state: {
59
+ export declare function resolvePantheonRoot(state: {
60
60
  directory?: string;
61
61
  worktree?: string;
62
62
  } | undefined, cwd?: string): string;
63
63
  /** Resolve the directory where delegation md reports are written.
64
64
  * The finalizer writes `.pantheon/delegations` RELATIVE to the server cwd,
65
65
  * which the TUI exposes as `TuiState.path.directory`. */
66
- declare function resolveDelegationsDir(state: {
66
+ export declare function resolveDelegationsDir(state: {
67
67
  directory?: string;
68
68
  worktree?: string;
69
69
  } | undefined, cwd?: string): string;
@@ -72,36 +72,36 @@ declare function resolveDelegationsDir(state: {
72
72
  * the delegations dir (or its dirname) directly made createTuiLogger append
73
73
  * to `<root>/.pantheon/.pantheon/logs/hooks.log`, a nested empty dir the real
74
74
  * log never saw. Pure — no I/O. */
75
- declare function panelLogDir(delegationsDir: string): string;
75
+ export declare function panelLogDir(delegationsDir: string): string;
76
76
  /** Where the panel logger appends lines: `<projectRoot>/.pantheon/logs/hooks.log`.
77
77
  * Pure — testable without the runtime. */
78
- declare function tuiLogPath(projectRoot: string): string;
78
+ export declare function tuiLogPath(projectRoot: string): string;
79
79
  /** Sort delegations: running first, then terminal by recency (updatedAt,
80
80
  * falling back to startedAt, descending). Shared by the md reader and
81
81
  * mergeDelegationSources. */
82
- declare function compareDelegationEntries(a: DelegationEntry, b: DelegationEntry): number;
82
+ export declare function compareDelegationEntries(a: DelegationEntry, b: DelegationEntry): number;
83
83
  /** Split the panel list: active jobs (running/retry, stale-marked) first,
84
84
  * then the most recent terminal reports; the remaining tail is collapsed
85
85
  * by the View into a single "… +N more" line. Pure — so the history-only panel (no sessionID) is testable
86
86
  * without the TUI runtime. */
87
- declare function splitDelegationList(all: readonly DelegationEntry[], maxRecent?: number, now?: number, staleThresholdMs?: number): {
87
+ export declare function splitDelegationList(all: readonly DelegationEntry[], maxRecent?: number, now?: number, staleThresholdMs?: number): {
88
88
  active: DelegationEntry[];
89
89
  recent: DelegationEntry[];
90
90
  };
91
91
  /** Live-first window used by {@link ceilingDelegationList} (kept for the
92
92
  * ceiling helper and existing tests): active jobs first, then the most
93
93
  * recent terminal reports (capped). Pure. */
94
- declare function visibleDelegationList(all: readonly DelegationEntry[], maxTerminal?: number, now?: number, staleThresholdMs?: number): DelegationEntry[];
94
+ export declare function visibleDelegationList(all: readonly DelegationEntry[], maxTerminal?: number, now?: number, staleThresholdMs?: number): DelegationEntry[];
95
95
  /** Default stale-running threshold: 30 minutes. */
96
- declare const STALE_RUNNING_THRESHOLD_MS: number;
96
+ export declare const STALE_RUNNING_THRESHOLD_MS: number;
97
97
  /** Idle silence window: if no updatedAt change in this window, the entry is
98
98
  * considered stale. Combined with the stale-running threshold to produce the
99
99
  * display-only `stale-running` state. */
100
- declare const IDLE_SILENCE_MS: number;
100
+ export declare const IDLE_SILENCE_MS: number;
101
101
  /** Visual-only terminal retention windows. Reports remain on disk; these
102
102
  * constants only control which rows enter the TUI window. */
103
- declare const DELEGATION_DONE_RETENTION_MS: number;
104
- declare const DELEGATION_FAILED_RETENTION_MS: number;
103
+ export declare const DELEGATION_DONE_RETENTION_MS: number;
104
+ export declare const DELEGATION_FAILED_RETENTION_MS: number;
105
105
  /** Grace window for an ABSENT child status. `api.state.session.status()` only
106
106
  * carries the sessions that are currently ALIVE; every finished child of a
107
107
  * long-lived session is missing from that map. A child with no status is
@@ -111,7 +111,7 @@ declare const DELEGATION_FAILED_RETENTION_MS: number;
111
111
  * has not been registered by the status API yet: within this window of its
112
112
  * last activity (`time.updated`, falling back to `time.created`) it still
113
113
  * reads as running. */
114
- declare const DELEGATION_CHILD_STATUS_GRACE_MS: number;
114
+ export declare const DELEGATION_CHILD_STATUS_GRACE_MS: number;
115
115
  /** Recency window for the children channel. `session.children` returns EVERY
116
116
  * child the focused session ever spawned, so a long session accumulates
117
117
  * hundreds of historical rows that would inflate the panel. A child whose
@@ -119,12 +119,12 @@ declare const DELEGATION_CHILD_STATUS_GRACE_MS: number;
119
119
  * is older than this window is dropped BEFORE it can enter the list. 24h
120
120
  * keeps the sidebar scoped to current work while still covering long
121
121
  * delegations. A child with no timestamp at all is kept (fail-open). */
122
- declare const DELEGATION_CHILDREN_RECENCY_MS: number;
122
+ export declare const DELEGATION_CHILDREN_RECENCY_MS: number;
123
123
  /** Alias-less NATIVE task() live entries never receive a report alias (the
124
124
  * task tool output carries none), so the 30s alias-less prune in
125
125
  * mergeChildDelegationSources must not apply to them — 5 minutes covers a
126
126
  * slow child listing while still bounding the live map. */
127
- declare const NATIVE_LIVE_ALIASLESS_TTL_MS: number;
127
+ export declare const NATIVE_LIVE_ALIASLESS_TTL_MS: number;
128
128
  /**
129
129
  * Mark a running entry as `stale-running` if it has been running longer than
130
130
  * the threshold AND has no recent activity (no `updatedAt` change in the last
@@ -133,40 +133,40 @@ declare const NATIVE_LIVE_ALIASLESS_TTL_MS: number;
133
133
  * A `stale-running` entry renders with a warning indicator but the underlying
134
134
  * delegation is still treated as running by the backend.
135
135
  */
136
- declare function markStaleIfRunning(entry: DelegationEntry, now: number, thresholdMs?: number): DelegationEntry;
136
+ export declare function markStaleIfRunning(entry: DelegationEntry, now: number, thresholdMs?: number): DelegationEntry;
137
137
  /** Compact elapsed-time label, single unit only: "12s"/"3m"/"1h"/"2d" — ticks every
138
138
  * second for running jobs. */
139
- declare function fmtElapsed(ms: number): string;
139
+ export declare function fmtElapsed(ms: number): string;
140
140
  /** Elapsed label for one entry: an ACTIVE entry (running/retry/stale-running)
141
141
  * ticks `now - startedAt`; a terminal one is fixed at
142
142
  * `updatedAt - startedAt` (em dash when no finalized timestamp). */
143
- declare function delegationElapsed(entry: DelegationEntry, now: number): string;
143
+ export declare function delegationElapsed(entry: DelegationEntry, now: number): string;
144
144
  /** The activity labels shown by the animated row. Keeping this pure makes the
145
145
  * state machine testable without booting OpenCode's renderer. */
146
- type DelegationActivity = 'delegating' | 'working' | 'completed' | 'error' | 'cancelled';
147
- declare function delegationActivity(entry: DelegationEntry): DelegationActivity;
148
- declare function delegationActivityLabel(entry: DelegationEntry): string;
146
+ export type DelegationActivity = 'delegating' | 'working' | 'completed' | 'error' | 'cancelled';
147
+ export declare function delegationActivity(entry: DelegationEntry): DelegationActivity;
148
+ export declare function delegationActivityLabel(entry: DelegationEntry): string;
149
149
  /** Return the spinner glyph for the given frame counter. The frame counter
150
150
  * is incremented every ~80ms by a dedicated animation timer, decoupled from
151
151
  * the data poll cycle. Pure — no side effects. */
152
- declare function delegationSpinnerFrame(frame: number): string;
152
+ export declare function delegationSpinnerFrame(frame: number): string;
153
153
  /** Every state the row knows how to draw: the delegation lifecycle states
154
154
  * derived from the children status + md reports (`completed`, `error`,
155
155
  * `cancelled`, `startup_failed`, `startup_unknown`) plus the TUI-only
156
156
  * states (`retry`, `stale-running`). Fase 1 deliberately omits speculative
157
157
  * blocked/paused/scheduled/skipped. There is no `pending` display state: a
158
158
  * pre-dispatch tool part maps to `running` in {@link reduceDelegationToolPart}. */
159
- type DelegationDisplayState = DelegationEntry['state'];
159
+ export type DelegationDisplayState = DelegationEntry['state'];
160
160
  /** Semantic tone mapped to the TUI theme at the row ({@link DelegationRow}).
161
161
  * Kept separate + pure so the color channel is testable without booting the
162
162
  * renderer. Every display state resolves to one of the three status colors;
163
163
  * the row paints its whole content with it (see {@link DelegationRow}). */
164
- type DelegationStateTone = 'warning' | 'error' | 'success';
164
+ export type DelegationStateTone = 'warning' | 'error' | 'success';
165
165
  /** Status → color mapping for the whole-row tone. Red = failure, green =
166
166
  * terminal, yellow = in flight. The glyph remains a redundant channel so the
167
167
  * state stays legible in monochrome. Display-only; no behavior change. */
168
- declare function delegationStateTone(state: DelegationDisplayState): DelegationStateTone;
169
- type ToolActivity = {
168
+ export declare function delegationStateTone(state: DelegationDisplayState): DelegationStateTone;
169
+ export type ToolActivity = {
170
170
  tool: string;
171
171
  summary: string;
172
172
  at: number;
@@ -174,7 +174,7 @@ type ToolActivity = {
174
174
  /** Reduce one message.part.updated tool part to displayable activity.
175
175
  * Returns null for non-tool parts, completed/error parts (no live activity)
176
176
  * or parts without a session id. Pure. */
177
- declare function extractToolActivity(part: {
177
+ export declare function extractToolActivity(part: {
178
178
  type?: string;
179
179
  tool?: string;
180
180
  sessionID?: string;
@@ -187,18 +187,18 @@ declare function extractToolActivity(part: {
187
187
  activity: ToolActivity;
188
188
  } | null;
189
189
  /** Record an activity sample (bounded map, oldest dropped). */
190
- declare function trackToolActivity(map: Map<string, ToolActivity>, sessionID: string, activity: ToolActivity): void;
190
+ export declare function trackToolActivity(map: Map<string, ToolActivity>, sessionID: string, activity: ToolActivity): void;
191
191
  /** Latest live activity for a child session, or null when absent/stale. */
192
- declare function latestToolActivityFor(map: Map<string, ToolActivity>, sessionID: string | undefined, now?: number, ttlMs?: number): ToolActivity | null;
192
+ export declare function latestToolActivityFor(map: Map<string, ToolActivity>, sessionID: string | undefined, now?: number, ttlMs?: number): ToolActivity | null;
193
193
  /** Merge the immediate tool-event channel into the child-session channel.
194
194
  *
195
195
  * Children remain the durable source, while live entries make a delegation
196
196
  * visible before the child API/report catches up. A finalized md entry wins
197
197
  * over a stale live entry; a child-only row is upgraded with live agent,
198
198
  * alias, phase and timestamps. */
199
- declare function mergeChildDelegationSources(children: readonly DelegationEntry[], live: readonly LiveDelegationEntry[]): DelegationEntry[];
199
+ export declare function mergeChildDelegationSources(children: readonly DelegationEntry[], live: readonly LiveDelegationEntry[]): DelegationEntry[];
200
200
  /** Duck-typed subset of a tool part (SDK v2 `ToolPart` / `ToolState`). */
201
- type DelegationToolPart = {
201
+ export type DelegationToolPart = {
202
202
  id?: string;
203
203
  callID?: string;
204
204
  sessionID?: string;
@@ -216,7 +216,7 @@ type DelegationToolPart = {
216
216
  };
217
217
  };
218
218
  /** One live delegation tracked in-memory, keyed by the task callID. */
219
- type LiveDelegationEntry = {
219
+ export type LiveDelegationEntry = {
220
220
  /** Tool call id of the task part (stable across events). */
221
221
  callID: string;
222
222
  /** Part id (for message.part.removed cleanup). */
@@ -236,7 +236,7 @@ type LiveDelegationEntry = {
236
236
  updatedAt: number | null;
237
237
  };
238
238
  /** Result of parsing one tool part into lifecycle-relevant fields. */
239
- type ParsedDelegationToolPart = {
239
+ export type ParsedDelegationToolPart = {
240
240
  callID: string;
241
241
  partID: string;
242
242
  sessionID: string;
@@ -254,13 +254,13 @@ type ParsedDelegationToolPart = {
254
254
  * reduce it to what the panel needs. Returns null for anything that is
255
255
  * not the native `task` subagent tool (parentID === caller mechanism —
256
256
  * its children render `nat:`), or is missing its callID. */
257
- declare function parseDelegationToolPart(part: DelegationToolPart, now?: number): ParsedDelegationToolPart | null;
257
+ export declare function parseDelegationToolPart(part: DelegationToolPart, now?: number): ParsedDelegationToolPart | null;
258
258
  /** Apply one tool part to the live map. Returns true when the map changed.
259
259
  * Pure w.r.t. I/O — only mutates `map`. */
260
- declare function reduceDelegationToolPart(map: Map<string, LiveDelegationEntry>, part: DelegationToolPart, now?: number): boolean;
260
+ export declare function reduceDelegationToolPart(map: Map<string, LiveDelegationEntry>, part: DelegationToolPart, now?: number): boolean;
261
261
  /** Remove a live entry by part id (message.part.removed) or call id.
262
262
  * Returns true when something was removed. */
263
- declare function removeDelegationEntry(map: Map<string, LiveDelegationEntry>, partIDOrCallID: string): boolean;
263
+ export declare function removeDelegationEntry(map: Map<string, LiveDelegationEntry>, partIDOrCallID: string): boolean;
264
264
  /** Collect native task tool parts from a session's messages.
265
265
  * Messages may carry their parts inline (duck-typed `msg.parts`); when
266
266
  * they don't, the optional `getParts(messageID)` callback is used (the TUI
@@ -269,7 +269,7 @@ declare function removeDelegationEntry(map: Map<string, LiveDelegationEntry>, pa
269
269
  * the refresh signal (rows come from the children channel). Pure w.r.t.
270
270
  * I/O — used by the mount re-scan to re-seed the live map after
271
271
  * compaction/attach. */
272
- declare function collectDelegationToolParts(messages: readonly {
272
+ export declare function collectDelegationToolParts(messages: readonly {
273
273
  id?: string;
274
274
  parts?: unknown[];
275
275
  }[] | undefined, getParts?: (messageID: string) => readonly unknown[] | undefined): DelegationToolPart[];
@@ -277,16 +277,16 @@ declare function collectDelegationToolParts(messages: readonly {
277
277
  * mount to re-seed entries that `message.part.removed` (compaction) wiped,
278
278
  * from the session's existing tool parts. Returns how many parts changed
279
279
  * the map (0 on the second identical seed — idempotent, no extra bumps). */
280
- declare function seedLiveDelegationMap(map: Map<string, LiveDelegationEntry>, parts: readonly DelegationToolPart[], now?: number): number;
280
+ export declare function seedLiveDelegationMap(map: Map<string, LiveDelegationEntry>, parts: readonly DelegationToolPart[], now?: number): number;
281
281
  /** Convert a live entry into the shared display shape. Alias falls back to
282
282
  * a `live-<callID>` prefix while the task call has not completed yet. */
283
- declare function toDelegationEntry(live: LiveDelegationEntry): DelegationEntry;
283
+ export declare function toDelegationEntry(live: LiveDelegationEntry): DelegationEntry;
284
284
  /** Combine the live channel with the md (historical) channel into one
285
285
  * display list. Dedupes by (sessionID, alias) — aliases are per-parent-
286
286
  * session, so the same alias in different sessions stays separate. A
287
287
  * terminal md entry is authoritative over a live running entry for the
288
288
  * same job (it carries Finalized/timedOut/cancelled from finalize). */
289
- declare function mergeDelegationSources(live: readonly LiveDelegationEntry[], md: readonly DelegationEntry[]): DelegationEntry[];
289
+ export declare function mergeDelegationSources(live: readonly LiveDelegationEntry[], md: readonly DelegationEntry[]): DelegationEntry[];
290
290
  /** Scope a fully-merged display list to the ACTIVE session only.
291
291
  *
292
292
  * The panel is session-scoped: rows from other sessions (md history under
@@ -303,7 +303,7 @@ declare function mergeDelegationSources(live: readonly LiveDelegationEntry[], md
303
303
  * Returns [] when no active session resolves (null/placeholder) — there is no
304
304
  * scope to show. Native children always carry the active session id (stamped
305
305
  * by `childrenToDelegationEntries`), so they survive the filter. Pure. */
306
- declare function filterDelegationsToSession(entries: readonly DelegationEntry[], activeSessionID: string | null | undefined): DelegationEntry[];
306
+ export declare function filterDelegationsToSession(entries: readonly DelegationEntry[], activeSessionID: string | null | undefined): DelegationEntry[];
307
307
  /** Server-aligned session id validity: opencode rejects anything not starting
308
308
  * with "ses" (SchemaError). This deliberately mirrors that exact contract —
309
309
  * nothing stricter, nothing looser — so a template placeholder ("{sessionID}"),
@@ -312,11 +312,11 @@ declare function filterDelegationsToSession(entries: readonly DelegationEntry[],
312
312
  * never reach a path and error-spam the log. Confirmed: "{sessionID}" starts
313
313
  * with "{" and "%7BsessionID%7D" with "%" — both fail startsWith("ses"), so
314
314
  * the placeholder is rejected WITHOUT an explicit denylist (covered by tests). */
315
- declare function isValidSessionId(id: unknown): id is string;
315
+ export declare function isValidSessionId(id: unknown): id is string;
316
316
  /** Sources the sidebar can resolve the CURRENT session id from. Duck-typed
317
317
  * subsets of TuiPluginApi / TuiState / TuiRouteCurrent so the helper stays
318
318
  * pure and testable without the TUI runtime. */
319
- type TuiSessionSources = {
319
+ export type TuiSessionSources = {
320
320
  /** sidebar_content slot prop (`session_id`). */
321
321
  sessionID?: string | null;
322
322
  api?: {
@@ -338,7 +338,7 @@ type TuiSessionSources = {
338
338
  * (typed route). Every source is validated; invalid/absent → next source.
339
339
  * NEVER returns a placeholder or non-ses id. Null → callers MUST skip the
340
340
  * fetch (empty panel, zero errors). Pure — no I/O, no runtime required. */
341
- declare function resolveCurrentSessionID(sources: TuiSessionSources): string | null;
341
+ export declare function resolveCurrentSessionID(sources: TuiSessionSources): string | null;
342
342
  /** THE single choke point for every `session.children` / session-API path.
343
343
  * Returns the v2 SDK parameter shape `{ sessionID }` ONLY for a
344
344
  * server-valid session id; returns null for anything else (placeholder,
@@ -350,7 +350,7 @@ declare function resolveCurrentSessionID(sources: TuiSessionSources): string | n
350
350
  * unsubstituted (`/session/%7BsessionID%7D/children`). Every session-API
351
351
  * call site MUST go through this function (enforced by the source-scan
352
352
  * test in tests/pantheon/tui-delegations.test.ts). */
353
- declare function safeSessionPath(id: unknown): {
353
+ export declare function safeSessionPath(id: unknown): {
354
354
  sessionID: string;
355
355
  } | null;
356
356
  /** Build the `session.children` parameters ONLY from a validated session id.
@@ -358,11 +358,11 @@ declare function safeSessionPath(id: unknown): {
358
358
  * the v2 SDK shape `{ sessionID }`; null for null/invalid ids so the caller
359
359
  * skips the fetch instead of sending an unsubstituted placeholder (the
360
360
  * "%7BsessionID%7D" regression). */
361
- declare function buildChildrenPath(id: string | null | undefined): {
361
+ export declare function buildChildrenPath(id: string | null | undefined): {
362
362
  sessionID: string;
363
363
  } | null;
364
364
  /** Duck-typed subset of a child Session (+ its live status type). */
365
- type ChildDelegationLike = {
365
+ export type ChildDelegationLike = {
366
366
  /** Child session id (= task id). */
367
367
  id: string;
368
368
  /** Session title — the delegate's description or prompt prefix. */
@@ -395,7 +395,7 @@ type ChildDelegationLike = {
395
395
  * @param now current wall-clock ms (injectable for tests)
396
396
  * @param graceMs recency window for the absent-status running assumption
397
397
  * Pure — no I/O. */
398
- declare function childStatusToState(status: string | undefined, time?: {
398
+ export declare function childStatusToState(status: string | undefined, time?: {
399
399
  created?: number;
400
400
  updated?: number;
401
401
  }, now?: number, graceMs?: number): 'running' | 'completed' | 'retry';
@@ -405,58 +405,58 @@ declare function childStatusToState(status: string | undefined, time?: {
405
405
  * `{glyph} {alias:7} {elapsed:>5}` plus a muted description line. The short
406
406
  * alias (`apo-1`) is the single identity; rows without a report alias show
407
407
  * the agent instead (never both). */
408
- type DelegationRowStatus = 'active' | 'done' | 'failed' | 'retry';
408
+ export type DelegationRowStatus = 'active' | 'done' | 'failed' | 'retry';
409
409
  /** Map every FSM/display state to one of the 4 row kinds. reconciled never
410
410
  * reaches the panel (the md parser drops it) but reads as done;
411
411
  * cancelled reads as done; startup_failed reads as failed while
412
412
  * startup_unknown (no error known) reads as retry. Pure. */
413
- declare function delegationRowStatus(state: DelegationDisplayState): DelegationRowStatus;
413
+ export declare function delegationRowStatus(state: DelegationDisplayState): DelegationRowStatus;
414
414
  /** The only 4 glyphs a row may show: animated active, done, failed, retry.
415
415
  * Shape is redundant with color (never the only signal). Pure. */
416
- declare const DELEGATION_ROW_GLYPHS: Readonly<Record<DelegationRowStatus, string>>;
417
- declare function delegationRowGlyph(status: DelegationRowStatus): string;
416
+ export declare const DELEGATION_ROW_GLYPHS: Readonly<Record<DelegationRowStatus, string>>;
417
+ export declare function delegationRowGlyph(status: DelegationRowStatus): string;
418
418
  /** Row marker (`<glyph> `) — the single state channel. `active` animates
419
419
  * through the spinner for the given frame counter (incremented every ~80ms);
420
420
  * every other kind is static. Pure. */
421
- declare function delegationRowMarker(state: DelegationDisplayState, frame?: number): string;
421
+ export declare function delegationRowMarker(state: DelegationDisplayState, frame?: number): string;
422
422
  /** ONE identity per row: the short report alias (`apo-1`); a row without a
423
423
  * report alias (native task() child `native-task` / `native-<id>`, or an
424
424
  * alias-less native live row `live-<callID>` kept as children-only) shows
425
425
  * the agent instead — never alias + agent stacked. Pure. */
426
- declare function delegationRowIdentity(entry: DelegationEntry): string;
426
+ export declare function delegationRowIdentity(entry: DelegationEntry): string;
427
427
  /** Fixed alias cell, pad-right + hard-truncate to `width` (default 7) so
428
428
  * identities line up across rows. Pure. */
429
- declare const DELEGATION_ALIAS_WIDTH = 7;
430
- declare function formatDelegationAlias(identity: string, width?: number): string;
429
+ export declare const DELEGATION_ALIAS_WIDTH = 7;
430
+ export declare function formatDelegationAlias(identity: string, width?: number): string;
431
431
  /** Max description width on the row detail line — the old 180-char slice
432
432
  * wrapped the sidebar; 44 keeps one readable line. */
433
- declare const DELEGATION_DESCRIPTION_MAX = 44;
433
+ export declare const DELEGATION_DESCRIPTION_MAX = 44;
434
434
  /** Truncate a description to `max` graphemes appending `…` when cut. Exact
435
435
  * `max`-length text is left untouched. Grapheme-granular, so an emoji made of
436
436
  * several code points is never split into mojibake at the boundary. Pure. */
437
- declare function truncateDelegationDescription(text: string, max?: number): string;
437
+ export declare function truncateDelegationDescription(text: string, max?: number): string;
438
438
  /** Fixed elapsed-time box: right-aligned to `width` (default 5) so elapsed
439
439
  * values line up across rows, e.g. ` 12s`. A label that already fills
440
440
  * the box is returned untouched. Pure. */
441
- declare const DELEGATION_ELAPSED_WIDTH = 5;
442
- declare function formatDelegationElapsed(entry: DelegationEntry, now: number, width?: number): string;
441
+ export declare const DELEGATION_ELAPSED_WIDTH = 5;
442
+ export declare function formatDelegationElapsed(entry: DelegationEntry, now: number, width?: number): string;
443
443
  /** Colored left half of a row line: `<marker><alias:7> ` — the state glyph
444
444
  * plus the single identity, padded so the muted elapsed column aligns. The
445
445
  * row renders this colored lead separately from the muted elapsed tail. Pure. */
446
- declare function formatDelegationRowLead(entry: DelegationEntry, marker: string): string;
446
+ export declare function formatDelegationRowLead(entry: DelegationEntry, marker: string): string;
447
447
  /** Visible-row ceiling for the panel: the remainder collapses into a single
448
448
  * "… +N more" line. Live rows render first, so a running job is never hidden
449
449
  * by the cap. */
450
- declare const DELEGATION_VISIBLE_CEILING = 8;
450
+ export declare const DELEGATION_VISIBLE_CEILING = 8;
451
451
  /** Header summary: `(N active · M done)` plus `· K failed` only when K > 0.
452
452
  * Active counts running/retry AND display-only stale-running (a stale row is
453
453
  * still a live job — it must never read as done); failed counts
454
454
  * error/startup_failed; cancelled reads as done. Pure. */
455
- declare function formatDelegationHeader(entries: readonly DelegationEntry[]): string;
455
+ export declare function formatDelegationHeader(entries: readonly DelegationEntry[]): string;
456
456
  /** Cap the panel: live rows first, then most-recent retained terminal rows, at
457
457
  * most `maxVisible` total. Hidden counts describe the retained render list,
458
458
  * not expired history. */
459
- declare function ceilingDelegationList(all: readonly DelegationEntry[], maxVisible?: number, now?: number): {
459
+ export declare function ceilingDelegationList(all: readonly DelegationEntry[], maxVisible?: number, now?: number): {
460
460
  visible: DelegationEntry[];
461
461
  hidden: number;
462
462
  hiddenActive: number;
@@ -465,7 +465,7 @@ declare function ceilingDelegationList(all: readonly DelegationEntry[], maxVisib
465
465
  /** Split a display list into native task() rows vs pantheon report rows.
466
466
  * Native = source 'children-only' (no delegate report); everything else counts
467
467
  * as pantheon. Pure — powers the hooks.log line. */
468
- declare function countDelegationSources(entries: readonly DelegationEntry[]): {
468
+ export declare function countDelegationSources(entries: readonly DelegationEntry[]): {
469
469
  native: number;
470
470
  pantheon: number;
471
471
  total: number;
@@ -473,25 +473,25 @@ declare function countDelegationSources(entries: readonly DelegationEntry[]): {
473
473
  /** Diagnostic hooks.log line for a panel re-fetch, with the children
474
474
  * breakdown (pantheon = children WITH a delegate report, native = children
475
475
  * WITHOUT one). Pure — the View logs the returned string verbatim. */
476
- declare function formatPanelLogLine(children: number, pantheon: number, native: number, md: number, events: number): string;
477
- declare function childrenToDelegationEntries(children: readonly ChildDelegationLike[] | undefined, md: readonly DelegationEntry[], now?: number, parentSessionID?: string): DelegationEntry[];
476
+ export declare function formatPanelLogLine(children: number, pantheon: number, native: number, md: number, events: number): string;
477
+ export declare function childrenToDelegationEntries(children: readonly ChildDelegationLike[] | undefined, md: readonly DelegationEntry[], now?: number, parentSessionID?: string): DelegationEntry[];
478
478
  /** Navigate the TUI to a child session (click/Enter on a delegation row).
479
479
  * Returns false when the route API is unavailable or the target id is
480
480
  * missing/placeholder — the row stays inert instead of crashing. Only a
481
481
  * server-valid session id ("ses...") ever reaches the router, so an
482
482
  * unsubstituted "{sessionID}" placeholder can never be routed. */
483
- declare function navigateToDelegationSession(route: {
483
+ export declare function navigateToDelegationSession(route: {
484
484
  navigate?: (name: string, params?: Record<string, unknown>) => void | PromiseLike<void>;
485
485
  } | undefined, taskID: string | undefined): boolean;
486
486
  /** Build the mouse handler used by each delegation row. */
487
- declare function createDelegationRowOpenHandler(route: {
487
+ export declare function createDelegationRowOpenHandler(route: {
488
488
  navigate?: (name: string, params?: Record<string, unknown>) => void | PromiseLike<void>;
489
489
  } | undefined, taskID: string | undefined): () => void;
490
490
  /** Plugin-level live delegation store shared with the event subscriptions
491
491
  * in `tui()`: the map of live entries + a version signal bumped on every
492
492
  * mutation. The View subscribes to the version (in an effect) to refresh the
493
493
  * durable child list and also reads the map as an optimistic live source. */
494
- type LiveDelegationStore = {
494
+ export type LiveDelegationStore = {
495
495
  map: Map<string, LiveDelegationEntry>;
496
496
  /** Reactive version getter — View reads it inside an effect to re-fetch. */
497
497
  version: () => number;
@@ -503,5 +503,5 @@ declare const plugin: TuiPluginModule & {
503
503
  setup: () => Promise<void>;
504
504
  };
505
505
  //#endregion
506
- export { ChildDelegationLike, DELEGATION_ALIAS_WIDTH, DELEGATION_CHILDREN_RECENCY_MS, DELEGATION_CHILD_STATUS_GRACE_MS, DELEGATION_DESCRIPTION_MAX, DELEGATION_DONE_RETENTION_MS, DELEGATION_ELAPSED_WIDTH, DELEGATION_FAILED_RETENTION_MS, DELEGATION_ROW_GLYPHS, DELEGATION_VISIBLE_CEILING, DelegationActivity, DelegationDisplayState, DelegationEntry, DelegationRowStatus, DelegationStateTone, DelegationToolPart, IDLE_SILENCE_MS, LiveDelegationEntry, LiveDelegationStore, NATIVE_LIVE_ALIASLESS_TTL_MS, ParsedDelegationToolPart, STALE_RUNNING_THRESHOLD_MS, ToolActivity, TuiSessionSources, buildChildrenPath, ceilingDelegationList, childStatusToState, childrenToDelegationEntries, collectDelegationToolParts, compareDelegationEntries, countDelegationSources, createDelegationRowOpenHandler, plugin as default, delegationActivity, delegationActivityLabel, delegationElapsed, delegationRowGlyph, delegationRowIdentity, delegationRowMarker, delegationRowStatus, delegationSpinnerFrame, delegationStateTone, extractToolActivity, filterDelegationsToSession, fmtElapsed, formatDelegationAlias, formatDelegationElapsed, formatDelegationHeader, formatDelegationRowLead, formatPanelLogLine, isValidSessionId, latestToolActivityFor, markStaleIfRunning, mergeChildDelegationSources, mergeDelegationSources, navigateToDelegationSession, panelLogDir, parseDelegationMarkdown, parseDelegationToolPart, readAllDelegationEntries, readDelegationEntries, reduceDelegationToolPart, removeDelegationEntry, resolveCurrentSessionID, resolveDelegationsDir, resolvePantheonRoot, safeSessionPath, seedLiveDelegationMap, splitDelegationList, toDelegationEntry, trackToolActivity, truncateDelegationDescription, tuiLogPath, visibleDelegationList };
506
+ export { plugin as default };
507
507
  //# sourceMappingURL=tui.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tui.d.ts","names":[],"sources":["../src/index.tsx"],"mappings":"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"}
1
+ {"version":3,"file":"tui.d.ts","names":[],"sources":["../src/index.tsx"],"mappings":"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"}
@@ -121,12 +121,14 @@ async function resolvePresetForTui(env, cwd) {
121
121
  }
122
122
  async function detectVersion(api) {
123
123
  try {
124
- const pkgContent = await readFile(fileURLToPath(new URL("../../package.json", import.meta.url)), "utf8");
124
+ const pkgUrl = new URL("../../package.json", import.meta.url);
125
+ const pkgContent = await readFile(fileURLToPath(pkgUrl), "utf8");
125
126
  const pkg = JSON.parse(pkgContent);
126
127
  if (pkg.version) return pkg.version;
127
128
  } catch {}
128
129
  try {
129
- const pkgContent = await readFile(fileURLToPath(new URL("../../../../package.json", import.meta.url)), "utf8");
130
+ const pkgUrl = new URL("../../../../package.json", import.meta.url);
131
+ const pkgContent = await readFile(fileURLToPath(pkgUrl), "utf8");
130
132
  const pkg = JSON.parse(pkgContent);
131
133
  if (pkg.version) return pkg.version;
132
134
  } catch {}
@@ -165,7 +167,7 @@ async function detectVersion(api) {
165
167
  if (ver) return ver;
166
168
  }
167
169
  } catch {}
168
- return "1.6.0-beta.3";
170
+ return "1.6.0-beta.4";
169
171
  }
170
172
  /**
171
173
  * usage-bar — AI subscription usage gauge for the opencode TUI.
@@ -763,10 +765,7 @@ function parseDelegationMarkdown(raw, fileAlias, sessionID = "") {
763
765
  case "Started":
764
766
  if (value !== "" && started === void 0) started = value;
765
767
  break;
766
- case "Finalized":
767
- finalized = value;
768
- break;
769
- default: break;
768
+ case "Finalized": finalized = value;
770
769
  }
771
770
  }
772
771
  const startedAt = started !== void 0 ? Date.parse(started) : NaN;
@@ -885,7 +884,7 @@ function compareDelegationEntries(a, b) {
885
884
  * then the most recent terminal reports; the remaining tail is collapsed
886
885
  * by the View into a single "… +N more" line. Pure — so the history-only panel (no sessionID) is testable
887
886
  * without the TUI runtime. */
888
- function splitDelegationList(all, maxRecent = 8, now = Date.now(), staleThresholdMs = 1800 * 1e3) {
887
+ function splitDelegationList(all, maxRecent = 8, now = Date.now(), staleThresholdMs = 18e5) {
889
888
  const isActiveState = (st) => st === "running" || st === "retry" || st === "stale-running";
890
889
  return {
891
890
  active: all.filter((d) => isActiveState(d.state)).map((d) => markStaleIfRunning(d, now, staleThresholdMs)).sort(compareDelegationEntries),
@@ -900,20 +899,20 @@ function splitDelegationList(all, maxRecent = 8, now = Date.now(), staleThreshol
900
899
  /** Live-first window used by {@link ceilingDelegationList} (kept for the
901
900
  * ceiling helper and existing tests): active jobs first, then the most
902
901
  * recent terminal reports (capped). Pure. */
903
- function visibleDelegationList(all, maxTerminal = 8, now = Date.now(), staleThresholdMs = 1800 * 1e3) {
902
+ function visibleDelegationList(all, maxTerminal = 8, now = Date.now(), staleThresholdMs = 18e5) {
904
903
  const { active, recent } = splitDelegationList(all, maxTerminal, now, staleThresholdMs);
905
904
  return [...active, ...recent];
906
905
  }
907
906
  /** Default stale-running threshold: 30 minutes. */
908
- const STALE_RUNNING_THRESHOLD_MS = 1800 * 1e3;
907
+ const STALE_RUNNING_THRESHOLD_MS = 18e5;
909
908
  /** Idle silence window: if no updatedAt change in this window, the entry is
910
909
  * considered stale. Combined with the stale-running threshold to produce the
911
910
  * display-only `stale-running` state. */
912
- const IDLE_SILENCE_MS = 60 * 1e3;
911
+ const IDLE_SILENCE_MS = 6e4;
913
912
  /** Visual-only terminal retention windows. Reports remain on disk; these
914
913
  * constants only control which rows enter the TUI window. */
915
- const DELEGATION_DONE_RETENTION_MS = 120 * 1e3;
916
- const DELEGATION_FAILED_RETENTION_MS = 600 * 1e3;
914
+ const DELEGATION_DONE_RETENTION_MS = 12e4;
915
+ const DELEGATION_FAILED_RETENTION_MS = 6e5;
917
916
  /** Grace window for an ABSENT child status. `api.state.session.status()` only
918
917
  * carries the sessions that are currently ALIVE; every finished child of a
919
918
  * long-lived session is missing from that map. A child with no status is
@@ -923,7 +922,7 @@ const DELEGATION_FAILED_RETENTION_MS = 600 * 1e3;
923
922
  * has not been registered by the status API yet: within this window of its
924
923
  * last activity (`time.updated`, falling back to `time.created`) it still
925
924
  * reads as running. */
926
- const DELEGATION_CHILD_STATUS_GRACE_MS = 60 * 1e3;
925
+ const DELEGATION_CHILD_STATUS_GRACE_MS = 6e4;
927
926
  /** Recency window for the children channel. `session.children` returns EVERY
928
927
  * child the focused session ever spawned, so a long session accumulates
929
928
  * hundreds of historical rows that would inflate the panel. A child whose
@@ -931,12 +930,12 @@ const DELEGATION_CHILD_STATUS_GRACE_MS = 60 * 1e3;
931
930
  * is older than this window is dropped BEFORE it can enter the list. 24h
932
931
  * keeps the sidebar scoped to current work while still covering long
933
932
  * delegations. A child with no timestamp at all is kept (fail-open). */
934
- const DELEGATION_CHILDREN_RECENCY_MS = 1440 * 60 * 1e3;
933
+ const DELEGATION_CHILDREN_RECENCY_MS = 864e5;
935
934
  /** Alias-less NATIVE task() live entries never receive a report alias (the
936
935
  * task tool output carries none), so the 30s alias-less prune in
937
936
  * mergeChildDelegationSources must not apply to them — 5 minutes covers a
938
937
  * slow child listing while still bounding the live map. */
939
- const NATIVE_LIVE_ALIASLESS_TTL_MS = 300 * 1e3;
938
+ const NATIVE_LIVE_ALIASLESS_TTL_MS = 3e5;
940
939
  /**
941
940
  * Mark a running entry as `stale-running` if it has been running longer than
942
941
  * the threshold AND has no recent activity (no `updatedAt` change in the last
@@ -1040,7 +1039,7 @@ function delegationStateTone(state) {
1040
1039
  /** Bounded tracker: child session id → latest running tool call. */
1041
1040
  const latestToolActivity = /* @__PURE__ */ new Map();
1042
1041
  const MAX_TOOL_ACTIVITY_ENTRIES = 200;
1043
- const TOOL_ACTIVITY_TTL_MS = 300 * 1e3;
1042
+ const TOOL_ACTIVITY_TTL_MS = 3e5;
1044
1043
  /** First usable summary string from common tool input fields. */
1045
1044
  function summarizeToolInput(input) {
1046
1045
  if (!input) return "";
@@ -1558,9 +1557,7 @@ function formatDelegationHeader(entries) {
1558
1557
  case "failed":
1559
1558
  failed++;
1560
1559
  break;
1561
- case "done":
1562
- done++;
1563
- break;
1560
+ case "done": done++;
1564
1561
  }
1565
1562
  const tail = failed > 0 ? ` · ${failed} failed` : "";
1566
1563
  return `(${active} active · ${done} done${tail})`;