zeitlich 0.2.22 → 0.2.24
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 +278 -59
- package/dist/adapters/sandbox/bedrock/index.cjs +427 -0
- package/dist/adapters/sandbox/bedrock/index.cjs.map +1 -0
- package/dist/adapters/sandbox/bedrock/index.d.cts +23 -0
- package/dist/adapters/sandbox/bedrock/index.d.ts +23 -0
- package/dist/adapters/sandbox/bedrock/index.js +424 -0
- package/dist/adapters/sandbox/bedrock/index.js.map +1 -0
- package/dist/adapters/sandbox/bedrock/workflow.cjs +33 -0
- package/dist/adapters/sandbox/bedrock/workflow.cjs.map +1 -0
- package/dist/adapters/sandbox/bedrock/workflow.d.cts +29 -0
- package/dist/adapters/sandbox/bedrock/workflow.d.ts +29 -0
- package/dist/adapters/sandbox/bedrock/workflow.js +31 -0
- package/dist/adapters/sandbox/bedrock/workflow.js.map +1 -0
- package/dist/adapters/sandbox/daytona/index.cjs +4 -1
- 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 +4 -1
- package/dist/adapters/sandbox/daytona/index.js.map +1 -1
- package/dist/adapters/sandbox/daytona/workflow.cjs +1 -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 +1 -0
- package/dist/adapters/sandbox/daytona/workflow.js.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.cjs +16 -2
- package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.d.cts +3 -2
- package/dist/adapters/sandbox/inmemory/index.d.ts +3 -2
- package/dist/adapters/sandbox/inmemory/index.js +16 -2
- package/dist/adapters/sandbox/inmemory/index.js.map +1 -1
- package/dist/adapters/sandbox/inmemory/workflow.cjs +1 -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 +1 -0
- package/dist/adapters/sandbox/inmemory/workflow.js.map +1 -1
- package/dist/adapters/sandbox/virtual/index.cjs +45 -11
- package/dist/adapters/sandbox/virtual/index.cjs.map +1 -1
- package/dist/adapters/sandbox/virtual/index.d.cts +6 -5
- package/dist/adapters/sandbox/virtual/index.d.ts +6 -5
- package/dist/adapters/sandbox/virtual/index.js +45 -11
- package/dist/adapters/sandbox/virtual/index.js.map +1 -1
- package/dist/adapters/sandbox/virtual/workflow.cjs +1 -0
- package/dist/adapters/sandbox/virtual/workflow.cjs.map +1 -1
- package/dist/adapters/sandbox/virtual/workflow.d.cts +3 -3
- package/dist/adapters/sandbox/virtual/workflow.d.ts +3 -3
- package/dist/adapters/sandbox/virtual/workflow.js +1 -0
- package/dist/adapters/sandbox/virtual/workflow.js.map +1 -1
- package/dist/adapters/thread/google-genai/index.d.cts +3 -3
- package/dist/adapters/thread/google-genai/index.d.ts +3 -3
- package/dist/adapters/thread/google-genai/workflow.d.cts +3 -3
- package/dist/adapters/thread/google-genai/workflow.d.ts +3 -3
- package/dist/adapters/thread/langchain/index.d.cts +3 -3
- package/dist/adapters/thread/langchain/index.d.ts +3 -3
- package/dist/adapters/thread/langchain/workflow.d.cts +3 -3
- package/dist/adapters/thread/langchain/workflow.d.ts +3 -3
- package/dist/index.cjs +443 -71
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +64 -10
- package/dist/index.d.ts +64 -10
- package/dist/index.js +442 -71
- package/dist/index.js.map +1 -1
- package/dist/{queries-Bw6WEPMw.d.cts → queries-BYGBImeC.d.cts} +1 -1
- package/dist/{queries-C27raDaB.d.ts → queries-DwBe2CAA.d.ts} +1 -1
- package/dist/{types-C5bkx6kQ.d.ts → types-7PeMi1bD.d.cts} +167 -36
- package/dist/{types-BJ8itUAl.d.cts → types-Bf8KV0Ci.d.cts} +6 -6
- package/dist/{types-HBosetv3.d.cts → types-ChAMwU3q.d.cts} +2 -0
- package/dist/{types-HBosetv3.d.ts → types-ChAMwU3q.d.ts} +2 -0
- package/dist/{types-YbL7JpEA.d.cts → types-D_igp10o.d.cts} +11 -0
- package/dist/{types-YbL7JpEA.d.ts → types-D_igp10o.d.ts} +11 -0
- package/dist/types-DhTCEMhr.d.cts +64 -0
- package/dist/{types-ENYCKFBk.d.ts → types-LVKmCNds.d.ts} +6 -6
- package/dist/types-d9NznUqd.d.ts +64 -0
- package/dist/{types-ClsHhtwL.d.cts → types-hmferhc2.d.ts} +167 -36
- package/dist/workflow.cjs +308 -63
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +54 -32
- package/dist/workflow.d.ts +54 -32
- package/dist/workflow.js +306 -61
- package/dist/workflow.js.map +1 -1
- package/package.json +27 -2
- package/src/adapters/sandbox/bedrock/filesystem.ts +313 -0
- package/src/adapters/sandbox/bedrock/index.ts +259 -0
- package/src/adapters/sandbox/bedrock/proxy.ts +56 -0
- package/src/adapters/sandbox/bedrock/types.ts +24 -0
- package/src/adapters/sandbox/daytona/filesystem.ts +1 -1
- package/src/adapters/sandbox/daytona/index.ts +4 -0
- package/src/adapters/sandbox/daytona/proxy.ts +4 -3
- package/src/adapters/sandbox/e2b/index.ts +5 -0
- package/src/adapters/sandbox/inmemory/index.ts +24 -4
- package/src/adapters/sandbox/inmemory/proxy.ts +2 -2
- package/src/adapters/sandbox/virtual/filesystem.ts +44 -18
- package/src/adapters/sandbox/virtual/provider.ts +13 -0
- package/src/adapters/sandbox/virtual/proxy.ts +1 -0
- package/src/adapters/sandbox/virtual/types.ts +9 -4
- package/src/adapters/sandbox/virtual/virtual-sandbox.test.ts +26 -0
- package/src/index.ts +2 -1
- package/src/lib/lifecycle.ts +57 -0
- package/src/lib/sandbox/manager.ts +13 -1
- package/src/lib/sandbox/node-fs.ts +115 -0
- package/src/lib/sandbox/types.ts +13 -4
- package/src/lib/session/index.ts +1 -0
- package/src/lib/session/session-edge-cases.integration.test.ts +447 -33
- package/src/lib/session/session.integration.test.ts +149 -32
- package/src/lib/session/session.ts +138 -33
- package/src/lib/session/types.ts +56 -17
- package/src/lib/skills/fs-provider.ts +65 -4
- package/src/lib/skills/handler.ts +43 -1
- package/src/lib/skills/index.ts +0 -1
- package/src/lib/skills/register.ts +17 -1
- package/src/lib/skills/skills.integration.test.ts +308 -24
- package/src/lib/skills/types.ts +6 -0
- package/src/lib/subagent/define.ts +5 -4
- package/src/lib/subagent/handler.ts +143 -14
- package/src/lib/subagent/index.ts +3 -0
- package/src/lib/subagent/register.ts +10 -3
- package/src/lib/subagent/signals.ts +8 -0
- package/src/lib/subagent/subagent.integration.test.ts +853 -150
- package/src/lib/subagent/tool.ts +2 -2
- package/src/lib/subagent/types.ts +77 -19
- package/src/lib/subagent/workflow.ts +83 -12
- package/src/lib/tool-router/router.integration.test.ts +137 -4
- package/src/lib/tool-router/router.ts +19 -6
- package/src/lib/tool-router/types.ts +11 -0
- package/src/lib/workflow.test.ts +89 -21
- package/src/lib/workflow.ts +33 -18
- package/src/workflow.ts +6 -1
- package/tsup.config.ts +3 -0
package/dist/workflow.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { uuid4, setHandler, defineUpdate, ApplicationFailure, condition, defineQuery, workflowInfo,
|
|
1
|
+
import { defineSignal, uuid4, setHandler, defineUpdate, ApplicationFailure, condition, defineQuery, workflowInfo, getExternalWorkflowHandle, startChild } from '@temporalio/workflow';
|
|
2
2
|
import z14, { z } from 'zod';
|
|
3
3
|
import { ApplicationFailure as ApplicationFailure$1 } from '@temporalio/common';
|
|
4
4
|
|
|
@@ -79,7 +79,12 @@ function createToolRouter(options) {
|
|
|
79
79
|
result: { error: errorStr, suppressed: true }
|
|
80
80
|
};
|
|
81
81
|
}
|
|
82
|
-
|
|
82
|
+
return {
|
|
83
|
+
content: JSON.stringify({
|
|
84
|
+
error: "The tool encountered an error. Please try again or use a different approach."
|
|
85
|
+
}),
|
|
86
|
+
result: { error: errorStr, suppressed: true }
|
|
87
|
+
};
|
|
83
88
|
}
|
|
84
89
|
async function runPostHooks(toolCall, tool, toolResult, effectiveArgs, turn, durationMs) {
|
|
85
90
|
if (tool?.hooks?.onPostToolUse) {
|
|
@@ -88,7 +93,8 @@ function createToolRouter(options) {
|
|
|
88
93
|
result: toolResult.data,
|
|
89
94
|
threadId: options.threadId,
|
|
90
95
|
turn,
|
|
91
|
-
durationMs
|
|
96
|
+
durationMs,
|
|
97
|
+
...toolResult.metadata && { metadata: toolResult.metadata }
|
|
92
98
|
});
|
|
93
99
|
}
|
|
94
100
|
if (options.hooks?.onPostToolUse) {
|
|
@@ -101,7 +107,7 @@ function createToolRouter(options) {
|
|
|
101
107
|
});
|
|
102
108
|
}
|
|
103
109
|
}
|
|
104
|
-
async function processToolCall(toolCall, turn, sandboxId) {
|
|
110
|
+
async function processToolCall(toolCall, turn, sandboxId, sandboxStateUpdate) {
|
|
105
111
|
const startTime = Date.now();
|
|
106
112
|
const tool = toolMap.get(toolCall.name);
|
|
107
113
|
const preResult = await runPreHooks(toolCall, tool, turn);
|
|
@@ -121,13 +127,15 @@ function createToolRouter(options) {
|
|
|
121
127
|
let result;
|
|
122
128
|
let content;
|
|
123
129
|
let resultAppended = false;
|
|
130
|
+
let metadata;
|
|
124
131
|
try {
|
|
125
132
|
if (tool) {
|
|
126
133
|
const routerContext = {
|
|
127
134
|
threadId: options.threadId,
|
|
128
135
|
toolCallId: toolCall.id,
|
|
129
136
|
toolName: toolCall.name,
|
|
130
|
-
...sandboxId !== void 0 && { sandboxId }
|
|
137
|
+
...sandboxId !== void 0 && { sandboxId },
|
|
138
|
+
...sandboxStateUpdate && { sandboxStateUpdate }
|
|
131
139
|
};
|
|
132
140
|
const response = await tool.handler(
|
|
133
141
|
effectiveArgs,
|
|
@@ -136,6 +144,7 @@ function createToolRouter(options) {
|
|
|
136
144
|
result = response.data;
|
|
137
145
|
content = response.toolResponse;
|
|
138
146
|
resultAppended = response.resultAppended === true;
|
|
147
|
+
metadata = response.metadata;
|
|
139
148
|
} else {
|
|
140
149
|
result = { error: `Unknown tool: ${toolCall.name}` };
|
|
141
150
|
content = JSON.stringify(result, null, 2);
|
|
@@ -168,7 +177,8 @@ function createToolRouter(options) {
|
|
|
168
177
|
const toolResult = {
|
|
169
178
|
toolCallId: toolCall.id,
|
|
170
179
|
name: toolCall.name,
|
|
171
|
-
data: result
|
|
180
|
+
data: result,
|
|
181
|
+
...metadata && { metadata }
|
|
172
182
|
};
|
|
173
183
|
await runPostHooks(
|
|
174
184
|
toolCall,
|
|
@@ -218,9 +228,10 @@ function createToolRouter(options) {
|
|
|
218
228
|
}
|
|
219
229
|
const turn = context?.turn ?? 0;
|
|
220
230
|
const sandboxId = context?.sandboxId;
|
|
231
|
+
const sandboxStateUpdate = context?.sandboxStateUpdate;
|
|
221
232
|
if (options.parallel) {
|
|
222
233
|
const results2 = await Promise.all(
|
|
223
|
-
toolCalls.map((tc) => processToolCall(tc, turn, sandboxId))
|
|
234
|
+
toolCalls.map((tc) => processToolCall(tc, turn, sandboxId, sandboxStateUpdate))
|
|
224
235
|
);
|
|
225
236
|
return results2.filter(
|
|
226
237
|
(r) => r !== null
|
|
@@ -228,7 +239,7 @@ function createToolRouter(options) {
|
|
|
228
239
|
}
|
|
229
240
|
const results = [];
|
|
230
241
|
for (const toolCall of toolCalls) {
|
|
231
|
-
const result = await processToolCall(toolCall, turn, sandboxId);
|
|
242
|
+
const result = await processToolCall(toolCall, turn, sandboxId, sandboxStateUpdate);
|
|
232
243
|
if (result !== null) {
|
|
233
244
|
results.push(result);
|
|
234
245
|
}
|
|
@@ -272,7 +283,8 @@ function createToolRouter(options) {
|
|
|
272
283
|
return {
|
|
273
284
|
toolCallId: toolCall.id,
|
|
274
285
|
name: toolCall.name,
|
|
275
|
-
data: response.data
|
|
286
|
+
data: response.data,
|
|
287
|
+
...response.metadata && { metadata: response.metadata }
|
|
276
288
|
};
|
|
277
289
|
};
|
|
278
290
|
if (options.parallel) {
|
|
@@ -316,7 +328,7 @@ function getShortId(length = 12) {
|
|
|
316
328
|
var SUBAGENT_TOOL_NAME = "Subagent";
|
|
317
329
|
function buildSubagentDescription(subagents) {
|
|
318
330
|
const subagentList = subagents.map((s) => {
|
|
319
|
-
const continuation = s.
|
|
331
|
+
const continuation = s.thread && s.thread !== "new" ? "\n*(Supports thread continuation \u2014 pass a threadId to resume a previous conversation)*" : "";
|
|
320
332
|
return `## ${s.agentName}
|
|
321
333
|
${s.description}${continuation}`;
|
|
322
334
|
}).join("\n\n");
|
|
@@ -332,7 +344,7 @@ function createSubagentTool(subagents) {
|
|
|
332
344
|
}
|
|
333
345
|
const names = subagents.map((s) => s.agentName);
|
|
334
346
|
const hasThreadContinuation = subagents.some(
|
|
335
|
-
(s) => s.
|
|
347
|
+
(s) => s.thread && s.thread !== "new"
|
|
336
348
|
);
|
|
337
349
|
const baseFields = {
|
|
338
350
|
subagent: z14.enum(names).describe("The type of subagent to launch"),
|
|
@@ -351,9 +363,25 @@ function createSubagentTool(subagents) {
|
|
|
351
363
|
schema
|
|
352
364
|
};
|
|
353
365
|
}
|
|
366
|
+
var childResultSignal = defineSignal("childResult");
|
|
367
|
+
var destroySandboxSignal = defineSignal("destroySandbox");
|
|
368
|
+
|
|
369
|
+
// src/lib/subagent/handler.ts
|
|
370
|
+
function resolveSandboxConfig(config) {
|
|
371
|
+
if (!config || config === "none") return { source: "none" };
|
|
372
|
+
if (config === "inherit") return { source: "inherit" };
|
|
373
|
+
if (config === "own") return { source: "own" };
|
|
374
|
+
return { source: "own", shutdown: config.shutdown };
|
|
375
|
+
}
|
|
354
376
|
function createSubagentHandler(subagents) {
|
|
355
377
|
const { taskQueue: parentTaskQueue } = workflowInfo();
|
|
356
|
-
|
|
378
|
+
const childResults = /* @__PURE__ */ new Map();
|
|
379
|
+
const pendingDestroys = /* @__PURE__ */ new Map();
|
|
380
|
+
const threadSandboxes = /* @__PURE__ */ new Map();
|
|
381
|
+
setHandler(childResultSignal, ({ childWorkflowId, result }) => {
|
|
382
|
+
childResults.set(childWorkflowId, result);
|
|
383
|
+
});
|
|
384
|
+
const handler = async (args, context) => {
|
|
357
385
|
const config = subagents.find((s) => s.agentName === args.subagent);
|
|
358
386
|
if (!config) {
|
|
359
387
|
throw new Error(
|
|
@@ -362,12 +390,36 @@ function createSubagentHandler(subagents) {
|
|
|
362
390
|
}
|
|
363
391
|
const childWorkflowId = `${args.subagent}-${getShortId()}`;
|
|
364
392
|
const { sandboxId: parentSandboxId } = context;
|
|
365
|
-
const
|
|
393
|
+
const sandboxCfg = resolveSandboxConfig(config.sandbox);
|
|
394
|
+
if (sandboxCfg.source === "inherit" && !parentSandboxId) {
|
|
395
|
+
throw new Error(
|
|
396
|
+
`Subagent "${config.agentName}" is configured with sandbox: "inherit" but the parent has no sandbox`
|
|
397
|
+
);
|
|
398
|
+
}
|
|
399
|
+
const threadMode = config.thread ?? "new";
|
|
400
|
+
const allowsContinuation = threadMode !== "new";
|
|
401
|
+
const continuationThreadId = args.threadId && allowsContinuation ? args.threadId : void 0;
|
|
402
|
+
let thread;
|
|
403
|
+
if (continuationThreadId) {
|
|
404
|
+
thread = { mode: threadMode, threadId: continuationThreadId };
|
|
405
|
+
}
|
|
406
|
+
let sandbox;
|
|
407
|
+
if (sandboxCfg.source === "inherit" && parentSandboxId) {
|
|
408
|
+
sandbox = {
|
|
409
|
+
mode: "inherit",
|
|
410
|
+
sandboxId: parentSandboxId,
|
|
411
|
+
...context.sandboxStateUpdate && { stateUpdate: context.sandboxStateUpdate }
|
|
412
|
+
};
|
|
413
|
+
} else if (sandboxCfg.source === "own") {
|
|
414
|
+
const prevSbId = continuationThreadId ? threadSandboxes.get(continuationThreadId) : void 0;
|
|
415
|
+
if (prevSbId) {
|
|
416
|
+
sandbox = { mode: "fork", sandboxId: prevSbId };
|
|
417
|
+
}
|
|
418
|
+
}
|
|
366
419
|
const workflowInput = {
|
|
367
|
-
...
|
|
368
|
-
|
|
369
|
-
}
|
|
370
|
-
...inheritSandbox && { sandboxId: parentSandboxId }
|
|
420
|
+
...thread && { thread },
|
|
421
|
+
...sandbox && { sandbox },
|
|
422
|
+
...sandboxCfg.shutdown && { sandboxShutdown: sandboxCfg.shutdown }
|
|
371
423
|
};
|
|
372
424
|
const resolvedContext = config.context === void 0 ? void 0 : typeof config.context === "function" ? config.context() : config.context;
|
|
373
425
|
const childOpts = {
|
|
@@ -375,17 +427,44 @@ function createSubagentHandler(subagents) {
|
|
|
375
427
|
args: resolvedContext === void 0 ? [args.prompt, workflowInput] : [args.prompt, workflowInput, resolvedContext],
|
|
376
428
|
taskQueue: config.taskQueue ?? parentTaskQueue
|
|
377
429
|
};
|
|
430
|
+
const childHandle = await startChild(config.workflow, childOpts);
|
|
431
|
+
const usesOwnSandbox = sandboxCfg.source === "own" || allowsContinuation && sandboxCfg.source !== "inherit";
|
|
432
|
+
if (usesOwnSandbox) {
|
|
433
|
+
pendingDestroys.set(childWorkflowId, childHandle);
|
|
434
|
+
}
|
|
435
|
+
await Promise.race([
|
|
436
|
+
condition(() => childResults.has(childWorkflowId)),
|
|
437
|
+
childHandle.result()
|
|
438
|
+
]);
|
|
439
|
+
if (!childResults.has(childWorkflowId)) {
|
|
440
|
+
await condition(() => childResults.has(childWorkflowId));
|
|
441
|
+
}
|
|
442
|
+
const childResult = childResults.get(childWorkflowId);
|
|
443
|
+
childResults.delete(childWorkflowId);
|
|
444
|
+
if (!childResult) {
|
|
445
|
+
return {
|
|
446
|
+
toolResponse: "Subagent workflow did not signal a result",
|
|
447
|
+
data: null
|
|
448
|
+
};
|
|
449
|
+
}
|
|
378
450
|
const {
|
|
379
451
|
toolResponse,
|
|
380
452
|
data,
|
|
381
453
|
usage,
|
|
382
|
-
threadId: childThreadId
|
|
383
|
-
|
|
454
|
+
threadId: childThreadId,
|
|
455
|
+
sandboxId: childSandboxId,
|
|
456
|
+
metadata
|
|
457
|
+
} = childResult;
|
|
458
|
+
if (allowsContinuation && childSandboxId && childThreadId) {
|
|
459
|
+
threadSandboxes.set(childThreadId, childSandboxId);
|
|
460
|
+
}
|
|
384
461
|
if (!toolResponse) {
|
|
385
462
|
return {
|
|
386
463
|
toolResponse: "Subagent workflow returned no response",
|
|
387
464
|
data: null,
|
|
388
|
-
...usage && { usage }
|
|
465
|
+
...usage && { usage },
|
|
466
|
+
...childSandboxId && { sandboxId: childSandboxId },
|
|
467
|
+
...metadata && { metadata }
|
|
389
468
|
};
|
|
390
469
|
}
|
|
391
470
|
const validated = config.resultSchema ? config.resultSchema.safeParse(data) : null;
|
|
@@ -393,11 +472,13 @@ function createSubagentHandler(subagents) {
|
|
|
393
472
|
return {
|
|
394
473
|
toolResponse: `Subagent workflow returned invalid data: ${validated.error.message}`,
|
|
395
474
|
data: null,
|
|
396
|
-
...usage && { usage }
|
|
475
|
+
...usage && { usage },
|
|
476
|
+
...childSandboxId && { sandboxId: childSandboxId },
|
|
477
|
+
...metadata && { metadata }
|
|
397
478
|
};
|
|
398
479
|
}
|
|
399
480
|
let finalToolResponse = toolResponse;
|
|
400
|
-
if (
|
|
481
|
+
if (allowsContinuation && childThreadId) {
|
|
401
482
|
finalToolResponse = typeof toolResponse === "string" ? `${toolResponse}
|
|
402
483
|
|
|
403
484
|
[${config.agentName} Thread ID: ${childThreadId}]` : toolResponse;
|
|
@@ -405,9 +486,22 @@ function createSubagentHandler(subagents) {
|
|
|
405
486
|
return {
|
|
406
487
|
toolResponse: finalToolResponse,
|
|
407
488
|
data: validated ? validated.data : data,
|
|
408
|
-
...usage && { usage }
|
|
489
|
+
...usage && { usage },
|
|
490
|
+
...childSandboxId && { sandboxId: childSandboxId },
|
|
491
|
+
...metadata && { metadata }
|
|
409
492
|
};
|
|
410
493
|
};
|
|
494
|
+
const destroySubagentSandboxes = async () => {
|
|
495
|
+
const handles = [...pendingDestroys.values()];
|
|
496
|
+
pendingDestroys.clear();
|
|
497
|
+
await Promise.all(
|
|
498
|
+
handles.map(async (handle) => {
|
|
499
|
+
await handle.signal(destroySandboxSignal);
|
|
500
|
+
await handle.result();
|
|
501
|
+
})
|
|
502
|
+
);
|
|
503
|
+
};
|
|
504
|
+
return { handler, destroySubagentSandboxes };
|
|
411
505
|
}
|
|
412
506
|
|
|
413
507
|
// src/lib/subagent/register.ts
|
|
@@ -421,12 +515,13 @@ function buildSubagentRegistration(subagents) {
|
|
|
421
515
|
if (s.hooks) subagentHooksMap.set(s.agentName, s.hooks);
|
|
422
516
|
}
|
|
423
517
|
const resolveSubagentName = (args) => args.subagent;
|
|
424
|
-
|
|
518
|
+
const { handler, destroySubagentSandboxes } = createSubagentHandler(subagents);
|
|
519
|
+
const registration = {
|
|
425
520
|
name: SUBAGENT_TOOL_NAME,
|
|
426
521
|
enabled: () => getEnabled().length > 0,
|
|
427
522
|
description: () => createSubagentTool(getEnabled()).description,
|
|
428
523
|
schema: () => createSubagentTool(getEnabled()).schema,
|
|
429
|
-
handler
|
|
524
|
+
handler,
|
|
430
525
|
...subagentHooksMap.size > 0 && {
|
|
431
526
|
hooks: {
|
|
432
527
|
onPreToolUse: async (ctx) => {
|
|
@@ -444,6 +539,7 @@ function buildSubagentRegistration(subagents) {
|
|
|
444
539
|
}
|
|
445
540
|
}
|
|
446
541
|
};
|
|
542
|
+
return { registration, destroySubagentSandboxes };
|
|
447
543
|
}
|
|
448
544
|
var READ_SKILL_TOOL_NAME = "ReadSkill";
|
|
449
545
|
function buildReadSkillDescription(skills) {
|
|
@@ -469,6 +565,29 @@ function createReadSkillTool(skills) {
|
|
|
469
565
|
}
|
|
470
566
|
|
|
471
567
|
// src/lib/skills/handler.ts
|
|
568
|
+
function formatSkillResponse(skill) {
|
|
569
|
+
const parts = [];
|
|
570
|
+
parts.push(`<skill_content name="${skill.name}">`);
|
|
571
|
+
parts.push(skill.instructions);
|
|
572
|
+
if (skill.location) {
|
|
573
|
+
parts.push(`
|
|
574
|
+
Skill directory: ${skill.location}`);
|
|
575
|
+
parts.push(
|
|
576
|
+
"Relative paths in this skill resolve against the skill directory above."
|
|
577
|
+
);
|
|
578
|
+
}
|
|
579
|
+
const resources = skill.resourceContents ? Object.keys(skill.resourceContents) : [];
|
|
580
|
+
if (resources.length > 0) {
|
|
581
|
+
parts.push("");
|
|
582
|
+
parts.push("<skill_resources>");
|
|
583
|
+
for (const r of resources) {
|
|
584
|
+
parts.push(` <file>${r}</file>`);
|
|
585
|
+
}
|
|
586
|
+
parts.push("</skill_resources>");
|
|
587
|
+
}
|
|
588
|
+
parts.push("</skill_content>");
|
|
589
|
+
return parts.join("\n");
|
|
590
|
+
}
|
|
472
591
|
function createReadSkillHandler(skills) {
|
|
473
592
|
const skillMap = new Map(skills.map((s) => [s.name, s]));
|
|
474
593
|
return (args) => {
|
|
@@ -482,22 +601,42 @@ function createReadSkillHandler(skills) {
|
|
|
482
601
|
};
|
|
483
602
|
}
|
|
484
603
|
return {
|
|
485
|
-
toolResponse: skill
|
|
604
|
+
toolResponse: formatSkillResponse(skill),
|
|
486
605
|
data: null
|
|
487
606
|
};
|
|
488
607
|
};
|
|
489
608
|
}
|
|
490
609
|
|
|
491
610
|
// src/lib/skills/register.ts
|
|
611
|
+
function validateSkillNames(skills) {
|
|
612
|
+
const names = skills.map((s) => s.name);
|
|
613
|
+
const dupes = names.filter((n, i) => names.indexOf(n) !== i);
|
|
614
|
+
if (dupes.length > 0) {
|
|
615
|
+
throw new Error(
|
|
616
|
+
`Duplicate skill names: ${[...new Set(dupes)].join(", ")}`
|
|
617
|
+
);
|
|
618
|
+
}
|
|
619
|
+
}
|
|
492
620
|
function buildSkillRegistration(skills) {
|
|
493
621
|
if (skills.length === 0) return null;
|
|
622
|
+
validateSkillNames(skills);
|
|
494
623
|
return {
|
|
495
624
|
...createReadSkillTool(skills),
|
|
496
625
|
handler: createReadSkillHandler(skills)
|
|
497
626
|
};
|
|
498
627
|
}
|
|
499
|
-
|
|
500
|
-
|
|
628
|
+
function collectSkillFiles(skills) {
|
|
629
|
+
let files;
|
|
630
|
+
for (const skill of skills) {
|
|
631
|
+
if (!skill.resourceContents || !skill.location) continue;
|
|
632
|
+
for (const [relPath, content] of Object.entries(skill.resourceContents)) {
|
|
633
|
+
files ??= {};
|
|
634
|
+
files[`${skill.location}/${relPath}`] = content;
|
|
635
|
+
}
|
|
636
|
+
}
|
|
637
|
+
return files;
|
|
638
|
+
}
|
|
639
|
+
async function createSession({
|
|
501
640
|
agentName,
|
|
502
641
|
maxTurns = 50,
|
|
503
642
|
metadata = {},
|
|
@@ -510,13 +649,27 @@ var createSession = async ({
|
|
|
510
649
|
processToolsInParallel = true,
|
|
511
650
|
hooks = {},
|
|
512
651
|
appendSystemPrompt = true,
|
|
513
|
-
continueThread = false,
|
|
514
652
|
waitForInputTimeout = "48h",
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
653
|
+
sandboxOps,
|
|
654
|
+
thread: threadInit,
|
|
655
|
+
sandbox: sandboxInit,
|
|
656
|
+
sandboxShutdown = "destroy"
|
|
657
|
+
}) {
|
|
658
|
+
const threadMode = threadInit?.mode ?? "new";
|
|
659
|
+
let threadId;
|
|
660
|
+
let sourceThreadId;
|
|
661
|
+
switch (threadMode) {
|
|
662
|
+
case "new":
|
|
663
|
+
threadId = threadInit?.mode === "new" && threadInit.threadId ? threadInit.threadId : getShortId();
|
|
664
|
+
break;
|
|
665
|
+
case "continue":
|
|
666
|
+
threadId = threadInit.threadId;
|
|
667
|
+
break;
|
|
668
|
+
case "fork":
|
|
669
|
+
sourceThreadId = threadInit.threadId;
|
|
670
|
+
threadId = getShortId();
|
|
671
|
+
break;
|
|
672
|
+
}
|
|
520
673
|
const {
|
|
521
674
|
appendToolResult,
|
|
522
675
|
appendHumanMessage,
|
|
@@ -525,9 +678,13 @@ var createSession = async ({
|
|
|
525
678
|
forkThread
|
|
526
679
|
} = threadOps;
|
|
527
680
|
const plugins = [];
|
|
681
|
+
let destroySubagentSandboxes;
|
|
528
682
|
if (subagents) {
|
|
529
|
-
const
|
|
530
|
-
if (
|
|
683
|
+
const result = buildSubagentRegistration(subagents);
|
|
684
|
+
if (result) {
|
|
685
|
+
plugins.push(result.registration);
|
|
686
|
+
destroySubagentSandboxes = result.destroySubagentSandboxes;
|
|
687
|
+
}
|
|
531
688
|
}
|
|
532
689
|
if (skills) {
|
|
533
690
|
const reg = buildSkillRegistration(skills);
|
|
@@ -575,12 +732,52 @@ var createSession = async ({
|
|
|
575
732
|
stateManager.run();
|
|
576
733
|
}
|
|
577
734
|
);
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
735
|
+
const sandboxMode = sandboxInit?.mode;
|
|
736
|
+
let sandboxId;
|
|
737
|
+
let sandboxOwned = false;
|
|
738
|
+
let sandboxStateUpdate;
|
|
739
|
+
if (sandboxMode === "inherit") {
|
|
740
|
+
const inheritInit = sandboxInit;
|
|
741
|
+
sandboxId = inheritInit.sandboxId;
|
|
742
|
+
if (inheritInit.stateUpdate) {
|
|
743
|
+
sandboxStateUpdate = inheritInit.stateUpdate;
|
|
744
|
+
stateManager.mergeUpdate(inheritInit.stateUpdate);
|
|
745
|
+
}
|
|
746
|
+
if (!sandboxOps) {
|
|
747
|
+
throw ApplicationFailure.create({
|
|
748
|
+
message: "sandboxId provided but no sandboxOps \u2014 cannot manage sandbox lifecycle",
|
|
749
|
+
nonRetryable: true
|
|
750
|
+
});
|
|
751
|
+
}
|
|
752
|
+
} else if (sandboxMode === "continue") {
|
|
753
|
+
if (!sandboxOps) {
|
|
754
|
+
throw ApplicationFailure.create({
|
|
755
|
+
message: "No sandboxOps provided \u2014 cannot continue sandbox",
|
|
756
|
+
nonRetryable: true
|
|
757
|
+
});
|
|
758
|
+
}
|
|
759
|
+
sandboxId = sandboxInit.sandboxId;
|
|
760
|
+
sandboxOwned = true;
|
|
761
|
+
} else if (sandboxMode === "fork") {
|
|
762
|
+
if (!sandboxOps) {
|
|
763
|
+
throw ApplicationFailure.create({
|
|
764
|
+
message: "No sandboxOps provided \u2014 cannot fork sandbox",
|
|
765
|
+
nonRetryable: true
|
|
766
|
+
});
|
|
767
|
+
}
|
|
768
|
+
sandboxId = await sandboxOps.forkSandbox(
|
|
769
|
+
sandboxInit.sandboxId
|
|
770
|
+
);
|
|
771
|
+
sandboxOwned = true;
|
|
772
|
+
} else if (sandboxOps) {
|
|
773
|
+
const skillFiles = skills ? collectSkillFiles(skills) : void 0;
|
|
774
|
+
const result = await sandboxOps.createSandbox(
|
|
775
|
+
skillFiles ? { initialFiles: skillFiles } : void 0
|
|
776
|
+
);
|
|
582
777
|
sandboxId = result.sandboxId;
|
|
778
|
+
sandboxOwned = true;
|
|
583
779
|
if (result.stateUpdate) {
|
|
780
|
+
sandboxStateUpdate = result.stateUpdate;
|
|
584
781
|
stateManager.mergeUpdate(result.stateUpdate);
|
|
585
782
|
}
|
|
586
783
|
}
|
|
@@ -592,9 +789,9 @@ var createSession = async ({
|
|
|
592
789
|
});
|
|
593
790
|
}
|
|
594
791
|
const systemPrompt = stateManager.getSystemPrompt();
|
|
595
|
-
if (
|
|
792
|
+
if (threadMode === "fork" && sourceThreadId) {
|
|
596
793
|
await forkThread(sourceThreadId, threadId);
|
|
597
|
-
} else {
|
|
794
|
+
} else if (threadMode === "continue") ; else {
|
|
598
795
|
if (appendSystemPrompt) {
|
|
599
796
|
if (!systemPrompt || systemPrompt.trim() === "") {
|
|
600
797
|
throw ApplicationFailure.create({
|
|
@@ -629,7 +826,8 @@ var createSession = async ({
|
|
|
629
826
|
threadId,
|
|
630
827
|
finalMessage: message,
|
|
631
828
|
exitReason,
|
|
632
|
-
usage: stateManager.getTotalUsage()
|
|
829
|
+
usage: stateManager.getTotalUsage(),
|
|
830
|
+
sandboxId
|
|
633
831
|
};
|
|
634
832
|
}
|
|
635
833
|
const parsedToolCalls = [];
|
|
@@ -651,7 +849,8 @@ var createSession = async ({
|
|
|
651
849
|
parsedToolCalls,
|
|
652
850
|
{
|
|
653
851
|
turn: currentTurn,
|
|
654
|
-
...sandboxId !== void 0 && { sandboxId }
|
|
852
|
+
...sandboxId !== void 0 && { sandboxId },
|
|
853
|
+
...sandboxStateUpdate && { sandboxStateUpdate }
|
|
655
854
|
}
|
|
656
855
|
);
|
|
657
856
|
for (const result of toolCallResults) {
|
|
@@ -680,30 +879,40 @@ var createSession = async ({
|
|
|
680
879
|
throw ApplicationFailure.fromError(error);
|
|
681
880
|
} finally {
|
|
682
881
|
await callSessionEnd(exitReason, stateManager.getTurns());
|
|
683
|
-
if (
|
|
684
|
-
|
|
882
|
+
if (sandboxOwned && sandboxId && sandboxOps) {
|
|
883
|
+
switch (sandboxShutdown) {
|
|
884
|
+
case "destroy":
|
|
885
|
+
await sandboxOps.destroySandbox(sandboxId);
|
|
886
|
+
break;
|
|
887
|
+
case "pause":
|
|
888
|
+
case "pause-until-parent-close":
|
|
889
|
+
await sandboxOps.pauseSandbox(sandboxId);
|
|
890
|
+
break;
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
if (destroySubagentSandboxes) {
|
|
894
|
+
await destroySubagentSandboxes();
|
|
685
895
|
}
|
|
686
896
|
}
|
|
687
897
|
return {
|
|
688
898
|
threadId,
|
|
689
899
|
finalMessage: null,
|
|
690
900
|
exitReason,
|
|
691
|
-
usage: stateManager.getTotalUsage()
|
|
901
|
+
usage: stateManager.getTotalUsage(),
|
|
902
|
+
sandboxId
|
|
692
903
|
};
|
|
693
904
|
}
|
|
694
905
|
};
|
|
695
|
-
}
|
|
906
|
+
}
|
|
696
907
|
|
|
697
908
|
// src/lib/workflow.ts
|
|
698
909
|
function defineWorkflow(config, fn) {
|
|
699
910
|
const workflow = async (input, workflowInput = {}) => {
|
|
700
911
|
const sessionInput = {
|
|
701
912
|
agentName: config.name,
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
},
|
|
706
|
-
...workflowInput.sandboxId && { sandboxId: workflowInput.sandboxId }
|
|
913
|
+
sandboxShutdown: config.sandboxShutdown ?? "destroy",
|
|
914
|
+
...workflowInput.thread && { thread: workflowInput.thread },
|
|
915
|
+
...workflowInput.sandbox && { sandbox: workflowInput.sandbox }
|
|
707
916
|
};
|
|
708
917
|
return fn(input, sessionInput);
|
|
709
918
|
};
|
|
@@ -884,19 +1093,55 @@ function defineSubagent(definition, overrides) {
|
|
|
884
1093
|
...overrides
|
|
885
1094
|
};
|
|
886
1095
|
}
|
|
887
|
-
|
|
888
|
-
// src/lib/subagent/workflow.ts
|
|
889
1096
|
function defineSubagentWorkflow(config, fn) {
|
|
890
1097
|
const workflow = async (prompt, workflowInput, context) => {
|
|
1098
|
+
const effectiveShutdown = workflowInput.sandboxShutdown ?? config.sandboxShutdown ?? "destroy";
|
|
891
1099
|
const sessionInput = {
|
|
892
1100
|
agentName: config.name,
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
},
|
|
897
|
-
...workflowInput.sandboxId && { sandboxId: workflowInput.sandboxId }
|
|
1101
|
+
sandboxShutdown: effectiveShutdown,
|
|
1102
|
+
...workflowInput.thread && { thread: workflowInput.thread },
|
|
1103
|
+
...workflowInput.sandbox && { sandbox: workflowInput.sandbox }
|
|
898
1104
|
};
|
|
899
|
-
|
|
1105
|
+
const { destroySandbox, ...result } = await fn(
|
|
1106
|
+
prompt,
|
|
1107
|
+
sessionInput,
|
|
1108
|
+
context ?? {}
|
|
1109
|
+
);
|
|
1110
|
+
if (effectiveShutdown === "pause-until-parent-close") {
|
|
1111
|
+
if (!destroySandbox) {
|
|
1112
|
+
throw ApplicationFailure.create({
|
|
1113
|
+
message: `Subagent "${config.name}" has sandboxShutdown="pause-until-parent-close" but fn did not return a destroySandbox callback`,
|
|
1114
|
+
nonRetryable: true
|
|
1115
|
+
});
|
|
1116
|
+
}
|
|
1117
|
+
if (!result.sandboxId) {
|
|
1118
|
+
throw ApplicationFailure.create({
|
|
1119
|
+
message: `Subagent "${config.name}" has sandboxShutdown="pause-until-parent-close" but fn did not return a sandboxId`,
|
|
1120
|
+
nonRetryable: true
|
|
1121
|
+
});
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
const { parent } = workflowInfo();
|
|
1125
|
+
if (!parent) {
|
|
1126
|
+
throw ApplicationFailure.create({
|
|
1127
|
+
message: "Subagent workflow called without a parent workflow",
|
|
1128
|
+
nonRetryable: true
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
const parentHandle = getExternalWorkflowHandle(parent.workflowId);
|
|
1132
|
+
await parentHandle.signal(childResultSignal, {
|
|
1133
|
+
childWorkflowId: workflowInfo().workflowId,
|
|
1134
|
+
result
|
|
1135
|
+
});
|
|
1136
|
+
if (destroySandbox) {
|
|
1137
|
+
let destroyRequested = false;
|
|
1138
|
+
setHandler(destroySandboxSignal, () => {
|
|
1139
|
+
destroyRequested = true;
|
|
1140
|
+
});
|
|
1141
|
+
await condition(() => destroyRequested);
|
|
1142
|
+
await destroySandbox();
|
|
1143
|
+
}
|
|
1144
|
+
return result;
|
|
900
1145
|
};
|
|
901
1146
|
Object.defineProperty(workflow, "name", { value: config.name });
|
|
902
1147
|
return Object.assign(workflow, {
|