@assistant-ui/react-langchain 0.0.7 → 0.0.10

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,5 +1,9 @@
1
- import type { useExternalMessageConverter } from "@assistant-ui/core/react";
2
- import type { LangChainBaseMessage } from "./types.js";
3
- export declare const getMessageType: (message: LangChainBaseMessage) => string;
4
- export declare const convertLangChainBaseMessage: useExternalMessageConverter.Callback<LangChainBaseMessage>;
1
+ import { LangChainBaseMessage } from "./types.js";
2
+ import { useExternalMessageConverter } from "@assistant-ui/core/react";
3
+
4
+ //#region src/convertMessages.d.ts
5
+ declare const getMessageType: (message: LangChainBaseMessage) => string;
6
+ declare const convertLangChainBaseMessage: useExternalMessageConverter.Callback<LangChainBaseMessage>;
7
+ //#endregion
8
+ export { convertLangChainBaseMessage, getMessageType };
5
9
  //# sourceMappingURL=convertMessages.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"convertMessages.d.ts","sourceRoot":"","sources":["../src/convertMessages.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAE5E,OAAO,KAAK,EAAE,oBAAoB,EAAyB,mBAAgB;AAE3E,eAAO,MAAM,cAAc,GAAI,SAAS,oBAAoB,KAAG,MAK9D,CAAC;AAkDF,eAAO,MAAM,2BAA2B,EAAE,2BAA2B,CAAC,QAAQ,CAC5E,oBAAoB,CA0ErB,CAAC"}
1
+ {"version":3,"file":"convertMessages.d.ts","names":[],"sources":["../src/convertMessages.ts"],"mappings":";;;;cAMa,cAAA,GAAkB,OAA6B,EAApB,oBAAoB;AAAA,cAuD/C,2BAAA,EAA6B,2BAAA,CAA4B,QAAQ,CAC5E,oBAAA"}
@@ -1,115 +1,103 @@
1
1
  "use client";
