zeitlich 0.2.41 → 0.2.42
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.
- package/dist/{activities-qUflxmfS.d.cts → activities-Coafq5zr.d.cts} +2 -2
- package/dist/{activities-D_g13S3y.d.ts → activities-CrN-ghLo.d.ts} +2 -2
- package/dist/adapters/sandbox/daytona/index.cjs +4 -23
- package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
- package/dist/adapters/sandbox/daytona/index.d.cts +18 -86
- package/dist/adapters/sandbox/daytona/index.d.ts +18 -86
- package/dist/adapters/sandbox/daytona/index.js +4 -23
- package/dist/adapters/sandbox/daytona/index.js.map +1 -1
- package/dist/adapters/sandbox/daytona/workflow.cjs +1 -7
- package/dist/adapters/sandbox/daytona/workflow.cjs.map +1 -1
- package/dist/adapters/sandbox/daytona/workflow.d.cts +9 -2
- package/dist/adapters/sandbox/daytona/workflow.d.ts +9 -2
- package/dist/adapters/sandbox/daytona/workflow.js +1 -7
- package/dist/adapters/sandbox/daytona/workflow.js.map +1 -1
- package/dist/adapters/sandbox/e2b/index.cjs +9 -0
- package/dist/adapters/sandbox/e2b/index.cjs.map +1 -1
- package/dist/adapters/sandbox/e2b/index.d.cts +13 -5
- package/dist/adapters/sandbox/e2b/index.d.ts +13 -5
- package/dist/adapters/sandbox/e2b/index.js +9 -1
- package/dist/adapters/sandbox/e2b/index.js.map +1 -1
- package/dist/adapters/sandbox/e2b/workflow.cjs.map +1 -1
- package/dist/adapters/sandbox/e2b/workflow.d.cts +4 -2
- package/dist/adapters/sandbox/e2b/workflow.d.ts +4 -2
- package/dist/adapters/sandbox/e2b/workflow.js.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.cjs +11 -0
- package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.d.cts +11 -3
- package/dist/adapters/sandbox/inmemory/index.d.ts +11 -3
- package/dist/adapters/sandbox/inmemory/index.js +11 -1
- package/dist/adapters/sandbox/inmemory/index.js.map +1 -1
- package/dist/adapters/sandbox/inmemory/workflow.cjs.map +1 -1
- package/dist/adapters/sandbox/inmemory/workflow.d.cts +4 -2
- package/dist/adapters/sandbox/inmemory/workflow.d.ts +4 -2
- package/dist/adapters/sandbox/inmemory/workflow.js.map +1 -1
- package/dist/adapters/thread/anthropic/index.cjs.map +1 -1
- package/dist/adapters/thread/anthropic/index.d.cts +5 -5
- package/dist/adapters/thread/anthropic/index.d.ts +5 -5
- package/dist/adapters/thread/anthropic/index.js.map +1 -1
- package/dist/adapters/thread/anthropic/workflow.d.cts +5 -5
- package/dist/adapters/thread/anthropic/workflow.d.ts +5 -5
- package/dist/adapters/thread/google-genai/index.cjs.map +1 -1
- package/dist/adapters/thread/google-genai/index.d.cts +5 -5
- package/dist/adapters/thread/google-genai/index.d.ts +5 -5
- package/dist/adapters/thread/google-genai/index.js.map +1 -1
- package/dist/adapters/thread/google-genai/workflow.d.cts +5 -5
- package/dist/adapters/thread/google-genai/workflow.d.ts +5 -5
- package/dist/adapters/thread/langchain/index.cjs.map +1 -1
- package/dist/adapters/thread/langchain/index.d.cts +5 -5
- package/dist/adapters/thread/langchain/index.d.ts +5 -5
- package/dist/adapters/thread/langchain/index.js.map +1 -1
- package/dist/adapters/thread/langchain/workflow.d.cts +5 -5
- package/dist/adapters/thread/langchain/workflow.d.ts +5 -5
- package/dist/index.cjs +224 -70
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +66 -16
- package/dist/index.d.ts +66 -16
- package/dist/index.js +224 -70
- package/dist/index.js.map +1 -1
- package/dist/{proxy-D7mvDEO6.d.cts → proxy-Bf7uI-Hw.d.cts} +1 -1
- package/dist/{proxy-BbcgoXg1.d.ts → proxy-COqA95FW.d.ts} +1 -1
- package/dist/{thread-manager-CTXPCu9W.d.ts → thread-manager-BhkOyQ1I.d.ts} +2 -2
- package/dist/{thread-manager-Dqstsw4i.d.ts → thread-manager-Bi1XlbpJ.d.ts} +2 -2
- package/dist/{thread-manager-cLhDhRRc.d.cts → thread-manager-BsLO3Fgc.d.cts} +2 -2
- package/dist/{thread-manager-DrWfVjlj.d.cts → thread-manager-wRVVBFgj.d.cts} +2 -2
- package/dist/{types-CjF1_Idx.d.ts → types-BkX4HLzi.d.ts} +1 -1
- package/dist/{types-CdvcmXb6.d.cts → types-C66-BVBr.d.cts} +1 -1
- package/dist/types-CJ7tCdl6.d.cts +266 -0
- package/dist/types-CJ7tCdl6.d.ts +266 -0
- package/dist/{types-DjaQKUJx.d.cts → types-CdALEF3z.d.cts} +300 -20
- package/dist/{types-BqTmyH31.d.ts → types-ChAy_jSP.d.ts} +300 -20
- package/dist/types-CjY93AWZ.d.cts +84 -0
- package/dist/types-gVa5XCWD.d.ts +84 -0
- package/dist/{workflow-N1MNDoul.d.ts → workflow-BwT5EybR.d.ts} +7 -6
- package/dist/{workflow-CuqxgS6X.d.cts → workflow-DMmiaw6w.d.cts} +7 -6
- package/dist/workflow.cjs +99 -46
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +4 -4
- package/dist/workflow.d.ts +4 -4
- package/dist/workflow.js +99 -46
- package/dist/workflow.js.map +1 -1
- package/package.json +7 -32
- package/src/adapters/sandbox/daytona/index.ts +25 -48
- package/src/adapters/sandbox/daytona/proxy.ts +7 -8
- package/src/adapters/sandbox/e2b/index.ts +21 -6
- package/src/adapters/sandbox/e2b/proxy.ts +3 -2
- package/src/adapters/sandbox/inmemory/index.ts +21 -1
- package/src/adapters/sandbox/inmemory/proxy.ts +7 -3
- package/src/lib/activity.ts +5 -0
- package/src/lib/sandbox/capability-types.test.ts +859 -0
- package/src/lib/sandbox/index.ts +1 -0
- package/src/lib/sandbox/manager.ts +187 -31
- package/src/lib/sandbox/types.ts +189 -46
- package/src/lib/session/index.ts +1 -0
- package/src/lib/session/session.ts +97 -35
- package/src/lib/session/types.ts +181 -5
- package/src/lib/subagent/handler.ts +66 -43
- package/src/lib/subagent/types.ts +484 -16
- package/src/workflow.ts +3 -0
- package/tsup.config.ts +0 -4
- package/dist/adapters/sandbox/bedrock/index.cjs +0 -457
- package/dist/adapters/sandbox/bedrock/index.cjs.map +0 -1
- package/dist/adapters/sandbox/bedrock/index.d.cts +0 -25
- package/dist/adapters/sandbox/bedrock/index.d.ts +0 -25
- package/dist/adapters/sandbox/bedrock/index.js +0 -454
- package/dist/adapters/sandbox/bedrock/index.js.map +0 -1
- package/dist/adapters/sandbox/bedrock/workflow.cjs +0 -36
- package/dist/adapters/sandbox/bedrock/workflow.cjs.map +0 -1
- package/dist/adapters/sandbox/bedrock/workflow.d.cts +0 -29
- package/dist/adapters/sandbox/bedrock/workflow.d.ts +0 -29
- package/dist/adapters/sandbox/bedrock/workflow.js +0 -34
- package/dist/adapters/sandbox/bedrock/workflow.js.map +0 -1
- package/dist/types-DAsQ21Rt.d.ts +0 -74
- package/dist/types-lm8tMNJQ.d.cts +0 -74
- package/dist/types-yx0LzPGn.d.cts +0 -173
- package/dist/types-yx0LzPGn.d.ts +0 -173
- package/src/adapters/sandbox/bedrock/filesystem.ts +0 -340
- package/src/adapters/sandbox/bedrock/index.ts +0 -274
- package/src/adapters/sandbox/bedrock/proxy.ts +0 -59
- package/src/adapters/sandbox/bedrock/types.ts +0 -24
|
@@ -6,11 +6,14 @@ import {
|
|
|
6
6
|
} from "@temporalio/workflow";
|
|
7
7
|
import type { SessionExitReason } from "../types";
|
|
8
8
|
import type { SessionConfig, ZeitlichSession } from "./types";
|
|
9
|
+
import { resolveSessionLifecycle } from "./types";
|
|
9
10
|
import type {
|
|
11
|
+
SandboxCapability,
|
|
10
12
|
SandboxCreateOptions,
|
|
11
13
|
SandboxOps,
|
|
12
14
|
SandboxSnapshot,
|
|
13
15
|
} from "../sandbox/types";
|
|
16
|
+
import type { SandboxInit, SubagentSandboxShutdown } from "../lifecycle";
|
|
14
17
|
import type {
|
|
15
18
|
AgentState,
|
|
16
19
|
AgentStateManager,
|
|
@@ -79,41 +82,89 @@ export async function createSession<
|
|
|
79
82
|
T extends ToolMap,
|
|
80
83
|
M = unknown,
|
|
81
84
|
TContent = string,
|
|
85
|
+
TInit extends SandboxInit | undefined = undefined,
|
|
86
|
+
TShutdown extends SubagentSandboxShutdown | undefined = undefined,
|
|
82
87
|
>(
|
|
83
|
-
config: SessionConfig<T, M, TContent> & {
|
|
88
|
+
config: SessionConfig<T, M, TContent, TInit, TShutdown> & {
|
|
89
|
+
sandboxOps: NonNullable<
|
|
90
|
+
SessionConfig<T, M, TContent, TInit, TShutdown>["sandboxOps"]
|
|
91
|
+
>;
|
|
92
|
+
}
|
|
84
93
|
): Promise<ZeitlichSession<M, true>>;
|
|
85
94
|
export async function createSession<
|
|
86
95
|
T extends ToolMap,
|
|
87
96
|
M = unknown,
|
|
88
97
|
TContent = string,
|
|
89
|
-
|
|
98
|
+
TInit extends SandboxInit | undefined = undefined,
|
|
99
|
+
TShutdown extends SubagentSandboxShutdown | undefined = undefined,
|
|
100
|
+
>(
|
|
101
|
+
config: SessionConfig<T, M, TContent, TInit, TShutdown>
|
|
102
|
+
): Promise<ZeitlichSession<M, false>>;
|
|
103
|
+
// Implementation. The overloads above narrow the public contract per
|
|
104
|
+
// `SessionRequiredCaps<TInit, TShutdown>`. The impl signature uses the
|
|
105
|
+
// `never` cap floor — the structurally-narrowest shape that every
|
|
106
|
+
// adapter (including Daytona/Bedrock) satisfies — so each overload's
|
|
107
|
+
// possibly-narrow `sandboxOps` is assignable here. Gated method calls
|
|
108
|
+
// inside the body go through `wideOps()` below, which casts the
|
|
109
|
+
// narrow-typed binding to the wide shape. This is structurally safe:
|
|
110
|
+
// the runtime gates each gated call on `sandboxMode === …` /
|
|
111
|
+
// `resolvedShutdown === …`, and the type system has already ruled out
|
|
112
|
+
// any (mode, shutdown, adapter) cell that would invoke a missing
|
|
113
|
+
// method.
|
|
90
114
|
export async function createSession<
|
|
91
115
|
T extends ToolMap,
|
|
92
116
|
M = unknown,
|
|
93
117
|
TContent = string,
|
|
94
|
-
>(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
118
|
+
>(
|
|
119
|
+
config: Omit<
|
|
120
|
+
SessionConfig<T, M, TContent, SandboxInit | undefined, undefined>,
|
|
121
|
+
"sandboxOps"
|
|
122
|
+
> & {
|
|
123
|
+
sandboxOps?: SandboxOps<SandboxCreateOptions, unknown, never>;
|
|
124
|
+
}
|
|
125
|
+
): Promise<ZeitlichSession<M, boolean>> {
|
|
126
|
+
const {
|
|
127
|
+
agentName,
|
|
128
|
+
maxTurns = 50,
|
|
129
|
+
metadata = {},
|
|
130
|
+
runAgent,
|
|
131
|
+
threadOps,
|
|
132
|
+
buildContextMessage,
|
|
133
|
+
subagents,
|
|
134
|
+
skills,
|
|
135
|
+
tools = {} as T,
|
|
136
|
+
processToolsInParallel = true,
|
|
137
|
+
hooks = {},
|
|
138
|
+
appendSystemPrompt = true,
|
|
139
|
+
threadKey,
|
|
140
|
+
sandboxOps,
|
|
141
|
+
thread: threadInit,
|
|
142
|
+
sandbox: sandboxInit,
|
|
143
|
+
sandboxShutdown,
|
|
144
|
+
onSandboxReady,
|
|
145
|
+
onSessionExit,
|
|
146
|
+
virtualFs: virtualFsConfig,
|
|
147
|
+
virtualFsOps,
|
|
148
|
+
} = config;
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* The narrow-typed `sandboxOps` binding cast to its wide
|
|
152
|
+
* (`SandboxCapability`) form. The overload signatures +
|
|
153
|
+
* `SessionRequiredCaps` SSOT have already ruled out `(sandbox.mode,
|
|
154
|
+
* sandboxShutdown, adapter)` combinations where a referenced method
|
|
155
|
+
* would be missing on the proxy, and each gated call site below is
|
|
156
|
+
* guarded by an `if (sandboxOps)` / `sandboxOps &&` runtime check,
|
|
157
|
+
* so the cast is structurally safe. `wideOps` returns the wide-cap
|
|
158
|
+
* shape; callers use it after their own runtime guard establishes
|
|
159
|
+
* that `sandboxOps` is defined.
|
|
160
|
+
*/
|
|
161
|
+
type WideSandboxOps = SandboxOps<
|
|
162
|
+
SandboxCreateOptions,
|
|
163
|
+
unknown,
|
|
164
|
+
SandboxCapability
|
|
165
|
+
>;
|
|
166
|
+
const wideOps = (): WideSandboxOps =>
|
|
167
|
+
sandboxOps as unknown as WideSandboxOps;
|
|
117
168
|
// ---------------------------------------------------------------------------
|
|
118
169
|
// Thread resolution
|
|
119
170
|
// ---------------------------------------------------------------------------
|
|
@@ -219,7 +270,18 @@ export async function createSession<
|
|
|
219
270
|
);
|
|
220
271
|
|
|
221
272
|
// --- Sandbox lifecycle: create, continue, fork, from-snapshot, or inherit ---
|
|
222
|
-
|
|
273
|
+
// Resolve `sandbox` / `sandboxShutdown` defaults through the SSOT
|
|
274
|
+
// so the runtime dispatch below and the type-level
|
|
275
|
+
// `SessionRequiredCaps` cannot disagree on what the documented
|
|
276
|
+
// defaults are. Both surfaces consult `resolveSessionLifecycle`
|
|
277
|
+
// (or its type-level equivalent) before checking individual
|
|
278
|
+
// mode/shutdown values.
|
|
279
|
+
const lifecycle = resolveSessionLifecycle(
|
|
280
|
+
sandboxInit,
|
|
281
|
+
sandboxShutdown
|
|
282
|
+
);
|
|
283
|
+
const sandboxMode: SandboxInit["mode"] | undefined = lifecycle.mode;
|
|
284
|
+
const resolvedShutdown: SubagentSandboxShutdown = lifecycle.shutdown;
|
|
223
285
|
let sandboxId: string | undefined;
|
|
224
286
|
let sandboxOwned = false;
|
|
225
287
|
let baseSnapshot: SandboxSnapshot | undefined;
|
|
@@ -248,8 +310,8 @@ export async function createSession<
|
|
|
248
310
|
}
|
|
249
311
|
sandboxId = (sandboxInit as { mode: "continue"; sandboxId: string })
|
|
250
312
|
.sandboxId;
|
|
251
|
-
if (
|
|
252
|
-
await
|
|
313
|
+
if (resolvedShutdown === "pause-until-parent-close") {
|
|
314
|
+
await wideOps().resumeSandbox(sandboxId);
|
|
253
315
|
}
|
|
254
316
|
sandboxOwned = true;
|
|
255
317
|
} else if (sandboxMode === "fork") {
|
|
@@ -264,7 +326,7 @@ export async function createSession<
|
|
|
264
326
|
sandboxId: string;
|
|
265
327
|
options?: SandboxCreateOptions;
|
|
266
328
|
};
|
|
267
|
-
sandboxId = await
|
|
329
|
+
sandboxId = await wideOps().forkSandbox(
|
|
268
330
|
forkInit.sandboxId,
|
|
269
331
|
forkInit.options
|
|
270
332
|
);
|
|
@@ -281,7 +343,7 @@ export async function createSession<
|
|
|
281
343
|
snapshot: SandboxSnapshot;
|
|
282
344
|
options?: SandboxCreateOptions;
|
|
283
345
|
};
|
|
284
|
-
sandboxId = await
|
|
346
|
+
sandboxId = await wideOps().restoreSandbox(
|
|
285
347
|
restoreInit.snapshot,
|
|
286
348
|
restoreInit.options
|
|
287
349
|
);
|
|
@@ -308,10 +370,10 @@ export async function createSession<
|
|
|
308
370
|
sandboxId &&
|
|
309
371
|
sandboxOwned &&
|
|
310
372
|
freshlyCreated &&
|
|
311
|
-
|
|
373
|
+
resolvedShutdown === "snapshot" &&
|
|
312
374
|
sandboxOps
|
|
313
375
|
) {
|
|
314
|
-
baseSnapshot = await
|
|
376
|
+
baseSnapshot = await wideOps().snapshotSandbox(sandboxId);
|
|
315
377
|
}
|
|
316
378
|
|
|
317
379
|
if (sandboxId && sandboxOwned && onSandboxReady) {
|
|
@@ -571,19 +633,19 @@ export async function createSession<
|
|
|
571
633
|
await callSessionEnd(exitReason, stateManager.getTurns());
|
|
572
634
|
|
|
573
635
|
if (sandboxOwned && sandboxId && sandboxOps) {
|
|
574
|
-
switch (
|
|
636
|
+
switch (resolvedShutdown) {
|
|
575
637
|
case "destroy":
|
|
576
638
|
await sandboxOps.destroySandbox(sandboxId);
|
|
577
639
|
break;
|
|
578
640
|
case "pause":
|
|
579
641
|
case "pause-until-parent-close":
|
|
580
|
-
await
|
|
642
|
+
await wideOps().pauseSandbox(sandboxId);
|
|
581
643
|
break;
|
|
582
644
|
case "keep":
|
|
583
645
|
case "keep-until-parent-close":
|
|
584
646
|
break;
|
|
585
647
|
case "snapshot":
|
|
586
|
-
exitSnapshot = await
|
|
648
|
+
exitSnapshot = await wideOps().snapshotSandbox(sandboxId);
|
|
587
649
|
await sandboxOps.destroySandbox(sandboxId);
|
|
588
650
|
break;
|
|
589
651
|
}
|
package/src/lib/session/types.ts
CHANGED
|
@@ -7,7 +7,12 @@ import type {
|
|
|
7
7
|
import type { Hooks } from "../hooks/types";
|
|
8
8
|
import type { SubagentConfig } from "../subagent/types";
|
|
9
9
|
import type { Skill } from "../skills/types";
|
|
10
|
-
import type {
|
|
10
|
+
import type {
|
|
11
|
+
SandboxCapability,
|
|
12
|
+
SandboxCreateOptions,
|
|
13
|
+
SandboxOps,
|
|
14
|
+
SandboxSnapshot,
|
|
15
|
+
} from "../sandbox/types";
|
|
11
16
|
import type { VirtualFsOps } from "../virtual-fs/types";
|
|
12
17
|
import type { RunAgentActivity } from "../model/types";
|
|
13
18
|
import type {
|
|
@@ -137,17 +142,171 @@ export type PrefixedThreadOps<TPrefix extends string, TContent = string> = {
|
|
|
137
142
|
[K in keyof ThreadOps<TContent> as `${TPrefix}${Capitalize<K & string>}`]: ThreadOps<TContent>[K];
|
|
138
143
|
};
|
|
139
144
|
|
|
145
|
+
// ============================================================================
|
|
146
|
+
// Session sandbox-lifecycle decision table (SSOT)
|
|
147
|
+
//
|
|
148
|
+
// `createSession` (`src/lib/session/session.ts`) dispatches gated
|
|
149
|
+
// sandbox methods based on `(sandbox.mode, sandboxShutdown)`. When a
|
|
150
|
+
// caller omits either field, the session uses the documented defaults
|
|
151
|
+
// (`sandbox: { mode: "new" }` and `sandboxShutdown: "destroy"`),
|
|
152
|
+
// which trigger only base ops (`createSandbox` / `destroySandbox`).
|
|
153
|
+
//
|
|
154
|
+
// Two surfaces have to agree on what gated methods may fire for a
|
|
155
|
+
// given config:
|
|
156
|
+
//
|
|
157
|
+
// 1. The runtime — what the session dispatches per `(mode,
|
|
158
|
+
// shutdown)` pair.
|
|
159
|
+
// 2. The type level — what caps `sandboxOps` has to advertise.
|
|
160
|
+
//
|
|
161
|
+
// `SessionRequiredCaps<TInit, TShutdown>` is the SSOT for the type
|
|
162
|
+
// level. `resolveSessionLifecycle(init, shutdown)` (in `session.ts`,
|
|
163
|
+
// re-exported below) is the runtime mirror. Adding a new branch to
|
|
164
|
+
// `session.ts` requires extending **both**; the
|
|
165
|
+
// `(sandbox.mode × sandboxShutdown × adapter)` matrix in
|
|
166
|
+
// `src/lib/sandbox/capability-types.test.ts` enforces agreement.
|
|
167
|
+
// ============================================================================
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Caps the session's sandbox-init dispatch may invoke for a given
|
|
171
|
+
* `(mode, shutdown)`. Mirror of `src/lib/session/session.ts:241-313`.
|
|
172
|
+
*
|
|
173
|
+
* The conditional branches are written non-distributively (each cap
|
|
174
|
+
* checked against the input `M` / `S` rather than over a union) so
|
|
175
|
+
* that the *omitted* case (defaults: M = "new", S = "destroy") flows
|
|
176
|
+
* through to `never`, not to "I don't know, assume everything."
|
|
177
|
+
*/
|
|
178
|
+
type _SessionInitCaps<M, S> =
|
|
179
|
+
| (M extends "fork" ? "fork" : never)
|
|
180
|
+
| (M extends "from-snapshot" ? "restore" : never)
|
|
181
|
+
| (M extends "continue"
|
|
182
|
+
? S extends "pause-until-parent-close"
|
|
183
|
+
? "resume"
|
|
184
|
+
: never
|
|
185
|
+
: never);
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Caps the session's exit dispatch may invoke. `"inherit"` mode keeps
|
|
189
|
+
* `sandboxOwned = false` so exit-shutdown caps NEVER fire — mirror of
|
|
190
|
+
* `src/lib/session/session.ts:598-615`.
|
|
191
|
+
*/
|
|
192
|
+
type _SessionExitCaps<M, S> = M extends "inherit"
|
|
193
|
+
? never
|
|
194
|
+
:
|
|
195
|
+
| (S extends "snapshot" ? "snapshot" : never)
|
|
196
|
+
| (S extends "pause" | "pause-until-parent-close" ? "pause" : never);
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Cap captured on entry for `mode: "new"` + `shutdown: "snapshot"` (the
|
|
200
|
+
* seeding-base-snapshot path). Mirror of
|
|
201
|
+
* `src/lib/session/session.ts:316-317`.
|
|
202
|
+
*/
|
|
203
|
+
type _SessionSeedCaps<M, S> = M extends "new"
|
|
204
|
+
? S extends "snapshot"
|
|
205
|
+
? "snapshot"
|
|
206
|
+
: never
|
|
207
|
+
: never;
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Resolves an omitted `sandbox` field to the runtime default
|
|
211
|
+
* `{ mode: "new" }`, and an omitted `sandboxShutdown` field to the
|
|
212
|
+
* runtime default `"destroy"`. The two `_Resolve…` helpers are the
|
|
213
|
+
* sole bridge between "user didn't set the field" and the SSOT below
|
|
214
|
+
* — keeping the defaults out of the conditional table itself.
|
|
215
|
+
*/
|
|
216
|
+
type _ResolveInit<TInit> = [TInit] extends [undefined]
|
|
217
|
+
? { mode: "new" }
|
|
218
|
+
: Exclude<TInit, undefined> extends infer Defined
|
|
219
|
+
? // If the user passed `SandboxInit | undefined` (the wide default),
|
|
220
|
+
// collapse `undefined` to the runtime default.
|
|
221
|
+
undefined extends TInit
|
|
222
|
+
? Defined | { mode: "new" }
|
|
223
|
+
: Defined
|
|
224
|
+
: never;
|
|
225
|
+
|
|
226
|
+
type _ResolveShutdown<TShutdown> = [TShutdown] extends [undefined]
|
|
227
|
+
? "destroy"
|
|
228
|
+
: Exclude<TShutdown, undefined> extends infer Defined
|
|
229
|
+
? undefined extends TShutdown
|
|
230
|
+
? Defined | "destroy"
|
|
231
|
+
: Defined
|
|
232
|
+
: never;
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Sandbox capabilities a session actually invokes on its
|
|
236
|
+
* `sandboxOps`, derived from the literal types of the surrounding
|
|
237
|
+
* `sandbox` and `sandboxShutdown` fields.
|
|
238
|
+
*
|
|
239
|
+
* `TInit` / `TShutdown` default to `undefined` so an un-parameterised
|
|
240
|
+
* `SessionRequiredCaps` resolves to the caps the runtime *defaults*
|
|
241
|
+
* (`{ mode: "new" }` + `"destroy"`) actually require — i.e.
|
|
242
|
+
* `never`. This lets a narrow adapter (e.g. `proxyDaytonaSandboxOps`)
|
|
243
|
+
* satisfy `sandboxOps?: SandboxOps<…, SessionRequiredCaps<…>>` when
|
|
244
|
+
* the caller doesn't pin literals, matching what's runtime-safe.
|
|
245
|
+
*
|
|
246
|
+
* Pin literals via `as const` or by ascribing `SessionConfig<…, TInit,
|
|
247
|
+
* TShutdown>` to tighten the requirement on a per-call basis.
|
|
248
|
+
*/
|
|
249
|
+
export type SessionRequiredCaps<
|
|
250
|
+
TInit extends SandboxInit | undefined = undefined,
|
|
251
|
+
TShutdown extends SubagentSandboxShutdown | undefined = undefined,
|
|
252
|
+
> = _ResolveInit<TInit> extends infer M
|
|
253
|
+
? _ResolveShutdown<TShutdown> extends infer S
|
|
254
|
+
? M extends { mode: infer Mode }
|
|
255
|
+
? S extends SubagentSandboxShutdown
|
|
256
|
+
?
|
|
257
|
+
| _SessionInitCaps<Mode, S>
|
|
258
|
+
| _SessionExitCaps<Mode, S>
|
|
259
|
+
| _SessionSeedCaps<Mode, S>
|
|
260
|
+
: never
|
|
261
|
+
: never
|
|
262
|
+
: never
|
|
263
|
+
: never;
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Runtime mirror of `SessionRequiredCaps`. Returns the names of the
|
|
267
|
+
* gated `sandboxOps` methods the session will invoke for a given
|
|
268
|
+
* `(sandboxInit, sandboxShutdown)` pair (after resolving documented
|
|
269
|
+
* defaults). Mirror of the dispatch in
|
|
270
|
+
* `src/lib/session/session.ts:241-313` and `:598-615`.
|
|
271
|
+
*
|
|
272
|
+
* Both surfaces consult this same table — the `(mode × shutdown ×
|
|
273
|
+
* adapter)` matrix in `src/lib/sandbox/capability-types.test.ts`
|
|
274
|
+
* enforces agreement.
|
|
275
|
+
*/
|
|
276
|
+
export function resolveSessionLifecycle(
|
|
277
|
+
init: SandboxInit | undefined,
|
|
278
|
+
shutdown: SubagentSandboxShutdown | undefined
|
|
279
|
+
): { mode: SandboxInit["mode"]; shutdown: SubagentSandboxShutdown } {
|
|
280
|
+
const resolvedInit: SandboxInit = init ?? { mode: "new" };
|
|
281
|
+
const resolvedShutdown: SubagentSandboxShutdown = shutdown ?? "destroy";
|
|
282
|
+
return {
|
|
283
|
+
mode: resolvedInit.mode,
|
|
284
|
+
shutdown: resolvedShutdown,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
|
|
140
288
|
/**
|
|
141
289
|
* Configuration for a Zeitlich agent session.
|
|
142
290
|
*
|
|
143
291
|
* @typeParam T - Tool map
|
|
144
292
|
* @typeParam M - SDK-native message type returned by the model invoker
|
|
145
293
|
* @typeParam TContent - SDK-native content type for human messages (defaults to `string`)
|
|
294
|
+
* @typeParam TInit - Literal type of `sandbox` (a {@link SandboxInit}
|
|
295
|
+
* variant or `undefined`). Defaults to the wide union; pin it via
|
|
296
|
+
* `as const` on the call site to narrow the cap requirement on
|
|
297
|
+
* `sandboxOps`.
|
|
298
|
+
* @typeParam TShutdown - Literal type of `sandboxShutdown`. Defaults
|
|
299
|
+
* to the wide union; pin it via `as const` on the call site to
|
|
300
|
+
* narrow the cap requirement on `sandboxOps`.
|
|
146
301
|
*/
|
|
147
302
|
export interface SessionConfig<
|
|
148
303
|
T extends ToolMap,
|
|
149
304
|
M = unknown,
|
|
150
305
|
TContent = string,
|
|
306
|
+
TInit extends SandboxInit | undefined = SandboxInit | undefined,
|
|
307
|
+
TShutdown extends
|
|
308
|
+
| SubagentSandboxShutdown
|
|
309
|
+
| undefined = SubagentSandboxShutdown | undefined,
|
|
151
310
|
> {
|
|
152
311
|
/** The name of the agent, should be unique within the workflows */
|
|
153
312
|
agentName: string;
|
|
@@ -203,8 +362,25 @@ export interface SessionConfig<
|
|
|
203
362
|
// Sandbox lifecycle
|
|
204
363
|
// ---------------------------------------------------------------------------
|
|
205
364
|
|
|
206
|
-
/**
|
|
207
|
-
|
|
365
|
+
/**
|
|
366
|
+
* Sandbox lifecycle operations (optional — omit for agents that don't
|
|
367
|
+
* need a sandbox).
|
|
368
|
+
*
|
|
369
|
+
* The `TCaps` argument is derived from {@link SessionRequiredCaps}
|
|
370
|
+
* over the literal types of the surrounding `sandbox` and
|
|
371
|
+
* `sandboxShutdown` fields. With the default wide
|
|
372
|
+
* `TInit` / `TShutdown`, this resolves to the full
|
|
373
|
+
* {@link SandboxCapability} union (current behaviour). When the
|
|
374
|
+
* caller pins those literals via `as const`, the cap requirement
|
|
375
|
+
* tightens so a narrow adapter (e.g. Daytona's
|
|
376
|
+
* `SandboxOps<…, never>`) can satisfy combinations that don't need
|
|
377
|
+
* a gated method.
|
|
378
|
+
*/
|
|
379
|
+
sandboxOps?: SandboxOps<
|
|
380
|
+
SandboxCreateOptions,
|
|
381
|
+
unknown,
|
|
382
|
+
SessionRequiredCaps<TInit, TShutdown> & SandboxCapability
|
|
383
|
+
>;
|
|
208
384
|
/**
|
|
209
385
|
* Sandbox initialization strategy.
|
|
210
386
|
*
|
|
@@ -215,14 +391,14 @@ export interface SessionConfig<
|
|
|
215
391
|
*
|
|
216
392
|
* When omitted and `sandboxOps` is provided, defaults to `{ mode: "new" }`.
|
|
217
393
|
*/
|
|
218
|
-
sandbox?:
|
|
394
|
+
sandbox?: TInit;
|
|
219
395
|
/**
|
|
220
396
|
* What to do with the sandbox when this session exits.
|
|
221
397
|
*
|
|
222
398
|
* Defaults to `"destroy"` when omitted.
|
|
223
399
|
* Has no effect when the sandbox is inherited (`sandbox.mode === "inherit"`).
|
|
224
400
|
*/
|
|
225
|
-
sandboxShutdown?:
|
|
401
|
+
sandboxShutdown?: TShutdown;
|
|
226
402
|
/**
|
|
227
403
|
* Called as soon as the sandbox is created (or resumed/forked), before the
|
|
228
404
|
* agent loop starts. Useful for signalling sandbox readiness to a parent.
|
|
@@ -6,16 +6,19 @@ import {
|
|
|
6
6
|
ApplicationFailure,
|
|
7
7
|
executeChild,
|
|
8
8
|
} from "@temporalio/workflow";
|
|
9
|
+
import type { Duration } from "@temporalio/common";
|
|
9
10
|
import { getShortId } from "../thread/id";
|
|
10
11
|
import type { ToolHandlerResponse, RouterContext } from "../tool-router";
|
|
11
12
|
import type { JsonValue } from "../state/types";
|
|
12
13
|
import type {
|
|
13
14
|
InferSubagentResult,
|
|
15
|
+
ResolvedSubagentSandboxConfig,
|
|
14
16
|
SubagentConfig,
|
|
15
17
|
SubagentFnResult,
|
|
16
18
|
SubagentSandboxConfig,
|
|
17
19
|
SubagentWorkflowInput,
|
|
18
20
|
} from "./types";
|
|
21
|
+
import { resolveSubagentLifecycle } from "./types";
|
|
19
22
|
import type { SubagentArgs } from "./tool";
|
|
20
23
|
import type { z } from "zod";
|
|
21
24
|
import type {
|
|
@@ -23,9 +26,33 @@ import type {
|
|
|
23
26
|
SandboxInit,
|
|
24
27
|
SubagentSandboxShutdown,
|
|
25
28
|
} from "../lifecycle";
|
|
26
|
-
import type {
|
|
29
|
+
import type {
|
|
30
|
+
SandboxCreateOptions,
|
|
31
|
+
SandboxOps,
|
|
32
|
+
SandboxSnapshot,
|
|
33
|
+
} from "../sandbox/types";
|
|
27
34
|
import { childSandboxReadySignal } from "./signals";
|
|
28
35
|
|
|
36
|
+
/**
|
|
37
|
+
* Methods the parent's subagent handler invokes on a subagent's `proxy`.
|
|
38
|
+
* Kept narrow so the handler's internal maps accept `SandboxOps<…, never>`
|
|
39
|
+
* (e.g. Daytona) and `SandboxOps<…, "snapshot">` (e.g. E2B for
|
|
40
|
+
* snapshot-driven continuations) alike.
|
|
41
|
+
*
|
|
42
|
+
* `destroySandbox` is base — always available.
|
|
43
|
+
* `deleteSandboxSnapshot` is only called for continuations that produce
|
|
44
|
+
* snapshots; it's stored separately and only populated when present on
|
|
45
|
+
* the cfg-specific proxy.
|
|
46
|
+
*/
|
|
47
|
+
type ParentDestroyOps = Pick<
|
|
48
|
+
SandboxOps<SandboxCreateOptions, unknown, never>,
|
|
49
|
+
"destroySandbox"
|
|
50
|
+
>;
|
|
51
|
+
type ParentDeleteSnapshotOps = Pick<
|
|
52
|
+
SandboxOps<SandboxCreateOptions, unknown, "snapshot">,
|
|
53
|
+
"deleteSandboxSnapshot"
|
|
54
|
+
>;
|
|
55
|
+
|
|
29
56
|
/**
|
|
30
57
|
* Default `workflowRunTimeout` applied to every subagent child workflow
|
|
31
58
|
* unless overridden via `SubagentConfig.workflowOptions.workflowRunTimeout`.
|
|
@@ -40,19 +67,11 @@ import { childSandboxReadySignal } from "./signals";
|
|
|
40
67
|
* still catching hangs; agents that legitimately need longer should set an
|
|
41
68
|
* explicit `workflowOptions.workflowRunTimeout`.
|
|
42
69
|
*/
|
|
43
|
-
export const DEFAULT_SUBAGENT_WORKFLOW_RUN_TIMEOUT = "1h";
|
|
44
|
-
|
|
45
|
-
/** Normalized sandbox config after resolving the union. */
|
|
46
|
-
interface ResolvedSandboxConfig {
|
|
47
|
-
source: "none" | "inherit" | "own";
|
|
48
|
-
init: "per-call" | "once";
|
|
49
|
-
continuation: "continue" | "fork" | "snapshot";
|
|
50
|
-
shutdown?: SubagentSandboxShutdown;
|
|
51
|
-
}
|
|
70
|
+
export const DEFAULT_SUBAGENT_WORKFLOW_RUN_TIMEOUT: Duration = "1h";
|
|
52
71
|
|
|
53
72
|
function resolveSandboxConfig(
|
|
54
73
|
config?: SubagentSandboxConfig
|
|
55
|
-
):
|
|
74
|
+
): ResolvedSubagentSandboxConfig {
|
|
56
75
|
if (!config || config === "none") {
|
|
57
76
|
return { source: "none", init: "per-call", continuation: "fork" };
|
|
58
77
|
}
|
|
@@ -96,11 +115,31 @@ export function createSubagentHandler<
|
|
|
96
115
|
} {
|
|
97
116
|
const { taskQueue: parentTaskQueue } = workflowInfo();
|
|
98
117
|
|
|
99
|
-
/**
|
|
100
|
-
|
|
118
|
+
/**
|
|
119
|
+
* Sandbox ops proxy per subagent, built eagerly from `sandbox.proxy`
|
|
120
|
+
* factories.
|
|
121
|
+
*
|
|
122
|
+
* Split into two maps so each accepts only the cap-narrowed slice the
|
|
123
|
+
* parent actually consumes. `destroyOps` accepts every adapter (base
|
|
124
|
+
* `destroySandbox` is always present); `deleteSnapshotOps` is only
|
|
125
|
+
* populated for `continuation: "snapshot"` configs, and the
|
|
126
|
+
* `SubagentSandboxConfig` type guarantees the proxy carries
|
|
127
|
+
* `deleteSandboxSnapshot` when that continuation is selected.
|
|
128
|
+
*/
|
|
129
|
+
const agentDestroyOps = new Map<string, ParentDestroyOps>();
|
|
130
|
+
const agentDeleteSnapshotOps = new Map<string, ParentDeleteSnapshotOps>();
|
|
101
131
|
for (const cfg of subagents) {
|
|
102
|
-
|
|
103
|
-
|
|
132
|
+
const cfgSandbox = cfg.sandbox;
|
|
133
|
+
if (!cfgSandbox || cfgSandbox === "none") continue;
|
|
134
|
+
if (cfgSandbox.continuation === "snapshot") {
|
|
135
|
+
// Pull the proxy here so the per-branch narrowing keeps
|
|
136
|
+
// `deleteSandboxSnapshot` in the inferred return type.
|
|
137
|
+
const proxy = cfgSandbox.proxy(cfg.agentName);
|
|
138
|
+
agentDestroyOps.set(cfg.agentName, proxy);
|
|
139
|
+
agentDeleteSnapshotOps.set(cfg.agentName, proxy);
|
|
140
|
+
} else {
|
|
141
|
+
const proxy = cfgSandbox.proxy(cfg.agentName);
|
|
142
|
+
agentDestroyOps.set(cfg.agentName, proxy);
|
|
104
143
|
}
|
|
105
144
|
}
|
|
106
145
|
|
|
@@ -182,7 +221,7 @@ export function createSubagentHandler<
|
|
|
182
221
|
|
|
183
222
|
if (
|
|
184
223
|
sandboxCfg.source !== "none" &&
|
|
185
|
-
!
|
|
224
|
+
!agentDestroyOps.has(config.agentName)
|
|
186
225
|
) {
|
|
187
226
|
throw ApplicationFailure.create({
|
|
188
227
|
message: `Subagent "${config.agentName}" uses a sandbox but no \`sandbox.proxy\` is configured on its SubagentConfig`,
|
|
@@ -272,7 +311,6 @@ export function createSubagentHandler<
|
|
|
272
311
|
if (baseSnap) {
|
|
273
312
|
sandbox = { mode: "from-snapshot", snapshot: baseSnap };
|
|
274
313
|
}
|
|
275
|
-
sandboxShutdownOverride = "snapshot";
|
|
276
314
|
} else if (sandboxCfg.source === "own") {
|
|
277
315
|
const isLazy = sandboxCfg.init === "once";
|
|
278
316
|
|
|
@@ -318,31 +356,16 @@ export function createSubagentHandler<
|
|
|
318
356
|
sandboxId: baseSandboxId,
|
|
319
357
|
};
|
|
320
358
|
}
|
|
359
|
+
}
|
|
321
360
|
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
const alreadySurvives =
|
|
331
|
-
userShutdown === "pause-until-parent-close" ||
|
|
332
|
-
userShutdown === "keep-until-parent-close" ||
|
|
333
|
-
userShutdown === "pause" ||
|
|
334
|
-
userShutdown === "keep";
|
|
335
|
-
|
|
336
|
-
const mustSurvive =
|
|
337
|
-
isLazyCreator ||
|
|
338
|
-
sandboxCfg.continuation === "continue" ||
|
|
339
|
-
(isLazy && sandboxCfg.continuation === "fork");
|
|
340
|
-
|
|
341
|
-
if (mustSurvive && !alreadySurvives) {
|
|
342
|
-
sandboxShutdownOverride = isLazyCreator
|
|
343
|
-
? "pause-until-parent-close"
|
|
344
|
-
: "pause";
|
|
345
|
-
}
|
|
361
|
+
// Resolve the lifecycle decision (auto-inject pause/snapshot, etc.)
|
|
362
|
+
// through the SSOT — same table the type-level `SubagentRequiredCaps`
|
|
363
|
+
// reads. Adding a new branch here means changing both. The matrix
|
|
364
|
+
// in `src/lib/sandbox/capability-types.test.ts` enforces the
|
|
365
|
+
// type-level / runtime agreement.
|
|
366
|
+
{
|
|
367
|
+
const lifecycle = resolveSubagentLifecycle(sandboxCfg, isLazyCreator);
|
|
368
|
+
sandboxShutdownOverride = lifecycle.shutdownOverride;
|
|
346
369
|
}
|
|
347
370
|
|
|
348
371
|
const workflowInput: SubagentWorkflowInput = {
|
|
@@ -555,7 +578,7 @@ export function createSubagentHandler<
|
|
|
555
578
|
pendingDestroys.clear();
|
|
556
579
|
await Promise.all(
|
|
557
580
|
entries.map(async ({ agentName, sandboxId }) => {
|
|
558
|
-
const ops =
|
|
581
|
+
const ops = agentDestroyOps.get(agentName);
|
|
559
582
|
if (!ops) {
|
|
560
583
|
log.warn(
|
|
561
584
|
"Skipping sandbox destroy — no sandbox.proxy registered for agent",
|
|
@@ -587,7 +610,7 @@ export function createSubagentHandler<
|
|
|
587
610
|
|
|
588
611
|
await Promise.all(
|
|
589
612
|
tagged.map(async ({ agentName, snapshot }) => {
|
|
590
|
-
const ops =
|
|
613
|
+
const ops = agentDeleteSnapshotOps.get(agentName);
|
|
591
614
|
if (!ops) {
|
|
592
615
|
log.warn(
|
|
593
616
|
"Skipping snapshot delete — no sandbox.proxy registered for agent",
|