zeitlich 0.2.20 → 0.2.21
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/dist/adapters/sandbox/virtual/index.d.cts +3 -3
- package/dist/adapters/sandbox/virtual/index.d.ts +3 -3
- package/dist/adapters/thread/google-genai/index.cjs +70 -23
- package/dist/adapters/thread/google-genai/index.cjs.map +1 -1
- package/dist/adapters/thread/google-genai/index.d.cts +10 -10
- package/dist/adapters/thread/google-genai/index.d.ts +10 -10
- package/dist/adapters/thread/google-genai/index.js +70 -23
- package/dist/adapters/thread/google-genai/index.js.map +1 -1
- package/dist/adapters/thread/langchain/index.cjs +75 -70
- package/dist/adapters/thread/langchain/index.cjs.map +1 -1
- package/dist/adapters/thread/langchain/index.d.cts +10 -10
- package/dist/adapters/thread/langchain/index.d.ts +10 -10
- package/dist/adapters/thread/langchain/index.js +75 -70
- package/dist/adapters/thread/langchain/index.js.map +1 -1
- package/dist/index.cjs +54 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -6
- package/dist/index.d.ts +6 -6
- package/dist/index.js +54 -9
- package/dist/index.js.map +1 -1
- package/dist/{queries-KHj5Otv7.d.ts → queries-6Avfh74U.d.ts} +1 -1
- package/dist/{queries-nIdzTCDS.d.cts → queries-CHa2iv_I.d.cts} +1 -1
- package/dist/{types-By80IE1x.d.ts → types-BkAYmc96.d.ts} +4 -4
- package/dist/{types-DZ7BkA3-.d.cts → types-CES_30qx.d.cts} +4 -4
- package/dist/{types-Ct2igz9y.d.ts → types-YbL7JpEA.d.cts} +1 -1
- package/dist/{types-Ct2igz9y.d.cts → types-YbL7JpEA.d.ts} +1 -1
- package/dist/workflow.cjs +7 -8
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +6 -6
- package/dist/workflow.d.ts +6 -6
- package/dist/workflow.js +7 -8
- package/dist/workflow.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/thread/google-genai/activities.ts +11 -9
- package/src/adapters/thread/google-genai/model-invoker.ts +6 -11
- package/src/adapters/thread/google-genai/thread-manager.ts +44 -29
- package/src/adapters/thread/langchain/activities.ts +6 -4
- package/src/adapters/thread/langchain/thread-manager.ts +46 -22
- package/src/lib/session/session.ts +5 -4
- package/src/lib/session/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 +59 -23
- package/src/lib/tool-router/router.integration.test.ts +55 -23
- package/src/lib/tool-router/router.ts +4 -3
- package/src/lib/tool-router/types.ts +1 -1
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { F as FileEntryMetadata, V as VirtualSandboxCreateOptions, a as FileResolver, b as VirtualSandboxContext, T as TreeMutation, c as FileEntry, d as VirtualSandbox } from '../../../queries-
|
|
2
|
-
export { e as FileTreeAccessor, f as VirtualFileTree, g as VirtualSandboxFileSystem, h as VirtualSandboxState, i as filesWithMimeType, j as hasDirectory, k as hasFileWithMimeType } from '../../../queries-
|
|
1
|
+
import { F as FileEntryMetadata, V as VirtualSandboxCreateOptions, a as FileResolver, b as VirtualSandboxContext, T as TreeMutation, c as FileEntry, d as VirtualSandbox } from '../../../queries-CHa2iv_I.cjs';
|
|
2
|
+
export { e as FileTreeAccessor, f as VirtualFileTree, g as VirtualSandboxFileSystem, h as VirtualSandboxState, i as filesWithMimeType, j as hasDirectory, k as hasFileWithMimeType } from '../../../queries-CHa2iv_I.cjs';
|
|
3
3
|
import { b as SandboxProvider, c as SandboxCapabilities, e as SandboxCreateResult } from '../../../types-BMRzfELQ.cjs';
|
|
4
4
|
import { WorkflowClient } from '@temporalio/client';
|
|
5
|
-
import { A as ActivityToolHandler } from '../../../types-
|
|
5
|
+
import { A as ActivityToolHandler } from '../../../types-YbL7JpEA.cjs';
|
|
6
6
|
import '@temporalio/common';
|
|
7
7
|
import 'zod';
|
|
8
8
|
import '@temporalio/workflow';
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { F as FileEntryMetadata, V as VirtualSandboxCreateOptions, a as FileResolver, b as VirtualSandboxContext, T as TreeMutation, c as FileEntry, d as VirtualSandbox } from '../../../queries-
|
|
2
|
-
export { e as FileTreeAccessor, f as VirtualFileTree, g as VirtualSandboxFileSystem, h as VirtualSandboxState, i as filesWithMimeType, j as hasDirectory, k as hasFileWithMimeType } from '../../../queries-
|
|
1
|
+
import { F as FileEntryMetadata, V as VirtualSandboxCreateOptions, a as FileResolver, b as VirtualSandboxContext, T as TreeMutation, c as FileEntry, d as VirtualSandbox } from '../../../queries-6Avfh74U.js';
|
|
2
|
+
export { e as FileTreeAccessor, f as VirtualFileTree, g as VirtualSandboxFileSystem, h as VirtualSandboxState, i as filesWithMimeType, j as hasDirectory, k as hasFileWithMimeType } from '../../../queries-6Avfh74U.js';
|
|
3
3
|
import { b as SandboxProvider, c as SandboxCapabilities, e as SandboxCreateResult } from '../../../types-BMRzfELQ.js';
|
|
4
4
|
import { WorkflowClient } from '@temporalio/client';
|
|
5
|
-
import { A as ActivityToolHandler } from '../../../types-
|
|
5
|
+
import { A as ActivityToolHandler } from '../../../types-YbL7JpEA.js';
|
|
6
6
|
import '@temporalio/common';
|
|
7
7
|
import 'zod';
|
|
8
8
|
import '@temporalio/workflow';
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var crypto = require('crypto');
|
|
4
|
+
|
|
3
5
|
// src/lib/thread/manager.ts
|
|
4
6
|
var THREAD_TTL_SECONDS = 60 * 60 * 24 * 90;
|
|
5
7
|
var APPEND_IDEMPOTENT_SCRIPT = `
|
|
@@ -121,27 +123,27 @@ function createGoogleGenAIThreadManager(config) {
|
|
|
121
123
|
};
|
|
122
124
|
const base = createThreadManager(baseConfig);
|
|
123
125
|
const helpers = {
|
|
124
|
-
createUserContent(content) {
|
|
126
|
+
createUserContent(id, content) {
|
|
125
127
|
return {
|
|
126
|
-
id
|
|
128
|
+
id,
|
|
127
129
|
content: { role: "user", parts: messageContentToParts(content) }
|
|
128
130
|
};
|
|
129
131
|
},
|
|
130
|
-
createSystemContent(content) {
|
|
132
|
+
createSystemContent(id, content) {
|
|
131
133
|
return {
|
|
132
|
-
id
|
|
134
|
+
id,
|
|
133
135
|
content: { role: "system", parts: [{ text: content }] }
|
|
134
136
|
};
|
|
135
137
|
},
|
|
136
|
-
createModelContent(parts) {
|
|
138
|
+
createModelContent(id, parts) {
|
|
137
139
|
return {
|
|
138
|
-
id
|
|
140
|
+
id,
|
|
139
141
|
content: { role: "model", parts }
|
|
140
142
|
};
|
|
141
143
|
},
|
|
142
|
-
createToolResponseContent(toolCallId, toolName, content) {
|
|
144
|
+
createToolResponseContent(id, toolCallId, toolName, content) {
|
|
143
145
|
return {
|
|
144
|
-
id
|
|
146
|
+
id,
|
|
145
147
|
content: {
|
|
146
148
|
role: "user",
|
|
147
149
|
parts: [
|
|
@@ -156,25 +158,70 @@ function createGoogleGenAIThreadManager(config) {
|
|
|
156
158
|
}
|
|
157
159
|
};
|
|
158
160
|
},
|
|
159
|
-
async appendUserMessage(content) {
|
|
160
|
-
await base.append([helpers.createUserContent(content)]);
|
|
161
|
+
async appendUserMessage(id, content) {
|
|
162
|
+
await base.append([helpers.createUserContent(id, content)]);
|
|
161
163
|
},
|
|
162
|
-
async appendSystemMessage(content) {
|
|
164
|
+
async appendSystemMessage(id, content) {
|
|
163
165
|
await base.initialize();
|
|
164
|
-
await base.append([helpers.createSystemContent(content)]);
|
|
166
|
+
await base.append([helpers.createSystemContent(id, content)]);
|
|
165
167
|
},
|
|
166
|
-
async appendModelContent(parts) {
|
|
167
|
-
await base.append([helpers.createModelContent(parts)]);
|
|
168
|
+
async appendModelContent(id, parts) {
|
|
169
|
+
await base.append([helpers.createModelContent(id, parts)]);
|
|
168
170
|
},
|
|
169
|
-
async appendToolResult(toolCallId, toolName, content) {
|
|
171
|
+
async appendToolResult(id, toolCallId, toolName, content) {
|
|
170
172
|
await base.append([
|
|
171
|
-
helpers.createToolResponseContent(toolCallId, toolName, content)
|
|
173
|
+
helpers.createToolResponseContent(id, toolCallId, toolName, content)
|
|
172
174
|
]);
|
|
173
175
|
}
|
|
174
176
|
};
|
|
175
177
|
return Object.assign(base, helpers);
|
|
176
178
|
}
|
|
177
179
|
|
|
180
|
+
// node_modules/uuid/dist/esm/stringify.js
|
|
181
|
+
var byteToHex = [];
|
|
182
|
+
for (let i = 0; i < 256; ++i) {
|
|
183
|
+
byteToHex.push((i + 256).toString(16).slice(1));
|
|
184
|
+
}
|
|
185
|
+
function unsafeStringify(arr, offset = 0) {
|
|
186
|
+
return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
|
|
187
|
+
}
|
|
188
|
+
var rnds8Pool = new Uint8Array(256);
|
|
189
|
+
var poolPtr = rnds8Pool.length;
|
|
190
|
+
function rng() {
|
|
191
|
+
if (poolPtr > rnds8Pool.length - 16) {
|
|
192
|
+
crypto.randomFillSync(rnds8Pool);
|
|
193
|
+
poolPtr = 0;
|
|
194
|
+
}
|
|
195
|
+
return rnds8Pool.slice(poolPtr, poolPtr += 16);
|
|
196
|
+
}
|
|
197
|
+
var native_default = { randomUUID: crypto.randomUUID };
|
|
198
|
+
|
|
199
|
+
// node_modules/uuid/dist/esm/v4.js
|
|
200
|
+
function v4(options, buf, offset) {
|
|
201
|
+
if (native_default.randomUUID && !buf && !options) {
|
|
202
|
+
return native_default.randomUUID();
|
|
203
|
+
}
|
|
204
|
+
options = options || {};
|
|
205
|
+
const rnds = options.random ?? options.rng?.() ?? rng();
|
|
206
|
+
if (rnds.length < 16) {
|
|
207
|
+
throw new Error("Random bytes length must be >= 16");
|
|
208
|
+
}
|
|
209
|
+
rnds[6] = rnds[6] & 15 | 64;
|
|
210
|
+
rnds[8] = rnds[8] & 63 | 128;
|
|
211
|
+
if (buf) {
|
|
212
|
+
offset = offset || 0;
|
|
213
|
+
if (offset < 0 || offset + 16 > buf.length) {
|
|
214
|
+
throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
|
|
215
|
+
}
|
|
216
|
+
for (let i = 0; i < 16; ++i) {
|
|
217
|
+
buf[offset + i] = rnds[i];
|
|
218
|
+
}
|
|
219
|
+
return buf;
|
|
220
|
+
}
|
|
221
|
+
return unsafeStringify(rnds);
|
|
222
|
+
}
|
|
223
|
+
var v4_default = v4;
|
|
224
|
+
|
|
178
225
|
// src/adapters/thread/google-genai/model-invoker.ts
|
|
179
226
|
function toFunctionDeclarations(tools) {
|
|
180
227
|
return tools.map((t) => ({
|
|
@@ -226,7 +273,7 @@ function createGoogleGenAIModelInvoker({
|
|
|
226
273
|
});
|
|
227
274
|
const responseParts = response.candidates?.[0]?.content?.parts ?? [];
|
|
228
275
|
const modelContent = { role: "model", parts: responseParts };
|
|
229
|
-
await thread.appendModelContent(responseParts);
|
|
276
|
+
await thread.appendModelContent(v4_default(), responseParts);
|
|
230
277
|
const functionCalls = response.functionCalls ?? [];
|
|
231
278
|
return {
|
|
232
279
|
message: modelContent,
|
|
@@ -261,18 +308,18 @@ function createGoogleGenAIAdapter(config) {
|
|
|
261
308
|
const thread = createGoogleGenAIThreadManager({ redis, threadId });
|
|
262
309
|
await thread.initialize();
|
|
263
310
|
},
|
|
264
|
-
async appendHumanMessage(threadId, content) {
|
|
311
|
+
async appendHumanMessage(threadId, id, content) {
|
|
265
312
|
const thread = createGoogleGenAIThreadManager({ redis, threadId });
|
|
266
|
-
await thread.appendUserMessage(content);
|
|
313
|
+
await thread.appendUserMessage(id, content);
|
|
267
314
|
},
|
|
268
|
-
async appendSystemMessage(threadId, content) {
|
|
315
|
+
async appendSystemMessage(threadId, id, content) {
|
|
269
316
|
const thread = createGoogleGenAIThreadManager({ redis, threadId });
|
|
270
|
-
await thread.appendSystemMessage(content);
|
|
317
|
+
await thread.appendSystemMessage(id, content);
|
|
271
318
|
},
|
|
272
|
-
async appendToolResult(cfg) {
|
|
319
|
+
async appendToolResult(id, cfg) {
|
|
273
320
|
const { threadId, toolCallId, toolName, content } = cfg;
|
|
274
321
|
const thread = createGoogleGenAIThreadManager({ redis, threadId });
|
|
275
|
-
await thread.appendToolResult(toolCallId, toolName, content);
|
|
322
|
+
await thread.appendToolResult(id, toolCallId, toolName, content);
|
|
276
323
|
},
|
|
277
324
|
async forkThread(sourceThreadId, targetThreadId) {
|
|
278
325
|
const thread = createGoogleGenAIThreadManager({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/lib/thread/manager.ts","../../../../src/adapters/thread/google-genai/thread-manager.ts","../../../../src/adapters/thread/google-genai/model-invoker.ts","../../../../src/adapters/thread/google-genai/activities.ts"],"names":["invokeGoogleGenAIModel"],"mappings":"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","file":"index.cjs","sourcesContent":["import type {\n ThreadManagerConfig,\n BaseThreadManager,\n} from \"./types\";\n\nconst THREAD_TTL_SECONDS = 60 * 60 * 24 * 90; // 90 days\n\n/**\n * Lua script for atomic idempotent append.\n * Checks a dedup key; if it exists the message was already appended and we\n * return 0. Otherwise appends all messages to the list, sets TTL on both\n * the list and the dedup key, and returns 1.\n *\n * KEYS[1] = dedup key, KEYS[2] = list key\n * ARGV[1] = TTL seconds, ARGV[2..N] = serialised messages\n */\nconst APPEND_IDEMPOTENT_SCRIPT = `\nif redis.call('EXISTS', KEYS[1]) == 1 then\n return 0\nend\nfor i = 2, #ARGV do\n redis.call('RPUSH', KEYS[2], ARGV[i])\nend\nredis.call('EXPIRE', KEYS[2], tonumber(ARGV[1]))\nredis.call('SET', KEYS[1], '1', 'EX', tonumber(ARGV[1]))\nreturn 1\n`;\n\nfunction getThreadKey(threadId: string, key: string): string {\n return `thread:${threadId}:${key}`;\n}\n\n/**\n * Creates a generic thread manager for handling conversation state in Redis.\n * Framework-agnostic — works with any serializable message type.\n */\nexport function createThreadManager<T>(\n config: ThreadManagerConfig<T>,\n): BaseThreadManager<T> {\n const {\n redis,\n threadId,\n key = \"messages\",\n serialize = (m: T): string => JSON.stringify(m),\n deserialize = (raw: string): T => JSON.parse(raw) as T,\n idOf,\n } = config;\n const redisKey = getThreadKey(threadId, key);\n const metaKey = getThreadKey(threadId, `${key}:meta`);\n\n async function assertThreadExists(): Promise<void> {\n const exists = await redis.exists(metaKey);\n if (!exists) {\n throw new Error(`Thread \"${threadId}\" (key: ${key}) does not exist`);\n }\n }\n\n return {\n async initialize(): Promise<void> {\n await redis.del(redisKey);\n await redis.set(metaKey, \"1\", \"EX\", THREAD_TTL_SECONDS);\n },\n\n async load(): Promise<T[]> {\n await assertThreadExists();\n const data = await redis.lrange(redisKey, 0, -1);\n return data.map(deserialize);\n },\n\n async append(messages: T[]): Promise<void> {\n if (messages.length === 0) return;\n await assertThreadExists();\n\n if (idOf) {\n const dedupId = messages.map(idOf).join(\":\");\n const dedupKey = getThreadKey(threadId, `dedup:${dedupId}`);\n await redis.eval(\n APPEND_IDEMPOTENT_SCRIPT,\n 2,\n dedupKey,\n redisKey,\n String(THREAD_TTL_SECONDS),\n ...messages.map(serialize),\n );\n } else {\n await redis.rpush(redisKey, ...messages.map(serialize));\n await redis.expire(redisKey, THREAD_TTL_SECONDS);\n }\n },\n\n async fork(newThreadId: string): Promise<BaseThreadManager<T>> {\n await assertThreadExists();\n const data = await redis.lrange(redisKey, 0, -1);\n const forked = createThreadManager({\n ...config,\n threadId: newThreadId,\n });\n await forked.initialize();\n if (data.length > 0) {\n const newKey = getThreadKey(newThreadId, key);\n await redis.rpush(newKey, ...data);\n await redis.expire(newKey, THREAD_TTL_SECONDS);\n }\n return forked;\n },\n\n async delete(): Promise<void> {\n await redis.del(redisKey, metaKey);\n },\n };\n}\n","import type Redis from \"ioredis\";\nimport type { Content, Part } from \"@google/genai\";\nimport {\n createThreadManager,\n type BaseThreadManager,\n type ThreadManagerConfig,\n} from \"../../../lib/thread\";\nimport type { MessageContent, ToolMessageContent } from \"../../../lib/types\";\n\n/** A Content with a unique ID for idempotent Redis storage */\nexport interface StoredContent {\n id: string;\n content: Content;\n}\n\nexport interface GoogleGenAIThreadManagerConfig {\n redis: Redis;\n threadId: string;\n /** Thread key, defaults to 'messages' */\n key?: string;\n}\n\n/** Thread manager with Google GenAI Content convenience helpers */\nexport interface GoogleGenAIThreadManager\n extends BaseThreadManager<StoredContent> {\n createUserContent(content: string | MessageContent): StoredContent;\n createSystemContent(content: string): StoredContent;\n createModelContent(parts: Part[]): StoredContent;\n createToolResponseContent(\n toolCallId: string,\n toolName: string,\n content: ToolMessageContent,\n ): StoredContent;\n appendUserMessage(content: string | MessageContent): Promise<void>;\n appendSystemMessage(content: string): Promise<void>;\n appendModelContent(parts: Part[]): Promise<void>;\n appendToolResult(\n toolCallId: string,\n toolName: string,\n content: ToolMessageContent,\n ): Promise<void>;\n}\n\nfunction storedContentId(msg: StoredContent): string {\n return msg.id;\n}\n\n/** Convert zeitlich MessageContent to Google GenAI Part[] */\nexport function messageContentToParts(\n content: string | MessageContent,\n): Part[] {\n if (typeof content === \"string\") {\n return [{ text: content }];\n }\n if (Array.isArray(content)) {\n return content.map((part) => {\n if (part.type === \"text\") {\n return { text: part.text as string };\n }\n return part as unknown as Part;\n });\n }\n return [{ text: String(content) }];\n}\n\n/** Parse ToolMessageContent into a Record suitable for functionResponse */\nfunction parseToolResponse(\n content: ToolMessageContent,\n): Record<string, unknown> {\n if (typeof content === \"string\") {\n try {\n const parsed: unknown = JSON.parse(content);\n return typeof parsed === \"object\" && parsed !== null\n ? (parsed as Record<string, unknown>)\n : { result: content };\n } catch {\n return { result: content };\n }\n }\n return { result: content };\n}\n\n/**\n * Creates a Google GenAI-specific thread manager that stores StoredContent\n * instances in Redis and provides convenience helpers for creating and\n * appending typed Content messages.\n */\nexport function createGoogleGenAIThreadManager(\n config: GoogleGenAIThreadManagerConfig,\n): GoogleGenAIThreadManager {\n const baseConfig: ThreadManagerConfig<StoredContent> = {\n redis: config.redis,\n threadId: config.threadId,\n key: config.key,\n idOf: storedContentId,\n };\n\n const base = createThreadManager(baseConfig);\n\n const helpers = {\n createUserContent(content: string | MessageContent): StoredContent {\n return {\n id: crypto.randomUUID(),\n content: { role: \"user\", parts: messageContentToParts(content) },\n };\n },\n\n createSystemContent(content: string): StoredContent {\n return {\n id: crypto.randomUUID(),\n content: { role: \"system\", parts: [{ text: content }] },\n };\n },\n\n createModelContent(parts: Part[]): StoredContent {\n return {\n id: crypto.randomUUID(),\n content: { role: \"model\", parts },\n };\n },\n\n createToolResponseContent(\n toolCallId: string,\n toolName: string,\n content: ToolMessageContent,\n ): StoredContent {\n return {\n id: crypto.randomUUID(),\n content: {\n role: \"user\",\n parts: [\n {\n functionResponse: {\n id: toolCallId,\n name: toolName,\n response: parseToolResponse(content),\n },\n },\n ],\n },\n };\n },\n\n async appendUserMessage(content: string | MessageContent): Promise<void> {\n await base.append([helpers.createUserContent(content)]);\n },\n\n async appendSystemMessage(content: string): Promise<void> {\n await base.initialize();\n await base.append([helpers.createSystemContent(content)]);\n },\n\n async appendModelContent(parts: Part[]): Promise<void> {\n await base.append([helpers.createModelContent(parts)]);\n },\n\n async appendToolResult(\n toolCallId: string,\n toolName: string,\n content: ToolMessageContent,\n ): Promise<void> {\n await base.append([\n helpers.createToolResponseContent(toolCallId, toolName, content),\n ]);\n },\n };\n\n return Object.assign(base, helpers);\n}\n","import type Redis from \"ioredis\";\nimport type {\n GoogleGenAI,\n Content,\n FunctionDeclaration,\n} from \"@google/genai\";\nimport type { SerializableToolDefinition } from \"../../../lib/types\";\nimport type { AgentResponse } from \"../../../lib/model\";\nimport type { ModelInvokerConfig } from \"../../../lib/model\";\nimport { createGoogleGenAIThreadManager } from \"./thread-manager\";\n\nexport interface GoogleGenAIModelInvokerConfig {\n redis: Redis;\n client: GoogleGenAI;\n model: string;\n}\n\nfunction toFunctionDeclarations(\n tools: SerializableToolDefinition[],\n): FunctionDeclaration[] {\n return tools.map((t) => ({\n name: t.name,\n description: t.description,\n parametersJsonSchema: t.schema,\n }));\n}\n\n/**\n * Merge consecutive Content objects sharing the same role.\n * The Gemini API requires alternating user/model turns; without\n * merging, multiple sequential tool-result messages would violate this.\n */\nfunction mergeConsecutiveContents(contents: Content[]): Content[] {\n const merged: Content[] = [];\n for (const content of contents) {\n const last = merged[merged.length - 1];\n if (last && last.role === content.role) {\n last.parts = [...(last.parts ?? []), ...(content.parts ?? [])];\n } else {\n merged.push({ ...content, parts: [...(content.parts ?? [])] });\n }\n }\n return merged;\n}\n\n/**\n * Creates a Google GenAI model invoker that satisfies the generic\n * `ModelInvoker<Content>` contract.\n *\n * Loads the conversation thread from Redis, invokes the Gemini model via\n * `client.models.generateContent`, appends the AI response, and returns\n * a normalised AgentResponse.\n *\n * @example\n * ```typescript\n * import { createGoogleGenAIModelInvoker } from 'zeitlich/adapters/thread/google-genai';\n * import { createRunAgentActivity } from 'zeitlich';\n * import { GoogleGenAI } from '@google/genai';\n *\n * const client = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });\n * const invoker = createGoogleGenAIModelInvoker({\n * redis,\n * client,\n * model: 'gemini-2.5-flash',\n * });\n *\n * return { runAgent: createRunAgentActivity(client, invoker) };\n * ```\n */\nexport function createGoogleGenAIModelInvoker({\n redis,\n client,\n model,\n}: GoogleGenAIModelInvokerConfig) {\n return async function invokeGoogleGenAIModel(\n config: ModelInvokerConfig,\n ): Promise<AgentResponse<Content>> {\n const { threadId, state } = config;\n\n const thread = createGoogleGenAIThreadManager({ redis, threadId });\n const stored = await thread.load();\n\n // Separate system instructions from conversation content.\n // Google GenAI takes system instructions via config, not in the contents array.\n let systemInstruction: string | undefined;\n const conversationContents: Content[] = [];\n\n for (const item of stored) {\n if (item.content.role === \"system\") {\n systemInstruction = item.content.parts?.[0]?.text;\n } else {\n conversationContents.push(item.content);\n }\n }\n\n const contents = mergeConsecutiveContents(conversationContents);\n\n const functionDeclarations = toFunctionDeclarations(state.tools);\n const tools =\n functionDeclarations.length > 0\n ? [{ functionDeclarations }]\n : undefined;\n\n const response = await client.models.generateContent({\n model,\n contents,\n config: {\n ...(systemInstruction ? { systemInstruction } : {}),\n ...(tools ? { tools } : {}),\n },\n });\n\n const responseParts = response.candidates?.[0]?.content?.parts ?? [];\n const modelContent: Content = { role: \"model\", parts: responseParts };\n\n await thread.appendModelContent(responseParts);\n\n const functionCalls = response.functionCalls ?? [];\n\n return {\n message: modelContent,\n rawToolCalls: functionCalls.map((fc) => ({\n id: fc.id,\n name: fc.name ?? \"\",\n args: fc.args ?? {},\n })),\n usage: {\n inputTokens: response.usageMetadata?.promptTokenCount,\n outputTokens: response.usageMetadata?.candidatesTokenCount,\n cachedReadTokens: response.usageMetadata?.cachedContentTokenCount,\n },\n };\n };\n}\n\n/**\n * Standalone function for one-shot Google GenAI model invocation.\n * Convenience wrapper around createGoogleGenAIModelInvoker for cases\n * where you don't need to reuse the invoker.\n */\nexport async function invokeGoogleGenAIModel({\n redis,\n client,\n model,\n config,\n}: {\n redis: Redis;\n client: GoogleGenAI;\n model: string;\n config: ModelInvokerConfig;\n}): Promise<AgentResponse<Content>> {\n const invoker = createGoogleGenAIModelInvoker({ redis, client, model });\n return invoker(config);\n}\n","import type Redis from \"ioredis\";\nimport type { GoogleGenAI, Content } from \"@google/genai\";\nimport type { ToolResultConfig } from \"../../../lib/types\";\nimport type { MessageContent } from \"../../../lib/types\";\nimport type { ThreadOps } from \"../../../lib/session/types\";\nimport type { ModelInvoker } from \"../../../lib/model\";\nimport { createGoogleGenAIThreadManager } from \"./thread-manager\";\nimport { createGoogleGenAIModelInvoker } from \"./model-invoker\";\n\nexport interface GoogleGenAIAdapterConfig {\n redis: Redis;\n client: GoogleGenAI;\n /** Default model name (e.g. 'gemini-2.5-flash'). If omitted, use `createModelInvoker()` */\n model?: string;\n}\n\nexport interface GoogleGenAIAdapter {\n /** Thread operations (register these as Temporal activities on the worker) */\n threadOps: ThreadOps;\n /** Model invoker using the default model (only available when `model` was provided) */\n invoker: ModelInvoker<Content>;\n /** Create an invoker for a specific model name (for multi-model setups) */\n createModelInvoker(model: string): ModelInvoker<Content>;\n}\n\n/**\n * Creates a Google GenAI adapter that bundles thread operations and model\n * invocation using the `@google/genai` SDK.\n *\n * The returned `threadOps` should be registered as Temporal activities on\n * the worker. The `invoker` (or invokers created via `createModelInvoker`)\n * should be wrapped with `createRunAgentActivity` for per-agent activities.\n *\n * @example\n * ```typescript\n * import { createGoogleGenAIAdapter } from 'zeitlich/adapters/thread/google-genai';\n * import { createRunAgentActivity } from 'zeitlich';\n * import { GoogleGenAI } from '@google/genai';\n *\n * const client = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });\n * const adapter = createGoogleGenAIAdapter({ redis, client, model: 'gemini-2.5-flash' });\n *\n * export function createActivities(temporalClient: WorkflowClient) {\n * return {\n * ...adapter.threadOps,\n * runAgent: createRunAgentActivity(temporalClient, adapter.invoker),\n * };\n * }\n * ```\n *\n * @example Multi-model setup\n * ```typescript\n * const adapter = createGoogleGenAIAdapter({ redis, client });\n *\n * export function createActivities(temporalClient: WorkflowClient) {\n * return {\n * ...adapter.threadOps,\n * runResearchAgent: createRunAgentActivity(\n * temporalClient,\n * adapter.createModelInvoker('gemini-2.5-pro'),\n * ),\n * runFastAgent: createRunAgentActivity(\n * temporalClient,\n * adapter.createModelInvoker('gemini-2.5-flash'),\n * ),\n * };\n * }\n * ```\n */\nexport function createGoogleGenAIAdapter(\n config: GoogleGenAIAdapterConfig,\n): GoogleGenAIAdapter {\n const { redis, client } = config;\n\n const threadOps: ThreadOps = {\n async initializeThread(threadId: string): Promise<void> {\n const thread = createGoogleGenAIThreadManager({ redis, threadId });\n await thread.initialize();\n },\n\n async appendHumanMessage(\n threadId: string,\n content: string | MessageContent,\n ): Promise<void> {\n const thread = createGoogleGenAIThreadManager({ redis, threadId });\n await thread.appendUserMessage(content);\n },\n\n async appendSystemMessage(\n threadId: string,\n content: string,\n ): Promise<void> {\n const thread = createGoogleGenAIThreadManager({ redis, threadId });\n await thread.appendSystemMessage(content);\n },\n\n async appendToolResult(cfg: ToolResultConfig): Promise<void> {\n const { threadId, toolCallId, toolName, content } = cfg;\n const thread = createGoogleGenAIThreadManager({ redis, threadId });\n await thread.appendToolResult(toolCallId, toolName, content);\n },\n\n async forkThread(\n sourceThreadId: string,\n targetThreadId: string,\n ): Promise<void> {\n const thread = createGoogleGenAIThreadManager({\n redis,\n threadId: sourceThreadId,\n });\n await thread.fork(targetThreadId);\n },\n };\n\n const makeInvoker = (model: string): ModelInvoker<Content> =>\n createGoogleGenAIModelInvoker({ redis, client, model });\n\n const invoker: ModelInvoker<Content> = config.model\n ? makeInvoker(config.model)\n : ((() => {\n throw new Error(\n \"No default model provided to createGoogleGenAIAdapter. \" +\n \"Either pass `model` in the config or use `createModelInvoker(model)` instead.\",\n );\n }) as unknown as ModelInvoker<Content>);\n\n return {\n threadOps,\n invoker,\n createModelInvoker: makeInvoker,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/thread/manager.ts","../../../../src/adapters/thread/google-genai/thread-manager.ts","../../../../node_modules/uuid/dist/esm/stringify.js","../../../../node_modules/uuid/dist/esm/rng.js","../../../../node_modules/uuid/dist/esm/native.js","../../../../node_modules/uuid/dist/esm/v4.js","../../../../src/adapters/thread/google-genai/model-invoker.ts","../../../../src/adapters/thread/google-genai/activities.ts"],"names":["randomFillSync","randomUUID","invokeGoogleGenAIModel"],"mappings":"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","file":"index.cjs","sourcesContent":["import type {\n ThreadManagerConfig,\n BaseThreadManager,\n} from \"./types\";\n\nconst THREAD_TTL_SECONDS = 60 * 60 * 24 * 90; // 90 days\n\n/**\n * Lua script for atomic idempotent append.\n * Checks a dedup key; if it exists the message was already appended and we\n * return 0. Otherwise appends all messages to the list, sets TTL on both\n * the list and the dedup key, and returns 1.\n *\n * KEYS[1] = dedup key, KEYS[2] = list key\n * ARGV[1] = TTL seconds, ARGV[2..N] = serialised messages\n */\nconst APPEND_IDEMPOTENT_SCRIPT = `\nif redis.call('EXISTS', KEYS[1]) == 1 then\n return 0\nend\nfor i = 2, #ARGV do\n redis.call('RPUSH', KEYS[2], ARGV[i])\nend\nredis.call('EXPIRE', KEYS[2], tonumber(ARGV[1]))\nredis.call('SET', KEYS[1], '1', 'EX', tonumber(ARGV[1]))\nreturn 1\n`;\n\nfunction getThreadKey(threadId: string, key: string): string {\n return `thread:${threadId}:${key}`;\n}\n\n/**\n * Creates a generic thread manager for handling conversation state in Redis.\n * Framework-agnostic — works with any serializable message type.\n */\nexport function createThreadManager<T>(\n config: ThreadManagerConfig<T>,\n): BaseThreadManager<T> {\n const {\n redis,\n threadId,\n key = \"messages\",\n serialize = (m: T): string => JSON.stringify(m),\n deserialize = (raw: string): T => JSON.parse(raw) as T,\n idOf,\n } = config;\n const redisKey = getThreadKey(threadId, key);\n const metaKey = getThreadKey(threadId, `${key}:meta`);\n\n async function assertThreadExists(): Promise<void> {\n const exists = await redis.exists(metaKey);\n if (!exists) {\n throw new Error(`Thread \"${threadId}\" (key: ${key}) does not exist`);\n }\n }\n\n return {\n async initialize(): Promise<void> {\n await redis.del(redisKey);\n await redis.set(metaKey, \"1\", \"EX\", THREAD_TTL_SECONDS);\n },\n\n async load(): Promise<T[]> {\n await assertThreadExists();\n const data = await redis.lrange(redisKey, 0, -1);\n return data.map(deserialize);\n },\n\n async append(messages: T[]): Promise<void> {\n if (messages.length === 0) return;\n await assertThreadExists();\n\n if (idOf) {\n const dedupId = messages.map(idOf).join(\":\");\n const dedupKey = getThreadKey(threadId, `dedup:${dedupId}`);\n await redis.eval(\n APPEND_IDEMPOTENT_SCRIPT,\n 2,\n dedupKey,\n redisKey,\n String(THREAD_TTL_SECONDS),\n ...messages.map(serialize),\n );\n } else {\n await redis.rpush(redisKey, ...messages.map(serialize));\n await redis.expire(redisKey, THREAD_TTL_SECONDS);\n }\n },\n\n async fork(newThreadId: string): Promise<BaseThreadManager<T>> {\n await assertThreadExists();\n const data = await redis.lrange(redisKey, 0, -1);\n const forked = createThreadManager({\n ...config,\n threadId: newThreadId,\n });\n await forked.initialize();\n if (data.length > 0) {\n const newKey = getThreadKey(newThreadId, key);\n await redis.rpush(newKey, ...data);\n await redis.expire(newKey, THREAD_TTL_SECONDS);\n }\n return forked;\n },\n\n async delete(): Promise<void> {\n await redis.del(redisKey, metaKey);\n },\n };\n}\n","import type Redis from \"ioredis\";\nimport type { Content, Part } from \"@google/genai\";\nimport {\n createThreadManager,\n type BaseThreadManager,\n type ThreadManagerConfig,\n} from \"../../../lib/thread\";\nimport type { MessageContent, ToolMessageContent } from \"../../../lib/types\";\n\n/** A Content with a unique ID for idempotent Redis storage */\nexport interface StoredContent {\n id: string;\n content: Content;\n}\n\nexport interface GoogleGenAIThreadManagerConfig {\n redis: Redis;\n threadId: string;\n /** Thread key, defaults to 'messages' */\n key?: string;\n}\n\n/** Thread manager with Google GenAI Content convenience helpers */\nexport interface GoogleGenAIThreadManager extends BaseThreadManager<StoredContent> {\n createUserContent(\n id: string,\n content: string | MessageContent\n ): StoredContent;\n createSystemContent(id: string, content: string): StoredContent;\n createModelContent(id: string, parts: Part[]): StoredContent;\n createToolResponseContent(\n id: string,\n toolCallId: string,\n toolName: string,\n content: ToolMessageContent\n ): StoredContent;\n appendUserMessage(\n id: string,\n content: string | MessageContent\n ): Promise<void>;\n appendSystemMessage(id: string, content: string): Promise<void>;\n appendModelContent(id: string, parts: Part[]): Promise<void>;\n appendToolResult(\n id: string,\n toolCallId: string,\n toolName: string,\n content: ToolMessageContent\n ): Promise<void>;\n}\n\nfunction storedContentId(msg: StoredContent): string {\n return msg.id;\n}\n\n/** Convert zeitlich MessageContent to Google GenAI Part[] */\nexport function messageContentToParts(\n content: string | MessageContent\n): Part[] {\n if (typeof content === \"string\") {\n return [{ text: content }];\n }\n if (Array.isArray(content)) {\n return content.map((part) => {\n if (part.type === \"text\") {\n return { text: part.text as string };\n }\n return part as unknown as Part;\n });\n }\n return [{ text: String(content) }];\n}\n\n/** Parse ToolMessageContent into a Record suitable for functionResponse */\nfunction parseToolResponse(\n content: ToolMessageContent\n): Record<string, unknown> {\n if (typeof content === \"string\") {\n try {\n const parsed: unknown = JSON.parse(content);\n return typeof parsed === \"object\" && parsed !== null\n ? (parsed as Record<string, unknown>)\n : { result: content };\n } catch {\n return { result: content };\n }\n }\n return { result: content };\n}\n\n/**\n * Creates a Google GenAI-specific thread manager that stores StoredContent\n * instances in Redis and provides convenience helpers for creating and\n * appending typed Content messages.\n */\nexport function createGoogleGenAIThreadManager(\n config: GoogleGenAIThreadManagerConfig\n): GoogleGenAIThreadManager {\n const baseConfig: ThreadManagerConfig<StoredContent> = {\n redis: config.redis,\n threadId: config.threadId,\n key: config.key,\n idOf: storedContentId,\n };\n\n const base = createThreadManager(baseConfig);\n\n const helpers = {\n createUserContent(\n id: string,\n content: string | MessageContent\n ): StoredContent {\n return {\n id,\n content: { role: \"user\", parts: messageContentToParts(content) },\n };\n },\n\n createSystemContent(id: string, content: string): StoredContent {\n return {\n id,\n content: { role: \"system\", parts: [{ text: content }] },\n };\n },\n\n createModelContent(id: string, parts: Part[]): StoredContent {\n return {\n id,\n content: { role: \"model\", parts },\n };\n },\n\n createToolResponseContent(\n id: string,\n toolCallId: string,\n toolName: string,\n content: ToolMessageContent\n ): StoredContent {\n return {\n id,\n content: {\n role: \"user\",\n parts: [\n {\n functionResponse: {\n id: toolCallId,\n name: toolName,\n response: parseToolResponse(content),\n },\n },\n ],\n },\n };\n },\n\n async appendUserMessage(\n id: string,\n content: string | MessageContent\n ): Promise<void> {\n await base.append([helpers.createUserContent(id, content)]);\n },\n\n async appendSystemMessage(id: string, content: string): Promise<void> {\n await base.initialize();\n await base.append([helpers.createSystemContent(id, content)]);\n },\n\n async appendModelContent(id: string, parts: Part[]): Promise<void> {\n await base.append([helpers.createModelContent(id, parts)]);\n },\n\n async appendToolResult(\n id: string,\n toolCallId: string,\n toolName: string,\n content: ToolMessageContent\n ): Promise<void> {\n await base.append([\n helpers.createToolResponseContent(id, toolCallId, toolName, content),\n ]);\n },\n };\n\n return Object.assign(base, helpers);\n}\n","import validate from './validate.js';\nconst byteToHex = [];\nfor (let i = 0; i < 256; ++i) {\n byteToHex.push((i + 0x100).toString(16).slice(1));\n}\nexport function unsafeStringify(arr, offset = 0) {\n return (byteToHex[arr[offset + 0]] +\n byteToHex[arr[offset + 1]] +\n byteToHex[arr[offset + 2]] +\n byteToHex[arr[offset + 3]] +\n '-' +\n byteToHex[arr[offset + 4]] +\n byteToHex[arr[offset + 5]] +\n '-' +\n byteToHex[arr[offset + 6]] +\n byteToHex[arr[offset + 7]] +\n '-' +\n byteToHex[arr[offset + 8]] +\n byteToHex[arr[offset + 9]] +\n '-' +\n byteToHex[arr[offset + 10]] +\n byteToHex[arr[offset + 11]] +\n byteToHex[arr[offset + 12]] +\n byteToHex[arr[offset + 13]] +\n byteToHex[arr[offset + 14]] +\n byteToHex[arr[offset + 15]]).toLowerCase();\n}\nfunction stringify(arr, offset = 0) {\n const uuid = unsafeStringify(arr, offset);\n if (!validate(uuid)) {\n throw TypeError('Stringified UUID is invalid');\n }\n return uuid;\n}\nexport default stringify;\n","import { randomFillSync } from 'crypto';\nconst rnds8Pool = new Uint8Array(256);\nlet poolPtr = rnds8Pool.length;\nexport default function rng() {\n if (poolPtr > rnds8Pool.length - 16) {\n randomFillSync(rnds8Pool);\n poolPtr = 0;\n }\n return rnds8Pool.slice(poolPtr, (poolPtr += 16));\n}\n","import { randomUUID } from 'crypto';\nexport default { randomUUID };\n","import native from './native.js';\nimport rng from './rng.js';\nimport { unsafeStringify } from './stringify.js';\nfunction v4(options, buf, offset) {\n if (native.randomUUID && !buf && !options) {\n return native.randomUUID();\n }\n options = options || {};\n const rnds = options.random ?? options.rng?.() ?? rng();\n if (rnds.length < 16) {\n throw new Error('Random bytes length must be >= 16');\n }\n rnds[6] = (rnds[6] & 0x0f) | 0x40;\n rnds[8] = (rnds[8] & 0x3f) | 0x80;\n if (buf) {\n offset = offset || 0;\n if (offset < 0 || offset + 16 > buf.length) {\n throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);\n }\n for (let i = 0; i < 16; ++i) {\n buf[offset + i] = rnds[i];\n }\n return buf;\n }\n return unsafeStringify(rnds);\n}\nexport default v4;\n","import type Redis from \"ioredis\";\nimport type { GoogleGenAI, Content, FunctionDeclaration } from \"@google/genai\";\nimport type { SerializableToolDefinition } from \"../../../lib/types\";\nimport type { AgentResponse } from \"../../../lib/model\";\nimport type { ModelInvokerConfig } from \"../../../lib/model\";\nimport { createGoogleGenAIThreadManager } from \"./thread-manager\";\nimport { v4 as uuidv4 } from \"uuid\";\n\nexport interface GoogleGenAIModelInvokerConfig {\n redis: Redis;\n client: GoogleGenAI;\n model: string;\n}\n\nfunction toFunctionDeclarations(\n tools: SerializableToolDefinition[]\n): FunctionDeclaration[] {\n return tools.map((t) => ({\n name: t.name,\n description: t.description,\n parametersJsonSchema: t.schema,\n }));\n}\n\n/**\n * Merge consecutive Content objects sharing the same role.\n * The Gemini API requires alternating user/model turns; without\n * merging, multiple sequential tool-result messages would violate this.\n */\nfunction mergeConsecutiveContents(contents: Content[]): Content[] {\n const merged: Content[] = [];\n for (const content of contents) {\n const last = merged[merged.length - 1];\n if (last && last.role === content.role) {\n last.parts = [...(last.parts ?? []), ...(content.parts ?? [])];\n } else {\n merged.push({ ...content, parts: [...(content.parts ?? [])] });\n }\n }\n return merged;\n}\n\n/**\n * Creates a Google GenAI model invoker that satisfies the generic\n * `ModelInvoker<Content>` contract.\n *\n * Loads the conversation thread from Redis, invokes the Gemini model via\n * `client.models.generateContent`, appends the AI response, and returns\n * a normalised AgentResponse.\n *\n * @example\n * ```typescript\n * import { createGoogleGenAIModelInvoker } from 'zeitlich/adapters/thread/google-genai';\n * import { createRunAgentActivity } from 'zeitlich';\n * import { GoogleGenAI } from '@google/genai';\n *\n * const client = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });\n * const invoker = createGoogleGenAIModelInvoker({\n * redis,\n * client,\n * model: 'gemini-2.5-flash',\n * });\n *\n * return { runAgent: createRunAgentActivity(client, invoker) };\n * ```\n */\nexport function createGoogleGenAIModelInvoker({\n redis,\n client,\n model,\n}: GoogleGenAIModelInvokerConfig) {\n return async function invokeGoogleGenAIModel(\n config: ModelInvokerConfig\n ): Promise<AgentResponse<Content>> {\n const { threadId, state } = config;\n\n const thread = createGoogleGenAIThreadManager({ redis, threadId });\n const stored = await thread.load();\n\n // Separate system instructions from conversation content.\n // Google GenAI takes system instructions via config, not in the contents array.\n let systemInstruction: string | undefined;\n const conversationContents: Content[] = [];\n\n for (const item of stored) {\n if (item.content.role === \"system\") {\n systemInstruction = item.content.parts?.[0]?.text;\n } else {\n conversationContents.push(item.content);\n }\n }\n\n const contents = mergeConsecutiveContents(conversationContents);\n\n const functionDeclarations = toFunctionDeclarations(state.tools);\n const tools =\n functionDeclarations.length > 0 ? [{ functionDeclarations }] : undefined;\n\n const response = await client.models.generateContent({\n model,\n contents,\n config: {\n ...(systemInstruction ? { systemInstruction } : {}),\n ...(tools ? { tools } : {}),\n },\n });\n\n const responseParts = response.candidates?.[0]?.content?.parts ?? [];\n const modelContent: Content = { role: \"model\", parts: responseParts };\n\n await thread.appendModelContent(uuidv4(), responseParts);\n\n const functionCalls = response.functionCalls ?? [];\n\n return {\n message: modelContent,\n rawToolCalls: functionCalls.map((fc) => ({\n id: fc.id,\n name: fc.name ?? \"\",\n args: fc.args ?? {},\n })),\n usage: {\n inputTokens: response.usageMetadata?.promptTokenCount,\n outputTokens: response.usageMetadata?.candidatesTokenCount,\n cachedReadTokens: response.usageMetadata?.cachedContentTokenCount,\n },\n };\n };\n}\n\n/**\n * Standalone function for one-shot Google GenAI model invocation.\n * Convenience wrapper around createGoogleGenAIModelInvoker for cases\n * where you don't need to reuse the invoker.\n */\nexport async function invokeGoogleGenAIModel({\n redis,\n client,\n model,\n config,\n}: {\n redis: Redis;\n client: GoogleGenAI;\n model: string;\n config: ModelInvokerConfig;\n}): Promise<AgentResponse<Content>> {\n const invoker = createGoogleGenAIModelInvoker({ redis, client, model });\n return invoker(config);\n}\n","import type Redis from \"ioredis\";\nimport type { GoogleGenAI, Content } from \"@google/genai\";\nimport type { ToolResultConfig } from \"../../../lib/types\";\nimport type { MessageContent } from \"../../../lib/types\";\nimport type { ThreadOps } from \"../../../lib/session/types\";\nimport type { ModelInvoker } from \"../../../lib/model\";\nimport { createGoogleGenAIThreadManager } from \"./thread-manager\";\nimport { createGoogleGenAIModelInvoker } from \"./model-invoker\";\n\nexport interface GoogleGenAIAdapterConfig {\n redis: Redis;\n client: GoogleGenAI;\n /** Default model name (e.g. 'gemini-2.5-flash'). If omitted, use `createModelInvoker()` */\n model?: string;\n}\n\nexport interface GoogleGenAIAdapter {\n /** Thread operations (register these as Temporal activities on the worker) */\n threadOps: ThreadOps;\n /** Model invoker using the default model (only available when `model` was provided) */\n invoker: ModelInvoker<Content>;\n /** Create an invoker for a specific model name (for multi-model setups) */\n createModelInvoker(model: string): ModelInvoker<Content>;\n}\n\n/**\n * Creates a Google GenAI adapter that bundles thread operations and model\n * invocation using the `@google/genai` SDK.\n *\n * The returned `threadOps` should be registered as Temporal activities on\n * the worker. The `invoker` (or invokers created via `createModelInvoker`)\n * should be wrapped with `createRunAgentActivity` for per-agent activities.\n *\n * @example\n * ```typescript\n * import { createGoogleGenAIAdapter } from 'zeitlich/adapters/thread/google-genai';\n * import { createRunAgentActivity } from 'zeitlich';\n * import { GoogleGenAI } from '@google/genai';\n *\n * const client = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });\n * const adapter = createGoogleGenAIAdapter({ redis, client, model: 'gemini-2.5-flash' });\n *\n * export function createActivities(temporalClient: WorkflowClient) {\n * return {\n * ...adapter.threadOps,\n * runAgent: createRunAgentActivity(temporalClient, adapter.invoker),\n * };\n * }\n * ```\n *\n * @example Multi-model setup\n * ```typescript\n * const adapter = createGoogleGenAIAdapter({ redis, client });\n *\n * export function createActivities(temporalClient: WorkflowClient) {\n * return {\n * ...adapter.threadOps,\n * runResearchAgent: createRunAgentActivity(\n * temporalClient,\n * adapter.createModelInvoker('gemini-2.5-pro'),\n * ),\n * runFastAgent: createRunAgentActivity(\n * temporalClient,\n * adapter.createModelInvoker('gemini-2.5-flash'),\n * ),\n * };\n * }\n * ```\n */\nexport function createGoogleGenAIAdapter(\n config: GoogleGenAIAdapterConfig\n): GoogleGenAIAdapter {\n const { redis, client } = config;\n\n const threadOps: ThreadOps = {\n async initializeThread(threadId: string): Promise<void> {\n const thread = createGoogleGenAIThreadManager({ redis, threadId });\n await thread.initialize();\n },\n\n async appendHumanMessage(\n threadId: string,\n id: string,\n content: string | MessageContent\n ): Promise<void> {\n const thread = createGoogleGenAIThreadManager({ redis, threadId });\n await thread.appendUserMessage(id, content);\n },\n\n async appendSystemMessage(\n threadId: string,\n id: string,\n content: string\n ): Promise<void> {\n const thread = createGoogleGenAIThreadManager({ redis, threadId });\n await thread.appendSystemMessage(id, content);\n },\n\n async appendToolResult(id: string, cfg: ToolResultConfig): Promise<void> {\n const { threadId, toolCallId, toolName, content } = cfg;\n const thread = createGoogleGenAIThreadManager({ redis, threadId });\n await thread.appendToolResult(id, toolCallId, toolName, content);\n },\n\n async forkThread(\n sourceThreadId: string,\n targetThreadId: string\n ): Promise<void> {\n const thread = createGoogleGenAIThreadManager({\n redis,\n threadId: sourceThreadId,\n });\n await thread.fork(targetThreadId);\n },\n };\n\n const makeInvoker = (model: string): ModelInvoker<Content> =>\n createGoogleGenAIModelInvoker({ redis, client, model });\n\n const invoker: ModelInvoker<Content> = config.model\n ? makeInvoker(config.model)\n : ((() => {\n throw new Error(\n \"No default model provided to createGoogleGenAIAdapter. \" +\n \"Either pass `model` in the config or use `createModelInvoker(model)` instead.\"\n );\n }) as unknown as ModelInvoker<Content>);\n\n return {\n threadOps,\n invoker,\n createModelInvoker: makeInvoker,\n };\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import Redis from 'ioredis';
|
|
2
2
|
import { Content, GoogleGenAI, Part } from '@google/genai';
|
|
3
|
-
import { T as ThreadOps, M as ModelInvoker, a as ModelInvokerConfig, A as AgentResponse } from '../../../types-
|
|
3
|
+
import { T as ThreadOps, M as ModelInvoker, a as ModelInvokerConfig, A as AgentResponse } from '../../../types-CES_30qx.cjs';
|
|
4
4
|
import { B as BaseThreadManager } from '../../../types-35POpVfa.cjs';
|
|
5
|
-
import { M as MessageContent, T as ToolMessageContent } from '../../../types-
|
|
5
|
+
import { M as MessageContent, T as ToolMessageContent } from '../../../types-YbL7JpEA.cjs';
|
|
6
6
|
import '@temporalio/common';
|
|
7
7
|
import 'zod';
|
|
8
8
|
import '../../../types-BMRzfELQ.cjs';
|
|
@@ -82,14 +82,14 @@ interface GoogleGenAIThreadManagerConfig {
|
|
|
82
82
|
}
|
|
83
83
|
/** Thread manager with Google GenAI Content convenience helpers */
|
|
84
84
|
interface GoogleGenAIThreadManager extends BaseThreadManager<StoredContent> {
|
|
85
|
-
createUserContent(content: string | MessageContent): StoredContent;
|
|
86
|
-
createSystemContent(content: string): StoredContent;
|
|
87
|
-
createModelContent(parts: Part[]): StoredContent;
|
|
88
|
-
createToolResponseContent(toolCallId: string, toolName: string, content: ToolMessageContent): StoredContent;
|
|
89
|
-
appendUserMessage(content: string | MessageContent): Promise<void>;
|
|
90
|
-
appendSystemMessage(content: string): Promise<void>;
|
|
91
|
-
appendModelContent(parts: Part[]): Promise<void>;
|
|
92
|
-
appendToolResult(toolCallId: string, toolName: string, content: ToolMessageContent): Promise<void>;
|
|
85
|
+
createUserContent(id: string, content: string | MessageContent): StoredContent;
|
|
86
|
+
createSystemContent(id: string, content: string): StoredContent;
|
|
87
|
+
createModelContent(id: string, parts: Part[]): StoredContent;
|
|
88
|
+
createToolResponseContent(id: string, toolCallId: string, toolName: string, content: ToolMessageContent): StoredContent;
|
|
89
|
+
appendUserMessage(id: string, content: string | MessageContent): Promise<void>;
|
|
90
|
+
appendSystemMessage(id: string, content: string): Promise<void>;
|
|
91
|
+
appendModelContent(id: string, parts: Part[]): Promise<void>;
|
|
92
|
+
appendToolResult(id: string, toolCallId: string, toolName: string, content: ToolMessageContent): Promise<void>;
|
|
93
93
|
}
|
|
94
94
|
/** Convert zeitlich MessageContent to Google GenAI Part[] */
|
|
95
95
|
declare function messageContentToParts(content: string | MessageContent): Part[];
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import Redis from 'ioredis';
|
|
2
2
|
import { Content, GoogleGenAI, Part } from '@google/genai';
|
|
3
|
-
import { T as ThreadOps, M as ModelInvoker, a as ModelInvokerConfig, A as AgentResponse } from '../../../types-
|
|
3
|
+
import { T as ThreadOps, M as ModelInvoker, a as ModelInvokerConfig, A as AgentResponse } from '../../../types-BkAYmc96.js';
|
|
4
4
|
import { B as BaseThreadManager } from '../../../types-35POpVfa.js';
|
|
5
|
-
import { M as MessageContent, T as ToolMessageContent } from '../../../types-
|
|
5
|
+
import { M as MessageContent, T as ToolMessageContent } from '../../../types-YbL7JpEA.js';
|
|
6
6
|
import '@temporalio/common';
|
|
7
7
|
import 'zod';
|
|
8
8
|
import '../../../types-BMRzfELQ.js';
|
|
@@ -82,14 +82,14 @@ interface GoogleGenAIThreadManagerConfig {
|
|
|
82
82
|
}
|
|
83
83
|
/** Thread manager with Google GenAI Content convenience helpers */
|
|
84
84
|
interface GoogleGenAIThreadManager extends BaseThreadManager<StoredContent> {
|
|
85
|
-
createUserContent(content: string | MessageContent): StoredContent;
|
|
86
|
-
createSystemContent(content: string): StoredContent;
|
|
87
|
-
createModelContent(parts: Part[]): StoredContent;
|
|
88
|
-
createToolResponseContent(toolCallId: string, toolName: string, content: ToolMessageContent): StoredContent;
|
|
89
|
-
appendUserMessage(content: string | MessageContent): Promise<void>;
|
|
90
|
-
appendSystemMessage(content: string): Promise<void>;
|
|
91
|
-
appendModelContent(parts: Part[]): Promise<void>;
|
|
92
|
-
appendToolResult(toolCallId: string, toolName: string, content: ToolMessageContent): Promise<void>;
|
|
85
|
+
createUserContent(id: string, content: string | MessageContent): StoredContent;
|
|
86
|
+
createSystemContent(id: string, content: string): StoredContent;
|
|
87
|
+
createModelContent(id: string, parts: Part[]): StoredContent;
|
|
88
|
+
createToolResponseContent(id: string, toolCallId: string, toolName: string, content: ToolMessageContent): StoredContent;
|
|
89
|
+
appendUserMessage(id: string, content: string | MessageContent): Promise<void>;
|
|
90
|
+
appendSystemMessage(id: string, content: string): Promise<void>;
|
|
91
|
+
appendModelContent(id: string, parts: Part[]): Promise<void>;
|
|
92
|
+
appendToolResult(id: string, toolCallId: string, toolName: string, content: ToolMessageContent): Promise<void>;
|
|
93
93
|
}
|
|
94
94
|
/** Convert zeitlich MessageContent to Google GenAI Part[] */
|
|
95
95
|
declare function messageContentToParts(content: string | MessageContent): Part[];
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { randomUUID, randomFillSync } from 'crypto';
|
|
2
|
+
|
|
1
3
|
// src/lib/thread/manager.ts
|
|
2
4
|
var THREAD_TTL_SECONDS = 60 * 60 * 24 * 90;
|
|
3
5
|
var APPEND_IDEMPOTENT_SCRIPT = `
|
|
@@ -119,27 +121,27 @@ function createGoogleGenAIThreadManager(config) {
|
|
|
119
121
|
};
|
|
120
122
|
const base = createThreadManager(baseConfig);
|
|
121
123
|
const helpers = {
|
|
122
|
-
createUserContent(content) {
|
|
124
|
+
createUserContent(id, content) {
|
|
123
125
|
return {
|
|
124
|
-
id
|
|
126
|
+
id,
|
|
125
127
|
content: { role: "user", parts: messageContentToParts(content) }
|
|
126
128
|
};
|
|
127
129
|
},
|
|
128
|
-
createSystemContent(content) {
|
|
130
|
+
createSystemContent(id, content) {
|
|
129
131
|
return {
|
|
130
|
-
id
|
|
132
|
+
id,
|
|
131
133
|
content: { role: "system", parts: [{ text: content }] }
|
|
132
134
|
};
|
|
133
135
|
},
|
|
134
|
-
createModelContent(parts) {
|
|
136
|
+
createModelContent(id, parts) {
|
|
135
137
|
return {
|
|
136
|
-
id
|
|
138
|
+
id,
|
|
137
139
|
content: { role: "model", parts }
|
|
138
140
|
};
|
|
139
141
|
},
|
|
140
|
-
createToolResponseContent(toolCallId, toolName, content) {
|
|
142
|
+
createToolResponseContent(id, toolCallId, toolName, content) {
|
|
141
143
|
return {
|
|
142
|
-
id
|
|
144
|
+
id,
|
|
143
145
|
content: {
|
|
144
146
|
role: "user",
|
|
145
147
|
parts: [
|
|
@@ -154,25 +156,70 @@ function createGoogleGenAIThreadManager(config) {
|
|
|
154
156
|
}
|
|
155
157
|
};
|
|
156
158
|
},
|
|
157
|
-
async appendUserMessage(content) {
|
|
158
|
-
await base.append([helpers.createUserContent(content)]);
|
|
159
|
+
async appendUserMessage(id, content) {
|
|
160
|
+
await base.append([helpers.createUserContent(id, content)]);
|
|
159
161
|
},
|
|
160
|
-
async appendSystemMessage(content) {
|
|
162
|
+
async appendSystemMessage(id, content) {
|
|
161
163
|
await base.initialize();
|
|
162
|
-
await base.append([helpers.createSystemContent(content)]);
|
|
164
|
+
await base.append([helpers.createSystemContent(id, content)]);
|
|
163
165
|
},
|
|
164
|
-
async appendModelContent(parts) {
|
|
165
|
-
await base.append([helpers.createModelContent(parts)]);
|
|
166
|
+
async appendModelContent(id, parts) {
|
|
167
|
+
await base.append([helpers.createModelContent(id, parts)]);
|
|
166
168
|
},
|
|
167
|
-
async appendToolResult(toolCallId, toolName, content) {
|
|
169
|
+
async appendToolResult(id, toolCallId, toolName, content) {
|
|
168
170
|
await base.append([
|
|
169
|
-
helpers.createToolResponseContent(toolCallId, toolName, content)
|
|
171
|
+
helpers.createToolResponseContent(id, toolCallId, toolName, content)
|
|
170
172
|
]);
|
|
171
173
|
}
|
|
172
174
|
};
|
|
173
175
|
return Object.assign(base, helpers);
|
|
174
176
|
}
|
|
175
177
|
|
|
178
|
+
// node_modules/uuid/dist/esm/stringify.js
|
|
179
|
+
var byteToHex = [];
|
|
180
|
+
for (let i = 0; i < 256; ++i) {
|
|
181
|
+
byteToHex.push((i + 256).toString(16).slice(1));
|
|
182
|
+
}
|
|
183
|
+
function unsafeStringify(arr, offset = 0) {
|
|
184
|
+
return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
|
|
185
|
+
}
|
|
186
|
+
var rnds8Pool = new Uint8Array(256);
|
|
187
|
+
var poolPtr = rnds8Pool.length;
|
|
188
|
+
function rng() {
|
|
189
|
+
if (poolPtr > rnds8Pool.length - 16) {
|
|
190
|
+
randomFillSync(rnds8Pool);
|
|
191
|
+
poolPtr = 0;
|
|
192
|
+
}
|
|
193
|
+
return rnds8Pool.slice(poolPtr, poolPtr += 16);
|
|
194
|
+
}
|
|
195
|
+
var native_default = { randomUUID };
|
|
196
|
+
|
|
197
|
+
// node_modules/uuid/dist/esm/v4.js
|
|
198
|
+
function v4(options, buf, offset) {
|
|
199
|
+
if (native_default.randomUUID && !buf && !options) {
|
|
200
|
+
return native_default.randomUUID();
|
|
201
|
+
}
|
|
202
|
+
options = options || {};
|
|
203
|
+
const rnds = options.random ?? options.rng?.() ?? rng();
|
|
204
|
+
if (rnds.length < 16) {
|
|
205
|
+
throw new Error("Random bytes length must be >= 16");
|
|
206
|
+
}
|
|
207
|
+
rnds[6] = rnds[6] & 15 | 64;
|
|
208
|
+
rnds[8] = rnds[8] & 63 | 128;
|
|
209
|
+
if (buf) {
|
|
210
|
+
offset = offset || 0;
|
|
211
|
+
if (offset < 0 || offset + 16 > buf.length) {
|
|
212
|
+
throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
|
|
213
|
+
}
|
|
214
|
+
for (let i = 0; i < 16; ++i) {
|
|
215
|
+
buf[offset + i] = rnds[i];
|
|
216
|
+
}
|
|
217
|
+
return buf;
|
|
218
|
+
}
|
|
219
|
+
return unsafeStringify(rnds);
|
|
220
|
+
}
|
|
221
|
+
var v4_default = v4;
|
|
222
|
+
|
|
176
223
|
// src/adapters/thread/google-genai/model-invoker.ts
|
|
177
224
|
function toFunctionDeclarations(tools) {
|
|
178
225
|
return tools.map((t) => ({
|
|
@@ -224,7 +271,7 @@ function createGoogleGenAIModelInvoker({
|
|
|
224
271
|
});
|
|
225
272
|
const responseParts = response.candidates?.[0]?.content?.parts ?? [];
|
|
226
273
|
const modelContent = { role: "model", parts: responseParts };
|
|
227
|
-
await thread.appendModelContent(responseParts);
|
|
274
|
+
await thread.appendModelContent(v4_default(), responseParts);
|
|
228
275
|
const functionCalls = response.functionCalls ?? [];
|
|
229
276
|
return {
|
|
230
277
|
message: modelContent,
|
|
@@ -259,18 +306,18 @@ function createGoogleGenAIAdapter(config) {
|
|
|
259
306
|
const thread = createGoogleGenAIThreadManager({ redis, threadId });
|
|
260
307
|
await thread.initialize();
|
|
261
308
|
},
|
|
262
|
-
async appendHumanMessage(threadId, content) {
|
|
309
|
+
async appendHumanMessage(threadId, id, content) {
|
|
263
310
|
const thread = createGoogleGenAIThreadManager({ redis, threadId });
|
|
264
|
-
await thread.appendUserMessage(content);
|
|
311
|
+
await thread.appendUserMessage(id, content);
|
|
265
312
|
},
|
|
266
|
-
async appendSystemMessage(threadId, content) {
|
|
313
|
+
async appendSystemMessage(threadId, id, content) {
|
|
267
314
|
const thread = createGoogleGenAIThreadManager({ redis, threadId });
|
|
268
|
-
await thread.appendSystemMessage(content);
|
|
315
|
+
await thread.appendSystemMessage(id, content);
|
|
269
316
|
},
|
|
270
|
-
async appendToolResult(cfg) {
|
|
317
|
+
async appendToolResult(id, cfg) {
|
|
271
318
|
const { threadId, toolCallId, toolName, content } = cfg;
|
|
272
319
|
const thread = createGoogleGenAIThreadManager({ redis, threadId });
|
|
273
|
-
await thread.appendToolResult(toolCallId, toolName, content);
|
|
320
|
+
await thread.appendToolResult(id, toolCallId, toolName, content);
|
|
274
321
|
},
|
|
275
322
|
async forkThread(sourceThreadId, targetThreadId) {
|
|
276
323
|
const thread = createGoogleGenAIThreadManager({
|