zeitlich 0.2.35 → 0.2.37

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 (199) hide show
  1. package/README.md +146 -92
  2. package/dist/{activities-BVI2lTwr.d.ts → activities-Bb-nAjwQ.d.ts} +2 -2
  3. package/dist/{activities-hd4aNnZE.d.cts → activities-vkI4_3CC.d.cts} +2 -2
  4. package/dist/adapters/sandbox/bedrock/index.cjs +14 -11
  5. package/dist/adapters/sandbox/bedrock/index.cjs.map +1 -1
  6. package/dist/adapters/sandbox/bedrock/index.d.cts +4 -3
  7. package/dist/adapters/sandbox/bedrock/index.d.ts +4 -3
  8. package/dist/adapters/sandbox/bedrock/index.js +14 -11
  9. package/dist/adapters/sandbox/bedrock/index.js.map +1 -1
  10. package/dist/adapters/sandbox/bedrock/workflow.cjs +2 -0
  11. package/dist/adapters/sandbox/bedrock/workflow.cjs.map +1 -1
  12. package/dist/adapters/sandbox/bedrock/workflow.d.cts +2 -2
  13. package/dist/adapters/sandbox/bedrock/workflow.d.ts +2 -2
  14. package/dist/adapters/sandbox/bedrock/workflow.js +2 -0
  15. package/dist/adapters/sandbox/bedrock/workflow.js.map +1 -1
  16. package/dist/adapters/sandbox/daytona/index.cjs +35 -6
  17. package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
  18. package/dist/adapters/sandbox/daytona/index.d.cts +3 -1
  19. package/dist/adapters/sandbox/daytona/index.d.ts +3 -1
  20. package/dist/adapters/sandbox/daytona/index.js +35 -6
  21. package/dist/adapters/sandbox/daytona/index.js.map +1 -1
  22. package/dist/adapters/sandbox/daytona/workflow.cjs +2 -0
  23. package/dist/adapters/sandbox/daytona/workflow.cjs.map +1 -1
  24. package/dist/adapters/sandbox/daytona/workflow.d.cts +1 -1
  25. package/dist/adapters/sandbox/daytona/workflow.d.ts +1 -1
  26. package/dist/adapters/sandbox/daytona/workflow.js +2 -0
  27. package/dist/adapters/sandbox/daytona/workflow.js.map +1 -1
  28. package/dist/adapters/sandbox/e2b/index.cjs +59 -10
  29. package/dist/adapters/sandbox/e2b/index.cjs.map +1 -1
  30. package/dist/adapters/sandbox/e2b/index.d.cts +5 -3
  31. package/dist/adapters/sandbox/e2b/index.d.ts +5 -3
  32. package/dist/adapters/sandbox/e2b/index.js +59 -10
  33. package/dist/adapters/sandbox/e2b/index.js.map +1 -1
  34. package/dist/adapters/sandbox/e2b/workflow.cjs +2 -0
  35. package/dist/adapters/sandbox/e2b/workflow.cjs.map +1 -1
  36. package/dist/adapters/sandbox/e2b/workflow.d.cts +1 -1
  37. package/dist/adapters/sandbox/e2b/workflow.d.ts +1 -1
  38. package/dist/adapters/sandbox/e2b/workflow.js +2 -0
  39. package/dist/adapters/sandbox/e2b/workflow.js.map +1 -1
  40. package/dist/adapters/sandbox/inmemory/index.cjs +5 -0
  41. package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
  42. package/dist/adapters/sandbox/inmemory/index.d.cts +2 -1
  43. package/dist/adapters/sandbox/inmemory/index.d.ts +2 -1
  44. package/dist/adapters/sandbox/inmemory/index.js +5 -0
  45. package/dist/adapters/sandbox/inmemory/index.js.map +1 -1
  46. package/dist/adapters/sandbox/inmemory/workflow.cjs +2 -0
  47. package/dist/adapters/sandbox/inmemory/workflow.cjs.map +1 -1
  48. package/dist/adapters/sandbox/inmemory/workflow.d.cts +1 -1
  49. package/dist/adapters/sandbox/inmemory/workflow.d.ts +1 -1
  50. package/dist/adapters/sandbox/inmemory/workflow.js +2 -0
  51. package/dist/adapters/sandbox/inmemory/workflow.js.map +1 -1
  52. package/dist/adapters/thread/anthropic/index.cjs +71 -36
  53. package/dist/adapters/thread/anthropic/index.cjs.map +1 -1
  54. package/dist/adapters/thread/anthropic/index.d.cts +5 -5
  55. package/dist/adapters/thread/anthropic/index.d.ts +5 -5
  56. package/dist/adapters/thread/anthropic/index.js +71 -36
  57. package/dist/adapters/thread/anthropic/index.js.map +1 -1
  58. package/dist/adapters/thread/anthropic/workflow.cjs +5 -1
  59. package/dist/adapters/thread/anthropic/workflow.cjs.map +1 -1
  60. package/dist/adapters/thread/anthropic/workflow.d.cts +5 -5
  61. package/dist/adapters/thread/anthropic/workflow.d.ts +5 -5
  62. package/dist/adapters/thread/anthropic/workflow.js +5 -1
  63. package/dist/adapters/thread/anthropic/workflow.js.map +1 -1
  64. package/dist/adapters/thread/google-genai/index.cjs +50 -25
  65. package/dist/adapters/thread/google-genai/index.cjs.map +1 -1
  66. package/dist/adapters/thread/google-genai/index.d.cts +5 -5
  67. package/dist/adapters/thread/google-genai/index.d.ts +5 -5
  68. package/dist/adapters/thread/google-genai/index.js +50 -25
  69. package/dist/adapters/thread/google-genai/index.js.map +1 -1
  70. package/dist/adapters/thread/google-genai/workflow.cjs +5 -1
  71. package/dist/adapters/thread/google-genai/workflow.cjs.map +1 -1
  72. package/dist/adapters/thread/google-genai/workflow.d.cts +5 -5
  73. package/dist/adapters/thread/google-genai/workflow.d.ts +5 -5
  74. package/dist/adapters/thread/google-genai/workflow.js +5 -1
  75. package/dist/adapters/thread/google-genai/workflow.js.map +1 -1
  76. package/dist/adapters/thread/langchain/index.cjs +34 -7
  77. package/dist/adapters/thread/langchain/index.cjs.map +1 -1
  78. package/dist/adapters/thread/langchain/index.d.cts +5 -5
  79. package/dist/adapters/thread/langchain/index.d.ts +5 -5
  80. package/dist/adapters/thread/langchain/index.js +34 -7
  81. package/dist/adapters/thread/langchain/index.js.map +1 -1
  82. package/dist/adapters/thread/langchain/workflow.cjs +5 -1
  83. package/dist/adapters/thread/langchain/workflow.cjs.map +1 -1
  84. package/dist/adapters/thread/langchain/workflow.d.cts +5 -5
  85. package/dist/adapters/thread/langchain/workflow.d.ts +5 -5
  86. package/dist/adapters/thread/langchain/workflow.js +5 -1
  87. package/dist/adapters/thread/langchain/workflow.js.map +1 -1
  88. package/dist/index.cjs +206 -120
  89. package/dist/index.cjs.map +1 -1
  90. package/dist/index.d.cts +17 -11
  91. package/dist/index.d.ts +17 -11
  92. package/dist/index.js +207 -121
  93. package/dist/index.js.map +1 -1
  94. package/dist/{proxy-BjdFGPTm.d.ts → proxy-0smGKvx8.d.ts} +1 -1
  95. package/dist/{proxy-7RnVaPdJ.d.cts → proxy-DEtowJyd.d.cts} +1 -1
  96. package/dist/{thread-manager-DjN5JYul.d.ts → thread-manager-3fszQih4.d.ts} +2 -2
  97. package/dist/{thread-manager-CbpiGq1L.d.ts → thread-manager-C-C4pI2z.d.ts} +2 -2
  98. package/dist/{thread-manager-BBzNgQWH.d.cts → thread-manager-CzYln2OC.d.cts} +2 -2
  99. package/dist/{thread-manager-DzXm9eeI.d.cts → thread-manager-D4vgzYrh.d.cts} +2 -2
  100. package/dist/{types-yiXmqedU.d.ts → types-B37hKoWA.d.ts} +1 -1
  101. package/dist/{types-DQ1l_gXL.d.cts → types-BO7Yju20.d.cts} +63 -14
  102. package/dist/{types-wiGLvxWf.d.ts → types-CNuWnvy9.d.ts} +1 -1
  103. package/dist/{types-CADc5V_P.d.ts → types-CPKDl-y_.d.ts} +63 -14
  104. package/dist/{types-Mc_4BCfT.d.cts → types-D08CXPh8.d.cts} +1 -1
  105. package/dist/{types-CBH54cwr.d.cts → types-DWEUmYAJ.d.cts} +1 -1
  106. package/dist/{types-DxCpFNv_.d.cts → types-tQL9njTu.d.cts} +25 -0
  107. package/dist/{types-DxCpFNv_.d.ts → types-tQL9njTu.d.ts} +25 -0
  108. package/dist/{workflow-P2pTSfKu.d.ts → workflow-CjXHbZZc.d.ts} +2 -2
  109. package/dist/{workflow-DhtWRovz.d.cts → workflow-Do_lzJpT.d.cts} +2 -2
  110. package/dist/workflow.cjs +182 -114
  111. package/dist/workflow.cjs.map +1 -1
  112. package/dist/workflow.d.cts +3 -3
  113. package/dist/workflow.d.ts +3 -3
  114. package/dist/workflow.js +183 -115
  115. package/dist/workflow.js.map +1 -1
  116. package/package.json +1 -1
  117. package/src/adapters/sandbox/bedrock/filesystem.ts +6 -12
  118. package/src/adapters/sandbox/bedrock/index.ts +10 -8
  119. package/src/adapters/sandbox/bedrock/proxy.ts +2 -0
  120. package/src/adapters/sandbox/daytona/filesystem.ts +29 -6
  121. package/src/adapters/sandbox/daytona/index.ts +6 -0
  122. package/src/adapters/sandbox/daytona/proxy.ts +2 -0
  123. package/src/adapters/sandbox/e2b/filesystem.ts +5 -4
  124. package/src/adapters/sandbox/e2b/index.ts +63 -12
  125. package/src/adapters/sandbox/e2b/proxy.ts +2 -0
  126. package/src/adapters/sandbox/inmemory/index.ts +5 -0
  127. package/src/adapters/sandbox/inmemory/proxy.ts +2 -0
  128. package/src/adapters/thread/anthropic/activities.ts +49 -26
  129. package/src/adapters/thread/anthropic/model-invoker.ts +15 -6
  130. package/src/adapters/thread/anthropic/proxy.ts +6 -2
  131. package/src/adapters/thread/anthropic/thread-manager.test.ts +26 -7
  132. package/src/adapters/thread/anthropic/thread-manager.ts +60 -46
  133. package/src/adapters/thread/google-genai/activities.ts +7 -2
  134. package/src/adapters/thread/google-genai/model-invoker.ts +26 -8
  135. package/src/adapters/thread/google-genai/proxy.ts +6 -2
  136. package/src/adapters/thread/google-genai/thread-manager.test.ts +13 -3
  137. package/src/adapters/thread/google-genai/thread-manager.ts +54 -33
  138. package/src/adapters/thread/langchain/activities.ts +46 -24
  139. package/src/adapters/thread/langchain/hooks.test.ts +36 -49
  140. package/src/adapters/thread/langchain/hooks.ts +18 -5
  141. package/src/adapters/thread/langchain/model-invoker.ts +3 -3
  142. package/src/adapters/thread/langchain/proxy.ts +6 -2
  143. package/src/adapters/thread/langchain/thread-manager.test.ts +5 -1
  144. package/src/adapters/thread/langchain/thread-manager.ts +20 -9
  145. package/src/index.ts +4 -1
  146. package/src/lib/activity.ts +16 -6
  147. package/src/lib/hooks/types.ts +6 -6
  148. package/src/lib/lifecycle.ts +9 -1
  149. package/src/lib/model/proxy.ts +2 -2
  150. package/src/lib/observability/hooks.ts +4 -5
  151. package/src/lib/observability/index.ts +1 -4
  152. package/src/lib/sandbox/manager.ts +21 -4
  153. package/src/lib/sandbox/node-fs.ts +3 -6
  154. package/src/lib/sandbox/sandbox.test.ts +36 -3
  155. package/src/lib/sandbox/tree.integration.test.ts +10 -3
  156. package/src/lib/sandbox/types.ts +35 -1
  157. package/src/lib/session/session-edge-cases.integration.test.ts +51 -13
  158. package/src/lib/session/session.integration.test.ts +139 -0
  159. package/src/lib/session/session.ts +50 -19
  160. package/src/lib/session/types.ts +13 -5
  161. package/src/lib/skills/fs-provider.ts +12 -8
  162. package/src/lib/skills/handler.ts +1 -1
  163. package/src/lib/skills/parse.ts +3 -1
  164. package/src/lib/skills/register.ts +1 -3
  165. package/src/lib/skills/skills.integration.test.ts +25 -15
  166. package/src/lib/state/manager.integration.test.ts +12 -2
  167. package/src/lib/subagent/define.ts +1 -1
  168. package/src/lib/subagent/handler.ts +186 -71
  169. package/src/lib/subagent/index.ts +1 -5
  170. package/src/lib/subagent/register.ts +3 -2
  171. package/src/lib/subagent/signals.ts +1 -10
  172. package/src/lib/subagent/subagent.integration.test.ts +438 -156
  173. package/src/lib/subagent/tool.ts +4 -3
  174. package/src/lib/subagent/types.ts +50 -20
  175. package/src/lib/subagent/workflow.ts +9 -49
  176. package/src/lib/thread/id.test.ts +1 -1
  177. package/src/lib/thread/id.ts +1 -2
  178. package/src/lib/thread/proxy.ts +3 -4
  179. package/src/lib/thread/types.ts +11 -3
  180. package/src/lib/tool-router/index.ts +1 -5
  181. package/src/lib/tool-router/router-edge-cases.integration.test.ts +1 -1
  182. package/src/lib/tool-router/router.ts +3 -2
  183. package/src/lib/tool-router/types.ts +11 -3
  184. package/src/lib/tool-router/with-sandbox.ts +19 -5
  185. package/src/lib/virtual-fs/filesystem.ts +1 -1
  186. package/src/lib/virtual-fs/index.ts +5 -1
  187. package/src/lib/virtual-fs/mutations.ts +2 -4
  188. package/src/lib/virtual-fs/queries.ts +9 -5
  189. package/src/lib/virtual-fs/types.ts +4 -1
  190. package/src/lib/virtual-fs/virtual-fs.test.ts +9 -11
  191. package/src/lib/workflow.test.ts +7 -4
  192. package/src/lib/workflow.ts +1 -5
  193. package/src/tools/ask-user-question/tool.ts +1 -3
  194. package/src/tools/glob/handler.ts +1 -4
  195. package/src/tools/task-get/handler.ts +4 -5
  196. package/src/tools/task-list/handler.ts +1 -4
  197. package/src/tools/task-update/handler.ts +4 -5
  198. package/src/workflow.ts +20 -7
  199. package/tsup.config.ts +9 -6
