@tangle-network/agent-runtime 0.37.0 → 0.39.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 (46) hide show
  1. package/dist/agent.d.ts +3 -3
  2. package/dist/analyst-loop.d.ts +2 -2
  3. package/dist/analyst-loop.js +3 -257
  4. package/dist/analyst-loop.js.map +1 -1
  5. package/dist/{chunk-T3GJBKHA.js → chunk-7ZECSZ3C.js} +2 -2
  6. package/dist/chunk-AXWGLYSF.js +201 -0
  7. package/dist/chunk-AXWGLYSF.js.map +1 -0
  8. package/dist/chunk-FNMGYYSS.js +60 -0
  9. package/dist/chunk-FNMGYYSS.js.map +1 -0
  10. package/dist/{chunk-V6GURW4W.js → chunk-HSX6PFZR.js} +1 -209
  11. package/dist/chunk-HSX6PFZR.js.map +1 -0
  12. package/dist/{chunk-M65QJD35.js → chunk-PK5DYSNO.js} +5 -3
  13. package/dist/{chunk-M65QJD35.js.map → chunk-PK5DYSNO.js.map} +1 -1
  14. package/dist/chunk-VLXRXMTF.js +212 -0
  15. package/dist/chunk-VLXRXMTF.js.map +1 -0
  16. package/dist/chunk-VOX6Z3II.js +90 -0
  17. package/dist/chunk-VOX6Z3II.js.map +1 -0
  18. package/dist/chunk-XBUG326M.js +261 -0
  19. package/dist/chunk-XBUG326M.js.map +1 -0
  20. package/dist/dynamic-DcrwVGuV.d.ts +106 -0
  21. package/dist/{improvement-adapter-CaZxFxTd.d.ts → improvement-adapter-BC4HhuAR.d.ts} +1 -1
  22. package/dist/improvement.d.ts +6 -130
  23. package/dist/improvement.js +4 -85
  24. package/dist/improvement.js.map +1 -1
  25. package/dist/index.d.ts +10 -85
  26. package/dist/index.js +27 -44
  27. package/dist/index.js.map +1 -1
  28. package/dist/{otel-export-DgFMwsVy.d.ts → kb-gate-YdPNEagq.d.ts} +62 -176
  29. package/dist/loop-runner-bin-DgZj0zfJ.d.ts +192 -0
  30. package/dist/loop-runner-bin.d.ts +12 -0
  31. package/dist/loop-runner-bin.js +19 -0
  32. package/dist/loop-runner-bin.js.map +1 -0
  33. package/dist/loops.d.ts +5 -106
  34. package/dist/mcp/bin.js +3 -2
  35. package/dist/mcp/bin.js.map +1 -1
  36. package/dist/mcp/index.d.ts +6 -79
  37. package/dist/mcp/index.js +11 -62
  38. package/dist/mcp/index.js.map +1 -1
  39. package/dist/optimize-prompt-D-urF2wW.d.ts +129 -0
  40. package/dist/otel-export-xgf4J6bo.d.ts +191 -0
  41. package/dist/profiles.d.ts +1 -1
  42. package/dist/{types-CmTjKLyB.d.ts → types-B9O7l-ij.d.ts} +2 -2
  43. package/dist/{types-D_MXrmJP.d.ts → types-p8dWBIXL.d.ts} +1 -1
  44. package/package.json +3 -2
  45. package/dist/chunk-V6GURW4W.js.map +0 -1
  46. /package/dist/{chunk-T3GJBKHA.js.map → chunk-7ZECSZ3C.js.map} +0 -0
