@tangle-network/agent-runtime 0.43.0 → 0.45.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 (89) hide show
  1. package/README.md +96 -202
  2. package/dist/agent.d.ts +5 -4
  3. package/dist/agent.js +5 -7
  4. package/dist/agent.js.map +1 -1
  5. package/dist/analyst-loop.d.ts +65 -4
  6. package/dist/analyst-loop.js +6 -1
  7. package/dist/audit.d.ts +93 -0
  8. package/dist/audit.js +312 -0
  9. package/dist/audit.js.map +1 -0
  10. package/dist/chunk-4B6U4CVQ.js +15 -0
  11. package/dist/chunk-4B6U4CVQ.js.map +1 -0
  12. package/dist/chunk-FK53TXOP.js +603 -0
  13. package/dist/chunk-FK53TXOP.js.map +1 -0
  14. package/dist/{chunk-MJDGCRAT.js → chunk-IJ6FGOPO.js} +5 -5
  15. package/dist/chunk-IJ6FGOPO.js.map +1 -0
  16. package/dist/{chunk-HVYOHJHK.js → chunk-IJGS6J7X.js} +2 -2
  17. package/dist/chunk-IJGS6J7X.js.map +1 -0
  18. package/dist/chunk-KEWO4KI6.js +3599 -0
  19. package/dist/chunk-KEWO4KI6.js.map +1 -0
  20. package/dist/{chunk-NRZOXCJK.js → chunk-KSMX62JF.js} +2 -2
  21. package/dist/{chunk-C5HMTTNY.js → chunk-NYN5RTLP.js} +13 -12
  22. package/dist/chunk-NYN5RTLP.js.map +1 -0
  23. package/dist/chunk-PRX45WE2.js +264 -0
  24. package/dist/chunk-PRX45WE2.js.map +1 -0
  25. package/dist/{chunk-3HMHSN22.js → chunk-QR4UUC5P.js} +6 -6
  26. package/dist/chunk-QR4UUC5P.js.map +1 -0
  27. package/dist/chunk-WIR4HOOJ.js +27 -0
  28. package/dist/chunk-WIR4HOOJ.js.map +1 -0
  29. package/dist/{chunk-MNCB4SJ5.js → chunk-Z2QXVBA6.js} +296 -8
  30. package/dist/chunk-Z2QXVBA6.js.map +1 -0
  31. package/dist/coder-CczgMqFx.d.ts +114 -0
  32. package/dist/dynamic-BvllHV6M.d.ts +221 -0
  33. package/dist/{improvement-adapter-BC4HhuAR.d.ts → improvement-adapter-CWegd3vw.d.ts} +1 -1
  34. package/dist/improvement.d.ts +2 -3
  35. package/dist/improvement.js +0 -5
  36. package/dist/improvement.js.map +1 -1
  37. package/dist/index.d.ts +123 -10
  38. package/dist/index.js +407 -19
  39. package/dist/index.js.map +1 -1
  40. package/dist/{kb-gate-DTBum3vH.d.ts → kb-gate-D9GBocLN.d.ts} +82 -5
  41. package/dist/{loop-runner-bin-CVoCBmYk.d.ts → loop-runner-bin-CPrCoKqC.d.ts} +14 -10
  42. package/dist/loop-runner-bin.d.ts +9 -7
  43. package/dist/loop-runner-bin.js +6 -8
  44. package/dist/loops.d.ts +7 -371
  45. package/dist/loops.js +96 -19
  46. package/dist/mcp/bin.js +7 -7
  47. package/dist/mcp/bin.js.map +1 -1
  48. package/dist/mcp/index.d.ts +284 -11
  49. package/dist/mcp/index.js +341 -9
  50. package/dist/mcp/index.js.map +1 -1
  51. package/dist/{otel-export-BzvF1Ela.d.ts → otel-export-Dy2DyUCU.d.ts} +1 -1
  52. package/dist/profiles.d.ts +385 -86
  53. package/dist/profiles.js +549 -4
  54. package/dist/profiles.js.map +1 -1
  55. package/dist/run-loop--hSoIknW.d.ts +112 -0
  56. package/dist/runtime-hooks-C7JwKb9E.d.ts +70 -0
  57. package/dist/runtime.d.ts +1860 -0
  58. package/dist/runtime.js +114 -0
  59. package/dist/runtime.js.map +1 -0
  60. package/dist/substrate-CUgk7F7s.d.ts +77 -0
  61. package/dist/topology.d.ts +73 -0
  62. package/dist/topology.js +111 -0
  63. package/dist/topology.js.map +1 -0
  64. package/dist/types-1HbsFa7H.d.ts +438 -0
  65. package/dist/{types-p8dWBIXL.d.ts → types-BtRLF2U3.d.ts} +1 -1
  66. package/dist/{types-Bcp071Jg.d.ts → types-DdzkffAm.d.ts} +95 -1
  67. package/dist/workflow.d.ts +551 -0
  68. package/dist/workflow.js +1778 -0
  69. package/dist/workflow.js.map +1 -0
  70. package/package.json +53 -16
  71. package/skills/agent-runtime-adoption/SKILL.md +29 -26
  72. package/dist/chunk-3HMHSN22.js.map +0 -1
  73. package/dist/chunk-C5HMTTNY.js.map +0 -1
  74. package/dist/chunk-EKBSQYZE.js +0 -813
  75. package/dist/chunk-EKBSQYZE.js.map +0 -1
  76. package/dist/chunk-HVYOHJHK.js.map +0 -1
  77. package/dist/chunk-MJDGCRAT.js.map +0 -1
  78. package/dist/chunk-MNCB4SJ5.js.map +0 -1
  79. package/dist/chunk-PY6NMZYX.js +0 -52
  80. package/dist/chunk-PY6NMZYX.js.map +0 -1
  81. package/dist/chunk-SQSCRJ7U.js +0 -65
  82. package/dist/chunk-SQSCRJ7U.js.map +0 -1
  83. package/dist/chunk-VOX6Z3II.js +0 -90
  84. package/dist/chunk-VOX6Z3II.js.map +0 -1
  85. package/dist/chunk-XBUG326M.js +0 -261
  86. package/dist/chunk-XBUG326M.js.map +0 -1
  87. package/dist/dynamic-B_7GgCwu.d.ts +0 -108
  88. package/dist/optimize-prompt-D-urF2wW.d.ts +0 -129
  89. /package/dist/{chunk-NRZOXCJK.js.map → chunk-KSMX62JF.js.map} +0 -0