@@ -6,9 +6,10 @@ export const SUBAGENT_TOOL_NAME = "Subagent" as const;
6
6
  function buildSubagentDescription(subagents: SubagentConfig[]): string {
7
7
  const subagentList = subagents
8
8
  .map((s) => {
9
- const continuation = s.thread && s.thread !== "new"
10
- ? "\n*(Supports thread continuation — pass a threadId to resume a previous conversation)*"
11
- : "";
9
+ const continuation =
10
+ s.thread && s.thread !== "new"
11
+ ? "\n*(Supports thread continuation — pass a threadId to resume a previous conversation)*"
12
+ : "";
12
13
  return `## ${s.agentName}\n${s.description}${continuation}`;
13
14
  })
14
15
  .join("\n\n");
@@ -10,10 +10,24 @@ import type {
10
10
  SandboxInit,
11
11
  SubagentSandboxShutdown,
12
12
  } from "../lifecycle";
13
+ import type { SandboxOps, SandboxSnapshot } from "../sandbox/types";
13
14
 
14
15
  /** ToolHandlerResponse with threadId required (subagents must always surface their thread) */
15
- export type SubagentHandlerResponse<TResult = null, TToolResponse = JsonValue> =
16
- ToolHandlerResponse<TResult, TToolResponse> & { threadId: string; sandboxId?: string };
16
+ export type SubagentHandlerResponse<
17
+ TResult = null,
18
+ TToolResponse = JsonValue,
19
+ > = ToolHandlerResponse<TResult, TToolResponse> & {
20
+ threadId: string;
21
+ sandboxId?: string;
22
+ /** Snapshot captured on session exit when `sandboxShutdown === "snapshot"`. */
23
+ snapshot?: SandboxSnapshot;
24
+ /**
25
+ * Snapshot captured immediately after the sandbox was seeded (before the
26
+ * first agent turn) when `continuation === "snapshot"`. Only set on the
27
+ * first call that actually created the sandbox.
28
+ */
29
+ baseSnapshot?: SandboxSnapshot;
30
+ };
17
31
 
18
32
  /**
19
33
  * Raw workflow input fields passed from parent to child workflow.
@@ -64,13 +78,19 @@ export type InferSubagentResult<T extends SubagentConfig> =
64
78
  * Sandbox configuration for a subagent.
65
79
  *
66
80
  * - `"none"` — no sandbox (default).
67
- * - `{ source: "inherit", continuation }` — reuse the parent's sandbox.
81
+ * - `{ source: "inherit", continuation, proxy }` — reuse the parent's sandbox.
68
82
  * `continuation: "continue"` shares the parent sandbox directly;
69
83
  * `continuation: "fork"` forks from the parent on every call.
70
- * - `{ source: "own", init?, continuation }` — the child gets its own sandbox.
71
- * `init: "per-call"` (default) creates fresh each call (thread continuation
72
- * uses the previous sandbox). `init: "once"` creates on the first call and
73
- * stores it for all subsequent calls.
84
+ * - `{ source: "own", init?, continuation, proxy }` — the child gets its own
85
+ * sandbox. `init: "per-call"` (default) creates fresh each call (thread
86
+ * continuation uses the previous sandbox). `init: "once"` creates on the
87
+ * first call and stores it for all subsequent calls.
88
+ *
89
+ * `proxy` is a factory that returns workflow-safe sandbox ops matching the
90
+ * subagent's own activities. Called once inside `createSubagentHandler` with
91
+ * `scope = agentName`, so the returned proxy resolves to the same activity
92
+ * prefix the child session uses. The parent uses it to destroy lingering
93
+ * sandboxes and delete stored snapshots at shutdown.
74
94
  */
75
95
  export type SubagentSandboxConfig =
76
96
  | "none"
@@ -78,12 +98,14 @@ export type SubagentSandboxConfig =
78
98
  source: "inherit";
79
99
  continuation: "continue" | "fork";
80
100
  shutdown?: SubagentSandboxShutdown;
101
+ proxy: (scope: string) => SandboxOps;
81
102
  }
