zidane 5.10.13 → 5.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/README.md +26 -0
  2. package/dist/{agent-BHkvYIH9.d.ts → agent-B7ilLoh8.d.ts} +63 -4
  3. package/dist/agent-B7ilLoh8.d.ts.map +1 -0
  4. package/dist/chat/pure.d.ts +3 -3
  5. package/dist/chat.d.ts +6 -6
  6. package/dist/chat.js +2 -2
  7. package/dist/contexts/docker.d.ts +1 -1
  8. package/dist/contexts/docker.d.ts.map +1 -1
  9. package/dist/contexts/docker.js +53 -14
  10. package/dist/contexts/docker.js.map +1 -1
  11. package/dist/contexts/e2b.d.ts +168 -0
  12. package/dist/contexts/e2b.d.ts.map +1 -0
  13. package/dist/contexts/e2b.js +261 -0
  14. package/dist/contexts/e2b.js.map +1 -0
  15. package/dist/{contexts-BJVgG0LY.js → contexts-DglWSzmR.js} +59 -9
  16. package/dist/contexts-DglWSzmR.js.map +1 -0
  17. package/dist/contexts.d.ts +3 -3
  18. package/dist/contexts.js +1 -1
  19. package/dist/eval.d.ts +1 -1
  20. package/dist/eval.js +4 -4
  21. package/dist/{headless-CPaunZsU.js → headless-CYHU4ZB-.js} +6 -6
  22. package/dist/{headless-CPaunZsU.js.map → headless-CYHU4ZB-.js.map} +1 -1
  23. package/dist/headless.d.ts +1 -1
  24. package/dist/headless.js +1 -1
  25. package/dist/{index-C4aT2kO_.d.ts → index-C-zEbeFI.d.ts} +13 -101
  26. package/dist/index-C-zEbeFI.d.ts.map +1 -0
  27. package/dist/{index-C_t8tW_X.d.ts → index-CrMb8jCE.d.ts} +2 -2
  28. package/dist/{index-C_t8tW_X.d.ts.map → index-CrMb8jCE.d.ts.map} +1 -1
  29. package/dist/{index-BIo67xLV.d.ts → index-CsRdmSh6.d.ts} +10 -3
  30. package/dist/index-CsRdmSh6.d.ts.map +1 -0
  31. package/dist/index.d.ts +7 -6
  32. package/dist/index.js +11 -10
  33. package/dist/index.js.map +1 -1
  34. package/dist/{interpolate-Dy7Lunvg.js → interpolate-CTfr0GdR.js} +19 -1
  35. package/dist/{interpolate-Dy7Lunvg.js.map → interpolate-CTfr0GdR.js.map} +1 -1
  36. package/dist/logger-Bd4Wn9Hc.d.ts +102 -0
  37. package/dist/logger-Bd4Wn9Hc.d.ts.map +1 -0
  38. package/dist/logger-Ktm-lj1s.js +300 -0
  39. package/dist/logger-Ktm-lj1s.js.map +1 -0
  40. package/dist/{login-0jP1pnSJ.js → login-DVLJzf-S.js} +4 -301
  41. package/dist/login-DVLJzf-S.js.map +1 -0
  42. package/dist/{mcp-tevNihk_.js → mcp-DPneQbw2.js} +21 -8
  43. package/dist/mcp-DPneQbw2.js.map +1 -0
  44. package/dist/mcp.d.ts +1 -1
  45. package/dist/mcp.js +1 -1
  46. package/dist/{messages-C_1AmSpk.js → messages-DJ7xdoUg.js} +5 -1
  47. package/dist/messages-DJ7xdoUg.js.map +1 -0
  48. package/dist/output/stream-json.d.ts +2 -2
  49. package/dist/output/stream-json.js +1 -1
  50. package/dist/output/terminal.d.ts +2 -2
  51. package/dist/output/terminal.js +1 -0
  52. package/dist/output/terminal.js.map +1 -1
  53. package/dist/{presets-Cm2BPJaU.js → presets-Q0yUDRA6.js} +2 -2
  54. package/dist/{presets-Cm2BPJaU.js.map → presets-Q0yUDRA6.js.map} +1 -1
  55. package/dist/presets.d.ts +2 -2
  56. package/dist/presets.js +1 -1
  57. package/dist/{providers-BGBB18zz.js → providers-BPdi7cUU.js} +73 -11
  58. package/dist/providers-BPdi7cUU.js.map +1 -0
  59. package/dist/providers.d.ts +1 -1
  60. package/dist/providers.js +2 -2
  61. package/dist/restate.d.ts +2 -2
  62. package/dist/restate.js +4 -1
  63. package/dist/restate.js.map +1 -1
  64. package/dist/session/sqlite.d.ts +1 -1
  65. package/dist/session/sqlite.d.ts.map +1 -1
  66. package/dist/session/sqlite.js +36 -4
  67. package/dist/session/sqlite.js.map +1 -1
  68. package/dist/{session-CtAWwwkn.js → session-D4GckETs.js} +69 -21
  69. package/dist/session-D4GckETs.js.map +1 -0
  70. package/dist/session.d.ts +2 -2
  71. package/dist/session.js +3 -3
  72. package/dist/shell-quote-BmnhZmdM.js +33 -0
  73. package/dist/shell-quote-BmnhZmdM.js.map +1 -0
  74. package/dist/skills.d.ts +3 -3
  75. package/dist/skills.js +1 -1
  76. package/dist/skills.js.map +1 -1
  77. package/dist/{tool-formatters-D_fX6FGl.d.ts → tool-formatters-DXO8rGut.d.ts} +2 -2
  78. package/dist/{tool-formatters-D_fX6FGl.d.ts.map → tool-formatters-DXO8rGut.d.ts.map} +1 -1
  79. package/dist/tools/fetch-url.d.ts +1 -1
  80. package/dist/tools/web-search.d.ts +1 -1
  81. package/dist/{tools-NxnEmzYg.js → tools-DqNkGwfd.js} +80 -73
  82. package/dist/tools-DqNkGwfd.js.map +1 -0
  83. package/dist/tools.d.ts +2 -2
  84. package/dist/tools.js +1 -1
  85. package/dist/{transcript-anchors-B_c7gWot.js → transcript-anchors-C3tVPR5n.js} +8 -8
  86. package/dist/{transcript-anchors-B_c7gWot.js.map → transcript-anchors-C3tVPR5n.js.map} +1 -1
  87. package/dist/{transcript-anchors-DA6XawEU.d.ts → transcript-anchors-p-ZsBSEF.d.ts} +10 -4
  88. package/dist/transcript-anchors-p-ZsBSEF.d.ts.map +1 -0
  89. package/dist/tui.d.ts +3 -3
  90. package/dist/tui.js +151 -41
  91. package/dist/tui.js.map +1 -1
  92. package/dist/{turn-operations-CCl7rpbT.d.ts → turn-operations-DD1D5VFx.d.ts} +3 -3
  93. package/dist/{turn-operations-CCl7rpbT.d.ts.map → turn-operations-DD1D5VFx.d.ts.map} +1 -1
  94. package/dist/{types-BibzMDjX.d.ts → types-B39tBba1.d.ts} +69 -2
  95. package/dist/types-B39tBba1.d.ts.map +1 -0
  96. package/dist/types.d.ts +5 -5
  97. package/docs/EXECUTION_CONTEXT.md +257 -0
  98. package/docs/RUN_IN_BACKGROUND.md +8 -0
  99. package/package.json +57 -24
  100. package/dist/agent-BHkvYIH9.d.ts.map +0 -1
  101. package/dist/contexts-BJVgG0LY.js.map +0 -1
  102. package/dist/index-BIo67xLV.d.ts.map +0 -1
  103. package/dist/index-C4aT2kO_.d.ts.map +0 -1
  104. package/dist/login-0jP1pnSJ.js.map +0 -1
  105. package/dist/mcp-tevNihk_.js.map +0 -1
  106. package/dist/messages-C_1AmSpk.js.map +0 -1
  107. package/dist/providers-BGBB18zz.js.map +0 -1
  108. package/dist/session-CtAWwwkn.js.map +0 -1
  109. package/dist/tools-NxnEmzYg.js.map +0 -1
  110. package/dist/transcript-anchors-DA6XawEU.d.ts.map +0 -1
  111. package/dist/types-BibzMDjX.d.ts.map +0 -1
