@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.
- package/dist/{activation-D2PVljaw.js → activation-CWPmt0Do.js} +4 -4
- package/dist/{activation-D2PVljaw.js.map → activation-CWPmt0Do.js.map} +1 -1
- package/dist/{activation-DGDl4wwI.d.ts → activation-CXqtijue.d.ts} +2 -2
- package/dist/agent.d.ts +1 -1
- package/dist/agent.js +2 -2
- package/dist/{bundle-DNUq-OPW.js → bundle-Cwpit6Tg.js} +2 -2
- package/dist/{bundle-DNUq-OPW.js.map → bundle-Cwpit6Tg.js.map} +1 -1
- package/dist/candidate-execution/index.js +4 -4
- package/dist/{driver-control-acknowledgers-MTrs8HAF.js → coordination-manager-B5JsolDR.js} +4852 -4539
- package/dist/coordination-manager-B5JsolDR.js.map +1 -0
- package/dist/{delegate-CtJIS-tp.js → delegate-Rl-5paLJ.js} +2 -2
- package/dist/{delegate-CtJIS-tp.js.map → delegate-Rl-5paLJ.js.map} +1 -1
- package/dist/durable.d.ts +1 -1
- package/dist/durable.js +451 -358
- package/dist/durable.js.map +1 -1
- package/dist/{graph-DfWqp_1e.js → graph-Ce-59ZXn.js} +5 -5
- package/dist/{graph-DfWqp_1e.js.map → graph-Ce-59ZXn.js.map} +1 -1
- package/dist/{improve-CKRVQqzt.js → improve-BZXt2qM0.js} +837 -704
- package/dist/improve-BZXt2qM0.js.map +1 -0
- package/dist/index.d.ts +3 -3
- package/dist/index.js +9 -9
- package/dist/intelligence.d.ts +2 -2
- package/dist/intelligence.js +205 -191
- package/dist/intelligence.js.map +1 -1
- package/dist/kernel.d.ts +1 -1
- package/dist/kernel.js +9 -9
- package/dist/{loop-runner-DNWbTcVm.js → loop-runner-B0MV1-CD.js} +2 -2
- package/dist/{loop-runner-DNWbTcVm.js.map → loop-runner-B0MV1-CD.js.map} +1 -1
- package/dist/{loop-runner-C4EWEcXf.d.ts → loop-runner-CuhbgVGo.d.ts} +2 -2
- package/dist/loop-runner-bin.d.ts +1 -1
- package/dist/loop-runner-bin.js +1 -1
- package/dist/mcp/bin.js +3 -3
- package/dist/mcp/index.d.ts +1 -1
- package/dist/mcp/index.js +5 -5
- package/dist/{prepare-FzJoS68l.js → prepare-C-cWCyt3.js} +988 -735
- package/dist/prepare-C-cWCyt3.js.map +1 -0
- package/dist/{profile-DToH0XEs.js → profile-CbMw5hAn.js} +2 -2
- package/dist/{profile-DToH0XEs.js.map → profile-CbMw5hAn.js.map} +1 -1
- package/dist/profiles.d.ts +1 -1
- package/dist/{provision-supervisor-DqvWXmAE.js → provision-supervisor-DL6gEMQp.js} +444 -419
- package/dist/provision-supervisor-DL6gEMQp.js.map +1 -0
- package/dist/{runtime-C55Zgo1R.js → runtime-eghmj6W4.js} +1245 -1028
- package/dist/runtime-eghmj6W4.js.map +1 -0
- package/dist/{sandbox-profile-compat-DRr3JwDx.js → sandbox-profile-compat-FN2kab2-.js} +72 -72
- package/dist/{sandbox-profile-compat-DRr3JwDx.js.map → sandbox-profile-compat-FN2kab2-.js.map} +1 -1
- package/dist/{search-executor-ChOlRBgg.js → search-executor-rbjdZ3OD.js} +3 -3
- package/dist/{search-executor-ChOlRBgg.js.map → search-executor-rbjdZ3OD.js.map} +1 -1
- package/dist/{server-DkVBSN_S.js → server-BiK1Kcno.js} +4 -4
- package/dist/{server-DkVBSN_S.js.map → server-BiK1Kcno.js.map} +1 -1
- package/dist/{structural-rollout-C1LEk_zq.js → structural-rollout-BD9IN7K_.js} +3 -3
- package/dist/{structural-rollout-C1LEk_zq.js.map → structural-rollout-BD9IN7K_.js.map} +1 -1
- package/dist/{supervise-CaUAxZZP.js → supervise-DmOi7gll.js} +6346 -5447
- package/dist/supervise-DmOi7gll.js.map +1 -0
- package/dist/{supervisor-VXuN2OHT.js → supervisor-DUWcecAd.js} +13822 -12826
- package/dist/supervisor-DUWcecAd.js.map +1 -0
- package/dist/testing.d.ts +1 -1
- package/dist/testing.js +13 -13
- package/dist/tui/index.d.ts +1 -1
- package/dist/tui/index.js +1 -1
- package/dist/{types-DZ6L0Bv3.d.ts → types-Cgs89PQd.d.ts} +266 -356
- package/dist/workspace-store/index.js +273 -265
- package/dist/workspace-store/index.js.map +1 -1
- package/package.json +8 -8
- package/dist/driver-control-acknowledgers-MTrs8HAF.js.map +0 -1
- package/dist/improve-CKRVQqzt.js.map +0 -1
- package/dist/prepare-FzJoS68l.js.map +0 -1
- package/dist/provision-supervisor-DqvWXmAE.js.map +0 -1
- package/dist/runtime-C55Zgo1R.js.map +0 -1
- package/dist/supervise-CaUAxZZP.js.map +0 -1
- 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-
|
|
3
|
-
import { Ct as armDeadlineTimer, U as abortError, ot as sleep } from "./sandbox-profile-compat-
|
|
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,
|
|
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-
|
|
61
|
+
//#region src/runtime/supervise/interactive-executor.ts
|
|
62
62
|
/**
|
|
63
|
-
*
|
|
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
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
-
|
|
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
|
-
|
|
107
|
+
resolveReady = resolve;
|
|
168
108
|
});
|
|
169
|
-
const
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
-
|
|
238
|
-
|
|
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
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
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
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
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
|
-
|
|
388
|
-
|
|
268
|
+
}, {
|
|
269
|
+
attemptId: run.attemptId,
|
|
270
|
+
binding: {
|
|
389
271
|
provider: input.provider.name,
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
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
|
-
|
|
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
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
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:
|
|
378
|
+
requestDigest: agentInteractiveSessionPromptRequestDigest(material)
|
|
479
379
|
};
|
|
480
|
-
|
|
481
|
-
|
|
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
|
-
|
|
485
|
-
|
|
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
|
-
|
|
505
|
-
|
|
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
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
}
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
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
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
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
|
-
|
|
440
|
+
await destroyEnvironment(run);
|
|
441
|
+
return { destroyed: true };
|
|
527
442
|
}
|
|
528
|
-
function
|
|
529
|
-
const
|
|
530
|
-
if (
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
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
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
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-
|
|
1030
|
+
//# sourceMappingURL=provision-supervisor-DL6gEMQp.js.map
|