82
103
  | {
83
104
  source: "own";
84
105
  init?: "per-call" | "once";
85
- continuation: "continue" | "fork";
106
+ continuation: "continue" | "fork" | "snapshot";
86
107
  shutdown?: SubagentSandboxShutdown;
108
+ proxy: (scope: string) => SandboxOps;
87
109
  };
88
110
 
89
111
  /**
@@ -122,6 +144,21 @@ export interface SubagentConfig<TResult extends z.ZodType = z.ZodType> {
122
144
  * Sandbox strategy for this subagent.
123
145
  *
124
146
  * @see {@link SubagentSandboxConfig}
147
+ *
148
+ * @example
149
+ * ```ts
150
+ * import { proxyDaytonaSandboxOps } from "zeitlich/adapters/sandbox/daytona/workflow";
151
+ *
152
+ * const researcher: SubagentConfig = {
153
+ * agentName: "researcher",
154
+ * workflow: researcherWorkflow,
155
+ * sandbox: {
156
+ * source: "own",
157
+ * continuation: "snapshot",
158
+ * proxy: proxyDaytonaSandboxOps,
159
+ * },
160
+ * };
161
+ * ```
125
162
  */
126
163
  sandbox?: SubagentSandboxConfig;
127
164
  }
@@ -157,12 +194,11 @@ export interface SubagentHooks<TArgs = unknown, TResult = unknown> {
157
194
  }
