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