@langgraph-js/sdk 1.7.9 → 1.7.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -40,6 +40,7 @@ export type RenderMessage = Message & {
40
40
  input_tokens: number;
41
41
  output_tokens: number;
42
42
  };
43
+ tool_call_id?: string;
43
44
  response_metadata?: {
44
45
  create_time: string;
45
46
  };
@@ -162,7 +162,7 @@ export class LangGraphClient extends Client {
162
162
  const closedToolCallIds = new Set();
163
163
  const result = [];
164
164
  const inputMessages = this.combineGraphMessagesWithStreamingMessages();
165
- console.log(inputMessages);
165
+ // console.log(inputMessages);
166
166
  // 从后往前遍历,这样可以保证最新的消息在前面
167
167
  for (let i = inputMessages.length - 1; i >= 0; i--) {
168
168
  const message = this.cloneMessage(inputMessages[i]);
@@ -226,17 +226,13 @@ export class LangGraphClient extends Client {
226
226
  let lastMessage = null;
227
227
  for (const message of result) {
228
228
  const createTime = ((_a = message.response_metadata) === null || _a === void 0 ? void 0 : _a.create_time) || "";
229
- try {
230
- // 用长度作为渲染 id,长度变了就要重新渲染
231
- message.unique_id = message.id + JSON.stringify(message.content).length;
232
- }
233
- catch (e) {
234
- message.unique_id = message.id;
235
- }
229
+ // 工具必须要使用 tool_call_id 来保证一致性
230
+ message.unique_id = message.tool_call_id || message.id;
236
231
  message.spend_time = new Date(createTime).getTime() - new Date(((_b = lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.response_metadata) === null || _b === void 0 ? void 0 : _b.create_time) || createTime).getTime();
237
232
  if (!message.usage_metadata && ((_c = message.response_metadata) === null || _c === void 0 ? void 0 : _c.usage)) {
238
233
  const usage = message.response_metadata.usage;
239
234
  message.usage_metadata = {
235
+ ...usage,
240
236
  input_tokens: usage.prompt_tokens,
241
237
  output_tokens: usage.completion_tokens,
242
238
  total_tokens: usage.total_tokens,
@@ -1,14 +1,18 @@
1
1
  import { RenderMessage } from "../LangGraphClient.js";
2
2
  import { LangGraphClient } from "../LangGraphClient.js";
3
- export declare class ToolRenderData<D> {
3
+ export type DeepPartial<T> = {
4
+ [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
5
+ };
6
+ export declare class ToolRenderData<I, D> {
4
7
  message: RenderMessage;
5
8
  client: LangGraphClient;
6
9
  constructor(message: RenderMessage, client: LangGraphClient);
7
- get state(): "idle" | "done";
8
- get input(): any;
10
+ get state(): "idle" | "done" | "loading";
11
+ get input(): I | null;
9
12
  get output(): string;
10
- getJSONOutput(): any;
13
+ getJSONOutput(): D;
11
14
  /** 如果解析失败,则返回 null */
12
- getJSONOutputSafe(): any;
15
+ getJSONOutputSafe(): D | null;
16
+ getInputRepaired(): DeepPartial<I>;
13
17
  response(data: D): void;
14
18
  }
@@ -1,4 +1,5 @@
1
1
  import { getMessageContent } from "../ui-store/createChatStore.js";
2
+ import { jsonrepair } from "jsonrepair";
2
3
  export class ToolRenderData {
3
4
  constructor(message, client) {
4
5
  this.message = message;
@@ -9,6 +10,9 @@ export class ToolRenderData {
9
10
  if (this.message.type === "tool" && ((_b = (_a = this.message) === null || _a === void 0 ? void 0 : _a.additional_kwargs) === null || _b === void 0 ? void 0 : _b.done)) {
10
11
  return "done";
11
12
  }
13
+ if (this.message.tool_input) {
14
+ return "loading";
15
+ }
12
16
  return "idle";
13
17
  }
14
18
  get input() {
@@ -34,6 +38,14 @@ export class ToolRenderData {
34
38
  return null;
35
39
  }
36
40
  }
41
+ getInputRepaired() {
42
+ try {
43
+ return JSON.parse(jsonrepair(this.message.tool_input || ""));
44
+ }
45
+ catch (e) {
46
+ return {};
47
+ }
48
+ }
37
49
  response(data) {
38
50
  this.client.doneFEToolWaiting(this.message.id, JSON.stringify(data));
39
51
  }
@@ -11,7 +11,7 @@ export interface UnionTool<Args extends ZodRawShape, Child extends Object = Obje
11
11
  execute: ToolCallback<Args>;
12
12
  /** 工具执行成功后触发的附加消息 */
13
13
  callbackMessage?: (result: CallToolResult) => Message[];
14
- render?: <D>(tool: ToolRenderData<D>) => Child;
14
+ render?: <D>(tool: ToolRenderData<z.objectOutputType<Args, ZodTypeAny>, D>) => Child;
15
15
  onlyRender?: boolean;
16
16
  /** 只允许指定的 agent 使用该工具,如果未指定,则所有 agent 都可以使用 */
17
17
  allowAgent?: string[];
@@ -56,10 +56,10 @@ export declare const createMCPTool: <Args extends ZodRawShape>(tool: UnionTool<A
56
56
  }>))[];
57
57
  export declare const createToolUI: <Args extends Parameter[] | [] = [], Child extends Object = {}>(tool: Action<Args> & {
58
58
  allowAgent?: string[];
59
- render?: (tool: ToolRenderData<any>) => Child;
59
+ render?: (tool: ToolRenderData<any, any>) => Child;
60
60
  onlyRender?: boolean;
61
61
  }) => {
62
- render: ((tool: ToolRenderData<any>) => Child) | undefined;
62
+ render: ((tool: ToolRenderData<any, any>) => Child) | undefined;
63
63
  onlyRender: boolean | undefined;
64
64
  name: string;
65
65
  description: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langgraph-js/sdk",
3
- "version": "1.7.9",
3
+ "version": "1.7.10",
4
4
  "description": "The UI SDK for LangGraph - seamlessly integrate your AI agents with frontend interfaces",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",
@@ -30,6 +30,7 @@
30
30
  },
31
31
  "dependencies": {
32
32
  "@langchain/langgraph-sdk": "^0.0.77",
33
+ "jsonrepair": "^3.12.0",
33
34
  "nanostores": "^1.0.1",
34
35
  "zod": "^3.25.17",
35
36
  "zod-to-json-schema": "^3.24.5"
@@ -40,6 +40,7 @@ export type RenderMessage = Message & {
40
40
  input_tokens: number;
41
41
  output_tokens: number;
42
42
  };
43
+ tool_call_id?: string;
43
44
  response_metadata?: {
44
45
  create_time: string;
45
46
  };
@@ -231,7 +232,7 @@ export class LangGraphClient extends Client {
231
232
  const closedToolCallIds = new Set<string>();
232
233
  const result: Message[] = [];
233
234
  const inputMessages = this.combineGraphMessagesWithStreamingMessages();
234
- console.log(inputMessages);
235
+ // console.log(inputMessages);
235
236
  // 从后往前遍历,这样可以保证最新的消息在前面
236
237
  for (let i = inputMessages.length - 1; i >= 0; i--) {
237
238
  const message = this.cloneMessage(inputMessages[i]);
@@ -295,12 +296,9 @@ export class LangGraphClient extends Client {
295
296
  let lastMessage: RenderMessage | null = null;
296
297
  for (const message of result) {
297
298
  const createTime = message.response_metadata?.create_time || "";
298
- try {
299
- // 用长度作为渲染 id,长度变了就要重新渲染
300
- message.unique_id = message.id! + JSON.stringify(message.content).length;
301
- } catch (e) {
302
- message.unique_id = message.id!;
303
- }
299
+ // 工具必须要使用 tool_call_id 来保证一致性
300
+ message.unique_id = message.tool_call_id! || message.id!;
301
+
304
302
  message.spend_time = new Date(createTime).getTime() - new Date(lastMessage?.response_metadata?.create_time || createTime).getTime();
305
303
  if (!message.usage_metadata && (message as AIMessage).response_metadata?.usage) {
306
304
  const usage = (message as AIMessage).response_metadata!.usage as {
@@ -309,6 +307,7 @@ export class LangGraphClient extends Client {
309
307
  total_tokens: number;
310
308
  };
311
309
  message.usage_metadata = {
310
+ ...usage,
312
311
  input_tokens: usage.prompt_tokens,
313
312
  output_tokens: usage.completion_tokens,
314
313
  total_tokens: usage.total_tokens,
@@ -2,8 +2,12 @@ import { RenderMessage } from "../LangGraphClient.js";
2
2
 
3
3
  import { LangGraphClient } from "../LangGraphClient.js";
4
4
  import { getMessageContent } from "../ui-store/createChatStore.js";
5
+ import { jsonrepair } from "jsonrepair";
5
6
 
6
- export class ToolRenderData<D> {
7
+ export type DeepPartial<T> = {
8
+ [P in keyof T]?: T[P] extends object ? DeepPartial<T[P]> : T[P];
9
+ };
10
+ export class ToolRenderData<I, D> {
7
11
  constructor(
8
12
  public message: RenderMessage,
9
13
  public client: LangGraphClient
@@ -12,9 +16,12 @@ export class ToolRenderData<D> {
12
16
  if (this.message.type === "tool" && this.message?.additional_kwargs?.done) {
13
17
  return "done";
14
18
  }
19
+ if (this.message.tool_input) {
20
+ return "loading";
21
+ }
15
22
  return "idle";
16
23
  }
17
- get input() {
24
+ get input(): I | null {
18
25
  try {
19
26
  return JSON.parse(this.message.tool_input!);
20
27
  } catch (e) {
@@ -24,17 +31,24 @@ export class ToolRenderData<D> {
24
31
  get output() {
25
32
  return getMessageContent(this.message.content);
26
33
  }
27
- getJSONOutput() {
34
+ getJSONOutput(): D {
28
35
  return JSON.parse(this.output);
29
36
  }
30
37
  /** 如果解析失败,则返回 null */
31
- getJSONOutputSafe() {
38
+ getJSONOutputSafe(): D | null {
32
39
  try {
33
40
  return JSON.parse(this.output);
34
41
  } catch (e) {
35
42
  return null;
36
43
  }
37
44
  }
45
+ getInputRepaired(): DeepPartial<I> {
46
+ try {
47
+ return JSON.parse(jsonrepair(this.message.tool_input || ""));
48
+ } catch (e) {
49
+ return {};
50
+ }
51
+ }
38
52
  response(data: D) {
39
53
  this.client.doneFEToolWaiting(this.message.id!, JSON.stringify(data));
40
54
  }
@@ -14,7 +14,7 @@ export interface UnionTool<Args extends ZodRawShape, Child extends Object = Obje
14
14
  execute: ToolCallback<Args>;
15
15
  /** 工具执行成功后触发的附加消息 */
16
16
  callbackMessage?: (result: CallToolResult) => Message[];
17
- render?: <D>(tool: ToolRenderData<D>) => Child;
17
+ render?: <D>(tool: ToolRenderData<z.objectOutputType<Args, ZodTypeAny>, D>) => Child;
18
18
  onlyRender?: boolean;
19
19
  /** 只允许指定的 agent 使用该工具,如果未指定,则所有 agent 都可以使用 */
20
20
  allowAgent?: string[];
@@ -92,7 +92,7 @@ export const createMCPTool = <Args extends ZodRawShape>(tool: UnionTool<Args>) =
92
92
  export const createToolUI = <Args extends Parameter[] | [] = [], Child extends Object = {}>(
93
93
  tool: Action<Args> & {
94
94
  allowAgent?: string[];
95
- render?: (tool: ToolRenderData<any>) => Child;
95
+ render?: (tool: ToolRenderData<any, any>) => Child;
96
96
  onlyRender?: boolean;
97
97
  }
98
98
  ) => {