zeitlich 0.2.24 → 0.2.26

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 (123) hide show
  1. package/dist/activities-BEJRyDVU.d.cts +137 -0
  2. package/dist/activities-LVQdLF6I.d.ts +137 -0
  3. package/dist/adapters/sandbox/bedrock/index.cjs +35 -10
  4. package/dist/adapters/sandbox/bedrock/index.cjs.map +1 -1
  5. package/dist/adapters/sandbox/bedrock/index.d.cts +2 -2
  6. package/dist/adapters/sandbox/bedrock/index.d.ts +2 -2
  7. package/dist/adapters/sandbox/bedrock/index.js +35 -10
  8. package/dist/adapters/sandbox/bedrock/index.js.map +1 -1
  9. package/dist/adapters/sandbox/bedrock/workflow.d.cts +1 -1
  10. package/dist/adapters/sandbox/bedrock/workflow.d.ts +1 -1
  11. package/dist/adapters/sandbox/virtual/index.cjs.map +1 -1
  12. package/dist/adapters/sandbox/virtual/index.d.cts +8 -7
  13. package/dist/adapters/sandbox/virtual/index.d.ts +8 -7
  14. package/dist/adapters/sandbox/virtual/index.js.map +1 -1
  15. package/dist/adapters/sandbox/virtual/workflow.d.cts +3 -2
  16. package/dist/adapters/sandbox/virtual/workflow.d.ts +3 -2
  17. package/dist/adapters/thread/anthropic/index.cjs +356 -0
  18. package/dist/adapters/thread/anthropic/index.cjs.map +1 -0
  19. package/dist/adapters/thread/anthropic/index.d.cts +148 -0
  20. package/dist/adapters/thread/anthropic/index.d.ts +148 -0
  21. package/dist/adapters/thread/anthropic/index.js +351 -0
  22. package/dist/adapters/thread/anthropic/index.js.map +1 -0
  23. package/dist/adapters/thread/anthropic/workflow.cjs +38 -0
  24. package/dist/adapters/thread/anthropic/workflow.cjs.map +1 -0
  25. package/dist/adapters/thread/anthropic/workflow.d.cts +37 -0
  26. package/dist/adapters/thread/anthropic/workflow.d.ts +37 -0
  27. package/dist/adapters/thread/anthropic/workflow.js +36 -0
  28. package/dist/adapters/thread/anthropic/workflow.js.map +1 -0
  29. package/dist/adapters/thread/google-genai/index.cjs +95 -97
  30. package/dist/adapters/thread/google-genai/index.cjs.map +1 -1
  31. package/dist/adapters/thread/google-genai/index.d.cts +9 -111
  32. package/dist/adapters/thread/google-genai/index.d.ts +9 -111
  33. package/dist/adapters/thread/google-genai/index.js +96 -97
  34. package/dist/adapters/thread/google-genai/index.js.map +1 -1
  35. package/dist/adapters/thread/google-genai/workflow.cjs +9 -4
  36. package/dist/adapters/thread/google-genai/workflow.cjs.map +1 -1
  37. package/dist/adapters/thread/google-genai/workflow.d.cts +10 -5
  38. package/dist/adapters/thread/google-genai/workflow.d.ts +10 -5
  39. package/dist/adapters/thread/google-genai/workflow.js +9 -4
  40. package/dist/adapters/thread/google-genai/workflow.js.map +1 -1
  41. package/dist/adapters/thread/langchain/index.cjs +43 -60
  42. package/dist/adapters/thread/langchain/index.cjs.map +1 -1
  43. package/dist/adapters/thread/langchain/index.d.cts +24 -38
  44. package/dist/adapters/thread/langchain/index.d.ts +24 -38
  45. package/dist/adapters/thread/langchain/index.js +43 -60
  46. package/dist/adapters/thread/langchain/index.js.map +1 -1
  47. package/dist/adapters/thread/langchain/workflow.cjs +9 -4
  48. package/dist/adapters/thread/langchain/workflow.cjs.map +1 -1
  49. package/dist/adapters/thread/langchain/workflow.d.cts +10 -5
  50. package/dist/adapters/thread/langchain/workflow.d.ts +10 -5
  51. package/dist/adapters/thread/langchain/workflow.js +9 -4
  52. package/dist/adapters/thread/langchain/workflow.js.map +1 -1
  53. package/dist/index.cjs +30 -12
  54. package/dist/index.cjs.map +1 -1
  55. package/dist/index.d.cts +13 -12
  56. package/dist/index.d.ts +13 -12
  57. package/dist/index.js +31 -13
  58. package/dist/index.js.map +1 -1
  59. package/dist/proxy-BK1ydQt0.d.ts +24 -0
  60. package/dist/proxy-BMAsMHdp.d.cts +24 -0
  61. package/dist/{queries-DwBe2CAA.d.ts → queries-BCgJ9Sr5.d.ts} +1 -1
  62. package/dist/{queries-BYGBImeC.d.cts → queries-DwnE2bu3.d.cts} +1 -1
  63. package/dist/thread-manager-CH9krS3h.d.ts +37 -0
  64. package/dist/thread-manager-Czhpxbt6.d.ts +29 -0
  65. package/dist/thread-manager-DOnQzImf.d.cts +29 -0
  66. package/dist/thread-manager-b4DML-qu.d.cts +37 -0
  67. package/dist/{types-35POpVfa.d.ts → types-BDRDbm3h.d.cts} +22 -1
  68. package/dist/{types-d9NznUqd.d.ts → types-BdCdR41N.d.ts} +10 -0
  69. package/dist/{types-hmferhc2.d.ts → types-CvJyXDYt.d.ts} +44 -123
  70. package/dist/{types-LVKmCNds.d.ts → types-DFUNSYbj.d.ts} +1 -1
  71. package/dist/{types-Bf8KV0Ci.d.cts → types-DRnz-OZp.d.cts} +1 -1
  72. package/dist/{types-7PeMi1bD.d.cts → types-DSOefLpY.d.cts} +44 -123
  73. package/dist/{types-35POpVfa.d.cts → types-WNSeZbWa.d.ts} +22 -1
  74. package/dist/{types-DhTCEMhr.d.cts → types-ZHs2v9Ap.d.cts} +10 -0
  75. package/dist/{types-D_igp10o.d.cts → types-mCVxKIZb.d.cts} +233 -137
  76. package/dist/{types-D_igp10o.d.ts → types-mCVxKIZb.d.ts} +233 -137
  77. package/dist/workflow.cjs +28 -11
  78. package/dist/workflow.cjs.map +1 -1
  79. package/dist/workflow.d.cts +11 -11
  80. package/dist/workflow.d.ts +11 -11
  81. package/dist/workflow.js +29 -12
  82. package/dist/workflow.js.map +1 -1
  83. package/package.json +26 -1
  84. package/src/adapters/sandbox/bedrock/filesystem.ts +43 -10
  85. package/src/adapters/sandbox/virtual/with-virtual-sandbox.ts +8 -3
  86. package/src/adapters/thread/anthropic/activities.ts +223 -0
  87. package/src/adapters/thread/anthropic/index.ts +44 -0
  88. package/src/adapters/thread/anthropic/model-invoker.ts +124 -0
  89. package/src/adapters/thread/anthropic/proxy.ts +33 -0
  90. package/src/adapters/thread/anthropic/thread-manager.ts +191 -0
  91. package/src/adapters/thread/google-genai/activities.ts +107 -32
  92. package/src/adapters/thread/google-genai/index.ts +3 -1
  93. package/src/adapters/thread/google-genai/model-invoker.ts +7 -40
  94. package/src/adapters/thread/google-genai/proxy.ts +6 -34
  95. package/src/adapters/thread/google-genai/thread-manager.ts +84 -104
  96. package/src/adapters/thread/langchain/activities.ts +53 -20
  97. package/src/adapters/thread/langchain/index.ts +3 -1
  98. package/src/adapters/thread/langchain/model-invoker.ts +7 -9
  99. package/src/adapters/thread/langchain/proxy.ts +6 -34
  100. package/src/adapters/thread/langchain/thread-manager.ts +44 -98
  101. package/src/index.ts +5 -1
  102. package/src/lib/activity.ts +4 -3
  103. package/src/lib/hooks/types.ts +12 -12
  104. package/src/lib/model/types.ts +2 -0
  105. package/src/lib/session/session-edge-cases.integration.test.ts +24 -6
  106. package/src/lib/session/session.ts +18 -14
  107. package/src/lib/session/types.ts +31 -14
  108. package/src/lib/subagent/handler.ts +20 -11
  109. package/src/lib/subagent/subagent.integration.test.ts +36 -4
  110. package/src/lib/subagent/types.ts +3 -2
  111. package/src/lib/thread/index.ts +2 -0
  112. package/src/lib/thread/manager.ts +4 -7
  113. package/src/lib/thread/proxy.ts +57 -0
  114. package/src/lib/thread/types.ts +31 -0
  115. package/src/lib/tool-router/auto-append-sandbox.integration.test.ts +54 -0
  116. package/src/lib/tool-router/auto-append.ts +5 -2
  117. package/src/lib/tool-router/router-edge-cases.integration.test.ts +9 -5
  118. package/src/lib/tool-router/router.ts +13 -7
  119. package/src/lib/tool-router/types.ts +20 -13
  120. package/src/lib/tool-router/with-sandbox.ts +4 -3
  121. package/src/lib/types.ts +7 -14
  122. package/src/workflow.ts +0 -4
  123. package/tsup.config.ts +5 -0
