@assistant-ui/react-langgraph 0.0.3 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +49 -24
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +49 -23
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -34,22 +34,22 @@ type LangChainEvent = {
|
|
|
34
34
|
|
|
35
35
|
declare const useLangGraphRuntime: ({ threadId, stream, }: {
|
|
36
36
|
threadId?: string | undefined;
|
|
37
|
-
stream: (
|
|
37
|
+
stream: (messages: LangChainMessage[]) => Promise<AsyncGenerator<{
|
|
38
38
|
event: string;
|
|
39
39
|
data: any;
|
|
40
40
|
}>>;
|
|
41
41
|
}) => ExternalStoreRuntime;
|
|
42
42
|
|
|
43
43
|
declare const useLangGraphMessages: <TMessage>({ stream, }: {
|
|
44
|
-
stream: (
|
|
44
|
+
stream: (messages: TMessage[]) => Promise<AsyncGenerator<{
|
|
45
45
|
event: string;
|
|
46
46
|
data: any;
|
|
47
47
|
}>>;
|
|
48
48
|
}) => {
|
|
49
49
|
messages: TMessage[];
|
|
50
|
-
sendMessage: (
|
|
50
|
+
sendMessage: (messages: TMessage[]) => Promise<void>;
|
|
51
51
|
};
|
|
52
52
|
|
|
53
53
|
declare const convertLangchainMessages: useExternalMessageConverter.Callback<LangChainMessage>;
|
|
54
54
|
|
|
55
|
-
export { type LangChainEvent, type LangChainMessage, type LangChainToolCall, type LangChainToolCallChunk, convertLangchainMessages,
|
|
55
|
+
export { type LangChainEvent, type LangChainMessage, type LangChainToolCall, type LangChainToolCallChunk, convertLangchainMessages, useLangGraphMessages, useLangGraphRuntime };
|
package/dist/index.d.ts
CHANGED
|
@@ -34,22 +34,22 @@ type LangChainEvent = {
|
|
|
34
34
|
|
|
35
35
|
declare const useLangGraphRuntime: ({ threadId, stream, }: {
|
|
36
36
|
threadId?: string | undefined;
|
|
37
|
-
stream: (
|
|
37
|
+
stream: (messages: LangChainMessage[]) => Promise<AsyncGenerator<{
|
|
38
38
|
event: string;
|
|
39
39
|
data: any;
|
|
40
40
|
}>>;
|
|
41
41
|
}) => ExternalStoreRuntime;
|
|
42
42
|
|
|
43
43
|
declare const useLangGraphMessages: <TMessage>({ stream, }: {
|
|
44
|
-
stream: (
|
|
44
|
+
stream: (messages: TMessage[]) => Promise<AsyncGenerator<{
|
|
45
45
|
event: string;
|
|
46
46
|
data: any;
|
|
47
47
|
}>>;
|
|
48
48
|
}) => {
|
|
49
49
|
messages: TMessage[];
|
|
50
|
-
sendMessage: (
|
|
50
|
+
sendMessage: (messages: TMessage[]) => Promise<void>;
|
|
51
51
|
};
|
|
52
52
|
|
|
53
53
|
declare const convertLangchainMessages: useExternalMessageConverter.Callback<LangChainMessage>;
|
|
54
54
|
|
|
55
|
-
export { type LangChainEvent, type LangChainMessage, type LangChainToolCall, type LangChainToolCallChunk, convertLangchainMessages,
|
|
55
|
+
export { type LangChainEvent, type LangChainMessage, type LangChainToolCall, type LangChainToolCallChunk, convertLangchainMessages, useLangGraphMessages, useLangGraphRuntime };
|
package/dist/index.js
CHANGED
|
@@ -21,7 +21,6 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var src_exports = {};
|
|
22
22
|
__export(src_exports, {
|
|
23
23
|
convertLangchainMessages: () => convertLangchainMessages,
|
|
24
|
-
useLangChainLangGraphRuntime: () => useLangGraphRuntime,
|
|
25
24
|
useLangGraphMessages: () => useLangGraphMessages,
|
|
26
25
|
useLangGraphRuntime: () => useLangGraphRuntime
|
|
27
26
|
});
|
|
@@ -83,23 +82,23 @@ var useLangGraphMessages = ({
|
|
|
83
82
|
}) => {
|
|
84
83
|
const [messages, setMessages] = (0, import_react.useState)([]);
|
|
85
84
|
const sendMessage = (0, import_react.useCallback)(
|
|
86
|
-
async (
|
|
87
|
-
if (
|
|
88
|
-
setMessages((currentMessages) => [...currentMessages,
|
|
85
|
+
async (messages2) => {
|
|
86
|
+
if (messages2.length > 0) {
|
|
87
|
+
setMessages((currentMessages) => [...currentMessages, ...messages2]);
|
|
89
88
|
}
|
|
90
|
-
const response = await stream(
|
|
89
|
+
const response = await stream(messages2);
|
|
91
90
|
const completeMessages = [];
|
|
92
91
|
let partialMessages = /* @__PURE__ */ new Map();
|
|
93
92
|
for await (const chunk of response) {
|
|
94
93
|
if (chunk.event === "messages/partial") {
|
|
95
|
-
for (const
|
|
96
|
-
if (!
|
|
97
|
-
partialMessages.set(
|
|
94
|
+
for (const message of chunk.data) {
|
|
95
|
+
if (!message.id) throw new Error("Partial message missing id");
|
|
96
|
+
partialMessages.set(message.id, message);
|
|
98
97
|
}
|
|
99
98
|
} else if (chunk.event === "messages/complete") {
|
|
100
|
-
for (const
|
|
101
|
-
if (!
|
|
102
|
-
partialMessages.delete(
|
|
99
|
+
for (const message of chunk.data) {
|
|
100
|
+
if (!message.id) continue;
|
|
101
|
+
partialMessages.delete(message.id);
|
|
103
102
|
}
|
|
104
103
|
completeMessages.push(...chunk.data);
|
|
105
104
|
} else {
|
|
@@ -117,6 +116,20 @@ var useLangGraphMessages = ({
|
|
|
117
116
|
};
|
|
118
117
|
|
|
119
118
|
// src/useLangGraphRuntime.ts
|
|
119
|
+
var getPendingToolCalls = (messages) => {
|
|
120
|
+
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
121
|
+
for (const message of messages) {
|
|
122
|
+
if (message.type === "ai") {
|
|
123
|
+
for (const toolCall of message.tool_calls ?? []) {
|
|
124
|
+
pendingToolCalls.set(toolCall.id, toolCall);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
if (message.type === "tool") {
|
|
128
|
+
pendingToolCalls.delete(message.tool_call_id);
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return [...pendingToolCalls.values()];
|
|
132
|
+
};
|
|
120
133
|
var useLangGraphRuntime = ({
|
|
121
134
|
threadId,
|
|
122
135
|
stream
|
|
@@ -125,10 +138,10 @@ var useLangGraphRuntime = ({
|
|
|
125
138
|
stream
|
|
126
139
|
});
|
|
127
140
|
const [isRunning, setIsRunning] = (0, import_react2.useState)(false);
|
|
128
|
-
const handleSendMessage = async (
|
|
141
|
+
const handleSendMessage = async (messages2) => {
|
|
129
142
|
try {
|
|
130
143
|
setIsRunning(true);
|
|
131
|
-
await sendMessage(
|
|
144
|
+
await sendMessage(messages2);
|
|
132
145
|
} catch (error) {
|
|
133
146
|
console.error("Error streaming messages:", error);
|
|
134
147
|
} finally {
|
|
@@ -147,25 +160,37 @@ var useLangGraphRuntime = ({
|
|
|
147
160
|
onNew: (msg) => {
|
|
148
161
|
if (msg.content.length !== 1 || msg.content[0]?.type !== "text")
|
|
149
162
|
throw new Error("Only text messages are supported");
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
163
|
+
const cancellations = getPendingToolCalls(messages).map(
|
|
164
|
+
(t) => ({
|
|
165
|
+
type: "tool",
|
|
166
|
+
name: t.name,
|
|
167
|
+
tool_call_id: t.id,
|
|
168
|
+
content: JSON.stringify({ cancelled: true })
|
|
169
|
+
})
|
|
170
|
+
);
|
|
171
|
+
return handleSendMessage([
|
|
172
|
+
...cancellations,
|
|
173
|
+
{
|
|
174
|
+
type: "human",
|
|
175
|
+
content: msg.content[0].text
|
|
176
|
+
}
|
|
177
|
+
]);
|
|
154
178
|
},
|
|
155
179
|
onAddToolResult: async ({ toolCallId, toolName, result }) => {
|
|
156
|
-
await handleSendMessage(
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
180
|
+
await handleSendMessage([
|
|
181
|
+
{
|
|
182
|
+
type: "tool",
|
|
183
|
+
name: toolName,
|
|
184
|
+
tool_call_id: toolCallId,
|
|
185
|
+
content: JSON.stringify(result)
|
|
186
|
+
}
|
|
187
|
+
]);
|
|
162
188
|
}
|
|
163
189
|
});
|
|
164
190
|
};
|
|
165
191
|
// Annotate the CommonJS export names for ESM import in node:
|
|
166
192
|
0 && (module.exports = {
|
|
167
193
|
convertLangchainMessages,
|
|
168
|
-
useLangChainLangGraphRuntime,
|
|
169
194
|
useLangGraphMessages,
|
|
170
195
|
useLangGraphRuntime
|
|
171
196
|
});
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/useLangGraphRuntime.ts","../src/convertLangchainMessages.ts","../src/useLangGraphMessages.ts"],"sourcesContent":["export { useLangGraphRuntime } from \"./useLangGraphRuntime\";\n\nexport { useLangGraphMessages } from \"./useLangGraphMessages\";\nexport { convertLangchainMessages } from \"./convertLangchainMessages\";\nexport type {\n LangChainMessage,\n LangChainEvent,\n LangChainToolCall,\n LangChainToolCallChunk,\n} from \"./types\";\n
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/useLangGraphRuntime.ts","../src/convertLangchainMessages.ts","../src/useLangGraphMessages.ts"],"sourcesContent":["export { useLangGraphRuntime } from \"./useLangGraphRuntime\";\n\nexport { useLangGraphMessages } from \"./useLangGraphMessages\";\nexport { convertLangchainMessages } from \"./convertLangchainMessages\";\nexport type {\n LangChainMessage,\n LangChainEvent,\n LangChainToolCall,\n LangChainToolCallChunk,\n} from \"./types\";\n","import { useState } from \"react\";\nimport { LangChainMessage, LangChainToolCall } from \"./types\";\nimport {\n useExternalMessageConverter,\n useExternalStoreRuntime,\n} from \"@assistant-ui/react\";\nimport { convertLangchainMessages } from \"./convertLangchainMessages\";\nimport { useLangGraphMessages } from \"./useLangGraphMessages\";\nimport { ExternalStoreRuntime } from \"@assistant-ui/react\";\n\nconst getPendingToolCalls = (messages: LangChainMessage[]) => {\n const pendingToolCalls = new Map<string, LangChainToolCall>();\n for (const message of messages) {\n if (message.type === \"ai\") {\n for (const toolCall of message.tool_calls ?? []) {\n pendingToolCalls.set(toolCall.id, toolCall);\n }\n }\n if (message.type === \"tool\") {\n pendingToolCalls.delete(message.tool_call_id);\n }\n }\n\n return [...pendingToolCalls.values()];\n};\n\nexport const useLangGraphRuntime = ({\n threadId,\n stream,\n}: {\n threadId?: string | undefined;\n stream: (messages: LangChainMessage[]) => Promise<\n AsyncGenerator<{\n event: string;\n data: any;\n }>\n >;\n}): ExternalStoreRuntime => {\n const { messages, sendMessage } = useLangGraphMessages({\n stream,\n });\n\n const [isRunning, setIsRunning] = useState(false);\n const handleSendMessage = async (messages: LangChainMessage[]) => {\n try {\n setIsRunning(true);\n await sendMessage(messages);\n } catch (error) {\n console.error(\"Error streaming messages:\", error);\n } finally {\n setIsRunning(false);\n }\n };\n\n const threadMessages = useExternalMessageConverter({\n callback: convertLangchainMessages,\n messages,\n isRunning,\n });\n\n return useExternalStoreRuntime({\n threadId,\n isRunning,\n messages: threadMessages,\n onNew: (msg) => {\n if (msg.content.length !== 1 || msg.content[0]?.type !== \"text\")\n throw new Error(\"Only text messages are supported\");\n\n const cancellations = getPendingToolCalls(messages).map(\n (t) =>\n ({\n type: \"tool\",\n name: t.name,\n tool_call_id: t.id,\n content: JSON.stringify({ cancelled: true }),\n }) satisfies LangChainMessage & { type: \"tool\" },\n );\n return handleSendMessage([\n ...cancellations,\n {\n type: \"human\",\n content: msg.content[0].text,\n },\n ]);\n },\n onAddToolResult: async ({ toolCallId, toolName, result }) => {\n await handleSendMessage([\n {\n type: \"tool\",\n name: toolName,\n tool_call_id: toolCallId,\n content: JSON.stringify(result),\n },\n ]);\n },\n });\n};\n","\"use client\";\n\nimport { useExternalMessageConverter } from \"@assistant-ui/react\";\nimport { LangChainMessage } from \"./types\";\nimport { ToolCallContentPart } from \"@assistant-ui/react\";\n\nexport const convertLangchainMessages: useExternalMessageConverter.Callback<\n LangChainMessage\n> = (message) => {\n switch (message.type) {\n case \"system\":\n return {\n role: \"system\",\n id: message.id,\n content: [{ type: \"text\", text: message.content }],\n };\n case \"human\":\n return {\n role: \"user\",\n id: message.id,\n content: [{ type: \"text\", text: message.content }],\n };\n case \"ai\":\n return {\n role: \"assistant\",\n id: message.id,\n content: [\n {\n type: \"text\",\n text: message.content,\n },\n ...(message.tool_calls?.map(\n (chunk): ToolCallContentPart => ({\n type: \"tool-call\",\n toolCallId: chunk.id,\n toolName: chunk.name,\n args: chunk.args,\n argsText:\n message.tool_call_chunks?.find((c) => c.id === chunk.id)\n ?.args ?? JSON.stringify(chunk.args),\n }),\n ) ?? []),\n ],\n };\n case \"tool\":\n return {\n role: \"tool\",\n toolName: message.name,\n toolCallId: message.tool_call_id,\n result: message.content,\n };\n }\n};\n","import { useState, useCallback } from \"react\";\n\nexport const useLangGraphMessages = <TMessage>({\n stream,\n}: {\n stream: (messages: TMessage[]) => Promise<\n AsyncGenerator<{\n event: string;\n data: any;\n }>\n >;\n}) => {\n const [messages, setMessages] = useState<TMessage[]>([]);\n\n const sendMessage = useCallback(\n async (messages: TMessage[]) => {\n if (messages.length > 0) {\n setMessages((currentMessages) => [...currentMessages, ...messages]);\n }\n\n const response = await stream(messages);\n\n const completeMessages: TMessage[] = [];\n let partialMessages: Map<string, TMessage> = new Map();\n for await (const chunk of response) {\n if (chunk.event === \"messages/partial\") {\n for (const message of chunk.data) {\n if (!message.id) throw new Error(\"Partial message missing id\");\n\n partialMessages.set(message.id, message);\n }\n } else if (chunk.event === \"messages/complete\") {\n for (const message of chunk.data) {\n if (!message.id) continue;\n partialMessages.delete(message.id);\n }\n\n completeMessages.push(...chunk.data);\n } else {\n continue;\n }\n\n setMessages([...completeMessages, ...partialMessages.values()]);\n }\n if (partialMessages.size > 0) {\n throw new Error(\"A partial message was not marked as complete\");\n }\n },\n [stream],\n );\n\n return { messages, sendMessage };\n};\n"],"mappings":"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","names":["import_react","messages","messages"]}
|
package/dist/index.mjs
CHANGED
|
@@ -57,23 +57,23 @@ var useLangGraphMessages = ({
|
|
|
57
57
|
}) => {
|
|
58
58
|
const [messages, setMessages] = useState([]);
|
|
59
59
|
const sendMessage = useCallback(
|
|
60
|
-
async (
|
|
61
|
-
if (
|
|
62
|
-
setMessages((currentMessages) => [...currentMessages,
|
|
60
|
+
async (messages2) => {
|
|
61
|
+
if (messages2.length > 0) {
|
|
62
|
+
setMessages((currentMessages) => [...currentMessages, ...messages2]);
|
|
63
63
|
}
|
|
64
|
-
const response = await stream(
|
|
64
|
+
const response = await stream(messages2);
|
|
65
65
|
const completeMessages = [];
|
|
66
66
|
let partialMessages = /* @__PURE__ */ new Map();
|
|
67
67
|
for await (const chunk of response) {
|
|
68
68
|
if (chunk.event === "messages/partial") {
|
|
69
|
-
for (const
|
|
70
|
-
if (!
|
|
71
|
-
partialMessages.set(
|
|
69
|
+
for (const message of chunk.data) {
|
|
70
|
+
if (!message.id) throw new Error("Partial message missing id");
|
|
71
|
+
partialMessages.set(message.id, message);
|
|
72
72
|
}
|
|
73
73
|
} else if (chunk.event === "messages/complete") {
|
|
74
|
-
for (const
|
|
75
|
-
if (!
|
|
76
|
-
partialMessages.delete(
|
|
74
|
+
for (const message of chunk.data) {
|
|
75
|
+
if (!message.id) continue;
|
|
76
|
+
partialMessages.delete(message.id);
|
|
77
77
|
}
|
|
78
78
|
completeMessages.push(...chunk.data);
|
|
79
79
|
} else {
|
|
@@ -91,6 +91,20 @@ var useLangGraphMessages = ({
|
|
|
91
91
|
};
|
|
92
92
|
|
|
93
93
|
// src/useLangGraphRuntime.ts
|
|
94
|
+
var getPendingToolCalls = (messages) => {
|
|
95
|
+
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
96
|
+
for (const message of messages) {
|
|
97
|
+
if (message.type === "ai") {
|
|
98
|
+
for (const toolCall of message.tool_calls ?? []) {
|
|
99
|
+
pendingToolCalls.set(toolCall.id, toolCall);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (message.type === "tool") {
|
|
103
|
+
pendingToolCalls.delete(message.tool_call_id);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return [...pendingToolCalls.values()];
|
|
107
|
+
};
|
|
94
108
|
var useLangGraphRuntime = ({
|
|
95
109
|
threadId,
|
|
96
110
|
stream
|
|
@@ -99,10 +113,10 @@ var useLangGraphRuntime = ({
|
|
|
99
113
|
stream
|
|
100
114
|
});
|
|
101
115
|
const [isRunning, setIsRunning] = useState2(false);
|
|
102
|
-
const handleSendMessage = async (
|
|
116
|
+
const handleSendMessage = async (messages2) => {
|
|
103
117
|
try {
|
|
104
118
|
setIsRunning(true);
|
|
105
|
-
await sendMessage(
|
|
119
|
+
await sendMessage(messages2);
|
|
106
120
|
} catch (error) {
|
|
107
121
|
console.error("Error streaming messages:", error);
|
|
108
122
|
} finally {
|
|
@@ -121,24 +135,36 @@ var useLangGraphRuntime = ({
|
|
|
121
135
|
onNew: (msg) => {
|
|
122
136
|
if (msg.content.length !== 1 || msg.content[0]?.type !== "text")
|
|
123
137
|
throw new Error("Only text messages are supported");
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
138
|
+
const cancellations = getPendingToolCalls(messages).map(
|
|
139
|
+
(t) => ({
|
|
140
|
+
type: "tool",
|
|
141
|
+
name: t.name,
|
|
142
|
+
tool_call_id: t.id,
|
|
143
|
+
content: JSON.stringify({ cancelled: true })
|
|
144
|
+
})
|
|
145
|
+
);
|
|
146
|
+
return handleSendMessage([
|
|
147
|
+
...cancellations,
|
|
148
|
+
{
|
|
149
|
+
type: "human",
|
|
150
|
+
content: msg.content[0].text
|
|
151
|
+
}
|
|
152
|
+
]);
|
|
128
153
|
},
|
|
129
154
|
onAddToolResult: async ({ toolCallId, toolName, result }) => {
|
|
130
|
-
await handleSendMessage(
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
155
|
+
await handleSendMessage([
|
|
156
|
+
{
|
|
157
|
+
type: "tool",
|
|
158
|
+
name: toolName,
|
|
159
|
+
tool_call_id: toolCallId,
|
|
160
|
+
content: JSON.stringify(result)
|
|
161
|
+
}
|
|
162
|
+
]);
|
|
136
163
|
}
|
|
137
164
|
});
|
|
138
165
|
};
|
|
139
166
|
export {
|
|
140
167
|
convertLangchainMessages,
|
|
141
|
-
useLangGraphRuntime as useLangChainLangGraphRuntime,
|
|
142
168
|
useLangGraphMessages,
|
|
143
169
|
useLangGraphRuntime
|
|
144
170
|
};
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/useLangGraphRuntime.ts","../src/convertLangchainMessages.ts","../src/useLangGraphMessages.ts"],"sourcesContent":["import { useState } from \"react\";\nimport { LangChainMessage } from \"./types\";\nimport {\n useExternalMessageConverter,\n useExternalStoreRuntime,\n} from \"@assistant-ui/react\";\nimport { convertLangchainMessages } from \"./convertLangchainMessages\";\nimport { useLangGraphMessages } from \"./useLangGraphMessages\";\nimport { ExternalStoreRuntime } from \"@assistant-ui/react\";\n\nexport const useLangGraphRuntime = ({\n threadId,\n stream,\n}: {\n threadId?: string | undefined;\n stream: (
|
|
1
|
+
{"version":3,"sources":["../src/useLangGraphRuntime.ts","../src/convertLangchainMessages.ts","../src/useLangGraphMessages.ts"],"sourcesContent":["import { useState } from \"react\";\nimport { LangChainMessage, LangChainToolCall } from \"./types\";\nimport {\n useExternalMessageConverter,\n useExternalStoreRuntime,\n} from \"@assistant-ui/react\";\nimport { convertLangchainMessages } from \"./convertLangchainMessages\";\nimport { useLangGraphMessages } from \"./useLangGraphMessages\";\nimport { ExternalStoreRuntime } from \"@assistant-ui/react\";\n\nconst getPendingToolCalls = (messages: LangChainMessage[]) => {\n const pendingToolCalls = new Map<string, LangChainToolCall>();\n for (const message of messages) {\n if (message.type === \"ai\") {\n for (const toolCall of message.tool_calls ?? []) {\n pendingToolCalls.set(toolCall.id, toolCall);\n }\n }\n if (message.type === \"tool\") {\n pendingToolCalls.delete(message.tool_call_id);\n }\n }\n\n return [...pendingToolCalls.values()];\n};\n\nexport const useLangGraphRuntime = ({\n threadId,\n stream,\n}: {\n threadId?: string | undefined;\n stream: (messages: LangChainMessage[]) => Promise<\n AsyncGenerator<{\n event: string;\n data: any;\n }>\n >;\n}): ExternalStoreRuntime => {\n const { messages, sendMessage } = useLangGraphMessages({\n stream,\n });\n\n const [isRunning, setIsRunning] = useState(false);\n const handleSendMessage = async (messages: LangChainMessage[]) => {\n try {\n setIsRunning(true);\n await sendMessage(messages);\n } catch (error) {\n console.error(\"Error streaming messages:\", error);\n } finally {\n setIsRunning(false);\n }\n };\n\n const threadMessages = useExternalMessageConverter({\n callback: convertLangchainMessages,\n messages,\n isRunning,\n });\n\n return useExternalStoreRuntime({\n threadId,\n isRunning,\n messages: threadMessages,\n onNew: (msg) => {\n if (msg.content.length !== 1 || msg.content[0]?.type !== \"text\")\n throw new Error(\"Only text messages are supported\");\n\n const cancellations = getPendingToolCalls(messages).map(\n (t) =>\n ({\n type: \"tool\",\n name: t.name,\n tool_call_id: t.id,\n content: JSON.stringify({ cancelled: true }),\n }) satisfies LangChainMessage & { type: \"tool\" },\n );\n return handleSendMessage([\n ...cancellations,\n {\n type: \"human\",\n content: msg.content[0].text,\n },\n ]);\n },\n onAddToolResult: async ({ toolCallId, toolName, result }) => {\n await handleSendMessage([\n {\n type: \"tool\",\n name: toolName,\n tool_call_id: toolCallId,\n content: JSON.stringify(result),\n },\n ]);\n },\n });\n};\n","\"use client\";\n\nimport { useExternalMessageConverter } from \"@assistant-ui/react\";\nimport { LangChainMessage } from \"./types\";\nimport { ToolCallContentPart } from \"@assistant-ui/react\";\n\nexport const convertLangchainMessages: useExternalMessageConverter.Callback<\n LangChainMessage\n> = (message) => {\n switch (message.type) {\n case \"system\":\n return {\n role: \"system\",\n id: message.id,\n content: [{ type: \"text\", text: message.content }],\n };\n case \"human\":\n return {\n role: \"user\",\n id: message.id,\n content: [{ type: \"text\", text: message.content }],\n };\n case \"ai\":\n return {\n role: \"assistant\",\n id: message.id,\n content: [\n {\n type: \"text\",\n text: message.content,\n },\n ...(message.tool_calls?.map(\n (chunk): ToolCallContentPart => ({\n type: \"tool-call\",\n toolCallId: chunk.id,\n toolName: chunk.name,\n args: chunk.args,\n argsText:\n message.tool_call_chunks?.find((c) => c.id === chunk.id)\n ?.args ?? JSON.stringify(chunk.args),\n }),\n ) ?? []),\n ],\n };\n case \"tool\":\n return {\n role: \"tool\",\n toolName: message.name,\n toolCallId: message.tool_call_id,\n result: message.content,\n };\n }\n};\n","import { useState, useCallback } from \"react\";\n\nexport const useLangGraphMessages = <TMessage>({\n stream,\n}: {\n stream: (messages: TMessage[]) => Promise<\n AsyncGenerator<{\n event: string;\n data: any;\n }>\n >;\n}) => {\n const [messages, setMessages] = useState<TMessage[]>([]);\n\n const sendMessage = useCallback(\n async (messages: TMessage[]) => {\n if (messages.length > 0) {\n setMessages((currentMessages) => [...currentMessages, ...messages]);\n }\n\n const response = await stream(messages);\n\n const completeMessages: TMessage[] = [];\n let partialMessages: Map<string, TMessage> = new Map();\n for await (const chunk of response) {\n if (chunk.event === \"messages/partial\") {\n for (const message of chunk.data) {\n if (!message.id) throw new Error(\"Partial message missing id\");\n\n partialMessages.set(message.id, message);\n }\n } else if (chunk.event === \"messages/complete\") {\n for (const message of chunk.data) {\n if (!message.id) continue;\n partialMessages.delete(message.id);\n }\n\n completeMessages.push(...chunk.data);\n } else {\n continue;\n }\n\n setMessages([...completeMessages, ...partialMessages.values()]);\n }\n if (partialMessages.size > 0) {\n throw new Error(\"A partial message was not marked as complete\");\n }\n },\n [stream],\n );\n\n return { messages, sendMessage };\n};\n"],"mappings":"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","names":["useState","messages","useState","messages"]}
|