@@ -0,0 +1,603 @@
1
+ import {
2
+ AnalystError,
3
+ extractLlmCallEvent,
4
+ randomSuffix
5
+ } from "./chunk-PRX45WE2.js";
6
+
7
+ // src/analyst-loop/iterations-to-trace-store.ts
8
+ import {
9
+ DEFAULT_TRACE_ANALYST_BUDGETS,
10
+ TRACE_ANALYST_TRUNCATION_MARKER_PREFIX
11
+ } from "@tangle-network/agent-eval";
12
+ var bytesOf = (v) => Buffer.byteLength(JSON.stringify(v) ?? "", "utf8");
13
+ var iso = (ms) => new Date(ms).toISOString();
14
+ function normalizeSignature(message) {
15
+ return message.replace(/0x[0-9a-fA-F]+/g, "HEX").replace(/[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}/g, "UUID").replace(/(\/[\w.-]+){2,}/g, "PATH").replace(/\b\d+(\.\d+)?(ms|s|m|h)\b/g, "DUR").replace(/\b\d+\b/g, "#").replace(/\s+/g, " ").trim().slice(0, 200);
16
+ }
17
+ function spanKindFor(event, agentRunName) {
18
+ const llm = extractLlmCallEvent(event, agentRunName);
19
+ if (llm) return { kind: "LLM", model: llm.model ?? null, tool: null };
20
+ const type = String(event?.type ?? "");
21
+ if (/tool/i.test(type)) {
22
+ const d = event?.data;
23
+ const tool = typeof d?.name === "string" ? d.name : typeof d?.tool === "string" ? d.tool : type;
24
+ return { kind: "TOOL", model: null, tool };
25
+ }
26
+ return { kind: "SPAN", model: null, tool: null };
27
+ }
28
+ function errorMessageOf(event) {
29
+ const type = String(event?.type ?? "");
30
+ const d = event?.data;
31
+ if (/error|fail/i.test(type) || d?.error) {
32
+ const m = d?.error ?? d?.message;
33
+ return typeof m === "string" ? m : `${type} error`;
34
+ }
35
+ return void 0;
36
+ }
37
+ function projectIteration(iter) {
38
+ const traceId = iter.events.find((e) => e?.data?.sandboxId)?.data?.sandboxId ?? `iter-${iter.index}`;
39
+ const start = iso(iter.startedAt);
40
+ const end = iso(iter.endedAt || iter.startedAt);
41
+ const durationMs = Math.max(0, (iter.endedAt || iter.startedAt) - iter.startedAt);
42
+ const rootId = `${traceId}:root`;
43
+ const iterErrored = Boolean(iter.error) || iter.verdict?.valid === false;
44
+ const spans = [
45
+ {
46
+ trace_id: traceId,
47
+ span_id: rootId,
48
+ parent_span_id: null,
49
+ name: iter.agentRunName,
50
+ kind: "AGENT",
51
+ start_time: start,
52
+ end_time: end,
53
+ duration_ms: durationMs,
54
+ status: iter.error ? "ERROR" : "OK",
55
+ status_message: iter.error?.message,
56
+ service_name: "agent-runtime",
57
+ agent_name: iter.agentRunName,
58
+ model_name: null,
59
+ tool_name: null,
60
+ attributes: {
61
+ "iteration.index": iter.index,
62
+ "verdict.valid": iter.verdict?.valid,
63
+ "verdict.score": iter.verdict?.score,
64
+ "output.preview": iter.output === void 0 ? void 0 : String(iter.output).slice(0, 2e3)
65
+ }
66
+ }
67
+ ];
68
+ const models = /* @__PURE__ */ new Set();
69
+ const tools = /* @__PURE__ */ new Set();
70
+ iter.events.forEach((event, i) => {
71
+ const { kind, model, tool } = spanKindFor(event, iter.agentRunName);
72
+ if (model) models.add(model);
73
+ if (tool) tools.add(tool);
74
+ const errMsg = errorMessageOf(event);
75
+ spans.push({
76
+ trace_id: traceId,
77
+ span_id: `${traceId}:e${i}`,
78
+ parent_span_id: rootId,
79
+ name: String(event?.type ?? "event"),
80
+ kind,
81
+ start_time: start,
82
+ end_time: end,
83
+ duration_ms: 0,
84
+ status: errMsg ? "ERROR" : "OK",
85
+ status_message: errMsg,
86
+ service_name: "agent-runtime",
87
+ agent_name: iter.agentRunName,
88
+ model_name: model,
89
+ tool_name: tool,
90
+ attributes: event?.data ?? {}
91
+ });
92
+ });
93
+ const hasErrors = spans.some((s) => s.status === "ERROR") || iterErrored;
94
+ const summary = {
95
+ trace_id: traceId,
96
+ service_name: "agent-runtime",
97
+ agent_name: iter.agentRunName,
98
+ span_count: spans.length,
99
+ has_errors: hasErrors,
100
+ start_time: start,
101
+ end_time: end,
102
+ duration_ms: durationMs,
103
+ raw_jsonl_bytes: bytesOf(spans),
104
+ models: [...models],
105
+ tools: [...tools]
106
+ };
107
+ return { summary, spans, rawBytes: summary.raw_jsonl_bytes };
108
+ }
109
+ function matchesFilters(t, f) {
110
+ if (!f) return true;
111
+ if (f.has_errors !== void 0 && t.summary.has_errors !== f.has_errors) return false;
112
+ if (f.service_names?.length && !f.service_names.includes(t.summary.service_name ?? ""))
113
+ return false;
114
+ if (f.agent_names?.length && !f.agent_names.includes(t.summary.agent_name ?? "")) return false;
115
+ if (f.model_names?.length && !f.model_names.some((m) => t.summary.models.includes(m)))
116
+ return false;
117
+ if (f.tool_names?.length && !f.tool_names.some((tn) => t.summary.tools.includes(tn))) return false;
118
+ if (f.start_time_after && t.summary.start_time < f.start_time_after) return false;
119
+ if (f.start_time_before && t.summary.start_time > f.start_time_before) return false;
120
+ if (f.regex_pattern && !new RegExp(f.regex_pattern).test(JSON.stringify(t.spans))) return false;
121
+ return true;
122
+ }
123
+ function capAttributes(attributes, perAttrCap) {
124
+ let truncated = 0;
125
+ const capped = {};
126
+ for (const [k, v] of Object.entries(attributes)) {
127
+ const s = typeof v === "string" ? v : JSON.stringify(v);
128
+ if (typeof s === "string" && s.length > perAttrCap) {
129
+ truncated += 1;
130
+ capped[k] = `${TRACE_ANALYST_TRUNCATION_MARKER_PREFIX} ${s.length}b]${s.slice(0, perAttrCap)}`;
131
+ } else {
132
+ capped[k] = v;
133
+ }
134
+ }
135
+ return { capped, truncated };
136
+ }
137
+ function iterationsToTraceStore(iterations, budgets = DEFAULT_TRACE_ANALYST_BUDGETS) {
138
+ if (iterations.length === 0) {
139
+ throw new AnalystError("iterationsToTraceStore: no iterations to analyze (empty round)");
140
+ }
141
+ const traces = iterations.map((it) => projectIteration(it));
142
+ const byId = new Map(traces.map((t) => [t.summary.trace_id, t]));
143
+ const buildClusters = (set) => {
144
+ const map = /* @__PURE__ */ new Map();
145
+ for (const t of set) {
146
+ for (const s of t.spans) {
147
+ if (s.status !== "ERROR" || !s.status_message) continue;
148
+ const sig = normalizeSignature(s.status_message);
149
+ const c = map.get(sig) ?? {
150
+ signature: sig,
151
+ status_message_sample: s.status_message,
152
+ span_name: s.name,
153
+ tool_name: s.tool_name,
154
+ trace_count: 0,
155
+ span_count: 0,
156
+ prevalence: 0,
157
+ exemplar_trace_ids: [],
158
+ exemplar_span_ids: []
159
+ };
160
+ c.span_count += 1;
161
+ if (!c.exemplar_trace_ids.includes(t.summary.trace_id) && c.exemplar_trace_ids.length < 10) {
162
+ c.exemplar_trace_ids.push(t.summary.trace_id);
163
+ c.trace_count += 1;
164
+ }
165
+ if (c.exemplar_span_ids.length < 10) c.exemplar_span_ids.push(s.span_id);
166
+ map.set(sig, c);
167
+ }
168
+ }
169
+ const errorTraces = set.filter((t) => t.summary.has_errors).length || 1;
170
+ const clusters = [...map.values()].map((c) => ({
171
+ ...c,
172
+ prevalence: c.trace_count / errorTraces
173
+ }));
174
+ return clusters.sort((a, b) => b.trace_count - a.trace_count);
175
+ };
176
+ return {
177
+ async getOverview(filters) {
178
+ const set = traces.filter((t) => matchesFilters(t, filters));
179
+ const services = /* @__PURE__ */ new Set();
180
+ const agents = /* @__PURE__ */ new Set();
181
+ const models = /* @__PURE__ */ new Set();
182
+ const tools = /* @__PURE__ */ new Set();
183
+ let errorSpans = 0;
184
+ for (const t of set) {
185
+ if (t.summary.service_name) services.add(t.summary.service_name);
186
+ if (t.summary.agent_name) agents.add(t.summary.agent_name);
187
+ for (const m of t.summary.models) models.add(m);
188
+ for (const tn of t.summary.tools) tools.add(tn);
189
+ errorSpans += t.spans.filter((s) => s.status === "ERROR").length;
190
+ }
191
+ const times = set.map((t) => t.summary.start_time).sort();
192
+ return {
193
+ total_traces: set.length,
194
+ raw_jsonl_bytes: set.reduce((n, t) => n + t.rawBytes, 0),
195
+ services: [...services],
196
+ agents: [...agents],
197
+ models: [...models],
198
+ tool_names: [...tools],
199
+ sample_trace_ids: set.slice(0, 20).map((t) => t.summary.trace_id),
200
+ errors: {
201
+ trace_count: set.filter((t) => t.summary.has_errors).length,
202
+ span_count: errorSpans
203
+ },
204
+ error_clusters: buildClusters(set),
205
+ time_range: times.length ? { earliest: times[0], latest: times[times.length - 1] } : null
206
+ };
207
+ },
208
+ async queryTraces(opts) {
209
+ const set = traces.filter((t) => matchesFilters(t, opts.filters));
210
+ const offset = opts.offset ?? 0;
211
+ const page = set.slice(offset, offset + opts.limit);
212
+ return {
213
+ traces: page.map((t) => t.summary),
214
+ total: set.length,
215
+ has_more: offset + opts.limit < set.length
216
+ };
217
+ },
218
+ async countTraces(filters) {
219
+ return traces.filter((t) => matchesFilters(t, filters)).length;
220
+ },
221
+ async viewTrace(opts) {
222
+ const t = byId.get(opts.trace_id);
223
+ if (!t) return { trace_id: opts.trace_id, spans: [] };
224
+ const cap = opts.per_attribute_byte_cap ?? budgets.perAttributeViewBudget;
225
+ const projected = t.spans.map((s) => ({
226
+ ...s,
227
+ attributes: capAttributes(s.attributes, cap).capped
228
+ }));
229
+ if (bytesOf(projected) > budgets.perCallByteCeiling) {
230
+ const names = /* @__PURE__ */ new Map();
231
+ for (const s of t.spans) names.set(s.name, (names.get(s.name) ?? 0) + 1);
232
+ return {
233
+ trace_id: opts.trace_id,
234
+ oversized: {
235
+ span_count: t.spans.length,
236
+ top_span_names: [...names.entries()].sort((a, b) => b[1] - a[1]).slice(0, 20),
237
+ span_response_bytes_max: Math.max(...t.spans.map((s) => bytesOf(s))),
238
+ error_span_count: t.spans.filter((s) => s.status === "ERROR").length
239
+ }
240
+ };
241
+ }
242
+ return { trace_id: opts.trace_id, spans: projected };
243
+ },
244
+ async viewSpans(opts) {
245
+ const t = byId.get(opts.trace_id);
246
+ const cap = opts.per_attribute_byte_cap ?? budgets.perAttributeSpanBudget;
247
+ const want = new Set(opts.span_ids);
248
+ const found = (t?.spans ?? []).filter((s) => want.has(s.span_id));
249
+ let truncated = 0;
250
+ const spans = found.map((s) => {
251
+ const { capped, truncated: n } = capAttributes(s.attributes, cap);
252
+ truncated += n;
253
+ return { ...s, attributes: capped };
254
+ });
255
+ const foundIds = new Set(found.map((s) => s.span_id));
256
+ return {
257
+ trace_id: opts.trace_id,
258
+ spans,
259
+ missing_span_ids: opts.span_ids.filter((id) => !foundIds.has(id)),
260
+ truncated_attribute_count: truncated
261
+ };
262
+ },
263
+ async searchTrace(opts) {
264
+ const t = byId.get(opts.trace_id);
265
+ const max = opts.max_matches ?? 50;
266
+ const hits = [];
267
+ for (const s of t?.spans ?? []) {
268
+ for (const hit of searchSpanAttrs(s, opts.regex_pattern, budgets.perMatchTextBudget)) {
269
+ if (hits.length >= max) break;
270
+ hits.push(hit);
271
+ }
272
+ }
273
+ return {
274
+ trace_id: opts.trace_id,
275
+ hits,
276
+ total_matches: hits.length,
277
+ has_more: hits.length >= max
278
+ };
279
+ },
280
+ async searchSpan(opts) {
281
+ const t = byId.get(opts.trace_id);
282
+ const max = opts.max_matches ?? 50;
283
+ const span = (t?.spans ?? []).find((s) => s.span_id === opts.span_id);
284
+ const hits = span ? searchSpanAttrs(span, opts.regex_pattern, budgets.perMatchTextBudget).slice(0, max) : [];
285
+ return {
286
+ trace_id: opts.trace_id,
287
+ span_id: opts.span_id,
288
+ hits,
289
+ total_matches: hits.length,
290
+ has_more: false
291
+ };
292
+ }
293
+ };
294
+ }
295
+ function searchSpanAttrs(span, pattern, textCap) {
296
+ const re = new RegExp(pattern, "g");
297
+ const hits = [];
298
+ for (const [k, v] of Object.entries(span.attributes)) {
299
+ const text = typeof v === "string" ? v : JSON.stringify(v);
300
+ if (typeof text !== "string") continue;
301
+ re.lastIndex = 0;
302
+ const m = re.exec(text);
303
+ if (!m) continue;
304
+ const at = m.index;
305
+ hits.push({
306
+ trace_id: span.trace_id,
307
+ span_id: span.span_id,
308
+ span_name: span.name,
309
+ span_kind: span.kind,
310
+ attribute_path: `attributes.${k}`,
311
+ matched_text: m[0].slice(0, textCap),
312
+ context_before: text.slice(Math.max(0, at - textCap / 2), at),
313
+ context_after: text.slice(at + m[0].length, at + m[0].length + textCap / 2),
314
+ match_offset: at
315
+ });
316
+ }
317
+ return hits;
318
+ }
319
+
320
+ // src/analyst-loop/run-analyst-loop.ts
321
+ import { diffFindings } from "@tangle-network/agent-eval";
322
+ async function runAnalystLoop(opts) {
323
+ const log = opts.log ?? defaultLog;
324
+ const strategy = opts.priorFindingsStrategy ?? "per-kind";
325
+ const emit = makeEmitter(opts.onEvent);
326
+ const startedAt = Date.now();
327
+ const baselineRunId = resolveBaselineRunId(opts);
328
+ const priorAll = baselineRunId ? opts.findingsStore?.loadRun(baselineRunId) ?? [] : [];
329
+ log("baseline resolved", { baselineRunId, prior_findings: priorAll.length });
330
+ await emit({
331
+ type: "baseline-resolved",
332
+ runId: opts.runId,
333
+ baselineRunId,
334
+ priorFindingCount: priorAll.length
335
+ });
336
+ const priorFindings = buildPriorFindingsInput(priorAll, strategy, opts.registry.list());
337
+ const analystResult = await runRegistry(opts, priorFindings, emit);
338
+ log("analyst run complete", {
339
+ findings: analystResult.findings.length,
340
+ cost_usd: analystResult.total_cost_usd,
341
+ per_analyst: analystResult.per_analyst.map((s) => ({
342
+ id: s.analyst_id,
343
+ status: s.status,
344
+ n: s.findings_count
345
+ }))
346
+ });
347
+ if (opts.findingsStore && analystResult.findings.length > 0) {
348
+ await opts.findingsStore.append(opts.runId, analystResult.findings);
349
+ await emit({
350
+ type: "findings-persisted",
351
+ runId: opts.runId,
352
+ count: analystResult.findings.length
353
+ });
354
+ }
355
+ let diff = null;
356
+ if (baselineRunId && analystResult.findings.length > 0) {
357
+ diff = diffFindings(
358
+ priorAll.map((f) => ({ ...f })),
359
+ analystResult.findings.map((f) => ({ ...f, run_id: opts.runId }))
360
+ );
361
+ log("diff vs baseline", {
362
+ appeared: diff.appeared.length,
363
+ disappeared: diff.disappeared.length,
364
+ persisted: diff.persisted.length,
365
+ changed: diff.changed.length
366
+ });
367
+ await emit({
368
+ type: "diff-computed",
369
+ runId: opts.runId,
370
+ baselineRunId,
371
+ appeared: diff.appeared.length,
372
+ disappeared: diff.disappeared.length,
373
+ persisted: diff.persisted.length,
374
+ changed: diff.changed.length
375
+ });
376
+ }
377
+ let knowledge = null;
378
+ if (opts.knowledgeAdapter) {
379
+ knowledge = await runKnowledgeAdapter(opts, analystResult.findings, log, emit);
380
+ }
381
+ let improvement = null;
382
+ if (opts.improvementAdapter) {
383
+ improvement = await runImprovementAdapter(opts, analystResult.findings, log, emit);
384
+ }
385
+ await emit({
386
+ type: "loop-completed",
387
+ runId: opts.runId,
388
+ durationMs: Date.now() - startedAt
389
+ });
390
+ return {
391
+ runId: opts.runId,
392
+ baselineRunId,
393
+ analystResult,
394
+ diff,
395
+ knowledge,
396
+ improvement
397
+ };
398
+ }
399
+ function makeEmitter(onEvent) {
400
+ if (!onEvent) return async () => {
401
+ };
402
+ return async (event) => {
403
+ await onEvent(event);
404
+ };
405
+ }
406
+ async function runRegistry(opts, priorFindings, emit) {
407
+ const reg = opts.registry;
408
+ if (typeof reg.runStream === "function" && opts.onEvent) {
409
+ let final = null;
410
+ for await (const ev of reg.runStream(opts.runId, opts.inputs, { priorFindings })) {
411
+ await emit({ type: "analyst", runId: opts.runId, event: ev });
412
+ if (ev.type === "run-completed") final = ev.result;
413
+ }
414
+ if (!final) {
415
+ throw new Error("runAnalystLoop: registry.runStream ended without run-completed event");
416
+ }
417
+ return final;
418
+ }
419
+ return opts.registry.run(opts.runId, opts.inputs, { priorFindings });
420
+ }
421
+ function resolveBaselineRunId(opts) {
422
+ if (opts.baselineRunId === null) return null;
423
+ if (typeof opts.baselineRunId === "string") return opts.baselineRunId;
424
+ if (!opts.findingsStore) return null;
425
+ const all = opts.findingsStore.loadAll();
426
+ let last = null;
427
+ for (const row of all) {
428
+ if (row.run_id === opts.runId) continue;
429
+ last = row.run_id;
430
+ }
431
+ return last;
432
+ }
433
+ function buildPriorFindingsInput(prior, strategy, registry) {
434
+ if (strategy === "none" || prior.length === 0) return void 0;
435
+ const stripped = prior.map(({ run_id: _run_id, ...rest }) => rest);
436
+ if (strategy === "wildcard") {
437
+ return { "*": stripped };
438
+ }
439
+ void registry;
440
+ return stripped;
441
+ }
442
+ async function runKnowledgeAdapter(opts, findings, log, emit) {
443
+ const adapter = opts.knowledgeAdapter;
444
+ const batch = await adapter.proposeFromFindings(findings);
445
+ log("knowledge.proposeFromFindings", {
446
+ proposals: batch.proposals.length,
447
+ skipped: batch.skipped,
448
+ errors: batch.errors.length
449
+ });
450
+ await emit({
451
+ type: "knowledge-proposed",
452
+ runId: opts.runId,
453
+ proposalCount: batch.proposals.length,
454
+ skipped: batch.skipped,
455
+ errors: batch.errors.length
456
+ });
457
+ const auto = opts.autoApply?.knowledge ?? false;
458
+ const threshold = opts.autoApply?.knowledgeConfidenceThreshold ?? 0.85;
459
+ if (!auto || !adapter.apply) {
460
+ await emit({
461
+ type: "knowledge-applied",
462
+ runId: opts.runId,
463
+ writtenCount: 0,
464
+ withheldForReview: batch.proposals.length
465
+ });
466
+ return {
467
+ proposals: batch.proposals,
468
+ applied: [],
469
+ skipped: batch.skipped,
470
+ errors: batch.errors,
471
+ withheld_for_review: batch.proposals.length
472
+ };
473
+ }
474
+ const findingsById = new Map(findings.map((f) => [f.finding_id, f]));
475
+ const safe = [];
476
+ let withheld = 0;
477
+ for (const p of batch.proposals) {
478
+ const src = p.sourceFindingId ? findingsById.get(p.sourceFindingId) : void 0;
479
+ if (!src) {
480
+ withheld += 1;
481
+ continue;
482
+ }
483
+ if (src.confidence < threshold) {
484
+ withheld += 1;
485
+ continue;
486
+ }
487
+ safe.push(p);
488
+ }
489
+ const result = await adapter.apply(safe);
490
+ log("knowledge.apply", {
491
+ applied: result.written.length,
492
+ withheld_for_review: withheld,
493
+ warnings: result.warnings.length
494
+ });
495
+ await emit({
496
+ type: "knowledge-applied",
497
+ runId: opts.runId,
498
+ writtenCount: result.written.length,
499
+ withheldForReview: withheld
500
+ });
501
+ return {
502
+ proposals: batch.proposals,
503
+ applied: result.written,
504
+ skipped: batch.skipped,
505
+ errors: batch.errors,
506
+ withheld_for_review: withheld
507
+ };
508
+ }
509
+ async function runImprovementAdapter(opts, findings, log, emit) {
510
+ const adapter = opts.improvementAdapter;
511
+ const batch = await adapter.proposeFromFindings(findings);
512
+ log("improvement.proposeFromFindings", {
513
+ edits: batch.edits.length,
514
+ skipped: batch.skipped,
515
+ errors: batch.errors.length
516
+ });
517
+ await emit({
518
+ type: "improvement-proposed",
519
+ runId: opts.runId,
520
+ editCount: batch.edits.length,
521
+ skipped: batch.skipped,
522
+ errors: batch.errors.length
523
+ });
524
+ const auto = opts.autoApply?.improvement ?? false;
525
+ const threshold = opts.autoApply?.improvementConfidenceThreshold ?? 0.9;
526
+ if (!auto || !adapter.apply) {
527
+ await emit({
528
+ type: "improvement-applied",
529
+ runId: opts.runId,
530
+ appliedCount: 0,
531
+ withheldForReview: batch.edits.length
532
+ });
533
+ return {
534
+ edits: batch.edits,
535
+ applied: [],
536
+ skipped: batch.skipped,
537
+ errors: batch.errors,
538
+ withheld_for_review: batch.edits.length
539
+ };
540
+ }
541
+ const findingsById = new Map(findings.map((f) => [f.finding_id, f]));
542
+ const safe = [];
543
+ let withheld = 0;
544
+ for (const e of batch.edits) {
545
+ const src = e.sourceFindingId ? findingsById.get(e.sourceFindingId) : void 0;
546
+ if (!src || src.confidence < threshold) {
547
+ withheld += 1;
548
+ continue;
549
+ }
550
+ safe.push(e);
551
+ }
552
+ const result = await adapter.apply(safe);
553
+ log("improvement.apply", {
554
+ applied: result.applied.length,
555
+ withheld_for_review: withheld,
556
+ warnings: result.warnings.length
557
+ });
558
+ await emit({
559
+ type: "improvement-applied",
560
+ runId: opts.runId,
561
+ appliedCount: result.applied.length,
562
+ withheldForReview: withheld
563
+ });
564
+ return {
565
+ edits: batch.edits,
566
+ applied: result.applied,
567
+ skipped: batch.skipped,
568
+ errors: batch.errors,
569
+ withheld_for_review: withheld
570
+ };
571
+ }
572
+ function defaultLog(msg, fields) {
573
+ if (fields) console.log(`[analyst-loop] ${msg}`, fields);
574
+ else console.log(`[analyst-loop] ${msg}`);
575
+ }
576
+
577
+ // src/analyst-loop/analyst-driver-hook.ts
578
+ function createAnalystDriverHook(opts) {
579
+ const baseRunId = opts.runId ?? `analyst-${randomSuffix()}`;
580
+ let priorRunId;
581
+ return async ({ history }) => {
582
+ const traceStore = iterationsToTraceStore(history);
583
+ const runId = `${baseRunId}-r${history.length}`;
584
+ const result = await runAnalystLoop({
585
+ runId,
586
+ registry: opts.registry,
587
+ inputs: { traceStore },
588
+ findingsStore: opts.findingsStore ?? null,
589
+ // thread the prior round's findings as the baseline → cross-round steering memory.
590
+ baselineRunId: priorRunId,
591
+ priorFindingsStrategy: opts.priorFindingsStrategy ?? "per-kind"
592
+ });
593
+ priorRunId = runId;
594
+ return result.analystResult.findings;
595
+ };
596
+ }
597
+
598
+ export {
599
+ iterationsToTraceStore,
600
+ runAnalystLoop,
601
+ createAnalystDriverHook
602
+ };
603
+ //# sourceMappingURL=chunk-FK53TXOP.js.map