@tangle-network/agent-runtime 0.340.0 → 0.342.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 (70) hide show
  1. package/dist/{activation-D2PVljaw.js → activation-CWPmt0Do.js} +4 -4
  2. package/dist/{activation-D2PVljaw.js.map → activation-CWPmt0Do.js.map} +1 -1
  3. package/dist/{activation-DGDl4wwI.d.ts → activation-CXqtijue.d.ts} +2 -2
  4. package/dist/agent.d.ts +1 -1
  5. package/dist/agent.js +2 -2
  6. package/dist/{bundle-DNUq-OPW.js → bundle-Cwpit6Tg.js} +2 -2
  7. package/dist/{bundle-DNUq-OPW.js.map → bundle-Cwpit6Tg.js.map} +1 -1
  8. package/dist/candidate-execution/index.js +4 -4
  9. package/dist/{driver-control-acknowledgers-MTrs8HAF.js → coordination-manager-B5JsolDR.js} +4852 -4539
  10. package/dist/coordination-manager-B5JsolDR.js.map +1 -0
  11. package/dist/{delegate-CtJIS-tp.js → delegate-Rl-5paLJ.js} +2 -2
  12. package/dist/{delegate-CtJIS-tp.js.map → delegate-Rl-5paLJ.js.map} +1 -1
  13. package/dist/durable.d.ts +1 -1
  14. package/dist/durable.js +451 -358
  15. package/dist/durable.js.map +1 -1
  16. package/dist/{graph-DfWqp_1e.js → graph-Ce-59ZXn.js} +5 -5
  17. package/dist/{graph-DfWqp_1e.js.map → graph-Ce-59ZXn.js.map} +1 -1
  18. package/dist/{improve-CKRVQqzt.js → improve-BZXt2qM0.js} +837 -704
  19. package/dist/improve-BZXt2qM0.js.map +1 -0
  20. package/dist/index.d.ts +3 -3
  21. package/dist/index.js +9 -9
  22. package/dist/intelligence.d.ts +2 -2
  23. package/dist/intelligence.js +205 -191
  24. package/dist/intelligence.js.map +1 -1
  25. package/dist/kernel.d.ts +1 -1
  26. package/dist/kernel.js +9 -9
  27. package/dist/{loop-runner-DNWbTcVm.js → loop-runner-B0MV1-CD.js} +2 -2
  28. package/dist/{loop-runner-DNWbTcVm.js.map → loop-runner-B0MV1-CD.js.map} +1 -1
  29. package/dist/{loop-runner-C4EWEcXf.d.ts → loop-runner-CuhbgVGo.d.ts} +2 -2
  30. package/dist/loop-runner-bin.d.ts +1 -1
  31. package/dist/loop-runner-bin.js +1 -1
  32. package/dist/mcp/bin.js +3 -3
  33. package/dist/mcp/index.d.ts +1 -1
  34. package/dist/mcp/index.js +5 -5
  35. package/dist/{prepare-FzJoS68l.js → prepare-C-cWCyt3.js} +988 -735
  36. package/dist/prepare-C-cWCyt3.js.map +1 -0
  37. package/dist/{profile-DToH0XEs.js → profile-CbMw5hAn.js} +2 -2
  38. package/dist/{profile-DToH0XEs.js.map → profile-CbMw5hAn.js.map} +1 -1
  39. package/dist/profiles.d.ts +1 -1
  40. package/dist/{provision-supervisor-DqvWXmAE.js → provision-supervisor-DL6gEMQp.js} +444 -419
  41. package/dist/provision-supervisor-DL6gEMQp.js.map +1 -0
  42. package/dist/{runtime-C55Zgo1R.js → runtime-eghmj6W4.js} +1245 -1028
  43. package/dist/runtime-eghmj6W4.js.map +1 -0
  44. package/dist/{sandbox-profile-compat-DRr3JwDx.js → sandbox-profile-compat-FN2kab2-.js} +72 -72
  45. package/dist/{sandbox-profile-compat-DRr3JwDx.js.map → sandbox-profile-compat-FN2kab2-.js.map} +1 -1
  46. package/dist/{search-executor-ChOlRBgg.js → search-executor-rbjdZ3OD.js} +3 -3
  47. package/dist/{search-executor-ChOlRBgg.js.map → search-executor-rbjdZ3OD.js.map} +1 -1
  48. package/dist/{server-DkVBSN_S.js → server-BiK1Kcno.js} +4 -4
  49. package/dist/{server-DkVBSN_S.js.map → server-BiK1Kcno.js.map} +1 -1
  50. package/dist/{structural-rollout-C1LEk_zq.js → structural-rollout-BD9IN7K_.js} +3 -3
  51. package/dist/{structural-rollout-C1LEk_zq.js.map → structural-rollout-BD9IN7K_.js.map} +1 -1
  52. package/dist/{supervise-CaUAxZZP.js → supervise-DmOi7gll.js} +6346 -5447
  53. package/dist/supervise-DmOi7gll.js.map +1 -0
  54. package/dist/{supervisor-VXuN2OHT.js → supervisor-DUWcecAd.js} +13822 -12826
  55. package/dist/supervisor-DUWcecAd.js.map +1 -0
  56. package/dist/testing.d.ts +1 -1
  57. package/dist/testing.js +13 -13
  58. package/dist/tui/index.d.ts +1 -1
  59. package/dist/tui/index.js +1 -1
  60. package/dist/{types-DZ6L0Bv3.d.ts → types-Cgs89PQd.d.ts} +266 -356
  61. package/dist/workspace-store/index.js +273 -265
  62. package/dist/workspace-store/index.js.map +1 -1
  63. package/package.json +8 -8
  64. package/dist/driver-control-acknowledgers-MTrs8HAF.js.map +0 -1
  65. package/dist/improve-CKRVQqzt.js.map +0 -1
  66. package/dist/prepare-FzJoS68l.js.map +0 -1
  67. package/dist/provision-supervisor-DqvWXmAE.js.map +0 -1
  68. package/dist/runtime-C55Zgo1R.js.map +0 -1
  69. package/dist/supervise-CaUAxZZP.js.map +0 -1
  70. package/dist/supervisor-VXuN2OHT.js.map +0 -1
@@ -1,8 +1,8 @@
1
1
  import { o as writeAtomicDurableFile } from "./durable-file-gNI9ILAn.js";