@@ -0,0 +1,261 @@
1
+ // src/analyst-loop/run-analyst-loop.ts
2
+ import { diffFindings } from "@tangle-network/agent-eval";
3
+ async function runAnalystLoop(opts) {
4
+ const log = opts.log ?? defaultLog;
5
+ const strategy = opts.priorFindingsStrategy ?? "per-kind";
6
+ const emit = makeEmitter(opts.onEvent);
7
+ const startedAt = Date.now();
8
+ const baselineRunId = resolveBaselineRunId(opts);
9
+ const priorAll = baselineRunId ? opts.findingsStore?.loadRun(baselineRunId) ?? [] : [];
10
+ log("baseline resolved", { baselineRunId, prior_findings: priorAll.length });
11
+ await emit({
12
+ type: "baseline-resolved",
13
+ runId: opts.runId,
14
+ baselineRunId,
15
+ priorFindingCount: priorAll.length
16
+ });
17
+ const priorFindings = buildPriorFindingsInput(priorAll, strategy, opts.registry.list());
18
+ const analystResult = await runRegistry(opts, priorFindings, emit);
19
+ log("analyst run complete", {
20
+ findings: analystResult.findings.length,
21
+ cost_usd: analystResult.total_cost_usd,
22
+ per_analyst: analystResult.per_analyst.map((s) => ({
23
+ id: s.analyst_id,
24
+ status: s.status,
25
+ n: s.findings_count
26
+ }))
27
+ });
28
+ if (opts.findingsStore && analystResult.findings.length > 0) {
29
+ await opts.findingsStore.append(opts.runId, analystResult.findings);
30
+ await emit({
31
+ type: "findings-persisted",
32
+ runId: opts.runId,
33
+ count: analystResult.findings.length
34
+ });
35
+ }
36
+ let diff = null;
37
+ if (baselineRunId && analystResult.findings.length > 0) {
38
+ diff = diffFindings(
39
+ priorAll.map((f) => ({ ...f })),
40
+ analystResult.findings.map((f) => ({ ...f, run_id: opts.runId }))
41
+ );
42
+ log("diff vs baseline", {
43
+ appeared: diff.appeared.length,
44
+ disappeared: diff.disappeared.length,
45
+ persisted: diff.persisted.length,
46
+ changed: diff.changed.length
47
+ });
48
+ await emit({
49
+ type: "diff-computed",
50
+ runId: opts.runId,
51
+ baselineRunId,
52
+ appeared: diff.appeared.length,
53
+ disappeared: diff.disappeared.length,
54
+ persisted: diff.persisted.length,
55
+ changed: diff.changed.length
56
+ });
57
+ }
58
+ let knowledge = null;
59
+ if (opts.knowledgeAdapter) {
60
+ knowledge = await runKnowledgeAdapter(opts, analystResult.findings, log, emit);
61
+ }
62
+ let improvement = null;
63
+ if (opts.improvementAdapter) {
64
+ improvement = await runImprovementAdapter(opts, analystResult.findings, log, emit);
65
+ }
66
+ await emit({
67
+ type: "loop-completed",
68
+ runId: opts.runId,
69
+ durationMs: Date.now() - startedAt
70
+ });
71
+ return {
72
+ runId: opts.runId,
73
+ baselineRunId,
74
+ analystResult,
75
+ diff,
76
+ knowledge,
77
+ improvement
78
+ };
79
+ }
80
+ function makeEmitter(onEvent) {
81
+ if (!onEvent) return async () => {
82
+ };
83
+ return async (event) => {
84
+ await onEvent(event);
85
+ };
86
+ }
87
+ async function runRegistry(opts, priorFindings, emit) {
88
+ const reg = opts.registry;
89
+ if (typeof reg.runStream === "function" && opts.onEvent) {
90
+ let final = null;
91
+ for await (const ev of reg.runStream(opts.runId, opts.inputs, { priorFindings })) {
92
+ await emit({ type: "analyst", runId: opts.runId, event: ev });
93
+ if (ev.type === "run-completed") final = ev.result;
94
+ }
95
+ if (!final) {
96
+ throw new Error("runAnalystLoop: registry.runStream ended without run-completed event");
97
+ }
98
+ return final;
99
+ }
100
+ return opts.registry.run(opts.runId, opts.inputs, { priorFindings });
101
+ }
102
+ function resolveBaselineRunId(opts) {
103
+ if (opts.baselineRunId === null) return null;
104
+ if (typeof opts.baselineRunId === "string") return opts.baselineRunId;
105
+ if (!opts.findingsStore) return null;
106
+ const all = opts.findingsStore.loadAll();
107
+ let last = null;
108
+ for (const row of all) {
109
+ if (row.run_id === opts.runId) continue;
110
+ last = row.run_id;
111
+ }
112
+ return last;
113
+ }
114
+ function buildPriorFindingsInput(prior, strategy, registry) {
115
+ if (strategy === "none" || prior.length === 0) return void 0;
116
+ const stripped = prior.map(({ run_id: _run_id, ...rest }) => rest);
117
+ if (strategy === "wildcard") {
118
+ return { "*": stripped };
119
+ }
120
+ void registry;
121
+ return stripped;
122
+ }
123
+ async function runKnowledgeAdapter(opts, findings, log, emit) {
124
+ const adapter = opts.knowledgeAdapter;
125
+ const batch = await adapter.proposeFromFindings(findings);
126
+ log("knowledge.proposeFromFindings", {
127
+ proposals: batch.proposals.length,
128
+ skipped: batch.skipped,
129
+ errors: batch.errors.length
130
+ });
131
+ await emit({
132
+ type: "knowledge-proposed",
133
+ runId: opts.runId,
134
+ proposalCount: batch.proposals.length,
135
+ skipped: batch.skipped,
136
+ errors: batch.errors.length
137
+ });
138
+ const auto = opts.autoApply?.knowledge ?? false;
139
+ const threshold = opts.autoApply?.knowledgeConfidenceThreshold ?? 0.85;
140
+ if (!auto || !adapter.apply) {
141
+ await emit({
142
+ type: "knowledge-applied",
143
+ runId: opts.runId,
144
+ writtenCount: 0,
145
+ withheldForReview: batch.proposals.length
146
+ });
147
+ return {
148
+ proposals: batch.proposals,
149
+ applied: [],
150
+ skipped: batch.skipped,
151
+ errors: batch.errors,
152
+ withheld_for_review: batch.proposals.length
153
+ };
154
+ }
155
+ const findingsById = new Map(findings.map((f) => [f.finding_id, f]));
156
+ const safe = [];
157
+ let withheld = 0;
158
+ for (const p of batch.proposals) {
159
+ const src = p.sourceFindingId ? findingsById.get(p.sourceFindingId) : void 0;
160
+ if (!src) {
161
+ withheld += 1;
162
+ continue;
163
+ }
164
+ if (src.confidence < threshold) {
165
+ withheld += 1;
166
+ continue;
167
+ }
168
+ safe.push(p);
169
+ }
170
+ const result = await adapter.apply(safe);
171
+ log("knowledge.apply", {
172
+ applied: result.written.length,
173
+ withheld_for_review: withheld,
174
+ warnings: result.warnings.length
175
+ });
176
+ await emit({
177
+ type: "knowledge-applied",
178
+ runId: opts.runId,
179
+ writtenCount: result.written.length,
180
+ withheldForReview: withheld
181
+ });
182
+ return {
183
+ proposals: batch.proposals,
184
+ applied: result.written,
185
+ skipped: batch.skipped,
186
+ errors: batch.errors,
187
+ withheld_for_review: withheld
188
+ };
189
+ }
190
+ async function runImprovementAdapter(opts, findings, log, emit) {
191
+ const adapter = opts.improvementAdapter;
192
+ const batch = await adapter.proposeFromFindings(findings);
193
+ log("improvement.proposeFromFindings", {
194
+ edits: batch.edits.length,
195
+ skipped: batch.skipped,
196
+ errors: batch.errors.length
197
+ });
198
+ await emit({
199
+ type: "improvement-proposed",
200
+ runId: opts.runId,
201
+ editCount: batch.edits.length,
202
+ skipped: batch.skipped,
203
+ errors: batch.errors.length
204
+ });
205
+ const auto = opts.autoApply?.improvement ?? false;
206
+ const threshold = opts.autoApply?.improvementConfidenceThreshold ?? 0.9;
207
+ if (!auto || !adapter.apply) {
208
+ await emit({
209
+ type: "improvement-applied",
210
+ runId: opts.runId,
211
+ appliedCount: 0,
212
+ withheldForReview: batch.edits.length
213
+ });
214
+ return {
215
+ edits: batch.edits,
216
+ applied: [],
217
+ skipped: batch.skipped,
218
+ errors: batch.errors,
219
+ withheld_for_review: batch.edits.length
220
+ };
221
+ }
222
+ const findingsById = new Map(findings.map((f) => [f.finding_id, f]));
223
+ const safe = [];
224
+ let withheld = 0;
225
+ for (const e of batch.edits) {
226
+ const src = e.sourceFindingId ? findingsById.get(e.sourceFindingId) : void 0;
227
+ if (!src || src.confidence < threshold) {
228
+ withheld += 1;
229
+ continue;
230
+ }
231
+ safe.push(e);
232
+ }
233
+ const result = await adapter.apply(safe);
234
+ log("improvement.apply", {
235
+ applied: result.applied.length,
236
+ withheld_for_review: withheld,
237
+ warnings: result.warnings.length
238
+ });
239
+ await emit({
240
+ type: "improvement-applied",
241
+ runId: opts.runId,
242
+ appliedCount: result.applied.length,
243
+ withheldForReview: withheld
244
+ });
245
+ return {
246
+ edits: batch.edits,
247
+ applied: result.applied,
248
+ skipped: batch.skipped,
249
+ errors: batch.errors,
250
+ withheld_for_review: withheld
251
+ };
252
+ }
253
+ function defaultLog(msg, fields) {
254
+ if (fields) console.log(`[analyst-loop] ${msg}`, fields);
255
+ else console.log(`[analyst-loop] ${msg}`);
256
+ }
257
+
258
+ export {
259
+ runAnalystLoop
260
+ };
261
+ //# sourceMappingURL=chunk-XBUG326M.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/analyst-loop/run-analyst-loop.ts"],"sourcesContent":["/**\n * `runAnalystLoop` — the one call agent apps reach for to close the\n * recursive-self-improvement loop.\n *\n * 1. Load baseline findings (last run, or the slice the caller specifies)\n * 2. Run the analyst registry with priorFindings injected\n * 3. Persist the new run's findings to the ledger\n * 4. Diff the new run against the baseline\n * 5. Hand the findings to the knowledge adapter → proposals (and\n * optionally apply them) → wiki edits\n * 6. Hand the findings to the improvement adapter → prompt / tool /\n * scaffolding edits (review-only by default)\n * 7. Return a single report the consumer renders / persists / acts on.\n *\n * Adapters are optional: the loop works as a \"run + diff + report\"\n * primitive when no adapters are wired; it closes end-to-end when\n * both adapters are wired.\n */\n\nimport type { AnalystFinding, AnalystRunResult, FindingsDiff } from '@tangle-network/agent-eval'\nimport { diffFindings } from '@tangle-network/agent-eval'\n\nimport type {\n AnalystLoopEvent,\n AnalystRegistryStreamingLike,\n ImprovementReport,\n KnowledgeReport,\n RunAnalystLoopOpts,\n RunAnalystLoopResult,\n} from './types'\n\nexport async function runAnalystLoop<TProposal = unknown, TEdit = unknown>(\n opts: RunAnalystLoopOpts,\n): Promise<RunAnalystLoopResult<TProposal, TEdit>> {\n const log = opts.log ?? defaultLog\n const strategy = opts.priorFindingsStrategy ?? 'per-kind'\n const emit = makeEmitter(opts.onEvent)\n const startedAt = Date.now()\n\n // 1. Resolve baseline + load prior findings.\n const baselineRunId = resolveBaselineRunId(opts)\n const priorAll: ReadonlyArray<AnalystFinding & { run_id: string }> = baselineRunId\n ? (opts.findingsStore?.loadRun(baselineRunId) ?? [])\n : []\n log('baseline resolved', { baselineRunId, prior_findings: priorAll.length })\n await emit({\n type: 'baseline-resolved',\n runId: opts.runId,\n baselineRunId,\n priorFindingCount: priorAll.length,\n })\n\n // 2. Run the registry. Strategy controls how analysts see priors.\n // When the registry exposes runStream, forward each event verbatim\n // so subscribers see per-analyst progress in real time.\n const priorFindings = buildPriorFindingsInput(priorAll, strategy, opts.registry.list())\n const analystResult = await runRegistry(opts, priorFindings, emit)\n log('analyst run complete', {\n findings: analystResult.findings.length,\n cost_usd: analystResult.total_cost_usd,\n per_analyst: analystResult.per_analyst.map((s) => ({\n id: s.analyst_id,\n status: s.status,\n n: s.findings_count,\n })),\n })\n\n // 3. Persist the new run before any side-effecting adapter runs so\n // the ledger is the source of truth even if an adapter throws.\n if (opts.findingsStore && analystResult.findings.length > 0) {\n await opts.findingsStore.append(opts.runId, analystResult.findings)\n await emit({\n type: 'findings-persisted',\n runId: opts.runId,\n count: analystResult.findings.length,\n })\n }\n\n // 4. Diff vs baseline.\n let diff: FindingsDiff | null = null\n if (baselineRunId && analystResult.findings.length > 0) {\n diff = diffFindings(\n priorAll.map((f) => ({ ...f })),\n analystResult.findings.map((f) => ({ ...f, run_id: opts.runId })),\n )\n log('diff vs baseline', {\n appeared: diff.appeared.length,\n disappeared: diff.disappeared.length,\n persisted: diff.persisted.length,\n changed: diff.changed.length,\n })\n await emit({\n type: 'diff-computed',\n runId: opts.runId,\n baselineRunId,\n appeared: diff.appeared.length,\n disappeared: diff.disappeared.length,\n persisted: diff.persisted.length,\n changed: diff.changed.length,\n })\n }\n\n // 5. Knowledge adapter — proposals + optional auto-apply.\n let knowledge: KnowledgeReport<TProposal> | null = null\n if (opts.knowledgeAdapter) {\n knowledge = await runKnowledgeAdapter(opts, analystResult.findings, log, emit)\n }\n\n // 6. Improvement adapter — prompt / tool / scaffolding edits.\n let improvement: ImprovementReport<TEdit> | null = null\n if (opts.improvementAdapter) {\n improvement = await runImprovementAdapter(opts, analystResult.findings, log, emit)\n }\n\n await emit({\n type: 'loop-completed',\n runId: opts.runId,\n durationMs: Date.now() - startedAt,\n })\n\n return {\n runId: opts.runId,\n baselineRunId,\n analystResult,\n diff,\n knowledge,\n improvement,\n }\n}\n\ntype Emitter = (event: AnalystLoopEvent) => Promise<void>\n\nfunction makeEmitter(onEvent: RunAnalystLoopOpts['onEvent']): Emitter {\n if (!onEvent) return async () => {}\n return async (event) => {\n await onEvent(event)\n }\n}\n\nasync function runRegistry(\n opts: RunAnalystLoopOpts,\n priorFindings: ReturnType<typeof buildPriorFindingsInput>,\n emit: Emitter,\n): Promise<AnalystRunResult> {\n const reg = opts.registry as AnalystRegistryStreamingLike\n if (typeof reg.runStream === 'function' && opts.onEvent) {\n let final: AnalystRunResult | null = null\n for await (const ev of reg.runStream(opts.runId, opts.inputs, { priorFindings })) {\n await emit({ type: 'analyst', runId: opts.runId, event: ev })\n if (ev.type === 'run-completed') final = ev.result\n }\n if (!final) {\n throw new Error('runAnalystLoop: registry.runStream ended without run-completed event')\n }\n return final\n }\n return opts.registry.run(opts.runId, opts.inputs, { priorFindings })\n}\n\nfunction resolveBaselineRunId(opts: RunAnalystLoopOpts): string | null {\n if (opts.baselineRunId === null) return null\n if (typeof opts.baselineRunId === 'string') return opts.baselineRunId\n if (!opts.findingsStore) return null\n const all = opts.findingsStore.loadAll()\n let last: string | null = null\n for (const row of all) {\n if (row.run_id === opts.runId) continue\n last = row.run_id\n }\n return last\n}\n\nfunction buildPriorFindingsInput(\n prior: ReadonlyArray<AnalystFinding & { run_id: string }>,\n strategy: 'per-kind' | 'wildcard' | 'none',\n registry: ReadonlyArray<{ id: string }>,\n): ReadonlyArray<AnalystFinding> | Record<string, ReadonlyArray<AnalystFinding>> | undefined {\n if (strategy === 'none' || prior.length === 0) return undefined\n const stripped = prior.map(({ run_id: _run_id, ...rest }) => rest as AnalystFinding)\n if (strategy === 'wildcard') {\n return { '*': stripped }\n }\n void registry\n return stripped\n}\n\nasync function runKnowledgeAdapter<TProposal>(\n opts: RunAnalystLoopOpts,\n findings: ReadonlyArray<AnalystFinding>,\n log: NonNullable<RunAnalystLoopOpts['log']>,\n emit: Emitter,\n): Promise<KnowledgeReport<TProposal>> {\n const adapter = opts.knowledgeAdapter!\n const batch = await adapter.proposeFromFindings(findings)\n log('knowledge.proposeFromFindings', {\n proposals: batch.proposals.length,\n skipped: batch.skipped,\n errors: batch.errors.length,\n })\n await emit({\n type: 'knowledge-proposed',\n runId: opts.runId,\n proposalCount: batch.proposals.length,\n skipped: batch.skipped,\n errors: batch.errors.length,\n })\n\n const auto = opts.autoApply?.knowledge ?? false\n const threshold = opts.autoApply?.knowledgeConfidenceThreshold ?? 0.85\n\n if (!auto || !adapter.apply) {\n await emit({\n type: 'knowledge-applied',\n runId: opts.runId,\n writtenCount: 0,\n withheldForReview: batch.proposals.length,\n })\n return {\n proposals: batch.proposals as TProposal[],\n applied: [],\n skipped: batch.skipped,\n errors: batch.errors,\n withheld_for_review: batch.proposals.length,\n }\n }\n\n const findingsById = new Map(findings.map((f) => [f.finding_id, f]))\n const safe: TProposal[] = []\n let withheld = 0\n for (const p of batch.proposals as Array<TProposal & { sourceFindingId?: string }>) {\n const src = p.sourceFindingId ? findingsById.get(p.sourceFindingId) : undefined\n if (!src) {\n withheld += 1\n continue\n }\n if (src.confidence < threshold) {\n withheld += 1\n continue\n }\n safe.push(p)\n }\n const result = await adapter.apply(safe)\n log('knowledge.apply', {\n applied: result.written.length,\n withheld_for_review: withheld,\n warnings: result.warnings.length,\n })\n await emit({\n type: 'knowledge-applied',\n runId: opts.runId,\n writtenCount: result.written.length,\n withheldForReview: withheld,\n })\n return {\n proposals: batch.proposals as TProposal[],\n applied: result.written,\n skipped: batch.skipped,\n errors: batch.errors,\n withheld_for_review: withheld,\n }\n}\n\nasync function runImprovementAdapter<TEdit>(\n opts: RunAnalystLoopOpts,\n findings: ReadonlyArray<AnalystFinding>,\n log: NonNullable<RunAnalystLoopOpts['log']>,\n emit: Emitter,\n): Promise<ImprovementReport<TEdit>> {\n const adapter = opts.improvementAdapter!\n const batch = await adapter.proposeFromFindings(findings)\n log('improvement.proposeFromFindings', {\n edits: batch.edits.length,\n skipped: batch.skipped,\n errors: batch.errors.length,\n })\n await emit({\n type: 'improvement-proposed',\n runId: opts.runId,\n editCount: batch.edits.length,\n skipped: batch.skipped,\n errors: batch.errors.length,\n })\n\n const auto = opts.autoApply?.improvement ?? false\n const threshold = opts.autoApply?.improvementConfidenceThreshold ?? 0.9\n\n if (!auto || !adapter.apply) {\n await emit({\n type: 'improvement-applied',\n runId: opts.runId,\n appliedCount: 0,\n withheldForReview: batch.edits.length,\n })\n return {\n edits: batch.edits as TEdit[],\n applied: [],\n skipped: batch.skipped,\n errors: batch.errors,\n withheld_for_review: batch.edits.length,\n }\n }\n\n const findingsById = new Map(findings.map((f) => [f.finding_id, f]))\n const safe: TEdit[] = []\n let withheld = 0\n for (const e of batch.edits as Array<TEdit & { sourceFindingId?: string }>) {\n const src = e.sourceFindingId ? findingsById.get(e.sourceFindingId) : undefined\n if (!src || src.confidence < threshold) {\n withheld += 1\n continue\n }\n safe.push(e)\n }\n const result = await adapter.apply(safe)\n log('improvement.apply', {\n applied: result.applied.length,\n withheld_for_review: withheld,\n warnings: result.warnings.length,\n })\n await emit({\n type: 'improvement-applied',\n runId: opts.runId,\n appliedCount: result.applied.length,\n withheldForReview: withheld,\n })\n return {\n edits: batch.edits as TEdit[],\n applied: result.applied,\n skipped: batch.skipped,\n errors: batch.errors,\n withheld_for_review: withheld,\n }\n}\n\nfunction defaultLog(msg: string, fields?: Record<string, unknown>): void {\n if (fields) console.log(`[analyst-loop] ${msg}`, fields)\n else console.log(`[analyst-loop] ${msg}`)\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,106 @@
1
+ import { I as Iteration, D as Driver } from './types-B9O7l-ij.js';
2
+
3
+ /**
4
+ * @experimental
5
+ *
6
+ * Dynamic driver — the agent authors the loop topology at runtime.
7
+ *
8
+ * Where `refine` and `fanout-vote` encode a fixed shape as a pure function of
9
+ * history, this driver delegates the per-round shape to an injected
10
+ * `TopologyPlanner`. Each round the planner inspects the task + iteration
11
+ * history and emits one `TopologyMove`:
12
+ * - `refine` → one task next round (optionally rewritten from the prior attempt)
13
+ * - `fanout` → N tasks next round (the kernel round-robins `agentRuns`, so a
14
+ * 2-harness fanout dispatches branch 0 to harness A and branch 1 to harness B)
15
+ * - `stop` → terminate; the kernel selects the winner across all iterations
16
+ *
17
+ * The planner is the brain; this driver is the structure. It maps moves onto
18
+ * the kernel's `plan`/`decide` contract, enforces the iteration + fanout caps,
19
+ * and fails loud on a malformed move. The planner is injected exactly like
20
+ * `refine`'s `refineTask` and `fanout-vote`'s `selector` — so a test can drive
21
+ * a deterministic policy through the real kernel, and production can wire it to
22
+ * an LLM via `createSandboxPlanner`.
23
+ *
24
+ * Topology is orthogonal to harness: the planner never names a backend. Which
25
+ * harness runs a branch is decided by the `AgentRunSpec` the kernel round-robins
26
+ * to, so one dynamic driver works across claude-code, codex, opencode, pi —
27
+ * including fanning a single round across several at once.
28
+ */
29
+
30
+ /** Terminal once `decide` returns `'done'` (a kernel terminal decision). */
31
+ type DynamicDecision = 'continue' | 'done';
32
+ /**
33
+ * One topology decision for the next round. `fanout` carries explicit tasks
34
+ * rather than a count so the planner can issue heterogeneous branches (a
35
+ * different sub-task per harness); pass N copies of one task for a homogeneous
36
+ * fanout that relies on `agentRuns` diversity instead.
37
+ *
38
+ * @experimental
39
+ */
40
+ type TopologyMove<Task> = {
41
+ kind: 'refine';
42
+ task: Task;
43
+ rationale?: string;
44
+ } | {
45
+ kind: 'fanout';
46
+ tasks: Task[];
47
+ rationale?: string;
48
+ } | {
49
+ kind: 'stop';
50
+ rationale?: string;
51
+ };
52
+ /** @experimental */
53
+ interface PlannerContext<Task, Output> {
54
+ /** The root task the loop was invoked with — stable across rounds. */
55
+ task: Task;
56
+ /** Every iteration so far, in dispatch order, with outputs + verdicts. */
57
+ history: ReadonlyArray<Iteration<Task, Output>>;
58
+ /** `history.length` — iterations already spent. */
59
+ iterationsSpent: number;
60
+ /** Iterations left before the driver's `maxIterations` cap forces a stop. */
61
+ iterationsRemaining: number;
62
+ }
63
+ /**
64
+ * Chooses the next topology move from the task + history. Sync or async; an
65
+ * async planner is where an LLM call goes (see `createSandboxPlanner`).
66
+ *
67
+ * @experimental
68
+ */
69
+ type TopologyPlanner<Task, Output> = (ctx: PlannerContext<Task, Output>) => TopologyMove<Task> | Promise<TopologyMove<Task>>;
70
+ /** @experimental */
71
+ interface CreateDynamicDriverOptions<Task, Output> {
72
+ /** The agent-authored topology policy. Invoked once per round in `plan`. */
73
+ planner: TopologyPlanner<Task, Output>;
74
+ /**
75
+ * Hard safety cap on total iterations. When reached, the driver stops before
76
+ * consulting the planner. Default 8. Set the kernel's `runLoop`
77
+ * `maxIterations >= ` this so the driver's cap governs and the loop closes on
78
+ * a clean `'done'` rather than a truncated `'continue'`.
79
+ */
80
+ maxIterations?: number;
81
+ /** Max branches a single `fanout` move may dispatch. Default 4. */
82
+ maxFanout?: number;
83
+ /** Stable identifier surfaced in trace events. Default `'dynamic'`. */
84
+ name?: string;
85
+ }
86
+ /** @experimental */
87
+ declare function createDynamicDriver<Task, Output>(options: CreateDynamicDriverOptions<Task, Output>): Driver<Task, Output, DynamicDecision>;
88
+ /**
89
+ * Compact, planner-friendly view of iteration history — what an LLM planner
90
+ * needs to choose the next move without the raw event streams. Output is
91
+ * truncated so a long run's prompt stays bounded.
92
+ *
93
+ * @experimental
94
+ */
95
+ declare function summarizeHistory<Task, Output>(history: ReadonlyArray<Iteration<Task, Output>>, opts?: {
96
+ maxOutputChars?: number;
97
+ }): Array<{
98
+ index: number;
99
+ agentRunName: string;
100
+ valid?: boolean;
101
+ score?: number;
102
+ error?: string;
103
+ output?: string;
104
+ }>;
105
+
106
+ export { type CreateDynamicDriverOptions as C, type DynamicDecision as D, type PlannerContext as P, type TopologyPlanner as T, type TopologyMove as a, createDynamicDriver as c, summarizeHistory as s };
@@ -1,5 +1,5 @@
1
1
  import { FindingSubject, AnalystFinding } from '@tangle-network/agent-eval';
