zeitlich 0.2.13 → 0.2.14

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 (135) hide show
  1. package/README.md +49 -38
  2. package/dist/adapters/sandbox/daytona/index.cjs +205 -0
  3. package/dist/adapters/sandbox/daytona/index.cjs.map +1 -0
  4. package/dist/adapters/sandbox/daytona/index.d.cts +86 -0
  5. package/dist/adapters/sandbox/daytona/index.d.ts +86 -0
  6. package/dist/adapters/sandbox/daytona/index.js +202 -0
  7. package/dist/adapters/sandbox/daytona/index.js.map +1 -0
  8. package/dist/adapters/sandbox/inmemory/index.cjs +174 -0
  9. package/dist/adapters/sandbox/inmemory/index.cjs.map +1 -0
  10. package/dist/adapters/sandbox/inmemory/index.d.cts +28 -0
  11. package/dist/adapters/sandbox/inmemory/index.d.ts +28 -0
  12. package/dist/adapters/sandbox/inmemory/index.js +172 -0
  13. package/dist/adapters/sandbox/inmemory/index.js.map +1 -0
  14. package/dist/adapters/sandbox/virtual/index.cjs +405 -0
  15. package/dist/adapters/sandbox/virtual/index.cjs.map +1 -0
  16. package/dist/adapters/sandbox/virtual/index.d.cts +85 -0
  17. package/dist/adapters/sandbox/virtual/index.d.ts +85 -0
  18. package/dist/adapters/sandbox/virtual/index.js +400 -0
  19. package/dist/adapters/sandbox/virtual/index.js.map +1 -0
  20. package/dist/adapters/thread/google-genai/index.cjs +284 -0
  21. package/dist/adapters/thread/google-genai/index.cjs.map +1 -0
  22. package/dist/adapters/thread/google-genai/index.d.cts +145 -0
  23. package/dist/adapters/thread/google-genai/index.d.ts +145 -0
  24. package/dist/adapters/thread/google-genai/index.js +278 -0
  25. package/dist/adapters/thread/google-genai/index.js.map +1 -0
  26. package/dist/adapters/{langchain → thread/langchain}/index.cjs +7 -9
  27. package/dist/adapters/thread/langchain/index.cjs.map +1 -0
  28. package/dist/adapters/{langchain → thread/langchain}/index.d.cts +17 -21
  29. package/dist/adapters/{langchain → thread/langchain}/index.d.ts +17 -21
  30. package/dist/adapters/{langchain → thread/langchain}/index.js +7 -9
  31. package/dist/adapters/thread/langchain/index.js.map +1 -0
  32. package/dist/index.cjs +816 -545
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +235 -74
  35. package/dist/index.d.ts +235 -74
  36. package/dist/index.js +804 -540
  37. package/dist/index.js.map +1 -1
  38. package/dist/types-B4C9txdq.d.ts +389 -0
  39. package/dist/{thread-manager-qc0g5Rvd.d.cts → types-B9ljZewB.d.cts} +1 -6
  40. package/dist/{thread-manager-qc0g5Rvd.d.ts → types-B9ljZewB.d.ts} +1 -6
  41. package/dist/types-BMXzv7TN.d.cts +476 -0
  42. package/dist/types-BMXzv7TN.d.ts +476 -0
  43. package/dist/types-BVP87m_W.d.cts +121 -0
  44. package/dist/types-CDubRtad.d.cts +115 -0
  45. package/dist/types-CDubRtad.d.ts +115 -0
  46. package/dist/types-CwwgQ_9H.d.ts +121 -0
  47. package/dist/types-GpMU4b0w.d.cts +389 -0
  48. package/dist/workflow.cjs +444 -318
  49. package/dist/workflow.cjs.map +1 -1
  50. package/dist/workflow.d.cts +271 -222
  51. package/dist/workflow.d.ts +271 -222
  52. package/dist/workflow.js +440 -316
  53. package/dist/workflow.js.map +1 -1
  54. package/package.json +59 -6
  55. package/src/adapters/sandbox/daytona/filesystem.ts +136 -0
  56. package/src/adapters/sandbox/daytona/index.ts +149 -0
  57. package/src/adapters/sandbox/daytona/types.ts +34 -0
  58. package/src/adapters/sandbox/inmemory/index.ts +213 -0
  59. package/src/adapters/sandbox/virtual/filesystem.ts +345 -0
  60. package/src/adapters/sandbox/virtual/index.ts +88 -0
  61. package/src/adapters/sandbox/virtual/mutations.ts +38 -0
  62. package/src/adapters/sandbox/virtual/provider.ts +101 -0
  63. package/src/adapters/sandbox/virtual/tree.ts +82 -0
  64. package/src/adapters/sandbox/virtual/types.ts +127 -0
  65. package/src/adapters/sandbox/virtual/virtual-sandbox.test.ts +523 -0
  66. package/src/adapters/sandbox/virtual/with-virtual-sandbox.ts +91 -0
  67. package/src/adapters/thread/google-genai/activities.ts +121 -0
  68. package/src/adapters/thread/google-genai/index.ts +41 -0
  69. package/src/adapters/thread/google-genai/model-invoker.ts +154 -0
  70. package/src/adapters/thread/google-genai/thread-manager.ts +169 -0
  71. package/src/adapters/{langchain → thread/langchain}/activities.ts +11 -15
  72. package/src/adapters/{langchain → thread/langchain}/index.ts +1 -1
  73. package/src/adapters/{langchain → thread/langchain}/model-invoker.ts +15 -18
  74. package/src/adapters/{langchain → thread/langchain}/thread-manager.ts +1 -1
  75. package/src/index.ts +32 -24
  76. package/src/lib/activity.ts +87 -0
  77. package/src/lib/hooks/index.ts +11 -0
  78. package/src/lib/hooks/types.ts +98 -0
  79. package/src/lib/model/helpers.ts +6 -0
  80. package/src/lib/model/index.ts +13 -0
  81. package/src/lib/{model-invoker.ts → model/types.ts} +18 -1
  82. package/src/lib/sandbox/index.ts +19 -0
  83. package/src/lib/sandbox/manager.ts +76 -0
  84. package/src/lib/sandbox/sandbox.test.ts +158 -0
  85. package/src/lib/{fs.ts → sandbox/tree.ts} +6 -6
  86. package/src/lib/sandbox/types.ts +164 -0
  87. package/src/lib/session/index.ts +11 -0
  88. package/src/lib/{session.ts → session/session.ts} +76 -48
  89. package/src/lib/session/types.ts +93 -0
  90. package/src/lib/skills/fs-provider.ts +16 -15
  91. package/src/lib/skills/handler.ts +31 -0
  92. package/src/lib/skills/index.ts +5 -1
  93. package/src/lib/skills/register.ts +20 -0
  94. package/src/lib/skills/tool.ts +47 -0
  95. package/src/lib/state/index.ts +9 -0
  96. package/src/lib/{state-manager.ts → state/manager.ts} +10 -147
  97. package/src/lib/state/types.ts +134 -0
  98. package/src/lib/subagent/define.ts +71 -0
  99. package/src/lib/subagent/handler.ts +99 -0
  100. package/src/lib/subagent/index.ts +13 -0
  101. package/src/lib/subagent/register.ts +53 -0
  102. package/src/lib/subagent/tool.ts +80 -0
  103. package/src/lib/subagent/types.ts +92 -0
  104. package/src/lib/thread/index.ts +7 -0
  105. package/src/lib/{thread-manager.ts → thread/manager.ts} +1 -33
  106. package/src/lib/thread/types.ts +33 -0
  107. package/src/lib/tool-router/auto-append.ts +55 -0
  108. package/src/lib/tool-router/index.ts +41 -0
  109. package/src/lib/tool-router/router.ts +462 -0
  110. package/src/lib/tool-router/types.ts +478 -0
  111. package/src/lib/tool-router/with-sandbox.ts +70 -0
  112. package/src/lib/types.ts +5 -382
  113. package/src/tools/bash/bash.test.ts +53 -55
  114. package/src/tools/bash/handler.ts +23 -51
  115. package/src/tools/edit/handler.ts +67 -81
  116. package/src/tools/glob/handler.ts +60 -17
  117. package/src/tools/read-file/handler.ts +67 -0
  118. package/src/tools/read-skill/handler.ts +1 -31
  119. package/src/tools/read-skill/tool.ts +5 -47
  120. package/src/tools/subagent/handler.ts +1 -100
  121. package/src/tools/subagent/tool.ts +5 -93
  122. package/src/tools/task-create/handler.ts +1 -1
  123. package/src/tools/task-get/handler.ts +1 -1
  124. package/src/tools/task-list/handler.ts +1 -1
  125. package/src/tools/task-update/handler.ts +1 -1
  126. package/src/tools/write-file/handler.ts +47 -0
  127. package/src/workflow.ts +88 -47
  128. package/tsup.config.ts +8 -1
  129. package/dist/adapters/langchain/index.cjs.map +0 -1
  130. package/dist/adapters/langchain/index.js.map +0 -1
  131. package/dist/model-invoker-y_zlyMqu.d.cts +0 -892
  132. package/dist/model-invoker-y_zlyMqu.d.ts +0 -892
  133. package/src/lib/tool-router.ts +0 -977
  134. package/src/lib/workflow-helpers.ts +0 -50
  135. /package/src/lib/{thread-id.ts → thread/id.ts} +0 -0
