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.
Files changed (135) hide show
  1. package/README.md +49 -38
  2. package/dist/adapters/sandbox/daytona/index.cjs +205 -0
  3. package/dist/adapters/sandbox/daytona/index.cjs.map +1 -0
  4. package/dist/adapters/sandbox/daytona/index.d.cts +86 -0
  5. package/dist/adapters/sandbox/daytona/index.d.ts +86 -0
  6. package/dist/adapters/sandbox/daytona/index.js +202 -0
  7. package/dist/adapters/sandbox/daytona/index.js.map +1 -0
  8. package/dist/adapters/sandbox/inmemory/index.cjs +174 -0
  9. package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -0
  10. package/dist/adapters/sandbox/inmemory/index.d.cts +28 -0
  11. package/dist/adapters/sandbox/inmemory/index.d.ts +28 -0
  12. package/dist/adapters/sandbox/inmemory/index.js +172 -0
  13. package/dist/adapters/sandbox/inmemory/index.js.map +1 -0
  14. package/dist/adapters/sandbox/virtual/index.cjs +405 -0
  15. package/dist/adapters/sandbox/virtual/index.cjs.map +1 -0
  16. package/dist/adapters/sandbox/virtual/index.d.cts +85 -0
  17. package/dist/adapters/sandbox/virtual/index.d.ts +85 -0
  18. package/dist/adapters/sandbox/virtual/index.js +400 -0
  19. package/dist/adapters/sandbox/virtual/index.js.map +1 -0
  20. package/dist/adapters/thread/google-genai/index.cjs +284 -0
  21. package/dist/adapters/thread/google-genai/index.cjs.map +1 -0
  22. package/dist/adapters/thread/google-genai/index.d.cts +145 -0
  23. package/dist/adapters/thread/google-genai/index.d.ts +145 -0
  24. package/dist/adapters/thread/google-genai/index.js +278 -0
  25. package/dist/adapters/thread/google-genai/index.js.map +1 -0
  26. package/dist/adapters/{langchain → thread/langchain}/index.cjs +7 -9
  27. package/dist/adapters/thread/langchain/index.cjs.map +1 -0
  28. package/dist/adapters/{langchain → thread/langchain}/index.d.cts +17 -21
  29. package/dist/adapters/{langchain → thread/langchain}/index.d.ts +17 -21
  30. package/dist/adapters/{langchain → thread/langchain}/index.js +7 -9
  31. package/dist/adapters/thread/langchain/index.js.map +1 -0
  32. package/dist/index.cjs +816 -545
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +235 -74
  35. package/dist/index.d.ts +235 -74
  36. package/dist/index.js +804 -540
  37. package/dist/index.js.map +1 -1
  38. package/dist/types-B4C9txdq.d.ts +389 -0
  39. package/dist/{thread-manager-qc0g5Rvd.d.cts → types-B9ljZewB.d.cts} +1 -6
  40. package/dist/{thread-manager-qc0g5Rvd.d.ts → types-B9ljZewB.d.ts} +1 -6
  41. package/dist/types-BMXzv7TN.d.cts +476 -0
  42. package/dist/types-BMXzv7TN.d.ts +476 -0
  43. package/dist/types-BVP87m_W.d.cts +121 -0
  44. package/dist/types-CDubRtad.d.cts +115 -0
  45. package/dist/types-CDubRtad.d.ts +115 -0
  46. package/dist/types-CwwgQ_9H.d.ts +121 -0
  47. package/dist/types-GpMU4b0w.d.cts +389 -0
  48. package/dist/workflow.cjs +444 -318
  49. package/dist/workflow.cjs.map +1 -1
  50. package/dist/workflow.d.cts +271 -222
  51. package/dist/workflow.d.ts +271 -222
  52. package/dist/workflow.js +440 -316
  53. package/dist/workflow.js.map +1 -1
  54. package/package.json +59 -6
  55. package/src/adapters/sandbox/daytona/filesystem.ts +136 -0
  56. package/src/adapters/sandbox/daytona/index.ts +149 -0
  57. package/src/adapters/sandbox/daytona/types.ts +34 -0
  58. package/src/adapters/sandbox/inmemory/index.ts +213 -0
  59. package/src/adapters/sandbox/virtual/filesystem.ts +345 -0
  60. package/src/adapters/sandbox/virtual/index.ts +88 -0
  61. package/src/adapters/sandbox/virtual/mutations.ts +38 -0
  62. package/src/adapters/sandbox/virtual/provider.ts +101 -0
  63. package/src/adapters/sandbox/virtual/tree.ts +82 -0
  64. package/src/adapters/sandbox/virtual/types.ts +127 -0
  65. package/src/adapters/sandbox/virtual/virtual-sandbox.test.ts +523 -0
  66. package/src/adapters/sandbox/virtual/with-virtual-sandbox.ts +91 -0
  67. package/src/adapters/thread/google-genai/activities.ts +121 -0
  68. package/src/adapters/thread/google-genai/index.ts +41 -0
  69. package/src/adapters/thread/google-genai/model-invoker.ts +154 -0
  70. package/src/adapters/thread/google-genai/thread-manager.ts +169 -0
  71. package/src/adapters/{langchain → thread/langchain}/activities.ts +11 -15
  72. package/src/adapters/{langchain → thread/langchain}/index.ts +1 -1
  73. package/src/adapters/{langchain → thread/langchain}/model-invoker.ts +15 -18
  74. package/src/adapters/{langchain → thread/langchain}/thread-manager.ts +1 -1
  75. package/src/index.ts +32 -24
  76. package/src/lib/activity.ts +87 -0
  77. package/src/lib/hooks/index.ts +11 -0
  78. package/src/lib/hooks/types.ts +98 -0
  79. package/src/lib/model/helpers.ts +6 -0
  80. package/src/lib/model/index.ts +13 -0
  81. package/src/lib/{model-invoker.ts → model/types.ts} +18 -1
  82. package/src/lib/sandbox/index.ts +19 -0
  83. package/src/lib/sandbox/manager.ts +76 -0
  84. package/src/lib/sandbox/sandbox.test.ts +158 -0
  85. package/src/lib/{fs.ts → sandbox/tree.ts} +6 -6
  86. package/src/lib/sandbox/types.ts +164 -0
  87. package/src/lib/session/index.ts +11 -0
  88. package/src/lib/{session.ts → session/session.ts} +76 -48
  89. package/src/lib/session/types.ts +93 -0
  90. package/src/lib/skills/fs-provider.ts +16 -15
  91. package/src/lib/skills/handler.ts +31 -0
  92. package/src/lib/skills/index.ts +5 -1
  93. package/src/lib/skills/register.ts +20 -0
  94. package/src/lib/skills/tool.ts +47 -0
  95. package/src/lib/state/index.ts +9 -0
  96. package/src/lib/{state-manager.ts → state/manager.ts} +10 -147
  97. package/src/lib/state/types.ts +134 -0
  98. package/src/lib/subagent/define.ts +71 -0
  99. package/src/lib/subagent/handler.ts +99 -0
  100. package/src/lib/subagent/index.ts +13 -0
  101. package/src/lib/subagent/register.ts +53 -0
  102. package/src/lib/subagent/tool.ts +80 -0
  103. package/src/lib/subagent/types.ts +92 -0
  104. package/src/lib/thread/index.ts +7 -0
  105. package/src/lib/{thread-manager.ts → thread/manager.ts} +1 -33
  106. package/src/lib/thread/types.ts +33 -0
  107. package/src/lib/tool-router/auto-append.ts +55 -0
  108. package/src/lib/tool-router/index.ts +41 -0
  109. package/src/lib/tool-router/router.ts +462 -0
  110. package/src/lib/tool-router/types.ts +478 -0
  111. package/src/lib/tool-router/with-sandbox.ts +70 -0
  112. package/src/lib/types.ts +5 -382
  113. package/src/tools/bash/bash.test.ts +53 -55
  114. package/src/tools/bash/handler.ts +23 -51
  115. package/src/tools/edit/handler.ts +67 -81
  116. package/src/tools/glob/handler.ts +60 -17
  117. package/src/tools/read-file/handler.ts +67 -0
  118. package/src/tools/read-skill/handler.ts +1 -31
  119. package/src/tools/read-skill/tool.ts +5 -47
  120. package/src/tools/subagent/handler.ts +1 -100
  121. package/src/tools/subagent/tool.ts +5 -93
  122. package/src/tools/task-create/handler.ts +1 -1
  123. package/src/tools/task-get/handler.ts +1 -1
  124. package/src/tools/task-list/handler.ts +1 -1
  125. package/src/tools/task-update/handler.ts +1 -1
  126. package/src/tools/write-file/handler.ts +47 -0
  127. package/src/workflow.ts +88 -47
  128. package/tsup.config.ts +8 -1
  129. package/dist/adapters/langchain/index.cjs.map +0 -1
  130. package/dist/adapters/langchain/index.js.map +0 -1
  131. package/dist/model-invoker-y_zlyMqu.d.cts +0 -892
  132. package/dist/model-invoker-y_zlyMqu.d.ts +0 -892
  133. package/src/lib/tool-router.ts +0 -977
  134. package/src/lib/workflow-helpers.ts +0 -50
  135. /package/src/lib/{thread-id.ts → thread/id.ts} +0 -0
package/dist/index.cjs CHANGED
@@ -2,157 +2,15 @@
2
2
 
3
3
  var workflow = require('@temporalio/workflow');
4
4
  var z14 = require('zod');
5
- var activity = require('@temporalio/activity');
6
- var justBash = require('just-bash');
7
- var promises = require('fs/promises');
5
+ var common = require('@temporalio/common');
8
6
  var path = require('path');
7
+ var activity = require('@temporalio/activity');
9
8
 
10
9
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
11
10
 
12
11
  var z14__default = /*#__PURE__*/_interopDefault(z14);
