zeitlich 0.2.21 → 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 (129) hide show
  1. package/README.md +303 -105
  2. package/dist/adapters/sandbox/daytona/index.cjs +7 -1
  3. package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
  4. package/dist/adapters/sandbox/daytona/index.d.cts +3 -1
  5. package/dist/adapters/sandbox/daytona/index.d.ts +3 -1
  6. package/dist/adapters/sandbox/daytona/index.js +7 -1
  7. package/dist/adapters/sandbox/daytona/index.js.map +1 -1
  8. package/dist/adapters/sandbox/daytona/workflow.cjs +33 -0
  9. package/dist/adapters/sandbox/daytona/workflow.cjs.map +1 -0
  10. package/dist/adapters/sandbox/daytona/workflow.d.cts +27 -0
  11. package/dist/adapters/sandbox/daytona/workflow.d.ts +27 -0
  12. package/dist/adapters/sandbox/daytona/workflow.js +31 -0
  13. package/dist/adapters/sandbox/daytona/workflow.js.map +1 -0
  14. package/dist/adapters/sandbox/inmemory/index.cjs +18 -1
  15. package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
  16. package/dist/adapters/sandbox/inmemory/index.d.cts +4 -2
  17. package/dist/adapters/sandbox/inmemory/index.d.ts +4 -2
  18. package/dist/adapters/sandbox/inmemory/index.js +18 -1
  19. package/dist/adapters/sandbox/inmemory/index.js.map +1 -1
  20. package/dist/adapters/sandbox/inmemory/workflow.cjs +33 -0
  21. package/dist/adapters/sandbox/inmemory/workflow.cjs.map +1 -0
  22. package/dist/adapters/sandbox/inmemory/workflow.d.cts +25 -0
  23. package/dist/adapters/sandbox/inmemory/workflow.d.ts +25 -0
  24. package/dist/adapters/sandbox/inmemory/workflow.js +31 -0
  25. package/dist/adapters/sandbox/inmemory/workflow.js.map +1 -0
  26. package/dist/adapters/sandbox/virtual/index.cjs +36 -9
  27. package/dist/adapters/sandbox/virtual/index.cjs.map +1 -1
  28. package/dist/adapters/sandbox/virtual/index.d.cts +8 -5
  29. package/dist/adapters/sandbox/virtual/index.d.ts +8 -5
  30. package/dist/adapters/sandbox/virtual/index.js +36 -9
  31. package/dist/adapters/sandbox/virtual/index.js.map +1 -1
  32. package/dist/adapters/sandbox/virtual/workflow.cjs +33 -0
  33. package/dist/adapters/sandbox/virtual/workflow.cjs.map +1 -0
  34. package/dist/adapters/sandbox/virtual/workflow.d.cts +27 -0
  35. package/dist/adapters/sandbox/virtual/workflow.d.ts +27 -0
  36. package/dist/adapters/sandbox/virtual/workflow.js +31 -0
  37. package/dist/adapters/sandbox/virtual/workflow.js.map +1 -0
  38. package/dist/adapters/thread/google-genai/index.cjs +9 -1
  39. package/dist/adapters/thread/google-genai/index.cjs.map +1 -1
  40. package/dist/adapters/thread/google-genai/index.d.cts +31 -19
  41. package/dist/adapters/thread/google-genai/index.d.ts +31 -19
  42. package/dist/adapters/thread/google-genai/index.js +9 -1
  43. package/dist/adapters/thread/google-genai/index.js.map +1 -1
  44. package/dist/adapters/thread/google-genai/workflow.cjs +33 -0
  45. package/dist/adapters/thread/google-genai/workflow.cjs.map +1 -0
  46. package/dist/adapters/thread/google-genai/workflow.d.cts +32 -0
  47. package/dist/adapters/thread/google-genai/workflow.d.ts +32 -0
  48. package/dist/adapters/thread/google-genai/workflow.js +31 -0
  49. package/dist/adapters/thread/google-genai/workflow.js.map +1 -0
  50. package/dist/adapters/thread/langchain/index.cjs +9 -1
  51. package/dist/adapters/thread/langchain/index.cjs.map +1 -1
  52. package/dist/adapters/thread/langchain/index.d.cts +27 -16
  53. package/dist/adapters/thread/langchain/index.d.ts +27 -16
  54. package/dist/adapters/thread/langchain/index.js +9 -1
  55. package/dist/adapters/thread/langchain/index.js.map +1 -1
  56. package/dist/adapters/thread/langchain/workflow.cjs +33 -0
  57. package/dist/adapters/thread/langchain/workflow.cjs.map +1 -0
  58. package/dist/adapters/thread/langchain/workflow.d.cts +32 -0
  59. package/dist/adapters/thread/langchain/workflow.d.ts +32 -0
  60. package/dist/adapters/thread/langchain/workflow.js +31 -0
  61. package/dist/adapters/thread/langchain/workflow.js.map +1 -0
  62. package/dist/index.cjs +282 -90
  63. package/dist/index.cjs.map +1 -1
  64. package/dist/index.d.cts +38 -16
  65. package/dist/index.d.ts +38 -16
  66. package/dist/index.js +281 -87
  67. package/dist/index.js.map +1 -1
  68. package/dist/queries-DModcWRy.d.cts +44 -0
  69. package/dist/queries-byD0jr1Y.d.ts +44 -0
  70. package/dist/{types-BkAYmc96.d.ts → types-B50pBPEV.d.ts} +190 -38
  71. package/dist/{types-YbL7JpEA.d.cts → types-Bll19FZJ.d.cts} +7 -0
  72. package/dist/{types-YbL7JpEA.d.ts → types-Bll19FZJ.d.ts} +7 -0
  73. package/dist/{queries-6Avfh74U.d.ts → types-BuXdFhaZ.d.cts} +7 -48
  74. package/dist/{types-BMRzfELQ.d.cts → types-ChAMwU3q.d.cts} +17 -1
  75. package/dist/{types-BMRzfELQ.d.ts → types-ChAMwU3q.d.ts} +17 -1
  76. package/dist/{types-CES_30qx.d.cts → types-DQW8l7pY.d.cts} +190 -38
  77. package/dist/{queries-CHa2iv_I.d.cts → types-GZ76HZSj.d.ts} +7 -48
  78. package/dist/workflow.cjs +244 -86
  79. package/dist/workflow.cjs.map +1 -1
  80. package/dist/workflow.d.cts +54 -65
  81. package/dist/workflow.d.ts +54 -65
  82. package/dist/workflow.js +243 -83
  83. package/dist/workflow.js.map +1 -1
  84. package/package.json +54 -2
  85. package/src/adapters/sandbox/daytona/filesystem.ts +1 -1
  86. package/src/adapters/sandbox/daytona/index.ts +8 -0
  87. package/src/adapters/sandbox/daytona/proxy.ts +56 -0
  88. package/src/adapters/sandbox/e2b/filesystem.ts +147 -0
  89. package/src/adapters/sandbox/e2b/index.ts +164 -0
  90. package/src/adapters/sandbox/e2b/types.ts +23 -0
  91. package/src/adapters/sandbox/inmemory/index.ts +27 -3
  92. package/src/adapters/sandbox/inmemory/proxy.ts +53 -0
  93. package/src/adapters/sandbox/virtual/filesystem.ts +41 -17
  94. package/src/adapters/sandbox/virtual/provider.ts +9 -1
  95. package/src/adapters/sandbox/virtual/proxy.ts +53 -0
  96. package/src/adapters/sandbox/virtual/types.ts +9 -4
  97. package/src/adapters/thread/google-genai/activities.ts +51 -17
  98. package/src/adapters/thread/google-genai/index.ts +1 -0
  99. package/src/adapters/thread/google-genai/proxy.ts +61 -0
  100. package/src/adapters/thread/langchain/activities.ts +47 -14
  101. package/src/adapters/thread/langchain/index.ts +1 -0
  102. package/src/adapters/thread/langchain/proxy.ts +61 -0
  103. package/src/lib/lifecycle.ts +57 -0
  104. package/src/lib/sandbox/manager.ts +52 -6
  105. package/src/lib/sandbox/sandbox.test.ts +12 -11
  106. package/src/lib/sandbox/types.ts +31 -4
  107. package/src/lib/session/index.ts +4 -5
  108. package/src/lib/session/session-edge-cases.integration.test.ts +491 -66
  109. package/src/lib/session/session.integration.test.ts +92 -80
  110. package/src/lib/session/session.ts +108 -96
  111. package/src/lib/session/types.ts +87 -17
  112. package/src/lib/subagent/define.ts +6 -5
  113. package/src/lib/subagent/handler.ts +148 -16
  114. package/src/lib/subagent/index.ts +4 -0
  115. package/src/lib/subagent/register.ts +10 -3
  116. package/src/lib/subagent/signals.ts +8 -0
  117. package/src/lib/subagent/subagent.integration.test.ts +893 -128
  118. package/src/lib/subagent/tool.ts +2 -2
  119. package/src/lib/subagent/types.ts +84 -21
  120. package/src/lib/subagent/workflow.ts +83 -12
  121. package/src/lib/tool-router/router-edge-cases.integration.test.ts +4 -1
  122. package/src/lib/tool-router/router.integration.test.ts +141 -5
  123. package/src/lib/tool-router/router.ts +13 -3
  124. package/src/lib/tool-router/types.ts +7 -0
  125. package/src/lib/workflow.test.ts +104 -27
  126. package/src/lib/workflow.ts +37 -19
  127. package/src/tools/bash/bash.test.ts +16 -7
  128. package/src/workflow.ts +11 -14
  129. package/tsup.config.ts +6 -0