@@ -0,0 +1,47 @@
1
+ import type { ActivityToolHandler } from "../../lib/tool-router";
2
+ import type { SandboxContext } from "../../lib/tool-router/with-sandbox";
3
+ import type { FileWriteArgs } from "./tool";
4
+
5
+ interface WriteFileResult {
6
+ path: string;
7
+ success: boolean;
8
+ }
9
+
10
+ /**
11
+ * Write-file tool handler — writes files to a {@link Sandbox} filesystem.
12
+ *
13
+ * Wrap with {@link withSandbox} at activity registration time to inject the
14
+ * sandbox automatically.
15
+ */
16
+ export const writeFileHandler: ActivityToolHandler<
17
+ FileWriteArgs,
18
+ WriteFileResult,
19
+ SandboxContext
20
+ > = async (args, { sandbox }) => {
21
+ const { fs } = sandbox;
22
+ const { file_path, content } = args;
23
+
24
+ try {
25
+ const lastSlash = file_path.lastIndexOf("/");
26
+ if (lastSlash > 0) {
27
+ const dir = file_path.slice(0, lastSlash);
28
+ const dirExists = await fs.exists(dir);
29
+ if (!dirExists) {
30
+ await fs.mkdir(dir, { recursive: true });
31
+ }
32
+ }
33
+
34
+ await fs.writeFile(file_path, content);
35
+
36
+ return {
37
+ toolResponse: `Successfully wrote to ${file_path}`,
38
+ data: { path: file_path, success: true },
39
+ };
40
+ } catch (error) {
41
+ const message = error instanceof Error ? error.message : "Unknown error";
42
+ return {
43
+ toolResponse: `Error writing file "${file_path}": ${message}`,
44
+ data: { path: file_path, success: false },
45
+ };
46
+ }
47
+ };
package/src/workflow.ts CHANGED
@@ -19,29 +19,33 @@
19
19
  */
