dsh-context 0.73.3 → 0.75.0

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/lib/index.d.ts CHANGED
@@ -4,21 +4,25 @@ import "@deepseek-ai/dsh-session";
4
4
  import z$1 from "@deepseek-ai/schemastery";
5
5
  import { Context } from "@deepseek-ai/cordis";
6
6
  //#region src/host/activity.d.ts
7
+ interface ToolStart {
8
+ start: number;
9
+ day: string;
10
+ }
7
11
  interface ActivityState {
8
12
  days: Record<string, ActivityDay>;
9
13
  /** The route in force (the last `request/header`'s config wins) — prices each settlement. */
10
14
  model?: string;
11
15
  provider?: string;
12
- /** The open step's start instant (armed by `step/start`, cleared by `step/end`). */
13
16
  stepStart?: number;
14
- /** Pending `skill`-tool call ids (armed by `tool/call`, consumed by the pairing `tool/result`):
15
- * the wrapper match alone is not trusted, or a `read` of source text quoting
16
- * `<skill_content name="…">` would book a load. Bounded at {@link MAX_PENDING_SKILL_CALLS}. */
17
+ /** The last turn whose first settlement was booked, so a multi-step turn counts once. */
18
+ lastTurn?: number;
19
+ toolStarts?: Record<string, ToolStart | undefined>;
20
+ /** Pending `skill`-tool call ids: the wrapper match alone is not trusted, or a `read` quoting it would book a load. */
17
21
  skillCalls?: string[];
18
22
  }
19
23
  //#endregion
20
24
  //#region src/host/headers.d.ts
