zeitlich 0.2.21 → 0.2.23
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 +303 -105
- package/dist/adapters/sandbox/daytona/index.cjs +7 -1
- package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
- package/dist/adapters/sandbox/daytona/index.d.cts +3 -1
- package/dist/adapters/sandbox/daytona/index.d.ts +3 -1
- package/dist/adapters/sandbox/daytona/index.js +7 -1
- package/dist/adapters/sandbox/daytona/index.js.map +1 -1
- package/dist/adapters/sandbox/daytona/workflow.cjs +33 -0
- package/dist/adapters/sandbox/daytona/workflow.cjs.map +1 -0
- package/dist/adapters/sandbox/daytona/workflow.d.cts +27 -0
- package/dist/adapters/sandbox/daytona/workflow.d.ts +27 -0
- package/dist/adapters/sandbox/daytona/workflow.js +31 -0
- package/dist/adapters/sandbox/daytona/workflow.js.map +1 -0
- package/dist/adapters/sandbox/inmemory/index.cjs +18 -1
- package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.d.cts +4 -2
- package/dist/adapters/sandbox/inmemory/index.d.ts +4 -2
- package/dist/adapters/sandbox/inmemory/index.js +18 -1
- package/dist/adapters/sandbox/inmemory/index.js.map +1 -1
- package/dist/adapters/sandbox/inmemory/workflow.cjs +33 -0
- package/dist/adapters/sandbox/inmemory/workflow.cjs.map +1 -0
- package/dist/adapters/sandbox/inmemory/workflow.d.cts +25 -0
- package/dist/adapters/sandbox/inmemory/workflow.d.ts +25 -0
- package/dist/adapters/sandbox/inmemory/workflow.js +31 -0
- package/dist/adapters/sandbox/inmemory/workflow.js.map +1 -0
- package/dist/adapters/sandbox/virtual/index.cjs +36 -9
- package/dist/adapters/sandbox/virtual/index.cjs.map +1 -1
- package/dist/adapters/sandbox/virtual/index.d.cts +8 -5
- package/dist/adapters/sandbox/virtual/index.d.ts +8 -5
- package/dist/adapters/sandbox/virtual/index.js +36 -9
- package/dist/adapters/sandbox/virtual/index.js.map +1 -1
- package/dist/adapters/sandbox/virtual/workflow.cjs +33 -0
- package/dist/adapters/sandbox/virtual/workflow.cjs.map +1 -0
- package/dist/adapters/sandbox/virtual/workflow.d.cts +27 -0
- package/dist/adapters/sandbox/virtual/workflow.d.ts +27 -0
- package/dist/adapters/sandbox/virtual/workflow.js +31 -0
- package/dist/adapters/sandbox/virtual/workflow.js.map +1 -0
- package/dist/adapters/thread/google-genai/index.cjs +9 -1
- package/dist/adapters/thread/google-genai/index.cjs.map +1 -1
- package/dist/adapters/thread/google-genai/index.d.cts +31 -19
- package/dist/adapters/thread/google-genai/index.d.ts +31 -19
- package/dist/adapters/thread/google-genai/index.js +9 -1
- package/dist/adapters/thread/google-genai/index.js.map +1 -1
- package/dist/adapters/thread/google-genai/workflow.cjs +33 -0
- package/dist/adapters/thread/google-genai/workflow.cjs.map +1 -0
- package/dist/adapters/thread/google-genai/workflow.d.cts +32 -0
- package/dist/adapters/thread/google-genai/workflow.d.ts +32 -0
- package/dist/adapters/thread/google-genai/workflow.js +31 -0
- package/dist/adapters/thread/google-genai/workflow.js.map +1 -0
- package/dist/adapters/thread/langchain/index.cjs +9 -1
- package/dist/adapters/thread/langchain/index.cjs.map +1 -1
- package/dist/adapters/thread/langchain/index.d.cts +27 -16
- package/dist/adapters/thread/langchain/index.d.ts +27 -16
- package/dist/adapters/thread/langchain/index.js +9 -1
- package/dist/adapters/thread/langchain/index.js.map +1 -1
- package/dist/adapters/thread/langchain/workflow.cjs +33 -0
- package/dist/adapters/thread/langchain/workflow.cjs.map +1 -0
- package/dist/adapters/thread/langchain/workflow.d.cts +32 -0
- package/dist/adapters/thread/langchain/workflow.d.ts +32 -0
- package/dist/adapters/thread/langchain/workflow.js +31 -0
- package/dist/adapters/thread/langchain/workflow.js.map +1 -0
- package/dist/index.cjs +282 -90
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -16
- package/dist/index.d.ts +38 -16
- package/dist/index.js +281 -87
- package/dist/index.js.map +1 -1
- package/dist/queries-DModcWRy.d.cts +44 -0
- package/dist/queries-byD0jr1Y.d.ts +44 -0
- package/dist/{types-BkAYmc96.d.ts → types-B50pBPEV.d.ts} +190 -38
- package/dist/{types-YbL7JpEA.d.cts → types-Bll19FZJ.d.cts} +7 -0
- package/dist/{types-YbL7JpEA.d.ts → types-Bll19FZJ.d.ts} +7 -0
- package/dist/{queries-6Avfh74U.d.ts → types-BuXdFhaZ.d.cts} +7 -48
- package/dist/{types-BMRzfELQ.d.cts → types-ChAMwU3q.d.cts} +17 -1
- package/dist/{types-BMRzfELQ.d.ts → types-ChAMwU3q.d.ts} +17 -1
- package/dist/{types-CES_30qx.d.cts → types-DQW8l7pY.d.cts} +190 -38
- package/dist/{queries-CHa2iv_I.d.cts → types-GZ76HZSj.d.ts} +7 -48
- package/dist/workflow.cjs +244 -86
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +54 -65
- package/dist/workflow.d.ts +54 -65
- package/dist/workflow.js +243 -83
- package/dist/workflow.js.map +1 -1
- package/package.json +54 -2
- package/src/adapters/sandbox/daytona/filesystem.ts +1 -1
- package/src/adapters/sandbox/daytona/index.ts +8 -0
- package/src/adapters/sandbox/daytona/proxy.ts +56 -0
- package/src/adapters/sandbox/e2b/filesystem.ts +147 -0
- package/src/adapters/sandbox/e2b/index.ts +164 -0
- package/src/adapters/sandbox/e2b/types.ts +23 -0
- package/src/adapters/sandbox/inmemory/index.ts +27 -3
- package/src/adapters/sandbox/inmemory/proxy.ts +53 -0
- package/src/adapters/sandbox/virtual/filesystem.ts +41 -17
- package/src/adapters/sandbox/virtual/provider.ts +9 -1
- package/src/adapters/sandbox/virtual/proxy.ts +53 -0
- package/src/adapters/sandbox/virtual/types.ts +9 -4
- package/src/adapters/thread/google-genai/activities.ts +51 -17
- package/src/adapters/thread/google-genai/index.ts +1 -0
- package/src/adapters/thread/google-genai/proxy.ts +61 -0
- package/src/adapters/thread/langchain/activities.ts +47 -14
- package/src/adapters/thread/langchain/index.ts +1 -0
- package/src/adapters/thread/langchain/proxy.ts +61 -0
- package/src/lib/lifecycle.ts +57 -0
- package/src/lib/sandbox/manager.ts +52 -6
- package/src/lib/sandbox/sandbox.test.ts +12 -11
- package/src/lib/sandbox/types.ts +31 -4
- package/src/lib/session/index.ts +4 -5
- package/src/lib/session/session-edge-cases.integration.test.ts +491 -66
- package/src/lib/session/session.integration.test.ts +92 -80
- package/src/lib/session/session.ts +108 -96
- package/src/lib/session/types.ts +87 -17
- package/src/lib/subagent/define.ts +6 -5
- package/src/lib/subagent/handler.ts +148 -16
- package/src/lib/subagent/index.ts +4 -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 +893 -128
- package/src/lib/subagent/tool.ts +2 -2
- package/src/lib/subagent/types.ts +84 -21
- package/src/lib/subagent/workflow.ts +83 -12
- package/src/lib/tool-router/router-edge-cases.integration.test.ts +4 -1
- package/src/lib/tool-router/router.integration.test.ts +141 -5
- package/src/lib/tool-router/router.ts +13 -3
- package/src/lib/tool-router/types.ts +7 -0
- package/src/lib/workflow.test.ts +104 -27
- package/src/lib/workflow.ts +37 -19
- package/src/tools/bash/bash.test.ts +16 -7
- package/src/workflow.ts +11 -14
- package/tsup.config.ts +6 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { workflowInfo, proxyActivities } from '@temporalio/workflow';
|
|
2
|
+
|
|
3
|
+
// src/adapters/thread/langchain/proxy.ts
|
|
4
|
+
var ADAPTER_PREFIX = "langChain";
|
|
5
|
+
function proxyLangChainThreadOps(scope, options) {
|
|
6
|
+
const resolvedScope = scope ?? workflowInfo().workflowType;
|
|
7
|
+
const acts = proxyActivities(
|
|
8
|
+
options ?? {
|
|
9
|
+
startToCloseTimeout: "10s",
|
|
10
|
+
retry: {
|
|
11
|
+
maximumAttempts: 6,
|
|
12
|
+
initialInterval: "5s",
|
|
13
|
+
maximumInterval: "15m",
|
|
14
|
+
backoffCoefficient: 4
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
);
|
|
18
|
+
const prefix = `${ADAPTER_PREFIX}${resolvedScope.charAt(0).toUpperCase()}${resolvedScope.slice(1)}`;
|
|
19
|
+
const p = (key) => `${prefix}${key.charAt(0).toUpperCase()}${key.slice(1)}`;
|
|
20
|
+
return {
|
|
21
|
+
initializeThread: acts[p("initializeThread")],
|
|
22
|
+
appendHumanMessage: acts[p("appendHumanMessage")],
|
|
23
|
+
appendToolResult: acts[p("appendToolResult")],
|
|
24
|
+
appendSystemMessage: acts[p("appendSystemMessage")],
|
|
25
|
+
forkThread: acts[p("forkThread")]
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export { proxyLangChainThreadOps };
|
|
30
|
+
//# sourceMappingURL=workflow.js.map
|
|
31
|
+
//# sourceMappingURL=workflow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/adapters/thread/langchain/proxy.ts"],"names":[],"mappings":";;;AA2BA,IAAM,cAAA,GAAiB,WAAA;AAEhB,SAAS,uBAAA,CACd,OACA,OAAA,EACiC;AACjC,EAAA,MAAM,aAAA,GAAgB,KAAA,IAAS,YAAA,EAAa,CAAE,YAAA;AAG9C,EAAA,MAAM,IAAA,GAAO,eAAA;AAAA,IACX,OAAA,IAAW;AAAA,MACT,mBAAA,EAAqB,KAAA;AAAA,MACrB,KAAA,EAAO;AAAA,QACL,eAAA,EAAiB,CAAA;AAAA,QACjB,eAAA,EAAiB,IAAA;AAAA,QACjB,eAAA,EAAiB,KAAA;AAAA,QACjB,kBAAA,EAAoB;AAAA;AACtB;AACF,GACF;AAEA,EAAA,MAAM,MAAA,GACJ,CAAA,EAAG,cAAc,CAAA,EAAG,cAAc,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,EAAa,CAAA,EAAG,aAAA,CAAc,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AACpF,EAAA,MAAM,IAAI,CAAC,GAAA,KACT,CAAA,EAAG,MAAM,GAAG,GAAA,CAAI,MAAA,CAAO,CAAC,CAAA,CAAE,aAAa,CAAA,EAAG,GAAA,CAAI,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA;AAExD,EAAA,OAAO;AAAA,IACL,gBAAA,EAAkB,IAAA,CAAK,CAAA,CAAE,kBAAkB,CAAC,CAAA;AAAA,IAC5C,kBAAA,EAAoB,IAAA,CAAK,CAAA,CAAE,oBAAoB,CAAC,CAAA;AAAA,IAChD,gBAAA,EAAkB,IAAA,CAAK,CAAA,CAAE,kBAAkB,CAAC,CAAA;AAAA,IAC5C,mBAAA,EAAqB,IAAA,CAAK,CAAA,CAAE,qBAAqB,CAAC,CAAA;AAAA,IAClD,UAAA,EAAY,IAAA,CAAK,CAAA,CAAE,YAAY,CAAC;AAAA,GAClC;AACF","file":"workflow.js","sourcesContent":["/**\n * Workflow-safe proxy for LangChain thread operations.\n *\n * Import this from `zeitlich/adapters/thread/langchain/workflow`\n * in your Temporal workflow files.\n *\n * By default the scope is derived from `workflowInfo().workflowType`,\n * so activities are automatically namespaced per workflow.\n *\n * @example\n * ```typescript\n * import { proxyLangChainThreadOps } from 'zeitlich/adapters/thread/langchain/workflow';\n *\n * // Auto-scoped to the current workflow name\n * const threadOps = proxyLangChainThreadOps();\n *\n * // Explicit scope override\n * const threadOps = proxyLangChainThreadOps(\"customScope\");\n * ```\n */\nimport {\n proxyActivities,\n workflowInfo,\n type ActivityInterfaceFor,\n} from \"@temporalio/workflow\";\nimport type { ThreadOps } from \"../../../lib/session/types\";\n\nconst ADAPTER_PREFIX = \"langChain\";\n\nexport function proxyLangChainThreadOps(\n scope?: string,\n options?: Parameters<typeof proxyActivities>[0]\n): ActivityInterfaceFor<ThreadOps> {\n const resolvedScope = scope ?? workflowInfo().workflowType;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const acts = proxyActivities<Record<string, (...args: any[]) => any>>(\n options ?? {\n startToCloseTimeout: \"10s\",\n retry: {\n maximumAttempts: 6,\n initialInterval: \"5s\",\n maximumInterval: \"15m\",\n backoffCoefficient: 4,\n },\n }\n );\n\n const prefix =\n `${ADAPTER_PREFIX}${resolvedScope.charAt(0).toUpperCase()}${resolvedScope.slice(1)}`;\n const p = (key: string): string =>\n `${prefix}${key.charAt(0).toUpperCase()}${key.slice(1)}`;\n\n return {\n initializeThread: acts[p(\"initializeThread\")],\n appendHumanMessage: acts[p(\"appendHumanMessage\")],\n appendToolResult: acts[p(\"appendToolResult\")],\n appendSystemMessage: acts[p(\"appendSystemMessage\")],\n forkThread: acts[p(\"forkThread\")],\n } as ActivityInterfaceFor<ThreadOps>;\n}\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -88,7 +88,12 @@ function createToolRouter(options) {
|
|
|
88
88
|
result: { error: errorStr, suppressed: true }
|
|
89
89
|
};
|
|
90
90
|
}
|
|
91
|
-
|
|
91
|
+
return {
|
|
92
|
+
content: JSON.stringify({
|
|
93
|
+
error: "The tool encountered an error. Please try again or use a different approach."
|
|
94
|
+
}),
|
|
95
|
+
result: { error: errorStr, suppressed: true }
|
|
96
|
+
};
|
|
92
97
|
}
|
|
93
98
|
async function runPostHooks(toolCall, tool, toolResult, effectiveArgs, turn, durationMs) {
|
|
94
99
|
if (tool?.hooks?.onPostToolUse) {
|
|
@@ -97,7 +102,8 @@ function createToolRouter(options) {
|
|
|
97
102
|
result: toolResult.data,
|
|
98
103
|
threadId: options.threadId,
|
|
99
104
|
turn,
|
|
100
|
-
durationMs
|
|
105
|
+
durationMs,
|
|
106
|
+
...toolResult.metadata && { metadata: toolResult.metadata }
|
|
101
107
|
});
|
|
102
108
|
}
|
|
103
109
|
if (options.hooks?.onPostToolUse) {
|
|
@@ -130,6 +136,7 @@ function createToolRouter(options) {
|
|
|
130
136
|
let result;
|
|
131
137
|
let content;
|
|
132
138
|
let resultAppended = false;
|
|
139
|
+
let metadata;
|
|
133
140
|
try {
|
|
134
141
|
if (tool) {
|
|
135
142
|
const routerContext = {
|
|
@@ -145,6 +152,7 @@ function createToolRouter(options) {
|
|
|
145
152
|
result = response.data;
|
|
146
153
|
content = response.toolResponse;
|
|
147
154
|
resultAppended = response.resultAppended === true;
|
|
155
|
+
metadata = response.metadata;
|
|
148
156
|
} else {
|
|
149
157
|
result = { error: `Unknown tool: ${toolCall.name}` };
|
|
150
158
|
content = JSON.stringify(result, null, 2);
|
|
@@ -177,7 +185,8 @@ function createToolRouter(options) {
|
|
|
177
185
|
const toolResult = {
|
|
178
186
|
toolCallId: toolCall.id,
|
|
179
187
|
name: toolCall.name,
|
|
180
|
-
data: result
|
|
188
|
+
data: result,
|
|
189
|
+
...metadata && { metadata }
|
|
181
190
|
};
|
|
182
191
|
await runPostHooks(
|
|
183
192
|
toolCall,
|
|
@@ -281,7 +290,8 @@ function createToolRouter(options) {
|
|
|
281
290
|
return {
|
|
282
291
|
toolCallId: toolCall.id,
|
|
283
292
|
name: toolCall.name,
|
|
284
|
-
data: response.data
|
|
293
|
+
data: response.data,
|
|
294
|
+
...response.metadata && { metadata: response.metadata }
|
|
285
295
|
};
|
|
286
296
|
};
|
|
287
297
|
if (options.parallel) {
|
|
@@ -325,7 +335,7 @@ function getShortId(length = 12) {
|
|
|
325
335
|
var SUBAGENT_TOOL_NAME = "Subagent";
|
|
326
336
|
function buildSubagentDescription(subagents) {
|
|
327
337
|
const subagentList = subagents.map((s) => {
|
|
328
|
-
const continuation = s.
|
|
338
|
+
const continuation = s.thread && s.thread !== "new" ? "\n*(Supports thread continuation \u2014 pass a threadId to resume a previous conversation)*" : "";
|
|
329
339
|
return `## ${s.agentName}
|
|
330
340
|
${s.description}${continuation}`;
|
|
331
341
|
}).join("\n\n");
|
|
@@ -341,7 +351,7 @@ function createSubagentTool(subagents) {
|
|
|
341
351
|
}
|
|
342
352
|
const names = subagents.map((s) => s.agentName);
|
|
343
353
|
const hasThreadContinuation = subagents.some(
|
|
344
|
-
(s) => s.
|
|
354
|
+
(s) => s.thread && s.thread !== "new"
|
|
345
355
|
);
|
|
346
356
|
const baseFields = {
|
|
347
357
|
subagent: z14__default.default.enum(names).describe("The type of subagent to launch"),
|
|
@@ -360,9 +370,25 @@ function createSubagentTool(subagents) {
|
|
|
360
370
|
schema
|
|
361
371
|
};
|
|
362
372
|
}
|
|
373
|
+
var childResultSignal = workflow.defineSignal("childResult");
|
|
374
|
+
var destroySandboxSignal = workflow.defineSignal("destroySandbox");
|
|
375
|
+
|
|
376
|
+
// src/lib/subagent/handler.ts
|
|
377
|
+
function resolveSandboxConfig(config) {
|
|
378
|
+
if (!config || config === "none") return { source: "none" };
|
|
379
|
+
if (config === "inherit") return { source: "inherit" };
|
|
380
|
+
if (config === "own") return { source: "own" };
|
|
381
|
+
return { source: "own", shutdown: config.shutdown };
|
|
382
|
+
}
|
|
363
383
|
function createSubagentHandler(subagents) {
|
|
364
384
|
const { taskQueue: parentTaskQueue } = workflow.workflowInfo();
|
|
365
|
-
|
|
385
|
+
const childResults = /* @__PURE__ */ new Map();
|
|
386
|
+
const pendingDestroys = /* @__PURE__ */ new Map();
|
|
387
|
+
const threadSandboxes = /* @__PURE__ */ new Map();
|
|
388
|
+
workflow.setHandler(childResultSignal, ({ childWorkflowId, result }) => {
|
|
389
|
+
childResults.set(childWorkflowId, result);
|
|
390
|
+
});
|
|
391
|
+
const handler = async (args, context) => {
|
|
366
392
|
const config = subagents.find((s) => s.agentName === args.subagent);
|
|
367
393
|
if (!config) {
|
|
368
394
|
throw new Error(
|
|
@@ -371,29 +397,77 @@ function createSubagentHandler(subagents) {
|
|
|
371
397
|
}
|
|
372
398
|
const childWorkflowId = `${args.subagent}-${getShortId()}`;
|
|
373
399
|
const { sandboxId: parentSandboxId } = context;
|
|
374
|
-
const
|
|
400
|
+
const sandboxCfg = resolveSandboxConfig(config.sandbox);
|
|
401
|
+
if (sandboxCfg.source === "inherit" && !parentSandboxId) {
|
|
402
|
+
throw new Error(
|
|
403
|
+
`Subagent "${config.agentName}" is configured with sandbox: "inherit" but the parent has no sandbox`
|
|
404
|
+
);
|
|
405
|
+
}
|
|
406
|
+
const threadMode = config.thread ?? "new";
|
|
407
|
+
const allowsContinuation = threadMode !== "new";
|
|
408
|
+
const continuationThreadId = args.threadId && allowsContinuation ? args.threadId : void 0;
|
|
409
|
+
let thread;
|
|
410
|
+
if (continuationThreadId) {
|
|
411
|
+
thread = { mode: threadMode, threadId: continuationThreadId };
|
|
412
|
+
}
|
|
413
|
+
let sandbox;
|
|
414
|
+
if (sandboxCfg.source === "inherit" && parentSandboxId) {
|
|
415
|
+
sandbox = { mode: "inherit", sandboxId: parentSandboxId };
|
|
416
|
+
} else if (sandboxCfg.source === "own") {
|
|
417
|
+
const prevSbId = continuationThreadId ? threadSandboxes.get(continuationThreadId) : void 0;
|
|
418
|
+
if (prevSbId) {
|
|
419
|
+
sandbox = { mode: "fork", sandboxId: prevSbId };
|
|
420
|
+
}
|
|
421
|
+
}
|
|
375
422
|
const workflowInput = {
|
|
376
|
-
...
|
|
377
|
-
|
|
378
|
-
}
|
|
379
|
-
...inheritSandbox && { sandboxId: parentSandboxId }
|
|
423
|
+
...thread && { thread },
|
|
424
|
+
...sandbox && { sandbox },
|
|
425
|
+
...sandboxCfg.shutdown && { sandboxShutdown: sandboxCfg.shutdown }
|
|
380
426
|
};
|
|
427
|
+
const resolvedContext = config.context === void 0 ? void 0 : typeof config.context === "function" ? config.context() : config.context;
|
|
381
428
|
const childOpts = {
|
|
382
429
|
workflowId: childWorkflowId,
|
|
383
|
-
args:
|
|
430
|
+
args: resolvedContext === void 0 ? [args.prompt, workflowInput] : [args.prompt, workflowInput, resolvedContext],
|
|
384
431
|
taskQueue: config.taskQueue ?? parentTaskQueue
|
|
385
432
|
};
|
|
433
|
+
const childHandle = await workflow.startChild(config.workflow, childOpts);
|
|
434
|
+
const usesOwnSandbox = sandboxCfg.source === "own" || allowsContinuation && sandboxCfg.source !== "inherit";
|
|
435
|
+
if (usesOwnSandbox) {
|
|
436
|
+
pendingDestroys.set(childWorkflowId, childHandle);
|
|
437
|
+
}
|
|
438
|
+
await Promise.race([
|
|
439
|
+
workflow.condition(() => childResults.has(childWorkflowId)),
|
|
440
|
+
childHandle.result()
|
|
441
|
+
]);
|
|
442
|
+
if (!childResults.has(childWorkflowId)) {
|
|
443
|
+
await workflow.condition(() => childResults.has(childWorkflowId));
|
|
444
|
+
}
|
|
445
|
+
const childResult = childResults.get(childWorkflowId);
|
|
446
|
+
childResults.delete(childWorkflowId);
|
|
447
|
+
if (!childResult) {
|
|
448
|
+
return {
|
|
449
|
+
toolResponse: "Subagent workflow did not signal a result",
|
|
450
|
+
data: null
|
|
451
|
+
};
|
|
452
|
+
}
|
|
386
453
|
const {
|
|
387
454
|
toolResponse,
|
|
388
455
|
data,
|
|
389
456
|
usage,
|
|
390
|
-
threadId: childThreadId
|
|
391
|
-
|
|
457
|
+
threadId: childThreadId,
|
|
458
|
+
sandboxId: childSandboxId,
|
|
459
|
+
metadata
|
|
460
|
+
} = childResult;
|
|
461
|
+
if (allowsContinuation && childSandboxId && childThreadId) {
|
|
462
|
+
threadSandboxes.set(childThreadId, childSandboxId);
|
|
463
|
+
}
|
|
392
464
|
if (!toolResponse) {
|
|
393
465
|
return {
|
|
394
466
|
toolResponse: "Subagent workflow returned no response",
|
|
395
467
|
data: null,
|
|
396
|
-
...usage && { usage }
|
|
468
|
+
...usage && { usage },
|
|
469
|
+
...childSandboxId && { sandboxId: childSandboxId },
|
|
470
|
+
...metadata && { metadata }
|
|
397
471
|
};
|
|
398
472
|
}
|
|
399
473
|
const validated = config.resultSchema ? config.resultSchema.safeParse(data) : null;
|
|
@@ -401,11 +475,13 @@ function createSubagentHandler(subagents) {
|
|
|
401
475
|
return {
|
|
402
476
|
toolResponse: `Subagent workflow returned invalid data: ${validated.error.message}`,
|
|
403
477
|
data: null,
|
|
404
|
-
...usage && { usage }
|
|
478
|
+
...usage && { usage },
|
|
479
|
+
...childSandboxId && { sandboxId: childSandboxId },
|
|
480
|
+
...metadata && { metadata }
|
|
405
481
|
};
|
|
406
482
|
}
|
|
407
483
|
let finalToolResponse = toolResponse;
|
|
408
|
-
if (
|
|
484
|
+
if (allowsContinuation && childThreadId) {
|
|
409
485
|
finalToolResponse = typeof toolResponse === "string" ? `${toolResponse}
|
|
410
486
|
|
|
411
487
|
[${config.agentName} Thread ID: ${childThreadId}]` : toolResponse;
|
|
@@ -413,9 +489,22 @@ function createSubagentHandler(subagents) {
|
|
|
413
489
|
return {
|
|
414
490
|
toolResponse: finalToolResponse,
|
|
415
491
|
data: validated ? validated.data : data,
|
|
416
|
-
...usage && { usage }
|
|
492
|
+
...usage && { usage },
|
|
493
|
+
...childSandboxId && { sandboxId: childSandboxId },
|
|
494
|
+
...metadata && { metadata }
|
|
417
495
|
};
|
|
418
496
|
};
|
|
497
|
+
const destroySubagentSandboxes = async () => {
|
|
498
|
+
const handles = [...pendingDestroys.values()];
|
|
499
|
+
pendingDestroys.clear();
|
|
500
|
+
await Promise.all(
|
|
501
|
+
handles.map(async (handle) => {
|
|
502
|
+
await handle.signal(destroySandboxSignal);
|
|
503
|
+
await handle.result();
|
|
504
|
+
})
|
|
505
|
+
);
|
|
506
|
+
};
|
|
507
|
+
return { handler, destroySubagentSandboxes };
|
|
419
508
|
}
|
|
420
509
|
|
|
421
510
|
// src/lib/subagent/register.ts
|
|
@@ -429,12 +518,13 @@ function buildSubagentRegistration(subagents) {
|
|
|
429
518
|
if (s.hooks) subagentHooksMap.set(s.agentName, s.hooks);
|
|
430
519
|
}
|
|
431
520
|
const resolveSubagentName = (args) => args.subagent;
|
|
432
|
-
|
|
521
|
+
const { handler, destroySubagentSandboxes } = createSubagentHandler(subagents);
|
|
522
|
+
const registration = {
|
|
433
523
|
name: SUBAGENT_TOOL_NAME,
|
|
434
524
|
enabled: () => getEnabled().length > 0,
|
|
435
525
|
description: () => createSubagentTool(getEnabled()).description,
|
|
436
526
|
schema: () => createSubagentTool(getEnabled()).schema,
|
|
437
|
-
handler
|
|
527
|
+
handler,
|
|
438
528
|
...subagentHooksMap.size > 0 && {
|
|
439
529
|
hooks: {
|
|
440
530
|
onPreToolUse: async (ctx) => {
|
|
@@ -452,6 +542,7 @@ function buildSubagentRegistration(subagents) {
|
|
|
452
542
|
}
|
|
453
543
|
}
|
|
454
544
|
};
|
|
545
|
+
return { registration, destroySubagentSandboxes };
|
|
455
546
|
}
|
|
456
547
|
var READ_SKILL_TOOL_NAME = "ReadSkill";
|
|
457
548
|
function buildReadSkillDescription(skills) {
|
|
@@ -504,8 +595,7 @@ function buildSkillRegistration(skills) {
|
|
|
504
595
|
handler: createReadSkillHandler(skills)
|
|
505
596
|
};
|
|
506
597
|
}
|
|
507
|
-
|
|
508
|
-
threadId: providedThreadId,
|
|
598
|
+
async function createSession({
|
|
509
599
|
agentName,
|
|
510
600
|
maxTurns = 50,
|
|
511
601
|
metadata = {},
|
|
@@ -518,24 +608,42 @@ var createSession = async ({
|
|
|
518
608
|
processToolsInParallel = true,
|
|
519
609
|
hooks = {},
|
|
520
610
|
appendSystemPrompt = true,
|
|
521
|
-
continueThread = false,
|
|
522
611
|
waitForInputTimeout = "48h",
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
612
|
+
sandboxOps,
|
|
613
|
+
thread: threadInit,
|
|
614
|
+
sandbox: sandboxInit,
|
|
615
|
+
sandboxShutdown = "destroy"
|
|
616
|
+
}) {
|
|
617
|
+
const threadMode = threadInit?.mode ?? "new";
|
|
618
|
+
let threadId;
|
|
619
|
+
let sourceThreadId;
|
|
620
|
+
switch (threadMode) {
|
|
621
|
+
case "new":
|
|
622
|
+
threadId = threadInit?.mode === "new" && threadInit.threadId ? threadInit.threadId : getShortId();
|
|
623
|
+
break;
|
|
624
|
+
case "continue":
|
|
625
|
+
threadId = threadInit.threadId;
|
|
626
|
+
break;
|
|
627
|
+
case "fork":
|
|
628
|
+
sourceThreadId = threadInit.threadId;
|
|
629
|
+
threadId = getShortId();
|
|
630
|
+
break;
|
|
631
|
+
}
|
|
528
632
|
const {
|
|
529
633
|
appendToolResult,
|
|
530
634
|
appendHumanMessage,
|
|
531
635
|
initializeThread,
|
|
532
636
|
appendSystemMessage,
|
|
533
637
|
forkThread
|
|
534
|
-
} = threadOps
|
|
638
|
+
} = threadOps;
|
|
535
639
|
const plugins = [];
|
|
640
|
+
let destroySubagentSandboxes;
|
|
536
641
|
if (subagents) {
|
|
537
|
-
const
|
|
538
|
-
if (
|
|
642
|
+
const result = buildSubagentRegistration(subagents);
|
|
643
|
+
if (result) {
|
|
644
|
+
plugins.push(result.registration);
|
|
645
|
+
destroySubagentSandboxes = result.destroySubagentSandboxes;
|
|
646
|
+
}
|
|
539
647
|
}
|
|
540
648
|
if (skills) {
|
|
541
649
|
const reg = buildSkillRegistration(skills);
|
|
@@ -583,11 +691,41 @@ var createSession = async ({
|
|
|
583
691
|
stateManager.run();
|
|
584
692
|
}
|
|
585
693
|
);
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
694
|
+
const sandboxMode = sandboxInit?.mode;
|
|
695
|
+
let sandboxId;
|
|
696
|
+
let sandboxOwned = false;
|
|
697
|
+
if (sandboxMode === "inherit") {
|
|
698
|
+
sandboxId = sandboxInit.sandboxId;
|
|
699
|
+
if (!sandboxOps) {
|
|
700
|
+
throw workflow.ApplicationFailure.create({
|
|
701
|
+
message: "sandboxId provided but no sandboxOps \u2014 cannot manage sandbox lifecycle",
|
|
702
|
+
nonRetryable: true
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
} else if (sandboxMode === "continue") {
|
|
706
|
+
if (!sandboxOps) {
|
|
707
|
+
throw workflow.ApplicationFailure.create({
|
|
708
|
+
message: "No sandboxOps provided \u2014 cannot continue sandbox",
|
|
709
|
+
nonRetryable: true
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
sandboxId = sandboxInit.sandboxId;
|
|
713
|
+
sandboxOwned = true;
|
|
714
|
+
} else if (sandboxMode === "fork") {
|
|
715
|
+
if (!sandboxOps) {
|
|
716
|
+
throw workflow.ApplicationFailure.create({
|
|
717
|
+
message: "No sandboxOps provided \u2014 cannot fork sandbox",
|
|
718
|
+
nonRetryable: true
|
|
719
|
+
});
|
|
720
|
+
}
|
|
721
|
+
sandboxId = await sandboxOps.forkSandbox(
|
|
722
|
+
sandboxInit.sandboxId
|
|
723
|
+
);
|
|
724
|
+
sandboxOwned = true;
|
|
725
|
+
} else if (sandboxOps) {
|
|
726
|
+
const result = await sandboxOps.createSandbox();
|
|
590
727
|
sandboxId = result.sandboxId;
|
|
728
|
+
sandboxOwned = true;
|
|
591
729
|
if (result.stateUpdate) {
|
|
592
730
|
stateManager.mergeUpdate(result.stateUpdate);
|
|
593
731
|
}
|
|
@@ -600,9 +738,9 @@ var createSession = async ({
|
|
|
600
738
|
});
|
|
601
739
|
}
|
|
602
740
|
const systemPrompt = stateManager.getSystemPrompt();
|
|
603
|
-
if (
|
|
741
|
+
if (threadMode === "fork" && sourceThreadId) {
|
|
604
742
|
await forkThread(sourceThreadId, threadId);
|
|
605
|
-
} else {
|
|
743
|
+
} else if (threadMode === "continue") ; else {
|
|
606
744
|
if (appendSystemPrompt) {
|
|
607
745
|
if (!systemPrompt || systemPrompt.trim() === "") {
|
|
608
746
|
throw workflow.ApplicationFailure.create({
|
|
@@ -637,7 +775,8 @@ var createSession = async ({
|
|
|
637
775
|
threadId,
|
|
638
776
|
finalMessage: message,
|
|
639
777
|
exitReason,
|
|
640
|
-
usage: stateManager.getTotalUsage()
|
|
778
|
+
usage: stateManager.getTotalUsage(),
|
|
779
|
+
sandboxId
|
|
641
780
|
};
|
|
642
781
|
}
|
|
643
782
|
const parsedToolCalls = [];
|
|
@@ -688,55 +827,40 @@ var createSession = async ({
|
|
|
688
827
|
throw workflow.ApplicationFailure.fromError(error);
|
|
689
828
|
} finally {
|
|
690
829
|
await callSessionEnd(exitReason, stateManager.getTurns());
|
|
691
|
-
if (
|
|
692
|
-
|
|
830
|
+
if (sandboxOwned && sandboxId && sandboxOps) {
|
|
831
|
+
switch (sandboxShutdown) {
|
|
832
|
+
case "destroy":
|
|
833
|
+
await sandboxOps.destroySandbox(sandboxId);
|
|
834
|
+
break;
|
|
835
|
+
case "pause":
|
|
836
|
+
case "pause-until-parent-close":
|
|
837
|
+
await sandboxOps.pauseSandbox(sandboxId);
|
|
838
|
+
break;
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
if (destroySubagentSandboxes) {
|
|
842
|
+
await destroySubagentSandboxes();
|
|
693
843
|
}
|
|
694
844
|
}
|
|
695
845
|
return {
|
|
696
846
|
threadId,
|
|
697
847
|
finalMessage: null,
|
|
698
848
|
exitReason,
|
|
699
|
-
usage: stateManager.getTotalUsage()
|
|
849
|
+
usage: stateManager.getTotalUsage(),
|
|
850
|
+
sandboxId
|
|
700
851
|
};
|
|
701
852
|
}
|
|
702
853
|
};
|
|
703
|
-
};
|
|
704
|
-
function proxyDefaultThreadOps(options) {
|
|
705
|
-
return workflow.proxyActivities(
|
|
706
|
-
options ?? {
|
|
707
|
-
startToCloseTimeout: "10s",
|
|
708
|
-
retry: {
|
|
709
|
-
maximumAttempts: 6,
|
|
710
|
-
initialInterval: "5s",
|
|
711
|
-
maximumInterval: "15m",
|
|
712
|
-
backoffCoefficient: 4
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
);
|
|
716
|
-
}
|
|
717
|
-
function proxySandboxOps(options) {
|
|
718
|
-
return workflow.proxyActivities(
|
|
719
|
-
options ?? {
|
|
720
|
-
startToCloseTimeout: "30s",
|
|
721
|
-
retry: {
|
|
722
|
-
maximumAttempts: 3,
|
|
723
|
-
initialInterval: "2s",
|
|
724
|
-
maximumInterval: "30s",
|
|
725
|
-
backoffCoefficient: 2
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
);
|
|
729
854
|
}
|
|
730
855
|
|
|
731
856
|
// src/lib/workflow.ts
|
|
732
857
|
function defineWorkflow(config, fn) {
|
|
733
858
|
const workflow = async (input, workflowInput = {}) => {
|
|
734
859
|
const sessionInput = {
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
}
|
|
739
|
-
...workflowInput.sandboxId && { sandboxId: workflowInput.sandboxId }
|
|
860
|
+
agentName: config.name,
|
|
861
|
+
sandboxShutdown: config.sandboxShutdown ?? "destroy",
|
|
862
|
+
...workflowInput.thread && { thread: workflowInput.thread },
|
|
863
|
+
...workflowInput.sandbox && { sandbox: workflowInput.sandbox }
|
|
740
864
|
};
|
|
741
865
|
return fn(input, sessionInput);
|
|
742
866
|
};
|
|
@@ -994,22 +1118,58 @@ function defineSubagent(definition, overrides) {
|
|
|
994
1118
|
...overrides
|
|
995
1119
|
};
|
|
996
1120
|
}
|
|
997
|
-
|
|
998
|
-
// src/lib/subagent/workflow.ts
|
|
999
1121
|
function defineSubagentWorkflow(config, fn) {
|
|
1000
|
-
const workflow = async (prompt, workflowInput, context) => {
|
|
1122
|
+
const workflow$1 = async (prompt, workflowInput, context) => {
|
|
1123
|
+
const effectiveShutdown = workflowInput.sandboxShutdown ?? config.sandboxShutdown ?? "destroy";
|
|
1001
1124
|
const sessionInput = {
|
|
1002
1125
|
agentName: config.name,
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
},
|
|
1007
|
-
...workflowInput.sandboxId && { sandboxId: workflowInput.sandboxId }
|
|
1126
|
+
sandboxShutdown: effectiveShutdown,
|
|
1127
|
+
...workflowInput.thread && { thread: workflowInput.thread },
|
|
1128
|
+
...workflowInput.sandbox && { sandbox: workflowInput.sandbox }
|
|
1008
1129
|
};
|
|
1009
|
-
|
|
1130
|
+
const { destroySandbox, ...result } = await fn(
|
|
1131
|
+
prompt,
|
|
1132
|
+
sessionInput,
|
|
1133
|
+
context ?? {}
|
|
1134
|
+
);
|
|
1135
|
+
if (effectiveShutdown === "pause-until-parent-close") {
|
|
1136
|
+
if (!destroySandbox) {
|
|
1137
|
+
throw workflow.ApplicationFailure.create({
|
|
1138
|
+
message: `Subagent "${config.name}" has sandboxShutdown="pause-until-parent-close" but fn did not return a destroySandbox callback`,
|
|
1139
|
+
nonRetryable: true
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
1142
|
+
if (!result.sandboxId) {
|
|
1143
|
+
throw workflow.ApplicationFailure.create({
|
|
1144
|
+
message: `Subagent "${config.name}" has sandboxShutdown="pause-until-parent-close" but fn did not return a sandboxId`,
|
|
1145
|
+
nonRetryable: true
|
|
1146
|
+
});
|
|
1147
|
+
}
|
|
1148
|
+
}
|
|
1149
|
+
const { parent } = workflow.workflowInfo();
|
|
1150
|
+
if (!parent) {
|
|
1151
|
+
throw workflow.ApplicationFailure.create({
|
|
1152
|
+
message: "Subagent workflow called without a parent workflow",
|
|
1153
|
+
nonRetryable: true
|
|
1154
|
+
});
|
|
1155
|
+
}
|
|
1156
|
+
const parentHandle = workflow.getExternalWorkflowHandle(parent.workflowId);
|
|
1157
|
+
await parentHandle.signal(childResultSignal, {
|
|
1158
|
+
childWorkflowId: workflow.workflowInfo().workflowId,
|
|
1159
|
+
result
|
|
1160
|
+
});
|
|
1161
|
+
if (destroySandbox) {
|
|
1162
|
+
let destroyRequested = false;
|
|
1163
|
+
workflow.setHandler(destroySandboxSignal, () => {
|
|
1164
|
+
destroyRequested = true;
|
|
1165
|
+
});
|
|
1166
|
+
await workflow.condition(() => destroyRequested);
|
|
1167
|
+
await destroySandbox();
|
|
1168
|
+
}
|
|
1169
|
+
return result;
|
|
1010
1170
|
};
|
|
1011
|
-
Object.defineProperty(workflow, "name", { value: config.name });
|
|
1012
|
-
return Object.assign(workflow, {
|
|
1171
|
+
Object.defineProperty(workflow$1, "name", { value: config.name });
|
|
1172
|
+
return Object.assign(workflow$1, {
|
|
1013
1173
|
agentName: config.name,
|
|
1014
1174
|
description: config.description,
|
|
1015
1175
|
...config.resultSchema !== void 0 && {
|
|
@@ -1741,6 +1901,9 @@ var SandboxManager = class {
|
|
|
1741
1901
|
async destroy(id) {
|
|
1742
1902
|
await this.provider.destroy(id);
|
|
1743
1903
|
}
|
|
1904
|
+
async pause(id, ttlSeconds) {
|
|
1905
|
+
await this.provider.pause(id, ttlSeconds);
|
|
1906
|
+
}
|
|
1744
1907
|
async snapshot(id) {
|
|
1745
1908
|
return this.provider.snapshot(id);
|
|
1746
1909
|
}
|
|
@@ -1748,22 +1911,53 @@ var SandboxManager = class {
|
|
|
1748
1911
|
const sandbox = await this.provider.restore(snapshot);
|
|
1749
1912
|
return sandbox.id;
|
|
1750
1913
|
}
|
|
1914
|
+
async fork(sandboxId) {
|
|
1915
|
+
const sandbox = await this.provider.fork(sandboxId);
|
|
1916
|
+
return sandbox.id;
|
|
1917
|
+
}
|
|
1751
1918
|
/**
|
|
1752
|
-
* Returns Temporal activity functions
|
|
1753
|
-
*
|
|
1919
|
+
* Returns Temporal activity functions with prefixed names.
|
|
1920
|
+
*
|
|
1921
|
+
* The provider's `id` is automatically prepended, so you only need
|
|
1922
|
+
* to pass the workflow/scope name. Use the matching `proxy*SandboxOps()`
|
|
1923
|
+
* helper from the adapter's `/workflow` entrypoint on the workflow side.
|
|
1924
|
+
*
|
|
1925
|
+
* @param scope - Workflow name (appended to the provider id)
|
|
1926
|
+
*
|
|
1927
|
+
* @example
|
|
1928
|
+
* ```typescript
|
|
1929
|
+
* const manager = new SandboxManager(new InMemorySandboxProvider());
|
|
1930
|
+
* manager.createActivities("CodingAgent");
|
|
1931
|
+
* // registers: inMemoryCodingAgentCreateSandbox, inMemoryCodingAgentDestroySandbox, …
|
|
1932
|
+
*
|
|
1933
|
+
* const vmgr = new SandboxManager(new VirtualSandboxProvider(resolver));
|
|
1934
|
+
* vmgr.createActivities("CodingAgent");
|
|
1935
|
+
* // registers: virtualCodingAgentCreateSandbox, …
|
|
1936
|
+
* ```
|
|
1754
1937
|
*/
|
|
1755
|
-
createActivities() {
|
|
1756
|
-
|
|
1938
|
+
createActivities(scope) {
|
|
1939
|
+
const prefix = `${this.provider.id}${scope.charAt(0).toUpperCase()}${scope.slice(1)}`;
|
|
1940
|
+
const ops = {
|
|
1757
1941
|
createSandbox: async (options) => {
|
|
1758
1942
|
return this.create(options);
|
|
1759
1943
|
},
|
|
1760
1944
|
destroySandbox: async (sandboxId) => {
|
|
1761
1945
|
await this.destroy(sandboxId);
|
|
1762
1946
|
},
|
|
1947
|
+
pauseSandbox: async (sandboxId, ttlSeconds) => {
|
|
1948
|
+
await this.pause(sandboxId, ttlSeconds);
|
|
1949
|
+
},
|
|
1763
1950
|
snapshotSandbox: async (sandboxId) => {
|
|
1764
1951
|
return this.snapshot(sandboxId);
|
|
1952
|
+
},
|
|
1953
|
+
forkSandbox: async (sandboxId) => {
|
|
1954
|
+
return this.fork(sandboxId);
|
|
1765
1955
|
}
|
|
1766
1956
|
};
|
|
1957
|
+
const cap = (s) => s.charAt(0).toUpperCase() + s.slice(1);
|
|
1958
|
+
return Object.fromEntries(
|
|
1959
|
+
Object.entries(ops).map(([k, v]) => [`${prefix}${cap(k)}`, v])
|
|
1960
|
+
);
|
|
1767
1961
|
}
|
|
1768
1962
|
};
|
|
1769
1963
|
|
|
@@ -2059,8 +2253,6 @@ exports.hasFileWithMimeType = hasFileWithMimeType;
|
|
|
2059
2253
|
exports.hasNoOtherToolCalls = hasNoOtherToolCalls;
|
|
2060
2254
|
exports.isTerminalStatus = isTerminalStatus;
|
|
2061
2255
|
exports.parseSkillFile = parseSkillFile;
|
|
2062
|
-
exports.proxyDefaultThreadOps = proxyDefaultThreadOps;
|
|
2063
|
-
exports.proxySandboxOps = proxySandboxOps;
|
|
2064
2256
|
exports.queryParentWorkflowState = queryParentWorkflowState;
|
|
2065
2257
|
exports.readFileHandler = readFileHandler;
|
|
2066
2258
|
exports.readFileTool = readFileTool;
|