@@ -2,10 +2,13 @@ import type Redis from "ioredis";
2
2
  import type { Content, Part } from "@google/genai";
3
3
  import {
4
4
  createThreadManager,
5
- type BaseThreadManager,
5
+ type ProviderThreadManager,
6
6
  type ThreadManagerConfig,
7
7
  } from "../../../lib/thread";
8
- import type { MessageContent, ToolMessageContent } from "../../../lib/types";
8
+ import type { GoogleGenAIToolResponse } from "./activities";
9
+
10
+ /** SDK-native content type for Google GenAI human messages */
11
+ export type GoogleGenAIContent = string | Part[];
9
12
 
10
13
  /** A Content with a unique ID for idempotent Redis storage */
11
14
  export interface StoredContent {
@@ -20,71 +23,55 @@ export interface GoogleGenAIThreadManagerConfig {
20
23
  key?: string;
21
24
  }
22
25
 
26
+ /** Prepared payload ready to send to the Google GenAI API */
27
+ export interface GoogleGenAIInvocationPayload {
28
+ contents: Content[];
29
+ systemInstruction?: string;
30
+ }
31
+
23
32
  /** Thread manager with Google GenAI Content convenience helpers */
24
- export interface GoogleGenAIThreadManager extends BaseThreadManager<StoredContent> {
25
- createUserContent(
26
- id: string,
27
- content: string | MessageContent
28
- ): StoredContent;
29
- createSystemContent(id: string, content: string): StoredContent;
30
- createModelContent(id: string, parts: Part[]): StoredContent;
31
- createToolResponseContent(
32
- id: string,
33
- toolCallId: string,
34
- toolName: string,
35
- content: ToolMessageContent
36
- ): StoredContent;
37
- appendUserMessage(
38
- id: string,
39
- content: string | MessageContent
40
- ): Promise<void>;
41
- appendSystemMessage(id: string, content: string): Promise<void>;
33
+ export interface GoogleGenAIThreadManager
34
+ extends ProviderThreadManager<StoredContent, GoogleGenAIContent, GoogleGenAIToolResponse> {
42
35
  appendModelContent(id: string, parts: Part[]): Promise<void>;
43
- appendToolResult(
44
- id: string,
45
- toolCallId: string,
46
- toolName: string,
47
- content: ToolMessageContent
48
- ): Promise<void>;
36
+ prepareForInvocation(): Promise<GoogleGenAIInvocationPayload>;
49
37
  }
50
38
 
51
39
  function storedContentId(msg: StoredContent): string {
52
40
  return msg.id;
53
41
  }
54
42
 
55
- /** Convert zeitlich MessageContent to Google GenAI Part[] */
56
- export function messageContentToParts(
57
- content: string | MessageContent
58
- ): Part[] {
43
+ /** Normalise content into Part[] */
44
+ function toParts(content: GoogleGenAIContent): Part[] {
59
45
  if (typeof content === "string") {
60
46
  return [{ text: content }];
61
47
  }
62
- if (Array.isArray(content)) {
63
- return content.map((part) => {
64
- if (part.type === "text") {
65
- return { text: part.text as string };
66
- }
67
- return part as unknown as Part;
68
- });
48
+ return content;
49
+ }
50
+
51
+ /** Convert a string or object into a Record suitable for functionResponse.response */
52
+ function toFunctionResponse(content: string | Record<string, unknown>): Record<string, unknown> {
53
+ if (typeof content === "object") {
54
+ return content;
69
55
  }
70
- return [{ text: String(content) }];
56
+ return { result: content };
71
57
  }
72
58
 
73
- /** Parse ToolMessageContent into a Record suitable for functionResponse */
74
- function parseToolResponse(
75
- content: ToolMessageContent
76
- ): Record<string, unknown> {
77
- if (typeof content === "string") {
78
- try {
79
- const parsed: unknown = JSON.parse(content);
80
- return typeof parsed === "object" && parsed !== null
81
- ? (parsed as Record<string, unknown>)
82
- : { result: content };
83
- } catch {
84
- return { result: content };
59
+ /**
60
+ * Merge consecutive Content objects sharing the same role.
61
+ * The Gemini API requires alternating user/model turns; without
62
+ * merging, multiple sequential tool-result messages would violate this.
63
+ */
64
+ function mergeConsecutiveContents(contents: Content[]): Content[] {
65
+ const merged: Content[] = [];
66
+ for (const content of contents) {
67
+ const last = merged[merged.length - 1];
68
+ if (last && last.role === content.role) {
69
+ last.parts = [...(last.parts ?? []), ...(content.parts ?? [])];
70
+ } else {
71
+ merged.push({ ...content, parts: [...(content.parts ?? [])] });
85
72
  }
86
73
  }
87
- return { result: content };
74
+ return merged;
88
75
  }
89
76
 
90
77
  /**
@@ -93,7 +80,7 @@ function parseToolResponse(
93
80
  * appending typed Content messages.
94
81
  */
95
82
  export function createGoogleGenAIThreadManager(
96
- config: GoogleGenAIThreadManagerConfig
83
+ config: GoogleGenAIThreadManagerConfig,
97
84
  ): GoogleGenAIThreadManager {
98
85
  const baseConfig: ThreadManagerConfig<StoredContent> = {
99
86
  redis: config.redis,
@@ -104,79 +91,72 @@ export function createGoogleGenAIThreadManager(
104
91
 
105
92
  const base = createThreadManager(baseConfig);
106
93
 
107
- const helpers = {
108
- createUserContent(
94
+ const helpers: Omit<GoogleGenAIThreadManager, keyof typeof base> = {
95
+ async appendUserMessage(
109
96
  id: string,
110
- content: string | MessageContent
111
- ): StoredContent {
112
- return {
97
+ content: GoogleGenAIContent,
98
+ ): Promise<void> {
99
+ await base.append([{
113
100
  id,
114
- content: { role: "user", parts: messageContentToParts(content) },
115
- };
101
+ content: { role: "user", parts: toParts(content) },
102
+ }]);
116
103
  },
117
104
 
118
- createSystemContent(id: string, content: string): StoredContent {
119
- return {
105
+ async appendSystemMessage(id: string, content: string): Promise<void> {
106
+ await base.initialize();
107
+ await base.append([{
120
108
  id,
121
109
  content: { role: "system", parts: [{ text: content }] },
122
- };
110
+ }]);
123
111
  },
124
112
 
125
- createModelContent(id: string, parts: Part[]): StoredContent {
126
- return {
113
+ async appendModelContent(id: string, parts: Part[]): Promise<void> {
114
+ await base.append([{
127
115
  id,
128
116
  content: { role: "model", parts },
129
- };
117
+ }]);
130
118
  },
131
119
 
132
- createToolResponseContent(
120
+ async appendToolResult(
133
121
  id: string,
134
122
  toolCallId: string,
135
123
  toolName: string,
136
- content: ToolMessageContent
137
- ): StoredContent {
138
- return {
139
- id,
140
- content: {
141
- role: "user",
142
- parts: [
143
- {
144
- functionResponse: {
145
- id: toolCallId,
146
- name: toolName,
147
- response: parseToolResponse(content),
148
- },
124
+ content: GoogleGenAIToolResponse,
125
+ ): Promise<void> {
126
+ const parts: Part[] = Array.isArray(content)
127
+ ? content as Part[]
128
+ : [{
129
+ functionResponse: {
130
+ id: toolCallId,
131
+ name: toolName,
132
+ response: toFunctionResponse(content),
149
133
  },
150
- ],
151
- },
152
- };
153
- },
134
+ }];
154
135
 
155
- async appendUserMessage(
156
- id: string,
157
- content: string | MessageContent
158
- ): Promise<void> {
159
- await base.append([helpers.createUserContent(id, content)]);
136
+ await base.append([{
137
+ id,
138
+ content: { role: "user", parts },
139
+ }]);
160
140
  },
161
141
 
162
- async appendSystemMessage(id: string, content: string): Promise<void> {
163
- await base.initialize();
164
- await base.append([helpers.createSystemContent(id, content)]);
165
- },
142
+ async prepareForInvocation(): Promise<GoogleGenAIInvocationPayload> {
143
+ const stored = await base.load();
166
144
 
167
- async appendModelContent(id: string, parts: Part[]): Promise<void> {
168
- await base.append([helpers.createModelContent(id, parts)]);
169
- },
145
+ let systemInstruction: string | undefined;
146
+ const conversationContents: Content[] = [];
170
147
 
171
- async appendToolResult(
172
- id: string,
173
- toolCallId: string,
174
- toolName: string,
175
- content: ToolMessageContent
176
- ): Promise<void> {
177
- await base.append([
178
- helpers.createToolResponseContent(id, toolCallId, toolName, content),
179
- ]);
148
+ for (const item of stored) {
149
+ if (item.content.role === "system") {
150
+ systemInstruction = item.content.parts?.[0]?.text;
151
+ } else {
152
+ conversationContents.push(item.content);
153
+ }
154
+ }
155
+
156
+ return {
157
+ contents: mergeConsecutiveContents(conversationContents),
158
+ ...(systemInstruction ? { systemInstruction } : {}),
159
+ };
180
160
  },
181
161
  };
182
162
 
@@ -1,6 +1,11 @@
1
1
  import type Redis from "ioredis";
2
2
  import type { ToolResultConfig } from "../../../lib/types";
3
3
  import type { MessageContent } from "@langchain/core/messages";
4
+ import type {
5
+ ActivityToolHandler,
6
+ RouterContext,
7
+ ToolHandlerResponse,
8
+ } from "../../../lib/tool-router/types";
4
9
  import type {
5
10
  ThreadOps,
6
11
  PrefixedThreadOps,
@@ -9,13 +14,16 @@ import type {
9
14
  import type { ModelInvoker } from "../../../lib/model";
10
15
  import type { StoredMessage } from "@langchain/core/messages";
11
16
  import type { BaseChatModel } from "@langchain/core/language_models/chat_models";
12
- import { createLangChainThreadManager } from "./thread-manager";
17
+ import {
18
+ createLangChainThreadManager,
19
+ type LangChainContent,
20
+ } from "./thread-manager";
13
21
  import { createLangChainModelInvoker } from "./model-invoker";
14
22
 
15
23
  const ADAPTER_PREFIX = "langChain" as const;
16
24
 
17
25
  export type LangChainThreadOps<TScope extends string = ""> =
18
- PrefixedThreadOps<ScopedPrefix<TScope, typeof ADAPTER_PREFIX>>;
26
+ PrefixedThreadOps<ScopedPrefix<TScope, typeof ADAPTER_PREFIX>, LangChainContent>;
19
27
 
20
28
  export interface LangChainAdapterConfig {
21
29
  redis: Redis;
@@ -24,6 +32,15 @@ export interface LangChainAdapterConfig {
24
32
  model?: BaseChatModel<any>;
25
33
  }
26
34
 
35
+ /**
36
+ * Tool response type accepted by the LangChain adapter.
37
+ *
38
+ * Content is passed directly to `ToolMessage` as `MessageContent`.
39
+ * Handlers can return a string or an array of content blocks
40
+ * (e.g. `{ type: "text", text: "..." }`, `{ type: "image_url", image_url: { ... } }`).
41
+ */
42
+ export type LangChainToolResponse = MessageContent;
43
+
27
44
  export interface LangChainAdapter {
28
45
  /** Model invoker using the default model (only available when `model` was provided) */
29
46
  invoker: ModelInvoker<StoredMessage>;
@@ -42,8 +59,19 @@ export interface LangChainAdapter {
42
59
  * ```
43
60
  */
44
61
  createActivities<S extends string = "">(
45
- scope?: S
62
+ scope?: S,
46
63
  ): LangChainThreadOps<S>;
64
+
65
+ /**
66
+ * Identity wrapper that types a tool handler for this adapter.
67
+ * Constrains `toolResponse` to {@link LangChainToolResponse}.
68
+ */
69
+ wrapHandler<TArgs, TResult, TContext extends RouterContext = RouterContext>(
70
+ handler: (
71
+ args: TArgs,
72
+ context: TContext,
73
+ ) => Promise<ToolHandlerResponse<TResult, LangChainToolResponse>>,
74
+ ): ActivityToolHandler<TArgs, TResult, TContext, LangChainToolResponse>;
47
75
  }
48
76
 
49
77
  /**
@@ -82,54 +110,58 @@ export interface LangChainAdapter {
82
110
  * ```
83
111
  */
84
112
  export function createLangChainAdapter(
85
- config: LangChainAdapterConfig
113
+ config: LangChainAdapterConfig,
86
114
  ): LangChainAdapter {
87
115
  const { redis } = config;
88
116
 
89
- const threadOps: ThreadOps = {
90
- async initializeThread(threadId: string): Promise<void> {
91
- const thread = createLangChainThreadManager({ redis, threadId });
117
+ const threadOps: ThreadOps<LangChainContent> = {
118
+ async initializeThread(threadId: string, threadKey?: string): Promise<void> {
119
+ const thread = createLangChainThreadManager({ redis, threadId, key: threadKey });
92
120
  await thread.initialize();
93
121
  },
94
122
 
95
123
  async appendHumanMessage(
96
124
  threadId: string,
97
125
  id: string,
98
- content: string | MessageContent
126
+ content: LangChainContent,
127
+ threadKey?: string,
99
128
  ): Promise<void> {
100
- const thread = createLangChainThreadManager({ redis, threadId });
101
- await thread.appendHumanMessage(id, content);
129
+ const thread = createLangChainThreadManager({ redis, threadId, key: threadKey });
130
+ await thread.appendUserMessage(id, content);
102
131
  },
103
132
 
104
133
  async appendSystemMessage(
105
134
  threadId: string,
106
135
  id: string,
107
- content: string
136
+ content: string,
137
+ threadKey?: string,
108
138
  ): Promise<void> {
109
- const thread = createLangChainThreadManager({ redis, threadId });
139
+ const thread = createLangChainThreadManager({ redis, threadId, key: threadKey });
110
140
  await thread.appendSystemMessage(id, content);
111
141
  },
112
142
 
113
143
  async appendToolResult(id: string, cfg: ToolResultConfig): Promise<void> {
114
- const { threadId, toolCallId, content } = cfg;
115
- const thread = createLangChainThreadManager({ redis, threadId });
116
- await thread.appendToolMessage(id, content, toolCallId);
144
+ const { threadId, threadKey, toolCallId, content } = cfg;
145
+ const thread = createLangChainThreadManager({ redis, threadId, key: threadKey });
146
+ await thread.appendToolResult(id, toolCallId, "", content);
117
147
  },
118
148
 
119
149
  async forkThread(
120
150
  sourceThreadId: string,
121
- targetThreadId: string
151
+ targetThreadId: string,
152
+ threadKey?: string,
122
153
  ): Promise<void> {
123
154
  const thread = createLangChainThreadManager({
124
155
  redis,
125
156
  threadId: sourceThreadId,
157
+ key: threadKey,
126
158
  });
127
159
  await thread.fork(targetThreadId);
128
160
  },
129
161
  };
130
162
 
131
163
  function createActivities<S extends string = "">(
132
- scope?: S
164
+ scope?: S,
133
165
  ): LangChainThreadOps<S> {
134
166
  const prefix = scope
135
167
  ? `${ADAPTER_PREFIX}${scope.charAt(0).toUpperCase()}${scope.slice(1)}`
@@ -137,13 +169,13 @@ export function createLangChainAdapter(
137
169
  const cap = (s: string): string =>
138
170
  s.charAt(0).toUpperCase() + s.slice(1);
139
171
  return Object.fromEntries(
140
- Object.entries(threadOps).map(([k, v]) => [`${prefix}${cap(k)}`, v])
172
+ Object.entries(threadOps).map(([k, v]) => [`${prefix}${cap(k)}`, v]),
141
173
  ) as LangChainThreadOps<S>;
142
174
  }
143
175
 
144
176
  const makeInvoker = (
145
177
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
146
- model: BaseChatModel<any>
178
+ model: BaseChatModel<any>,
147
179
  ): ModelInvoker<StoredMessage> =>
148
180
  createLangChainModelInvoker({ redis, model });
149
181
 
@@ -152,7 +184,7 @@ export function createLangChainAdapter(
152
184
  : () => {
153
185
  throw new Error(
154
186
  "No default model provided to createLangChainAdapter. " +
155
- "Either pass `model` in the config or use `createModelInvoker(model)` instead."
187
+ "Either pass `model` in the config or use `createModelInvoker(model)` instead.",
156
188
  );
157
189
  };
158
190
 
@@ -160,5 +192,6 @@ export function createLangChainAdapter(
160
192
  createActivities,
161
193
  invoker,
162
194
  createModelInvoker: makeInvoker,
195
+ wrapHandler: (handler) => handler,
163
196
  };
164
197
  }
@@ -21,6 +21,7 @@ export {
21
21
  type LangChainAdapter,
22
22
  type LangChainAdapterConfig,
23
23
  type LangChainThreadOps,
24
+ type LangChainToolResponse,
24
25
  } from "./activities";
25
26
 
26
27
  // Thread manager
@@ -28,7 +29,8 @@ export {
28
29
  createLangChainThreadManager,
29
30
  type LangChainThreadManager,
30
31
  type LangChainThreadManagerConfig,
31
- type LangChainToolMessageContent,
32
+ type LangChainContent,
33
+ type LangChainInvocationPayload,
32
34
  } from "./thread-manager";
33
35
 
34
36
  // Model invoker (for advanced use — prefer adapter.createModelInvoker)
@@ -1,7 +1,5 @@
1
1
  import type Redis from "ioredis";
2
- import type { AgentResponse } from "../../../lib/model";
3
- import type { ModelInvokerConfig } from "../../../lib/model";
4
- import { mapStoredMessagesToChatMessages } from "@langchain/core/messages";
2
+ import type { AgentResponse, ModelInvokerConfig } from "../../../lib/model";
5
3
  import type { StoredMessage } from "@langchain/core/messages";
6
4
  import { v4 as uuidv4 } from "uuid";
7
5
  import type { BaseChatModel } from "@langchain/core/language_models/chat_models";
@@ -37,22 +35,22 @@ export function createLangChainModelInvoker<TModel extends BaseChatModel<any> =
37
35
  { redis, model }: LangChainModelInvokerConfig<TModel>,
38
36
  ) {
39
37
  return async function invokeLangChainModel(
40
- config: ModelInvokerConfig
38
+ config: ModelInvokerConfig,
41
39
  ): Promise<AgentResponse<StoredMessage>> {
42
- const { threadId, agentName, state, metadata } = config;
40
+ const { threadId, threadKey, agentName, state, metadata } = config;
43
41
 
44
- const thread = createLangChainThreadManager({ redis, threadId });
42
+ const thread = createLangChainThreadManager({ redis, threadId, key: threadKey });
45
43
  const runId = uuidv4();
46
44
 
47
- const messages = await thread.load();
45
+ const { messages } = await thread.prepareForInvocation();
48
46
  const response = await model.invoke(
49
- [...mapStoredMessagesToChatMessages(messages)],
47
+ messages,
50
48
  {
51
49
  runName: agentName,
52
50
  runId,
53
51
  metadata: { thread_id: `${agentName}-${threadId}`, ...metadata },
54
52
  tools: state.tools,
55
- }
53
+ },
56
54
  );
57
55
 
58
56
  await thread.append([response.toDict()]);
@@ -18,44 +18,16 @@
18
18
  * const threadOps = proxyLangChainThreadOps("customScope");
19
19
  * ```
20
20
  */
21
- import {
22
- proxyActivities,
23
- workflowInfo,
24
- type ActivityInterfaceFor,
25
- } from "@temporalio/workflow";
21
+ import { type ActivityInterfaceFor } from "@temporalio/workflow";
26
22
  import type { ThreadOps } from "../../../lib/session/types";
23
+ import type { LangChainContent } from "./thread-manager";
24
+ import { createThreadOpsProxy } from "../../../lib/thread/proxy";
27
25
 
28
26
  const ADAPTER_PREFIX = "langChain";
29
27
 
30
28
  export function proxyLangChainThreadOps(
31
29
  scope?: string,
32
- options?: Parameters<typeof proxyActivities>[0]
33
- ): ActivityInterfaceFor<ThreadOps> {
34
- const resolvedScope = scope ?? workflowInfo().workflowType;
35
-
36
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
37
- const acts = proxyActivities<Record<string, (...args: any[]) => any>>(
38
- options ?? {
39
- startToCloseTimeout: "10s",
40
- retry: {
41
- maximumAttempts: 6,
42
- initialInterval: "5s",
43
- maximumInterval: "15m",
44
- backoffCoefficient: 4,
45
- },
46
- }
47
- );
48
-
49
- const prefix =
50
- `${ADAPTER_PREFIX}${resolvedScope.charAt(0).toUpperCase()}${resolvedScope.slice(1)}`;
51
- const p = (key: string): string =>
52
- `${prefix}${key.charAt(0).toUpperCase()}${key.slice(1)}`;
53
-
54
- return {
55
- initializeThread: acts[p("initializeThread")],
56
- appendHumanMessage: acts[p("appendHumanMessage")],
57
- appendToolResult: acts[p("appendToolResult")],
58
- appendSystemMessage: acts[p("appendSystemMessage")],
59
- forkThread: acts[p("forkThread")],
60
- } as ActivityInterfaceFor<ThreadOps>;
30
+ options?: Parameters<typeof createThreadOpsProxy>[2],
31
+ ): ActivityInterfaceFor<ThreadOps<LangChainContent>> {
32
+ return createThreadOpsProxy(ADAPTER_PREFIX, scope, options) as ActivityInterfaceFor<ThreadOps<LangChainContent>>;
61
33
  }