zeitlich 0.2.36 → 0.2.38
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-BKhMtKDd.d.ts} +4 -2
- package/dist/{activities-hd4aNnZE.d.cts → activities-CDcwkRZs.d.cts} +4 -2
- package/dist/adapters/sandbox/bedrock/index.cjs +17 -14
- package/dist/adapters/sandbox/bedrock/index.cjs.map +1 -1
- package/dist/adapters/sandbox/bedrock/index.d.cts +7 -6
- package/dist/adapters/sandbox/bedrock/index.d.ts +7 -6
- package/dist/adapters/sandbox/bedrock/index.js +17 -14
- 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 +11 -3
- package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
- package/dist/adapters/sandbox/daytona/index.d.cts +5 -4
- package/dist/adapters/sandbox/daytona/index.d.ts +5 -4
- package/dist/adapters/sandbox/daytona/index.js +11 -3
- 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 +73 -12
- package/dist/adapters/sandbox/e2b/index.cjs.map +1 -1
- package/dist/adapters/sandbox/e2b/index.d.cts +26 -4
- package/dist/adapters/sandbox/e2b/index.d.ts +26 -4
- package/dist/adapters/sandbox/e2b/index.js +73 -12
- 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 +8 -3
- package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
- package/dist/adapters/sandbox/inmemory/index.d.cts +5 -4
- package/dist/adapters/sandbox/inmemory/index.d.ts +5 -4
- package/dist/adapters/sandbox/inmemory/index.js +8 -3
- 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 +94 -39
- 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 +94 -39
- package/dist/adapters/thread/anthropic/index.js.map +1 -1
- package/dist/adapters/thread/anthropic/workflow.cjs +7 -2
- 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 +7 -2
- package/dist/adapters/thread/anthropic/workflow.js.map +1 -1
- package/dist/adapters/thread/google-genai/index.cjs +77 -28
- 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 +77 -28
- package/dist/adapters/thread/google-genai/index.js.map +1 -1
- package/dist/adapters/thread/google-genai/workflow.cjs +7 -2
- 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 +7 -2
- package/dist/adapters/thread/google-genai/workflow.js.map +1 -1
- package/dist/adapters/thread/langchain/index.cjs +57 -10
- 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 +57 -10
- package/dist/adapters/thread/langchain/index.js.map +1 -1
- package/dist/adapters/thread/langchain/workflow.cjs +7 -2
- 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 +7 -2
- package/dist/adapters/thread/langchain/workflow.js.map +1 -1
- package/dist/index.cjs +322 -146
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -14
- package/dist/index.d.ts +20 -14
- package/dist/index.js +323 -147
- package/dist/index.js.map +1 -1
- package/dist/{proxy-BjdFGPTm.d.ts → proxy-CUlKSvZS.d.ts} +1 -1
- package/dist/{proxy-7RnVaPdJ.d.cts → proxy-D_3x7RN4.d.cts} +1 -1
- package/dist/{thread-manager-CbpiGq1L.d.ts → thread-manager-CVu7o2cs.d.ts} +4 -2
- package/dist/{thread-manager-DzXm9eeI.d.cts → thread-manager-HSwyh28L.d.cts} +4 -2
- package/dist/{thread-manager-BBzNgQWH.d.cts → thread-manager-c1gPopAG.d.ts} +4 -2
- package/dist/{thread-manager-DjN5JYul.d.ts → thread-manager-wGi-LqIP.d.cts} +4 -2
- package/dist/{types-Mc_4BCfT.d.cts → types-BH_IRryz.d.ts} +10 -1
- package/dist/{types-yiXmqedU.d.ts → types-BaOw4hKI.d.cts} +10 -1
- package/dist/{types-DQ1l_gXL.d.cts → types-C06FwR96.d.cts} +121 -17
- package/dist/{types-wiGLvxWf.d.ts → types-DAsQ21Rt.d.ts} +1 -1
- package/dist/{types-CADc5V_P.d.ts → types-DNr31FzL.d.ts} +121 -17
- package/dist/{types-CBH54cwr.d.cts → types-lm8tMNJQ.d.cts} +1 -1
- package/dist/{types-DxCpFNv_.d.cts → types-yx0LzPGn.d.cts} +44 -5
- package/dist/{types-DxCpFNv_.d.ts → types-yx0LzPGn.d.ts} +44 -5
- package/dist/{workflow-DhtWRovz.d.cts → workflow-CSCkpwAL.d.ts} +2 -2
- package/dist/{workflow-P2pTSfKu.d.ts → workflow-DuvMZ8Vm.d.cts} +2 -2
- package/dist/workflow.cjs +274 -130
- 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 +275 -131
- package/dist/workflow.js.map +1 -1
- package/package.json +2 -2
- package/src/adapters/sandbox/bedrock/filesystem.ts +6 -12
- package/src/adapters/sandbox/bedrock/index.ts +22 -11
- package/src/adapters/sandbox/bedrock/proxy.ts +2 -0
- package/src/adapters/sandbox/daytona/index.ts +18 -3
- 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 +87 -14
- package/src/adapters/sandbox/e2b/proxy.ts +2 -0
- package/src/adapters/sandbox/e2b/types.ts +16 -0
- package/src/adapters/sandbox/inmemory/index.ts +17 -3
- package/src/adapters/sandbox/inmemory/proxy.ts +2 -0
- package/src/adapters/thread/anthropic/activities.ts +58 -26
- package/src/adapters/thread/anthropic/model-invoker.ts +18 -7
- 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 +63 -46
- package/src/adapters/thread/google-genai/activities.ts +20 -2
- package/src/adapters/thread/google-genai/model-invoker.ts +27 -7
- 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 +57 -33
- package/src/adapters/thread/langchain/activities.ts +55 -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 +5 -4
- 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 +23 -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 +18 -3
- package/src/lib/model/proxy.ts +2 -2
- package/src/lib/model/types.ts +10 -0
- package/src/lib/observability/hooks.ts +4 -5
- package/src/lib/observability/index.ts +1 -4
- package/src/lib/sandbox/manager.ts +45 -20
- 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 +60 -6
- package/src/lib/session/session-edge-cases.integration.test.ts +316 -14
- package/src/lib/session/session.integration.test.ts +161 -1
- package/src/lib/session/session.ts +106 -21
- package/src/lib/session/types.ts +25 -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 +526 -248
- 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/manager.ts +18 -0
- package/src/lib/thread/proxy.ts +4 -4
- package/src/lib/thread/types.ts +20 -3
- package/src/lib/tool-router/index.ts +3 -5
- package/src/lib/tool-router/router-edge-cases.integration.test.ts +93 -1
- package/src/lib/tool-router/router.integration.test.ts +12 -0
- package/src/lib/tool-router/router.ts +90 -16
- package/src/lib/tool-router/types.ts +45 -4
- 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 +22 -7
- package/tsup.config.ts +9 -6
- package/src/lib/.env +0 -1
- package/src/tools/bash/.env +0 -1
|
@@ -2,7 +2,10 @@ import type Redis from "ioredis";
|
|
|
2
2
|
import type Anthropic from "@anthropic-ai/sdk";
|
|
3
3
|
import type { SerializableToolDefinition } from "../../../lib/types";
|
|
4
4
|
import type { AgentResponse, ModelInvokerConfig } from "../../../lib/model";
|
|
5
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
createAnthropicThreadManager,
|
|
7
|
+
type AnthropicThreadManagerHooks,
|
|
8
|
+
} from "./thread-manager";
|
|
6
9
|
import { getActivityContext } from "../../../lib/activity";
|
|
7
10
|
|
|
8
11
|
export interface AnthropicModelInvokerConfig {
|
|
@@ -15,7 +18,7 @@ export interface AnthropicModelInvokerConfig {
|
|
|
15
18
|
}
|
|
16
19
|
|
|
17
20
|
function toAnthropicTools(
|
|
18
|
-
tools: SerializableToolDefinition[]
|
|
21
|
+
tools: SerializableToolDefinition[]
|
|
19
22
|
): Anthropic.Messages.Tool[] {
|
|
20
23
|
return tools.map((t) => ({
|
|
21
24
|
name: t.name,
|
|
@@ -56,13 +59,19 @@ export function createAnthropicModelInvoker({
|
|
|
56
59
|
hooks,
|
|
57
60
|
}: AnthropicModelInvokerConfig) {
|
|
58
61
|
return async function invokeAnthropicModel(
|
|
59
|
-
config: ModelInvokerConfig
|
|
62
|
+
config: ModelInvokerConfig
|
|
60
63
|
): Promise<AgentResponse<Anthropic.Messages.Message>> {
|
|
61
64
|
const { threadId, threadKey, state } = config;
|
|
62
65
|
const { heartbeat, signal } = getActivityContext();
|
|
63
66
|
|
|
64
|
-
const thread = createAnthropicThreadManager({
|
|
65
|
-
|
|
67
|
+
const thread = createAnthropicThreadManager({
|
|
68
|
+
redis,
|
|
69
|
+
threadId,
|
|
70
|
+
key: threadKey,
|
|
71
|
+
hooks,
|
|
72
|
+
});
|
|
73
|
+
const { messages, system, storedLength } =
|
|
74
|
+
await thread.prepareForInvocation();
|
|
66
75
|
|
|
67
76
|
const anthropicTools = toAnthropicTools(state.tools);
|
|
68
77
|
const tools = anthropicTools.length > 0 ? anthropicTools : undefined;
|
|
@@ -85,7 +94,7 @@ export function createAnthropicModelInvoker({
|
|
|
85
94
|
|
|
86
95
|
const toolCalls = response.content.filter(
|
|
87
96
|
(block): block is Anthropic.Messages.ToolUseBlock =>
|
|
88
|
-
block.type === "tool_use"
|
|
97
|
+
block.type === "tool_use"
|
|
89
98
|
);
|
|
90
99
|
|
|
91
100
|
return {
|
|
@@ -98,9 +107,11 @@ export function createAnthropicModelInvoker({
|
|
|
98
107
|
usage: {
|
|
99
108
|
inputTokens: response.usage.input_tokens,
|
|
100
109
|
outputTokens: response.usage.output_tokens,
|
|
101
|
-
cachedWriteTokens:
|
|
110
|
+
cachedWriteTokens:
|
|
111
|
+
response.usage.cache_creation_input_tokens ?? undefined,
|
|
102
112
|
cachedReadTokens: response.usage.cache_read_input_tokens ?? undefined,
|
|
103
113
|
},
|
|
114
|
+
threadLengthAtCall: storedLength,
|
|
104
115
|
};
|
|
105
116
|
};
|
|
106
117
|
}
|
|
@@ -27,7 +27,11 @@ const ADAPTER_PREFIX = "anthropic";
|
|
|
27
27
|
|
|
28
28
|
export function proxyAnthropicThreadOps(
|
|
29
29
|
scope?: string,
|
|
30
|
-
options?: Parameters<typeof createThreadOpsProxy>[2]
|
|
30
|
+
options?: Parameters<typeof createThreadOpsProxy>[2]
|
|
31
31
|
): ActivityInterfaceFor<ThreadOps<AnthropicContent>> {
|
|
32
|
-
return createThreadOpsProxy(
|
|
32
|
+
return createThreadOpsProxy(
|
|
33
|
+
ADAPTER_PREFIX,
|
|
34
|
+
scope,
|
|
35
|
+
options
|
|
36
|
+
) as ActivityInterfaceFor<ThreadOps<AnthropicContent>>;
|
|
33
37
|
}
|
|
@@ -27,7 +27,10 @@ const userMsg: StoredMessage = {
|
|
|
27
27
|
|
|
28
28
|
const assistantMsg: StoredMessage = {
|
|
29
29
|
id: "msg-2",
|
|
30
|
-
message: {
|
|
30
|
+
message: {
|
|
31
|
+
role: "assistant",
|
|
32
|
+
content: [{ type: "text", text: "Hi there!" }],
|
|
33
|
+
},
|
|
31
34
|
};
|
|
32
35
|
|
|
33
36
|
describe("Anthropic thread manager hooks", () => {
|
|
@@ -40,7 +43,9 @@ describe("Anthropic thread manager hooks", () => {
|
|
|
40
43
|
...msg,
|
|
41
44
|
message: {
|
|
42
45
|
...msg.message,
|
|
43
|
-
content: [
|
|
46
|
+
content: [
|
|
47
|
+
{ type: "text" as const, text: `[modified] ${firstBlock?.text}` },
|
|
48
|
+
],
|
|
44
49
|
},
|
|
45
50
|
};
|
|
46
51
|
});
|
|
@@ -55,10 +60,18 @@ describe("Anthropic thread manager hooks", () => {
|
|
|
55
60
|
const { messages, system } = await tm.prepareForInvocation();
|
|
56
61
|
|
|
57
62
|
expect(hook).toHaveBeenCalledTimes(3);
|
|
58
|
-
expect(hook).toHaveBeenCalledWith(systemMsg, 0, [
|
|
63
|
+
expect(hook).toHaveBeenCalledWith(systemMsg, 0, [
|
|
64
|
+
systemMsg,
|
|
65
|
+
userMsg,
|
|
66
|
+
assistantMsg,
|
|
67
|
+
]);
|
|
59
68
|
expect(system).toBe("You are helpful.");
|
|
60
|
-
expect(messages[0]?.content).toEqual([
|
|
61
|
-
|
|
69
|
+
expect(messages[0]?.content).toEqual([
|
|
70
|
+
{ type: "text", text: "[modified] Hello" },
|
|
71
|
+
]);
|
|
72
|
+
expect(messages[1]?.content).toEqual([
|
|
73
|
+
{ type: "text", text: "[modified] Hi there!" },
|
|
74
|
+
]);
|
|
62
75
|
});
|
|
63
76
|
|
|
64
77
|
it("is not called when not configured", async () => {
|
|
@@ -90,7 +103,9 @@ describe("Anthropic thread manager hooks", () => {
|
|
|
90
103
|
const { messages } = await tm.prepareForInvocation();
|
|
91
104
|
|
|
92
105
|
expect(hook).toHaveBeenCalledTimes(2);
|
|
93
|
-
expect(messages[0]?.content).toEqual([
|
|
106
|
+
expect(messages[0]?.content).toEqual([
|
|
107
|
+
{ type: "text", text: "[post] done" },
|
|
108
|
+
]);
|
|
94
109
|
});
|
|
95
110
|
|
|
96
111
|
it("receives the full prepared messages array", async () => {
|
|
@@ -105,7 +120,11 @@ describe("Anthropic thread manager hooks", () => {
|
|
|
105
120
|
|
|
106
121
|
await tm.prepareForInvocation();
|
|
107
122
|
|
|
108
|
-
const args = hook.mock.calls[0] as unknown as [
|
|
123
|
+
const args = hook.mock.calls[0] as unknown as [
|
|
124
|
+
unknown,
|
|
125
|
+
number,
|
|
126
|
+
unknown[],
|
|
127
|
+
];
|
|
109
128
|
expect(args[2]).toHaveLength(2);
|
|
110
129
|
});
|
|
111
130
|
});
|
|
@@ -9,9 +9,7 @@ import type {
|
|
|
9
9
|
} from "../../../lib/thread/types";
|
|
10
10
|
|
|
11
11
|
/** SDK-native content type for Anthropic human messages */
|
|
12
|
-
export type AnthropicContent =
|
|
13
|
-
| string
|
|
14
|
-
| Anthropic.Messages.ContentBlockParam[];
|
|
12
|
+
export type AnthropicContent = string | Anthropic.Messages.ContentBlockParam[];
|
|
15
13
|
|
|
16
14
|
/** SDK-native content type for Anthropic system prompts (supports cache_control blocks) */
|
|
17
15
|
export type AnthropicSystemContent =
|
|
@@ -26,7 +24,10 @@ export interface StoredMessage {
|
|
|
26
24
|
isSystem?: boolean;
|
|
27
25
|
}
|
|
28
26
|
|
|
29
|
-
export type AnthropicThreadManagerHooks = ThreadManagerHooks<
|
|
27
|
+
export type AnthropicThreadManagerHooks = ThreadManagerHooks<
|
|
28
|
+
StoredMessage,
|
|
29
|
+
Anthropic.Messages.MessageParam
|
|
30
|
+
>;
|
|
30
31
|
|
|
31
32
|
export interface AnthropicThreadManagerConfig {
|
|
32
33
|
redis: Redis;
|
|
@@ -40,14 +41,20 @@ export interface AnthropicThreadManagerConfig {
|
|
|
40
41
|
export interface AnthropicInvocationPayload {
|
|
41
42
|
messages: Anthropic.Messages.MessageParam[];
|
|
42
43
|
system?: string | Anthropic.Messages.TextBlockParam[];
|
|
44
|
+
/** Number of stored messages loaded from Redis before preparation. */
|
|
45
|
+
storedLength: number;
|
|
43
46
|
}
|
|
44
47
|
|
|
45
48
|
/** Thread manager with Anthropic MessageParam convenience helpers */
|
|
46
|
-
export interface AnthropicThreadManager
|
|
47
|
-
|
|
49
|
+
export interface AnthropicThreadManager extends ProviderThreadManager<
|
|
50
|
+
StoredMessage,
|
|
51
|
+
AnthropicContent,
|
|
52
|
+
JsonValue,
|
|
53
|
+
AnthropicSystemContent
|
|
54
|
+
> {
|
|
48
55
|
appendAssistantMessage(
|
|
49
56
|
id: string,
|
|
50
|
-
content: Anthropic.Messages.ContentBlock[]
|
|
57
|
+
content: Anthropic.Messages.ContentBlock[]
|
|
51
58
|
): Promise<void>;
|
|
52
59
|
prepareForInvocation(): Promise<AnthropicInvocationPayload>;
|
|
53
60
|
}
|
|
@@ -58,7 +65,7 @@ function storedMessageId(msg: StoredMessage): string {
|
|
|
58
65
|
|
|
59
66
|
/** Normalise content into an array of ContentBlockParam */
|
|
60
67
|
function toContentBlocks(
|
|
61
|
-
content: AnthropicContent
|
|
68
|
+
content: AnthropicContent
|
|
62
69
|
): Anthropic.Messages.ContentBlockParam[] {
|
|
63
70
|
if (typeof content === "string") {
|
|
64
71
|
return [{ type: "text", text: content }];
|
|
@@ -72,7 +79,7 @@ function toContentBlocks(
|
|
|
72
79
|
* merging, multiple sequential tool-result messages would violate this.
|
|
73
80
|
*/
|
|
74
81
|
function mergeConsecutiveMessages(
|
|
75
|
-
messages: Anthropic.Messages.MessageParam[]
|
|
82
|
+
messages: Anthropic.Messages.MessageParam[]
|
|
76
83
|
): Anthropic.Messages.MessageParam[] {
|
|
77
84
|
const merged: Anthropic.Messages.MessageParam[] = [];
|
|
78
85
|
for (const msg of messages) {
|
|
@@ -88,9 +95,7 @@ function mergeConsecutiveMessages(
|
|
|
88
95
|
} else {
|
|
89
96
|
merged.push({
|
|
90
97
|
...msg,
|
|
91
|
-
content: Array.isArray(msg.content)
|
|
92
|
-
? [...msg.content]
|
|
93
|
-
: msg.content,
|
|
98
|
+
content: Array.isArray(msg.content) ? [...msg.content] : msg.content,
|
|
94
99
|
});
|
|
95
100
|
}
|
|
96
101
|
}
|
|
@@ -103,7 +108,7 @@ function mergeConsecutiveMessages(
|
|
|
103
108
|
* appending typed messages.
|
|
104
109
|
*/
|
|
105
110
|
export function createAnthropicThreadManager(
|
|
106
|
-
config: AnthropicThreadManagerConfig
|
|
111
|
+
config: AnthropicThreadManagerConfig
|
|
107
112
|
): AnthropicThreadManager {
|
|
108
113
|
const baseConfig: ThreadManagerConfig<StoredMessage> = {
|
|
109
114
|
redis: config.redis,
|
|
@@ -117,49 +122,56 @@ export function createAnthropicThreadManager(
|
|
|
117
122
|
const helpers: Omit<AnthropicThreadManager, keyof typeof base> = {
|
|
118
123
|
async appendUserMessage(
|
|
119
124
|
id: string,
|
|
120
|
-
content: AnthropicContent
|
|
125
|
+
content: AnthropicContent
|
|
121
126
|
): Promise<void> {
|
|
122
|
-
await base.append([
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
127
|
+
await base.append([
|
|
128
|
+
{
|
|
129
|
+
id,
|
|
130
|
+
message: { role: "user", content: toContentBlocks(content) },
|
|
131
|
+
},
|
|
132
|
+
]);
|
|
126
133
|
},
|
|
127
134
|
|
|
128
135
|
async appendSystemMessage(
|
|
129
136
|
id: string,
|
|
130
|
-
content: AnthropicSystemContent
|
|
137
|
+
content: AnthropicSystemContent
|
|
131
138
|
): Promise<void> {
|
|
132
139
|
await base.initialize();
|
|
133
|
-
await base.append([
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
+
await base.append([
|
|
141
|
+
{
|
|
142
|
+
id,
|
|
143
|
+
// Stored under a user-role placeholder to satisfy the MessageParam
|
|
144
|
+
// shape; the `isSystem` flag steers extraction in prepareForInvocation.
|
|
145
|
+
message: {
|
|
146
|
+
role: "user",
|
|
147
|
+
content: content as Anthropic.Messages.MessageParam["content"],
|
|
148
|
+
},
|
|
149
|
+
isSystem: true,
|
|
140
150
|
},
|
|
141
|
-
|
|
142
|
-
}]);
|
|
151
|
+
]);
|
|
143
152
|
},
|
|
144
153
|
|
|
145
154
|
async appendAssistantMessage(
|
|
146
155
|
id: string,
|
|
147
|
-
content: Anthropic.Messages.ContentBlock[]
|
|
156
|
+
content: Anthropic.Messages.ContentBlock[]
|
|
148
157
|
): Promise<void> {
|
|
149
|
-
await base.append([
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
158
|
+
await base.append([
|
|
159
|
+
{
|
|
160
|
+
id,
|
|
161
|
+
message: {
|
|
162
|
+
role: "assistant",
|
|
163
|
+
content:
|
|
164
|
+
content as unknown as Anthropic.Messages.ContentBlockParam[],
|
|
165
|
+
},
|
|
154
166
|
},
|
|
155
|
-
|
|
167
|
+
]);
|
|
156
168
|
},
|
|
157
169
|
|
|
158
170
|
async appendToolResult(
|
|
159
171
|
id: string,
|
|
160
172
|
toolCallId: string,
|
|
161
173
|
_toolName: string,
|
|
162
|
-
content: JsonValue
|
|
174
|
+
content: JsonValue
|
|
163
175
|
): Promise<void> {
|
|
164
176
|
const toolContent =
|
|
165
177
|
typeof content === "string"
|
|
@@ -167,17 +179,21 @@ export function createAnthropicThreadManager(
|
|
|
167
179
|
: Array.isArray(content)
|
|
168
180
|
? (content as unknown as Anthropic.Messages.ToolResultBlockParam["content"])
|
|
169
181
|
: JSON.stringify(content);
|
|
170
|
-
await base.append([
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
182
|
+
await base.append([
|
|
183
|
+
{
|
|
184
|
+
id,
|
|
185
|
+
message: {
|
|
186
|
+
role: "user",
|
|
187
|
+
content: [
|
|
188
|
+
{
|
|
189
|
+
type: "tool_result" as const,
|
|
190
|
+
tool_use_id: toolCallId,
|
|
191
|
+
content: toolContent,
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
},
|
|
179
195
|
},
|
|
180
|
-
|
|
196
|
+
]);
|
|
181
197
|
},
|
|
182
198
|
|
|
183
199
|
async prepareForInvocation(): Promise<AnthropicInvocationPayload> {
|
|
@@ -206,6 +222,7 @@ export function createAnthropicThreadManager(
|
|
|
206
222
|
? messages.map((msg, i) => onPreparedMessage(msg, i, messages))
|
|
207
223
|
: messages,
|
|
208
224
|
...(system ? { system } : {}),
|
|
225
|
+
storedLength: stored.length,
|
|
209
226
|
};
|
|
210
227
|
},
|
|
211
228
|
};
|
|
@@ -200,7 +200,7 @@ export function createGoogleGenAIAdapter(
|
|
|
200
200
|
threadId: string,
|
|
201
201
|
id: string,
|
|
202
202
|
message: Content,
|
|
203
|
-
threadKey?: string
|
|
203
|
+
threadKey?: string
|
|
204
204
|
): Promise<void> {
|
|
205
205
|
const thread = createGoogleGenAIThreadManager({
|
|
206
206
|
redis,
|
|
@@ -222,6 +222,19 @@ export function createGoogleGenAIAdapter(
|
|
|
222
222
|
});
|
|
223
223
|
await thread.fork(targetThreadId);
|
|
224
224
|
},
|
|
225
|
+
|
|
226
|
+
async truncateThread(
|
|
227
|
+
threadId: string,
|
|
228
|
+
length: number,
|
|
229
|
+
threadKey?: string,
|
|
230
|
+
): Promise<void> {
|
|
231
|
+
const thread = createGoogleGenAIThreadManager({
|
|
232
|
+
redis,
|
|
233
|
+
threadId,
|
|
234
|
+
key: threadKey,
|
|
235
|
+
});
|
|
236
|
+
await thread.truncate(length);
|
|
237
|
+
},
|
|
225
238
|
};
|
|
226
239
|
|
|
227
240
|
function createActivities<S extends string = "">(
|
|
@@ -240,7 +253,12 @@ export function createGoogleGenAIAdapter(
|
|
|
240
253
|
model: string,
|
|
241
254
|
client: GoogleGenAI
|
|
242
255
|
): ModelInvoker<Content> =>
|
|
243
|
-
createGoogleGenAIModelInvoker({
|
|
256
|
+
createGoogleGenAIModelInvoker({
|
|
257
|
+
redis,
|
|
258
|
+
client,
|
|
259
|
+
model,
|
|
260
|
+
hooks: config.hooks,
|
|
261
|
+
});
|
|
244
262
|
|
|
245
263
|
const invoker: ModelInvoker<Content> =
|
|
246
264
|
config.model && config.client
|
|
@@ -1,8 +1,17 @@
|
|
|
1
1
|
import type Redis from "ioredis";
|
|
2
|
-
import type {
|
|
2
|
+
import type {
|
|
3
|
+
GoogleGenAI,
|
|
4
|
+
Content,
|
|
5
|
+
FunctionDeclaration,
|
|
6
|
+
Part,
|
|
7
|
+
GenerateContentResponse,
|
|
8
|
+
} from "@google/genai";
|
|
3
9
|
import type { SerializableToolDefinition } from "../../../lib/types";
|
|
4
10
|
import type { AgentResponse, ModelInvokerConfig } from "../../../lib/model";
|
|
5
|
-
import {
|
|
11
|
+
import {
|
|
12
|
+
createGoogleGenAIThreadManager,
|
|
13
|
+
type GoogleGenAIThreadManagerHooks,
|
|
14
|
+
} from "./thread-manager";
|
|
6
15
|
import { getActivityContext } from "../../../lib/activity";
|
|
7
16
|
|
|
8
17
|
export interface GoogleGenAIModelInvokerConfig {
|
|
@@ -13,7 +22,7 @@ export interface GoogleGenAIModelInvokerConfig {
|
|
|
13
22
|
}
|
|
14
23
|
|
|
15
24
|
function toFunctionDeclarations(
|
|
16
|
-
tools: SerializableToolDefinition[]
|
|
25
|
+
tools: SerializableToolDefinition[]
|
|
17
26
|
): FunctionDeclaration[] {
|
|
18
27
|
return tools.map((t) => ({
|
|
19
28
|
name: t.name,
|
|
@@ -53,13 +62,18 @@ export function createGoogleGenAIModelInvoker({
|
|
|
53
62
|
hooks,
|
|
54
63
|
}: GoogleGenAIModelInvokerConfig) {
|
|
55
64
|
return async function invokeGoogleGenAIModel(
|
|
56
|
-
config: ModelInvokerConfig
|
|
65
|
+
config: ModelInvokerConfig
|
|
57
66
|
): Promise<AgentResponse<Content>> {
|
|
58
67
|
const { threadId, threadKey, state } = config;
|
|
59
68
|
const { heartbeat, signal } = getActivityContext();
|
|
60
69
|
|
|
61
|
-
const thread = createGoogleGenAIThreadManager({
|
|
62
|
-
|
|
70
|
+
const thread = createGoogleGenAIThreadManager({
|
|
71
|
+
redis,
|
|
72
|
+
threadId,
|
|
73
|
+
key: threadKey,
|
|
74
|
+
hooks,
|
|
75
|
+
});
|
|
76
|
+
const { contents, systemInstruction, storedLength } =
|
|
63
77
|
await thread.prepareForInvocation();
|
|
64
78
|
|
|
65
79
|
const functionDeclarations = toFunctionDeclarations(state.tools);
|
|
@@ -103,6 +117,7 @@ export function createGoogleGenAIModelInvoker({
|
|
|
103
117
|
outputTokens: lastChunk.usageMetadata?.candidatesTokenCount,
|
|
104
118
|
cachedReadTokens: lastChunk.usageMetadata?.cachedContentTokenCount,
|
|
105
119
|
},
|
|
120
|
+
threadLengthAtCall: storedLength,
|
|
106
121
|
};
|
|
107
122
|
};
|
|
108
123
|
}
|
|
@@ -125,6 +140,11 @@ export async function invokeGoogleGenAIModel({
|
|
|
125
140
|
hooks?: GoogleGenAIThreadManagerHooks;
|
|
126
141
|
config: ModelInvokerConfig;
|
|
127
142
|
}): Promise<AgentResponse<Content>> {
|
|
128
|
-
const invoker = createGoogleGenAIModelInvoker({
|
|
143
|
+
const invoker = createGoogleGenAIModelInvoker({
|
|
144
|
+
redis,
|
|
145
|
+
client,
|
|
146
|
+
model,
|
|
147
|
+
hooks,
|
|
148
|
+
});
|
|
129
149
|
return invoker(config);
|
|
130
150
|
}
|
|
@@ -27,7 +27,11 @@ const ADAPTER_PREFIX = "googleGenAI";
|
|
|
27
27
|
|
|
28
28
|
export function proxyGoogleGenAIThreadOps(
|
|
29
29
|
scope?: string,
|
|
30
|
-
options?: Parameters<typeof createThreadOpsProxy>[2]
|
|
30
|
+
options?: Parameters<typeof createThreadOpsProxy>[2]
|
|
31
31
|
): ActivityInterfaceFor<ThreadOps<GoogleGenAIContent>> {
|
|
32
|
-
return createThreadOpsProxy(
|
|
32
|
+
return createThreadOpsProxy(
|
|
33
|
+
ADAPTER_PREFIX,
|
|
34
|
+
scope,
|
|
35
|
+
options
|
|
36
|
+
) as ActivityInterfaceFor<ThreadOps<GoogleGenAIContent>>;
|
|
33
37
|
}
|
|
@@ -39,7 +39,9 @@ describe("Google GenAI thread manager hooks", () => {
|
|
|
39
39
|
...msg,
|
|
40
40
|
content: {
|
|
41
41
|
...msg.content,
|
|
42
|
-
parts: [
|
|
42
|
+
parts: [
|
|
43
|
+
{ text: `[modified] ${msg.content.parts?.[0]?.text ?? ""}` },
|
|
44
|
+
],
|
|
43
45
|
},
|
|
44
46
|
};
|
|
45
47
|
});
|
|
@@ -54,7 +56,11 @@ describe("Google GenAI thread manager hooks", () => {
|
|
|
54
56
|
const { contents, systemInstruction } = await tm.prepareForInvocation();
|
|
55
57
|
|
|
56
58
|
expect(hook).toHaveBeenCalledTimes(3);
|
|
57
|
-
expect(hook).toHaveBeenCalledWith(systemContent, 0, [
|
|
59
|
+
expect(hook).toHaveBeenCalledWith(systemContent, 0, [
|
|
60
|
+
systemContent,
|
|
61
|
+
userContent,
|
|
62
|
+
modelContent,
|
|
63
|
+
]);
|
|
58
64
|
expect(systemInstruction).toEqual([{ text: "You are helpful." }]);
|
|
59
65
|
expect(contents[0]?.parts?.[0]?.text).toBe("[modified] Hello");
|
|
60
66
|
expect(contents[1]?.parts?.[0]?.text).toBe("[modified] Hi there!");
|
|
@@ -106,7 +112,11 @@ describe("Google GenAI thread manager hooks", () => {
|
|
|
106
112
|
|
|
107
113
|
await tm.prepareForInvocation();
|
|
108
114
|
|
|
109
|
-
const args = hook.mock.calls[0] as unknown as [
|
|
115
|
+
const args = hook.mock.calls[0] as unknown as [
|
|
116
|
+
Content,
|
|
117
|
+
number,
|
|
118
|
+
Content[],
|
|
119
|
+
];
|
|
110
120
|
expect(args[2]).toHaveLength(2);
|
|
111
121
|
});
|
|
112
122
|
});
|
|
@@ -20,7 +20,10 @@ export interface StoredContent {
|
|
|
20
20
|
content: Content;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
-
export type GoogleGenAIThreadManagerHooks = ThreadManagerHooks<
|
|
23
|
+
export type GoogleGenAIThreadManagerHooks = ThreadManagerHooks<
|
|
24
|
+
StoredContent,
|
|
25
|
+
Content
|
|
26
|
+
>;
|
|
24
27
|
|
|
25
28
|
export interface GoogleGenAIThreadManagerConfig {
|
|
26
29
|
redis: Redis;
|
|
@@ -34,11 +37,17 @@ export interface GoogleGenAIThreadManagerConfig {
|
|
|
34
37
|
export interface GoogleGenAIInvocationPayload {
|
|
35
38
|
contents: Content[];
|
|
36
39
|
systemInstruction?: Part[];
|
|
40
|
+
/** Number of stored messages loaded from Redis before preparation. */
|
|
41
|
+
storedLength: number;
|
|
37
42
|
}
|
|
38
43
|
|
|
39
44
|
/** Thread manager with Google GenAI Content convenience helpers */
|
|
40
|
-
export interface GoogleGenAIThreadManager
|
|
41
|
-
|
|
45
|
+
export interface GoogleGenAIThreadManager extends ProviderThreadManager<
|
|
46
|
+
StoredContent,
|
|
47
|
+
GoogleGenAIContent,
|
|
48
|
+
GoogleGenAIToolResponse,
|
|
49
|
+
GoogleGenAISystemContent
|
|
50
|
+
> {
|
|
42
51
|
appendModelContent(id: string, parts: Part[]): Promise<void>;
|
|
43
52
|
prepareForInvocation(): Promise<GoogleGenAIInvocationPayload>;
|
|
44
53
|
}
|
|
@@ -56,7 +65,9 @@ function toParts(content: GoogleGenAIContent): Part[] {
|
|
|
56
65
|
}
|
|
57
66
|
|
|
58
67
|
/** Convert a string or object into a Record suitable for functionResponse.response */
|
|
59
|
-
function toFunctionResponse(
|
|
68
|
+
function toFunctionResponse(
|
|
69
|
+
content: string | Record<string, unknown>
|
|
70
|
+
): Record<string, unknown> {
|
|
60
71
|
if (typeof content === "object") {
|
|
61
72
|
return content;
|
|
62
73
|
}
|
|
@@ -87,7 +98,7 @@ function mergeConsecutiveContents(contents: Content[]): Content[] {
|
|
|
87
98
|
* appending typed Content messages.
|
|
88
99
|
*/
|
|
89
100
|
export function createGoogleGenAIThreadManager(
|
|
90
|
-
config: GoogleGenAIThreadManagerConfig
|
|
101
|
+
config: GoogleGenAIThreadManagerConfig
|
|
91
102
|
): GoogleGenAIThreadManager {
|
|
92
103
|
const baseConfig: ThreadManagerConfig<StoredContent> = {
|
|
93
104
|
redis: config.redis,
|
|
@@ -101,54 +112,64 @@ export function createGoogleGenAIThreadManager(
|
|
|
101
112
|
const helpers: Omit<GoogleGenAIThreadManager, keyof typeof base> = {
|
|
102
113
|
async appendUserMessage(
|
|
103
114
|
id: string,
|
|
104
|
-
content: GoogleGenAIContent
|
|
115
|
+
content: GoogleGenAIContent
|
|
105
116
|
): Promise<void> {
|
|
106
|
-
await base.append([
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
117
|
+
await base.append([
|
|
118
|
+
{
|
|
119
|
+
id,
|
|
120
|
+
content: { role: "user", parts: toParts(content) },
|
|
121
|
+
},
|
|
122
|
+
]);
|
|
110
123
|
},
|
|
111
124
|
|
|
112
125
|
async appendSystemMessage(
|
|
113
126
|
id: string,
|
|
114
|
-
content: GoogleGenAISystemContent
|
|
127
|
+
content: GoogleGenAISystemContent
|
|
115
128
|
): Promise<void> {
|
|
116
129
|
const parts: Part[] =
|
|
117
130
|
typeof content === "string" ? [{ text: content }] : content;
|
|
118
131
|
await base.initialize();
|
|
119
|
-
await base.append([
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
132
|
+
await base.append([
|
|
133
|
+
{
|
|
134
|
+
id,
|
|
135
|
+
content: { role: "system", parts },
|
|
136
|
+
},
|
|
137
|
+
]);
|
|
123
138
|
},
|
|
124
139
|
|
|
125
140
|
async appendModelContent(id: string, parts: Part[]): Promise<void> {
|
|
126
|
-
await base.append([
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
141
|
+
await base.append([
|
|
142
|
+
{
|
|
143
|
+
id,
|
|
144
|
+
content: { role: "model", parts },
|
|
145
|
+
},
|
|
146
|
+
]);
|
|
130
147
|
},
|
|
131
148
|
|
|
132
149
|
async appendToolResult(
|
|
133
150
|
id: string,
|
|
134
151
|
toolCallId: string,
|
|
135
152
|
toolName: string,
|
|
136
|
-
content: GoogleGenAIToolResponse
|
|
153
|
+
content: GoogleGenAIToolResponse
|
|
137
154
|
): Promise<void> {
|
|
138
155
|
const parts: Part[] = Array.isArray(content)
|
|
139
|
-
? content as Part[]
|
|
140
|
-
: [
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
156
|
+
? (content as Part[])
|
|
157
|
+
: [
|
|
158
|
+
{
|
|
159
|
+
functionResponse: {
|
|
160
|
+
id: toolCallId,
|
|
161
|
+
name: toolName,
|
|
162
|
+
response: toFunctionResponse(content),
|
|
163
|
+
},
|
|
145
164
|
},
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
await base.append([
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
165
|
+
];
|
|
166
|
+
|
|
167
|
+
await base.append([
|
|
168
|
+
{
|
|
169
|
+
id,
|
|
170
|
+
content: { role: "user", parts },
|
|
171
|
+
},
|
|
172
|
+
]);
|
|
152
173
|
},
|
|
153
174
|
|
|
154
175
|
async prepareForInvocation(): Promise<GoogleGenAIInvocationPayload> {
|
|
@@ -174,7 +195,10 @@ export function createGoogleGenAIThreadManager(
|
|
|
174
195
|
contents: onPreparedMessage
|
|
175
196
|
? contents.map((msg, i) => onPreparedMessage(msg, i, contents))
|
|
176
197
|
: contents,
|
|
177
|
-
...(systemInstruction && systemInstruction.length > 0
|
|
198
|
+
...(systemInstruction && systemInstruction.length > 0
|
|
199
|
+
? { systemInstruction }
|
|
200
|
+
: {}),
|
|
201
|
+
storedLength: stored.length,
|
|
178
202
|
};
|
|
179
203
|
},
|
|
180
204
|
};
|