@assistant-ui/react-langchain 0.0.6 → 0.0.8

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.
@@ -1,216 +1,238 @@
1
1
  "use client";
2
+ import { convertLangChainBaseMessage, getMessageType } from "./convertMessages.js";
2
3
  import { useMemo, useRef, useState } from "react";
3
- import { useCloudThreadListAdapter, useExternalStoreRuntime, useExternalMessageConverter, useRemoteThreadListRuntime, useToolInvocations, } from "@assistant-ui/core/react";
4
+ import { useCloudThreadListAdapter, useExternalMessageConverter, useExternalStoreRuntime, useRemoteThreadListRuntime, useToolInvocations } from "@assistant-ui/core/react";
4
5
  import { useAui, useAuiState } from "@assistant-ui/store";
5
6
  import { useStream } from "@langchain/react";
6
- import { convertLangChainBaseMessage } from "./convertMessages.js";
7
+ //#region src/useStreamRuntime.ts
7
8
  const symbolLangChainRuntimeExtras = Symbol("langchain-runtime-extras");
8
9
  const asLangChainRuntimeExtras = (extras) => {
9
- if (typeof extras !== "object" ||
10
- extras == null ||
11
- !(symbolLangChainRuntimeExtras in extras))
12
- throw new Error("This method can only be called when you are using useStreamRuntime");
13
- return extras;
10
+ if (typeof extras !== "object" || extras == null || !(symbolLangChainRuntimeExtras in extras)) throw new Error("This method can only be called when you are using useStreamRuntime");
11
+ return extras;
12
+ };
13
+ const getPendingToolCalls = (messages) => {
14
+ const pending = /* @__PURE__ */ new Map();
15
+ for (const m of messages) {
16
+ const type = getMessageType(m);
17
+ if (type === "ai") for (const tc of m.tool_calls ?? []) pending.set(tc.id, tc);
18
+ else if (type === "tool" && m.tool_call_id) pending.delete(m.tool_call_id);
19
+ }
20
+ return [...pending.values()];
14
21
  };
