zidane 5.2.1 → 5.3.1
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 +7 -5
- package/dist/{agent-CGQajqtC.d.ts → agent-bKs7MRT2.d.ts} +429 -4
- package/dist/agent-bKs7MRT2.d.ts.map +1 -0
- package/dist/chat.d.ts +212 -58
- package/dist/chat.d.ts.map +1 -1
- package/dist/chat.js +2 -2
- package/dist/{errors-COmsomd5.js → errors-Byb0F8B9.js} +44 -2
- package/dist/errors-Byb0F8B9.js.map +1 -0
- package/dist/{index-DwbcFBr_.d.ts → index-BlMvPh9X.d.ts} +29 -3
- package/dist/index-BlMvPh9X.d.ts.map +1 -0
- package/dist/{index-BDP6mA3Y.d.ts → index-CTmNaIDb.d.ts} +2 -2
- package/dist/{index-BDP6mA3Y.d.ts.map → index-CTmNaIDb.d.ts.map} +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +10 -10
- package/dist/{interpolate-BhmHKD6x.js → interpolate-ERgZUxgg.js} +2 -2
- package/dist/{interpolate-BhmHKD6x.js.map → interpolate-ERgZUxgg.js.map} +1 -1
- package/dist/{login-D7Tp-K5f.js → login-CNS9_8Ue.js} +3 -3
- package/dist/{login-D7Tp-K5f.js.map → login-CNS9_8Ue.js.map} +1 -1
- package/dist/{mcp-B1psg7jf.js → mcp-ZsSFo4Dp.js} +2 -2
- package/dist/{mcp-B1psg7jf.js.map → mcp-ZsSFo4Dp.js.map} +1 -1
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +1 -1
- package/dist/{messages-DsbMYNmt.js → messages-D0xT979U.js} +631 -68
- package/dist/messages-D0xT979U.js.map +1 -0
- package/dist/{presets-AgF0RFx1.js → presets-h5i3kpOP.js} +2 -2
- package/dist/{presets-AgF0RFx1.js.map → presets-h5i3kpOP.js.map} +1 -1
- package/dist/presets.d.ts +2 -2
- package/dist/presets.js +1 -1
- package/dist/{providers-v1Rn2rqG.js → providers-x3LZByR5.js} +38 -6
- package/dist/providers-x3LZByR5.js.map +1 -0
- package/dist/providers.d.ts +2 -2
- package/dist/providers.js +3 -3
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/session/sqlite.js +1 -1
- package/dist/{session-DOJgRXvF.js → session-BHZwxmfr.js} +2 -2
- package/dist/{session-DOJgRXvF.js.map → session-BHZwxmfr.js.map} +1 -1
- package/dist/session.d.ts +1 -1
- package/dist/session.js +2 -2
- package/dist/skills.d.ts +2 -2
- package/dist/skills.js +1 -1
- package/dist/{tools-BRbbfdJh.js → tools-CWEDS2ZT.js} +251 -47
- package/dist/tools-CWEDS2ZT.js.map +1 -0
- package/dist/tools.d.ts +2 -2
- package/dist/tools.js +1 -1
- package/dist/{transcript-anchors-BBuIoU0x.d.ts → transcript-anchors-DOUqyvXR.d.ts} +28 -4
- package/dist/transcript-anchors-DOUqyvXR.d.ts.map +1 -0
- package/dist/tui.d.ts +29 -3
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +363 -28
- package/dist/tui.js.map +1 -1
- package/dist/{turn-operations-gJ0qtLPv.js → turn-operations-D9HvatsR.js} +396 -89
- package/dist/turn-operations-D9HvatsR.js.map +1 -0
- package/dist/types-IcokUOyC.js.map +1 -1
- package/dist/types.d.ts +2 -2
- package/dist/types.js +1 -1
- package/docs/ARCHITECTURE.md +3 -2
- package/docs/CHAT.md +55 -16
- package/docs/TUI.md +22 -2
- package/package.json +1 -1
- package/dist/agent-CGQajqtC.d.ts.map +0 -1
- package/dist/errors-COmsomd5.js.map +0 -1
- package/dist/index-DwbcFBr_.d.ts.map +0 -1
- package/dist/messages-DsbMYNmt.js.map +0 -1
- package/dist/providers-v1Rn2rqG.js.map +0 -1
- package/dist/tools-BRbbfdJh.js.map +0 -1
- package/dist/transcript-anchors-BBuIoU0x.d.ts.map +0 -1
- package/dist/turn-operations-gJ0qtLPv.js.map +0 -1
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { a as multiEdit, c as grep, d as resolveOldString, f as styleReplacementForVia, i as readFile$1, l as glob, n as createSpawnTool, o as listFiles, r as shell, t as writeFile$1, u as edit } from "./tools-
|
|
2
|
-
import {
|
|
1
|
+
import { a as multiEdit, c as grep, d as resolveOldString, f as styleReplacementForVia, i as readFile$1, l as glob, n as createSpawnTool, o as listFiles, r as shell, t as writeFile$1, u as edit } from "./tools-CWEDS2ZT.js";
|
|
2
|
+
import { s as errorMessage } from "./errors-Byb0F8B9.js";
|
|
3
3
|
import { n as toolResultToText } from "./types-IcokUOyC.js";
|
|
4
|
-
import { r as normalizeMcpServers } from "./mcp-
|
|
5
|
-
import { a as discoverSkills } from "./interpolate-
|
|
4
|
+
import { r as normalizeMcpServers } from "./mcp-ZsSFo4Dp.js";
|
|
5
|
+
import { a as discoverSkills } from "./interpolate-ERgZUxgg.js";
|
|
6
6
|
import { n as formatTokenUsage } from "./stats-DgOvY7wd.js";
|
|
7
|
-
import { n as definePreset, t as composePresets } from "./presets-
|
|
8
|
-
import { a as writeFileAtomic, i as anthropic, n as openai, r as cerebras, t as openrouter } from "./providers-
|
|
7
|
+
import { n as definePreset, t as composePresets } from "./presets-h5i3kpOP.js";
|
|
8
|
+
import { a as writeFileAtomic, i as anthropic, n as openai, r as cerebras, t as openrouter } from "./providers-x3LZByR5.js";
|
|
9
9
|
import { spawn } from "node:child_process";
|
|
10
10
|
import { readdir, stat, writeFile } from "node:fs/promises";
|
|
11
11
|
import { dirname, isAbsolute, join, posix, relative, resolve, sep } from "node:path";
|
|
@@ -260,90 +260,197 @@ const TODOREAD_TOOL = "todoread";
|
|
|
260
260
|
function isTodoTool(name) {
|
|
261
261
|
return name === "todowrite" || name === "todoread";
|
|
262
262
|
}
|
|
263
|
-
/** `session.metadata[TODOS_METADATA_KEY]:
|
|
264
|
-
const TODOS_METADATA_KEY = "
|
|
265
|
-
/** `session.metadata[TODO_WRITE_COUNTS_METADATA_KEY]:
|
|
266
|
-
const TODO_WRITE_COUNTS_METADATA_KEY = "
|
|
263
|
+
/** `session.metadata[TODOS_METADATA_KEY]: TodosBag` — see {@link TodosBag}. */
|
|
264
|
+
const TODOS_METADATA_KEY = "todos";
|
|
265
|
+
/** `session.metadata[TODO_WRITE_COUNTS_METADATA_KEY]: CountsBag` — mirrors `TodosBag` shape. */
|
|
266
|
+
const TODO_WRITE_COUNTS_METADATA_KEY = "todoWriteCounts";
|
|
267
267
|
const TODO_STATUS_VALUES = [
|
|
268
268
|
"pending",
|
|
269
269
|
"in_progress",
|
|
270
270
|
"completed",
|
|
271
271
|
"cancelled"
|
|
272
272
|
];
|
|
273
|
-
const
|
|
274
|
-
|
|
273
|
+
const TODO_STATUS_GLYPHS = {
|
|
274
|
+
pending: "☐",
|
|
275
|
+
in_progress: "◐",
|
|
276
|
+
completed: "☑",
|
|
277
|
+
cancelled: "☒"
|
|
278
|
+
};
|
|
279
|
+
const WRITE_DESCRIPTION = "Replace the active task list. Pass the **full** list of items every call — there is no partial update. The list persists across user prompts in the same session, so an aborted run with `in_progress` items reads back on the next `todoread` and you can pick up where you left off. When every item is `completed`, the list auto-clears so the next prompt starts fresh.\n\nUse the `status` field to track progress: `pending` (queued), `in_progress` (currently working), `completed` (done), `cancelled` (no longer relevant).\n\nOnly checkpoint at significant transitions:\n 1. When the user gives you a multi-step task — write the initial plan with everything `pending`.\n 2. When you transition between steps — mark the previous one `completed` and the next one `in_progress`.\n 3. When the user asks for the current status — re-emit the list unchanged so they can see it.\n\nDo NOT call this on every action. The list is for the user's situational awareness, not for self-narrating.";
|
|
280
|
+
const READ_DESCRIPTION = "Return the current active task list. Returns an empty list if nothing has been written yet, or if the previous batch was auto-cleared after all items completed. Use sparingly — you already see the latest list in your own `todowrite` tool_result above.";
|
|
275
281
|
function defaultReminder(count) {
|
|
276
|
-
return `(You've called todowrite ${count} times
|
|
282
|
+
return `(You've called todowrite ${count} times. Make sure each checkpoint reflects real progress; avoid re-planning every step.)`;
|
|
277
283
|
}
|
|
278
284
|
/**
|
|
279
|
-
*
|
|
280
|
-
*
|
|
285
|
+
* `true` when the run with `runId` is a subagent (has a `parentRunId`).
|
|
286
|
+
* Top-level runs return `false`; an unknown / missing run also returns
|
|
287
|
+
* `false` (defensive — should never happen in practice, but treating an
|
|
288
|
+
* orphan as top-level is the right fallback since the session slot is
|
|
289
|
+
* the more general bucket).
|
|
290
|
+
*/
|
|
291
|
+
function isSubagentRun(session, runId) {
|
|
292
|
+
return !!session.runs.find((r) => r.id === runId)?.parentRunId;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Read the active list for `runId`. Top-level runs see the session-shared
|
|
296
|
+
* slot; subagent runs see their own. Returns a fresh `[]` (not stored in
|
|
297
|
+
* metadata) when no slot exists — the caller can mutate the result
|
|
281
298
|
* without affecting state.
|
|
282
299
|
*/
|
|
283
300
|
function getTodosForRun(session, runId) {
|
|
284
|
-
const
|
|
285
|
-
|
|
301
|
+
const bag = readTodosBag(session);
|
|
302
|
+
if (isSubagentRun(session, runId)) {
|
|
303
|
+
const items = bag.byRun?.[runId];
|
|
304
|
+
return Array.isArray(items) ? [...items] : [];
|
|
305
|
+
}
|
|
306
|
+
return Array.isArray(bag.session) ? [...bag.session] : [];
|
|
286
307
|
}
|
|
287
308
|
/**
|
|
288
|
-
* Replace the active list for
|
|
289
|
-
*
|
|
309
|
+
* Replace the active list for `runId`. Routes to the session-shared slot
|
|
310
|
+
* for top-level runs and to the per-run slot for subagents. Empty arrays
|
|
311
|
+
* delete the slot entirely so persisted metadata stays clean.
|
|
312
|
+
*
|
|
313
|
+
* Side effect: a **non-empty** write also stashes the same list into
|
|
314
|
+
* `bag.archive` (same routing). Empty writes never touch the archive —
|
|
315
|
+
* clearing the live list (whether explicitly or via the tool's auto-
|
|
316
|
+
* clear) preserves the "last shown" snapshot so UI surfaces can keep
|
|
317
|
+
* rendering what was just completed. See {@link getArchivedTodosForRun}.
|
|
290
318
|
*/
|
|
291
319
|
function setTodosForRun(session, runId, items) {
|
|
292
|
-
const bag =
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
320
|
+
const bag = readTodosBag(session);
|
|
321
|
+
const normalized = items.map(normalizeItem);
|
|
322
|
+
const subagent = isSubagentRun(session, runId);
|
|
323
|
+
if (subagent) {
|
|
324
|
+
const byRun = { ...bag.byRun ?? {} };
|
|
325
|
+
if (normalized.length === 0) delete byRun[runId];
|
|
326
|
+
else byRun[runId] = normalized;
|
|
327
|
+
bag.byRun = byRun;
|
|
328
|
+
} else if (normalized.length === 0) delete bag.session;
|
|
329
|
+
else bag.session = normalized;
|
|
330
|
+
if (normalized.length > 0) {
|
|
331
|
+
const archive = { ...bag.archive ?? {} };
|
|
332
|
+
if (subagent) {
|
|
333
|
+
const archiveByRun = { ...archive.byRun ?? {} };
|
|
334
|
+
archiveByRun[runId] = normalized;
|
|
335
|
+
archive.byRun = archiveByRun;
|
|
336
|
+
} else archive.session = normalized;
|
|
337
|
+
bag.archive = archive;
|
|
338
|
+
}
|
|
339
|
+
writeTodosBag(session, bag);
|
|
296
340
|
}
|
|
297
341
|
/**
|
|
298
|
-
*
|
|
299
|
-
*
|
|
300
|
-
*
|
|
342
|
+
* Read the archived (most-recent non-empty) list for `runId`. Same slot
|
|
343
|
+
* routing as {@link getTodosForRun}, but reads `bag.archive` instead of
|
|
344
|
+
* the live slot. Returns a fresh `[]` when no archive exists.
|
|
301
345
|
*
|
|
302
|
-
*
|
|
346
|
+
* UI surfaces use this to keep showing "what was just completed" after
|
|
347
|
+
* the live list auto-clears. The model never sees the archive — it's a
|
|
348
|
+
* read-only sidecar for human-facing rendering.
|
|
349
|
+
*/
|
|
350
|
+
function getArchivedTodosForRun(session, runId) {
|
|
351
|
+
const archive = readTodosBag(session).archive;
|
|
352
|
+
if (!archive) return [];
|
|
353
|
+
if (isSubagentRun(session, runId)) {
|
|
354
|
+
const items = archive.byRun?.[runId];
|
|
355
|
+
return Array.isArray(items) ? [...items] : [];
|
|
356
|
+
}
|
|
357
|
+
return Array.isArray(archive.session) ? [...archive.session] : [];
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Reconcile `session.metadata.todos.byRun` (live + archive) against
|
|
361
|
+
* `session.runs`. Drops subagent slots whose runId isn't in the run
|
|
362
|
+
* list. The top-level `session` slot is unaffected — it's session-
|
|
363
|
+
* scoped, not per-run, so there's no orphan to GC.
|
|
364
|
+
*
|
|
365
|
+
* Useful after `session.setRuns()` (fork / restore) or to GC stale
|
|
366
|
+
* metadata mutated by an external caller. Also prunes the parallel
|
|
367
|
+
* counter bag so the two don't drift.
|
|
368
|
+
*
|
|
369
|
+
* `dropped` reports the live-byRun orphans only (archive-only orphans
|
|
370
|
+
* are silently swept). The live half is the contract callers actually
|
|
371
|
+
* observe.
|
|
303
372
|
*/
|
|
304
373
|
function pruneTodosByRun(session) {
|
|
305
374
|
const validRunIds = new Set(session.runs.map((r) => r.id));
|
|
306
375
|
const dropped = [];
|
|
307
376
|
const bag = readTodosBag(session);
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
377
|
+
let bagChanged = false;
|
|
378
|
+
if (bag.byRun) {
|
|
379
|
+
const nextByRun = {};
|
|
380
|
+
for (const [runId, items] of Object.entries(bag.byRun)) if (validRunIds.has(runId)) nextByRun[runId] = items;
|
|
381
|
+
else {
|
|
382
|
+
dropped.push(runId);
|
|
383
|
+
bagChanged = true;
|
|
384
|
+
}
|
|
385
|
+
if (Object.keys(nextByRun).length !== Object.keys(bag.byRun).length) bag.byRun = nextByRun;
|
|
386
|
+
}
|
|
387
|
+
if (bag.archive?.byRun) {
|
|
388
|
+
const nextByRun = {};
|
|
389
|
+
let archiveChanged = false;
|
|
390
|
+
for (const [runId, items] of Object.entries(bag.archive.byRun)) if (validRunIds.has(runId)) nextByRun[runId] = items;
|
|
391
|
+
else archiveChanged = true;
|
|
392
|
+
if (archiveChanged) {
|
|
393
|
+
bag.archive = {
|
|
394
|
+
...bag.archive,
|
|
395
|
+
byRun: nextByRun
|
|
396
|
+
};
|
|
397
|
+
bagChanged = true;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
if (bagChanged) writeTodosBag(session, bag);
|
|
312
401
|
const counts = readCountsBag(session);
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
402
|
+
if (counts.byRun) {
|
|
403
|
+
const nextByRun = {};
|
|
404
|
+
let changed = false;
|
|
405
|
+
for (const [runId, n] of Object.entries(counts.byRun)) if (validRunIds.has(runId)) nextByRun[runId] = n;
|
|
406
|
+
else changed = true;
|
|
407
|
+
if (changed) {
|
|
408
|
+
counts.byRun = nextByRun;
|
|
409
|
+
writeCountsBag(session, counts);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
318
412
|
return { dropped };
|
|
319
413
|
}
|
|
320
414
|
/**
|
|
321
|
-
* Build a `Preset` carrying the `{ todowrite, todoread }` tool pair
|
|
322
|
-
*
|
|
323
|
-
*
|
|
324
|
-
*
|
|
325
|
-
*
|
|
326
|
-
*
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
-
*
|
|
330
|
-
*
|
|
331
|
-
*
|
|
332
|
-
*
|
|
415
|
+
* Build a `Preset` carrying the `{ todowrite, todoread }` tool pair.
|
|
416
|
+
* Identical-payload dedup is handled inside the tool body — the
|
|
417
|
+
* comparison resolves against the active slot (session-shared for
|
|
418
|
+
* top-level runs, per-run for subagents) and intentionally does NOT
|
|
419
|
+
* plumb through `behavior.dedupTools`. See the `dedupIdentical` option
|
|
420
|
+
* doc for the rationale.
|
|
421
|
+
*
|
|
422
|
+
* By default the preset adds **no** `toolBudgets` entry — `todowrite`
|
|
423
|
+
* is a state-transition tool, so a hard cap is the wrong abstraction
|
|
424
|
+
* (it punishes the legitimate "finish the N-item plan" path). Hosts
|
|
425
|
+
* that want a ceiling pass `maxWritesPerRun: N` explicitly; the
|
|
426
|
+
* factory then plumbs a `behavior.toolBudgets.todowrite` entry
|
|
427
|
+
* through.
|
|
428
|
+
*
|
|
429
|
+
* Returning a `Preset` (not a bare tool map) lets the result flow
|
|
430
|
+
* through {@link composePresets} unchanged — todos compose with any
|
|
431
|
+
* other preset the same way every other preset does. `toolBudgets` is
|
|
432
|
+
* a tool-name-keyed record that `composePresets` deep-merges, so a
|
|
433
|
+
* caller's custom budget entries for other tools survive the
|
|
434
|
+
* layering, and a caller's override for `todowrite` itself wins by
|
|
435
|
+
* being placed later in the chain.
|
|
333
436
|
*
|
|
334
437
|
* ```ts
|
|
335
438
|
* import { basic, composePresets } from 'zidane/presets'
|
|
336
439
|
* import { createTodoTools } from 'zidane/chat'
|
|
337
440
|
*
|
|
441
|
+
* // Default: no budget — relies on the in-band reminder + dedup.
|
|
442
|
+
* createAgent({ ...composePresets(basic, createTodoTools()), provider })
|
|
443
|
+
*
|
|
444
|
+
* // Opt-in hard cap: refuse > 20 writes per run.
|
|
338
445
|
* createAgent({
|
|
339
|
-
* ...composePresets(basic, createTodoTools({ maxWritesPerRun:
|
|
446
|
+
* ...composePresets(basic, createTodoTools({ maxWritesPerRun: 20 })),
|
|
340
447
|
* provider,
|
|
341
448
|
* })
|
|
342
449
|
* ```
|
|
343
450
|
*
|
|
344
451
|
* For the trivial "just add the tools to an existing config" case, plain
|
|
345
|
-
* spread is also fine since the returned `Preset` only sets `tools`
|
|
346
|
-
* `behavior
|
|
452
|
+
* spread is also fine since the returned `Preset` only sets `tools`
|
|
453
|
+
* (and `behavior` when a budget is opted in):
|
|
347
454
|
*
|
|
348
455
|
* ```ts
|
|
349
456
|
* createAgent({ ...basic, ...createTodoTools(), provider })
|
|
@@ -354,7 +461,7 @@ function createTodoTools(options = {}) {
|
|
|
354
461
|
const remindAfter = options.remindAfter ?? 3;
|
|
355
462
|
const reminderText = options.reminderText ?? ((count, _items) => defaultReminder(count));
|
|
356
463
|
const dedupIdentical = options.dedupIdentical ?? true;
|
|
357
|
-
const maxWritesPerRun = options.maxWritesPerRun ??
|
|
464
|
+
const maxWritesPerRun = options.maxWritesPerRun ?? 0;
|
|
358
465
|
const onMaxWrites = options.onMaxWrites ?? "steer";
|
|
359
466
|
const tools = {
|
|
360
467
|
[TODOWRITE_TOOL]: createTodoWriteTool({
|
|
@@ -425,25 +532,34 @@ function createTodoWriteTool(opts) {
|
|
|
425
532
|
const current = getTodosForRun(session, runId);
|
|
426
533
|
const unchanged = opts.dedupIdentical && todosEqual(current, normalized);
|
|
427
534
|
const count = incrementCount(session, runId);
|
|
428
|
-
|
|
535
|
+
const allCompleted = normalized.length > 0 && normalized.every((t) => t.status === "completed");
|
|
536
|
+
if (!unchanged) if (allCompleted) {
|
|
537
|
+
setTodosForRun(session, runId, normalized);
|
|
538
|
+
setTodosForRun(session, runId, []);
|
|
539
|
+
} else setTodosForRun(session, runId, normalized);
|
|
429
540
|
return formatWriteResult({
|
|
430
541
|
items: normalized,
|
|
431
542
|
dropped,
|
|
432
543
|
count,
|
|
433
544
|
unchanged,
|
|
545
|
+
cleared: allCompleted && !unchanged,
|
|
434
546
|
opts
|
|
435
547
|
});
|
|
436
548
|
}
|
|
437
549
|
};
|
|
438
550
|
}
|
|
439
551
|
function formatWriteResult(input) {
|
|
440
|
-
const { items, dropped, count, unchanged, opts } = input;
|
|
552
|
+
const { items, dropped, count, unchanged, cleared, opts } = input;
|
|
441
553
|
const lines = [];
|
|
442
554
|
const n = items.length;
|
|
443
555
|
const suffix = n === 1 ? "" : "s";
|
|
444
|
-
lines.push(
|
|
445
|
-
|
|
446
|
-
|
|
556
|
+
if (cleared) lines.push(`Marked ${n} item${suffix} complete — list cleared.`);
|
|
557
|
+
else if (unchanged) lines.push(`No change — ${n} todo item${suffix} already tracked.`);
|
|
558
|
+
else lines.push(`Updated ${n} todo item${suffix}.`);
|
|
559
|
+
if (!cleared) {
|
|
560
|
+
const tally = summarizeStatuses(items);
|
|
561
|
+
if (tally) lines.push(tally);
|
|
562
|
+
}
|
|
447
563
|
if (dropped > 0) lines.push(`Dropped ${dropped} malformed item${dropped === 1 ? "" : "s"}.`);
|
|
448
564
|
const reminder = opts.remindAfter > 0 && count >= opts.remindAfter ? opts.reminderText(count, items) : void 0;
|
|
449
565
|
if (reminder && reminder.length > 0) lines.push(reminder);
|
|
@@ -479,23 +595,74 @@ function requireSessionAndRun(ctx, toolName) {
|
|
|
479
595
|
runId: ctx.runId
|
|
480
596
|
};
|
|
481
597
|
}
|
|
598
|
+
/** Read the todos bag from session metadata, normalizing the live shape. */
|
|
482
599
|
function readTodosBag(session) {
|
|
483
600
|
const raw = session.metadata[TODOS_METADATA_KEY];
|
|
484
|
-
if (!raw
|
|
485
|
-
|
|
601
|
+
if (!isPlainObject(raw)) return {};
|
|
602
|
+
const archive = isPlainObject(raw.archive) ? {
|
|
603
|
+
session: Array.isArray(raw.archive.session) ? raw.archive.session : void 0,
|
|
604
|
+
byRun: isPlainObject(raw.archive.byRun) ? raw.archive.byRun : void 0
|
|
605
|
+
} : void 0;
|
|
606
|
+
return {
|
|
607
|
+
session: Array.isArray(raw.session) ? raw.session : void 0,
|
|
608
|
+
byRun: isPlainObject(raw.byRun) ? raw.byRun : void 0,
|
|
609
|
+
archive
|
|
610
|
+
};
|
|
611
|
+
}
|
|
612
|
+
function writeTodosBag(session, bag) {
|
|
613
|
+
const clean = {};
|
|
614
|
+
if (bag.session && bag.session.length > 0) clean.session = bag.session;
|
|
615
|
+
if (bag.byRun && Object.keys(bag.byRun).length > 0) clean.byRun = bag.byRun;
|
|
616
|
+
if (bag.archive) {
|
|
617
|
+
const archive = {};
|
|
618
|
+
if (bag.archive.session && bag.archive.session.length > 0) archive.session = bag.archive.session;
|
|
619
|
+
if (bag.archive.byRun && Object.keys(bag.archive.byRun).length > 0) archive.byRun = bag.archive.byRun;
|
|
620
|
+
if (archive.session || archive.byRun) clean.archive = archive;
|
|
621
|
+
}
|
|
622
|
+
session.setMeta(TODOS_METADATA_KEY, clean);
|
|
486
623
|
}
|
|
487
624
|
function readCountsBag(session) {
|
|
488
625
|
const raw = session.metadata[TODO_WRITE_COUNTS_METADATA_KEY];
|
|
489
|
-
if (!raw
|
|
490
|
-
return
|
|
626
|
+
if (!isPlainObject(raw)) return {};
|
|
627
|
+
return {
|
|
628
|
+
session: typeof raw.session === "number" ? raw.session : void 0,
|
|
629
|
+
byRun: isPlainObject(raw.byRun) ? raw.byRun : void 0
|
|
630
|
+
};
|
|
491
631
|
}
|
|
632
|
+
function writeCountsBag(session, bag) {
|
|
633
|
+
const clean = {};
|
|
634
|
+
if (typeof bag.session === "number" && bag.session > 0) clean.session = bag.session;
|
|
635
|
+
if (bag.byRun && Object.keys(bag.byRun).length > 0) clean.byRun = bag.byRun;
|
|
636
|
+
session.setMeta(TODO_WRITE_COUNTS_METADATA_KEY, clean);
|
|
637
|
+
}
|
|
638
|
+
/**
|
|
639
|
+
* Bump the call counter for the active slot and return the new value.
|
|
640
|
+
* Top-level runs increment `bag.session` (cumulative across prompts);
|
|
641
|
+
* subagent runs increment their own entry under `bag.byRun`. Same
|
|
642
|
+
* keying as {@link setTodosForRun} so the counter and the data move
|
|
643
|
+
* together — a freshly seeded run's count starts at 1 on its first
|
|
644
|
+
* write, a continuing top-level run's count picks up from where the
|
|
645
|
+
* prior prompt left off.
|
|
646
|
+
*/
|
|
492
647
|
function incrementCount(session, runId) {
|
|
493
|
-
const bag =
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
648
|
+
const bag = readCountsBag(session);
|
|
649
|
+
let next;
|
|
650
|
+
if (isSubagentRun(session, runId)) {
|
|
651
|
+
const byRun = { ...bag.byRun ?? {} };
|
|
652
|
+
next = (byRun[runId] ?? 0) + 1;
|
|
653
|
+
byRun[runId] = next;
|
|
654
|
+
bag.byRun = byRun;
|
|
655
|
+
} else {
|
|
656
|
+
next = (bag.session ?? 0) + 1;
|
|
657
|
+
bag.session = next;
|
|
658
|
+
}
|
|
659
|
+
writeCountsBag(session, bag);
|
|
497
660
|
return next;
|
|
498
661
|
}
|
|
662
|
+
/** Narrow guard — `Record<string, unknown>` excluding arrays / null. */
|
|
663
|
+
function isPlainObject(v) {
|
|
664
|
+
return !!v && typeof v === "object" && !Array.isArray(v);
|
|
665
|
+
}
|
|
499
666
|
function normalizeItem(item) {
|
|
500
667
|
return {
|
|
501
668
|
id: item.id,
|
|
@@ -557,6 +724,109 @@ function todosEqual(a, b) {
|
|
|
557
724
|
}
|
|
558
725
|
return true;
|
|
559
726
|
}
|
|
727
|
+
const EMPTY_TALLY = {
|
|
728
|
+
pending: 0,
|
|
729
|
+
in_progress: 0,
|
|
730
|
+
completed: 0,
|
|
731
|
+
cancelled: 0
|
|
732
|
+
};
|
|
733
|
+
const EMPTY_ACTIVE = {
|
|
734
|
+
runId: null,
|
|
735
|
+
todos: [],
|
|
736
|
+
archive: [],
|
|
737
|
+
inProgress: null,
|
|
738
|
+
tally: EMPTY_TALLY
|
|
739
|
+
};
|
|
740
|
+
/**
|
|
741
|
+
* Pick the "active" run for UI surfaces that show one slot at a time
|
|
742
|
+
* (todos indicator, todos modal, footer ctx indicator). The resolved
|
|
743
|
+
* runId then routes through {@link getTodosForRun} — top-level runs
|
|
744
|
+
* land on the session-shared slot, subagent runs on their own.
|
|
745
|
+
*
|
|
746
|
+
* - A currently-running run wins (latest-started one if several).
|
|
747
|
+
* - Otherwise the most recently appended run wins.
|
|
748
|
+
* - `null` when the session has no runs.
|
|
749
|
+
*
|
|
750
|
+
* Mirrors the "most recent thing that mattered" policy that drives
|
|
751
|
+
* `lastContextSizeFromTurns` — but walks `session.runs` rather than
|
|
752
|
+
* `session.turns` because the active todo slot is a function of the
|
|
753
|
+
* run, not of message history.
|
|
754
|
+
*/
|
|
755
|
+
function pickActiveRunId(session) {
|
|
756
|
+
if (!session) return null;
|
|
757
|
+
const runs = session.runs;
|
|
758
|
+
if (!runs || runs.length === 0) return null;
|
|
759
|
+
let latestRunning = null;
|
|
760
|
+
for (let i = runs.length - 1; i >= 0; i--) if (runs[i].status === "running") {
|
|
761
|
+
latestRunning = runs[i].id;
|
|
762
|
+
break;
|
|
763
|
+
}
|
|
764
|
+
if (latestRunning) return latestRunning;
|
|
765
|
+
return runs[runs.length - 1].id;
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Pure selector — derive the active-todos state from a session snapshot.
|
|
769
|
+
* Used by {@link useActiveTodos} and directly testable without React.
|
|
770
|
+
*
|
|
771
|
+
* Resolves both `todos` (live, model-facing) and `archive` (last
|
|
772
|
+
* non-empty snapshot for UI fallback). The tally folds over whichever
|
|
773
|
+
* list is non-empty; `inProgress` is sourced strictly from `todos`
|
|
774
|
+
* because an archived in-progress item is by definition stale.
|
|
775
|
+
*/
|
|
776
|
+
function selectActiveTodos(session) {
|
|
777
|
+
const runId = pickActiveRunId(session);
|
|
778
|
+
if (!session || !runId) return EMPTY_ACTIVE;
|
|
779
|
+
const todos = getTodosForRun(session, runId);
|
|
780
|
+
const archive = getArchivedTodosForRun(session, runId);
|
|
781
|
+
const display = todos.length > 0 ? todos : archive;
|
|
782
|
+
if (display.length === 0) return {
|
|
783
|
+
runId,
|
|
784
|
+
todos,
|
|
785
|
+
archive,
|
|
786
|
+
inProgress: null,
|
|
787
|
+
tally: EMPTY_TALLY
|
|
788
|
+
};
|
|
789
|
+
const tally = {
|
|
790
|
+
pending: 0,
|
|
791
|
+
in_progress: 0,
|
|
792
|
+
completed: 0,
|
|
793
|
+
cancelled: 0
|
|
794
|
+
};
|
|
795
|
+
let inProgress = null;
|
|
796
|
+
for (const t of display) tally[t.status] += 1;
|
|
797
|
+
if (todos.length > 0) {
|
|
798
|
+
for (const t of todos) if (t.status === "in_progress") {
|
|
799
|
+
inProgress = t;
|
|
800
|
+
break;
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
return {
|
|
804
|
+
runId,
|
|
805
|
+
todos,
|
|
806
|
+
archive,
|
|
807
|
+
inProgress,
|
|
808
|
+
tally
|
|
809
|
+
};
|
|
810
|
+
}
|
|
811
|
+
/**
|
|
812
|
+
* React hook — active-todos state for the supplied session. Recomputes
|
|
813
|
+
* on every parent re-render; the work is O(runs + todos), both bounded
|
|
814
|
+
* by small constants in practice.
|
|
815
|
+
*
|
|
816
|
+
* Why no memoization: `Session.runs` is mutated in place by `completeRun`
|
|
817
|
+
* / `abortRun` (status flips without changing array length or item
|
|
818
|
+
* identity), so any memo keyed off length / bag identity would silently
|
|
819
|
+
* return stale state when e.g. a child subagent run completes and the
|
|
820
|
+
* "active" run should reflow to the parent. The selector is cheap
|
|
821
|
+
* enough that running it every parent render is the simpler, correct
|
|
822
|
+
* answer — see `selectActiveTodos` for the O(n) cost.
|
|
823
|
+
*
|
|
824
|
+
* The hook lives in `chat/` so a GUI consumer can mount it verbatim.
|
|
825
|
+
* Renderer-agnostic — no `@opentui/*` imports.
|
|
826
|
+
*/
|
|
827
|
+
function useActiveTodos(session) {
|
|
828
|
+
return selectActiveTodos(session);
|
|
829
|
+
}
|
|
560
830
|
//#endregion
|
|
561
831
|
//#region src/chat/agents.ts
|
|
562
832
|
/**
|
|
@@ -1855,6 +2125,12 @@ const KEYBINDING_DEFS = [
|
|
|
1855
2125
|
label: "effort",
|
|
1856
2126
|
description: "open the reasoning-effort picker (when the active model supports it)"
|
|
1857
2127
|
},
|
|
2128
|
+
{
|
|
2129
|
+
action: "openTodos",
|
|
2130
|
+
default: "ctrl+t",
|
|
2131
|
+
label: "todos",
|
|
2132
|
+
description: "open the active run's todo list (the agent's `todowrite` checkpoints)"
|
|
2133
|
+
},
|
|
1858
2134
|
{
|
|
1859
2135
|
action: "cycleAgent",
|
|
1860
2136
|
default: "shift+tab",
|
|
@@ -2906,10 +3182,6 @@ function eventsFromTurns(turns, runs = []) {
|
|
|
2906
3182
|
pushSpawnStart(run);
|
|
2907
3183
|
openStack.push(run);
|
|
2908
3184
|
}
|
|
2909
|
-
if (depth === 0 && lastDepthAtEmission === 0) events.push({
|
|
2910
|
-
kind: "separator",
|
|
2911
|
-
text: ""
|
|
2912
|
-
});
|
|
2913
3185
|
const subagentTag = depth > 0 && turn.runId ? {
|
|
2914
3186
|
childId: labelFor(turn.runId),
|
|
2915
3187
|
depth
|
|
@@ -2920,11 +3192,17 @@ function eventsFromTurns(turns, runs = []) {
|
|
|
2920
3192
|
};
|
|
2921
3193
|
if (turn.role === "user") {
|
|
2922
3194
|
for (const block of turn.content) if (block.type === "text" && block.text.trim()) {
|
|
2923
|
-
if (depth === 0)
|
|
2924
|
-
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
3195
|
+
if (depth === 0) {
|
|
3196
|
+
if (lastDepthAtEmission === 0) events.push({
|
|
3197
|
+
kind: "separator",
|
|
3198
|
+
text: ""
|
|
3199
|
+
});
|
|
3200
|
+
events.push({
|
|
3201
|
+
kind: "user-prompt",
|
|
3202
|
+
text: block.text,
|
|
3203
|
+
turnId: turn.id
|
|
3204
|
+
});
|
|
3205
|
+
}
|
|
2928
3206
|
} else if (block.type === "tool_result") {
|
|
2929
3207
|
const tool = toolByCallId.get(block.callId);
|
|
2930
3208
|
const raw = toolResultText(block.output);
|
|
@@ -4444,7 +4722,9 @@ const DEFAULT_SETTINGS = {
|
|
|
4444
4722
|
showEditDiffs: true,
|
|
4445
4723
|
targetFps: 60,
|
|
4446
4724
|
allowInteraction: true,
|
|
4447
|
-
smoothStreaming: true
|
|
4725
|
+
smoothStreaming: true,
|
|
4726
|
+
showTodoIndicator: true,
|
|
4727
|
+
showThrobber: false
|
|
4448
4728
|
};
|
|
4449
4729
|
/**
|
|
4450
4730
|
* Hard-clamp a `targetFps` value to a safe range before handing it to
|
|
@@ -4559,6 +4839,16 @@ const SETTINGS_TOGGLES = [
|
|
|
4559
4839
|
key: "smoothStreaming",
|
|
4560
4840
|
label: "Smooth streaming",
|
|
4561
4841
|
description: "drip-feed streamed text character-by-character at a steady cadence (typewriter effect)"
|
|
4842
|
+
},
|
|
4843
|
+
{
|
|
4844
|
+
key: "showTodoIndicator",
|
|
4845
|
+
label: "Todo indicator",
|
|
4846
|
+
description: "show the subtle \"in progress\" todo line above the prompt (modal stays accessible regardless)"
|
|
4847
|
+
},
|
|
4848
|
+
{
|
|
4849
|
+
key: "showThrobber",
|
|
4850
|
+
label: "Streaming throbber",
|
|
4851
|
+
description: "animated gradient glyphs at the transcript tail while the assistant is working"
|
|
4562
4852
|
}
|
|
4563
4853
|
];
|
|
4564
4854
|
const SETTINGS_CHOICES = [
|
|
@@ -6288,7 +6578,7 @@ function getSafelist(dataDir, projectDir) {
|
|
|
6288
6578
|
return readProjects(dataDir)[projectDir]?.safelist ?? [];
|
|
6289
6579
|
}
|
|
6290
6580
|
/**
|
|
6291
|
-
* Tools that always pass without prompting.
|
|
6581
|
+
* Tools that always pass without prompting. Three categories:
|
|
6292
6582
|
*
|
|
6293
6583
|
* - **Pure reads** (`read_file`, `list_files`, `glob`, `grep`) — no
|
|
6294
6584
|
* side effects on disk or the model's own state.
|
|
@@ -6296,6 +6586,12 @@ function getSafelist(dataDir, projectDir) {
|
|
|
6296
6586
|
* itself surfaces a TUI picker the user has to answer, so prompting
|
|
6297
6587
|
* for approval first would mean "approve this prompt before you see
|
|
6298
6588
|
* the prompt": redundant + breaks the flow. The picker IS the gate.
|
|
6589
|
+
* - **Todos** (`todowrite`, `todoread`) — write to a slot on
|
|
6590
|
+
* `session.metadata.todos` and nothing else. No shell, no disk, no
|
|
6591
|
+
* network. The model uses these for checkpointing every few steps;
|
|
6592
|
+
* a per-call approval prompt would drown the conversation in
|
|
6593
|
+
* interruptions that buy no safety since the tool's surface is
|
|
6594
|
+
* read/write on a metadata bag we already trust the agent with.
|
|
6299
6595
|
*
|
|
6300
6596
|
* Users who want to gate any of these must disable safe-mode entirely
|
|
6301
6597
|
* (or fork this list in their own embedding).
|
|
@@ -6306,7 +6602,9 @@ const IMPLICITLY_SAFE_TOOLS = [
|
|
|
6306
6602
|
"glob",
|
|
6307
6603
|
"grep",
|
|
6308
6604
|
"ask_user",
|
|
6309
|
-
"present_plan"
|
|
6605
|
+
"present_plan",
|
|
6606
|
+
"todowrite",
|
|
6607
|
+
"todoread"
|
|
6310
6608
|
];
|
|
6311
6609
|
/** Common input keys carrying the "primary argument" we scope safelists on. */
|
|
6312
6610
|
const PRIMARY_ARG_KEYS = [
|
|
@@ -6822,15 +7120,16 @@ const TICK_INTERVAL_MS = 16;
|
|
|
6822
7120
|
/**
|
|
6823
7121
|
* Smooth-streaming display rate, in characters per second.
|
|
6824
7122
|
*
|
|
6825
|
-
* - {@link SMOOTH_BASE_CPS} —
|
|
6826
|
-
*
|
|
6827
|
-
* typist's pace; comfortably readable without feeling like a deliberate
|
|
7123
|
+
* - {@link SMOOTH_BASE_CPS} — calm-state cap. ~200 CPS is a fast typist's
|
|
7124
|
+
* pace; comfortably readable without feeling like a deliberate
|
|
6828
7125
|
* typewriter performance.
|
|
6829
|
-
* - {@link SMOOTH_BURST_CPS} —
|
|
6830
|
-
*
|
|
6831
|
-
*
|
|
6832
|
-
*
|
|
6833
|
-
* the
|
|
7126
|
+
* - {@link SMOOTH_BURST_CPS} — cap once the buffer is the full
|
|
7127
|
+
* {@link SMOOTH_BURST_BACKLOG_CHARS} behind the provider. The rate
|
|
7128
|
+
* ramps continuously from base to burst across that range (see
|
|
7129
|
+
* {@link smoothCharsForTick}) so the typewriter cadence never visibly
|
|
7130
|
+
* "steps up" mid-stream — the old step function (BASE for <100,
|
|
7131
|
+
* BURST for ≥100) tripled the chars-per-frame the instant the
|
|
7132
|
+
* threshold was crossed, which read as the text jumping.
|
|
6834
7133
|
* - {@link SMOOTH_INSTANT_BACKLOG_CHARS} — failsafe. If the buffer
|
|
6835
7134
|
* somehow accumulates >2K chars (paste-heavy responses, model dumping
|
|
6836
7135
|
* pre-computed text, etc.) the ticker stops smoothing entirely for
|
|
@@ -6839,7 +7138,7 @@ const TICK_INTERVAL_MS = 16;
|
|
|
6839
7138
|
*/
|
|
6840
7139
|
const SMOOTH_BASE_CPS = 200;
|
|
6841
7140
|
const SMOOTH_BURST_CPS = 600;
|
|
6842
|
-
const SMOOTH_BURST_BACKLOG_CHARS =
|
|
7141
|
+
const SMOOTH_BURST_BACKLOG_CHARS = 400;
|
|
6843
7142
|
const SMOOTH_INSTANT_BACKLOG_CHARS = 2e3;
|
|
6844
7143
|
const PARENT_OWNER = "parent";
|
|
6845
7144
|
function emptyBucket(owner, depth) {
|
|
@@ -6963,11 +7262,19 @@ function turnContextSize(usage) {
|
|
|
6963
7262
|
* current backlog of one bucket. Caps at the bucket length (never
|
|
6964
7263
|
* over-drains) and bypasses smoothing entirely once the backlog goes
|
|
6965
7264
|
* past {@link SMOOTH_INSTANT_BACKLOG_CHARS}.
|
|
7265
|
+
*
|
|
7266
|
+
* The CPS ramps continuously from {@link SMOOTH_BASE_CPS} at zero backlog
|
|
7267
|
+
* to {@link SMOOTH_BURST_CPS} at {@link SMOOTH_BURST_BACKLOG_CHARS},
|
|
7268
|
+
* then plateaus at burst up to the instant cliff. Continuous (vs. the
|
|
7269
|
+
* legacy step at the burst threshold) so the chars-per-frame count never
|
|
7270
|
+
* jumps mid-stream — visible jumps in the typewriter cadence read as the
|
|
7271
|
+
* text itself jumping.
|
|
6966
7272
|
*/
|
|
6967
7273
|
function smoothCharsForTick(backlog) {
|
|
6968
7274
|
if (backlog <= 0) return 0;
|
|
6969
7275
|
if (backlog >= SMOOTH_INSTANT_BACKLOG_CHARS) return backlog;
|
|
6970
|
-
|
|
7276
|
+
const cps = SMOOTH_BASE_CPS + Math.min(1, backlog / SMOOTH_BURST_BACKLOG_CHARS) * (SMOOTH_BURST_CPS - SMOOTH_BASE_CPS);
|
|
7277
|
+
return Math.max(1, Math.min(backlog, Math.ceil(cps * TICK_INTERVAL_MS / 1e3)));
|
|
6971
7278
|
}
|
|
6972
7279
|
/**
|
|
6973
7280
|
* Slice `n` chars off the front of `buf` without splitting a UTF-16
|
|
@@ -7626,6 +7933,6 @@ function countNeighbors(turnIds, turnId) {
|
|
|
7626
7933
|
};
|
|
7627
7934
|
}
|
|
7628
7935
|
//#endregion
|
|
7629
|
-
export { useMcpAuthDispatch as $, bootTick as $n, isVisible as $t, getSafelist as A, KEYBINDING_DEF_BY_ACTION as An, TODOREAD_TOOL as Ar, clampFps as At, supportsOAuth as B, uniqueSkillNamesFromReferences as Bn,
|
|
7936
|
+
export { useMcpAuthDispatch as $, bootTick as $n, TOKEN_DISCIPLINE_DOCTRINE as $r, isVisible as $t, getSafelist as A, KEYBINDING_DEF_BY_ACTION as An, TODOREAD_TOOL as Ar, clampFps as At, supportsOAuth as B, uniqueSkillNamesFromReferences as Bn, pruneTodosByRun as Br, CATPPUCCIN_MOCHA as Bt, resolveSessionExportTarget as C, maskToOutcomeKinds as Cn, BUILTIN_AGENTS as Cr, shortId as Ct, useSafeModeQueue as D, findGitRoot$1 as Dn, accentColor as Dr, SETTINGS_CHOICES as Dt, useSafeModeActions as E, summarizeOutcomes as En, PLAN_AGENT as Er, DEFAULT_SETTINGS as Et, suggestSafelistEntry as F, parseBindingSpec as Fn, createTodoTools as Fr, resolveTheme as Ft, defaultMcpsConfigPaths as G, collectReferences as Gn, COMMUNICATION_DOCTRINE as Gr, ConfigProvider as Gt, filterModelCatalog as H, createFilesCompletionProvider as Hn, setTodosForRun as Hr, DiscoveryProvider as Ht, writeProjects as I, readKeybindings as In, getArchivedTodosForRun as Ir, VAPORWAVE_THEME as It, projectUserPaths as J, useCompletion as Jn, INTERACTION_GUIDANCE as Jr, createStateStore as Jt, discoverProjectMcps as K, findActiveTrigger as Kn, DOING_TASKS_DOCTRINE as Kr, useConfig as Kt, splitPromptSegments as L, stripJsonComments as Ln, getTodosForRun as Lr, CATPPUCCIN_FRAPPE as Lt, matchesSafelistEntry as M, keybindingsPath as Mn, TODOWRITE_TOOL as Mr, BUILTIN_THEMES as Mt, projectsFilePath as N, matchesBinding as Nn, TODO_STATUS_GLYPHS as Nr, DEFAULT_THEME as Nt, IMPLICITLY_SAFE_TOOLS as O, DEFAULT_KEYBINDINGS as On, resolveAgentId as Or, SETTINGS_TOGGLES as Ot, readProjects as P, mergeKeybindings as Pn, TODO_WRITE_COUNTS_METADATA_KEY as Pr, resolveChipColor as Pt, McpAuthProvider as Q, bootProfileEnabled as Qn, SUBAGENT_GUIDANCE as Qr, isTurnHighlighted as Qt, formatPathForCwd as R, SKILLS_TRIGGER as Rn, isTodoTool as Rr, CATPPUCCIN_LATTE as Rt, renderSession as S, buildEditOutcomesAnnotation as Sn, BUILD_AGENT as Sr, fmtTokens as St, SafeModeProvider as T, resolveApprovalForPayload as Tn, DEFAULT_PERSIST_EXCLUDE_TOOLS as Tr, useEnabledToggleSet as Tt, indexOfEntry as U, uniqueFilesFromReferences as Un, useActiveTodos as Ur, useDiscovery as Ut, buildModelCatalog as V, FILES_TRIGGER as Vn, selectActiveTodos as Vr, createDiscoverySlot as Vt, buildMcpServers as W, applyInsert as Wn, ACTIONS_WITH_CARE_DOCTRINE as Wr, useDiscoveryOptional as Wt, mcpCredentialsPath as X, buildLinearRamp as Xn, PLAN_MODE_DOCTRINE as Xr, eventsFromTurns as Xt, createFileMcpCredentialStore as Y, blendHsl as Yn, INTERACTION_GUIDANCE_NO_PROMPTS as Yr, deriveSessionTitle as Yt, patchMcpCredential as Z, tryOpenBrowser as Zn, PLAN_MODE_DOCTRINE_NO_PROMPTS as Zr, isEditErrorResult as Zt, turnContextSize as _, extractEditPayload as _n, modelSupportsReasoning as _r, truncateTrailing as _t, computeTurnAnchors as a, selectableTurnIds as an, readProviderCredential as ar, InteractionsProvider as at, defaultSkillScanPaths as b, splitLines as bn, openrouterDescriptor as br, ageString as bt, formatToolCall as c, titleFromTurns as cn, writeCredentials as cr, createInteractionTools as ct, useSelectStyle as d, turnSelectionOwnership as dn, anthropicDescriptor as dr, pendingInteractionsFromTurns as dt, buildBuildSystem as ei, lastContextSizeFromTurns as en, shouldAutoCompact as er, useMcpAuthState as et, useSurfaces as f, applyEditPayload as fn, cerebrasDescriptor as fr, serializeInteractionResponse as ft, finalizeStreamingMarkdownForOwner as g, computeLineDiff as gn, getModelInfo as gr, hintsLength as gt, finalizeStreamingMarkdown as h, computeInlineDiff as hn, getContextWindow as hr, clipHintsToWidth as ht, turnAsText as i, saveState as in, readCredentials as ir, ASK_USER_TOOL as it, isOnSafelist as j, ensureKeybindingsFile as jn, TODOS_METADATA_KEY as jr, useSettings as jt, addToSafelist as k, KEYBINDING_DEFS as kn, singleAgentRegistry as kr, SettingsProvider as kt, ThemeProvider as l, toolCallPreview as ln, BUILTIN_PROVIDERS as lr, isInteractionTool as lt, useTheme as m, buildUnifiedDiff as mn, effectiveContextWindow as mr, useInteractionsQueue as mt, deleteTurnSafely as n, envSection as ni, loadState as nn, applyApiKeyEnv as nr, reduceMcpAuth as nt, TOOL_DISPLAY as o, stripSpawnTokensLine as on, removeProviderCredential as or, PRESENT_PLAN_TOOL as ot, useSyntaxStyles as p, buildContextualDiff as pn, credKeyOf as pr, useInteractionsActions as pt, parseMcpsFile as q, mergeReferences as qn, IDENTITY_PREFIX as qr, resolveConfig as qt, truncateTurnsAt as r, marginTopFor as rn, credentialsPath as rr, splitMarkdownCodeBlocks as rt, displayNameFor as s, sumRunCosts as sn, setProviderCredential as sr, buildResumedToolResultsTurn as st, countNeighbors as t, buildPlanSystem as ti, listSessionMeta as tn, detectAuth as tr, getMcpAuthStatus as tt, useColors as u, toolResultText as un, OUTPUT_RESERVE_TOKENS as ur, makeRequestInteraction as ut, useStreamBuffer as v, filetypeFromPath as vn, modelsForDescriptor as vr, cleanTitle as vt, writeSessionExport as w, parseEditOutcomesFromResult as wn, DEFAULT_AGENT_ID as wr, listProjectFiles as wt, discoverProjectSkills as x, tokenize as xn, piIdOf as xr, compactPath as xt, buildSkillsConfig as y, previewEditPayload as yn, openaiDescriptor as yr, generateSessionTitle as yt, runOAuthLogin as z, createSkillsCompletionProvider as zn, pickActiveRunId as zr, CATPPUCCIN_MACCHIATO as zt };
|
|
7630
7937
|
|
|
7631
|
-
//# sourceMappingURL=turn-operations-
|
|
7938
|
+
//# sourceMappingURL=turn-operations-D9HvatsR.js.map
|