158
195
 
159
196
  /**
160
- * Extended response from the subagent `fn` — includes optional cleanup callbacks
161
- * stripped before signaling the parent.
197
+ * Response returned from a subagent workflow `fn`.
162
198
  *
163
199
  * When `TSandboxShutdown` is `"pause-until-parent-close"` or
164
- * `"keep-until-parent-close"`, both `destroySandbox` and `sandboxId` become
165
- * required so the parent can coordinate cleanup.
200
+ * `"keep-until-parent-close"`, the parent needs the `sandboxId` to destroy
201
+ * the sandbox at its own shutdown, so the field becomes required.
166
202
  */
167
203
  export type SubagentFnResult<
168
204
  TResult = null,
@@ -171,14 +207,8 @@ export type SubagentFnResult<
171
207
  (TSandboxShutdown extends
172
208
  | "pause-until-parent-close"
173
209
  | "keep-until-parent-close"
174
- ? { destroySandbox: () => Promise<void>; sandboxId: string }
175
- : { destroySandbox?: () => Promise<void> });
176
-
177
- /** Payload sent by a child workflow to signal its result back to the parent */
178
- export interface ChildResultSignalPayload {
179
- childWorkflowId: string;
180
- result: SubagentHandlerResponse;
181
- }
210
+ ? { sandboxId: string }
211
+ : { sandboxId?: string });
182
212
 
183
213
  /** Payload sent by a child workflow as soon as its sandbox is ready */
