@assistant-ui/react-langgraph 0.5.5 → 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.
Files changed (35) hide show
  1. package/dist/LangGraphMessageAccumulator.d.ts +0 -4
  2. package/dist/LangGraphMessageAccumulator.d.ts.map +1 -1
  3. package/dist/LangGraphMessageAccumulator.js.map +1 -1
  4. package/dist/appendLangChainChunk.d.ts.map +1 -1
  5. package/dist/appendLangChainChunk.js +23 -10
  6. package/dist/appendLangChainChunk.js.map +1 -1
  7. package/dist/convertLangChainMessages.d.ts.map +1 -1
  8. package/dist/convertLangChainMessages.js +4 -0
  9. package/dist/convertLangChainMessages.js.map +1 -1
  10. package/dist/testUtils.d.ts +4 -0
  11. package/dist/testUtils.d.ts.map +1 -0
  12. package/dist/testUtils.js +10 -0
  13. package/dist/testUtils.js.map +1 -0
  14. package/dist/types.d.ts +29 -11
  15. package/dist/types.d.ts.map +1 -1
  16. package/dist/types.js +14 -0
  17. package/dist/types.js.map +1 -1
  18. package/dist/useLangGraphMessages.d.ts +9 -2
  19. package/dist/useLangGraphMessages.d.ts.map +1 -1
  20. package/dist/useLangGraphMessages.js +72 -10
  21. package/dist/useLangGraphMessages.js.map +1 -1
  22. package/dist/useLangGraphRuntime.d.ts +23 -2
  23. package/dist/useLangGraphRuntime.d.ts.map +1 -1
  24. package/dist/useLangGraphRuntime.js +4 -2
  25. package/dist/useLangGraphRuntime.js.map +1 -1
  26. package/package.json +14 -8
  27. package/src/LangGraphMessageAccumulator.ts +0 -11
  28. package/src/appendLangChainChunk.ts +31 -11
  29. package/src/convertLangChainMessages.ts +4 -0
  30. package/src/testUtils.ts +11 -0
  31. package/src/types.ts +42 -8
  32. package/src/useLangGraphMessages.test.ts +611 -0
  33. package/src/useLangGraphMessages.ts +98 -19
  34. package/src/useLangGraphRuntime.test.tsx +276 -0
  35. package/src/useLangGraphRuntime.ts +33 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@assistant-ui/react-langgraph",
3
- "version": "0.5.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.28"
23
+ "zod": "^3.25.49"
24
24
  },
25
25
  "peerDependencies": {
26
- "@assistant-ui/react": "^0.10.19",
26
+ "@assistant-ui/react": "^0.10.21",
27
27
  "@types/react": "*",
28
28
  "react": "^18 || ^19 || ^19.0.0-rc"
29
29
  },
@@ -33,14 +33,18 @@
33
33
  }
34
34
  },
35
35
  "devDependencies": {
36
- "@types/node": "^22.15.21",
37
- "@types/react": "^19.1.5",
36
+ "@testing-library/dom": "^10.4.0",
37
+ "@testing-library/react": "^16.3.0",
38
+ "@types/node": "^22.15.29",
39
+ "@types/react": "^19.1.6",
38
40
  "@types/uuid": "^10.0.0",
39
41
  "eslint": "^9",
40
- "eslint-config-next": "15.3.2",
42
+ "eslint-config-next": "15.3.3",
43
+ "jsdom": "^26.1.0",
41
44
  "react": "^19.1.0",
42
45
  "tsx": "^4.19.4",
43
- "@assistant-ui/react": "0.10.19",
46
+ "vitest": "^3.2.0",
47
+ "@assistant-ui/react": "0.10.21",
44
48
  "@assistant-ui/x-buildutils": "0.0.1"
45
49
  },
46
50
  "publishConfig": {
@@ -57,6 +61,8 @@
57
61
  },
58
62
  "scripts": {
59
63
  "build": "tsx scripts/build.mts",
60
- "lint": "eslint ."
64
+ "lint": "eslint .",
65
+ "test": "vitest run",
66
+ "test:watch": "vitest"
61
67
  }
62
68
  }
@@ -1,16 +1,5 @@
1
1
  import { v4 as uuidv4 } from "uuid";
2
2
 
