zeitlich 0.2.37 → 0.2.39
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 +18 -0
- package/dist/{activities-Bb-nAjwQ.d.ts → activities-Bmu7XnaG.d.ts} +4 -4
- package/dist/{activities-vkI4_3CC.d.cts → activities-ByBFLvm2.d.cts} +4 -4
- package/dist/adapter-id-BB-mmrts.d.cts +17 -0
- package/dist/adapter-id-BB-mmrts.d.ts +17 -0
- package/dist/adapter-id-CMwVrVqv.d.cts +17 -0
- package/dist/adapter-id-CMwVrVqv.d.ts +17 -0
- package/dist/adapter-id-CbY2zeSt.d.cts +17 -0
- package/dist/adapter-id-CbY2zeSt.d.ts +17 -0
- package/dist/adapters/sandbox/bedrock/index.cjs +3 -3
- package/dist/adapters/sandbox/bedrock/index.cjs.map +1 -1
- package/dist/adapters/sandbox/bedrock/index.d.cts +6 -6
- package/dist/adapters/sandbox/bedrock/index.d.ts +6 -6
- package/dist/adapters/sandbox/bedrock/index.js +3 -3
- package/dist/adapters/sandbox/bedrock/index.js.map +1 -1
- package/dist/adapters/sandbox/bedrock/workflow.d.cts +2 -2
- package/dist/adapters/sandbox/bedrock/workflow.d.ts +2 -2
- package/dist/adapters/sandbox/daytona/index.cjs +3 -3
- package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
- package/dist/adapters/sandbox/daytona/index.d.cts +4 -4
- package/dist/adapters/sandbox/daytona/index.d.ts +4 -4
- package/dist/adapters/sandbox/daytona/index.js +3 -3
- package/dist/adapters/sandbox/daytona/index.js.map +1 -1
- package/dist/adapters/sandbox/daytona/workflow.d.cts +1 -1
- package/dist/adapters/sandbox/daytona/workflow.d.ts +1 -1
- package/dist/adapters/sandbox/e2b/index.cjs +26 -14
- package/dist/adapters/sandbox/e2b/index.cjs.map +1 -1
- package/dist/adapters/sandbox/e2b/index.d.cts +24 -4
- package/dist/adapters/sandbox/e2b/index.d.ts +24 -4
- package/dist/adapters/sandbox/e2b/index.js +26 -14
- package/dist/adapters/sandbox/e2b/index.js.map +1 -1
- package/dist/adapters/sandbox/e2b/workflow.d.cts +1 -1
- package/dist/adapters/sandbox/e2b/workflow.d.ts +1 -1
- package/dist/adapters/sandbox/inmemory/index.cjs +3 -3
- package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.d.cts +4 -4
- package/dist/adapters/sandbox/inmemory/index.d.ts +4 -4
- package/dist/adapters/sandbox/inmemory/index.js +3 -3
- package/dist/adapters/sandbox/inmemory/index.js.map +1 -1
- package/dist/adapters/sandbox/inmemory/workflow.d.cts +1 -1
- package/dist/adapters/sandbox/inmemory/workflow.d.ts +1 -1
- package/dist/adapters/thread/anthropic/index.cjs +150 -13
- package/dist/adapters/thread/anthropic/index.cjs.map +1 -1
- package/dist/adapters/thread/anthropic/index.d.cts +9 -8
- package/dist/adapters/thread/anthropic/index.d.ts +9 -8
- package/dist/adapters/thread/anthropic/index.js +150 -14
- package/dist/adapters/thread/anthropic/index.js.map +1 -1
- package/dist/adapters/thread/anthropic/workflow.cjs +9 -3
- package/dist/adapters/thread/anthropic/workflow.cjs.map +1 -1
- package/dist/adapters/thread/anthropic/workflow.d.cts +6 -5
- package/dist/adapters/thread/anthropic/workflow.d.ts +6 -5
- package/dist/adapters/thread/anthropic/workflow.js +9 -4
- package/dist/adapters/thread/anthropic/workflow.js.map +1 -1
- package/dist/adapters/thread/google-genai/index.cjs +154 -13
- package/dist/adapters/thread/google-genai/index.cjs.map +1 -1
- package/dist/adapters/thread/google-genai/index.d.cts +6 -5
- package/dist/adapters/thread/google-genai/index.d.ts +6 -5
- package/dist/adapters/thread/google-genai/index.js +154 -14
- package/dist/adapters/thread/google-genai/index.js.map +1 -1
- package/dist/adapters/thread/google-genai/workflow.cjs +9 -3
- package/dist/adapters/thread/google-genai/workflow.cjs.map +1 -1
- package/dist/adapters/thread/google-genai/workflow.d.cts +6 -5
- package/dist/adapters/thread/google-genai/workflow.d.ts +6 -5
- package/dist/adapters/thread/google-genai/workflow.js +9 -4
- package/dist/adapters/thread/google-genai/workflow.js.map +1 -1
- package/dist/adapters/thread/index.cjs +16 -0
- package/dist/adapters/thread/index.cjs.map +1 -0
- package/dist/adapters/thread/index.d.cts +34 -0
- package/dist/adapters/thread/index.d.ts +34 -0
- package/dist/adapters/thread/index.js +12 -0
- package/dist/adapters/thread/index.js.map +1 -0
- package/dist/adapters/thread/langchain/index.cjs +149 -14
- package/dist/adapters/thread/langchain/index.cjs.map +1 -1
- package/dist/adapters/thread/langchain/index.d.cts +9 -8
- package/dist/adapters/thread/langchain/index.d.ts +9 -8
- package/dist/adapters/thread/langchain/index.js +149 -15
- package/dist/adapters/thread/langchain/index.js.map +1 -1
- package/dist/adapters/thread/langchain/workflow.cjs +9 -3
- package/dist/adapters/thread/langchain/workflow.cjs.map +1 -1
- package/dist/adapters/thread/langchain/workflow.d.cts +6 -5
- package/dist/adapters/thread/langchain/workflow.d.ts +6 -5
- package/dist/adapters/thread/langchain/workflow.js +9 -4
- package/dist/adapters/thread/langchain/workflow.js.map +1 -1
- package/dist/index.cjs +367 -59
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -11
- package/dist/index.d.ts +11 -11
- package/dist/index.js +365 -61
- package/dist/index.js.map +1 -1
- package/dist/{proxy-DEtowJyd.d.cts → proxy-BAKzNGRq.d.cts} +1 -1
- package/dist/{proxy-0smGKvx8.d.ts → proxy-DO_MXbY4.d.ts} +1 -1
- package/dist/{thread-manager-C-C4pI2z.d.ts → thread-manager-CcRXasqs.d.ts} +2 -2
- package/dist/{thread-manager-D4vgzYrh.d.cts → thread-manager-ClwSaUnj.d.cts} +2 -2
- package/dist/{thread-manager-3fszQih4.d.ts → thread-manager-D-7lp1JK.d.ts} +2 -2
- package/dist/{thread-manager-CzYln2OC.d.cts → thread-manager-Y8Ucf0Tf.d.cts} +2 -2
- package/dist/{types-CPKDl-y_.d.ts → types-Bcbiq8iv.d.cts} +195 -22
- package/dist/{types-CNuWnvy9.d.ts → types-DAsQ21Rt.d.ts} +1 -1
- package/dist/{types-B37hKoWA.d.ts → types-DpHTX-iO.d.ts} +58 -1
- package/dist/{types-BO7Yju20.d.cts → types-Dt8-HBBT.d.ts} +195 -22
- package/dist/{types-D08CXPh8.d.cts → types-hFFi-Zd9.d.cts} +58 -1
- package/dist/{types-DWEUmYAJ.d.cts → types-lm8tMNJQ.d.cts} +1 -1
- package/dist/{types-tQL9njTu.d.cts → types-yx0LzPGn.d.cts} +21 -7
- package/dist/{types-tQL9njTu.d.ts → types-yx0LzPGn.d.ts} +21 -7
- package/dist/{workflow-CjXHbZZc.d.ts → workflow-Bmf9EtDW.d.ts} +83 -3
- package/dist/{workflow-Do_lzJpT.d.cts → workflow-Bx9utBwb.d.cts} +83 -3
- package/dist/workflow.cjs +266 -39
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +3 -3
- package/dist/workflow.d.ts +3 -3
- package/dist/workflow.js +264 -41
- package/dist/workflow.js.map +1 -1
- package/package.json +12 -2
- package/src/adapters/sandbox/bedrock/index.ts +12 -3
- package/src/adapters/sandbox/daytona/index.ts +12 -3
- package/src/adapters/sandbox/e2b/index.ts +36 -14
- package/src/adapters/sandbox/e2b/types.ts +16 -0
- package/src/adapters/sandbox/inmemory/index.ts +12 -3
- package/src/adapters/thread/adapter-id.test.ts +42 -0
- package/src/adapters/thread/anthropic/activities.ts +40 -5
- package/src/adapters/thread/anthropic/adapter-id.ts +16 -0
- package/src/adapters/thread/anthropic/fork-transform.test.ts +291 -0
- package/src/adapters/thread/anthropic/index.ts +3 -0
- package/src/adapters/thread/anthropic/model-invoker.ts +7 -1
- package/src/adapters/thread/anthropic/proxy.ts +3 -2
- package/src/adapters/thread/anthropic/thread-manager.ts +27 -1
- package/src/adapters/thread/google-genai/activities.ts +44 -5
- package/src/adapters/thread/google-genai/adapter-id.ts +16 -0
- package/src/adapters/thread/google-genai/fork-transform.test.ts +149 -0
- package/src/adapters/thread/google-genai/index.ts +3 -0
- package/src/adapters/thread/google-genai/model-invoker.ts +8 -2
- package/src/adapters/thread/google-genai/proxy.ts +3 -2
- package/src/adapters/thread/google-genai/thread-manager.ts +27 -1
- package/src/adapters/thread/index.ts +39 -0
- package/src/adapters/thread/langchain/activities.ts +40 -5
- package/src/adapters/thread/langchain/adapter-id.ts +16 -0
- package/src/adapters/thread/langchain/fork-transform.test.ts +142 -0
- package/src/adapters/thread/langchain/index.ts +3 -0
- package/src/adapters/thread/langchain/model-invoker.ts +7 -1
- package/src/adapters/thread/langchain/proxy.ts +3 -2
- package/src/adapters/thread/langchain/thread-manager.ts +27 -1
- package/src/lib/lifecycle.ts +14 -5
- package/src/lib/model/types.ts +7 -0
- package/src/lib/sandbox/manager.ts +26 -18
- package/src/lib/sandbox/types.ts +27 -7
- package/src/lib/session/session-edge-cases.integration.test.ts +336 -4
- package/src/lib/session/session.integration.test.ts +192 -2
- package/src/lib/session/session.ts +102 -8
- package/src/lib/session/types.ts +66 -3
- package/src/lib/state/index.ts +1 -0
- package/src/lib/state/manager.integration.test.ts +109 -0
- package/src/lib/state/manager.ts +38 -8
- package/src/lib/state/types.ts +25 -0
- package/src/lib/subagent/handler.ts +124 -11
- package/src/lib/subagent/index.ts +5 -1
- package/src/lib/subagent/subagent.integration.test.ts +628 -104
- package/src/lib/subagent/types.ts +63 -14
- package/src/lib/subagent/workflow.ts +29 -2
- package/src/lib/thread/index.ts +5 -0
- package/src/lib/thread/keys.test.ts +101 -0
- package/src/lib/thread/keys.ts +94 -0
- package/src/lib/thread/manager.test.ts +139 -0
- package/src/lib/thread/manager.ts +105 -9
- package/src/lib/thread/proxy.ts +3 -0
- package/src/lib/thread/types.ts +64 -1
- package/src/lib/tool-router/index.ts +2 -0
- package/src/lib/tool-router/router-edge-cases.integration.test.ts +92 -0
- package/src/lib/tool-router/router.integration.test.ts +12 -0
- package/src/lib/tool-router/router.ts +89 -16
- package/src/lib/tool-router/types.ts +42 -1
- package/src/lib/types.ts +12 -0
- package/src/workflow.ts +14 -1
- package/tsup.config.ts +1 -0
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import { describe, expect, it, vi } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
HumanMessage,
|
|
4
|
+
AIMessage,
|
|
5
|
+
type StoredMessage,
|
|
6
|
+
} from "@langchain/core/messages";
|
|
7
|
+
import { createLangChainThreadManager } from "./thread-manager";
|
|
8
|
+
|
|
9
|
+
function createStatefulRedis() {
|
|
10
|
+
const lists = new Map<string, string[]>();
|
|
11
|
+
const strings = new Map<string, string>();
|
|
12
|
+
|
|
13
|
+
return {
|
|
14
|
+
exists: vi.fn(async (...keys: string[]) =>
|
|
15
|
+
keys.reduce(
|
|
16
|
+
(acc, k) => acc + (lists.has(k) || strings.has(k) ? 1 : 0),
|
|
17
|
+
0
|
|
18
|
+
)
|
|
19
|
+
),
|
|
20
|
+
lrange: vi.fn(async (key: string, start: number, stop: number) => {
|
|
21
|
+
const list = lists.get(key) ?? [];
|
|
22
|
+
const end = stop === -1 ? list.length : stop + 1;
|
|
23
|
+
return list.slice(start, end);
|
|
24
|
+
}),
|
|
25
|
+
rpush: vi.fn(async (key: string, ...values: string[]) => {
|
|
26
|
+
const list = lists.get(key) ?? [];
|
|
27
|
+
list.push(...values);
|
|
28
|
+
lists.set(key, list);
|
|
29
|
+
return list.length;
|
|
30
|
+
}),
|
|
31
|
+
ltrim: vi.fn(async () => "OK"),
|
|
32
|
+
del: vi.fn(async (...keys: string[]) => {
|
|
33
|
+
let removed = 0;
|
|
34
|
+
for (const k of keys) {
|
|
35
|
+
if (lists.delete(k)) removed++;
|
|
36
|
+
if (strings.delete(k)) removed++;
|
|
37
|
+
}
|
|
38
|
+
return removed;
|
|
39
|
+
}),
|
|
40
|
+
set: vi.fn(async (key: string, value: string) => {
|
|
41
|
+
strings.set(key, value);
|
|
42
|
+
return "OK";
|
|
43
|
+
}),
|
|
44
|
+
get: vi.fn(async (key: string) => strings.get(key) ?? null),
|
|
45
|
+
expire: vi.fn(async () => 1),
|
|
46
|
+
llen: vi.fn(async (key: string) => (lists.get(key) ?? []).length),
|
|
47
|
+
eval: vi.fn(
|
|
48
|
+
async (_script: string, _numKeys: number, ...args: string[]) => {
|
|
49
|
+
const [dedupKey, listKey, , ...serialised] = args;
|
|
50
|
+
if (!dedupKey || !listKey) return 0;
|
|
51
|
+
if (strings.has(dedupKey)) return 0;
|
|
52
|
+
const list = lists.get(listKey) ?? [];
|
|
53
|
+
list.push(...serialised);
|
|
54
|
+
lists.set(listKey, list);
|
|
55
|
+
strings.set(dedupKey, "1");
|
|
56
|
+
return 1;
|
|
57
|
+
}
|
|
58
|
+
),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const humanMsg = new HumanMessage({ id: "msg-1", content: "Hello" }).toDict();
|
|
63
|
+
const aiMsg = new AIMessage({ id: "msg-2", content: "Hi there!" }).toDict();
|
|
64
|
+
const humanMsg2 = new HumanMessage({
|
|
65
|
+
id: "msg-3",
|
|
66
|
+
content: "Again please",
|
|
67
|
+
}).toDict();
|
|
68
|
+
|
|
69
|
+
async function seed(
|
|
70
|
+
redis: ReturnType<typeof createStatefulRedis>,
|
|
71
|
+
threadId: string,
|
|
72
|
+
messages: StoredMessage[]
|
|
73
|
+
): Promise<void> {
|
|
74
|
+
const tm = createLangChainThreadManager({
|
|
75
|
+
redis: redis as never,
|
|
76
|
+
threadId,
|
|
77
|
+
});
|
|
78
|
+
await tm.initialize();
|
|
79
|
+
await tm.append(messages);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
describe("LangChain fork + transform hooks", () => {
|
|
83
|
+
it("falls back to plain fork when no hooks are set", async () => {
|
|
84
|
+
const redis = createStatefulRedis();
|
|
85
|
+
await seed(redis, "src", [humanMsg, aiMsg]);
|
|
86
|
+
|
|
87
|
+
const tm = createLangChainThreadManager({
|
|
88
|
+
redis: redis as never,
|
|
89
|
+
threadId: "src",
|
|
90
|
+
});
|
|
91
|
+
const forked = await tm.fork("dst");
|
|
92
|
+
expect(await forked.load()).toEqual([humanMsg, aiMsg]);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("applies onForkPrepareThread then onForkTransform in order", async () => {
|
|
96
|
+
const redis = createStatefulRedis();
|
|
97
|
+
await seed(redis, "src", [humanMsg, aiMsg, humanMsg2]);
|
|
98
|
+
|
|
99
|
+
const order: string[] = [];
|
|
100
|
+
const tm = createLangChainThreadManager({
|
|
101
|
+
redis: redis as never,
|
|
102
|
+
threadId: "src",
|
|
103
|
+
hooks: {
|
|
104
|
+
onForkPrepareThread: async (messages) => {
|
|
105
|
+
order.push("prepare");
|
|
106
|
+
return messages.slice(0, -1);
|
|
107
|
+
},
|
|
108
|
+
onForkTransform: (msg, i) => {
|
|
109
|
+
order.push("transform");
|
|
110
|
+
return { ...msg, data: { ...msg.data, content: `[x${i}]` } };
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
const forked = await tm.fork("dst");
|
|
116
|
+
const loaded = await forked.load();
|
|
117
|
+
|
|
118
|
+
expect(order).toEqual(["prepare", "transform", "transform"]);
|
|
119
|
+
expect(loaded).toHaveLength(2);
|
|
120
|
+
expect(loaded[0]?.data.content).toBe("[x0]");
|
|
121
|
+
expect(loaded[1]?.data.content).toBe("[x1]");
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
it("keeps the source thread untouched", async () => {
|
|
125
|
+
const redis = createStatefulRedis();
|
|
126
|
+
await seed(redis, "src", [humanMsg, aiMsg]);
|
|
127
|
+
|
|
128
|
+
const tm = createLangChainThreadManager({
|
|
129
|
+
redis: redis as never,
|
|
130
|
+
threadId: "src",
|
|
131
|
+
hooks: {
|
|
132
|
+
onForkTransform: (msg) => ({
|
|
133
|
+
...msg,
|
|
134
|
+
data: { ...msg.data, content: "mutated" },
|
|
135
|
+
}),
|
|
136
|
+
},
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
await tm.fork("dst");
|
|
140
|
+
expect(await tm.load()).toEqual([humanMsg, aiMsg]);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
@@ -47,7 +47,8 @@ export function createLangChainModelInvoker<
|
|
|
47
47
|
return async function invokeLangChainModel(
|
|
48
48
|
config: ModelInvokerConfig
|
|
49
49
|
): Promise<AgentResponse<StoredMessage>> {
|
|
50
|
-
const { threadId, threadKey, agentName, state, metadata } =
|
|
50
|
+
const { threadId, threadKey, agentName, state, metadata, assistantMessageId } =
|
|
51
|
+
config;
|
|
51
52
|
const { heartbeat, signal } = getActivityContext();
|
|
52
53
|
|
|
53
54
|
const thread = createLangChainThreadManager({
|
|
@@ -58,6 +59,11 @@ export function createLangChainModelInvoker<
|
|
|
58
59
|
});
|
|
59
60
|
const runId = uuidv4();
|
|
60
61
|
|
|
62
|
+
// Truncate the thread starting at the id the assistant message
|
|
63
|
+
// will be stored under. No-op on the first attempt; on rewind
|
|
64
|
+
// retry / Temporal reset it wipes the prior attempt's assistant
|
|
65
|
+
// + tool results so the LLM sees the original pre-call state.
|
|
66
|
+
await thread.truncateFromId(assistantMessageId);
|
|
61
67
|
const { messages } = await thread.prepareForInvocation();
|
|
62
68
|
|
|
63
69
|
const heartbeatInterval = heartbeat
|
|
@@ -22,15 +22,16 @@ import { type ActivityInterfaceFor } from "@temporalio/workflow";
|
|
|
22
22
|
import type { ThreadOps } from "../../../lib/session/types";
|
|
23
23
|
import type { LangChainContent } from "./thread-manager";
|
|
24
24
|
import { createThreadOpsProxy } from "../../../lib/thread/proxy";
|
|
25
|
+
import { ADAPTER_ID } from "./adapter-id";
|
|
25
26
|
|
|
26
|
-
|
|
27
|
+
export { ADAPTER_ID, type AdapterId } from "./adapter-id";
|
|
27
28
|
|
|
28
29
|
export function proxyLangChainThreadOps(
|
|
29
30
|
scope?: string,
|
|
30
31
|
options?: Parameters<typeof createThreadOpsProxy>[2]
|
|
31
32
|
): ActivityInterfaceFor<ThreadOps<LangChainContent>> {
|
|
32
33
|
return createThreadOpsProxy(
|
|
33
|
-
|
|
34
|
+
ADAPTER_ID,
|
|
34
35
|
scope,
|
|
35
36
|
options
|
|
36
37
|
) as ActivityInterfaceFor<ThreadOps<LangChainContent>>;
|
|
@@ -143,5 +143,31 @@ export function createLangChainThreadManager(
|
|
|
143
143
|
},
|
|
144
144
|
};
|
|
145
145
|
|
|
146
|
-
|
|
146
|
+
const manager = Object.assign(base, helpers);
|
|
147
|
+
|
|
148
|
+
const originalFork = manager.fork.bind(manager);
|
|
149
|
+
manager.fork = async (
|
|
150
|
+
newThreadId: string
|
|
151
|
+
): Promise<LangChainThreadManager> => {
|
|
152
|
+
await originalFork(newThreadId);
|
|
153
|
+
const forked = createLangChainThreadManager({
|
|
154
|
+
...config,
|
|
155
|
+
threadId: newThreadId,
|
|
156
|
+
});
|
|
157
|
+
const { onForkPrepareThread, onForkTransform } = config.hooks ?? {};
|
|
158
|
+
if (!onForkPrepareThread && !onForkTransform) {
|
|
159
|
+
return forked;
|
|
160
|
+
}
|
|
161
|
+
let next = await forked.load();
|
|
162
|
+
if (onForkPrepareThread) {
|
|
163
|
+
next = await onForkPrepareThread(next);
|
|
164
|
+
}
|
|
165
|
+
if (onForkTransform) {
|
|
166
|
+
next = next.map((msg, i) => onForkTransform(msg, i, next));
|
|
167
|
+
}
|
|
168
|
+
await forked.replaceAll(next);
|
|
169
|
+
return forked;
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
return manager;
|
|
147
173
|
}
|
package/src/lib/lifecycle.ts
CHANGED
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
* - `"new"` — start a fresh thread (optionally specify its ID).
|
|
9
9
|
* - `"continue"` — append directly to an existing thread in-place.
|
|
10
10
|
* - `"fork"` — copy all messages from an existing thread into a new one and
|
|
11
|
-
* continue there.
|
|
11
|
+
* continue there. When the adapter has `onForkPrepareThread` and/or
|
|
12
|
+
* `onForkTransform` hooks configured, they are applied once to the forked
|
|
13
|
+
* thread before the session starts.
|
|
12
14
|
*/
|
|
13
15
|
export type ThreadInit =
|
|
14
16
|
| { mode: "new"; threadId?: string }
|
|
@@ -19,7 +21,7 @@ export type ThreadInit =
|
|
|
19
21
|
// Sandbox lifecycle
|
|
20
22
|
// ============================================================================
|
|
21
23
|
|
|
22
|
-
import type { SandboxSnapshot } from "./sandbox/types";
|
|
24
|
+
import type { SandboxCreateOptions, SandboxSnapshot } from "./sandbox/types";
|
|
23
25
|
|
|
24
26
|
/**
|
|
25
27
|
* Sandbox initialization strategy.
|
|
@@ -31,17 +33,24 @@ import type { SandboxSnapshot } from "./sandbox/types";
|
|
|
31
33
|
* Paused sandboxes are automatically resumed. The shutdown policy applies
|
|
32
34
|
* on exit.
|
|
33
35
|
* - `"fork"` — fork from an existing (or paused) sandbox; a new sandbox is
|
|
34
|
-
* created and owned by this session.
|
|
36
|
+
* created and owned by this session. `options` is an optional per-call
|
|
37
|
+
* override merged on top of the provider's static defaults.
|
|
35
38
|
* - `"from-snapshot"` — restore a fresh sandbox from a previously captured
|
|
36
39
|
* {@link SandboxSnapshot}. The new sandbox is owned by this session.
|
|
40
|
+
* `options` is an optional per-call override merged on top of the
|
|
41
|
+
* provider's static defaults.
|
|
37
42
|
* - `"inherit"` — use a sandbox owned by someone else (e.g. a parent agent).
|
|
38
43
|
* The session will **not** manage its lifecycle on exit.
|
|
39
44
|
*/
|
|
40
45
|
export type SandboxInit =
|
|
41
46
|
| { mode: "new"; ctx?: unknown }
|
|
42
47
|
| { mode: "continue"; sandboxId: string }
|
|
43
|
-
| { mode: "fork"; sandboxId: string }
|
|
44
|
-
| {
|
|
48
|
+
| { mode: "fork"; sandboxId: string; options?: SandboxCreateOptions }
|
|
49
|
+
| {
|
|
50
|
+
mode: "from-snapshot";
|
|
51
|
+
snapshot: SandboxSnapshot;
|
|
52
|
+
options?: SandboxCreateOptions;
|
|
53
|
+
}
|
|
45
54
|
| {
|
|
46
55
|
mode: "inherit";
|
|
47
56
|
sandboxId: string;
|
package/src/lib/model/types.ts
CHANGED
|
@@ -29,6 +29,13 @@ export interface ModelInvokerConfig {
|
|
|
29
29
|
agentName: string;
|
|
30
30
|
state: BaseAgentState;
|
|
31
31
|
metadata?: Record<string, unknown>;
|
|
32
|
+
/**
|
|
33
|
+
* The id the assistant message produced by this call will be stored
|
|
34
|
+
* under. Invokers truncate the thread from this id on entry so that
|
|
35
|
+
* rewind retries and Temporal workflow resets restore the pre-call
|
|
36
|
+
* state before re-invoking the LLM. See {@link RunAgentConfig}.
|
|
37
|
+
*/
|
|
38
|
+
assistantMessageId: string;
|
|
32
39
|
}
|
|
33
40
|
|
|
34
41
|
/**
|
|
@@ -120,9 +120,7 @@ export class SandboxManager<
|
|
|
120
120
|
async create(
|
|
121
121
|
options?: TOptions,
|
|
122
122
|
ctx?: TCtx
|
|
123
|
-
): Promise<{
|
|
124
|
-
sandboxId: string;
|
|
125
|
-
} | null> {
|
|
123
|
+
): Promise<{ sandboxId: string } | null> {
|
|
126
124
|
let providerOptions = options;
|
|
127
125
|
|
|
128
126
|
if (this.hooks.onPreCreate) {
|
|
@@ -175,12 +173,15 @@ export class SandboxManager<
|
|
|
175
173
|
await this.provider.resume(id);
|
|
176
174
|
}
|
|
177
175
|
|
|
178
|
-
async snapshot(id: string): Promise<SandboxSnapshot> {
|
|
179
|
-
return this.provider.snapshot(id);
|
|
176
|
+
async snapshot(id: string, options?: TOptions): Promise<SandboxSnapshot> {
|
|
177
|
+
return this.provider.snapshot(id, options);
|
|
180
178
|
}
|
|
181
179
|
|
|
182
|
-
async restore(
|
|
183
|
-
|
|
180
|
+
async restore(
|
|
181
|
+
snapshot: SandboxSnapshot,
|
|
182
|
+
options?: TOptions
|
|
183
|
+
): Promise<string> {
|
|
184
|
+
const sandbox = await this.provider.restore(snapshot, options);
|
|
184
185
|
return sandbox.id;
|
|
185
186
|
}
|
|
186
187
|
|
|
@@ -188,8 +189,8 @@ export class SandboxManager<
|
|
|
188
189
|
await this.provider.deleteSnapshot(snapshot);
|
|
189
190
|
}
|
|
190
191
|
|
|
191
|
-
async fork(sandboxId: string): Promise<string> {
|
|
192
|
-
const sandbox = await this.provider.fork(sandboxId);
|
|
192
|
+
async fork(sandboxId: string, options?: TOptions): Promise<string> {
|
|
193
|
+
const sandbox = await this.provider.fork(sandboxId, options);
|
|
193
194
|
return sandbox.id;
|
|
194
195
|
}
|
|
195
196
|
|
|
@@ -221,9 +222,7 @@ export class SandboxManager<
|
|
|
221
222
|
createSandbox: async (
|
|
222
223
|
options?: TOptions,
|
|
223
224
|
ctx?: TCtx
|
|
224
|
-
): Promise<{
|
|
225
|
-
sandboxId: string;
|
|
226
|
-
} | null> => {
|
|
225
|
+
): Promise<{ sandboxId: string } | null> => {
|
|
227
226
|
return this.create(options, ctx);
|
|
228
227
|
},
|
|
229
228
|
destroySandbox: async (sandboxId: string): Promise<void> => {
|
|
@@ -238,19 +237,28 @@ export class SandboxManager<
|
|
|
238
237
|
resumeSandbox: async (sandboxId: string): Promise<void> => {
|
|
239
238
|
await this.resume(sandboxId);
|
|
240
239
|
},
|
|
241
|
-
snapshotSandbox: async (
|
|
242
|
-
|
|
240
|
+
snapshotSandbox: async (
|
|
241
|
+
sandboxId: string,
|
|
242
|
+
options?: TOptions
|
|
243
|
+
): Promise<SandboxSnapshot> => {
|
|
244
|
+
return this.snapshot(sandboxId, options);
|
|
243
245
|
},
|
|
244
|
-
restoreSandbox: async (
|
|
245
|
-
|
|
246
|
+
restoreSandbox: async (
|
|
247
|
+
snapshot: SandboxSnapshot,
|
|
248
|
+
options?: TOptions
|
|
249
|
+
): Promise<string> => {
|
|
250
|
+
return this.restore(snapshot, options);
|
|
246
251
|
},
|
|
247
252
|
deleteSandboxSnapshot: async (
|
|
248
253
|
snapshot: SandboxSnapshot
|
|
249
254
|
): Promise<void> => {
|
|
250
255
|
await this.deleteSnapshot(snapshot);
|
|
251
256
|
},
|
|
252
|
-
forkSandbox: async (
|
|
253
|
-
|
|
257
|
+
forkSandbox: async (
|
|
258
|
+
sandboxId: string,
|
|
259
|
+
options?: TOptions
|
|
260
|
+
): Promise<string> => {
|
|
261
|
+
return this.fork(sandboxId, options);
|
|
254
262
|
},
|
|
255
263
|
};
|
|
256
264
|
const cap = (s: string): string => s.charAt(0).toUpperCase() + s.slice(1);
|
package/src/lib/sandbox/types.ts
CHANGED
|
@@ -158,11 +158,23 @@ export interface SandboxProvider<
|
|
|
158
158
|
pause(sandboxId: string, ttlSeconds?: number): Promise<void>;
|
|
159
159
|
/** Resume a paused sandbox. No-op if already running. */
|
|
160
160
|
resume(sandboxId: string): Promise<void>;
|
|
161
|
-
|
|
162
|
-
|
|
161
|
+
/**
|
|
162
|
+
* Capture a snapshot of a running sandbox. `options` is a per-call override
|
|
163
|
+
* merged on top of the provider's static defaults.
|
|
164
|
+
*/
|
|
165
|
+
snapshot(sandboxId: string, options?: TOptions): Promise<SandboxSnapshot>;
|
|
166
|
+
/**
|
|
167
|
+
* Restore a sandbox from a snapshot. `options` is a per-call override
|
|
168
|
+
* merged on top of the provider's static defaults.
|
|
169
|
+
*/
|
|
170
|
+
restore(snapshot: SandboxSnapshot, options?: TOptions): Promise<Sandbox>;
|
|
163
171
|
/** Delete a previously captured snapshot. No-op if already deleted. */
|
|
164
172
|
deleteSnapshot(snapshot: SandboxSnapshot): Promise<void>;
|
|
165
|
-
|
|
173
|
+
/**
|
|
174
|
+
* Fork a running sandbox into a new one. `options` is a per-call override
|
|
175
|
+
* merged on top of the provider's static defaults.
|
|
176
|
+
*/
|
|
177
|
+
fork(sandboxId: string, options?: TOptions): Promise<Sandbox>;
|
|
166
178
|
}
|
|
167
179
|
|
|
168
180
|
// ============================================================================
|
|
@@ -181,12 +193,20 @@ export interface SandboxOps<
|
|
|
181
193
|
pauseSandbox(sandboxId: string): Promise<void>;
|
|
182
194
|
/** Resume a paused sandbox. No-op if already running. */
|
|
183
195
|
resumeSandbox(sandboxId: string): Promise<void>;
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
196
|
+
/** Capture a snapshot. `options` is a per-call override merged on top of provider defaults. */
|
|
197
|
+
snapshotSandbox(
|
|
198
|
+
sandboxId: string,
|
|
199
|
+
options?: TOptions
|
|
200
|
+
): Promise<SandboxSnapshot>;
|
|
201
|
+
/** Create a fresh sandbox from a snapshot. `options` is a per-call override merged on top of provider defaults. */
|
|
202
|
+
restoreSandbox(
|
|
203
|
+
snapshot: SandboxSnapshot,
|
|
204
|
+
options?: TOptions
|
|
205
|
+
): Promise<string>;
|
|
187
206
|
/** Delete a previously captured snapshot. No-op if already deleted. */
|
|
188
207
|
deleteSandboxSnapshot(snapshot: SandboxSnapshot): Promise<void>;
|
|
189
|
-
|
|
208
|
+
/** Fork a running sandbox. `options` is a per-call override merged on top of provider defaults. */
|
|
209
|
+
forkSandbox(sandboxId: string, options?: TOptions): Promise<string>;
|
|
190
210
|
}
|
|
191
211
|
|
|
192
212
|
/**
|