13
12
 
14
- // src/lib/session.ts
15
- var SUBAGENT_TOOL_NAME = "Subagent";
16
- function buildSubagentDescription(subagents) {
17
- const subagentList = subagents.map((s) => {
18
- const continuation = s.allowThreadContinuation ? "\n*(Supports thread continuation \u2014 pass a threadId to resume a previous conversation)*" : "";
19
- return `## ${s.agentName}
20
- ${s.description}${continuation}`;
21
- }).join("\n\n");
22
- 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.
23
-
24
- # Available subagents:
25
- ${subagentList}
26
- `;
27
- }
28
- function createSubagentTool(subagents) {
29
- if (subagents.length === 0) {
30
- throw new Error("createTaskTool requires at least one subagent");
31
- }
32
- const names = subagents.map((s) => s.agentName);
33
- const hasThreadContinuation = subagents.some(
34
- (s) => s.allowThreadContinuation
35
- );
36
- const baseFields = {
37
- subagent: z14__default.default.enum(names).describe("The type of subagent to launch"),
38
- description: z14__default.default.string().describe("A short (3-5 word) description of the task"),
39
- prompt: z14__default.default.string().describe("The task for the agent to perform")
40
- };
41
- const schema = hasThreadContinuation ? z14__default.default.object({
42
- ...baseFields,
43
- threadId: z14__default.default.string().nullable().describe(
44
- "Thread ID to continue an existing conversation, or null to start a new one"
45
- )
46
- }) : z14__default.default.object(baseFields);
47
- return {
48
- name: SUBAGENT_TOOL_NAME,
49
- description: buildSubagentDescription(subagents),
50
- schema
51
- };
52
- }
53
- var BASE62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
54
- function getShortId(length = 12) {
55
- const hex = workflow.uuid4().replace(/-/g, "");
56
- let result = "";
57
- for (let i = 0; i < length; i++) {
58
- const byte = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
59
- result += BASE62[byte % BASE62.length];
60
- }
61
- return result;
62
- }
63
-
64
- // src/tools/subagent/handler.ts
65
- function createSubagentHandler(subagents) {
66
- const { taskQueue: parentTaskQueue } = workflow.workflowInfo();
67
- return async (args) => {
68
- const config = subagents.find((s) => s.agentName === args.subagent);
69
- if (!config) {
70
- throw new Error(
71
- `Unknown subagent: ${args.subagent}. Available: ${subagents.map((s) => s.agentName).join(", ")}`
72
- );
73
- }
74
- const childWorkflowId = `${args.subagent}-${getShortId()}`;
75
- const input = {
76
- prompt: args.prompt,
77
- ...config.context && { context: config.context },
78
- ...args.threadId && config.allowThreadContinuation && { threadId: args.threadId }
79
- };
80
- const childOpts = {
81
- workflowId: childWorkflowId,
82
- args: [input],
83
- taskQueue: config.taskQueue ?? parentTaskQueue
84
- };
85
- const { toolResponse, data, usage, threadId: childThreadId } = typeof config.workflow === "string" ? await workflow.executeChild(config.workflow, childOpts) : await workflow.executeChild(config.workflow, childOpts);
86
- if (!toolResponse) {
87
- return {
88
- toolResponse: "Subagent workflow returned no response",
89
- data: null,
90
- ...usage && { usage }
91
- };
92
- }
93
- const validated = config.resultSchema ? config.resultSchema.safeParse(data) : null;
94
- if (validated && !validated.success) {
95
- return {
96
- toolResponse: `Subagent workflow returned invalid data: ${validated.error.message}`,
97
- data: null,
98
- ...usage && { usage }
99
- };
100
- }
101
- let finalToolResponse = toolResponse;
102
- if (config.allowThreadContinuation && childThreadId) {
103
- finalToolResponse = typeof toolResponse === "string" ? `${toolResponse}
104
-
105
- [Thread ID: ${childThreadId}]` : toolResponse;
106
- }
107
- return {
108
- toolResponse: finalToolResponse,
109
- data: validated ? validated.data : data,
110
- ...usage && { usage }
111
- };
112
- };
113
- }
114
- var READ_SKILL_TOOL_NAME = "ReadSkill";
115
- function buildReadSkillDescription(skills) {
116
- const skillList = skills.map((s) => `- **${s.name}**: ${s.description}`).join("\n");
117
- return `Load the full instructions for a skill. Read the skill before following its instructions.
118
-
119
- # Available skills:
120
- ${skillList}
121
- `;
122
- }
123
- function createReadSkillTool(skills) {
124
- if (skills.length === 0) {
125
- throw new Error("createReadSkillTool requires at least one skill");
126
- }
127
- const names = skills.map((s) => s.name);
128
- return {
129
- name: READ_SKILL_TOOL_NAME,
130
- description: buildReadSkillDescription(skills),
131
- schema: z14__default.default.object({
132
- skill_name: z14__default.default.enum(names).describe("The name of the skill to load")
133
- })
134
- };
135
- }
136
-
137
- // src/tools/read-skill/handler.ts
138
- function createReadSkillHandler(skills) {
139
- const skillMap = new Map(skills.map((s) => [s.name, s]));
140
- return (args) => {
141
- const skill = skillMap.get(args.skill_name);
142
- if (!skill) {
143
- return {
144
- toolResponse: JSON.stringify({
145
- error: `Skill "${args.skill_name}" not found`
146
- }),
147
- data: null
148
- };
149
- }
150
- return {
151
- toolResponse: skill.instructions,
152
- data: null
153
- };
154
- };
155
- }
13
+ // src/lib/session/session.ts
156
14
  function createToolRouter(options) {
157
15
  const { appendToolResult } = options;
158
16
  const toolMap = /* @__PURE__ */ new Map();
@@ -160,45 +18,12 @@ function createToolRouter(options) {
160
18
  toolMap.set(tool.name, tool);
161
19
  }
162
20
  const isEnabled = (tool) => tool.enabled ?? true;
163
- if (options.subagents) {
164
- if (options.subagents.length > 0) {
165
- const subagentHooksMap = /* @__PURE__ */ new Map();
166
- for (const s of options.subagents) {
167
- if (s.hooks) subagentHooksMap.set(s.agentName, s.hooks);
168
- }
169
- const resolveSubagentName = (args) => args.subagent;
170
- toolMap.set(SUBAGENT_TOOL_NAME, {
171
- ...createSubagentTool(options.subagents),
172
- handler: createSubagentHandler(options.subagents),
173
- ...subagentHooksMap.size > 0 && {
174
- hooks: {
175
- onPreToolUse: async (ctx) => {
176
- const hooks = subagentHooksMap.get(resolveSubagentName(ctx.args));
177
- return hooks?.onPreExecution?.(ctx) ?? {};
178
- },
179
- onPostToolUse: async (ctx) => {
180
- const hooks = subagentHooksMap.get(resolveSubagentName(ctx.args));
181
- await hooks?.onPostExecution?.(ctx);
182
- },
183
- onPostToolUseFailure: async (ctx) => {
184
- const hooks = subagentHooksMap.get(resolveSubagentName(ctx.args));
185
- return hooks?.onExecutionFailure?.(ctx) ?? {};
186
- }
187
- }
188
- }
189
- });
21
+ if (options.plugins) {
22
+ for (const plugin of options.plugins) {
23
+ toolMap.set(plugin.name, plugin);
190
24
  }
191
25
  }
192
- if (options.skills && options.skills.length > 0) {
193
- toolMap.set(READ_SKILL_TOOL_NAME, {
194
- ...createReadSkillTool(options.skills),
195
- handler: createReadSkillHandler(options.skills)
196
- });
197
- }
198
- async function processToolCall(toolCall, turn, handlerContext) {
199
- const startTime = Date.now();
200
- const tool = toolMap.get(toolCall.name);
201
- const toolHooks = tool?.hooks;
26
+ async function runPreHooks(toolCall, tool, turn) {
202
27
  let effectiveArgs = toolCall.args;
203
28
  if (options.hooks?.onPreToolUse) {
204
29
  const preResult = await options.hooks.onPreToolUse({
@@ -206,58 +31,105 @@ function createToolRouter(options) {
206
31
  threadId: options.threadId,
207
32
  turn
208
33
  });
209
- if (preResult?.skip) {
210
- await appendToolResult({
211
- threadId: options.threadId,
212
- toolCallId: toolCall.id,
213
- toolName: toolCall.name,
214
- content: JSON.stringify({
215
- skipped: true,
216
- reason: "Skipped by PreToolUse hook"
217
- })
218
- });
219
- return null;
220
- }
221
- if (preResult?.modifiedArgs !== void 0) {
34
+ if (preResult?.skip) return { skip: true };
35
+ if (preResult?.modifiedArgs !== void 0)
222
36
  effectiveArgs = preResult.modifiedArgs;
223
- }
224
37
  }
225
- if (toolHooks?.onPreToolUse) {
226
- const preResult = await toolHooks.onPreToolUse({
38
+ if (tool?.hooks?.onPreToolUse) {
39
+ const preResult = await tool.hooks.onPreToolUse({
227
40
  args: effectiveArgs,
228
41
  threadId: options.threadId,
229
42
  turn
230
43
  });
231
- if (preResult?.skip) {
232
- await appendToolResult({
233
- threadId: options.threadId,
234
- toolCallId: toolCall.id,
235
- toolName: toolCall.name,
236
- content: JSON.stringify({
237
- skipped: true,
238
- reason: "Skipped by tool PreToolUse hook"
239
- })
240
- });
241
- return null;
242
- }
243
- if (preResult?.modifiedArgs !== void 0) {
44
+ if (preResult?.skip) return { skip: true };
45
+ if (preResult?.modifiedArgs !== void 0)
244
46
  effectiveArgs = preResult.modifiedArgs;
245
- }
246
47
  }
48
+ return { skip: false, args: effectiveArgs };
49
+ }
50
+ async function runFailureHooks(toolCall, tool, error, effectiveArgs, turn) {
51
+ const err = error instanceof Error ? error : new Error(String(error));
52
+ const errorStr = String(error);
53
+ if (tool?.hooks?.onPostToolUseFailure) {
54
+ const r = await tool.hooks.onPostToolUseFailure({
55
+ args: effectiveArgs,
56
+ error: err,
57
+ threadId: options.threadId,
58
+ turn
59
+ });
60
+ if (r?.fallbackContent !== void 0)
61
+ return { content: r.fallbackContent, result: { error: errorStr, recovered: true } };
62
+ if (r?.suppress)
63
+ return {
64
+ content: JSON.stringify({ error: errorStr, suppressed: true }),
65
+ result: { error: errorStr, suppressed: true }
66
+ };
67
+ }
68
+ if (options.hooks?.onPostToolUseFailure) {
69
+ const r = await options.hooks.onPostToolUseFailure({
70
+ toolCall,
71
+ error: err,
72
+ threadId: options.threadId,
73
+ turn
74
+ });
75
+ if (r?.fallbackContent !== void 0)
76
+ return { content: r.fallbackContent, result: { error: errorStr, recovered: true } };
77
+ if (r?.suppress)
78
+ return {
79
+ content: JSON.stringify({ error: errorStr, suppressed: true }),
80
+ result: { error: errorStr, suppressed: true }
81
+ };
82
+ }
83
+ throw workflow.ApplicationFailure.fromError(error, { nonRetryable: true });
84
+ }
85
+ async function runPostHooks(toolCall, tool, toolResult, effectiveArgs, turn, durationMs) {
86
+ if (tool?.hooks?.onPostToolUse) {
87
+ await tool.hooks.onPostToolUse({
88
+ args: effectiveArgs,
89
+ result: toolResult.data,
90
+ threadId: options.threadId,
91
+ turn,
92
+ durationMs
93
+ });
94
+ }
95
+ if (options.hooks?.onPostToolUse) {
96
+ await options.hooks.onPostToolUse({
97
+ toolCall,
98
+ result: toolResult,
99
+ threadId: options.threadId,
100
+ turn,
101
+ durationMs
102
+ });
103
+ }
104
+ }
105
+ async function processToolCall(toolCall, turn, sandboxId) {
106
+ const startTime = Date.now();
107
+ const tool = toolMap.get(toolCall.name);
108
+ const preResult = await runPreHooks(toolCall, tool, turn);
109
+ if (preResult.skip) {
110
+ await appendToolResult({
111
+ threadId: options.threadId,
112
+ toolCallId: toolCall.id,
113
+ toolName: toolCall.name,
114
+ content: JSON.stringify({ skipped: true, reason: "Skipped by PreToolUse hook" })
115
+ });
116
+ return null;
117
+ }
118
+ const effectiveArgs = preResult.args;
247
119
  let result;
248
120
  let content;
249
121
  let resultAppended = false;
250
122
  try {
251
123
  if (tool) {
252
- const enrichedContext = {
253
- ...handlerContext ?? {},
124
+ const routerContext = {
254
125
  threadId: options.threadId,
255
126
  toolCallId: toolCall.id,
256
- toolName: toolCall.name
127
+ toolName: toolCall.name,
128
+ ...sandboxId !== void 0 && { sandboxId }
257
129
  };
258
130
  const response = await tool.handler(
259
131
  effectiveArgs,
260
- enrichedContext
132
+ routerContext
261
133
  );
262
134
  result = response.data;
263
135
  content = response.toolResponse;
@@ -267,47 +139,9 @@ function createToolRouter(options) {
267
139
  content = JSON.stringify(result, null, 2);
268
140
  }
269
141
  } catch (error) {
270
- const err = error instanceof Error ? error : new Error(String(error));
271
- let recovered = false;
272
- if (toolHooks?.onPostToolUseFailure) {
273
- const failureResult = await toolHooks.onPostToolUseFailure({
274
- args: effectiveArgs,
275
- error: err,
276
- threadId: options.threadId,
277
- turn
278
- });
279
- if (failureResult?.fallbackContent !== void 0) {
280
- content = failureResult.fallbackContent;
281
- result = { error: String(error), recovered: true };
282
- recovered = true;
283
- } else if (failureResult?.suppress) {
284
- content = JSON.stringify({ error: String(error), suppressed: true });
285
- result = { error: String(error), suppressed: true };
286
- recovered = true;
287
- }
288
- }
289
- if (!recovered && options.hooks?.onPostToolUseFailure) {
290
- const failureResult = await options.hooks.onPostToolUseFailure({
291
- toolCall,
292
- error: err,
293
- threadId: options.threadId,
294
- turn
295
- });
296
- if (failureResult?.fallbackContent !== void 0) {
297
- content = failureResult.fallbackContent;
298
- result = { error: String(error), recovered: true };
299
- recovered = true;
300
- } else if (failureResult?.suppress) {
301
- content = JSON.stringify({ error: String(error), suppressed: true });
302
- result = { error: String(error), suppressed: true };
303
- recovered = true;
304
- }
305
- }
306
- if (!recovered) {
307
- throw workflow.ApplicationFailure.fromError(error, {
308
- nonRetryable: true
309
- });
310
- }
142
+ const recovery = await runFailureHooks(toolCall, tool, error, effectiveArgs, turn);
143
+ result = recovery.result;
144
+ content = recovery.content;
311
145
  }
312
146
  if (!resultAppended) {
313
147
  await appendToolResult({
@@ -322,29 +156,10 @@ function createToolRouter(options) {
322
156
  name: toolCall.name,
323
157
  data: result
324
158
  };
325
- const durationMs = Date.now() - startTime;
326
- if (toolHooks?.onPostToolUse) {
327
- await toolHooks.onPostToolUse({
328
- args: effectiveArgs,
329
- result,
330
- threadId: options.threadId,
331
- turn,
332
- durationMs
333
- });
334
- }
335
- if (options.hooks?.onPostToolUse) {
336
- await options.hooks.onPostToolUse({
337
- toolCall,
338
- result: toolResult,
339
- threadId: options.threadId,
340
- turn,
341
- durationMs
342
- });
343
- }
159
+ await runPostHooks(toolCall, tool, toolResult, effectiveArgs, turn, Date.now() - startTime);
344
160
  return toolResult;
345
161
  }
346
162
  return {
347
- // --- Methods from registry ---
348
163
  hasTools() {
349
164
  return Array.from(toolMap.values()).some(isEnabled);
350
165
  },
@@ -368,32 +183,25 @@ function createToolRouter(options) {
368
183
  return Array.from(toolMap.entries()).filter(([, tool]) => isEnabled(tool)).map(([name]) => name);
369
184
  },
370
185
  getToolDefinitions() {
371
- const activeSubagents = options.subagents?.filter((subagent) => isEnabled(subagent)) ?? [];
372
- const activeSkills = options.skills ?? [];
373
- return [
374
- ...Array.from(toolMap).filter(
375
- ([, tool]) => isEnabled(tool) && tool.name !== SUBAGENT_TOOL_NAME && tool.name !== READ_SKILL_TOOL_NAME
376
- ).map(([name, tool]) => ({
377
- name,
378
- description: tool.description,
379
- schema: tool.schema,
380
- strict: tool.strict,
381
- max_uses: tool.max_uses
382
- })),
383
- ...activeSubagents.length > 0 ? [createSubagentTool(activeSubagents)] : [],
384
- ...activeSkills.length > 0 ? [createReadSkillTool(activeSkills)] : []
385
- ];
186
+ return Array.from(toolMap).filter(([, tool]) => isEnabled(tool)).map(([name, tool]) => ({
187
+ name,
188
+ description: tool.description,
189
+ schema: tool.schema,
190
+ strict: tool.strict,
191
+ max_uses: tool.max_uses
192
+ }));
386
193
  },
387
- // --- Methods for processing tool calls ---
388
194
  async processToolCalls(toolCalls, context) {
389
195
  if (toolCalls.length === 0) {
390
196
  return [];
391
197
  }
392
198
  const turn = context?.turn ?? 0;
393
- const handlerContext = context?.handlerContext;
199
+ const sandboxId = context?.sandboxId;
394
200
  if (options.parallel) {
395
201
  const results2 = await Promise.all(
396
- toolCalls.map((tc) => processToolCall(tc, turn, handlerContext))
202
+ toolCalls.map(
203
+ (tc) => processToolCall(tc, turn, sandboxId)
204
+ )
397
205
  );
398
206
  return results2.filter(
399
207
  (r) => r !== null
@@ -401,7 +209,11 @@ function createToolRouter(options) {
401
209
  }
402
210
  const results = [];
403
211
  for (const toolCall of toolCalls) {
404
- const result = await processToolCall(toolCall, turn, handlerContext);
212
+ const result = await processToolCall(
213
+ toolCall,
214
+ turn,
215
+ sandboxId
216
+ );
405
217
  if (result !== null) {
406
218
  results.push(result);
407
219
  }
@@ -413,17 +225,16 @@ function createToolRouter(options) {
413
225
  if (matchingCalls.length === 0) {
414
226
  return [];
415
227
  }
416
- const handlerContext = context?.handlerContext ?? {};
417
228
  const processOne = async (toolCall) => {
418
- const enrichedContext = {
419
- ...handlerContext ?? {},
229
+ const routerContext = {
420
230
  threadId: options.threadId,
421
231
  toolCallId: toolCall.id,
422
- toolName: toolCall.name
232
+ toolName: toolCall.name,
233
+ ...context?.sandboxId !== void 0 && { sandboxId: context.sandboxId }
423
234
  };
424
235
  const response = await handler(
425
236
  toolCall.args,
426
- enrichedContext
237
+ routerContext
427
238
  );
428
239
  if (!response.resultAppended) {
429
240
  await appendToolResult({
@@ -448,7 +259,6 @@ function createToolRouter(options) {
448
259
  }
449
260
  return results;
450
261
  },
451
- // --- Utility methods ---
452
262
  filterByName(toolCalls, name) {
453
263
  return toolCalls.filter(
454
264
  (tc) => tc.name === name
@@ -462,36 +272,201 @@ function createToolRouter(options) {
462
272
  }
463
273
  };
464
274
  }
465
- function withAutoAppend(threadHandler, handler) {
275
+ function defineTool(tool) {
276
+ return tool;
277
+ }
278
+ function hasNoOtherToolCalls(toolCalls, excludeName) {
279
+ return toolCalls.filter((tc) => tc.name !== excludeName).length === 0;
280
+ }
281
+ var BASE62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
282
+ function getShortId(length = 12) {
283
+ const hex = workflow.uuid4().replace(/-/g, "");
284
+ let result = "";
285
+ for (let i = 0; i < length; i++) {
286
+ const byte = parseInt(hex.slice(i * 2, i * 2 + 2), 16);
287
+ result += BASE62[byte % BASE62.length];
288
+ }
289
+ return result;
290
+ }
291
+ var SUBAGENT_TOOL_NAME = "Subagent";
292
+ function buildSubagentDescription(subagents) {
293
+ const subagentList = subagents.map((s) => {
294
+ const continuation = s.allowThreadContinuation ? "\n*(Supports thread continuation \u2014 pass a threadId to resume a previous conversation)*" : "";
295
+ return `## ${s.agentName}
296
+ ${s.description}${continuation}`;
297
+ }).join("\n\n");
298
+ 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.
299
+
300
+ # Available subagents:
301
+ ${subagentList}
302
+ `;
303
+ }
304
+ function createSubagentTool(subagents) {
305
+ if (subagents.length === 0) {
306
+ throw new Error("createSubagentTool requires at least one subagent");
307
+ }
308
+ const names = subagents.map((s) => s.agentName);
309
+ const hasThreadContinuation = subagents.some(
310
+ (s) => s.allowThreadContinuation
311
+ );
312
+ const baseFields = {
313
+ subagent: z14__default.default.enum(names).describe("The type of subagent to launch"),
314
+ description: z14__default.default.string().describe("A short (3-5 word) description of the task"),
315
+ prompt: z14__default.default.string().describe("The task for the agent to perform")
316
+ };
317
+ const schema = hasThreadContinuation ? z14__default.default.object({
318
+ ...baseFields,
319
+ threadId: z14__default.default.string().nullable().describe(
320
+ "Thread ID to continue an existing conversation, or null to start a new one"
321
+ )
322
+ }) : z14__default.default.object(baseFields);
323
+ return {
324
+ name: SUBAGENT_TOOL_NAME,
325
+ description: buildSubagentDescription(subagents),
326
+ schema
327
+ };
328
+ }
329
+ function createSubagentHandler(subagents) {
330
+ const { taskQueue: parentTaskQueue } = workflow.workflowInfo();
466
331
  return async (args, context) => {
467
- const response = await handler(args, context);
468
- const threadId = context.threadId;
469
- const toolCallId = context.toolCallId;
470
- const toolName = context.toolName;
471
- await threadHandler({
472
- threadId,
473
- toolCallId,
474
- toolName,
475
- content: response.toolResponse
476
- });
332
+ const config = subagents.find((s) => s.agentName === args.subagent);
333
+ if (!config) {
334
+ throw new Error(
335
+ `Unknown subagent: ${args.subagent}. Available: ${subagents.map((s) => s.agentName).join(", ")}`
336
+ );
337
+ }
338
+ const childWorkflowId = `${args.subagent}-${getShortId()}`;
339
+ const { sandboxId: parentSandboxId } = context;
340
+ const inheritSandbox = config.sandbox !== "own" && !!parentSandboxId;
341
+ const input = {
342
+ prompt: args.prompt,
343
+ ...config.context && { context: config.context },
344
+ ...args.threadId && args.threadId !== null && config.allowThreadContinuation && { previousThreadId: args.threadId },
345
+ ...inheritSandbox && { sandboxId: parentSandboxId }
346
+ };
347
+ const childOpts = {
348
+ workflowId: childWorkflowId,
349
+ args: [input],
350
+ taskQueue: config.taskQueue ?? parentTaskQueue
351
+ };
352
+ const {
353
+ toolResponse,
354
+ data,
355
+ usage,
356
+ threadId: childThreadId
357
+ } = typeof config.workflow === "string" ? await workflow.executeChild(config.workflow, childOpts) : await workflow.executeChild(config.workflow, childOpts);
358
+ if (!toolResponse) {
359
+ return {
360
+ toolResponse: "Subagent workflow returned no response",
361
+ data: null,
362
+ ...usage && { usage }
363
+ };
364
+ }
365
+ const validated = config.resultSchema ? config.resultSchema.safeParse(data) : null;
366
+ if (validated && !validated.success) {
367
+ return {
368
+ toolResponse: `Subagent workflow returned invalid data: ${validated.error.message}`,
369
+ data: null,
370
+ ...usage && { usage }
371
+ };
372
+ }
373
+ let finalToolResponse = toolResponse;
374
+ if (config.allowThreadContinuation && childThreadId) {
375
+ finalToolResponse = typeof toolResponse === "string" ? `${toolResponse}
376
+
377
+ [Thread ID: ${childThreadId}]` : toolResponse;
378
+ }
477
379
  return {
478
- toolResponse: "Response appended via withAutoAppend",
479
- data: response.data,
480
- resultAppended: true
380
+ toolResponse: finalToolResponse,
381
+ data: validated ? validated.data : data,
382
+ ...usage && { usage }
481
383
  };
482
384
  };
483
385
  }
