@tangle-network/agent-runtime 0.138.1 → 0.140.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/dist/{activation-AyIFaunX.js → activation-eLJ6uRlP.js} +3 -3
  2. package/dist/{activation-AyIFaunX.js.map → activation-eLJ6uRlP.js.map} +1 -1
  3. package/dist/agent.d.ts +4 -4
  4. package/dist/agent.js +3 -3
  5. package/dist/{analyst-loop-Dk6_xfhI.js → analyst-loop-DtOEXGzR.js} +3 -3
  6. package/dist/{analyst-loop-Dk6_xfhI.js.map → analyst-loop-DtOEXGzR.js.map} +1 -1
  7. package/dist/analyst-loop.d.ts +1 -1
  8. package/dist/analyst-loop.js +1 -1
  9. package/dist/{authoring-Cw6Ufsng.js → authoring-J93uFAwd.js} +3 -3
  10. package/dist/{authoring-Cw6Ufsng.js.map → authoring-J93uFAwd.js.map} +1 -1
  11. package/dist/candidate-execution/index.d.ts +3 -3
  12. package/dist/candidate-execution/index.js +4 -4
  13. package/dist/{candidate-execution-CN2hO-og.js → candidate-execution-uuUeFSc6.js} +5 -5
  14. package/dist/{candidate-execution-CN2hO-og.js.map → candidate-execution-uuUeFSc6.js.map} +1 -1
  15. package/dist/{conversation-DIUtiLkC.js → conversation-C3eZCvLd.js} +8 -6
  16. package/dist/conversation-C3eZCvLd.js.map +1 -0
  17. package/dist/conversation.d.ts +1 -1
  18. package/dist/conversation.js +1 -1
  19. package/dist/durable.d.ts +1 -1
  20. package/dist/{environment-provider-CLNVqp6H.js → environment-provider-BAO8wt1_.js} +147 -48
  21. package/dist/environment-provider-BAO8wt1_.js.map +1 -0
  22. package/dist/{environment-provider-DA8LqBV-.d.ts → environment-provider-Bu3S3v78.d.ts} +3 -3
  23. package/dist/environment-provider.d.ts +1 -1
  24. package/dist/environment-provider.js +1 -1
  25. package/dist/{errors-CVIDr7GQ.js → errors-CDZ8XsVj.js} +34 -9
  26. package/dist/errors-CDZ8XsVj.js.map +1 -0
  27. package/dist/{graph-DxU92LTL.js → graph-BbMjq7-x.js} +5 -5
  28. package/dist/{graph-DxU92LTL.js.map → graph-BbMjq7-x.js.map} +1 -1
  29. package/dist/{improvement-cycle-hIOGxDtV.js → improvement-cycle-D6rhMJR0.js} +67 -66
  30. package/dist/improvement-cycle-D6rhMJR0.js.map +1 -0
  31. package/dist/{index-Bdgpx2Dx.d.ts → index-C6yfz0QN.d.ts} +5 -5
  32. package/dist/{index-BOgzou1U.d.ts → index-COnuT0h7.d.ts} +263 -82
  33. package/dist/{index-CETQJlqT.d.ts → index-CTz17pH6.d.ts} +11 -11
  34. package/dist/{index-DQxQgKDs.d.ts → index-DQv7iCeE.d.ts} +6 -6
  35. package/dist/index.d.ts +16 -16
  36. package/dist/index.js +16 -16
  37. package/dist/intelligence.d.ts +736 -681
  38. package/dist/intelligence.js +113 -8
  39. package/dist/intelligence.js.map +1 -1
  40. package/dist/kernel.d.ts +7 -7
  41. package/dist/kernel.js +12 -12
  42. package/dist/{knowledge-C-JiS5Xg.js → knowledge-CD-_FbJT.js} +7 -7
  43. package/dist/{knowledge-C-JiS5Xg.js.map → knowledge-CD-_FbJT.js.map} +1 -1
  44. package/dist/knowledge.d.ts +1 -1
  45. package/dist/knowledge.js +1 -1
  46. package/dist/{loop-runner-bin-B_Ww2iqY.js → loop-runner-bin-BBz_ACfQ.js} +5 -5
  47. package/dist/{loop-runner-bin-B_Ww2iqY.js.map → loop-runner-bin-BBz_ACfQ.js.map} +1 -1
  48. package/dist/{loop-runner-bin-OH61zEVw.d.ts → loop-runner-bin-DUNxyuaG.d.ts} +3 -3
  49. package/dist/loop-runner-bin.d.ts +1 -1
  50. package/dist/loop-runner-bin.js +1 -1
  51. package/dist/{materialization-BP5zspr2.js → materialization-CrdcfWXp.js} +4 -4
  52. package/dist/{materialization-BP5zspr2.js.map → materialization-CrdcfWXp.js.map} +1 -1
  53. package/dist/mcp/bin.js +4 -4
  54. package/dist/mcp/index.d.ts +5 -5
  55. package/dist/mcp/index.js +8 -8
  56. package/dist/mcp/memory-bin.js +1 -1
  57. package/dist/{memory-server-Cdpy7Uu8.js → memory-server-DsKOhzGf.js} +3 -3
  58. package/dist/{memory-server-Cdpy7Uu8.js.map → memory-server-DsKOhzGf.js.map} +1 -1
  59. package/dist/{model-policy-UTTc9Z-A.js → model-policy-DgRJIJse.js} +2 -2
  60. package/dist/{model-policy-UTTc9Z-A.js.map → model-policy-DgRJIJse.js.map} +1 -1
  61. package/dist/{openai-tools-BKJqaQ1b.js → openai-tools-DIKr72_l.js} +2 -2
  62. package/dist/{openai-tools-BKJqaQ1b.js.map → openai-tools-DIKr72_l.js.map} +1 -1
  63. package/dist/{openai-tools-DU3TZvFY.d.ts → openai-tools-yoRRzAUW.d.ts} +2 -2
  64. package/dist/{prepare-CYqGSYza.js → prepare-DK1qnk7-.js} +3 -3
  65. package/dist/{prepare-CYqGSYza.js.map → prepare-DK1qnk7-.js.map} +1 -1
  66. package/dist/primeintellect/index.d.ts +1 -1
  67. package/dist/profiles.d.ts +1 -1
  68. package/dist/profiles.js +1 -1
  69. package/dist/{protected-model-port-DEsTWOFs.d.ts → protected-model-port-B8ssMyUg.d.ts} +7 -7
  70. package/dist/{protected-model-port-B6DW_x2I.js → protected-model-port-DHeCm_UF.js} +2 -2
  71. package/dist/{protected-model-port-B6DW_x2I.js.map → protected-model-port-DHeCm_UF.js.map} +1 -1
  72. package/dist/{redact-BwEdhuVH.d.ts → redact-CLw2B7Qj.d.ts} +9 -9
  73. package/dist/{researcher-DBfKdnAz.js → researcher-CiSY6Wzb.js} +3 -3
  74. package/dist/{researcher-DBfKdnAz.js.map → researcher-CiSY6Wzb.js.map} +1 -1
  75. package/dist/retained-run-binding-Dp2e8xne.js +268 -0
  76. package/dist/retained-run-binding-Dp2e8xne.js.map +1 -0
  77. package/dist/{runtime-DhPCNvuH.d.ts → runtime-CVNWEw16.d.ts} +4 -4
  78. package/dist/{runtime-CUpB4rEP.js → runtime-tTA2iCZQ.js} +650 -222
  79. package/dist/runtime-tTA2iCZQ.js.map +1 -0
  80. package/dist/{sandbox-events-CA2amHoA.js → sandbox-events-DPmXlcKw.js} +24 -2
  81. package/dist/sandbox-events-DPmXlcKw.js.map +1 -0
  82. package/dist/{snapshot-BOIprwBk.js → snapshot-cK9K420n.js} +2 -2
  83. package/dist/{snapshot-BOIprwBk.js.map → snapshot-cK9K420n.js.map} +1 -1
  84. package/dist/{spawn-journal-DVFqdzO9.js → spawn-journal-DGXei3xG.js} +3 -3
  85. package/dist/{spawn-journal-DVFqdzO9.js.map → spawn-journal-DGXei3xG.js.map} +1 -1
  86. package/dist/{stream-agent-turn-Q5ellSUu.js → stream-agent-turn-4kUH8Nnn.js} +77 -34
  87. package/dist/stream-agent-turn-4kUH8Nnn.js.map +1 -0
  88. package/dist/{stream-agent-turn-DhPlvHwp.d.ts → stream-agent-turn-RjrKGk6S.d.ts} +5 -8
  89. package/dist/{structural-rollout-CwtVIJf-.js → structural-rollout-7LP9Ex0F.js} +9 -9
  90. package/dist/structural-rollout-7LP9Ex0F.js.map +1 -0
  91. package/dist/{supervise-CUJRmx3s.js → supervise-Cx1QY_hj.js} +9 -9
  92. package/dist/{supervise-CUJRmx3s.js.map → supervise-Cx1QY_hj.js.map} +1 -1
  93. package/dist/{supervisor-BoC2tFgH.js → supervisor-BV72aDmP.js} +13 -9
  94. package/dist/supervisor-BV72aDmP.js.map +1 -0
  95. package/dist/testing.d.ts +2 -2
  96. package/dist/testing.js +12 -12
  97. package/dist/{tool-server-Dh-NcbHr.js → tool-server-DEmLr9YY.js} +2 -2
  98. package/dist/{tool-server-Dh-NcbHr.js.map → tool-server-DEmLr9YY.js.map} +1 -1
  99. package/dist/{types-CxU37Uzr.d.ts → types-19ZOddS3.d.ts} +2 -2
  100. package/dist/{types-BBwGSiAj.d.ts → types-C244Huc9.d.ts} +16 -7
  101. package/dist/{types-BCkweg3w.d.ts → types-D4arYjUl.d.ts} +6 -6
  102. package/dist/{workspace-archive-C7AvjSVb.js → workspace-archive-HYlsPhfm.js} +2 -2
  103. package/dist/{workspace-archive-C7AvjSVb.js.map → workspace-archive-HYlsPhfm.js.map} +1 -1
  104. package/package.json +8 -8
  105. package/dist/conversation-DIUtiLkC.js.map +0 -1
  106. package/dist/environment-provider-CLNVqp6H.js.map +0 -1
  107. package/dist/errors-CVIDr7GQ.js.map +0 -1
  108. package/dist/improvement-cycle-hIOGxDtV.js.map +0 -1
  109. package/dist/runtime-CUpB4rEP.js.map +0 -1
  110. package/dist/sandbox-events-CA2amHoA.js.map +0 -1
  111. package/dist/stream-agent-turn-Q5ellSUu.js.map +0 -1
  112. package/dist/structural-rollout-CwtVIJf-.js.map +0 -1
  113. package/dist/supervisor-BoC2tFgH.js.map +0 -1