184
214
  export interface ChildSandboxReadySignalPayload {
@@ -2,8 +2,6 @@ import type { z } from "zod";
2
2
  import {
3
3
  workflowInfo,
4
4
  getExternalWorkflowHandle,
5
- setHandler,
6
- condition,
7
5
  ApplicationFailure,
8
6
  } from "@temporalio/workflow";
9
7
  import type {
@@ -14,11 +12,7 @@ import type {
14
12
  SubagentSessionInput,
15
13
  } from "./types";
16
14
  import type { SubagentSandboxShutdown } from "../lifecycle";
17
- import {
18
- childResultSignal,
19
- childSandboxReadySignal,
20
- destroySandboxSignal,
21
- } from "./signals";
15
+ import { childSandboxReadySignal } from "./signals";
22
16
 
23
17
  /**
24
18
  * Defines a subagent workflow with embedded metadata (name, description, resultSchema).
@@ -137,51 +131,17 @@ export function defineSubagentWorkflow(
137
131
  ...(workflowInput.thread && { thread: workflowInput.thread }),
138
132
  ...(workflowInput.sandbox && { sandbox: workflowInput.sandbox }),
139
133
  onSandboxReady: (sandboxId: string) => {
140
- void parentHandle.signal(childSandboxReadySignal, {
141
- childWorkflowId: workflowInfo().workflowId,
142
- sandboxId,
143
- });
134
+ const isReuse = workflowInput.sandbox?.mode === "continue";
135
+ if (!isReuse) {
136
+ void parentHandle.signal(childSandboxReadySignal, {
137
+ childWorkflowId: workflowInfo().workflowId,
138
+ sandboxId,
139
+ });
140
+ }
144
141
  },
145
142
  };
146
- const { destroySandbox, ...result } = await fn(
147
- prompt,
148
- sessionInput,
149
- context ?? {}
150
- );
151
-
152
- if (
153
- effectiveShutdown === "pause-until-parent-close" ||
154
- effectiveShutdown === "keep-until-parent-close"
155
- ) {
156
- if (!destroySandbox) {
157
- throw ApplicationFailure.create({
158
- message: `Subagent "${config.name}" has sandboxShutdown="${effectiveShutdown}" but fn did not return a destroySandbox callback`,
159
- nonRetryable: true,
160
- });
161
- }
162
- if (!result.sandboxId) {
163
- throw ApplicationFailure.create({
164
- message: `Subagent "${config.name}" has sandboxShutdown="${effectiveShutdown}" but fn did not return a sandboxId`,
165
- nonRetryable: true,
166
- });
167
- }
168
- }
169
-
170
- await parentHandle.signal(childResultSignal, {
171
- childWorkflowId: workflowInfo().workflowId,
172
- result,
173
- });
174
-
175
- if (destroySandbox) {
176
- let destroyRequested = false;
177
- setHandler(destroySandboxSignal, () => {
178
- destroyRequested = true;
179
- });
180
- await condition(() => destroyRequested);
181
- await destroySandbox();
182
- }
183
143
 
184
- return result;
144
+ return fn(prompt, sessionInput, context ?? {});
185
145
  };
186
146
 
187
147
  // for temporal workflow name
@@ -8,7 +8,7 @@ vi.mock("@temporalio/workflow", () => ({
8
8
  const bytes = Array.from({ length: 16 }, (_, i) =>
9
9
  ((uuidCounter * 31 + i * 7 + uuidCounter * i) & 0xff)
10
10
  .toString(16)
11
- .padStart(2, "0"),
11
+ .padStart(2, "0")
12
12
  ).join("");
13
13
  return `${bytes.slice(0, 8)}-${bytes.slice(8, 12)}-${bytes.slice(12, 16)}-${bytes.slice(16, 20)}-${bytes.slice(20, 32)}`;
14
14
  },
@@ -1,7 +1,6 @@
1
1
  import { uuid4 } from "@temporalio/workflow";
2
2
 
3
- const BASE62 =
4
- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
3
+ const BASE62 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
5
4
 
6
5
  /**
7
6
  * Generate a compact, workflow-deterministic identifier.
@@ -25,7 +25,7 @@ import type { ThreadOps } from "../session/types";
25
25
  export function createThreadOpsProxy(
26
26
  adapterPrefix: string,
27
27
  scope?: string,
28
- options?: Parameters<typeof proxyActivities>[0],
28
+ options?: Parameters<typeof proxyActivities>[0]
29
29
  ): ActivityInterfaceFor<ThreadOps> {
30
30
  const resolvedScope = scope ?? workflowInfo().workflowType;
31
31
 
@@ -39,11 +39,10 @@ export function createThreadOpsProxy(
39
39
  maximumInterval: "15m",
40
40
  backoffCoefficient: 4,
41
41
  },
42
- },
42
+ }
43
43
  );
44
44
 
45
- const prefix =
46
- `${adapterPrefix}${resolvedScope.charAt(0).toUpperCase()}${resolvedScope.slice(1)}`;
45
+ const prefix = `${adapterPrefix}${resolvedScope.charAt(0).toUpperCase()}${resolvedScope.slice(1)}`;
47
46
  const p = (key: string): string =>
48
47
  `${prefix}${key.charAt(0).toUpperCase()}${key.slice(1)}`;
49
48
 
@@ -61,9 +61,17 @@ export interface BaseThreadManager<T> {
61
61
  */
62
62
  export interface ThreadManagerHooks<TStored, TPrepared = TStored> {
63
63
  /** Called for each stored message before SDK-specific processing (system extraction, role merging, format conversion) */
64
- onPrepareMessage?: (message: TStored, index: number, thread: readonly TStored[]) => TStored;
64
+ onPrepareMessage?: (
65
+ message: TStored,
66
+ index: number,
67
+ thread: readonly TStored[]
68
+ ) => TStored;
65
69
  /** Called for each SDK-native message after all processing, right before the payload is returned */
66
- onPreparedMessage?: (message: TPrepared, index: number, messages: readonly TPrepared[]) => TPrepared;
70
+ onPreparedMessage?: (
71
+ message: TPrepared,
72
+ index: number,
73
+ messages: readonly TPrepared[]
74
+ ) => TPrepared;
67
75
  }
68
76
 
69
77
  export interface ProviderThreadManager<
@@ -78,6 +86,6 @@ export interface ProviderThreadManager<
78
86
  id: string,
79
87
  toolCallId: string,
80
88
  toolName: string,
81
- content: TToolContent,
89
+ content: TToolContent
82
90
  ): Promise<void>;
83
91
  }
