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.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,198 @@ 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
+ const enabled = subagents.filter((s) => s.enabled ?? true);
382
+ if (enabled.length === 0) return null;
383
+ const subagentHooksMap = /* @__PURE__ */ new Map();
384
+ for (const s of enabled) {
385
+ if (s.hooks) subagentHooksMap.set(s.agentName, s.hooks);
386
+ }
387
+ const resolveSubagentName = (args) => args.subagent;
388
+ return {
389
+ ...createSubagentTool(enabled),
390
+ handler: createSubagentHandler(enabled),
391
+ ...subagentHooksMap.size > 0 && {
392
+ hooks: {
393
+ onPreToolUse: async (ctx) => {
394
+ const hooks = subagentHooksMap.get(resolveSubagentName(ctx.args));
395
+ return hooks?.onPreExecution?.(ctx) ?? {};
396
+ },
397
+ onPostToolUse: async (ctx) => {
398
+ const hooks = subagentHooksMap.get(resolveSubagentName(ctx.args));
399
+ await hooks?.onPostExecution?.(ctx);
400
+ },
401
+ onPostToolUseFailure: async (ctx) => {
402
+ const hooks = subagentHooksMap.get(resolveSubagentName(ctx.args));
403
+ return hooks?.onExecutionFailure?.(ctx) ?? {};
404
+ }
405
+ }
406
+ }
407
+ };
408
+ }
409
+ var READ_SKILL_TOOL_NAME = "ReadSkill";
410
+ function buildReadSkillDescription(skills) {
411
+ const skillList = skills.map((s) => `- **${s.name}**: ${s.description}`).join("\n");
412
+ return `Load the full instructions for a skill. Read the skill before following its instructions.
413
+
414
+ # Available skills:
415
+ ${skillList}
416
+ `;
417
+ }
418
+ function createReadSkillTool(skills) {
419
+ if (skills.length === 0) {
420
+ throw new Error("createReadSkillTool requires at least one skill");
421
+ }
422
+ const names = skills.map((s) => s.name);
423
+ return {
424
+ name: READ_SKILL_TOOL_NAME,
425
+ description: buildReadSkillDescription(skills),
426
+ schema: z14.object({
427
+ skill_name: z14.enum(names).describe("The name of the skill to load")
428
+ })
429
+ };
430
+ }
431
+
432
+ // src/lib/skills/handler.ts
433
+ function createReadSkillHandler(skills) {
434
+ const skillMap = new Map(skills.map((s) => [s.name, s]));
435
+ return (args) => {
436
+ const skill = skillMap.get(args.skill_name);
437
+ if (!skill) {
438
+ return {
439
+ toolResponse: JSON.stringify({
440
+ error: `Skill "${args.skill_name}" not found`
441
+ }),
442
+ data: null
443
+ };
444
+ }
445
+ return {
446
+ toolResponse: skill.instructions,
447
+ data: null
448
+ };
449
+ };
450
+ }
451
+
452
+ // src/lib/skills/register.ts
453
+ function buildSkillRegistration(skills) {
454
+ if (skills.length === 0) return null;
455
+ return {
456
+ ...createReadSkillTool(skills),
457
+ handler: createReadSkillHandler(skills)
458
+ };
459
+ }
464
460
 