15
22
  const getMessageContent = (msg) => {
16
- const allContent = [
17
- ...msg.content,
18
- ...(msg.attachments?.flatMap((a) => a.content) ?? []),
19
- ];
20
- const hasNonText = allContent.some((part) => part.type === "file" || part.type === "image");
21
- const hasText = allContent.some((part) => part.type === "text");
22
- if (hasNonText && !hasText) {
23
- allContent.unshift({ type: "text", text: " " });
24
- }
25
- const content = allContent.map((part) => {
26
- const type = part.type;
27
- switch (type) {
28
- case "text":
29
- return { type: "text", text: part.text };
30
- case "image":
31
- return { type: "image_url", image_url: { url: part.image } };
32
- case "file":
33
- return {
34
- type: "file",
35
- data: part.data,
36
- mime_type: part.mimeType,
37
- metadata: { filename: part.filename ?? "file" },
38
- source_type: "base64",
39
- };
40
- case "tool-call":
41
- throw new Error("Tool call appends are not supported.");
42
- default: {
43
- const _exhaustiveCheck = type;
44
- throw new Error(`Unsupported append message part type: ${_exhaustiveCheck}`);
45
- }
46
- }
47
- });
48
- if (content.length === 1 && content[0]?.type === "text") {
49
- return content[0].text ?? "";
50
- }
51
- return content;
23
+ const allContent = [...msg.content, ...msg.attachments?.flatMap((a) => a.content) ?? []];
24
+ const hasNonText = allContent.some((part) => part.type === "file" || part.type === "image");
25
+ const hasText = allContent.some((part) => part.type === "text");
26
+ if (hasNonText && !hasText) allContent.unshift({
27
+ type: "text",
28
+ text: " "
29
+ });
30
+ const content = allContent.map((part) => {
31
+ const type = part.type;
32
+ switch (type) {
33
+ case "text": return {
34
+ type: "text",
35
+ text: part.text
36
+ };
37
+ case "image": return {
38
+ type: "image_url",
39
+ image_url: { url: part.image }
40
+ };
41
+ case "file": return {
42
+ type: "file",
43
+ data: part.data,
44
+ mime_type: part.mimeType,
45
+ metadata: { filename: part.filename ?? "file" },
46
+ source_type: "base64"
47
+ };
48
+ case "tool-call": throw new Error("Tool call appends are not supported.");
49
+ default: throw new Error(`Unsupported append message part type: ${type}`);
50
+ }
51
+ });
52
+ if (content.length === 1 && content[0]?.type === "text") return content[0].text ?? "";
53
+ return content;
54
+ };
55
+ const useStreamThreadRuntime = (options) => {
56
+ const { adapters, autoCancelPendingToolCalls, unstable_allowCancellation } = options;
57
+ const messagesKey = options.messagesKey ?? "messages";
58
+ options.threadId = useAuiState((s) => s.threadListItem.externalId);
59
+ const stream = useStream(options);
60
+ const [toolStatuses, setToolStatuses] = useState({});
61
+ const hasExecutingTools = Object.values(toolStatuses).some((s) => s?.type === "executing");
62
+ const effectiveIsRunning = stream.isLoading || hasExecutingTools;
63
+ const threadMessages = useExternalMessageConverter({
64
+ callback: convertLangChainBaseMessage,
65
+ messages: stream.messages,
66
+ isRunning: effectiveIsRunning
67
+ });
68
+ const [runtimeRef] = useState(() => ({ get current() {
69
+ return runtime;
70
+ } }));
71
+ const streamRef = useRef(stream);
72
+ streamRef.current = stream;
73
+ const toolInvocations = useToolInvocations({
74
+ state: {
75
+ messages: threadMessages,
76
+ isRunning: effectiveIsRunning
77
+ },
78
+ getTools: () => runtimeRef.current.thread.getModelContext().tools,
79
+ onResult: (command) => {
80
+ if (command.type === "add-tool-result") streamRef.current.submit({ [messagesKey]: [{
81
+ type: "tool",
82
+ name: command.toolName,
83
+ tool_call_id: command.toolCallId,
84
+ content: JSON.stringify(command.result),
85
+ status: command.isError ? "error" : "success"
86
+ }] }, {});
87
+ },
88
+ setToolStatuses
89
+ });
90
+ const runtime = useExternalStoreRuntime({
91
+ isRunning: effectiveIsRunning,
92
+ messages: threadMessages,
93
+ adapters,
94
+ extras: useMemo(() => ({
95
+ [symbolLangChainRuntimeExtras]: true,
96
+ interrupt: stream.interrupt,
97
+ interrupts: stream.interrupts,
98
+ submit: stream.submit,
99
+ values: stream.values,
100
+ messagesKey
101
+ }), [
102
+ stream.interrupt,
103
+ stream.interrupts,
104
+ stream.submit,
105
+ stream.values,
106
+ messagesKey
107
+ ]),
108
+ onNew: async (msg) => {
109
+ await toolInvocations.abort();
110
+ const content = getMessageContent(msg);
111
+ const cancellations = autoCancelPendingToolCalls !== false ? getPendingToolCalls(streamRef.current.messages).map((t) => ({
112
+ type: "tool",
113
+ name: t.name,
114
+ tool_call_id: t.id,
115
+ content: JSON.stringify({ cancelled: true }),
116
+ status: "error"
117
+ })) : [];
118
+ await stream.submit({ [messagesKey]: [...cancellations, {
119
+ type: "human",
120
+ content
121
+ }] });
122
+ },
123
+ onAddToolResult: async ({ toolCallId, toolName, result, isError, artifact }) => {
124
+ await stream.submit({ [messagesKey]: [{
125
+ type: "tool",
126
+ name: toolName,
127
+ tool_call_id: toolCallId,
128
+ content: JSON.stringify(result),
129
+ ...artifact !== void 0 && { artifact },
130
+ status: isError ? "error" : "success"
131
+ }] });
132
+ },
133
+ onCancel: unstable_allowCancellation !== false ? async () => {
134
+ await stream.stop();
135
+ await toolInvocations.abort();
136
+ } : void 0
137
+ });
138
+ return runtime;
52
139
  };
