@tangle-network/agent-runtime 0.174.1 → 0.177.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 (104) hide show
  1. package/README.md +4 -0
  2. package/dist/{activation-CsdJWRXX.js → activation-XVI_z1g3.js} +3 -3
  3. package/dist/{activation-CsdJWRXX.js.map → activation-XVI_z1g3.js.map} +1 -1
  4. package/dist/agent.d.ts +1 -1
  5. package/dist/agent.js +2 -2
  6. package/dist/{authoring-DsLNInAz.js → authoring-bXmPNfCI.js} +2 -2
  7. package/dist/{authoring-DsLNInAz.js.map → authoring-bXmPNfCI.js.map} +1 -1
  8. package/dist/candidate-execution/index.js +4 -4
  9. package/dist/{candidate-execution-BbMbyhgC.js → candidate-execution-fBNUyWyE.js} +10 -4
  10. package/dist/candidate-execution-fBNUyWyE.js.map +1 -0
  11. package/dist/{conversation-7XGKoDM6.js → conversation-BREx2hi-.js} +3 -3
  12. package/dist/{conversation-7XGKoDM6.js.map → conversation-BREx2hi-.js.map} +1 -1
  13. package/dist/conversation.d.ts +1 -1
  14. package/dist/conversation.js +1 -1
  15. package/dist/coordination-driver-xO1tkxy-.js +3063 -0
  16. package/dist/coordination-driver-xO1tkxy-.js.map +1 -0
  17. package/dist/durable-file-g3YdfEh4.js +131 -0
  18. package/dist/durable-file-g3YdfEh4.js.map +1 -0
  19. package/dist/durable.d.ts +2 -2
  20. package/dist/durable.js +1 -1
  21. package/dist/{environment-provider-DWjbGH8W.d.ts → environment-provider-5E82esWE.d.ts} +6 -3
  22. package/dist/{environment-provider-Bn3652YU.js → environment-provider-DKyMWQJd.js} +121 -17
  23. package/dist/environment-provider-DKyMWQJd.js.map +1 -0
  24. package/dist/environment-provider.d.ts +1 -1
  25. package/dist/environment-provider.js +1 -1
  26. package/dist/{graph-BbeHgLXH.js → graph-DwJXa1Ph.js} +3 -3
  27. package/dist/graph-DwJXa1Ph.js.map +1 -0
  28. package/dist/graph.d.ts +11 -3
  29. package/dist/graph.js +35 -4
  30. package/dist/graph.js.map +1 -1
  31. package/dist/{improvement-cycle-DKGDCukL.js → improvement-cycle-eiSv6aH4.js} +5 -5
  32. package/dist/{improvement-cycle-DKGDCukL.js.map → improvement-cycle-eiSv6aH4.js.map} +1 -1
  33. package/dist/{index-CIhkH7mq.d.ts → index-BnAiQVLD.d.ts} +290 -29
  34. package/dist/{index-CFMB9ux3.d.ts → index-Bs0uhf-y.d.ts} +2 -2
  35. package/dist/{index-Dk5X9eKg.d.ts → index-C9XTLVP1.d.ts} +4 -4
  36. package/dist/index.d.ts +7 -7
  37. package/dist/index.js +13 -13
  38. package/dist/intelligence.d.ts +4 -4
  39. package/dist/intelligence.js +6 -6
  40. package/dist/kernel.d.ts +6 -6
  41. package/dist/kernel.js +13 -11
  42. package/dist/{knowledge-BaAX0HVu.js → knowledge-Bmtj_7u7.js} +5 -5
  43. package/dist/{knowledge-BaAX0HVu.js.map → knowledge-Bmtj_7u7.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-DRYApMiu.d.ts → loop-runner-bin-ChS5deJ0.d.ts} +3 -3
  47. package/dist/{loop-runner-bin-D63Tytdk.js → loop-runner-bin-GTN5wqCt.js} +3 -3
  48. package/dist/{loop-runner-bin-D63Tytdk.js.map → loop-runner-bin-GTN5wqCt.js.map} +1 -1
  49. package/dist/loop-runner-bin.d.ts +1 -1
  50. package/dist/loop-runner-bin.js +1 -1
  51. package/dist/{materialization-Ct3I4wu3.js → materialization-CekWK6OO.js} +5 -3
  52. package/dist/materialization-CekWK6OO.js.map +1 -0
  53. package/dist/mcp/bin.js +3 -3
  54. package/dist/mcp/index.d.ts +3 -3
  55. package/dist/mcp/index.js +5 -4
  56. package/dist/mcp/index.js.map +1 -1
  57. package/dist/{openai-tools-BBgjWYNw.js → openai-tools-BBj1QGJp.js} +2 -2
  58. package/dist/{openai-tools-BBgjWYNw.js.map → openai-tools-BBj1QGJp.js.map} +1 -1
  59. package/dist/{prepare-BAyaNoZu.js → prepare-Tip-2ZoZ.js} +2 -2
  60. package/dist/{prepare-BAyaNoZu.js.map → prepare-Tip-2ZoZ.js.map} +1 -1
  61. package/dist/primeintellect/index.d.ts +1 -1
  62. package/dist/{protected-model-port-T2UWrDNQ.js → protected-model-port-Dd3a1SRm.js} +2 -2
  63. package/dist/{protected-model-port-T2UWrDNQ.js.map → protected-model-port-Dd3a1SRm.js.map} +1 -1
  64. package/dist/provision-supervisor-zA__ayUX.js +1020 -0
  65. package/dist/provision-supervisor-zA__ayUX.js.map +1 -0
  66. package/dist/{redact-DvLf4x1m.d.ts → redact-DkRLcSiE.d.ts} +3 -3
  67. package/dist/run-layout-Cd_l2XWV.js +645 -0
  68. package/dist/run-layout-Cd_l2XWV.js.map +1 -0
  69. package/dist/{runtime-D5u1M6T5.d.ts → runtime-B2eZ76kG.d.ts} +3 -3
  70. package/dist/{runtime-CojgP-hr.js → runtime-CJNlF5wM.js} +16 -1095
  71. package/dist/runtime-CJNlF5wM.js.map +1 -0
  72. package/dist/{spawn-journal-Tgvp5VS5.js → spawn-journal--N8Ten1q.js} +3 -1
  73. package/dist/{spawn-journal-Tgvp5VS5.js.map → spawn-journal--N8Ten1q.js.map} +1 -1
  74. package/dist/{stream-agent-turn-DxQ3GOuR.d.ts → stream-agent-turn-ByY8po9W.d.ts} +2 -2
  75. package/dist/{stream-agent-turn-CKIpCbSq.js → stream-agent-turn-CPj9SqVm.js} +2 -2
  76. package/dist/{stream-agent-turn-CKIpCbSq.js.map → stream-agent-turn-CPj9SqVm.js.map} +1 -1
  77. package/dist/{structural-rollout-BUYA61iV.js → structural-rollout-BeAUK7Ta.js} +4 -4
  78. package/dist/{structural-rollout-BUYA61iV.js.map → structural-rollout-BeAUK7Ta.js.map} +1 -1
  79. package/dist/{supervise-Ci0RfWQF.js → supervise-HsRKOlKY.js} +405 -3374
  80. package/dist/supervise-HsRKOlKY.js.map +1 -0
  81. package/dist/{supervisor-Bt1XLCVq.js → supervisor-ChLgoYhG.js} +1620 -33
  82. package/dist/supervisor-ChLgoYhG.js.map +1 -0
  83. package/dist/testing.d.ts +2 -2
  84. package/dist/testing.js +13 -12
  85. package/dist/testing.js.map +1 -1
  86. package/dist/{top-app-3rYfFPTW.js → top-app-DIBApkt1.js} +25 -9
  87. package/dist/top-app-DIBApkt1.js.map +1 -0
  88. package/dist/tui/bin.js +1 -1
  89. package/dist/tui/index.d.ts +9 -1
  90. package/dist/tui/index.js +3 -2
  91. package/dist/{types-DjVO-p7R.d.ts → types-a2ZZUl80.d.ts} +25 -2
  92. package/dist/{workspace-archive-B0Hqp2eJ.js → workspace-archive-DOZAeeKU.js} +2 -2
  93. package/dist/{workspace-archive-B0Hqp2eJ.js.map → workspace-archive-DOZAeeKU.js.map} +1 -1
  94. package/package.json +5 -4
  95. package/dist/candidate-execution-BbMbyhgC.js.map +0 -1
  96. package/dist/environment-provider-Bn3652YU.js.map +0 -1
  97. package/dist/graph-BbeHgLXH.js.map +0 -1
  98. package/dist/materialization-Ct3I4wu3.js.map +0 -1
  99. package/dist/run-layout-C2jgwsCq.js +0 -393
  100. package/dist/run-layout-C2jgwsCq.js.map +0 -1
  101. package/dist/runtime-CojgP-hr.js.map +0 -1
  102. package/dist/supervise-Ci0RfWQF.js.map +0 -1
  103. package/dist/supervisor-Bt1XLCVq.js.map +0 -1
  104. package/dist/top-app-3rYfFPTW.js.map +0 -1
