@invergent/agent-chat-react 1.6.5 → 1.6.6
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.cjs +76 -22
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +76 -22
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -8421,10 +8421,16 @@ function applyLlmResponse(state, event) {
|
|
|
8421
8421
|
const responseContent = stringValue2(message?.content) || stringValue2(event.data.content);
|
|
8422
8422
|
const toolCalls = Array.isArray(message?.tool_calls) ? message?.tool_calls : [];
|
|
8423
8423
|
const hasToolCalls = toolCalls.length > 0;
|
|
8424
|
+
const responseToolCallIds = toolCallIdsFromResponse(toolCalls);
|
|
8424
8425
|
const idx = findLastAssistantIndex(messages);
|
|
8425
8426
|
const prevAssistant = idx >= 0 ? messages[idx] : void 0;
|
|
8426
8427
|
const prevHasTools = Boolean(prevAssistant?.toolCalls?.length);
|
|
8427
8428
|
const hasUserAfter = idx >= 0 && hasUserAfterIndex(messages, idx);
|
|
8429
|
+
const matchesExistingToolTurn = Boolean(
|
|
8430
|
+
hasToolCalls && prevAssistant?.toolCalls?.length && responseToolCallIds.length > 0 && !hasUserAfter && responseToolCallIds.every(
|
|
8431
|
+
(id) => prevAssistant.toolCalls?.some((tc) => tc.id === id)
|
|
8432
|
+
)
|
|
8433
|
+
);
|
|
8428
8434
|
if (state.hadDeltas && idx >= 0 && !hasUserAfter) {
|
|
8429
8435
|
const current = messages[idx];
|
|
8430
8436
|
if (hasToolCalls) {
|
|
@@ -8437,6 +8443,13 @@ function applyLlmResponse(state, event) {
|
|
|
8437
8443
|
} else {
|
|
8438
8444
|
messages[idx] = { ...current, status: "complete" };
|
|
8439
8445
|
}
|
|
8446
|
+
} else if (matchesExistingToolTurn && idx >= 0) {
|
|
8447
|
+
const current = messages[idx];
|
|
8448
|
+
messages[idx] = {
|
|
8449
|
+
...current,
|
|
8450
|
+
reasoning: responseContent ? appendText(current.reasoning, responseContent) : current.reasoning,
|
|
8451
|
+
status: "streaming"
|
|
8452
|
+
};
|
|
8440
8453
|
} else if (prevHasTools || !prevAssistant || hasUserAfter) {
|
|
8441
8454
|
messages.push({
|
|
8442
8455
|
id: `evt-${event.eventId}`,
|
|
@@ -8480,6 +8493,15 @@ function applyLlmResponse(state, event) {
|
|
|
8480
8493
|
}
|
|
8481
8494
|
};
|
|
8482
8495
|
}
|
|
8496
|
+
function toolCallIdsFromResponse(toolCalls) {
|
|
8497
|
+
return toolCalls.map((toolCall) => stringValue2(objectValue(toolCall)?.id)).filter((id) => id.length > 0);
|
|
8498
|
+
}
|
|
8499
|
+
function appendText(existing, addition) {
|
|
8500
|
+
if (!existing) return addition;
|
|
8501
|
+
if (existing.includes(addition)) return existing;
|
|
8502
|
+
return `${existing}
|
|
8503
|
+
${addition}`;
|
|
8504
|
+
}
|
|
8483
8505
|
function applyLlmThinking(state, event) {
|
|
8484
8506
|
const reasoningText = stringValue2(event.data.reasoning) || stringValue2(event.data.content);
|
|
8485
8507
|
const messages = [...state.messages];
|
|
@@ -8773,9 +8795,13 @@ function useAgentChatRuntime({
|
|
|
8773
8795
|
const streamRef = react.useRef(null);
|
|
8774
8796
|
const reconnectTimerRef = react.useRef(null);
|
|
8775
8797
|
const previousSessionIdRef = react.useRef(sessionId);
|
|
8798
|
+
const sessionIdRef = react.useRef(sessionId);
|
|
8776
8799
|
react.useEffect(() => {
|
|
8777
8800
|
stateRef.current = state;
|
|
8778
8801
|
}, [state]);
|
|
8802
|
+
react.useEffect(() => {
|
|
8803
|
+
sessionIdRef.current = sessionId;
|
|
8804
|
+
}, [sessionId]);
|
|
8779
8805
|
const clearReconnectTimer = react.useCallback(() => {
|
|
8780
8806
|
if (reconnectTimerRef.current) {
|
|
8781
8807
|
clearTimeout(reconnectTimerRef.current);
|
|
@@ -8787,21 +8813,10 @@ function useAgentChatRuntime({
|
|
|
8787
8813
|
streamRef.current = null;
|
|
8788
8814
|
stream?.close();
|
|
8789
8815
|
}, []);
|
|
8790
|
-
react.
|
|
8791
|
-
|
|
8792
|
-
previousSessionIdRef.current = sessionId;
|
|
8793
|
-
clearReconnectTimer();
|
|
8794
|
-
closeStream();
|
|
8795
|
-
if (!sessionId) {
|
|
8796
|
-
setSession(null);
|
|
8797
|
-
setState(createInitialAgentChatState());
|
|
8798
|
-
return;
|
|
8799
|
-
}
|
|
8800
|
-
let cancelled = false;
|
|
8801
|
-
const connect = (after) => {
|
|
8802
|
-
if (cancelled) return;
|
|
8816
|
+
const openStream = react.useCallback(
|
|
8817
|
+
(targetSessionId, after) => {
|
|
8803
8818
|
const stream = adapter.openEventStream({
|
|
8804
|
-
sessionId,
|
|
8819
|
+
sessionId: targetSessionId,
|
|
8805
8820
|
after: after ?? stateRef.current.lastEventId
|
|
8806
8821
|
});
|
|
8807
8822
|
streamRef.current = stream;
|
|
@@ -8824,11 +8839,41 @@ function useAgentChatRuntime({
|
|
|
8824
8839
|
if (streamRef.current === stream) {
|
|
8825
8840
|
streamRef.current = null;
|
|
8826
8841
|
}
|
|
8827
|
-
if (!stateRef.current.sessionDone &&
|
|
8828
|
-
reconnectTimerRef.current = setTimeout(
|
|
8842
|
+
if (!stateRef.current.sessionDone && sessionIdRef.current === targetSessionId) {
|
|
8843
|
+
reconnectTimerRef.current = setTimeout(
|
|
8844
|
+
() => openStream(targetSessionId),
|
|
8845
|
+
3e3
|
|
8846
|
+
);
|
|
8829
8847
|
}
|
|
8830
8848
|
};
|
|
8831
|
-
}
|
|
8849
|
+
},
|
|
8850
|
+
[adapter]
|
|
8851
|
+
);
|
|
8852
|
+
const ensureStreamForNewTurn = react.useCallback(
|
|
8853
|
+
(targetSessionId) => {
|
|
8854
|
+
if (streamRef.current && !stateRef.current.sessionDone) return;
|
|
8855
|
+
const after = stateRef.current.lastEventId;
|
|
8856
|
+
clearReconnectTimer();
|
|
8857
|
+
closeStream();
|
|
8858
|
+
stateRef.current = {
|
|
8859
|
+
...stateRef.current,
|
|
8860
|
+
sessionDone: false,
|
|
8861
|
+
terminal: false
|
|
8862
|
+
};
|
|
8863
|
+
openStream(targetSessionId, after);
|
|
8864
|
+
},
|
|
8865
|
+
[clearReconnectTimer, closeStream, openStream]
|
|
8866
|
+
);
|
|
8867
|
+
react.useEffect(() => {
|
|
8868
|
+
const previousSessionId = previousSessionIdRef.current;
|
|
8869
|
+
previousSessionIdRef.current = sessionId;
|
|
8870
|
+
clearReconnectTimer();
|
|
8871
|
+
closeStream();
|
|
8872
|
+
if (!sessionId) {
|
|
8873
|
+
setSession(null);
|
|
8874
|
+
setState(createInitialAgentChatState());
|
|
8875
|
+
return;
|
|
8876
|
+
}
|
|
8832
8877
|
const currentState = stateRef.current;
|
|
8833
8878
|
const preservePendingFirstMessage = previousSessionId === null && currentState.isRunning && currentState.messages.some(
|
|
8834
8879
|
(message) => message.role === "user" && message.id.startsWith("local-")
|
|
@@ -8843,9 +8888,9 @@ function useAgentChatRuntime({
|
|
|
8843
8888
|
stateRef.current = initialState;
|
|
8844
8889
|
setSession(null);
|
|
8845
8890
|
setState(initialState);
|
|
8846
|
-
|
|
8891
|
+
openStream(sessionId, 0);
|
|
8847
8892
|
adapter.getSession({ sessionId }).then((loadedSession) => {
|
|
8848
|
-
if (
|
|
8893
|
+
if (sessionIdRef.current !== sessionId) return;
|
|
8849
8894
|
setSession(loadedSession);
|
|
8850
8895
|
if (loadedSession.messageCount === 0) {
|
|
8851
8896
|
setState((prev) => ({
|
|
@@ -8862,16 +8907,16 @@ function useAgentChatRuntime({
|
|
|
8862
8907
|
}
|
|
8863
8908
|
}).catch(() => void 0);
|
|
8864
8909
|
return () => {
|
|
8865
|
-
cancelled = true;
|
|
8866
8910
|
clearReconnectTimer();
|
|
8867
8911
|
closeStream();
|
|
8868
8912
|
};
|
|
8869
|
-
}, [adapter, clearReconnectTimer, closeStream, sessionId]);
|
|
8913
|
+
}, [adapter, clearReconnectTimer, closeStream, openStream, sessionId]);
|
|
8870
8914
|
const markSending = react.useCallback(
|
|
8871
8915
|
(content, images) => {
|
|
8872
8916
|
setState((prev) => ({
|
|
8873
8917
|
...prev,
|
|
8874
8918
|
terminal: false,
|
|
8919
|
+
sessionDone: false,
|
|
8875
8920
|
isRunning: true,
|
|
8876
8921
|
messages: [
|
|
8877
8922
|
...prev.messages,
|
|
@@ -8952,13 +8997,22 @@ function useAgentChatRuntime({
|
|
|
8952
8997
|
return;
|
|
8953
8998
|
}
|
|
8954
8999
|
try {
|
|
9000
|
+
ensureStreamForNewTurn(sessionId);
|
|
8955
9001
|
await adapter.sendMessage({ sessionId, content, images });
|
|
8956
9002
|
} catch (error) {
|
|
8957
9003
|
markSendError(error instanceof Error ? error.message : "send failed");
|
|
8958
9004
|
throw error;
|
|
8959
9005
|
}
|
|
8960
9006
|
},
|
|
8961
|
-
[
|
|
9007
|
+
[
|
|
9008
|
+
adapter,
|
|
9009
|
+
agentId,
|
|
9010
|
+
ensureStreamForNewTurn,
|
|
9011
|
+
markSendError,
|
|
9012
|
+
markSending,
|
|
9013
|
+
onSessionChange,
|
|
9014
|
+
sessionId
|
|
9015
|
+
]
|
|
8962
9016
|
);
|
|
8963
9017
|
const stop = react.useCallback(async () => {
|
|
8964
9018
|
if (!sessionId) return;
|