2
- export const getMessageType = (message) => {
3
- if (typeof message._getType === "function")
4
- return message._getType();
5
- if ("type" in message)
6
- return message.type;
7
- throw new Error("Cannot determine message type");
2
+ //#region src/convertMessages.ts
3
+ const getMessageType = (message) => {
4
+ if (typeof message._getType === "function") return message._getType();
5
+ if ("type" in message) return message.type;
6
+ throw new Error("Cannot determine message type");
8
7
  };
9
8
  const contentToParts = (content) => {
10
- if (typeof content === "string")
11
- return [{ type: "text", text: content }];
12
- const parts = content;
13
- return parts
14
- .map((part) => {
15
- const type = part.type;
16
- switch (type) {
17
- case "text":
18
- case "text_delta":
19
- return { type: "text", text: part.text };
20
- case "image_url":
21
- if (typeof part.image_url === "string") {
22
- return { type: "image", image: part.image_url };
23
- }
24
- return { type: "image", image: part.image_url.url };
25
- case "thinking":
26
- return { type: "reasoning", text: part.thinking };
27
- case "reasoning":
28
- return {
29
- type: "reasoning",
30
- text: part.summary.map((s) => s.text).join("\n\n\n"),
31
- };
32
- case "tool_use":
33
- case "input_json_delta":
34
- return null;
35
- default:
36
- return null;
37
- }
38
- })
39
- .filter((p) => p !== null);
9
+ if (typeof content === "string") return [{
10
+ type: "text",
11
+ text: content
12
+ }];
13
+ return content.map((part) => {
14
+ switch (part.type) {
15
+ case "text":
16
+ case "text_delta": return {
17
+ type: "text",
18
+ text: part.text
19
+ };
20
+ case "image_url":
21
+ if (typeof part.image_url === "string") return {
22
+ type: "image",
23
+ image: part.image_url
24
+ };
25
+ return {
26
+ type: "image",
27
+ image: part.image_url.url
28
+ };
29
+ case "thinking": return {
30
+ type: "reasoning",
31
+ text: part.thinking
32
+ };
33
+ case "reasoning": return {
34
+ type: "reasoning",
35
+ text: part.summary.map((s) => s.text).join("\n\n\n")
36
+ };
37
+ case "tool_use":
38
+ case "input_json_delta": return null;
39
+ default: return null;
40
+ }
41
+ }).filter((p) => p !== null);
40
42
  };
41
43
  const getCustomMetadata = (additionalKwargs) => additionalKwargs?.metadata ?? {};
42
44
  const getStringContent = (content) => {
43
- if (typeof content === "string")
44
- return content;
45
- const parts = content;
46
- return parts
47
- .filter((c) => c.type === "text")
48
- .map((c) => c.text)
49
- .join("");
45
+ if (typeof content === "string") return content;
46
+ return content.filter((c) => c.type === "text").map((c) => c.text).join("");
50
47
  };
51
- export const convertLangChainBaseMessage = (message) => {
52
- const type = getMessageType(message);
53
- switch (type) {
54
- case "system":
55
- return {
56
- role: "system",
57
- id: message.id,
58
- content: [{ type: "text", text: getStringContent(message.content) }],
59
- metadata: {
60
- custom: getCustomMetadata(message.additional_kwargs),
61
- },
62
- };
63
- case "human":
64
- return {
65
- role: "user",
66
- id: message.id,
67
- content: contentToParts(message.content),
68
- metadata: {
69
- custom: getCustomMetadata(message.additional_kwargs),
70
- },
71
- };
72
- case "ai": {
73
- const toolCallParts = message.tool_calls?.map((tc) => ({
74
- type: "tool-call",
75
- toolCallId: tc.id,
76
- toolName: tc.name,
77
- args: tc.args,
78
- argsText: JSON.stringify(tc.args),
79
- })) ?? [];
80
- const assistantStatus = typeof message.status === "object" ? message.status : undefined;
81
- return {
82
- role: "assistant",
83
- id: message.id,
84
- content: [...contentToParts(message.content), ...toolCallParts],
85
- metadata: {
86
- custom: getCustomMetadata(message.additional_kwargs),
87
- },
88
- ...(assistantStatus && { status: assistantStatus }),
89
- };
90
- }
91
- case "tool":
92
- return {
93
- role: "tool",
94
- toolName: message.name ?? "",
95
- toolCallId: message.tool_call_id ?? "",
96
- result: message.content,
97
- artifact: message.artifact,
98
- isError: message.status === "error",
99
- };
100
- default:
101
- return {
102
- role: "system",
103
- id: message.id,
104
- content: [
105
- {
106
- type: "text",
107
- text: typeof message.content === "string"
108
- ? message.content
109
- : JSON.stringify(message.content),
110
- },
111
- ],
112
- };
113
- }
48
+ const convertLangChainBaseMessage = (message) => {
49
+ switch (getMessageType(message)) {
50
+ case "system": return {
51
+ role: "system",
52
+ id: message.id,
53
+ content: [{
54
+ type: "text",
55
+ text: getStringContent(message.content)
56
+ }],
57
+ metadata: { custom: getCustomMetadata(message.additional_kwargs) }
58
+ };
59
+ case "human": return {
60
+ role: "user",
61
+ id: message.id,
62
+ content: contentToParts(message.content),
63
+ metadata: { custom: getCustomMetadata(message.additional_kwargs) }
64
+ };
65
+ case "ai": {
66
+ const toolCallParts = message.tool_calls?.map((tc) => ({
67
+ type: "tool-call",
68
+ toolCallId: tc.id,
69
+ toolName: tc.name,
70
+ args: tc.args,
71
+ argsText: JSON.stringify(tc.args)
72
+ })) ?? [];
73
+ const assistantStatus = typeof message.status === "object" ? message.status : void 0;
74
+ return {
75
+ role: "assistant",
76
+ id: message.id,
77
+ content: [...contentToParts(message.content), ...toolCallParts],
78
+ metadata: { custom: getCustomMetadata(message.additional_kwargs) },
79
+ ...assistantStatus && { status: assistantStatus }
80
+ };
81
+ }
82
+ case "tool": return {
83
+ role: "tool",
84
+ toolName: message.name ?? "",
85
+ toolCallId: message.tool_call_id ?? "",
86
+ result: message.content,
87
+ artifact: message.artifact,
88
+ isError: message.status === "error"
89
+ };
90
+ default: return {
91
+ role: "system",
92
+ id: message.id,
93
+ content: [{
94
+ type: "text",
95
+ text: typeof message.content === "string" ? message.content : JSON.stringify(message.content)
96
+ }]
97
+ };
98
+ }
114
99
  };
100
+ //#endregion
101
+ export { convertLangChainBaseMessage, getMessageType };
102
+
115
103
  //# sourceMappingURL=convertMessages.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"convertMessages.js","sourceRoot":"","sources":["../src/convertMessages.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"convertMessages.js","names":["parts"],"sources":["../src/convertMessages.ts"],"sourcesContent":["\"use client\";\n\nimport type { useExternalMessageConverter } from \"@assistant-ui/core/react\";\nimport type { ReadonlyJSONObject } from \"assistant-stream/utils\";\nimport type { LangChainBaseMessage, LangChainContentBlock } from \"./types\";\n\nexport const getMessageType = (message: LangChainBaseMessage): string => {\n if (typeof message._getType === \"function\") return message._getType();\n if (\"type\" in message)\n return (message as Record<string, unknown>).type as string;\n throw new Error(\"Cannot determine message type\");\n};\n\nconst contentToParts = (content: unknown) => {\n if (typeof content === \"string\")\n return [{ type: \"text\" as const, text: content }];\n\n const parts = content as readonly LangChainContentBlock[];\n return parts\n .map((part) => {\n const type = part.type;\n switch (type) {\n case \"text\":\n case \"text_delta\":\n return { type: \"text\" as const, text: part.text };\n case \"image_url\":\n if (typeof part.image_url === \"string\") {\n return { type: \"image\" as const, image: part.image_url };\n }\n return { type: \"image\" as const, image: part.image_url.url };\n case \"thinking\":\n return { type: \"reasoning\" as const, text: part.thinking };\n case \"reasoning\":\n return {\n type: \"reasoning\" as const,\n text: part.summary.map((s) => s.text).join(\"\\n\\n\\n\"),\n };\n case \"tool_use\":\n case \"input_json_delta\":\n return null;\n default:\n return null;\n }\n })\n .filter((p) => p !== null);\n};\n\nconst getCustomMetadata = (\n additionalKwargs: Record<string, unknown> | undefined,\n): Record<string, unknown> =>\n (additionalKwargs?.metadata as Record<string, unknown>) ?? {};\n\nconst getStringContent = (content: unknown): string => {\n if (typeof content === \"string\") return content;\n const parts = content as readonly LangChainContentBlock[];\n return parts\n .filter((c): c is { type: \"text\"; text: string } => c.type === \"text\")\n .map((c) => c.text)\n .join(\"\");\n};\n\nexport const convertLangChainBaseMessage: useExternalMessageConverter.Callback<\n LangChainBaseMessage\n> = (message) => {\n const type = getMessageType(message);\n\n switch (type) {\n case \"system\":\n return {\n role: \"system\",\n id: message.id,\n content: [{ type: \"text\", text: getStringContent(message.content) }],\n metadata: {\n custom: getCustomMetadata(message.additional_kwargs),\n },\n };\n\n case \"human\":\n return {\n role: \"user\",\n id: message.id,\n content: contentToParts(message.content),\n metadata: {\n custom: getCustomMetadata(message.additional_kwargs),\n },\n };\n\n case \"ai\": {\n const toolCallParts =\n message.tool_calls?.map((tc) => ({\n type: \"tool-call\" as const,\n toolCallId: tc.id,\n toolName: tc.name,\n args: tc.args as ReadonlyJSONObject,\n argsText: JSON.stringify(tc.args),\n })) ?? [];\n\n const assistantStatus =\n typeof message.status === \"object\" ? message.status : undefined;\n\n return {\n role: \"assistant\",\n id: message.id,\n content: [...contentToParts(message.content), ...toolCallParts],\n metadata: {\n custom: getCustomMetadata(message.additional_kwargs),\n },\n ...(assistantStatus && { status: assistantStatus }),\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 artifact: message.artifact,\n isError: message.status === \"error\",\n };\n\n default:\n return {\n role: \"system\",\n id: message.id,\n content: [\n {\n type: \"text\",\n text:\n typeof message.content === \"string\"\n ? message.content\n : JSON.stringify(message.content),\n },\n ],\n };\n }\n};\n"],"mappings":";;AAMA,MAAa,kBAAkB,YAA0C;CACvE,IAAI,OAAO,QAAQ,aAAa,YAAY,OAAO,QAAQ,SAAS;CACpE,IAAI,UAAU,SACZ,OAAQ,QAAoC;CAC9C,MAAM,IAAI,MAAM,+BAA+B;AACjD;AAEA,MAAM,kBAAkB,YAAqB;CAC3C,IAAI,OAAO,YAAY,UACrB,OAAO,CAAC;EAAE,MAAM;EAAiB,MAAM;CAAQ,CAAC;CAGlD,OAAOA,QACJ,KAAK,SAAS;EAEb,QADa,KAAK,MAClB;GACE,KAAK;GACL,KAAK,cACH,OAAO;IAAE,MAAM;IAAiB,MAAM,KAAK;GAAK;GAClD,KAAK;IACH,IAAI,OAAO,KAAK,cAAc,UAC5B,OAAO;KAAE,MAAM;KAAkB,OAAO,KAAK;IAAU;IAEzD,OAAO;KAAE,MAAM;KAAkB,OAAO,KAAK,UAAU;IAAI;GAC7D,KAAK,YACH,OAAO;IAAE,MAAM;IAAsB,MAAM,KAAK;GAAS;GAC3D,KAAK,aACH,OAAO;IACL,MAAM;IACN,MAAM,KAAK,QAAQ,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,QAAQ;GACrD;GACF,KAAK;GACL,KAAK,oBACH,OAAO;GACT,SACE,OAAO;EACX;CACF,CAAC,EACA,QAAQ,MAAM,MAAM,IAAI;AAC7B;AAEA,MAAM,qBACJ,qBAEC,kBAAkB,YAAwC,CAAC;AAE9D,MAAM,oBAAoB,YAA6B;CACrD,IAAI,OAAO,YAAY,UAAU,OAAO;CAExC,OAAOA,QACJ,QAAQ,MAA2C,EAAE,SAAS,MAAM,EACpE,KAAK,MAAM,EAAE,IAAI,EACjB,KAAK,EAAE;AACZ;AAEA,MAAa,+BAER,YAAY;CAGf,QAFa,eAAe,OAEjB,GAAX;EACE,KAAK,UACH,OAAO;GACL,MAAM;GACN,IAAI,QAAQ;GACZ,SAAS,CAAC;IAAE,MAAM;IAAQ,MAAM,iBAAiB,QAAQ,OAAO;GAAE,CAAC;GACnE,UAAU,EACR,QAAQ,kBAAkB,QAAQ,iBAAiB,EACrD;EACF;EAEF,KAAK,SACH,OAAO;GACL,MAAM;GACN,IAAI,QAAQ;GACZ,SAAS,eAAe,QAAQ,OAAO;GACvC,UAAU,EACR,QAAQ,kBAAkB,QAAQ,iBAAiB,EACrD;EACF;EAEF,KAAK,MAAM;GACT,MAAM,gBACJ,QAAQ,YAAY,KAAK,QAAQ;IAC/B,MAAM;IACN,YAAY,GAAG;IACf,UAAU,GAAG;IACb,MAAM,GAAG;IACT,UAAU,KAAK,UAAU,GAAG,IAAI;GAClC,EAAE,KAAK,CAAC;GAEV,MAAM,kBACJ,OAAO,QAAQ,WAAW,WAAW,QAAQ,SAAS,KAAA;GAExD,OAAO;IACL,MAAM;IACN,IAAI,QAAQ;IACZ,SAAS,CAAC,GAAG,eAAe,QAAQ,OAAO,GAAG,GAAG,aAAa;IAC9D,UAAU,EACR,QAAQ,kBAAkB,QAAQ,iBAAiB,EACrD;IACA,GAAI,mBAAmB,EAAE,QAAQ,gBAAgB;GACnD;EACF;EAEA,KAAK,QACH,OAAO;GACL,MAAM;GACN,UAAU,QAAQ,QAAQ;GAC1B,YAAY,QAAQ,gBAAgB;GACpC,QAAQ,QAAQ;GAChB,UAAU,QAAQ;GAClB,SAAS,QAAQ,WAAW;EAC9B;EAEF,SACE,OAAO;GACL,MAAM;GACN,IAAI,QAAQ;GACZ,SAAS,CACP;IACE,MAAM;IACN,MACE,OAAO,QAAQ,YAAY,WACvB,QAAQ,UACR,KAAK,UAAU,QAAQ,OAAO;GACtC,CACF;EACF;CACJ;AACF"}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,4 @@
1
- export { useStreamRuntime, useLangChainInterruptState, useLangChainSend, useLangChainSendCommand, useLangChainState, useLangChainSubmit, } from "./useStreamRuntime.js";
2
- export type { UseStreamRuntimeOptions } from "./useStreamRuntime.js";
3
- export { convertLangChainBaseMessage } from "./convertMessages.js";
4
- export type { LangChainBaseMessage, LangChainContentBlock, LangChainToolCall, } from "./types.js";
5
- //# sourceMappingURL=index.d.ts.map
1
+ import { LangChainBaseMessage, LangChainContentBlock, LangChainToolCall } from "./types.js";
2
+ import { convertLangChainBaseMessage } from "./convertMessages.js";
3
+ import { UseStreamRuntimeOptions, useLangChainInterruptState, useLangChainSend, useLangChainSendCommand, useLangChainState, useLangChainSubmit, useStreamRuntime } from "./useStreamRuntime.js";
4
+ export { type LangChainBaseMessage, type LangChainContentBlock, type LangChainToolCall, type UseStreamRuntimeOptions, convertLangChainBaseMessage, useLangChainInterruptState, useLangChainSend, useLangChainSendCommand, useLangChainState, useLangChainSubmit, useStreamRuntime };
package/dist/index.js CHANGED
@@ -1,3 +1,3 @@
1
- export { useStreamRuntime, useLangChainInterruptState, useLangChainSend, useLangChainSendCommand, useLangChainState, useLangChainSubmit, } from "./useStreamRuntime.js";
2
- export { convertLangChainBaseMessage } from "./convertMessages.js";
3
- //# sourceMappingURL=index.js.map
1
+ import { convertLangChainBaseMessage } from "./convertMessages.js";
2
+ import { useLangChainInterruptState, useLangChainSend, useLangChainSendCommand, useLangChainState, useLangChainSubmit, useStreamRuntime } from "./useStreamRuntime.js";
3
+ export { convertLangChainBaseMessage, useLangChainInterruptState, useLangChainSend, useLangChainSendCommand, useLangChainState, useLangChainSubmit, useStreamRuntime };
package/dist/types.d.ts CHANGED
@@ -1,32 +1,34 @@
1
- import type { MessageStatus } from "@assistant-ui/core";
1
+ import { MessageStatus } from "@assistant-ui/core";
2
+
3
+ //#region src/types.d.ts
2
4
  /** Known content block types from @langchain/core messages. */
3
- export type LangChainContentBlock = {
4
- type: "text";
5
- text: string;
5
+ type LangChainContentBlock = {
6
+ type: "text";
7
+ text: string;
6
8
  } | {
7
- type: "text_delta";
8
- text: string;
9
+ type: "text_delta";
10
+ text: string;
9
11
  } | {
10
- type: "image_url";
11
- image_url: string | {
12
- url: string;
13
- };
12
+ type: "image_url";
13
+ image_url: string | {
14
+ url: string;
15
+ };
14
16
  } | {
15
- type: "thinking";
16
- thinking: string;
17
+ type: "thinking";
18
+ thinking: string;
17
19
  } | {
18
- type: "reasoning";
19
- summary: Array<{
20
- type: "summary_text";
21
- text: string;
22
- }>;
20
+ type: "reasoning";
21
+ summary: Array<{
22
+ type: "summary_text";
23
+ text: string;
24
+ }>;
23
25
  } | {
24
- type: "tool_use" | "input_json_delta";
26
+ type: "tool_use" | "input_json_delta";
25
27
  };
26
- export type LangChainToolCall = {
27
- id: string;
28
- name: string;
29
- args: Record<string, unknown>;
28
+ type LangChainToolCall = {
29
+ id: string;
30
+ name: string;
31
+ args: Record<string, unknown>;
30
32
  };
31
33
  /**
32
34
  * Minimal duck-typed interface for BaseMessage class instances returned by
@@ -35,19 +37,17 @@ export type LangChainToolCall = {
35
37
  * Uses `unknown` for `content` to remain compatible with
36
38
  * `@langchain/core`'s `MessageContent` union.
37
39
  */
38
- export type LangChainBaseMessage = {
39
- _getType: () => string;
40
- content: unknown;
41
- id?: string | undefined;
42
- name?: string | undefined;
43
- additional_kwargs?: Record<string, unknown> | undefined;
44
- /** Present on AIMessage */
45
- tool_calls?: readonly LangChainToolCall[] | undefined;
46
- /** Present on ToolMessage */
47
- tool_call_id?: string | undefined;
48
- /** Completion status (AIMessage) or outcome status (ToolMessage) */
49
- status?: MessageStatus | "success" | "error" | undefined;
50
- /** Present on ToolMessage */
51
- artifact?: unknown;
40
+ type LangChainBaseMessage = {
41
+ _getType: () => string;
42
+ content: unknown;
43
+ id?: string | undefined;
44
+ name?: string | undefined;
45
+ additional_kwargs?: Record<string, unknown> | undefined; /** Present on AIMessage */
46
+ tool_calls?: readonly LangChainToolCall[] | undefined; /** Present on ToolMessage */
47
+ tool_call_id?: string | undefined; /** Completion status (AIMessage) or outcome status (ToolMessage) */
48
+ status?: MessageStatus | "success" | "error" | undefined; /** Present on ToolMessage */
49
+ artifact?: unknown;
52
50
  };
51
+ //#endregion
52
+ export { LangChainBaseMessage, LangChainContentBlock, LangChainToolCall };
53
53
  //# sourceMappingURL=types.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAExD,+DAA+D;AAC/D,MAAM,MAAM,qBAAqB,GAC7B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACpC;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACtC;IACE,IAAI,EAAE,WAAW,CAAC;IAClB,OAAO,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,cAAc,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;CACxD,GACD;IAAE,IAAI,EAAE,UAAU,GAAG,kBAAkB,CAAA;CAAE,CAAC;AAE9C,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC/B,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,MAAM,MAAM,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACxB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACxD,2BAA2B;IAC3B,UAAU,CAAC,EAAE,SAAS,iBAAiB,EAAE,GAAG,SAAS,CAAC;IACtD,6BAA6B;IAC7B,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,oEAAoE;IACpE,MAAM,CAAC,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACzD,6BAA6B;IAC7B,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../src/types.ts"],"mappings":";;;;KAGY,qBAAA;EACN,IAAA;EAAc,IAAA;AAAA;EACd,IAAA;EAAoB,IAAA;AAAA;EACpB,IAAA;EAAmB,SAAA;IAAsB,GAAA;EAAA;AAAA;EACzC,IAAA;EAAkB,QAAA;AAAA;EAElB,IAAA;EACA,OAAA,EAAS,KAAK;IAAG,IAAA;IAAsB,IAAA;EAAA;AAAA;EAEvC,IAAA;AAAA;AAAA,KAEM,iBAAA;EACV,EAAA;EACA,IAAA;EACA,IAAA,EAAM,MAAM;AAAA;;;;AAAA;AAUd;;;KAAY,oBAAA;EACV,QAAA;EACA,OAAA;EACA,EAAA;EACA,IAAA;EACA,iBAAA,GAAoB,MAAA,+BAHpB;EAKA,UAAA,YAAsB,iBAAA,gBAHtB;EAKA,YAAA,uBAJoB;EAMpB,MAAA,GAAS,aAAA,oCAJa;EAMtB,QAAA;AAAA"}
package/dist/types.js CHANGED
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=types.js.map
@@ -1,39 +1,40 @@
1
- import type { AttachmentAdapter, FeedbackAdapter, RemoteThreadListAdapter, SpeechSynthesisAdapter } from "@assistant-ui/core";
2
- import type { AssistantCloud } from "assistant-cloud";
3
- import { type UseStreamOptions } from "@langchain/react";
4
- import type { LangChainBaseMessage } from "./types.js";
1
+ /// <reference types="@assistant-ui/core/store" />
2
+ import { LangChainBaseMessage } from "./types.js";
3
+ import { UseStreamOptions } from "@langchain/react";
4
+ import { AttachmentAdapter, FeedbackAdapter, RemoteThreadListAdapter, SpeechSynthesisAdapter } from "@assistant-ui/core";
5
+ import { AssistantCloud } from "assistant-cloud";
6
+
7
+ //#region src/useStreamRuntime.d.ts
5
8
  type LangChainRuntimeExtraOptions = {
6
- cloud?: AssistantCloud | undefined;
7
- adapters?: {
8
- attachments?: AttachmentAdapter | undefined;
9
- speech?: SpeechSynthesisAdapter | undefined;
10
- feedback?: FeedbackAdapter | undefined;
11
- } | undefined;
12
- /**
13
- * When the user sends a new message while previous tool calls are
14
- * still pending, automatically submit `tool` messages that cancel
15
- * them so the agent's tool-call accounting stays consistent.
16
- * Defaults to `true`.
17
- */
18
- autoCancelPendingToolCalls?: boolean | undefined;
19
- /**
20
- * Routes the Cancel button's click to `useStream().stop()`. On by
21
- * default. Pass `false` to disable the Cancel button.
22
- */
23
- unstable_allowCancellation?: boolean | undefined;
24
- /**
25
- * Custom `RemoteThreadListAdapter`. When provided, replaces the
26
- * cloud-backed thread list adapter.
27
- */
28
- unstable_threadListAdapter?: RemoteThreadListAdapter | undefined;
29
- /** Custom thread-creation hook, forwarded to the cloud adapter. */
30
- create?: (() => Promise<{
31
- externalId: string | undefined;
32
- }>) | undefined;
33
- /** Custom thread-deletion hook, forwarded to the cloud adapter. */
34
- delete?: ((threadId: string) => Promise<void>) | undefined;
9
+ cloud?: AssistantCloud | undefined;
10
+ adapters?: {
11
+ attachments?: AttachmentAdapter | undefined;
12
+ speech?: SpeechSynthesisAdapter | undefined;
13
+ feedback?: FeedbackAdapter | undefined;
14
+ } | undefined;
15
+ /**
16
+ * When the user sends a new message while previous tool calls are
17
+ * still pending, automatically submit `tool` messages that cancel
18
+ * them so the agent's tool-call accounting stays consistent.
19
+ * Defaults to `true`.
20
+ */
21
+ autoCancelPendingToolCalls?: boolean | undefined;
22
+ /**
23
+ * Routes the Cancel button's click to `useStream().stop()`. On by
24
+ * default. Pass `false` to disable the Cancel button.
25
+ */
26
+ unstable_allowCancellation?: boolean | undefined;
27
+ /**
28
+ * Custom `RemoteThreadListAdapter`. When provided, replaces the
29
+ * cloud-backed thread list adapter.
30
+ */
31
+ unstable_threadListAdapter?: RemoteThreadListAdapter | undefined; /** Custom thread-creation hook, forwarded to the cloud adapter. */
32
+ create?: (() => Promise<{
33
+ externalId: string | undefined;
34
+ }>) | undefined; /** Custom thread-deletion hook, forwarded to the cloud adapter. */
35
+ delete?: ((threadId: string) => Promise<void>) | undefined;
35
36
  };
36
- export type UseStreamRuntimeOptions = UseStreamOptions extends infer O ? O extends UseStreamOptions ? O & LangChainRuntimeExtraOptions : never : never;
37
+ type UseStreamRuntimeOptions = UseStreamOptions extends infer O ? O extends UseStreamOptions ? O & LangChainRuntimeExtraOptions : never : never;
37
38
  /**
38
39
  * Creates an assistant-ui runtime backed by LangChain's `useStream` hook.
39
40
  * Accepts the same options as `useStream` from `@langchain/react`, plus
@@ -58,25 +59,25 @@ export type UseStreamRuntimeOptions = UseStreamOptions extends infer O ? O exten
58
59
  * }
59
60
  * ```
60
61
  */
61
- export declare const useStreamRuntime: (rawOptions: UseStreamRuntimeOptions) => import("@assistant-ui/core").AssistantRuntime;
62
+ declare const useStreamRuntime: (rawOptions: UseStreamRuntimeOptions) => import("@assistant-ui/core").AssistantRuntime;
62
63
  /**
63
64
  * Read the current LangGraph interrupt state from the runtime extras.
64
65
  */
65
- export declare const useLangChainInterruptState: () => {
66
- value?: unknown;
66
+ declare const useLangChainInterruptState: () => {
67
+ value?: unknown;
67
68
  } | undefined;
68
69
  /**
69
70
  * Returns a function to submit raw state updates to the LangGraph agent,
70
71
  * bypassing the normal message flow. Useful for sending interrupt resume
71
72
  * commands.
72
73
  */
73
- export declare const useLangChainSubmit: () => (values: Record<string, unknown> | null | undefined, options?: Record<string, unknown>) => Promise<void>;
74
+ declare const useLangChainSubmit: () => (values: Record<string, unknown> | null | undefined, options?: Record<string, unknown>) => Promise<void>;
74
75
  /**
75
76
  * Submit a list of LangChain-shaped messages on the current thread.
76
77
  * Parity helper for migrating from `useLangGraphSend`. Routes to
77
78
  * `useStream().submit({ [messagesKey]: messages }, options)`.
78
79
  */
79
- export declare const useLangChainSend: () => (messages: readonly LangChainBaseMessage[], options?: Record<string, unknown>) => Promise<void>;
80
+ declare const useLangChainSend: () => (messages: readonly LangChainBaseMessage[], options?: Record<string, unknown>) => Promise<void>;
80
81
  /**
81
82
  * Submit a `useStream` command (e.g. interrupt resume). Parity helper
82
83
  * for migrating from `useLangGraphSendCommand`. Note that v1's command
@@ -84,7 +85,7 @@ export declare const useLangChainSend: () => (messages: readonly LangChainBaseMe
84
85
  * `{ resume: string }` form — to carry a payload, use the input or
85
86
  * `stream.respond` instead.
86
87
  */
87
- export declare const useLangChainSendCommand: () => (command: Record<string, unknown>) => Promise<void>;
88
+ declare const useLangChainSendCommand: () => (command: Record<string, unknown>) => Promise<void>;
88
89
  /**
89
90
  * Read a custom LangGraph state key from the current thread. Mirrors
90
91
  * `useStream().values[key]` from `@langchain/react` and updates when the
@@ -96,7 +97,8 @@ export declare const useLangChainSendCommand: () => (command: Record<string, unk
96
97
  * const files = useLangChainState<Record<string, string>>("files", {});
97
98
  * ```
98
99
  */
99
- export declare function useLangChainState<T>(key: string): T | undefined;
100
- export declare function useLangChainState<T>(key: string, defaultValue: T): T;
101
- export {};
100
+ declare function useLangChainState<T>(key: string): T | undefined;
101
+ declare function useLangChainState<T>(key: string, defaultValue: T): T;
102
+ //#endregion
103
+ export { UseStreamRuntimeOptions, useLangChainInterruptState, useLangChainSend, useLangChainSendCommand, useLangChainState, useLangChainSubmit, useStreamRuntime };
102
104
  //# sourceMappingURL=useStreamRuntime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useStreamRuntime.d.ts","sourceRoot":"","sources":["../src/useStreamRuntime.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,iBAAiB,EACjB,eAAe,EACf,uBAAuB,EACvB,sBAAsB,EACvB,MAAM,oBAAoB,CAAC;AAU5B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACtD,OAAO,EAAa,KAAK,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,KAAK,EAAE,oBAAoB,EAAqB,mBAAgB;AA6BvE,KAAK,4BAA4B,GAAG;IAClC,KAAK,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC;IACnC,QAAQ,CAAC,EACL;QACE,WAAW,CAAC,EAAE,iBAAiB,GAAG,SAAS,CAAC;QAC5C,MAAM,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC;QAC5C,QAAQ,CAAC,EAAE,eAAe,GAAG,SAAS,CAAC;KACxC,GACD,SAAS,CAAC;IACd;;;;;OAKG;IACH,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjD;;;OAGG;IACH,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjD;;;OAGG;IACH,0BAA0B,CAAC,EAAE,uBAAuB,GAAG,SAAS,CAAC;IACjE,mEAAmE;IACnE,MAAM,CAAC,EAAE,CAAC,MAAM,OAAO,CAAC;QAAE,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC,CAAC,GAAG,SAAS,CAAC;IACzE,mEAAmE;IACnE,MAAM,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAC;CAC5D,CAAC;AAqBF,MAAM,MAAM,uBAAuB,GAAG,gBAAgB,SAAS,MAAM,CAAC,GAClE,CAAC,SAAS,gBAAgB,GACxB,CAAC,GAAG,4BAA4B,GAChC,KAAK,GACP,KAAK,CAAC;AA8MV;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,gBAAgB,GAAI,YAAY,uBAAuB,kDA2BnE,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,0BAA0B;YAnVhB,OAAO;aAyV7B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,SAG3B,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GAAG,SAAS,EAClD,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,kBAMpC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,SAGzB,UAAU,SAAS,oBAAoB,EAAE,EACzC,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,kBAOpC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,SAE1B,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,kBACzC,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC;AACjE,wBAAgB,iBAAiB,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC,GAAG,CAAC,CAAC"}
1
+ {"version":3,"file":"useStreamRuntime.d.ts","names":[],"sources":["../src/useStreamRuntime.ts"],"mappings":";;;;;;KAkDK,4BAAA;EACH,KAAA,GAAQ,cAAA;EACR,QAAA;IAEM,WAAA,GAAc,iBAAA;IACd,MAAA,GAAS,sBAAA;IACT,QAAA,GAAW,eAAA;EAAA;EADF;;;;;;EAUf,0BAAA;EAdA;;;;EAmBA,0BAAA;EAfM;;;;EAoBN,0BAAA,GAA6B,uBAAA,cAL7B;EAOA,MAAA,UAAgB,OAAA;IAAU,UAAA;EAAA,iBAAV;EAEhB,MAAA,KAAW,QAAA,aAAqB,OAAA;AAAA;AAAA,KAsBtB,uBAAA,GAA0B,gBAAA,mBAClC,CAAA,SAAU,gBAAA,GACR,CAAA,GAAI,4BAAA;;;AAxB+B;AAsBzC;;;;;;;;;;;;;;;;AAEsC;AAyMtC;;;;cAAa,gBAAA,GAAoB,UAAA,EAAY,uBAAuB,kCAAA,gBAAA;;;;cAgCvD,0BAAA;EAMZ,KAAA;AAAA;;;;AAOD;;cAAa,kBAAA,SAGT,MAAA,EAAQ,MAAA,sCACR,OAAA,GAAU,MAAA,sBAAuB,OAAA;;;;;;cAaxB,gBAAA,SAGT,QAAA,WAAmB,oBAAA,IACnB,OAAA,GAAU,MAAA,sBAAuB,OAAA;;;;;;AAjBA;AAarC;cAoBa,uBAAA,SAEH,OAAA,EAAS,MAAA,sBAAuB,OAAA;;;;;;;;;;;;iBAc1B,iBAAA,GAAA,CAAqB,GAAA,WAAc,CAAC;AAAA,iBACpC,iBAAA,GAAA,CAAqB,GAAA,UAAa,YAAA,EAAc,CAAA,GAAI,CAAC"}
@@ -1,280 +1,217 @@
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 } from "@assistant-ui/core/react";
4
5
  import { useAui, useAuiState } from "@assistant-ui/store";
5
6
  import { useStream } from "@langchain/react";
6
- import { convertLangChainBaseMessage, getMessageType } 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;
14
12
  };
15
13
  const getPendingToolCalls = (messages) => {
16
- const pending = new Map();
17
- for (const m of messages) {
18
- const type = getMessageType(m);
19
- if (type === "ai") {
20
- for (const tc of m.tool_calls ?? [])
21
- pending.set(tc.id, tc);
22
- }
23
- else if (type === "tool" && m.tool_call_id) {
24
- pending.delete(m.tool_call_id);
25
- }
26
- }
27
- return [...pending.values()];
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()];
28
21
  };
29
22
  const getMessageContent = (msg) => {
30
- const allContent = [
31
- ...msg.content,
32
- ...(msg.attachments?.flatMap((a) => a.content) ?? []),
33
- ];
34
- const hasNonText = allContent.some((part) => part.type === "file" || part.type === "image");
35
- const hasText = allContent.some((part) => part.type === "text");
36
- if (hasNonText && !hasText) {
37
- allContent.unshift({ type: "text", text: " " });
38
- }
39
- const content = allContent.map((part) => {
40
- const type = part.type;
41
- switch (type) {
42
- case "text":
43
- return { type: "text", text: part.text };
44
- case "image":
45
- return { type: "image_url", image_url: { url: part.image } };
46
- case "file":
47
- return {
48
- type: "file",
49
- data: part.data,
50
- mime_type: part.mimeType,
51
- metadata: { filename: part.filename ?? "file" },
52
- source_type: "base64",
53
- };
54
- case "tool-call":
55
- throw new Error("Tool call appends are not supported.");
56
- default: {
57
- const _exhaustiveCheck = type;
58
- throw new Error(`Unsupported append message part type: ${_exhaustiveCheck}`);
59
- }
60
- }
61
- });
62
- if (content.length === 1 && content[0]?.type === "text") {
63
- return content[0].text ?? "";
64
- }
65
- 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;
66
54
  };
67
55
  const useStreamThreadRuntime = (options) => {
68
- const { adapters, autoCancelPendingToolCalls, unstable_allowCancellation } = options;
69
- const messagesKey = options.messagesKey ?? "messages";
70
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
71
- const externalId = useAuiState((s) => s.threadListItem.externalId);
72
- // Mutate in place rather than `{ ...options, threadId }`: spreading
73
- // `UseStreamOptions` (a discriminated union on `transport`) into an object
74
- // literal merges both arms' transport types, breaking arm assignment.
75
- options.threadId = externalId;
76
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
77
- const stream = useStream(options);
78
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
79
- const [toolStatuses, setToolStatuses] = useState({});
80
- const hasExecutingTools = Object.values(toolStatuses).some((s) => s?.type === "executing");
81
- const effectiveIsRunning = stream.isLoading || hasExecutingTools;
82
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
83
- const threadMessages = useExternalMessageConverter({
84
- callback: convertLangChainBaseMessage,
85
- messages: stream.messages,
86
- isRunning: effectiveIsRunning,
87
- });
88
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
89
- const [runtimeRef] = useState(() => ({
90
- get current() {
91
- return runtime;
92
- },
93
- }));
94
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
95
- const streamRef = useRef(stream);
96
- streamRef.current = stream;
97
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
98
- const toolInvocations = useToolInvocations({
99
- state: {
100
- messages: threadMessages,
101
- isRunning: effectiveIsRunning,
102
- },
103
- getTools: () => runtimeRef.current.thread.getModelContext().tools,
104
- onResult: (command) => {
105
- if (command.type === "add-tool-result") {
106
- void streamRef.current.submit({
107
- [messagesKey]: [
108
- {
109
- type: "tool",
110
- name: command.toolName,
111
- tool_call_id: command.toolCallId,
112
- content: JSON.stringify(command.result),
113
- status: command.isError ? "error" : "success",
114
- },
115
- ],
116
- }, {});
117
- }
118
- },
119
- setToolStatuses,
120
- });
121
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
122
- const extras = useMemo(() => ({
123
- [symbolLangChainRuntimeExtras]: true,
124
- interrupt: stream.interrupt,
125
- interrupts: stream.interrupts,
126
- submit: stream.submit,
127
- values: stream.values,
128
- messagesKey,
129
- }), [
130
- stream.interrupt,
131
- stream.interrupts,
132
- stream.submit,
133
- stream.values,
134
- messagesKey,
135
- ]);
136
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
137
- const runtime = useExternalStoreRuntime({
138
- isRunning: effectiveIsRunning,
139
- messages: threadMessages,
140
- adapters,
141
- extras,
142
- onNew: async (msg) => {
143
- await toolInvocations.abort();
144
- const content = getMessageContent(msg);
145
- const cancellations = autoCancelPendingToolCalls !== false
146
- ? getPendingToolCalls(streamRef.current.messages).map((t) => ({
147
- type: "tool",
148
- name: t.name,
149
- tool_call_id: t.id,
150
- content: JSON.stringify({ cancelled: true }),
151
- status: "error",
152
- }))
153
- : [];
154
- await stream.submit({
155
- [messagesKey]: [...cancellations, { type: "human", content }],
156
- });
157
- },
158
- onAddToolResult: async ({ toolCallId, toolName, result, isError, artifact, }) => {
159
- await stream.submit({
160
- [messagesKey]: [
161
- {
162
- type: "tool",
163
- name: toolName,
164
- tool_call_id: toolCallId,
165
- content: JSON.stringify(result),
166
- ...(artifact !== undefined && { artifact }),
167
- status: isError ? "error" : "success",
168
- },
169
- ],
170
- });
171
- },
172
- onCancel: unstable_allowCancellation !== false
173
- ? async () => {
174
- await stream.stop();
175
- await toolInvocations.abort();
176
- }
177
- : undefined,
178
- });
179
- return runtime;
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 streamRef = useRef(stream);
69
+ streamRef.current = stream;
70
+ return useExternalStoreRuntime({
71
+ isRunning: effectiveIsRunning,
72
+ messages: threadMessages,
73
+ adapters,
74
+ extras: useMemo(() => ({
75
+ [symbolLangChainRuntimeExtras]: true,
76
+ interrupt: stream.interrupt,
77
+ interrupts: stream.interrupts,
78
+ submit: stream.submit,
79
+ values: stream.values,
80
+ messagesKey
81
+ }), [
82
+ stream.interrupt,
83
+ stream.interrupts,
84
+ stream.submit,
85
+ stream.values,
86
+ messagesKey
87
+ ]),
88
+ unstable_enableToolInvocations: true,
89
+ setToolStatuses,
90
+ onNew: async (msg) => {
91
+ const content = getMessageContent(msg);
92
+ const cancellations = autoCancelPendingToolCalls !== false ? getPendingToolCalls(streamRef.current.messages).map((t) => ({
93
+ type: "tool",
94
+ name: t.name,
95
+ tool_call_id: t.id,
96
+ content: JSON.stringify({ cancelled: true }),
97
+ status: "error"
98
+ })) : [];
99
+ await stream.submit({ [messagesKey]: [...cancellations, {
100
+ type: "human",
101
+ content
102
+ }] });
103
+ },
104
+ onAddToolResult: async ({ toolCallId, toolName, result, isError, artifact }) => {
105
+ await stream.submit({ [messagesKey]: [{
106
+ type: "tool",
107
+ name: toolName,
108
+ tool_call_id: toolCallId,
109
+ content: JSON.stringify(result),
110
+ ...artifact !== void 0 && { artifact },
111
+ status: isError ? "error" : "success"
112
+ }] });
113
+ },
114
+ onCancel: unstable_allowCancellation !== false ? async () => {
115
+ await stream.stop();
116
+ } : void 0
117
+ });
180
118
  };
181
119
  /**
182
- * Creates an assistant-ui runtime backed by LangChain's `useStream` hook.
183
- * Accepts the same options as `useStream` from `@langchain/react`, plus
184
- * `cloud` and `adapters`.
185
- *
186
- * @example
187
- * ```tsx
188
- * import { useStreamRuntime } from "@assistant-ui/react-langchain";
189
- * import { AssistantRuntimeProvider, Thread } from "@assistant-ui/react";
190
- *
191
- * function App() {
192
- * const runtime = useStreamRuntime({
193
- * assistantId: "agent",
194
- * apiUrl: "http://localhost:2024",
195
- * });
196
- *
197
- * return (
198
- * <AssistantRuntimeProvider runtime={runtime}>
199
- * <Thread />
200
- * </AssistantRuntimeProvider>
201
- * );
202
- * }
203
- * ```
204
- */
205
- export const useStreamRuntime = (rawOptions) => {
206
- const { cloud, unstable_threadListAdapter, create, delete: deleteFn, ...options } = rawOptions;
207
- const optionsRef = useRef(options);
208
- optionsRef.current = options;
209
- const cloudAdapter = useCloudThreadListAdapter({
210
- cloud,
211
- create,
212
- delete: deleteFn,
213
- });
214
- const adapter = unstable_threadListAdapter ?? cloudAdapter;
215
- return useRemoteThreadListRuntime({
216
- runtimeHook: function RuntimeHook() {
217
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
218
- return useStreamThreadRuntime(optionsRef.current);
219
- },
220
- adapter,
221
- allowNesting: true,
222
- });
120
+ * Creates an assistant-ui runtime backed by LangChain's `useStream` hook.
121
+ * Accepts the same options as `useStream` from `@langchain/react`, plus
122
+ * `cloud` and `adapters`.
123
+ *
124
+ * @example
125
+ * ```tsx
126
+ * import { useStreamRuntime } from "@assistant-ui/react-langchain";
127
+ * import { AssistantRuntimeProvider, Thread } from "@assistant-ui/react";
128
+ *
129
+ * function App() {
130
+ * const runtime = useStreamRuntime({
131
+ * assistantId: "agent",
132
+ * apiUrl: "http://localhost:2024",
133
+ * });
134
+ *
135
+ * return (
136
+ * <AssistantRuntimeProvider runtime={runtime}>
137
+ * <Thread />
138
+ * </AssistantRuntimeProvider>
139
+ * );
140
+ * }
141
+ * ```
142
+ */
143
+ const useStreamRuntime = (rawOptions) => {
144
+ const { cloud, unstable_threadListAdapter, create, delete: deleteFn, ...options } = rawOptions;
145
+ const optionsRef = useRef(options);
146
+ optionsRef.current = options;
147
+ const cloudAdapter = useCloudThreadListAdapter({
148
+ cloud,
149
+ create,
150
+ delete: deleteFn
151
+ });
152
+ return useRemoteThreadListRuntime({
153
+ runtimeHook: function RuntimeHook() {
154
+ return useStreamThreadRuntime(optionsRef.current);
155
+ },
156
+ adapter: unstable_threadListAdapter ?? cloudAdapter,
157
+ allowNesting: true
158
+ });
223
159
  };
224
160
  /**
225
- * Read the current LangGraph interrupt state from the runtime extras.
226
- */
227
- export const useLangChainInterruptState = () => {
228
- return useAuiState((s) => {
229
- const extras = s.thread.extras;
230
- if (!extras)
231
- return undefined;
232
- return asLangChainRuntimeExtras(extras).interrupt;
233
- });
161
+ * Read the current LangGraph interrupt state from the runtime extras.
162
+ */
163
+ const useLangChainInterruptState = () => {
164
+ return useAuiState((s) => {
165
+ const extras = s.thread.extras;
166
+ if (!extras) return void 0;
167
+ return asLangChainRuntimeExtras(extras).interrupt;
168
+ });
234
169
  };
235
170
  /**
236
- * Returns a function to submit raw state updates to the LangGraph agent,
237
- * bypassing the normal message flow. Useful for sending interrupt resume
238
- * commands.
239
- */
240
- export const useLangChainSubmit = () => {
241
- const aui = useAui();
242
- return (values, options) => {
243
- const extras = aui.thread().getState().extras;
244
- const { submit } = asLangChainRuntimeExtras(extras);
245
- return submit(values, options);
246
- };
171
+ * Returns a function to submit raw state updates to the LangGraph agent,
172
+ * bypassing the normal message flow. Useful for sending interrupt resume
173
+ * commands.
174
+ */
175
+ const useLangChainSubmit = () => {
176
+ const aui = useAui();
177
+ return (values, options) => {
178
+ const extras = aui.thread().getState().extras;
179
+ const { submit } = asLangChainRuntimeExtras(extras);
180
+ return submit(values, options);
181
+ };
247
182
  };
248
183
  /**
249
- * Submit a list of LangChain-shaped messages on the current thread.
250
- * Parity helper for migrating from `useLangGraphSend`. Routes to
251
- * `useStream().submit({ [messagesKey]: messages }, options)`.
252
- */
253
- export const useLangChainSend = () => {
254
- const aui = useAui();
255
- return (messages, options) => {
256
- const { submit, messagesKey } = asLangChainRuntimeExtras(aui.thread().getState().extras);
257
- return submit({ [messagesKey]: messages }, options);
258
- };
184
+ * Submit a list of LangChain-shaped messages on the current thread.
185
+ * Parity helper for migrating from `useLangGraphSend`. Routes to
186
+ * `useStream().submit({ [messagesKey]: messages }, options)`.
187
+ */
188
+ const useLangChainSend = () => {
189
+ const aui = useAui();
190
+ return (messages, options) => {
191
+ const { submit, messagesKey } = asLangChainRuntimeExtras(aui.thread().getState().extras);
192
+ return submit({ [messagesKey]: messages }, options);
193
+ };
259
194
  };
260
195
  /**
261
- * Submit a `useStream` command (e.g. interrupt resume). Parity helper
262
- * for migrating from `useLangGraphSendCommand`. Note that v1's command
263
- * shape (`{ resume?, goto?, update? }`) differs from the legacy
264
- * `{ resume: string }` form — to carry a payload, use the input or
265
- * `stream.respond` instead.
266
- */
267
- export const useLangChainSendCommand = () => {
268
- const submit = useLangChainSubmit();
269
- return (command) => submit(null, { command });
196
+ * Submit a `useStream` command (e.g. interrupt resume). Parity helper
197
+ * for migrating from `useLangGraphSendCommand`. Note that v1's command
198
+ * shape (`{ resume?, goto?, update? }`) differs from the legacy
199
+ * `{ resume: string }` form — to carry a payload, use the input or
200
+ * `stream.respond` instead.
201
+ */
202
+ const useLangChainSendCommand = () => {
203
+ const submit = useLangChainSubmit();
204
+ return (command) => submit(null, { command });
270
205
  };
271
- export function useLangChainState(key, defaultValue) {
272
- return useAuiState((s) => {
273
- const extras = s.thread.extras;
274
- if (!extras)
275
- return defaultValue;
276
- const value = asLangChainRuntimeExtras(extras).values[key];
277
- return value !== undefined ? value : defaultValue;
278
- });
206
+ function useLangChainState(key, defaultValue) {
207
+ return useAuiState((s) => {
208
+ const extras = s.thread.extras;
209
+ if (!extras) return defaultValue;
210
+ const value = asLangChainRuntimeExtras(extras).values[key];
211
+ return value !== void 0 ? value : defaultValue;
212
+ });
279
213
  }
214
+ //#endregion
215
+ export { useLangChainInterruptState, useLangChainSend, useLangChainSendCommand, useLangChainState, useLangChainSubmit, useStreamRuntime };
216
+
280
217
  //# 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":["/// <reference types=\"@assistant-ui/core/store\" />\n\"use client\";\n\nimport { useMemo, useRef, useState } from \"react\";\nimport type {\n AppendMessage,\n AttachmentAdapter,\n FeedbackAdapter,\n RemoteThreadListAdapter,\n SpeechSynthesisAdapter,\n ToolExecutionStatus,\n} from \"@assistant-ui/core\";\nimport {\n useCloudThreadListAdapter,\n useExternalStoreRuntime,\n useExternalMessageConverter,\n useRemoteThreadListRuntime,\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 streamRef = useRef(stream);\n streamRef.current = stream;\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 unstable_enableToolInvocations: true,\n setToolStatuses,\n onNew: async (msg) => {\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 }\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.7",
3
+ "version": "0.0.10",
4
4
  "description": "LangChain useStream adapter for assistant-ui",
5
5
  "keywords": [
6
6
  "langchain",
@@ -29,10 +29,10 @@
29
29
  ],
30
30
  "sideEffects": false,
31
31
  "dependencies": {
32
- "@assistant-ui/core": "^0.2.3",
33
- "@assistant-ui/store": "^0.2.11",
32
+ "@assistant-ui/core": "^0.2.7",
33
+ "@assistant-ui/store": "^0.2.12",
34
34
  "assistant-cloud": "*",
35
- "assistant-stream": "^0.3.15"
35
+ "assistant-stream": "^0.3.16"
36
36
  },
37
37
  "peerDependencies": {
38
38
  "@langchain/react": "^1.0.2",
@@ -45,15 +45,15 @@
45
45
  }
46
46
  },
47
47
  "devDependencies": {
48
- "@langchain/core": "^1.1.44",
49
- "@langchain/langgraph-sdk": "^1.9.2",
50
- "@langchain/react": "^1.0.2",
48
+ "@langchain/core": "^1.1.48",
49
+ "@langchain/langgraph-sdk": "^1.9.6",
50
+ "@langchain/react": "^1.0.6",
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.8"
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",
@@ -1,3 +1,4 @@
1
+ /// <reference types="@assistant-ui/core/store" />
1
2
  "use client";
2
3
 
3
4
  import { useMemo, useRef, useState } from "react";
@@ -7,14 +8,13 @@ import type {
7
8
  FeedbackAdapter,
8
9
  RemoteThreadListAdapter,
9
10
  SpeechSynthesisAdapter,
11
+ ToolExecutionStatus,
10
12
  } from "@assistant-ui/core";
11
13
  import {
12
14
  useCloudThreadListAdapter,
13
15
  useExternalStoreRuntime,
14
16
  useExternalMessageConverter,
15
17
  useRemoteThreadListRuntime,
16
- useToolInvocations,
17
- type ToolExecutionStatus,
18
18
  } from "@assistant-ui/core/react";
19
19
  import { useAui, useAuiState } from "@assistant-ui/store";
20
20
  import type { AssistantCloud } from "assistant-cloud";
@@ -137,8 +137,12 @@ const getMessageContent = (msg: AppendMessage) => {
137
137
  case "tool-call":
138
138
  throw new Error("Tool call appends are not supported.");
139
139
  default: {
140
- const _exhaustiveCheck: "reasoning" | "source" | "audio" | "data" =
141
- type;
140
+ const _exhaustiveCheck:
141
+ | "reasoning"
142
+ | "source"
143
+ | "audio"
144
+ | "data"
145
+ | "generative-ui" = type;
142
146
  throw new Error(
143
147
  `Unsupported append message part type: ${_exhaustiveCheck}`,
144
148
  );
@@ -194,45 +198,10 @@ const useStreamThreadRuntime = (
194
198
  isRunning: effectiveIsRunning,
195
199
  });
196
200
 
197
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
198
- const [runtimeRef] = useState(() => ({
199
- get current() {
200
- return runtime;
201
- },
202
- }));
203
-
204
201
  // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
205
202
  const streamRef = useRef(stream);
206
203
  streamRef.current = stream;
207
204
 
208
- // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
209
- const toolInvocations = useToolInvocations({
210
- state: {
211
- messages: threadMessages,
212
- isRunning: effectiveIsRunning,
213
- },
214
- getTools: () => runtimeRef.current.thread.getModelContext().tools,
215
- onResult: (command) => {
216
- if (command.type === "add-tool-result") {
217
- void streamRef.current.submit(
218
- {
219
- [messagesKey]: [
220
- {
221
- type: "tool",
222
- name: command.toolName,
223
- tool_call_id: command.toolCallId,
224
- content: JSON.stringify(command.result),
225
- status: command.isError ? "error" : "success",
226
- },
227
- ],
228
- },
229
- {},
230
- );
231
- }
232
- },
233
- setToolStatuses,
234
- });
235
-
236
205
  // biome-ignore lint/correctness/useHookAtTopLevel: intentional conditional/nested hook usage
237
206
  const extras = useMemo(
238
207
  (): LangChainRuntimeExtras => ({
@@ -258,8 +227,9 @@ const useStreamThreadRuntime = (
258
227
  messages: threadMessages,
259
228
  adapters,
260
229
  extras,
230
+ unstable_enableToolInvocations: true,
231
+ setToolStatuses,
261
232
  onNew: async (msg) => {
262
- await toolInvocations.abort();
263
233
  const content = getMessageContent(msg);
264
234
  const cancellations =
265
235
  autoCancelPendingToolCalls !== false
@@ -301,7 +271,6 @@ const useStreamThreadRuntime = (
301
271
  unstable_allowCancellation !== false
302
272
  ? async () => {
303
273
  await stream.stop();
304
- await toolInvocations.abort();
305
274
  }
306
275
  : undefined,
307
276
  });
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,0BAA0B,EAC1B,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,GACnB,8BAA2B;AAC5B,YAAY,EAAE,uBAAuB,EAAE,8BAA2B;AAElE,OAAO,EAAE,2BAA2B,EAAE,6BAA0B;AAEhE,YAAY,EACV,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,GAClB,mBAAgB"}
package/dist/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,gBAAgB,EAChB,0BAA0B,EAC1B,gBAAgB,EAChB,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,GACnB,8BAA2B;AAG5B,OAAO,EAAE,2BAA2B,EAAE,6BAA0B"}
package/dist/types.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}