zidane 4.1.8 → 4.1.9
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/dist/{index-bgh-k8Mv.d.ts → agent-CMIhYhDz.d.ts} +2032 -1993
- package/dist/agent-CMIhYhDz.d.ts.map +1 -0
- package/dist/chat.d.ts +7 -6
- package/dist/chat.d.ts.map +1 -1
- package/dist/chat.js +2 -2
- package/dist/contexts.d.ts +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-D6Dd6Kc0.d.ts} +3 -3
- package/dist/{index-Ds5YpvfZ.d.ts.map → index-D6Dd6Kc0.d.ts.map} +1 -1
- package/dist/{index-DRoG_udt.d.ts → index-DAaKyadO.d.ts} +2 -2
- package/dist/{index-DRoG_udt.d.ts.map → index-DAaKyadO.d.ts.map} +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +6 -6
- package/dist/{interpolate-CukJwP2G.js → interpolate-BydkV1eT.js} +3 -1
- package/dist/interpolate-BydkV1eT.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-BzkJDW1K.js → presets-4zCJzCYw.js} +2 -2
- package/dist/{presets-BzkJDW1K.js.map → presets-4zCJzCYw.js.map} +1 -1
- package/dist/presets.d.ts +1 -1
- package/dist/presets.js +1 -1
- 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 +70 -27
- package/dist/session/sqlite.js.map +1 -1
- package/dist/{session-Cn68UASv.js → session-B1RN0uoi.js} +42 -30
- package/dist/{session-Cn68UASv.js.map → session-B1RN0uoi.js.map} +1 -1
- 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-BlXO6yHe.d.ts → theme-Caf4AvTO.d.ts} +147 -13
- package/dist/theme-Caf4AvTO.d.ts.map +1 -0
- package/dist/{theme-context-MungM3SY.js → theme-context-DQM2lx4U.js} +212 -72
- package/dist/theme-context-DQM2lx4U.js.map +1 -0
- package/dist/{tools-C8kDot0H.js → tools-BdQENveS.js} +409 -312
- package/dist/tools-BdQENveS.js.map +1 -0
- package/dist/tools.d.ts +2 -2
- package/dist/tools.js +1 -1
- package/dist/tui.d.ts +64 -7
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +481 -143
- package/dist/tui.js.map +1 -1
- package/dist/types.d.ts +3 -3
- package/dist/types.js +1 -1
- package/package.json +6 -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/stats-BT9l57RS.js.map +0 -1
- package/dist/theme-BlXO6yHe.d.ts.map +0 -1
- package/dist/theme-context-MungM3SY.js.map +0 -1
- package/dist/tools-C8kDot0H.js.map +0 -1
|
@@ -1,16 +1,105 @@
|
|
|
1
|
+
import { a as multiEdit, c as grep, i as readFile, l as glob, n as createSpawnTool, o as listFiles, r as shell, t as writeFile, u as edit } from "./tools-BdQENveS.js";
|
|
1
2
|
import { n as toolResultToText } from "./types-Bx_F8jet.js";
|
|
2
|
-
import { n as formatTokenUsage } from "./stats-
|
|
3
|
-
import {
|
|
3
|
+
import { n as formatTokenUsage } from "./stats-DZIsGqzu.js";
|
|
4
|
+
import { t as definePreset } from "./presets-4zCJzCYw.js";
|
|
4
5
|
import { i as anthropic, n as openai, r as cerebras, t as openrouter } from "./providers-CCDvIXGJ.js";
|
|
5
|
-
import { createSqliteStore } from "./session/sqlite.js";
|
|
6
6
|
import { spawn } from "node:child_process";
|
|
7
7
|
import { dirname, resolve } from "node:path";
|
|
8
8
|
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
9
9
|
import { homedir } from "node:os";
|
|
10
10
|
import { anthropicOAuthProvider, openaiCodexOAuthProvider } from "@mariozechner/pi-ai/oauth";
|
|
11
11
|
import { getModel, getModels } from "@mariozechner/pi-ai";
|
|
12
|
-
import { createContext, useCallback, useContext, useMemo, useRef, useState } from "react";
|
|
13
|
-
import { jsx } from "
|
|
12
|
+
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
13
|
+
import { jsx } from "react/jsx-runtime";
|
|
14
|
+
//#region src/chat/agents.ts
|
|
15
|
+
/** Read-only tool slice shared by the Plan profile and any host-built read-only variant. */
|
|
16
|
+
const READ_ONLY_TOOLS = {
|
|
17
|
+
readFile,
|
|
18
|
+
listFiles,
|
|
19
|
+
glob,
|
|
20
|
+
grep
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Build agent — the default profile. Full read/write/shell access plus
|
|
24
|
+
* subagent spawning. Mirrors the legacy `basic` preset so existing TUI
|
|
25
|
+
* behavior is preserved when `agents` is omitted.
|
|
26
|
+
*/
|
|
27
|
+
const BUILD_AGENT = {
|
|
28
|
+
id: "build",
|
|
29
|
+
label: "Build",
|
|
30
|
+
description: "full tool access — read, write, edit, shell, and spawn subagents",
|
|
31
|
+
accent: "accent",
|
|
32
|
+
preset: definePreset({
|
|
33
|
+
name: "build",
|
|
34
|
+
system: "You are a helpful coding assistant with full access to the workspace: shell, file reading, file writing, surgical and multi-edit tools, directory listing, codebase search, and sub-agent spawning. Prefer `edit` / `multi_edit` for in-place changes and `write_file` for full file overwrites. Spawn subagents for parallelizable work.",
|
|
35
|
+
tools: {
|
|
36
|
+
shell,
|
|
37
|
+
readFile,
|
|
38
|
+
writeFile,
|
|
39
|
+
listFiles,
|
|
40
|
+
edit,
|
|
41
|
+
multiEdit,
|
|
42
|
+
glob,
|
|
43
|
+
grep,
|
|
44
|
+
spawn: createSpawnTool({ persist: true })
|
|
45
|
+
}
|
|
46
|
+
})
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Plan agent — read-only exploration mode. Locked down to file reading and
|
|
50
|
+
* codebase search; no shell, no edits, no spawning. The system prompt
|
|
51
|
+
* frames the conversation as planning rather than execution so the model
|
|
52
|
+
* outputs proposals instead of attempting mutations.
|
|
53
|
+
*/
|
|
54
|
+
const PLAN_AGENT = {
|
|
55
|
+
id: "plan",
|
|
56
|
+
label: "Plan",
|
|
57
|
+
description: "read-only — explore, analyze, and propose without modifying anything",
|
|
58
|
+
accent: "model",
|
|
59
|
+
preset: definePreset({
|
|
60
|
+
name: "plan",
|
|
61
|
+
system: "You are in PLAN mode. You can read files, list directories, and search the codebase — but you CANNOT modify files, run shell commands, or spawn subagents. Use this mode to investigate, understand the problem, and propose a clear plan in detail. The user will switch to Build mode to execute it.",
|
|
62
|
+
tools: READ_ONLY_TOOLS
|
|
63
|
+
})
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Default registry shipped with `zidane/tui`. Insertion order = picker order.
|
|
67
|
+
* Hosts that want only one profile can pass `{ agents: { build: BUILD_AGENT } }`,
|
|
68
|
+
* or a fully custom registry of their own profiles.
|
|
69
|
+
*/
|
|
70
|
+
const BUILTIN_AGENTS = {
|
|
71
|
+
build: BUILD_AGENT,
|
|
72
|
+
plan: PLAN_AGENT
|
|
73
|
+
};
|
|
74
|
+
/** Id of the profile activated on first launch when nothing is persisted. */
|
|
75
|
+
const DEFAULT_AGENT_ID = "build";
|
|
76
|
+
/**
|
|
77
|
+
* Resolve an agent id against a registry with sensible fallbacks: the
|
|
78
|
+
* requested id wins when present, then `defaultId`, then the first key.
|
|
79
|
+
* Returns `null` when the registry is empty (host misconfiguration —
|
|
80
|
+
* the caller should surface this rather than silently failing).
|
|
81
|
+
*/
|
|
82
|
+
function resolveAgentId(registry, requestedId, defaultId) {
|
|
83
|
+
if (requestedId && registry[requestedId]) return requestedId;
|
|
84
|
+
if (defaultId && registry[defaultId]) return defaultId;
|
|
85
|
+
return Object.keys(registry)[0] ?? null;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Wrap a legacy single `Preset` into a single-profile registry. Used by
|
|
89
|
+
* `resolveConfig` when the host passed `preset` without `agents`, so older
|
|
90
|
+
* call sites keep working — they get a one-entry registry whose picker is
|
|
91
|
+
* a no-op (only one option).
|
|
92
|
+
*/
|
|
93
|
+
function singleAgentRegistry(preset) {
|
|
94
|
+
return { default: {
|
|
95
|
+
id: "default",
|
|
96
|
+
label: typeof preset.name === "string" && preset.name.length > 0 ? preset.name : "Default",
|
|
97
|
+
description: "host-provided preset",
|
|
98
|
+
preset,
|
|
99
|
+
accent: "accent"
|
|
100
|
+
} };
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
14
103
|
//#region src/chat/providers.ts
|
|
15
104
|
/** Convenience accessor — returns `credentialFileKey ?? key`. */
|
|
16
105
|
function credKeyOf(desc) {
|
|
@@ -285,20 +374,16 @@ function detectAuth(dataDir, registry, env = process.env) {
|
|
|
285
374
|
}
|
|
286
375
|
//#endregion
|
|
287
376
|
//#region src/chat/store.ts
|
|
288
|
-
function
|
|
377
|
+
function ensureStateDir(path) {
|
|
289
378
|
const dir = dirname(path);
|
|
290
379
|
if (existsSync(dir)) return;
|
|
291
380
|
try {
|
|
292
381
|
mkdirSync(dir, { recursive: true });
|
|
293
382
|
} catch (err) {
|
|
294
383
|
const message = err instanceof Error ? err.message : String(err);
|
|
295
|
-
throw new Error(`Could not create TUI
|
|
384
|
+
throw new Error(`Could not create TUI state directory at "${dir}". Override the location via \`runTui({ storageDir, prefix })\` or the \`ZIDANE_STORAGE_DIR\` env var. Original error: ${message}`);
|
|
296
385
|
}
|
|
297
386
|
}
|
|
298
|
-
function createTuiStore(dbPath) {
|
|
299
|
-
ensureDir$1(dbPath);
|
|
300
|
-
return createSqliteStore({ path: dbPath });
|
|
301
|
-
}
|
|
302
387
|
function createStateStore(path) {
|
|
303
388
|
return {
|
|
304
389
|
load: () => loadState(path),
|
|
@@ -314,7 +399,7 @@ function loadState(path) {
|
|
|
314
399
|
return {};
|
|
315
400
|
}
|
|
316
401
|
function saveState(path, state) {
|
|
317
|
-
|
|
402
|
+
ensureStateDir(path);
|
|
318
403
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
319
404
|
writeFileSync(tmp, JSON.stringify(state, null, 2));
|
|
320
405
|
renameSync(tmp, path);
|
|
@@ -323,10 +408,15 @@ function saveState(path, state) {
|
|
|
323
408
|
* Load every session and project it to the compact `SessionMeta` shape used by
|
|
324
409
|
* the picker. Sorted by recency via the underlying store's `list()` contract
|
|
325
410
|
* (sqlite store returns by `updated_at DESC`).
|
|
411
|
+
*
|
|
412
|
+
* Robust to per-row failures: `Promise.allSettled` so a single corrupt or
|
|
413
|
+
* unreadable row (malformed JSON, partial write, transient I/O error)
|
|
414
|
+
* doesn't take down the entire picker. Failed rows are silently skipped;
|
|
415
|
+
* a stderr line is emitted under `ZIDANE_DEBUG` for diagnosis.
|
|
326
416
|
*/
|
|
327
417
|
async function listSessionMeta(store) {
|
|
328
418
|
const ids = await store.list();
|
|
329
|
-
|
|
419
|
+
const settled = await Promise.allSettled(ids.map(async (id) => {
|
|
330
420
|
const data = await store.load(id);
|
|
331
421
|
if (!data) return null;
|
|
332
422
|
return {
|
|
@@ -335,7 +425,17 @@ async function listSessionMeta(store) {
|
|
|
335
425
|
turnCount: data.turns.length,
|
|
336
426
|
updatedAt: data.updatedAt
|
|
337
427
|
};
|
|
338
|
-
}))
|
|
428
|
+
}));
|
|
429
|
+
const metas = [];
|
|
430
|
+
for (let i = 0; i < settled.length; i++) {
|
|
431
|
+
const result = settled[i];
|
|
432
|
+
if (result.status === "fulfilled" && result.value) metas.push(result.value);
|
|
433
|
+
else if (result.status === "rejected" && process.env.ZIDANE_DEBUG) {
|
|
434
|
+
const cause = result.reason instanceof Error ? result.reason.message : String(result.reason);
|
|
435
|
+
process.stderr.write(`[zidane/chat] failed to load session "${ids[i]}": ${cause}\n`);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
return metas;
|
|
339
439
|
}
|
|
340
440
|
/** Derive a short title from the first user message — returns null when empty. */
|
|
341
441
|
function titleFromTurns(turns) {
|
|
@@ -376,13 +476,25 @@ function eventsFromTurns(turns, runs = []) {
|
|
|
376
476
|
if (turn.role !== "assistant") continue;
|
|
377
477
|
for (const block of turn.content) if (block.type === "tool_call") toolByCallId.set(block.id, block.name);
|
|
378
478
|
}
|
|
479
|
+
const ancestryOf = (turnRunId) => {
|
|
480
|
+
if (!turnRunId) return [];
|
|
481
|
+
const chain = [];
|
|
482
|
+
let cursor = runById.get(turnRunId);
|
|
483
|
+
const seen = /* @__PURE__ */ new Set();
|
|
484
|
+
while (cursor) {
|
|
485
|
+
if (seen.has(cursor.id)) break;
|
|
486
|
+
seen.add(cursor.id);
|
|
487
|
+
if ((cursor.depth ?? 0) > 0) chain.unshift(cursor);
|
|
488
|
+
cursor = cursor.parentRunId ? runById.get(cursor.parentRunId) : void 0;
|
|
489
|
+
}
|
|
490
|
+
return chain;
|
|
491
|
+
};
|
|
379
492
|
const events = [];
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
if (!run) return;
|
|
493
|
+
/** Currently-open child runs, root-of-tree first, innermost last. */
|
|
494
|
+
const openStack = [];
|
|
495
|
+
/** True iff anything has been emitted at the active depth-0 level. Used to decide separators between top-level turns. */
|
|
496
|
+
let lastDepthAtEmission = -1;
|
|
497
|
+
const pushSpawnEnd = (run) => {
|
|
386
498
|
const tag = run.status === "aborted" || run.status === "error" ? run.status : "done";
|
|
387
499
|
const usage = formatTokenUsage({
|
|
388
500
|
totalIn: run.tokensIn ?? run.totalUsage?.input ?? 0,
|
|
@@ -393,42 +505,39 @@ function eventsFromTurns(turns, runs = []) {
|
|
|
393
505
|
events.push({
|
|
394
506
|
kind: "spawn-end",
|
|
395
507
|
text: `${tag} ${usage}`,
|
|
396
|
-
childId: labelFor(
|
|
397
|
-
depth
|
|
508
|
+
childId: labelFor(run.id),
|
|
509
|
+
depth: run.depth ?? 1
|
|
398
510
|
});
|
|
399
511
|
};
|
|
400
|
-
const
|
|
401
|
-
if (depth <= 0) return;
|
|
402
|
-
const run = runById.get(runId);
|
|
403
|
-
if (!run) return;
|
|
512
|
+
const pushSpawnStart = (run) => {
|
|
404
513
|
const taskPreview = run.prompt.length > 80 ? `${run.prompt.slice(0, 80)}…` : run.prompt;
|
|
405
514
|
events.push({
|
|
406
515
|
kind: "spawn-start",
|
|
407
516
|
text: taskPreview,
|
|
408
|
-
childId: labelFor(
|
|
409
|
-
depth
|
|
517
|
+
childId: labelFor(run.id),
|
|
518
|
+
depth: run.depth ?? 1
|
|
410
519
|
});
|
|
411
520
|
};
|
|
412
521
|
for (let i = 0; i < turns.length; i++) {
|
|
413
522
|
const turn = turns[i];
|
|
414
|
-
const
|
|
523
|
+
const targetChain = ancestryOf(turn.runId);
|
|
524
|
+
const depth = targetChain.length;
|
|
525
|
+
let common = 0;
|
|
526
|
+
while (common < openStack.length && common < targetChain.length && openStack[common].id === targetChain[common].id) common++;
|
|
527
|
+
while (openStack.length > common) pushSpawnEnd(openStack.pop());
|
|
528
|
+
while (openStack.length < targetChain.length) {
|
|
529
|
+
const run = targetChain[openStack.length];
|
|
530
|
+
pushSpawnStart(run);
|
|
531
|
+
openStack.push(run);
|
|
532
|
+
}
|
|
533
|
+
if (depth === 0 && lastDepthAtEmission === 0) events.push({
|
|
534
|
+
kind: "separator",
|
|
535
|
+
text: ""
|
|
536
|
+
});
|
|
415
537
|
const tag = depth > 0 && turn.runId ? {
|
|
416
538
|
childId: labelFor(turn.runId),
|
|
417
539
|
depth
|
|
418
540
|
} : void 0;
|
|
419
|
-
if (turn.runId !== lastRunId) {
|
|
420
|
-
closeRun(lastRunId, lastDepth);
|
|
421
|
-
if (depth === 0 && lastDepth === 0 && i > 0) events.push({
|
|
422
|
-
kind: "separator",
|
|
423
|
-
text: ""
|
|
424
|
-
});
|
|
425
|
-
if (turn.runId) openRun(turn.runId, depth);
|
|
426
|
-
lastRunId = turn.runId;
|
|
427
|
-
lastDepth = depth;
|
|
428
|
-
} else if (i > 0 && depth === 0) events.push({
|
|
429
|
-
kind: "separator",
|
|
430
|
-
text: ""
|
|
431
|
-
});
|
|
432
541
|
if (turn.role === "user") {
|
|
433
542
|
for (const block of turn.content) if (block.type === "text" && block.text.trim()) {
|
|
434
543
|
if (depth === 0) events.push({
|
|
@@ -446,6 +555,7 @@ function eventsFromTurns(turns, runs = []) {
|
|
|
446
555
|
...tag
|
|
447
556
|
});
|
|
448
557
|
}
|
|
558
|
+
lastDepthAtEmission = depth;
|
|
449
559
|
continue;
|
|
450
560
|
}
|
|
451
561
|
if (turn.role === "assistant") {
|
|
@@ -461,9 +571,10 @@ function eventsFromTurns(turns, runs = []) {
|
|
|
461
571
|
tool: block.name,
|
|
462
572
|
...tag
|
|
463
573
|
});
|
|
574
|
+
lastDepthAtEmission = depth;
|
|
464
575
|
}
|
|
465
576
|
}
|
|
466
|
-
|
|
577
|
+
while (openStack.length > 0) pushSpawnEnd(openStack.pop());
|
|
467
578
|
return events;
|
|
468
579
|
}
|
|
469
580
|
/** Shared formatter for the `↳ name(args)` line shown on tool calls. */
|
|
@@ -489,20 +600,36 @@ function toolResultText(output) {
|
|
|
489
600
|
* (post-`formatTokenUsage`) shapes.
|
|
490
601
|
*/
|
|
491
602
|
function stripSpawnTokensLine(text) {
|
|
492
|
-
return text.replace(
|
|
603
|
+
return text.replace(/(^\[sub-agent [^\n]+\n)Tokens:[^\n]*\n?/, "$1");
|
|
493
604
|
}
|
|
494
605
|
/** Effective context size of the most recent assistant turn — drives the footer indicator. */
|
|
495
|
-
|
|
606
|
+
/**
|
|
607
|
+
* Walk from the end of `turns` and return the cache-aware input-token total
|
|
608
|
+
* of the most recent **parent** (depth-0) assistant turn. Subagent turns
|
|
609
|
+
* are skipped because their context window is the child's, not the parent's
|
|
610
|
+
* — surfacing a subagent's `usage.input` as the footer's "context used"
|
|
611
|
+
* after a session ends mid-spawn would be misleading. The next prompt
|
|
612
|
+
* feeds the parent, so the parent's last view is what matters.
|
|
613
|
+
*
|
|
614
|
+
* `runs` is optional for backwards compatibility (older call sites and
|
|
615
|
+
* tests that don't have ancestry info). Without it, this falls back to the
|
|
616
|
+
* pre-fix behavior — depth is unknown so every assistant turn qualifies.
|
|
617
|
+
*/
|
|
618
|
+
function lastContextSizeFromTurns(turns, runs = []) {
|
|
619
|
+
const childRunIds = /* @__PURE__ */ new Set();
|
|
620
|
+
for (const run of runs) if ((run.depth ?? 0) > 0) childRunIds.add(run.id);
|
|
496
621
|
for (let i = turns.length - 1; i >= 0; i--) {
|
|
497
622
|
const turn = turns[i];
|
|
498
|
-
if (turn.role
|
|
623
|
+
if (turn.role !== "assistant" || !turn.usage) continue;
|
|
624
|
+
if (turn.runId && childRunIds.has(turn.runId)) continue;
|
|
625
|
+
return (turn.usage.input ?? 0) + (turn.usage.cacheRead ?? 0) + (turn.usage.cacheCreation ?? 0);
|
|
499
626
|
}
|
|
500
627
|
return 0;
|
|
501
628
|
}
|
|
502
629
|
//#endregion
|
|
503
630
|
//#region src/chat/config.ts
|
|
504
631
|
/** Resolve user options into a fully-bound runtime config. Pure aside from disk reads. */
|
|
505
|
-
function resolveConfig(options
|
|
632
|
+
function resolveConfig(options) {
|
|
506
633
|
const prefix = options.prefix ?? process.env.ZIDANE_PREFIX ?? ".zidane";
|
|
507
634
|
const storageDir = options.storageDir ?? process.env.ZIDANE_STORAGE_DIR ?? homedir();
|
|
508
635
|
const dir = resolve(storageDir, prefix);
|
|
@@ -511,22 +638,28 @@ function resolveConfig(options = {}) {
|
|
|
511
638
|
db: resolve(dir, "sessions.db"),
|
|
512
639
|
state: resolve(dir, "state.json")
|
|
513
640
|
};
|
|
514
|
-
|
|
641
|
+
if (!options.store) throw new Error("resolveConfig: `store` is required. Pass a `SessionStore` instance, or a factory — terminal hosts can use `createTuiStore` from `zidane/session/sqlite`.");
|
|
642
|
+
const store = typeof options.store === "function" ? options.store(paths) : options.store;
|
|
515
643
|
const stateStore = createStateStore(paths.state);
|
|
516
644
|
const initialState = stateStore.load();
|
|
517
645
|
const providers = options.providers ?? BUILTIN_PROVIDERS;
|
|
518
|
-
|
|
646
|
+
if (options.agents && options.preset) throw new Error("resolveConfig: pass either `preset` (single-agent legacy) or `agents` (multi-profile registry), not both. Migrate `preset` into an entry inside `agents` if you want both worlds.");
|
|
647
|
+
const agents = options.agents ?? (options.preset ? singleAgentRegistry(options.preset) : BUILTIN_AGENTS);
|
|
648
|
+
if (Object.keys(agents).length === 0) throw new Error("resolveConfig: `agents` registry is empty — at least one profile is required.");
|
|
519
649
|
process.env.ZIDANE_CREDENTIALS_PATH = credentialsPath(dir);
|
|
520
650
|
applyApiKeyEnv(dir, providers);
|
|
521
651
|
const modelsFor = makeModelsResolver(providers);
|
|
522
652
|
const resumeProvider = resolveResumeProvider(initialState, providers, dir);
|
|
523
653
|
const initialPicked = resumeProvider ? pickInitial(resumeProvider, providers, initialState) : null;
|
|
654
|
+
const initialAgentId = resolveAgentId(agents, initialState.lastAgent, options.defaultAgent ?? "build");
|
|
655
|
+
if (!initialAgentId) throw new Error("resolveConfig: failed to resolve an initial agent id from a non-empty registry.");
|
|
524
656
|
return {
|
|
525
657
|
prefix,
|
|
526
658
|
storageDir,
|
|
527
659
|
paths,
|
|
528
660
|
providers,
|
|
529
|
-
|
|
661
|
+
agents,
|
|
662
|
+
initialAgentId,
|
|
530
663
|
store,
|
|
531
664
|
stateStore,
|
|
532
665
|
modelsFor,
|
|
@@ -1131,7 +1264,7 @@ function catppuccinTheme(id, label, p) {
|
|
|
1131
1264
|
const CATPPUCCIN_MOCHA = catppuccinTheme("catppuccin-mocha", "Catppuccin Mocha", MOCHA);
|
|
1132
1265
|
const CATPPUCCIN_MACCHIATO = catppuccinTheme("catppuccin-macchiato", "Catppuccin Macchiato", MACCHIATO);
|
|
1133
1266
|
const CATPPUCCIN_FRAPPE = catppuccinTheme("catppuccin-frappe", "Catppuccin Frappé", FRAPPE);
|
|
1134
|
-
const CATPPUCCIN_LATTE = catppuccinTheme("catppuccin-latte", "Catppuccin Latte", LATTE);
|
|
1267
|
+
const CATPPUCCIN_LATTE = catppuccinTheme("catppuccin-latte", "Catppuccin Latte (light)", LATTE);
|
|
1135
1268
|
//#endregion
|
|
1136
1269
|
//#region src/chat/themes/vaporwave.ts
|
|
1137
1270
|
const PALETTE = {
|
|
@@ -1145,6 +1278,12 @@ const PALETTE = {
|
|
|
1145
1278
|
yellow: "#FFFB96",
|
|
1146
1279
|
red: "#F43E5C",
|
|
1147
1280
|
text: "#D5D8DA",
|
|
1281
|
+
/**
|
|
1282
|
+
* ~70% of `text` — used for captions / helper / "dim" text so that
|
|
1283
|
+
* secondary copy is visually distinct from primary copy. Matches the
|
|
1284
|
+
* upstream theme's sidebar foreground (`#b7c5d3`) tonality.
|
|
1285
|
+
*/
|
|
1286
|
+
textDim: "#B7C5D3",
|
|
1148
1287
|
textBright: "#EEFFFF",
|
|
1149
1288
|
comment: "#BBBBBB",
|
|
1150
1289
|
muted: "#6C6F93",
|
|
@@ -1160,7 +1299,7 @@ const VAPORWAVE_THEME = {
|
|
|
1160
1299
|
model: PALETTE.blue,
|
|
1161
1300
|
warn: PALETTE.yellow,
|
|
1162
1301
|
error: PALETTE.red,
|
|
1163
|
-
dim: PALETTE.
|
|
1302
|
+
dim: PALETTE.textDim,
|
|
1164
1303
|
mute: PALETTE.muted,
|
|
1165
1304
|
border: PALETTE.surface,
|
|
1166
1305
|
borderActive: PALETTE.muted
|
|
@@ -1439,27 +1578,28 @@ const DEFAULT_SETTINGS = {
|
|
|
1439
1578
|
const SettingsContext = createContext(null);
|
|
1440
1579
|
function SettingsProvider({ initial, onChange, children }) {
|
|
1441
1580
|
const [settings, setSettings] = useState(initial);
|
|
1581
|
+
const onChangeRef = useRef(onChange);
|
|
1582
|
+
onChangeRef.current = onChange;
|
|
1583
|
+
const initialMount = useRef(true);
|
|
1584
|
+
useEffect(() => {
|
|
1585
|
+
if (initialMount.current) {
|
|
1586
|
+
initialMount.current = false;
|
|
1587
|
+
return;
|
|
1588
|
+
}
|
|
1589
|
+
onChangeRef.current?.(settings);
|
|
1590
|
+
}, [settings]);
|
|
1442
1591
|
const toggle = useCallback((key) => {
|
|
1443
|
-
setSettings((prev) => {
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
onChange?.(next);
|
|
1449
|
-
return next;
|
|
1450
|
-
});
|
|
1451
|
-
}, [onChange]);
|
|
1592
|
+
setSettings((prev) => ({
|
|
1593
|
+
...prev,
|
|
1594
|
+
[key]: !prev[key]
|
|
1595
|
+
}));
|
|
1596
|
+
}, []);
|
|
1452
1597
|
const setSetting = useCallback((key, value) => {
|
|
1453
|
-
setSettings((prev) => {
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
...prev,
|
|
1457
|
-
[key]: value
|
|
1458
|
-
};
|
|
1459
|
-
onChange?.(next);
|
|
1460
|
-
return next;
|
|
1598
|
+
setSettings((prev) => prev[key] === value ? prev : {
|
|
1599
|
+
...prev,
|
|
1600
|
+
[key]: value
|
|
1461
1601
|
});
|
|
1462
|
-
}, [
|
|
1602
|
+
}, []);
|
|
1463
1603
|
const value = useMemo(() => ({
|
|
1464
1604
|
settings,
|
|
1465
1605
|
toggle,
|
|
@@ -1708,6 +1848,6 @@ function useSyntaxStyles() {
|
|
|
1708
1848
|
return useContext(ThemeContext).syntax;
|
|
1709
1849
|
}
|
|
1710
1850
|
//#endregion
|
|
1711
|
-
export {
|
|
1851
|
+
export { toolResultText as $, isOnSafelist as A, shortId as B, CATPPUCCIN_MOCHA as C, IMPLICITLY_SAFE_TOOLS as D, useSafeModeQueue as E, writeProjects as F, eventsFromTurns as G, useConfig as H, runOAuthLogin as I, loadState as J, lastContextSizeFromTurns as K, supportsOAuth as L, projectsFilePath as M, readProjects as N, addToSafelist as O, suggestSafelistEntry as P, toolCallPreview as Q, ageString as R, CATPPUCCIN_MACCHIATO as S, singleAgentRegistry as St, useSafeModeActions as T, resolveConfig as U, ConfigProvider as V, createStateStore as W, stripSpawnTokensLine as X, saveState as Y, titleFromTurns as Z, DEFAULT_THEME as _, BUILD_AGENT as _t, useSyntaxStyles as a, removeProviderCredential as at, CATPPUCCIN_FRAPPE as b, PLAN_AGENT as bt, finalizeStreamingMarkdownForOwner as c, BUILTIN_PROVIDERS as ct, DEFAULT_SETTINGS as d, credKeyOf as dt, detectAuth as et, SETTINGS_CHOICES as f, getContextWindow as ft, BUILTIN_THEMES as g, piIdOf as gt, useSettings as h, openrouterDescriptor as ht, useSurfaces as i, readProviderCredential as it, matchesSafelistEntry as j, getSafelist as k, turnContextSize as l, anthropicDescriptor as lt, SettingsProvider as m, openaiDescriptor as mt, useColors as n, credentialsPath as nt, useTheme as o, setProviderCredential as ot, SETTINGS_TOGGLES as p, modelsForDescriptor as pt, listSessionMeta as q, useSelectStyle as r, readCredentials as rt, finalizeStreamingMarkdown as s, writeCredentials as st, ThemeProvider as t, applyApiKeyEnv as tt, useStreamBuffer as u, cerebrasDescriptor as ut, resolveTheme as v, BUILTIN_AGENTS as vt, SafeModeProvider as w, CATPPUCCIN_LATTE as x, resolveAgentId as xt, VAPORWAVE_THEME as y, DEFAULT_AGENT_ID as yt, fmtTokens as z };
|
|
1712
1852
|
|
|
1713
|
-
//# sourceMappingURL=theme-context-
|
|
1853
|
+
//# sourceMappingURL=theme-context-DQM2lx4U.js.map
|