@vegintech/langchain-react-agent 0.0.35 → 0.0.36
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 +1 -1
- package/dist/index.mjs +50 -8
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -154,7 +154,7 @@ interface ToolCallInput {
|
|
|
154
154
|
status?: "success" | "error";
|
|
155
155
|
}
|
|
156
156
|
/** 工具执行状态 */
|
|
157
|
-
type ToolExecutionStatus = "pending" | "running" | "success" | "error";
|
|
157
|
+
type ToolExecutionStatus = "pending" | "running" | "success" | "error" | "cancelled";
|
|
158
158
|
/** 工具执行结果 */
|
|
159
159
|
interface ToolExecutionRecord {
|
|
160
160
|
callId: string;
|
package/dist/index.mjs
CHANGED
|
@@ -563,10 +563,16 @@ function useToolExecution({ tools, toolCalls, isLoading = false, onExecutionChan
|
|
|
563
563
|
const batchResultsRef = useRef(/* @__PURE__ */ new Map());
|
|
564
564
|
const isProcessingRef = useRef(false);
|
|
565
565
|
const batchSubmittedRef = useRef(false);
|
|
566
|
+
const cancelledCallIdsRef = useRef(/* @__PURE__ */ new Set());
|
|
567
|
+
const cancelledExecutionsRef = useRef(/* @__PURE__ */ new Set());
|
|
566
568
|
useEffect(() => {
|
|
567
569
|
if (!completedToolResults || completedToolResults.size === 0) return;
|
|
568
570
|
completedToolResults.forEach(({ result, status }, callId) => {
|
|
569
571
|
if (notifiedCompletedRef.current.has(callId)) return;
|
|
572
|
+
if (cancelledExecutionsRef.current.has(callId)) {
|
|
573
|
+
notifiedCompletedRef.current.add(callId);
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
570
576
|
if (executedCallsRef.current.has(callId)) {
|
|
571
577
|
notifiedCompletedRef.current.add(callId);
|
|
572
578
|
return;
|
|
@@ -630,7 +636,12 @@ function useToolExecution({ tools, toolCalls, isLoading = false, onExecutionChan
|
|
|
630
636
|
batchResultsRef.current.set(callId, createToolMessage(callId, call.name, null, "error", errorMessage));
|
|
631
637
|
} finally {
|
|
632
638
|
executingCallsRef.current.delete(callId);
|
|
633
|
-
|
|
639
|
+
if (cancelledCallIdsRef.current.has(callId)) {
|
|
640
|
+
cancelledCallIdsRef.current.delete(callId);
|
|
641
|
+
cancelledExecutionsRef.current.add(callId);
|
|
642
|
+
batchResultsRef.current.delete(callId);
|
|
643
|
+
batchCallIdsRef.current.delete(callId);
|
|
644
|
+
} else executedCallsRef.current.add(callId);
|
|
634
645
|
checkAndSubmitBatch();
|
|
635
646
|
}
|
|
636
647
|
}, [onExecutionChange, checkAndSubmitBatch]);
|
|
@@ -643,7 +654,7 @@ function useToolExecution({ tools, toolCalls, isLoading = false, onExecutionChan
|
|
|
643
654
|
const frontendCalls = [];
|
|
644
655
|
for (const call of toolCalls) {
|
|
645
656
|
const callId = call.id;
|
|
646
|
-
if (executedCallsRef.current.has(callId) || executingCallsRef.current.has(callId)) continue;
|
|
657
|
+
if (executedCallsRef.current.has(callId) || executingCallsRef.current.has(callId) || cancelledExecutionsRef.current.has(callId)) continue;
|
|
647
658
|
const tool = findTool(tools, call.name);
|
|
648
659
|
if (isLoading) {
|
|
649
660
|
if (!pendingNotifiedRef.current.has(callId)) {
|
|
@@ -695,11 +706,36 @@ function useToolExecution({ tools, toolCalls, isLoading = false, onExecutionChan
|
|
|
695
706
|
executeFrontendTool,
|
|
696
707
|
onExecutionChange
|
|
697
708
|
]);
|
|
709
|
+
/**
|
|
710
|
+
* 取消当前正在执行或待执行的前端工具
|
|
711
|
+
*
|
|
712
|
+
* 由于 JavaScript 无法真正中断异步执行,取消仅做标记:
|
|
713
|
+
* 1. 正在执行的工具完成后会被无视(不提交结果)
|
|
714
|
+
* 2. 尚未执行的工具被直接移除,不再执行
|
|
715
|
+
*/
|
|
716
|
+
const cancel = useCallback(() => {
|
|
717
|
+
const callIdsToCancel = new Set([...executingCallsRef.current, ...batchCallIdsRef.current]);
|
|
718
|
+
for (const callId of callIdsToCancel) {
|
|
719
|
+
cancelledCallIdsRef.current.add(callId);
|
|
720
|
+
if (!executingCallsRef.current.has(callId)) {
|
|
721
|
+
cancelledExecutionsRef.current.add(callId);
|
|
722
|
+
batchCallIdsRef.current.delete(callId);
|
|
723
|
+
}
|
|
724
|
+
const call = toolCalls.find((c) => c.id === callId);
|
|
725
|
+
if (call) onExecutionChange?.({
|
|
726
|
+
callId,
|
|
727
|
+
name: call.name,
|
|
728
|
+
args: call.args,
|
|
729
|
+
status: "cancelled"
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
}, [toolCalls, onExecutionChange]);
|
|
698
733
|
useEffect(() => {
|
|
699
734
|
processToolCalls();
|
|
700
735
|
}, [useMemo(() => {
|
|
701
|
-
return toolCalls.filter((call) => !executedCallsRef.current.has(call.id) && !executingCallsRef.current.has(call.id)).map((call) => call.id).sort().join(",");
|
|
736
|
+
return toolCalls.filter((call) => !executedCallsRef.current.has(call.id) && !executingCallsRef.current.has(call.id) && !cancelledExecutionsRef.current.has(call.id)).map((call) => call.id).sort().join(",");
|
|
702
737
|
}, [toolCalls]), isLoading]);
|
|
738
|
+
return { cancel };
|
|
703
739
|
}
|
|
704
740
|
//#endregion
|
|
705
741
|
//#region src/utils/messageUtils.ts
|
|
@@ -951,7 +987,6 @@ const AgentChat = forwardRef(({ stream, className = "", tools, contexts, message
|
|
|
951
987
|
onSubmit: stream.submit
|
|
952
988
|
});
|
|
953
989
|
const [toolExecutions, setToolExecutions] = useState(/* @__PURE__ */ new Map());
|
|
954
|
-
const isLoading = stream.isLoading;
|
|
955
990
|
const { messages, toolResults } = useMemo(() => {
|
|
956
991
|
return processMessages(stream.messages);
|
|
957
992
|
}, [stream.messages]);
|
|
@@ -968,6 +1003,12 @@ const AgentChat = forwardRef(({ stream, className = "", tools, contexts, message
|
|
|
968
1003
|
const frontendTools = useMemo(() => {
|
|
969
1004
|
return tools?.filter(isFrontendTool) || [];
|
|
970
1005
|
}, [tools]);
|
|
1006
|
+
const frontendToolNames = useMemo(() => new Set(frontendTools.map((t) => t.name)), [frontendTools]);
|
|
1007
|
+
const hasToolExecuting = useMemo(() => {
|
|
1008
|
+
for (const record of toolExecutions.values()) if (frontendToolNames.has(record.name) && (record.status === "running" || record.status === "pending")) return true;
|
|
1009
|
+
return false;
|
|
1010
|
+
}, [toolExecutions, frontendToolNames]);
|
|
1011
|
+
const isLoading = stream.isLoading || hasToolExecuting;
|
|
971
1012
|
const submitToStream = useCallback(async (submitMessages) => {
|
|
972
1013
|
await stream.submit({
|
|
973
1014
|
...agentState,
|
|
@@ -1012,10 +1053,7 @@ const AgentChat = forwardRef(({ stream, className = "", tools, contexts, message
|
|
|
1012
1053
|
if (messages.length === 0) return;
|
|
1013
1054
|
await submitToStream(messages);
|
|
1014
1055
|
}, [onPreSend, submitToStream]);
|
|
1015
|
-
const
|
|
1016
|
-
await stream.stop();
|
|
1017
|
-
}, [stream]);
|
|
1018
|
-
useToolExecution({
|
|
1056
|
+
const { cancel: cancelToolExecution } = useToolExecution({
|
|
1019
1057
|
tools,
|
|
1020
1058
|
toolCalls: allToolCalls,
|
|
1021
1059
|
isLoading: stream.isLoading,
|
|
@@ -1023,6 +1061,10 @@ const AgentChat = forwardRef(({ stream, className = "", tools, contexts, message
|
|
|
1023
1061
|
onToolResultsBatch: handleToolResultsBatch,
|
|
1024
1062
|
completedToolResults: toolResults
|
|
1025
1063
|
});
|
|
1064
|
+
const handleStop = useCallback(async () => {
|
|
1065
|
+
cancelToolExecution();
|
|
1066
|
+
await stream.stop();
|
|
1067
|
+
}, [stream, cancelToolExecution]);
|
|
1026
1068
|
const shouldRenderWelcome = messages.length === 0 && !isLoading && welcome;
|
|
1027
1069
|
return /* @__PURE__ */ jsxs("div", {
|
|
1028
1070
|
className: `agent-chat-container ${className}`,
|