zeitlich 0.2.19 → 0.2.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/adapters/sandbox/daytona/index.cjs +25 -10
- package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
- package/dist/adapters/sandbox/daytona/index.d.cts +4 -1
- package/dist/adapters/sandbox/daytona/index.d.ts +4 -1
- package/dist/adapters/sandbox/daytona/index.js +25 -10
- package/dist/adapters/sandbox/daytona/index.js.map +1 -1
- package/dist/adapters/sandbox/virtual/index.d.cts +4 -3
- package/dist/adapters/sandbox/virtual/index.d.ts +4 -3
- package/dist/adapters/thread/google-genai/index.cjs +69 -24
- package/dist/adapters/thread/google-genai/index.cjs.map +1 -1
- package/dist/adapters/thread/google-genai/index.d.cts +10 -10
- package/dist/adapters/thread/google-genai/index.d.ts +10 -10
- package/dist/adapters/thread/google-genai/index.js +69 -24
- package/dist/adapters/thread/google-genai/index.js.map +1 -1
- package/dist/adapters/thread/langchain/index.cjs +76 -69
- package/dist/adapters/thread/langchain/index.cjs.map +1 -1
- package/dist/adapters/thread/langchain/index.d.cts +11 -11
- package/dist/adapters/thread/langchain/index.d.ts +11 -11
- package/dist/adapters/thread/langchain/index.js +76 -69
- package/dist/adapters/thread/langchain/index.js.map +1 -1
- package/dist/index.cjs +198 -118
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +14 -14
- package/dist/index.d.ts +14 -14
- package/dist/index.js +198 -118
- package/dist/index.js.map +1 -1
- package/dist/{queries-D8T4pEeu.d.ts → queries-6Avfh74U.d.ts} +1 -1
- package/dist/{queries-D22uWTOb.d.cts → queries-CHa2iv_I.d.cts} +1 -1
- package/dist/{types-CxWLeJTB.d.ts → types-BkAYmc96.d.ts} +6 -6
- package/dist/{types-CCfJb5Jl.d.cts → types-CES_30qx.d.cts} +6 -6
- package/dist/{types-DjT78Sdp.d.cts → types-YbL7JpEA.d.cts} +4 -2
- package/dist/{types-DjT78Sdp.d.ts → types-YbL7JpEA.d.ts} +4 -2
- package/dist/workflow.cjs +68 -34
- package/dist/workflow.cjs.map +1 -1
- package/dist/workflow.d.cts +16 -12
- package/dist/workflow.d.ts +16 -12
- package/dist/workflow.js +68 -34
- package/dist/workflow.js.map +1 -1
- package/package.json +1 -1
- package/src/adapters/sandbox/daytona/filesystem.ts +21 -12
- package/src/adapters/sandbox/daytona/index.ts +24 -23
- package/src/adapters/thread/google-genai/activities.ts +11 -9
- package/src/adapters/thread/google-genai/model-invoker.ts +6 -11
- package/src/adapters/thread/google-genai/thread-manager.ts +44 -29
- package/src/adapters/thread/langchain/activities.ts +6 -4
- package/src/adapters/thread/langchain/thread-manager.ts +55 -27
- package/src/lib/session/session-edge-cases.integration.test.ts +20 -2
- package/src/lib/session/session.integration.test.ts +16 -2
- package/src/lib/session/session.ts +7 -5
- package/src/lib/session/types.ts +9 -3
- package/src/lib/subagent/handler.ts +1 -1
- package/src/lib/subagent/subagent.integration.test.ts +5 -4
- package/src/lib/subagent/tool.ts +1 -1
- package/src/lib/thread/index.ts +0 -1
- package/src/lib/tool-router/auto-append-sandbox.integration.test.ts +20 -21
- package/src/lib/tool-router/auto-append.ts +3 -2
- package/src/lib/tool-router/router-edge-cases.integration.test.ts +64 -23
- package/src/lib/tool-router/router.integration.test.ts +60 -23
- package/src/lib/tool-router/router.ts +58 -29
- package/src/lib/tool-router/types.ts +12 -7
- package/src/lib/workflow.test.ts +18 -6
- package/src/lib/workflow.ts +13 -3
- package/src/tools/task-create/handler.ts +3 -6
- package/src/workflow.ts +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../node_modules/uuid/dist/esm/stringify.js","../../../../node_modules/uuid/dist/esm/rng.js","../../../../node_modules/uuid/dist/esm/native.js","../../../../node_modules/uuid/dist/esm/v4.js","../../../../src/lib/thread/manager.ts","../../../../src/adapters/thread/langchain/thread-manager.ts","../../../../src/adapters/thread/langchain/model-invoker.ts","../../../../src/adapters/thread/langchain/activities.ts"],"names":["invokeLangChainModel"],"mappings":"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","file":"index.js","sourcesContent":["import validate from './validate.js';\nconst byteToHex = [];\nfor (let i = 0; i < 256; ++i) {\n byteToHex.push((i + 0x100).toString(16).slice(1));\n}\nexport function unsafeStringify(arr, offset = 0) {\n return (byteToHex[arr[offset + 0]] +\n byteToHex[arr[offset + 1]] +\n byteToHex[arr[offset + 2]] +\n byteToHex[arr[offset + 3]] +\n '-' +\n byteToHex[arr[offset + 4]] +\n byteToHex[arr[offset + 5]] +\n '-' +\n byteToHex[arr[offset + 6]] +\n byteToHex[arr[offset + 7]] +\n '-' +\n byteToHex[arr[offset + 8]] +\n byteToHex[arr[offset + 9]] +\n '-' +\n byteToHex[arr[offset + 10]] +\n byteToHex[arr[offset + 11]] +\n byteToHex[arr[offset + 12]] +\n byteToHex[arr[offset + 13]] +\n byteToHex[arr[offset + 14]] +\n byteToHex[arr[offset + 15]]).toLowerCase();\n}\nfunction stringify(arr, offset = 0) {\n const uuid = unsafeStringify(arr, offset);\n if (!validate(uuid)) {\n throw TypeError('Stringified UUID is invalid');\n }\n return uuid;\n}\nexport default stringify;\n","import { randomFillSync } from 'crypto';\nconst rnds8Pool = new Uint8Array(256);\nlet poolPtr = rnds8Pool.length;\nexport default function rng() {\n if (poolPtr > rnds8Pool.length - 16) {\n randomFillSync(rnds8Pool);\n poolPtr = 0;\n }\n return rnds8Pool.slice(poolPtr, (poolPtr += 16));\n}\n","import { randomUUID } from 'crypto';\nexport default { randomUUID };\n","import native from './native.js';\nimport rng from './rng.js';\nimport { unsafeStringify } from './stringify.js';\nfunction v4(options, buf, offset) {\n if (native.randomUUID && !buf && !options) {\n return native.randomUUID();\n }\n options = options || {};\n const rnds = options.random ?? options.rng?.() ?? rng();\n if (rnds.length < 16) {\n throw new Error('Random bytes length must be >= 16');\n }\n rnds[6] = (rnds[6] & 0x0f) | 0x40;\n rnds[8] = (rnds[8] & 0x3f) | 0x80;\n if (buf) {\n offset = offset || 0;\n if (offset < 0 || offset + 16 > buf.length) {\n throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);\n }\n for (let i = 0; i < 16; ++i) {\n buf[offset + i] = rnds[i];\n }\n return buf;\n }\n return unsafeStringify(rnds);\n}\nexport default v4;\n","import type {\n ThreadManagerConfig,\n BaseThreadManager,\n} from \"./types\";\n\nconst THREAD_TTL_SECONDS = 60 * 60 * 24 * 90; // 90 days\n\n/**\n * Lua script for atomic idempotent append.\n * Checks a dedup key; if it exists the message was already appended and we\n * return 0. Otherwise appends all messages to the list, sets TTL on both\n * the list and the dedup key, and returns 1.\n *\n * KEYS[1] = dedup key, KEYS[2] = list key\n * ARGV[1] = TTL seconds, ARGV[2..N] = serialised messages\n */\nconst APPEND_IDEMPOTENT_SCRIPT = `\nif redis.call('EXISTS', KEYS[1]) == 1 then\n return 0\nend\nfor i = 2, #ARGV do\n redis.call('RPUSH', KEYS[2], ARGV[i])\nend\nredis.call('EXPIRE', KEYS[2], tonumber(ARGV[1]))\nredis.call('SET', KEYS[1], '1', 'EX', tonumber(ARGV[1]))\nreturn 1\n`;\n\nfunction getThreadKey(threadId: string, key: string): string {\n return `thread:${threadId}:${key}`;\n}\n\n/**\n * Creates a generic thread manager for handling conversation state in Redis.\n * Framework-agnostic — works with any serializable message type.\n */\nexport function createThreadManager<T>(\n config: ThreadManagerConfig<T>,\n): BaseThreadManager<T> {\n const {\n redis,\n threadId,\n key = \"messages\",\n serialize = (m: T): string => JSON.stringify(m),\n deserialize = (raw: string): T => JSON.parse(raw) as T,\n idOf,\n } = config;\n const redisKey = getThreadKey(threadId, key);\n const metaKey = getThreadKey(threadId, `${key}:meta`);\n\n async function assertThreadExists(): Promise<void> {\n const exists = await redis.exists(metaKey);\n if (!exists) {\n throw new Error(`Thread \"${threadId}\" (key: ${key}) does not exist`);\n }\n }\n\n return {\n async initialize(): Promise<void> {\n await redis.del(redisKey);\n await redis.set(metaKey, \"1\", \"EX\", THREAD_TTL_SECONDS);\n },\n\n async load(): Promise<T[]> {\n await assertThreadExists();\n const data = await redis.lrange(redisKey, 0, -1);\n return data.map(deserialize);\n },\n\n async append(messages: T[]): Promise<void> {\n if (messages.length === 0) return;\n await assertThreadExists();\n\n if (idOf) {\n const dedupId = messages.map(idOf).join(\":\");\n const dedupKey = getThreadKey(threadId, `dedup:${dedupId}`);\n await redis.eval(\n APPEND_IDEMPOTENT_SCRIPT,\n 2,\n dedupKey,\n redisKey,\n String(THREAD_TTL_SECONDS),\n ...messages.map(serialize),\n );\n } else {\n await redis.rpush(redisKey, ...messages.map(serialize));\n await redis.expire(redisKey, THREAD_TTL_SECONDS);\n }\n },\n\n async fork(newThreadId: string): Promise<BaseThreadManager<T>> {\n await assertThreadExists();\n const data = await redis.lrange(redisKey, 0, -1);\n const forked = createThreadManager({\n ...config,\n threadId: newThreadId,\n });\n await forked.initialize();\n if (data.length > 0) {\n const newKey = getThreadKey(newThreadId, key);\n await redis.rpush(newKey, ...data);\n await redis.expire(newKey, THREAD_TTL_SECONDS);\n }\n return forked;\n },\n\n async delete(): Promise<void> {\n await redis.del(redisKey, metaKey);\n },\n };\n}\n","import type Redis from \"ioredis\";\nimport {\n type $InferMessageContent,\n AIMessage,\n HumanMessage,\n type MessageContent,\n type MessageStructure,\n type StoredMessage,\n SystemMessage,\n ToolMessage,\n} from \"@langchain/core/messages\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport {\n createThreadManager,\n type BaseThreadManager,\n type ThreadManagerConfig,\n} from \"../../../lib/thread\";\n\nexport type LangChainToolMessageContent = $InferMessageContent<\n MessageStructure,\n \"tool\"\n>;\n\nexport interface LangChainThreadManagerConfig {\n redis: Redis;\n threadId: string;\n /** Thread key, defaults to 'messages' */\n key?: string;\n}\n\n/** Thread manager with LangChain StoredMessage convenience helpers */\nexport interface LangChainThreadManager extends BaseThreadManager<StoredMessage> {\n createHumanMessage(content: string | MessageContent): StoredMessage;\n createSystemMessage(content: string): StoredMessage;\n createAIMessage(\n content: string | MessageContent,\n kwargs?: { header?: string; options?: string[]; multiSelect?: boolean },\n ): StoredMessage;\n createToolMessage(\n content: LangChainToolMessageContent,\n toolCallId: string,\n ): StoredMessage;\n appendHumanMessage(content: string | MessageContent): Promise<void>;\n appendSystemMessage(content: string): Promise<void>;\n appendToolMessage(\n content: LangChainToolMessageContent,\n toolCallId: string,\n ): Promise<void>;\n appendAIMessage(content: string | MessageContent): Promise<void>;\n}\n\nfunction storedMessageId(msg: StoredMessage): string {\n return msg.data.id ?? \"\";\n}\n\n/**\n * Creates a LangChain-specific thread manager that stores StoredMessage\n * instances in Redis and provides convenience helpers for creating and\n * appending typed LangChain messages.\n */\nexport function createLangChainThreadManager(\n config: LangChainThreadManagerConfig,\n): LangChainThreadManager {\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 = {\n createHumanMessage(content: string | MessageContent): StoredMessage {\n return new HumanMessage({\n id: uuidv4(),\n content: content as string,\n }).toDict();\n },\n\n createSystemMessage(content: string): StoredMessage {\n return new SystemMessage({\n id: uuidv4(),\n content: content as string,\n }).toDict();\n },\n\n createAIMessage(\n content: string,\n kwargs?: { header?: string; options?: string[]; multiSelect?: boolean },\n ): StoredMessage {\n return new AIMessage({\n id: uuidv4(),\n content,\n additional_kwargs: kwargs\n ? {\n header: kwargs.header,\n options: kwargs.options,\n multiSelect: kwargs.multiSelect,\n }\n : undefined,\n }).toDict();\n },\n\n createToolMessage(\n content: LangChainToolMessageContent,\n toolCallId: string,\n ): StoredMessage {\n return new ToolMessage({\n id: uuidv4(),\n content: content as MessageContent,\n tool_call_id: toolCallId,\n }).toDict();\n },\n\n async appendHumanMessage(content: string | MessageContent): Promise<void> {\n const message = helpers.createHumanMessage(content);\n await base.append([message]);\n },\n\n async appendToolMessage(\n content: LangChainToolMessageContent,\n toolCallId: string,\n ): Promise<void> {\n const message = helpers.createToolMessage(content, toolCallId);\n await base.append([message]);\n },\n\n async appendAIMessage(content: string | MessageContent): Promise<void> {\n const message = helpers.createAIMessage(content as string);\n await base.append([message]);\n },\n\n async appendSystemMessage(content: string): Promise<void> {\n const message = helpers.createSystemMessage(content);\n await base.initialize();\n await base.append([message]);\n },\n };\n\n return Object.assign(base, helpers);\n}\n","import type Redis from \"ioredis\";\nimport type { AgentResponse } from \"../../../lib/model\";\nimport type { ModelInvokerConfig } from \"../../../lib/model\";\nimport { mapStoredMessagesToChatMessages } from \"@langchain/core/messages\";\nimport type { StoredMessage } from \"@langchain/core/messages\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport { createLangChainThreadManager } from \"./thread-manager\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface LangChainModelInvokerConfig<TModel extends BaseChatModel<any> = BaseChatModel<any>> {\n redis: Redis;\n model: TModel;\n}\n\n/**\n * Creates a LangChain-based model invoker that satisfies the generic\n * `ModelInvoker<StoredMessage>` contract.\n *\n * Loads the conversation thread from Redis, invokes a LangChain chat model,\n * appends the AI response, and returns a normalised AgentResponse.\n *\n * @example\n * ```typescript\n * import { createLangChainModelInvoker } from 'zeitlich/adapters/thread/langchain';\n * import { createRunAgentActivity } from 'zeitlich';\n * import { ChatAnthropic } from '@langchain/anthropic';\n *\n * const model = new ChatAnthropic({ model: \"claude-sonnet-4-6\" });\n * const invoker = createLangChainModelInvoker({ redis, model });\n *\n * return { runAgent: createRunAgentActivity(client, invoker) };\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function createLangChainModelInvoker<TModel extends BaseChatModel<any> = BaseChatModel<any>>(\n { redis, model }: LangChainModelInvokerConfig<TModel>,\n) {\n return async function invokeLangChainModel(\n config: ModelInvokerConfig\n ): Promise<AgentResponse<StoredMessage>> {\n const { threadId, agentName, state, metadata } = config;\n\n const thread = createLangChainThreadManager({ redis, threadId });\n const runId = uuidv4();\n\n const messages = await thread.load();\n const response = await model.invoke(\n [...mapStoredMessagesToChatMessages(messages)],\n {\n runName: agentName,\n runId,\n metadata: { thread_id: `${agentName}-${threadId}`, ...metadata },\n tools: state.tools,\n }\n );\n\n await thread.append([response.toDict()]);\n\n const toolCalls = response.tool_calls ?? [];\n\n return {\n message: response.toDict(),\n rawToolCalls: toolCalls.map((tc) => ({\n id: tc.id,\n name: tc.name,\n args: tc.args,\n })),\n usage: {\n inputTokens: response.usage_metadata?.input_tokens,\n outputTokens: response.usage_metadata?.output_tokens,\n reasonTokens: response.usage_metadata?.output_token_details?.reasoning,\n cachedWriteTokens:\n response.usage_metadata?.input_token_details?.cache_creation,\n cachedReadTokens:\n response.usage_metadata?.input_token_details?.cache_read,\n },\n };\n };\n}\n\n/**\n * Standalone function for one-shot LangChain model invocation.\n * Convenience wrapper around createLangChainModelInvoker for cases where\n * you don't need to reuse the invoker.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function invokeLangChainModel<TModel extends BaseChatModel<any> = BaseChatModel<any>>({\n redis,\n model,\n config,\n}: {\n redis: Redis;\n config: ModelInvokerConfig;\n model: TModel;\n}): Promise<AgentResponse<StoredMessage>> {\n const invoker = createLangChainModelInvoker({ redis, model });\n return invoker(config);\n}\n","import type Redis from \"ioredis\";\nimport type { ToolResultConfig } from \"../../../lib/types\";\nimport type { MessageContent } from \"@langchain/core/messages\";\nimport type { ThreadOps } from \"../../../lib/session/types\";\nimport type { ModelInvoker } from \"../../../lib/model\";\nimport type { StoredMessage } from \"@langchain/core/messages\";\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport { createLangChainThreadManager } from \"./thread-manager\";\nimport { createLangChainModelInvoker } from \"./model-invoker\";\n\nexport interface LangChainAdapterConfig {\n redis: Redis;\n /** Optional default model — if omitted, use `createModelInvoker()` to create invokers later */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n model?: BaseChatModel<any>;\n}\n\nexport interface LangChainAdapter {\n /** Thread operations (register these as Temporal activities on the worker) */\n threadOps: ThreadOps;\n /** Model invoker using the default model (only available when `model` was provided) */\n invoker: ModelInvoker<StoredMessage>;\n /** Create an invoker for a specific model (for multi-model setups) */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n createModelInvoker(model: BaseChatModel<any>): ModelInvoker<StoredMessage>;\n}\n\n/**\n * Creates a LangChain adapter that bundles thread operations and model\n * invocation using a consistent message format (StoredMessage).\n *\n * The returned `threadOps` should be registered as Temporal activities on\n * the worker. The `invoker` (or invokers created via `createModelInvoker`)\n * should be wrapped with `createRunAgentActivity` for per-agent activities.\n *\n * @example\n * ```typescript\n * import { createLangChainAdapter } from 'zeitlich/adapters/thread/langchain';\n * import { createRunAgentActivity } from 'zeitlich';\n *\n * const adapter = createLangChainAdapter({ redis, model });\n *\n * export function createActivities(client: WorkflowClient) {\n * return {\n * ...adapter.threadOps,\n * runAgent: createRunAgentActivity(client, adapter.invoker),\n * };\n * }\n * ```\n *\n * @example Multi-model setup\n * ```typescript\n * const adapter = createLangChainAdapter({ redis });\n *\n * export function createActivities(client: WorkflowClient) {\n * return {\n * ...adapter.threadOps,\n * runResearchAgent: createRunAgentActivity(client, adapter.createModelInvoker(claude)),\n * runWriterAgent: createRunAgentActivity(client, adapter.createModelInvoker(gpt4)),\n * };\n * }\n * ```\n */\nexport function createLangChainAdapter(\n config: LangChainAdapterConfig\n): LangChainAdapter {\n const { redis } = config;\n\n const threadOps: ThreadOps = {\n async initializeThread(threadId: string): Promise<void> {\n const thread = createLangChainThreadManager({ redis, threadId });\n await thread.initialize();\n },\n\n async appendHumanMessage(\n threadId: string,\n content: string | MessageContent\n ): Promise<void> {\n const thread = createLangChainThreadManager({ redis, threadId });\n await thread.appendHumanMessage(content);\n },\n\n async appendSystemMessage(\n threadId: string,\n content: string\n ): Promise<void> {\n const thread = createLangChainThreadManager({ redis, threadId });\n await thread.appendSystemMessage(content);\n },\n\n async appendToolResult(cfg: ToolResultConfig): Promise<void> {\n const { threadId, toolCallId, content } = cfg;\n const thread = createLangChainThreadManager({ redis, threadId });\n await thread.appendToolMessage(content, toolCallId);\n },\n\n async forkThread(\n sourceThreadId: string,\n targetThreadId: string\n ): Promise<void> {\n const thread = createLangChainThreadManager({\n redis,\n threadId: sourceThreadId,\n });\n await thread.fork(targetThreadId);\n },\n };\n\n const makeInvoker = (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n model: BaseChatModel<any>\n ): ModelInvoker<StoredMessage> =>\n createLangChainModelInvoker({ redis, model });\n\n const invoker: ModelInvoker<StoredMessage> = config.model\n ? makeInvoker(config.model)\n : () => {\n throw new Error(\n \"No default model provided to createLangChainAdapter. \" +\n \"Either pass `model` in the config or use `createModelInvoker(model)` instead.\"\n );\n };\n\n return {\n threadOps,\n invoker,\n createModelInvoker: makeInvoker,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../../src/lib/thread/manager.ts","../../../../src/adapters/thread/langchain/thread-manager.ts","../../../../node_modules/uuid/dist/esm/stringify.js","../../../../node_modules/uuid/dist/esm/rng.js","../../../../node_modules/uuid/dist/esm/native.js","../../../../node_modules/uuid/dist/esm/v4.js","../../../../src/adapters/thread/langchain/model-invoker.ts","../../../../src/adapters/thread/langchain/activities.ts"],"names":["invokeLangChainModel"],"mappings":"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","file":"index.js","sourcesContent":["import type {\n ThreadManagerConfig,\n BaseThreadManager,\n} from \"./types\";\n\nconst THREAD_TTL_SECONDS = 60 * 60 * 24 * 90; // 90 days\n\n/**\n * Lua script for atomic idempotent append.\n * Checks a dedup key; if it exists the message was already appended and we\n * return 0. Otherwise appends all messages to the list, sets TTL on both\n * the list and the dedup key, and returns 1.\n *\n * KEYS[1] = dedup key, KEYS[2] = list key\n * ARGV[1] = TTL seconds, ARGV[2..N] = serialised messages\n */\nconst APPEND_IDEMPOTENT_SCRIPT = `\nif redis.call('EXISTS', KEYS[1]) == 1 then\n return 0\nend\nfor i = 2, #ARGV do\n redis.call('RPUSH', KEYS[2], ARGV[i])\nend\nredis.call('EXPIRE', KEYS[2], tonumber(ARGV[1]))\nredis.call('SET', KEYS[1], '1', 'EX', tonumber(ARGV[1]))\nreturn 1\n`;\n\nfunction getThreadKey(threadId: string, key: string): string {\n return `thread:${threadId}:${key}`;\n}\n\n/**\n * Creates a generic thread manager for handling conversation state in Redis.\n * Framework-agnostic — works with any serializable message type.\n */\nexport function createThreadManager<T>(\n config: ThreadManagerConfig<T>,\n): BaseThreadManager<T> {\n const {\n redis,\n threadId,\n key = \"messages\",\n serialize = (m: T): string => JSON.stringify(m),\n deserialize = (raw: string): T => JSON.parse(raw) as T,\n idOf,\n } = config;\n const redisKey = getThreadKey(threadId, key);\n const metaKey = getThreadKey(threadId, `${key}:meta`);\n\n async function assertThreadExists(): Promise<void> {\n const exists = await redis.exists(metaKey);\n if (!exists) {\n throw new Error(`Thread \"${threadId}\" (key: ${key}) does not exist`);\n }\n }\n\n return {\n async initialize(): Promise<void> {\n await redis.del(redisKey);\n await redis.set(metaKey, \"1\", \"EX\", THREAD_TTL_SECONDS);\n },\n\n async load(): Promise<T[]> {\n await assertThreadExists();\n const data = await redis.lrange(redisKey, 0, -1);\n return data.map(deserialize);\n },\n\n async append(messages: T[]): Promise<void> {\n if (messages.length === 0) return;\n await assertThreadExists();\n\n if (idOf) {\n const dedupId = messages.map(idOf).join(\":\");\n const dedupKey = getThreadKey(threadId, `dedup:${dedupId}`);\n await redis.eval(\n APPEND_IDEMPOTENT_SCRIPT,\n 2,\n dedupKey,\n redisKey,\n String(THREAD_TTL_SECONDS),\n ...messages.map(serialize),\n );\n } else {\n await redis.rpush(redisKey, ...messages.map(serialize));\n await redis.expire(redisKey, THREAD_TTL_SECONDS);\n }\n },\n\n async fork(newThreadId: string): Promise<BaseThreadManager<T>> {\n await assertThreadExists();\n const data = await redis.lrange(redisKey, 0, -1);\n const forked = createThreadManager({\n ...config,\n threadId: newThreadId,\n });\n await forked.initialize();\n if (data.length > 0) {\n const newKey = getThreadKey(newThreadId, key);\n await redis.rpush(newKey, ...data);\n await redis.expire(newKey, THREAD_TTL_SECONDS);\n }\n return forked;\n },\n\n async delete(): Promise<void> {\n await redis.del(redisKey, metaKey);\n },\n };\n}\n","import type Redis from \"ioredis\";\nimport {\n type $InferMessageContent,\n AIMessage,\n HumanMessage,\n type MessageContent,\n type MessageStructure,\n type StoredMessage,\n SystemMessage,\n ToolMessage,\n} from \"@langchain/core/messages\";\nimport {\n createThreadManager,\n type BaseThreadManager,\n type ThreadManagerConfig,\n} from \"../../../lib/thread\";\n\nexport type LangChainToolMessageContent = $InferMessageContent<\n MessageStructure,\n \"tool\"\n>;\n\nexport interface LangChainThreadManagerConfig {\n redis: Redis;\n threadId: string;\n /** Thread key, defaults to 'messages' */\n key?: string;\n}\n\n/** Thread manager with LangChain StoredMessage convenience helpers */\nexport interface LangChainThreadManager extends BaseThreadManager<StoredMessage> {\n createHumanMessage(\n id: string,\n content: string | MessageContent\n ): StoredMessage;\n createSystemMessage(id: string, content: string): StoredMessage;\n createAIMessage(\n id: string,\n content: string | MessageContent,\n kwargs?: { header?: string; options?: string[]; multiSelect?: boolean }\n ): StoredMessage;\n createToolMessage(\n id: string,\n content: LangChainToolMessageContent,\n toolCallId: string\n ): StoredMessage;\n appendHumanMessage(\n id: string,\n content: string | MessageContent\n ): Promise<void>;\n appendSystemMessage(id: string, content: string): Promise<void>;\n appendToolMessage(\n id: string,\n content: LangChainToolMessageContent,\n toolCallId: string\n ): Promise<void>;\n appendAIMessage(id: string, content: string | MessageContent): Promise<void>;\n}\n\nfunction storedMessageId(msg: StoredMessage): string {\n if (msg.type === \"tool\" && msg.data.tool_call_id) {\n return msg.data.tool_call_id;\n }\n\n if (msg.data.id) {\n return msg.data.id;\n }\n\n throw new Error(\"No id found for message\");\n}\n\n/**\n * Creates a LangChain-specific thread manager that stores StoredMessage\n * instances in Redis and provides convenience helpers for creating and\n * appending typed LangChain messages.\n */\nexport function createLangChainThreadManager(\n config: LangChainThreadManagerConfig\n): LangChainThreadManager {\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 = {\n createHumanMessage(\n id: string,\n content: string | MessageContent\n ): StoredMessage {\n return new HumanMessage({\n id,\n content: content as string,\n }).toDict();\n },\n\n createSystemMessage(id: string, content: string): StoredMessage {\n return new SystemMessage({\n id,\n content: content as string,\n }).toDict();\n },\n\n createAIMessage(\n id: string,\n content: string,\n kwargs?: { header?: string; options?: string[]; multiSelect?: boolean }\n ): StoredMessage {\n return new AIMessage({\n id,\n content,\n additional_kwargs: kwargs\n ? {\n header: kwargs.header,\n options: kwargs.options,\n multiSelect: kwargs.multiSelect,\n }\n : undefined,\n }).toDict();\n },\n\n createToolMessage(\n id: string,\n content: LangChainToolMessageContent,\n toolCallId: string\n ): StoredMessage {\n return new ToolMessage({\n id,\n content: content as MessageContent,\n tool_call_id: toolCallId,\n }).toDict();\n },\n\n async appendHumanMessage(\n id: string,\n content: string | MessageContent\n ): Promise<void> {\n const message = helpers.createHumanMessage(id, content);\n await base.append([message]);\n },\n\n async appendToolMessage(\n id: string,\n content: LangChainToolMessageContent,\n toolCallId: string\n ): Promise<void> {\n const message = helpers.createToolMessage(id, content, toolCallId);\n await base.append([message]);\n },\n\n async appendAIMessage(\n id: string,\n content: string | MessageContent\n ): Promise<void> {\n const message = helpers.createAIMessage(id, content as string);\n await base.append([message]);\n },\n\n async appendSystemMessage(id: string, content: string): Promise<void> {\n const message = helpers.createSystemMessage(id, content);\n await base.initialize();\n await base.append([message]);\n },\n };\n\n return Object.assign(base, helpers);\n}\n","import validate from './validate.js';\nconst byteToHex = [];\nfor (let i = 0; i < 256; ++i) {\n byteToHex.push((i + 0x100).toString(16).slice(1));\n}\nexport function unsafeStringify(arr, offset = 0) {\n return (byteToHex[arr[offset + 0]] +\n byteToHex[arr[offset + 1]] +\n byteToHex[arr[offset + 2]] +\n byteToHex[arr[offset + 3]] +\n '-' +\n byteToHex[arr[offset + 4]] +\n byteToHex[arr[offset + 5]] +\n '-' +\n byteToHex[arr[offset + 6]] +\n byteToHex[arr[offset + 7]] +\n '-' +\n byteToHex[arr[offset + 8]] +\n byteToHex[arr[offset + 9]] +\n '-' +\n byteToHex[arr[offset + 10]] +\n byteToHex[arr[offset + 11]] +\n byteToHex[arr[offset + 12]] +\n byteToHex[arr[offset + 13]] +\n byteToHex[arr[offset + 14]] +\n byteToHex[arr[offset + 15]]).toLowerCase();\n}\nfunction stringify(arr, offset = 0) {\n const uuid = unsafeStringify(arr, offset);\n if (!validate(uuid)) {\n throw TypeError('Stringified UUID is invalid');\n }\n return uuid;\n}\nexport default stringify;\n","import { randomFillSync } from 'crypto';\nconst rnds8Pool = new Uint8Array(256);\nlet poolPtr = rnds8Pool.length;\nexport default function rng() {\n if (poolPtr > rnds8Pool.length - 16) {\n randomFillSync(rnds8Pool);\n poolPtr = 0;\n }\n return rnds8Pool.slice(poolPtr, (poolPtr += 16));\n}\n","import { randomUUID } from 'crypto';\nexport default { randomUUID };\n","import native from './native.js';\nimport rng from './rng.js';\nimport { unsafeStringify } from './stringify.js';\nfunction v4(options, buf, offset) {\n if (native.randomUUID && !buf && !options) {\n return native.randomUUID();\n }\n options = options || {};\n const rnds = options.random ?? options.rng?.() ?? rng();\n if (rnds.length < 16) {\n throw new Error('Random bytes length must be >= 16');\n }\n rnds[6] = (rnds[6] & 0x0f) | 0x40;\n rnds[8] = (rnds[8] & 0x3f) | 0x80;\n if (buf) {\n offset = offset || 0;\n if (offset < 0 || offset + 16 > buf.length) {\n throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);\n }\n for (let i = 0; i < 16; ++i) {\n buf[offset + i] = rnds[i];\n }\n return buf;\n }\n return unsafeStringify(rnds);\n}\nexport default v4;\n","import type Redis from \"ioredis\";\nimport type { AgentResponse } from \"../../../lib/model\";\nimport type { ModelInvokerConfig } from \"../../../lib/model\";\nimport { mapStoredMessagesToChatMessages } from \"@langchain/core/messages\";\nimport type { StoredMessage } from \"@langchain/core/messages\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport { createLangChainThreadManager } from \"./thread-manager\";\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport interface LangChainModelInvokerConfig<TModel extends BaseChatModel<any> = BaseChatModel<any>> {\n redis: Redis;\n model: TModel;\n}\n\n/**\n * Creates a LangChain-based model invoker that satisfies the generic\n * `ModelInvoker<StoredMessage>` contract.\n *\n * Loads the conversation thread from Redis, invokes a LangChain chat model,\n * appends the AI response, and returns a normalised AgentResponse.\n *\n * @example\n * ```typescript\n * import { createLangChainModelInvoker } from 'zeitlich/adapters/thread/langchain';\n * import { createRunAgentActivity } from 'zeitlich';\n * import { ChatAnthropic } from '@langchain/anthropic';\n *\n * const model = new ChatAnthropic({ model: \"claude-sonnet-4-6\" });\n * const invoker = createLangChainModelInvoker({ redis, model });\n *\n * return { runAgent: createRunAgentActivity(client, invoker) };\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function createLangChainModelInvoker<TModel extends BaseChatModel<any> = BaseChatModel<any>>(\n { redis, model }: LangChainModelInvokerConfig<TModel>,\n) {\n return async function invokeLangChainModel(\n config: ModelInvokerConfig\n ): Promise<AgentResponse<StoredMessage>> {\n const { threadId, agentName, state, metadata } = config;\n\n const thread = createLangChainThreadManager({ redis, threadId });\n const runId = uuidv4();\n\n const messages = await thread.load();\n const response = await model.invoke(\n [...mapStoredMessagesToChatMessages(messages)],\n {\n runName: agentName,\n runId,\n metadata: { thread_id: `${agentName}-${threadId}`, ...metadata },\n tools: state.tools,\n }\n );\n\n await thread.append([response.toDict()]);\n\n const toolCalls = response.tool_calls ?? [];\n\n return {\n message: response.toDict(),\n rawToolCalls: toolCalls.map((tc) => ({\n id: tc.id,\n name: tc.name,\n args: tc.args,\n })),\n usage: {\n inputTokens: response.usage_metadata?.input_tokens,\n outputTokens: response.usage_metadata?.output_tokens,\n reasonTokens: response.usage_metadata?.output_token_details?.reasoning,\n cachedWriteTokens:\n response.usage_metadata?.input_token_details?.cache_creation,\n cachedReadTokens:\n response.usage_metadata?.input_token_details?.cache_read,\n },\n };\n };\n}\n\n/**\n * Standalone function for one-shot LangChain model invocation.\n * Convenience wrapper around createLangChainModelInvoker for cases where\n * you don't need to reuse the invoker.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport async function invokeLangChainModel<TModel extends BaseChatModel<any> = BaseChatModel<any>>({\n redis,\n model,\n config,\n}: {\n redis: Redis;\n config: ModelInvokerConfig;\n model: TModel;\n}): Promise<AgentResponse<StoredMessage>> {\n const invoker = createLangChainModelInvoker({ redis, model });\n return invoker(config);\n}\n","import type Redis from \"ioredis\";\nimport type { ToolResultConfig } from \"../../../lib/types\";\nimport type { MessageContent } from \"@langchain/core/messages\";\nimport type { ThreadOps } from \"../../../lib/session/types\";\nimport type { ModelInvoker } from \"../../../lib/model\";\nimport type { StoredMessage } from \"@langchain/core/messages\";\nimport type { BaseChatModel } from \"@langchain/core/language_models/chat_models\";\nimport { createLangChainThreadManager } from \"./thread-manager\";\nimport { createLangChainModelInvoker } from \"./model-invoker\";\n\nexport interface LangChainAdapterConfig {\n redis: Redis;\n /** Optional default model — if omitted, use `createModelInvoker()` to create invokers later */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n model?: BaseChatModel<any>;\n}\n\nexport interface LangChainAdapter {\n /** Thread operations (register these as Temporal activities on the worker) */\n threadOps: ThreadOps;\n /** Model invoker using the default model (only available when `model` was provided) */\n invoker: ModelInvoker<StoredMessage>;\n /** Create an invoker for a specific model (for multi-model setups) */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n createModelInvoker(model: BaseChatModel<any>): ModelInvoker<StoredMessage>;\n}\n\n/**\n * Creates a LangChain adapter that bundles thread operations and model\n * invocation using a consistent message format (StoredMessage).\n *\n * The returned `threadOps` should be registered as Temporal activities on\n * the worker. The `invoker` (or invokers created via `createModelInvoker`)\n * should be wrapped with `createRunAgentActivity` for per-agent activities.\n *\n * @example\n * ```typescript\n * import { createLangChainAdapter } from 'zeitlich/adapters/thread/langchain';\n * import { createRunAgentActivity } from 'zeitlich';\n *\n * const adapter = createLangChainAdapter({ redis, model });\n *\n * export function createActivities(client: WorkflowClient) {\n * return {\n * ...adapter.threadOps,\n * runAgent: createRunAgentActivity(client, adapter.invoker),\n * };\n * }\n * ```\n *\n * @example Multi-model setup\n * ```typescript\n * const adapter = createLangChainAdapter({ redis });\n *\n * export function createActivities(client: WorkflowClient) {\n * return {\n * ...adapter.threadOps,\n * runResearchAgent: createRunAgentActivity(client, adapter.createModelInvoker(claude)),\n * runWriterAgent: createRunAgentActivity(client, adapter.createModelInvoker(gpt4)),\n * };\n * }\n * ```\n */\nexport function createLangChainAdapter(\n config: LangChainAdapterConfig\n): LangChainAdapter {\n const { redis } = config;\n\n const threadOps: ThreadOps = {\n async initializeThread(threadId: string): Promise<void> {\n const thread = createLangChainThreadManager({ redis, threadId });\n await thread.initialize();\n },\n\n async appendHumanMessage(\n threadId: string,\n id: string,\n content: string | MessageContent\n ): Promise<void> {\n const thread = createLangChainThreadManager({ redis, threadId });\n await thread.appendHumanMessage(id, content);\n },\n\n async appendSystemMessage(\n threadId: string,\n id: string,\n content: string\n ): Promise<void> {\n const thread = createLangChainThreadManager({ redis, threadId });\n await thread.appendSystemMessage(id, content);\n },\n\n async appendToolResult(id: string, cfg: ToolResultConfig): Promise<void> {\n const { threadId, toolCallId, content } = cfg;\n const thread = createLangChainThreadManager({ redis, threadId });\n await thread.appendToolMessage(id, content, toolCallId);\n },\n\n async forkThread(\n sourceThreadId: string,\n targetThreadId: string\n ): Promise<void> {\n const thread = createLangChainThreadManager({\n redis,\n threadId: sourceThreadId,\n });\n await thread.fork(targetThreadId);\n },\n };\n\n const makeInvoker = (\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n model: BaseChatModel<any>\n ): ModelInvoker<StoredMessage> =>\n createLangChainModelInvoker({ redis, model });\n\n const invoker: ModelInvoker<StoredMessage> = config.model\n ? makeInvoker(config.model)\n : () => {\n throw new Error(\n \"No default model provided to createLangChainAdapter. \" +\n \"Either pass `model` in the config or use `createModelInvoker(model)` instead.\"\n );\n };\n\n return {\n threadOps,\n invoker,\n createModelInvoker: makeInvoker,\n };\n}\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
var workflow = require('@temporalio/workflow');
|
|
4
4
|
var z14 = require('zod');
|
|
5
|
+
var crypto = require('crypto');
|
|
5
6
|
var common = require('@temporalio/common');
|
|
6
7
|
var path = require('path');
|
|
7
8
|
var activity = require('@temporalio/activity');
|
|
@@ -59,7 +60,10 @@ function createToolRouter(options) {
|
|
|
59
60
|
turn
|
|
60
61
|
});
|
|
61
62
|
if (r?.fallbackContent !== void 0)
|
|
62
|
-
return {
|
|
63
|
+
return {
|
|
64
|
+
content: r.fallbackContent,
|
|
65
|
+
result: { error: errorStr, recovered: true }
|
|
66
|
+
};
|
|
63
67
|
if (r?.suppress)
|
|
64
68
|
return {
|
|
65
69
|
content: JSON.stringify({ error: errorStr, suppressed: true }),
|
|
@@ -74,7 +78,10 @@ function createToolRouter(options) {
|
|
|
74
78
|
turn
|
|
75
79
|
});
|
|
76
80
|
if (r?.fallbackContent !== void 0)
|
|
77
|
-
return {
|
|
81
|
+
return {
|
|
82
|
+
content: r.fallbackContent,
|
|
83
|
+
result: { error: errorStr, recovered: true }
|
|
84
|
+
};
|
|
78
85
|
if (r?.suppress)
|
|
79
86
|
return {
|
|
80
87
|
content: JSON.stringify({ error: errorStr, suppressed: true }),
|
|
@@ -108,11 +115,14 @@ function createToolRouter(options) {
|
|
|
108
115
|
const tool = toolMap.get(toolCall.name);
|
|
109
116
|
const preResult = await runPreHooks(toolCall, tool, turn);
|
|
110
117
|
if (preResult.skip) {
|
|
111
|
-
await appendToolResult({
|
|
118
|
+
await appendToolResult(workflow.uuid4(), {
|
|
112
119
|
threadId: options.threadId,
|
|
113
120
|
toolCallId: toolCall.id,
|
|
114
121
|
toolName: toolCall.name,
|
|
115
|
-
content: JSON.stringify({
|
|
122
|
+
content: JSON.stringify({
|
|
123
|
+
skipped: true,
|
|
124
|
+
reason: "Skipped by PreToolUse hook"
|
|
125
|
+
})
|
|
116
126
|
});
|
|
117
127
|
return null;
|
|
118
128
|
}
|
|
@@ -140,24 +150,43 @@ function createToolRouter(options) {
|
|
|
140
150
|
content = JSON.stringify(result, null, 2);
|
|
141
151
|
}
|
|
142
152
|
} catch (error) {
|
|
143
|
-
const recovery = await runFailureHooks(
|
|
153
|
+
const recovery = await runFailureHooks(
|
|
154
|
+
toolCall,
|
|
155
|
+
tool,
|
|
156
|
+
error,
|
|
157
|
+
effectiveArgs,
|
|
158
|
+
turn
|
|
159
|
+
);
|
|
144
160
|
result = recovery.result;
|
|
145
161
|
content = recovery.content;
|
|
146
162
|
}
|
|
147
163
|
if (!resultAppended) {
|
|
148
|
-
|
|
164
|
+
const config = {
|
|
149
165
|
threadId: options.threadId,
|
|
150
166
|
toolCallId: toolCall.id,
|
|
151
167
|
toolName: toolCall.name,
|
|
152
168
|
content
|
|
153
|
-
}
|
|
169
|
+
};
|
|
170
|
+
await appendToolResult.executeWithOptions(
|
|
171
|
+
{
|
|
172
|
+
summary: `Append ${toolCall.name} result`
|
|
173
|
+
},
|
|
174
|
+
[workflow.uuid4(), config]
|
|
175
|
+
);
|
|
154
176
|
}
|
|
155
177
|
const toolResult = {
|
|
156
178
|
toolCallId: toolCall.id,
|
|
157
179
|
name: toolCall.name,
|
|
158
180
|
data: result
|
|
159
181
|
};
|
|
160
|
-
await runPostHooks(
|
|
182
|
+
await runPostHooks(
|
|
183
|
+
toolCall,
|
|
184
|
+
tool,
|
|
185
|
+
toolResult,
|
|
186
|
+
effectiveArgs,
|
|
187
|
+
turn,
|
|
188
|
+
Date.now() - startTime
|
|
189
|
+
);
|
|
161
190
|
return toolResult;
|
|
162
191
|
}
|
|
163
192
|
return {
|
|
@@ -200,9 +229,7 @@ function createToolRouter(options) {
|
|
|
200
229
|
const sandboxId = context?.sandboxId;
|
|
201
230
|
if (options.parallel) {
|
|
202
231
|
const results2 = await Promise.all(
|
|
203
|
-
toolCalls.map(
|
|
204
|
-
(tc) => processToolCall(tc, turn, sandboxId)
|
|
205
|
-
)
|
|
232
|
+
toolCalls.map((tc) => processToolCall(tc, turn, sandboxId))
|
|
206
233
|
);
|
|
207
234
|
return results2.filter(
|
|
208
235
|
(r) => r !== null
|
|
@@ -210,11 +237,7 @@ function createToolRouter(options) {
|
|
|
210
237
|
}
|
|
211
238
|
const results = [];
|
|
212
239
|
for (const toolCall of toolCalls) {
|
|
213
|
-
const result = await processToolCall(
|
|
214
|
-
toolCall,
|
|
215
|
-
turn,
|
|
216
|
-
sandboxId
|
|
217
|
-
);
|
|
240
|
+
const result = await processToolCall(toolCall, turn, sandboxId);
|
|
218
241
|
if (result !== null) {
|
|
219
242
|
results.push(result);
|
|
220
243
|
}
|
|
@@ -231,19 +254,29 @@ function createToolRouter(options) {
|
|
|
231
254
|
threadId: options.threadId,
|
|
232
255
|
toolCallId: toolCall.id,
|
|
233
256
|
toolName: toolCall.name,
|
|
234
|
-
...context?.sandboxId !== void 0 && {
|
|
257
|
+
...context?.sandboxId !== void 0 && {
|
|
258
|
+
sandboxId: context.sandboxId
|
|
259
|
+
}
|
|
235
260
|
};
|
|
236
261
|
const response = await handler(
|
|
237
262
|
toolCall.args,
|
|
238
263
|
routerContext
|
|
239
264
|
);
|
|
240
265
|
if (!response.resultAppended) {
|
|
241
|
-
await appendToolResult(
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
266
|
+
await appendToolResult.executeWithOptions(
|
|
267
|
+
{
|
|
268
|
+
summary: `Append ${toolCall.name} result`
|
|
269
|
+
},
|
|
270
|
+
[
|
|
271
|
+
workflow.uuid4(),
|
|
272
|
+
{
|
|
273
|
+
threadId: options.threadId,
|
|
274
|
+
toolCallId: toolCall.id,
|
|
275
|
+
toolName: toolCall.name,
|
|
276
|
+
content: response.toolResponse
|
|
277
|
+
}
|
|
278
|
+
]
|
|
279
|
+
);
|
|
247
280
|
}
|
|
248
281
|
return {
|
|
249
282
|
toolCallId: toolCall.id,
|
|
@@ -318,7 +351,7 @@ function createSubagentTool(subagents) {
|
|
|
318
351
|
const schema = hasThreadContinuation ? z14__default.default.object({
|
|
319
352
|
...baseFields,
|
|
320
353
|
threadId: z14__default.default.string().nullable().describe(
|
|
321
|
-
"Thread ID to continue an existing conversation, or null to start a new one"
|
|
354
|
+
"Thread ID to continue an existing conversation from the same subagent, or null to start a new one"
|
|
322
355
|
)
|
|
323
356
|
}) : z14__default.default.object(baseFields);
|
|
324
357
|
return {
|
|
@@ -375,7 +408,7 @@ function createSubagentHandler(subagents) {
|
|
|
375
408
|
if (config.allowThreadContinuation && childThreadId) {
|
|
376
409
|
finalToolResponse = typeof toolResponse === "string" ? `${toolResponse}
|
|
377
410
|
|
|
378
|
-
[Thread ID: ${childThreadId}]` : toolResponse;
|
|
411
|
+
[${config.agentName} Thread ID: ${childThreadId}]` : toolResponse;
|
|
379
412
|
}
|
|
380
413
|
return {
|
|
381
414
|
toolResponse: finalToolResponse,
|
|
@@ -471,8 +504,6 @@ function buildSkillRegistration(skills) {
|
|
|
471
504
|
handler: createReadSkillHandler(skills)
|
|
472
505
|
};
|
|
473
506
|
}
|
|
474
|
-
|
|
475
|
-
// src/lib/session/session.ts
|
|
476
507
|
var createSession = async ({
|
|
477
508
|
threadId: providedThreadId,
|
|
478
509
|
agentName,
|
|
@@ -542,7 +573,7 @@ var createSession = async ({
|
|
|
542
573
|
threadId
|
|
543
574
|
});
|
|
544
575
|
}
|
|
545
|
-
await appendHumanMessage(threadId, message);
|
|
576
|
+
await appendHumanMessage(threadId, workflow.uuid4(), message);
|
|
546
577
|
if (hooks.onPostHumanMessageAppend) {
|
|
547
578
|
await hooks.onPostHumanMessageAppend({
|
|
548
579
|
message,
|
|
@@ -579,12 +610,12 @@ var createSession = async ({
|
|
|
579
610
|
nonRetryable: true
|
|
580
611
|
});
|
|
581
612
|
}
|
|
582
|
-
await appendSystemMessage(threadId, systemPrompt);
|
|
613
|
+
await appendSystemMessage(threadId, workflow.uuid4(), systemPrompt);
|
|
583
614
|
} else {
|
|
584
615
|
await initializeThread(threadId);
|
|
585
616
|
}
|
|
586
617
|
}
|
|
587
|
-
await appendHumanMessage(threadId, await buildContextMessage());
|
|
618
|
+
await appendHumanMessage(threadId, workflow.uuid4(), await buildContextMessage());
|
|
588
619
|
let exitReason = "completed";
|
|
589
620
|
try {
|
|
590
621
|
while (stateManager.isRunning() && !stateManager.isTerminal() && stateManager.getTurns() < maxTurns) {
|
|
@@ -614,7 +645,7 @@ var createSession = async ({
|
|
|
614
645
|
try {
|
|
615
646
|
parsedToolCalls.push(toolRouter.parseToolCall(tc));
|
|
616
647
|
} catch (error) {
|
|
617
|
-
await appendToolResult({
|
|
648
|
+
await appendToolResult(workflow.uuid4(), {
|
|
618
649
|
threadId,
|
|
619
650
|
toolCallId: tc.id ?? "",
|
|
620
651
|
toolName: tc.name,
|
|
@@ -698,8 +729,8 @@ function proxySandboxOps(options) {
|
|
|
698
729
|
}
|
|
699
730
|
|
|
700
731
|
// src/lib/workflow.ts
|
|
701
|
-
function defineWorkflow(fn) {
|
|
702
|
-
|
|
732
|
+
function defineWorkflow(config, fn) {
|
|
733
|
+
const workflow = async (input, workflowInput = {}) => {
|
|
703
734
|
const sessionInput = {
|
|
704
735
|
...workflowInput.previousThreadId && {
|
|
705
736
|
threadId: workflowInput.previousThreadId,
|
|
@@ -709,89 +740,8 @@ function defineWorkflow(fn) {
|
|
|
709
740
|
};
|
|
710
741
|
return fn(input, sessionInput);
|
|
711
742
|
};
|
|
712
|
-
}
|
|
713
|
-
|
|
714
|
-
// src/lib/thread/manager.ts
|
|
715
|
-
var THREAD_TTL_SECONDS = 60 * 60 * 24 * 90;
|
|
716
|
-
var APPEND_IDEMPOTENT_SCRIPT = `
|
|
717
|
-
if redis.call('EXISTS', KEYS[1]) == 1 then
|
|
718
|
-
return 0
|
|
719
|
-
end
|
|
720
|
-
for i = 2, #ARGV do
|
|
721
|
-
redis.call('RPUSH', KEYS[2], ARGV[i])
|
|
722
|
-
end
|
|
723
|
-
redis.call('EXPIRE', KEYS[2], tonumber(ARGV[1]))
|
|
724
|
-
redis.call('SET', KEYS[1], '1', 'EX', tonumber(ARGV[1]))
|
|
725
|
-
return 1
|
|
726
|
-
`;
|
|
727
|
-
function getThreadKey(threadId, key) {
|
|
728
|
-
return `thread:${threadId}:${key}`;
|
|
729
|
-
}
|
|
730
|
-
function createThreadManager(config) {
|
|
731
|
-
const {
|
|
732
|
-
redis,
|
|
733
|
-
threadId,
|
|
734
|
-
key = "messages",
|
|
735
|
-
serialize = (m) => JSON.stringify(m),
|
|
736
|
-
deserialize = (raw) => JSON.parse(raw),
|
|
737
|
-
idOf
|
|
738
|
-
} = config;
|
|
739
|
-
const redisKey = getThreadKey(threadId, key);
|
|
740
|
-
const metaKey = getThreadKey(threadId, `${key}:meta`);
|
|
741
|
-
async function assertThreadExists() {
|
|
742
|
-
const exists = await redis.exists(metaKey);
|
|
743
|
-
if (!exists) {
|
|
744
|
-
throw new Error(`Thread "${threadId}" (key: ${key}) does not exist`);
|
|
745
|
-
}
|
|
746
|
-
}
|
|
747
|
-
return {
|
|
748
|
-
async initialize() {
|
|
749
|
-
await redis.del(redisKey);
|
|
750
|
-
await redis.set(metaKey, "1", "EX", THREAD_TTL_SECONDS);
|
|
751
|
-
},
|
|
752
|
-
async load() {
|
|
753
|
-
await assertThreadExists();
|
|
754
|
-
const data = await redis.lrange(redisKey, 0, -1);
|
|
755
|
-
return data.map(deserialize);
|
|
756
|
-
},
|
|
757
|
-
async append(messages) {
|
|
758
|
-
if (messages.length === 0) return;
|
|
759
|
-
await assertThreadExists();
|
|
760
|
-
if (idOf) {
|
|
761
|
-
const dedupId = messages.map(idOf).join(":");
|
|
762
|
-
const dedupKey = getThreadKey(threadId, `dedup:${dedupId}`);
|
|
763
|
-
await redis.eval(
|
|
764
|
-
APPEND_IDEMPOTENT_SCRIPT,
|
|
765
|
-
2,
|
|
766
|
-
dedupKey,
|
|
767
|
-
redisKey,
|
|
768
|
-
String(THREAD_TTL_SECONDS),
|
|
769
|
-
...messages.map(serialize)
|
|
770
|
-
);
|
|
771
|
-
} else {
|
|
772
|
-
await redis.rpush(redisKey, ...messages.map(serialize));
|
|
773
|
-
await redis.expire(redisKey, THREAD_TTL_SECONDS);
|
|
774
|
-
}
|
|
775
|
-
},
|
|
776
|
-
async fork(newThreadId) {
|
|
777
|
-
await assertThreadExists();
|
|
778
|
-
const data = await redis.lrange(redisKey, 0, -1);
|
|
779
|
-
const forked = createThreadManager({
|
|
780
|
-
...config,
|
|
781
|
-
threadId: newThreadId
|
|
782
|
-
});
|
|
783
|
-
await forked.initialize();
|
|
784
|
-
if (data.length > 0) {
|
|
785
|
-
const newKey = getThreadKey(newThreadId, key);
|
|
786
|
-
await redis.rpush(newKey, ...data);
|
|
787
|
-
await redis.expire(newKey, THREAD_TTL_SECONDS);
|
|
788
|
-
}
|
|
789
|
-
return forked;
|
|
790
|
-
},
|
|
791
|
-
async delete() {
|
|
792
|
-
await redis.del(redisKey, metaKey);
|
|
793
|
-
}
|
|
794
|
-
};
|
|
743
|
+
Object.defineProperty(workflow, "name", { value: config.name });
|
|
744
|
+
return workflow;
|
|
795
745
|
}
|
|
796
746
|
|
|
797
747
|
// src/lib/types.ts
|
|
@@ -955,11 +905,56 @@ function createAgentStateManager({
|
|
|
955
905
|
};
|
|
956
906
|
}
|
|
957
907
|
|
|
908
|
+
// node_modules/uuid/dist/esm/stringify.js
|
|
909
|
+
var byteToHex = [];
|
|
910
|
+
for (let i = 0; i < 256; ++i) {
|
|
911
|
+
byteToHex.push((i + 256).toString(16).slice(1));
|
|
912
|
+
}
|
|
913
|
+
function unsafeStringify(arr, offset = 0) {
|
|
914
|
+
return (byteToHex[arr[offset + 0]] + byteToHex[arr[offset + 1]] + byteToHex[arr[offset + 2]] + byteToHex[arr[offset + 3]] + "-" + byteToHex[arr[offset + 4]] + byteToHex[arr[offset + 5]] + "-" + byteToHex[arr[offset + 6]] + byteToHex[arr[offset + 7]] + "-" + byteToHex[arr[offset + 8]] + byteToHex[arr[offset + 9]] + "-" + byteToHex[arr[offset + 10]] + byteToHex[arr[offset + 11]] + byteToHex[arr[offset + 12]] + byteToHex[arr[offset + 13]] + byteToHex[arr[offset + 14]] + byteToHex[arr[offset + 15]]).toLowerCase();
|
|
915
|
+
}
|
|
916
|
+
var rnds8Pool = new Uint8Array(256);
|
|
917
|
+
var poolPtr = rnds8Pool.length;
|
|
918
|
+
function rng() {
|
|
919
|
+
if (poolPtr > rnds8Pool.length - 16) {
|
|
920
|
+
crypto.randomFillSync(rnds8Pool);
|
|
921
|
+
poolPtr = 0;
|
|
922
|
+
}
|
|
923
|
+
return rnds8Pool.slice(poolPtr, poolPtr += 16);
|
|
924
|
+
}
|
|
925
|
+
var native_default = { randomUUID: crypto.randomUUID };
|
|
926
|
+
|
|
927
|
+
// node_modules/uuid/dist/esm/v4.js
|
|
928
|
+
function v4(options, buf, offset) {
|
|
929
|
+
if (native_default.randomUUID && !buf && !options) {
|
|
930
|
+
return native_default.randomUUID();
|
|
931
|
+
}
|
|
932
|
+
options = options || {};
|
|
933
|
+
const rnds = options.random ?? options.rng?.() ?? rng();
|
|
934
|
+
if (rnds.length < 16) {
|
|
935
|
+
throw new Error("Random bytes length must be >= 16");
|
|
936
|
+
}
|
|
937
|
+
rnds[6] = rnds[6] & 15 | 64;
|
|
938
|
+
rnds[8] = rnds[8] & 63 | 128;
|
|
939
|
+
if (buf) {
|
|
940
|
+
offset = offset || 0;
|
|
941
|
+
if (offset < 0 || offset + 16 > buf.length) {
|
|
942
|
+
throw new RangeError(`UUID byte range ${offset}:${offset + 15} is out of buffer bounds`);
|
|
943
|
+
}
|
|
944
|
+
for (let i = 0; i < 16; ++i) {
|
|
945
|
+
buf[offset + i] = rnds[i];
|
|
946
|
+
}
|
|
947
|
+
return buf;
|
|
948
|
+
}
|
|
949
|
+
return unsafeStringify(rnds);
|
|
950
|
+
}
|
|
951
|
+
var v4_default = v4;
|
|
952
|
+
|
|
958
953
|
// src/lib/tool-router/auto-append.ts
|
|
959
954
|
function withAutoAppend(threadHandler, handler) {
|
|
960
955
|
return async (args, context) => {
|
|
961
956
|
const response = await handler(args, context);
|
|
962
|
-
await threadHandler({
|
|
957
|
+
await threadHandler(v4_default(), {
|
|
963
958
|
threadId: context.threadId,
|
|
964
959
|
toolCallId: context.toolCallId,
|
|
965
960
|
toolName: context.toolName,
|
|
@@ -1390,10 +1385,12 @@ var taskCreateTool = {
|
|
|
1390
1385
|
metadata: z14__default.default.record(z14__default.default.string(), z14__default.default.string()).describe("Arbitrary key-value pairs for tracking")
|
|
1391
1386
|
})
|
|
1392
1387
|
};
|
|
1388
|
+
|
|
1389
|
+
// src/tools/task-create/handler.ts
|
|
1393
1390
|
function createTaskCreateHandler(stateManager) {
|
|
1394
1391
|
return (args) => {
|
|
1395
1392
|
const task = {
|
|
1396
|
-
id:
|
|
1393
|
+
id: getShortId(),
|
|
1397
1394
|
subject: args.subject,
|
|
1398
1395
|
description: args.description,
|
|
1399
1396
|
activeForm: args.activeForm,
|
|
@@ -1625,6 +1622,89 @@ var FileSystemSkillProvider = class {
|
|
|
1625
1622
|
return dirs;
|
|
1626
1623
|
}
|
|
1627
1624
|
};
|
|
1625
|
+
|
|
1626
|
+
// src/lib/thread/manager.ts
|
|
1627
|
+
var THREAD_TTL_SECONDS = 60 * 60 * 24 * 90;
|
|
1628
|
+
var APPEND_IDEMPOTENT_SCRIPT = `
|
|
1629
|
+
if redis.call('EXISTS', KEYS[1]) == 1 then
|
|
1630
|
+
return 0
|
|
1631
|
+
end
|
|
1632
|
+
for i = 2, #ARGV do
|
|
1633
|
+
redis.call('RPUSH', KEYS[2], ARGV[i])
|
|
1634
|
+
end
|
|
1635
|
+
redis.call('EXPIRE', KEYS[2], tonumber(ARGV[1]))
|
|
1636
|
+
redis.call('SET', KEYS[1], '1', 'EX', tonumber(ARGV[1]))
|
|
1637
|
+
return 1
|
|
1638
|
+
`;
|
|
1639
|
+
function getThreadKey(threadId, key) {
|
|
1640
|
+
return `thread:${threadId}:${key}`;
|
|
1641
|
+
}
|
|
1642
|
+
function createThreadManager(config) {
|
|
1643
|
+
const {
|
|
1644
|
+
redis,
|
|
1645
|
+
threadId,
|
|
1646
|
+
key = "messages",
|
|
1647
|
+
serialize = (m) => JSON.stringify(m),
|
|
1648
|
+
deserialize = (raw) => JSON.parse(raw),
|
|
1649
|
+
idOf
|
|
1650
|
+
} = config;
|
|
1651
|
+
const redisKey = getThreadKey(threadId, key);
|
|
1652
|
+
const metaKey = getThreadKey(threadId, `${key}:meta`);
|
|
1653
|
+
async function assertThreadExists() {
|
|
1654
|
+
const exists = await redis.exists(metaKey);
|
|
1655
|
+
if (!exists) {
|
|
1656
|
+
throw new Error(`Thread "${threadId}" (key: ${key}) does not exist`);
|
|
1657
|
+
}
|
|
1658
|
+
}
|
|
1659
|
+
return {
|
|
1660
|
+
async initialize() {
|
|
1661
|
+
await redis.del(redisKey);
|
|
1662
|
+
await redis.set(metaKey, "1", "EX", THREAD_TTL_SECONDS);
|
|
1663
|
+
},
|
|
1664
|
+
async load() {
|
|
1665
|
+
await assertThreadExists();
|
|
1666
|
+
const data = await redis.lrange(redisKey, 0, -1);
|
|
1667
|
+
return data.map(deserialize);
|
|
1668
|
+
},
|
|
1669
|
+
async append(messages) {
|
|
1670
|
+
if (messages.length === 0) return;
|
|
1671
|
+
await assertThreadExists();
|
|
1672
|
+
if (idOf) {
|
|
1673
|
+
const dedupId = messages.map(idOf).join(":");
|
|
1674
|
+
const dedupKey = getThreadKey(threadId, `dedup:${dedupId}`);
|
|
1675
|
+
await redis.eval(
|
|
1676
|
+
APPEND_IDEMPOTENT_SCRIPT,
|
|
1677
|
+
2,
|
|
1678
|
+
dedupKey,
|
|
1679
|
+
redisKey,
|
|
1680
|
+
String(THREAD_TTL_SECONDS),
|
|
1681
|
+
...messages.map(serialize)
|
|
1682
|
+
);
|
|
1683
|
+
} else {
|
|
1684
|
+
await redis.rpush(redisKey, ...messages.map(serialize));
|
|
1685
|
+
await redis.expire(redisKey, THREAD_TTL_SECONDS);
|
|
1686
|
+
}
|
|
1687
|
+
},
|
|
1688
|
+
async fork(newThreadId) {
|
|
1689
|
+
await assertThreadExists();
|
|
1690
|
+
const data = await redis.lrange(redisKey, 0, -1);
|
|
1691
|
+
const forked = createThreadManager({
|
|
1692
|
+
...config,
|
|
1693
|
+
threadId: newThreadId
|
|
1694
|
+
});
|
|
1695
|
+
await forked.initialize();
|
|
1696
|
+
if (data.length > 0) {
|
|
1697
|
+
const newKey = getThreadKey(newThreadId, key);
|
|
1698
|
+
await redis.rpush(newKey, ...data);
|
|
1699
|
+
await redis.expire(newKey, THREAD_TTL_SECONDS);
|
|
1700
|
+
}
|
|
1701
|
+
return forked;
|
|
1702
|
+
},
|
|
1703
|
+
async delete() {
|
|
1704
|
+
await redis.del(redisKey, metaKey);
|
|
1705
|
+
}
|
|
1706
|
+
};
|
|
1707
|
+
}
|
|
1628
1708
|
async function queryParentWorkflowState(client) {
|
|
1629
1709
|
const { workflowExecution } = activity.Context.current().info;
|
|
1630
1710
|
const handle = client.getHandle(
|