pantheon-opencode 1.6.0-beta.3 → 1.6.0-beta.5
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.
- package/AGENTS.md +24 -5
- package/CHANGELOG.md +49 -0
- package/README.md +51 -19
- package/README.pt-BR.md +32 -13
- package/bin/pantheon-init.mjs +26 -3
- package/package.json +12 -11
- package/plugin.json +1 -1
- package/pyproject.toml +6 -6
- package/scripts/{code_mode_server.py → code_mode.py} +3 -3
- package/scripts/cost.mjs +244 -41
- package/scripts/doctor.mjs +151 -1
- package/scripts/install/agents-md.mjs +2 -2
- package/scripts/install/config-migration.mjs +80 -2
- package/scripts/install/health-check.mjs +21 -19
- package/scripts/install/opencode-version.mjs +246 -4
- package/scripts/install/opencode.mjs +250 -119
- package/scripts/install/shared.mjs +5 -5
- package/scripts/install-mcp.mjs +28 -9
- package/scripts/{mcp_persistence_server.py → mcp_persistence.py} +2 -2
- package/{src/mcp/mcp_resources_server.py → scripts/mcp_resources.py} +2 -2
- package/scripts/{memory_mcp_server.py → memory_mcp.py} +2 -2
- package/scripts/probe-context-rehydrate.mjs +8 -2
- package/scripts/probe-pantheon-cost.mjs +71 -15
- package/scripts/sync-artifacts.mjs +5 -5
- package/scripts/test-opencode-v2-sandbox.sh +21 -21
- package/scripts/validate-routing.mjs +3 -3
- package/skills-lock.json +1 -1
- package/src/agents/apollo.md +7 -2
- package/src/agents/zeus.md +29 -1
- package/src/instructions/memory-protocol.instructions.md +15 -4
- package/src/instructions/zeus-anti-stall.instructions.md +9 -1
- package/src/mcp/{code_mode_server.py → code_mode.py} +3 -3
- package/src/mcp/eval_store.py +2 -2
- package/src/mcp/{mcp_persistence_server.py → mcp_persistence.py} +2 -2
- package/{scripts/mcp_resources_server.py → src/mcp/mcp_resources.py} +2 -2
- package/src/mcp/{memory_mcp_server.py → memory_mcp.py} +2 -2
- package/src/mcp/{pantheon_vision_server.py → pantheon_vision.py} +1 -1
- package/src/mcp/requirements-mcp.txt +6 -4
- package/src/mcp/requirements-vision.txt +2 -2
- package/src/pantheon/cost-command.ts +399 -101
- package/src/pantheon/presets.mjs +3 -3
- package/src/pantheon/v2-unsupported.d.mts +11 -0
- package/src/pantheon/v2-unsupported.mjs +113 -0
- package/src/plugin-v2.ts +269 -100
- package/src/plugins/tui/dist/server.d.ts +1 -2
- package/src/plugins/tui/dist/server.d.ts.map +1 -1
- package/src/plugins/tui/dist/tui.d.ts +74 -74
- package/src/plugins/tui/dist/tui.d.ts.map +1 -1
- package/src/plugins/tui/dist/tui.js +17 -20
- package/src/plugins/tui/package-lock.json +364 -317
- package/src/plugins/tui/package.json +8 -5
- package/src/plugins/tui/tsconfig.build.json +5 -0
- package/src/plugins/tui/tsdown.config.ts +3 -0
- package/src/skills/context-compression/SKILL.md +1 -1
- package/opencode.json +0 -58
|
@@ -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 {
|
|
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":";;
|
|
1
|
+
{"version":3,"file":"tui.d.ts","names":[],"sources":["../src/index.tsx"],"mappings":";;YA07BY;;EAEV;;EAEA;;;;EAIA;;EAEA;EACA;;EAUA;;EAEA;EACA;EACA;;;;;;EAUA;;;;;;;;;;;wBAsBc,wBACd,aACA,oBACA,qBACC;;;;;;wBAkHmB,sBAAsB,cAAc,QAAQ;;;;;;;;;wBAyC5C,yBAAyB,eAAe,QAAQ;;;;;;;wBAUtD,oBACd;EAAS;EAAoB;eAC7B;;;;wBAUc,sBACd;EAAS;EAAoB;eAC7B;;;;;;wBAUc,YAAY;;;wBAMZ,WAAW;;;;wBAOX,yBAAyB,GAAG,iBAAiB,GAAG;;;;;wBAahD,oBACd,cAAc,mBACd,oBACA,cACA;EACG,QAAQ;EAAmB,QAAQ;;;;;wBAmCxB,sBACd,cAAc,mBACd,sBACA,cACA,4BACC;;qBAMU;;;;qBAKA;;;qBAIA;qBACA;;;;;;;;;;qBAWA;;;;;;;;qBASA;;;;;qBAMA;;;;;;;;;wBAUG,mBACd,OAAO,iBACP,aACA,uBACC;;;wBAWa,WAAW;;;;wBAeX,kBAAkB,OAAO,iBAAiB;;;YAQ9C;wBAEI,mBAAmB,OAAO,kBAAkB;wBAa5C,wBAAwB,OAAO;;;;wBAqB/B,uBAAuB;;;;;;;YAW3B,yBAAyB;;;;;YAMzB;;;;wBAKI,oBAAoB,OAAO,yBAAyB;YAuBxD;EACV;EACA;EACA;;;;;wBAsBc,oBACd;EACE;EACA;EACA;EACA;IAAU;IAAiB,QAAQ;;GAErC;EACG;EAAmB,UAAU;;;wBAYlB,kBACd,KAAK,YAAY,eACjB,mBACA,UAAU;;wBAWI,sBACd,KAAK,YAAY,eACjB,+BACA,cACA,iBACC;;;;;;;wBAca,4BACd,mBAAmB,mBACnB,eAAe,wBACd;;YAiGS;EACV;EACA;EACA;EACA;EACA;EACA;IACE;IACA,QAAQ;IACR;IACA;IACA;MAAS;MAAgB;;;;;YAKjB;;EAEV;;EAEA;;EAEA;EACA;;EAEA;EACA;;EAEA;;EAEA;EACA;EACA;EACA;;;YAIU;EACV;EACA;EACA;EACA;;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;;;;;;wBAYc,wBACd,MAAM,oBACN,eACC;;;wBAsDa,yBACd,KAAK,YAAY,sBACjB,MAAM,oBACN;;;wBAwEc,sBACd,KAAK,YAAY,sBACjB;;;;;;;;;wBAoBc,2BACd;EAAqB;EAAa;iBAClC,YAAY,uDACX;;;;;wBAwBa,sBACd,KAAK,YAAY,sBACjB,gBAAgB,sBAChB;;;wBAWc,kBAAkB,MAAM,sBAAsB;;;;;;wBAoB9C,uBACd,eAAe,uBACf,aAAa,oBACZ;;;;;;;;;;;;;;;;;wBA0Ca,2BACd,kBAAkB,mBAClB,6CACC;;;;;;;;;wBAyCa,iBAAiB,cAAc;;;;YAOnC;;EAEV;EACA;;IAEE;MAAU;;;IAEV;MAAU;QAAY;QAAe,SAAS;;;;;;;;;;wBASlC,wBAAwB,SAAS;;;;;;;;;;;;wBAuBjC,gBAAgB;EAAgB;;;;;;;wBAUhC,kBAAkB;EAAkC;;;YAKxD;;EAEV;;EAEA;;;EAGA;;;EAGA;EACA;IACE;IACA;;;;;;;;;;;;;;;;;;;;wBAqBY,mBACd,4BACA;EAAS;EAAkB;GAC3B,cACA;;;;;;;YA6BU;;;;;wBAMI,oBAAoB,OAAO,yBAAyB;;;qBAmBvD,uBAAuB,SAAS,OAAO;wBAOpC,mBAAmB,QAAQ;;;;wBAO3B,oBAAoB,OAAO,wBAAwB;;;;;wBAUnD,sBAAsB,OAAO;;;qBAShC;wBAEG,sBAAsB,kBAAkB;;;qBAO3C;;;;wBAoBG,8BACd,cACA;;;;qBAUW;wBAEG,wBACd,OAAO,iBACP,aACA;;;;wBAUc,wBAAwB,OAAO,iBAAiB;;;;qBAYnD;;;;;wBAMG,uBAAuB,kBAAkB;;;;wBAyBzC,sBACd,cAAc,mBACd,qBACA;EACG,SAAS;EAAmB;EAAgB;EAAsB;;;;;wBAevD,uBAAuB,kBAAkB;EACvD;EACA;EACA;;;;;wBAUc,mBACd,kBACA,kBACA,gBACA,YACA;wBA8Cc,4BACd,mBAAmB,mCACnB,aAAa,mBACb,cACA,2BACC;;;;;;wBA4Da,4BACd;EAEM,YAAY,cAAc,SAAS,mCAAmC;eAG5E;;wBAmBc,+BACd;EAEM,YAAY,cAAc,SAAS,mCAAmC;eAG5E;;;;;YAwLU;EACV,KAAK,YAAY;;EAEjB;;EAEA;;cAsfI,QAAQ;EAAoB;EAAY,aAAa"}
|
|
@@ -121,12 +121,14 @@ async function resolvePresetForTui(env, cwd) {
|
|
|
121
121
|
}
|
|
122
122
|
async function detectVersion(api) {
|
|
123
123
|
try {
|
|
124
|
-
const
|
|
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
|
|
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.
|
|
170
|
+
return "1.6.0-beta.5";
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
916
|
-
const DELEGATION_FAILED_RETENTION_MS =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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})`;
|