@@ -0,0 +1,57 @@
1
+ // ============================================================================
2
+ // Thread lifecycle
3
+ // ============================================================================
4
+
5
+ /**
6
+ * Thread initialization strategy.
7
+ *
8
+ * - `"new"` — start a fresh thread (optionally specify its ID).
9
+ * - `"continue"` — append directly to an existing thread in-place.
10
+ * - `"fork"` — copy all messages from an existing thread into a new one and
11
+ * continue there.
12
+ */
13
+ export type ThreadInit =
14
+ | { mode: "new"; threadId?: string }
15
+ | { mode: "continue"; threadId: string }
16
+ | { mode: "fork"; threadId: string };
17
+
18
+ // ============================================================================
19
+ // Sandbox lifecycle
20
+ // ============================================================================
21
+
22
+ /**
23
+ * Sandbox initialization strategy.
24
+ *
25
+ * - `"new"` — create a fresh sandbox.
26
+ * - `"continue"` — resume a previously-paused sandbox (this session takes
27
+ * ownership and the shutdown policy applies on exit).
28
+ * - `"fork"` — fork from an existing (or paused) sandbox; a new sandbox is
29
+ * created and owned by this session.
30
+ * - `"inherit"` — use a sandbox owned by someone else (e.g. a parent agent).
31
+ * The session will **not** manage its lifecycle on exit.
32
+ */
33
+ export type SandboxInit =
34
+ | { mode: "new" }
35
+ | { mode: "continue"; sandboxId: string }
36
+ | { mode: "fork"; sandboxId: string }
37
+ | { mode: "inherit"; sandboxId: string };
38
+
39
+ /**
40
+ * What to do with the sandbox when the session exits.
41
+ *
42
+ * - `"destroy"` — tear down the sandbox entirely.
43
+ * - `"pause"` — pause the sandbox so it can be resumed later.
44
+ * - `"keep"` — leave the sandbox running (no-op on exit).
45
+ */
46
+ export type SandboxShutdown = "destroy" | "pause" | "keep";
47
+
48
+ /**
49
+ * Extended shutdown options available to subagent workflows.
50
+ *
51
+ * Includes all base {@link SandboxShutdown} values plus:
52
+ * - `"pause-until-parent-close"` — pause the sandbox on exit, then wait for
53
+ * the parent workflow to signal when to destroy it.
54
+ */
55
+ export type SubagentSandboxShutdown =
56
+ | SandboxShutdown
57
+ | "pause-until-parent-close";
@@ -2,6 +2,7 @@ import type {
2
2
  Sandbox,
3
3
  SandboxCreateOptions,
4
4
  SandboxOps,
5
+ PrefixedSandboxOps,
5
6
  SandboxProvider,
6
7
  SandboxSnapshot,
7
8
  } from "./types";
