zidane 5.6.14 → 5.7.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/README.md +3 -1
  2. package/dist/{agent-ClkpElCZ.d.ts → agent-BNS2nx_T.d.ts} +535 -15
  3. package/dist/agent-BNS2nx_T.d.ts.map +1 -0
  4. package/dist/chat/pure.d.ts +4 -0
  5. package/dist/chat/pure.js +3 -0
  6. package/dist/chat.d.ts +31 -661
  7. package/dist/chat.d.ts.map +1 -1
  8. package/dist/chat.js +5 -3
  9. package/dist/chat.js.map +1 -1
  10. package/dist/contexts/docker.d.ts +1 -1
  11. package/dist/contexts/docker.d.ts.map +1 -1
  12. package/dist/contexts/docker.js.map +1 -1
  13. package/dist/{contexts-BOtMvzli.js → contexts-BD2U_xpi.js} +2 -2
  14. package/dist/{contexts-BOtMvzli.js.map → contexts-BD2U_xpi.js.map} +1 -1
  15. package/dist/contexts.d.ts +3 -3
  16. package/dist/contexts.js +1 -1
  17. package/dist/edit-utils-DnfNoj16.js +574 -0
  18. package/dist/edit-utils-DnfNoj16.js.map +1 -0
  19. package/dist/{errors-DdZXnyXE.js → errors-CoQnKRf1.js} +32 -2
  20. package/dist/{errors-DdZXnyXE.js.map → errors-CoQnKRf1.js.map} +1 -1
  21. package/dist/fetch-url-CPxfiXDa.js +518 -0
  22. package/dist/fetch-url-CPxfiXDa.js.map +1 -0
  23. package/dist/image-sniff-B7uFSNO1.js +90 -0
  24. package/dist/image-sniff-B7uFSNO1.js.map +1 -0
  25. package/dist/{index-CbS75MD3.d.ts → index-CZOwAJIX.d.ts} +2 -2
  26. package/dist/index-CZOwAJIX.d.ts.map +1 -0
  27. package/dist/{index-CTDMMdIy.d.ts → index-Ck_AWt8P.d.ts} +3 -4
  28. package/dist/index-Ck_AWt8P.d.ts.map +1 -0
  29. package/dist/{index-v3Tzobqr.d.ts → index-KiS7w0dC.d.ts} +3 -3
  30. package/dist/index-KiS7w0dC.d.ts.map +1 -0
  31. package/dist/index.d.ts +6 -6
  32. package/dist/index.js +13 -12
  33. package/dist/index.js.map +1 -1
  34. package/dist/{interpolate-DM1UcKeQ.js → interpolate-TySiqKzc.js} +23 -23
  35. package/dist/{interpolate-DM1UcKeQ.js.map → interpolate-TySiqKzc.js.map} +1 -1
  36. package/dist/{login-7tHcckmX.js → login-BDeqENSe.js} +7 -58
  37. package/dist/login-BDeqENSe.js.map +1 -0
  38. package/dist/{mcp-DGeB7-3D.js → mcp-Kqzz-Rs_.js} +8 -6
  39. package/dist/mcp-Kqzz-Rs_.js.map +1 -0
  40. package/dist/mcp.d.ts +2 -2
  41. package/dist/mcp.js +1 -1
  42. package/dist/{messages-Dym8S_YH.js → messages-CvRQTdbR.js} +118 -39
  43. package/dist/messages-CvRQTdbR.js.map +1 -0
  44. package/dist/{presets-w9Px_aAm.js → presets-JuOnSI-i.js} +2 -2
  45. package/dist/{presets-w9Px_aAm.js.map → presets-JuOnSI-i.js.map} +1 -1
  46. package/dist/presets.d.ts +3 -3
  47. package/dist/presets.js +1 -1
  48. package/dist/{providers-beXyD9W9.js → providers-h4HJPbbv.js} +485 -31
  49. package/dist/providers-h4HJPbbv.js.map +1 -0
  50. package/dist/providers.d.ts +2 -2
  51. package/dist/providers.js +3 -3
  52. package/dist/restate.d.ts +1 -1
  53. package/dist/restate.d.ts.map +1 -1
  54. package/dist/restate.js.map +1 -1
  55. package/dist/session/sqlite.d.ts +1 -1
  56. package/dist/session/sqlite.d.ts.map +1 -1
  57. package/dist/session/sqlite.js +1 -1
  58. package/dist/session/sqlite.js.map +1 -1
  59. package/dist/{session-BRIsmBSY.js → session-BzLou2_-.js} +2 -2
  60. package/dist/{session-BRIsmBSY.js.map → session-BzLou2_-.js.map} +1 -1
  61. package/dist/session.d.ts +2 -2
  62. package/dist/session.js +2 -2
  63. package/dist/skills.d.ts +3 -3
  64. package/dist/skills.js +1 -1
  65. package/dist/skills.js.map +1 -1
  66. package/dist/{stats-Lc3zL3RM.js → stats-DAKBEKjc.js} +12 -2
  67. package/dist/stats-DAKBEKjc.js.map +1 -0
  68. package/dist/{stdio-loader-EVAF5KlU.js → stdio-loader-Ce68wUmM.js} +4 -4
  69. package/dist/stdio-loader-Ce68wUmM.js.map +1 -0
  70. package/dist/tool-formatters-CU-j3a3e.d.ts +1471 -0
  71. package/dist/tool-formatters-CU-j3a3e.d.ts.map +1 -0
  72. package/dist/tools/fetch-url.d.ts +70 -0
  73. package/dist/tools/fetch-url.d.ts.map +1 -0
  74. package/dist/tools/fetch-url.js +2 -0
  75. package/dist/tools/web-search.d.ts +7 -0
  76. package/dist/tools/web-search.d.ts.map +1 -0
  77. package/dist/tools/web-search.js +190 -0
  78. package/dist/tools/web-search.js.map +1 -0
  79. package/dist/{tools-DhrLrOEr.js → tools-BGtJK0vo.js} +1368 -421
  80. package/dist/tools-BGtJK0vo.js.map +1 -0
  81. package/dist/tools.d.ts +3 -3
  82. package/dist/tools.js +1 -1
  83. package/dist/{turn-operations-UAkOjO-u.js → transcript-anchors-BTSZAPVc.js} +147 -2713
  84. package/dist/transcript-anchors-BTSZAPVc.js.map +1 -0
  85. package/dist/{transcript-anchors-D0TR6djV.d.ts → transcript-anchors-DX90kXc4.d.ts} +13 -1299
  86. package/dist/transcript-anchors-DX90kXc4.d.ts.map +1 -0
  87. package/dist/tui.d.ts +58 -28
  88. package/dist/tui.d.ts.map +1 -1
  89. package/dist/tui.js +1349 -422
  90. package/dist/tui.js.map +1 -1
  91. package/dist/turn-operations-CCHfR9eC.js +1938 -0
  92. package/dist/turn-operations-CCHfR9eC.js.map +1 -0
  93. package/dist/turn-operations-DDIl4YVk.d.ts +658 -0
  94. package/dist/turn-operations-DDIl4YVk.d.ts.map +1 -0
  95. package/dist/{types-oKPBdCmL.js → types-BPw_i5vb.js} +1 -1
  96. package/dist/types-BPw_i5vb.js.map +1 -0
  97. package/dist/{types-KukEp-mi.d.ts → types-CEAMIUXw.d.ts} +1 -1
  98. package/dist/types-CEAMIUXw.d.ts.map +1 -0
  99. package/dist/types.d.ts +4 -4
  100. package/dist/types.js +3 -3
  101. package/docs/CHAT.md +53 -6
  102. package/docs/SKILL.md +3 -0
  103. package/docs/TUI.md +7 -0
  104. package/package.json +18 -2
  105. package/dist/agent-ClkpElCZ.d.ts.map +0 -1
  106. package/dist/index-CTDMMdIy.d.ts.map +0 -1
  107. package/dist/index-CbS75MD3.d.ts.map +0 -1
  108. package/dist/index-v3Tzobqr.d.ts.map +0 -1
  109. package/dist/login-7tHcckmX.js.map +0 -1
  110. package/dist/mcp-DGeB7-3D.js.map +0 -1
  111. package/dist/messages-Dym8S_YH.js.map +0 -1
  112. package/dist/providers-beXyD9W9.js.map +0 -1
  113. package/dist/stats-Lc3zL3RM.js.map +0 -1
  114. package/dist/stdio-loader-EVAF5KlU.js.map +0 -1
  115. package/dist/tools-DhrLrOEr.js.map +0 -1
  116. package/dist/transcript-anchors-D0TR6djV.d.ts.map +0 -1
  117. package/dist/turn-operations-UAkOjO-u.js.map +0 -1
  118. package/dist/types-KukEp-mi.d.ts.map +0 -1
  119. package/dist/types-oKPBdCmL.js.map +0 -1
@@ -1,8 +1,7 @@
1
- import { F as SessionRun, I as SessionStore, Kt as McpServerConfig, P as SessionData, dn as ToolResultContent, ln as ThinkingLevel, lt as Provider, on as SessionTurn, y as ToolDef } from "./agent-ClkpElCZ.js";
2
- import { t as Preset } from "./index-CTDMMdIy.js";
3
- import { OAuthProviderInterface } from "@earendil-works/pi-ai/oauth";
1
+ import { F as SessionRun, I as SessionStore, P as SessionData, Zt as McpServerConfig, dn as SessionTurn, gn as ToolResultContent, mn as ThinkingLevel, y as ToolDef } from "./agent-BNS2nx_T.js";
2
+ import { t as Preset } from "./index-Ck_AWt8P.js";
3
+ import { A as SessionMeta, G as ProviderKey, I as CompletionItem, L as CompletionProvider, M as StreamEvent, O as Picked, P as ActiveTrigger, Q as ProviderDescriptor, R as CompletionReference, W as ProviderAuth, Y as ModelInfo, j as Settings, w as EditOutcome } from "./tool-formatters-CU-j3a3e.js";
4
4
  import { ReactNode } from "react";
5
- import * as _$react_jsx_runtime0 from "react/jsx-runtime";
6
5
 
7
6
  //#region src/chat/agents.d.ts
8
7
  /**
@@ -124,202 +123,6 @@ declare function resolveAgentId(registry: AgentRegistry, requestedId: string | u
124
123
  */
125
124
  declare function singleAgentRegistry(preset: Preset): AgentRegistry;
126
125
  //#endregion