2
- import { An as taskToPrompt, Ht as retainedCreateMaterial, Si as contentAddress, Ur as finalizeRuntimeOwnedPendingExecutor, Ut as destroyInteractiveEnvironment, Wt as environmentGone, bn as createInbox, g as interactiveAdmissionSeamKey, gr as linkAbort, ii as executableAgentProfileSnapshot, n as createSupervisor, o as createRootHandle, qr as newExecutionAttemptId, v as readWorkerInteractiveBinding, vr as signalAbortError, x as startRetainedInteractiveRun, xi as detachedSnapshot, xn as failPendingAfter, zr as attestRuntimeOwnedPendingExecutor } from "./supervisor-VXuN2OHT.js";
3
- import { Ct as armDeadlineTimer, U as abortError, ot as sleep } from "./sandbox-profile-compat-DRr3JwDx.js";
2
+ import { An as taskToPrompt, Ht as retainedCreateMaterial, Si as contentAddress, Ur as finalizeRuntimeOwnedPendingExecutor, Ut as destroyInteractiveEnvironment, Wt as environmentGone, bn as createInbox, g as interactiveAdmissionSeamKey, gr as linkAbort, ii as executableAgentProfileSnapshot, n as createSupervisor, o as createRootHandle, qr as newExecutionAttemptId, v as readWorkerInteractiveBinding, vr as signalAbortError, x as startRetainedInteractiveRun, xi as detachedSnapshot, xn as failPendingAfter, zr as attestRuntimeOwnedPendingExecutor } from "./supervisor-DUWcecAd.js";
3
+ import { Ct as armDeadlineTimer, U as abortError, ot as sleep } from "./sandbox-profile-compat-FN2kab2-.js";
4
4
  import { a as concreteProfileModel } from "./model-policy-CyCUwHed.js";
5
- import { f as createFileRunContext, n as createSteerAcknowledger, r as createCoordinationTools, t as createCancelAcknowledger } from "./driver-control-acknowledgers-MTrs8HAF.js";
5
+ import { f as createFileRunContext, o as createCancelAcknowledger, s as createSteerAcknowledger, t as createCoordinationTools } from "./coordination-manager-B5JsolDR.js";
6
6
  import { g as supervisorRunDir } from "./run-cancellation-C9oL62sW.js";
7
7
  import { agentInteractiveSessionControlClaimRequestDigest, agentInteractiveSessionPromptRequestDigest, agentInteractiveSessionStopRequestDigest, agentProfileSchema, canonicalAgentProfileDigest, canonicalCandidateDigest } from "@tangle-network/agent-interface";
8
8
  import { randomUUID } from "node:crypto";