20
20
 
21
21
  // Session
22
- export { createSession, proxyDefaultThreadOps } from "./lib/session";
22
+ export {
23
+ createSession,
24
+ proxyDefaultThreadOps,
25
+ proxySandboxOps,
26
+ } from "./lib/session";
27
+ export type { ZeitlichSession, ThreadOps, SessionConfig } from "./lib/session";
23
28
 
24
29
  // Thread utilities
25
- export { getShortId } from "./lib/thread-id";
26
- export type { ZeitlichSession, SessionLifecycleHooks } from "./lib/session";
30
+ export { getShortId } from "./lib/thread";
27
31
 
28
32
  // State management
29
- export { createAgentStateManager } from "./lib/state-manager";
33
+ export { createAgentStateManager } from "./lib/state";
30
34
  export type {
31
35
  AgentState,
32
36
  AgentStateManager,
33
37
  JsonSerializable,
34
38
  JsonValue,
35
39
  JsonPrimitive,
36
- } from "./lib/state-manager";
40
+ } from "./lib/state";
37
41
 
38
42
  // Tool router (includes registry functionality)
39
43
  export {
40
44
  createToolRouter,
41
45
  hasNoOtherToolCalls,
42
46
  defineTool,
43
- defineSubagent,
44
47
  } from "./lib/tool-router";
