@agimon-ai/po-log 0.0.0-alpha.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 (42) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +66 -0
  3. package/dist/apiContracts.cjs +164 -0
  4. package/dist/apiContracts.cjs.map +1 -0
  5. package/dist/apiContracts.d.mts +53 -0
  6. package/dist/apiContracts.d.mts.map +1 -0
  7. package/dist/apiContracts.mjs +159 -0
  8. package/dist/apiContracts.mjs.map +1 -0
  9. package/dist/extensions/server.cjs +1034 -0
  10. package/dist/extensions/server.cjs.map +1 -0
  11. package/dist/extensions/server.d.mts +5 -0
  12. package/dist/extensions/server.d.mts.map +1 -0
  13. package/dist/extensions/server.mjs +1006 -0
  14. package/dist/extensions/server.mjs.map +1 -0
  15. package/dist/extensions/web.mjs +1542 -0
  16. package/dist/extensions/web.mjs.map +1 -0
  17. package/dist/index-CTZMUfTZ.d.mts +185 -0
  18. package/dist/index-CTZMUfTZ.d.mts.map +1 -0
  19. package/dist/index.cjs +13 -0
  20. package/dist/index.d.mts +36 -0
  21. package/dist/index.d.mts.map +1 -0
  22. package/dist/index.mjs +2 -0
  23. package/dist/metrics-DywCpDJ_.mjs +508 -0
  24. package/dist/metrics-DywCpDJ_.mjs.map +1 -0
  25. package/dist/metrics-jCZe13Xg.cjs +573 -0
  26. package/dist/metrics-jCZe13Xg.cjs.map +1 -0
  27. package/dist/metrics.cjs +13 -0
  28. package/dist/metrics.d.mts +2 -0
  29. package/dist/metrics.mjs +2 -0
  30. package/dist/metricsSource-DXZLawQu.mjs +130 -0
  31. package/dist/metricsSource-DXZLawQu.mjs.map +1 -0
  32. package/dist/metricsSource-DdwQNzoY.cjs +135 -0
  33. package/dist/metricsSource-DdwQNzoY.cjs.map +1 -0
  34. package/dist/metricsSource-cZnErdv4.d.mts +51 -0
  35. package/dist/metricsSource-cZnErdv4.d.mts.map +1 -0
  36. package/dist/metricsSource.cjs +3 -0
  37. package/dist/metricsSource.d.mts +18 -0
  38. package/dist/metricsSource.d.mts.map +1 -0
  39. package/dist/metricsSource.mjs +2 -0
  40. package/llms.txt +7 -0
  41. package/package.json +140 -0
  42. package/src/prompts/po-debug-agent/SKILL.md +28 -0