@@ -58,493 +58,407 @@ function controlClaimOperationId(handle, holderId, expectedGeneration) {
58
58
  }).slice(7, 47)}`;
59
59
  }
60
60
  //#endregion
61
- //#region src/runtime/supervise/interactive-worker.ts
61
+ //#region src/runtime/supervise/interactive-executor.ts
62
62
  /**
63
- * Runtime-owned worker seam for a provider's native interactive coding-agent process.
64
- *
65
- * This adapter composes the retained-interactive lifecycle. It does not create a second stream,
66
- * replay buffer, session id, or cancellation protocol. The provider owns process state; Scope owns
67
- * the supervised worker, journal, budget, and local control inbox.
63
+ * The executor behind one interactive worker: starts the provider's retained interactive process,
64
+ * polls it to exit, relays steers as prompts, and stops and releases it exactly once.
68
65
  */
69
66
  const INTERACTIVE_TEARDOWN_TIMEOUT_MS = 3e4;
70
- /**
71
- * Build a `MakeWorkerAgent` that starts one exact provider-owned native TUI per worker.
72
- *
73
- * A Scope supplies the durable admission hook and kernel-minted node attempt. The returned worker
74
- * exposes `interactiveReady`, so Scope writes the exact provider reference before the worker can be
75
- * attached by a different process. `attachWorker` then reconnects that same reference through the
76
- * provider's public `get`/interactive contract.
77
- */
78
- function workerFromInteractiveProvider(provider, options = {}) {
79
- if (!provider.name.trim()) throw new Error("workerFromInteractiveProvider: provider.name required");
80
- if (!provider.get) throw new Error(`workerFromInteractiveProvider(${provider.name}): provider.get is required for reconnect`);
81
- const capturedEnvironment = options.environment ? structuredClone(options.environment) : void 0;
82
- const unscopedNamespace = randomUUID();
83
- let unscopedOrdinal = 0;
84
- const runtime = options.runtime ?? provider.name;
85
- return (rawProfile, spawnContext) => {
86
- const profile = executableAgentProfileSnapshot(rawProfile, `workerFromInteractiveProvider(${provider.name})`);
87
- const input = {
88
- provider: provider.name,
89
- profile,
90
- ...spawnContext === void 0 ? {} : { context: spawnContext }
91
- };
92
- const assignmentId = spawnContext?.assignmentId ?? `unscoped:${unscopedNamespace}:${unscopedOrdinal++}`;
93
- const baseInput = {
94
- ...input,
95
- nodeId: spawnContext?.parentNodeId
96
- };
97
- const environmentKey = stableKey(options.environmentIdempotencyKey?.({ ...baseInput }) ?? derivedKey("supervised-interactive-environment", {
98
- provider: provider.name,
99
- assignmentId,
100
- parentNodeId: spawnContext?.parentNodeId,
101
- profile
102
- }), "environment idempotency key");
103
- const name = profile.name ?? "interactive-worker";
104
- const executorFactory = (spec, ctx) => interactiveExecutor({
105
- provider,
106
- profile: spec.profile,
107
- context: spawnContext,
108
- environment: capturedEnvironment,
109
- environmentKey,
110
- interactiveKey: (task) => stableKey(options.interactiveIdempotencyKey?.({
111
- ...baseInput,
112
- task
113
- }) ?? derivedKey("supervised-interactive-session", {
114
- provider: provider.name,
115
- assignmentId,
116
- parentNodeId: spawnContext?.parentNodeId,
117
- profile: spec.profile,
118
- task
119
- }), "interactive idempotency key"),
120
- holderId: (task) => {
121
- return stableKey((typeof options.holderId === "function" ? options.holderId({
122
- ...baseInput,
123
- task
124
- }) : options.holderId) ?? `runtime-interactive-worker:${canonicalCandidateDigest({
125
- provider: provider.name,
126
- assignmentId
127
- })}`, "interactive holder id");
128
- },
129
- initialPrompt: options.initialPrompt,
130
- cwd: options.cwd,
131
- cols: options.cols,
132
- rows: options.rows,
133
- runtime,
134
- pollIntervalMs: options.pollIntervalMs,
135
- destroyEnvironmentOnTeardown: options.destroyEnvironmentOnTeardown,
136
- executionAttemptId: ctx.node?.attemptId,
137
- nodeId: ctx.node?.nodeId,
138
- admission: admissionWriter(ctx, provider.name, ctx.node?.nodeId)
139
- });
140
- return {
141
- name,
142
- act: async () => {
143
- throw new Error("workerFromInteractiveProvider: interactive workers execute through executorSpec");
144
- },
145
- executorSpec: {
146
- profile,
147
- harness: null,
148
- executorFactory,
149
- ...spawnContext?.execution ? { execution: spawnContext.execution } : {}
150
- }
151
- };
67
+ const descriptorOf = (input) => ({
68
+ kind: "interactive-session",
69
+ provider: input.provider.name,
70
+ transport: "agent-environment"
71
+ });
72
+ function plannedDeclarationOf(input) {
73
+ const declaredEnvironment = input.environment ? retainedCreateMaterial({
74
+ ...input.environment,
75
+ profile: input.profile,
76
+ idempotencyKey: input.environmentKey
77
+ }) : null;
78
+ const profileModel = concreteProfileModel(input.profile);
79
+ return {
80
+ effectiveProfile: input.profile,
81
+ backend: input.provider.name,
82
+ model: profileModel ? {
83
+ status: "known",
84
+ id: profileModel
85
+ } : {
86
+ status: "unknown",
87
+ reason: "provider selected the model"
88
+ },
89
+ execution: {
90
+ kind: "interactive-session",
91
+ id: input.nodeId ?? input.environmentKey
92
+ },
93
+ materializer: "retained-interactive-provider",
94
+ plan: {
95
+ kind: "retained-interactive-provider",
96
+ provider: input.provider.name,
97
+ environment: declaredEnvironment,
98
+ environmentIdempotencyKey: input.environmentKey,
99
+ destroyEnvironmentOnTeardown: input.destroyEnvironmentOnTeardown !== false
100
+ }
152
101
  };
153
102
  }
154
103
  function interactiveExecutor(input) {
155
104
  const attemptId = input.executionAttemptId ?? newExecutionAttemptId(input.nodeId ?? input.environmentKey);
156
- const localController = new AbortController();
157
- const inbox = createInbox();
158
- let handle;
159
- let createdEnvironment;
160
- let environmentId;
161
- let artifact;
162
- let activeLink;
163
- let startPromise;
164
- let executeStarted = false;
165
- let readyResolve;
105
+ let resolveReady;
166
106
  const ready = new Promise((resolve) => {
167
- readyResolve = resolve;
107
+ resolveReady = resolve;
168
108
  });
169
- const stopOperations = /* @__PURE__ */ new Map();
170
- const memoryAdmissions = /* @__PURE__ */ new Map();
171
- let teardownComplete = false;
172
- let teardownPromise;
173
- let flushChain = Promise.resolve();
174
- let controlError;
175
- const executor = {
109
+ const run = {
110
+ input,
111
+ attemptId,
112
+ localController: new AbortController(),
113
+ inbox: createInbox(),
114
+ planned: plannedDeclarationOf(input),
115
+ stopOperations: /* @__PURE__ */ new Map(),
116
+ memoryAdmissions: /* @__PURE__ */ new Map(),
117
+ ready,
118
+ resolveReady,
119
+ executor: void 0,
120
+ handle: void 0,
121
+ createdEnvironment: void 0,
122
+ environmentId: void 0,
123
+ artifact: void 0,
124
+ activeLink: void 0,
125
+ startPromise: void 0,
126
+ executeStarted: false,
127
+ teardownComplete: false,
128
+ teardownPromise: void 0,
129
+ flushChain: Promise.resolve(),
130
+ controlError: void 0
131
+ };
132
+ run.executor = interactiveSurface(run);
133
+ attestRuntimeOwnedPendingExecutor(run.executor, input.runtime, run.planned, {
134
+ attemptId,
135
+ binding: {
136
+ provider: input.provider.name,
137
+ environmentIdempotencyKey: input.environmentKey,
138
+ nodeId: input.nodeId ?? null
139
+ },
140
+ descriptor: descriptorOf(input)
141
+ });
142
+ return run.executor;
143
+ }
144
+ function interactiveSurface(run) {
145
+ const { input } = run;
146
+ return {
176
147
  runtime: input.runtime,
177
148
  teardownTimeoutMs: INTERACTIVE_TEARDOWN_TIMEOUT_MS,
178
149
  execute(task, signal) {
179
- if (executeStarted || teardownComplete || teardownPromise !== void 0) throw new Error("workerFromInteractiveProvider: execute() may only be called once");
180
- executeStarted = true;
181
- startPromise = startInteractive(task, signal);
182
- return failPendingAfter(inbox, runInteractive(signal));
150
+ if (run.executeStarted || run.teardownComplete || run.teardownPromise !== void 0) throw new Error("workerFromInteractiveProvider: execute() may only be called once");
151
+ run.executeStarted = true;
152
+ run.startPromise = startInteractive(run, task, signal);
153
+ return failPendingAfter(run.inbox, runInteractive(run, signal));
183
154
  },
184
155
  deliver(message) {
185
- if (teardownComplete || teardownPromise !== void 0) return false;
186
- const accepted = inbox.deliver(message);
187
- if (accepted) flushInbox();
156
+ if (run.teardownComplete || run.teardownPromise !== void 0) return false;
157
+ const accepted = run.inbox.deliver(message);
158
+ if (accepted) flushInbox(run);
188
159
  return accepted;
189
160
  },
190
161
  interactive() {
191
- return handle ? {
162
+ return run.handle ? {
192
163
  status: "available",
193
- handle
164
+ handle: run.handle
194
165
  } : {
195
166
  status: "unavailable",
196
167
  reason: "interactive-session-not-started"
197
168
  };
198
169
  },
199
170
  interactiveReady() {
200
- return ready;
171
+ return run.ready;
201
172
  },
202
173
  async cancel(request) {
203
- const existing = stopOperations.get(request.operationId);
174
+ const existing = run.stopOperations.get(request.operationId);
204
175
  if (existing) return existing;
205
- const tracked = stopInteractive(request.operationId, request.reason, request.signal).then((result) => {
206
- if (result.status === "unknown" && stopOperations.get(request.operationId) === tracked) stopOperations.delete(request.operationId);
176
+ const tracked = stopInteractive(run, request.operationId, request.reason, request.signal).then((result) => {
177
+ if (result.status === "unknown" && run.stopOperations.get(request.operationId) === tracked) run.stopOperations.delete(request.operationId);
207
178
  return result;
208
179
  });
209
- stopOperations.set(request.operationId, tracked);
180
+ run.stopOperations.set(request.operationId, tracked);
210
181
  return tracked;
211
182
  },
212
183
  teardown(grace) {
213
- if (teardownComplete) return Promise.resolve({ destroyed: true });
214
- if (teardownPromise !== void 0) return teardownPromise;
215
- teardownPromise = teardownInteractive().then((result) => {
216
- teardownComplete = true;
184
+ if (run.teardownComplete) return Promise.resolve({ destroyed: true });
185
+ if (run.teardownPromise !== void 0) return run.teardownPromise;
186
+ run.teardownPromise = teardownInteractive(run).then((result) => {
187
+ run.teardownComplete = true;
217
188
  return result;
218
189
  }, (error) => {
219
- teardownPromise = void 0;
190
+ run.teardownPromise = void 0;
220
191
  throw error;
221
192
  });
222
- return teardownPromise;
193
+ return run.teardownPromise;
223
194
  },
224
195
  heldEnvironments() {
225
- if (teardownComplete || input.destroyEnvironmentOnTeardown === false) return [];
226
- const held = createdEnvironment?.id ?? environmentId ?? handle?.ref.run.environmentId;
196
+ if (run.teardownComplete || input.destroyEnvironmentOnTeardown === false) return [];
197
+ const held = run.createdEnvironment?.id ?? run.environmentId ?? run.handle?.ref.run.environmentId;
227
198
  return held === void 0 ? [] : [{
228
199
  provider: input.provider.name,
229
200
  environmentId: held
230
201
  }];
231
202
  },
232
203
  resultArtifact() {
233
- if (!artifact) throw new Error("workerFromInteractiveProvider: resultArtifact() read before execution settled");
234
- return artifact;
204
+ if (!run.artifact) throw new Error("workerFromInteractiveProvider: resultArtifact() read before execution settled");
205
+ return run.artifact;
235
206
  }
236
207
  };
237
- const declaredEnvironment = input.environment ? retainedCreateMaterial({
238
- ...input.environment,
208
+ }
209
+ function initialPromptFor(input, task) {
210
+ const initialPrompt = typeof input.initialPrompt === "function" ? input.initialPrompt(task, {
211
+ provider: input.provider.name,
239
212
  profile: input.profile,
240
- idempotencyKey: input.environmentKey
241
- }) : null;
242
- const profileModel = concreteProfileModel(input.profile);
243
- const plannedDeclaration = {
244
- effectiveProfile: input.profile,
245
- backend: input.provider.name,
246
- model: profileModel ? {
247
- status: "known",
248
- id: profileModel
249
- } : {
250
- status: "unknown",
251
- reason: "provider selected the model"
252
- },
253
- execution: {
254
- kind: "interactive-session",
255
- id: input.nodeId ?? input.environmentKey
256
- },
257
- materializer: "retained-interactive-provider",
258
- plan: {
259
- kind: "retained-interactive-provider",
260
- provider: input.provider.name,
261
- environment: declaredEnvironment,
262
- environmentIdempotencyKey: input.environmentKey,
263
- destroyEnvironmentOnTeardown: input.destroyEnvironmentOnTeardown !== false
264
- }
265
- };
266
- attestRuntimeOwnedPendingExecutor(executor, input.runtime, plannedDeclaration, {
267
- attemptId,
268
- binding: {
269
- provider: input.provider.name,
270
- environmentIdempotencyKey: input.environmentKey,
271
- nodeId: input.nodeId ?? null
272
- },
273
- descriptor: {
274
- kind: "interactive-session",
275
- provider: input.provider.name,
276
- transport: "agent-environment"
277
- }
278
- });
279
- async function startInteractive(task, signal) {
280
- try {
281
- activeLink = linkAbort(signal, localController.signal);
282
- const initialPrompt = typeof input.initialPrompt === "function" ? input.initialPrompt(task, {
283
- provider: input.provider.name,
284
- profile: input.profile,
285
- ...input.context === void 0 ? {} : { context: input.context },
286
- task,
287
- ...input.nodeId === void 0 ? {} : { nodeId: input.nodeId }
288
- }) : input.initialPrompt ?? taskToPrompt(task);
289
- if (typeof initialPrompt !== "string") throw new Error("workerFromInteractiveProvider: initialPrompt must return a string");
290
- const interactiveIdempotencyKey = input.interactiveKey(task);
291
- const started = await startRetainedInteractiveRun({
292
- provider: {
293
- ...input.provider,
294
- async create(environmentInput) {
295
- const environment = await input.provider.create(environmentInput);
296
- createdEnvironment = environment;
297
- return environment;
298
- }
299
- },
300
- environment: {
301
- ...input.environment ?? {},
302
- profile: input.profile,
303
- idempotencyKey: input.environmentKey
304
- },
305
- interactiveIdempotencyKey,
306
- ...initialPrompt.length === 0 ? {} : { initialPrompt },
307
- ...input.cwd === void 0 ? {} : { cwd: input.cwd },
308
- ...input.cols === void 0 ? {} : { cols: input.cols },
309
- ...input.rows === void 0 ? {} : { rows: input.rows },
310
- onAdmission: async (admission) => {
311
- environmentId = admission.phase === "interactive_environment" ? admission.environmentId : environmentId;
312
- const existing = memoryAdmissions.get(admission.phase);
313
- if (existing !== void 0) {
314
- if (canonicalCandidateDigest(existing) !== canonicalCandidateDigest(admission)) throw new Error(`interactive admission phase '${admission.phase}' changed across retry`);
315
- } else memoryAdmissions.set(admission.phase, detachedSnapshot(admission, "interactive admission"));
316
- await input.admission(admission);
317
- },
318
- signal: activeLink.signal
319
- });
320
- finalizeRuntimeOwnedPendingExecutor(executor, {
321
- ...plannedDeclaration,
322
- execution: {
323
- kind: "interactive-session",
324
- id: started.ref.run.executionId
325
- },
326
- plan: {
327
- ...plannedDeclaration.plan,
328
- environmentId: started.ref.run.environmentId,
329
- interactiveIdempotencyKey
330
- }
331
- }, {
332
- attemptId,
333
- binding: {
334
- provider: input.provider.name,
335
- ref: started.ref,
336
- environmentId: started.ref.run.environmentId
337
- },
338
- descriptor: {
339
- kind: "interactive-session",
340
- provider: input.provider.name,
341
- transport: "agent-environment"
213
+ ...input.context === void 0 ? {} : { context: input.context },
214
+ task,
215
+ ...input.nodeId === void 0 ? {} : { nodeId: input.nodeId }
216
+ }) : input.initialPrompt ?? taskToPrompt(task);
217
+ if (typeof initialPrompt !== "string") throw new Error("workerFromInteractiveProvider: initialPrompt must return a string");
218
+ return initialPrompt;
219
+ }
220
+ /** Keep each admission phase's first snapshot in memory and refuse a retry that changes it. */
221
+ async function recordAdmission(run, admission) {
222
+ run.environmentId = admission.phase === "interactive_environment" ? admission.environmentId : run.environmentId;
223
+ const existing = run.memoryAdmissions.get(admission.phase);
224
+ if (existing !== void 0) {
225
+ if (canonicalCandidateDigest(existing) !== canonicalCandidateDigest(admission)) throw new Error(`interactive admission phase '${admission.phase}' changed across retry`);
226
+ } else run.memoryAdmissions.set(admission.phase, detachedSnapshot(admission, "interactive admission"));
227
+ await run.input.admission(admission);
228
+ }
229
+ async function startInteractive(run, task, signal) {
230
+ const { input } = run;
231
+ try {
232
+ run.activeLink = linkAbort(signal, run.localController.signal);
233
+ const initialPrompt = initialPromptFor(input, task);
234
+ const interactiveIdempotencyKey = input.interactiveKey(task);
235
+ const started = await startRetainedInteractiveRun({
236
+ provider: {
237
+ ...input.provider,
238
+ async create(environmentInput) {
239
+ const environment = await input.provider.create(environmentInput);
240
+ run.createdEnvironment = environment;
241
+ return environment;
342
242
  }
343
- });
344
- handle = started;
345
- readyResolve({
346
- status: "available",
347
- handle: started
348
- });
349
- flushInbox();
350
- return started;
351
- } catch (error) {
352
- readyResolve({
353
- status: "unavailable",
354
- reason: unavailableReason(error)
355
- });
356
- activeLink?.release();
357
- throw error;
358
- }
359
- }
360
- async function* runInteractive(signal) {
361
- const startedAt = Date.now();
362
- try {
363
- const current = await startPromise;
364
- if (current === void 0) throw new Error("workerFromInteractiveProvider: interactive start did not begin");
365
- yield { kind: "iteration" };
366
- yield {
367
- kind: "tokens",
368
- input: 0,
369
- output: 0,
370
- tokensKnown: false
371
- };
372
- yield {
373
- kind: "cost",
374
- usd: 0,
375
- usdKnown: false,
376
- provenance: "uncaptured"
377
- };
378
- let status;
379
- for (;;) {
380
- if (signal.aborted || localController.signal.aborted) throw signalAbortError(signal.aborted ? signal : localController.signal, "interactive execution aborted");
381
- status = await current.status({ signal: activeLink?.signal });
382
- await flushChain;
383
- if (controlError !== void 0) throw controlErrorValue(controlError);
384
- if (status.state !== "running") break;
385
- await sleep(input.pollIntervalMs ?? 100, activeLink?.signal);
243
+ },
244
+ environment: {
245
+ ...input.environment ?? {},
246
+ profile: input.profile,
247
+ idempotencyKey: input.environmentKey
248
+ },
249
+ interactiveIdempotencyKey,
250
+ ...initialPrompt.length === 0 ? {} : { initialPrompt },
251
+ ...input.cwd === void 0 ? {} : { cwd: input.cwd },
252
+ ...input.cols === void 0 ? {} : { cols: input.cols },
253
+ ...input.rows === void 0 ? {} : { rows: input.rows },
254
+ onAdmission: (admission) => recordAdmission(run, admission),
255
+ signal: run.activeLink.signal
256
+ });
257
+ finalizeRuntimeOwnedPendingExecutor(run.executor, {
258
+ ...run.planned,
259
+ execution: {
260
+ kind: "interactive-session",
261
+ id: started.ref.run.executionId
262
+ },
263
+ plan: {
264
+ ...run.planned.plan,
265
+ environmentId: started.ref.run.environmentId,
266
+ interactiveIdempotencyKey
386
267
  }
387
- const finished = status;
388
- const output = {
268
+ }, {
269
+ attemptId: run.attemptId,
270
+ binding: {
389
271
  provider: input.provider.name,
390
- environmentId: current.ref.run.environmentId,
391
- sessionId: current.ref.run.sessionId,
392
- executionId: current.ref.run.executionId,
393
- state: finished?.state === "exited" ? "exited" : "unknown",
394
- ref: current.ref,
395
- ...finished?.state === "exited" && finished.reason ? { reason: finished.reason } : {},
396
- ...finished?.state === "exited" && finished.exitCode !== void 0 ? { exitCode: finished.exitCode } : {},
397
- ...finished?.state === "exited" && finished.exitSignal !== void 0 ? { exitSignal: finished.exitSignal } : {}
398
- };
399
- const spent = {
400
- iterations: 1,
401
- tokens: {
402
- input: 0,
403
- output: 0
404
- },
405
- tokensKnown: false,
406
- usd: 0,
407
- usdKnown: false,
408
- ms: Date.now() - startedAt
409
- };
410
- artifact = {
411
- outRef: contentAddress(output),
412
- out: output,
413
- spent
414
- };
415
- } finally {
416
- activeLink?.release();
417
- }
418
- }
419
- async function flushInbox() {
420
- flushChain = flushChain.then(async () => {
421
- if (!handle) return;
422
- const lease = inbox.take();
423
- try {
424
- const messages = lease.messages;
425
- if (messages.length === 0) return;
426
- const prompt = inbox.fold(messages);
427
- const operationId = `interactive-prompt-${canonicalCandidateDigest({
428
- ref: handle.ref,
429
- prompt
430
- }).slice(7)}`;
431
- const control = await claimRetainedInteractiveControl({
432
- handle,
433
- holderId: input.holderId(void 0)
434
- });
435
- const material = {
436
- operationId,
437
- ref: handle.ref,
438
- control,
439
- prompt
440
- };
441
- const command = {
442
- ...material,
443
- requestDigest: agentInteractiveSessionPromptRequestDigest(material)
444
- };
445
- await handle.sendPrompt(command);
446
- for (const message of messages) lease.commit(operationId, message.id);
447
- } catch (error) {
448
- lease.release();
449
- controlError ??= error;
450
- }
272
+ ref: started.ref,
273
+ environmentId: started.ref.run.environmentId
274
+ },
275
+ descriptor: descriptorOf(input)
276
+ });
277
+ run.handle = started;
278
+ run.resolveReady({
279
+ status: "available",
280
+ handle: started
451
281
  });
452
- await flushChain;
282
+ flushInbox(run);
283
+ return started;
284
+ } catch (error) {
285
+ run.resolveReady({
286
+ status: "unavailable",
287
+ reason: unavailableReason(error)
288
+ });
289
+ run.activeLink?.release();
290
+ throw error;
453
291
  }
454
- async function stopInteractive(operationId, reason, signal) {
455
- const observedAt = (/* @__PURE__ */ new Date()).toISOString();
456
- if (!handle) {
457
- localController.abort(reason ?? "interactive cancellation requested");
458
- return {
459
- status: "unknown",
460
- effect: "cancel_requested",
461
- observedAt,
462
- detail: "interactive process has not published a provider reference"
463
- };
292
+ }
293
+ async function* runInteractive(run, signal) {
294
+ const { input, localController } = run;
295
+ const startedAt = Date.now();
296
+ try {
297
+ const current = await run.startPromise;
298
+ if (current === void 0) throw new Error("workerFromInteractiveProvider: interactive start did not begin");
299
+ yield { kind: "iteration" };
300
+ yield {
301
+ kind: "tokens",
302
+ input: 0,
303
+ output: 0,
304
+ tokensKnown: false
305
+ };
306
+ yield {
307
+ kind: "cost",
308
+ usd: 0,
309
+ usdKnown: false,
310
+ provenance: "uncaptured"
311
+ };
312
+ let status;
313
+ for (;;) {
314
+ if (signal.aborted || localController.signal.aborted) throw signalAbortError(signal.aborted ? signal : localController.signal, "interactive execution aborted");
315
+ status = await current.status({ signal: run.activeLink?.signal });
316
+ await run.flushChain;
317
+ if (run.controlError !== void 0) throw controlErrorValue(run.controlError);
318
+ if (status.state !== "running") break;
319
+ await sleep(input.pollIntervalMs ?? 100, run.activeLink?.signal);
464
320
  }
321
+ const finished = status;
322
+ const output = {
323
+ provider: input.provider.name,
324
+ environmentId: current.ref.run.environmentId,
325
+ sessionId: current.ref.run.sessionId,
326
+ executionId: current.ref.run.executionId,
327
+ state: finished?.state === "exited" ? "exited" : "unknown",
328
+ ref: current.ref,
329
+ ...finished?.state === "exited" && finished.reason ? { reason: finished.reason } : {},
330
+ ...finished?.state === "exited" && finished.exitCode !== void 0 ? { exitCode: finished.exitCode } : {},
331
+ ...finished?.state === "exited" && finished.exitSignal !== void 0 ? { exitSignal: finished.exitSignal } : {}
332
+ };
333
+ const spent = {
334
+ iterations: 1,
335
+ tokens: {
336
+ input: 0,
337
+ output: 0
338
+ },
339
+ tokensKnown: false,
340
+ usd: 0,
341
+ usdKnown: false,
342
+ ms: Date.now() - startedAt
343
+ };
344
+ run.artifact = {
345
+ outRef: contentAddress(output),
346
+ out: output,
347
+ spent
348
+ };
349
+ } finally {
350
+ run.activeLink?.release();
351
+ }
352
+ }
353
+ async function flushInbox(run) {
354
+ run.flushChain = run.flushChain.then(async () => {
355
+ const handle = run.handle;
356
+ if (!handle) return;
357
+ const lease = run.inbox.take();
465
358
  try {
359
+ const messages = lease.messages;
360
+ if (messages.length === 0) return;
361
+ const prompt = run.inbox.fold(messages);
362
+ const operationId = `interactive-prompt-${canonicalCandidateDigest({
363
+ ref: handle.ref,
364
+ prompt
365
+ }).slice(7)}`;
466
366
  const control = await claimRetainedInteractiveControl({
467
367
  handle,
468
- holderId: input.holderId(void 0),
469
- signal
368
+ holderId: run.input.holderId(void 0)
470
369
  });
471
370
  const material = {
472
371
  operationId,
473
372
  ref: handle.ref,
474
- control
373
+ control,
374
+ prompt
475
375
  };
476
376
  const command = {
477
377
  ...material,
478
- requestDigest: agentInteractiveSessionStopRequestDigest(material)
378
+ requestDigest: agentInteractiveSessionPromptRequestDigest(material)
479
379
  };
480
- const acknowledgement = await handle.stop(command, signal === void 0 ? void 0 : { signal });
481
- localController.abort(reason ?? "interactive cancellation requested");
482
- return cancellationFromAcknowledgement(acknowledgement, observedAt);
380
+ await handle.sendPrompt(command);
381
+ for (const message of messages) lease.commit(operationId, message.id);
483
382
  } catch (error) {
484
- localController.abort(reason ?? "interactive cancellation requested");
485
- return {
486
- status: "unknown",
487
- effect: "cancel_requested",
488
- observedAt,
489
- detail: error instanceof Error ? error.message : String(error),
490
- evidence: { operationId }
491
- };
492
- }
493
- }
494
- async function teardownInteractive() {
495
- localController.abort("interactive worker teardown");
496
- activeLink?.release();
497
- await startPromise?.catch(() => void 0);
498
- if (handle) {
499
- if ((await safeStatus(handle))?.state === "running") {
500
- const cancellation = await stopInteractive(`interactive-teardown-${canonicalCandidateDigest(handle.ref).slice(7)}`, "interactive worker teardown");
501
- if (cancellation.status === "rejected" || cancellation.status === "unknown") throw new Error(cancellation.detail ?? "interactive teardown was not acknowledged");
502
- }
383
+ lease.release();
384
+ run.controlError ??= error;
503
385
  }
504
- await destroyEnvironment();
505
- return { destroyed: true };
386
+ });
387
+ await run.flushChain;
388
+ }
389
+ async function stopInteractive(run, operationId, reason, signal) {
390
+ const observedAt = (/* @__PURE__ */ new Date()).toISOString();
391
+ const handle = run.handle;
392
+ if (!handle) {
393
+ run.localController.abort(reason ?? "interactive cancellation requested");
394
+ return {
395
+ status: "unknown",
396
+ effect: "cancel_requested",
397
+ observedAt,
398
+ detail: "interactive process has not published a provider reference"
399
+ };
506
400
  }
507
- async function destroyEnvironment() {
508
- if (input.destroyEnvironmentOnTeardown === false) return;
509
- if (createdEnvironment !== void 0) {
510
- await destroyConfirmed(createdEnvironment);
511
- return;
512
- }
513
- if (!input.provider.get) return;
514
- const cleanupEnvironmentId = environmentId ?? handle?.ref.run.environmentId;
515
- if (!cleanupEnvironmentId) return;
516
- const environment = await input.provider.get(cleanupEnvironmentId);
517
- if (environment !== void 0 && environment !== null) await destroyConfirmed(environment);
401
+ try {
402
+ const control = await claimRetainedInteractiveControl({
403
+ handle,
404
+ holderId: run.input.holderId(void 0),
405
+ signal
406
+ });
407
+ const material = {
408
+ operationId,
409
+ ref: handle.ref,
410
+ control
411
+ };
412
+ const command = {
413
+ ...material,
414
+ requestDigest: agentInteractiveSessionStopRequestDigest(material)
415
+ };
416
+ const acknowledgement = await handle.stop(command, signal === void 0 ? void 0 : { signal });
417
+ run.localController.abort(reason ?? "interactive cancellation requested");
418
+ return cancellationFromAcknowledgement(acknowledgement, observedAt);
419
+ } catch (error) {
420
+ run.localController.abort(reason ?? "interactive cancellation requested");
421
+ return {
422
+ status: "unknown",
423
+ effect: "cancel_requested",
424
+ observedAt,
425
+ detail: error instanceof Error ? error.message : String(error),
426
+ evidence: { operationId }
427
+ };
518
428
  }
519
- async function destroyConfirmed(environment) {
520
- try {
521
- await destroyInteractiveEnvironment(environment);
522
- } catch (error) {
523
- if (!await environmentGone(input.provider, environment.id)) throw error;
429
+ }
430
+ async function teardownInteractive(run) {
431
+ run.localController.abort("interactive worker teardown");
432
+ run.activeLink?.release();
433
+ await run.startPromise?.catch(() => void 0);
434
+ if (run.handle) {
435
+ if ((await safeStatus(run.handle))?.state === "running") {
436
+ const cancellation = await stopInteractive(run, `interactive-teardown-${canonicalCandidateDigest(run.handle.ref).slice(7)}`, "interactive worker teardown");
437
+ if (cancellation.status === "rejected" || cancellation.status === "unknown") throw new Error(cancellation.detail ?? "interactive teardown was not acknowledged");
524
438
  }
525
439
  }
526
- return executor;
440
+ await destroyEnvironment(run);
441
+ return { destroyed: true };
527
442
  }
528
- function admissionWriter(ctx, provider, workerId) {
529
- const candidate = ctx.seams[interactiveAdmissionSeamKey];
530
- if (typeof candidate === "function") return async (admission) => {
531
- await candidate(admission);
532
- };
533
- const records = /* @__PURE__ */ new Map();
534
- return async (admission) => {
535
- const prior = records.get(admission.phase);
536
- if (prior && canonicalCandidateDigest(prior) !== canonicalCandidateDigest(admission)) throw new Error(`worker ${workerId ?? "(unscoped)"} provider ${provider} admission changed in memory`);
537
- records.set(admission.phase, detachedSnapshot(admission, "interactive admission"));
538
- };
539
- }
540
- function derivedKey(kind, value) {
541
- return `${kind}-${canonicalCandidateDigest(value).slice(7)}`;
443
+ async function destroyEnvironment(run) {
444
+ const { input } = run;
445
+ if (input.destroyEnvironmentOnTeardown === false) return;
446
+ if (run.createdEnvironment !== void 0) {
447
+ await destroyConfirmed(input.provider, run.createdEnvironment);
448
+ return;
449
+ }
450
+ if (!input.provider.get) return;
451
+ const cleanupEnvironmentId = run.environmentId ?? run.handle?.ref.run.environmentId;
452
+ if (!cleanupEnvironmentId) return;
453
+ const environment = await input.provider.get(cleanupEnvironmentId);
454
+ if (environment !== void 0 && environment !== null) await destroyConfirmed(input.provider, environment);
542
455
  }
543
- function stableKey(value, label) {
544
- if (typeof value !== "string" || value.trim().length === 0) throw new Error(`${label} must be a non-empty string`);
545
- const key = value.trim();
546
- if (key.length > 256) throw new Error(`${label} must not exceed 256 bytes`);
547
- return key;
456
+ async function destroyConfirmed(provider, environment) {
457
+ try {
458
+ await destroyInteractiveEnvironment(environment);
459
+ } catch (error) {
460
+ if (!await environmentGone(provider, environment.id)) throw error;
461
+ }
548
462
  }
549
463
  function unavailableReason(error) {
550
464
  const message = error instanceof Error ? error.message : String(error);
@@ -582,6 +496,117 @@ async function safeStatus(handle) {
582
496
  }
583
497
  }
584
498
  //#endregion
499
+ //#region src/runtime/supervise/interactive-worker.ts
500
+ /**
501
+ * Runtime-owned worker seam for a provider's native interactive coding-agent process. It composes
502
+ * the retained-interactive lifecycle, adding no second stream, replay buffer, session id or
503
+ * cancellation protocol: the provider owns process state; Scope owns the worker, journal, budget
504
+ * and local control inbox.
505
+ */
506
+ /**
507
+ * Build a `MakeWorkerAgent` that starts one provider-owned native TUI per worker. A Scope supplies
508
+ * the durable admission hook and node attempt; the worker exposes `interactiveReady`, so the exact
509
+ * provider reference is written before another process can attach, and `attachWorker` reconnects
510
+ * it through the provider's public `get`/interactive contract.
511
+ */
512
+ function workerFromInteractiveProvider(provider, options = {}) {
513
+ if (!provider.name.trim()) throw new Error("workerFromInteractiveProvider: provider.name required");
514
+ if (!provider.get) throw new Error(`workerFromInteractiveProvider(${provider.name}): provider.get is required for reconnect`);
515
+ const capturedEnvironment = options.environment ? structuredClone(options.environment) : void 0;
516
+ const unscopedNamespace = randomUUID();
517
+ let unscopedOrdinal = 0;
518
+ const runtime = options.runtime ?? provider.name;
519
+ return (rawProfile, spawnContext) => {
520
+ const profile = executableAgentProfileSnapshot(rawProfile, `workerFromInteractiveProvider(${provider.name})`);
521
+ const input = {
522
+ provider: provider.name,
523
+ profile,
524
+ ...spawnContext === void 0 ? {} : { context: spawnContext }
525
+ };
526
+ const assignmentId = spawnContext?.assignmentId ?? `unscoped:${unscopedNamespace}:${unscopedOrdinal++}`;
527
+ const baseInput = {
528
+ ...input,
529
+ nodeId: spawnContext?.parentNodeId
530
+ };
531
+ const environmentKey = stableKey(options.environmentIdempotencyKey?.({ ...baseInput }) ?? derivedKey("supervised-interactive-environment", {
532
+ provider: provider.name,
533
+ assignmentId,
534
+ parentNodeId: spawnContext?.parentNodeId,
535
+ profile
536
+ }), "environment idempotency key");
537
+ const name = profile.name ?? "interactive-worker";
538
+ const executorFactory = (spec, ctx) => interactiveExecutor({
539
+ provider,
540
+ profile: spec.profile,
541
+ context: spawnContext,
542
+ environment: capturedEnvironment,
543
+ environmentKey,
544
+ interactiveKey: (task) => stableKey(options.interactiveIdempotencyKey?.({
545
+ ...baseInput,
546
+ task
547
+ }) ?? derivedKey("supervised-interactive-session", {
548
+ provider: provider.name,
549
+ assignmentId,
550
+ parentNodeId: spawnContext?.parentNodeId,
551
+ profile: spec.profile,
552
+ task
553
+ }), "interactive idempotency key"),
554
+ holderId: (task) => {
555
+ return stableKey((typeof options.holderId === "function" ? options.holderId({
556
+ ...baseInput,
557
+ task
558
+ }) : options.holderId) ?? `runtime-interactive-worker:${canonicalCandidateDigest({
559
+ provider: provider.name,
560
+ assignmentId
561
+ })}`, "interactive holder id");
562
+ },
563
+ initialPrompt: options.initialPrompt,
564
+ cwd: options.cwd,
565
+ cols: options.cols,
566
+ rows: options.rows,
567
+ runtime,
568
+ pollIntervalMs: options.pollIntervalMs,
569
+ destroyEnvironmentOnTeardown: options.destroyEnvironmentOnTeardown,
570
+ executionAttemptId: ctx.node?.attemptId,
571
+ nodeId: ctx.node?.nodeId,
572
+ admission: admissionWriter(ctx, provider.name, ctx.node?.nodeId)
573
+ });
574
+ return {
575
+ name,
576
+ act: async () => {
577
+ throw new Error("workerFromInteractiveProvider: interactive workers execute through executorSpec");
578
+ },
579
+ executorSpec: {
580
+ profile,
581
+ harness: null,
582
+ executorFactory,
583
+ ...spawnContext?.execution ? { execution: spawnContext.execution } : {}
584
+ }
585
+ };
586
+ };
587
+ }
588
+ function admissionWriter(ctx, provider, workerId) {
589
+ const candidate = ctx.seams[interactiveAdmissionSeamKey];
590
+ if (typeof candidate === "function") return async (admission) => {
591
+ await candidate(admission);
592
+ };
593
+ const records = /* @__PURE__ */ new Map();
594
+ return async (admission) => {
595
+ const prior = records.get(admission.phase);
596
+ if (prior && canonicalCandidateDigest(prior) !== canonicalCandidateDigest(admission)) throw new Error(`worker ${workerId ?? "(unscoped)"} provider ${provider} admission changed in memory`);
597
+ records.set(admission.phase, detachedSnapshot(admission, "interactive admission"));
598
+ };
599
+ }
600
+ function derivedKey(kind, value) {
601
+ return `${kind}-${canonicalCandidateDigest(value).slice(7)}`;
602
+ }
603
+ function stableKey(value, label) {
604
+ if (typeof value !== "string" || value.trim().length === 0) throw new Error(`${label} must be a non-empty string`);
605
+ const key = value.trim();
606
+ if (key.length > 256) throw new Error(`${label} must not exceed 256 bytes`);
607
+ return key;
608
+ }
609
+ //#endregion
585
610
  //#region src/runtime/supervise/provision-supervisor.ts
586
611
  /**
587
612
  * Public one-call composition for a durable Runtime supervisor proof run.
@@ -1002,4 +1027,4 @@ function writeState(path, state) {
1002
1027
  //#endregion
1003
1028
  export { workerFromInteractiveProvider as n, claimRetainedInteractiveControl as r, provisionSupervisor as t };
1004
1029
 
1005
- //# sourceMappingURL=provision-supervisor-DqvWXmAE.js.map
1030
+ //# sourceMappingURL=provision-supervisor-DL6gEMQp.js.map