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.
- package/README.md +11 -2
- package/dist/{index-bgh-k8Mv.d.ts → agent-JhicgLOV.d.ts} +2082 -1969
- package/dist/agent-JhicgLOV.d.ts.map +1 -0
- package/dist/chat.d.ts +340 -9
- package/dist/chat.d.ts.map +1 -1
- package/dist/chat.js +2 -2
- package/dist/contexts.d.ts +1 -1
- package/dist/{index-DRoG_udt.d.ts → index-2yLUyTbc.d.ts} +34 -4
- package/dist/{index-DRoG_udt.d.ts.map → index-2yLUyTbc.d.ts.map} +1 -1
- package/dist/{index-BB4kuRh3.d.ts → index-CXVvqTQj.d.ts} +1 -1
- package/dist/{index-BB4kuRh3.d.ts.map → index-CXVvqTQj.d.ts.map} +1 -1
- package/dist/{index-Ds5YpvfZ.d.ts → index-t_W9i7Ql.d.ts} +9 -4
- package/dist/index-t_W9i7Ql.d.ts.map +1 -0
- package/dist/index.d.ts +4 -4
- package/dist/index.js +6 -6
- package/dist/{interpolate-CukJwP2G.js → interpolate-Ck970-61.js} +11 -2
- package/dist/interpolate-Ck970-61.js.map +1 -0
- package/dist/{mcp-8wClKY-3.js → mcp-Dw-fRPVk.js} +61 -65
- package/dist/mcp-Dw-fRPVk.js.map +1 -0
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +1 -1
- package/dist/presets-BRFH2qsQ.js +90 -0
- package/dist/presets-BRFH2qsQ.js.map +1 -0
- package/dist/presets.d.ts +3 -2
- package/dist/presets.js +2 -2
- package/dist/providers.d.ts +1 -1
- package/dist/session/sqlite.d.ts +13 -2
- package/dist/session/sqlite.d.ts.map +1 -1
- package/dist/session/sqlite.js +96 -38
- package/dist/session/sqlite.js.map +1 -1
- package/dist/{session-Cn68UASv.js → session-791hhrFa.js} +65 -30
- package/dist/session-791hhrFa.js.map +1 -0
- package/dist/session.d.ts +1 -1
- package/dist/session.js +1 -1
- package/dist/skills.d.ts +2 -2
- package/dist/skills.js +1 -1
- package/dist/{stats-BT9l57RS.js → stats-DZIsGqzu.js} +15 -5
- package/dist/stats-DZIsGqzu.js.map +1 -0
- package/dist/theme-pJv47erq.d.ts +1202 -0
- package/dist/theme-pJv47erq.d.ts.map +1 -0
- package/dist/{tools-C8kDot0H.js → tools-CLazLRb4.js} +475 -318
- package/dist/tools-CLazLRb4.js.map +1 -0
- package/dist/tools.d.ts +2 -2
- package/dist/tools.js +1 -1
- package/dist/tui.d.ts +303 -18
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +3305 -509
- package/dist/tui.js.map +1 -1
- package/dist/turn-operations-5aQu4dJg.js +3587 -0
- package/dist/turn-operations-5aQu4dJg.js.map +1 -0
- package/dist/types.d.ts +3 -3
- package/dist/types.js +1 -1
- package/package.json +6 -1
- package/dist/index-Ds5YpvfZ.d.ts.map +0 -1
- package/dist/index-bgh-k8Mv.d.ts.map +0 -1
- package/dist/interpolate-CukJwP2G.js.map +0 -1
- package/dist/mcp-8wClKY-3.js.map +0 -1
- package/dist/presets-BzkJDW1K.js +0 -39
- package/dist/presets-BzkJDW1K.js.map +0 -1
- package/dist/session-Cn68UASv.js.map +0 -1
- package/dist/stats-BT9l57RS.js.map +0 -1
- package/dist/theme-BlXO6yHe.d.ts +0 -503
- package/dist/theme-BlXO6yHe.d.ts.map +0 -1
- package/dist/theme-context-MungM3SY.js +0 -1713
- package/dist/theme-context-MungM3SY.js.map +0 -1
- 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
|