@@ -1,21 +1,23 @@
1
- import { c as RetainedRunAdmissionError, f as ValidationError, l as RetainedRunDispatchBindingError, n as AnalystError, s as PlannerError } from "./errors-CVIDr7GQ.js";
2
- import "./stream-agent-turn-Q5ellSUu.js";
3
- import { g as isTraceAnalysisStore, i as InMemorySpawnJournal, r as InMemoryResultBlobStore, y as contentAddress } from "./spawn-journal-DVFqdzO9.js";
1
+ import { C as sameControlCoordinates, S as isTerminalSessionStatus, _ as exactSession, a as assertEventBinding, b as freezeControlRef, c as assertSequence, d as awaitAbortable, f as cancellationRequest, g as exactControlRef, h as exactContinuedControlRef, i as assertCanonicalEventBinding, l as assertStableText, m as delay, n as abortError, o as assertInteractionBinding, p as copyControlRef, r as assertBoundaryBinding, s as assertResultBinding, t as RetainedRunProviderContractError, u as assertWaitDuration, v as exactSessionCancel, w as freshTurnInput, x as hasDurableCancel, y as exactSessionResult } from "./retained-run-binding-Dp2e8xne.js";
2
+ import { c as RetainedInteractiveAdmissionError, d as RetainedRunDispatchBindingError, l as RetainedInteractiveBindingError, m as ValidationError, n as AnalystError, s as PlannerError, u as RetainedRunAdmissionError } from "./errors-CDZ8XsVj.js";
3
+ import "./stream-agent-turn-4kUH8Nnn.js";
4
+ import { t as detachedSnapshot } from "./snapshot-cK9K420n.js";
5
+ import { g as isTraceAnalysisStore, i as InMemorySpawnJournal, r as InMemoryResultBlobStore, y as contentAddress } from "./spawn-journal-DGXei3xG.js";
4
6
  import { _ as zeroTokenUsage, a as hasCompleteCacheBreakdown, d as sleep, f as stringifySafe, h as usdEstimatedOf, l as randomSuffix, n as chargedTokens, o as isAbortError, r as cloneTokenUsage, t as addTokenUsage } from "./util-C1bv6yog.js";
5
7
  import { i as redactProtectedValue, r as redactProtectedReason } from "./protected-redaction--F3v1oo8.js";
6
- import { a as notifySandboxEventObserver, c as parseCanonicalTransportEvent, s as extractTransportEventIdentity } from "./sandbox-events-CA2amHoA.js";
7
- import { c as profileProviderModel, i as concreteModelId, s as profileModelExecutionSettings, t as assertExecutableAgentProfile } from "./model-policy-UTTc9Z-A.js";
8
- import { E as executableAgentSpecSnapshot, T as executableAgentProfileSnapshot } from "./materialization-BP5zspr2.js";
9
- import { E as rollingDispatch, I as createExecutor, L as createExecutorRegistry, _t as runBrainLoop, ft as runAgentRounds, g as settledToIteration, gt as routerBrain, l as withDriverExecutor, mt as probeSandboxCapabilities, n as createSupervisor, pt as createSandboxLineage, q as createPushTraceSource, ut as defaultSelectWinner, vt as canonicalObservedModel, z as createWorktreeCliExecutor } from "./supervisor-BoC2tFgH.js";
10
- import "./environment-provider-CLNVqp6H.js";
8
+ import { c as extractTransportEventIdentity, l as parseCanonicalTransportEvent, o as notifySandboxEventObserver } from "./sandbox-events-DPmXlcKw.js";
9
+ import { c as profileProviderModel, i as concreteModelId, s as profileModelExecutionSettings, t as assertExecutableAgentProfile } from "./model-policy-DgRJIJse.js";
10
+ import { E as executableAgentSpecSnapshot, T as executableAgentProfileSnapshot } from "./materialization-CrdcfWXp.js";
11
+ import { E as rollingDispatch, I as createExecutor, L as createExecutorRegistry, _t as runBrainLoop, ft as runAgentRounds, g as settledToIteration, gt as routerBrain, l as withDriverExecutor, mt as probeSandboxCapabilities, n as createSupervisor, pt as createSandboxLineage, q as createPushTraceSource, ut as defaultSelectWinner, vt as canonicalObservedModel, z as createWorktreeCliExecutor } from "./supervisor-BV72aDmP.js";
12
+ import "./environment-provider-BAO8wt1_.js";
11
13
  import { i as notifyRuntimeHookEvent } from "./runtime-hooks-C7iJOWm3.js";
12
- import { C as observe, O as strategyAuthorMethod, T as profileChatClient, b as sample, v as refine, x as sampleThenRefine, y as runAgentic } from "./structural-rollout-CwtVIJf-.js";
13
- import { It as gateOnDeliverable, Lt as mapExecutorResult, n as supervise } from "./supervise-CUJRmx3s.js";
14
- import "./authoring-Cw6Ufsng.js";
15
- import "./graph-DxU92LTL.js";
14
+ import { C as observe, O as strategyAuthorMethod, T as profileChatClient, b as sample, v as refine, x as sampleThenRefine, y as runAgentic } from "./structural-rollout-7LP9Ex0F.js";
15
+ import { It as gateOnDeliverable, Lt as mapExecutorResult, n as supervise } from "./supervise-Cx1QY_hj.js";
16
+ import "./authoring-J93uFAwd.js";
17
+ import "./graph-BbMjq7-x.js";
18
+ import { AgentEnvironmentCapabilitiesSchema, AgentExactRunControlRefSchema, AgentInteractiveSessionControlClaimAcknowledgementSchema, AgentInteractiveSessionControlClaimSchema, AgentInteractiveSessionPromptAcknowledgementSchema, AgentInteractiveSessionRefSchema, AgentInteractiveSessionStatusSchema, AgentInteractiveSessionStopAcknowledgementSchema, AgentNativeContextContinuationResultSchema, AgentTurnResultSchema, InteractionAcknowledgementSchema, InteractionResponseCommandSchema, NativeContextBoundaryProofSchema, NativeContextContinuationRequestSchema, RuntimeEventEnvelopeSchema, TerminalReplayWindowSchema, TerminalSessionRefSchema, agentInteractiveSessionControlClaimAcknowledgementMatchesRequest, agentInteractiveSessionControlClaimMatchesRef, agentInteractiveSessionControlClaimRequestDigest, agentInteractiveSessionPromptAcknowledgementMatchesCommand, agentInteractiveSessionRefMatchesStart, agentInteractiveSessionRunRef, agentInteractiveSessionStatusMatchesRef, agentInteractiveSessionStopAcknowledgementMatchesCommand, agentNativeContextContinuationResultMatchesRequest, agentProfileSchema, canonicalAgentProfileDigest, canonicalCandidateDigest, exactAgentInteractiveSessionStart, nativeContextContinuationTurnDigest, validateAgentProfileSecurity } from "@tangle-network/agent-interface";
16
19
  import { CODING_HARNESSES, InMemoryTraceStore, OUTPUT_VALUE, benjaminiHochberg, buildTrajectory, computeFindingId as computeFindingId$1, confidenceInterval, expandProfileAxes, makeFinding as makeFinding$1, pairedBootstrap, paretoFrontier, wilcoxonSignedRank, wilson } from "@tangle-network/agent-eval";
17
20
  import { heldoutSignificance, runProfileMatrix } from "@tangle-network/agent-eval/campaign";
18
- import { AgentEnvironmentCapabilitiesSchema, AgentExactRunControlRefSchema, AgentNativeContextContinuationResultSchema, AgentRunCancellationAcknowledgementSchema, AgentRunCancellationRequestSchema, AgentTurnResultSchema, InteractionAcknowledgementSchema, InteractionResponseCommandSchema, NativeContextBoundaryProofSchema, NativeContextContinuationRequestSchema, RuntimeEventEnvelopeSchema, agentNativeContextContinuationResultMatchesRequest, agentProfileSchema, agentRunCancellationAcknowledgementMatchesRequest, agentRunCancellationRequestDigest, canonicalAgentProfileDigest, canonicalCandidateDigest, nativeContextContinuationTurnDigest, validateAgentProfileSecurity } from "@tangle-network/agent-interface";
19
21
  import { createHash } from "node:crypto";
20
22
  import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
21
23
  import { mkdir, readFile, realpath, writeFile } from "node:fs/promises";
@@ -3483,187 +3485,242 @@ function promotionGate(opts) {
3483
3485
  };
3484
3486
  }
3485
3487
  //#endregion