127
- //#region src/chat/providers.d.ts
128
- /**
129
- * Structural model metadata — compatible with pi-ai's `Model` interface but
130
- * not coupled to it, so hosts can pass either pi-ai-shaped objects or a
131
- * custom registry of their own.
132
- *
133
- * Deliberately a structural duplicate of pi-ai's `Model` rather than a
134
- * re-export: keeps the public API stable when pi-ai bumps shape, and lets
135
- * hosts implement their own registry without depending on pi-ai's types.
136
- *
137
- * Lives here (rather than `./config`) because `ProviderDescriptor.models`
138
- * needs it — pushing it to `config.tsx` created an import cycle.
139
- */
140
- interface ModelInfo {
141
- id: string;
142
- name?: string;
143
- contextWindow: number;
144
- maxTokens?: number;
145
- reasoning?: boolean;
146
- input?: readonly ('text' | 'image')[];
147
- cost?: {
148
- input: number;
149
- output: number;
150
- cacheRead?: number;
151
- cacheWrite?: number;
152
- };
153
- provider?: string;
154
- }
155
- interface ProviderDescriptor {
156
- /**
157
- * Unique identifier. Used as the registry key, persisted in `state.json`
158
- * as the resumed provider, and (by default) as the credential-file key.
159
- */
160
- key: string;
161
- /** Display name shown in the TUI's provider picker and labels. */
162
- label: string;
163
- /**
164
- * Factory that builds a fresh `Provider` instance. Called on every session
165
- * activation. Some factories (e.g. zidane's built-in `anthropic`) eagerly
166
- * resolve credentials at construction time and throw when none are
167
- * configured — set {@link defaultModel} on the descriptor to avoid the TUI
168
- * calling the factory before the user has picked + authed a provider.
169
- */
170
- factory: () => Provider;
171
- /**
172
- * Default model id to seed the picker with. When omitted, the TUI falls
173
- * back to `descriptor.factory().meta.defaultModel`, which constructs the
174
- * provider — fine for lazy-credential factories, but breaks for factories
175
- * that throw on missing credentials before the wizard runs. Setting this
176
- * eagerly lets the TUI render the auth wizard without ever instantiating
177
- * the provider.
178
- */
179
- defaultModel?: string;
180
- /**
181
- * Env var checked when detecting whether the user has an API key
182
- * configured for this provider. Optional — set to `undefined` when the
183
- * provider only supports OAuth (or only credentials via a custom path).
184
- */
185
- envKey?: string;
186
- /**
187
- * Key under which credentials live in `credentials.json`. Defaults to
188
- * `key`. The only built-in that overrides this is OpenAI Codex
189
- * (`openai` → `openai-codex`) to stay compatible with the harness
190
- * provider's existing lookup.
191
- */
192
- credentialFileKey?: string;
193
- /** Placeholder shown in the wizard's API-key input. */
194
- apiKeyPlaceholder?: string;
195
- /**
196
- * pi-ai (or compat) OAuth provider. When present, the wizard offers an
197
- * OAuth option in addition to API key.
198
- */
199
- oauthProvider?: OAuthProviderInterface;
200
- /**
201
- * Optional copy appended to the wizard's "OAuth" method description.
202
- * Use to communicate why a user might pick OAuth (e.g. subscription tier,
203
- * org-wide SSO). Shown after `browser-based sign-in`. Skip the leading
204
- * space — the wizard adds it. Example: `'Claude Pro/Max subscription'`.
205
- */
206
- oauthHint?: string;
207
- /**
208
- * pi-ai provider id used to look up models in pi-ai's built-in registry.
209
- * Defaults to `key`. Only Codex differs (`openai` → `openai-codex`).
210
- */
211
- piProviderId?: string;
212
- /**
213
- * Override the model list returned for this provider's picker. When set,
214
- * skips pi-ai's registry entirely. Useful for hosts maintaining their
215
- * own model catalogue or for custom providers pi-ai doesn't know about.
216
- */
217
- models?: readonly ModelInfo[];
218
- }
219
- /** Convenience accessor — returns `credentialFileKey ?? key`. */
220
- declare function credKeyOf(desc: ProviderDescriptor): string;
221
- /** Convenience accessor — returns `piProviderId ?? key`. */
222
- declare function piIdOf(desc: ProviderDescriptor): string;
223
- declare const anthropicDescriptor: ProviderDescriptor;
224
- declare const openaiDescriptor: ProviderDescriptor;
225
- declare const openrouterDescriptor: ProviderDescriptor;
226
- declare const cerebrasDescriptor: ProviderDescriptor;
227
- /**
228
- * Default provider registry. Passed verbatim when `runTui` is invoked without
229
- * an explicit `providers` option. Hosts that want to override per-provider
230
- * metadata can spread this and replace specific entries:
231
- *
232
- * ```ts
233
- * runTui({ providers: { ...BUILTIN_PROVIDERS, anthropic: myOwnAnthropicDescriptor } })
234
- * ```
235
- */
236
- declare const BUILTIN_PROVIDERS: Readonly<Record<string, ProviderDescriptor>>;
237
- /**
238
- * Resolve the model list for a given provider. Honors `descriptor.models`
239
- * when set; otherwise queries pi-ai via `descriptor.piProviderId`. Returns
240
- * `[]` for descriptors with no known mapping (custom providers without a
241
- * model list) — callers should hide the model picker in that case.
242
- */
243
- declare function modelsForDescriptor(descriptor: ProviderDescriptor): readonly ModelInfo[];
244
- /**
245
- * Resolve a single model's metadata via the descriptor's model source.
246
- * Mirrors {@link modelsForDescriptor} routing: descriptor's own list wins,
247
- * pi-ai's registry is the fallback. Returns `null` when the model isn't
248
- * known.
249
- */
250
- declare function getModelInfo(descriptor: ProviderDescriptor, modelId: string): ModelInfo | null;
251
- /**
252
- * Look up the model's max context window via the descriptor's model source.
253
- * Returns `null` when the model isn't known (custom slugs, providers without
254
- * a registry); callers should hide the context indicator in that case.
255
- */
256
- declare function getContextWindow(descriptor: ProviderDescriptor, modelId: string): number | null;
257
- /**
258
- * Reserved output budget subtracted from the raw context window when
259
- * computing the effective ceiling for compaction / warning thresholds.
260
- *
261
- * Aligned with Claude Code's `COMPACT_MAX_OUTPUT_TOKENS = 20_000`
262
- * (`utils/context.ts:12`) — covers p99.99 of summary + response output.
263
- * A turn that consumed N input tokens leaves `effectiveWindow - N`
264
- * headroom for the next prompt's response; once headroom shrinks
265
- * below the threshold, auto-compaction fires.
266
- */
267
- declare const OUTPUT_RESERVE_TOKENS = 20000;
268
- /**
269
- * Effective context window — what the next user turn can actually pack
270
- * before the provider reserves space for the assistant's reply. Equals
271
- * `rawWindow - OUTPUT_RESERVE_TOKENS`, clamped to `>= 1` so a tiny
272
- * (or absurd) window doesn't yield zero / negative thresholds.
273
- *
274
- * Used by both the footer's context indicator and the auto-compact
275
- * trigger so the two surfaces agree on "how full are we, really".
276
- * Pass `null` through unchanged so callers can pipe `getContextWindow`
277
- * directly without an intermediate check.
278
- */
279
- declare function effectiveContextWindow(rawWindow: number | null): number | null;
280
- /**
281
- * Whether the given model exposes a reasoning / extended-thinking knob.
282
- * Drives the TUI's effort picker visibility — the `ctrl+n` shortcut and
283
- * the bottom-bar `effortName` segment only surface when this is `true`.
284
- * Returns `false` for unknown models (no registry entry → no advertised
285
- * capability).
286
- */
287
- declare function modelSupportsReasoning(descriptor: ProviderDescriptor, modelId: string): boolean;
288
- //#endregion
289
- //#region src/chat/auth.d.ts
290
- /**
291
- * Provider identifier as known to the TUI. Built-in keys are `anthropic`,
292
- * `openai`, `openrouter`, `cerebras`, but hosts can register additional
293
- * keys via {@link ProviderDescriptor} — so the type is open.
294
- */
295
- type ProviderKey = string;
296
- interface AuthMethod {
297
- source: 'env' | 'oauth' | 'apikey';
298
- /** Human-readable detail (env var name, expiry timestamp, …). */
299
- detail: string;
300
- }
301
- interface ProviderAuth {
302
- key: ProviderKey;
303
- label: string;
304
- /** True when at least one credential source is present. */
305
- available: boolean;
306
- methods: AuthMethod[];
307
- }
308
- /**
309
- * Detect available auth for every registered provider.
310
- *
311
- * Resolution order per provider (a method appears in `methods` for each
312
- * layer that has a credential — the agent itself resolves them in the same
313
- * order via its provider factories):
314
- *
315
- * 1. `kind: 'apikey'` from `credentials.json` (injected into env at TUI launch)
316
- * 2. explicit env var (descriptor's `envKey`)
317
- * 3. `kind: 'oauth'` from `credentials.json` (or legacy `cwd/.credentials.json`)
318
- *
319
- * Pure read — never refreshes or rewrites the credentials file.
320
- */
321
- declare function detectAuth(dataDir: string, registry: Readonly<Record<string, ProviderDescriptor>>, env?: Record<string, string | undefined>): ProviderAuth[];
322
- //#endregion
323
126
  //#region src/chat/hints.d.ts
