zeitlich 0.2.36 → 0.2.38
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/README.md +146 -92
- package/dist/{activities-BVI2lTwr.d.ts → activities-BKhMtKDd.d.ts} +4 -2
- package/dist/{activities-hd4aNnZE.d.cts → activities-CDcwkRZs.d.cts} +4 -2
- package/dist/adapters/sandbox/bedrock/index.cjs +17 -14
- package/dist/adapters/sandbox/bedrock/index.cjs.map +1 -1
- package/dist/adapters/sandbox/bedrock/index.d.cts +7 -6
- package/dist/adapters/sandbox/bedrock/index.d.ts +7 -6
- package/dist/adapters/sandbox/bedrock/index.js +17 -14
- package/dist/adapters/sandbox/bedrock/index.js.map +1 -1
- package/dist/adapters/sandbox/bedrock/workflow.cjs +2 -0
- package/dist/adapters/sandbox/bedrock/workflow.cjs.map +1 -1
- package/dist/adapters/sandbox/bedrock/workflow.d.cts +2 -2
- package/dist/adapters/sandbox/bedrock/workflow.d.ts +2 -2
- package/dist/adapters/sandbox/bedrock/workflow.js +2 -0
- package/dist/adapters/sandbox/bedrock/workflow.js.map +1 -1
- package/dist/adapters/sandbox/daytona/index.cjs +11 -3
- package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
- package/dist/adapters/sandbox/daytona/index.d.cts +5 -4
- package/dist/adapters/sandbox/daytona/index.d.ts +5 -4
- package/dist/adapters/sandbox/daytona/index.js +11 -3
- package/dist/adapters/sandbox/daytona/index.js.map +1 -1
- package/dist/adapters/sandbox/daytona/workflow.cjs +2 -0
- package/dist/adapters/sandbox/daytona/workflow.cjs.map +1 -1
- package/dist/adapters/sandbox/daytona/workflow.d.cts +1 -1
- package/dist/adapters/sandbox/daytona/workflow.d.ts +1 -1
- package/dist/adapters/sandbox/daytona/workflow.js +2 -0
- package/dist/adapters/sandbox/daytona/workflow.js.map +1 -1
- package/dist/adapters/sandbox/e2b/index.cjs +73 -12
- package/dist/adapters/sandbox/e2b/index.cjs.map +1 -1
- package/dist/adapters/sandbox/e2b/index.d.cts +26 -4
- package/dist/adapters/sandbox/e2b/index.d.ts +26 -4
- package/dist/adapters/sandbox/e2b/index.js +73 -12
- package/dist/adapters/sandbox/e2b/index.js.map +1 -1
- package/dist/adapters/sandbox/e2b/workflow.cjs +2 -0
- package/dist/adapters/sandbox/e2b/workflow.cjs.map +1 -1
- package/dist/adapters/sandbox/e2b/workflow.d.cts +1 -1
- package/dist/adapters/sandbox/e2b/workflow.d.ts +1 -1
- package/dist/adapters/sandbox/e2b/workflow.js +2 -0
- package/dist/adapters/sandbox/e2b/workflow.js.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.cjs +8 -3
- package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.d.cts +5 -4
- package/dist/adapters/sandbox/inmemory/index.d.ts +5 -4
- package/dist/adapters/sandbox/inmemory/index.js +8 -3
- package/dist/adapters/sandbox/inmemory/index.js.map +1 -1
- package/dist/adapters/sandbox/inmemory/workflow.cjs +2 -0
- package/dist/adapters/sandbox/inmemory/workflow.cjs.map +1 -1
- package/dist/adapters/sandbox/inmemory/workflow.d.cts +1 -1
- package/dist/adapters/sandbox/inmemory/workflow.d.ts +1 -1
- package/dist/adapters/sandbox/inmemory/workflow.js +2 -0
- package/dist/adapters/sandbox/inmemory/workflow.js.map +1 -1
- package/dist/adapters/thread/anthropic/index.cjs +94 -39
- package/dist/adapters/thread/anthropic/index.cjs.map +1 -1
- package/dist/adapters/thread/anthropic/index.d.cts +5 -5
- package/dist/adapters/thread/anthropic/index.d.ts +5 -5
- package/dist/adapters/thread/anthropic/index.js +94 -39
- package/dist/adapters/thread/anthropic/index.js.map +1 -1
- package/dist/adapters/thread/anthropic/workflow.cjs +7 -2
- package/dist/adapters/thread/anthropic/workflow.cjs.map +1 -1
- package/dist/adapters/thread/anthropic/workflow.d.cts +5 -5
- package/dist/adapters/thread/anthropic/workflow.d.ts +5 -5
- package/dist/adapters/thread/anthropic/workflow.js +7 -2
- package/dist/adapters/thread/anthropic/workflow.js.map +1 -1
- package/dist/adapters/thread/google-genai/index.cjs +77 -28
- package/dist/adapters/thread/google-genai/index.cjs.map +1 -1
- package/dist/adapters/thread/google-genai/index.d.cts +5 -5
- package/dist/adapters/thread/google-genai/index.d.ts +5 -5
- package/dist/adapters/thread/google-genai/index.js +77 -28
- package/dist/adapters/thread/google-genai/index.js.map +1 -1
- package/dist/adapters/thread/google-genai/workflow.cjs +7 -2
- package/dist/adapters/thread/google-genai/workflow.cjs.map +1 -1
- package/dist/adapters/thread/google-genai/workflow.d.cts +5 -5
- package/dist/adapters/thread/google-genai/workflow.d.ts +5 -5
- package/dist/adapters/thread/google-genai/workflow.js +7 -2
- package/dist/adapters/thread/google-genai/workflow.js.map +1 -1
- package/dist/adapters/thread/langchain/index.cjs +57 -10
- package/dist/adapters/thread/langchain/index.cjs.map +1 -1
- package/dist/adapters/thread/langchain/index.d.cts +5 -5
- package/dist/adapters/thread/langchain/index.d.ts +5 -5
- package/dist/adapters/thread/langchain/index.js +57 -10
- package/dist/adapters/thread/langchain/index.js.map +1 -1
- package/dist/adapters/thread/langchain/workflow.cjs +7 -2
- package/dist/adapters/thread/langchain/workflow.cjs.map +1 -1
- package/dist/adapters/thread/langchain/workflow.d.cts +5 -5
- package/dist/adapters/thread/langchain/workflow.d.ts +5 -5
- package/dist/adapters/thread/langchain/workflow.js +7 -2
- package/dist/adapters/thread/langchain/workflow.js.map +1 -1
- package/dist/index.cjs +322 -146
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -14
- package/dist/index.d.ts +20 -14
- package/dist/index.js +323 -147
- package/dist/index.js.map +1 -1
- package/dist/{proxy-BjdFGPTm.d.ts → proxy-CUlKSvZS.d.ts} +1 -1
- package/dist/{proxy-7RnVaPdJ.d.cts → proxy-D_3x7RN4.d.cts} +1 -1
- package/dist/{thread-manager-CbpiGq1L.d.ts → thread-manager-CVu7o2cs.d.ts} +4 -2
- package/dist/{thread-manager-DzXm9eeI.d.cts → thread-manager-HSwyh28L.d.cts} +4 -2
- package/dist/{thread-manager-BBzNgQWH.d.cts → thread-manager-c1gPopAG.d.ts} +4 -2
- package/dist/{thread-manager-DjN5JYul.d.ts → thread-manager-wGi-LqIP.d.cts} +4 -2
- package/dist/{types-Mc_4BCfT.d.cts → types-BH_IRryz.d.ts} +10 -1
- package/dist/{types-yiXmqedU.d.ts → types-BaOw4hKI.d.cts} +10 -1
- package/dist/{types-DQ1l_gXL.d.cts → types-C06FwR96.d.cts} +121 -17
- package/dist/{types-wiGLvxWf.d.ts → types-DAsQ21Rt.d.ts} +1 -1
- package/dist/{types-CADc5V_P.d.ts → types-DNr31FzL.d.ts} +121 -17
- package/dist/{types-CBH54cwr.d.cts → types-lm8tMNJQ.d.cts} +1 -1
- package/dist/{types-DxCpFNv_.d.cts → types-yx0LzPGn.d.cts} +44 -5
- package/dist/{types-DxCpFNv_.d.ts → types-yx0LzPGn.d.ts} +44 -5
- package/dist/{workflow-DhtWRovz.d.cts → workflow-CSCkpwAL.d.ts} +2 -2
- package/dist/{workflow-P2pTSfKu.d.ts → workflow-DuvMZ8Vm.d.cts} +2 -2
- package/dist/workflow.cjs +274 -130
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +3 -3
- package/dist/workflow.d.ts +3 -3
- package/dist/workflow.js +275 -131
- package/dist/workflow.js.map +1 -1
- package/package.json +2 -2
- package/src/adapters/sandbox/bedrock/filesystem.ts +6 -12
- package/src/adapters/sandbox/bedrock/index.ts +22 -11
- package/src/adapters/sandbox/bedrock/proxy.ts +2 -0
- package/src/adapters/sandbox/daytona/index.ts +18 -3
- package/src/adapters/sandbox/daytona/proxy.ts +2 -0
- package/src/adapters/sandbox/e2b/filesystem.ts +5 -4
- package/src/adapters/sandbox/e2b/index.ts +87 -14
- package/src/adapters/sandbox/e2b/proxy.ts +2 -0
- package/src/adapters/sandbox/e2b/types.ts +16 -0
- package/src/adapters/sandbox/inmemory/index.ts +17 -3
- package/src/adapters/sandbox/inmemory/proxy.ts +2 -0
- package/src/adapters/thread/anthropic/activities.ts +58 -26
- package/src/adapters/thread/anthropic/model-invoker.ts +18 -7
- package/src/adapters/thread/anthropic/proxy.ts +6 -2
- package/src/adapters/thread/anthropic/thread-manager.test.ts +26 -7
- package/src/adapters/thread/anthropic/thread-manager.ts +63 -46
- package/src/adapters/thread/google-genai/activities.ts +20 -2
- package/src/adapters/thread/google-genai/model-invoker.ts +27 -7
- package/src/adapters/thread/google-genai/proxy.ts +6 -2
- package/src/adapters/thread/google-genai/thread-manager.test.ts +13 -3
- package/src/adapters/thread/google-genai/thread-manager.ts +57 -33
- package/src/adapters/thread/langchain/activities.ts +55 -24
- package/src/adapters/thread/langchain/hooks.test.ts +36 -49
- package/src/adapters/thread/langchain/hooks.ts +18 -5
- package/src/adapters/thread/langchain/model-invoker.ts +5 -4
- package/src/adapters/thread/langchain/proxy.ts +6 -2
- package/src/adapters/thread/langchain/thread-manager.test.ts +5 -1
- package/src/adapters/thread/langchain/thread-manager.ts +23 -9
- package/src/index.ts +4 -1
- package/src/lib/activity.ts +16 -6
- package/src/lib/hooks/types.ts +6 -6
- package/src/lib/lifecycle.ts +18 -3
- package/src/lib/model/proxy.ts +2 -2
- package/src/lib/model/types.ts +10 -0
- package/src/lib/observability/hooks.ts +4 -5
- package/src/lib/observability/index.ts +1 -4
- package/src/lib/sandbox/manager.ts +45 -20
- package/src/lib/sandbox/node-fs.ts +3 -6
- package/src/lib/sandbox/sandbox.test.ts +36 -3
- package/src/lib/sandbox/tree.integration.test.ts +10 -3
- package/src/lib/sandbox/types.ts +60 -6
- package/src/lib/session/session-edge-cases.integration.test.ts +316 -14
- package/src/lib/session/session.integration.test.ts +161 -1
- package/src/lib/session/session.ts +106 -21
- package/src/lib/session/types.ts +25 -5
- package/src/lib/skills/fs-provider.ts +12 -8
- package/src/lib/skills/handler.ts +1 -1
- package/src/lib/skills/parse.ts +3 -1
- package/src/lib/skills/register.ts +1 -3
- package/src/lib/skills/skills.integration.test.ts +25 -15
- package/src/lib/state/manager.integration.test.ts +12 -2
- package/src/lib/subagent/define.ts +1 -1
- package/src/lib/subagent/handler.ts +186 -71
- package/src/lib/subagent/index.ts +1 -5
- package/src/lib/subagent/register.ts +3 -2
- package/src/lib/subagent/signals.ts +1 -10
- package/src/lib/subagent/subagent.integration.test.ts +526 -248
- package/src/lib/subagent/tool.ts +4 -3
- package/src/lib/subagent/types.ts +50 -20
- package/src/lib/subagent/workflow.ts +9 -49
- package/src/lib/thread/id.test.ts +1 -1
- package/src/lib/thread/id.ts +1 -2
- package/src/lib/thread/manager.ts +18 -0
- package/src/lib/thread/proxy.ts +4 -4
- package/src/lib/thread/types.ts +20 -3
- package/src/lib/tool-router/index.ts +3 -5
- package/src/lib/tool-router/router-edge-cases.integration.test.ts +93 -1
- package/src/lib/tool-router/router.integration.test.ts +12 -0
- package/src/lib/tool-router/router.ts +90 -16
- package/src/lib/tool-router/types.ts +45 -4
- package/src/lib/tool-router/with-sandbox.ts +19 -5
- package/src/lib/virtual-fs/filesystem.ts +1 -1
- package/src/lib/virtual-fs/index.ts +5 -1
- package/src/lib/virtual-fs/mutations.ts +2 -4
- package/src/lib/virtual-fs/queries.ts +9 -5
- package/src/lib/virtual-fs/types.ts +4 -1
- package/src/lib/virtual-fs/virtual-fs.test.ts +9 -11
- package/src/lib/workflow.test.ts +7 -4
- package/src/lib/workflow.ts +1 -5
- package/src/tools/ask-user-question/tool.ts +1 -3
- package/src/tools/glob/handler.ts +1 -4
- package/src/tools/task-get/handler.ts +4 -5
- package/src/tools/task-list/handler.ts +1 -4
- package/src/tools/task-update/handler.ts +4 -5
- package/src/workflow.ts +22 -7
- package/tsup.config.ts +9 -6
- package/src/lib/.env +0 -1
- package/src/tools/bash/.env +0 -1
package/dist/workflow.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineSignal, uuid4, setHandler, defineUpdate, ApplicationFailure, log, condition, defineQuery, proxySinks, workflowInfo, proxyActivities, getExternalWorkflowHandle,
|
|
1
|
+
import { defineSignal, CancellationScope, isCancellation, uuid4, setHandler, defineUpdate, ApplicationFailure, log, condition, defineQuery, proxySinks, workflowInfo, proxyActivities, getExternalWorkflowHandle, executeChild } from '@temporalio/workflow';
|
|
2
2
|
import z14, { z } from 'zod';
|
|
3
3
|
import { ApplicationFailure as ApplicationFailure$1 } from '@temporalio/common';
|
|
4
4
|
|
|
@@ -107,7 +107,7 @@ function createToolRouter(options) {
|
|
|
107
107
|
});
|
|
108
108
|
}
|
|
109
109
|
}
|
|
110
|
-
async function processToolCall(toolCall, turn, sandboxId) {
|
|
110
|
+
async function processToolCall(toolCall, turn, sandboxId, onRewindRequested) {
|
|
111
111
|
const startTime = Date.now();
|
|
112
112
|
const tool = toolMap.get(toolCall.name);
|
|
113
113
|
const preResult = await runPreHooks(toolCall, tool, turn);
|
|
@@ -122,7 +122,7 @@ function createToolRouter(options) {
|
|
|
122
122
|
reason: "Skipped by PreToolUse hook"
|
|
123
123
|
})
|
|
124
124
|
});
|
|
125
|
-
return
|
|
125
|
+
return { kind: "skipped" };
|
|
126
126
|
}
|
|
127
127
|
const effectiveArgs = preResult.args;
|
|
128
128
|
log.debug("tool call dispatched", {
|
|
@@ -134,6 +134,7 @@ function createToolRouter(options) {
|
|
|
134
134
|
let content;
|
|
135
135
|
let resultAppended = false;
|
|
136
136
|
let metadata;
|
|
137
|
+
let rewindRequested = false;
|
|
137
138
|
try {
|
|
138
139
|
if (tool) {
|
|
139
140
|
const routerContext = {
|
|
@@ -151,11 +152,15 @@ function createToolRouter(options) {
|
|
|
151
152
|
content = response.toolResponse;
|
|
152
153
|
resultAppended = response.resultAppended === true;
|
|
153
154
|
metadata = response.metadata;
|
|
155
|
+
rewindRequested = response.rewind === true;
|
|
154
156
|
} else {
|
|
155
157
|
result = { error: `Unknown tool: ${toolCall.name}` };
|
|
156
158
|
content = JSON.stringify(result, null, 2);
|
|
157
159
|
}
|
|
158
160
|
} catch (error) {
|
|
161
|
+
if (isCancellation(error)) {
|
|
162
|
+
throw error;
|
|
163
|
+
}
|
|
159
164
|
log.warn("tool call failed", {
|
|
160
165
|
toolName: toolCall.name,
|
|
161
166
|
toolCallId: toolCall.id,
|
|
@@ -173,6 +178,15 @@ function createToolRouter(options) {
|
|
|
173
178
|
result = recovery.result;
|
|
174
179
|
content = recovery.content;
|
|
175
180
|
}
|
|
181
|
+
if (rewindRequested) {
|
|
182
|
+
const signal = {
|
|
183
|
+
toolCallId: toolCall.id,
|
|
184
|
+
toolName: toolCall.name
|
|
185
|
+
};
|
|
186
|
+
log.info("tool requested rewind", { ...signal });
|
|
187
|
+
onRewindRequested?.(signal);
|
|
188
|
+
return { kind: "rewind", signal };
|
|
189
|
+
}
|
|
176
190
|
if (!resultAppended) {
|
|
177
191
|
const config = {
|
|
178
192
|
threadId: options.threadId,
|
|
@@ -209,7 +223,7 @@ function createToolRouter(options) {
|
|
|
209
223
|
turn,
|
|
210
224
|
durationMs
|
|
211
225
|
);
|
|
212
|
-
return toolResult;
|
|
226
|
+
return { kind: "result", value: toolResult };
|
|
213
227
|
}
|
|
214
228
|
return {
|
|
215
229
|
hasTools() {
|
|
@@ -244,27 +258,59 @@ function createToolRouter(options) {
|
|
|
244
258
|
}));
|
|
245
259
|
},
|
|
246
260
|
async processToolCalls(toolCalls, context) {
|
|
261
|
+
const attachRewind = (arr, rewind) => {
|
|
262
|
+
if (rewind) {
|
|
263
|
+
arr.rewind = rewind;
|
|
264
|
+
}
|
|
265
|
+
return arr;
|
|
266
|
+
};
|
|
247
267
|
if (toolCalls.length === 0) {
|
|
248
|
-
return [];
|
|
268
|
+
return attachRewind([], void 0);
|
|
249
269
|
}
|
|
250
270
|
const turn = context?.turn ?? 0;
|
|
251
271
|
const sandboxId = context?.sandboxId;
|
|
272
|
+
let rewindSignal;
|
|
252
273
|
if (options.parallel) {
|
|
253
|
-
const
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
274
|
+
const scope = new CancellationScope({ cancellable: true });
|
|
275
|
+
const onRewindRequested = (signal) => {
|
|
276
|
+
if (!rewindSignal) {
|
|
277
|
+
rewindSignal = signal;
|
|
278
|
+
scope.cancel();
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
const outcomes = await scope.run(
|
|
282
|
+
async () => Promise.allSettled(
|
|
283
|
+
toolCalls.map(
|
|
284
|
+
(tc) => processToolCall(tc, turn, sandboxId, onRewindRequested)
|
|
285
|
+
)
|
|
286
|
+
)
|
|
258
287
|
);
|
|
288
|
+
const results2 = [];
|
|
289
|
+
for (const outcome of outcomes) {
|
|
290
|
+
if (outcome.status === "rejected") {
|
|
291
|
+
if (isCancellation(outcome.reason)) {
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
294
|
+
throw outcome.reason;
|
|
295
|
+
}
|
|
296
|
+
if (outcome.value.kind === "result") {
|
|
297
|
+
results2.push(outcome.value.value);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return attachRewind(results2, rewindSignal);
|
|
259
301
|
}
|
|
260
302
|
const results = [];
|
|
261
303
|
for (const toolCall of toolCalls) {
|
|
262
|
-
const
|
|
263
|
-
if (
|
|
264
|
-
|
|
304
|
+
const outcome = await processToolCall(toolCall, turn, sandboxId);
|
|
305
|
+
if (outcome.kind === "rewind") {
|
|
306
|
+
rewindSignal = outcome.signal;
|
|
307
|
+
break;
|
|
308
|
+
}
|
|
309
|
+
if (outcome.kind === "result") {
|
|
310
|
+
results.push(outcome.value);
|
|
265
311
|
}
|
|
266
312
|
}
|
|
267
|
-
return results;
|
|
313
|
+
return attachRewind(results, rewindSignal);
|
|
268
314
|
},
|
|
269
315
|
async processToolCallsByName(toolCalls, toolName, handler, context) {
|
|
270
316
|
const matchingCalls = toolCalls.filter((tc) => tc.name === toolName);
|
|
@@ -385,9 +431,7 @@ function createSubagentTool(subagents) {
|
|
|
385
431
|
schema
|
|
386
432
|
};
|
|
387
433
|
}
|
|
388
|
-
var childResultSignal = defineSignal("childResult");
|
|
389
434
|
var childSandboxReadySignal = defineSignal("childSandboxReady");
|
|
390
|
-
var destroySandboxSignal = defineSignal("destroySandbox");
|
|
391
435
|
|
|
392
436
|
// src/lib/subagent/handler.ts
|
|
393
437
|
function resolveSandboxConfig(config) {
|
|
@@ -411,25 +455,27 @@ function resolveSandboxConfig(config) {
|
|
|
411
455
|
}
|
|
412
456
|
function createSubagentHandler(subagents) {
|
|
413
457
|
const { taskQueue: parentTaskQueue } = workflowInfo();
|
|
414
|
-
const
|
|
458
|
+
const agentSandboxOps = /* @__PURE__ */ new Map();
|
|
459
|
+
for (const cfg of subagents) {
|
|
460
|
+
if (cfg.sandbox && cfg.sandbox !== "none") {
|
|
461
|
+
agentSandboxOps.set(cfg.agentName, cfg.sandbox.proxy(cfg.agentName));
|
|
462
|
+
}
|
|
463
|
+
}
|
|
415
464
|
const pendingDestroys = /* @__PURE__ */ new Map();
|
|
416
465
|
const threadSandboxes = /* @__PURE__ */ new Map();
|
|
417
466
|
const persistentSandboxes = /* @__PURE__ */ new Map();
|
|
418
467
|
const persistentSandboxCreating = /* @__PURE__ */ new Set();
|
|
419
468
|
const lazyCreatorAgent = /* @__PURE__ */ new Map();
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
setHandler(
|
|
424
|
-
|
|
425
|
-
(
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
persistentSandboxes.set(agentName, sandboxId);
|
|
429
|
-
lazyCreatorAgent.delete(childWorkflowId);
|
|
430
|
-
}
|
|
469
|
+
const threadSnapshots = /* @__PURE__ */ new Map();
|
|
470
|
+
const persistentBaseSnapshot = /* @__PURE__ */ new Map();
|
|
471
|
+
const persistentBaseSnapshotCreating = /* @__PURE__ */ new Set();
|
|
472
|
+
setHandler(childSandboxReadySignal, ({ childWorkflowId, sandboxId }) => {
|
|
473
|
+
const agentName = lazyCreatorAgent.get(childWorkflowId);
|
|
474
|
+
if (agentName && !persistentSandboxes.has(agentName)) {
|
|
475
|
+
persistentSandboxes.set(agentName, sandboxId);
|
|
476
|
+
lazyCreatorAgent.delete(childWorkflowId);
|
|
431
477
|
}
|
|
432
|
-
);
|
|
478
|
+
});
|
|
433
479
|
const handler = async (args, context) => {
|
|
434
480
|
const config = subagents.find((s) => s.agentName === args.subagent);
|
|
435
481
|
if (!config) {
|
|
@@ -440,6 +486,12 @@ function createSubagentHandler(subagents) {
|
|
|
440
486
|
const childWorkflowId = `${args.subagent}-${getShortId()}`;
|
|
441
487
|
const { sandboxId: parentSandboxId } = context;
|
|
442
488
|
const sandboxCfg = resolveSandboxConfig(config.sandbox);
|
|
489
|
+
if (sandboxCfg.source !== "none" && !agentSandboxOps.has(config.agentName)) {
|
|
490
|
+
throw ApplicationFailure.create({
|
|
491
|
+
message: `Subagent "${config.agentName}" uses a sandbox but no \`sandbox.proxy\` is configured on its SubagentConfig`,
|
|
492
|
+
nonRetryable: true
|
|
493
|
+
});
|
|
494
|
+
}
|
|
443
495
|
if (sandboxCfg.source === "inherit" && !parentSandboxId) {
|
|
444
496
|
throw new Error(
|
|
445
497
|
`Subagent "${config.agentName}" is configured with sandbox: "inherit" but the parent has no sandbox`
|
|
@@ -458,12 +510,39 @@ function createSubagentHandler(subagents) {
|
|
|
458
510
|
let sandbox;
|
|
459
511
|
let sandboxShutdownOverride;
|
|
460
512
|
let isLazyCreator = false;
|
|
513
|
+
let isSnapshotBaseCreator = false;
|
|
461
514
|
if (sandboxCfg.source === "inherit" && parentSandboxId) {
|
|
462
515
|
if (sandboxCfg.continuation === "fork") {
|
|
463
516
|
sandbox = { mode: "fork", sandboxId: parentSandboxId };
|
|
517
|
+
} else if (sandboxCfg.continuation === "snapshot") {
|
|
518
|
+
throw new Error(
|
|
519
|
+
`Subagent "${config.agentName}" has sandbox source "inherit" with continuation "snapshot" \u2014 snapshot continuation is only supported for source "own"`
|
|
520
|
+
);
|
|
464
521
|
} else {
|
|
465
522
|
sandbox = { mode: "inherit", sandboxId: parentSandboxId };
|
|
466
523
|
}
|
|
524
|
+
} else if (sandboxCfg.source === "own" && sandboxCfg.continuation === "snapshot") {
|
|
525
|
+
const isLazy = sandboxCfg.init === "once";
|
|
526
|
+
let baseSnap;
|
|
527
|
+
if (continuationThreadId) {
|
|
528
|
+
baseSnap = threadSnapshots.get(continuationThreadId)?.snapshot;
|
|
529
|
+
}
|
|
530
|
+
if (!baseSnap && isLazy) {
|
|
531
|
+
baseSnap = persistentBaseSnapshot.get(config.agentName);
|
|
532
|
+
if (!baseSnap) {
|
|
533
|
+
if (persistentBaseSnapshotCreating.has(config.agentName)) {
|
|
534
|
+
await condition(() => persistentBaseSnapshot.has(config.agentName));
|
|
535
|
+
baseSnap = persistentBaseSnapshot.get(config.agentName);
|
|
536
|
+
} else {
|
|
537
|
+
persistentBaseSnapshotCreating.add(config.agentName);
|
|
538
|
+
isSnapshotBaseCreator = true;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
if (baseSnap) {
|
|
543
|
+
sandbox = { mode: "from-snapshot", snapshot: baseSnap };
|
|
544
|
+
}
|
|
545
|
+
sandboxShutdownOverride = "snapshot";
|
|
467
546
|
} else if (sandboxCfg.source === "own") {
|
|
468
547
|
const isLazy = sandboxCfg.init === "once";
|
|
469
548
|
let baseSandboxId;
|
|
@@ -514,31 +593,8 @@ function createSubagentHandler(subagents) {
|
|
|
514
593
|
threadMode,
|
|
515
594
|
sandboxSource: sandboxCfg.source
|
|
516
595
|
});
|
|
517
|
-
const
|
|
596
|
+
const childResult = await executeChild(config.workflow, childOpts);
|
|
518
597
|
const effectiveShutdown = sandboxShutdownOverride ?? sandboxCfg.shutdown ?? "destroy";
|
|
519
|
-
if (effectiveShutdown === "pause-until-parent-close" || effectiveShutdown === "keep-until-parent-close") {
|
|
520
|
-
const key = isLazyCreator ? `persistent:${config.agentName}` : childWorkflowId;
|
|
521
|
-
pendingDestroys.set(key, childHandle);
|
|
522
|
-
}
|
|
523
|
-
await Promise.race([
|
|
524
|
-
condition(() => childResults.has(childWorkflowId)),
|
|
525
|
-
childHandle.result()
|
|
526
|
-
]);
|
|
527
|
-
if (!childResults.has(childWorkflowId)) {
|
|
528
|
-
await condition(() => childResults.has(childWorkflowId));
|
|
529
|
-
}
|
|
530
|
-
const childResult = childResults.get(childWorkflowId);
|
|
531
|
-
childResults.delete(childWorkflowId);
|
|
532
|
-
if (!childResult) {
|
|
533
|
-
log.warn("subagent returned no result", {
|
|
534
|
-
subagent: config.agentName,
|
|
535
|
-
childWorkflowId
|
|
536
|
-
});
|
|
537
|
-
return {
|
|
538
|
-
toolResponse: "Subagent workflow did not signal a result",
|
|
539
|
-
data: null
|
|
540
|
-
};
|
|
541
|
-
}
|
|
542
598
|
log.info("subagent completed", {
|
|
543
599
|
subagent: config.agentName,
|
|
544
600
|
childWorkflowId,
|
|
@@ -550,19 +606,42 @@ function createSubagentHandler(subagents) {
|
|
|
550
606
|
usage,
|
|
551
607
|
threadId: childThreadId,
|
|
552
608
|
sandboxId: childSandboxId,
|
|
609
|
+
snapshot: childSnapshot,
|
|
610
|
+
baseSnapshot: childBaseSnapshot,
|
|
553
611
|
metadata
|
|
554
612
|
} = childResult;
|
|
555
613
|
if (childSandboxId) {
|
|
556
|
-
if (sandboxCfg.source === "own" && sandboxCfg.init === "once" && !persistentSandboxes.has(config.agentName)) {
|
|
614
|
+
if (sandboxCfg.source === "own" && sandboxCfg.init === "once" && sandboxCfg.continuation !== "snapshot" && !persistentSandboxes.has(config.agentName)) {
|
|
557
615
|
persistentSandboxes.set(config.agentName, childSandboxId);
|
|
558
|
-
} else if (allowsContinuation && childThreadId) {
|
|
616
|
+
} else if (allowsContinuation && childThreadId && sandboxCfg.source === "own" && sandboxCfg.continuation !== "snapshot") {
|
|
559
617
|
threadSandboxes.set(childThreadId, childSandboxId);
|
|
560
618
|
}
|
|
561
619
|
}
|
|
620
|
+
if (childSandboxId && (effectiveShutdown === "pause-until-parent-close" || effectiveShutdown === "keep-until-parent-close")) {
|
|
621
|
+
const key = isLazyCreator ? `persistent:${config.agentName}` : childWorkflowId;
|
|
622
|
+
pendingDestroys.set(key, {
|
|
623
|
+
agentName: config.agentName,
|
|
624
|
+
sandboxId: childSandboxId
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
if (sandboxCfg.source === "own" && sandboxCfg.continuation === "snapshot") {
|
|
628
|
+
if (childSnapshot && childThreadId) {
|
|
629
|
+
threadSnapshots.set(childThreadId, {
|
|
630
|
+
agentName: config.agentName,
|
|
631
|
+
snapshot: childSnapshot
|
|
632
|
+
});
|
|
633
|
+
}
|
|
634
|
+
if (isSnapshotBaseCreator && childBaseSnapshot && !persistentBaseSnapshot.has(config.agentName)) {
|
|
635
|
+
persistentBaseSnapshot.set(config.agentName, childBaseSnapshot);
|
|
636
|
+
}
|
|
637
|
+
}
|
|
562
638
|
if (isLazyCreator) {
|
|
563
639
|
persistentSandboxCreating.delete(config.agentName);
|
|
564
640
|
lazyCreatorAgent.delete(childWorkflowId);
|
|
565
641
|
}
|
|
642
|
+
if (isSnapshotBaseCreator) {
|
|
643
|
+
persistentBaseSnapshotCreating.delete(config.agentName);
|
|
644
|
+
}
|
|
566
645
|
if (!toolResponse) {
|
|
567
646
|
return {
|
|
568
647
|
toolResponse: "Subagent workflow returned no response",
|
|
@@ -598,22 +677,60 @@ function createSubagentHandler(subagents) {
|
|
|
598
677
|
};
|
|
599
678
|
};
|
|
600
679
|
const destroySubagentSandboxes = async () => {
|
|
601
|
-
const
|
|
680
|
+
const entries = [...pendingDestroys.values()];
|
|
602
681
|
pendingDestroys.clear();
|
|
603
682
|
await Promise.all(
|
|
604
|
-
|
|
683
|
+
entries.map(async ({ agentName, sandboxId }) => {
|
|
684
|
+
const ops = agentSandboxOps.get(agentName);
|
|
685
|
+
if (!ops) {
|
|
686
|
+
log.warn(
|
|
687
|
+
"Skipping sandbox destroy \u2014 no sandbox.proxy registered for agent",
|
|
688
|
+
{ agentName, sandboxId }
|
|
689
|
+
);
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
try {
|
|
693
|
+
await ops.destroySandbox(sandboxId);
|
|
694
|
+
} catch (err) {
|
|
695
|
+
log.warn("Failed to destroy subagent sandbox", {
|
|
696
|
+
agentName,
|
|
697
|
+
sandboxId,
|
|
698
|
+
error: err
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
})
|
|
702
|
+
);
|
|
703
|
+
};
|
|
704
|
+
const cleanupSubagentSnapshots = async () => {
|
|
705
|
+
const tagged = [];
|
|
706
|
+
for (const entry of threadSnapshots.values()) tagged.push(entry);
|
|
707
|
+
for (const [agentName, snapshot] of persistentBaseSnapshot.entries()) {
|
|
708
|
+
tagged.push({ agentName, snapshot });
|
|
709
|
+
}
|
|
710
|
+
threadSnapshots.clear();
|
|
711
|
+
persistentBaseSnapshot.clear();
|
|
712
|
+
await Promise.all(
|
|
713
|
+
tagged.map(async ({ agentName, snapshot }) => {
|
|
714
|
+
const ops = agentSandboxOps.get(agentName);
|
|
715
|
+
if (!ops) {
|
|
716
|
+
log.warn(
|
|
717
|
+
"Skipping snapshot delete \u2014 no sandbox.proxy registered for agent",
|
|
718
|
+
{ agentName }
|
|
719
|
+
);
|
|
720
|
+
return;
|
|
721
|
+
}
|
|
605
722
|
try {
|
|
606
|
-
await
|
|
607
|
-
await handle.result();
|
|
723
|
+
await ops.deleteSandboxSnapshot(snapshot);
|
|
608
724
|
} catch (err) {
|
|
609
|
-
log.warn("Failed to
|
|
725
|
+
log.warn("Failed to delete subagent snapshot", {
|
|
726
|
+
agentName,
|
|
610
727
|
error: err
|
|
611
728
|
});
|
|
612
729
|
}
|
|
613
730
|
})
|
|
614
731
|
);
|
|
615
732
|
};
|
|
616
|
-
return { handler, destroySubagentSandboxes };
|
|
733
|
+
return { handler, destroySubagentSandboxes, cleanupSubagentSnapshots };
|
|
617
734
|
}
|
|
618
735
|
|
|
619
736
|
// src/lib/subagent/register.ts
|
|
@@ -627,7 +744,7 @@ function buildSubagentRegistration(subagents) {
|
|
|
627
744
|
if (s.hooks) subagentHooksMap.set(s.agentName, s.hooks);
|
|
628
745
|
}
|
|
629
746
|
const resolveSubagentName = (args) => args.subagent;
|
|
630
|
-
const { handler, destroySubagentSandboxes } = createSubagentHandler(subagents);
|
|
747
|
+
const { handler, destroySubagentSandboxes, cleanupSubagentSnapshots } = createSubagentHandler(subagents);
|
|
631
748
|
const registration = {
|
|
632
749
|
name: SUBAGENT_TOOL_NAME,
|
|
633
750
|
enabled: () => getEnabled().length > 0,
|
|
@@ -651,7 +768,7 @@ function buildSubagentRegistration(subagents) {
|
|
|
651
768
|
}
|
|
652
769
|
}
|
|
653
770
|
};
|
|
654
|
-
return { registration, destroySubagentSandboxes };
|
|
771
|
+
return { registration, destroySubagentSandboxes, cleanupSubagentSnapshots };
|
|
655
772
|
}
|
|
656
773
|
var READ_SKILL_TOOL_NAME = "ReadSkill";
|
|
657
774
|
function buildReadSkillDescription(skills) {
|
|
@@ -724,9 +841,7 @@ function validateSkillNames(skills) {
|
|
|
724
841
|
const names = skills.map((s) => s.name);
|
|
725
842
|
const dupes = names.filter((n, i) => names.indexOf(n) !== i);
|
|
726
843
|
if (dupes.length > 0) {
|
|
727
|
-
throw new Error(
|
|
728
|
-
`Duplicate skill names: ${[...new Set(dupes)].join(", ")}`
|
|
729
|
-
);
|
|
844
|
+
throw new Error(`Duplicate skill names: ${[...new Set(dupes)].join(", ")}`);
|
|
730
845
|
}
|
|
731
846
|
}
|
|
732
847
|
function buildSkillRegistration(skills) {
|
|
@@ -792,15 +907,18 @@ async function createSession({
|
|
|
792
907
|
initializeThread,
|
|
793
908
|
appendSystemMessage,
|
|
794
909
|
appendAgentMessage,
|
|
795
|
-
forkThread
|
|
910
|
+
forkThread,
|
|
911
|
+
truncateThread
|
|
796
912
|
} = threadOps;
|
|
797
913
|
const plugins = [];
|
|
798
914
|
let destroySubagentSandboxes;
|
|
915
|
+
let cleanupSubagentSnapshots;
|
|
799
916
|
if (subagents) {
|
|
800
917
|
const result = buildSubagentRegistration(subagents);
|
|
801
918
|
if (result) {
|
|
802
919
|
plugins.push(result.registration);
|
|
803
920
|
destroySubagentSandboxes = result.destroySubagentSandboxes;
|
|
921
|
+
cleanupSubagentSnapshots = result.cleanupSubagentSnapshots;
|
|
804
922
|
}
|
|
805
923
|
}
|
|
806
924
|
if (skills) {
|
|
@@ -853,6 +971,9 @@ async function createSession({
|
|
|
853
971
|
const sandboxMode = sandboxInit?.mode;
|
|
854
972
|
let sandboxId;
|
|
855
973
|
let sandboxOwned = false;
|
|
974
|
+
let baseSnapshot;
|
|
975
|
+
let exitSnapshot;
|
|
976
|
+
let freshlyCreated = false;
|
|
856
977
|
if (sandboxMode === "inherit") {
|
|
857
978
|
const inheritInit = sandboxInit;
|
|
858
979
|
sandboxId = inheritInit.sandboxId;
|
|
@@ -881,8 +1002,23 @@ async function createSession({
|
|
|
881
1002
|
nonRetryable: true
|
|
882
1003
|
});
|
|
883
1004
|
}
|
|
1005
|
+
const forkInit = sandboxInit;
|
|
884
1006
|
sandboxId = await sandboxOps.forkSandbox(
|
|
885
|
-
|
|
1007
|
+
forkInit.sandboxId,
|
|
1008
|
+
forkInit.options
|
|
1009
|
+
);
|
|
1010
|
+
sandboxOwned = true;
|
|
1011
|
+
} else if (sandboxMode === "from-snapshot") {
|
|
1012
|
+
if (!sandboxOps) {
|
|
1013
|
+
throw ApplicationFailure.create({
|
|
1014
|
+
message: "No sandboxOps provided \u2014 cannot restore sandbox",
|
|
1015
|
+
nonRetryable: true
|
|
1016
|
+
});
|
|
1017
|
+
}
|
|
1018
|
+
const restoreInit = sandboxInit;
|
|
1019
|
+
sandboxId = await sandboxOps.restoreSandbox(
|
|
1020
|
+
restoreInit.snapshot,
|
|
1021
|
+
restoreInit.options
|
|
886
1022
|
);
|
|
887
1023
|
sandboxOwned = true;
|
|
888
1024
|
} else if (sandboxOps) {
|
|
@@ -893,9 +1029,13 @@ async function createSession({
|
|
|
893
1029
|
if (result) {
|
|
894
1030
|
sandboxId = result.sandboxId;
|
|
895
1031
|
sandboxOwned = true;
|
|
1032
|
+
freshlyCreated = true;
|
|
896
1033
|
}
|
|
897
1034
|
}
|
|
898
|
-
if (sandboxId &&
|
|
1035
|
+
if (sandboxId && sandboxOwned && freshlyCreated && sandboxShutdown === "snapshot" && sandboxOps) {
|
|
1036
|
+
baseSnapshot = await sandboxOps.snapshotSandbox(sandboxId);
|
|
1037
|
+
}
|
|
1038
|
+
if (sandboxId && sandboxOwned && onSandboxReady) {
|
|
899
1039
|
onSandboxReady(sandboxId);
|
|
900
1040
|
}
|
|
901
1041
|
if (virtualFsConfig) {
|
|
@@ -961,18 +1101,25 @@ async function createSession({
|
|
|
961
1101
|
threadKey
|
|
962
1102
|
);
|
|
963
1103
|
let exitReason = "completed";
|
|
1104
|
+
let finalMessage = null;
|
|
964
1105
|
try {
|
|
965
1106
|
while (stateManager.isRunning() && !stateManager.isTerminal() && stateManager.getTurns() < maxTurns) {
|
|
966
1107
|
stateManager.incrementTurns();
|
|
967
1108
|
const currentTurn = stateManager.getTurns();
|
|
968
1109
|
log.debug("turn started", { agentName, threadId, turn: currentTurn });
|
|
969
1110
|
stateManager.setTools(toolRouter.getToolDefinitions());
|
|
970
|
-
const {
|
|
1111
|
+
const {
|
|
1112
|
+
message,
|
|
1113
|
+
rawToolCalls,
|
|
1114
|
+
usage,
|
|
1115
|
+
threadLengthAtCall
|
|
1116
|
+
} = await runAgent({
|
|
971
1117
|
threadId,
|
|
972
1118
|
threadKey,
|
|
973
1119
|
agentName,
|
|
974
1120
|
metadata
|
|
975
1121
|
});
|
|
1122
|
+
const preAssistantLength = threadLengthAtCall;
|
|
976
1123
|
await appendAgentMessage(threadId, uuid4(), message, threadKey);
|
|
977
1124
|
if (usage) {
|
|
978
1125
|
stateManager.updateUsage(usage);
|
|
@@ -987,21 +1134,8 @@ async function createSession({
|
|
|
987
1134
|
if (!toolRouter.hasTools() || rawToolCalls.length === 0) {
|
|
988
1135
|
stateManager.complete();
|
|
989
1136
|
exitReason = "completed";
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
threadId,
|
|
993
|
-
exitReason,
|
|
994
|
-
turns: currentTurn,
|
|
995
|
-
durationMs: Date.now() - sessionStartMs,
|
|
996
|
-
usage: stateManager.getTotalUsage()
|
|
997
|
-
});
|
|
998
|
-
return {
|
|
999
|
-
threadId,
|
|
1000
|
-
finalMessage: message,
|
|
1001
|
-
exitReason,
|
|
1002
|
-
usage: stateManager.getTotalUsage(),
|
|
1003
|
-
sandboxId
|
|
1004
|
-
};
|
|
1137
|
+
finalMessage = message;
|
|
1138
|
+
break;
|
|
1005
1139
|
}
|
|
1006
1140
|
const parsedToolCalls = [];
|
|
1007
1141
|
for (const tc of rawToolCalls) {
|
|
@@ -1031,6 +1165,24 @@ async function createSession({
|
|
|
1031
1165
|
stateManager.updateUsage(result.usage);
|
|
1032
1166
|
}
|
|
1033
1167
|
}
|
|
1168
|
+
const rewind = toolCallResults.rewind;
|
|
1169
|
+
if (rewind) {
|
|
1170
|
+
log.info("rewinding turn", {
|
|
1171
|
+
agentName,
|
|
1172
|
+
threadId,
|
|
1173
|
+
turn: currentTurn,
|
|
1174
|
+
toolCallId: rewind.toolCallId,
|
|
1175
|
+
toolName: rewind.toolName
|
|
1176
|
+
});
|
|
1177
|
+
if (preAssistantLength === void 0) {
|
|
1178
|
+
throw ApplicationFailure.create({
|
|
1179
|
+
message: "Rewind requested but runAgent did not report `threadLengthAtCall`; the adapter must populate it to support rewinds.",
|
|
1180
|
+
nonRetryable: true
|
|
1181
|
+
});
|
|
1182
|
+
}
|
|
1183
|
+
await truncateThread(threadId, preAssistantLength, threadKey);
|
|
1184
|
+
continue;
|
|
1185
|
+
}
|
|
1034
1186
|
if (stateManager.getStatus() === "WAITING_FOR_INPUT") {
|
|
1035
1187
|
const conditionMet = await condition(
|
|
1036
1188
|
() => stateManager.getStatus() === "RUNNING",
|
|
@@ -1073,11 +1225,21 @@ async function createSession({
|
|
|
1073
1225
|
case "pause-until-parent-close":
|
|
1074
1226
|
await sandboxOps.pauseSandbox(sandboxId);
|
|
1075
1227
|
break;
|
|
1228
|
+
case "keep":
|
|
1229
|
+
case "keep-until-parent-close":
|
|
1230
|
+
break;
|
|
1231
|
+
case "snapshot":
|
|
1232
|
+
exitSnapshot = await sandboxOps.snapshotSandbox(sandboxId);
|
|
1233
|
+
await sandboxOps.destroySandbox(sandboxId);
|
|
1234
|
+
break;
|
|
1076
1235
|
}
|
|
1077
1236
|
}
|
|
1078
1237
|
if (destroySubagentSandboxes) {
|
|
1079
1238
|
await destroySubagentSandboxes();
|
|
1080
1239
|
}
|
|
1240
|
+
if (cleanupSubagentSnapshots) {
|
|
1241
|
+
await cleanupSubagentSnapshots();
|
|
1242
|
+
}
|
|
1081
1243
|
}
|
|
1082
1244
|
log.info("session ended", {
|
|
1083
1245
|
agentName,
|
|
@@ -1085,14 +1247,18 @@ async function createSession({
|
|
|
1085
1247
|
exitReason,
|
|
1086
1248
|
turns: stateManager.getTurns(),
|
|
1087
1249
|
durationMs: Date.now() - sessionStartMs,
|
|
1088
|
-
usage: stateManager.getTotalUsage()
|
|
1250
|
+
usage: stateManager.getTotalUsage(),
|
|
1251
|
+
...baseSnapshot && { hasBaseSnapshot: true },
|
|
1252
|
+
...exitSnapshot && { hasExitSnapshot: true }
|
|
1089
1253
|
});
|
|
1090
1254
|
return {
|
|
1091
1255
|
threadId,
|
|
1092
|
-
finalMessage
|
|
1256
|
+
finalMessage,
|
|
1093
1257
|
exitReason,
|
|
1094
1258
|
usage: stateManager.getTotalUsage(),
|
|
1095
|
-
sandboxId
|
|
1259
|
+
sandboxId,
|
|
1260
|
+
...baseSnapshot && { baseSnapshot },
|
|
1261
|
+
...exitSnapshot && { snapshot: exitSnapshot }
|
|
1096
1262
|
};
|
|
1097
1263
|
}
|
|
1098
1264
|
};
|
|
@@ -1303,44 +1469,16 @@ function defineSubagentWorkflow(config, fn) {
|
|
|
1303
1469
|
...workflowInput.thread && { thread: workflowInput.thread },
|
|
1304
1470
|
...workflowInput.sandbox && { sandbox: workflowInput.sandbox },
|
|
1305
1471
|
onSandboxReady: (sandboxId) => {
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1472
|
+
const isReuse = workflowInput.sandbox?.mode === "continue";
|
|
1473
|
+
if (!isReuse) {
|
|
1474
|
+
void parentHandle.signal(childSandboxReadySignal, {
|
|
1475
|
+
childWorkflowId: workflowInfo().workflowId,
|
|
1476
|
+
sandboxId
|
|
1477
|
+
});
|
|
1478
|
+
}
|
|
1310
1479
|
}
|
|
1311
1480
|
};
|
|
1312
|
-
|
|
1313
|
-
prompt,
|
|
1314
|
-
sessionInput,
|
|
1315
|
-
context ?? {}
|
|
1316
|
-
);
|
|
1317
|
-
if (effectiveShutdown === "pause-until-parent-close" || effectiveShutdown === "keep-until-parent-close") {
|
|
1318
|
-
if (!destroySandbox) {
|
|
1319
|
-
throw ApplicationFailure.create({
|
|
1320
|
-
message: `Subagent "${config.name}" has sandboxShutdown="${effectiveShutdown}" but fn did not return a destroySandbox callback`,
|
|
1321
|
-
nonRetryable: true
|
|
1322
|
-
});
|
|
1323
|
-
}
|
|
1324
|
-
if (!result.sandboxId) {
|
|
1325
|
-
throw ApplicationFailure.create({
|
|
1326
|
-
message: `Subagent "${config.name}" has sandboxShutdown="${effectiveShutdown}" but fn did not return a sandboxId`,
|
|
1327
|
-
nonRetryable: true
|
|
1328
|
-
});
|
|
1329
|
-
}
|
|
1330
|
-
}
|
|
1331
|
-
await parentHandle.signal(childResultSignal, {
|
|
1332
|
-
childWorkflowId: workflowInfo().workflowId,
|
|
1333
|
-
result
|
|
1334
|
-
});
|
|
1335
|
-
if (destroySandbox) {
|
|
1336
|
-
let destroyRequested = false;
|
|
1337
|
-
setHandler(destroySandboxSignal, () => {
|
|
1338
|
-
destroyRequested = true;
|
|
1339
|
-
});
|
|
1340
|
-
await condition(() => destroyRequested);
|
|
1341
|
-
await destroySandbox();
|
|
1342
|
-
}
|
|
1343
|
-
return result;
|
|
1481
|
+
return fn(prompt, sessionInput, context ?? {});
|
|
1344
1482
|
};
|
|
1345
1483
|
Object.defineProperty(workflow, "name", { value: config.name });
|
|
1346
1484
|
return Object.assign(workflow, {
|
|
@@ -1450,9 +1588,7 @@ function applyVirtualTreeMutations(stateManager, mutations) {
|
|
|
1450
1588
|
tree = tree.filter((e) => e.path !== m.path);
|
|
1451
1589
|
break;
|
|
1452
1590
|
case "update":
|
|
1453
|
-
tree = tree.map(
|
|
1454
|
-
(e) => e.path === m.path ? { ...e, ...m.entry } : e
|
|
1455
|
-
);
|
|
1591
|
+
tree = tree.map((e) => e.path === m.path ? { ...e, ...m.entry } : e);
|
|
1456
1592
|
break;
|
|
1457
1593
|
}
|
|
1458
1594
|
}
|
|
@@ -1511,7 +1647,9 @@ function formatVirtualFileTree(entries, opts = {}) {
|
|
|
1511
1647
|
// src/lib/virtual-fs/queries.ts
|
|
1512
1648
|
function hasFileWithMimeType(stateManager, pattern) {
|
|
1513
1649
|
const tree = stateManager.get("fileTree");
|
|
1514
|
-
const matchers = (Array.isArray(pattern) ? pattern : [pattern]).map(
|
|
1650
|
+
const matchers = (Array.isArray(pattern) ? pattern : [pattern]).map(
|
|
1651
|
+
buildMatcher
|
|
1652
|
+
);
|
|
1515
1653
|
return tree.some((entry) => {
|
|
1516
1654
|
const meta = entry.metadata;
|
|
1517
1655
|
const mime = meta?.mimeType;
|
|
@@ -1572,7 +1710,9 @@ function proxyVirtualFsOps(scope, options) {
|
|
|
1572
1710
|
// src/lib/skills/parse.ts
|
|
1573
1711
|
function parseSkillFile(raw) {
|
|
1574
1712
|
const trimmed = raw.replace(/^\uFEFF/, "");
|
|
1575
|
-
const match = trimmed.match(
|
|
1713
|
+
const match = trimmed.match(
|
|
1714
|
+
/^---[ \t]*\r?\n([\s\S]*?)\r?\n---[ \t]*\r?\n?([\s\S]*)$/
|
|
1715
|
+
);
|
|
1576
1716
|
if (!match) {
|
|
1577
1717
|
throw new Error(
|
|
1578
1718
|
"SKILL.md must start with YAML frontmatter delimited by ---"
|
|
@@ -1844,7 +1984,9 @@ function createTaskGetHandler(stateManager) {
|
|
|
1844
1984
|
const task = stateManager.getTask(args.taskId) ?? null;
|
|
1845
1985
|
if (!task) {
|
|
1846
1986
|
return {
|
|
1847
|
-
toolResponse: JSON.stringify({
|
|
1987
|
+
toolResponse: JSON.stringify({
|
|
1988
|
+
error: `Task not found: ${args.taskId}`
|
|
1989
|
+
}),
|
|
1848
1990
|
data: null
|
|
1849
1991
|
};
|
|
1850
1992
|
}
|
|
@@ -1887,7 +2029,9 @@ function createTaskUpdateHandler(stateManager) {
|
|
|
1887
2029
|
const task = stateManager.getTask(args.taskId);
|
|
1888
2030
|
if (!task) {
|
|
1889
2031
|
return {
|
|
1890
|
-
toolResponse: JSON.stringify({
|
|
2032
|
+
toolResponse: JSON.stringify({
|
|
2033
|
+
error: `Task not found: ${args.taskId}`
|
|
2034
|
+
}),
|
|
1891
2035
|
data: null
|
|
1892
2036
|
};
|
|
1893
2037
|
}
|