48
+ export { defineSubagent } from "./lib/subagent";
45
49
  export type {
46
50
  // Tool definition types
47
51
  ToolDefinition,
@@ -53,10 +57,11 @@ export type {
53
57
  ParsedToolCallUnion,
54
58
  // Router types
55
59
  ToolRouter,
60
+ ToolRouterHooks,
56
61
  // Handler types
57
62
  ToolHandler,
58
63
  ActivityToolHandler,
59
- ToolHandlerContext,
64
+ RouterContext,
60
65
  ToolHandlerResponse,
61
66
  // Result types
62
67
  ToolArgs,
@@ -64,12 +69,35 @@ export type {
64
69
  ToolCallResult,
65
70
  ToolCallResultUnion,
66
71
  InferToolResults,
72
+ // Tool hook types
73
+ PreToolUseHook,
74
+ PreToolUseHookContext,
75
+ PreToolUseHookResult,
76
+ PostToolUseHook,
77
+ PostToolUseHookContext,
78
+ PostToolUseFailureHook,
79
+ PostToolUseFailureHookContext,
80
+ PostToolUseFailureHookResult,
81
+ ToolHooks,
67
82
  // Other
68
83
  AppendToolResultFn,
69
84
  ProcessToolCallsContext,
70
85
  } from "./lib/tool-router";
71
86
 
72
- // Types
87
+ // Session & message lifecycle hooks
88
+ export type {
89
+ Hooks,
90
+ SessionStartHook,
91
+ SessionStartHookContext,
92
+ SessionEndHook,
93
+ SessionEndHookContext,
94
+ PreHumanMessageAppendHook,
95
+ PreHumanMessageAppendHookContext,
96
+ PostHumanMessageAppendHook,
97
+ PostHumanMessageAppendHookContext,
98
+ } from "./lib/hooks";
99
+
100
+ // Core types
73
101
  export type {
74
102
  // Message types (framework-agnostic)
75
103
  ContentPart,
@@ -80,61 +108,74 @@ export type {
80
108
  AgentStatus,
81
109
  BaseAgentState,
82
110
  AgentFile,
83
- AgentResponse,
84
- ThreadOps,
85
111
  AgentConfig,
86
- SessionConfig,
87
112
  RunAgentConfig,
88
- RunAgentActivity,
89
113
  ToolResultConfig,
90
114
  SessionExitReason,
91
- // Hook types
92
- PreToolUseHook,
93
- PreToolUseHookContext,
94
- PreToolUseHookResult,
95
- PostToolUseHook,
96
- PostToolUseHookContext,
97
- PostToolUseFailureHook,
98
- PostToolUseFailureHookContext,
99
- PostToolUseFailureHookResult,
100
- PreHumanMessageAppendHook,
101
- PreHumanMessageAppendHookContext,
102
- PostHumanMessageAppendHook,
103
- PostHumanMessageAppendHookContext,
104
- Hooks,
105
- ToolHooks,
106
- SessionStartHook,
107
- SessionStartHookContext,
108
- SessionEndHook,
109
- SessionEndHookContext,
110
- // Subagent types
111
- SubagentConfig,
112
- SubagentHooks,
113
- SubagentInput,
115
+ SerializableToolDefinition,
114
116
  // Task types
115
117
  TaskStatus,
116
118
  WorkflowTask,
117
119
  } from "./lib/types";
120
+ export { isTerminalStatus } from "./lib/types";
121
+
122
+ // Model types
123
+ export type {
124
+ AgentResponse,
125
+ RunAgentActivity,
126
+ ModelInvoker,
127
+ ModelInvokerConfig,
128
+ } from "./lib/model";
129
+
130
+ // Subagent types
131
+ export type {
132
+ SubagentConfig,
133
+ SubagentHooks,
134
+ SubagentInput,
135
+ SubagentHandlerResponse,
136
+ SubagentWorkflow,
137
+ } from "./lib/subagent/types";
138
+ // Sandbox types (workflow-safe — no activity-side code)
139
+ export type {
140
+ Sandbox,
141
+ SandboxCapabilities,
142
+ SandboxCreateOptions,
143
+ SandboxCreateResult,
144
+ SandboxFileSystem,
145
+ SandboxOps,
146
+ SandboxProvider,
147
+ SandboxSnapshot,
148
+ ExecOptions,
149
+ ExecResult,
150
+ DirentEntry as SandboxDirentEntry,
151
+ FileStat as SandboxFileStat,
152
+ } from "./lib/sandbox/types";
118
153
  export {
119
- isTerminalStatus,
120
- agentQueryName,
121
- agentStateChangeUpdateName,
122
- } from "./lib/types";
154
+ SandboxNotFoundError,
155
+ SandboxNotSupportedError,
156
+ } from "./lib/sandbox/types";
123
157
 
124
- // Model invoker contract
125
- export type { ModelInvoker, ModelInvokerConfig } from "./lib/model-invoker";
158
+ // Virtual sandbox (workflow-safe — imported from leaf modules to avoid
159
+ // pulling activity-side code like VirtualSandboxFileSystem / Provider).
160
+ export { applyVirtualTreeMutations } from "./adapters/sandbox/virtual/mutations";
161
+ export { formatVirtualFileTree } from "./adapters/sandbox/virtual/tree";
162
+ export type {
163
+ FileEntry,
164
+ FileEntryMetadata,
165
+ FileResolver,
166
+ VirtualFileTree,
167
+ VirtualSandboxState,
168
+ TreeMutation,
169
+ } from "./adapters/sandbox/virtual/types";
126
170
 
127
171
  // Subagent support
128
- export { createSubagentTool } from "./tools/subagent/tool";
129
- export type { SubagentArgs } from "./tools/subagent/tool";
130
- export type { SubagentWorkflow } from "./lib/types";
172
+ export type { SubagentArgs } from "./lib/subagent";
131
173
 
132
174
  // Skills (types + workflow-safe utilities)
133
175
  export type { Skill, SkillMetadata, SkillProvider } from "./lib/skills/types";
134
176
  export { parseSkillFile } from "./lib/skills/parse";
135
- export { createReadSkillTool } from "./tools/read-skill/tool";
136
- export { createReadSkillHandler } from "./tools/read-skill/handler";
137
- export type { ReadSkillArgs } from "./tools/read-skill/tool";
177
+ export { createReadSkillTool, createReadSkillHandler } from "./lib/skills";
178
+ export type { ReadSkillArgs } from "./lib/skills";
138
179
 
139
180
  // Tool definitions (schemas only - no handlers)
140
181
  export { globTool } from "./tools/glob/tool";
package/tsup.config.ts CHANGED
@@ -4,7 +4,12 @@ export default defineConfig({
4
4
  entry: {
5
5
  index: "src/index.ts",
6
6
  workflow: "src/workflow.ts",
7
- "adapters/langchain/index": "src/adapters/langchain/index.ts",
7
+ "adapters/thread/langchain/index": "src/adapters/thread/langchain/index.ts",
8
+ "adapters/thread/google-genai/index":
9
+ "src/adapters/thread/google-genai/index.ts",
10
+ "adapters/sandbox/inmemory/index": "src/adapters/sandbox/inmemory/index.ts",
11
+ "adapters/sandbox/daytona/index": "src/adapters/sandbox/daytona/index.ts",
12
+ "adapters/sandbox/virtual/index": "src/adapters/sandbox/virtual/index.ts",
8
13
  },
9
14
  format: ["esm", "cjs"],
10
15
  dts: true,
@@ -16,6 +21,8 @@ export default defineConfig({
16
21
  external: [
17
22
  /^@temporalio\//,
18
23
  /^@langchain\//,
24
+ /^@google\//,
25
+ /^@daytonaio\//,
19
26
  "ioredis",
20
27
  "@mongodb-js/zstd",
21
28
  "node-liblzma",
@@ -1 +0,0 @@
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/langchain/thread-manager.ts","../../../src/adapters/langchain/model-invoker.ts","../../../src/adapters/langchain/activities.ts"],"names":["randomFillSync","randomUUID","HumanMessage","SystemMessage","AIMessage","ToolMessage","invokeLangChainModel","messages","mapStoredMessagesToChatMessages"],"mappings":"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","file":"index.cjs","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 Redis from \"ioredis\";\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\nexport interface ThreadManagerConfig<T> {\n redis: Redis;\n threadId: string;\n /** Thread key, defaults to 'messages' */\n key?: string;\n /** Custom serializer, defaults to JSON.stringify */\n serialize?: (message: T) => string;\n /** Custom deserializer, defaults to JSON.parse */\n deserialize?: (raw: string) => T;\n /**\n * Extract a unique id from a message for idempotent appends.\n * When provided, `append` uses an atomic Lua script to skip duplicate writes.\n */\n idOf?: (message: T) => string;\n}\n\n/** Generic thread manager for any message type */\nexport interface BaseThreadManager<T> {\n /** Initialize an empty thread */\n initialize(): Promise<void>;\n /** Load all messages from the thread */\n load(): Promise<T[]>;\n /**\n * Append messages to the thread.\n * When `idOf` is configured, appends are idempotent — retries with the\n * same message ids are atomically skipped via a Redis Lua script.\n */\n append(messages: T[]): Promise<void>;\n /** Delete the thread */\n delete(): Promise<void>;\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 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-manager\";\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/types\";\nimport type { ModelInvokerConfig } from \"../../lib/model-invoker\";\nimport { mapStoredMessagesToChatMessages } from \"@langchain/core/messages\";\nimport type { StoredMessage } from \"@langchain/core/messages\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport type {\n BaseChatModel,\n BaseChatModelCallOptions,\n BindToolsInput,\n} from \"@langchain/core/language_models/chat_models\";\nimport { createLangChainThreadManager } from \"./thread-manager\";\n\nexport interface LangChainModelInvokerConfig {\n redis: Redis;\n model: BaseChatModel<BaseChatModelCallOptions & { tools?: BindToolsInput }>;\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/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 * // Wrap with createRunAgentActivity to use as runAgent activity:\n * return { runAgent: createRunAgentActivity(client, invoker) };\n * ```\n */\nexport function createLangChainModelInvoker({\n redis,\n model,\n}: LangChainModelInvokerConfig) {\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: 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 */\nexport async function invokeLangChainModel({\n redis,\n model,\n config,\n}: {\n redis: Redis;\n config: ModelInvokerConfig;\n model: BaseChatModel<BaseChatModelCallOptions & { tools?: BindToolsInput }>;\n}): Promise<AgentResponse<StoredMessage>> {\n const invoker = createLangChainModelInvoker({ redis, model });\n return invoker(config);\n}\n","import type Redis from \"ioredis\";\nimport type { ThreadOps, ToolResultConfig } from \"../../lib/types\";\nimport type { MessageContent } from \"@langchain/core/messages\";\nimport type { ModelInvoker } from \"../../lib/model-invoker\";\nimport type { StoredMessage } from \"@langchain/core/messages\";\nimport type {\n BaseChatModel,\n BaseChatModelCallOptions,\n BindToolsInput,\n} from \"@langchain/core/language_models/chat_models\";\nimport { createLangChainThreadManager } from \"./thread-manager\";\nimport { createLangChainModelInvoker } from \"./model-invoker\";\n\ntype LangChainModel = BaseChatModel<\n BaseChatModelCallOptions & { tools?: BindToolsInput }\n>;\n\nexport interface LangChainAdapterConfig {\n redis: Redis;\n /** Optional default model — if omitted, use `createModelInvoker()` to create invokers later */\n model?: LangChainModel;\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 createModelInvoker(model: LangChainModel): 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/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\n const makeInvoker = (model: LangChainModel): 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 }) as unknown as ModelInvoker<StoredMessage>);\n\n return {\n threadOps,\n invoker,\n createModelInvoker: makeInvoker,\n };\n}\n"]}
@@ -1 +0,0 @@
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/langchain/thread-manager.ts","../../../src/adapters/langchain/model-invoker.ts","../../../src/adapters/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 Redis from \"ioredis\";\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\nexport interface ThreadManagerConfig<T> {\n redis: Redis;\n threadId: string;\n /** Thread key, defaults to 'messages' */\n key?: string;\n /** Custom serializer, defaults to JSON.stringify */\n serialize?: (message: T) => string;\n /** Custom deserializer, defaults to JSON.parse */\n deserialize?: (raw: string) => T;\n /**\n * Extract a unique id from a message for idempotent appends.\n * When provided, `append` uses an atomic Lua script to skip duplicate writes.\n */\n idOf?: (message: T) => string;\n}\n\n/** Generic thread manager for any message type */\nexport interface BaseThreadManager<T> {\n /** Initialize an empty thread */\n initialize(): Promise<void>;\n /** Load all messages from the thread */\n load(): Promise<T[]>;\n /**\n * Append messages to the thread.\n * When `idOf` is configured, appends are idempotent — retries with the\n * same message ids are atomically skipped via a Redis Lua script.\n */\n append(messages: T[]): Promise<void>;\n /** Delete the thread */\n delete(): Promise<void>;\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 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-manager\";\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/types\";\nimport type { ModelInvokerConfig } from \"../../lib/model-invoker\";\nimport { mapStoredMessagesToChatMessages } from \"@langchain/core/messages\";\nimport type { StoredMessage } from \"@langchain/core/messages\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport type {\n BaseChatModel,\n BaseChatModelCallOptions,\n BindToolsInput,\n} from \"@langchain/core/language_models/chat_models\";\nimport { createLangChainThreadManager } from \"./thread-manager\";\n\nexport interface LangChainModelInvokerConfig {\n redis: Redis;\n model: BaseChatModel<BaseChatModelCallOptions & { tools?: BindToolsInput }>;\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/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 * // Wrap with createRunAgentActivity to use as runAgent activity:\n * return { runAgent: createRunAgentActivity(client, invoker) };\n * ```\n */\nexport function createLangChainModelInvoker({\n redis,\n model,\n}: LangChainModelInvokerConfig) {\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: 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 */\nexport async function invokeLangChainModel({\n redis,\n model,\n config,\n}: {\n redis: Redis;\n config: ModelInvokerConfig;\n model: BaseChatModel<BaseChatModelCallOptions & { tools?: BindToolsInput }>;\n}): Promise<AgentResponse<StoredMessage>> {\n const invoker = createLangChainModelInvoker({ redis, model });\n return invoker(config);\n}\n","import type Redis from \"ioredis\";\nimport type { ThreadOps, ToolResultConfig } from \"../../lib/types\";\nimport type { MessageContent } from \"@langchain/core/messages\";\nimport type { ModelInvoker } from \"../../lib/model-invoker\";\nimport type { StoredMessage } from \"@langchain/core/messages\";\nimport type {\n BaseChatModel,\n BaseChatModelCallOptions,\n BindToolsInput,\n} from \"@langchain/core/language_models/chat_models\";\nimport { createLangChainThreadManager } from \"./thread-manager\";\nimport { createLangChainModelInvoker } from \"./model-invoker\";\n\ntype LangChainModel = BaseChatModel<\n BaseChatModelCallOptions & { tools?: BindToolsInput }\n>;\n\nexport interface LangChainAdapterConfig {\n redis: Redis;\n /** Optional default model — if omitted, use `createModelInvoker()` to create invokers later */\n model?: LangChainModel;\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 createModelInvoker(model: LangChainModel): 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/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\n const makeInvoker = (model: LangChainModel): 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 }) as unknown as ModelInvoker<StoredMessage>);\n\n return {\n threadOps,\n invoker,\n createModelInvoker: makeInvoker,\n };\n}\n"]}