21
- /** One stored tool: v1 rows carried the producer description and raw schema; later folds append metadata-only. */
25
+ /** v1 rows carried the producer description and raw schema; later folds append metadata-only. */
22
26
  interface StoredHeaderTool {
23
27
  name: string;
24
28
  tokens: number;
@@ -26,7 +30,7 @@ interface StoredHeaderTool {
26
30
  plugin?: string;
27
31
  schema?: unknown;
28
32
  }
29
- /** One stored epoch: v1 rows carried `system`; later folds carry `systemTokens`. */
33
+ /** v1 rows carried `system`; later folds carry `systemTokens`. */
30
34
  interface StoredHeaderRecord {
31
35
  seq: number;
32
36
  time: number;
@@ -39,115 +43,109 @@ interface HeadersState {
39
43
  }
40
44
  //#endregion
41
45
  //#region src/host/foldState.d.ts
46
+ /** The state's command record: the wire record plus the callId the fold pairs result/job events on. Never served —
47
+ * `foldWire` strips it (optional precisely so the strip is a plain `delete`). */
48
+ interface CommandStateRecord extends CommandRecord {
49
+ call?: string;
50
+ }
42
51
  interface TimelineState {
43
52
  /** Model-visible surface, newest last. */
44
53
  surface: SurfaceNode[];
45
54
  sums: Record<Category, number>;
46
55
  systemTokens: number;
47
- /** The live system-prompt nodes, oldest first. `systemTokens` is the LAST entry with tokens > 0 (the harness's
48
- * own "last nonempty surviving system" rule), so an empty dormant node keeps its position without clearing the
49
- * prompt. Bounded by SYSTEM_NODES_MAX. Absent on rows folded before this field existed; the client then falls
50
- * back to the header epoch's own envelope figure. */
56
+ /** The live system-prompt nodes, oldest first; `systemTokens` is the LAST nonempty one (the harness rule), so an empty dormant node
57
+ * keeps its position. Absent rows fall back to the header epoch's envelope figure. */
51
58
  systems?: SystemPromptNode[];
52
59
  toolsTokens: number;
53
- /** The projection cache requires plain JSON: a property whose value is `undefined` makes the whole checkpoint
54
- * unserializable, failing EVERY cache write for the session — including the `title` row that powers the session
55
- * list after a restart. Optional fields therefore stay absent until a value is known, never `undefined`-valued. */
60
+ /** The projection cache requires plain JSON: an `undefined`-valued property fails EVERY cache write for the session, so optional fields
61
+ * stay absent until a value is known. */
56
62
  model?: string;
57
63
  provider?: string;
58
64
  lastModel?: string;
59
65
  contextWindow?: number;
60
- /** The newest `request/header` envelope's routed output cap (dsh materializes the adapter default
61
- * into it). Last-wins: a header omitting the cap clears it. */
66
+ /** The newest `request/header` envelope's routed output cap (dsh materializes the adapter default into it). Last-wins: a header
67
+ * omitting the cap clears it. */
62
68
  maxOutputTokens?: number;
63
69
  requests: RequestRecord[];
64
- /** The number of turn runs in `requests` (a run = consecutive records sharing one `turn`). Maintained
65
- * incrementally at the single append site and recomputed when a trim replaces the array, so the retention
66
- * trim's cap check stays O(1) per event. Absent on rows folded before the field existed. */
70
+ /** Turn runs in `requests` (consecutive records sharing one `turn`), maintained at the single append site and recomputed on trim, so
71
+ * the cap check stays O(1); absent on older rows. */
67
72
  turnRuns?: number;
68
73
  events: ContextEventRecord[];
69
- /** Recently removed surface nodes (stamped COPIES carrying `gone`), in removal order. Bounded two ways in
70
- * trimState: capped to `maxArchiveNodes`, and pruned to removals after the oldest retained request. */
74
+ /** Removed surface nodes as stamped COPIES carrying `gone`, in removal order; bounded to `maxArchiveNodes` and pruned to removals after
75
+ * the oldest retained request. */
71
76
  archived: SurfaceNode[];
72
- /** Cumulative billed-token totals per (provider, model), split into pricing periods for DeepSeek. Never trimmed, so
73
- * the estimate covers the COMPLETE session log. */
77
+ /** Cumulative billed-token totals per (provider, model, period); never trimmed, so the estimate covers the COMPLETE log. */
74
78
  cost?: SessionCostUsage;
75
- /** Whole-session human-input tally (see Snapshot.humanInputs); never trimmed, like `cost`. */
76
79
  humanInputs?: number;
77
- /** Whole-session answers tally (see Snapshot.answers); never trimmed, like `humanInputs`. */
78
80
  answers?: number;
79
- /** The user's newest own message as a bounded one-line preview. Last-wins: a text-less input (images only) keeps the previous line. */
81
+ /** The user's newest own message as a bounded one-line preview. Last-wins: a text-less input keeps the previous line. */
80
82
  lastUser?: string;
81
83
  archiveFloor?: number;
82
- /** Bumped by every fold that mutates the request records, context events, live surface, or removed-node
83
- * archive; the slim wire head carries it so an open tab knows its fetched detail went stale. */
84
+ /** Bumped when a fold mutates the served detail (requests, events, live surface, archive); the slim head carries it. */
84
85
  detailRev?: number;
85
- /** Whole-session timing totals (see TimingTotals), running sums over the COMPLETE session log like `cost`. */
86
+ /** Whole-session timing totals, running sums over the COMPLETE log like `cost`. */
86
87
  timing?: TimingTotals;
87
- /** The open step's start instant, armed by `step/start` and consumed by the `assistant/message` (TTFT/generation
88
- * split) and `step/end` (wall time) that follow. One slot, not a map: steps are sequential in the log, so the
89
- * newest `step/start` is the one those events close — a hostile interleaved log degrades to skipped durations. */
88
+ /** The open step's start instant, armed by `step/start` and consumed by the following `assistant/message` and `step/end`; one slot, not
89
+ * a map, so a hostile interleaved log degrades to skipped durations. */
90
90
  stepStart?: {
91
91
  time: number;
92
92
  firstToken?: number;
93
93
  };
94
- /** The open step's CLOSED user-wait intervals (real log instants), pushed replace-style as each wait settles: an
95
- * approval decision, or an `ask_user_question` call's whole tool window. `step/end` subtracts their clamped
96
- * union from the step window to price the request's `activeMs`, then deletes the slot. */
94
+ /** The open step's CLOSED user-wait intervals; `step/end` subtracts their clamped union from the step window to price `activeMs`, then
95
+ * deletes the slot. */
97
96
  stepWaits?: {
98
97
  start: number;
99
98
  end: number;
100
99
  }[];
101
- /** The open step's PENDING approval waits (request id → its `approval/asked` instant), disarmed by the matching
102
- * `approval/decided`. A crash mid-decision leaves the pair dangling, so `step/end` closes the survivors at its
103
- * own instant. Deleted at `step/start` (a superseded step's leftovers) and `step/end`. */
100
+ /** The open step's PENDING approval waits (request id → `approval/asked` instant); a crash mid-decision leaves the pair dangling, so
101
+ * `step/end` closes the survivors at its own instant. */
104
102
  stepApprovals?: Record<string, number>;
105
- /** The seq of the request record committed by the open step's `assistant/message` — the back-pointer `step/end`
106
- * stamps `activeMs` onto. Nothing pushes between a step's message and its end, so the record is the requests
107
- * tail and the stamp is an O(1) tail write guarded by this seq. */
103
+ /** The seq of the request record the open step's `assistant/message` committed — the back-pointer `step/end` stamps `activeMs` onto;
104
+ * nothing pushes between a step's message and its end, so the stamp is an O(1) tail write. */
108
105
  stepRequestSeq?: number;
109
- /** The timing strip's painted spans: every completed step's time slices in log order, stamped with their REAL
110
- * instants — the TTFT wait, the decode blocks in stream order, the tool-run windows, and the in-step residue.
111
- * Idle time BETWEEN steps carries no span. Bounded by TIMING_SPANS_MAX (newest tail kept). */
106
+ /** The timing strip's painted spans in log order, stamped with their REAL instants; idle time BETWEEN steps carries no span. Bounded by
107
+ * TIMING_SPANS_MAX (newest tail kept). */
112
108
  spans: TimingSpan[];
113
- /** The open step's accumulated painted spans; `step/end` clamps them into the step window, de-overlaps
114
- * first-wins (parallel runs paint their union), fills the holes with the residue kind, and flushes the tiling
115
- * into `spans`. Deleted at the flush (the plain-JSON precondition). */
109
+ /** The open step's accumulated spans; `step/end` clamps them into the step window, de-overlaps first-wins (parallel runs paint their
110
+ * union), fills holes with the residue kind, then deletes the slot (plain-JSON precondition). */
116
111
  stepSpans?: TimingSpan[];
117
- /** Tool callId → the call's name, start instant, and raw arguments, armed by `tool/call` and DELETED when its
118
- * `tool/result` folds in — the map stays at pending-call size instead of growing for the session's lifetime. */
112
+ /** Tool callId → name, start instant and raw arguments, armed by `tool/call` and DELETED when its `tool/result` folds in — the map
113
+ * stays at pending-call size instead of growing for the session's lifetime. */
119
114
  callNames: Record<string, {
120
115
  name: string;
121
116
  start: number;
122
117
  argsRaw?: string;
123
118
  }>;
124
- /** Seq list of the surface nodes the next replacement will shadow, armed by the metering event
125
- * (`compaction/summary` | `compaction/prune`) and consumed by the replacement that must follow it
126
- * synchronously. The producer's shadow price covers exactly these seqs, which can differ from the
127
- * replacement's declared range (pruned replacement nodes keep their own seqs, beyond the range end). */
119
+ /** Seq list the next replacement shadows, armed by the metering event and consumed by the replacement that must follow synchronously;
120
+ * it can differ from the replacement's declared range (pruned nodes keep their own seqs). */
128
121
  pendingShadowedSeqs?: number[];
129
- /** The seq of the `compaction/prune` event that armed `pendingShadowedSeqs`. The shadowed path rewrites that
130
- * event's `tokens` from the gross shadow price to the NET freed amount, so the row matches the drop the trend chart shows. */
122
+ /** The metering event whose `tokens` the shadowed path rewrites from gross shadow price to the NET freed amount. */
131
123
  pendingShadowEventSeq?: number;
132
- /** The fold-derived file-operation log: one record per executed file op, bounded by `maxFileOps`; the trim stamps `fileOpsFloor`. */
133
124
  fileOps: FileOpRecord[];
134
125
  /** The newest dropped op's seq (the card's coverage floor for the served op log). */
135
126
  fileOpsFloor?: number;
136
- /** Nested Code-Mode ops buffered by their top run_code call id until the parent's result folds (the dispatch
137
- * events land BEFORE it). Bounded by PENDING_CODE_OPS_MAX, so a hostile log that never settles a run_code cannot grow it. */
127
+ /** The command log, in call order (creation at `tool/call`, settle in place at `tool/result`/`job/settled`). */
128
+ commands: CommandStateRecord[];
129
+ /** The newest dropped command record's seq (the panel's coverage floor). */
130
+ commandsFloor?: number;
131
+ /** Whole-log execution tallies; each record contributes exactly once, at its running → terminal transition. */
132
+ commandStats?: CommandStats;
133
+ /** Nested Code-Mode command records buffered by their top run_code call id until the parent's result folds
134
+ * (same lifecycle as `pendingCodeOps`). */
135
+ pendingCodeCmds?: Record<string, CommandStateRecord[]>;
136
+ /** Nested Code-Mode ops buffered by their top run_code call id until the parent's result folds (the dispatch events land BEFORE it).
137
+ * Bounded by PENDING_CODE_OPS_MAX, so a hostile log that never settles a run_code cannot grow it. */
138
138
  pendingCodeOps?: Record<string, FileOpRecord[]>;
139
139
  }
140
140
  //#endregion
141
141
  //#region src/shared/types.d.ts
142
142
  declare module '@deepseek-ai/dsh-session-projection/types' {
143
143
  interface SessionProjectionMap {
144
- /** The plugin's timeline: slim head on the split generation, inline value on channel-less
145
- * hosts; key absence = the host half is not composed. */
144
+ /** Slim head on the split generation, inline value on channel-less hosts; key absence = no host half. */
146
145
  contextTimeline: ContextTimeline;
147
- /** Request-header content epochs — a separate unit so the hot timeline value stays lean;
148
- * key absence = an older host (tokens only). */
146
+ /** Epoch metadata in its own unit so the hot timeline stays lean; key absence = an older host (tokens only). */
149
147
  contextHeaders: ContextHeaders;
150
- /** The per-day activity ledger behind the Context Insights heatmap; key absence = an older host (empty heatmap). */
148
+ /** The per-day activity ledger; key absence = an older host (empty heatmap). */
151
149
  contextActivity: ContextActivity;
152
150
  }
153
151
  interface SessionProjectionStateMap {
@@ -156,25 +154,23 @@ declare module '@deepseek-ai/dsh-session-projection/types' {
156
154
  contextActivity: ActivityState;
157
155
  }
158
156
  }
159
- /** The priced surface buckets. `skill` carries the skill-machinery content the harness injects:
160
- * the `<available_skills>` digest, a `/name` invocation's instructions, and a `skill`-tool load. */
157
+ /** `skill` is the harness-injected skill machinery: the `<available_skills>` digest, a `/name` invocation's instructions, and a
158
+ * `skill`-tool load. */
161
159
  type Category = 'user' | 'inject' | 'skill' | 'assistant' | 'tool';
162
- /** One live system-prompt node; the harness models the prompt as a surface node, so its TEXT is
163
- * fetched from the `system/message` event at `seq`. The effective figure is the LAST node with `tokens > 0`. */
160
+ /** Its TEXT comes from the `system/message` event at `seq`; the effective figure is the LAST node with `tokens > 0`. */
164
161
  interface SystemPromptNode {
165
162
  seq: number;
166
163
  time: number;
167
164
  tokens: number;
168
165
  }
169
- /** Counts precomputed over the RETAINED request/event records; `steps` is the retained request-record count. */
166
+ /** Counts over the RETAINED records; `steps` is the retained request-record count. */
170
167
  interface TimelineCounts {
171
168
  turns: number;
172
169
  steps: number;
173
170
  injects: number;
174
171
  compactions: number;
175
172
  prunes: number;
176
- /** Distinct names among the retained events tagged `sub: 'skill'`; the `<available_skills>`
177
- * digest has no name and never counts. Absent = 0. */
173
+ /** Distinct names among the retained events tagged `sub: 'skill'`; the digest has none and never counts. Absent = 0. */
178
174
  skills?: number;
179
175
  }
180
176
  /** The newest retained request record's billing summary. */
@@ -184,47 +180,55 @@ interface TimelineLast {
184
180
  prompt?: number;
185
181
  }
186
182
  interface ActivityDay {
187
- /** Billed tokens from provider-reported usage that day (input + cache read/write + output); a
188
- * settlement-less request counts only toward `requests`. */
183
+ /** Billed tokens that day (input + cache read/write + output); a settlement-less request counts only toward `requests`. */
189
184
  tokens: number;
190
185
  /** Completed model calls (assistant settlements) that day. */
191
186
  requests: number;
192
- /** The day's billed buckets keyed provider → model → pricing period, scoped to the day the
193
- * requests INITIATED in. Absent = tokens-only bars. */
187
+ /** Keyed provider → model → pricing period, scoped to the day the requests INITIATED. Absent = tokens-only bars. */
194
188
  cost?: SessionCostUsage;
189
+ /** Turns whose FIRST settlement landed on this (step-initiation) day. */
190
+ turns?: number;
191
+ /** Completed tool runs whose step STARTED that day. */
192
+ toolCalls?: number;
193
+ /** Summed tool-run durations for those runs, in ms. */
194
+ toolsMs?: number;
195
+ /** Summed wall time of steps that ENDED, charged to the day their step STARTED, in ms. */
196
+ wallMs?: number;
195
197
  /** Skill name → `{ n: loads, last: last-load instant in epoch ms }`; absent = an empty day. */
196
198
  skills?: Record<string, {
197
199
  n: number;
198
200
  last: number;
199
201
  }>;
200
202
  }
201
- /** The per-session daily ledger: host-local day key (`YYYY-MM-DD`, shared/days.ts) → that day's
202
- * billed volume; the Context Insights page merges every listed session's ledger. */
203
+ /** Host-local day key (`YYYY-MM-DD`, shared/days.ts) → that day's billed volume; the Insights page merges every listed ledger. */
203
204
  interface ContextActivity {
204
205
  days: Record<string, ActivityDay>;
205
206
  }
206
- /** One available skill's catalog metadata, served by `/api/dsh-context/skills` (host/skills.ts); every field but `name` is best-effort. */
207
+ /** Served by `/api/dsh-context/skills` (host/skills.ts); every field but `name` is best-effort. */
207
208
  interface SkillInfo {
208
209
  /** Kebab-case identifier — the join key onto `ActivityDay.skills`. */
209
210
  name: string;
210
211
  description: string;
211
212
  /** Absolute instruction file path, when the provider is filesystem-backed. */
212
213
  path?: string;
213
- /** Discovery source bucket (e.g. 'project-agents', 'user-dsh', 'bundled'). */
214
+ /** Discovery source bucket ('project-agents', 'user-dsh', 'bundled', …). */
214
215
  source?: string;
215
216
  }
216
- /** The display-preference vocabulary of the `dsh-context` entry — the ONE declaration shared by
217
- * the Host Config schema (host/config.ts) and the Client's settings form (client/settings.ts). */
217
+ /** The ONE declaration shared by the Host Config schema (host/config.ts) and the Client's settings form. */
218
218
  type DefaultGranularity = 'step' | 'turn';
219
219
  type DefaultTrendMode = 'total' | 'delta';
220
- /** The browser delta baseline: against the immediately preceding record, or the previous turn's last step. */
220
+ /** The browser delta baseline: the immediately preceding record, or the previous turn's last step. */
221
221
  type DefaultDeltaBase = 'step' | 'turn';
222
- type DefaultFileSort = 'count' | 'latest' | 'path' | 'name';
222
+ type DefaultFileSort = 'count' | 'lines' | 'latest' | 'path' | 'name';
223
223
  type DefaultToolSort = 'size' | 'count' | 'name';
224
- type DefaultPlacement = 'all' | 'tab' | 'sidebar';
224
+ /** Where the Context panel mounts; 'hide' registers no surface. */
225
+ type DefaultPlacement = 'all' | 'tab' | 'sidebar' | 'hide';
225
226
  type InsightsEntry = 'show' | 'hide';
226
227
  type DefaultDurationCurve = 'show' | 'hide';
227
- /** Whether the Fleet conversation tab is served. */
228
+ /** Retained-step count at which the trend turns its Overview ribbon on; 'off' never auto-switches. */
229
+ type OverviewAutoSteps = 'off' | '100' | '200' | '300';
230
+ /** The Insights page's rolling preset; a calendar-picked range replaces it for that visit only. */
231
+ type DefaultOverviewRange = 'today' | '7d' | '30d' | 'all';
228
232
  type FleetTab = 'show' | 'hide';
229
233
  interface PluginSettings {
230
234
  defaultPlacement: DefaultPlacement;
@@ -235,6 +239,8 @@ interface PluginSettings {
235
239
  defaultFileSort: DefaultFileSort;
236
240
  insightsEntry: InsightsEntry;
237
241
  defaultDurationCurve: DefaultDurationCurve;
242
+ overviewAutoSteps: OverviewAutoSteps;
243
+ defaultOverviewRange: DefaultOverviewRange;
238
244
  fleetTab: FleetTab;
239
245
  /** Free text joined ahead of the harness's assembled system prompt; empty disables. */
240
246
  promptPrefix: string;
@@ -243,8 +249,7 @@ interface PluginSettings {
243
249
  }
244
250
  interface Snapshot {
245
251
  ok: boolean;
246
- /** Present ONLY when the running harness is below the supported baseline: the host folds
247
- * nothing (all figures zero) and the client shows the upgrade gate. */
252
+ /** Present ONLY below the supported baseline: the host folds nothing (all figures zero) and the client shows the upgrade gate. */
248
253
  unsupported?: {
249
254
  current: string;
250
255
  minimum: string;
@@ -252,8 +257,8 @@ interface Snapshot {
252
257
  model?: string;
253
258
  provider?: string;
254
259
  contextWindow?: number;
255
- /** The newest request envelope's routed output cap, which auto-compaction reserves before pricing
256
- * its pressure trigger. Absent = no cap in the log (or a row folded before the field existed). */
260
+ /** The newest request envelope's routed output cap (auto-compaction reserves it). Absent = no cap in the log, or a row folded before
261
+ * the field existed. */
257
262
  maxOutputTokens?: number;
258
263
  current: {
259
264
  system: number;
@@ -265,57 +270,58 @@ interface Snapshot {
265
270
  tool: number;
266
271
  total: number;
267
272
  };
268
- /** Image blocks in the CURRENT context (uploads plus nested tool-result images), summed over live surface nodes. Absent = 0. */
273
+ /** Image blocks in the CURRENT context (uploads plus nested tool-result images). Absent = 0. */
269
274
  images?: number;
270
- /** Tool calls whose result is live (a `skill`-tool node keeps counting); in-flight and
271
- * compacted/pruned-out calls are excluded. Absent = 0. */
275
+ /** Tool calls whose result is live (a `skill`-tool node keeps counting). Absent = 0. */
272
276
  toolCalls?: number;
273
- /** Whole-session tally of non-injection `user/message` plus answered `ask_user_question` — a
274
- * running total over the COMPLETE log. Absent = 0. */
277
+ /** Whole-session tally of non-injection `user/message` plus answered `ask_user_question` over the COMPLETE log. Absent = 0. */
275
278
  humanInputs?: number;
276
279
  /** Whole-session replies: one per assistant message carrying non-blank text (tool-only steps are not replies). Absent = 0. */
277
280
  answers?: number;
278
281
  /** The newest own message as a one-line preview (first text block, whitespace collapsed, 80 chars max). Absent = hidden. */
279
282
  lastUser?: string;
280
- /** Split-generation head fields — present exactly when the host serves the slim head;
281
- * `detailRev` bumps whenever the detail collections change. */
283
+ /** Split-generation head fields: present exactly when the host serves the slim head; `detailRev` bumps whenever the detail collections
284
+ * change. */
282
285
  counts?: TimelineCounts;
283
286
  last?: TimelineLast;
284
287
  detailRev?: number;
285
- /** The slim head serves these EMPTY (the collections ride the detail channel); the client swaps in the detail payload's collections. */
288
+ /** The slim head serves these EMPTY (collections ride the detail channel): the client swaps in the detail payload's. */
286
289
  requests: RequestRecord[];
287
290
  events: ContextEventRecord[];
288
- /** Cumulative session-cost raw material (SessionCostUsage); absent until a request with a known model reports usage. */
291
+ /** Cumulative session-cost raw material; absent until a request with a known model reports usage. */
289
292
  cost?: SessionCostUsage;
290
- /** Whole-session timing totals (TimingTotals). Absent until the first step lifecycle completes. */
293
+ /** Whole-session timing totals; absent until the first step lifecycle completes. */
291
294
  timing?: TimingTotals;
292
- /** The live system-prompt nodes, oldest first. Absent on rows folded before the field existed
293
- * — the client then reads the header epoch's `systemTokens`. */
295
+ /** The live system-prompt nodes, oldest first. Absent on rows folded before the field existed: the client then reads the header epoch's
296
+ * `systemTokens`. */
294
297
  systems?: SystemPromptNode[];
295
- /** The served live surface: the newest `maxNodes` tail PLUS every live inject/skill node older
296
- * than the tail (they land first and are pinned). Seq-ordered, oldest first. */
298
+ /** The served live surface: the newest `maxNodes` tail PLUS every older live inject/skill node (they land first and are pinned).
299
+ * Seq-ordered, oldest first. */
297
300
  nodes: SurfaceNode[];
298
301
  /** Live nodes not served: the overflow beyond `maxNodes` minus the pinned inject/skill nodes. */
299
302
  droppedNodes: number;
300
- /** Recently REMOVED surface nodes (compaction/prune shadows) stamped with `gone` (the replacing
301
- * event's seq); a node belongs to request R when `seq < R.seq && (gone undefined || gone > R.seq)`. */
303
+ /** Recently REMOVED surface nodes stamped with `gone` (the replacing event's seq); a node belongs to request R when `seq < R.seq &&
304
+ * (gone undefined || gone > R.seq)`. */
302
305
  archive: SurfaceNode[];
303
306
  /** Newest seq among the `droppedNodes` nodes not served; present only when droppedNodes > 0. */
304
307
  surfaceFloor?: number;
305
308
  /** Newest `gone` among retention-dropped archive entries; steps below it may miss removed nodes. */
306
309
  archiveFloor?: number;
307
- /** The fold-derived file-op log and trim floor: the INLINE value and detail payload, never the slim head. */
310
+ /** The fold-derived file-op log and trim floor: INLINE value and detail payload only, never the slim head. */
308
311
  fileOps?: FileOpRecord[];
309
312
  fileOpsFloor?: number;
310
- /** The timing strip's painted spans: INLINE value and detail payload only; absent on rows folded before the collection existed. */
313
+ /** The fold-derived command log and its trim floor/coverage honesty, same channel as `fileOps`. */
314
+ commands?: CommandRecord[];
315
+ commandsFloor?: number;
316
+ /** Whole-log execution tallies behind the command panel's title; survives list trimming. */
317
+ commandStats?: CommandStats;
318
+ /** INLINE value and detail payload only; absent on rows folded before the collection existed. */
311
319
  spans?: TimingSpan[];
312
320
  }
313
- /** The on-demand DETAIL payload of the split generation: the heavy collections the slim head no
314
- * longer carries (host/detail.ts). `rev` mirrors the head's `detailRev` and is the client's latest-wins cursor. */
321
+ /** The split generation's DETAIL payload (host/detail.ts); `rev` mirrors the head's `detailRev` and is the client's latest-wins cursor. */
315
322
  interface ContextTimelineDetail {
316
323
  rev: number;
317
- /** The slim head at the SAME fold cut as the collections — a session listed cold has no
318
- * `contextTimeline` row, so the Agent network ring reads this. Optional. */
324
+ /** The slim head at the SAME fold cut; a cold-listed session has no `contextTimeline` row, so the Agent network ring reads this. */
319
325
  head?: ContextTimeline;
320
326
  requests: RequestRecord[];
321
327
  events: ContextEventRecord[];
@@ -324,16 +330,84 @@ interface ContextTimelineDetail {
324
330
  archive: SurfaceNode[];
325
331
  surfaceFloor?: number;
326
332
  archiveFloor?: number;
327
- /** The file-op log (shared/fileOps.ts) over the FULL log; Code-Mode nested dispatches book on their parent run_code result (`parent`). */
333
+ /** The file-op log (shared/fileOps.ts) over the FULL log; Code-Mode nested dispatches book on their parent `run_code` result. */
328
334
  fileOps?: FileOpRecord[];
329
- /** The newest dropped op's seq when the op log trimmed (coverage honesty, same family as archiveFloor). */
335
+ /** The newest dropped op's seq when the op log trimmed (coverage honesty, same family as `archiveFloor`). */
330
336
  fileOpsFloor?: number;
337
+ /** The command log (shared/commands.ts); nested Code-Mode dispatches flush on their parent `run_code` result. */
338
+ commands?: CommandRecord[];
339
+ /** The newest dropped record's seq when the command log trimmed. */
340
+ commandsFloor?: number;
341
+ commandStats?: CommandStats;
331
342
  /** The completed steps' time slices in log order, positioned by their real instants. Absent = no strip. */
332
343
  spans?: TimingSpan[];
333
344
  }
334
- /** One executed file operation, folded host-side from the durable tool lifecycle (`tool/call` +
335
- * `tool/result`, or a nested `tool/ptc-dispatch`); line deltas are estimates read off the call
336
- * ARGUMENTS. `gone` is client-joined, not host-stamped. */
345
+ type CommandStatus = 'running' | 'completed' | 'failed' | 'killed';
346
+ /** One shell/code execution, folded from `tool/call` (creation) paired with `tool/result` and — on hosts that log them —
347
+ * `job/registered` / `job/settled` (precise timing and outcome). Without job events the timing/exit are envelope-derived
348
+ * (`derived: true`). Nested Code-Mode dispatches carry `parent` (their run_code result's seq, the locate target).
349
+ * `gone` is client-joined, not host-stamped. */
350
+ interface CommandRecord {
351
+ /** The call event's seq — the record's stable identity. */
352
+ seq: number;
353
+ /** The result event's seq — the surface node a reveal targets. Absent while running and on nested Code-Mode records
354
+ * (those reveal on `parent`). */
355
+ resultSeq?: number;
356
+ /** The call event's instant — the list's chronological anchor. */
357
+ time: number;
358
+ tool: string;
359
+ /** The command text (a run_code record carries the program's source), capped at the fold's maxCommandChars. */
360
+ cmd: string;
361
+ cmdTruncated?: true;
362
+ /** The model-authored intent (bash/pwsh require it; persistent shells and run_code may omit it). */
363
+ description?: string;
364
+ /** The result meta's cwd when logged, else the workdir argument; absent = the session's cwd. */
365
+ cwd?: string;
366
+ timeoutMs?: number;
367
+ /** Dispatched to the background (an acked result with no outcome yet shows running until a `job/settled` lands). */
368
+ background?: true;
369
+ /** The requested sandbox escalation, when the call carried one. */
370
+ sandbox?: string;
371
+ /** A nested Code-Mode dispatch record. */
372
+ codeMode?: true;
373
+ parent?: number;
374
+ turn?: number;
375
+ step?: number;
376
+ /** job.startedAt when registered, else the call instant. */
377
+ start: number;
378
+ /** job.finishedAt when settled, else the result instant; absent while running. */
379
+ end?: number;
380
+ status: CommandStatus;
381
+ /** Explicit exit code from a marker or job detail; absent = unknown (never fabricate a 0). */
382
+ exit?: number;
383
+ /** The exit 0 was inferred from the ABSENCE of any marker (the shell tools omit the marker on a clean exit). */
384
+ exitInferred?: true;
385
+ signal?: string;
386
+ timedOut?: true;
387
+ stopped?: true;
388
+ denied?: true;
389
+ /** The result message's isError (an infrastructure failure, not a command failure). */
390
+ err: boolean;
391
+ outChars?: number;
392
+ outTruncated?: true;
393
+ stderr?: true;
394
+ /** Timing/exit derive from event envelopes — no job events on this log (parallel calls can overstate durations). */
395
+ derived?: true;
396
+ gone?: number;
397
+ }
398
+ /** Whole-log execution tallies, maintained incrementally: `runs`/`failed`/`ms` at each record's terminal transition,
399
+ * `bg` when a background dispatch becomes known (the argument at creation, else the hand-off ack). */
400
+ interface CommandStats {
401
+ runs: number;
402
+ /** Failed OR killed terminal outcomes. */
403
+ failed: number;
404
+ /** Summed execution ms over records with both endpoints known (concurrent runs double-count wall time). */
405
+ ms: number;
406
+ /** Runs dispatched to the background, whether or not they ever settle. */
407
+ bg: number;
408
+ }
409
+ /** Folded from the durable tool lifecycle (`tool/call` + `tool/result`, or a nested `tool/ptc-dispatch`); line deltas are estimates off
410
+ * the call ARGUMENTS. `gone` is client-joined, not host-stamped. */
337
411
  interface FileOpRecord {
338
412
  seq: number;
339
413
  /** The op's file; for a pathless search the searched PATTERN (`pattern: true`). */
@@ -367,9 +441,8 @@ interface FileOpRecord {
367
441
  }
368
442
  /** The `contextTimeline` projection's whole value; `ok` is always `true` here (kept for wire compatibility). */
369
443
  type ContextTimeline = Snapshot;
370
- /** One painted span of the timing card's session-time strip (a step's TTFT wait, decode block,
371
- * tool-run window, or residue gap). `start`/`end` are the slice's REAL instants; the strip packs
372
- * them gapless in log order, and `end` > `start` always. */
444
+ /** One painted span of the timing strip (TTFT wait, decode block, tool-run window, or residue gap); `start`/`end` are REAL instants,
445
+ * packed gapless in log order, and `end` > `start` always. */
373
446
  interface TimingSpan {
374
447
  /** The timing card's own slice vocabulary (same keys, same colors). */
375
448
  kind: 'ttft' | 'reasoning' | 'text' | 'toolarg' | 'tools' | 'other';
@@ -387,23 +460,9 @@ interface ToolTimingTotals {
387
460
  calls: number;
388
461
  ms: number;
389
462
  }
390
- /**
391
- * Whole-session timing totals, host-folded from the durable step/tool lifecycle plus the call's
392
- * first token (its embedded `assistant/message.data.stream`); running totals over the COMPLETE log.
393
- *
394
- * Milliseconds: `wallMs` sums whole steps; `ttftMs` the step-start → decode-start slice and `genMs`
395
- * the decode-start → assistant-message slice (only over calls whose stream carried a token delta);
396
- * `toolsMs` sums per-call tool durations (parallel calls each count). The decode window opens at the
397
- * first OBSERVABLE instant — the first token, or an earlier `block-start` marker (a redacted
398
- * reasoning block leaves no chunk): anchoring at the token would double-count the marker-tiled
399
- * window past 100%.
400
- *
401
- * The generation split comes off the stream's `block-start` framing (`blockType`): `reasoningMs` /
402
- * `textMs` / `toolArgMs` and their block counts, each marker owning the interval to the next.
403
- * `speedTokens`/`speedMs` are the harness-parity throughput seat (first-token → assistant-message,
404
- * calls carrying both); `speedMs` KEEPS the first-token anchor. `calls` counts folded assistant
405
- * messages, `toolCalls` folded call/result pairs.
406
- */
463
+ /** Whole-session totals over the COMPLETE log: `wallMs` whole steps, `ttftMs` step-start → decode-start, `genMs`
464
+ * decode-start → assistant-message, `toolsMs` per-call. The decode window opens at the first OBSERVABLE instant, so
465
+ * marker-tiled windows never double-count; speed* keep the first-token anchor; `calls`/`toolCalls` count messages/pairs. */
407
466
  interface TimingTotals {
408
467
  wallMs: number;
409
468
  ttftMs: number;
@@ -422,20 +481,19 @@ interface TimingTotals {
422
481
  /** Per-tool-name tallies behind the timing card's ranking (bounded). */
423
482
  tools: Record<string, ToolTimingTotals>;
424
483
  }
425
- /** One billed model's totals split by pricing period: providers without period pricing book
426
- * everything under `peak`; DeepSeek bills `peak` at list price and `off` at half. */
484
+ /** One billed model's totals split by pricing period: period-less providers book everything under `peak`; DeepSeek's `peak` prices at
485
+ * twice the list (off-peak) rate, `off` at list. */
427
486
  interface CostModelUsage {
428
487
  peak?: CostBucketTotals;
429
488
  off?: CostBucketTotals;
430
489
  }
431
- /** The session-cost raw material: cumulative provider-reported billed tokens keyed by the request
432
- * envelope's DSH provider id ('' when none) then model id — the faces the Client's models.dev price book resolves. */
490
+ /** Cumulative provider-reported billed tokens keyed by the request envelope's DSH provider id ('' when none) then model id — the faces
491
+ * the Client's models.dev price book resolves. */
433
492
  interface SessionCostUsage {
434
493
  [provider: string]: {
435
494
  [model: string]: CostModelUsage;
436
495
  };
437
496
  }
438
- /** One model-visible message on the surface, with its heuristic token price. */
439
497
  interface SurfaceNode {
440
498
  seq: number;
441
499
  time?: number;
@@ -446,8 +504,8 @@ interface SurfaceNode {
446
504
  /** Set only on `archive` entries: the seq of the replacement event that shadowed this node. */
447
505
  gone?: number;
448
506
  form?: string;
449
- /** The producer identity the matching inject event names (host pricing.ts
450
- * `injectionSourceName`); absent when unreadable or predating the stamp. */
507
+ /** The producer identity the matching inject event names (host pricing.ts `injectionSourceName`); absent when unreadable or predating
508
+ * the stamp. */
451
509
  name?: string;
452
510
  text?: string;
453
511
  tool?: string;
@@ -469,15 +527,13 @@ interface RequestRecord {
469
527
  tool: number;
470
528
  total: number;
471
529
  prompt?: number;
472
- /** Skill-machinery tokens of this request (the `skill` composition category); absent on rows
473
- * folded before the category existed (read as 0). */
530
+ /** Skill-machinery tokens of this request; absent on rows folded before the category existed (read as 0). */
474
531
  skill?: number;
475
- /** Billed cache-read (served) prompt tokens — the hit-rate numerator against `prompt`; absent
476
- * on older hosts, and zero is a real value. */
532
+ /** Billed cache-read (served) prompt tokens — the hit-rate numerator against `prompt`; absent on older hosts, and zero is a real value.
533
+ */
477
534
  cacheRead?: number;
478
535
  output?: number;
479
- /** The step's ACTIVE ms (`step/start` → `step/end` minus in-step user waits: approval decisions
480
- * and `ask_user_question`), stamped at `step/end`; absent while the step is open. */
536
+ /** The step's ACTIVE ms (`step/start` → `step/end` minus in-step user waits), stamped at `step/end`; absent while the step is open. */
481
537
  activeMs?: number;
482
538
  /** Turn-mode aggregate marker, set by the Client's aggregateByTurn (the Host never sets it). */
483
539
  stepCount?: number;
@@ -503,17 +559,15 @@ interface ContextEventRecord {
503
559
  turn?: number;
504
560
  step?: number;
505
561
  }
506
- /** One tool of a request-header epoch, with its display price. */
507
562
  interface HeaderTool {
508
563
  name: string;
509
564
  tokens: number;
510
- /** The registering plugin's label when known: `mcp:<server>` for MCP tools, or the pinned
511
- * first-party map; `UNKNOWN_TOOL_SOURCE` marks a boot-time tool, absent = no tag. */
565
+ /** The registering plugin's label: `mcp:<server>` for MCP tools, or the pinned first-party map; `UNKNOWN_TOOL_SOURCE` marks a boot-time
566
+ * tool, absent = no tag. */
512
567
  plugin?: string;
513
568
  }
514
- /** One request-header epoch's METADATA (epoch boundaries and token prices, in force from this seq
515
- * until the next). The CONTENT is deliberately not projected — every list row and push frame would
516
- * carry it — and is fetched on demand as a {@link HeaderEpochContent}. */
569
+ /** One request-header epoch's METADATA, in force from this seq until the next. CONTENT is deliberately not projected (every list row
570
+ * would carry it) and is fetched as a {@link HeaderEpochContent}. */
517
571
  interface HeaderRecord {
518
572
  seq: number;
519
573
  time: number;
@@ -525,18 +579,16 @@ interface HeaderRecord {
525
579
  interface ContextHeaders {
526
580
  headers: HeaderRecord[];
527
581
  }
528
- /** One currency's DeepSeek open-platform balance figures. */
529
582
  interface PlatformBalanceEntry {
530
583
  /** The ISO code the platform reported (`CNY` / `USD`). */
531
584
  currency: string;
532
585
  /** `granted` + `toppedUp`, derived rather than read from the platform's `total_balance`, which rounds independently of its parts. */
533
586
  total: number;
534
- /** The not-expired granted (gift) balance. */
535
587
  granted: number;
536
588
  toppedUp: number;
537
589
  }
538
- /** The DeepSeek open-platform balance, served by `/api/dsh-context/balance`; `null` on the wire
539
- * (nothing rendered) when unconfigured or the read fails. */
590
+ /** The DeepSeek open-platform balance, served by `/api/dsh-context/balance`; `null` on the wire (nothing rendered) when unconfigured or
591
+ * the read fails. */
540
592
  interface PlatformBalance {
541
593
  isAvailable: boolean;
542
594
  /** One entry per currency the account holds; at least one. */
@@ -553,6 +605,9 @@ declare const DEFAULT_BOUNDS: {
553
605
  maxNodes: number;
554
606
  maxArchiveNodes: number;
555
607
  maxFileOps: number;
608
+ maxCommands: number;
609
+ /** The command text caps per record; the card offers the full text through the browser's message body. */
610
+ maxCommandChars: number;
556
611
  };
557
612
  /** The resolved fold bounds; derived from {@link DEFAULT_BOUNDS} so the two cannot drift. */
558
613
  type FoldBounds = typeof DEFAULT_BOUNDS;
@@ -564,14 +619,18 @@ export declare const Config: z$1<Schemastery.ObjectS<NoInfer<{
564
619
  maxNodes: z$1<number, number, "defined">;
565
620
  maxArchiveNodes: z$1<number, number, "defined">;
566
621
  maxFileOps: z$1<number, number, "defined">;
567
- defaultPlacement: z$1<"all" | "sidebar" | "tab", "all" | "sidebar" | "tab", "defined">;
622
+ maxCommands: z$1<number, number, "defined">;
623
+ maxCommandChars: z$1<number, number, "defined">;
624
+ defaultPlacement: z$1<"all" | "hide" | "sidebar" | "tab", "all" | "hide" | "sidebar" | "tab", "defined">;
568
625
  defaultGranularity: z$1<"step" | "turn", "step" | "turn", "defined">;
569
626
  defaultTrendMode: z$1<"delta" | "total", "delta" | "total", "defined">;
570
627
  defaultDeltaBase: z$1<"step" | "turn", "step" | "turn", "defined">;
571
628
  defaultToolSort: z$1<"count" | "name" | "size", "count" | "name" | "size", "defined">;
572
- defaultFileSort: z$1<"count" | "latest" | "name" | "path", "count" | "latest" | "name" | "path", "defined">;
629
+ defaultFileSort: z$1<"count" | "latest" | "lines" | "name" | "path", "count" | "latest" | "lines" | "name" | "path", "defined">;
573
630
  insightsEntry: z$1<"hide" | "show", "hide" | "show", "defined">;
574
631
  defaultDurationCurve: z$1<"hide" | "show", "hide" | "show", "defined">;
632
+ overviewAutoSteps: z$1<"100" | "200" | "300" | "off", "100" | "200" | "300" | "off", "defined">;
633
+ defaultOverviewRange: z$1<"30d" | "7d" | "all" | "today", "30d" | "7d" | "all" | "today", "defined">;
575
634
  fleetTab: z$1<"hide" | "show", "hide" | "show", "defined">;
576
635
  promptPrefix: z$1<string, string, "defined">;
577
636
  promptSuffix: z$1<string, string, "defined">;
@@ -582,14 +641,18 @@ export declare const Config: z$1<Schemastery.ObjectS<NoInfer<{
582
641
  maxNodes: z$1<number, number, "defined">;
583
642
  maxArchiveNodes: z$1<number, number, "defined">;
584
643
  maxFileOps: z$1<number, number, "defined">;
585
- defaultPlacement: z$1<"all" | "sidebar" | "tab", "all" | "sidebar" | "tab", "defined">;
644
+ maxCommands: z$1<number, number, "defined">;
645
+ maxCommandChars: z$1<number, number, "defined">;
646
+ defaultPlacement: z$1<"all" | "hide" | "sidebar" | "tab", "all" | "hide" | "sidebar" | "tab", "defined">;
586
647
  defaultGranularity: z$1<"step" | "turn", "step" | "turn", "defined">;
587
648
  defaultTrendMode: z$1<"delta" | "total", "delta" | "total", "defined">;
588
649
  defaultDeltaBase: z$1<"step" | "turn", "step" | "turn", "defined">;
589
650
  defaultToolSort: z$1<"count" | "name" | "size", "count" | "name" | "size", "defined">;
590
- defaultFileSort: z$1<"count" | "latest" | "name" | "path", "count" | "latest" | "name" | "path", "defined">;
651
+ defaultFileSort: z$1<"count" | "latest" | "lines" | "name" | "path", "count" | "latest" | "lines" | "name" | "path", "defined">;
591
652
  insightsEntry: z$1<"hide" | "show", "hide" | "show", "defined">;
592
653
  defaultDurationCurve: z$1<"hide" | "show", "hide" | "show", "defined">;
654
+ overviewAutoSteps: z$1<"100" | "200" | "300" | "off", "100" | "200" | "300" | "off", "defined">;
655
+ defaultOverviewRange: z$1<"30d" | "7d" | "all" | "today", "30d" | "7d" | "all" | "today", "defined">;
593
656
  fleetTab: z$1<"hide" | "show", "hide" | "show", "defined">;
594
657
  promptPrefix: z$1<string, string, "defined">;
595
658
  promptSuffix: z$1<string, string, "defined">;