zeitlich 0.2.37 → 0.2.39
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 +18 -0
- package/dist/{activities-Bb-nAjwQ.d.ts → activities-Bmu7XnaG.d.ts} +4 -4
- package/dist/{activities-vkI4_3CC.d.cts → activities-ByBFLvm2.d.cts} +4 -4
- package/dist/adapter-id-BB-mmrts.d.cts +17 -0
- package/dist/adapter-id-BB-mmrts.d.ts +17 -0
- package/dist/adapter-id-CMwVrVqv.d.cts +17 -0
- package/dist/adapter-id-CMwVrVqv.d.ts +17 -0
- package/dist/adapter-id-CbY2zeSt.d.cts +17 -0
- package/dist/adapter-id-CbY2zeSt.d.ts +17 -0
- package/dist/adapters/sandbox/bedrock/index.cjs +3 -3
- package/dist/adapters/sandbox/bedrock/index.cjs.map +1 -1
- package/dist/adapters/sandbox/bedrock/index.d.cts +6 -6
- package/dist/adapters/sandbox/bedrock/index.d.ts +6 -6
- package/dist/adapters/sandbox/bedrock/index.js +3 -3
- package/dist/adapters/sandbox/bedrock/index.js.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/daytona/index.cjs +3 -3
- package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
- package/dist/adapters/sandbox/daytona/index.d.cts +4 -4
- package/dist/adapters/sandbox/daytona/index.d.ts +4 -4
- package/dist/adapters/sandbox/daytona/index.js +3 -3
- package/dist/adapters/sandbox/daytona/index.js.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/e2b/index.cjs +26 -14
- package/dist/adapters/sandbox/e2b/index.cjs.map +1 -1
- package/dist/adapters/sandbox/e2b/index.d.cts +24 -4
- package/dist/adapters/sandbox/e2b/index.d.ts +24 -4
- package/dist/adapters/sandbox/e2b/index.js +26 -14
- package/dist/adapters/sandbox/e2b/index.js.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/inmemory/index.cjs +3 -3
- package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.d.cts +4 -4
- package/dist/adapters/sandbox/inmemory/index.d.ts +4 -4
- package/dist/adapters/sandbox/inmemory/index.js +3 -3
- package/dist/adapters/sandbox/inmemory/index.js.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/thread/anthropic/index.cjs +150 -13
- package/dist/adapters/thread/anthropic/index.cjs.map +1 -1
- package/dist/adapters/thread/anthropic/index.d.cts +9 -8
- package/dist/adapters/thread/anthropic/index.d.ts +9 -8
- package/dist/adapters/thread/anthropic/index.js +150 -14
- package/dist/adapters/thread/anthropic/index.js.map +1 -1
- package/dist/adapters/thread/anthropic/workflow.cjs +9 -3
- package/dist/adapters/thread/anthropic/workflow.cjs.map +1 -1
- package/dist/adapters/thread/anthropic/workflow.d.cts +6 -5
- package/dist/adapters/thread/anthropic/workflow.d.ts +6 -5
- package/dist/adapters/thread/anthropic/workflow.js +9 -4
- package/dist/adapters/thread/anthropic/workflow.js.map +1 -1
- package/dist/adapters/thread/google-genai/index.cjs +154 -13
- package/dist/adapters/thread/google-genai/index.cjs.map +1 -1
- package/dist/adapters/thread/google-genai/index.d.cts +6 -5
- package/dist/adapters/thread/google-genai/index.d.ts +6 -5
- package/dist/adapters/thread/google-genai/index.js +154 -14
- package/dist/adapters/thread/google-genai/index.js.map +1 -1
- package/dist/adapters/thread/google-genai/workflow.cjs +9 -3
- package/dist/adapters/thread/google-genai/workflow.cjs.map +1 -1
- package/dist/adapters/thread/google-genai/workflow.d.cts +6 -5
- package/dist/adapters/thread/google-genai/workflow.d.ts +6 -5
- package/dist/adapters/thread/google-genai/workflow.js +9 -4
- package/dist/adapters/thread/google-genai/workflow.js.map +1 -1
- package/dist/adapters/thread/index.cjs +16 -0
- package/dist/adapters/thread/index.cjs.map +1 -0
- package/dist/adapters/thread/index.d.cts +34 -0
- package/dist/adapters/thread/index.d.ts +34 -0
- package/dist/adapters/thread/index.js +12 -0
- package/dist/adapters/thread/index.js.map +1 -0
- package/dist/adapters/thread/langchain/index.cjs +149 -14
- package/dist/adapters/thread/langchain/index.cjs.map +1 -1
- package/dist/adapters/thread/langchain/index.d.cts +9 -8
- package/dist/adapters/thread/langchain/index.d.ts +9 -8
- package/dist/adapters/thread/langchain/index.js +149 -15
- package/dist/adapters/thread/langchain/index.js.map +1 -1
- package/dist/adapters/thread/langchain/workflow.cjs +9 -3
- package/dist/adapters/thread/langchain/workflow.cjs.map +1 -1
- package/dist/adapters/thread/langchain/workflow.d.cts +6 -5
- package/dist/adapters/thread/langchain/workflow.d.ts +6 -5
- package/dist/adapters/thread/langchain/workflow.js +9 -4
- package/dist/adapters/thread/langchain/workflow.js.map +1 -1
- package/dist/index.cjs +367 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -11
- package/dist/index.d.ts +11 -11
- package/dist/index.js +365 -61
- package/dist/index.js.map +1 -1
- package/dist/{proxy-DEtowJyd.d.cts → proxy-BAKzNGRq.d.cts} +1 -1
- package/dist/{proxy-0smGKvx8.d.ts → proxy-DO_MXbY4.d.ts} +1 -1
- package/dist/{thread-manager-C-C4pI2z.d.ts → thread-manager-CcRXasqs.d.ts} +2 -2
- package/dist/{thread-manager-D4vgzYrh.d.cts → thread-manager-ClwSaUnj.d.cts} +2 -2
- package/dist/{thread-manager-3fszQih4.d.ts → thread-manager-D-7lp1JK.d.ts} +2 -2
- package/dist/{thread-manager-CzYln2OC.d.cts → thread-manager-Y8Ucf0Tf.d.cts} +2 -2
- package/dist/{types-CPKDl-y_.d.ts → types-Bcbiq8iv.d.cts} +195 -22
- package/dist/{types-CNuWnvy9.d.ts → types-DAsQ21Rt.d.ts} +1 -1
- package/dist/{types-B37hKoWA.d.ts → types-DpHTX-iO.d.ts} +58 -1
- package/dist/{types-BO7Yju20.d.cts → types-Dt8-HBBT.d.ts} +195 -22
- package/dist/{types-D08CXPh8.d.cts → types-hFFi-Zd9.d.cts} +58 -1
- package/dist/{types-DWEUmYAJ.d.cts → types-lm8tMNJQ.d.cts} +1 -1
- package/dist/{types-tQL9njTu.d.cts → types-yx0LzPGn.d.cts} +21 -7
- package/dist/{types-tQL9njTu.d.ts → types-yx0LzPGn.d.ts} +21 -7
- package/dist/{workflow-CjXHbZZc.d.ts → workflow-Bmf9EtDW.d.ts} +83 -3
- package/dist/{workflow-Do_lzJpT.d.cts → workflow-Bx9utBwb.d.cts} +83 -3
- package/dist/workflow.cjs +266 -39
- 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 +264 -41
- package/dist/workflow.js.map +1 -1
- package/package.json +12 -2
- package/src/adapters/sandbox/bedrock/index.ts +12 -3
- package/src/adapters/sandbox/daytona/index.ts +12 -3
- package/src/adapters/sandbox/e2b/index.ts +36 -14
- package/src/adapters/sandbox/e2b/types.ts +16 -0
- package/src/adapters/sandbox/inmemory/index.ts +12 -3
- package/src/adapters/thread/adapter-id.test.ts +42 -0
- package/src/adapters/thread/anthropic/activities.ts +40 -5
- package/src/adapters/thread/anthropic/adapter-id.ts +16 -0
- package/src/adapters/thread/anthropic/fork-transform.test.ts +291 -0
- package/src/adapters/thread/anthropic/index.ts +3 -0
- package/src/adapters/thread/anthropic/model-invoker.ts +7 -1
- package/src/adapters/thread/anthropic/proxy.ts +3 -2
- package/src/adapters/thread/anthropic/thread-manager.ts +27 -1
- package/src/adapters/thread/google-genai/activities.ts +44 -5
- package/src/adapters/thread/google-genai/adapter-id.ts +16 -0
- package/src/adapters/thread/google-genai/fork-transform.test.ts +149 -0
- package/src/adapters/thread/google-genai/index.ts +3 -0
- package/src/adapters/thread/google-genai/model-invoker.ts +8 -2
- package/src/adapters/thread/google-genai/proxy.ts +3 -2
- package/src/adapters/thread/google-genai/thread-manager.ts +27 -1
- package/src/adapters/thread/index.ts +39 -0
- package/src/adapters/thread/langchain/activities.ts +40 -5
- package/src/adapters/thread/langchain/adapter-id.ts +16 -0
- package/src/adapters/thread/langchain/fork-transform.test.ts +142 -0
- package/src/adapters/thread/langchain/index.ts +3 -0
- package/src/adapters/thread/langchain/model-invoker.ts +7 -1
- package/src/adapters/thread/langchain/proxy.ts +3 -2
- package/src/adapters/thread/langchain/thread-manager.ts +27 -1
- package/src/lib/lifecycle.ts +14 -5
- package/src/lib/model/types.ts +7 -0
- package/src/lib/sandbox/manager.ts +26 -18
- package/src/lib/sandbox/types.ts +27 -7
- package/src/lib/session/session-edge-cases.integration.test.ts +336 -4
- package/src/lib/session/session.integration.test.ts +192 -2
- package/src/lib/session/session.ts +102 -8
- package/src/lib/session/types.ts +66 -3
- package/src/lib/state/index.ts +1 -0
- package/src/lib/state/manager.integration.test.ts +109 -0
- package/src/lib/state/manager.ts +38 -8
- package/src/lib/state/types.ts +25 -0
- package/src/lib/subagent/handler.ts +124 -11
- package/src/lib/subagent/index.ts +5 -1
- package/src/lib/subagent/subagent.integration.test.ts +628 -104
- package/src/lib/subagent/types.ts +63 -14
- package/src/lib/subagent/workflow.ts +29 -2
- package/src/lib/thread/index.ts +5 -0
- package/src/lib/thread/keys.test.ts +101 -0
- package/src/lib/thread/keys.ts +94 -0
- package/src/lib/thread/manager.test.ts +139 -0
- package/src/lib/thread/manager.ts +105 -9
- package/src/lib/thread/proxy.ts +3 -0
- package/src/lib/thread/types.ts +64 -1
- package/src/lib/tool-router/index.ts +2 -0
- package/src/lib/tool-router/router-edge-cases.integration.test.ts +92 -0
- package/src/lib/tool-router/router.integration.test.ts +12 -0
- package/src/lib/tool-router/router.ts +89 -16
- package/src/lib/tool-router/types.ts +42 -1
- package/src/lib/types.ts +12 -0
- package/src/workflow.ts +14 -1
- package/tsup.config.ts +1 -0
package/dist/workflow.cjs
CHANGED
|
@@ -113,7 +113,7 @@ function createToolRouter(options) {
|
|
|
113
113
|
});
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
|
-
async function processToolCall(toolCall, turn, sandboxId) {
|
|
116
|
+
async function processToolCall(toolCall, turn, sandboxId, onRewindRequested) {
|
|
117
117
|
const startTime = Date.now();
|
|
118
118
|
const tool = toolMap.get(toolCall.name);
|
|
119
119
|
const preResult = await runPreHooks(toolCall, tool, turn);
|
|
@@ -128,7 +128,7 @@ function createToolRouter(options) {
|
|
|
128
128
|
reason: "Skipped by PreToolUse hook"
|
|
129
129
|
})
|
|
130
130
|
});
|
|
131
|
-
return
|
|
131
|
+
return { kind: "skipped" };
|
|
132
132
|
}
|
|
133
133
|
const effectiveArgs = preResult.args;
|
|
134
134
|
workflow.log.debug("tool call dispatched", {
|
|
@@ -140,6 +140,7 @@ function createToolRouter(options) {
|
|
|
140
140
|
let content;
|
|
141
141
|
let resultAppended = false;
|
|
142
142
|
let metadata;
|
|
143
|
+
let rewindRequested = false;
|
|
143
144
|
try {
|
|
144
145
|
if (tool) {
|
|
145
146
|
const routerContext = {
|
|
@@ -157,11 +158,15 @@ function createToolRouter(options) {
|
|
|
157
158
|
content = response.toolResponse;
|
|
158
159
|
resultAppended = response.resultAppended === true;
|
|
159
160
|
metadata = response.metadata;
|
|
161
|
+
rewindRequested = response.rewind === true;
|
|
160
162
|
} else {
|
|
161
163
|
result = { error: `Unknown tool: ${toolCall.name}` };
|
|
162
164
|
content = JSON.stringify(result, null, 2);
|
|
163
165
|
}
|
|
164
166
|
} catch (error) {
|
|
167
|
+
if (workflow.isCancellation(error)) {
|
|
168
|
+
throw error;
|
|
169
|
+
}
|
|
165
170
|
workflow.log.warn("tool call failed", {
|
|
166
171
|
toolName: toolCall.name,
|
|
167
172
|
toolCallId: toolCall.id,
|
|
@@ -179,6 +184,15 @@ function createToolRouter(options) {
|
|
|
179
184
|
result = recovery.result;
|
|
180
185
|
content = recovery.content;
|
|
181
186
|
}
|
|
187
|
+
if (rewindRequested) {
|
|
188
|
+
const signal = {
|
|
189
|
+
toolCallId: toolCall.id,
|
|
190
|
+
toolName: toolCall.name
|
|
191
|
+
};
|
|
192
|
+
workflow.log.info("tool requested rewind", { ...signal });
|
|
193
|
+
onRewindRequested?.(signal);
|
|
194
|
+
return { kind: "rewind", signal };
|
|
195
|
+
}
|
|
182
196
|
if (!resultAppended) {
|
|
183
197
|
const config = {
|
|
184
198
|
threadId: options.threadId,
|
|
@@ -215,7 +229,7 @@ function createToolRouter(options) {
|
|
|
215
229
|
turn,
|
|
216
230
|
durationMs
|
|
217
231
|
);
|
|
218
|
-
return toolResult;
|
|
232
|
+
return { kind: "result", value: toolResult };
|
|
219
233
|
}
|
|
220
234
|
return {
|
|
221
235
|
hasTools() {
|
|
@@ -250,27 +264,59 @@ function createToolRouter(options) {
|
|
|
250
264
|
}));
|
|
251
265
|
},
|
|
252
266
|
async processToolCalls(toolCalls, context) {
|
|
267
|
+
const attachRewind = (arr, rewind) => {
|
|
268
|
+
if (rewind) {
|
|
269
|
+
arr.rewind = rewind;
|
|
270
|
+
}
|
|
271
|
+
return arr;
|
|
272
|
+
};
|
|
253
273
|
if (toolCalls.length === 0) {
|
|
254
|
-
return [];
|
|
274
|
+
return attachRewind([], void 0);
|
|
255
275
|
}
|
|
256
276
|
const turn = context?.turn ?? 0;
|
|
257
277
|
const sandboxId = context?.sandboxId;
|
|
278
|
+
let rewindSignal;
|
|
258
279
|
if (options.parallel) {
|
|
259
|
-
const
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
280
|
+
const scope = new workflow.CancellationScope({ cancellable: true });
|
|
281
|
+
const onRewindRequested = (signal) => {
|
|
282
|
+
if (!rewindSignal) {
|
|
283
|
+
rewindSignal = signal;
|
|
284
|
+
scope.cancel();
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
const outcomes = await scope.run(
|
|
288
|
+
async () => Promise.allSettled(
|
|
289
|
+
toolCalls.map(
|
|
290
|
+
(tc) => processToolCall(tc, turn, sandboxId, onRewindRequested)
|
|
291
|
+
)
|
|
292
|
+
)
|
|
264
293
|
);
|
|
294
|
+
const results2 = [];
|
|
295
|
+
for (const outcome of outcomes) {
|
|
296
|
+
if (outcome.status === "rejected") {
|
|
297
|
+
if (workflow.isCancellation(outcome.reason)) {
|
|
298
|
+
continue;
|
|
299
|
+
}
|
|
300
|
+
throw outcome.reason;
|
|
301
|
+
}
|
|
302
|
+
if (outcome.value.kind === "result") {
|
|
303
|
+
results2.push(outcome.value.value);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return attachRewind(results2, rewindSignal);
|
|
265
307
|
}
|
|
266
308
|
const results = [];
|
|
267
309
|
for (const toolCall of toolCalls) {
|
|
268
|
-
const
|
|
269
|
-
if (
|
|
270
|
-
|
|
310
|
+
const outcome = await processToolCall(toolCall, turn, sandboxId);
|
|
311
|
+
if (outcome.kind === "rewind") {
|
|
312
|
+
rewindSignal = outcome.signal;
|
|
313
|
+
break;
|
|
314
|
+
}
|
|
315
|
+
if (outcome.kind === "result") {
|
|
316
|
+
results.push(outcome.value);
|
|
271
317
|
}
|
|
272
318
|
}
|
|
273
|
-
return results;
|
|
319
|
+
return attachRewind(results, rewindSignal);
|
|
274
320
|
},
|
|
275
321
|
async processToolCallsByName(toolCalls, toolName, handler, context) {
|
|
276
322
|
const matchingCalls = toolCalls.filter((tc) => tc.name === toolName);
|
|
@@ -394,6 +440,7 @@ function createSubagentTool(subagents) {
|
|
|
394
440
|
var childSandboxReadySignal = workflow.defineSignal("childSandboxReady");
|
|
395
441
|
|
|
396
442
|
// src/lib/subagent/handler.ts
|
|
443
|
+
var DEFAULT_SUBAGENT_WORKFLOW_RUN_TIMEOUT = "1h";
|
|
397
444
|
function resolveSandboxConfig(config) {
|
|
398
445
|
if (!config || config === "none") {
|
|
399
446
|
return { source: "none", init: "per-call", continuation: "fork" };
|
|
@@ -425,17 +472,28 @@ function createSubagentHandler(subagents) {
|
|
|
425
472
|
const threadSandboxes = /* @__PURE__ */ new Map();
|
|
426
473
|
const persistentSandboxes = /* @__PURE__ */ new Map();
|
|
427
474
|
const persistentSandboxCreating = /* @__PURE__ */ new Set();
|
|
475
|
+
const persistentSandboxCreationError = /* @__PURE__ */ new Map();
|
|
428
476
|
const lazyCreatorAgent = /* @__PURE__ */ new Map();
|
|
477
|
+
const snapshotBaseCreatorAgent = /* @__PURE__ */ new Map();
|
|
429
478
|
const threadSnapshots = /* @__PURE__ */ new Map();
|
|
430
479
|
const persistentBaseSnapshot = /* @__PURE__ */ new Map();
|
|
431
480
|
const persistentBaseSnapshotCreating = /* @__PURE__ */ new Set();
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
lazyCreatorAgent.
|
|
481
|
+
const persistentBaseSnapshotCreationError = /* @__PURE__ */ new Map();
|
|
482
|
+
workflow.setHandler(
|
|
483
|
+
childSandboxReadySignal,
|
|
484
|
+
({ childWorkflowId, sandboxId, baseSnapshot }) => {
|
|
485
|
+
const lazyAgent = lazyCreatorAgent.get(childWorkflowId);
|
|
486
|
+
if (lazyAgent && !persistentSandboxes.has(lazyAgent)) {
|
|
487
|
+
persistentSandboxes.set(lazyAgent, sandboxId);
|
|
488
|
+
lazyCreatorAgent.delete(childWorkflowId);
|
|
489
|
+
}
|
|
490
|
+
const snapAgent = snapshotBaseCreatorAgent.get(childWorkflowId);
|
|
491
|
+
if (snapAgent && baseSnapshot && !persistentBaseSnapshot.has(snapAgent)) {
|
|
492
|
+
persistentBaseSnapshot.set(snapAgent, baseSnapshot);
|
|
493
|
+
snapshotBaseCreatorAgent.delete(childWorkflowId);
|
|
494
|
+
}
|
|
437
495
|
}
|
|
438
|
-
|
|
496
|
+
);
|
|
439
497
|
const handler = async (args, context) => {
|
|
440
498
|
const config = subagents.find((s) => s.agentName === args.subagent);
|
|
441
499
|
if (!config) {
|
|
@@ -491,8 +549,20 @@ function createSubagentHandler(subagents) {
|
|
|
491
549
|
baseSnap = persistentBaseSnapshot.get(config.agentName);
|
|
492
550
|
if (!baseSnap) {
|
|
493
551
|
if (persistentBaseSnapshotCreating.has(config.agentName)) {
|
|
494
|
-
await workflow.condition(
|
|
552
|
+
await workflow.condition(
|
|
553
|
+
() => persistentBaseSnapshot.has(config.agentName) || persistentBaseSnapshotCreationError.has(config.agentName) || !persistentBaseSnapshotCreating.has(config.agentName)
|
|
554
|
+
);
|
|
555
|
+
const creatorErr = persistentBaseSnapshotCreationError.get(
|
|
556
|
+
config.agentName
|
|
557
|
+
);
|
|
558
|
+
if (creatorErr !== void 0) {
|
|
559
|
+
throw creatorErr;
|
|
560
|
+
}
|
|
495
561
|
baseSnap = persistentBaseSnapshot.get(config.agentName);
|
|
562
|
+
if (!baseSnap) {
|
|
563
|
+
persistentBaseSnapshotCreating.add(config.agentName);
|
|
564
|
+
isSnapshotBaseCreator = true;
|
|
565
|
+
}
|
|
496
566
|
} else {
|
|
497
567
|
persistentBaseSnapshotCreating.add(config.agentName);
|
|
498
568
|
isSnapshotBaseCreator = true;
|
|
@@ -510,8 +580,20 @@ function createSubagentHandler(subagents) {
|
|
|
510
580
|
baseSandboxId = persistentSandboxes.get(config.agentName);
|
|
511
581
|
if (!baseSandboxId) {
|
|
512
582
|
if (persistentSandboxCreating.has(config.agentName)) {
|
|
513
|
-
await workflow.condition(
|
|
583
|
+
await workflow.condition(
|
|
584
|
+
() => persistentSandboxes.has(config.agentName) || persistentSandboxCreationError.has(config.agentName) || !persistentSandboxCreating.has(config.agentName)
|
|
585
|
+
);
|
|
586
|
+
const creatorErr = persistentSandboxCreationError.get(
|
|
587
|
+
config.agentName
|
|
588
|
+
);
|
|
589
|
+
if (creatorErr !== void 0) {
|
|
590
|
+
throw creatorErr;
|
|
591
|
+
}
|
|
514
592
|
baseSandboxId = persistentSandboxes.get(config.agentName);
|
|
593
|
+
if (!baseSandboxId) {
|
|
594
|
+
persistentSandboxCreating.add(config.agentName);
|
|
595
|
+
isLazyCreator = true;
|
|
596
|
+
}
|
|
515
597
|
} else {
|
|
516
598
|
persistentSandboxCreating.add(config.agentName);
|
|
517
599
|
isLazyCreator = true;
|
|
@@ -540,6 +622,12 @@ function createSubagentHandler(subagents) {
|
|
|
540
622
|
};
|
|
541
623
|
const resolvedContext = config.context === void 0 ? void 0 : typeof config.context === "function" ? config.context() : config.context;
|
|
542
624
|
const childOpts = {
|
|
625
|
+
// Apply a bounded run timeout by default so a child workflow that
|
|
626
|
+
// fails to initialize or otherwise never reaches a terminal state
|
|
627
|
+
// cannot hang the parent's `Subagent` tool call forever. Callers can
|
|
628
|
+
// raise, lower, or disable it via `workflowOptions.workflowRunTimeout`.
|
|
629
|
+
workflowRunTimeout: DEFAULT_SUBAGENT_WORKFLOW_RUN_TIMEOUT,
|
|
630
|
+
...config.workflowOptions ?? {},
|
|
543
631
|
workflowId: childWorkflowId,
|
|
544
632
|
args: resolvedContext === void 0 ? [args.prompt, workflowInput] : [args.prompt, workflowInput, resolvedContext],
|
|
545
633
|
taskQueue: config.taskQueue ?? parentTaskQueue
|
|
@@ -547,13 +635,39 @@ function createSubagentHandler(subagents) {
|
|
|
547
635
|
if (isLazyCreator) {
|
|
548
636
|
lazyCreatorAgent.set(childWorkflowId, config.agentName);
|
|
549
637
|
}
|
|
638
|
+
if (isSnapshotBaseCreator) {
|
|
639
|
+
snapshotBaseCreatorAgent.set(childWorkflowId, config.agentName);
|
|
640
|
+
}
|
|
550
641
|
workflow.log.info("subagent spawned", {
|
|
551
642
|
subagent: config.agentName,
|
|
552
643
|
childWorkflowId,
|
|
553
644
|
threadMode,
|
|
554
645
|
sandboxSource: sandboxCfg.source
|
|
555
646
|
});
|
|
556
|
-
|
|
647
|
+
let childResult;
|
|
648
|
+
try {
|
|
649
|
+
childResult = await workflow.executeChild(
|
|
650
|
+
config.workflow,
|
|
651
|
+
childOpts
|
|
652
|
+
);
|
|
653
|
+
} catch (err) {
|
|
654
|
+
workflow.log.warn("subagent failed", {
|
|
655
|
+
subagent: config.agentName,
|
|
656
|
+
childWorkflowId,
|
|
657
|
+
error: err instanceof Error ? err.message : String(err)
|
|
658
|
+
});
|
|
659
|
+
if (isLazyCreator) {
|
|
660
|
+
persistentSandboxCreating.delete(config.agentName);
|
|
661
|
+
persistentSandboxCreationError.set(config.agentName, err);
|
|
662
|
+
lazyCreatorAgent.delete(childWorkflowId);
|
|
663
|
+
}
|
|
664
|
+
if (isSnapshotBaseCreator) {
|
|
665
|
+
persistentBaseSnapshotCreating.delete(config.agentName);
|
|
666
|
+
persistentBaseSnapshotCreationError.set(config.agentName, err);
|
|
667
|
+
snapshotBaseCreatorAgent.delete(childWorkflowId);
|
|
668
|
+
}
|
|
669
|
+
throw err;
|
|
670
|
+
}
|
|
557
671
|
const effectiveShutdown = sandboxShutdownOverride ?? sandboxCfg.shutdown ?? "destroy";
|
|
558
672
|
workflow.log.info("subagent completed", {
|
|
559
673
|
subagent: config.agentName,
|
|
@@ -597,10 +711,13 @@ function createSubagentHandler(subagents) {
|
|
|
597
711
|
}
|
|
598
712
|
if (isLazyCreator) {
|
|
599
713
|
persistentSandboxCreating.delete(config.agentName);
|
|
714
|
+
persistentSandboxCreationError.delete(config.agentName);
|
|
600
715
|
lazyCreatorAgent.delete(childWorkflowId);
|
|
601
716
|
}
|
|
602
717
|
if (isSnapshotBaseCreator) {
|
|
603
718
|
persistentBaseSnapshotCreating.delete(config.agentName);
|
|
719
|
+
persistentBaseSnapshotCreationError.delete(config.agentName);
|
|
720
|
+
snapshotBaseCreatorAgent.delete(childWorkflowId);
|
|
604
721
|
}
|
|
605
722
|
if (!toolResponse) {
|
|
606
723
|
return {
|
|
@@ -843,6 +960,7 @@ async function createSession({
|
|
|
843
960
|
sandbox: sandboxInit,
|
|
844
961
|
sandboxShutdown = "destroy",
|
|
845
962
|
onSandboxReady,
|
|
963
|
+
onSessionExit,
|
|
846
964
|
virtualFs: virtualFsConfig,
|
|
847
965
|
virtualFsOps
|
|
848
966
|
}) {
|
|
@@ -867,7 +985,9 @@ async function createSession({
|
|
|
867
985
|
initializeThread,
|
|
868
986
|
appendSystemMessage,
|
|
869
987
|
appendAgentMessage,
|
|
870
|
-
forkThread
|
|
988
|
+
forkThread,
|
|
989
|
+
loadThreadState,
|
|
990
|
+
saveThreadState
|
|
871
991
|
} = threadOps;
|
|
872
992
|
const plugins = [];
|
|
873
993
|
let destroySubagentSandboxes;
|
|
@@ -961,8 +1081,10 @@ async function createSession({
|
|
|
961
1081
|
nonRetryable: true
|
|
962
1082
|
});
|
|
963
1083
|
}
|
|
1084
|
+
const forkInit = sandboxInit;
|
|
964
1085
|
sandboxId = await sandboxOps.forkSandbox(
|
|
965
|
-
|
|
1086
|
+
forkInit.sandboxId,
|
|
1087
|
+
forkInit.options
|
|
966
1088
|
);
|
|
967
1089
|
sandboxOwned = true;
|
|
968
1090
|
} else if (sandboxMode === "from-snapshot") {
|
|
@@ -972,8 +1094,11 @@ async function createSession({
|
|
|
972
1094
|
nonRetryable: true
|
|
973
1095
|
});
|
|
974
1096
|
}
|
|
975
|
-
const
|
|
976
|
-
sandboxId = await sandboxOps.restoreSandbox(
|
|
1097
|
+
const restoreInit = sandboxInit;
|
|
1098
|
+
sandboxId = await sandboxOps.restoreSandbox(
|
|
1099
|
+
restoreInit.snapshot,
|
|
1100
|
+
restoreInit.options
|
|
1101
|
+
);
|
|
977
1102
|
sandboxOwned = true;
|
|
978
1103
|
} else if (sandboxOps) {
|
|
979
1104
|
const skillFiles = skills ? collectSkillFiles(skills) : void 0;
|
|
@@ -990,7 +1115,10 @@ async function createSession({
|
|
|
990
1115
|
baseSnapshot = await sandboxOps.snapshotSandbox(sandboxId);
|
|
991
1116
|
}
|
|
992
1117
|
if (sandboxId && sandboxOwned && onSandboxReady) {
|
|
993
|
-
onSandboxReady(
|
|
1118
|
+
onSandboxReady({
|
|
1119
|
+
sandboxId,
|
|
1120
|
+
...baseSnapshot && { baseSnapshot }
|
|
1121
|
+
});
|
|
994
1122
|
}
|
|
995
1123
|
if (virtualFsConfig) {
|
|
996
1124
|
if (!virtualFsOps) {
|
|
@@ -1033,9 +1161,20 @@ async function createSession({
|
|
|
1033
1161
|
});
|
|
1034
1162
|
const sessionStartMs = Date.now();
|
|
1035
1163
|
const systemPrompt = stateManager.getSystemPrompt();
|
|
1164
|
+
const rehydrateFromSlice = (slice) => {
|
|
1165
|
+
stateManager.mergeUpdate({
|
|
1166
|
+
tasks: new Map(slice.tasks),
|
|
1167
|
+
...slice.custom
|
|
1168
|
+
});
|
|
1169
|
+
};
|
|
1036
1170
|
if (threadMode === "fork" && sourceThreadId) {
|
|
1037
1171
|
await forkThread(sourceThreadId, threadId, threadKey);
|
|
1038
|
-
|
|
1172
|
+
const forkedSlice = await loadThreadState(threadId, threadKey);
|
|
1173
|
+
if (forkedSlice) rehydrateFromSlice(forkedSlice);
|
|
1174
|
+
} else if (threadMode === "continue") {
|
|
1175
|
+
const continuedSlice = await loadThreadState(threadId, threadKey);
|
|
1176
|
+
if (continuedSlice) rehydrateFromSlice(continuedSlice);
|
|
1177
|
+
} else {
|
|
1039
1178
|
if (appendSystemPrompt) {
|
|
1040
1179
|
if (systemPrompt == null || typeof systemPrompt === "string" && systemPrompt.trim() === "") {
|
|
1041
1180
|
throw workflow.ApplicationFailure.create({
|
|
@@ -1057,18 +1196,21 @@ async function createSession({
|
|
|
1057
1196
|
let exitReason = "completed";
|
|
1058
1197
|
let finalMessage = null;
|
|
1059
1198
|
try {
|
|
1199
|
+
let assistantId;
|
|
1060
1200
|
while (stateManager.isRunning() && !stateManager.isTerminal() && stateManager.getTurns() < maxTurns) {
|
|
1061
1201
|
stateManager.incrementTurns();
|
|
1062
1202
|
const currentTurn = stateManager.getTurns();
|
|
1063
1203
|
workflow.log.debug("turn started", { agentName, threadId, turn: currentTurn });
|
|
1064
1204
|
stateManager.setTools(toolRouter.getToolDefinitions());
|
|
1205
|
+
assistantId ??= workflow.uuid4();
|
|
1065
1206
|
const { message, rawToolCalls, usage } = await runAgent({
|
|
1066
1207
|
threadId,
|
|
1067
1208
|
threadKey,
|
|
1068
1209
|
agentName,
|
|
1069
|
-
metadata
|
|
1210
|
+
metadata,
|
|
1211
|
+
assistantMessageId: assistantId
|
|
1070
1212
|
});
|
|
1071
|
-
await appendAgentMessage(threadId,
|
|
1213
|
+
await appendAgentMessage(threadId, assistantId, message, threadKey);
|
|
1072
1214
|
if (usage) {
|
|
1073
1215
|
stateManager.updateUsage(usage);
|
|
1074
1216
|
}
|
|
@@ -1113,6 +1255,18 @@ async function createSession({
|
|
|
1113
1255
|
stateManager.updateUsage(result.usage);
|
|
1114
1256
|
}
|
|
1115
1257
|
}
|
|
1258
|
+
const rewind = toolCallResults.rewind;
|
|
1259
|
+
if (rewind) {
|
|
1260
|
+
workflow.log.info("rewinding turn", {
|
|
1261
|
+
agentName,
|
|
1262
|
+
threadId,
|
|
1263
|
+
turn: currentTurn,
|
|
1264
|
+
toolCallId: rewind.toolCallId,
|
|
1265
|
+
toolName: rewind.toolName
|
|
1266
|
+
});
|
|
1267
|
+
continue;
|
|
1268
|
+
}
|
|
1269
|
+
assistantId = void 0;
|
|
1116
1270
|
if (stateManager.getStatus() === "WAITING_FOR_INPUT") {
|
|
1117
1271
|
const conditionMet = await workflow.condition(
|
|
1118
1272
|
() => stateManager.getStatus() === "RUNNING",
|
|
@@ -1145,6 +1299,19 @@ async function createSession({
|
|
|
1145
1299
|
});
|
|
1146
1300
|
throw workflow.ApplicationFailure.fromError(error);
|
|
1147
1301
|
} finally {
|
|
1302
|
+
try {
|
|
1303
|
+
await saveThreadState(
|
|
1304
|
+
threadId,
|
|
1305
|
+
stateManager.getPersistedSlice(),
|
|
1306
|
+
threadKey
|
|
1307
|
+
);
|
|
1308
|
+
} catch (persistError) {
|
|
1309
|
+
workflow.log.warn("failed to persist thread state", {
|
|
1310
|
+
agentName,
|
|
1311
|
+
threadId,
|
|
1312
|
+
error: persistError instanceof Error ? persistError.message : String(persistError)
|
|
1313
|
+
});
|
|
1314
|
+
}
|
|
1148
1315
|
await callSessionEnd(exitReason, stateManager.getTurns());
|
|
1149
1316
|
if (sandboxOwned && sandboxId && sandboxOps) {
|
|
1150
1317
|
switch (sandboxShutdown) {
|
|
@@ -1181,6 +1348,12 @@ async function createSession({
|
|
|
1181
1348
|
...baseSnapshot && { hasBaseSnapshot: true },
|
|
1182
1349
|
...exitSnapshot && { hasExitSnapshot: true }
|
|
1183
1350
|
});
|
|
1351
|
+
if (onSessionExit) {
|
|
1352
|
+
onSessionExit({
|
|
1353
|
+
...sandboxId && { sandboxId },
|
|
1354
|
+
...exitSnapshot && { snapshot: exitSnapshot }
|
|
1355
|
+
});
|
|
1356
|
+
}
|
|
1184
1357
|
return {
|
|
1185
1358
|
threadId,
|
|
1186
1359
|
finalMessage,
|
|
@@ -1209,6 +1382,15 @@ function defineWorkflow(config, fn) {
|
|
|
1209
1382
|
return workflow;
|
|
1210
1383
|
}
|
|
1211
1384
|
|
|
1385
|
+
// src/lib/thread/keys.ts
|
|
1386
|
+
var THREAD_TTL_SECONDS = 60 * 60 * 24 * 90;
|
|
1387
|
+
function getThreadListKey(threadKey, threadId) {
|
|
1388
|
+
return `${threadKey}:thread:${threadId}`;
|
|
1389
|
+
}
|
|
1390
|
+
function getThreadMetaKey(threadKey, threadId) {
|
|
1391
|
+
return `${threadKey}:meta:thread:${threadId}`;
|
|
1392
|
+
}
|
|
1393
|
+
|
|
1212
1394
|
// src/lib/types.ts
|
|
1213
1395
|
function isTerminalStatus(status) {
|
|
1214
1396
|
return status === "COMPLETED" || status === "FAILED" || status === "CANCELLED";
|
|
@@ -1228,11 +1410,19 @@ function createAgentStateManager({
|
|
|
1228
1410
|
let systemPrompt = initialState?.systemPrompt;
|
|
1229
1411
|
const tasks = new Map(initialState?.tasks);
|
|
1230
1412
|
const {
|
|
1231
|
-
status:
|
|
1232
|
-
version:
|
|
1233
|
-
turns:
|
|
1234
|
-
tasks:
|
|
1235
|
-
tools:
|
|
1413
|
+
status: _status,
|
|
1414
|
+
version: _version,
|
|
1415
|
+
turns: _turns,
|
|
1416
|
+
tasks: _tasks,
|
|
1417
|
+
tools: _tools,
|
|
1418
|
+
systemPrompt: _systemPrompt,
|
|
1419
|
+
fileTree: _fileTree,
|
|
1420
|
+
inlineFiles: _inlineFiles,
|
|
1421
|
+
virtualFsCtx: _virtualFsCtx,
|
|
1422
|
+
totalInputTokens: _totalInputTokens,
|
|
1423
|
+
totalOutputTokens: _totalOutputTokens,
|
|
1424
|
+
cachedWriteTokens: _cachedWriteTokens,
|
|
1425
|
+
cachedReadTokens: _cachedReadTokens,
|
|
1236
1426
|
...custom
|
|
1237
1427
|
} = initialState ?? {};
|
|
1238
1428
|
const customState = custom;
|
|
@@ -1312,7 +1502,14 @@ function createAgentStateManager({
|
|
|
1312
1502
|
version++;
|
|
1313
1503
|
},
|
|
1314
1504
|
mergeUpdate(update) {
|
|
1315
|
-
|
|
1505
|
+
const { tasks: nextTasks, ...rest } = update;
|
|
1506
|
+
if (nextTasks) {
|
|
1507
|
+
tasks.clear();
|
|
1508
|
+
for (const [id, task] of nextTasks) {
|
|
1509
|
+
tasks.set(id, task);
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1512
|
+
Object.assign(customState, rest);
|
|
1316
1513
|
version++;
|
|
1317
1514
|
},
|
|
1318
1515
|
getCurrentState() {
|
|
@@ -1350,6 +1547,12 @@ function createAgentStateManager({
|
|
|
1350
1547
|
}
|
|
1351
1548
|
return deleted;
|
|
1352
1549
|
},
|
|
1550
|
+
getPersistedSlice() {
|
|
1551
|
+
return {
|
|
1552
|
+
tasks: Array.from(tasks.entries()),
|
|
1553
|
+
custom: { ...customState }
|
|
1554
|
+
};
|
|
1555
|
+
},
|
|
1353
1556
|
updateUsage(usage) {
|
|
1354
1557
|
totalInputTokens += usage.inputTokens ?? 0;
|
|
1355
1558
|
totalOutputTokens += usage.outputTokens ?? 0;
|
|
@@ -1393,22 +1596,42 @@ function defineSubagentWorkflow(config, fn) {
|
|
|
1393
1596
|
});
|
|
1394
1597
|
}
|
|
1395
1598
|
const parentHandle = workflow.getExternalWorkflowHandle(parent.workflowId);
|
|
1599
|
+
let capturedSandboxId;
|
|
1600
|
+
let capturedSnapshot;
|
|
1601
|
+
let capturedBaseSnapshot;
|
|
1602
|
+
let capturedThreadId;
|
|
1396
1603
|
const sessionInput = {
|
|
1397
1604
|
agentName: config.name,
|
|
1398
1605
|
sandboxShutdown: effectiveShutdown,
|
|
1399
1606
|
...workflowInput.thread && { thread: workflowInput.thread },
|
|
1400
1607
|
...workflowInput.sandbox && { sandbox: workflowInput.sandbox },
|
|
1401
|
-
onSandboxReady: (sandboxId) => {
|
|
1608
|
+
onSandboxReady: ({ sandboxId, baseSnapshot }) => {
|
|
1609
|
+
capturedBaseSnapshot = baseSnapshot;
|
|
1402
1610
|
const isReuse = workflowInput.sandbox?.mode === "continue";
|
|
1403
1611
|
if (!isReuse) {
|
|
1404
1612
|
void parentHandle.signal(childSandboxReadySignal, {
|
|
1405
1613
|
childWorkflowId: workflow.workflowInfo().workflowId,
|
|
1406
|
-
sandboxId
|
|
1614
|
+
sandboxId,
|
|
1615
|
+
...baseSnapshot && { baseSnapshot }
|
|
1407
1616
|
});
|
|
1408
1617
|
}
|
|
1618
|
+
},
|
|
1619
|
+
onSessionExit: ({ sandboxId, snapshot, threadId }) => {
|
|
1620
|
+
capturedSandboxId = sandboxId;
|
|
1621
|
+
capturedSnapshot = snapshot;
|
|
1622
|
+
capturedThreadId = threadId;
|
|
1623
|
+
}
|
|
1624
|
+
};
|
|
1625
|
+
const result = await fn(prompt, sessionInput, context ?? {});
|
|
1626
|
+
return {
|
|
1627
|
+
...result,
|
|
1628
|
+
...capturedThreadId !== void 0 && { threadId: capturedThreadId },
|
|
1629
|
+
...capturedSandboxId !== void 0 && { sandboxId: capturedSandboxId },
|
|
1630
|
+
...capturedSnapshot !== void 0 && { snapshot: capturedSnapshot },
|
|
1631
|
+
...capturedBaseSnapshot !== void 0 && {
|
|
1632
|
+
baseSnapshot: capturedBaseSnapshot
|
|
1409
1633
|
}
|
|
1410
1634
|
};
|
|
1411
|
-
return fn(prompt, sessionInput, context ?? {});
|
|
1412
1635
|
};
|
|
1413
1636
|
Object.defineProperty(workflow$1, "name", { value: config.name });
|
|
1414
1637
|
return Object.assign(workflow$1, {
|
|
@@ -2067,8 +2290,10 @@ var createAskUserQuestionHandler = () => async (args) => {
|
|
|
2067
2290
|
};
|
|
2068
2291
|
};
|
|
2069
2292
|
|
|
2293
|
+
exports.DEFAULT_SUBAGENT_WORKFLOW_RUN_TIMEOUT = DEFAULT_SUBAGENT_WORKFLOW_RUN_TIMEOUT;
|
|
2070
2294
|
exports.SandboxNotFoundError = SandboxNotFoundError;
|
|
2071
2295
|
exports.SandboxNotSupportedError = SandboxNotSupportedError;
|
|
2296
|
+
exports.THREAD_TTL_SECONDS = THREAD_TTL_SECONDS;
|
|
2072
2297
|
exports.applyVirtualTreeMutations = applyVirtualTreeMutations;
|
|
2073
2298
|
exports.askUserQuestionTool = askUserQuestionTool;
|
|
2074
2299
|
exports.bashTool = bashTool;
|
|
@@ -2093,6 +2318,8 @@ exports.editTool = editTool;
|
|
|
2093
2318
|
exports.filesWithMimeType = filesWithMimeType;
|
|
2094
2319
|
exports.formatVirtualFileTree = formatVirtualFileTree;
|
|
2095
2320
|
exports.getShortId = getShortId;
|
|
2321
|
+
exports.getThreadListKey = getThreadListKey;
|
|
2322
|
+
exports.getThreadMetaKey = getThreadMetaKey;
|
|
2096
2323
|
exports.globTool = globTool;
|
|
2097
2324
|
exports.grepTool = grepTool;
|
|
2098
2325
|
exports.hasDirectory = hasDirectory;
|