zidane 5.10.13 → 5.11.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 +31 -5
- package/dist/{agent-BHkvYIH9.d.ts → agent-D0W9yClt.d.ts} +114 -27
- package/dist/agent-D0W9yClt.d.ts.map +1 -0
- package/dist/chat/pure.d.ts +3 -3
- package/dist/chat.d.ts +7 -7
- package/dist/chat.js +2 -2
- package/dist/contexts/docker.d.ts +1 -1
- package/dist/contexts/docker.d.ts.map +1 -1
- package/dist/contexts/docker.js +53 -14
- package/dist/contexts/docker.js.map +1 -1
- package/dist/contexts/e2b.d.ts +168 -0
- package/dist/contexts/e2b.d.ts.map +1 -0
- package/dist/contexts/e2b.js +261 -0
- package/dist/contexts/e2b.js.map +1 -0
- package/dist/{contexts-BJVgG0LY.js → contexts-DglWSzmR.js} +59 -9
- package/dist/contexts-DglWSzmR.js.map +1 -0
- package/dist/contexts.d.ts +3 -3
- package/dist/contexts.js +1 -1
- package/dist/eval.d.ts +1 -1
- package/dist/eval.js +5 -5
- package/dist/eval.js.map +1 -1
- package/dist/{headless-CPaunZsU.js → headless-Bb5gU8AR.js} +6 -6
- package/dist/{headless-CPaunZsU.js.map → headless-Bb5gU8AR.js.map} +1 -1
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +1 -1
- package/dist/{index-C_t8tW_X.d.ts → index-CrMb8jCE.d.ts} +2 -2
- package/dist/{index-C_t8tW_X.d.ts.map → index-CrMb8jCE.d.ts.map} +1 -1
- package/dist/{index-BIo67xLV.d.ts → index-D60tX5XC.d.ts} +10 -3
- package/dist/index-D60tX5XC.d.ts.map +1 -0
- package/dist/{index-C4aT2kO_.d.ts → index-DZR99FD4.d.ts} +30 -111
- package/dist/index-DZR99FD4.d.ts.map +1 -0
- package/dist/index.d.ts +7 -6
- package/dist/index.js +11 -10
- package/dist/index.js.map +1 -1
- package/dist/{interpolate-Dy7Lunvg.js → interpolate-CTfr0GdR.js} +19 -1
- package/dist/{interpolate-Dy7Lunvg.js.map → interpolate-CTfr0GdR.js.map} +1 -1
- package/dist/logger-Ktm-lj1s.js +300 -0
- package/dist/logger-Ktm-lj1s.js.map +1 -0
- package/dist/logger-n4LsLISE.d.ts +102 -0
- package/dist/logger-n4LsLISE.d.ts.map +1 -0
- package/dist/{login-0jP1pnSJ.js → login-BHhOdTp9.js} +4 -301
- package/dist/login-BHhOdTp9.js.map +1 -0
- package/dist/{mcp-tevNihk_.js → mcp-Cy9mgCcr.js} +22 -9
- package/dist/mcp-Cy9mgCcr.js.map +1 -0
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +1 -1
- package/dist/{messages-C_1AmSpk.js → messages-RPKrEPvH.js} +6 -2
- package/dist/messages-RPKrEPvH.js.map +1 -0
- package/dist/output/stream-json.d.ts +2 -2
- package/dist/output/stream-json.js +1 -1
- package/dist/output/terminal.d.ts +2 -2
- package/dist/output/terminal.js +1 -0
- package/dist/output/terminal.js.map +1 -1
- package/dist/{presets-Cm2BPJaU.js → presets-D5ibZTml.js} +2 -2
- package/dist/{presets-Cm2BPJaU.js.map → presets-D5ibZTml.js.map} +1 -1
- package/dist/presets.d.ts +2 -2
- package/dist/presets.js +1 -1
- package/dist/{providers-BGBB18zz.js → providers-C2cxujp_.js} +85 -20
- package/dist/providers-C2cxujp_.js.map +1 -0
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +2 -2
- package/dist/restate.d.ts +2 -2
- package/dist/restate.js +4 -1
- package/dist/restate.js.map +1 -1
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/session/sqlite.d.ts.map +1 -1
- package/dist/session/sqlite.js +36 -4
- package/dist/session/sqlite.js.map +1 -1
- package/dist/{session-CtAWwwkn.js → session-Do_TQV7c.js} +70 -22
- package/dist/session-Do_TQV7c.js.map +1 -0
- package/dist/session.d.ts +2 -2
- package/dist/session.js +3 -3
- package/dist/shell-quote-BmnhZmdM.js +33 -0
- package/dist/shell-quote-BmnhZmdM.js.map +1 -0
- package/dist/skills.d.ts +3 -3
- package/dist/skills.js +1 -1
- package/dist/skills.js.map +1 -1
- package/dist/{tool-formatters-D_fX6FGl.d.ts → tool-formatters-RT5-gyE2.d.ts} +2 -2
- package/dist/{tool-formatters-D_fX6FGl.d.ts.map → tool-formatters-RT5-gyE2.d.ts.map} +1 -1
- package/dist/tools/fetch-url.d.ts +1 -1
- package/dist/tools/web-search.d.ts +1 -1
- package/dist/{tools-NxnEmzYg.js → tools-ZHKOh44k.js} +342 -123
- package/dist/tools-ZHKOh44k.js.map +1 -0
- package/dist/tools.d.ts +2 -2
- package/dist/tools.js +1 -1
- package/dist/{transcript-anchors-DA6XawEU.d.ts → transcript-anchors-B4FxkG-8.d.ts} +10 -4
- package/dist/transcript-anchors-B4FxkG-8.d.ts.map +1 -0
- package/dist/{transcript-anchors-B_c7gWot.js → transcript-anchors-CS46ul6X.js} +10 -10
- package/dist/transcript-anchors-CS46ul6X.js.map +1 -0
- package/dist/tui.d.ts +3 -3
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +167 -41
- package/dist/tui.js.map +1 -1
- package/dist/{turn-operations-CCl7rpbT.d.ts → turn-operations-CoRj3mYZ.d.ts} +3 -3
- package/dist/{turn-operations-CCl7rpbT.d.ts.map → turn-operations-CoRj3mYZ.d.ts.map} +1 -1
- package/dist/{types-BibzMDjX.d.ts → types-B39tBba1.d.ts} +69 -2
- package/dist/types-B39tBba1.d.ts.map +1 -0
- package/dist/types-BiobHM1D.js.map +1 -1
- package/dist/types.d.ts +5 -5
- package/docs/ARCHITECTURE.md +1 -1
- package/docs/CHAT.md +3 -3
- package/docs/EXECUTION_CONTEXT.md +257 -0
- package/docs/RUN_IN_BACKGROUND.md +8 -0
- package/docs/SKILL.md +3 -3
- package/package.json +57 -24
- package/dist/agent-BHkvYIH9.d.ts.map +0 -1
- package/dist/contexts-BJVgG0LY.js.map +0 -1
- package/dist/index-BIo67xLV.d.ts.map +0 -1
- package/dist/index-C4aT2kO_.d.ts.map +0 -1
- package/dist/login-0jP1pnSJ.js.map +0 -1
- package/dist/mcp-tevNihk_.js.map +0 -1
- package/dist/messages-C_1AmSpk.js.map +0 -1
- package/dist/providers-BGBB18zz.js.map +0 -1
- package/dist/session-CtAWwwkn.js.map +0 -1
- package/dist/tools-NxnEmzYg.js.map +0 -1
- package/dist/transcript-anchors-B_c7gWot.js.map +0 -1
- package/dist/transcript-anchors-DA6XawEU.d.ts.map +0 -1
- package/dist/types-BibzMDjX.d.ts.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"terminal.js","names":[],"sources":["../../src/output/terminal.ts"],"sourcesContent":["import type { Agent, AgentHooks } from '../agent'\nimport type { Preset } from '../presets'\nimport chalk from 'chalk'\nimport { previewLine } from '../chat/format'\nimport { statsByModel } from '../stats'\n\n// ---------------------------------------------------------------------------\n// Depth-aware streaming output\n//\n// The renderer interleaves three streams onto stdout:\n//\n// - parent agent (depth 0) — full color\n// - direct subagents (depth 1) — dim, indented one level\n// - grandchildren (depth ≥ 2) — dim italic, indented per depth\n//\n// Child events arrive on the parent's hook bus as `child:*` carrying `childId`\n// and `depth`. We bucket per-emitter cursor state so a child's text doesn't\n// glue onto the parent's line and vice-versa: when the active emitter changes\n// mid-stream, we emit a newline + indent prefix so the next chunk lands on a\n// fresh line.\n// ---------------------------------------------------------------------------\n\n/** Cursor state per emitter (parent or specific child). */\ninterface EmitterCursor {\n /** Indent depth — 0 = parent, ≥ 1 = subagent. */\n depth: number\n /** Have we written any text in the *current* turn yet? */\n isFirstDelta: boolean\n /** Have we just printed one or more tool-call lines (need a newline before text)? */\n hadToolCalls: boolean\n /** Are we currently inside a thinking block? */\n isThinking: boolean\n}\n\nconst PARENT_KEY = '__parent__'\n\nfunction indent(depth: number): string {\n return ' '.repeat(depth)\n}\n\n/** Style child output dim so the visual hierarchy is obvious at a glance. */\nfunction dye(depth: number, s: string): string {\n if (depth === 0)\n return s\n return chalk.dim(s)\n}\n\nexport interface TerminalOutputOptions {\n printHeader?: boolean\n title?: string\n shouldPrint?: () => boolean\n shouldPrintToolCall?: (ctx: Parameters<AgentHooks['tool:before']>[0]) => boolean\n shouldPrintSummary?: (stats: Parameters<AgentHooks['agent:done']>[0]) => boolean\n}\n\nexport function printTerminalHeader(agent: Agent, model: string, prompt: string, preset: Preset, title = '⚽ Zizou') {\n console.log(`\\n${title}`)\n console.log(`${chalk.bold('🤖 Model:')} ${chalk.green(model)} (${agent.meta.isOAuth ? chalk.green('oauth') : chalk.red('key')})`)\n console.log(`${chalk.bold('📝 Prompt:')} ${chalk.yellow(prompt)}`)\n if (preset.name)\n console.log(`${chalk.bold('🔧 Preset:')} ${chalk.cyan(preset.name)}`)\n if (preset.tools) {\n const names = Object.values(preset.tools).map(t => t.spec.name).join(', ')\n if (names)\n console.log(`${chalk.bold('🔧 Tools:')} ${chalk.cyan(names)}`)\n }\n console.log()\n}\n\n/**\n * Wire the depth-aware terminal renderer onto an agent's hook bus.\n *\n * Returns a disposer that unregisters every hook this function installed —\n * hosts reusing one agent across phases can detach the renderer without\n * tearing the agent down. Callers that ignore the return value keep the old\n * fire-and-forget behavior.\n */\nexport async function setupTerminalOutput(agent: Agent, model: string, prompt: string, preset: Preset, options: TerminalOutputOptions = {}): Promise<() => void> {\n if (options.printHeader !== false)\n printTerminalHeader(agent, model, prompt, preset, options.title)\n\n const unregisters: Array<() => void> = []\n const hook: typeof agent.hooks.hook = (name, fn) => {\n const unregister = agent.hooks.hook(name, fn)\n unregisters.push(unregister)\n return unregister\n }\n\n // Per-emitter cursor map. Parent always exists; child entries appear lazily\n // on first event and disappear on `spawn:complete`/`spawn:error`.\n const cursors = new Map<string, EmitterCursor>()\n cursors.set(PARENT_KEY, { depth: 0, isFirstDelta: true, hadToolCalls: false, isThinking: false })\n\n /** Last emitter that wrote to stdout. Drives newline-on-switch behavior. */\n let activeEmitter: string = PARENT_KEY\n let needsSummaryNewline = false\n\n function noteStreamWrite(text: string): void {\n needsSummaryNewline = !text.endsWith('\\n')\n }\n\n function ensureSummaryLineStart(): void {\n process.stdout.write('\\n\\n')\n needsSummaryNewline = false\n activeEmitter = PARENT_KEY\n }\n\n function canPrint(): boolean {\n return options.shouldPrint?.() ?? true\n }\n\n function getCursor(key: string, depth: number): EmitterCursor {\n let c = cursors.get(key)\n if (!c) {\n c = { depth, isFirstDelta: true, hadToolCalls: false, isThinking: false }\n cursors.set(key, c)\n }\n return c\n }\n\n /**\n * Switch the active emitter; when it changes mid-stream, drop a newline +\n * indent prefix so the next write lands cleanly on its own line.\n */\n function switchTo(key: string, depth: number): EmitterCursor {\n const cursor = getCursor(key, depth)\n if (activeEmitter !== key) {\n // Close out previous emitter's line and indent for the new one.\n process.stdout.write(`\\n${indent(depth)}`)\n activeEmitter = key\n cursor.isFirstDelta = false\n }\n return cursor\n }\n\n // ---------------------------------------------------------------------------\n // Parent loop\n // ---------------------------------------------------------------------------\n\n hook('turn:before', () => {\n const c = cursors.get(PARENT_KEY)!\n c.isFirstDelta = true\n c.isThinking = false\n })\n\n hook('stream:thinking', ({ delta }) => {\n if (!canPrint())\n return\n const c = switchTo(PARENT_KEY, 0)\n if (!c.isThinking) {\n if (c.hadToolCalls)\n process.stdout.write('\\n')\n process.stdout.write(chalk.dim.italic('🧠 '))\n noteStreamWrite('🧠 ')\n c.isThinking = true\n c.hadToolCalls = false\n }\n process.stdout.write(chalk.dim.italic(delta))\n noteStreamWrite(delta)\n })\n\n hook('stream:text', ({ delta }) => {\n if (!canPrint())\n return\n const c = switchTo(PARENT_KEY, 0)\n if (c.isFirstDelta) {\n if (c.isThinking) {\n process.stdout.write('\\n')\n c.isThinking = false\n }\n if (c.hadToolCalls)\n process.stdout.write('\\n')\n c.isFirstDelta = false\n c.hadToolCalls = false\n }\n process.stdout.write(delta)\n noteStreamWrite(delta)\n })\n\n hook('stream:end', () => {\n needsSummaryNewline = false\n })\n\n hook('tool:before', (ctx) => {\n if (!canPrint())\n return\n if (options.shouldPrintToolCall && !options.shouldPrintToolCall(ctx))\n return\n\n const c = switchTo(PARENT_KEY, 0)\n if (c.isThinking) {\n process.stdout.write('\\n')\n c.isThinking = false\n }\n if (!c.hadToolCalls)\n process.stdout.write('\\n')\n c.hadToolCalls = true\n const stringified = JSON.stringify(ctx.input)\n const args = stringified && stringified.trim() !== '{}' ? ` (${chalk.yellow(stringified)})` : ''\n console.log(` ↳ ${chalk.cyan(ctx.name)}${args}`)\n activeEmitter = PARENT_KEY\n })\n\n hook('system:before', (ctx) => {\n if (!canPrint())\n return\n console.log(chalk.cyan(`System: ${chalk.yellow(ctx.system)}`))\n })\n\n // ---------------------------------------------------------------------------\n // Spawn lifecycle — print boundary lines so the user can see when a\n // subagent starts and finishes, with cumulative usage at completion.\n // ---------------------------------------------------------------------------\n\n hook('spawn:before', ({ id, task, depth }) => {\n if (!canPrint())\n return\n const d = depth ?? 1\n // Always start a fresh line for spawn announcements.\n if (activeEmitter !== PARENT_KEY)\n process.stdout.write('\\n')\n const taskPreview = previewLine(task, 80)\n console.log(`${indent(d)}${chalk.dim('🌱')} ${chalk.bold(dye(d, `[${id}]`))} ${chalk.dim('depth=')}${chalk.dim(String(d))} ${dye(d, taskPreview)}`)\n activeEmitter = PARENT_KEY\n })\n\n hook('spawn:complete', (ctx) => {\n if (!canPrint())\n return\n const d = ctx.depth ?? 1\n const stats = ctx.stats\n if (activeEmitter !== PARENT_KEY)\n process.stdout.write('\\n')\n const status = ctx.status === 'completed'\n ? chalk.green('✓')\n : ctx.status === 'aborted'\n ? chalk.yellow('⚠')\n : chalk.red('✗')\n let summary = `${indent(d)}${status} ${chalk.bold(dye(d, `[${ctx.id}]`))} ${chalk.dim(`${ctx.status ?? 'completed'} ·`)} ${chalk.yellow(stats.totalIn)} in / ${chalk.green(stats.totalOut)} out`\n if (typeof stats.cost === 'number' && stats.cost > 0)\n summary += chalk.dim(` · $${stats.cost.toFixed(6)}`)\n if (stats.children && stats.children.length > 0)\n summary += chalk.dim(` · ${stats.children.length} sub-spawn${stats.children.length === 1 ? '' : 's'}`)\n console.log(summary)\n cursors.delete(ctx.id)\n activeEmitter = PARENT_KEY\n })\n\n hook('spawn:error', ({ id, depth, error }) => {\n if (!canPrint())\n return\n const d = depth ?? 1\n if (activeEmitter !== PARENT_KEY)\n process.stdout.write('\\n')\n console.log(`${indent(d)}${chalk.red('✗')} ${chalk.bold(dye(d, `[${id}]`))} ${chalk.red(`error: ${error.message}`)}`)\n cursors.delete(id)\n activeEmitter = PARENT_KEY\n })\n\n // ---------------------------------------------------------------------------\n // Child streaming — re-fired child events with `childId` + `depth`. Render\n // them with the matching depth indent so the user can see subagent output\n // happen live without losing track of the parent's stream.\n // ---------------------------------------------------------------------------\n\n hook('child:turn:after', ({ childId }) => {\n // New child turn boundary — reset its first-delta state so the next\n // text/thinking chunk starts a fresh line under the indent.\n const c = cursors.get(childId)\n if (c) {\n c.isFirstDelta = true\n c.isThinking = false\n }\n })\n\n hook('child:stream:thinking', ({ delta, childId, depth }) => {\n if (!canPrint())\n return\n const c = switchTo(childId, depth)\n if (!c.isThinking) {\n if (c.hadToolCalls)\n process.stdout.write(`\\n${indent(depth)}`)\n process.stdout.write(chalk.dim.italic('🧠 '))\n noteStreamWrite('🧠 ')\n c.isThinking = true\n c.hadToolCalls = false\n }\n process.stdout.write(chalk.dim.italic(delta))\n noteStreamWrite(delta)\n })\n\n hook('child:stream:text', ({ delta, childId, depth }) => {\n if (!canPrint())\n return\n const c = switchTo(childId, depth)\n if (c.isFirstDelta) {\n if (c.isThinking) {\n process.stdout.write(`\\n${indent(depth)}`)\n c.isThinking = false\n }\n if (c.hadToolCalls)\n process.stdout.write(`\\n${indent(depth)}`)\n c.isFirstDelta = false\n c.hadToolCalls = false\n }\n // Wrap each delta in dim so multi-line child output stays visually nested.\n // We don't re-indent on \\n inside a delta — providers chunk text in small\n // pieces, so cross-line indentation would feel jittery; the depth prefix\n // on emitter switch is enough.\n process.stdout.write(dye(depth, delta))\n noteStreamWrite(delta)\n })\n\n hook('child:stream:end', ({ childId }) => {\n if (activeEmitter === childId)\n activeEmitter = PARENT_KEY\n needsSummaryNewline = false\n })\n\n hook('child:tool:before', ({ name, input, childId, depth }) => {\n if (!canPrint())\n return\n const c = switchTo(childId, depth)\n if (c.isThinking) {\n process.stdout.write('\\n')\n c.isThinking = false\n }\n if (!c.hadToolCalls)\n process.stdout.write('\\n')\n c.hadToolCalls = true\n const stringified = JSON.stringify(input)\n const args = stringified && stringified.trim() !== '{}' ? ` (${chalk.yellow(stringified)})` : ''\n console.log(`${indent(depth)} ↳ ${chalk.cyan(name)}${args}`)\n activeEmitter = childId\n })\n\n hook('child:tool:error', ({ name, error, depth }) => {\n if (!canPrint())\n return\n if (activeEmitter !== PARENT_KEY)\n process.stdout.write('\\n')\n console.log(`${indent(depth)} ${chalk.red('✗')} ${chalk.cyan(name)}: ${chalk.red(error.message)}`)\n activeEmitter = PARENT_KEY\n })\n\n // ---------------------------------------------------------------------------\n // Final summary\n // ---------------------------------------------------------------------------\n\n hook('agent:done', (stats) => {\n if (!canPrint())\n return\n if (options.shouldPrintSummary && !options.shouldPrintSummary(stats))\n return\n const { totalIn, totalOut, totalCacheRead, totalCacheCreation, turns, elapsed, cost, children } = stats\n\n // Make sure we're not gluing onto an unfinished stream line.\n ensureSummaryLineStart()\n\n const seconds = Math.floor(elapsed / 1000)\n const minutes = Math.floor(seconds / 60)\n const remainingSeconds = seconds % 60\n const timeStr = minutes > 0 ? `${minutes}m ${remainingSeconds}s` : `${remainingSeconds}s`\n\n let line = `🧮 Tokens: ${chalk.yellow(totalIn)} in / ${chalk.green(totalOut)} out`\n line += ` (${chalk.magenta(turns)} parent turn${turns !== 1 ? 's' : ''})`\n line += ` in ${chalk.green(timeStr)}`\n\n if (totalCacheCreation || totalCacheRead)\n line += `\\n Cache: ${chalk.blue(totalCacheCreation)} created / ${chalk.blue(totalCacheRead)} read`\n\n if (cost)\n line += `\\n💸 Cost: ${chalk.yellow(`$${cost.toFixed(6)}`)}`\n\n // Per-child breakdown — one line per direct child with its cumulative\n // tokens. Useful for spotting \"which subagent burned all the tokens\".\n if (children && children.length > 0) {\n line += `\\n Children: ${chalk.magenta(children.length)}`\n for (const child of children) {\n line += `\\n · [${chalk.bold(child.id)}] ${chalk.yellow(child.stats.totalIn)} in / ${chalk.green(child.stats.totalOut)} out`\n line += chalk.dim(` (${child.stats.turns} turn${child.stats.turns === 1 ? '' : 's'}, ${child.status ?? 'completed'})`)\n }\n }\n\n // Per-model breakdown — only worth showing when the run touched more\n // than one model id (cross-model spawn, vision-fallback, etc.). Skipping\n // the single-model case keeps the happy-path summary compact.\n const byModel = statsByModel(stats)\n if (byModel.size > 1) {\n line += `\\n By model:`\n for (const [modelId, usage] of byModel) {\n line += `\\n · ${chalk.cyan(modelId)} ${chalk.yellow(usage.input)} in / ${chalk.green(usage.output)} out (${usage.turns} turn${usage.turns === 1 ? '' : 's'})`\n if (usage.cost > 0)\n line += chalk.dim(` · $${usage.cost.toFixed(6)}`)\n }\n }\n\n console.log(chalk.cyan(line))\n\n // Session summary — sums what's actually in the session's run ledger.\n // Each `SessionRun.tokensIn` records parent-loop tokens for that run only\n // (children persisted via `createSpawnTool({ persist: true })` get their\n // own SessionRun entries — summing then matches `stats.totalIn`). When\n // children ran in-memory (the default), the recorded total is parent-\n // only and is intentionally lower than the cumulative figure above.\n if (agent.session) {\n const session = agent.session\n const totalRuns = session.runs.length\n const recordedIn = session.runs.reduce((sum, r) => sum + (r.tokensIn ?? 0), 0)\n const recordedOut = session.runs.reduce((sum, r) => sum + (r.tokensOut ?? 0), 0)\n const recordedCost = session.runs.reduce((sum, r) => sum + (r.cost ?? 0), 0)\n\n let sessionLine = `📋 Session ${chalk.dim(session.id)}: ${chalk.bold(String(totalRuns))} run${totalRuns === 1 ? '' : 's'} recorded`\n sessionLine += `, ${chalk.yellow(recordedIn)} in / ${chalk.green(recordedOut)} out`\n if (recordedCost)\n sessionLine += `, ${chalk.yellow(`$${recordedCost.toFixed(6)}`)}`\n console.log(chalk.dim(sessionLine))\n\n // When the run consumed more than what's recorded (children ran in\n // memory), surface the gap so the difference between the two lines\n // doesn't look like a bug. Compares cumulative `totalIn` against the\n // session ledger; non-zero only with non-persistent spawns.\n const offLedgerIn = totalIn - recordedIn\n const offLedgerOut = totalOut - recordedOut\n const childCount = countDescendants(children)\n if ((offLedgerIn > 0 || offLedgerOut > 0) && childCount > 0) {\n const note = ` ↳ ${chalk.magenta(childCount)} subagent${childCount === 1 ? '' : 's'} ran in-memory (+${chalk.yellow(offLedgerIn)} in / +${chalk.green(offLedgerOut)} out, not persisted)`\n console.log(chalk.dim(note))\n }\n }\n })\n\n return () => {\n for (const unregister of unregisters)\n unregister()\n }\n}\n\n/** Recursively count every descendant in the children tree. */\nfunction countDescendants(children: import('../types').ChildRunStats[] | undefined): number {\n if (!children)\n return 0\n let n = 0\n for (const child of children)\n n += 1 + countDescendants(child.stats.children)\n return n\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"terminal.js","names":[],"sources":["../../src/output/terminal.ts"],"sourcesContent":["import type { Agent, AgentHooks } from '../agent'\nimport type { Preset } from '../presets'\nimport chalk from 'chalk'\nimport { previewLine } from '../chat/format'\nimport { statsByModel } from '../stats'\n\n// ---------------------------------------------------------------------------\n// Depth-aware streaming output\n//\n// The renderer interleaves three streams onto stdout:\n//\n// - parent agent (depth 0) — full color\n// - direct subagents (depth 1) — dim, indented one level\n// - grandchildren (depth ≥ 2) — dim italic, indented per depth\n//\n// Child events arrive on the parent's hook bus as `child:*` carrying `childId`\n// and `depth`. We bucket per-emitter cursor state so a child's text doesn't\n// glue onto the parent's line and vice-versa: when the active emitter changes\n// mid-stream, we emit a newline + indent prefix so the next chunk lands on a\n// fresh line.\n// ---------------------------------------------------------------------------\n\n/** Cursor state per emitter (parent or specific child). */\ninterface EmitterCursor {\n /** Indent depth — 0 = parent, ≥ 1 = subagent. */\n depth: number\n /** Have we written any text in the *current* turn yet? */\n isFirstDelta: boolean\n /** Have we just printed one or more tool-call lines (need a newline before text)? */\n hadToolCalls: boolean\n /** Are we currently inside a thinking block? */\n isThinking: boolean\n}\n\nconst PARENT_KEY = '__parent__'\n\nfunction indent(depth: number): string {\n return ' '.repeat(depth)\n}\n\n/** Style child output dim so the visual hierarchy is obvious at a glance. */\nfunction dye(depth: number, s: string): string {\n if (depth === 0)\n return s\n return chalk.dim(s)\n}\n\nexport interface TerminalOutputOptions {\n printHeader?: boolean\n title?: string\n shouldPrint?: () => boolean\n shouldPrintToolCall?: (ctx: Parameters<AgentHooks['tool:before']>[0]) => boolean\n shouldPrintSummary?: (stats: Parameters<AgentHooks['agent:done']>[0]) => boolean\n}\n\nexport function printTerminalHeader(agent: Agent, model: string, prompt: string, preset: Preset, title = '⚽ Zizou') {\n console.log(`\\n${title}`)\n console.log(`${chalk.bold('🤖 Model:')} ${chalk.green(model)} (${agent.meta.isOAuth ? chalk.green('oauth') : chalk.red('key')})`)\n console.log(`${chalk.bold('📝 Prompt:')} ${chalk.yellow(prompt)}`)\n if (preset.name)\n console.log(`${chalk.bold('🔧 Preset:')} ${chalk.cyan(preset.name)}`)\n if (preset.tools) {\n const names = Object.values(preset.tools).map(t => t.spec.name).join(', ')\n if (names)\n console.log(`${chalk.bold('🔧 Tools:')} ${chalk.cyan(names)}`)\n }\n console.log()\n}\n\n/**\n * Wire the depth-aware terminal renderer onto an agent's hook bus.\n *\n * Returns a disposer that unregisters every hook this function installed —\n * hosts reusing one agent across phases can detach the renderer without\n * tearing the agent down. Callers that ignore the return value keep the old\n * fire-and-forget behavior.\n */\nexport async function setupTerminalOutput(agent: Agent, model: string, prompt: string, preset: Preset, options: TerminalOutputOptions = {}): Promise<() => void> {\n if (options.printHeader !== false)\n printTerminalHeader(agent, model, prompt, preset, options.title)\n\n const unregisters: Array<() => void> = []\n const hook: typeof agent.hooks.hook = (name, fn) => {\n const unregister = agent.hooks.hook(name, fn)\n unregisters.push(unregister)\n return unregister\n }\n\n // Per-emitter cursor map. Parent always exists; child entries appear lazily\n // on first event and disappear on `spawn:complete`/`spawn:error`.\n const cursors = new Map<string, EmitterCursor>()\n cursors.set(PARENT_KEY, { depth: 0, isFirstDelta: true, hadToolCalls: false, isThinking: false })\n\n /** Last emitter that wrote to stdout. Drives newline-on-switch behavior. */\n let activeEmitter: string = PARENT_KEY\n let needsSummaryNewline = false\n\n function noteStreamWrite(text: string): void {\n needsSummaryNewline = !text.endsWith('\\n')\n }\n\n function ensureSummaryLineStart(): void {\n process.stdout.write('\\n\\n')\n needsSummaryNewline = false\n activeEmitter = PARENT_KEY\n }\n\n function canPrint(): boolean {\n return options.shouldPrint?.() ?? true\n }\n\n function getCursor(key: string, depth: number): EmitterCursor {\n let c = cursors.get(key)\n if (!c) {\n c = { depth, isFirstDelta: true, hadToolCalls: false, isThinking: false }\n cursors.set(key, c)\n }\n return c\n }\n\n /**\n * Switch the active emitter; when it changes mid-stream, drop a newline +\n * indent prefix so the next write lands cleanly on its own line.\n */\n function switchTo(key: string, depth: number): EmitterCursor {\n const cursor = getCursor(key, depth)\n if (activeEmitter !== key) {\n // Close out previous emitter's line and indent for the new one.\n process.stdout.write(`\\n${indent(depth)}`)\n activeEmitter = key\n cursor.isFirstDelta = false\n }\n return cursor\n }\n\n // ---------------------------------------------------------------------------\n // Parent loop\n // ---------------------------------------------------------------------------\n\n hook('turn:before', () => {\n const c = cursors.get(PARENT_KEY)!\n c.isFirstDelta = true\n c.isThinking = false\n })\n\n hook('stream:thinking', ({ delta }) => {\n if (!canPrint())\n return\n const c = switchTo(PARENT_KEY, 0)\n if (!c.isThinking) {\n if (c.hadToolCalls)\n process.stdout.write('\\n')\n process.stdout.write(chalk.dim.italic('🧠 '))\n noteStreamWrite('🧠 ')\n c.isThinking = true\n c.hadToolCalls = false\n }\n process.stdout.write(chalk.dim.italic(delta))\n noteStreamWrite(delta)\n })\n\n hook('stream:text', ({ delta }) => {\n if (!canPrint())\n return\n const c = switchTo(PARENT_KEY, 0)\n if (c.isFirstDelta) {\n if (c.isThinking) {\n process.stdout.write('\\n')\n c.isThinking = false\n }\n if (c.hadToolCalls)\n process.stdout.write('\\n')\n c.isFirstDelta = false\n c.hadToolCalls = false\n }\n process.stdout.write(delta)\n noteStreamWrite(delta)\n })\n\n hook('stream:end', () => {\n needsSummaryNewline = false\n })\n\n hook('tool:before', (ctx) => {\n if (!canPrint())\n return\n if (options.shouldPrintToolCall && !options.shouldPrintToolCall(ctx))\n return\n\n const c = switchTo(PARENT_KEY, 0)\n if (c.isThinking) {\n process.stdout.write('\\n')\n c.isThinking = false\n }\n if (!c.hadToolCalls)\n process.stdout.write('\\n')\n c.hadToolCalls = true\n const stringified = JSON.stringify(ctx.input)\n const args = stringified && stringified.trim() !== '{}' ? ` (${chalk.yellow(stringified)})` : ''\n console.log(` ↳ ${chalk.cyan(ctx.name)}${args}`)\n activeEmitter = PARENT_KEY\n })\n\n hook('system:before', (ctx) => {\n if (!canPrint())\n return\n console.log(chalk.cyan(`System: ${chalk.yellow(ctx.system)}`))\n })\n\n // ---------------------------------------------------------------------------\n // Spawn lifecycle — print boundary lines so the user can see when a\n // subagent starts and finishes, with cumulative usage at completion.\n // ---------------------------------------------------------------------------\n\n hook('spawn:before', ({ id, task, depth }) => {\n if (!canPrint())\n return\n const d = depth ?? 1\n // Always start a fresh line for spawn announcements.\n if (activeEmitter !== PARENT_KEY)\n process.stdout.write('\\n')\n const taskPreview = previewLine(task, 80)\n console.log(`${indent(d)}${chalk.dim('🌱')} ${chalk.bold(dye(d, `[${id}]`))} ${chalk.dim('depth=')}${chalk.dim(String(d))} ${dye(d, taskPreview)}`)\n activeEmitter = PARENT_KEY\n })\n\n hook('spawn:complete', (ctx) => {\n if (!canPrint())\n return\n const d = ctx.depth ?? 1\n const stats = ctx.stats\n if (activeEmitter !== PARENT_KEY)\n process.stdout.write('\\n')\n const status = ctx.status === 'completed'\n ? chalk.green('✓')\n : ctx.status === 'aborted'\n ? chalk.yellow('⚠')\n : chalk.red('✗')\n let summary = `${indent(d)}${status} ${chalk.bold(dye(d, `[${ctx.id}]`))} ${chalk.dim(`${ctx.status ?? 'completed'} ·`)} ${chalk.yellow(stats.totalIn)} in / ${chalk.green(stats.totalOut)} out`\n if (typeof stats.cost === 'number' && stats.cost > 0)\n summary += chalk.dim(` · $${stats.cost.toFixed(6)}`)\n if (stats.children && stats.children.length > 0)\n summary += chalk.dim(` · ${stats.children.length} sub-spawn${stats.children.length === 1 ? '' : 's'}`)\n console.log(summary)\n cursors.delete(ctx.id)\n activeEmitter = PARENT_KEY\n })\n\n hook('spawn:error', ({ id, depth, error }) => {\n if (!canPrint())\n return\n const d = depth ?? 1\n if (activeEmitter !== PARENT_KEY)\n process.stdout.write('\\n')\n console.log(`${indent(d)}${chalk.red('✗')} ${chalk.bold(dye(d, `[${id}]`))} ${chalk.red(`error: ${error.message}`)}`)\n cursors.delete(id)\n activeEmitter = PARENT_KEY\n })\n\n // ---------------------------------------------------------------------------\n // Child streaming — re-fired child events with `childId` + `depth`. Render\n // them with the matching depth indent so the user can see subagent output\n // happen live without losing track of the parent's stream.\n // ---------------------------------------------------------------------------\n\n hook('child:turn:after', ({ childId }) => {\n // New child turn boundary — reset its first-delta state so the next\n // text/thinking chunk starts a fresh line under the indent.\n const c = cursors.get(childId)\n if (c) {\n c.isFirstDelta = true\n c.isThinking = false\n }\n })\n\n hook('child:stream:thinking', ({ delta, childId, depth }) => {\n if (!canPrint())\n return\n const c = switchTo(childId, depth)\n if (!c.isThinking) {\n if (c.hadToolCalls)\n process.stdout.write(`\\n${indent(depth)}`)\n process.stdout.write(chalk.dim.italic('🧠 '))\n noteStreamWrite('🧠 ')\n c.isThinking = true\n c.hadToolCalls = false\n }\n process.stdout.write(chalk.dim.italic(delta))\n noteStreamWrite(delta)\n })\n\n hook('child:stream:text', ({ delta, childId, depth }) => {\n if (!canPrint())\n return\n const c = switchTo(childId, depth)\n if (c.isFirstDelta) {\n if (c.isThinking) {\n process.stdout.write(`\\n${indent(depth)}`)\n c.isThinking = false\n }\n if (c.hadToolCalls)\n process.stdout.write(`\\n${indent(depth)}`)\n c.isFirstDelta = false\n c.hadToolCalls = false\n }\n // Wrap each delta in dim so multi-line child output stays visually nested.\n // We don't re-indent on \\n inside a delta — providers chunk text in small\n // pieces, so cross-line indentation would feel jittery; the depth prefix\n // on emitter switch is enough.\n process.stdout.write(dye(depth, delta))\n noteStreamWrite(delta)\n })\n\n hook('child:stream:end', ({ childId }) => {\n if (activeEmitter === childId)\n activeEmitter = PARENT_KEY\n needsSummaryNewline = false\n })\n\n hook('child:tool:before', ({ name, input, childId, depth }) => {\n if (!canPrint())\n return\n const c = switchTo(childId, depth)\n if (c.isThinking) {\n process.stdout.write('\\n')\n c.isThinking = false\n }\n if (!c.hadToolCalls)\n process.stdout.write('\\n')\n c.hadToolCalls = true\n const stringified = JSON.stringify(input)\n const args = stringified && stringified.trim() !== '{}' ? ` (${chalk.yellow(stringified)})` : ''\n console.log(`${indent(depth)} ↳ ${chalk.cyan(name)}${args}`)\n activeEmitter = childId\n })\n\n hook('child:tool:error', ({ name, error, depth }) => {\n if (!canPrint())\n return\n if (activeEmitter !== PARENT_KEY)\n process.stdout.write('\\n')\n console.log(`${indent(depth)} ${chalk.red('✗')} ${chalk.cyan(name)}: ${chalk.red(error.message)}`)\n activeEmitter = PARENT_KEY\n })\n\n // ---------------------------------------------------------------------------\n // Final summary\n // ---------------------------------------------------------------------------\n\n hook('agent:done', (stats) => {\n if (!canPrint())\n return\n if (options.shouldPrintSummary && !options.shouldPrintSummary(stats))\n return\n const { totalIn, totalOut, totalCacheRead, totalCacheCreation, turns, elapsed, cost, children } = stats\n\n // Make sure we're not gluing onto an unfinished stream line.\n ensureSummaryLineStart()\n\n const seconds = Math.floor(elapsed / 1000)\n const minutes = Math.floor(seconds / 60)\n const remainingSeconds = seconds % 60\n const timeStr = minutes > 0 ? `${minutes}m ${remainingSeconds}s` : `${remainingSeconds}s`\n\n let line = `🧮 Tokens: ${chalk.yellow(totalIn)} in / ${chalk.green(totalOut)} out`\n line += ` (${chalk.magenta(turns)} parent turn${turns !== 1 ? 's' : ''})`\n line += ` in ${chalk.green(timeStr)}`\n\n if (totalCacheCreation || totalCacheRead)\n line += `\\n Cache: ${chalk.blue(totalCacheCreation)} created / ${chalk.blue(totalCacheRead)} read`\n\n if (cost)\n line += `\\n💸 Cost: ${chalk.yellow(`$${cost.toFixed(6)}`)}`\n\n if (agent.execution.type === 'sandbox' && agent.handle?.id)\n line += `\\n📦 Sandbox: ${chalk.cyan(agent.handle.id)}`\n\n // Per-child breakdown — one line per direct child with its cumulative\n // tokens. Useful for spotting \"which subagent burned all the tokens\".\n if (children && children.length > 0) {\n line += `\\n Children: ${chalk.magenta(children.length)}`\n for (const child of children) {\n line += `\\n · [${chalk.bold(child.id)}] ${chalk.yellow(child.stats.totalIn)} in / ${chalk.green(child.stats.totalOut)} out`\n line += chalk.dim(` (${child.stats.turns} turn${child.stats.turns === 1 ? '' : 's'}, ${child.status ?? 'completed'})`)\n }\n }\n\n // Per-model breakdown — only worth showing when the run touched more\n // than one model id (cross-model spawn, vision-fallback, etc.). Skipping\n // the single-model case keeps the happy-path summary compact.\n const byModel = statsByModel(stats)\n if (byModel.size > 1) {\n line += `\\n By model:`\n for (const [modelId, usage] of byModel) {\n line += `\\n · ${chalk.cyan(modelId)} ${chalk.yellow(usage.input)} in / ${chalk.green(usage.output)} out (${usage.turns} turn${usage.turns === 1 ? '' : 's'})`\n if (usage.cost > 0)\n line += chalk.dim(` · $${usage.cost.toFixed(6)}`)\n }\n }\n\n console.log(chalk.cyan(line))\n\n // Session summary — sums what's actually in the session's run ledger.\n // Each `SessionRun.tokensIn` records parent-loop tokens for that run only\n // (children persisted via `createSpawnTool({ persist: true })` get their\n // own SessionRun entries — summing then matches `stats.totalIn`). When\n // children ran in-memory (the default), the recorded total is parent-\n // only and is intentionally lower than the cumulative figure above.\n if (agent.session) {\n const session = agent.session\n const totalRuns = session.runs.length\n const recordedIn = session.runs.reduce((sum, r) => sum + (r.tokensIn ?? 0), 0)\n const recordedOut = session.runs.reduce((sum, r) => sum + (r.tokensOut ?? 0), 0)\n const recordedCost = session.runs.reduce((sum, r) => sum + (r.cost ?? 0), 0)\n\n let sessionLine = `📋 Session ${chalk.dim(session.id)}: ${chalk.bold(String(totalRuns))} run${totalRuns === 1 ? '' : 's'} recorded`\n sessionLine += `, ${chalk.yellow(recordedIn)} in / ${chalk.green(recordedOut)} out`\n if (recordedCost)\n sessionLine += `, ${chalk.yellow(`$${recordedCost.toFixed(6)}`)}`\n console.log(chalk.dim(sessionLine))\n\n // When the run consumed more than what's recorded (children ran in\n // memory), surface the gap so the difference between the two lines\n // doesn't look like a bug. Compares cumulative `totalIn` against the\n // session ledger; non-zero only with non-persistent spawns.\n const offLedgerIn = totalIn - recordedIn\n const offLedgerOut = totalOut - recordedOut\n const childCount = countDescendants(children)\n if ((offLedgerIn > 0 || offLedgerOut > 0) && childCount > 0) {\n const note = ` ↳ ${chalk.magenta(childCount)} subagent${childCount === 1 ? '' : 's'} ran in-memory (+${chalk.yellow(offLedgerIn)} in / +${chalk.green(offLedgerOut)} out, not persisted)`\n console.log(chalk.dim(note))\n }\n }\n })\n\n return () => {\n for (const unregister of unregisters)\n unregister()\n }\n}\n\n/** Recursively count every descendant in the children tree. */\nfunction countDescendants(children: import('../types').ChildRunStats[] | undefined): number {\n if (!children)\n return 0\n let n = 0\n for (const child of children)\n n += 1 + countDescendants(child.stats.children)\n return n\n}\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as multiEdit,
|
|
1
|
+
import { a as multiEdit, i as readFile, n as createSpawnTool, o as listFiles, p as waitTask, r as shellKill, t as writeFile, u as edit, y as shell } from "./tools-ZHKOh44k.js";
|
|
2
2
|
//#region src/presets/basic.ts
|
|
3
3
|
/**
|
|
4
4
|
* Core tools available in every basic preset (without spawn).
|
|
@@ -110,4 +110,4 @@ function composePresets(...presets) {
|
|
|
110
110
|
//#endregion
|
|
111
111
|
export { basic_default as i, definePreset as n, basicTools as r, composePresets as t };
|
|
112
112
|
|
|
113
|
-
//# sourceMappingURL=presets-
|
|
113
|
+
//# sourceMappingURL=presets-D5ibZTml.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presets-
|
|
1
|
+
{"version":3,"file":"presets-D5ibZTml.js","names":[],"sources":["../src/presets/basic.ts","../src/presets/index.ts"],"sourcesContent":["import { definePreset } from '.'\nimport { edit, listFiles, multiEdit, readFile, shell, shellKill, waitTask, writeFile } from '../tools'\nimport { createSpawnTool } from '../tools/spawn'\n\n/**\n * Core tools available in every basic preset (without spawn).\n *\n * `edit` and `multi_edit` ship in the basic set because surgical edits are the\n * default modality for production agents — `write_file` is for full overwrites.\n * `glob` and `grep` are exported but opt-in: not every agent needs codebase\n * search, and shipping them by default would force `tool:gate` work onto\n * consumers that prefer the model to use `shell` + classic Unix tools.\n */\nexport const basicTools = { shell, shellKill, waitTask, readFile, writeFile, listFiles, edit, multiEdit }\n\nexport default definePreset({\n name: 'basic',\n system: 'You are a helpful assistant with access to shell, file reading, file writing, surgical and multi-edit tools, directory listing, and sub-agent spawning. Prefer `edit` / `multi_edit` for in-place changes and `write_file` for full file overwrites. Use them to accomplish tasks in the project directory.',\n // `tools` is a getter so each access (every `{ ...basic }` spread into\n // `createAgent`) mints a FRESH spawn tool. `createSpawnTool()` carries\n // per-instance state (running children, concurrency counter, child-stats\n // accumulator); a module-level singleton instance would be shared by every\n // agent in the process, breaking concurrent rollouts.\n //\n // `persist: true` shares the parent's session with every child agent — child\n // turns land in `session.turns` tagged with their own `runId`, and the run\n // itself is recorded in `session.runs` with `parentRunId` + `depth`. That's\n // what lets a reloaded TUI session reconstruct the full subagent tree (see\n // `eventsFromTurns` in `tui/store.ts`). Hosts that want children in-memory\n // only can construct their own preset with `createSpawnTool()`.\n get tools() {\n return { ...basicTools, spawn: createSpawnTool({ persist: true }) }\n },\n})\n","import type { AgentHooks, AgentOptions } from '../agent'\n\nexport type { AgentHookMap } from '../agent'\n\n/**\n * A preset is a reusable slice of `AgentOptions` — spread it into `createAgent()`\n * to configure tools, a default system prompt, aliases, behavior defaults, and\n * agent-lifetime hooks.\n *\n * `provider`, `execution`, `session`, and internal fields are excluded so presets\n * remain shareable and composable.\n *\n * ```ts\n * import { basic } from 'zidane/presets'\n * createAgent({ ...basic, provider })\n * ```\n *\n * ### Composing multiple presets\n *\n * Bare `...spread` is shallow — `{ ...a, ...b }` overwrites every key `b`\n * defines, including `hooks`. Use {@link composePresets} when you want\n * field-aware merging (per-event hook concat, tools shallow-merge, etc.):\n *\n * ```ts\n * createAgent({ ...composePresets(basic, telemetry, mine), provider })\n * ```\n */\nexport type Preset = Omit<Partial<AgentOptions>, 'provider' | 'execution' | 'session' | 'mcpConnector'>\n\n/**\n * Identity helper for type inference when defining a preset.\n */\nexport function definePreset(config: Preset): Preset {\n return config\n}\n\n/**\n * Field-aware composition of presets. Right-most preset wins for scalar fields;\n * objects shallow-merge; arrays and hook handler lists concatenate. Designed so\n * stacking presets does the obvious thing without the spread-collision footgun:\n *\n * - `name`, `system`, `eager`, `skills` → last-defined wins\n * - `tools`, `toolAliases`, `behavior` → shallow-merge (later keys override)\n * - `behavior.dedupTools`, `behavior.toolBudgets` → **deep-merge** (per-tool-name; later wins on collision)\n * - `mcpServers` → concat with last-wins on `name` collision\n * - `hooks` → per-event concat; every handler fires\n *\n * `hooks` always emerges as `event → handler[]` so downstream registration\n * (in `createAgent`) sees a uniform shape. Order of handlers within an event\n * follows preset order: earlier presets register first.\n *\n * `mcpServers` is deduped by `name` because shipping two servers with the same\n * name would trip the connector at runtime — a later preset overriding an\n * earlier preset's `github` server is the practical intent.\n *\n * `behavior.dedupTools` and `behavior.toolBudgets` get the same per-key deep-merge\n * because they are tool-name-keyed records — a preset that ships a dedup hasher\n * for one tool should not erase a hasher another preset ships for a different\n * tool. Last-wins still applies on a per-tool collision so a downstream preset\n * can override an upstream preset's policy for one specific tool. Other\n * `behavior` fields keep last-wins semantics.\n */\nexport function composePresets(...presets: Preset[]): Preset {\n const out: Preset = {}\n const hooksByEvent: { [K in keyof AgentHooks]?: AgentHooks[K][] } = {}\n // Keep mcpServers in source-order on first sight, but allow later\n // declarations to override earlier ones with the same `name`. A `Map`\n // keyed by name gives O(1) override + stable iteration.\n const mcpByName = new Map<string, NonNullable<Preset['mcpServers']>[number]>()\n\n for (const p of presets) {\n if (p.name !== undefined)\n out.name = p.name\n if (p.system !== undefined)\n out.system = p.system\n if (p.eager !== undefined)\n out.eager = p.eager\n if (p.skills !== undefined)\n out.skills = p.skills\n if (p.tools)\n out.tools = { ...out.tools, ...p.tools }\n if (p.toolAliases)\n out.toolAliases = { ...out.toolAliases, ...p.toolAliases }\n if (p.behavior) {\n // Top-level shallow-merge first; then deep-merge the two tool-name-keyed\n // sub-records so per-tool entries from earlier presets aren't clobbered.\n const merged: NonNullable<Preset['behavior']> = { ...out.behavior, ...p.behavior }\n if (out.behavior?.dedupTools || p.behavior.dedupTools) {\n merged.dedupTools = { ...out.behavior?.dedupTools, ...p.behavior.dedupTools }\n }\n if (out.behavior?.toolBudgets || p.behavior.toolBudgets) {\n merged.toolBudgets = { ...out.behavior?.toolBudgets, ...p.behavior.toolBudgets }\n }\n out.behavior = merged\n }\n if (p.mcpServers) {\n for (const server of p.mcpServers)\n mcpByName.set(server.name, server)\n }\n if (p.hooks) {\n for (const [event, handler] of Object.entries(p.hooks)) {\n if (handler === undefined)\n continue\n const list = Array.isArray(handler) ? handler : [handler]\n const key = event as keyof AgentHooks\n // Safe cast: we read the loose `AgentHookMap` shape (handler-or-array)\n // and re-emit only as arrays. Each `list` element matches the event's\n // handler signature by construction (the input was typed `AgentHookMap`).\n const bucket = (hooksByEvent[key] ??= []) as unknown[]\n bucket.push(...(list as unknown[]))\n }\n }\n }\n\n if (mcpByName.size > 0)\n out.mcpServers = [...mcpByName.values()]\n\n if (Object.keys(hooksByEvent).length > 0)\n out.hooks = hooksByEvent\n\n return out\n}\n\nexport { default as basic, basicTools } from './basic'\n"],"mappings":";;;;;;;;;;;AAaA,MAAa,aAAa;CAAE;CAAO;CAAW;CAAU;CAAU;CAAW;CAAW;CAAM;AAAU;AAExG,IAAA,gBAAe,aAAa;CAC1B,MAAM;CACN,QAAQ;CAaR,IAAI,QAAQ;EACV,OAAO;GAAE,GAAG;GAAY,OAAO,gBAAgB,EAAE,SAAS,KAAK,CAAC;EAAE;CACpE;AACF,CAAC;;;;;;ACDD,SAAgB,aAAa,QAAwB;CACnD,OAAO;AACT;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,SAAgB,eAAe,GAAG,SAA2B;CAC3D,MAAM,MAAc,CAAC;CACrB,MAAM,eAA8D,CAAC;CAIrE,MAAM,4BAAY,IAAI,IAAuD;CAE7E,KAAK,MAAM,KAAK,SAAS;EACvB,IAAI,EAAE,SAAS,KAAA,GACb,IAAI,OAAO,EAAE;EACf,IAAI,EAAE,WAAW,KAAA,GACf,IAAI,SAAS,EAAE;EACjB,IAAI,EAAE,UAAU,KAAA,GACd,IAAI,QAAQ,EAAE;EAChB,IAAI,EAAE,WAAW,KAAA,GACf,IAAI,SAAS,EAAE;EACjB,IAAI,EAAE,OACJ,IAAI,QAAQ;GAAE,GAAG,IAAI;GAAO,GAAG,EAAE;EAAM;EACzC,IAAI,EAAE,aACJ,IAAI,cAAc;GAAE,GAAG,IAAI;GAAa,GAAG,EAAE;EAAY;EAC3D,IAAI,EAAE,UAAU;GAGd,MAAM,SAA0C;IAAE,GAAG,IAAI;IAAU,GAAG,EAAE;GAAS;GACjF,IAAI,IAAI,UAAU,cAAc,EAAE,SAAS,YACzC,OAAO,aAAa;IAAE,GAAG,IAAI,UAAU;IAAY,GAAG,EAAE,SAAS;GAAW;GAE9E,IAAI,IAAI,UAAU,eAAe,EAAE,SAAS,aAC1C,OAAO,cAAc;IAAE,GAAG,IAAI,UAAU;IAAa,GAAG,EAAE,SAAS;GAAY;GAEjF,IAAI,WAAW;EACjB;EACA,IAAI,EAAE,YACJ,KAAK,MAAM,UAAU,EAAE,YACrB,UAAU,IAAI,OAAO,MAAM,MAAM;EAErC,IAAI,EAAE,OACJ,KAAK,MAAM,CAAC,OAAO,YAAY,OAAO,QAAQ,EAAE,KAAK,GAAG;GACtD,IAAI,YAAY,KAAA,GACd;GACF,MAAM,OAAO,MAAM,QAAQ,OAAO,IAAI,UAAU,CAAC,OAAO;GACxD,MAAM,MAAM;GAKZ,CADgB,aAAa,SAAS,CAAC,GAChC,KAAK,GAAI,IAAkB;EACpC;CAEJ;CAEA,IAAI,UAAU,OAAO,GACnB,IAAI,aAAa,CAAC,GAAG,UAAU,OAAO,CAAC;CAEzC,IAAI,OAAO,KAAK,YAAY,EAAE,SAAS,GACrC,IAAI,QAAQ;CAEd,OAAO;AACT"}
|
package/dist/presets.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { n as AgentHookMap } from "./agent-
|
|
2
|
-
import { a as basicTools, i as _default, n as composePresets, r as definePreset, t as Preset } from "./index-
|
|
1
|
+
import { n as AgentHookMap } from "./agent-D0W9yClt.js";
|
|
2
|
+
import { a as basicTools, i as _default, n as composePresets, r as definePreset, t as Preset } from "./index-DZR99FD4.js";
|
|
3
3
|
export { type AgentHookMap, Preset, _default as basic, basicTools, composePresets, definePreset };
|
package/dist/presets.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { i as basic_default, n as definePreset, r as basicTools, t as composePresets } from "./presets-
|
|
1
|
+
import { i as basic_default, n as definePreset, r as basicTools, t as composePresets } from "./presets-D5ibZTml.js";
|
|
2
2
|
export { basic_default as basic, basicTools, composePresets, definePreset };
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { c as classifyErrorPrelude, d as matchesContextExceeded, f as matchesToolPairingError, l as errorMessage, u as isRetryableHttpStatus } from "./errors-DkR6GPJw.js";
|
|
2
|
-
import { A as renderSystemForWire, C as sanitizeToolSpecs, M as splitSystemPrompt, b as toolResultsMessage, f as toAnthropic, g as assistantMessage, l as fromAnthropic, n as SYNTHETIC_TOOL_RESULT_PLACEHOLDER, w as fillEstimatedCost, x as userMessage, y as openaiCompat } from "./messages-
|
|
2
|
+
import { A as renderSystemForWire, C as sanitizeToolSpecs, M as splitSystemPrompt, b as toolResultsMessage, f as toAnthropic, g as assistantMessage, l as fromAnthropic, n as SYNTHETIC_TOOL_RESULT_PLACEHOLDER, w as fillEstimatedCost, x as userMessage, y as openaiCompat } from "./messages-RPKrEPvH.js";
|
|
3
3
|
import { n as documentBlockMarker } from "./types-BiobHM1D.js";
|
|
4
4
|
import { dirname, resolve } from "node:path";
|
|
5
5
|
import { getModel } from "@earendil-works/pi-ai";
|
|
6
6
|
import { Buffer } from "node:buffer";
|
|
7
|
-
import { existsSync, mkdirSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
7
|
+
import { closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, renameSync, statSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
8
8
|
import { homedir } from "node:os";
|
|
9
9
|
import { getOAuthApiKey } from "@earendil-works/pi-ai/oauth";
|
|
10
|
+
import { mkdir, open, rename, rm } from "node:fs/promises";
|
|
10
11
|
import { streamOpenAICodexResponses } from "@earendil-works/pi-ai/openai-codex-responses";
|
|
11
12
|
//#region src/chat/anthropic-models.ts
|
|
12
13
|
/**
|
|
@@ -108,24 +109,55 @@ const ANTHROPIC_EXTRA_MODELS = [{
|
|
|
108
109
|
*
|
|
109
110
|
* Used by the chat-layer state / safelist / credentials / keybindings writers
|
|
110
111
|
* and the OAuth credentials store. The pattern is always the same: write to a
|
|
111
|
-
* sibling temp file, then `renameSync` over the target. `rename(2)`
|
|
112
|
-
* on the same filesystem, so concurrent readers either see the
|
|
113
|
-
* or the new one — never a half-written intermediate. The
|
|
112
|
+
* sibling temp file, fsync it, then `renameSync` over the target. `rename(2)`
|
|
113
|
+
* is atomic on the same filesystem, so concurrent readers either see the
|
|
114
|
+
* previous file or the new one — never a half-written intermediate. The fsync
|
|
115
|
+
* before the rename ensures the temp file's bytes are on disk before it takes
|
|
116
|
+
* the target's place (without it, a power loss shortly after rename can leave
|
|
117
|
+
* a zero-length or partial target on some filesystems). The temp suffix folds
|
|
114
118
|
* `process.pid` + a per-process monotonic counter so two writers — same
|
|
115
119
|
* process or same-millisecond siblings — can't pick the same tmp path.
|
|
116
120
|
*
|
|
117
121
|
* `ensureDir` runs `mkdirSync(dirname(path), { recursive: true })` before
|
|
118
122
|
* the write so callers don't have to repeat the boilerplate. `mode` is
|
|
119
|
-
* forwarded to
|
|
123
|
+
* forwarded to the file open (e.g. `0o600` for credentials files).
|
|
120
124
|
*/
|
|
121
125
|
let tmpCounter = 0;
|
|
126
|
+
function nextTmpPath(path) {
|
|
127
|
+
tmpCounter = (tmpCounter + 1) % Number.MAX_SAFE_INTEGER;
|
|
128
|
+
return `${path}.${process.pid}.${tmpCounter.toString(36)}.tmp`;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Best-effort fsync of the directory containing `path`, so the rename
|
|
132
|
+
* itself (the directory entry) is durable. Wrapped in try/catch: opening
|
|
133
|
+
* a directory for fsync fails on some platforms (notably Windows) and
|
|
134
|
+
* durability of the entry is a nice-to-have on top of the data fsync.
|
|
135
|
+
*/
|
|
136
|
+
function fsyncDirSync(path) {
|
|
137
|
+
try {
|
|
138
|
+
const fd = openSync(dirname(path), "r");
|
|
139
|
+
try {
|
|
140
|
+
fsyncSync(fd);
|
|
141
|
+
} finally {
|
|
142
|
+
closeSync(fd);
|
|
143
|
+
}
|
|
144
|
+
} catch {}
|
|
145
|
+
}
|
|
122
146
|
function writeFileAtomic(path, contents, options = {}) {
|
|
123
147
|
if (options.ensureDir) mkdirSync(dirname(path), { recursive: true });
|
|
124
|
-
|
|
125
|
-
const tmp = `${path}.${process.pid}.${tmpCounter.toString(36)}.tmp`;
|
|
148
|
+
const tmp = nextTmpPath(path);
|
|
126
149
|
try {
|
|
127
|
-
|
|
150
|
+
const fd = openSync(tmp, "w", options.mode);
|
|
151
|
+
try {
|
|
152
|
+
const buf = Buffer.from(contents, "utf8");
|
|
153
|
+
let offset = 0;
|
|
154
|
+
while (offset < buf.length) offset += writeSync(fd, buf, offset);
|
|
155
|
+
fsyncSync(fd);
|
|
156
|
+
} finally {
|
|
157
|
+
closeSync(fd);
|
|
158
|
+
}
|
|
128
159
|
renameSync(tmp, path);
|
|
160
|
+
fsyncDirSync(path);
|
|
129
161
|
} catch (err) {
|
|
130
162
|
try {
|
|
131
163
|
unlinkSync(tmp);
|
|
@@ -133,6 +165,36 @@ function writeFileAtomic(path, contents, options = {}) {
|
|
|
133
165
|
throw err;
|
|
134
166
|
}
|
|
135
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* Async variant of {@link writeFileAtomic} — same tmp-suffix, fsync and
|
|
170
|
+
* cleanup-on-failure semantics over `node:fs/promises`. Used by writers
|
|
171
|
+
* that already live on the async path (e.g. loop persistence blobs).
|
|
172
|
+
*/
|
|
173
|
+
async function writeFileAtomicAsync(path, contents, options = {}) {
|
|
174
|
+
if (options.ensureDir) await mkdir(dirname(path), { recursive: true });
|
|
175
|
+
const tmp = nextTmpPath(path);
|
|
176
|
+
try {
|
|
177
|
+
const fh = await open(tmp, "w", options.mode);
|
|
178
|
+
try {
|
|
179
|
+
await fh.writeFile(contents, "utf8");
|
|
180
|
+
await fh.sync();
|
|
181
|
+
} finally {
|
|
182
|
+
await fh.close();
|
|
183
|
+
}
|
|
184
|
+
await rename(tmp, path);
|
|
185
|
+
try {
|
|
186
|
+
const dh = await open(dirname(path), "r");
|
|
187
|
+
try {
|
|
188
|
+
await dh.sync();
|
|
189
|
+
} finally {
|
|
190
|
+
await dh.close();
|
|
191
|
+
}
|
|
192
|
+
} catch {}
|
|
193
|
+
} catch (err) {
|
|
194
|
+
await rm(tmp, { force: true }).catch(() => {});
|
|
195
|
+
throw err;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
136
198
|
//#endregion
|
|
137
199
|
//#region src/providers/oauth.ts
|
|
138
200
|
/**
|
|
@@ -504,15 +566,16 @@ function createClient(SDK, apiKey, isOAuth, baseURL, extraBetas, extraHeaders) {
|
|
|
504
566
|
}
|
|
505
567
|
/**
|
|
506
568
|
* Map `ThinkingLevel` budgeted tiers to Anthropic's `output_config.effort`
|
|
507
|
-
* enum.
|
|
508
|
-
*
|
|
509
|
-
* closest equivalent — Anthropic does not have a sub-`low` tier).
|
|
569
|
+
* enum. `minimal` collapses to `low` (the closest equivalent — Anthropic does
|
|
570
|
+
* not have a sub-`low` tier).
|
|
510
571
|
*/
|
|
511
572
|
const EFFORT_FOR_LEVEL = {
|
|
512
573
|
minimal: "low",
|
|
513
574
|
low: "low",
|
|
514
575
|
medium: "medium",
|
|
515
|
-
high: "high"
|
|
576
|
+
high: "high",
|
|
577
|
+
xhigh: "xhigh",
|
|
578
|
+
max: "max"
|
|
516
579
|
};
|
|
517
580
|
/**
|
|
518
581
|
* Decide how to translate a `ThinkingLevel` into Anthropic's request shape.
|
|
@@ -526,8 +589,8 @@ const EFFORT_FOR_LEVEL = {
|
|
|
526
589
|
* so the request builder caps `max_tokens` accordingly — adaptive has no
|
|
527
590
|
* native budget knob, but capping the response envelope soft-bounds the
|
|
528
591
|
* thinking that lives inside it.
|
|
529
|
-
* -
|
|
530
|
-
* `
|
|
592
|
+
* - Budgeted levels → adaptive thinking with an `effort` hint, unless
|
|
593
|
+
* `customBudget` is provided.
|
|
531
594
|
* - Any level + `customBudget` → explicit-budget `enabled` path. The caller
|
|
532
595
|
* has opted into precise budget control and accepts the Anthropic
|
|
533
596
|
* deprecation warning that comes with it on opus 4.6+. `'adaptive'` is the
|
|
@@ -840,6 +903,7 @@ function anthropic(anthropicParams) {
|
|
|
840
903
|
meta: {
|
|
841
904
|
defaultModel,
|
|
842
905
|
isOAuth,
|
|
906
|
+
clearsContextServerSide: Boolean(anthropicParams?.contextManagement),
|
|
843
907
|
capabilities: {
|
|
844
908
|
vision: true,
|
|
845
909
|
imageInToolResult: true,
|
|
@@ -1132,7 +1196,8 @@ function getApiKey$3(params) {
|
|
|
1132
1196
|
* Map zidane's thinking level to Baseten's per-model reasoning request shape:
|
|
1133
1197
|
*
|
|
1134
1198
|
* - `reasoning_effort` models (DeepSeek V4 Pro, GPT-OSS 120B) reason by
|
|
1135
|
-
* default; the effort string tunes depth. `'
|
|
1199
|
+
* default; the effort string tunes depth. `'minimal'` maps to `'low'`,
|
|
1200
|
+
* Anthropic-only upper tiers map to `'high'`, `'adaptive'` sends nothing
|
|
1136
1201
|
* (server default = medium); `'off'` sends nothing (cannot be disabled).
|
|
1137
1202
|
* - All other models opt in via `chat_template_args.enable_thinking` — any
|
|
1138
1203
|
* non-off level enables it (the template arg is boolean, no depth knob).
|
|
@@ -1144,7 +1209,7 @@ function planBasetenReasoning(ctx) {
|
|
|
1144
1209
|
if (!thinking || thinking === "off") return void 0;
|
|
1145
1210
|
if (EFFORT_MODELS.has(model)) {
|
|
1146
1211
|
if (thinking === "adaptive") return void 0;
|
|
1147
|
-
return { reasoning_effort: thinking === "minimal" ? "low" : thinking };
|
|
1212
|
+
return { reasoning_effort: thinking === "minimal" ? "low" : thinking === "xhigh" || thinking === "max" ? "high" : thinking };
|
|
1148
1213
|
}
|
|
1149
1214
|
return { chat_template_args: { enable_thinking: true } };
|
|
1150
1215
|
}
|
|
@@ -1851,7 +1916,7 @@ function openai(params) {
|
|
|
1851
1916
|
messages: toPiMessages(options.messages, modelId),
|
|
1852
1917
|
tools: options.tools
|
|
1853
1918
|
};
|
|
1854
|
-
const reasoningLevel = options.thinking && options.thinking !== "off" && options.thinking !== "adaptive" ? options.thinking : void 0;
|
|
1919
|
+
const reasoningLevel = options.thinking && options.thinking !== "off" && options.thinking !== "adaptive" ? options.thinking === "xhigh" || options.thinking === "max" ? "high" : options.thinking : void 0;
|
|
1855
1920
|
const stream = streamOpenAICodexResponses(model, context, {
|
|
1856
1921
|
apiKey,
|
|
1857
1922
|
maxTokens: options.maxTokens,
|
|
@@ -1927,6 +1992,6 @@ function openrouter(params) {
|
|
|
1927
1992
|
});
|
|
1928
1993
|
}
|
|
1929
1994
|
//#endregion
|
|
1930
|
-
export { createCursorOAuthProvider as a, baseten as c, anthropic as d, applyAnthropicCacheBreakpoints as f, FAST_MODE_OPTIONS as h, cursor as i, planBasetenReasoning as l,
|
|
1995
|
+
export { createCursorOAuthProvider as a, baseten as c, anthropic as d, applyAnthropicCacheBreakpoints as f, FAST_MODE_OPTIONS as g, ANTHROPIC_EXTRA_MODELS as h, cursor as i, planBasetenReasoning as l, writeFileAtomicAsync as m, openai as n, generatePkce as o, writeFileAtomic as p, local as r, cerebras as s, openrouter as t, arcee as u };
|
|
1931
1996
|
|
|
1932
|
-
//# sourceMappingURL=providers-
|
|
1997
|
+
//# sourceMappingURL=providers-C2cxujp_.js.map
|