@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
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/candidate-execution/workspace-archive.ts"],"sourcesContent":["import { randomUUID } from 'node:crypto'\nimport { constants as fsConstants } from 'node:fs'\nimport {\n lstat,\n mkdir,\n mkdtemp,\n open,\n readdir,\n readFile,\n realpath,\n rename,\n rm,\n writeFile,\n} from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { dirname, isAbsolute, join, resolve, sep, win32 } from 'node:path'\nimport { isAnyArrayBuffer, isSharedArrayBuffer } from 'node:util/types'\n\nimport type {\n AgentCandidateCapturedArtifact,\n AgentCandidateWorkspaceSnapshotEvidence,\n} from '@tangle-network/agent-interface'\nimport { type Entry, extract, type Pack, pack } from 'tar-stream'\n\nimport {\n candidateWorkspaceManifest,\n captureMaterializedWorkspace,\n verifyBytes,\n verifyMaterializedWorkspace,\n} from './artifacts'\nimport {\n canonicalCandidateBytes,\n canonicalCandidateDigest,\n deepFreezeCandidate,\n embeddedCandidateArtifact,\n sha256Bytes,\n} from './digest'\nimport {\n assertNoGitIndirection,\n readCandidateGitTreeFiles,\n runCandidateGit,\n} from './git-materialize'\nimport { persistCandidateOutputArtifact } from './output-artifacts'\nimport type {\n AgentCandidateExecutorWorkspaceFile,\n AgentCandidateOutputArtifactPort,\n AgentCandidateWorkspacePort,\n} from './types'\n\nconst archiveKind = 'agent-candidate-workspace-archive' as const\nconst workspaceEntryPrefix = 'workspace/'\nconst repositoryMetadataEntry = 'metadata/repository.json'\nconst repositoryBundleEntry = 'metadata/repository.bundle'\nconst fixedTarTime = new Date(0)\n\nexport interface AgentCandidateWorkspaceArchiveLimits {\n maxArchiveBytes: number\n maxEmbeddedArtifactBytes: number\n maxFiles: number\n maxFileBytes: number\n maxTotalFileBytes: number\n maxPathBytes: number\n maxRepositoryBundleBytes: number\n}\n\nconst defaultLimits: AgentCandidateWorkspaceArchiveLimits = Object.freeze({\n maxArchiveBytes: 512 * 1024 * 1024,\n maxEmbeddedArtifactBytes: 1024 * 1024,\n maxFiles: 50_000,\n maxFileBytes: 128 * 1024 * 1024,\n maxTotalFileBytes: 256 * 1024 * 1024,\n maxPathBytes: 4_096,\n maxRepositoryBundleBytes: 128 * 1024 * 1024,\n})\n\ninterface WorkspaceArchiveRepository {\n headCommit: string\n headTree: string\n bundle: {\n sha256: `sha256:${string}`\n byteLength: number\n bytes: Uint8Array\n }\n}\n\ninterface WorkspaceArchiveRepositoryMetadata {\n kind: typeof archiveKind\n headCommit: string\n headTree: string\n bundle: {\n sha256: `sha256:${string}`\n byteLength: number\n }\n}\n\ninterface DecodedWorkspaceArchive {\n files: Array<{ path: string; mode: number; bytes: Uint8Array }>\n repository?: WorkspaceArchiveRepository\n}\n\nexport interface CaptureAgentCandidateWorkspaceOptions {\n /** Include Git HEAD so task preparation can prove its exact commit and tree. */\n includeRepository?: boolean\n limits?: Partial<AgentCandidateWorkspaceArchiveLimits>\n /** Use the evaluator-owned artifact store when manifest or archive bytes should not be embedded. */\n artifactPersistence?: {\n executionId: string\n outputArtifacts: AgentCandidateOutputArtifactPort\n signal?: AbortSignal\n }\n}\n\nexport interface CreateAgentCandidateWorkspacePortOptions {\n limits?: Partial<AgentCandidateWorkspaceArchiveLimits>\n}\n\nexport interface CapturedAgentCandidateWorkspace {\n readonly snapshot: AgentCandidateWorkspaceSnapshotEvidence\n /** Caller-owned bytes accepted by createAgentCandidateWorkspacePort. */\n readonly archive: Uint8Array\n}\n\n/** Capture one exact regular-file workspace for immutable candidate execution. */\nexport async function captureAgentCandidateWorkspace(\n rootInput: string,\n options: CaptureAgentCandidateWorkspaceOptions = {},\n): Promise<CapturedAgentCandidateWorkspace> {\n const root = resolve(rootInput)\n const limits = workspaceLimits(options.limits)\n const captured = options.includeRepository\n ? await captureRepository(root, limits)\n : await captureMaterializedWorkspace(root, {\n limits: {\n maxFiles: limits.maxFiles,\n maxFileBytes: limits.maxFileBytes,\n maxTotalFileBytes: limits.maxTotalFileBytes,\n },\n })\n assertWorkspaceFilesWithinLimits(captured.files, limits)\n const repository = 'repository' in captured ? captured.repository : undefined\n return captureWorkspaceFiles(captured.files, repository, limits, options.artifactPersistence)\n}\n\n/** Capture detached files returned by a remote executor into the standard archive. */\nexport async function captureAgentCandidateWorkspaceFiles(\n input: readonly AgentCandidateExecutorWorkspaceFile[],\n options: Omit<CaptureAgentCandidateWorkspaceOptions, 'includeRepository'> = {},\n): Promise<CapturedAgentCandidateWorkspace> {\n const limits = workspaceLimits(options.limits)\n return captureWorkspaceFiles(\n normalizeWorkspaceFiles(input, limits),\n undefined,\n limits,\n options.artifactPersistence,\n )\n}\n\nasync function captureWorkspaceFiles(\n files: readonly AgentCandidateExecutorWorkspaceFile[],\n repository: WorkspaceArchiveRepository | undefined,\n limits: AgentCandidateWorkspaceArchiveLimits,\n artifactPersistence: CaptureAgentCandidateWorkspaceOptions['artifactPersistence'],\n): Promise<CapturedAgentCandidateWorkspace> {\n const material = candidateWorkspaceManifest(files)\n const manifest = canonicalCandidateBytes(material)\n const archive = await encodeWorkspaceArchive(files, repository, limits.maxArchiveBytes)\n if (\n !artifactPersistence &&\n (manifest.byteLength > limits.maxEmbeddedArtifactBytes ||\n archive.byteLength > limits.maxEmbeddedArtifactBytes)\n ) {\n throw new Error(\n 'candidate workspace artifacts exceed maxEmbeddedArtifactBytes; artifactPersistence is required',\n )\n }\n const manifestArtifact = await captureWorkspaceArtifact('manifest', manifest, artifactPersistence)\n const archiveArtifact = await captureWorkspaceArtifact('archive', archive, artifactPersistence)\n const snapshot = deepFreezeCandidate({\n kind: 'agent-candidate-workspace-snapshot',\n digest: canonicalCandidateDigest(material),\n material,\n manifest: manifestArtifact,\n archive: archiveArtifact,\n } satisfies AgentCandidateWorkspaceSnapshotEvidence)\n return Object.freeze({ snapshot, archive })\n}\n\nasync function captureWorkspaceArtifact(\n kind: 'manifest' | 'archive',\n bytes: Uint8Array,\n persistence: CaptureAgentCandidateWorkspaceOptions['artifactPersistence'],\n): Promise<AgentCandidateCapturedArtifact> {\n if (!persistence) return embeddedCandidateArtifact(bytes)\n if (!persistence.executionId.trim()) {\n throw new Error('candidate workspace artifact persistence requires an executionId')\n }\n return persistCandidateOutputArtifact(persistence.outputArtifacts, {\n executionId: persistence.executionId,\n purpose: kind === 'manifest' ? 'candidate-workspace-manifest' : 'candidate-workspace-archive',\n bytes,\n ...(persistence.signal ? { signal: persistence.signal } : {}),\n })\n}\n\n/** Create the standard bounded materializer for candidate execution ports. */\nexport function createAgentCandidateWorkspacePort(\n options: CreateAgentCandidateWorkspacePortOptions = {},\n): AgentCandidateWorkspacePort {\n const limits = workspaceLimits(options.limits)\n const port: AgentCandidateWorkspacePort = {\n materialize: async ({ role, snapshot, archive, destination }) => {\n await materializeAgentCandidateWorkspace({\n role,\n snapshot,\n archive,\n destination,\n limits,\n })\n },\n }\n return Object.freeze(port)\n}\n\nasync function materializeAgentCandidateWorkspace(input: {\n role: 'task' | 'candidate' | 'knowledge' | 'memory'\n snapshot: AgentCandidateWorkspaceSnapshotEvidence\n archive: Uint8Array\n destination: string\n limits: AgentCandidateWorkspaceArchiveLimits\n}): Promise<void> {\n verifyBytes(\n input.archive,\n input.snapshot.archive.sha256,\n input.snapshot.archive.byteLength,\n 'candidate workspace archive',\n )\n const decoded = await parseWorkspaceArchive(input.archive, input.limits)\n if (decoded.repository && input.role !== 'task') {\n throw new Error('only task workspaces may carry a Git repository')\n }\n assertArchiveMatchesSnapshot(decoded.files, input.snapshot)\n const destination = resolve(input.destination)\n await prepareEmptyDestination(destination)\n const staging = await mkdtemp(`${destination}.materializing-`)\n try {\n await writeWorkspaceFiles(staging, decoded.files)\n if (decoded.repository) {\n await materializeRepository(decoded.repository, staging)\n }\n await verifyMaterializedWorkspace(staging, input.snapshot.material, {\n ignoredProtectedRootEntries: decoded.repository ? ['.git'] : [],\n })\n await rename(staging, destination)\n } catch (error) {\n await rm(staging, { recursive: true, force: true })\n await rm(destination, { recursive: true, force: true })\n throw error\n }\n}\n\nasync function captureRepository(\n root: string,\n limits: AgentCandidateWorkspaceArchiveLimits,\n): Promise<{\n files: Array<{ path: string; mode: number; bytes: Uint8Array }>\n repository: WorkspaceArchiveRepository\n}> {\n const stats = await lstat(root)\n if (!stats.isDirectory() || stats.isSymbolicLink() || (await realpath(root)) !== root) {\n throw new Error('candidate repository root must be a real directory')\n }\n const topLevel = (await runCandidateGit(root, ['rev-parse', '--show-toplevel'])).stdout\n .toString('utf8')\n .trim()\n if (resolve(topLevel) !== root) {\n throw new Error('candidate repository capture must start at the Git worktree root')\n }\n const gitDir = resolve(\n (await runCandidateGit(root, ['rev-parse', '--absolute-git-dir'])).stdout\n .toString('utf8')\n .trim(),\n )\n if ((await realpath(gitDir)) !== gitDir || gitDir.includes(':')) {\n throw new Error('candidate repository Git object store has an unsupported path')\n }\n await assertNoGitIndirection(root, gitDir, 'candidate repository')\n const headCommit = (await runCandidateGit(root, ['rev-parse', 'HEAD'])).stdout\n .toString('utf8')\n .trim()\n const headTree = (await runCandidateGit(root, ['rev-parse', 'HEAD^{tree}'])).stdout\n .toString('utf8')\n .trim()\n assertGitObjectId(headCommit, 'HEAD')\n assertGitObjectId(headTree, 'HEAD tree')\n if (headCommit.length !== headTree.length) {\n throw new Error('candidate repository HEAD and tree use different object formats')\n }\n const files = await readCandidateGitTreeFiles(root, headTree, {}, limits)\n assertWorkspaceFilesWithinLimits(files, limits)\n const reachableBytesText = (\n await runCandidateGit(root, ['rev-list', '--disk-usage', '--objects', 'HEAD'])\n ).stdout\n .toString('utf8')\n .trim()\n const reachableBytes = Number(reachableBytesText)\n if (!Number.isSafeInteger(reachableBytes) || reachableBytes < 0) {\n throw new Error('candidate repository reachable size is invalid')\n }\n if (reachableBytes > limits.maxRepositoryBundleBytes) {\n throw new Error('candidate repository exceeds maxRepositoryBundleBytes')\n }\n const temporary = await mkdtemp(join(tmpdir(), 'agent-candidate-workspace-bundle-'))\n const bundlePath = join(temporary, `${randomUUID()}.bundle`)\n try {\n await runCandidateGit(root, ['bundle', 'create', bundlePath, 'HEAD'])\n const bundle = Uint8Array.from(await readFile(bundlePath))\n if (bundle.byteLength > limits.maxRepositoryBundleBytes) {\n throw new Error('candidate repository bundle exceeds maxRepositoryBundleBytes')\n }\n return {\n files,\n repository: {\n headCommit,\n headTree,\n bundle: {\n sha256: sha256Bytes(bundle),\n byteLength: bundle.byteLength,\n bytes: bundle,\n },\n },\n }\n } finally {\n await rm(temporary, { recursive: true, force: true })\n }\n}\n\nasync function encodeWorkspaceArchive(\n files: ReadonlyArray<{ path: string; mode: number; bytes: Uint8Array }>,\n repository: WorkspaceArchiveRepository | undefined,\n maxArchiveBytes: number,\n): Promise<Uint8Array> {\n const archive = pack()\n const output = collectStream(archive, maxArchiveBytes, 'candidate workspace archive')\n try {\n await writeWorkspaceArchiveEntries(archive, files, repository)\n archive.finalize()\n return await output\n } catch (error) {\n archive.destroy(error instanceof Error ? error : new Error(String(error)))\n await output.catch(() => undefined)\n throw error\n }\n}\n\nasync function verifyCanonicalWorkspaceArchive(\n files: ReadonlyArray<{ path: string; mode: number; bytes: Uint8Array }>,\n repository: WorkspaceArchiveRepository | undefined,\n expected: Uint8Array,\n maxArchiveBytes: number,\n): Promise<void> {\n const archive = pack()\n const comparison = streamEqualsBytes(\n archive,\n expected,\n maxArchiveBytes,\n 'candidate workspace archive',\n )\n try {\n await writeWorkspaceArchiveEntries(archive, files, repository)\n archive.finalize()\n if (!(await comparison)) throw new Error('candidate workspace tar is not canonical')\n } catch (error) {\n archive.destroy(error instanceof Error ? error : new Error(String(error)))\n await comparison.catch(() => undefined)\n throw error\n }\n}\n\nasync function writeWorkspaceArchiveEntries(\n archive: Pack,\n files: ReadonlyArray<{ path: string; mode: number; bytes: Uint8Array }>,\n repository: WorkspaceArchiveRepository | undefined,\n): Promise<void> {\n for (const file of files) {\n await writeTarEntry(archive, `${workspaceEntryPrefix}${file.path}`, file.mode, file.bytes)\n }\n if (!repository) return\n const metadata = canonicalCandidateBytes({\n kind: archiveKind,\n headCommit: repository.headCommit,\n headTree: repository.headTree,\n bundle: {\n sha256: repository.bundle.sha256,\n byteLength: repository.bundle.byteLength,\n },\n } satisfies WorkspaceArchiveRepositoryMetadata)\n await writeTarEntry(archive, repositoryMetadataEntry, 0o600, metadata)\n await writeTarEntry(archive, repositoryBundleEntry, 0o600, repository.bundle.bytes)\n}\n\nasync function parseWorkspaceArchive(\n bytes: Uint8Array,\n limits: AgentCandidateWorkspaceArchiveLimits,\n): Promise<DecodedWorkspaceArchive> {\n if (bytes.byteLength > limits.maxArchiveBytes) {\n throw new Error('candidate workspace archive exceeds maxArchiveBytes')\n }\n const parser = extract()\n const files: DecodedWorkspaceArchive['files'] = []\n const observedEntryNames = new Set<string>()\n const observedPaths = new Set<string>()\n let totalBytes = 0\n let retainedEntryBytes = 0\n let previousPath: string | undefined\n let repositoryMetadata: WorkspaceArchiveRepositoryMetadata | undefined\n let repositoryBundle: Uint8Array | undefined\n const decoded = (async () => {\n for await (const entry of parser) {\n const name = entry.header.name\n if (\n entry.header.type !== 'file' ||\n typeof name !== 'string' ||\n observedEntryNames.has(name)\n ) {\n throw new Error('candidate workspace tar contains an invalid entry')\n }\n observedEntryNames.add(name)\n if (name.startsWith(workspaceEntryPrefix)) {\n if (files.length >= limits.maxFiles) {\n throw new Error('candidate workspace archive has an invalid file count')\n }\n const path = safeArchivePath(name.slice(workspaceEntryPrefix.length), limits.maxPathBytes)\n if (!isWorkspaceFileMode(entry.header.mode)) {\n throw new Error(`candidate workspace archive has an unsupported mode: ${path}`)\n }\n assertRetainedArchiveSize(bytes.byteLength, retainedEntryBytes, entry.header.size, limits)\n const fileBytes = await readTarEntry(entry, limits.maxFileBytes, `workspace file ${path}`)\n retainedEntryBytes += fileBytes.byteLength\n assertWorkspacePathOrder(\n path,\n previousPath,\n observedPaths,\n 'candidate workspace archive paths must be unique and sorted',\n )\n previousPath = path\n if (fileBytes.byteLength > limits.maxTotalFileBytes - totalBytes) {\n throw new Error('candidate workspace archive exceeds maxTotalFileBytes')\n }\n totalBytes += fileBytes.byteLength\n files.push({ path, mode: entry.header.mode, bytes: fileBytes })\n } else if (name === repositoryMetadataEntry) {\n if (entry.header.mode !== 0o600 || repositoryMetadata) {\n throw new Error('candidate workspace archive repository metadata is invalid')\n }\n assertRetainedArchiveSize(bytes.byteLength, retainedEntryBytes, entry.header.size, limits)\n const metadataBytes = await readTarEntry(\n entry,\n limits.maxPathBytes,\n 'candidate repository metadata',\n )\n retainedEntryBytes += metadataBytes.byteLength\n repositoryMetadata = parseRepositoryMetadata(metadataBytes, limits.maxRepositoryBundleBytes)\n } else if (name === repositoryBundleEntry) {\n if (entry.header.mode !== 0o600 || repositoryBundle) {\n throw new Error('candidate workspace archive repository bundle is invalid')\n }\n assertRetainedArchiveSize(bytes.byteLength, retainedEntryBytes, entry.header.size, limits)\n repositoryBundle = await readTarEntry(\n entry,\n limits.maxRepositoryBundleBytes,\n 'candidate Git bundle',\n )\n retainedEntryBytes += repositoryBundle.byteLength\n } else {\n throw new Error(`candidate workspace tar contains an unsupported entry: ${name}`)\n }\n }\n if (Boolean(repositoryMetadata) !== Boolean(repositoryBundle)) {\n throw new Error('candidate workspace archive repository evidence is incomplete')\n }\n const repository =\n repositoryMetadata && repositoryBundle\n ? repositoryFromTar(repositoryMetadata, repositoryBundle)\n : undefined\n return { files, ...(repository ? { repository } : {}) }\n })()\n parser.end(Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength))\n const result = await decoded\n await verifyCanonicalWorkspaceArchive(\n result.files,\n result.repository,\n bytes,\n limits.maxArchiveBytes,\n )\n return result\n}\n\nfunction assertRetainedArchiveSize(\n archiveBytes: number,\n retainedEntryBytes: number,\n entryBytes: number | undefined,\n limits: AgentCandidateWorkspaceArchiveLimits,\n): void {\n if (\n !Number.isSafeInteger(entryBytes) ||\n entryBytes === undefined ||\n entryBytes < 0 ||\n entryBytes > limits.maxArchiveBytes - archiveBytes - retainedEntryBytes\n ) {\n throw new Error('candidate workspace archive exceeds maxArchiveBytes while decoding')\n }\n}\n\nfunction parseRepositoryMetadata(\n bytes: Uint8Array,\n maxBundleBytes: number,\n): WorkspaceArchiveRepositoryMetadata {\n let value: unknown\n try {\n value = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes))\n } catch (error) {\n throw new Error('candidate workspace archive repository metadata is invalid', { cause: error })\n }\n if (\n !isRecord(value) ||\n Object.keys(value).sort().join(',') !== 'bundle,headCommit,headTree,kind' ||\n value.kind !== archiveKind ||\n typeof value.headCommit !== 'string' ||\n typeof value.headTree !== 'string' ||\n !isRecord(value.bundle) ||\n Object.keys(value.bundle).sort().join(',') !== 'byteLength,sha256' ||\n typeof value.bundle.sha256 !== 'string' ||\n !/^sha256:[a-f0-9]{64}$/.test(value.bundle.sha256) ||\n !Number.isSafeInteger(value.bundle.byteLength) ||\n (value.bundle.byteLength as number) <= 0 ||\n (value.bundle.byteLength as number) > maxBundleBytes\n ) {\n throw new Error('candidate workspace archive repository is invalid')\n }\n if (!Buffer.from(canonicalCandidateBytes(value)).equals(Buffer.from(bytes))) {\n throw new Error('candidate workspace archive repository metadata is not canonical')\n }\n assertGitObjectId(value.headCommit, 'repository HEAD')\n assertGitObjectId(value.headTree, 'repository HEAD tree')\n if (value.headCommit.length !== value.headTree.length) {\n throw new Error('candidate repository HEAD and tree use different object formats')\n }\n return {\n kind: archiveKind,\n headCommit: value.headCommit,\n headTree: value.headTree,\n bundle: {\n sha256: value.bundle.sha256 as `sha256:${string}`,\n byteLength: value.bundle.byteLength as number,\n },\n }\n}\n\nfunction repositoryFromTar(\n metadata: WorkspaceArchiveRepositoryMetadata,\n bundle: Uint8Array,\n): WorkspaceArchiveRepository {\n verifyBytes(bundle, metadata.bundle.sha256, metadata.bundle.byteLength, 'candidate Git bundle')\n return {\n headCommit: metadata.headCommit,\n headTree: metadata.headTree,\n bundle: { ...metadata.bundle, bytes: bundle },\n }\n}\n\nasync function writeTarEntry(\n archive: Pack,\n name: string,\n mode: number,\n bytes: Uint8Array,\n): Promise<void> {\n await new Promise<void>((resolveEntry, rejectEntry) => {\n archive.entry(\n {\n name,\n mode,\n uid: 0,\n gid: 0,\n size: bytes.byteLength,\n mtime: fixedTarTime,\n type: 'file',\n uname: '',\n gname: '',\n },\n Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength),\n (error) => (error ? rejectEntry(error) : resolveEntry()),\n )\n })\n}\n\nasync function readTarEntry(entry: Entry, maxBytes: number, label: string): Promise<Uint8Array> {\n const size = entry.header.size\n if (!Number.isSafeInteger(size) || size === undefined || size < 0 || size > maxBytes) {\n throw new Error(`${label} has an invalid tar size`)\n }\n const bytes = await collectStream(entry, maxBytes, label)\n if (bytes.byteLength !== size) throw new Error(`${label} differs from its tar size`)\n return bytes\n}\n\nasync function collectStream(\n stream: AsyncIterable<Uint8Array>,\n maxBytes: number,\n label: string,\n): Promise<Uint8Array> {\n const chunks: Buffer[] = []\n let totalBytes = 0\n for await (const chunk of stream) {\n if (chunk.byteLength > maxBytes - totalBytes) {\n const error = new Error(`${label} exceeds its size limit`)\n if ('destroy' in stream && typeof stream.destroy === 'function') stream.destroy(error)\n throw error\n }\n const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n chunks.push(bytes)\n totalBytes += bytes.byteLength\n }\n return Buffer.concat(chunks, totalBytes)\n}\n\nasync function streamEqualsBytes(\n stream: AsyncIterable<Uint8Array>,\n expected: Uint8Array,\n maxBytes: number,\n label: string,\n): Promise<boolean> {\n const expectedBuffer = Buffer.from(expected.buffer, expected.byteOffset, expected.byteLength)\n let equal = true\n let offset = 0\n for await (const chunk of stream) {\n if (chunk.byteLength > maxBytes - offset) {\n const error = new Error(`${label} exceeds its size limit`)\n if ('destroy' in stream && typeof stream.destroy === 'function') stream.destroy(error)\n throw error\n }\n const observed = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength)\n if (\n offset + observed.byteLength > expectedBuffer.byteLength ||\n !observed.equals(expectedBuffer.subarray(offset, offset + observed.byteLength))\n ) {\n equal = false\n }\n offset += observed.byteLength\n }\n return equal && offset === expectedBuffer.byteLength\n}\n\nasync function prepareEmptyDestination(destination: string): Promise<void> {\n await mkdir(destination, { recursive: true, mode: 0o700 })\n const stats = await lstat(destination)\n if (\n !stats.isDirectory() ||\n stats.isSymbolicLink() ||\n (await realpath(destination)) !== destination\n ) {\n throw new Error('candidate workspace destination must be a real directory')\n }\n if ((await readdir(destination)).length > 0) {\n throw new Error('candidate workspace destination must be empty')\n }\n}\n\nasync function writeWorkspaceFiles(\n destination: string,\n files: ReadonlyArray<{ path: string; mode: number; bytes: Uint8Array }>,\n): Promise<void> {\n for (const file of files) {\n const path = workspacePath(destination, file.path)\n await mkdir(dirname(path), { recursive: true, mode: 0o700 })\n const descriptor = await open(\n path,\n fsConstants.O_WRONLY |\n fsConstants.O_CREAT |\n fsConstants.O_EXCL |\n (typeof fsConstants.O_NOFOLLOW === 'number' ? fsConstants.O_NOFOLLOW : 0),\n 0o600,\n )\n try {\n await descriptor.writeFile(file.bytes)\n const stats = await descriptor.stat()\n if (!stats.isFile() || stats.nlink !== 1) {\n throw new Error(`candidate workspace file identity changed while writing: ${file.path}`)\n }\n await descriptor.chmod(file.mode)\n } finally {\n await descriptor.close()\n }\n }\n}\n\nasync function materializeRepository(\n repository: WorkspaceArchiveRepository,\n destination: string,\n): Promise<void> {\n const temporary = await mkdtemp(join(tmpdir(), 'agent-candidate-workspace-bundle-'))\n const bundlePath = join(temporary, `${randomUUID()}.bundle`)\n try {\n await writeFile(bundlePath, repository.bundle.bytes, { flag: 'wx', mode: 0o600 })\n await runCandidateGit(destination, [\n 'init',\n '--quiet',\n '--initial-branch=candidate',\n `--object-format=${repository.headCommit.length === 64 ? 'sha256' : 'sha1'}`,\n ])\n await runCandidateGit(destination, ['bundle', 'verify', bundlePath])\n await runCandidateGit(destination, ['bundle', 'unbundle', bundlePath])\n const objectType = (\n await runCandidateGit(destination, ['cat-file', '-t', repository.headCommit])\n ).stdout\n .toString('utf8')\n .trim()\n if (objectType !== 'commit') throw new Error('candidate repository HEAD is not a commit')\n const observedTree = (\n await runCandidateGit(destination, ['rev-parse', `${repository.headCommit}^{tree}`])\n ).stdout\n .toString('utf8')\n .trim()\n if (observedTree !== repository.headTree) {\n throw new Error('candidate repository bundle HEAD tree changed')\n }\n await runCandidateGit(destination, ['update-ref', '--no-deref', 'HEAD', repository.headCommit])\n await runCandidateGit(destination, ['read-tree', repository.headTree])\n const status = (\n await runCandidateGit(destination, ['status', '--porcelain=v1', '--untracked-files=all'])\n ).stdout\n .toString('utf8')\n .trim()\n if (status) throw new Error('candidate repository files do not exactly match HEAD')\n } finally {\n await rm(temporary, { recursive: true, force: true })\n }\n}\n\nfunction assertArchiveMatchesSnapshot(\n files: ReadonlyArray<{ path: string; mode: number; bytes: Uint8Array }>,\n snapshot: AgentCandidateWorkspaceSnapshotEvidence,\n): void {\n const material = candidateWorkspaceManifest(files)\n const materialBytes = canonicalCandidateBytes(material)\n verifyBytes(\n materialBytes,\n snapshot.manifest.sha256,\n snapshot.manifest.byteLength,\n 'candidate workspace manifest',\n )\n if (\n canonicalCandidateDigest(material) !== snapshot.digest ||\n !Buffer.from(materialBytes).equals(Buffer.from(canonicalCandidateBytes(snapshot.material)))\n ) {\n throw new Error('candidate workspace archive does not match its snapshot manifest')\n }\n}\n\nfunction assertWorkspaceFilesWithinLimits(\n files: ReadonlyArray<{ path: string; mode: number; bytes: Uint8Array }>,\n limits: AgentCandidateWorkspaceArchiveLimits,\n): void {\n if (files.length > limits.maxFiles) {\n throw new Error('candidate workspace exceeds maxFiles')\n }\n let totalBytes = 0\n let previousPath: string | undefined\n const observedPaths = new Set<string>()\n for (const file of files) {\n const path = safeArchivePath(file.path, limits.maxPathBytes)\n assertWorkspacePathOrder(\n path,\n previousPath,\n observedPaths,\n 'candidate workspace paths must be unique and sorted',\n )\n previousPath = path\n if (!isWorkspaceFileMode(file.mode)) {\n throw new Error(`candidate workspace file has unsupported mode: ${path}`)\n }\n if (file.bytes.byteLength > limits.maxFileBytes) {\n throw new Error(`candidate workspace file exceeds maxFileBytes: ${path}`)\n }\n totalBytes += file.bytes.byteLength\n if (totalBytes > limits.maxTotalFileBytes) {\n throw new Error('candidate workspace exceeds maxTotalFileBytes')\n }\n }\n}\n\nfunction normalizeWorkspaceFiles(\n input: readonly AgentCandidateExecutorWorkspaceFile[],\n limits: AgentCandidateWorkspaceArchiveLimits,\n): AgentCandidateExecutorWorkspaceFile[] {\n if (!Array.isArray(input)) {\n throw new Error('candidate workspace files must be an array')\n }\n const fileCount = input.length\n if (fileCount > limits.maxFiles) {\n throw new Error('candidate workspace exceeds maxFiles')\n }\n let totalBytes = 0\n const files: AgentCandidateExecutorWorkspaceFile[] = []\n for (let index = 0; index < fileCount; index++) {\n const inputFile = input[index]\n if (!isRecord(inputFile) || Object.keys(inputFile).sort().join(',') !== 'bytes,mode,path') {\n throw new Error(`candidate workspace file ${index} is invalid`)\n }\n const descriptors = Object.getOwnPropertyDescriptors(inputFile)\n if (\n !('value' in (descriptors.path ?? {})) ||\n !('value' in (descriptors.mode ?? {})) ||\n !('value' in (descriptors.bytes ?? {}))\n ) {\n throw new Error(`candidate workspace file ${index} must use fixed values`)\n }\n const path = safeArchivePath(descriptors.path?.value, limits.maxPathBytes)\n const mode = descriptors.mode?.value\n const inputBytes = descriptors.bytes?.value\n if (!isWorkspaceFileMode(mode)) {\n throw new Error(`candidate workspace file has unsupported mode: ${path}`)\n }\n const view = inspectWorkspaceBytes(inputBytes, path)\n if (view.byteLength > limits.maxFileBytes) {\n throw new Error(`candidate workspace file exceeds maxFileBytes: ${path}`)\n }\n if (view.byteLength > limits.maxTotalFileBytes - totalBytes) {\n throw new Error('candidate workspace exceeds maxTotalFileBytes')\n }\n if (view.byteLength > Math.max(0, limits.maxArchiveBytes - 1024)) {\n throw new Error('candidate workspace archive exceeds maxArchiveBytes')\n }\n totalBytes += view.byteLength\n files.push({ path, mode, bytes: detachWorkspaceBytes(view) })\n }\n files.sort((left, right) => (left.path < right.path ? -1 : left.path > right.path ? 1 : 0))\n assertWorkspaceFilesWithinLimits(files, limits)\n return files\n}\n\nfunction isWorkspaceFileMode(value: unknown): value is number {\n return Number.isSafeInteger(value) && (value as number) >= 0 && (value as number) <= 0o777\n}\n\nfunction workspaceLimits(\n overrides: Partial<AgentCandidateWorkspaceArchiveLimits> | undefined,\n): AgentCandidateWorkspaceArchiveLimits {\n const limits = { ...defaultLimits, ...overrides }\n for (const [name, value] of Object.entries(limits)) {\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new Error(`candidate workspace ${name} must be a positive safe integer`)\n }\n }\n return Object.freeze(limits)\n}\n\nfunction safeArchivePath(value: unknown, maxPathBytes: number): string {\n if (\n typeof value !== 'string' ||\n !value ||\n !isWellFormedUnicode(value) ||\n Buffer.byteLength(value, 'utf8') > maxPathBytes ||\n isAbsolute(value) ||\n win32.isAbsolute(value) ||\n value.includes('\\\\') ||\n value.includes('\\0') ||\n hasControlCharacter(value) ||\n value.split('/').some((part) => !part || part === '.' || part === '..') ||\n ['.git', '.sidecar'].includes(value.split('/')[0]?.toLowerCase() ?? '')\n ) {\n throw new Error(`candidate workspace archive contains an unsafe path: ${String(value)}`)\n }\n return value\n}\n\nfunction assertWorkspacePathOrder(\n path: string,\n previousPath: string | undefined,\n observedPaths: Set<string>,\n errorMessage: string,\n): void {\n if (previousPath !== undefined && previousPath >= path) throw new Error(errorMessage)\n for (let slash = path.indexOf('/'); slash !== -1; slash = path.indexOf('/', slash + 1)) {\n if (observedPaths.has(path.slice(0, slash))) throw new Error(errorMessage)\n }\n observedPaths.add(path)\n}\n\nfunction inspectWorkspaceBytes(\n input: unknown,\n path: string,\n): { buffer: ArrayBuffer; byteOffset: number; byteLength: number } {\n let buffer: ArrayBufferLike\n let byteOffset: number\n let byteLength: number\n try {\n buffer = typedArrayBufferGetter.call(input as Uint8Array) as ArrayBufferLike\n byteOffset = typedArrayByteOffsetGetter.call(input as Uint8Array) as number\n byteLength = typedArrayByteLengthGetter.call(input as Uint8Array) as number\n } catch {\n throw new Error(`candidate workspace file bytes are invalid: ${path}`)\n }\n if (isSharedArrayBuffer(buffer)) {\n throw new Error(`candidate workspace file uses shared bytes: ${path}`)\n }\n if (!isAnyArrayBuffer(buffer)) {\n throw new Error(`candidate workspace file bytes are invalid: ${path}`)\n }\n return { buffer, byteOffset, byteLength }\n}\n\nfunction detachWorkspaceBytes(input: {\n buffer: ArrayBuffer\n byteOffset: number\n byteLength: number\n}): Uint8Array {\n const { buffer, byteOffset, byteLength } = input\n const copy = new Uint8Array(byteLength)\n Uint8Array.prototype.set.call(copy, new Uint8Array(buffer, byteOffset, byteLength))\n return copy\n}\n\nfunction isWellFormedUnicode(value: string): boolean {\n for (let index = 0; index < value.length; index++) {\n const code = value.charCodeAt(index)\n if (code >= 0xd800 && code <= 0xdbff) {\n const next = value.charCodeAt(index + 1)\n if (!(next >= 0xdc00 && next <= 0xdfff)) return false\n index++\n } else if (code >= 0xdc00 && code <= 0xdfff) {\n return false\n }\n }\n return true\n}\n\nfunction workspacePath(root: string, relativePath: string): string {\n const path = resolve(root, relativePath)\n if (!path.startsWith(`${root}${sep}`)) {\n throw new Error(`candidate workspace archive path escapes its destination: ${relativePath}`)\n }\n return path\n}\n\nfunction assertGitObjectId(value: string, label: string): void {\n if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(value)) {\n throw new Error(`candidate repository ${label} is not a Git object id`)\n }\n}\n\nfunction hasControlCharacter(value: string): boolean {\n for (let index = 0; index < value.length; index++) {\n const code = value.charCodeAt(index)\n if (code < 0x20 || code === 0x7f) return true\n }\n return false\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\ntype TypedArrayGetter = (this: Uint8Array) => unknown\n\nfunction requireTypedArrayGetter(name: 'buffer' | 'byteOffset' | 'byteLength'): TypedArrayGetter {\n const typedArrayPrototype = Object.getPrototypeOf(Uint8Array.prototype) as object\n const getter = Object.getOwnPropertyDescriptor(typedArrayPrototype, name)?.get\n if (!getter) throw new Error(`typed array intrinsic ${name} accessor is unavailable`)\n return getter\n}\n\nconst typedArrayBufferGetter = requireTypedArrayGetter('buffer')\nconst typedArrayByteOffsetGetter = requireTypedArrayGetter('byteOffset')\nconst typedArrayByteLengthGetter = requireTypedArrayGetter('byteLength')\n"],"mappings":"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","names":[]}
@@ -1,5 +1,6 @@
1
1
  import {
2
- BackendTransportError
2
+ BackendTransportError,
3
+ SessionMismatchError
3
4
  } from "./chunk-YEJR7IXO.js";
4
5
 
5
6
  // src/sessions.ts
@@ -20,6 +21,36 @@ function touchSession(session) {
20
21
  function nowIso() {
21
22
  return (/* @__PURE__ */ new Date()).toISOString();
22
23
  }
24
+ async function startOrResumeRuntimeSession(options) {
25
+ const existing = options.resume && options.sessionId ? await options.store?.get(options.sessionId) : void 0;
26
+ if (!existing) {
27
+ const input2 = resolveSessionInput(options.input);
28
+ const session2 = options.backend.start ? await options.backend.start(input2, {
29
+ ...options.context,
30
+ requestedSessionId: options.sessionId
31
+ }) : newRuntimeSession(options.backend.kind, options.sessionId);
32
+ assertSessionBackend(session2, options.backend.kind);
33
+ options.validateSession?.(session2);
34
+ await options.store?.put(session2);
35
+ return { session: session2, input: input2, resumed: false };
36
+ }
37
+ assertSessionBackend(existing, options.backend.kind);
38
+ const continued = options.backend.resume !== void 0;
39
+ const input = resolveSessionInput(
40
+ continued ? options.continuationInput ?? options.input : options.input
41
+ );
42
+ const session = options.backend.resume ? await options.backend.resume(existing, input, options.context) : touchSession({ ...existing, status: "active" });
43
+ assertSessionBackend(session, options.backend.kind);
44
+ options.validateSession?.(session);
45
+ await options.store?.put(session);
46
+ return { session, input, resumed: true };
47
+ }
48
+ function resolveSessionInput(input) {
49
+ return typeof input === "function" ? input() : input;
50
+ }
51
+ function assertSessionBackend(session, backend) {
52
+ if (session.backend !== backend) throw new SessionMismatchError(session.backend, backend);
53
+ }
23
54
  var InMemoryRuntimeSessionStore = class {
24
55
  sessions = /* @__PURE__ */ new Map();
25
56
  events = /* @__PURE__ */ new Map();
@@ -630,10 +661,11 @@ export {
630
661
  newRuntimeSession,
631
662
  touchSession,
632
663
  nowIso,
664
+ startOrResumeRuntimeSession,
633
665
  InMemoryRuntimeSessionStore,
634
666
  createIterableBackend,
635
667
  createSandboxPromptBackend,
636
668
  createOpenAICompatibleBackend,
637
669
  normalizeBackendStreamEvent
638
670
  };
639
- //# sourceMappingURL=chunk-AEG3NGJ2.js.map
671
+ //# sourceMappingURL=chunk-Q2JSAVQ3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sessions.ts","../src/backends.ts"],"sourcesContent":["/**\n *\n * Session helpers + an in-memory `RuntimeSessionStore` implementation suitable\n * for tests, scratch processes, and per-request scratch storage in serverless\n * runtimes. Durable stores (D1, postgres, Durable Objects) implement the same\n * interface from `./types`.\n *\n * @stable\n */\n\nimport { SessionMismatchError } from './errors'\nimport type {\n AgentBackendContext,\n AgentBackendInput,\n AgentExecutionBackend,\n RuntimeSession,\n RuntimeSessionStore,\n RuntimeStreamEvent,\n} from './types'\n\n/** @internal */\nexport function newRuntimeSession(\n backend: string,\n requestedId?: string,\n metadata?: Record<string, unknown>,\n): RuntimeSession {\n const now = nowIso()\n return {\n id: requestedId || crypto.randomUUID(),\n backend,\n status: 'active',\n createdAt: now,\n updatedAt: now,\n metadata,\n }\n}\n\n/** @internal */\nexport function touchSession(session: RuntimeSession): RuntimeSession {\n return { ...session, updatedAt: nowIso() }\n}\n\n/** @internal */\nexport function nowIso(): string {\n return new Date().toISOString()\n}\n\ninterface StartOrResumeRuntimeSessionOptions<TInput extends AgentBackendInput> {\n backend: AgentExecutionBackend<TInput>\n input: TInput | (() => TInput)\n /** Smaller input used only when the backend can continue its native session. */\n continuationInput?: TInput | (() => TInput)\n context: Omit<AgentBackendContext, 'session'>\n store?: RuntimeSessionStore\n sessionId?: string\n resume?: boolean\n validateSession?: (session: RuntimeSession) => void\n}\n\ninterface RuntimeSessionCall<TInput extends AgentBackendInput> {\n session: RuntimeSession\n input: TInput\n resumed: boolean\n}\n\n/** Start or resume one backend session and persist its current identity. @internal */\nexport async function startOrResumeRuntimeSession<TInput extends AgentBackendInput>(\n options: StartOrResumeRuntimeSessionOptions<TInput>,\n): Promise<RuntimeSessionCall<TInput>> {\n const existing =\n options.resume && options.sessionId ? await options.store?.get(options.sessionId) : undefined\n if (!existing) {\n const input = resolveSessionInput(options.input)\n const session = options.backend.start\n ? await options.backend.start(input, {\n ...options.context,\n requestedSessionId: options.sessionId,\n })\n : newRuntimeSession(options.backend.kind, options.sessionId)\n assertSessionBackend(session, options.backend.kind)\n options.validateSession?.(session)\n await options.store?.put(session)\n return { session, input, resumed: false }\n }\n\n assertSessionBackend(existing, options.backend.kind)\n const continued = options.backend.resume !== undefined\n const input = resolveSessionInput(\n continued ? (options.continuationInput ?? options.input) : options.input,\n )\n const session = options.backend.resume\n ? await options.backend.resume(existing, input, options.context)\n : touchSession({ ...existing, status: 'active' })\n assertSessionBackend(session, options.backend.kind)\n options.validateSession?.(session)\n await options.store?.put(session)\n return { session, input, resumed: true }\n}\n\nfunction resolveSessionInput<TInput extends AgentBackendInput>(\n input: TInput | (() => TInput),\n): TInput {\n return typeof input === 'function' ? input() : input\n}\n\nfunction assertSessionBackend(session: RuntimeSession, backend: string): void {\n if (session.backend !== backend) throw new SessionMismatchError(session.backend, backend)\n}\n\n/** In-memory `RuntimeSessionStore` for single-process use and tests. @stable */\nexport class InMemoryRuntimeSessionStore implements RuntimeSessionStore {\n private readonly sessions = new Map<string, RuntimeSession>()\n private readonly events = new Map<string, RuntimeStreamEvent[]>()\n\n get(sessionId: string): RuntimeSession | undefined {\n return this.sessions.get(sessionId)\n }\n\n put(session: RuntimeSession): void {\n this.sessions.set(session.id, session)\n }\n\n appendEvent(sessionId: string, event: RuntimeStreamEvent): void {\n const existing = this.events.get(sessionId) ?? []\n existing.push(event)\n this.events.set(sessionId, existing)\n }\n\n listEvents(sessionId: string): RuntimeStreamEvent[] {\n return [...(this.events.get(sessionId) ?? [])]\n }\n}\n","/**\n *\n * Backend factories for `runAgentTaskStream`. Three shapes ship in core:\n *\n * - `createIterableBackend` — wrap any custom async iterable into a backend\n * - `createSandboxPromptBackend` — sandbox / sidecar `streamPrompt` clients\n * - `createOpenAICompatibleBackend` — OpenAI-style chat completions endpoints\n *\n * Adapters stay thin: domain repos own auth, model selection, and the concrete\n * tool surface. The factories handle session creation, stream normalization,\n * and graceful end-of-stream signalling.\n *\n * @stable\n */\n\nimport { BackendTransportError } from './errors'\nimport { newRuntimeSession, nowIso, touchSession } from './sessions'\nimport type {\n AgentBackendContext,\n AgentBackendInput,\n AgentExecutionBackend,\n OpenAIChatResponseFormat,\n OpenAIChatTool,\n OpenAIChatToolChoice,\n RuntimeSession,\n RuntimeStreamEvent,\n} from './types'\n\n/** Wrap any custom async-iterable stream into a typed `AgentExecutionBackend`. @stable */\nexport function createIterableBackend<TInput extends AgentBackendInput>(options: {\n kind: string\n start?: AgentExecutionBackend<TInput>['start']\n resume?: AgentExecutionBackend<TInput>['resume']\n stream: AgentExecutionBackend<TInput>['stream']\n stop?: AgentExecutionBackend<TInput>['stop']\n}): AgentExecutionBackend<TInput> {\n return options\n}\n\n/** Build an `AgentExecutionBackend` backed by a sandbox/sidecar `streamPrompt` call. @stable */\nexport function createSandboxPromptBackend<\n TBox,\n TInput extends AgentBackendInput = AgentBackendInput,\n>(options: {\n kind?: string\n getBox(input: TInput, context: Omit<AgentBackendContext, 'session'>): Promise<TBox> | TBox\n streamPrompt(box: TBox, message: string, context: AgentBackendContext): AsyncIterable<unknown>\n mapEvent?: (event: unknown, context: AgentBackendContext) => RuntimeStreamEvent | undefined\n getSessionId?: (box: TBox, input: TInput) => string | undefined\n}): AgentExecutionBackend<TInput> {\n const kind = options.kind ?? 'sandbox'\n return {\n kind,\n async start(input, context) {\n const box = await options.getBox(input, context)\n return newRuntimeSession(\n kind,\n options.getSessionId?.(box, input) ?? context.requestedSessionId,\n { resumable: true },\n )\n },\n resume(session) {\n return touchSession({ ...session, status: 'active' })\n },\n async *stream(input, context) {\n const box = await options.getBox(input, context)\n const message = input.message ?? input.messages?.at(-1)?.content ?? context.task.intent\n for await (const event of options.streamPrompt(box, message, context)) {\n const mapped = options.mapEvent?.(event, context) ?? mapCommonBackendEvent(event, context)\n if (mapped) yield mapped\n }\n },\n }\n}\n\n/** @stable */\n/**\n * Retry policy for transient transport errors (rate limits, upstream\n * timeouts). Defaults to 5 attempts with exponential backoff starting at\n * 1s, ±25% jitter, capped at 30s. Set `maxAttempts: 1` to disable retries.\n *\n * Retried status codes:\n * - 408 Request Timeout\n * - 425 Too Early\n * - 429 Too Many Requests\n * - 500 / 502 / 503 / 504 — upstream transient failures\n *\n * Hard failures (401, 403, 4xx other than the above) propagate immediately.\n */\nexport interface BackendRetryPolicy {\n /** Total attempts including the first try. Default 5. */\n maxAttempts?: number\n /** Initial backoff in ms before the second attempt. Default 1000. */\n initialBackoffMs?: number\n /** Hard ceiling on backoff in ms. Default 30000. */\n maxBackoffMs?: number\n /** Jitter fraction in [0, 1]. Default 0.25 (±25%). */\n jitter?: number\n /** Status codes that trigger a retry. Default: 408, 425, 429, 500, 502, 503, 504. */\n retryStatuses?: ReadonlyArray<number>\n /**\n * Per-attempt wall-clock deadline in ms. If a single fetch attempt does\n * not return headers within this window the attempt is aborted and\n * retried. Default 120000 (2 min). Without this a hung upstream blocks\n * the attempt indefinitely — observed in production as a 15-minute\n * `fetch failed` that burned an entire eval persona. Set to 0 to disable.\n */\n requestTimeoutMs?: number\n}\n\nconst DEFAULT_RETRY_STATUSES = [408, 425, 429, 500, 502, 503, 504] as const\n\nfunction pickRetryDelayMs(attempt: number, policy: Required<BackendRetryPolicy>): number {\n const exp = policy.initialBackoffMs * 2 ** (attempt - 1)\n const capped = Math.min(exp, policy.maxBackoffMs)\n const jitter = capped * policy.jitter * (Math.random() * 2 - 1)\n return Math.max(0, Math.round(capped + jitter))\n}\n\n/**\n * Derive a per-attempt AbortSignal that fires when EITHER the caller's\n * signal aborts OR `timeoutMs` elapses. `dispose()` clears the timer so a\n * completed attempt doesn't leak a pending timeout. `timeoutMs <= 0`\n * disables the deadline (caller signal still propagates).\n */\nfunction withTimeout(\n callerSignal: AbortSignal | undefined,\n timeoutMs: number,\n): { signal: AbortSignal; dispose: () => void } {\n if (timeoutMs <= 0) {\n return { signal: callerSignal ?? new AbortController().signal, dispose: () => undefined }\n }\n const controller = new AbortController()\n const timer = setTimeout(\n () => controller.abort(new Error(`request timed out after ${timeoutMs}ms`)),\n timeoutMs,\n )\n if (typeof (timer as { unref?: () => void }).unref === 'function') {\n ;(timer as { unref: () => void }).unref()\n }\n const onCallerAbort = () => controller.abort(callerSignal?.reason ?? new Error('aborted'))\n if (callerSignal) {\n if (callerSignal.aborted) onCallerAbort()\n else callerSignal.addEventListener('abort', onCallerAbort, { once: true })\n }\n return {\n signal: controller.signal,\n dispose: () => {\n clearTimeout(timer)\n callerSignal?.removeEventListener('abort', onCallerAbort)\n },\n }\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) {\n reject(signal.reason ?? new Error('aborted'))\n return\n }\n const t = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort)\n resolve()\n }, ms)\n const onAbort = () => {\n clearTimeout(t)\n reject(signal?.reason ?? new Error('aborted'))\n }\n signal?.addEventListener('abort', onAbort, { once: true })\n })\n}\n\n/**\n *\n * OpenAI-compat streaming backend. Routes `runAgentTaskStream` through any\n * `POST /chat/completions` endpoint that speaks OpenAI's SSE protocol —\n * Tangle Router, OpenAI direct, OpenRouter, Groq, DeepSeek, Together. The\n * router also fronts Anthropic models in Anthropic-native SSE shape; this\n * backend handles both.\n *\n * ### Tool calls\n *\n * Pass `tools` (and optionally `toolChoice`) to forward an OpenAI Chat\n * Completions `tools[]` array on every request. Streamed `tool_call` chunks\n * are buffered until the model finalizes them (either `finish_reason:\n * 'tool_calls'` for OpenAI shape or a `content_block_stop` for Anthropic\n * `tool_use` blocks proxied through the router), then emitted as a single\n * `tool_call` RuntimeStreamEvent with the assembled `args`.\n *\n * The backend does NOT execute tools — it surfaces calls for the caller's\n * own dispatcher (typically the product's MCP / sandbox runtime) to fulfill\n * and feed back as a subsequent `messages` turn. This keeps the transport\n * thin and lets the agent host own tool dispatch policy.\n *\n * ### Fail-loud errors\n *\n * Non-success HTTP responses (4xx/5xx) and exhausted retry budgets throw\n * `BackendTransportError` from inside the `stream()` generator. The runtime\n * catches the throw, yields a `backend_error` with a typed `error` field\n * (`kind`, `status`, truncated `body`) and a terminal `final` event with\n * `status: 'failed'` carrying the same detail. Consumers MUST map\n * `final.error` onto their `RunRecord.error` — silently treating an empty\n * `finalText` as \"agent produced nothing\" hides credit exhaustion, auth\n * failure, and upstream outages.\n *\n * @stable\n */\nexport function createOpenAICompatibleBackend<\n TInput extends AgentBackendInput = AgentBackendInput,\n>(options: {\n apiKey: string\n baseUrl: string\n model: string\n kind?: string\n /**\n * OpenAI Chat Completions `tools[]` definitions surfaced to the model on\n * every request. Omit to send a tool-free request (existing behavior).\n * The runtime makes no assumption about the dispatcher — calls stream out\n * as `tool_call` events and the caller is responsible for executing them\n * and feeding `tool_result` messages back on a follow-up turn.\n */\n tools?: ReadonlyArray<OpenAIChatTool>\n /**\n * OpenAI Chat Completions `tool_choice`. Default `undefined` (request\n * omits the field; provider falls back to its own default — typically\n * `'auto'`).\n */\n toolChoice?: OpenAIChatToolChoice\n /**\n * OpenAI Chat Completions `response_format`. Omit for provider default text.\n */\n responseFormat?: OpenAIChatResponseFormat\n /** OpenAI Chat Completions `temperature`. Omit for provider default. */\n temperature?: number\n /** Maximum completion tokens, sent as OpenAI-compatible `max_tokens`. Omit for provider default. */\n maxTokens?: number\n fetchImpl?: typeof fetch\n retry?: BackendRetryPolicy\n}): AgentExecutionBackend<TInput> {\n const fetcher = options.fetchImpl ?? fetch\n const kind = options.kind ?? 'tcloud'\n const retryPolicy: Required<BackendRetryPolicy> = {\n maxAttempts: options.retry?.maxAttempts ?? 5,\n initialBackoffMs: options.retry?.initialBackoffMs ?? 1000,\n maxBackoffMs: options.retry?.maxBackoffMs ?? 30000,\n jitter: options.retry?.jitter ?? 0.25,\n retryStatuses: options.retry?.retryStatuses ?? DEFAULT_RETRY_STATUSES,\n requestTimeoutMs: options.retry?.requestTimeoutMs ?? 120_000,\n }\n return {\n kind,\n start(_input, context) {\n return newRuntimeSession(kind, context.requestedSessionId)\n },\n async *stream(input, context) {\n const url = `${options.baseUrl.replace(/\\/$/, '')}/chat/completions`\n // `stream_options.include_usage` instructs OpenAI-compatible providers\n // (and the Tangle Router) to emit a final usage chunk in the SSE stream.\n // Without this the response carries no token counts and every downstream\n // ledger reads zero. Providers that don't recognize the field ignore it.\n const bodyPayload: Record<string, unknown> = {\n model: options.model,\n stream: true,\n stream_options: { include_usage: true },\n messages: input.messages ?? [\n { role: 'user', content: input.message ?? context.task.intent },\n ],\n }\n if (options.tools && options.tools.length > 0) {\n bodyPayload.tools = options.tools\n if (options.toolChoice !== undefined) bodyPayload.tool_choice = options.toolChoice\n }\n if (options.responseFormat !== undefined) {\n bodyPayload.response_format = options.responseFormat\n }\n if (options.temperature !== undefined) {\n bodyPayload.temperature = options.temperature\n }\n if (options.maxTokens !== undefined) {\n bodyPayload.max_tokens = options.maxTokens\n }\n const requestBody = JSON.stringify(bodyPayload)\n let response: Response | undefined\n let lastStatus = 0\n // The last thrown transport error (timeout abort, DNS / connection\n // failure). Network throws are retryable just like 5xx — without this\n // a `fetch failed` propagated immediately and burned the attempt.\n let lastThrown: unknown\n for (let attempt = 1; attempt <= retryPolicy.maxAttempts; attempt++) {\n lastThrown = undefined\n // Per-attempt deadline: abort a hung upstream instead of waiting\n // forever. Linked to context.signal so a caller cancel still wins.\n const attemptSignal = withTimeout(context.signal, retryPolicy.requestTimeoutMs)\n try {\n response = await fetcher(url, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${options.apiKey}`,\n 'Content-Type': 'application/json',\n // Cross-gateway forwarding: when this call is part of a\n // multi-agent conversation, the runner stamps run/turn/\n // depth/forwarded-auth headers onto the context. They flow\n // through to the downstream gateway verbatim so the original\n // user gets billed, the recursion depth stays bounded, and\n // the trace correlates across hops.\n ...(context.propagatedHeaders ?? {}),\n },\n body: requestBody,\n signal: attemptSignal.signal,\n })\n } catch (err) {\n attemptSignal.dispose()\n // A caller-initiated abort is terminal — do not retry it.\n if (context.signal?.aborted) throw err\n lastThrown = err\n response = undefined\n if (attempt === retryPolicy.maxAttempts) break\n await sleep(pickRetryDelayMs(attempt, retryPolicy), context.signal)\n continue\n }\n attemptSignal.dispose()\n if (response.ok) break\n lastStatus = response.status\n if (!retryPolicy.retryStatuses.includes(response.status)) break\n if (attempt === retryPolicy.maxAttempts) break\n // Drain the failed body so the connection can be reused.\n try {\n await response.body?.cancel()\n } catch {\n // Best-effort — some runtimes don't expose cancel.\n }\n const delayMs = pickRetryDelayMs(attempt, retryPolicy)\n await sleep(delayMs, context.signal)\n }\n if (!response) {\n const reason = lastThrown instanceof Error ? lastThrown.message : String(lastThrown)\n throw new BackendTransportError(\n kind,\n `chat backend unreachable after ${retryPolicy.maxAttempts} attempts: ${reason}`,\n { status: 0 },\n )\n }\n if (!response.ok) {\n // Capture the upstream body so the operator sees *why* the call\n // failed (e.g. `free_tier_limit`, `invalid_api_key`,\n // `model_not_found`). Truncate aggressively — HTML error pages from a\n // misconfigured proxy can be megabytes and would otherwise bloat\n // every persisted event. Best-effort: if body reading throws we\n // still surface the status code.\n let body: string | undefined\n try {\n const raw = await response.text()\n body = raw.length > MAX_ERROR_BODY_BYTES ? `${raw.slice(0, MAX_ERROR_BODY_BYTES)}…` : raw\n } catch {\n body = undefined\n }\n throw new BackendTransportError(kind, `chat backend returned ${lastStatus || 'unknown'}`, {\n status: lastStatus || 0,\n body,\n })\n }\n yield* streamResponseEvents(response, context, options.model)\n },\n }\n}\n\n/**\n * Cap the captured error body. 2 KiB is enough to carry a JSON error envelope\n * with a structured `code`/`message` payload (the router returns ~150 bytes\n * for a free-tier denial; OpenAI returns ~300 bytes for invalid auth) without\n * letting an HTML error page balloon persisted events.\n */\nconst MAX_ERROR_BODY_BYTES = 2048\n\n/**\n * Token usage accumulated across an SSE stream. OpenAI emits a single final\n * `usage` chunk; Anthropic emits `input_tokens` on `message_start` and\n * `output_tokens` on the terminal `message_delta`. We accept both — and the\n * router proxy may forward either shape depending on which upstream answered.\n */\ninterface StreamUsageAccumulator {\n tokensIn?: number\n tokensOut?: number\n model?: string\n finishReason?: string\n saw: boolean\n}\n\n/** @internal */\nexport function normalizeBackendStreamEvent(\n event: RuntimeStreamEvent,\n task: AgentBackendContext['task'],\n session: RuntimeSession,\n): RuntimeStreamEvent {\n if (\n 'task' in event &&\n event.task &&\n 'session' in event &&\n event.session &&\n 'timestamp' in event &&\n event.timestamp\n ) {\n return event\n }\n return {\n ...event,\n task: 'task' in event && event.task ? event.task : task,\n session: 'session' in event && event.session ? event.session : session,\n timestamp: 'timestamp' in event && event.timestamp ? event.timestamp : nowIso(),\n } as RuntimeStreamEvent\n}\n\nfunction mapCommonBackendEvent(\n event: unknown,\n context: AgentBackendContext,\n): RuntimeStreamEvent | undefined {\n if (!event || typeof event !== 'object') return undefined\n const record = event as Record<string, unknown>\n const type = String(record.type ?? '')\n const data =\n record.data && typeof record.data === 'object'\n ? (record.data as Record<string, unknown>)\n : record\n if (type === 'message.part.updated' || type === 'text_delta' || type === 'delta') {\n // `@tangle-network/sandbox` `box.streamTask` emits `message.part.updated`\n // with a nested part: `{ type: 'message.part.updated', data: { part:\n // { type: 'text', text: '…' } } }`. Walk into `data.part.text` so the\n // canonical sandbox-SDK shape produces a `text_delta` natively — no\n // per-product `mapEvent` shim required. Tool parts are picked up by\n // the `tool_call` / `tool_result` branches below; non-text parts here\n // fall through to `undefined` (the consumer can opt in via `mapEvent`).\n const part = data.part as Record<string, unknown> | undefined\n const partText =\n part !== undefined &&\n typeof part === 'object' &&\n (part.type === 'text' || part.type === undefined)\n ? stringValue(part.text)\n : undefined\n const text =\n stringValue(data.text) ?? stringValue(data.delta) ?? stringValue(record.text) ?? partText\n return text\n ? {\n type: 'text_delta',\n task: context.task,\n session: context.session,\n text,\n timestamp: nowIso(),\n }\n : undefined\n }\n if (type === 'reasoning_delta') {\n const text = stringValue(data.text) ?? stringValue(record.text)\n return text\n ? {\n type: 'reasoning_delta',\n task: context.task,\n session: context.session,\n text,\n timestamp: nowIso(),\n }\n : undefined\n }\n if (type === 'tool_call') {\n return {\n type: 'tool_call',\n task: context.task,\n session: context.session,\n toolName: stringValue(data.name) ?? stringValue(record.toolName) ?? 'tool',\n toolCallId: stringValue(data.id) ?? stringValue(record.toolCallId),\n args: data.args ?? data.input ?? record.args,\n timestamp: nowIso(),\n }\n }\n if (type === 'tool_result') {\n return {\n type: 'tool_result',\n task: context.task,\n session: context.session,\n toolName: stringValue(data.name) ?? stringValue(record.toolName) ?? 'tool',\n toolCallId: stringValue(data.id) ?? stringValue(record.toolCallId),\n result: data.result ?? data.output ?? record.result,\n timestamp: nowIso(),\n }\n }\n if (type === 'artifact') {\n const artifactId =\n stringValue(data.artifactId) ?? stringValue(data.id) ?? stringValue(record.artifactId)\n if (!artifactId) return undefined\n return {\n type: 'artifact',\n task: context.task,\n session: context.session,\n artifactId,\n name: stringValue(data.name) ?? stringValue(record.name),\n mimeType: stringValue(data.mimeType) ?? stringValue(record.mimeType),\n uri: stringValue(data.uri) ?? stringValue(record.uri),\n content: stringValue(data.content) ?? stringValue(data.body) ?? stringValue(record.content),\n metadata:\n data.metadata && typeof data.metadata === 'object'\n ? (data.metadata as Record<string, unknown>)\n : undefined,\n timestamp: nowIso(),\n }\n }\n if (type === 'proposal_created' || type === 'proposal' || type === 'filing') {\n const proposalId =\n stringValue(data.proposalId) ?? stringValue(data.id) ?? stringValue(record.proposalId)\n if (!proposalId) return undefined\n const status = stringValue(data.status) ?? stringValue(record.status)\n return {\n type: 'proposal_created',\n task: context.task,\n session: context.session,\n proposalId,\n title: stringValue(data.title) ?? stringValue(record.title) ?? proposalId,\n status:\n status === 'pending' || status === 'approved' || status === 'rejected' ? status : undefined,\n content: stringValue(data.content) ?? stringValue(data.body) ?? stringValue(record.content),\n timestamp: nowIso(),\n }\n }\n if (type === 'result' || type === 'final') {\n const text = stringValue(data.finalText) ?? stringValue(data.text) ?? stringValue(record.text)\n return text\n ? {\n type: 'text_delta',\n task: context.task,\n session: context.session,\n text,\n timestamp: nowIso(),\n }\n : undefined\n }\n return undefined\n}\n\nasync function* streamResponseEvents(\n response: Response,\n context: AgentBackendContext,\n requestedModel: string,\n): AsyncIterable<RuntimeStreamEvent> {\n const body = response.body\n if (!body) return\n const reader = body.getReader()\n const decoder = new TextDecoder()\n let buffer = ''\n const usage: StreamUsageAccumulator = { saw: false }\n // Tool-call assembly is stateful across SSE chunks: both OpenAI and\n // Anthropic streamed `arguments`/`partial_json` incrementally and the\n // final event is only safe to emit once we see a `finish_reason:\n // 'tool_calls'` or `content_block_stop` for the relevant index.\n const toolCalls: ToolCallAccumulator = new Map()\n const startedAt = Date.now()\n for (;;) {\n const { done, value } = await reader.read()\n if (done) break\n buffer += decoder.decode(value, { stream: true }).replace(/\\r\\n/g, '\\n')\n for (const event of drainStreamBuffer(false)) yield event\n }\n buffer += decoder.decode().replace(/\\r\\n/g, '\\n')\n for (const event of drainStreamBuffer(true)) yield event\n if (buffer.trim()) {\n for (const event of parseStreamChunk(buffer, context, usage, toolCalls)) yield event\n }\n // Flush any tool calls the model never closed via `finish_reason` — the\n // upstream may have terminated the stream without a terminal chunk (e.g.\n // when the proxy proactively forwards `[DONE]`). Emitting these here is\n // strictly safer than silently dropping a tool call the agent intended.\n for (const event of flushPendingToolCalls(toolCalls, context)) yield event\n // Synthesize a single `llm_call` event from accumulated usage. We only emit\n // when the upstream actually reported tokens — silent zeros would corrupt\n // every cost ledger that observes the stream. Consumers that need to detect\n // missing usage can check `tokensIn === undefined`.\n if (usage.saw) {\n yield {\n type: 'llm_call',\n task: context.task,\n session: context.session,\n model: usage.model ?? requestedModel,\n tokensIn: usage.tokensIn,\n tokensOut: usage.tokensOut,\n // `costUsd` is intentionally absent — pricing tables live in consumers\n // (agent-eval's `estimateCost`, MetricsCollector). Emitting a wrong\n // number here is worse than emitting none.\n latencyMs: Date.now() - startedAt,\n finishReason: usage.finishReason,\n timestamp: nowIso(),\n }\n }\n\n function* drainStreamBuffer(flush: boolean): Iterable<RuntimeStreamEvent> {\n for (;;) {\n const sseBoundary = buffer.indexOf('\\n\\n')\n if (sseBoundary >= 0) {\n const chunk = buffer.slice(0, sseBoundary)\n buffer = buffer.slice(sseBoundary + 2)\n for (const event of parseStreamChunk(chunk, context, usage, toolCalls)) yield event\n continue\n }\n\n const newline = buffer.indexOf('\\n')\n if (newline >= 0 && !buffer.slice(0, newline).startsWith('data:')) {\n const line = buffer.slice(0, newline)\n buffer = buffer.slice(newline + 1)\n for (const event of parseStreamChunk(line, context, usage, toolCalls)) yield event\n continue\n }\n\n if (flush && buffer.trim() && !buffer.trimStart().startsWith('data:')) {\n const line = buffer\n buffer = ''\n for (const event of parseStreamChunk(line, context, usage, toolCalls)) yield event\n continue\n }\n\n break\n }\n }\n}\n\n/**\n * Per-tool-call accumulator. Keyed by either OpenAI `index` (cast to string)\n * or Anthropic `content_block` `index`. Holds the streamed identifier, name,\n * and string-form `arguments` so we can emit a single typed `tool_call`\n * event once the stream signals the call is finalized.\n */\ntype ToolCallAccumulator = Map<\n string,\n {\n id?: string\n name?: string\n /** Accumulated JSON-string `arguments` / `input` payload. */\n argsRaw: string\n /** Source format: OpenAI delta vs Anthropic `tool_use` block. */\n source: 'openai' | 'anthropic'\n /** Set true once the model signals this call is complete. */\n finalized: boolean\n }\n>\n\nfunction* parseStreamChunk(\n chunk: string,\n context: AgentBackendContext,\n usage: StreamUsageAccumulator,\n toolCalls: ToolCallAccumulator,\n): Iterable<RuntimeStreamEvent> {\n const lines = chunk.split(/\\r?\\n/)\n const dataLines = lines.filter((line) => line.startsWith('data:'))\n if (\n dataLines.length === 0 &&\n lines.every((line) => {\n const trimmed = line.trim()\n return trimmed.length === 0 || trimmed.startsWith(':')\n })\n ) {\n return\n }\n const data =\n dataLines.length > 0\n ? dataLines.map((line) => line.slice(5).trimStart()).join('\\n')\n : chunk.trim()\n if (!data || data === '[DONE]') return\n let parsed: Record<string, unknown>\n try {\n parsed = JSON.parse(data) as Record<string, unknown>\n } catch {\n yield {\n type: 'text_delta',\n task: context.task,\n session: context.session,\n text: data,\n timestamp: nowIso(),\n }\n return\n }\n captureStreamUsage(parsed, usage)\n const choices = parsed.choices\n const choice = Array.isArray(choices)\n ? (choices[0] as Record<string, unknown> | undefined)\n : undefined\n const delta = choice?.delta as Record<string, unknown> | undefined\n const message = choice?.message as Record<string, unknown> | undefined\n\n // ── OpenAI streamed `tool_calls` deltas ─────────────────────────────\n const deltaToolCalls = delta?.tool_calls\n if (Array.isArray(deltaToolCalls)) {\n for (const tc of deltaToolCalls) {\n if (!tc || typeof tc !== 'object') continue\n const rec = tc as Record<string, unknown>\n const idx = numberValue(rec.index) ?? 0\n const key = `openai:${idx}`\n const acc = toolCalls.get(key) ?? { argsRaw: '', source: 'openai' as const, finalized: false }\n const id = stringValue(rec.id)\n if (id) acc.id = id\n const fn = rec.function as Record<string, unknown> | undefined\n const name = stringValue(fn?.name)\n if (name) acc.name = name\n const args = stringValue(fn?.arguments)\n if (args) acc.argsRaw += args\n toolCalls.set(key, acc)\n }\n }\n // `message.tool_calls` is the non-streamed shape — the model returned a\n // complete tool call in one chunk. Treat the whole array as terminal.\n const messageToolCalls = message?.tool_calls\n if (Array.isArray(messageToolCalls)) {\n for (const tc of messageToolCalls) {\n if (!tc || typeof tc !== 'object') continue\n const rec = tc as Record<string, unknown>\n const fn = rec.function as Record<string, unknown> | undefined\n const idx = numberValue(rec.index) ?? messageToolCalls.indexOf(tc)\n const key = `openai:${idx}`\n const acc = toolCalls.get(key) ?? { argsRaw: '', source: 'openai' as const, finalized: false }\n const id = stringValue(rec.id)\n if (id) acc.id = id\n const name = stringValue(fn?.name)\n if (name) acc.name = name\n const args = stringValue(fn?.arguments)\n if (args) acc.argsRaw += args\n acc.finalized = true\n toolCalls.set(key, acc)\n }\n }\n\n const finishReason = stringValue(choice?.finish_reason)\n if (finishReason === 'tool_calls') {\n // Model signaled it's done streaming tool calls — flush every OpenAI-\n // sourced pending entry. Subsequent chunks (usage, [DONE]) won't add\n // more.\n for (const [key, acc] of toolCalls) {\n if (acc.source === 'openai' && !acc.finalized) acc.finalized = true\n toolCalls.set(key, acc)\n }\n }\n\n // ── Anthropic shape (proxied through router) ────────────────────────\n const eventType = stringValue(parsed.type)\n if (eventType === 'content_block_start') {\n const block = parsed.content_block as Record<string, unknown> | undefined\n if (block && stringValue(block.type) === 'tool_use') {\n const idx = numberValue(parsed.index) ?? 0\n const key = `anthropic:${idx}`\n toolCalls.set(key, {\n id: stringValue(block.id),\n name: stringValue(block.name),\n argsRaw: '',\n source: 'anthropic',\n finalized: false,\n })\n }\n }\n if (eventType === 'content_block_delta') {\n const d = parsed.delta as Record<string, unknown> | undefined\n const dType = stringValue(d?.type)\n if (dType === 'input_json_delta') {\n const idx = numberValue(parsed.index) ?? 0\n const key = `anthropic:${idx}`\n const acc = toolCalls.get(key)\n if (acc) {\n const partial = stringValue(d?.partial_json) ?? ''\n acc.argsRaw += partial\n toolCalls.set(key, acc)\n }\n } else {\n const text = stringValue(d?.text)\n if (text) {\n yield {\n type: 'text_delta',\n task: context.task,\n session: context.session,\n text,\n timestamp: nowIso(),\n }\n }\n }\n }\n if (eventType === 'content_block_stop') {\n const idx = numberValue(parsed.index) ?? 0\n const key = `anthropic:${idx}`\n const acc = toolCalls.get(key)\n if (acc) {\n acc.finalized = true\n toolCalls.set(key, acc)\n }\n }\n\n // Emit any tool calls that just became finalized. Done eagerly per-chunk so\n // consumers see the call as soon as it's safe — the analyst loop watches\n // `tool_call` events for delegation-pattern detection.\n for (const event of drainFinalizedToolCalls(toolCalls, context)) yield event\n\n // ── Text deltas ──────────────────────────────────────────────────────\n const text =\n stringValue(delta?.content) ?? stringValue(message?.content) ?? stringValue(parsed.text)\n if (text) {\n yield {\n type: 'text_delta',\n task: context.task,\n session: context.session,\n text,\n timestamp: nowIso(),\n }\n return\n }\n const mapped = mapCommonBackendEvent(parsed, context)\n if (mapped) yield mapped\n}\n\nfunction* drainFinalizedToolCalls(\n toolCalls: ToolCallAccumulator,\n context: AgentBackendContext,\n): Iterable<RuntimeStreamEvent> {\n for (const [key, acc] of toolCalls) {\n if (!acc.finalized) continue\n toolCalls.delete(key)\n yield buildToolCallEvent(acc, context)\n }\n}\n\nfunction* flushPendingToolCalls(\n toolCalls: ToolCallAccumulator,\n context: AgentBackendContext,\n): Iterable<RuntimeStreamEvent> {\n for (const [key, acc] of toolCalls) {\n toolCalls.delete(key)\n yield buildToolCallEvent(acc, context)\n }\n}\n\nfunction buildToolCallEvent(\n acc: { id?: string; name?: string; argsRaw: string; source: 'openai' | 'anthropic' },\n context: AgentBackendContext,\n): RuntimeStreamEvent {\n // `argsRaw` is JSON-string by the provider contract (OpenAI streams an\n // escaped JSON string; Anthropic streams `partial_json` chunks). Parse\n // best-effort — surface the raw string if parsing fails so downstream\n // doesn't lose the call entirely.\n let args: unknown = acc.argsRaw\n if (acc.argsRaw.length > 0) {\n try {\n args = JSON.parse(acc.argsRaw)\n } catch {\n args = acc.argsRaw\n }\n } else {\n args = {}\n }\n return {\n type: 'tool_call',\n task: context.task,\n session: context.session,\n toolName: acc.name ?? 'tool',\n toolCallId: acc.id,\n args,\n timestamp: nowIso(),\n }\n}\n\n/**\n * Accumulate token usage from any SSE chunk shape the router may emit.\n *\n * - OpenAI: a final chunk before `[DONE]` with `{ usage: { prompt_tokens,\n * completion_tokens, total_tokens } }` and (often) empty `choices`. The\n * `model` field is on every chunk and the last `choices[0].finish_reason`\n * carries the stop reason.\n * - Anthropic: `message_start` carries `message.model` and\n * `message.usage.input_tokens`. The terminal `message_delta` carries\n * `usage.output_tokens` and `delta.stop_reason`.\n */\nfunction captureStreamUsage(parsed: Record<string, unknown>, usage: StreamUsageAccumulator): void {\n const model = stringValue(parsed.model)\n if (model && !usage.model) usage.model = model\n\n const openAiUsage = parsed.usage as Record<string, unknown> | undefined\n if (openAiUsage && typeof openAiUsage === 'object') {\n const promptTokens = numberValue(openAiUsage.prompt_tokens)\n const completionTokens = numberValue(openAiUsage.completion_tokens)\n const inputTokens = numberValue(openAiUsage.input_tokens)\n const outputTokens = numberValue(openAiUsage.output_tokens)\n if (promptTokens !== undefined) {\n usage.tokensIn = promptTokens\n usage.saw = true\n } else if (inputTokens !== undefined) {\n usage.tokensIn = (usage.tokensIn ?? 0) + inputTokens\n usage.saw = true\n }\n if (completionTokens !== undefined) {\n usage.tokensOut = completionTokens\n usage.saw = true\n } else if (outputTokens !== undefined) {\n usage.tokensOut = (usage.tokensOut ?? 0) + outputTokens\n usage.saw = true\n }\n }\n\n const type = stringValue(parsed.type)\n if (type === 'message_start') {\n const message = parsed.message as Record<string, unknown> | undefined\n const messageModel = stringValue(message?.model)\n if (messageModel && !usage.model) usage.model = messageModel\n const messageUsage = message?.usage as Record<string, unknown> | undefined\n const inputTokens = numberValue(messageUsage?.input_tokens)\n if (inputTokens !== undefined) {\n usage.tokensIn = inputTokens\n usage.saw = true\n }\n const outputTokens = numberValue(messageUsage?.output_tokens)\n if (outputTokens !== undefined) {\n usage.tokensOut = (usage.tokensOut ?? 0) + outputTokens\n usage.saw = true\n }\n }\n if (type === 'message_delta') {\n const delta = parsed.delta as Record<string, unknown> | undefined\n const stopReason = stringValue(delta?.stop_reason)\n if (stopReason) usage.finishReason = stopReason\n }\n\n const choices = parsed.choices\n if (Array.isArray(choices)) {\n const finishReason = stringValue(\n (choices[0] as Record<string, unknown> | undefined)?.finish_reason,\n )\n if (finishReason) usage.finishReason = finishReason\n }\n}\n\nfunction numberValue(value: unknown): number | undefined {\n return typeof value === 'number' && Number.isFinite(value) ? value : undefined\n}\n\nfunction stringValue(value: unknown): string | undefined {\n return typeof value === 'string' && value.length > 0 ? value : undefined\n}\n"],"mappings":"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","names":["input","session","text"]}