zidane 5.10.13 → 5.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -5
- package/dist/{agent-BHkvYIH9.d.ts → agent-D0W9yClt.d.ts} +114 -27
- package/dist/agent-D0W9yClt.d.ts.map +1 -0
- package/dist/chat/pure.d.ts +3 -3
- package/dist/chat.d.ts +7 -7
- package/dist/chat.js +2 -2
- package/dist/contexts/docker.d.ts +1 -1
- package/dist/contexts/docker.d.ts.map +1 -1
- package/dist/contexts/docker.js +53 -14
- package/dist/contexts/docker.js.map +1 -1
- package/dist/contexts/e2b.d.ts +168 -0
- package/dist/contexts/e2b.d.ts.map +1 -0
- package/dist/contexts/e2b.js +261 -0
- package/dist/contexts/e2b.js.map +1 -0
- package/dist/{contexts-BJVgG0LY.js → contexts-DglWSzmR.js} +59 -9
- package/dist/contexts-DglWSzmR.js.map +1 -0
- package/dist/contexts.d.ts +3 -3
- package/dist/contexts.js +1 -1
- package/dist/eval.d.ts +1 -1
- package/dist/eval.js +5 -5
- package/dist/eval.js.map +1 -1
- package/dist/{headless-CPaunZsU.js → headless-Bb5gU8AR.js} +6 -6
- package/dist/{headless-CPaunZsU.js.map → headless-Bb5gU8AR.js.map} +1 -1
- package/dist/headless.d.ts +1 -1
- package/dist/headless.js +1 -1
- package/dist/{index-C_t8tW_X.d.ts → index-CrMb8jCE.d.ts} +2 -2
- package/dist/{index-C_t8tW_X.d.ts.map → index-CrMb8jCE.d.ts.map} +1 -1
- package/dist/{index-BIo67xLV.d.ts → index-D60tX5XC.d.ts} +10 -3
- package/dist/index-D60tX5XC.d.ts.map +1 -0
- package/dist/{index-C4aT2kO_.d.ts → index-DZR99FD4.d.ts} +30 -111
- package/dist/index-DZR99FD4.d.ts.map +1 -0
- package/dist/index.d.ts +7 -6
- package/dist/index.js +11 -10
- package/dist/index.js.map +1 -1
- package/dist/{interpolate-Dy7Lunvg.js → interpolate-CTfr0GdR.js} +19 -1
- package/dist/{interpolate-Dy7Lunvg.js.map → interpolate-CTfr0GdR.js.map} +1 -1
- package/dist/logger-Ktm-lj1s.js +300 -0
- package/dist/logger-Ktm-lj1s.js.map +1 -0
- package/dist/logger-n4LsLISE.d.ts +102 -0
- package/dist/logger-n4LsLISE.d.ts.map +1 -0
- package/dist/{login-0jP1pnSJ.js → login-BHhOdTp9.js} +4 -301
- package/dist/login-BHhOdTp9.js.map +1 -0
- package/dist/{mcp-tevNihk_.js → mcp-Cy9mgCcr.js} +22 -9
- package/dist/mcp-Cy9mgCcr.js.map +1 -0
- package/dist/mcp.d.ts +1 -1
- package/dist/mcp.js +1 -1
- package/dist/{messages-C_1AmSpk.js → messages-RPKrEPvH.js} +6 -2
- package/dist/messages-RPKrEPvH.js.map +1 -0
- package/dist/output/stream-json.d.ts +2 -2
- package/dist/output/stream-json.js +1 -1
- package/dist/output/terminal.d.ts +2 -2
- package/dist/output/terminal.js +1 -0
- package/dist/output/terminal.js.map +1 -1
- package/dist/{presets-Cm2BPJaU.js → presets-D5ibZTml.js} +2 -2
- package/dist/{presets-Cm2BPJaU.js.map → presets-D5ibZTml.js.map} +1 -1
- package/dist/presets.d.ts +2 -2
- package/dist/presets.js +1 -1
- package/dist/{providers-BGBB18zz.js → providers-C2cxujp_.js} +85 -20
- package/dist/providers-C2cxujp_.js.map +1 -0
- package/dist/providers.d.ts +1 -1
- package/dist/providers.js +2 -2
- package/dist/restate.d.ts +2 -2
- package/dist/restate.js +4 -1
- package/dist/restate.js.map +1 -1
- package/dist/session/sqlite.d.ts +1 -1
- package/dist/session/sqlite.d.ts.map +1 -1
- package/dist/session/sqlite.js +36 -4
- package/dist/session/sqlite.js.map +1 -1
- package/dist/{session-CtAWwwkn.js → session-Do_TQV7c.js} +70 -22
- package/dist/session-Do_TQV7c.js.map +1 -0
- package/dist/session.d.ts +2 -2
- package/dist/session.js +3 -3
- package/dist/shell-quote-BmnhZmdM.js +33 -0
- package/dist/shell-quote-BmnhZmdM.js.map +1 -0
- package/dist/skills.d.ts +3 -3
- package/dist/skills.js +1 -1
- package/dist/skills.js.map +1 -1
- package/dist/{tool-formatters-D_fX6FGl.d.ts → tool-formatters-RT5-gyE2.d.ts} +2 -2
- package/dist/{tool-formatters-D_fX6FGl.d.ts.map → tool-formatters-RT5-gyE2.d.ts.map} +1 -1
- package/dist/tools/fetch-url.d.ts +1 -1
- package/dist/tools/web-search.d.ts +1 -1
- package/dist/{tools-NxnEmzYg.js → tools-ZHKOh44k.js} +342 -123
- package/dist/tools-ZHKOh44k.js.map +1 -0
- package/dist/tools.d.ts +2 -2
- package/dist/tools.js +1 -1
- package/dist/{transcript-anchors-DA6XawEU.d.ts → transcript-anchors-B4FxkG-8.d.ts} +10 -4
- package/dist/transcript-anchors-B4FxkG-8.d.ts.map +1 -0
- package/dist/{transcript-anchors-B_c7gWot.js → transcript-anchors-CS46ul6X.js} +10 -10
- package/dist/transcript-anchors-CS46ul6X.js.map +1 -0
- package/dist/tui.d.ts +3 -3
- package/dist/tui.d.ts.map +1 -1
- package/dist/tui.js +167 -41
- package/dist/tui.js.map +1 -1
- package/dist/{turn-operations-CCl7rpbT.d.ts → turn-operations-CoRj3mYZ.d.ts} +3 -3
- package/dist/{turn-operations-CCl7rpbT.d.ts.map → turn-operations-CoRj3mYZ.d.ts.map} +1 -1
- package/dist/{types-BibzMDjX.d.ts → types-B39tBba1.d.ts} +69 -2
- package/dist/types-B39tBba1.d.ts.map +1 -0
- package/dist/types-BiobHM1D.js.map +1 -1
- package/dist/types.d.ts +5 -5
- package/docs/ARCHITECTURE.md +1 -1
- package/docs/CHAT.md +3 -3
- package/docs/EXECUTION_CONTEXT.md +257 -0
- package/docs/RUN_IN_BACKGROUND.md +8 -0
- package/docs/SKILL.md +3 -3
- package/package.json +57 -24
- package/dist/agent-BHkvYIH9.d.ts.map +0 -1
- package/dist/contexts-BJVgG0LY.js.map +0 -1
- package/dist/index-BIo67xLV.d.ts.map +0 -1
- package/dist/index-C4aT2kO_.d.ts.map +0 -1
- package/dist/login-0jP1pnSJ.js.map +0 -1
- package/dist/mcp-tevNihk_.js.map +0 -1
- package/dist/messages-C_1AmSpk.js.map +0 -1
- package/dist/providers-BGBB18zz.js.map +0 -1
- package/dist/session-CtAWwwkn.js.map +0 -1
- package/dist/tools-NxnEmzYg.js.map +0 -1
- package/dist/transcript-anchors-B_c7gWot.js.map +0 -1
- package/dist/transcript-anchors-DA6XawEU.d.ts.map +0 -1
- package/dist/types-BibzMDjX.d.ts.map +0 -1
|
@@ -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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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { r as AgentHooks } from "./agent-D0W9yClt.js";
|
|
2
|
+
import { Hookable } from "hookable";
|
|
3
|
+
|
|
4
|
+
//#region src/logger.d.ts
|
|
5
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
6
|
+
interface LogRecord {
|
|
7
|
+
level: LogLevel;
|
|
8
|
+
/** Unix ms — set by `Logger` at emit time. */
|
|
9
|
+
timestamp: number;
|
|
10
|
+
/** Free-form message. Sinks render this as the human-facing line. */
|
|
11
|
+
message: string;
|
|
12
|
+
/** Structured fields. Correlation ids land here automatically. */
|
|
13
|
+
attrs: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
interface LogSink {
|
|
16
|
+
emit: (record: LogRecord) => void;
|
|
17
|
+
}
|
|
18
|
+
interface Logger {
|
|
19
|
+
debug: (message: string, attrs?: Record<string, unknown>) => void;
|
|
20
|
+
info: (message: string, attrs?: Record<string, unknown>) => void;
|
|
21
|
+
warn: (message: string, attrs?: Record<string, unknown>) => void;
|
|
22
|
+
error: (message: string, attrs?: Record<string, unknown>) => void;
|
|
23
|
+
/**
|
|
24
|
+
* Returns a child logger that prepends the given attributes onto every
|
|
25
|
+
* subsequent emit. Equivalent to `pino.child` / `winston.child`. The
|
|
26
|
+
* parent and child share the same sink — children are zero-cost.
|
|
27
|
+
*/
|
|
28
|
+
with: (extra: Record<string, unknown>) => Logger;
|
|
29
|
+
/**
|
|
30
|
+
* Inspectable baseline attributes — handy for tests and for hook
|
|
31
|
+
* handlers that want to clone-with-extra without recursing.
|
|
32
|
+
*/
|
|
33
|
+
readonly baseAttributes: Readonly<Record<string, unknown>>;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Build a Logger from a sink. Stateless and cheap; create one per agent
|
|
37
|
+
* (or per app) and use `.with()` to attach correlation ids per-call.
|
|
38
|
+
*/
|
|
39
|
+
declare function createLogger(sink: LogSink, baseAttributes?: Readonly<Record<string, unknown>>): Logger;
|
|
40
|
+
interface ConsoleSinkOptions {
|
|
41
|
+
/**
|
|
42
|
+
* Minimum level to emit. Defaults to `'info'` — `debug` is dropped so
|
|
43
|
+
* the harness's lifecycle logging is not noisy by default. Set to
|
|
44
|
+
* `'debug'` to see every event.
|
|
45
|
+
*/
|
|
46
|
+
minLevel?: LogLevel;
|
|
47
|
+
/** Custom output stream. Defaults to `process.stderr` so logs don't pollute stdout. */
|
|
48
|
+
stream?: {
|
|
49
|
+
write: (chunk: string) => void;
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Human-readable terminal sink. Renders each record as
|
|
54
|
+
* `<ISO timestamp> <LEVEL> <message> <attrs as kv pairs>`.
|
|
55
|
+
*
|
|
56
|
+
* Honors `process.stderr` by default so log lines don't interleave with
|
|
57
|
+
* the agent's stdout-bound output (chat responses, JSON results).
|
|
58
|
+
*/
|
|
59
|
+
declare function consoleSink(options?: ConsoleSinkOptions): LogSink;
|
|
60
|
+
/**
|
|
61
|
+
* One-JSON-object-per-line sink. Suitable for piping into log aggregators
|
|
62
|
+
* (Datadog Agent, Fluent Bit, Loki, Vector) that expect JSONL.
|
|
63
|
+
*/
|
|
64
|
+
declare function jsonSink(options?: ConsoleSinkOptions): LogSink;
|
|
65
|
+
interface LoggingHooksOptions {
|
|
66
|
+
logger: Logger;
|
|
67
|
+
/**
|
|
68
|
+
* Minimum interesting level for harness-emitted lines. Default `'info'`.
|
|
69
|
+
* Set to `'debug'` to see every tool dispatch / stream event. Set to
|
|
70
|
+
* `'warn'` to mute the chatty ones and only see failures + budgets.
|
|
71
|
+
*/
|
|
72
|
+
level?: LogLevel;
|
|
73
|
+
/**
|
|
74
|
+
* When true (default), lifecycle events (`agent:start`, `turn:before`,
|
|
75
|
+
* `tool:before`, `mcp:bootstrap:start`) emit at `debug` level so they
|
|
76
|
+
* stay quiet by default. Set false to mute them entirely regardless of
|
|
77
|
+
* the configured minimum level — useful when piping into a tracer
|
|
78
|
+
* that already captures lifecycle.
|
|
79
|
+
*/
|
|
80
|
+
includeLifecycle?: boolean;
|
|
81
|
+
}
|
|
82
|
+
interface LoggingHookSet {
|
|
83
|
+
install: (hooks: Hookable<AgentHooks>) => () => void;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Install a bundle of hook handlers that emit a structured line per
|
|
87
|
+
* relevant lifecycle event, automatically attaching correlation ids
|
|
88
|
+
* (`runId`, `turnId`, `callId`, `childId`, `depth`, `agentName`).
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```ts
|
|
92
|
+
* const logger = createLogger(consoleSink({ minLevel: 'debug' }), { service: 'tui' })
|
|
93
|
+
* const lh = createLoggingHooks({ logger })
|
|
94
|
+
* const uninstall = lh.install(agent.hooks)
|
|
95
|
+
* try { await agent.run({ prompt }) }
|
|
96
|
+
* finally { uninstall() }
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
declare function createLoggingHooks(options: LoggingHooksOptions): LoggingHookSet;
|
|
100
|
+
//#endregion
|
|
101
|
+
export { Logger as a, consoleSink as c, jsonSink as d, LogSink as i, createLogger as l, LogLevel as n, LoggingHookSet as o, LogRecord as r, LoggingHooksOptions as s, ConsoleSinkOptions as t, createLoggingHooks as u };
|
|
102
|
+
//# sourceMappingURL=logger-n4LsLISE.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger-n4LsLISE.d.ts","names":[],"sources":["../src/logger.ts"],"mappings":";;;;KAgCY,QAAA;AAAA,UAEK,SAAA;EACf,KAAA,EAAO,QAAA;EAUiB;EARxB,SAAA;EAWqB;EATrB,OAAA;EAUiC;EARjC,KAAA,EAAO,MAAM;AAAA;AAAA,UAGE,OAAA;EACf,IAAA,GAAO,MAAA,EAAQ,SAAS;AAAA;AAAA,UAGT,MAAA;EACf,KAAA,GAAQ,OAAA,UAAiB,KAAA,GAAQ,MAAA;EACjC,IAAA,GAAO,OAAA,UAAiB,KAAA,GAAQ,MAAA;EAChC,IAAA,GAAO,OAAA,UAAiB,KAAA,GAAQ,MAAA;EAChC,KAAA,GAAQ,OAAA,UAAiB,KAAA,GAAQ,MAAA;EAHzB;;;;;EASR,IAAA,GAAO,KAAA,EAAO,MAAA,sBAA4B,MAAA;EARlB;;;;EAAA,SAaf,cAAA,EAAgB,QAAA,CAAS,MAAA;AAAA;;;;;iBAWpB,YAAA,CACd,IAAA,EAAM,OAAA,EACN,cAAA,GAAgB,QAAA,CAAS,MAAA,qBACxB,MAAA;AAAA,UA6Bc,kBAAA;EAhD2B;;;;;EAsD1C,QAAA,GAAW,QAAQ;EAtCL;EAwCd,MAAA;IAAW,KAAA,GAAQ,KAAA;EAAA;AAAA;;;;;;;;iBAiBL,WAAA,CAAY,OAAA,GAAS,kBAAA,GAA0B,OAAO;;;;AAtD7D;iBA2EO,QAAA,CAAS,OAAA,GAAS,kBAAA,GAA0B,OAAO;AAAA,UAqBlD,mBAAA;EACf,MAAA,EAAQ,MAAA;EA9DW;;;;;EAoEnB,KAAA,GAAQ,QAAQ;EAlEgB;AAAA;AAiBlC;;;;;EAyDE,gBAAA;AAAA;AAAA,UAGe,cAAA;EACf,OAAA,GAAU,KAAA,EAAO,QAAQ,CAAC,UAAA;AAAA;;;;;;;;AAxCuC;AAqBnE;;;;;;iBAoCgB,kBAAA,CAAmB,OAAA,EAAS,mBAAA,GAAsB,cAAc"}
|