@agimon-ai/doompi-log 0.0.1-alpha.82 → 0.0.1-alpha.84

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.
@@ -0,0 +1,183 @@
1
+ import { l as PACKAGE_NAME } from "./telemetryEnabled-B6g7R7BP.mjs";
2
+ import { t as createMetricsSource } from "./metricsSource-DXZLawQu.mjs";
3
+ import { defineTool } from "@agimon-ai/doompi-core/piExtension";
4
+ import { DOOM_HELP_WHEN } from "@agimon-ai/doompi-core/help";
5
+ import { Check } from "typebox/value";
6
+ import { Type } from "typebox";
7
+ //#region src/constants/diagnostics.ts
8
+ const DIAGNOSE_AGENT_NAME = "diagnose_agent";
9
+ const DIAGNOSE_AGENT_DESCRIPTION = "Inspect captured failures and token usage for the current DoomPi session. Read-only, bounded to the last day or week; omits prompts, tool arguments, credentials, and unrelated sessions.";
10
+ const AGENT_DIAGNOSTIC_TIMEOUT_MS = 15e3;
11
+ const AGENT_ISSUE_CATEGORIES = [
12
+ "tool_failure",
13
+ "infrastructure_failure",
14
+ "caller_error",
15
+ "expected_failure",
16
+ "page_state",
17
+ "api_error",
18
+ "api_refusal",
19
+ "api_retries_exhausted",
20
+ "tool_rejected",
21
+ "log_error"
22
+ ];
23
+ const AGENT_DIAGNOSTIC_SKILL = {
24
+ name: "doompi-debug-agent",
25
+ description: "Debug a DoomPi 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."
26
+ };
27
+ //#endregion
28
+ //#region src/schemas/agentDiagnostics.ts
29
+ const count = Type.Number({ minimum: 0 });
30
+ const coverage = Type.Number({
31
+ minimum: 0,
32
+ maximum: 100
33
+ });
34
+ const agentDiagnosticParameters = Type.Object({
35
+ period: Type.Optional(Type.Union([Type.Literal("day"), Type.Literal("week")])),
36
+ toolLimit: Type.Optional(Type.Integer({
37
+ minimum: 1,
38
+ maximum: 20
39
+ }))
40
+ }, { additionalProperties: false });
41
+ /** Validate only the fields we return. Extra upstream fields never cross this boundary. */
42
+ const scopedMetricsSchema = Type.Object({
43
+ groupBy: Type.Literal("session"),
44
+ period: Type.Union([Type.Literal("day"), Type.Literal("week")]),
45
+ filters: Type.Object({ sessionId: Type.String({ minLength: 1 }) }),
46
+ totals: Type.Object({
47
+ totalRecords: count,
48
+ issueCount: count,
49
+ usageEventCount: count,
50
+ inputTokens: count,
51
+ outputTokens: count,
52
+ totalTokens: count,
53
+ cachedInputTokens: count,
54
+ reasoningOutputTokens: count,
55
+ tokenCoveragePercent: coverage
56
+ }),
57
+ groups: Type.Array(Type.Object({
58
+ sessionId: Type.String({ minLength: 1 }),
59
+ byCategory: Type.Record(Type.String(), count)
60
+ }), { maxItems: 1 }),
61
+ tools: Type.Object({
62
+ returnedTools: count,
63
+ rows: Type.Array(Type.Object({
64
+ toolName: Type.String({
65
+ minLength: 1,
66
+ maxLength: 128,
67
+ pattern: "^[A-Za-z0-9_./:-]+$"
68
+ }),
69
+ invocationCount: count,
70
+ toolCallTurn: Type.Object({
71
+ samples: count,
72
+ avgTotalTokens: count,
73
+ p90TotalTokens: count
74
+ })
75
+ }), { maxItems: 20 })
76
+ })
77
+ });
78
+ //#endregion
79
+ //#region src/services/agentDiagnostics/index.ts
80
+ async function readAgentDiagnostics(source, sessionId, input, signal) {
81
+ const period = input.period ?? "day";
82
+ const limit = input.toolLimit ?? 10;
83
+ signal.throwIfAborted();
84
+ let onAbort = () => {};
85
+ try {
86
+ const report = await Promise.race([source.query({
87
+ groupBy: "session",
88
+ period,
89
+ limit: 1,
90
+ toolLimit: limit,
91
+ filter: { sessionId }
92
+ }), new Promise((_resolve, reject) => {
93
+ onAbort = () => reject(signal.reason);
94
+ signal.addEventListener("abort", onAbort, { once: true });
95
+ if (signal.aborted) onAbort();
96
+ })]);
97
+ signal.throwIfAborted();
98
+ if (!Check(scopedMetricsSchema, report) || report.filters.sessionId !== sessionId || report.period !== period || report.groups.some((group) => group.sessionId !== sessionId)) return {
99
+ evidence: "unavailable",
100
+ code: "METRICS_SCOPE_NOT_CONFIRMED",
101
+ scope: "current-session",
102
+ period
103
+ };
104
+ const totals = report.totals;
105
+ return {
106
+ scope: "current-session",
107
+ period,
108
+ evidence: totals.totalRecords === 0 ? "empty" : "available",
109
+ transport: source.lastTransport(),
110
+ capturedRecords: totals.totalRecords,
111
+ capturedIssues: totals.issueCount,
112
+ issuesByCategory: Object.fromEntries(AGENT_ISSUE_CATEGORIES.map((category) => [category, report.groups[0]?.byCategory[category] ?? 0])),
113
+ usage: {
114
+ inputTokens: totals.inputTokens,
115
+ outputTokens: totals.outputTokens,
116
+ totalTokens: totals.totalTokens,
117
+ cachedInputTokens: totals.cachedInputTokens,
118
+ reasoningOutputTokens: totals.reasoningOutputTokens,
119
+ usageEventCount: totals.usageEventCount,
120
+ tokenCoveragePercent: totals.tokenCoveragePercent
121
+ },
122
+ tools: report.tools.rows.slice(0, limit).map((tool) => ({
123
+ name: tool.toolName,
124
+ invocations: tool.invocationCount,
125
+ sampledTurns: tool.toolCallTurn.samples,
126
+ averageTurnTokens: tool.toolCallTurn.avgTotalTokens,
127
+ p90TurnTokens: tool.toolCallTurn.p90TotalTokens
128
+ })),
129
+ toolRowLimit: limit,
130
+ limitReached: report.tools.rows.length >= limit,
131
+ captureCompleteness: "not-reported",
132
+ 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 doompi-debug-agent for deeper authorized investigation."
133
+ };
134
+ } catch (error) {
135
+ if (signal.aborted) throw error;
136
+ return {
137
+ evidence: "unavailable",
138
+ code: "METRICS_UNAVAILABLE",
139
+ scope: "current-session",
140
+ period
141
+ };
142
+ } finally {
143
+ signal.removeEventListener("abort", onAbort);
144
+ }
145
+ }
146
+ function createAgentDiagnosticsTool(readScope, authorize) {
147
+ return defineTool({
148
+ name: DIAGNOSE_AGENT_NAME,
149
+ description: DIAGNOSE_AGENT_DESCRIPTION,
150
+ parameters: agentDiagnosticParameters,
151
+ when: DOOM_HELP_WHEN,
152
+ executionMode: "serial",
153
+ async execute(input, execution) {
154
+ const active = authorize(execution.signal);
155
+ const signal = AbortSignal.any([active, AbortSignal.timeout(AGENT_DIAGNOSTIC_TIMEOUT_MS)]);
156
+ const scope = readScope();
157
+ if (!scope.sessionId) throw new Error("Agent diagnostics require an active session.");
158
+ const source = createMetricsSource({
159
+ packageName: PACKAGE_NAME,
160
+ serviceName: "pi",
161
+ ...scope.options
162
+ });
163
+ try {
164
+ const report = await readAgentDiagnostics(source, scope.sessionId, input, signal);
165
+ signal.throwIfAborted();
166
+ authorize(execution.signal);
167
+ return {
168
+ content: [{
169
+ type: "text",
170
+ text: JSON.stringify(report, null, 2)
171
+ }],
172
+ details: report
173
+ };
174
+ } finally {
175
+ await source.close?.();
176
+ }
177
+ }
178
+ });
179
+ }
180
+ //#endregion
181
+ export { AGENT_DIAGNOSTIC_SKILL as n, DIAGNOSE_AGENT_NAME as r, createAgentDiagnosticsTool as t };
182
+
183
+ //# sourceMappingURL=agentDiagnostics-C2KgHmsD.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentDiagnostics-C2KgHmsD.mjs","names":["HELP_WHEN"],"sources":["../src/constants/diagnostics.ts","../src/schemas/agentDiagnostics.ts","../src/services/agentDiagnostics/index.ts"],"sourcesContent":["export const DIAGNOSE_AGENT_NAME = 'diagnose_agent';\nexport const DIAGNOSE_AGENT_DESCRIPTION =\n 'Inspect captured failures and token usage for the current DoomPi session. Read-only, bounded to the last day or week; omits prompts, tool arguments, credentials, and unrelated sessions.';\nexport const AGENT_DIAGNOSTIC_TOOL_LIMIT = 10;\nexport const AGENT_DIAGNOSTIC_MAX_TOOLS = 20;\nexport const AGENT_DIAGNOSTIC_TIMEOUT_MS = 15_000;\nexport const AGENT_ISSUE_CATEGORIES = [\n 'tool_failure',\n 'infrastructure_failure',\n 'caller_error',\n 'expected_failure',\n 'page_state',\n 'api_error',\n 'api_refusal',\n 'api_retries_exhausted',\n 'tool_rejected',\n 'log_error',\n] as const;\nexport const AGENT_DIAGNOSTIC_SKILL = {\n name: 'doompi-debug-agent',\n description:\n 'Debug a DoomPi 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.',\n} as const;\n","import { Type } from 'typebox';\n\nimport { AGENT_DIAGNOSTIC_MAX_TOOLS } from '../constants/diagnostics';\n\nconst count = Type.Number({ minimum: 0 });\nconst coverage = Type.Number({ minimum: 0, maximum: 100 });\nexport const agentDiagnosticParameters = Type.Object(\n {\n period: Type.Optional(Type.Union([Type.Literal('day'), Type.Literal('week')])),\n toolLimit: Type.Optional(Type.Integer({ minimum: 1, maximum: AGENT_DIAGNOSTIC_MAX_TOOLS })),\n },\n { additionalProperties: false },\n);\n\n/** Validate only the fields we return. Extra upstream fields never cross this boundary. */\nexport const scopedMetricsSchema = Type.Object({\n groupBy: Type.Literal('session'),\n period: Type.Union([Type.Literal('day'), Type.Literal('week')]),\n filters: Type.Object({ sessionId: Type.String({ minLength: 1 }) }),\n totals: Type.Object({\n totalRecords: count,\n issueCount: count,\n usageEventCount: count,\n inputTokens: count,\n outputTokens: count,\n totalTokens: count,\n cachedInputTokens: count,\n reasoningOutputTokens: count,\n tokenCoveragePercent: coverage,\n }),\n groups: Type.Array(\n Type.Object({\n sessionId: Type.String({ minLength: 1 }),\n byCategory: Type.Record(Type.String(), count),\n }),\n { maxItems: 1 },\n ),\n tools: Type.Object({\n returnedTools: count,\n rows: Type.Array(\n Type.Object({\n toolName: Type.String({ minLength: 1, maxLength: 128, pattern: '^[A-Za-z0-9_./:-]+$' }),\n invocationCount: count,\n toolCallTurn: Type.Object({ samples: count, avgTotalTokens: count, p90TotalTokens: count }),\n }),\n { maxItems: AGENT_DIAGNOSTIC_MAX_TOOLS },\n ),\n }),\n});\n","import { DOOM_HELP_WHEN as HELP_WHEN } from '@agimon-ai/doompi-core/help';\nimport { defineTool } from '@agimon-ai/doompi-core/piExtension';\nimport type { Static } from 'typebox';\nimport { Check } from 'typebox/value';\n\nimport {\n AGENT_DIAGNOSTIC_TIMEOUT_MS,\n AGENT_DIAGNOSTIC_TOOL_LIMIT,\n AGENT_ISSUE_CATEGORIES,\n DIAGNOSE_AGENT_DESCRIPTION,\n DIAGNOSE_AGENT_NAME,\n} from '../../constants/diagnostics';\nimport { PACKAGE_NAME, SERVICE_NAME } from '../../constants/telemetry';\nimport { agentDiagnosticParameters, scopedMetricsSchema } from '../../schemas/agentDiagnostics';\nimport type { MetricsSource } from '../../types/metricsSource';\nimport { createMetricsSource, type MetricsSourceOptions } from '../metricsSource';\n\nexport async function readAgentDiagnostics(\n source: MetricsSource,\n sessionId: string,\n input: Static<typeof agentDiagnosticParameters>,\n signal: AbortSignal,\n) {\n const period = input.period ?? 'day';\n const limit = input.toolLimit ?? AGENT_DIAGNOSTIC_TOOL_LIMIT;\n signal.throwIfAborted();\n let onAbort = () => {};\n try {\n const report: unknown = await Promise.race([\n source.query({ groupBy: 'session', period, limit: 1, toolLimit: limit, filter: { sessionId } }),\n new Promise<never>((_resolve, reject) => {\n onAbort = () => reject(signal.reason);\n signal.addEventListener('abort', onAbort, { once: true });\n if (signal.aborted) onAbort();\n }),\n ]);\n signal.throwIfAborted();\n if (\n !Check(scopedMetricsSchema, report) ||\n report.filters.sessionId !== sessionId ||\n report.period !== period ||\n report.groups.some((group) => group.sessionId !== sessionId)\n ) {\n return { evidence: 'unavailable', code: 'METRICS_SCOPE_NOT_CONFIRMED', scope: 'current-session', period };\n }\n const totals = report.totals;\n return {\n scope: 'current-session',\n period,\n evidence: totals.totalRecords === 0 ? 'empty' : 'available',\n transport: source.lastTransport(),\n capturedRecords: totals.totalRecords,\n capturedIssues: totals.issueCount,\n issuesByCategory: Object.fromEntries(\n AGENT_ISSUE_CATEGORIES.map((category) => [category, report.groups[0]?.byCategory[category] ?? 0]),\n ),\n usage: {\n inputTokens: totals.inputTokens,\n outputTokens: totals.outputTokens,\n totalTokens: totals.totalTokens,\n cachedInputTokens: totals.cachedInputTokens,\n reasoningOutputTokens: totals.reasoningOutputTokens,\n usageEventCount: totals.usageEventCount,\n tokenCoveragePercent: totals.tokenCoveragePercent,\n },\n tools: report.tools.rows.slice(0, limit).map((tool) => ({\n name: tool.toolName,\n invocations: tool.invocationCount,\n sampledTurns: tool.toolCallTurn.samples,\n averageTurnTokens: tool.toolCallTurn.avgTotalTokens,\n p90TurnTokens: tool.toolCallTurn.p90TotalTokens,\n })),\n toolRowLimit: limit,\n limitReached: report.tools.rows.length >= limit,\n captureCompleteness: 'not-reported',\n limitations:\n '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 doompi-debug-agent for deeper authorized investigation.',\n };\n } catch (error) {\n if (signal.aborted) throw error;\n return { evidence: 'unavailable', code: 'METRICS_UNAVAILABLE', scope: 'current-session', period };\n } finally {\n signal.removeEventListener('abort', onAbort);\n }\n}\n\nexport function createAgentDiagnosticsTool(\n readScope: () => { sessionId: string; options: MetricsSourceOptions },\n authorize: (signal?: AbortSignal) => AbortSignal,\n) {\n return defineTool({\n name: DIAGNOSE_AGENT_NAME,\n description: DIAGNOSE_AGENT_DESCRIPTION,\n parameters: agentDiagnosticParameters,\n when: HELP_WHEN,\n executionMode: 'serial',\n async execute(input, execution) {\n const active = authorize(execution.signal);\n const signal = AbortSignal.any([active, AbortSignal.timeout(AGENT_DIAGNOSTIC_TIMEOUT_MS)]);\n const scope = readScope();\n if (!scope.sessionId) throw new Error('Agent diagnostics require an active session.');\n const source = createMetricsSource({ packageName: PACKAGE_NAME, serviceName: SERVICE_NAME, ...scope.options });\n try {\n const report = await readAgentDiagnostics(source, scope.sessionId, input, signal);\n signal.throwIfAborted();\n authorize(execution.signal);\n return { content: [{ type: 'text', text: JSON.stringify(report, null, 2) }], details: report };\n } finally {\n await source.close?.();\n }\n },\n });\n}\n"],"mappings":"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"}
@@ -0,0 +1,200 @@
1
+ const require_telemetryEnabled = require("./telemetryEnabled-BJ2BKyps.cjs");
2
+ const require_metricsSource = require("./metricsSource-DdwQNzoY.cjs");
3
+ let _agimon_ai_doompi_core_piExtension = require("@agimon-ai/doompi-core/piExtension");
4
+ let _agimon_ai_doompi_core_help = require("@agimon-ai/doompi-core/help");
5
+ let typebox_value = require("typebox/value");
6
+ let typebox = require("typebox");
7
+ //#region src/constants/diagnostics.ts
8
+ const DIAGNOSE_AGENT_NAME = "diagnose_agent";
9
+ const DIAGNOSE_AGENT_DESCRIPTION = "Inspect captured failures and token usage for the current DoomPi session. Read-only, bounded to the last day or week; omits prompts, tool arguments, credentials, and unrelated sessions.";
10
+ const AGENT_DIAGNOSTIC_TIMEOUT_MS = 15e3;
11
+ const AGENT_ISSUE_CATEGORIES = [
12
+ "tool_failure",
13
+ "infrastructure_failure",
14
+ "caller_error",
15
+ "expected_failure",
16
+ "page_state",
17
+ "api_error",
18
+ "api_refusal",
19
+ "api_retries_exhausted",
20
+ "tool_rejected",
21
+ "log_error"
22
+ ];
23
+ const AGENT_DIAGNOSTIC_SKILL = {
24
+ name: "doompi-debug-agent",
25
+ description: "Debug a DoomPi 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."
26
+ };
27
+ //#endregion
28
+ //#region src/schemas/agentDiagnostics.ts
29
+ const count = typebox.Type.Number({ minimum: 0 });
30
+ const coverage = typebox.Type.Number({
31
+ minimum: 0,
32
+ maximum: 100
33
+ });
34
+ const agentDiagnosticParameters = typebox.Type.Object({
35
+ period: typebox.Type.Optional(typebox.Type.Union([typebox.Type.Literal("day"), typebox.Type.Literal("week")])),
36
+ toolLimit: typebox.Type.Optional(typebox.Type.Integer({
37
+ minimum: 1,
38
+ maximum: 20
39
+ }))
40
+ }, { additionalProperties: false });
41
+ /** Validate only the fields we return. Extra upstream fields never cross this boundary. */
42
+ const scopedMetricsSchema = typebox.Type.Object({
43
+ groupBy: typebox.Type.Literal("session"),
44
+ period: typebox.Type.Union([typebox.Type.Literal("day"), typebox.Type.Literal("week")]),
45
+ filters: typebox.Type.Object({ sessionId: typebox.Type.String({ minLength: 1 }) }),
46
+ totals: typebox.Type.Object({
47
+ totalRecords: count,
48
+ issueCount: count,
49
+ usageEventCount: count,
50
+ inputTokens: count,
51
+ outputTokens: count,
52
+ totalTokens: count,
53
+ cachedInputTokens: count,
54
+ reasoningOutputTokens: count,
55
+ tokenCoveragePercent: coverage
56
+ }),
57
+ groups: typebox.Type.Array(typebox.Type.Object({
58
+ sessionId: typebox.Type.String({ minLength: 1 }),
59
+ byCategory: typebox.Type.Record(typebox.Type.String(), count)
60
+ }), { maxItems: 1 }),
61
+ tools: typebox.Type.Object({
62
+ returnedTools: count,
63
+ rows: typebox.Type.Array(typebox.Type.Object({
64
+ toolName: typebox.Type.String({
65
+ minLength: 1,
66
+ maxLength: 128,
67
+ pattern: "^[A-Za-z0-9_./:-]+$"
68
+ }),
69
+ invocationCount: count,
70
+ toolCallTurn: typebox.Type.Object({
71
+ samples: count,
72
+ avgTotalTokens: count,
73
+ p90TotalTokens: count
74
+ })
75
+ }), { maxItems: 20 })
76
+ })
77
+ });
78
+ //#endregion
79
+ //#region src/services/agentDiagnostics/index.ts
80
+ async function readAgentDiagnostics(source, sessionId, input, signal) {
81
+ const period = input.period ?? "day";
82
+ const limit = input.toolLimit ?? 10;
83
+ signal.throwIfAborted();
84
+ let onAbort = () => {};
85
+ try {
86
+ const report = await Promise.race([source.query({
87
+ groupBy: "session",
88
+ period,
89
+ limit: 1,
90
+ toolLimit: limit,
91
+ filter: { sessionId }
92
+ }), new Promise((_resolve, reject) => {
93
+ onAbort = () => reject(signal.reason);
94
+ signal.addEventListener("abort", onAbort, { once: true });
95
+ if (signal.aborted) onAbort();
96
+ })]);
97
+ signal.throwIfAborted();
98
+ if (!(0, typebox_value.Check)(scopedMetricsSchema, report) || report.filters.sessionId !== sessionId || report.period !== period || report.groups.some((group) => group.sessionId !== sessionId)) return {
99
+ evidence: "unavailable",
100
+ code: "METRICS_SCOPE_NOT_CONFIRMED",
101
+ scope: "current-session",
102
+ period
103
+ };
104
+ const totals = report.totals;
105
+ return {
106
+ scope: "current-session",
107
+ period,
108
+ evidence: totals.totalRecords === 0 ? "empty" : "available",
109
+ transport: source.lastTransport(),
110
+ capturedRecords: totals.totalRecords,
111
+ capturedIssues: totals.issueCount,
112
+ issuesByCategory: Object.fromEntries(AGENT_ISSUE_CATEGORIES.map((category) => [category, report.groups[0]?.byCategory[category] ?? 0])),
113
+ usage: {
114
+ inputTokens: totals.inputTokens,
115
+ outputTokens: totals.outputTokens,
116
+ totalTokens: totals.totalTokens,
117
+ cachedInputTokens: totals.cachedInputTokens,
118
+ reasoningOutputTokens: totals.reasoningOutputTokens,
119
+ usageEventCount: totals.usageEventCount,
120
+ tokenCoveragePercent: totals.tokenCoveragePercent
121
+ },
122
+ tools: report.tools.rows.slice(0, limit).map((tool) => ({
123
+ name: tool.toolName,
124
+ invocations: tool.invocationCount,
125
+ sampledTurns: tool.toolCallTurn.samples,
126
+ averageTurnTokens: tool.toolCallTurn.avgTotalTokens,
127
+ p90TurnTokens: tool.toolCallTurn.p90TotalTokens
128
+ })),
129
+ toolRowLimit: limit,
130
+ limitReached: report.tools.rows.length >= limit,
131
+ captureCompleteness: "not-reported",
132
+ 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 doompi-debug-agent for deeper authorized investigation."
133
+ };
134
+ } catch (error) {
135
+ if (signal.aborted) throw error;
136
+ return {
137
+ evidence: "unavailable",
138
+ code: "METRICS_UNAVAILABLE",
139
+ scope: "current-session",
140
+ period
141
+ };
142
+ } finally {
143
+ signal.removeEventListener("abort", onAbort);
144
+ }
145
+ }
146
+ function createAgentDiagnosticsTool(readScope, authorize) {
147
+ return (0, _agimon_ai_doompi_core_piExtension.defineTool)({
148
+ name: DIAGNOSE_AGENT_NAME,
149
+ description: DIAGNOSE_AGENT_DESCRIPTION,
150
+ parameters: agentDiagnosticParameters,
151
+ when: _agimon_ai_doompi_core_help.DOOM_HELP_WHEN,
152
+ executionMode: "serial",
153
+ async execute(input, execution) {
154
+ const active = authorize(execution.signal);
155
+ const signal = AbortSignal.any([active, AbortSignal.timeout(AGENT_DIAGNOSTIC_TIMEOUT_MS)]);
156
+ const scope = readScope();
157
+ if (!scope.sessionId) throw new Error("Agent diagnostics require an active session.");
158
+ const source = require_metricsSource.createMetricsSource({
159
+ packageName: require_telemetryEnabled.PACKAGE_NAME,
160
+ serviceName: "pi",
161
+ ...scope.options
162
+ });
163
+ try {
164
+ const report = await readAgentDiagnostics(source, scope.sessionId, input, signal);
165
+ signal.throwIfAborted();
166
+ authorize(execution.signal);
167
+ return {
168
+ content: [{
169
+ type: "text",
170
+ text: JSON.stringify(report, null, 2)
171
+ }],
172
+ details: report
173
+ };
174
+ } finally {
175
+ await source.close?.();
176
+ }
177
+ }
178
+ });
179
+ }
180
+ //#endregion
181
+ Object.defineProperty(exports, "AGENT_DIAGNOSTIC_SKILL", {
182
+ enumerable: true,
183
+ get: function() {
184
+ return AGENT_DIAGNOSTIC_SKILL;
185
+ }
186
+ });
187
+ Object.defineProperty(exports, "DIAGNOSE_AGENT_NAME", {
188
+ enumerable: true,
189
+ get: function() {
190
+ return DIAGNOSE_AGENT_NAME;
191
+ }
192
+ });
193
+ Object.defineProperty(exports, "createAgentDiagnosticsTool", {
194
+ enumerable: true,
195
+ get: function() {
196
+ return createAgentDiagnosticsTool;
197
+ }
198
+ });
199
+
200
+ //# sourceMappingURL=agentDiagnostics-XrO2jPyN.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentDiagnostics-XrO2jPyN.cjs","names":["Type","Check","defineTool","HELP_WHEN","createMetricsSource","PACKAGE_NAME"],"sources":["../src/constants/diagnostics.ts","../src/schemas/agentDiagnostics.ts","../src/services/agentDiagnostics/index.ts"],"sourcesContent":["export const DIAGNOSE_AGENT_NAME = 'diagnose_agent';\nexport const DIAGNOSE_AGENT_DESCRIPTION =\n 'Inspect captured failures and token usage for the current DoomPi session. Read-only, bounded to the last day or week; omits prompts, tool arguments, credentials, and unrelated sessions.';\nexport const AGENT_DIAGNOSTIC_TOOL_LIMIT = 10;\nexport const AGENT_DIAGNOSTIC_MAX_TOOLS = 20;\nexport const AGENT_DIAGNOSTIC_TIMEOUT_MS = 15_000;\nexport const AGENT_ISSUE_CATEGORIES = [\n 'tool_failure',\n 'infrastructure_failure',\n 'caller_error',\n 'expected_failure',\n 'page_state',\n 'api_error',\n 'api_refusal',\n 'api_retries_exhausted',\n 'tool_rejected',\n 'log_error',\n] as const;\nexport const AGENT_DIAGNOSTIC_SKILL = {\n name: 'doompi-debug-agent',\n description:\n 'Debug a DoomPi 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.',\n} as const;\n","import { Type } from 'typebox';\n\nimport { AGENT_DIAGNOSTIC_MAX_TOOLS } from '../constants/diagnostics';\n\nconst count = Type.Number({ minimum: 0 });\nconst coverage = Type.Number({ minimum: 0, maximum: 100 });\nexport const agentDiagnosticParameters = Type.Object(\n {\n period: Type.Optional(Type.Union([Type.Literal('day'), Type.Literal('week')])),\n toolLimit: Type.Optional(Type.Integer({ minimum: 1, maximum: AGENT_DIAGNOSTIC_MAX_TOOLS })),\n },\n { additionalProperties: false },\n);\n\n/** Validate only the fields we return. Extra upstream fields never cross this boundary. */\nexport const scopedMetricsSchema = Type.Object({\n groupBy: Type.Literal('session'),\n period: Type.Union([Type.Literal('day'), Type.Literal('week')]),\n filters: Type.Object({ sessionId: Type.String({ minLength: 1 }) }),\n totals: Type.Object({\n totalRecords: count,\n issueCount: count,\n usageEventCount: count,\n inputTokens: count,\n outputTokens: count,\n totalTokens: count,\n cachedInputTokens: count,\n reasoningOutputTokens: count,\n tokenCoveragePercent: coverage,\n }),\n groups: Type.Array(\n Type.Object({\n sessionId: Type.String({ minLength: 1 }),\n byCategory: Type.Record(Type.String(), count),\n }),\n { maxItems: 1 },\n ),\n tools: Type.Object({\n returnedTools: count,\n rows: Type.Array(\n Type.Object({\n toolName: Type.String({ minLength: 1, maxLength: 128, pattern: '^[A-Za-z0-9_./:-]+$' }),\n invocationCount: count,\n toolCallTurn: Type.Object({ samples: count, avgTotalTokens: count, p90TotalTokens: count }),\n }),\n { maxItems: AGENT_DIAGNOSTIC_MAX_TOOLS },\n ),\n }),\n});\n","import { DOOM_HELP_WHEN as HELP_WHEN } from '@agimon-ai/doompi-core/help';\nimport { defineTool } from '@agimon-ai/doompi-core/piExtension';\nimport type { Static } from 'typebox';\nimport { Check } from 'typebox/value';\n\nimport {\n AGENT_DIAGNOSTIC_TIMEOUT_MS,\n AGENT_DIAGNOSTIC_TOOL_LIMIT,\n AGENT_ISSUE_CATEGORIES,\n DIAGNOSE_AGENT_DESCRIPTION,\n DIAGNOSE_AGENT_NAME,\n} from '../../constants/diagnostics';\nimport { PACKAGE_NAME, SERVICE_NAME } from '../../constants/telemetry';\nimport { agentDiagnosticParameters, scopedMetricsSchema } from '../../schemas/agentDiagnostics';\nimport type { MetricsSource } from '../../types/metricsSource';\nimport { createMetricsSource, type MetricsSourceOptions } from '../metricsSource';\n\nexport async function readAgentDiagnostics(\n source: MetricsSource,\n sessionId: string,\n input: Static<typeof agentDiagnosticParameters>,\n signal: AbortSignal,\n) {\n const period = input.period ?? 'day';\n const limit = input.toolLimit ?? AGENT_DIAGNOSTIC_TOOL_LIMIT;\n signal.throwIfAborted();\n let onAbort = () => {};\n try {\n const report: unknown = await Promise.race([\n source.query({ groupBy: 'session', period, limit: 1, toolLimit: limit, filter: { sessionId } }),\n new Promise<never>((_resolve, reject) => {\n onAbort = () => reject(signal.reason);\n signal.addEventListener('abort', onAbort, { once: true });\n if (signal.aborted) onAbort();\n }),\n ]);\n signal.throwIfAborted();\n if (\n !Check(scopedMetricsSchema, report) ||\n report.filters.sessionId !== sessionId ||\n report.period !== period ||\n report.groups.some((group) => group.sessionId !== sessionId)\n ) {\n return { evidence: 'unavailable', code: 'METRICS_SCOPE_NOT_CONFIRMED', scope: 'current-session', period };\n }\n const totals = report.totals;\n return {\n scope: 'current-session',\n period,\n evidence: totals.totalRecords === 0 ? 'empty' : 'available',\n transport: source.lastTransport(),\n capturedRecords: totals.totalRecords,\n capturedIssues: totals.issueCount,\n issuesByCategory: Object.fromEntries(\n AGENT_ISSUE_CATEGORIES.map((category) => [category, report.groups[0]?.byCategory[category] ?? 0]),\n ),\n usage: {\n inputTokens: totals.inputTokens,\n outputTokens: totals.outputTokens,\n totalTokens: totals.totalTokens,\n cachedInputTokens: totals.cachedInputTokens,\n reasoningOutputTokens: totals.reasoningOutputTokens,\n usageEventCount: totals.usageEventCount,\n tokenCoveragePercent: totals.tokenCoveragePercent,\n },\n tools: report.tools.rows.slice(0, limit).map((tool) => ({\n name: tool.toolName,\n invocations: tool.invocationCount,\n sampledTurns: tool.toolCallTurn.samples,\n averageTurnTokens: tool.toolCallTurn.avgTotalTokens,\n p90TurnTokens: tool.toolCallTurn.p90TotalTokens,\n })),\n toolRowLimit: limit,\n limitReached: report.tools.rows.length >= limit,\n captureCompleteness: 'not-reported',\n limitations:\n '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 doompi-debug-agent for deeper authorized investigation.',\n };\n } catch (error) {\n if (signal.aborted) throw error;\n return { evidence: 'unavailable', code: 'METRICS_UNAVAILABLE', scope: 'current-session', period };\n } finally {\n signal.removeEventListener('abort', onAbort);\n }\n}\n\nexport function createAgentDiagnosticsTool(\n readScope: () => { sessionId: string; options: MetricsSourceOptions },\n authorize: (signal?: AbortSignal) => AbortSignal,\n) {\n return defineTool({\n name: DIAGNOSE_AGENT_NAME,\n description: DIAGNOSE_AGENT_DESCRIPTION,\n parameters: agentDiagnosticParameters,\n when: HELP_WHEN,\n executionMode: 'serial',\n async execute(input, execution) {\n const active = authorize(execution.signal);\n const signal = AbortSignal.any([active, AbortSignal.timeout(AGENT_DIAGNOSTIC_TIMEOUT_MS)]);\n const scope = readScope();\n if (!scope.sessionId) throw new Error('Agent diagnostics require an active session.');\n const source = createMetricsSource({ packageName: PACKAGE_NAME, serviceName: SERVICE_NAME, ...scope.options });\n try {\n const report = await readAgentDiagnostics(source, scope.sessionId, input, signal);\n signal.throwIfAborted();\n authorize(execution.signal);\n return { content: [{ type: 'text', text: JSON.stringify(report, null, 2) }], details: report };\n } finally {\n await source.close?.();\n }\n },\n });\n}\n"],"mappings":"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"}
@@ -4,8 +4,11 @@ Object.defineProperties(exports, {
4
4
  });