@@ -0,0 +1,1034 @@
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
4
+ });
5
+ //#region \0rolldown/runtime.js
6
+ var __create = Object.create;
7
+ var __defProp = Object.defineProperty;
8
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
9
+ var __getOwnPropNames = Object.getOwnPropertyNames;
10
+ var __getProtoOf = Object.getPrototypeOf;
11
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
14
+ key = keys[i];
15
+ if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
16
+ get: ((k) => from[k]).bind(null, key),
17
+ enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
18
+ });
19
+ }
20
+ return to;
21
+ };
22
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule || !__hasOwnProp.call(mod, "default") ? __defProp(target, "default", {
23
+ value: mod,
24
+ enumerable: true
25
+ }) : target, mod));
26
+ //#endregion
27
+ const require_metricsSource = require("../metricsSource-DdwQNzoY.cjs");
28
+ let _agimon_ai_log_sink_mcp = require("@agimon-ai/log-sink-mcp");
29
+ let _agimon_ai_po_core_serverFacet = require("@agimon-ai/po-core/serverFacet");
30
+ let _agimon_ai_po_core_extensionFile = require("@agimon-ai/po-core/extensionFile");
31
+ let _agimon_ai_po_core_runtimeJson = require("@agimon-ai/po-core/runtimeJson");
32
+ let _agimon_ai_po_telemetry = require("@agimon-ai/po-telemetry");
33
+ let hono = require("hono");
34
+ let node_child_process = require("node:child_process");
35
+ let node_module = require("node:module");
36
+ let node_path = require("node:path");
37
+ node_path = __toESM(node_path, 1);
38
+ let _agimon_ai_po_core_web = require("@agimon-ai/po-core/web");
39
+ let _agimon_ai_po_core_help = require("@agimon-ai/po-core/help");
40
+ let typebox_value = require("typebox/value");
41
+ let typebox = require("typebox");
42
+ //#region src/constants/telemetry.ts
43
+ const PACKAGE_NAME$1 = "@agimon-ai/po-log";
44
+ //#endregion
45
+ //#region src/services/telemetryEnabled/index.ts
46
+ function isEnabled(value) {
47
+ return value === "1" || value?.toLowerCase() === "true" || value?.toLowerCase() === "yes";
48
+ }
49
+ //#endregion
50
+ //#region src/services/serverTelemetry/index.ts
51
+ function contextAttributes(execution) {
52
+ return {
53
+ "pi.mode": "json",
54
+ "pi.session.id": execution.sessionId,
55
+ ...execution.model === void 0 ? {} : {
56
+ "gen_ai.provider.name": execution.model.provider,
57
+ "gen_ai.request.model": execution.model.id
58
+ }
59
+ };
60
+ }
61
+ /** Headless hooks carry untrusted records, not Pi's typed assistant messages. */
62
+ function usageAttributes(message) {
63
+ const usage = (0, _agimon_ai_po_core_runtimeJson.isRecord)(message.usage) ? message.usage : {};
64
+ const attributes = {};
65
+ for (const [field, attribute] of Object.entries({
66
+ input: "gen_ai.usage.input_tokens",
67
+ output: "gen_ai.usage.output_tokens",
68
+ cacheRead: "gen_ai.usage.cache_read_tokens",
69
+ cacheWrite: "gen_ai.usage.cache_write_tokens",
70
+ totalTokens: "gen_ai.usage.total_tokens",
71
+ reasoning: "gen_ai.usage.reasoning_tokens"
72
+ })) {
73
+ const value = usage[field];
74
+ if (typeof value === "number" && Number.isFinite(value) && value >= 0) attributes[attribute] = value;
75
+ }
76
+ const cost = (0, _agimon_ai_po_core_runtimeJson.isRecord)(usage.cost) ? usage.cost.total : void 0;
77
+ if (typeof cost === "number" && Number.isFinite(cost) && cost >= 0) attributes["gen_ai.usage.cost"] = cost;
78
+ return attributes;
79
+ }
80
+ function createServerTelemetry(options = {}) {
81
+ let active = false;
82
+ let finished = false;
83
+ let queue = Promise.resolve();
84
+ let disposal;
85
+ let thinkingLevel;
86
+ const sessionAttributes = (execution) => ({
87
+ ...contextAttributes(execution),
88
+ ...thinkingLevel ? { "pi.thinking_level": thinkingLevel } : {}
89
+ });
90
+ const enqueue = (operation) => {
91
+ const pending = queue.then(operation);
92
+ queue = pending.catch((error) => options.onDiagnostic?.(String(error)));
93
+ return pending;
94
+ };
95
+ let telemetry;
96
+ const turns = /* @__PURE__ */ new Map();
97
+ const tools = /* @__PURE__ */ new Map();
98
+ let agentStartedAt;
99
+ let turnIndex = 0;
100
+ const activity = {
101
+ name: PACKAGE_NAME$1,
102
+ start(execution) {
103
+ const current = (0, _agimon_ai_po_telemetry.createDoomTelemetry)({
104
+ serviceName: options.serviceName ?? "pi",
105
+ packageName: PACKAGE_NAME$1,
106
+ cwd: execution.cwd,
107
+ env: {
108
+ ...options.env ?? execution.environment,
109
+ PI_SESSION_ID: execution.sessionId
110
+ },
111
+ allowFileFallback: options.allowFileFallback,
112
+ telemetryFactory: options.telemetryFactory,
113
+ warn: options.onDiagnostic ?? (() => void 0),
114
+ onRecord: (record) => options.metrics?.record(record.event, record.attributes),
115
+ onStatus: (status) => options.onSinkStatus?.({
116
+ service: status.serviceName,
117
+ backend: status.backend,
118
+ endpoint: status.endpoint ?? "none",
119
+ endpointSource: status.endpointSource,
120
+ traces: status.traces,
121
+ redaction: true,
122
+ fileFallback: status.fileFallback
123
+ }),
124
+ enableLogs: true,
125
+ enableTraces: (options.env ?? execution.environment).AGENT_OTEL_TRACES === void 0 || isEnabled((options.env ?? execution.environment).AGENT_OTEL_TRACES)
126
+ });
127
+ telemetry = current;
128
+ active = true;
129
+ finished = false;
130
+ return () => disposal ??= (async () => {
131
+ active = false;
132
+ await queue;
133
+ if (telemetry === current) {
134
+ telemetry = void 0;
135
+ turns.clear();
136
+ tools.clear();
137
+ agentStartedAt = void 0;
138
+ }
139
+ await current.shutdown();
140
+ })();
141
+ }
142
+ };
143
+ const command = {
144
+ name: "log-metrics",
145
+ description: "Show headless telemetry sink status.",
146
+ async execute(_args, execution) {
147
+ await execution.client.notify({
148
+ title: "Po telemetry",
149
+ body: JSON.stringify(telemetry?.status() ?? { active: false }, null, 2),
150
+ level: "info"
151
+ });
152
+ }
153
+ };
154
+ const hooks = [
155
+ {
156
+ event: "session_start",
157
+ async handle(_event, execution) {
158
+ thinkingLevel = (await execution.session?.readModelSettings?.())?.thinkingLevel;
159
+ await telemetry?.recordEvent("pi.session.started", {
160
+ ...sessionAttributes(execution),
161
+ "pi.session.reason": "startup",
162
+ "pi.session.previous": false
163
+ });
164
+ }
165
+ },
166
+ {
167
+ event: "agent_settled",
168
+ async handle(_event, execution) {
169
+ await telemetry?.recordDebug("pi.agent.settled", sessionAttributes(execution));
170
+ }
171
+ },
172
+ {
173
+ event: "session_shutdown",
174
+ async handle(_event, execution) {
175
+ if (finished) return;
176
+ finished = true;
177
+ await telemetry?.recordEvent("pi.session.finished", {
178
+ ...sessionAttributes(execution),
179
+ "pi.session.reason": "quit"
180
+ });
181
+ execution.client.setStatus("po-log", void 0);
182
+ }
183
+ },
184
+ {
185
+ event: "turn_start",
186
+ async handle(event, execution) {
187
+ if (!telemetry) return;
188
+ await telemetry.recordDebug("pi.turn.started", {
189
+ ...sessionAttributes(execution),
190
+ "pi.turn.index": event.turnIndex,
191
+ ...typeof event.turnId === "string" ? { "pi.turn.id": event.turnId } : {}
192
+ });
193
+ }
194
+ },
195
+ {
196
+ event: "turn_end",
197
+ async handle(event, execution) {
198
+ const current = telemetry;
199
+ if (!current) return;
200
+ const duration = event.telemetryDurationMs;
201
+ const message = (0, _agimon_ai_po_core_runtimeJson.isRecord)(event.message) && event.message.role === "assistant" ? event.message : void 0;
202
+ const usage = message === void 0 ? {} : usageAttributes(message);
203
+ const attributes = {
204
+ ...sessionAttributes(execution),
205
+ "pi.turn.index": event.turnIndex,
206
+ ...typeof event.turnId === "string" ? { "pi.turn.id": event.turnId } : {},
207
+ ...message === void 0 ? {} : {
208
+ "gen_ai.provider.name": message.provider ?? execution.model?.provider,
209
+ "gen_ai.response.model": message.responseModel ?? message.model,
210
+ "gen_ai.response.finish_reasons": message.stopReason
211
+ }
212
+ };
213
+ const results = Array.isArray(event.toolResults) ? event.toolResults.filter(_agimon_ai_po_core_runtimeJson.isRecord) : [];
214
+ await current.recordEvent("pi.turn.finished", {
215
+ ...attributes,
216
+ ...usage,
217
+ "pi.tool_result.count": results.length,
218
+ ...typeof duration === "number" ? { "pi.turn.duration_ms": duration } : {}
219
+ });
220
+ if (message?.stopReason === "error" || message?.stopReason === "aborted") {
221
+ const failure = {
222
+ ...attributes,
223
+ "error.type": "ProviderError",
224
+ "error.code": message.stopReason,
225
+ outcome: message.stopReason === "aborted" ? "aborted" : "error"
226
+ };
227
+ if (message.stopReason === "aborted") await current.recordWarning("pi.turn.failed", void 0, failure);
228
+ else await current.recordError("pi.turn.failed", void 0, failure);
229
+ }
230
+ if (Object.keys(usage).length > 0) for (const result of results) await current.recordDebug("pi.tool_token_sample", {
231
+ ...attributes,
232
+ ...usage,
233
+ "tool.name": result.toolName,
234
+ token_attribution: "toolCallTurn"
235
+ });
236
+ }
237
+ },
238
+ {
239
+ event: "tool_execution_start",
240
+ async handle(event, execution) {
241
+ if (!telemetry) return;
242
+ await telemetry.recordDebug("pi.tool_call", {
243
+ ...sessionAttributes(execution),
244
+ "tool.name": event.toolName,
245
+ "tool.call.id": event.toolCallId
246
+ });
247
+ }
248
+ },
249
+ {
250
+ event: "tool_execution_end",
251
+ async handle(event, execution) {
252
+ const current = telemetry;
253
+ if (!current) return;
254
+ const duration = event.telemetryDurationMs;
255
+ await current.recordEvent("pi.tool_result", {
256
+ ...sessionAttributes(execution),
257
+ "tool.name": event.toolName,
258
+ "tool.call.id": event.toolCallId,
259
+ success: event.isError !== true,
260
+ "tool.result.error": event.isError === true,
261
+ ...typeof duration === "number" ? { "tool.duration_ms": duration } : {}
262
+ });
263
+ if (typeof event.toolCallId === "string" && event.toolCallId.startsWith("external-")) await current.flush();
264
+ }
265
+ },
266
+ {
267
+ event: "agent_start",
268
+ async handle(_event, execution) {
269
+ if (!telemetry) return;
270
+ await telemetry.recordEvent("pi.agent.started", sessionAttributes(execution));
271
+ }
272
+ },
273
+ {
274
+ event: "model_select",
275
+ async handle(event, execution) {
276
+ await telemetry?.recordEvent("pi.model.selected", {
277
+ ...sessionAttributes(execution),
278
+ "pi.model.source": "set",
279
+ "gen_ai.provider.name": event.model.provider,
280
+ "gen_ai.request.model": event.model.id
281
+ });
282
+ }
283
+ },
284
+ {
285
+ event: "agent_end",
286
+ async handle(event, execution) {
287
+ await telemetry?.recordEvent("pi.agent.finished", {
288
+ ...sessionAttributes(execution),
289
+ "pi.message.count": Array.isArray(event.messages) ? event.messages.length : 0,
290
+ ...typeof event.telemetryDurationMs === "number" ? { "pi.agent.duration_ms": event.telemetryDurationMs } : {}
291
+ });
292
+ await telemetry?.flush();
293
+ }
294
+ }
295
+ ];
296
+ for (const hook of hooks) {
297
+ const handle = hook.handle.bind(hook);
298
+ hook.handle = (event, execution) => {
299
+ if (!active) return;
300
+ const now = Date.now();
301
+ if (hook.event === "agent_start") turnIndex = 0;
302
+ const index = typeof event.turnIndex === "number" ? event.turnIndex : turnIndex;
303
+ const turnKey = typeof event.turnId === "string" ? event.turnId : String(index);
304
+ if (hook.event === "turn_start") turns.set(turnKey, now);
305
+ if (hook.event === "tool_execution_start" && typeof event.toolCallId === "string") tools.set(event.toolCallId, now);
306
+ if (hook.event === "agent_start") agentStartedAt = now;
307
+ let duration;
308
+ if (hook.event === "turn_end") {
309
+ const start = turns.get(turnKey);
310
+ turns.delete(turnKey);
311
+ turnIndex += 1;
312
+ if (start !== void 0) duration = now - start;
313
+ }
314
+ if (hook.event === "tool_execution_end" && typeof event.toolCallId === "string") {
315
+ const start = tools.get(event.toolCallId);
316
+ tools.delete(event.toolCallId);
317
+ if (start !== void 0) duration = now - start;
318
+ }
319
+ if (hook.event === "agent_end") {
320
+ if (agentStartedAt !== void 0) duration = now - agentStartedAt;
321
+ agentStartedAt = void 0;
322
+ }
323
+ return enqueue(async () => {
324
+ thinkingLevel = (await execution.session?.readModelSettings?.())?.thinkingLevel;
325
+ await handle({
326
+ ...event,
327
+ turnIndex: index,
328
+ telemetryDurationMs: duration
329
+ }, execution);
330
+ });
331
+ };
332
+ }
333
+ return {
334
+ activities: [activity],
335
+ commands: [command],
336
+ hooks
337
+ };
338
+ }
339
+ //#endregion
340
+ //#region src/extensions/workspaces/sessions/(backend)/_lib/serverRoot.ts
341
+ const createLogServerRoot = () => {
342
+ const runtime = createServerTelemetry();
343
+ return {
344
+ value: runtime,
345
+ activities: runtime.activities
346
+ };
347
+ };
348
+ //#endregion
349
+ //#region src/extensions/workspaces/sessions/(backend)/root.server.ts
350
+ var root_server_default = (0, _agimon_ai_po_core_extensionFile.defineRoot)(createLogServerRoot);
351
+ //#endregion
352
+ //#region src/services/issuesSource/index.ts
353
+ /**
354
+ * Agent-issue analysis over the sink's CLI.
355
+ *
356
+ * One transport, not two, because the daemon serves only /api/metrics and
357
+ * /api/logs: there is no issues route to prefer. Every call is a subprocess,
358
+ * which is why the page asks for this only when a reader opens the section
359
+ * rather than alongside each report.
360
+ */
361
+ const PACKAGE_NAME = "@agimon-ai/log-sink-mcp";
362
+ const CLI_TIMEOUT_MS = 6e4;
363
+ /** The analysis scans the whole window, so its output is larger than a metrics report. */
364
+ const MAX_CLI_BUFFER = 33554432;
365
+ function cliEntryPoint() {
366
+ const packageJson = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href).resolve(`${PACKAGE_NAME}/package.json`);
367
+ return node_path.default.join(node_path.default.dirname(packageJson), "dist", "cli.mjs");
368
+ }
369
+ function runCli(params, dbPath) {
370
+ return new Promise((resolve, reject) => {
371
+ (0, node_child_process.execFile)(process.execPath, [
372
+ cliEntryPoint(),
373
+ "logs",
374
+ "agent-issues",
375
+ "--limit",
376
+ String(params.limit),
377
+ ...params.sessionId === void 0 ? [] : ["--session-id", params.sessionId],
378
+ ...params.startTime === void 0 ? [] : ["--start-time", params.startTime],
379
+ ...params.endTime === void 0 ? [] : ["--end-time", params.endTime],
380
+ ...dbPath === void 0 ? [] : ["--db-path", dbPath]
381
+ ], {
382
+ timeout: CLI_TIMEOUT_MS,
383
+ maxBuffer: MAX_CLI_BUFFER
384
+ }, (error, stdout, stderr) => {
385
+ if (error) {
386
+ reject(new Error(stderr.trim() || error.message));
387
+ return;
388
+ }
389
+ try {
390
+ resolve(JSON.parse(stdout));
391
+ } catch {
392
+ reject(/* @__PURE__ */ new Error("The log sink returned output this version cannot read."));
393
+ }
394
+ });
395
+ });
396
+ }
397
+ function isRecord(value) {
398
+ return typeof value === "object" && value !== null && !Array.isArray(value);
399
+ }
400
+ function counts(value) {
401
+ if (!isRecord(value)) return {};
402
+ const entries = Object.entries(value).flatMap(([key, count]) => typeof count === "number" ? [[key, count]] : []);
403
+ return Object.fromEntries(entries);
404
+ }
405
+ function text(value) {
406
+ return typeof value === "string" ? value : "";
407
+ }
408
+ function nullableText(value) {
409
+ return typeof value === "string" && value !== "" ? value : null;
410
+ }
411
+ function toSample(value) {
412
+ if (!isRecord(value)) return [];
413
+ return [{
414
+ fingerprint: text(value.fingerprint),
415
+ occurrenceCount: typeof value.occurrenceCount === "number" ? value.occurrenceCount : 1,
416
+ category: text(value.category),
417
+ timestamp: text(value.timestamp),
418
+ level: text(value.level),
419
+ message: text(value.message),
420
+ detail: nullableText(value.detail) ?? text(value.message),
421
+ tool: nullableText(value.tool),
422
+ errorType: nullableText(value.errorType),
423
+ agentName: nullableText(value.agentName),
424
+ model: nullableText(value.model),
425
+ statusCode: nullableText(value.statusCode)
426
+ }];
427
+ }
428
+ /**
429
+ * The CLI's report is a foreign process's JSON, so every field is narrowed
430
+ * here rather than cast. A sink one version ahead may add fields, and a sink
431
+ * one version behind may omit them; neither should throw.
432
+ */
433
+ function toReport$1(raw) {
434
+ if (!isRecord(raw)) throw new Error("The log sink returned output this version cannot read.");
435
+ const samples = Array.isArray(raw.issues) ? raw.issues.flatMap(toSample) : [];
436
+ return {
437
+ totalIssues: typeof raw.totalIssues === "number" ? raw.totalIssues : 0,
438
+ uniqueIncidents: typeof raw.uniqueIncidents === "number" ? raw.uniqueIncidents : 0,
439
+ byCategory: counts(raw.byCategory),
440
+ byTool: counts(raw.byTool),
441
+ byErrorType: counts(raw.byErrorType),
442
+ samples
443
+ };
444
+ }
445
+ function createIssuesSource(options = {}) {
446
+ const instance = (0, _agimon_ai_log_sink_mcp.resolveLogSinkInstance)({
447
+ env: options.env,
448
+ cwd: options.cwd,
449
+ packageName: options.packageName,
450
+ serviceName: options.serviceName
451
+ });
452
+ const cliRunner = options.cliRunner ?? ((params) => runCli(params, instance?.dbPath));
453
+ return { async query(params) {
454
+ return toReport$1(await cliRunner(params));
455
+ } };
456
+ }
457
+ //#endregion
458
+ //#region src/types/webMetrics.ts
459
+ /**
460
+ * The dimensions the page offers.
461
+ *
462
+ * log-sink-mcp also groups by 'workflow-run', 'workflow-name', 'job' and
463
+ * 'step'. Those are omitted on purpose: no Po package emits the matching
464
+ * attributes today, so offering them would draw an empty chart and read as a
465
+ * bug rather than as a gap.
466
+ */
467
+ const METRICS_DIMENSIONS = [
468
+ "session",
469
+ "agent",
470
+ "model",
471
+ "provider"
472
+ ];
473
+ const METRICS_PERIODS = [
474
+ "day",
475
+ "week",
476
+ "month",
477
+ "all"
478
+ ];
479
+ const METRICS_QUERY_PARAMS = {
480
+ dimension: "dimension",
481
+ period: "period",
482
+ /** Narrows the whole report to one value of the current dimension. */
483
+ focus: "focus"
484
+ };
485
+ function isMetricsDimension(value) {
486
+ return METRICS_DIMENSIONS.includes(value);
487
+ }
488
+ function isMetricsPeriod(value) {
489
+ return METRICS_PERIODS.includes(value);
490
+ }
491
+ //#endregion
492
+ //#region src/types/apiRoutes.ts
493
+ /**
494
+ * This package's routes, as data.
495
+ *
496
+ * No scope and no base path. The build reads both off
497
+ * `src/extensions/(backend)/api/log/`, so the mount is stated once, by the
498
+ * folder that creates it. They used to be written here, in the contract, and
499
+ * again inside every URL the page built, and the copies were free to disagree.
500
+ *
501
+ * This is the one file the routes, the Hono app and the browser all read, so a
502
+ * path cannot move on one side alone.
503
+ */
504
+ var apiRoutes_default = (0, _agimon_ai_po_core_web.defineApiRoutes)({
505
+ metrics: {
506
+ method: "GET",
507
+ path: "/metrics",
508
+ query: [
509
+ METRICS_QUERY_PARAMS.dimension,
510
+ METRICS_QUERY_PARAMS.period,
511
+ METRICS_QUERY_PARAMS.focus
512
+ ],
513
+ response: (0, _agimon_ai_po_core_web.apiResponse)()
514
+ },
515
+ /**
516
+ * Separate from the report because the hub answers it from a subprocess: the
517
+ * running daemon exposes no issues route, so folding it in would make every
518
+ * refresh wait on the slowest transport.
519
+ */
520
+ issues: {
521
+ method: "GET",
522
+ path: "/issues",
523
+ query: [METRICS_QUERY_PARAMS.focus],
524
+ response: (0, _agimon_ai_po_core_web.apiResponse)()
525
+ }
526
+ });
527
+ //#endregion
528
+ //#region src/services/hubApi/index.ts
529
+ /**
530
+ * The cockpit's half of this package's metrics access.
531
+ *
532
+ * Hub-scoped rather than session-scoped: the questions this answers, where the
533
+ * tokens went and which agents failed, are about the machine over time, and a
534
+ * session server can only see itself. The sink is already machine-wide, so the
535
+ * hub is the only place the two agree.
536
+ *
537
+ * The query path is not reimplemented here. `createMetricsSource` already owns
538
+ * the sink's two transports and its fallback order, and the TUI overlay reads
539
+ * through the same source, so both surfaces answer from one implementation.
540
+ */
541
+ const DEFAULT_DIMENSION = "model";
542
+ const DEFAULT_PERIOD = "week";
543
+ /** The sink groups sessions under a different name than the page's dimension. */
544
+ const SINK_GROUP_BY = {
545
+ session: "session",
546
+ agent: "agent",
547
+ model: "model",
548
+ provider: "provider"
549
+ };
550
+ function toBucket(bucket) {
551
+ return {
552
+ label: bucket.label,
553
+ totalTokens: bucket.totalTokens,
554
+ inputTokens: bucket.inputTokens,
555
+ outputTokens: bucket.outputTokens
556
+ };
557
+ }
558
+ function toGroup(row) {
559
+ return {
560
+ key: row.key,
561
+ totalTokens: row.totalTokens,
562
+ inputTokens: row.inputTokens,
563
+ outputTokens: row.outputTokens,
564
+ issueCount: row.issueCount,
565
+ failed: row.failed
566
+ };
567
+ }
568
+ /**
569
+ * The turn's p90 rather than a sum: the sink attributes a whole turn's tokens
570
+ * to every tool that ran in it, so adding them across calls would multiply the
571
+ * same tokens by however many tools shared the turn.
572
+ */
573
+ function toTool(row) {
574
+ return {
575
+ name: row.toolName,
576
+ calls: row.invocationCount,
577
+ p90TotalTokens: row.toolCallTurn.p90TotalTokens
578
+ };
579
+ }
580
+ /** Which filter field carries a focus value, per dimension. */
581
+ const FOCUS_FIELD = {
582
+ session: "sessionId",
583
+ agent: "agentName",
584
+ model: "model",
585
+ provider: "provider"
586
+ };
587
+ /**
588
+ * The focus the sink actually applied, read from its own echo.
589
+ *
590
+ * A daemon that predates a filter ignores it and answers with everything. If
591
+ * the page trusted the request instead of this echo, it would label the whole
592
+ * machine's numbers as one model's.
593
+ */
594
+ function appliedFocus(report, dimension) {
595
+ const filters = report.filters;
596
+ if (filters === void 0) return void 0;
597
+ if (dimension === "session") return filters.sessionId;
598
+ if (dimension === "agent") return filters.agentName;
599
+ const applied = dimension === "model" ? filters.model : filters.provider;
600
+ if (applied === void 0) return void 0;
601
+ return Array.isArray(applied) ? applied[0] : applied;
602
+ }
603
+ /**
604
+ * The sink's own type says Date, but both transports parse JSON, so what
605
+ * arrives is an ISO string. Trusting the declared type here throws on every
606
+ * real response, which no test using a hand-built Date would ever catch.
607
+ */
608
+ function generatedAtIso(value) {
609
+ if (value instanceof Date) return value.toISOString();
610
+ const parsed = new Date(value);
611
+ return Number.isNaN(parsed.getTime()) ? (/* @__PURE__ */ new Date(0)).toISOString() : parsed.toISOString();
612
+ }
613
+ function toReport(report, source, dimension) {
614
+ const focus = appliedFocus(report, dimension);
615
+ return {
616
+ generatedAt: generatedAtIso(report.generatedAt),
617
+ ...report.filters?.startTime === void 0 ? {} : { startTime: generatedAtIso(report.filters.startTime) },
618
+ endTime: generatedAtIso(report.filters?.endTime ?? report.generatedAt),
619
+ dimension: report.groupBy,
620
+ period: report.period,
621
+ bucketUnit: String(report.bucket),
622
+ transport: source.lastTransport(),
623
+ ...focus === void 0 ? {} : { focus },
624
+ totals: {
625
+ usageEventCount: report.totals.usageEventCount,
626
+ totalRecords: report.totals.totalRecords,
627
+ totalTokens: report.totals.totalTokens,
628
+ inputTokens: report.totals.inputTokens,
629
+ outputTokens: report.totals.outputTokens,
630
+ cachedTokens: report.totals.cachedInputTokens,
631
+ reasoningTokens: report.totals.reasoningOutputTokens,
632
+ groupCount: report.totals.groupCount,
633
+ failedGroups: report.totals.failedGroups,
634
+ issueCount: report.totals.issueCount
635
+ },
636
+ timeline: report.timeline.map(toBucket),
637
+ groups: report.groups.map(toGroup),
638
+ tools: report.tools.rows.map(toTool)
639
+ };
640
+ }
641
+ /**
642
+ * A report with nothing in it reads as "no data", not as an empty chart. The
643
+ * reader may have used the HTTP sink or a worker against an empty history, so
644
+ * the empty-state detail must not claim the sink is running.
645
+ */
646
+ function isEmpty(report) {
647
+ return report.totals.totalTokens === 0 && report.groups.length === 0 && report.tools.length === 0;
648
+ }
649
+ function createLogHubApi(options = {}) {
650
+ const app = new hono.Hono();
651
+ const identity = {
652
+ packageName: PACKAGE_NAME$1,
653
+ serviceName: "pi",
654
+ ...options.env === void 0 ? {} : { env: options.env }
655
+ };
656
+ const source = options.source ?? require_metricsSource.createMetricsSource(identity);
657
+ const issues = options.issues ?? createIssuesSource(identity);
658
+ app.get(apiRoutes_default.metrics.path, async (context) => {
659
+ const requestedDimension = context.req.query(METRICS_QUERY_PARAMS.dimension) ?? DEFAULT_DIMENSION;
660
+ const requestedPeriod = context.req.query(METRICS_QUERY_PARAMS.period) ?? DEFAULT_PERIOD;
661
+ if (!isMetricsDimension(requestedDimension)) return context.json({ error: `Unknown dimension '${requestedDimension}'.` }, 400);
662
+ if (!isMetricsPeriod(requestedPeriod)) return context.json({ error: `Unknown period '${requestedPeriod}'.` }, 400);
663
+ const focus = context.req.query(METRICS_QUERY_PARAMS.focus);
664
+ const filter = focus === void 0 || focus === "" ? void 0 : { [FOCUS_FIELD[requestedDimension]]: focus };
665
+ let report;
666
+ try {
667
+ report = await source.query({
668
+ groupBy: SINK_GROUP_BY[requestedDimension],
669
+ period: requestedPeriod,
670
+ limit: 20,
671
+ toolLimit: 15,
672
+ ...filter === void 0 ? {} : { filter }
673
+ });
674
+ } catch (error) {
675
+ const unavailable = {
676
+ unavailable: "query-error",
677
+ detail: error instanceof Error ? error.message : "The metrics query failed."
678
+ };
679
+ return context.json(unavailable);
680
+ }
681
+ const body = toReport(report, source, requestedDimension);
682
+ if (isEmpty(body)) return context.json({
683
+ unavailable: "no-data",
684
+ detail: "No recorded usage was found for this period."
685
+ });
686
+ return context.json(body);
687
+ });
688
+ /**
689
+ * The detail behind the count the report carries. Separate from /metrics
690
+ * because it costs a subprocess: the running daemon has no issues route, so
691
+ * folding it into every report would make the whole page as slow as its
692
+ * slowest transport.
693
+ */
694
+ app.get(apiRoutes_default.issues.path, async (context) => {
695
+ const focus = context.req.query(METRICS_QUERY_PARAMS.focus);
696
+ const startTime = context.req.query("startTime");
697
+ const endTime = context.req.query("endTime");
698
+ const validTime = (value) => value === void 0 || /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(value) && Number.isFinite(Date.parse(value));
699
+ if (!validTime(startTime) || !validTime(endTime) || startTime !== void 0 && endTime !== void 0 && Date.parse(startTime) > Date.parse(endTime)) return context.json({ error: "Issue time bounds must be valid ISO instants in chronological order." }, 400);
700
+ try {
701
+ const report = await issues.query({
702
+ limit: 50,
703
+ ...startTime === void 0 ? {} : { startTime },
704
+ ...endTime === void 0 ? {} : { endTime },
705
+ ...focus === void 0 || focus === "" ? {} : { sessionId: focus }
706
+ });
707
+ return context.json(report);
708
+ } catch (error) {
709
+ const unavailable = {
710
+ unavailable: "query-error",
711
+ detail: error instanceof Error ? error.message : "The issues query failed."
712
+ };
713
+ return context.json(unavailable);
714
+ }
715
+ });
716
+ return app;
717
+ }
718
+ //#endregion
719
+ //#region src/extensions/(backend)/api/log/route.server.ts
720
+ var route_server_default = (0, _agimon_ai_po_core_extensionFile.defineRoute)({
721
+ basePath: "log",
722
+ start(context) {
723
+ const env = { ...context.environment };
724
+ const source = require_metricsSource.createMetricsSource({
725
+ env,
726
+ packageName: PACKAGE_NAME$1,
727
+ serviceName: "pi"
728
+ });
729
+ const app = createLogHubApi({
730
+ source,
731
+ env
732
+ });
733
+ return {
734
+ fetch: (request) => app.fetch(request),
735
+ close: () => source.close?.()
736
+ };
737
+ }
738
+ });
739
+ //#endregion
740
+ //#region src/extensions/workspaces/sessions/(backend)/command/log-metrics.server.ts
741
+ var log_metrics_server_default = (0, _agimon_ai_po_core_extensionFile.defineServerCommand)((context) => context.root.commands[0]);
742
+ //#endregion
743
+ //#region src/extensions/workspaces/sessions/(backend)/hook/agent-end.server.ts
744
+ var agent_end_server_default = (0, _agimon_ai_po_core_extensionFile.defineHook)((context) => context.root.hooks[9]);
745
+ //#endregion
746
+ //#region src/extensions/workspaces/sessions/(backend)/hook/agent-settled.server.ts
747
+ var agent_settled_server_default = (0, _agimon_ai_po_core_extensionFile.defineHook)((context) => context.root.hooks[1]);
748
+ //#endregion
749
+ //#region src/extensions/workspaces/sessions/(backend)/hook/agent-start.server.ts
750
+ var agent_start_server_default = (0, _agimon_ai_po_core_extensionFile.defineHook)((context) => context.root.hooks[7]);
751
+ //#endregion
752
+ //#region src/extensions/workspaces/sessions/(backend)/hook/model-select.server.ts
753
+ var model_select_server_default = (0, _agimon_ai_po_core_extensionFile.defineHook)((context) => context.root.hooks[8]);
754
+ //#endregion
755
+ //#region src/extensions/workspaces/sessions/(backend)/hook/session-shutdown.server.ts
756
+ var session_shutdown_server_default = (0, _agimon_ai_po_core_extensionFile.defineHook)((context) => context.root.hooks[2]);
757
+ //#endregion
758
+ //#region src/extensions/workspaces/sessions/(backend)/hook/session-start.server.ts
759
+ var session_start_server_default = (0, _agimon_ai_po_core_extensionFile.defineHook)((context) => context.root.hooks[0]);
760
+ //#endregion
761
+ //#region src/extensions/workspaces/sessions/(backend)/hook/tool-execution-end.server.ts
762
+ var tool_execution_end_server_default = (0, _agimon_ai_po_core_extensionFile.defineHook)((context) => context.root.hooks[6]);
763
+ //#endregion
764
+ //#region src/extensions/workspaces/sessions/(backend)/hook/tool-execution-start.server.ts
765
+ var tool_execution_start_server_default = (0, _agimon_ai_po_core_extensionFile.defineHook)((context) => context.root.hooks[5]);
766
+ //#endregion
767
+ //#region src/extensions/workspaces/sessions/(backend)/hook/turn-end.server.ts
768
+ var turn_end_server_default = (0, _agimon_ai_po_core_extensionFile.defineHook)((context) => context.root.hooks[4]);
769
+ //#endregion
770
+ //#region src/extensions/workspaces/sessions/(backend)/hook/turn-start.server.ts
771
+ var turn_start_server_default = (0, _agimon_ai_po_core_extensionFile.defineHook)((context) => context.root.hooks[3]);
772
+ //#endregion
773
+ //#region src/constants/diagnostics.ts
774
+ const DIAGNOSE_AGENT_NAME = "diagnose_agent";
775
+ const DIAGNOSE_AGENT_DESCRIPTION = "Inspect captured failures and token usage for the current Po session. Read-only, bounded to the last day or week; omits prompts, tool arguments, credentials, and unrelated sessions.";
776
+ const AGENT_DIAGNOSTIC_TIMEOUT_MS = 15e3;
777
+ const AGENT_ISSUE_CATEGORIES = [
778
+ "tool_failure",
779
+ "infrastructure_failure",
780
+ "caller_error",
781
+ "expected_failure",
782
+ "page_state",
783
+ "api_error",
784
+ "api_refusal",
785
+ "api_retries_exhausted",
786
+ "tool_rejected",
787
+ "log_error"
788
+ ];
789
+ //#endregion
790
+ //#region src/extensions/workspaces/sessions/(backend)/resource/po-debug-agent.server.ts
791
+ var po_debug_agent_server_default = (0, _agimon_ai_po_core_extensionFile.defineResource)({
792
+ name: "po-debug-agent",
793
+ description: "Debug a Po agent using session-scoped failure and usage evidence. Distinguish missing telemetry from a healthy run, diagnose expensive or failed tools, and investigate deeper traces without exposing secrets or changing the sink.",
794
+ when: _agimon_ai_po_core_help.DOOM_HELP_WHEN,
795
+ kind: "skill",
796
+ path: (0, _agimon_ai_po_core_serverFacet.packageResourcePath)(require("url").pathToFileURL(__filename).href, "src/prompts/po-debug-agent/SKILL.md"),
797
+ read: () => (0, _agimon_ai_po_core_serverFacet.readPackageResource)(require("url").pathToFileURL(__filename).href, "src/prompts/po-debug-agent/SKILL.md")
798
+ });
799
+ //#endregion
800
+ //#region src/schemas/agentDiagnostics.ts
801
+ const count = typebox.Type.Number({ minimum: 0 });
802
+ const coverage = typebox.Type.Number({
803
+ minimum: 0,
804
+ maximum: 100
805
+ });
806
+ const agentDiagnosticParameters = typebox.Type.Object({
807
+ period: typebox.Type.Optional(typebox.Type.Union([typebox.Type.Literal("day"), typebox.Type.Literal("week")])),
808
+ toolLimit: typebox.Type.Optional(typebox.Type.Integer({
809
+ minimum: 1,
810
+ maximum: 20
811
+ }))
812
+ }, { additionalProperties: false });
813
+ /** Validate only the fields we return. Extra upstream fields never cross this boundary. */
814
+ const scopedMetricsSchema = typebox.Type.Object({
815
+ groupBy: typebox.Type.Literal("session"),
816
+ period: typebox.Type.Union([typebox.Type.Literal("day"), typebox.Type.Literal("week")]),
817
+ filters: typebox.Type.Object({ sessionId: typebox.Type.String({ minLength: 1 }) }),
818
+ totals: typebox.Type.Object({
819
+ totalRecords: count,
820
+ issueCount: count,
821
+ usageEventCount: count,
822
+ inputTokens: count,
823
+ outputTokens: count,
824
+ totalTokens: count,
825
+ cachedInputTokens: count,
826
+ reasoningOutputTokens: count,
827
+ tokenCoveragePercent: coverage
828
+ }),
829
+ groups: typebox.Type.Array(typebox.Type.Object({
830
+ sessionId: typebox.Type.String({ minLength: 1 }),
831
+ byCategory: typebox.Type.Record(typebox.Type.String(), count)
832
+ }), { maxItems: 1 }),
833
+ tools: typebox.Type.Object({
834
+ returnedTools: count,
835
+ rows: typebox.Type.Array(typebox.Type.Object({
836
+ toolName: typebox.Type.String({
837
+ minLength: 1,
838
+ maxLength: 128,
839
+ pattern: "^[A-Za-z0-9_./:-]+$"
840
+ }),
841
+ invocationCount: count,
842
+ toolCallTurn: typebox.Type.Object({
843
+ samples: count,
844
+ avgTotalTokens: count,
845
+ p90TotalTokens: count
846
+ })
847
+ }), { maxItems: 20 })
848
+ })
849
+ });
850
+ //#endregion
851
+ //#region src/services/agentDiagnostics/index.ts
852
+ async function readAgentDiagnostics(source, sessionId, input, signal) {
853
+ const period = input.period ?? "day";
854
+ const limit = input.toolLimit ?? 10;
855
+ signal.throwIfAborted();
856
+ let onAbort = () => {};
857
+ try {
858
+ const report = await Promise.race([source.query({
859
+ groupBy: "session",
860
+ period,
861
+ limit: 1,
862
+ toolLimit: limit,
863
+ filter: { sessionId }
864
+ }), new Promise((_resolve, reject) => {
865
+ onAbort = () => reject(signal.reason);
866
+ signal.addEventListener("abort", onAbort, { once: true });
867
+ if (signal.aborted) onAbort();
868
+ })]);
869
+ signal.throwIfAborted();
870
+ if (!(0, typebox_value.Check)(scopedMetricsSchema, report) || report.filters.sessionId !== sessionId || report.period !== period || report.groups.some((group) => group.sessionId !== sessionId)) return {
871
+ evidence: "unavailable",
872
+ code: "METRICS_SCOPE_NOT_CONFIRMED",
873
+ scope: "current-session",
874
+ period
875
+ };
876
+ const totals = report.totals;
877
+ return {
878
+ scope: "current-session",
879
+ period,
880
+ evidence: totals.totalRecords === 0 ? "empty" : "available",
881
+ transport: source.lastTransport(),
882
+ capturedRecords: totals.totalRecords,
883
+ capturedIssues: totals.issueCount,
884
+ issuesByCategory: Object.fromEntries(AGENT_ISSUE_CATEGORIES.map((category) => [category, report.groups[0]?.byCategory[category] ?? 0])),
885
+ usage: {
886
+ inputTokens: totals.inputTokens,
887
+ outputTokens: totals.outputTokens,
888
+ totalTokens: totals.totalTokens,
889
+ cachedInputTokens: totals.cachedInputTokens,
890
+ reasoningOutputTokens: totals.reasoningOutputTokens,
891
+ usageEventCount: totals.usageEventCount,
892
+ tokenCoveragePercent: totals.tokenCoveragePercent
893
+ },
894
+ tools: report.tools.rows.slice(0, limit).map((tool) => ({
895
+ name: tool.toolName,
896
+ invocations: tool.invocationCount,
897
+ sampledTurns: tool.toolCallTurn.samples,
898
+ averageTurnTokens: tool.toolCallTurn.avgTotalTokens,
899
+ p90TurnTokens: tool.toolCallTurn.p90TotalTokens
900
+ })),
901
+ toolRowLimit: limit,
902
+ limitReached: report.tools.rows.length >= limit,
903
+ captureCompleteness: "not-reported",
904
+ limitations: "Only captured records in this window are represented. Empty data is not proof of a healthy run. Token coverage is not event-capture coverage; per-tool token samples describe the containing turn, not exclusive tool cost. Raw prompts, error messages, tool arguments and traces are omitted. Use po-debug-agent for deeper authorized investigation."
905
+ };
906
+ } catch (error) {
907
+ if (signal.aborted) throw error;
908
+ return {
909
+ evidence: "unavailable",
910
+ code: "METRICS_UNAVAILABLE",
911
+ scope: "current-session",
912
+ period
913
+ };
914
+ } finally {
915
+ signal.removeEventListener("abort", onAbort);
916
+ }
917
+ }
918
+ function createAgentDiagnosticsTool(readScope, authorize) {
919
+ return (0, _agimon_ai_po_core_serverFacet.defineTool)({
920
+ name: DIAGNOSE_AGENT_NAME,
921
+ description: DIAGNOSE_AGENT_DESCRIPTION,
922
+ parameters: agentDiagnosticParameters,
923
+ when: _agimon_ai_po_core_help.DOOM_HELP_WHEN,
924
+ executionMode: "serial",
925
+ async execute(input, execution) {
926
+ const active = authorize(execution.signal);
927
+ const signal = AbortSignal.any([active, AbortSignal.timeout(AGENT_DIAGNOSTIC_TIMEOUT_MS)]);
928
+ const scope = readScope();
929
+ if (!scope.sessionId) throw new Error("Agent diagnostics require an active session.");
930
+ const source = require_metricsSource.createMetricsSource({
931
+ packageName: PACKAGE_NAME$1,
932
+ serviceName: "pi",
933
+ ...scope.options
934
+ });
935
+ try {
936
+ const report = await readAgentDiagnostics(source, scope.sessionId, input, signal);
937
+ signal.throwIfAborted();
938
+ authorize(execution.signal);
939
+ return {
940
+ content: [{
941
+ type: "text",
942
+ text: JSON.stringify(report, null, 2)
943
+ }],
944
+ details: report
945
+ };
946
+ } finally {
947
+ await source.close?.();
948
+ }
949
+ }
950
+ });
951
+ }
952
+ //#endregion
953
+ //#region src/extensions/workspaces/sessions/(backend)/tool/diagnose_agent.server.ts
954
+ var diagnose_agent_server_default = (0, _agimon_ai_po_core_extensionFile.defineTool)(({ agent, signal: ownerSignal }) => {
955
+ if (!agent) throw new Error("Agent diagnostics require a session host.");
956
+ return createAgentDiagnosticsTool(() => ({
957
+ sessionId: agent.context.sessionId,
958
+ options: {
959
+ cwd: agent.context.cwd,
960
+ env: {
961
+ ...agent.context.environment,
962
+ PI_SESSION_ID: agent.context.sessionId
963
+ }
964
+ }
965
+ }), (signal) => {
966
+ ownerSignal.throwIfAborted();
967
+ signal?.throwIfAborted();
968
+ agent.assertActive(PACKAGE_NAME$1);
969
+ if (!(agent.context.selection.state?.["minor-mode"] ?? []).includes("help")) throw new Error("Help mode is not active.");
970
+ return signal ? AbortSignal.any([signal, ownerSignal]) : ownerSignal;
971
+ });
972
+ });
973
+ //#endregion
974
+ //#region generated/server.ts
975
+ const at = (value, context) => typeof value === "function" ? value(context) : value;
976
+ const via = (identity, value) => value === void 0 ? void 0 : {
977
+ ...identity,
978
+ ...value
979
+ };
980
+ const facet = (0, _agimon_ai_po_core_serverFacet.defineServerPlugin)({
981
+ name: "@agimon-ai/po-log",
982
+ providerOverrides: (0, _agimon_ai_po_core_serverFacet.composeServerProviderOverrides)(root_server_default),
983
+ global: (context) => ({ get api() {
984
+ return [at(route_server_default, context)];
985
+ } }),
986
+ workspace: (context) => ({ get api() {
987
+ return [at(route_server_default, context)];
988
+ } }),
989
+ session: async (context) => {
990
+ const scopeSession = await root_server_default(context);
991
+ const contextSession = {
992
+ ...context,
993
+ root: scopeSession.value
994
+ };
995
+ return {
996
+ ...(0, _agimon_ai_po_core_extensionFile.composeRootHooks)(scopeSession),
997
+ get api() {
998
+ return [at(route_server_default, context)];
999
+ },
1000
+ get commands() {
1001
+ return [via({ name: "log-metrics" }, at(log_metrics_server_default, contextSession))];
1002
+ },
1003
+ get hooks() {
1004
+ return [
1005
+ via({ event: "agent_end" }, at(agent_end_server_default, contextSession)),
1006
+ via({ event: "agent_settled" }, at(agent_settled_server_default, contextSession)),
1007
+ via({ event: "agent_start" }, at(agent_start_server_default, contextSession)),
1008
+ via({ event: "model_select" }, at(model_select_server_default, contextSession)),
1009
+ via({ event: "session_shutdown" }, at(session_shutdown_server_default, contextSession)),
1010
+ via({ event: "session_start" }, at(session_start_server_default, contextSession)),
1011
+ via({ event: "tool_execution_end" }, at(tool_execution_end_server_default, contextSession)),
1012
+ via({ event: "tool_execution_start" }, at(tool_execution_start_server_default, contextSession)),
1013
+ via({ event: "turn_end" }, at(turn_end_server_default, contextSession)),
1014
+ via({ event: "turn_start" }, at(turn_start_server_default, contextSession))
1015
+ ];
1016
+ },
1017
+ get resources() {
1018
+ return [at(po_debug_agent_server_default, contextSession)];
1019
+ },
1020
+ get tools() {
1021
+ return [via({ name: "diagnose_agent" }, at(diagnose_agent_server_default, contextSession))];
1022
+ },
1023
+ services: [...scopeSession.services ?? []],
1024
+ get activities() {
1025
+ return [...scopeSession.activities ?? []];
1026
+ }
1027
+ };
1028
+ }
1029
+ });
1030
+ //#endregion
1031
+ exports.default = facet;
1032
+ exports.facet = facet;
1033
+
1034
+ //# sourceMappingURL=server.cjs.map