53
- const useStreamThreadRuntime = ({ adapters, messagesKey = "messages", ...streamOptions }) => {
54
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
55
- const externalId = useAuiState((s) => s.threadListItem.externalId);
56
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
57
- const stream = useStream({
58
- ...streamOptions,
59
- threadId: externalId,
60
- });
61
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
62
- const [toolStatuses, setToolStatuses] = useState({});
63
- const hasExecutingTools = Object.values(toolStatuses).some((s) => s?.type === "executing");
64
- const effectiveIsRunning = stream.isLoading || hasExecutingTools;
65
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
66
- const threadMessages = useExternalMessageConverter({
67
- callback: convertLangChainBaseMessage,
68
- messages: stream.messages,
69
- isRunning: effectiveIsRunning,
70
- });
71
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
72
- const [runtimeRef] = useState(() => ({
73
- get current() {
74
- return runtime;
75
- },
76
- }));
77
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
78
- const streamRef = useRef(stream);
79
- streamRef.current = stream;
80
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
81
- const toolInvocations = useToolInvocations({
82
- state: {
83
- messages: threadMessages,
84
- isRunning: effectiveIsRunning,
85
- },
86
- getTools: () => runtimeRef.current.thread.getModelContext().tools,
87
- onResult: (command) => {
88
- if (command.type === "add-tool-result") {
89
- void streamRef.current.submit({
90
- [messagesKey]: [
91
- {
92
- type: "tool",
93
- name: command.toolName,
94
- tool_call_id: command.toolCallId,
95
- content: JSON.stringify(command.result),
96
- status: command.isError ? "error" : "success",
97
- },
98
- ],
99
- }, {});
100
- }
101
- },
102
- setToolStatuses,
103
- });
104
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
105
- const extras = useMemo(() => ({
106
- [symbolLangChainRuntimeExtras]: true,
107
- interrupt: stream.interrupt,
108
- interrupts: stream.interrupts,
109
- submit: stream.submit,
110
- values: stream.values,
111
- }), [stream.interrupt, stream.interrupts, stream.submit, stream.values]);
112
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
113
- const runtime = useExternalStoreRuntime({
114
- isRunning: effectiveIsRunning,
115
- messages: threadMessages,
116
- adapters,
117
- extras,
118
- onNew: async (msg) => {
119
- await toolInvocations.abort();
120
- const content = getMessageContent(msg);
121
- await stream.submit({
122
- [messagesKey]: [{ type: "human", content }],
123
- });
124
- },
125
- onAddToolResult: async ({ toolCallId, toolName, result, isError, artifact, }) => {
126
- await stream.submit({
127
- [messagesKey]: [
128
- {
129
- type: "tool",
130
- name: toolName,
131
- tool_call_id: toolCallId,
132
- content: JSON.stringify(result),
133
- ...(artifact !== undefined && { artifact }),
134
- status: isError ? "error" : "success",
135
- },
136
- ],
137
- });
138
- },
139
- onCancel: async () => {
140
- await stream.stop();
141
- await toolInvocations.abort();
142
- },
143
- });
144
- return runtime;
140
+ /**
141
+ * Creates an assistant-ui runtime backed by LangChain's `useStream` hook.
142
+ * Accepts the same options as `useStream` from `@langchain/react`, plus
143
+ * `cloud` and `adapters`.
144
+ *
145
+ * @example
146
+ * ```tsx
147
+ * import { useStreamRuntime } from "@assistant-ui/react-langchain";
148
+ * import { AssistantRuntimeProvider, Thread } from "@assistant-ui/react";
149
+ *
150
+ * function App() {
151
+ * const runtime = useStreamRuntime({
152
+ * assistantId: "agent",
153
+ * apiUrl: "http://localhost:2024",
154
+ * });
155
+ *
156
+ * return (
157
+ * <AssistantRuntimeProvider runtime={runtime}>
158
+ * <Thread />
159
+ * </AssistantRuntimeProvider>
160
+ * );
161
+ * }
162
+ * ```
163
+ */
164
+ const useStreamRuntime = (rawOptions) => {
165
+ const { cloud, unstable_threadListAdapter, create, delete: deleteFn, ...options } = rawOptions;
166
+ const optionsRef = useRef(options);
167
+ optionsRef.current = options;
168
+ const cloudAdapter = useCloudThreadListAdapter({
169
+ cloud,
170
+ create,
171
+ delete: deleteFn
172
+ });
173
+ return useRemoteThreadListRuntime({
174
+ runtimeHook: function RuntimeHook() {
175
+ return useStreamThreadRuntime(optionsRef.current);
176
+ },
177
+ adapter: unstable_threadListAdapter ?? cloudAdapter,
178
+ allowNesting: true
179
+ });
180
+ };
181
+ /**
182
+ * Read the current LangGraph interrupt state from the runtime extras.
183
+ */
184
+ const useLangChainInterruptState = () => {
185
+ return useAuiState((s) => {
186
+ const extras = s.thread.extras;
187
+ if (!extras) return void 0;
188
+ return asLangChainRuntimeExtras(extras).interrupt;
189
+ });
145
190
  };
146
191
  /**
147
- * Creates an assistant-ui runtime backed by LangChain's `useStream` hook.
148
- * Accepts the same options as `useStream` from `@langchain/react`, plus
149
- * `cloud` and `adapters`.
150
- *
151
- * @example
152
- * ```tsx
153
- * import { useStreamRuntime } from "@assistant-ui/react-langchain";
154
- * import { AssistantRuntimeProvider, Thread } from "@assistant-ui/react";
155
- *
156
- * function App() {
157
- * const runtime = useStreamRuntime({
158
- * assistantId: "agent",
159
- * apiUrl: "http://localhost:2024",
160
- * });
161
- *
162
- * return (
163
- * <AssistantRuntimeProvider runtime={runtime}>
164
- * <Thread />
165
- * </AssistantRuntimeProvider>
166
- * );
167
- * }
168
- * ```
169
- */
170
- export const useStreamRuntime = ({ cloud, ...options }) => {
171
- const optionsRef = useRef(options);
172
- optionsRef.current = options;
173
- const cloudAdapter = useCloudThreadListAdapter({ cloud });
174
- return useRemoteThreadListRuntime({
175
- runtimeHook: function RuntimeHook() {
176
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
177
- return useStreamThreadRuntime(optionsRef.current);
178
- },
179
- adapter: cloudAdapter,
180
- allowNesting: true,
181
- });
192
+ * Returns a function to submit raw state updates to the LangGraph agent,
193
+ * bypassing the normal message flow. Useful for sending interrupt resume
194
+ * commands.
195
+ */
196
+ const useLangChainSubmit = () => {
197
+ const aui = useAui();
198
+ return (values, options) => {
199
+ const extras = aui.thread().getState().extras;
200
+ const { submit } = asLangChainRuntimeExtras(extras);
201
+ return submit(values, options);
202
+ };
182
203
  };
183
204
  /**
184
- * Read the current LangGraph interrupt state from the runtime extras.
185
- */
186
- export const useLangChainInterruptState = () => {
187
- return useAuiState((s) => {
188
- const extras = s.thread.extras;
189
- if (!extras)
190
- return undefined;
191
- return asLangChainRuntimeExtras(extras).interrupt;
192
- });
205
+ * Submit a list of LangChain-shaped messages on the current thread.
206
+ * Parity helper for migrating from `useLangGraphSend`. Routes to
207
+ * `useStream().submit({ [messagesKey]: messages }, options)`.
208
+ */
209
+ const useLangChainSend = () => {
210
+ const aui = useAui();
211
+ return (messages, options) => {
212
+ const { submit, messagesKey } = asLangChainRuntimeExtras(aui.thread().getState().extras);
213
+ return submit({ [messagesKey]: messages }, options);
214
+ };
193
215
  };
194
216
  /**
195
- * Returns a function to submit raw state updates to the LangGraph agent,
196
- * bypassing the normal message flow. Useful for sending interrupt resume
197
- * commands.
198
- */
199
- export const useLangChainSubmit = () => {
200
- const aui = useAui();
201
- return (values, options) => {
202
- const extras = aui.thread().getState().extras;
203
- const { submit } = asLangChainRuntimeExtras(extras);
204
- return submit(values, options);
205
- };
217
+ * Submit a `useStream` command (e.g. interrupt resume). Parity helper
218
+ * for migrating from `useLangGraphSendCommand`. Note that v1's command
219
+ * shape (`{ resume?, goto?, update? }`) differs from the legacy
220
+ * `{ resume: string }` form — to carry a payload, use the input or
221
+ * `stream.respond` instead.
222
+ */
223
+ const useLangChainSendCommand = () => {
224
+ const submit = useLangChainSubmit();
225
+ return (command) => submit(null, { command });
206
226
  };
207
- export function useLangChainState(key, defaultValue) {
208
- return useAuiState((s) => {
209
- const extras = s.thread.extras;
210
- if (!extras)
211
- return defaultValue;
212
- const value = asLangChainRuntimeExtras(extras).values[key];
213
- return value !== undefined ? value : defaultValue;
214
- });
227
+ function useLangChainState(key, defaultValue) {
228
+ return useAuiState((s) => {
229
+ const extras = s.thread.extras;
230
+ if (!extras) return defaultValue;
231
+ const value = asLangChainRuntimeExtras(extras).values[key];
232
+ return value !== void 0 ? value : defaultValue;
233
+ });
215
234
  }
235
+ //#endregion
236
+ export { useLangChainInterruptState, useLangChainSend, useLangChainSendCommand, useLangChainState, useLangChainSubmit, useStreamRuntime };
237
+
216
238
  //# sourceMappingURL=useStreamRuntime.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useStreamRuntime.js","sourceRoot":"","sources":["../src/useStreamRuntime.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useStreamRuntime.js","names":["_exhaustiveCheck"],"sources":["../src/useStreamRuntime.ts"],"sourcesContent":["\"use client\";\n\nimport { useMemo, useRef, useState } from \"react\";\nimport type {\n AppendMessage,\n AttachmentAdapter,\n FeedbackAdapter,\n RemoteThreadListAdapter,\n SpeechSynthesisAdapter,\n} from \"@assistant-ui/core\";\nimport {\n useCloudThreadListAdapter,\n useExternalStoreRuntime,\n useExternalMessageConverter,\n useRemoteThreadListRuntime,\n useToolInvocations,\n type ToolExecutionStatus,\n} from \"@assistant-ui/core/react\";\nimport { useAui, useAuiState } from \"@assistant-ui/store\";\nimport type { AssistantCloud } from \"assistant-cloud\";\nimport { useStream, type UseStreamOptions } from \"@langchain/react\";\nimport type { LangChainBaseMessage, LangChainToolCall } from \"./types\";\nimport { convertLangChainBaseMessage, getMessageType } from \"./convertMessages\";\n\nconst symbolLangChainRuntimeExtras = Symbol(\"langchain-runtime-extras\");\n\ntype LangChainRuntimeExtras = {\n [symbolLangChainRuntimeExtras]: true;\n interrupt: { value?: unknown } | undefined;\n interrupts: readonly { value?: unknown }[];\n submit: (\n values: Record<string, unknown> | null | undefined,\n options?: Record<string, unknown>,\n ) => Promise<void>;\n values: Record<string, unknown>;\n messagesKey: string;\n};\n\nconst asLangChainRuntimeExtras = (extras: unknown): LangChainRuntimeExtras => {\n if (\n typeof extras !== \"object\" ||\n extras == null ||\n !(symbolLangChainRuntimeExtras in extras)\n )\n throw new Error(\n \"This method can only be called when you are using useStreamRuntime\",\n );\n return extras as LangChainRuntimeExtras;\n};\n\ntype LangChainRuntimeExtraOptions = {\n cloud?: AssistantCloud | undefined;\n adapters?:\n | {\n attachments?: AttachmentAdapter | undefined;\n speech?: SpeechSynthesisAdapter | undefined;\n feedback?: FeedbackAdapter | undefined;\n }\n | undefined;\n /**\n * When the user sends a new message while previous tool calls are\n * still pending, automatically submit `tool` messages that cancel\n * them so the agent's tool-call accounting stays consistent.\n * Defaults to `true`.\n */\n autoCancelPendingToolCalls?: boolean | undefined;\n /**\n * Routes the Cancel button's click to `useStream().stop()`. On by\n * default. Pass `false` to disable the Cancel button.\n */\n unstable_allowCancellation?: boolean | undefined;\n /**\n * Custom `RemoteThreadListAdapter`. When provided, replaces the\n * cloud-backed thread list adapter.\n */\n unstable_threadListAdapter?: RemoteThreadListAdapter | undefined;\n /** Custom thread-creation hook, forwarded to the cloud adapter. */\n create?: (() => Promise<{ externalId: string | undefined }>) | undefined;\n /** Custom thread-deletion hook, forwarded to the cloud adapter. */\n delete?: ((threadId: string) => Promise<void>) | undefined;\n};\n\nconst getPendingToolCalls = (\n messages: readonly LangChainBaseMessage[],\n): LangChainToolCall[] => {\n const pending = new Map<string, LangChainToolCall>();\n for (const m of messages) {\n const type = getMessageType(m);\n if (type === \"ai\") {\n for (const tc of m.tool_calls ?? []) pending.set(tc.id, tc);\n } else if (type === \"tool\" && m.tool_call_id) {\n pending.delete(m.tool_call_id);\n }\n }\n return [...pending.values()];\n};\n\n// Distribute the intersection through the union arms of `UseStreamOptions`\n// (`AgentServerOptions | CustomAdapterOptions`). Writing `UseStreamOptions & X`\n// directly collapses arm tracking, so `Omit<…, \"cloud\">` and the like would\n// produce a flattened structural type that no longer matches either arm.\nexport type UseStreamRuntimeOptions = UseStreamOptions extends infer O\n ? O extends UseStreamOptions\n ? O & LangChainRuntimeExtraOptions\n : never\n : never;\n\nconst getMessageContent = (msg: AppendMessage) => {\n const allContent = [\n ...msg.content,\n ...(msg.attachments?.flatMap((a) => a.content) ?? []),\n ];\n\n const hasNonText = allContent.some(\n (part) => part.type === \"file\" || part.type === \"image\",\n );\n const hasText = allContent.some((part) => part.type === \"text\");\n if (hasNonText && !hasText) {\n allContent.unshift({ type: \"text\", text: \" \" });\n }\n\n const content = allContent.map((part) => {\n const type = part.type;\n switch (type) {\n case \"text\":\n return { type: \"text\" as const, text: part.text };\n case \"image\":\n return { type: \"image_url\" as const, image_url: { url: part.image } };\n case \"file\":\n return {\n type: \"file\" as const,\n data: part.data,\n mime_type: part.mimeType,\n metadata: { filename: part.filename ?? \"file\" },\n source_type: \"base64\" as const,\n };\n case \"tool-call\":\n throw new Error(\"Tool call appends are not supported.\");\n default: {\n const _exhaustiveCheck:\n | \"reasoning\"\n | \"source\"\n | \"audio\"\n | \"data\"\n | \"generative-ui\" = type;\n throw new Error(\n `Unsupported append message part type: ${_exhaustiveCheck}`,\n );\n }\n }\n });\n\n if (content.length === 1 && content[0]?.type === \"text\") {\n return content[0].text ?? \"\";\n }\n return content;\n};\n\ntype DistributiveOmit<T, K extends keyof any> = T extends unknown\n ? Omit<T, K>\n : never;\n\nconst useStreamThreadRuntime = (\n options: DistributiveOmit<\n UseStreamRuntimeOptions,\n \"cloud\" | \"unstable_threadListAdapter\" | \"create\" | \"delete\"\n >,\n) => {\n const { adapters, autoCancelPendingToolCalls, unstable_allowCancellation } =\n options;\n const messagesKey = options.messagesKey ?? \"messages\";\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const externalId = useAuiState((s) => s.threadListItem.externalId) as\n | string\n | null;\n // Mutate in place rather than `{ ...options, threadId }`: spreading\n // `UseStreamOptions` (a discriminated union on `transport`) into an object\n // literal merges both arms' transport types, breaking arm assignment.\n options.threadId = externalId;\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const stream = useStream(options);\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const [toolStatuses, setToolStatuses] = useState<\n Record<string, ToolExecutionStatus>\n >({});\n const hasExecutingTools = Object.values(toolStatuses).some(\n (s) => s?.type === \"executing\",\n );\n const effectiveIsRunning = stream.isLoading || hasExecutingTools;\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const threadMessages = useExternalMessageConverter({\n callback: convertLangChainBaseMessage,\n messages: stream.messages as LangChainBaseMessage[],\n isRunning: effectiveIsRunning,\n });\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const [runtimeRef] = useState(() => ({\n get current() {\n return runtime;\n },\n }));\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const streamRef = useRef(stream);\n streamRef.current = stream;\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const toolInvocations = useToolInvocations({\n state: {\n messages: threadMessages,\n isRunning: effectiveIsRunning,\n },\n getTools: () => runtimeRef.current.thread.getModelContext().tools,\n onResult: (command) => {\n if (command.type === \"add-tool-result\") {\n void streamRef.current.submit(\n {\n [messagesKey]: [\n {\n type: \"tool\",\n name: command.toolName,\n tool_call_id: command.toolCallId,\n content: JSON.stringify(command.result),\n status: command.isError ? \"error\" : \"success\",\n },\n ],\n },\n {},\n );\n }\n },\n setToolStatuses,\n });\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const extras = useMemo(\n (): LangChainRuntimeExtras => ({\n [symbolLangChainRuntimeExtras]: true,\n interrupt: stream.interrupt,\n interrupts: stream.interrupts,\n submit: stream.submit,\n values: stream.values,\n messagesKey,\n }),\n [\n stream.interrupt,\n stream.interrupts,\n stream.submit,\n stream.values,\n messagesKey,\n ],\n );\n\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n const runtime = useExternalStoreRuntime({\n isRunning: effectiveIsRunning,\n messages: threadMessages,\n adapters,\n extras,\n onNew: async (msg) => {\n await toolInvocations.abort();\n const content = getMessageContent(msg);\n const cancellations =\n autoCancelPendingToolCalls !== false\n ? getPendingToolCalls(\n streamRef.current.messages as readonly LangChainBaseMessage[],\n ).map((t) => ({\n type: \"tool\" as const,\n name: t.name,\n tool_call_id: t.id,\n content: JSON.stringify({ cancelled: true }),\n status: \"error\" as const,\n }))\n : [];\n await stream.submit({\n [messagesKey]: [...cancellations, { type: \"human\", content }],\n });\n },\n onAddToolResult: async ({\n toolCallId,\n toolName,\n result,\n isError,\n artifact,\n }) => {\n await stream.submit({\n [messagesKey]: [\n {\n type: \"tool\",\n name: toolName,\n tool_call_id: toolCallId,\n content: JSON.stringify(result),\n ...(artifact !== undefined && { artifact }),\n status: isError ? \"error\" : \"success\",\n },\n ],\n });\n },\n onCancel:\n unstable_allowCancellation !== false\n ? async () => {\n await stream.stop();\n await toolInvocations.abort();\n }\n : undefined,\n });\n\n return runtime;\n};\n\n/**\n * Creates an assistant-ui runtime backed by LangChain's `useStream` hook.\n * Accepts the same options as `useStream` from `@langchain/react`, plus\n * `cloud` and `adapters`.\n *\n * @example\n * ```tsx\n * import { useStreamRuntime } from \"@assistant-ui/react-langchain\";\n * import { AssistantRuntimeProvider, Thread } from \"@assistant-ui/react\";\n *\n * function App() {\n * const runtime = useStreamRuntime({\n * assistantId: \"agent\",\n * apiUrl: \"http://localhost:2024\",\n * });\n *\n * return (\n * <AssistantRuntimeProvider runtime={runtime}>\n * <Thread />\n * </AssistantRuntimeProvider>\n * );\n * }\n * ```\n */\nexport const useStreamRuntime = (rawOptions: UseStreamRuntimeOptions) => {\n const {\n cloud,\n unstable_threadListAdapter,\n create,\n delete: deleteFn,\n ...options\n } = rawOptions;\n\n const optionsRef = useRef(options);\n optionsRef.current = options;\n\n const cloudAdapter = useCloudThreadListAdapter({\n cloud,\n create,\n delete: deleteFn,\n });\n const adapter = unstable_threadListAdapter ?? cloudAdapter;\n\n return useRemoteThreadListRuntime({\n runtimeHook: function RuntimeHook() {\n // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage\n return useStreamThreadRuntime(optionsRef.current);\n },\n adapter,\n allowNesting: true,\n });\n};\n\n/**\n * Read the current LangGraph interrupt state from the runtime extras.\n */\nexport const useLangChainInterruptState = () => {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return undefined;\n return asLangChainRuntimeExtras(extras).interrupt;\n });\n};\n\n/**\n * Returns a function to submit raw state updates to the LangGraph agent,\n * bypassing the normal message flow. Useful for sending interrupt resume\n * commands.\n */\nexport const useLangChainSubmit = () => {\n const aui = useAui();\n return (\n values: Record<string, unknown> | null | undefined,\n options?: Record<string, unknown>,\n ) => {\n const extras = aui.thread().getState().extras;\n const { submit } = asLangChainRuntimeExtras(extras);\n return submit(values, options);\n };\n};\n\n/**\n * Submit a list of LangChain-shaped messages on the current thread.\n * Parity helper for migrating from `useLangGraphSend`. Routes to\n * `useStream().submit({ [messagesKey]: messages }, options)`.\n */\nexport const useLangChainSend = () => {\n const aui = useAui();\n return (\n messages: readonly LangChainBaseMessage[],\n options?: Record<string, unknown>,\n ) => {\n const { submit, messagesKey } = asLangChainRuntimeExtras(\n aui.thread().getState().extras,\n );\n return submit({ [messagesKey]: messages }, options);\n };\n};\n\n/**\n * Submit a `useStream` command (e.g. interrupt resume). Parity helper\n * for migrating from `useLangGraphSendCommand`. Note that v1's command\n * shape (`{ resume?, goto?, update? }`) differs from the legacy\n * `{ resume: string }` form — to carry a payload, use the input or\n * `stream.respond` instead.\n */\nexport const useLangChainSendCommand = () => {\n const submit = useLangChainSubmit();\n return (command: Record<string, unknown>) => submit(null, { command });\n};\n\n/**\n * Read a custom LangGraph state key from the current thread. Mirrors\n * `useStream().values[key]` from `@langchain/react` and updates when the\n * stream emits new state.\n *\n * @example\n * ```tsx\n * const todos = useLangChainState<Todo[]>(\"todos\");\n * const files = useLangChainState<Record<string, string>>(\"files\", {});\n * ```\n */\nexport function useLangChainState<T>(key: string): T | undefined;\nexport function useLangChainState<T>(key: string, defaultValue: T): T;\nexport function useLangChainState<T>(\n key: string,\n defaultValue?: T,\n): T | undefined {\n return useAuiState((s) => {\n const extras = s.thread.extras;\n if (!extras) return defaultValue;\n const value = asLangChainRuntimeExtras(extras).values[key] as T | undefined;\n return value !== undefined ? value : defaultValue;\n });\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/react-langchain",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "description": "LangChain useStream adapter for assistant-ui",
5
5
  "keywords": [
6
6
  "langchain",
@@ -29,13 +29,13 @@
29
29
  ],
30
30
  "sideEffects": false,
31
31
  "dependencies": {
32
- "@assistant-ui/core": "^0.2.0",
33
- "@assistant-ui/store": "^0.2.10",
32
+ "@assistant-ui/core": "^0.2.5",
33
+ "@assistant-ui/store": "^0.2.12",
34
34
  "assistant-cloud": "*",
35
- "assistant-stream": "^0.3.13"
35
+ "assistant-stream": "^0.3.16"
36
36
  },
37
37
  "peerDependencies": {
38
- "@langchain/react": "^0.3.3",
38
+ "@langchain/react": "^1.0.2",
39
39
  "@types/react": "*",
40
40
  "react": "^18 || ^19"
41
41
  },
@@ -45,15 +45,15 @@
45
45
  }
46
46
  },
47
47
  "devDependencies": {
48
- "@langchain/core": "^1.1.44",
49
- "@langchain/langgraph-sdk": "^1.9.1",
50
- "@langchain/react": "^0.3.3",
48
+ "@langchain/core": "^1.1.47",
49
+ "@langchain/langgraph-sdk": "^1.9.4",
50
+ "@langchain/react": "^1.0.4",
51
51
  "@testing-library/react": "^16.3.2",
52
- "@types/react": "^19.2.14",
52
+ "@types/react": "^19.2.15",
53
53
  "jsdom": "^29.1.1",
54
- "react": "^19.2.5",
55
- "vitest": "^4.1.5",
56
- "@assistant-ui/x-buildutils": "0.0.7"
54
+ "react": "^19.2.6",
55
+ "vitest": "^4.1.7",
56
+ "@assistant-ui/x-buildutils": "0.0.9"
57
57
  },
58
58
  "publishConfig": {
59
59
  "access": "public",
@@ -4,7 +4,7 @@ import type { useExternalMessageConverter } from "@assistant-ui/core/react";
4
4
  import type { ReadonlyJSONObject } from "assistant-stream/utils";
5
5
  import type { LangChainBaseMessage, LangChainContentBlock } from "./types";
6
6
 
7
- const getMessageType = (message: LangChainBaseMessage): string => {
7
+ export const getMessageType = (message: LangChainBaseMessage): string => {
8
8
  if (typeof message._getType === "function") return message._getType();
9
9
  if ("type" in message)
10
10
  return (message as Record<string, unknown>).type as string;
package/src/index.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export {
2
2
  useStreamRuntime,
3
3
  useLangChainInterruptState,
4
+ useLangChainSend,
5
+ useLangChainSendCommand,
4
6
  useLangChainState,
5
7
  useLangChainSubmit,
6
8
  } from "./useStreamRuntime";