zeitlich 0.2.13 → 0.2.15

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