zeitlich 0.2.22 → 0.2.23

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 (101) hide show
  1. package/README.md +242 -59
  2. package/dist/adapters/sandbox/daytona/index.cjs +4 -1
  3. package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
  4. package/dist/adapters/sandbox/daytona/index.d.cts +2 -1
  5. package/dist/adapters/sandbox/daytona/index.d.ts +2 -1
  6. package/dist/adapters/sandbox/daytona/index.js +4 -1
  7. package/dist/adapters/sandbox/daytona/index.js.map +1 -1
  8. package/dist/adapters/sandbox/daytona/workflow.cjs +1 -0
  9. package/dist/adapters/sandbox/daytona/workflow.cjs.map +1 -1
  10. package/dist/adapters/sandbox/daytona/workflow.d.cts +1 -1
  11. package/dist/adapters/sandbox/daytona/workflow.d.ts +1 -1
  12. package/dist/adapters/sandbox/daytona/workflow.js +1 -0
  13. package/dist/adapters/sandbox/daytona/workflow.js.map +1 -1
  14. package/dist/adapters/sandbox/inmemory/index.cjs +16 -2
  15. package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
  16. package/dist/adapters/sandbox/inmemory/index.d.cts +3 -2
  17. package/dist/adapters/sandbox/inmemory/index.d.ts +3 -2
  18. package/dist/adapters/sandbox/inmemory/index.js +16 -2
  19. package/dist/adapters/sandbox/inmemory/index.js.map +1 -1
  20. package/dist/adapters/sandbox/inmemory/workflow.cjs +1 -0
  21. package/dist/adapters/sandbox/inmemory/workflow.cjs.map +1 -1
  22. package/dist/adapters/sandbox/inmemory/workflow.d.cts +1 -1
  23. package/dist/adapters/sandbox/inmemory/workflow.d.ts +1 -1
  24. package/dist/adapters/sandbox/inmemory/workflow.js +1 -0
  25. package/dist/adapters/sandbox/inmemory/workflow.js.map +1 -1
  26. package/dist/adapters/sandbox/virtual/index.cjs +33 -9
  27. package/dist/adapters/sandbox/virtual/index.cjs.map +1 -1
  28. package/dist/adapters/sandbox/virtual/index.d.cts +6 -5
  29. package/dist/adapters/sandbox/virtual/index.d.ts +6 -5
  30. package/dist/adapters/sandbox/virtual/index.js +33 -9
  31. package/dist/adapters/sandbox/virtual/index.js.map +1 -1
  32. package/dist/adapters/sandbox/virtual/workflow.cjs +1 -0
  33. package/dist/adapters/sandbox/virtual/workflow.cjs.map +1 -1
  34. package/dist/adapters/sandbox/virtual/workflow.d.cts +3 -3
  35. package/dist/adapters/sandbox/virtual/workflow.d.ts +3 -3
  36. package/dist/adapters/sandbox/virtual/workflow.js +1 -0
  37. package/dist/adapters/sandbox/virtual/workflow.js.map +1 -1
  38. package/dist/adapters/thread/google-genai/index.d.cts +3 -3
  39. package/dist/adapters/thread/google-genai/index.d.ts +3 -3
  40. package/dist/adapters/thread/google-genai/workflow.d.cts +3 -3
  41. package/dist/adapters/thread/google-genai/workflow.d.ts +3 -3
  42. package/dist/adapters/thread/langchain/index.d.cts +3 -3
  43. package/dist/adapters/thread/langchain/index.d.ts +3 -3
  44. package/dist/adapters/thread/langchain/workflow.d.cts +3 -3
  45. package/dist/adapters/thread/langchain/workflow.d.ts +3 -3
  46. package/dist/index.cjs +247 -57
  47. package/dist/index.cjs.map +1 -1
  48. package/dist/index.d.cts +9 -8
  49. package/dist/index.d.ts +9 -8
  50. package/dist/index.js +245 -55
  51. package/dist/index.js.map +1 -1
  52. package/dist/{queries-Bw6WEPMw.d.cts → queries-DModcWRy.d.cts} +1 -1
  53. package/dist/{queries-C27raDaB.d.ts → queries-byD0jr1Y.d.ts} +1 -1
  54. package/dist/{types-ClsHhtwL.d.cts → types-B50pBPEV.d.ts} +159 -35
  55. package/dist/{types-YbL7JpEA.d.cts → types-Bll19FZJ.d.cts} +7 -0
  56. package/dist/{types-YbL7JpEA.d.ts → types-Bll19FZJ.d.ts} +7 -0
  57. package/dist/{types-BJ8itUAl.d.cts → types-BuXdFhaZ.d.cts} +6 -6
  58. package/dist/{types-HBosetv3.d.cts → types-ChAMwU3q.d.cts} +2 -0
  59. package/dist/{types-HBosetv3.d.ts → types-ChAMwU3q.d.ts} +2 -0
  60. package/dist/{types-C5bkx6kQ.d.ts → types-DQW8l7pY.d.cts} +159 -35
  61. package/dist/{types-ENYCKFBk.d.ts → types-GZ76HZSj.d.ts} +6 -6
  62. package/dist/workflow.cjs +241 -57
  63. package/dist/workflow.cjs.map +1 -1
  64. package/dist/workflow.d.cts +49 -32
  65. package/dist/workflow.d.ts +49 -32
  66. package/dist/workflow.js +239 -55
  67. package/dist/workflow.js.map +1 -1
  68. package/package.json +2 -2
  69. package/src/adapters/sandbox/daytona/filesystem.ts +1 -1
  70. package/src/adapters/sandbox/daytona/index.ts +4 -0
  71. package/src/adapters/sandbox/daytona/proxy.ts +4 -3
  72. package/src/adapters/sandbox/e2b/index.ts +5 -0
  73. package/src/adapters/sandbox/inmemory/index.ts +24 -4
  74. package/src/adapters/sandbox/inmemory/proxy.ts +2 -2
  75. package/src/adapters/sandbox/virtual/filesystem.ts +41 -17
  76. package/src/adapters/sandbox/virtual/provider.ts +4 -0
  77. package/src/adapters/sandbox/virtual/proxy.ts +1 -0
  78. package/src/adapters/sandbox/virtual/types.ts +9 -4
  79. package/src/lib/lifecycle.ts +57 -0
  80. package/src/lib/sandbox/manager.ts +13 -1
  81. package/src/lib/sandbox/types.ts +13 -4
  82. package/src/lib/session/index.ts +1 -0
  83. package/src/lib/session/session-edge-cases.integration.test.ts +447 -33
  84. package/src/lib/session/session.integration.test.ts +52 -32
  85. package/src/lib/session/session.ts +107 -33
  86. package/src/lib/session/types.ts +55 -16
  87. package/src/lib/subagent/define.ts +5 -4
  88. package/src/lib/subagent/handler.ts +139 -14
  89. package/src/lib/subagent/index.ts +3 -0
  90. package/src/lib/subagent/register.ts +10 -3
  91. package/src/lib/subagent/signals.ts +8 -0
  92. package/src/lib/subagent/subagent.integration.test.ts +853 -150
  93. package/src/lib/subagent/tool.ts +2 -2
  94. package/src/lib/subagent/types.ts +77 -19
  95. package/src/lib/subagent/workflow.ts +83 -12
  96. package/src/lib/tool-router/router.integration.test.ts +137 -4
  97. package/src/lib/tool-router/router.ts +13 -3
  98. package/src/lib/tool-router/types.ts +7 -0
  99. package/src/lib/workflow.test.ts +89 -21
  100. package/src/lib/workflow.ts +33 -18
  101. package/src/workflow.ts +6 -1