324
127
  /**
325
128
  * Single hint entry — `<key> <label>`, optionally followed by an inline
@@ -392,158 +195,6 @@ declare const EMPTY_HINTS: readonly Hint[];
392
195
  declare function clipHintsToWidth(hints: readonly Hint[], budget: number): readonly Hint[];
393
196
  //#endregion
394
197
  //#region src/chat/completion.d.ts
395
- /**
396
- * Prompt autocompletion framework.
397
- *
398
- * Renderer-agnostic. Providers plug in by registering a `trigger` character
399
- * (e.g. `/` for skills, `@` for files) and exposing two operations:
400
- *
401
- * 1. `suggest(query)` — return ranked items for the live query.
402
- * 2. `parseReferences(text)` — find all references to the provider's
403
- * items in arbitrary text. Used to highlight in-prompt mentions and
404
- * drive submit-time side effects (activate the skill, attach the
405
- * file, …).
406
- *
407
- * The TUI consumes `useCompletion()` to drive a popover above the textarea.
408
- * A future GUI consumes the same hook to drive a dropdown. The popup
409
- * component itself only reads `label` + `description` on each item, so
410
- * provider-specific typing (`TItem`) stays at the registration boundary
411
- * and never leaks into the renderer.
412
- */
413
- /**
414
- * A discoverable, selectable thing — one row in the autocomplete popover.
415
- * `TItem` is provider-specific; consumers can inspect `data` when they
416
- * need the originating payload (e.g. the full `SkillConfig` for tooltips).
417
- */
418
- interface CompletionItem<TItem = unknown> {
419
- /** Stable identifier within the provider. Used as React key + selection equality. */
420
- id: string;
421
- /** User-visible primary string ("research"). */
422
- label: string;
423
- /** Optional one-line secondary string ("In-depth research with citations"). */
424
- description?: string;
425
- /**
426
- * Text that replaces the active span (trigger + query) on commit. Usually
427
- * `${trigger}${label}` with a trailing space so the cursor lands ready
428
- * for the next token.
429
- */
430
- insertText: string;
431
- /** Original provider-specific payload. */
432
- data: TItem;
433
- }
434
- /**
435
- * A reference to a provider item inside arbitrary prompt text. Producers:
436
- * `provider.parseReferences(text)`. Consumers: the TUI for highlighting,
437
- * the run flow for "activate every referenced skill before agent.run()".
438
- *
439
- * Spans are half-open `[start, end)` codepoint offsets into the source
440
- * string. Overlapping spans from the same or different providers are
441
- * caller-resolved — the helpers below ship a "first wins" merger.
442
- */
443
- interface CompletionReference<TItem = unknown> {
444
- providerId: string;
445
- start: number;
446
- end: number;
447
- itemId: string;
448
- data: TItem;
449
- }
450
- /**
451
- * Provider contract. Implementations decide their own ranking, fuzzy-match
452
- * rules, async loading behavior, and reference grammar.
453
- */
454
- interface CompletionProvider<TItem = unknown> {
455
- /** Stable id used for tagging references + React keys. */
456
- id: string;
457
- /**
458
- * Single character that activates this provider. The engine considers a
459
- * trigger "active" when it appears at the start of the buffer or
460
- * immediately after whitespace, and is not closed by whitespace before
461
- * the cursor (so a trigger plus query is a contiguous token).
462
- */
463
- trigger: string;
464
- /** Human-readable name. Reserved for future multi-provider popover headers. */
465
- label: string;
466
- /**
467
- * Returns items for the active `query` (the text between the trigger and
468
- * the cursor, excluding the trigger itself). Synchronous return is the
469
- * common case; promises let providers paginate or hit a backend.
470
- *
471
- * `signal` is aborted when the query changes or the popover closes —
472
- * use it to cancel in-flight network calls.
473
- */
474
- suggest: (query: string, ctx: CompletionContext, signal: AbortSignal) => CompletionItem<TItem>[] | Promise<CompletionItem<TItem>[]>;
475
- /**
476
- * Find every reference to this provider's items in `text`. Pure: must not
477
- * mutate ctx. The TUI calls this on every keystroke for highlighting, so
478
- * keep it cheap (linear scan, no I/O).
479
- */
480
- parseReferences: (text: string, ctx: CompletionContext) => CompletionReference<TItem>[];
481
- }
482
- /**
483
- * Read-only view of the active prompt buffer + cursor passed to provider
484
- * callbacks. Kept minimal so providers stay portable across renderers.
485
- */
486
- interface CompletionContext {
487
- /** Full prompt text. */
488
- text: string;
489
- /** Codepoint offset of the cursor (0-based). */
490
- cursor: number;
491
- }
492
- /**
493
- * Identified active trigger span. Returned by `findActiveTrigger` so
494
- * callers can show the popover, query the provider, and on commit replace
495
- * the span with the selected item's `insertText`.
496
- */
497
- interface ActiveTrigger<TItem = unknown> {
498
- provider: CompletionProvider<TItem>;
499
- /** Substring after the trigger, up to the cursor. Empty if cursor sits right after the trigger. */
500
- query: string;
501
- /** `[start, end)` — span covered by the trigger + query in the source. */
502
- span: {
503
- start: number;
504
- end: number;
505
- };
506
- }
507
- /**
508
- * Resolve the provider trigger active at `cursor`, or `null` when none fits.
509
- *
510
- * Rules:
511
- * - The trigger character must sit at position 0 of the buffer OR be
512
- * preceded by whitespace. This prevents `http://` from triggering the
513
- * `/`-bound skills provider mid-URL.
514
- * - The cursor must be at or past the trigger position.
515
- * - Nothing between the trigger and the cursor may be whitespace (the
516
- * query is one contiguous token).
517
- * - The query length is bounded — `maxQueryLength` defaults to 64 — so
518
- * a runaway buffer scan can't pin the renderer.
519
- */
520
- declare function findActiveTrigger<TItem>(text: string, cursor: number, providers: readonly CompletionProvider<TItem>[], options?: {
521
- maxQueryLength?: number;
522
- }): ActiveTrigger<TItem> | null;
523
- /**
524
- * Replace `[span.start, span.end)` in `text` with `insertText`. Returns the
525
- * mutated text and the new cursor position (end of insertion).
526
- */
527
- declare function applyInsert(text: string, span: {
528
- start: number;
529
- end: number;
530
- }, insertText: string): {
531
- text: string;
532
- cursor: number;
533
- };
534
- /**
535
- * Merge reference lists from multiple providers into one ordered list with
536
- * earlier-start-wins disambiguation when spans overlap. Ties broken by
537
- * insertion order. Spans are sorted ascending so renderers can walk them
538
- * sequentially with a cursor through the source string.
539
- */
540
- declare function mergeReferences<TItem>(refs: readonly CompletionReference<TItem>[]): CompletionReference<TItem>[];
541
- /**
542
- * Collect every provider's references in one pass. Convenience wrapper —
543
- * the TUI textarea component calls this on every keystroke to highlight
544
- * in-prompt mentions.
545
- */
546
- declare function collectReferences<TItem>(text: string, providers: readonly CompletionProvider<TItem>[], cursor?: number): CompletionReference<TItem>[];
547
198
  /** State surface returned by `useCompletion()`. */