2
- import { I as ImprovementAdapter } from './types-D_MXrmJP.js';
2
+ import { I as ImprovementAdapter } from './types-p8dWBIXL.js';
3
3
 
4
4
  /**
5
5
  * `AgentSurfaces` — declarative map of the mutable file/directory paths
@@ -1,8 +1,9 @@
1
- import { AnalystFinding, LlmClientOptions } from '@tangle-network/agent-eval';
1
+ import { AnalystFinding } from '@tangle-network/agent-eval';
2
2
  import { L as LocalHarness, r as runLocalHarness } from './local-harness-KrdFTY5R.js';
3
- import { LabeledScenarioStore, WorktreeAdapter, ImprovementDriver, Scenario, DispatchContext, JudgeConfig, Gate, CampaignStorage, GateResult, RunImprovementLoopResult } from '@tangle-network/agent-eval/campaign';
4
- import { S as SurfaceImprovementEdit } from './improvement-adapter-CaZxFxTd.js';
5
- import { I as ImprovementAdapter } from './types-D_MXrmJP.js';
3
+ import { LabeledScenarioStore, WorktreeAdapter, ImprovementDriver } from '@tangle-network/agent-eval/campaign';
4
+ export { O as OptimizePromptOptions, b as OptimizePromptReflection, a as OptimizePromptResult, o as optimizePrompt } from './optimize-prompt-D-urF2wW.js';
5
+ import { S as SurfaceImprovementEdit } from './improvement-adapter-BC4HhuAR.js';
6
+ import { I as ImprovementAdapter } from './types-p8dWBIXL.js';
6
7
  import 'node:child_process';
7
8
 
8
9
  /**
@@ -98,131 +99,6 @@ interface AgenticGeneratorOptions {
98
99
  }
99
100
  declare function agenticGenerator(opts?: AgenticGeneratorOptions): CandidateGenerator;
100
101
 
101
- /**
102
- * @experimental
103
- *
104
- * `optimizePrompt` — identity-gated optimization for any TEXT prompt surface
105
- * (system prompt, planner prompt, judge rubric, skill doc).
106
- *
107
- * The text-surface sibling to this module's `improvementDriver` (the
108
- * CODE-surface / worktree path). Both feed agent-eval's `runImprovementLoop`;
109
- * this one defaults the driver to agent-eval's `gepaDriver` (reflective text
110
- * mutator) and the gate to `heldOutGate`.
111
- *
112
- * IDENTITY-GATED BY CONSTRUCTION — the whole point. The loop runs evals,
113
- * collects per-scenario signal, proposes candidates, and the gate compares
114
- * candidate-vs-baseline ON THE HELDOUT. `result.prompt` is the baseline
115
- * (identity) UNLESS the gate decided `'ship'`. So wiring a surface up is safe:
116
- * a surface with no beneficial mutation simply keeps its baseline. You never
117
- * regress by registering a prompt — you only ever improve when the held-out
118
- * data earns it.
119
- *
120
- * Generic over the runtime: `runWithPrompt` is the only domain seam — given a
121
- * candidate prompt + scenario, run it however the surface runs (sandbox
122
- * `streamPrompt`, a `runLoop`, a direct model call) and return the artifact the
123
- * judges score. The optimizer never assumes how a prompt is executed.
124
- */
125
-
126
- /** Reflection config for the default `gepaDriver`. Omit when passing a custom
127
- * `driver`. */
128
- interface OptimizePromptReflection {
129
- /** Router transport for the reflection model. */
130
- llm: LlmClientOptions;
131
- /** Model that performs the reflective rewrite. */
132
- model: string;
133
- /** What is being optimized — orients the reflection prompt. Default
134
- * `'system prompt'`. */
135
- target?: string;
136
- /** Surface-specific mutation levers offered to the reflector. */
137
- mutationPrimitives?: string[];
138
- /** H2 (`## Foo`) headings that MUST survive every candidate. gepaDriver's
139
- * only structural guard — load-bearing sections of the prompt should be
140
- * `##` headings so a rewrite cannot drop them. */
141
- preserveSections?: string[];
142
- /** Max sentence-level edits per candidate vs the parent (a textual learning
143
- * rate). Caps a rewrite from wiping prior rules in one generation. */
144
- maxSentenceEdits?: number;
145
- }
146
- /** @experimental */
147
- interface OptimizePromptOptions<TScenario extends Scenario, TArtifact> {
148
- /** The prompt being optimized — the identity baseline the gate protects. */
149
- baselinePrompt: string;
150
- /** Domain seam: run a candidate prompt against a scenario → artifact the
151
- * judges score. The optimizer is agnostic to HOW the prompt runs. */
152
- runWithPrompt: (prompt: string, scenario: TScenario, ctx: DispatchContext) => Promise<TArtifact>;
153
- /** Training pool — scored each generation to rank candidates. */
154
- scenarios: TScenario[];
155
- /** Held out of training — scored ONLY for the gate's baseline-vs-winner
156
- * delta. Disjoint from `scenarios`; this is what makes promotion measure
157
- * generalization, not memorization. */
158
- holdoutScenarios: TScenario[];
159
- /** Scorers — deterministic checks or LLM judges. */
160
- judges: JudgeConfig<TArtifact, TScenario>[];
161
- /** Where artifacts + traces land (opaque key under in-memory storage). */
162
- runDir: string;
163
- /** Default driver = `gepaDriver` built from this. Required UNLESS `driver`
164
- * is supplied. */
165
- reflection?: OptimizePromptReflection;
166
- /** Override the improvement strategy (custom driver / deterministic tests). */
167
- driver?: ImprovementDriver;
168
- /** Override the promotion gate. Default `heldOutGate` over `holdoutScenarios`
169
- * — zero extra LLM. Wrap `defaultProductionGate` for red-team/reward-hacking
170
- * hardening on production wiring. */
171
- gate?: Gate<TArtifact, TScenario>;
172
- /** Minimum held-out composite lift to ship, forwarded to the default
173
- * `heldOutGate`. When omitted the gate uses its own default. */
174
- deltaThreshold?: number;
175
- /** Candidates proposed per generation. Default 4. */
176
- populationSize?: number;
177
- /** Generations to run. Default 3. */
178
- maxGenerations?: number;
179
- /** Candidates carried to the next generation. Default 2. */
180
- promoteTopK?: number;
181
- /** Storage backend. Pass `inMemoryCampaignStorage()` for filesystem-less /
182
- * test runs. Default: Node filesystem. */
183
- storage?: CampaignStorage;
184
- /** Reproducibility seed. Default 42. */
185
- seed?: number;
186
- /** Per-scenario replicates for CI bands. Default 1. */
187
- reps?: number;
188
- /** Max concurrent cells. Default 2. */
189
- maxConcurrency?: number;
190
- /** Test seam — override the wall clock. */
191
- now?: () => Date;
192
- /** On a shipped gate: `'pr'` opens a PR, `'none'` just reports. Default
193
- * `'none'`. */
194
- autoOnPromote?: 'pr' | 'none';
195
- ghOwner?: string;
196
- ghRepo?: string;
197
- }
198
- /** @experimental */
199
- interface OptimizePromptResult<TArtifact, TScenario extends Scenario> {
200
- /** The prompt to USE. Identity (the baseline) unless the gate shipped a
201
- * winner — so a caller can always assign `result.prompt` unconditionally. */
202
- prompt: string;
203
- /** True only when the gate promoted a candidate over baseline on holdout. */
204
- improved: boolean;
205
- /** The gate's verdict (`'ship' | 'hold' | 'need_more_work' | ...`). */
206
- decision: GateResult['decision'];
207
- /** Human-readable reasons the gate gave. */
208
- reasons: string[];
209
- /** Mean held-out composite of the baseline. */
210
- baselineComposite: number;
211
- /** Mean held-out composite of the winner candidate. */
212
- winnerComposite: number;
213
- /** Held-out lift (winner − baseline); the gate's `delta` when it reported one. */
214
- delta: number;
215
- /** Why the winner was proposed — present when a shipped winner carried a
216
- * driver rationale. */
217
- rationale?: string;
218
- /** Unified baseline→winner diff (empty when the winner is the baseline). */
219
- diff: string;
220
- /** The full loop result for callers that need generations / campaigns. */
221
- raw: RunImprovementLoopResult<TArtifact, TScenario>;
222
- }
223
- /** @experimental */
224
- declare function optimizePrompt<TScenario extends Scenario, TArtifact>(opts: OptimizePromptOptions<TScenario, TArtifact>): Promise<OptimizePromptResult<TArtifact, TScenario>>;
225
-
226
102
  /**
227
103
  * @experimental
228
104
  *
@@ -242,4 +118,4 @@ interface ReflectiveGeneratorOptions {
242
118
  }
243
119
  declare function reflectiveGenerator(opts: ReflectiveGeneratorOptions): CandidateGenerator;
244
120
 
245
- export { type AgenticGeneratorOptions, type CandidateGenerator, type ImprovementDriverOptions, type OptimizePromptOptions, type OptimizePromptReflection, type OptimizePromptResult, type ReflectiveGeneratorOptions, agenticGenerator, improvementDriver, optimizePrompt, reflectiveGenerator };
121
+ export { type AgenticGeneratorOptions, type CandidateGenerator, type ImprovementDriverOptions, type ReflectiveGeneratorOptions, agenticGenerator, improvementDriver, reflectiveGenerator };
@@ -1,9 +1,10 @@
1
+ import {
2
+ optimizePrompt
3
+ } from "./chunk-VOX6Z3II.js";
1
4
  import {
2
5
  runLocalHarness
3
6
  } from "./chunk-GLR25NG7.js";
4
- import {
5
- ConfigError
6
- } from "./chunk-SQSCRJ7U.js";
7
+ import "./chunk-SQSCRJ7U.js";
7
8
  import "./chunk-DGUM43GV.js";
8
9
 
9
10
  // src/improvement/agentic-generator.ts
@@ -130,88 +131,6 @@ function resolveFindings(ctx) {
130
131
  return ctx.findings;
131
132
  }
132
133
 
133
- // src/improvement/optimize-prompt.ts
134
- import { gepaDriver, heldOutGate, runImprovementLoop } from "@tangle-network/agent-eval/campaign";
135
- async function optimizePrompt(opts) {
136
- if (!opts.driver && !opts.reflection) {
137
- throw new ConfigError(
138
- "optimizePrompt: pass `reflection` (builds the default gepaDriver) or a custom `driver`"
139
- );
140
- }
141
- if (opts.scenarios.length === 0) {
142
- throw new ConfigError("optimizePrompt: `scenarios` must be non-empty");
143
- }
144
- if (opts.holdoutScenarios.length === 0) {
145
- throw new ConfigError(
146
- "optimizePrompt: `holdoutScenarios` must be non-empty (the gate needs it)"
147
- );
148
- }
149
- const driver = opts.driver ?? gepaDriver({
150
- llm: opts.reflection.llm,
151
- model: opts.reflection.model,
152
- target: opts.reflection.target ?? "system prompt",
153
- mutationPrimitives: opts.reflection.mutationPrimitives,
154
- constraints: opts.reflection.preserveSections || opts.reflection.maxSentenceEdits !== void 0 ? {
155
- preserveSections: opts.reflection.preserveSections,
156
- maxSentenceEdits: opts.reflection.maxSentenceEdits
157
- } : void 0
158
- });
159
- const gate = opts.gate ?? heldOutGate({
160
- scenarios: opts.holdoutScenarios,
161
- ...opts.deltaThreshold !== void 0 ? { deltaThreshold: opts.deltaThreshold } : {}
162
- });
163
- const result = await runImprovementLoop({
164
- baselineSurface: opts.baselinePrompt,
165
- dispatchWithSurface: (surface, scenario, ctx) => {
166
- if (typeof surface !== "string") {
167
- throw new ConfigError(
168
- "optimizePrompt: received a CodeSurface \u2014 this entry point optimizes string prompts only"
169
- );
170
- }
171
- return opts.runWithPrompt(surface, scenario, ctx);
172
- },
173
- driver,
174
- populationSize: opts.populationSize ?? 4,
175
- maxGenerations: opts.maxGenerations ?? 3,
176
- ...opts.promoteTopK !== void 0 ? { promoteTopK: opts.promoteTopK } : {},
177
- scenarios: opts.scenarios,
178
- holdoutScenarios: opts.holdoutScenarios,
179
- judges: opts.judges,
180
- gate,
181
- autoOnPromote: opts.autoOnPromote ?? "none",
182
- ...opts.ghOwner !== void 0 ? { ghOwner: opts.ghOwner } : {},
183
- ...opts.ghRepo !== void 0 ? { ghRepo: opts.ghRepo } : {},
184
- runDir: opts.runDir,
185
- ...opts.storage !== void 0 ? { storage: opts.storage } : {},
186
- ...opts.seed !== void 0 ? { seed: opts.seed } : {},
187
- ...opts.reps !== void 0 ? { reps: opts.reps } : {},
188
- ...opts.maxConcurrency !== void 0 ? { maxConcurrency: opts.maxConcurrency } : {},
189
- ...opts.now !== void 0 ? { now: opts.now } : {}
190
- });
191
- const improved = result.gateResult.decision === "ship";
192
- const winnerSurface = typeof result.winnerSurface === "string" ? result.winnerSurface : opts.baselinePrompt;
193
- const baselineComposite = meanComposite(result.baselineOnHoldout);
194
- const winnerComposite = meanComposite(result.winnerOnHoldout);
195
- return {
196
- prompt: improved ? winnerSurface : opts.baselinePrompt,
197
- improved,
198
- decision: result.gateResult.decision,
199
- reasons: result.gateResult.reasons,
200
- baselineComposite,
201
- winnerComposite,
202
- delta: result.gateResult.delta ?? winnerComposite - baselineComposite,
203
- ...improved && result.winnerRationale ? { rationale: result.winnerRationale } : {},
204
- diff: result.promotedDiff,
205
- raw: result
206
- };
207
- }
208
- function meanComposite(campaign) {
209
- const scenarios = Object.values(campaign.aggregates.byScenario);
210
- if (scenarios.length === 0) return 0;
211
- const sum = scenarios.reduce((acc, s) => acc + s.meanComposite, 0);
212
- return sum / scenarios.length;
213
- }
214
-
215
134
  // src/improvement/reflective-generator.ts
216
135
  import { spawnSync as spawnSync2 } from "child_process";
217
136
  function reflectiveGenerator(opts) {