484
- function defineTool(tool) {
485
- return tool;
386
+
387
+ // src/lib/subagent/register.ts
388
+ function buildSubagentRegistration(subagents) {
389
+ const enabled = subagents.filter((s) => s.enabled ?? true);
390
+ if (enabled.length === 0) return null;
391
+ const subagentHooksMap = /* @__PURE__ */ new Map();
392
+ for (const s of enabled) {
393
+ if (s.hooks) subagentHooksMap.set(s.agentName, s.hooks);
394
+ }
395
+ const resolveSubagentName = (args) => args.subagent;
396
+ return {
397
+ ...createSubagentTool(enabled),
398
+ handler: createSubagentHandler(enabled),
399
+ ...subagentHooksMap.size > 0 && {
400
+ hooks: {
401
+ onPreToolUse: async (ctx) => {
402
+ const hooks = subagentHooksMap.get(resolveSubagentName(ctx.args));
403
+ return hooks?.onPreExecution?.(ctx) ?? {};
404
+ },
405
+ onPostToolUse: async (ctx) => {
406
+ const hooks = subagentHooksMap.get(resolveSubagentName(ctx.args));
407
+ await hooks?.onPostExecution?.(ctx);
408
+ },
409
+ onPostToolUseFailure: async (ctx) => {
410
+ const hooks = subagentHooksMap.get(resolveSubagentName(ctx.args));
411
+ return hooks?.onExecutionFailure?.(ctx) ?? {};
412
+ }
413
+ }
414
+ }
415
+ };
486
416
  }
487
- function defineSubagent(config) {
488
- return config;
417
+ var READ_SKILL_TOOL_NAME = "ReadSkill";
418
+ function buildReadSkillDescription(skills) {
419
+ const skillList = skills.map((s) => `- **${s.name}**: ${s.description}`).join("\n");
420
+ return `Load the full instructions for a skill. Read the skill before following its instructions.
421
+
422
+ # Available skills:
423
+ ${skillList}
424
+ `;
489
425
  }
490
- function hasNoOtherToolCalls(toolCalls, excludeName) {
491
- return toolCalls.filter((tc) => tc.name !== excludeName).length === 0;
426
+ function createReadSkillTool(skills) {
427
+ if (skills.length === 0) {
428
+ throw new Error("createReadSkillTool requires at least one skill");
429
+ }
430
+ const names = skills.map((s) => s.name);
431
+ return {
432
+ name: READ_SKILL_TOOL_NAME,
433
+ description: buildReadSkillDescription(skills),
434
+ schema: z14__default.default.object({
435
+ skill_name: z14__default.default.enum(names).describe("The name of the skill to load")
436
+ })
437
+ };
438
+ }
439
+
440
+ // src/lib/skills/handler.ts
441
+ function createReadSkillHandler(skills) {
442
+ const skillMap = new Map(skills.map((s) => [s.name, s]));
443
+ return (args) => {
444
+ const skill = skillMap.get(args.skill_name);
445
+ if (!skill) {
446
+ return {
447
+ toolResponse: JSON.stringify({
448
+ error: `Skill "${args.skill_name}" not found`
449
+ }),
450
+ data: null
451
+ };
452
+ }
453
+ return {
454
+ toolResponse: skill.instructions,
455
+ data: null
456
+ };
457
+ };
458
+ }
459
+
460
+ // src/lib/skills/register.ts
461
+ function buildSkillRegistration(skills) {
462
+ if (skills.length === 0) return null;
463
+ return {
464
+ ...createReadSkillTool(skills),
465
+ handler: createReadSkillHandler(skills)
466
+ };
492
467
  }
493
468
 
494
- // src/lib/session.ts
469
+ // src/lib/session/session.ts
495
470
  var createSession = async ({
496
471
  threadId: providedThreadId,
497
472
  agentName,
@@ -507,7 +482,9 @@ var createSession = async ({
507
482
  hooks = {},
508
483
  appendSystemPrompt = true,
509
484
  continueThread = false,
510
- waitForInputTimeout = "48h"
485
+ waitForInputTimeout = "48h",
486
+ sandbox: sandboxOps,
487
+ sandboxId: inheritedSandboxId
511
488
  }) => {
512
489
  const threadId = providedThreadId ?? getShortId();
513
490
  const {
@@ -516,13 +493,21 @@ var createSession = async ({
516
493
  initializeThread,
517
494
  appendSystemMessage
518
495
  } = threadOps ?? proxyDefaultThreadOps();
496
+ const plugins = [];
497
+ if (subagents) {
498
+ const reg = buildSubagentRegistration(subagents);
499
+ if (reg) plugins.push(reg);
500
+ }
501
+ if (skills) {
502
+ const reg = buildSkillRegistration(skills);
503
+ if (reg) plugins.push(reg);
504
+ }
519
505
  const toolRouter = createToolRouter({
520
506
  tools,
521
507
  appendToolResult,
522
508
  threadId,
523
509
  hooks,
524
- subagents,
525
- skills,
510
+ plugins,
526
511
  parallel: processToolsInParallel
527
512
  });
528
513
  const callSessionEnd = async (exitReason, turns) => {
@@ -559,6 +544,17 @@ var createSession = async ({
559
544
  stateManager.run();
560
545
  }
561
546
  );
547
+ let sandboxId = inheritedSandboxId;
548
+ const ownsSandbox = !sandboxId && !!sandboxOps;
549
+ if (ownsSandbox) {
550
+ const result = await sandboxOps.createSandbox({ id: threadId });
551
+ sandboxId = result.sandboxId;
552
+ if (result.stateUpdate) {
553
+ stateManager.mergeUpdate(
554
+ result.stateUpdate
555
+ );
556
+ }
557
+ }
562
558
  if (hooks.onSessionStart) {
563
559
  await hooks.onSessionStart({
564
560
  threadId,
@@ -599,6 +595,7 @@ var createSession = async ({
599
595
  stateManager.complete();
600
596
  exitReason = "completed";
601
597
  return {
598
+ threadId,
602
599
  finalMessage: message,
603
600
  exitReason,
604
601
  usage: stateManager.getTotalUsage()
@@ -622,7 +619,8 @@ var createSession = async ({
622
619
  const toolCallResults = await toolRouter.processToolCalls(
623
620
  parsedToolCalls,
624
621
  {
625
- turn: currentTurn
622
+ turn: currentTurn,
623
+ ...sandboxId !== void 0 && { sandboxId }
626
624
  }
627
625
  );
628
626
  for (const result of toolCallResults) {
@@ -650,8 +648,12 @@ var createSession = async ({
650
648
  throw workflow.ApplicationFailure.fromError(error);
651
649
  } finally {
652
650
  await callSessionEnd(exitReason, stateManager.getTurns());
651
+ if (ownsSandbox && sandboxId && sandboxOps) {
652
+ await sandboxOps.destroySandbox(sandboxId);
653
+ }
653
654
  }
654
655
  return {
656
+ threadId,
655
657
  finalMessage: null,
656
658
  exitReason,
657
659
  usage: stateManager.getTotalUsage()
@@ -672,16 +674,94 @@ function proxyDefaultThreadOps(options) {
672
674
  }
673
675
  );
674
676
  }
677
+ function proxySandboxOps(options) {
678
+ return workflow.proxyActivities(
679
+ options ?? {
680
+ startToCloseTimeout: "30s",
681
+ retry: {
682
+ maximumAttempts: 3,
683
+ initialInterval: "2s",
684
+ maximumInterval: "30s",
685
+ backoffCoefficient: 2
686
+ }
687
+ }
688
+ );
689
+ }
690
+
691
+ // src/lib/thread/manager.ts
692
+ var THREAD_TTL_SECONDS = 60 * 60 * 24 * 90;
693
+ var APPEND_IDEMPOTENT_SCRIPT = `
694
+ if redis.call('EXISTS', KEYS[1]) == 1 then
695
+ return 0
696
+ end
697
+ for i = 2, #ARGV do
698
+ redis.call('RPUSH', KEYS[2], ARGV[i])
699
+ end
700
+ redis.call('EXPIRE', KEYS[2], tonumber(ARGV[1]))
701
+ redis.call('SET', KEYS[1], '1', 'EX', tonumber(ARGV[1]))
702
+ return 1
703
+ `;
704
+ function getThreadKey(threadId, key) {
705
+ return `thread:${threadId}:${key}`;
706
+ }
707
+ function createThreadManager(config) {
708
+ const {
709
+ redis,
710
+ threadId,
711
+ key = "messages",
712
+ serialize = (m) => JSON.stringify(m),
713
+ deserialize = (raw) => JSON.parse(raw),
714
+ idOf
715
+ } = config;
716
+ const redisKey = getThreadKey(threadId, key);
717
+ const metaKey = getThreadKey(threadId, `${key}:meta`);
718
+ async function assertThreadExists() {
719
+ const exists = await redis.exists(metaKey);
720
+ if (!exists) {
721
+ throw new Error(`Thread "${threadId}" (key: ${key}) does not exist`);
722
+ }
723
+ }
724
+ return {
725
+ async initialize() {
726
+ await redis.del(redisKey);
727
+ await redis.set(metaKey, "1", "EX", THREAD_TTL_SECONDS);
728
+ },
729
+ async load() {
730
+ await assertThreadExists();
731
+ const data = await redis.lrange(redisKey, 0, -1);
732
+ return data.map(deserialize);
733
+ },
734
+ async append(messages) {
735
+ if (messages.length === 0) return;
736
+ await assertThreadExists();
737
+ if (idOf) {
738
+ const dedupId = messages.map(idOf).join(":");
739
+ const dedupKey = getThreadKey(threadId, `dedup:${dedupId}`);
740
+ await redis.eval(
741
+ APPEND_IDEMPOTENT_SCRIPT,
742
+ 2,
743
+ dedupKey,
744
+ redisKey,
745
+ String(THREAD_TTL_SECONDS),
746
+ ...messages.map(serialize)
747
+ );
748
+ } else {
749
+ await redis.rpush(redisKey, ...messages.map(serialize));
750
+ await redis.expire(redisKey, THREAD_TTL_SECONDS);
751
+ }
752
+ },
753
+ async delete() {
754
+ await redis.del(redisKey, metaKey);
755
+ }
756
+ };
757
+ }
675
758
 
676
759
  // src/lib/types.ts
677
- var agentQueryName = (agentName) => `get${agentName}State`;
678
- var agentStateChangeUpdateName = (agentName) => `waitFor${agentName}StateChange`;
679
760
  function isTerminalStatus(status) {
680
761
  return status === "COMPLETED" || status === "FAILED" || status === "CANCELLED";
681
762
  }
682
763
  function createAgentStateManager({
683
- initialState,
684
- agentName
764
+ initialState
685
765
  }) {
686
766
  let status = initialState?.status ?? "RUNNING";
687
767
  let version = initialState?.version ?? 0;
@@ -712,11 +792,9 @@ function createAgentStateManager({
712
792
  ...customState
713
793
  };
714
794
  }
715
- const stateQuery = workflow.defineQuery(
716
- agentQueryName(agentName)
717
- );
795
+ const stateQuery = workflow.defineQuery("getAgentState");
718
796
  const stateChangeUpdate = workflow.defineUpdate(
719
- agentStateChangeUpdateName(agentName)
797
+ "waitForAgentStateChange"
720
798
  );
721
799
  workflow.setHandler(stateQuery, () => buildState());
722
800
  workflow.setHandler(stateChangeUpdate, async (lastKnownVersion) => {
@@ -780,6 +858,10 @@ function createAgentStateManager({
780
858
  customState[key] = value;
781
859
  version++;
782
860
  },
861
+ mergeUpdate(update) {
862
+ Object.assign(customState, update);
863
+ version++;
864
+ },
783
865
  getCurrentState() {
784
866
  return buildState();
785
867
  },
@@ -835,6 +917,127 @@ function createAgentStateManager({
835
917
  };
836
918
  }
837
919
 
920
+ // src/lib/tool-router/auto-append.ts
921
+ function withAutoAppend(threadHandler, handler) {
922
+ return async (args, context) => {
923
+ const response = await handler(args, context);
924
+ await threadHandler({
925
+ threadId: context.threadId,
926
+ toolCallId: context.toolCallId,
927
+ toolName: context.toolName,
928
+ content: response.toolResponse
929
+ });
930
+ return {
931
+ toolResponse: "Response appended via withAutoAppend",
932
+ data: response.data,
933
+ resultAppended: true
934
+ };
935
+ };
936
+ }
937
+
938
+ // src/lib/tool-router/with-sandbox.ts
939
+ function withSandbox(manager, handler) {
940
+ return async (args, context) => {
941
+ if (!context.sandboxId) {
942
+ return {
943
+ toolResponse: `Error: No sandbox configured for this agent. The ${context.toolName} tool requires a sandbox.`,
944
+ data: null
945
+ };
946
+ }
947
+ const sandbox = await manager.getSandbox(context.sandboxId);
948
+ return handler(args, { ...context, sandbox, sandboxId: context.sandboxId });
949
+ };
950
+ }
951
+
952
+ // src/lib/subagent/define.ts
953
+ function defineSubagent(config) {
954
+ return config;
955
+ }
956
+ var SandboxNotSupportedError = class extends common.ApplicationFailure {
957
+ constructor(operation) {
958
+ super(
959
+ `Sandbox does not support: ${operation}`,
960
+ "SandboxNotSupportedError",
961
+ true
962
+ );
963
+ }
964
+ };
965
+ var SandboxNotFoundError = class extends common.ApplicationFailure {
966
+ constructor(sandboxId) {
967
+ super(`Sandbox not found: ${sandboxId}`, "SandboxNotFoundError", true);
968
+ }
969
+ };
970
+
971
+ // src/adapters/sandbox/virtual/mutations.ts
972
+ function applyVirtualTreeMutations(stateManager, mutations) {
973
+ let tree = [...stateManager.get("fileTree")];
974
+ for (const m of mutations) {
975
+ switch (m.type) {
976
+ case "add":
977
+ tree.push(m.entry);
978
+ break;
979
+ case "remove":
980
+ tree = tree.filter((e) => e.path !== m.path);
981
+ break;
982
+ case "update":
983
+ tree = tree.map(
984
+ (e) => e.path === m.path ? { ...e, ...m.entry } : e
985
+ );
986
+ break;
987
+ }
988
+ }
989
+ stateManager.set("fileTree", tree);
990
+ return tree;
991
+ }
992
+
993
+ // src/adapters/sandbox/virtual/tree.ts
994
+ var buildTree = (entries) => {
995
+ const root = { name: "/", children: /* @__PURE__ */ new Map(), isFile: false };
996
+ for (const entry of entries) {
997
+ const parts = entry.path.split("/").filter(Boolean);
998
+ let current = root;
999
+ for (const part of parts) {
1000
+ let child = current.children.get(part);
1001
+ if (!child) {
1002
+ child = { name: part, children: /* @__PURE__ */ new Map(), isFile: false };
1003
+ current.children.set(part, child);
1004
+ }
1005
+ current = child;
1006
+ }
1007
+ current.isFile = current.children.size === 0;
1008
+ }
1009
+ return root;
1010
+ };
1011
+ var printNode = (node, tab, sort) => {
1012
+ const entries = [...node.children.values()];
1013
+ if (sort) {
1014
+ entries.sort((a, b) => {
1015
+ if (!a.isFile && !b.isFile) return a.name.localeCompare(b.name);
1016
+ if (!a.isFile) return -1;
1017
+ if (!b.isFile) return 1;
1018
+ return a.name.localeCompare(b.name);
1019
+ });
1020
+ }
1021
+ let str = "";
1022
+ for (const [i, entry] of entries.entries()) {
1023
+ const isLast = i === entries.length - 1;
1024
+ const branch = isLast ? "\u2514\u2500" : "\u251C\u2500";
1025
+ const childTab = tab + (isLast ? " " : "\u2502 ");
1026
+ if (entry.isFile) {
1027
+ str += "\n" + tab + branch + " " + entry.name;
1028
+ } else {
1029
+ const subtree = printNode(entry, childTab, sort);
1030
+ str += "\n" + tab + branch + " " + entry.name + "/" + subtree;
1031
+ }
1032
+ }
1033
+ return str;
1034
+ };
1035
+ function formatVirtualFileTree(entries, opts = {}) {
1036
+ const sort = opts.sort ?? true;
1037
+ const root = buildTree(entries);
1038
+ return "/" + printNode(root, "", sort);
1039
+ }
1040
+
838
1041
  // src/lib/skills/parse.ts
839
1042
  function parseSkillFile(raw) {
840
1043
  const trimmed = raw.replace(/^\uFEFF/, "");
@@ -1256,197 +1459,313 @@ var createAskUserQuestionHandler = () => async (args) => {
1256
1459
  data: { questions: args.questions }
1257
1460
  };
1258
1461
  };
1259
-
1260
- // src/lib/thread-manager.ts
1261
- var THREAD_TTL_SECONDS = 60 * 60 * 24 * 90;
1262
- var APPEND_IDEMPOTENT_SCRIPT = `
1263
- if redis.call('EXISTS', KEYS[1]) == 1 then
1264
- return 0
1265
- end
1266
- for i = 2, #ARGV do
1267
- redis.call('RPUSH', KEYS[2], ARGV[i])
1268
- end
1269
- redis.call('EXPIRE', KEYS[2], tonumber(ARGV[1]))
1270
- redis.call('SET', KEYS[1], '1', 'EX', tonumber(ARGV[1]))
1271
- return 1
1272
- `;
1273
- function getThreadKey(threadId, key) {
1274
- return `thread:${threadId}:${key}`;
1275
- }
1276
- function createThreadManager(config) {
1277
- const {
1278
- redis,
1279
- threadId,
1280
- key = "messages",
1281
- serialize = (m) => JSON.stringify(m),
1282
- deserialize = (raw) => JSON.parse(raw),
1283
- idOf
1284
- } = config;
1285
- const redisKey = getThreadKey(threadId, key);
1286
- const metaKey = getThreadKey(threadId, `${key}:meta`);
1287
- async function assertThreadExists() {
1288
- const exists = await redis.exists(metaKey);
1289
- if (!exists) {
1290
- throw new Error(`Thread "${threadId}" (key: ${key}) does not exist`);
1462
+ var FileSystemSkillProvider = class {
1463
+ constructor(fs, baseDir) {
1464
+ this.fs = fs;
1465
+ this.baseDir = baseDir;
1466
+ }
1467
+ async listSkills() {
1468
+ const dirs = await this.discoverSkillDirs();
1469
+ const skills = [];
1470
+ for (const dir of dirs) {
1471
+ const raw = await this.fs.readFile(path.join(this.baseDir, dir, "SKILL.md"));
1472
+ const { frontmatter } = parseSkillFile(raw);
1473
+ skills.push(frontmatter);
1291
1474
  }
1475
+ return skills;
1292
1476
  }
1293
- return {
1294
- async initialize() {
1295
- await redis.del(redisKey);
1296
- await redis.set(metaKey, "1", "EX", THREAD_TTL_SECONDS);
1297
- },
1298
- async load() {
1299
- await assertThreadExists();
1300
- const data = await redis.lrange(redisKey, 0, -1);
1301
- return data.map(deserialize);
1302
- },
1303
- async append(messages) {
1304
- if (messages.length === 0) return;
1305
- await assertThreadExists();
1306
- if (idOf) {
1307
- const dedupId = messages.map(idOf).join(":");
1308
- const dedupKey = getThreadKey(threadId, `dedup:${dedupId}`);
1309
- await redis.eval(
1310
- APPEND_IDEMPOTENT_SCRIPT,
1311
- 2,
1312
- dedupKey,
1313
- redisKey,
1314
- String(THREAD_TTL_SECONDS),
1315
- ...messages.map(serialize)
1316
- );
1317
- } else {
1318
- await redis.rpush(redisKey, ...messages.map(serialize));
1319
- await redis.expire(redisKey, THREAD_TTL_SECONDS);
1477
+ async getSkill(name) {
1478
+ const raw = await this.fs.readFile(
1479
+ path.join(this.baseDir, name, "SKILL.md")
1480
+ );
1481
+ const { frontmatter, body } = parseSkillFile(raw);
1482
+ if (frontmatter.name !== name) {
1483
+ throw new Error(
1484
+ `Skill directory "${name}" contains SKILL.md with mismatched name "${frontmatter.name}"`
1485
+ );
1486
+ }
1487
+ return { ...frontmatter, instructions: body };
1488
+ }
1489
+ /**
1490
+ * Convenience method to load all skills with full instructions.
1491
+ * Returns `Skill[]` ready to pass into a workflow.
1492
+ */
1493
+ async loadAll() {
1494
+ const dirs = await this.discoverSkillDirs();
1495
+ const skills = [];
1496
+ for (const dir of dirs) {
1497
+ const raw = await this.fs.readFile(path.join(this.baseDir, dir, "SKILL.md"));
1498
+ const { frontmatter, body } = parseSkillFile(raw);
1499
+ skills.push({ ...frontmatter, instructions: body });
1500
+ }
1501
+ return skills;
1502
+ }
1503
+ async discoverSkillDirs() {
1504
+ const entries = await this.fs.readdirWithFileTypes(this.baseDir);
1505
+ const dirs = [];
1506
+ for (const entry of entries) {
1507
+ if (!entry.isDirectory) continue;
1508
+ const skillPath = path.join(this.baseDir, entry.name, "SKILL.md");
1509
+ if (await this.fs.exists(skillPath)) {
1510
+ dirs.push(entry.name);
1320
1511
  }
1321
- },
1322
- async delete() {
1323
- await redis.del(redisKey, metaKey);
1324
1512
  }
1325
- };
1326
- }
1327
- async function queryParentWorkflowState(client, queryName) {
1513
+ return dirs;
1514
+ }
1515
+ };
1516
+ async function queryParentWorkflowState(client) {
1328
1517
  const { workflowExecution } = activity.Context.current().info;
1329
1518
  const handle = client.getHandle(
1330
1519
  workflowExecution.workflowId,
1331
1520
  workflowExecution.runId
1332
1521
  );
1333
- return handle.query(queryName);
1522
+ return handle.query("getAgentState");
1334
1523
  }
1335
- function createRunAgentActivity(client, invoker) {
1524
+ function createRunAgentActivity(client, handler) {
1336
1525
  return async (config) => {
1337
- const state = await queryParentWorkflowState(
1338
- client,
1339
- agentQueryName(config.agentName)
1340
- );
1341
- return invoker({ ...config, state });
1526
+ const state = await queryParentWorkflowState(client);
1527
+ return handler({ ...config, state });
1342
1528
  };
1343
1529
  }
1344
- function createGlobHandler(fs) {
1345
- return async (_args) => {
1346
- new justBash.Bash({ fs });
1347
- return {
1348
- toolResponse: "Hello, world!",
1349
- data: { files: [] }
1350
- };
1530
+ function withParentWorkflowState(client, handler) {
1531
+ return async (args, context) => {
1532
+ const state = await queryParentWorkflowState(client);
1533
+ return handler(args, { ...context, state });
1351
1534
  };
1352
1535
  }
1353
1536
 
1537
+ // src/lib/sandbox/manager.ts
1538
+ var SandboxManager = class {
1539
+ constructor(provider) {
1540
+ this.provider = provider;
1541
+ }
1542
+ async create(options) {
1543
+ const { sandbox, stateUpdate } = await this.provider.create(options);
1544
+ return { sandboxId: sandbox.id, ...stateUpdate && { stateUpdate } };
1545
+ }
1546
+ async getSandbox(id) {
1547
+ return this.provider.get(id);
1548
+ }
1549
+ async destroy(id) {
1550
+ await this.provider.destroy(id);
1551
+ }
1552
+ async snapshot(id) {
1553
+ return this.provider.snapshot(id);
1554
+ }
1555
+ async restore(snapshot) {
1556
+ const sandbox = await this.provider.restore(snapshot);
1557
+ return sandbox.id;
1558
+ }
1559
+ /**
1560
+ * Returns Temporal activity functions matching {@link SandboxOps}.
1561
+ * Spread these into your worker's activity map.
1562
+ */
1563
+ createActivities() {
1564
+ return {
1565
+ createSandbox: async (options) => {
1566
+ return this.create(options);
1567
+ },
1568
+ destroySandbox: async (sandboxId) => {
1569
+ await this.destroy(sandboxId);
1570
+ },
1571
+ snapshotSandbox: async (sandboxId) => {
1572
+ return this.snapshot(sandboxId);
1573
+ }
1574
+ };
1575
+ }
1576
+ };
1577
+
1578
+ // src/tools/bash/handler.ts
1579
+ var bashHandler = async (args, { sandbox }) => {
1580
+ try {
1581
+ const result = await sandbox.exec(args.command);
1582
+ return {
1583
+ toolResponse: `Exit code: ${result.exitCode}
1584
+
1585
+ stdout:
1586
+ ${result.stdout}
1587
+
1588
+ stderr:
1589
+ ${result.stderr}`,
1590
+ data: result
1591
+ };
1592
+ } catch (error) {
1593
+ const err = error instanceof Error ? error : new Error("Unknown error");
1594
+ return {
1595
+ toolResponse: `Error executing bash command: ${err.message}`,
1596
+ data: null
1597
+ };
1598
+ }
1599
+ };
1600
+
1354
1601
  // src/tools/edit/handler.ts
1355
1602
  function escapeRegExp(str) {
1356
1603
  return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1357
1604
  }
1358
- function createEditHandler(fs) {
1359
- return async (args) => {
1360
- const { file_path, old_string, new_string, replace_all = false } = args;
1361
- if (old_string === new_string) {
1605
+ var editHandler = async (args, { sandbox }) => {
1606
+ const { fs } = sandbox;
1607
+ const { file_path, old_string, new_string, replace_all = false } = args;
1608
+ if (old_string === new_string) {
1609
+ return {
1610
+ toolResponse: `Error: old_string and new_string must be different.`,
1611
+ data: { path: file_path, success: false, replacements: 0 }
1612
+ };
1613
+ }
1614
+ try {
1615
+ const exists = await fs.exists(file_path);
1616
+ if (!exists) {
1362
1617
  return {
1363
- toolResponse: `Error: old_string and new_string must be different.`,
1618
+ toolResponse: `Error: File "${file_path}" does not exist.`,
1364
1619
  data: { path: file_path, success: false, replacements: 0 }
1365
1620
  };
1366
1621
  }
1367
- try {
1368
- const exists = await fs.exists(file_path);
1369
- if (!exists) {
1370
- return {
1371
- toolResponse: `Error: File "${file_path}" does not exist.`,
1372
- data: { path: file_path, success: false, replacements: 0 }
1373
- };
1374
- }
1375
- const content = await fs.readFile(file_path);
1376
- if (!content.includes(old_string)) {
1377
- return {
1378
- toolResponse: `Error: Could not find the specified text in "${file_path}". Make sure old_string matches exactly (whitespace-sensitive).`,
1379
- data: { path: file_path, success: false, replacements: 0 }
1380
- };
1381
- }
1382
- const escapedOldString = escapeRegExp(old_string);
1383
- const globalRegex = new RegExp(escapedOldString, "g");
1384
- const occurrences = (content.match(globalRegex) || []).length;
1385
- if (!replace_all && occurrences > 1) {
1386
- return {
1387
- toolResponse: `Error: old_string appears ${occurrences} times in "${file_path}". Either provide more context to make it unique, or use replace_all: true.`,
1388
- data: { path: file_path, success: false, replacements: 0 }
1389
- };
1390
- }
1391
- let newContent;
1392
- let replacements;
1393
- if (replace_all) {
1394
- newContent = content.split(old_string).join(new_string);
1395
- replacements = occurrences;
1396
- } else {
1397
- const index = content.indexOf(old_string);
1398
- newContent = content.slice(0, index) + new_string + content.slice(index + old_string.length);
1399
- replacements = 1;
1400
- }
1401
- await fs.writeFile(file_path, newContent);
1402
- const summary = replace_all ? `Replaced ${replacements} occurrence(s)` : `Replaced 1 occurrence`;
1622
+ const content = await fs.readFile(file_path);
1623
+ if (!content.includes(old_string)) {
1403
1624
  return {
1404
- toolResponse: `${summary} in ${file_path}`,
1405
- data: { path: file_path, success: true, replacements }
1625
+ toolResponse: `Error: Could not find the specified text in "${file_path}". Make sure old_string matches exactly (whitespace-sensitive).`,
1626
+ data: { path: file_path, success: false, replacements: 0 }
1406
1627
  };
1407
- } catch (error) {
1408
- const message = error instanceof Error ? error.message : "Unknown error";
1628
+ }
1629
+ const escapedOldString = escapeRegExp(old_string);
1630
+ const globalRegex = new RegExp(escapedOldString, "g");
1631
+ const occurrences = (content.match(globalRegex) || []).length;
1632
+ if (!replace_all && occurrences > 1) {
1409
1633
  return {
1410
- toolResponse: `Error editing file "${file_path}": ${message}`,
1634
+ toolResponse: `Error: old_string appears ${occurrences} times in "${file_path}". Either provide more context to make it unique, or use replace_all: true.`,
1411
1635
  data: { path: file_path, success: false, replacements: 0 }
1412
1636
  };
1413
1637
  }
1414
- };
1638
+ let newContent;
1639
+ let replacements;
1640
+ if (replace_all) {
1641
+ newContent = content.split(old_string).join(new_string);
1642
+ replacements = occurrences;
1643
+ } else {
1644
+ const index = content.indexOf(old_string);
1645
+ newContent = content.slice(0, index) + new_string + content.slice(index + old_string.length);
1646
+ replacements = 1;
1647
+ }
1648
+ await fs.writeFile(file_path, newContent);
1649
+ const summary = replace_all ? `Replaced ${replacements} occurrence(s)` : `Replaced 1 occurrence`;
1650
+ return {
1651
+ toolResponse: `${summary} in ${file_path}`,
1652
+ data: { path: file_path, success: true, replacements }
1653
+ };
1654
+ } catch (error) {
1655
+ const message = error instanceof Error ? error.message : "Unknown error";
1656
+ return {
1657
+ toolResponse: `Error editing file "${file_path}": ${message}`,
1658
+ data: { path: file_path, success: false, replacements: 0 }
1659
+ };
1660
+ }
1661
+ };
1662
+
1663
+ // src/tools/glob/handler.ts
1664
+ function matchGlob(pattern, path) {
1665
+ const regex = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*\*/g, "{{GLOBSTAR}}").replace(/\*/g, "[^/]*").replace(/\{\{GLOBSTAR\}\}/g, ".*");
1666
+ return new RegExp(`^${regex}$`).test(path);
1415
1667
  }
1416
- var createBashHandler = (bashOptions) => async (args, _context) => {
1417
- const { command } = args;
1418
- const mergedOptions = {
1419
- ...bashOptions,
1420
- executionLimits: {
1421
- maxStringLength: 52428800,
1422
- // 50MB default
1423
- ...bashOptions.executionLimits
1668
+ async function walk(fs, dir) {
1669
+ const results = [];
1670
+ const entries = await fs.readdirWithFileTypes(dir);
1671
+ for (const entry of entries) {
1672
+ const full = dir === "/" ? `/${entry.name}` : `${dir}/${entry.name}`;
1673
+ if (entry.isDirectory) {
1674
+ results.push(...await walk(fs, full));
1675
+ } else {
1676
+ results.push(full);
1424
1677
  }
1425
- };
1426
- const bash = new justBash.Bash(mergedOptions);
1678
+ }
1679
+ return results;
1680
+ }
1681
+ var globHandler = async (args, { sandbox }) => {
1682
+ const { fs } = sandbox;
1683
+ const { pattern, root = "/" } = args;
1427
1684
  try {
1428
- const { exitCode, stderr, stdout } = await bash.exec(command);
1429
- const bashExecOut = { exitCode, stderr, stdout };
1685
+ const allFiles = await walk(fs, root);
1686
+ const relativeTo = root.endsWith("/") ? root : `${root}/`;
1687
+ const matched = allFiles.map((f) => f.startsWith(relativeTo) ? f.slice(relativeTo.length) : f).filter((f) => matchGlob(pattern, f));
1430
1688
  return {
1431
- toolResponse: `Exit code: ${exitCode}
1432
-
1433
- stdout:
1434
- ${stdout}
1689
+ toolResponse: matched.length > 0 ? `Found ${matched.length} file(s):
1690
+ ${matched.join("\n")}` : `No files matched pattern "${pattern}"`,
1691
+ data: { files: matched }
1692
+ };
1693
+ } catch (error) {
1694
+ const message = error instanceof Error ? error.message : "Unknown error";
1695
+ return {
1696
+ toolResponse: `Error running glob: ${message}`,
1697
+ data: { files: [] }
1698
+ };
1699
+ }
1700
+ };
1435
1701
 
1436
- stderr:
1437
- ${stderr}`,
1438
- data: bashExecOut
1702
+ // src/tools/read-file/handler.ts
1703
+ var readFileHandler = async (args, { sandbox }) => {
1704
+ const { fs } = sandbox;
1705
+ const { path, offset, limit } = args;
1706
+ try {
1707
+ const exists = await fs.exists(path);
1708
+ if (!exists) {
1709
+ return {
1710
+ toolResponse: `Error: File "${path}" does not exist.`,
1711
+ data: null
1712
+ };
1713
+ }
1714
+ const raw = await fs.readFile(path);
1715
+ const lines = raw.split("\n");
1716
+ const totalLines = lines.length;
1717
+ if (offset !== void 0 || limit !== void 0) {
1718
+ const start = Math.max(0, (offset ?? 1) - 1);
1719
+ const end = limit !== void 0 ? start + limit : lines.length;
1720
+ const slice = lines.slice(start, end);
1721
+ const numbered2 = slice.map((line, i) => `${String(start + i + 1).padStart(6)}|${line}`).join("\n");
1722
+ return {
1723
+ toolResponse: numbered2,
1724
+ data: { path, content: numbered2, totalLines }
1725
+ };
1726
+ }
1727
+ const numbered = lines.map((line, i) => `${String(i + 1).padStart(6)}|${line}`).join("\n");
1728
+ return {
1729
+ toolResponse: numbered,
1730
+ data: { path, content: numbered, totalLines }
1439
1731
  };
1440
1732
  } catch (error) {
1441
- const err = error instanceof Error ? error : new Error("Unknown error");
1733
+ const message = error instanceof Error ? error.message : "Unknown error";
1442
1734
  return {
1443
- toolResponse: `Error executing bash command: ${err.message}`,
1735
+ toolResponse: `Error reading file "${path}": ${message}`,
1444
1736
  data: null
1445
1737
  };
1446
1738
  }
1447
1739
  };
1448
1740
 
1449
- // src/lib/fs.ts
1741
+ // src/tools/write-file/handler.ts
1742
+ var writeFileHandler = async (args, { sandbox }) => {
1743
+ const { fs } = sandbox;
1744
+ const { file_path, content } = args;
1745
+ try {
1746
+ const lastSlash = file_path.lastIndexOf("/");
1747
+ if (lastSlash > 0) {
1748
+ const dir = file_path.slice(0, lastSlash);
1749
+ const dirExists = await fs.exists(dir);
1750
+ if (!dirExists) {
1751
+ await fs.mkdir(dir, { recursive: true });
1752
+ }
1753
+ }
1754
+ await fs.writeFile(file_path, content);
1755
+ return {
1756
+ toolResponse: `Successfully wrote to ${file_path}`,
1757
+ data: { path: file_path, success: true }
1758
+ };
1759
+ } catch (error) {
1760
+ const message = error instanceof Error ? error.message : "Unknown error";
1761
+ return {
1762
+ toolResponse: `Error writing file "${file_path}": ${message}`,
1763
+ data: { path: file_path, success: false }
1764
+ };
1765
+ }
1766
+ };
1767
+
1768
+ // src/lib/sandbox/tree.ts
1450
1769
  var basename = (path, separator) => {
1451
1770
  if (path[path.length - 1] === separator) path = path.slice(0, -1);
1452
1771
  const lastSlashIndex = path.lastIndexOf(separator);
@@ -1475,7 +1794,7 @@ var toTree = async (fs, opts = {}) => {
1475
1794
  const sort = opts.sort ?? true;
1476
1795
  let subtree = " (...)";
1477
1796
  if (depth > 0) {
1478
- const list = await fs.readdirWithFileTypes?.(dir) || [];
1797
+ const list = await fs.readdirWithFileTypes(dir);
1479
1798
  if (sort) {
1480
1799
  list.sort((a, b) => {
1481
1800
  if (a.isDirectory && b.isDirectory) {
@@ -1509,78 +1828,22 @@ var toTree = async (fs, opts = {}) => {
1509
1828
  const base = basename(dir, separator) + separator;
1510
1829
  return base + subtree;
1511
1830
  };
1512
- var FileSystemSkillProvider = class {
1513
- constructor(baseDir) {
1514
- this.baseDir = baseDir;
1515
- }
1516
- async listSkills() {
1517
- const dirs = await this.discoverSkillDirs();
1518
- const skills = [];
1519
- for (const dir of dirs) {
1520
- const raw = await promises.readFile(path.join(this.baseDir, dir, "SKILL.md"), "utf-8");
1521
- const { frontmatter } = parseSkillFile(raw);
1522
- skills.push(frontmatter);
1523
- }
1524
- return skills;
1525
- }
1526
- async getSkill(name) {
1527
- const raw = await promises.readFile(
1528
- path.join(this.baseDir, name, "SKILL.md"),
1529
- "utf-8"
1530
- );
1531
- const { frontmatter, body } = parseSkillFile(raw);
1532
- if (frontmatter.name !== name) {
1533
- throw new Error(
1534
- `Skill directory "${name}" contains SKILL.md with mismatched name "${frontmatter.name}"`
1535
- );
1536
- }
1537
- return { ...frontmatter, instructions: body };
1538
- }
1539
- /**
1540
- * Convenience method to load all skills with full instructions.
1541
- * Returns `Skill[]` ready to pass into a workflow.
1542
- */
1543
- async loadAll() {
1544
- const dirs = await this.discoverSkillDirs();
1545
- const skills = [];
1546
- for (const dir of dirs) {
1547
- const raw = await promises.readFile(path.join(this.baseDir, dir, "SKILL.md"), "utf-8");
1548
- const { frontmatter, body } = parseSkillFile(raw);
1549
- skills.push({ ...frontmatter, instructions: body });
1550
- }
1551
- return skills;
1552
- }
1553
- async discoverSkillDirs() {
1554
- const entries = await promises.readdir(this.baseDir, { withFileTypes: true });
1555
- const dirs = [];
1556
- for (const entry of entries) {
1557
- if (!entry.isDirectory()) continue;
1558
- try {
1559
- await promises.readFile(path.join(this.baseDir, entry.name, "SKILL.md"), "utf-8");
1560
- dirs.push(entry.name);
1561
- } catch {
1562
- }
1563
- }
1564
- return dirs;
1565
- }
1566
- };
1567
1831
 
1568
1832
  exports.FileSystemSkillProvider = FileSystemSkillProvider;
1569
- exports.agentQueryName = agentQueryName;
1570
- exports.agentStateChangeUpdateName = agentStateChangeUpdateName;
1833
+ exports.SandboxManager = SandboxManager;
1834
+ exports.SandboxNotFoundError = SandboxNotFoundError;
1835
+ exports.SandboxNotSupportedError = SandboxNotSupportedError;
1836
+ exports.applyVirtualTreeMutations = applyVirtualTreeMutations;
1571
1837
  exports.askUserQuestionTool = askUserQuestionTool;
1838
+ exports.bashHandler = bashHandler;
1572
1839
  exports.bashTool = bashTool;
1573
1840
  exports.createAgentStateManager = createAgentStateManager;
1574
1841
  exports.createAskUserQuestionHandler = createAskUserQuestionHandler;
1575
- exports.createBashHandler = createBashHandler;
1576
1842
  exports.createBashToolDescription = createBashToolDescription;
1577
- exports.createEditHandler = createEditHandler;
1578
- exports.createGlobHandler = createGlobHandler;
1579
1843
  exports.createReadSkillHandler = createReadSkillHandler;
1580
1844
  exports.createReadSkillTool = createReadSkillTool;
1581
1845
  exports.createRunAgentActivity = createRunAgentActivity;
1582
1846
  exports.createSession = createSession;
1583
- exports.createSubagentTool = createSubagentTool;
1584
1847
  exports.createTaskCreateHandler = createTaskCreateHandler;
1585
1848
  exports.createTaskGetHandler = createTaskGetHandler;
1586
1849
  exports.createTaskListHandler = createTaskListHandler;
@@ -1589,15 +1852,20 @@ exports.createThreadManager = createThreadManager;
1589
1852
  exports.createToolRouter = createToolRouter;
1590
1853
  exports.defineSubagent = defineSubagent;
1591
1854
  exports.defineTool = defineTool;
1855
+ exports.editHandler = editHandler;
1592
1856
  exports.editTool = editTool;
1857
+ exports.formatVirtualFileTree = formatVirtualFileTree;
1593
1858
  exports.getShortId = getShortId;
1859
+ exports.globHandler = globHandler;
1594
1860
  exports.globTool = globTool;
1595
1861
  exports.grepTool = grepTool;
1596
1862
  exports.hasNoOtherToolCalls = hasNoOtherToolCalls;
1597
1863
  exports.isTerminalStatus = isTerminalStatus;
1598
1864
  exports.parseSkillFile = parseSkillFile;
1599
1865
  exports.proxyDefaultThreadOps = proxyDefaultThreadOps;
1866
+ exports.proxySandboxOps = proxySandboxOps;
1600
1867
  exports.queryParentWorkflowState = queryParentWorkflowState;
1868
+ exports.readFileHandler = readFileHandler;
1601
1869
  exports.readFileTool = readFileTool;
1602
1870
  exports.taskCreateTool = taskCreateTool;
1603
1871
  exports.taskGetTool = taskGetTool;
@@ -1605,6 +1873,9 @@ exports.taskListTool = taskListTool;
1605
1873
  exports.taskUpdateTool = taskUpdateTool;
1606
1874
  exports.toTree = toTree;
1607
1875
  exports.withAutoAppend = withAutoAppend;
1876
+ exports.withParentWorkflowState = withParentWorkflowState;
1877
+ exports.withSandbox = withSandbox;
1878
+ exports.writeFileHandler = writeFileHandler;
1608
1879
  exports.writeFileTool = writeFileTool;
1609
1880
  //# sourceMappingURL=index.cjs.map
1610
1881
  //# sourceMappingURL=index.cjs.map