@tangle-network/agent-runtime 6.0.8 → 8.0.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.
- package/CHANGELOG.md +86 -0
- package/README.md +23 -12
- package/dist/{activation-Cwy3_Qn_.js → activation-Ce4zUcu8.js} +4 -4
- package/dist/{activation-Cwy3_Qn_.js.map → activation-Ce4zUcu8.js.map} +1 -1
- package/dist/{activation-CWx7I1PU.d.ts → activation-xxvLF1-1.d.ts} +2 -2
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +3 -3
- package/dist/{bundle-Cy5igJdv.js → bundle-CcpL2lfr.js} +2 -2
- package/dist/{bundle-Cy5igJdv.js.map → bundle-CcpL2lfr.js.map} +1 -1
- package/dist/candidate-execution/index.js +4 -4
- package/dist/continuation-CIyKnS1Q.js +451 -0
- package/dist/continuation-CIyKnS1Q.js.map +1 -0
- package/dist/{coordination-manager-D9z7To7p.js → coordination-manager-sa_PkISw.js} +247 -149
- package/dist/coordination-manager-sa_PkISw.js.map +1 -0
- package/dist/{coordination-map-routing-CKRNZSaV.js → coordination-map-routing-XZXTlCmn.js} +2 -4
- package/dist/coordination-map-routing-XZXTlCmn.js.map +1 -0
- package/dist/{delegate-ws-KBA2H.js → delegate-DhTkJIta.js} +3 -3
- package/dist/{delegate-ws-KBA2H.js.map → delegate-DhTkJIta.js.map} +1 -1
- package/dist/durable.d.ts +71 -4
- package/dist/durable.js +162 -13
- package/dist/durable.js.map +1 -1
- package/dist/{errors-AzSuGI23.js → errors-DG8yufqX.js} +8 -1
- package/dist/errors-DG8yufqX.js.map +1 -0
- package/dist/{failure-cause-BzjUUsRz.js → failure-cause-CVB-YE88.js} +17 -16
- package/dist/failure-cause-CVB-YE88.js.map +1 -0
- package/dist/{graph-registry-7X2nrreR.js → graph-registry-czAwYwNj.js} +133 -9
- package/dist/graph-registry-czAwYwNj.js.map +1 -0
- package/dist/{graph-registry-gYbq4L5Z.js → graph-registry-uTIyyy7A.js} +1 -1
- package/dist/graph-tSIT_eWK.js +1793 -0
- package/dist/graph-tSIT_eWK.js.map +1 -0
- package/dist/{improve-BxfqTsZy.js → improve-H08hiIw9.js} +19 -48
- package/dist/improve-H08hiIw9.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +16 -16
- package/dist/intelligence.d.ts +2 -2
- package/dist/intelligence.js +8 -8
- package/dist/intelligence.js.map +1 -1
- package/dist/kernel.d.ts +2 -2
- package/dist/kernel.js +16 -15
- package/dist/{loop-runner-CUMypgRw.d.ts → loop-runner-BGwhcn1p.d.ts} +2 -2
- package/dist/{loop-runner-BmGZ4y1W.js → loop-runner-ChqK8kSz.js} +3 -3
- package/dist/{loop-runner-BmGZ4y1W.js.map → loop-runner-ChqK8kSz.js.map} +1 -1
- package/dist/loop-runner-bin.d.ts +1 -1
- package/dist/loop-runner-bin.js +1 -1
- package/dist/mcp/bin.js +7 -5
- package/dist/mcp/bin.js.map +1 -1
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +9 -9
- package/dist/mcp/memory-bin.js +2 -2
- package/dist/{model-policy-JOcg3NRs.js → model-policy-yxOrDTTj.js} +9 -9
- package/dist/model-policy-yxOrDTTj.js.map +1 -0
- package/dist/{prepare-Dtfk_Wi_.js → prepare-BnF8nGIg.js} +4 -4
- package/dist/{prepare-Dtfk_Wi_.js.map → prepare-BnF8nGIg.js.map} +1 -1
- package/dist/{profile-CNSQjOes.js → profile-CD25rTJF.js} +4 -4
- package/dist/{profile-CNSQjOes.js.map → profile-CD25rTJF.js.map} +1 -1
- package/dist/profiles.d.ts +1 -1
- package/dist/profiles.js +2 -2
- package/dist/{provision-supervisor-CeQTPHRr.js → provision-supervisor-Dx4TXTMM.js} +8 -8
- package/dist/{provision-supervisor-CeQTPHRr.js.map → provision-supervisor-Dx4TXTMM.js.map} +1 -1
- package/dist/{run-cancellation-D_4vJ522.js → run-cancellation-DYszFJtQ.js} +4 -4
- package/dist/{run-cancellation-D_4vJ522.js.map → run-cancellation-DYszFJtQ.js.map} +1 -1
- package/dist/{run-state-CTZVngI_.js → run-state-DHBoJjaF.js} +6 -6
- package/dist/{run-state-CTZVngI_.js.map → run-state-DHBoJjaF.js.map} +1 -1
- package/dist/{runtime-COm9uBBx.js → runtime-CaM5Gbbv.js} +76 -987
- package/dist/runtime-CaM5Gbbv.js.map +1 -0
- package/dist/{sandbox-profile-compat-oFGWESLn.js → sandbox-profile-compat-l-SLQnGb.js} +2 -2
- package/dist/{sandbox-profile-compat-oFGWESLn.js.map → sandbox-profile-compat-l-SLQnGb.js.map} +1 -1
- package/dist/{search-executor-DTEIl58w.js → search-executor-B9L8W_1O.js} +17 -46
- package/dist/search-executor-B9L8W_1O.js.map +1 -0
- package/dist/{server-zO9Nz9Nk.js → server-BlDV8sj_.js} +32 -8
- package/dist/{server-zO9Nz9Nk.js.map → server-BlDV8sj_.js.map} +1 -1
- package/dist/{settle-record-U7fkQEZa.js → settle-record-WWQasnDq.js} +12 -4
- package/dist/settle-record-WWQasnDq.js.map +1 -0
- package/dist/{snapshot-Cgj2Wzi6.js → snapshot-BKI_w3JD.js} +19 -5
- package/dist/snapshot-BKI_w3JD.js.map +1 -0
- package/dist/{structural-rollout-BwTwTUXF.js → structural-rollout-C1xxoWcN.js} +39 -57
- package/dist/structural-rollout-C1xxoWcN.js.map +1 -0
- package/dist/{supervise-tmqDU6YT.js → supervise-DWiSgPLB.js} +103 -111
- package/dist/supervise-DWiSgPLB.js.map +1 -0
- package/dist/{supervision-discovery-CGbXayGv.js → supervision-discovery-C9kfBLKy.js} +4 -4
- package/dist/{supervision-discovery-CGbXayGv.js.map → supervision-discovery-C9kfBLKy.js.map} +1 -1
- package/dist/{supervisor-1A27fE6k.js → supervisor-Dpeu7rnZ.js} +209 -999
- package/dist/supervisor-Dpeu7rnZ.js.map +1 -0
- package/dist/{scope-gIYQ5ZiL.js → supervisor-accounting-Bw4MJk-b.js} +755 -458
- package/dist/supervisor-accounting-Bw4MJk-b.js.map +1 -0
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +13 -13
- package/dist/{tool-server-B9q2dtnW.js → tool-server-DYwRbi0I.js} +3 -3
- package/dist/{tool-server-B9q2dtnW.js.map → tool-server-DYwRbi0I.js.map} +1 -1
- package/dist/{top-web-CS4PD4ck.js → top-web-B3HOAtrZ.js} +9 -7
- package/dist/{top-web-CS4PD4ck.js.map → top-web-B3HOAtrZ.js.map} +1 -1
- package/dist/tui/bin.js +6 -6
- package/dist/tui/bin.js.map +1 -1
- package/dist/tui/index.d.ts +1 -1
- package/dist/tui/index.js +2 -2
- package/dist/{types-w3Oo1uRJ.d.ts → types-C_qbnw9N.d.ts} +1263 -1497
- package/dist/{util-C_cdPNC4.js → util-fcckrkKp.js} +39 -113
- package/dist/util-fcckrkKp.js.map +1 -0
- package/dist/{workspace-streams-B7yNMahl.js → workspace-streams-DA9R3j-p.js} +2 -2
- package/dist/{workspace-streams-B7yNMahl.js.map → workspace-streams-DA9R3j-p.js.map} +1 -1
- package/package.json +1 -1
- package/dist/coordination-manager-D9z7To7p.js.map +0 -1
- package/dist/coordination-map-routing-CKRNZSaV.js.map +0 -1
- package/dist/errors-AzSuGI23.js.map +0 -1
- package/dist/failure-cause-BzjUUsRz.js.map +0 -1
- package/dist/graph-2_nX4ib4.js +0 -579
- package/dist/graph-2_nX4ib4.js.map +0 -1
- package/dist/graph-registry-7X2nrreR.js.map +0 -1
- package/dist/improve-BxfqTsZy.js.map +0 -1
- package/dist/model-policy-JOcg3NRs.js.map +0 -1
- package/dist/runtime-COm9uBBx.js.map +0 -1
- package/dist/scope-gIYQ5ZiL.js.map +0 -1
- package/dist/search-executor-DTEIl58w.js.map +0 -1
- package/dist/settle-record-U7fkQEZa.js.map +0 -1
- package/dist/snapshot-Cgj2Wzi6.js.map +0 -1
- package/dist/structural-rollout-BwTwTUXF.js.map +0 -1
- package/dist/supervise-tmqDU6YT.js.map +0 -1
- package/dist/supervisor-1A27fE6k.js.map +0 -1
- package/dist/util-C_cdPNC4.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"search-executor-DTEIl58w.js","names":["dollars"],"sources":["../src/improvement/search-decision.ts","../src/runtime/shared-box-retry.ts","../src/runtime/shared-box-worker.ts","../src/runtime/shared-box.ts","../src/improvement/search-executor.ts"],"sourcesContent":["/**\n * Runtime's decision on a closed search, made from its records alone: the claim\n * the ledger supports, the cost ledger's accounting, the ship rule, and, when\n * the search ships, the profiles-table promotion that cites the claim.\n *\n * `improve()` applies it when a search closes. `decideSearchImprovement`\n * applies it to a closed search's directory, so a search is decided again under\n * the current rule without running or spending anything. The ship rule is not\n * part of a search's identity: the same ledger re-decided after a rule change is\n * the same search.\n */\n\nimport { createHash } from 'node:crypto'\nimport { dirname, join } from 'node:path'\nimport type { CostLedgerHandle, PairedPromotionDecision } from '@tangle-network/agent-eval'\nimport {\n type CampaignStorage,\n createRunCostLedger,\n fsCampaignStorage,\n openSearchLedger,\n type SearchArtifactRef,\n type SearchClaim,\n type SearchClaimVerification,\n type SearchStateView,\n searchClaimDecision,\n verifySearchClaim,\n} from '@tangle-network/agent-eval/campaign'\nimport { type ExperimentSpec, sealExperiment } from '@tangle-network/agent-eval/experiment'\nimport {\n type AgentProfile,\n agentProfileSchema,\n canonicalAgentProfileDigest,\n} from '@tangle-network/agent-interface'\nimport { immutableCandidateValue } from '../candidate-execution/digest'\nimport { ConfigError } from '../errors'\nimport type { ImproveCost, SearchPromotion } from './improve-types'\n\n/** What Runtime decided about a closed search. */\ninterface SearchShipDecision {\n decision: 'ship' | 'hold'\n /** The claim's reason, the Runtime rule that held a statistical ship, and any\n * cost bound the decision relied on. */\n reason: string\n /** The shipped finalist's test delta against the root, when the claim tested it. */\n lift?: number\n liftInterval?: { low: number; high: number }\n /** Present exactly when `decision` is `ship`: the sealed claim and Eval's\n * paired decision, ready for `SuperviseRegistry.profiles` beside the shipped\n * profile. */\n promotion?: SearchPromotion\n}\n\n/**\n * A search's cost as `ImproveCost`: the ledger's summary, plus the bound on the\n * calls whose cost is unknown when each declared a maximum before it ran. Those\n * are calls that failed with no receipt, or that a killed process left pending\n * and a restart settled unknown. Each counts at its maximum, the same bound the\n * ledger enforces its ceiling with.\n */\nexport function improveSearchCost(ledger: CostLedgerHandle): ImproveCost {\n const summary = ledger.summary()\n const cost: ImproveCost = {\n totalCostUsd: summary.totalCostUsd,\n accountingComplete: summary.accountingComplete,\n incompleteReasons: [...summary.incompleteReasons],\n }\n if (summary.accountingComplete || summary.pendingCalls > 0) return cost\n let unknownCalls = 0\n let unknownMaximumUsd = 0\n for (const receipt of ledger.list()) {\n if (receipt.costUnknown) {\n if (receipt.maximumCostUsd === undefined) return cost\n unknownCalls += 1\n unknownMaximumUsd += receipt.maximumCostUsd\n } else if (\n receipt.usageUnknown ||\n (receipt.maximumCostUsd !== undefined && receipt.costUsd > receipt.maximumCostUsd)\n ) {\n // Unknown usage on a priced call, or a call above its own maximum, is not\n // a bounded unknown: the accounting stays incomplete.\n return cost\n }\n }\n if (unknownCalls === 0) return cost\n return {\n ...cost,\n costBound: {\n unknownCalls,\n unknownMaximumUsd,\n totalMaximumUsd: summary.totalCostUsd + unknownMaximumUsd,\n },\n }\n}\n\n/** Runtime's ship rule over the kernel's statistical claim (design §6.5 step 5), shared by\n * `searchMethod` and `runStrategyEvolution`. */\nexport function runtimeShipDecision(input: {\n claim: SearchClaim\n verified: boolean\n cost: Pick<ImproveCost, 'accountingComplete' | 'costBound'>\n costCeiling: number | undefined\n lowerBound: number | null\n minimumLift: number\n}): { decision: 'ship' | 'hold'; reason: string } {\n const { claim, cost, costCeiling } = input\n if (claim.decision !== 'ship') return { decision: 'hold', reason: claim.reason }\n if (!input.verified) {\n return {\n decision: 'hold',\n reason:\n 'the claim shipped, but it does not re-derive from the ledger under this rule revision',\n }\n }\n const bound = cost.accountingComplete ? undefined : cost.costBound\n if (!cost.accountingComplete && bound === undefined) {\n return {\n decision: 'hold',\n reason: 'the claim shipped, but the search cost accounting is incomplete',\n }\n }\n if (bound && costCeiling !== undefined && bound.totalMaximumUsd > costCeiling) {\n return {\n decision: 'hold',\n reason: `the claim shipped, but ${bound.unknownCalls} call(s) of unknown cost, counted at their declared maximum, put the search at up to $${dollars(bound.totalMaximumUsd)}, above its $${dollars(costCeiling)} ceiling`,\n }\n }\n if (input.lowerBound === null || !(input.lowerBound > input.minimumLift)) {\n return {\n decision: 'hold',\n reason: `the claim shipped, but its test lower bound ${input.lowerBound} does not exceed minimumLift ${input.minimumLift}`,\n }\n }\n return {\n decision: 'ship',\n reason: bound\n ? `${claim.reason}; ${bound.unknownCalls} call(s) ended with no receipt and count at their declared maximum, $${dollars(bound.unknownMaximumUsd)}, so the search cost at most $${dollars(bound.totalMaximumUsd)}${costCeiling === undefined ? '' : ` of its $${dollars(costCeiling)} ceiling`}`\n : claim.reason,\n }\n}\n\n/**\n * Decide a closed search: the ship rule, and the promotion when it ships.\n * `profileOf` returns the exact profile a node holds.\n */\nexport async function decideClosedSearch(input: {\n state: SearchStateView\n claim: SearchClaim\n claimVerification: SearchClaimVerification\n cost: ImproveCost\n costCeiling: number | undefined\n minimumLift: number\n profileOf: (nodeId: string) => AgentProfile\n}): Promise<SearchShipDecision> {\n const { claim, state } = input\n const shipped = claim.finalists.find(\n (finalist) => finalist.nodeId === claim.selected && finalist.test !== null,\n )\n const ruled = runtimeShipDecision({\n claim,\n verified: input.claimVerification.status === 'verified',\n cost: input.cost,\n costCeiling: input.costCeiling,\n lowerBound: shipped?.test?.interval[0] ?? null,\n minimumLift: input.minimumLift,\n })\n const lift = shipped?.test\n ? {\n lift: shipped.test.delta,\n liftInterval: { low: shipped.test.interval[0], high: shipped.test.interval[1] },\n }\n : {}\n if (ruled.decision !== 'ship') return { ...ruled, ...lift }\n const promotion = await searchPromotion(state, claim, input.profileOf)\n if ('refused' in promotion) {\n return { decision: 'hold', reason: `${ruled.reason}; held: ${promotion.refused}`, ...lift }\n }\n return { ...ruled, ...lift, promotion }\n}\n\n/**\n * The claim as a profiles-table promotion. The sealed experiment states the\n * claim's design: the root as control and every finalist the claim tested as a\n * treatment, each by its exact profile digest, fixed before any test cell ran.\n * The decision is Eval's paired decision for the selected finalist, made again\n * from the ledger by `searchClaimDecision`. The seal is dated by the search's\n * close, so the same ledger always yields the same promotion.\n */\nasync function searchPromotion(\n state: SearchStateView,\n claim: SearchClaim,\n profileOf: (nodeId: string) => AgentProfile,\n): Promise<SearchPromotion | { refused: string }> {\n const header = state.header\n const closed = state.closed\n const root = state.rootNodeId\n const selected = claim.selected\n if (!header || !closed || root === null || selected === null) {\n return { refused: 'the ledger holds no closed claim with a selected finalist' }\n }\n const decision: PairedPromotionDecision | null = searchClaimDecision(state, selected)\n if (decision === null || decision.promote !== true) {\n return { refused: `Eval's paired decision for ${selected} does not promote` }\n }\n if (!('adequate' in claim.power)) {\n return { refused: 'the claim tested its finalists without a known power' }\n }\n const tested = claim.finalists.filter((finalist) => finalist.test !== null)\n const estimator = claim.power.estimator\n let outcome: ExperimentSpec['outcome']\n if (estimator.kind === 'binary') {\n outcome = { kind: 'binary', pass: `the per-unit test mean equals ${estimator.scale}` }\n } else {\n // A campaign judge's composite is on [0, 1] by convention; a score off that\n // scale has no registered bound, so the claim cannot be stated as a bounded score.\n const scores = [root, ...tested.map((finalist) => finalist.nodeId)].flatMap((nodeId) =>\n state.unitScores(nodeId, 'test').map((unit) => unit.mean),\n )\n if (scores.some((score) => score < 0 || score > 1)) {\n return { refused: \"a test score leaves the campaign's [0, 1] score scale\" }\n }\n outcome = {\n kind: 'bounded-score',\n min: 0,\n max: 1,\n orientation:\n header.objective.direction === 'maximize' ? 'higher-is-better' : 'lower-is-better',\n }\n }\n const arm = (nodeId: string, role: 'control' | 'treatment') => ({\n id: nodeId,\n role,\n profileDigest: canonicalAgentProfileDigest(profileOf(nodeId)),\n pins: { searchId: state.searchId, nodeId },\n })\n const testUnits = new Set(header.splits.test.tasks.map((task) => task.unitId)).size\n const experiment = await sealExperiment(\n {\n id: `${state.searchId}.claim`,\n claim: header.objective.claim,\n hypothesis: `Each finalist of search ${state.searchId} beats the root on its ${testUnits} sealed test units at confidence ${tested[0]?.test?.confidence ?? claim.confidence}, by Eval's paired decision (${claim.rule.uri} ${claim.rule.revision}); the claim fixed these arms before any test cell ran.`,\n arms: [arm(root, 'control'), ...tested.map((finalist) => arm(finalist.nodeId, 'treatment'))],\n outcome,\n decision: { kind: 'report-only', estimands: [], intervals: [], perRow: [] },\n seed: header.policy.seed,\n },\n { sealedAt: closed.occurredAt },\n )\n return { experiment, decision }\n}\n\nexport interface DecideSearchImprovementOptions {\n /** The closed search's directory, `<runDir>/search/<searchId>`: its\n * `ledger.jsonl`, `blobs/` and, unless `costLedger` is given, `cost-ledger.jsonl`. */\n searchDir: string\n /** The `minimumLift` the search ran with. Default 0, as in `improve()`. */\n minimumLift?: number\n /** The cost ledger the search recorded into, when `improve()` was given one. */\n costLedger?: CostLedgerHandle\n storage?: CampaignStorage\n}\n\nexport interface SearchImprovementDecision extends SearchShipDecision {\n searchId: string\n claim: SearchClaim\n claimVerification: SearchClaimVerification\n cost: ImproveCost\n /** The root's exact profile. */\n baseline: AgentProfile\n /** The profile the search keeps: the shipped finalist, else the claim's\n * selection, else the root. */\n candidate: AgentProfile\n}\n\n/**\n * Decide a closed search from its directory, under the current ship rule, with\n * no model call: the claim verified from the ledger, the cost from its cost\n * ledger, and the promotion when it ships. Use it to cite a finished search as\n * a registry promotion, or to re-decide one that an earlier rule held.\n */\nexport async function decideSearchImprovement(\n options: DecideSearchImprovementOptions,\n): Promise<SearchImprovementDecision> {\n const storage = options.storage ?? fsCampaignStorage()\n const minimumLift = options.minimumLift ?? 0\n if (!Number.isFinite(minimumLift) || minimumLift < 0) {\n throw new ConfigError(\n 'decideSearchImprovement(): minimumLift must be a finite number of at least 0',\n )\n }\n const ledgerPath = join(options.searchDir, 'ledger.jsonl')\n const text = storage.read(ledgerPath)\n if (text === undefined) {\n throw new ConfigError(`decideSearchImprovement(): no search ledger at ${ledgerPath}`)\n }\n const first = text.slice(0, text.indexOf('\\n'))\n const searchId = (JSON.parse(first) as { searchId?: unknown }).searchId\n if (typeof searchId !== 'string') {\n throw new ConfigError(`decideSearchImprovement(): ${ledgerPath} names no searchId`)\n }\n const ledger =\n storage.kind === 'filesystem'\n ? openSearchLedger({ path: ledgerPath, searchId })\n : openSearchLedger({ path: ledgerPath, searchId, store: storage })\n const state = await ledger.state()\n const claim = state.closed?.claim\n if (!state.closed || !claim) {\n throw new ConfigError(\n `decideSearchImprovement(): search ${searchId} is ${state.closed ? 'closed without a claim' : 'still open'}`,\n )\n }\n const costLedger =\n options.costLedger ??\n createRunCostLedger({ storage, runDir: options.searchDir, ensureRunDir: false })\n const profileOf = searchProfileReader(state, storage, dirname(ledgerPath))\n const cost = improveSearchCost(costLedger)\n const claimVerification = verifySearchClaim(state)!\n const decided = await decideClosedSearch({\n state,\n claim,\n claimVerification,\n cost,\n costCeiling: state.header?.budget.maxUsd ?? undefined,\n minimumLift,\n profileOf,\n })\n const root = state.rootNodeId!\n return {\n searchId,\n claim,\n claimVerification,\n cost,\n ...decided,\n baseline: profileOf(root),\n candidate: profileOf(claim.selected ?? root),\n }\n}\n\n/** Each node's exact profile from the search's blob store, checked against\n * the blob's content address and the node's profile digest. */\nfunction searchProfileReader(\n state: SearchStateView,\n storage: CampaignStorage,\n dir: string,\n): (nodeId: string) => AgentProfile {\n const read = new Map<string, AgentProfile>()\n return (nodeId) => {\n const known = read.get(nodeId)\n if (known) return known\n const node = state.node(nodeId)\n if (!node) throw new ConfigError(`decideSearchImprovement(): no node ${nodeId}`)\n const stored = readBlob(storage, dir, node.artifact) as { kind?: unknown; profile?: unknown }\n const parsed = agentProfileSchema.safeParse(stored.profile)\n if (stored.kind !== 'agent-profile' || !parsed.success) {\n throw new ConfigError(`decideSearchImprovement(): node ${nodeId} holds no AgentProfile`)\n }\n const profile = immutableCandidateValue(parsed.data) as AgentProfile\n if (canonicalAgentProfileDigest(profile) !== node.artifactDigest) {\n throw new ConfigError(\n `decideSearchImprovement(): node ${nodeId}'s profile does not match its digest ${node.artifactDigest}`,\n )\n }\n read.set(nodeId, profile)\n return profile\n }\n}\n\n/** A blob the search stored, read from the blob directory beside its ledger,\n * whatever directory the ledger was written in, and checked against its digest. */\nfunction readBlob(storage: CampaignStorage, dir: string, ref: SearchArtifactRef): unknown {\n const hex = ref.sha256.slice('sha256:'.length)\n const path = join(dir, 'blobs', `${hex}.json`)\n const text = storage.read(path)\n if (text === undefined) throw new ConfigError(`decideSearchImprovement(): missing blob ${path}`)\n if (createHash('sha256').update(text, 'utf8').digest('hex') !== hex) {\n throw new ConfigError(`decideSearchImprovement(): blob ${path} does not match its digest`)\n }\n return JSON.parse(text)\n}\n\nfunction dollars(value: number): string {\n return value.toFixed(value < 1 ? 4 : 2)\n}\n","import type { SharedBoxHandle, SharedBoxProcess } from './shared-box-worker'\nimport { sleep } from './util'\n\n/**\n * Attempts for one Sandbox API call that failed on the way to the box.\n *\n * Every call re-verifies the API key with the platform, and a burst of workers makes that check\n * time out: 8 of 64 workers failed with `502 platform_unavailable` (reason `platform_timeout`) in\n * one burst, and 3 more lost their transcript enumeration the same way. The check\n * refuses the request before it reaches the box, so repeating it is safe; five attempts over about\n * fifteen seconds rode out every such failure measured.\n */\nconst TRANSIENT_ATTEMPTS = 5\n\nexport const TRANSIENT_BASE_DELAY_MS = 1_000\n\n/** A failure that a repeated request can change: the platform, the gateway or the network. */\nexport function isTransientSandboxFailure(error: unknown): boolean {\n if (error === null || typeof error !== 'object') return false\n const record = error as { status?: unknown; code?: unknown; name?: unknown; message?: unknown }\n if (\n typeof record.status === 'number' &&\n [408, 425, 429, 500, 502, 503, 504].includes(record.status)\n ) {\n return true\n }\n const text = `${String(record.code ?? '')} ${String(record.name ?? '')} ${String(record.message ?? '')}`\n return /platform_unavailable|platform_timeout|platform_unreachable|fetch failed|ECONNRESET|ETIMEDOUT|EAI_AGAIN|socket hang up|UND_ERR|bad gateway|gateway timeout/iu.test(\n text,\n )\n}\n\nexport async function transientRetry<T>(\n operation: (attempt: number) => Promise<T>,\n options: { signal?: AbortSignal; delayMs?: number } = {},\n): Promise<T> {\n const delayMs = options.delayMs ?? TRANSIENT_BASE_DELAY_MS\n for (let attempt = 1; ; attempt += 1) {\n try {\n return await operation(attempt)\n } catch (error) {\n if (attempt >= TRANSIENT_ATTEMPTS || !isTransientSandboxFailure(error)) throw error\n options.signal?.throwIfAborted()\n await sleep(delayMs * 2 ** (attempt - 1), options.signal)\n }\n }\n}\n\n/**\n * The Sandbox calls one worker makes, each repeated on a transient failure.\n *\n * A launch is repeated only after the pool confirms the box did not start it: a failed request\n * may have reached the box before its answer was lost, so the repeat first looks for a process\n * in the worker's own directory that this worker did not start yet, and adopts it. A process log\n * that breaks mid-stream is read again from the start, because the box replays a process's\n * buffered output, and the part already delivered is skipped.\n */\nexport function resilientBox(box: SharedBoxHandle, delayMs: number) {\n const retry = <T>(operation: () => Promise<T>) => transientRetry(operation, { delayMs })\n return {\n id: box.id,\n exec: (command: string, options?: { timeoutMs?: number }) =>\n retry(() => box.exec(command, options)),\n fs: {\n read: (path: string) => retry(() => box.fs.read(path)),\n write: (path: string, content: string) => retry(() => box.fs.write(path, content)),\n },\n async spawnInDirectory(\n executable: string,\n args: readonly string[],\n options: { cwd: string; env?: Record<string, string>; timeoutMs?: number },\n known: ReadonlySet<number>,\n ): Promise<SharedBoxProcess> {\n return await transientRetry(\n async (attempt) => {\n if (attempt > 1) {\n const listed = await box.process.list()\n const launched = listed.find(\n (entry) =>\n entry.cwd === options.cwd && entry.command === executable && !known.has(entry.pid),\n )\n const adopted = launched === undefined ? null : await box.process.get(launched.pid)\n if (adopted !== null) return adopted\n }\n return await box.process.spawnExact(executable, args, options)\n },\n { delayMs },\n )\n },\n async wait(process: SharedBoxProcess): Promise<number> {\n return await retry(async () => {\n try {\n return await process.wait()\n } catch (error) {\n if (!isTransientSandboxFailure(error)) throw error\n const again = await box.process.get(process.pid)\n if (again === null) throw error\n return await again.wait()\n }\n })\n },\n async *output(process: SharedBoxProcess, stream: 'stdout' | 'stderr'): AsyncGenerator<string> {\n let delivered = 0\n let source: SharedBoxProcess = process\n for (let attempt = 1; ; attempt += 1) {\n let seen = 0\n try {\n for await (const chunk of source[stream]()) {\n const fresh =\n seen + chunk.length <= delivered ? '' : chunk.slice(Math.max(0, delivered - seen))\n seen += chunk.length\n if (fresh.length > 0) {\n delivered += fresh.length\n yield fresh\n }\n }\n return\n } catch (error) {\n if (attempt >= TRANSIENT_ATTEMPTS || !isTransientSandboxFailure(error)) throw error\n await sleep(delayMs * 2 ** (attempt - 1))\n source = (await retry(() => box.process.get(process.pid))) ?? source\n }\n }\n },\n delete: () => retry(() => box.delete()),\n }\n}\n","import { randomUUID } from 'node:crypto'\nimport {\n type AgentProfile,\n agentProfileSchema,\n canonicalAgentProfileDigest,\n canonicalCandidateDigest,\n} from '@tangle-network/agent-interface'\nimport type {\n AgentEnvironment,\n AgentEnvironmentCapabilities,\n AgentEnvironmentEvent,\n AgentTurnInput,\n CreateAgentEnvironmentInput,\n} from '@tangle-network/agent-interface/environment-provider'\nimport { harnessSystemPromptIntents } from '@tangle-network/agent-interface/harness-capabilities'\nimport { materializeProfile } from '@tangle-network/agent-profile-materialize'\nimport type { CreateSandboxOptions, Process, PromptOptions } from '@tangle-network/sandbox'\nimport { ValidationError } from '../errors'\nimport { harnessInvocation } from '../mcp/local-harness-invocation'\nimport { LEAF_CONTINUATION_TASK } from './environment-provider/provider-executor-lifecycle'\nimport type { BoxLease } from './shared-box'\nimport { resilientBox } from './shared-box-retry'\nimport { concreteProfileModel, profileProviderModel } from './supervise/model-policy'\nimport {\n type UnavailablePausePolicy,\n unavailablePauseMs,\n unavailableSignalOfFailure,\n} from './supervise/upstream-unavailable'\nimport { promptFromAgentTurnInput, promptOptionsFromAgentTurnInput } from './turn-input'\nimport { sleep } from './util'\n\n/** The SDK's per-turn model routing config (`PromptOptions['backend']['model']`), whose\n * package-root export name varies across sandbox releases — derived here instead. */\ntype TurnModelRouting = NonNullable<PromptOptions['backend']>['model']\n\nexport const HARNESS = 'opencode'\n\nexport const SHARED_PROVIDER_NAME = 'tangle-shared-box'\n\nconst DEFAULT_EXEC_TIMEOUT_MS = 120_000\n\n/** The request header the router records as a usage row's `clientName`. */\nexport const ROUTER_CLIENT_HEADER = 'x-tangle-client'\n\n/**\n * The router client name of the worker that runs supervised node `nodeId`.\n *\n * The node id is already in the spawn journal, so a keeper joins a router row to a node without\n * a new record: the row whose `clientName` is `agent-runtime-node/<nodeId>` is that node's spend.\n */\nexport function sharedWorkerClientName(nodeId: string): string {\n // A header value the router stores as sent: visible ASCII, no spaces.\n if (!/^[!-~]+$/u.test(nodeId)) {\n throw new ValidationError('sharedWorkerClientName: a node id must be visible ASCII')\n }\n return `agent-runtime-node/${nodeId}`\n}\n\n/** The Sandbox box surface a shared box uses. The Sandbox SDK's `SandboxInstance` satisfies it. */\nexport interface SharedBoxHandle {\n readonly id: string\n exec(\n command: string,\n options?: { timeoutMs?: number },\n ): Promise<{ exitCode?: number | null; stdout?: string; stderr?: string }>\n readonly fs: {\n read(path: string): Promise<string>\n write(path: string, content: string): Promise<unknown>\n }\n readonly process: {\n spawnExact(\n executable: string,\n args: readonly string[],\n options?: { cwd?: string; env?: Record<string, string>; timeoutMs?: number },\n ): Promise<SharedBoxProcess>\n list(): Promise<ReadonlyArray<{ pid: number; command?: string; cwd?: string }>>\n get(pid: number): Promise<SharedBoxProcess | null>\n }\n delete(): Promise<unknown>\n}\n\n/** One process in a shared box, as the Sandbox SDK's process manager returns it. */\nexport interface SharedBoxProcess extends Pick<Process, 'pid' | 'wait' | 'stdout' | 'stderr'> {\n kill(signal?: 'SIGTERM' | 'SIGKILL', options?: { tree?: boolean }): Promise<void>\n}\n\n/**\n * Why a shared box cannot carry `profile`, or `undefined` when it can.\n *\n * A shared box carries a profile whose whole behavior reaches an opencode process through its own\n * working directory, its own configuration and the box's own model credential. Everything else\n * keeps a dedicated box: another harness, a model the box credential cannot reach, a replaced\n * system prompt, MCP servers, connections, hooks, subagents, extensions, tool grants, and any\n * resource the materializer does not lower into the worker's directory.\n */\nexport function sharedBoxRefusal(profile: AgentProfile): string | undefined {\n if (profile.model?.metadata?.credentialSource !== undefined) {\n return 'model.metadata.credentialSource requires a dedicated provider'\n }\n if (profile.harness !== HARNESS) return `harness ${String(profile.harness)} is not ${HARNESS}`\n const model = concreteProfileModel(profile)\n if (model === undefined) return 'profile names no concrete model'\n if (profile.model?.provider === undefined) return 'profile names no model provider'\n if (profile.model?.reasoningEffort !== undefined) {\n const invocation = tryInvocation(profile)\n if (invocation === undefined) return 'model.reasoningEffort has no opencode variant'\n }\n if (profile.prompt?.systemPrompt !== undefined)\n return 'prompt.systemPrompt replaces a system prompt'\n for (const field of [\n 'mcp',\n 'connections',\n 'hooks',\n 'subagents',\n 'extensions',\n 'confidential',\n 'modes',\n ] as const) {\n if ((profile as Record<string, unknown>)[field] !== undefined)\n return `profile declares ${field}`\n }\n if (profile.tools !== undefined && Object.keys(profile.tools).length > 0) {\n return 'profile grants tools'\n }\n const resources = profile.resources\n if (resources !== undefined) {\n for (const field of ['skills', 'agents', 'commands', 'tools'] as const) {\n if ((resources as Record<string, unknown>)[field] !== undefined) {\n return `profile declares resources.${field}`\n }\n }\n for (const file of resources.files ?? []) {\n if (file.resource.kind !== 'inline') return `resource file ${file.path} is not inline`\n }\n if (\n resources.instructions !== undefined &&\n typeof resources.instructions !== 'string' &&\n resources.instructions.kind !== 'inline'\n ) {\n return 'resources.instructions is not inline'\n }\n }\n let plan: ReturnType<typeof materializeProfile>\n try {\n plan = materializeProfile(profile, HARNESS)\n } catch (error) {\n return `opencode materialization failed: ${error instanceof Error ? error.message : String(error)}`\n }\n if (plan.unsupported.length > 0) {\n return `opencode cannot carry ${plan.unsupported.map((row) => row.dimension).join(', ')}`\n }\n if (Object.keys(plan.env).length > 0 || plan.flags.length > 0) {\n return 'profile needs launch environment or flags'\n }\n for (const file of plan.files) {\n if (file.root === 'agent') return `profile writes ${file.relPath} into the harness home`\n if ((file.secretSlots?.length ?? 0) > 0) return `profile file ${file.relPath} carries a secret`\n if (isUnsafeRelativePath(file.relPath))\n return `profile file ${file.relPath} leaves its directory`\n }\n return undefined\n}\n\nfunction tryInvocation(profile: AgentProfile): string[] | undefined {\n try {\n return harnessInvocation(HARNESS, invocationProfile(profile), 'probe').args\n } catch {\n return undefined\n }\n}\n\n/**\n * The profile the invocation table reads. The prompt reaches opencode through its configuration\n * and the model through the provider this placement declares, so only the reasoning effort is\n * left for the table to lower into `--variant`.\n */\nfunction invocationProfile(profile: AgentProfile): AgentProfile {\n const { prompt: _prompt, model, ...rest } = profile\n return {\n ...rest,\n ...(model?.reasoningEffort === undefined\n ? {}\n : { model: { reasoningEffort: model.reasoningEffort } }),\n } as AgentProfile\n}\n\nexport function isUnsafeRelativePath(path: string): boolean {\n return (\n path.length === 0 ||\n path.startsWith('/') ||\n path.split('/').some((segment) => segment === '..' || segment === '')\n )\n}\n\nexport function sharedBoxCapabilities(): AgentEnvironmentCapabilities {\n return {\n profile: {\n namedProfiles: false,\n systemPrompt: { ...harnessSystemPromptIntents(HARNESS), replace: false },\n instructions: true,\n tools: false,\n permissions: true,\n mcp: false,\n subagents: false,\n resources: { files: true, instructions: true },\n runtimeUpdate: false,\n validation: false,\n },\n streaming: { live: true, replay: false, detach: false, turnIdempotency: false },\n sessions: { continue: false, list: false, messages: false },\n workspace: { read: true, write: true, exec: true, git: false, upload: false, download: false },\n branching: { checkpoint: false, fork: false },\n placement: true,\n usage: true,\n confidential: false,\n }\n}\n\nexport function parseSharedWorkerProfile(input: CreateAgentEnvironmentInput): AgentProfile {\n const parsed = agentProfileSchema.safeParse(input.profile)\n if (!parsed.success) {\n throw new ValidationError('sharedBoxPlacement: an exact AgentProfile is required at create')\n }\n return parsed.data\n}\n\n/**\n * A worker create carries only what a slot in a shared box can honor. Box-level settings belong\n * to the placement's own box options, and a per-worker request for them is refused rather than\n * dropped: a worker that asked for an environment variable, a repository or its own resources\n * would otherwise run without them and report nothing.\n */\nexport function assertWorkerCreateInput(input: CreateAgentEnvironmentInput): void {\n for (const key of [\n 'idempotencyKey',\n 'workspace',\n 'resources',\n 'runtimeAttachments',\n 'requestedId',\n 'egress',\n 'billingOwner',\n ] as const) {\n if (input[key] !== undefined) {\n throw new ValidationError(`sharedBoxPlacement: a shared worker cannot set ${key}`)\n }\n }\n if (input.env !== undefined && Object.keys(input.env).length > 0) {\n throw new ValidationError('sharedBoxPlacement: a shared worker cannot set env')\n }\n if (input.secrets !== undefined && Object.keys(input.secrets).length > 0) {\n throw new ValidationError('sharedBoxPlacement: a shared worker cannot request secrets')\n }\n if (input.backend !== undefined && input.backend !== HARNESS) {\n throw new ValidationError(`sharedBoxPlacement: backend ${input.backend} is not ${HARNESS}`)\n }\n for (const key of Object.keys(input.providerOptions ?? {})) {\n if (key !== 'sandboxCreateOptions') {\n throw new ValidationError(\n `sharedBoxPlacement: a shared worker cannot set providerOptions.${key}`,\n )\n }\n }\n // The round engine projects only its profile and annotations through this input.\n // Every physical or security control must stay on the owning box placement.\n const box = input.providerOptions?.sandboxCreateOptions\n if (box === undefined) return\n if (box === null || typeof box !== 'object' || Array.isArray(box)) {\n throw new ValidationError('sharedBoxPlacement: sandboxCreateOptions must be an object')\n }\n for (const key of Object.keys(box)) {\n if (!['backend', 'metadata', 'name'].includes(key)) {\n throw new ValidationError(`sharedBoxPlacement: a shared worker cannot set ${key}`)\n }\n }\n const projected = box as Pick<CreateSandboxOptions, 'backend' | 'metadata' | 'name'>\n if (projected.name !== undefined && projected.name !== input.name) {\n throw new ValidationError('sharedBoxPlacement: projected name must match the worker name')\n }\n if (\n projected.metadata !== undefined &&\n (input.metadata === undefined ||\n canonicalCandidateDigest(projected.metadata) !== canonicalCandidateDigest(input.metadata))\n ) {\n throw new ValidationError('sharedBoxPlacement: projected metadata must match worker metadata')\n }\n const backend = projected.backend\n if (backend?.type !== undefined && backend.type !== HARNESS) {\n throw new ValidationError(`sharedBoxPlacement: backend ${backend.type} is not ${HARNESS}`)\n }\n for (const key of Object.keys(backend ?? {})) {\n if (key !== 'type' && key !== 'profile') {\n throw new ValidationError(`sharedBoxPlacement: a shared worker cannot set backend.${key}`)\n }\n }\n if (\n backend?.profile !== undefined &&\n canonicalAgentProfileDigest(agentProfileSchema.parse(backend.profile)) !==\n canonicalAgentProfileDigest(parseSharedWorkerProfile(input))\n ) {\n throw new ValidationError(\n 'sharedBoxPlacement: projected profile must match the exact worker profile',\n )\n }\n}\n\n// ── One worker ───────────────────────────────────────────────────────────────────────────────\n\ninterface WorkerPaths {\n readonly dir: string\n readonly home: string\n readonly cache: string\n}\n\n/** The environment one worker's processes see: its own directory, HOME and XDG roots. */\nfunction workerEnv(paths: WorkerPaths): string[] {\n return [\n // A worker directory sits under the sidecar's workspace, and opencode merges every\n // project configuration it finds above its directory. Without this, a worker loads the\n // box's own opencode.json and instructions.\n 'OPENCODE_DISABLE_PROJECT_CONFIG=1',\n `OPENCODE_CONFIG_DIR=${paths.dir}/.opencode`,\n // opencode takes its project directory from PWD, not from the process working directory.\n `PWD=${paths.dir}`,\n `HOME=${paths.home}`,\n `XDG_DATA_HOME=${paths.home}/.local/share`,\n `XDG_CONFIG_HOME=${paths.home}/.config`,\n `XDG_STATE_HOME=${paths.home}/.local/state`,\n // The package cache holds downloaded model-provider packages and no session state, so the\n // workers of one box share it and download each package once.\n `XDG_CACHE_HOME=${paths.cache}`,\n ]\n}\n\nexport async function createWorker(\n lease: BoxLease,\n root: string,\n createProfile: AgentProfile,\n placement: {\n readonly retryDelayMs: number\n readonly clientName: string | undefined\n readonly name?: string\n readonly metadata?: Record<string, unknown>\n readonly unavailablePause: UnavailablePausePolicy | false\n },\n): Promise<AgentEnvironment> {\n const { clientName, unavailablePause } = placement\n const box = resilientBox(lease.box, placement.retryDelayMs)\n const workerId = `w-${randomUUID()}`\n const paths: WorkerPaths = {\n dir: `${root}/${workerId}`,\n home: `${root}/${workerId}/.home`,\n cache: `${root}/.cache`,\n }\n const made = await box.exec(`mkdir -p '${paths.home}' '${paths.cache}'`, {\n timeoutMs: DEFAULT_EXEC_TIMEOUT_MS,\n })\n if ((made.exitCode ?? 1) !== 0) {\n throw new Error(`sharedBoxPlacement: could not create ${paths.dir}: ${made.stderr ?? ''}`)\n }\n const env = workerEnv(paths)\n let running: SharedBoxProcess | undefined\n // A turn stays active through a pause, when no process runs.\n let turnActive = false\n let released = false\n\n // Every process this worker started, so a repeated launch never adopts one of them.\n const started = new Set<number>()\n const run = async (\n args: readonly string[],\n timeoutMs: number,\n extraEnv?: Record<string, string>,\n ): Promise<SharedBoxProcess> => {\n const process = await box.spawnInDirectory(\n '/usr/bin/env',\n [...env, ...args],\n {\n cwd: paths.dir,\n ...(extraEnv === undefined ? {} : { env: extraEnv }),\n timeoutMs,\n },\n started,\n )\n started.add(process.pid)\n return process\n }\n\n const collect = async (\n process: SharedBoxProcess,\n ): Promise<{ exitCode: number; stdout: string; stderr: string }> => {\n const [stdout, stderr, exitCode] = await Promise.all([\n drain(box.output(process, 'stdout')),\n drain(box.output(process, 'stderr')),\n box.wait(process),\n ])\n return { exitCode, stdout, stderr }\n }\n\n const resolvePath = (path: string): string => {\n if (path.startsWith('/')) return path\n if (isUnsafeRelativePath(path)) {\n throw new ValidationError(`sharedBoxPlacement: path ${path} leaves the worker directory`)\n }\n return `${paths.dir}/${path}`\n }\n\n /**\n * One turn: one or more opencode runs of the same session. The first runs `message`; a later run\n * continues the session after the model provider refused a run for capacity.\n */\n async function* turn(\n message: string,\n turnProfile: AgentProfile,\n /** The SDK's per-turn options (the 0.60.41 PromptOptions: signal, timeoutMs,\n * backend, per-turn model, secret-profile receipts). The turn reads only the\n * fields it has always read; the wider type is what `machine.prompt` takes. */\n options: PromptOptions | undefined,\n ): AsyncGenerator<AgentEnvironmentEvent> {\n const signal = options?.signal\n const timeoutMs = options?.timeoutMs ?? 0\n const turnDeadline = timeoutMs > 0 ? Date.now() + timeoutMs : undefined\n let sessionId: string | undefined\n // Every harness subagent any run of this turn started, a run the provider refused included.\n const subagents = new Set<string>()\n let refusalsInARow = 0\n let prompt = message\n for (let invocation = 1; ; invocation += 1) {\n const launch = await materializeWorker(\n box,\n paths,\n turnProfile,\n prompt,\n options?.backend?.model,\n clientName,\n sessionId,\n )\n signal?.throwIfAborted()\n const remainingMs = turnDeadline === undefined ? 0 : Math.max(1, turnDeadline - Date.now())\n const process = await run(launch.args, remainingMs, {\n OPENCODE_CONFIG_CONTENT: launch.config,\n })\n running = process\n const onAbort = () => {\n void process.kill('SIGKILL', { tree: true }).catch(() => undefined)\n }\n signal?.addEventListener('abort', onAbort, { once: true })\n const stderr = drain(box.output(process, 'stderr'))\n const lines = lineReader()\n const parsed = createOpencodeEventParser(launch.model)\n let exitCode: number\n let errorText: string\n try {\n for await (const chunk of box.output(process, 'stdout')) {\n for (const line of lines.push(chunk)) yield* parsed.line(line)\n }\n for (const line of lines.end()) yield* parsed.line(line)\n exitCode = await box.wait(process)\n errorText = (await stderr).slice(-4_000)\n } finally {\n signal?.removeEventListener('abort', onAbort)\n running = undefined\n }\n sessionId = parsed.sessionId() ?? sessionId\n for (const child of parsed.subagentSessionIds()) subagents.add(child)\n const failure = parsed.failure(exitCode, errorText)\n const refusal =\n failure === undefined || unavailablePause === false || signal?.aborted\n ? undefined\n : unavailableSignalOfFailure({ error: failure })\n // The same rule a driver and a dedicated leaf follow: doubling per refusal in a row,\n // restarting after a refused run that still did work.\n refusalsInARow = parsed.madeProgress() ? 1 : refusalsInARow + 1\n const pauseMs =\n refusal === undefined || unavailablePause === false\n ? 0\n : unavailablePauseMs(refusalsInARow, unavailablePause)\n if (\n refusal === undefined ||\n (turnDeadline !== undefined && Date.now() + pauseMs >= turnDeadline)\n ) {\n if (sessionId !== undefined) await exportSession(run, collect, paths, sessionId)\n // Each harness subagent ran in a session of its own, which the parent's export does not\n // hold: without these, its steps are in no record (#1264).\n for (const child of subagents) {\n if (child !== sessionId) await exportSession(run, collect, paths, child)\n }\n signal?.throwIfAborted()\n yield* parsed.finish(exitCode, errorText, invocation)\n return\n }\n await sleep(pauseMs, signal)\n signal?.throwIfAborted()\n if (released) throw new ValidationError('sharedBoxPlacement: this worker was released')\n // A run that never opened a session did no work, so its task runs again whole.\n prompt = sessionId === undefined ? message : LEAF_CONTINUATION_TASK\n }\n }\n\n const worker: AgentEnvironment = {\n id: `${box.id}/${workerId}`,\n provider: SHARED_PROVIDER_NAME,\n name: placement.name ?? workerId,\n creation: 'created',\n capabilities: sharedBoxCapabilities(),\n async status() {\n return released ? 'stopped' : 'running'\n },\n metadata: { ...placement.metadata, sharedBoxId: box.id, workerId, workerDir: paths.dir },\n async *stream(input: AgentTurnInput): AsyncGenerator<AgentEnvironmentEvent> {\n const message = promptFromAgentTurnInput(input)\n if (typeof message !== 'string') {\n throw new ValidationError('sharedBoxPlacement: a shared worker requires a text prompt')\n }\n const options = promptOptionsFromAgentTurnInput(input)\n if (released) throw new ValidationError('sharedBoxPlacement: this worker was released')\n if (turnActive) {\n throw new ValidationError('sharedBoxPlacement: a worker runs one turn at a time')\n }\n const turnProfile =\n options?.backend?.profile === undefined\n ? createProfile\n : agentProfileSchema.parse(options.backend.profile)\n if (\n canonicalAgentProfileDigest(turnProfile) !== canonicalAgentProfileDigest(createProfile) &&\n sharedBoxRefusal(turnProfile) !== undefined\n ) {\n throw new ValidationError(`sharedBoxPlacement: ${sharedBoxRefusal(turnProfile)}`)\n }\n if (options?.backend?.type !== undefined && options.backend.type !== HARNESS) {\n throw new ValidationError(\n `sharedBoxPlacement: backend ${options.backend.type} is not ${HARNESS}`,\n )\n }\n turnActive = true\n try {\n yield* turn(message, turnProfile, options)\n } finally {\n turnActive = false\n }\n },\n async exec(\n command: string,\n options?: { timeoutMs?: number },\n ): Promise<{ exitCode: number; stdout: string; stderr: string }> {\n const process = await run(\n ['/bin/sh', '-c', command],\n options?.timeoutMs ?? DEFAULT_EXEC_TIMEOUT_MS,\n )\n return await collect(process)\n },\n async read(path: string): Promise<string> {\n return await box.fs.read(resolvePath(path))\n },\n async write(path: string, content: string): Promise<void> {\n await box.fs.write(resolvePath(path), content)\n },\n async placement() {\n return { kind: 'sandbox', sandboxId: box.id }\n },\n async refresh(): Promise<void> {},\n async destroy(): Promise<void> {\n if (released) return\n released = true\n try {\n await running?.kill('SIGKILL', { tree: true })\n await box.exec(`rm -rf '${paths.dir}'`, { timeoutMs: DEFAULT_EXEC_TIMEOUT_MS })\n } finally {\n await lease.release()\n }\n },\n }\n return worker\n}\n\nasync function drain(stream: AsyncIterable<string>): Promise<string> {\n let text = ''\n for await (const chunk of stream) text += chunk\n return text\n}\n\nfunction lineReader(): { push(chunk: string): string[]; end(): string[] } {\n let pending = ''\n return {\n push(chunk) {\n pending += chunk\n const lines = pending.split('\\n')\n pending = lines.pop() ?? ''\n return lines.filter((line) => line.trim().length > 0)\n },\n end() {\n const rest = pending.trim()\n pending = ''\n return rest.length > 0 ? [rest] : []\n },\n }\n}\n\n/**\n * Write the worker's materialized profile into its directory and build its launch.\n *\n * The files come from the same materializer the Sandbox sidecar uses, so a shared worker gets the\n * same instruction file, permissions and resource files a dedicated box would. The generated\n * `opencode.json` is passed as `OPENCODE_CONFIG_CONTENT` with its instruction paths made absolute,\n * because opencode resolves an instruction path in that variable against nothing.\n */\nasync function materializeWorker(\n box: ReturnType<typeof resilientBox>,\n paths: WorkerPaths,\n profile: AgentProfile,\n task: string,\n turnModel: TurnModelRouting | undefined,\n clientName: string | undefined,\n continueSession?: string,\n): Promise<{ args: string[]; config: string; model: string }> {\n const refusal = sharedBoxRefusal(profile)\n if (refusal !== undefined) throw new ValidationError(`sharedBoxPlacement: ${refusal}`)\n if (\n turnModel?.cliAuth !== undefined ||\n turnModel?.authFiles !== undefined ||\n turnModel?.authMode === 'oauth'\n ) {\n throw new ValidationError('sharedBoxPlacement: a shared worker cannot carry native credentials')\n }\n const plan = materializeProfile(profile, HARNESS)\n let generated: Record<string, unknown> = {}\n for (const file of plan.files) {\n if (file.relPath === 'opencode.json' && file.source === 'generated') {\n generated = JSON.parse(file.content) as Record<string, unknown>\n continue\n }\n // A continued session keeps the directory as the worker left it.\n if (continueSession === undefined) {\n await box.fs.write(`${paths.dir}/${file.relPath}`, file.content)\n }\n }\n const instructions = Array.isArray(generated.instructions)\n ? (generated.instructions as unknown[]).map((entry) =>\n typeof entry === 'string' && !entry.startsWith('/') ? `${paths.dir}/${entry}` : entry,\n )\n : undefined\n const providerId = profile.model!.provider!\n const modelId = profileProviderModel(profile)!\n const apiKeyEnv =\n typeof turnModel?.apiKeyEnv === 'string' ? turnModel.apiKeyEnv : 'OPENCODE_MODEL_API_KEY'\n const baseURL =\n typeof turnModel?.baseUrl === 'string' ? turnModel.baseUrl : '{env:OPENCODE_MODEL_BASE_URL}'\n const config = {\n $schema: 'https://opencode.ai/config.json',\n ...generated,\n ...(instructions === undefined ? {} : { instructions }),\n permission: {\n // The Sandbox sidecar's default: file tools stay inside the worker's own directory.\n external_directory: { '*': 'deny', '/tmp/**': 'allow' },\n ...((generated.permission as Record<string, unknown> | undefined) ?? {}),\n },\n provider: {\n [providerId]: {\n npm: '@ai-sdk/openai-compatible',\n name: providerId,\n options: {\n baseURL,\n apiKey: `{env:${apiKeyEnv}}`,\n ...(clientName === undefined ? {} : { headers: { [ROUTER_CLIENT_HEADER]: clientName } }),\n },\n models: { [modelId]: { name: modelId } },\n },\n },\n }\n // The invocation table owns the opencode argv, including the reasoning variant and the\n // unattended permission flag; the profile prompt is already in the configuration above.\n const invocation = harnessInvocation(HARNESS, invocationProfile(profile), task, {\n dangerouslySkipPermissions: true,\n })\n const model = `${providerId}/${modelId}`\n if (continueSession !== undefined && !/^[A-Za-z0-9_-]+$/u.test(continueSession)) {\n throw new ValidationError(`sharedBoxPlacement: session id ${continueSession} is not opencode's`)\n }\n return {\n args: [\n invocation.command,\n ...invocation.args,\n ...(continueSession === undefined ? [] : ['--session', continueSession]),\n '--format',\n 'json',\n '-m',\n model,\n ],\n config: JSON.stringify(config),\n model,\n }\n}\n\n/**\n * Save the harness's own record of the session where the transcript capture reads it.\n *\n * Current opencode keeps sessions in a SQLite database, which the capture cannot carry as text.\n * `opencode export` writes the same session as JSON.\n */\nasync function exportSession(\n run: (args: readonly string[], timeoutMs: number) => Promise<SharedBoxProcess>,\n collect: (process: SharedBoxProcess) => Promise<{ exitCode: number; stderr: string }>,\n paths: WorkerPaths,\n sessionId: string,\n): Promise<void> {\n if (!SESSION_ID.test(sessionId)) return\n const target = `${paths.home}/.local/share/opencode/export/${sessionId}.json`\n const process = await run(\n [\n '/bin/sh',\n '-c',\n 'mkdir -p \"$(dirname \"$2\")\" && exec opencode export \"$1\" > \"$2\"',\n 'export-session',\n sessionId,\n target,\n ],\n DEFAULT_EXEC_TIMEOUT_MS,\n )\n await collect(process)\n}\n\nconst SESSION_ID = /^[A-Za-z0-9_-]+$/u\n\n/** A subagent's session id in a `task` result (`<task id=\"ses_…\">`) or failure (`task_id: ses_…`). */\nconst TASK_SESSION = /(?:<task id=\"|task_id: )(ses_[A-Za-z0-9]+)/u\n\n/**\n * The session a harness subagent ran in, named by its parent's `task` tool part.\n *\n * opencode starts each subagent in a child session and refuses a nested one unless the\n * configuration raises `subagent_depth` above 1, so under the default the parent's parts name\n * every subagent session. A running part carries the id in `state.metadata.sessionId`; a finished\n * one also carries it in its output, and a failed one in its error.\n */\nfunction subagentSessionOf(part: Record<string, unknown>): string | undefined {\n if (part.type !== 'tool' || part.tool !== 'task') return undefined\n const state = part.state\n if (state === undefined || state === null || typeof state !== 'object') return undefined\n const { metadata, output, error } = state as Record<string, unknown>\n const named =\n metadata !== null && typeof metadata === 'object'\n ? (metadata as Record<string, unknown>).sessionId\n : undefined\n if (typeof named === 'string' && SESSION_ID.test(named)) return named\n for (const text of [output, error]) {\n const match = typeof text === 'string' ? TASK_SESSION.exec(text) : null\n if (match !== null) return match[1]\n }\n return undefined\n}\n\n// ── opencode `run --format json` to environment events ──────────────────────────────────\n\ninterface OpencodeLine {\n readonly type?: string\n readonly sessionID?: string\n readonly part?: Record<string, unknown>\n readonly error?: unknown\n}\n\n/**\n * Translate opencode's JSON event lines into events the provider executor reads.\n *\n * Every part becomes `message.part.updated`, which is how the sidecar forwards opencode parts, so\n * the existing trace and progress readers decode them unchanged. Each `step-finish` part also\n * becomes one canonical `llm_call` receipt with its token counts. opencode reports no dollar\n * receipt for a custom provider, so every receipt says the cost is unknown and Runtime prices the\n * tokens as an estimate instead of a bill.\n */\nfunction createOpencodeEventParser(model: string) {\n let sessionId: string | undefined\n let finalMessageId: string | undefined\n const textByMessage = new Map<string, string[]>()\n const subagentSessions = new Set<string>()\n const errors: string[] = []\n let malformed = 0\n let spentTokens = false\n const failureOf = (exitCode: number, stderr: string): string | undefined => {\n if (exitCode !== 0) {\n // opencode prints the provider's refusal as a JSON error line and exits 1, so the line's\n // text is the reason; stderr adds what the process itself said.\n const said = [...errors, stderr.trim().slice(-1_000)].filter((text) => text.length > 0)\n return `opencode exited ${exitCode}${said.length > 0 ? `: ${said.join('; ')}` : ''}`\n }\n return errors.length > 0 && finalMessageId === undefined ? errors.join('; ') : undefined\n }\n return {\n sessionId: () => sessionId,\n subagentSessionIds: (): readonly string[] => [...subagentSessions],\n /** Why this run failed, or `undefined` when it answered. */\n failure: failureOf,\n /** Whether this run spent any model tokens before it ended. */\n madeProgress: () => spentTokens,\n *line(raw: string): Generator<AgentEnvironmentEvent> {\n let event: OpencodeLine\n try {\n event = JSON.parse(raw) as OpencodeLine\n } catch {\n malformed += 1\n return\n }\n if (typeof event.sessionID === 'string') sessionId ??= event.sessionID\n if (event.type === 'error') {\n const message = errorMessage(event.error)\n errors.push(message)\n yield { type: 'error', data: { message } }\n return\n }\n const part = event.part\n if (part === undefined || part === null || typeof part !== 'object') return\n const subagent = subagentSessionOf(part)\n if (subagent !== undefined) subagentSessions.add(subagent)\n yield { type: 'message.part.updated', data: { part } }\n const messageId = typeof part.messageID === 'string' ? part.messageID : undefined\n if (part.type === 'text' && messageId !== undefined && typeof part.text === 'string') {\n const texts = textByMessage.get(messageId) ?? []\n texts.push(part.text)\n textByMessage.set(messageId, texts)\n }\n if (part.type === 'step-finish') {\n if (messageId !== undefined) finalMessageId = messageId\n const receipt = stepReceipt(part, model)\n if (receipt !== undefined) {\n const data = (receipt as { data?: { tokensIn?: number; tokensOut?: number } }).data\n if ((data?.tokensIn ?? 0) > 0 || (data?.tokensOut ?? 0) > 0) spentTokens = true\n yield receipt\n }\n }\n },\n /** The turn's terminal frames, from its last run. `runs` counts the runs of the session. */\n *finish(exitCode: number, stderr: string, runs = 1): Generator<AgentEnvironmentEvent> {\n const finalText =\n (finalMessageId === undefined ? undefined : textByMessage.get(finalMessageId)?.join('')) ??\n ''\n const failure = failureOf(exitCode, stderr)\n const counted = {\n ...(malformed > 0 ? { malformedLines: malformed } : {}),\n ...(runs > 1 ? { sessionRuns: runs } : {}),\n }\n if (failure !== undefined) {\n yield {\n type: 'result',\n data: { success: false, status: 'failed', error: failure, finalText, ...counted },\n }\n yield { type: 'done', data: { outcome: { type: 'failed' } } }\n return\n }\n yield {\n type: 'result',\n data: { success: true, finalText, ...counted },\n }\n yield { type: 'done', data: { outcome: { type: 'completed' } } }\n },\n }\n}\n\nfunction stepReceipt(\n part: Record<string, unknown>,\n model: string,\n): AgentEnvironmentEvent | undefined {\n const tokens = part.tokens as Record<string, unknown> | undefined\n if (tokens === undefined || tokens === null || typeof tokens !== 'object') return undefined\n const count = (value: unknown): number | undefined =>\n typeof value === 'number' && Number.isSafeInteger(value) && value >= 0 ? value : undefined\n const cache = (tokens.cache ?? {}) as Record<string, unknown>\n const input = count(tokens.input)\n const output = count(tokens.output)\n const reasoning = count(tokens.reasoning) ?? 0\n const cacheRead = count(cache.read) ?? 0\n const cacheWrite = count(cache.write) ?? 0\n const known = input !== undefined && output !== undefined\n return {\n type: 'llm_call',\n ...(typeof part.id === 'string' ? { id: part.id } : {}),\n usageMode: 'delta',\n ...(known\n ? {\n usage: {\n inputTokens: input + cacheRead + cacheWrite,\n outputTokens: output + reasoning,\n ...(reasoning > 0 ? { reasoningTokens: reasoning } : {}),\n },\n }\n : {}),\n data: {\n usageMode: 'delta',\n model,\n ...(known\n ? {\n // Runtime counts cached prompt tokens inside the prompt total; opencode reports\n // them apart, and reports reasoning apart from the visible output.\n tokensIn: input + cacheRead + cacheWrite,\n tokensOut: output + reasoning,\n ...(reasoning > 0 ? { reasoningTokens: reasoning } : {}),\n }\n : { tokensKnown: false }),\n costKnown: false,\n },\n }\n}\n\nfunction errorMessage(error: unknown): string {\n if (typeof error === 'string') return error\n if (error !== null && typeof error === 'object') {\n const record = error as Record<string, unknown>\n const data = record.data as Record<string, unknown> | undefined\n const text =\n typeof data?.message === 'string'\n ? data.message\n : typeof record.message === 'string'\n ? record.message\n : typeof record.name === 'string'\n ? record.name\n : 'opencode reported an error'\n // opencode reports a provider's HTTP refusal with its status and a prose message; the router's\n // own code does not survive into that message (\"Inference temporarily unavailable\" for a\n // refused flash). The status, in the `status code <n>` framing, is what tells a\n // capacity refusal (429, 503, 529) from a wrong request.\n const status = data?.statusCode\n return typeof status === 'number' && Number.isSafeInteger(status)\n ? `${text} (status code ${status})`\n : text\n }\n return 'opencode reported an error'\n}\n","/**\n * Shared-box placement: many harness workers in one Sandbox box, each as its own process.\n *\n * The default provider placement gives every worker its own Sandbox box. A box costs a create\n * call, a sidecar, an egress proxy, a preview link and a memory reservation sized for the box,\n * while one opencode worker uses about half a gigabyte. This module packs workers into a small\n * pool of boxes instead. Each worker runs `opencode run` as a separate process with its own\n * working directory and its own HOME, so each worker has its own harness session, its own\n * materialized profile and its own transcript files.\n *\n * Why processes and not sidecar sessions: the sidecar serves every session in one box from one\n * workspace and writes each session's profile into the same files. Measured 2026-09-24 on\n * sandbox-ff52a989e7c9: eight concurrent sessions with different instructions, and seven of eight\n * answered with another session's instructions. A process with its own directory, its own HOME and\n * `OPENCODE_DISABLE_PROJECT_CONFIG` reads only its own configuration: sixteen of sixteen concurrent\n * workers answered with their own instructions and wrote only into their own directory.\n *\n * The boundary is cooperative, not a security boundary. Every worker runs as the same Linux user,\n * so a worker can read a co-tenant's files through its shell. A profile that writes a repository,\n * runs untrusted code, holds a credential of its own, or must stay blind to its siblings keeps a\n * dedicated box: {@link SharedBoxPlacement.refusal} names the profile features this placement\n * cannot carry, and Runtime then uses the dedicated provider.\n *\n * A worker whose model provider refuses a turn for capacity keeps its process's session and\n * directory, pauses by the driver's rule, and continues the same opencode session, the way a\n * dedicated leaf does (`ProviderExecutorOptions.unavailablePause`). 15 of 23\n * down children of play anomaly-referee-v3d ended on `provider_quota_exhausted`, and opencode\n * itself gives up on a refused model after about 70 seconds of its own retries.\n *\n * The workers of one box share the box's router key. Each worker names itself to the router with\n * the `x-tangle-client` header, which the router stores as `clientName` on every usage row, so a\n * keeper can price one worker from the key's per-client rows (`tangle-ops router-spend --key\n * <box key>`). A request without the header stays charged to the box.\n *\n * `workersPerBox` is the one structural cap, and it protects the box. A Tangle box has a fixed\n * 512-task pids limit. An idle box uses about 118 tasks and one opencode worker about 34, so\n * twelve workers reach the limit. At that limit the sidecar's own process spawn fails with EAGAIN\n * and the sidecar restarts, which ends every worker in the box (measured on the same box: 28\n * workers crashed the sidecar twice; 16 workers crashed it once).\n */\n\nimport { randomUUID } from 'node:crypto'\nimport { type AgentProfile, canonicalCandidateDigest } from '@tangle-network/agent-interface'\nimport type {\n AgentEnvironment,\n AgentEnvironmentProvider,\n} from '@tangle-network/agent-interface/environment-provider'\nimport type { CreateSandboxOptions } from '@tangle-network/sandbox'\nimport { ValidationError } from '../errors'\nimport { TRANSIENT_BASE_DELAY_MS, transientRetry } from './shared-box-retry'\nimport {\n assertWorkerCreateInput,\n createWorker,\n HARNESS,\n isUnsafeRelativePath,\n parseSharedWorkerProfile,\n SHARED_PROVIDER_NAME,\n type SharedBoxHandle,\n sharedBoxCapabilities,\n sharedBoxRefusal,\n sharedWorkerClientName,\n} from './shared-box-worker'\nimport type { UnavailablePausePolicy } from './supervise/upstream-unavailable'\nimport type { SandboxClient } from './types'\n\n/**\n * The most workers one default box carries at once.\n *\n * It keeps a worker count that the 512-task pids limit of a Tangle box can hold with headroom\n * for the sidecar's own processes and the workers' tool shells: 118 idle tasks plus 8 workers at\n * about 34 tasks each is 390. Memory is not the binding limit: 8 workers used about 4 GB in a\n * 16 GB box. Raise it only for a box whose pids limit was raised with it.\n */\nexport const DEFAULT_SHARED_BOX_WORKERS = 8\n\n/** The box shape the default placement creates: memory for 8 workers at about 0.5 GB each plus\n * the sidecar, and 4 cores, because the workers wait on the model most of the time. */\nexport const DEFAULT_SHARED_BOX_RESOURCES = Object.freeze({ cpuCores: 4, memoryMB: 8192 })\n\nconst DEFAULT_WORKER_ROOT = '/home/agent/workers'\n\n/** Options for {@link sharedBoxPlacement}. */\nexport interface SharedBoxPlacementOptions {\n /** The Sandbox client that creates and deletes the shared boxes. */\n client: SandboxClient\n /**\n * Create options for every shared box: resources, egress, secrets, lifetime and billing.\n * Runtime owns `backend`, so the box's sidecar never serves a worker turn.\n */\n box?: Omit<CreateSandboxOptions, 'backend'>\n /** The most workers one box carries at once. Defaults to {@link DEFAULT_SHARED_BOX_WORKERS}. */\n workersPerBox?: number\n /** Absolute directory in each box that holds one directory per worker. */\n workerRoot?: string\n /** First wait before repeating a Sandbox call that failed transiently; doubles per attempt. */\n retryDelayMs?: number\n /**\n * How a worker waits out a model provider that cannot serve now: a quota, a rate limit, an\n * overload, or the router's own refused credential (`unavailableSignalOfFailure`). The worker\n * pauses 15 s, doubling to 5 min, the rule a driver and a dedicated leaf follow, then continues\n * its own opencode session in its own directory. Only cancellation, the turn's `timeoutMs` and\n * the node's deadline and budget, which abort the turn, end the pauses. `false` ends the turn on\n * the refused run.\n */\n unavailablePause?: UnavailablePausePolicy | false\n}\n\n/** Counts that show how the pool placed its workers. */\nexport interface SharedBoxStats {\n readonly boxesCreated: number\n readonly boxesLive: number\n readonly workersPlaced: number\n readonly workersLive: number\n /** The most workers any one box carried at the same time. */\n readonly peakWorkersPerBox: number\n /** Every box this pool created, with the workers it served. */\n readonly boxes: ReadonlyArray<{\n readonly id: string\n readonly workersServed: number\n readonly deleted: boolean\n /** Milliseconds from the create request to a box that runs processes. */\n readonly createMs: number\n }>\n}\n\n/** What {@link SharedBoxPlacement.close} did to each box. */\nexport interface SharedBoxCloseReceipt {\n readonly boxId: string\n readonly deleted: boolean\n readonly error?: string\n}\n\n/** Who a shared worker is, for the router rows its model calls leave on the box's key. */\nexport interface SharedWorkerIdentity {\n /** The supervised node the worker runs. Absent for a worker outside a supervised tree. */\n readonly nodeId?: string\n}\n\n/** A shared-box placement: the provider Runtime uses for a profile the placement accepts. */\nexport interface SharedBoxPlacement {\n /**\n * The environment provider that places one accepted worker in a shared box. A worker with a\n * `nodeId` sends `x-tangle-client: agent-runtime-node/<nodeId>` on its router calls; without\n * one, its calls carry no client name and stay charged to the box.\n */\n providerFor(worker?: SharedWorkerIdentity): AgentEnvironmentProvider\n /** Public identity of this placement, recorded on every execution it serves. */\n readonly identity: { readonly id: string; readonly digest: string }\n /** Why a shared box cannot carry this profile, or `undefined` when it can. */\n refusal(profile: AgentProfile): string | undefined\n stats(): SharedBoxStats\n /** Delete every box this placement created and still holds. Call it when the run settles. */\n close(): Promise<ReadonlyArray<SharedBoxCloseReceipt>>\n}\n\n/**\n * Place accepted workers as processes in a pool of shared Sandbox boxes.\n *\n * The pool fills a box before it creates the next one and deletes a box when its last worker\n * releases it. Runtime reaches this placement through `createExecutor({ backend: 'provider',\n * shared })`: a profile that {@link SharedBoxPlacement.refusal} accepts runs here, and every other\n * profile keeps the dedicated provider.\n */\nexport function sharedBoxPlacement(options: SharedBoxPlacementOptions): SharedBoxPlacement {\n const workersPerBox = options.workersPerBox ?? DEFAULT_SHARED_BOX_WORKERS\n if (!Number.isSafeInteger(workersPerBox) || workersPerBox < 1) {\n throw new ValidationError('sharedBoxPlacement: workersPerBox must be a positive integer')\n }\n const workerRoot = options.workerRoot ?? DEFAULT_WORKER_ROOT\n if (!workerRoot.startsWith('/') || isUnsafeRelativePath(workerRoot.slice(1))) {\n throw new ValidationError('sharedBoxPlacement: workerRoot must be an absolute, normalized path')\n }\n const boxOptions: CreateSandboxOptions = {\n resources: { ...DEFAULT_SHARED_BOX_RESOURCES },\n ...(options.box ?? {}),\n }\n if ((boxOptions as { backend?: unknown }).backend !== undefined) {\n throw new ValidationError('sharedBoxPlacement: box.backend is owned by Runtime')\n }\n const identity = {\n id: 'shared-box',\n digest: canonicalCandidateDigest({\n kind: 'shared-box-placement.v1',\n harness: HARNESS,\n workersPerBox,\n workerRoot,\n box: publicBoxOptions(boxOptions),\n }),\n }\n const retryDelayMs = options.retryDelayMs ?? TRANSIENT_BASE_DELAY_MS\n const pool = createBoxPool(options.client, boxOptions, workersPerBox, retryDelayMs)\n const providerFor = (worker: SharedWorkerIdentity = {}): AgentEnvironmentProvider => {\n const clientName =\n worker.nodeId === undefined ? undefined : sharedWorkerClientName(worker.nodeId)\n return {\n name: SHARED_PROVIDER_NAME,\n capabilities: sharedBoxCapabilities,\n async create(input): Promise<AgentEnvironment> {\n const profile = parseSharedWorkerProfile(input)\n const refusal = sharedBoxRefusal(profile)\n if (refusal !== undefined) {\n throw new ValidationError(`sharedBoxPlacement: ${refusal}`)\n }\n assertWorkerCreateInput(input)\n input.signal?.throwIfAborted()\n const lease = await pool.acquire()\n try {\n input.signal?.throwIfAborted()\n return await createWorker(lease, workerRoot, profile, {\n retryDelayMs,\n clientName,\n name: input.name,\n metadata: input.metadata,\n unavailablePause: options.unavailablePause ?? {},\n })\n } catch (error) {\n await lease.release()\n throw error\n }\n },\n }\n }\n return {\n providerFor,\n identity,\n refusal: sharedBoxRefusal,\n stats: () => pool.stats(),\n close: () => pool.close(),\n }\n}\n\nfunction publicBoxOptions(box: CreateSandboxOptions): unknown {\n const { env, secrets, ...rest } = box as CreateSandboxOptions & {\n env?: Record<string, string>\n secrets?: unknown\n }\n return {\n ...rest,\n ...(env === undefined ? {} : { environmentVariableNames: Object.keys(env).sort() }),\n ...(secrets === undefined ? {} : { secrets }),\n }\n}\n\n// ── The box pool ─────────────────────────────────────────────────────────────────────────────\n\ninterface PooledBox {\n readonly seq: number\n readonly ready: Promise<SharedBoxHandle>\n id?: string\n createMs?: number\n workers: number\n served: number\n retired: boolean\n deleted: boolean\n}\n\nexport interface BoxLease {\n readonly box: SharedBoxHandle\n release(): Promise<void>\n}\n\nfunction createBoxPool(\n client: SandboxClient,\n boxOptions: CreateSandboxOptions,\n workersPerBox: number,\n retryDelayMs: number,\n) {\n // One key per box, so a create repeated after a lost answer returns the same box.\n const poolId = randomUUID()\n const boxes: PooledBox[] = []\n const history: PooledBox[] = []\n let seq = 0\n let placed = 0\n let peak = 0\n let closing = false\n\n const retire = async (entry: PooledBox): Promise<SharedBoxCloseReceipt | undefined> => {\n if (entry.retired) return undefined\n entry.retired = true\n const index = boxes.indexOf(entry)\n if (index >= 0) boxes.splice(index, 1)\n let handle: SharedBoxHandle\n try {\n handle = await entry.ready\n } catch {\n return undefined\n }\n try {\n await transientRetry(() => handle.delete(), { delayMs: retryDelayMs })\n entry.deleted = true\n return { boxId: handle.id, deleted: true }\n } catch (error) {\n return {\n boxId: handle.id,\n deleted: false,\n error: error instanceof Error ? error.message : String(error),\n }\n }\n }\n\n return {\n async acquire(): Promise<BoxLease> {\n if (closing) throw new ValidationError('sharedBoxPlacement: the placement is closed')\n let entry = boxes.find((candidate) => !candidate.retired && candidate.workers < workersPerBox)\n if (entry === undefined) {\n const boxSeq = seq++\n const request = {\n ...boxOptions,\n name: boxOptions.name ?? `shared-box-${poolId.slice(0, 8)}-${boxSeq}`,\n idempotencyKey: `shared-box-${poolId}-${boxSeq}`,\n // The box's own sidecar never serves a worker turn. It still needs a harness to\n // start, and a minimal profile keeps its workspace free of worker instructions.\n backend: { type: HARNESS, profile: { name: 'shared-box', harness: HARNESS } },\n } as CreateSandboxOptions\n const requestedAt = Date.now()\n const created: PooledBox = {\n seq: boxSeq,\n ready: transientRetry(() => client.create(request), { delayMs: retryDelayMs }).then(\n (box) => box as unknown as SharedBoxHandle,\n ),\n workers: 0,\n served: 0,\n retired: false,\n deleted: false,\n }\n created.ready.then(\n (box) => {\n created.id = box.id\n created.createMs = Date.now() - requestedAt\n },\n () => {\n // Every waiting lease sees the same rejection through `ready`.\n const index = boxes.indexOf(created)\n if (index >= 0) boxes.splice(index, 1)\n created.retired = true\n },\n )\n boxes.push(created)\n history.push(created)\n entry = created\n }\n const leased = entry\n leased.workers += 1\n leased.served += 1\n placed += 1\n peak = Math.max(peak, leased.workers)\n let box: SharedBoxHandle\n try {\n box = await leased.ready\n } catch (error) {\n leased.workers -= 1\n throw error\n }\n let released = false\n return {\n box,\n async release(): Promise<void> {\n if (released) return\n released = true\n leased.workers -= 1\n if (leased.workers === 0 && !closing) await retire(leased)\n },\n }\n },\n stats(): SharedBoxStats {\n return {\n boxesCreated: history.length,\n boxesLive: history.filter((entry) => !entry.retired).length,\n workersPlaced: placed,\n workersLive: history.reduce((sum, entry) => sum + entry.workers, 0),\n peakWorkersPerBox: peak,\n boxes: history\n .filter((entry) => entry.id !== undefined)\n .map((entry) => ({\n id: entry.id!,\n workersServed: entry.served,\n deleted: entry.deleted,\n createMs: entry.createMs ?? 0,\n })),\n }\n },\n async close(): Promise<ReadonlyArray<SharedBoxCloseReceipt>> {\n closing = true\n const receipts = await Promise.all(history.map((entry) => retire(entry)))\n return receipts.filter((receipt): receipt is SharedBoxCloseReceipt => receipt !== undefined)\n },\n }\n}\n","/**\n * The search kernel's executor port for cells Runtime runs.\n *\n * A lane is a pool of execution slots with one cost rule: a shared box, dedicated\n * environments, subscription seats, or the router. The kernel places each cell on a lane and\n * bounds each lane's running cells by its capacity. This executor adds what one search cannot\n * see or enforce on its own:\n *\n * - Fleet slots. A `WorkerSlots` allocator shared by concurrent searches bounds working cells\n * across all of them. A cell waits for a slot, and the wait is its `queueMs`.\n * - Fleet dollars. On a hard lane a cell holds its enforced maximum as a `BudgetPool` ticket\n * before it starts, waits while open tickets could return enough, and settles the ticket\n * with its measured spend. Estimate lanes take no ticket: they cannot bound a cell, and an\n * unknown cost would close a capped pool for every search that shares it.\n * - Hard caps. On a hard lane every paid call of the cell, the agent's and the judges', holds\n * its maximum against the lane's `cellUsd` and is refused when it would pass it, so the\n * kernel's hard reservation is a bound and not a hope.\n * - Adoption. A finished attempt is written under its run id before the kernel sees it, so a\n * kernel that restarts adopts the attempt instead of running it again. The run id is stable\n * across restarts; an agent that runs remote work keys it by `ctx.search.runId`, so a lost\n * response is fetched again rather than executed again.\n * - Accounting. Every paid call is tagged with its search and attempt, and an attempt's cost is\n * every call tagged with its run id, including calls a process that ended made for it. A\n * reopened search settles those interrupted calls first: from the provider through the lane's\n * `recoverReceipt`, else with an unknown cost, never as free.\n * - Environment faults. A `SearchEnvironmentFault`, or a platform failure a repeated request\n * can change, settles `errored` and retryable, and the kernel runs a fresh attempt.\n * - Traces. Each attempt is one trace whose root span carries `agent.branch.id` = the node id.\n * The spans the attempt's exporter wrote and dropped go into the cell's `traceRef`.\n */\n\nimport { mkdirSync, renameSync, writeFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\nimport {\n CostAccountingIncompleteError,\n CostCeilingReachedError,\n type CostLedgerHandle,\n type CostReceiptInput,\n costForTokenPricing,\n costForUsage,\n type MaximumCharge,\n type PaidCallResult,\n type PendingCostCallView,\n type RunPaidCallInput,\n type RunRecord,\n} from '@tangle-network/agent-eval'\nimport {\n type CampaignStorage,\n type SearchLane as KernelSearchLane,\n type SearchAttemptAccounting,\n type SearchCellResult,\n type SearchCellStage,\n type SearchCellWork,\n type SearchExecutionIdentity,\n type SearchExecutor,\n type SearchSplit,\n type SearchTraceRef,\n searchReceiptAccounting,\n} from '@tangle-network/agent-eval/campaign'\nimport type { AgentProfile } from '@tangle-network/agent-interface'\nimport { ATTR, branchSpan, toW3CSpanId, toW3CTraceId } from '@tangle-network/agent-trace-contract'\nimport { msToUnixNano, toOtlpAttributes } from '@tangle-network/agent-trace-contract/otlp'\nimport { ConfigError } from '../errors'\nimport {\n createOpenInferenceFileExporter,\n createOtelExporter,\n generateSpanId,\n type OtelExportConfig,\n type OtelExporter,\n type OtelSpan,\n} from '../otel-export'\nimport {\n DEFAULT_SHARED_BOX_WORKERS,\n type SharedBoxPlacement,\n type SharedBoxPlacementOptions,\n sharedBoxPlacement,\n} from '../runtime/shared-box'\nimport { isTransientSandboxFailure } from '../runtime/shared-box-retry'\nimport type { BudgetPool, ReservationTicket } from '../runtime/supervise/budget'\nimport type { Spend } from '../runtime/supervise/types'\nimport { openSlotGroup, type SlotGroup, type WorkerSlots } from '../runtime/supervise/worker-slots'\n\n/** What a lane's slots are. */\nexport type SearchLaneKind = 'shared-box' | 'dedicated' | 'subscription' | 'router'\n\n/** An execution lane: slots that share one cost rule, and the profiles they cannot run. */\nexport interface SearchLane extends KernelSearchLane {\n readonly name: string\n readonly kind: SearchLaneKind\n readonly capacity: number\n readonly costCap: 'hard' | 'estimate'\n readonly cellUsd: number\n /** Why this lane cannot run `profile`, or undefined when it can. */\n refusal(profile: AgentProfile): string | undefined\n /** The receipt of a paid call that a process which ended made on this lane, asked of the\n * provider by `call.callId`; null when the provider cannot say. Without it, such a call\n * settles with an unknown cost. */\n recoverReceipt?(call: PendingCostCallView): Promise<CostReceiptInput | null>\n}\n\n/** Options every lane builder takes. */\nexport interface SearchLaneOptions {\n name?: string\n recoverReceipt?: SearchLane['recoverReceipt']\n}\n\nfunction laneReceipts(options: SearchLaneOptions): Pick<SearchLane, 'recoverReceipt'> {\n return options.recoverReceipt ? { recoverReceipt: options.recoverReceipt } : {}\n}\n\n/** A lane of workers packed into shared Sandbox boxes. Close `placement` when the run settles. */\nexport interface SharedBoxSearchLane extends SearchLane {\n readonly kind: 'shared-box'\n readonly placement: SharedBoxPlacement\n}\n\nconst acceptEveryProfile = (): undefined => undefined\n\nfunction laneName(name: string | undefined, fallback: string): string {\n const resolved = name ?? fallback\n if (!/^[A-Za-z0-9._-]{1,64}$/u.test(resolved)) {\n throw new ConfigError(`search lane name '${resolved}' must be 1-64 of [A-Za-z0-9._-]`)\n }\n return resolved\n}\n\nfunction positiveInteger(value: number, name: string): number {\n if (!Number.isSafeInteger(value) || value < 1) {\n throw new ConfigError(`${name} must be a positive integer`)\n }\n return value\n}\n\nfunction dollars(value: number, name: string): number {\n if (!Number.isFinite(value) || value < 0) {\n throw new ConfigError(`${name} must be a finite non-negative number of dollars`)\n }\n return value\n}\n\n/**\n * Cells as workers packed into shared Sandbox boxes, `workersPerBox` to a box.\n *\n * Capacity is `boxes × workersPerBox`. The workers of one box share its router key, which caps\n * no single worker, so the lane holds an estimate (`cellUsd` is the prior until 20 cells settle).\n * A profile the placement refuses (a repository writer, a replaced system prompt, MCP servers,\n * hooks, subagents, tool grants) needs another lane. The agent reaches the box through\n * `lane.placement.providerFor({ nodeId: ctx.search.runId })`, which names the attempt to the\n * router on every call.\n */\nexport function sharedBoxLane(\n options: SharedBoxPlacementOptions & SearchLaneOptions & { boxes: number; cellUsd: number },\n): SharedBoxSearchLane {\n const { name, boxes, cellUsd, recoverReceipt, ...placementOptions } = options\n const placement = sharedBoxPlacement(placementOptions)\n const workersPerBox = placementOptions.workersPerBox ?? DEFAULT_SHARED_BOX_WORKERS\n return Object.freeze({\n name: laneName(name, 'shared-box'),\n kind: 'shared-box' as const,\n capacity: positiveInteger(boxes, 'sharedBoxLane(): boxes') * workersPerBox,\n costCap: 'estimate' as const,\n cellUsd: dollars(cellUsd, 'sharedBoxLane(): cellUsd'),\n refusal: (profile: AgentProfile) => placement.refusal(profile),\n ...laneReceipts({ recoverReceipt }),\n placement,\n })\n}\n\n/**\n * Cells that each run in their own environment, `capacity` at once. The lane cannot bound a\n * cell's dollars, so it holds an estimate: `cellUsd` until 20 cells settle, then 1.5 × the p99\n * of its settled cells.\n */\nexport function dedicatedLane(\n options: SearchLaneOptions & { capacity: number; cellUsd: number },\n): SearchLane {\n return Object.freeze({\n name: laneName(options.name, 'dedicated'),\n kind: 'dedicated' as const,\n capacity: positiveInteger(options.capacity, 'dedicatedLane(): capacity'),\n costCap: 'estimate' as const,\n cellUsd: dollars(options.cellUsd, 'dedicatedLane(): cellUsd'),\n refusal: acceptEveryProfile,\n ...laneReceipts(options),\n })\n}\n\n/**\n * Cells on subscription seats, one cell a seat. A seat charges no dollar per call, so its own\n * work costs $0 and reports no tokens. `cellUsd` bounds the cell's priced calls, such as its\n * judges; every one of them must declare a maximum, and the lane refuses a call past it.\n */\nexport function subscriptionLane(\n options: SearchLaneOptions & { seats: number; cellUsd?: number },\n): SearchLane {\n return Object.freeze({\n name: laneName(options.name, 'subscription'),\n kind: 'subscription' as const,\n capacity: positiveInteger(options.seats, 'subscriptionLane(): seats'),\n costCap: 'hard' as const,\n cellUsd: dollars(options.cellUsd ?? 0, 'subscriptionLane(): cellUsd'),\n refusal: acceptEveryProfile,\n ...laneReceipts(options),\n })\n}\n\n/**\n * Cells whose model calls are priced router calls, `capacity` at once. Every paid call of a\n * cell must declare its maximum charge, and the lane refuses a call that would take the cell\n * past `cellUsd`, so `cellUsd` is each cell's hard maximum.\n */\nexport function routerLane(\n options: SearchLaneOptions & { capacity: number; cellUsd: number },\n): SearchLane {\n return Object.freeze({\n name: laneName(options.name, 'router'),\n kind: 'router' as const,\n capacity: positiveInteger(options.capacity, 'routerLane(): capacity'),\n costCap: 'hard' as const,\n cellUsd: dollars(options.cellUsd, 'routerLane(): cellUsd'),\n refusal: acceptEveryProfile,\n ...laneReceipts(options),\n })\n}\n\n/** Check a lane list: at least one lane, unique names, a hard lane's cap known. */\nexport function assertSearchLanes(lanes: readonly SearchLane[], context: string): void {\n if (!Array.isArray(lanes) || lanes.length === 0) {\n throw new ConfigError(`${context}: lanes needs at least one lane`)\n }\n const names = new Set<string>()\n for (const lane of lanes) {\n if (!lane || typeof lane.refusal !== 'function' || typeof lane.kind !== 'string') {\n throw new ConfigError(\n `${context}: every lane comes from sharedBoxLane, dedicatedLane, subscriptionLane or routerLane`,\n )\n }\n if (names.has(lane.name)) throw new ConfigError(`${context}: lane '${lane.name}' appears twice`)\n names.add(lane.name)\n }\n}\n\n/**\n * The environment, not the candidate, ended the attempt: a box that died, a platform that\n * refused the run, a quota. The attempt settles `errored` and retryable, and the kernel runs a\n * fresh attempt up to its `maxAttempts`. Throw anything else for the agent's own failure.\n */\nexport class SearchEnvironmentFault extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options)\n this.name = 'SearchEnvironmentFault'\n }\n}\n\n/** Whether an attempt's error is the environment's: a `SearchEnvironmentFault`, or a platform,\n * gateway or network failure that a repeated request can change. */\nexport function isSearchEnvironmentFault(error: unknown): boolean {\n return error instanceof SearchEnvironmentFault || isTransientSandboxFailure(error)\n}\n\n/** What the agent of one attempt knows about where and as what it runs. */\nexport interface SearchCellContext {\n readonly searchId: string\n readonly cellId: string\n readonly nodeId: string\n readonly taskId: string\n readonly split: SearchSplit\n readonly stage: SearchCellStage\n readonly attempt: number\n /** `cellId:attempt`. It is the same after a restart, so key remote work by it: a request sent\n * again with the same run id must return the first execution's result, not start a second. */\n readonly runId: string\n readonly lane: SearchLane\n /** The attempt's trace. Parent your own spans on `spanId`. Null when tracing is off. */\n readonly trace: { readonly traceId: string; readonly spanId: string } | null\n}\n\n/** Where a search's cell spans go. Default: one OpenInference file per search when storage is\n * the filesystem. `otlp` gives each attempt its own exporter, so its counts are exact. */\nexport type SearchTraceOptions = 'off' | { readonly otlp: OtelExportConfig }\n\n/** One attempt as the executor hands it to the cell runner. */\ninterface SearchAttempt<TArtifact> {\n readonly work: SearchCellWork<TArtifact>\n readonly lane: SearchLane\n readonly context: SearchCellContext\n /** The cost ledger the attempt's paid calls go through. It tags each call with the attempt,\n * and on a hard lane it refuses a call that would take the attempt past the lane's `cellUsd`,\n * or that declares no priced maximum. */\n readonly costLedger: CostLedgerHandle\n /** Open a span under the attempt's root span; `end` exports it. */\n span(name: string, attributes?: Record<string, unknown>): SearchAttemptSpan\n}\n\ninterface SearchAttemptSpan {\n setAttribute(key: string, value: unknown): void\n end(attributes?: Record<string, unknown>): void\n}\n\ninterface SearchExecutorOptions<TArtifact> {\n lanes: readonly SearchLane[]\n /** The profile a node runs, read by placement to skip a lane that refuses it. */\n profileOf(nodeId: string): AgentProfile | null\n /** Run one attempt. Report an environment fault as an `errored` retryable outcome; throw only\n * for a failure that must stop the search. The executor replaces the result's accounting\n * with the receipts tagged with the attempt's run id. */\n runAttempt(attempt: SearchAttempt<TArtifact>): Promise<\n SearchCellResult & {\n /** Mint from the final attempt accounting before adoption or ledger settlement. */\n recordCell?: (result: SearchCellResult) => RunRecord | Promise<RunRecord>\n }\n >\n /** The search's cost ledger. */\n costLedger: CostLedgerHandle\n /** What the search runs, recorded on an attempt the search's own stop interrupted. */\n identity: SearchExecutionIdentity\n storage: CampaignStorage\n /** The search's directory: attempt records go in `attempts/`, spans in `spans.otlp.jsonl`. */\n dir: string\n /** Bound working cells across every search that shares this allocator. */\n workerSlots?: WorkerSlots\n /** Fleet dollars: a hard-lane cell holds its maximum here before it starts. */\n budgetPool?: BudgetPool\n trace?: SearchTraceOptions\n}\n\nconst USD_TOLERANCE = 1e-9\n\n/** The kernel's executor port over Runtime lanes. */\nexport function searchExecutor<TArtifact>(\n options: SearchExecutorOptions<TArtifact>,\n): SearchExecutor<TArtifact> {\n assertSearchLanes(options.lanes, 'searchExecutor()')\n const lanes = new Map(options.lanes.map((lane) => [lane.name, lane]))\n const placed = new Map(options.lanes.map((lane) => [lane.name, 0]))\n const slots: SlotGroup | null = options.workerSlots ? openSlotGroup(options.workerSlots) : null\n const attempts = attemptStore(options.storage, join(options.dir, 'attempts'))\n const tracing = searchTracing(options)\n\n const laneOf = (work: SearchCellWork<TArtifact>): SearchLane => {\n const lane = lanes.get(work.lane)\n if (!lane)\n throw new Error(`search cell ${work.cellId} was placed on unknown lane '${work.lane}'`)\n return lane\n }\n\n return {\n lanes: () => options.lanes,\n // Weighted round robin: each lane receives cells in proportion to its capacity, first\n // declared first on a tie, skipping lanes that refuse the node's profile.\n place(cell) {\n const profile = options.profileOf(cell.nodeId)\n let chosen: SearchLane | undefined\n for (const lane of options.lanes) {\n if (profile && lane.refusal(profile) !== undefined) continue\n if (\n chosen === undefined ||\n placed.get(lane.name)! / lane.capacity < placed.get(chosen.name)! / chosen.capacity\n ) {\n chosen = lane\n }\n }\n if (!chosen) {\n throw new Error(\n `no search lane can run node ${cell.nodeId}; admission should have refused it`,\n )\n }\n placed.set(chosen.name, placed.get(chosen.name)! + 1)\n return chosen.name\n },\n async adopt(work) {\n return attempts.read(work.runId)\n },\n async run(work) {\n const lane = laneOf(work)\n const queuedAt = Date.now()\n let hold: FleetHold\n try {\n hold = await holdFleet(lane, work, options.budgetPool, slots)\n } catch (error) {\n // The search stopped while the cell waited: the kernel leaves an errored attempt\n // unsettled while it stops, and the next process runs it.\n if (work.signal.aborted) return interrupted(work, lane, options.identity, error)\n throw error\n }\n const queueMs = Date.now() - queuedAt\n const trace = tracing.open(work, lane)\n let result: SearchCellResult | undefined\n try {\n const context: SearchCellContext = Object.freeze({\n searchId: work.searchId,\n cellId: work.cellId,\n nodeId: work.nodeId,\n taskId: work.taskId,\n split: work.split,\n stage: work.stage,\n attempt: work.attempt,\n runId: work.runId,\n lane,\n trace: trace.ids,\n })\n const tags = searchCallTags(work.searchId, { run: work.runId, lane: lane.name })\n const { recordCell, ...measured } = await options.runAttempt({\n work,\n lane,\n context,\n costLedger: attemptLedger(options.costLedger, lane, tags),\n span: trace.span,\n })\n const traceRef = await trace.finish(measured)\n const execRunId =\n measured.traceRef && 'execRunId' in measured.traceRef ? measured.traceRef.execRunId : null\n result = {\n ...measured,\n accounting: attemptAccounting(options.costLedger, lane, tags),\n queueMs,\n placement: { lane: lane.name, boxId: measured.placement?.boxId ?? null },\n traceRef: execRunId && 'traceId' in traceRef ? { ...traceRef, execRunId } : traceRef,\n }\n if (recordCell && result.outcome.status !== 'errored') {\n result.runRecord = await recordCell(result)\n }\n } finally {\n hold.release(result)\n }\n // An attempt interrupted by the search stopping is not recorded: the next process runs\n // the same attempt again instead of adopting an interruption as the attempt's result.\n if (!work.signal.aborted) attempts.write(work.runId, result)\n return result\n },\n }\n}\n\nfunction interrupted(\n work: SearchCellWork<unknown>,\n lane: SearchLane,\n identity: SearchExecutionIdentity,\n error: unknown,\n): SearchCellResult {\n return {\n outcome: {\n status: 'errored',\n metrics: {},\n error: {\n code: 'interrupted',\n message: `search cell ${work.runId} was interrupted before it ran: ${error instanceof Error ? error.message : String(error)}`,\n retryable: true,\n },\n },\n accounting: {\n tokens: { status: 'known', inputTokens: 0, outputTokens: 0, cachedTokens: 0 },\n cost: { status: 'known', usd: 0, source: 'free' },\n },\n identity,\n placement: { lane: lane.name, boxId: null },\n traceRef: { unknown: 'the attempt never started' },\n }\n}\n\ninterface FleetHold {\n release(result: SearchCellResult | undefined): void\n}\n\n/** Take the attempt's fleet dollars, then its fleet slot. A cell waiting for budget holds no\n * slot, so it cannot hold a slot the cells it waits on need. */\nasync function holdFleet(\n lane: SearchLane,\n work: SearchCellWork<unknown>,\n pool: BudgetPool | undefined,\n slots: SlotGroup | null,\n): Promise<FleetHold> {\n let ticket: ReservationTicket | undefined\n if (pool && lane.costCap === 'hard' && lane.cellUsd > 0) {\n const reserved = pool.reserve(\n { maxUsd: lane.cellUsd, maxTokens: 0, maxIterations: 0 },\n { label: work.runId, stage: 'admitted' },\n { wait: true },\n )\n if (!reserved.ok) {\n throw new Error(\n `the fleet budget pool refused search cell ${work.runId} on lane ${lane.name}: ${reserved.reason}`,\n )\n }\n ticket = reserved.ticket\n if (reserved.granted) {\n try {\n await abortable(reserved.granted, work.signal)\n } catch (error) {\n pool.reconcile(ticket, noSpend())\n throw error\n }\n }\n pool.attribute(ticket, { label: work.runId, stage: 'executing' })\n }\n const permit = slots?.acquire(0)\n if (permit) {\n try {\n await abortable(permit.ready, work.signal)\n } catch (error) {\n permit.release()\n if (ticket) pool!.reconcile(ticket, noSpend())\n throw error\n }\n }\n return {\n release(result) {\n permit?.release()\n if (!ticket) return\n try {\n pool!.reconcile(ticket, result ? spendOf(result) : unknownSpend())\n } catch {\n // The pool has committed the spend and, for an unknown dollar cost under its cap,\n // closed dollar admission; its next reservation refuses and stops the searches that\n // share it. The cell's own result stands.\n }\n },\n }\n}\n\nfunction abortable<T>(promise: Promise<T>, signal: AbortSignal): Promise<T> {\n if (signal.aborted) return Promise.reject(signal.reason ?? new Error('search cell aborted'))\n return new Promise<T>((resolve, reject) => {\n const onAbort = () => reject(signal.reason ?? new Error('search cell aborted'))\n signal.addEventListener('abort', onAbort, { once: true })\n promise.then(\n (value) => {\n signal.removeEventListener('abort', onAbort)\n resolve(value)\n },\n (error: unknown) => {\n signal.removeEventListener('abort', onAbort)\n reject(error)\n },\n )\n })\n}\n\nfunction noSpend(): Spend {\n return { iterations: 0, tokens: { input: 0, output: 0 }, usd: 0, ms: 0 }\n}\n\nfunction unknownSpend(): Spend {\n return { ...noSpend(), usdKnown: false, tokensKnown: false }\n}\n\n/** The attempt's spend as the budget pool reads it. Unknown dollars carry their proven floor. */\nfunction spendOf(result: SearchCellResult): Spend {\n const { cost, tokens } = result.accounting\n return {\n iterations: 0,\n tokens:\n tokens.status === 'known'\n ? { input: tokens.inputTokens, output: tokens.outputTokens }\n : { input: 0, output: 0 },\n ...(tokens.status === 'known' ? {} : { tokensKnown: false }),\n usd: cost.status === 'known' ? cost.usd : cost.knownLowerBoundUsd,\n ...(cost.status === 'known' ? {} : { usdKnown: false }),\n ms: result.wallMs ?? 0,\n }\n}\n\n/** The dollar maximum a paid call declares, or null when it declares no priced one. */\nfunction chargeMaximumUsd(maximum: MaximumCharge | undefined): number | null {\n if (!maximum) return null\n if ('externallyEnforcedMaximumUsd' in maximum) return maximum.externallyEnforcedMaximumUsd\n if ('customTokenPricing' in maximum)\n return costForTokenPricing(maximum.customTokenPricing, maximum)\n const priced = costForUsage(maximum.model, maximum)\n return priced.costUnknown ? null : priced.costUsd\n}\n\nconst TAG_SEARCH = 'searchId'\nconst TAG_RUN = 'searchRunId'\nconst TAG_LANE = 'searchLane'\nconst TAG_OPERATION = 'searchOperation'\n\n/** The cost-ledger tags of one search's calls: a cell attempt's, or a proposal operation's. */\nexport function searchCallTags(\n searchId: string,\n of: { run: string; lane: string } | { operation: string },\n): Record<string, string> {\n return 'run' in of\n ? { [TAG_SEARCH]: searchId, [TAG_RUN]: of.run, [TAG_LANE]: of.lane }\n : { [TAG_SEARCH]: searchId, [TAG_OPERATION]: of.operation }\n}\n\n/** The search ledger with `tags` added to every paid call. */\nexport function taggedLedger(\n ledger: CostLedgerHandle,\n tags: Record<string, string>,\n): CostLedgerHandle {\n return ledgerView(ledger, (input) =>\n ledger.runPaidCall({ ...input, tags: { ...input.tags, ...tags } }),\n )\n}\n\nfunction ledgerView(\n ledger: CostLedgerHandle,\n runPaidCall: CostLedgerHandle['runPaidCall'],\n): CostLedgerHandle {\n return new Proxy(ledger, {\n get(target, property) {\n if (property === 'runPaidCall') return runPaidCall\n const value = Reflect.get(target, property, target)\n return typeof value === 'function' ? value.bind(target) : value\n },\n })\n}\n\n/**\n * The search ledger seen by one attempt: every paid call carries the attempt's tags. On a hard\n * lane every call also holds its declared maximum against the lane's `cellUsd` until its\n * receipt replaces the hold with the charge, and a call that would pass the cap, or declares no\n * priced maximum, is refused. A charge the provider left unknown keeps its maximum held.\n */\nfunction attemptLedger(\n ledger: CostLedgerHandle,\n lane: SearchLane,\n tags: Record<string, string>,\n): CostLedgerHandle {\n const tagged = taggedLedger(ledger, tags)\n if (lane.costCap !== 'hard') return tagged\n let heldUsd = 0\n const runPaidCall = async <T>(input: RunPaidCallInput<T>): Promise<PaidCallResult<T>> => {\n const maximumUsd = chargeMaximumUsd(input.maximumCharge)\n if (maximumUsd === null) {\n return {\n succeeded: false,\n error: new CostAccountingIncompleteError(\n `lane ${lane.name} caps each cell at $${lane.cellUsd}, so paid call '${input.actor}' during '${input.phase}' needs a priced maximumCharge`,\n ),\n }\n }\n if (heldUsd + maximumUsd > lane.cellUsd + USD_TOLERANCE) {\n return {\n succeeded: false,\n error: new CostCeilingReachedError(\n lane.cellUsd,\n heldUsd,\n maximumUsd,\n input.phase,\n input.actor,\n ),\n }\n }\n heldUsd += maximumUsd\n const result = await tagged.runPaidCall(input)\n const { receipt } = result\n if (receipt && !receipt.costUnknown) heldUsd += receipt.costUsd - maximumUsd\n return result\n }\n return ledgerView(tagged, runPaidCall)\n}\n\n/**\n * An attempt's cost is every call tagged with its run id, a call a process that ended made for\n * it included; a call still pending makes the cost unknown with the settled calls as its floor.\n * A subscription seat reports no tokens, and its own work charges no dollar.\n */\nfunction attemptAccounting(\n ledger: CostLedgerHandle,\n lane: SearchLane,\n tags: Record<string, string>,\n): SearchAttemptAccounting {\n const receipts = ledger.list({ tags })\n const accounting = searchReceiptAccounting(receipts)\n const pending = ledger.listPending?.({ tags }) ?? []\n const floorUsd =\n accounting.cost.status === 'known' ? accounting.cost.usd : accounting.cost.knownLowerBoundUsd\n const cost: SearchAttemptAccounting['cost'] =\n pending.length > 0\n ? {\n status: 'unknown',\n knownLowerBoundUsd: floorUsd,\n reason: `${pending.length} paid call(s) of the attempt had no receipt when it ended`,\n }\n : accounting.cost.status === 'known' &&\n accounting.cost.usd > 0 &&\n receipts.some((receipt) => receipt.actualCostUsd === undefined)\n ? { ...accounting.cost, source: 'pricing-table' }\n : accounting.cost\n return {\n tokens:\n lane.kind === 'subscription'\n ? { status: 'unknown', reason: 'a subscription seat reports no token usage' }\n : accounting.tokens,\n cost,\n }\n}\n\n/**\n * Settle every paid call of `searchId` that a process which ended left pending, before the\n * reopened search makes a new one: a capped ledger refuses new paid work while one is\n * unresolved. A cell's call is asked of its lane's provider through `recoverReceipt`; any other\n * call, or one the provider cannot answer, settles failed with an unknown cost.\n */\nexport async function reconcileInterruptedSearchCalls(\n ledger: CostLedgerHandle,\n searchId: string,\n lanes: readonly SearchLane[],\n): Promise<{ recovered: number; unknown: number }> {\n const interrupted = (ledger.listPending?.({ tags: { [TAG_SEARCH]: searchId } }) ?? []).filter(\n (call) => call.state === 'interrupted',\n )\n let recovered = 0\n for (const call of interrupted) {\n const lane = lanes.find((candidate) => candidate.name === call.tags?.[TAG_LANE])\n const receipt = (await lane?.recoverReceipt?.(call)) ?? null\n if (receipt) {\n ledger.reconcile(call.callId, receipt)\n recovered += 1\n } else {\n ledger.reconcile(\n call.callId,\n {\n model: call.model,\n inputTokens: 0,\n outputTokens: 0,\n costUnknown: true,\n usageUnknown: true,\n },\n { error: 'the process that made this call ended before its receipt' },\n )\n }\n }\n return { recovered, unknown: interrupted.length - recovered }\n}\n\n/** Finished attempts by run id: the record a restarted kernel adopts. */\nfunction attemptStore(storage: CampaignStorage, dir: string) {\n const pathOf = (runId: string) => join(dir, `${runId.replace(/[^A-Za-z0-9_-]/gu, '.')}.json`)\n storage.ensureDir(dir)\n return {\n read(runId: string): SearchCellResult | null {\n const text = storage.read(pathOf(runId))\n if (text === undefined) return null\n const record = JSON.parse(text) as { runId?: unknown; result?: SearchCellResult }\n if (record.runId !== runId || !record.result) {\n throw new Error(`attempt record ${pathOf(runId)} does not hold run ${runId}`)\n }\n return record.result\n },\n write(runId: string, result: SearchCellResult): void {\n const text = `${JSON.stringify({ runId, result })}\\n`\n const path = pathOf(runId)\n if (storage.kind !== 'filesystem') {\n storage.write(path, text)\n return\n }\n // Written whole under a temporary name and renamed, so a killed process leaves the record\n // absent or complete. It is not synced: a record lost to an operating-system crash costs a\n // rerun of the same run id, which a remote worker keyed by run id answers without executing.\n mkdirSync(dirname(path), { recursive: true })\n const temporary = `${path}.${process.pid}.tmp`\n writeFileSync(temporary, text)\n renameSync(temporary, path)\n },\n }\n}\n\ninterface AttemptTrace {\n readonly ids: { readonly traceId: string; readonly spanId: string } | null\n span(name: string, attributes?: Record<string, unknown>): SearchAttemptSpan\n finish(result: SearchCellResult): Promise<SearchTraceRef>\n}\n\nconst STATUS_OK = 1\nconst STATUS_ERROR = 2\nconst MAX_ATTRIBUTE_CHARS = 256\n\nfunction searchTracing<TArtifact>(options: SearchExecutorOptions<TArtifact>) {\n const mode = options.trace\n const fileExporter =\n mode === undefined && options.storage.kind === 'filesystem'\n ? createOpenInferenceFileExporter(join(options.dir, 'spans.otlp.jsonl'))\n : undefined\n const off = (reason: string): AttemptTrace => ({\n ids: null,\n span: () => ({ setAttribute() {}, end() {} }),\n finish: async () => ({ unknown: reason }),\n })\n return {\n open(work: SearchCellWork<TArtifact>, lane: SearchLane): AttemptTrace {\n if (mode === 'off') return off('tracing is off for this search')\n const exporter = mode === undefined ? fileExporter : createOtelExporter(mode.otlp)\n if (!exporter) {\n return off(\n mode === undefined\n ? 'the search storage is not the filesystem and no OTLP exporter was configured'\n : 'the OTLP exporter has no endpoint',\n )\n }\n return attemptTrace(work, lane, exporter, mode !== undefined)\n },\n }\n}\n\n/**\n * One attempt's trace. Its ids derive from the run id, so an attempt run again after a restart\n * writes into the same trace. A shared file exporter writes each span synchronously, so the\n * attempt's written and dropped counts are the change in the exporter's own counts across each\n * of its spans; an attempt's own OTLP exporter is shut down at the end and read whole.\n */\nfunction attemptTrace(\n work: SearchCellWork<unknown>,\n lane: SearchLane,\n exporter: OtelExporter,\n ownsExporter: boolean,\n): AttemptTrace {\n const traceId = toW3CTraceId(`search-cell:${work.runId}`)\n const rootSpanId = toW3CSpanId(`search-cell:${work.runId}`)\n const startMs = Date.now()\n let written = 0\n let dropped = 0\n const exportCounted = (span: OtelSpan) => {\n if (ownsExporter) {\n exporter.exportSpan(span)\n return\n }\n const before = exporter.stats()\n exporter.exportSpan(span)\n const after = exporter.stats()\n written += after.written - before.written\n dropped += after.dropped - before.dropped\n }\n return {\n ids: { traceId, spanId: rootSpanId },\n span(name, attributes = {}) {\n const opened = Date.now()\n const record: Record<string, unknown> = { ...attributes }\n let ended = false\n return {\n setAttribute(key, value) {\n record[key] = value\n },\n end(endAttributes = {}) {\n if (ended) return\n ended = true\n exportCounted(\n otelSpan({\n traceId,\n spanId: generateSpanId(),\n parentSpanId: rootSpanId,\n name,\n startMs: opened,\n endMs: Date.now(),\n attributes: { ...record, ...endAttributes },\n status: STATUS_OK,\n }),\n )\n },\n }\n },\n async finish(result) {\n const root = branchSpan({\n traceId,\n spanId: rootSpanId,\n name: 'search.cell',\n startTime: new Date(startMs).toISOString(),\n branchId: work.nodeId,\n arm: lane.name,\n attributes: {\n 'tangle.search.id': work.searchId,\n 'tangle.search.cell_id': work.cellId,\n 'tangle.search.run_id': work.runId,\n 'tangle.search.task_id': work.taskId,\n 'tangle.search.split': work.split,\n 'tangle.search.stage': work.stage,\n 'tangle.search.attempt': work.attempt,\n 'tangle.search.lane': lane.name,\n 'tangle.search.lane_kind': lane.kind,\n 'tangle.search.outcome': result.outcome.status,\n ...('score' in result.outcome ? { [ATTR.score]: result.outcome.score } : {}),\n },\n })\n exportCounted(\n otelSpan({\n traceId,\n spanId: rootSpanId,\n name: root.name,\n startMs,\n endMs: Date.now(),\n attributes: root.attributes,\n status: result.outcome.status === 'errored' ? STATUS_ERROR : STATUS_OK,\n }),\n )\n if (ownsExporter) {\n await exporter.shutdown()\n const stats = exporter.stats()\n written = stats.written\n dropped = stats.dropped\n }\n return { traceId, execRunId: null, spansWritten: written, spansDropped: dropped }\n },\n }\n}\n\nfunction otelSpan(input: {\n traceId: string\n spanId: string\n parentSpanId?: string\n name: string\n startMs: number\n endMs: number\n attributes: Record<string, unknown>\n status: number\n}): OtelSpan {\n const attributes: Record<string, string | number | boolean> = {}\n for (const [key, value] of Object.entries(input.attributes)) {\n if (typeof value === 'number' || typeof value === 'boolean') attributes[key] = value\n else if (typeof value === 'string') attributes[key] = value.slice(0, MAX_ATTRIBUTE_CHARS)\n }\n return {\n traceId: input.traceId,\n spanId: input.spanId,\n ...(input.parentSpanId ? { parentSpanId: input.parentSpanId } : {}),\n name: input.name,\n kind: 1,\n startTimeUnixNano: msToUnixNano(input.startMs),\n endTimeUnixNano: msToUnixNano(Math.max(input.startMs, input.endMs)),\n attributes: toOtlpAttributes(attributes),\n status: { code: input.status },\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"settle-record-U7fkQEZa.js","names":[],"sources":["../src/durable/settle-record.ts"],"sourcesContent":["import { readFile } from 'node:fs/promises'\nimport { resolve } from 'node:path'\nimport { canonicalCandidateDigest, canonicalCandidateJson } from '@tangle-network/agent-interface'\nimport {\n publishExclusiveDurableFile,\n writeAtomicDurableFile,\n} from '../runtime/supervise/durable-file'\nimport type { RootStreamReceipt, SupervisedResult } from '../runtime/supervise/types'\nimport { isNoEntError } from './jsonl-file'\n\n/** Terminal evidence has one result per segment. Reopen archives that result byte for byte;\n * a failed attempt may resume because failure.json records only the latest throw.\n * Serialization, exclusive publication and validation stay with the record operations below.\n */\n\n/** The settle record: the returned `SupervisedResult` as canonical JSON, written once. */\nexport const SETTLE_RECORD_FILE = 'result.json'\n/** The failure record: the most recent throw, replaced by a later throw. */\nexport const FAILURE_RECORD_FILE = 'failure.json'\n\n/** What `failure.json` records about the most recent throw. */\nexport interface DurableFailureRecord {\n readonly runId: string\n readonly pursuitId: string\n /** ISO instant the throw was recorded. */\n readonly at: string\n readonly error: { readonly name: string; readonly message: string }\n /** The root's retained provider stream at the time of the throw, when the directory holds one:\n * a root that died mid-turn keeps what it had streamed, and this names it. */\n readonly rootStream?: RootStreamReceipt\n}\n\n/** The directory already holds a settle record, so the run it records must not be re-entered. */\nexport class SettledRunDirectoryError extends Error {\n readonly path: string\n /** The root of the recorded run, which is its `runId`. */\n readonly recordedRunId: string\n\n constructor(path: string, recordedRunId: string, requestedRunId: string) {\n super(\n recordedRunId === requestedRunId\n ? `supervisePursuit: ${path} records that run '${recordedRunId}' already settled; a settled run is not re-entered unless the call passes reopen: { operator, reason, operationId }`\n : `supervisePursuit: ${path} records that run '${recordedRunId}' already settled in this directory; a directory holds one settle record, so run '${requestedRunId}' needs its own runDir`,\n )\n this.name = 'SettledRunDirectoryError'\n this.path = path\n this.recordedRunId = recordedRunId\n }\n}\n\n/** A result member whose JSON form would misstate it. */\nclass UnrecordableSettleValueError extends TypeError {\n readonly path: string\n\n constructor(path: string, kind: string) {\n super(\n `supervisePursuit: result${path} is a ${kind}, which JSON cannot record faithfully; a settle record holds plain data only`,\n )\n this.name = 'UnrecordableSettleValueError'\n this.path = path\n }\n}\n\nconst PLAIN_PROTOTYPES = new Set<unknown>([Object.prototype, Array.prototype, null])\n\n/**\n * The JSON value of a result, or a throw naming the first member JSON would misstate. An\n * `undefined` member and a function are dropped, exactly as any JSON consumer drops them; a Map,\n * a Set, a Date, a typed array, or a class instance would be rewritten to `{}` or a string and\n * so is refused.\n */\nfunction jsonValue(result: unknown): unknown {\n const seen: unknown[] = []\n const visit = (value: unknown, path: string): void => {\n if (value === null || typeof value !== 'object') return\n if (value instanceof Map) throw new UnrecordableSettleValueError(path, 'Map')\n if (value instanceof Set) throw new UnrecordableSettleValueError(path, 'Set')\n if (value instanceof Date) throw new UnrecordableSettleValueError(path, 'Date')\n if (ArrayBuffer.isView(value) || value instanceof ArrayBuffer) {\n throw new UnrecordableSettleValueError(path, 'binary buffer')\n }\n if (!PLAIN_PROTOTYPES.has(Object.getPrototypeOf(value))) {\n throw new UnrecordableSettleValueError(path, 'class instance')\n }\n if (seen.includes(value)) throw new UnrecordableSettleValueError(path, 'cycle')\n seen.push(value)\n if (Array.isArray(value)) {\n for (const [index, item] of value.entries()) visit(item, `${path}[${index}]`)\n } else {\n for (const [key, item] of Object.entries(value)) visit(item, `${path}.${key}`)\n }\n seen.pop()\n }\n visit(result, '')\n return JSON.parse(JSON.stringify(result))\n}\n\n/**\n * The exact bytes `result.json` holds for a result: its JSON value serialized as RFC 8785\n * canonical JSON. Throws `UnrecordableSettleValueError` before any byte is written when the\n * result carries a value JSON would misstate.\n */\nexport function settleRecordJson(result: unknown): string {\n return canonicalCandidateJson(jsonValue(result))\n}\n\n/** The digest the settle record's bytes hash to: the candidate digest of the result's JSON value. */\nexport function settleRecordDigest(result: unknown): string {\n return canonicalCandidateDigest(jsonValue(result))\n}\n\n/** Publish `result.json` in the run directory once. Throws when a record is already there. */\nexport async function writeSettleRecord(runDir: string, result: unknown): Promise<string> {\n const path = resolve(runDir, SETTLE_RECORD_FILE)\n if (!publishExclusiveDurableFile(path, settleRecordJson(result))) {\n throw new Error(`supervisePursuit: ${path} already exists; a settle record is written once`)\n }\n return path\n}\n\n/** Replace `failure.json` in the run directory with the most recent throw. */\nexport async function writeFailureRecord(\n runDir: string,\n record: DurableFailureRecord,\n): Promise<string> {\n const path = resolve(runDir, FAILURE_RECORD_FILE)\n writeAtomicDurableFile(path, `${JSON.stringify(record, null, 2)}\\n`)\n return path\n}\n\n/**\n * Read the settle record a run directory holds, or `undefined` when it holds none. A file that\n * is present but is not a settle record is corruption and fails loud.\n */\nexport async function readSettleRecord(\n runDir: string,\n): Promise<SupervisedResult<unknown> | undefined> {\n return readTerminalFile(runDir, SETTLE_RECORD_FILE, parseSettleRecord)\n}\n\nasync function readTerminalFile<T>(\n runDir: string,\n file: string,\n parse: (text: string, path: string) => T,\n): Promise<T | undefined> {\n const path = resolve(runDir, file)\n try {\n return parse(await readFile(path, 'utf8'), path)\n } catch (error) {\n if (isNoEntError(error)) return undefined\n throw error\n }\n}\n\nfunction parseTerminalJson(text: string, path: string): unknown {\n try {\n return JSON.parse(text)\n } catch (cause) {\n throw new Error(`supervisePursuit: ${path} is not valid JSON`, { cause })\n }\n}\n\n/** Parse settle-record bytes already read, so a caller hashes and parses the same bytes. */\nexport function parseSettleRecord(text: string, path: string): SupervisedResult<unknown> {\n const parsed = parseTerminalJson(text, path)\n const record = parsed as { kind?: unknown; tree?: { root?: unknown } }\n if (\n typeof record !== 'object' ||\n record === null ||\n typeof record.kind !== 'string' ||\n typeof record.tree !== 'object' ||\n record.tree === null ||\n typeof record.tree.root !== 'string'\n ) {\n throw new Error(`supervisePursuit: ${path} is not a settle record (no kind or tree.root)`)\n }\n return parsed as SupervisedResult<unknown>\n}\n\n/** Read the most recent failure record, or `undefined` when the directory holds none. */\nexport async function readFailureRecord(runDir: string): Promise<DurableFailureRecord | undefined> {\n return readTerminalFile(runDir, FAILURE_RECORD_FILE, (text, path) => {\n const parsed = parseTerminalJson(text, path)\n const record = parsed as Partial<DurableFailureRecord>\n if (\n typeof record !== 'object' ||\n record === null ||\n typeof record.runId !== 'string' ||\n typeof record.pursuitId !== 'string' ||\n typeof record.at !== 'string' ||\n typeof record.error?.name !== 'string' ||\n typeof record.error.message !== 'string' ||\n (record.rootStream !== undefined &&\n (typeof record.rootStream.ref !== 'string' || typeof record.rootStream.events !== 'number'))\n ) {\n throw new Error(`supervisePursuit: ${path} is not a failure record`)\n }\n return parsed as DurableFailureRecord\n })\n}\n"],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"snapshot-Cgj2Wzi6.js","names":[],"sources":["../src/redact.ts","../src/runtime/supervise/error-message.ts","../src/runtime/supervise/snapshot.ts"],"sourcesContent":["/**\n * Redaction for values that may leave the Runtime process. The built-in\n * redactor is agent-eval's redaction core (`@tangle-network/agent-eval/traces`,\n * default profile): credentials found by field name or value shape are\n * replaced whole, email, card, SSN and phone values in place, and token counts\n * such as `inputTokens` or `max_tokens` are kept. A customer with\n * domain-specific PII supplies their own `redact` hook.\n *\n * This is narrower than `src/sanitize.ts`, which drops fields of the runtime's\n * *event envelope* unless the caller opts in: here the value is opaque customer\n * payload, so the scrub is value-shaped, not schema-shaped.\n *\n * @experimental\n */\n\nimport { REDACTION_VERSION, redact } from '@tangle-network/agent-eval/traces'\n\n/** A redactor maps an arbitrary trace value to a safe-to-export value. Pure;\n * must not throw on cyclic input (the default tolerates cycles). */\nexport type Redactor = (value: unknown) => unknown\n\n/**\n * The built-in redactor. Cycle-safe, depth-bounded and total: it never throws\n * on customer input and never mutates it.\n */\nexport function defaultRedactor(value: unknown): unknown {\n return redact(value).value\n}\n\n/** Stable identity input for saved work that depends on built-in redaction behavior. */\nexport function defaultRedactorIdentityMaterial(): unknown {\n return {\n core: '@tangle-network/agent-eval/traces redact',\n profile: 'default',\n version: REDACTION_VERSION,\n }\n}\n\n/**\n * Resolve the redactor a client uses. A caller-supplied hook handles\n * domain-specific values first, then the built-in scrubber still removes\n * credentials and personal data. Returning `false` is the explicit opt-out for\n * already-reviewed public values.\n */\nexport function resolveRedactor(redact: Redactor | false | undefined): Redactor {\n if (redact === false) return (value) => value\n if (!redact) return defaultRedactor\n return (value) => defaultRedactor(redact(value))\n}\n","import { defaultRedactor } from '../../redact'\n\nconst maxCauseDepth = 4\nconst maxMessageLength = 32_768\nconst maxPartLength = 2_048\n\n/** A persisted failure must explain its wrappers without exporting credentials or unbounded data. */\nexport function errorText(value: unknown): string {\n let text: string\n try {\n text = typeof value === 'string' ? value : (JSON.stringify(value) ?? String(value))\n } catch {\n text = '[unprintable rejection]'\n }\n return String(defaultRedactor(text)).slice(0, maxMessageLength)\n}\n\nexport function errorProperty(\n error: Error,\n field: 'name' | 'message' | 'stack',\n): string | undefined {\n try {\n const value = error[field]\n return value === undefined\n ? undefined\n : errorText(value).slice(0, field === 'name' ? 256 : maxMessageLength)\n } catch {\n return `[unreadable error ${field}]`\n }\n}\n\n/** An HTTP status carried on a thrown error, read without trusting its getter. Provider SDKs put\n * one on their own error classes, so this is how a refusal is recognised outside the transport\n * taxonomy — for the persisted message here, and for the driver's retry verdict. */\nexport function errorHttpStatus(error: Error): number | undefined {\n try {\n const status: unknown = Reflect.get(error, 'status')\n return typeof status === 'number' && Number.isInteger(status) && status >= 100 && status <= 599\n ? status\n : undefined\n } catch {\n return undefined\n }\n}\n\n/** Shared by child settlements, driver attempts, and the final no-winner result. */\nexport function errMessage(error: unknown): string {\n const parts: string[] = []\n const seen = new Set<Error>()\n let current = error\n for (let depth = 0; depth <= maxCauseDepth; depth += 1) {\n try {\n if (!(current instanceof Error)) {\n parts.push(errorText(current).slice(0, maxPartLength))\n break\n }\n if (seen.has(current)) {\n parts.push('[circular]')\n break\n }\n seen.add(current)\n const status = errorHttpStatus(current)\n const message =\n (status === undefined ? '' : `HTTP ${status}: `) + (errorProperty(current, 'message') ?? '')\n // An AggregateError's members carry its evidence: name each, one level deep.\n const members: unknown = Reflect.get(current, 'errors')\n const named = Array.isArray(members)\n ? ` [${members.map((m) => (m instanceof Error ? `${errorProperty(m, 'name')}: ${errorProperty(m, 'message')}` : errorText(m))).join('; ')}]`\n : ''\n const part = depth === 0 ? message : `${errorProperty(current, 'name')}: ${message}`\n parts.push(`${part}${named}`.slice(0, maxPartLength))\n current = current.cause\n if (current === undefined || current === null) break\n if (depth === maxCauseDepth) parts.push('[cause chain truncated]')\n } catch {\n parts.push('[unreadable error cause]')\n break\n }\n }\n return parts.join(': caused by ').slice(0, maxMessageLength)\n}\n\n/** The error and its causes (`cause`, and `errors` members), bounded and cycle-safe. */\nexport function causeChain(error: unknown): object[] {\n const chain: object[] = []\n const queue: unknown[] = [error]\n while (queue.length > 0 && chain.length < 12) {\n const value = queue.shift()\n if (typeof value !== 'object' || value === null || chain.includes(value)) continue\n chain.push(value)\n try {\n const errors: unknown = Reflect.get(value, 'errors')\n if (Array.isArray(errors)) queue.push(...errors)\n queue.push(Reflect.get(value, 'cause'))\n } catch {\n // A cause that cannot be read ends this branch of the walk.\n }\n }\n return chain\n}\n","import { ValidationError } from '../../errors'\n\n/** Deeply detach and freeze untrusted data at a runtime decision boundary. The clone prevents the\n * caller from mutating it later; the freeze prevents downstream code from mutating the snapshot.\n * Strings are immutable, so the snapshot shares the caller's strings instead of copying them. */\nexport function detachedSnapshot<T>(value: T, context: string): T {\n let clone: T\n try {\n clone = structuredClone(value)\n } catch (error) {\n throw new ValidationError(`${context}: input must be structured-cloneable`, { cause: error })\n }\n return deepFreeze(shareSourceStrings(value, clone))\n}\n\n/** Detach a value from its caller and freeze it, without the `ValidationError` framing\n * {@link detachedSnapshot} adds. For a boundary that has already validated its input. */\nexport function detachedFrozen<T>(value: T): T {\n return deepFreeze(shareSourceStrings(value, structuredClone(value)))\n}\n\n/**\n * Point each string in a fresh structured clone at the equal string in its source.\n *\n * `structuredClone` copies every string, and a copied string buys no isolation: only objects and\n * arrays can change through a shared reference. A spawned profile passes several boundaries, and\n * each one kept its own copy: in a reproduction of Discovery's hosted coordinator, a child profile\n * that mounts a 5.3 MB file packet was held four times per spawned child. A scope keeps every\n * child it spawned, so the heap grew about 22 MB per spawn, and hosted coordinators died with V8\n * heap OOM after 37 spawns.\n *\n * The walk pairs only own data properties of plain objects and arrays. Accessors, Maps, Sets and\n * other cloned types keep the clone's values. A string is replaced only by a string equal to it,\n * so the snapshot holds exactly the clone's value. The snapshot keeps the source's strings alive.\n */\nfunction shareSourceStrings<T>(source: unknown, clone: T): T {\n const visited = new Set<object>()\n const visit = (from: unknown, to: unknown): void => {\n if (from === null || to === null || typeof from !== 'object' || typeof to !== 'object') return\n const array = Array.isArray(to)\n if (array !== Array.isArray(from)) return\n if (!array && Object.getPrototypeOf(to) !== Object.prototype) return\n if (visited.has(to)) return\n visited.add(to)\n const target = to as Record<string, unknown>\n for (const key of Object.keys(target)) {\n const own = Object.getOwnPropertyDescriptor(from, key)\n if (own === undefined || !('value' in own)) continue\n const cloned = target[key]\n if (typeof cloned === 'string') {\n if (own.value === cloned) target[key] = own.value\n } else visit(own.value, cloned)\n }\n }\n visit(source, clone)\n return clone\n}\n\n/**\n * Replace each string in a freshly parsed JSON value with an equal string already in `pool`, and\n * add the new ones. One recovery pass parses every interrupted child's profile from its own blob,\n * so children that carry the same file packet would otherwise hold one copy each. The value is\n * updated in place, so it must belong to the caller; frozen objects are left as they are.\n */\nexport function shareParsedStrings<T>(value: T, pool: Map<string, string>): T {\n const visit = (node: unknown): void => {\n if (node === null || typeof node !== 'object' || Object.isFrozen(node)) return\n if (!Array.isArray(node) && Object.getPrototypeOf(node) !== Object.prototype) return\n const target = node as Record<string, unknown>\n for (const key of Object.keys(target)) {\n const item = target[key]\n if (typeof item !== 'string') {\n visit(item)\n continue\n }\n const shared = pool.get(item)\n if (shared === undefined) pool.set(item, item)\n else target[key] = shared\n }\n }\n visit(value)\n return value\n}\n\nfunction deepFreeze<T>(value: T, seen = new Set<object>()): T {\n // `Object.freeze` throws `TypeError: Cannot freeze array buffer views with elements` on any\n // non-empty TypedArray or Buffer, so binary inside a payload must be handed back untouched\n // rather than frozen. Its bytes are already detached by the `structuredClone` above.\n if (value === null || typeof value !== 'object' || ArrayBuffer.isView(value) || seen.has(value)) {\n return value\n }\n seen.add(value)\n for (const child of Object.values(value as Record<string, unknown>)) deepFreeze(child, seen)\n return Object.freeze(value)\n}\n"],"mappings":"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"}
|