zeitlich 0.2.36 → 0.2.37
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 +146 -92
- package/dist/{activities-BVI2lTwr.d.ts → activities-Bb-nAjwQ.d.ts} +2 -2
- package/dist/{activities-hd4aNnZE.d.cts → activities-vkI4_3CC.d.cts} +2 -2
- package/dist/adapters/sandbox/bedrock/index.cjs +14 -11
- package/dist/adapters/sandbox/bedrock/index.cjs.map +1 -1
- package/dist/adapters/sandbox/bedrock/index.d.cts +4 -3
- package/dist/adapters/sandbox/bedrock/index.d.ts +4 -3
- package/dist/adapters/sandbox/bedrock/index.js +14 -11
- package/dist/adapters/sandbox/bedrock/index.js.map +1 -1
- package/dist/adapters/sandbox/bedrock/workflow.cjs +2 -0
- package/dist/adapters/sandbox/bedrock/workflow.cjs.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/bedrock/workflow.js +2 -0
- package/dist/adapters/sandbox/bedrock/workflow.js.map +1 -1
- package/dist/adapters/sandbox/daytona/index.cjs +8 -0
- package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
- package/dist/adapters/sandbox/daytona/index.d.cts +2 -1
- package/dist/adapters/sandbox/daytona/index.d.ts +2 -1
- package/dist/adapters/sandbox/daytona/index.js +8 -0
- package/dist/adapters/sandbox/daytona/index.js.map +1 -1
- package/dist/adapters/sandbox/daytona/workflow.cjs +2 -0
- package/dist/adapters/sandbox/daytona/workflow.cjs.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/daytona/workflow.js +2 -0
- package/dist/adapters/sandbox/daytona/workflow.js.map +1 -1
- package/dist/adapters/sandbox/e2b/index.cjs +59 -10
- package/dist/adapters/sandbox/e2b/index.cjs.map +1 -1
- package/dist/adapters/sandbox/e2b/index.d.cts +5 -3
- package/dist/adapters/sandbox/e2b/index.d.ts +5 -3
- package/dist/adapters/sandbox/e2b/index.js +59 -10
- package/dist/adapters/sandbox/e2b/index.js.map +1 -1
- package/dist/adapters/sandbox/e2b/workflow.cjs +2 -0
- package/dist/adapters/sandbox/e2b/workflow.cjs.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/e2b/workflow.js +2 -0
- package/dist/adapters/sandbox/e2b/workflow.js.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.cjs +5 -0
- package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.d.cts +2 -1
- package/dist/adapters/sandbox/inmemory/index.d.ts +2 -1
- package/dist/adapters/sandbox/inmemory/index.js +5 -0
- package/dist/adapters/sandbox/inmemory/index.js.map +1 -1
- package/dist/adapters/sandbox/inmemory/workflow.cjs +2 -0
- package/dist/adapters/sandbox/inmemory/workflow.cjs.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/sandbox/inmemory/workflow.js +2 -0
- package/dist/adapters/sandbox/inmemory/workflow.js.map +1 -1
- package/dist/adapters/thread/anthropic/index.cjs +71 -36
- 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 +71 -36
- package/dist/adapters/thread/anthropic/index.js.map +1 -1
- package/dist/adapters/thread/anthropic/workflow.cjs +5 -1
- package/dist/adapters/thread/anthropic/workflow.cjs.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/anthropic/workflow.js +5 -1
- package/dist/adapters/thread/anthropic/workflow.js.map +1 -1
- package/dist/adapters/thread/google-genai/index.cjs +50 -25
- 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 +50 -25
- package/dist/adapters/thread/google-genai/index.js.map +1 -1
- package/dist/adapters/thread/google-genai/workflow.cjs +5 -1
- package/dist/adapters/thread/google-genai/workflow.cjs.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/google-genai/workflow.js +5 -1
- package/dist/adapters/thread/google-genai/workflow.js.map +1 -1
- package/dist/adapters/thread/langchain/index.cjs +34 -7
- 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 +34 -7
- package/dist/adapters/thread/langchain/index.js.map +1 -1
- package/dist/adapters/thread/langchain/workflow.cjs +5 -1
- package/dist/adapters/thread/langchain/workflow.cjs.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/adapters/thread/langchain/workflow.js +5 -1
- package/dist/adapters/thread/langchain/workflow.js.map +1 -1
- package/dist/index.cjs +206 -120
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +17 -11
- package/dist/index.d.ts +17 -11
- package/dist/index.js +207 -121
- package/dist/index.js.map +1 -1
- package/dist/{proxy-BjdFGPTm.d.ts → proxy-0smGKvx8.d.ts} +1 -1
- package/dist/{proxy-7RnVaPdJ.d.cts → proxy-DEtowJyd.d.cts} +1 -1
- package/dist/{thread-manager-DjN5JYul.d.ts → thread-manager-3fszQih4.d.ts} +2 -2
- package/dist/{thread-manager-CbpiGq1L.d.ts → thread-manager-C-C4pI2z.d.ts} +2 -2
- package/dist/{thread-manager-BBzNgQWH.d.cts → thread-manager-CzYln2OC.d.cts} +2 -2
- package/dist/{thread-manager-DzXm9eeI.d.cts → thread-manager-D4vgzYrh.d.cts} +2 -2
- package/dist/{types-yiXmqedU.d.ts → types-B37hKoWA.d.ts} +1 -1
- package/dist/{types-DQ1l_gXL.d.cts → types-BO7Yju20.d.cts} +63 -14
- package/dist/{types-wiGLvxWf.d.ts → types-CNuWnvy9.d.ts} +1 -1
- package/dist/{types-CADc5V_P.d.ts → types-CPKDl-y_.d.ts} +63 -14
- package/dist/{types-Mc_4BCfT.d.cts → types-D08CXPh8.d.cts} +1 -1
- package/dist/{types-CBH54cwr.d.cts → types-DWEUmYAJ.d.cts} +1 -1
- package/dist/{types-DxCpFNv_.d.cts → types-tQL9njTu.d.cts} +25 -0
- package/dist/{types-DxCpFNv_.d.ts → types-tQL9njTu.d.ts} +25 -0
- package/dist/{workflow-P2pTSfKu.d.ts → workflow-CjXHbZZc.d.ts} +2 -2
- package/dist/{workflow-DhtWRovz.d.cts → workflow-Do_lzJpT.d.cts} +2 -2
- package/dist/workflow.cjs +182 -114
- 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 +183 -115
- package/dist/workflow.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/sandbox/bedrock/filesystem.ts +6 -12
- package/src/adapters/sandbox/bedrock/index.ts +10 -8
- package/src/adapters/sandbox/bedrock/proxy.ts +2 -0
- package/src/adapters/sandbox/daytona/index.ts +6 -0
- package/src/adapters/sandbox/daytona/proxy.ts +2 -0
- package/src/adapters/sandbox/e2b/filesystem.ts +5 -4
- package/src/adapters/sandbox/e2b/index.ts +63 -12
- package/src/adapters/sandbox/e2b/proxy.ts +2 -0
- package/src/adapters/sandbox/inmemory/index.ts +5 -0
- package/src/adapters/sandbox/inmemory/proxy.ts +2 -0
- package/src/adapters/thread/anthropic/activities.ts +49 -26
- package/src/adapters/thread/anthropic/model-invoker.ts +15 -6
- package/src/adapters/thread/anthropic/proxy.ts +6 -2
- package/src/adapters/thread/anthropic/thread-manager.test.ts +26 -7
- package/src/adapters/thread/anthropic/thread-manager.ts +60 -46
- package/src/adapters/thread/google-genai/activities.ts +7 -2
- package/src/adapters/thread/google-genai/model-invoker.ts +26 -8
- package/src/adapters/thread/google-genai/proxy.ts +6 -2
- package/src/adapters/thread/google-genai/thread-manager.test.ts +13 -3
- package/src/adapters/thread/google-genai/thread-manager.ts +54 -33
- package/src/adapters/thread/langchain/activities.ts +46 -24
- package/src/adapters/thread/langchain/hooks.test.ts +36 -49
- package/src/adapters/thread/langchain/hooks.ts +18 -5
- package/src/adapters/thread/langchain/model-invoker.ts +3 -3
- package/src/adapters/thread/langchain/proxy.ts +6 -2
- package/src/adapters/thread/langchain/thread-manager.test.ts +5 -1
- package/src/adapters/thread/langchain/thread-manager.ts +20 -9
- package/src/index.ts +4 -1
- package/src/lib/activity.ts +16 -6
- package/src/lib/hooks/types.ts +6 -6
- package/src/lib/lifecycle.ts +9 -1
- package/src/lib/model/proxy.ts +2 -2
- package/src/lib/observability/hooks.ts +4 -5
- package/src/lib/observability/index.ts +1 -4
- package/src/lib/sandbox/manager.ts +21 -4
- package/src/lib/sandbox/node-fs.ts +3 -6
- package/src/lib/sandbox/sandbox.test.ts +36 -3
- package/src/lib/sandbox/tree.integration.test.ts +10 -3
- package/src/lib/sandbox/types.ts +35 -1
- package/src/lib/session/session-edge-cases.integration.test.ts +51 -13
- package/src/lib/session/session.integration.test.ts +139 -0
- package/src/lib/session/session.ts +50 -19
- package/src/lib/session/types.ts +13 -5
- package/src/lib/skills/fs-provider.ts +12 -8
- package/src/lib/skills/handler.ts +1 -1
- package/src/lib/skills/parse.ts +3 -1
- package/src/lib/skills/register.ts +1 -3
- package/src/lib/skills/skills.integration.test.ts +25 -15
- package/src/lib/state/manager.integration.test.ts +12 -2
- package/src/lib/subagent/define.ts +1 -1
- package/src/lib/subagent/handler.ts +186 -71
- package/src/lib/subagent/index.ts +1 -5
- package/src/lib/subagent/register.ts +3 -2
- package/src/lib/subagent/signals.ts +1 -10
- package/src/lib/subagent/subagent.integration.test.ts +438 -156
- package/src/lib/subagent/tool.ts +4 -3
- package/src/lib/subagent/types.ts +50 -20
- package/src/lib/subagent/workflow.ts +9 -49
- package/src/lib/thread/id.test.ts +1 -1
- package/src/lib/thread/id.ts +1 -2
- package/src/lib/thread/proxy.ts +3 -4
- package/src/lib/thread/types.ts +11 -3
- package/src/lib/tool-router/index.ts +1 -5
- package/src/lib/tool-router/router-edge-cases.integration.test.ts +1 -1
- package/src/lib/tool-router/router.ts +3 -2
- package/src/lib/tool-router/types.ts +11 -3
- package/src/lib/tool-router/with-sandbox.ts +19 -5
- package/src/lib/virtual-fs/filesystem.ts +1 -1
- package/src/lib/virtual-fs/index.ts +5 -1
- package/src/lib/virtual-fs/mutations.ts +2 -4
- package/src/lib/virtual-fs/queries.ts +9 -5
- package/src/lib/virtual-fs/types.ts +4 -1
- package/src/lib/virtual-fs/virtual-fs.test.ts +9 -11
- package/src/lib/workflow.test.ts +7 -4
- package/src/lib/workflow.ts +1 -5
- package/src/tools/ask-user-question/tool.ts +1 -3
- package/src/tools/glob/handler.ts +1 -4
- package/src/tools/task-get/handler.ts +4 -5
- package/src/tools/task-list/handler.ts +1 -4
- package/src/tools/task-update/handler.ts +4 -5
- package/src/workflow.ts +20 -7
- package/tsup.config.ts +9 -6
- package/src/lib/.env +0 -1
- package/src/tools/bash/.env +0 -1
|
@@ -3,11 +3,14 @@ import { HumanMessage, AIMessage } from "@langchain/core/messages";
|
|
|
3
3
|
import type { BaseMessage } from "@langchain/core/messages";
|
|
4
4
|
import { appendCachePoint } from "./hooks";
|
|
5
5
|
|
|
6
|
-
const cacheBlock = {
|
|
6
|
+
const cacheBlock = {
|
|
7
|
+
type: "cache_control" as const,
|
|
8
|
+
cache_control: { type: "ephemeral" as const },
|
|
9
|
+
};
|
|
7
10
|
|
|
8
11
|
function applyHook(
|
|
9
12
|
messages: BaseMessage[],
|
|
10
|
-
hook: ReturnType<typeof appendCachePoint
|
|
13
|
+
hook: ReturnType<typeof appendCachePoint>
|
|
11
14
|
): BaseMessage[] {
|
|
12
15
|
return messages.map((m, i, arr) => hook(m, i, arr));
|
|
13
16
|
}
|
|
@@ -47,29 +50,25 @@ describe("appendCachePoint", () => {
|
|
|
47
50
|
it("deduplicates within the last message", () => {
|
|
48
51
|
const messages: BaseMessage[] = [
|
|
49
52
|
new HumanMessage({
|
|
50
|
-
content: [
|
|
51
|
-
{ type: "text", text: "hello" },
|
|
52
|
-
cacheBlock,
|
|
53
|
-
],
|
|
53
|
+
content: [{ type: "text", text: "hello" }, cacheBlock],
|
|
54
54
|
}),
|
|
55
55
|
];
|
|
56
56
|
const hook = appendCachePoint(cacheBlock);
|
|
57
57
|
const result = applyHook(messages, hook);
|
|
58
58
|
|
|
59
|
-
const blocks = (
|
|
60
|
-
(
|
|
61
|
-
);
|
|
59
|
+
const blocks = (
|
|
60
|
+
messageAt(result, 0).content as Array<{ type: string }>
|
|
61
|
+
).filter((b) => b.type === cacheBlock.type);
|
|
62
62
|
expect(blocks).toHaveLength(1);
|
|
63
63
|
});
|
|
64
64
|
|
|
65
65
|
it("strips old cache blocks when total would exceed maxBlocks", () => {
|
|
66
|
-
const messages: BaseMessage[] = Array.from(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
cacheBlock,
|
|
71
|
-
|
|
72
|
-
}),
|
|
66
|
+
const messages: BaseMessage[] = Array.from(
|
|
67
|
+
{ length: 6 },
|
|
68
|
+
(_, i) =>
|
|
69
|
+
new HumanMessage({
|
|
70
|
+
content: [{ type: "text", text: `msg ${i}` }, cacheBlock],
|
|
71
|
+
})
|
|
73
72
|
);
|
|
74
73
|
const hook = appendCachePoint(cacheBlock, { maxBlocks: 4 });
|
|
75
74
|
const result = applyHook(messages, hook);
|
|
@@ -78,13 +77,12 @@ describe("appendCachePoint", () => {
|
|
|
78
77
|
});
|
|
79
78
|
|
|
80
79
|
it("keeps the most recent cache blocks", () => {
|
|
81
|
-
const messages: BaseMessage[] = Array.from(
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
cacheBlock,
|
|
86
|
-
|
|
87
|
-
}),
|
|
80
|
+
const messages: BaseMessage[] = Array.from(
|
|
81
|
+
{ length: 6 },
|
|
82
|
+
(_, i) =>
|
|
83
|
+
new HumanMessage({
|
|
84
|
+
content: [{ type: "text", text: `msg ${i}` }, cacheBlock],
|
|
85
|
+
})
|
|
88
86
|
);
|
|
89
87
|
const hook = appendCachePoint(cacheBlock, { maxBlocks: 4 });
|
|
90
88
|
const result = applyHook(messages, hook);
|
|
@@ -101,13 +99,12 @@ describe("appendCachePoint", () => {
|
|
|
101
99
|
});
|
|
102
100
|
|
|
103
101
|
it("respects a custom maxBlocks value", () => {
|
|
104
|
-
const messages: BaseMessage[] = Array.from(
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
cacheBlock,
|
|
109
|
-
|
|
110
|
-
}),
|
|
102
|
+
const messages: BaseMessage[] = Array.from(
|
|
103
|
+
{ length: 5 },
|
|
104
|
+
(_, i) =>
|
|
105
|
+
new HumanMessage({
|
|
106
|
+
content: [{ type: "text", text: `msg ${i}` }, cacheBlock],
|
|
107
|
+
})
|
|
111
108
|
);
|
|
112
109
|
const hook = appendCachePoint(cacheBlock, { maxBlocks: 2 });
|
|
113
110
|
const result = applyHook(messages, hook);
|
|
@@ -141,13 +138,12 @@ describe("appendCachePoint", () => {
|
|
|
141
138
|
});
|
|
142
139
|
|
|
143
140
|
it("defaults maxBlocks to 4", () => {
|
|
144
|
-
const messages: BaseMessage[] = Array.from(
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
cacheBlock,
|
|
149
|
-
|
|
150
|
-
}),
|
|
141
|
+
const messages: BaseMessage[] = Array.from(
|
|
142
|
+
{ length: 8 },
|
|
143
|
+
(_, i) =>
|
|
144
|
+
new HumanMessage({
|
|
145
|
+
content: [{ type: "text", text: `msg ${i}` }, cacheBlock],
|
|
146
|
+
})
|
|
151
147
|
);
|
|
152
148
|
const hook = appendCachePoint(cacheBlock);
|
|
153
149
|
const result = applyHook(messages, hook);
|
|
@@ -165,22 +161,13 @@ describe("appendCachePoint", () => {
|
|
|
165
161
|
],
|
|
166
162
|
}),
|
|
167
163
|
new HumanMessage({
|
|
168
|
-
content: [
|
|
169
|
-
{ type: "text", text: "msg 1" },
|
|
170
|
-
cacheBlock,
|
|
171
|
-
],
|
|
164
|
+
content: [{ type: "text", text: "msg 1" }, cacheBlock],
|
|
172
165
|
}),
|
|
173
166
|
new HumanMessage({
|
|
174
|
-
content: [
|
|
175
|
-
{ type: "text", text: "msg 2" },
|
|
176
|
-
cacheBlock,
|
|
177
|
-
],
|
|
167
|
+
content: [{ type: "text", text: "msg 2" }, cacheBlock],
|
|
178
168
|
}),
|
|
179
169
|
new HumanMessage({
|
|
180
|
-
content: [
|
|
181
|
-
{ type: "text", text: "msg 3" },
|
|
182
|
-
cacheBlock,
|
|
183
|
-
],
|
|
170
|
+
content: [{ type: "text", text: "msg 3" }, cacheBlock],
|
|
184
171
|
}),
|
|
185
172
|
new HumanMessage("last"),
|
|
186
173
|
];
|
|
@@ -12,8 +12,12 @@ type ContentBlock = MessageContent extends (infer U)[] | string ? U : never;
|
|
|
12
12
|
*/
|
|
13
13
|
export function appendCachePoint(
|
|
14
14
|
block: ContentBlock,
|
|
15
|
-
{ maxBlocks = 4 }: { maxBlocks?: number } = {}
|
|
16
|
-
): (
|
|
15
|
+
{ maxBlocks = 4 }: { maxBlocks?: number } = {}
|
|
16
|
+
): (
|
|
17
|
+
message: BaseMessage,
|
|
18
|
+
index: number,
|
|
19
|
+
messages: readonly BaseMessage[]
|
|
20
|
+
) => BaseMessage {
|
|
17
21
|
return (message, index, messages) => {
|
|
18
22
|
const isLast = index === messages.length - 1;
|
|
19
23
|
|
|
@@ -23,13 +27,19 @@ export function appendCachePoint(
|
|
|
23
27
|
if (content.some((b) => b.type === block.type)) return message;
|
|
24
28
|
message.content = [...content, block];
|
|
25
29
|
} else if (typeof content === "string") {
|
|
26
|
-
message.content = [
|
|
30
|
+
message.content = [
|
|
31
|
+
{ type: "text", text: content },
|
|
32
|
+
block,
|
|
33
|
+
] satisfies MessageContent;
|
|
27
34
|
}
|
|
28
35
|
return message;
|
|
29
36
|
}
|
|
30
37
|
|
|
31
38
|
const { content } = message;
|
|
32
|
-
if (
|
|
39
|
+
if (
|
|
40
|
+
!Array.isArray(content) ||
|
|
41
|
+
!content.some((b) => b.type === block.type)
|
|
42
|
+
) {
|
|
33
43
|
return message;
|
|
34
44
|
}
|
|
35
45
|
|
|
@@ -40,7 +50,10 @@ export function appendCachePoint(
|
|
|
40
50
|
const msg = messages[i];
|
|
41
51
|
if (!msg) continue;
|
|
42
52
|
const c = msg.content;
|
|
43
|
-
if (
|
|
53
|
+
if (
|
|
54
|
+
Array.isArray(c) &&
|
|
55
|
+
c.some((b: ContentBlock) => b.type === block.type)
|
|
56
|
+
) {
|
|
44
57
|
cacheBlocksAfter++;
|
|
45
58
|
}
|
|
46
59
|
}
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
} from "./thread-manager";
|
|
10
10
|
import { getActivityContext } from "../../../lib/activity";
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
export interface LangChainModelInvokerConfig<
|
|
14
14
|
TModel extends BaseChatModel<any> = BaseChatModel<any>,
|
|
15
15
|
> {
|
|
@@ -40,7 +40,7 @@ export interface LangChainModelInvokerConfig<
|
|
|
40
40
|
* return { ...createRunAgentActivity(client, invoker, "myAgent") };
|
|
41
41
|
* ```
|
|
42
42
|
*/
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
export function createLangChainModelInvoker<
|
|
45
45
|
TModel extends BaseChatModel<any> = BaseChatModel<any>,
|
|
46
46
|
>({ redis, model, hooks }: LangChainModelInvokerConfig<TModel>) {
|
|
@@ -109,7 +109,7 @@ export function createLangChainModelInvoker<
|
|
|
109
109
|
* Convenience wrapper around createLangChainModelInvoker for cases where
|
|
110
110
|
* you don't need to reuse the invoker.
|
|
111
111
|
*/
|
|
112
|
-
|
|
112
|
+
|
|
113
113
|
export async function invokeLangChainModel<
|
|
114
114
|
TModel extends BaseChatModel<any> = BaseChatModel<any>,
|
|
115
115
|
>({
|
|
@@ -27,7 +27,11 @@ const ADAPTER_PREFIX = "langChain";
|
|
|
27
27
|
|
|
28
28
|
export function proxyLangChainThreadOps(
|
|
29
29
|
scope?: string,
|
|
30
|
-
options?: Parameters<typeof createThreadOpsProxy>[2]
|
|
30
|
+
options?: Parameters<typeof createThreadOpsProxy>[2]
|
|
31
31
|
): ActivityInterfaceFor<ThreadOps<LangChainContent>> {
|
|
32
|
-
return createThreadOpsProxy(
|
|
32
|
+
return createThreadOpsProxy(
|
|
33
|
+
ADAPTER_PREFIX,
|
|
34
|
+
scope,
|
|
35
|
+
options
|
|
36
|
+
) as ActivityInterfaceFor<ThreadOps<LangChainContent>>;
|
|
33
37
|
}
|
|
@@ -91,7 +91,11 @@ describe("LangChain thread manager hooks", () => {
|
|
|
91
91
|
|
|
92
92
|
await tm.prepareForInvocation();
|
|
93
93
|
|
|
94
|
-
const args = hook.mock.calls[0] as unknown as [
|
|
94
|
+
const args = hook.mock.calls[0] as unknown as [
|
|
95
|
+
unknown,
|
|
96
|
+
number,
|
|
97
|
+
unknown[],
|
|
98
|
+
];
|
|
95
99
|
expect(args[2]).toHaveLength(2);
|
|
96
100
|
});
|
|
97
101
|
});
|
|
@@ -23,7 +23,10 @@ export type LangChainContent = string | MessageContent;
|
|
|
23
23
|
/** SDK-native content type for LangChain system messages */
|
|
24
24
|
export type LangChainSystemContent = string | MessageContent;
|
|
25
25
|
|
|
26
|
-
export type LangChainThreadManagerHooks = ThreadManagerHooks<
|
|
26
|
+
export type LangChainThreadManagerHooks = ThreadManagerHooks<
|
|
27
|
+
StoredMessage,
|
|
28
|
+
BaseMessage
|
|
29
|
+
>;
|
|
27
30
|
|
|
28
31
|
export interface LangChainThreadManagerConfig {
|
|
29
32
|
redis: Redis;
|
|
@@ -39,8 +42,12 @@ export interface LangChainInvocationPayload {
|
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
/** Thread manager with LangChain StoredMessage convenience helpers */
|
|
42
|
-
export interface LangChainThreadManager
|
|
43
|
-
|
|
45
|
+
export interface LangChainThreadManager extends ProviderThreadManager<
|
|
46
|
+
StoredMessage,
|
|
47
|
+
LangChainContent,
|
|
48
|
+
JsonValue,
|
|
49
|
+
LangChainSystemContent
|
|
50
|
+
> {
|
|
44
51
|
appendAIMessage(id: string, content: string | MessageContent): Promise<void>;
|
|
45
52
|
prepareForInvocation(): Promise<LangChainInvocationPayload>;
|
|
46
53
|
}
|
|
@@ -63,7 +70,7 @@ function storedMessageId(msg: StoredMessage): string {
|
|
|
63
70
|
* appending typed LangChain messages.
|
|
64
71
|
*/
|
|
65
72
|
export function createLangChainThreadManager(
|
|
66
|
-
config: LangChainThreadManagerConfig
|
|
73
|
+
config: LangChainThreadManagerConfig
|
|
67
74
|
): LangChainThreadManager {
|
|
68
75
|
const baseConfig: ThreadManagerConfig<StoredMessage> = {
|
|
69
76
|
redis: config.redis,
|
|
@@ -77,7 +84,7 @@ export function createLangChainThreadManager(
|
|
|
77
84
|
const helpers: Omit<LangChainThreadManager, keyof typeof base> = {
|
|
78
85
|
async appendUserMessage(
|
|
79
86
|
id: string,
|
|
80
|
-
content: LangChainContent
|
|
87
|
+
content: LangChainContent
|
|
81
88
|
): Promise<void> {
|
|
82
89
|
await base.append([
|
|
83
90
|
new HumanMessage({ id, content: content as MessageContent }).toDict(),
|
|
@@ -86,7 +93,7 @@ export function createLangChainThreadManager(
|
|
|
86
93
|
|
|
87
94
|
async appendSystemMessage(
|
|
88
95
|
id: string,
|
|
89
|
-
content: LangChainSystemContent
|
|
96
|
+
content: LangChainSystemContent
|
|
90
97
|
): Promise<void> {
|
|
91
98
|
await base.initialize();
|
|
92
99
|
await base.append([
|
|
@@ -99,7 +106,7 @@ export function createLangChainThreadManager(
|
|
|
99
106
|
|
|
100
107
|
async appendAIMessage(
|
|
101
108
|
id: string,
|
|
102
|
-
content: string | MessageContent
|
|
109
|
+
content: string | MessageContent
|
|
103
110
|
): Promise<void> {
|
|
104
111
|
await base.append([
|
|
105
112
|
new AIMessage({ id, content: content as MessageContent }).toDict(),
|
|
@@ -110,10 +117,14 @@ export function createLangChainThreadManager(
|
|
|
110
117
|
id: string,
|
|
111
118
|
_toolCallId: string,
|
|
112
119
|
_toolName: string,
|
|
113
|
-
content: JsonValue
|
|
120
|
+
content: JsonValue
|
|
114
121
|
): Promise<void> {
|
|
115
122
|
await base.append([
|
|
116
|
-
new ToolMessage({
|
|
123
|
+
new ToolMessage({
|
|
124
|
+
id,
|
|
125
|
+
content: content as MessageContent,
|
|
126
|
+
tool_call_id: _toolCallId,
|
|
127
|
+
}).toDict(),
|
|
117
128
|
]);
|
|
118
129
|
},
|
|
119
130
|
|
package/src/index.ts
CHANGED
|
@@ -58,7 +58,10 @@ export type { AgentStateContext } from "./lib/activity";
|
|
|
58
58
|
|
|
59
59
|
// Sandbox (activity-side: manager + Node.js filesystem adapter)
|
|
60
60
|
export { SandboxManager } from "./lib/sandbox/manager";
|
|
61
|
-
export type {
|
|
61
|
+
export type {
|
|
62
|
+
SandboxManagerHooks,
|
|
63
|
+
PreCreateHookResult,
|
|
64
|
+
} from "./lib/sandbox/manager";
|
|
62
65
|
export { NodeFsSandboxFileSystem } from "./lib/sandbox/node-fs";
|
|
63
66
|
|
|
64
67
|
// Virtual filesystem (activity-side)
|
package/src/lib/activity.ts
CHANGED
|
@@ -59,10 +59,13 @@ export async function queryParentWorkflowState<T>(
|
|
|
59
59
|
* };
|
|
60
60
|
* ```
|
|
61
61
|
*/
|
|
62
|
-
export function createRunAgentActivity<
|
|
62
|
+
export function createRunAgentActivity<
|
|
63
|
+
R,
|
|
64
|
+
S extends BaseAgentState = BaseAgentState,
|
|
65
|
+
>(
|
|
63
66
|
client: WorkflowClient,
|
|
64
67
|
handler: (config: RunAgentConfig & { state: S }) => Promise<R>,
|
|
65
|
-
scope: string
|
|
68
|
+
scope: string
|
|
66
69
|
): Record<string, (config: RunAgentConfig) => Promise<R>> {
|
|
67
70
|
const name = `run${scope.charAt(0).toUpperCase()}${scope.slice(1)}`;
|
|
68
71
|
return {
|
|
@@ -76,7 +79,9 @@ export function createRunAgentActivity<R, S extends BaseAgentState = BaseAgentSt
|
|
|
76
79
|
/**
|
|
77
80
|
* Context injected into tool handlers created via {@link withParentWorkflowState}.
|
|
78
81
|
*/
|
|
79
|
-
export interface AgentStateContext<
|
|
82
|
+
export interface AgentStateContext<
|
|
83
|
+
S extends BaseAgentState = BaseAgentState,
|
|
84
|
+
> extends RouterContext {
|
|
80
85
|
state: S;
|
|
81
86
|
}
|
|
82
87
|
|
|
@@ -101,12 +106,17 @@ export interface AgentStateContext<S extends BaseAgentState = BaseAgentState> ex
|
|
|
101
106
|
* );
|
|
102
107
|
* ```
|
|
103
108
|
*/
|
|
104
|
-
export function withParentWorkflowState<
|
|
109
|
+
export function withParentWorkflowState<
|
|
110
|
+
TArgs,
|
|
111
|
+
TResult,
|
|
112
|
+
S extends BaseAgentState = BaseAgentState,
|
|
113
|
+
TToolResponse = JsonValue,
|
|
114
|
+
>(
|
|
105
115
|
client: WorkflowClient,
|
|
106
116
|
handler: (
|
|
107
117
|
args: TArgs,
|
|
108
|
-
context: AgentStateContext<S
|
|
109
|
-
) => Promise<ToolHandlerResponse<TResult, TToolResponse
|
|
118
|
+
context: AgentStateContext<S>
|
|
119
|
+
) => Promise<ToolHandlerResponse<TResult, TToolResponse>>
|
|
110
120
|
): ActivityToolHandler<TArgs, TResult, RouterContext, TToolResponse> {
|
|
111
121
|
return async (args, context) => {
|
|
112
122
|
const state = await queryParentWorkflowState<S>(client);
|
package/src/lib/hooks/types.ts
CHANGED
|
@@ -1,8 +1,5 @@
|
|
|
1
1
|
import type { SessionExitReason } from "../types";
|
|
2
|
-
import type {
|
|
3
|
-
ToolMap,
|
|
4
|
-
ToolRouterHooks,
|
|
5
|
-
} from "../tool-router/types";
|
|
2
|
+
import type { ToolMap, ToolRouterHooks } from "../tool-router/types";
|
|
6
3
|
|
|
7
4
|
// ============================================================================
|
|
8
5
|
// Session Lifecycle Hooks
|
|
@@ -85,8 +82,11 @@ export type PostHumanMessageAppendHook<TContent = unknown> = (
|
|
|
85
82
|
* (consumed by the router) with session/message lifecycle hooks
|
|
86
83
|
* (consumed directly by the session).
|
|
87
84
|
*/
|
|
88
|
-
export interface Hooks<
|
|
89
|
-
extends
|
|
85
|
+
export interface Hooks<
|
|
86
|
+
T extends ToolMap,
|
|
87
|
+
TResult = unknown,
|
|
88
|
+
TContent = unknown,
|
|
89
|
+
> extends ToolRouterHooks<T, TResult> {
|
|
90
90
|
/** Called before each human message is appended to the thread */
|
|
91
91
|
onPreHumanMessageAppend?: PreHumanMessageAppendHook<TContent>;
|
|
92
92
|
/** Called after each human message is appended to the thread */
|
package/src/lib/lifecycle.ts
CHANGED
|
@@ -19,6 +19,8 @@ export type ThreadInit =
|
|
|
19
19
|
// Sandbox lifecycle
|
|
20
20
|
// ============================================================================
|
|
21
21
|
|
|
22
|
+
import type { SandboxSnapshot } from "./sandbox/types";
|
|
23
|
+
|
|
22
24
|
/**
|
|
23
25
|
* Sandbox initialization strategy.
|
|
24
26
|
*
|
|
@@ -30,6 +32,8 @@ export type ThreadInit =
|
|
|
30
32
|
* on exit.
|
|
31
33
|
* - `"fork"` — fork from an existing (or paused) sandbox; a new sandbox is
|
|
32
34
|
* created and owned by this session.
|
|
35
|
+
* - `"from-snapshot"` — restore a fresh sandbox from a previously captured
|
|
36
|
+
* {@link SandboxSnapshot}. The new sandbox is owned by this session.
|
|
33
37
|
* - `"inherit"` — use a sandbox owned by someone else (e.g. a parent agent).
|
|
34
38
|
* The session will **not** manage its lifecycle on exit.
|
|
35
39
|
*/
|
|
@@ -37,6 +41,7 @@ export type SandboxInit =
|
|
|
37
41
|
| { mode: "new"; ctx?: unknown }
|
|
38
42
|
| { mode: "continue"; sandboxId: string }
|
|
39
43
|
| { mode: "fork"; sandboxId: string }
|
|
44
|
+
| { mode: "from-snapshot"; snapshot: SandboxSnapshot }
|
|
40
45
|
| {
|
|
41
46
|
mode: "inherit";
|
|
42
47
|
sandboxId: string;
|
|
@@ -48,8 +53,11 @@ export type SandboxInit =
|
|
|
48
53
|
* - `"destroy"` — tear down the sandbox entirely.
|
|
49
54
|
* - `"pause"` — pause the sandbox so it can be resumed later.
|
|
50
55
|
* - `"keep"` — leave the sandbox running (no-op on exit).
|
|
56
|
+
* - `"snapshot"` — capture a snapshot then destroy the sandbox. The snapshot
|
|
57
|
+
* is surfaced on the session result so the caller can reuse it to spawn
|
|
58
|
+
* future sandboxes.
|
|
51
59
|
*/
|
|
52
|
-
export type SandboxShutdown = "destroy" | "pause" | "keep";
|
|
60
|
+
export type SandboxShutdown = "destroy" | "pause" | "keep" | "snapshot";
|
|
53
61
|
|
|
54
62
|
/**
|
|
55
63
|
* Extended shutdown options available to subagent workflows.
|
package/src/lib/model/proxy.ts
CHANGED
|
@@ -29,7 +29,7 @@ import type { RunAgentConfig } from "../types";
|
|
|
29
29
|
|
|
30
30
|
export function proxyRunAgent<M = unknown>(
|
|
31
31
|
scope?: string,
|
|
32
|
-
options?: Parameters<typeof proxyActivities>[0]
|
|
32
|
+
options?: Parameters<typeof proxyActivities>[0]
|
|
33
33
|
): (config: RunAgentConfig) => Promise<AgentResponse<M>> {
|
|
34
34
|
const resolvedScope = scope ?? workflowInfo().workflowType;
|
|
35
35
|
const name = `run${resolvedScope.charAt(0).toUpperCase()}${resolvedScope.slice(1)}`;
|
|
@@ -44,7 +44,7 @@ export function proxyRunAgent<M = unknown>(
|
|
|
44
44
|
maximumInterval: "2m",
|
|
45
45
|
backoffCoefficient: 3,
|
|
46
46
|
},
|
|
47
|
-
}
|
|
47
|
+
}
|
|
48
48
|
);
|
|
49
49
|
return acts[name] as (config: RunAgentConfig) => Promise<AgentResponse<M>>;
|
|
50
50
|
}
|
|
@@ -1,9 +1,6 @@
|
|
|
1
1
|
import { proxySinks } from "@temporalio/workflow";
|
|
2
2
|
import type { ZeitlichObservabilitySinks } from "./sinks";
|
|
3
|
-
import type {
|
|
4
|
-
SessionStartHook,
|
|
5
|
-
SessionEndHook,
|
|
6
|
-
} from "../hooks/types";
|
|
3
|
+
import type { SessionStartHook, SessionEndHook } from "../hooks/types";
|
|
7
4
|
import type {
|
|
8
5
|
PostToolUseHook,
|
|
9
6
|
PostToolUseFailureHook,
|
|
@@ -39,7 +36,9 @@ export interface ObservabilityHooks {
|
|
|
39
36
|
*
|
|
40
37
|
* @param agentName - Agent name attached to every emitted event
|
|
41
38
|
*/
|
|
42
|
-
export function createObservabilityHooks(
|
|
39
|
+
export function createObservabilityHooks(
|
|
40
|
+
agentName: string
|
|
41
|
+
): ObservabilityHooks {
|
|
43
42
|
const { zeitlichMetrics } = proxySinks<ZeitlichObservabilitySinks>();
|
|
44
43
|
let sessionStartMs = Date.now();
|
|
45
44
|
|
|
@@ -50,8 +50,12 @@ export interface SandboxManagerHooks<
|
|
|
50
50
|
|
|
51
51
|
/**
|
|
52
52
|
* Called after a sandbox has been successfully created.
|
|
53
|
+
*
|
|
54
|
+
* Receives the live {@link Sandbox} instance so the hook can run setup
|
|
55
|
+
* commands, seed files, or capture identifiers without an extra
|
|
56
|
+
* `provider.get()` round-trip.
|
|
53
57
|
*/
|
|
54
|
-
onPostCreate?: (
|
|
58
|
+
onPostCreate?: (sandbox: Sandbox, ctx: TCtx) => Promise<void>;
|
|
55
59
|
}
|
|
56
60
|
|
|
57
61
|
/**
|
|
@@ -87,8 +91,9 @@ export interface SandboxManagerHooks<
|
|
|
87
91
|
* for (const p of filePaths) files[p] = await db.readFile(projectId, p);
|
|
88
92
|
* return { modifiedOptions: { initialFiles: files } };
|
|
89
93
|
* },
|
|
90
|
-
* onPostCreate: async (
|
|
91
|
-
* console.log("Sandbox created:",
|
|
94
|
+
* onPostCreate: async (sandbox) => {
|
|
95
|
+
* console.log("Sandbox created:", sandbox.id);
|
|
96
|
+
* await sandbox.exec("git init");
|
|
92
97
|
* },
|
|
93
98
|
* },
|
|
94
99
|
* },
|
|
@@ -148,7 +153,7 @@ export class SandboxManager<
|
|
|
148
153
|
const { sandbox } = await this.provider.create(providerOptions);
|
|
149
154
|
|
|
150
155
|
if (this.hooks.onPostCreate) {
|
|
151
|
-
await this.hooks.onPostCreate(sandbox
|
|
156
|
+
await this.hooks.onPostCreate(sandbox, ctx ?? ({} as TCtx));
|
|
152
157
|
}
|
|
153
158
|
|
|
154
159
|
return { sandboxId: sandbox.id };
|
|
@@ -179,6 +184,10 @@ export class SandboxManager<
|
|
|
179
184
|
return sandbox.id;
|
|
180
185
|
}
|
|
181
186
|
|
|
187
|
+
async deleteSnapshot(snapshot: SandboxSnapshot): Promise<void> {
|
|
188
|
+
await this.provider.deleteSnapshot(snapshot);
|
|
189
|
+
}
|
|
190
|
+
|
|
182
191
|
async fork(sandboxId: string): Promise<string> {
|
|
183
192
|
const sandbox = await this.provider.fork(sandboxId);
|
|
184
193
|
return sandbox.id;
|
|
@@ -232,6 +241,14 @@ export class SandboxManager<
|
|
|
232
241
|
snapshotSandbox: async (sandboxId: string): Promise<SandboxSnapshot> => {
|
|
233
242
|
return this.snapshot(sandboxId);
|
|
234
243
|
},
|
|
244
|
+
restoreSandbox: async (snapshot: SandboxSnapshot): Promise<string> => {
|
|
245
|
+
return this.restore(snapshot);
|
|
246
|
+
},
|
|
247
|
+
deleteSandboxSnapshot: async (
|
|
248
|
+
snapshot: SandboxSnapshot
|
|
249
|
+
): Promise<void> => {
|
|
250
|
+
await this.deleteSnapshot(snapshot);
|
|
251
|
+
},
|
|
235
252
|
forkSandbox: async (sandboxId: string): Promise<string> => {
|
|
236
253
|
return this.fork(sandboxId);
|
|
237
254
|
},
|
|
@@ -65,10 +65,7 @@ export class NodeFsSandboxFileSystem implements SandboxFileSystem {
|
|
|
65
65
|
};
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
async mkdir(
|
|
69
|
-
path: string,
|
|
70
|
-
options?: { recursive?: boolean },
|
|
71
|
-
): Promise<void> {
|
|
68
|
+
async mkdir(path: string, options?: { recursive?: boolean }): Promise<void> {
|
|
72
69
|
await fsp.mkdir(this.abs(path), options);
|
|
73
70
|
}
|
|
74
71
|
|
|
@@ -88,7 +85,7 @@ export class NodeFsSandboxFileSystem implements SandboxFileSystem {
|
|
|
88
85
|
|
|
89
86
|
async rm(
|
|
90
87
|
path: string,
|
|
91
|
-
options?: { recursive?: boolean; force?: boolean }
|
|
88
|
+
options?: { recursive?: boolean; force?: boolean }
|
|
92
89
|
): Promise<void> {
|
|
93
90
|
await fsp.rm(this.abs(path), options);
|
|
94
91
|
}
|
|
@@ -96,7 +93,7 @@ export class NodeFsSandboxFileSystem implements SandboxFileSystem {
|
|
|
96
93
|
async cp(
|
|
97
94
|
src: string,
|
|
98
95
|
dest: string,
|
|
99
|
-
options?: { recursive?: boolean }
|
|
96
|
+
options?: { recursive?: boolean }
|
|
100
97
|
): Promise<void> {
|
|
101
98
|
await fsp.cp(this.abs(src), this.abs(dest), options);
|
|
102
99
|
}
|
|
@@ -157,18 +157,21 @@ describe("SandboxManager", () => {
|
|
|
157
157
|
expect(await sandbox.fs.readFile("/file.txt")).toBe("explicit");
|
|
158
158
|
});
|
|
159
159
|
|
|
160
|
-
it("onPostCreate hook receives
|
|
160
|
+
it("onPostCreate hook receives the live sandbox", async () => {
|
|
161
161
|
let capturedId: string | undefined;
|
|
162
162
|
const mgr = new SandboxManager(new InMemorySandboxProvider(), {
|
|
163
163
|
hooks: {
|
|
164
|
-
onPostCreate: async (
|
|
165
|
-
capturedId =
|
|
164
|
+
onPostCreate: async (sandbox) => {
|
|
165
|
+
capturedId = sandbox.id;
|
|
166
|
+
await sandbox.fs.writeFile("/hook.txt", "written-by-hook");
|
|
166
167
|
},
|
|
167
168
|
},
|
|
168
169
|
});
|
|
169
170
|
|
|
170
171
|
const { sandboxId } = await mustCreate(mgr);
|
|
171
172
|
expect(capturedId).toBe(sandboxId);
|
|
173
|
+
const sandbox = await mgr.getSandbox(sandboxId);
|
|
174
|
+
expect(await sandbox.fs.readFile("/hook.txt")).toBe("written-by-hook");
|
|
172
175
|
});
|
|
173
176
|
|
|
174
177
|
it("onPostCreate hook does not run when creation is skipped", async () => {
|
|
@@ -192,6 +195,8 @@ describe("SandboxManager", () => {
|
|
|
192
195
|
expect(activities.inMemoryTestCreateSandbox).toBeTypeOf("function");
|
|
193
196
|
expect(activities.inMemoryTestDestroySandbox).toBeTypeOf("function");
|
|
194
197
|
expect(activities.inMemoryTestSnapshotSandbox).toBeTypeOf("function");
|
|
198
|
+
expect(activities.inMemoryTestRestoreSandbox).toBeTypeOf("function");
|
|
199
|
+
expect(activities.inMemoryTestDeleteSandboxSnapshot).toBeTypeOf("function");
|
|
195
200
|
|
|
196
201
|
const result = await activities.inMemoryTestCreateSandbox();
|
|
197
202
|
expect(result).not.toBeNull();
|
|
@@ -203,6 +208,34 @@ describe("SandboxManager", () => {
|
|
|
203
208
|
SandboxNotFoundError
|
|
204
209
|
);
|
|
205
210
|
});
|
|
211
|
+
|
|
212
|
+
it("restoreSandbox activity creates a new sandbox from a snapshot", async () => {
|
|
213
|
+
const activities = manager.createActivities("Test");
|
|
214
|
+
|
|
215
|
+
const created = await activities.inMemoryTestCreateSandbox({
|
|
216
|
+
initialFiles: { "/greeting.txt": "hello" },
|
|
217
|
+
});
|
|
218
|
+
const { sandboxId } = created as { sandboxId: string };
|
|
219
|
+
|
|
220
|
+
const snapshot = await activities.inMemoryTestSnapshotSandbox(sandboxId);
|
|
221
|
+
await activities.inMemoryTestDestroySandbox(sandboxId);
|
|
222
|
+
|
|
223
|
+
const restoredId = await activities.inMemoryTestRestoreSandbox(snapshot);
|
|
224
|
+
const restored = await manager.getSandbox(restoredId);
|
|
225
|
+
expect(await restored.fs.readFile("/greeting.txt")).toBe("hello");
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
it("deleteSandboxSnapshot activity is a no-op for in-memory snapshots", async () => {
|
|
229
|
+
const activities = manager.createActivities("Test");
|
|
230
|
+
|
|
231
|
+
const created = await activities.inMemoryTestCreateSandbox();
|
|
232
|
+
const { sandboxId } = created as { sandboxId: string };
|
|
233
|
+
|
|
234
|
+
const snapshot = await activities.inMemoryTestSnapshotSandbox(sandboxId);
|
|
235
|
+
await expect(
|
|
236
|
+
activities.inMemoryTestDeleteSandboxSnapshot(snapshot)
|
|
237
|
+
).resolves.toBeUndefined();
|
|
238
|
+
});
|
|
206
239
|
});
|
|
207
240
|
|
|
208
241
|
describe("InMemorySandboxProvider", () => {
|