zidane 4.1.8 → 5.0.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.
Files changed (66) hide show
  1. package/README.md +11 -2
  2. package/dist/{index-bgh-k8Mv.d.ts → agent-JhicgLOV.d.ts} +2082 -1969
  3. package/dist/agent-JhicgLOV.d.ts.map +1 -0
  4. package/dist/chat.d.ts +340 -9
  5. package/dist/chat.d.ts.map +1 -1
  6. package/dist/chat.js +2 -2
  7. package/dist/contexts.d.ts +1 -1
  8. package/dist/{index-DRoG_udt.d.ts → index-2yLUyTbc.d.ts} +34 -4
  9. package/dist/{index-DRoG_udt.d.ts.map → index-2yLUyTbc.d.ts.map} +1 -1
  10. package/dist/{index-BB4kuRh3.d.ts → index-CXVvqTQj.d.ts} +1 -1
  11. package/dist/{index-BB4kuRh3.d.ts.map → index-CXVvqTQj.d.ts.map} +1 -1
  12. package/dist/{index-Ds5YpvfZ.d.ts → index-t_W9i7Ql.d.ts} +9 -4
  13. package/dist/index-t_W9i7Ql.d.ts.map +1 -0
  14. package/dist/index.d.ts +4 -4
  15. package/dist/index.js +6 -6
  16. package/dist/{interpolate-CukJwP2G.js → interpolate-Ck970-61.js} +11 -2
  17. package/dist/interpolate-Ck970-61.js.map +1 -0
  18. package/dist/{mcp-8wClKY-3.js → mcp-Dw-fRPVk.js} +61 -65
  19. package/dist/mcp-Dw-fRPVk.js.map +1 -0
  20. package/dist/mcp.d.ts +1 -1
  21. package/dist/mcp.js +1 -1
  22. package/dist/presets-BRFH2qsQ.js +90 -0
  23. package/dist/presets-BRFH2qsQ.js.map +1 -0
  24. package/dist/presets.d.ts +3 -2
  25. package/dist/presets.js +2 -2
  26. package/dist/providers.d.ts +1 -1
  27. package/dist/session/sqlite.d.ts +13 -2
  28. package/dist/session/sqlite.d.ts.map +1 -1
  29. package/dist/session/sqlite.js +96 -38
  30. package/dist/session/sqlite.js.map +1 -1
  31. package/dist/{session-Cn68UASv.js → session-791hhrFa.js} +65 -30
  32. package/dist/session-791hhrFa.js.map +1 -0
  33. package/dist/session.d.ts +1 -1
  34. package/dist/session.js +1 -1
  35. package/dist/skills.d.ts +2 -2
  36. package/dist/skills.js +1 -1
  37. package/dist/{stats-BT9l57RS.js → stats-DZIsGqzu.js} +15 -5
  38. package/dist/stats-DZIsGqzu.js.map +1 -0
  39. package/dist/theme-pJv47erq.d.ts +1202 -0
  40. package/dist/theme-pJv47erq.d.ts.map +1 -0
  41. package/dist/{tools-C8kDot0H.js → tools-CLazLRb4.js} +475 -318
  42. package/dist/tools-CLazLRb4.js.map +1 -0
  43. package/dist/tools.d.ts +2 -2
  44. package/dist/tools.js +1 -1
  45. package/dist/tui.d.ts +303 -18
  46. package/dist/tui.d.ts.map +1 -1
  47. package/dist/tui.js +3305 -509
  48. package/dist/tui.js.map +1 -1
  49. package/dist/turn-operations-5aQu4dJg.js +3587 -0
  50. package/dist/turn-operations-5aQu4dJg.js.map +1 -0
  51. package/dist/types.d.ts +3 -3
  52. package/dist/types.js +1 -1
  53. package/package.json +6 -1
  54. package/dist/index-Ds5YpvfZ.d.ts.map +0 -1
  55. package/dist/index-bgh-k8Mv.d.ts.map +0 -1
  56. package/dist/interpolate-CukJwP2G.js.map +0 -1
  57. package/dist/mcp-8wClKY-3.js.map +0 -1
  58. package/dist/presets-BzkJDW1K.js +0 -39
  59. package/dist/presets-BzkJDW1K.js.map +0 -1
  60. package/dist/session-Cn68UASv.js.map +0 -1
  61. package/dist/stats-BT9l57RS.js.map +0 -1
  62. package/dist/theme-BlXO6yHe.d.ts +0 -503
  63. package/dist/theme-BlXO6yHe.d.ts.map +0 -1
  64. package/dist/theme-context-MungM3SY.js +0 -1713
  65. package/dist/theme-context-MungM3SY.js.map +0 -1
  66. package/dist/tools-C8kDot0H.js.map +0 -1
