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.
- package/README.md +303 -105
- package/dist/adapters/sandbox/daytona/index.cjs +7 -1
- package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
- package/dist/adapters/sandbox/daytona/index.d.cts +3 -1
- package/dist/adapters/sandbox/daytona/index.d.ts +3 -1
- package/dist/adapters/sandbox/daytona/index.js +7 -1
- package/dist/adapters/sandbox/daytona/index.js.map +1 -1
- package/dist/adapters/sandbox/daytona/workflow.cjs +33 -0
- package/dist/adapters/sandbox/daytona/workflow.cjs.map +1 -0
- package/dist/adapters/sandbox/daytona/workflow.d.cts +27 -0
- package/dist/adapters/sandbox/daytona/workflow.d.ts +27 -0
- package/dist/adapters/sandbox/daytona/workflow.js +31 -0
- package/dist/adapters/sandbox/daytona/workflow.js.map +1 -0
- package/dist/adapters/sandbox/inmemory/index.cjs +18 -1
- package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.d.cts +4 -2
- package/dist/adapters/sandbox/inmemory/index.d.ts +4 -2
- package/dist/adapters/sandbox/inmemory/index.js +18 -1
- package/dist/adapters/sandbox/inmemory/index.js.map +1 -1
- package/dist/adapters/sandbox/inmemory/workflow.cjs +33 -0
- package/dist/adapters/sandbox/inmemory/workflow.cjs.map +1 -0
- package/dist/adapters/sandbox/inmemory/workflow.d.cts +25 -0
- package/dist/adapters/sandbox/inmemory/workflow.d.ts +25 -0
- package/dist/adapters/sandbox/inmemory/workflow.js +31 -0
- package/dist/adapters/sandbox/inmemory/workflow.js.map +1 -0
- package/dist/adapters/sandbox/virtual/index.cjs +36 -9
- package/dist/adapters/sandbox/virtual/index.cjs.map +1 -1
- package/dist/adapters/sandbox/virtual/index.d.cts +8 -5
- package/dist/adapters/sandbox/virtual/index.d.ts +8 -5
- package/dist/adapters/sandbox/virtual/index.js +36 -9
- package/dist/adapters/sandbox/virtual/index.js.map +1 -1
- package/dist/adapters/sandbox/virtual/workflow.cjs +33 -0
- package/dist/adapters/sandbox/virtual/workflow.cjs.map +1 -0
- package/dist/adapters/sandbox/virtual/workflow.d.cts +27 -0
- package/dist/adapters/sandbox/virtual/workflow.d.ts +27 -0
- package/dist/adapters/sandbox/virtual/workflow.js +31 -0
- package/dist/adapters/sandbox/virtual/workflow.js.map +1 -0
- package/dist/adapters/thread/google-genai/index.cjs +9 -1
- package/dist/adapters/thread/google-genai/index.cjs.map +1 -1
- package/dist/adapters/thread/google-genai/index.d.cts +31 -19
- package/dist/adapters/thread/google-genai/index.d.ts +31 -19
- package/dist/adapters/thread/google-genai/index.js +9 -1
- package/dist/adapters/thread/google-genai/index.js.map +1 -1
- package/dist/adapters/thread/google-genai/workflow.cjs +33 -0
- package/dist/adapters/thread/google-genai/workflow.cjs.map +1 -0
- package/dist/adapters/thread/google-genai/workflow.d.cts +32 -0
- package/dist/adapters/thread/google-genai/workflow.d.ts +32 -0
- package/dist/adapters/thread/google-genai/workflow.js +31 -0
- package/dist/adapters/thread/google-genai/workflow.js.map +1 -0
- package/dist/adapters/thread/langchain/index.cjs +9 -1
- package/dist/adapters/thread/langchain/index.cjs.map +1 -1
- package/dist/adapters/thread/langchain/index.d.cts +27 -16
- package/dist/adapters/thread/langchain/index.d.ts +27 -16
- package/dist/adapters/thread/langchain/index.js +9 -1
- package/dist/adapters/thread/langchain/index.js.map +1 -1
- package/dist/adapters/thread/langchain/workflow.cjs +33 -0
- package/dist/adapters/thread/langchain/workflow.cjs.map +1 -0
- package/dist/adapters/thread/langchain/workflow.d.cts +32 -0
- package/dist/adapters/thread/langchain/workflow.d.ts +32 -0
- package/dist/adapters/thread/langchain/workflow.js +31 -0
- package/dist/adapters/thread/langchain/workflow.js.map +1 -0
- package/dist/index.cjs +282 -90
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -16
- package/dist/index.d.ts +38 -16
- package/dist/index.js +281 -87
- package/dist/index.js.map +1 -1
- package/dist/queries-DModcWRy.d.cts +44 -0
- package/dist/queries-byD0jr1Y.d.ts +44 -0
- package/dist/{types-BkAYmc96.d.ts → types-B50pBPEV.d.ts} +190 -38
- package/dist/{types-YbL7JpEA.d.cts → types-Bll19FZJ.d.cts} +7 -0
- package/dist/{types-YbL7JpEA.d.ts → types-Bll19FZJ.d.ts} +7 -0
- package/dist/{queries-6Avfh74U.d.ts → types-BuXdFhaZ.d.cts} +7 -48
- package/dist/{types-BMRzfELQ.d.cts → types-ChAMwU3q.d.cts} +17 -1
- package/dist/{types-BMRzfELQ.d.ts → types-ChAMwU3q.d.ts} +17 -1
- package/dist/{types-CES_30qx.d.cts → types-DQW8l7pY.d.cts} +190 -38
- package/dist/{queries-CHa2iv_I.d.cts → types-GZ76HZSj.d.ts} +7 -48
- package/dist/workflow.cjs +244 -86
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +54 -65
- package/dist/workflow.d.ts +54 -65
- package/dist/workflow.js +243 -83
- package/dist/workflow.js.map +1 -1
- package/package.json +54 -2
- package/src/adapters/sandbox/daytona/filesystem.ts +1 -1
- package/src/adapters/sandbox/daytona/index.ts +8 -0
- package/src/adapters/sandbox/daytona/proxy.ts +56 -0
- package/src/adapters/sandbox/e2b/filesystem.ts +147 -0
- package/src/adapters/sandbox/e2b/index.ts +164 -0
- package/src/adapters/sandbox/e2b/types.ts +23 -0
- package/src/adapters/sandbox/inmemory/index.ts +27 -3
- package/src/adapters/sandbox/inmemory/proxy.ts +53 -0
- package/src/adapters/sandbox/virtual/filesystem.ts +41 -17
- package/src/adapters/sandbox/virtual/provider.ts +9 -1
- package/src/adapters/sandbox/virtual/proxy.ts +53 -0
- package/src/adapters/sandbox/virtual/types.ts +9 -4
- package/src/adapters/thread/google-genai/activities.ts +51 -17
- package/src/adapters/thread/google-genai/index.ts +1 -0
- package/src/adapters/thread/google-genai/proxy.ts +61 -0
- package/src/adapters/thread/langchain/activities.ts +47 -14
- package/src/adapters/thread/langchain/index.ts +1 -0
- package/src/adapters/thread/langchain/proxy.ts +61 -0
- package/src/lib/lifecycle.ts +57 -0
- package/src/lib/sandbox/manager.ts +52 -6
- package/src/lib/sandbox/sandbox.test.ts +12 -11
- package/src/lib/sandbox/types.ts +31 -4
- package/src/lib/session/index.ts +4 -5
- package/src/lib/session/session-edge-cases.integration.test.ts +491 -66
- package/src/lib/session/session.integration.test.ts +92 -80
- package/src/lib/session/session.ts +108 -96
- package/src/lib/session/types.ts +87 -17
- package/src/lib/subagent/define.ts +6 -5
- package/src/lib/subagent/handler.ts +148 -16
- package/src/lib/subagent/index.ts +4 -0
- package/src/lib/subagent/register.ts +10 -3
- package/src/lib/subagent/signals.ts +8 -0
- package/src/lib/subagent/subagent.integration.test.ts +893 -128
- package/src/lib/subagent/tool.ts +2 -2
- package/src/lib/subagent/types.ts +84 -21
- package/src/lib/subagent/workflow.ts +83 -12
- package/src/lib/tool-router/router-edge-cases.integration.test.ts +4 -1
- package/src/lib/tool-router/router.integration.test.ts +141 -5
- package/src/lib/tool-router/router.ts +13 -3
- package/src/lib/tool-router/types.ts +7 -0
- package/src/lib/workflow.test.ts +104 -27
- package/src/lib/workflow.ts +37 -19
- package/src/tools/bash/bash.test.ts +16 -7
- package/src/workflow.ts +11 -14
- package/tsup.config.ts +6 -0
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
-
proxyActivities,
|
|
3
2
|
condition,
|
|
4
3
|
defineUpdate,
|
|
5
4
|
setHandler,
|
|
6
5
|
ApplicationFailure,
|
|
7
|
-
type ActivityInterfaceFor,
|
|
8
6
|
} from "@temporalio/workflow";
|
|
9
7
|
import type { SessionExitReason, MessageContent } from "../types";
|
|
10
|
-
import type {
|
|
8
|
+
import type { SessionConfig, ZeitlichSession } from "./types";
|
|
11
9
|
import type { SandboxOps } from "../sandbox/types";
|
|
12
10
|
import { type AgentStateManager, type JsonSerializable } from "../state/types";
|
|
13
11
|
import { createToolRouter } from "../tool-router/router";
|
|
@@ -21,22 +19,22 @@ import { uuid4 } from "@temporalio/workflow";
|
|
|
21
19
|
* Creates an agent session that manages the agent loop: LLM invocation,
|
|
22
20
|
* tool routing, subagent coordination, and lifecycle hooks.
|
|
23
21
|
*
|
|
22
|
+
* When `sandboxOps` is provided the returned session result is guaranteed to
|
|
23
|
+
* include `sandboxId: string`. Without it, `sandboxId` is `undefined`.
|
|
24
|
+
*
|
|
24
25
|
* @param config - Session and agent configuration (merged `SessionConfig` and `AgentConfig`)
|
|
25
26
|
* @returns A session object with `runSession()` to start the agent loop
|
|
26
27
|
*
|
|
27
28
|
* @example
|
|
28
29
|
* ```typescript
|
|
29
30
|
* import { createSession, createAgentStateManager, defineTool, bashTool } from 'zeitlich/workflow';
|
|
30
|
-
*
|
|
31
|
-
* const stateManager = createAgentStateManager({
|
|
32
|
-
* initialState: { systemPrompt: "You are a helpful assistant." },
|
|
33
|
-
* agentName: "my-agent",
|
|
34
|
-
* });
|
|
31
|
+
* import { proxyGoogleGenAIThreadOps } from 'zeitlich/adapters/thread/google-genai/workflow';
|
|
35
32
|
*
|
|
36
33
|
* const session = await createSession({
|
|
37
34
|
* agentName: "my-agent",
|
|
38
35
|
* maxTurns: 20,
|
|
39
|
-
*
|
|
36
|
+
* thread: { mode: "new" },
|
|
37
|
+
* threadOps: proxyGoogleGenAIThreadOps(),
|
|
40
38
|
* runAgent: runAgentActivity,
|
|
41
39
|
* buildContextMessage: () => [{ type: "text", text: prompt }],
|
|
42
40
|
* subagents: [researcherSubagent],
|
|
@@ -48,8 +46,13 @@ import { uuid4 } from "@temporalio/workflow";
|
|
|
48
46
|
* const { finalMessage, exitReason } = await session.runSession({ stateManager });
|
|
49
47
|
* ```
|
|
50
48
|
*/
|
|
51
|
-
export
|
|
52
|
-
|
|
49
|
+
export async function createSession<T extends ToolMap, M = unknown>(
|
|
50
|
+
config: SessionConfig<T, M> & { sandboxOps: SandboxOps }
|
|
51
|
+
): Promise<ZeitlichSession<M, true>>;
|
|
52
|
+
export async function createSession<T extends ToolMap, M = unknown>(
|
|
53
|
+
config: SessionConfig<T, M>
|
|
54
|
+
): Promise<ZeitlichSession<M, false>>;
|
|
55
|
+
export async function createSession<T extends ToolMap, M = unknown>({
|
|
53
56
|
agentName,
|
|
54
57
|
maxTurns = 50,
|
|
55
58
|
metadata = {},
|
|
@@ -62,16 +65,33 @@ export const createSession = async <T extends ToolMap, M = unknown>({
|
|
|
62
65
|
processToolsInParallel = true,
|
|
63
66
|
hooks = {},
|
|
64
67
|
appendSystemPrompt = true,
|
|
65
|
-
continueThread = false,
|
|
66
68
|
waitForInputTimeout = "48h",
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
69
|
+
sandboxOps,
|
|
70
|
+
thread: threadInit,
|
|
71
|
+
sandbox: sandboxInit,
|
|
72
|
+
sandboxShutdown = "destroy",
|
|
73
|
+
}: SessionConfig<T, M>): Promise<ZeitlichSession<M, boolean>> {
|
|
74
|
+
// ---------------------------------------------------------------------------
|
|
75
|
+
// Thread resolution
|
|
76
|
+
// ---------------------------------------------------------------------------
|
|
77
|
+
const threadMode = threadInit?.mode ?? "new";
|
|
78
|
+
let threadId: string;
|
|
79
|
+
let sourceThreadId: string | undefined;
|
|
80
|
+
|
|
81
|
+
switch (threadMode) {
|
|
82
|
+
case "new":
|
|
83
|
+
threadId = threadInit?.mode === "new" && threadInit.threadId
|
|
84
|
+
? threadInit.threadId
|
|
85
|
+
: getShortId();
|
|
86
|
+
break;
|
|
87
|
+
case "continue":
|
|
88
|
+
threadId = (threadInit as { mode: "continue"; threadId: string }).threadId;
|
|
89
|
+
break;
|
|
90
|
+
case "fork":
|
|
91
|
+
sourceThreadId = (threadInit as { mode: "fork"; threadId: string }).threadId;
|
|
92
|
+
threadId = getShortId();
|
|
93
|
+
break;
|
|
94
|
+
}
|
|
75
95
|
|
|
76
96
|
const {
|
|
77
97
|
appendToolResult,
|
|
@@ -79,12 +99,16 @@ export const createSession = async <T extends ToolMap, M = unknown>({
|
|
|
79
99
|
initializeThread,
|
|
80
100
|
appendSystemMessage,
|
|
81
101
|
forkThread,
|
|
82
|
-
} = threadOps
|
|
102
|
+
} = threadOps;
|
|
83
103
|
|
|
84
104
|
const plugins: ToolMap[string][] = [];
|
|
105
|
+
let destroySubagentSandboxes: (() => Promise<void>) | undefined;
|
|
85
106
|
if (subagents) {
|
|
86
|
-
const
|
|
87
|
-
if (
|
|
107
|
+
const result = buildSubagentRegistration(subagents);
|
|
108
|
+
if (result) {
|
|
109
|
+
plugins.push(result.registration);
|
|
110
|
+
destroySubagentSandboxes = result.destroySubagentSandboxes;
|
|
111
|
+
}
|
|
88
112
|
}
|
|
89
113
|
if (skills) {
|
|
90
114
|
const reg = buildSkillRegistration(skills);
|
|
@@ -120,12 +144,7 @@ export const createSession = async <T extends ToolMap, M = unknown>({
|
|
|
120
144
|
stateManager,
|
|
121
145
|
}: {
|
|
122
146
|
stateManager: AgentStateManager<TState>;
|
|
123
|
-
})
|
|
124
|
-
threadId: string;
|
|
125
|
-
finalMessage: M | null;
|
|
126
|
-
exitReason: SessionExitReason;
|
|
127
|
-
usage: ReturnType<AgentStateManager<TState>["getTotalUsage"]>;
|
|
128
|
-
}> => {
|
|
147
|
+
}) => {
|
|
129
148
|
setHandler(
|
|
130
149
|
defineUpdate<unknown, [MessageContent]>(`add${agentName}Message`),
|
|
131
150
|
async (message: MessageContent) => {
|
|
@@ -146,12 +165,43 @@ export const createSession = async <T extends ToolMap, M = unknown>({
|
|
|
146
165
|
}
|
|
147
166
|
);
|
|
148
167
|
|
|
149
|
-
// --- Sandbox lifecycle: create or inherit
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
168
|
+
// --- Sandbox lifecycle: create, continue, fork, or inherit ----------
|
|
169
|
+
const sandboxMode = sandboxInit?.mode;
|
|
170
|
+
let sandboxId: string | undefined;
|
|
171
|
+
let sandboxOwned = false;
|
|
172
|
+
|
|
173
|
+
if (sandboxMode === "inherit") {
|
|
174
|
+
sandboxId = (sandboxInit as { mode: "inherit"; sandboxId: string }).sandboxId;
|
|
175
|
+
if (!sandboxOps) {
|
|
176
|
+
throw ApplicationFailure.create({
|
|
177
|
+
message: "sandboxId provided but no sandboxOps — cannot manage sandbox lifecycle",
|
|
178
|
+
nonRetryable: true,
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
} else if (sandboxMode === "continue") {
|
|
182
|
+
if (!sandboxOps) {
|
|
183
|
+
throw ApplicationFailure.create({
|
|
184
|
+
message: "No sandboxOps provided — cannot continue sandbox",
|
|
185
|
+
nonRetryable: true,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
sandboxId = (sandboxInit as { mode: "continue"; sandboxId: string }).sandboxId;
|
|
189
|
+
sandboxOwned = true;
|
|
190
|
+
} else if (sandboxMode === "fork") {
|
|
191
|
+
if (!sandboxOps) {
|
|
192
|
+
throw ApplicationFailure.create({
|
|
193
|
+
message: "No sandboxOps provided — cannot fork sandbox",
|
|
194
|
+
nonRetryable: true,
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
sandboxId = await sandboxOps.forkSandbox(
|
|
198
|
+
(sandboxInit as { mode: "fork"; sandboxId: string }).sandboxId
|
|
199
|
+
);
|
|
200
|
+
sandboxOwned = true;
|
|
201
|
+
} else if (sandboxOps) {
|
|
202
|
+
const result = await sandboxOps.createSandbox();
|
|
154
203
|
sandboxId = result.sandboxId;
|
|
204
|
+
sandboxOwned = true;
|
|
155
205
|
if (result.stateUpdate) {
|
|
156
206
|
stateManager.mergeUpdate(result.stateUpdate as Partial<TState>);
|
|
157
207
|
}
|
|
@@ -167,8 +217,11 @@ export const createSession = async <T extends ToolMap, M = unknown>({
|
|
|
167
217
|
|
|
168
218
|
const systemPrompt = stateManager.getSystemPrompt();
|
|
169
219
|
|
|
170
|
-
|
|
220
|
+
// --- Thread lifecycle: new, continue, or fork ----------------------
|
|
221
|
+
if (threadMode === "fork" && sourceThreadId) {
|
|
171
222
|
await forkThread(sourceThreadId, threadId);
|
|
223
|
+
} else if (threadMode === "continue") {
|
|
224
|
+
// "continue" — thread already exists, just append the new message
|
|
172
225
|
} else {
|
|
173
226
|
if (appendSystemPrompt) {
|
|
174
227
|
if (!systemPrompt || systemPrompt.trim() === "") {
|
|
@@ -215,7 +268,8 @@ export const createSession = async <T extends ToolMap, M = unknown>({
|
|
|
215
268
|
finalMessage: message,
|
|
216
269
|
exitReason,
|
|
217
270
|
usage: stateManager.getTotalUsage(),
|
|
218
|
-
|
|
271
|
+
sandboxId,
|
|
272
|
+
} as Awaited<ReturnType<ZeitlichSession<M, boolean>["runSession"]>>;
|
|
219
273
|
}
|
|
220
274
|
|
|
221
275
|
const parsedToolCalls: ParsedToolCallUnion<T>[] = [];
|
|
@@ -271,8 +325,22 @@ export const createSession = async <T extends ToolMap, M = unknown>({
|
|
|
271
325
|
} finally {
|
|
272
326
|
await callSessionEnd(exitReason, stateManager.getTurns());
|
|
273
327
|
|
|
274
|
-
if (
|
|
275
|
-
|
|
328
|
+
if (sandboxOwned && sandboxId && sandboxOps) {
|
|
329
|
+
switch (sandboxShutdown) {
|
|
330
|
+
case "destroy":
|
|
331
|
+
await sandboxOps.destroySandbox(sandboxId);
|
|
332
|
+
break;
|
|
333
|
+
case "pause":
|
|
334
|
+
case "pause-until-parent-close":
|
|
335
|
+
await sandboxOps.pauseSandbox(sandboxId);
|
|
336
|
+
break;
|
|
337
|
+
case "keep":
|
|
338
|
+
break;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
if (destroySubagentSandboxes) {
|
|
343
|
+
await destroySubagentSandboxes();
|
|
276
344
|
}
|
|
277
345
|
}
|
|
278
346
|
|
|
@@ -281,64 +349,8 @@ export const createSession = async <T extends ToolMap, M = unknown>({
|
|
|
281
349
|
finalMessage: null,
|
|
282
350
|
exitReason,
|
|
283
351
|
usage: stateManager.getTotalUsage(),
|
|
284
|
-
|
|
352
|
+
sandboxId,
|
|
353
|
+
} as Awaited<ReturnType<ZeitlichSession<M, boolean>["runSession"]>>;
|
|
285
354
|
},
|
|
286
355
|
};
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
/**
|
|
290
|
-
* Proxy the adapter's thread operations as Temporal activities.
|
|
291
|
-
* Call this in workflow code to delegate thread operations to the
|
|
292
|
-
* adapter-provided activities registered on the worker.
|
|
293
|
-
*
|
|
294
|
-
* @example
|
|
295
|
-
* ```typescript
|
|
296
|
-
* const session = await createSession({
|
|
297
|
-
* threadOps: proxyDefaultThreadOps(),
|
|
298
|
-
* // ...
|
|
299
|
-
* });
|
|
300
|
-
* ```
|
|
301
|
-
*/
|
|
302
|
-
export function proxyDefaultThreadOps(
|
|
303
|
-
options?: Parameters<typeof proxyActivities>[0]
|
|
304
|
-
): ActivityInterfaceFor<ThreadOps> {
|
|
305
|
-
return proxyActivities<ThreadOps>(
|
|
306
|
-
options ?? {
|
|
307
|
-
startToCloseTimeout: "10s",
|
|
308
|
-
retry: {
|
|
309
|
-
maximumAttempts: 6,
|
|
310
|
-
initialInterval: "5s",
|
|
311
|
-
maximumInterval: "15m",
|
|
312
|
-
backoffCoefficient: 4,
|
|
313
|
-
},
|
|
314
|
-
}
|
|
315
|
-
);
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
/**
|
|
319
|
-
* Proxy sandbox lifecycle operations as Temporal activities.
|
|
320
|
-
* Call this in workflow code when the agent needs a sandbox.
|
|
321
|
-
*
|
|
322
|
-
* @example
|
|
323
|
-
* ```typescript
|
|
324
|
-
* const session = await createSession({
|
|
325
|
-
* sandbox: proxySandboxOps(),
|
|
326
|
-
* // ...
|
|
327
|
-
* });
|
|
328
|
-
* ```
|
|
329
|
-
*/
|
|
330
|
-
export function proxySandboxOps(
|
|
331
|
-
options?: Parameters<typeof proxyActivities>[0]
|
|
332
|
-
): SandboxOps {
|
|
333
|
-
return proxyActivities<SandboxOps>(
|
|
334
|
-
options ?? {
|
|
335
|
-
startToCloseTimeout: "30s",
|
|
336
|
-
retry: {
|
|
337
|
-
maximumAttempts: 3,
|
|
338
|
-
initialInterval: "2s",
|
|
339
|
-
maximumInterval: "30s",
|
|
340
|
-
backoffCoefficient: 2,
|
|
341
|
-
},
|
|
342
|
-
}
|
|
343
|
-
);
|
|
344
356
|
}
|
package/src/lib/session/types.ts
CHANGED
|
@@ -16,6 +16,7 @@ import type { SandboxOps } from "../sandbox/types";
|
|
|
16
16
|
import type { RunAgentActivity } from "../model/types";
|
|
17
17
|
import type { AgentStateManager, JsonSerializable } from "../state/types";
|
|
18
18
|
import type { ActivityInterfaceFor } from "@temporalio/workflow";
|
|
19
|
+
import type { ThreadInit, SandboxInit, SubagentSandboxShutdown } from "../lifecycle";
|
|
19
20
|
|
|
20
21
|
/**
|
|
21
22
|
* Thread operations required by a session.
|
|
@@ -42,14 +43,43 @@ export interface ThreadOps {
|
|
|
42
43
|
forkThread(sourceThreadId: string, targetThreadId: string): Promise<void>;
|
|
43
44
|
}
|
|
44
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Composes an adapter prefix + workflow scope for activity naming.
|
|
48
|
+
*
|
|
49
|
+
* The adapter prefix stays first (camelCase); the workflow scope is
|
|
50
|
+
* capitalised and appended. When `TScope` is empty the adapter prefix
|
|
51
|
+
* is used as-is.
|
|
52
|
+
*
|
|
53
|
+
* @example
|
|
54
|
+
* ```typescript
|
|
55
|
+
* ScopedPrefix<"codingAgent", "googleGenAI"> // "googleGenAICodingAgent"
|
|
56
|
+
* ScopedPrefix<"", "googleGenAI"> // "googleGenAI"
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export type ScopedPrefix<
|
|
60
|
+
TScope extends string,
|
|
61
|
+
TAdapter extends string,
|
|
62
|
+
> = TScope extends "" ? TAdapter : `${TAdapter}${Capitalize<TScope>}`;
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Maps generic {@link ThreadOps} method names to adapter-prefixed names.
|
|
66
|
+
*
|
|
67
|
+
* @example
|
|
68
|
+
* ```typescript
|
|
69
|
+
* type GoogleOps = PrefixedThreadOps<"googleGenAI">;
|
|
70
|
+
* // → { googleGenAIInitializeThread, googleGenAIAppendHumanMessage, … }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export type PrefixedThreadOps<TPrefix extends string> = {
|
|
74
|
+
[K in keyof ThreadOps as `${TPrefix}${Capitalize<K & string>}`]: ThreadOps[K];
|
|
75
|
+
};
|
|
76
|
+
|
|
45
77
|
/**
|
|
46
78
|
* Configuration for a Zeitlich agent session
|
|
47
79
|
*/
|
|
48
80
|
export interface SessionConfig<T extends ToolMap, M = unknown> {
|
|
49
81
|
/** The name of the agent, should be unique within the workflows */
|
|
50
82
|
agentName: string;
|
|
51
|
-
/** The thread ID to use for the session (defaults to a short generated ID) */
|
|
52
|
-
threadId?: string;
|
|
53
83
|
/** Metadata for the session */
|
|
54
84
|
metadata?: Record<string, unknown>;
|
|
55
85
|
/** Whether to append the system prompt as message to the thread */
|
|
@@ -59,7 +89,7 @@ export interface SessionConfig<T extends ToolMap, M = unknown> {
|
|
|
59
89
|
/** Workflow-specific runAgent activity (with tools pre-bound) */
|
|
60
90
|
runAgent: RunAgentActivity<M>;
|
|
61
91
|
/** Thread operations (initialize, append messages, parse tool calls) */
|
|
62
|
-
threadOps
|
|
92
|
+
threadOps: ActivityInterfaceFor<ThreadOps>;
|
|
63
93
|
/** Tool router for processing tool calls (optional if agent has no tools) */
|
|
64
94
|
tools?: T;
|
|
65
95
|
/** Subagent configurations */
|
|
@@ -75,27 +105,67 @@ export interface SessionConfig<T extends ToolMap, M = unknown> {
|
|
|
75
105
|
* Returns MessageContent array for the initial HumanMessage.
|
|
76
106
|
*/
|
|
77
107
|
buildContextMessage: () => MessageContent | Promise<MessageContent>;
|
|
78
|
-
/** When true, skip thread initialization and system prompt — append only the new human message to the existing thread. */
|
|
79
|
-
continueThread?: boolean;
|
|
80
108
|
/** How long to wait for input before cancelling the workflow */
|
|
81
109
|
waitForInputTimeout?: Duration;
|
|
110
|
+
|
|
111
|
+
// ---------------------------------------------------------------------------
|
|
112
|
+
// Thread lifecycle
|
|
113
|
+
// ---------------------------------------------------------------------------
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Thread initialization strategy (default: `{ mode: "new" }`).
|
|
117
|
+
*
|
|
118
|
+
* - `{ mode: "new" }` — start a fresh thread.
|
|
119
|
+
* - `{ mode: "new", threadId: "..." }` — start a fresh thread with a specific ID.
|
|
120
|
+
* - `{ mode: "continue", threadId: "..." }` — append to an existing thread in-place.
|
|
121
|
+
* - `{ mode: "fork", threadId: "..." }` — fork an existing thread and continue in the copy.
|
|
122
|
+
*/
|
|
123
|
+
thread?: ThreadInit;
|
|
124
|
+
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
// Sandbox lifecycle
|
|
127
|
+
// ---------------------------------------------------------------------------
|
|
128
|
+
|
|
82
129
|
/** Sandbox lifecycle operations (optional — omit for agents that don't need a sandbox) */
|
|
83
|
-
|
|
130
|
+
sandboxOps?: SandboxOps;
|
|
84
131
|
/**
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
132
|
+
* Sandbox initialization strategy.
|
|
133
|
+
*
|
|
134
|
+
* - `{ mode: "new" }` — create a fresh sandbox.
|
|
135
|
+
* - `{ mode: "continue", sandboxId: "..." }` — resume a paused sandbox (session owns it).
|
|
136
|
+
* - `{ mode: "fork", sandboxId: "..." }` — fork from an existing sandbox.
|
|
137
|
+
* - `{ mode: "inherit", sandboxId: "..." }` — use a parent's sandbox without ownership.
|
|
138
|
+
*
|
|
139
|
+
* When omitted and `sandboxOps` is provided, defaults to `{ mode: "new" }`.
|
|
88
140
|
*/
|
|
89
|
-
|
|
141
|
+
sandbox?: SandboxInit;
|
|
142
|
+
/**
|
|
143
|
+
* What to do with the sandbox when this session exits.
|
|
144
|
+
*
|
|
145
|
+
* Defaults to `"destroy"` when omitted.
|
|
146
|
+
* Has no effect when the sandbox is inherited (`sandbox.mode === "inherit"`).
|
|
147
|
+
*/
|
|
148
|
+
sandboxShutdown?: SubagentSandboxShutdown;
|
|
90
149
|
}
|
|
91
150
|
|
|
92
|
-
export
|
|
151
|
+
export type SessionResult<
|
|
152
|
+
M,
|
|
153
|
+
TState extends JsonSerializable<TState>,
|
|
154
|
+
HasSandbox extends boolean = boolean,
|
|
155
|
+
> = {
|
|
156
|
+
threadId: string;
|
|
157
|
+
finalMessage: M | null;
|
|
158
|
+
exitReason: SessionExitReason;
|
|
159
|
+
usage: ReturnType<AgentStateManager<TState>["getTotalUsage"]>;
|
|
160
|
+
} & (HasSandbox extends true
|
|
161
|
+
? { sandboxId: string }
|
|
162
|
+
: { sandboxId?: undefined });
|
|
163
|
+
|
|
164
|
+
export interface ZeitlichSession<
|
|
165
|
+
M = unknown,
|
|
166
|
+
HasSandbox extends boolean = boolean,
|
|
167
|
+
> {
|
|
93
168
|
runSession<T extends JsonSerializable<T>>(args: {
|
|
94
169
|
stateManager: AgentStateManager<T>;
|
|
95
|
-
}): Promise<
|
|
96
|
-
threadId: string;
|
|
97
|
-
finalMessage: M | null;
|
|
98
|
-
exitReason: SessionExitReason;
|
|
99
|
-
usage: ReturnType<AgentStateManager<T>["getTotalUsage"]>;
|
|
100
|
-
}>;
|
|
170
|
+
}): Promise<SessionResult<M, T, HasSandbox>>;
|
|
101
171
|
}
|
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
SubagentConfig,
|
|
4
4
|
SubagentDefinition,
|
|
5
5
|
SubagentHooks,
|
|
6
|
+
SubagentSandboxConfig,
|
|
6
7
|
SubagentWorkflow,
|
|
7
8
|
} from "./types";
|
|
8
9
|
import type { SubagentArgs } from "./tool";
|
|
@@ -19,8 +20,8 @@ import type { SubagentArgs } from "./tool";
|
|
|
19
20
|
*
|
|
20
21
|
* // With parent-specific overrides
|
|
21
22
|
* export const researcher = defineSubagent(researcherWorkflow, {
|
|
22
|
-
*
|
|
23
|
-
* sandbox: "own",
|
|
23
|
+
* thread: "fork",
|
|
24
|
+
* sandbox: { source: "own", shutdown: "pause" },
|
|
24
25
|
* hooks: {
|
|
25
26
|
* onPostExecution: ({ result }) => console.log(result),
|
|
26
27
|
* },
|
|
@@ -38,12 +39,12 @@ export function defineSubagent<
|
|
|
38
39
|
>(
|
|
39
40
|
definition: SubagentDefinition<TResult, TContext>,
|
|
40
41
|
overrides?: {
|
|
41
|
-
context?: TContext;
|
|
42
|
+
context?: TContext | (() => TContext);
|
|
42
43
|
hooks?: SubagentHooks<SubagentArgs, z.infer<TResult>>;
|
|
43
44
|
enabled?: boolean | (() => boolean);
|
|
44
45
|
taskQueue?: string;
|
|
45
|
-
|
|
46
|
-
sandbox?:
|
|
46
|
+
thread?: "new" | "fork" | "continue";
|
|
47
|
+
sandbox?: SubagentSandboxConfig;
|
|
47
48
|
},
|
|
48
49
|
): SubagentConfig<TResult> {
|
|
49
50
|
return {
|