@@ -0,0 +1,1020 @@
1
+ import { D as abortError, o as finalizeRuntimeOwnedPendingExecutor, r as attestRuntimeOwnedPendingExecutor, u as newExecutionAttemptId } from "./materialization-CekWK6OO.js";
2
+ import { n as detachedSnapshot } from "./snapshot-CTAf4uuA.js";
3
+ import { x as contentAddress } from "./spawn-journal--N8Ten1q.js";
4
+ import { t as executableAgentProfileSnapshot } from "./executable-spec-CkGvdPds.js";
5
+ import { a as concreteProfileModel } from "./model-policy-Sw4ywhtL.js";
6
+ import { A as readWorkerInteractiveBinding, B as retainedCreateMaterial, E as interactiveAdmissionSeamKey, F as startRetainedInteractiveRun, Nt as taskToPrompt, n as createSupervisor, t as createRootHandle, xt as createInbox } from "./supervisor-ChLgoYhG.js";
7
+ import { a as sandboxClientAsProvider, c as linkAbort, s as abortError$1 } from "./environment-provider-DKyMWQJd.js";
8
+ import { i as writeAtomicDurableFile } from "./durable-file-g3YdfEh4.js";
9
+ import { n as createSteerAcknowledger, t as createCancelAcknowledger, v as createFileRunContext, w as createCoordinationTools } from "./coordination-driver-xO1tkxy-.js";
10
+ import { h as supervisorRunDir } from "./run-layout-Cd_l2XWV.js";
11
+ import { agentInteractiveSessionControlClaimRequestDigest, agentInteractiveSessionPromptRequestDigest, agentInteractiveSessionStopRequestDigest, agentProfileSchema, canonicalAgentProfileDigest, canonicalCandidateDigest } from "@tangle-network/agent-interface";
12
+ import { randomUUID } from "node:crypto";
13
+ import { dirname, join, resolve } from "node:path";
14
+ import { mkdirSync } from "node:fs";
15
+ import { tmpdir } from "node:os";
16
+ //#region src/runtime/retained-interactive-control.ts
17
+ const MAX_GENERATION_CONFLICTS = 8;
18
+ /**
19
+ * Acquire provider-issued write authority without reading authority from status.
20
+ *
21
+ * A new coordinator starts at generation zero. If another claim already exists,
22
+ * the provider returns its public generation and this helper retries one new
23
+ * compare-and-swap operation. Every generation has a deterministic operation
24
+ * identifier, so retrying after an ambiguous response cannot create two claims.
25
+ * @stable
26
+ */
27
+ async function claimRetainedInteractiveControl(options) {
28
+ const expected = options.expectedGeneration ?? 0;
29
+ if (!Number.isSafeInteger(expected) || expected < 0) throw new Error("interactive control expectedGeneration must be a non-negative integer");
30
+ let generation = expected;
31
+ for (let conflict = 0; conflict <= MAX_GENERATION_CONFLICTS; conflict += 1) {
32
+ if (options.signal?.aborted) throw abortError(options.signal.reason);
33
+ const material = {
34
+ operationId: controlClaimOperationId(options.handle, options.holderId, generation),
35
+ ref: options.handle.ref,
36
+ holderId: options.holderId,
37
+ expectedGeneration: generation
38
+ };
39
+ const acknowledgement = await options.handle.claimControl({
40
+ ...material,
41
+ requestDigest: agentInteractiveSessionControlClaimRequestDigest(material)
42
+ }, options.signal === void 0 ? void 0 : { signal: options.signal });
43
+ if (acknowledgement.status === "accepted" || acknowledgement.status === "replayed") {
44
+ const control = acknowledgement.control;
45
+ if (control === void 0) throw new Error("provider accepted interactive control without returning its claim");
46
+ if (Date.parse(control.expiresAt) <= Date.now()) throw new Error("provider returned an expired interactive control claim");
47
+ return control;
48
+ }
49
+ 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");
50
+ const current = acknowledgement.currentGeneration;
51
+ if (current === void 0 || current <= generation) throw new Error("provider returned a non-advancing interactive control generation");
52
+ generation = current;
53
+ }
54
+ throw new Error("interactive control changed too often to acquire safely");
55
+ }
56
+ function controlClaimOperationId(handle, holderId, expectedGeneration) {
57
+ return `interactive-claim-${canonicalCandidateDigest({
58
+ kind: "retained-interactive-control-claim.v1",
59
+ ref: handle.ref,
60
+ holderId,
61
+ expectedGeneration
62
+ }).slice(7, 47)}`;
63
+ }
64
+ //#endregion
65
+ //#region src/runtime/supervise/interactive-worker.ts
66
+ /**
67
+ * Runtime-owned worker seam for a provider's native interactive coding-agent process.
68
+ *
69
+ * This adapter composes the retained-interactive lifecycle. It does not create a second stream,
70
+ * replay buffer, session id, or cancellation protocol. The provider owns process state; Scope owns
71
+ * the supervised worker, journal, budget, and local control inbox.
72
+ */
73
+ /**
74
+ * Build a `MakeWorkerAgent` that starts one exact provider-owned native TUI per worker.
75
+ *
76
+ * A Scope supplies the durable admission hook and kernel-minted node attempt. The returned worker
77
+ * exposes `interactiveReady`, so Scope writes the exact provider reference before the worker can be
78
+ * attached by a different process. `attachWorker` then reconnects that same reference through the
79
+ * provider's public `get`/interactive contract.
80
+ */
81
+ function workerFromInteractiveProvider(provider, options = {}) {
82
+ if (!provider.name.trim()) throw new Error("workerFromInteractiveProvider: provider.name required");
83
+ if (!provider.get) throw new Error(`workerFromInteractiveProvider(${provider.name}): provider.get is required for reconnect`);
84
+ const capturedEnvironment = options.environment ? structuredClone(options.environment) : void 0;
85
+ const unscopedNamespace = randomUUID();
86
+ let unscopedOrdinal = 0;
87
+ const runtime = options.runtime ?? provider.name;
88
+ return (rawProfile, spawnContext) => {
89
+ const profile = executableAgentProfileSnapshot(rawProfile, `workerFromInteractiveProvider(${provider.name})`);
90
+ const input = {
91
+ provider: provider.name,
92
+ profile,
93
+ ...spawnContext === void 0 ? {} : { context: spawnContext }
94
+ };
95
+ const assignmentId = spawnContext?.assignmentId ?? `unscoped:${unscopedNamespace}:${unscopedOrdinal++}`;
96
+ const baseInput = {
97
+ ...input,
98
+ nodeId: spawnContext?.parentNodeId
99
+ };
100
+ const environmentKey = stableKey(options.environmentIdempotencyKey?.({ ...baseInput }) ?? derivedKey("supervised-interactive-environment", {
101
+ provider: provider.name,
102
+ assignmentId,
103
+ parentNodeId: spawnContext?.parentNodeId,
104
+ profile
105
+ }), "environment idempotency key");
106
+ const name = profile.name ?? "interactive-worker";
107
+ const executorFactory = (spec, ctx) => interactiveExecutor({
108
+ provider,
109
+ profile: spec.profile,
110
+ context: spawnContext,
111
+ environment: capturedEnvironment,
112
+ environmentKey,
113
+ interactiveKey: (task) => stableKey(options.interactiveIdempotencyKey?.({
114
+ ...baseInput,
115
+ task
116
+ }) ?? derivedKey("supervised-interactive-session", {
117
+ provider: provider.name,
118
+ assignmentId,
119
+ parentNodeId: spawnContext?.parentNodeId,
120
+ profile: spec.profile,
121
+ task
122
+ }), "interactive idempotency key"),
123
+ holderId: (task) => {
124
+ return stableKey((typeof options.holderId === "function" ? options.holderId({
125
+ ...baseInput,
126
+ task
127
+ }) : options.holderId) ?? `runtime-interactive-worker:${canonicalCandidateDigest({
128
+ provider: provider.name,
129
+ assignmentId
130
+ })}`, "interactive holder id");
131
+ },
132
+ initialPrompt: options.initialPrompt,
133
+ cwd: options.cwd,
134
+ cols: options.cols,
135
+ rows: options.rows,
136
+ runtime,
137
+ pollIntervalMs: options.pollIntervalMs,
138
+ destroyEnvironmentOnTeardown: options.destroyEnvironmentOnTeardown,
139
+ executionAttemptId: ctx.node?.attemptId,
140
+ nodeId: ctx.node?.nodeId,
141
+ admission: admissionWriter(ctx, provider.name, ctx.node?.nodeId)
142
+ });
143
+ return {
144
+ name,
145
+ act: async () => {
146
+ throw new Error("workerFromInteractiveProvider: interactive workers execute through executorSpec");
147
+ },
148
+ executorSpec: {
149
+ profile,
150
+ harness: null,
151
+ executorFactory,
152
+ ...spawnContext?.execution ? { execution: spawnContext.execution } : {}
153
+ }
154
+ };
155
+ };
156
+ }
157
+ function interactiveExecutor(input) {
158
+ const attemptId = input.executionAttemptId ?? newExecutionAttemptId(input.nodeId ?? input.environmentKey);
159
+ const localController = new AbortController();
160
+ const inbox = createInbox();
161
+ let handle;
162
+ let environmentId;
163
+ let artifact;
164
+ let activeLink;
165
+ let startPromise;
166
+ let executeStarted = false;
167
+ let readyResolve;
168
+ const ready = new Promise((resolve) => {
169
+ readyResolve = resolve;
170
+ });
171
+ const stopOperations = /* @__PURE__ */ new Map();
172
+ const memoryAdmissions = /* @__PURE__ */ new Map();
173
+ let teardownComplete = false;
174
+ let teardownPromise;
175
+ let flushChain = Promise.resolve();
176
+ let controlError;
177
+ const executor = {
178
+ runtime: input.runtime,
179
+ execute(task, signal) {
180
+ if (executeStarted || teardownComplete || teardownPromise !== void 0) throw new Error("workerFromInteractiveProvider: execute() may only be called once");
181
+ executeStarted = true;
182
+ startPromise = startInteractive(task, signal);
183
+ return runInteractive(signal);
184
+ },
185
+ deliver(message) {
186
+ if (teardownComplete || teardownPromise !== void 0) return false;
187
+ const accepted = inbox.deliver(message);
188
+ if (accepted) flushInbox();
189
+ return accepted;
190
+ },
191
+ interactive() {
192
+ return handle ? {
193
+ status: "available",
194
+ handle
195
+ } : {
196
+ status: "unavailable",
197
+ reason: "interactive-session-not-started"
198
+ };
199
+ },
200
+ interactiveReady() {
201
+ return ready;
202
+ },
203
+ async cancel(request) {
204
+ const existing = stopOperations.get(request.operationId);
205
+ if (existing) return existing;
206
+ const tracked = stopInteractive(request.operationId, request.reason, request.signal).then((result) => {
207
+ if (result.status === "unknown" && stopOperations.get(request.operationId) === tracked) stopOperations.delete(request.operationId);
208
+ return result;
209
+ });
210
+ stopOperations.set(request.operationId, tracked);
211
+ return tracked;
212
+ },
213
+ teardown(grace) {
214
+ if (teardownComplete) return Promise.resolve({ destroyed: true });
215
+ if (teardownPromise !== void 0) return teardownPromise;
216
+ teardownPromise = teardownInteractive().then((result) => {
217
+ teardownComplete = true;
218
+ return result;
219
+ }, (error) => {
220
+ teardownPromise = void 0;
221
+ throw error;
222
+ });
223
+ return teardownPromise;
224
+ },
225
+ resultArtifact() {
226
+ if (!artifact) throw new Error("workerFromInteractiveProvider: resultArtifact() read before execution settled");
227
+ return artifact;
228
+ }
229
+ };
230
+ const declaredEnvironment = input.environment ? retainedCreateMaterial({
231
+ ...input.environment,
232
+ profile: input.profile,
233
+ idempotencyKey: input.environmentKey
234
+ }) : null;
235
+ const profileModel = concreteProfileModel(input.profile);
236
+ const plannedDeclaration = {
237
+ effectiveProfile: input.profile,
238
+ backend: input.provider.name,
239
+ model: profileModel ? {
240
+ status: "known",
241
+ id: profileModel
242
+ } : {
243
+ status: "unknown",
244
+ reason: "provider selected the model"
245
+ },
246
+ execution: {
247
+ kind: "interactive-session",
248
+ id: input.nodeId ?? input.environmentKey
249
+ },
250
+ materializer: "retained-interactive-provider",
251
+ plan: {
252
+ kind: "retained-interactive-provider",
253
+ provider: input.provider.name,
254
+ environment: declaredEnvironment,
255
+ environmentIdempotencyKey: input.environmentKey,
256
+ destroyEnvironmentOnTeardown: input.destroyEnvironmentOnTeardown !== false
257
+ }
258
+ };
259
+ attestRuntimeOwnedPendingExecutor(executor, input.runtime, plannedDeclaration, {
260
+ attemptId,
261
+ binding: {
262
+ provider: input.provider.name,
263
+ environmentIdempotencyKey: input.environmentKey,
264
+ nodeId: input.nodeId ?? null
265
+ },
266
+ descriptor: {
267
+ kind: "interactive-session",
268
+ provider: input.provider.name,
269
+ transport: "agent-environment"
270
+ }
271
+ });
272
+ async function startInteractive(task, signal) {
273
+ try {
274
+ activeLink = linkAbort(signal, localController.signal);
275
+ const initialPrompt = typeof input.initialPrompt === "function" ? input.initialPrompt(task, {
276
+ provider: input.provider.name,
277
+ profile: input.profile,
278
+ ...input.context === void 0 ? {} : { context: input.context },
279
+ task,
280
+ ...input.nodeId === void 0 ? {} : { nodeId: input.nodeId }
281
+ }) : input.initialPrompt ?? taskToPrompt(task);
282
+ if (typeof initialPrompt !== "string") throw new Error("workerFromInteractiveProvider: initialPrompt must return a string");
283
+ const interactiveIdempotencyKey = input.interactiveKey(task);
284
+ const started = await startRetainedInteractiveRun({
285
+ provider: input.provider,
286
+ environment: {
287
+ ...input.environment ?? {},
288
+ profile: input.profile,
289
+ idempotencyKey: input.environmentKey
290
+ },
291
+ interactiveIdempotencyKey,
292
+ ...initialPrompt.length === 0 ? {} : { initialPrompt },
293
+ ...input.cwd === void 0 ? {} : { cwd: input.cwd },
294
+ ...input.cols === void 0 ? {} : { cols: input.cols },
295
+ ...input.rows === void 0 ? {} : { rows: input.rows },
296
+ onAdmission: async (admission) => {
297
+ environmentId = admission.phase === "interactive_environment" ? admission.environmentId : environmentId;
298
+ const existing = memoryAdmissions.get(admission.phase);
299
+ if (existing !== void 0) {
300
+ if (canonicalCandidateDigest(existing) !== canonicalCandidateDigest(admission)) throw new Error(`interactive admission phase '${admission.phase}' changed across retry`);
301
+ } else memoryAdmissions.set(admission.phase, detachedSnapshot(admission, "interactive admission"));
302
+ await input.admission(admission);
303
+ },
304
+ signal: activeLink.signal
305
+ });
306
+ finalizeRuntimeOwnedPendingExecutor(executor, {
307
+ ...plannedDeclaration,
308
+ execution: {
309
+ kind: "interactive-session",
310
+ id: started.ref.run.executionId
311
+ },
312
+ plan: {
313
+ ...plannedDeclaration.plan,
314
+ environmentId: started.ref.run.environmentId,
315
+ interactiveIdempotencyKey
316
+ }
317
+ }, {
318
+ attemptId,
319
+ binding: {
320
+ provider: input.provider.name,
321
+ ref: started.ref,
322
+ environmentId: started.ref.run.environmentId
323
+ },
324
+ descriptor: {
325
+ kind: "interactive-session",
326
+ provider: input.provider.name,
327
+ transport: "agent-environment"
328
+ }
329
+ });
330
+ handle = started;
331
+ readyResolve({
332
+ status: "available",
333
+ handle: started
334
+ });
335
+ flushInbox();
336
+ return started;
337
+ } catch (error) {
338
+ readyResolve({
339
+ status: "unavailable",
340
+ reason: unavailableReason(error)
341
+ });
342
+ activeLink?.release();
343
+ throw error;
344
+ }
345
+ }
346
+ async function* runInteractive(signal) {
347
+ const startedAt = Date.now();
348
+ try {
349
+ const current = await startPromise;
350
+ if (current === void 0) throw new Error("workerFromInteractiveProvider: interactive start did not begin");
351
+ yield { kind: "iteration" };
352
+ yield {
353
+ kind: "tokens",
354
+ input: 0,
355
+ output: 0,
356
+ tokensKnown: false
357
+ };
358
+ yield {
359
+ kind: "cost",
360
+ usd: 0,
361
+ usdKnown: false,
362
+ provenance: "uncaptured"
363
+ };
364
+ let status;
365
+ for (;;) {
366
+ if (signal.aborted || localController.signal.aborted) throw abortError$1(signal.aborted ? signal : localController.signal, "interactive execution aborted");
367
+ status = await current.status({ signal: activeLink?.signal });
368
+ await flushChain;
369
+ if (controlError !== void 0) throw controlErrorValue(controlError);
370
+ if (status.state !== "running") break;
371
+ await sleep(input.pollIntervalMs ?? 100, activeLink?.signal);
372
+ }
373
+ const finished = status;
374
+ const output = {
375
+ provider: input.provider.name,
376
+ environmentId: current.ref.run.environmentId,
377
+ sessionId: current.ref.run.sessionId,
378
+ executionId: current.ref.run.executionId,
379
+ state: finished?.state === "exited" ? "exited" : "unknown",
380
+ ref: current.ref,
381
+ ...finished?.state === "exited" && finished.reason ? { reason: finished.reason } : {},
382
+ ...finished?.state === "exited" && finished.exitCode !== void 0 ? { exitCode: finished.exitCode } : {},
383
+ ...finished?.state === "exited" && finished.exitSignal !== void 0 ? { exitSignal: finished.exitSignal } : {}
384
+ };
385
+ const spent = {
386
+ iterations: 1,
387
+ tokens: {
388
+ input: 0,
389
+ output: 0
390
+ },
391
+ tokensKnown: false,
392
+ usd: 0,
393
+ usdKnown: false,
394
+ ms: Date.now() - startedAt
395
+ };
396
+ artifact = {
397
+ outRef: contentAddress(output),
398
+ out: output,
399
+ spent
400
+ };
401
+ } finally {
402
+ activeLink?.release();
403
+ }
404
+ }
405
+ async function flushInbox() {
406
+ flushChain = flushChain.then(async () => {
407
+ try {
408
+ if (!handle) return;
409
+ const messages = inbox.drain();
410
+ if (messages.length === 0) return;
411
+ const prompt = inbox.fold(messages);
412
+ const operationId = `interactive-prompt-${canonicalCandidateDigest({
413
+ ref: handle.ref,
414
+ prompt
415
+ }).slice(7)}`;
416
+ const control = await claimRetainedInteractiveControl({
417
+ handle,
418
+ holderId: input.holderId(void 0)
419
+ });
420
+ const material = {
421
+ operationId,
422
+ ref: handle.ref,
423
+ control,
424
+ prompt
425
+ };
426
+ const command = {
427
+ ...material,
428
+ requestDigest: agentInteractiveSessionPromptRequestDigest(material)
429
+ };
430
+ await handle.sendPrompt(command);
431
+ } catch (error) {
432
+ controlError ??= error;
433
+ }
434
+ });
435
+ await flushChain;
436
+ }
437
+ async function stopInteractive(operationId, reason, signal) {
438
+ const observedAt = (/* @__PURE__ */ new Date()).toISOString();
439
+ if (!handle) {
440
+ localController.abort(reason ?? "interactive cancellation requested");
441
+ return {
442
+ status: "unknown",
443
+ effect: "cancel_requested",
444
+ observedAt,
445
+ detail: "interactive process has not published a provider reference"
446
+ };
447
+ }
448
+ try {
449
+ const control = await claimRetainedInteractiveControl({
450
+ handle,
451
+ holderId: input.holderId(void 0),
452
+ signal
453
+ });
454
+ const material = {
455
+ operationId,
456
+ ref: handle.ref,
457
+ control
458
+ };
459
+ const command = {
460
+ ...material,
461
+ requestDigest: agentInteractiveSessionStopRequestDigest(material)
462
+ };
463
+ const acknowledgement = await handle.stop(command, signal === void 0 ? void 0 : { signal });
464
+ localController.abort(reason ?? "interactive cancellation requested");
465
+ return cancellationFromAcknowledgement(acknowledgement, observedAt);
466
+ } catch (error) {
467
+ localController.abort(reason ?? "interactive cancellation requested");
468
+ return {
469
+ status: "unknown",
470
+ effect: "cancel_requested",
471
+ observedAt,
472
+ detail: error instanceof Error ? error.message : String(error),
473
+ evidence: { operationId }
474
+ };
475
+ }
476
+ }
477
+ async function teardownInteractive() {
478
+ localController.abort("interactive worker teardown");
479
+ activeLink?.release();
480
+ await startPromise?.catch(() => void 0);
481
+ if (handle) {
482
+ if ((await safeStatus(handle))?.state === "running") {
483
+ const cancellation = await stopInteractive(`interactive-teardown-${canonicalCandidateDigest(handle.ref).slice(7)}`, "interactive worker teardown");
484
+ if (cancellation.status === "rejected" || cancellation.status === "unknown") throw new Error(cancellation.detail ?? "interactive teardown was not acknowledged");
485
+ }
486
+ }
487
+ await destroyEnvironment();
488
+ return { destroyed: true };
489
+ }
490
+ async function destroyEnvironment() {
491
+ if (input.destroyEnvironmentOnTeardown === false) return;
492
+ if (!environmentId || !input.provider.get) return;
493
+ await (await input.provider.get(environmentId))?.destroy?.();
494
+ }
495
+ return executor;
496
+ }
497
+ function admissionWriter(ctx, provider, workerId) {
498
+ const candidate = ctx.seams[interactiveAdmissionSeamKey];
499
+ if (typeof candidate === "function") return async (admission) => {
500
+ await candidate(admission);
501
+ };
502
+ const records = /* @__PURE__ */ new Map();
503
+ return async (admission) => {
504
+ const prior = records.get(admission.phase);
505
+ if (prior && canonicalCandidateDigest(prior) !== canonicalCandidateDigest(admission)) throw new Error(`worker ${workerId ?? "(unscoped)"} provider ${provider} admission changed in memory`);
506
+ records.set(admission.phase, detachedSnapshot(admission, "interactive admission"));
507
+ };
508
+ }
509
+ function derivedKey(kind, value) {
510
+ return `${kind}-${canonicalCandidateDigest(value).slice(7)}`;
511
+ }
512
+ function stableKey(value, label) {
513
+ if (typeof value !== "string" || value.trim().length === 0) throw new Error(`${label} must be a non-empty string`);
514
+ const key = value.trim();
515
+ if (key.length > 256) throw new Error(`${label} must not exceed 256 bytes`);
516
+ return key;
517
+ }
518
+ function unavailableReason(error) {
519
+ const message = error instanceof Error ? error.message : String(error);
520
+ return message.includes("interactive") || message.includes("Interactive") ? "provider-has-no-interactive-contract" : "interactive-binding-stale";
521
+ }
522
+ function cancellationFromAcknowledgement(acknowledgement, observedAt) {
523
+ return {
524
+ status: acknowledgement.status === "accepted" || acknowledgement.status === "replayed" ? "accepted" : acknowledgement.status === "conflict" ? "rejected" : "unknown",
525
+ effect: acknowledgement.effect === "stopped" ? "cancelled" : acknowledgement.effect === "not_live" ? "not_live" : acknowledgement.effect === "stop_requested" ? "cancel_requested" : "unknown",
526
+ observedAt,
527
+ ...acknowledgement.message === void 0 ? {} : { detail: acknowledgement.message },
528
+ evidence: {
529
+ operationId: acknowledgement.operationId,
530
+ requestDigest: acknowledgement.requestDigest,
531
+ providerStatus: acknowledgement.status,
532
+ providerEffect: acknowledgement.effect
533
+ }
534
+ };
535
+ }
536
+ function controlErrorValue(error) {
537
+ return error instanceof Error ? error : new Error(String(error));
538
+ }
539
+ async function safeStatus(handle) {
540
+ try {
541
+ return await handle.status();
542
+ } catch {
543
+ return;
544
+ }
545
+ }
546
+ async function sleep(ms, signal) {
547
+ await new Promise((resolve) => {
548
+ if (signal?.aborted) {
549
+ resolve();
550
+ return;
551
+ }
552
+ let settled = false;
553
+ const onAbort = () => {
554
+ if (settled) return;
555
+ settled = true;
556
+ clearTimeout(timer);
557
+ signal?.removeEventListener("abort", onAbort);
558
+ resolve();
559
+ };
560
+ const timer = setTimeout(() => {
561
+ if (settled) return;
562
+ settled = true;
563
+ signal?.removeEventListener("abort", onAbort);
564
+ resolve();
565
+ }, Math.max(0, ms));
566
+ signal?.addEventListener("abort", onAbort, { once: true });
567
+ });
568
+ }
569
+ //#endregion
570
+ //#region src/runtime/supervise/provision-supervisor.ts
571
+ /**
572
+ * Public one-call composition for a durable Runtime supervisor proof run.
573
+ *
574
+ * This is intentionally a thin owner of existing Runtime primitives. The supervisor owns the
575
+ * root abort channel and join barrier, Scope owns worker admission and lifecycle, and the provider
576
+ * owns the environment and interactive process. External clients receive identifiers and opaque
577
+ * handles; they do not receive a second supervisor protocol or a copy of provider state.
578
+ *
579
+ * @experimental
580
+ */
581
+ const DEFAULT_TIMEOUT_MS = 6e4;
582
+ const DEFAULT_POLL_MS = 25;
583
+ const ROOT_MAX_ITERATIONS = 100;
584
+ const ROOT_MAX_TOKENS = 1e5;
585
+ const WORKER_MAX_ITERATIONS = 25;
586
+ const WORKER_MAX_TOKENS = 25e3;
587
+ var SupervisorProvisionUnavailableError = class extends Error {
588
+ unavailable = true;
589
+ constructor(message, cause) {
590
+ super(message, cause === void 0 ? void 0 : { cause });
591
+ this.name = "SupervisorProvisionUnavailableError";
592
+ }
593
+ };
594
+ /**
595
+ * Provision one real provider-backed worker and keep its owning manager alive for controls.
596
+ *
597
+ * The root manager does not use a model. It runs the same coordination tools used by a driver in a
598
+ * small deterministic loop, so durable steer and cancel requests are acknowledged by the owning
599
+ * Runtime turn loop and never by a test-only shortcut. The caller owns profile, task, and provider
600
+ * connection selection; Runtime does not infer them from process environment variables.
601
+ */
602
+ async function provisionSupervisor(request) {
603
+ const input = normalizeRequest(request);
604
+ const provider = await resolveProvider(input);
605
+ const terminalTakeover = terminalCapability(await readCapabilities(provider));
606
+ const profile = input.profile;
607
+ const rootDir = resolve(input.workspaceDir ?? makeWorkspaceDir());
608
+ mkdirSync(rootDir, { recursive: true });
609
+ const supervisorId = supervisorIdFor(input.invocationId);
610
+ const eventDir = supervisorRunDir(rootDir, supervisorId);
611
+ const statePath = join(eventDir, "state.json");
612
+ mkdirSync(dirname(eventDir), { recursive: true });
613
+ try {
614
+ mkdirSync(eventDir);
615
+ } catch (error) {
616
+ if (error.code === "EEXIST") throw unavailable(`Runtime supervisor '${supervisorId}' already exists at '${eventDir}'; use a new invocationId`);
617
+ throw error;
618
+ }
619
+ const context = createFileRunContext(eventDir);
620
+ const startedAtMs = Date.now();
621
+ const state = {
622
+ id: supervisorId,
623
+ status: "running",
624
+ task: input.task,
625
+ workspaceDir: rootDir,
626
+ budget: ROOT_MAX_TOKENS,
627
+ ...profile.model?.default === void 0 ? {} : { workerModel: profile.model.default },
628
+ startedAt: new Date(startedAtMs).toISOString()
629
+ };
630
+ writeState(statePath, state);
631
+ const rootHandle = createRootHandle();
632
+ const supervisor = createSupervisor();
633
+ supervisor.attach(rootHandle);
634
+ const workerSpawned = deferred();
635
+ const workerRunning = deferred();
636
+ const workerProfile = profile;
637
+ const makeWorkerAgent = workerFromInteractiveProvider(provider, {
638
+ environment: {
639
+ ...input.workerEnvironment ?? {},
640
+ metadata: {
641
+ ...input.workerEnvironment?.metadata ?? {},
642
+ runtime: "agent-runtime",
643
+ invocationId: input.invocationId
644
+ },
645
+ name: input.workerEnvironment?.name ?? `runtime-${supervisorId}`
646
+ },
647
+ pollIntervalMs: input.pollMs,
648
+ destroyEnvironmentOnTeardown: true
649
+ });
650
+ const rootAgent = {
651
+ name: "runtime-supervisor-root",
652
+ async act(_task, scope) {
653
+ const coord = createCoordinationTools({
654
+ scope,
655
+ blobs: context.blobs,
656
+ makeWorkerAgent,
657
+ perWorker: workerBudget()
658
+ });
659
+ await coord.ready();
660
+ const childId = workerIdFromSpawn(await findTool(coord.tools, "spawn_agent").handler({
661
+ profile: workerProfile,
662
+ task: input.task,
663
+ label: "interactive-worker"
664
+ }));
665
+ workerSpawned.resolve(childId);
666
+ for (;;) {
667
+ const child = scope.view.nodes.find((node) => node.id === childId);
668
+ if (child?.status === "running") break;
669
+ if (child === void 0 || child.status === "done" || child.status === "failed" || child.status === "cancelled") throw new Error(`Runtime supervisor worker '${childId}' ended before becoming live`);
670
+ await delay(input.pollMs);
671
+ }
672
+ workerRunning.resolve();
673
+ const steerAcknowledger = createSteerAcknowledger({
674
+ dir: eventDir,
675
+ coord,
676
+ now: Date.now,
677
+ ownerId: scope.view.root
678
+ });
679
+ const cancelAcknowledger = createCancelAcknowledger({
680
+ dir: eventDir,
681
+ coord,
682
+ scope,
683
+ now: Date.now,
684
+ ownerId: scope.view.root,
685
+ controlScope: "run"
686
+ });
687
+ const settled = scope.next();
688
+ try {
689
+ while (true) {
690
+ await steerAcknowledger.pass("turn");
691
+ cancelAcknowledger.pass("turn");
692
+ const outcome = await raceSettlement(settled, input.pollMs, scope.signal);
693
+ if (outcome !== void 0 && outcome !== null) {
694
+ await coord.drainResolved();
695
+ await steerAcknowledger.pass("final");
696
+ cancelAcknowledger.pass("final");
697
+ return outcome.kind === "done" ? outcome.out : void 0;
698
+ }
699
+ }
700
+ } finally {
701
+ await steerAcknowledger.pass("final");
702
+ cancelAcknowledger.pass("final");
703
+ cancelAcknowledger.finish();
704
+ }
705
+ }
706
+ };
707
+ const runBudget = rootBudget(input.timeoutMs);
708
+ let runResult;
709
+ let runError;
710
+ let runSettled = false;
711
+ const runPromise = supervisor.run(rootAgent, input.task, {
712
+ budget: runBudget,
713
+ rootIdentity: {
714
+ profileDigest: canonicalAgentProfileDigest(profile),
715
+ taskDigest: canonicalCandidateDigest(input.task)
716
+ },
717
+ runId: supervisorId,
718
+ ...context,
719
+ interactiveBindingDir: eventDir,
720
+ maxDepth: 1,
721
+ maxLiveWorkers: 1
722
+ }).then((result) => {
723
+ runResult = result;
724
+ runSettled = true;
725
+ updateStateFromResult(state, result);
726
+ writeState(statePath, state);
727
+ return result;
728
+ }, (error) => {
729
+ runError = error;
730
+ runSettled = true;
731
+ state.status = "down";
732
+ state.completedAt = (/* @__PURE__ */ new Date()).toISOString();
733
+ writeState(statePath, state);
734
+ throw error;
735
+ });
736
+ runPromise.catch(() => void 0);
737
+ let workerId;
738
+ try {
739
+ workerId = await waitForWorkerSpawn(workerSpawned.promise, runPromise, input.timeoutMs);
740
+ await waitForWorkerRunning(workerRunning.promise, runPromise, input.timeoutMs);
741
+ if (terminalTakeover === "required") await waitForInteractiveBinding(eventDir, workerId, runPromise, input.timeoutMs, input.pollMs);
742
+ } catch (error) {
743
+ if (!runSettled) try {
744
+ rootHandle.abort("supervisor provisioning failed");
745
+ } catch {}
746
+ await runPromise.catch(() => void 0);
747
+ throw error;
748
+ }
749
+ let cleanupPromise;
750
+ const cleanup = async () => {
751
+ cleanupPromise ??= (async () => {
752
+ if (!runSettled) try {
753
+ rootHandle.abort("supervisor cleanup");
754
+ } catch {}
755
+ const result = await runPromise.catch((error) => {
756
+ runError = error;
757
+ });
758
+ if (result !== void 0) runResult = result;
759
+ if (runError !== void 0) throw runError;
760
+ const workerStatus = workerStatusFromEvents(await waitForWorkerTerminal(context.journal, supervisorId, workerId, input.timeoutMs, input.pollMs), workerId);
761
+ if (workerStatus === "running") throw new Error(`Runtime supervisor worker '${workerId}' did not reach a terminal state`);
762
+ if (runResult?.teardownUnconfirmed?.length) throw new Error(`Runtime supervisor cleanup could not confirm ${runResult.teardownUnconfirmed.length} resource(s) released`);
763
+ const supervisorStatus = state.status;
764
+ state.completedAt ??= (/* @__PURE__ */ new Date()).toISOString();
765
+ writeState(statePath, state);
766
+ return Object.freeze({
767
+ status: "completed",
768
+ rootDir,
769
+ supervisorId,
770
+ workerId,
771
+ supervisorStatus,
772
+ workerStatus,
773
+ resourcesReleased: true,
774
+ remainingResources: Object.freeze([])
775
+ });
776
+ })();
777
+ return cleanupPromise;
778
+ };
779
+ return Object.freeze({
780
+ rootDir,
781
+ supervisorId,
782
+ workerId,
783
+ providers: provider,
784
+ terminalTakeover,
785
+ cleanup
786
+ });
787
+ }
788
+ function normalizeRequest(request) {
789
+ const invocationId = request.invocationId.trim();
790
+ if (!invocationId) throw new SupervisorProvisionUnavailableError("invocationId is required");
791
+ const task = request.task.trim();
792
+ if (!task) throw new SupervisorProvisionUnavailableError("task is required");
793
+ const profile = resolveProfile(request.profile);
794
+ if (request.connection === void 0) throw new SupervisorProvisionUnavailableError("provider connection is required");
795
+ const timeoutMs = positiveNumber(request.timeoutMs ?? DEFAULT_TIMEOUT_MS, "timeoutMs");
796
+ const pollMs = positiveNumber(request.pollMs ?? DEFAULT_POLL_MS, "pollMs");
797
+ return {
798
+ ...request,
799
+ invocationId,
800
+ task,
801
+ timeoutMs,
802
+ pollMs,
803
+ profile
804
+ };
805
+ }
806
+ function positiveNumber(value, name) {
807
+ if (!Number.isSafeInteger(value) || value <= 0) throw new SupervisorProvisionUnavailableError(`${name} must be a positive safe integer`);
808
+ return value;
809
+ }
810
+ function makeWorkspaceDir() {
811
+ return join(tmpdir(), `agent-runtime-supervisor-${randomUUID()}`);
812
+ }
813
+ function supervisorIdFor(invocationId) {
814
+ return `runtime-supervisor-${canonicalCandidateDigest({
815
+ kind: "runtime-supervisor",
816
+ invocationId
817
+ }).slice(7)}`;
818
+ }
819
+ /** The root deadline covers the complete supervisor lifecycle from run start through cleanup. */
820
+ function rootBudget(timeoutMs) {
821
+ return {
822
+ maxIterations: ROOT_MAX_ITERATIONS,
823
+ maxTokens: ROOT_MAX_TOKENS,
824
+ deadlineMs: timeoutMs
825
+ };
826
+ }
827
+ function workerBudget() {
828
+ return {
829
+ maxIterations: WORKER_MAX_ITERATIONS,
830
+ maxTokens: WORKER_MAX_TOKENS
831
+ };
832
+ }
833
+ function resolveProfile(profile) {
834
+ const parsed = agentProfileSchema.safeParse(profile);
835
+ if (!parsed.success) throw unavailable(`Runtime supervisor profile is invalid: ${parsed.error.issues.map((issue) => `${issue.path.join(".")}: ${issue.message}`).join("; ")}`);
836
+ return parsed.data;
837
+ }
838
+ async function resolveProvider(request) {
839
+ const connection = request.connection;
840
+ if (connection === void 0) throw unavailable("Runtime supervisor provider connection is required");
841
+ if (connection?.provider !== void 0) return requireReconnectProvider(connection.provider);
842
+ const client = connection?.client ?? connection?.sandboxClient;
843
+ if (client !== void 0) return requireReconnectProvider(sandboxClientAsProvider(client));
844
+ const apiKey = connection.apiKey?.trim();
845
+ const endpoint = connection.endpoint?.trim();
846
+ if (!apiKey || !endpoint) throw unavailable("Runtime supervisor needs a provider/client or both connection.endpoint and connection.apiKey");
847
+ let module;
848
+ try {
849
+ module = await import("@tangle-network/sandbox");
850
+ } catch (error) {
851
+ throw unavailable("Runtime supervisor could not load the Sandbox SDK peer dependency", error);
852
+ }
853
+ const SandboxCtor = module.Sandbox;
854
+ if (SandboxCtor === void 0) throw unavailable("Sandbox SDK does not export a Sandbox client");
855
+ return requireReconnectProvider(sandboxClientAsProvider(new SandboxCtor({
856
+ apiKey,
857
+ baseUrl: endpoint
858
+ })));
859
+ }
860
+ function requireReconnectProvider(provider) {
861
+ if (!provider.name.trim()) throw unavailable("Runtime supervisor provider has no name");
862
+ if (typeof provider.get !== "function") throw unavailable(`Runtime supervisor provider '${provider.name}' cannot reconnect environments`);
863
+ return provider;
864
+ }
865
+ async function readCapabilities(provider) {
866
+ try {
867
+ return await provider.capabilities();
868
+ } catch (error) {
869
+ throw unavailable(`Runtime supervisor could not read '${provider.name}' capabilities`, error);
870
+ }
871
+ }
872
+ function terminalCapability(capabilities) {
873
+ const interactive = capabilities.interactiveAgent;
874
+ if (interactive === void 0) return "unsupported";
875
+ return [
876
+ interactive.start,
877
+ interactive.control,
878
+ interactive.status,
879
+ interactive.attach,
880
+ interactive.reattach,
881
+ interactive.sendPrompt,
882
+ interactive.input,
883
+ interactive.resize,
884
+ interactive.stop
885
+ ].every((value) => value === true) ? "required" : "unsupported";
886
+ }
887
+ function findTool(tools, name) {
888
+ const tool = tools.find((candidate) => candidate.name === name);
889
+ if (tool === void 0) throw new Error(`Runtime supervisor coordination tool '${name}' is missing`);
890
+ return tool;
891
+ }
892
+ function workerIdFromSpawn(value) {
893
+ if (value === null || typeof value !== "object" || Array.isArray(value)) throw new Error("Runtime supervisor spawn did not return a worker id");
894
+ const workerId = value.workerId;
895
+ if (typeof workerId !== "string" || !workerId.trim()) throw new Error("Runtime supervisor spawn did not return a worker id");
896
+ return workerId;
897
+ }
898
+ async function raceSettlement(promise, pollMs, signal) {
899
+ let timer;
900
+ let onAbort;
901
+ const poll = new Promise((resolvePoll) => {
902
+ timer = setTimeout(() => resolvePoll(void 0), pollMs);
903
+ if (typeof timer.unref === "function") timer.unref();
904
+ onAbort = () => resolvePoll(void 0);
905
+ signal.addEventListener("abort", onAbort, { once: true });
906
+ });
907
+ try {
908
+ return await Promise.race([promise, poll]);
909
+ } finally {
910
+ if (timer !== void 0) clearTimeout(timer);
911
+ if (onAbort !== void 0) signal.removeEventListener("abort", onAbort);
912
+ }
913
+ }
914
+ async function waitForWorkerSpawn(worker, run, timeoutMs) {
915
+ return await withTimeout(Promise.race([worker, run.then(() => {
916
+ throw new Error("Runtime supervisor ended before it spawned a worker");
917
+ })]), timeoutMs, "worker spawn");
918
+ }
919
+ async function waitForWorkerRunning(running, run, timeoutMs) {
920
+ await withTimeout(Promise.race([running, run.then(() => {
921
+ throw new Error("Runtime supervisor ended before the worker became live");
922
+ })]), timeoutMs, "worker readiness");
923
+ }
924
+ async function waitForInteractiveBinding(eventDir, workerId, run, timeoutMs, pollMs) {
925
+ await withTimeout(pollUntil(async () => {
926
+ const binding = readWorkerInteractiveBinding(eventDir, workerId);
927
+ if (binding?.status === "available") return true;
928
+ if (binding?.status === "unavailable") throw unavailable(`Runtime worker '${workerId}' could not publish an interactive binding`);
929
+ return false;
930
+ }, run, pollMs), timeoutMs, "interactive terminal binding");
931
+ }
932
+ async function pollUntil(read, run, pollMs) {
933
+ for (;;) {
934
+ if (await read()) return;
935
+ await Promise.race([delay(pollMs), run.then(() => {
936
+ throw new Error("Runtime supervisor ended before readiness was observed");
937
+ })]);
938
+ }
939
+ }
940
+ async function withTimeout(promise, timeoutMs, label) {
941
+ let timer;
942
+ const timeout = new Promise((_resolve, reject) => {
943
+ timer = setTimeout(() => reject(unavailable(`Runtime supervisor timed out waiting for ${label}`)), timeoutMs);
944
+ if (typeof timer.unref === "function") timer.unref();
945
+ });
946
+ try {
947
+ return await Promise.race([promise, timeout]);
948
+ } finally {
949
+ if (timer !== void 0) clearTimeout(timer);
950
+ }
951
+ }
952
+ function delay(ms) {
953
+ return new Promise((resolveDelay) => {
954
+ const timer = setTimeout(resolveDelay, ms);
955
+ if (typeof timer.unref === "function") timer.unref();
956
+ });
957
+ }
958
+ function updateStateFromResult(state, result) {
959
+ state.status = result.kind === "winner" ? "done" : result.reason === "aborted" ? "cancelled" : "down";
960
+ state.completedAt = (/* @__PURE__ */ new Date()).toISOString();
961
+ }
962
+ function workerStatusFromEvents(events, workerId) {
963
+ let status = "running";
964
+ let terminal = false;
965
+ for (const event of events) {
966
+ if (event.id !== workerId) continue;
967
+ if (terminal) continue;
968
+ if (event.kind === "spawned" || event.kind === "progress") status = "running";
969
+ else if (event.kind === "settled") {
970
+ status = event.status === "done" ? "done" : "down";
971
+ terminal = true;
972
+ } else if (event.kind === "cancelled") {
973
+ status = "cancelled";
974
+ terminal = true;
975
+ }
976
+ }
977
+ return status;
978
+ }
979
+ async function waitForWorkerTerminal(journal, root, workerId, timeoutMs, pollMs) {
980
+ const deadline = Date.now() + timeoutMs;
981
+ for (;;) {
982
+ const events = await journal.loadTree(root);
983
+ if (events !== void 0 && workerStatusFromEvents(events, workerId) !== "running") return events;
984
+ if (Date.now() >= deadline) throw unavailable(`Runtime supervisor timed out waiting for worker '${workerId}' to settle`);
985
+ await delay(pollMs);
986
+ }
987
+ }
988
+ function deferred() {
989
+ let done = false;
990
+ let resolveValue;
991
+ let rejectValue;
992
+ return {
993
+ promise: new Promise((resolvePromise, rejectPromise) => {
994
+ resolveValue = (value) => {
995
+ if (done) return;
996
+ done = true;
997
+ resolvePromise(value);
998
+ };
999
+ rejectValue = (error) => {
1000
+ if (done) return;
1001
+ done = true;
1002
+ rejectPromise(error);
1003
+ };
1004
+ }),
1005
+ resolve: resolveValue,
1006
+ reject: rejectValue,
1007
+ settled: () => done
1008
+ };
1009
+ }
1010
+ function unavailable(message, cause) {
1011
+ return new SupervisorProvisionUnavailableError(message, cause);
1012
+ }
1013
+ function writeState(path, state) {
1014
+ mkdirSync(dirname(path), { recursive: true });
1015
+ writeAtomicDurableFile(path, `${JSON.stringify(state)}\n`, { mode: 384 });
1016
+ }
1017
+ //#endregion
1018
+ export { workerFromInteractiveProvider as n, claimRetainedInteractiveControl as r, provisionSupervisor as t };
1019
+
1020
+ //# sourceMappingURL=provision-supervisor-zA__ayUX.js.map