3486
- //#region src/runtime/retained-run-binding.ts
3487
- function exactSession(environment, controlRef) {
3488
- if (environment.id !== controlRef.environmentId || environment.provider !== controlRef.provider) throw new Error("provider reconstructed a different retained environment");
3489
- if (!environment.session || !controlRef.sessionId) throw new Error("retained run control requires a provider session id");
3490
- const session = environment.session(controlRef.sessionId, { controlRef });
3491
- if (session.id !== controlRef.sessionId) throw new Error("provider reconstructed a different session");
3492
- if (session.controlRef === void 0) throw new Error("provider session did not return its provider-owned run control reference");
3493
- const currentControlRef = AgentExactRunControlRefSchema.parse(session.controlRef);
3494
- if (!sameControlCoordinates(currentControlRef, controlRef)) throw new Error("provider session reconstructed a different retained session");
3495
- if (canonicalCandidateDigest(currentControlRef) !== canonicalCandidateDigest(controlRef)) throw new Error("provider session did not retain the exact run control reference");
3496
- return {
3497
- session,
3498
- controlRef: currentControlRef
3499
- };
3500
- }
3501
- function sameControlCoordinates(left, right) {
3502
- return canonicalCandidateDigest(left) === canonicalCandidateDigest(right);
3503
- }
3504
- function freezeControlRef(controlRef) {
3505
- return Object.freeze({ ...AgentExactRunControlRefSchema.parse(controlRef) });
3506
- }
3507
- function copyControlRef(controlRef) {
3508
- return { ...controlRef };
3509
- }
3510
- function exactControlRef(candidate, expected) {
3511
- if (!candidate) throw new Error("provider dispatch returned no durable run control reference");
3512
- const controlRef = AgentExactRunControlRefSchema.parse(candidate);
3513
- if (controlRef.provider !== expected.provider || controlRef.environmentId !== expected.environmentId || controlRef.sessionId !== expected.sessionId) throw new Error("provider dispatch returned control coordinates for another run");
3514
- return controlRef;
3515
- }
3516
- function exactContinuedControlRef(candidate, initial) {
3517
- const controlRef = AgentExactRunControlRefSchema.parse(candidate);
3518
- if (controlRef.provider !== initial.provider || controlRef.environmentId !== initial.environmentId || controlRef.sessionId !== initial.sessionId) throw new Error("provider continuation advanced to another retained session");
3519
- if (controlRef.runId === initial.runId && controlRef.executionId === initial.executionId) throw new Error("provider continuation did not return a new exact run execution");
3520
- return controlRef;
3488
+ //#region src/runtime/retained-interactive-handle.ts
3489
+ function createRetainedInteractiveRunHandle(environment, inputRef, capabilities, requestedStart) {
3490
+ const ref = freezeInteractiveRef(inputRef);
3491
+ const source = environment.interactive(ref);
3492
+ if (!sameInteractiveRef(source.ref, ref)) throw new Error("provider reconstructed a different interactive process");
3493
+ if (!source.sendPrompt) throw new Error("provider declared interactive prompt support but exposed no prompt method");
3494
+ return Object.freeze({
3495
+ ref,
3496
+ capabilities,
3497
+ claimControl: async (request, options) => exactClaim(ref, request, await awaitAbortable(Promise.resolve().then(() => source.claimControl(request, options)), options?.signal)),
3498
+ status: async (options) => exactStatus(ref, await awaitAbortable(Promise.resolve().then(() => source.status(options)), options?.signal), requestedStart),
3499
+ attach: async (request, options) => exactTerminal(ref, request, await awaitAbortable(Promise.resolve().then(() => source.attach(request, options)), options?.signal)),
3500
+ sendPrompt: async (command, options) => exactPrompt(ref, await awaitAbortable(Promise.resolve().then(() => source.sendPrompt(command, options)), options?.signal), command),
3501
+ stop: async (command, options) => exactStop(ref, await awaitAbortable(Promise.resolve().then(() => source.stop(command, options)), options?.signal), command)
3502
+ });
3521
3503
  }
3522
- function assertInteractionBinding(controlRef, command) {
3523
- if (command.binding.runId !== controlRef.runId || command.binding.provider !== controlRef.provider || command.binding.environmentId !== controlRef.environmentId || command.binding.sessionId !== controlRef.sessionId || command.binding.executionId !== controlRef.executionId) throw new Error("interaction response command does not target this retained run");
3504
+ function freezeInteractiveRef(value) {
3505
+ return detachedSnapshot(AgentInteractiveSessionRefSchema.parse(value), "interactive session ref");
3524
3506
  }
3525
- function assertBoundaryBinding(controlRef, proof) {
3526
- if (proof.runId !== controlRef.runId || proof.provider !== controlRef.provider || proof.environmentId !== controlRef.environmentId || proof.sessionId !== controlRef.sessionId || proof.executionId !== controlRef.executionId || proof.requestDigest !== controlRef.requestDigest) throw new Error("native context proof does not identify this retained run");
3507
+ function exactClaim(ref, request, value) {
3508
+ const acknowledgement = parseProviderAcknowledgement(AgentInteractiveSessionControlClaimAcknowledgementSchema, value, "control claim");
3509
+ if (!agentInteractiveSessionControlClaimAcknowledgementMatchesRequest(request, acknowledgement)) throw new RetainedRunProviderContractError("provider returned a control claim acknowledgement for another request");
3510
+ if (acknowledgement.control && !agentInteractiveSessionControlClaimMatchesRef(ref, acknowledgement.control)) throw new RetainedRunProviderContractError("provider returned a control claim for another interactive process");
3511
+ return acknowledgement;
3527
3512
  }
3528
- function assertSequence(value, label) {
3529
- if (typeof value !== "number" || !Number.isSafeInteger(value) || value < 0) throw new Error(`${label} must be a non-negative safe integer`);
3513
+ function exactPrompt(ref, value, command) {
3514
+ const acknowledgement = parseProviderAcknowledgement(AgentInteractiveSessionPromptAcknowledgementSchema, value, "prompt");
3515
+ if (!agentInteractiveSessionPromptAcknowledgementMatchesCommand(command, acknowledgement)) throw new RetainedRunProviderContractError("provider returned a prompt acknowledgement for another request");
3516
+ if (!agentInteractiveSessionControlClaimMatchesRef(ref, acknowledgement.control)) throw new RetainedRunProviderContractError("provider returned a prompt acknowledgement for another interactive process");
3517
+ return acknowledgement;
3530
3518
  }
3531
- function assertResultBinding(controlRef, result) {
3532
- if (result.sessionId !== controlRef.sessionId) throw new Error("provider returned a result for another retained session");
3533
- const metadata = result.metadata;
3534
- if (controlRef.executionId !== void 0 && metadata?.executionId !== controlRef.executionId) throw new Error("provider returned a result for another retained execution");
3535
- if (metadata?.runId !== controlRef.runId) throw new Error("provider returned a result for another retained run");
3536
- if (metadata?.requestDigest !== controlRef.requestDigest) throw new Error("provider returned a result for another retained request");
3519
+ function exactStop(ref, value, command) {
3520
+ const acknowledgement = parseProviderAcknowledgement(AgentInteractiveSessionStopAcknowledgementSchema, value, "stop");
3521
+ if (!agentInteractiveSessionStopAcknowledgementMatchesCommand(command, acknowledgement)) throw new RetainedRunProviderContractError("provider returned a stop acknowledgement for another request");
3522
+ if (!agentInteractiveSessionControlClaimMatchesRef(ref, acknowledgement.control)) throw new RetainedRunProviderContractError("provider returned a stop acknowledgement for another interactive process");
3523
+ return acknowledgement;
3537
3524
  }
3538
- var RetainedRunProviderContractError = class extends Error {
3539
- constructor(message) {
3540
- super(message);
3541
- this.name = "RetainedRunProviderContractError";
3525
+ function parseProviderAcknowledgement(schema, value, operation) {
3526
+ try {
3527
+ return schema.parse(value);
3528
+ } catch {
3529
+ throw new RetainedRunProviderContractError(`provider returned an invalid interactive ${operation} acknowledgement`);
3542
3530
  }
3543
- };
3544
- function cancellationRequest(controlRef, operationId, reason) {
3545
- const material = {
3546
- operationId,
3547
- run: AgentExactRunControlRefSchema.parse(controlRef),
3548
- ...reason === void 0 ? {} : { reason }
3549
- };
3550
- return AgentRunCancellationRequestSchema.parse({
3551
- ...material,
3552
- requestDigest: agentRunCancellationRequestDigest(material)
3553
- });
3554
3531
  }
3555
- async function exactSessionCancel(session, request, options) {
3556
- if (!session.cancelRun) throw new Error("provider session does not expose durable cancellation operations");
3557
- let acknowledgement;
3532
+ function exactStatus(ref, value, requestedStart) {
3533
+ let status;
3558
3534
  try {
3559
- acknowledgement = await awaitAbortable(Promise.resolve().then(() => session.cancelRun(request, options)), options.signal);
3535
+ status = AgentInteractiveSessionStatusSchema.parse(value);
3560
3536
  } catch (error) {
3561
- if (error instanceof RetainedRunProviderContractError) throw error;
3562
- throw error;
3537
+ if (requestedStart === void 0) throw error;
3538
+ throw new RetainedInteractiveBindingError(detachedSnapshot(requestedStart, "interactive status binding request"), {}, { cause: error });
3563
3539
  }
3564
- let exactAcknowledgement;
3565
- try {
3566
- exactAcknowledgement = AgentRunCancellationAcknowledgementSchema.parse(acknowledgement);
3567
- } catch {
3568
- throw new RetainedRunProviderContractError("provider returned an invalid retained cancellation acknowledgement");
3540
+ if (!agentInteractiveSessionStatusMatchesRef(ref, status)) {
3541
+ if (requestedStart !== void 0) throw new RetainedInteractiveBindingError(detachedSnapshot(requestedStart, "interactive status binding request"), detachedSnapshot({ status: detachedSnapshot(status, "interactive provider status") }, "interactive provider status result"), { cause: /* @__PURE__ */ new Error("provider returned status for another interactive process") });
3542
+ throw new Error("provider returned status for another interactive process");
3569
3543
  }
3570
- if (!agentRunCancellationAcknowledgementMatchesRequest(request, exactAcknowledgement)) throw new RetainedRunProviderContractError("provider returned a retained cancellation acknowledgement for another request");
3571
- return exactAcknowledgement;
3544
+ return status;
3545
+ }
3546
+ function exactTerminal(ref, request, terminal) {
3547
+ const terminalRef = TerminalSessionRefSchema.parse(terminal.ref);
3548
+ TerminalReplayWindowSchema.parse(terminal.cursors);
3549
+ if (terminalRef.parentExecutionId !== ref.run.executionId) throw new Error("provider attached a terminal from another interactive run");
3550
+ AgentInteractiveSessionControlClaimSchema.parse(terminal.control);
3551
+ if (!agentInteractiveSessionControlClaimMatchesRef(ref, terminal.control)) throw new Error("provider attached a terminal with a claim for another interactive process");
3552
+ if (canonicalCandidateDigest(terminal.control) !== canonicalCandidateDigest(request.control)) throw new Error("provider attached a terminal with a different interactive control claim");
3553
+ return terminal;
3554
+ }
3555
+ function sameInteractiveRef(left, right) {
3556
+ return canonicalCandidateDigest(left) === canonicalCandidateDigest(right);
3572
3557
  }
3573
- function hasDurableCancel(session) {
3574
- return typeof session.cancelRun === "function";
3558
+ //#endregion
3559
+ //#region src/runtime/retained-interactive-lifecycle.ts
3560
+ const INTERACTIVE_CLEANUP_TIMEOUT_MS = 3e4;
3561
+ /** Create one environment while retaining ownership if cancellation wins the race. */
3562
+ async function createInteractiveEnvironment(create, signal) {
3563
+ if (signal?.aborted) throw abortError(signal.reason);
3564
+ const creation = Promise.resolve().then(create);
3565
+ if (signal === void 0) return creation;
3566
+ return new Promise((resolve, reject) => {
3567
+ let owner = "pending";
3568
+ const removeAbortListener = () => signal.removeEventListener("abort", onAbort);
3569
+ const onAbort = () => {
3570
+ if (owner !== "pending") return;
3571
+ owner = "runtime";
3572
+ removeAbortListener();
3573
+ disposeInteractiveEnvironment(creation, signal.reason);
3574
+ reject(abortError(signal.reason));
3575
+ };
3576
+ signal.addEventListener("abort", onAbort, { once: true });
3577
+ creation.then((environment) => {
3578
+ if (owner !== "pending") return;
3579
+ owner = "caller";
3580
+ removeAbortListener();
3581
+ resolve(environment);
3582
+ }, (error) => {
3583
+ if (owner !== "pending") return;
3584
+ owner = "runtime";
3585
+ removeAbortListener();
3586
+ reject(error);
3587
+ });
3588
+ });
3575
3589
  }
3576
- async function awaitAbortable(work, signal) {
3577
- if (signal === void 0) return await work;
3578
- if (signal.aborted) {
3579
- Promise.resolve(work).catch(() => void 0);
3590
+ /** Start one process while destroying its unreturned environment on cancellation. */
3591
+ async function startInteractiveProcess(environment, start, signal) {
3592
+ if (signal?.aborted) {
3593
+ disposeInteractiveEnvironment(Promise.resolve(environment), signal.reason);
3580
3594
  throw abortError(signal.reason);
3581
3595
  }
3582
- return await new Promise((resolve, reject) => {
3583
- let settled = false;
3584
- const cleanup = () => signal.removeEventListener("abort", onAbort);
3596
+ const pending = Promise.resolve().then(start);
3597
+ if (signal === void 0) return pending;
3598
+ return new Promise((resolve, reject) => {
3599
+ let owner = "pending";
3600
+ const removeAbortListener = () => signal.removeEventListener("abort", onAbort);
3585
3601
  const onAbort = () => {
3586
- queueMicrotask(() => {
3587
- if (settled) return;
3588
- settled = true;
3589
- cleanup();
3590
- reject(abortError(signal.reason));
3591
- });
3602
+ if (owner !== "pending") return;
3603
+ owner = "runtime";
3604
+ removeAbortListener();
3605
+ disposeInteractiveEnvironment(Promise.resolve(environment), signal.reason);
3606
+ reject(abortError(signal.reason));
3592
3607
  };
3593
3608
  signal.addEventListener("abort", onAbort, { once: true });
3594
- Promise.resolve(work).then((value) => {
3595
- if (settled) return;
3596
- settled = true;
3597
- cleanup();
3598
- resolve(value);
3609
+ pending.then((result) => {
3610
+ if (owner !== "pending") return;
3611
+ owner = "caller";
3612
+ removeAbortListener();
3613
+ resolve(result);
3599
3614
  }, (error) => {
3600
- if (settled) return;
3601
- settled = true;
3602
- cleanup();
3615
+ if (owner !== "pending") return;
3616
+ owner = "runtime";
3617
+ removeAbortListener();
3603
3618
  reject(error);
3604
3619
  });
3605
3620
  });
3606
3621
  }
3607
- async function exactSessionResult(session) {
3608
- return session.result();
3609
- }
3610
- function assertEventBinding(source, controlRef) {
3611
- const transport = isRecord(source) ? source : void 0;
3612
- const payload = isRecord(source.data) ? source.data : void 0;
3613
- const providerEvent = isRecord(source.providerEvent) ? source.providerEvent : void 0;
3614
- const bindings = [
3615
- {
3616
- value: transport,
3617
- checkSessionId: true
3618
- },
3619
- {
3620
- value: payload,
3621
- checkSessionId: source.type !== "session.updated"
3622
- },
3623
- {
3624
- value: providerEvent,
3625
- checkSessionId: true
3626
- }
3627
- ];
3628
- for (const { value, checkSessionId } of bindings) {
3629
- if (value === void 0) continue;
3630
- if (value.runId !== void 0 && value.runId !== controlRef.runId) throw new Error("provider returned an event for another retained run");
3631
- if (value.executionId !== void 0 && value.executionId !== controlRef.executionId) throw new Error("provider returned an event for another retained execution");
3632
- if (checkSessionId && value.sessionId !== void 0 && value.sessionId !== controlRef.sessionId) throw new Error("provider returned an event for another retained session");
3622
+ /** Destroy an environment with fresh, bounded cleanup authority. */
3623
+ async function destroyInteractiveEnvironment(environment) {
3624
+ if (!environment.destroy) throw new Error(`provider environment "${environment.id}" does not expose destroy()`);
3625
+ const controller = new AbortController();
3626
+ const timeout = /* @__PURE__ */ new Error("interactive environment cleanup timed out");
3627
+ let timer;
3628
+ const destruction = Promise.resolve().then(() => environment.destroy?.({ signal: controller.signal }));
3629
+ destruction.catch(() => void 0);
3630
+ try {
3631
+ await Promise.race([destruction, new Promise((_resolve, reject) => {
3632
+ timer = setTimeout(() => {
3633
+ controller.abort(timeout);
3634
+ reject(timeout);
3635
+ }, INTERACTIVE_CLEANUP_TIMEOUT_MS);
3636
+ })]);
3637
+ } finally {
3638
+ if (timer !== void 0) clearTimeout(timer);
3633
3639
  }
3634
3640
  }
3635
- function isRecord(value) {
3636
- return typeof value === "object" && value !== null && !Array.isArray(value);
3641
+ function disposeInteractiveEnvironment(environment, abortReason) {
3642
+ environment.then(destroyInteractiveEnvironment, () => void 0).catch((cleanupError) => {
3643
+ const reason = abortReason instanceof Error ? abortReason : new Error(String(abortReason));
3644
+ const failure = new AggregateError([reason, cleanupError], "cancelled interactive environment cleanup failed");
3645
+ process.emitWarning(failure, { code: "AGENT_RUNTIME_INTERACTIVE_CLEANUP_FAILED" });
3646
+ });
3637
3647
  }
3638
- function assertStableText(value, label) {
3639
- if (value.length === 0 || value.trim() !== value) throw new Error(`${label} must be non-empty and have no outer whitespace`);
3648
+ //#endregion
3649
+ //#region src/runtime/retained-run-intent.ts
3650
+ /**
3651
+ * Project environment creation input into public digest material.
3652
+ *
3653
+ * Opaque values never enter the material or its digest. Public scalar fields
3654
+ * remain bound directly, while opaque records retain only their key names.
3655
+ * Secret names remain public binding data, so changing requested credentials
3656
+ * still conflicts before provider effects begin.
3657
+ */
3658
+ function retainedCreateMaterial(environment) {
3659
+ return {
3660
+ ...environment.backend === void 0 ? {} : { backend: environment.backend },
3661
+ ...environment.workspace === void 0 ? {} : { workspaceDigest: canonicalCandidateDigest(publicWorkspaceMaterial(environment.workspace)) },
3662
+ ...environment.resources === void 0 ? {} : { resourcesDigest: canonicalCandidateDigest(publicResourceMaterial(environment.resources)) },
3663
+ ...environment.name === void 0 ? {} : { name: environment.name },
3664
+ ...environment.env === void 0 ? {} : { environmentVariableNames: retainedObjectNames(environment.env) },
3665
+ ...environment.secrets === void 0 ? {} : { secretNames: retainedSecretNames(environment.secrets) },
3666
+ ...environment.metadata === void 0 ? {} : { metadataKeys: retainedObjectNames(environment.metadata) },
3667
+ ...environment.providerOptions === void 0 ? {} : { providerOptionNames: retainedObjectNames(environment.providerOptions) }
3668
+ };
3640
3669
  }
3641
- function abortError(reason) {
3642
- const error = new Error(reason === void 0 ? "aborted" : String(reason));
3643
- error.name = "AbortError";
3644
- return error;
3670
+ function publicWorkspaceMaterial(workspace) {
3671
+ return {
3672
+ ...workspace.environment === void 0 ? {} : { environment: workspace.environment },
3673
+ ...workspace.image === void 0 ? {} : { image: workspace.image },
3674
+ ...workspace.repoUrl === void 0 ? {} : { repoUrl: workspace.repoUrl },
3675
+ ...workspace.gitRef === void 0 ? {} : { gitRef: workspace.gitRef },
3676
+ ...workspace.cwd === void 0 ? {} : { cwd: workspace.cwd },
3677
+ ...workspace.providerOptions === void 0 ? {} : { providerOptionNames: retainedObjectNames(workspace.providerOptions) }
3678
+ };
3645
3679
  }
3646
- function assertWaitDuration(value, label) {
3647
- if (!Number.isSafeInteger(value) || value < 0) throw new Error(`${label} must be a non-negative safe integer`);
3680
+ function publicResourceMaterial(resources) {
3681
+ return {
3682
+ ...resources.cpu === void 0 ? {} : { cpu: resources.cpu },
3683
+ ...resources.memoryMb === void 0 ? {} : { memoryMb: resources.memoryMb },
3684
+ ...resources.diskMb === void 0 ? {} : { diskMb: resources.diskMb },
3685
+ ...resources.gpu === void 0 ? {} : { gpu: resources.gpu },
3686
+ ...resources.providerOptions === void 0 ? {} : { providerOptionNames: retainedObjectNames(resources.providerOptions) }
3687
+ };
3648
3688
  }
3649
- function isTerminalSessionStatus(status) {
3650
- return status === "completed" || status === "failed" || status === "cancelled" || status === "expired";
3689
+ function retainedObjectNames(value) {
3690
+ return Object.keys(value).sort();
3651
3691
  }
3652
- function delay(ms, signal) {
3653
- if (signal?.aborted) return Promise.reject(abortError(signal.reason));
3654
- return new Promise((resolveDelay, rejectDelay) => {
3655
- const timer = setTimeout(finish, ms);
3656
- function finish() {
3657
- signal?.removeEventListener("abort", onAbort);
3658
- resolveDelay();
3659
- }
3660
- function onAbort() {
3661
- clearTimeout(timer);
3662
- signal?.removeEventListener("abort", onAbort);
3663
- rejectDelay(abortError(signal?.reason));
3664
- }
3665
- signal?.addEventListener("abort", onAbort, { once: true });
3666
- });
3692
+ function retainedSecretNames(secrets) {
3693
+ return Array.isArray(secrets) ? [...secrets].sort() : Object.keys(secrets).sort();
3694
+ }
3695
+ /** Project one headless turn into the material that `freshTurnInput` forwards. */
3696
+ function retainedTurnMaterial(input) {
3697
+ return {
3698
+ ...input.prompt === void 0 ? {} : { prompt: input.prompt },
3699
+ ...input.parts === void 0 ? {} : { parts: input.parts },
3700
+ ...input.model === void 0 ? {} : { model: input.model },
3701
+ ...input.timeoutMs === void 0 ? {} : { timeoutMs: input.timeoutMs },
3702
+ ...input.context === void 0 ? {} : { context: input.context },
3703
+ ...input.interactions === void 0 ? {} : { interactions: input.interactions },
3704
+ ...input.providerOptions === void 0 ? {} : { providerOptions: input.providerOptions }
3705
+ };
3706
+ }
3707
+ //#endregion
3708
+ //#region src/runtime/interaction-capabilities.ts
3709
+ /**
3710
+ * Check one turn's interaction request before the provider can dispatch it.
3711
+ *
3712
+ * A requested interaction is durable only when the provider can replay its
3713
+ * event and safely replay the response command. An unsupported request fails
3714
+ * before environment creation or dispatch begins.
3715
+ */
3716
+ function assertRequestedInteractionCapabilities(providerName, requested, capabilities) {
3717
+ const requestedKinds = Object.entries(requested ?? {}).filter(([, enabled]) => enabled === true).map(([kind]) => kind);
3718
+ if (requestedKinds.length === 0) return;
3719
+ const interactions = capabilities.interactions;
3720
+ if (!interactions) throw new Error(`provider "${providerName}" does not support requested interactions: ${requestedKinds.join(", ")}`);
3721
+ const unsupportedKinds = requestedKinds.filter((kind) => !interactions.kinds.includes(kind));
3722
+ if (unsupportedKinds.length > 0) throw new Error(`provider "${providerName}" does not support requested interaction kinds: ${unsupportedKinds.join(", ")}`);
3723
+ if (interactions.replay !== true || interactions.responseIdempotency !== true) throw new Error(`provider "${providerName}" cannot safely dispatch requested interactions without replay and response idempotency`);
3667
3724
  }
3668
3725
  //#endregion
3669
3726
  //#region src/runtime/retained-run-events.ts
@@ -3693,6 +3750,7 @@ async function* retainedRunEvents(session, controlRef, options, now) {
3693
3750
  if (sourceCursor === after?.cursor) continue;
3694
3751
  const event = canonicalEvent(source);
3695
3752
  if (!event) continue;
3753
+ assertCanonicalEventBinding(controlRef, event);
3696
3754
  if (firstAfterEvent && after !== void 0) {
3697
3755
  if (identity.sequence !== void 0 && identity.sequence <= after.sequence) throw new Error("provider replay did not prove that the first event follows the requested cursor");
3698
3756
  firstAfterEvent = false;
@@ -3736,6 +3794,7 @@ function canonicalEvent(source) {
3736
3794
  //#region src/runtime/retained-run-handle.ts
3737
3795
  function createRetainedRunHandle(environment, session, initialControlRef, capabilities, now) {
3738
3796
  const clock = now ?? Date.now;
3797
+ const measuredCapabilities = structuredClone(capabilities);
3739
3798
  let activeControlRef = freezeControlRef(initialControlRef);
3740
3799
  const snapshot = async (reason, signal) => {
3741
3800
  if (signal?.aborted) throw abortError(signal.reason);
@@ -3761,6 +3820,9 @@ function createRetainedRunHandle(environment, session, initialControlRef, capabi
3761
3820
  get controlRef() {
3762
3821
  return copyControlRef(activeControlRef);
3763
3822
  },
3823
+ get capabilities() {
3824
+ return structuredClone(measuredCapabilities);
3825
+ },
3764
3826
  status: async (options) => {
3765
3827
  const waitMs = options?.waitMs ?? 0;
3766
3828
  assertWaitDuration(waitMs, "retained status wait");
@@ -3784,7 +3846,7 @@ function createRetainedRunHandle(environment, session, initialControlRef, capabi
3784
3846
  async respondToInteraction(command, options) {
3785
3847
  const exactCommand = InteractionResponseCommandSchema.parse(command);
3786
3848
  assertInteractionBinding(activeControlRef, exactCommand);
3787
- if (capabilities.interactions?.responseIdempotency !== true) throw new Error(`provider "${activeControlRef.provider}" does not promise retry-safe interaction responses`);
3849
+ if (measuredCapabilities.interactions?.replay !== true || measuredCapabilities.interactions.responseIdempotency !== true) throw new Error(`provider "${activeControlRef.provider}" does not promise retry-safe interaction responses`);
3788
3850
  const respond = session.respondToInteraction ?? environment.respondToInteraction;
3789
3851
  if (!respond) throw new Error(`provider "${activeControlRef.provider}" does not support interaction responses`);
3790
3852
  const acknowledgement = InteractionAcknowledgementSchema.parse(await awaitAbortable(Promise.resolve().then(() => respond.call(session.respondToInteraction ? session : environment, exactCommand, options)), options?.signal));
@@ -3804,7 +3866,7 @@ function createRetainedRunHandle(environment, session, initialControlRef, capabi
3804
3866
  if (!sameControlCoordinates(exactRequest.run, activeControlRef)) throw new Error("native continuation request targets another retained run");
3805
3867
  const { timeoutMs, signal, ...semanticTurn } = turn;
3806
3868
  if (nativeContextContinuationTurnDigest(semanticTurn) !== exactRequest.turnDigest) throw new Error("native continuation request targets another user turn");
3807
- if (capabilities.nativeContinuation?.atomicBoundary !== true || capabilities.nativeContinuation.requestIdempotency !== true || !session.continueNative) throw new Error(`provider "${activeControlRef.provider}" does not support retry-safe native continuation`);
3869
+ if (measuredCapabilities.nativeContinuation?.atomicBoundary !== true || measuredCapabilities.nativeContinuation.requestIdempotency !== true || !session.continueNative) throw new Error(`provider "${activeControlRef.provider}" does not support retry-safe native continuation`);
3808
3870
  const outcome = AgentNativeContextContinuationResultSchema.parse(await awaitAbortable(Promise.resolve().then(() => session.continueNative(exactRequest, {
3809
3871
  turn: semanticTurn,
3810
3872
  ...timeoutMs === void 0 ? {} : { timeoutMs },
@@ -3862,31 +3924,6 @@ function createRetainedRunHandle(environment, session, initialControlRef, capabi
3862
3924
  };
3863
3925
  }
3864
3926
  //#endregion
3865
- //#region src/runtime/turn-input.ts
3866
- /**
3867
- * Copy only fields that describe a new provider turn.
3868
- *
3869
- * Session, replay, continuation, and transfer coordinates are runtime-owned
3870
- * and are injected by the caller that owns that lifecycle. Keeping this copy
3871
- * explicit also makes JavaScript callers subject to the same boundary.
3872
- */
3873
- function freshTurnInput(input, runtime) {
3874
- return {
3875
- ...input.prompt === void 0 ? {} : { prompt: input.prompt },
3876
- ...input.parts === void 0 ? {} : { parts: input.parts },
3877
- ...input.model === void 0 ? {} : { model: input.model },
3878
- ...input.timeoutMs === void 0 ? {} : { timeoutMs: input.timeoutMs },
3879
- ...input.context === void 0 ? {} : { context: input.context },
3880
- ...input.providerOptions === void 0 ? {} : { providerOptions: input.providerOptions },
3881
- ...input.signal === void 0 ? {} : { signal: input.signal },
3882
- turnId: runtime.turnId,
3883
- detach: runtime.detach,
3884
- ...runtime.sessionId === void 0 ? {} : { sessionId: runtime.sessionId },
3885
- ...runtime.executionId === void 0 ? {} : { executionId: runtime.executionId },
3886
- ...runtime.contextTransfer === void 0 ? {} : { contextTransfer: runtime.contextTransfer }
3887
- };
3888
- }
3889
- //#endregion
3890
3927
  //#region src/runtime/retained-run-start.ts
3891
3928
  /**
3892
3929
  * Mint deterministic dispatch coordinates from the two caller-supplied keys.
@@ -3911,11 +3948,10 @@ function mintRetainedIdentity(idempotencyKey, turnId) {
3911
3948
  * Dispatch one detached, replayable run and return only after exact durable
3912
3949
  * coordinates are confirmed by the provider and persisted by the caller.
3913
3950
  *
3914
- * The required `onAdmission` hook is awaited twice: with the recovery
3915
- * coordinates after environment creation, and with the verified exact control
3916
- * reference after dispatch. The returned promise resolves only after the
3917
- * dispatched admission is durable, so no caller can observe a successful start
3918
- * whose exact reference a crash would lose.
3951
+ * The required `onAdmission` hook first records a digest-only intent before
3952
+ * creation, then records recovery coordinates and the verified exact control
3953
+ * reference. The returned promise resolves only after the dispatched admission
3954
+ * is durable, so a crash cannot lose a successful start's exact reference.
3919
3955
  *
3920
3956
  * @stable
3921
3957
  */
@@ -3928,17 +3964,35 @@ async function startRetainedRun(options) {
3928
3964
  }
3929
3965
  if (typeof options.onAdmission !== "function") throw new Error("startRetainedRun requires an awaited onAdmission durability hook");
3930
3966
  const identity = options.identity ?? mintRetainedIdentity(options.environment.idempotencyKey, options.turn.turnId);
3931
- const capabilities = await assertRetainedCapabilities(options.provider);
3932
3967
  if (!options.provider.get) throw new Error(`provider "${options.provider.name}" cannot reconstruct an environment by id`);
3968
+ const intent = retainedRunIntent(options, identity);
3969
+ if (options.intent === void 0) await admitDurably(options.onAdmission, intent);
3970
+ else assertExactRetainedRunIntent(options.intent, intent);
3971
+ const providerCapabilities = await assertRetainedCapabilities(options.provider);
3972
+ assertRequestedInteractionCapabilities(options.provider.name, options.turn.interactions, providerCapabilities);
3933
3973
  const environment = await options.provider.create({
3934
3974
  ...options.environment,
3935
3975
  metadata: {
3936
3976
  ...options.environment.metadata,
3937
3977
  retainedIdempotencyKey: options.environment.idempotencyKey,
3978
+ retainedIntentDigest: intent.requestDigest,
3979
+ retainedRunId: intent.runId,
3938
3980
  sessionId: identity.sessionId,
3939
3981
  executionId: identity.executionId
3940
3982
  }
3941
3983
  });
3984
+ let capabilities;
3985
+ try {
3986
+ capabilities = retainedCapabilitiesForEnvironment(options.provider.name, providerCapabilities, environment);
3987
+ assertRequestedInteractionCapabilities(options.provider.name, options.turn.interactions, capabilities);
3988
+ } catch (error) {
3989
+ try {
3990
+ await environment.destroy?.();
3991
+ } catch (cleanupError) {
3992
+ throw new AggregateError([error, cleanupError], "retained run environment published invalid capabilities and could not be destroyed");
3993
+ }
3994
+ throw error;
3995
+ }
3942
3996
  if (!environment.dispatch || !environment.session) {
3943
3997
  try {
3944
3998
  await environment.destroy?.();
@@ -3977,11 +4031,13 @@ async function startRetainedRunInEnvironment(options) {
3977
4031
  }
3978
4032
  if (typeof options.onAdmission !== "function") throw new Error("startRetainedRunInEnvironment requires an awaited onAdmission durability hook");
3979
4033
  const identity = options.identity ?? mintRetainedIdentity(options.environment.idempotencyKey, options.turn.turnId);
3980
- const capabilities = await assertRetainedCapabilities(options.provider);
4034
+ const providerCapabilities = await assertRetainedCapabilities(options.provider);
3981
4035
  if (!options.provider.get) throw new Error(`provider "${options.provider.name}" cannot reconstruct an environment by id`);
3982
4036
  const environment = await options.provider.get(options.environment.id);
3983
4037
  if (!environment) throw new Error(`provider "${options.provider.name}" no longer holds environment "${options.environment.id}"`);
3984
4038
  if (environment.id !== options.environment.id || environment.provider !== options.provider.name) throw new Error("provider reconstructed a different retained environment");
4039
+ const capabilities = retainedCapabilitiesForEnvironment(options.provider.name, providerCapabilities, environment);
4040
+ assertRequestedInteractionCapabilities(options.provider.name, options.turn.interactions, capabilities);
3985
4041
  if (!environment.dispatch || !environment.session) throw new Error(`provider "${options.provider.name}" does not expose detached session control`);
3986
4042
  await assertRetainedEnvironmentOwnership(options.provider, environment.id, options.environment.idempotencyKey);
3987
4043
  return dispatchRetainedRun({
@@ -4002,6 +4058,7 @@ async function assertRetainedEnvironmentOwnership(provider, environmentId, idemp
4002
4058
  }
4003
4059
  async function dispatchRetainedRun(options) {
4004
4060
  const { environment, identity } = options;
4061
+ assertRequestedInteractionCapabilities(options.provider.name, options.turn.interactions, options.capabilities);
4005
4062
  await admitDurably(options.onAdmission, {
4006
4063
  phase: "environment",
4007
4064
  provider: options.provider.name,
@@ -4054,37 +4111,39 @@ async function dispatchRetainedRun(options) {
4054
4111
  * callers can distinguish a persistence failure from a provider failure.
4055
4112
  */
4056
4113
  async function admitDurably(onAdmission, admission) {
4114
+ const stableAdmission = detachedSnapshot(admission, "retained run admission");
4057
4115
  try {
4058
- await onAdmission(Object.freeze(admission));
4116
+ await onAdmission(stableAdmission);
4059
4117
  } catch (error) {
4060
- throw new RetainedRunAdmissionError(admission, { cause: error });
4118
+ if (isInteractiveAdmission(stableAdmission)) throw new RetainedInteractiveAdmissionError(stableAdmission, { cause: error });
4119
+ throw new RetainedRunAdmissionError(stableAdmission, { cause: error });
4061
4120
  }
4062
4121
  }
4063
- /**
4064
- * Rebuild the exact run named by pre-dispatch admission coordinates, or
4065
- * report why the provider cannot prove it.
4066
- *
4067
- * `not_found`: the provider no longer holds the environment, so nothing
4068
- * remains to destroy. `recovered`: the provider self-identified the session
4069
- * with a strict exact reference matching the recorded coordinates.
4070
- * `unverifiable`: the environment exists but the provider cannot
4071
- * self-identify the session — no session accessor, an accessor that throws,
4072
- * a lazy accessor with no stored reference, or a loose reference. That
4073
- * outcome is never destroy-safe: keep the environment, retry
4074
- * `reconnectRetainedRun` with a dispatched admission record, or inspect the
4075
- * environment with provider-native tools. A session that self-identifies
4076
- * with different coordinates throws: something live is not the recorded run.
4077
- *
4078
- * @stable
4079
- */
4122
+ function isInteractiveAdmission(admission) {
4123
+ return admission.phase === "interactive_intent" || admission.phase === "interactive_environment" || admission.phase === "interactive_started";
4124
+ }
4080
4125
  async function recoverRetainedRun(options) {
4126
+ if ("admission" in options) {
4127
+ if (options.admission.provider !== options.provider.name) throw new Error("retained run intent belongs to another provider");
4128
+ return {
4129
+ outcome: "recovered",
4130
+ handle: await startRetainedRun({
4131
+ provider: options.provider,
4132
+ ...options.replay,
4133
+ intent: options.admission,
4134
+ onAdmission: options.onAdmission,
4135
+ now: options.now
4136
+ })
4137
+ };
4138
+ }
4081
4139
  assertStableText(options.environmentId, "retained environment id");
4082
4140
  assertStableText(options.sessionId, "retained session id");
4083
4141
  assertStableText(options.executionId, "retained execution id");
4084
- const capabilities = await assertRetainedCapabilities(options.provider);
4142
+ const providerCapabilities = await assertRetainedCapabilities(options.provider);
4085
4143
  if (!options.provider.get) throw new Error(`provider "${options.provider.name}" cannot reconstruct an environment by id`);
4086
4144
  const environment = await options.provider.get(options.environmentId);
4087
4145
  if (!environment) return { outcome: "not_found" };
4146
+ const capabilities = retainedCapabilitiesForEnvironment(options.provider.name, providerCapabilities, environment);
4088
4147
  if (!environment.session) return {
4089
4148
  outcome: "unverifiable",
4090
4149
  environment
@@ -4111,23 +4170,392 @@ async function recoverRetainedRun(options) {
4111
4170
  handle: createRetainedRunHandle(environment, exact.session, exact.controlRef, capabilities, options.now)
4112
4171
  };
4113
4172
  }
4173
+ function retainedRunIntent(options, identity) {
4174
+ const requestedProfileDigest = canonicalCandidateDigest(options.environment.profile);
4175
+ const requestDigest = canonicalCandidateDigest({
4176
+ kind: "retained-run-intent.v1",
4177
+ provider: options.provider.name,
4178
+ idempotencyKey: options.environment.idempotencyKey,
4179
+ turnId: options.turn.turnId,
4180
+ sessionId: identity.sessionId,
4181
+ executionId: identity.executionId,
4182
+ requestedProfileDigest,
4183
+ create: retainedCreateMaterial(options.environment),
4184
+ turn: retainedTurnMaterial(options.turn)
4185
+ });
4186
+ return {
4187
+ phase: "intent",
4188
+ provider: options.provider.name,
4189
+ idempotencyKey: options.environment.idempotencyKey,
4190
+ turnId: options.turn.turnId,
4191
+ sessionId: identity.sessionId,
4192
+ executionId: identity.executionId,
4193
+ runId: `retained-intent-run:${requestDigest.slice(7)}`,
4194
+ requestedProfileDigest,
4195
+ requestDigest
4196
+ };
4197
+ }
4198
+ function assertExactRetainedRunIntent(received, expected) {
4199
+ if (canonicalCandidateDigest(parseRetainedRunIntent(received)) !== canonicalCandidateDigest(expected)) throw new Error("retained run intent conflicts with replay material");
4200
+ }
4201
+ function parseRetainedRunIntent(value) {
4202
+ const stable = detachedSnapshot(value, "retained run intent");
4203
+ if (stable === null || typeof stable !== "object" || Array.isArray(stable)) throw new Error("retained run intent is malformed");
4204
+ const record = stable;
4205
+ const allowed = /* @__PURE__ */ new Set([
4206
+ "phase",
4207
+ "provider",
4208
+ "idempotencyKey",
4209
+ "turnId",
4210
+ "sessionId",
4211
+ "executionId",
4212
+ "runId",
4213
+ "requestedProfileDigest",
4214
+ "requestDigest"
4215
+ ]);
4216
+ if (Object.keys(record).some((key) => !allowed.has(key))) throw new Error("retained run intent contains unsupported material");
4217
+ if (record.phase !== "intent") throw new Error("retained run intent has an invalid phase");
4218
+ for (const [key, value] of Object.entries(record)) {
4219
+ if (key === "phase") continue;
4220
+ if (typeof value !== "string" || value.length === 0) throw new Error(`retained run intent field "${key}" is invalid`);
4221
+ }
4222
+ assertDigest$1(record.requestedProfileDigest, "retained run intent profile digest");
4223
+ assertDigest$1(record.requestDigest, "retained run intent request digest");
4224
+ return stable;
4225
+ }
4226
+ function assertDigest$1(value, label) {
4227
+ if (typeof value !== "string" || !/^sha256:[a-f0-9]{64}$/u.test(value)) throw new Error(`${label} is invalid`);
4228
+ }
4114
4229
  /** Rebuild a retained-run client without retaining any object from the starter. @stable */
4115
4230
  async function reconnectRetainedRun(options) {
4116
4231
  const controlRef = AgentExactRunControlRefSchema.parse(options.controlRef);
4117
4232
  if (controlRef.provider !== options.provider.name) throw new Error(`run provider "${controlRef.provider}" does not match "${options.provider.name}"`);
4118
- const capabilities = await assertRetainedCapabilities(options.provider);
4233
+ const providerCapabilities = await assertRetainedCapabilities(options.provider);
4119
4234
  if (!options.provider.get) throw new Error(`provider "${options.provider.name}" cannot reconstruct an environment by id`);
4120
4235
  const environment = await options.provider.get(controlRef.environmentId);
4121
4236
  if (!environment) return null;
4237
+ const capabilities = retainedCapabilitiesForEnvironment(options.provider.name, providerCapabilities, environment);
4122
4238
  const exact = exactSession(environment, controlRef);
4123
4239
  return createRetainedRunHandle(environment, exact.session, exact.controlRef, capabilities, options.now);
4124
4240
  }
4125
4241
  async function assertRetainedCapabilities(provider) {
4126
4242
  const capabilities = AgentEnvironmentCapabilitiesSchema.parse(await provider.capabilities());
4243
+ assertRetainedCapabilityRequirements(provider.name, capabilities);
4244
+ return capabilities;
4245
+ }
4246
+ /**
4247
+ * Select the capability document for one concrete environment.
4248
+ *
4249
+ * A measured environment document is authoritative. An absent document uses
4250
+ * the provider document because that provider claims the same guarantee for
4251
+ * every environment it creates.
4252
+ */
4253
+ function retainedCapabilitiesForEnvironment(providerName, providerCapabilities, environment) {
4254
+ if (environment.capabilities === void 0) return providerCapabilities;
4255
+ const measured = AgentEnvironmentCapabilitiesSchema.parse(environment.capabilities);
4256
+ assertRetainedCapabilityRequirements(providerName, measured);
4257
+ return measured;
4258
+ }
4259
+ function assertRetainedCapabilityRequirements(providerName, capabilities) {
4127
4260
  const retained = capabilities.retainedControl;
4128
- if (retained?.exactRunIdentity !== true || retained.resultIdentity !== true || retained.eventIdentity !== true || retained.cancellationIdempotency !== true || !capabilities.streaming.detach || !capabilities.streaming.replay || !capabilities.streaming.turnIdempotency) throw new Error(`provider "${provider.name}" cannot control a retry-safe retained run`);
4261
+ if (retained?.exactRunIdentity !== true || retained.resultIdentity !== true || retained.eventIdentity !== true || retained.cancellationIdempotency !== true || !capabilities.streaming.detach || !capabilities.streaming.replay || !capabilities.streaming.turnIdempotency) throw new Error(`provider "${providerName}" cannot control a retry-safe retained run`);
4262
+ }
4263
+ //#endregion
4264
+ //#region src/runtime/retained-interactive.ts
4265
+ /**
4266
+ * Start one retry-safe native coding-agent TUI without dispatching a headless turn.
4267
+ * The intent admission is durable before provider.create; the environment and
4268
+ * process admissions follow only after their exact provider coordinates exist.
4269
+ * @stable
4270
+ */
4271
+ async function startRetainedInteractiveRun(options) {
4272
+ options.signal?.throwIfAborted();
4273
+ assertStableText(options.environment.idempotencyKey, "environment idempotency key");
4274
+ assertStableText(options.interactiveIdempotencyKey, "interactive idempotency key");
4275
+ if (typeof options.onAdmission !== "function") throw new Error("startRetainedInteractiveRun requires an awaited onAdmission durability hook");
4276
+ if (!options.provider.get) throw new Error(`provider "${options.provider.name}" cannot reconstruct an environment by id`);
4277
+ const profile = agentProfileSchema.parse(options.environment.profile);
4278
+ if (profile.harness === void 0) throw new Error("retained interactive runs require AgentProfile.harness");
4279
+ const requestedProfileDigest = canonicalAgentProfileDigest(profile);
4280
+ const identity = mintRetainedIdentity(options.environment.idempotencyKey, options.interactiveIdempotencyKey);
4281
+ const intent = interactiveIntent(options, profile, identity);
4282
+ if (options.intent === void 0) await admitDurably(options.onAdmission, intent);
4283
+ else assertExactInteractiveIntent(options.intent, intent);
4284
+ const providerCapabilities = AgentEnvironmentCapabilitiesSchema.parse(await awaitAbortable(Promise.resolve().then(() => options.provider.capabilities()), options.signal));
4285
+ assertInteractiveCapabilities(options.provider.name, providerCapabilities);
4286
+ const environment = await createInteractiveEnvironment(() => options.provider.create({
4287
+ ...options.environment,
4288
+ profile,
4289
+ signal: options.signal,
4290
+ metadata: {
4291
+ ...options.environment.metadata,
4292
+ retainedIdempotencyKey: options.environment.idempotencyKey,
4293
+ interactiveIdempotencyKey: options.interactiveIdempotencyKey,
4294
+ requestedProfileDigest,
4295
+ interactiveIntentDigest: intent.requestDigest,
4296
+ interactiveRunId: intent.runId,
4297
+ sessionId: identity.sessionId,
4298
+ executionId: identity.executionId
4299
+ }
4300
+ }), options.signal);
4301
+ let capabilities;
4302
+ try {
4303
+ assertExactEnvironment(options.provider.name, environment);
4304
+ options.signal?.throwIfAborted();
4305
+ capabilities = interactiveCapabilitiesForEnvironment(options.provider.name, providerCapabilities, environment);
4306
+ assertInteractiveMethods(options.provider.name, environment);
4307
+ } catch (error) {
4308
+ await destroyUnusedEnvironment(environment, error);
4309
+ throw error;
4310
+ }
4311
+ const request = interactiveRequest(options, environment, profile, requestedProfileDigest, identity);
4312
+ await admitDurably(options.onAdmission, {
4313
+ phase: "interactive_environment",
4314
+ provider: options.provider.name,
4315
+ environmentId: environment.id,
4316
+ idempotencyKey: options.environment.idempotencyKey,
4317
+ interactiveIdempotencyKey: options.interactiveIdempotencyKey,
4318
+ request
4319
+ });
4320
+ const ref = exactStartedRef(request, await startInteractiveProcess(environment, () => environment.startInteractive(request, { signal: options.signal }), options.signal));
4321
+ await admitDurably(options.onAdmission, {
4322
+ phase: "interactive_started",
4323
+ idempotencyKey: options.environment.idempotencyKey,
4324
+ interactiveIdempotencyKey: options.interactiveIdempotencyKey,
4325
+ ref
4326
+ });
4327
+ return createRetainedInteractiveRunHandle(environment, ref, capabilities, request);
4328
+ }
4329
+ /** Retry one exact start after its provider response may have been lost. @stable */
4330
+ async function recoverRetainedInteractiveRun(options) {
4331
+ options.signal?.throwIfAborted();
4332
+ if (typeof options.onAdmission !== "function") throw new Error("recoverRetainedInteractiveRun requires an awaited onAdmission durability hook");
4333
+ const admission = options.admission;
4334
+ if (admission.provider !== options.provider.name) throw new Error("interactive admission belongs to another provider");
4335
+ if (admission.phase === "interactive_intent") {
4336
+ if (options.replay === void 0) throw new Error("recoverRetainedInteractiveRun requires the original start material for an interactive intent");
4337
+ return startRetainedInteractiveRun({
4338
+ provider: options.provider,
4339
+ ...options.replay,
4340
+ intent: admission,
4341
+ onAdmission: options.onAdmission,
4342
+ signal: options.signal
4343
+ });
4344
+ }
4345
+ const request = exactRecoveryRequest(admission);
4346
+ const { environment, capabilities } = await reconstructEnvironment(options.provider, admission.environmentId, options.signal);
4347
+ if (!environment || !capabilities) return null;
4348
+ const ref = exactStartedRef(request, await awaitAbortable(Promise.resolve().then(() => environment.startInteractive(request, { signal: options.signal })), options.signal));
4349
+ await admitDurably(options.onAdmission, {
4350
+ phase: "interactive_started",
4351
+ idempotencyKey: admission.idempotencyKey,
4352
+ interactiveIdempotencyKey: admission.interactiveIdempotencyKey,
4353
+ ref
4354
+ });
4355
+ return createRetainedInteractiveRunHandle(environment, ref, capabilities, request);
4356
+ }
4357
+ function exactRecoveryRequest(admission) {
4358
+ assertStableText(admission.environmentId, "interactive environment id");
4359
+ assertStableText(admission.idempotencyKey, "environment idempotency key");
4360
+ assertStableText(admission.interactiveIdempotencyKey, "interactive idempotency key");
4361
+ const request = exactAgentInteractiveSessionStart(admission.request);
4362
+ const identity = mintRetainedIdentity(admission.idempotencyKey, admission.interactiveIdempotencyKey);
4363
+ if (request.run.provider !== admission.provider || request.run.environmentId !== admission.environmentId || request.run.sessionId !== identity.sessionId || request.run.executionId !== identity.executionId) throw new Error("interactive admission does not match its recovery coordinates");
4364
+ return request;
4365
+ }
4366
+ /** Rebuild controls for one exact provider-owned coding-agent process. @stable */
4367
+ async function reconnectRetainedInteractiveRun(options) {
4368
+ options.signal?.throwIfAborted();
4369
+ const ref = AgentInteractiveSessionRefSchema.parse(options.ref);
4370
+ if (ref.run.provider !== options.provider.name) throw new Error("interactive session reference belongs to another provider");
4371
+ const { environment, capabilities } = await reconstructEnvironment(options.provider, ref.run.environmentId, options.signal);
4372
+ if (!environment || !capabilities) return null;
4373
+ const handle = createRetainedInteractiveRunHandle(environment, ref, capabilities);
4374
+ await handle.status({ signal: options.signal });
4375
+ return handle;
4376
+ }
4377
+ function interactiveRequest(options, environment, profile, requestedProfileDigest, identity) {
4378
+ const start = {
4379
+ profile,
4380
+ requestedProfileDigest,
4381
+ ...options.initialPrompt === void 0 ? {} : { initialPrompt: options.initialPrompt },
4382
+ ...options.cwd === void 0 ? {} : { cwd: options.cwd },
4383
+ ...options.cols === void 0 ? {} : { cols: options.cols },
4384
+ ...options.rows === void 0 ? {} : { rows: options.rows }
4385
+ };
4386
+ return exactAgentInteractiveSessionStart({
4387
+ run: agentInteractiveSessionRunRef({
4388
+ provider: options.provider.name,
4389
+ environmentId: environment.id,
4390
+ ...identity
4391
+ }, start),
4392
+ ...start
4393
+ });
4394
+ }
4395
+ function interactiveIntent(options, profile, identity) {
4396
+ const requestedProfileDigest = canonicalAgentProfileDigest(profile);
4397
+ const requestDigest = canonicalCandidateDigest({
4398
+ kind: "retained-interactive-intent.v1",
4399
+ provider: options.provider.name,
4400
+ idempotencyKey: options.environment.idempotencyKey,
4401
+ interactiveIdempotencyKey: options.interactiveIdempotencyKey,
4402
+ sessionId: identity.sessionId,
4403
+ executionId: identity.executionId,
4404
+ requestedProfileDigest,
4405
+ create: retainedCreateMaterial(options.environment),
4406
+ start: sanitizedStartMaterial(options)
4407
+ });
4408
+ return {
4409
+ phase: "interactive_intent",
4410
+ provider: options.provider.name,
4411
+ idempotencyKey: options.environment.idempotencyKey,
4412
+ interactiveIdempotencyKey: options.interactiveIdempotencyKey,
4413
+ sessionId: identity.sessionId,
4414
+ executionId: identity.executionId,
4415
+ runId: `interactive-intent-run:${requestDigest.slice(7)}`,
4416
+ requestedProfileDigest,
4417
+ requestDigest
4418
+ };
4419
+ }
4420
+ function sanitizedStartMaterial(options) {
4421
+ return {
4422
+ ...options.initialPrompt === void 0 ? {} : { initialPrompt: options.initialPrompt },
4423
+ ...options.cwd === void 0 ? {} : { cwd: options.cwd },
4424
+ ...options.cols === void 0 ? {} : { cols: options.cols },
4425
+ ...options.rows === void 0 ? {} : { rows: options.rows }
4426
+ };
4427
+ }
4428
+ function assertExactInteractiveIntent(received, expected) {
4429
+ if (canonicalCandidateDigest(parseInteractiveIntent(received)) !== canonicalCandidateDigest(expected)) throw new Error("interactive intent conflicts with replay material");
4430
+ }
4431
+ function parseInteractiveIntent(value) {
4432
+ const stable = detachedSnapshot(value, "interactive intent");
4433
+ if (stable === null || typeof stable !== "object" || Array.isArray(stable)) throw new Error("interactive intent is malformed");
4434
+ const record = stable;
4435
+ const allowed = /* @__PURE__ */ new Set([
4436
+ "phase",
4437
+ "provider",
4438
+ "idempotencyKey",
4439
+ "interactiveIdempotencyKey",
4440
+ "sessionId",
4441
+ "executionId",
4442
+ "runId",
4443
+ "requestedProfileDigest",
4444
+ "requestDigest"
4445
+ ]);
4446
+ if (Object.keys(record).some((key) => !allowed.has(key))) throw new Error("interactive intent contains unsupported material");
4447
+ if (record.phase !== "interactive_intent") throw new Error("interactive intent has an invalid phase");
4448
+ for (const [key, value] of Object.entries(record)) {
4449
+ if (key === "phase") continue;
4450
+ if (typeof value !== "string" || value.length === 0) throw new Error(`interactive intent field "${key}" is invalid`);
4451
+ }
4452
+ assertDigest(record.requestedProfileDigest, "interactive intent profile digest");
4453
+ assertDigest(record.requestDigest, "interactive intent request digest");
4454
+ return stable;
4455
+ }
4456
+ function assertDigest(value, label) {
4457
+ if (typeof value !== "string" || !/^sha256:[a-f0-9]{64}$/u.test(value)) throw new Error(`${label} is invalid`);
4458
+ }
4459
+ async function reconstructEnvironment(provider, environmentId, signal) {
4460
+ if (!provider.get) throw new Error(`provider "${provider.name}" cannot reconstruct an environment by id`);
4461
+ const providerCapabilities = AgentEnvironmentCapabilitiesSchema.parse(await awaitAbortable(Promise.resolve().then(() => provider.capabilities()), signal));
4462
+ assertInteractiveCapabilities(provider.name, providerCapabilities);
4463
+ const environment = await awaitAbortable(Promise.resolve().then(() => provider.get(environmentId, { signal })), signal);
4464
+ if (!environment) return {
4465
+ environment: null,
4466
+ capabilities: null
4467
+ };
4468
+ assertExactEnvironment(provider.name, environment, environmentId);
4469
+ const capabilities = interactiveCapabilitiesForEnvironment(provider.name, providerCapabilities, environment);
4470
+ assertInteractiveMethods(provider.name, environment);
4471
+ return {
4472
+ environment,
4473
+ capabilities
4474
+ };
4475
+ }
4476
+ function exactStartedRef(request, value) {
4477
+ const stableRequest = detachedSnapshot(request, "interactive start binding request");
4478
+ let ref;
4479
+ try {
4480
+ ref = AgentInteractiveSessionRefSchema.parse(value);
4481
+ } catch (error) {
4482
+ throw new RetainedInteractiveBindingError(stableRequest, {}, { cause: error });
4483
+ }
4484
+ if (!agentInteractiveSessionRefMatchesStart(request, ref)) throw new RetainedInteractiveBindingError(stableRequest, detachedSnapshot({ ref: detachedSnapshot(ref, "interactive provider start reference") }, "interactive provider start result"), { cause: /* @__PURE__ */ new Error("provider started another interactive run than requested") });
4485
+ return freezeInteractiveRef(ref);
4486
+ }
4487
+ function assertExactEnvironment(providerName, environment, environmentId) {
4488
+ if (environment.provider !== providerName || environmentId && environment.id !== environmentId) throw new Error("provider returned another interactive environment");
4489
+ assertStableText(environment.id, "interactive environment id");
4490
+ }
4491
+ function interactiveCapabilitiesForEnvironment(providerName, providerCapabilities, environment) {
4492
+ const capabilities = environment.capabilities === void 0 ? providerCapabilities : AgentEnvironmentCapabilitiesSchema.parse(environment.capabilities);
4493
+ assertInteractiveCapabilities(providerName, capabilities);
4129
4494
  return capabilities;
4130
4495
  }
4496
+ function assertInteractiveCapabilities(providerName, capabilities) {
4497
+ const interactive = capabilities.interactiveAgent;
4498
+ if (!interactive?.start || !interactive.control || !interactive.status || !interactive.attach || !interactive.reattach || !interactive.sendPrompt || !interactive.input || !interactive.resize || !interactive.stop) throw new Error(`provider "${providerName}" cannot control an exact interactive agent`);
4499
+ }
4500
+ function assertInteractiveMethods(providerName, environment) {
4501
+ if (!environment.startInteractive || !environment.interactive) throw new Error(`provider "${providerName}" exposes incomplete interactive agent controls`);
4502
+ }
4503
+ async function destroyUnusedEnvironment(environment, cause) {
4504
+ try {
4505
+ await destroyInteractiveEnvironment(environment);
4506
+ } catch (cleanupError) {
4507
+ throw new AggregateError([cause, cleanupError], "interactive environment was invalid and could not be destroyed");
4508
+ }
4509
+ }
4510
+ //#endregion
4511
+ //#region src/runtime/retained-interactive-control.ts
4512
+ const MAX_GENERATION_CONFLICTS = 8;
4513
+ /**
4514
+ * Acquire provider-issued write authority without reading authority from status.
4515
+ *
4516
+ * A new coordinator starts at generation zero. If another claim already exists,
4517
+ * the provider returns its public generation and this helper retries one new
4518
+ * compare-and-swap operation. Every generation has a deterministic operation
4519
+ * identifier, so retrying after an ambiguous response cannot create two claims.
4520
+ * @stable
4521
+ */
4522
+ async function claimRetainedInteractiveControl(options) {
4523
+ const expected = options.expectedGeneration ?? 0;
4524
+ if (!Number.isSafeInteger(expected) || expected < 0) throw new Error("interactive control expectedGeneration must be a non-negative integer");
4525
+ let generation = expected;
4526
+ for (let conflict = 0; conflict <= MAX_GENERATION_CONFLICTS; conflict += 1) {
4527
+ if (options.signal?.aborted) throw abortError(options.signal.reason);
4528
+ const material = {
4529
+ operationId: controlClaimOperationId(options.handle, options.holderId, generation),
4530
+ ref: options.handle.ref,
4531
+ holderId: options.holderId,
4532
+ expectedGeneration: generation
4533
+ };
4534
+ const acknowledgement = await options.handle.claimControl({
4535
+ ...material,
4536
+ requestDigest: agentInteractiveSessionControlClaimRequestDigest(material)
4537
+ }, options.signal === void 0 ? void 0 : { signal: options.signal });
4538
+ if (acknowledgement.status === "accepted" || acknowledgement.status === "replayed") {
4539
+ const control = acknowledgement.control;
4540
+ if (control === void 0) throw new Error("provider accepted interactive control without returning its claim");
4541
+ if (Date.parse(control.expiresAt) <= Date.now()) throw new Error("provider returned an expired interactive control claim");
4542
+ return control;
4543
+ }
4544
+ if (acknowledgement.status !== "conflict" || acknowledgement.conflictReason !== "generation_mismatch") throw new Error(acknowledgement.status === "unknown" ? "interactive control claim outcome is unknown; retry the same acquisition" : "interactive control claim operation conflicts with different request material");
4545
+ const current = acknowledgement.currentGeneration;
4546
+ if (current === void 0 || current <= generation) throw new Error("provider returned a non-advancing interactive control generation");
4547
+ generation = current;
4548
+ }
4549
+ throw new Error("interactive control changed too often to acquire safely");
4550
+ }
4551
+ function controlClaimOperationId(handle, holderId, expectedGeneration) {
4552
+ return `interactive-claim-${canonicalCandidateDigest({
4553
+ kind: "retained-interactive-control-claim.v1",
4554
+ ref: handle.ref,
4555
+ holderId,
4556
+ expectedGeneration
4557
+ }).slice(7, 47)}`;
4558
+ }
4131
4559
  //#endregion
4132
4560
  //#region src/runtime/run-benchmark.ts
4133
4561
  /**
@@ -6670,6 +7098,6 @@ function tail(s) {
6670
7098
  return s.slice(-400);
6671
7099
  }
6672
7100
  //#endregion
6673
- export { FileCorpus as $, pickChampion as A, renderLeaderboardMarkdown as At, runBenchmark as B, envKeyProvider as Bt, analyzeTrace as C, completionAuthorizes as Ct, chatWorkerSeam as D, leaderboard as Dt, chatTransportExecutor as E, stopSentinel as Et, strategyAuthorContract as F, McpSpawnFault as Ft, promotionGate as G, recoverRetainedRun as H, resolveMcpServerLaunch as Ht, strategyAuthorSystemPrompt as I, connectStdioMcp as It, definePersona as J, equalKOnCost as K, SandboxRunAbortError as L, materializeLocalMcp as Lt, selectChampion as M, renderPairwiseMarkdown as Mt, assertStrategyContract as N, auditIntent as Nt, createChatSessionStore as O, pairwiseSignificance as Ot, authorStrategy as P, defaultAuditorInstruction as Pt, registerShape as Q, openSandboxRun as R, createMcpEnvironment as Rt, withUntrackedArtifacts as S, superviseDispatch as St, runCoderChecks as T, sentinelCompletion as Tt, startRetainedRun as U, resolveSecretEnv as Ut, reconnectRetainedRun as V, mcpSecretEnvMetadataKey as Vt, startRetainedRunInEnvironment as W, secretEnvOfMcpServer as Wt, builtinShapes as X, runPersonified as Y, createShapeRegistry as Z, VERIFY_TAIL_CHARS as _, resolveSandboxClient as _t, localShell as a, panel as at, settledWorkerOut as b, loopCampaignDispatch as bt, createVerifierEnvironment as c, verify as ct, harvestSurfaceDiffs as d, buildSteerContext as dt, InMemoryCorpus as et, failuresAnalyst as f, createScopeAnalyst as ft, NOTE_MAX_CHARS as g, defineLeaderboard as gt, EVIDENCE_MAX_CHARS as h, harvestCorpus as ht, jjWorkspace as i, loopUntil as it, runStrategyEvolution as j, renderLeaderboardSvg as jt, discriminatingMeans as k, renderLeaderboardHtml as kt, boxSurfaceReader as l, widen as lt, worktreeFanout as m, inProcessSandboxClient as mt, makeFinding$1 as n, fanout as nt, runInWorkspace as o, pipeline as ot, superviseSurface as p, registryScopeAnalyst as pt, trajectoryReport as q, gitWorkspace as r, flatWidenGate as rt, createWaterfallCollector as s, selectValidWinner as st, computeFindingId$1 as t, renderCorpusToInstructions as tt, fsSurfaceReader as u, assertTraceDerivedFindings as ut, closingWorkerNote as v, localSandboxClient as vt, patchDelivered as w, deterministicCompletion as wt, copyUntrackedIntoClone as x, loopDispatch as xt, composeWorkerEvidence as y, inlineSandboxClient as yt, printBenchmarkReport as z, sanitizeMcpToolSchema as zt };
7101
+ export { runPersonified as $, pickChampion as A, stopSentinel as At, runBenchmark as B, connectStdioMcp as Bt, analyzeTrace as C, inlineSandboxClient as Ct, chatWorkerSeam as D, completionAuthorizes as Dt, chatTransportExecutor as E, superviseDispatch as Et, strategyAuthorContract as F, renderLeaderboardSvg as Ft, reconnectRetainedRun as G, mcpSecretEnvMetadataKey as Gt, reconnectRetainedInteractiveRun as H, createMcpEnvironment as Ht, strategyAuthorSystemPrompt as I, renderPairwiseMarkdown as It, startRetainedRunInEnvironment as J, secretEnvOfMcpServer as Jt, recoverRetainedRun as K, resolveMcpServerLaunch as Kt, SandboxRunAbortError as L, auditIntent as Lt, selectChampion as M, pairwiseSignificance as Mt, assertStrategyContract as N, renderLeaderboardHtml as Nt, createChatSessionStore as O, deterministicCompletion as Ot, authorStrategy as P, renderLeaderboardMarkdown as Pt, definePersona as Q, openSandboxRun as R, defaultAuditorInstruction as Rt, withUntrackedArtifacts as S, localSandboxClient as St, runCoderChecks as T, loopDispatch as Tt, recoverRetainedInteractiveRun as U, sanitizeMcpToolSchema as Ut, claimRetainedInteractiveControl as V, materializeLocalMcp as Vt, startRetainedInteractiveRun as W, envKeyProvider as Wt, equalKOnCost as X, promotionGate as Y, trajectoryReport as Z, VERIFY_TAIL_CHARS as _, registryScopeAnalyst as _t, localShell as a, renderCorpusToInstructions as at, settledWorkerOut as b, defineLeaderboard as bt, createVerifierEnvironment as c, loopUntil as ct, harvestSurfaceDiffs as d, selectValidWinner as dt, builtinShapes as et, failuresAnalyst as f, verify as ft, NOTE_MAX_CHARS as g, createScopeAnalyst as gt, EVIDENCE_MAX_CHARS as h, buildSteerContext as ht, jjWorkspace as i, InMemoryCorpus as it, runStrategyEvolution as j, leaderboard as jt, discriminatingMeans as k, sentinelCompletion as kt, boxSurfaceReader as l, panel as lt, worktreeFanout as m, assertTraceDerivedFindings as mt, makeFinding$1 as n, registerShape as nt, runInWorkspace as o, fanout as ot, superviseSurface as p, widen as pt, startRetainedRun as q, resolveSecretEnv as qt, gitWorkspace as r, FileCorpus as rt, createWaterfallCollector as s, flatWidenGate as st, computeFindingId$1 as t, createShapeRegistry as tt, fsSurfaceReader as u, pipeline as ut, closingWorkerNote as v, inProcessSandboxClient as vt, patchDelivered as w, loopCampaignDispatch as wt, copyUntrackedIntoClone as x, resolveSandboxClient as xt, composeWorkerEvidence as y, harvestCorpus as yt, printBenchmarkReport as z, McpSpawnFault as zt };
6674
7102
 
6675
- //# sourceMappingURL=runtime-CUpB4rEP.js.map
7103
+ //# sourceMappingURL=runtime-tTA2iCZQ.js.map