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/index.cjs
CHANGED
|
@@ -6,6 +6,7 @@ var crypto = require('crypto');
|
|
|
6
6
|
var common = require('@temporalio/common');
|
|
7
7
|
var path = require('path');
|
|
8
8
|
var activity = require('@temporalio/activity');
|
|
9
|
+
var fs = require('fs');
|
|
9
10
|
|
|
10
11
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
12
|
|
|
@@ -18,8 +19,8 @@ function createToolRouter(options) {
|
|
|
18
19
|
for (const [_key, tool] of Object.entries(options.tools)) {
|
|
19
20
|
toolMap.set(tool.name, tool);
|
|
20
21
|
}
|
|
21
|
-
const
|
|
22
|
-
const isEnabled = (tool) =>
|
|
22
|
+
const resolve2 = (v) => typeof v === "function" ? v() : v;
|
|
23
|
+
const isEnabled = (tool) => resolve2(tool.enabled) ?? true;
|
|
23
24
|
if (options.plugins) {
|
|
24
25
|
for (const plugin of options.plugins) {
|
|
25
26
|
toolMap.set(plugin.name, plugin);
|
|
@@ -88,7 +89,12 @@ function createToolRouter(options) {
|
|
|
88
89
|
result: { error: errorStr, suppressed: true }
|
|
89
90
|
};
|
|
90
91
|
}
|
|
91
|
-
|
|
92
|
+
return {
|
|
93
|
+
content: JSON.stringify({
|
|
94
|
+
error: "The tool encountered an error. Please try again or use a different approach."
|
|
95
|
+
}),
|
|
96
|
+
result: { error: errorStr, suppressed: true }
|
|
97
|
+
};
|
|
92
98
|
}
|
|
93
99
|
async function runPostHooks(toolCall, tool, toolResult, effectiveArgs, turn, durationMs) {
|
|
94
100
|
if (tool?.hooks?.onPostToolUse) {
|
|
@@ -97,7 +103,8 @@ function createToolRouter(options) {
|
|
|
97
103
|
result: toolResult.data,
|
|
98
104
|
threadId: options.threadId,
|
|
99
105
|
turn,
|
|
100
|
-
durationMs
|
|
106
|
+
durationMs,
|
|
107
|
+
...toolResult.metadata && { metadata: toolResult.metadata }
|
|
101
108
|
});
|
|
102
109
|
}
|
|
103
110
|
if (options.hooks?.onPostToolUse) {
|
|
@@ -110,7 +117,7 @@ function createToolRouter(options) {
|
|
|
110
117
|
});
|
|
111
118
|
}
|
|
112
119
|
}
|
|
113
|
-
async function processToolCall(toolCall, turn, sandboxId) {
|
|
120
|
+
async function processToolCall(toolCall, turn, sandboxId, sandboxStateUpdate) {
|
|
114
121
|
const startTime = Date.now();
|
|
115
122
|
const tool = toolMap.get(toolCall.name);
|
|
116
123
|
const preResult = await runPreHooks(toolCall, tool, turn);
|
|
@@ -130,13 +137,15 @@ function createToolRouter(options) {
|
|
|
130
137
|
let result;
|
|
131
138
|
let content;
|
|
132
139
|
let resultAppended = false;
|
|
140
|
+
let metadata;
|
|
133
141
|
try {
|
|
134
142
|
if (tool) {
|
|
135
143
|
const routerContext = {
|
|
136
144
|
threadId: options.threadId,
|
|
137
145
|
toolCallId: toolCall.id,
|
|
138
146
|
toolName: toolCall.name,
|
|
139
|
-
...sandboxId !== void 0 && { sandboxId }
|
|
147
|
+
...sandboxId !== void 0 && { sandboxId },
|
|
148
|
+
...sandboxStateUpdate && { sandboxStateUpdate }
|
|
140
149
|
};
|
|
141
150
|
const response = await tool.handler(
|
|
142
151
|
effectiveArgs,
|
|
@@ -145,6 +154,7 @@ function createToolRouter(options) {
|
|
|
145
154
|
result = response.data;
|
|
146
155
|
content = response.toolResponse;
|
|
147
156
|
resultAppended = response.resultAppended === true;
|
|
157
|
+
metadata = response.metadata;
|
|
148
158
|
} else {
|
|
149
159
|
result = { error: `Unknown tool: ${toolCall.name}` };
|
|
150
160
|
content = JSON.stringify(result, null, 2);
|
|
@@ -177,7 +187,8 @@ function createToolRouter(options) {
|
|
|
177
187
|
const toolResult = {
|
|
178
188
|
toolCallId: toolCall.id,
|
|
179
189
|
name: toolCall.name,
|
|
180
|
-
data: result
|
|
190
|
+
data: result,
|
|
191
|
+
...metadata && { metadata }
|
|
181
192
|
};
|
|
182
193
|
await runPostHooks(
|
|
183
194
|
toolCall,
|
|
@@ -198,7 +209,7 @@ function createToolRouter(options) {
|
|
|
198
209
|
if (!tool || !isEnabled(tool)) {
|
|
199
210
|
throw new Error(`Tool ${toolCall.name} not found`);
|
|
200
211
|
}
|
|
201
|
-
const parsedArgs =
|
|
212
|
+
const parsedArgs = resolve2(tool.schema).parse(toolCall.args);
|
|
202
213
|
return {
|
|
203
214
|
id: toolCall.id ?? "",
|
|
204
215
|
name: toolCall.name,
|
|
@@ -215,8 +226,8 @@ function createToolRouter(options) {
|
|
|
215
226
|
getToolDefinitions() {
|
|
216
227
|
return Array.from(toolMap).filter(([, tool]) => isEnabled(tool)).map(([name, tool]) => ({
|
|
217
228
|
name,
|
|
218
|
-
description:
|
|
219
|
-
schema:
|
|
229
|
+
description: resolve2(tool.description),
|
|
230
|
+
schema: resolve2(tool.schema),
|
|
220
231
|
strict: tool.strict,
|
|
221
232
|
max_uses: tool.max_uses
|
|
222
233
|
}));
|
|
@@ -227,9 +238,10 @@ function createToolRouter(options) {
|
|
|
227
238
|
}
|
|
228
239
|
const turn = context?.turn ?? 0;
|
|
229
240
|
const sandboxId = context?.sandboxId;
|
|
241
|
+
const sandboxStateUpdate = context?.sandboxStateUpdate;
|
|
230
242
|
if (options.parallel) {
|
|
231
243
|
const results2 = await Promise.all(
|
|
232
|
-
toolCalls.map((tc) => processToolCall(tc, turn, sandboxId))
|
|
244
|
+
toolCalls.map((tc) => processToolCall(tc, turn, sandboxId, sandboxStateUpdate))
|
|
233
245
|
);
|
|
234
246
|
return results2.filter(
|
|
235
247
|
(r) => r !== null
|
|
@@ -237,7 +249,7 @@ function createToolRouter(options) {
|
|
|
237
249
|
}
|
|
238
250
|
const results = [];
|
|
239
251
|
for (const toolCall of toolCalls) {
|
|
240
|
-
const result = await processToolCall(toolCall, turn, sandboxId);
|
|
252
|
+
const result = await processToolCall(toolCall, turn, sandboxId, sandboxStateUpdate);
|
|
241
253
|
if (result !== null) {
|
|
242
254
|
results.push(result);
|
|
243
255
|
}
|
|
@@ -281,7 +293,8 @@ function createToolRouter(options) {
|
|
|
281
293
|
return {
|
|
282
294
|
toolCallId: toolCall.id,
|
|
283
295
|
name: toolCall.name,
|
|
284
|
-
data: response.data
|
|
296
|
+
data: response.data,
|
|
297
|
+
...response.metadata && { metadata: response.metadata }
|
|
285
298
|
};
|
|
286
299
|
};
|
|
287
300
|
if (options.parallel) {
|
|
@@ -325,7 +338,7 @@ function getShortId(length = 12) {
|
|
|
325
338
|
var SUBAGENT_TOOL_NAME = "Subagent";
|
|
326
339
|
function buildSubagentDescription(subagents) {
|
|
327
340
|
const subagentList = subagents.map((s) => {
|
|
328
|
-
const continuation = s.
|
|
341
|
+
const continuation = s.thread && s.thread !== "new" ? "\n*(Supports thread continuation \u2014 pass a threadId to resume a previous conversation)*" : "";
|
|
329
342
|
return `## ${s.agentName}
|
|
330
343
|
${s.description}${continuation}`;
|
|
331
344
|
}).join("\n\n");
|
|
@@ -341,7 +354,7 @@ function createSubagentTool(subagents) {
|
|
|
341
354
|
}
|
|
342
355
|
const names = subagents.map((s) => s.agentName);
|
|
343
356
|
const hasThreadContinuation = subagents.some(
|
|
344
|
-
(s) => s.
|
|
357
|
+
(s) => s.thread && s.thread !== "new"
|
|
345
358
|
);
|
|
346
359
|
const baseFields = {
|
|
347
360
|
subagent: z14__default.default.enum(names).describe("The type of subagent to launch"),
|
|
@@ -360,9 +373,25 @@ function createSubagentTool(subagents) {
|
|
|
360
373
|
schema
|
|
361
374
|
};
|
|
362
375
|
}
|
|
376
|
+
var childResultSignal = workflow.defineSignal("childResult");
|
|
377
|
+
var destroySandboxSignal = workflow.defineSignal("destroySandbox");
|
|
378
|
+
|
|
379
|
+
// src/lib/subagent/handler.ts
|
|
380
|
+
function resolveSandboxConfig(config) {
|
|
381
|
+
if (!config || config === "none") return { source: "none" };
|
|
382
|
+
if (config === "inherit") return { source: "inherit" };
|
|
383
|
+
if (config === "own") return { source: "own" };
|
|
384
|
+
return { source: "own", shutdown: config.shutdown };
|
|
385
|
+
}
|
|
363
386
|
function createSubagentHandler(subagents) {
|
|
364
387
|
const { taskQueue: parentTaskQueue } = workflow.workflowInfo();
|
|
365
|
-
|
|
388
|
+
const childResults = /* @__PURE__ */ new Map();
|
|
389
|
+
const pendingDestroys = /* @__PURE__ */ new Map();
|
|
390
|
+
const threadSandboxes = /* @__PURE__ */ new Map();
|
|
391
|
+
workflow.setHandler(childResultSignal, ({ childWorkflowId, result }) => {
|
|
392
|
+
childResults.set(childWorkflowId, result);
|
|
393
|
+
});
|
|
394
|
+
const handler = async (args, context) => {
|
|
366
395
|
const config = subagents.find((s) => s.agentName === args.subagent);
|
|
367
396
|
if (!config) {
|
|
368
397
|
throw new Error(
|
|
@@ -371,12 +400,36 @@ function createSubagentHandler(subagents) {
|
|
|
371
400
|
}
|
|
372
401
|
const childWorkflowId = `${args.subagent}-${getShortId()}`;
|
|
373
402
|
const { sandboxId: parentSandboxId } = context;
|
|
374
|
-
const
|
|
403
|
+
const sandboxCfg = resolveSandboxConfig(config.sandbox);
|
|
404
|
+
if (sandboxCfg.source === "inherit" && !parentSandboxId) {
|
|
405
|
+
throw new Error(
|
|
406
|
+
`Subagent "${config.agentName}" is configured with sandbox: "inherit" but the parent has no sandbox`
|
|
407
|
+
);
|
|
408
|
+
}
|
|
409
|
+
const threadMode = config.thread ?? "new";
|
|
410
|
+
const allowsContinuation = threadMode !== "new";
|
|
411
|
+
const continuationThreadId = args.threadId && allowsContinuation ? args.threadId : void 0;
|
|
412
|
+
let thread;
|
|
413
|
+
if (continuationThreadId) {
|
|
414
|
+
thread = { mode: threadMode, threadId: continuationThreadId };
|
|
415
|
+
}
|
|
416
|
+
let sandbox;
|
|
417
|
+
if (sandboxCfg.source === "inherit" && parentSandboxId) {
|
|
418
|
+
sandbox = {
|
|
419
|
+
mode: "inherit",
|
|
420
|
+
sandboxId: parentSandboxId,
|
|
421
|
+
...context.sandboxStateUpdate && { stateUpdate: context.sandboxStateUpdate }
|
|
422
|
+
};
|
|
423
|
+
} else if (sandboxCfg.source === "own") {
|
|
424
|
+
const prevSbId = continuationThreadId ? threadSandboxes.get(continuationThreadId) : void 0;
|
|
425
|
+
if (prevSbId) {
|
|
426
|
+
sandbox = { mode: "fork", sandboxId: prevSbId };
|
|
427
|
+
}
|
|
428
|
+
}
|
|
375
429
|
const workflowInput = {
|
|
376
|
-
...
|
|
377
|
-
|
|
378
|
-
}
|
|
379
|
-
...inheritSandbox && { sandboxId: parentSandboxId }
|
|
430
|
+
...thread && { thread },
|
|
431
|
+
...sandbox && { sandbox },
|
|
432
|
+
...sandboxCfg.shutdown && { sandboxShutdown: sandboxCfg.shutdown }
|
|
380
433
|
};
|
|
381
434
|
const resolvedContext = config.context === void 0 ? void 0 : typeof config.context === "function" ? config.context() : config.context;
|
|
382
435
|
const childOpts = {
|
|
@@ -384,17 +437,44 @@ function createSubagentHandler(subagents) {
|
|
|
384
437
|
args: resolvedContext === void 0 ? [args.prompt, workflowInput] : [args.prompt, workflowInput, resolvedContext],
|
|
385
438
|
taskQueue: config.taskQueue ?? parentTaskQueue
|
|
386
439
|
};
|
|
440
|
+
const childHandle = await workflow.startChild(config.workflow, childOpts);
|
|
441
|
+
const usesOwnSandbox = sandboxCfg.source === "own" || allowsContinuation && sandboxCfg.source !== "inherit";
|
|
442
|
+
if (usesOwnSandbox) {
|
|
443
|
+
pendingDestroys.set(childWorkflowId, childHandle);
|
|
444
|
+
}
|
|
445
|
+
await Promise.race([
|
|
446
|
+
workflow.condition(() => childResults.has(childWorkflowId)),
|
|
447
|
+
childHandle.result()
|
|
448
|
+
]);
|
|
449
|
+
if (!childResults.has(childWorkflowId)) {
|
|
450
|
+
await workflow.condition(() => childResults.has(childWorkflowId));
|
|
451
|
+
}
|
|
452
|
+
const childResult = childResults.get(childWorkflowId);
|
|
453
|
+
childResults.delete(childWorkflowId);
|
|
454
|
+
if (!childResult) {
|
|
455
|
+
return {
|
|
456
|
+
toolResponse: "Subagent workflow did not signal a result",
|
|
457
|
+
data: null
|
|
458
|
+
};
|
|
459
|
+
}
|
|
387
460
|
const {
|
|
388
461
|
toolResponse,
|
|
389
462
|
data,
|
|
390
463
|
usage,
|
|
391
|
-
threadId: childThreadId
|
|
392
|
-
|
|
464
|
+
threadId: childThreadId,
|
|
465
|
+
sandboxId: childSandboxId,
|
|
466
|
+
metadata
|
|
467
|
+
} = childResult;
|
|
468
|
+
if (allowsContinuation && childSandboxId && childThreadId) {
|
|
469
|
+
threadSandboxes.set(childThreadId, childSandboxId);
|
|
470
|
+
}
|
|
393
471
|
if (!toolResponse) {
|
|
394
472
|
return {
|
|
395
473
|
toolResponse: "Subagent workflow returned no response",
|
|
396
474
|
data: null,
|
|
397
|
-
...usage && { usage }
|
|
475
|
+
...usage && { usage },
|
|
476
|
+
...childSandboxId && { sandboxId: childSandboxId },
|
|
477
|
+
...metadata && { metadata }
|
|
398
478
|
};
|
|
399
479
|
}
|
|
400
480
|
const validated = config.resultSchema ? config.resultSchema.safeParse(data) : null;
|
|
@@ -402,11 +482,13 @@ function createSubagentHandler(subagents) {
|
|
|
402
482
|
return {
|
|
403
483
|
toolResponse: `Subagent workflow returned invalid data: ${validated.error.message}`,
|
|
404
484
|
data: null,
|
|
405
|
-
...usage && { usage }
|
|
485
|
+
...usage && { usage },
|
|
486
|
+
...childSandboxId && { sandboxId: childSandboxId },
|
|
487
|
+
...metadata && { metadata }
|
|
406
488
|
};
|
|
407
489
|
}
|
|
408
490
|
let finalToolResponse = toolResponse;
|
|
409
|
-
if (
|
|
491
|
+
if (allowsContinuation && childThreadId) {
|
|
410
492
|
finalToolResponse = typeof toolResponse === "string" ? `${toolResponse}
|
|
411
493
|
|
|
412
494
|
[${config.agentName} Thread ID: ${childThreadId}]` : toolResponse;
|
|
@@ -414,9 +496,22 @@ function createSubagentHandler(subagents) {
|
|
|
414
496
|
return {
|
|
415
497
|
toolResponse: finalToolResponse,
|
|
416
498
|
data: validated ? validated.data : data,
|
|
417
|
-
...usage && { usage }
|
|
499
|
+
...usage && { usage },
|
|
500
|
+
...childSandboxId && { sandboxId: childSandboxId },
|
|
501
|
+
...metadata && { metadata }
|
|
418
502
|
};
|
|
419
503
|
};
|
|
504
|
+
const destroySubagentSandboxes = async () => {
|
|
505
|
+
const handles = [...pendingDestroys.values()];
|
|
506
|
+
pendingDestroys.clear();
|
|
507
|
+
await Promise.all(
|
|
508
|
+
handles.map(async (handle) => {
|
|
509
|
+
await handle.signal(destroySandboxSignal);
|
|
510
|
+
await handle.result();
|
|
511
|
+
})
|
|
512
|
+
);
|
|
513
|
+
};
|
|
514
|
+
return { handler, destroySubagentSandboxes };
|
|
420
515
|
}
|
|
421
516
|
|
|
422
517
|
// src/lib/subagent/register.ts
|
|
@@ -430,12 +525,13 @@ function buildSubagentRegistration(subagents) {
|
|
|
430
525
|
if (s.hooks) subagentHooksMap.set(s.agentName, s.hooks);
|
|
431
526
|
}
|
|
432
527
|
const resolveSubagentName = (args) => args.subagent;
|
|
433
|
-
|
|
528
|
+
const { handler, destroySubagentSandboxes } = createSubagentHandler(subagents);
|
|
529
|
+
const registration = {
|
|
434
530
|
name: SUBAGENT_TOOL_NAME,
|
|
435
531
|
enabled: () => getEnabled().length > 0,
|
|
436
532
|
description: () => createSubagentTool(getEnabled()).description,
|
|
437
533
|
schema: () => createSubagentTool(getEnabled()).schema,
|
|
438
|
-
handler
|
|
534
|
+
handler,
|
|
439
535
|
...subagentHooksMap.size > 0 && {
|
|
440
536
|
hooks: {
|
|
441
537
|
onPreToolUse: async (ctx) => {
|
|
@@ -453,6 +549,7 @@ function buildSubagentRegistration(subagents) {
|
|
|
453
549
|
}
|
|
454
550
|
}
|
|
455
551
|
};
|
|
552
|
+
return { registration, destroySubagentSandboxes };
|
|
456
553
|
}
|
|
457
554
|
var READ_SKILL_TOOL_NAME = "ReadSkill";
|
|
458
555
|
function buildReadSkillDescription(skills) {
|
|
@@ -478,6 +575,29 @@ function createReadSkillTool(skills) {
|
|
|
478
575
|
}
|
|
479
576
|
|
|
480
577
|
// src/lib/skills/handler.ts
|
|
578
|
+
function formatSkillResponse(skill) {
|
|
579
|
+
const parts = [];
|
|
580
|
+
parts.push(`<skill_content name="${skill.name}">`);
|
|
581
|
+
parts.push(skill.instructions);
|
|
582
|
+
if (skill.location) {
|
|
583
|
+
parts.push(`
|
|
584
|
+
Skill directory: ${skill.location}`);
|
|
585
|
+
parts.push(
|
|
586
|
+
"Relative paths in this skill resolve against the skill directory above."
|
|
587
|
+
);
|
|
588
|
+
}
|
|
589
|
+
const resources = skill.resourceContents ? Object.keys(skill.resourceContents) : [];
|
|
590
|
+
if (resources.length > 0) {
|
|
591
|
+
parts.push("");
|
|
592
|
+
parts.push("<skill_resources>");
|
|
593
|
+
for (const r of resources) {
|
|
594
|
+
parts.push(` <file>${r}</file>`);
|
|
595
|
+
}
|
|
596
|
+
parts.push("</skill_resources>");
|
|
597
|
+
}
|
|
598
|
+
parts.push("</skill_content>");
|
|
599
|
+
return parts.join("\n");
|
|
600
|
+
}
|
|
481
601
|
function createReadSkillHandler(skills) {
|
|
482
602
|
const skillMap = new Map(skills.map((s) => [s.name, s]));
|
|
483
603
|
return (args) => {
|
|
@@ -491,22 +611,42 @@ function createReadSkillHandler(skills) {
|
|
|
491
611
|
};
|
|
492
612
|
}
|
|
493
613
|
return {
|
|
494
|
-
toolResponse: skill
|
|
614
|
+
toolResponse: formatSkillResponse(skill),
|
|
495
615
|
data: null
|
|
496
616
|
};
|
|
497
617
|
};
|
|
498
618
|
}
|
|
499
619
|
|
|
500
620
|
// src/lib/skills/register.ts
|
|
621
|
+
function validateSkillNames(skills) {
|
|
622
|
+
const names = skills.map((s) => s.name);
|
|
623
|
+
const dupes = names.filter((n, i) => names.indexOf(n) !== i);
|
|
624
|
+
if (dupes.length > 0) {
|
|
625
|
+
throw new Error(
|
|
626
|
+
`Duplicate skill names: ${[...new Set(dupes)].join(", ")}`
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
501
630
|
function buildSkillRegistration(skills) {
|
|
502
631
|
if (skills.length === 0) return null;
|
|
632
|
+
validateSkillNames(skills);
|
|
503
633
|
return {
|
|
504
634
|
...createReadSkillTool(skills),
|
|
505
635
|
handler: createReadSkillHandler(skills)
|
|
506
636
|
};
|
|
507
637
|
}
|
|
508
|
-
|
|
509
|
-
|
|
638
|
+
function collectSkillFiles(skills) {
|
|
639
|
+
let files;
|
|
640
|
+
for (const skill of skills) {
|
|
641
|
+
if (!skill.resourceContents || !skill.location) continue;
|
|
642
|
+
for (const [relPath, content] of Object.entries(skill.resourceContents)) {
|
|
643
|
+
files ??= {};
|
|
644
|
+
files[`${skill.location}/${relPath}`] = content;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
return files;
|
|
648
|
+
}
|
|
649
|
+
async function createSession({
|
|
510
650
|
agentName,
|
|
511
651
|
maxTurns = 50,
|
|
512
652
|
metadata = {},
|
|
@@ -519,13 +659,27 @@ var createSession = async ({
|
|
|
519
659
|
processToolsInParallel = true,
|
|
520
660
|
hooks = {},
|
|
521
661
|
appendSystemPrompt = true,
|
|
522
|
-
continueThread = false,
|
|
523
662
|
waitForInputTimeout = "48h",
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
663
|
+
sandboxOps,
|
|
664
|
+
thread: threadInit,
|
|
665
|
+
sandbox: sandboxInit,
|
|
666
|
+
sandboxShutdown = "destroy"
|
|
667
|
+
}) {
|
|
668
|
+
const threadMode = threadInit?.mode ?? "new";
|
|
669
|
+
let threadId;
|
|
670
|
+
let sourceThreadId;
|
|
671
|
+
switch (threadMode) {
|
|
672
|
+
case "new":
|
|
673
|
+
threadId = threadInit?.mode === "new" && threadInit.threadId ? threadInit.threadId : getShortId();
|
|
674
|
+
break;
|
|
675
|
+
case "continue":
|
|
676
|
+
threadId = threadInit.threadId;
|
|
677
|
+
break;
|
|
678
|
+
case "fork":
|
|
679
|
+
sourceThreadId = threadInit.threadId;
|
|
680
|
+
threadId = getShortId();
|
|
681
|
+
break;
|
|
682
|
+
}
|
|
529
683
|
const {
|
|
530
684
|
appendToolResult,
|
|
531
685
|
appendHumanMessage,
|
|
@@ -534,9 +688,13 @@ var createSession = async ({
|
|
|
534
688
|
forkThread
|
|
535
689
|
} = threadOps;
|
|
536
690
|
const plugins = [];
|
|
691
|
+
let destroySubagentSandboxes;
|
|
537
692
|
if (subagents) {
|
|
538
|
-
const
|
|
539
|
-
if (
|
|
693
|
+
const result = buildSubagentRegistration(subagents);
|
|
694
|
+
if (result) {
|
|
695
|
+
plugins.push(result.registration);
|
|
696
|
+
destroySubagentSandboxes = result.destroySubagentSandboxes;
|
|
697
|
+
}
|
|
540
698
|
}
|
|
541
699
|
if (skills) {
|
|
542
700
|
const reg = buildSkillRegistration(skills);
|
|
@@ -584,12 +742,52 @@ var createSession = async ({
|
|
|
584
742
|
stateManager.run();
|
|
585
743
|
}
|
|
586
744
|
);
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
745
|
+
const sandboxMode = sandboxInit?.mode;
|
|
746
|
+
let sandboxId;
|
|
747
|
+
let sandboxOwned = false;
|
|
748
|
+
let sandboxStateUpdate;
|
|
749
|
+
if (sandboxMode === "inherit") {
|
|
750
|
+
const inheritInit = sandboxInit;
|
|
751
|
+
sandboxId = inheritInit.sandboxId;
|
|
752
|
+
if (inheritInit.stateUpdate) {
|
|
753
|
+
sandboxStateUpdate = inheritInit.stateUpdate;
|
|
754
|
+
stateManager.mergeUpdate(inheritInit.stateUpdate);
|
|
755
|
+
}
|
|
756
|
+
if (!sandboxOps) {
|
|
757
|
+
throw workflow.ApplicationFailure.create({
|
|
758
|
+
message: "sandboxId provided but no sandboxOps \u2014 cannot manage sandbox lifecycle",
|
|
759
|
+
nonRetryable: true
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
} else if (sandboxMode === "continue") {
|
|
763
|
+
if (!sandboxOps) {
|
|
764
|
+
throw workflow.ApplicationFailure.create({
|
|
765
|
+
message: "No sandboxOps provided \u2014 cannot continue sandbox",
|
|
766
|
+
nonRetryable: true
|
|
767
|
+
});
|
|
768
|
+
}
|
|
769
|
+
sandboxId = sandboxInit.sandboxId;
|
|
770
|
+
sandboxOwned = true;
|
|
771
|
+
} else if (sandboxMode === "fork") {
|
|
772
|
+
if (!sandboxOps) {
|
|
773
|
+
throw workflow.ApplicationFailure.create({
|
|
774
|
+
message: "No sandboxOps provided \u2014 cannot fork sandbox",
|
|
775
|
+
nonRetryable: true
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
sandboxId = await sandboxOps.forkSandbox(
|
|
779
|
+
sandboxInit.sandboxId
|
|
780
|
+
);
|
|
781
|
+
sandboxOwned = true;
|
|
782
|
+
} else if (sandboxOps) {
|
|
783
|
+
const skillFiles = skills ? collectSkillFiles(skills) : void 0;
|
|
784
|
+
const result = await sandboxOps.createSandbox(
|
|
785
|
+
skillFiles ? { initialFiles: skillFiles } : void 0
|
|
786
|
+
);
|
|
591
787
|
sandboxId = result.sandboxId;
|
|
788
|
+
sandboxOwned = true;
|
|
592
789
|
if (result.stateUpdate) {
|
|
790
|
+
sandboxStateUpdate = result.stateUpdate;
|
|
593
791
|
stateManager.mergeUpdate(result.stateUpdate);
|
|
594
792
|
}
|
|
595
793
|
}
|
|
@@ -601,9 +799,9 @@ var createSession = async ({
|
|
|
601
799
|
});
|
|
602
800
|
}
|
|
603
801
|
const systemPrompt = stateManager.getSystemPrompt();
|
|
604
|
-
if (
|
|
802
|
+
if (threadMode === "fork" && sourceThreadId) {
|
|
605
803
|
await forkThread(sourceThreadId, threadId);
|
|
606
|
-
} else {
|
|
804
|
+
} else if (threadMode === "continue") ; else {
|
|
607
805
|
if (appendSystemPrompt) {
|
|
608
806
|
if (!systemPrompt || systemPrompt.trim() === "") {
|
|
609
807
|
throw workflow.ApplicationFailure.create({
|
|
@@ -638,7 +836,8 @@ var createSession = async ({
|
|
|
638
836
|
threadId,
|
|
639
837
|
finalMessage: message,
|
|
640
838
|
exitReason,
|
|
641
|
-
usage: stateManager.getTotalUsage()
|
|
839
|
+
usage: stateManager.getTotalUsage(),
|
|
840
|
+
sandboxId
|
|
642
841
|
};
|
|
643
842
|
}
|
|
644
843
|
const parsedToolCalls = [];
|
|
@@ -660,7 +859,8 @@ var createSession = async ({
|
|
|
660
859
|
parsedToolCalls,
|
|
661
860
|
{
|
|
662
861
|
turn: currentTurn,
|
|
663
|
-
...sandboxId !== void 0 && { sandboxId }
|
|
862
|
+
...sandboxId !== void 0 && { sandboxId },
|
|
863
|
+
...sandboxStateUpdate && { sandboxStateUpdate }
|
|
664
864
|
}
|
|
665
865
|
);
|
|
666
866
|
for (const result of toolCallResults) {
|
|
@@ -689,30 +889,40 @@ var createSession = async ({
|
|
|
689
889
|
throw workflow.ApplicationFailure.fromError(error);
|
|
690
890
|
} finally {
|
|
691
891
|
await callSessionEnd(exitReason, stateManager.getTurns());
|
|
692
|
-
if (
|
|
693
|
-
|
|
892
|
+
if (sandboxOwned && sandboxId && sandboxOps) {
|
|
893
|
+
switch (sandboxShutdown) {
|
|
894
|
+
case "destroy":
|
|
895
|
+
await sandboxOps.destroySandbox(sandboxId);
|
|
896
|
+
break;
|
|
897
|
+
case "pause":
|
|
898
|
+
case "pause-until-parent-close":
|
|
899
|
+
await sandboxOps.pauseSandbox(sandboxId);
|
|
900
|
+
break;
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
if (destroySubagentSandboxes) {
|
|
904
|
+
await destroySubagentSandboxes();
|
|
694
905
|
}
|
|
695
906
|
}
|
|
696
907
|
return {
|
|
697
908
|
threadId,
|
|
698
909
|
finalMessage: null,
|
|
699
910
|
exitReason,
|
|
700
|
-
usage: stateManager.getTotalUsage()
|
|
911
|
+
usage: stateManager.getTotalUsage(),
|
|
912
|
+
sandboxId
|
|
701
913
|
};
|
|
702
914
|
}
|
|
703
915
|
};
|
|
704
|
-
}
|
|
916
|
+
}
|
|
705
917
|
|
|
706
918
|
// src/lib/workflow.ts
|
|
707
919
|
function defineWorkflow(config, fn) {
|
|
708
920
|
const workflow = async (input, workflowInput = {}) => {
|
|
709
921
|
const sessionInput = {
|
|
710
922
|
agentName: config.name,
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
},
|
|
715
|
-
...workflowInput.sandboxId && { sandboxId: workflowInput.sandboxId }
|
|
923
|
+
sandboxShutdown: config.sandboxShutdown ?? "destroy",
|
|
924
|
+
...workflowInput.thread && { thread: workflowInput.thread },
|
|
925
|
+
...workflowInput.sandbox && { sandbox: workflowInput.sandbox }
|
|
716
926
|
};
|
|
717
927
|
return fn(input, sessionInput);
|
|
718
928
|
};
|
|
@@ -970,22 +1180,58 @@ function defineSubagent(definition, overrides) {
|
|
|
970
1180
|
...overrides
|
|
971
1181
|
};
|
|
972
1182
|
}
|
|
973
|
-
|
|
974
|
-
// src/lib/subagent/workflow.ts
|
|
975
1183
|
function defineSubagentWorkflow(config, fn) {
|
|
976
|
-
const workflow = async (prompt, workflowInput, context) => {
|
|
1184
|
+
const workflow$1 = async (prompt, workflowInput, context) => {
|
|
1185
|
+
const effectiveShutdown = workflowInput.sandboxShutdown ?? config.sandboxShutdown ?? "destroy";
|
|
977
1186
|
const sessionInput = {
|
|
978
1187
|
agentName: config.name,
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
},
|
|
983
|
-
...workflowInput.sandboxId && { sandboxId: workflowInput.sandboxId }
|
|
1188
|
+
sandboxShutdown: effectiveShutdown,
|
|
1189
|
+
...workflowInput.thread && { thread: workflowInput.thread },
|
|
1190
|
+
...workflowInput.sandbox && { sandbox: workflowInput.sandbox }
|
|
984
1191
|
};
|
|
985
|
-
|
|
1192
|
+
const { destroySandbox, ...result } = await fn(
|
|
1193
|
+
prompt,
|
|
1194
|
+
sessionInput,
|
|
1195
|
+
context ?? {}
|
|
1196
|
+
);
|
|
1197
|
+
if (effectiveShutdown === "pause-until-parent-close") {
|
|
1198
|
+
if (!destroySandbox) {
|
|
1199
|
+
throw workflow.ApplicationFailure.create({
|
|
1200
|
+
message: `Subagent "${config.name}" has sandboxShutdown="pause-until-parent-close" but fn did not return a destroySandbox callback`,
|
|
1201
|
+
nonRetryable: true
|
|
1202
|
+
});
|
|
1203
|
+
}
|
|
1204
|
+
if (!result.sandboxId) {
|
|
1205
|
+
throw workflow.ApplicationFailure.create({
|
|
1206
|
+
message: `Subagent "${config.name}" has sandboxShutdown="pause-until-parent-close" but fn did not return a sandboxId`,
|
|
1207
|
+
nonRetryable: true
|
|
1208
|
+
});
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
const { parent } = workflow.workflowInfo();
|
|
1212
|
+
if (!parent) {
|
|
1213
|
+
throw workflow.ApplicationFailure.create({
|
|
1214
|
+
message: "Subagent workflow called without a parent workflow",
|
|
1215
|
+
nonRetryable: true
|
|
1216
|
+
});
|
|
1217
|
+
}
|
|
1218
|
+
const parentHandle = workflow.getExternalWorkflowHandle(parent.workflowId);
|
|
1219
|
+
await parentHandle.signal(childResultSignal, {
|
|
1220
|
+
childWorkflowId: workflow.workflowInfo().workflowId,
|
|
1221
|
+
result
|
|
1222
|
+
});
|
|
1223
|
+
if (destroySandbox) {
|
|
1224
|
+
let destroyRequested = false;
|
|
1225
|
+
workflow.setHandler(destroySandboxSignal, () => {
|
|
1226
|
+
destroyRequested = true;
|
|
1227
|
+
});
|
|
1228
|
+
await workflow.condition(() => destroyRequested);
|
|
1229
|
+
await destroySandbox();
|
|
1230
|
+
}
|
|
1231
|
+
return result;
|
|
986
1232
|
};
|
|
987
|
-
Object.defineProperty(workflow, "name", { value: config.name });
|
|
988
|
-
return Object.assign(workflow, {
|
|
1233
|
+
Object.defineProperty(workflow$1, "name", { value: config.name });
|
|
1234
|
+
return Object.assign(workflow$1, {
|
|
989
1235
|
agentName: config.name,
|
|
990
1236
|
description: config.description,
|
|
991
1237
|
...config.resultSchema !== void 0 && {
|
|
@@ -1555,7 +1801,11 @@ var FileSystemSkillProvider = class {
|
|
|
1555
1801
|
for (const dir of dirs) {
|
|
1556
1802
|
const raw = await this.fs.readFile(path.join(this.baseDir, dir, "SKILL.md"));
|
|
1557
1803
|
const { frontmatter } = parseSkillFile(raw);
|
|
1558
|
-
|
|
1804
|
+
const location = path.join(this.baseDir, dir);
|
|
1805
|
+
skills.push({
|
|
1806
|
+
...frontmatter,
|
|
1807
|
+
location
|
|
1808
|
+
});
|
|
1559
1809
|
}
|
|
1560
1810
|
return skills;
|
|
1561
1811
|
}
|
|
@@ -1569,7 +1819,15 @@ var FileSystemSkillProvider = class {
|
|
|
1569
1819
|
`Skill directory "${name}" contains SKILL.md with mismatched name "${frontmatter.name}"`
|
|
1570
1820
|
);
|
|
1571
1821
|
}
|
|
1572
|
-
|
|
1822
|
+
const location = path.join(this.baseDir, name);
|
|
1823
|
+
const resourcePaths = await this.discoverResources(name);
|
|
1824
|
+
const resourceContents = await this.readResourceContents(location, resourcePaths);
|
|
1825
|
+
return {
|
|
1826
|
+
...frontmatter,
|
|
1827
|
+
instructions: body,
|
|
1828
|
+
location,
|
|
1829
|
+
...resourceContents && { resourceContents }
|
|
1830
|
+
};
|
|
1573
1831
|
}
|
|
1574
1832
|
/**
|
|
1575
1833
|
* Convenience method to load all skills with full instructions.
|
|
@@ -1581,10 +1839,48 @@ var FileSystemSkillProvider = class {
|
|
|
1581
1839
|
for (const dir of dirs) {
|
|
1582
1840
|
const raw = await this.fs.readFile(path.join(this.baseDir, dir, "SKILL.md"));
|
|
1583
1841
|
const { frontmatter, body } = parseSkillFile(raw);
|
|
1584
|
-
|
|
1842
|
+
const location = path.join(this.baseDir, dir);
|
|
1843
|
+
const resourcePaths = await this.discoverResources(dir);
|
|
1844
|
+
const resourceContents = await this.readResourceContents(location, resourcePaths);
|
|
1845
|
+
skills.push({
|
|
1846
|
+
...frontmatter,
|
|
1847
|
+
instructions: body,
|
|
1848
|
+
location,
|
|
1849
|
+
...resourceContents && { resourceContents }
|
|
1850
|
+
});
|
|
1585
1851
|
}
|
|
1586
1852
|
return skills;
|
|
1587
1853
|
}
|
|
1854
|
+
/**
|
|
1855
|
+
* Recursively discovers all non-SKILL.md files inside the skill directory
|
|
1856
|
+
* and returns their paths relative to the skill root.
|
|
1857
|
+
*/
|
|
1858
|
+
async discoverResources(skillDir) {
|
|
1859
|
+
const skillRoot = path.join(this.baseDir, skillDir);
|
|
1860
|
+
const resources = [];
|
|
1861
|
+
const walk2 = async (dir, prefix) => {
|
|
1862
|
+
const entries = await this.fs.readdirWithFileTypes(dir);
|
|
1863
|
+
for (const e of entries) {
|
|
1864
|
+
if (e.name.startsWith(".")) continue;
|
|
1865
|
+
const relPath = prefix ? `${prefix}/${e.name}` : e.name;
|
|
1866
|
+
if (e.isDirectory) {
|
|
1867
|
+
await walk2(path.join(dir, e.name), relPath);
|
|
1868
|
+
} else if (e.isFile && e.name !== "SKILL.md") {
|
|
1869
|
+
resources.push(relPath);
|
|
1870
|
+
}
|
|
1871
|
+
}
|
|
1872
|
+
};
|
|
1873
|
+
await walk2(skillRoot, "");
|
|
1874
|
+
return resources;
|
|
1875
|
+
}
|
|
1876
|
+
async readResourceContents(location, resources) {
|
|
1877
|
+
if (resources.length === 0) return void 0;
|
|
1878
|
+
const contents = {};
|
|
1879
|
+
for (const r of resources) {
|
|
1880
|
+
contents[r] = await this.fs.readFile(path.join(location, r));
|
|
1881
|
+
}
|
|
1882
|
+
return contents;
|
|
1883
|
+
}
|
|
1588
1884
|
async discoverSkillDirs() {
|
|
1589
1885
|
const entries = await this.fs.readdirWithFileTypes(this.baseDir);
|
|
1590
1886
|
const dirs = [];
|
|
@@ -1717,6 +2013,9 @@ var SandboxManager = class {
|
|
|
1717
2013
|
async destroy(id) {
|
|
1718
2014
|
await this.provider.destroy(id);
|
|
1719
2015
|
}
|
|
2016
|
+
async pause(id, ttlSeconds) {
|
|
2017
|
+
await this.provider.pause(id, ttlSeconds);
|
|
2018
|
+
}
|
|
1720
2019
|
async snapshot(id) {
|
|
1721
2020
|
return this.provider.snapshot(id);
|
|
1722
2021
|
}
|
|
@@ -1757,6 +2056,9 @@ var SandboxManager = class {
|
|
|
1757
2056
|
destroySandbox: async (sandboxId) => {
|
|
1758
2057
|
await this.destroy(sandboxId);
|
|
1759
2058
|
},
|
|
2059
|
+
pauseSandbox: async (sandboxId, ttlSeconds) => {
|
|
2060
|
+
await this.pause(sandboxId, ttlSeconds);
|
|
2061
|
+
},
|
|
1760
2062
|
snapshotSandbox: async (sandboxId) => {
|
|
1761
2063
|
return this.snapshot(sandboxId);
|
|
1762
2064
|
},
|
|
@@ -1770,6 +2072,75 @@ var SandboxManager = class {
|
|
|
1770
2072
|
);
|
|
1771
2073
|
}
|
|
1772
2074
|
};
|
|
2075
|
+
var NodeFsSandboxFileSystem = class {
|
|
2076
|
+
workspaceBase;
|
|
2077
|
+
constructor(workspaceBase) {
|
|
2078
|
+
this.workspaceBase = workspaceBase;
|
|
2079
|
+
}
|
|
2080
|
+
abs(path$1) {
|
|
2081
|
+
return path.resolve(this.workspaceBase, path$1);
|
|
2082
|
+
}
|
|
2083
|
+
async readFile(path) {
|
|
2084
|
+
return fs.promises.readFile(this.abs(path), "utf-8");
|
|
2085
|
+
}
|
|
2086
|
+
async readFileBuffer(path) {
|
|
2087
|
+
return fs.promises.readFile(this.abs(path));
|
|
2088
|
+
}
|
|
2089
|
+
async writeFile(path, content) {
|
|
2090
|
+
await fs.promises.writeFile(this.abs(path), content);
|
|
2091
|
+
}
|
|
2092
|
+
async appendFile(path, content) {
|
|
2093
|
+
await fs.promises.appendFile(this.abs(path), content);
|
|
2094
|
+
}
|
|
2095
|
+
async exists(path) {
|
|
2096
|
+
try {
|
|
2097
|
+
await fs.promises.access(this.abs(path));
|
|
2098
|
+
return true;
|
|
2099
|
+
} catch {
|
|
2100
|
+
return false;
|
|
2101
|
+
}
|
|
2102
|
+
}
|
|
2103
|
+
async stat(path) {
|
|
2104
|
+
const s = await fs.promises.stat(this.abs(path));
|
|
2105
|
+
return {
|
|
2106
|
+
isFile: s.isFile(),
|
|
2107
|
+
isDirectory: s.isDirectory(),
|
|
2108
|
+
isSymbolicLink: s.isSymbolicLink(),
|
|
2109
|
+
size: s.size,
|
|
2110
|
+
mtime: s.mtime
|
|
2111
|
+
};
|
|
2112
|
+
}
|
|
2113
|
+
async mkdir(path, options) {
|
|
2114
|
+
await fs.promises.mkdir(this.abs(path), options);
|
|
2115
|
+
}
|
|
2116
|
+
async readdir(path) {
|
|
2117
|
+
return fs.promises.readdir(this.abs(path));
|
|
2118
|
+
}
|
|
2119
|
+
async readdirWithFileTypes(path) {
|
|
2120
|
+
const entries = await fs.promises.readdir(this.abs(path), { withFileTypes: true });
|
|
2121
|
+
return entries.map((e) => ({
|
|
2122
|
+
name: e.name,
|
|
2123
|
+
isFile: e.isFile(),
|
|
2124
|
+
isDirectory: e.isDirectory(),
|
|
2125
|
+
isSymbolicLink: e.isSymbolicLink()
|
|
2126
|
+
}));
|
|
2127
|
+
}
|
|
2128
|
+
async rm(path, options) {
|
|
2129
|
+
await fs.promises.rm(this.abs(path), options);
|
|
2130
|
+
}
|
|
2131
|
+
async cp(src, dest, options) {
|
|
2132
|
+
await fs.promises.cp(this.abs(src), this.abs(dest), options);
|
|
2133
|
+
}
|
|
2134
|
+
async mv(src, dest) {
|
|
2135
|
+
await fs.promises.rename(this.abs(src), this.abs(dest));
|
|
2136
|
+
}
|
|
2137
|
+
async readlink(path) {
|
|
2138
|
+
return fs.promises.readlink(this.abs(path));
|
|
2139
|
+
}
|
|
2140
|
+
resolvePath(base, path$1) {
|
|
2141
|
+
return path.posix.resolve(base, path$1);
|
|
2142
|
+
}
|
|
2143
|
+
};
|
|
1773
2144
|
|
|
1774
2145
|
// src/tools/bash/handler.ts
|
|
1775
2146
|
var bashHandler = async (args, { sandbox }) => {
|
|
@@ -2026,6 +2397,7 @@ var toTree = async (fs, opts = {}) => {
|
|
|
2026
2397
|
};
|
|
2027
2398
|
|
|
2028
2399
|
exports.FileSystemSkillProvider = FileSystemSkillProvider;
|
|
2400
|
+
exports.NodeFsSandboxFileSystem = NodeFsSandboxFileSystem;
|
|
2029
2401
|
exports.SandboxManager = SandboxManager;
|
|
2030
2402
|
exports.SandboxNotFoundError = SandboxNotFoundError;
|
|
2031
2403
|
exports.SandboxNotSupportedError = SandboxNotSupportedError;
|