5
5
  const require_telemetryEnabled = require("../telemetryEnabled-BJ2BKyps.cjs");
6
6
  const require_logRuntime = require("../logRuntime-DcD32EjA.cjs");
7
+ const require_agentDiagnostics = require("../agentDiagnostics-XrO2jPyN.cjs");
7
8
  let _agimon_ai_doompi_core_piExtension = require("@agimon-ai/doompi-core/piExtension");
8
9
  let _agimon_ai_doompi_core_extensionFile = require("@agimon-ai/doompi-core/extensionFile");
10
+ let _agimon_ai_doompi_core_cordisHost = require("@agimon-ai/doompi-core/cordisHost");
11
+ let _agimon_ai_doompi_core_help = require("@agimon-ai/doompi-core/help");
9
12
  let _agimon_ai_doompi_core_readiness = require("@agimon-ai/doompi-core/readiness");
10
13
  let _agimon_ai_doompi_telemetry = require("@agimon-ai/doompi-telemetry");
11
14
  //#region src/services/piTelemetry/index.ts
@@ -341,13 +344,40 @@ const createLogPiRoot = ({ context, options }) => {
341
344
  const view = require_logRuntime.createLogViewRuntime((ctx) => telemetry.waitForSession(ctx), options);
342
345
  telemetry = createPiTelemetryRuntime(context, view.telemetryOptions, true);
343
346
  let shutdown;
347
+ const gate = (0, _agimon_ai_doompi_core_help.createPiHelpToolGate)(require_telemetryEnabled.PACKAGE_NAME, [require_agentDiagnostics.DIAGNOSE_AGENT_NAME]);
348
+ let session;
349
+ const bindSession = (cordis) => {
350
+ cordis.inject([_agimon_ai_doompi_core_cordisHost.DOOM_CORDIS_SESSION_SERVICE], (child) => {
351
+ const current = (0, _agimon_ai_doompi_core_cordisHost.requireDoomCordisSession)(child);
352
+ session = current;
353
+ return () => {
354
+ if (session === current) session = void 0;
355
+ };
356
+ });
357
+ };
344
358
  return {
345
359
  value: {
346
360
  telemetry,
347
361
  view,
362
+ diagnosticTool: require_agentDiagnostics.createAgentDiagnosticsTool(() => {
363
+ if (!session) throw new Error("Agent diagnostics require the current session.");
364
+ return {
365
+ sessionId: session.sessionId,
366
+ options: {
367
+ cwd: session.context.cwd,
368
+ env: { ...options?.env ?? process.env },
369
+ serviceName: options?.serviceName ?? "pi"
370
+ }
371
+ };
372
+ }, (signal) => gate.assertActive(require_agentDiagnostics.DIAGNOSE_AGENT_NAME, signal)),
348
373
  sessionShutdown: (event, ctx) => shutdown ??= telemetry.finishSession(event.reason, ctx)
349
374
  },
350
- services: view.services,
375
+ services: [
376
+ ...gate.services,
377
+ bindSession,
378
+ ...view.services
379
+ ],
380
+ onStart: gate.onStart,
351
381
  async onDispose() {
352
382
  await view.onDispose();
353
383
  await telemetry.onDispose();
@@ -397,12 +427,26 @@ var turn_end_cli_default = (0, _agimon_ai_doompi_core_extensionFile.defineCliHoo
397
427
  //#region src/extensions/workspaces/sessions/(backend)/hook/turn-start.cli.ts
398
428
  var turn_start_cli_default = (0, _agimon_ai_doompi_core_extensionFile.defineCliHook)((context) => context.root.telemetry.events.turn_start);
399
429
  //#endregion
430
+ //#region src/extensions/workspaces/sessions/(backend)/resource/doompi-debug-agent.cli.ts
431
+ var doompi_debug_agent_cli_default = (0, _agimon_ai_doompi_core_extensionFile.defineResource)({
432
+ source: require_telemetryEnabled.PACKAGE_NAME,
433
+ moduleUrl: require("url").pathToFileURL(__filename).href,
434
+ skills: [require_agentDiagnostics.AGENT_DIAGNOSTIC_SKILL]
435
+ });
436
+ //#endregion
437
+ //#region src/extensions/workspaces/sessions/(backend)/tool/diagnose_agent.cli.ts
438
+ var diagnose_agent_cli_default = (0, _agimon_ai_doompi_core_extensionFile.defineTool)((context) => context.root.diagnosticTool);
439
+ //#endregion
400
440
  //#region generated/pi.ts
401
441
  const at = (value, context) => typeof value === "function" ? value(context) : value;
402
442
  const many = (value, context) => {
403
443
  const resolved = typeof value === "function" ? value(context) : value;
404
444
  return Array.isArray(resolved) ? resolved : [resolved];
405
445
  };
446
+ const via = (identity, value) => value === void 0 ? void 0 : {
447
+ ...identity,
448
+ ...value
449
+ };
406
450
  const extension = (0, _agimon_ai_doompi_core_piExtension.definePiExtension)("@agimon-ai/doompi-log", async (context) => {
407
451
  const scopeSession = await root_cli_default(context);
408
452
  const contextSession = {
@@ -428,6 +472,10 @@ const extension = (0, _agimon_ai_doompi_core_piExtension.definePiExtension)("@ag
428
472
  turn_end: at(turn_end_cli_default, contextSession),
429
473
  turn_start: at(turn_start_cli_default, contextSession)
430
474
  },
475
+ get resources() {
476
+ return [at(doompi_debug_agent_cli_default, contextSession)];
477
+ },
478
+ ...(0, _agimon_ai_doompi_core_piExtension.piToolContributions)("@agimon-ai/doompi-log", [via({ name: "diagnose_agent" }, at(diagnose_agent_cli_default, contextSession))]),
431
479
  services: [...scopeSession.services ?? []]
432
480
  };
433
481
  });