zeitlich 0.2.32 → 0.2.34

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.
Files changed (143) hide show
  1. package/README.md +28 -16
  2. package/dist/{activities-FIXVz7DT.d.ts → activities-JOqPfKP0.d.cts} +6 -5
  3. package/dist/{activities-DA-bQM12.d.cts → activities-WwMsjRwm.d.ts} +6 -5
  4. package/dist/adapters/sandbox/bedrock/index.cjs +2 -0
  5. package/dist/adapters/sandbox/bedrock/index.cjs.map +1 -1
  6. package/dist/adapters/sandbox/bedrock/index.d.cts +4 -3
  7. package/dist/adapters/sandbox/bedrock/index.d.ts +4 -3
  8. package/dist/adapters/sandbox/bedrock/index.js +2 -0
  9. package/dist/adapters/sandbox/bedrock/index.js.map +1 -1
  10. package/dist/adapters/sandbox/bedrock/workflow.cjs +1 -0
  11. package/dist/adapters/sandbox/bedrock/workflow.cjs.map +1 -1
  12. package/dist/adapters/sandbox/bedrock/workflow.d.cts +2 -2
  13. package/dist/adapters/sandbox/bedrock/workflow.d.ts +2 -2
  14. package/dist/adapters/sandbox/bedrock/workflow.js +1 -0
  15. package/dist/adapters/sandbox/bedrock/workflow.js.map +1 -1
  16. package/dist/adapters/sandbox/daytona/index.cjs +2 -0
  17. package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
  18. package/dist/adapters/sandbox/daytona/index.d.cts +2 -1
  19. package/dist/adapters/sandbox/daytona/index.d.ts +2 -1
  20. package/dist/adapters/sandbox/daytona/index.js +2 -0
  21. package/dist/adapters/sandbox/daytona/index.js.map +1 -1
  22. package/dist/adapters/sandbox/daytona/workflow.cjs +1 -0
  23. package/dist/adapters/sandbox/daytona/workflow.cjs.map +1 -1
  24. package/dist/adapters/sandbox/daytona/workflow.d.cts +1 -1
  25. package/dist/adapters/sandbox/daytona/workflow.d.ts +1 -1
  26. package/dist/adapters/sandbox/daytona/workflow.js +1 -0
  27. package/dist/adapters/sandbox/daytona/workflow.js.map +1 -1
  28. package/dist/adapters/sandbox/e2b/index.cjs +3 -0
  29. package/dist/adapters/sandbox/e2b/index.cjs.map +1 -1
  30. package/dist/adapters/sandbox/e2b/index.d.cts +2 -1
  31. package/dist/adapters/sandbox/e2b/index.d.ts +2 -1
  32. package/dist/adapters/sandbox/e2b/index.js +3 -0
  33. package/dist/adapters/sandbox/e2b/index.js.map +1 -1
  34. package/dist/adapters/sandbox/e2b/workflow.cjs +1 -0
  35. package/dist/adapters/sandbox/e2b/workflow.cjs.map +1 -1
  36. package/dist/adapters/sandbox/e2b/workflow.d.cts +1 -1
  37. package/dist/adapters/sandbox/e2b/workflow.d.ts +1 -1
  38. package/dist/adapters/sandbox/e2b/workflow.js +1 -0
  39. package/dist/adapters/sandbox/e2b/workflow.js.map +1 -1
  40. package/dist/adapters/sandbox/inmemory/index.cjs +2 -0
  41. package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -1
  42. package/dist/adapters/sandbox/inmemory/index.d.cts +2 -1
  43. package/dist/adapters/sandbox/inmemory/index.d.ts +2 -1
  44. package/dist/adapters/sandbox/inmemory/index.js +2 -0
  45. package/dist/adapters/sandbox/inmemory/index.js.map +1 -1
  46. package/dist/adapters/sandbox/inmemory/workflow.cjs +1 -0
  47. package/dist/adapters/sandbox/inmemory/workflow.cjs.map +1 -1
  48. package/dist/adapters/sandbox/inmemory/workflow.d.cts +1 -1
  49. package/dist/adapters/sandbox/inmemory/workflow.d.ts +1 -1
  50. package/dist/adapters/sandbox/inmemory/workflow.js +1 -0
  51. package/dist/adapters/sandbox/inmemory/workflow.js.map +1 -1
  52. package/dist/adapters/thread/anthropic/index.cjs +18 -2
  53. package/dist/adapters/thread/anthropic/index.cjs.map +1 -1
  54. package/dist/adapters/thread/anthropic/index.d.cts +12 -11
  55. package/dist/adapters/thread/anthropic/index.d.ts +12 -11
  56. package/dist/adapters/thread/anthropic/index.js +18 -2
  57. package/dist/adapters/thread/anthropic/index.js.map +1 -1
  58. package/dist/adapters/thread/anthropic/workflow.d.cts +5 -5
  59. package/dist/adapters/thread/anthropic/workflow.d.ts +5 -5
  60. package/dist/adapters/thread/google-genai/index.cjs +29 -8
  61. package/dist/adapters/thread/google-genai/index.cjs.map +1 -1
  62. package/dist/adapters/thread/google-genai/index.d.cts +8 -8
  63. package/dist/adapters/thread/google-genai/index.d.ts +8 -8
  64. package/dist/adapters/thread/google-genai/index.js +29 -8
  65. package/dist/adapters/thread/google-genai/index.js.map +1 -1
  66. package/dist/adapters/thread/google-genai/workflow.d.cts +5 -5
  67. package/dist/adapters/thread/google-genai/workflow.d.ts +5 -5
  68. package/dist/adapters/thread/langchain/index.cjs +42 -23
  69. package/dist/adapters/thread/langchain/index.cjs.map +1 -1
  70. package/dist/adapters/thread/langchain/index.d.cts +13 -11
  71. package/dist/adapters/thread/langchain/index.d.ts +13 -11
  72. package/dist/adapters/thread/langchain/index.js +42 -23
  73. package/dist/adapters/thread/langchain/index.js.map +1 -1
  74. package/dist/adapters/thread/langchain/workflow.d.cts +5 -5
  75. package/dist/adapters/thread/langchain/workflow.d.ts +5 -5
  76. package/dist/index.cjs +148 -34
  77. package/dist/index.cjs.map +1 -1
  78. package/dist/index.d.cts +32 -16
  79. package/dist/index.d.ts +32 -16
  80. package/dist/index.js +147 -35
  81. package/dist/index.js.map +1 -1
  82. package/dist/{proxy-CTCYWjkr.d.cts → proxy-BesT2ioL.d.cts} +1 -1
  83. package/dist/{proxy-Br4unLTC.d.ts → proxy-Bz6wXYW-.d.ts} +1 -1
  84. package/dist/{thread-manager-Cv_BR28i.d.cts → thread-manager-CCVAOK8g.d.cts} +1 -1
  85. package/dist/{thread-manager-CUubPYPH.d.cts → thread-manager-Cf_34H8w.d.cts} +1 -1
  86. package/dist/{thread-manager-YJLoc1vH.d.ts → thread-manager-ClKAQx78.d.ts} +1 -1
  87. package/dist/{thread-manager-DKWxHUzD.d.ts → thread-manager-DarJIK_b.d.ts} +1 -1
  88. package/dist/{types-Bpq5fDI5.d.cts → types-BGLW5Zyj.d.ts} +35 -20
  89. package/dist/{types-BxiT8w9d.d.ts → types-BVUmLYpj.d.ts} +1 -1
  90. package/dist/{types-DUvEZSDe.d.cts → types-CBH54cwr.d.cts} +1 -1
  91. package/dist/{types-NJDyMyUx.d.cts → types-DPAZ3KCs.d.cts} +1 -1
  92. package/dist/{types-CheCTLeV.d.ts → types-DlLajQcu.d.cts} +35 -20
  93. package/dist/{types-AujBIMMn.d.cts → types-DxCpFNv_.d.cts} +4 -0
  94. package/dist/{types-AujBIMMn.d.ts → types-DxCpFNv_.d.ts} +4 -0
  95. package/dist/{types-DBk-C8zM.d.ts → types-wiGLvxWf.d.ts} +1 -1
  96. package/dist/{workflow-BWKQcz9d.d.cts → workflow-_ZGcacCK.d.ts} +32 -4
  97. package/dist/{workflow-D8wK7TJY.d.ts → workflow-hocXpLwg.d.cts} +32 -4
  98. package/dist/workflow.cjs +126 -30
  99. package/dist/workflow.cjs.map +1 -1
  100. package/dist/workflow.d.cts +3 -3
  101. package/dist/workflow.d.ts +3 -3
  102. package/dist/workflow.js +126 -31
  103. package/dist/workflow.js.map +1 -1
  104. package/package.json +1 -1
  105. package/src/adapters/sandbox/bedrock/index.ts +4 -0
  106. package/src/adapters/sandbox/bedrock/proxy.ts +1 -0
  107. package/src/adapters/sandbox/daytona/index.ts +4 -0
  108. package/src/adapters/sandbox/daytona/proxy.ts +1 -0
  109. package/src/adapters/sandbox/e2b/index.ts +4 -0
  110. package/src/adapters/sandbox/e2b/proxy.ts +1 -0
  111. package/src/adapters/sandbox/inmemory/index.ts +4 -0
  112. package/src/adapters/sandbox/inmemory/proxy.ts +1 -0
  113. package/src/adapters/thread/anthropic/activities.ts +4 -3
  114. package/src/adapters/thread/anthropic/model-invoker.ts +15 -5
  115. package/src/adapters/thread/google-genai/activities.ts +4 -3
  116. package/src/adapters/thread/google-genai/model-invoker.ts +24 -11
  117. package/src/adapters/thread/langchain/activities.ts +3 -3
  118. package/src/adapters/thread/langchain/model-invoker.ts +63 -34
  119. package/src/index.ts +1 -0
  120. package/src/lib/activity.ts +36 -9
  121. package/src/lib/lifecycle.ts +7 -3
  122. package/src/lib/model/helpers.ts +1 -0
  123. package/src/lib/model/index.ts +1 -0
  124. package/src/lib/model/proxy.ts +50 -0
  125. package/src/lib/sandbox/manager.ts +7 -0
  126. package/src/lib/sandbox/types.ts +4 -0
  127. package/src/lib/session/session-edge-cases.integration.test.ts +194 -0
  128. package/src/lib/session/session.integration.test.ts +5 -0
  129. package/src/lib/session/session.ts +9 -0
  130. package/src/lib/session/types.ts +5 -0
  131. package/src/lib/subagent/define.ts +1 -1
  132. package/src/lib/subagent/handler.ts +142 -32
  133. package/src/lib/subagent/index.ts +5 -1
  134. package/src/lib/subagent/signals.ts +8 -1
  135. package/src/lib/subagent/subagent.integration.test.ts +532 -25
  136. package/src/lib/subagent/types.ts +32 -15
  137. package/src/lib/subagent/workflow.ts +26 -13
  138. package/src/lib/virtual-fs/manager.ts +1 -1
  139. package/src/lib/virtual-fs/types.ts +2 -2
  140. package/src/lib/virtual-fs/virtual-fs.test.ts +2 -2
  141. package/src/workflow.ts +3 -0
  142. package/src/lib/.env +0 -1
  143. package/src/tools/bash/.env +0 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/lib/thread/manager.ts","../../../../src/adapters/thread/anthropic/thread-manager.ts","../../../../src/adapters/thread/anthropic/model-invoker.ts","../../../../src/adapters/thread/anthropic/activities.ts"],"names":["invokeAnthropicModel"],"mappings":"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","file":"index.js","sourcesContent":["import type { ThreadManagerConfig, BaseThreadManager } 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 `${key}:thread:${threadId}`;\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 Anthropic from \"@anthropic-ai/sdk\";\nimport type { JsonValue } from \"../../../lib/state/types\";\nimport { createThreadManager } from \"../../../lib/thread/manager\";\nimport type {\n ProviderThreadManager,\n ThreadManagerConfig,\n ThreadManagerHooks,\n} from \"../../../lib/thread/types\";\n\n/** SDK-native content type for Anthropic human messages */\nexport type AnthropicContent =\n | string\n | Anthropic.Messages.ContentBlockParam[];\n\n/** A MessageParam with a unique ID for idempotent Redis storage */\nexport interface StoredMessage {\n id: string;\n message: Anthropic.Messages.MessageParam;\n /** System messages are stored separately since Anthropic passes them via config */\n isSystem?: boolean;\n}\n\nexport type AnthropicThreadManagerHooks = ThreadManagerHooks<StoredMessage, Anthropic.Messages.MessageParam>;\n\nexport interface AnthropicThreadManagerConfig {\n redis: Redis;\n threadId: string;\n /** Thread key, defaults to 'messages' */\n key?: string;\n hooks?: AnthropicThreadManagerHooks;\n}\n\n/** Prepared payload ready to send to the Anthropic API */\nexport interface AnthropicInvocationPayload {\n messages: Anthropic.Messages.MessageParam[];\n system?: string;\n}\n\n/** Thread manager with Anthropic MessageParam convenience helpers */\nexport interface AnthropicThreadManager\n extends ProviderThreadManager<StoredMessage, AnthropicContent> {\n appendAssistantMessage(\n id: string,\n content: Anthropic.Messages.ContentBlock[],\n ): Promise<void>;\n prepareForInvocation(): Promise<AnthropicInvocationPayload>;\n}\n\nfunction storedMessageId(msg: StoredMessage): string {\n return msg.id;\n}\n\n/** Normalise content into an array of ContentBlockParam */\nfunction toContentBlocks(\n content: AnthropicContent,\n): Anthropic.Messages.ContentBlockParam[] {\n if (typeof content === \"string\") {\n return [{ type: \"text\", text: content }];\n }\n return content;\n}\n\n/**\n * Merge consecutive messages with the same role.\n * The Anthropic API requires alternating user/assistant turns; without\n * merging, multiple sequential tool-result messages would violate this.\n */\nfunction mergeConsecutiveMessages(\n messages: Anthropic.Messages.MessageParam[],\n): Anthropic.Messages.MessageParam[] {\n const merged: Anthropic.Messages.MessageParam[] = [];\n for (const msg of messages) {\n const last = merged[merged.length - 1];\n if (last && last.role === msg.role) {\n const lastContent = Array.isArray(last.content)\n ? last.content\n : [{ type: \"text\" as const, text: last.content }];\n const msgContent = Array.isArray(msg.content)\n ? msg.content\n : [{ type: \"text\" as const, text: msg.content }];\n last.content = [...lastContent, ...msgContent];\n } else {\n merged.push({\n ...msg,\n content: Array.isArray(msg.content)\n ? [...msg.content]\n : msg.content,\n });\n }\n }\n return merged;\n}\n\n/**\n * Creates an Anthropic-specific thread manager that stores StoredMessage\n * instances in Redis and provides convenience helpers for creating and\n * appending typed messages.\n */\nexport function createAnthropicThreadManager(\n config: AnthropicThreadManagerConfig,\n): AnthropicThreadManager {\n const baseConfig: ThreadManagerConfig<StoredMessage> = {\n redis: config.redis,\n threadId: config.threadId,\n key: config.key,\n idOf: storedMessageId,\n };\n\n const base = createThreadManager(baseConfig);\n\n const helpers: Omit<AnthropicThreadManager, keyof typeof base> = {\n async appendUserMessage(\n id: string,\n content: AnthropicContent,\n ): Promise<void> {\n await base.append([{\n id,\n message: { role: \"user\", content: toContentBlocks(content) },\n }]);\n },\n\n async appendSystemMessage(id: string, content: string): Promise<void> {\n await base.initialize();\n await base.append([{\n id,\n message: { role: \"user\", content },\n isSystem: true,\n }]);\n },\n\n async appendAssistantMessage(\n id: string,\n content: Anthropic.Messages.ContentBlock[],\n ): Promise<void> {\n await base.append([{\n id,\n message: {\n role: \"assistant\",\n content: content as unknown as Anthropic.Messages.ContentBlockParam[],\n },\n }]);\n },\n\n async appendToolResult(\n id: string,\n toolCallId: string,\n _toolName: string,\n content: JsonValue,\n ): Promise<void> {\n const toolContent =\n typeof content === \"string\"\n ? content\n : Array.isArray(content)\n ? (content as unknown as Anthropic.Messages.ToolResultBlockParam[\"content\"])\n : JSON.stringify(content);\n await base.append([{\n id,\n message: {\n role: \"user\",\n content: [{\n type: \"tool_result\" as const,\n tool_use_id: toolCallId,\n content: toolContent,\n }],\n },\n }]);\n },\n\n async prepareForInvocation(): Promise<AnthropicInvocationPayload> {\n const stored = await base.load();\n const { onPrepareMessage, onPreparedMessage } = config.hooks ?? {};\n const mapped = onPrepareMessage\n ? stored.map((msg, i) => onPrepareMessage(msg, i, stored))\n : stored;\n\n let system: string | undefined;\n const conversationMessages: Anthropic.Messages.MessageParam[] = [];\n\n for (const item of mapped) {\n if (item.isSystem) {\n system =\n typeof item.message.content === \"string\"\n ? item.message.content\n : undefined;\n } else {\n conversationMessages.push(item.message);\n }\n }\n\n const messages = mergeConsecutiveMessages(conversationMessages);\n return {\n messages: onPreparedMessage\n ? messages.map((msg, i) => onPreparedMessage(msg, i, messages))\n : messages,\n ...(system ? { system } : {}),\n };\n },\n };\n\n return Object.assign(base, helpers);\n}\n","import type Redis from \"ioredis\";\nimport type Anthropic from \"@anthropic-ai/sdk\";\nimport type { SerializableToolDefinition } from \"../../../lib/types\";\nimport type { AgentResponse, ModelInvokerConfig } from \"../../../lib/model\";\nimport { createAnthropicThreadManager, type AnthropicThreadManagerHooks } from \"./thread-manager\";\n\nexport interface AnthropicModelInvokerConfig {\n redis: Redis;\n client: Anthropic;\n model: string;\n /** Maximum tokens to generate. Defaults to 16384. */\n maxTokens?: number;\n hooks?: AnthropicThreadManagerHooks;\n}\n\nfunction toAnthropicTools(\n tools: SerializableToolDefinition[],\n): Anthropic.Messages.Tool[] {\n return tools.map((t) => ({\n name: t.name,\n description: t.description,\n input_schema: t.schema as Anthropic.Messages.Tool.InputSchema,\n }));\n}\n\n/**\n * Creates an Anthropic model invoker that satisfies the generic\n * `ModelInvoker<Anthropic.Messages.Message>` contract.\n *\n * Loads the conversation thread from Redis, invokes the Claude model via\n * `client.messages.create`, and returns a normalised AgentResponse.\n * The caller is responsible for appending the response to the thread.\n *\n * @example\n * ```typescript\n * import { createAnthropicModelInvoker } from 'zeitlich/adapters/thread/anthropic';\n * import { createRunAgentActivity } from 'zeitlich';\n * import Anthropic from '@anthropic-ai/sdk';\n *\n * const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });\n * const invoker = createAnthropicModelInvoker({\n * redis,\n * client,\n * model: 'claude-sonnet-4-20250514',\n * });\n *\n * return { runAgent: createRunAgentActivity(client, invoker) };\n * ```\n */\nexport function createAnthropicModelInvoker({\n redis,\n client,\n model,\n maxTokens = 16384,\n hooks,\n}: AnthropicModelInvokerConfig) {\n return async function invokeAnthropicModel(\n config: ModelInvokerConfig,\n ): Promise<AgentResponse<Anthropic.Messages.Message>> {\n const { threadId, threadKey, state } = config;\n\n const thread = createAnthropicThreadManager({ redis, threadId, key: threadKey, hooks });\n const { messages, system } = await thread.prepareForInvocation();\n\n const anthropicTools = toAnthropicTools(state.tools);\n const tools = anthropicTools.length > 0 ? anthropicTools : undefined;\n\n const response = await client.messages.create({\n model,\n max_tokens: maxTokens,\n messages,\n ...(system ? { system } : {}),\n ...(tools ? { tools } : {}),\n });\n\n const toolCalls = response.content.filter(\n (block): block is Anthropic.Messages.ToolUseBlock =>\n block.type === \"tool_use\",\n );\n\n return {\n message: response,\n rawToolCalls: toolCalls.map((tc) => ({\n id: tc.id,\n name: tc.name,\n args: (tc.input as Record<string, unknown>) ?? {},\n })),\n usage: {\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n cachedWriteTokens: response.usage.cache_creation_input_tokens ?? undefined,\n cachedReadTokens: response.usage.cache_read_input_tokens ?? undefined,\n },\n };\n };\n}\n\n/**\n * Standalone function for one-shot Anthropic model invocation.\n * Convenience wrapper around createAnthropicModelInvoker for cases\n * where you don't need to reuse the invoker.\n */\nexport async function invokeAnthropicModel({\n redis,\n client,\n model,\n maxTokens,\n hooks,\n config,\n}: {\n redis: Redis;\n client: Anthropic;\n model: string;\n maxTokens?: number;\n hooks?: AnthropicThreadManagerHooks;\n config: ModelInvokerConfig;\n}): Promise<AgentResponse<Anthropic.Messages.Message>> {\n const invoker = createAnthropicModelInvoker({\n redis,\n client,\n model,\n maxTokens,\n hooks,\n });\n return invoker(config);\n}\n","import type Redis from \"ioredis\";\nimport type Anthropic from \"@anthropic-ai/sdk\";\nimport type { ToolResultConfig } from \"../../../lib/types\";\nimport type {\n ActivityToolHandler,\n RouterContext,\n ToolHandlerResponse,\n} from \"../../../lib/tool-router/types\";\nimport type {\n ThreadOps,\n PrefixedThreadOps,\n ScopedPrefix,\n} from \"../../../lib/session/types\";\nimport type { ModelInvoker } from \"../../../lib/model\";\nimport {\n createAnthropicThreadManager,\n type AnthropicContent,\n type AnthropicThreadManagerHooks,\n} from \"./thread-manager\";\nimport {\n createAnthropicModelInvoker,\n type AnthropicModelInvokerConfig,\n} from \"./model-invoker\";\n\nconst ADAPTER_PREFIX = \"anthropic\" as const;\n\nexport type AnthropicThreadOps<TScope extends string = \"\"> =\n PrefixedThreadOps<ScopedPrefix<TScope, typeof ADAPTER_PREFIX>, AnthropicContent>;\n\nexport interface AnthropicAdapterConfig {\n redis: Redis;\n client: Anthropic;\n /** Default model name (e.g. 'claude-sonnet-4-20250514'). If omitted, use `createModelInvoker()` */\n model?: string;\n /** Maximum tokens to generate. Defaults to 16384. */\n maxTokens?: number;\n hooks?: AnthropicThreadManagerHooks;\n}\n\n/**\n * Tool response type accepted by the Anthropic adapter.\n *\n * Handlers can return:\n * - **`string`** — plain text content for the tool result.\n * - **`Anthropic.Messages.ToolResultBlockParam[\"content\"]`** — array of content blocks\n * (e.g. `{ type: \"text\", text: \"...\" }`, `{ type: \"image\", source: { ... } }`).\n * Passed through as-is to the `tool_result` block.\n */\nexport type AnthropicToolResponse = Anthropic.Messages.ToolResultBlockParam[\"content\"];\n\nexport interface AnthropicAdapter {\n /** Model invoker using the default model (only available when `model` was provided) */\n invoker: ModelInvoker<Anthropic.Messages.Message>;\n /** Create an invoker for a specific model name (for multi-model setups) */\n createModelInvoker(\n model: string,\n maxTokens?: number,\n ): ModelInvoker<Anthropic.Messages.Message>;\n /**\n * Create prefixed thread activities for registration on the worker.\n *\n * @param scope - Workflow name appended to the adapter prefix.\n * Use different scopes for the main agent vs subagents to avoid collisions.\n *\n * @example\n * ```typescript\n * adapter.createActivities(\"codingAgent\")\n * // → { anthropicCodingAgentInitializeThread, anthropicCodingAgentAppendHumanMessage, … }\n *\n * adapter.createActivities(\"researchAgent\")\n * // → { anthropicResearchAgentInitializeThread, … }\n * ```\n */\n createActivities<S extends string = \"\">(\n scope?: S,\n ): AnthropicThreadOps<S>;\n\n /**\n * Identity wrapper that types a tool handler for this adapter.\n * Constrains `toolResponse` to {@link AnthropicToolResponse}.\n */\n wrapHandler<TArgs, TResult, TContext extends RouterContext = RouterContext>(\n handler: (\n args: TArgs,\n context: TContext,\n ) => Promise<ToolHandlerResponse<TResult, AnthropicToolResponse>>,\n ): ActivityToolHandler<TArgs, TResult, TContext, AnthropicToolResponse>;\n}\n\n/**\n * Creates an Anthropic adapter that bundles thread operations and model\n * invocation using the `@anthropic-ai/sdk`.\n *\n * Use `createActivities(scope)` to register scoped thread operations as\n * Temporal activities on the worker. The `invoker` (or invokers created via\n * `createModelInvoker`) should be wrapped with `createRunAgentActivity`.\n *\n * @example\n * ```typescript\n * import { createAnthropicAdapter } from 'zeitlich/adapters/thread/anthropic';\n * import { createRunAgentActivity } from 'zeitlich';\n * import Anthropic from '@anthropic-ai/sdk';\n *\n * const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });\n * const adapter = createAnthropicAdapter({ redis, client, model: 'claude-sonnet-4-20250514' });\n *\n * export function createActivities(temporalClient: WorkflowClient) {\n * return {\n * ...adapter.createActivities(\"codingAgent\"),\n * runCodingAgent: createRunAgentActivity(temporalClient, adapter.invoker),\n * };\n * }\n * ```\n *\n * @example Multi-agent worker (main + subagent share the adapter)\n * ```typescript\n * export function createActivities(temporalClient: WorkflowClient) {\n * return {\n * ...adapter.createActivities(\"codingAgent\"),\n * ...adapter.createActivities(\"researchAgent\"),\n * runCodingAgent: createRunAgentActivity(temporalClient, adapter.invoker),\n * runResearchAgent: createRunAgentActivity(\n * temporalClient,\n * adapter.createModelInvoker('claude-sonnet-4-20250514'),\n * ),\n * };\n * }\n * ```\n */\nexport function createAnthropicAdapter(\n config: AnthropicAdapterConfig,\n): AnthropicAdapter {\n const { redis, client } = config;\n\n const threadOps: ThreadOps<AnthropicContent> = {\n async initializeThread(threadId: string, threadKey?: string): Promise<void> {\n const thread = createAnthropicThreadManager({ redis, threadId, key: threadKey });\n await thread.initialize();\n },\n\n async appendHumanMessage(\n threadId: string,\n id: string,\n content: AnthropicContent,\n threadKey?: string,\n ): Promise<void> {\n const thread = createAnthropicThreadManager({ redis, threadId, key: threadKey });\n await thread.appendUserMessage(id, content);\n },\n\n async appendSystemMessage(\n threadId: string,\n id: string,\n content: string,\n threadKey?: string,\n ): Promise<void> {\n const thread = createAnthropicThreadManager({ redis, threadId, key: threadKey });\n await thread.appendSystemMessage(id, content);\n },\n\n async appendToolResult(id: string, cfg: ToolResultConfig): Promise<void> {\n const { threadId, threadKey, toolCallId, toolName, content } = cfg;\n const thread = createAnthropicThreadManager({ redis, threadId, key: threadKey });\n await thread.appendToolResult(id, toolCallId, toolName, content);\n },\n\n async appendAgentMessage(\n threadId: string,\n id: string,\n message: Anthropic.Messages.Message,\n threadKey?: string,\n ): Promise<void> {\n const thread = createAnthropicThreadManager({ redis, threadId, key: threadKey });\n await thread.appendAssistantMessage(id, message.content);\n },\n\n async forkThread(\n sourceThreadId: string,\n targetThreadId: string,\n threadKey?: string,\n ): Promise<void> {\n const thread = createAnthropicThreadManager({\n redis,\n threadId: sourceThreadId,\n key: threadKey,\n });\n await thread.fork(targetThreadId);\n },\n };\n\n function createActivities<S extends string = \"\">(\n scope?: S,\n ): AnthropicThreadOps<S> {\n const prefix = scope\n ? `${ADAPTER_PREFIX}${scope.charAt(0).toUpperCase()}${scope.slice(1)}`\n : ADAPTER_PREFIX;\n const cap = (s: string): string =>\n s.charAt(0).toUpperCase() + s.slice(1);\n return Object.fromEntries(\n Object.entries(threadOps).map(([k, v]) => [`${prefix}${cap(k)}`, v]),\n ) as AnthropicThreadOps<S>;\n }\n\n const makeInvoker = (\n model: string,\n maxTokens?: number,\n ): ModelInvoker<Anthropic.Messages.Message> => {\n const invokerConfig: AnthropicModelInvokerConfig = {\n redis,\n client,\n model,\n ...(maxTokens !== undefined ? { maxTokens } : {}),\n ...(config.maxTokens !== undefined && maxTokens === undefined\n ? { maxTokens: config.maxTokens }\n : {}),\n hooks: config.hooks,\n };\n return createAnthropicModelInvoker(invokerConfig);\n };\n\n const invoker: ModelInvoker<Anthropic.Messages.Message> = config.model\n ? makeInvoker(config.model)\n : ((() => {\n throw new Error(\n \"No default model provided to createAnthropicAdapter. \" +\n \"Either pass `model` in the config or use `createModelInvoker(model)` instead.\",\n );\n }) as unknown as ModelInvoker<Anthropic.Messages.Message>);\n\n return {\n createActivities,\n invoker,\n createModelInvoker: makeInvoker,\n wrapHandler: (handler) => handler,\n };\n}\n"]}
