@vegintech/langchain-react-agent 0.0.31 → 0.0.33

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/index.d.mts CHANGED
@@ -169,6 +169,8 @@ interface ToolRenderProps<TArgs = Record<string, unknown>> {
169
169
  result?: unknown;
170
170
  status: ToolExecutionStatus;
171
171
  error?: string;
172
+ /** 是否正在加载 */
173
+ isLoading?: boolean;
172
174
  }
173
175
  /** 前端工具:需要完整的工具定义(用于前端执行) */
174
176
  interface FrontendTool<TArgs = Record<string, unknown>> {
package/dist/index.mjs CHANGED
@@ -61,7 +61,7 @@ ChatInput.displayName = "ChatInput";
61
61
  * 2. 支持自定义 render 函数
62
62
  * 3. 默认渲染:简单的工具卡片样式
63
63
  */
64
- const ToolCallRenderer = ({ tool, record }) => {
64
+ const ToolCallRenderer = ({ tool, record, isLoading }) => {
65
65
  if (tool?.render) return /* @__PURE__ */ jsx("div", {
66
66
  className: "tool-call-wrapper",
67
67
  children: tool.render({
@@ -69,7 +69,8 @@ const ToolCallRenderer = ({ tool, record }) => {
69
69
  args: record.args,
70
70
  result: record.result,
71
71
  status: record.status,
72
- error: record.error
72
+ error: record.error,
73
+ isLoading
73
74
  })
74
75
  });
75
76
  return /* @__PURE__ */ jsx(DefaultToolCallRenderer, { record });
@@ -324,7 +325,7 @@ const renderMessageContent = (message, isLastMessage, isLoading, tools, toolExec
324
325
  hasToolCalls && /* @__PURE__ */ jsx("div", {
325
326
  className: "tool-calls-container",
326
327
  style: { marginTop: !isContentEmpty ? "8px" : "0px" },
327
- children: renderToolCalls(message.toolCalls, tools, toolExecutions)
328
+ children: renderToolCalls(message.toolCalls, tools, toolExecutions, isLoading)
328
329
  })
329
330
  ]
330
331
  }, message.id);
@@ -337,7 +338,7 @@ const toBubbleItem = (message, isLastMessage, isLoading, tools, toolExecutions,
337
338
  placement: message.type === "human" ? "end" : "start"
338
339
  };
339
340
  };
340
- const renderToolCalls = (toolCalls, tools, toolExecutions) => {
341
+ const renderToolCalls = (toolCalls, tools, toolExecutions, isLoading) => {
341
342
  return toolCalls.map((call) => {
342
343
  const tool = findTool(tools, call.name);
343
344
  let record;
@@ -360,7 +361,8 @@ const renderToolCalls = (toolCalls, tools, toolExecutions) => {
360
361
  };
361
362
  return /* @__PURE__ */ jsx(ToolCallRenderer, {
362
363
  tool,
363
- record
364
+ record,
365
+ isLoading
364
366
  }, call.id);
365
367
  }).filter(Boolean);
366
368
  };
@@ -504,6 +506,46 @@ function useInterrupt({ interrupt, config, onSubmit }) {
504
506
  //#endregion
505
507
  //#region src/hooks/useToolExecution.ts
506
508
  /**
509
+ * 根据工具执行结果构建 ToolMessage
510
+ *
511
+ * 支持两种模式:
512
+ * 1. 工具返回 { content, artifact } 结构,自动拆分为 ToolMessage 字段
513
+ * 2. 工具直接返回 ToolMessage(对象且 type === "tool"),透传使用
514
+ */
515
+ function createToolMessage(callId, name, result, status, errorMessage) {
516
+ if (status === "error") return {
517
+ type: "tool",
518
+ content: `Error: ${errorMessage}`,
519
+ tool_call_id: callId,
520
+ name,
521
+ status
522
+ };
523
+ if (result !== null && typeof result === "object" && "type" in result && result.type === "tool") {
524
+ const toolMsg = result;
525
+ return {
526
+ ...toolMsg,
527
+ tool_call_id: toolMsg.tool_call_id || callId,
528
+ name: toolMsg.name || name
529
+ };
530
+ }
531
+ let content;
532
+ let artifact;
533
+ if (result !== null && typeof result === "object" && "content" in result && "artifact" in result) {
534
+ const r = result;
535
+ content = typeof r.content === "string" ? r.content : JSON.stringify(r.content);
536
+ artifact = r.artifact;
537
+ } else content = typeof result === "string" ? result : JSON.stringify(result);
538
+ const message = {
539
+ type: "tool",
540
+ content,
541
+ tool_call_id: callId,
542
+ name,
543
+ status
544
+ };
545
+ if (artifact !== void 0) message.artifact = artifact;
546
+ return message;
547
+ }
548
+ /**
507
549
  * useToolExecution - 管理前端工具执行的 Hook
508
550
  *
509
551
  * 职责:
@@ -571,11 +613,7 @@ function useToolExecution({ tools, toolCalls, isLoading = false, onExecutionChan
571
613
  status: "success",
572
614
  result
573
615
  });
574
- batchResultsRef.current.set(callId, {
575
- callId,
576
- name: call.name,
577
- result
578
- });
616
+ batchResultsRef.current.set(callId, createToolMessage(callId, call.name, result, "success"));
579
617
  } catch (error) {
580
618
  const errorMessage = error instanceof Error ? error.message : String(error);
581
619
  onExecutionChange?.({
@@ -585,11 +623,7 @@ function useToolExecution({ tools, toolCalls, isLoading = false, onExecutionChan
585
623
  status: "error",
586
624
  error: errorMessage
587
625
  });
588
- batchResultsRef.current.set(callId, {
589
- callId,
590
- name: call.name,
591
- result: { error: errorMessage }
592
- });
626
+ batchResultsRef.current.set(callId, createToolMessage(callId, call.name, null, "error", errorMessage));
593
627
  } finally {
594
628
  executingCallsRef.current.delete(callId);
595
629
  executedCallsRef.current.add(callId);
@@ -945,15 +979,7 @@ const AgentChat = forwardRef(({ stream, className = "", tools, contexts, message
945
979
  contexts,
946
980
  agentState
947
981
  ]);
948
- const handleToolResultsBatch = useCallback((results) => {
949
- const toolMessages = results.map(({ callId, name, result }) => {
950
- return {
951
- type: "tool",
952
- content: typeof result === "string" ? result : JSON.stringify(result),
953
- tool_call_id: callId,
954
- name
955
- };
956
- });
982
+ const handleToolResultsBatch = useCallback((toolMessages) => {
957
983
  setTimeout(() => {
958
984
  submitToStream(toolMessages);
959
985
  }, 100);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vegintech/langchain-react-agent",
3
- "version": "0.0.31",
3
+ "version": "0.0.33",
4
4
  "description": "LangChain Agent UI component library for React",
5
5
  "license": "MIT",
6
6
  "files": [