zeitlich 0.2.36 → 0.2.37
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-Bb-nAjwQ.d.ts} +2 -2
- package/dist/{activities-hd4aNnZE.d.cts → activities-vkI4_3CC.d.cts} +2 -2
- package/dist/adapters/sandbox/bedrock/index.cjs +14 -11
- package/dist/adapters/sandbox/bedrock/index.cjs.map +1 -1
- package/dist/adapters/sandbox/bedrock/index.d.cts +4 -3
- package/dist/adapters/sandbox/bedrock/index.d.ts +4 -3
- package/dist/adapters/sandbox/bedrock/index.js +14 -11
- 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 +8 -0
- package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
- package/dist/adapters/sandbox/daytona/index.d.cts +2 -1
- package/dist/adapters/sandbox/daytona/index.d.ts +2 -1
- package/dist/adapters/sandbox/daytona/index.js +8 -0
- 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 +59 -10
- package/dist/adapters/sandbox/e2b/index.cjs.map +1 -1
- package/dist/adapters/sandbox/e2b/index.d.cts +5 -3
- package/dist/adapters/sandbox/e2b/index.d.ts +5 -3
- package/dist/adapters/sandbox/e2b/index.js +59 -10
- 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 +5 -0
- package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.d.cts +2 -1
- package/dist/adapters/sandbox/inmemory/index.d.ts +2 -1
- package/dist/adapters/sandbox/inmemory/index.js +5 -0
- 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 +71 -36
- 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 +71 -36
- package/dist/adapters/thread/anthropic/index.js.map +1 -1
- package/dist/adapters/thread/anthropic/workflow.cjs +5 -1
- 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 +5 -1
- package/dist/adapters/thread/anthropic/workflow.js.map +1 -1
- package/dist/adapters/thread/google-genai/index.cjs +50 -25
- 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 +50 -25
- package/dist/adapters/thread/google-genai/index.js.map +1 -1
- package/dist/adapters/thread/google-genai/workflow.cjs +5 -1
- 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 +5 -1
- package/dist/adapters/thread/google-genai/workflow.js.map +1 -1
- package/dist/adapters/thread/langchain/index.cjs +34 -7
- 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 +34 -7
- package/dist/adapters/thread/langchain/index.js.map +1 -1
- package/dist/adapters/thread/langchain/workflow.cjs +5 -1
- 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 +5 -1
- package/dist/adapters/thread/langchain/workflow.js.map +1 -1
- package/dist/index.cjs +206 -120
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -11
- package/dist/index.d.ts +17 -11
- package/dist/index.js +207 -121
- package/dist/index.js.map +1 -1
- package/dist/{proxy-BjdFGPTm.d.ts → proxy-0smGKvx8.d.ts} +1 -1
- package/dist/{proxy-7RnVaPdJ.d.cts → proxy-DEtowJyd.d.cts} +1 -1
- package/dist/{thread-manager-DjN5JYul.d.ts → thread-manager-3fszQih4.d.ts} +2 -2
- package/dist/{thread-manager-CbpiGq1L.d.ts → thread-manager-C-C4pI2z.d.ts} +2 -2
- package/dist/{thread-manager-BBzNgQWH.d.cts → thread-manager-CzYln2OC.d.cts} +2 -2
- package/dist/{thread-manager-DzXm9eeI.d.cts → thread-manager-D4vgzYrh.d.cts} +2 -2
- package/dist/{types-yiXmqedU.d.ts → types-B37hKoWA.d.ts} +1 -1
- package/dist/{types-DQ1l_gXL.d.cts → types-BO7Yju20.d.cts} +63 -14
- package/dist/{types-wiGLvxWf.d.ts → types-CNuWnvy9.d.ts} +1 -1
- package/dist/{types-CADc5V_P.d.ts → types-CPKDl-y_.d.ts} +63 -14
- package/dist/{types-Mc_4BCfT.d.cts → types-D08CXPh8.d.cts} +1 -1
- package/dist/{types-CBH54cwr.d.cts → types-DWEUmYAJ.d.cts} +1 -1
- package/dist/{types-DxCpFNv_.d.cts → types-tQL9njTu.d.cts} +25 -0
- package/dist/{types-DxCpFNv_.d.ts → types-tQL9njTu.d.ts} +25 -0
- package/dist/{workflow-P2pTSfKu.d.ts → workflow-CjXHbZZc.d.ts} +2 -2
- package/dist/{workflow-DhtWRovz.d.cts → workflow-Do_lzJpT.d.cts} +2 -2
- package/dist/workflow.cjs +182 -114
- 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 +183 -115
- package/dist/workflow.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/sandbox/bedrock/filesystem.ts +6 -12
- package/src/adapters/sandbox/bedrock/index.ts +10 -8
- package/src/adapters/sandbox/bedrock/proxy.ts +2 -0
- package/src/adapters/sandbox/daytona/index.ts +6 -0
- 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 +63 -12
- package/src/adapters/sandbox/e2b/proxy.ts +2 -0
- package/src/adapters/sandbox/inmemory/index.ts +5 -0
- package/src/adapters/sandbox/inmemory/proxy.ts +2 -0
- package/src/adapters/thread/anthropic/activities.ts +49 -26
- package/src/adapters/thread/anthropic/model-invoker.ts +15 -6
- 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 +60 -46
- package/src/adapters/thread/google-genai/activities.ts +7 -2
- package/src/adapters/thread/google-genai/model-invoker.ts +26 -8
- 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 +54 -33
- package/src/adapters/thread/langchain/activities.ts +46 -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 +3 -3
- 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 +20 -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 +9 -1
- package/src/lib/model/proxy.ts +2 -2
- package/src/lib/observability/hooks.ts +4 -5
- package/src/lib/observability/index.ts +1 -4
- package/src/lib/sandbox/manager.ts +21 -4
- 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 +35 -1
- package/src/lib/session/session-edge-cases.integration.test.ts +51 -13
- package/src/lib/session/session.integration.test.ts +139 -0
- package/src/lib/session/session.ts +50 -19
- package/src/lib/session/types.ts +13 -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 +438 -156
- 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/proxy.ts +3 -4
- package/src/lib/thread/types.ts +11 -3
- package/src/lib/tool-router/index.ts +1 -5
- package/src/lib/tool-router/router-edge-cases.integration.test.ts +1 -1
- package/src/lib/tool-router/router.ts +3 -2
- package/src/lib/tool-router/types.ts +11 -3
- 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 +20 -7
- package/tsup.config.ts +9 -6
- package/src/lib/.env +0 -1
- package/src/tools/bash/.env +0 -1
package/dist/workflow.cjs
CHANGED
|
@@ -391,9 +391,7 @@ function createSubagentTool(subagents) {
|
|
|
391
391
|
schema
|
|
392
392
|
};
|
|
393
393
|
}
|
|
394
|
-
var childResultSignal = workflow.defineSignal("childResult");
|
|
395
394
|
var childSandboxReadySignal = workflow.defineSignal("childSandboxReady");
|
|
396
|
-
var destroySandboxSignal = workflow.defineSignal("destroySandbox");
|
|
397
395
|
|
|
398
396
|
// src/lib/subagent/handler.ts
|
|
399
397
|
function resolveSandboxConfig(config) {
|
|
@@ -417,25 +415,27 @@ function resolveSandboxConfig(config) {
|
|
|
417
415
|
}
|
|
418
416
|
function createSubagentHandler(subagents) {
|
|
419
417
|
const { taskQueue: parentTaskQueue } = workflow.workflowInfo();
|
|
420
|
-
const
|
|
418
|
+
const agentSandboxOps = /* @__PURE__ */ new Map();
|
|
419
|
+
for (const cfg of subagents) {
|
|
420
|
+
if (cfg.sandbox && cfg.sandbox !== "none") {
|
|
421
|
+
agentSandboxOps.set(cfg.agentName, cfg.sandbox.proxy(cfg.agentName));
|
|
422
|
+
}
|
|
423
|
+
}
|
|
421
424
|
const pendingDestroys = /* @__PURE__ */ new Map();
|
|
422
425
|
const threadSandboxes = /* @__PURE__ */ new Map();
|
|
423
426
|
const persistentSandboxes = /* @__PURE__ */ new Map();
|
|
424
427
|
const persistentSandboxCreating = /* @__PURE__ */ new Set();
|
|
425
428
|
const lazyCreatorAgent = /* @__PURE__ */ new Map();
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
workflow.setHandler(
|
|
430
|
-
|
|
431
|
-
(
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
persistentSandboxes.set(agentName, sandboxId);
|
|
435
|
-
lazyCreatorAgent.delete(childWorkflowId);
|
|
436
|
-
}
|
|
429
|
+
const threadSnapshots = /* @__PURE__ */ new Map();
|
|
430
|
+
const persistentBaseSnapshot = /* @__PURE__ */ new Map();
|
|
431
|
+
const persistentBaseSnapshotCreating = /* @__PURE__ */ new Set();
|
|
432
|
+
workflow.setHandler(childSandboxReadySignal, ({ childWorkflowId, sandboxId }) => {
|
|
433
|
+
const agentName = lazyCreatorAgent.get(childWorkflowId);
|
|
434
|
+
if (agentName && !persistentSandboxes.has(agentName)) {
|
|
435
|
+
persistentSandboxes.set(agentName, sandboxId);
|
|
436
|
+
lazyCreatorAgent.delete(childWorkflowId);
|
|
437
437
|
}
|
|
438
|
-
);
|
|
438
|
+
});
|
|
439
439
|
const handler = async (args, context) => {
|
|
440
440
|
const config = subagents.find((s) => s.agentName === args.subagent);
|
|
441
441
|
if (!config) {
|
|
@@ -446,6 +446,12 @@ function createSubagentHandler(subagents) {
|
|
|
446
446
|
const childWorkflowId = `${args.subagent}-${getShortId()}`;
|
|
447
447
|
const { sandboxId: parentSandboxId } = context;
|
|
448
448
|
const sandboxCfg = resolveSandboxConfig(config.sandbox);
|
|
449
|
+
if (sandboxCfg.source !== "none" && !agentSandboxOps.has(config.agentName)) {
|
|
450
|
+
throw workflow.ApplicationFailure.create({
|
|
451
|
+
message: `Subagent "${config.agentName}" uses a sandbox but no \`sandbox.proxy\` is configured on its SubagentConfig`,
|
|
452
|
+
nonRetryable: true
|
|
453
|
+
});
|
|
454
|
+
}
|
|
449
455
|
if (sandboxCfg.source === "inherit" && !parentSandboxId) {
|
|
450
456
|
throw new Error(
|
|
451
457
|
`Subagent "${config.agentName}" is configured with sandbox: "inherit" but the parent has no sandbox`
|
|
@@ -464,12 +470,39 @@ function createSubagentHandler(subagents) {
|
|
|
464
470
|
let sandbox;
|
|
465
471
|
let sandboxShutdownOverride;
|
|
466
472
|
let isLazyCreator = false;
|
|
473
|
+
let isSnapshotBaseCreator = false;
|
|
467
474
|
if (sandboxCfg.source === "inherit" && parentSandboxId) {
|
|
468
475
|
if (sandboxCfg.continuation === "fork") {
|
|
469
476
|
sandbox = { mode: "fork", sandboxId: parentSandboxId };
|
|
477
|
+
} else if (sandboxCfg.continuation === "snapshot") {
|
|
478
|
+
throw new Error(
|
|
479
|
+
`Subagent "${config.agentName}" has sandbox source "inherit" with continuation "snapshot" \u2014 snapshot continuation is only supported for source "own"`
|
|
480
|
+
);
|
|
470
481
|
} else {
|
|
471
482
|
sandbox = { mode: "inherit", sandboxId: parentSandboxId };
|
|
472
483
|
}
|
|
484
|
+
} else if (sandboxCfg.source === "own" && sandboxCfg.continuation === "snapshot") {
|
|
485
|
+
const isLazy = sandboxCfg.init === "once";
|
|
486
|
+
let baseSnap;
|
|
487
|
+
if (continuationThreadId) {
|
|
488
|
+
baseSnap = threadSnapshots.get(continuationThreadId)?.snapshot;
|
|
489
|
+
}
|
|
490
|
+
if (!baseSnap && isLazy) {
|
|
491
|
+
baseSnap = persistentBaseSnapshot.get(config.agentName);
|
|
492
|
+
if (!baseSnap) {
|
|
493
|
+
if (persistentBaseSnapshotCreating.has(config.agentName)) {
|
|
494
|
+
await workflow.condition(() => persistentBaseSnapshot.has(config.agentName));
|
|
495
|
+
baseSnap = persistentBaseSnapshot.get(config.agentName);
|
|
496
|
+
} else {
|
|
497
|
+
persistentBaseSnapshotCreating.add(config.agentName);
|
|
498
|
+
isSnapshotBaseCreator = true;
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
if (baseSnap) {
|
|
503
|
+
sandbox = { mode: "from-snapshot", snapshot: baseSnap };
|
|
504
|
+
}
|
|
505
|
+
sandboxShutdownOverride = "snapshot";
|
|
473
506
|
} else if (sandboxCfg.source === "own") {
|
|
474
507
|
const isLazy = sandboxCfg.init === "once";
|
|
475
508
|
let baseSandboxId;
|
|
@@ -520,31 +553,8 @@ function createSubagentHandler(subagents) {
|
|
|
520
553
|
threadMode,
|
|
521
554
|
sandboxSource: sandboxCfg.source
|
|
522
555
|
});
|
|
523
|
-
const
|
|
556
|
+
const childResult = await workflow.executeChild(config.workflow, childOpts);
|
|
524
557
|
const effectiveShutdown = sandboxShutdownOverride ?? sandboxCfg.shutdown ?? "destroy";
|
|
525
|
-
if (effectiveShutdown === "pause-until-parent-close" || effectiveShutdown === "keep-until-parent-close") {
|
|
526
|
-
const key = isLazyCreator ? `persistent:${config.agentName}` : childWorkflowId;
|
|
527
|
-
pendingDestroys.set(key, childHandle);
|
|
528
|
-
}
|
|
529
|
-
await Promise.race([
|
|
530
|
-
workflow.condition(() => childResults.has(childWorkflowId)),
|
|
531
|
-
childHandle.result()
|
|
532
|
-
]);
|
|
533
|
-
if (!childResults.has(childWorkflowId)) {
|
|
534
|
-
await workflow.condition(() => childResults.has(childWorkflowId));
|
|
535
|
-
}
|
|
536
|
-
const childResult = childResults.get(childWorkflowId);
|
|
537
|
-
childResults.delete(childWorkflowId);
|
|
538
|
-
if (!childResult) {
|
|
539
|
-
workflow.log.warn("subagent returned no result", {
|
|
540
|
-
subagent: config.agentName,
|
|
541
|
-
childWorkflowId
|
|
542
|
-
});
|
|
543
|
-
return {
|
|
544
|
-
toolResponse: "Subagent workflow did not signal a result",
|
|
545
|
-
data: null
|
|
546
|
-
};
|
|
547
|
-
}
|
|
548
558
|
workflow.log.info("subagent completed", {
|
|
549
559
|
subagent: config.agentName,
|
|
550
560
|
childWorkflowId,
|
|
@@ -556,19 +566,42 @@ function createSubagentHandler(subagents) {
|
|
|
556
566
|
usage,
|
|
557
567
|
threadId: childThreadId,
|
|
558
568
|
sandboxId: childSandboxId,
|
|
569
|
+
snapshot: childSnapshot,
|
|
570
|
+
baseSnapshot: childBaseSnapshot,
|
|
559
571
|
metadata
|
|
560
572
|
} = childResult;
|
|
561
573
|
if (childSandboxId) {
|
|
562
|
-
if (sandboxCfg.source === "own" && sandboxCfg.init === "once" && !persistentSandboxes.has(config.agentName)) {
|
|
574
|
+
if (sandboxCfg.source === "own" && sandboxCfg.init === "once" && sandboxCfg.continuation !== "snapshot" && !persistentSandboxes.has(config.agentName)) {
|
|
563
575
|
persistentSandboxes.set(config.agentName, childSandboxId);
|
|
564
|
-
} else if (allowsContinuation && childThreadId) {
|
|
576
|
+
} else if (allowsContinuation && childThreadId && sandboxCfg.source === "own" && sandboxCfg.continuation !== "snapshot") {
|
|
565
577
|
threadSandboxes.set(childThreadId, childSandboxId);
|
|
566
578
|
}
|
|
567
579
|
}
|
|
580
|
+
if (childSandboxId && (effectiveShutdown === "pause-until-parent-close" || effectiveShutdown === "keep-until-parent-close")) {
|
|
581
|
+
const key = isLazyCreator ? `persistent:${config.agentName}` : childWorkflowId;
|
|
582
|
+
pendingDestroys.set(key, {
|
|
583
|
+
agentName: config.agentName,
|
|
584
|
+
sandboxId: childSandboxId
|
|
585
|
+
});
|
|
586
|
+
}
|
|
587
|
+
if (sandboxCfg.source === "own" && sandboxCfg.continuation === "snapshot") {
|
|
588
|
+
if (childSnapshot && childThreadId) {
|
|
589
|
+
threadSnapshots.set(childThreadId, {
|
|
590
|
+
agentName: config.agentName,
|
|
591
|
+
snapshot: childSnapshot
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
if (isSnapshotBaseCreator && childBaseSnapshot && !persistentBaseSnapshot.has(config.agentName)) {
|
|
595
|
+
persistentBaseSnapshot.set(config.agentName, childBaseSnapshot);
|
|
596
|
+
}
|
|
597
|
+
}
|
|
568
598
|
if (isLazyCreator) {
|
|
569
599
|
persistentSandboxCreating.delete(config.agentName);
|
|
570
600
|
lazyCreatorAgent.delete(childWorkflowId);
|
|
571
601
|
}
|
|
602
|
+
if (isSnapshotBaseCreator) {
|
|
603
|
+
persistentBaseSnapshotCreating.delete(config.agentName);
|
|
604
|
+
}
|
|
572
605
|
if (!toolResponse) {
|
|
573
606
|
return {
|
|
574
607
|
toolResponse: "Subagent workflow returned no response",
|
|
@@ -604,22 +637,60 @@ function createSubagentHandler(subagents) {
|
|
|
604
637
|
};
|
|
605
638
|
};
|
|
606
639
|
const destroySubagentSandboxes = async () => {
|
|
607
|
-
const
|
|
640
|
+
const entries = [...pendingDestroys.values()];
|
|
608
641
|
pendingDestroys.clear();
|
|
609
642
|
await Promise.all(
|
|
610
|
-
|
|
643
|
+
entries.map(async ({ agentName, sandboxId }) => {
|
|
644
|
+
const ops = agentSandboxOps.get(agentName);
|
|
645
|
+
if (!ops) {
|
|
646
|
+
workflow.log.warn(
|
|
647
|
+
"Skipping sandbox destroy \u2014 no sandbox.proxy registered for agent",
|
|
648
|
+
{ agentName, sandboxId }
|
|
649
|
+
);
|
|
650
|
+
return;
|
|
651
|
+
}
|
|
611
652
|
try {
|
|
612
|
-
await
|
|
613
|
-
await handle.result();
|
|
653
|
+
await ops.destroySandbox(sandboxId);
|
|
614
654
|
} catch (err) {
|
|
615
|
-
workflow.log.warn("Failed to
|
|
655
|
+
workflow.log.warn("Failed to destroy subagent sandbox", {
|
|
656
|
+
agentName,
|
|
657
|
+
sandboxId,
|
|
616
658
|
error: err
|
|
617
659
|
});
|
|
618
660
|
}
|
|
619
661
|
})
|
|
620
662
|
);
|
|
621
663
|
};
|
|
622
|
-
|
|
664
|
+
const cleanupSubagentSnapshots = async () => {
|
|
665
|
+
const tagged = [];
|
|
666
|
+
for (const entry of threadSnapshots.values()) tagged.push(entry);
|
|
667
|
+
for (const [agentName, snapshot] of persistentBaseSnapshot.entries()) {
|
|
668
|
+
tagged.push({ agentName, snapshot });
|
|
669
|
+
}
|
|
670
|
+
threadSnapshots.clear();
|
|
671
|
+
persistentBaseSnapshot.clear();
|
|
672
|
+
await Promise.all(
|
|
673
|
+
tagged.map(async ({ agentName, snapshot }) => {
|
|
674
|
+
const ops = agentSandboxOps.get(agentName);
|
|
675
|
+
if (!ops) {
|
|
676
|
+
workflow.log.warn(
|
|
677
|
+
"Skipping snapshot delete \u2014 no sandbox.proxy registered for agent",
|
|
678
|
+
{ agentName }
|
|
679
|
+
);
|
|
680
|
+
return;
|
|
681
|
+
}
|
|
682
|
+
try {
|
|
683
|
+
await ops.deleteSandboxSnapshot(snapshot);
|
|
684
|
+
} catch (err) {
|
|
685
|
+
workflow.log.warn("Failed to delete subagent snapshot", {
|
|
686
|
+
agentName,
|
|
687
|
+
error: err
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
})
|
|
691
|
+
);
|
|
692
|
+
};
|
|
693
|
+
return { handler, destroySubagentSandboxes, cleanupSubagentSnapshots };
|
|
623
694
|
}
|
|
624
695
|
|
|
625
696
|
// src/lib/subagent/register.ts
|
|
@@ -633,7 +704,7 @@ function buildSubagentRegistration(subagents) {
|
|
|
633
704
|
if (s.hooks) subagentHooksMap.set(s.agentName, s.hooks);
|
|
634
705
|
}
|
|
635
706
|
const resolveSubagentName = (args) => args.subagent;
|
|
636
|
-
const { handler, destroySubagentSandboxes } = createSubagentHandler(subagents);
|
|
707
|
+
const { handler, destroySubagentSandboxes, cleanupSubagentSnapshots } = createSubagentHandler(subagents);
|
|
637
708
|
const registration = {
|
|
638
709
|
name: SUBAGENT_TOOL_NAME,
|
|
639
710
|
enabled: () => getEnabled().length > 0,
|
|
@@ -657,7 +728,7 @@ function buildSubagentRegistration(subagents) {
|
|
|
657
728
|
}
|
|
658
729
|
}
|
|
659
730
|
};
|
|
660
|
-
return { registration, destroySubagentSandboxes };
|
|
731
|
+
return { registration, destroySubagentSandboxes, cleanupSubagentSnapshots };
|
|
661
732
|
}
|
|
662
733
|
var READ_SKILL_TOOL_NAME = "ReadSkill";
|
|
663
734
|
function buildReadSkillDescription(skills) {
|
|
@@ -730,9 +801,7 @@ function validateSkillNames(skills) {
|
|
|
730
801
|
const names = skills.map((s) => s.name);
|
|
731
802
|
const dupes = names.filter((n, i) => names.indexOf(n) !== i);
|
|
732
803
|
if (dupes.length > 0) {
|
|
733
|
-
throw new Error(
|
|
734
|
-
`Duplicate skill names: ${[...new Set(dupes)].join(", ")}`
|
|
735
|
-
);
|
|
804
|
+
throw new Error(`Duplicate skill names: ${[...new Set(dupes)].join(", ")}`);
|
|
736
805
|
}
|
|
737
806
|
}
|
|
738
807
|
function buildSkillRegistration(skills) {
|
|
@@ -802,11 +871,13 @@ async function createSession({
|
|
|
802
871
|
} = threadOps;
|
|
803
872
|
const plugins = [];
|
|
804
873
|
let destroySubagentSandboxes;
|
|
874
|
+
let cleanupSubagentSnapshots;
|
|
805
875
|
if (subagents) {
|
|
806
876
|
const result = buildSubagentRegistration(subagents);
|
|
807
877
|
if (result) {
|
|
808
878
|
plugins.push(result.registration);
|
|
809
879
|
destroySubagentSandboxes = result.destroySubagentSandboxes;
|
|
880
|
+
cleanupSubagentSnapshots = result.cleanupSubagentSnapshots;
|
|
810
881
|
}
|
|
811
882
|
}
|
|
812
883
|
if (skills) {
|
|
@@ -859,6 +930,9 @@ async function createSession({
|
|
|
859
930
|
const sandboxMode = sandboxInit?.mode;
|
|
860
931
|
let sandboxId;
|
|
861
932
|
let sandboxOwned = false;
|
|
933
|
+
let baseSnapshot;
|
|
934
|
+
let exitSnapshot;
|
|
935
|
+
let freshlyCreated = false;
|
|
862
936
|
if (sandboxMode === "inherit") {
|
|
863
937
|
const inheritInit = sandboxInit;
|
|
864
938
|
sandboxId = inheritInit.sandboxId;
|
|
@@ -891,6 +965,16 @@ async function createSession({
|
|
|
891
965
|
sandboxInit.sandboxId
|
|
892
966
|
);
|
|
893
967
|
sandboxOwned = true;
|
|
968
|
+
} else if (sandboxMode === "from-snapshot") {
|
|
969
|
+
if (!sandboxOps) {
|
|
970
|
+
throw workflow.ApplicationFailure.create({
|
|
971
|
+
message: "No sandboxOps provided \u2014 cannot restore sandbox",
|
|
972
|
+
nonRetryable: true
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
const snap = sandboxInit.snapshot;
|
|
976
|
+
sandboxId = await sandboxOps.restoreSandbox(snap);
|
|
977
|
+
sandboxOwned = true;
|
|
894
978
|
} else if (sandboxOps) {
|
|
895
979
|
const skillFiles = skills ? collectSkillFiles(skills) : void 0;
|
|
896
980
|
const ctx = sandboxInit?.ctx;
|
|
@@ -899,9 +983,13 @@ async function createSession({
|
|
|
899
983
|
if (result) {
|
|
900
984
|
sandboxId = result.sandboxId;
|
|
901
985
|
sandboxOwned = true;
|
|
986
|
+
freshlyCreated = true;
|
|
902
987
|
}
|
|
903
988
|
}
|
|
904
|
-
if (sandboxId &&
|
|
989
|
+
if (sandboxId && sandboxOwned && freshlyCreated && sandboxShutdown === "snapshot" && sandboxOps) {
|
|
990
|
+
baseSnapshot = await sandboxOps.snapshotSandbox(sandboxId);
|
|
991
|
+
}
|
|
992
|
+
if (sandboxId && sandboxOwned && onSandboxReady) {
|
|
905
993
|
onSandboxReady(sandboxId);
|
|
906
994
|
}
|
|
907
995
|
if (virtualFsConfig) {
|
|
@@ -967,6 +1055,7 @@ async function createSession({
|
|
|
967
1055
|
threadKey
|
|
968
1056
|
);
|
|
969
1057
|
let exitReason = "completed";
|
|
1058
|
+
let finalMessage = null;
|
|
970
1059
|
try {
|
|
971
1060
|
while (stateManager.isRunning() && !stateManager.isTerminal() && stateManager.getTurns() < maxTurns) {
|
|
972
1061
|
stateManager.incrementTurns();
|
|
@@ -993,21 +1082,8 @@ async function createSession({
|
|
|
993
1082
|
if (!toolRouter.hasTools() || rawToolCalls.length === 0) {
|
|
994
1083
|
stateManager.complete();
|
|
995
1084
|
exitReason = "completed";
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
threadId,
|
|
999
|
-
exitReason,
|
|
1000
|
-
turns: currentTurn,
|
|
1001
|
-
durationMs: Date.now() - sessionStartMs,
|
|
1002
|
-
usage: stateManager.getTotalUsage()
|
|
1003
|
-
});
|
|
1004
|
-
return {
|
|
1005
|
-
threadId,
|
|
1006
|
-
finalMessage: message,
|
|
1007
|
-
exitReason,
|
|
1008
|
-
usage: stateManager.getTotalUsage(),
|
|
1009
|
-
sandboxId
|
|
1010
|
-
};
|
|
1085
|
+
finalMessage = message;
|
|
1086
|
+
break;
|
|
1011
1087
|
}
|
|
1012
1088
|
const parsedToolCalls = [];
|
|
1013
1089
|
for (const tc of rawToolCalls) {
|
|
@@ -1079,11 +1155,21 @@ async function createSession({
|
|
|
1079
1155
|
case "pause-until-parent-close":
|
|
1080
1156
|
await sandboxOps.pauseSandbox(sandboxId);
|
|
1081
1157
|
break;
|
|
1158
|
+
case "keep":
|
|
1159
|
+
case "keep-until-parent-close":
|
|
1160
|
+
break;
|
|
1161
|
+
case "snapshot":
|
|
1162
|
+
exitSnapshot = await sandboxOps.snapshotSandbox(sandboxId);
|
|
1163
|
+
await sandboxOps.destroySandbox(sandboxId);
|
|
1164
|
+
break;
|
|
1082
1165
|
}
|
|
1083
1166
|
}
|
|
1084
1167
|
if (destroySubagentSandboxes) {
|
|
1085
1168
|
await destroySubagentSandboxes();
|
|
1086
1169
|
}
|
|
1170
|
+
if (cleanupSubagentSnapshots) {
|
|
1171
|
+
await cleanupSubagentSnapshots();
|
|
1172
|
+
}
|
|
1087
1173
|
}
|
|
1088
1174
|
workflow.log.info("session ended", {
|
|
1089
1175
|
agentName,
|
|
@@ -1091,14 +1177,18 @@ async function createSession({
|
|
|
1091
1177
|
exitReason,
|
|
1092
1178
|
turns: stateManager.getTurns(),
|
|
1093
1179
|
durationMs: Date.now() - sessionStartMs,
|
|
1094
|
-
usage: stateManager.getTotalUsage()
|
|
1180
|
+
usage: stateManager.getTotalUsage(),
|
|
1181
|
+
...baseSnapshot && { hasBaseSnapshot: true },
|
|
1182
|
+
...exitSnapshot && { hasExitSnapshot: true }
|
|
1095
1183
|
});
|
|
1096
1184
|
return {
|
|
1097
1185
|
threadId,
|
|
1098
|
-
finalMessage
|
|
1186
|
+
finalMessage,
|
|
1099
1187
|
exitReason,
|
|
1100
1188
|
usage: stateManager.getTotalUsage(),
|
|
1101
|
-
sandboxId
|
|
1189
|
+
sandboxId,
|
|
1190
|
+
...baseSnapshot && { baseSnapshot },
|
|
1191
|
+
...exitSnapshot && { snapshot: exitSnapshot }
|
|
1102
1192
|
};
|
|
1103
1193
|
}
|
|
1104
1194
|
};
|
|
@@ -1309,44 +1399,16 @@ function defineSubagentWorkflow(config, fn) {
|
|
|
1309
1399
|
...workflowInput.thread && { thread: workflowInput.thread },
|
|
1310
1400
|
...workflowInput.sandbox && { sandbox: workflowInput.sandbox },
|
|
1311
1401
|
onSandboxReady: (sandboxId) => {
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
|
|
1402
|
+
const isReuse = workflowInput.sandbox?.mode === "continue";
|
|
1403
|
+
if (!isReuse) {
|
|
1404
|
+
void parentHandle.signal(childSandboxReadySignal, {
|
|
1405
|
+
childWorkflowId: workflow.workflowInfo().workflowId,
|
|
1406
|
+
sandboxId
|
|
1407
|
+
});
|
|
1408
|
+
}
|
|
1316
1409
|
}
|
|
1317
1410
|
};
|
|
1318
|
-
|
|
1319
|
-
prompt,
|
|
1320
|
-
sessionInput,
|
|
1321
|
-
context ?? {}
|
|
1322
|
-
);
|
|
1323
|
-
if (effectiveShutdown === "pause-until-parent-close" || effectiveShutdown === "keep-until-parent-close") {
|
|
1324
|
-
if (!destroySandbox) {
|
|
1325
|
-
throw workflow.ApplicationFailure.create({
|
|
1326
|
-
message: `Subagent "${config.name}" has sandboxShutdown="${effectiveShutdown}" but fn did not return a destroySandbox callback`,
|
|
1327
|
-
nonRetryable: true
|
|
1328
|
-
});
|
|
1329
|
-
}
|
|
1330
|
-
if (!result.sandboxId) {
|
|
1331
|
-
throw workflow.ApplicationFailure.create({
|
|
1332
|
-
message: `Subagent "${config.name}" has sandboxShutdown="${effectiveShutdown}" but fn did not return a sandboxId`,
|
|
1333
|
-
nonRetryable: true
|
|
1334
|
-
});
|
|
1335
|
-
}
|
|
1336
|
-
}
|
|
1337
|
-
await parentHandle.signal(childResultSignal, {
|
|
1338
|
-
childWorkflowId: workflow.workflowInfo().workflowId,
|
|
1339
|
-
result
|
|
1340
|
-
});
|
|
1341
|
-
if (destroySandbox) {
|
|
1342
|
-
let destroyRequested = false;
|
|
1343
|
-
workflow.setHandler(destroySandboxSignal, () => {
|
|
1344
|
-
destroyRequested = true;
|
|
1345
|
-
});
|
|
1346
|
-
await workflow.condition(() => destroyRequested);
|
|
1347
|
-
await destroySandbox();
|
|
1348
|
-
}
|
|
1349
|
-
return result;
|
|
1411
|
+
return fn(prompt, sessionInput, context ?? {});
|
|
1350
1412
|
};
|
|
1351
1413
|
Object.defineProperty(workflow$1, "name", { value: config.name });
|
|
1352
1414
|
return Object.assign(workflow$1, {
|
|
@@ -1456,9 +1518,7 @@ function applyVirtualTreeMutations(stateManager, mutations) {
|
|
|
1456
1518
|
tree = tree.filter((e) => e.path !== m.path);
|
|
1457
1519
|
break;
|
|
1458
1520
|
case "update":
|
|
1459
|
-
tree = tree.map(
|
|
1460
|
-
(e) => e.path === m.path ? { ...e, ...m.entry } : e
|
|
1461
|
-
);
|
|
1521
|
+
tree = tree.map((e) => e.path === m.path ? { ...e, ...m.entry } : e);
|
|
1462
1522
|
break;
|
|
1463
1523
|
}
|
|
1464
1524
|
}
|
|
@@ -1517,7 +1577,9 @@ function formatVirtualFileTree(entries, opts = {}) {
|
|
|
1517
1577
|
// src/lib/virtual-fs/queries.ts
|
|
1518
1578
|
function hasFileWithMimeType(stateManager, pattern) {
|
|
1519
1579
|
const tree = stateManager.get("fileTree");
|
|
1520
|
-
const matchers = (Array.isArray(pattern) ? pattern : [pattern]).map(
|
|
1580
|
+
const matchers = (Array.isArray(pattern) ? pattern : [pattern]).map(
|
|
1581
|
+
buildMatcher
|
|
1582
|
+
);
|
|
1521
1583
|
return tree.some((entry) => {
|
|
1522
1584
|
const meta = entry.metadata;
|
|
1523
1585
|
const mime = meta?.mimeType;
|
|
@@ -1578,7 +1640,9 @@ function proxyVirtualFsOps(scope, options) {
|
|
|
1578
1640
|
// src/lib/skills/parse.ts
|
|
1579
1641
|
function parseSkillFile(raw) {
|
|
1580
1642
|
const trimmed = raw.replace(/^\uFEFF/, "");
|
|
1581
|
-
const match = trimmed.match(
|
|
1643
|
+
const match = trimmed.match(
|
|
1644
|
+
/^---[ \t]*\r?\n([\s\S]*?)\r?\n---[ \t]*\r?\n?([\s\S]*)$/
|
|
1645
|
+
);
|
|
1582
1646
|
if (!match) {
|
|
1583
1647
|
throw new Error(
|
|
1584
1648
|
"SKILL.md must start with YAML frontmatter delimited by ---"
|
|
@@ -1850,7 +1914,9 @@ function createTaskGetHandler(stateManager) {
|
|
|
1850
1914
|
const task = stateManager.getTask(args.taskId) ?? null;
|
|
1851
1915
|
if (!task) {
|
|
1852
1916
|
return {
|
|
1853
|
-
toolResponse: JSON.stringify({
|
|
1917
|
+
toolResponse: JSON.stringify({
|
|
1918
|
+
error: `Task not found: ${args.taskId}`
|
|
1919
|
+
}),
|
|
1854
1920
|
data: null
|
|
1855
1921
|
};
|
|
1856
1922
|
}
|
|
@@ -1893,7 +1959,9 @@ function createTaskUpdateHandler(stateManager) {
|
|
|
1893
1959
|
const task = stateManager.getTask(args.taskId);
|
|
1894
1960
|
if (!task) {
|
|
1895
1961
|
return {
|
|
1896
|
-
toolResponse: JSON.stringify({
|
|
1962
|
+
toolResponse: JSON.stringify({
|
|
1963
|
+
error: `Task not found: ${args.taskId}`
|
|
1964
|
+
}),
|
|
1897
1965
|
data: null
|
|
1898
1966
|
};
|
|
1899
1967
|
}
|