1
+ {"version":3,"sources":["../../../../src/lib/thread/manager.ts","../../../../src/adapters/thread/anthropic/thread-manager.ts","../../../../src/lib/activity.ts","../../../../src/adapters/thread/anthropic/model-invoker.ts","../../../../src/adapters/thread/anthropic/activities.ts"],"names":["invokeAnthropicModel"],"mappings":"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","file":"index.js","sourcesContent":["import type { ThreadManagerConfig, BaseThreadManager } 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 `${key}:thread:${threadId}`;\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 Anthropic from \"@anthropic-ai/sdk\";\nimport type { JsonValue } from \"../../../lib/state/types\";\nimport { createThreadManager } from \"../../../lib/thread/manager\";\nimport type {\n ProviderThreadManager,\n ThreadManagerConfig,\n ThreadManagerHooks,\n} from \"../../../lib/thread/types\";\n\n/** SDK-native content type for Anthropic human messages */\nexport type AnthropicContent =\n | string\n | Anthropic.Messages.ContentBlockParam[];\n\n/** A MessageParam with a unique ID for idempotent Redis storage */\nexport interface StoredMessage {\n id: string;\n message: Anthropic.Messages.MessageParam;\n /** System messages are stored separately since Anthropic passes them via config */\n isSystem?: boolean;\n}\n\nexport type AnthropicThreadManagerHooks = ThreadManagerHooks<StoredMessage, Anthropic.Messages.MessageParam>;\n\nexport interface AnthropicThreadManagerConfig {\n redis: Redis;\n threadId: string;\n /** Thread key, defaults to 'messages' */\n key?: string;\n hooks?: AnthropicThreadManagerHooks;\n}\n\n/** Prepared payload ready to send to the Anthropic API */\nexport interface AnthropicInvocationPayload {\n messages: Anthropic.Messages.MessageParam[];\n system?: string;\n}\n\n/** Thread manager with Anthropic MessageParam convenience helpers */\nexport interface AnthropicThreadManager\n extends ProviderThreadManager<StoredMessage, AnthropicContent> {\n appendAssistantMessage(\n id: string,\n content: Anthropic.Messages.ContentBlock[],\n ): Promise<void>;\n prepareForInvocation(): Promise<AnthropicInvocationPayload>;\n}\n\nfunction storedMessageId(msg: StoredMessage): string {\n return msg.id;\n}\n\n/** Normalise content into an array of ContentBlockParam */\nfunction toContentBlocks(\n content: AnthropicContent,\n): Anthropic.Messages.ContentBlockParam[] {\n if (typeof content === \"string\") {\n return [{ type: \"text\", text: content }];\n }\n return content;\n}\n\n/**\n * Merge consecutive messages with the same role.\n * The Anthropic API requires alternating user/assistant turns; without\n * merging, multiple sequential tool-result messages would violate this.\n */\nfunction mergeConsecutiveMessages(\n messages: Anthropic.Messages.MessageParam[],\n): Anthropic.Messages.MessageParam[] {\n const merged: Anthropic.Messages.MessageParam[] = [];\n for (const msg of messages) {\n const last = merged[merged.length - 1];\n if (last && last.role === msg.role) {\n const lastContent = Array.isArray(last.content)\n ? last.content\n : [{ type: \"text\" as const, text: last.content }];\n const msgContent = Array.isArray(msg.content)\n ? msg.content\n : [{ type: \"text\" as const, text: msg.content }];\n last.content = [...lastContent, ...msgContent];\n } else {\n merged.push({\n ...msg,\n content: Array.isArray(msg.content)\n ? [...msg.content]\n : msg.content,\n });\n }\n }\n return merged;\n}\n\n/**\n * Creates an Anthropic-specific thread manager that stores StoredMessage\n * instances in Redis and provides convenience helpers for creating and\n * appending typed messages.\n */\nexport function createAnthropicThreadManager(\n config: AnthropicThreadManagerConfig,\n): AnthropicThreadManager {\n const baseConfig: ThreadManagerConfig<StoredMessage> = {\n redis: config.redis,\n threadId: config.threadId,\n key: config.key,\n idOf: storedMessageId,\n };\n\n const base = createThreadManager(baseConfig);\n\n const helpers: Omit<AnthropicThreadManager, keyof typeof base> = {\n async appendUserMessage(\n id: string,\n content: AnthropicContent,\n ): Promise<void> {\n await base.append([{\n id,\n message: { role: \"user\", content: toContentBlocks(content) },\n }]);\n },\n\n async appendSystemMessage(id: string, content: string): Promise<void> {\n await base.initialize();\n await base.append([{\n id,\n message: { role: \"user\", content },\n isSystem: true,\n }]);\n },\n\n async appendAssistantMessage(\n id: string,\n content: Anthropic.Messages.ContentBlock[],\n ): Promise<void> {\n await base.append([{\n id,\n message: {\n role: \"assistant\",\n content: content as unknown as Anthropic.Messages.ContentBlockParam[],\n },\n }]);\n },\n\n async appendToolResult(\n id: string,\n toolCallId: string,\n _toolName: string,\n content: JsonValue,\n ): Promise<void> {\n const toolContent =\n typeof content === \"string\"\n ? content\n : Array.isArray(content)\n ? (content as unknown as Anthropic.Messages.ToolResultBlockParam[\"content\"])\n : JSON.stringify(content);\n await base.append([{\n id,\n message: {\n role: \"user\",\n content: [{\n type: \"tool_result\" as const,\n tool_use_id: toolCallId,\n content: toolContent,\n }],\n },\n }]);\n },\n\n async prepareForInvocation(): Promise<AnthropicInvocationPayload> {\n const stored = await base.load();\n const { onPrepareMessage, onPreparedMessage } = config.hooks ?? {};\n const mapped = onPrepareMessage\n ? stored.map((msg, i) => onPrepareMessage(msg, i, stored))\n : stored;\n\n let system: string | undefined;\n const conversationMessages: Anthropic.Messages.MessageParam[] = [];\n\n for (const item of mapped) {\n if (item.isSystem) {\n system =\n typeof item.message.content === \"string\"\n ? item.message.content\n : undefined;\n } else {\n conversationMessages.push(item.message);\n }\n }\n\n const messages = mergeConsecutiveMessages(conversationMessages);\n return {\n messages: onPreparedMessage\n ? messages.map((msg, i) => onPreparedMessage(msg, i, messages))\n : messages,\n ...(system ? { system } : {}),\n };\n },\n };\n\n return Object.assign(base, helpers);\n}\n","import { Context } from \"@temporalio/activity\";\nimport type { WorkflowClient } from \"@temporalio/client\";\nimport type { BaseAgentState, RunAgentConfig } from \"./types\";\nimport type { JsonValue } from \"./state/types\";\nimport type {\n ActivityToolHandler,\n RouterContext,\n ToolHandlerResponse,\n} from \"./tool-router/types\";\n\n/**\n * Safely retrieve Temporal activity heartbeat and cancellation signal.\n * Returns empty object when called outside a Temporal activity (e.g. tests).\n */\nexport function getActivityContext(): {\n heartbeat?: () => void;\n signal?: AbortSignal;\n} {\n try {\n const ctx = Context.current();\n return { heartbeat: () => ctx.heartbeat(), signal: ctx.cancellationSignal };\n } catch {\n return {};\n }\n}\n\n/**\n * Query the parent workflow's state from within an activity.\n * Resolves the workflow handle from the current activity context.\n */\nexport async function queryParentWorkflowState<T>(\n client: WorkflowClient\n): Promise<T> {\n const { workflowExecution } = Context.current().info;\n const handle = client.getHandle(\n workflowExecution.workflowId,\n workflowExecution.runId\n );\n return handle.query<T>(\"getAgentState\");\n}\n\n/**\n * Wraps a handler into a scope-prefixed `RunAgentActivity` by auto-fetching\n * the parent workflow's agent state before each invocation.\n *\n * Returns a `Record` with a single key `run<Scope>` so it can be spread\n * into the activities object alongside adapter activities.\n *\n * @param scope - Workflow scope used to derive the activity name.\n * `\"myAgentWorkflow\"` produces `{ runMyAgentWorkflow: fn }`.\n *\n * @example\n * ```typescript\n * import { createRunAgentActivity } from 'zeitlich';\n *\n * return {\n * ...adapter.createActivities(\"myAgentWorkflow\"),\n * ...createRunAgentActivity(client, adapter.invoker, \"myAgentWorkflow\"),\n * };\n * ```\n */\nexport function createRunAgentActivity<R, S extends BaseAgentState = BaseAgentState>(\n client: WorkflowClient,\n handler: (config: RunAgentConfig & { state: S }) => Promise<R>,\n scope: string,\n): Record<string, (config: RunAgentConfig) => Promise<R>> {\n const name = `run${scope.charAt(0).toUpperCase()}${scope.slice(1)}`;\n return {\n [name]: async (config: RunAgentConfig) => {\n const state = await queryParentWorkflowState<S>(client);\n return handler({ ...config, state });\n },\n };\n}\n\n/**\n * Context injected into tool handlers created via {@link withParentWorkflowState}.\n */\nexport interface AgentStateContext<S extends BaseAgentState = BaseAgentState> extends RouterContext {\n state: S;\n}\n\n/**\n * Wraps a tool handler into an `ActivityToolHandler` by auto-fetching the\n * parent workflow's agent state before each invocation.\n *\n * @typeParam S - Custom agent state type (defaults to `BaseAgentState`)\n *\n * @example\n * ```typescript\n * import { withParentWorkflowState, type AgentStateContext } from 'zeitlich';\n *\n * // With custom state:\n * interface MyState extends BaseAgentState { customField: string }\n * const myHandler = withParentWorkflowState<MyArgs, MyResult, MyState>(\n * client,\n * async (args, ctx) => {\n * console.log(ctx.state.customField);\n * return { toolResponse: 'done', data: null };\n * },\n * );\n * ```\n */\nexport function withParentWorkflowState<TArgs, TResult, S extends BaseAgentState = BaseAgentState, TToolResponse = JsonValue>(\n client: WorkflowClient,\n handler: (\n args: TArgs,\n context: AgentStateContext<S>,\n ) => Promise<ToolHandlerResponse<TResult, TToolResponse>>,\n): ActivityToolHandler<TArgs, TResult, RouterContext, TToolResponse> {\n return async (args, context) => {\n const state = await queryParentWorkflowState<S>(client);\n return handler(args, { ...context, state });\n };\n}\n","import type Redis from \"ioredis\";\nimport type Anthropic from \"@anthropic-ai/sdk\";\nimport type { SerializableToolDefinition } from \"../../../lib/types\";\nimport type { AgentResponse, ModelInvokerConfig } from \"../../../lib/model\";\nimport { createAnthropicThreadManager, type AnthropicThreadManagerHooks } from \"./thread-manager\";\nimport { getActivityContext } from \"../../../lib/activity\";\n\nexport interface AnthropicModelInvokerConfig {\n redis: Redis;\n client: Anthropic;\n model: string;\n /** Maximum tokens to generate. Defaults to 16384. */\n maxTokens?: number;\n hooks?: AnthropicThreadManagerHooks;\n}\n\nfunction toAnthropicTools(\n tools: SerializableToolDefinition[],\n): Anthropic.Messages.Tool[] {\n return tools.map((t) => ({\n name: t.name,\n description: t.description,\n input_schema: t.schema as Anthropic.Messages.Tool.InputSchema,\n }));\n}\n\n/**\n * Creates an Anthropic model invoker that satisfies the generic\n * `ModelInvoker<Anthropic.Messages.Message>` contract.\n *\n * Internally streams the response and emits Temporal heartbeats on each\n * event so that long-running LLM calls remain visible to the scheduler.\n * The caller is responsible for appending the response to the thread.\n *\n * @example\n * ```typescript\n * import { createAnthropicModelInvoker } from 'zeitlich/adapters/thread/anthropic';\n * import { createRunAgentActivity } from 'zeitlich';\n * import Anthropic from '@anthropic-ai/sdk';\n *\n * const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });\n * const invoker = createAnthropicModelInvoker({\n * redis,\n * client,\n * model: 'claude-sonnet-4-20250514',\n * });\n *\n * return { ...createRunAgentActivity(client, invoker, \"myAgent\") };\n * ```\n */\nexport function createAnthropicModelInvoker({\n redis,\n client,\n model,\n maxTokens = 16384,\n hooks,\n}: AnthropicModelInvokerConfig) {\n return async function invokeAnthropicModel(\n config: ModelInvokerConfig,\n ): Promise<AgentResponse<Anthropic.Messages.Message>> {\n const { threadId, threadKey, state } = config;\n const { heartbeat, signal } = getActivityContext();\n\n const thread = createAnthropicThreadManager({ redis, threadId, key: threadKey, hooks });\n const { messages, system } = await thread.prepareForInvocation();\n\n const anthropicTools = toAnthropicTools(state.tools);\n const tools = anthropicTools.length > 0 ? anthropicTools : undefined;\n\n const params: Anthropic.MessageCreateParams = {\n model,\n max_tokens: maxTokens,\n messages,\n ...(system ? { system } : {}),\n ...(tools ? { tools } : {}),\n };\n\n const stream = client.messages.stream(params, { signal });\n\n for await (const _event of stream) {\n heartbeat?.();\n }\n\n const response: Anthropic.Messages.Message = await stream.finalMessage();\n\n const toolCalls = response.content.filter(\n (block): block is Anthropic.Messages.ToolUseBlock =>\n block.type === \"tool_use\",\n );\n\n return {\n message: response,\n rawToolCalls: toolCalls.map((tc) => ({\n id: tc.id,\n name: tc.name,\n args: (tc.input as Record<string, unknown>) ?? {},\n })),\n usage: {\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n cachedWriteTokens: response.usage.cache_creation_input_tokens ?? undefined,\n cachedReadTokens: response.usage.cache_read_input_tokens ?? undefined,\n },\n };\n };\n}\n\n/**\n * Standalone function for one-shot Anthropic model invocation.\n * Convenience wrapper around createAnthropicModelInvoker for cases\n * where you don't need to reuse the invoker.\n */\nexport async function invokeAnthropicModel({\n redis,\n client,\n model,\n maxTokens,\n hooks,\n config,\n}: {\n redis: Redis;\n client: Anthropic;\n model: string;\n maxTokens?: number;\n hooks?: AnthropicThreadManagerHooks;\n config: ModelInvokerConfig;\n}): Promise<AgentResponse<Anthropic.Messages.Message>> {\n const invoker = createAnthropicModelInvoker({\n redis,\n client,\n model,\n maxTokens,\n hooks,\n });\n return invoker(config);\n}\n","import type Redis from \"ioredis\";\nimport type Anthropic from \"@anthropic-ai/sdk\";\nimport type { ToolResultConfig } from \"../../../lib/types\";\nimport type {\n ActivityToolHandler,\n RouterContext,\n ToolHandlerResponse,\n} from \"../../../lib/tool-router/types\";\nimport type {\n ThreadOps,\n PrefixedThreadOps,\n ScopedPrefix,\n} from \"../../../lib/session/types\";\nimport type { ModelInvoker } from \"../../../lib/model\";\nimport {\n createAnthropicThreadManager,\n type AnthropicContent,\n type AnthropicThreadManagerHooks,\n} from \"./thread-manager\";\nimport {\n createAnthropicModelInvoker,\n type AnthropicModelInvokerConfig,\n} from \"./model-invoker\";\n\nconst ADAPTER_PREFIX = \"anthropic\" as const;\n\nexport type AnthropicThreadOps<TScope extends string = \"\"> =\n PrefixedThreadOps<ScopedPrefix<TScope, typeof ADAPTER_PREFIX>, AnthropicContent>;\n\nexport interface AnthropicAdapterConfig {\n redis: Redis;\n client: Anthropic;\n /** Default model name (e.g. 'claude-sonnet-4-20250514'). If omitted, use `createModelInvoker()` */\n model?: string;\n /** Maximum tokens to generate. Defaults to 16384. */\n maxTokens?: number;\n hooks?: AnthropicThreadManagerHooks;\n}\n\n/**\n * Tool response type accepted by the Anthropic adapter.\n *\n * Handlers can return:\n * - **`string`** — plain text content for the tool result.\n * - **`Anthropic.Messages.ToolResultBlockParam[\"content\"]`** — array of content blocks\n * (e.g. `{ type: \"text\", text: \"...\" }`, `{ type: \"image\", source: { ... } }`).\n * Passed through as-is to the `tool_result` block.\n */\nexport type AnthropicToolResponse = Anthropic.Messages.ToolResultBlockParam[\"content\"];\n\nexport interface AnthropicAdapter {\n /** Model invoker using the default model (only available when `model` was provided) */\n invoker: ModelInvoker<Anthropic.Messages.Message>;\n /** Create an invoker for a specific model name (for multi-model setups) */\n createModelInvoker(\n model: string,\n maxTokens?: number,\n ): ModelInvoker<Anthropic.Messages.Message>;\n /**\n * Create prefixed thread activities for registration on the worker.\n *\n * @param scope - Workflow name appended to the adapter prefix.\n * Use different scopes for the main agent vs subagents to avoid collisions.\n *\n * @example\n * ```typescript\n * adapter.createActivities(\"codingAgent\")\n * // → { anthropicCodingAgentInitializeThread, anthropicCodingAgentAppendHumanMessage, … }\n *\n * adapter.createActivities(\"researchAgent\")\n * // → { anthropicResearchAgentInitializeThread, … }\n * ```\n */\n createActivities<S extends string = \"\">(\n scope?: S,\n ): AnthropicThreadOps<S>;\n\n /**\n * Identity wrapper that types a tool handler for this adapter.\n * Constrains `toolResponse` to {@link AnthropicToolResponse}.\n */\n wrapHandler<TArgs, TResult, TContext extends RouterContext = RouterContext>(\n handler: (\n args: TArgs,\n context: TContext,\n ) => Promise<ToolHandlerResponse<TResult, AnthropicToolResponse>>,\n ): ActivityToolHandler<TArgs, TResult, TContext, AnthropicToolResponse>;\n}\n\n/**\n * Creates an Anthropic adapter that bundles thread operations and model\n * invocation using the `@anthropic-ai/sdk`.\n *\n * Use `createActivities(scope)` to register scoped thread operations as\n * Temporal activities on the worker. The `invoker` (or invokers created via\n * `createModelInvoker`) should be wrapped with `createRunAgentActivity`.\n *\n * @example\n * ```typescript\n * import { createAnthropicAdapter } from 'zeitlich/adapters/thread/anthropic';\n * import { createRunAgentActivity } from 'zeitlich';\n * import Anthropic from '@anthropic-ai/sdk';\n *\n * const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });\n * const adapter = createAnthropicAdapter({ redis, client, model: 'claude-sonnet-4-20250514' });\n *\n * export function createActivities(temporalClient: WorkflowClient) {\n * return {\n * ...adapter.createActivities(\"codingAgent\"),\n * ...createRunAgentActivity(temporalClient, adapter.invoker, \"codingAgent\"),\n * };\n * }\n * ```\n *\n * @example Multi-agent worker (main + subagent share the adapter)\n * ```typescript\n * export function createActivities(temporalClient: WorkflowClient) {\n * return {\n * ...adapter.createActivities(\"codingAgent\"),\n * ...adapter.createActivities(\"researchAgent\"),\n * ...createRunAgentActivity(temporalClient, adapter.invoker, \"codingAgent\"),\n * ...createRunAgentActivity(\n * temporalClient,\n * adapter.createModelInvoker('claude-sonnet-4-20250514'),\n * \"researchAgent\",\n * ),\n * };\n * }\n * ```\n */\nexport function createAnthropicAdapter(\n config: AnthropicAdapterConfig,\n): AnthropicAdapter {\n const { redis, client } = config;\n\n const threadOps: ThreadOps<AnthropicContent> = {\n async initializeThread(threadId: string, threadKey?: string): Promise<void> {\n const thread = createAnthropicThreadManager({ redis, threadId, key: threadKey });\n await thread.initialize();\n },\n\n async appendHumanMessage(\n threadId: string,\n id: string,\n content: AnthropicContent,\n threadKey?: string,\n ): Promise<void> {\n const thread = createAnthropicThreadManager({ redis, threadId, key: threadKey });\n await thread.appendUserMessage(id, content);\n },\n\n async appendSystemMessage(\n threadId: string,\n id: string,\n content: string,\n threadKey?: string,\n ): Promise<void> {\n const thread = createAnthropicThreadManager({ redis, threadId, key: threadKey });\n await thread.appendSystemMessage(id, content);\n },\n\n async appendToolResult(id: string, cfg: ToolResultConfig): Promise<void> {\n const { threadId, threadKey, toolCallId, toolName, content } = cfg;\n const thread = createAnthropicThreadManager({ redis, threadId, key: threadKey });\n await thread.appendToolResult(id, toolCallId, toolName, content);\n },\n\n async appendAgentMessage(\n threadId: string,\n id: string,\n message: Anthropic.Messages.Message,\n threadKey?: string,\n ): Promise<void> {\n const thread = createAnthropicThreadManager({ redis, threadId, key: threadKey });\n await thread.appendAssistantMessage(id, message.content);\n },\n\n async forkThread(\n sourceThreadId: string,\n targetThreadId: string,\n threadKey?: string,\n ): Promise<void> {\n const thread = createAnthropicThreadManager({\n redis,\n threadId: sourceThreadId,\n key: threadKey,\n });\n await thread.fork(targetThreadId);\n },\n };\n\n function createActivities<S extends string = \"\">(\n scope?: S,\n ): AnthropicThreadOps<S> {\n const prefix = scope\n ? `${ADAPTER_PREFIX}${scope.charAt(0).toUpperCase()}${scope.slice(1)}`\n : ADAPTER_PREFIX;\n const cap = (s: string): string =>\n s.charAt(0).toUpperCase() + s.slice(1);\n return Object.fromEntries(\n Object.entries(threadOps).map(([k, v]) => [`${prefix}${cap(k)}`, v]),\n ) as AnthropicThreadOps<S>;\n }\n\n const makeInvoker = (\n model: string,\n maxTokens?: number,\n ): ModelInvoker<Anthropic.Messages.Message> => {\n const invokerConfig: AnthropicModelInvokerConfig = {\n redis,\n client,\n model,\n ...(maxTokens !== undefined ? { maxTokens } : {}),\n ...(config.maxTokens !== undefined && maxTokens === undefined\n ? { maxTokens: config.maxTokens }\n : {}),\n hooks: config.hooks,\n };\n return createAnthropicModelInvoker(invokerConfig);\n };\n\n const invoker: ModelInvoker<Anthropic.Messages.Message> = config.model\n ? makeInvoker(config.model)\n : ((() => {\n throw new Error(\n \"No default model provided to createAnthropicAdapter. \" +\n \"Either pass `model` in the config or use `createModelInvoker(model)` instead.\",\n );\n }) as unknown as ModelInvoker<Anthropic.Messages.Message>);\n\n return {\n createActivities,\n invoker,\n createModelInvoker: makeInvoker,\n wrapHandler: (handler) => handler,\n };\n}\n"]}
@@ -1,14 +1,14 @@
1
1
  import { ActivityInterfaceFor } from '@temporalio/workflow';