548
199
  interface CompletionState<TItem = unknown> {
549
200
  /** Active trigger, or null when the cursor doesn't sit in a completable span. */
@@ -624,7 +275,7 @@ declare function useCompletion<TItem = unknown>(input: {
624
275
  * here forces every consumer (TUI keyboard handler, hint rows, settings
625
276
  * UI) to handle it, and ships a default that the user can override.
626
277
  */
627
- type KeyAction = 'openSettings' | 'openSessionDetails' | 'openModelPicker' | 'openEffortPicker' | 'openTodos' | 'openKeybindings' | 'cycleAgent' | 'enterSelectTurnMode' | 'cancelToolCall' | 'changeCwd' | 'enterQueueSelection' | 'pushQueuedMessage' | 'dropQueuedMessage' | 'turnFork' | 'turnDelete' | 'turnCopy' | 'turnEdit' | 'sessionDelete' | 'sessionCopyId' | 'sessionGenerateTitle' | 'sessionExportMarkdown' | 'sessionExportJson' | 'sessionCompact';
278
+ type KeyAction = 'openSettings' | 'openSessionDetails' | 'openModelPicker' | 'openEffortPicker' | 'openTodos' | 'openContextPanel' | 'openKeybindings' | 'cycleAgent' | 'enterSelectTurnMode' | 'cancelToolCall' | 'changeCwd' | 'enterQueueSelection' | 'pushQueuedMessage' | 'dropQueuedMessage' | 'turnFork' | 'turnDelete' | 'turnCopy' | 'turnEdit' | 'sessionDelete' | 'sessionCopyId' | 'sessionGenerateTitle' | 'sessionExportMarkdown' | 'sessionExportJson' | 'sessionCompact';
628
279
  /** Resolved keybindings — every action has a current spec string. */
629
280
  type KeyBindings = Record<KeyAction, string>;
630
281
  /**
@@ -785,662 +436,6 @@ declare function ensureKeybindingsFile(userDir: string): string;
785
436
  */
786
437
  declare function stripJsonComments(input: string): string;
787
438
  //#endregion
788
- //#region src/chat/types.d.ts
789
- type Screen = 'auth' | 'sessions' | 'chat';
790
- /** Identifies the agent that produced a streaming event. */
791
- type Owner = 'parent' | string;
792
- interface StreamEvent {
793
- kind: 'thinking' | 'tool' | 'tool-result' | 'error'
794
- /**
795
- * Echo of a submitted user prompt — the `❯` chevron block in the
796
- * transcript. Distinct from `'info'` (generic informational text)
797
- * so consumers can count user messages and rebuild prompt history
798
- * without filtering by text-prefix regex.
799
- *
800
- * `text` is the **raw** prompt without the `❯ ` prefix; renderers
801
- * prepend the chevron. `refs` offsets are aligned to this raw text.
802
- */
803
- | 'user-prompt'
804
- /**
805
- * Generic informational banner — status notice, transient message.
806
- * Reserved for non-user content; user prompts use `'user-prompt'`.
807
- */
808
- | 'info' | 'separator' | 'markdown' | 'spawn-start' | 'spawn-end'
809
- /**
810
- * Compaction boundary — produced by `eventsFromTurns` when a turn
811
- * carries a `compact-summary` block. Marks the point at which the
812
- * model's view of history was replaced by an LLM-generated summary.
813
- * `text` is the summary body; `compact` carries the extra metadata
814
- * needed for the visual card (replaced-turn count, model, usage).
815
- *
816
- * The renderer is free to style this as a collapsed card; the user
817
- * can still scroll above the marker to see the original turns —
818
- * compaction never deletes from disk.
819
- */
820
- | 'compact-summary'
821
- /**
822
- * Background task lifecycle banner. Produced when a task started via
823
- * `shell({ run_in_background: true })` terminates — natural exit, kill,
824
- * or `agent.destroy()` teardown. The framework injects a
825
- * `<task-notification>` text block into the next user-turn so the model
826
- * sees it inline with its prompt; the renderer suppresses the raw text
827
- * block in favor of this structured event for a cleaner transcript.
828
- *
829
- * `text` is a short human-readable summary (e.g. `npm run build (4.2s)
830
- * — exited 0`); `task` carries the structured fields the banner reads.
831
- * On replay (`eventsFromTurns`), the event is re-synthesized from the
832
- * persisted `<task-notification>` XML inside the user turn's text block;
833
- * the underlying text block is dropped from the rendered stream so the
834
- * banner doesn't double-paint alongside it.
835
- */
836
- | 'task-notification';
837
- text: string;
838
- /**
839
- * Background task metadata — only set on `task-notification` events.
840
- * Mirrors the `<task-notification>` XML's fields. Renderer reads this
841
- * (not `text`) for the structured banner so swapping languages /
842
- * formats stays a renderer-level concern.
843
- */
844
- task?: {
845
- taskId: string; /** `'exited'` (clean or non-zero) or `'killed'` (we issued SIGTERM). */
846
- status: 'exited' | 'killed';
847
- exitCode: number; /** Absolute path to the log file — banner renders an OSC 8 hyperlink to it. */
848
- outputPath: string; /** Original command, truncated for display by the renderer if long. */
849
- command: string; /** Wall-clock spawn → exit duration. */
850
- durationMs: number;
851
- };
852
- /**
853
- * Compaction metadata — only set on `compact-summary` events. Mirrors
854
- * the underlying `SessionContentBlock` shape but flattened to numbers
855
- * so the renderer doesn't need to import the agent's TurnUsage type.
856
- */
857
- compact?: {
858
- /** Number of turns the summary replaces (renderer shows "N turns compacted"). */replacedCount: number; /** Model used for the summary call. */
859
- model: string; /** Unix-ms when compaction completed. */
860
- compactedAt: number; /** Token usage from the summary call. Renderer formats for display. */
861
- inputTokens: number;
862
- outputTokens: number;
863
- cacheReadTokens: number;
864
- cacheCreationTokens: number;
865
- };
866
- /**
867
- * For `markdown` events: true while the block is still receiving deltas.
868
- * Renderers keep their markdown parser in streaming mode while this is
869
- * true (OpenTUI's `<markdown streaming>` leaves the trailing block
870
- * unstable to absorb tokens as they arrive). Flipped to false on
871
- * `turn:after`.
872
- */
873
- streaming?: boolean;
874
- /** Subagent that produced this event. Absent / 'parent' = top-level agent. */
875
- childId?: string;
876
- /** Nesting depth — 0 = parent, ≥ 1 = subagent (matches zidane's spawn depth). */
877
- depth?: number;
878
- /**
879
- * Canonical tool name for `tool` / `tool-result` events. Lets the renderer
880
- * filter by tool — e.g. hide the parent's `spawn` tool-result when
881
- * `hideSubagentOutput` is on, since the spawn-end marker already shows the
882
- * same stats. Absent for non-tool events.
883
- */
884
- tool?: string;
885
- /**
886
- * Matches `tool_use.id` on the assistant turn's `tool_call` block. Lets
887
- * out-of-process consumers (GUI, SDK, logger, replayer) pair `tool` ↔
888
- * `tool-result` events by id instead of falling back to fragile positional
889
- * heuristics within a tool-name bucket — the latter breaks visibly the
890
- * moment two parallel calls share a tool name (common for `read_file`,
891
- * `edit`, `multi_edit`).
892
- *
893
- * Always set when `kind` is `tool` / `tool-result` / `error` for a real
894
- * tool call; absent for non-tool events (`markdown`, `thinking`,
895
- * `user-prompt`, `separator`, `info`, `spawn-start`, `spawn-end`,
896
- * `compact-summary`) and for `error` events that don't have a callId
897
- * in scope (provider / session-level failures).
898
- */
899
- callId?: string;
900
- /**
901
- * Raw tool input arguments — only set on `tool` events. Carried so the
902
- * renderer can run per-tool formatters (e.g. `↳ Read src/foo.ts L10-25`)
903
- * without parsing JSON back out of `text`. Plain object, same shape the
904
- * model emitted; renderers must treat unexpected fields as optional.
905
- */
906
- input?: Record<string, unknown>;
907
- /**
908
- * Structured payload for `edit` / `multi_edit` / `write_file` tool calls,
909
- * extracted from the model's `input` and (for `write_file`) paired with
910
- * a pre-write snapshot read at hook time. Drives the `EditDiffBlock`
911
- * renderer when {@link Settings.showEditDiffs} is on; absent means
912
- * "render as a plain `↳ name(args)` line" (the unstructured fallback).
913
- */
914
- edit?: EditPayload;
915
- /**
916
- * Highlighted spans within `text`, in source order. Used by the renderer
917
- * to colorize completion references in submitted prompts (`user-prompt`
918
- * events). Provider-agnostic — the renderer only reads `start`, `end`,
919
- * `providerId`. Spans are half-open `[start, end)`; overlapping spans
920
- * are caller-resolved before reaching here. Field name matches
921
- * `CompletionReference.providerId` and `PromptSegment.providerId` so
922
- * the same identifier flows end-to-end.
923
- */
924
- refs?: readonly {
925
- start: number;
926
- end: number;
927
- providerId: string;
928
- }[];
929
- /**
930
- * Attachment metadata for `user-prompt` events — name, media-type, and
931
- * byte size of each file the user attached (image drag, multiline paste,
932
- * etc.). The full content travels in the `PromptPart[]` sent to the
933
- * model; only lightweight metadata is echoed to the transcript.
934
- */
935
- attachments?: readonly {
936
- name: string;
937
- mediaType: string;
938
- size: number;
939
- }[];
940
- /**
941
- * `SessionTurn.id` the event was emitted by — set both on historical
942
- * events synthesized in `eventsFromTurns` and on live events tagged by
943
- * the agent hooks (via `StreamHookContext.turnId` / `ToolHookContext.turnId`).
944
- * Drives the TUI's "select turn" mode: each turn is addressable as a
945
- * highlightable group of events.
946
- *
947
- * Absent on synthetic events that don't map to a turn (`spawn-start`,
948
- * `spawn-end`, `separator`, etc.) and on events emitted before the
949
- * first `turn:before` fires on a freshly-mounted session.
950
- */
951
- turnId?: string;
952
- }
953
- /**
954
- * Structured edit data attached to a `tool` event for `edit` /
955
- * `multi_edit` / `write_file`. Lets the renderer compute a unified diff
956
- * without re-parsing the JSON input string.
957
- *
958
- * - `edit` produces one hunk with `replaceAll` defaulting to false.
959
- * - `multi_edit` produces one hunk per `edits[]` step (in order).
960
- * - `write_file` produces a single hunk where `oldString` is the
961
- * pre-write file content (empty for a fresh create) and `newString`
962
- * is the new content; `replaceAll` is meaningless here and absent.
963
- *
964
- * Live capture happens in the TUI's `tool:before` hook (where the
965
- * pre-write snapshot can be read off disk before the tool runs).
966
- * Historical replay from persisted turns can only reconstruct the
967
- * edit/multi_edit shape — write_file historical events have no
968
- * pre-write content and render with `oldString: ''` (= every line is
969
- * an addition), matching git's "new file" diff convention.
970
- */
971
- interface EditPayload {
972
- /** Tool name that produced this payload — drives the header glyph + result-suppression matrix. */
973
- tool: 'edit' | 'multi_edit' | 'write_file';
974
- /** Workspace-relative file path. Used as the diff header. */
975
- path: string;
976
- /** Ordered list of `(old, new)` pairs. Each rendered as one hunk. */
977
- hunks: readonly EditHunk[];
978
- /**
979
- * Per-hunk outcome of the approval / application pipeline, 1:1 with
980
- * {@link hunks}. Absent on a fresh tool call before the gate decides —
981
- * the renderer treats absence as "all applied" (the legacy code path
982
- * predates partial application).
983
- *
984
- * Surfaces in the transcript so a partially-approved `multi_edit` shows
985
- * the denied hunks alongside the applied ones, dimmed / badged. Live
986
- * approval populates this from the modal's per-edit decisions; replay
987
- * reconstructs it from the tool_result body (which the tool serializes
988
- * in a stable line shape — see `multi_edit`).
989
- */
990
- outcomes?: readonly EditOutcome[];
991
- /**
992
- * Pre-write file content snapshot, captured by the TUI's `tool:before`
993
- * hook for all three edit tools. Lets the diff renderer build a
994
- * contextual unified diff with real file line numbers (matching what
995
- * the user's editor shows) instead of synthetic `@@ -1,N +1,M @@`
996
- * headers anchored at line 1 within each hunk's snippet.
997
- *
998
- * Absent on historical replay (the field isn't persisted — payloads
999
- * are reconstructed from `input` alone in `eventsFromTurns`). The
1000
- * renderer falls back to `buildUnifiedDiff` in that case.
1001
- *
1002
- * NOT serialized into session turns; lives only on the live in-memory
1003
- * `StreamEvent` to avoid bloating session files with snapshots of
1004
- * every edited file.
1005
- */
1006
- priorContent?: string;
1007
- }
1008
- interface EditHunk {
1009
- oldString: string;
1010
- newString: string;
1011
- /** Mirrored from the tool's `replace_all` flag — surfaced as `× N` in the hunk header. */
1012
- replaceAll?: boolean;
1013
- }
1014
- /**
1015
- * Per-hunk lifecycle state surfaced in the diff/apply viewer. Mirrors the
1016
- * states a `multi_edit` step can be in across the approve → apply pipeline:
1017
- *
1018
- * - `applied` — the gate let it through and the tool wrote it.
1019
- * - `denied` — the user (or an auto-deny rule) refused this specific edit.
1020
- * - `skipped` — the user explicitly stepped past this edit in the modal,
1021
- * or an earlier edit failed and the batch unwound.
1022
- * - `failed` — the gate let it through but the tool body rejected the
1023
- * edit (`old_string` not found, ambiguous, etc.).
1024
- * - `pending` — placeholder used while the modal is open. Never persisted.
1025
- */
1026
- type EditOutcomeKind = 'applied' | 'denied' | 'skipped' | 'failed' | 'pending';
1027
- interface EditOutcome {
1028
- kind: EditOutcomeKind;
1029
- /** Short human-readable explanation surfaced in the transcript badge. */
1030
- reason?: string;
1031
- }
1032
- interface Picked {
1033
- provider: ProviderAuth;
1034
- model: string;
1035
- /**
1036
- * Reasoning effort the user selected for `model`. Only meaningful when
1037
- * the active model exposes reasoning (`ModelInfo.reasoning === true`);
1038
- * `undefined` otherwise. Forwarded to `agent.run` as `thinking` so
1039
- * providers route it to their per-model reasoning control.
1040
- */
1041
- effort?: ThinkingLevel;
1042
- }
1043
- interface SessionMeta {
1044
- id: string;
1045
- title: string;
1046
- /** Total turns (user + assistant + system). */
1047
- turnCount: number;
1048
- /** Count of `role: 'user'` turns — the volume of human messages. */
1049
- userMessageCount: number;
1050
- /** Top-level runs recorded against the session (one per `agent.run()` call). */
1051
- runCount: number;
1052
- /**
1053
- * Project this session was created under (see {@link SessionData.projectRoot}).
1054
- * Surfaced on the meta row so the sessions screen can show a
1055
- * per-project label when `Settings.showAllProjects` is on. Absent
1056
- * for legacy pre-tagging sessions.
1057
- */
1058
- projectRoot?: string;
1059
- updatedAt: number;
1060
- }
1061
- /**
1062
- * How `tool` events render in the transcript. Drives `Settings.toolCallDisplay`.
1063
- *
1064
- * - `'hidden'` — `tool` events filtered out entirely (the matching
1065
- * `tool-result` block still shows unless its own toggle suppresses
1066
- * it). Use when the transcript should read like a chat log.
1067
- * - `'formatted'` (default) — each tool renders a clean per-tool
1068
- * summary line (e.g. `↳ Read src/foo.ts`, `↳ Shell git status`).
1069
- * Native tools have curated formatters; unknown / MCP tools fall
1070
- * back to a compact `↳ <name>` line.
1071
- * - `'full'` — debug view: `↳ <name>` header plus the entire raw
1072
- * `input` rendered as syntax-highlighted JSON. Useful for
1073
- * inspecting what the model actually sent.
1074
- */
1075
- type ToolCallDisplay = 'hidden' | 'formatted' | 'full';
1076
- /**
1077
- * How `edit` / `multi_edit` / `write_file` diffs render in the transcript.
1078
- * Gated by {@link Settings.showEditDiffs}; when that's off, the raw `↳ name(args)`
1079
- * line is used regardless of this setting.
1080
- *
1081
- * - `'full'` — current behavior: the entire unified diff body, with
1082
- * line numbers in the gutter. Uses real file line numbers when the
1083
- * pre-write snapshot is available (live calls), synthetic when not
1084
- * (historical replay).
1085
- * - `'compact'` — header line + one short summary line per hunk
1086
- * (`L42 · +2 −1 · old → new`). The full diff body is dropped from
1087
- * the transcript; users open the approval modal or scroll the file
1088
- * to see the changes in detail.
1089
- */
1090
- type EditDiffDisplay = 'compact' | 'full';
1091
- /**
1092
- * Chat-screen chrome density. Drives a small, opinionated set of UI
1093
- * collapses without touching the runtime feature surface:
1094
- *
1095
- * - `'full'` (default) — every shortcut the chat screen advertises is
1096
- * visible: bottom-bar hints (agent / model / skills / session /
1097
- * settings / sessions / update), the prompt-overlay shortcuts
1098
- * (`↵ send`, `shift+↵ newline`, `↑↓ history`, `ctrl+s messages`) +
1099
- * the `@ files` / `/ skills` triggers, and the `ctrl+x session`
1100
- * chip on the title meta.
1101
- * - `'minimal'` — strip the chat session UI to just the controls a
1102
- * user actually keeps hands on:
1103
- * Bottom bar (idle): `agent`, `model/effort`, `keybindings`.
1104
- * Sessions / settings / session-details / update chip are
1105
- * dropped; the full catalog stays one keystroke away via the
1106
- * keybindings panel (`ctrl+y`).
1107
- * Prompt-overlay hints (idle): only the `@ files` / `/ skills`
1108
- * triggers — the resting send/newline/history line is dropped.
1109
- * Title meta: drop the `ctrl+x session` chip. Cwd + message /
1110
- * turn stats stay.
1111
- *
1112
- * Busy / pending / select-turn / queue / approval states keep their
1113
- * full hint sets in both modes — those affordances are load-bearing
1114
- * (abort, navigate, approve) and not the noise the minimal mode is
1115
- * targeting.
1116
- */
1117
- type UiMode = 'full' | 'minimal';
1118
- /** Persisted, user-toggleable transcript filters and modes. */
1119
- interface Settings {
1120
- showThinking: boolean;
1121
- /**
1122
- * Rendering mode for `tool` events. See {@link ToolCallDisplay}.
1123
- * Replaces the legacy `showToolCalls: boolean` (TUI auto-migrates
1124
- * old `state.json` files on first launch).
1125
- */
1126
- toolCallDisplay: ToolCallDisplay;
1127
- showToolResults: boolean;
1128
- /**
1129
- * Safe mode — when enabled, every tool call requires explicit user
1130
- * approval unless it's covered by the project safelist (`projects.json`)
1131
- * or the implicit read-only allow-list. Default: on.
1132
- */
1133
- safeMode: boolean;
1134
- /**
1135
- * Hide a subagent's internal events (its streamed markdown, thinking,
1136
- * tool calls, and tool results) from the transcript. The `🌱` start and
1137
- * `✓` end markers stay visible so the user still sees that a subagent
1138
- * is working and when it finished. Default: on — subagent runs are
1139
- * usually noisy and the parent's final response already summarizes them.
1140
- *
1141
- * When off, those events are visible and wrapped in a dim bordered box
1142
- * for clear visual hierarchy.
1143
- */
1144
- hideSubagentOutput: boolean;
1145
- /**
1146
- * Active theme id — looked up in `BUILTIN_THEMES` to resolve the palette,
1147
- * select styling, syntax highlight tokens, etc. Default: `'default'`.
1148
- * Unknown ids fall back to `DEFAULT_THEME` rather than throwing.
1149
- */
1150
- theme: string;
1151
- /**
1152
- * Show sessions from every project (and pre-tagging legacy ones)
1153
- * in the sessions list, instead of filtering to the current
1154
- * project. Off by default — each project shows only its own
1155
- * conversations. Flip on to inspect / jump across projects without
1156
- * leaving the TUI. Per-row project labels appear when on.
1157
- */
1158
- showAllProjects: boolean;
1159
- /**
1160
- * Auto-resume the previously-active session on launch. Default: on.
1161
- * When off, the TUI always lands on the sessions list (or a fresh
1162
- * session if the list is empty), regardless of what `state.json`
1163
- * remembers as the last session id.
1164
- *
1165
- * The setting is read once on launch — toggling it mid-session
1166
- * affects the NEXT start, not the current one. `state.lastSessionId`
1167
- * is still tracked underneath so flipping the setting back on
1168
- * restores the resume behavior without losing the pointer.
1169
- */
1170
- resumeLastSession: boolean;
1171
- /**
1172
- * Persist large `tool_result` outputs to disk and substitute a
1173
- * `<persisted-output>` stub (preview + filesystem path) inline. Built-in
1174
- * profiles default to 8 KiB threshold via `behavior.persistThreshold`;
1175
- * this setting is the user-facing kill-switch. When off, the TUI
1176
- * overrides `behavior.persistThreshold = 0` at agent build time so the
1177
- * loop's persistence branch never fires.
1178
- *
1179
- * The setting takes effect on the next session activation — toggling
1180
- * mid-stream doesn't tear down an in-flight tool call. Persisted blobs
1181
- * already on disk stay readable via `read_file`; only future tool
1182
- * results are affected by the flip.
1183
- *
1184
- * Default: on.
1185
- */
1186
- persistToolResults: boolean;
1187
- /**
1188
- * Fire {@link compactConversation} automatically when the latest turn's
1189
- * input-token usage crosses {@link Settings.autoCompactThreshold} of the
1190
- * model's effective context window (raw window minus a fixed output
1191
- * reserve — see `OUTPUT_RESERVE_TOKENS` in `chat/providers.ts`).
1192
- *
1193
- * When the trigger fires, the TUI:
1194
- * - Appends an `info` event to the transcript announcing the compaction.
1195
- * - Runs `compactConversation` in the background — the prompt area stays
1196
- * visible so the user can compose the next message while it runs.
1197
- * - The next prompt submission `await`s the in-flight compaction before
1198
- * calling `agent.run()`, so the new run sees the post-compaction
1199
- * message history (no race with the summary's `appendTurns`).
1200
- * - Does NOT auto-continue the conversation after compaction completes
1201
- * — the user controls when the next turn fires.
1202
- *
1203
- * Default: on.
1204
- */
1205
- autoCompact: boolean;
1206
- /**
1207
- * Threshold for {@link Settings.autoCompact}, expressed as a fraction of
1208
- * the effective context window. `0.8` means "fire when the latest turn
1209
- * used 80% of the effective window". Values outside `(0, 1)` are
1210
- * treated as misconfiguration and skip the trigger.
1211
- *
1212
- * The settings modal cycles through `0.6 / 0.7 / 0.8 / 0.9` — coarse
1213
- * enough that users don't get lost, fine enough to tune for verbose
1214
- * workflows (lower) versus context-heavy ones (higher).
1215
- *
1216
- * Default: `0.8`.
1217
- */
1218
- autoCompactThreshold: number;
1219
- /**
1220
- * Render `edit` / `multi_edit` / `write_file` tool calls as a clean
1221
- * unified diff (red `-` / green `+` lines) instead of the raw
1222
- * `↳ name({"path":"…","old_string":"…"})` JSON dump. When on, the
1223
- * paired successful `tool-result` ("Edited path: …") is suppressed
1224
- * too since the diff already conveys success; errors still show.
1225
- *
1226
- * Off falls back to the unstructured `↳ name(args)` line + the
1227
- * regular `tool-result` block — same display the TUI had before
1228
- * the diff feature shipped. Default: on.
1229
- */
1230
- showEditDiffs: boolean;
1231
- /**
1232
- * Density of the edit-diff rendering. See {@link EditDiffDisplay}.
1233
- * Only consulted when {@link showEditDiffs} is on. Default: `'full'`.
1234
- */
1235
- editDiffDisplay: EditDiffDisplay;
1236
- /**
1237
- * Renderer target + max fps (the same value drives both — uncapping
1238
- * `maxFps` past the target just burns CPU on a terminal that's
1239
- * already painting at the target rate). The Settings modal cycles
1240
- * through `30 / 60 / 120`:
1241
- *
1242
- * - `30` — easy on CPU + battery; matches OpenTUI's historical
1243
- * default. Streaming still feels fine; modal animations and
1244
- * cursor blink visibly stutter on fast input.
1245
- * - `60` — recommended default. Matches the refresh rate of
1246
- * virtually every non-ProMotion display; sweet spot between
1247
- * smoothness and load.
1248
- * - `120` — only worth it on a 120Hz / ProMotion display + a
1249
- * modern terminal (Ghostty, Kitty, Alacritty, iTerm2 ≥ 3.5).
1250
- * Costs roughly 2× the CPU of 60 for marginal gains on most
1251
- * setups — sustained 120fps over SSH / nested tmux can add
1252
- * input latency from stdout backpressure.
1253
- *
1254
- * Applied live via `renderer.targetFps` / `renderer.maxFps` — flipping
1255
- * the setting takes effect on the next frame, no restart needed.
1256
- *
1257
- * Default: `60`.
1258
- */
1259
- targetFps: number;
1260
- /**
1261
- * Expose interactive tools (`ask_user`, `present_plan`) to the agent.
1262
- * When off, both tools are omitted from the agent's tool set at session
1263
- * activation — the model can't pause for clarifying questions and can't
1264
- * submit a structured plan, so it must proceed on its best guess and
1265
- * narrate any plan inline in its final message instead.
1266
- *
1267
- * The system prompt also adapts: the `INTERACTION_GUIDANCE` block is
1268
- * replaced with a short note explaining the lack of interactive tools,
1269
- * and Plan-mode's "explore → ask → propose" loop becomes
1270
- * "explore → propose-in-chat".
1271
- *
1272
- * Takes effect on the next session activation — flipping mid-stream
1273
- * doesn't tear down an in-flight `ask_user` / `present_plan` call.
1274
- * Default: on.
1275
- */
1276
- allowInteraction: boolean;
1277
- /**
1278
- * Drip-feed the assistant's text content character-by-character at a
1279
- * smooth cadence (typewriter effect) instead of committing each
1280
- * provider chunk in batches as it arrives. The display rate is capped
1281
- * so fast LLMs don't blast a wall of text into the transcript; an
1282
- * adaptive burst kicks in when the buffer falls behind, and turn
1283
- * boundaries always flush any remaining buffered content immediately
1284
- * — so the response never APPEARS slower to finish than it actually
1285
- * did, just easier to read mid-flight.
1286
- *
1287
- * Off falls back to the legacy ~30Hz batched flush (every provider
1288
- * delta lands in the transcript on the next tick, unsmoothed).
1289
- *
1290
- * Takes effect on the next provider delta — flipping mid-stream is
1291
- * safe; the buffer reads the setting on every tick.
1292
- *
1293
- * Default: on.
1294
- */
1295
- smoothStreaming: boolean;
1296
- /**
1297
- * Show the subtle one-line "in progress todo" indicator above the
1298
- * prompt input. Hidden entirely when there's no session, no active
1299
- * run, or no `in_progress` item in the active run's `todowrite` list
1300
- * — so flipping this off is a clean "I don't want even the bar".
1301
- *
1302
- * The dedicated modal (`ctrl+t` by default — see {@link KeyAction})
1303
- * is unaffected: opening it is an explicit user gesture.
1304
- *
1305
- * Default: on.
1306
- */
1307
- showTodoIndicator: boolean;
1308
- /**
1309
- * Render the inline gradient throbber (cycling hex/symbol glyphs +
1310
- * optional "Thinking…" label) at the tail of the transcript while a
1311
- * run is streaming. The throbber is purely decorative — `busy` state
1312
- * is also surfaced by the prompt's status row and the streaming
1313
- * markdown's incremental updates, so users who find the animated
1314
- * glyphs noisy / distracting can flip this off without losing the
1315
- * "assistant is working" signal.
1316
- *
1317
- * Default: off — opt-in to keep the transcript calm by default.
1318
- */
1319
- showThrobber: boolean;
1320
- /**
1321
- * Quietly check the npm registry for a newer release of the host
1322
- * package (`zidane-tui` for the shipped binary; any consumer can
1323
- * pass their own via `<App auto-update>` / `useUpdateCheck`).
1324
- *
1325
- * Hot path is cache-driven: one HTTP roundtrip per 24 h, persisted
1326
- * under `userDir/update-check-<pkg>@<channel>.json`. Boot is never
1327
- * blocked — the check fires after first paint with a 3-second
1328
- * timeout and degrades silently on network failure. CI runners
1329
- * (env `CI`), the npm-ecosystem `NO_UPDATE_NOTIFIER`, and the
1330
- * project-specific `ZIDANE_NO_UPDATE` env vars all force-disable
1331
- * regardless of this setting.
1332
- *
1333
- * Surfaces in the footer as a passive `↑ vX.Y.Z` chip (renderable
1334
- * by `useUpdateCheck` and `buildUpdateHint`). The explicit
1335
- * `zidane upgrade` subcommand bypasses both this toggle and the
1336
- * env opt-outs (it's an explicit user gesture).
1337
- *
1338
- * Default: on.
1339
- */
1340
- checkForUpdates: boolean;
1341
- /**
1342
- * Chat-screen chrome density. See {@link UiMode} for the contract —
1343
- * `'full'` keeps every advertised shortcut visible, `'minimal'`
1344
- * collapses the chat session UI to agent / model / keybindings + the
1345
- * `@` / `/` triggers, with the rest one keystroke away via `ctrl+y`.
1346
- * Default: `'full'`.
1347
- */
1348
- uiMode: UiMode;
1349
- /**
1350
- * Which scope(s) of personal instructions to inject into the system
1351
- * prompt at session activation. Discovered files:
1352
- *
1353
- * - `'none'` — skip discovery entirely. No `AGENTS.md` / `CLAUDE.md`
1354
- * files are loaded. Useful for reproducible reviews,
1355
- * demos, debugging the base system prompt, or running
1356
- * zidane against a repo whose committed `AGENTS.md`
1357
- * you don't trust yet.
1358
- * - `'user'` — `~/.agents/AGENTS.md`, `~/.{prefix}/AGENTS.md`,
1359
- * `~/.claude/CLAUDE.md`. Cross-project preferences
1360
- * (coding style, "always run lint before commit", …).
1361
- * - `'project'` — `<root>/AGENTS.md`, `<root>/.agents/AGENTS.md`,
1362
- * `<root>/.{prefix}/AGENTS.md`, `<root>/CLAUDE.md`.
1363
- * Repo-local context ("use pnpm, not npm").
1364
- * - `'both'` — union; user files render first (broader), project
1365
- * second (closer to the conversation, narrower
1366
- * context wins in the model's eyes).
1367
- *
1368
- * Within each enabled scope, EVERY matching file is loaded — no
1369
- * shadowing. Empty / whitespace-only files are skipped.
1370
- *
1371
- * Takes effect on the next session activation. Default: `'both'`.
1372
- */
1373
- userInstructionsScope: 'both' | 'none' | 'project' | 'user';
1374
- /**
1375
- * Allowlist of skill names to expose to the agent + slash-command picker.
1376
- * `undefined` means "every discovered skill" (default). An empty array
1377
- * fully disables the skills subsystem (no scan, no tool injection).
1378
- */
1379
- enabledSkills?: readonly string[];
1380
- /**
1381
- * Allowlist of MCP server names (from `.{prefix}/mcps.json`). Same
1382
- * semantics as `enabledSkills`: `undefined` enables every discovered
1383
- * server; `[]` disables all.
1384
- */
1385
- enabledMcps?: readonly string[];
1386
- /**
1387
- * Per-server **deny-list** of tool names to hide from the model. Maps
1388
- * 1:1 onto `McpServerConfig.disabledTools` at agent-construction
1389
- * time. Polarity is intentionally opposite to `enabledMcps`:
1390
- *
1391
- * - missing entry (or `undefined`) → every advertised tool enabled
1392
- * - `[]` → every advertised tool enabled
1393
- * - `['big_tool']` → drop `big_tool`; keep the rest
1394
- *
1395
- * The deny-list semantics mean a server that ships a new tool in a
1396
- * later release auto-enables for users who haven't explicitly opted
1397
- * it out — opposite preference from server-level toggles (where a
1398
- * new server should NOT silently appear). The TUI's MCP settings
1399
- * panel writes here when the user unchecks a tool checkbox.
1400
- *
1401
- * Composes with `McpServerConfig.disabledTools` on the JSON-side via
1402
- * union — a tool listed in either is dropped. JSON-side wins on
1403
- * conflict (you can't re-enable a JSON-pinned tool from the UI).
1404
- */
1405
- disabledMcpTools?: Record<string, readonly string[]>;
1406
- /**
1407
- * Master switch for the prompt textarea's paste-as-attachment
1408
- * pipeline. When `true` (default), the host intercepts paste events
1409
- * and folds:
1410
- *
1411
- * - single-line pastes that resolve to a real file on disk
1412
- * (drag-and-drop or `file://` URLs) into a binary attachment
1413
- * tagged with the matching MIME type, and
1414
- * - multiline pastes into a `paste.txt` document attachment so
1415
- * the prompt textarea doesn't balloon vertically.
1416
- *
1417
- * Flip to `false` to opt out entirely — every paste lands inline in
1418
- * the textarea verbatim, regardless of size, shape, or whether the
1419
- * content matches a file path on disk. Useful for users who paste
1420
- * short snippets often and find the auto-attach behavior breaks
1421
- * their composing flow.
1422
- *
1423
- * Doesn't affect the rest of the multimodal pipeline — embedders
1424
- * that build `PromptPart[]` directly (image messages from a GUI,
1425
- * dropped files via a custom handler) still flow through unchanged.
1426
- * Default: on.
1427
- */
1428
- attachmentsEnabled: boolean;
1429
- /**
1430
- * What happens when the user presses Ctrl+C.
1431
- *
1432
- * - `'quit'` — exit immediately (default, legacy behavior).
1433
- * - `'quit-confirm'` — show a confirmation modal; Enter / y confirms,
1434
- * Escape / n cancels. A second Ctrl+C while the
1435
- * modal is open also confirms.
1436
- * - `'stop-then-quit'` — first press aborts the active run or clears the
1437
- * input; second consecutive press (within 1.5 s)
1438
- * exits. If there's nothing to stop and the input
1439
- * is empty, the first press exits directly.
1440
- */
1441
- ctrlCBehavior: 'quit' | 'quit-confirm' | 'stop-then-quit';
1442
- }
1443
- //#endregion
1444
439
  //#region src/chat/store.d.ts
1445
440
  interface TuiState {
1446
441
  lastProvider?: ProviderKey;
@@ -1453,6 +448,12 @@ interface TuiState {
1453
448
  * intent. Models without reasoning support are absent from the map.
1454
449
  */
1455
450
  lastEffortByModel?: Record<string, ThinkingLevel>;
451
+ /**
452
+ * Per-model last-picked custom options (e.g. `{ fast: true }`). Keyed by
453
+ * model id like {@link lastEffortByModel}, so a toggle follows the model
454
+ * across providers. Models with no options are absent from the map.
455
+ */
456
+ lastModelOptionsByModel?: Record<string, Record<string, boolean>>;
1456
457
  /**
1457
458
  * Last-active agent profile id (see {@link AgentRegistry}). Resumed on
1458
459
  * launch so a returning user lands back in the same mode (Build / Plan /
@@ -1553,38 +554,6 @@ declare function toolResultText(output: string | ToolResultContent[]): string;
1553
554
  * (post-`formatTokenUsage`) shapes.
1554
555
  */
1555
556
  declare function stripSpawnTokensLine(text: string): string;
1556
- /**
1557
- * Recognize a tool-result body as carrying NON-success information so the
1558
- * renderer doesn't suppress it under `showEditDiffs`. Three categories:
1559
- *
1560
- * - `edit` → "Edit error: …"
1561
- * - `write_file` permission errors wrapped by the loop → "Tool failed: …"
1562
- * - `multi_edit` → legacy single-line error `multi_edit error: …`, OR
1563
- * a result carrying an `<edit-outcomes>…</edit-outcomes>` annotation
1564
- * block. The TUI only appends the annotation when at least one hunk
1565
- * was NOT applied, so its mere presence is the signal — the result
1566
- * body needs to stay visible next to the diff so the user can read
1567
- * denial / skip / failure reasons longer than the per-hunk badge.
1568
- * - Fully-denied gate emit (`[fully denied] <edit-outcomes>…`) likewise
1569
- * stays visible.
1570
- *
1571
- * Exported for unit-testability of the visibility matrix.
1572
- */
1573
- declare function isEditErrorResult(text: string): boolean;
1574
- /**
1575
- * Per-event visibility — filters honor user toggles and the
1576
- * `hideSubagentOutput` setting. When subagent output is hidden:
1577
- * - Child-agent events are filtered down to the `spawn-start` /
1578
- * `spawn-end` markers so the user still sees "🌱 working… 🌳 done".
1579
- * - The parent's `tool-result` for `spawn` is hidden too. Its body
1580
- * duplicates `spawn-end`'s stats line *and* the parent's next
1581
- * markdown turn; showing it again produces an extra
1582
- * `┃ [sub-agent child-1] Completed …` block users just want gone.
1583
- *
1584
- * Renderer-agnostic — returns plain `boolean` so TUI / GUI consumers
1585
- * can filter events identically.
1586
- */
1587
- declare function isVisible(event: StreamEvent, settings: Settings): boolean;
1588
557
  /**
1589
558
  * Resolve the top margin (in rows) for an event given the one rendered
1590
559
  * just before it. Context-aware rules:
@@ -1612,67 +581,6 @@ declare function isVisible(event: StreamEvent, settings: Settings): boolean;
1612
581
  * use the same number as the row's top margin in `em` / `rem`.
1613
582
  */
1614
583
  declare function marginTopFor(event: StreamEvent, previous: StreamEvent | undefined): number;
1615
- /**
1616
- * Build the `resultTurnId → owningAssistantTurnId` map used by the select-
1617
- * turn mode to coalesce a tool-call's surrounding turns into ONE navigation
1618
- * stop.
1619
- *
1620
- * Protocol shape: every `tool_call` block in an assistant turn is closed by
1621
- * a matching `tool_result` block in the *next* user turn (the agent loop's
1622
- * history validator depends on this). When the next user turn's only events
1623
- * are `tool-result`s — i.e. it's pure plumbing for the prior assistant
1624
- * turn — we map it back to that assistant turn here. The select-turn nav
1625
- * index ({@link selectableTurnIds}) skips owned turns, and the renderer's
1626
- * highlight gate ({@link isTurnHighlighted}) extends the selection accent
1627
- * from the assistant turn to the events of any turn it owns. Net effect:
1628
- *
1629
- * - Navigation never lands the cursor on a result-only turn whose own
1630
- * events may be hidden by `showToolResults: false` — the cursor
1631
- * wouldn't be visible.
1632
- * - Selecting an assistant turn highlights the call AND its result as
1633
- * one unit, matching the user's mental model of "one message".
1634
- *
1635
- * Owner-lookup is conservative: result-only turns with no matching prior
1636
- * assistant turn (orphaned — usually because the parent was deleted)
1637
- * stay selectable so the user can act on them via the turn-details modal.
1638
- *
1639
- * Subagent (`childId` set) events are ignored — they live in a separate
1640
- * conversation tree.
1641
- */
1642
- declare function turnSelectionOwnership(events: readonly StreamEvent[]): Map<string, string>;
1643
- /**
1644
- * Render-time check: should `event` paint with the selection accent?
1645
- *
1646
- * `true` when the event's own turn is selected, OR when the selected turn
1647
- * `owns` the event's turn via {@link turnSelectionOwnership} (the call and
1648
- * its tool-result rows highlight together). `false` when nothing is
1649
- * selected or the relationship doesn't apply.
1650
- *
1651
- * Pure. Renderer-agnostic — the TUI's `<Transcript>` uses it; a GUI's
1652
- * equivalent walks the same rule.
1653
- */
1654
- declare function isTurnHighlighted(event: Pick<StreamEvent, 'turnId'>, selectedTurnId: string | null, ownership: ReadonlyMap<string, string>): boolean;
1655
- /**
1656
- * Deduplicated, in-order list of **parent-conversation** turn ids that appear
1657
- * in a rendered transcript — the navigation index for the TUI's select-turn
1658
- * mode. Three classes of turns are deliberately skipped:
1659
- *
1660
- * - **Subagent turns** (`childId` set). Nested execution detail; the
1661
- * user's mental model of a "message" is the conversational exchange,
1662
- * not each spawn turn. Also filtered out by `isVisible` under
1663
- * `hideSubagentOutput: true` — selecting them would highlight nothing.
1664
- * - **Result-only turns** — see {@link turnSelectionOwnership}. These get
1665
- * coalesced into the assistant turn that emitted their tool_calls.
1666
- * - **Settings-hidden turns** (when `settings` is supplied). A turn whose
1667
- * every event fails {@link isVisible} would render no rows — landing
1668
- * the cursor there hides it from the user entirely. The check is opt-
1669
- * in so SDK callers without a Settings object keep the legacy
1670
- * "everything visible" behavior.
1671
- *
1672
- * Synthetic events (separator, spawn-start, spawn-end) have no `turnId` and
1673
- * are skipped naturally.
1674
- */
1675
- declare function selectableTurnIds(events: readonly StreamEvent[], settings?: Settings): string[];
1676
584
  /** Effective context size of the most recent assistant turn — drives the footer indicator. */
1677
585
  /**
1678
586
  * Walk from the end of `turns` and return the cache-aware input-token total
@@ -2217,64 +1125,6 @@ declare function buildMcpServers(opts: {
2217
1125
  disabledTools?: Record<string, readonly string[]>;
2218
1126
  }): McpServerConfig[];
2219
1127
  //#endregion
2220
- //#region src/chat/safe-mode-context.d.ts
2221
- /**
2222
- * Outcome of an approval prompt. Four bulk decisions match the original
2223
- * single-edit modal contract; `partial` is the multi-edit branch — the
2224
- * user accepted a subset of an `edit` / `multi_edit` / `write_file` call.
2225
- *
2226
- * `partial.mask` is 1:1 with the call's hunks (in input order): `true`
2227
- * means apply, `false` means deny. The gate handler walks the mask to
2228
- * build per-hunk outcomes; the TUI rebinds `ctx.input.edits` to the
2229
- * approved subset and the renderer reconstructs the full per-hunk view
2230
- * from the `<edit-outcomes>` annotation appended to the tool result.
2231
- */
2232
- type ApprovalDecision = 'accept-once' | 'accept-session' | 'accept-safelist' | 'deny' | {
2233
- kind: 'partial';
2234
- mask: readonly boolean[];
2235
- };
2236
- /**
2237
- * Identifies the caller behind an approval prompt — the parent agent or
2238
- * a specific subagent (`child-N`). The modal's right-side title pins the
2239
- * label so the user knows which agent issued the call when subagents
2240
- * bubble their gates up through the parent's hook bus.
2241
- */
2242
- type ApprovalOriginator = {
2243
- kind: 'parent';
2244
- } | {
2245
- kind: 'child';
2246
- label: string;
2247
- };
2248
- interface ApprovalRequest {
2249
- id: string;
2250
- tool: string;
2251
- input: Record<string, unknown>;
2252
- resolve: (decision: ApprovalDecision) => void;
2253
- /** Caller attribution. Absent ≡ `{ kind: 'parent' }`. */
2254
- originator?: ApprovalOriginator;
2255
- }
2256
- /** Function signature consumed by `tool:gate` handlers + the child-tool wrap. */
2257
- type RequestApproval = (tool: string, input: Record<string, unknown>, originator?: ApprovalOriginator) => Promise<ApprovalDecision>;
2258
- interface SafeModeActions {
2259
- /** Request a decision; resolves once the user picks. */
2260
- requestApproval: RequestApproval;
2261
- /** Resolve the head and shift the queue forward. */
2262
- resolveHead: (decision: ApprovalDecision) => void;
2263
- /** Resolve all pending with `deny`. Used on abort / hard exit. */
2264
- denyAll: () => void;
2265
- }
2266
- /**
2267
- * Owns the queue + actions. Splits the value across two contexts so a queue
2268
- * change doesn't invalidate every callback memo that closes over the actions.
2269
- */
2270
- declare function SafeModeProvider({
2271
- children
2272
- }: {
2273
- children: ReactNode;
2274
- }): _$react_jsx_runtime0.JSX.Element;
2275
- declare function useSafeModeQueue(): readonly ApprovalRequest[];
2276
- declare function useSafeModeActions(): SafeModeActions;
2277
- //#endregion
2278
1128
  //#region src/chat/enabled-toggle-set.d.ts
2279
1129
  /**
2280
1130
  * Renderer-agnostic state machine for an "enabled allowlist" — the shape
@@ -2522,7 +1372,7 @@ declare function InteractionsProvider({
2522
1372
  children
2523
1373
  }: {
2524
1374
  children: ReactNode;
2525
- }): _$react_jsx_runtime0.JSX.Element;
1375
+ }): import("react/jsx-runtime").JSX.Element;
2526
1376
  /** Read the live queue (re-renders on every push/pop). */
2527
1377
  declare function useInteractionsQueue(): readonly PendingInteractionEntry[];
2528
1378
  /** Read the stable actions object. */
@@ -2575,67 +1425,6 @@ interface MarkdownSegment {
2575
1425
  */
2576
1426
  declare function splitMarkdownCodeBlocks(text: string): MarkdownSegment[];
2577
1427
  //#endregion
2578
- //#region src/chat/prompt-segments.d.ts
2579
- /**
2580
- * Pure string + reference math for rendering a submitted prompt with chip
2581
- * pills around completion references. Renderer-agnostic — the TUI walks
2582
- * the segments into OpenTUI `<text>` nodes, a GUI walks them into JSX
2583
- * spans + `<span class="chip">` pills. No layout engine assumptions.
2584
- */
2585
- /**
2586
- * Highlight span — half-open `[start, end)` over the source string.
2587
- *
2588
- * Offsets are JS string indices (UTF-16 code units) — the same convention used
2589
- * everywhere else in the chat layer (`text[i]`, `m.index`, `String.slice`).
2590
- * Surrogate pairs that straddle a span boundary would render malformed, but
2591
- * realistic prompts in this surface (terminal text + ASCII triggers) keep that
2592
- * risk theoretical; callers feeding emoji-heavy content should normalize to
2593
- * codepoint walks upstream.
2594
- */
2595
- interface PromptSegmentRef {
2596
- start: number;
2597
- end: number;
2598
- /** Provider id tagging this span (`'skills'`, `'files'`, …). Free-form. */
2599
- providerId: string;
2600
- }
2601
- /**
2602
- * One atomic unit emitted by {@link splitPromptSegments}. Plain segments
2603
- * are word-sized so wraps land cleanly between words; chip segments
2604
- * carry the source `providerId` (`'skills'`, `'files'`, …) so renderers
2605
- * can pick per-kind colors without re-walking the ref list.
2606
- */
2607
- type PromptSegment = {
2608
- kind: 'plain';
2609
- text: string;
2610
- } | {
2611
- kind: 'chip';
2612
- text: string;
2613
- providerId: string;
2614
- };
2615
- /**
2616
- * Split a prompt buffer into word-sized atomic segments suitable for a
2617
- * flex-row + flex-wrap renderer (TUI) or a `display: inline` flow with
2618
- * inline-block chips (GUI). Each chip becomes one segment (atomic —
2619
- * never broken across rows); each plain run is split into "word +
2620
- * trailing space" units so wraps land at clean word boundaries.
2621
- *
2622
- * Robust to:
2623
- * - Overlapping refs — sorted by start; later refs that overlap are
2624
- * dropped via the first-wins rule.
2625
- * - Out-of-bounds refs — dropped entirely when `end > text.length` or
2626
- * `start >= text.length`. Partial clipping would silently truncate
2627
- * a chip's label; the caller is in a better position to surface the
2628
- * mismatch (typically a stale `refs` array referencing a previous text).
2629
- * - Whitespace-only plain runs — emitted as their own plain segment
2630
- * so chip-adjacent-to-chip cases keep the original spacing.
2631
- *
2632
- * Word splitter rationale: `\S+\s*` keeps trailing whitespace attached
2633
- * to its preceding word so wrap boundaries land between words (cleanly).
2634
- * A leading-whitespace-only segment is captured by `\s+` so we don't
2635
- * drop it entirely when the plain run starts with a space.
2636
- */
2637
- declare function splitPromptSegments(text: string, refs: readonly PromptSegmentRef[]): PromptSegment[];
2638
- //#endregion
2639
1428
  //#region src/chat/session-export.d.ts
2640
1429
  /** File format supported by the exporter. */
2641
1430
  type SessionExportFormat = 'markdown' | 'json';
@@ -2910,81 +1699,6 @@ declare const BUILTIN_THEMES: Readonly<Record<string, Theme>>;
2910
1699
  /** Resolve a theme id to its full `Theme`, falling back to default on unknown ids. */
2911
1700
  declare function resolveTheme(id: string | undefined): Theme;
2912
1701
  //#endregion
2913
- //#region src/chat/tool-formatters.d.ts
2914
- /**
2915
- * Per-tool display metadata + one-line formatters consumed by any
2916
- * surface that renders a `tool` event in `'formatted'` mode (see
2917
- * `Settings.toolCallDisplay`).
2918
- *
2919
- * Each native tool gets a curated entry — a `displayName` verb that
2920
- * reads in sentence case (e.g. "Read", "Shell") and a `format` callback
2921
- * that pulls the most informative bits out of the model's raw input to
2922
- * a single scannable line. Unknown tools (MCP servers, host-added
2923
- * tools, future zidane additions) fall back to {@link formatToolCall}
2924
- * returning `null` — the renderer then shows a minimal `↳ <name>` line.
2925
- *
2926
- * Renderer-agnostic: returns plain data (`{ target, meta }`) so the
2927
- * TUI's React/OpenTUI surface and any future GUI consumer can paint
2928
- * the same shape in their own style. Lives in `zidane/chat` because
2929
- * it has no rendering concerns; the TUI just consumes it.
2930
- */
2931
- interface ToolFormatLine {
2932
- /**
2933
- * Primary target — typically a path, command, pattern, or
2934
- * task description. Renderer paints this in the model accent color
2935
- * so the eye lands on it first.
2936
- */
2937
- target?: string;
2938
- /**
2939
- * Secondary annotations rendered after the target, joined with
2940
- * ` · ` separators. Use for line ranges (`L10-25`), limits, flags,
2941
- * or any short suffix that adds context without bloating the line.
2942
- */
2943
- meta?: readonly string[];
2944
- }
2945
- interface ToolDisplayMeta {
2946
- /**
2947
- * Title-case display verb (e.g. `Read`, `Shell`, `Edit`). When the
2948
- * label depends on an input field (e.g. `skills_use`'s
2949
- * `mode: 'activate' | 'deactivate'` → `Enable` / `Disable`), supply
2950
- * a function instead and read the field defensively. The function
2951
- * form is called whenever {@link displayNameFor} has the call's
2952
- * input in scope; callers without input fall back to the function's
2953
- * `input: undefined` branch, which should return a stable default.
2954
- */
2955
- displayName: string | ((input: Record<string, unknown> | undefined) => string);
2956
- /**
2957
- * Pull a {@link ToolFormatLine} out of the raw model input. Returns
2958
- * `null` when the shape isn't what the tool expects (typed defensively
2959
- * — we never want a malformed call to crash the transcript).
2960
- */
2961
- format: (input: Record<string, unknown>) => ToolFormatLine | null;
2962
- }
2963
- declare const TOOL_DISPLAY: Readonly<Record<string, ToolDisplayMeta>>;
2964
- /**
2965
- * Resolve the display verb for a tool. Native tools use their curated
2966
- * entry from {@link TOOL_DISPLAY}; everything else gets a sentence-case
2967
- * version of the raw name (`my_host_tool` → `My host tool`) so an MCP /
2968
- * host tool still reads cleanly in the transcript without shouting
2969
- * Title Case at every word.
2970
- *
2971
- * MCP convention: every tool surfaced by `mcp/connectMcpServers` is
2972
- * namespaced as `mcp_<server>_<tool>` (see `src/mcp/index.ts`). The
2973
- * `mcp_` prefix is plumbing — strip it before casing so the label
2974
- * reads as `Github create issue` instead of `Mcp github create issue`.
2975
- * The server name leads, which doubles as a free visual grouping
2976
- * affordance ("everything starting with `Github` came from the github
2977
- * MCP server").
2978
- */
2979
- declare function displayNameFor(name: string, input?: Record<string, unknown>): string;
2980
- /**
2981
- * Run a tool's curated formatter and return the result, or `null` when
2982
- * no formatter is registered / the input shape doesn't match. Renderer
2983
- * decides what to do with `null` — typically: show `↳ <displayName>`
2984
- * with no target / meta tail.
2985
- */
2986
- declare function formatToolCall(name: string, input: Record<string, unknown>): ToolFormatLine | null;
2987
- //#endregion
2988
1702
  //#region src/chat/transcript-anchors.d.ts
2989
1703
  /**
2990
1704
  * One entry in the partitioned transcript-row list. Single events
@@ -3028,5 +1742,5 @@ declare function computeTurnAnchors(items: readonly TranscriptItem[]): {
3028
1742
  lastTurnId: string | undefined;
3029
1743
  };
3030
1744
  //#endregion
3031
- export { TextQuestion as $, detectAuth as $n, titleFromTurns as $t, splitMarkdownCodeBlocks as A, mergeKeybindings as An, resolveConfig as At, PendingInteractionEntry as B, applyInsert as Bn, deriveSessionTitle as Bt, renderSession as C, KeyBindings as Cn, PLAN_AGENT as Cr, discoverProjectMcps as Ct, PromptSegmentRef as D, groupBindings as Dn, ProviderRegistry as Dt, PromptSegment as E, formatBindingForDisplay as En, singleAgentRegistry as Er, ChatOptions as Et, InteractionRequest as F, CompletionContext as Fn, StorageSlot as Ft, PlanStep as G, EMPTY_HINTS as Gn, lastContextSizeFromTurns as Gt, PlanPayload as H, findActiveTrigger as Hn, isEditErrorResult as Ht, InteractionResponse as I, CompletionItem as In, resolveStorageDirs as It, QuestionPayload as J, hintsLength as Jn, marginTopFor as Jt, Question as K, Hint as Kn, listSessionMeta as Kt, InteractionsActions as L, CompletionProvider as Ln, StateStoreApi as Lt, AnswerValue as M, readKeybindings as Mn, ResolveStorageDirsOptions as Mt, ConfirmQuestion as N, stripJsonComments as Nn, StorageDirs as Nt, splitPromptSegments as O, keybindingsPath as On, ResolvedConfig as Ot, CreateInteractionToolsOptions as P, ActiveTrigger as Pn, StorageMode as Pt, SelectQuestion as Q, ProviderKey as Qn, sumRunCosts as Qt, InteractionsProvider as R, CompletionReference as Rn, TuiState as Rt, SessionExportTarget as S, KeyBindingSection as Sn, DEFAULT_PERSIST_EXCLUDE_TOOLS as Sr, defaultMcpsConfigPaths as St, writeSessionExport as T, ensureKeybindingsFile as Tn, resolveAgentId as Tr, AutoUpdateConfig as Tt, PlanRequest as U, mergeReferences as Un, isTurnHighlighted as Ut, PlanDecision as V, collectReferences as Vn, eventsFromTurns as Vt, PlanResponse as W, useCompletion as Wn, isVisible as Wt, QuestionResponse as X, AuthMethod as Xn, selectableTurnIds as Xt, QuestionRequest as Y, truncateTrailing as Yn, saveState as Yt, QuestionType as Z, ProviderAuth as Zn, stripSpawnTokensLine as Zt, ThemeSurfaces as _, KEYBINDING_DEFS as _n, AgentRegistry as _r, useSafeModeQueue as _t, ToolFormatLine as a, EditHunk as an, cerebrasDescriptor as ar, serializeInteractionResponse as at, SessionExportAnchor as b, KeyAction as bn, DEFAULT_AGENT_ID as br, DiscoveryResult as bt, BUILTIN_THEMES as c, EditPayload as cn, getContextWindow as cr, EnabledAllowlistKey as ct, DEFAULT_THEME as d, Screen as dn, modelsForDescriptor as dr, ApprovalDecision as dt, toolCallPreview as en, BUILTIN_PROVIDERS as er, buildResumedToolResultsTurn as et, SyntaxStyles as f, SessionMeta as fn, openaiDescriptor as fr, ApprovalRequest as ft, ThemeSelect as g, DEFAULT_KEYBINDINGS as gn, AgentProfile as gr, useSafeModeActions as gt, ThemeColors as h, ToolCallDisplay as hn, AgentAccent as hr, SafeModeProvider as ht, ToolDisplayMeta as i, EditDiffDisplay as in, anthropicDescriptor as ir, pendingInteractionsFromTurns as it, ASK_USER_TOOL as j, parseBindingSpec as jn, resolveStoragePaths as jt, MarkdownSegment as k, matchesBinding as kn, ResolvedPaths as kt, ChipColor as l, Owner as ln, getModelInfo as lr, EnabledToggleSet as lt, Theme as m, StreamEvent as mn, piIdOf as mr, SafeModeActions as mt, computeTurnAnchors as n, turnSelectionOwnership as nn, OUTPUT_RESERVE_TOKENS as nr, isInteractionTool as nt, displayNameFor as o, EditOutcome as on, credKeyOf as or, useInteractionsActions as ot, SyntaxTokenStyle as p, Settings as pn, openrouterDescriptor as pr, RequestApproval as pt, QuestionChoice as q, clipHintsToWidth as qn, loadState as qt, TOOL_DISPLAY as r, updateToolEventOutcomes as rn, ProviderDescriptor as rr, makeRequestInteraction as rt, formatToolCall as s, EditOutcomeKind as sn, effectiveContextWindow as sr, useInteractionsQueue as st, TranscriptItem as t, toolResultText as tn, ModelInfo as tr, createInteractionTools as tt, ChipColorMap as u, Picked as un, modelSupportsReasoning as ur, useEnabledToggleSet as ut, resolveChipColor as v, KEYBINDING_DEF_BY_ACTION as vn, BUILD_AGENT as vr, DiscoveredMcp as vt, resolveSessionExportTarget as w, ParsedBinding as wn, accentColor as wr, parseMcpsFile as wt, SessionExportFormat as x, KeyBindingDef as xn, DEFAULT_BUDGET_EXCLUDE_TOOLS as xr, buildMcpServers as xt, resolveTheme as y, KEYBINDING_KEY_COL_WIDTH as yn, BUILTIN_AGENTS as yr, DiscoveryError as yt, PRESENT_PLAN_TOOL as z, CompletionState as zn, createStateStore as zt };
3032
- //# sourceMappingURL=transcript-anchors-D0TR6djV.d.ts.map
1745
+ export { useInteractionsQueue as $, parseBindingSpec as $t, InteractionsProvider as A, marginTopFor as At, QuestionPayload as B, KEYBINDING_DEF_BY_ACTION as Bt, ASK_USER_TOOL as C, TuiState as Ct, InteractionRequest as D, lastContextSizeFromTurns as Dt, CreateInteractionToolsOptions as E, eventsFromTurns as Et, PlanRequest as F, toolCallPreview as Ft, TextQuestion as G, KeyBindings as Gt, QuestionResponse as H, KeyAction as Ht, PlanResponse as I, toolResultText as It, isInteractionTool as J, formatBindingForDisplay as Jt, buildResumedToolResultsTurn as K, ParsedBinding as Kt, PlanStep as L, updateToolEventOutcomes as Lt, PendingInteractionEntry as M, stripSpawnTokensLine as Mt, PlanDecision as N, sumRunCosts as Nt, InteractionResponse as O, listSessionMeta as Ot, PlanPayload as P, titleFromTurns as Pt, useInteractionsActions as Q, mergeKeybindings as Qt, Question as R, DEFAULT_KEYBINDINGS as Rt, splitMarkdownCodeBlocks as S, StateStoreApi as St, ConfirmQuestion as T, deriveSessionTitle as Tt, QuestionType as U, KeyBindingDef as Ut, QuestionRequest as V, KEYBINDING_KEY_COL_WIDTH as Vt, SelectQuestion as W, KeyBindingSection as Wt, pendingInteractionsFromTurns as X, keybindingsPath as Xt, makeRequestInteraction as Y, groupBindings as Yt, serializeInteractionResponse as Z, matchesBinding as Zt, SessionExportTarget as _, PLAN_AGENT as _n, ResolveStorageDirsOptions as _t, ChipColorMap as a, Hint as an, DiscoveryResult as at, writeSessionExport as b, singleAgentRegistry as bn, StorageSlot as bt, SyntaxTokenStyle as c, truncateTrailing as cn, discoverProjectMcps as ct, ThemeSelect as d, AgentRegistry as dn, ChatOptions as dt, readKeybindings as en, EnabledAllowlistKey as et, ThemeSurfaces as f, BUILD_AGENT as fn, ProviderRegistry as ft, SessionExportFormat as g, DEFAULT_PERSIST_EXCLUDE_TOOLS as gn, resolveStoragePaths as gt, SessionExportAnchor as h, DEFAULT_BUDGET_EXCLUDE_TOOLS as hn, resolveConfig as ht, ChipColor as i, EMPTY_HINTS as in, DiscoveryError as it, PRESENT_PLAN_TOOL as j, saveState as jt, InteractionsActions as k, loadState as kt, Theme as l, AgentAccent as ln, parseMcpsFile as lt, resolveTheme as m, DEFAULT_AGENT_ID as mn, ResolvedPaths as mt, computeTurnAnchors as n, CompletionState as nn, useEnabledToggleSet as nt, DEFAULT_THEME as o, clipHintsToWidth as on, buildMcpServers as ot, resolveChipColor as p, BUILTIN_AGENTS as pn, ResolvedConfig as pt, createInteractionTools as q, ensureKeybindingsFile as qt, BUILTIN_THEMES as r, useCompletion as rn, DiscoveredMcp as rt, SyntaxStyles as s, hintsLength as sn, defaultMcpsConfigPaths as st, TranscriptItem as t, stripJsonComments as tn, EnabledToggleSet as tt, ThemeColors as u, AgentProfile as un, AutoUpdateConfig as ut, renderSession as v, accentColor as vn, StorageDirs as vt, AnswerValue as w, createStateStore as wt, MarkdownSegment as x, resolveStorageDirs as xt, resolveSessionExportTarget as y, resolveAgentId as yn, StorageMode as yt, QuestionChoice as z, KEYBINDING_DEFS as zt };
1746
+ //# sourceMappingURL=transcript-anchors-DX90kXc4.d.ts.map