3
- export type LangGraphMessagesEvent<TMessage> = {
4
- event:
5
- | "messages"
6
- | "messages/partial"
7
- | "messages/complete"
8
- | "metadata"
9
- | "updates"
10
- | string;
11
- data: TMessage[] | any;
12
- };
13
-
14
3
  export type LangGraphStateAccumulatorConfig<TMessage> = {
15
4
  initialMessages?: TMessage[];
16
5
  appendMessage?: (prev: TMessage | undefined, curr: TMessage) => TMessage;
@@ -1,4 +1,8 @@
1
- import { LangChainMessage, LangChainMessageChunk } from "./types";
1
+ import {
2
+ LangChainMessage,
3
+ LangChainMessageChunk,
4
+ MessageContentText,
5
+ } from "./types";
2
6
  import { parsePartialJsonObject } from "assistant-stream/utils";
3
7
 
4
8
  export const appendLangChainChunk = (
@@ -21,20 +25,36 @@ export const appendLangChainChunk = (
21
25
  ? [{ type: "text" as const, text: prev.content }]
22
26
  : [...prev.content];
23
27
 
24
- for (const chunk of curr.content) {
25
- if (chunk.type === "text") {
26
- const existing = newContent[chunk.index] ?? { type: "text", text: "" };
27
- if (existing.type !== "text") throw new Error("");
28
- newContent[chunk.index] = {
29
- ...existing,
30
- ...chunk,
31
- text: existing.text + chunk.text,
32
- };
28
+ if (typeof curr?.content === "string") {
29
+ const lastIndex = newContent.length - 1;
30
+ if (newContent[lastIndex]?.type === "text") {
31
+ (newContent[lastIndex] as MessageContentText).text =
32
+ (newContent[lastIndex] as MessageContentText).text + curr.content;
33
+ } else {
34
+ newContent.push({ type: "text", text: curr.content });
35
+ }
36
+ } else if (Array.isArray(curr.content)) {
37
+ const lastIndex = newContent.length - 1;
38
+ for (const item of curr.content) {
39
+ if (!("type" in item)) {
40
+ continue;
41
+ }
42
+
43
+ if (item.type === "text") {
44
+ if (newContent[lastIndex]?.type === "text") {
45
+ (newContent[lastIndex] as MessageContentText).text =
46
+ (newContent[lastIndex] as MessageContentText).text + item.text;
47
+ } else {
48
+ newContent.push({ type: "text", text: item.text });
49
+ }
50
+ } else if (item.type === "image_url") {
51
+ newContent.push(item);
52
+ }
33
53
  }
34
54
  }
35
55
 
36
56
  const newToolCalls = [...(prev.tool_calls ?? [])];
37
- for (const chunk of curr.tool_call_chunks) {
57
+ for (const chunk of curr.tool_call_chunks ?? []) {
38
58
  const existing = newToolCalls[chunk.index - 1] ?? { argsText: "" };
39
59
  const newArgsText = existing.argsText + chunk.args;
40
60
  newToolCalls[chunk.index - 1] = {
@@ -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}`);
@@ -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
@@ -14,23 +14,38 @@ export type LangChainToolCall = {
14
14
  args: ReadonlyJSONObject;
15
15
  };
16
16
 
17
- type MessageContentText = {
18
- type: "text";
17
+ export type MessageContentText = {
18
+ type: "text" | "text_delta";
19
19
  text: string;
20
20
  };
21
21
 
22
- type MessageContentImageUrl = {
22
+ export type MessageContentImageUrl = {
23
23
  type: "image_url";
24
24
  image_url: string | { url: string };
25
25
  };
26
26
 
27
27
  type MessageContentToolUse = {
28
- type: "tool_use";
28
+ type: "tool_use" | "input_json_delta";
29
29
  };
30
30
 
31
+ export enum LangGraphKnownEventTypes {
32
+ Messages = "messages",
33
+ MessagesPartial = "messages/partial",
34
+ MessagesComplete = "messages/complete",
35
+ Metadata = "metadata",
36
+ Updates = "updates",
37
+ Info = "info",
38
+ Error = "error",
39
+ }
40
+
41
+ type CustomEventType = string;
42
+
43
+ export type EventType = LangGraphKnownEventTypes | CustomEventType;
44
+
31
45
  type UserMessageContentComplex = MessageContentText | MessageContentImageUrl;
32
46
  type AssistantMessageContentComplex =
33
47
  | MessageContentText
48
+ | MessageContentImageUrl
34
49
  | MessageContentToolUse;
35
50
 
36
51
  type UserMessageContent = string | UserMessageContentComplex[];
@@ -65,13 +80,32 @@ export type LangChainMessage =
65
80
  };
66
81
 
67
82
  export type LangChainMessageChunk = {
68
- id: string;
83
+ id?: string | undefined;
69
84
  type: "AIMessageChunk";
70
- content: (AssistantMessageContentComplex & { index: number })[];
71
- tool_call_chunks: LangChainToolCallChunk[];
85
+ content?: AssistantMessageContent | undefined;
86
+ tool_call_chunks?: LangChainToolCallChunk[] | undefined;
72
87
  };
73
88
 
74
89
  export type LangChainEvent = {
75
- event: "messages/partial" | "messages/complete";
90
+ event:
91
+ | LangGraphKnownEventTypes.MessagesPartial
92
+ | LangGraphKnownEventTypes.MessagesComplete;
76
93
  data: LangChainMessage[];
77
94
  };
95
+
96
+ type LangGraphTupleMetadata = Record<string, unknown>;
97
+
98
+ export type LangChainMessageTupleEvent = {
99
+ event: LangGraphKnownEventTypes.Messages;
100
+ data: [LangChainMessageChunk, LangGraphTupleMetadata];
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>;