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.
Files changed (64) hide show
  1. package/dist/adapters/sandbox/daytona/index.cjs +25 -10
  2. package/dist/adapters/sandbox/daytona/index.cjs.map +1 -1
  3. package/dist/adapters/sandbox/daytona/index.d.cts +4 -1
  4. package/dist/adapters/sandbox/daytona/index.d.ts +4 -1
  5. package/dist/adapters/sandbox/daytona/index.js +25 -10
  6. package/dist/adapters/sandbox/daytona/index.js.map +1 -1
  7. package/dist/adapters/sandbox/virtual/index.d.cts +4 -3
  8. package/dist/adapters/sandbox/virtual/index.d.ts +4 -3
  9. package/dist/adapters/thread/google-genai/index.cjs +69 -24
  10. package/dist/adapters/thread/google-genai/index.cjs.map +1 -1
  11. package/dist/adapters/thread/google-genai/index.d.cts +10 -10
  12. package/dist/adapters/thread/google-genai/index.d.ts +10 -10
  13. package/dist/adapters/thread/google-genai/index.js +69 -24
  14. package/dist/adapters/thread/google-genai/index.js.map +1 -1
  15. package/dist/adapters/thread/langchain/index.cjs +76 -69
  16. package/dist/adapters/thread/langchain/index.cjs.map +1 -1
  17. package/dist/adapters/thread/langchain/index.d.cts +11 -11
  18. package/dist/adapters/thread/langchain/index.d.ts +11 -11
  19. package/dist/adapters/thread/langchain/index.js +76 -69
  20. package/dist/adapters/thread/langchain/index.js.map +1 -1
  21. package/dist/index.cjs +198 -118
  22. package/dist/index.cjs.map +1 -1
  23. package/dist/index.d.cts +14 -14
  24. package/dist/index.d.ts +14 -14
  25. package/dist/index.js +198 -118
  26. package/dist/index.js.map +1 -1
  27. package/dist/{queries-D8T4pEeu.d.ts → queries-6Avfh74U.d.ts} +1 -1
  28. package/dist/{queries-D22uWTOb.d.cts → queries-CHa2iv_I.d.cts} +1 -1
  29. package/dist/{types-CxWLeJTB.d.ts → types-BkAYmc96.d.ts} +6 -6
  30. package/dist/{types-CCfJb5Jl.d.cts → types-CES_30qx.d.cts} +6 -6
  31. package/dist/{types-DjT78Sdp.d.cts → types-YbL7JpEA.d.cts} +4 -2
  32. package/dist/{types-DjT78Sdp.d.ts → types-YbL7JpEA.d.ts} +4 -2
  33. package/dist/workflow.cjs +68 -34
  34. package/dist/workflow.cjs.map +1 -1
  35. package/dist/workflow.d.cts +16 -12
  36. package/dist/workflow.d.ts +16 -12
  37. package/dist/workflow.js +68 -34
  38. package/dist/workflow.js.map +1 -1
  39. package/package.json +1 -1
  40. package/src/adapters/sandbox/daytona/filesystem.ts +21 -12
  41. package/src/adapters/sandbox/daytona/index.ts +24 -23
  42. package/src/adapters/thread/google-genai/activities.ts +11 -9
  43. package/src/adapters/thread/google-genai/model-invoker.ts +6 -11
  44. package/src/adapters/thread/google-genai/thread-manager.ts +44 -29
  45. package/src/adapters/thread/langchain/activities.ts +6 -4
  46. package/src/adapters/thread/langchain/thread-manager.ts +55 -27
  47. package/src/lib/session/session-edge-cases.integration.test.ts +20 -2
  48. package/src/lib/session/session.integration.test.ts +16 -2
  49. package/src/lib/session/session.ts +7 -5
  50. package/src/lib/session/types.ts +9 -3
  51. package/src/lib/subagent/handler.ts +1 -1
  52. package/src/lib/subagent/subagent.integration.test.ts +5 -4
  53. package/src/lib/subagent/tool.ts +1 -1
  54. package/src/lib/thread/index.ts +0 -1
  55. package/src/lib/tool-router/auto-append-sandbox.integration.test.ts +20 -21
  56. package/src/lib/tool-router/auto-append.ts +3 -2
  57. package/src/lib/tool-router/router-edge-cases.integration.test.ts +64 -23
  58. package/src/lib/tool-router/router.integration.test.ts +60 -23
  59. package/src/lib/tool-router/router.ts +58 -29
  60. package/src/lib/tool-router/types.ts +12 -7
  61. package/src/lib/workflow.test.ts +18 -6
  62. package/src/lib/workflow.ts +13 -3
  63. package/src/tools/task-create/handler.ts +3 -6
  64. 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 { content: r.fallbackContent, result: { error: errorStr, recovered: true } };
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 { content: r.fallbackContent, result: { error: errorStr, recovered: true } };
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({ skipped: true, reason: "Skipped by PreToolUse hook" })
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(toolCall, tool, error, effectiveArgs, turn);
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
- await appendToolResult({
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(toolCall, tool, toolResult, effectiveArgs, turn, Date.now() - startTime);
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 && { sandboxId: context.sandboxId }
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
- threadId: options.threadId,
243
- toolCallId: toolCall.id,
244
- toolName: toolCall.name,
245
- content: response.toolResponse
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
- return async (input, workflowInput = {}) => {
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: workflow.uuid4(),
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(