@@ -0,0 +1,1202 @@
1
+ import { Dt as SessionTurn, Nt as ToolResultContent, O as SessionRun, U as Provider, ht as McpServerConfig, k as SessionStore } from "./agent-JhicgLOV.js";
2
+ import { t as Preset } from "./index-2yLUyTbc.js";
3
+ import { OAuthProviderInterface } from "@mariozechner/pi-ai/oauth";
4
+ import { ReactNode } from "react";
5
+ import * as _$react_jsx_runtime0 from "react/jsx-runtime";
6
+
7
+ //#region src/chat/agents.d.ts
8
+ /**
9
+ * Theme color token used to accent the active profile in the UI (footer
10
+ * badge, picker highlight). Resolved against `ThemeColors` via
11
+ * `useColors()`; falls back to `accent` when omitted.
12
+ */
13
+ type AgentAccent = 'brand' | 'accent' | 'warn' | 'model';
14
+ interface AgentProfile {
15
+ /** Stable identifier persisted in `TuiState.lastAgent` and shown in keybindings. */
16
+ id: string;
17
+ /** Human-readable label rendered in the picker and footer badge. */
18
+ label: string;
19
+ /** One-line description shown next to the label in the picker. */
20
+ description: string;
21
+ /**
22
+ * Preset applied to `createAgent()` when this profile is active. Profiles
23
+ * are self-contained: the host's chat-level `preset` (if any) is NOT
24
+ * merged underneath. Hosts that want a shared base across profiles
25
+ * should compose it explicitly in each profile's preset.
26
+ */
27
+ preset: Preset;
28
+ /** Theme token used by the picker / footer badge. Defaults to `'accent'`. */
29
+ accent?: AgentAccent;
30
+ }
31
+ type AgentRegistry = Readonly<Record<string, AgentProfile>>;
32
+ /**
33
+ * Build agent — the default profile. Full read/write/shell access plus
34
+ * subagent spawning. Mirrors the legacy `basic` preset so existing TUI
35
+ * behavior is preserved when `agents` is omitted.
36
+ */
37
+ declare const BUILD_AGENT: AgentProfile;
38
+ /**
39
+ * Plan agent — read-only exploration mode. Locked down to file reading and
40
+ * codebase search; no shell, no edits, no spawning. The system prompt
41
+ * frames the conversation as planning rather than execution so the model
42
+ * outputs proposals instead of attempting mutations.
43
+ */
44
+ declare const PLAN_AGENT: AgentProfile;
45
+ /**
46
+ * Default registry shipped with `zidane/tui`. Insertion order = picker order.
47
+ * Hosts that want only one profile can pass `{ agents: { build: BUILD_AGENT } }`,
48
+ * or a fully custom registry of their own profiles.
49
+ */
50
+ declare const BUILTIN_AGENTS: AgentRegistry;
51
+ /** Id of the profile activated on first launch when nothing is persisted. */
52
+ declare const DEFAULT_AGENT_ID = "build";
53
+ /**
54
+ * Resolve an agent id against a registry with sensible fallbacks: the
55
+ * requested id wins when present, then `defaultId`, then the first key.
56
+ * Returns `null` when the registry is empty (host misconfiguration —
57
+ * the caller should surface this rather than silently failing).
58
+ */
59
+ declare function resolveAgentId(registry: AgentRegistry, requestedId: string | undefined, defaultId: string | undefined): string | null;
60
+ /**
61
+ * Wrap a legacy single `Preset` into a single-profile registry. Used by
62
+ * `resolveConfig` when the host passed `preset` without `agents`, so older
63
+ * call sites keep working — they get a one-entry registry whose picker is
64
+ * a no-op (only one option).
65
+ */
66
+ declare function singleAgentRegistry(preset: Preset): AgentRegistry;
67
+ //#endregion
68
+ //#region src/chat/providers.d.ts
69
+ /**
70
+ * Structural model metadata — compatible with pi-ai's `Model` interface but
71
+ * not coupled to it, so hosts can pass either pi-ai-shaped objects or a
72
+ * custom registry of their own.
73
+ *
74
+ * Deliberately a structural duplicate of pi-ai's `Model` rather than a
75
+ * re-export: keeps the public API stable when pi-ai bumps shape, and lets
76
+ * hosts implement their own registry without depending on pi-ai's types.
77
+ *
78
+ * Lives here (rather than `./config`) because `ProviderDescriptor.models`
79
+ * needs it — pushing it to `config.tsx` created an import cycle.
80
+ */
81
+ interface ModelInfo {
82
+ id: string;
83
+ name?: string;
84
+ contextWindow: number;
85
+ maxTokens?: number;
86
+ reasoning?: boolean;
87
+ input?: readonly ('text' | 'image')[];
88
+ cost?: {
89
+ input: number;
90
+ output: number;
91
+ cacheRead?: number;
92
+ cacheWrite?: number;
93
+ };
94
+ provider?: string;
95
+ }
96
+ interface ProviderDescriptor {
97
+ /**
98
+ * Unique identifier. Used as the registry key, persisted in `state.json`
99
+ * as the resumed provider, and (by default) as the credential-file key.
100
+ */
101
+ key: string;
102
+ /** Display name shown in the TUI's provider picker and labels. */
103
+ label: string;
104
+ /**
105
+ * Factory that builds a fresh `Provider` instance. Called on every session
106
+ * activation. Some factories (e.g. zidane's built-in `anthropic`) eagerly
107
+ * resolve credentials at construction time and throw when none are
108
+ * configured — set {@link defaultModel} on the descriptor to avoid the TUI
109
+ * calling the factory before the user has picked + authed a provider.
110
+ */
111
+ factory: () => Provider;
112
+ /**
113
+ * Default model id to seed the picker with. When omitted, the TUI falls
114
+ * back to `descriptor.factory().meta.defaultModel`, which constructs the
115
+ * provider — fine for lazy-credential factories, but breaks for factories
116
+ * that throw on missing credentials before the wizard runs. Setting this
117
+ * eagerly lets the TUI render the auth wizard without ever instantiating
118
+ * the provider.
119
+ */
120
+ defaultModel?: string;
121
+ /**
122
+ * Env var checked when detecting whether the user has an API key
123
+ * configured for this provider. Optional — set to `undefined` when the
124
+ * provider only supports OAuth (or only credentials via a custom path).
125
+ */
126
+ envKey?: string;
127
+ /**
128
+ * Key under which credentials live in `credentials.json`. Defaults to
129
+ * `key`. The only built-in that overrides this is OpenAI Codex
130
+ * (`openai` → `openai-codex`) to stay compatible with the harness
131
+ * provider's existing lookup.
132
+ */
133
+ credentialFileKey?: string;
134
+ /** Placeholder shown in the wizard's API-key input. */
135
+ apiKeyPlaceholder?: string;
136
+ /**
137
+ * pi-ai (or compat) OAuth provider. When present, the wizard offers an
138
+ * OAuth option in addition to API key.
139
+ */
140
+ oauthProvider?: OAuthProviderInterface;
141
+ /**
142
+ * Optional copy appended to the wizard's "OAuth" method description.
143
+ * Use to communicate why a user might pick OAuth (e.g. subscription tier,
144
+ * org-wide SSO). Shown after `browser-based sign-in`. Skip the leading
145
+ * space — the wizard adds it. Example: `'Claude Pro/Max subscription'`.
146
+ */
147
+ oauthHint?: string;
148
+ /**
149
+ * pi-ai provider id used to look up models in pi-ai's built-in registry.
150
+ * Defaults to `key`. Only Codex differs (`openai` → `openai-codex`).
151
+ */
152
+ piProviderId?: string;
153
+ /**
154
+ * Override the model list returned for this provider's picker. When set,
155
+ * skips pi-ai's registry entirely. Useful for hosts maintaining their
156
+ * own model catalogue or for custom providers pi-ai doesn't know about.
157
+ */
158
+ models?: readonly ModelInfo[];
159
+ }
160
+ /** Convenience accessor — returns `credentialFileKey ?? key`. */
161
+ declare function credKeyOf(desc: ProviderDescriptor): string;
162
+ /** Convenience accessor — returns `piProviderId ?? key`. */
163
+ declare function piIdOf(desc: ProviderDescriptor): string;
164
+ declare const anthropicDescriptor: ProviderDescriptor;
165
+ declare const openaiDescriptor: ProviderDescriptor;
166
+ declare const openrouterDescriptor: ProviderDescriptor;
167
+ declare const cerebrasDescriptor: ProviderDescriptor;
168
+ /**
169
+ * Default provider registry. Passed verbatim when `runTui` is invoked without
170
+ * an explicit `providers` option. Hosts that want to override per-provider
171
+ * metadata can spread this and replace specific entries:
172
+ *
173
+ * ```ts
174
+ * runTui({ providers: { ...BUILTIN_PROVIDERS, anthropic: myOwnAnthropicDescriptor } })
175
+ * ```
176
+ */
177
+ declare const BUILTIN_PROVIDERS: Readonly<Record<string, ProviderDescriptor>>;
178
+ /**
179
+ * Resolve the model list for a given provider. Honors `descriptor.models`
180
+ * when set; otherwise queries pi-ai via `descriptor.piProviderId`. Returns
181
+ * `[]` for descriptors with no known mapping (custom providers without a
182
+ * model list) — callers should hide the model picker in that case.
183
+ */
184
+ declare function modelsForDescriptor(descriptor: ProviderDescriptor): readonly ModelInfo[];
185
+ /**
186
+ * Look up the model's max context window via the descriptor's model source.
187
+ * Returns `null` when the model isn't known (custom slugs, providers without
188
+ * a registry); callers should hide the context indicator in that case.
189
+ */
190
+ declare function getContextWindow(descriptor: ProviderDescriptor, modelId: string): number | null;
191
+ //#endregion
192
+ //#region src/chat/auth.d.ts
193
+ /**
194
+ * Provider identifier as known to the TUI. Built-in keys are `anthropic`,
195
+ * `openai`, `openrouter`, `cerebras`, but hosts can register additional
196
+ * keys via {@link ProviderDescriptor} — so the type is open.
197
+ */
198
+ type ProviderKey = string;
199
+ interface AuthMethod {
200
+ source: 'env' | 'oauth' | 'apikey';
201
+ /** Human-readable detail (env var name, expiry timestamp, …). */
202
+ detail: string;
203
+ }
204
+ interface ProviderAuth {
205
+ key: ProviderKey;
206
+ label: string;
207
+ /** True when at least one credential source is present. */
208
+ available: boolean;
209
+ methods: AuthMethod[];
210
+ }
211
+ /**
212
+ * Detect available auth for every registered provider.
213
+ *
214
+ * Resolution order per provider (a method appears in `methods` for each
215
+ * layer that has a credential — the agent itself resolves them in the same
216
+ * order via its provider factories):
217
+ *
218
+ * 1. `kind: 'apikey'` from `credentials.json` (injected into env at TUI launch)
219
+ * 2. explicit env var (descriptor's `envKey`)
220
+ * 3. `kind: 'oauth'` from `credentials.json` (or legacy `cwd/.credentials.json`)
221
+ *
222
+ * Pure read — never refreshes or rewrites the credentials file.
223
+ */
224
+ declare function detectAuth(dataDir: string, registry: Readonly<Record<string, ProviderDescriptor>>, env?: Record<string, string | undefined>): ProviderAuth[];
225
+ //#endregion
226
+ //#region src/chat/completion.d.ts
227
+ /**
228
+ * Prompt autocompletion framework.
229
+ *
230
+ * Renderer-agnostic. Providers plug in by registering a `trigger` character
231
+ * (e.g. `/` for skills, `@` for files) and exposing two operations:
232
+ *
233
+ * 1. `suggest(query)` — return ranked items for the live query.
234
+ * 2. `parseReferences(text)` — find all references to the provider's
235
+ * items in arbitrary text. Used to highlight in-prompt mentions and
236
+ * drive submit-time side effects (activate the skill, attach the
237
+ * file, …).
238
+ *
239
+ * The TUI consumes `useCompletion()` to drive a popover above the textarea.
240
+ * A future GUI consumes the same hook to drive a dropdown. The popup
241
+ * component itself only reads `label` + `description` on each item, so
242
+ * provider-specific typing (`TItem`) stays at the registration boundary
243
+ * and never leaks into the renderer.
244
+ */
245
+ /**
246
+ * A discoverable, selectable thing — one row in the autocomplete popover.
247
+ * `TItem` is provider-specific; consumers can inspect `data` when they
248
+ * need the originating payload (e.g. the full `SkillConfig` for tooltips).
249
+ */
250
+ interface CompletionItem<TItem = unknown> {
251
+ /** Stable identifier within the provider. Used as React key + selection equality. */
252
+ id: string;
253
+ /** User-visible primary string ("research"). */
254
+ label: string;
255
+ /** Optional one-line secondary string ("In-depth research with citations"). */
256
+ description?: string;
257
+ /**
258
+ * Text that replaces the active span (trigger + query) on commit. Usually
259
+ * `${trigger}${label}` with a trailing space so the cursor lands ready
260
+ * for the next token.
261
+ */
262
+ insertText: string;
263
+ /** Original provider-specific payload. */
264
+ data: TItem;
265
+ }
266
+ /**
267
+ * A reference to a provider item inside arbitrary prompt text. Producers:
268
+ * `provider.parseReferences(text)`. Consumers: the TUI for highlighting,
269
+ * the run flow for "activate every referenced skill before agent.run()".
270
+ *
271
+ * Spans are half-open `[start, end)` codepoint offsets into the source
272
+ * string. Overlapping spans from the same or different providers are
273
+ * caller-resolved — the helpers below ship a "first wins" merger.
274
+ */
275
+ interface CompletionReference<TItem = unknown> {
276
+ providerId: string;
277
+ start: number;
278
+ end: number;
279
+ itemId: string;
280
+ data: TItem;
281
+ }
282
+ /**
283
+ * Provider contract. Implementations decide their own ranking, fuzzy-match
284
+ * rules, async loading behavior, and reference grammar.
285
+ */
286
+ interface CompletionProvider<TItem = unknown> {
287
+ /** Stable id used for tagging references + React keys. */
288
+ id: string;
289
+ /**
290
+ * Single character that activates this provider. The engine considers a
291
+ * trigger "active" when it appears at the start of the buffer or
292
+ * immediately after whitespace, and is not closed by whitespace before
293
+ * the cursor (so a trigger plus query is a contiguous token).
294
+ */
295
+ trigger: string;
296
+ /** Human-readable name. Reserved for future multi-provider popover headers. */
297
+ label: string;
298
+ /**
299
+ * Returns items for the active `query` (the text between the trigger and
300
+ * the cursor, excluding the trigger itself). Synchronous return is the
301
+ * common case; promises let providers paginate or hit a backend.
302
+ *
303
+ * `signal` is aborted when the query changes or the popover closes —
304
+ * use it to cancel in-flight network calls.
305
+ */
306
+ suggest: (query: string, ctx: CompletionContext, signal: AbortSignal) => CompletionItem<TItem>[] | Promise<CompletionItem<TItem>[]>;
307
+ /**
308
+ * Find every reference to this provider's items in `text`. Pure: must not
309
+ * mutate ctx. The TUI calls this on every keystroke for highlighting, so
310
+ * keep it cheap (linear scan, no I/O).
311
+ */
312
+ parseReferences: (text: string, ctx: CompletionContext) => CompletionReference<TItem>[];
313
+ }
314
+ /**
315
+ * Read-only view of the active prompt buffer + cursor passed to provider
316
+ * callbacks. Kept minimal so providers stay portable across renderers.
317
+ */
318
+ interface CompletionContext {
319
+ /** Full prompt text. */
320
+ text: string;
321
+ /** Codepoint offset of the cursor (0-based). */
322
+ cursor: number;
323
+ }
324
+ /**
325
+ * Identified active trigger span. Returned by `findActiveTrigger` so
326
+ * callers can show the popover, query the provider, and on commit replace
327
+ * the span with the selected item's `insertText`.
328
+ */
329
+ interface ActiveTrigger<TItem = unknown> {
330
+ provider: CompletionProvider<TItem>;
331
+ /** Substring after the trigger, up to the cursor. Empty if cursor sits right after the trigger. */
332
+ query: string;
333
+ /** `[start, end)` — span covered by the trigger + query in the source. */
334
+ span: {
335
+ start: number;
336
+ end: number;
337
+ };
338
+ }
339
+ /**
340
+ * Resolve the provider trigger active at `cursor`, or `null` when none fits.
341
+ *
342
+ * Rules:
343
+ * - The trigger character must sit at position 0 of the buffer OR be
344
+ * preceded by whitespace. This prevents `http://` from triggering the
345
+ * `/`-bound skills provider mid-URL.
346
+ * - The cursor must be at or past the trigger position.
347
+ * - Nothing between the trigger and the cursor may be whitespace (the
348
+ * query is one contiguous token).
349
+ * - The query length is bounded — `maxQueryLength` defaults to 64 — so
350
+ * a runaway buffer scan can't pin the renderer.
351
+ */
352
+ declare function findActiveTrigger<TItem>(text: string, cursor: number, providers: readonly CompletionProvider<TItem>[], options?: {
353
+ maxQueryLength?: number;
354
+ }): ActiveTrigger<TItem> | null;
355
+ /**
356
+ * Replace `[span.start, span.end)` in `text` with `insertText`. Returns the
357
+ * mutated text and the new cursor position (end of insertion).
358
+ */
359
+ declare function applyInsert(text: string, span: {
360
+ start: number;
361
+ end: number;
362
+ }, insertText: string): {
363
+ text: string;
364
+ cursor: number;
365
+ };
366
+ /**
367
+ * Merge reference lists from multiple providers into one ordered list with
368
+ * earlier-start-wins disambiguation when spans overlap. Ties broken by
369
+ * insertion order. Spans are sorted ascending so renderers can walk them
370
+ * sequentially with a cursor through the source string.
371
+ */
372
+ declare function mergeReferences<TItem>(refs: readonly CompletionReference<TItem>[]): CompletionReference<TItem>[];
373
+ /**
374
+ * Collect every provider's references in one pass. Convenience wrapper —
375
+ * the TUI textarea component calls this on every keystroke to highlight
376
+ * in-prompt mentions.
377
+ */
378
+ declare function collectReferences<TItem>(text: string, providers: readonly CompletionProvider<TItem>[], cursor?: number): CompletionReference<TItem>[];
379
+ /** State surface returned by `useCompletion()`. */
380
+ interface CompletionState<TItem = unknown> {
381
+ /** Active trigger, or null when the cursor doesn't sit in a completable span. */
382
+ active: ActiveTrigger<TItem> | null;
383
+ /** Items for the active query. Empty when no trigger is active. */
384
+ items: readonly CompletionItem<TItem>[];
385
+ /** True while the provider's `suggest` promise is pending. */
386
+ loading: boolean;
387
+ /** Index of the highlighted item inside `items`. */
388
+ selectedIndex: number;
389
+ /** Move the highlight. Wraps at the ends. No-op when `items` is empty. */
390
+ selectNext: () => void;
391
+ selectPrev: () => void;
392
+ /**
393
+ * Commit the highlighted item. Returns the new text + cursor pair, or
394
+ * `null` when there's nothing to commit (no active trigger, empty list).
395
+ */
396
+ commit: () => {
397
+ text: string;
398
+ cursor: number;
399
+ } | null;
400
+ /** Force-close the popover until the user types again. */
401
+ dismiss: () => void;
402
+ /** All references in the current buffer, regardless of provider. */
403
+ references: readonly CompletionReference<TItem>[];
404
+ }
405
+ /**
406
+ * Drive a prompt-completion popover from React state.
407
+ *
408
+ * Inputs are pull-style — the caller owns `text` + `cursor` (typically
409
+ * mirroring an `OpenTUI TextareaRenderable` or a `<textarea>` element) and
410
+ * passes them in each render. Providers are matched by their `trigger`
411
+ * character; the engine picks at most one active provider per cursor
412
+ * position.
413
+ *
414
+ * Asynchronous suggest calls are aborted when the query changes or the
415
+ * popover closes, so providers that hit a backend don't leak.
416
+ */
417
+ declare function useCompletion<TItem = unknown>(input: {
418
+ text: string;
419
+ cursor: number;
420
+ }, providers: readonly CompletionProvider<TItem>[], options?: {
421
+ maxQueryLength?: number;
422
+ }): CompletionState<TItem>;
423
+ //#endregion
424
+ //#region src/chat/types.d.ts
425
+ type Screen = 'auth' | 'sessions' | 'chat';
426
+ /** Identifies the agent that produced a streaming event. */
427
+ type Owner = 'parent' | string;
428
+ interface StreamEvent {
429
+ kind: 'thinking' | 'tool' | 'tool-result' | 'error'
430
+ /**
431
+ * Echo of a submitted user prompt — the `❯` chevron block in the
432
+ * transcript. Distinct from `'info'` (generic informational text)
433
+ * so consumers can count user messages and rebuild prompt history
434
+ * without filtering by text-prefix regex.
435
+ *
436
+ * `text` is the **raw** prompt without the `❯ ` prefix; renderers
437
+ * prepend the chevron. `refs` offsets are aligned to this raw text.
438
+ */
439
+ | 'user-prompt'
440
+ /**
441
+ * Generic informational banner — status notice, transient message.
442
+ * Reserved for non-user content; user prompts use `'user-prompt'`.
443
+ */
444
+ | 'info' | 'separator' | 'markdown' | 'spawn-start' | 'spawn-end';
445
+ text: string;
446
+ /**
447
+ * For `markdown` events: true while the block is still receiving deltas.
448
+ * Renderers keep their markdown parser in streaming mode while this is
449
+ * true (OpenTUI's `<markdown streaming>` leaves the trailing block
450
+ * unstable to absorb tokens as they arrive). Flipped to false on
451
+ * `turn:after`.
452
+ */
453
+ streaming?: boolean;
454
+ /** Subagent that produced this event. Absent / 'parent' = top-level agent. */
455
+ childId?: string;
456
+ /** Nesting depth — 0 = parent, ≥ 1 = subagent (matches zidane's spawn depth). */
457
+ depth?: number;
458
+ /**
459
+ * Canonical tool name for `tool` / `tool-result` events. Lets the renderer
460
+ * filter by tool — e.g. hide the parent's `spawn` tool-result when
461
+ * `hideSubagentOutput` is on, since the spawn-end marker already shows the
462
+ * same stats. Absent for non-tool events.
463
+ */
464
+ tool?: string;
465
+ /**
466
+ * Highlighted spans within `text`, in source order. Used by the renderer
467
+ * to colorize completion references in submitted prompts (`user-prompt`
468
+ * events). Provider-agnostic — the renderer only reads `start`, `end`,
469
+ * `providerId`. Spans are half-open `[start, end)`; overlapping spans
470
+ * are caller-resolved before reaching here. Field name matches
471
+ * `CompletionReference.providerId` and `PromptSegment.providerId` so
472
+ * the same identifier flows end-to-end.
473
+ */
474
+ refs?: readonly {
475
+ start: number;
476
+ end: number;
477
+ providerId: string;
478
+ }[];
479
+ /**
480
+ * `SessionTurn.id` the event was emitted by — set both on historical
481
+ * events synthesized in `eventsFromTurns` and on live events tagged by
482
+ * the agent hooks (via `StreamHookContext.turnId` / `ToolHookContext.turnId`).
483
+ * Drives the TUI's "select turn" mode: each turn is addressable as a
484
+ * highlightable group of events.
485
+ *
486
+ * Absent on synthetic events that don't map to a turn (`spawn-start`,
487
+ * `spawn-end`, `separator`, etc.) and on events emitted before the
488
+ * first `turn:before` fires on a freshly-mounted session.
489
+ */
490
+ turnId?: string;
491
+ }
492
+ interface Picked {
493
+ provider: ProviderAuth;
494
+ model: string;
495
+ }
496
+ interface SessionMeta {
497
+ id: string;
498
+ title: string;
499
+ /** Total turns (user + assistant + system). */
500
+ turnCount: number;
501
+ /** Count of `role: 'user'` turns — the volume of human messages. */
502
+ userMessageCount: number;
503
+ /** Top-level runs recorded against the session (one per `agent.run()` call). */
504
+ runCount: number;
505
+ /**
506
+ * Project this session was created under (see {@link SessionData.projectRoot}).
507
+ * Surfaced on the meta row so the sessions screen can show a
508
+ * per-project label when `Settings.showAllProjects` is on. Absent
509
+ * for legacy pre-tagging sessions.
510
+ */
511
+ projectRoot?: string;
512
+ updatedAt: number;
513
+ }
514
+ /** Persisted, user-toggleable transcript filters and modes. */
515
+ interface Settings {
516
+ showThinking: boolean;
517
+ showToolCalls: boolean;
518
+ showToolResults: boolean;
519
+ /**
520
+ * Safe mode — when enabled, every tool call requires explicit user
521
+ * approval unless it's covered by the project safelist (`projects.json`)
522
+ * or the implicit read-only allow-list. Default: on.
523
+ */
524
+ safeMode: boolean;
525
+ /**
526
+ * Hide a subagent's internal events (its streamed markdown, thinking,
527
+ * tool calls, and tool results) from the transcript. The `🌱` start and
528
+ * `✓` end markers stay visible so the user still sees that a subagent
529
+ * is working and when it finished. Default: on — subagent runs are
530
+ * usually noisy and the parent's final response already summarizes them.
531
+ *
532
+ * When off, those events are visible and wrapped in a dim bordered box
533
+ * for clear visual hierarchy.
534
+ */
535
+ hideSubagentOutput: boolean;
536
+ /**
537
+ * Active theme id — looked up in `BUILTIN_THEMES` to resolve the palette,
538
+ * select styling, syntax highlight tokens, etc. Default: `'default'`.
539
+ * Unknown ids fall back to `DEFAULT_THEME` rather than throwing.
540
+ */
541
+ theme: string;
542
+ /**
543
+ * Show sessions from every project (and pre-tagging legacy ones)
544
+ * in the sessions list, instead of filtering to the current
545
+ * project. Off by default — each project shows only its own
546
+ * conversations. Flip on to inspect / jump across projects without
547
+ * leaving the TUI. Per-row project labels appear when on.
548
+ */
549
+ showAllProjects: boolean;
550
+ /**
551
+ * Allowlist of skill names to expose to the agent + slash-command picker.
552
+ * `undefined` means "every discovered skill" (default). An empty array
553
+ * fully disables the skills subsystem (no scan, no tool injection).
554
+ */
555
+ enabledSkills?: readonly string[];
556
+ /**
557
+ * Allowlist of MCP server names (from `.{prefix}/mcps.json`). Same
558
+ * semantics as `enabledSkills`: `undefined` enables every discovered
559
+ * server; `[]` disables all.
560
+ */
561
+ enabledMcps?: readonly string[];
562
+ }
563
+ //#endregion
564
+ //#region src/chat/store.d.ts
565
+ interface TuiState {
566
+ lastProvider?: ProviderKey;
567
+ lastSessionId?: string;
568
+ /** Per-provider last-used model id. */
569
+ lastModelByProvider?: Partial<Record<ProviderKey, string>>;
570
+ /**
571
+ * Last-active agent profile id (see {@link AgentRegistry}). Resumed on
572
+ * launch so a returning user lands back in the same mode (Build / Plan /
573
+ * a host profile). Falls back to the host's `defaultAgent` then the first
574
+ * registry key if the id is no longer registered.
575
+ */
576
+ lastAgent?: string;
577
+ /** User-toggled transcript filters. Persisted so they outlive a launch. */
578
+ settings?: Partial<Settings>;
579
+ }
580
+ interface StateStoreApi {
581
+ load: () => TuiState;
582
+ save: (state: TuiState) => void;
583
+ }
584
+ declare function createStateStore(path: string): StateStoreApi;
585
+ declare function loadState(path: string): TuiState;
586
+ declare function saveState(path: string, state: TuiState): void;
587
+ /**
588
+ * Load every session and project it to the compact `SessionMeta` shape used by
589
+ * the picker. Sorted by recency via the underlying store's `list()` contract
590
+ * (sqlite store returns by `updated_at DESC`).
591
+ *
592
+ * Robust to per-row failures: `Promise.allSettled` so a single corrupt or
593
+ * unreadable row (malformed JSON, partial write, transient I/O error)
594
+ * doesn't take down the entire picker. Failed rows are silently skipped;
595
+ * a stderr line is emitted under `ZIDANE_DEBUG` for diagnosis.
596
+ */
597
+ declare function listSessionMeta(store: SessionStore, filter?: {
598
+ /**
599
+ * Restrict to sessions belonging to this project. Omit to ignore
600
+ * the axis; pass `null` to ask for untagged (legacy) sessions
601
+ * specifically. The TUI defaults to passing the current git root /
602
+ * cwd here so each project sees only its own conversations.
603
+ */
604
+ projectRoot?: string | null;
605
+ }): Promise<SessionMeta[]>;
606
+ /** Derive a short title from the first user message — returns null when empty. */
607
+ declare function titleFromTurns(turns: SessionTurn[]): string | null;
608
+ /**
609
+ * Display title for a session — preferred sources, in order:
610
+ *
611
+ * 1. `metadata.title` if it's a non-empty string (typically set by
612
+ * the session-details modal's "generate title" action).
613
+ * 2. {@link titleFromTurns} — the first user message, one-line + clipped.
614
+ * 3. The literal `'untitled'`.
615
+ *
616
+ * Total / pure / defensive on non-string metadata values.
617
+ */
618
+ declare function deriveSessionTitle(turns: SessionTurn[], metadata?: Record<string, unknown>): string;
619
+ /**
620
+ * Replay persisted turns as a viewable transcript. Mirrors the event shape
621
+ * produced live by the agent hooks so loaded and streaming history render
622
+ * identically — including subagent ancestry when `runs` is supplied.
623
+ *
624
+ * Subagent reconstruction:
625
+ * - Every turn carries a `runId`. We look that up in `runs` to get the
626
+ * run's `depth` and tag the resulting events with `{ depth, childId }`
627
+ * — the same shape the live `child:*` bubble hooks produce.
628
+ * - We synthesize `spawn-start` / `spawn-end` markers at each child-run
629
+ * boundary so the transcript reads the same as a live run did
630
+ * (`🌱 [run-id] task` … child events … `🌳 [run-id] done · tokens`).
631
+ * - For child runs (`depth > 0`), the user-role "task" text is suppressed
632
+ * because `spawn-start` already shows it.
633
+ *
634
+ * Without `runs` (legacy callers / tests), the function falls back to the
635
+ * old behavior: depth-0 events with no subagent grouping.
636
+ */
637
+ declare function eventsFromTurns(turns: SessionTurn[], runs?: readonly SessionRun[]): StreamEvent[];
638
+ /** Shared formatter for the `↳ name(args)` line shown on tool calls. */
639
+ declare function toolCallPreview(name: string, input: Record<string, unknown>): string;
640
+ /** Render tool output as plain text, whether it's a string or structured content. */
641
+ declare function toolResultText(output: string | ToolResultContent[]): string;
642
+ /**
643
+ * Strip the `Tokens: …` line from a spawn tool-result. The spawn-end marker
644
+ * displayed right above already shows the same stats; keeping the line in the
645
+ * rendered tool-result body just produces a visible duplicate (and, on
646
+ * reloaded pre-fix sessions, an *inconsistent* duplicate — the persisted line
647
+ * uses the old `13 in / 4075 out` shape while the freshly synthesized
648
+ * spawn-end uses the cache-aware `in 92615 (cache 92602) / 4075 out` shape).
649
+ *
650
+ * Display-only: the persisted tool_result content is untouched, so the LLM
651
+ * still sees the full string in its context window. Anchored to start-of-line
652
+ * and matches both `Tokens: 13 in / 4075 out` (legacy) and `Tokens: in 13 …`
653
+ * (post-`formatTokenUsage`) shapes.
654
+ */
655
+ declare function stripSpawnTokensLine(text: string): string;
656
+ /**
657
+ * Deduplicated, in-order list of **parent-conversation** turn ids that appear
658
+ * in a rendered transcript — the navigation index for the TUI's select-turn
659
+ * mode. Subagent (`childId` set) events are deliberately skipped:
660
+ *
661
+ * - With `hideSubagentOutput: true` (default), child events are filtered
662
+ * out of the transcript by `isVisible`, so allowing the user to "select"
663
+ * them would highlight nothing and scroll to nowhere.
664
+ * - With `hideSubagentOutput: false`, child events are visible but they're
665
+ * nested execution detail; the user's mental model of a "message" is
666
+ * the conversational exchange, not each spawn turn.
667
+ *
668
+ * Synthetic events (separator, spawn-start, spawn-end) have no `turnId` and
669
+ * are skipped naturally. Pure function over the event stream — no settings
670
+ * dependency, no host concerns — so it composes the same in TUI / SDK
671
+ * consumers.
672
+ */
673
+ declare function selectableTurnIds(events: readonly StreamEvent[]): string[];
674
+ /** Effective context size of the most recent assistant turn — drives the footer indicator. */
675
+ /**
676
+ * Walk from the end of `turns` and return the cache-aware input-token total
677
+ * of the most recent **parent** (depth-0) assistant turn. Subagent turns
678
+ * are skipped because their context window is the child's, not the parent's
679
+ * — surfacing a subagent's `usage.input` as the footer's "context used"
680
+ * after a session ends mid-spawn would be misleading. The next prompt
681
+ * feeds the parent, so the parent's last view is what matters.
682
+ *
683
+ * `runs` is optional for backwards compatibility (older call sites and
684
+ * tests that don't have ancestry info). Without it, this falls back to the
685
+ * pre-fix behavior — depth is unknown so every assistant turn qualifies.
686
+ */
687
+ declare function lastContextSizeFromTurns(turns: SessionTurn[], runs?: readonly SessionRun[]): number;
688
+ //#endregion
689
+ //#region src/chat/config.d.ts
690
+ /**
691
+ * Provider registry — a map keyed by `descriptor.key`. Passed verbatim to the
692
+ * chat engine; there is no implicit merge with built-ins. Hosts that want the
693
+ * four default providers spread {@link BUILTIN_PROVIDERS}; hosts that only
694
+ * want their own pass exactly their own.
695
+ */
696
+ type ProviderRegistry = Readonly<Record<string, ProviderDescriptor>>;
697
+ /**
698
+ * Options accepted by `resolveConfig()` (and, transitively, by `runTui()` and
699
+ * any future GUI launcher). Every field is optional — defaults boot a working
700
+ * chat against the built-in providers with sessions stored under `~/.zidane/`.
701
+ */
702
+ interface ChatOptions {
703
+ /**
704
+ * Directory name used under `storageDir` for sessions + state.
705
+ * Default: `'.zidane'` → `~/.zidane/sessions.db` + `~/.zidane/state.json`.
706
+ * Pass e.g. `'.myapp'` for `~/.myapp/...`, or `'myapp'` for a visible dir.
707
+ */
708
+ prefix?: string;
709
+ /**
710
+ * Storage root. Defaults to the user's home directory. Combined with
711
+ * `prefix` to form the data directory.
712
+ */
713
+ storageDir?: string;
714
+ /**
715
+ * Provider registry. Each value is a {@link ProviderDescriptor} carrying
716
+ * label + factory + credential metadata. **No automatic merge** — hosts
717
+ * pass exactly what they want.
718
+ *
719
+ * - Omitted → {@link BUILTIN_PROVIDERS} (anthropic + openai + openrouter + cerebras).
720
+ * - `providers: BUILTIN_PROVIDERS` → same as omitted, but explicit.
721
+ * - `providers: { anthropic: anthropicDescriptor }` → only Anthropic.
722
+ * - `providers: { ...BUILTIN_PROVIDERS, mine: customDescriptor }` → built-ins + custom.
723
+ * - `providers: { mine: customDescriptor }` → custom-only, **no built-ins**.
724
+ */
725
+ providers?: ProviderRegistry;
726
+ /**
727
+ * Legacy single-agent preset (tools, system prompt, behavior). When set
728
+ * **without** {@link ChatOptions.agents}, the resolver wraps this preset
729
+ * into a one-entry {@link AgentRegistry} keyed `default` so existing
730
+ * callers keep working and the picker is effectively hidden.
731
+ *
732
+ * Prefer `agents` for any multi-profile setup. Passing both throws.
733
+ */
734
+ preset?: Preset;
735
+ /**
736
+ * Agent profile registry — keyed by `profile.id`. Each profile bundles a
737
+ * preset with display metadata (label, description, accent). The TUI
738
+ * shows a picker (Ctrl+A) when more than one profile is registered.
739
+ *
740
+ * - Omitted (and `preset` omitted) → {@link BUILTIN_AGENTS} (Build + Plan).
741
+ * - Omitted but `preset` provided → single-entry registry around the preset.
742
+ * - Provided → host owns the registry; pass exactly what you want.
743
+ *
744
+ * Hosts mixing built-ins with their own typically spread:
745
+ * `agents: { ...BUILTIN_AGENTS, debug: myDebugProfile }`.
746
+ */
747
+ agents?: AgentRegistry;
748
+ /**
749
+ * Id of the profile activated on first launch. Resolved against `agents`;
750
+ * unknown ids fall through to the registry's first key. Persisted
751
+ * `state.lastAgent` overrides this on subsequent launches.
752
+ */
753
+ defaultAgent?: string;
754
+ /**
755
+ * Session store — either an instance or a factory called with the
756
+ * resolved storage paths. **Required** at the chat layer so this module
757
+ * stays platform-agnostic (no `bun:sqlite` baked in). Terminal hosts use
758
+ * `createTuiStore` from `zidane/session/sqlite`; a future GUI host can
759
+ * supply a different adapter (IndexedDB, remote API, in-memory) without
760
+ * touching this layer.
761
+ *
762
+ * ```ts
763
+ * import { createTuiStore } from 'zidane/session/sqlite'
764
+ *
765
+ * // Either pass a factory…
766
+ * resolveConfig({ store: paths => createTuiStore(paths.db) })
767
+ *
768
+ * // …or an instance built ahead of time.
769
+ * const store = createTuiStore('/path/to/sessions.db')
770
+ * resolveConfig({ store })
771
+ * ```
772
+ */
773
+ store: SessionStore | ((paths: ResolvedPaths) => SessionStore);
774
+ /**
775
+ * Project-scoped session storage. When `true` (default), launching
776
+ * inside a git repo auto-creates `<git-root>/.{prefix}/` and stores
777
+ * `sessions.db` + `state.json` there — so sessions, mcps.json, and
778
+ * skills all live alongside the project they belong to. Credentials
779
+ * and the cross-project safelist stay at `~/.{prefix}/` regardless.
780
+ *
781
+ * Precedence: `options.projectDb` > `~/.{prefix}/config.json`
782
+ * `projectDb` > `true`. The env var `ZIDANE_PROJECT_DB=0` flips it
783
+ * off too, for one-shot CLI invocations.
784
+ *
785
+ * When `false`, OR when not inside a git repo, everything lives at
786
+ * `~/.{prefix}/` — the classic single-store layout.
787
+ */
788
+ projectDb?: boolean;
789
+ /**
790
+ * Override for the project root. Defaults to `process.cwd()`. Hosts
791
+ * embedding the TUI from a non-CLI context (tests, daemons) can pin
792
+ * the cwd here so the git-root walk produces a stable result. Has no
793
+ * effect when `projectDb` resolves to `false`.
794
+ */
795
+ cwd?: string;
796
+ }
797
+ /** Resolved on-disk layout produced by {@link resolveConfig}. */
798
+ interface ResolvedPaths {
799
+ /**
800
+ * Effective data root — equals `userDir` when project mode is off,
801
+ * `projectDir` when it's on. Kept for callers that wrote against the
802
+ * pre-project-db API; new code should reference `userDir` /
803
+ * `projectDir` / the explicit `db` / `state` paths instead.
804
+ */
805
+ dir: string;
806
+ /**
807
+ * User-scoped data root. Always `<storageDir>/<prefix>` (default
808
+ * `~/.zidane/`). Credentials, the project-keyed safelist, and the
809
+ * user-level `config.json` live here regardless of project mode —
810
+ * they MUST NOT leak into a checked-in project directory.
811
+ */
812
+ userDir: string;
813
+ /**
814
+ * Project-scoped data root. Set to `<git-root>/<prefix>` when project
815
+ * mode resolved to ON and a git root was found. `null` otherwise.
816
+ */
817
+ projectDir: string | null;
818
+ /** Resolved `sessions.db` path. Lives under `projectDir` when active, else `userDir`. */
819
+ db: string;
820
+ /** Resolved `state.json` path. Same scoping rule as `db`. */
821
+ state: string;
822
+ }
823
+ interface ResolvedConfig {
824
+ prefix: string;
825
+ storageDir: string;
826
+ paths: ResolvedPaths;
827
+ providers: ProviderRegistry;
828
+ /**
829
+ * Resolved profile registry. Always non-empty; the resolver throws when
830
+ * the host passes an empty `agents` map (same contract as `providers`).
831
+ */
832
+ agents: AgentRegistry;
833
+ /** Id of the profile to activate on mount. Guaranteed to key into `agents`. */
834
+ initialAgentId: string;
835
+ store: SessionStore;
836
+ stateStore: StateStoreApi;
837
+ /** Lookup by `ProviderKey` returning the available models for the picker. */
838
+ modelsFor: (key: ProviderKey) => readonly ModelInfo[];
839
+ initialState: TuiState;
840
+ initialSettings: Partial<Settings>;
841
+ resumeProvider: ProviderAuth | null;
842
+ initialPicked: Picked | null;
843
+ }
844
+ /** Resolve user options into a fully-bound runtime config. Pure aside from disk reads. */
845
+ declare function resolveConfig(options: ChatOptions): ResolvedConfig;
846
+ //#endregion
847
+ //#region src/chat/enabled-toggle-set.d.ts
848
+ /**
849
+ * Renderer-agnostic state machine for an "enabled allowlist" — the shape
850
+ * used by `settings.enabledSkills` / `settings.enabledMcps` (and any future
851
+ * `enabledX` toggle backed by a `Settings` field).
852
+ *
853
+ * Semantics, kept identical across all three call sites:
854
+ * - `undefined` → every catalog entry is enabled (default — user has
855
+ * never opened the picker; new entries flow in).
856
+ * - `[]` → the whole subsystem is off.
857
+ * - `[names]` → explicit allowlist; the persisted shape stays a
858
+ * concrete array once the user has toggled anything.
859
+ *
860
+ * The hook exposes a live `enabledSet` (Set<string>) + a `toggle(name)`
861
+ * callback that persists the result through `useSettings().setSetting`.
862
+ * The first toggle seeds the persisted allowlist from the current catalog
863
+ * so newly-added entries don't silently drop on the next launch.
864
+ *
865
+ * Renderer-neutral: works for the TUI's `<ToggleListModal>`, a GUI
866
+ * checkbox list, a CLI flag tool. Hook tests live alongside the chat
867
+ * suite; the rendering layer is tested where it lives.
868
+ */
869
+ /** Settings keys whose value type is `readonly string[] | undefined`. */
870
+ type EnabledAllowlistKey = 'enabledSkills' | 'enabledMcps';
871
+ interface EnabledToggleSet {
872
+ /** Live set of enabled names — `Set` for O(1) `has`. */
873
+ enabledSet: ReadonlySet<string>;
874
+ /** Toggle one name on/off; persists immediately via `setSetting`. */
875
+ toggle: (name: string) => void;
876
+ }
877
+ /**
878
+ * Bind an "enabled allowlist" setting to a discovered catalog.
879
+ *
880
+ * `keyOf` extracts the persisted identity from a catalog entry (skill name,
881
+ * MCP server name, …). Pass a stable, collision-free key — the persisted
882
+ * allowlist is keyed against it forever.
883
+ */
884
+ declare function useEnabledToggleSet<T>(opts: {
885
+ catalog: readonly T[];
886
+ keyOf: (entry: T) => string;
887
+ settingKey: EnabledAllowlistKey;
888
+ }): EnabledToggleSet;
889
+ //#endregion
890
+ //#region src/chat/mcps-discovery.d.ts
891
+ /**
892
+ * One entry in the discovered list. `path` is the source file so a Settings
893
+ * picker can show "Defined in ~/.zidane/mcps.json" tooltips.
894
+ */
895
+ interface DiscoveredMcp {
896
+ config: McpServerConfig;
897
+ source: 'project' | 'user';
898
+ path: string;
899
+ }
900
+ /**
901
+ * Search order for `mcps.json` — see {@link projectUserPaths}. Project
902
+ * beats user; the first file found for each (name) wins. Non-existent
903
+ * files are skipped without error.
904
+ */
905
+ declare function defaultMcpsConfigPaths(opts?: {
906
+ cwd?: string;
907
+ home?: string;
908
+ prefix?: string;
909
+ }): {
910
+ path: string;
911
+ source: 'project' | 'user';
912
+ }[];
913
+ /**
914
+ * Parse one `mcps.json` file. Accepts:
915
+ * - A raw `McpServerConfig[]` array — host-SDK convention.
916
+ * - An object with `{ "mcpServers": { name: {...} } }` — Claude Desktop
917
+ * + many client wrappers. The `mcpServers` value is unwrapped before
918
+ * normalization (otherwise `normalizeMcpServers` would treat the whole
919
+ * wrapper as a single server).
920
+ * - A name-keyed map (`{ fs: {...}, github: {...} }`) — host-SDK
921
+ * convenience shape.
922
+ *
923
+ * Validation flows through `normalizeMcpServers` so the result matches
924
+ * what `createAgent` accepts. Throws on malformed JSON; the caller decides
925
+ * whether to surface or swallow.
926
+ */
927
+ declare function parseMcpsFile(text: string): McpServerConfig[];
928
+ /**
929
+ * Walk the default config paths, parse every file that exists, and return
930
+ * `DiscoveredMcp[]` in source-priority order. Project entries appear
931
+ * before user entries; first occurrence of a `name` wins (later
932
+ * duplicates dropped).
933
+ *
934
+ * Parse errors are logged under `ZIDANE_DEBUG` and the file skipped so a
935
+ * single malformed `mcps.json` can't take down the picker.
936
+ */
937
+ declare function discoverProjectMcps(opts?: {
938
+ cwd?: string;
939
+ home?: string;
940
+ prefix?: string;
941
+ }): DiscoveredMcp[];
942
+ /**
943
+ * Map a user-toggled enable list onto the `mcpServers` array the agent
944
+ * receives. Conventions match `buildSkillsConfig`:
945
+ *
946
+ * - `enabled === undefined` → every discovered server enabled (default).
947
+ * - `enabled === []` → no servers (the agent runs MCP-less).
948
+ * - `enabled === [names]` → allowlist; servers not in the list are
949
+ * dropped.
950
+ *
951
+ * Returns a fresh array — callers can mutate without affecting the
952
+ * underlying discovery list.
953
+ */
954
+ declare function buildMcpServers(opts: {
955
+ discovered: readonly DiscoveredMcp[];
956
+ enabled?: readonly string[];
957
+ }): McpServerConfig[];
958
+ //#endregion
959
+ //#region src/chat/prompt-segments.d.ts
960
+ /**
961
+ * Pure string + reference math for rendering a submitted prompt with chip
962
+ * pills around completion references. Renderer-agnostic — the TUI walks
963
+ * the segments into OpenTUI `<text>` nodes, a GUI walks them into JSX
964
+ * spans + `<span class="chip">` pills. No layout engine assumptions.
965
+ */
966
+ /**
967
+ * Highlight span — half-open `[start, end)` over the source string.
968
+ *
969
+ * Offsets are JS string indices (UTF-16 code units) — the same convention used
970
+ * everywhere else in the chat layer (`text[i]`, `m.index`, `String.slice`).
971
+ * Surrogate pairs that straddle a span boundary would render malformed, but
972
+ * realistic prompts in this surface (terminal text + ASCII triggers) keep that
973
+ * risk theoretical; callers feeding emoji-heavy content should normalize to
974
+ * codepoint walks upstream.
975
+ */
976
+ interface PromptSegmentRef {
977
+ start: number;
978
+ end: number;
979
+ /** Provider id tagging this span (`'skills'`, `'files'`, …). Free-form. */
980
+ providerId: string;
981
+ }
982
+ /**
983
+ * One atomic unit emitted by {@link splitPromptSegments}. Plain segments
984
+ * are word-sized so wraps land cleanly between words; chip segments
985
+ * carry the source `providerId` (`'skills'`, `'files'`, …) so renderers
986
+ * can pick per-kind colors without re-walking the ref list.
987
+ */
988
+ type PromptSegment = {
989
+ kind: 'plain';
990
+ text: string;
991
+ } | {
992
+ kind: 'chip';
993
+ text: string;
994
+ providerId: string;
995
+ };
996
+ /**
997
+ * Split a prompt buffer into word-sized atomic segments suitable for a
998
+ * flex-row + flex-wrap renderer (TUI) or a `display: inline` flow with
999
+ * inline-block chips (GUI). Each chip becomes one segment (atomic —
1000
+ * never broken across rows); each plain run is split into "word +
1001
+ * trailing space" units so wraps land at clean word boundaries.
1002
+ *
1003
+ * Robust to:
1004
+ * - Overlapping refs — sorted by start; later refs that overlap are
1005
+ * dropped via the first-wins rule.
1006
+ * - Out-of-bounds refs — dropped entirely when `end > text.length` or
1007
+ * `start >= text.length`. Partial clipping would silently truncate
1008
+ * a chip's label; the caller is in a better position to surface the
1009
+ * mismatch (typically a stale `refs` array referencing a previous text).
1010
+ * - Whitespace-only plain runs — emitted as their own plain segment
1011
+ * so chip-adjacent-to-chip cases keep the original spacing.
1012
+ *
1013
+ * Word splitter rationale: `\S+\s*` keeps trailing whitespace attached
1014
+ * to its preceding word so wrap boundaries land between words (cleanly).
1015
+ * A leading-whitespace-only segment is captured by `\s+` so we don't
1016
+ * drop it entirely when the plain run starts with a space.
1017
+ */
1018
+ declare function splitPromptSegments(text: string, refs: readonly PromptSegmentRef[]): PromptSegment[];
1019
+ //#endregion
1020
+ //#region src/chat/safe-mode-context.d.ts
1021
+ type ApprovalDecision = 'accept-once' | 'accept-safelist' | 'deny';
1022
+ interface ApprovalRequest {
1023
+ id: string;
1024
+ tool: string;
1025
+ input: Record<string, unknown>;
1026
+ resolve: (decision: ApprovalDecision) => void;
1027
+ }
1028
+ /** Function signature consumed by `tool:gate` handlers + the child-tool wrap. */
1029
+ type RequestApproval = (tool: string, input: Record<string, unknown>) => Promise<ApprovalDecision>;
1030
+ interface SafeModeActions {
1031
+ /** Request a decision; resolves once the user picks. */
1032
+ requestApproval: RequestApproval;
1033
+ /** Resolve the head and shift the queue forward. */
1034
+ resolveHead: (decision: ApprovalDecision) => void;
1035
+ /** Resolve all pending with `deny`. Used on abort / hard exit. */
1036
+ denyAll: () => void;
1037
+ }
1038
+ /**
1039
+ * Owns the queue + actions. Splits the value across two contexts so a queue
1040
+ * change doesn't invalidate every callback memo that closes over the actions.
1041
+ */
1042
+ declare function SafeModeProvider({
1043
+ children
1044
+ }: {
1045
+ children: ReactNode;
1046
+ }): _$react_jsx_runtime0.JSX.Element;
1047
+ declare function useSafeModeQueue(): readonly ApprovalRequest[];
1048
+ declare function useSafeModeActions(): SafeModeActions;
1049
+ //#endregion
1050
+ //#region src/chat/theme.d.ts
1051
+ /**
1052
+ * Renderer-agnostic theme system.
1053
+ *
1054
+ * A `Theme` bundles every variable that can change visually between
1055
+ * "themes" — colors, select-row styling, code/markdown syntax highlight
1056
+ * tokens, panel backgrounds. Plain JSON: no OpenTUI dependency, no React,
1057
+ * no functions. The TUI consumes the theme by reading from `useTheme()`
1058
+ * and converting hex strings into OpenTUI's `RGBA`/`SyntaxStyle`; a future
1059
+ * GUI consumes the same theme by converting into CSS variables or Tailwind
1060
+ * tokens.
1061
+ *
1062
+ * Components should always read theme values through `useTheme()` /
1063
+ * `useColors()` so a runtime theme switch (Settings → Theme) re-paints
1064
+ * the whole tree. Importing a raw theme object directly bypasses the
1065
+ * context and pins the component to a single look.
1066
+ *
1067
+ * Built-in flavors (Catppuccin, Vaporwave) live in `./themes/`. This file
1068
+ * just defines the shape + the default theme + the registry.
1069
+ */
1070
+ /** Role-named color palette. Reused throughout the UI for text, borders, accents. */
1071
+ interface ThemeColors {
1072
+ /** Primary accent — selected text, brand emphasis (e.g. `▶` markers). */
1073
+ brand: string;
1074
+ /** Success / progress accent — used sparingly. */
1075
+ accent: string;
1076
+ /** Model badge accent (provider/model name in the footer, links). */
1077
+ model: string;
1078
+ /** Warnings — busy spinner, approval picker border, esc hints. */
1079
+ warn: string;
1080
+ /** Errors — `✗` prefix on error events, validation messages. */
1081
+ error: string;
1082
+ /** Secondary text — captions, helper text, dim transcript lines. */
1083
+ dim: string;
1084
+ /** Tertiary text — separators, descriptions, the `┃` tool-result bar. */
1085
+ mute: string;
1086
+ /** Resting border color. */
1087
+ border: string;
1088
+ /** Border color on focused / active elements. */
1089
+ borderActive: string;
1090
+ }
1091
+ /** Select-component styling. Plain prop shape; both OpenTUI's `<select>` and any GUI equivalent can consume this. */
1092
+ interface ThemeSelect {
1093
+ backgroundColor: string;
1094
+ focusedBackgroundColor: string;
1095
+ selectedBackgroundColor: string;
1096
+ selectedTextColor: string;
1097
+ textColor: string;
1098
+ descriptionColor: string;
1099
+ selectedDescriptionColor: string;
1100
+ }
1101
+ /** Background + foreground pair for a completion-reference chip pill. */
1102
+ interface ChipColor {
1103
+ /** Background paint — the pill itself. High-saturation by convention. */
1104
+ bg: string;
1105
+ /** Foreground paint — the chip text. Pre-paired with {@link ChipColor.bg} for legibility. */
1106
+ fg: string;
1107
+ }
1108
+ /**
1109
+ * Chip colors keyed by completion-provider id (`'skills'`, `'files'`, …).
1110
+ * `default` is the required fallback used by any provider id without an
1111
+ * explicit entry — keeps host-registered providers themable out of the
1112
+ * box. Use {@link resolveChipColor} to perform the kind-specific → default
1113
+ * lookup rather than indexing the map directly.
1114
+ */
1115
+ /**
1116
+ * Map of provider id → chip color pair. `default` is required so callers
1117
+ * always have a fallback; every other key is optional so direct indexing
1118
+ * (`chips['unknown']`) surfaces as `ChipColor | undefined` and nudges
1119
+ * consumers toward {@link resolveChipColor}, which encodes the fallback.
1120
+ */
1121
+ type ChipColorMap = {
1122
+ default: ChipColor;
1123
+ } & Partial<Record<string, ChipColor>>;
1124
+ /**
1125
+ * Look up the chip color pair for a provider id, falling back to
1126
+ * `chips.default` when the theme has no kind-specific entry. Mirrors
1127
+ * `resolveChipStyleId` so both rendering surfaces (submitted echo +
1128
+ * live textarea) share one canonical lookup rule.
1129
+ */
1130
+ declare function resolveChipColor(chips: ChipColorMap, providerId: string): ChipColor;
1131
+ /** Panel / surface backgrounds. */
1132
+ interface ThemeSurfaces {
1133
+ /** Background of an overlaid modal panel (settings, model picker, …). */
1134
+ modal: string;
1135
+ /**
1136
+ * Completion-chip color pairs keyed by provider id. Built-in themes
1137
+ * ship distinct `skills` + `files` tones so the two reference kinds
1138
+ * read differently in both the submitted echo and the live textarea.
1139
+ */
1140
+ chips: ChipColorMap;
1141
+ /**
1142
+ * Background paint for the selected turn's events in select-turn mode.
1143
+ * Subtle, low-saturation lift from the terminal default so the whole
1144
+ * span of the selected turn reads as one continuous highlighted block
1145
+ * without overpowering the foreground text. Inverse-tinted on the
1146
+ * light flavor (Latte) so the same visual role works there.
1147
+ */
1148
+ selection: string;
1149
+ }
1150
+ /**
1151
+ * One entry in a `SyntaxStyles` map — what OpenTUI's `SyntaxStyle.fromStyles`
1152
+ * accepts, minus the `RGBA` conversion. Renderer-agnostic JSON.
1153
+ */
1154
+ interface SyntaxTokenStyle {
1155
+ fg?: string;
1156
+ bg?: string;
1157
+ bold?: boolean;
1158
+ italic?: boolean;
1159
+ underline?: boolean;
1160
+ dim?: boolean;
1161
+ }
1162
+ /**
1163
+ * Map of Tree-sitter / markdown capture group → token style.
1164
+ *
1165
+ * Two flavours of keys live in the same table:
1166
+ * - `markup.*` — the markdown structure captures (heading, bold, italic,
1167
+ * list, quote, raw inline + block, link). OpenTUI's markdown parser
1168
+ * emits these for the markdown text itself.
1169
+ * - bare token names (`keyword`, `string`, `function`, …) — emitted by
1170
+ * the embedded language Tree-sitter grammars when a code fence
1171
+ * declares a language. OpenTUI passes the same `SyntaxStyle` down to
1172
+ * the fenced-code renderable, so this map drives both surfaces.
1173
+ */
1174
+ type SyntaxStyles = Record<string, SyntaxTokenStyle>;
1175
+ /** Full theme bundle. */
1176
+ interface Theme {
1177
+ /** Stable identifier, used as the key in `BUILTIN_THEMES` and `Settings.theme`. */
1178
+ id: string;
1179
+ /** Human-readable label shown in the settings picker. */
1180
+ label: string;
1181
+ colors: ThemeColors;
1182
+ select: ThemeSelect;
1183
+ surfaces: ThemeSurfaces;
1184
+ syntax: SyntaxStyles;
1185
+ }
1186
+ declare const DEFAULT_THEME: Theme;
1187
+ /**
1188
+ * Built-in theme registry, keyed by `theme.id`. The TUI looks up the active
1189
+ * theme here using `Settings.theme`; unknown ids fall back to
1190
+ * `DEFAULT_THEME`. Hosts can extend this by passing additional themes to a
1191
+ * future `runTui({ themes })` option (not yet wired).
1192
+ *
1193
+ * Insertion order is the picker cycle order — keep `default` first so a
1194
+ * fresh install (no `theme` in `state.json`) sees the familiar yellow theme
1195
+ * before the others.
1196
+ */
1197
+ declare const BUILTIN_THEMES: Readonly<Record<string, Theme>>;
1198
+ /** Resolve a theme id to its full `Theme`, falling back to default on unknown ids. */
1199
+ declare function resolveTheme(id: string | undefined): Theme;
1200
+ //#endregion
1201
+ export { Settings as $, useEnabledToggleSet as A, BUILD_AGENT as At, lastContextSizeFromTurns as B, DiscoveredMcp as C, modelsForDescriptor as Ct, parseMcpsFile as D, AgentAccent as Dt, discoverProjectMcps as E, piIdOf as Et, StateStoreApi as F, singleAgentRegistry as Ft, stripSpawnTokensLine as G, loadState as H, TuiState as I, toolResultText as J, titleFromTurns as K, createStateStore as L, ProviderRegistry as M, DEFAULT_AGENT_ID as Mt, ResolvedConfig as N, PLAN_AGENT as Nt, EnabledAllowlistKey as O, AgentProfile as Ot, resolveConfig as P, resolveAgentId as Pt, SessionMeta as Q, deriveSessionTitle as R, splitPromptSegments as S, getContextWindow as St, defaultMcpsConfigPaths as T, openrouterDescriptor as Tt, saveState as U, listSessionMeta as V, selectableTurnIds as W, Picked as X, Owner as Y, Screen as Z, SafeModeProvider as _, ModelInfo as _t, SyntaxStyles as a, CompletionReference as at, PromptSegment as b, cerebrasDescriptor as bt, ThemeColors as c, collectReferences as ct, resolveChipColor as d, useCompletion as dt, StreamEvent as et, resolveTheme as f, AuthMethod as ft, SafeModeActions as g, BUILTIN_PROVIDERS as gt, RequestApproval as h, detectAuth as ht, DEFAULT_THEME as i, CompletionProvider as it, ChatOptions as j, BUILTIN_AGENTS as jt, EnabledToggleSet as k, AgentRegistry as kt, ThemeSelect as l, findActiveTrigger as lt, ApprovalRequest as m, ProviderKey as mt, ChipColor as n, CompletionContext as nt, SyntaxTokenStyle as o, CompletionState as ot, ApprovalDecision as p, ProviderAuth as pt, toolCallPreview as q, ChipColorMap as r, CompletionItem as rt, Theme as s, applyInsert as st, BUILTIN_THEMES as t, ActiveTrigger as tt, ThemeSurfaces as u, mergeReferences as ut, useSafeModeActions as v, ProviderDescriptor as vt, buildMcpServers as w, openaiDescriptor as wt, PromptSegmentRef as x, credKeyOf as xt, useSafeModeQueue as y, anthropicDescriptor as yt, eventsFromTurns as z };
1202
+ //# sourceMappingURL=theme-pJv47erq.d.ts.map