zeitlich 0.2.20 → 0.2.22
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 +70 -55
- package/dist/adapters/sandbox/daytona/index.cjs +3 -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 +3 -0
- package/dist/adapters/sandbox/daytona/index.js.map +1 -1
- package/dist/adapters/sandbox/daytona/workflow.cjs +32 -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 +30 -0
- package/dist/adapters/sandbox/daytona/workflow.js.map +1 -0
- package/dist/adapters/sandbox/inmemory/index.cjs +4 -1
- package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.d.cts +3 -2
- package/dist/adapters/sandbox/inmemory/index.d.ts +3 -2
- package/dist/adapters/sandbox/inmemory/index.js +4 -1
- package/dist/adapters/sandbox/inmemory/index.js.map +1 -1
- package/dist/adapters/sandbox/inmemory/workflow.cjs +32 -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 +30 -0
- package/dist/adapters/sandbox/inmemory/workflow.js.map +1 -0
- package/dist/adapters/sandbox/virtual/index.cjs +3 -0
- package/dist/adapters/sandbox/virtual/index.cjs.map +1 -1
- package/dist/adapters/sandbox/virtual/index.d.cts +7 -5
- package/dist/adapters/sandbox/virtual/index.d.ts +7 -5
- package/dist/adapters/sandbox/virtual/index.js +3 -0
- package/dist/adapters/sandbox/virtual/index.js.map +1 -1
- package/dist/adapters/sandbox/virtual/workflow.cjs +32 -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 +30 -0
- package/dist/adapters/sandbox/virtual/workflow.js.map +1 -0
- package/dist/adapters/thread/google-genai/index.cjs +79 -24
- package/dist/adapters/thread/google-genai/index.cjs.map +1 -1
- package/dist/adapters/thread/google-genai/index.d.cts +39 -27
- package/dist/adapters/thread/google-genai/index.d.ts +39 -27
- package/dist/adapters/thread/google-genai/index.js +79 -24
- 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 +84 -71
- package/dist/adapters/thread/langchain/index.cjs.map +1 -1
- package/dist/adapters/thread/langchain/index.d.cts +35 -24
- package/dist/adapters/thread/langchain/index.d.ts +35 -24
- package/dist/adapters/thread/langchain/index.js +84 -71
- 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 +90 -43
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +38 -17
- package/dist/index.d.ts +38 -17
- package/dist/index.js +92 -43
- package/dist/index.js.map +1 -1
- package/dist/queries-Bw6WEPMw.d.cts +44 -0
- package/dist/queries-C27raDaB.d.ts +44 -0
- package/dist/{queries-KHj5Otv7.d.ts → types-BJ8itUAl.d.cts} +3 -44
- package/dist/{types-By80IE1x.d.ts → types-C5bkx6kQ.d.ts} +37 -9
- package/dist/{types-DZ7BkA3-.d.cts → types-ClsHhtwL.d.cts} +37 -9
- package/dist/{queries-nIdzTCDS.d.cts → types-ENYCKFBk.d.ts} +3 -44
- package/dist/{types-BMRzfELQ.d.cts → types-HBosetv3.d.cts} +15 -1
- package/dist/{types-BMRzfELQ.d.ts → types-HBosetv3.d.ts} +15 -1
- package/dist/{types-Ct2igz9y.d.cts → types-YbL7JpEA.d.cts} +1 -1
- package/dist/{types-Ct2igz9y.d.ts → types-YbL7JpEA.d.ts} +1 -1
- package/dist/workflow.cjs +11 -38
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +15 -43
- package/dist/workflow.d.ts +15 -43
- package/dist/workflow.js +13 -38
- package/dist/workflow.js.map +1 -1
- package/package.json +53 -1
- package/src/adapters/sandbox/daytona/index.ts +4 -0
- package/src/adapters/sandbox/daytona/proxy.ts +55 -0
- package/src/adapters/sandbox/e2b/filesystem.ts +147 -0
- package/src/adapters/sandbox/e2b/index.ts +159 -0
- package/src/adapters/sandbox/e2b/types.ts +23 -0
- package/src/adapters/sandbox/inmemory/index.ts +5 -1
- package/src/adapters/sandbox/inmemory/proxy.ts +53 -0
- package/src/adapters/sandbox/virtual/provider.ts +5 -1
- package/src/adapters/sandbox/virtual/proxy.ts +52 -0
- package/src/adapters/thread/google-genai/activities.ts +62 -26
- package/src/adapters/thread/google-genai/index.ts +1 -0
- package/src/adapters/thread/google-genai/model-invoker.ts +6 -11
- package/src/adapters/thread/google-genai/proxy.ts +61 -0
- package/src/adapters/thread/google-genai/thread-manager.ts +44 -29
- package/src/adapters/thread/langchain/activities.ts +53 -18
- package/src/adapters/thread/langchain/index.ts +1 -0
- package/src/adapters/thread/langchain/proxy.ts +61 -0
- package/src/adapters/thread/langchain/thread-manager.ts +46 -22
- package/src/lib/sandbox/manager.ts +40 -6
- package/src/lib/sandbox/sandbox.test.ts +12 -11
- package/src/lib/sandbox/types.ts +18 -0
- package/src/lib/session/index.ts +3 -5
- package/src/lib/session/session-edge-cases.integration.test.ts +45 -34
- package/src/lib/session/session.integration.test.ts +40 -48
- package/src/lib/session/session.ts +9 -70
- package/src/lib/session/types.ts +39 -3
- package/src/lib/subagent/define.ts +1 -1
- package/src/lib/subagent/handler.ts +9 -2
- package/src/lib/subagent/index.ts +1 -0
- package/src/lib/subagent/subagent.integration.test.ts +62 -0
- package/src/lib/subagent/types.ts +7 -2
- package/src/lib/tool-router/auto-append-sandbox.integration.test.ts +20 -21
- package/src/lib/tool-router/auto-append.ts +3 -2
- package/src/lib/tool-router/router-edge-cases.integration.test.ts +63 -24
- package/src/lib/tool-router/router.integration.test.ts +59 -24
- package/src/lib/tool-router/router.ts +4 -3
- package/src/lib/tool-router/types.ts +1 -1
- package/src/lib/workflow.test.ts +19 -10
- package/src/lib/workflow.ts +4 -1
- package/src/tools/bash/bash.test.ts +16 -7
- package/src/workflow.ts +6 -14
- package/tsup.config.ts +6 -0
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
SystemMessage,
|
|
10
10
|
ToolMessage,
|
|
11
11
|
} from "@langchain/core/messages";
|
|
12
|
-
import { v4 as uuidv4 } from "uuid";
|
|
13
12
|
import {
|
|
14
13
|
createThreadManager,
|
|
15
14
|
type BaseThreadManager,
|
|
@@ -30,31 +29,44 @@ export interface LangChainThreadManagerConfig {
|
|
|
30
29
|
|
|
31
30
|
/** Thread manager with LangChain StoredMessage convenience helpers */
|
|
32
31
|
export interface LangChainThreadManager extends BaseThreadManager<StoredMessage> {
|
|
33
|
-
createHumanMessage(
|
|
34
|
-
|
|
32
|
+
createHumanMessage(
|
|
33
|
+
id: string,
|
|
34
|
+
content: string | MessageContent
|
|
35
|
+
): StoredMessage;
|
|
36
|
+
createSystemMessage(id: string, content: string): StoredMessage;
|
|
35
37
|
createAIMessage(
|
|
38
|
+
id: string,
|
|
36
39
|
content: string | MessageContent,
|
|
37
40
|
kwargs?: { header?: string; options?: string[]; multiSelect?: boolean }
|
|
38
41
|
): StoredMessage;
|
|
39
42
|
createToolMessage(
|
|
43
|
+
id: string,
|
|
40
44
|
content: LangChainToolMessageContent,
|
|
41
45
|
toolCallId: string
|
|
42
46
|
): StoredMessage;
|
|
43
|
-
appendHumanMessage(
|
|
44
|
-
|
|
47
|
+
appendHumanMessage(
|
|
48
|
+
id: string,
|
|
49
|
+
content: string | MessageContent
|
|
50
|
+
): Promise<void>;
|
|
51
|
+
appendSystemMessage(id: string, content: string): Promise<void>;
|
|
45
52
|
appendToolMessage(
|
|
53
|
+
id: string,
|
|
46
54
|
content: LangChainToolMessageContent,
|
|
47
55
|
toolCallId: string
|
|
48
56
|
): Promise<void>;
|
|
49
|
-
appendAIMessage(content: string | MessageContent): Promise<void>;
|
|
57
|
+
appendAIMessage(id: string, content: string | MessageContent): Promise<void>;
|
|
50
58
|
}
|
|
51
59
|
|
|
52
60
|
function storedMessageId(msg: StoredMessage): string {
|
|
53
|
-
if (msg.type === "tool") {
|
|
54
|
-
return msg.data.tool_call_id
|
|
61
|
+
if (msg.type === "tool" && msg.data.tool_call_id) {
|
|
62
|
+
return msg.data.tool_call_id;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (msg.data.id) {
|
|
66
|
+
return msg.data.id;
|
|
55
67
|
}
|
|
56
68
|
|
|
57
|
-
|
|
69
|
+
throw new Error("No id found for message");
|
|
58
70
|
}
|
|
59
71
|
|
|
60
72
|
/**
|
|
@@ -75,26 +87,30 @@ export function createLangChainThreadManager(
|
|
|
75
87
|
const base = createThreadManager(baseConfig);
|
|
76
88
|
|
|
77
89
|
const helpers = {
|
|
78
|
-
createHumanMessage(
|
|
90
|
+
createHumanMessage(
|
|
91
|
+
id: string,
|
|
92
|
+
content: string | MessageContent
|
|
93
|
+
): StoredMessage {
|
|
79
94
|
return new HumanMessage({
|
|
80
|
-
id
|
|
95
|
+
id,
|
|
81
96
|
content: content as string,
|
|
82
97
|
}).toDict();
|
|
83
98
|
},
|
|
84
99
|
|
|
85
|
-
createSystemMessage(content: string): StoredMessage {
|
|
100
|
+
createSystemMessage(id: string, content: string): StoredMessage {
|
|
86
101
|
return new SystemMessage({
|
|
87
|
-
id
|
|
102
|
+
id,
|
|
88
103
|
content: content as string,
|
|
89
104
|
}).toDict();
|
|
90
105
|
},
|
|
91
106
|
|
|
92
107
|
createAIMessage(
|
|
108
|
+
id: string,
|
|
93
109
|
content: string,
|
|
94
110
|
kwargs?: { header?: string; options?: string[]; multiSelect?: boolean }
|
|
95
111
|
): StoredMessage {
|
|
96
112
|
return new AIMessage({
|
|
97
|
-
id
|
|
113
|
+
id,
|
|
98
114
|
content,
|
|
99
115
|
additional_kwargs: kwargs
|
|
100
116
|
? {
|
|
@@ -107,36 +123,44 @@ export function createLangChainThreadManager(
|
|
|
107
123
|
},
|
|
108
124
|
|
|
109
125
|
createToolMessage(
|
|
126
|
+
id: string,
|
|
110
127
|
content: LangChainToolMessageContent,
|
|
111
128
|
toolCallId: string
|
|
112
129
|
): StoredMessage {
|
|
113
130
|
return new ToolMessage({
|
|
114
|
-
id
|
|
131
|
+
id,
|
|
115
132
|
content: content as MessageContent,
|
|
116
133
|
tool_call_id: toolCallId,
|
|
117
134
|
}).toDict();
|
|
118
135
|
},
|
|
119
136
|
|
|
120
|
-
async appendHumanMessage(
|
|
121
|
-
|
|
137
|
+
async appendHumanMessage(
|
|
138
|
+
id: string,
|
|
139
|
+
content: string | MessageContent
|
|
140
|
+
): Promise<void> {
|
|
141
|
+
const message = helpers.createHumanMessage(id, content);
|
|
122
142
|
await base.append([message]);
|
|
123
143
|
},
|
|
124
144
|
|
|
125
145
|
async appendToolMessage(
|
|
146
|
+
id: string,
|
|
126
147
|
content: LangChainToolMessageContent,
|
|
127
148
|
toolCallId: string
|
|
128
149
|
): Promise<void> {
|
|
129
|
-
const message = helpers.createToolMessage(content, toolCallId);
|
|
150
|
+
const message = helpers.createToolMessage(id, content, toolCallId);
|
|
130
151
|
await base.append([message]);
|
|
131
152
|
},
|
|
132
153
|
|
|
133
|
-
async appendAIMessage(
|
|
134
|
-
|
|
154
|
+
async appendAIMessage(
|
|
155
|
+
id: string,
|
|
156
|
+
content: string | MessageContent
|
|
157
|
+
): Promise<void> {
|
|
158
|
+
const message = helpers.createAIMessage(id, content as string);
|
|
135
159
|
await base.append([message]);
|
|
136
160
|
},
|
|
137
161
|
|
|
138
|
-
async appendSystemMessage(content: string): Promise<void> {
|
|
139
|
-
const message = helpers.createSystemMessage(content);
|
|
162
|
+
async appendSystemMessage(id: string, content: string): Promise<void> {
|
|
163
|
+
const message = helpers.createSystemMessage(id, content);
|
|
140
164
|
await base.initialize();
|
|
141
165
|
await base.append([message]);
|
|
142
166
|
},
|
|
@@ -2,6 +2,7 @@ import type {
|
|
|
2
2
|
Sandbox,
|
|
3
3
|
SandboxCreateOptions,
|
|
4
4
|
SandboxOps,
|
|
5
|
+
PrefixedSandboxOps,
|
|
5
6
|
SandboxProvider,
|
|
6
7
|
SandboxSnapshot,
|
|
7
8
|
} from "./types";
|
|
@@ -16,16 +17,18 @@ import type {
|
|
|
16
17
|
* ```typescript
|
|
17
18
|
* const manager = new SandboxManager(new InMemorySandboxProvider());
|
|
18
19
|
* const activities = {
|
|
19
|
-
* ...manager.createActivities(),
|
|
20
|
+
* ...manager.createActivities("CodingAgent"),
|
|
20
21
|
* bashHandler: withSandbox(manager, bashHandler),
|
|
21
22
|
* };
|
|
23
|
+
* // registers: inMemoryCodingAgentCreateSandbox, …
|
|
22
24
|
* ```
|
|
23
25
|
*/
|
|
24
26
|
export class SandboxManager<
|
|
25
27
|
TOptions extends SandboxCreateOptions = SandboxCreateOptions,
|
|
26
28
|
TSandbox extends Sandbox = Sandbox,
|
|
29
|
+
TId extends string = string,
|
|
27
30
|
> {
|
|
28
|
-
constructor(private provider: SandboxProvider<TOptions, TSandbox>) {}
|
|
31
|
+
constructor(private provider: SandboxProvider<TOptions, TSandbox> & { readonly id: TId }) {}
|
|
29
32
|
|
|
30
33
|
async create(
|
|
31
34
|
options?: TOptions
|
|
@@ -51,12 +54,36 @@ export class SandboxManager<
|
|
|
51
54
|
return sandbox.id;
|
|
52
55
|
}
|
|
53
56
|
|
|
57
|
+
async fork(sandboxId: string): Promise<string> {
|
|
58
|
+
const sandbox = await this.provider.fork(sandboxId);
|
|
59
|
+
return sandbox.id;
|
|
60
|
+
}
|
|
61
|
+
|
|
54
62
|
/**
|
|
55
|
-
* Returns Temporal activity functions
|
|
56
|
-
*
|
|
63
|
+
* Returns Temporal activity functions with prefixed names.
|
|
64
|
+
*
|
|
65
|
+
* The provider's `id` is automatically prepended, so you only need
|
|
66
|
+
* to pass the workflow/scope name. Use the matching `proxy*SandboxOps()`
|
|
67
|
+
* helper from the adapter's `/workflow` entrypoint on the workflow side.
|
|
68
|
+
*
|
|
69
|
+
* @param scope - Workflow name (appended to the provider id)
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```typescript
|
|
73
|
+
* const manager = new SandboxManager(new InMemorySandboxProvider());
|
|
74
|
+
* manager.createActivities("CodingAgent");
|
|
75
|
+
* // registers: inMemoryCodingAgentCreateSandbox, inMemoryCodingAgentDestroySandbox, …
|
|
76
|
+
*
|
|
77
|
+
* const vmgr = new SandboxManager(new VirtualSandboxProvider(resolver));
|
|
78
|
+
* vmgr.createActivities("CodingAgent");
|
|
79
|
+
* // registers: virtualCodingAgentCreateSandbox, …
|
|
80
|
+
* ```
|
|
57
81
|
*/
|
|
58
|
-
createActivities
|
|
59
|
-
|
|
82
|
+
createActivities<S extends string>(
|
|
83
|
+
scope: S
|
|
84
|
+
): PrefixedSandboxOps<`${TId}${Capitalize<S>}`, TOptions> {
|
|
85
|
+
const prefix = `${this.provider.id}${scope.charAt(0).toUpperCase()}${scope.slice(1)}`;
|
|
86
|
+
const ops: SandboxOps<TOptions> = {
|
|
60
87
|
createSandbox: async (
|
|
61
88
|
options?: TOptions
|
|
62
89
|
): Promise<{
|
|
@@ -71,6 +98,13 @@ export class SandboxManager<
|
|
|
71
98
|
snapshotSandbox: async (sandboxId: string): Promise<SandboxSnapshot> => {
|
|
72
99
|
return this.snapshot(sandboxId);
|
|
73
100
|
},
|
|
101
|
+
forkSandbox: async (sandboxId: string): Promise<string> => {
|
|
102
|
+
return this.fork(sandboxId);
|
|
103
|
+
},
|
|
74
104
|
};
|
|
105
|
+
const cap = (s: string): string => s.charAt(0).toUpperCase() + s.slice(1);
|
|
106
|
+
return Object.fromEntries(
|
|
107
|
+
Object.entries(ops).map(([k, v]) => [`${prefix}${cap(k)}`, v])
|
|
108
|
+
) as PrefixedSandboxOps<`${TId}${Capitalize<S>}`, TOptions>;
|
|
75
109
|
}
|
|
76
110
|
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { describe, expect, it, beforeEach } from "vitest";
|
|
2
2
|
import { SandboxManager } from "./manager";
|
|
3
3
|
import { InMemorySandboxProvider } from "../../adapters/sandbox/inmemory/index";
|
|
4
|
-
import { SandboxNotFoundError } from "./types";
|
|
4
|
+
import { SandboxNotFoundError, type Sandbox, type SandboxCreateOptions } from "./types";
|
|
5
5
|
|
|
6
6
|
describe("SandboxManager", () => {
|
|
7
|
-
let manager: SandboxManager
|
|
7
|
+
let manager: SandboxManager<SandboxCreateOptions, Sandbox, "inMemory">;
|
|
8
8
|
|
|
9
9
|
beforeEach(() => {
|
|
10
10
|
manager = new SandboxManager(new InMemorySandboxProvider());
|
|
@@ -54,7 +54,7 @@ describe("SandboxManager", () => {
|
|
|
54
54
|
|
|
55
55
|
const snapshot = await manager.snapshot(sandboxId);
|
|
56
56
|
expect(snapshot.sandboxId).toBe(sandboxId);
|
|
57
|
-
expect(snapshot.providerId).toBe("
|
|
57
|
+
expect(snapshot.providerId).toBe("inMemory");
|
|
58
58
|
|
|
59
59
|
await manager.destroy(sandboxId);
|
|
60
60
|
await expect(manager.getSandbox(sandboxId)).rejects.toThrow(SandboxNotFoundError);
|
|
@@ -68,16 +68,17 @@ describe("SandboxManager", () => {
|
|
|
68
68
|
expect(extra).toBe("world");
|
|
69
69
|
});
|
|
70
70
|
|
|
71
|
-
it("createActivities returns SandboxOps-shaped object", async () => {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
expect(activities.
|
|
75
|
-
expect(activities.
|
|
71
|
+
it("createActivities returns prefixed SandboxOps-shaped object", async () => {
|
|
72
|
+
// provider.id is "inMemory", scope is "Test" → prefix "inMemoryTest"
|
|
73
|
+
const activities = manager.createActivities("Test");
|
|
74
|
+
expect(activities.inMemoryTestCreateSandbox).toBeTypeOf("function");
|
|
75
|
+
expect(activities.inMemoryTestDestroySandbox).toBeTypeOf("function");
|
|
76
|
+
expect(activities.inMemoryTestSnapshotSandbox).toBeTypeOf("function");
|
|
76
77
|
|
|
77
|
-
const { sandboxId } = await activities.
|
|
78
|
+
const { sandboxId } = await activities.inMemoryTestCreateSandbox();
|
|
78
79
|
await expect(manager.getSandbox(sandboxId)).resolves.toBeTruthy();
|
|
79
80
|
|
|
80
|
-
await activities.
|
|
81
|
+
await activities.inMemoryTestDestroySandbox(sandboxId);
|
|
81
82
|
await expect(manager.getSandbox(sandboxId)).rejects.toThrow(
|
|
82
83
|
SandboxNotFoundError,
|
|
83
84
|
);
|
|
@@ -85,7 +86,7 @@ describe("SandboxManager", () => {
|
|
|
85
86
|
});
|
|
86
87
|
|
|
87
88
|
describe("InMemorySandboxProvider", () => {
|
|
88
|
-
let manager: SandboxManager
|
|
89
|
+
let manager: SandboxManager<SandboxCreateOptions, Sandbox, "inMemory">;
|
|
89
90
|
|
|
90
91
|
beforeEach(() => {
|
|
91
92
|
manager = new SandboxManager(new InMemorySandboxProvider());
|
package/src/lib/sandbox/types.ts
CHANGED
|
@@ -127,6 +127,7 @@ export interface SandboxProvider<
|
|
|
127
127
|
destroy(sandboxId: string): Promise<void>;
|
|
128
128
|
snapshot(sandboxId: string): Promise<SandboxSnapshot>;
|
|
129
129
|
restore(snapshot: SandboxSnapshot): Promise<Sandbox>;
|
|
130
|
+
fork(sandboxId: string): Promise<Sandbox>;
|
|
130
131
|
}
|
|
131
132
|
|
|
132
133
|
// ============================================================================
|
|
@@ -141,8 +142,25 @@ export interface SandboxOps<
|
|
|
141
142
|
): Promise<{ sandboxId: string; stateUpdate?: Record<string, unknown> }>;
|
|
142
143
|
destroySandbox(sandboxId: string): Promise<void>;
|
|
143
144
|
snapshotSandbox(sandboxId: string): Promise<SandboxSnapshot>;
|
|
145
|
+
forkSandbox(sandboxId: string): Promise<string>;
|
|
144
146
|
}
|
|
145
147
|
|
|
148
|
+
/**
|
|
149
|
+
* Maps generic {@link SandboxOps} method names to adapter-prefixed names.
|
|
150
|
+
*
|
|
151
|
+
* @example
|
|
152
|
+
* ```typescript
|
|
153
|
+
* type InMemOps = PrefixedSandboxOps<"inMemory">;
|
|
154
|
+
* // → { inMemoryCreateSandbox, inMemoryDestroySandbox, inMemorySnapshotSandbox }
|
|
155
|
+
* ```
|
|
156
|
+
*/
|
|
157
|
+
export type PrefixedSandboxOps<
|
|
158
|
+
TPrefix extends string,
|
|
159
|
+
TOptions extends SandboxCreateOptions = SandboxCreateOptions,
|
|
160
|
+
> = {
|
|
161
|
+
[K in keyof SandboxOps<TOptions> as `${TPrefix}${Capitalize<K & string>}`]: SandboxOps<TOptions>[K];
|
|
162
|
+
};
|
|
163
|
+
|
|
146
164
|
// ============================================================================
|
|
147
165
|
// Errors
|
|
148
166
|
// ============================================================================
|
package/src/lib/session/index.ts
CHANGED
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
export {
|
|
2
|
-
createSession,
|
|
3
|
-
proxyDefaultThreadOps,
|
|
4
|
-
proxySandboxOps,
|
|
5
|
-
} from "./session";
|
|
1
|
+
export { createSession } from "./session";
|
|
6
2
|
|
|
7
3
|
export type {
|
|
8
4
|
ThreadOps,
|
|
5
|
+
PrefixedThreadOps,
|
|
6
|
+
ScopedPrefix,
|
|
9
7
|
SessionConfig,
|
|
10
8
|
ZeitlichSession,
|
|
11
9
|
} from "./types";
|
|
@@ -56,12 +56,11 @@ type TurnScript = {
|
|
|
56
56
|
* Wraps every method on a ThreadOps object so it also has `.executeWithOptions()`,
|
|
57
57
|
* matching Temporal's `ActivityInterfaceFor<ThreadOps>` shape.
|
|
58
58
|
*/
|
|
59
|
-
function toActivityInterface(
|
|
60
|
-
raw: ThreadOps,
|
|
61
|
-
): ActivityInterfaceFor<ThreadOps> {
|
|
59
|
+
function toActivityInterface(raw: ThreadOps): ActivityInterfaceFor<ThreadOps> {
|
|
62
60
|
const result = {} as Record<string, unknown>;
|
|
63
61
|
for (const [key, fn] of Object.entries(raw)) {
|
|
64
|
-
const wrapped = (...args: unknown[]) =>
|
|
62
|
+
const wrapped = (...args: unknown[]) =>
|
|
63
|
+
(fn as (...a: unknown[]) => unknown)(...args);
|
|
65
64
|
wrapped.executeWithOptions = (_opts: unknown, args: unknown[]) =>
|
|
66
65
|
(fn as (...a: unknown[]) => unknown)(...args);
|
|
67
66
|
result[key] = wrapped;
|
|
@@ -75,14 +74,14 @@ function createMockThreadOps() {
|
|
|
75
74
|
initializeThread: async (threadId) => {
|
|
76
75
|
log.push({ op: "initializeThread", args: [threadId] });
|
|
77
76
|
},
|
|
78
|
-
appendHumanMessage: async (threadId, content) => {
|
|
79
|
-
log.push({ op: "appendHumanMessage", args: [threadId, content] });
|
|
77
|
+
appendHumanMessage: async (threadId, id, content) => {
|
|
78
|
+
log.push({ op: "appendHumanMessage", args: [threadId, id, content] });
|
|
80
79
|
},
|
|
81
|
-
appendToolResult: async (config) => {
|
|
82
|
-
log.push({ op: "appendToolResult", args: [config] });
|
|
80
|
+
appendToolResult: async (id, config) => {
|
|
81
|
+
log.push({ op: "appendToolResult", args: [id, config] });
|
|
83
82
|
},
|
|
84
|
-
appendSystemMessage: async (threadId, content) => {
|
|
85
|
-
log.push({ op: "appendSystemMessage", args: [threadId, content] });
|
|
83
|
+
appendSystemMessage: async (threadId, id, content) => {
|
|
84
|
+
log.push({ op: "appendSystemMessage", args: [threadId, id, content] });
|
|
86
85
|
},
|
|
87
86
|
forkThread: async (source, target) => {
|
|
88
87
|
log.push({ op: "forkThread", args: [source, target] });
|
|
@@ -91,7 +90,9 @@ function createMockThreadOps() {
|
|
|
91
90
|
return { ops, log };
|
|
92
91
|
}
|
|
93
92
|
|
|
94
|
-
function createScriptedRunAgent(
|
|
93
|
+
function createScriptedRunAgent(
|
|
94
|
+
turns: TurnScript[]
|
|
95
|
+
): RunAgentActivity<unknown> {
|
|
95
96
|
let call = 0;
|
|
96
97
|
return async () => {
|
|
97
98
|
const turn = turns[call++];
|
|
@@ -113,7 +114,7 @@ function createEchoTool() {
|
|
|
113
114
|
schema: z.object({ text: z.string() }),
|
|
114
115
|
handler: async (
|
|
115
116
|
args: { text: string },
|
|
116
|
-
_ctx: RouterContext
|
|
117
|
+
_ctx: RouterContext
|
|
117
118
|
): Promise<ToolHandlerResponse<{ echoed: string }>> => ({
|
|
118
119
|
toolResponse: `Echo: ${args.text}`,
|
|
119
120
|
data: { echoed: args.text },
|
|
@@ -216,8 +217,11 @@ describe("createSession edge cases", () => {
|
|
|
216
217
|
|
|
217
218
|
const errorResults = log.filter((l) => {
|
|
218
219
|
if (l.op !== "appendToolResult") return false;
|
|
219
|
-
const config = l.args[
|
|
220
|
-
return
|
|
220
|
+
const config = l.args[1] as ToolResultConfig;
|
|
221
|
+
return (
|
|
222
|
+
typeof config.content === "string" &&
|
|
223
|
+
config.content.includes("Invalid tool call")
|
|
224
|
+
);
|
|
221
225
|
});
|
|
222
226
|
expect(errorResults).toHaveLength(2);
|
|
223
227
|
});
|
|
@@ -365,7 +369,7 @@ describe("createSession edge cases", () => {
|
|
|
365
369
|
});
|
|
366
370
|
|
|
367
371
|
await expect(session.runSession({ stateManager })).rejects.toThrow(
|
|
368
|
-
"unrecoverable tool"
|
|
372
|
+
"unrecoverable tool"
|
|
369
373
|
);
|
|
370
374
|
expect(endReason).toBe("failed");
|
|
371
375
|
});
|
|
@@ -381,9 +385,7 @@ describe("createSession edge cases", () => {
|
|
|
381
385
|
agentName: "TestAgent",
|
|
382
386
|
threadId: "thread-1",
|
|
383
387
|
metadata: { env: "test", version: 42 },
|
|
384
|
-
runAgent: createScriptedRunAgent([
|
|
385
|
-
{ message: "done", toolCalls: [] },
|
|
386
|
-
]),
|
|
388
|
+
runAgent: createScriptedRunAgent([{ message: "done", toolCalls: [] }]),
|
|
387
389
|
threadOps: ops,
|
|
388
390
|
buildContextMessage: () => "go",
|
|
389
391
|
hooks: {
|
|
@@ -422,6 +424,7 @@ describe("createSession edge cases", () => {
|
|
|
422
424
|
data: null,
|
|
423
425
|
createdAt: new Date().toISOString(),
|
|
424
426
|
}),
|
|
427
|
+
forkSandbox: async () => "forked-sandbox-id",
|
|
425
428
|
};
|
|
426
429
|
|
|
427
430
|
const session = await createSession({
|
|
@@ -438,7 +441,7 @@ describe("createSession edge cases", () => {
|
|
|
438
441
|
});
|
|
439
442
|
|
|
440
443
|
await expect(session.runSession({ stateManager })).rejects.toThrow(
|
|
441
|
-
"sandbox creation failed"
|
|
444
|
+
"sandbox creation failed"
|
|
442
445
|
);
|
|
443
446
|
});
|
|
444
447
|
|
|
@@ -462,6 +465,7 @@ describe("createSession edge cases", () => {
|
|
|
462
465
|
data: null,
|
|
463
466
|
createdAt: new Date().toISOString(),
|
|
464
467
|
}),
|
|
468
|
+
forkSandbox: async () => "forked-sandbox-id",
|
|
465
469
|
};
|
|
466
470
|
|
|
467
471
|
const session = await createSession({
|
|
@@ -480,7 +484,7 @@ describe("createSession edge cases", () => {
|
|
|
480
484
|
});
|
|
481
485
|
|
|
482
486
|
await expect(session.runSession({ stateManager })).rejects.toThrow(
|
|
483
|
-
"LLM crash"
|
|
487
|
+
"LLM crash"
|
|
484
488
|
);
|
|
485
489
|
|
|
486
490
|
expect(sandboxLog).toContain("create");
|
|
@@ -505,7 +509,7 @@ describe("createSession edge cases", () => {
|
|
|
505
509
|
});
|
|
506
510
|
|
|
507
511
|
await expect(session.runSession({ stateManager })).rejects.toThrow(
|
|
508
|
-
"No system prompt in state"
|
|
512
|
+
"No system prompt in state"
|
|
509
513
|
);
|
|
510
514
|
});
|
|
511
515
|
|
|
@@ -700,24 +704,27 @@ describe("createSession edge cases", () => {
|
|
|
700
704
|
|
|
701
705
|
const toolResults = log.filter((l) => l.op === "appendToolResult");
|
|
702
706
|
const echoResult = toolResults.find((l) => {
|
|
703
|
-
const config = l.args[
|
|
707
|
+
const config = l.args[1] as ToolResultConfig;
|
|
704
708
|
return config.toolName === "Echo";
|
|
705
709
|
});
|
|
706
710
|
expect(echoResult).toBeDefined();
|
|
707
711
|
if (echoResult) {
|
|
708
|
-
expect((echoResult.args[
|
|
712
|
+
expect((echoResult.args[1] as ToolResultConfig).content).toBe(
|
|
713
|
+
"Echo: valid"
|
|
714
|
+
);
|
|
709
715
|
}
|
|
710
716
|
|
|
711
717
|
const unknownResult = toolResults.find((l) => {
|
|
712
|
-
const config = l.args[
|
|
718
|
+
const config = l.args[1] as ToolResultConfig;
|
|
713
719
|
return config.toolName === "Unknown";
|
|
714
720
|
});
|
|
715
721
|
expect(unknownResult).toBeDefined();
|
|
716
722
|
const unknownContent = unknownResult
|
|
717
|
-
? (unknownResult.args[
|
|
723
|
+
? (unknownResult.args[1] as ToolResultConfig).content
|
|
718
724
|
: undefined;
|
|
719
725
|
expect(
|
|
720
|
-
typeof unknownContent === "string" &&
|
|
726
|
+
typeof unknownContent === "string" &&
|
|
727
|
+
unknownContent.includes("Invalid tool call")
|
|
721
728
|
).toBe(true);
|
|
722
729
|
});
|
|
723
730
|
|
|
@@ -729,9 +736,7 @@ describe("createSession edge cases", () => {
|
|
|
729
736
|
const session = await createSession({
|
|
730
737
|
agentName: "TestAgent",
|
|
731
738
|
threadId: "thread-1",
|
|
732
|
-
runAgent: createScriptedRunAgent([
|
|
733
|
-
{ message: "done", toolCalls: [] },
|
|
734
|
-
]),
|
|
739
|
+
runAgent: createScriptedRunAgent([{ message: "done", toolCalls: [] }]),
|
|
735
740
|
threadOps: ops,
|
|
736
741
|
buildContextMessage: () => [
|
|
737
742
|
{ type: "text", text: "Hello" },
|
|
@@ -749,7 +754,7 @@ describe("createSession edge cases", () => {
|
|
|
749
754
|
expect(humanOps).toHaveLength(1);
|
|
750
755
|
const humanOp = humanOps[0];
|
|
751
756
|
if (!humanOp) throw new Error("expected human op");
|
|
752
|
-
const content = humanOp.args[
|
|
757
|
+
const content = humanOp.args[2];
|
|
753
758
|
expect(Array.isArray(content)).toBe(true);
|
|
754
759
|
const firstContent = (content as { type: string }[])[0];
|
|
755
760
|
if (!firstContent) throw new Error("expected content item");
|
|
@@ -834,7 +839,7 @@ describe("createSession edge cases", () => {
|
|
|
834
839
|
|
|
835
840
|
const toolResults = log.filter((l) => {
|
|
836
841
|
if (l.op !== "appendToolResult") return false;
|
|
837
|
-
const config = l.args[
|
|
842
|
+
const config = l.args[1] as ToolResultConfig;
|
|
838
843
|
return config.toolName === "SelfAppend";
|
|
839
844
|
});
|
|
840
845
|
expect(toolResults).toHaveLength(0);
|
|
@@ -860,7 +865,10 @@ describe("createSession edge cases", () => {
|
|
|
860
865
|
buildContextMessage: () => "go",
|
|
861
866
|
hooks: {
|
|
862
867
|
onPreToolUse: async ({ toolCall }) => {
|
|
863
|
-
if (
|
|
868
|
+
if (
|
|
869
|
+
toolCall.args &&
|
|
870
|
+
(toolCall.args as { text: string }).text === "skip-me"
|
|
871
|
+
) {
|
|
864
872
|
return { skip: true };
|
|
865
873
|
}
|
|
866
874
|
return {};
|
|
@@ -878,8 +886,10 @@ describe("createSession edge cases", () => {
|
|
|
878
886
|
expect(toolResults).toHaveLength(1);
|
|
879
887
|
const toolResult = toolResults[0];
|
|
880
888
|
if (!toolResult) throw new Error("expected tool result");
|
|
881
|
-
const content = (toolResult.args[
|
|
882
|
-
expect(typeof content === "string" && content.includes("Skipped")).toBe(
|
|
889
|
+
const content = (toolResult.args[1] as ToolResultConfig).content;
|
|
890
|
+
expect(typeof content === "string" && content.includes("Skipped")).toBe(
|
|
891
|
+
true
|
|
892
|
+
);
|
|
883
893
|
});
|
|
884
894
|
|
|
885
895
|
// --- Sandbox snapshot is not called on normal flow ---
|
|
@@ -897,6 +907,7 @@ describe("createSession edge cases", () => {
|
|
|
897
907
|
createSandbox: async () => ({ sandboxId: "sb-test" }),
|
|
898
908
|
destroySandbox: async () => {},
|
|
899
909
|
snapshotSandbox: snapshotSpy,
|
|
910
|
+
forkSandbox: async () => "forked-sandbox-id",
|
|
900
911
|
};
|
|
901
912
|
|
|
902
913
|
const session = await createSession({
|