2
- import { T as ThreadOps } from '../../../types-Bpq5fDI5.cjs';
3
- import { A as AnthropicContent } from '../../../thread-manager-CUubPYPH.cjs';
4
- import { c as createThreadOpsProxy } from '../../../proxy-CTCYWjkr.cjs';
2
+ import { T as ThreadOps } from '../../../types-DlLajQcu.cjs';
3
+ import { A as AnthropicContent } from '../../../thread-manager-Cf_34H8w.cjs';
4
+ import { c as createThreadOpsProxy } from '../../../proxy-BesT2ioL.cjs';
5
5
  import '@temporalio/common';
6
6
  import '@temporalio/common/lib/interfaces';
7
7
  import 'zod';
8
- import '../../../types-AujBIMMn.cjs';
8
+ import '../../../types-DxCpFNv_.cjs';
9
9
  import 'ioredis';
10
10
  import '@anthropic-ai/sdk';
11
- import '../../../types-NJDyMyUx.cjs';
11
+ import '../../../types-DPAZ3KCs.cjs';
12
12
 
13
13
  /**
14
14
  * Workflow-safe proxy for Anthropic thread operations.
@@ -1,14 +1,14 @@
1
1
  import { ActivityInterfaceFor } from '@temporalio/workflow';
2
- import { T as ThreadOps } from '../../../types-CheCTLeV.js';
3
- import { A as AnthropicContent } from '../../../thread-manager-YJLoc1vH.js';
4
- import { c as createThreadOpsProxy } from '../../../proxy-Br4unLTC.js';
2
+ import { T as ThreadOps } from '../../../types-BGLW5Zyj.js';
3
+ import { A as AnthropicContent } from '../../../thread-manager-ClKAQx78.js';
4
+ import { c as createThreadOpsProxy } from '../../../proxy-Bz6wXYW-.js';
5
5
  import '@temporalio/common';
6
6
  import '@temporalio/common/lib/interfaces';
7
7
  import 'zod';
8
- import '../../../types-AujBIMMn.js';
8
+ import '../../../types-DxCpFNv_.js';
9
9
  import 'ioredis';
10
10
  import '@anthropic-ai/sdk';
11
- import '../../../types-BxiT8w9d.js';
11
+ import '../../../types-BVUmLYpj.js';
12
12
 
13
13
  /**
14
14
  * Workflow-safe proxy for Anthropic thread operations.
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ var activity = require('@temporalio/activity');
4
+
3
5
  // src/lib/thread/manager.ts
4
6
  var THREAD_TTL_SECONDS = 60 * 60 * 24 * 90;
5
7
  var APPEND_IDEMPOTENT_SCRIPT = `
@@ -174,6 +176,14 @@ function createGoogleGenAIThreadManager(config) {
174
176
  };
175
177
  return Object.assign(base, helpers);
176
178
  }
179
+ function getActivityContext() {
180
+ try {
181
+ const ctx = activity.Context.current();
182
+ return { heartbeat: () => ctx.heartbeat(), signal: ctx.cancellationSignal };
183
+ } catch {
184
+ return {};
185
+ }
186
+ }
177
187
 
178
188
  // src/adapters/thread/google-genai/model-invoker.ts
179
189
  function toFunctionDeclarations(tools) {
@@ -191,21 +201,32 @@ function createGoogleGenAIModelInvoker({
191
201
  }) {
192
202
  return async function invokeGoogleGenAIModel2(config) {
193
203
  const { threadId, threadKey, state } = config;
204
+ const { heartbeat, signal } = getActivityContext();
194
205
  const thread = createGoogleGenAIThreadManager({ redis, threadId, key: threadKey, hooks });
195
206
  const { contents, systemInstruction } = await thread.prepareForInvocation();
196
207
  const functionDeclarations = toFunctionDeclarations(state.tools);
197
208
  const tools = functionDeclarations.length > 0 ? [{ functionDeclarations }] : void 0;
198
- const response = await client.models.generateContent({
209
+ const stream = await client.models.generateContentStream({
199
210
  model,
200
211
  contents,
201
212
  config: {
202
213
  ...systemInstruction ? { systemInstruction } : {},
203
- ...tools ? { tools } : {}
214
+ ...tools ? { tools } : {},
215
+ abortSignal: signal
204
216
  }
205
217
  });
206
- const responseParts = response.candidates?.[0]?.content?.parts ?? [];
207
- const modelContent = { role: "model", parts: responseParts };
208
- const functionCalls = response.functionCalls ?? [];
218
+ const allParts = [];
219
+ let lastChunk;
220
+ for await (const chunk of stream) {
221
+ lastChunk = chunk;
222
+ allParts.push(...chunk.candidates?.[0]?.content?.parts ?? []);
223
+ heartbeat?.();
224
+ }
225
+ if (!lastChunk) {
226
+ throw new Error("Google GenAI stream ended without producing any chunks");
227
+ }
228
+ const modelContent = { role: "model", parts: allParts };
229
+ const functionCalls = lastChunk.functionCalls ?? [];
209
230
  return {
210
231
  message: modelContent,
211
232
  rawToolCalls: functionCalls.map((fc) => ({
@@ -214,9 +235,9 @@ function createGoogleGenAIModelInvoker({
214
235
  args: fc.args ?? {}
215
236
  })),
216
237
  usage: {
217
- inputTokens: response.usageMetadata?.promptTokenCount,
218
- outputTokens: response.usageMetadata?.candidatesTokenCount,
219
- cachedReadTokens: response.usageMetadata?.cachedContentTokenCount
238
+ inputTokens: lastChunk.usageMetadata?.promptTokenCount,
239
+ outputTokens: lastChunk.usageMetadata?.candidatesTokenCount,
240
+ cachedReadTokens: lastChunk.usageMetadata?.cachedContentTokenCount
220
241
  }
221
242
  };
222
243
  };
@@ -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":";;;AAEA,IAAM,kBAAA,GAAqB,EAAA,GAAK,EAAA,GAAK,EAAA,GAAK,EAAA;AAW1C,IAAM,wBAAA,GAA2B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,CAAA;AAYjC,SAAS,YAAA,CAAa,UAAkB,GAAA,EAAqB;AAC3D,EAAA,OAAO,CAAA,EAAG,GAAG,CAAA,QAAA,EAAW,QAAQ,CAAA,CAAA;AAClC;AAMO,SAAS,oBACd,MAAA,EACsB;AACtB,EAAA,MAAM;AAAA,IACJ,KAAA;AAAA,IACA,QAAA;AAAA,IACA,GAAA,GAAM,UAAA;AAAA,IACN,SAAA,GAAY,CAAC,CAAA,KAAiB,IAAA,CAAK,UAAU,CAAC,CAAA;AAAA,IAC9C,WAAA,GAAc,CAAC,GAAA,KAAmB,IAAA,CAAK,MAAM,GAAG,CAAA;AAAA,IAChD;AAAA,GACF,GAAI,MAAA;AACJ,EAAA,MAAM,QAAA,GAAW,YAAA,CAAa,QAAA,EAAU,GAAG,CAAA;AAC3C,EAAA,MAAM,OAAA,GAAU,YAAA,CAAa,QAAA,EAAU,CAAA,EAAG,GAAG,CAAA,KAAA,CAAO,CAAA;AAEpD,EAAA,eAAe,kBAAA,GAAoC;AACjD,IAAA,MAAM,MAAA,GAAS,MAAM,KAAA,CAAM,MAAA,CAAO,OAAO,CAAA;AACzC,IAAA,IAAI,CAAC,MAAA,EAAQ;AACX,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,QAAA,EAAW,QAAQ,CAAA,QAAA,EAAW,GAAG,CAAA,gBAAA,CAAkB,CAAA;AAAA,IACrE;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,MAAM,UAAA,GAA4B;AAChC,MAAA,MAAM,KAAA,CAAM,IAAI,QAAQ,CAAA;AACxB,MAAA,MAAM,KAAA,CAAM,GAAA,CAAI,OAAA,EAAS,GAAA,EAAK,MAAM,kBAAkB,CAAA;AAAA,IACxD,CAAA;AAAA,IAEA,MAAM,IAAA,GAAqB;AACzB,MAAA,MAAM,kBAAA,EAAmB;AACzB,MAAA,MAAM,OAAO,MAAM,KAAA,CAAM,MAAA,CAAO,QAAA,EAAU,GAAG,EAAE,CAAA;AAC/C,MAAA,OAAO,IAAA,CAAK,IAAI,WAAW,CAAA;AAAA,IAC7B,CAAA;AAAA,IAEA,MAAM,OAAO,QAAA,EAA8B;AACzC,MAAA,IAAI,QAAA,CAAS,WAAW,CAAA,EAAG;AAC3B,MAAA,MAAM,kBAAA,EAAmB;AAEzB,MAAA,IAAI,IAAA,EAAM;AACR,QAAA,MAAM,UAAU,QAAA,CAAS,GAAA,CAAI,IAAI,CAAA,CAAE,KAAK,GAAG,CAAA;AAC3C,QAAA,MAAM,QAAA,GAAW,YAAA,CAAa,QAAA,EAAU,CAAA,MAAA,EAAS,OAAO,CAAA,CAAE,CAAA;AAC1D,QAAA,MAAM,KAAA,CAAM,IAAA;AAAA,UACV,wBAAA;AAAA,UACA,CAAA;AAAA,UACA,QAAA;AAAA,UACA,QAAA;AAAA,UACA,OAAO,kBAAkB,CAAA;AAAA,UACzB,GAAG,QAAA,CAAS,GAAA,CAAI,SAAS;AAAA,SAC3B;AAAA,MACF,CAAA,MAAO;AACL,QAAA,MAAM,MAAM,KAAA,CAAM,QAAA,EAAU,GAAG,QAAA,CAAS,GAAA,CAAI,SAAS,CAAC,CAAA;AACtD,QAAA,MAAM,KAAA,CAAM,MAAA,CAAO,QAAA,EAAU,kBAAkB,CAAA;AAAA,MACjD;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,KAAK,WAAA,EAAoD;AAC7D,MAAA,MAAM,kBAAA,EAAmB;AACzB,MAAA,MAAM,OAAO,MAAM,KAAA,CAAM,MAAA,CAAO,QAAA,EAAU,GAAG,EAAE,CAAA;AAC/C,MAAA,MAAM,SAAS,mBAAA,CAAoB;AAAA,QACjC,GAAG,MAAA;AAAA,QACH,QAAA,EAAU;AAAA,OACX,CAAA;AACD,MAAA,MAAM,OAAO,UAAA,EAAW;AACxB,MAAA,IAAI,IAAA,CAAK,SAAS,CAAA,EAAG;AACnB,QAAA,MAAM,MAAA,GAAS,YAAA,CAAa,WAAA,EAAa,GAAG,CAAA;AAC5C,QAAA,MAAM,KAAA,CAAM,KAAA,CAAM,MAAA,EAAQ,GAAG,IAAI,CAAA;AACjC,QAAA,MAAM,KAAA,CAAM,MAAA,CAAO,MAAA,EAAQ,kBAAkB,CAAA;AAAA,MAC/C;AACA,MAAA,OAAO,MAAA;AAAA,IACT,CAAA;AAAA,IAEA,MAAM,MAAA,GAAwB;AAC5B,MAAA,MAAM,KAAA,CAAM,GAAA,CAAI,QAAA,EAAU,OAAO,CAAA;AAAA,IACnC;AAAA,GACF;AACF;;;ACjEA,SAAS,gBAAgB,GAAA,EAA4B;AACnD,EAAA,OAAO,GAAA,CAAI,EAAA;AACb;AAGA,SAAS,QAAQ,OAAA,EAAqC;AACpD,EAAA,IAAI,OAAO,YAAY,QAAA,EAAU;AAC/B,IAAA,OAAO,CAAC,EAAE,IAAA,EAAM,OAAA,EAAS,CAAA;AAAA,EAC3B;AACA,EAAA,OAAO,OAAA;AACT;AAGA,SAAS,mBAAmB,OAAA,EAAoE;AAC9F,EAAA,IAAI,OAAO,YAAY,QAAA,EAAU;AAC/B,IAAA,OAAO,OAAA;AAAA,EACT;AACA,EAAA,OAAO,EAAE,QAAQ,OAAA,EAAQ;AAC3B;AAOA,SAAS,yBAAyB,QAAA,EAAgC;AAChE,EAAA,MAAM,SAAoB,EAAC;AAC3B,EAAA,KAAA,MAAW,WAAW,QAAA,EAAU;AAC9B,IAAA,MAAM,IAAA,GAAO,MAAA,CAAO,MAAA,CAAO,MAAA,GAAS,CAAC,CAAA;AACrC,IAAA,IAAI,IAAA,IAAQ,IAAA,CAAK,IAAA,KAAS,OAAA,CAAQ,IAAA,EAAM;AACtC,MAAA,IAAA,CAAK,KAAA,GAAQ,CAAC,GAAI,IAAA,CAAK,KAAA,IAAS,EAAC,EAAI,GAAI,OAAA,CAAQ,KAAA,IAAS,EAAG,CAAA;AAAA,IAC/D,CAAA,MAAO;AACL,MAAA,MAAA,CAAO,IAAA,CAAK,EAAE,GAAG,OAAA,EAAS,KAAA,EAAO,CAAC,GAAI,OAAA,CAAQ,KAAA,IAAS,EAAG,CAAA,EAAG,CAAA;AAAA,IAC/D;AAAA,EACF;AACA,EAAA,OAAO,MAAA;AACT;AAOO,SAAS,+BACd,MAAA,EAC0B;AAC1B,EAAA,MAAM,UAAA,GAAiD;AAAA,IACrD,OAAO,MAAA,CAAO,KAAA;AAAA,IACd,UAAU,MAAA,CAAO,QAAA;AAAA,IACjB,KAAK,MAAA,CAAO,GAAA;AAAA,IACZ,IAAA,EAAM;AAAA,GACR;AAEA,EAAA,MAAM,IAAA,GAAO,oBAAoB,UAAU,CAAA;AAE3C,EAAA,MAAM,OAAA,GAA6D;AAAA,IACjE,MAAM,iBAAA,CACJ,EAAA,EACA,OAAA,EACe;AACf,MAAA,MAAM,IAAA,CAAK,OAAO,CAAC;AAAA,QACjB,EAAA;AAAA,QACA,SAAS,EAAE,IAAA,EAAM,QAAQ,KAAA,EAAO,OAAA,CAAQ,OAAO,CAAA;AAAE,OAClD,CAAC,CAAA;AAAA,IACJ,CAAA;AAAA,IAEA,MAAM,mBAAA,CAAoB,EAAA,EAAY,OAAA,EAAgC;AACpE,MAAA,MAAM,KAAK,UAAA,EAAW;AACtB,MAAA,MAAM,IAAA,CAAK,OAAO,CAAC;AAAA,QACjB,EAAA;AAAA,QACA,OAAA,EAAS,EAAE,IAAA,EAAM,QAAA,EAAU,KAAA,EAAO,CAAC,EAAE,IAAA,EAAM,OAAA,EAAS,CAAA;AAAE,OACvD,CAAC,CAAA;AAAA,IACJ,CAAA;AAAA,IAEA,MAAM,kBAAA,CAAmB,EAAA,EAAY,KAAA,EAA8B;AACjE,MAAA,MAAM,IAAA,CAAK,OAAO,CAAC;AAAA,QACjB,EAAA;AAAA,QACA,OAAA,EAAS,EAAE,IAAA,EAAM,OAAA,EAAS,KAAA;AAAM,OACjC,CAAC,CAAA;AAAA,IACJ,CAAA;AAAA,IAEA,MAAM,gBAAA,CACJ,EAAA,EACA,UAAA,EACA,UACA,OAAA,EACe;AACf,MAAA,MAAM,QAAgB,KAAA,CAAM,OAAA,CAAQ,OAAO,CAAA,GACvC,UACA,CAAC;AAAA,QACC,gBAAA,EAAkB;AAAA,UAChB,EAAA,EAAI,UAAA;AAAA,UACJ,IAAA,EAAM,QAAA;AAAA,UACN,QAAA,EAAU,mBAAmB,OAAO;AAAA;AACtC,OACD,CAAA;AAEL,MAAA,MAAM,IAAA,CAAK,OAAO,CAAC;AAAA,QACjB,EAAA;AAAA,QACA,OAAA,EAAS,EAAE,IAAA,EAAM,MAAA,EAAQ,KAAA;AAAM,OAChC,CAAC,CAAA;AAAA,IACJ,CAAA;AAAA,IAEA,MAAM,oBAAA,GAA8D;AAClE,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,IAAA,EAAK;AAC/B,MAAA,MAAM,EAAE,gBAAA,EAAkB,iBAAA,EAAkB,GAAI,MAAA,CAAO,SAAS,EAAC;AACjE,MAAA,MAAM,MAAA,GAAS,gBAAA,GACX,MAAA,CAAO,GAAA,CAAI,CAAC,GAAA,EAAK,CAAA,KAAM,gBAAA,CAAiB,GAAA,EAAK,CAAA,EAAG,MAAM,CAAC,CAAA,GACvD,MAAA;AAEJ,MAAA,IAAI,iBAAA;AACJ,MAAA,MAAM,uBAAkC,EAAC;AAEzC,MAAA,KAAA,MAAW,QAAQ,MAAA,EAAQ;AACzB,QAAA,IAAI,IAAA,CAAK,OAAA,CAAQ,IAAA,KAAS,QAAA,EAAU;AAClC,UAAA,iBAAA,GAAoB,IAAA,CAAK,OAAA,CAAQ,KAAA,GAAQ,CAAC,CAAA,EAAG,IAAA;AAAA,QAC/C,CAAA,MAAO;AACL,UAAA,oBAAA,CAAqB,IAAA,CAAK,KAAK,OAAO,CAAA;AAAA,QACxC;AAAA,MACF;AAEA,MAAA,MAAM,QAAA,GAAW,yBAAyB,oBAAoB,CAAA;AAC9D,MAAA,OAAO;AAAA,QACL,QAAA,EAAU,iBAAA,GACN,QAAA,CAAS,GAAA,CAAI,CAAC,GAAA,EAAK,CAAA,KAAM,iBAAA,CAAkB,GAAA,EAAK,CAAA,EAAG,QAAQ,CAAC,CAAA,GAC5D,QAAA;AAAA,QACJ,GAAI,iBAAA,GAAoB,EAAE,iBAAA,KAAsB;AAAC,OACnD;AAAA,IACF;AAAA,GACF;AAEA,EAAA,OAAO,MAAA,CAAO,MAAA,CAAO,IAAA,EAAM,OAAO,CAAA;AACpC;;;ACjKA,SAAS,uBACP,KAAA,EACuB;AACvB,EAAA,OAAO,KAAA,CAAM,GAAA,CAAI,CAAC,CAAA,MAAO;AAAA,IACvB,MAAM,CAAA,CAAE,IAAA;AAAA,IACR,aAAa,CAAA,CAAE,WAAA;AAAA,IACf,sBAAsB,CAAA,CAAE;AAAA,GAC1B,CAAE,CAAA;AACJ;AA0BO,SAAS,6BAAA,CAA8B;AAAA,EAC5C,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAAA,EAAkC;AAChC,EAAA,OAAO,eAAeA,wBACpB,MAAA,EACiC;AACjC,IAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAW,KAAA,EAAM,GAAI,MAAA;AAEvC,IAAA,MAAM,MAAA,GAAS,+BAA+B,EAAE,KAAA,EAAO,UAAU,GAAA,EAAK,SAAA,EAAW,OAAO,CAAA;AACxF,IAAA,MAAM,EAAE,QAAA,EAAU,iBAAA,EAAkB,GAClC,MAAM,OAAO,oBAAA,EAAqB;AAEpC,IAAA,MAAM,oBAAA,GAAuB,sBAAA,CAAuB,KAAA,CAAM,KAAK,CAAA;AAC/D,IAAA,MAAM,KAAA,GACJ,qBAAqB,MAAA,GAAS,CAAA,GAAI,CAAC,EAAE,oBAAA,EAAsB,CAAA,GAAI,MAAA;AAEjE,IAAA,MAAM,QAAA,GAAW,MAAM,MAAA,CAAO,MAAA,CAAO,eAAA,CAAgB;AAAA,MACnD,KAAA;AAAA,MACA,QAAA;AAAA,MACA,MAAA,EAAQ;AAAA,QACN,GAAI,iBAAA,GAAoB,EAAE,iBAAA,KAAsB,EAAC;AAAA,QACjD,GAAI,KAAA,GAAQ,EAAE,KAAA,KAAU;AAAC;AAC3B,KACD,CAAA;AAED,IAAA,MAAM,gBAAgB,QAAA,CAAS,UAAA,GAAa,CAAC,CAAA,EAAG,OAAA,EAAS,SAAS,EAAC;AACnE,IAAA,MAAM,YAAA,GAAwB,EAAE,IAAA,EAAM,OAAA,EAAS,OAAO,aAAA,EAAc;AAEpE,IAAA,MAAM,aAAA,GAAgB,QAAA,CAAS,aAAA,IAAiB,EAAC;AAEjD,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,YAAA;AAAA,MACT,YAAA,EAAc,aAAA,CAAc,GAAA,CAAI,CAAC,EAAA,MAAQ;AAAA,QACvC,IAAI,EAAA,CAAG,EAAA;AAAA,QACP,IAAA,EAAM,GAAG,IAAA,IAAQ,EAAA;AAAA,QACjB,IAAA,EAAM,EAAA,CAAG,IAAA,IAAQ;AAAC,OACpB,CAAE,CAAA;AAAA,MACF,KAAA,EAAO;AAAA,QACL,WAAA,EAAa,SAAS,aAAA,EAAe,gBAAA;AAAA,QACrC,YAAA,EAAc,SAAS,aAAA,EAAe,oBAAA;AAAA,QACtC,gBAAA,EAAkB,SAAS,aAAA,EAAe;AAAA;AAC5C,KACF;AAAA,EACF,CAAA;AACF;AAOA,eAAsB,sBAAA,CAAuB;AAAA,EAC3C,KAAA;AAAA,EACA,MAAA;AAAA,EACA,KAAA;AAAA,EACA,KAAA;AAAA,EACA;AACF,CAAA,EAMoC;AAClC,EAAA,MAAM,UAAU,6BAAA,CAA8B,EAAE,OAAO,MAAA,EAAQ,KAAA,EAAO,OAAO,CAAA;AAC7E,EAAA,OAAO,QAAQ,MAAM,CAAA;AACvB;;;AC/FA,IAAM,cAAA,GAAiB,aAAA;AAkHhB,SAAS,yBACd,MAAA,EACoB;AACpB,EAAA,MAAM,EAAE,OAAM,GAAI,MAAA;AAElB,EAAA,MAAM,SAAA,GAA2C;AAAA,IAC/C,MAAM,gBAAA,CACJ,QAAA,EACA,SAAA,EACe;AACf,MAAA,MAAM,SAAS,8BAAA,CAA+B;AAAA,QAC5C,KAAA;AAAA,QACA,QAAA;AAAA,QACA,GAAA,EAAK;AAAA,OACN,CAAA;AACD,MAAA,MAAM,OAAO,UAAA,EAAW;AAAA,IAC1B,CAAA;AAAA,IAEA,MAAM,kBAAA,CACJ,QAAA,EACA,EAAA,EACA,SACA,SAAA,EACe;AACf,MAAA,MAAM,SAAS,8BAAA,CAA+B;AAAA,QAC5C,KAAA;AAAA,QACA,QAAA;AAAA,QACA,GAAA,EAAK;AAAA,OACN,CAAA;AACD,MAAA,MAAM,MAAA,CAAO,iBAAA,CAAkB,EAAA,EAAI,OAAO,CAAA;AAAA,IAC5C,CAAA;AAAA,IAEA,MAAM,mBAAA,CACJ,QAAA,EACA,EAAA,EACA,SACA,SAAA,EACe;AACf,MAAA,MAAM,SAAS,8BAAA,CAA+B;AAAA,QAC5C,KAAA;AAAA,QACA,QAAA;AAAA,QACA,GAAA,EAAK;AAAA,OACN,CAAA;AACD,MAAA,MAAM,MAAA,CAAO,mBAAA,CAAoB,EAAA,EAAI,OAAO,CAAA;AAAA,IAC9C,CAAA;AAAA,IAEA,MAAM,gBAAA,CAAiB,EAAA,EAAY,GAAA,EAAsC;AACvE,MAAA,MAAM,EAAE,QAAA,EAAU,SAAA,EAAW,UAAA,EAAY,QAAA,EAAU,SAAQ,GAAI,GAAA;AAC/D,MAAA,MAAM,SAAS,8BAAA,CAA+B;AAAA,QAC5C,KAAA;AAAA,QACA,QAAA;AAAA,QACA,GAAA,EAAK;AAAA,OACN,CAAA;AACD,MAAA,MAAM,MAAA,CAAO,gBAAA;AAAA,QACX,EAAA;AAAA,QACA,UAAA;AAAA,QACA,QAAA;AAAA,QACA;AAAA,OACF;AAAA,IACF,CAAA;AAAA,IAEA,MAAM,kBAAA,CACJ,QAAA,EACA,EAAA,EACA,SACA,SAAA,EACe;AACf,MAAA,MAAM,SAAS,8BAAA,CAA+B;AAAA,QAC5C,KAAA;AAAA,QACA,QAAA;AAAA,QACA,GAAA,EAAK;AAAA,OACN,CAAA;AACD,MAAA,MAAM,OAAO,kBAAA,CAAmB,EAAA,EAAI,OAAA,CAAQ,KAAA,IAAS,EAAE,CAAA;AAAA,IACzD,CAAA;AAAA,IAEA,MAAM,UAAA,CACJ,cAAA,EACA,cAAA,EACA,SAAA,EACe;AACf,MAAA,MAAM,SAAS,8BAAA,CAA+B;AAAA,QAC5C,KAAA;AAAA,QACA,QAAA,EAAU,cAAA;AAAA,QACV,GAAA,EAAK;AAAA,OACN,CAAA;AACD,MAAA,MAAM,MAAA,CAAO,KAAK,cAAc,CAAA;AAAA,IAClC;AAAA,GACF;AAEA,EAAA,SAAS,iBACP,KAAA,EACyB;AACzB,IAAA,MAAM,SAAS,KAAA,GACX,CAAA,EAAG,cAAc,CAAA,EAAG,MAAM,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,EAAa,CAAA,EAAG,KAAA,CAAM,KAAA,CAAM,CAAC,CAAC,CAAA,CAAA,GAClE,cAAA;AACJ,IAAA,MAAM,GAAA,GAAM,CAAC,CAAA,KAAsB,CAAA,CAAE,MAAA,CAAO,CAAC,CAAA,CAAE,WAAA,EAAY,GAAI,CAAA,CAAE,KAAA,CAAM,CAAC,CAAA;AACxE,IAAA,OAAO,MAAA,CAAO,WAAA;AAAA,MACZ,OAAO,OAAA,CAAQ,SAAS,EAAE,GAAA,CAAI,CAAC,CAAC,CAAA,EAAG,CAAC,MAAM,CAAC,CAAA,EAAG,MAAM,CAAA,EAAG,GAAA,CAAI,CAAC,CAAC,CAAA,CAAA,EAAI,CAAC,CAAC;AAAA,KACrE;AAAA,EACF;AAEA,EAAA,MAAM,WAAA,GAAc,CAClB,KAAA,EACA,MAAA,KAEA,6BAAA,CAA8B,EAAE,KAAA,EAAO,MAAA,EAAQ,KAAA,EAAO,KAAA,EAAO,MAAA,CAAO,KAAA,EAAO,CAAA;AAE7E,EAAA,MAAM,OAAA,GACJ,MAAA,CAAO,KAAA,IAAS,MAAA,CAAO,MAAA,GACnB,WAAA,CAAY,MAAA,CAAO,KAAA,EAAO,MAAA,CAAO,MAAM,CAAA,IACrC,MAAM;AACN,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KAEF;AAAA,EACF,CAAA,CAAA;AAEN,EAAA,OAAO;AAAA,IACL,gBAAA;AAAA,IACA,OAAA;AAAA,IACA,kBAAA,EAAoB,WAAA;AAAA,IACpB,WAAA,EAAa,CAAC,OAAA,KAAY;AAAA,GAC5B;AACF","file":"index.cjs","sourcesContent":["import type { ThreadManagerConfig, BaseThreadManager } 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 `${key}:thread:${threadId}`;\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 { createThreadManager } from \"../../../lib/thread/manager\";\nimport type {\n ProviderThreadManager,\n ThreadManagerConfig,\n ThreadManagerHooks,\n} from \"../../../lib/thread/types\";\nimport type { GoogleGenAIToolResponse } from \"./activities\";\n\n/** SDK-native content type for Google GenAI human messages */\nexport type GoogleGenAIContent = string | Part[];\n\n/** A Content with a unique ID for idempotent Redis storage */\nexport interface StoredContent {\n id: string;\n content: Content;\n}\n\nexport type GoogleGenAIThreadManagerHooks = ThreadManagerHooks<StoredContent, Content>;\n\nexport interface GoogleGenAIThreadManagerConfig {\n redis: Redis;\n threadId: string;\n /** Thread key, defaults to 'messages' */\n key?: string;\n hooks?: GoogleGenAIThreadManagerHooks;\n}\n\n/** Prepared payload ready to send to the Google GenAI API */\nexport interface GoogleGenAIInvocationPayload {\n contents: Content[];\n systemInstruction?: string;\n}\n\n/** Thread manager with Google GenAI Content convenience helpers */\nexport interface GoogleGenAIThreadManager\n extends ProviderThreadManager<StoredContent, GoogleGenAIContent, GoogleGenAIToolResponse> {\n appendModelContent(id: string, parts: Part[]): Promise<void>;\n prepareForInvocation(): Promise<GoogleGenAIInvocationPayload>;\n}\n\nfunction storedContentId(msg: StoredContent): string {\n return msg.id;\n}\n\n/** Normalise content into Part[] */\nfunction toParts(content: GoogleGenAIContent): Part[] {\n if (typeof content === \"string\") {\n return [{ text: content }];\n }\n return content;\n}\n\n/** Convert a string or object into a Record suitable for functionResponse.response */\nfunction toFunctionResponse(content: string | Record<string, unknown>): Record<string, unknown> {\n if (typeof content === \"object\") {\n return content;\n }\n return { result: content };\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-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: Omit<GoogleGenAIThreadManager, keyof typeof base> = {\n async appendUserMessage(\n id: string,\n content: GoogleGenAIContent,\n ): Promise<void> {\n await base.append([{\n id,\n content: { role: \"user\", parts: toParts(content) },\n }]);\n },\n\n async appendSystemMessage(id: string, content: string): Promise<void> {\n await base.initialize();\n await base.append([{\n id,\n content: { role: \"system\", parts: [{ text: content }] },\n }]);\n },\n\n async appendModelContent(id: string, parts: Part[]): Promise<void> {\n await base.append([{\n id,\n content: { role: \"model\", parts },\n }]);\n },\n\n async appendToolResult(\n id: string,\n toolCallId: string,\n toolName: string,\n content: GoogleGenAIToolResponse,\n ): Promise<void> {\n const parts: Part[] = Array.isArray(content)\n ? content as Part[]\n : [{\n functionResponse: {\n id: toolCallId,\n name: toolName,\n response: toFunctionResponse(content),\n },\n }];\n\n await base.append([{\n id,\n content: { role: \"user\", parts },\n }]);\n },\n\n async prepareForInvocation(): Promise<GoogleGenAIInvocationPayload> {\n const stored = await base.load();\n const { onPrepareMessage, onPreparedMessage } = config.hooks ?? {};\n const mapped = onPrepareMessage\n ? stored.map((msg, i) => onPrepareMessage(msg, i, stored))\n : stored;\n\n let systemInstruction: string | undefined;\n const conversationContents: Content[] = [];\n\n for (const item of mapped) {\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 return {\n contents: onPreparedMessage\n ? contents.map((msg, i) => onPreparedMessage(msg, i, contents))\n : contents,\n ...(systemInstruction ? { systemInstruction } : {}),\n };\n },\n };\n\n return Object.assign(base, helpers);\n}\n","import type Redis from \"ioredis\";\nimport type { GoogleGenAI, Content, FunctionDeclaration } from \"@google/genai\";\nimport type { SerializableToolDefinition } from \"../../../lib/types\";\nimport type { AgentResponse, ModelInvokerConfig } from \"../../../lib/model\";\nimport { createGoogleGenAIThreadManager, type GoogleGenAIThreadManagerHooks } from \"./thread-manager\";\n\nexport interface GoogleGenAIModelInvokerConfig {\n redis: Redis;\n client: GoogleGenAI;\n model: string;\n hooks?: GoogleGenAIThreadManagerHooks;\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 * 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`, and returns a normalised AgentResponse.\n * The caller is responsible for appending the response to the thread.\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 hooks,\n}: GoogleGenAIModelInvokerConfig) {\n return async function invokeGoogleGenAIModel(\n config: ModelInvokerConfig,\n ): Promise<AgentResponse<Content>> {\n const { threadId, threadKey, state } = config;\n\n const thread = createGoogleGenAIThreadManager({ redis, threadId, key: threadKey, hooks });\n const { contents, systemInstruction } =\n await thread.prepareForInvocation();\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 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 hooks,\n config,\n}: {\n redis: Redis;\n client: GoogleGenAI;\n model: string;\n hooks?: GoogleGenAIThreadManagerHooks;\n config: ModelInvokerConfig;\n}): Promise<AgentResponse<Content>> {\n const invoker = createGoogleGenAIModelInvoker({ redis, client, model, hooks });\n return invoker(config);\n}\n","import type Redis from \"ioredis\";\nimport type { GoogleGenAI, Content, Part } from \"@google/genai\";\nimport type { ToolResultConfig } from \"../../../lib/types\";\nimport type {\n ActivityToolHandler,\n RouterContext,\n ToolHandlerResponse,\n} from \"../../../lib/tool-router/types\";\nimport type {\n ThreadOps,\n PrefixedThreadOps,\n ScopedPrefix,\n} from \"../../../lib/session/types\";\nimport type { ModelInvoker } from \"../../../lib/model\";\nimport {\n createGoogleGenAIThreadManager,\n type GoogleGenAIContent,\n type GoogleGenAIThreadManagerHooks,\n} from \"./thread-manager\";\nimport { createGoogleGenAIModelInvoker } from \"./model-invoker\";\n\nconst ADAPTER_PREFIX = \"googleGenAI\" as const;\n\nexport type GoogleGenAIThreadOps<TScope extends string = \"\"> =\n PrefixedThreadOps<\n ScopedPrefix<TScope, typeof ADAPTER_PREFIX>,\n GoogleGenAIContent\n >;\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 hooks?: GoogleGenAIThreadManagerHooks;\n}\n\n/**\n * Tool response type accepted by the Google GenAI adapter.\n *\n * Handlers can return:\n * - **`string`** — plain text, wrapped in a `functionResponse` part.\n * - **`Record<string, unknown>`** — structured object used as `functionResponse.response`.\n * - **`Part[]`** — pre-built parts used directly as `Content.parts`.\n * The handler is responsible for building correct Part objects (e.g. `functionResponse`,\n * `inlineData`, `text`). Use `context.toolCallId` and `context.toolName` to construct\n * `functionResponse` parts.\n *\n * @example\n * ```typescript\n * adapter.wrapHandler(async (args, ctx) => ({\n * toolResponse: [\n * { functionResponse: { id: ctx.toolCallId, name: ctx.toolName, response: { result: \"done\" } } },\n * { inlineData: { data: base64, mimeType: \"image/png\" } },\n * ],\n * data: null,\n * }));\n * ```\n */\nexport type GoogleGenAIToolResponse = string | Record<string, unknown> | Part[];\n\nexport interface GoogleGenAIAdapter {\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, client: GoogleGenAI): ModelInvoker<Content>;\n /**\n * Create prefixed thread activities for registration on the worker.\n *\n * @param scope - Workflow name appended to the adapter prefix.\n * Use different scopes for the main agent vs subagents to avoid collisions.\n *\n * @example\n * ```typescript\n * adapter.createActivities(\"codingAgent\")\n * // → { googleGenAICodingAgentInitializeThread, googleGenAICodingAgentAppendHumanMessage, … }\n *\n * adapter.createActivities(\"researchAgent\")\n * // → { googleGenAIResearchAgentInitializeThread, … }\n * ```\n */\n createActivities<S extends string = \"\">(scope?: S): GoogleGenAIThreadOps<S>;\n\n /**\n * Identity wrapper that types a tool handler for this adapter.\n * Constrains `toolResponse` to {@link GoogleGenAIToolResponse}.\n */\n wrapHandler<TArgs, TResult, TContext extends RouterContext = RouterContext>(\n handler: (\n args: TArgs,\n context: TContext\n ) => Promise<ToolHandlerResponse<TResult, GoogleGenAIToolResponse>>\n ): ActivityToolHandler<TArgs, TResult, TContext, GoogleGenAIToolResponse>;\n}\n\n/**\n * Creates a Google GenAI adapter that bundles thread operations and model\n * invocation using the `@google/genai` SDK.\n *\n * Use `createActivities(scope)` to register scoped thread operations as\n * Temporal activities on the worker. The `invoker` (or invokers created via\n * `createModelInvoker`) should be wrapped with `createRunAgentActivity`.\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.createActivities(\"codingAgent\"),\n * runCodingAgent: createRunAgentActivity(temporalClient, adapter.invoker),\n * };\n * }\n * ```\n *\n * @example Multi-agent worker (main + subagent share the adapter)\n * ```typescript\n * export function createActivities(temporalClient: WorkflowClient) {\n * return {\n * ...adapter.createActivities(\"codingAgent\"),\n * ...adapter.createActivities(\"researchAgent\"),\n * runCodingAgent: createRunAgentActivity(temporalClient, adapter.invoker),\n * runResearchAgent: createRunAgentActivity(\n * temporalClient,\n * adapter.createModelInvoker('gemini-2.5-pro'),\n * ),\n * };\n * }\n * ```\n */\nexport function createGoogleGenAIAdapter(\n config: GoogleGenAIAdapterConfig\n): GoogleGenAIAdapter {\n const { redis } = config;\n\n const threadOps: ThreadOps<GoogleGenAIContent> = {\n async initializeThread(\n threadId: string,\n threadKey?: string\n ): Promise<void> {\n const thread = createGoogleGenAIThreadManager({\n redis,\n threadId,\n key: threadKey,\n });\n await thread.initialize();\n },\n\n async appendHumanMessage(\n threadId: string,\n id: string,\n content: GoogleGenAIContent,\n threadKey?: string\n ): Promise<void> {\n const thread = createGoogleGenAIThreadManager({\n redis,\n threadId,\n key: threadKey,\n });\n await thread.appendUserMessage(id, content);\n },\n\n async appendSystemMessage(\n threadId: string,\n id: string,\n content: string,\n threadKey?: string\n ): Promise<void> {\n const thread = createGoogleGenAIThreadManager({\n redis,\n threadId,\n key: threadKey,\n });\n await thread.appendSystemMessage(id, content);\n },\n\n async appendToolResult(id: string, cfg: ToolResultConfig): Promise<void> {\n const { threadId, threadKey, toolCallId, toolName, content } = cfg;\n const thread = createGoogleGenAIThreadManager({\n redis,\n threadId,\n key: threadKey,\n });\n await thread.appendToolResult(\n id,\n toolCallId,\n toolName,\n content as GoogleGenAIToolResponse\n );\n },\n\n async appendAgentMessage(\n threadId: string,\n id: string,\n message: Content,\n threadKey?: string,\n ): Promise<void> {\n const thread = createGoogleGenAIThreadManager({\n redis,\n threadId,\n key: threadKey,\n });\n await thread.appendModelContent(id, message.parts ?? []);\n },\n\n async forkThread(\n sourceThreadId: string,\n targetThreadId: string,\n threadKey?: string\n ): Promise<void> {\n const thread = createGoogleGenAIThreadManager({\n redis,\n threadId: sourceThreadId,\n key: threadKey,\n });\n await thread.fork(targetThreadId);\n },\n };\n\n function createActivities<S extends string = \"\">(\n scope?: S\n ): GoogleGenAIThreadOps<S> {\n const prefix = scope\n ? `${ADAPTER_PREFIX}${scope.charAt(0).toUpperCase()}${scope.slice(1)}`\n : ADAPTER_PREFIX;\n const cap = (s: string): string => s.charAt(0).toUpperCase() + s.slice(1);\n return Object.fromEntries(\n Object.entries(threadOps).map(([k, v]) => [`${prefix}${cap(k)}`, v])\n ) as GoogleGenAIThreadOps<S>;\n }\n\n const makeInvoker = (\n model: string,\n client: GoogleGenAI\n ): ModelInvoker<Content> =>\n createGoogleGenAIModelInvoker({ redis, client, model, hooks: config.hooks });\n\n const invoker: ModelInvoker<Content> =\n config.model && config.client\n ? makeInvoker(config.model, config.client)\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 createActivities,\n invoker,\n createModelInvoker: makeInvoker,\n wrapHandler: (handler) => handler,\n };\n}\n"]}
1
+ {"version":3,"sources":["../../../../src/lib/thread/manager.ts","../../../../src/adapters/thread/google-genai/thread-manager.ts","../../../../src/lib/activity.ts","../../../../src/adapters/thread/google-genai/model-invoker.ts","../../../../src/adapters/thread/google-genai/activities.ts"],"names":["Context","invokeGoogleGenAIModel"],"mappings":"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","file":"index.cjs","sourcesContent":["import type { ThreadManagerConfig, BaseThreadManager } 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 `${key}:thread:${threadId}`;\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 { createThreadManager } from \"../../../lib/thread/manager\";\nimport type {\n ProviderThreadManager,\n ThreadManagerConfig,\n ThreadManagerHooks,\n} from \"../../../lib/thread/types\";\nimport type { GoogleGenAIToolResponse } from \"./activities\";\n\n/** SDK-native content type for Google GenAI human messages */\nexport type GoogleGenAIContent = string | Part[];\n\n/** A Content with a unique ID for idempotent Redis storage */\nexport interface StoredContent {\n id: string;\n content: Content;\n}\n\nexport type GoogleGenAIThreadManagerHooks = ThreadManagerHooks<StoredContent, Content>;\n\nexport interface GoogleGenAIThreadManagerConfig {\n redis: Redis;\n threadId: string;\n /** Thread key, defaults to 'messages' */\n key?: string;\n hooks?: GoogleGenAIThreadManagerHooks;\n}\n\n/** Prepared payload ready to send to the Google GenAI API */\nexport interface GoogleGenAIInvocationPayload {\n contents: Content[];\n systemInstruction?: string;\n}\n\n/** Thread manager with Google GenAI Content convenience helpers */\nexport interface GoogleGenAIThreadManager\n extends ProviderThreadManager<StoredContent, GoogleGenAIContent, GoogleGenAIToolResponse> {\n appendModelContent(id: string, parts: Part[]): Promise<void>;\n prepareForInvocation(): Promise<GoogleGenAIInvocationPayload>;\n}\n\nfunction storedContentId(msg: StoredContent): string {\n return msg.id;\n}\n\n/** Normalise content into Part[] */\nfunction toParts(content: GoogleGenAIContent): Part[] {\n if (typeof content === \"string\") {\n return [{ text: content }];\n }\n return content;\n}\n\n/** Convert a string or object into a Record suitable for functionResponse.response */\nfunction toFunctionResponse(content: string | Record<string, unknown>): Record<string, unknown> {\n if (typeof content === \"object\") {\n return content;\n }\n return { result: content };\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-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: Omit<GoogleGenAIThreadManager, keyof typeof base> = {\n async appendUserMessage(\n id: string,\n content: GoogleGenAIContent,\n ): Promise<void> {\n await base.append([{\n id,\n content: { role: \"user\", parts: toParts(content) },\n }]);\n },\n\n async appendSystemMessage(id: string, content: string): Promise<void> {\n await base.initialize();\n await base.append([{\n id,\n content: { role: \"system\", parts: [{ text: content }] },\n }]);\n },\n\n async appendModelContent(id: string, parts: Part[]): Promise<void> {\n await base.append([{\n id,\n content: { role: \"model\", parts },\n }]);\n },\n\n async appendToolResult(\n id: string,\n toolCallId: string,\n toolName: string,\n content: GoogleGenAIToolResponse,\n ): Promise<void> {\n const parts: Part[] = Array.isArray(content)\n ? content as Part[]\n : [{\n functionResponse: {\n id: toolCallId,\n name: toolName,\n response: toFunctionResponse(content),\n },\n }];\n\n await base.append([{\n id,\n content: { role: \"user\", parts },\n }]);\n },\n\n async prepareForInvocation(): Promise<GoogleGenAIInvocationPayload> {\n const stored = await base.load();\n const { onPrepareMessage, onPreparedMessage } = config.hooks ?? {};\n const mapped = onPrepareMessage\n ? stored.map((msg, i) => onPrepareMessage(msg, i, stored))\n : stored;\n\n let systemInstruction: string | undefined;\n const conversationContents: Content[] = [];\n\n for (const item of mapped) {\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 return {\n contents: onPreparedMessage\n ? contents.map((msg, i) => onPreparedMessage(msg, i, contents))\n : contents,\n ...(systemInstruction ? { systemInstruction } : {}),\n };\n },\n };\n\n return Object.assign(base, helpers);\n}\n","import { Context } from \"@temporalio/activity\";\nimport type { WorkflowClient } from \"@temporalio/client\";\nimport type { BaseAgentState, RunAgentConfig } from \"./types\";\nimport type { JsonValue } from \"./state/types\";\nimport type {\n ActivityToolHandler,\n RouterContext,\n ToolHandlerResponse,\n} from \"./tool-router/types\";\n\n/**\n * Safely retrieve Temporal activity heartbeat and cancellation signal.\n * Returns empty object when called outside a Temporal activity (e.g. tests).\n */\nexport function getActivityContext(): {\n heartbeat?: () => void;\n signal?: AbortSignal;\n} {\n try {\n const ctx = Context.current();\n return { heartbeat: () => ctx.heartbeat(), signal: ctx.cancellationSignal };\n } catch {\n return {};\n }\n}\n\n/**\n * Query the parent workflow's state from within an activity.\n * Resolves the workflow handle from the current activity context.\n */\nexport async function queryParentWorkflowState<T>(\n client: WorkflowClient\n): Promise<T> {\n const { workflowExecution } = Context.current().info;\n const handle = client.getHandle(\n workflowExecution.workflowId,\n workflowExecution.runId\n );\n return handle.query<T>(\"getAgentState\");\n}\n\n/**\n * Wraps a handler into a scope-prefixed `RunAgentActivity` by auto-fetching\n * the parent workflow's agent state before each invocation.\n *\n * Returns a `Record` with a single key `run<Scope>` so it can be spread\n * into the activities object alongside adapter activities.\n *\n * @param scope - Workflow scope used to derive the activity name.\n * `\"myAgentWorkflow\"` produces `{ runMyAgentWorkflow: fn }`.\n *\n * @example\n * ```typescript\n * import { createRunAgentActivity } from 'zeitlich';\n *\n * return {\n * ...adapter.createActivities(\"myAgentWorkflow\"),\n * ...createRunAgentActivity(client, adapter.invoker, \"myAgentWorkflow\"),\n * };\n * ```\n */\nexport function createRunAgentActivity<R, S extends BaseAgentState = BaseAgentState>(\n client: WorkflowClient,\n handler: (config: RunAgentConfig & { state: S }) => Promise<R>,\n scope: string,\n): Record<string, (config: RunAgentConfig) => Promise<R>> {\n const name = `run${scope.charAt(0).toUpperCase()}${scope.slice(1)}`;\n return {\n [name]: async (config: RunAgentConfig) => {\n const state = await queryParentWorkflowState<S>(client);\n return handler({ ...config, state });\n },\n };\n}\n\n/**\n * Context injected into tool handlers created via {@link withParentWorkflowState}.\n */\nexport interface AgentStateContext<S extends BaseAgentState = BaseAgentState> extends RouterContext {\n state: S;\n}\n\n/**\n * Wraps a tool handler into an `ActivityToolHandler` by auto-fetching the\n * parent workflow's agent state before each invocation.\n *\n * @typeParam S - Custom agent state type (defaults to `BaseAgentState`)\n *\n * @example\n * ```typescript\n * import { withParentWorkflowState, type AgentStateContext } from 'zeitlich';\n *\n * // With custom state:\n * interface MyState extends BaseAgentState { customField: string }\n * const myHandler = withParentWorkflowState<MyArgs, MyResult, MyState>(\n * client,\n * async (args, ctx) => {\n * console.log(ctx.state.customField);\n * return { toolResponse: 'done', data: null };\n * },\n * );\n * ```\n */\nexport function withParentWorkflowState<TArgs, TResult, S extends BaseAgentState = BaseAgentState, TToolResponse = JsonValue>(\n client: WorkflowClient,\n handler: (\n args: TArgs,\n context: AgentStateContext<S>,\n ) => Promise<ToolHandlerResponse<TResult, TToolResponse>>,\n): ActivityToolHandler<TArgs, TResult, RouterContext, TToolResponse> {\n return async (args, context) => {\n const state = await queryParentWorkflowState<S>(client);\n return handler(args, { ...context, state });\n };\n}\n","import type Redis from \"ioredis\";\nimport type { GoogleGenAI, Content, FunctionDeclaration, Part, GenerateContentResponse } from \"@google/genai\";\nimport type { SerializableToolDefinition } from \"../../../lib/types\";\nimport type { AgentResponse, ModelInvokerConfig } from \"../../../lib/model\";\nimport { createGoogleGenAIThreadManager, type GoogleGenAIThreadManagerHooks } from \"./thread-manager\";\nimport { getActivityContext } from \"../../../lib/activity\";\n\nexport interface GoogleGenAIModelInvokerConfig {\n redis: Redis;\n client: GoogleGenAI;\n model: string;\n hooks?: GoogleGenAIThreadManagerHooks;\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 * Creates a Google GenAI model invoker that satisfies the generic\n * `ModelInvoker<Content>` contract.\n *\n * Internally streams the response and emits Temporal heartbeats on each\n * chunk so that long-running LLM calls remain visible to the scheduler.\n * The caller is responsible for appending the response to the thread.\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 { ...createRunAgentActivity(client, invoker, \"myAgent\") };\n * ```\n */\nexport function createGoogleGenAIModelInvoker({\n redis,\n client,\n model,\n hooks,\n}: GoogleGenAIModelInvokerConfig) {\n return async function invokeGoogleGenAIModel(\n config: ModelInvokerConfig,\n ): Promise<AgentResponse<Content>> {\n const { threadId, threadKey, state } = config;\n const { heartbeat, signal } = getActivityContext();\n\n const thread = createGoogleGenAIThreadManager({ redis, threadId, key: threadKey, hooks });\n const { contents, systemInstruction } =\n await thread.prepareForInvocation();\n\n const functionDeclarations = toFunctionDeclarations(state.tools);\n const tools =\n functionDeclarations.length > 0 ? [{ functionDeclarations }] : undefined;\n\n const stream = await client.models.generateContentStream({\n model,\n contents,\n config: {\n ...(systemInstruction ? { systemInstruction } : {}),\n ...(tools ? { tools } : {}),\n abortSignal: signal,\n },\n });\n\n const allParts: Part[] = [];\n let lastChunk: GenerateContentResponse | undefined;\n for await (const chunk of stream) {\n lastChunk = chunk;\n allParts.push(...(chunk.candidates?.[0]?.content?.parts ?? []));\n heartbeat?.();\n }\n\n if (!lastChunk) {\n throw new Error(\"Google GenAI stream ended without producing any chunks\");\n }\n\n const modelContent: Content = { role: \"model\", parts: allParts };\n const functionCalls = lastChunk.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: lastChunk.usageMetadata?.promptTokenCount,\n outputTokens: lastChunk.usageMetadata?.candidatesTokenCount,\n cachedReadTokens: lastChunk.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 hooks,\n config,\n}: {\n redis: Redis;\n client: GoogleGenAI;\n model: string;\n hooks?: GoogleGenAIThreadManagerHooks;\n config: ModelInvokerConfig;\n}): Promise<AgentResponse<Content>> {\n const invoker = createGoogleGenAIModelInvoker({ redis, client, model, hooks });\n return invoker(config);\n}\n","import type Redis from \"ioredis\";\nimport type { GoogleGenAI, Content, Part } from \"@google/genai\";\nimport type { ToolResultConfig } from \"../../../lib/types\";\nimport type {\n ActivityToolHandler,\n RouterContext,\n ToolHandlerResponse,\n} from \"../../../lib/tool-router/types\";\nimport type {\n ThreadOps,\n PrefixedThreadOps,\n ScopedPrefix,\n} from \"../../../lib/session/types\";\nimport type { ModelInvoker } from \"../../../lib/model\";\nimport {\n createGoogleGenAIThreadManager,\n type GoogleGenAIContent,\n type GoogleGenAIThreadManagerHooks,\n} from \"./thread-manager\";\nimport { createGoogleGenAIModelInvoker } from \"./model-invoker\";\n\nconst ADAPTER_PREFIX = \"googleGenAI\" as const;\n\nexport type GoogleGenAIThreadOps<TScope extends string = \"\"> =\n PrefixedThreadOps<\n ScopedPrefix<TScope, typeof ADAPTER_PREFIX>,\n GoogleGenAIContent\n >;\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 hooks?: GoogleGenAIThreadManagerHooks;\n}\n\n/**\n * Tool response type accepted by the Google GenAI adapter.\n *\n * Handlers can return:\n * - **`string`** — plain text, wrapped in a `functionResponse` part.\n * - **`Record<string, unknown>`** — structured object used as `functionResponse.response`.\n * - **`Part[]`** — pre-built parts used directly as `Content.parts`.\n * The handler is responsible for building correct Part objects (e.g. `functionResponse`,\n * `inlineData`, `text`). Use `context.toolCallId` and `context.toolName` to construct\n * `functionResponse` parts.\n *\n * @example\n * ```typescript\n * adapter.wrapHandler(async (args, ctx) => ({\n * toolResponse: [\n * { functionResponse: { id: ctx.toolCallId, name: ctx.toolName, response: { result: \"done\" } } },\n * { inlineData: { data: base64, mimeType: \"image/png\" } },\n * ],\n * data: null,\n * }));\n * ```\n */\nexport type GoogleGenAIToolResponse = string | Record<string, unknown> | Part[];\n\nexport interface GoogleGenAIAdapter {\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, client: GoogleGenAI): ModelInvoker<Content>;\n /**\n * Create prefixed thread activities for registration on the worker.\n *\n * @param scope - Workflow name appended to the adapter prefix.\n * Use different scopes for the main agent vs subagents to avoid collisions.\n *\n * @example\n * ```typescript\n * adapter.createActivities(\"codingAgent\")\n * // → { googleGenAICodingAgentInitializeThread, googleGenAICodingAgentAppendHumanMessage, … }\n *\n * adapter.createActivities(\"researchAgent\")\n * // → { googleGenAIResearchAgentInitializeThread, … }\n * ```\n */\n createActivities<S extends string = \"\">(scope?: S): GoogleGenAIThreadOps<S>;\n\n /**\n * Identity wrapper that types a tool handler for this adapter.\n * Constrains `toolResponse` to {@link GoogleGenAIToolResponse}.\n */\n wrapHandler<TArgs, TResult, TContext extends RouterContext = RouterContext>(\n handler: (\n args: TArgs,\n context: TContext\n ) => Promise<ToolHandlerResponse<TResult, GoogleGenAIToolResponse>>\n ): ActivityToolHandler<TArgs, TResult, TContext, GoogleGenAIToolResponse>;\n}\n\n/**\n * Creates a Google GenAI adapter that bundles thread operations and model\n * invocation using the `@google/genai` SDK.\n *\n * Use `createActivities(scope)` to register scoped thread operations as\n * Temporal activities on the worker. The `invoker` (or invokers created via\n * `createModelInvoker`) should be wrapped with `createRunAgentActivity`.\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.createActivities(\"codingAgent\"),\n * ...createRunAgentActivity(temporalClient, adapter.invoker, \"codingAgent\"),\n * };\n * }\n * ```\n *\n * @example Multi-agent worker (main + subagent share the adapter)\n * ```typescript\n * export function createActivities(temporalClient: WorkflowClient) {\n * return {\n * ...adapter.createActivities(\"codingAgent\"),\n * ...adapter.createActivities(\"researchAgent\"),\n * ...createRunAgentActivity(temporalClient, adapter.invoker, \"codingAgent\"),\n * ...createRunAgentActivity(\n * temporalClient,\n * adapter.createModelInvoker('gemini-2.5-pro'),\n * \"researchAgent\",\n * ),\n * };\n * }\n * ```\n */\nexport function createGoogleGenAIAdapter(\n config: GoogleGenAIAdapterConfig\n): GoogleGenAIAdapter {\n const { redis } = config;\n\n const threadOps: ThreadOps<GoogleGenAIContent> = {\n async initializeThread(\n threadId: string,\n threadKey?: string\n ): Promise<void> {\n const thread = createGoogleGenAIThreadManager({\n redis,\n threadId,\n key: threadKey,\n });\n await thread.initialize();\n },\n\n async appendHumanMessage(\n threadId: string,\n id: string,\n content: GoogleGenAIContent,\n threadKey?: string\n ): Promise<void> {\n const thread = createGoogleGenAIThreadManager({\n redis,\n threadId,\n key: threadKey,\n });\n await thread.appendUserMessage(id, content);\n },\n\n async appendSystemMessage(\n threadId: string,\n id: string,\n content: string,\n threadKey?: string\n ): Promise<void> {\n const thread = createGoogleGenAIThreadManager({\n redis,\n threadId,\n key: threadKey,\n });\n await thread.appendSystemMessage(id, content);\n },\n\n async appendToolResult(id: string, cfg: ToolResultConfig): Promise<void> {\n const { threadId, threadKey, toolCallId, toolName, content } = cfg;\n const thread = createGoogleGenAIThreadManager({\n redis,\n threadId,\n key: threadKey,\n });\n await thread.appendToolResult(\n id,\n toolCallId,\n toolName,\n content as GoogleGenAIToolResponse\n );\n },\n\n async appendAgentMessage(\n threadId: string,\n id: string,\n message: Content,\n threadKey?: string,\n ): Promise<void> {\n const thread = createGoogleGenAIThreadManager({\n redis,\n threadId,\n key: threadKey,\n });\n await thread.appendModelContent(id, message.parts ?? []);\n },\n\n async forkThread(\n sourceThreadId: string,\n targetThreadId: string,\n threadKey?: string\n ): Promise<void> {\n const thread = createGoogleGenAIThreadManager({\n redis,\n threadId: sourceThreadId,\n key: threadKey,\n });\n await thread.fork(targetThreadId);\n },\n };\n\n function createActivities<S extends string = \"\">(\n scope?: S\n ): GoogleGenAIThreadOps<S> {\n const prefix = scope\n ? `${ADAPTER_PREFIX}${scope.charAt(0).toUpperCase()}${scope.slice(1)}`\n : ADAPTER_PREFIX;\n const cap = (s: string): string => s.charAt(0).toUpperCase() + s.slice(1);\n return Object.fromEntries(\n Object.entries(threadOps).map(([k, v]) => [`${prefix}${cap(k)}`, v])\n ) as GoogleGenAIThreadOps<S>;\n }\n\n const makeInvoker = (\n model: string,\n client: GoogleGenAI\n ): ModelInvoker<Content> =>\n createGoogleGenAIModelInvoker({ redis, client, model, hooks: config.hooks });\n\n const invoker: ModelInvoker<Content> =\n config.model && config.client\n ? makeInvoker(config.model, config.client)\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 createActivities,\n invoker,\n createModelInvoker: makeInvoker,\n wrapHandler: (handler) => handler,\n };\n}\n"]}
@@ -1,14 +1,14 @@
1
- import { G as GoogleGenAIThreadManagerHooks } from '../../../activities-DA-bQM12.cjs';
2
- export { a as GoogleGenAIAdapter, b as GoogleGenAIAdapterConfig, c as GoogleGenAIContent, d as GoogleGenAIInvocationPayload, e as GoogleGenAIThreadManager, f as GoogleGenAIThreadManagerConfig, g as GoogleGenAIThreadOps, h as GoogleGenAIToolResponse, S as StoredContent, i as createGoogleGenAIAdapter, j as createGoogleGenAIThreadManager } from '../../../activities-DA-bQM12.cjs';
1
+ import { G as GoogleGenAIThreadManagerHooks } from '../../../activities-JOqPfKP0.cjs';
2
+ export { a as GoogleGenAIAdapter, b as GoogleGenAIAdapterConfig, c as GoogleGenAIContent, d as GoogleGenAIInvocationPayload, e as GoogleGenAIThreadManager, f as GoogleGenAIThreadManagerConfig, g as GoogleGenAIThreadOps, h as GoogleGenAIToolResponse, S as StoredContent, i as createGoogleGenAIAdapter, j as createGoogleGenAIThreadManager } from '../../../activities-JOqPfKP0.cjs';
3
3
  import Redis from 'ioredis';
