zeitlich 0.2.13 → 0.2.14
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 +49 -38
- package/dist/adapters/sandbox/daytona/index.cjs +205 -0
- package/dist/adapters/sandbox/daytona/index.cjs.map +1 -0
- package/dist/adapters/sandbox/daytona/index.d.cts +86 -0
- package/dist/adapters/sandbox/daytona/index.d.ts +86 -0
- package/dist/adapters/sandbox/daytona/index.js +202 -0
- package/dist/adapters/sandbox/daytona/index.js.map +1 -0
- package/dist/adapters/sandbox/inmemory/index.cjs +174 -0
- package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -0
- package/dist/adapters/sandbox/inmemory/index.d.cts +28 -0
- package/dist/adapters/sandbox/inmemory/index.d.ts +28 -0
- package/dist/adapters/sandbox/inmemory/index.js +172 -0
- package/dist/adapters/sandbox/inmemory/index.js.map +1 -0
- package/dist/adapters/sandbox/virtual/index.cjs +405 -0
- package/dist/adapters/sandbox/virtual/index.cjs.map +1 -0
- package/dist/adapters/sandbox/virtual/index.d.cts +85 -0
- package/dist/adapters/sandbox/virtual/index.d.ts +85 -0
- package/dist/adapters/sandbox/virtual/index.js +400 -0
- package/dist/adapters/sandbox/virtual/index.js.map +1 -0
- package/dist/adapters/thread/google-genai/index.cjs +284 -0
- package/dist/adapters/thread/google-genai/index.cjs.map +1 -0
- package/dist/adapters/thread/google-genai/index.d.cts +145 -0
- package/dist/adapters/thread/google-genai/index.d.ts +145 -0
- package/dist/adapters/thread/google-genai/index.js +278 -0
- package/dist/adapters/thread/google-genai/index.js.map +1 -0
- package/dist/adapters/{langchain → thread/langchain}/index.cjs +7 -9
- package/dist/adapters/thread/langchain/index.cjs.map +1 -0
- package/dist/adapters/{langchain → thread/langchain}/index.d.cts +17 -21
- package/dist/adapters/{langchain → thread/langchain}/index.d.ts +17 -21
- package/dist/adapters/{langchain → thread/langchain}/index.js +7 -9
- package/dist/adapters/thread/langchain/index.js.map +1 -0
- package/dist/index.cjs +816 -545
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +235 -74
- package/dist/index.d.ts +235 -74
- package/dist/index.js +804 -540
- package/dist/index.js.map +1 -1
- package/dist/types-B4C9txdq.d.ts +389 -0
- package/dist/{thread-manager-qc0g5Rvd.d.cts → types-B9ljZewB.d.cts} +1 -6
- package/dist/{thread-manager-qc0g5Rvd.d.ts → types-B9ljZewB.d.ts} +1 -6
- package/dist/types-BMXzv7TN.d.cts +476 -0
- package/dist/types-BMXzv7TN.d.ts +476 -0
- package/dist/types-BVP87m_W.d.cts +121 -0
- package/dist/types-CDubRtad.d.cts +115 -0
- package/dist/types-CDubRtad.d.ts +115 -0
- package/dist/types-CwwgQ_9H.d.ts +121 -0
- package/dist/types-GpMU4b0w.d.cts +389 -0
- package/dist/workflow.cjs +444 -318
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +271 -222
- package/dist/workflow.d.ts +271 -222
- package/dist/workflow.js +440 -316
- package/dist/workflow.js.map +1 -1
- package/package.json +59 -6
- package/src/adapters/sandbox/daytona/filesystem.ts +136 -0
- package/src/adapters/sandbox/daytona/index.ts +149 -0
- package/src/adapters/sandbox/daytona/types.ts +34 -0
- package/src/adapters/sandbox/inmemory/index.ts +213 -0
- package/src/adapters/sandbox/virtual/filesystem.ts +345 -0
- package/src/adapters/sandbox/virtual/index.ts +88 -0
- package/src/adapters/sandbox/virtual/mutations.ts +38 -0
- package/src/adapters/sandbox/virtual/provider.ts +101 -0
- package/src/adapters/sandbox/virtual/tree.ts +82 -0
- package/src/adapters/sandbox/virtual/types.ts +127 -0
- package/src/adapters/sandbox/virtual/virtual-sandbox.test.ts +523 -0
- package/src/adapters/sandbox/virtual/with-virtual-sandbox.ts +91 -0
- package/src/adapters/thread/google-genai/activities.ts +121 -0
- package/src/adapters/thread/google-genai/index.ts +41 -0
- package/src/adapters/thread/google-genai/model-invoker.ts +154 -0
- package/src/adapters/thread/google-genai/thread-manager.ts +169 -0
- package/src/adapters/{langchain → thread/langchain}/activities.ts +11 -15
- package/src/adapters/{langchain → thread/langchain}/index.ts +1 -1
- package/src/adapters/{langchain → thread/langchain}/model-invoker.ts +15 -18
- package/src/adapters/{langchain → thread/langchain}/thread-manager.ts +1 -1
- package/src/index.ts +32 -24
- package/src/lib/activity.ts +87 -0
- package/src/lib/hooks/index.ts +11 -0
- package/src/lib/hooks/types.ts +98 -0
- package/src/lib/model/helpers.ts +6 -0
- package/src/lib/model/index.ts +13 -0
- package/src/lib/{model-invoker.ts → model/types.ts} +18 -1
- package/src/lib/sandbox/index.ts +19 -0
- package/src/lib/sandbox/manager.ts +76 -0
- package/src/lib/sandbox/sandbox.test.ts +158 -0
- package/src/lib/{fs.ts → sandbox/tree.ts} +6 -6
- package/src/lib/sandbox/types.ts +164 -0
- package/src/lib/session/index.ts +11 -0
- package/src/lib/{session.ts → session/session.ts} +76 -48
- package/src/lib/session/types.ts +93 -0
- package/src/lib/skills/fs-provider.ts +16 -15
- package/src/lib/skills/handler.ts +31 -0
- package/src/lib/skills/index.ts +5 -1
- package/src/lib/skills/register.ts +20 -0
- package/src/lib/skills/tool.ts +47 -0
- package/src/lib/state/index.ts +9 -0
- package/src/lib/{state-manager.ts → state/manager.ts} +10 -147
- package/src/lib/state/types.ts +134 -0
- package/src/lib/subagent/define.ts +71 -0
- package/src/lib/subagent/handler.ts +99 -0
- package/src/lib/subagent/index.ts +13 -0
- package/src/lib/subagent/register.ts +53 -0
- package/src/lib/subagent/tool.ts +80 -0
- package/src/lib/subagent/types.ts +92 -0
- package/src/lib/thread/index.ts +7 -0
- package/src/lib/{thread-manager.ts → thread/manager.ts} +1 -33
- package/src/lib/thread/types.ts +33 -0
- package/src/lib/tool-router/auto-append.ts +55 -0
- package/src/lib/tool-router/index.ts +41 -0
- package/src/lib/tool-router/router.ts +462 -0
- package/src/lib/tool-router/types.ts +478 -0
- package/src/lib/tool-router/with-sandbox.ts +70 -0
- package/src/lib/types.ts +5 -382
- package/src/tools/bash/bash.test.ts +53 -55
- package/src/tools/bash/handler.ts +23 -51
- package/src/tools/edit/handler.ts +67 -81
- package/src/tools/glob/handler.ts +60 -17
- package/src/tools/read-file/handler.ts +67 -0
- package/src/tools/read-skill/handler.ts +1 -31
- package/src/tools/read-skill/tool.ts +5 -47
- package/src/tools/subagent/handler.ts +1 -100
- package/src/tools/subagent/tool.ts +5 -93
- package/src/tools/task-create/handler.ts +1 -1
- package/src/tools/task-get/handler.ts +1 -1
- package/src/tools/task-list/handler.ts +1 -1
- package/src/tools/task-update/handler.ts +1 -1
- package/src/tools/write-file/handler.ts +47 -0
- package/src/workflow.ts +88 -47
- package/tsup.config.ts +8 -1
- package/dist/adapters/langchain/index.cjs.map +0 -1
- package/dist/adapters/langchain/index.js.map +0 -1
- package/dist/model-invoker-y_zlyMqu.d.cts +0 -892
- package/dist/model-invoker-y_zlyMqu.d.ts +0 -892
- package/src/lib/tool-router.ts +0 -977
- package/src/lib/workflow-helpers.ts +0 -50
- /package/src/lib/{thread-id.ts → thread/id.ts} +0 -0
package/dist/workflow.cjs
CHANGED
|
@@ -2,153 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
var workflow = require('@temporalio/workflow');
|
|
4
4
|
var z14 = require('zod');
|
|
5
|
+
var common = require('@temporalio/common');
|
|
5
6
|
|
|
6
7
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
7
8
|
|
|
8
9
|
var z14__default = /*#__PURE__*/_interopDefault(z14);
|
|
9
10
|
|
|
10
|
-
// src/lib/session.ts
|
|
11
|
-
var SUBAGENT_TOOL_NAME = "Subagent";
|
|
12
|
-
function buildSubagentDescription(subagents) {
|
|
13
|
-
const subagentList = subagents.map((s) => {
|
|
14
|
-
const continuation = s.allowThreadContinuation ? "\n*(Supports thread continuation \u2014 pass a threadId to resume a previous conversation)*" : "";
|
|
15
|
-
return `## ${s.agentName}
|
|
16
|
-
${s.description}${continuation}`;
|
|
17
|
-
}).join("\n\n");
|
|
18
|
-
return `The ${SUBAGENT_TOOL_NAME} tool launches specialized agents (subagents) that autonomously handle complex work. Each agent type has specific capabilities and tools available to it.
|
|
19
|
-
|
|
20
|
-
# Available subagents:
|
|
21
|
-
${subagentList}
|
|
22
|
-
`;
|
|
23
|
-
}
|
|
24
|
-
function createSubagentTool(subagents) {
|
|
25
|
-
if (subagents.length === 0) {
|
|
26
|
-
throw new Error("createTaskTool requires at least one subagent");
|
|
27
|
-
}
|
|
28
|
-
const names = subagents.map((s) => s.agentName);
|
|
29
|
-
const hasThreadContinuation = subagents.some(
|
|
30
|
-
(s) => s.allowThreadContinuation
|
|
31
|
-
);
|
|
32
|
-
const baseFields = {
|
|
33
|
-
subagent: z14__default.default.enum(names).describe("The type of subagent to launch"),
|
|
34
|
-
description: z14__default.default.string().describe("A short (3-5 word) description of the task"),
|
|
35
|
-
prompt: z14__default.default.string().describe("The task for the agent to perform")
|
|
36
|
-
};
|
|
37
|
-
const schema = hasThreadContinuation ? z14__default.default.object({
|
|
38
|
-
...baseFields,
|
|
39
|
-
threadId: z14__default.default.string().nullable().describe(
|
|
40
|
-
"Thread ID to continue an existing conversation, or null to start a new one"
|
|
41
|
-
)
|
|
42
|
-
}) : z14__default.default.object(baseFields);
|
|
43
|
-
return {
|
|
44
|
-
name: SUBAGENT_TOOL_NAME,
|
|
45
|
-
description: buildSubagentDescription(subagents),
|
|
46
|
-
schema
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
var BASE62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
50
|
-
function getShortId(length = 12) {
|
|
51
|
-
const hex = workflow.uuid4().replace(/-/g, "");
|
|
52
|
-
let result = "";
|
|
53
|
-
for (let i = 0; i < length; i++) {
|
|
54
|
-
const byte = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
55
|
-
result += BASE62[byte % BASE62.length];
|
|
56
|
-
}
|
|
57
|
-
return result;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// src/tools/subagent/handler.ts
|
|
61
|
-
function createSubagentHandler(subagents) {
|
|
62
|
-
const { taskQueue: parentTaskQueue } = workflow.workflowInfo();
|
|
63
|
-
return async (args) => {
|
|
64
|
-
const config = subagents.find((s) => s.agentName === args.subagent);
|
|
65
|
-
if (!config) {
|
|
66
|
-
throw new Error(
|
|
67
|
-
`Unknown subagent: ${args.subagent}. Available: ${subagents.map((s) => s.agentName).join(", ")}`
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
const childWorkflowId = `${args.subagent}-${getShortId()}`;
|
|
71
|
-
const input = {
|
|
72
|
-
prompt: args.prompt,
|
|
73
|
-
...config.context && { context: config.context },
|
|
74
|
-
...args.threadId && config.allowThreadContinuation && { threadId: args.threadId }
|
|
75
|
-
};
|
|
76
|
-
const childOpts = {
|
|
77
|
-
workflowId: childWorkflowId,
|
|
78
|
-
args: [input],
|
|
79
|
-
taskQueue: config.taskQueue ?? parentTaskQueue
|
|
80
|
-
};
|
|
81
|
-
const { toolResponse, data, usage, threadId: childThreadId } = typeof config.workflow === "string" ? await workflow.executeChild(config.workflow, childOpts) : await workflow.executeChild(config.workflow, childOpts);
|
|
82
|
-
if (!toolResponse) {
|
|
83
|
-
return {
|
|
84
|
-
toolResponse: "Subagent workflow returned no response",
|
|
85
|
-
data: null,
|
|
86
|
-
...usage && { usage }
|
|
87
|
-
};
|
|
88
|
-
}
|
|
89
|
-
const validated = config.resultSchema ? config.resultSchema.safeParse(data) : null;
|
|
90
|
-
if (validated && !validated.success) {
|
|
91
|
-
return {
|
|
92
|
-
toolResponse: `Subagent workflow returned invalid data: ${validated.error.message}`,
|
|
93
|
-
data: null,
|
|
94
|
-
...usage && { usage }
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
let finalToolResponse = toolResponse;
|
|
98
|
-
if (config.allowThreadContinuation && childThreadId) {
|
|
99
|
-
finalToolResponse = typeof toolResponse === "string" ? `${toolResponse}
|
|
100
|
-
|
|
101
|
-
[Thread ID: ${childThreadId}]` : toolResponse;
|
|
102
|
-
}
|
|
103
|
-
return {
|
|
104
|
-
toolResponse: finalToolResponse,
|
|
105
|
-
data: validated ? validated.data : data,
|
|
106
|
-
...usage && { usage }
|
|
107
|
-
};
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
var READ_SKILL_TOOL_NAME = "ReadSkill";
|
|
111
|
-
function buildReadSkillDescription(skills) {
|
|
112
|
-
const skillList = skills.map((s) => `- **${s.name}**: ${s.description}`).join("\n");
|
|
113
|
-
return `Load the full instructions for a skill. Read the skill before following its instructions.
|
|
114
|
-
|
|
115
|
-
# Available skills:
|
|
116
|
-
${skillList}
|
|
117
|
-
`;
|
|
118
|
-
}
|
|
119
|
-
function createReadSkillTool(skills) {
|
|
120
|
-
if (skills.length === 0) {
|
|
121
|
-
throw new Error("createReadSkillTool requires at least one skill");
|
|
122
|
-
}
|
|
123
|
-
const names = skills.map((s) => s.name);
|
|
124
|
-
return {
|
|
125
|
-
name: READ_SKILL_TOOL_NAME,
|
|
126
|
-
description: buildReadSkillDescription(skills),
|
|
127
|
-
schema: z14__default.default.object({
|
|
128
|
-
skill_name: z14__default.default.enum(names).describe("The name of the skill to load")
|
|
129
|
-
})
|
|
130
|
-
};
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
// src/tools/read-skill/handler.ts
|
|
134
|
-
function createReadSkillHandler(skills) {
|
|
135
|
-
const skillMap = new Map(skills.map((s) => [s.name, s]));
|
|
136
|
-
return (args) => {
|
|
137
|
-
const skill = skillMap.get(args.skill_name);
|
|
138
|
-
if (!skill) {
|
|
139
|
-
return {
|
|
140
|
-
toolResponse: JSON.stringify({
|
|
141
|
-
error: `Skill "${args.skill_name}" not found`
|
|
142
|
-
}),
|
|
143
|
-
data: null
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
return {
|
|
147
|
-
toolResponse: skill.instructions,
|
|
148
|
-
data: null
|
|
149
|
-
};
|
|
150
|
-
};
|
|
151
|
-
}
|
|
11
|
+
// src/lib/session/session.ts
|
|
152
12
|
function createToolRouter(options) {
|
|
153
13
|
const { appendToolResult } = options;
|
|
154
14
|
const toolMap = /* @__PURE__ */ new Map();
|
|
@@ -156,45 +16,12 @@ function createToolRouter(options) {
|
|
|
156
16
|
toolMap.set(tool.name, tool);
|
|
157
17
|
}
|
|
158
18
|
const isEnabled = (tool) => tool.enabled ?? true;
|
|
159
|
-
if (options.
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
for (const s of options.subagents) {
|
|
163
|
-
if (s.hooks) subagentHooksMap.set(s.agentName, s.hooks);
|
|
164
|
-
}
|
|
165
|
-
const resolveSubagentName = (args) => args.subagent;
|
|
166
|
-
toolMap.set(SUBAGENT_TOOL_NAME, {
|
|
167
|
-
...createSubagentTool(options.subagents),
|
|
168
|
-
handler: createSubagentHandler(options.subagents),
|
|
169
|
-
...subagentHooksMap.size > 0 && {
|
|
170
|
-
hooks: {
|
|
171
|
-
onPreToolUse: async (ctx) => {
|
|
172
|
-
const hooks = subagentHooksMap.get(resolveSubagentName(ctx.args));
|
|
173
|
-
return hooks?.onPreExecution?.(ctx) ?? {};
|
|
174
|
-
},
|
|
175
|
-
onPostToolUse: async (ctx) => {
|
|
176
|
-
const hooks = subagentHooksMap.get(resolveSubagentName(ctx.args));
|
|
177
|
-
await hooks?.onPostExecution?.(ctx);
|
|
178
|
-
},
|
|
179
|
-
onPostToolUseFailure: async (ctx) => {
|
|
180
|
-
const hooks = subagentHooksMap.get(resolveSubagentName(ctx.args));
|
|
181
|
-
return hooks?.onExecutionFailure?.(ctx) ?? {};
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
});
|
|
19
|
+
if (options.plugins) {
|
|
20
|
+
for (const plugin of options.plugins) {
|
|
21
|
+
toolMap.set(plugin.name, plugin);
|
|
186
22
|
}
|
|
187
23
|
}
|
|
188
|
-
|
|
189
|
-
toolMap.set(READ_SKILL_TOOL_NAME, {
|
|
190
|
-
...createReadSkillTool(options.skills),
|
|
191
|
-
handler: createReadSkillHandler(options.skills)
|
|
192
|
-
});
|
|
193
|
-
}
|
|
194
|
-
async function processToolCall(toolCall, turn, handlerContext) {
|
|
195
|
-
const startTime = Date.now();
|
|
196
|
-
const tool = toolMap.get(toolCall.name);
|
|
197
|
-
const toolHooks = tool?.hooks;
|
|
24
|
+
async function runPreHooks(toolCall, tool, turn) {
|
|
198
25
|
let effectiveArgs = toolCall.args;
|
|
199
26
|
if (options.hooks?.onPreToolUse) {
|
|
200
27
|
const preResult = await options.hooks.onPreToolUse({
|
|
@@ -202,58 +29,105 @@ function createToolRouter(options) {
|
|
|
202
29
|
threadId: options.threadId,
|
|
203
30
|
turn
|
|
204
31
|
});
|
|
205
|
-
if (preResult?.skip) {
|
|
206
|
-
|
|
207
|
-
threadId: options.threadId,
|
|
208
|
-
toolCallId: toolCall.id,
|
|
209
|
-
toolName: toolCall.name,
|
|
210
|
-
content: JSON.stringify({
|
|
211
|
-
skipped: true,
|
|
212
|
-
reason: "Skipped by PreToolUse hook"
|
|
213
|
-
})
|
|
214
|
-
});
|
|
215
|
-
return null;
|
|
216
|
-
}
|
|
217
|
-
if (preResult?.modifiedArgs !== void 0) {
|
|
32
|
+
if (preResult?.skip) return { skip: true };
|
|
33
|
+
if (preResult?.modifiedArgs !== void 0)
|
|
218
34
|
effectiveArgs = preResult.modifiedArgs;
|
|
219
|
-
}
|
|
220
35
|
}
|
|
221
|
-
if (
|
|
222
|
-
const preResult = await
|
|
36
|
+
if (tool?.hooks?.onPreToolUse) {
|
|
37
|
+
const preResult = await tool.hooks.onPreToolUse({
|
|
223
38
|
args: effectiveArgs,
|
|
224
39
|
threadId: options.threadId,
|
|
225
40
|
turn
|
|
226
41
|
});
|
|
227
|
-
if (preResult?.skip) {
|
|
228
|
-
|
|
229
|
-
threadId: options.threadId,
|
|
230
|
-
toolCallId: toolCall.id,
|
|
231
|
-
toolName: toolCall.name,
|
|
232
|
-
content: JSON.stringify({
|
|
233
|
-
skipped: true,
|
|
234
|
-
reason: "Skipped by tool PreToolUse hook"
|
|
235
|
-
})
|
|
236
|
-
});
|
|
237
|
-
return null;
|
|
238
|
-
}
|
|
239
|
-
if (preResult?.modifiedArgs !== void 0) {
|
|
42
|
+
if (preResult?.skip) return { skip: true };
|
|
43
|
+
if (preResult?.modifiedArgs !== void 0)
|
|
240
44
|
effectiveArgs = preResult.modifiedArgs;
|
|
241
|
-
}
|
|
242
45
|
}
|
|
46
|
+
return { skip: false, args: effectiveArgs };
|
|
47
|
+
}
|
|
48
|
+
async function runFailureHooks(toolCall, tool, error, effectiveArgs, turn) {
|
|
49
|
+
const err = error instanceof Error ? error : new Error(String(error));
|
|
50
|
+
const errorStr = String(error);
|
|
51
|
+
if (tool?.hooks?.onPostToolUseFailure) {
|
|
52
|
+
const r = await tool.hooks.onPostToolUseFailure({
|
|
53
|
+
args: effectiveArgs,
|
|
54
|
+
error: err,
|
|
55
|
+
threadId: options.threadId,
|
|
56
|
+
turn
|
|
57
|
+
});
|
|
58
|
+
if (r?.fallbackContent !== void 0)
|
|
59
|
+
return { content: r.fallbackContent, result: { error: errorStr, recovered: true } };
|
|
60
|
+
if (r?.suppress)
|
|
61
|
+
return {
|
|
62
|
+
content: JSON.stringify({ error: errorStr, suppressed: true }),
|
|
63
|
+
result: { error: errorStr, suppressed: true }
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
if (options.hooks?.onPostToolUseFailure) {
|
|
67
|
+
const r = await options.hooks.onPostToolUseFailure({
|
|
68
|
+
toolCall,
|
|
69
|
+
error: err,
|
|
70
|
+
threadId: options.threadId,
|
|
71
|
+
turn
|
|
72
|
+
});
|
|
73
|
+
if (r?.fallbackContent !== void 0)
|
|
74
|
+
return { content: r.fallbackContent, result: { error: errorStr, recovered: true } };
|
|
75
|
+
if (r?.suppress)
|
|
76
|
+
return {
|
|
77
|
+
content: JSON.stringify({ error: errorStr, suppressed: true }),
|
|
78
|
+
result: { error: errorStr, suppressed: true }
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
throw workflow.ApplicationFailure.fromError(error, { nonRetryable: true });
|
|
82
|
+
}
|
|
83
|
+
async function runPostHooks(toolCall, tool, toolResult, effectiveArgs, turn, durationMs) {
|
|
84
|
+
if (tool?.hooks?.onPostToolUse) {
|
|
85
|
+
await tool.hooks.onPostToolUse({
|
|
86
|
+
args: effectiveArgs,
|
|
87
|
+
result: toolResult.data,
|
|
88
|
+
threadId: options.threadId,
|
|
89
|
+
turn,
|
|
90
|
+
durationMs
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
if (options.hooks?.onPostToolUse) {
|
|
94
|
+
await options.hooks.onPostToolUse({
|
|
95
|
+
toolCall,
|
|
96
|
+
result: toolResult,
|
|
97
|
+
threadId: options.threadId,
|
|
98
|
+
turn,
|
|
99
|
+
durationMs
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async function processToolCall(toolCall, turn, sandboxId) {
|
|
104
|
+
const startTime = Date.now();
|
|
105
|
+
const tool = toolMap.get(toolCall.name);
|
|
106
|
+
const preResult = await runPreHooks(toolCall, tool, turn);
|
|
107
|
+
if (preResult.skip) {
|
|
108
|
+
await appendToolResult({
|
|
109
|
+
threadId: options.threadId,
|
|
110
|
+
toolCallId: toolCall.id,
|
|
111
|
+
toolName: toolCall.name,
|
|
112
|
+
content: JSON.stringify({ skipped: true, reason: "Skipped by PreToolUse hook" })
|
|
113
|
+
});
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
const effectiveArgs = preResult.args;
|
|
243
117
|
let result;
|
|
244
118
|
let content;
|
|
245
119
|
let resultAppended = false;
|
|
246
120
|
try {
|
|
247
121
|
if (tool) {
|
|
248
|
-
const
|
|
249
|
-
...handlerContext ?? {},
|
|
122
|
+
const routerContext = {
|
|
250
123
|
threadId: options.threadId,
|
|
251
124
|
toolCallId: toolCall.id,
|
|
252
|
-
toolName: toolCall.name
|
|
125
|
+
toolName: toolCall.name,
|
|
126
|
+
...sandboxId !== void 0 && { sandboxId }
|
|
253
127
|
};
|
|
254
128
|
const response = await tool.handler(
|
|
255
129
|
effectiveArgs,
|
|
256
|
-
|
|
130
|
+
routerContext
|
|
257
131
|
);
|
|
258
132
|
result = response.data;
|
|
259
133
|
content = response.toolResponse;
|
|
@@ -263,47 +137,9 @@ function createToolRouter(options) {
|
|
|
263
137
|
content = JSON.stringify(result, null, 2);
|
|
264
138
|
}
|
|
265
139
|
} catch (error) {
|
|
266
|
-
const
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
const failureResult = await toolHooks.onPostToolUseFailure({
|
|
270
|
-
args: effectiveArgs,
|
|
271
|
-
error: err,
|
|
272
|
-
threadId: options.threadId,
|
|
273
|
-
turn
|
|
274
|
-
});
|
|
275
|
-
if (failureResult?.fallbackContent !== void 0) {
|
|
276
|
-
content = failureResult.fallbackContent;
|
|
277
|
-
result = { error: String(error), recovered: true };
|
|
278
|
-
recovered = true;
|
|
279
|
-
} else if (failureResult?.suppress) {
|
|
280
|
-
content = JSON.stringify({ error: String(error), suppressed: true });
|
|
281
|
-
result = { error: String(error), suppressed: true };
|
|
282
|
-
recovered = true;
|
|
283
|
-
}
|
|
284
|
-
}
|
|
285
|
-
if (!recovered && options.hooks?.onPostToolUseFailure) {
|
|
286
|
-
const failureResult = await options.hooks.onPostToolUseFailure({
|
|
287
|
-
toolCall,
|
|
288
|
-
error: err,
|
|
289
|
-
threadId: options.threadId,
|
|
290
|
-
turn
|
|
291
|
-
});
|
|
292
|
-
if (failureResult?.fallbackContent !== void 0) {
|
|
293
|
-
content = failureResult.fallbackContent;
|
|
294
|
-
result = { error: String(error), recovered: true };
|
|
295
|
-
recovered = true;
|
|
296
|
-
} else if (failureResult?.suppress) {
|
|
297
|
-
content = JSON.stringify({ error: String(error), suppressed: true });
|
|
298
|
-
result = { error: String(error), suppressed: true };
|
|
299
|
-
recovered = true;
|
|
300
|
-
}
|
|
301
|
-
}
|
|
302
|
-
if (!recovered) {
|
|
303
|
-
throw workflow.ApplicationFailure.fromError(error, {
|
|
304
|
-
nonRetryable: true
|
|
305
|
-
});
|
|
306
|
-
}
|
|
140
|
+
const recovery = await runFailureHooks(toolCall, tool, error, effectiveArgs, turn);
|
|
141
|
+
result = recovery.result;
|
|
142
|
+
content = recovery.content;
|
|
307
143
|
}
|
|
308
144
|
if (!resultAppended) {
|
|
309
145
|
await appendToolResult({
|
|
@@ -318,29 +154,10 @@ function createToolRouter(options) {
|
|
|
318
154
|
name: toolCall.name,
|
|
319
155
|
data: result
|
|
320
156
|
};
|
|
321
|
-
|
|
322
|
-
if (toolHooks?.onPostToolUse) {
|
|
323
|
-
await toolHooks.onPostToolUse({
|
|
324
|
-
args: effectiveArgs,
|
|
325
|
-
result,
|
|
326
|
-
threadId: options.threadId,
|
|
327
|
-
turn,
|
|
328
|
-
durationMs
|
|
329
|
-
});
|
|
330
|
-
}
|
|
331
|
-
if (options.hooks?.onPostToolUse) {
|
|
332
|
-
await options.hooks.onPostToolUse({
|
|
333
|
-
toolCall,
|
|
334
|
-
result: toolResult,
|
|
335
|
-
threadId: options.threadId,
|
|
336
|
-
turn,
|
|
337
|
-
durationMs
|
|
338
|
-
});
|
|
339
|
-
}
|
|
157
|
+
await runPostHooks(toolCall, tool, toolResult, effectiveArgs, turn, Date.now() - startTime);
|
|
340
158
|
return toolResult;
|
|
341
159
|
}
|
|
342
160
|
return {
|
|
343
|
-
// --- Methods from registry ---
|
|
344
161
|
hasTools() {
|
|
345
162
|
return Array.from(toolMap.values()).some(isEnabled);
|
|
346
163
|
},
|
|
@@ -364,32 +181,25 @@ function createToolRouter(options) {
|
|
|
364
181
|
return Array.from(toolMap.entries()).filter(([, tool]) => isEnabled(tool)).map(([name]) => name);
|
|
365
182
|
},
|
|
366
183
|
getToolDefinitions() {
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
description: tool.description,
|
|
375
|
-
schema: tool.schema,
|
|
376
|
-
strict: tool.strict,
|
|
377
|
-
max_uses: tool.max_uses
|
|
378
|
-
})),
|
|
379
|
-
...activeSubagents.length > 0 ? [createSubagentTool(activeSubagents)] : [],
|
|
380
|
-
...activeSkills.length > 0 ? [createReadSkillTool(activeSkills)] : []
|
|
381
|
-
];
|
|
184
|
+
return Array.from(toolMap).filter(([, tool]) => isEnabled(tool)).map(([name, tool]) => ({
|
|
185
|
+
name,
|
|
186
|
+
description: tool.description,
|
|
187
|
+
schema: tool.schema,
|
|
188
|
+
strict: tool.strict,
|
|
189
|
+
max_uses: tool.max_uses
|
|
190
|
+
}));
|
|
382
191
|
},
|
|
383
|
-
// --- Methods for processing tool calls ---
|
|
384
192
|
async processToolCalls(toolCalls, context) {
|
|
385
193
|
if (toolCalls.length === 0) {
|
|
386
194
|
return [];
|
|
387
195
|
}
|
|
388
196
|
const turn = context?.turn ?? 0;
|
|
389
|
-
const
|
|
197
|
+
const sandboxId = context?.sandboxId;
|
|
390
198
|
if (options.parallel) {
|
|
391
199
|
const results2 = await Promise.all(
|
|
392
|
-
toolCalls.map(
|
|
200
|
+
toolCalls.map(
|
|
201
|
+
(tc) => processToolCall(tc, turn, sandboxId)
|
|
202
|
+
)
|
|
393
203
|
);
|
|
394
204
|
return results2.filter(
|
|
395
205
|
(r) => r !== null
|
|
@@ -397,7 +207,11 @@ function createToolRouter(options) {
|
|
|
397
207
|
}
|
|
398
208
|
const results = [];
|
|
399
209
|
for (const toolCall of toolCalls) {
|
|
400
|
-
const result = await processToolCall(
|
|
210
|
+
const result = await processToolCall(
|
|
211
|
+
toolCall,
|
|
212
|
+
turn,
|
|
213
|
+
sandboxId
|
|
214
|
+
);
|
|
401
215
|
if (result !== null) {
|
|
402
216
|
results.push(result);
|
|
403
217
|
}
|
|
@@ -409,17 +223,16 @@ function createToolRouter(options) {
|
|
|
409
223
|
if (matchingCalls.length === 0) {
|
|
410
224
|
return [];
|
|
411
225
|
}
|
|
412
|
-
const handlerContext = context?.handlerContext ?? {};
|
|
413
226
|
const processOne = async (toolCall) => {
|
|
414
|
-
const
|
|
415
|
-
...handlerContext ?? {},
|
|
227
|
+
const routerContext = {
|
|
416
228
|
threadId: options.threadId,
|
|
417
229
|
toolCallId: toolCall.id,
|
|
418
|
-
toolName: toolCall.name
|
|
230
|
+
toolName: toolCall.name,
|
|
231
|
+
...context?.sandboxId !== void 0 && { sandboxId: context.sandboxId }
|
|
419
232
|
};
|
|
420
233
|
const response = await handler(
|
|
421
234
|
toolCall.args,
|
|
422
|
-
|
|
235
|
+
routerContext
|
|
423
236
|
);
|
|
424
237
|
if (!response.resultAppended) {
|
|
425
238
|
await appendToolResult({
|
|
@@ -444,7 +257,6 @@ function createToolRouter(options) {
|
|
|
444
257
|
}
|
|
445
258
|
return results;
|
|
446
259
|
},
|
|
447
|
-
// --- Utility methods ---
|
|
448
260
|
filterByName(toolCalls, name) {
|
|
449
261
|
return toolCalls.filter(
|
|
450
262
|
(tc) => tc.name === name
|
|
@@ -461,14 +273,198 @@ function createToolRouter(options) {
|
|
|
461
273
|
function defineTool(tool) {
|
|
462
274
|
return tool;
|
|
463
275
|
}
|
|
464
|
-
function defineSubagent(config) {
|
|
465
|
-
return config;
|
|
466
|
-
}
|
|
467
276
|
function hasNoOtherToolCalls(toolCalls, excludeName) {
|
|
468
277
|
return toolCalls.filter((tc) => tc.name !== excludeName).length === 0;
|
|
469
278
|
}
|
|
279
|
+
var BASE62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
280
|
+
function getShortId(length = 12) {
|
|
281
|
+
const hex = workflow.uuid4().replace(/-/g, "");
|
|
282
|
+
let result = "";
|
|
283
|
+
for (let i = 0; i < length; i++) {
|
|
284
|
+
const byte = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
|
|
285
|
+
result += BASE62[byte % BASE62.length];
|
|
286
|
+
}
|
|
287
|
+
return result;
|
|
288
|
+
}
|
|
289
|
+
var SUBAGENT_TOOL_NAME = "Subagent";
|
|
290
|
+
function buildSubagentDescription(subagents) {
|
|
291
|
+
const subagentList = subagents.map((s) => {
|
|
292
|
+
const continuation = s.allowThreadContinuation ? "\n*(Supports thread continuation \u2014 pass a threadId to resume a previous conversation)*" : "";
|
|
293
|
+
return `## ${s.agentName}
|
|
294
|
+
${s.description}${continuation}`;
|
|
295
|
+
}).join("\n\n");
|
|
296
|
+
return `The ${SUBAGENT_TOOL_NAME} tool launches specialized agents (subagents) that autonomously handle complex work. Each agent type has specific capabilities and tools available to it.
|
|
297
|
+
|
|
298
|
+
# Available subagents:
|
|
299
|
+
${subagentList}
|
|
300
|
+
`;
|
|
301
|
+
}
|
|
302
|
+
function createSubagentTool(subagents) {
|
|
303
|
+
if (subagents.length === 0) {
|
|
304
|
+
throw new Error("createSubagentTool requires at least one subagent");
|
|
305
|
+
}
|
|
306
|
+
const names = subagents.map((s) => s.agentName);
|
|
307
|
+
const hasThreadContinuation = subagents.some(
|
|
308
|
+
(s) => s.allowThreadContinuation
|
|
309
|
+
);
|
|
310
|
+
const baseFields = {
|
|
311
|
+
subagent: z14__default.default.enum(names).describe("The type of subagent to launch"),
|
|
312
|
+
description: z14__default.default.string().describe("A short (3-5 word) description of the task"),
|
|
313
|
+
prompt: z14__default.default.string().describe("The task for the agent to perform")
|
|
314
|
+
};
|
|
315
|
+
const schema = hasThreadContinuation ? z14__default.default.object({
|
|
316
|
+
...baseFields,
|
|
317
|
+
threadId: z14__default.default.string().nullable().describe(
|
|
318
|
+
"Thread ID to continue an existing conversation, or null to start a new one"
|
|
319
|
+
)
|
|
320
|
+
}) : z14__default.default.object(baseFields);
|
|
321
|
+
return {
|
|
322
|
+
name: SUBAGENT_TOOL_NAME,
|
|
323
|
+
description: buildSubagentDescription(subagents),
|
|
324
|
+
schema
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
function createSubagentHandler(subagents) {
|
|
328
|
+
const { taskQueue: parentTaskQueue } = workflow.workflowInfo();
|
|
329
|
+
return async (args, context) => {
|
|
330
|
+
const config = subagents.find((s) => s.agentName === args.subagent);
|
|
331
|
+
if (!config) {
|
|
332
|
+
throw new Error(
|
|
333
|
+
`Unknown subagent: ${args.subagent}. Available: ${subagents.map((s) => s.agentName).join(", ")}`
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
const childWorkflowId = `${args.subagent}-${getShortId()}`;
|
|
337
|
+
const { sandboxId: parentSandboxId } = context;
|
|
338
|
+
const inheritSandbox = config.sandbox !== "own" && !!parentSandboxId;
|
|
339
|
+
const input = {
|
|
340
|
+
prompt: args.prompt,
|
|
341
|
+
...config.context && { context: config.context },
|
|
342
|
+
...args.threadId && args.threadId !== null && config.allowThreadContinuation && { previousThreadId: args.threadId },
|
|
343
|
+
...inheritSandbox && { sandboxId: parentSandboxId }
|
|
344
|
+
};
|
|
345
|
+
const childOpts = {
|
|
346
|
+
workflowId: childWorkflowId,
|
|
347
|
+
args: [input],
|
|
348
|
+
taskQueue: config.taskQueue ?? parentTaskQueue
|
|
349
|
+
};
|
|
350
|
+
const {
|
|
351
|
+
toolResponse,
|
|
352
|
+
data,
|
|
353
|
+
usage,
|
|
354
|
+
threadId: childThreadId
|
|
355
|
+
} = typeof config.workflow === "string" ? await workflow.executeChild(config.workflow, childOpts) : await workflow.executeChild(config.workflow, childOpts);
|
|
356
|
+
if (!toolResponse) {
|
|
357
|
+
return {
|
|
358
|
+
toolResponse: "Subagent workflow returned no response",
|
|
359
|
+
data: null,
|
|
360
|
+
...usage && { usage }
|
|
361
|
+
};
|
|
362
|
+
}
|
|
363
|
+
const validated = config.resultSchema ? config.resultSchema.safeParse(data) : null;
|
|
364
|
+
if (validated && !validated.success) {
|
|
365
|
+
return {
|
|
366
|
+
toolResponse: `Subagent workflow returned invalid data: ${validated.error.message}`,
|
|
367
|
+
data: null,
|
|
368
|
+
...usage && { usage }
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
let finalToolResponse = toolResponse;
|
|
372
|
+
if (config.allowThreadContinuation && childThreadId) {
|
|
373
|
+
finalToolResponse = typeof toolResponse === "string" ? `${toolResponse}
|
|
374
|
+
|
|
375
|
+
[Thread ID: ${childThreadId}]` : toolResponse;
|
|
376
|
+
}
|
|
377
|
+
return {
|
|
378
|
+
toolResponse: finalToolResponse,
|
|
379
|
+
data: validated ? validated.data : data,
|
|
380
|
+
...usage && { usage }
|
|
381
|
+
};
|
|
382
|
+
};
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// src/lib/subagent/register.ts
|
|
386
|
+
function buildSubagentRegistration(subagents) {
|
|
387
|
+
const enabled = subagents.filter((s) => s.enabled ?? true);
|
|
388
|
+
if (enabled.length === 0) return null;
|
|
389
|
+
const subagentHooksMap = /* @__PURE__ */ new Map();
|
|
390
|
+
for (const s of enabled) {
|
|
391
|
+
if (s.hooks) subagentHooksMap.set(s.agentName, s.hooks);
|
|
392
|
+
}
|
|
393
|
+
const resolveSubagentName = (args) => args.subagent;
|
|
394
|
+
return {
|
|
395
|
+
...createSubagentTool(enabled),
|
|
396
|
+
handler: createSubagentHandler(enabled),
|
|
397
|
+
...subagentHooksMap.size > 0 && {
|
|
398
|
+
hooks: {
|
|
399
|
+
onPreToolUse: async (ctx) => {
|
|
400
|
+
const hooks = subagentHooksMap.get(resolveSubagentName(ctx.args));
|
|
401
|
+
return hooks?.onPreExecution?.(ctx) ?? {};
|
|
402
|
+
},
|
|
403
|
+
onPostToolUse: async (ctx) => {
|
|
404
|
+
const hooks = subagentHooksMap.get(resolveSubagentName(ctx.args));
|
|
405
|
+
await hooks?.onPostExecution?.(ctx);
|
|
406
|
+
},
|
|
407
|
+
onPostToolUseFailure: async (ctx) => {
|
|
408
|
+
const hooks = subagentHooksMap.get(resolveSubagentName(ctx.args));
|
|
409
|
+
return hooks?.onExecutionFailure?.(ctx) ?? {};
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
var READ_SKILL_TOOL_NAME = "ReadSkill";
|
|
416
|
+
function buildReadSkillDescription(skills) {
|
|
417
|
+
const skillList = skills.map((s) => `- **${s.name}**: ${s.description}`).join("\n");
|
|
418
|
+
return `Load the full instructions for a skill. Read the skill before following its instructions.
|
|
419
|
+
|
|
420
|
+
# Available skills:
|
|
421
|
+
${skillList}
|
|
422
|
+
`;
|
|
423
|
+
}
|
|
424
|
+
function createReadSkillTool(skills) {
|
|
425
|
+
if (skills.length === 0) {
|
|
426
|
+
throw new Error("createReadSkillTool requires at least one skill");
|
|
427
|
+
}
|
|
428
|
+
const names = skills.map((s) => s.name);
|
|
429
|
+
return {
|
|
430
|
+
name: READ_SKILL_TOOL_NAME,
|
|
431
|
+
description: buildReadSkillDescription(skills),
|
|
432
|
+
schema: z14__default.default.object({
|
|
433
|
+
skill_name: z14__default.default.enum(names).describe("The name of the skill to load")
|
|
434
|
+
})
|
|
435
|
+
};
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// src/lib/skills/handler.ts
|
|
439
|
+
function createReadSkillHandler(skills) {
|
|
440
|
+
const skillMap = new Map(skills.map((s) => [s.name, s]));
|
|
441
|
+
return (args) => {
|
|
442
|
+
const skill = skillMap.get(args.skill_name);
|
|
443
|
+
if (!skill) {
|
|
444
|
+
return {
|
|
445
|
+
toolResponse: JSON.stringify({
|
|
446
|
+
error: `Skill "${args.skill_name}" not found`
|
|
447
|
+
}),
|
|
448
|
+
data: null
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
return {
|
|
452
|
+
toolResponse: skill.instructions,
|
|
453
|
+
data: null
|
|
454
|
+
};
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// src/lib/skills/register.ts
|
|
459
|
+
function buildSkillRegistration(skills) {
|
|
460
|
+
if (skills.length === 0) return null;
|
|
461
|
+
return {
|
|
462
|
+
...createReadSkillTool(skills),
|
|
463
|
+
handler: createReadSkillHandler(skills)
|
|
464
|
+
};
|
|
465
|
+
}
|
|
470
466
|
|
|
471
|
-
// src/lib/session.ts
|
|
467
|
+
// src/lib/session/session.ts
|
|
472
468
|
var createSession = async ({
|
|
473
469
|
threadId: providedThreadId,
|
|
474
470
|
agentName,
|
|
@@ -484,7 +480,9 @@ var createSession = async ({
|
|
|
484
480
|
hooks = {},
|
|
485
481
|
appendSystemPrompt = true,
|
|
486
482
|
continueThread = false,
|
|
487
|
-
waitForInputTimeout = "48h"
|
|
483
|
+
waitForInputTimeout = "48h",
|
|
484
|
+
sandbox: sandboxOps,
|
|
485
|
+
sandboxId: inheritedSandboxId
|
|
488
486
|
}) => {
|
|
489
487
|
const threadId = providedThreadId ?? getShortId();
|
|
490
488
|
const {
|
|
@@ -493,13 +491,21 @@ var createSession = async ({
|
|
|
493
491
|
initializeThread,
|
|
494
492
|
appendSystemMessage
|
|
495
493
|
} = threadOps ?? proxyDefaultThreadOps();
|
|
494
|
+
const plugins = [];
|
|
495
|
+
if (subagents) {
|
|
496
|
+
const reg = buildSubagentRegistration(subagents);
|
|
497
|
+
if (reg) plugins.push(reg);
|
|
498
|
+
}
|
|
499
|
+
if (skills) {
|
|
500
|
+
const reg = buildSkillRegistration(skills);
|
|
501
|
+
if (reg) plugins.push(reg);
|
|
502
|
+
}
|
|
496
503
|
const toolRouter = createToolRouter({
|
|
497
504
|
tools,
|
|
498
505
|
appendToolResult,
|
|
499
506
|
threadId,
|
|
500
507
|
hooks,
|
|
501
|
-
|
|
502
|
-
skills,
|
|
508
|
+
plugins,
|
|
503
509
|
parallel: processToolsInParallel
|
|
504
510
|
});
|
|
505
511
|
const callSessionEnd = async (exitReason, turns) => {
|
|
@@ -536,6 +542,17 @@ var createSession = async ({
|
|
|
536
542
|
stateManager.run();
|
|
537
543
|
}
|
|
538
544
|
);
|
|
545
|
+
let sandboxId = inheritedSandboxId;
|
|
546
|
+
const ownsSandbox = !sandboxId && !!sandboxOps;
|
|
547
|
+
if (ownsSandbox) {
|
|
548
|
+
const result = await sandboxOps.createSandbox({ id: threadId });
|
|
549
|
+
sandboxId = result.sandboxId;
|
|
550
|
+
if (result.stateUpdate) {
|
|
551
|
+
stateManager.mergeUpdate(
|
|
552
|
+
result.stateUpdate
|
|
553
|
+
);
|
|
554
|
+
}
|
|
555
|
+
}
|
|
539
556
|
if (hooks.onSessionStart) {
|
|
540
557
|
await hooks.onSessionStart({
|
|
541
558
|
threadId,
|
|
@@ -576,6 +593,7 @@ var createSession = async ({
|
|
|
576
593
|
stateManager.complete();
|
|
577
594
|
exitReason = "completed";
|
|
578
595
|
return {
|
|
596
|
+
threadId,
|
|
579
597
|
finalMessage: message,
|
|
580
598
|
exitReason,
|
|
581
599
|
usage: stateManager.getTotalUsage()
|
|
@@ -599,7 +617,8 @@ var createSession = async ({
|
|
|
599
617
|
const toolCallResults = await toolRouter.processToolCalls(
|
|
600
618
|
parsedToolCalls,
|
|
601
619
|
{
|
|
602
|
-
turn: currentTurn
|
|
620
|
+
turn: currentTurn,
|
|
621
|
+
...sandboxId !== void 0 && { sandboxId }
|
|
603
622
|
}
|
|
604
623
|
);
|
|
605
624
|
for (const result of toolCallResults) {
|
|
@@ -627,8 +646,12 @@ var createSession = async ({
|
|
|
627
646
|
throw workflow.ApplicationFailure.fromError(error);
|
|
628
647
|
} finally {
|
|
629
648
|
await callSessionEnd(exitReason, stateManager.getTurns());
|
|
649
|
+
if (ownsSandbox && sandboxId && sandboxOps) {
|
|
650
|
+
await sandboxOps.destroySandbox(sandboxId);
|
|
651
|
+
}
|
|
630
652
|
}
|
|
631
653
|
return {
|
|
654
|
+
threadId,
|
|
632
655
|
finalMessage: null,
|
|
633
656
|
exitReason,
|
|
634
657
|
usage: stateManager.getTotalUsage()
|
|
@@ -649,16 +672,26 @@ function proxyDefaultThreadOps(options) {
|
|
|
649
672
|
}
|
|
650
673
|
);
|
|
651
674
|
}
|
|
675
|
+
function proxySandboxOps(options) {
|
|
676
|
+
return workflow.proxyActivities(
|
|
677
|
+
options ?? {
|
|
678
|
+
startToCloseTimeout: "30s",
|
|
679
|
+
retry: {
|
|
680
|
+
maximumAttempts: 3,
|
|
681
|
+
initialInterval: "2s",
|
|
682
|
+
maximumInterval: "30s",
|
|
683
|
+
backoffCoefficient: 2
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
);
|
|
687
|
+
}
|
|
652
688
|
|
|
653
689
|
// src/lib/types.ts
|
|
654
|
-
var agentQueryName = (agentName) => `get${agentName}State`;
|
|
655
|
-
var agentStateChangeUpdateName = (agentName) => `waitFor${agentName}StateChange`;
|
|
656
690
|
function isTerminalStatus(status) {
|
|
657
691
|
return status === "COMPLETED" || status === "FAILED" || status === "CANCELLED";
|
|
658
692
|
}
|
|
659
693
|
function createAgentStateManager({
|
|
660
|
-
initialState
|
|
661
|
-
agentName
|
|
694
|
+
initialState
|
|
662
695
|
}) {
|
|
663
696
|
let status = initialState?.status ?? "RUNNING";
|
|
664
697
|
let version = initialState?.version ?? 0;
|
|
@@ -689,11 +722,9 @@ function createAgentStateManager({
|
|
|
689
722
|
...customState
|
|
690
723
|
};
|
|
691
724
|
}
|
|
692
|
-
const stateQuery = workflow.defineQuery(
|
|
693
|
-
agentQueryName(agentName)
|
|
694
|
-
);
|
|
725
|
+
const stateQuery = workflow.defineQuery("getAgentState");
|
|
695
726
|
const stateChangeUpdate = workflow.defineUpdate(
|
|
696
|
-
|
|
727
|
+
"waitForAgentStateChange"
|
|
697
728
|
);
|
|
698
729
|
workflow.setHandler(stateQuery, () => buildState());
|
|
699
730
|
workflow.setHandler(stateChangeUpdate, async (lastKnownVersion) => {
|
|
@@ -757,6 +788,10 @@ function createAgentStateManager({
|
|
|
757
788
|
customState[key] = value;
|
|
758
789
|
version++;
|
|
759
790
|
},
|
|
791
|
+
mergeUpdate(update) {
|
|
792
|
+
Object.assign(customState, update);
|
|
793
|
+
version++;
|
|
794
|
+
},
|
|
760
795
|
getCurrentState() {
|
|
761
796
|
return buildState();
|
|
762
797
|
},
|
|
@@ -812,6 +847,95 @@ function createAgentStateManager({
|
|
|
812
847
|
};
|
|
813
848
|
}
|
|
814
849
|
|
|
850
|
+
// src/lib/subagent/define.ts
|
|
851
|
+
function defineSubagent(config) {
|
|
852
|
+
return config;
|
|
853
|
+
}
|
|
854
|
+
var SandboxNotSupportedError = class extends common.ApplicationFailure {
|
|
855
|
+
constructor(operation) {
|
|
856
|
+
super(
|
|
857
|
+
`Sandbox does not support: ${operation}`,
|
|
858
|
+
"SandboxNotSupportedError",
|
|
859
|
+
true
|
|
860
|
+
);
|
|
861
|
+
}
|
|
862
|
+
};
|
|
863
|
+
var SandboxNotFoundError = class extends common.ApplicationFailure {
|
|
864
|
+
constructor(sandboxId) {
|
|
865
|
+
super(`Sandbox not found: ${sandboxId}`, "SandboxNotFoundError", true);
|
|
866
|
+
}
|
|
867
|
+
};
|
|
868
|
+
|
|
869
|
+
// src/adapters/sandbox/virtual/mutations.ts
|
|
870
|
+
function applyVirtualTreeMutations(stateManager, mutations) {
|
|
871
|
+
let tree = [...stateManager.get("fileTree")];
|
|
872
|
+
for (const m of mutations) {
|
|
873
|
+
switch (m.type) {
|
|
874
|
+
case "add":
|
|
875
|
+
tree.push(m.entry);
|
|
876
|
+
break;
|
|
877
|
+
case "remove":
|
|
878
|
+
tree = tree.filter((e) => e.path !== m.path);
|
|
879
|
+
break;
|
|
880
|
+
case "update":
|
|
881
|
+
tree = tree.map(
|
|
882
|
+
(e) => e.path === m.path ? { ...e, ...m.entry } : e
|
|
883
|
+
);
|
|
884
|
+
break;
|
|
885
|
+
}
|
|
886
|
+
}
|
|
887
|
+
stateManager.set("fileTree", tree);
|
|
888
|
+
return tree;
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// src/adapters/sandbox/virtual/tree.ts
|
|
892
|
+
var buildTree = (entries) => {
|
|
893
|
+
const root = { name: "/", children: /* @__PURE__ */ new Map(), isFile: false };
|
|
894
|
+
for (const entry of entries) {
|
|
895
|
+
const parts = entry.path.split("/").filter(Boolean);
|
|
896
|
+
let current = root;
|
|
897
|
+
for (const part of parts) {
|
|
898
|
+
let child = current.children.get(part);
|
|
899
|
+
if (!child) {
|
|
900
|
+
child = { name: part, children: /* @__PURE__ */ new Map(), isFile: false };
|
|
901
|
+
current.children.set(part, child);
|
|
902
|
+
}
|
|
903
|
+
current = child;
|
|
904
|
+
}
|
|
905
|
+
current.isFile = current.children.size === 0;
|
|
906
|
+
}
|
|
907
|
+
return root;
|
|
908
|
+
};
|
|
909
|
+
var printNode = (node, tab, sort) => {
|
|
910
|
+
const entries = [...node.children.values()];
|
|
911
|
+
if (sort) {
|
|
912
|
+
entries.sort((a, b) => {
|
|
913
|
+
if (!a.isFile && !b.isFile) return a.name.localeCompare(b.name);
|
|
914
|
+
if (!a.isFile) return -1;
|
|
915
|
+
if (!b.isFile) return 1;
|
|
916
|
+
return a.name.localeCompare(b.name);
|
|
917
|
+
});
|
|
918
|
+
}
|
|
919
|
+
let str = "";
|
|
920
|
+
for (const [i, entry] of entries.entries()) {
|
|
921
|
+
const isLast = i === entries.length - 1;
|
|
922
|
+
const branch = isLast ? "\u2514\u2500" : "\u251C\u2500";
|
|
923
|
+
const childTab = tab + (isLast ? " " : "\u2502 ");
|
|
924
|
+
if (entry.isFile) {
|
|
925
|
+
str += "\n" + tab + branch + " " + entry.name;
|
|
926
|
+
} else {
|
|
927
|
+
const subtree = printNode(entry, childTab, sort);
|
|
928
|
+
str += "\n" + tab + branch + " " + entry.name + "/" + subtree;
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
return str;
|
|
932
|
+
};
|
|
933
|
+
function formatVirtualFileTree(entries, opts = {}) {
|
|
934
|
+
const sort = opts.sort ?? true;
|
|
935
|
+
const root = buildTree(entries);
|
|
936
|
+
return "/" + printNode(root, "", sort);
|
|
937
|
+
}
|
|
938
|
+
|
|
815
939
|
// src/lib/skills/parse.ts
|
|
816
940
|
function parseSkillFile(raw) {
|
|
817
941
|
const trimmed = raw.replace(/^\uFEFF/, "");
|
|
@@ -1234,8 +1358,9 @@ var createAskUserQuestionHandler = () => async (args) => {
|
|
|
1234
1358
|
};
|
|
1235
1359
|
};
|
|
1236
1360
|
|
|
1237
|
-
exports.
|
|
1238
|
-
exports.
|
|
1361
|
+
exports.SandboxNotFoundError = SandboxNotFoundError;
|
|
1362
|
+
exports.SandboxNotSupportedError = SandboxNotSupportedError;
|
|
1363
|
+
exports.applyVirtualTreeMutations = applyVirtualTreeMutations;
|
|
1239
1364
|
exports.askUserQuestionTool = askUserQuestionTool;
|
|
1240
1365
|
exports.bashTool = bashTool;
|
|
1241
1366
|
exports.createAgentStateManager = createAgentStateManager;
|
|
@@ -1244,7 +1369,6 @@ exports.createBashToolDescription = createBashToolDescription;
|
|
|
1244
1369
|
exports.createReadSkillHandler = createReadSkillHandler;
|
|
1245
1370
|
exports.createReadSkillTool = createReadSkillTool;
|
|
1246
1371
|
exports.createSession = createSession;
|
|
1247
|
-
exports.createSubagentTool = createSubagentTool;
|
|
1248
1372
|
exports.createTaskCreateHandler = createTaskCreateHandler;
|
|
1249
1373
|
exports.createTaskGetHandler = createTaskGetHandler;
|
|
1250
1374
|
exports.createTaskListHandler = createTaskListHandler;
|
|
@@ -1253,6 +1377,7 @@ exports.createToolRouter = createToolRouter;
|
|
|
1253
1377
|
exports.defineSubagent = defineSubagent;
|
|
1254
1378
|
exports.defineTool = defineTool;
|
|
1255
1379
|
exports.editTool = editTool;
|
|
1380
|
+
exports.formatVirtualFileTree = formatVirtualFileTree;
|
|
1256
1381
|
exports.getShortId = getShortId;
|
|
1257
1382
|
exports.globTool = globTool;
|
|
1258
1383
|
exports.grepTool = grepTool;
|
|
@@ -1260,6 +1385,7 @@ exports.hasNoOtherToolCalls = hasNoOtherToolCalls;
|
|
|
1260
1385
|
exports.isTerminalStatus = isTerminalStatus;
|
|
1261
1386
|
exports.parseSkillFile = parseSkillFile;
|
|
1262
1387
|
exports.proxyDefaultThreadOps = proxyDefaultThreadOps;
|
|
1388
|
+
exports.proxySandboxOps = proxySandboxOps;
|
|
1263
1389
|
exports.readFileTool = readFileTool;
|
|
1264
1390
|
exports.taskCreateTool = taskCreateTool;
|
|
1265
1391
|
exports.taskGetTool = taskGetTool;
|