@assistant-ui/react-langgraph 0.5.6 → 0.5.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/convertLangChainMessages.d.ts.map +1 -1
- package/dist/convertLangChainMessages.js +4 -0
- package/dist/convertLangChainMessages.js.map +1 -1
- package/dist/testUtils.d.ts +4 -0
- package/dist/testUtils.d.ts.map +1 -0
- package/dist/testUtils.js +10 -0
- package/dist/testUtils.js.map +1 -0
- package/dist/types.d.ts +9 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -1
- package/dist/useLangGraphMessages.d.ts +8 -2
- package/dist/useLangGraphMessages.d.ts.map +1 -1
- package/dist/useLangGraphMessages.js +33 -4
- package/dist/useLangGraphMessages.js.map +1 -1
- package/dist/useLangGraphRuntime.d.ts +23 -2
- package/dist/useLangGraphRuntime.d.ts.map +1 -1
- package/dist/useLangGraphRuntime.js +4 -2
- package/dist/useLangGraphRuntime.js.map +1 -1
- package/package.json +8 -8
- package/src/convertLangChainMessages.ts +4 -0
- package/src/testUtils.ts +11 -0
- package/src/types.ts +15 -2
- package/src/useLangGraphMessages.test.ts +3 -18
- package/src/useLangGraphMessages.ts +43 -4
- package/src/useLangGraphRuntime.test.tsx +276 -0
- package/src/useLangGraphRuntime.ts +33 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convertLangChainMessages.d.ts","sourceRoot":"","sources":["../src/convertLangChainMessages.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"convertLangChainMessages.d.ts","sourceRoot":"","sources":["../src/convertLangChainMessages.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,2BAA2B,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAqC3C,eAAO,MAAM,wBAAwB,EAAE,2BAA2B,CAAC,QAAQ,CACzE,gBAAgB,CA4CjB,CAAC"}
|
|
@@ -9,6 +9,8 @@ var contentToParts = (content) => {
|
|
|
9
9
|
switch (type) {
|
|
10
10
|
case "text":
|
|
11
11
|
return { type: "text", text: part.text };
|
|
12
|
+
case "text_delta":
|
|
13
|
+
return { type: "text", text: part.text };
|
|
12
14
|
case "image_url":
|
|
13
15
|
if (typeof part.image_url === "string") {
|
|
14
16
|
return { type: "image", image: part.image_url };
|
|
@@ -20,6 +22,8 @@ var contentToParts = (content) => {
|
|
|
20
22
|
}
|
|
21
23
|
case "tool_use":
|
|
22
24
|
return null;
|
|
25
|
+
case "input_json_delta":
|
|
26
|
+
return null;
|
|
23
27
|
default:
|
|
24
28
|
const _exhaustiveCheck = type;
|
|
25
29
|
throw new Error(`Unknown content part type: ${_exhaustiveCheck}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/convertLangChainMessages.ts"],"sourcesContent":["\"use client\";\n\nimport { useExternalMessageConverter } from \"@assistant-ui/react\";\nimport { LangChainMessage } from \"./types\";\nimport { ToolCallContentPart } from \"@assistant-ui/react\";\nimport { ThreadUserMessage } from \"@assistant-ui/react\";\n\nconst contentToParts = (content: LangChainMessage[\"content\"]) => {\n if (typeof content === \"string\")\n return [{ type: \"text\" as const, text: content }];\n return content\n .map((part): ThreadUserMessage[\"content\"][number] | null => {\n const type = part.type;\n switch (type) {\n case \"text\":\n return { type: \"text\", text: part.text };\n case \"image_url\":\n if (typeof part.image_url === \"string\") {\n return { type: \"image\", image: part.image_url };\n } else {\n return {\n type: \"image\",\n image: part.image_url.url,\n };\n }\n\n case \"tool_use\":\n return null;\n default:\n const _exhaustiveCheck: never = type;\n throw new Error(`Unknown content part type: ${_exhaustiveCheck}`);\n }\n })\n .filter((a) => a !== null);\n};\n\nexport const convertLangChainMessages: useExternalMessageConverter.Callback<\n LangChainMessage\n> = (message) => {\n switch (message.type) {\n case \"system\":\n return {\n role: \"system\",\n id: message.id,\n content: [{ type: \"text\", text: message.content }],\n };\n case \"human\":\n return {\n role: \"user\",\n id: message.id,\n content: contentToParts(message.content),\n };\n case \"ai\":\n return {\n role: \"assistant\",\n id: message.id,\n content: [\n ...contentToParts(message.content),\n ...(message.tool_calls?.map(\n (chunk): ToolCallContentPart => ({\n type: \"tool-call\",\n toolCallId: chunk.id,\n toolName: chunk.name,\n args: chunk.args,\n argsText:\n message.tool_call_chunks?.find((c) => c.id === chunk.id)\n ?.args ?? JSON.stringify(chunk.args),\n }),\n ) ?? []),\n ],\n };\n case \"tool\":\n return {\n role: \"tool\",\n toolName: message.name,\n toolCallId: message.tool_call_id,\n result: message.content,\n artifact: message.artifact,\n isError: message.status === \"error\",\n };\n }\n};\n"],"mappings":";;;AAOA,IAAM,iBAAiB,CAAC,YAAyC;AAC/D,MAAI,OAAO,YAAY;AACrB,WAAO,CAAC,EAAE,MAAM,QAAiB,MAAM,QAAQ,CAAC;AAClD,SAAO,QACJ,IAAI,CAAC,SAAsD;AAC1D,UAAM,OAAO,KAAK;AAClB,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,eAAO,EAAE,MAAM,QAAQ,MAAM,KAAK,KAAK;AAAA,MACzC,KAAK;AACH,YAAI,OAAO,KAAK,cAAc,UAAU;AACtC,iBAAO,EAAE,MAAM,SAAS,OAAO,KAAK,UAAU;AAAA,QAChD,OAAO;AACL,iBAAO;AAAA,YACL,MAAM;AAAA,YACN,OAAO,KAAK,UAAU;AAAA,UACxB;AAAA,QACF;AAAA,MAEF,KAAK;AACH,eAAO;AAAA,MACT;AACE,cAAM,mBAA0B;AAChC,cAAM,IAAI,MAAM,8BAA8B,gBAAgB,EAAE;AAAA,IACpE;AAAA,EACF,CAAC,EACA,OAAO,CAAC,MAAM,MAAM,IAAI;AAC7B;AAEO,IAAM,2BAET,CAAC,YAAY;AACf,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,IAAI,QAAQ;AAAA,QACZ,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,QAAQ,QAAQ,CAAC;AAAA,MACnD;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,IAAI,QAAQ;AAAA,QACZ,SAAS,eAAe,QAAQ,OAAO;AAAA,MACzC;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,IAAI,QAAQ;AAAA,QACZ,SAAS;AAAA,UACP,GAAG,eAAe,QAAQ,OAAO;AAAA,UACjC,GAAI,QAAQ,YAAY;AAAA,YACtB,CAAC,WAAgC;AAAA,cAC/B,MAAM;AAAA,cACN,YAAY,MAAM;AAAA,cAClB,UAAU,MAAM;AAAA,cAChB,MAAM,MAAM;AAAA,cACZ,UACE,QAAQ,kBAAkB,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE,GACnD,QAAQ,KAAK,UAAU,MAAM,IAAI;AAAA,YACzC;AAAA,UACF,KAAK,CAAC;AAAA,QACR;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,UAAU,QAAQ;AAAA,QAClB,YAAY,QAAQ;AAAA,QACpB,QAAQ,QAAQ;AAAA,QAChB,UAAU,QAAQ;AAAA,QAClB,SAAS,QAAQ,WAAW;AAAA,MAC9B;AAAA,EACJ;AACF;","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/convertLangChainMessages.ts"],"sourcesContent":["\"use client\";\n\nimport { useExternalMessageConverter } from \"@assistant-ui/react\";\nimport { LangChainMessage } from \"./types\";\nimport { ToolCallContentPart } from \"@assistant-ui/react\";\nimport { ThreadUserMessage } from \"@assistant-ui/react\";\n\nconst contentToParts = (content: LangChainMessage[\"content\"]) => {\n if (typeof content === \"string\")\n return [{ type: \"text\" as const, text: content }];\n return content\n .map((part): ThreadUserMessage[\"content\"][number] | null => {\n const type = part.type;\n switch (type) {\n case \"text\":\n return { type: \"text\", text: part.text };\n case \"text_delta\":\n return { type: \"text\", text: part.text };\n case \"image_url\":\n if (typeof part.image_url === \"string\") {\n return { type: \"image\", image: part.image_url };\n } else {\n return {\n type: \"image\",\n image: part.image_url.url,\n };\n }\n\n case \"tool_use\":\n return null;\n case \"input_json_delta\":\n return null;\n default:\n const _exhaustiveCheck: never = type;\n throw new Error(`Unknown content part type: ${_exhaustiveCheck}`);\n }\n })\n .filter((a) => a !== null);\n};\n\nexport const convertLangChainMessages: useExternalMessageConverter.Callback<\n LangChainMessage\n> = (message) => {\n switch (message.type) {\n case \"system\":\n return {\n role: \"system\",\n id: message.id,\n content: [{ type: \"text\", text: message.content }],\n };\n case \"human\":\n return {\n role: \"user\",\n id: message.id,\n content: contentToParts(message.content),\n };\n case \"ai\":\n return {\n role: \"assistant\",\n id: message.id,\n content: [\n ...contentToParts(message.content),\n ...(message.tool_calls?.map(\n (chunk): ToolCallContentPart => ({\n type: \"tool-call\",\n toolCallId: chunk.id,\n toolName: chunk.name,\n args: chunk.args,\n argsText:\n message.tool_call_chunks?.find((c) => c.id === chunk.id)\n ?.args ?? JSON.stringify(chunk.args),\n }),\n ) ?? []),\n ],\n };\n case \"tool\":\n return {\n role: \"tool\",\n toolName: message.name,\n toolCallId: message.tool_call_id,\n result: message.content,\n artifact: message.artifact,\n isError: message.status === \"error\",\n };\n }\n};\n"],"mappings":";;;AAOA,IAAM,iBAAiB,CAAC,YAAyC;AAC/D,MAAI,OAAO,YAAY;AACrB,WAAO,CAAC,EAAE,MAAM,QAAiB,MAAM,QAAQ,CAAC;AAClD,SAAO,QACJ,IAAI,CAAC,SAAsD;AAC1D,UAAM,OAAO,KAAK;AAClB,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,eAAO,EAAE,MAAM,QAAQ,MAAM,KAAK,KAAK;AAAA,MACzC,KAAK;AACH,eAAO,EAAE,MAAM,QAAQ,MAAM,KAAK,KAAK;AAAA,MACzC,KAAK;AACH,YAAI,OAAO,KAAK,cAAc,UAAU;AACtC,iBAAO,EAAE,MAAM,SAAS,OAAO,KAAK,UAAU;AAAA,QAChD,OAAO;AACL,iBAAO;AAAA,YACL,MAAM;AAAA,YACN,OAAO,KAAK,UAAU;AAAA,UACxB;AAAA,QACF;AAAA,MAEF,KAAK;AACH,eAAO;AAAA,MACT,KAAK;AACH,eAAO;AAAA,MACT;AACE,cAAM,mBAA0B;AAChC,cAAM,IAAI,MAAM,8BAA8B,gBAAgB,EAAE;AAAA,IACpE;AAAA,EACF,CAAC,EACA,OAAO,CAAC,MAAM,MAAM,IAAI;AAC7B;AAEO,IAAM,2BAET,CAAC,YAAY;AACf,UAAQ,QAAQ,MAAM;AAAA,IACpB,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,IAAI,QAAQ;AAAA,QACZ,SAAS,CAAC,EAAE,MAAM,QAAQ,MAAM,QAAQ,QAAQ,CAAC;AAAA,MACnD;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,IAAI,QAAQ;AAAA,QACZ,SAAS,eAAe,QAAQ,OAAO;AAAA,MACzC;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,IAAI,QAAQ;AAAA,QACZ,SAAS;AAAA,UACP,GAAG,eAAe,QAAQ,OAAO;AAAA,UACjC,GAAI,QAAQ,YAAY;AAAA,YACtB,CAAC,WAAgC;AAAA,cAC/B,MAAM;AAAA,cACN,YAAY,MAAM;AAAA,cAClB,UAAU,MAAM;AAAA,cAChB,MAAM,MAAM;AAAA,cACZ,UACE,QAAQ,kBAAkB,KAAK,CAAC,MAAM,EAAE,OAAO,MAAM,EAAE,GACnD,QAAQ,KAAK,UAAU,MAAM,IAAI;AAAA,YACzC;AAAA,UACF,KAAK,CAAC;AAAA,QACR;AAAA,MACF;AAAA,IACF,KAAK;AACH,aAAO;AAAA,QACL,MAAM;AAAA,QACN,UAAU,QAAQ;AAAA,QAClB,YAAY,QAAQ;AAAA,QACpB,QAAQ,QAAQ;AAAA,QAChB,UAAU,QAAQ;AAAA,QAClB,SAAS,QAAQ,WAAW;AAAA,MAC9B;AAAA,EACJ;AACF;","names":[]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { LangChainMessage } from "./types";
|
|
2
|
+
import { LangGraphMessagesEvent } from "./useLangGraphMessages";
|
|
3
|
+
export declare const mockStreamCallbackFactory: (events: Array<LangGraphMessagesEvent<LangChainMessage>>) => () => AsyncGenerator<LangGraphMessagesEvent<LangChainMessage>, void, unknown>;
|
|
4
|
+
//# sourceMappingURL=testUtils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"testUtils.d.ts","sourceRoot":"","sources":["../src/testUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAC3C,OAAO,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAEhE,eAAO,MAAM,yBAAyB,GACpC,QAAQ,KAAK,CAAC,sBAAsB,CAAC,gBAAgB,CAAC,CAAC,kFAMtD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/testUtils.ts"],"sourcesContent":["import { LangChainMessage } from \"./types\";\nimport { LangGraphMessagesEvent } from \"./useLangGraphMessages\";\n\nexport const mockStreamCallbackFactory = (\n events: Array<LangGraphMessagesEvent<LangChainMessage>>,\n) =>\n async function* () {\n for (const event of events) {\n yield event;\n }\n };\n"],"mappings":";AAGO,IAAM,4BAA4B,CACvC,WAEA,mBAAmB;AACjB,aAAW,SAAS,QAAQ;AAC1B,UAAM;AAAA,EACR;AACF;","names":[]}
|
package/dist/types.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export type LangChainToolCall = {
|
|
|
12
12
|
args: ReadonlyJSONObject;
|
|
13
13
|
};
|
|
14
14
|
export type MessageContentText = {
|
|
15
|
-
type: "text";
|
|
15
|
+
type: "text" | "text_delta";
|
|
16
16
|
text: string;
|
|
17
17
|
};
|
|
18
18
|
export type MessageContentImageUrl = {
|
|
@@ -22,14 +22,16 @@ export type MessageContentImageUrl = {
|
|
|
22
22
|
};
|
|
23
23
|
};
|
|
24
24
|
type MessageContentToolUse = {
|
|
25
|
-
type: "tool_use";
|
|
25
|
+
type: "tool_use" | "input_json_delta";
|
|
26
26
|
};
|
|
27
27
|
export declare enum LangGraphKnownEventTypes {
|
|
28
28
|
Messages = "messages",
|
|
29
29
|
MessagesPartial = "messages/partial",
|
|
30
30
|
MessagesComplete = "messages/complete",
|
|
31
31
|
Metadata = "metadata",
|
|
32
|
-
Updates = "updates"
|
|
32
|
+
Updates = "updates",
|
|
33
|
+
Info = "info",
|
|
34
|
+
Error = "error"
|
|
33
35
|
}
|
|
34
36
|
type CustomEventType = string;
|
|
35
37
|
export type EventType = LangGraphKnownEventTypes | CustomEventType;
|
|
@@ -75,5 +77,9 @@ export type LangChainMessageTupleEvent = {
|
|
|
75
77
|
event: LangGraphKnownEventTypes.Messages;
|
|
76
78
|
data: [LangChainMessageChunk, LangGraphTupleMetadata];
|
|
77
79
|
};
|
|
80
|
+
export type OnMetadataEventCallback = (metadata: unknown) => void | Promise<void>;
|
|
81
|
+
export type OnInfoEventCallback = (info: unknown) => void | Promise<void>;
|
|
82
|
+
export type OnErrorEventCallback = (error: unknown) => void | Promise<void>;
|
|
83
|
+
export type OnCustomEventCallback = (type: string, data: unknown) => void | Promise<void>;
|
|
78
84
|
export {};
|
|
79
85
|
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,MAAM,sBAAsB,GAAG;IACnC,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,kBAAkB,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,IAAI,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
CHANGED
|
@@ -5,6 +5,8 @@ var LangGraphKnownEventTypes = /* @__PURE__ */ ((LangGraphKnownEventTypes2) => {
|
|
|
5
5
|
LangGraphKnownEventTypes2["MessagesComplete"] = "messages/complete";
|
|
6
6
|
LangGraphKnownEventTypes2["Metadata"] = "metadata";
|
|
7
7
|
LangGraphKnownEventTypes2["Updates"] = "updates";
|
|
8
|
+
LangGraphKnownEventTypes2["Info"] = "info";
|
|
9
|
+
LangGraphKnownEventTypes2["Error"] = "error";
|
|
8
10
|
return LangGraphKnownEventTypes2;
|
|
9
11
|
})(LangGraphKnownEventTypes || {});
|
|
10
12
|
export {
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import { ReadonlyJSONObject } from \"assistant-stream/utils\";\n\nexport type LangChainToolCallChunk = {\n index: number;\n id: string;\n name: string;\n args: string;\n};\n\nexport type LangChainToolCall = {\n id: string;\n name: string;\n argsText: string;\n args: ReadonlyJSONObject;\n};\n\nexport type MessageContentText = {\n type: \"text\";\n text: string;\n};\n\nexport type MessageContentImageUrl = {\n type: \"image_url\";\n image_url: string | { url: string };\n};\n\ntype MessageContentToolUse = {\n type: \"tool_use\";\n};\n\nexport enum LangGraphKnownEventTypes {\n Messages = \"messages\",\n MessagesPartial = \"messages/partial\",\n MessagesComplete = \"messages/complete\",\n Metadata = \"metadata\",\n Updates = \"updates\",\n}\ntype CustomEventType = string;\n\nexport type EventType = LangGraphKnownEventTypes | CustomEventType;\n\ntype UserMessageContentComplex = MessageContentText | MessageContentImageUrl;\ntype AssistantMessageContentComplex =\n | MessageContentText\n | MessageContentImageUrl\n | MessageContentToolUse;\n\ntype UserMessageContent = string | UserMessageContentComplex[];\ntype AssistantMessageContent = string | AssistantMessageContentComplex[];\n\nexport type LangChainMessage =\n | {\n id?: string;\n type: \"system\";\n content: string;\n }\n | {\n id?: string;\n type: \"human\";\n content: UserMessageContent;\n }\n | {\n id?: string;\n type: \"tool\";\n content: string;\n tool_call_id: string;\n name: string;\n artifact?: any;\n status: \"success\" | \"error\";\n }\n | {\n id?: string;\n type: \"ai\";\n content: AssistantMessageContent;\n tool_call_chunks?: LangChainToolCallChunk[];\n tool_calls?: LangChainToolCall[];\n };\n\nexport type LangChainMessageChunk = {\n id?: string | undefined;\n type: \"AIMessageChunk\";\n content?: AssistantMessageContent | undefined;\n tool_call_chunks?: LangChainToolCallChunk[] | undefined;\n};\n\nexport type LangChainEvent = {\n event:\n | LangGraphKnownEventTypes.MessagesPartial\n | LangGraphKnownEventTypes.MessagesComplete;\n data: LangChainMessage[];\n};\n\ntype LangGraphTupleMetadata = Record<string, unknown>;\n\nexport type LangChainMessageTupleEvent = {\n event: LangGraphKnownEventTypes.Messages;\n data: [LangChainMessageChunk, LangGraphTupleMetadata];\n};\n"],"mappings":";AA8BO,IAAK,2BAAL,kBAAKA,8BAAL;AACL,EAAAA,0BAAA,cAAW;AACX,EAAAA,0BAAA,qBAAkB;AAClB,EAAAA,0BAAA,sBAAmB;AACnB,EAAAA,0BAAA,cAAW;AACX,EAAAA,0BAAA,aAAU;
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import { ReadonlyJSONObject } from \"assistant-stream/utils\";\n\nexport type LangChainToolCallChunk = {\n index: number;\n id: string;\n name: string;\n args: string;\n};\n\nexport type LangChainToolCall = {\n id: string;\n name: string;\n argsText: string;\n args: ReadonlyJSONObject;\n};\n\nexport type MessageContentText = {\n type: \"text\" | \"text_delta\";\n text: string;\n};\n\nexport type MessageContentImageUrl = {\n type: \"image_url\";\n image_url: string | { url: string };\n};\n\ntype MessageContentToolUse = {\n type: \"tool_use\" | \"input_json_delta\";\n};\n\nexport enum LangGraphKnownEventTypes {\n Messages = \"messages\",\n MessagesPartial = \"messages/partial\",\n MessagesComplete = \"messages/complete\",\n Metadata = \"metadata\",\n Updates = \"updates\",\n Info = \"info\",\n Error = \"error\",\n}\n\ntype CustomEventType = string;\n\nexport type EventType = LangGraphKnownEventTypes | CustomEventType;\n\ntype UserMessageContentComplex = MessageContentText | MessageContentImageUrl;\ntype AssistantMessageContentComplex =\n | MessageContentText\n | MessageContentImageUrl\n | MessageContentToolUse;\n\ntype UserMessageContent = string | UserMessageContentComplex[];\ntype AssistantMessageContent = string | AssistantMessageContentComplex[];\n\nexport type LangChainMessage =\n | {\n id?: string;\n type: \"system\";\n content: string;\n }\n | {\n id?: string;\n type: \"human\";\n content: UserMessageContent;\n }\n | {\n id?: string;\n type: \"tool\";\n content: string;\n tool_call_id: string;\n name: string;\n artifact?: any;\n status: \"success\" | \"error\";\n }\n | {\n id?: string;\n type: \"ai\";\n content: AssistantMessageContent;\n tool_call_chunks?: LangChainToolCallChunk[];\n tool_calls?: LangChainToolCall[];\n };\n\nexport type LangChainMessageChunk = {\n id?: string | undefined;\n type: \"AIMessageChunk\";\n content?: AssistantMessageContent | undefined;\n tool_call_chunks?: LangChainToolCallChunk[] | undefined;\n};\n\nexport type LangChainEvent = {\n event:\n | LangGraphKnownEventTypes.MessagesPartial\n | LangGraphKnownEventTypes.MessagesComplete;\n data: LangChainMessage[];\n};\n\ntype LangGraphTupleMetadata = Record<string, unknown>;\n\nexport type LangChainMessageTupleEvent = {\n event: LangGraphKnownEventTypes.Messages;\n data: [LangChainMessageChunk, LangGraphTupleMetadata];\n};\n\nexport type OnMetadataEventCallback = (\n metadata: unknown,\n) => void | Promise<void>;\nexport type OnInfoEventCallback = (info: unknown) => void | Promise<void>;\nexport type OnErrorEventCallback = (error: unknown) => void | Promise<void>;\nexport type OnCustomEventCallback = (\n type: string,\n data: unknown,\n) => void | Promise<void>;\n"],"mappings":";AA8BO,IAAK,2BAAL,kBAAKA,8BAAL;AACL,EAAAA,0BAAA,cAAW;AACX,EAAAA,0BAAA,qBAAkB;AAClB,EAAAA,0BAAA,sBAAmB;AACnB,EAAAA,0BAAA,cAAW;AACX,EAAAA,0BAAA,aAAU;AACV,EAAAA,0BAAA,UAAO;AACP,EAAAA,0BAAA,WAAQ;AAPE,SAAAA;AAAA,GAAA;","names":["LangGraphKnownEventTypes"]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventType } from "./types";
|
|
1
|
+
import { EventType, OnCustomEventCallback, OnErrorEventCallback, OnInfoEventCallback, OnMetadataEventCallback } from "./types";
|
|
2
2
|
export type LangGraphCommand = {
|
|
3
3
|
resume: string;
|
|
4
4
|
};
|
|
@@ -21,9 +21,15 @@ export type LangGraphInterruptState = {
|
|
|
21
21
|
};
|
|
22
22
|
export declare const useLangGraphMessages: <TMessage extends {
|
|
23
23
|
id?: string;
|
|
24
|
-
}>({ stream, appendMessage, }: {
|
|
24
|
+
}>({ stream, appendMessage, eventHandlers, }: {
|
|
25
25
|
stream: LangGraphStreamCallback<TMessage>;
|
|
26
26
|
appendMessage?: (prev: TMessage | undefined, curr: TMessage) => TMessage;
|
|
27
|
+
eventHandlers?: {
|
|
28
|
+
onMetadata?: OnMetadataEventCallback;
|
|
29
|
+
onInfo?: OnInfoEventCallback;
|
|
30
|
+
onError?: OnErrorEventCallback;
|
|
31
|
+
onCustomEvent?: OnCustomEventCallback;
|
|
32
|
+
};
|
|
27
33
|
}) => {
|
|
28
34
|
interrupt: LangGraphInterruptState | undefined;
|
|
29
35
|
messages: TMessage[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLangGraphMessages.d.ts","sourceRoot":"","sources":["../src/useLangGraphMessages.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,SAAS,
|
|
1
|
+
{"version":3,"file":"useLangGraphMessages.d.ts","sourceRoot":"","sources":["../src/useLangGraphMessages.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,SAAS,EAIT,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,0BAA0B,GAAG;IACvC,OAAO,CAAC,EAAE,gBAAgB,CAAC;IAC3B,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,sBAAsB,CAAC,QAAQ,IAAI;IAC7C,KAAK,EAAE,SAAS,CAAC;IACjB,IAAI,EAAE,QAAQ,EAAE,GAAG,GAAG,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,uBAAuB,CAAC,QAAQ,IAAI,CAC9C,QAAQ,EAAE,QAAQ,EAAE,EACpB,MAAM,EAAE,0BAA0B,GAAG;IAAE,WAAW,EAAE,WAAW,CAAA;CAAE,KAE/D,OAAO,CAAC,cAAc,CAAC,sBAAsB,CAAC,QAAQ,CAAC,CAAC,CAAC,GACzD,cAAc,CAAC,sBAAsB,CAAC,QAAQ,CAAC,CAAC,CAAC;AAErD,MAAM,MAAM,uBAAuB,GAAG;IACpC,KAAK,CAAC,EAAE,GAAG,CAAC;IACZ,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC;CACf,CAAC;AAuBF,eAAO,MAAM,oBAAoB,GAAI,QAAQ,SAAS;IAAE,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,2CAIpE;IACD,MAAM,EAAE,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IAC1C,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,QAAQ,GAAG,SAAS,EAAE,IAAI,EAAE,QAAQ,KAAK,QAAQ,CAAC;IACzE,aAAa,CAAC,EAAE;QACd,UAAU,CAAC,EAAE,uBAAuB,CAAC;QACrC,MAAM,CAAC,EAAE,mBAAmB,CAAC;QAC7B,OAAO,CAAC,EAAE,oBAAoB,CAAC;QAC/B,aAAa,CAAC,EAAE,qBAAqB,CAAC;KACvC,CAAC;CACH;;;+BAauB,QAAQ,EAAE,UAAU,0BAA0B;;;;CA2FrE,CAAC"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// src/useLangGraphMessages.ts
|
|
2
|
-
import { useState, useCallback, useRef } from "react";
|
|
2
|
+
import { useState, useCallback, useRef, useMemo } from "react";
|
|
3
3
|
import { v4 as uuidv4 } from "uuid";
|
|
4
4
|
import { LangGraphMessageAccumulator } from "./LangGraphMessageAccumulator.js";
|
|
5
5
|
import {
|
|
@@ -13,11 +13,16 @@ var isLangChainMessageChunk = (value) => {
|
|
|
13
13
|
};
|
|
14
14
|
var useLangGraphMessages = ({
|
|
15
15
|
stream,
|
|
16
|
-
appendMessage = DEFAULT_APPEND_MESSAGE
|
|
16
|
+
appendMessage = DEFAULT_APPEND_MESSAGE,
|
|
17
|
+
eventHandlers
|
|
17
18
|
}) => {
|
|
18
19
|
const [interrupt, setInterrupt] = useState();
|
|
19
20
|
const [messages, setMessages] = useState([]);
|
|
20
21
|
const abortControllerRef = useRef(null);
|
|
22
|
+
const { onMetadata, onInfo, onError, onCustomEvent } = useMemo(
|
|
23
|
+
() => eventHandlers ?? {},
|
|
24
|
+
[eventHandlers]
|
|
25
|
+
);
|
|
21
26
|
const sendMessage = useCallback(
|
|
22
27
|
async (newMessages, config) => {
|
|
23
28
|
const newMessagesWithId = newMessages.map(
|
|
@@ -59,13 +64,37 @@ var useLangGraphMessages = ({
|
|
|
59
64
|
break;
|
|
60
65
|
}
|
|
61
66
|
case LangGraphKnownEventTypes.Metadata:
|
|
67
|
+
onMetadata?.(chunk.data);
|
|
68
|
+
break;
|
|
69
|
+
case LangGraphKnownEventTypes.Info:
|
|
70
|
+
onInfo?.(chunk.data);
|
|
71
|
+
break;
|
|
72
|
+
case LangGraphKnownEventTypes.Error:
|
|
73
|
+
onError?.(chunk.data);
|
|
62
74
|
break;
|
|
63
75
|
default:
|
|
64
|
-
|
|
76
|
+
if (onCustomEvent) {
|
|
77
|
+
onCustomEvent(chunk.event, chunk.data);
|
|
78
|
+
} else {
|
|
79
|
+
console.warn(
|
|
80
|
+
"Unhandled event received:",
|
|
81
|
+
chunk.event,
|
|
82
|
+
chunk.data
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
break;
|
|
65
86
|
}
|
|
66
87
|
}
|
|
67
88
|
},
|
|
68
|
-
[
|
|
89
|
+
[
|
|
90
|
+
messages,
|
|
91
|
+
appendMessage,
|
|
92
|
+
stream,
|
|
93
|
+
onMetadata,
|
|
94
|
+
onInfo,
|
|
95
|
+
onError,
|
|
96
|
+
onCustomEvent
|
|
97
|
+
]
|
|
69
98
|
);
|
|
70
99
|
const cancel = useCallback(() => {
|
|
71
100
|
if (abortControllerRef.current) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/useLangGraphMessages.ts"],"sourcesContent":["import { useState, useCallback, useRef } from \"react\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { LangGraphMessageAccumulator } from \"./LangGraphMessageAccumulator\";\nimport {\n EventType,\n LangChainMessageTupleEvent,\n LangGraphKnownEventTypes,\n LangChainMessageChunk,\n} from \"./types\";\n\nexport type LangGraphCommand = {\n resume: string;\n};\n\nexport type LangGraphSendMessageConfig = {\n command?: LangGraphCommand;\n runConfig?: unknown;\n};\n\nexport type LangGraphMessagesEvent<TMessage> = {\n event: EventType;\n data: TMessage[] | any;\n};\n\nexport type LangGraphStreamCallback<TMessage> = (\n messages: TMessage[],\n config: LangGraphSendMessageConfig & { abortSignal: AbortSignal },\n) =>\n | Promise<AsyncGenerator<LangGraphMessagesEvent<TMessage>>>\n | AsyncGenerator<LangGraphMessagesEvent<TMessage>>;\n\nexport type LangGraphInterruptState = {\n value?: any;\n resumable?: boolean;\n when: string;\n ns?: string[];\n};\n\nconst DEFAULT_APPEND_MESSAGE = <TMessage>(\n _: TMessage | undefined,\n curr: TMessage,\n) => curr;\n\nconst isLangChainMessageChunk = (\n value: unknown,\n): value is LangChainMessageChunk => {\n if (!value || typeof value !== \"object\") return false;\n const chunk = value as any;\n return (\n \"type\" in chunk &&\n chunk.type === \"AIMessageChunk\" &&\n (chunk.content === undefined ||\n typeof chunk.content === \"string\" ||\n Array.isArray(chunk.content)) &&\n (chunk.tool_call_chunks === undefined ||\n Array.isArray(chunk.tool_call_chunks))\n );\n};\n\nexport const useLangGraphMessages = <TMessage extends { id?: string }>({\n stream,\n appendMessage = DEFAULT_APPEND_MESSAGE,\n}: {\n stream: LangGraphStreamCallback<TMessage>;\n appendMessage?: (prev: TMessage | undefined, curr: TMessage) => TMessage;\n}) => {\n const [interrupt, setInterrupt] = useState<\n LangGraphInterruptState | undefined\n >();\n const [messages, setMessages] = useState<TMessage[]>([]);\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const sendMessage = useCallback(\n async (newMessages: TMessage[], config: LangGraphSendMessageConfig) => {\n // ensure all messages have an ID\n const newMessagesWithId = newMessages.map((m) =>\n m.id ? m : { ...m, id: uuidv4() },\n );\n\n const accumulator = new LangGraphMessageAccumulator({\n initialMessages: messages,\n appendMessage,\n });\n setMessages(accumulator.addMessages(newMessagesWithId));\n\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n const response = await stream(newMessagesWithId, {\n ...config,\n abortSignal: abortController.signal,\n });\n\n for await (const chunk of response) {\n switch (chunk.event) {\n case LangGraphKnownEventTypes.MessagesPartial:\n case LangGraphKnownEventTypes.MessagesComplete:\n setMessages(accumulator.addMessages(chunk.data));\n break;\n case LangGraphKnownEventTypes.Updates:\n setInterrupt(chunk.data.__interrupt__?.[0]);\n break;\n case LangGraphKnownEventTypes.Messages: {\n const [messageChunk] = (chunk as LangChainMessageTupleEvent).data;\n if (!isLangChainMessageChunk(messageChunk)) {\n console.warn(\n \"Received invalid message chunk format:\",\n messageChunk,\n );\n break;\n }\n const updatedMessages = accumulator.addMessages([\n messageChunk as unknown as TMessage,\n ]);\n setMessages(updatedMessages);\n break;\n }\n case LangGraphKnownEventTypes.Metadata:\n
|
|
1
|
+
{"version":3,"sources":["../src/useLangGraphMessages.ts"],"sourcesContent":["import { useState, useCallback, useRef, useMemo } from \"react\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { LangGraphMessageAccumulator } from \"./LangGraphMessageAccumulator\";\nimport {\n EventType,\n LangChainMessageTupleEvent,\n LangGraphKnownEventTypes,\n LangChainMessageChunk,\n OnCustomEventCallback,\n OnErrorEventCallback,\n OnInfoEventCallback,\n OnMetadataEventCallback,\n} from \"./types\";\n\nexport type LangGraphCommand = {\n resume: string;\n};\n\nexport type LangGraphSendMessageConfig = {\n command?: LangGraphCommand;\n runConfig?: unknown;\n};\n\nexport type LangGraphMessagesEvent<TMessage> = {\n event: EventType;\n data: TMessage[] | any;\n};\n\nexport type LangGraphStreamCallback<TMessage> = (\n messages: TMessage[],\n config: LangGraphSendMessageConfig & { abortSignal: AbortSignal },\n) =>\n | Promise<AsyncGenerator<LangGraphMessagesEvent<TMessage>>>\n | AsyncGenerator<LangGraphMessagesEvent<TMessage>>;\n\nexport type LangGraphInterruptState = {\n value?: any;\n resumable?: boolean;\n when: string;\n ns?: string[];\n};\n\nconst DEFAULT_APPEND_MESSAGE = <TMessage>(\n _: TMessage | undefined,\n curr: TMessage,\n) => curr;\n\nconst isLangChainMessageChunk = (\n value: unknown,\n): value is LangChainMessageChunk => {\n if (!value || typeof value !== \"object\") return false;\n const chunk = value as any;\n return (\n \"type\" in chunk &&\n chunk.type === \"AIMessageChunk\" &&\n (chunk.content === undefined ||\n typeof chunk.content === \"string\" ||\n Array.isArray(chunk.content)) &&\n (chunk.tool_call_chunks === undefined ||\n Array.isArray(chunk.tool_call_chunks))\n );\n};\n\nexport const useLangGraphMessages = <TMessage extends { id?: string }>({\n stream,\n appendMessage = DEFAULT_APPEND_MESSAGE,\n eventHandlers,\n}: {\n stream: LangGraphStreamCallback<TMessage>;\n appendMessage?: (prev: TMessage | undefined, curr: TMessage) => TMessage;\n eventHandlers?: {\n onMetadata?: OnMetadataEventCallback;\n onInfo?: OnInfoEventCallback;\n onError?: OnErrorEventCallback;\n onCustomEvent?: OnCustomEventCallback;\n };\n}) => {\n const [interrupt, setInterrupt] = useState<\n LangGraphInterruptState | undefined\n >();\n const [messages, setMessages] = useState<TMessage[]>([]);\n const abortControllerRef = useRef<AbortController | null>(null);\n\n const { onMetadata, onInfo, onError, onCustomEvent } = useMemo(\n () => eventHandlers ?? {},\n [eventHandlers],\n );\n\n const sendMessage = useCallback(\n async (newMessages: TMessage[], config: LangGraphSendMessageConfig) => {\n // ensure all messages have an ID\n const newMessagesWithId = newMessages.map((m) =>\n m.id ? m : { ...m, id: uuidv4() },\n );\n\n const accumulator = new LangGraphMessageAccumulator({\n initialMessages: messages,\n appendMessage,\n });\n setMessages(accumulator.addMessages(newMessagesWithId));\n\n const abortController = new AbortController();\n abortControllerRef.current = abortController;\n const response = await stream(newMessagesWithId, {\n ...config,\n abortSignal: abortController.signal,\n });\n\n for await (const chunk of response) {\n switch (chunk.event) {\n case LangGraphKnownEventTypes.MessagesPartial:\n case LangGraphKnownEventTypes.MessagesComplete:\n setMessages(accumulator.addMessages(chunk.data));\n break;\n case LangGraphKnownEventTypes.Updates:\n setInterrupt(chunk.data.__interrupt__?.[0]);\n break;\n case LangGraphKnownEventTypes.Messages: {\n const [messageChunk] = (chunk as LangChainMessageTupleEvent).data;\n if (!isLangChainMessageChunk(messageChunk)) {\n console.warn(\n \"Received invalid message chunk format:\",\n messageChunk,\n );\n break;\n }\n const updatedMessages = accumulator.addMessages([\n messageChunk as unknown as TMessage,\n ]);\n setMessages(updatedMessages);\n break;\n }\n case LangGraphKnownEventTypes.Metadata:\n onMetadata?.(chunk.data);\n break;\n case LangGraphKnownEventTypes.Info:\n onInfo?.(chunk.data);\n break;\n case LangGraphKnownEventTypes.Error:\n onError?.(chunk.data);\n break;\n default:\n if (onCustomEvent) {\n onCustomEvent(chunk.event, chunk.data);\n } else {\n console.warn(\n \"Unhandled event received:\",\n chunk.event,\n chunk.data,\n );\n }\n break;\n }\n }\n },\n [\n messages,\n appendMessage,\n stream,\n onMetadata,\n onInfo,\n onError,\n onCustomEvent,\n ],\n );\n\n const cancel = useCallback(() => {\n if (abortControllerRef.current) {\n abortControllerRef.current.abort();\n }\n }, [abortControllerRef]);\n\n return {\n interrupt,\n messages,\n sendMessage,\n cancel,\n setInterrupt,\n setMessages,\n };\n};\n"],"mappings":"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","names":[]}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LangChainMessage } from "./types";
|
|
1
|
+
import { LangChainMessage, OnCustomEventCallback, OnErrorEventCallback, OnInfoEventCallback, OnMetadataEventCallback } from "./types";
|
|
2
2
|
import { LangGraphCommand, LangGraphInterruptState, LangGraphSendMessageConfig, LangGraphStreamCallback } from "./useLangGraphMessages";
|
|
3
3
|
import { AttachmentAdapter } from "@assistant-ui/react";
|
|
4
4
|
import { FeedbackAdapter } from "@assistant-ui/react";
|
|
@@ -6,7 +6,7 @@ import { SpeechSynthesisAdapter } from "@assistant-ui/react";
|
|
|
6
6
|
export declare const useLangGraphInterruptState: () => LangGraphInterruptState | undefined;
|
|
7
7
|
export declare const useLangGraphSend: () => (messages: LangChainMessage[], config: LangGraphSendMessageConfig) => Promise<void>;
|
|
8
8
|
export declare const useLangGraphSendCommand: () => (command: LangGraphCommand) => Promise<void>;
|
|
9
|
-
export declare const useLangGraphRuntime: ({ autoCancelPendingToolCalls, adapters: { attachments, feedback, speech }, unstable_allowCancellation, stream, threadId, onSwitchToNewThread, onSwitchToThread, }: {
|
|
9
|
+
export declare const useLangGraphRuntime: ({ autoCancelPendingToolCalls, adapters: { attachments, feedback, speech }, unstable_allowCancellation, stream, threadId, onSwitchToNewThread, onSwitchToThread, eventHandlers, }: {
|
|
10
10
|
/**
|
|
11
11
|
* @deprecated For thread management use `useCloudThreadListRuntime` instead. This option will be removed in a future version.
|
|
12
12
|
*/
|
|
@@ -27,5 +27,26 @@ export declare const useLangGraphRuntime: ({ autoCancelPendingToolCalls, adapter
|
|
|
27
27
|
speech?: SpeechSynthesisAdapter;
|
|
28
28
|
feedback?: FeedbackAdapter;
|
|
29
29
|
} | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Event handlers for various LangGraph stream events
|
|
32
|
+
*/
|
|
33
|
+
eventHandlers?: {
|
|
34
|
+
/**
|
|
35
|
+
* Called when metadata is received from the LangGraph stream
|
|
36
|
+
*/
|
|
37
|
+
onMetadata?: OnMetadataEventCallback;
|
|
38
|
+
/**
|
|
39
|
+
* Called when informational messages are received from the LangGraph stream
|
|
40
|
+
*/
|
|
41
|
+
onInfo?: OnInfoEventCallback;
|
|
42
|
+
/**
|
|
43
|
+
* Called when errors occur during LangGraph stream processing
|
|
44
|
+
*/
|
|
45
|
+
onError?: OnErrorEventCallback;
|
|
46
|
+
/**
|
|
47
|
+
* Called when custom events are received from the LangGraph stream
|
|
48
|
+
*/
|
|
49
|
+
onCustomEvent?: OnCustomEventCallback;
|
|
50
|
+
} | undefined;
|
|
30
51
|
}) => import("@assistant-ui/react").AssistantRuntime;
|
|
31
52
|
//# sourceMappingURL=useLangGraphRuntime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useLangGraphRuntime.d.ts","sourceRoot":"","sources":["../src/useLangGraphRuntime.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"useLangGraphRuntime.d.ts","sourceRoot":"","sources":["../src/useLangGraphRuntime.ts"],"names":[],"mappings":"AACA,OAAO,EACL,gBAAgB,EAEhB,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,uBAAuB,EACxB,MAAM,SAAS,CAAC;AAQjB,OAAO,EACL,gBAAgB,EAChB,uBAAuB,EACvB,0BAA0B,EAC1B,uBAAuB,EAExB,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AA0E7D,eAAO,MAAM,0BAA0B,2CAGtC,CAAC;AAEF,eAAO,MAAM,gBAAgB,mBAxBf,gBAAgB,EAAE,UACpB,0BAA0B,KAC/B,OAAO,CAAC,IAAI,CAyBlB,CAAC;AAEF,eAAO,MAAM,uBAAuB,SAE1B,SAAS,gBAAgB,kBAClC,CAAC;AAEF,eAAO,MAAM,mBAAmB,GAAI,kLASjC;IACD;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC9B,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjD,0BAA0B,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACjD,MAAM,EAAE,uBAAuB,CAAC,gBAAgB,CAAC,CAAC;IAClD;;OAEG;IACH,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC;IACjD,gBAAgB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC;QAC/C,QAAQ,EAAE,gBAAgB,EAAE,CAAC;QAC7B,UAAU,CAAC,EAAE,uBAAuB,EAAE,CAAC;KACxC,CAAC,CAAC;IACH,QAAQ,CAAC,EACL;QACE,WAAW,CAAC,EAAE,iBAAiB,CAAC;QAChC,MAAM,CAAC,EAAE,sBAAsB,CAAC;QAChC,QAAQ,CAAC,EAAE,eAAe,CAAC;KAC5B,GACD,SAAS,CAAC;IACd;;OAEG;IACH,aAAa,CAAC,EACV;QACE;;WAEG;QACH,UAAU,CAAC,EAAE,uBAAuB,CAAC;QACrC;;WAEG;QACH,MAAM,CAAC,EAAE,mBAAmB,CAAC;QAC7B;;WAEG;QACH,OAAO,CAAC,EAAE,oBAAoB,CAAC;QAC/B;;WAEG;QACH,aAAa,CAAC,EAAE,qBAAqB,CAAC;KACvC,GACD,SAAS,CAAC;CACf,mDA8IA,CAAC"}
|
|
@@ -78,7 +78,8 @@ var useLangGraphRuntime = ({
|
|
|
78
78
|
stream,
|
|
79
79
|
threadId,
|
|
80
80
|
onSwitchToNewThread,
|
|
81
|
-
onSwitchToThread
|
|
81
|
+
onSwitchToThread,
|
|
82
|
+
eventHandlers
|
|
82
83
|
}) => {
|
|
83
84
|
const {
|
|
84
85
|
interrupt,
|
|
@@ -89,7 +90,8 @@ var useLangGraphRuntime = ({
|
|
|
89
90
|
setMessages
|
|
90
91
|
} = useLangGraphMessages({
|
|
91
92
|
appendMessage: appendLangChainChunk,
|
|
92
|
-
stream
|
|
93
|
+
stream,
|
|
94
|
+
...eventHandlers && { eventHandlers }
|
|
93
95
|
});
|
|
94
96
|
const [isRunning, setIsRunning] = useState(false);
|
|
95
97
|
const handleSendMessage = async (messages2, config) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/useLangGraphRuntime.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport { LangChainMessage, LangChainToolCall } from \"./types\";\nimport {\n useExternalMessageConverter,\n useExternalStoreRuntime,\n useThread,\n useThreadListItemRuntime,\n} from \"@assistant-ui/react\";\nimport { convertLangChainMessages } from \"./convertLangChainMessages\";\nimport {\n LangGraphCommand,\n LangGraphInterruptState,\n LangGraphSendMessageConfig,\n LangGraphStreamCallback,\n useLangGraphMessages,\n} from \"./useLangGraphMessages\";\nimport { AttachmentAdapter } from \"@assistant-ui/react\";\nimport { AppendMessage } from \"@assistant-ui/react\";\nimport { ExternalStoreAdapter } from \"@assistant-ui/react\";\nimport { FeedbackAdapter } from \"@assistant-ui/react\";\nimport { SpeechSynthesisAdapter } from \"@assistant-ui/react\";\nimport { appendLangChainChunk } from \"./appendLangChainChunk\";\n\nconst getPendingToolCalls = (messages: LangChainMessage[]) => {\n const pendingToolCalls = new Map<string, LangChainToolCall>();\n for (const message of messages) {\n if (message.type === \"ai\") {\n for (const toolCall of message.tool_calls ?? []) {\n pendingToolCalls.set(toolCall.id, toolCall);\n }\n }\n if (message.type === \"tool\") {\n pendingToolCalls.delete(message.tool_call_id);\n }\n }\n\n return [...pendingToolCalls.values()];\n};\n\nconst getMessageContent = (msg: AppendMessage) => {\n const allContent = [\n ...msg.content,\n ...(msg.attachments?.flatMap((a) => a.content) ?? []),\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\n case \"tool-call\":\n throw new Error(\"Tool call appends are not supported.\");\n\n default:\n const _exhaustiveCheck: \"reasoning\" | \"source\" | \"file\" | \"audio\" =\n type;\n throw new Error(\n `Unsupported append content part type: ${_exhaustiveCheck}`,\n );\n }\n });\n\n if (content.length === 1 && content[0]?.type === \"text\") {\n return content[0].text ?? \"\";\n }\n\n return content;\n};\n\nconst symbolLangGraphRuntimeExtras = Symbol(\"langgraph-runtime-extras\");\ntype LangGraphRuntimeExtras = {\n [symbolLangGraphRuntimeExtras]: true;\n send: (\n messages: LangChainMessage[],\n config: LangGraphSendMessageConfig,\n ) => Promise<void>;\n interrupt: LangGraphInterruptState | undefined;\n};\n\nconst asLangGraphRuntimeExtras = (extras: unknown): LangGraphRuntimeExtras => {\n if (\n typeof extras !== \"object\" ||\n extras == null ||\n !(symbolLangGraphRuntimeExtras in extras)\n )\n throw new Error(\n \"This method can only be called when you are using useLangGraphRuntime\",\n );\n\n return extras as LangGraphRuntimeExtras;\n};\n\nexport const useLangGraphInterruptState = () => {\n const { interrupt } = useThread((t) => asLangGraphRuntimeExtras(t.extras));\n return interrupt;\n};\n\nexport const useLangGraphSend = () => {\n const { send } = useThread((t) => asLangGraphRuntimeExtras(t.extras));\n return send;\n};\n\nexport const useLangGraphSendCommand = () => {\n const send = useLangGraphSend();\n return (command: LangGraphCommand) => send([], { command });\n};\n\nexport const useLangGraphRuntime = ({\n autoCancelPendingToolCalls,\n adapters: { attachments, feedback, speech } = {},\n unstable_allowCancellation,\n stream,\n threadId,\n onSwitchToNewThread,\n onSwitchToThread,\n}: {\n /**\n * @deprecated For thread management use `useCloudThreadListRuntime` instead. This option will be removed in a future version.\n */\n threadId?: string | undefined;\n autoCancelPendingToolCalls?: boolean | undefined;\n unstable_allowCancellation?: boolean | undefined;\n stream: LangGraphStreamCallback<LangChainMessage>;\n /**\n * @deprecated For thread management use `useCloudThreadListRuntime` instead. This option will be removed in a future version.\n */\n onSwitchToNewThread?: () => Promise<void> | void;\n onSwitchToThread?: (threadId: string) => Promise<{\n messages: LangChainMessage[];\n interrupts?: LangGraphInterruptState[];\n }>;\n adapters?:\n | {\n attachments?: AttachmentAdapter;\n speech?: SpeechSynthesisAdapter;\n feedback?: FeedbackAdapter;\n }\n | undefined;\n}) => {\n const {\n interrupt,\n setInterrupt,\n messages,\n sendMessage,\n cancel,\n setMessages,\n } = useLangGraphMessages({\n appendMessage: appendLangChainChunk,\n stream,\n });\n\n const [isRunning, setIsRunning] = useState(false);\n const handleSendMessage = async (\n messages: LangChainMessage[],\n config: LangGraphSendMessageConfig,\n ) => {\n try {\n setIsRunning(true);\n await sendMessage(messages, config);\n } catch (error) {\n console.error(\"Error streaming messages:\", error);\n } finally {\n setIsRunning(false);\n }\n };\n\n const threadMessages = useExternalMessageConverter({\n callback: convertLangChainMessages,\n messages,\n isRunning,\n });\n\n const switchToThread = !onSwitchToThread\n ? undefined\n : async (externalId: string) => {\n const { messages, interrupts } = await onSwitchToThread(externalId);\n setMessages(messages);\n setInterrupt(interrupts?.[0]);\n };\n\n const threadList: NonNullable<\n ExternalStoreAdapter[\"adapters\"]\n >[\"threadList\"] = {\n threadId,\n onSwitchToNewThread: !onSwitchToNewThread\n ? undefined\n : async () => {\n await onSwitchToNewThread();\n setMessages([]);\n },\n onSwitchToThread: switchToThread,\n };\n\n const loadingRef = useRef(false);\n const threadListItemRuntime = useThreadListItemRuntime({ optional: true });\n useEffect(() => {\n if (!threadListItemRuntime || !switchToThread || loadingRef.current) return;\n\n const externalId = threadListItemRuntime.getState().externalId;\n if (externalId) {\n loadingRef.current = true;\n switchToThread(externalId).finally(() => {\n loadingRef.current = false;\n });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return useExternalStoreRuntime({\n isRunning,\n messages: threadMessages,\n adapters: {\n attachments,\n feedback,\n speech,\n threadList,\n },\n extras: {\n [symbolLangGraphRuntimeExtras]: true,\n interrupt,\n send: handleSendMessage,\n } satisfies LangGraphRuntimeExtras,\n onNew: (msg) => {\n const cancellations =\n autoCancelPendingToolCalls !== false\n ? getPendingToolCalls(messages).map(\n (t) =>\n ({\n type: \"tool\",\n name: t.name,\n tool_call_id: t.id,\n content: JSON.stringify({ cancelled: true }),\n status: \"error\",\n }) satisfies LangChainMessage & { type: \"tool\" },\n )\n : [];\n\n return handleSendMessage(\n [\n ...cancellations,\n {\n type: \"human\",\n content: getMessageContent(msg),\n },\n ],\n {\n runConfig: msg.runConfig,\n },\n );\n },\n onAddToolResult: async ({\n toolCallId,\n toolName,\n result,\n isError,\n artifact,\n }) => {\n // TODO parallel human in the loop calls\n await handleSendMessage(\n [\n {\n type: \"tool\",\n name: toolName,\n tool_call_id: toolCallId,\n content: JSON.stringify(result),\n artifact,\n status: isError ? \"error\" : \"success\",\n },\n ],\n // TODO reuse runconfig here!\n {},\n );\n },\n onCancel: unstable_allowCancellation\n ? async () => {\n cancel();\n }\n : undefined,\n });\n};\n"],"mappings":"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","names":["messages"]}
|
|
1
|
+
{"version":3,"sources":["../src/useLangGraphRuntime.ts"],"sourcesContent":["import { useEffect, useRef, useState } from \"react\";\nimport {\n LangChainMessage,\n LangChainToolCall,\n OnCustomEventCallback,\n OnErrorEventCallback,\n OnInfoEventCallback,\n OnMetadataEventCallback,\n} from \"./types\";\nimport {\n useExternalMessageConverter,\n useExternalStoreRuntime,\n useThread,\n useThreadListItemRuntime,\n} from \"@assistant-ui/react\";\nimport { convertLangChainMessages } from \"./convertLangChainMessages\";\nimport {\n LangGraphCommand,\n LangGraphInterruptState,\n LangGraphSendMessageConfig,\n LangGraphStreamCallback,\n useLangGraphMessages,\n} from \"./useLangGraphMessages\";\nimport { AttachmentAdapter } from \"@assistant-ui/react\";\nimport { AppendMessage } from \"@assistant-ui/react\";\nimport { ExternalStoreAdapter } from \"@assistant-ui/react\";\nimport { FeedbackAdapter } from \"@assistant-ui/react\";\nimport { SpeechSynthesisAdapter } from \"@assistant-ui/react\";\nimport { appendLangChainChunk } from \"./appendLangChainChunk\";\n\nconst getPendingToolCalls = (messages: LangChainMessage[]) => {\n const pendingToolCalls = new Map<string, LangChainToolCall>();\n for (const message of messages) {\n if (message.type === \"ai\") {\n for (const toolCall of message.tool_calls ?? []) {\n pendingToolCalls.set(toolCall.id, toolCall);\n }\n }\n if (message.type === \"tool\") {\n pendingToolCalls.delete(message.tool_call_id);\n }\n }\n\n return [...pendingToolCalls.values()];\n};\n\nconst getMessageContent = (msg: AppendMessage) => {\n const allContent = [\n ...msg.content,\n ...(msg.attachments?.flatMap((a) => a.content) ?? []),\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\n case \"tool-call\":\n throw new Error(\"Tool call appends are not supported.\");\n\n default:\n const _exhaustiveCheck: \"reasoning\" | \"source\" | \"file\" | \"audio\" =\n type;\n throw new Error(\n `Unsupported append content part type: ${_exhaustiveCheck}`,\n );\n }\n });\n\n if (content.length === 1 && content[0]?.type === \"text\") {\n return content[0].text ?? \"\";\n }\n\n return content;\n};\n\nconst symbolLangGraphRuntimeExtras = Symbol(\"langgraph-runtime-extras\");\ntype LangGraphRuntimeExtras = {\n [symbolLangGraphRuntimeExtras]: true;\n send: (\n messages: LangChainMessage[],\n config: LangGraphSendMessageConfig,\n ) => Promise<void>;\n interrupt: LangGraphInterruptState | undefined;\n};\n\nconst asLangGraphRuntimeExtras = (extras: unknown): LangGraphRuntimeExtras => {\n if (\n typeof extras !== \"object\" ||\n extras == null ||\n !(symbolLangGraphRuntimeExtras in extras)\n )\n throw new Error(\n \"This method can only be called when you are using useLangGraphRuntime\",\n );\n\n return extras as LangGraphRuntimeExtras;\n};\n\nexport const useLangGraphInterruptState = () => {\n const { interrupt } = useThread((t) => asLangGraphRuntimeExtras(t.extras));\n return interrupt;\n};\n\nexport const useLangGraphSend = () => {\n const { send } = useThread((t) => asLangGraphRuntimeExtras(t.extras));\n return send;\n};\n\nexport const useLangGraphSendCommand = () => {\n const send = useLangGraphSend();\n return (command: LangGraphCommand) => send([], { command });\n};\n\nexport const useLangGraphRuntime = ({\n autoCancelPendingToolCalls,\n adapters: { attachments, feedback, speech } = {},\n unstable_allowCancellation,\n stream,\n threadId,\n onSwitchToNewThread,\n onSwitchToThread,\n eventHandlers,\n}: {\n /**\n * @deprecated For thread management use `useCloudThreadListRuntime` instead. This option will be removed in a future version.\n */\n threadId?: string | undefined;\n autoCancelPendingToolCalls?: boolean | undefined;\n unstable_allowCancellation?: boolean | undefined;\n stream: LangGraphStreamCallback<LangChainMessage>;\n /**\n * @deprecated For thread management use `useCloudThreadListRuntime` instead. This option will be removed in a future version.\n */\n onSwitchToNewThread?: () => Promise<void> | void;\n onSwitchToThread?: (threadId: string) => Promise<{\n messages: LangChainMessage[];\n interrupts?: LangGraphInterruptState[];\n }>;\n adapters?:\n | {\n attachments?: AttachmentAdapter;\n speech?: SpeechSynthesisAdapter;\n feedback?: FeedbackAdapter;\n }\n | undefined;\n /**\n * Event handlers for various LangGraph stream events\n */\n eventHandlers?:\n | {\n /**\n * Called when metadata is received from the LangGraph stream\n */\n onMetadata?: OnMetadataEventCallback;\n /**\n * Called when informational messages are received from the LangGraph stream\n */\n onInfo?: OnInfoEventCallback;\n /**\n * Called when errors occur during LangGraph stream processing\n */\n onError?: OnErrorEventCallback;\n /**\n * Called when custom events are received from the LangGraph stream\n */\n onCustomEvent?: OnCustomEventCallback;\n }\n | undefined;\n}) => {\n const {\n interrupt,\n setInterrupt,\n messages,\n sendMessage,\n cancel,\n setMessages,\n } = useLangGraphMessages({\n appendMessage: appendLangChainChunk,\n stream,\n ...(eventHandlers && { eventHandlers }),\n });\n\n const [isRunning, setIsRunning] = useState(false);\n const handleSendMessage = async (\n messages: LangChainMessage[],\n config: LangGraphSendMessageConfig,\n ) => {\n try {\n setIsRunning(true);\n await sendMessage(messages, config);\n } catch (error) {\n console.error(\"Error streaming messages:\", error);\n } finally {\n setIsRunning(false);\n }\n };\n\n const threadMessages = useExternalMessageConverter({\n callback: convertLangChainMessages,\n messages,\n isRunning,\n });\n\n const switchToThread = !onSwitchToThread\n ? undefined\n : async (externalId: string) => {\n const { messages, interrupts } = await onSwitchToThread(externalId);\n setMessages(messages);\n setInterrupt(interrupts?.[0]);\n };\n\n const threadList: NonNullable<\n ExternalStoreAdapter[\"adapters\"]\n >[\"threadList\"] = {\n threadId,\n onSwitchToNewThread: !onSwitchToNewThread\n ? undefined\n : async () => {\n await onSwitchToNewThread();\n setMessages([]);\n },\n onSwitchToThread: switchToThread,\n };\n\n const loadingRef = useRef(false);\n const threadListItemRuntime = useThreadListItemRuntime({ optional: true });\n useEffect(() => {\n if (!threadListItemRuntime || !switchToThread || loadingRef.current) return;\n\n const externalId = threadListItemRuntime.getState().externalId;\n if (externalId) {\n loadingRef.current = true;\n switchToThread(externalId).finally(() => {\n loadingRef.current = false;\n });\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return useExternalStoreRuntime({\n isRunning,\n messages: threadMessages,\n adapters: {\n attachments,\n feedback,\n speech,\n threadList,\n },\n extras: {\n [symbolLangGraphRuntimeExtras]: true,\n interrupt,\n send: handleSendMessage,\n } satisfies LangGraphRuntimeExtras,\n onNew: (msg) => {\n const cancellations =\n autoCancelPendingToolCalls !== false\n ? getPendingToolCalls(messages).map(\n (t) =>\n ({\n type: \"tool\",\n name: t.name,\n tool_call_id: t.id,\n content: JSON.stringify({ cancelled: true }),\n status: \"error\",\n }) satisfies LangChainMessage & { type: \"tool\" },\n )\n : [];\n\n return handleSendMessage(\n [\n ...cancellations,\n {\n type: \"human\",\n content: getMessageContent(msg),\n },\n ],\n {\n runConfig: msg.runConfig,\n },\n );\n },\n onAddToolResult: async ({\n toolCallId,\n toolName,\n result,\n isError,\n artifact,\n }) => {\n // TODO parallel human in the loop calls\n await handleSendMessage(\n [\n {\n type: \"tool\",\n name: toolName,\n tool_call_id: toolCallId,\n content: JSON.stringify(result),\n artifact,\n status: isError ? \"error\" : \"success\",\n },\n ],\n // TODO reuse runconfig here!\n {},\n );\n },\n onCancel: unstable_allowCancellation\n ? async () => {\n cancel();\n }\n : undefined,\n });\n};\n"],"mappings":"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","names":["messages"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@assistant-ui/react-langgraph",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.7",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -20,10 +20,10 @@
|
|
|
20
20
|
"dependencies": {
|
|
21
21
|
"assistant-stream": "^0.2.14",
|
|
22
22
|
"uuid": "^11.1.0",
|
|
23
|
-
"zod": "^3.25.
|
|
23
|
+
"zod": "^3.25.49"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
|
-
"@assistant-ui/react": "^0.10.
|
|
26
|
+
"@assistant-ui/react": "^0.10.21",
|
|
27
27
|
"@types/react": "*",
|
|
28
28
|
"react": "^18 || ^19 || ^19.0.0-rc"
|
|
29
29
|
},
|
|
@@ -35,16 +35,16 @@
|
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@testing-library/dom": "^10.4.0",
|
|
37
37
|
"@testing-library/react": "^16.3.0",
|
|
38
|
-
"@types/node": "^22.15.
|
|
39
|
-
"@types/react": "^19.1.
|
|
38
|
+
"@types/node": "^22.15.29",
|
|
39
|
+
"@types/react": "^19.1.6",
|
|
40
40
|
"@types/uuid": "^10.0.0",
|
|
41
41
|
"eslint": "^9",
|
|
42
|
-
"eslint-config-next": "15.3.
|
|
42
|
+
"eslint-config-next": "15.3.3",
|
|
43
43
|
"jsdom": "^26.1.0",
|
|
44
44
|
"react": "^19.1.0",
|
|
45
45
|
"tsx": "^4.19.4",
|
|
46
|
-
"vitest": "^3.
|
|
47
|
-
"@assistant-ui/react": "0.10.
|
|
46
|
+
"vitest": "^3.2.0",
|
|
47
|
+
"@assistant-ui/react": "0.10.21",
|
|
48
48
|
"@assistant-ui/x-buildutils": "0.0.1"
|
|
49
49
|
},
|
|
50
50
|
"publishConfig": {
|
|
@@ -14,6 +14,8 @@ const contentToParts = (content: LangChainMessage["content"]) => {
|
|
|
14
14
|
switch (type) {
|
|
15
15
|
case "text":
|
|
16
16
|
return { type: "text", text: part.text };
|
|
17
|
+
case "text_delta":
|
|
18
|
+
return { type: "text", text: part.text };
|
|
17
19
|
case "image_url":
|
|
18
20
|
if (typeof part.image_url === "string") {
|
|
19
21
|
return { type: "image", image: part.image_url };
|
|
@@ -26,6 +28,8 @@ const contentToParts = (content: LangChainMessage["content"]) => {
|
|
|
26
28
|
|
|
27
29
|
case "tool_use":
|
|
28
30
|
return null;
|
|
31
|
+
case "input_json_delta":
|
|
32
|
+
return null;
|
|
29
33
|
default:
|
|
30
34
|
const _exhaustiveCheck: never = type;
|
|
31
35
|
throw new Error(`Unknown content part type: ${_exhaustiveCheck}`);
|
package/src/testUtils.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { LangChainMessage } from "./types";
|
|
2
|
+
import { LangGraphMessagesEvent } from "./useLangGraphMessages";
|
|
3
|
+
|
|
4
|
+
export const mockStreamCallbackFactory = (
|
|
5
|
+
events: Array<LangGraphMessagesEvent<LangChainMessage>>,
|
|
6
|
+
) =>
|
|
7
|
+
async function* () {
|
|
8
|
+
for (const event of events) {
|
|
9
|
+
yield event;
|
|
10
|
+
}
|
|
11
|
+
};
|
package/src/types.ts
CHANGED
|
@@ -15,7 +15,7 @@ export type LangChainToolCall = {
|
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
export type MessageContentText = {
|
|
18
|
-
type: "text";
|
|
18
|
+
type: "text" | "text_delta";
|
|
19
19
|
text: string;
|
|
20
20
|
};
|
|
21
21
|
|
|
@@ -25,7 +25,7 @@ export type MessageContentImageUrl = {
|
|
|
25
25
|
};
|
|
26
26
|
|
|
27
27
|
type MessageContentToolUse = {
|
|
28
|
-
type: "tool_use";
|
|
28
|
+
type: "tool_use" | "input_json_delta";
|
|
29
29
|
};
|
|
30
30
|
|
|
31
31
|
export enum LangGraphKnownEventTypes {
|
|
@@ -34,7 +34,10 @@ export enum LangGraphKnownEventTypes {
|
|
|
34
34
|
MessagesComplete = "messages/complete",
|
|
35
35
|
Metadata = "metadata",
|
|
36
36
|
Updates = "updates",
|
|
37
|
+
Info = "info",
|
|
38
|
+
Error = "error",
|
|
37
39
|
}
|
|
40
|
+
|
|
38
41
|
type CustomEventType = string;
|
|
39
42
|
|
|
40
43
|
export type EventType = LangGraphKnownEventTypes | CustomEventType;
|
|
@@ -96,3 +99,13 @@ export type LangChainMessageTupleEvent = {
|
|
|
96
99
|
event: LangGraphKnownEventTypes.Messages;
|
|
97
100
|
data: [LangChainMessageChunk, LangGraphTupleMetadata];
|
|
98
101
|
};
|
|
102
|
+
|
|
103
|
+
export type OnMetadataEventCallback = (
|
|
104
|
+
metadata: unknown,
|
|
105
|
+
) => void | Promise<void>;
|
|
106
|
+
export type OnInfoEventCallback = (info: unknown) => void | Promise<void>;
|
|
107
|
+
export type OnErrorEventCallback = (error: unknown) => void | Promise<void>;
|
|
108
|
+
export type OnCustomEventCallback = (
|
|
109
|
+
type: string,
|
|
110
|
+
data: unknown,
|
|
111
|
+
) => void | Promise<void>;
|
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
import { describe, it, expect } from "vitest";
|
|
2
2
|
import { act, renderHook, waitFor } from "@testing-library/react";
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
LangGraphMessagesEvent,
|
|
6
|
-
useLangGraphMessages,
|
|
7
|
-
} from "./useLangGraphMessages";
|
|
4
|
+
import { useLangGraphMessages } from "./useLangGraphMessages";
|
|
8
5
|
import { appendLangChainChunk } from "./appendLangChainChunk";
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
MessageContentImageUrl,
|
|
12
|
-
MessageContentText,
|
|
13
|
-
} from "./types";
|
|
6
|
+
import { MessageContentImageUrl, MessageContentText } from "./types";
|
|
7
|
+
import { mockStreamCallbackFactory } from "./testUtils";
|
|
14
8
|
|
|
15
9
|
const metadataEvent = {
|
|
16
10
|
event: "metadata",
|
|
@@ -20,15 +14,6 @@ const metadataEvent = {
|
|
|
20
14
|
},
|
|
21
15
|
};
|
|
22
16
|
|
|
23
|
-
const mockStreamCallbackFactory = (
|
|
24
|
-
events: Array<LangGraphMessagesEvent<LangChainMessage>>,
|
|
25
|
-
) =>
|
|
26
|
-
async function* () {
|
|
27
|
-
for (const event of events) {
|
|
28
|
-
yield event;
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
|
|
32
17
|
describe("useLangGraphMessages", {}, () => {
|
|
33
18
|
it("processes chunks correctly", async () => {
|
|
34
19
|
const mockStreamCallback = mockStreamCallbackFactory([
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { useState, useCallback, useRef } from "react";
|
|
1
|
+
import { useState, useCallback, useRef, useMemo } from "react";
|
|
2
2
|
import { v4 as uuidv4 } from "uuid";
|
|
3
3
|
import { LangGraphMessageAccumulator } from "./LangGraphMessageAccumulator";
|
|
4
4
|
import {
|
|
@@ -6,6 +6,10 @@ import {
|
|
|
6
6
|
LangChainMessageTupleEvent,
|
|
7
7
|
LangGraphKnownEventTypes,
|
|
8
8
|
LangChainMessageChunk,
|
|
9
|
+
OnCustomEventCallback,
|
|
10
|
+
OnErrorEventCallback,
|
|
11
|
+
OnInfoEventCallback,
|
|
12
|
+
OnMetadataEventCallback,
|
|
9
13
|
} from "./types";
|
|
10
14
|
|
|
11
15
|
export type LangGraphCommand = {
|
|
@@ -60,9 +64,16 @@ const isLangChainMessageChunk = (
|
|
|
60
64
|
export const useLangGraphMessages = <TMessage extends { id?: string }>({
|
|
61
65
|
stream,
|
|
62
66
|
appendMessage = DEFAULT_APPEND_MESSAGE,
|
|
67
|
+
eventHandlers,
|
|
63
68
|
}: {
|
|
64
69
|
stream: LangGraphStreamCallback<TMessage>;
|
|
65
70
|
appendMessage?: (prev: TMessage | undefined, curr: TMessage) => TMessage;
|
|
71
|
+
eventHandlers?: {
|
|
72
|
+
onMetadata?: OnMetadataEventCallback;
|
|
73
|
+
onInfo?: OnInfoEventCallback;
|
|
74
|
+
onError?: OnErrorEventCallback;
|
|
75
|
+
onCustomEvent?: OnCustomEventCallback;
|
|
76
|
+
};
|
|
66
77
|
}) => {
|
|
67
78
|
const [interrupt, setInterrupt] = useState<
|
|
68
79
|
LangGraphInterruptState | undefined
|
|
@@ -70,6 +81,11 @@ export const useLangGraphMessages = <TMessage extends { id?: string }>({
|
|
|
70
81
|
const [messages, setMessages] = useState<TMessage[]>([]);
|
|
71
82
|
const abortControllerRef = useRef<AbortController | null>(null);
|
|
72
83
|
|
|
84
|
+
const { onMetadata, onInfo, onError, onCustomEvent } = useMemo(
|
|
85
|
+
() => eventHandlers ?? {},
|
|
86
|
+
[eventHandlers],
|
|
87
|
+
);
|
|
88
|
+
|
|
73
89
|
const sendMessage = useCallback(
|
|
74
90
|
async (newMessages: TMessage[], config: LangGraphSendMessageConfig) => {
|
|
75
91
|
// ensure all messages have an ID
|
|
@@ -115,14 +131,37 @@ export const useLangGraphMessages = <TMessage extends { id?: string }>({
|
|
|
115
131
|
break;
|
|
116
132
|
}
|
|
117
133
|
case LangGraphKnownEventTypes.Metadata:
|
|
118
|
-
|
|
134
|
+
onMetadata?.(chunk.data);
|
|
135
|
+
break;
|
|
136
|
+
case LangGraphKnownEventTypes.Info:
|
|
137
|
+
onInfo?.(chunk.data);
|
|
138
|
+
break;
|
|
139
|
+
case LangGraphKnownEventTypes.Error:
|
|
140
|
+
onError?.(chunk.data);
|
|
119
141
|
break;
|
|
120
142
|
default:
|
|
121
|
-
|
|
143
|
+
if (onCustomEvent) {
|
|
144
|
+
onCustomEvent(chunk.event, chunk.data);
|
|
145
|
+
} else {
|
|
146
|
+
console.warn(
|
|
147
|
+
"Unhandled event received:",
|
|
148
|
+
chunk.event,
|
|
149
|
+
chunk.data,
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
break;
|
|
122
153
|
}
|
|
123
154
|
}
|
|
124
155
|
},
|
|
125
|
-
[
|
|
156
|
+
[
|
|
157
|
+
messages,
|
|
158
|
+
appendMessage,
|
|
159
|
+
stream,
|
|
160
|
+
onMetadata,
|
|
161
|
+
onInfo,
|
|
162
|
+
onError,
|
|
163
|
+
onCustomEvent,
|
|
164
|
+
],
|
|
126
165
|
);
|
|
127
166
|
|
|
128
167
|
const cancel = useCallback(() => {
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { describe, it, expect, vi } from "vitest";
|
|
2
|
+
import { act, renderHook, waitFor } from "@testing-library/react";
|
|
3
|
+
import {
|
|
4
|
+
AssistantRuntime,
|
|
5
|
+
AssistantRuntimeProvider,
|
|
6
|
+
} from "@assistant-ui/react";
|
|
7
|
+
import { useLangGraphRuntime, useLangGraphSend } from "./useLangGraphRuntime";
|
|
8
|
+
import { mockStreamCallbackFactory } from "./testUtils";
|
|
9
|
+
import React, { ReactNode } from "react";
|
|
10
|
+
|
|
11
|
+
const metadataEvent = {
|
|
12
|
+
event: "metadata",
|
|
13
|
+
data: {
|
|
14
|
+
thread_id: "123",
|
|
15
|
+
run_attempt: 1,
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const infoEvent = {
|
|
20
|
+
event: "info",
|
|
21
|
+
data: {
|
|
22
|
+
message: "Processing request",
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const errorEvent = {
|
|
27
|
+
event: "error",
|
|
28
|
+
data: {
|
|
29
|
+
message: "Something went wrong",
|
|
30
|
+
},
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const customEvent = {
|
|
34
|
+
event: "custom",
|
|
35
|
+
data: {
|
|
36
|
+
type: "test",
|
|
37
|
+
value: "custom data",
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
describe("useLangGraphRuntime", () => {
|
|
42
|
+
const wrapperFactory =
|
|
43
|
+
(runtime: AssistantRuntime) =>
|
|
44
|
+
// eslint-disable-next-line react/display-name
|
|
45
|
+
({ children }: { children: ReactNode }) => (
|
|
46
|
+
<AssistantRuntimeProvider runtime={runtime}>
|
|
47
|
+
{children}
|
|
48
|
+
</AssistantRuntimeProvider>
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
it("should handle metadata events", async () => {
|
|
52
|
+
const onMetadata = vi.fn();
|
|
53
|
+
|
|
54
|
+
const streamMock = vi
|
|
55
|
+
.fn()
|
|
56
|
+
.mockImplementation(() => mockStreamCallbackFactory([metadataEvent])());
|
|
57
|
+
|
|
58
|
+
const { result: runtimeResult } = renderHook(
|
|
59
|
+
() =>
|
|
60
|
+
useLangGraphRuntime({
|
|
61
|
+
stream: streamMock,
|
|
62
|
+
eventHandlers: {
|
|
63
|
+
onMetadata,
|
|
64
|
+
},
|
|
65
|
+
}),
|
|
66
|
+
{},
|
|
67
|
+
);
|
|
68
|
+
|
|
69
|
+
const wrapper = wrapperFactory(runtimeResult.current);
|
|
70
|
+
|
|
71
|
+
const { result: sendResult } = renderHook(() => useLangGraphSend(), {
|
|
72
|
+
wrapper,
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
act(() => {
|
|
76
|
+
sendResult.current(
|
|
77
|
+
[
|
|
78
|
+
{
|
|
79
|
+
type: "human",
|
|
80
|
+
content: "Hello, world!",
|
|
81
|
+
},
|
|
82
|
+
],
|
|
83
|
+
{},
|
|
84
|
+
);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
await waitFor(() => {
|
|
88
|
+
expect(streamMock).toHaveBeenCalled();
|
|
89
|
+
expect(onMetadata).toHaveBeenCalledWith(metadataEvent.data);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("should handle info events", async () => {
|
|
94
|
+
const onInfo = vi.fn();
|
|
95
|
+
|
|
96
|
+
const streamMock = vi
|
|
97
|
+
.fn()
|
|
98
|
+
.mockImplementation(() => mockStreamCallbackFactory([infoEvent])());
|
|
99
|
+
|
|
100
|
+
const { result: runtimeResult } = renderHook(
|
|
101
|
+
() =>
|
|
102
|
+
useLangGraphRuntime({
|
|
103
|
+
stream: streamMock,
|
|
104
|
+
eventHandlers: {
|
|
105
|
+
onInfo,
|
|
106
|
+
},
|
|
107
|
+
}),
|
|
108
|
+
{},
|
|
109
|
+
);
|
|
110
|
+
|
|
111
|
+
const wrapper = ({ children }: { children: ReactNode }) => (
|
|
112
|
+
<AssistantRuntimeProvider runtime={runtimeResult.current}>
|
|
113
|
+
{children}
|
|
114
|
+
</AssistantRuntimeProvider>
|
|
115
|
+
);
|
|
116
|
+
|
|
117
|
+
const { result: sendResult } = renderHook(() => useLangGraphSend(), {
|
|
118
|
+
wrapper,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
act(() => {
|
|
122
|
+
sendResult.current(
|
|
123
|
+
[
|
|
124
|
+
{
|
|
125
|
+
type: "human",
|
|
126
|
+
content: "Hello, world!",
|
|
127
|
+
},
|
|
128
|
+
],
|
|
129
|
+
{},
|
|
130
|
+
);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
await waitFor(() => {
|
|
134
|
+
expect(streamMock).toHaveBeenCalled();
|
|
135
|
+
expect(onInfo).toHaveBeenCalledWith(infoEvent.data);
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
it("should handle error events", async () => {
|
|
140
|
+
const onError = vi.fn();
|
|
141
|
+
|
|
142
|
+
const streamMock = vi
|
|
143
|
+
.fn()
|
|
144
|
+
.mockImplementation(() => mockStreamCallbackFactory([errorEvent])());
|
|
145
|
+
|
|
146
|
+
const { result: runtimeResult } = renderHook(
|
|
147
|
+
() =>
|
|
148
|
+
useLangGraphRuntime({
|
|
149
|
+
stream: streamMock,
|
|
150
|
+
eventHandlers: {
|
|
151
|
+
onError,
|
|
152
|
+
},
|
|
153
|
+
}),
|
|
154
|
+
{},
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
const wrapper = ({ children }: { children: ReactNode }) => (
|
|
158
|
+
<AssistantRuntimeProvider runtime={runtimeResult.current}>
|
|
159
|
+
{children}
|
|
160
|
+
</AssistantRuntimeProvider>
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
const { result: sendResult } = renderHook(() => useLangGraphSend(), {
|
|
164
|
+
wrapper,
|
|
165
|
+
});
|
|
166
|
+
|
|
167
|
+
act(() => {
|
|
168
|
+
sendResult.current(
|
|
169
|
+
[
|
|
170
|
+
{
|
|
171
|
+
type: "human",
|
|
172
|
+
content: "Hello, world!",
|
|
173
|
+
},
|
|
174
|
+
],
|
|
175
|
+
{},
|
|
176
|
+
);
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
await waitFor(() => {
|
|
180
|
+
expect(streamMock).toHaveBeenCalled();
|
|
181
|
+
expect(onError).toHaveBeenCalledWith(errorEvent.data);
|
|
182
|
+
});
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
it("should handle custom events", async () => {
|
|
186
|
+
const onCustomEvent = vi.fn();
|
|
187
|
+
|
|
188
|
+
const streamMock = vi
|
|
189
|
+
.fn()
|
|
190
|
+
.mockImplementation(() => mockStreamCallbackFactory([customEvent])());
|
|
191
|
+
|
|
192
|
+
const { result: runtimeResult } = renderHook(
|
|
193
|
+
() =>
|
|
194
|
+
useLangGraphRuntime({
|
|
195
|
+
stream: streamMock,
|
|
196
|
+
eventHandlers: {
|
|
197
|
+
onCustomEvent,
|
|
198
|
+
},
|
|
199
|
+
}),
|
|
200
|
+
{},
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
const wrapper = wrapperFactory(runtimeResult.current);
|
|
204
|
+
|
|
205
|
+
const { result: sendResult } = renderHook(() => useLangGraphSend(), {
|
|
206
|
+
wrapper,
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
act(() => {
|
|
210
|
+
sendResult.current(
|
|
211
|
+
[
|
|
212
|
+
{
|
|
213
|
+
type: "human",
|
|
214
|
+
content: "Hello, world!",
|
|
215
|
+
},
|
|
216
|
+
],
|
|
217
|
+
{},
|
|
218
|
+
);
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
await waitFor(() => {
|
|
222
|
+
expect(streamMock).toHaveBeenCalled();
|
|
223
|
+
expect(onCustomEvent).toHaveBeenCalledWith(
|
|
224
|
+
customEvent.event,
|
|
225
|
+
customEvent.data,
|
|
226
|
+
);
|
|
227
|
+
});
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it("should work without any provided callbacks", async () => {
|
|
231
|
+
const streamMock = vi
|
|
232
|
+
.fn()
|
|
233
|
+
.mockImplementation(() =>
|
|
234
|
+
mockStreamCallbackFactory([
|
|
235
|
+
metadataEvent,
|
|
236
|
+
infoEvent,
|
|
237
|
+
errorEvent,
|
|
238
|
+
customEvent,
|
|
239
|
+
])(),
|
|
240
|
+
);
|
|
241
|
+
|
|
242
|
+
const { result: runtimeResult } = renderHook(
|
|
243
|
+
() =>
|
|
244
|
+
useLangGraphRuntime({
|
|
245
|
+
stream: streamMock,
|
|
246
|
+
eventHandlers: {},
|
|
247
|
+
}),
|
|
248
|
+
{},
|
|
249
|
+
);
|
|
250
|
+
|
|
251
|
+
const wrapper = wrapperFactory(runtimeResult.current);
|
|
252
|
+
|
|
253
|
+
const { result: sendResult } = renderHook(() => useLangGraphSend(), {
|
|
254
|
+
wrapper,
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
act(() => {
|
|
258
|
+
sendResult.current(
|
|
259
|
+
[
|
|
260
|
+
{
|
|
261
|
+
type: "human",
|
|
262
|
+
content: "Hello, world!",
|
|
263
|
+
},
|
|
264
|
+
],
|
|
265
|
+
{},
|
|
266
|
+
);
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
await waitFor(() => {
|
|
270
|
+
expect(streamMock).toHaveBeenCalled();
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
// Should not throw any errors even when events are processed without handlers
|
|
274
|
+
expect(runtimeResult.current).toBeDefined();
|
|
275
|
+
});
|
|
276
|
+
});
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import { useEffect, useRef, useState } from "react";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
LangChainMessage,
|
|
4
|
+
LangChainToolCall,
|
|
5
|
+
OnCustomEventCallback,
|
|
6
|
+
OnErrorEventCallback,
|
|
7
|
+
OnInfoEventCallback,
|
|
8
|
+
OnMetadataEventCallback,
|
|
9
|
+
} from "./types";
|
|
3
10
|
import {
|
|
4
11
|
useExternalMessageConverter,
|
|
5
12
|
useExternalStoreRuntime,
|
|
@@ -115,6 +122,7 @@ export const useLangGraphRuntime = ({
|
|
|
115
122
|
threadId,
|
|
116
123
|
onSwitchToNewThread,
|
|
117
124
|
onSwitchToThread,
|
|
125
|
+
eventHandlers,
|
|
118
126
|
}: {
|
|
119
127
|
/**
|
|
120
128
|
* @deprecated For thread management use `useCloudThreadListRuntime` instead. This option will be removed in a future version.
|
|
@@ -138,6 +146,29 @@ export const useLangGraphRuntime = ({
|
|
|
138
146
|
feedback?: FeedbackAdapter;
|
|
139
147
|
}
|
|
140
148
|
| undefined;
|
|
149
|
+
/**
|
|
150
|
+
* Event handlers for various LangGraph stream events
|
|
151
|
+
*/
|
|
152
|
+
eventHandlers?:
|
|
153
|
+
| {
|
|
154
|
+
/**
|
|
155
|
+
* Called when metadata is received from the LangGraph stream
|
|
156
|
+
*/
|
|
157
|
+
onMetadata?: OnMetadataEventCallback;
|
|
158
|
+
/**
|
|
159
|
+
* Called when informational messages are received from the LangGraph stream
|
|
160
|
+
*/
|
|
161
|
+
onInfo?: OnInfoEventCallback;
|
|
162
|
+
/**
|
|
163
|
+
* Called when errors occur during LangGraph stream processing
|
|
164
|
+
*/
|
|
165
|
+
onError?: OnErrorEventCallback;
|
|
166
|
+
/**
|
|
167
|
+
* Called when custom events are received from the LangGraph stream
|
|
168
|
+
*/
|
|
169
|
+
onCustomEvent?: OnCustomEventCallback;
|
|
170
|
+
}
|
|
171
|
+
| undefined;
|
|
141
172
|
}) => {
|
|
142
173
|
const {
|
|
143
174
|
interrupt,
|
|
@@ -149,6 +180,7 @@ export const useLangGraphRuntime = ({
|
|
|
149
180
|
} = useLangGraphMessages({
|
|
150
181
|
appendMessage: appendLangChainChunk,
|
|
151
182
|
stream,
|
|
183
|
+
...(eventHandlers && { eventHandlers }),
|
|
152
184
|
});
|
|
153
185
|
|
|
154
186
|
const [isRunning, setIsRunning] = useState(false);
|