4
4
  import { GoogleGenAI, Content } from '@google/genai';
5
- import { M as ModelInvokerConfig, A as AgentResponse } from '../../../types-Bpq5fDI5.cjs';
6
- import '../../../types-NJDyMyUx.cjs';
5
+ import { M as ModelInvokerConfig, A as AgentResponse } from '../../../types-DlLajQcu.cjs';
6
+ import '../../../types-DPAZ3KCs.cjs';
7
7
  import '@temporalio/common';
8
8
  import '@temporalio/workflow';
9
9
  import '@temporalio/common/lib/interfaces';
10
10
  import 'zod';
11
- import '../../../types-AujBIMMn.cjs';
11
+ import '../../../types-DxCpFNv_.cjs';
12
12
 
13
13
  interface GoogleGenAIModelInvokerConfig {
14
14
  redis: Redis;
@@ -20,8 +20,8 @@ interface GoogleGenAIModelInvokerConfig {
20
20
  * Creates a Google GenAI model invoker that satisfies the generic
21
21
  * `ModelInvoker<Content>` contract.
22
22
  *
23
- * Loads the conversation thread from Redis, invokes the Gemini model via
24
- * `client.models.generateContent`, and returns a normalised AgentResponse.
23
+ * Internally streams the response and emits Temporal heartbeats on each
24
+ * chunk so that long-running LLM calls remain visible to the scheduler.
25
25
  * The caller is responsible for appending the response to the thread.
26
26
  *
27
27
  * @example
@@ -37,7 +37,7 @@ interface GoogleGenAIModelInvokerConfig {
37
37
  * model: 'gemini-2.5-flash',
38
38
  * });
39
39
  *
40
- * return { runAgent: createRunAgentActivity(client, invoker) };
40
+ * return { ...createRunAgentActivity(client, invoker, "myAgent") };
41
41
  * ```
42
42
  */
43
43
  declare function createGoogleGenAIModelInvoker({ redis, client, model, hooks, }: GoogleGenAIModelInvokerConfig): (config: ModelInvokerConfig) => Promise<AgentResponse<Content>>;
@@ -1,14 +1,14 @@
1
- import { G as GoogleGenAIThreadManagerHooks } from '../../../activities-FIXVz7DT.js';
2
- export { a as GoogleGenAIAdapter, b as GoogleGenAIAdapterConfig, c as GoogleGenAIContent, d as GoogleGenAIInvocationPayload, e as GoogleGenAIThreadManager, f as GoogleGenAIThreadManagerConfig, g as GoogleGenAIThreadOps, h as GoogleGenAIToolResponse, S as StoredContent, i as createGoogleGenAIAdapter, j as createGoogleGenAIThreadManager } from '../../../activities-FIXVz7DT.js';
1
+ import { G as GoogleGenAIThreadManagerHooks } from '../../../activities-WwMsjRwm.js';
2
+ export { a as GoogleGenAIAdapter, b as GoogleGenAIAdapterConfig, c as GoogleGenAIContent, d as GoogleGenAIInvocationPayload, e as GoogleGenAIThreadManager, f as GoogleGenAIThreadManagerConfig, g as GoogleGenAIThreadOps, h as GoogleGenAIToolResponse, S as StoredContent, i as createGoogleGenAIAdapter, j as createGoogleGenAIThreadManager } from '../../../activities-WwMsjRwm.js';
3
3
  import Redis from 'ioredis';
4
4
  import { GoogleGenAI, Content } from '@google/genai';
5
- import { M as ModelInvokerConfig, A as AgentResponse } from '../../../types-CheCTLeV.js';
6
- import '../../../types-BxiT8w9d.js';
5
+ import { M as ModelInvokerConfig, A as AgentResponse } from '../../../types-BGLW5Zyj.js';
6
+ import '../../../types-BVUmLYpj.js';
7
7
  import '@temporalio/common';
8
8
  import '@temporalio/workflow';
9
9
  import '@temporalio/common/lib/interfaces';
10
10
  import 'zod';
11
- import '../../../types-AujBIMMn.js';
11
+ import '../../../types-DxCpFNv_.js';
12
12
 
13
13
  interface GoogleGenAIModelInvokerConfig {
14
14
  redis: Redis;
@@ -20,8 +20,8 @@ interface GoogleGenAIModelInvokerConfig {
20
20
  * Creates a Google GenAI model invoker that satisfies the generic
21
21
  * `ModelInvoker<Content>` contract.
22
22
  *
23
- * Loads the conversation thread from Redis, invokes the Gemini model via
24
- * `client.models.generateContent`, and returns a normalised AgentResponse.
23
+ * Internally streams the response and emits Temporal heartbeats on each
24
+ * chunk so that long-running LLM calls remain visible to the scheduler.
25
25
  * The caller is responsible for appending the response to the thread.
26
26
  *
27
27
  * @example
@@ -37,7 +37,7 @@ interface GoogleGenAIModelInvokerConfig {
37
37
  * model: 'gemini-2.5-flash',
38
38
  * });
39
39
  *
40
- * return { runAgent: createRunAgentActivity(client, invoker) };
40
+ * return { ...createRunAgentActivity(client, invoker, "myAgent") };
41
41
  * ```
42
42
  */
43
43
  declare function createGoogleGenAIModelInvoker({ redis, client, model, hooks, }: GoogleGenAIModelInvokerConfig): (config: ModelInvokerConfig) => Promise<AgentResponse<Content>>;
@@ -1,3 +1,5 @@
1
+ import { Context } from '@temporalio/activity';
2
+
1
3
  // src/lib/thread/manager.ts
2
4
  var THREAD_TTL_SECONDS = 60 * 60 * 24 * 90;
3
5
  var APPEND_IDEMPOTENT_SCRIPT = `
@@ -172,6 +174,14 @@ function createGoogleGenAIThreadManager(config) {
172
174
  };
173
175
  return Object.assign(base, helpers);
174
176
  }
177
+ function getActivityContext() {
178
+ try {
179
+ const ctx = Context.current();
180
+ return { heartbeat: () => ctx.heartbeat(), signal: ctx.cancellationSignal };
181
+ } catch {
182
+ return {};
183
+ }
184
+ }
175
185
 
176
186
  // src/adapters/thread/google-genai/model-invoker.ts
177
187
  function toFunctionDeclarations(tools) {
@@ -189,21 +199,32 @@ function createGoogleGenAIModelInvoker({
189
199
  }) {
190
200
  return async function invokeGoogleGenAIModel2(config) {
191
201
  const { threadId, threadKey, state } = config;
202
+ const { heartbeat, signal } = getActivityContext();
192
203
  const thread = createGoogleGenAIThreadManager({ redis, threadId, key: threadKey, hooks });
193
204
  const { contents, systemInstruction } = await thread.prepareForInvocation();
194
205
  const functionDeclarations = toFunctionDeclarations(state.tools);
195
206
  const tools = functionDeclarations.length > 0 ? [{ functionDeclarations }] : void 0;
196
- const response = await client.models.generateContent({
207
+ const stream = await client.models.generateContentStream({
197
208
  model,
198
209
  contents,
199
210
  config: {
200
211
  ...systemInstruction ? { systemInstruction } : {},
201
- ...tools ? { tools } : {}
212
+ ...tools ? { tools } : {},
213
+ abortSignal: signal
202
214
  }
203
215
  });
204
- const responseParts = response.candidates?.[0]?.content?.parts ?? [];
205
- const modelContent = { role: "model", parts: responseParts };
206
- const functionCalls = response.functionCalls ?? [];
216
+ const allParts = [];
217
+ let lastChunk;
218
+ for await (const chunk of stream) {
219
+ lastChunk = chunk;
220
+ allParts.push(...chunk.candidates?.[0]?.content?.parts ?? []);
221
+ heartbeat?.();
222
+ }
223
+ if (!lastChunk) {
224
+ throw new Error("Google GenAI stream ended without producing any chunks");
225
+ }
226
+ const modelContent = { role: "model", parts: allParts };
227
+ const functionCalls = lastChunk.functionCalls ?? [];
207
228
  return {
208
229
  message: modelContent,
209
230
  rawToolCalls: functionCalls.map((fc) => ({
@@ -212,9 +233,9 @@ function createGoogleGenAIModelInvoker({
212
233
  args: fc.args ?? {}
213
234
  })),
214
235
  usage: {
215
- inputTokens: response.usageMetadata?.promptTokenCount,
216
- outputTokens: response.usageMetadata?.candidatesTokenCount,
217
- cachedReadTokens: response.usageMetadata?.cachedContentTokenCount
236
+ inputTokens: lastChunk.usageMetadata?.promptTokenCount,
237
+ outputTokens: lastChunk.usageMetadata?.candidatesTokenCount,
238
+ cachedReadTokens: lastChunk.usageMetadata?.cachedContentTokenCount
218
239
  }
219
240
  };
220
241
  };