@tangle-network/agent-runtime 0.94.12 → 0.95.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 (80) hide show
  1. package/dist/agent.d.ts +2 -25
  2. package/dist/agent.js +9 -12
  3. package/dist/agent.js.map +1 -1
  4. package/dist/{agentic-generator-DDMM45kZ.d.ts → agentic-generator-hCaQRAes.d.ts} +0 -1
  5. package/dist/analyst-loop.d.ts +1 -1
  6. package/dist/candidate-execution/index.d.ts +43 -16
  7. package/dist/candidate-execution/index.js +18 -8
  8. package/dist/{chunk-VYA2YEKA.js → chunk-2KGAN2HM.js} +83 -14
  9. package/dist/chunk-2KGAN2HM.js.map +1 -0
  10. package/dist/{chunk-FTXM7Q7P.js → chunk-6YBA64Z2.js} +120 -724
  11. package/dist/chunk-6YBA64Z2.js.map +1 -0
  12. package/dist/{chunk-HGRW27YY.js → chunk-AP7CPGMZ.js} +139 -19
  13. package/dist/chunk-AP7CPGMZ.js.map +1 -0
  14. package/dist/{chunk-XP5KDM3R.js → chunk-BPGXIKK7.js} +3 -3
  15. package/dist/{chunk-D3H7F6L2.js → chunk-DHCHL6OG.js} +2 -3
  16. package/dist/chunk-DHCHL6OG.js.map +1 -0
  17. package/dist/{chunk-PCURO3DL.js → chunk-G55QE4IQ.js} +512 -36
  18. package/dist/chunk-G55QE4IQ.js.map +1 -0
  19. package/dist/{chunk-C3UKLQ54.js → chunk-IADLKE7I.js} +14 -4
  20. package/dist/chunk-IADLKE7I.js.map +1 -0
  21. package/dist/{chunk-WIPGQ4GT.js → chunk-IMSNJSXH.js} +1 -1
  22. package/dist/{chunk-WIPGQ4GT.js.map → chunk-IMSNJSXH.js.map} +1 -1
  23. package/dist/{chunk-VSWBYWFK.js → chunk-M6MD6JBS.js} +20 -27
  24. package/dist/chunk-M6MD6JBS.js.map +1 -0
  25. package/dist/chunk-MKGRLDWB.js +684 -0
  26. package/dist/chunk-MKGRLDWB.js.map +1 -0
  27. package/dist/{chunk-AEG3NGJ2.js → chunk-Q2JSAVQ3.js} +34 -2
  28. package/dist/chunk-Q2JSAVQ3.js.map +1 -0
  29. package/dist/{chunk-37V4KQDC.js → chunk-WTZ37EQY.js} +1021 -514
  30. package/dist/chunk-WTZ37EQY.js.map +1 -0
  31. package/dist/{chunk-U33YZ7B2.js → chunk-YLUOTX6U.js} +4 -4
  32. package/dist/{chunk-33OG2NN3.js → chunk-Z5I642SY.js} +2 -2
  33. package/dist/{completion-gate-D1gX1-hg.d.ts → completion-gate-C80jiRfN.d.ts} +1 -1
  34. package/dist/conversation.d.ts +12 -1
  35. package/dist/conversation.js +2 -2
  36. package/dist/{coordination-Dr_axlAf.d.ts → coordination-BFE3Den7.d.ts} +10 -11
  37. package/dist/environment-provider.d.ts +2 -2
  38. package/dist/environment-provider.js +1 -1
  39. package/dist/{improve-BN3HyXIO.d.ts → improve-B-UYaEH5.d.ts} +3 -3
  40. package/dist/index.d.ts +22 -25
  41. package/dist/index.js +45 -50
  42. package/dist/index.js.map +1 -1
  43. package/dist/intelligence.d.ts +177 -119
  44. package/dist/intelligence.js +501 -342
  45. package/dist/intelligence.js.map +1 -1
  46. package/dist/knowledge.d.ts +22 -11
  47. package/dist/knowledge.js +9 -4
  48. package/dist/lifecycle.d.ts +2 -2
  49. package/dist/lifecycle.js +1 -1
  50. package/dist/{loop-runner-bin-BRQSQdHa.d.ts → loop-runner-bin-BIQldFS8.d.ts} +2 -2
  51. package/dist/loop-runner-bin.d.ts +5 -5
  52. package/dist/loop-runner-bin.js +6 -6
  53. package/dist/loops.d.ts +12 -12
  54. package/dist/loops.js +5 -5
  55. package/dist/mcp/bin.js +3 -3
  56. package/dist/mcp/index.d.ts +6 -6
  57. package/dist/mcp/index.js +6 -6
  58. package/dist/{mcp-serve-verifier-DQQDbuyz.d.ts → mcp-serve-verifier-Bs_n0xPc.d.ts} +1 -1
  59. package/dist/primeintellect/index.js +1 -1
  60. package/dist/profile-DbfaMTdk.d.ts +233 -0
  61. package/dist/profiles.d.ts +1 -1
  62. package/dist/{supervise-DmYOug5f.d.ts → supervise-BLPI50-w.d.ts} +3 -3
  63. package/dist/{types-ByAYqlVb.d.ts → types-B3vAW0Oq.d.ts} +1 -1
  64. package/dist/types-CWqfCO8s.d.ts +491 -0
  65. package/dist/{types-1d5QGK3t.d.ts → types-CmnA2iL3.d.ts} +3 -3
  66. package/dist/{worktree-fanout-CPprU-qI.d.ts → worktree-fanout-DCA3G4bO.d.ts} +3 -3
  67. package/package.json +13 -10
  68. package/dist/chunk-37V4KQDC.js.map +0 -1
  69. package/dist/chunk-AEG3NGJ2.js.map +0 -1
  70. package/dist/chunk-C3UKLQ54.js.map +0 -1
  71. package/dist/chunk-D3H7F6L2.js.map +0 -1
  72. package/dist/chunk-FTXM7Q7P.js.map +0 -1
  73. package/dist/chunk-HGRW27YY.js.map +0 -1
  74. package/dist/chunk-PCURO3DL.js.map +0 -1
  75. package/dist/chunk-VSWBYWFK.js.map +0 -1
  76. package/dist/chunk-VYA2YEKA.js.map +0 -1
  77. package/dist/prepare-DIeVgQG3.d.ts +0 -718
  78. /package/dist/{chunk-XP5KDM3R.js.map → chunk-BPGXIKK7.js.map} +0 -0
  79. /package/dist/{chunk-U33YZ7B2.js.map → chunk-YLUOTX6U.js.map} +0 -0
  80. /package/dist/{chunk-33OG2NN3.js.map → chunk-Z5I642SY.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/improvement/improvement-driver.ts","../src/improvement/raw-trace-distiller.ts","../src/improvement/improve.ts"],"sourcesContent":["/**\n *\n * `improvementDriver` — the ONE reflective/agentic improvement proposer for\n * agent-eval's improvement loop. It implements `SurfaceProposer` and owns\n * the candidate lifecycle (worktree create → generate → finalize/discard,\n * × populationSize); it delegates the only thing that genuinely varies — HOW\n * a candidate change is produced — to a pluggable `CandidateGenerator`.\n *\n * There is no separate \"analyst driver\" vs \"autoresearch driver\": those are\n * the SAME driver at two settings of a dial.\n * - cheap reflective path → `reflectiveGenerator` (shots=1, no sandbox;\n * applies pre-drafted patches)\n * - full agentic path → `agenticGenerator` (shots=N, multi-shot\n * verify-in-session loop; an agent reads code +\n * report, edits, and re-tries on verifier failure)\n * Both emit changes into a worktree the driver finalizes into a\n * `CodeSurface{ worktreeRef }` the loop measures on the holdout. See\n * agent-eval's `docs/design/self-improvement-engine.md`.\n *\n * @experimental\n */\n\nimport { spawnSync } from 'node:child_process'\nimport type { AnalystFinding, CostLedgerHandle } from '@tangle-network/agent-eval'\nimport {\n type CodeSurface,\n type LabeledScenarioStore,\n type ProposeContext,\n type SurfaceProposer,\n verifyCodeSurface,\n type Worktree,\n type WorktreeAdapter,\n} from '@tangle-network/agent-eval/campaign'\n\n/** The byte-producing seam — the ONE thing that differs between the cheap\n * reflective path and the full agentic path. A generator makes (uncommitted)\n * changes inside `worktreePath`; the driver commits them via the worktree\n * adapter's `finalize`. */\nexport interface CandidateGenerator {\n kind: string\n /** Whether this generator can produce a candidate from an EMPTY findings set\n * and no phase-2 report — i.e. it draws its change signal from the repo and\n * the raw-trace filesystem context on disk, not only from pre-summarized\n * findings. An agentic coder (`agenticGenerator`) sets this: the seed repo +\n * raw traces ARE the signal, so it must still run the full `populationSize`\n * when the distiller yielded nothing (this is the meta-harness contract — the\n * agent diagnoses from the raw traces itself). A patch-applier\n * (`reflectiveGenerator`) leaves it unset — with no findings there is no\n * patch to draft, so the driver short-circuits rather than spin up worktrees\n * for a guaranteed no-op. Default `false`. */\n proposesWithoutFindings?: boolean\n generate(args: {\n /** The candidate worktree — a clean checkout of the current incumbent. */\n worktreePath: string\n /** Phase-2 research report (analyst findings + diff), opaque. */\n report: unknown\n /** Findings resolved from the report or the loop context. */\n findings: AnalystFinding[]\n /** Handle to all captured data, to ground the change. */\n dataset?: LabeledScenarioStore\n /** DEPTH: max iterations the generator may take (agentic uses this; the\n * reflective generator ignores it). */\n maxShots: number\n signal: AbortSignal\n /** Improvement-loop coordinates. Present when called through improvementDriver. */\n generation?: number\n candidateIndex?: number\n /** Shared run-wide paid-call account supplied by agent-eval 0.117+. */\n costLedger?: CostLedgerHandle\n /** Receipt attribution phase supplied alongside `costLedger`. */\n costPhase?: string\n }): Promise<{ applied: boolean; summary: string }>\n}\n\nexport interface ImprovementDriverOptions {\n worktree: WorktreeAdapter\n generator: CandidateGenerator\n /** Root ref for first-generation/direct callers. Default `main`.\n * Later code generations retain the incumbent's original root. */\n baseRef?: string\n}\n\nexport interface ManagedImprovementDriver extends SurfaceProposer<AnalystFinding> {\n /** Remove every owned candidate except explicitly retained finalized winners. */\n cleanup(retainWorktreeRefs?: readonly string[]): Promise<void>\n}\n\n/** The one reflective/agentic improvement proposer (`SurfaceProposer`): owns the candidate worktree lifecycle and delegates HOW a change is produced to a pluggable `CandidateGenerator`. */\nexport function improvementDriver(opts: ImprovementDriverOptions): ManagedImprovementDriver {\n const baseRef = opts.baseRef ?? 'main'\n const owned = new Map<string, Worktree>()\n\n return {\n kind: `improvement:${opts.generator.kind}`,\n async propose(ctx: ProposeContext<AnalystFinding>) {\n const findings = resolveFindings(ctx)\n // No findings AND no report AND a generator that can only act on findings\n // (the reflective patch-applier) — propose nothing rather than spin up\n // worktrees for a guaranteed no-op. An agentic coder draws its signal from\n // the repo + raw traces on disk, so it opts in via `proposesWithoutFindings`\n // and still runs the full populationSize even on an empty findings set —\n // otherwise the FIRST generation (whose seed findings are empty and whose\n // rawTraceDistiller has not run yet) would always generate ZERO candidates.\n if (\n findings.length === 0 &&\n ctx.report === undefined &&\n !opts.generator.proposesWithoutFindings\n ) {\n return []\n }\n\n const surfaces: CodeSurface[] = []\n const incumbent = verifiedCodeIncumbent(ctx.currentSurface)\n const proposalBaseRef = incumbent?.baseCommit ?? baseRef\n for (let i = 0; i < ctx.populationSize; i++) {\n if (ctx.signal.aborted) break\n const wt = await opts.worktree.create({\n baseRef: proposalBaseRef,\n label: `${opts.generator.kind}-gen${ctx.generation}-cand${i}`,\n })\n owned.set(wt.path, wt)\n // Once a worktree exists it MUST be accounted for: finalized into a\n // surface, or discarded. A throw from generate()/finalize() must not\n // leak the worktree + branch — discard best-effort, then rethrow loud.\n try {\n if (incumbent) advanceToIncumbent(wt, incumbent)\n const { applied, summary } = await opts.generator.generate({\n worktreePath: wt.path,\n report: ctx.report,\n findings,\n dataset: ctx.dataset,\n maxShots: ctx.maxImprovementShots ?? 1,\n signal: ctx.signal,\n generation: ctx.generation,\n candidateIndex: i,\n ...(ctx.costLedger ? { costLedger: ctx.costLedger } : {}),\n ...(ctx.costPhase ? { costPhase: ctx.costPhase } : {}),\n })\n if (!applied) {\n await opts.worktree.discard(wt)\n owned.delete(wt.path)\n continue\n }\n const surface = await opts.worktree.finalize(wt, summary)\n surfaces.push(surface)\n owned.delete(wt.path)\n owned.set(surface.worktreeRef, wt)\n } catch (err) {\n const cleanupErrors: unknown[] = []\n for (let attempt = 0; attempt < 2; attempt += 1) {\n try {\n await opts.worktree.discard(wt)\n owned.delete(wt.path)\n break\n } catch (cause) {\n cleanupErrors.push(cause)\n }\n }\n if (cleanupErrors.length === 0) throw err\n const failure = err instanceof Error ? err.message : String(err)\n const cleanupSucceeded = !owned.has(wt.path)\n throw new AggregateError(\n [err, ...cleanupErrors],\n cleanupSucceeded\n ? `improvementDriver: ${failure}; candidate cleanup retry succeeded`\n : `improvementDriver: ${failure}; candidate worktree could not be cleaned`,\n )\n }\n }\n return surfaces\n },\n async cleanup(retainWorktreeRefs = []) {\n const retained = new Set(retainWorktreeRefs)\n const errors: unknown[] = []\n for (const [worktreeRef, worktree] of owned) {\n if (retained.has(worktreeRef)) continue\n try {\n await opts.worktree.discard(worktree)\n owned.delete(worktreeRef)\n } catch (cause) {\n errors.push(cause)\n }\n }\n if (errors.length > 0) {\n throw new AggregateError(errors, 'improvementDriver: failed to discard candidate worktrees')\n }\n },\n }\n}\n\n/** A code incumbent must still match the immutable identity that was measured. */\nfunction verifiedCodeIncumbent(surface: ProposeContext['currentSurface']): CodeSurface | undefined {\n if (typeof surface !== 'object' || surface.kind !== 'code') return undefined\n verifyCodeSurface(surface)\n return surface\n}\n\n/** Start at the root commit recorded by the incumbent, then fast-forward the\n * fresh branch to the incumbent commit. The worktree stays clean for the\n * generator while `finalize()` still emits one cumulative root-to-candidate\n * patch that can be applied or rolled back independently of prior branches. */\nfunction advanceToIncumbent(worktree: Worktree, incumbent: CodeSurface): void {\n if (worktree.baseCommit !== incumbent.baseCommit || worktree.baseTree !== incumbent.baseTree) {\n throw new Error('improvementDriver: candidate worktree does not match incumbent base identity')\n }\n if (worktree.baseCommit === incumbent.candidateCommit) return\n\n const merge = spawnSync('git', ['merge', '--ff-only', incumbent.candidateCommit], {\n cwd: worktree.path,\n encoding: 'utf8',\n })\n if (merge.error) {\n throw new Error(\n `improvementDriver: failed to start candidate from incumbent: ${merge.error.message}`,\n )\n }\n if (merge.status !== 0) {\n throw new Error(\n `improvementDriver: could not fast-forward candidate to incumbent ${incumbent.candidateCommit}: ${merge.stderr.trim()}`,\n )\n }\n\n const head = spawnSync('git', ['rev-parse', '--verify', 'HEAD'], {\n cwd: worktree.path,\n encoding: 'utf8',\n })\n if (head.error || head.status !== 0 || head.stdout.trim() !== incumbent.candidateCommit) {\n throw new Error('improvementDriver: candidate worktree did not reach the incumbent commit')\n }\n}\n\n/** Phase-2 report carries `findings` when present; else fall back to the\n * loop's `ctx.findings`. The report is opaque to the substrate, so probe it\n * structurally. */\nfunction resolveFindings(ctx: ProposeContext<AnalystFinding>): AnalystFinding[] {\n const report = ctx.report\n if (report && typeof report === 'object' && 'findings' in report) {\n const f = (report as { findings: unknown }).findings\n if (Array.isArray(f) && f.length > 0) return f as AnalystFinding[]\n }\n return ctx.findings\n}\n","/**\n *\n * `rawTraceDistiller` — the meta-harness `analyzeGeneration` producer.\n *\n * The default `generationFailureDistiller` (in `improve.ts`) COMPRESSES each\n * generation's failing cells into ~400-char structured findings before the next\n * proposal round. That is the ACE-style recipe: a small summary is the proposer's\n * whole view of what went wrong. This producer does the opposite — the\n * meta-harness recipe (yoonholee.com/meta-harness): it does NOT summarize. It\n * points the coding-agent proposer at the generation's RAW run traces already on\n * disk under `runDir` — the durable per-cell `spans.jsonl` event logs,\n * `cached-result.json` scores, and any artifacts the substrate persisted — and\n * instructs the agent to `grep`/`cat`/`ls` them to diagnose the failures itself\n * (up to the harness's full context, ~millions of tokens, vs a ~400-char digest).\n *\n * It emits `AnalystFinding[]` so it drops into the SAME `opts.analyzeGeneration`\n * slot the default distiller uses, and renders through the same\n * `agenticGenerator` prompt path (`claim` + `recommended_action`). The findings\n * carry ABSOLUTE paths — the coding harness runs with `cwd` = a candidate\n * worktree, so a relative `runDir` would be uncattable from there.\n *\n * Runtime layout it reads (written by agent-eval's optimization loop):\n *\n * <runDir>/gen-<N>/ ← the generation dir (input.runDir)\n * candidate-<i>/ ← one candidate campaign (campaign.runDir)\n * <sanitized cellId>/ ← one scenario×rep cell\n * spans.jsonl ← the raw trace (event/span log)\n * cached-result.json ← the cell's score + artifact ref\n * <artifacts…> ← whatever the dispatch wrote\n *\n * @experimental\n */\n\nimport { type Dirent, existsSync, readdirSync } from 'node:fs'\nimport { basename, join, resolve } from 'node:path'\nimport { type AnalystFinding, makeFinding } from '@tangle-network/agent-eval'\nimport type { Scenario, SelfImproveOptions } from '@tangle-network/agent-eval/contract'\n\nconst ANALYST_ID = 'raw-trace-distiller'\n/** A cell counts as \"failing\" below this mean composite (matches the default\n * distiller's near-perfect threshold) or when it recorded an `error`. */\nconst PASS_THRESHOLD = 0.999\n\nexport interface RawTraceDistillerOptions {\n /** Anchor the emitted paths at this run root instead of the generation `runDir`\n * the loop passes in. Normally unset — each call points at that generation's\n * own directory (`input.runDir`). Pass an absolute path when you construct the\n * producer ahead of the loop and want a fixed anchor (e.g. a test fixture). */\n runDir?: string\n /** Max candidates to surface trace paths for, worst-scoring first. Default 12. */\n maxCandidates?: number\n /** Max failing cells to enumerate per candidate before collapsing the rest into\n * an \"ls the candidate dir\" pointer. Default 8. */\n maxCellsPerCandidate?: number\n /** Max concrete file paths to list per cell (the agent can always `ls` the dir\n * for the rest). Default 24. */\n maxFilesPerCell?: number\n /** Findings to fall back to when the generation had NO failing cells, so a\n * clean round never wipes the proposer's steering context. Mirrors the default\n * distiller's static-seed fallback. Default: a single instruction finding. */\n fallbackFindings?: unknown[]\n}\n\ninterface CellTrace {\n scenarioId: string\n composite: number\n error?: string\n cellDir: string\n files: string[]\n truncatedFiles: boolean\n}\n\n/**\n * Build an `analyzeGeneration` producer that feeds the proposer RAW-TRACE\n * FILESYSTEM CONTEXT — paths into the prior generation's real run traces plus a\n * grep/cat-to-diagnose instruction — instead of a pre-summarized digest.\n *\n * Drop-in for `opts.analyzeGeneration` on `improve()` / `selfImprove()`:\n *\n * await improve(profile, seedFindings, {\n * surface: 'code',\n * code: { repoRoot },\n * runDir: '/abs/run', // MUST be a real path — the traces live here\n * analyzeGeneration: rawTraceDistiller(),\n * scenarios, judge, agent,\n * })\n */\nexport function rawTraceDistiller<TScenario extends Scenario = Scenario, TArtifact = unknown>(\n options: RawTraceDistillerOptions = {},\n): NonNullable<SelfImproveOptions<TScenario, TArtifact>['analyzeGeneration']> {\n const maxCandidates = options.maxCandidates ?? 12\n const maxCellsPerCandidate = options.maxCellsPerCandidate ?? 8\n const maxFilesPerCell = options.maxFilesPerCell ?? 24\n\n return async (input) => {\n const genRoot = absoluteRunDir(options.runDir ?? input.runDir)\n const durable = isDurable(genRoot)\n\n // Rank candidates worst-first; the worst failures are the highest-signal\n // context for the next edit. Stable sort keeps equal-composite order.\n const ranked = [...input.candidates]\n .map((c) => ({\n surfaceHash: c.surfaceHash,\n composite: c.composite,\n campaignDir: absoluteRunDir(c.campaign.runDir),\n cells: failingCells(c.campaign, maxCellsPerCandidate, maxFilesPerCell),\n }))\n .sort((a, b) => a.composite - b.composite)\n .slice(0, maxCandidates)\n\n const totalFailingCells = ranked.reduce((n, c) => n + c.cells.length, 0)\n\n // A clean generation: keep the proposer's steering context rather than\n // wiping it (parity with the default distiller's static-seed fallback). An\n // EMPTY fallback array means there is no STATIC seed to preserve — it must NOT\n // wipe the context to nothing. Fall through to the default raw-trace\n // instruction so the meta-harness discipline stays live (the agent still\n // inspects the on-disk traces next round, and the finding's `raw-trace-context`\n // area keeps the agenticGenerator's diagnosis-evidence gate armed). A bare\n // `??` would return the empty array and silently disable both.\n if (totalFailingCells === 0) {\n if (options.fallbackFindings && options.fallbackFindings.length > 0) {\n return options.fallbackFindings\n }\n return [\n makeFinding({\n analyst_id: ANALYST_ID,\n severity: 'info',\n area: 'raw-trace-context',\n confidence: 1,\n claim: `Generation ${input.generation} had no failing cells. The full raw run traces are on disk under ${genRoot}.`,\n recommended_action: `To keep improving, grep/cat the raw traces under ${genRoot} (per-cell spans.jsonl + cached-result.json) to find the weakest passing runs, then make a targeted harness-code edit.`,\n evidence_refs: [{ kind: 'artifact', uri: genRoot }],\n metadata: { generation: input.generation, runDir: genRoot, failingCells: 0 },\n }),\n ]\n }\n\n const findings: AnalystFinding[] = []\n\n // 1. The meta-harness instruction: diagnose from the RAW traces, not a digest.\n findings.push(\n makeFinding({\n analyst_id: ANALYST_ID,\n severity: 'high',\n area: 'raw-trace-context',\n confidence: 1,\n claim: `Generation ${input.generation} produced ${totalFailingCells} failing/low-scoring cell(s) across ${ranked.length} candidate(s). Their FULL RAW run traces are on disk under ${genRoot} — the actual event logs (spans.jsonl), scores (cached-result.json), and artifacts, not a summary.${\n durable\n ? ''\n : ' (WARNING: this run root does not exist on disk — it looks like an in-memory run; pass a real runDir to improve() to get raw-trace context.)'\n }`,\n recommended_action: `Do NOT rely on a pre-summarized finding. Before editing, DIAGNOSE from the raw traces: run \\`grep\\`/\\`cat\\`/\\`ls\\` over the trace files and directories named in the following findings to see exactly what each failing run did and why it scored low, then make the smallest harness-code edit that fixes the dominant failure. Start with \\`grep -rIn \"error\" ${genRoot}\\` then \\`cat\\` the spans.jsonl of the worst cell.`,\n evidence_refs: [{ kind: 'artifact', uri: genRoot }],\n metadata: {\n generation: input.generation,\n runDir: genRoot,\n failingCells: totalFailingCells,\n candidates: ranked.length,\n },\n }),\n )\n\n // 2. One finding per failing candidate: its campaign dir + the concrete raw\n // trace files to grep/cat.\n for (const cand of ranked) {\n if (cand.cells.length === 0) continue\n const scenarioList = cand.cells.map((c) => c.scenarioId).join(', ')\n const fileLines = cand.cells\n .map((c) => {\n const header = ` cell ${c.scenarioId} (composite ${c.composite.toFixed(3)}${\n c.error ? `, error: ${truncate(c.error, 160)}` : ''\n }) — dir ${c.cellDir}`\n const files = c.files.map((f) => ` - ${f}`).join('\\n')\n const more = c.truncatedFiles ? `\\n - …(ls ${c.cellDir} for the rest)` : ''\n return c.files.length > 0 ? `${header}\\n${files}${more}` : header\n })\n .join('\\n')\n\n findings.push(\n makeFinding({\n analyst_id: ANALYST_ID,\n severity: cand.composite < 0.5 ? 'critical' : 'high',\n area: 'raw-trace-context',\n confidence: 1,\n subject: cand.surfaceHash,\n claim: `Candidate ${cand.surfaceHash} scored composite ${cand.composite.toFixed(3)} with ${cand.cells.length} failing cell(s) [${scenarioList}]. Its raw traces are under ${cand.campaignDir}.`,\n recommended_action: `grep/cat these raw trace files to diagnose WHY this candidate failed before editing:\\n${fileLines}\\nOr scan the whole candidate at once: \\`grep -rIn . ${cand.campaignDir}\\` and \\`ls -R ${cand.campaignDir}\\`.`,\n evidence_refs: [\n { kind: 'artifact', uri: cand.campaignDir },\n ...cand.cells.flatMap((c) =>\n c.files.map((f) => ({ kind: 'artifact' as const, uri: f })),\n ),\n ],\n metadata: {\n surfaceHash: cand.surfaceHash,\n composite: cand.composite,\n campaignDir: cand.campaignDir,\n cells: cand.cells.map((c) => ({\n scenarioId: c.scenarioId,\n composite: c.composite,\n cellDir: c.cellDir,\n files: c.files,\n ...(c.error ? { error: c.error } : {}),\n })),\n },\n }),\n )\n }\n\n return findings\n }\n}\n\n/** The failing cells of a candidate campaign, each with its on-disk trace files.\n * Mirrors the default distiller's per-cell composite (mean of judge composites,\n * 0 when a cell produced no judge score) and its failing predicate. */\nfunction failingCells(\n campaign: {\n runDir: string\n cells: ReadonlyArray<{\n cellId: string\n scenarioId: string\n error?: string\n judgeScores: Record<string, { composite?: number }>\n }>\n artifactsByPath?: Record<string, string>\n },\n maxCells: number,\n maxFiles: number,\n): CellTrace[] {\n const campaignDir = absoluteRunDir(campaign.runDir)\n const durable = isDurable(campaignDir)\n const out: CellTrace[] = []\n for (const cell of campaign.cells) {\n const scores = Object.values(cell.judgeScores ?? {})\n const composite =\n scores.length === 0\n ? 0\n : scores.reduce((sum, s) => sum + (s.composite ?? 0), 0) / scores.length\n if (!cell.error && composite >= PASS_THRESHOLD) continue\n\n const cellDir = join(campaignDir, sanitizeCellId(cell.cellId))\n const artifactPaths = artifactPathsForCell(campaign.artifactsByPath, cell.cellId)\n const discovered = durable ? listTraceFiles(cellDir) : []\n // Canonical anchors the substrate always writes, kept even when a mem:// run\n // never flushed them to disk (so the agent still learns the expected path).\n const canonical = [join(cellDir, 'spans.jsonl'), join(cellDir, 'cached-result.json')]\n const files = dedupeSorted([...discovered, ...artifactPaths, ...canonical])\n\n out.push({\n scenarioId: cell.scenarioId,\n composite: Number(composite.toFixed(3)),\n ...(cell.error ? { error: cell.error } : {}),\n cellDir,\n files: files.slice(0, maxFiles),\n truncatedFiles: files.length > maxFiles,\n })\n if (out.length >= maxCells) break\n }\n return out\n}\n\n/** Absolute paths of artifacts the campaign recorded for a cell. `artifactsByPath`\n * is keyed `${cellId}/${relPath}` → absolute path. */\nfunction artifactPathsForCell(\n artifactsByPath: Record<string, string> | undefined,\n cellId: string,\n): string[] {\n if (!artifactsByPath) return []\n const prefix = `${cellId}/`\n return Object.entries(artifactsByPath)\n .filter(([key]) => key.startsWith(prefix))\n .map(([, absPath]) => resolve(absPath))\n}\n\n/** Real files directly under `dir` and one level of sub-directories (artifacts\n * are sometimes nested). Absolute paths, sorted. `[]` when the dir is absent,\n * stale, unreadable, or contains symlinked dirs — trace context is advisory and\n * the canonical anchors below still tell the proposer where to inspect. */\nfunction listTraceFiles(dir: string): string[] {\n const out: string[] = []\n for (const entry of safeReadDir(dir)) {\n const full = join(dir, entry.name)\n if (entry.isFile()) {\n out.push(full)\n } else if (!entry.isSymbolicLink() && entry.isDirectory()) {\n for (const sub of safeReadDir(full)) {\n if (sub.isFile()) out.push(join(full, sub.name))\n }\n }\n }\n return out\n}\n\nfunction safeReadDir(dir: string): Dirent[] {\n try {\n return readdirSync(dir, { withFileTypes: true })\n } catch {\n return []\n }\n}\n\n/** Substrate cell-dir sanitization — must match agent-eval's\n * `cellId.replace(/[^a-zA-Z0-9_-]/g, '_')` so the computed dir matches disk. */\nfunction sanitizeCellId(cellId: string): string {\n return cellId.replace(/[^a-zA-Z0-9_-]/g, '_')\n}\n\n/** A run root is durable (has real files) when it is not an in-memory sentinel\n * and exists on disk. `mem://` runs keep everything in-process — no traces. */\nfunction isDurable(runDir: string): boolean {\n return !runDir.startsWith('mem://') && existsSync(runDir)\n}\n\n/** Resolve a run dir to absolute (the coding harness runs from a worktree cwd, so\n * relative paths are uncattable there). `mem://` sentinels pass through untouched. */\nfunction absoluteRunDir(runDir: string): string {\n return runDir.startsWith('mem://') ? runDir : resolve(runDir)\n}\n\nfunction dedupeSorted(paths: string[]): string[] {\n return [...new Set(paths)].sort((a, b) => {\n // Group by directory then filename for a stable, readable listing.\n const da = a.slice(0, a.length - basename(a).length)\n const db = b.slice(0, b.length - basename(b).length)\n return da === db ? basename(a).localeCompare(basename(b)) : da.localeCompare(db)\n })\n}\n\nfunction truncate(s: string, n: number): string {\n return s.length <= n ? s : `${s.slice(0, n - 1)}…`\n}\n","/**\n *\n * `improve` — the ONE public, surface-pluggable RSI verb.\n *\n * A thin facade over agent-eval's `selfImprove` (the held-out-gated closed\n * loop). It removes the two things a caller otherwise has to know to drive the\n * loop by hand: WHICH `MutableSurface` of the profile is being optimized, and\n * WHICH `SurfaceProposer` mutates that surface. You name a `surface`; the\n * facade picks the matching default proposer, extracts the baseline surface from\n * the profile, runs `selfImprove`, and (on a ship verdict) writes the promoted\n * winner back into the corresponding profile field.\n *\n * - `surface: 'prompt'` → `gepaProposer` mutates `profile.prompt.systemPrompt`.\n * - `surface: 'skills'` → `skillOptProposer` mutates a skills document string.\n * - `surface: 'memory'` → `memoryCurationProposer` curates a bounded durable\n * lesson document supplied through `opts.memory`.\n * - `surface: 'agent-profile'` → caller-supplied proposer mutates the complete\n * canonical AgentProfile JSON in one candidate.\n * - `surface` ∈ {`tools`, `mcp`, `hooks`, `subagents`, `agent-profile`} → no zero-config default\n * proposer exists (a code/config proposer needs caller-supplied wiring — a\n * worktree repo root, a candidate generator, a serializer). The facade\n * requires an explicit `opts.generator` for these and throws a `ConfigError`\n * otherwise. This is a designed boundary, not a missing default: there is\n * no safe value the facade could invent for those surfaces. Code instead\n * requires `opts.code.repoRoot` and accepts only the runtime-owned\n * `opts.code.generator` path so every isolated checkout can be released.\n *\n * Everything else (`scenarios`, `judge`, `agent`, `budget`, `llm`) passes\n * straight through to `selfImprove`.\n *\n * @experimental\n */\n\nimport { canonicalJson } from '@tangle-network/agent-eval'\nimport {\n gepaProposer,\n gitWorktreeAdapter,\n memoryCurationProposer,\n skillOptProposer,\n type Worktree,\n type WorktreeAdapter,\n} from '@tangle-network/agent-eval/campaign'\nimport {\n type CodeSurface,\n type MutableSurface,\n type Scenario,\n type SelfImproveBudget,\n type SelfImproveLlm,\n type SelfImproveOptions,\n type SelfImproveResult,\n type SurfaceProposer,\n selfImprove,\n} from '@tangle-network/agent-eval/contract'\nimport { type AgentProfile, agentProfileSchema } from '@tangle-network/agent-interface'\nimport { ConfigError } from '../errors'\nimport type { LocalHarness } from '../mcp/local-harness'\nimport { assertModelAllowed } from '../runtime/supervise/model-policy'\nimport { agenticGenerator, type Verifier } from './agentic-generator'\nimport {\n type CandidateGenerator,\n improvementDriver,\n type ManagedImprovementDriver,\n} from './improvement-driver'\nimport { rawTraceDistiller } from './raw-trace-distiller'\n\n/** The executable agent lever `improve` optimizes. Profile fields remain\n * portable AgentProfile coordinates; implementation and orchestration files\n * use the code surface so a winner can be sealed into an exact candidate. */\nexport type ImproveSurface =\n | 'prompt'\n | 'skills'\n | 'tools'\n | 'mcp'\n | 'hooks'\n | 'subagents'\n | 'agent-profile'\n | 'memory'\n | 'code'\n\nexport type ImproveOptions<TScenario extends Scenario, TArtifact> = Omit<\n SelfImproveOptions<TScenario, TArtifact>,\n 'analyzeGeneration' | 'baselineSurface' | 'findings' | 'gate' | 'proposer'\n> & {\n /** Which profile lever to optimize. Default `'prompt'`. Selects the default\n * generator + the baseline-surface extraction shape. */\n surface?: ImproveSurface\n /** The `SurfaceProposer` that mutates a profile surface. When unset, the facade\n * picks the default for prompt, skills, and memory; surfaces\n * with no default REQUIRE this (fail-loud otherwise). Forbidden for code;\n * use `code.generator` so the runtime owns candidate cleanup. */\n generator?: SurfaceProposer\n /** Gate mode. `'holdout'` (default) runs the held-out promotion gate;\n * `'none'` is a baseline-only run (`budget.generations = 0`). */\n gate?: 'holdout' | 'none'\n /** Restrict the run to this subset of models. When set, the reflection model\n * (`llm.model`, or the default when unset) must be a member, or `improve()` throws\n * a `ConfigError` before the generator is built. Unset = unrestricted. */\n allowedModels?: readonly string[]\n /** Per-generation findings producer passthrough (see selfImprove.analyzeGeneration).\n * DEFAULT: the built-in failure distiller — after each generation it turns the\n * worst-scoring/errored cells into structured findings ({ scenario, composite,\n * notes, error }) for the NEXT proposal round, so the proposer reasons over what\n * actually failed instead of a static seed. Pass your own producer (e.g. a\n * trace-analyst over the runDir's traces) to replace it; pass `null` to disable\n * and keep the static `findings` all the way through. */\n analyzeGeneration?: SelfImproveOptions<TScenario, TArtifact>['analyzeGeneration'] | null\n /** META-HARNESS mode: instead of the ~400-char distilled findings, feed the\n * proposer RAW-TRACE FILESYSTEM CONTEXT — the PATHS into the prior generation's\n * real run traces under `runDir` (per-cell `spans.jsonl` event logs +\n * `cached-result.json` scores + artifacts) plus a `grep`/`cat`-to-diagnose\n * instruction — so the coding agent reads the actual failures itself rather than\n * a pre-summary. Requires a REAL `runDir` (that is where the traces live).\n * Ignored when `analyzeGeneration` is set explicitly (that wins) or is `null`\n * (disabled). Equivalent to `analyzeGeneration: rawTraceDistiller()`; this flag\n * is the one-line enable. Default `false` (the distiller stays the default). */\n rawTraceContext?: boolean\n /** CODE-surface wiring: name `surface: 'code'`, point at a repo, and the\n * facade assembles the whole candidate pipeline — an isolated incumbent plus git worktrees\n * (`gitWorktreeAdapter`) driven by `improvementDriver` with the full agentic\n * generator (a real coding harness edits each candidate worktree; a `verify`\n * hook gates candidates before they are ever measured). Ignored when\n * `opts.generator` is supplied. Required for every code run because a real\n * repository and base ref are necessary to measure the incumbent. */\n code?: ImproveCodeOptions\n /** SKILLS-surface wiring for real skill-DOCUMENT optimization. Without this,\n * `surface: 'skills'` optimizes the profile's skills REFS array (file pointers)\n * — which `skillOptProposer` (a document patcher) cannot meaningfully edit.\n * Provide the document CONTENT to optimize + a `writeBack` to persist the\n * shipped winner (the profile ref points at a file the caller owns). This is\n * what makes skillOpt reachable through improve(). */\n skills?: ImproveSkillsOptions\n /** MEMORY-surface wiring for a curated durable memory document. The default\n * deterministic proposer deduplicates and ranks lessons from findings, then\n * replaces its managed block instead of growing memory without bound. */\n memory?: ImproveMemoryOptions\n /** Custom held-back-exam decision. The string `gate` above controls whether\n * the exam runs; this callback controls how its evidence decides promotion. */\n promotionGate?: SelfImproveOptions<TScenario, TArtifact>['gate']\n}\n\nexport interface ImproveSkillsOptions {\n /** The skill document's current text — the baseline `skillOptProposer` patches. */\n document: string\n /** Persist the shipped winner document (write the file the profile ref points at).\n * Called only on a ship verdict. When omitted, the winner is still returned in\n * `result.raw.winner.surface` for the caller to materialize. */\n writeBack?: (winnerDocument: string) => void | Promise<void>\n}\n\nexport interface ImproveMemoryOptions {\n /** Current durable memory text used as the measured baseline. */\n document: string\n /** Persist the promoted memory document. Never called on hold or error. */\n writeBack?: (winnerDocument: string) => void | Promise<void>\n}\n\nexport interface ImproveCodeOptions {\n /** Repo root candidate worktrees fork from. */\n repoRoot: string\n /** Base ref candidates fork from. Default `main`. */\n baseRef?: string\n /** Directory worktrees are created under. Default `<repoRoot>/.worktrees`. */\n worktreeDir?: string\n /** Git-compatible adapter override, primarily for tests. Candidate advancement\n * still requires normal Git worktree and commit semantics. */\n worktree?: WorktreeAdapter\n /** Coding harness the agentic generator runs in each worktree. Default `claude`. */\n harness?: LocalHarness\n /** Verify a candidate worktree before it becomes a measurable surface; failures\n * feed the next shot (see `agenticGenerator.verify` / `commandVerifier`). */\n verify?: Verifier\n /** Per-shot wall-clock timeout for the harness (ms). */\n timeoutMs?: number\n /** Byte-producer override — the test seam and the escape hatch for custom\n * candidate production. When set, `harness`/`verify`/`timeoutMs` are unused. */\n generator?: CandidateGenerator\n}\n\nexport interface ImproveResult<TScenario extends Scenario, TArtifact> {\n /** The profile after improvement: the winner surface applied back into the\n * matching field when the gate shipped, else the input profile unchanged. */\n profile: AgentProfile\n /** True when `gateDecision === 'ship'`. */\n shipped: boolean\n /** Held-out lift (`winner − baseline` composite). */\n lift: number\n /** The five-valued gate verdict from `selfImprove`. */\n gateDecision: SelfImproveResult<TScenario, TArtifact>['gateDecision']\n /** Full `selfImprove` result for advanced inspection. For code runs,\n * `raw.winner.surface.worktreeRef` remains live after return whether the\n * candidate shipped or held; call `dispose()` after consuming it. */\n raw: SelfImproveResult<TScenario, TArtifact>\n /** Release resources owned by this result. Idempotent; currently disposes\n * the returned code worktree and is a no-op for profile-only surfaces. */\n dispose(): Promise<void>\n}\n\n/** Default model id for the reflective drivers when `llm.model` is unset — a model the Tangle\n * router actually serves (callers should pass their own `llm.model`). */\nconst defaultReflectionModel = 'deepseek-v4-flash'\n\n/** The reflective proposers (`gepaProposer`/`skillOptProposer`) take a full\n * `LlmClientOptions`; `SelfImproveLlm` is the thin user-facing subset. */\nfunction llmClientOptions(llm: SelfImproveLlm | undefined): { baseUrl?: string; apiKey?: string } {\n return { baseUrl: llm?.baseUrl, apiKey: llm?.apiKey }\n}\n\n/** The default proposer for a surface, or `undefined` when the surface has no\n * zero-config default (the caller must supply `opts.generator`). */\nfunction defaultGeneratorFor(\n surface: ImproveSurface,\n llm: SelfImproveLlm | undefined,\n): SurfaceProposer | undefined {\n const model = llm?.model ?? defaultReflectionModel\n switch (surface) {\n case 'prompt':\n return gepaProposer({ llm: llmClientOptions(llm), model, target: 'agent system prompt' })\n case 'skills':\n return skillOptProposer({ llm: llmClientOptions(llm), model, target: 'agent skill document' })\n case 'memory':\n return memoryCurationProposer()\n default:\n return undefined\n }\n}\n\n/** Extract the baseline surface a driver mutates from the profile field that\n * backs `surface`. Prompt, skills, and memory are text surfaces; config\n * surfaces serialize the matching profile record. */\nfunction baselineSurfaceFor(\n profile: AgentProfile,\n surface: ImproveSurface,\n skills?: ImproveSkillsOptions,\n memory?: ImproveMemoryOptions,\n): MutableSurface {\n switch (surface) {\n case 'prompt':\n return profile.prompt?.systemPrompt ?? ''\n case 'skills':\n // With a document supplied, optimize its CONTENT (the real skillOpt path);\n // otherwise fall back to the refs-array surface for back-compat.\n return skills?.document ?? JSON.stringify(profile.resources?.skills ?? [])\n case 'tools':\n return JSON.stringify(profile.tools ?? {})\n case 'mcp':\n return JSON.stringify(profile.mcp ?? {})\n case 'hooks':\n return JSON.stringify(profile.hooks ?? {})\n case 'subagents':\n return JSON.stringify(profile.subagents ?? {})\n case 'agent-profile':\n return canonicalJson(profile)\n case 'memory':\n if (!memory) {\n throw new ConfigError(\"improve(): surface 'memory' requires opts.memory.document\")\n }\n return memory.document\n case 'code':\n throw new ConfigError(\n 'improve(): code requires the isolated baseline created from opts.code.repoRoot',\n )\n }\n}\n\n/** The default `analyzeGeneration`: distill each generation's failing cells into\n * findings for the next proposal round. Deliberately dependency-free — judge notes\n * and errors are already the domain's own diagnosis (executable gates put their\n * reasons there); a trace-analyst can replace this wholesale via\n * `opts.analyzeGeneration`. Falls back to the static seed findings when the\n * generation had no failures, so a clean round never wipes the seed context. */\nfunction generationFailureDistiller<TScenario extends Scenario, TArtifact>(\n staticFindings: unknown[],\n): NonNullable<SelfImproveOptions<TScenario, TArtifact>['analyzeGeneration']> {\n const CAP = 12\n return async (input) => {\n const failures: Array<{\n scenario: string\n composite: number\n notes: string\n claim?: string\n error?: string\n }> = []\n for (const candidate of input.candidates) {\n for (const rawCell of candidate.campaign.cells) {\n const cell = rawCell as unknown as Record<string, unknown>\n const scenario = String(cell.scenarioId ?? 'unknown')\n const error = typeof cell.error === 'string' ? cell.error : undefined\n const judgeScores =\n cell.judgeScores && typeof cell.judgeScores === 'object'\n ? Object.values(\n cell.judgeScores as Record<string, { composite?: number; notes?: string }>,\n )\n : []\n const composite =\n judgeScores.length === 0\n ? 0\n : judgeScores.reduce((sum, j) => sum + (j.composite ?? 0), 0) / judgeScores.length\n if (!error && composite >= 0.999) continue\n const notes = judgeScores\n .map((j) => j.notes)\n .filter((n): n is string => typeof n === 'string' && n.length > 0)\n .join('; ')\n .slice(0, 400)\n const claim = notes || (error ? `Scenario ${scenario} failed: ${error.slice(0, 200)}` : '')\n failures.push({\n scenario,\n composite: Number(composite.toFixed(3)),\n notes,\n ...(claim ? { claim } : {}),\n ...(error ? { error: error.slice(0, 200) } : {}),\n })\n }\n }\n if (failures.length === 0) return staticFindings\n failures.sort((a, b) => a.composite - b.composite)\n return failures.slice(0, CAP)\n }\n}\n\n/** Memory accumulates durable lessons, so keep the caller's seed findings while\n * adding fresh judge failures. Curator proposers consume `claim`; the generic\n * distiller retains the richer diagnostic fields for reflective proposers. */\nfunction memoryGenerationDistiller<TScenario extends Scenario, TArtifact>(\n staticFindings: unknown[],\n): NonNullable<SelfImproveOptions<TScenario, TArtifact>['analyzeGeneration']> {\n const distillFailures = generationFailureDistiller<TScenario, TArtifact>(staticFindings)\n return async (input) => {\n const fresh = await distillFailures(input)\n return fresh === staticFindings ? staticFindings : [...staticFindings, ...fresh]\n }\n}\n\ninterface PreparedCodeRun {\n baseline: CodeSurface\n proposer: SurfaceProposer\n cleanup(retainedWinner?: MutableSurface): Promise<void>\n}\n\n/** Preserve the primary failure while making two best-effort cleanup attempts.\n * A failed first attempt is retained in the thrown AggregateError even when the\n * retry succeeds, so callers can diagnose degraded cleanup without losing the\n * error that caused cleanup to run. */\nasync function rethrowAfterCleanup(\n cause: unknown,\n cleanup: () => Promise<void>,\n message: string,\n): Promise<never> {\n const cleanupErrors: unknown[] = []\n for (let attempt = 0; attempt < 2; attempt += 1) {\n try {\n await cleanup()\n } catch (cleanupCause) {\n cleanupErrors.push(cleanupCause)\n continue\n }\n if (cleanupErrors.length === 0) throw cause\n throw new AggregateError([cause, ...cleanupErrors], `${message}; the cleanup retry succeeded`)\n }\n throw new AggregateError([cause, ...cleanupErrors], message)\n}\n\nasync function discardPreparedBaseline(\n worktree: WorktreeAdapter,\n baselineWorktree: Worktree,\n cause: unknown,\n): Promise<never> {\n return rethrowAfterCleanup(\n cause,\n () => worktree.discard(baselineWorktree),\n 'improve(): code preparation failed and its baseline worktree could not be cleaned',\n )\n}\n\nfunction isCodeSurface(surface: MutableSurface | undefined): surface is CodeSurface {\n return typeof surface === 'object' && surface !== null && surface.kind === 'code'\n}\n\n/** Create a clean incumbent checkout and the candidate producer for a code run. */\nasync function prepareCodeRun(code: ImproveCodeOptions): Promise<PreparedCodeRun> {\n const baseRef = code.baseRef ?? 'main'\n const worktree =\n code.worktree ??\n gitWorktreeAdapter({\n repoRoot: code.repoRoot,\n ...(code.worktreeDir ? { worktreeDir: code.worktreeDir } : {}),\n })\n const baselineWorktree = await worktree.create({ baseRef, label: 'incumbent-baseline' })\n try {\n const baseline = await worktree.finalize(baselineWorktree, 'Incumbent code checkout')\n let baselineDiscarded = false\n const generator =\n code.generator ??\n agenticGenerator({\n ...(code.harness ? { harness: code.harness } : {}),\n ...(code.verify ? { verify: code.verify } : {}),\n ...(code.timeoutMs ? { timeoutMs: code.timeoutMs } : {}),\n })\n const managed: ManagedImprovementDriver = improvementDriver({ worktree, generator, baseRef })\n\n return {\n baseline,\n proposer: managed,\n async cleanup(retainedWinner) {\n const errors: unknown[] = []\n const retainedWorktreeRef = isCodeSurface(retainedWinner)\n ? retainedWinner.worktreeRef\n : undefined\n try {\n await managed?.cleanup(retainedWorktreeRef ? [retainedWorktreeRef] : [])\n } catch (cause) {\n errors.push(cause)\n }\n if (!baselineDiscarded && retainedWorktreeRef !== baseline.worktreeRef) {\n try {\n await worktree.discard(baselineWorktree)\n baselineDiscarded = true\n } catch (cause) {\n errors.push(cause)\n }\n }\n if (errors.length > 0) {\n throw new AggregateError(errors, 'improve(): failed to clean code improvement worktrees')\n }\n },\n }\n } catch (cause) {\n return discardPreparedBaseline(worktree, baselineWorktree, cause)\n }\n}\n\nfunction idempotentDispose(dispose: () => Promise<void>): () => Promise<void> {\n let disposed = false\n let inFlight: Promise<void> | undefined\n return async () => {\n if (disposed) return\n if (inFlight) return inFlight\n inFlight = (async () => {\n await dispose()\n disposed = true\n })()\n try {\n await inFlight\n } finally {\n inFlight = undefined\n }\n }\n}\n\n/** Parse a JSON winner surface (`tools`/`mcp`/`hooks`/`subagents`/`agent-profile`) with a typed,\n * contextual error. A malformed generator output must fail loud here, not throw\n * a raw `SyntaxError` to the caller after a ship verdict. */\nfunction parseWinnerJson<T>(winner: string, surface: ImproveSurface): T {\n try {\n return JSON.parse(winner) as T\n } catch (cause) {\n throw new ConfigError(\n `improve(): the shipped '${surface}' winner is not valid JSON, so it cannot be applied back to the profile: ${\n (cause as Error).message\n }`,\n )\n }\n}\n\n/** Apply a promoted winner surface back into the profile field for `surface`.\n * Returns a shallow copy; never mutates the input profile. */\nexport function applyImprovementWinnerToProfile(\n profile: AgentProfile,\n surface: ImproveSurface,\n winner: MutableSurface,\n): AgentProfile {\n // Only string surfaces map cleanly back onto a profile field. A `CodeSurface`\n // winner (the `code` lever) is a worktree ref, not a profile value — the\n // caller materializes it from `raw.winner.surface`; the returned profile is\n // unchanged for that lever.\n if (typeof winner !== 'string') return profile\n let candidate: AgentProfile\n switch (surface) {\n case 'prompt':\n candidate = { ...profile, prompt: { ...profile.prompt, systemPrompt: winner } }\n break\n case 'skills':\n candidate = {\n ...profile,\n resources: { ...profile.resources, skills: parseWinnerJson(winner, surface) },\n }\n break\n case 'tools':\n candidate = { ...profile, tools: parseWinnerJson(winner, surface) }\n break\n case 'mcp':\n candidate = { ...profile, mcp: parseWinnerJson(winner, surface) }\n break\n case 'hooks':\n candidate = { ...profile, hooks: parseWinnerJson(winner, surface) }\n break\n case 'subagents':\n candidate = { ...profile, subagents: parseWinnerJson(winner, surface) }\n break\n case 'agent-profile':\n candidate = parseWinnerJson(winner, surface)\n break\n case 'memory':\n return profile\n case 'code':\n return profile\n }\n const parsed = agentProfileSchema.safeParse(candidate)\n if (!parsed.success) {\n throw new ConfigError(\n `improve(): the shipped '${surface}' winner does not produce a valid AgentProfile: ${parsed.error.message}`,\n )\n }\n return parsed.data\n}\n\n/**\n * Run the held-out-gated self-improvement loop on ONE profile surface.\n *\n * @example Optimize the system prompt, default holdout gate:\n *\n * const out = await improve(profile, findings, {\n * surface: 'prompt',\n * scenarios,\n * judge,\n * agent: (surface, scenario, ctx) => runAgent(surface, scenario, ctx.signal),\n * })\n * if (out.shipped) deploy(out.profile)\n */\nexport async function improve<TScenario extends Scenario, TArtifact>(\n profile: AgentProfile,\n findings: unknown[],\n opts: ImproveOptions<TScenario, TArtifact>,\n): Promise<ImproveResult<TScenario, TArtifact>> {\n const {\n surface = 'prompt',\n gate = 'holdout',\n generator,\n allowedModels,\n rawTraceContext,\n code,\n skills,\n memory,\n promotionGate,\n analyzeGeneration,\n ...sharedOptions\n } = opts\n\n const parsedProfile = agentProfileSchema.safeParse(profile)\n if (!parsedProfile.success) {\n throw new ConfigError(\n `improve(): input is not a valid AgentProfile: ${parsedProfile.error.message}`,\n )\n }\n if (surface === 'skills' && !generator && !skills) {\n throw new ConfigError(\n 'improve(): the default skills optimizer requires opts.skills.document; pass the skill text or an explicit generator that understands resource refs',\n )\n }\n if (surface === 'memory' && !memory) {\n throw new ConfigError(\"improve(): surface 'memory' requires opts.memory.document\")\n }\n if (surface === 'code' && generator) {\n throw new ConfigError(\n \"improve(): surface 'code' forbids opts.generator because an external SurfaceProposer cannot transfer checkout ownership; pass opts.code.generator instead\",\n )\n }\n const usesReflectionModel = !generator && (surface === 'prompt' || surface === 'skills')\n if (usesReflectionModel) {\n assertModelAllowed(sharedOptions.llm?.model ?? defaultReflectionModel, allowedModels)\n }\n\n let preparedCode: PreparedCodeRun | undefined\n if (surface === 'code') {\n if (!code) {\n throw new ConfigError(\n \"improve(): surface 'code' requires opts.code.repoRoot so the incumbent can run from an isolated checkout\",\n )\n }\n preparedCode = await prepareCodeRun(code)\n }\n const proposer =\n preparedCode?.proposer ?? generator ?? defaultGeneratorFor(surface, sharedOptions.llm)\n if (!proposer) {\n throw new ConfigError(\n `improve(): surface '${surface}' has no default generator — pass opts.generator (a SurfaceProposer) explicitly`,\n )\n }\n\n const budget: SelfImproveBudget =\n gate === 'none' ? { ...sharedOptions.budget, generations: 0 } : { ...sharedOptions.budget }\n\n let raw: SelfImproveResult<TScenario, TArtifact>\n try {\n raw = await selfImprove<TScenario, TArtifact>({\n ...sharedOptions,\n baselineSurface:\n preparedCode?.baseline ?? baselineSurfaceFor(profile, surface, skills, memory),\n proposer,\n budget,\n findings,\n ...(promotionGate !== undefined ? { gate: promotionGate } : {}),\n ...(analyzeGeneration === null\n ? {}\n : {\n analyzeGeneration:\n analyzeGeneration ??\n (rawTraceContext\n ? rawTraceDistiller<TScenario, TArtifact>({ fallbackFindings: findings })\n : surface === 'memory'\n ? memoryGenerationDistiller<TScenario, TArtifact>(findings)\n : generationFailureDistiller<TScenario, TArtifact>(findings)),\n }),\n })\n } catch (cause) {\n if (!preparedCode) throw cause\n return rethrowAfterCleanup(\n cause,\n () => preparedCode.cleanup(),\n 'improve(): code improvement failed and its worktrees could not be cleaned',\n )\n }\n\n const shipped = raw.gateDecision === 'ship'\n const winnerSurface = raw.winner.surface\n if (preparedCode) {\n try {\n await preparedCode.cleanup(winnerSurface)\n } catch (cleanupCause) {\n try {\n await preparedCode.cleanup()\n } catch (finalCleanupCause) {\n throw new AggregateError(\n [cleanupCause, finalCleanupCause],\n 'improve(): code result cleanup failed, including the final all-worktree retry',\n )\n }\n throw new AggregateError(\n [cleanupCause],\n 'improve(): code result cleanup failed; the final all-worktree retry succeeded',\n )\n }\n }\n const dispose = idempotentDispose(async () => preparedCode?.cleanup())\n // When a skill DOCUMENT was optimized, the winner is document text — persist it\n // via writeBack (the profile ref points at the caller's file, unchanged) rather\n // than parsing it as a refs array. Otherwise use the standard field write-back.\n const externalDocument =\n surface === 'skills' && skills ? skills : surface === 'memory' && memory ? memory : undefined\n if (shipped && externalDocument) {\n if (typeof winnerSurface !== 'string') {\n throw new ConfigError(\n `improve(): the shipped '${surface}' winner must be text before it can be persisted`,\n )\n }\n await externalDocument.writeBack?.(winnerSurface)\n }\n const nextProfile =\n shipped && !externalDocument\n ? applyImprovementWinnerToProfile(profile, surface, winnerSurface)\n : profile\n\n return {\n profile: nextProfile,\n shipped,\n lift: raw.lift,\n gateDecision: raw.gateDecision,\n raw,\n dispose,\n }\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/runtime/environment-provider.ts"],"sourcesContent":["import type {\n AgentProfile,\n AgentProfileValidationResult,\n InputPart,\n TokenUsage,\n} from '@tangle-network/agent-interface'\nimport type {\n AgentEnvironment,\n AgentEnvironmentCapabilities,\n AgentEnvironmentEvent,\n AgentEnvironmentProvider,\n AgentEnvironmentQuery,\n AgentEnvironmentStatus,\n AgentEnvironmentSummary,\n AgentProfileRef,\n AgentSession,\n AgentSessionRef,\n AgentSessionStatus,\n AgentTurnInput,\n AgentTurnResult,\n CheckpointRef,\n CheckpointRequest,\n CreateAgentEnvironmentInput,\n ExecRequest,\n ExecResult,\n ForkRequest,\n PlacementInfo,\n ResourceRequest,\n} from '@tangle-network/agent-interface/environment-provider'\nimport type {\n BackendType,\n CreateSandboxOptions,\n PromptOptions,\n PromptResult,\n SandboxEvent,\n ExecResult as SandboxExecResult,\n SandboxInstance,\n} from '@tangle-network/sandbox'\nimport type {\n Executor,\n ExecutorContext,\n ExecutorFactory,\n ExecutorResult,\n Runtime,\n Spend,\n UsageEvent,\n} from './supervise/types'\nimport type { LoopSandboxPlacement, SandboxClient } from './types'\nimport { zeroTokenUsage } from './util'\n\n// Keep this file loadable from the lean `./environment-provider` export without agent-eval installed.\nclass ValidationError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options)\n this.name = 'ValidationError'\n }\n}\n\nexport type {\n AgentEnvironment,\n AgentEnvironmentCapabilities,\n AgentEnvironmentEvent,\n AgentEnvironmentProvider,\n AgentEnvironmentQuery,\n AgentEnvironmentStatus,\n AgentEnvironmentSummary,\n AgentProfileRef,\n AgentSession,\n AgentSessionRef,\n AgentSessionStatus,\n AgentTurnInput,\n AgentTurnResult,\n CheckpointRef,\n CheckpointRequest,\n CreateAgentEnvironmentInput,\n ExecRequest,\n ExecResult,\n ForkRequest,\n PlacementInfo,\n ResourceRequest,\n WorkspaceRequest,\n} from '@tangle-network/agent-interface/environment-provider'\n\n/** Provider object or registry name accepted by runtime provider adapters.\n * @experimental */\nexport type AgentEnvironmentProviderRef = AgentEnvironmentProvider | string\n\n/** In-memory registry for named `AgentEnvironmentProvider` instances.\n * @experimental */\nexport interface AgentEnvironmentProviderRegistry {\n register(provider: AgentEnvironmentProvider, options?: { replace?: boolean }): void\n has(name: string): boolean\n get(name: string): AgentEnvironmentProvider | undefined\n require(name: string): AgentEnvironmentProvider\n names(): string[]\n providers(): AgentEnvironmentProvider[]\n capabilities(name: string): Promise<AgentEnvironmentCapabilities>\n}\n\n/** Create a registry that resolves provider names to concrete provider instances.\n * @experimental */\nexport function createAgentEnvironmentProviderRegistry(\n providers: Iterable<AgentEnvironmentProvider> = [],\n): AgentEnvironmentProviderRegistry {\n const entries = new Map<string, AgentEnvironmentProvider>()\n\n const registry: AgentEnvironmentProviderRegistry = {\n register(provider, options = {}): void {\n if (!provider.name) {\n throw new ValidationError('agent environment provider registry: provider.name required')\n }\n if (!options.replace && entries.has(provider.name)) {\n throw new ValidationError(\n `agent environment provider registry: provider \"${provider.name}\" already registered`,\n )\n }\n entries.set(provider.name, provider)\n },\n has(name): boolean {\n return entries.has(name)\n },\n get(name): AgentEnvironmentProvider | undefined {\n return entries.get(name)\n },\n require(name): AgentEnvironmentProvider {\n const provider = entries.get(name)\n if (!provider) {\n const available = Array.from(entries.keys()).sort()\n const suffix = available.length > 0 ? `; available: ${available.join(', ')}` : ''\n throw new ValidationError(\n `agent environment provider registry: provider \"${name}\" is not registered${suffix}`,\n )\n }\n return provider\n },\n names(): string[] {\n return Array.from(entries.keys()).sort()\n },\n providers(): AgentEnvironmentProvider[] {\n return registry.names().map((name) => registry.require(name))\n },\n async capabilities(name): Promise<AgentEnvironmentCapabilities> {\n return registry.require(name).capabilities()\n },\n }\n\n for (const provider of providers) registry.register(provider)\n return registry\n}\n\n/** Resolve a provider instance or registry name, failing loudly when a name is unknown.\n * @experimental */\nexport function resolveAgentEnvironmentProvider(\n provider: AgentEnvironmentProviderRef,\n registry?: AgentEnvironmentProviderRegistry,\n): AgentEnvironmentProvider {\n if (typeof provider !== 'string') return provider\n if (!registry) {\n throw new ValidationError(\n `agent environment provider \"${provider}\" requires an AgentEnvironmentProviderRegistry`,\n )\n }\n return registry.require(provider)\n}\n\n/** Options for exposing an `AgentEnvironmentProvider` through the legacy sandbox client port.\n * @experimental */\nexport interface ProviderAsSandboxClientOptions {\n defaults?: Partial<CreateAgentEnvironmentInput>\n requireTerminalEvent?: boolean\n mapCreateOptions?: (\n options: CreateSandboxOptions | undefined,\n ) => Partial<CreateAgentEnvironmentInput>\n}\n\n/** Adapt a neutral environment provider to the `SandboxClient` interface used by existing loop paths.\n * @experimental */\nexport function providerAsSandboxClient(\n provider: AgentEnvironmentProvider,\n options: ProviderAsSandboxClientOptions = {},\n): SandboxClient {\n return {\n async create(createOptions?: CreateSandboxOptions): Promise<SandboxInstance> {\n const mapped = {\n ...(options.defaults ?? {}),\n ...createInputFromSandboxOptions(createOptions),\n ...(options.mapCreateOptions?.(createOptions) ?? {}),\n }\n if (mapped.profile === undefined) {\n throw new ValidationError(\n `providerAsSandboxClient(${provider.name}): profile required in defaults or CreateSandboxOptions.backend.profile`,\n )\n }\n const environment = await provider.create(mapped as CreateAgentEnvironmentInput)\n return environmentAsSandboxInstance(environment, {\n requireTerminalEvent: options.requireTerminalEvent ?? true,\n })\n },\n }\n}\n\n/** Options for wrapping the current Tangle sandbox client as an environment provider.\n * @experimental */\nexport interface SandboxClientProviderOptions {\n name?: string\n defaultBackend?: BackendType\n capabilities?:\n | AgentEnvironmentCapabilities\n | (() => AgentEnvironmentCapabilities | Promise<AgentEnvironmentCapabilities>)\n validateProfile?: (\n profile: AgentProfileRef,\n ) => AgentProfileValidationResult | Promise<AgentProfileValidationResult>\n mapCreateInput?: (input: CreateAgentEnvironmentInput) => CreateSandboxOptions\n}\n\n/** Adapt a `SandboxClient` into the shared `AgentEnvironmentProvider` contract.\n * @experimental */\nexport function sandboxClientAsProvider(\n client: SandboxClient,\n options: SandboxClientProviderOptions = {},\n): AgentEnvironmentProvider {\n const providerName = options.name ?? 'tangle-sandbox'\n return {\n name: providerName,\n capabilities: async () => {\n if (options.capabilities) {\n return typeof options.capabilities === 'function'\n ? options.capabilities()\n : options.capabilities\n }\n return defaultTangleSandboxCapabilities()\n },\n ...(options.validateProfile ? { validateProfile: options.validateProfile } : {}),\n async create(input: CreateAgentEnvironmentInput): Promise<AgentEnvironment> {\n const createOptions =\n options.mapCreateInput?.(input) ??\n sandboxOptionsFromCreateInput(input, options.defaultBackend ?? 'opencode')\n const box = await client.create(createOptions)\n return sandboxInstanceAsEnvironment(box, providerName, client)\n },\n ...(hasGet(client)\n ? {\n async get(id: string): Promise<AgentEnvironment | null> {\n const box = await client.get(id)\n return box ? sandboxInstanceAsEnvironment(box, providerName, client) : null\n },\n }\n : {}),\n ...(hasList(client)\n ? {\n async list(query?: AgentEnvironmentQuery): Promise<AgentEnvironmentSummary[]> {\n const boxes = await client.list(query?.providerOptions)\n return boxes.map((box) => ({\n id: String(box.id),\n provider: providerName,\n name: typeof box.name === 'string' ? box.name : undefined,\n status: statusFromUnknown(readBoxStatus(box)),\n metadata: readBoxMetadata(box),\n }))\n },\n }\n : {}),\n }\n}\n\n/** Options for running a provider as a supervise-mode executor.\n * @experimental */\nexport interface ProviderExecutorOptions {\n defaults?: Partial<CreateAgentEnvironmentInput>\n runtime?: Runtime\n destroyOnSettle?: boolean\n requireTerminalEvent?: boolean\n taskToTurn?: (task: unknown, specProfile: AgentProfile) => AgentTurnInput\n}\n\n/** Adapt an environment provider into an `ExecutorFactory` for `createExecutor`.\n * @experimental */\nexport function providerAsExecutor(\n provider: AgentEnvironmentProvider,\n options: ProviderExecutorOptions = {},\n): ExecutorFactory<unknown> {\n return (spec, ctx) => createProviderExecutor(provider, spec.profile, ctx, options)\n}\n\nfunction createProviderExecutor(\n provider: AgentEnvironmentProvider,\n profile: AgentProfile,\n ctx: ExecutorContext,\n options: ProviderExecutorOptions,\n): Executor<unknown> {\n const controller = new AbortController()\n const abortIfSignalled = () => {\n if (ctx.signal.aborted) controller.abort()\n }\n abortIfSignalled()\n if (!ctx.signal.aborted) ctx.signal.addEventListener('abort', abortIfSignalled, { once: true })\n\n let environment: AgentEnvironment | undefined\n let artifact: ExecutorResult<unknown> | undefined\n\n return {\n runtime: options.runtime ?? (provider.name as Runtime),\n execute(task, signal): AsyncIterable<UsageEvent> {\n return streamProviderExecutor({\n provider,\n profile,\n task,\n signal,\n controller,\n options,\n onEnvironment: (env) => {\n environment = env\n },\n onArtifact: (next) => {\n artifact = next\n },\n })\n },\n async teardown(_grace): Promise<{ destroyed: boolean }> {\n controller.abort()\n await environment?.destroy?.()\n return { destroyed: true }\n },\n resultArtifact(): ExecutorResult<unknown> {\n if (!artifact) {\n throw new ValidationError(\n `providerAsExecutor(${provider.name}): resultArtifact() read before stream drained`,\n )\n }\n return artifact\n },\n }\n}\n\ninterface StreamProviderExecutorArgs {\n provider: AgentEnvironmentProvider\n profile: AgentProfile\n task: unknown\n signal: AbortSignal\n controller: AbortController\n options: ProviderExecutorOptions\n onEnvironment: (environment: AgentEnvironment) => void\n onArtifact: (artifact: ExecutorResult<unknown>) => void\n}\n\nasync function* streamProviderExecutor(\n args: StreamProviderExecutorArgs,\n): AsyncIterable<UsageEvent> {\n const started = Date.now()\n const linked = mergeAbortSignals(args.signal, args.controller.signal)\n const environment = await args.provider.create({\n ...(args.options.defaults ?? {}),\n profile: args.profile,\n signal: linked,\n })\n args.onEnvironment(environment)\n\n const turn =\n args.options.taskToTurn?.(args.task, args.profile) ?? taskToTurnInput(args.task, linked)\n const events: AgentEnvironmentEvent[] = []\n const tokens = zeroTokenUsage()\n let usd = 0\n let text = ''\n let terminal = false\n try {\n for await (const event of environment.stream({ ...turn, signal: linked })) {\n events.push(event)\n text += textFromEnvironmentEvent(event)\n const usage = usageFromEnvironmentEvent(event)\n if (usage.input || usage.output) {\n tokens.input += usage.input\n tokens.output += usage.output\n yield { kind: 'tokens', input: usage.input, output: usage.output }\n }\n if (usage.usd) {\n usd += usage.usd\n yield { kind: 'cost', usd: usage.usd }\n }\n if (isTerminalEnvironmentEvent(event)) terminal = true\n }\n if ((args.options.requireTerminalEvent ?? true) && !terminal) {\n throw new ValidationError(\n `providerAsExecutor(${args.provider.name}): stream ended without a terminal result/done/status event`,\n )\n }\n yield { kind: 'iteration' }\n const result = resultFromEvents(events, text)\n const spent: Spend = {\n iterations: 1,\n tokens,\n usd,\n ms: Date.now() - started,\n }\n args.onArtifact({\n outRef: contentRef(`provider:${args.provider.name}`, result),\n out: result,\n spent,\n })\n } finally {\n if (args.options.destroyOnSettle ?? true) await environment.destroy?.()\n }\n}\n\nfunction createInputFromSandboxOptions(\n options: CreateSandboxOptions | undefined,\n): Partial<CreateAgentEnvironmentInput> {\n const profile = options?.backend?.profile as AgentProfileRef | undefined\n const backend = options?.backend?.type\n return {\n ...(profile !== undefined ? { profile } : {}),\n ...(backend ? { backend } : {}),\n workspace: {\n ...(options?.environment ? { environment: options.environment } : {}),\n ...(options?.image ? { image: options.image } : {}),\n ...(options?.git?.url ? { repoUrl: options.git.url } : {}),\n ...(options?.git?.ref ? { gitRef: options.git.ref } : {}),\n },\n ...(options?.resources ? { resources: options.resources as ResourceRequest } : {}),\n ...(options?.env ? { env: options.env } : {}),\n ...(options?.secrets ? { secrets: options.secrets } : {}),\n ...(options?.metadata ? { metadata: options.metadata } : {}),\n ...(options?.name ? { name: options.name } : {}),\n ...(options?.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {}),\n providerOptions: { sandboxCreateOptions: options ?? {} },\n }\n}\n\nfunction sandboxOptionsFromCreateInput(\n input: CreateAgentEnvironmentInput,\n defaultBackend: BackendType,\n): CreateSandboxOptions {\n const backendType = (input.backend ?? defaultBackend) as BackendType\n const workspace = input.workspace ?? {}\n const providerOptions = input.providerOptions?.sandboxCreateOptions\n const base =\n providerOptions && typeof providerOptions === 'object'\n ? ({ ...(providerOptions as CreateSandboxOptions) } as CreateSandboxOptions)\n : ({} satisfies CreateSandboxOptions)\n return {\n ...base,\n ...(workspace.environment ? { environment: workspace.environment } : {}),\n ...(workspace.image ? { image: workspace.image } : {}),\n ...(workspace.repoUrl ? { git: { url: workspace.repoUrl, ref: workspace.gitRef } } : {}),\n ...(input.resources ? { resources: input.resources as CreateSandboxOptions['resources'] } : {}),\n ...(input.env ? { env: input.env } : {}),\n ...(Array.isArray(input.secrets) ? { secrets: input.secrets } : {}),\n ...(input.metadata ? { metadata: input.metadata } : {}),\n ...(input.name ? { name: input.name } : {}),\n ...(input.idempotencyKey ? { idempotencyKey: input.idempotencyKey } : {}),\n backend: {\n ...(base.backend ?? {}),\n type: backendType,\n profile: input.profile,\n },\n }\n}\n\nfunction environmentAsSandboxInstance(\n environment: AgentEnvironment,\n options: { requireTerminalEvent: boolean },\n): SandboxInstance {\n const box = {\n id: environment.id,\n name: environment.name,\n status: 'running',\n async refresh(): Promise<void> {\n await environment.refresh?.()\n },\n async *streamPrompt(\n message: string | InputPart[],\n promptOptions?: PromptOptions,\n ): AsyncGenerator<SandboxEvent> {\n let terminal = false\n const input = turnInputFromPrompt(message, promptOptions)\n for await (const event of environment.stream(input)) {\n if (isTerminalEnvironmentEvent(event)) terminal = true\n const usageEvent = usageSandboxEvent(event)\n if (usageEvent) yield usageEvent\n yield sandboxEventFromEnvironmentEvent(event)\n }\n if (options.requireTerminalEvent && !terminal) {\n throw new ValidationError(\n `providerAsSandboxClient(${environment.provider}): stream ended without a terminal result/done/status event`,\n )\n }\n },\n async prompt(\n message: string | InputPart[],\n promptOptions?: PromptOptions,\n ): Promise<PromptResult> {\n const events: AgentEnvironmentEvent[] = []\n let text = ''\n let usage: TokenUsage | undefined\n let terminal = false\n for await (const event of environment.stream(turnInputFromPrompt(message, promptOptions))) {\n events.push(event)\n if (isTerminalEnvironmentEvent(event)) terminal = true\n text += textFromEnvironmentEvent(event)\n usage = mergeTokenUsage(usage, event.usage)\n }\n if (options.requireTerminalEvent && !terminal) {\n throw new ValidationError(\n `providerAsSandboxClient(${environment.provider}): prompt ended without a terminal result/done/status event`,\n )\n }\n return promptResultCompat(\n {\n response: resultFromEvents(events, text).content,\n success: true,\n durationMs: 0,\n ...(usage ? { usage } : {}),\n },\n 'success',\n )\n },\n ...(environment.dispatch\n ? {\n async dispatchPrompt(message: string | InputPart[], promptOptions?: PromptOptions) {\n const session = await environment.dispatch?.(\n turnInputFromPrompt(message, promptOptions),\n )\n if (!session)\n throw new ValidationError('providerAsSandboxClient: dispatch returned no session')\n return sandboxDispatchResultFromSessionRef(session)\n },\n }\n : {}),\n ...(environment.session\n ? {\n session(id: string) {\n return sessionAsSandboxSession(environment.session?.(id))\n },\n }\n : {}),\n ...(environment.read ? { read: environment.read.bind(environment) } : {}),\n ...(environment.write ? { write: environment.write.bind(environment) } : {}),\n ...(environment.exec\n ? {\n exec: environment.exec.bind(environment),\n }\n : {}),\n ...(environment.checkpoint\n ? {\n async checkpoint(checkpointOptions?: CheckpointRequest) {\n const checkpoint = await environment.checkpoint?.(checkpointOptions)\n return { checkpointId: checkpoint?.id, id: checkpoint?.id }\n },\n }\n : {}),\n ...(environment.fork\n ? {\n async fork(checkpointId: string, forkOptions?: ForkRequest) {\n const forked = await environment.fork?.({ id: checkpointId }, forkOptions)\n if (!forked)\n throw new ValidationError('providerAsSandboxClient: fork returned no environment')\n return environmentAsSandboxInstance(forked, options)\n },\n }\n : {}),\n async delete(): Promise<void> {\n await environment.destroy?.()\n },\n }\n return box as unknown as SandboxInstance\n}\n\nfunction sandboxInstanceAsEnvironment(\n box: SandboxInstance,\n providerName: string,\n client: SandboxClient,\n): AgentEnvironment {\n const environment: AgentEnvironment = {\n id: String(box.id),\n provider: providerName,\n ...(typeof box.name === 'string' ? { name: box.name } : {}),\n async status(): Promise<AgentEnvironmentStatus> {\n await maybeRefresh(box)\n return statusFromUnknown(readBoxStatus(box))\n },\n async *stream(input: AgentTurnInput): AsyncIterable<AgentEnvironmentEvent> {\n for await (const event of box.streamPrompt(\n promptFromTurnInput(input),\n promptOptionsFromTurnInput(input),\n )) {\n yield environmentEventFromSandboxEvent(event)\n }\n },\n ...(hasDispatchPrompt(box)\n ? {\n async dispatch(input: AgentTurnInput): Promise<AgentSessionRef> {\n const dispatched = await box.dispatchPrompt(\n promptFromTurnInput(input),\n promptOptionsFromTurnInput(input),\n )\n return sessionRefFromSandboxDispatch(dispatched, providerName)\n },\n }\n : {}),\n ...(hasSession(box)\n ? {\n session(id: string): AgentSession {\n return sandboxSessionAsAgentSession(box.session(id))\n },\n }\n : {}),\n ...(hasRead(box) ? { read: box.read.bind(box) } : {}),\n ...(hasWrite(box) ? { write: box.write.bind(box) } : {}),\n ...(hasExec(box)\n ? {\n async exec(command: string, options?: ExecRequest): Promise<ExecResult> {\n return execResultFromSandboxExecResult(await box.exec(command, options as never))\n },\n }\n : {}),\n ...(hasCheckpoint(box)\n ? {\n async checkpoint(options?: CheckpointRequest): Promise<CheckpointRef> {\n const result = await box.checkpoint(options as never)\n return { id: checkpointIdFromResult(result), provider: providerName }\n },\n }\n : {}),\n ...(hasFork(box)\n ? {\n async fork(checkpoint: CheckpointRef, options?: ForkRequest): Promise<AgentEnvironment> {\n const forked = await box.fork(checkpoint.id, options as never)\n return sandboxInstanceAsEnvironment(forked, providerName, client)\n },\n }\n : {}),\n async placement(): Promise<PlacementInfo> {\n return placementInfoFromLoopPlacement(client.describePlacement?.(box), box)\n },\n async refresh(): Promise<void> {\n await maybeRefresh(box)\n },\n async destroy(): Promise<void> {\n await destroyBox(box)\n },\n }\n return environment\n}\n\nfunction sandboxSessionAsAgentSession(session: SandboxSessionLike): AgentSession {\n return {\n id: session.id,\n async status(): Promise<AgentSessionStatus | null> {\n const status = await session.status()\n if (!status) return null\n return sessionStatusFromUnknown((status as { status?: unknown }).status)\n },\n async *events(options?: {\n since?: string\n signal?: AbortSignal\n }): AsyncIterable<AgentEnvironmentEvent> {\n for await (const event of session.events(options))\n yield environmentEventFromSandboxEvent(event)\n },\n async result(): Promise<AgentTurnResult> {\n return agentTurnResultFromPromptResult(await session.result())\n },\n async prompt(input: AgentTurnInput): Promise<AgentTurnResult> {\n return agentTurnResultFromPromptResult(\n await session.prompt(promptFromTurnInput(input), promptOptionsFromTurnInput(input)),\n )\n },\n cancel(): Promise<void> {\n return session.cancel()\n },\n }\n}\n\nfunction sessionAsSandboxSession(session: AgentSession | undefined): unknown {\n if (!session) throw new ValidationError('providerAsSandboxClient: session(id) returned undefined')\n return {\n id: session.id,\n status: session.status.bind(session),\n async *events(options?: {\n since?: string\n signal?: AbortSignal\n }): AsyncGenerator<SandboxEvent> {\n for await (const event of session.events(options))\n yield sandboxEventFromEnvironmentEvent(event)\n },\n async result(): Promise<PromptResult> {\n return promptResultFromAgentTurnResult(await session.result())\n },\n async prompt(message: string | InputPart[], options?: PromptOptions): Promise<PromptResult> {\n return promptResultFromAgentTurnResult(\n await session.prompt(turnInputFromPrompt(message, options)),\n )\n },\n cancel: session.cancel.bind(session),\n }\n}\n\nfunction environmentEventFromSandboxEvent(event: SandboxEvent): AgentEnvironmentEvent {\n const data =\n event.data && typeof event.data === 'object'\n ? (event.data as Record<string, unknown>)\n : ({} as Record<string, unknown>)\n return {\n type: String(event.type),\n data,\n ...(event.id ? { id: event.id } : {}),\n usage: tokenUsageFromData(data),\n providerEvent: event,\n }\n}\n\nfunction sandboxEventFromEnvironmentEvent(event: AgentEnvironmentEvent): SandboxEvent {\n return {\n type: event.type,\n data: {\n ...event.data,\n ...(event.usage ? { usage: tokenUsageData(event.usage) } : {}),\n },\n ...(event.id ? { id: event.id } : {}),\n }\n}\n\nfunction usageSandboxEvent(event: AgentEnvironmentEvent): SandboxEvent | undefined {\n if (!event.usage || isUsageType(event.type)) return undefined\n const usage = tokenUsageData(event.usage)\n if (\n usage.inputTokens === undefined &&\n usage.outputTokens === undefined &&\n usage.totalCostUsd === undefined\n ) {\n return undefined\n }\n return { type: 'llm_call', data: usage }\n}\n\nfunction tokenUsageData(usage: TokenUsage): Record<string, number | undefined> {\n return {\n inputTokens: usage.inputTokens,\n outputTokens: usage.outputTokens,\n totalCostUsd: usage.cost,\n }\n}\n\nfunction turnInputFromPrompt(\n message: string | InputPart[],\n options?: PromptOptions,\n): AgentTurnInput {\n return {\n ...(typeof message === 'string' ? { prompt: message } : { parts: message }),\n ...(options?.sessionId ? { sessionId: options.sessionId } : {}),\n ...(options?.model ? { model: options.model } : {}),\n ...(options?.timeoutMs ? { timeoutMs: options.timeoutMs } : {}),\n ...(options?.executionId ? { executionId: options.executionId } : {}),\n ...(options?.lastEventId ? { lastEventId: options.lastEventId } : {}),\n ...(options?.turnId ? { turnId: options.turnId } : {}),\n ...(options?.detach !== undefined ? { detach: options.detach } : {}),\n ...(options?.context ? { context: options.context } : {}),\n ...(options?.signal ? { signal: options.signal } : {}),\n ...(options?.backend ? { providerOptions: { backend: options.backend } } : {}),\n }\n}\n\nfunction promptFromTurnInput(input: AgentTurnInput): string | InputPart[] {\n if (input.parts) return input.parts\n return input.prompt ?? ''\n}\n\nfunction promptOptionsFromTurnInput(input: AgentTurnInput): PromptOptions {\n return {\n ...(input.sessionId ? { sessionId: input.sessionId } : {}),\n ...(input.model ? { model: input.model } : {}),\n ...(input.timeoutMs ? { timeoutMs: input.timeoutMs } : {}),\n ...(input.context ? { context: input.context } : {}),\n ...(input.signal ? { signal: input.signal } : {}),\n ...(input.executionId ? { executionId: input.executionId } : {}),\n ...(input.lastEventId ? { lastEventId: input.lastEventId } : {}),\n ...(input.turnId ? { turnId: input.turnId } : {}),\n ...(input.detach !== undefined ? { detach: input.detach } : {}),\n }\n}\n\nfunction taskToTurnInput(task: unknown, signal: AbortSignal): AgentTurnInput {\n return { prompt: taskToPrompt(task), signal }\n}\n\nfunction taskToPrompt(task: unknown): string {\n if (typeof task === 'string') return task\n if (task && typeof task === 'object') {\n const record = task as Record<string, unknown>\n for (const key of ['prompt', 'content', 'task', 'message']) {\n if (typeof record[key] === 'string') return record[key]\n }\n }\n return JSON.stringify(task)\n}\n\nfunction resultFromEvents(\n events: AgentEnvironmentEvent[],\n fallbackText: string,\n): { content: string; events: AgentEnvironmentEvent[] } {\n for (let i = events.length - 1; i >= 0; i -= 1) {\n const event = events[i]\n const text = event ? resultTextFromData(event.data) : undefined\n if (text !== undefined) return { content: text, events }\n }\n return { content: fallbackText, events }\n}\n\nfunction textFromEnvironmentEvent(event: AgentEnvironmentEvent): string {\n if (\n typeof event.normalized === 'object' &&\n event.normalized &&\n event.normalized.type === 'message.part.updated'\n ) {\n return typeof event.normalized.delta === 'string' ? event.normalized.delta : ''\n }\n const data = event.data\n for (const key of ['delta', 'chunk', 'content', 'text']) {\n if (typeof data[key] === 'string' && !isTerminalEnvironmentEvent(event)) return data[key]\n }\n return ''\n}\n\nfunction resultTextFromData(data: Record<string, unknown>): string | undefined {\n for (const key of ['finalText', 'text', 'response', 'resultSummary', 'content']) {\n if (typeof data[key] === 'string') return data[key]\n }\n return undefined\n}\n\nfunction isTerminalEnvironmentEvent(event: AgentEnvironmentEvent): boolean {\n if (event.type === 'result' || event.type === 'done' || event.type === 'final') return true\n if (event.type.endsWith('.completed') || event.type.endsWith('.failed')) return true\n if (event.type === 'status') {\n const status = event.data.status\n return status === 'completed' || status === 'failed' || status === 'cancelled'\n }\n return false\n}\n\nfunction isUsageType(type: string): boolean {\n return type === 'llm_call' || type === 'usage' || type === 'cost.usage'\n}\n\nfunction usageFromEnvironmentEvent(event: AgentEnvironmentEvent): {\n input: number\n output: number\n usd: number\n} {\n const usage = event.usage ?? tokenUsageFromData(event.data)\n return {\n input: finiteNumber(usage?.inputTokens) ?? 0,\n output: finiteNumber(usage?.outputTokens) ?? 0,\n usd:\n finiteNumber(usage?.cost) ??\n finiteNumber(event.data.costUsd) ??\n finiteNumber(event.data.totalCostUsd) ??\n 0,\n }\n}\n\nfunction tokenUsageFromData(data: Record<string, unknown>): TokenUsage | undefined {\n const usageRecord =\n data.usage && typeof data.usage === 'object'\n ? (data.usage as Record<string, unknown>)\n : data.tokenUsage && typeof data.tokenUsage === 'object'\n ? (data.tokenUsage as Record<string, unknown>)\n : data\n const inputTokens =\n finiteNumber(usageRecord.inputTokens) ??\n finiteNumber(usageRecord.tokensIn) ??\n finiteNumber(usageRecord.prompt_tokens)\n const outputTokens =\n finiteNumber(usageRecord.outputTokens) ??\n finiteNumber(usageRecord.tokensOut) ??\n finiteNumber(usageRecord.completion_tokens)\n const cost =\n finiteNumber(usageRecord.cost) ??\n finiteNumber(usageRecord.costUsd) ??\n finiteNumber(usageRecord.totalCostUsd) ??\n finiteNumber(data.costUsd) ??\n finiteNumber(data.totalCostUsd)\n if (inputTokens === undefined && outputTokens === undefined && cost === undefined)\n return undefined\n return {\n inputTokens: inputTokens ?? 0,\n outputTokens: outputTokens ?? 0,\n ...(cost !== undefined ? { cost } : {}),\n }\n}\n\nfunction mergeTokenUsage(\n left: TokenUsage | undefined,\n right: TokenUsage | undefined,\n): TokenUsage | undefined {\n if (!left) return right\n if (!right) return left\n return {\n inputTokens: left.inputTokens + right.inputTokens,\n outputTokens: left.outputTokens + right.outputTokens,\n ...(left.cost !== undefined || right.cost !== undefined\n ? { cost: (left.cost ?? 0) + (right.cost ?? 0) }\n : {}),\n }\n}\n\nfunction finiteNumber(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined\n}\n\ntype PromptResultCompatInput = {\n response?: string\n success: boolean\n error?: string\n traceId?: string\n durationMs: number\n usage?: PromptResult['usage']\n}\n\nfunction promptResultCompat(\n input: PromptResultCompatInput,\n status: 'success' | 'failed',\n): PromptResult {\n // sandbox 0.8 omitted `status`; sandbox 0.9 requires it. Emit it at runtime\n // while keeping this adapter type-checkable across the supported peer range.\n return { ...input, status } as unknown as PromptResult\n}\n\nfunction promptResultFromAgentTurnResult(result: AgentTurnResult): PromptResult {\n return promptResultCompat(\n {\n response: result.text,\n success: result.success,\n durationMs: 0,\n ...(result.error ? { error: result.error } : {}),\n ...(result.usage ? { usage: result.usage } : {}),\n },\n result.success ? 'success' : 'failed',\n )\n}\n\nfunction agentTurnResultFromPromptResult(result: PromptResult): AgentTurnResult {\n const record = result as unknown as Record<string, unknown>\n const text =\n typeof record.response === 'string'\n ? record.response\n : typeof record.text === 'string'\n ? record.text\n : typeof record.finalText === 'string'\n ? record.finalText\n : ''\n const success = typeof record.success === 'boolean' ? record.success : true\n return {\n text,\n success,\n ...(typeof record.error === 'string' ? { error: record.error } : {}),\n usage: tokenUsageFromData(record),\n }\n}\n\nfunction sandboxDispatchResultFromSessionRef(session: AgentSessionRef): Record<string, unknown> {\n const hasStatus = session.metadata && Object.hasOwn(session.metadata, 'status')\n const status = hasStatus ? sessionStatusFromUnknown(session.metadata?.status) : 'running'\n return {\n sessionId: session.id,\n status,\n alreadyExisted: session.metadata?.alreadyExisted === true,\n }\n}\n\nfunction sessionRefFromSandboxDispatch(dispatched: unknown, providerName: string): AgentSessionRef {\n const record =\n dispatched && typeof dispatched === 'object'\n ? (dispatched as Record<string, unknown>)\n : undefined\n const id = record?.sessionId ?? record?.id\n if (typeof id !== 'string' || id.length === 0) {\n throw new ValidationError('sandboxClientAsProvider: dispatch returned no session id')\n }\n if (!record) {\n throw new ValidationError('sandboxClientAsProvider: dispatch returned no session record')\n }\n return {\n id,\n provider: providerName,\n metadata: {\n ...(record.status ? { status: record.status } : {}),\n ...(record.alreadyExisted !== undefined ? { alreadyExisted: record.alreadyExisted } : {}),\n },\n }\n}\n\nfunction execResultFromSandboxExecResult(result: SandboxExecResult): ExecResult {\n const record = result as unknown as Record<string, unknown>\n const exitCode = finiteNumber(record.exitCode) ?? finiteNumber(record.code)\n if (exitCode === undefined) {\n throw new ValidationError('sandboxClientAsProvider: exec returned no exit code')\n }\n return {\n exitCode,\n stdout: typeof record.stdout === 'string' ? record.stdout : '',\n stderr: typeof record.stderr === 'string' ? record.stderr : '',\n }\n}\n\nfunction statusFromUnknown(status: unknown): AgentEnvironmentStatus {\n if (status === 'pending' || status === 'provisioning' || status === 'running') return status\n if (status === 'stopped' || status === 'failed' || status === 'expired') return status\n if (status === 'completed') return 'stopped'\n if (status === 'cancelled') return 'stopped'\n return 'unknown'\n}\n\nfunction sessionStatusFromUnknown(status: unknown): AgentSessionStatus | null {\n if (status === 'completed' || status === 'cancelled') return status\n return statusFromUnknown(status)\n}\n\nfunction readBoxStatus(box: SandboxInstance): unknown {\n return (box as unknown as { status?: unknown }).status\n}\n\nfunction readBoxMetadata(box: SandboxInstance): Record<string, unknown> | undefined {\n const metadata = (box as unknown as { metadata?: unknown }).metadata\n return metadata && typeof metadata === 'object'\n ? (metadata as Record<string, unknown>)\n : undefined\n}\n\nasync function maybeRefresh(box: SandboxInstance): Promise<void> {\n const refresh = (box as unknown as { refresh?: () => Promise<void> }).refresh\n if (typeof refresh === 'function') await refresh.call(box)\n}\n\nasync function destroyBox(box: SandboxInstance): Promise<void> {\n const deleteBox = (box as unknown as { delete?: () => Promise<void> }).delete\n if (typeof deleteBox === 'function') await deleteBox.call(box)\n}\n\nfunction placementInfoFromLoopPlacement(\n placement: LoopSandboxPlacement | undefined,\n box: SandboxInstance,\n): PlacementInfo {\n if (!placement) return { kind: 'sandbox', sandboxId: String(box.id) }\n return {\n kind: placement.kind === 'fleet' ? 'fleet' : 'sandbox',\n ...(placement.sandboxId ? { sandboxId: placement.sandboxId } : { sandboxId: String(box.id) }),\n ...(placement.fleetId ? { fleetId: placement.fleetId } : {}),\n ...(placement.machineId ? { machineId: placement.machineId } : {}),\n }\n}\n\nfunction checkpointIdFromResult(result: unknown): string {\n const record = result && typeof result === 'object' ? (result as Record<string, unknown>) : {}\n const id = record.checkpointId ?? record.id\n if (typeof id !== 'string' || id.length === 0) {\n throw new ValidationError('sandboxClientAsProvider: checkpoint returned no checkpoint id')\n }\n return id\n}\n\nfunction defaultTangleSandboxCapabilities(): AgentEnvironmentCapabilities {\n return {\n profile: {\n namedProfiles: true,\n systemPrompt: true,\n instructions: true,\n tools: true,\n permissions: true,\n mcp: true,\n subagents: true,\n resources: {\n files: true,\n instructions: true,\n tools: true,\n skills: true,\n agents: true,\n commands: true,\n },\n hooks: true,\n modes: true,\n runtimeUpdate: true,\n validation: true,\n },\n streaming: { live: true, replay: true, detach: true, turnIdempotency: true },\n sessions: { continue: true, list: true, messages: true },\n workspace: { read: true, write: true, exec: true, git: true, upload: true, download: true },\n branching: { checkpoint: true, fork: true },\n placement: true,\n usage: true,\n confidential: true,\n }\n}\n\nfunction mergeAbortSignals(a: AbortSignal, b: AbortSignal): AbortSignal {\n const controller = new AbortController()\n const abort = () => controller.abort()\n if (a.aborted || b.aborted) controller.abort()\n else {\n a.addEventListener('abort', abort, { once: true })\n b.addEventListener('abort', abort, { once: true })\n }\n return controller.signal\n}\n\nfunction contentRef(prefix: string, value: unknown): string {\n let str: string\n try {\n str = JSON.stringify(value) ?? String(value)\n } catch {\n str = String(value)\n }\n let hash = 0x811c9dc5\n for (let i = 0; i < str.length; i += 1) {\n hash ^= str.charCodeAt(i)\n hash = Math.imul(hash, 0x01000193)\n }\n return `${prefix}:${(hash >>> 0).toString(16).padStart(8, '0')}`\n}\n\nfunction hasGet(\n client: SandboxClient,\n): client is SandboxClient & { get(id: string): Promise<SandboxInstance | null> } {\n return typeof (client as { get?: unknown }).get === 'function'\n}\n\nfunction hasList(\n client: SandboxClient,\n): client is SandboxClient & { list(options?: unknown): Promise<SandboxInstance[]> } {\n return typeof (client as { list?: unknown }).list === 'function'\n}\n\nfunction hasDispatchPrompt(box: SandboxInstance): box is SandboxInstance & {\n dispatchPrompt(message: string | InputPart[], options?: PromptOptions): Promise<unknown>\n} {\n return typeof (box as { dispatchPrompt?: unknown }).dispatchPrompt === 'function'\n}\n\nfunction hasSession(\n box: SandboxInstance,\n): box is SandboxInstance & { session(id: string): SandboxSessionLike } {\n return typeof (box as { session?: unknown }).session === 'function'\n}\n\nfunction hasRead(box: SandboxInstance): box is SandboxInstance & {\n read(path: string, options?: { sessionId?: string }): Promise<string>\n} {\n return typeof (box as { read?: unknown }).read === 'function'\n}\n\nfunction hasWrite(\n box: SandboxInstance,\n): box is SandboxInstance & { write(path: string, content: string): Promise<void> } {\n return typeof (box as { write?: unknown }).write === 'function'\n}\n\nfunction hasExec(box: SandboxInstance): box is SandboxInstance & {\n exec(command: string, options?: unknown): Promise<SandboxExecResult>\n} {\n return typeof (box as { exec?: unknown }).exec === 'function'\n}\n\nfunction hasCheckpoint(\n box: SandboxInstance,\n): box is SandboxInstance & { checkpoint(options?: unknown): Promise<unknown> } {\n return typeof (box as { checkpoint?: unknown }).checkpoint === 'function'\n}\n\nfunction hasFork(box: SandboxInstance): box is SandboxInstance & {\n fork(checkpointId: string, options?: unknown): Promise<SandboxInstance>\n} {\n return typeof (box as { fork?: unknown }).fork === 'function'\n}\n\ninterface SandboxSessionLike {\n readonly id: string\n status(): Promise<unknown | null>\n events(options?: { since?: string; signal?: AbortSignal }): AsyncIterable<SandboxEvent>\n result(): Promise<PromptResult>\n prompt(message: string | InputPart[], options?: PromptOptions): Promise<PromptResult>\n cancel(): Promise<void>\n}\n"],"mappings":"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","names":[]}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/conversation/call-policy.ts","../src/conversation/headers.ts","../src/conversation/turn-id.ts","../src/conversation/run-conversation.ts","../src/conversation/conversation-backend.ts","../src/conversation/define-conversation.ts","../src/conversation/journal.ts","../src/conversation/journal-sql.ts","../src/conversation/run-persona.ts"],"sourcesContent":["/**\n *\n * Per-call resilience policy for participant backends: deadline, retry with\n * backoff, and a circuit breaker. Each policy is applied *around* a single\n * turn's backend invocation, not across the whole conversation — the\n * conversation-level credit cap and `maxTurns` bound the broader run.\n *\n * Deadlines abort the underlying backend stream via `AbortSignal` linkage so\n * the OpenAI/SDK clients tear down their HTTP request cleanly instead of\n * leaking sockets. Retries replay the same logical turn (same `turnId`) so\n * any caching gateway can dedupe. Circuit breakers are *per participant*: A's\n * failures don't open B's breaker.\n *\n * @stable\n */\n\n/** Pure judgment of whether an error is worth retrying. Defaults: TimeoutError, AbortError, fetch-level network errors. */\nexport type RetryableErrorPredicate = (err: unknown) => boolean\n\n/** Backoff between attempts. Constant ms, or `(attempt: 1-indexed) => ms`. */\nexport type RetryBackoff = number | ((attempt: number) => number)\n\n/** Circuit-breaker tuning. `failuresToOpen` consecutive failures opens it; closed only after `cooldownMs`. */\nexport interface CircuitBreakerConfig {\n failuresToOpen: number\n cooldownMs: number\n}\n\nexport interface BackendCallPolicy {\n /** Per-attempt wall clock limit. Exceeding fires an AbortSignal and is treated as a retryable failure. */\n perAttemptDeadlineMs?: number\n /** Number of retries after the first attempt; total attempts = 1 + maxRetries. Default 0. */\n maxRetries?: number\n /** Backoff between attempts. Default 250ms with jitter. */\n retryBackoffMs?: RetryBackoff\n /** Custom retry classifier. Defaults to {@link defaultIsRetryable}. */\n isRetryable?: RetryableErrorPredicate\n /** Circuit breaker that opens after N consecutive failures per participant. */\n circuitBreaker?: CircuitBreakerConfig\n}\n\n/** Thrown when the circuit breaker is open for a participant and no retry is allowed yet. */\nexport class CircuitOpenError extends Error {\n constructor(participant: string, retryAfterMs: number) {\n super(\n `circuit open for participant '${participant}'; ${retryAfterMs}ms remaining before retry allowed`,\n )\n this.name = 'CircuitOpenError'\n }\n}\n\n/** Thrown when a backend call exceeds its per-attempt deadline. */\nexport class DeadlineExceededError extends Error {\n constructor(deadlineMs: number) {\n super(`backend call exceeded per-attempt deadline of ${deadlineMs}ms`)\n this.name = 'DeadlineExceededError'\n }\n}\n\n/**\n * Default retryable classification — network/timeout class errors. Errors\n * a model deliberately throws (validation, refusal, 4xx) are not retried;\n * those represent real outcomes, not transient infrastructure faults.\n */\nexport const defaultIsRetryable: RetryableErrorPredicate = (err) => {\n if (err instanceof DeadlineExceededError) return true\n if (err instanceof Error) {\n const name = err.name\n const message = err.message.toLowerCase()\n if (name === 'AbortError' || name === 'TimeoutError') return true\n if (\n message.includes('econnreset') ||\n message.includes('etimedout') ||\n message.includes('econnrefused') ||\n message.includes('socket hang up') ||\n message.includes('network') ||\n message.includes('fetch failed')\n ) {\n return true\n }\n }\n return false\n}\n\n/** Live circuit-breaker state — one instance per (participant, conversation run). */\nexport class CircuitBreakerState {\n private consecutiveFailures = 0\n private openedAt: number | undefined\n\n constructor(private readonly config: CircuitBreakerConfig | undefined) {}\n\n /**\n * Check whether the next call is allowed. Throws `CircuitOpenError` when\n * the breaker is open and the cooldown hasn't elapsed.\n */\n preflight(participant: string, now: number = Date.now()): void {\n if (!this.config || this.openedAt === undefined) return\n const remaining = this.config.cooldownMs - (now - this.openedAt)\n if (remaining > 0) {\n throw new CircuitOpenError(participant, remaining)\n }\n this.openedAt = undefined\n this.consecutiveFailures = 0\n }\n\n recordSuccess(): void {\n this.consecutiveFailures = 0\n this.openedAt = undefined\n }\n\n recordFailure(now: number = Date.now()): void {\n if (!this.config) return\n this.consecutiveFailures += 1\n if (this.consecutiveFailures >= this.config.failuresToOpen) {\n this.openedAt = now\n }\n }\n}\n\n/**\n * Build a per-attempt AbortSignal linked to the parent signal AND fired when\n * the deadline elapses. The returned `dispose()` MUST be called in a\n * `finally` (clears the timer, detaches the listener) so we don't leak.\n *\n * When the deadline fires, the signal's `reason` is a `DeadlineExceededError`\n * — callers can detect timeout-vs-cancel by reading `signal.reason` after\n * the underlying operation throws.\n */\nexport function makePerAttemptSignal(\n parentSignal: AbortSignal | undefined,\n deadlineMs: number | undefined,\n): {\n signal: AbortSignal\n dispose: () => void\n getDeadlineError(): DeadlineExceededError | undefined\n} {\n const controller = new AbortController()\n let deadlineError: DeadlineExceededError | undefined\n const cleanups: Array<() => void> = []\n\n if (parentSignal) {\n if (parentSignal.aborted) controller.abort(parentSignal.reason)\n else {\n const onAbort = () => controller.abort(parentSignal.reason)\n parentSignal.addEventListener('abort', onAbort, { once: true })\n cleanups.push(() => parentSignal.removeEventListener('abort', onAbort))\n }\n }\n if (deadlineMs !== undefined) {\n const ms = deadlineMs\n const timer = setTimeout(() => {\n deadlineError = new DeadlineExceededError(ms)\n controller.abort(deadlineError)\n }, ms)\n cleanups.push(() => clearTimeout(timer))\n }\n return {\n signal: controller.signal,\n dispose() {\n for (const c of cleanups) c()\n },\n getDeadlineError() {\n return deadlineError\n },\n }\n}\n\n/** Compute the delay before the next attempt. Default: 250ms exponential with jitter. */\nexport function computeBackoff(spec: RetryBackoff | undefined, attempt: number): number {\n if (spec === undefined) {\n const base = 250\n const jitter = Math.floor(Math.random() * base)\n return base * 2 ** (attempt - 1) + jitter\n }\n if (typeof spec === 'function') return Math.max(0, spec(attempt))\n return Math.max(0, spec)\n}\n\n/** Resolve after `ms` milliseconds — used for retry backoff in conversation call policy. */\nexport function sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms))\n}\n","/**\n *\n * Cross-gateway forwarding headers — the wire-level contract that makes\n * agent-to-agent communication composable across organizational boundaries.\n * Every header here is read on inbound and re-emitted on outbound, so a chain\n * `caller → A's gateway → A's runtime → B's gateway → B's runtime` ends with\n * B billing the original user, the depth counter monotonically incremented,\n * and the run/turn correlation IDs preserved end-to-end.\n *\n * The actual depth refusal (HTTP 413 at MAX_DEPTH) is enforced by\n * `agent-gateway`'s middleware; this module owns the names + the propagation\n * rules so both sides agree.\n *\n * Full protocol: `docs/agent-bus-protocol.md`.\n *\n * @stable\n */\n\n/** Standard names — lowercased so Headers maps interop on every runtime. */\nexport const FORWARD_HEADERS = {\n /** Forwarded original-user identity (`Bearer sk-tan-<user>`); downstream gateways bill against this. */\n authorization: 'x-tangle-forwarded-authorization',\n /** Monotonically incremented on every gateway hop. Refused at MAX_DEPTH. */\n depth: 'x-tangle-forwarded-depth',\n /** Top-level conversation run identifier, propagated through every nested call. */\n runId: 'x-tangle-runid',\n /** This call's turn within the run; deterministic + stable across retries. */\n turnId: 'x-tangle-turnid',\n /** When the call is *inside* another turn (recursion), the parent turn's id. */\n parentTurnId: 'x-tangle-parent-turnid',\n /** Logical conversation peer label at the sending side, for trace stitching. */\n speaker: 'x-tangle-speaker',\n} as const\n\nexport type ForwardHeaderName = (typeof FORWARD_HEADERS)[keyof typeof FORWARD_HEADERS]\n\n/** Hard cap on chained gateway hops; refused beyond this. Default keeps recursion bounded. */\nexport const DEFAULT_MAX_DEPTH = 4\n\n/**\n * Lowercase a header lookup so we read the same key regardless of source\n * casing (Hono, fetch's `Headers`, raw Node IncomingMessage, …).\n */\nfunction lc(name: string): string {\n return name.toLowerCase()\n}\n\n/**\n * Read the depth counter off an inbound request. Missing → 0 (caller is the\n * origin). Non-integer → throws — silent coercion would let a bad caller\n * reset depth and bypass the limit.\n */\nexport function readDepth(\n headers: Readonly<Record<string, string | string[] | undefined>>,\n): number {\n const raw = pickHeader(headers, FORWARD_HEADERS.depth)\n if (raw === undefined || raw === '') return 0\n const n = Number(raw)\n if (!Number.isInteger(n) || n < 0) {\n throw new Error(\n `invalid ${FORWARD_HEADERS.depth} header value '${raw}' — must be a non-negative integer`,\n )\n }\n return n\n}\n\n/**\n * Refuse further forwarding when the inbound depth has reached the limit.\n * Callers (the gateway middleware) translate the boolean to an HTTP 413.\n */\nexport function isDepthExceeded(inboundDepth: number, max: number = DEFAULT_MAX_DEPTH): boolean {\n return inboundDepth >= max\n}\n\n/**\n * Build the headers to emit on an outbound participant call, given the\n * conversation's propagation context. Depth is incremented from the inbound\n * value; runId / turnId / speaker stamp the current hop; the user's\n * `Authorization` is preserved verbatim so the downstream gateway bills the\n * right wallet.\n */\nexport function buildForwardHeaders(input: {\n inboundDepth: number\n forwardedAuthorization?: string\n runId: string\n turnId: string\n parentTurnId?: string\n speaker: string\n}): Record<string, string> {\n const out: Record<string, string> = {\n [FORWARD_HEADERS.depth]: String(input.inboundDepth + 1),\n [FORWARD_HEADERS.runId]: input.runId,\n [FORWARD_HEADERS.turnId]: input.turnId,\n [FORWARD_HEADERS.speaker]: input.speaker,\n }\n if (input.forwardedAuthorization !== undefined) {\n out[FORWARD_HEADERS.authorization] = input.forwardedAuthorization\n }\n if (input.parentTurnId !== undefined) {\n out[FORWARD_HEADERS.parentTurnId] = input.parentTurnId\n }\n return out\n}\n\n/**\n * Header bag carried through `AgentBackendContext.propagatedHeaders` so\n * backends that opt in can merge them into their outbound HTTP requests.\n * Distinct from `buildForwardHeaders` so callers can attach extra\n * non-protocol headers (e.g. tracing) without colliding.\n */\nexport type PropagatedHeaders = Readonly<Record<string, string>>\n\nfunction pickHeader(\n headers: Readonly<Record<string, string | string[] | undefined>>,\n name: string,\n): string | undefined {\n const target = lc(name)\n for (const key of Object.keys(headers)) {\n if (lc(key) === target) {\n const value = headers[key]\n if (Array.isArray(value)) return value[0]\n return value\n }\n }\n return undefined\n}\n","/**\n *\n * Deterministic turn identifier. Stable across retries of the same logical\n * turn so backends (and any caching gateway in between) can dedupe on it.\n * A retry triggered by a network blip or deadline timeout MUST produce the\n * same `turn_id`; only the underlying attempt count differs.\n *\n * Shape: `${runId}.t${index}.${speakerSlug}` — readable in logs, sortable by\n * turn index, attributable to a speaker. Slugify keeps the speaker portion\n * URL-safe so it can ride in HTTP headers without escaping.\n *\n * @stable\n */\n\nexport function turnId(runId: string, index: number, speaker: string): string {\n return `${runId}.t${index}.${slugifySpeaker(speaker)}`\n}\n\n/**\n * Reduce a speaker name to ASCII alphanumerics + dashes. Preserves enough\n * substance to read in a log line; collisions between speakers within a\n * single Conversation are prevented by `defineConversation`'s\n * unique-name check, so the slug only needs to be deterministic, not unique.\n */\nexport function slugifySpeaker(speaker: string): string {\n const cleaned = speaker\n .normalize('NFKD')\n .replace(/[^\\w-]+/g, '-')\n .replace(/-+/g, '-')\n .replace(/^-|-$/g, '')\n .toLowerCase()\n return cleaned || 'anon'\n}\n","/**\n *\n * Conversation orchestrator. Drives N participants in turn through their own\n * `AgentExecutionBackend`s, aggregating per-turn text + usage, enforcing\n * `maxTurns` / `maxCreditsCents` / `haltOn`, and emitting per-event stream\n * markers so callers can plumb the run through SSE without buffering.\n *\n * `runConversation` returns the full result; `runConversationStream` returns\n * an `AsyncIterable<ConversationStreamEvent>` for callers that want to\n * forward events as they arrive. Both share one driving loop.\n *\n * Distributed-systems primitives layered on top of the loop:\n * - **Idempotent turn ids** — `turnId(runId, index, speaker)` stays stable\n * across retries so caching gateways can dedupe.\n * - **Durable journal** — optional `ConversationJournal` persists every\n * committed turn; reusing a runId against the same journal resumes\n * transparently from the last committed turn.\n * - **Per-turn call policy** — deadline, retry-with-backoff, and a\n * per-participant circuit breaker. Retries replay the same logical turn\n * (same `turnId`); the retry loop lives inside the outer generator so\n * deltas yield naturally without cross-coroutine buffering.\n * - **Header propagation** — run/turn/depth headers (+ forwarded user\n * authorization) stamped onto every outbound backend call so downstream\n * gateways can bill the right user and enforce `X-Tangle-Forwarded-Depth`.\n *\n * Credit cap is enforced *between turns*, not mid-stream: a turn that\n * overshoots the cap completes, the cap then halts the conversation before\n * the next turn.\n *\n * @stable\n */\n\nimport type { KnowledgeReadinessReport } from '@tangle-network/agent-eval'\n\nimport { BackendTransportError } from '../errors'\nimport { newRuntimeSession, nowIso, touchSession } from '../sessions'\nimport type {\n AgentBackendContext,\n AgentBackendInput,\n AgentTaskSpec,\n RuntimeSession,\n} from '../types'\nimport {\n type BackendCallPolicy,\n CircuitBreakerState,\n computeBackoff,\n defaultIsRetryable,\n makePerAttemptSignal,\n sleep,\n} from './call-policy'\nimport { buildForwardHeaders, FORWARD_HEADERS } from './headers'\nimport { turnId as deriveTurnId } from './turn-id'\nimport type {\n Conversation,\n ConversationParticipant,\n ConversationResult,\n ConversationStreamEvent,\n ConversationTurn,\n HaltContext,\n HaltReason,\n RunConversationOptions,\n TurnOrder,\n} from './types'\n\nexport async function runConversation(\n conversation: Conversation,\n options: RunConversationOptions,\n): Promise<ConversationResult> {\n let result: ConversationResult | undefined\n for await (const event of runConversationStream(conversation, options)) {\n if (options.onEvent) await options.onEvent(event)\n if (event.type === 'conversation_end') result = event.result\n }\n if (!result) {\n throw new BackendTransportError(\n 'conversation',\n 'conversation stream ended without a conversation_end event',\n )\n }\n return result\n}\n\n/** Streaming conversation orchestrator: drives N participants in turn through their own backends, enforcing `maxTurns` / `maxCreditsCents` / `haltOn`, yielding per-event stream markers. */\nexport async function* runConversationStream(\n conversation: Conversation,\n options: RunConversationOptions,\n): AsyncIterable<ConversationStreamEvent> {\n const runId = options.runId ?? `conv_${crypto.randomUUID()}`\n const inboundDepth = options.inboundDepth ?? 0\n const callerHeaders = options.propagatedHeaders ?? {}\n const forwardedAuthorization = callerHeaders[FORWARD_HEADERS.authorization]\n\n const breakers = new Map<string, CircuitBreakerState>()\n for (const participant of conversation.participants) {\n const cfg =\n participant.callPolicy?.circuitBreaker ??\n conversation.policy.defaultCallPolicy?.circuitBreaker\n breakers.set(participant.name, new CircuitBreakerState(cfg))\n }\n\n let transcript: ConversationTurn[] = []\n let spentCreditsCents = 0\n let startedAt = nowIso()\n let resumed = false\n\n if (options.journal) {\n const prior = await options.journal.loadRun(runId)\n if (prior) {\n if (prior.halted) {\n // Run already terminated — surface its final state without re-running.\n const replayResult: ConversationResult = {\n runId,\n transcript: prior.turns,\n turns: prior.turns.length,\n spentCreditsCents: prior.turns.reduce(\n (sum, t) => sum + centsFromUsd(t.usage?.costUsd ?? 0),\n 0,\n ),\n halted: prior.halted,\n durationMs: 0,\n startedAt: prior.startedAt,\n endedAt: prior.endedAt ?? prior.startedAt,\n }\n yield {\n type: 'conversation_resumed',\n runId,\n participants: conversation.participants.map((p) => p.name),\n transcript: prior.turns,\n timestamp: nowIso(),\n }\n yield { type: 'conversation_end', runId, result: replayResult, timestamp: nowIso() }\n return\n }\n transcript = [...prior.turns]\n spentCreditsCents = transcript.reduce(\n (sum, t) => sum + centsFromUsd(t.usage?.costUsd ?? 0),\n 0,\n )\n startedAt = prior.startedAt\n resumed = true\n } else {\n await options.journal.beginRun(runId, startedAt)\n }\n }\n const startedAtMs = Date.now()\n\n if (resumed) {\n yield {\n type: 'conversation_resumed',\n runId,\n participants: conversation.participants.map((p) => p.name),\n // Snapshot the resumed transcript — the live `transcript` array gets\n // pushed to as the run continues, so handing the bare reference to a\n // subscriber would leak future writes into a past event.\n transcript: [...transcript],\n timestamp: nowIso(),\n }\n } else {\n yield {\n type: 'conversation_start',\n runId,\n participants: conversation.participants.map((p) => p.name),\n seed: options.seed,\n timestamp: startedAt,\n }\n }\n\n // When resumed, the next user input is the last persisted turn's text;\n // for a fresh run, it's the caller's seed.\n let currentInput =\n transcript.length === 0\n ? options.seed\n : (transcript[transcript.length - 1]?.text ?? options.seed)\n let halt: HaltReason | undefined\n\n const initialOffset = transcript.length\n for (let turnIndex = initialOffset; turnIndex < conversation.policy.maxTurns; turnIndex++) {\n if (options.signal?.aborted) {\n halt = { kind: 'abort' }\n break\n }\n if (\n conversation.policy.maxCreditsCents !== undefined &&\n spentCreditsCents >= conversation.policy.maxCreditsCents\n ) {\n halt = {\n kind: 'max_credits',\n spentCents: spentCreditsCents,\n capCents: conversation.policy.maxCreditsCents,\n }\n break\n }\n\n const speakerIdx = selectSpeaker(\n conversation.policy.turnOrder,\n conversation.participants.length,\n { transcript, turnIndex, spentCreditsCents },\n )\n const speaker = conversation.participants[speakerIdx]\n if (!speaker) {\n throw new BackendTransportError(\n 'conversation',\n `turnOrder selector returned out-of-range index ${speakerIdx} for ${conversation.participants.length} participants`,\n )\n }\n\n const tid = deriveTurnId(runId, turnIndex, speaker.name)\n const callPolicy: BackendCallPolicy | undefined =\n speaker.callPolicy ?? conversation.policy.defaultCallPolicy\n const breaker = breakers.get(speaker.name)\n if (!breaker) {\n throw new BackendTransportError(\n 'conversation',\n `internal: no circuit-breaker state registered for participant '${speaker.name}'`,\n )\n }\n const isRetryable = callPolicy?.isRetryable ?? defaultIsRetryable\n const totalAttempts = 1 + (callPolicy?.maxRetries ?? 0)\n\n yield {\n type: 'turn_start',\n runId,\n index: turnIndex,\n speaker: speaker.name,\n turnId: tid,\n attempt: 1,\n timestamp: nowIso(),\n }\n\n let aggregator: TurnAggregator | undefined\n let attemptCount = 0\n let lastError: unknown\n let breakerOpenFailure: unknown\n\n for (let attempt = 1; attempt <= totalAttempts; attempt++) {\n attemptCount = attempt\n try {\n breaker.preflight(speaker.name)\n } catch (err) {\n // Breaker open — no point retrying; halt the conversation with this\n // participant's error rather than busy-looping until exhaustion.\n breakerOpenFailure = err\n break\n }\n\n if (attempt > 1) {\n yield {\n type: 'turn_retry',\n runId,\n index: turnIndex,\n speaker: speaker.name,\n turnId: tid,\n attempt,\n reason: lastError instanceof Error ? lastError.message : String(lastError),\n timestamp: nowIso(),\n }\n }\n\n const perAttempt = makePerAttemptSignal(options.signal, callPolicy?.perAttemptDeadlineMs)\n const localAgg = new TurnAggregator({\n index: turnIndex,\n speaker: speaker.name,\n startedAt: nowIso(),\n })\n\n try {\n for await (const delta of driveSingleAttempt({\n speaker,\n participants: conversation.participants,\n input: currentInput,\n turnIndex,\n runId,\n turnId: tid,\n transcript,\n signal: perAttempt.signal,\n aggregator: localAgg,\n propagatedHeaders: buildForwardHeaders({\n inboundDepth,\n // When the participant elects to pay for its own outbound calls,\n // drop the forwarded user identity so the downstream gateway\n // bills the participant's own credentials instead. The backend\n // brings its own `Authorization` header at construction time\n // (e.g. `createOpenAICompatibleBackend({ apiKey: sk-tan-AGENT })`);\n // omitting the forwarded header is what flips the billing target.\n forwardedAuthorization: resolveAuthForwarding(speaker, {\n transcript,\n turnIndex,\n spentCreditsCents,\n })\n ? forwardedAuthorization\n : undefined,\n runId,\n turnId: tid,\n parentTurnId: options.parentTurnId,\n speaker: speaker.name,\n }),\n })) {\n yield {\n type: 'turn_text_delta',\n runId,\n index: turnIndex,\n speaker: speaker.name,\n turnId: tid,\n text: delta.text,\n timestamp: delta.timestamp,\n }\n }\n perAttempt.dispose()\n breaker.recordSuccess()\n aggregator = localAgg\n break\n } catch (err) {\n perAttempt.dispose()\n breaker.recordFailure()\n // Surface the deadline error explicitly when timeout was the cause —\n // otherwise the upstream may throw a generic AbortError that loses\n // diagnostic info.\n lastError = perAttempt.getDeadlineError() ?? err\n if (attempt >= totalAttempts || !isRetryable(lastError)) {\n break\n }\n await sleep(computeBackoff(callPolicy?.retryBackoffMs, attempt))\n }\n }\n\n if (!aggregator) {\n const failure = breakerOpenFailure ?? lastError\n const message = failure instanceof Error ? failure.message : String(failure)\n halt = { kind: 'participant_error', participant: speaker.name, message }\n break\n }\n\n const turn = aggregator.toTurn({ turnId: tid, attempts: attemptCount })\n transcript.push(turn)\n spentCreditsCents += centsFromUsd(turn.usage?.costUsd ?? 0)\n if (options.journal) {\n await options.journal.appendTurn(runId, turn)\n }\n\n yield { type: 'turn_end', runId, turn, timestamp: nowIso() }\n\n if (conversation.policy.haltOn) {\n const haltCtx: HaltContext = {\n transcript,\n lastTurn: turn,\n turnIndex,\n spentCreditsCents,\n }\n const decision = await conversation.policy.haltOn(haltCtx)\n if (decision === true) {\n halt = { kind: 'predicate', reason: 'predicate_true' }\n break\n }\n if (typeof decision === 'object' && decision !== null && decision.halted) {\n halt = { kind: 'predicate', reason: decision.reason }\n break\n }\n }\n\n currentInput = turn.text\n }\n\n if (!halt) halt = { kind: 'max_turns', turns: transcript.length }\n\n const endedAt = nowIso()\n const result: ConversationResult = {\n runId,\n transcript,\n turns: transcript.length,\n spentCreditsCents,\n halted: halt,\n durationMs: Date.now() - startedAtMs,\n startedAt,\n endedAt,\n }\n if (options.journal) {\n await options.journal.recordHalt(runId, halt, endedAt)\n }\n\n yield { type: 'conversation_end', runId, result, timestamp: endedAt }\n}\n\n// ── Single attempt ───────────────────────────────────────────────────────\n\ninterface SingleAttemptArgs {\n speaker: ConversationParticipant\n participants: readonly ConversationParticipant[]\n input: string\n turnIndex: number\n runId: string\n turnId: string\n transcript: readonly ConversationTurn[]\n signal: AbortSignal\n aggregator: TurnAggregator\n propagatedHeaders: Record<string, string>\n}\n\nasync function* driveSingleAttempt(\n args: SingleAttemptArgs,\n): AsyncGenerator<{ text: string; timestamp?: string }> {\n const task: AgentTaskSpec = {\n id: args.turnId,\n intent: args.input,\n metadata: {\n runId: args.runId,\n turnId: args.turnId,\n turnIndex: args.turnIndex,\n speaker: args.speaker.name,\n participants: args.participants.map((p) => p.name),\n },\n }\n const knowledge = passingReadiness(task.id)\n const messages = buildMessagesFor(args.speaker.name, args.transcript, args.input)\n const backendInput: AgentBackendInput = { task, message: args.input, messages }\n\n const startCtx: Omit<AgentBackendContext, 'session'> & { requestedSessionId?: string } = {\n task,\n knowledge,\n signal: args.signal,\n runId: args.runId,\n turnId: args.turnId,\n propagatedHeaders: args.propagatedHeaders,\n }\n const session: RuntimeSession = args.speaker.backend.start\n ? touchSession(await args.speaker.backend.start(backendInput, startCtx))\n : newRuntimeSession(args.speaker.backend.kind, undefined, {\n runId: args.runId,\n turnIndex: args.turnIndex,\n turnId: args.turnId,\n speaker: args.speaker.name,\n })\n\n const streamCtx: AgentBackendContext = {\n task,\n knowledge,\n session,\n signal: args.signal,\n runId: args.runId,\n turnId: args.turnId,\n propagatedHeaders: args.propagatedHeaders,\n }\n\n for await (const event of args.speaker.backend.stream(backendInput, streamCtx)) {\n if (args.signal.aborted) {\n // Surface the abort so the outer retry/halt logic can react. The signal\n // either fires because of caller-cancel (propagate as-is) or because of\n // the per-attempt deadline timer (signal.reason is DeadlineExceededError).\n const reason = args.signal.reason\n throw reason instanceof Error ? reason : new Error('aborted')\n }\n if (event.type === 'text_delta') {\n args.aggregator.appendText(event.text)\n yield { text: event.text, timestamp: event.timestamp }\n } else if (event.type === 'llm_call') {\n args.aggregator.recordUsage(event)\n } else if (event.type === 'backend_error') {\n throw new BackendTransportError(args.speaker.backend.kind, event.message, {\n status: event.error?.status,\n body: event.error?.body,\n })\n } else if (event.type === 'final') {\n if (event.status !== 'completed') {\n throw new BackendTransportError(\n args.speaker.backend.kind,\n event.error?.message ?? event.reason,\n { status: event.error?.status, body: event.error?.body },\n )\n }\n args.aggregator.adoptFinalText(event.text)\n }\n }\n\n if (!args.aggregator.hasText()) {\n throw new BackendTransportError(\n args.speaker.backend.kind,\n `backend '${args.speaker.backend.kind}' completed without text`,\n )\n }\n}\n\nclass TurnAggregator {\n private text = ''\n private adoptedFinal = false\n private usage:\n | {\n tokensIn?: number\n tokensOut?: number\n costUsd?: number\n latencyMs?: number\n model?: string\n }\n | undefined\n\n constructor(private readonly base: { index: number; speaker: string; startedAt: string }) {}\n\n appendText(text: string): void {\n if (this.adoptedFinal) return\n this.text += text\n }\n\n /**\n * Use the backend's `final.text` only when no streamed deltas were observed.\n * Some backends emit deltas AND a final summary; treating both as content\n * would double-count.\n */\n adoptFinalText(text: string | undefined): void {\n if (!text) return\n if (this.text.length > 0) return\n this.text = text\n this.adoptedFinal = true\n }\n\n hasText(): boolean {\n return this.text.trim().length > 0\n }\n\n recordUsage(event: {\n model?: string\n tokensIn?: number\n tokensOut?: number\n costUsd?: number\n latencyMs?: number\n }): void {\n const u = this.usage ?? {}\n if (event.tokensIn !== undefined) u.tokensIn = (u.tokensIn ?? 0) + event.tokensIn\n if (event.tokensOut !== undefined) u.tokensOut = (u.tokensOut ?? 0) + event.tokensOut\n if (event.costUsd !== undefined) u.costUsd = (u.costUsd ?? 0) + event.costUsd\n if (event.latencyMs !== undefined) u.latencyMs = event.latencyMs\n if (event.model !== undefined) u.model = event.model\n this.usage = u\n }\n\n toTurn(meta: { turnId: string; attempts: number }): ConversationTurn {\n return {\n index: this.base.index,\n speaker: this.base.speaker,\n turnId: meta.turnId,\n text: this.text.trim(),\n usage: this.usage,\n attempts: meta.attempts,\n startedAt: this.base.startedAt,\n endedAt: nowIso(),\n }\n }\n}\n\n/**\n * Build the participant's POV of the transcript so an OpenAI-compatible\n * backend sees its own turns as `assistant` and everyone else's as `user`,\n * with explicit speaker tags so 3+ party conversations stay disambiguated.\n * The seed / current input is appended as the trailing user message.\n */\nfunction buildMessagesFor(\n speakerName: string,\n transcript: readonly ConversationTurn[],\n currentInput: string,\n): Array<{ role: string; content: string }> {\n const messages: Array<{ role: string; content: string }> = []\n for (const turn of transcript) {\n if (turn.speaker === speakerName) {\n messages.push({ role: 'assistant', content: turn.text })\n } else {\n messages.push({ role: 'user', content: `[${turn.speaker}] ${turn.text}` })\n }\n }\n if (currentInput) messages.push({ role: 'user', content: currentInput })\n return messages\n}\n\n/**\n * True when this participant should forward the caller's\n * `X-Tangle-Forwarded-Authorization` on outbound calls (the \"pass-through\"\n * commercial mode). False when it elects to pay for its own outbound calls\n * (the \"reseller\" / \"bundle\" mode). See ConversationParticipant.authSource.\n */\nfunction resolveAuthForwarding(\n participant: ConversationParticipant,\n state: { transcript: readonly ConversationTurn[]; turnIndex: number; spentCreditsCents: number },\n): boolean {\n const decision =\n typeof participant.authSource === 'function'\n ? participant.authSource(state)\n : (participant.authSource ?? 'forward-user')\n return decision === 'forward-user'\n}\n\nfunction selectSpeaker(\n order: TurnOrder | undefined,\n participantCount: number,\n state: { transcript: readonly ConversationTurn[]; turnIndex: number; spentCreditsCents: number },\n): number {\n const resolved = order ?? (participantCount === 2 ? 'alternate' : 'round-robin')\n if (resolved === 'alternate' || resolved === 'round-robin') {\n return state.turnIndex % participantCount\n }\n if (typeof resolved === 'function') {\n const idx = resolved(state)\n if (!Number.isInteger(idx) || idx < 0 || idx >= participantCount) {\n throw new BackendTransportError(\n 'conversation',\n `turnOrder function returned invalid index ${String(idx)} for ${participantCount} participants`,\n )\n }\n return idx\n }\n throw new BackendTransportError('conversation', `unknown turnOrder: ${String(resolved)}`)\n}\n\nfunction centsFromUsd(usd: number): number {\n return Math.round(usd * 100)\n}\n\n/**\n * Synthesize a knowledge-readiness report that *passes* every gate, used to\n * satisfy `AgentBackendContext.knowledge` per turn. Conversations don't apply\n * task-level readiness gating per-turn — that's a `runAgentTask` concern.\n */\nfunction passingReadiness(taskId: string): KnowledgeReadinessReport {\n return {\n taskId,\n readinessScore: 1,\n blockingMissingRequirements: [],\n nonBlockingGaps: [],\n recommendedAction: 'run_agent',\n bundle: {\n taskId,\n requirements: [],\n evidenceIds: [],\n claimIds: [],\n wikiPageIds: [],\n userAnswers: {},\n missing: [],\n readinessScore: 1,\n },\n severity: 'info',\n reason: 'conversation-mode: readiness gating not applied per-turn',\n }\n}\n","/**\n *\n * Wrap a `Conversation` so it satisfies `AgentExecutionBackend`. The result is\n * an addressable \"single agent\" whose internal behavior is an N-party\n * orchestrated conversation — the recursion primitive that lets a swarm be a\n * participant inside another swarm, or be published behind a single\n * agent-gateway endpoint.\n *\n * Stream events from inner participants are NOT forwarded verbatim. Outer\n * callers see one `text_delta` per inner turn (the turn's full text), tagged\n * with `[speaker] ` prefix so the outer transcript stays attributable. The\n * conversation's `conversation_end` halt reason rides on a `final` event.\n *\n * @stable\n */\n\nimport { newRuntimeSession, nowIso } from '../sessions'\nimport type {\n AgentBackendContext,\n AgentBackendInput,\n AgentExecutionBackend,\n RuntimeSession,\n RuntimeStreamEvent,\n} from '../types'\nimport { FORWARD_HEADERS, readDepth } from './headers'\nimport { runConversationStream } from './run-conversation'\nimport type { Conversation, HaltReason } from './types'\n\nexport function createConversationBackend(options: {\n conversation: Conversation\n /** Optional backend kind label. Defaults to `'conversation'`. */\n kind?: string\n}): AgentExecutionBackend {\n const kind = options.kind ?? 'conversation'\n\n return {\n kind,\n start(_input, context): RuntimeSession {\n return newRuntimeSession(kind, context.requestedSessionId, {\n participants: options.conversation.participants.map((p) => p.name),\n })\n },\n async *stream(\n input: AgentBackendInput,\n context: AgentBackendContext,\n ): AsyncIterable<RuntimeStreamEvent> {\n const seed = input.message ?? input.messages?.at(-1)?.content ?? context.task.intent\n const task = context.task\n const session = context.session\n\n yield { type: 'backend_start', task, session, backend: kind, timestamp: nowIso() }\n\n let finalText = ''\n let totalCostUsd = 0\n let totalTokensIn = 0\n let totalTokensOut = 0\n\n // Recursion: forward this call's propagation context into the nested\n // conversation. The nested run INHERITS the parent's runId (protocol\n // invariant: runId is immutable across nesting), continues the depth\n // counter from the headers, and stamps the enclosing turn as the\n // parentTurnId so trace stitching reaches across nesting levels.\n const inboundDepth = parseInboundDepth(context.propagatedHeaders)\n for await (const event of runConversationStream(options.conversation, {\n seed,\n signal: context.signal,\n runId: context.runId,\n propagatedHeaders: context.propagatedHeaders,\n inboundDepth,\n parentTurnId: context.turnId,\n })) {\n if (event.type === 'turn_end') {\n const tagged = `[${event.turn.speaker}] ${event.turn.text}\\n`\n finalText += tagged\n yield { type: 'text_delta', task, session, text: tagged, timestamp: event.timestamp }\n if (event.turn.usage) {\n const u = event.turn.usage\n if (u.costUsd !== undefined) totalCostUsd += u.costUsd\n if (u.tokensIn !== undefined) totalTokensIn += u.tokensIn\n if (u.tokensOut !== undefined) totalTokensOut += u.tokensOut\n yield {\n type: 'llm_call',\n task,\n session,\n model: u.model ?? `${kind}/${event.turn.speaker}`,\n tokensIn: u.tokensIn,\n tokensOut: u.tokensOut,\n costUsd: u.costUsd,\n latencyMs: u.latencyMs,\n timestamp: event.timestamp,\n }\n }\n } else if (event.type === 'conversation_end') {\n const halt = event.result.halted\n yield {\n type: 'final',\n task,\n session,\n status: halt.kind === 'participant_error' ? 'failed' : 'completed',\n reason: describeHalt(halt),\n text: finalText.trim(),\n metadata: {\n conversationRunId: event.result.runId,\n turns: event.result.turns,\n spentCreditsCents: event.result.spentCreditsCents,\n halted: halt,\n durationMs: event.result.durationMs,\n tokensIn: totalTokensIn,\n tokensOut: totalTokensOut,\n costUsd: totalCostUsd,\n },\n timestamp: event.timestamp,\n }\n }\n }\n\n yield { type: 'backend_end', task, session, backend: kind, timestamp: nowIso() }\n },\n }\n}\n\nfunction parseInboundDepth(headers: Readonly<Record<string, string>> | undefined): number {\n if (!headers) return 0\n // Accept either the canonical header key OR a lookup via the keyed name.\n const raw = headers[FORWARD_HEADERS.depth]\n if (raw === undefined) return 0\n try {\n return readDepth({ [FORWARD_HEADERS.depth]: raw })\n } catch {\n return 0\n }\n}\n\nfunction describeHalt(halt: HaltReason): string {\n switch (halt.kind) {\n case 'max_turns':\n return `max_turns (${halt.turns})`\n case 'max_credits':\n return `max_credits (${halt.spentCents}/${halt.capCents}¢)`\n case 'predicate':\n return `predicate: ${halt.reason}`\n case 'abort':\n return 'abort'\n case 'participant_error':\n return `participant_error[${halt.participant}]: ${halt.message}`\n }\n}\n","/**\n *\n * Declarative constructor for a multi-agent `Conversation`. Validates inputs\n * fail-loud at definition time (duplicate participant names, alternate order\n * with ≠2 participants, non-positive `maxTurns`) so misconfiguration is caught\n * before `runConversation` is called and not buried inside a streaming run.\n *\n * @stable\n */\n\nimport { ValidationError } from '../errors'\nimport type { Conversation, ConversationParticipant, ConversationPolicy, TurnOrder } from './types'\n\nexport function defineConversation(input: {\n participants: ConversationParticipant[]\n policy: ConversationPolicy\n}): Conversation {\n if (input.participants.length < 2) {\n throw new ValidationError(\n `Conversation requires at least 2 participants; received ${input.participants.length}.`,\n )\n }\n\n const seen = new Set<string>()\n for (const p of input.participants) {\n if (!p.name || p.name.trim() === '') {\n throw new ValidationError('Conversation participant.name must be a non-empty string.')\n }\n if (seen.has(p.name)) {\n throw new ValidationError(\n `Conversation participant names must be unique within a Conversation; '${p.name}' appears more than once.`,\n )\n }\n seen.add(p.name)\n if (!p.backend || typeof p.backend.stream !== 'function') {\n throw new ValidationError(\n `Conversation participant '${p.name}' is missing a backend with a stream() method.`,\n )\n }\n }\n\n const policy = normalizePolicy(input.policy, input.participants.length)\n\n return {\n participants: input.participants,\n policy,\n }\n}\n\nfunction normalizePolicy(policy: ConversationPolicy, participantCount: number): ConversationPolicy {\n if (!Number.isInteger(policy.maxTurns) || policy.maxTurns < 1) {\n throw new ValidationError(\n `ConversationPolicy.maxTurns must be a positive integer; received ${String(policy.maxTurns)}.`,\n )\n }\n if (\n policy.maxCreditsCents !== undefined &&\n (!Number.isFinite(policy.maxCreditsCents) || policy.maxCreditsCents < 0)\n ) {\n throw new ValidationError(\n `ConversationPolicy.maxCreditsCents must be a non-negative finite number when set; received ${String(\n policy.maxCreditsCents,\n )}.`,\n )\n }\n const turnOrder = policy.turnOrder ?? (participantCount === 2 ? 'alternate' : 'round-robin')\n if (turnOrder === 'alternate' && participantCount !== 2) {\n throw new ValidationError(\n `ConversationPolicy.turnOrder 'alternate' requires exactly 2 participants; received ${participantCount}. Use 'round-robin' or a custom selector for N-party conversations.`,\n )\n }\n return { ...policy, turnOrder: turnOrder as TurnOrder }\n}\n","/**\n *\n * Durable conversation transcript — survives a driver process crash mid-run.\n * The runner journals every committed turn before yielding `turn_end`, so a\n * resumed run replays the same `runId` against the same journal and picks up\n * from the first un-recorded turn. Combined with the deterministic\n * `turnId(runId, index, speaker)`, a retried turn collides with the prior\n * attempt's id and any caching gateway can dedupe.\n *\n * The interface is small enough that a Cloudflare D1 / R2 / postgres adapter\n * is ~30 lines. The in-memory adapter is the default for tests and scratch.\n * The file adapter (JSONL on disk) is the default-durable choice when no\n * upstream store is wired.\n *\n * @stable\n */\n\nimport type { ConversationTurn, HaltReason } from './types'\n\nexport interface ConversationJournalEntry {\n runId: string\n startedAt: string\n /** Set when the run reaches a terminal state. */\n halted?: HaltReason\n endedAt?: string\n turns: ConversationTurn[]\n}\n\nexport interface ConversationJournal {\n /**\n * Load any prior state for `runId`. Returns `undefined` for a fresh run.\n * Implementations MUST NOT mutate the returned object — the runner clones\n * before continuing — but the runtime treats absence and emptiness\n * identically, so a journal with zero turns is equivalent to \"fresh.\"\n */\n loadRun(runId: string): Promise<ConversationJournalEntry | undefined>\n\n /**\n * Initialise journal state for a fresh run. Called once per run, before any\n * `appendTurn`. Idempotent: calling with an existing runId is a no-op if\n * the entry already exists with the same `startedAt`.\n */\n beginRun(runId: string, startedAt: string): Promise<void>\n\n /**\n * Append a committed turn. The runner only calls this AFTER the turn's\n * backend stream completed and the credit total has been updated, so an\n * appended turn is observed-committed and never speculative.\n */\n appendTurn(runId: string, turn: ConversationTurn): Promise<void>\n\n /**\n * Record the run's terminal halt reason + end time. Once called, the run\n * is observed-final; subsequent `loadRun` returns the same halt.\n */\n recordHalt(runId: string, halt: HaltReason, endedAt: string): Promise<void>\n}\n\n/** In-memory `ConversationJournal` — suitable for testing and single-process runs. */\nexport class InMemoryConversationJournal implements ConversationJournal {\n private readonly entries = new Map<string, ConversationJournalEntry>()\n\n async loadRun(runId: string): Promise<ConversationJournalEntry | undefined> {\n const entry = this.entries.get(runId)\n if (!entry) return undefined\n // Defensive copy — callers MUST NOT mutate journal-owned arrays.\n return {\n runId: entry.runId,\n startedAt: entry.startedAt,\n halted: entry.halted,\n endedAt: entry.endedAt,\n turns: [...entry.turns],\n }\n }\n\n async beginRun(runId: string, startedAt: string): Promise<void> {\n const existing = this.entries.get(runId)\n if (existing) {\n if (existing.startedAt !== startedAt) {\n throw new Error(\n `runId '${runId}' already exists with startedAt=${existing.startedAt}; refusing to overwrite with ${startedAt}`,\n )\n }\n return\n }\n this.entries.set(runId, { runId, startedAt, turns: [] })\n }\n\n async appendTurn(runId: string, turn: ConversationTurn): Promise<void> {\n const entry = this.entries.get(runId)\n if (!entry) {\n throw new Error(\n `appendTurn called for unknown runId '${runId}'; call beginRun first or use the runner which handles it`,\n )\n }\n if (entry.halted) {\n throw new Error(\n `cannot append turn to halted run '${runId}' (halt reason: ${JSON.stringify(entry.halted)})`,\n )\n }\n entry.turns.push(turn)\n }\n\n async recordHalt(runId: string, halt: HaltReason, endedAt: string): Promise<void> {\n const entry = this.entries.get(runId)\n if (!entry) {\n throw new Error(`recordHalt called for unknown runId '${runId}'`)\n }\n entry.halted = halt\n entry.endedAt = endedAt\n }\n}\n\n/**\n * JSONL on disk. One line per record; first line is the `begin`, subsequent\n * lines are `turn` records, terminal line is `halt`. Replays the whole file\n * on `loadRun` — cheap for the conversation sizes this is designed for\n * (thousands of turns, not millions). For huge runs, plug in a real DB\n * adapter; the interface is small.\n *\n * Each `appendTurn` / `recordHalt` calls `fsync` after the write so a\n * process crash between writes never loses an acknowledged turn.\n */\nexport class FileConversationJournal implements ConversationJournal {\n constructor(private readonly path: string) {}\n\n async loadRun(runId: string): Promise<ConversationJournalEntry | undefined> {\n const fs = await import('node:fs/promises')\n let text: string\n try {\n text = await fs.readFile(this.path, 'utf8')\n } catch (err) {\n if (isNoEntError(err)) return undefined\n throw err\n }\n const lines = text.split('\\n').filter((line) => line.length > 0)\n let entry: ConversationJournalEntry | undefined\n for (const line of lines) {\n const record = JSON.parse(line) as JournalRecord\n if (record.runId !== runId) continue\n if (record.kind === 'begin') {\n entry = { runId, startedAt: record.startedAt, turns: [] }\n } else if (record.kind === 'turn') {\n if (!entry) {\n throw new Error(\n `journal corrupted: turn record for runId '${runId}' precedes its begin record`,\n )\n }\n entry.turns.push(record.turn)\n } else if (record.kind === 'halt') {\n if (!entry) {\n throw new Error(\n `journal corrupted: halt record for runId '${runId}' precedes its begin record`,\n )\n }\n entry.halted = record.halted\n entry.endedAt = record.endedAt\n }\n }\n return entry\n }\n\n async beginRun(runId: string, startedAt: string): Promise<void> {\n const existing = await this.loadRun(runId)\n if (existing) {\n if (existing.startedAt !== startedAt) {\n throw new Error(\n `runId '${runId}' already exists in ${this.path} with startedAt=${existing.startedAt}; refusing to overwrite with ${startedAt}`,\n )\n }\n return\n }\n await this.appendRecord({ kind: 'begin', runId, startedAt })\n }\n\n async appendTurn(runId: string, turn: ConversationTurn): Promise<void> {\n await this.appendRecord({ kind: 'turn', runId, turn })\n }\n\n async recordHalt(runId: string, halt: HaltReason, endedAt: string): Promise<void> {\n await this.appendRecord({ kind: 'halt', runId, halted: halt, endedAt })\n }\n\n private async appendRecord(record: JournalRecord): Promise<void> {\n const fs = await import('node:fs/promises')\n const path = await import('node:path')\n await fs.mkdir(path.dirname(this.path), { recursive: true })\n const fh = await fs.open(this.path, 'a')\n try {\n await fh.write(`${JSON.stringify(record)}\\n`)\n await fh.sync()\n } finally {\n await fh.close()\n }\n }\n}\n\ntype JournalRecord =\n | { kind: 'begin'; runId: string; startedAt: string }\n | { kind: 'turn'; runId: string; turn: ConversationTurn }\n | { kind: 'halt'; runId: string; halted: HaltReason; endedAt: string }\n\nfunction isNoEntError(err: unknown): boolean {\n return (\n typeof err === 'object' &&\n err !== null &&\n 'code' in err &&\n (err as { code: unknown }).code === 'ENOENT'\n )\n}\n","/**\n *\n * Durable conversation journal backed by any SQL store. Adapter-agnostic by\n * design: callers wire a `SqlAdapter` against their driver of choice (D1,\n * postgres, sqlite, libSQL…) and the same journal implementation persists\n * conversation runs durably across process restarts. The schema is two\n * tables — runs (latest state) + events (append-only log) — so a partial\n * crash in the middle of a turn leaves an unambiguous \"last committed turn\"\n * to resume from.\n *\n * Why not bake in a specific driver? agent-runtime ships against multiple\n * runtimes (Cloudflare Workers, Node, Bun, Deno) and consumers' fleets have\n * already standardized on one of D1 / postgres / sqlite / libSQL. Adapter\n * indirection costs ~5 lines per driver in the consumer's code and keeps the\n * SDK free of native deps.\n *\n * @example D1 (Cloudflare Workers)\n * import { SqlConversationJournal, d1ToSqlAdapter } from '@tangle-network/agent-runtime'\n * const journal = new SqlConversationJournal(d1ToSqlAdapter(env.DB))\n * await journal.migrate() // once at deploy\n * await runConversation(conv, { seed, journal, runId: 'run_abc' })\n *\n * @example node-postgres\n * import { Pool } from 'pg'\n * const pool = new Pool({ connectionString: process.env.DATABASE_URL })\n * const pg: SqlAdapter = {\n * exec: async (sql, params = []) => {\n * const r = await pool.query(sql, params as never)\n * return { rowsAffected: r.rowCount ?? 0 }\n * },\n * query: async (sql, params = []) => (await pool.query(sql, params as never)).rows,\n * }\n * const journal = new SqlConversationJournal(pg)\n * await journal.migrate()\n *\n * @stable\n */\n\nimport type { ConversationJournal, ConversationJournalEntry } from './journal'\nimport type { ConversationTurn, HaltReason } from './types'\n\n/**\n * Minimal SQL driver shape. Implementations forward to whichever client the\n * deployment already uses; agent-runtime takes no opinion on which.\n *\n * Parameter placeholders MUST be `?` (positional). All adapters listed in the\n * file header accept this convention.\n */\nexport interface SqlAdapter {\n /** Execute a write statement (INSERT/UPDATE/DELETE/DDL). */\n exec(sql: string, params?: readonly unknown[]): Promise<{ rowsAffected: number }>\n /** Execute a read statement (SELECT). Returns rows as plain objects. */\n query<TRow = Record<string, unknown>>(sql: string, params?: readonly unknown[]): Promise<TRow[]>\n}\n\n/**\n * Adapt a Cloudflare D1 binding to the SqlAdapter shape. Lives here so D1\n * consumers don't have to write the wrapper themselves; the runtime never\n * imports `@cloudflare/workers-types` directly (peer-style typing).\n */\nexport function d1ToSqlAdapter(db: D1DatabaseLike): SqlAdapter {\n return {\n async exec(sql, params = []) {\n const stmt = db.prepare(sql)\n const bound = params.length > 0 ? stmt.bind(...params) : stmt\n const result = await bound.run()\n const meta = (result as { meta?: { rows_written?: number; changes?: number } }).meta\n return { rowsAffected: meta?.rows_written ?? meta?.changes ?? 0 }\n },\n async query<TRow>(sql: string, params: readonly unknown[] = []): Promise<TRow[]> {\n const stmt = db.prepare(sql)\n const bound = params.length > 0 ? stmt.bind(...params) : stmt\n const result = await bound.all<TRow>()\n return result.results ?? []\n },\n }\n}\n\n/**\n * Structural type matching the surface of `D1Database` we depend on, so the\n * SDK never imports `@cloudflare/workers-types`. Consumers pass their real\n * `D1Database` from `env.DB` and TS structural compatibility lines it up.\n */\nexport interface D1DatabaseLike {\n prepare(sql: string): D1StmtLike\n}\nexport interface D1StmtLike {\n bind(...params: unknown[]): D1StmtLike\n run(): Promise<unknown>\n all<TRow = unknown>(): Promise<{ results?: TRow[] }>\n}\n\nconst RUNS_TABLE_DDL = (table: string) => `\n CREATE TABLE IF NOT EXISTS ${table}_runs (\n run_id TEXT PRIMARY KEY,\n started_at TEXT NOT NULL,\n halted_kind TEXT,\n halted_payload TEXT,\n ended_at TEXT\n )\n`\nconst TURNS_TABLE_DDL = (table: string) => `\n CREATE TABLE IF NOT EXISTS ${table}_turns (\n run_id TEXT NOT NULL,\n turn_index INTEGER NOT NULL,\n payload TEXT NOT NULL,\n PRIMARY KEY (run_id, turn_index)\n )\n`\nconst TURNS_INDEX_DDL = (table: string) => `\n CREATE INDEX IF NOT EXISTS idx_${table}_turns_run ON ${table}_turns (run_id, turn_index)\n`\n\n/**\n * SQL-backed ConversationJournal. Two tables — runs (one row per runId, holds\n * start/halt timestamps + halt reason) and turns (one row per committed turn,\n * payload is the ConversationTurn JSON). Replays the turns table on\n * `loadRun` and writes append-only per `appendTurn`.\n */\nexport class SqlConversationJournal implements ConversationJournal {\n /**\n * @param db SQL adapter (D1, postgres, sqlite, libSQL — all work)\n * @param table Table-name prefix; the journal creates `${table}_runs` and\n * `${table}_turns`. Lets multiple journals share a database\n * without colliding (e.g. one per product surface).\n */\n constructor(\n private readonly db: SqlAdapter,\n private readonly table: string = 'agent_runtime_journal',\n ) {}\n\n /**\n * Create the journal's tables if absent. Idempotent. Call once at deploy\n * (or at app boot) — running on every request is harmless but adds latency.\n */\n async migrate(): Promise<void> {\n await this.db.exec(RUNS_TABLE_DDL(this.table))\n await this.db.exec(TURNS_TABLE_DDL(this.table))\n await this.db.exec(TURNS_INDEX_DDL(this.table))\n }\n\n async loadRun(runId: string): Promise<ConversationJournalEntry | undefined> {\n const runs = await this.db.query<{\n run_id: string\n started_at: string\n halted_kind: string | null\n halted_payload: string | null\n ended_at: string | null\n }>(\n `SELECT run_id, started_at, halted_kind, halted_payload, ended_at FROM ${this.table}_runs WHERE run_id = ?`,\n [runId],\n )\n const row = runs[0]\n if (!row) return undefined\n const turns = await this.db.query<{ payload: string; turn_index: number }>(\n `SELECT payload, turn_index FROM ${this.table}_turns WHERE run_id = ? ORDER BY turn_index ASC`,\n [runId],\n )\n return {\n runId: row.run_id,\n startedAt: row.started_at,\n halted: row.halted_payload ? (JSON.parse(row.halted_payload) as HaltReason) : undefined,\n endedAt: row.ended_at ?? undefined,\n turns: turns.map((t) => JSON.parse(t.payload) as ConversationTurn),\n }\n }\n\n async beginRun(runId: string, startedAt: string): Promise<void> {\n const existing = await this.db.query<{ started_at: string }>(\n `SELECT started_at FROM ${this.table}_runs WHERE run_id = ?`,\n [runId],\n )\n if (existing.length > 0) {\n if (existing[0]?.started_at !== startedAt) {\n throw new Error(\n `runId '${runId}' already exists with startedAt=${existing[0]?.started_at}; refusing to overwrite with ${startedAt}`,\n )\n }\n return\n }\n await this.db.exec(`INSERT INTO ${this.table}_runs (run_id, started_at) VALUES (?, ?)`, [\n runId,\n startedAt,\n ])\n }\n\n async appendTurn(runId: string, turn: ConversationTurn): Promise<void> {\n const halted = await this.db.query<{ halted_kind: string | null }>(\n `SELECT halted_kind FROM ${this.table}_runs WHERE run_id = ?`,\n [runId],\n )\n if (halted.length === 0) {\n throw new Error(\n `appendTurn called for unknown runId '${runId}'; call beginRun first or use the runner which handles it`,\n )\n }\n if (halted[0]?.halted_kind) {\n throw new Error(\n `cannot append turn to halted run '${runId}' (halt kind: ${halted[0]?.halted_kind})`,\n )\n }\n await this.db.exec(\n `INSERT INTO ${this.table}_turns (run_id, turn_index, payload) VALUES (?, ?, ?)`,\n [runId, turn.index, JSON.stringify(turn)],\n )\n }\n\n async recordHalt(runId: string, halt: HaltReason, endedAt: string): Promise<void> {\n const rs = await this.db.exec(\n `UPDATE ${this.table}_runs SET halted_kind = ?, halted_payload = ?, ended_at = ? WHERE run_id = ?`,\n [halt.kind, JSON.stringify(halt), endedAt, runId],\n )\n if (rs.rowsAffected === 0) {\n throw new Error(`recordHalt called for unknown runId '${runId}'`)\n }\n }\n}\n","/**\n * `runPersonaConversation` — the persona loop runner: run a WORKER `AgentProfile`\n * (the agent under test) as a multi-round conversation driven by a PERSONA (the\n * simulated user), over the persistent conversation transcript.\n *\n * It is profiles-vs-profiles: the persona is itself a driver `AgentProfile` (an\n * LLM role-playing the user from its facts) — `runConversation` runs the two\n * against each other. Scripted persona turns are kept as a deterministic\n * fast-path. Only the WORKER is metered (it is the side under test); the\n * persona-driver is the test harness, not billed against the agent.\n *\n * `runPersonaDispatch` wraps the runner as a `ProfileDispatchFn` so it drops\n * straight into `runProfileMatrix({ dispatch })` — the same loop serves a single\n * cell and the whole matrix, replacing the per-agent hand-rolled\n * `dispatchWithSurface` bridges.\n */\n\nimport type { AgentProfile, MaximumCharge } from '@tangle-network/agent-eval'\nimport type {\n DispatchContext,\n ProfileDispatchFn,\n Scenario,\n} from '@tangle-network/agent-eval/campaign'\nimport { createIterableBackend } from '../backends'\nimport type { AgentExecutionBackend, RuntimeStreamEvent } from '../types'\nimport { defineConversation } from './define-conversation'\nimport { runConversation } from './run-conversation'\nimport type { ConversationTurn, HaltPredicate, HaltReason } from './types'\n\n/** A persona that drives the conversation: either a full driver `AgentProfile`\n * (an LLM user-sim) or a deterministic script of user turns (the fast-path). */\nexport type PersonaDriver =\n | { kind: 'profile'; profile: AgentProfile }\n | { kind: 'scripted'; turns: string[] }\n\nexport interface RunPersonaConversationOptions {\n /** The agent under test. Metered; its rendered prompt leads its turns. */\n worker: AgentProfile\n /** The simulated user driving the dialogue. */\n persona: PersonaDriver\n /** Turn an `AgentProfile` into a runnable backend (router / sandbox / fake).\n * Applied to the worker and to a `profile`-kind persona. */\n backendFor: (profile: AgentProfile, role: 'worker' | 'persona') => AgentExecutionBackend\n /** Render a profile's system prompt — prepended to that profile's messages. */\n systemPromptOf: (profile: AgentProfile) => string\n /** Speaker-turn cap. Default for a scripted persona = `2 * turns.length`\n * (worker answers each user turn). REQUIRED for a `profile` persona. */\n maxTurns?: number\n /** Kickoff message routed to the first speaker (the persona). Default 'Begin.' */\n seed?: string\n /** Content-based \"until satisfied\" halt, called after every turn. `maxTurns` is the\n * hard ceiling; this is the early stop (the persona declares the goal met / unreachable). */\n haltOn?: HaltPredicate\n signal?: AbortSignal\n /** Worker participant / transcript speaker label. Default 'agent'. */\n workerName?: string\n}\n\nexport interface PersonaConversationResult {\n transcript: ConversationTurn[]\n turns: number\n halted: HaltReason\n /** Worker-only spend (the side under test). */\n costUsd: number\n tokensIn: number\n tokensOut: number\n}\n\ninterface UsageCounter {\n tokensIn: number\n tokensOut: number\n costUsd: number\n}\n\n/** Prefix a backend's requests with `systemPrompt`; when `counter` is given,\n * accumulate its `llm_call` token/cost usage (used for the metered worker). */\nfunction withProfilePrompt(\n inner: AgentExecutionBackend,\n systemPrompt: string,\n counter?: UsageCounter,\n): AgentExecutionBackend {\n return {\n kind: inner.kind,\n start: inner.start ? (input, ctx) => inner.start!(input, ctx) : undefined,\n resume: inner.resume ? (session, input, ctx) => inner.resume!(session, input, ctx) : undefined,\n stop: inner.stop ? (session, reason) => inner.stop!(session, reason) : undefined,\n async *stream(input, context) {\n const base =\n input.messages ?? (input.message ? [{ role: 'user', content: input.message }] : [])\n const messages =\n base[0]?.role === 'system' ? base : [{ role: 'system', content: systemPrompt }, ...base]\n for await (const event of inner.stream({ ...input, messages }, context)) {\n if (counter && event.type === 'llm_call') {\n counter.tokensIn += event.tokensIn ?? 0\n counter.tokensOut += event.tokensOut ?? 0\n counter.costUsd += event.costUsd ?? 0\n }\n yield event\n }\n },\n }\n}\n\n/** A persona participant that replays scripted user turns in order. */\nfunction scriptedPersonaBackend(turns: readonly string[]): AgentExecutionBackend {\n let idx = 0\n return createIterableBackend({\n kind: 'persona-user',\n async *stream(_input, context) {\n const text = turns[idx]\n if (text === undefined) {\n throw new Error(\n `persona-user: ran out of scripted turns at index ${idx} (had ${turns.length})`,\n )\n }\n idx += 1\n yield {\n type: 'text_delta',\n task: context.task,\n session: context.session,\n text,\n timestamp: new Date().toISOString(),\n } satisfies RuntimeStreamEvent\n },\n })\n}\n\n/**\n * Run one worker profile against one persona as a multi-round conversation.\n * The persona leads (participant 0): it speaks, the worker answers, repeat,\n * until `maxTurns`. Returns the persistent transcript + worker-only usage.\n */\nexport async function runPersonaConversation(\n opts: RunPersonaConversationOptions,\n): Promise<PersonaConversationResult> {\n const counter: UsageCounter = { tokensIn: 0, tokensOut: 0, costUsd: 0 }\n const workerName = opts.workerName ?? 'agent'\n const worker = withProfilePrompt(\n opts.backendFor(opts.worker, 'worker'),\n opts.systemPromptOf(opts.worker),\n counter,\n )\n\n let persona: AgentExecutionBackend\n let maxTurns: number\n if (opts.persona.kind === 'scripted') {\n if (opts.persona.turns.length === 0) {\n throw new Error('runPersonaConversation: scripted persona has no turns')\n }\n persona = scriptedPersonaBackend(opts.persona.turns)\n maxTurns = opts.maxTurns ?? 2 * opts.persona.turns.length\n } else {\n persona = withProfilePrompt(\n opts.backendFor(opts.persona.profile, 'persona'),\n opts.systemPromptOf(opts.persona.profile),\n )\n if (opts.maxTurns === undefined) {\n throw new Error('runPersonaConversation: maxTurns is required for a profile-driven persona')\n }\n maxTurns = opts.maxTurns\n }\n\n const conversation = defineConversation({\n // Persona leads (participant 0): the seed routes to it, it produces the\n // user turn, the worker answers, alternate.\n participants: [\n { name: 'user', backend: persona },\n { name: workerName, backend: worker },\n ],\n policy: { maxTurns, turnOrder: 'alternate', ...(opts.haltOn ? { haltOn: opts.haltOn } : {}) },\n })\n const result = await runConversation(conversation, {\n seed: opts.seed ?? 'Begin.',\n signal: opts.signal,\n })\n // Worker-only cost. Prefer the worker's own metered llm_call spend. Fall back\n // to the engine's aggregate spend ONLY for a scripted persona — there the\n // harness has no LLM cost so the aggregate IS the worker's. For a\n // profile-driven persona the aggregate also includes the persona-driver's\n // spend, so attributing it to the worker would over-count; report the\n // worker's metered spend (0 if its backend reported none) instead.\n const costUsd =\n counter.costUsd > 0\n ? counter.costUsd\n : opts.persona.kind === 'scripted'\n ? result.spentCreditsCents / 100\n : 0\n return {\n transcript: result.transcript,\n turns: result.turns,\n halted: result.halted,\n costUsd,\n tokensIn: counter.tokensIn,\n tokensOut: counter.tokensOut,\n }\n}\n\nexport interface RunPersonaConfig<TScenario extends Scenario, TArtifact> {\n /** Turn an `AgentProfile` into a runnable backend (router / sandbox / fake). */\n backendFor: (profile: AgentProfile, role: 'worker' | 'persona') => AgentExecutionBackend\n /** Render a profile's system prompt. */\n systemPromptOf: (profile: AgentProfile) => string\n /** The persona driving each scenario — a driver profile or scripted turns. */\n personaOf: (scenario: TScenario) => PersonaDriver\n /** Build the scored artifact from the finished transcript. */\n artifactOf: (transcript: ConversationTurn[], scenario: TScenario) => TArtifact\n /** Speaker-turn cap (required when a persona is profile-driven). */\n maxTurns?: (scenario: TScenario) => number\n seed?: (scenario: TScenario) => string\n workerName?: string\n /** Provider- or executor-enforced maximum for the whole worker conversation.\n * Required before execution when the enclosing campaign is cost-capped. */\n maximumCharge?:\n | MaximumCharge\n | ((worker: AgentProfile, scenario: TScenario) => MaximumCharge | undefined)\n}\n\n/**\n * Wrap {@link runPersonaConversation} as a `ProfileDispatchFn` for\n * `runProfileMatrix`: the profile axis is the worker-under-test, the scenario\n * axis is the persona, and the runner is the cell. Meters the worker through\n * `ctx.cost` so the matrix's backend-integrity guard sees real usage.\n */\nexport function runPersonaDispatch<TScenario extends Scenario, TArtifact>(\n config: RunPersonaConfig<TScenario, TArtifact>,\n): ProfileDispatchFn<TScenario, TArtifact> {\n return async (\n worker: AgentProfile,\n scenario: TScenario,\n ctx: DispatchContext,\n ): Promise<TArtifact> => {\n const model = worker.model?.default ?? 'unknown'\n const maximumCharge =\n typeof config.maximumCharge === 'function'\n ? config.maximumCharge(worker, scenario)\n : config.maximumCharge\n const paid = await ctx.cost.runPaidCall({\n channel: 'agent',\n actor: 'persona-conversation',\n model,\n signal: ctx.signal,\n ...(maximumCharge ? { maximumCharge } : {}),\n execute: (executionSignal) =>\n runPersonaConversation({\n worker,\n persona: config.personaOf(scenario),\n backendFor: config.backendFor,\n systemPromptOf: config.systemPromptOf,\n maxTurns: config.maxTurns?.(scenario),\n seed: config.seed?.(scenario),\n signal: executionSignal,\n workerName: config.workerName,\n }),\n receipt: (result) => ({\n model,\n inputTokens: result.tokensIn,\n outputTokens: result.tokensOut,\n ...(result.costUsd > 0 ? { actualCostUsd: result.costUsd } : {}),\n }),\n })\n if (!paid.succeeded) throw paid.error\n const result = paid.value\n return config.artifactOf(result.transcript, scenario)\n }\n}\n"],"mappings":"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","names":["result"]}