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