@assistant-ui/react-langgraph 0.4.4 → 0.5.0
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/LangGraphMessageAccumulator.js +36 -0
- package/dist/LangGraphMessageAccumulator.js.map +1 -0
- package/dist/appendLangChainChunk.js +44 -0
- package/dist/appendLangChainChunk.js.map +1 -0
- package/dist/convertLangChainMessages.js +71 -0
- package/dist/convertLangChainMessages.js.map +1 -0
- package/dist/index.js +16 -415
- package/dist/index.js.map +1 -1
- package/dist/types.js +1 -0
- package/dist/types.js.map +1 -0
- package/dist/useLangGraphMessages.js +53 -0
- package/dist/useLangGraphMessages.js.map +1 -0
- package/dist/useLangGraphRuntime.js +195 -0
- package/dist/useLangGraphRuntime.js.map +1 -0
- package/package.json +15 -16
- package/dist/index.d.mts +0 -150
- package/dist/index.d.ts +0 -150
- package/dist/index.mjs +0 -394
- package/dist/index.mjs.map +0 -1
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { v4 as uuidv4 } from "uuid";
|
|
2
|
+
class LangGraphMessageAccumulator {
|
|
3
|
+
messagesMap = /* @__PURE__ */ new Map();
|
|
4
|
+
appendMessage;
|
|
5
|
+
constructor({
|
|
6
|
+
initialMessages = [],
|
|
7
|
+
appendMessage = (_, curr) => curr
|
|
8
|
+
} = {}) {
|
|
9
|
+
this.appendMessage = appendMessage;
|
|
10
|
+
this.addMessages(initialMessages);
|
|
11
|
+
}
|
|
12
|
+
ensureMessageId(message) {
|
|
13
|
+
return message.id ? message : { ...message, id: uuidv4() };
|
|
14
|
+
}
|
|
15
|
+
addMessages(newMessages) {
|
|
16
|
+
if (newMessages.length === 0) return this.getMessages();
|
|
17
|
+
for (const message of newMessages.map(this.ensureMessageId)) {
|
|
18
|
+
const previous = message.id ? this.messagesMap.get(message.id) : void 0;
|
|
19
|
+
this.messagesMap.set(
|
|
20
|
+
message.id ?? uuidv4(),
|
|
21
|
+
this.appendMessage(previous, message)
|
|
22
|
+
);
|
|
23
|
+
}
|
|
24
|
+
return this.getMessages();
|
|
25
|
+
}
|
|
26
|
+
getMessages() {
|
|
27
|
+
return [...this.messagesMap.values()];
|
|
28
|
+
}
|
|
29
|
+
clear() {
|
|
30
|
+
this.messagesMap.clear();
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
LangGraphMessageAccumulator
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=LangGraphMessageAccumulator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/LangGraphMessageAccumulator.ts"],"sourcesContent":["import { v4 as uuidv4 } from \"uuid\";\n\nexport type LangGraphMessagesEvent<TMessage> = {\n event:\n | \"messages\"\n | \"messages/partial\"\n | \"messages/complete\"\n | \"metadata\"\n | \"updates\"\n | string;\n data: TMessage[] | any;\n};\n\nexport type LangGraphStateAccumulatorConfig<TMessage> = {\n initialMessages?: TMessage[];\n appendMessage?: (prev: TMessage | undefined, curr: TMessage) => TMessage;\n};\n\nexport class LangGraphMessageAccumulator<TMessage extends { id?: string }> {\n private messagesMap = new Map<string, TMessage>();\n private appendMessage: (\n prev: TMessage | undefined,\n curr: TMessage,\n ) => TMessage;\n\n constructor({\n initialMessages = [],\n appendMessage = ((_: TMessage | undefined, curr: TMessage) => curr) as (\n prev: TMessage | undefined,\n curr: TMessage,\n ) => TMessage,\n }: LangGraphStateAccumulatorConfig<TMessage> = {}) {\n this.appendMessage = appendMessage;\n this.addMessages(initialMessages);\n }\n\n private ensureMessageId(message: TMessage): TMessage {\n return message.id ? message : { ...message, id: uuidv4() };\n }\n\n public addMessages(newMessages: TMessage[]) {\n if (newMessages.length === 0) return this.getMessages();\n\n for (const message of newMessages.map(this.ensureMessageId)) {\n const previous = message.id\n ? this.messagesMap.get(message.id)\n : undefined;\n this.messagesMap.set(\n message.id ?? uuidv4(),\n this.appendMessage(previous, message),\n );\n }\n return this.getMessages();\n }\n\n public getMessages(): TMessage[] {\n return [...this.messagesMap.values()];\n }\n\n public clear() {\n this.messagesMap.clear();\n }\n}\n"],"mappings":"AAAA,SAAS,MAAM,cAAc;AAkBtB,MAAM,4BAA8D;AAAA,EACjE,cAAc,oBAAI,IAAsB;AAAA,EACxC;AAAA,EAKR,YAAY;AAAA,IACV,kBAAkB,CAAC;AAAA,IACnB,gBAAiB,CAAC,GAAyB,SAAmB;AAAA,EAIhE,IAA+C,CAAC,GAAG;AACjD,SAAK,gBAAgB;AACrB,SAAK,YAAY,eAAe;AAAA,EAClC;AAAA,EAEQ,gBAAgB,SAA6B;AACnD,WAAO,QAAQ,KAAK,UAAU,EAAE,GAAG,SAAS,IAAI,OAAO,EAAE;AAAA,EAC3D;AAAA,EAEO,YAAY,aAAyB;AAC1C,QAAI,YAAY,WAAW,EAAG,QAAO,KAAK,YAAY;AAEtD,eAAW,WAAW,YAAY,IAAI,KAAK,eAAe,GAAG;AAC3D,YAAM,WAAW,QAAQ,KACrB,KAAK,YAAY,IAAI,QAAQ,EAAE,IAC/B;AACJ,WAAK,YAAY;AAAA,QACf,QAAQ,MAAM,OAAO;AAAA,QACrB,KAAK,cAAc,UAAU,OAAO;AAAA,MACtC;AAAA,IACF;AACA,WAAO,KAAK,YAAY;AAAA,EAC1B;AAAA,EAEO,cAA0B;AAC/B,WAAO,CAAC,GAAG,KAAK,YAAY,OAAO,CAAC;AAAA,EACtC;AAAA,EAEO,QAAQ;AACb,SAAK,YAAY,MAAM;AAAA,EACzB;AACF;","names":[]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { parsePartialJsonObject } from "assistant-stream/utils";
|
|
2
|
+
const appendLangChainChunk = (prev, curr) => {
|
|
3
|
+
if (curr.type !== "AIMessageChunk") {
|
|
4
|
+
return curr;
|
|
5
|
+
}
|
|
6
|
+
if (!prev || prev.type !== "ai") {
|
|
7
|
+
return {
|
|
8
|
+
...curr,
|
|
9
|
+
type: curr.type.replace("MessageChunk", "").toLowerCase()
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
const newContent = typeof prev.content === "string" ? [{ type: "text", text: prev.content }] : [...prev.content];
|
|
13
|
+
for (const chunk of curr.content) {
|
|
14
|
+
if (chunk.type === "text") {
|
|
15
|
+
const existing = newContent[chunk.index] ?? { type: "text", text: "" };
|
|
16
|
+
if (existing.type !== "text") throw new Error("");
|
|
17
|
+
newContent[chunk.index] = {
|
|
18
|
+
...existing,
|
|
19
|
+
...chunk,
|
|
20
|
+
text: existing.text + chunk.text
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
const newToolCalls = [...prev.tool_calls ?? []];
|
|
25
|
+
for (const chunk of curr.tool_call_chunks) {
|
|
26
|
+
const existing = newToolCalls[chunk.index - 1] ?? { argsText: "" };
|
|
27
|
+
const newArgsText = existing.argsText + chunk.args;
|
|
28
|
+
newToolCalls[chunk.index - 1] = {
|
|
29
|
+
...chunk,
|
|
30
|
+
...existing,
|
|
31
|
+
argsText: newArgsText,
|
|
32
|
+
args: parsePartialJsonObject(newArgsText) ?? ("args" in existing ? existing.args : {})
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
...prev,
|
|
37
|
+
content: newContent,
|
|
38
|
+
tool_calls: newToolCalls
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
export {
|
|
42
|
+
appendLangChainChunk
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=appendLangChainChunk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/appendLangChainChunk.ts"],"sourcesContent":["import { LangChainMessage, LangChainMessageChunk } from \"./types\";\nimport { parsePartialJsonObject } from \"assistant-stream/utils\";\n\nexport const appendLangChainChunk = (\n prev: LangChainMessage | undefined,\n curr: LangChainMessage | LangChainMessageChunk,\n): LangChainMessage => {\n if (curr.type !== \"AIMessageChunk\") {\n return curr;\n }\n\n if (!prev || prev.type !== \"ai\") {\n return {\n ...curr,\n type: curr.type.replace(\"MessageChunk\", \"\").toLowerCase(),\n } as LangChainMessage;\n }\n\n const newContent =\n typeof prev.content === \"string\"\n ? [{ type: \"text\" as const, text: prev.content }]\n : [...prev.content];\n\n for (const chunk of curr.content) {\n if (chunk.type === \"text\") {\n const existing = newContent[chunk.index] ?? { type: \"text\", text: \"\" };\n if (existing.type !== \"text\") throw new Error(\"\");\n newContent[chunk.index] = {\n ...existing,\n ...chunk,\n text: existing.text + chunk.text,\n };\n }\n }\n\n const newToolCalls = [...(prev.tool_calls ?? [])];\n for (const chunk of curr.tool_call_chunks) {\n const existing = newToolCalls[chunk.index - 1] ?? { argsText: \"\" };\n const newArgsText = existing.argsText + chunk.args;\n newToolCalls[chunk.index - 1] = {\n ...chunk,\n ...existing,\n argsText: newArgsText,\n args:\n parsePartialJsonObject(newArgsText) ??\n (\"args\" in existing ? existing.args : {}),\n };\n }\n\n return {\n ...prev,\n content: newContent,\n tool_calls: newToolCalls,\n };\n};\n"],"mappings":"AACA,SAAS,8BAA8B;AAEhC,MAAM,uBAAuB,CAClC,MACA,SACqB;AACrB,MAAI,KAAK,SAAS,kBAAkB;AAClC,WAAO;AAAA,EACT;AAEA,MAAI,CAAC,QAAQ,KAAK,SAAS,MAAM;AAC/B,WAAO;AAAA,MACL,GAAG;AAAA,MACH,MAAM,KAAK,KAAK,QAAQ,gBAAgB,EAAE,EAAE,YAAY;AAAA,IAC1D;AAAA,EACF;AAEA,QAAM,aACJ,OAAO,KAAK,YAAY,WACpB,CAAC,EAAE,MAAM,QAAiB,MAAM,KAAK,QAAQ,CAAC,IAC9C,CAAC,GAAG,KAAK,OAAO;AAEtB,aAAW,SAAS,KAAK,SAAS;AAChC,QAAI,MAAM,SAAS,QAAQ;AACzB,YAAM,WAAW,WAAW,MAAM,KAAK,KAAK,EAAE,MAAM,QAAQ,MAAM,GAAG;AACrE,UAAI,SAAS,SAAS,OAAQ,OAAM,IAAI,MAAM,EAAE;AAChD,iBAAW,MAAM,KAAK,IAAI;AAAA,QACxB,GAAG;AAAA,QACH,GAAG;AAAA,QACH,MAAM,SAAS,OAAO,MAAM;AAAA,MAC9B;AAAA,IACF;AAAA,EACF;AAEA,QAAM,eAAe,CAAC,GAAI,KAAK,cAAc,CAAC,CAAE;AAChD,aAAW,SAAS,KAAK,kBAAkB;AACzC,UAAM,WAAW,aAAa,MAAM,QAAQ,CAAC,KAAK,EAAE,UAAU,GAAG;AACjE,UAAM,cAAc,SAAS,WAAW,MAAM;AAC9C,iBAAa,MAAM,QAAQ,CAAC,IAAI;AAAA,MAC9B,GAAG;AAAA,MACH,GAAG;AAAA,MACH,UAAU;AAAA,MACV,MACE,uBAAuB,WAAW,MACjC,UAAU,WAAW,SAAS,OAAO,CAAC;AAAA,IAC3C;AAAA,EACF;AAEA,SAAO;AAAA,IACL,GAAG;AAAA,IACH,SAAS;AAAA,IACT,YAAY;AAAA,EACd;AACF;","names":[]}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
const contentToParts = (content) => {
|
|
3
|
+
if (typeof content === "string")
|
|
4
|
+
return [{ type: "text", text: content }];
|
|
5
|
+
return content.map((part) => {
|
|
6
|
+
const type = part.type;
|
|
7
|
+
switch (type) {
|
|
8
|
+
case "text":
|
|
9
|
+
return { type: "text", text: part.text };
|
|
10
|
+
case "image_url":
|
|
11
|
+
if (typeof part.image_url === "string") {
|
|
12
|
+
return { type: "image", image: part.image_url };
|
|
13
|
+
} else {
|
|
14
|
+
return {
|
|
15
|
+
type: "image",
|
|
16
|
+
image: part.image_url.url
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
case "tool_use":
|
|
20
|
+
return null;
|
|
21
|
+
default:
|
|
22
|
+
const _exhaustiveCheck = type;
|
|
23
|
+
throw new Error(`Unknown content part type: ${_exhaustiveCheck}`);
|
|
24
|
+
}
|
|
25
|
+
}).filter((a) => a !== null);
|
|
26
|
+
};
|
|
27
|
+
const convertLangChainMessages = (message) => {
|
|
28
|
+
switch (message.type) {
|
|
29
|
+
case "system":
|
|
30
|
+
return {
|
|
31
|
+
role: "system",
|
|
32
|
+
id: message.id,
|
|
33
|
+
content: [{ type: "text", text: message.content }]
|
|
34
|
+
};
|
|
35
|
+
case "human":
|
|
36
|
+
return {
|
|
37
|
+
role: "user",
|
|
38
|
+
id: message.id,
|
|
39
|
+
content: contentToParts(message.content)
|
|
40
|
+
};
|
|
41
|
+
case "ai":
|
|
42
|
+
return {
|
|
43
|
+
role: "assistant",
|
|
44
|
+
id: message.id,
|
|
45
|
+
content: [
|
|
46
|
+
...contentToParts(message.content),
|
|
47
|
+
...message.tool_calls?.map(
|
|
48
|
+
(chunk) => ({
|
|
49
|
+
type: "tool-call",
|
|
50
|
+
toolCallId: chunk.id,
|
|
51
|
+
toolName: chunk.name,
|
|
52
|
+
args: chunk.args,
|
|
53
|
+
argsText: message.tool_call_chunks?.find((c) => c.id === chunk.id)?.args ?? JSON.stringify(chunk.args)
|
|
54
|
+
})
|
|
55
|
+
) ?? []
|
|
56
|
+
]
|
|
57
|
+
};
|
|
58
|
+
case "tool":
|
|
59
|
+
return {
|
|
60
|
+
role: "tool",
|
|
61
|
+
toolName: message.name,
|
|
62
|
+
toolCallId: message.tool_call_id,
|
|
63
|
+
result: message.content,
|
|
64
|
+
artifact: message.artifact
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
};
|
|
68
|
+
export {
|
|
69
|
+
convertLangChainMessages
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=convertLangChainMessages.js.map
|
|
@@ -0,0 +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 };\n }\n};\n"],"mappings":";AAOA,MAAM,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,MAAM,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,MACpB;AAAA,EACJ;AACF;","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -1,424 +1,25 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
return to;
|
|
17
|
-
};
|
|
18
|
-
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
-
|
|
20
|
-
// src/index.ts
|
|
21
|
-
var index_exports = {};
|
|
22
|
-
__export(index_exports, {
|
|
23
|
-
LangGraphMessageAccumulator: () => LangGraphMessageAccumulator,
|
|
24
|
-
appendLangChainChunk: () => appendLangChainChunk,
|
|
25
|
-
convertLangChainMessages: () => convertLangChainMessages,
|
|
26
|
-
convertLangchainMessages: () => convertLangChainMessages,
|
|
27
|
-
useLangGraphInterruptState: () => useLangGraphInterruptState,
|
|
28
|
-
useLangGraphMessages: () => useLangGraphMessages,
|
|
29
|
-
useLangGraphRuntime: () => useLangGraphRuntime,
|
|
30
|
-
useLangGraphSend: () => useLangGraphSend,
|
|
31
|
-
useLangGraphSendCommand: () => useLangGraphSendCommand
|
|
32
|
-
});
|
|
33
|
-
module.exports = __toCommonJS(index_exports);
|
|
34
|
-
|
|
35
|
-
// src/useLangGraphRuntime.ts
|
|
36
|
-
var import_react2 = require("react");
|
|
37
|
-
var import_react3 = require("@assistant-ui/react");
|
|
38
|
-
|
|
39
|
-
// src/convertLangChainMessages.ts
|
|
40
|
-
var contentToParts = (content) => {
|
|
41
|
-
if (typeof content === "string")
|
|
42
|
-
return [{ type: "text", text: content }];
|
|
43
|
-
return content.map((part) => {
|
|
44
|
-
const type = part.type;
|
|
45
|
-
switch (type) {
|
|
46
|
-
case "text":
|
|
47
|
-
return { type: "text", text: part.text };
|
|
48
|
-
case "image_url":
|
|
49
|
-
if (typeof part.image_url === "string") {
|
|
50
|
-
return { type: "image", image: part.image_url };
|
|
51
|
-
} else {
|
|
52
|
-
return {
|
|
53
|
-
type: "image",
|
|
54
|
-
image: part.image_url.url
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
case "tool_use":
|
|
58
|
-
return null;
|
|
59
|
-
default:
|
|
60
|
-
const _exhaustiveCheck = type;
|
|
61
|
-
throw new Error(`Unknown content part type: ${_exhaustiveCheck}`);
|
|
62
|
-
}
|
|
63
|
-
}).filter((a) => a !== null);
|
|
64
|
-
};
|
|
65
|
-
var convertLangChainMessages = (message) => {
|
|
66
|
-
switch (message.type) {
|
|
67
|
-
case "system":
|
|
68
|
-
return {
|
|
69
|
-
role: "system",
|
|
70
|
-
id: message.id,
|
|
71
|
-
content: [{ type: "text", text: message.content }]
|
|
72
|
-
};
|
|
73
|
-
case "human":
|
|
74
|
-
return {
|
|
75
|
-
role: "user",
|
|
76
|
-
id: message.id,
|
|
77
|
-
content: contentToParts(message.content)
|
|
78
|
-
};
|
|
79
|
-
case "ai":
|
|
80
|
-
return {
|
|
81
|
-
role: "assistant",
|
|
82
|
-
id: message.id,
|
|
83
|
-
content: [
|
|
84
|
-
...contentToParts(message.content),
|
|
85
|
-
...message.tool_calls?.map(
|
|
86
|
-
(chunk) => ({
|
|
87
|
-
type: "tool-call",
|
|
88
|
-
toolCallId: chunk.id,
|
|
89
|
-
toolName: chunk.name,
|
|
90
|
-
args: chunk.args,
|
|
91
|
-
argsText: message.tool_call_chunks?.find((c) => c.id === chunk.id)?.args ?? JSON.stringify(chunk.args)
|
|
92
|
-
})
|
|
93
|
-
) ?? []
|
|
94
|
-
]
|
|
95
|
-
};
|
|
96
|
-
case "tool":
|
|
97
|
-
return {
|
|
98
|
-
role: "tool",
|
|
99
|
-
toolName: message.name,
|
|
100
|
-
toolCallId: message.tool_call_id,
|
|
101
|
-
result: message.content,
|
|
102
|
-
artifact: message.artifact
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
|
|
107
|
-
// src/useLangGraphMessages.ts
|
|
108
|
-
var import_react = require("react");
|
|
109
|
-
var import_uuid2 = require("uuid");
|
|
110
|
-
|
|
111
|
-
// src/LangGraphMessageAccumulator.ts
|
|
112
|
-
var import_uuid = require("uuid");
|
|
113
|
-
var LangGraphMessageAccumulator = class {
|
|
114
|
-
messagesMap = /* @__PURE__ */ new Map();
|
|
115
|
-
appendMessage;
|
|
116
|
-
constructor({
|
|
117
|
-
initialMessages = [],
|
|
118
|
-
appendMessage = (_, curr) => curr
|
|
119
|
-
} = {}) {
|
|
120
|
-
this.appendMessage = appendMessage;
|
|
121
|
-
this.addMessages(initialMessages);
|
|
122
|
-
}
|
|
123
|
-
ensureMessageId(message) {
|
|
124
|
-
return message.id ? message : { ...message, id: (0, import_uuid.v4)() };
|
|
125
|
-
}
|
|
126
|
-
addMessages(newMessages) {
|
|
127
|
-
if (newMessages.length === 0) return this.getMessages();
|
|
128
|
-
for (const message of newMessages.map(this.ensureMessageId)) {
|
|
129
|
-
const previous = message.id ? this.messagesMap.get(message.id) : void 0;
|
|
130
|
-
this.messagesMap.set(
|
|
131
|
-
message.id ?? (0, import_uuid.v4)(),
|
|
132
|
-
this.appendMessage(previous, message)
|
|
133
|
-
);
|
|
134
|
-
}
|
|
135
|
-
return this.getMessages();
|
|
136
|
-
}
|
|
137
|
-
getMessages() {
|
|
138
|
-
return [...this.messagesMap.values()];
|
|
139
|
-
}
|
|
140
|
-
clear() {
|
|
141
|
-
this.messagesMap.clear();
|
|
142
|
-
}
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
// src/useLangGraphMessages.ts
|
|
146
|
-
var DEFAULT_APPEND_MESSAGE = (_, curr) => curr;
|
|
147
|
-
var useLangGraphMessages = ({
|
|
148
|
-
stream,
|
|
149
|
-
appendMessage = DEFAULT_APPEND_MESSAGE
|
|
150
|
-
}) => {
|
|
151
|
-
const [interrupt, setInterrupt] = (0, import_react.useState)();
|
|
152
|
-
const [messages, setMessages] = (0, import_react.useState)([]);
|
|
153
|
-
const abortControllerRef = (0, import_react.useRef)(null);
|
|
154
|
-
const sendMessage = (0, import_react.useCallback)(
|
|
155
|
-
async (newMessages, config) => {
|
|
156
|
-
newMessages = newMessages.map((m) => m.id ? m : { ...m, id: (0, import_uuid2.v4)() });
|
|
157
|
-
const accumulator = new LangGraphMessageAccumulator({
|
|
158
|
-
initialMessages: messages,
|
|
159
|
-
appendMessage
|
|
160
|
-
});
|
|
161
|
-
setMessages(accumulator.addMessages(newMessages));
|
|
162
|
-
const abortController = new AbortController();
|
|
163
|
-
abortControllerRef.current = abortController;
|
|
164
|
-
const response = await stream(newMessages, {
|
|
165
|
-
...config,
|
|
166
|
-
abortSignal: abortController.signal
|
|
167
|
-
});
|
|
168
|
-
for await (const chunk of response) {
|
|
169
|
-
if (chunk.event === "messages/partial" || chunk.event === "messages/complete") {
|
|
170
|
-
setMessages(accumulator.addMessages(chunk.data));
|
|
171
|
-
} else if (chunk.event === "updates") {
|
|
172
|
-
setInterrupt(chunk.data.__interrupt__?.[0]);
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
},
|
|
176
|
-
[messages, stream, appendMessage]
|
|
177
|
-
);
|
|
178
|
-
const cancel = (0, import_react.useCallback)(() => {
|
|
179
|
-
if (abortControllerRef.current) {
|
|
180
|
-
abortControllerRef.current.abort();
|
|
181
|
-
}
|
|
182
|
-
}, [abortControllerRef]);
|
|
183
|
-
return {
|
|
184
|
-
interrupt,
|
|
185
|
-
messages,
|
|
186
|
-
sendMessage,
|
|
187
|
-
cancel,
|
|
188
|
-
setInterrupt,
|
|
189
|
-
setMessages
|
|
190
|
-
};
|
|
191
|
-
};
|
|
192
|
-
|
|
193
|
-
// src/appendLangChainChunk.ts
|
|
194
|
-
var import_utils = require("assistant-stream/utils");
|
|
195
|
-
var appendLangChainChunk = (prev, curr) => {
|
|
196
|
-
if (curr.type !== "AIMessageChunk") {
|
|
197
|
-
return curr;
|
|
198
|
-
}
|
|
199
|
-
if (!prev || prev.type !== "ai") {
|
|
200
|
-
return {
|
|
201
|
-
...curr,
|
|
202
|
-
type: curr.type.replace("MessageChunk", "").toLowerCase()
|
|
203
|
-
};
|
|
204
|
-
}
|
|
205
|
-
const newContent = typeof prev.content === "string" ? [{ type: "text", text: prev.content }] : [...prev.content];
|
|
206
|
-
for (const chunk of curr.content) {
|
|
207
|
-
if (chunk.type === "text") {
|
|
208
|
-
const existing = newContent[chunk.index] ?? { type: "text", text: "" };
|
|
209
|
-
if (existing.type !== "text") throw new Error("");
|
|
210
|
-
newContent[chunk.index] = {
|
|
211
|
-
...existing,
|
|
212
|
-
...chunk,
|
|
213
|
-
text: existing.text + chunk.text
|
|
214
|
-
};
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
const newToolCalls = [...prev.tool_calls ?? []];
|
|
218
|
-
for (const chunk of curr.tool_call_chunks) {
|
|
219
|
-
const existing = newToolCalls[chunk.index - 1] ?? { argsText: "" };
|
|
220
|
-
const newArgsText = existing.argsText + chunk.args;
|
|
221
|
-
newToolCalls[chunk.index - 1] = {
|
|
222
|
-
...chunk,
|
|
223
|
-
...existing,
|
|
224
|
-
argsText: newArgsText,
|
|
225
|
-
args: (0, import_utils.parsePartialJsonObject)(newArgsText) ?? ("args" in existing ? existing.args : {})
|
|
226
|
-
};
|
|
227
|
-
}
|
|
228
|
-
return {
|
|
229
|
-
...prev,
|
|
230
|
-
content: newContent,
|
|
231
|
-
tool_calls: newToolCalls
|
|
232
|
-
};
|
|
233
|
-
};
|
|
234
|
-
|
|
235
|
-
// src/useLangGraphRuntime.ts
|
|
236
|
-
var getPendingToolCalls = (messages) => {
|
|
237
|
-
const pendingToolCalls = /* @__PURE__ */ new Map();
|
|
238
|
-
for (const message of messages) {
|
|
239
|
-
if (message.type === "ai") {
|
|
240
|
-
for (const toolCall of message.tool_calls ?? []) {
|
|
241
|
-
pendingToolCalls.set(toolCall.id, toolCall);
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
if (message.type === "tool") {
|
|
245
|
-
pendingToolCalls.delete(message.tool_call_id);
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
return [...pendingToolCalls.values()];
|
|
249
|
-
};
|
|
250
|
-
var getMessageContent = (msg) => {
|
|
251
|
-
const allContent = [
|
|
252
|
-
...msg.content,
|
|
253
|
-
...msg.attachments?.flatMap((a) => a.content) ?? []
|
|
254
|
-
];
|
|
255
|
-
const content = allContent.map((part) => {
|
|
256
|
-
const type = part.type;
|
|
257
|
-
switch (type) {
|
|
258
|
-
case "text":
|
|
259
|
-
return { type: "text", text: part.text };
|
|
260
|
-
case "image":
|
|
261
|
-
return { type: "image_url", image_url: { url: part.image } };
|
|
262
|
-
case "tool-call":
|
|
263
|
-
throw new Error("Tool call appends are not supported.");
|
|
264
|
-
default:
|
|
265
|
-
const _exhaustiveCheck = type;
|
|
266
|
-
throw new Error(
|
|
267
|
-
`Unsupported append content part type: ${_exhaustiveCheck}`
|
|
268
|
-
);
|
|
269
|
-
}
|
|
270
|
-
});
|
|
271
|
-
if (content.length === 1 && content[0]?.type === "text") {
|
|
272
|
-
return content[0].text ?? "";
|
|
273
|
-
}
|
|
274
|
-
return content;
|
|
275
|
-
};
|
|
276
|
-
var symbolLangGraphRuntimeExtras = Symbol("langgraph-runtime-extras");
|
|
277
|
-
var asLangGraphRuntimeExtras = (extras) => {
|
|
278
|
-
if (typeof extras !== "object" || extras == null || !(symbolLangGraphRuntimeExtras in extras))
|
|
279
|
-
throw new Error(
|
|
280
|
-
"This method can only be called when you are using useLangGraphRuntime"
|
|
281
|
-
);
|
|
282
|
-
return extras;
|
|
283
|
-
};
|
|
284
|
-
var useLangGraphInterruptState = () => {
|
|
285
|
-
const { interrupt } = (0, import_react3.useThread)((t) => asLangGraphRuntimeExtras(t.extras));
|
|
286
|
-
return interrupt;
|
|
287
|
-
};
|
|
288
|
-
var useLangGraphSend = () => {
|
|
289
|
-
const { send } = (0, import_react3.useThread)((t) => asLangGraphRuntimeExtras(t.extras));
|
|
290
|
-
return send;
|
|
291
|
-
};
|
|
292
|
-
var useLangGraphSendCommand = () => {
|
|
293
|
-
const send = useLangGraphSend();
|
|
294
|
-
return (command) => send([], { command });
|
|
295
|
-
};
|
|
296
|
-
var useLangGraphRuntime = ({
|
|
297
|
-
autoCancelPendingToolCalls,
|
|
298
|
-
adapters: { attachments, feedback, speech } = {},
|
|
299
|
-
unstable_allowCancellation,
|
|
300
|
-
stream,
|
|
301
|
-
threadId,
|
|
302
|
-
onSwitchToNewThread,
|
|
303
|
-
onSwitchToThread
|
|
304
|
-
}) => {
|
|
305
|
-
const {
|
|
306
|
-
interrupt,
|
|
307
|
-
setInterrupt,
|
|
308
|
-
messages,
|
|
309
|
-
sendMessage,
|
|
310
|
-
cancel,
|
|
311
|
-
setMessages
|
|
312
|
-
} = useLangGraphMessages({
|
|
313
|
-
appendMessage: appendLangChainChunk,
|
|
314
|
-
stream
|
|
315
|
-
});
|
|
316
|
-
const [isRunning, setIsRunning] = (0, import_react2.useState)(false);
|
|
317
|
-
const handleSendMessage = async (messages2, config) => {
|
|
318
|
-
try {
|
|
319
|
-
setIsRunning(true);
|
|
320
|
-
await sendMessage(messages2, config);
|
|
321
|
-
} catch (error) {
|
|
322
|
-
console.error("Error streaming messages:", error);
|
|
323
|
-
} finally {
|
|
324
|
-
setIsRunning(false);
|
|
325
|
-
}
|
|
326
|
-
};
|
|
327
|
-
const threadMessages = (0, import_react3.useExternalMessageConverter)({
|
|
328
|
-
callback: convertLangChainMessages,
|
|
329
|
-
messages,
|
|
330
|
-
isRunning
|
|
331
|
-
});
|
|
332
|
-
const switchToThread = !onSwitchToThread ? void 0 : async (externalId) => {
|
|
333
|
-
const { messages: messages2, interrupts } = await onSwitchToThread(externalId);
|
|
334
|
-
setMessages(messages2);
|
|
335
|
-
setInterrupt(interrupts?.[0]);
|
|
336
|
-
};
|
|
337
|
-
const threadList = {
|
|
338
|
-
threadId,
|
|
339
|
-
onSwitchToNewThread: !onSwitchToNewThread ? void 0 : async () => {
|
|
340
|
-
await onSwitchToNewThread();
|
|
341
|
-
setMessages([]);
|
|
342
|
-
},
|
|
343
|
-
onSwitchToThread: switchToThread
|
|
344
|
-
};
|
|
345
|
-
const loadingRef = (0, import_react2.useRef)(false);
|
|
346
|
-
const threadListItemRuntime = (0, import_react3.useThreadListItemRuntime)({ optional: true });
|
|
347
|
-
(0, import_react2.useEffect)(() => {
|
|
348
|
-
if (!threadListItemRuntime || !switchToThread || loadingRef.current) return;
|
|
349
|
-
const externalId = threadListItemRuntime.getState().externalId;
|
|
350
|
-
if (externalId) {
|
|
351
|
-
loadingRef.current = true;
|
|
352
|
-
switchToThread(externalId).finally(() => {
|
|
353
|
-
loadingRef.current = false;
|
|
354
|
-
});
|
|
355
|
-
}
|
|
356
|
-
}, []);
|
|
357
|
-
return (0, import_react3.useExternalStoreRuntime)({
|
|
358
|
-
isRunning,
|
|
359
|
-
messages: threadMessages,
|
|
360
|
-
adapters: {
|
|
361
|
-
attachments,
|
|
362
|
-
feedback,
|
|
363
|
-
speech,
|
|
364
|
-
threadList
|
|
365
|
-
},
|
|
366
|
-
extras: {
|
|
367
|
-
[symbolLangGraphRuntimeExtras]: true,
|
|
368
|
-
interrupt,
|
|
369
|
-
send: handleSendMessage
|
|
370
|
-
},
|
|
371
|
-
onNew: (msg) => {
|
|
372
|
-
const cancellations = autoCancelPendingToolCalls !== false ? getPendingToolCalls(messages).map(
|
|
373
|
-
(t) => ({
|
|
374
|
-
type: "tool",
|
|
375
|
-
name: t.name,
|
|
376
|
-
tool_call_id: t.id,
|
|
377
|
-
content: JSON.stringify({ cancelled: true })
|
|
378
|
-
})
|
|
379
|
-
) : [];
|
|
380
|
-
return handleSendMessage(
|
|
381
|
-
[
|
|
382
|
-
...cancellations,
|
|
383
|
-
{
|
|
384
|
-
type: "human",
|
|
385
|
-
content: getMessageContent(msg)
|
|
386
|
-
}
|
|
387
|
-
],
|
|
388
|
-
{
|
|
389
|
-
runConfig: msg.runConfig
|
|
390
|
-
}
|
|
391
|
-
);
|
|
392
|
-
},
|
|
393
|
-
onAddToolResult: async ({ toolCallId, toolName, result }) => {
|
|
394
|
-
await handleSendMessage(
|
|
395
|
-
[
|
|
396
|
-
{
|
|
397
|
-
type: "tool",
|
|
398
|
-
name: toolName,
|
|
399
|
-
tool_call_id: toolCallId,
|
|
400
|
-
content: JSON.stringify(result)
|
|
401
|
-
}
|
|
402
|
-
],
|
|
403
|
-
// TODO reuse runconfig here!
|
|
404
|
-
{}
|
|
405
|
-
);
|
|
406
|
-
},
|
|
407
|
-
onCancel: unstable_allowCancellation ? async () => {
|
|
408
|
-
cancel();
|
|
409
|
-
} : void 0
|
|
410
|
-
});
|
|
411
|
-
};
|
|
412
|
-
// Annotate the CommonJS export names for ESM import in node:
|
|
413
|
-
0 && (module.exports = {
|
|
1
|
+
import {
|
|
2
|
+
useLangGraphRuntime,
|
|
3
|
+
useLangGraphSend,
|
|
4
|
+
useLangGraphSendCommand,
|
|
5
|
+
useLangGraphInterruptState
|
|
6
|
+
} from "./useLangGraphRuntime";
|
|
7
|
+
import {
|
|
8
|
+
useLangGraphMessages
|
|
9
|
+
} from "./useLangGraphMessages";
|
|
10
|
+
import { convertLangChainMessages } from "./convertLangChainMessages";
|
|
11
|
+
import { convertLangChainMessages as convertLangChainMessages2 } from "./convertLangChainMessages";
|
|
12
|
+
import { LangGraphMessageAccumulator } from "./LangGraphMessageAccumulator";
|
|
13
|
+
import { appendLangChainChunk } from "./appendLangChainChunk";
|
|
14
|
+
export {
|
|
414
15
|
LangGraphMessageAccumulator,
|
|
415
16
|
appendLangChainChunk,
|
|
416
17
|
convertLangChainMessages,
|
|
417
|
-
convertLangchainMessages,
|
|
18
|
+
convertLangChainMessages2 as convertLangchainMessages,
|
|
418
19
|
useLangGraphInterruptState,
|
|
419
20
|
useLangGraphMessages,
|
|
420
21
|
useLangGraphRuntime,
|
|
421
22
|
useLangGraphSend,
|
|
422
23
|
useLangGraphSendCommand
|
|
423
|
-
}
|
|
24
|
+
};
|
|
424
25
|
//# sourceMappingURL=index.js.map
|