@tangle-network/agent-runtime 0.43.0 → 0.45.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +96 -202
  2. package/dist/agent.d.ts +5 -4
  3. package/dist/agent.js +5 -7
  4. package/dist/agent.js.map +1 -1
  5. package/dist/analyst-loop.d.ts +65 -4
  6. package/dist/analyst-loop.js +6 -1
  7. package/dist/audit.d.ts +93 -0
  8. package/dist/audit.js +312 -0
  9. package/dist/audit.js.map +1 -0
  10. package/dist/chunk-4B6U4CVQ.js +15 -0
  11. package/dist/chunk-4B6U4CVQ.js.map +1 -0
  12. package/dist/chunk-FK53TXOP.js +603 -0
  13. package/dist/chunk-FK53TXOP.js.map +1 -0
  14. package/dist/{chunk-MJDGCRAT.js → chunk-IJ6FGOPO.js} +5 -5
  15. package/dist/chunk-IJ6FGOPO.js.map +1 -0
  16. package/dist/{chunk-HVYOHJHK.js → chunk-IJGS6J7X.js} +2 -2
  17. package/dist/chunk-IJGS6J7X.js.map +1 -0
  18. package/dist/chunk-KEWO4KI6.js +3599 -0
  19. package/dist/chunk-KEWO4KI6.js.map +1 -0
  20. package/dist/{chunk-NRZOXCJK.js → chunk-KSMX62JF.js} +2 -2
  21. package/dist/{chunk-C5HMTTNY.js → chunk-NYN5RTLP.js} +13 -12
  22. package/dist/chunk-NYN5RTLP.js.map +1 -0
  23. package/dist/chunk-PRX45WE2.js +264 -0
  24. package/dist/chunk-PRX45WE2.js.map +1 -0
  25. package/dist/{chunk-3HMHSN22.js → chunk-QR4UUC5P.js} +6 -6
  26. package/dist/chunk-QR4UUC5P.js.map +1 -0
  27. package/dist/chunk-WIR4HOOJ.js +27 -0
  28. package/dist/chunk-WIR4HOOJ.js.map +1 -0
  29. package/dist/{chunk-MNCB4SJ5.js → chunk-Z2QXVBA6.js} +296 -8
  30. package/dist/chunk-Z2QXVBA6.js.map +1 -0
  31. package/dist/coder-CczgMqFx.d.ts +114 -0
  32. package/dist/dynamic-BvllHV6M.d.ts +221 -0
  33. package/dist/{improvement-adapter-BC4HhuAR.d.ts → improvement-adapter-CWegd3vw.d.ts} +1 -1
  34. package/dist/improvement.d.ts +2 -3
  35. package/dist/improvement.js +0 -5
  36. package/dist/improvement.js.map +1 -1
  37. package/dist/index.d.ts +123 -10
  38. package/dist/index.js +407 -19
  39. package/dist/index.js.map +1 -1
  40. package/dist/{kb-gate-DTBum3vH.d.ts → kb-gate-D9GBocLN.d.ts} +82 -5
  41. package/dist/{loop-runner-bin-CVoCBmYk.d.ts → loop-runner-bin-CPrCoKqC.d.ts} +14 -10
  42. package/dist/loop-runner-bin.d.ts +9 -7
  43. package/dist/loop-runner-bin.js +6 -8
  44. package/dist/loops.d.ts +7 -371
  45. package/dist/loops.js +96 -19
  46. package/dist/mcp/bin.js +7 -7
  47. package/dist/mcp/bin.js.map +1 -1
  48. package/dist/mcp/index.d.ts +284 -11
  49. package/dist/mcp/index.js +341 -9
  50. package/dist/mcp/index.js.map +1 -1
  51. package/dist/{otel-export-BzvF1Ela.d.ts → otel-export-Dy2DyUCU.d.ts} +1 -1
  52. package/dist/profiles.d.ts +385 -86
  53. package/dist/profiles.js +549 -4
  54. package/dist/profiles.js.map +1 -1
  55. package/dist/run-loop--hSoIknW.d.ts +112 -0
  56. package/dist/runtime-hooks-C7JwKb9E.d.ts +70 -0
  57. package/dist/runtime.d.ts +1860 -0
  58. package/dist/runtime.js +114 -0
  59. package/dist/runtime.js.map +1 -0
  60. package/dist/substrate-CUgk7F7s.d.ts +77 -0
  61. package/dist/topology.d.ts +73 -0
  62. package/dist/topology.js +111 -0
  63. package/dist/topology.js.map +1 -0
  64. package/dist/types-1HbsFa7H.d.ts +438 -0
  65. package/dist/{types-p8dWBIXL.d.ts → types-BtRLF2U3.d.ts} +1 -1
  66. package/dist/{types-Bcp071Jg.d.ts → types-DdzkffAm.d.ts} +95 -1
  67. package/dist/workflow.d.ts +551 -0
  68. package/dist/workflow.js +1778 -0
  69. package/dist/workflow.js.map +1 -0
  70. package/package.json +53 -16
  71. package/skills/agent-runtime-adoption/SKILL.md +29 -26
  72. package/dist/chunk-3HMHSN22.js.map +0 -1
  73. package/dist/chunk-C5HMTTNY.js.map +0 -1
  74. package/dist/chunk-EKBSQYZE.js +0 -813
  75. package/dist/chunk-EKBSQYZE.js.map +0 -1
  76. package/dist/chunk-HVYOHJHK.js.map +0 -1
  77. package/dist/chunk-MJDGCRAT.js.map +0 -1
  78. package/dist/chunk-MNCB4SJ5.js.map +0 -1
  79. package/dist/chunk-PY6NMZYX.js +0 -52
  80. package/dist/chunk-PY6NMZYX.js.map +0 -1
  81. package/dist/chunk-SQSCRJ7U.js +0 -65
  82. package/dist/chunk-SQSCRJ7U.js.map +0 -1
  83. package/dist/chunk-VOX6Z3II.js +0 -90
  84. package/dist/chunk-VOX6Z3II.js.map +0 -1
  85. package/dist/chunk-XBUG326M.js +0 -261
  86. package/dist/chunk-XBUG326M.js.map +0 -1
  87. package/dist/dynamic-B_7GgCwu.d.ts +0 -108
  88. package/dist/optimize-prompt-D-urF2wW.d.ts +0 -129
  89. /package/dist/{chunk-NRZOXCJK.js.map → chunk-KSMX62JF.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/mcp/worktree.ts","../src/mcp/in-process-executor.ts","../src/mcp/bin-helpers.ts","../src/mcp/server.ts","../src/mcp/trace-propagation.ts"],"sourcesContent":["/**\n * @experimental\n *\n * Git worktree helpers for the in-process delegation executor. Each\n * delegation runs in its own worktree so multiple parallel harness\n * subprocesses (claude / codex / opencode in a 3-way fanout) don't clobber\n * each other's edits on the shared workspace.\n *\n * Worktrees live under `<repoRoot>/.coder-variants/<runId>/`. After the\n * harness exits + the diff is captured, the worktree is removed.\n *\n * All operations spawn `git` via `child_process.spawn` synchronously\n * (via a `runGit` helper). Stays narrow on purpose: no working-tree\n * staging, no commits, no rebases.\n */\n\nimport { spawn } from 'node:child_process'\n\n/** @experimental */\nexport interface WorktreeHandle {\n /** Absolute path to the worktree directory. */\n path: string\n /** SHA the worktree was created at. */\n baseSha: string\n /** Branch name created for this worktree (typically `delegate/<runId>`). */\n branch: string\n}\n\n/** @experimental */\nexport interface CreateWorktreeOptions {\n /** Absolute path to the main git checkout. */\n repoRoot: string\n /** Unique id for the worktree path + branch. Use the delegation run id. */\n runId: string\n /** Parent directory the worktree lives under. Defaults to `.coder-variants`. */\n variantsDir?: string\n /** Override the base ref (default `HEAD`). */\n baseRef?: string\n /** Test seam — inject a custom git runner. */\n runGit?: GitRunner\n}\n\n/** @experimental */\nexport interface DiffOptions {\n /** Worktree to diff. */\n worktree: WorktreeHandle\n /** What to compare against. Default `worktree.baseSha`. */\n baseRef?: string\n /** Test seam. */\n runGit?: GitRunner\n}\n\n/** @experimental */\nexport interface DiffResult {\n patch: string\n stats: {\n filesChanged: number\n insertions: number\n deletions: number\n }\n}\n\n/** @experimental */\nexport interface RemoveWorktreeOptions {\n worktree: WorktreeHandle\n repoRoot: string\n /** Force removal even if dirty (default true; the loser of a fanout has uncommitted changes). */\n force?: boolean\n /** Test seam. */\n runGit?: GitRunner\n}\n\n/** Pluggable git runner (sync) — replaceable in tests. */\nexport type GitRunner = (\n args: ReadonlyArray<string>,\n opts: { cwd: string },\n) => { stdout: string; stderr: string; exitCode: number }\n\nasync function runGitAsync(\n args: ReadonlyArray<string>,\n cwd: string,\n runner?: GitRunner,\n): Promise<{ stdout: string; stderr: string; exitCode: number }> {\n if (runner) return runner(args, { cwd })\n return new Promise((resolve, reject) => {\n const proc = spawn('git', args, { cwd, stdio: 'pipe' })\n let stdout = ''\n let stderr = ''\n proc.stdout?.on('data', (c) => {\n stdout += String(c)\n })\n proc.stderr?.on('data', (c) => {\n stderr += String(c)\n })\n proc.on('error', reject)\n proc.on('close', (code) => resolve({ stdout, stderr, exitCode: code ?? -1 }))\n })\n}\n\nfunction ensureGitOk(\n step: string,\n result: { stdout: string; stderr: string; exitCode: number },\n): void {\n if (result.exitCode !== 0) {\n throw new Error(\n `worktree: git ${step} failed (exit ${result.exitCode}): ${result.stderr.slice(0, 400)}`,\n )\n }\n}\n\n/** @experimental */\nexport async function createWorktree(options: CreateWorktreeOptions): Promise<WorktreeHandle> {\n const variants = options.variantsDir ?? '.coder-variants'\n const baseRef = options.baseRef ?? 'HEAD'\n const branch = `delegate/${options.runId}`\n const path = `${options.repoRoot.replace(/\\/+$/, '')}/${variants}/${options.runId}`\n\n const headSha = await runGitAsync(['rev-parse', baseRef], options.repoRoot, options.runGit)\n ensureGitOk(`rev-parse ${baseRef}`, headSha)\n\n const add = await runGitAsync(\n ['worktree', 'add', '-b', branch, path, baseRef],\n options.repoRoot,\n options.runGit,\n )\n ensureGitOk(`worktree add ${path}`, add)\n\n return { path, baseSha: headSha.stdout.trim(), branch }\n}\n\n/** @experimental */\nexport async function captureWorktreeDiff(options: DiffOptions): Promise<DiffResult> {\n const baseRef = options.baseRef ?? options.worktree.baseSha\n const patch = await runGitAsync(['diff', baseRef], options.worktree.path, options.runGit)\n // No `ensureGitOk` here — diff returns 0 even when there are no changes.\n\n // Stats: `git diff --shortstat` produces e.g. \" 3 files changed, 42 insertions(+), 10 deletions(-)\".\n const shortstat = await runGitAsync(\n ['diff', '--shortstat', baseRef],\n options.worktree.path,\n options.runGit,\n )\n const stats = parseShortstat(shortstat.stdout)\n return { patch: patch.stdout, stats }\n}\n\nfunction parseShortstat(text: string): DiffResult['stats'] {\n // `text` is the raw stdout of `git diff --shortstat`. Empty when no\n // changes. Parse defensively — the format is stable but we don't trust\n // it for type-safety.\n const out = { filesChanged: 0, insertions: 0, deletions: 0 }\n const filesMatch = text.match(/(\\d+)\\s+files?\\s+changed/)\n if (filesMatch?.[1]) out.filesChanged = Number(filesMatch[1])\n const insertMatch = text.match(/(\\d+)\\s+insertions?/)\n if (insertMatch?.[1]) out.insertions = Number(insertMatch[1])\n const deleteMatch = text.match(/(\\d+)\\s+deletions?/)\n if (deleteMatch?.[1]) out.deletions = Number(deleteMatch[1])\n return out\n}\n\n/** @experimental */\nexport async function removeWorktree(options: RemoveWorktreeOptions): Promise<void> {\n const force = options.force ?? true\n const args = ['worktree', 'remove']\n if (force) args.push('--force')\n args.push(options.worktree.path)\n const result = await runGitAsync(args, options.repoRoot, options.runGit)\n // Don't ensureGitOk — partial-removal scenarios are tolerable; the\n // worktree dir may already be gone (caller deleted it manually).\n if (result.exitCode !== 0 && !/not a working tree/.test(result.stderr)) {\n // Best-effort branch cleanup so the next run can reuse the runId.\n await runGitAsync(\n ['branch', '-D', options.worktree.branch],\n options.repoRoot,\n options.runGit,\n ).catch(() => undefined)\n }\n // Always attempt branch removal — the worktree-remove sometimes leaves\n // the branch behind even when the directory is gone.\n await runGitAsync(\n ['branch', '-D', options.worktree.branch],\n options.repoRoot,\n options.runGit,\n ).catch(() => undefined)\n}\n","/**\n * @experimental\n *\n * In-process delegation executor — when `agent-runtime-mcp` is running\n * inside a sandbox whose image carries the local coding-harness CLIs\n * (claude / codex / opencode), delegations spawn the harness AS A\n * SUBPROCESS against a git worktree on the SAME filesystem instead of\n * provisioning a sibling sandbox.\n *\n * Why: zero provisioning latency, worker diffs land in-place, multi-harness\n * fanout = N parallel subprocesses in N parallel worktrees.\n *\n * Selection:\n * - env `AGENT_RUNTIME_IN_SANDBOX=1` (set by the parent harness at MCP\n * server launch) → in-process executor\n * - env `TANGLE_FLEET_ID=...` → fleet executor (Phase 2.5)\n * - neither → sibling sandbox executor (default)\n *\n * Multi-harness rotation: pass `harnesses: ['claude', 'codex', 'opencode']`\n * to round-robin across calls. A `runLoop` + `FanoutVote(n: 3)` against this\n * executor produces three parallel iterations, each running a different\n * harness on its own worktree.\n *\n * Architecture:\n *\n * client.create() → returns a fake SandboxInstance whose streamPrompt:\n * 1. createWorktree() — git worktree add /workspace/.coder-variants/<id>\n * 2. runLocalHarness() — spawn claude/codex/opencode subprocess\n * 3. captureWorktreeDiff() — git diff HEAD → patch + stats\n * 4. run testCmd + typecheckCmd if specified (the executor doesn't\n * own these — caller wires via task-extractor callback)\n * 5. emit ONE SandboxEvent { type: 'result', data: { result: CoderOutput } }\n * 6. removeWorktree() in finally\n */\n\nimport { randomUUID } from 'node:crypto'\nimport type { CreateSandboxOptions, SandboxEvent, SandboxInstance } from '@tangle-network/sandbox'\nimport type { LoopSandboxClient, LoopSandboxPlacement } from '../loops'\nimport type { DelegationExecutor } from './executor'\nimport { type LocalHarness, runLocalHarness } from './local-harness'\nimport {\n captureWorktreeDiff,\n createWorktree,\n type GitRunner,\n removeWorktree,\n type WorktreeHandle,\n} from './worktree'\n\n/** @experimental */\nexport interface InProcessExecutorOptions {\n /**\n * Absolute path to the git repo (the workspace inside the sandbox). The\n * executor creates worktrees under `<repoRoot>/.coder-variants/`.\n */\n repoRoot: string\n /**\n * Harnesses to round-robin across calls. With one entry every delegation\n * uses that harness; with three you get fanout diversity for free.\n * Default `['claude']`.\n */\n harnesses?: ReadonlyArray<LocalHarness>\n /**\n * Optional per-delegation test command. Run with `cwd = worktree.path`\n * after the harness exits. The exit code populates\n * `CoderOutput.testResult.passed`.\n */\n testCmd?: string\n /**\n * Optional per-delegation typecheck command. Same shape as `testCmd`.\n */\n typecheckCmd?: string\n /** Wall-clock cap per harness subprocess (ms). Default 5min. */\n harnessTimeoutMs?: number\n /** Wall-clock cap per test/typecheck subprocess (ms). Default 2min. */\n postCheckTimeoutMs?: number\n /** Test seam — override the git runner used by the worktree helpers. */\n runGit?: GitRunner\n /**\n * Test seam — override the harness runner. Defaults to spawning the real\n * CLI via `runLocalHarness`. Tests inject a stub that returns a scripted\n * `LocalHarnessResult`.\n */\n runHarness?: typeof runLocalHarness\n /**\n * Test seam — override the post-check runner. Defaults to spawning the\n * configured `testCmd` / `typecheckCmd` via `child_process.spawn`.\n */\n runPostCheck?: (\n cmd: string,\n cwd: string,\n signal?: AbortSignal,\n ) => Promise<{ exitCode: number; stdout: string; stderr: string }>\n}\n\n/** @experimental */\nexport interface InProcessExecutorDescribePlacement extends LoopSandboxPlacement {\n /**\n * Worktree path in the parent sandbox's filesystem. Set so trace\n * consumers can correlate dispatch events with on-disk artifacts after\n * the worker exits.\n */\n worktreePath?: string\n /** Which harness handled this delegation. */\n harness?: LocalHarness\n}\n\ninterface VirtualSandbox extends SandboxInstance {\n __inProcess: {\n runId: string\n harness: LocalHarness\n worktree?: WorktreeHandle\n }\n}\n\nconst DEFAULT_HARNESS_TIMEOUT_MS = 5 * 60 * 1000\nconst DEFAULT_POSTCHECK_TIMEOUT_MS = 2 * 60 * 1000\n\n/**\n * Build an in-process executor.\n *\n * Returns a {@link DelegationExecutor} whose `client.create()` returns a\n * minimal \"virtual\" SandboxInstance — the kernel calls `streamPrompt(msg)`\n * on it, which runs the local harness on a worktree and emits one\n * `result` event whose `data.result` is a `CoderOutput`-shaped record.\n *\n * Pairs with `coderProfile`'s event parser (it walks the event list\n * back-to-front for the first `type === 'result'`).\n *\n * @experimental\n */\nexport function createInProcessExecutor(options: InProcessExecutorOptions): DelegationExecutor {\n const harnesses =\n options.harnesses && options.harnesses.length > 0\n ? [...options.harnesses]\n : (['claude'] as const)\n const runHarness = options.runHarness ?? runLocalHarness\n const runPostCheck = options.runPostCheck ?? defaultRunPostCheck\n\n let callIndex = 0\n\n const client: LoopSandboxClient = {\n async create(_opts?: CreateSandboxOptions): Promise<SandboxInstance> {\n const runId = randomUUID()\n const harness = harnesses[callIndex % harnesses.length] as LocalHarness\n callIndex += 1\n\n const virtual: VirtualSandbox = {\n // Synthesize the minimum SandboxInstance surface the kernel touches.\n // We CAST through unknown because SandboxInstance is a `declare class`\n // with private fields; we're producing a structural subtype that\n // satisfies the kernel's narrow usage (`box.id`, `box.streamPrompt`).\n id: `in-process-${runId}`,\n __inProcess: { runId, harness },\n // eslint-disable-next-line require-yield\n async *streamPrompt(\n this: VirtualSandbox,\n message: string | unknown[],\n promptOpts?: { signal?: AbortSignal },\n ): AsyncGenerator<SandboxEvent> {\n const taskPrompt =\n typeof message === 'string'\n ? message\n : message\n .map((p) =>\n typeof p === 'object' && p && 'text' in p\n ? String((p as { text: unknown }).text)\n : '',\n )\n .join('\\n')\n\n let worktree: WorktreeHandle | undefined\n try {\n worktree = await createWorktree({\n repoRoot: options.repoRoot,\n runId,\n runGit: options.runGit,\n })\n this.__inProcess.worktree = worktree\n\n // Yield a dispatch-equivalent event so traces see the placement.\n yield {\n type: 'in_process.harness.started',\n data: {\n runId,\n harness,\n worktreePath: worktree.path,\n command: harness,\n },\n }\n\n const harnessResult = await runHarness({\n harness,\n cwd: worktree.path,\n taskPrompt,\n timeoutMs: options.harnessTimeoutMs ?? DEFAULT_HARNESS_TIMEOUT_MS,\n signal: promptOpts?.signal,\n })\n\n yield {\n type: 'in_process.harness.ended',\n data: {\n runId,\n exitCode: harnessResult.exitCode,\n durationMs: harnessResult.durationMs,\n killedBySignal: harnessResult.killedBySignal,\n timedOut: harnessResult.timedOut,\n stdoutBytes: harnessResult.stdout.length,\n stderrBytes: harnessResult.stderr.length,\n },\n }\n\n // Capture diff regardless of exit code — a failed run can still\n // leave a partial diff worth inspecting.\n const diff = await captureWorktreeDiff({ worktree, runGit: options.runGit })\n\n // Optional post-checks. Each runs in the WORKTREE so it sees the\n // harness's edits.\n const testCheck = options.testCmd\n ? await runPostCheck(options.testCmd, worktree.path, promptOpts?.signal).catch(\n (err) => ({\n exitCode: -1,\n stdout: '',\n stderr: err instanceof Error ? err.message : String(err),\n }),\n )\n : { exitCode: 0, stdout: '', stderr: '' }\n const typecheckCheck = options.typecheckCmd\n ? await runPostCheck(options.typecheckCmd, worktree.path, promptOpts?.signal).catch(\n (err) => ({\n exitCode: -1,\n stdout: '',\n stderr: err instanceof Error ? err.message : String(err),\n }),\n )\n : { exitCode: 0, stdout: '', stderr: '' }\n\n const coderOutput = {\n branch: worktree.branch,\n patch: diff.patch,\n testResult: {\n passed: !options.testCmd || testCheck.exitCode === 0,\n output: tail(testCheck.stderr || testCheck.stdout, 4000),\n },\n typecheckResult: {\n passed: !options.typecheckCmd || typecheckCheck.exitCode === 0,\n output: tail(typecheckCheck.stderr || typecheckCheck.stdout, 4000),\n },\n diffStats: diff.stats,\n reviewerNotes:\n harnessResult.exitCode === 0\n ? undefined\n : `harness ${harness} exited ${harnessResult.exitCode}${harnessResult.timedOut ? ' (timed out)' : ''}`,\n }\n\n // The terminal event the coderProfile parser looks for.\n yield {\n type: 'result',\n data: {\n result: coderOutput,\n source: 'in-process-executor',\n harness,\n runId,\n },\n }\n } finally {\n if (worktree) {\n await removeWorktree({\n worktree,\n repoRoot: options.repoRoot,\n runGit: options.runGit,\n }).catch(() => undefined)\n }\n }\n },\n } as unknown as VirtualSandbox\n\n return virtual\n },\n describePlacement(box: SandboxInstance): InProcessExecutorDescribePlacement {\n const sandboxId = (box as unknown as { id?: string }).id\n const meta = (box as VirtualSandbox).__inProcess\n return {\n kind: 'sibling',\n sandboxId,\n worktreePath: meta?.worktree?.path,\n harness: meta?.harness,\n }\n },\n }\n\n return {\n client,\n describe(): string {\n return `in-process (repoRoot=${options.repoRoot}, harnesses=[${harnesses.join(',')}]${\n options.testCmd ? `, testCmd=\"${options.testCmd}\"` : ''\n }${options.typecheckCmd ? `, typecheckCmd=\"${options.typecheckCmd}\"` : ''})`\n },\n }\n}\n\nasync function defaultRunPostCheck(\n cmd: string,\n cwd: string,\n signal?: AbortSignal,\n): Promise<{ exitCode: number; stdout: string; stderr: string }> {\n const { spawn } = await import('node:child_process')\n return new Promise((resolve, reject) => {\n // Run via sh -c so multi-word commands (\"pnpm test\") and shell features work.\n const child = spawn('sh', ['-c', cmd], { cwd, stdio: 'pipe' })\n let stdout = ''\n let stderr = ''\n child.stdout?.on('data', (c) => {\n stdout += String(c)\n })\n child.stderr?.on('data', (c) => {\n stderr += String(c)\n })\n if (signal) {\n const onAbort = () => {\n if (!child.killed) child.kill('SIGTERM')\n }\n if (signal.aborted) onAbort()\n else signal.addEventListener('abort', onAbort, { once: true })\n }\n const killTimer = setTimeout(() => {\n if (!child.killed) child.kill('SIGTERM')\n }, DEFAULT_POSTCHECK_TIMEOUT_MS)\n if (typeof (killTimer as { unref?: () => void }).unref === 'function') {\n ;(killTimer as { unref: () => void }).unref()\n }\n child.on('error', (err) => {\n clearTimeout(killTimer)\n reject(err)\n })\n child.on('close', (code) => {\n clearTimeout(killTimer)\n resolve({ exitCode: code ?? -1, stdout, stderr })\n })\n })\n}\n\nfunction tail(text: string, max: number): string {\n if (text.length <= max) return text\n return text.slice(text.length - max)\n}\n","/**\n * @experimental\n *\n * Helpers extracted from `bin.ts` so the env-detection + executor-selection\n * logic is unit-testable without spawning a subprocess. The bin imports from\n * here; tests import from here directly.\n */\n\nimport type { LoopSandboxClient } from '../loops'\nimport {\n createFleetWorkspaceExecutor,\n createSiblingSandboxExecutor,\n type DelegationExecutor,\n type FleetHandle,\n} from './executor'\nimport { createInProcessExecutor } from './in-process-executor'\nimport type { LocalHarness } from './local-harness'\n\n/** @experimental */\nexport interface DetectExecutorArgs {\n sandboxClient: LoopSandboxClient\n /** Raw env (defaults to `process.env`). Pass an explicit map for tests. */\n env?: Record<string, string | undefined>\n /**\n * Override how a fleet handle is resolved from the client + fleet id. The\n * default reads `client.fleets.get(fleetId)` and validates the returned\n * shape against the structural `FleetHandle` contract.\n */\n resolveFleet?: (client: LoopSandboxClient, fleetId: string) => Promise<FleetHandle>\n}\n\n/**\n * Pick the right executor for an MCP server invocation based on env vars.\n *\n * - `TANGLE_FLEET_ID` set → fleet-workspace placement; resolves the handle\n * via `sandboxClient.fleets.get(...)`.\n * - Otherwise → sibling-sandbox placement; each delegation creates a fresh\n * sandbox via `sandboxClient.create(...)`.\n *\n * Fails loud (throws) when fleet mode is requested but the SDK shape is\n * incompatible — the operator chose fleet semantics, silently degrading to\n * sibling mode would lie about workspace topology.\n *\n * @experimental\n */\nexport async function detectExecutor(args: DetectExecutorArgs): Promise<DelegationExecutor> {\n const env = args.env ?? process.env\n\n // In-process (Phase 2.8): parent harness sets AGENT_RUNTIME_IN_SANDBOX=1\n // and points us at the workspace root. Highest-priority — when this is\n // set, delegations spawn local harness CLIs on git worktrees in the\n // SAME filesystem instead of provisioning sibling sandboxes.\n if (env.AGENT_RUNTIME_IN_SANDBOX === '1') {\n const repoRoot = env.AGENT_RUNTIME_REPO_ROOT?.trim()\n if (!repoRoot) {\n throw new Error(\n 'agent-runtime-mcp: AGENT_RUNTIME_IN_SANDBOX=1 requires AGENT_RUNTIME_REPO_ROOT to point at the workspace root',\n )\n }\n return createInProcessExecutor({\n repoRoot,\n harnesses: parseHarnesses(env.AGENT_RUNTIME_LOCAL_HARNESSES),\n testCmd: env.AGENT_RUNTIME_TEST_CMD?.trim() || undefined,\n typecheckCmd: env.AGENT_RUNTIME_TYPECHECK_CMD?.trim() || undefined,\n })\n }\n\n const fleetId = parseFleetId(env.TANGLE_FLEET_ID)\n if (!fleetId) {\n return createSiblingSandboxExecutor({ client: args.sandboxClient })\n }\n const resolveFleet = args.resolveFleet ?? defaultResolveFleet\n const fleet = await resolveFleet(args.sandboxClient, fleetId)\n const excludeMachineIds = parseList(env.TANGLE_FLEET_EXCLUDE_MACHINES)\n return createFleetWorkspaceExecutor({\n fleet,\n excludeMachineIds,\n })\n}\n\nconst KNOWN_HARNESSES: ReadonlyArray<LocalHarness> = ['claude', 'codex', 'opencode']\n\nfunction parseHarnesses(raw: string | undefined): ReadonlyArray<LocalHarness> | undefined {\n if (!raw) return undefined\n const parts = raw\n .split(',')\n .map((s) => s.trim())\n .filter(Boolean)\n if (parts.length === 0) return undefined\n for (const part of parts) {\n if (!KNOWN_HARNESSES.includes(part as LocalHarness)) {\n throw new Error(\n `agent-runtime-mcp: AGENT_RUNTIME_LOCAL_HARNESSES contains unknown harness \"${part}\". Expected: ${KNOWN_HARNESSES.join(', ')}.`,\n )\n }\n }\n return parts as LocalHarness[]\n}\n\ninterface FleetsApi {\n get(fleetId: string): Promise<unknown>\n}\n\nasync function defaultResolveFleet(\n sandboxClient: LoopSandboxClient,\n fleetId: string,\n): Promise<FleetHandle> {\n const fleets = (sandboxClient as unknown as { fleets?: FleetsApi }).fleets\n if (!fleets || typeof fleets.get !== 'function') {\n throw new Error(\n 'agent-runtime-mcp: the configured sandbox client does not expose `.fleets.get`; upgrade @tangle-network/sandbox to >= 0.2.1 or unset TANGLE_FLEET_ID.',\n )\n }\n const raw = await fleets.get(fleetId)\n if (!raw || typeof raw !== 'object') {\n throw new Error(`agent-runtime-mcp: fleets.get(${fleetId}) returned no handle`)\n }\n const handle = raw as Partial<FleetHandle>\n if (typeof handle.fleetId !== 'string' || !Array.isArray(handle.ids)) {\n throw new Error(\n `agent-runtime-mcp: fleet handle for ${fleetId} is missing fleetId/ids — incompatible sandbox SDK shape`,\n )\n }\n if (typeof handle.sandbox !== 'function') {\n throw new Error(\n `agent-runtime-mcp: fleet handle for ${fleetId} is missing sandbox(machineId) — incompatible sandbox SDK shape`,\n )\n }\n return handle as FleetHandle\n}\n\nfunction parseFleetId(raw: string | undefined): string | undefined {\n if (typeof raw !== 'string') return undefined\n const trimmed = raw.trim()\n return trimmed.length > 0 ? trimmed : undefined\n}\n\nfunction parseList(raw: string | undefined): string[] | undefined {\n if (!raw) return undefined\n const list = raw\n .split(',')\n .map((entry) => entry.trim())\n .filter(Boolean)\n return list.length > 0 ? list : undefined\n}\n","/**\n * @experimental\n *\n * Stdio JSON-RPC MCP server exposing the 5 delegation tools to sandbox\n * coding-harness agents (claude-code, codex, opencode, ...).\n *\n * The server is transport-bound but topology-free: tool execution is\n * delegated to handler functions composed from a queue, a feedback\n * store, and per-profile run delegates. Consumers wire those at\n * construction time. The `agent-runtime-mcp` bin spins up a default\n * configuration for the common case (real sandbox client + coder).\n *\n * Wire protocol: line-delimited JSON-RPC 2.0 over stdio. Each line is\n * one request; each response is one line. `tools/list` and `tools/call`\n * mirror the MCP 2024-11-05 spec; we do not pull in\n * `@modelcontextprotocol/sdk` to keep the dependency footprint zero.\n */\n\nimport { createInterface, type Interface as ReadlineInterface } from 'node:readline'\nimport { Readable, Writable } from 'node:stream'\nimport type { CoderDelegate, ResearcherDelegate } from './delegates'\nimport { type FeedbackStore, InMemoryFeedbackStore } from './feedback-store'\nimport { DelegationTaskQueue } from './task-queue'\nimport {\n createDelegateCodeHandler,\n DELEGATE_CODE_DESCRIPTION,\n DELEGATE_CODE_INPUT_SCHEMA,\n DELEGATE_CODE_TOOL_NAME,\n} from './tools/delegate-code'\nimport {\n createDelegateFeedbackHandler,\n DELEGATE_FEEDBACK_DESCRIPTION,\n DELEGATE_FEEDBACK_INPUT_SCHEMA,\n DELEGATE_FEEDBACK_TOOL_NAME,\n} from './tools/delegate-feedback'\nimport {\n createDelegateResearchHandler,\n DELEGATE_RESEARCH_DESCRIPTION,\n DELEGATE_RESEARCH_INPUT_SCHEMA,\n DELEGATE_RESEARCH_TOOL_NAME,\n} from './tools/delegate-research'\nimport {\n createDelegationHistoryHandler,\n DELEGATION_HISTORY_DESCRIPTION,\n DELEGATION_HISTORY_INPUT_SCHEMA,\n DELEGATION_HISTORY_TOOL_NAME,\n} from './tools/delegation-history'\nimport {\n createDelegationStatusHandler,\n DELEGATION_STATUS_DESCRIPTION,\n DELEGATION_STATUS_INPUT_SCHEMA,\n DELEGATION_STATUS_TOOL_NAME,\n} from './tools/delegation-status'\n\n/** @experimental */\nexport interface McpServerOptions {\n /** Required to enable delegate_code. */\n coderDelegate?: CoderDelegate\n /**\n * Required to enable delegate_research. The substrate cannot ship a\n * default — wire one that closes over your `runLoop` + a\n * researcher profile (typically `@tangle-network/agent-knowledge`'s\n * `researcherProfile` / `multiHarnessResearcherFanout`).\n */\n researcherDelegate?: ResearcherDelegate\n /** Override the default in-memory feedback store. */\n feedbackStore?: FeedbackStore\n /** Override the default in-memory task queue. */\n queue?: DelegationTaskQueue\n /** Server display name surfaced via `initialize`. Default `'agent-runtime-mcp'`. */\n serverName?: string\n /** Server version surfaced via `initialize`. Default = the package version baked at build time. */\n serverVersion?: string\n}\n\n/** @experimental */\nexport interface McpToolDescriptor {\n name: string\n description: string\n inputSchema: Record<string, unknown>\n handler: (raw: unknown) => Promise<unknown>\n}\n\n/** @experimental */\nexport interface McpServer {\n /** Tools currently registered (depend on which delegates were wired). */\n readonly tools: ReadonlyMap<string, McpToolDescriptor>\n /** The underlying queue — exposed so tests can introspect it. */\n readonly queue: DelegationTaskQueue\n /** The feedback store — exposed for the same reason. */\n readonly feedbackStore: FeedbackStore\n /** Handle a single parsed JSON-RPC message. Returns the response object (or `null` for notifications). */\n handle(message: JsonRpcMessage): Promise<JsonRpcResponse | null>\n /** Drive the server on a stdio-shaped transport until `stop()` is called. */\n serve(transport?: McpTransport): Promise<void>\n /** Stop a `serve` call. Subsequent requests are rejected. */\n stop(): void\n}\n\n/** @experimental */\nexport interface McpTransport {\n input: NodeJS.ReadableStream\n output: NodeJS.WritableStream\n}\n\n/** @experimental */\nexport interface JsonRpcMessage {\n jsonrpc: '2.0'\n id?: number | string | null\n method: string\n params?: unknown\n}\n\n/** @experimental */\nexport interface JsonRpcResponse {\n jsonrpc: '2.0'\n id: number | string | null\n result?: unknown\n error?: { code: number; message: string; data?: unknown }\n}\n\nconst PROTOCOL_VERSION = '2024-11-05'\nconst DEFAULT_SERVER_NAME = 'agent-runtime-mcp'\nconst DEFAULT_SERVER_VERSION = '0.22.0'\n\n/** @experimental */\nexport function createMcpServer(options: McpServerOptions = {}): McpServer {\n const queue = options.queue ?? new DelegationTaskQueue()\n const feedbackStore = options.feedbackStore ?? new InMemoryFeedbackStore()\n const serverName = options.serverName ?? DEFAULT_SERVER_NAME\n const serverVersion = options.serverVersion ?? DEFAULT_SERVER_VERSION\n\n const tools = new Map<string, McpToolDescriptor>()\n\n if (options.coderDelegate) {\n tools.set(DELEGATE_CODE_TOOL_NAME, {\n name: DELEGATE_CODE_TOOL_NAME,\n description: DELEGATE_CODE_DESCRIPTION,\n inputSchema: DELEGATE_CODE_INPUT_SCHEMA as unknown as Record<string, unknown>,\n handler: createDelegateCodeHandler({ queue, delegate: options.coderDelegate }),\n })\n }\n if (options.researcherDelegate) {\n tools.set(DELEGATE_RESEARCH_TOOL_NAME, {\n name: DELEGATE_RESEARCH_TOOL_NAME,\n description: DELEGATE_RESEARCH_DESCRIPTION,\n inputSchema: DELEGATE_RESEARCH_INPUT_SCHEMA as unknown as Record<string, unknown>,\n handler: createDelegateResearchHandler({ queue, delegate: options.researcherDelegate }),\n })\n }\n tools.set(DELEGATE_FEEDBACK_TOOL_NAME, {\n name: DELEGATE_FEEDBACK_TOOL_NAME,\n description: DELEGATE_FEEDBACK_DESCRIPTION,\n inputSchema: DELEGATE_FEEDBACK_INPUT_SCHEMA as unknown as Record<string, unknown>,\n handler: createDelegateFeedbackHandler({ queue, store: feedbackStore }),\n })\n tools.set(DELEGATION_STATUS_TOOL_NAME, {\n name: DELEGATION_STATUS_TOOL_NAME,\n description: DELEGATION_STATUS_DESCRIPTION,\n inputSchema: DELEGATION_STATUS_INPUT_SCHEMA as unknown as Record<string, unknown>,\n handler: createDelegationStatusHandler({ queue }),\n })\n tools.set(DELEGATION_HISTORY_TOOL_NAME, {\n name: DELEGATION_HISTORY_TOOL_NAME,\n description: DELEGATION_HISTORY_DESCRIPTION,\n inputSchema: DELEGATION_HISTORY_INPUT_SCHEMA as unknown as Record<string, unknown>,\n handler: createDelegationHistoryHandler({ queue }),\n })\n\n let stopped = false\n let activeReadline: ReadlineInterface | undefined\n\n async function handle(message: JsonRpcMessage): Promise<JsonRpcResponse | null> {\n if (stopped) {\n return rpcError(message.id ?? null, -32099, 'server stopped')\n }\n if (message.method === 'initialize') {\n return rpcResult(message.id ?? null, {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: { tools: {} },\n serverInfo: { name: serverName, version: serverVersion },\n })\n }\n if (message.method === 'notifications/initialized') {\n // MCP clients send this after the handshake; it has no id and expects\n // no response.\n return null\n }\n if (message.method === 'tools/list') {\n return rpcResult(message.id ?? null, {\n tools: [...tools.values()].map((tool) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n })),\n })\n }\n if (message.method === 'tools/call') {\n const params = (message.params ?? {}) as { name?: unknown; arguments?: unknown }\n const name = typeof params.name === 'string' ? params.name : ''\n const tool = tools.get(name)\n if (!tool) {\n return rpcError(message.id ?? null, -32601, `unknown tool: ${name}`)\n }\n try {\n const output = await tool.handler(params.arguments ?? {})\n return rpcResult(message.id ?? null, {\n content: [{ type: 'text', text: JSON.stringify(output) }],\n structuredContent: output,\n isError: false,\n })\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err)\n const code = err instanceof TypeError || err instanceof RangeError ? -32602 : -32000\n return rpcError(message.id ?? null, code, reason)\n }\n }\n if (message.id === undefined || message.id === null) return null\n return rpcError(message.id, -32601, `unknown method: ${message.method}`)\n }\n\n async function serve(transport?: McpTransport): Promise<void> {\n const input = transport?.input ?? process.stdin\n const output = transport?.output ?? process.stdout\n const rl = createInterface({ input, crlfDelay: Number.POSITIVE_INFINITY })\n activeReadline = rl\n return new Promise<void>((resolve, reject) => {\n rl.on('line', (line) => {\n const trimmed = line.trim()\n if (!trimmed) return\n let parsed: JsonRpcMessage | undefined\n try {\n parsed = JSON.parse(trimmed) as JsonRpcMessage\n } catch (err) {\n writeResponse(output, rpcError(null, -32700, `parse error: ${(err as Error).message}`))\n return\n }\n if (!parsed || parsed.jsonrpc !== '2.0' || typeof parsed.method !== 'string') {\n writeResponse(output, rpcError(parsed?.id ?? null, -32600, 'invalid request'))\n return\n }\n void handle(parsed).then((response) => {\n if (response) writeResponse(output, response)\n })\n })\n rl.on('close', () => resolve())\n rl.on('error', (err) => reject(err))\n if (stopped) {\n rl.close()\n resolve()\n }\n })\n }\n\n function stop(): void {\n stopped = true\n activeReadline?.close()\n activeReadline = undefined\n }\n\n return {\n tools,\n queue,\n feedbackStore,\n handle,\n serve,\n stop,\n }\n}\n\nfunction rpcResult(id: number | string | null, result: unknown): JsonRpcResponse {\n return { jsonrpc: '2.0', id, result }\n}\n\nfunction rpcError(\n id: number | string | null,\n code: number,\n message: string,\n data?: unknown,\n): JsonRpcResponse {\n return {\n jsonrpc: '2.0',\n id,\n error: data === undefined ? { code, message } : { code, message, data },\n }\n}\n\nfunction writeResponse(output: NodeJS.WritableStream, response: JsonRpcResponse): void {\n output.write(`${JSON.stringify(response)}\\n`)\n}\n\n/**\n * In-process pair of `Readable` + `Writable` streams suitable for driving\n * `server.serve(...)` from a test. Returns the agent-side stream (the\n * client writes to it) and the server-side stream (the test reads from it).\n *\n * @experimental\n */\nexport function createInProcessTransport(): {\n transport: McpTransport\n clientWrite(line: string): void\n clientClose(): void\n readServer(): Promise<JsonRpcResponse[]>\n} {\n const responses: JsonRpcResponse[] = []\n const input = new Readable({ read() {} })\n const output = new Writable({\n write(chunk, _enc, cb) {\n const text = chunk.toString('utf8')\n for (const line of text.split('\\n')) {\n const trimmed = line.trim()\n if (!trimmed) continue\n try {\n responses.push(JSON.parse(trimmed) as JsonRpcResponse)\n } catch {\n // Non-JSON output should never appear; drop it silently in the\n // test transport rather than crashing.\n }\n }\n cb()\n },\n })\n return {\n transport: { input, output },\n clientWrite(line: string) {\n input.push(`${line}\\n`)\n },\n clientClose() {\n input.push(null)\n },\n async readServer() {\n // Yield to the event loop a few times so async handlers drain.\n for (let i = 0; i < 5; i += 1) await new Promise((r) => setImmediate(r))\n return [...responses]\n },\n }\n}\n","/**\n * @experimental\n *\n * Trace context propagation for MCP subprocess.\n *\n * When the MCP server is launched as a child process by a sandbox harness,\n * the parent passes trace context via environment variables:\n *\n * TRACE_ID=<current-run-trace-id>\n * PARENT_SPAN_ID=<span-that-dispatched-the-delegation>\n *\n * The MCP server reads these at startup and uses them as the root of its\n * internal trace tree. All spans emitted by `runLoop` invocations inside\n * the MCP are children of the parent's delegation span.\n *\n * When these env vars are absent, the MCP generates a fresh trace root —\n * the server operates standalone without trace joining.\n */\n\nimport type { LoopTraceEmitter, LoopTraceEvent } from '../loops/types'\nimport type { OtelExporter } from '../otel-export'\nimport { buildLoopOtelSpans, createOtelExporter } from '../otel-export'\n\nexport interface TraceContext {\n /** Trace id inherited from the parent process, or a fresh one. */\n traceId: string\n /** Parent span id from the delegation that launched this MCP server. */\n parentSpanId?: string\n}\n\n/**\n * Read trace context from the process environment.\n * Returns a context with inherited ids or a freshly generated root.\n */\nexport function readTraceContextFromEnv(): TraceContext {\n const traceId = process.env.TRACE_ID || generateTraceId()\n const parentSpanId = process.env.PARENT_SPAN_ID || undefined\n return { traceId, parentSpanId }\n}\n\n/**\n * Create a LoopTraceEmitter that:\n * 1. Parents all spans under the inherited PARENT_SPAN_ID.\n * 2. Exports spans to OTEL when OTEL_EXPORTER_OTLP_ENDPOINT is set.\n *\n * Returns both the emitter and the optional exporter handle for shutdown.\n */\nexport function createPropagatingTraceEmitter(ctx: TraceContext): {\n emitter: LoopTraceEmitter\n exporter: OtelExporter | undefined\n context: TraceContext\n} {\n const exporter = createOtelExporter()\n\n // Buffer events per loop run, then emit the full nested span tree on\n // `loop.ended` so the topology hierarchy (loop → round → branch) reaches the\n // OTLP collector — not a flat list of zero-duration point spans. A run that\n // never reaches `loop.ended` (hard abort) drops its buffer; acceptable for\n // the short-lived MCP subprocess.\n const buffers = new Map<string, LoopTraceEvent[]>()\n\n const emitter: LoopTraceEmitter = {\n emit(event: LoopTraceEvent) {\n if (!exporter) return\n const buf = buffers.get(event.runId)\n if (buf) buf.push(event)\n else buffers.set(event.runId, [event])\n if (event.kind === 'loop.ended') {\n const events = buffers.get(event.runId) ?? [event]\n buffers.delete(event.runId)\n for (const span of buildLoopOtelSpans(events, ctx.traceId, ctx.parentSpanId)) {\n exporter.exportSpan(span)\n }\n }\n },\n }\n\n return { emitter, exporter, context: ctx }\n}\n\n/**\n * Build env vars to pass to a child MCP subprocess so it inherits the\n * current trace context.\n */\nexport function traceContextToEnv(ctx: TraceContext): Record<string, string> {\n const env: Record<string, string> = { TRACE_ID: ctx.traceId }\n if (ctx.parentSpanId) env.PARENT_SPAN_ID = ctx.parentSpanId\n return env\n}\n\nfunction generateTraceId(): string {\n const bytes = new Uint8Array(16)\n if (typeof globalThis.crypto?.getRandomValues === 'function') {\n globalThis.crypto.getRandomValues(bytes)\n } else {\n for (let i = 0; i < 16; i++) bytes[i] = Math.floor(Math.random() * 256)\n }\n return Array.from(bytes)\n .map((b) => b.toString(16).padStart(2, '0'))\n .join('')\n}\n"],"mappings":"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","names":["spawn"]}
@@ -1,52 +0,0 @@
1
- import {
2
- ValidationError
3
- } from "./chunk-SQSCRJ7U.js";
4
-
5
- // src/loops/drivers/fanout-vote.ts
6
- function createFanoutVoteDriver(options) {
7
- if (!Number.isFinite(options.n) || options.n < 1) {
8
- throw new ValidationError(`createFanoutVoteDriver: n must be >= 1, got ${options.n}`);
9
- }
10
- const selector = options.selector ?? defaultSelector;
11
- return {
12
- name: options.name ?? "fanout-vote",
13
- async plan(task, history) {
14
- if (history.length === 0) return Array.from({ length: options.n }, () => task);
15
- return [];
16
- },
17
- decide(history) {
18
- const scored = scoreIterations(history);
19
- return selector(scored) ? "pick-winner" : "fail";
20
- }
21
- };
22
- }
23
- function defaultSelector(scored) {
24
- const valid = scored.filter((entry) => entry.verdict?.valid === true);
25
- if (valid.length === 0) return void 0;
26
- return [...valid].sort(
27
- (a, b) => (b.verdict?.score ?? 0) - (a.verdict?.score ?? 0) || a.iterationIndex - b.iterationIndex
28
- )[0];
29
- }
30
- function scoreIterations(iterations) {
31
- const out = [];
32
- for (const iter of iterations) {
33
- if (iter.output === void 0 || iter.error) continue;
34
- out.push({
35
- task: iter.task,
36
- output: iter.output,
37
- verdict: iter.verdict,
38
- iterationIndex: iter.index,
39
- agentRunName: iter.agentRunName
40
- });
41
- }
42
- return out;
43
- }
44
- function scoreFanoutVoteIterations(iterations) {
45
- return scoreIterations(iterations);
46
- }
47
-
48
- export {
49
- createFanoutVoteDriver,
50
- scoreFanoutVoteIterations
51
- };
52
- //# sourceMappingURL=chunk-PY6NMZYX.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/loops/drivers/fanout-vote.ts"],"sourcesContent":["/**\n * @experimental\n *\n * FanoutVote driver — N parallel attempts in iteration 0, pick the highest-\n * scoring valid output. No second iteration: the topology is \"spawn N, score,\n * pick winner\". The kernel handles heterogeneous fanout via the\n * `agentRuns: AgentRunSpec[]` form on `runLoop`.\n */\n\nimport { ValidationError } from '../../errors'\nimport type { DefaultVerdict, Driver, Iteration } from '../types'\n\nexport type FanoutVoteDecision = 'pick-winner' | 'fail'\n\n/** @experimental */\nexport interface FanoutVoteScored<Task, Output> {\n task: Task\n output: Output\n verdict?: DefaultVerdict\n iterationIndex: number\n agentRunName: string\n}\n\n/** @experimental */\nexport interface CreateFanoutVoteDriverOptions<Task, Output> {\n /** Number of parallel attempts. Must be >= 1. */\n n: number\n /**\n * Pick the winner from the scored set. Default: highest `verdict.score`\n * among valid outputs (ties broken by smallest iteration index). When\n * no valid outputs exist, returns `undefined` and `decide()` resolves\n * to `'fail'`. The kernel still records winners structurally — this\n * selector only feeds `decide()`'s pass/fail signal.\n */\n selector?: (\n scored: FanoutVoteScored<Task, Output>[],\n ) => FanoutVoteScored<Task, Output> | undefined\n /** Stable identifier surfaced in trace events. Default `'fanout-vote'`. */\n name?: string\n}\n\n/** @experimental */\nexport function createFanoutVoteDriver<Task, Output>(\n options: CreateFanoutVoteDriverOptions<Task, Output>,\n): Driver<Task, Output, FanoutVoteDecision> {\n if (!Number.isFinite(options.n) || options.n < 1) {\n throw new ValidationError(`createFanoutVoteDriver: n must be >= 1, got ${options.n}`)\n }\n const selector = options.selector ?? defaultSelector\n return {\n name: options.name ?? 'fanout-vote',\n async plan(task, history) {\n if (history.length === 0) return Array.from({ length: options.n }, () => task)\n return []\n },\n decide(history) {\n const scored = scoreIterations(history)\n return selector(scored) ? 'pick-winner' : 'fail'\n },\n }\n}\n\nfunction defaultSelector<Task, Output>(\n scored: FanoutVoteScored<Task, Output>[],\n): FanoutVoteScored<Task, Output> | undefined {\n const valid = scored.filter((entry) => entry.verdict?.valid === true)\n if (valid.length === 0) return undefined\n return [...valid].sort(\n (a, b) =>\n (b.verdict?.score ?? 0) - (a.verdict?.score ?? 0) || a.iterationIndex - b.iterationIndex,\n )[0]\n}\n\nfunction scoreIterations<Task, Output>(\n iterations: ReadonlyArray<Iteration<Task, Output>>,\n): FanoutVoteScored<Task, Output>[] {\n const out: FanoutVoteScored<Task, Output>[] = []\n for (const iter of iterations) {\n if (iter.output === undefined || iter.error) continue\n out.push({\n task: iter.task,\n output: iter.output,\n verdict: iter.verdict,\n iterationIndex: iter.index,\n agentRunName: iter.agentRunName,\n })\n }\n return out\n}\n\n/**\n * Test helper: surface the per-iteration scored view a custom `selector`\n * would receive. Exposed so consumers writing a custom selector can test it\n * standalone without driving the full kernel.\n *\n * @experimental\n */\nexport function scoreFanoutVoteIterations<Task, Output>(\n iterations: ReadonlyArray<Iteration<Task, Output>>,\n): FanoutVoteScored<Task, Output>[] {\n return scoreIterations(iterations)\n}\n"],"mappings":";;;;;AA0CO,SAAS,uBACd,SAC0C;AAC1C,MAAI,CAAC,OAAO,SAAS,QAAQ,CAAC,KAAK,QAAQ,IAAI,GAAG;AAChD,UAAM,IAAI,gBAAgB,+CAA+C,QAAQ,CAAC,EAAE;AAAA,EACtF;AACA,QAAM,WAAW,QAAQ,YAAY;AACrC,SAAO;AAAA,IACL,MAAM,QAAQ,QAAQ;AAAA,IACtB,MAAM,KAAK,MAAM,SAAS;AACxB,UAAI,QAAQ,WAAW,EAAG,QAAO,MAAM,KAAK,EAAE,QAAQ,QAAQ,EAAE,GAAG,MAAM,IAAI;AAC7E,aAAO,CAAC;AAAA,IACV;AAAA,IACA,OAAO,SAAS;AACd,YAAM,SAAS,gBAAgB,OAAO;AACtC,aAAO,SAAS,MAAM,IAAI,gBAAgB;AAAA,IAC5C;AAAA,EACF;AACF;AAEA,SAAS,gBACP,QAC4C;AAC5C,QAAM,QAAQ,OAAO,OAAO,CAAC,UAAU,MAAM,SAAS,UAAU,IAAI;AACpE,MAAI,MAAM,WAAW,EAAG,QAAO;AAC/B,SAAO,CAAC,GAAG,KAAK,EAAE;AAAA,IAChB,CAAC,GAAG,OACD,EAAE,SAAS,SAAS,MAAM,EAAE,SAAS,SAAS,MAAM,EAAE,iBAAiB,EAAE;AAAA,EAC9E,EAAE,CAAC;AACL;AAEA,SAAS,gBACP,YACkC;AAClC,QAAM,MAAwC,CAAC;AAC/C,aAAW,QAAQ,YAAY;AAC7B,QAAI,KAAK,WAAW,UAAa,KAAK,MAAO;AAC7C,QAAI,KAAK;AAAA,MACP,MAAM,KAAK;AAAA,MACX,QAAQ,KAAK;AAAA,MACb,SAAS,KAAK;AAAA,MACd,gBAAgB,KAAK;AAAA,MACrB,cAAc,KAAK;AAAA,IACrB,CAAC;AAAA,EACH;AACA,SAAO;AACT;AASO,SAAS,0BACd,YACkC;AAClC,SAAO,gBAAgB,UAAU;AACnC;","names":[]}
@@ -1,65 +0,0 @@
1
- // src/errors.ts
2
- import { AgentEvalError } from "@tangle-network/agent-eval";
3
- import {
4
- AgentEvalError as AgentEvalError2,
5
- CaptureIntegrityError,
6
- ConfigError,
7
- JudgeError,
8
- NotFoundError,
9
- ReplayError,
10
- ValidationError,
11
- VerificationError
12
- } from "@tangle-network/agent-eval";
13
- var SessionMismatchError = class extends AgentEvalError {
14
- sessionBackend;
15
- requestedBackend;
16
- constructor(sessionBackend, requestedBackend, options) {
17
- super(
18
- "validation",
19
- `Cannot resume ${sessionBackend} session with ${requestedBackend} backend`,
20
- options
21
- );
22
- this.sessionBackend = sessionBackend;
23
- this.requestedBackend = requestedBackend;
24
- }
25
- };
26
- var BackendTransportError = class extends AgentEvalError {
27
- backend;
28
- status;
29
- /**
30
- * Truncated upstream response body (≤2 KiB) when available. Diagnostic
31
- * only — surfaces in `backend_error.error.body` and `final.error.body`
32
- * so operators can see "free_tier_limit", "invalid_api_key", etc. without
33
- * cracking the log line open.
34
- */
35
- body;
36
- constructor(backend, message, options) {
37
- super("config", message, options);
38
- this.backend = backend;
39
- this.status = options?.status;
40
- this.body = options?.body;
41
- }
42
- };
43
- var RuntimeRunStateError = class extends AgentEvalError {
44
- constructor(message, options) {
45
- super("validation", message, options);
46
- }
47
- };
48
- var PlannerError = class extends AgentEvalError {
49
- constructor(message, options) {
50
- super("validation", message, options);
51
- }
52
- };
53
-
54
- export {
55
- SessionMismatchError,
56
- BackendTransportError,
57
- RuntimeRunStateError,
58
- PlannerError,
59
- AgentEvalError2 as AgentEvalError,
60
- ConfigError,
61
- JudgeError,
62
- NotFoundError,
63
- ValidationError
64
- };
65
- //# sourceMappingURL=chunk-SQSCRJ7U.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/errors.ts"],"sourcesContent":["/**\n * @stable\n *\n * Error taxonomy for `@tangle-network/agent-runtime`.\n *\n * Public contract: every error this package throws as part of its consumer-\n * facing API either extends `AgentEvalError` (re-exported here for ergonomic\n * `instanceof` checks at the runtime boundary) or extends one of the\n * runtime-specific subclasses below.\n *\n * Internal invariant guards (`throw new Error('this should never happen')`)\n * remain plain `Error` — they are programmer-mistake assertions, not\n * consumer-catchable contract failures.\n *\n * Subclassing strategy: where a runtime-specific failure maps cleanly to an\n * agent-eval code (validation, config, not_found), we re-use the agent-eval\n * subclass. Runtime-only failure modes (session resume against the wrong\n * backend, backend transport errors) get fresh subclasses that still carry an\n * `AgentEvalErrorCode` so cross-package handlers can pattern-match without\n * importing the runtime.\n */\n\nimport { AgentEvalError } from '@tangle-network/agent-eval'\n\nexport {\n AgentEvalError,\n type AgentEvalErrorCode,\n CaptureIntegrityError,\n ConfigError,\n JudgeError,\n NotFoundError,\n ReplayError,\n ValidationError,\n VerificationError,\n} from '@tangle-network/agent-eval'\n\n/**\n * @stable\n *\n * Caller asked to resume a session against a backend whose `kind` does not\n * match the session's recorded backend. This is a routing bug — the same\n * session id was reused across two different backend implementations — and\n * is not retryable without picking the right backend.\n */\nexport class SessionMismatchError extends AgentEvalError {\n readonly sessionBackend: string\n readonly requestedBackend: string\n\n constructor(sessionBackend: string, requestedBackend: string, options?: { cause?: unknown }) {\n super(\n 'validation',\n `Cannot resume ${sessionBackend} session with ${requestedBackend} backend`,\n options,\n )\n this.sessionBackend = sessionBackend\n this.requestedBackend = requestedBackend\n }\n}\n\n/**\n * @stable\n *\n * A backend transport call (HTTP, gRPC, sidecar IPC) failed with a non-success\n * status. Distinct from `JudgeError` (which is structural / unrecoverable)\n * because backend failures are sometimes retryable and consumers may want to\n * branch on the upstream status code.\n */\nexport class BackendTransportError extends AgentEvalError {\n readonly backend: string\n readonly status?: number\n /**\n * Truncated upstream response body (≤2 KiB) when available. Diagnostic\n * only — surfaces in `backend_error.error.body` and `final.error.body`\n * so operators can see \"free_tier_limit\", \"invalid_api_key\", etc. without\n * cracking the log line open.\n */\n readonly body?: string\n\n constructor(\n backend: string,\n message: string,\n options?: { cause?: unknown; status?: number; body?: string },\n ) {\n super('config', message, options)\n this.backend = backend\n this.status = options?.status\n this.body = options?.body\n }\n}\n\n/**\n * @stable\n *\n * A runtime-run lifecycle method was called in an order the state machine does\n * not allow: `persist()` before `complete()`, `complete()` twice, etc.\n */\nexport class RuntimeRunStateError extends AgentEvalError {\n constructor(message: string, options?: { cause?: unknown }) {\n super('validation', message, options)\n }\n}\n\n/**\n * @stable\n *\n * The dynamic-loop planner returned an unusable topology move — the LLM emitted\n * no parseable envelope, an unknown `kind`, or a structurally-invalid move\n * (e.g. a fanout with zero tasks). This is a structural failure of the\n * agent-authored topology, not a config mistake: the planner ran but its output\n * cannot drive the kernel. Carries `validation` so cross-package handlers can\n * pattern-match without importing the runtime. Fail loud — never substitute a\n * default move, or the loop silently runs a topology nobody chose.\n */\nexport class PlannerError extends AgentEvalError {\n constructor(message: string, options?: { cause?: unknown }) {\n super('validation', message, options)\n }\n}\n"],"mappings":";AAsBA,SAAS,sBAAsB;AAE/B;AAAA,EACE,kBAAAA;AAAA,EAEA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAUA,IAAM,uBAAN,cAAmC,eAAe;AAAA,EAC9C;AAAA,EACA;AAAA,EAET,YAAY,gBAAwB,kBAA0B,SAA+B;AAC3F;AAAA,MACE;AAAA,MACA,iBAAiB,cAAc,iBAAiB,gBAAgB;AAAA,MAChE;AAAA,IACF;AACA,SAAK,iBAAiB;AACtB,SAAK,mBAAmB;AAAA,EAC1B;AACF;AAUO,IAAM,wBAAN,cAAoC,eAAe;AAAA,EAC/C;AAAA,EACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA;AAAA,EAET,YACE,SACA,SACA,SACA;AACA,UAAM,UAAU,SAAS,OAAO;AAChC,SAAK,UAAU;AACf,SAAK,SAAS,SAAS;AACvB,SAAK,OAAO,SAAS;AAAA,EACvB;AACF;AAQO,IAAM,uBAAN,cAAmC,eAAe;AAAA,EACvD,YAAY,SAAiB,SAA+B;AAC1D,UAAM,cAAc,SAAS,OAAO;AAAA,EACtC;AACF;AAaO,IAAM,eAAN,cAA2B,eAAe;AAAA,EAC/C,YAAY,SAAiB,SAA+B;AAC1D,UAAM,cAAc,SAAS,OAAO;AAAA,EACtC;AACF;","names":["AgentEvalError"]}
@@ -1,90 +0,0 @@
1
- import {
2
- ConfigError
3
- } from "./chunk-SQSCRJ7U.js";
4
-
5
- // src/improvement/optimize-prompt.ts
6
- import { gepaDriver, heldOutGate, runImprovementLoop } from "@tangle-network/agent-eval/campaign";
7
- async function optimizePrompt(opts) {
8
- if (!opts.driver && !opts.reflection) {
9
- throw new ConfigError(
10
- "optimizePrompt: pass `reflection` (builds the default gepaDriver) or a custom `driver`"
11
- );
12
- }
13
- if (opts.scenarios.length === 0) {
14
- throw new ConfigError("optimizePrompt: `scenarios` must be non-empty");
15
- }
16
- if (opts.holdoutScenarios.length === 0) {
17
- throw new ConfigError(
18
- "optimizePrompt: `holdoutScenarios` must be non-empty (the gate needs it)"
19
- );
20
- }
21
- const driver = opts.driver ?? gepaDriver({
22
- llm: opts.reflection.llm,
23
- model: opts.reflection.model,
24
- target: opts.reflection.target ?? "system prompt",
25
- mutationPrimitives: opts.reflection.mutationPrimitives,
26
- constraints: opts.reflection.preserveSections || opts.reflection.maxSentenceEdits !== void 0 ? {
27
- preserveSections: opts.reflection.preserveSections,
28
- maxSentenceEdits: opts.reflection.maxSentenceEdits
29
- } : void 0
30
- });
31
- const gate = opts.gate ?? heldOutGate({
32
- scenarios: opts.holdoutScenarios,
33
- ...opts.deltaThreshold !== void 0 ? { deltaThreshold: opts.deltaThreshold } : {}
34
- });
35
- const result = await runImprovementLoop({
36
- baselineSurface: opts.baselinePrompt,
37
- dispatchWithSurface: (surface, scenario, ctx) => {
38
- if (typeof surface !== "string") {
39
- throw new ConfigError(
40
- "optimizePrompt: received a CodeSurface \u2014 this entry point optimizes string prompts only"
41
- );
42
- }
43
- return opts.runWithPrompt(surface, scenario, ctx);
44
- },
45
- driver,
46
- populationSize: opts.populationSize ?? 4,
47
- maxGenerations: opts.maxGenerations ?? 3,
48
- ...opts.promoteTopK !== void 0 ? { promoteTopK: opts.promoteTopK } : {},
49
- scenarios: opts.scenarios,
50
- holdoutScenarios: opts.holdoutScenarios,
51
- judges: opts.judges,
52
- gate,
53
- autoOnPromote: opts.autoOnPromote ?? "none",
54
- ...opts.ghOwner !== void 0 ? { ghOwner: opts.ghOwner } : {},
55
- ...opts.ghRepo !== void 0 ? { ghRepo: opts.ghRepo } : {},
56
- runDir: opts.runDir,
57
- ...opts.storage !== void 0 ? { storage: opts.storage } : {},
58
- ...opts.seed !== void 0 ? { seed: opts.seed } : {},
59
- ...opts.reps !== void 0 ? { reps: opts.reps } : {},
60
- ...opts.maxConcurrency !== void 0 ? { maxConcurrency: opts.maxConcurrency } : {},
61
- ...opts.now !== void 0 ? { now: opts.now } : {}
62
- });
63
- const improved = result.gateResult.decision === "ship";
64
- const winnerSurface = typeof result.winnerSurface === "string" ? result.winnerSurface : opts.baselinePrompt;
65
- const baselineComposite = meanComposite(result.baselineOnHoldout);
66
- const winnerComposite = meanComposite(result.winnerOnHoldout);
67
- return {
68
- prompt: improved ? winnerSurface : opts.baselinePrompt,
69
- improved,
70
- decision: result.gateResult.decision,
71
- reasons: result.gateResult.reasons,
72
- baselineComposite,
73
- winnerComposite,
74
- delta: result.gateResult.delta ?? winnerComposite - baselineComposite,
75
- ...improved && result.winnerRationale ? { rationale: result.winnerRationale } : {},
76
- diff: result.promotedDiff,
77
- raw: result
78
- };
79
- }
80
- function meanComposite(campaign) {
81
- const scenarios = Object.values(campaign.aggregates.byScenario);
82
- if (scenarios.length === 0) return 0;
83
- const sum = scenarios.reduce((acc, s) => acc + s.meanComposite, 0);
84
- return sum / scenarios.length;
85
- }
86
-
87
- export {
88
- optimizePrompt
89
- };
90
- //# sourceMappingURL=chunk-VOX6Z3II.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/improvement/optimize-prompt.ts"],"sourcesContent":["/**\n * @experimental\n *\n * `optimizePrompt` — identity-gated optimization for any TEXT prompt surface\n * (system prompt, planner prompt, judge rubric, skill doc).\n *\n * The text-surface sibling to this module's `improvementDriver` (the\n * CODE-surface / worktree path). Both feed agent-eval's `runImprovementLoop`;\n * this one defaults the driver to agent-eval's `gepaDriver` (reflective text\n * mutator) and the gate to `heldOutGate`.\n *\n * IDENTITY-GATED BY CONSTRUCTION — the whole point. The loop runs evals,\n * collects per-scenario signal, proposes candidates, and the gate compares\n * candidate-vs-baseline ON THE HELDOUT. `result.prompt` is the baseline\n * (identity) UNLESS the gate decided `'ship'`. So wiring a surface up is safe:\n * a surface with no beneficial mutation simply keeps its baseline. You never\n * regress by registering a prompt — you only ever improve when the held-out\n * data earns it.\n *\n * Generic over the runtime: `runWithPrompt` is the only domain seam — given a\n * candidate prompt + scenario, run it however the surface runs (sandbox\n * `streamPrompt`, a `runLoop`, a direct model call) and return the artifact the\n * judges score. The optimizer never assumes how a prompt is executed.\n */\n\nimport type { LlmClientOptions } from '@tangle-network/agent-eval'\nimport type {\n CampaignResult,\n CampaignStorage,\n DispatchContext,\n Gate,\n GateResult,\n ImprovementDriver,\n JudgeConfig,\n RunImprovementLoopResult,\n Scenario,\n} from '@tangle-network/agent-eval/campaign'\nimport { gepaDriver, heldOutGate, runImprovementLoop } from '@tangle-network/agent-eval/campaign'\nimport { ConfigError } from '../errors'\n\n/** Reflection config for the default `gepaDriver`. Omit when passing a custom\n * `driver`. */\nexport interface OptimizePromptReflection {\n /** Router transport for the reflection model. */\n llm: LlmClientOptions\n /** Model that performs the reflective rewrite. */\n model: string\n /** What is being optimized — orients the reflection prompt. Default\n * `'system prompt'`. */\n target?: string\n /** Surface-specific mutation levers offered to the reflector. */\n mutationPrimitives?: string[]\n /** H2 (`## Foo`) headings that MUST survive every candidate. gepaDriver's\n * only structural guard — load-bearing sections of the prompt should be\n * `##` headings so a rewrite cannot drop them. */\n preserveSections?: string[]\n /** Max sentence-level edits per candidate vs the parent (a textual learning\n * rate). Caps a rewrite from wiping prior rules in one generation. */\n maxSentenceEdits?: number\n}\n\n/** @experimental */\nexport interface OptimizePromptOptions<TScenario extends Scenario, TArtifact> {\n /** The prompt being optimized — the identity baseline the gate protects. */\n baselinePrompt: string\n /** Domain seam: run a candidate prompt against a scenario → artifact the\n * judges score. The optimizer is agnostic to HOW the prompt runs. */\n runWithPrompt: (prompt: string, scenario: TScenario, ctx: DispatchContext) => Promise<TArtifact>\n /** Training pool — scored each generation to rank candidates. */\n scenarios: TScenario[]\n /** Held out of training — scored ONLY for the gate's baseline-vs-winner\n * delta. Disjoint from `scenarios`; this is what makes promotion measure\n * generalization, not memorization. */\n holdoutScenarios: TScenario[]\n /** Scorers — deterministic checks or LLM judges. */\n judges: JudgeConfig<TArtifact, TScenario>[]\n /** Where artifacts + traces land (opaque key under in-memory storage). */\n runDir: string\n /** Default driver = `gepaDriver` built from this. Required UNLESS `driver`\n * is supplied. */\n reflection?: OptimizePromptReflection\n /** Override the improvement strategy (custom driver / deterministic tests). */\n driver?: ImprovementDriver\n /** Override the promotion gate. Default `heldOutGate` over `holdoutScenarios`\n * — zero extra LLM. Wrap `defaultProductionGate` for red-team/reward-hacking\n * hardening on production wiring. */\n gate?: Gate<TArtifact, TScenario>\n /** Minimum held-out composite lift to ship, forwarded to the default\n * `heldOutGate`. When omitted the gate uses its own default. */\n deltaThreshold?: number\n /** Candidates proposed per generation. Default 4. */\n populationSize?: number\n /** Generations to run. Default 3. */\n maxGenerations?: number\n /** Candidates carried to the next generation. Default 2. */\n promoteTopK?: number\n /** Storage backend. Pass `inMemoryCampaignStorage()` for filesystem-less /\n * test runs. Default: Node filesystem. */\n storage?: CampaignStorage\n /** Reproducibility seed. Default 42. */\n seed?: number\n /** Per-scenario replicates for CI bands. Default 1. */\n reps?: number\n /** Max concurrent cells. Default 2. */\n maxConcurrency?: number\n /** Test seam — override the wall clock. */\n now?: () => Date\n /** On a shipped gate: `'pr'` opens a PR, `'none'` just reports. Default\n * `'none'`. */\n autoOnPromote?: 'pr' | 'none'\n ghOwner?: string\n ghRepo?: string\n}\n\n/** @experimental */\nexport interface OptimizePromptResult<TArtifact, TScenario extends Scenario> {\n /** The prompt to USE. Identity (the baseline) unless the gate shipped a\n * winner — so a caller can always assign `result.prompt` unconditionally. */\n prompt: string\n /** True only when the gate promoted a candidate over baseline on holdout. */\n improved: boolean\n /** The gate's verdict (`'ship' | 'hold' | 'need_more_work' | ...`). */\n decision: GateResult['decision']\n /** Human-readable reasons the gate gave. */\n reasons: string[]\n /** Mean held-out composite of the baseline. */\n baselineComposite: number\n /** Mean held-out composite of the winner candidate. */\n winnerComposite: number\n /** Held-out lift (winner − baseline); the gate's `delta` when it reported one. */\n delta: number\n /** Why the winner was proposed — present when a shipped winner carried a\n * driver rationale. */\n rationale?: string\n /** Unified baseline→winner diff (empty when the winner is the baseline). */\n diff: string\n /** The full loop result for callers that need generations / campaigns. */\n raw: RunImprovementLoopResult<TArtifact, TScenario>\n}\n\n/** @experimental */\nexport async function optimizePrompt<TScenario extends Scenario, TArtifact>(\n opts: OptimizePromptOptions<TScenario, TArtifact>,\n): Promise<OptimizePromptResult<TArtifact, TScenario>> {\n if (!opts.driver && !opts.reflection) {\n throw new ConfigError(\n 'optimizePrompt: pass `reflection` (builds the default gepaDriver) or a custom `driver`',\n )\n }\n if (opts.scenarios.length === 0) {\n throw new ConfigError('optimizePrompt: `scenarios` must be non-empty')\n }\n if (opts.holdoutScenarios.length === 0) {\n throw new ConfigError(\n 'optimizePrompt: `holdoutScenarios` must be non-empty (the gate needs it)',\n )\n }\n\n const driver =\n opts.driver ??\n gepaDriver({\n llm: opts.reflection!.llm,\n model: opts.reflection!.model,\n target: opts.reflection!.target ?? 'system prompt',\n mutationPrimitives: opts.reflection!.mutationPrimitives,\n constraints:\n opts.reflection!.preserveSections || opts.reflection!.maxSentenceEdits !== undefined\n ? {\n preserveSections: opts.reflection!.preserveSections,\n maxSentenceEdits: opts.reflection!.maxSentenceEdits,\n }\n : undefined,\n })\n\n const gate =\n opts.gate ??\n heldOutGate<TArtifact, TScenario>({\n scenarios: opts.holdoutScenarios,\n ...(opts.deltaThreshold !== undefined ? { deltaThreshold: opts.deltaThreshold } : {}),\n })\n\n const result = await runImprovementLoop<TScenario, TArtifact>({\n baselineSurface: opts.baselinePrompt,\n dispatchWithSurface: (surface, scenario, ctx) => {\n if (typeof surface !== 'string') {\n // optimizePrompt is the TEXT-surface entry point; a CodeSurface means\n // the caller wired the wrong driver. Fail loud — don't silently run the\n // baseline and report a phantom score.\n throw new ConfigError(\n 'optimizePrompt: received a CodeSurface — this entry point optimizes string prompts only',\n )\n }\n return opts.runWithPrompt(surface, scenario, ctx)\n },\n driver,\n populationSize: opts.populationSize ?? 4,\n maxGenerations: opts.maxGenerations ?? 3,\n ...(opts.promoteTopK !== undefined ? { promoteTopK: opts.promoteTopK } : {}),\n scenarios: opts.scenarios,\n holdoutScenarios: opts.holdoutScenarios,\n judges: opts.judges,\n gate,\n autoOnPromote: opts.autoOnPromote ?? 'none',\n ...(opts.ghOwner !== undefined ? { ghOwner: opts.ghOwner } : {}),\n ...(opts.ghRepo !== undefined ? { ghRepo: opts.ghRepo } : {}),\n runDir: opts.runDir,\n ...(opts.storage !== undefined ? { storage: opts.storage } : {}),\n ...(opts.seed !== undefined ? { seed: opts.seed } : {}),\n ...(opts.reps !== undefined ? { reps: opts.reps } : {}),\n ...(opts.maxConcurrency !== undefined ? { maxConcurrency: opts.maxConcurrency } : {}),\n ...(opts.now !== undefined ? { now: opts.now } : {}),\n })\n\n const improved = result.gateResult.decision === 'ship'\n const winnerSurface =\n typeof result.winnerSurface === 'string' ? result.winnerSurface : opts.baselinePrompt\n const baselineComposite = meanComposite(result.baselineOnHoldout)\n const winnerComposite = meanComposite(result.winnerOnHoldout)\n\n return {\n prompt: improved ? winnerSurface : opts.baselinePrompt,\n improved,\n decision: result.gateResult.decision,\n reasons: result.gateResult.reasons,\n baselineComposite,\n winnerComposite,\n delta: result.gateResult.delta ?? winnerComposite - baselineComposite,\n ...(improved && result.winnerRationale ? { rationale: result.winnerRationale } : {}),\n diff: result.promotedDiff,\n raw: result,\n }\n}\n\n/** Mean composite over a campaign's per-scenario aggregates. The held-out\n * campaigns score one surface across `holdoutScenarios`; averaging the\n * per-scenario means gives the single number the gate's delta is built from. */\nfunction meanComposite(campaign: CampaignResult<unknown, Scenario>): number {\n const scenarios = Object.values(campaign.aggregates.byScenario)\n if (scenarios.length === 0) return 0\n const sum = scenarios.reduce((acc, s) => acc + s.meanComposite, 0)\n return sum / scenarios.length\n}\n"],"mappings":"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","names":[]}
@@ -1,261 +0,0 @@
1
- // src/analyst-loop/run-analyst-loop.ts
2
- import { diffFindings } from "@tangle-network/agent-eval";
3
- async function runAnalystLoop(opts) {
4
- const log = opts.log ?? defaultLog;
5
- const strategy = opts.priorFindingsStrategy ?? "per-kind";
6
- const emit = makeEmitter(opts.onEvent);
7
- const startedAt = Date.now();
8
- const baselineRunId = resolveBaselineRunId(opts);
9
- const priorAll = baselineRunId ? opts.findingsStore?.loadRun(baselineRunId) ?? [] : [];
10
- log("baseline resolved", { baselineRunId, prior_findings: priorAll.length });
11
- await emit({
12
- type: "baseline-resolved",
13
- runId: opts.runId,
14
- baselineRunId,
15
- priorFindingCount: priorAll.length
16
- });
17
- const priorFindings = buildPriorFindingsInput(priorAll, strategy, opts.registry.list());
18
- const analystResult = await runRegistry(opts, priorFindings, emit);
19
- log("analyst run complete", {
20
- findings: analystResult.findings.length,
21
- cost_usd: analystResult.total_cost_usd,
22
- per_analyst: analystResult.per_analyst.map((s) => ({
23
- id: s.analyst_id,
24
- status: s.status,
25
- n: s.findings_count
26
- }))
27
- });
28
- if (opts.findingsStore && analystResult.findings.length > 0) {
29
- await opts.findingsStore.append(opts.runId, analystResult.findings);
30
- await emit({
31
- type: "findings-persisted",
32
- runId: opts.runId,
33
- count: analystResult.findings.length
34
- });
35
- }
36
- let diff = null;
37
- if (baselineRunId && analystResult.findings.length > 0) {
38
- diff = diffFindings(
39
- priorAll.map((f) => ({ ...f })),
40
- analystResult.findings.map((f) => ({ ...f, run_id: opts.runId }))
41
- );
42
- log("diff vs baseline", {
43
- appeared: diff.appeared.length,
44
- disappeared: diff.disappeared.length,
45
- persisted: diff.persisted.length,
46
- changed: diff.changed.length
47
- });
48
- await emit({
49
- type: "diff-computed",
50
- runId: opts.runId,
51
- baselineRunId,
52
- appeared: diff.appeared.length,
53
- disappeared: diff.disappeared.length,
54
- persisted: diff.persisted.length,
55
- changed: diff.changed.length
56
- });
57
- }
58
- let knowledge = null;
59
- if (opts.knowledgeAdapter) {
60
- knowledge = await runKnowledgeAdapter(opts, analystResult.findings, log, emit);
61
- }
62
- let improvement = null;
63
- if (opts.improvementAdapter) {
64
- improvement = await runImprovementAdapter(opts, analystResult.findings, log, emit);
65
- }
66
- await emit({
67
- type: "loop-completed",
68
- runId: opts.runId,
69
- durationMs: Date.now() - startedAt
70
- });
71
- return {
72
- runId: opts.runId,
73
- baselineRunId,
74
- analystResult,
75
- diff,
76
- knowledge,
77
- improvement
78
- };
79
- }
80
- function makeEmitter(onEvent) {
81
- if (!onEvent) return async () => {
82
- };
83
- return async (event) => {
84
- await onEvent(event);
85
- };
86
- }
87
- async function runRegistry(opts, priorFindings, emit) {
88
- const reg = opts.registry;
89
- if (typeof reg.runStream === "function" && opts.onEvent) {
90
- let final = null;
91
- for await (const ev of reg.runStream(opts.runId, opts.inputs, { priorFindings })) {
92
- await emit({ type: "analyst", runId: opts.runId, event: ev });
93
- if (ev.type === "run-completed") final = ev.result;
94
- }
95
- if (!final) {
96
- throw new Error("runAnalystLoop: registry.runStream ended without run-completed event");
97
- }
98
- return final;
99
- }
100
- return opts.registry.run(opts.runId, opts.inputs, { priorFindings });
101
- }
102
- function resolveBaselineRunId(opts) {
103
- if (opts.baselineRunId === null) return null;
104
- if (typeof opts.baselineRunId === "string") return opts.baselineRunId;
105
- if (!opts.findingsStore) return null;
106
- const all = opts.findingsStore.loadAll();
107
- let last = null;
108
- for (const row of all) {
109
- if (row.run_id === opts.runId) continue;
110
- last = row.run_id;
111
- }
112
- return last;
113
- }
114
- function buildPriorFindingsInput(prior, strategy, registry) {
115
- if (strategy === "none" || prior.length === 0) return void 0;
116
- const stripped = prior.map(({ run_id: _run_id, ...rest }) => rest);
117
- if (strategy === "wildcard") {
118
- return { "*": stripped };
119
- }
120
- void registry;
121
- return stripped;
122
- }
123
- async function runKnowledgeAdapter(opts, findings, log, emit) {
124
- const adapter = opts.knowledgeAdapter;
125
- const batch = await adapter.proposeFromFindings(findings);
126
- log("knowledge.proposeFromFindings", {
127
- proposals: batch.proposals.length,
128
- skipped: batch.skipped,
129
- errors: batch.errors.length
130
- });
131
- await emit({
132
- type: "knowledge-proposed",
133
- runId: opts.runId,
134
- proposalCount: batch.proposals.length,
135
- skipped: batch.skipped,
136
- errors: batch.errors.length
137
- });
138
- const auto = opts.autoApply?.knowledge ?? false;
139
- const threshold = opts.autoApply?.knowledgeConfidenceThreshold ?? 0.85;
140
- if (!auto || !adapter.apply) {
141
- await emit({
142
- type: "knowledge-applied",
143
- runId: opts.runId,
144
- writtenCount: 0,
145
- withheldForReview: batch.proposals.length
146
- });
147
- return {
148
- proposals: batch.proposals,
149
- applied: [],
150
- skipped: batch.skipped,
151
- errors: batch.errors,
152
- withheld_for_review: batch.proposals.length
153
- };
154
- }
155
- const findingsById = new Map(findings.map((f) => [f.finding_id, f]));
156
- const safe = [];
157
- let withheld = 0;
158
- for (const p of batch.proposals) {
159
- const src = p.sourceFindingId ? findingsById.get(p.sourceFindingId) : void 0;
160
- if (!src) {
161
- withheld += 1;
162
- continue;
163
- }
164
- if (src.confidence < threshold) {
165
- withheld += 1;
166
- continue;
167
- }
168
- safe.push(p);
169
- }
170
- const result = await adapter.apply(safe);
171
- log("knowledge.apply", {
172
- applied: result.written.length,
173
- withheld_for_review: withheld,
174
- warnings: result.warnings.length
175
- });
176
- await emit({
177
- type: "knowledge-applied",
178
- runId: opts.runId,
179
- writtenCount: result.written.length,
180
- withheldForReview: withheld
181
- });
182
- return {
183
- proposals: batch.proposals,
184
- applied: result.written,
185
- skipped: batch.skipped,
186
- errors: batch.errors,
187
- withheld_for_review: withheld
188
- };
189
- }
190
- async function runImprovementAdapter(opts, findings, log, emit) {
191
- const adapter = opts.improvementAdapter;
192
- const batch = await adapter.proposeFromFindings(findings);
193
- log("improvement.proposeFromFindings", {
194
- edits: batch.edits.length,
195
- skipped: batch.skipped,
196
- errors: batch.errors.length
197
- });
198
- await emit({
199
- type: "improvement-proposed",
200
- runId: opts.runId,
201
- editCount: batch.edits.length,
202
- skipped: batch.skipped,
203
- errors: batch.errors.length
204
- });
205
- const auto = opts.autoApply?.improvement ?? false;
206
- const threshold = opts.autoApply?.improvementConfidenceThreshold ?? 0.9;
207
- if (!auto || !adapter.apply) {
208
- await emit({
209
- type: "improvement-applied",
210
- runId: opts.runId,
211
- appliedCount: 0,
212
- withheldForReview: batch.edits.length
213
- });
214
- return {
215
- edits: batch.edits,
216
- applied: [],
217
- skipped: batch.skipped,
218
- errors: batch.errors,
219
- withheld_for_review: batch.edits.length
220
- };
221
- }
222
- const findingsById = new Map(findings.map((f) => [f.finding_id, f]));
223
- const safe = [];
224
- let withheld = 0;
225
- for (const e of batch.edits) {
226
- const src = e.sourceFindingId ? findingsById.get(e.sourceFindingId) : void 0;
227
- if (!src || src.confidence < threshold) {
228
- withheld += 1;
229
- continue;
230
- }
231
- safe.push(e);
232
- }
233
- const result = await adapter.apply(safe);
234
- log("improvement.apply", {
235
- applied: result.applied.length,
236
- withheld_for_review: withheld,
237
- warnings: result.warnings.length
238
- });
239
- await emit({
240
- type: "improvement-applied",
241
- runId: opts.runId,
242
- appliedCount: result.applied.length,
243
- withheldForReview: withheld
244
- });
245
- return {
246
- edits: batch.edits,
247
- applied: result.applied,
248
- skipped: batch.skipped,
249
- errors: batch.errors,
250
- withheld_for_review: withheld
251
- };
252
- }
253
- function defaultLog(msg, fields) {
254
- if (fields) console.log(`[analyst-loop] ${msg}`, fields);
255
- else console.log(`[analyst-loop] ${msg}`);
256
- }
257
-
258
- export {
259
- runAnalystLoop
260
- };
261
- //# sourceMappingURL=chunk-XBUG326M.js.map