@@ -0,0 +1,300 @@
1
+ //#region src/logger.ts
2
+ /**
3
+ * Build a Logger from a sink. Stateless and cheap; create one per agent
4
+ * (or per app) and use `.with()` to attach correlation ids per-call.
5
+ */
6
+ function createLogger(sink, baseAttributes = {}) {
7
+ function emit(level, message, attrs) {
8
+ try {
9
+ sink.emit({
10
+ level,
11
+ timestamp: Date.now(),
12
+ message,
13
+ attrs: attrs ? {
14
+ ...baseAttributes,
15
+ ...attrs
16
+ } : { ...baseAttributes }
17
+ });
18
+ } catch {}
19
+ }
20
+ return {
21
+ debug: (m, a) => emit("debug", m, a),
22
+ info: (m, a) => emit("info", m, a),
23
+ warn: (m, a) => emit("warn", m, a),
24
+ error: (m, a) => emit("error", m, a),
25
+ with: (extra) => createLogger(sink, {
26
+ ...baseAttributes,
27
+ ...extra
28
+ }),
29
+ baseAttributes
30
+ };
31
+ }
32
+ const LEVEL_ORDER = {
33
+ debug: 0,
34
+ info: 1,
35
+ warn: 2,
36
+ error: 3
37
+ };
38
+ /**
39
+ * Human-readable terminal sink. Renders each record as
40
+ * `<ISO timestamp> <LEVEL> <message> <attrs as kv pairs>`.
41
+ *
42
+ * Honors `process.stderr` by default so log lines don't interleave with
43
+ * the agent's stdout-bound output (chat responses, JSON results).
44
+ */
45
+ function consoleSink(options = {}) {
46
+ const min = LEVEL_ORDER[options.minLevel ?? "info"];
47
+ const stream = options.stream ?? process.stderr;
48
+ return { emit(record) {
49
+ if (LEVEL_ORDER[record.level] < min) return;
50
+ const ts = new Date(record.timestamp).toISOString();
51
+ const kv = Object.entries(record.attrs).filter(([, v]) => v !== void 0).map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`).join(" ");
52
+ stream.write(`${ts} ${record.level.toUpperCase().padEnd(5)} ${record.message}${kv ? ` ${kv}` : ""}\n`);
53
+ } };
54
+ }
55
+ /**
56
+ * One-JSON-object-per-line sink. Suitable for piping into log aggregators
57
+ * (Datadog Agent, Fluent Bit, Loki, Vector) that expect JSONL.
58
+ */
59
+ function jsonSink(options = {}) {
60
+ const min = LEVEL_ORDER[options.minLevel ?? "info"];
61
+ const stream = options.stream ?? process.stderr;
62
+ return { emit(record) {
63
+ if (LEVEL_ORDER[record.level] < min) return;
64
+ try {
65
+ stream.write(`${JSON.stringify(record)}\n`);
66
+ } catch {}
67
+ } };
68
+ }
69
+ /**
70
+ * Install a bundle of hook handlers that emit a structured line per
71
+ * relevant lifecycle event, automatically attaching correlation ids
72
+ * (`runId`, `turnId`, `callId`, `childId`, `depth`, `agentName`).
73
+ *
74
+ * @example
75
+ * ```ts
76
+ * const logger = createLogger(consoleSink({ minLevel: 'debug' }), { service: 'tui' })
77
+ * const lh = createLoggingHooks({ logger })
78
+ * const uninstall = lh.install(agent.hooks)
79
+ * try { await agent.run({ prompt }) }
80
+ * finally { uninstall() }
81
+ * ```
82
+ */
83
+ function createLoggingHooks(options) {
84
+ const root = options.logger;
85
+ const includeLifecycle = options.includeLifecycle ?? true;
86
+ const minLevel = LEVEL_ORDER[options.level ?? "info"];
87
+ /**
88
+ * Wrap a Logger so emissions below `minLevel` are dropped before they
89
+ * hit the sink. Lets us gate harness chatter without forcing every
90
+ * `LogSink` to re-implement level filtering. Preserves `.with()`
91
+ * composition (children inherit the filter).
92
+ */
93
+ function gateLevel(logger) {
94
+ const skip = (level) => LEVEL_ORDER[level] < minLevel;
95
+ const wrap = (l) => ({
96
+ debug: (m, a) => {
97
+ if (!skip("debug")) l.debug(m, a);
98
+ },
99
+ info: (m, a) => {
100
+ if (!skip("info")) l.info(m, a);
101
+ },
102
+ warn: (m, a) => {
103
+ if (!skip("warn")) l.warn(m, a);
104
+ },
105
+ error: (m, a) => {
106
+ if (!skip("error")) l.error(m, a);
107
+ },
108
+ with: (extra) => wrap(l.with(extra)),
109
+ baseAttributes: l.baseAttributes
110
+ });
111
+ return wrap(logger);
112
+ }
113
+ return { install(hooks) {
114
+ const unregisters = [];
115
+ const gatedRoot = gateLevel(root);
116
+ let runLogger = gatedRoot;
117
+ let turnLogger = gatedRoot;
118
+ unregisters.push(hooks.hook("agent:start", (ctx) => {
119
+ runLogger = gatedRoot.with({
120
+ runId: ctx.runId,
121
+ ...ctx.parentRunId ? { parentRunId: ctx.parentRunId } : {},
122
+ depth: ctx.depth,
123
+ ...ctx.agentName ? { agentName: ctx.agentName } : {}
124
+ });
125
+ turnLogger = runLogger;
126
+ if (includeLifecycle) runLogger.debug("agent run started");
127
+ }));
128
+ unregisters.push(hooks.hook("agent:done", (stats) => {
129
+ runLogger.info("agent run completed", {
130
+ turns: stats.turns,
131
+ totalIn: stats.totalIn,
132
+ totalOut: stats.totalOut,
133
+ ...typeof stats.cost === "number" ? { cost: stats.cost } : {},
134
+ elapsedMs: stats.elapsed,
135
+ ...typeof stats.timeTillFirstTokenMs === "number" ? { ttftMs: stats.timeTillFirstTokenMs } : {}
136
+ });
137
+ }));
138
+ unregisters.push(hooks.hook("agent:abort", () => {
139
+ runLogger.warn("agent run aborted");
140
+ }));
141
+ unregisters.push(hooks.hook("turn:before", (ctx) => {
142
+ turnLogger = runLogger.with({
143
+ turnId: ctx.turnId,
144
+ turn: ctx.turn
145
+ });
146
+ if (includeLifecycle) turnLogger.debug("turn started");
147
+ }));
148
+ unregisters.push(hooks.hook("turn:after", (ctx) => {
149
+ turnLogger.debug("turn ended", {
150
+ inputTokens: ctx.usage.input,
151
+ outputTokens: ctx.usage.output,
152
+ ...ctx.usage.finishReason ? { finishReason: ctx.usage.finishReason } : {},
153
+ ...ctx.usage.modelId ? { modelId: ctx.usage.modelId } : {},
154
+ ...typeof ctx.usage.timeToFirstTokenMs === "number" ? { ttftMs: ctx.usage.timeToFirstTokenMs } : {}
155
+ });
156
+ }));
157
+ unregisters.push(hooks.hook("stream:error", (ctx) => {
158
+ turnLogger.error("stream error", {
159
+ message: ctx.err instanceof Error ? ctx.err.message : String(ctx.err),
160
+ ...ctx.statusCode !== void 0 ? { statusCode: ctx.statusCode } : {},
161
+ ...ctx.requestId !== void 0 ? { requestId: ctx.requestId } : {}
162
+ });
163
+ }));
164
+ unregisters.push(hooks.hook("tool:before", (ctx) => {
165
+ if (!includeLifecycle) return;
166
+ turnLogger.debug("tool started", {
167
+ toolName: ctx.name,
168
+ displayName: ctx.displayName,
169
+ callId: ctx.callId
170
+ });
171
+ }));
172
+ unregisters.push(hooks.hook("tool:after", (ctx) => {
173
+ if (!includeLifecycle) return;
174
+ turnLogger.debug("tool ended", {
175
+ toolName: ctx.name,
176
+ callId: ctx.callId,
177
+ outputBytes: ctx.outputBytes
178
+ });
179
+ }));
180
+ unregisters.push(hooks.hook("tool:error", (ctx) => {
181
+ turnLogger.error("tool error", {
182
+ toolName: ctx.name,
183
+ callId: ctx.callId,
184
+ message: ctx.error.message
185
+ });
186
+ }));
187
+ unregisters.push(hooks.hook("tool:dispatched", (ctx) => {
188
+ const isAnomaly = ctx.outcome === "gate-block" || ctx.outcome === "unknown" || ctx.outcome === "invalid-input";
189
+ if (!isAnomaly && !includeLifecycle) return;
190
+ turnLogger[isAnomaly ? "warn" : "debug"]("tool dispatched", {
191
+ toolName: ctx.name,
192
+ callId: ctx.callId,
193
+ outcome: ctx.outcome,
194
+ ...ctx.reason ? { reason: ctx.reason } : {}
195
+ });
196
+ }));
197
+ unregisters.push(hooks.hook("validation:reject", (ctx) => {
198
+ turnLogger.warn("tool input rejected", {
199
+ toolName: ctx.name,
200
+ callId: ctx.callId,
201
+ reason: ctx.reason
202
+ });
203
+ }));
204
+ unregisters.push(hooks.hook("budget:exceeded", (ctx) => {
205
+ turnLogger.warn("byte budget exceeded", {
206
+ bytes: ctx.bytes,
207
+ budget: ctx.budget
208
+ });
209
+ }));
210
+ unregisters.push(hooks.hook("tool-budget:exceeded", (ctx) => {
211
+ turnLogger.warn("tool budget exceeded", {
212
+ toolName: ctx.tool,
213
+ count: ctx.count,
214
+ max: ctx.max,
215
+ mode: ctx.mode
216
+ });
217
+ }));
218
+ unregisters.push(hooks.hook("mcp:bootstrap:end", (ctx) => {
219
+ if (ctx.ok) {
220
+ if (includeLifecycle) runLogger.debug("mcp bootstrap ok", {
221
+ server: ctx.name,
222
+ transport: ctx.transport,
223
+ durationMs: ctx.durationMs,
224
+ toolCount: ctx.toolCount,
225
+ ...ctx.lazy ? { lazy: true } : {},
226
+ ...ctx.cached ? { cached: true } : {}
227
+ });
228
+ } else runLogger.warn("mcp bootstrap failed", {
229
+ server: ctx.name,
230
+ transport: ctx.transport,
231
+ durationMs: ctx.durationMs,
232
+ message: ctx.error.message
233
+ });
234
+ }));
235
+ unregisters.push(hooks.hook("mcp:error", (ctx) => {
236
+ runLogger.error("mcp error", {
237
+ server: ctx.name,
238
+ message: ctx.error.message
239
+ });
240
+ }));
241
+ unregisters.push(hooks.hook("mcp:warn", (ctx) => {
242
+ runLogger.warn("mcp warn", {
243
+ server: ctx.name,
244
+ message: ctx.message
245
+ });
246
+ }));
247
+ unregisters.push(hooks.hook("mcp:auth:required", (ctx) => {
248
+ runLogger.warn("mcp auth required", {
249
+ server: ctx.name,
250
+ transport: ctx.transport,
251
+ reason: ctx.reason
252
+ });
253
+ }));
254
+ unregisters.push(hooks.hook("mcp:tool:error", (ctx) => {
255
+ turnLogger.error("mcp tool error", {
256
+ server: ctx.server,
257
+ tool: ctx.displayName,
258
+ callId: ctx.callId,
259
+ message: ctx.error.message
260
+ });
261
+ }));
262
+ unregisters.push(hooks.hook("spawn:before", (ctx) => {
263
+ if (!includeLifecycle) return;
264
+ runLogger.debug("spawn started", {
265
+ childId: ctx.id,
266
+ depth: ctx.depth
267
+ });
268
+ }));
269
+ unregisters.push(hooks.hook("spawn:complete", (ctx) => {
270
+ runLogger.info("spawn completed", {
271
+ childId: ctx.id,
272
+ ...ctx.depth ? { depth: ctx.depth } : {},
273
+ status: ctx.status ?? "completed",
274
+ turns: ctx.stats.turns,
275
+ totalIn: ctx.stats.totalIn,
276
+ totalOut: ctx.stats.totalOut,
277
+ ...typeof ctx.stats.cost === "number" ? { cost: ctx.stats.cost } : {}
278
+ });
279
+ }));
280
+ unregisters.push(hooks.hook("spawn:error", (ctx) => {
281
+ runLogger.error("spawn error", {
282
+ childId: ctx.id,
283
+ ...ctx.depth ? { depth: ctx.depth } : {},
284
+ message: ctx.error.message
285
+ });
286
+ }));
287
+ let disposed = false;
288
+ return function uninstall() {
289
+ if (disposed) return;
290
+ disposed = true;
291
+ for (const un of unregisters) try {
292
+ un();
293
+ } catch {}
294
+ };
295
+ } };
296
+ }
297
+ //#endregion
298
+ export { jsonSink as i, createLogger as n, createLoggingHooks as r, consoleSink as t };
299
+
300
+ //# sourceMappingURL=logger-Ktm-lj1s.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger-Ktm-lj1s.js","names":[],"sources":["../src/logger.ts"],"sourcesContent":["/**\n * Structured logging primitive with auto-correlation.\n *\n * Every consumer of the harness used to roll its own logger; the TUI has\n * one, downstream apps have theirs, observability backends each want a\n * slightly different shape. This module ships the smallest reasonable\n * shared surface:\n *\n * - {@link Logger} — minimal level-tagged interface (`debug` / `info` /\n * `warn` / `error`) plus a `with(...)` method that returns a child\n * logger carrying baseline attributes (`runId`, `turnId`, `callId`,\n * `childId`, `depth`, anything you want).\n * - {@link createLogger} — builds a Logger from a {@link LogSink}.\n * - {@link consoleSink} / {@link jsonSink} — built-in sinks that cover\n * the common cases (human-readable to a terminal vs. one JSON object\n * per line to a log aggregator).\n * - {@link createLoggingHooks} — installs Logger-attached hook handlers\n * on an agent so every lifecycle event lands on the sink with the\n * right correlation ids already stamped in.\n *\n * Hosts that already own a logger (pino, winston, structlog binding,\n * platform-native) plug it in via a custom {@link LogSink} — the helper\n * itself does no I/O.\n */\n\nimport type { Hookable } from 'hookable'\nimport type { AgentHooks } from './agent'\n\n// ---------------------------------------------------------------------------\n// Core types\n// ---------------------------------------------------------------------------\n\nexport type LogLevel = 'debug' | 'info' | 'warn' | 'error'\n\nexport interface LogRecord {\n level: LogLevel\n /** Unix ms — set by `Logger` at emit time. */\n timestamp: number\n /** Free-form message. Sinks render this as the human-facing line. */\n message: string\n /** Structured fields. Correlation ids land here automatically. */\n attrs: Record<string, unknown>\n}\n\nexport interface LogSink {\n emit: (record: LogRecord) => void\n}\n\nexport interface Logger {\n debug: (message: string, attrs?: Record<string, unknown>) => void\n info: (message: string, attrs?: Record<string, unknown>) => void\n warn: (message: string, attrs?: Record<string, unknown>) => void\n error: (message: string, attrs?: Record<string, unknown>) => void\n /**\n * Returns a child logger that prepends the given attributes onto every\n * subsequent emit. Equivalent to `pino.child` / `winston.child`. The\n * parent and child share the same sink — children are zero-cost.\n */\n with: (extra: Record<string, unknown>) => Logger\n /**\n * Inspectable baseline attributes — handy for tests and for hook\n * handlers that want to clone-with-extra without recursing.\n */\n readonly baseAttributes: Readonly<Record<string, unknown>>\n}\n\n// ---------------------------------------------------------------------------\n// createLogger\n// ---------------------------------------------------------------------------\n\n/**\n * Build a Logger from a sink. Stateless and cheap; create one per agent\n * (or per app) and use `.with()` to attach correlation ids per-call.\n */\nexport function createLogger(\n sink: LogSink,\n baseAttributes: Readonly<Record<string, unknown>> = {},\n): Logger {\n function emit(level: LogLevel, message: string, attrs?: Record<string, unknown>): void {\n try {\n sink.emit({\n level,\n timestamp: Date.now(),\n message,\n attrs: attrs ? { ...baseAttributes, ...attrs } : { ...baseAttributes },\n })\n }\n catch {\n // Sinks should never crash the run.\n }\n }\n\n return {\n debug: (m, a) => emit('debug', m, a),\n info: (m, a) => emit('info', m, a),\n warn: (m, a) => emit('warn', m, a),\n error: (m, a) => emit('error', m, a),\n with: extra => createLogger(sink, { ...baseAttributes, ...extra }),\n baseAttributes,\n }\n}\n\n// ---------------------------------------------------------------------------\n// Built-in sinks\n// ---------------------------------------------------------------------------\n\nexport interface ConsoleSinkOptions {\n /**\n * Minimum level to emit. Defaults to `'info'` — `debug` is dropped so\n * the harness's lifecycle logging is not noisy by default. Set to\n * `'debug'` to see every event.\n */\n minLevel?: LogLevel\n /** Custom output stream. Defaults to `process.stderr` so logs don't pollute stdout. */\n stream?: { write: (chunk: string) => void }\n}\n\nconst LEVEL_ORDER: Record<LogLevel, number> = {\n debug: 0,\n info: 1,\n warn: 2,\n error: 3,\n}\n\n/**\n * Human-readable terminal sink. Renders each record as\n * `<ISO timestamp> <LEVEL> <message> <attrs as kv pairs>`.\n *\n * Honors `process.stderr` by default so log lines don't interleave with\n * the agent's stdout-bound output (chat responses, JSON results).\n */\nexport function consoleSink(options: ConsoleSinkOptions = {}): LogSink {\n const min = LEVEL_ORDER[options.minLevel ?? 'info']\n const stream = options.stream ?? process.stderr\n return {\n emit(record) {\n if (LEVEL_ORDER[record.level] < min)\n return\n const ts = new Date(record.timestamp).toISOString()\n const kv = Object.entries(record.attrs)\n .filter(([, v]) => v !== undefined)\n .map(([k, v]) => `${k}=${typeof v === 'string' ? v : JSON.stringify(v)}`)\n .join(' ')\n stream.write(`${ts} ${record.level.toUpperCase().padEnd(5)} ${record.message}${kv ? ` ${kv}` : ''}\\n`)\n },\n }\n}\n\n/**\n * One-JSON-object-per-line sink. Suitable for piping into log aggregators\n * (Datadog Agent, Fluent Bit, Loki, Vector) that expect JSONL.\n */\nexport function jsonSink(options: ConsoleSinkOptions = {}): LogSink {\n const min = LEVEL_ORDER[options.minLevel ?? 'info']\n const stream = options.stream ?? process.stderr\n return {\n emit(record) {\n if (LEVEL_ORDER[record.level] < min)\n return\n try {\n stream.write(`${JSON.stringify(record)}\\n`)\n }\n catch {\n // Non-serializable attr (cycle, BigInt, etc.). Skip rather than throw.\n }\n },\n }\n}\n\n// ---------------------------------------------------------------------------\n// createLoggingHooks\n// ---------------------------------------------------------------------------\n\nexport interface LoggingHooksOptions {\n logger: Logger\n /**\n * Minimum interesting level for harness-emitted lines. Default `'info'`.\n * Set to `'debug'` to see every tool dispatch / stream event. Set to\n * `'warn'` to mute the chatty ones and only see failures + budgets.\n */\n level?: LogLevel\n /**\n * When true (default), lifecycle events (`agent:start`, `turn:before`,\n * `tool:before`, `mcp:bootstrap:start`) emit at `debug` level so they\n * stay quiet by default. Set false to mute them entirely regardless of\n * the configured minimum level — useful when piping into a tracer\n * that already captures lifecycle.\n */\n includeLifecycle?: boolean\n}\n\nexport interface LoggingHookSet {\n install: (hooks: Hookable<AgentHooks>) => () => void\n}\n\n/**\n * Install a bundle of hook handlers that emit a structured line per\n * relevant lifecycle event, automatically attaching correlation ids\n * (`runId`, `turnId`, `callId`, `childId`, `depth`, `agentName`).\n *\n * @example\n * ```ts\n * const logger = createLogger(consoleSink({ minLevel: 'debug' }), { service: 'tui' })\n * const lh = createLoggingHooks({ logger })\n * const uninstall = lh.install(agent.hooks)\n * try { await agent.run({ prompt }) }\n * finally { uninstall() }\n * ```\n */\nexport function createLoggingHooks(options: LoggingHooksOptions): LoggingHookSet {\n const root = options.logger\n const includeLifecycle = options.includeLifecycle ?? true\n const minLevel = LEVEL_ORDER[options.level ?? 'info']\n\n /**\n * Wrap a Logger so emissions below `minLevel` are dropped before they\n * hit the sink. Lets us gate harness chatter without forcing every\n * `LogSink` to re-implement level filtering. Preserves `.with()`\n * composition (children inherit the filter).\n */\n function gateLevel(logger: Logger): Logger {\n const skip = (level: LogLevel): boolean => LEVEL_ORDER[level] < minLevel\n const wrap = (l: Logger): Logger => ({\n debug: (m, a) => {\n if (!skip('debug'))\n l.debug(m, a)\n },\n info: (m, a) => {\n if (!skip('info'))\n l.info(m, a)\n },\n warn: (m, a) => {\n if (!skip('warn'))\n l.warn(m, a)\n },\n error: (m, a) => {\n if (!skip('error'))\n l.error(m, a)\n },\n with: extra => wrap(l.with(extra)),\n baseAttributes: l.baseAttributes,\n })\n return wrap(logger)\n }\n\n return {\n install(hooks: Hookable<AgentHooks>): () => void {\n const unregisters: Array<() => void> = []\n // Per-install loggers, refreshed on `agent:start` / `turn:before`.\n // Scoped INSIDE install() so concurrent installs across different\n // agents don't share state — each call to `install()` gets its own\n // attribution state.\n const gatedRoot = gateLevel(root)\n let runLogger = gatedRoot\n let turnLogger = gatedRoot\n\n // ---- Agent lifecycle --------------------------------------------\n\n unregisters.push(hooks.hook('agent:start', (ctx) => {\n runLogger = gatedRoot.with({\n runId: ctx.runId,\n ...(ctx.parentRunId ? { parentRunId: ctx.parentRunId } : {}),\n depth: ctx.depth,\n ...(ctx.agentName ? { agentName: ctx.agentName } : {}),\n })\n turnLogger = runLogger\n if (includeLifecycle)\n runLogger.debug('agent run started')\n }))\n\n unregisters.push(hooks.hook('agent:done', (stats) => {\n runLogger.info('agent run completed', {\n turns: stats.turns,\n totalIn: stats.totalIn,\n totalOut: stats.totalOut,\n ...(typeof stats.cost === 'number' ? { cost: stats.cost } : {}),\n elapsedMs: stats.elapsed,\n ...(typeof stats.timeTillFirstTokenMs === 'number' ? { ttftMs: stats.timeTillFirstTokenMs } : {}),\n })\n }))\n\n unregisters.push(hooks.hook('agent:abort', () => {\n runLogger.warn('agent run aborted')\n }))\n\n // ---- Turn / stream ---------------------------------------------\n\n unregisters.push(hooks.hook('turn:before', (ctx) => {\n turnLogger = runLogger.with({ turnId: ctx.turnId, turn: ctx.turn })\n if (includeLifecycle)\n turnLogger.debug('turn started')\n }))\n\n unregisters.push(hooks.hook('turn:after', (ctx) => {\n turnLogger.debug('turn ended', {\n inputTokens: ctx.usage.input,\n outputTokens: ctx.usage.output,\n ...(ctx.usage.finishReason ? { finishReason: ctx.usage.finishReason } : {}),\n ...(ctx.usage.modelId ? { modelId: ctx.usage.modelId } : {}),\n ...(typeof ctx.usage.timeToFirstTokenMs === 'number' ? { ttftMs: ctx.usage.timeToFirstTokenMs } : {}),\n })\n }))\n\n unregisters.push(hooks.hook('stream:error', (ctx) => {\n turnLogger.error('stream error', {\n message: ctx.err instanceof Error ? ctx.err.message : String(ctx.err),\n ...(ctx.statusCode !== undefined ? { statusCode: ctx.statusCode } : {}),\n ...(ctx.requestId !== undefined ? { requestId: ctx.requestId } : {}),\n })\n }))\n\n // ---- Tool calls -------------------------------------------------\n\n unregisters.push(hooks.hook('tool:before', (ctx) => {\n if (!includeLifecycle)\n return\n turnLogger.debug('tool started', {\n toolName: ctx.name,\n displayName: ctx.displayName,\n callId: ctx.callId,\n })\n }))\n\n unregisters.push(hooks.hook('tool:after', (ctx) => {\n if (!includeLifecycle)\n return\n turnLogger.debug('tool ended', {\n toolName: ctx.name,\n callId: ctx.callId,\n outputBytes: ctx.outputBytes,\n })\n }))\n\n unregisters.push(hooks.hook('tool:error', (ctx) => {\n turnLogger.error('tool error', {\n toolName: ctx.name,\n callId: ctx.callId,\n message: ctx.error.message,\n })\n }))\n\n unregisters.push(hooks.hook('tool:dispatched', (ctx) => {\n // Successful + gate-substitute paths are routine — only log at\n // debug level. The three \"something refused / went wrong\" paths\n // (gate-block, unknown tool, invalid input) land at warn so they\n // surface in default-config dashboards without forcing debug.\n const isAnomaly = ctx.outcome === 'gate-block'\n || ctx.outcome === 'unknown'\n || ctx.outcome === 'invalid-input'\n if (!isAnomaly && !includeLifecycle)\n return\n const lvl: LogLevel = isAnomaly ? 'warn' : 'debug'\n turnLogger[lvl]('tool dispatched', {\n toolName: ctx.name,\n callId: ctx.callId,\n outcome: ctx.outcome,\n ...(ctx.reason ? { reason: ctx.reason } : {}),\n })\n }))\n\n unregisters.push(hooks.hook('validation:reject', (ctx) => {\n turnLogger.warn('tool input rejected', {\n toolName: ctx.name,\n callId: ctx.callId,\n reason: ctx.reason,\n })\n }))\n\n // ---- Budgets ----------------------------------------------------\n\n unregisters.push(hooks.hook('budget:exceeded', (ctx) => {\n turnLogger.warn('byte budget exceeded', {\n bytes: ctx.bytes,\n budget: ctx.budget,\n })\n }))\n\n unregisters.push(hooks.hook('tool-budget:exceeded', (ctx) => {\n turnLogger.warn('tool budget exceeded', {\n toolName: ctx.tool,\n count: ctx.count,\n max: ctx.max,\n mode: ctx.mode,\n })\n }))\n\n // ---- MCP --------------------------------------------------------\n\n unregisters.push(hooks.hook('mcp:bootstrap:end', (ctx) => {\n if (ctx.ok) {\n if (includeLifecycle) {\n runLogger.debug('mcp bootstrap ok', {\n server: ctx.name,\n transport: ctx.transport,\n durationMs: ctx.durationMs,\n toolCount: ctx.toolCount,\n ...(ctx.lazy ? { lazy: true } : {}),\n ...(ctx.cached ? { cached: true } : {}),\n })\n }\n }\n else {\n runLogger.warn('mcp bootstrap failed', {\n server: ctx.name,\n transport: ctx.transport,\n durationMs: ctx.durationMs,\n message: ctx.error.message,\n })\n }\n }))\n\n unregisters.push(hooks.hook('mcp:error', (ctx) => {\n runLogger.error('mcp error', {\n server: ctx.name,\n message: ctx.error.message,\n })\n }))\n\n unregisters.push(hooks.hook('mcp:warn', (ctx) => {\n runLogger.warn('mcp warn', {\n server: ctx.name,\n message: ctx.message,\n })\n }))\n\n unregisters.push(hooks.hook('mcp:auth:required', (ctx) => {\n runLogger.warn('mcp auth required', {\n server: ctx.name,\n transport: ctx.transport,\n reason: ctx.reason,\n })\n }))\n\n unregisters.push(hooks.hook('mcp:tool:error', (ctx) => {\n turnLogger.error('mcp tool error', {\n server: ctx.server,\n tool: ctx.displayName,\n callId: ctx.callId,\n message: ctx.error.message,\n })\n }))\n\n // ---- Spawn ------------------------------------------------------\n\n unregisters.push(hooks.hook('spawn:before', (ctx) => {\n if (!includeLifecycle)\n return\n runLogger.debug('spawn started', {\n childId: ctx.id,\n depth: ctx.depth,\n })\n }))\n\n unregisters.push(hooks.hook('spawn:complete', (ctx) => {\n runLogger.info('spawn completed', {\n childId: ctx.id,\n ...(ctx.depth ? { depth: ctx.depth } : {}),\n status: ctx.status ?? 'completed',\n turns: ctx.stats.turns,\n totalIn: ctx.stats.totalIn,\n totalOut: ctx.stats.totalOut,\n ...(typeof ctx.stats.cost === 'number' ? { cost: ctx.stats.cost } : {}),\n })\n }))\n\n unregisters.push(hooks.hook('spawn:error', (ctx) => {\n runLogger.error('spawn error', {\n childId: ctx.id,\n ...(ctx.depth ? { depth: ctx.depth } : {}),\n message: ctx.error.message,\n })\n }))\n\n // -----------------------------------------------------------------\n // Disposal\n // -----------------------------------------------------------------\n\n let disposed = false\n return function uninstall() {\n if (disposed)\n return\n disposed = true\n for (const un of unregisters) {\n try {\n un()\n }\n catch { /* ignore */ }\n }\n }\n },\n }\n}\n"],"mappings":"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"}
@@ -1,8 +1,8 @@
1
1
  import { n as estimateTokens, r as utf8ByteLength } from "./utils-ngQzYzZD.js";
2
- import { o as ensureEndsWithUserMessage, s as ensureToolResultPairing } from "./messages-C_1AmSpk.js";
2
+ import { o as ensureEndsWithUserMessage, s as ensureToolResultPairing } from "./messages-DJ7xdoUg.js";
3
3
  import { i as toolOutputByteLength } from "./types-BiobHM1D.js";
4
4
  import { t as getReadState } from "./read-state-BFqpQRc5.js";
5
- import { c as McpOAuthProvider, o as createTolerantClient, s as sseToJsonFetchIfNeeded } from "./mcp-tevNihk_.js";
5
+ import { c as McpOAuthProvider, o as createTolerantClient, s as sseToJsonFetchIfNeeded } from "./mcp-DPneQbw2.js";
6
6
  import { createServer } from "node:http";
7
7
  //#region src/compact/errors.ts
8
8
  /**
@@ -954,303 +954,6 @@ async function buildPostCompactAttachments(opts) {
954
954
  };
955
955
  }
956
956
  //#endregion
957
- //#region src/logger.ts
958
- /**
959
- * Build a Logger from a sink. Stateless and cheap; create one per agent
960
- * (or per app) and use `.with()` to attach correlation ids per-call.
961
- */
962
- function createLogger(sink, baseAttributes = {}) {
963
- function emit(level, message, attrs) {
964
- try {
965
- sink.emit({
966
- level,
967
- timestamp: Date.now(),
968
- message,
969
- attrs: attrs ? {
970
- ...baseAttributes,
971
- ...attrs
972
- } : { ...baseAttributes }
973
- });
974
- } catch {}
975
- }
976
- return {
977
- debug: (m, a) => emit("debug", m, a),
978
- info: (m, a) => emit("info", m, a),
979
- warn: (m, a) => emit("warn", m, a),
980
- error: (m, a) => emit("error", m, a),
981
- with: (extra) => createLogger(sink, {
982
- ...baseAttributes,
983
- ...extra
984
- }),
985
- baseAttributes
986
- };
987
- }
988
- const LEVEL_ORDER = {
989
- debug: 0,
990
- info: 1,
991
- warn: 2,
992
- error: 3
993
- };
994
- /**
995
- * Human-readable terminal sink. Renders each record as
996
- * `<ISO timestamp> <LEVEL> <message> <attrs as kv pairs>`.
997
- *
998
- * Honors `process.stderr` by default so log lines don't interleave with
999
- * the agent's stdout-bound output (chat responses, JSON results).
1000
- */
1001
- function consoleSink(options = {}) {
1002
- const min = LEVEL_ORDER[options.minLevel ?? "info"];
1003
- const stream = options.stream ?? process.stderr;
1004
- return { emit(record) {
1005
- if (LEVEL_ORDER[record.level] < min) return;
1006
- const ts = new Date(record.timestamp).toISOString();
1007
- const kv = Object.entries(record.attrs).filter(([, v]) => v !== void 0).map(([k, v]) => `${k}=${typeof v === "string" ? v : JSON.stringify(v)}`).join(" ");
1008
- stream.write(`${ts} ${record.level.toUpperCase().padEnd(5)} ${record.message}${kv ? ` ${kv}` : ""}\n`);
1009
- } };
1010
- }
1011
- /**
1012
- * One-JSON-object-per-line sink. Suitable for piping into log aggregators
1013
- * (Datadog Agent, Fluent Bit, Loki, Vector) that expect JSONL.
1014
- */
1015
- function jsonSink(options = {}) {
1016
- const min = LEVEL_ORDER[options.minLevel ?? "info"];
1017
- const stream = options.stream ?? process.stderr;
1018
- return { emit(record) {
1019
- if (LEVEL_ORDER[record.level] < min) return;
1020
- try {
1021
- stream.write(`${JSON.stringify(record)}\n`);
1022
- } catch {}
1023
- } };
1024
- }
1025
- /**
1026
- * Install a bundle of hook handlers that emit a structured line per
1027
- * relevant lifecycle event, automatically attaching correlation ids
1028
- * (`runId`, `turnId`, `callId`, `childId`, `depth`, `agentName`).
1029
- *
1030
- * @example
1031
- * ```ts
1032
- * const logger = createLogger(consoleSink({ minLevel: 'debug' }), { service: 'tui' })
1033
- * const lh = createLoggingHooks({ logger })
1034
- * const uninstall = lh.install(agent.hooks)
1035
- * try { await agent.run({ prompt }) }
1036
- * finally { uninstall() }
1037
- * ```
1038
- */
1039
- function createLoggingHooks(options) {
1040
- const root = options.logger;
1041
- const includeLifecycle = options.includeLifecycle ?? true;
1042
- const minLevel = LEVEL_ORDER[options.level ?? "info"];
1043
- /**
1044
- * Wrap a Logger so emissions below `minLevel` are dropped before they
1045
- * hit the sink. Lets us gate harness chatter without forcing every
1046
- * `LogSink` to re-implement level filtering. Preserves `.with()`
1047
- * composition (children inherit the filter).
1048
- */
1049
- function gateLevel(logger) {
1050
- const skip = (level) => LEVEL_ORDER[level] < minLevel;
1051
- const wrap = (l) => ({
1052
- debug: (m, a) => {
1053
- if (!skip("debug")) l.debug(m, a);
1054
- },
1055
- info: (m, a) => {
1056
- if (!skip("info")) l.info(m, a);
1057
- },
1058
- warn: (m, a) => {
1059
- if (!skip("warn")) l.warn(m, a);
1060
- },
1061
- error: (m, a) => {
1062
- if (!skip("error")) l.error(m, a);
1063
- },
1064
- with: (extra) => wrap(l.with(extra)),
1065
- baseAttributes: l.baseAttributes
1066
- });
1067
- return wrap(logger);
1068
- }
1069
- return { install(hooks) {
1070
- const unregisters = [];
1071
- const gatedRoot = gateLevel(root);
1072
- let runLogger = gatedRoot;
1073
- let turnLogger = gatedRoot;
1074
- unregisters.push(hooks.hook("agent:start", (ctx) => {
1075
- runLogger = gatedRoot.with({
1076
- runId: ctx.runId,
1077
- ...ctx.parentRunId ? { parentRunId: ctx.parentRunId } : {},
1078
- depth: ctx.depth,
1079
- ...ctx.agentName ? { agentName: ctx.agentName } : {}
1080
- });
1081
- turnLogger = runLogger;
1082
- if (includeLifecycle) runLogger.debug("agent run started");
1083
- }));
1084
- unregisters.push(hooks.hook("agent:done", (stats) => {
1085
- runLogger.info("agent run completed", {
1086
- turns: stats.turns,
1087
- totalIn: stats.totalIn,
1088
- totalOut: stats.totalOut,
1089
- ...typeof stats.cost === "number" ? { cost: stats.cost } : {},
1090
- elapsedMs: stats.elapsed,
1091
- ...typeof stats.timeTillFirstTokenMs === "number" ? { ttftMs: stats.timeTillFirstTokenMs } : {}
1092
- });
1093
- }));
1094
- unregisters.push(hooks.hook("agent:abort", () => {
1095
- runLogger.warn("agent run aborted");
1096
- }));
1097
- unregisters.push(hooks.hook("turn:before", (ctx) => {
1098
- turnLogger = runLogger.with({
1099
- turnId: ctx.turnId,
1100
- turn: ctx.turn
1101
- });
1102
- if (includeLifecycle) turnLogger.debug("turn started");
1103
- }));
1104
- unregisters.push(hooks.hook("turn:after", (ctx) => {
1105
- turnLogger.debug("turn ended", {
1106
- inputTokens: ctx.usage.input,
1107
- outputTokens: ctx.usage.output,
1108
- ...ctx.usage.finishReason ? { finishReason: ctx.usage.finishReason } : {},
1109
- ...ctx.usage.modelId ? { modelId: ctx.usage.modelId } : {},
1110
- ...typeof ctx.usage.timeToFirstTokenMs === "number" ? { ttftMs: ctx.usage.timeToFirstTokenMs } : {}
1111
- });
1112
- }));
1113
- unregisters.push(hooks.hook("stream:error", (ctx) => {
1114
- turnLogger.error("stream error", {
1115
- message: ctx.err instanceof Error ? ctx.err.message : String(ctx.err),
1116
- ...ctx.statusCode !== void 0 ? { statusCode: ctx.statusCode } : {},
1117
- ...ctx.requestId !== void 0 ? { requestId: ctx.requestId } : {}
1118
- });
1119
- }));
1120
- unregisters.push(hooks.hook("tool:before", (ctx) => {
1121
- if (!includeLifecycle) return;
1122
- turnLogger.debug("tool started", {
1123
- toolName: ctx.name,
1124
- displayName: ctx.displayName,
1125
- callId: ctx.callId
1126
- });
1127
- }));
1128
- unregisters.push(hooks.hook("tool:after", (ctx) => {
1129
- if (!includeLifecycle) return;
1130
- turnLogger.debug("tool ended", {
1131
- toolName: ctx.name,
1132
- callId: ctx.callId,
1133
- outputBytes: ctx.outputBytes
1134
- });
1135
- }));
1136
- unregisters.push(hooks.hook("tool:error", (ctx) => {
1137
- turnLogger.error("tool error", {
1138
- toolName: ctx.name,
1139
- callId: ctx.callId,
1140
- message: ctx.error.message
1141
- });
1142
- }));
1143
- unregisters.push(hooks.hook("tool:dispatched", (ctx) => {
1144
- const isAnomaly = ctx.outcome === "gate-block" || ctx.outcome === "unknown" || ctx.outcome === "invalid-input";
1145
- if (!isAnomaly && !includeLifecycle) return;
1146
- turnLogger[isAnomaly ? "warn" : "debug"]("tool dispatched", {
1147
- toolName: ctx.name,
1148
- callId: ctx.callId,
1149
- outcome: ctx.outcome,
1150
- ...ctx.reason ? { reason: ctx.reason } : {}
1151
- });
1152
- }));
1153
- unregisters.push(hooks.hook("validation:reject", (ctx) => {
1154
- turnLogger.warn("tool input rejected", {
1155
- toolName: ctx.name,
1156
- callId: ctx.callId,
1157
- reason: ctx.reason
1158
- });
1159
- }));
1160
- unregisters.push(hooks.hook("budget:exceeded", (ctx) => {
1161
- turnLogger.warn("byte budget exceeded", {
1162
- bytes: ctx.bytes,
1163
- budget: ctx.budget
1164
- });
1165
- }));
1166
- unregisters.push(hooks.hook("tool-budget:exceeded", (ctx) => {
1167
- turnLogger.warn("tool budget exceeded", {
1168
- toolName: ctx.tool,
1169
- count: ctx.count,
1170
- max: ctx.max,
1171
- mode: ctx.mode
1172
- });
1173
- }));
1174
- unregisters.push(hooks.hook("mcp:bootstrap:end", (ctx) => {
1175
- if (ctx.ok) {
1176
- if (includeLifecycle) runLogger.debug("mcp bootstrap ok", {
1177
- server: ctx.name,
1178
- transport: ctx.transport,
1179
- durationMs: ctx.durationMs,
1180
- toolCount: ctx.toolCount,
1181
- ...ctx.lazy ? { lazy: true } : {},
1182
- ...ctx.cached ? { cached: true } : {}
1183
- });
1184
- } else runLogger.warn("mcp bootstrap failed", {
1185
- server: ctx.name,
1186
- transport: ctx.transport,
1187
- durationMs: ctx.durationMs,
1188
- message: ctx.error.message
1189
- });
1190
- }));
1191
- unregisters.push(hooks.hook("mcp:error", (ctx) => {
1192
- runLogger.error("mcp error", {
1193
- server: ctx.name,
1194
- message: ctx.error.message
1195
- });
1196
- }));
1197
- unregisters.push(hooks.hook("mcp:warn", (ctx) => {
1198
- runLogger.warn("mcp warn", {
1199
- server: ctx.name,
1200
- message: ctx.message
1201
- });
1202
- }));
1203
- unregisters.push(hooks.hook("mcp:auth:required", (ctx) => {
1204
- runLogger.warn("mcp auth required", {
1205
- server: ctx.name,
1206
- transport: ctx.transport,
1207
- reason: ctx.reason
1208
- });
1209
- }));
1210
- unregisters.push(hooks.hook("mcp:tool:error", (ctx) => {
1211
- turnLogger.error("mcp tool error", {
1212
- server: ctx.server,
1213
- tool: ctx.displayName,
1214
- callId: ctx.callId,
1215
- message: ctx.error.message
1216
- });
1217
- }));
1218
- unregisters.push(hooks.hook("spawn:before", (ctx) => {
1219
- if (!includeLifecycle) return;
1220
- runLogger.debug("spawn started", {
1221
- childId: ctx.id,
1222
- depth: ctx.depth
1223
- });
1224
- }));
1225
- unregisters.push(hooks.hook("spawn:complete", (ctx) => {
1226
- runLogger.info("spawn completed", {
1227
- childId: ctx.id,
1228
- ...ctx.depth ? { depth: ctx.depth } : {},
1229
- status: ctx.status ?? "completed",
1230
- turns: ctx.stats.turns,
1231
- totalIn: ctx.stats.totalIn,
1232
- totalOut: ctx.stats.totalOut,
1233
- ...typeof ctx.stats.cost === "number" ? { cost: ctx.stats.cost } : {}
1234
- });
1235
- }));
1236
- unregisters.push(hooks.hook("spawn:error", (ctx) => {
1237
- runLogger.error("spawn error", {
1238
- childId: ctx.id,
1239
- ...ctx.depth ? { depth: ctx.depth } : {},
1240
- message: ctx.error.message
1241
- });
1242
- }));
1243
- let disposed = false;
1244
- return function uninstall() {
1245
- if (disposed) return;
1246
- disposed = true;
1247
- for (const un of unregisters) try {
1248
- un();
1249
- } catch {}
1250
- };
1251
- } };
1252
- }
1253
- //#endregion
1254
957
  //#region src/mcp/oauth-callback.ts
1255
958
  const DEFAULT_PATH = "/callback";
1256
959
  const DEFAULT_HOST = "127.0.0.1";
@@ -1513,6 +1216,6 @@ async function raceLoginCallback(handle, timeoutMs, signal) {
1513
1216
  }
1514
1217
  }
1515
1218
  //#endregion
1516
- export { stripImagesFromTurns as C, CompactPromptTooLongError as D, CompactInvalidInputError as E, sliceForCompaction as S, truncateHeadForPtlRetry as T, buildFullCompactPrompt as _, createLoggingHooks as a, ANCHOR_PREVIEW_MAX_CHARS as b, selectFilesFromReadState as c, compactConversation as d, BASE_INSTRUCTIONS as f, buildFromCompactPrompt as g, buildCompactPrompt as h, createLogger as i, selectFilesFromSession as l, TRAILER as m, startOAuthCallback as n, jsonSink as o, NO_TOOLS_PREAMBLE as p, consoleSink as r, buildPostCompactAttachments as s, loginMcpServer as t, selectRecentFiles as u, buildTailCompactPrompt as v, summaryToTurn as w, anchorPreviewFor as x, buildUpToCompactPrompt as y };
1219
+ export { CompactPromptTooLongError as C, CompactInvalidInputError as S, anchorPreviewFor as _, selectFilesFromSession as a, summaryToTurn as b, BASE_INSTRUCTIONS as c, buildCompactPrompt as d, buildFromCompactPrompt as f, ANCHOR_PREVIEW_MAX_CHARS as g, buildUpToCompactPrompt as h, selectFilesFromReadState as i, NO_TOOLS_PREAMBLE as l, buildTailCompactPrompt as m, startOAuthCallback as n, selectRecentFiles as o, buildFullCompactPrompt as p, buildPostCompactAttachments as r, compactConversation as s, loginMcpServer as t, TRAILER as u, sliceForCompaction as v, truncateHeadForPtlRetry as x, stripImagesFromTurns as y };
1517
1220
 
1518
- //# sourceMappingURL=login-0jP1pnSJ.js.map
1221
+ //# sourceMappingURL=login-DVLJzf-S.js.map