zidane 5.9.13 → 5.9.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chat/pure.js +3 -2
- package/dist/chat.d.ts +2 -2
- package/dist/chat.js +5 -4
- package/dist/chat.js.map +1 -1
- package/dist/{edit-utils-CzHl1ct_.js → edit-utils-BkPqw6WE.js} +2 -135
- package/dist/edit-utils-BkPqw6WE.js.map +1 -0
- package/dist/eval.d.ts +1 -1
- package/dist/eval.js +2 -2
- package/dist/format-BNOXpl-1.js +136 -0
- package/dist/format-BNOXpl-1.js.map +1 -0
- package/dist/{headless-C15FmGco.js → headless-DNBpUy-6.js} +6 -6
- package/dist/headless-DNBpUy-6.js.map +1 -0
- package/dist/headless.d.ts +2 -2
- package/dist/headless.js +2 -2
- package/dist/{index-DgLlL4AT.d.ts → index-DutpkJJ7.d.ts} +3 -2
- package/dist/index-DutpkJJ7.d.ts.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -4
- package/dist/{login-DiSC5Ows.js → login-CVUjBzaO.js} +2 -2
- package/dist/{login-DiSC5Ows.js.map → login-CVUjBzaO.js.map} +1 -1
- package/dist/output/stream-json.d.ts +24 -0
- package/dist/output/stream-json.d.ts.map +1 -0
- package/dist/output/stream-json.js +37 -0
- package/dist/output/stream-json.js.map +1 -0
- package/dist/output/terminal.d.ts +16 -0
- package/dist/output/terminal.d.ts.map +1 -0
- package/dist/output/terminal.js +272 -0
- package/dist/output/terminal.js.map +1 -0
- package/dist/output.d.ts +3 -0
- package/dist/output.js +3 -0
- package/dist/{presets-ChaDIZaf.js → presets-DNuF7aK5.js} +2 -2
- package/dist/{presets-ChaDIZaf.js.map → presets-DNuF7aK5.js.map} +1 -1
- package/dist/presets.d.ts +1 -1
- package/dist/presets.js +1 -1
- package/dist/{tools-BLAxircm.js → tools-Cf5IsJEu.js} +3 -2
- package/dist/{tools-BLAxircm.js.map → tools-Cf5IsJEu.js.map} +1 -1
- package/dist/tools.d.ts +1 -1
- package/dist/tools.js +1 -1
- package/dist/{transcript-anchors-DELDp3Tl.d.ts → transcript-anchors-D7Nc5Rmy.d.ts} +2 -2
- package/dist/{transcript-anchors-DELDp3Tl.d.ts.map → transcript-anchors-D7Nc5Rmy.d.ts.map} +1 -1
- package/dist/{transcript-anchors-awh3E-cq.js → transcript-anchors-NA-s8Ore.js} +5 -5
- package/dist/{transcript-anchors-awh3E-cq.js.map → transcript-anchors-NA-s8Ore.js.map} +1 -1
- package/dist/tui.d.ts +1 -1
- package/dist/tui.js +6 -6
- package/dist/{turn-operations-CP8vfESx.js → turn-operations-BKg16YDb.js} +2 -2
- package/dist/{turn-operations-CP8vfESx.js.map → turn-operations-BKg16YDb.js.map} +1 -1
- package/dist/types.d.ts +1 -1
- package/docs/HEADLESS.md +57 -0
- package/package.json +13 -1
- package/dist/edit-utils-CzHl1ct_.js.map +0 -1
- package/dist/headless-C15FmGco.js.map +0 -1
- package/dist/index-DgLlL4AT.d.ts.map +0 -1
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { t as Agent } from "../agent-CYPEZ9i3.js";
|
|
2
|
+
import { In as HeadlessOutputFormat, Ln as HeadlessResult, Mn as FormattedHeadlessTurnEvent, Pn as HeadlessEvent, jn as FormattedHeadlessResult } from "../index-DutpkJJ7.js";
|
|
3
|
+
|
|
4
|
+
//#region src/output/stream-json.d.ts
|
|
5
|
+
type StreamJsonOutputFormat = HeadlessOutputFormat;
|
|
6
|
+
type StreamJsonTurnEvent = Extract<HeadlessEvent, {
|
|
7
|
+
type: 'turn';
|
|
8
|
+
}>;
|
|
9
|
+
interface StreamJsonFormatOptions {
|
|
10
|
+
format?: StreamJsonOutputFormat;
|
|
11
|
+
providerName?: string;
|
|
12
|
+
}
|
|
13
|
+
interface StreamJsonOutputOptions extends StreamJsonFormatOptions {
|
|
14
|
+
write?: (line: string) => void;
|
|
15
|
+
}
|
|
16
|
+
declare function formatStreamJsonTurnEvent(event: StreamJsonTurnEvent, options?: StreamJsonFormatOptions): FormattedHeadlessTurnEvent;
|
|
17
|
+
declare function streamJsonTurnEventToJsonl(event: StreamJsonTurnEvent, options?: StreamJsonFormatOptions): string;
|
|
18
|
+
declare function formatStreamJsonResult(result: HeadlessResult, options?: StreamJsonFormatOptions): FormattedHeadlessResult;
|
|
19
|
+
declare function streamJsonResultToJsonl(result: HeadlessResult, options?: StreamJsonFormatOptions): string;
|
|
20
|
+
declare function createStreamJsonOutputHandler(options?: StreamJsonOutputOptions): (event: HeadlessEvent) => void;
|
|
21
|
+
declare function setupStreamJsonOutput(agent: Agent, options?: StreamJsonOutputOptions): () => void;
|
|
22
|
+
//#endregion
|
|
23
|
+
export { StreamJsonFormatOptions, StreamJsonOutputFormat, StreamJsonOutputOptions, StreamJsonTurnEvent, createStreamJsonOutputHandler, formatStreamJsonResult, formatStreamJsonTurnEvent, setupStreamJsonOutput, streamJsonResultToJsonl, streamJsonTurnEventToJsonl };
|
|
24
|
+
//# sourceMappingURL=stream-json.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-json.d.ts","names":[],"sources":["../../src/output/stream-json.ts"],"mappings":";;;;KAeY,sBAAA,GAAyB,oBAAoB;AAAA,KAC7C,mBAAA,GAAsB,OAAO,CAAC,aAAA;EAAiB,IAAA;AAAA;AAAA,UAE1C,uBAAA;EACf,MAAA,GAAS,sBAAsB;EAC/B,YAAA;AAAA;AAAA,UAGe,uBAAA,SAAgC,uBAAuB;EACtE,KAAA,IAAS,IAAA;AAAA;AAAA,iBAiBK,yBAAA,CACd,KAAA,EAAO,mBAAA,EACP,OAAA,GAAS,uBAAA,GACR,0BAAA;AAAA,iBAIa,0BAAA,CACd,KAAA,EAAO,mBAAA,EACP,OAAA,GAAS,uBAA4B;AAAA,iBAKvB,sBAAA,CACd,MAAA,EAAQ,cAAA,EACR,OAAA,GAAS,uBAAA,GACR,uBAAA;AAAA,iBAIa,uBAAA,CACd,MAAA,EAAQ,cAAA,EACR,OAAA,GAAS,uBAA4B;AAAA,iBAKvB,6BAAA,CACd,OAAA,GAAS,uBAAA,IACP,KAAA,EAAO,aAAa;AAAA,iBASR,qBAAA,CACd,KAAA,EAAO,KAAA,EACP,OAAA,GAAS,uBAA4B"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { i as formattedHeadlessTurnEventToJsonl, n as formatHeadlessResult, o as installHeadlessEventAdapter, r as formatHeadlessTurnEvent } from "../headless-DNBpUy-6.js";
|
|
2
|
+
//#region src/output/stream-json.ts
|
|
3
|
+
function resolveFormatOptions(options) {
|
|
4
|
+
return {
|
|
5
|
+
format: options.format ?? "zidane",
|
|
6
|
+
providerName: options.providerName ?? "openai"
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
function defaultWrite(line) {
|
|
10
|
+
process.stdout.write(line);
|
|
11
|
+
}
|
|
12
|
+
function formatStreamJsonTurnEvent(event, options = {}) {
|
|
13
|
+
return formatHeadlessTurnEvent(event, resolveFormatOptions(options));
|
|
14
|
+
}
|
|
15
|
+
function streamJsonTurnEventToJsonl(event, options = {}) {
|
|
16
|
+
return formattedHeadlessTurnEventToJsonl(formatStreamJsonTurnEvent(event, options));
|
|
17
|
+
}
|
|
18
|
+
function formatStreamJsonResult(result, options = {}) {
|
|
19
|
+
return formatHeadlessResult(result, resolveFormatOptions(options));
|
|
20
|
+
}
|
|
21
|
+
function streamJsonResultToJsonl(result, options = {}) {
|
|
22
|
+
return `${JSON.stringify(formatStreamJsonResult(result, options))}\n`;
|
|
23
|
+
}
|
|
24
|
+
function createStreamJsonOutputHandler(options = {}) {
|
|
25
|
+
const write = options.write ?? defaultWrite;
|
|
26
|
+
return (event) => {
|
|
27
|
+
if (event.type !== "turn") return;
|
|
28
|
+
write(streamJsonTurnEventToJsonl(event, options));
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function setupStreamJsonOutput(agent, options = {}) {
|
|
32
|
+
return installHeadlessEventAdapter(agent.hooks, createStreamJsonOutputHandler(options));
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { createStreamJsonOutputHandler, formatStreamJsonResult, formatStreamJsonTurnEvent, setupStreamJsonOutput, streamJsonResultToJsonl, streamJsonTurnEventToJsonl };
|
|
36
|
+
|
|
37
|
+
//# sourceMappingURL=stream-json.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-json.js","names":[],"sources":["../../src/output/stream-json.ts"],"sourcesContent":["import type { Agent } from '../agent'\nimport type {\n FormattedHeadlessResult,\n FormattedHeadlessTurnEvent,\n HeadlessEvent,\n HeadlessOutputFormat,\n HeadlessResult,\n} from '../headless'\nimport {\n formatHeadlessResult,\n formatHeadlessTurnEvent,\n formattedHeadlessTurnEventToJsonl,\n installHeadlessEventAdapter,\n} from '../headless'\n\nexport type StreamJsonOutputFormat = HeadlessOutputFormat\nexport type StreamJsonTurnEvent = Extract<HeadlessEvent, { type: 'turn' }>\n\nexport interface StreamJsonFormatOptions {\n format?: StreamJsonOutputFormat\n providerName?: string\n}\n\nexport interface StreamJsonOutputOptions extends StreamJsonFormatOptions {\n write?: (line: string) => void\n}\n\nfunction resolveFormatOptions(options: StreamJsonFormatOptions): {\n format: StreamJsonOutputFormat\n providerName: string\n} {\n return {\n format: options.format ?? 'zidane',\n providerName: options.providerName ?? 'openai',\n }\n}\n\nfunction defaultWrite(line: string): void {\n process.stdout.write(line)\n}\n\nexport function formatStreamJsonTurnEvent(\n event: StreamJsonTurnEvent,\n options: StreamJsonFormatOptions = {},\n): FormattedHeadlessTurnEvent {\n return formatHeadlessTurnEvent(event, resolveFormatOptions(options))\n}\n\nexport function streamJsonTurnEventToJsonl(\n event: StreamJsonTurnEvent,\n options: StreamJsonFormatOptions = {},\n): string {\n return formattedHeadlessTurnEventToJsonl(formatStreamJsonTurnEvent(event, options))\n}\n\nexport function formatStreamJsonResult(\n result: HeadlessResult,\n options: StreamJsonFormatOptions = {},\n): FormattedHeadlessResult {\n return formatHeadlessResult(result, resolveFormatOptions(options))\n}\n\nexport function streamJsonResultToJsonl(\n result: HeadlessResult,\n options: StreamJsonFormatOptions = {},\n): string {\n return `${JSON.stringify(formatStreamJsonResult(result, options))}\\n`\n}\n\nexport function createStreamJsonOutputHandler(\n options: StreamJsonOutputOptions = {},\n): (event: HeadlessEvent) => void {\n const write = options.write ?? defaultWrite\n return (event) => {\n if (event.type !== 'turn')\n return\n write(streamJsonTurnEventToJsonl(event, options))\n }\n}\n\nexport function setupStreamJsonOutput(\n agent: Agent,\n options: StreamJsonOutputOptions = {},\n): () => void {\n return installHeadlessEventAdapter(agent.hooks, createStreamJsonOutputHandler(options))\n}\n"],"mappings":";;AA2BA,SAAS,qBAAqB,SAG5B;CACA,OAAO;EACL,QAAQ,QAAQ,UAAU;EAC1B,cAAc,QAAQ,gBAAgB;CACxC;AACF;AAEA,SAAS,aAAa,MAAoB;CACxC,QAAQ,OAAO,MAAM,IAAI;AAC3B;AAEA,SAAgB,0BACd,OACA,UAAmC,CAAC,GACR;CAC5B,OAAO,wBAAwB,OAAO,qBAAqB,OAAO,CAAC;AACrE;AAEA,SAAgB,2BACd,OACA,UAAmC,CAAC,GAC5B;CACR,OAAO,kCAAkC,0BAA0B,OAAO,OAAO,CAAC;AACpF;AAEA,SAAgB,uBACd,QACA,UAAmC,CAAC,GACX;CACzB,OAAO,qBAAqB,QAAQ,qBAAqB,OAAO,CAAC;AACnE;AAEA,SAAgB,wBACd,QACA,UAAmC,CAAC,GAC5B;CACR,OAAO,GAAG,KAAK,UAAU,uBAAuB,QAAQ,OAAO,CAAC,EAAE;AACpE;AAEA,SAAgB,8BACd,UAAmC,CAAC,GACJ;CAChC,MAAM,QAAQ,QAAQ,SAAS;CAC/B,QAAQ,UAAU;EAChB,IAAI,MAAM,SAAS,QACjB;EACF,MAAM,2BAA2B,OAAO,OAAO,CAAC;CAClD;AACF;AAEA,SAAgB,sBACd,OACA,UAAmC,CAAC,GACxB;CACZ,OAAO,4BAA4B,MAAM,OAAO,8BAA8B,OAAO,CAAC;AACxF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { r as AgentHooks, t as Agent } from "../agent-CYPEZ9i3.js";
|
|
2
|
+
import { t as Preset } from "../index-DutpkJJ7.js";
|
|
3
|
+
|
|
4
|
+
//#region src/output/terminal.d.ts
|
|
5
|
+
interface TerminalOutputOptions {
|
|
6
|
+
printHeader?: boolean;
|
|
7
|
+
title?: string;
|
|
8
|
+
shouldPrint?: () => boolean;
|
|
9
|
+
shouldPrintToolCall?: (ctx: Parameters<AgentHooks['tool:before']>[0]) => boolean;
|
|
10
|
+
shouldPrintSummary?: (stats: Parameters<AgentHooks['agent:done']>[0]) => boolean;
|
|
11
|
+
}
|
|
12
|
+
declare function printTerminalHeader(agent: Agent, model: string, prompt: string, preset: Preset, title?: string): void;
|
|
13
|
+
declare function setupTerminalOutput(agent: Agent, model: string, prompt: string, preset: Preset, options?: TerminalOutputOptions): Promise<void>;
|
|
14
|
+
//#endregion
|
|
15
|
+
export { TerminalOutputOptions, printTerminalHeader, setupTerminalOutput };
|
|
16
|
+
//# sourceMappingURL=terminal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"terminal.d.ts","names":[],"sources":["../../src/output/terminal.ts"],"mappings":";;;;UA+CiB,qBAAA;EACf,WAAA;EACA,KAAA;EACA,WAAA;EACA,mBAAA,IAAuB,GAAA,EAAK,UAAA,CAAW,UAAA;EACvC,kBAAA,IAAsB,KAAA,EAAO,UAAA,CAAW,UAAA;AAAA;AAAA,iBAG1B,mBAAA,CAAoB,KAAA,EAAO,KAAA,EAAO,KAAA,UAAe,MAAA,UAAgB,MAAA,EAAQ,MAAM,EAAE,KAAA;AAAA,iBAc3E,mBAAA,CAAoB,KAAA,EAAO,KAAA,EAAO,KAAA,UAAe,MAAA,UAAgB,MAAA,EAAQ,MAAA,EAAQ,OAAA,GAAS,qBAAA,GAA0B,OAAA"}
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
import { s as previewLine } from "../format-BNOXpl-1.js";
|
|
2
|
+
import { i as statsByModel } from "../stats-DAKBEKjc.js";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
//#region src/output/terminal.ts
|
|
5
|
+
const PARENT_KEY = "__parent__";
|
|
6
|
+
function indent(depth) {
|
|
7
|
+
return " ".repeat(depth);
|
|
8
|
+
}
|
|
9
|
+
/** Style child output dim so the visual hierarchy is obvious at a glance. */
|
|
10
|
+
function dye(depth, s) {
|
|
11
|
+
if (depth === 0) return s;
|
|
12
|
+
return chalk.dim(s);
|
|
13
|
+
}
|
|
14
|
+
function printTerminalHeader(agent, model, prompt, preset, title = "⚽ Zizou") {
|
|
15
|
+
console.log(`\n${title}`);
|
|
16
|
+
console.log(`${chalk.bold("🤖 Model:")} ${chalk.green(model)} (${agent.meta.isOAuth ? chalk.green("oauth") : chalk.red("key")})`);
|
|
17
|
+
console.log(`${chalk.bold("📝 Prompt:")} ${chalk.yellow(prompt)}`);
|
|
18
|
+
if (preset.name) console.log(`${chalk.bold("🔧 Preset:")} ${chalk.cyan(preset.name)}`);
|
|
19
|
+
if (preset.tools) {
|
|
20
|
+
const names = Object.values(preset.tools).map((t) => t.spec.name).join(", ");
|
|
21
|
+
if (names) console.log(`${chalk.bold("🔧 Tools:")} ${chalk.cyan(names)}`);
|
|
22
|
+
}
|
|
23
|
+
console.log();
|
|
24
|
+
}
|
|
25
|
+
async function setupTerminalOutput(agent, model, prompt, preset, options = {}) {
|
|
26
|
+
if (options.printHeader !== false) printTerminalHeader(agent, model, prompt, preset, options.title);
|
|
27
|
+
const cursors = /* @__PURE__ */ new Map();
|
|
28
|
+
cursors.set(PARENT_KEY, {
|
|
29
|
+
depth: 0,
|
|
30
|
+
isFirstDelta: true,
|
|
31
|
+
hadToolCalls: false,
|
|
32
|
+
isThinking: false
|
|
33
|
+
});
|
|
34
|
+
/** Last emitter that wrote to stdout. Drives newline-on-switch behavior. */
|
|
35
|
+
let activeEmitter = PARENT_KEY;
|
|
36
|
+
function noteStreamWrite(text) {
|
|
37
|
+
text.endsWith("\n");
|
|
38
|
+
}
|
|
39
|
+
function ensureSummaryLineStart() {
|
|
40
|
+
process.stdout.write("\n\n");
|
|
41
|
+
activeEmitter = PARENT_KEY;
|
|
42
|
+
}
|
|
43
|
+
function canPrint() {
|
|
44
|
+
return options.shouldPrint?.() ?? true;
|
|
45
|
+
}
|
|
46
|
+
function getCursor(key, depth) {
|
|
47
|
+
let c = cursors.get(key);
|
|
48
|
+
if (!c) {
|
|
49
|
+
c = {
|
|
50
|
+
depth,
|
|
51
|
+
isFirstDelta: true,
|
|
52
|
+
hadToolCalls: false,
|
|
53
|
+
isThinking: false
|
|
54
|
+
};
|
|
55
|
+
cursors.set(key, c);
|
|
56
|
+
}
|
|
57
|
+
return c;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Switch the active emitter; when it changes mid-stream, drop a newline +
|
|
61
|
+
* indent prefix so the next write lands cleanly on its own line.
|
|
62
|
+
*/
|
|
63
|
+
function switchTo(key, depth) {
|
|
64
|
+
const cursor = getCursor(key, depth);
|
|
65
|
+
if (activeEmitter !== key) {
|
|
66
|
+
process.stdout.write(`\n${indent(depth)}`);
|
|
67
|
+
activeEmitter = key;
|
|
68
|
+
cursor.isFirstDelta = false;
|
|
69
|
+
}
|
|
70
|
+
return cursor;
|
|
71
|
+
}
|
|
72
|
+
agent.hooks.hook("turn:before", () => {
|
|
73
|
+
const c = cursors.get(PARENT_KEY);
|
|
74
|
+
c.isFirstDelta = true;
|
|
75
|
+
c.isThinking = false;
|
|
76
|
+
});
|
|
77
|
+
agent.hooks.hook("stream:thinking", ({ delta }) => {
|
|
78
|
+
if (!canPrint()) return;
|
|
79
|
+
const c = switchTo(PARENT_KEY, 0);
|
|
80
|
+
if (!c.isThinking) {
|
|
81
|
+
if (c.hadToolCalls) process.stdout.write("\n");
|
|
82
|
+
process.stdout.write(chalk.dim.italic("🧠 "));
|
|
83
|
+
noteStreamWrite("🧠 ");
|
|
84
|
+
c.isThinking = true;
|
|
85
|
+
c.hadToolCalls = false;
|
|
86
|
+
}
|
|
87
|
+
process.stdout.write(chalk.dim.italic(delta));
|
|
88
|
+
noteStreamWrite(delta);
|
|
89
|
+
});
|
|
90
|
+
agent.hooks.hook("stream:text", ({ delta }) => {
|
|
91
|
+
if (!canPrint()) return;
|
|
92
|
+
const c = switchTo(PARENT_KEY, 0);
|
|
93
|
+
if (c.isFirstDelta) {
|
|
94
|
+
if (c.isThinking) {
|
|
95
|
+
process.stdout.write("\n");
|
|
96
|
+
c.isThinking = false;
|
|
97
|
+
}
|
|
98
|
+
if (c.hadToolCalls) process.stdout.write("\n");
|
|
99
|
+
c.isFirstDelta = false;
|
|
100
|
+
c.hadToolCalls = false;
|
|
101
|
+
}
|
|
102
|
+
process.stdout.write(delta);
|
|
103
|
+
noteStreamWrite(delta);
|
|
104
|
+
});
|
|
105
|
+
agent.hooks.hook("stream:end", () => {});
|
|
106
|
+
agent.hooks.hook("tool:before", (ctx) => {
|
|
107
|
+
if (!canPrint()) return;
|
|
108
|
+
if (options.shouldPrintToolCall && !options.shouldPrintToolCall(ctx)) return;
|
|
109
|
+
const c = switchTo(PARENT_KEY, 0);
|
|
110
|
+
if (c.isThinking) {
|
|
111
|
+
process.stdout.write("\n");
|
|
112
|
+
c.isThinking = false;
|
|
113
|
+
}
|
|
114
|
+
if (!c.hadToolCalls) process.stdout.write("\n");
|
|
115
|
+
c.hadToolCalls = true;
|
|
116
|
+
const stringified = JSON.stringify(ctx.input);
|
|
117
|
+
const args = stringified && stringified.trim() !== "{}" ? ` (${chalk.yellow(stringified)})` : "";
|
|
118
|
+
console.log(` ↳ ${chalk.cyan(ctx.name)}${args}`);
|
|
119
|
+
activeEmitter = PARENT_KEY;
|
|
120
|
+
});
|
|
121
|
+
agent.hooks.hook("system:before", (ctx) => {
|
|
122
|
+
if (!canPrint()) return;
|
|
123
|
+
console.log(chalk.cyan(`System: ${chalk.yellow(ctx.system)}`));
|
|
124
|
+
});
|
|
125
|
+
agent.hooks.hook("spawn:before", ({ id, task, depth }) => {
|
|
126
|
+
if (!canPrint()) return;
|
|
127
|
+
const d = depth ?? 1;
|
|
128
|
+
if (activeEmitter !== PARENT_KEY) process.stdout.write("\n");
|
|
129
|
+
const taskPreview = previewLine(task, 80);
|
|
130
|
+
console.log(`${indent(d)}${chalk.dim("🌱")} ${chalk.bold(dye(d, `[${id}]`))} ${chalk.dim("depth=")}${chalk.dim(String(d))} ${dye(d, taskPreview)}`);
|
|
131
|
+
activeEmitter = PARENT_KEY;
|
|
132
|
+
});
|
|
133
|
+
agent.hooks.hook("spawn:complete", (ctx) => {
|
|
134
|
+
if (!canPrint()) return;
|
|
135
|
+
const d = ctx.depth ?? 1;
|
|
136
|
+
const stats = ctx.stats;
|
|
137
|
+
if (activeEmitter !== PARENT_KEY) process.stdout.write("\n");
|
|
138
|
+
const status = ctx.status === "completed" ? chalk.green("✓") : ctx.status === "aborted" ? chalk.yellow("⚠") : chalk.red("✗");
|
|
139
|
+
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`;
|
|
140
|
+
if (typeof stats.cost === "number" && stats.cost > 0) summary += chalk.dim(` · $${stats.cost.toFixed(6)}`);
|
|
141
|
+
if (stats.children && stats.children.length > 0) summary += chalk.dim(` · ${stats.children.length} sub-spawn${stats.children.length === 1 ? "" : "s"}`);
|
|
142
|
+
console.log(summary);
|
|
143
|
+
cursors.delete(ctx.id);
|
|
144
|
+
activeEmitter = PARENT_KEY;
|
|
145
|
+
});
|
|
146
|
+
agent.hooks.hook("spawn:error", ({ id, depth, error }) => {
|
|
147
|
+
if (!canPrint()) return;
|
|
148
|
+
const d = depth ?? 1;
|
|
149
|
+
if (activeEmitter !== PARENT_KEY) process.stdout.write("\n");
|
|
150
|
+
console.log(`${indent(d)}${chalk.red("✗")} ${chalk.bold(dye(d, `[${id}]`))} ${chalk.red(`error: ${error.message}`)}`);
|
|
151
|
+
cursors.delete(id);
|
|
152
|
+
activeEmitter = PARENT_KEY;
|
|
153
|
+
});
|
|
154
|
+
agent.hooks.hook("child:turn:after", ({ childId }) => {
|
|
155
|
+
const c = cursors.get(childId);
|
|
156
|
+
if (c) {
|
|
157
|
+
c.isFirstDelta = true;
|
|
158
|
+
c.isThinking = false;
|
|
159
|
+
}
|
|
160
|
+
});
|
|
161
|
+
agent.hooks.hook("child:stream:thinking", ({ delta, childId, depth }) => {
|
|
162
|
+
if (!canPrint()) return;
|
|
163
|
+
const c = switchTo(childId, depth);
|
|
164
|
+
if (!c.isThinking) {
|
|
165
|
+
if (c.hadToolCalls) process.stdout.write(`\n${indent(depth)}`);
|
|
166
|
+
process.stdout.write(chalk.dim.italic("🧠 "));
|
|
167
|
+
noteStreamWrite("🧠 ");
|
|
168
|
+
c.isThinking = true;
|
|
169
|
+
c.hadToolCalls = false;
|
|
170
|
+
}
|
|
171
|
+
process.stdout.write(chalk.dim.italic(delta));
|
|
172
|
+
noteStreamWrite(delta);
|
|
173
|
+
});
|
|
174
|
+
agent.hooks.hook("child:stream:text", ({ delta, childId, depth }) => {
|
|
175
|
+
if (!canPrint()) return;
|
|
176
|
+
const c = switchTo(childId, depth);
|
|
177
|
+
if (c.isFirstDelta) {
|
|
178
|
+
if (c.isThinking) {
|
|
179
|
+
process.stdout.write(`\n${indent(depth)}`);
|
|
180
|
+
c.isThinking = false;
|
|
181
|
+
}
|
|
182
|
+
if (c.hadToolCalls) process.stdout.write(`\n${indent(depth)}`);
|
|
183
|
+
c.isFirstDelta = false;
|
|
184
|
+
c.hadToolCalls = false;
|
|
185
|
+
}
|
|
186
|
+
process.stdout.write(dye(depth, delta));
|
|
187
|
+
noteStreamWrite(delta);
|
|
188
|
+
});
|
|
189
|
+
agent.hooks.hook("child:stream:end", ({ childId }) => {
|
|
190
|
+
if (activeEmitter === childId) activeEmitter = PARENT_KEY;
|
|
191
|
+
});
|
|
192
|
+
agent.hooks.hook("child:tool:before", ({ name, input, childId, depth }) => {
|
|
193
|
+
if (!canPrint()) return;
|
|
194
|
+
const c = switchTo(childId, depth);
|
|
195
|
+
if (c.isThinking) {
|
|
196
|
+
process.stdout.write("\n");
|
|
197
|
+
c.isThinking = false;
|
|
198
|
+
}
|
|
199
|
+
if (!c.hadToolCalls) process.stdout.write("\n");
|
|
200
|
+
c.hadToolCalls = true;
|
|
201
|
+
const stringified = JSON.stringify(input);
|
|
202
|
+
const args = stringified && stringified.trim() !== "{}" ? ` (${chalk.yellow(stringified)})` : "";
|
|
203
|
+
console.log(`${indent(depth)} ↳ ${chalk.cyan(name)}${args}`);
|
|
204
|
+
activeEmitter = childId;
|
|
205
|
+
});
|
|
206
|
+
agent.hooks.hook("child:tool:error", ({ name, error, depth }) => {
|
|
207
|
+
if (!canPrint()) return;
|
|
208
|
+
if (activeEmitter !== PARENT_KEY) process.stdout.write("\n");
|
|
209
|
+
console.log(`${indent(depth)} ${chalk.red("✗")} ${chalk.cyan(name)}: ${chalk.red(error.message)}`);
|
|
210
|
+
activeEmitter = PARENT_KEY;
|
|
211
|
+
});
|
|
212
|
+
agent.hooks.hook("agent:done", (stats) => {
|
|
213
|
+
if (!canPrint()) return;
|
|
214
|
+
if (options.shouldPrintSummary && !options.shouldPrintSummary(stats)) return;
|
|
215
|
+
const { totalIn, totalOut, totalCacheRead, totalCacheCreation, turns, elapsed, cost, children } = stats;
|
|
216
|
+
ensureSummaryLineStart();
|
|
217
|
+
const seconds = Math.floor(elapsed / 1e3);
|
|
218
|
+
const minutes = Math.floor(seconds / 60);
|
|
219
|
+
const remainingSeconds = seconds % 60;
|
|
220
|
+
const timeStr = minutes > 0 ? `${minutes}m ${remainingSeconds}s` : `${remainingSeconds}s`;
|
|
221
|
+
let line = `🧮 Tokens: ${chalk.yellow(totalIn)} in / ${chalk.green(totalOut)} out`;
|
|
222
|
+
line += ` (${chalk.magenta(turns)} parent turn${turns !== 1 ? "s" : ""})`;
|
|
223
|
+
line += ` in ${chalk.green(timeStr)}`;
|
|
224
|
+
if (totalCacheCreation || totalCacheRead) line += `\n Cache: ${chalk.blue(totalCacheCreation)} created / ${chalk.blue(totalCacheRead)} read`;
|
|
225
|
+
if (cost) line += `\n💸 Cost: ${chalk.yellow(`$${cost.toFixed(6)}`)}`;
|
|
226
|
+
if (children && children.length > 0) {
|
|
227
|
+
line += `\n Children: ${chalk.magenta(children.length)}`;
|
|
228
|
+
for (const child of children) {
|
|
229
|
+
line += `\n · [${chalk.bold(child.id)}] ${chalk.yellow(child.stats.totalIn)} in / ${chalk.green(child.stats.totalOut)} out`;
|
|
230
|
+
line += chalk.dim(` (${child.stats.turns} turn${child.stats.turns === 1 ? "" : "s"}, ${child.status ?? "completed"})`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
const byModel = statsByModel(stats);
|
|
234
|
+
if (byModel.size > 1) {
|
|
235
|
+
line += `\n By model:`;
|
|
236
|
+
for (const [modelId, usage] of byModel) {
|
|
237
|
+
line += `\n · ${chalk.cyan(modelId)} ${chalk.yellow(usage.input)} in / ${chalk.green(usage.output)} out (${usage.turns} turn${usage.turns === 1 ? "" : "s"})`;
|
|
238
|
+
if (usage.cost > 0) line += chalk.dim(` · $${usage.cost.toFixed(6)}`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
console.log(chalk.cyan(line));
|
|
242
|
+
if (agent.session) {
|
|
243
|
+
const session = agent.session;
|
|
244
|
+
const totalRuns = session.runs.length;
|
|
245
|
+
const recordedIn = session.runs.reduce((sum, r) => sum + (r.tokensIn ?? 0), 0);
|
|
246
|
+
const recordedOut = session.runs.reduce((sum, r) => sum + (r.tokensOut ?? 0), 0);
|
|
247
|
+
const recordedCost = session.runs.reduce((sum, r) => sum + (r.cost ?? 0), 0);
|
|
248
|
+
let sessionLine = `📋 Session ${chalk.dim(session.id)}: ${chalk.bold(String(totalRuns))} run${totalRuns === 1 ? "" : "s"} recorded`;
|
|
249
|
+
sessionLine += `, ${chalk.yellow(recordedIn)} in / ${chalk.green(recordedOut)} out`;
|
|
250
|
+
if (recordedCost) sessionLine += `, ${chalk.yellow(`$${recordedCost.toFixed(6)}`)}`;
|
|
251
|
+
console.log(chalk.dim(sessionLine));
|
|
252
|
+
const offLedgerIn = totalIn - recordedIn;
|
|
253
|
+
const offLedgerOut = totalOut - recordedOut;
|
|
254
|
+
const childCount = countDescendants(children);
|
|
255
|
+
if ((offLedgerIn > 0 || offLedgerOut > 0) && childCount > 0) {
|
|
256
|
+
const note = ` ↳ ${chalk.magenta(childCount)} subagent${childCount === 1 ? "" : "s"} ran in-memory (+${chalk.yellow(offLedgerIn)} in / +${chalk.green(offLedgerOut)} out, not persisted)`;
|
|
257
|
+
console.log(chalk.dim(note));
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
/** Recursively count every descendant in the children tree. */
|
|
263
|
+
function countDescendants(children) {
|
|
264
|
+
if (!children) return 0;
|
|
265
|
+
let n = 0;
|
|
266
|
+
for (const child of children) n += 1 + countDescendants(child.stats.children);
|
|
267
|
+
return n;
|
|
268
|
+
}
|
|
269
|
+
//#endregion
|
|
270
|
+
export { printTerminalHeader, setupTerminalOutput };
|
|
271
|
+
|
|
272
|
+
//# sourceMappingURL=terminal.js.map
|
|
@@ -0,0 +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\nexport async function setupTerminalOutput(agent: Agent, model: string, prompt: string, preset: Preset, options: TerminalOutputOptions = {}) {\n if (options.printHeader !== false)\n printTerminalHeader(agent, model, prompt, preset, options.title)\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 agent.hooks.hook('turn:before', () => {\n const c = cursors.get(PARENT_KEY)!\n c.isFirstDelta = true\n c.isThinking = false\n })\n\n agent.hooks.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 agent.hooks.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 agent.hooks.hook('stream:end', () => {\n needsSummaryNewline = false\n })\n\n agent.hooks.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 agent.hooks.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 agent.hooks.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 agent.hooks.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 agent.hooks.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 agent.hooks.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 agent.hooks.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 agent.hooks.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 agent.hooks.hook('child:stream:end', ({ childId }) => {\n if (activeEmitter === childId)\n activeEmitter = PARENT_KEY\n needsSummaryNewline = false\n })\n\n agent.hooks.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 agent.hooks.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 agent.hooks.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\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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"}
|
package/dist/output.d.ts
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { StreamJsonFormatOptions, StreamJsonOutputFormat, StreamJsonOutputOptions, StreamJsonTurnEvent, createStreamJsonOutputHandler, formatStreamJsonResult, formatStreamJsonTurnEvent, setupStreamJsonOutput, streamJsonResultToJsonl, streamJsonTurnEventToJsonl } from "./output/stream-json.js";
|
|
2
|
+
import { TerminalOutputOptions, printTerminalHeader, setupTerminalOutput } from "./output/terminal.js";
|
|
3
|
+
export { type StreamJsonFormatOptions, type StreamJsonOutputFormat, type StreamJsonOutputOptions, type StreamJsonTurnEvent, type TerminalOutputOptions, createStreamJsonOutputHandler, formatStreamJsonResult, formatStreamJsonTurnEvent, printTerminalHeader, setupStreamJsonOutput, setupTerminalOutput, streamJsonResultToJsonl, streamJsonTurnEventToJsonl };
|
package/dist/output.js
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import { createStreamJsonOutputHandler, formatStreamJsonResult, formatStreamJsonTurnEvent, setupStreamJsonOutput, streamJsonResultToJsonl, streamJsonTurnEventToJsonl } from "./output/stream-json.js";
|
|
2
|
+
import { printTerminalHeader, setupTerminalOutput } from "./output/terminal.js";
|
|
3
|
+
export { createStreamJsonOutputHandler, formatStreamJsonResult, formatStreamJsonTurnEvent, printTerminalHeader, setupStreamJsonOutput, setupTerminalOutput, streamJsonResultToJsonl, streamJsonTurnEventToJsonl };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as multiEdit, i as readFile, n as createSpawnTool, o as listFiles, r as shellKill, t as writeFile, u as edit, v as shell } from "./tools-
|
|
1
|
+
import { a as multiEdit, i as readFile, n as createSpawnTool, o as listFiles, r as shellKill, t as writeFile, u as edit, v as shell } from "./tools-Cf5IsJEu.js";
|
|
2
2
|
//#region src/presets/basic.ts
|
|
3
3
|
/**
|
|
4
4
|
* Core tools available in every basic preset (without spawn).
|
|
@@ -107,4 +107,4 @@ function composePresets(...presets) {
|
|
|
107
107
|
//#endregion
|
|
108
108
|
export { basic_default as i, definePreset as n, basicTools as r, composePresets as t };
|
|
109
109
|
|
|
110
|
-
//# sourceMappingURL=presets-
|
|
110
|
+
//# sourceMappingURL=presets-DNuF7aK5.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"presets-
|
|
1
|
+
{"version":3,"file":"presets-DNuF7aK5.js","names":[],"sources":["../src/presets/basic.ts","../src/presets/index.ts"],"sourcesContent":["import { definePreset } from '.'\nimport { edit, listFiles, multiEdit, readFile, shell, shellKill, 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, 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 // `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 tools: { ...basicTools, spawn: createSpawnTool({ persist: true }) },\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;CAAW;CAAW;CAAM;AAAU;AAE9F,IAAA,gBAAe,aAAa;CAC1B,MAAM;CACN,QAAQ;CAOR,OAAO;EAAE,GAAG;EAAY,OAAO,gBAAgB,EAAE,SAAS,KAAK,CAAC;CAAE;AACpE,CAAC;;;;;;ACOD,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
1
|
import { n as AgentHookMap } from "./agent-CYPEZ9i3.js";
|
|
2
|
-
import { a as basicTools, i as _default, n as composePresets, r as definePreset, t as Preset } from "./index-
|
|
2
|
+
import { a as basicTools, i as _default, n as composePresets, r as definePreset, t as Preset } from "./index-DutpkJJ7.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-DNuF7aK5.js";
|
|
2
2
|
export { basic_default as basic, basicTools, composePresets, definePreset };
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { r as utf8ByteLength } from "./utils-ngQzYzZD.js";
|
|
2
|
-
import {
|
|
2
|
+
import { i as buildContextBreakdown, n as stripLineNumberPrefixes, r as styleReplacementForVia, t as resolveOldString } from "./edit-utils-BkPqw6WE.js";
|
|
3
|
+
import { a as formatTaskStatus, i as formatDuration, o as formatTaskSummary, s as previewLine } from "./format-BNOXpl-1.js";
|
|
3
4
|
import { a as createCursorOAuthProvider, c as arcee, f as ANTHROPIC_EXTRA_MODELS, l as anthropic, n as openai, o as generatePkce, p as FAST_MODE_OPTIONS, r as local, s as cerebras, t as openrouter } from "./providers-NAYlDy0H.js";
|
|
4
5
|
import { i as AgentProviderError, l as errorMessage, n as AgentBudgetExceededError, o as AgentToolPairingError, p as toTypedError, t as AgentAbortedError } from "./errors-B-GeaKTX.js";
|
|
5
6
|
import { E as appendStaticSection, a as detectTurnInterruption, c as filterUnresolvedToolUses, k as renderSystemForWire, n as SYNTHETIC_TOOL_RESULT_PLACEHOLDER, o as ensureEndsWithUserMessage, s as ensureToolResultPairing } from "./messages-CWz0yRAE.js";
|
|
@@ -8285,4 +8286,4 @@ const writeFile$1 = {
|
|
|
8285
8286
|
//#endregion
|
|
8286
8287
|
export { resolvePersistDir as A, credKeyOf as B, validateToolArgs as C, cleanupPersistedSession as D, buildPersistedStub as E, resolveReadStateMap as F, localDescriptor as G, enabledModelOptions as H, BUILTIN_PROVIDERS as I, modelsForDescriptor as J, modelOptionsFor as K, OUTPUT_RESERVE_TOKENS as L, getReadState as M, hashContent as N, maybePersistToolResult as O, readStateKey as P, restoreModelOptions as Q, anthropicDescriptor as R, TOOL_USE_SKIPPED_MESSAGE as S, PERSISTENCE_PREVIEW_BYTES as T, getContextWindow as U, effectiveContextWindow as V, getModelInfo as W, openrouterDescriptor as X, openaiDescriptor as Y, piIdOf as Z, createShellTool as _, multiEdit as a, SHELL_CASCADE_CANCEL_MESSAGE as b, grep as c, createAgent as d, createToolSearchTool as f, createSkillsReadTool as g, alwaysQuote as h, readFile$1 as i, resolveTasksDir as j, resolveMcpWarningsDir as k, glob$1 as l, createSkillsRunScriptTool as m, createSpawnTool as n, listFiles as o, createSkillsUseTool as p, modelSupportsReasoning as q, shellKill as r, createInteractionTool as s, writeFile$1 as t, edit as u, shell as v, PERSISTED_STUB_PREFIX as w, TOOL_USE_CANCELLED_MESSAGE as x, INTERRUPT_MESSAGE_FOR_TOOL_USE as y, cerebrasDescriptor as z };
|
|
8287
8288
|
|
|
8288
|
-
//# sourceMappingURL=tools-
|
|
8289
|
+
//# sourceMappingURL=tools-Cf5IsJEu.js.map
|