@@ -8,7 +8,7 @@ import {
8
8
  const cfg = { name: "test-workflow" };
9
9
 
10
10
  describe("defineWorkflow", () => {
11
- it("maps previousThreadId to threadId + continueThread", async () => {
11
+ it("maps thread fork into sessionInput", async () => {
12
12
  let capturedSession: WorkflowSessionInput | undefined;
13
13
 
14
14
  const workflow = defineWorkflow(cfg, async (_input, sessionInput) => {
@@ -16,16 +16,16 @@ describe("defineWorkflow", () => {
16
16
  return { ok: true };
17
17
  });
18
18
 
19
- await workflow({}, { previousThreadId: "prev-42" });
19
+ await workflow({}, { thread: { mode: "fork", threadId: "prev-42" } });
20
20
 
21
21
  expect(capturedSession).toEqual({
22
22
  agentName: "test-workflow",
23
- threadId: "prev-42",
24
- continueThread: true,
23
+ sandboxShutdown: "destroy",
24
+ thread: { mode: "fork", threadId: "prev-42" },
25
25
  });
26
26
  });
27
27
 
28
- it("maps sandboxId", async () => {
28
+ it("maps sandbox inherit", async () => {
29
29
  let capturedSession: WorkflowSessionInput | undefined;
30
30
 
31
31
  const workflow = defineWorkflow(cfg, async (_input, sessionInput) => {
@@ -33,15 +33,16 @@ describe("defineWorkflow", () => {
33
33
  return { ok: true };
34
34
  });
35
35
 
36
- await workflow({}, { sandboxId: "sb-123" });
36
+ await workflow({}, { sandbox: { mode: "inherit", sandboxId: "sb-123" } });
37
37
 
38
38
  expect(capturedSession).toEqual({
39
39
  agentName: "test-workflow",
40
- sandboxId: "sb-123",
40
+ sandboxShutdown: "destroy",
41
+ sandbox: { mode: "inherit", sandboxId: "sb-123" },
41
42
  });
42
43
  });
43
44
 
44
- it("maps both previousThreadId and sandboxId together", async () => {
45
+ it("maps thread fork and sandbox together", async () => {
45
46
  let capturedSession: WorkflowSessionInput | undefined;
46
47
 
47
48
  const workflow = defineWorkflow(cfg, async (_input, sessionInput) => {
@@ -49,17 +50,20 @@ describe("defineWorkflow", () => {
49
50
  return { ok: true };
50
51
  });
51
52
 
52
- await workflow({}, { previousThreadId: "prev-1", sandboxId: "sb-1" });
53
+ await workflow({}, {
54
+ thread: { mode: "fork", threadId: "prev-1" },
55
+ sandbox: { mode: "continue", sandboxId: "sb-1" },
56
+ });
53
57
 
54
58
  expect(capturedSession).toEqual({
55
59
  agentName: "test-workflow",
56
- threadId: "prev-1",
57
- continueThread: true,
58
- sandboxId: "sb-1",
60
+ sandboxShutdown: "destroy",
61
+ thread: { mode: "fork", threadId: "prev-1" },
62
+ sandbox: { mode: "continue", sandboxId: "sb-1" },
59
63
  });
60
64
  });
61
65
 
62
- it("returns empty sessionInput when no previousThreadId or sandboxId", async () => {
66
+ it("defaults sandboxShutdown to destroy when no workflowInput", async () => {
63
67
  let capturedSession: WorkflowSessionInput | undefined;
64
68
 
65
69
  const workflow = defineWorkflow(cfg, async (_input, sessionInput) => {
@@ -69,7 +73,73 @@ describe("defineWorkflow", () => {
69
73
 
70
74
  await workflow({});
71
75
 
72
- expect(capturedSession).toEqual({ agentName: "test-workflow" });
76
+ expect(capturedSession).toEqual({
77
+ agentName: "test-workflow",
78
+ sandboxShutdown: "destroy",
79
+ });
80
+ });
81
+
82
+ it("maps sandbox fork from workflowInput", async () => {
83
+ let capturedSession: WorkflowSessionInput | undefined;
84
+
85
+ const workflow = defineWorkflow(cfg, async (_input, sessionInput) => {
86
+ capturedSession = sessionInput;
87
+ return { ok: true };
88
+ });
89
+
90
+ await workflow({}, { sandbox: { mode: "fork", sandboxId: "prev-sb-1" } });
91
+
92
+ expect(capturedSession).toEqual({
93
+ agentName: "test-workflow",
94
+ sandboxShutdown: "destroy",
95
+ sandbox: { mode: "fork", sandboxId: "prev-sb-1" },
96
+ });
97
+ });
98
+
99
+ it("uses sandboxShutdown from config", async () => {
100
+ let capturedSession: WorkflowSessionInput | undefined;
101
+
102
+ const workflow = defineWorkflow(
103
+ { name: "test-workflow", sandboxShutdown: "pause" },
104
+ async (_input, sessionInput) => {
105
+ capturedSession = sessionInput;
106
+ return { ok: true };
107
+ }
108
+ );
109
+
110
+ await workflow({});
111
+
112
+ expect(capturedSession).toEqual({
113
+ agentName: "test-workflow",
114
+ sandboxShutdown: "pause",
115
+ });
116
+ });
117
+
118
+ it("maps all lifecycle fields together", async () => {
119
+ let capturedSession: WorkflowSessionInput | undefined;
120
+
121
+ const workflow = defineWorkflow(
122
+ { name: "test-workflow", sandboxShutdown: "pause" },
123
+ async (_input, sessionInput) => {
124
+ capturedSession = sessionInput;
125
+ return { ok: true };
126
+ }
127
+ );
128
+
129
+ await workflow(
130
+ {},
131
+ {
132
+ thread: { mode: "fork", threadId: "prev-t" },
133
+ sandbox: { mode: "fork", sandboxId: "prev-sb-1" },
134
+ }
135
+ );
136
+
137
+ expect(capturedSession).toEqual({
138
+ agentName: "test-workflow",
139
+ sandboxShutdown: "pause",
140
+ thread: { mode: "fork", threadId: "prev-t" },
141
+ sandbox: { mode: "fork", sandboxId: "prev-sb-1" },
142
+ });
73
143
  });
74
144
 
75
145
  it("passes full input as first argument", async () => {
@@ -79,8 +149,6 @@ describe("defineWorkflow", () => {
79
149
  {
80
150
  prompt: string;
81
151
  metadata: { key: string };
82
- previousThreadId?: string;
83
- sandboxId?: string;
84
152
  },
85
153
  { ok: boolean }
86
154
  >(cfg, async (input, _sessionInput) => {
@@ -113,17 +181,17 @@ describe("defineWorkflow", () => {
113
181
  );
114
182
 
115
183
  const workflowInput: WorkflowInput = {
116
- previousThreadId: "prev",
117
- sandboxId: "sb",
184
+ thread: { mode: "fork", threadId: "prev" },
185
+ sandbox: { mode: "continue", sandboxId: "sb" },
118
186
  };
119
187
  await workflow({ prompt: "go" }, workflowInput);
120
188
 
121
189
  expect(capturedInput).toEqual({ prompt: "go" });
122
190
  expect(capturedSession).toEqual({
123
191
  agentName: "test-workflow",
124
- threadId: "prev",
125
- continueThread: true,
126
- sandboxId: "sb",
192
+ sandboxShutdown: "destroy",
193
+ thread: { mode: "fork", threadId: "prev" },
194
+ sandbox: { mode: "continue", sandboxId: "sb" },
127
195
  });
128
196
  });
129
197
 
@@ -1,3 +1,9 @@
1
+ import type {
2
+ ThreadInit,
3
+ SandboxInit,
4
+ SandboxShutdown,
5
+ } from "./lifecycle";
6
+
1
7
  /**
2
8
  * Session config fields derived from a main workflow input, ready to spread
3
9
  * into `createSession`.
@@ -5,25 +11,33 @@
5
11
  export interface WorkflowSessionInput {
6
12
  /** Agent name — spread directly into `createSession` */
7
13
  agentName: string;
8
- /** Thread ID to continue (set from `input.previousThreadId`) */
9
- threadId?: string;
10
- /** Whether to continue an existing thread (true when `previousThreadId` is present) */
11
- continueThread?: boolean;
12
- /** Optional sandbox ID forwarded to the session */
13
- sandboxId?: string;
14
+ /** Thread initialization strategy */
15
+ thread?: ThreadInit;
16
+ /** Sandbox initialization strategy */
17
+ sandbox?: SandboxInit;
18
+ /** Sandbox shutdown policy (default: "destroy") */
19
+ sandboxShutdown?: SandboxShutdown;
14
20
  }
15
21
 
16
22
  /** Raw workflow input fields that map into `WorkflowSessionInput`. */
17
23
  export interface WorkflowInput {
18
- /** When set, continue this thread instead of starting fresh */
19
- previousThreadId?: string;
20
- /** Optional sandbox ID to reuse */
21
- sandboxId?: string;
24
+ /** Thread initialization strategy (default: `{ mode: "new" }`) */
25
+ thread?: ThreadInit;
26
+ /** Sandbox initialization strategy */
27
+ sandbox?: SandboxInit;
22
28
  }
23
29
 
24
30
  export interface WorkflowConfig {
25
31
  /** Workflow name — used as the Temporal workflow function name */
26
32
  name: string;
33
+ /**
34
+ * Sandbox shutdown policy applied when the main agent session exits.
35
+ *
36
+ * - `"destroy"` (default) — destroy the sandbox on exit.
37
+ * - `"pause"` — pause the sandbox so it can be resumed later.
38
+ * - `"keep"` — leave the sandbox running (no-op on exit).
39
+ */
40
+ sandboxShutdown?: SandboxShutdown;
27
41
  }
28
42
 
29
43
  /**
@@ -33,21 +47,22 @@ export interface WorkflowConfig {
33
47
  * The wrapper:
34
48
  * - Accepts a `config` with at least a `name` (used for Temporal workflow naming)
35
49
  * - Accepts a handler `fn` receiving `(input, sessionInput)`
36
- * - Derives `threadId` + `continueThread` from `workflowInput.previousThreadId`
37
- * - Derives `sandboxId` from `workflowInput.sandboxId`
50
+ * - Derives thread / sandbox init from `workflowInput`
51
+ * - Applies the configured `sandboxShutdown` policy
38
52
  */
39
53
  export function defineWorkflow<TInput, TResult>(
40
54
  config: WorkflowConfig,
41
55
  fn: (input: TInput, sessionInput: WorkflowSessionInput) => Promise<TResult>
42
56
  ): (input: TInput, workflowInput?: WorkflowInput) => Promise<TResult> {
43
- const workflow = async (input: TInput, workflowInput: WorkflowInput = {}) => {
57
+ const workflow = async (
58
+ input: TInput,
59
+ workflowInput: WorkflowInput = {}
60
+ ): Promise<TResult> => {
44
61
  const sessionInput: WorkflowSessionInput = {
45
62
  agentName: config.name,
46
- ...(workflowInput.previousThreadId && {
47
- threadId: workflowInput.previousThreadId,
48
- continueThread: true,
49
- }),
50
- ...(workflowInput.sandboxId && { sandboxId: workflowInput.sandboxId }),
63
+ sandboxShutdown: config.sandboxShutdown ?? "destroy",
64
+ ...(workflowInput.thread && { thread: workflowInput.thread }),
65
+ ...(workflowInput.sandbox && { sandbox: workflowInput.sandbox }),
51
66
  };
52
67
  return fn(input, sessionInput);
53
68
  };
package/src/workflow.ts CHANGED
@@ -15,10 +15,13 @@
15
15
 
16
16
  // Session
17
17
  export { createSession } from "./lib/session";
18
- export type { ZeitlichSession, ThreadOps, PrefixedThreadOps, ScopedPrefix, SessionConfig } from "./lib/session";
18
+ export type { ZeitlichSession, SessionResult, ThreadOps, PrefixedThreadOps, ScopedPrefix, SessionConfig } from "./lib/session";
19
19
  export { defineWorkflow } from "./lib/workflow";
20
20
  export type { WorkflowConfig, WorkflowInput, WorkflowSessionInput } from "./lib/workflow";
21
21
 
22
+ // Lifecycle types
23
+ export type { ThreadInit, SandboxInit, SandboxShutdown, SubagentSandboxShutdown } from "./lib/lifecycle";
24
+
22
25
  // Thread utilities
23
26
  export { getShortId } from "./lib/thread/id";
24
27
 
@@ -124,8 +127,10 @@ export type {
124
127
  export type {
125
128
  SubagentConfig,
126
129
  SubagentDefinition,
130
+ SubagentFnResult,
127
131
  SubagentHooks,
128
132
  SubagentHandlerResponse,
133
+ SubagentSandboxConfig,
129
134
  SubagentWorkflow,
130
135
  SubagentWorkflowInput,
131
136
  SubagentSessionInput,