@cat-factory/orchestration 0.159.2 → 0.161.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.
- package/dist/container/dependencies.d.ts +16 -1
- package/dist/container/dependencies.d.ts.map +1 -1
- package/dist/container/platform-modules.d.ts.map +1 -1
- package/dist/container/platform-modules.js +15 -0
- package/dist/container/platform-modules.js.map +1 -1
- package/dist/container.d.ts +7 -0
- package/dist/container.d.ts.map +1 -1
- package/dist/container.js +1 -0
- package/dist/container.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/dist/modules/debug/RunDebugService.d.ts +96 -0
- package/dist/modules/debug/RunDebugService.d.ts.map +1 -0
- package/dist/modules/debug/RunDebugService.js +190 -0
- package/dist/modules/debug/RunDebugService.js.map +1 -0
- package/dist/modules/debug/debug.logic.d.ts +104 -0
- package/dist/modules/debug/debug.logic.d.ts.map +1 -0
- package/dist/modules/debug/debug.logic.js +403 -0
- package/dist/modules/debug/debug.logic.js.map +1 -0
- package/dist/modules/debug/promptMessages.d.ts +27 -0
- package/dist/modules/debug/promptMessages.d.ts.map +1 -0
- package/dist/modules/debug/promptMessages.js +165 -0
- package/dist/modules/debug/promptMessages.js.map +1 -0
- package/dist/modules/execution/RunStateMachine.d.ts +4 -0
- package/dist/modules/execution/RunStateMachine.d.ts.map +1 -1
- package/dist/modules/execution/RunStateMachine.js +31 -4
- package/dist/modules/execution/RunStateMachine.js.map +1 -1
- package/dist/modules/observability/observability.logic.d.ts +10 -0
- package/dist/modules/observability/observability.logic.d.ts.map +1 -1
- package/dist/modules/observability/observability.logic.js +1 -1
- package/dist/modules/observability/observability.logic.js.map +1 -1
- package/package.json +11 -11
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import { deriveSignals, foldLlmRollup, toDebugAgentContextDetail, toDebugAgentContextEntry, toDebugLlmCall, toDebugRunStep, toDebugRunSummary, } from './debug.logic.js';
|
|
2
|
+
import { toDebugLlmCallMessagesView } from './promptMessages.js';
|
|
3
|
+
/**
|
|
4
|
+
* Take one row more than the caller asked for, so "is there another page?" is answered by the
|
|
5
|
+
* query rather than by a second COUNT — and mint the next cursor from the LAST row actually
|
|
6
|
+
* returned, which is the row the next page must resume strictly after.
|
|
7
|
+
*/
|
|
8
|
+
function paginate(rows, limit, key, project) {
|
|
9
|
+
const hasMore = rows.length > limit;
|
|
10
|
+
const kept = hasMore ? rows.slice(0, limit) : rows;
|
|
11
|
+
const last = kept[kept.length - 1];
|
|
12
|
+
return {
|
|
13
|
+
items: kept.map(project),
|
|
14
|
+
// Never the PEEKED row: resuming strictly after it would skip it entirely.
|
|
15
|
+
nextCursor: hasMore && last ? key(last) : null,
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export class RunDebugService {
|
|
19
|
+
deps;
|
|
20
|
+
constructor(deps) {
|
|
21
|
+
this.deps = deps;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* One bounded page of the workspace's runs, newest first. The entry point for a client that
|
|
25
|
+
* holds no run id — "which of my runs failed in the last hour" — and the only read here that
|
|
26
|
+
* is not already scoped to a single run.
|
|
27
|
+
*/
|
|
28
|
+
async listRuns(workspaceId, opts) {
|
|
29
|
+
const rows = await this.deps.executionRepository.listRecent(workspaceId, {
|
|
30
|
+
limit: opts.limit + 1,
|
|
31
|
+
cursor: opts.cursor,
|
|
32
|
+
statuses: opts.status ? [opts.status] : undefined,
|
|
33
|
+
since: opts.since,
|
|
34
|
+
});
|
|
35
|
+
return paginate(rows, opts.limit, (run) => ({ createdAt: run.createdAt ?? 0, id: run.id }), toDebugRunSummary);
|
|
36
|
+
}
|
|
37
|
+
/** The run itself, or null when the workspace has no such run. */
|
|
38
|
+
getRun(workspaceId, runId) {
|
|
39
|
+
return this.deps.executionRepository.get(workspaceId, runId);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Whether the workspace has this run — the 404 guard the per-run detail lists apply on
|
|
43
|
+
* every page. A probe rather than {@link RunDebugService.getRun}: the guard discards the
|
|
44
|
+
* run, and `get` JSON-decodes the heaviest row in the request to answer a boolean.
|
|
45
|
+
*/
|
|
46
|
+
runExists(workspaceId, runId) {
|
|
47
|
+
return this.deps.executionRepository.exists(workspaceId, runId);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The run's diagnostic map. Composed from AGGREGATES ONLY — four counts and one GROUP BY,
|
|
51
|
+
* no prompt, response or context body — which is what makes it cheap enough to be the first
|
|
52
|
+
* call a debugging client always issues, and what lets its `sinks` block stop the caller
|
|
53
|
+
* issuing four detail requests to discover three of them are empty.
|
|
54
|
+
*
|
|
55
|
+
* Takes the already-loaded run rather than a run id: the caller has to load it anyway to
|
|
56
|
+
* decide whether the key may see it, and re-reading it here would be a second decode of the
|
|
57
|
+
* heaviest row in the request.
|
|
58
|
+
*/
|
|
59
|
+
async overview(workspaceId, execution) {
|
|
60
|
+
const runId = execution.id;
|
|
61
|
+
// Independent aggregates over four separate stores — issued together rather than in
|
|
62
|
+
// sequence, since the overview's whole value proposition is that it is one cheap call.
|
|
63
|
+
const [summaries, contextCount, searchCount, logCounts] = await Promise.all([
|
|
64
|
+
this.deps.llmCallMetricRepository?.summarizeByExecution(workspaceId, runId) ?? [],
|
|
65
|
+
this.deps.agentContextSnapshotRepository?.countByExecution(workspaceId, runId) ?? 0,
|
|
66
|
+
this.deps.agentSearchQueryRepository?.countByExecution(workspaceId, runId) ?? 0,
|
|
67
|
+
// Total + failures in one aggregate pass — the overview always wants both.
|
|
68
|
+
this.deps.provisioningLogRepository?.countByExecution(workspaceId, runId) ?? {
|
|
69
|
+
total: 0,
|
|
70
|
+
failures: 0,
|
|
71
|
+
},
|
|
72
|
+
]);
|
|
73
|
+
const { totals, byAgentKind, byPhase } = foldLlmRollup(summaries);
|
|
74
|
+
const steps = execution.steps.map(toDebugRunStep);
|
|
75
|
+
const sinks = {
|
|
76
|
+
// The LLM call count is FOLDED from the per-kind rollup rather than counted separately:
|
|
77
|
+
// the two would be the same COUNT over the same rows, and a second query could only
|
|
78
|
+
// disagree with the breakdown it sits next to.
|
|
79
|
+
llmCalls: { available: !!this.deps.llmCallMetricRepository, count: totals.calls },
|
|
80
|
+
agentContext: {
|
|
81
|
+
available: !!this.deps.agentContextSnapshotRepository,
|
|
82
|
+
count: contextCount,
|
|
83
|
+
},
|
|
84
|
+
searchQueries: { available: !!this.deps.agentSearchQueryRepository, count: searchCount },
|
|
85
|
+
provisioningLog: { available: !!this.deps.provisioningLogRepository, count: logCounts.total },
|
|
86
|
+
};
|
|
87
|
+
return {
|
|
88
|
+
kind: 'cat-factory.run-debug-overview',
|
|
89
|
+
version: 1,
|
|
90
|
+
generatedAt: this.deps.clock.now(),
|
|
91
|
+
run: toDebugRunSummary(execution),
|
|
92
|
+
steps,
|
|
93
|
+
diagnostics: execution.diagnostics ?? null,
|
|
94
|
+
sinks,
|
|
95
|
+
llm: { totals, byAgentKind, byPhase },
|
|
96
|
+
signals: deriveSignals({
|
|
97
|
+
execution,
|
|
98
|
+
steps,
|
|
99
|
+
totals,
|
|
100
|
+
byAgentKind,
|
|
101
|
+
sinks,
|
|
102
|
+
provisioningFailures: logCounts.failures,
|
|
103
|
+
}),
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/** One bounded page of the run's recorded model calls. */
|
|
107
|
+
async listLlmCalls(workspaceId, runId, opts) {
|
|
108
|
+
const repo = this.deps.llmCallMetricRepository;
|
|
109
|
+
if (!repo)
|
|
110
|
+
return { items: [], nextCursor: null };
|
|
111
|
+
const rows = await repo.listPage(workspaceId, {
|
|
112
|
+
executionId: runId,
|
|
113
|
+
limit: opts.limit + 1,
|
|
114
|
+
cursor: opts.cursor,
|
|
115
|
+
agentKind: opts.agentKind,
|
|
116
|
+
phase: opts.phase,
|
|
117
|
+
outcome: opts.outcome,
|
|
118
|
+
order: opts.order,
|
|
119
|
+
bodyChars: opts.bodyChars,
|
|
120
|
+
contains: opts.contains,
|
|
121
|
+
});
|
|
122
|
+
return paginate(rows, opts.limit, (call) => ({ createdAt: call.createdAt, id: call.id }), (call) => toDebugLlmCall(call));
|
|
123
|
+
}
|
|
124
|
+
/** One recorded call with its bodies windowed, or null when the workspace has no such call. */
|
|
125
|
+
async getLlmCall(workspaceId, callId, opts = {}) {
|
|
126
|
+
const repo = this.deps.llmCallMetricRepository;
|
|
127
|
+
if (!repo)
|
|
128
|
+
return null;
|
|
129
|
+
if (opts.view === 'messages') {
|
|
130
|
+
// The parse needs the COMPLETE delta (a truncated JSON array parses as nothing), so this
|
|
131
|
+
// view reads the row whole and windows in the projection instead of in SQL. That trades
|
|
132
|
+
// one whole-row transfer from the store — bounded by the store's own per-body cap — for a
|
|
133
|
+
// response whose messages are budgeted independently; the HTTP payload stays bounded
|
|
134
|
+
// either way.
|
|
135
|
+
const row = await repo.get(workspaceId, callId);
|
|
136
|
+
return row ? toDebugLlmCallMessagesView(row, opts.bodyChars ?? 0, opts.bodyOffset ?? 0) : null;
|
|
137
|
+
}
|
|
138
|
+
const row = await repo.get(workspaceId, callId, {
|
|
139
|
+
chars: opts.bodyChars,
|
|
140
|
+
offset: opts.bodyOffset,
|
|
141
|
+
});
|
|
142
|
+
return row ? toDebugLlmCall(row, opts.bodyOffset ?? 0) : null;
|
|
143
|
+
}
|
|
144
|
+
/** One bounded page of the run's captured dispatches — identity and sizes, never bodies. */
|
|
145
|
+
async listAgentContext(workspaceId, runId, opts) {
|
|
146
|
+
const repo = this.deps.agentContextSnapshotRepository;
|
|
147
|
+
if (!repo)
|
|
148
|
+
return { items: [], nextCursor: null };
|
|
149
|
+
const rows = await repo.listIndex(workspaceId, {
|
|
150
|
+
executionId: runId,
|
|
151
|
+
limit: opts.limit + 1,
|
|
152
|
+
cursor: opts.cursor,
|
|
153
|
+
stepIndex: opts.stepIndex,
|
|
154
|
+
});
|
|
155
|
+
return paginate(rows, opts.limit, (row) => ({ createdAt: row.createdAt, id: row.id }), toDebugAgentContextEntry);
|
|
156
|
+
}
|
|
157
|
+
/** One captured dispatch with every body budgeted independently. */
|
|
158
|
+
async getAgentContext(workspaceId, snapshotId, bodyChars, bodyOffset = 0) {
|
|
159
|
+
const repo = this.deps.agentContextSnapshotRepository;
|
|
160
|
+
if (!repo)
|
|
161
|
+
return null;
|
|
162
|
+
const snapshot = await repo.get(workspaceId, snapshotId);
|
|
163
|
+
return snapshot ? toDebugAgentContextDetail(snapshot, bodyChars, bodyOffset) : null;
|
|
164
|
+
}
|
|
165
|
+
/** One bounded page of the web searches the run's agents performed. */
|
|
166
|
+
async listSearchQueries(workspaceId, runId, opts) {
|
|
167
|
+
const repo = this.deps.agentSearchQueryRepository;
|
|
168
|
+
if (!repo)
|
|
169
|
+
return { items: [], nextCursor: null };
|
|
170
|
+
const rows = await repo.listPage(workspaceId, {
|
|
171
|
+
executionId: runId,
|
|
172
|
+
limit: opts.limit + 1,
|
|
173
|
+
cursor: opts.cursor,
|
|
174
|
+
});
|
|
175
|
+
return paginate(rows, opts.limit, (row) => ({ createdAt: row.createdAt, id: row.id }), (row) => row);
|
|
176
|
+
}
|
|
177
|
+
/** One bounded page of the run's provisioning event log. */
|
|
178
|
+
async listProvisioningLog(workspaceId, runId, opts) {
|
|
179
|
+
const repo = this.deps.provisioningLogRepository;
|
|
180
|
+
if (!repo)
|
|
181
|
+
return { items: [], nextCursor: null };
|
|
182
|
+
const rows = await repo.list(workspaceId, {
|
|
183
|
+
executionId: runId,
|
|
184
|
+
limit: opts.limit + 1,
|
|
185
|
+
cursor: opts.cursor,
|
|
186
|
+
});
|
|
187
|
+
return paginate(rows, opts.limit, (row) => ({ createdAt: row.createdAt, id: row.id }), (row) => row);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=RunDebugService.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RunDebugService.js","sourceRoot":"","sources":["../../../src/modules/debug/RunDebugService.ts"],"names":[],"mappings":"AAoBA,OAAO,EACL,aAAa,EACb,aAAa,EACb,yBAAyB,EACzB,wBAAwB,EACxB,cAAc,EACd,cAAc,EACd,iBAAiB,GAClB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAA;AAyChE;;;;GAIG;AACH,SAAS,QAAQ,CACf,IAAW,EACX,KAAa,EACb,GAA8B,EAC9B,OAA2B;IAE3B,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,GAAG,KAAK,CAAA;IACnC,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAClD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAA;IAClC,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,OAAO,CAAC;QACxB,2EAA2E;QAC3E,UAAU,EAAE,OAAO,IAAI,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI;KAC/C,CAAA;AACH,CAAC;AAED,MAAM,OAAO,eAAe;IACG,IAAI;IAAjC,YAA6B,IAAiC;oBAAjC,IAAI;IAAgC,CAAC;IAElE;;;;OAIG;IACH,KAAK,CAAC,QAAQ,CACZ,WAAmB,EACnB,IAAuF;QAEvF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,UAAU,CAAC,WAAW,EAAE;YACvE,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS;YACjD,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAC,CAAA;QACF,OAAO,QAAQ,CACb,IAAI,EACJ,IAAI,CAAC,KAAK,EACV,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EACxD,iBAAiB,CAClB,CAAA;IACH,CAAC;IAED,kEAAkE;IAClE,MAAM,CAAC,WAAmB,EAAE,KAAa;QACvC,OAAO,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,GAAG,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;IAC9D,CAAC;IAED;;;;OAIG;IACH,SAAS,CAAC,WAAmB,EAAE,KAAa;QAC1C,OAAO,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,MAAM,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;IACjE,CAAC;IAED;;;;;;;;;OASG;IACH,KAAK,CAAC,QAAQ,CAAC,WAAmB,EAAE,SAA4B;QAC9D,MAAM,KAAK,GAAG,SAAS,CAAC,EAAE,CAAA;QAC1B,oFAAoF;QACpF,uFAAuF;QACvF,MAAM,CAAC,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAC1E,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,oBAAoB,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,EAAE;YACjF,IAAI,CAAC,IAAI,CAAC,8BAA8B,EAAE,gBAAgB,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC;YACnF,IAAI,CAAC,IAAI,CAAC,0BAA0B,EAAE,gBAAgB,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC;YAC/E,2EAA2E;YAC3E,IAAI,CAAC,IAAI,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI;gBAC3E,KAAK,EAAE,CAAC;gBACR,QAAQ,EAAE,CAAC;aACZ;SACF,CAAC,CAAA;QACF,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,aAAa,CAAC,SAAS,CAAC,CAAA;QACjE,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;QACjD,MAAM,KAAK,GAAG;YACZ,wFAAwF;YACxF,oFAAoF;YACpF,+CAA+C;YAC/C,QAAQ,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,uBAAuB,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE;YACjF,YAAY,EAAE;gBACZ,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,8BAA8B;gBACrD,KAAK,EAAE,YAAY;aACpB;YACD,aAAa,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,0BAA0B,EAAE,KAAK,EAAE,WAAW,EAAE;YACxF,eAAe,EAAE,EAAE,SAAS,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,yBAAyB,EAAE,KAAK,EAAE,SAAS,CAAC,KAAK,EAAE;SAC9F,CAAA;QACD,OAAO;YACL,IAAI,EAAE,gCAAgC;YACtC,OAAO,EAAE,CAAC;YACV,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;YAClC,GAAG,EAAE,iBAAiB,CAAC,SAAS,CAAC;YACjC,KAAK;YACL,WAAW,EAAE,SAAS,CAAC,WAAW,IAAI,IAAI;YAC1C,KAAK;YACL,GAAG,EAAE,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE;YACrC,OAAO,EAAE,aAAa,CAAC;gBACrB,SAAS;gBACT,KAAK;gBACL,MAAM;gBACN,WAAW;gBACX,KAAK;gBACL,oBAAoB,EAAE,SAAS,CAAC,QAAQ;aACzC,CAAC;SACH,CAAA;IACH,CAAC;IAED,0DAA0D;IAC1D,KAAK,CAAC,YAAY,CAChB,WAAmB,EACnB,KAAa,EACb,IAWC;QAED,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,uBAAuB,CAAA;QAC9C,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;QACjD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE;YAC5C,WAAW,EAAE,KAAK;YAClB,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,SAAS,EAAE,IAAI,CAAC,SAAS;YACzB,QAAQ,EAAE,IAAI,CAAC,QAAQ;SACxB,CAAC,CAAA;QACF,OAAO,QAAQ,CACb,IAAI,EACJ,IAAI,CAAC,KAAK,EACV,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,EACtD,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,CAAC,CAC/B,CAAA;IACH,CAAC;IAED,+FAA+F;IAC/F,KAAK,CAAC,UAAU,CACd,WAAmB,EACnB,MAAc,EACd,IAAI,GAA2E,EAAE;QAEjF,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,uBAAuB,CAAA;QAC9C,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAA;QACtB,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC7B,yFAAyF;YACzF,wFAAwF;YACxF,0FAA0F;YAC1F,qFAAqF;YACrF,cAAc;YACd,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,CAAC,CAAA;YAC/C,OAAO,GAAG,CAAC,CAAC,CAAC,0BAA0B,CAAC,GAAG,EAAE,IAAI,CAAC,SAAS,IAAI,CAAC,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;QAChG,CAAC;QACD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE;YAC9C,KAAK,EAAE,IAAI,CAAC,SAAS;YACrB,MAAM,EAAE,IAAI,CAAC,UAAU;SACxB,CAAC,CAAA;QACF,OAAO,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,UAAU,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAC/D,CAAC;IAED,4FAA4F;IAC5F,KAAK,CAAC,gBAAgB,CACpB,WAAmB,EACnB,KAAa,EACb,IAAiE;QAEjE,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAA;QACrD,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;QACjD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE;YAC7C,WAAW,EAAE,KAAK;YAClB,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,SAAS,EAAE,IAAI,CAAC,SAAS;SAC1B,CAAC,CAAA;QACF,OAAO,QAAQ,CACb,IAAI,EACJ,IAAI,CAAC,KAAK,EACV,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EACnD,wBAAwB,CACzB,CAAA;IACH,CAAC;IAED,oEAAoE;IACpE,KAAK,CAAC,eAAe,CACnB,WAAmB,EACnB,UAAkB,EAClB,SAAiB,EACjB,UAAU,GAAG,CAAC;QAEd,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,8BAA8B,CAAA;QACrD,IAAI,CAAC,IAAI;YAAE,OAAO,IAAI,CAAA;QACtB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,UAAU,CAAC,CAAA;QACxD,OAAO,QAAQ,CAAC,CAAC,CAAC,yBAAyB,CAAC,QAAQ,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IACrF,CAAC;IAED,uEAAuE;IACvE,KAAK,CAAC,iBAAiB,CACrB,WAAmB,EACnB,KAAa,EACb,IAA6C;QAE7C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,0BAA0B,CAAA;QACjD,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;QACjD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,WAAW,EAAE;YAC5C,WAAW,EAAE,KAAK;YAClB,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAA;QACF,OAAO,QAAQ,CACb,IAAI,EACJ,IAAI,CAAC,KAAK,EACV,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EACnD,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CACb,CAAA;IACH,CAAC;IAED,4DAA4D;IAC5D,KAAK,CAAC,mBAAmB,CACvB,WAAmB,EACnB,KAAa,EACb,IAA6C;QAE7C,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,yBAAyB,CAAA;QAChD,IAAI,CAAC,IAAI;YAAE,OAAO,EAAE,KAAK,EAAE,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAA;QACjD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE;YACxC,WAAW,EAAE,KAAK;YAClB,KAAK,EAAE,IAAI,CAAC,KAAK,GAAG,CAAC;YACrB,MAAM,EAAE,IAAI,CAAC,MAAM;SACpB,CAAC,CAAA;QACF,OAAO,QAAQ,CACb,IAAI,EACJ,IAAI,CAAC,KAAK,EACV,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,SAAS,EAAE,GAAG,CAAC,SAAS,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,EACnD,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CACb,CAAA;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import type { AgentContextSnapshot, AgentContextSnapshotIndex, ExecutionInstance, LlmCallBodySlice, LlmCallMetricPage, LlmCallMetricSummary, PipelineStep } from '@cat-factory/kernel';
|
|
2
|
+
import type { DebugAgentContextDetail, DebugAgentContextEntry, DebugLlmCall, DebugRunStep, DebugRunSummary, DebugSignal, DebugSinkStatus, DebugText, LlmExportInsight, LlmExportTotals, LlmPhaseInsight } from '@cat-factory/contracts';
|
|
3
|
+
import { classifyCall, isWarningFinishReason } from '../observability/observability.logic.js';
|
|
4
|
+
/** Cap on the container post-mortem inlined on a step (it is a log tail, not a document). */
|
|
5
|
+
export declare const MAX_EVICTION_DETAIL_CHARS = 4000;
|
|
6
|
+
/**
|
|
7
|
+
* Slice a stored body to a caller's window and SAY SO. The metadata matters more than the
|
|
8
|
+
* text: a bare truncated string reads exactly like a short one, so a model handed the first
|
|
9
|
+
* 2 kB of a 40 kB reply would confidently report that the agent said almost nothing.
|
|
10
|
+
*
|
|
11
|
+
* `budget` of 0 returns no text at all while still reporting the full size — that is the
|
|
12
|
+
* shape a sweep uses, and the reason a size-only page is still worth reading. `offset`
|
|
13
|
+
* starts the window later, which is how the tail of a large body is reached; past the end
|
|
14
|
+
* it returns an empty slice whose `offset` is clamped to the total, so
|
|
15
|
+
* `offset + chars <= totalChars` always holds.
|
|
16
|
+
*
|
|
17
|
+
* Budgets, offsets and sizes are CODE POINTS (see {@link codePointLength}), matching the
|
|
18
|
+
* SQL-sliced bodies — and the cut walks whole code points, so it can never split a
|
|
19
|
+
* surrogate pair and hand the caller a lone half of one.
|
|
20
|
+
*/
|
|
21
|
+
export declare function sliceText(text: string, budget: number, offset?: number): DebugText;
|
|
22
|
+
/**
|
|
23
|
+
* Project a body the STORE already sliced. The repository returns `{ text, totalChars }`
|
|
24
|
+
* because it cut the body in SQL (so the untaken bytes never left the database); this only
|
|
25
|
+
* re-derives the fields the wire shape adds. Deliberately does NOT re-slice: `text` is
|
|
26
|
+
* already within the window, and slicing again would silently disagree with `totalChars`.
|
|
27
|
+
*
|
|
28
|
+
* `offset` is the window start the caller asked the store for (0 for a list slice), clamped
|
|
29
|
+
* to the total so an ask past the end reports where the body actually stops. A search's
|
|
30
|
+
* per-body `matchOffset` rides through untouched — null (no match in this body) and absent
|
|
31
|
+
* (no search ran) stay distinct on the wire.
|
|
32
|
+
*
|
|
33
|
+
* `chars` and the truncation check count CODE POINTS, because `totalChars` came from SQL
|
|
34
|
+
* `length()` which counts the same — a JS `.length` here reads a SQL-cut emoji-bearing body
|
|
35
|
+
* as untruncated (see {@link codePointLength}).
|
|
36
|
+
*/
|
|
37
|
+
export declare function toDebugText(slice: LlmCallBodySlice, offset?: number): DebugText;
|
|
38
|
+
/** Project a persisted run onto the lean summary every debug list and overview leads with. */
|
|
39
|
+
export declare function toDebugRunSummary(execution: ExecutionInstance): DebugRunSummary;
|
|
40
|
+
/** Project one pipeline step onto the debug view (identity + clocks + container mortality). */
|
|
41
|
+
export declare function toDebugRunStep(step: PipelineStep, index: number): DebugRunStep;
|
|
42
|
+
/**
|
|
43
|
+
* Project a bounded call-page row onto the wire shape. `bodyOffset` is the window start the
|
|
44
|
+
* store's slices were taken at (a point read's `?bodyOffset=`; always 0 on a list row).
|
|
45
|
+
*/
|
|
46
|
+
export declare function toDebugLlmCall(call: LlmCallMetricPage, bodyOffset?: number): DebugLlmCall;
|
|
47
|
+
/** Project a snapshot index row onto the wire shape. */
|
|
48
|
+
export declare function toDebugAgentContextEntry(row: AgentContextSnapshotIndex): DebugAgentContextEntry;
|
|
49
|
+
/**
|
|
50
|
+
* Project a whole snapshot onto the wire shape, budgeting EVERY body INDEPENDENTLY rather
|
|
51
|
+
* than against one shared allowance. A snapshot routinely holds one enormous injected file
|
|
52
|
+
* next to the prompts, and a shared budget spent in array order would leave the prompts — the
|
|
53
|
+
* thing a reader almost always came for — empty because a README came first.
|
|
54
|
+
*/
|
|
55
|
+
export declare function toDebugAgentContextDetail(snapshot: AgentContextSnapshot, bodyChars: number, bodyOffset?: number): DebugAgentContextDetail;
|
|
56
|
+
/**
|
|
57
|
+
* Fold the store's `(agentKind, phase)` rollup cells into the run-level totals + the two
|
|
58
|
+
* breakdowns the overview reports. Built from {@link LlmCallMetricSummary} — the aggregate the
|
|
59
|
+
* store computes without touching a text column — rather than from the calls themselves, so a
|
|
60
|
+
* 3,000-call run costs one GROUP BY here instead of reading 3,000 rows to add them up in
|
|
61
|
+
* JavaScript.
|
|
62
|
+
*
|
|
63
|
+
* Both breakdowns are folds over the SAME cells (kernel's `foldRollupsBy*`), so they total
|
|
64
|
+
* identically to each other and to `totals` by construction — the alternative, one aggregate
|
|
65
|
+
* per axis, could only ever produce two answers to the same question.
|
|
66
|
+
*
|
|
67
|
+
* The per-kind output reuses the metrics EXPORT's shapes on purpose: both describe the same
|
|
68
|
+
* run's model activity, and two independently-derived totals would eventually disagree.
|
|
69
|
+
*/
|
|
70
|
+
export declare function foldLlmRollup(summaries: LlmCallMetricSummary[]): {
|
|
71
|
+
totals: LlmExportTotals;
|
|
72
|
+
byAgentKind: LlmExportInsight[];
|
|
73
|
+
byPhase: LlmPhaseInsight[];
|
|
74
|
+
};
|
|
75
|
+
/** What {@link deriveSignals} needs beyond the run itself. */
|
|
76
|
+
export interface SignalInput {
|
|
77
|
+
execution: ExecutionInstance;
|
|
78
|
+
steps: DebugRunStep[];
|
|
79
|
+
totals: LlmExportTotals;
|
|
80
|
+
byAgentKind: LlmExportInsight[];
|
|
81
|
+
sinks: {
|
|
82
|
+
llmCalls: DebugSinkStatus;
|
|
83
|
+
agentContext: DebugSinkStatus;
|
|
84
|
+
searchQueries: DebugSinkStatus;
|
|
85
|
+
provisioningLog: DebugSinkStatus;
|
|
86
|
+
};
|
|
87
|
+
/** Provisioning attempts for this run recorded as failures. */
|
|
88
|
+
provisioningFailures: number;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Precompute the diagnostic hints the overview publishes. Every one of these is derivable by
|
|
92
|
+
* the caller from the same payload — which is exactly the point: a model that has to
|
|
93
|
+
* rediscover "13 of 40 calls were truncated" by arithmetic over a JSON blob will sometimes get
|
|
94
|
+
* it wrong and will always spend context getting it right. Ordered most-severe first, so a
|
|
95
|
+
* reader that truncates the list keeps what matters.
|
|
96
|
+
*
|
|
97
|
+
* Deliberately NOT a verdict. Each signal names one observation and its magnitude; nothing
|
|
98
|
+
* here claims to know why the run failed, because a wrong confident cause is worse for a
|
|
99
|
+
* debugging client than an ordered list of facts.
|
|
100
|
+
*/
|
|
101
|
+
export declare function deriveSignals(input: SignalInput): DebugSignal[];
|
|
102
|
+
/** Re-exported so the service and its tests classify a call exactly as the SPA does. */
|
|
103
|
+
export { classifyCall, isWarningFinishReason };
|
|
104
|
+
//# sourceMappingURL=debug.logic.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"debug.logic.d.ts","sourceRoot":"","sources":["../../../src/modules/debug/debug.logic.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EACpB,yBAAyB,EACzB,iBAAiB,EACjB,gBAAgB,EAChB,iBAAiB,EACjB,oBAAoB,EACpB,YAAY,EACb,MAAM,qBAAqB,CAAA;AAE5B,OAAO,KAAK,EACV,uBAAuB,EACvB,sBAAsB,EACtB,YAAY,EACZ,YAAY,EACZ,eAAe,EACf,WAAW,EACX,eAAe,EACf,SAAS,EACT,gBAAgB,EAChB,eAAe,EACf,eAAe,EAChB,MAAM,wBAAwB,CAAA;AAC/B,OAAO,EAEL,YAAY,EACZ,qBAAqB,EAGtB,MAAM,yCAAyC,CAAA;AAOhD,6FAA6F;AAC7F,eAAO,MAAM,yBAAyB,OAAQ,CAAA;AA+B9C;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,SAAI,GAAG,SAAS,CAiB7E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAI,GAAG,SAAS,CAU1E;AAED,8FAA8F;AAC9F,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,iBAAiB,GAAG,eAAe,CAY/E;AAED,+FAA+F;AAC/F,wBAAgB,cAAc,CAAC,IAAI,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,GAAG,YAAY,CAwB9E;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,iBAAiB,EAAE,UAAU,SAAI,GAAG,YAAY,CAgCpF;AAED,wDAAwD;AACxD,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,yBAAyB,GAAG,sBAAsB,CAa/F;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,QAAQ,EAAE,oBAAoB,EAC9B,SAAS,EAAE,MAAM,EACjB,UAAU,SAAI,GACb,uBAAuB,CAuBzB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,aAAa,CAAC,SAAS,EAAE,oBAAoB,EAAE,GAAG;IAChE,MAAM,EAAE,eAAe,CAAA;IACvB,WAAW,EAAE,gBAAgB,EAAE,CAAA;IAC/B,OAAO,EAAE,eAAe,EAAE,CAAA;CAC3B,CAkEA;AAED,8DAA8D;AAC9D,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,iBAAiB,CAAA;IAC5B,KAAK,EAAE,YAAY,EAAE,CAAA;IACrB,MAAM,EAAE,eAAe,CAAA;IACvB,WAAW,EAAE,gBAAgB,EAAE,CAAA;IAC/B,KAAK,EAAE;QACL,QAAQ,EAAE,eAAe,CAAA;QACzB,YAAY,EAAE,eAAe,CAAA;QAC7B,aAAa,EAAE,eAAe,CAAA;QAC9B,eAAe,EAAE,eAAe,CAAA;KACjC,CAAA;IACD,+DAA+D;IAC/D,oBAAoB,EAAE,MAAM,CAAA;CAC7B;AASD;;;;;;;;;;GAUG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,GAAG,WAAW,EAAE,CAkJ/D;AAED,wFAAwF;AACxF,OAAO,EAAE,YAAY,EAAE,qBAAqB,EAAE,CAAA"}
|