@@ -1,8 +1,4 @@
1
- export {
2
- createToolRouter,
3
- defineTool,
4
- hasNoOtherToolCalls,
5
- } from "./router";
1
+ export { createToolRouter, defineTool, hasNoOtherToolCalls } from "./router";
6
2
  export { withAutoAppend } from "./auto-append";
7
3
  export { withSandbox } from "./with-sandbox";
8
4
  export type { SandboxContext } from "./with-sandbox";
@@ -348,7 +348,7 @@ describe("createToolRouter edge cases", () => {
348
348
  parallel: true,
349
349
  });
350
350
 
351
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
351
+
352
352
  const results = await router.processToolCalls([
353
353
  { id: "tc-1", name: "Unknown1", args: {} },
354
354
  { id: "tc-2", name: "Unknown2", args: {} },
@@ -162,7 +162,8 @@ export function createToolRouter<T extends ToolMap>(
162
162
 
163
163
  return {
164
164
  content: JSON.stringify({
165
- error: "The tool encountered an error. Please try again or use a different approach.",
165
+ error:
166
+ "The tool encountered an error. Please try again or use a different approach.",
166
167
  }),
167
168
  result: { error: errorStr, suppressed: true },
168
169
  };
@@ -201,7 +202,7 @@ export function createToolRouter<T extends ToolMap>(
201
202
  async function processToolCall(
202
203
  toolCall: ParsedToolCallUnion<T>,
203
204
  turn: number,
204
- sandboxId?: string,
205
+ sandboxId?: string
205
206
  ): Promise<ToolCallResultUnion<TResults> | null> {
206
207
  const startTime = Date.now();
207
208
  const tool = toolMap.get(toolCall.name);
@@ -124,7 +124,10 @@ export type AppendToolResultFn = ActivityFunctionWithOptions<
124
124
  * Tools that don't return additional data should use `data: null` (TResult defaults to null).
125
125
  * Tools that may fail to produce data should type TResult as `SomeType | null`.
126
126
  */
127
- export interface ToolHandlerResponse<TResult = null, TToolResponse = JsonValue> {
127
+ export interface ToolHandlerResponse<
128
+ TResult = null,
129
+ TToolResponse = JsonValue,
130
+ > {
128
131
  /** Content sent back to the LLM as the tool call response */
129
132
  toolResponse: TToolResponse;
130
133
  /** Data returned to the workflow and hooks for further processing */
@@ -172,7 +175,9 @@ export type ToolHandler<
172
175
  > = (
173
176
  args: TArgs,
174
177
  context: TContext
175
- ) => ToolHandlerResponse<TResult, TToolResponse> | Promise<ToolHandlerResponse<TResult, TToolResponse>>;
178
+ ) =>
179
+ | ToolHandlerResponse<TResult, TToolResponse>
180
+ | Promise<ToolHandlerResponse<TResult, TToolResponse>>;
176
181
 
177
182
  /**
178
183
  * Activity-compatible tool handler that always returns a Promise.
@@ -195,7 +200,10 @@ export type ActivityToolHandler<
195
200
  TResult,
196
201
  TContext extends RouterContext = RouterContext,
197
202
  TToolResponse = JsonValue,
198
- > = (args: TArgs, context: TContext) => Promise<ToolHandlerResponse<TResult, TToolResponse>>;
203
+ > = (
204
+ args: TArgs,
205
+ context: TContext
206
+ ) => Promise<ToolHandlerResponse<TResult, TToolResponse>>;
199
207
 
200
208
  /**
201
209
  * Extract the args type for a specific tool name from a tool map.
@@ -1,6 +1,10 @@
1
1
  import type { Sandbox } from "../sandbox/types";
2
2
  import type { JsonValue } from "../state/types";
3
- import type { ActivityToolHandler, RouterContext, ToolHandlerResponse } from "./types";
3
+ import type {
4
+ ActivityToolHandler,
5
+ RouterContext,
6
+ ToolHandlerResponse,
7
+ } from "./types";
4
8
 
5
9
  /**
6
10
  * Extended router context with a resolved {@link Sandbox} instance.
@@ -51,13 +55,23 @@ export interface SandboxContext extends RouterContext {
51
55
  * });
52
56
  * ```
53
57
  */
54
- export function withSandbox<TArgs, TResult, TSandbox extends Sandbox = Sandbox, TToolResponse = JsonValue>(
58
+ export function withSandbox<
59
+ TArgs,
60
+ TResult,
61
+ TSandbox extends Sandbox = Sandbox,
62
+ TToolResponse = JsonValue,
63
+ >(
55
64
  manager: { getSandbox(id: string): Promise<TSandbox> },
56
65
  handler: (
57
66
  args: TArgs,
58
- context: RouterContext & { sandbox: TSandbox; sandboxId: string },
59
- ) => Promise<ToolHandlerResponse<TResult, TToolResponse>>,
60
- ): ActivityToolHandler<TArgs, TResult | null, RouterContext, TToolResponse | string> {
67
+ context: RouterContext & { sandbox: TSandbox; sandboxId: string }
68
+ ) => Promise<ToolHandlerResponse<TResult, TToolResponse>>
69
+ ): ActivityToolHandler<
70
+ TArgs,
71
+ TResult | null,
72
+ RouterContext,
73
+ TToolResponse | string
74
+ > {
61
75
  return async (args, context) => {
62
76
  if (!context.sandboxId) {
63
77
  return {
@@ -67,7 +67,7 @@ export class VirtualFileSystem<
67
67
  private resolver: FileResolver<TCtx, TMeta>,
68
68
  private ctx: TCtx,
69
69
  workspaceBase = "/",
70
- inlineFiles?: Record<string, string>,
70
+ inlineFiles?: Record<string, string>
71
71
  ) {
72
72
  this.workspaceBase = normalisePath(workspaceBase);
73
73
  this.entries = new Map(
@@ -1,7 +1,11 @@
1
1
  export { VirtualFileSystem } from "./filesystem";
2
2
  export { withVirtualFs } from "./with-virtual-fs";
3
3
  export { createVirtualFsActivities } from "./manager";
4
- export { hasFileWithMimeType, filesWithMimeType, hasDirectory } from "./queries";
4
+ export {
5
+ hasFileWithMimeType,
6
+ filesWithMimeType,
7
+ hasDirectory,
8
+ } from "./queries";
5
9
  export { applyVirtualTreeMutations } from "./mutations";
6
10
  export { formatVirtualFileTree } from "./tree";
7
11
  export type { FileTreeAccessor } from "./queries";
@@ -13,7 +13,7 @@ export function applyVirtualTreeMutations<TMeta = FileEntryMetadata>(
13
13
  get(key: "fileTree"): VirtualFileTree<TMeta>;
14
14
  set(key: "fileTree", value: VirtualFileTree<TMeta>): void;
15
15
  },
16
- mutations: TreeMutation<TMeta>[],
16
+ mutations: TreeMutation<TMeta>[]
17
17
  ): VirtualFileTree<TMeta> {
18
18
  let tree = [...stateManager.get("fileTree")];
19
19
 
@@ -26,9 +26,7 @@ export function applyVirtualTreeMutations<TMeta = FileEntryMetadata>(
26
26
  tree = tree.filter((e) => e.path !== m.path);
27
27
  break;
28
28
  case "update":
29
- tree = tree.map((e) =>
30
- e.path === m.path ? { ...e, ...m.entry } : e
31
- );
29
+ tree = tree.map((e) => (e.path === m.path ? { ...e, ...m.entry } : e));
32
30
  break;
33
31
  }
34
32
  }
@@ -25,10 +25,12 @@ export interface FileTreeAccessor<TMeta> {
25
25
  */
26
26
  export function hasFileWithMimeType<TMeta>(
27
27
  stateManager: FileTreeAccessor<TMeta>,
28
- pattern: string | string[],
28
+ pattern: string | string[]
29
29
  ): boolean {
30
30
  const tree = stateManager.get("fileTree");
31
- const matchers = (Array.isArray(pattern) ? pattern : [pattern]).map(buildMatcher);
31
+ const matchers = (Array.isArray(pattern) ? pattern : [pattern]).map(
32
+ buildMatcher
33
+ );
32
34
  return tree.some((entry) => {
33
35
  const meta = entry.metadata as Record<string, unknown> | undefined;
34
36
  const mime = meta?.mimeType;
@@ -41,7 +43,7 @@ export function hasFileWithMimeType<TMeta>(
41
43
  */
42
44
  export function filesWithMimeType<TMeta>(
43
45
  stateManager: FileTreeAccessor<TMeta>,
44
- pattern: string,
46
+ pattern: string
45
47
  ): FileEntry<TMeta>[] {
46
48
  const tree = stateManager.get("fileTree");
47
49
  const match = buildMatcher(pattern);
@@ -66,7 +68,7 @@ export function filesWithMimeType<TMeta>(
66
68
  */
67
69
  export function hasDirectory<TMeta>(
68
70
  stateManager: FileTreeAccessor<TMeta>,
69
- pattern: string,
71
+ pattern: string
70
72
  ): boolean {
71
73
  const tree = stateManager.get("fileTree");
72
74
  const match = buildGlobMatcher(pattern);
@@ -91,7 +93,9 @@ function buildMatcher(pattern: string): (value: string) => boolean {
91
93
  function buildGlobMatcher(pattern: string): (value: string) => boolean {
92
94
  if (!pattern.includes("*")) return (v) => v === pattern;
93
95
  const re = new RegExp(
94
- "^" + pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") + "$",
96
+ "^" +
97
+ pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*") +
98
+ "$"
95
99
  );
96
100
  return (v) => re.test(v);
97
101
  }
@@ -104,7 +104,10 @@ export type PrefixedVirtualFsOps<
104
104
  [K in keyof VirtualFsOps<
105
105
  TCtx,
106
106
  TMeta
107
- > as `virtualFs${Capitalize<TPrefix>}${Capitalize<K & string>}`]: VirtualFsOps<TCtx, TMeta>[K];
107
+ > as `virtualFs${Capitalize<TPrefix>}${Capitalize<K & string>}`]: VirtualFsOps<
108
+ TCtx,
109
+ TMeta
110
+ >[K];
108
111
  };
109
112
 
110
113
  // ============================================================================
@@ -53,7 +53,7 @@ function createMockResolver(): {
53
53
  id,
54
54
  typeof content === "string"
55
55
  ? content
56
- : new TextDecoder().decode(content),
56
+ : new TextDecoder().decode(content)
57
57
  );
58
58
  },
59
59
 
@@ -63,7 +63,7 @@ function createMockResolver(): {
63
63
  id,
64
64
  typeof content === "string"
65
65
  ? content
66
- : new TextDecoder().decode(content),
66
+ : new TextDecoder().decode(content)
67
67
  );
68
68
  const size =
69
69
  typeof content === "string"
@@ -286,9 +286,7 @@ describe("VirtualFileSystem", () => {
286
286
  });
287
287
 
288
288
  it("rm force does not throw for missing path", async () => {
289
- await expect(
290
- fs.rm("/nonexistent", { force: true }),
291
- ).resolves.not.toThrow();
289
+ await expect(fs.rm("/nonexistent", { force: true })).resolves.not.toThrow();
292
290
  });
293
291
 
294
292
  // --- cp / mv ---
@@ -320,7 +318,7 @@ describe("VirtualFileSystem", () => {
320
318
 
321
319
  it("readlink throws SandboxNotSupportedError", async () => {
322
320
  await expect(fs.readlink("/src/index.ts")).rejects.toThrow(
323
- SandboxNotSupportedError,
321
+ SandboxNotSupportedError
324
322
  );
325
323
  });
326
324
  });
@@ -349,7 +347,7 @@ describe("VirtualFileSystem — inlineFiles", () => {
349
347
  resolver,
350
348
  ctx,
351
349
  "/",
352
- inlineFiles,
350
+ inlineFiles
353
351
  );
354
352
  }
355
353
 
@@ -418,7 +416,9 @@ describe("applyVirtualTreeMutations", () => {
418
416
  let fileTree = tree;
419
417
  return {
420
418
  get: (_key: "fileTree"): FileEntry[] => fileTree,
421
- set: (_key: "fileTree", value: FileEntry[]): void => { fileTree = value; },
419
+ set: (_key: "fileTree", value: FileEntry[]): void => {
420
+ fileTree = value;
421
+ },
422
422
  current: (): FileEntry[] => fileTree,
423
423
  };
424
424
  }
@@ -490,9 +490,7 @@ describe("applyVirtualTreeMutations", () => {
490
490
  it("does not mutate the original array passed to the state manager", () => {
491
491
  const original = [...sampleTree];
492
492
  const sm = mockStateManager(sampleTree);
493
- applyVirtualTreeMutations(sm, [
494
- { type: "remove", path: "/src/index.ts" },
495
- ]);
493
+ applyVirtualTreeMutations(sm, [{ type: "remove", path: "/src/index.ts" }]);
496
494
  expect(sampleTree).toEqual(original);
497
495
  });
498
496
  });
@@ -50,10 +50,13 @@ describe("defineWorkflow", () => {
50
50
  return { ok: true };
51
51
  });
52
52
 
53
- await workflow({}, {
54
- thread: { mode: "fork", threadId: "prev-1" },
55
- sandbox: { mode: "continue", sandboxId: "sb-1" },
56
- });
53
+ await workflow(
54
+ {},
55
+ {
56
+ thread: { mode: "fork", threadId: "prev-1" },
57
+ sandbox: { mode: "continue", sandboxId: "sb-1" },
58
+ }
59
+ );
57
60
 
58
61
  expect(capturedSession).toEqual({
59
62
  agentName: "test-workflow",
@@ -1,8 +1,4 @@
1
- import type {
2
- ThreadInit,
3
- SandboxInit,
4
- SandboxShutdown,
5
- } from "./lifecycle";
1
+ import type { ThreadInit, SandboxInit, SandboxShutdown } from "./lifecycle";
6
2
 
7
3
  /**
8
4
  * Session config fields derived from a main workflow input, ready to spread
@@ -42,6 +42,4 @@ Usage notes:
42
42
  strict: true,
43
43
  } satisfies ToolDefinition;
44
44
 
45
- export type AskUserQuestionArgs = z.infer<
46
- typeof askUserQuestionTool.schema
47
- >;
45
+ export type AskUserQuestionArgs = z.infer<typeof askUserQuestionTool.schema>;
@@ -19,10 +19,7 @@ function matchGlob(pattern: string, path: string): boolean {
19
19
  return new RegExp(`^${regex}$`).test(path);
20
20
  }
21
21
 
22
- async function walk(
23
- fs: Sandbox["fs"],
24
- dir: string,
25
- ): Promise<string[]> {
22
+ async function walk(fs: Sandbox["fs"], dir: string): Promise<string[]> {
26
23
  const results: string[] = [];
27
24
  const entries = await fs.readdirWithFileTypes(dir);
28
25
  for (const entry of entries) {
@@ -1,7 +1,4 @@
1
- import type {
2
- AgentStateManager,
3
- JsonSerializable,
4
- } from "../../lib/state";
1
+ import type { AgentStateManager, JsonSerializable } from "../../lib/state";
5
2
  import type { ToolHandler } from "../../lib/tool-router";
6
3
  import type { WorkflowTask } from "../../lib/types";
7
4
  import type { TaskGetArgs } from "./tool";
@@ -20,7 +17,9 @@ export function createTaskGetHandler<TCustom extends JsonSerializable<TCustom>>(
20
17
 
21
18
  if (!task) {
22
19
  return {
23
- toolResponse: JSON.stringify({ error: `Task not found: ${args.taskId}` }),
20
+ toolResponse: JSON.stringify({
21
+ error: `Task not found: ${args.taskId}`,
22
+ }),
24
23
  data: null,
25
24
  };
26
25
  }
@@ -1,7 +1,4 @@
1
- import type {
2
- AgentStateManager,
3
- JsonSerializable,
4
- } from "../../lib/state";
1
+ import type { AgentStateManager, JsonSerializable } from "../../lib/state";
5
2
  import type { ToolHandler } from "../../lib/tool-router";
6
3
  import type { WorkflowTask } from "../../lib/types";
7
4
  import type { TaskListArgs } from "./tool";