@@ -16,16 +17,20 @@ import type {
16
17
  * ```typescript
17
18
  * const manager = new SandboxManager(new InMemorySandboxProvider());
18
19
  * const activities = {
19
- * ...manager.createActivities(),
20
+ * ...manager.createActivities("CodingAgent"),
20
21
  * bashHandler: withSandbox(manager, bashHandler),
21
22
  * };
23
+ * // registers: inMemoryCodingAgentCreateSandbox, …
22
24
  * ```
23
25
  */
24
26
  export class SandboxManager<
25
27
  TOptions extends SandboxCreateOptions = SandboxCreateOptions,
26
28
  TSandbox extends Sandbox = Sandbox,
29
+ TId extends string = string,
27
30
  > {
28
- constructor(private provider: SandboxProvider<TOptions, TSandbox>) {}
31
+ constructor(
32
+ private provider: SandboxProvider<TOptions, TSandbox> & { readonly id: TId }
33
+ ) {}
29
34
 
30
35
  async create(
31
36
  options?: TOptions
@@ -42,6 +47,10 @@ export class SandboxManager<
42
47
  await this.provider.destroy(id);
43
48
  }
44
49
 
50
+ async pause(id: string, ttlSeconds?: number): Promise<void> {
51
+ await this.provider.pause(id, ttlSeconds);
52
+ }
53
+
45
54
  async snapshot(id: string): Promise<SandboxSnapshot> {
46
55
  return this.provider.snapshot(id);
47
56
  }
@@ -51,12 +60,36 @@ export class SandboxManager<
51
60
  return sandbox.id;
52
61
  }
53
62
 
63
+ async fork(sandboxId: string): Promise<string> {
64
+ const sandbox = await this.provider.fork(sandboxId);
65
+ return sandbox.id;
66
+ }
67
+
54
68
  /**
55
- * Returns Temporal activity functions matching {@link SandboxOps}.
56
- * Spread these into your worker's activity map.
69
+ * Returns Temporal activity functions with prefixed names.
70
+ *
71
+ * The provider's `id` is automatically prepended, so you only need
72
+ * to pass the workflow/scope name. Use the matching `proxy*SandboxOps()`
73
+ * helper from the adapter's `/workflow` entrypoint on the workflow side.
74
+ *
75
+ * @param scope - Workflow name (appended to the provider id)
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * const manager = new SandboxManager(new InMemorySandboxProvider());
80
+ * manager.createActivities("CodingAgent");
81
+ * // registers: inMemoryCodingAgentCreateSandbox, inMemoryCodingAgentDestroySandbox, …
82
+ *
83
+ * const vmgr = new SandboxManager(new VirtualSandboxProvider(resolver));
84
+ * vmgr.createActivities("CodingAgent");
85
+ * // registers: virtualCodingAgentCreateSandbox, …
86
+ * ```
57
87
  */
58
- createActivities(): SandboxOps<TOptions> {
59
- return {
88
+ createActivities<S extends string>(
89
+ scope: S
90
+ ): PrefixedSandboxOps<`${TId}${Capitalize<S>}`, TOptions> {
91
+ const prefix = `${this.provider.id}${scope.charAt(0).toUpperCase()}${scope.slice(1)}`;
92
+ const ops: SandboxOps<TOptions> = {
60
93
  createSandbox: async (
61
94
  options?: TOptions
62
95
  ): Promise<{
@@ -68,9 +101,22 @@ export class SandboxManager<
68
101
  destroySandbox: async (sandboxId: string): Promise<void> => {
69
102
  await this.destroy(sandboxId);
70
103
  },
104
+ pauseSandbox: async (
105
+ sandboxId: string,
106
+ ttlSeconds?: number
107
+ ): Promise<void> => {
108
+ await this.pause(sandboxId, ttlSeconds);
109
+ },
71
110
  snapshotSandbox: async (sandboxId: string): Promise<SandboxSnapshot> => {
72
111
  return this.snapshot(sandboxId);
73
112
  },
113
+ forkSandbox: async (sandboxId: string): Promise<string> => {
114
+ return this.fork(sandboxId);
115
+ },
74
116
  };
117
+ const cap = (s: string): string => s.charAt(0).toUpperCase() + s.slice(1);
118
+ return Object.fromEntries(
119
+ Object.entries(ops).map(([k, v]) => [`${prefix}${cap(k)}`, v])
120
+ ) as PrefixedSandboxOps<`${TId}${Capitalize<S>}`, TOptions>;
75
121
  }
76
122
  }
@@ -1,10 +1,10 @@
1
1
  import { describe, expect, it, beforeEach } from "vitest";
2
2
  import { SandboxManager } from "./manager";
3
3
  import { InMemorySandboxProvider } from "../../adapters/sandbox/inmemory/index";
4
- import { SandboxNotFoundError } from "./types";
4
+ import { SandboxNotFoundError, type Sandbox, type SandboxCreateOptions } from "./types";
5
5
 
6
6
  describe("SandboxManager", () => {
7
- let manager: SandboxManager;
7
+ let manager: SandboxManager<SandboxCreateOptions, Sandbox, "inMemory">;
8
8
 
9
9
  beforeEach(() => {
10
10
  manager = new SandboxManager(new InMemorySandboxProvider());
@@ -54,7 +54,7 @@ describe("SandboxManager", () => {
54
54
 
55
55
  const snapshot = await manager.snapshot(sandboxId);
56
56
  expect(snapshot.sandboxId).toBe(sandboxId);
57
- expect(snapshot.providerId).toBe("inmemory");
57
+ expect(snapshot.providerId).toBe("inMemory");
58
58
 
59
59
  await manager.destroy(sandboxId);
60
60
  await expect(manager.getSandbox(sandboxId)).rejects.toThrow(SandboxNotFoundError);
@@ -68,16 +68,17 @@ describe("SandboxManager", () => {
68
68
  expect(extra).toBe("world");
69
69
  });
70
70
 
71
- it("createActivities returns SandboxOps-shaped object", async () => {
72
- const activities = manager.createActivities();
73
- expect(activities.createSandbox).toBeTypeOf("function");
74
- expect(activities.destroySandbox).toBeTypeOf("function");
75
- expect(activities.snapshotSandbox).toBeTypeOf("function");
71
+ it("createActivities returns prefixed SandboxOps-shaped object", async () => {
72
+ // provider.id is "inMemory", scope is "Test" → prefix "inMemoryTest"
73
+ const activities = manager.createActivities("Test");
74
+ expect(activities.inMemoryTestCreateSandbox).toBeTypeOf("function");
75
+ expect(activities.inMemoryTestDestroySandbox).toBeTypeOf("function");
76
+ expect(activities.inMemoryTestSnapshotSandbox).toBeTypeOf("function");
76
77
 
77
- const { sandboxId } = await activities.createSandbox();
78
+ const { sandboxId } = await activities.inMemoryTestCreateSandbox();
78
79
  await expect(manager.getSandbox(sandboxId)).resolves.toBeTruthy();
79
80
 
80
- await activities.destroySandbox(sandboxId);
81
+ await activities.inMemoryTestDestroySandbox(sandboxId);
81
82
  await expect(manager.getSandbox(sandboxId)).rejects.toThrow(
82
83
  SandboxNotFoundError,
83
84
  );
@@ -85,7 +86,7 @@ describe("SandboxManager", () => {
85
86
  });
86
87
 
87
88
  describe("InMemorySandboxProvider", () => {
88
- let manager: SandboxManager;
89
+ let manager: SandboxManager<SandboxCreateOptions, Sandbox, "inMemory">;
89
90
 
90
91
  beforeEach(() => {
91
92
  manager = new SandboxManager(new InMemorySandboxProvider());
@@ -35,8 +35,15 @@ export interface SandboxFileSystem {
35
35
  mkdir(path: string, options?: { recursive?: boolean }): Promise<void>;
36
36
  readdir(path: string): Promise<string[]>;
37
37
  readdirWithFileTypes(path: string): Promise<DirentEntry[]>;
38
- rm(path: string, options?: { recursive?: boolean; force?: boolean }): Promise<void>;
39
- cp(src: string, dest: string, options?: { recursive?: boolean }): Promise<void>;
38
+ rm(
39
+ path: string,
40
+ options?: { recursive?: boolean; force?: boolean }
41
+ ): Promise<void>;
42
+ cp(
43
+ src: string,
44
+ dest: string,
45
+ options?: { recursive?: boolean }
46
+ ): Promise<void>;
40
47
  mv(src: string, dest: string): Promise<void>;
41
48
  readlink(path: string): Promise<string>;
42
49
  resolvePath(base: string, path: string): string;
@@ -125,8 +132,10 @@ export interface SandboxProvider<
125
132
  create(options?: TOptions): Promise<SandboxCreateResult>;
126
133
  get(sandboxId: string): Promise<TSandbox>;
127
134
  destroy(sandboxId: string): Promise<void>;
135
+ pause(sandboxId: string, ttlSeconds?: number): Promise<void>;
128
136
  snapshot(sandboxId: string): Promise<SandboxSnapshot>;
129
137
  restore(snapshot: SandboxSnapshot): Promise<Sandbox>;
138
+ fork(sandboxId: string): Promise<Sandbox>;
130
139
  }
131
140
 
132
141
  // ============================================================================
@@ -137,12 +146,30 @@ export interface SandboxOps<
137
146
  TOptions extends SandboxCreateOptions = SandboxCreateOptions,
138
147
  > {
139
148
  createSandbox(
140
- options?: TOptions,
149
+ options?: TOptions
141
150
  ): Promise<{ sandboxId: string; stateUpdate?: Record<string, unknown> }>;
142
151
  destroySandbox(sandboxId: string): Promise<void>;
152
+ pauseSandbox(sandboxId: string): Promise<void>;
143
153
  snapshotSandbox(sandboxId: string): Promise<SandboxSnapshot>;
154
+ forkSandbox(sandboxId: string): Promise<string>;
144
155
  }
145
156
 
157
+ /**
158
+ * Maps generic {@link SandboxOps} method names to adapter-prefixed names.
159
+ *
160
+ * @example
161
+ * ```typescript
162
+ * type InMemOps = PrefixedSandboxOps<"inMemory">;
163
+ * // → { inMemoryCreateSandbox, inMemoryDestroySandbox, inMemorySnapshotSandbox }
164
+ * ```
165
+ */
166
+ export type PrefixedSandboxOps<
167
+ TPrefix extends string,
168
+ TOptions extends SandboxCreateOptions = SandboxCreateOptions,
169
+ > = {
170
+ [K in keyof SandboxOps<TOptions> as `${TPrefix}${Capitalize<K & string>}`]: SandboxOps<TOptions>[K];
171
+ };
172
+
146
173
  // ============================================================================
147
174
  // Errors
148
175
  // ============================================================================
@@ -154,7 +181,7 @@ export class SandboxNotSupportedError extends ApplicationFailure {
154
181
  super(
155
182
  `Sandbox does not support: ${operation}`,
156
183
  "SandboxNotSupportedError",
157
- true,
184
+ true
158
185
  );
159
186
  }
160
187
  }
@@ -1,11 +1,10 @@
1
- export {
2
- createSession,
3
- proxyDefaultThreadOps,
4
- proxySandboxOps,
5
- } from "./session";
1
+ export { createSession } from "./session";
6
2
 
7
3
  export type {
8
4
  ThreadOps,
5
+ PrefixedThreadOps,
6
+ ScopedPrefix,
9
7
  SessionConfig,
8
+ SessionResult,
10
9
  ZeitlichSession,
11
10
  } from "./types";