465
- // src/lib/session.ts
461
+ // src/lib/session/session.ts
466
462
  var createSession = async ({
467
463
  threadId: providedThreadId,
468
464
  agentName,
@@ -478,7 +474,9 @@ var createSession = async ({
478
474
  hooks = {},
479
475
  appendSystemPrompt = true,
480
476
  continueThread = false,
481
- waitForInputTimeout = "48h"
477
+ waitForInputTimeout = "48h",
478
+ sandbox: sandboxOps,
479
+ sandboxId: inheritedSandboxId
482
480
  }) => {
483
481
  const threadId = providedThreadId ?? getShortId();
484
482
  const {
@@ -487,13 +485,21 @@ var createSession = async ({
487
485
  initializeThread,
488
486
  appendSystemMessage
489
487
  } = threadOps ?? proxyDefaultThreadOps();
488
+ const plugins = [];
489
+ if (subagents) {
490
+ const reg = buildSubagentRegistration(subagents);
491
+ if (reg) plugins.push(reg);
492
+ }
493
+ if (skills) {
494
+ const reg = buildSkillRegistration(skills);
495
+ if (reg) plugins.push(reg);
496
+ }
490
497
  const toolRouter = createToolRouter({
491
498
  tools,
492
499
  appendToolResult,
493
500
  threadId,
494
501
  hooks,
495
- subagents,
496
- skills,
502
+ plugins,
497
503
  parallel: processToolsInParallel
498
504
  });
499
505
  const callSessionEnd = async (exitReason, turns) => {
@@ -530,6 +536,17 @@ var createSession = async ({
530
536
  stateManager.run();
531
537
  }
532
538
  );
539
+ let sandboxId = inheritedSandboxId;
540
+ const ownsSandbox = !sandboxId && !!sandboxOps;
541
+ if (ownsSandbox) {
542
+ const result = await sandboxOps.createSandbox({ id: threadId });
543
+ sandboxId = result.sandboxId;
544
+ if (result.stateUpdate) {
545
+ stateManager.mergeUpdate(
546
+ result.stateUpdate
547
+ );
548
+ }
549
+ }
533
550
  if (hooks.onSessionStart) {
534
551
  await hooks.onSessionStart({
535
552
  threadId,
@@ -570,6 +587,7 @@ var createSession = async ({
570
587
  stateManager.complete();
571
588
  exitReason = "completed";
572
589
  return {
590
+ threadId,
573
591
  finalMessage: message,
574
592
  exitReason,
575
593
  usage: stateManager.getTotalUsage()
@@ -593,7 +611,8 @@ var createSession = async ({
593
611
  const toolCallResults = await toolRouter.processToolCalls(
594
612
  parsedToolCalls,
595
613
  {
596
- turn: currentTurn
614
+ turn: currentTurn,
615
+ ...sandboxId !== void 0 && { sandboxId }
597
616
  }
598
617
  );
599
618
  for (const result of toolCallResults) {
@@ -621,8 +640,12 @@ var createSession = async ({
621
640
  throw ApplicationFailure.fromError(error);
622
641
  } finally {
623
642
  await callSessionEnd(exitReason, stateManager.getTurns());
643
+ if (ownsSandbox && sandboxId && sandboxOps) {
644
+ await sandboxOps.destroySandbox(sandboxId);
645
+ }
624
646
  }
625
647
  return {
648
+ threadId,
626
649
  finalMessage: null,
627
650
  exitReason,
628
651
  usage: stateManager.getTotalUsage()
@@ -643,16 +666,26 @@ function proxyDefaultThreadOps(options) {
643
666
  }
644
667
  );
645
668
  }
669
+ function proxySandboxOps(options) {
670
+ return proxyActivities(
671
+ options ?? {
672
+ startToCloseTimeout: "30s",
673
+ retry: {
674
+ maximumAttempts: 3,
675
+ initialInterval: "2s",
676
+ maximumInterval: "30s",
677
+ backoffCoefficient: 2
678
+ }
679
+ }
680
+ );
681
+ }
646
682
 
647
683
  // src/lib/types.ts
648
- var agentQueryName = (agentName) => `get${agentName}State`;
649
- var agentStateChangeUpdateName = (agentName) => `waitFor${agentName}StateChange`;
650
684
  function isTerminalStatus(status) {
651
685
  return status === "COMPLETED" || status === "FAILED" || status === "CANCELLED";
652
686
  }
653
687
  function createAgentStateManager({
654
- initialState,
655
- agentName
688
+ initialState
656
689
  }) {
657
690
  let status = initialState?.status ?? "RUNNING";
658
691
  let version = initialState?.version ?? 0;
@@ -683,11 +716,9 @@ function createAgentStateManager({
683
716
  ...customState
684
717
  };
685
718
  }
686
- const stateQuery = defineQuery(
687
- agentQueryName(agentName)
688
- );
719
+ const stateQuery = defineQuery("getAgentState");
689
720
  const stateChangeUpdate = defineUpdate(
690
- agentStateChangeUpdateName(agentName)
721
+ "waitForAgentStateChange"
691
722
  );
692
723
  setHandler(stateQuery, () => buildState());
693
724
  setHandler(stateChangeUpdate, async (lastKnownVersion) => {
@@ -751,6 +782,10 @@ function createAgentStateManager({
751
782
  customState[key] = value;
752
783
  version++;
753
784
  },
785
+ mergeUpdate(update) {
786
+ Object.assign(customState, update);
787
+ version++;
788
+ },
754
789
  getCurrentState() {
755
790
  return buildState();
756
791
  },
@@ -806,6 +841,95 @@ function createAgentStateManager({
806
841
  };
807
842
  }
808
843
 
844
+ // src/lib/subagent/define.ts
845
+ function defineSubagent(config) {
846
+ return config;
847
+ }
848
+ var SandboxNotSupportedError = class extends ApplicationFailure$1 {
849
+ constructor(operation) {
850
+ super(
851
+ `Sandbox does not support: ${operation}`,
852
+ "SandboxNotSupportedError",
853
+ true
854
+ );
855
+ }
856
+ };
857
+ var SandboxNotFoundError = class extends ApplicationFailure$1 {
858
+ constructor(sandboxId) {
859
+ super(`Sandbox not found: ${sandboxId}`, "SandboxNotFoundError", true);
860
+ }
861
+ };
862
+
863
+ // src/adapters/sandbox/virtual/mutations.ts
864
+ function applyVirtualTreeMutations(stateManager, mutations) {
865
+ let tree = [...stateManager.get("fileTree")];
866
+ for (const m of mutations) {
867
+ switch (m.type) {
868
+ case "add":
869
+ tree.push(m.entry);
870
+ break;
871
+ case "remove":
872
+ tree = tree.filter((e) => e.path !== m.path);
873
+ break;
874
+ case "update":
875
+ tree = tree.map(
876
+ (e) => e.path === m.path ? { ...e, ...m.entry } : e
877
+ );
878
+ break;
879
+ }
880
+ }
881
+ stateManager.set("fileTree", tree);
882
+ return tree;
883
+ }
884
+
885
+ // src/adapters/sandbox/virtual/tree.ts
886
+ var buildTree = (entries) => {
887
+ const root = { name: "/", children: /* @__PURE__ */ new Map(), isFile: false };
888
+ for (const entry of entries) {
889
+ const parts = entry.path.split("/").filter(Boolean);
890
+ let current = root;
891
+ for (const part of parts) {
892
+ let child = current.children.get(part);
893
+ if (!child) {
894
+ child = { name: part, children: /* @__PURE__ */ new Map(), isFile: false };
895
+ current.children.set(part, child);
896
+ }
897
+ current = child;
898
+ }
899
+ current.isFile = current.children.size === 0;
900
+ }
901
+ return root;
902
+ };
903
+ var printNode = (node, tab, sort) => {
904
+ const entries = [...node.children.values()];
905
+ if (sort) {
906
+ entries.sort((a, b) => {
907
+ if (!a.isFile && !b.isFile) return a.name.localeCompare(b.name);
908
+ if (!a.isFile) return -1;
909
+ if (!b.isFile) return 1;
910
+ return a.name.localeCompare(b.name);
911
+ });
912
+ }
913
+ let str = "";
914
+ for (const [i, entry] of entries.entries()) {
915
+ const isLast = i === entries.length - 1;
916
+ const branch = isLast ? "\u2514\u2500" : "\u251C\u2500";
917
+ const childTab = tab + (isLast ? " " : "\u2502 ");
918
+ if (entry.isFile) {
919
+ str += "\n" + tab + branch + " " + entry.name;
920
+ } else {
921
+ const subtree = printNode(entry, childTab, sort);
922
+ str += "\n" + tab + branch + " " + entry.name + "/" + subtree;
923
+ }
924
+ }
925
+ return str;
926
+ };
927
+ function formatVirtualFileTree(entries, opts = {}) {
928
+ const sort = opts.sort ?? true;
929
+ const root = buildTree(entries);
930
+ return "/" + printNode(root, "", sort);
931
+ }
932
+
809
933
  // src/lib/skills/parse.ts
810
934
  function parseSkillFile(raw) {
811
935
  const trimmed = raw.replace(/^\uFEFF/, "");
@@ -1228,6 +1352,6 @@ var createAskUserQuestionHandler = () => async (args) => {
1228
1352
  };
1229
1353
  };
1230
1354
 
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 };
1355
+ 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
1356
  //# sourceMappingURL=workflow.js.map
1233
1357
  //# sourceMappingURL=workflow.js.map