@springbrand/chat-client 0.1.3-alpha.46 → 0.1.3-alpha.47

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@springbrand/chat-client",
3
- "version": "0.1.3-alpha.46",
3
+ "version": "0.1.3-alpha.47",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "src",
@@ -27,7 +27,7 @@
27
27
  "@types/react-dom": "^19.2.5",
28
28
  "react-dom": "^19.2.8",
29
29
  "typescript": "^7.0.2",
30
- "@springbrand/agent-runtime": "0.2.0-alpha.62"
30
+ "@springbrand/agent-runtime": "0.2.0-alpha.63"
31
31
  },
32
32
  "scripts": {
33
33
  "typecheck": "tsc --noEmit"
@@ -539,34 +539,46 @@ export function useUniversalAgentChat(): ChatRuntime {
539
539
  : authoritativeStatus;
540
540
  const messagesRef = useRef(messages);
541
541
  messagesRef.current = messages;
542
- const replayFallbackMessageIdRef = useRef<string | undefined>(undefined);
542
+ // SDK callback identities can change without a new recovery request.
543
+ const replayActionsRef = useRef({ setMessages, clearError });
544
+ replayActionsRef.current = { setMessages, clearError };
543
545
  useEffect(() => {
544
546
  const activeMessageId = facetState?.turn?.activeMessageId;
545
547
  if (
546
548
  !activeMessageId ||
547
549
  sdkStatus !== "error" ||
548
550
  sdkIsRecovering ||
549
- isServerStreaming ||
550
- replayFallbackMessageIdRef.current === activeMessageId
551
+ isServerStreaming
551
552
  ) return;
552
553
  const url = chatAgent.getHttpUrl();
553
554
  if (!url) return;
554
- replayFallbackMessageIdRef.current = activeMessageId;
555
+ const baseline = messagesRef.current;
556
+ let cancelled = false;
555
557
  void loadInitialMessages(url, connection.credentials, "full")
556
558
  .then((snapshot) => {
557
- setMessages(snapshot);
558
- clearError();
559
+ if (cancelled) return;
560
+ // The SDK protects its own snapshots while streaming. This HTTP
561
+ // fallback must also reject a response older than the current store.
562
+ const actions = replayActionsRef.current;
563
+ let applied = false;
564
+ actions.setMessages((current) => {
565
+ if (current !== baseline) return current;
566
+ applied = true;
567
+ return snapshot;
568
+ });
569
+ if (applied) actions.clearError();
559
570
  })
560
571
  .catch(() => undefined);
572
+ return () => {
573
+ cancelled = true;
574
+ };
561
575
  }, [
562
576
  chatAgent,
563
- clearError,
564
577
  connection.credentials,
565
578
  facetState?.turn?.activeMessageId,
566
579
  isServerStreaming,
567
580
  sdkIsRecovering,
568
581
  sdkStatus,
569
- setMessages,
570
582
  ]);
571
583
  const turnTimingRef = useRef<ChatTurnTiming | null>(null);
572
584
 
@@ -762,7 +774,7 @@ export function useUniversalAgentChat(): ChatRuntime {
762
774
  markChatTurnPhase(turnTimingRef.current, "rpcReceipt");
763
775
  }
764
776
  if (receipt.kind === "rejected") {
765
- if (projection === "queue") rollback();
777
+ rollback();
766
778
  if (turnTimingRef.current?.messageId === message.id) {
767
779
  turnTimingRef.current = null;
768
780
  }
@@ -830,7 +842,7 @@ export function useUniversalAgentChat(): ChatRuntime {
830
842
  }
831
843
  return true;
832
844
  } catch (cause) {
833
- if (projection === "queue") rollback();
845
+ rollback();
834
846
  if (turnTimingRef.current?.messageId === message.id) {
835
847
  turnTimingRef.current = null;
836
848
  }