@copilotkit/react-core 1.51.3-next.6 → 1.51.3-next.7

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.
Files changed (97) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/dist/chunk-77IVITG3.mjs +158 -0
  3. package/dist/chunk-77IVITG3.mjs.map +1 -0
  4. package/dist/chunk-BKMJ4LC7.mjs +119 -0
  5. package/dist/chunk-BKMJ4LC7.mjs.map +1 -0
  6. package/dist/chunk-C3YJYDK4.mjs +189 -0
  7. package/dist/chunk-C3YJYDK4.mjs.map +1 -0
  8. package/dist/{chunk-GIU66J37.mjs → chunk-DQXCQWSG.mjs} +47 -5
  9. package/dist/chunk-DQXCQWSG.mjs.map +1 -0
  10. package/dist/{chunk-HBMPXNW2.mjs → chunk-LO4RRITI.mjs} +71 -18
  11. package/dist/chunk-LO4RRITI.mjs.map +1 -0
  12. package/dist/{chunk-3G4VFRVV.mjs → chunk-NXHQDCZF.mjs} +2 -2
  13. package/dist/{chunk-FDOMAPJY.mjs → chunk-QD7EID4N.mjs} +1 -1
  14. package/dist/chunk-QD7EID4N.mjs.map +1 -0
  15. package/dist/{chunk-YTQHRJUA.mjs → chunk-VKNLTZJE.mjs} +2 -2
  16. package/dist/{chunk-4RRUJHCI.mjs → chunk-VP43SLSZ.mjs} +2 -2
  17. package/dist/{chunk-MF2ZSLBV.mjs → chunk-XZFIJ7XF.mjs} +2 -2
  18. package/dist/components/copilot-provider/copilotkit.js +437 -150
  19. package/dist/components/copilot-provider/copilotkit.js.map +1 -1
  20. package/dist/components/copilot-provider/copilotkit.mjs +5 -3
  21. package/dist/components/copilot-provider/index.js +437 -150
  22. package/dist/components/copilot-provider/index.js.map +1 -1
  23. package/dist/components/copilot-provider/index.mjs +5 -3
  24. package/dist/components/index.js +437 -150
  25. package/dist/components/index.js.map +1 -1
  26. package/dist/components/index.mjs +5 -3
  27. package/dist/context/coagent-state-renders-context.d.ts +1 -0
  28. package/dist/context/coagent-state-renders-context.js.map +1 -1
  29. package/dist/context/coagent-state-renders-context.mjs +1 -1
  30. package/dist/context/index.js.map +1 -1
  31. package/dist/context/index.mjs +1 -1
  32. package/dist/hooks/index.js +512 -212
  33. package/dist/hooks/index.js.map +1 -1
  34. package/dist/hooks/index.mjs +19 -17
  35. package/dist/hooks/use-coagent-state-render-bridge.helpers.d.ts +92 -0
  36. package/dist/hooks/use-coagent-state-render-bridge.helpers.js +231 -0
  37. package/dist/hooks/use-coagent-state-render-bridge.helpers.js.map +1 -0
  38. package/dist/hooks/use-coagent-state-render-bridge.helpers.mjs +24 -0
  39. package/dist/hooks/use-coagent-state-render-bridge.helpers.mjs.map +1 -0
  40. package/dist/hooks/use-coagent-state-render-bridge.js +334 -72
  41. package/dist/hooks/use-coagent-state-render-bridge.js.map +1 -1
  42. package/dist/hooks/use-coagent-state-render-bridge.mjs +4 -2
  43. package/dist/hooks/use-coagent-state-render-registry.d.ts +25 -0
  44. package/dist/hooks/use-coagent-state-render-registry.js +358 -0
  45. package/dist/hooks/use-coagent-state-render-registry.js.map +1 -0
  46. package/dist/hooks/use-coagent-state-render-registry.mjs +9 -0
  47. package/dist/hooks/use-coagent-state-render-registry.mjs.map +1 -0
  48. package/dist/hooks/use-coagent-state-render.js.map +1 -1
  49. package/dist/hooks/use-coagent-state-render.mjs +2 -2
  50. package/dist/hooks/use-copilot-chat-headless_c.js +414 -114
  51. package/dist/hooks/use-copilot-chat-headless_c.js.map +1 -1
  52. package/dist/hooks/use-copilot-chat-headless_c.mjs +7 -5
  53. package/dist/hooks/use-copilot-chat.js +406 -106
  54. package/dist/hooks/use-copilot-chat.js.map +1 -1
  55. package/dist/hooks/use-copilot-chat.mjs +7 -5
  56. package/dist/hooks/use-copilot-chat_internal.js +406 -106
  57. package/dist/hooks/use-copilot-chat_internal.js.map +1 -1
  58. package/dist/hooks/use-copilot-chat_internal.mjs +6 -4
  59. package/dist/hooks/use-langgraph-interrupt-render.mjs +1 -1
  60. package/dist/index.js +651 -311
  61. package/dist/index.js.map +1 -1
  62. package/dist/index.mjs +22 -20
  63. package/dist/lib/copilot-task.js.map +1 -1
  64. package/dist/lib/copilot-task.mjs +6 -4
  65. package/dist/lib/index.js.map +1 -1
  66. package/dist/lib/index.mjs +6 -4
  67. package/dist/setupTests.js +1 -0
  68. package/dist/setupTests.js.map +1 -1
  69. package/dist/setupTests.mjs +1 -0
  70. package/dist/setupTests.mjs.map +1 -1
  71. package/dist/test-helpers/copilot-context.d.ts +14 -0
  72. package/dist/test-helpers/copilot-context.js +128 -0
  73. package/dist/test-helpers/copilot-context.js.map +1 -0
  74. package/dist/test-helpers/copilot-context.mjs +74 -0
  75. package/dist/test-helpers/copilot-context.mjs.map +1 -0
  76. package/dist/types/index.mjs +1 -1
  77. package/package.json +5 -5
  78. package/src/components/copilot-provider/copilotkit.tsx +56 -0
  79. package/src/context/coagent-state-renders-context.tsx +1 -0
  80. package/src/hooks/__tests__/use-coagent-state-render-bridge.helpers.test.ts +100 -0
  81. package/src/hooks/__tests__/use-coagent-state-render.e2e.test.tsx +892 -37
  82. package/src/hooks/__tests__/use-coagent-state-render.test.tsx +334 -0
  83. package/src/hooks/use-coagent-state-render-bridge.helpers.ts +311 -0
  84. package/src/hooks/use-coagent-state-render-bridge.tsx +25 -120
  85. package/src/hooks/use-coagent-state-render-registry.ts +215 -0
  86. package/src/hooks/use-copilot-chat_internal.ts +93 -34
  87. package/src/setupTests.ts +1 -0
  88. package/src/test-helpers/copilot-context.ts +91 -0
  89. package/dist/chunk-3X3I7OJV.mjs +0 -172
  90. package/dist/chunk-3X3I7OJV.mjs.map +0 -1
  91. package/dist/chunk-FDOMAPJY.mjs.map +0 -1
  92. package/dist/chunk-GIU66J37.mjs.map +0 -1
  93. package/dist/chunk-HBMPXNW2.mjs.map +0 -1
  94. /package/dist/{chunk-3G4VFRVV.mjs.map → chunk-NXHQDCZF.mjs.map} +0 -0
  95. /package/dist/{chunk-YTQHRJUA.mjs.map → chunk-VKNLTZJE.mjs.map} +0 -0
  96. /package/dist/{chunk-4RRUJHCI.mjs.map → chunk-VP43SLSZ.mjs.map} +0 -0
  97. /package/dist/{chunk-MF2ZSLBV.mjs.map → chunk-XZFIJ7XF.mjs.map} +0 -0
@@ -84,7 +84,7 @@ __export(use_copilot_chat_exports, {
84
84
  module.exports = __toCommonJS(use_copilot_chat_exports);
85
85
 
86
86
  // src/hooks/use-copilot-chat_internal.ts
87
- var import_react13 = require("react");
87
+ var import_react14 = require("react");
88
88
 
89
89
  // src/context/copilot-context.tsx
90
90
  var import_react = __toESM(require("react"));
@@ -473,7 +473,7 @@ function useLangGraphInterruptRender(agent) {
473
473
  }
474
474
 
475
475
  // src/hooks/use-copilot-chat_internal.ts
476
- var import_react14 = require("@copilotkitnext/react");
476
+ var import_react15 = require("@copilotkitnext/react");
477
477
 
478
478
  // src/hooks/use-lazy-tool-renderer.tsx
479
479
  var import_react9 = require("@copilotkitnext/react");
@@ -504,8 +504,11 @@ function useLazyToolRenderer() {
504
504
  var import_client = require("@ag-ui/client");
505
505
 
506
506
  // src/hooks/use-coagent-state-render-bridge.tsx
507
- var import_react11 = require("@copilotkitnext/react");
508
- var import_react12 = require("react");
507
+ var import_react12 = require("@copilotkitnext/react");
508
+ var import_react13 = require("react");
509
+ var import_shared4 = require("@copilotkit/shared");
510
+
511
+ // src/hooks/use-coagent-state-render-bridge.helpers.ts
509
512
  var import_shared3 = require("@copilotkit/shared");
510
513
  function getStateWithoutConstantKeys(state) {
511
514
  if (!state)
@@ -528,16 +531,294 @@ function areStatesEquals(a, b) {
528
531
  ]);
529
532
  return JSON.stringify(aWithoutConstantKeys) === JSON.stringify(bWithoutConstantKeys);
530
533
  }
534
+ function isPlaceholderMessageId(messageId) {
535
+ return !!messageId && messageId.startsWith("coagent-state-render-");
536
+ }
537
+ function isPlaceholderMessageName(messageName) {
538
+ return messageName === "coagent-state-render";
539
+ }
540
+ function readCachedMessageEntry(entry) {
541
+ if (!entry || typeof entry !== "object") {
542
+ return { snapshot: entry, runId: void 0 };
543
+ }
544
+ const snapshot = "snapshot" in entry ? entry.snapshot : entry;
545
+ const runId = "runId" in entry ? entry.runId : void 0;
546
+ return { snapshot, runId };
547
+ }
548
+ function getEffectiveRunId({
549
+ existingClaimRunId,
550
+ cachedMessageRunId,
551
+ runId
552
+ }) {
553
+ return existingClaimRunId || cachedMessageRunId || runId || "pending";
554
+ }
555
+ function resolveClaim({
556
+ claims,
557
+ context,
558
+ stateSnapshot
559
+ }) {
560
+ const { messageId, stateRenderId, runId, messageIndex } = context;
561
+ const existing = claims[messageId];
562
+ if (existing) {
563
+ const canRender = existing.stateRenderId === stateRenderId;
564
+ const shouldUpdateRunId = canRender && runId && (!existing.runId || existing.runId === "pending");
565
+ return {
566
+ canRender,
567
+ action: canRender ? "existing" /* Existing */ : "block" /* Block */,
568
+ updateRunId: shouldUpdateRunId ? runId : void 0
569
+ };
570
+ }
571
+ const normalizedRunId = runId != null ? runId : "pending";
572
+ const renderClaimedByOtherMessageEntry = Object.entries(claims).find(
573
+ ([, claim]) => {
574
+ var _a;
575
+ return claim.stateRenderId === stateRenderId && ((_a = claim.runId) != null ? _a : "pending") === normalizedRunId && (0, import_shared3.dataToUUID)(getStateWithoutConstantKeys(claim.stateSnapshot)) === (0, import_shared3.dataToUUID)(getStateWithoutConstantKeys(stateSnapshot));
576
+ }
577
+ );
578
+ const renderClaimedByOtherMessage = renderClaimedByOtherMessageEntry == null ? void 0 : renderClaimedByOtherMessageEntry[1];
579
+ const claimedMessageId = renderClaimedByOtherMessageEntry == null ? void 0 : renderClaimedByOtherMessageEntry[0];
580
+ if (renderClaimedByOtherMessage) {
581
+ if (messageIndex !== void 0 && renderClaimedByOtherMessage.messageIndex !== void 0 && messageIndex > renderClaimedByOtherMessage.messageIndex) {
582
+ return {
583
+ canRender: true,
584
+ action: "override" /* Override */,
585
+ nextClaim: { stateRenderId, runId, messageIndex },
586
+ lockOthers: runId === renderClaimedByOtherMessage.runId || isPlaceholderMessageId(claimedMessageId)
587
+ };
588
+ }
589
+ if (runId && renderClaimedByOtherMessage.runId && runId !== renderClaimedByOtherMessage.runId) {
590
+ return {
591
+ canRender: true,
592
+ action: "override" /* Override */,
593
+ nextClaim: { stateRenderId, runId, messageIndex },
594
+ lockOthers: isPlaceholderMessageId(claimedMessageId)
595
+ };
596
+ }
597
+ if (isPlaceholderMessageId(claimedMessageId)) {
598
+ return {
599
+ canRender: true,
600
+ action: "override" /* Override */,
601
+ nextClaim: { stateRenderId, runId, messageIndex },
602
+ lockOthers: true
603
+ };
604
+ }
605
+ if (stateSnapshot && renderClaimedByOtherMessage.stateSnapshot && !areStatesEquals(renderClaimedByOtherMessage.stateSnapshot, stateSnapshot)) {
606
+ return {
607
+ canRender: true,
608
+ action: "override" /* Override */,
609
+ nextClaim: { stateRenderId, runId }
610
+ };
611
+ }
612
+ return { canRender: false, action: "block" /* Block */ };
613
+ }
614
+ if (!runId) {
615
+ return { canRender: false, action: "block" /* Block */ };
616
+ }
617
+ return {
618
+ canRender: true,
619
+ action: "create" /* Create */,
620
+ nextClaim: { stateRenderId, runId, messageIndex }
621
+ };
622
+ }
623
+ function selectSnapshot({
624
+ messageId,
625
+ messageName,
626
+ allowLiveState,
627
+ skipLatestCache,
628
+ stateRenderId,
629
+ effectiveRunId,
630
+ stateSnapshotProp,
631
+ agentState,
632
+ agentMessages,
633
+ existingClaim,
634
+ caches
635
+ }) {
636
+ var _a, _b, _c, _d, _e, _f;
637
+ const lastAssistantId = agentMessages ? (_a = [...agentMessages].reverse().find((msg) => msg.role === "assistant")) == null ? void 0 : _a.id : void 0;
638
+ const latestSnapshot = stateRenderId !== void 0 ? caches.byStateRenderAndRun[`${stateRenderId}::latest`] : void 0;
639
+ const messageIndex = agentMessages ? agentMessages.findIndex((msg) => msg.id === messageId) : -1;
640
+ const messageRole = messageIndex >= 0 && agentMessages ? (_b = agentMessages[messageIndex]) == null ? void 0 : _b.role : void 0;
641
+ let previousUserMessageId;
642
+ if (messageIndex > 0 && agentMessages) {
643
+ for (let i = messageIndex - 1; i >= 0; i -= 1) {
644
+ if (((_c = agentMessages[i]) == null ? void 0 : _c.role) === "user") {
645
+ previousUserMessageId = (_d = agentMessages[i]) == null ? void 0 : _d.id;
646
+ break;
647
+ }
648
+ }
649
+ }
650
+ const liveStateIsStale = stateSnapshotProp === void 0 && latestSnapshot !== void 0 && agentState !== void 0 && areStatesEquals(latestSnapshot, agentState);
651
+ const shouldUseLiveState = (Boolean(allowLiveState) || !lastAssistantId || messageId === lastAssistantId) && !liveStateIsStale;
652
+ const snapshot = stateSnapshotProp ? (0, import_shared3.parseJson)(stateSnapshotProp, stateSnapshotProp) : shouldUseLiveState ? agentState : void 0;
653
+ const hasSnapshotKeys = !!(snapshot && Object.keys(snapshot).length > 0);
654
+ const allowEmptySnapshot = snapshot !== void 0 && !hasSnapshotKeys && (stateSnapshotProp !== void 0 || shouldUseLiveState);
655
+ const messageCacheEntry = caches.byMessageId[messageId];
656
+ const cachedMessageSnapshot = readCachedMessageEntry(messageCacheEntry).snapshot;
657
+ const cacheKey = stateRenderId !== void 0 ? `${stateRenderId}::${effectiveRunId}` : void 0;
658
+ let cachedSnapshot = cachedMessageSnapshot != null ? cachedMessageSnapshot : caches.byMessageId[messageId];
659
+ if (cachedSnapshot === void 0 && cacheKey && caches.byStateRenderAndRun[cacheKey] !== void 0) {
660
+ cachedSnapshot = caches.byStateRenderAndRun[cacheKey];
661
+ }
662
+ if (cachedSnapshot === void 0 && stateRenderId && previousUserMessageId && caches.byStateRenderAndRun[`${stateRenderId}::pending:${previousUserMessageId}`] !== void 0) {
663
+ cachedSnapshot = caches.byStateRenderAndRun[`${stateRenderId}::pending:${previousUserMessageId}`];
664
+ }
665
+ if (cachedSnapshot === void 0 && !skipLatestCache && stateRenderId && messageRole !== "assistant" && (stateSnapshotProp !== void 0 || agentState && Object.keys(agentState).length > 0)) {
666
+ cachedSnapshot = caches.byStateRenderAndRun[`${stateRenderId}::latest`];
667
+ }
668
+ const snapshotForClaim = (existingClaim == null ? void 0 : existingClaim.locked) ? (_e = existingClaim.stateSnapshot) != null ? _e : cachedSnapshot : hasSnapshotKeys ? snapshot : (_f = existingClaim == null ? void 0 : existingClaim.stateSnapshot) != null ? _f : cachedSnapshot;
669
+ return { snapshot, hasSnapshotKeys, cachedSnapshot, allowEmptySnapshot, snapshotForClaim };
670
+ }
671
+
672
+ // src/hooks/use-coagent-state-render-registry.ts
673
+ var import_react11 = require("react");
674
+ var LAST_SNAPSHOTS_BY_RENDER_AND_RUN = "__lastSnapshotsByStateRenderIdAndRun";
675
+ var LAST_SNAPSHOTS_BY_MESSAGE = "__lastSnapshotsByMessageId";
676
+ function getClaimsStore(claimsRef) {
677
+ return claimsRef.current;
678
+ }
679
+ function getSnapshotCaches(claimsRef) {
680
+ var _a, _b;
681
+ const store = getClaimsStore(claimsRef);
682
+ return {
683
+ byStateRenderAndRun: (_a = store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN]) != null ? _a : {},
684
+ byMessageId: (_b = store[LAST_SNAPSHOTS_BY_MESSAGE]) != null ? _b : {}
685
+ };
686
+ }
687
+ function useStateRenderRegistry({
688
+ agentId,
689
+ stateRenderId,
690
+ message,
691
+ messageIndex,
692
+ stateSnapshot,
693
+ agentState,
694
+ agentMessages,
695
+ claimsRef
696
+ }) {
697
+ var _a, _b, _c, _d, _e, _f;
698
+ const store = getClaimsStore(claimsRef);
699
+ const runId = message.runId;
700
+ const cachedMessageEntry = (_a = store[LAST_SNAPSHOTS_BY_MESSAGE]) == null ? void 0 : _a[message.id];
701
+ const { runId: cachedMessageRunId } = readCachedMessageEntry(cachedMessageEntry);
702
+ const existingClaimRunId = (_b = claimsRef.current[message.id]) == null ? void 0 : _b.runId;
703
+ const effectiveRunId = getEffectiveRunId({
704
+ existingClaimRunId,
705
+ cachedMessageRunId,
706
+ runId
707
+ });
708
+ (0, import_react11.useEffect)(() => {
709
+ return () => {
710
+ var _a2, _b2, _c2, _d2;
711
+ const existingClaim2 = claimsRef.current[message.id];
712
+ if ((existingClaim2 == null ? void 0 : existingClaim2.stateSnapshot) && Object.keys(existingClaim2.stateSnapshot).length > 0) {
713
+ const snapshotCache = __spreadValues({}, (_a2 = store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN]) != null ? _a2 : {});
714
+ const cacheKey = `${existingClaim2.stateRenderId}::${(_b2 = existingClaim2.runId) != null ? _b2 : "pending"}`;
715
+ snapshotCache[cacheKey] = existingClaim2.stateSnapshot;
716
+ snapshotCache[`${existingClaim2.stateRenderId}::latest`] = existingClaim2.stateSnapshot;
717
+ store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN] = snapshotCache;
718
+ const messageCache = __spreadValues({}, (_c2 = store[LAST_SNAPSHOTS_BY_MESSAGE]) != null ? _c2 : {});
719
+ messageCache[message.id] = {
720
+ snapshot: existingClaim2.stateSnapshot,
721
+ runId: (_d2 = existingClaim2.runId) != null ? _d2 : effectiveRunId
722
+ };
723
+ store[LAST_SNAPSHOTS_BY_MESSAGE] = messageCache;
724
+ }
725
+ delete claimsRef.current[message.id];
726
+ };
727
+ }, [claimsRef, effectiveRunId, message.id]);
728
+ if (!stateRenderId) {
729
+ return { canRender: false };
730
+ }
731
+ const caches = getSnapshotCaches(claimsRef);
732
+ const existingClaim = claimsRef.current[message.id];
733
+ const { snapshot, hasSnapshotKeys, allowEmptySnapshot, snapshotForClaim } = selectSnapshot({
734
+ messageId: message.id,
735
+ messageName: message.name,
736
+ allowLiveState: isPlaceholderMessageName(message.name) || isPlaceholderMessageId(message.id),
737
+ skipLatestCache: isPlaceholderMessageName(message.name) || isPlaceholderMessageId(message.id),
738
+ stateRenderId,
739
+ effectiveRunId,
740
+ stateSnapshotProp: stateSnapshot,
741
+ agentState,
742
+ agentMessages,
743
+ existingClaim,
744
+ caches
745
+ });
746
+ const resolution = resolveClaim({
747
+ claims: claimsRef.current,
748
+ context: {
749
+ agentId,
750
+ messageId: message.id,
751
+ stateRenderId,
752
+ runId: effectiveRunId,
753
+ messageIndex
754
+ },
755
+ stateSnapshot: snapshotForClaim
756
+ });
757
+ if (resolution.action === "block" /* Block */) {
758
+ return { canRender: false };
759
+ }
760
+ if (resolution.updateRunId && claimsRef.current[message.id]) {
761
+ claimsRef.current[message.id].runId = resolution.updateRunId;
762
+ }
763
+ if (resolution.nextClaim) {
764
+ claimsRef.current[message.id] = resolution.nextClaim;
765
+ }
766
+ if (resolution.lockOthers) {
767
+ Object.entries(claimsRef.current).forEach(([id, claim]) => {
768
+ if (id !== message.id && claim.stateRenderId === stateRenderId) {
769
+ claim.locked = true;
770
+ }
771
+ });
772
+ }
773
+ if (existingClaim && !existingClaim.locked && (agentMessages == null ? void 0 : agentMessages.length)) {
774
+ const indexInAgentMessages = agentMessages.findIndex((msg) => msg.id === message.id);
775
+ if (indexInAgentMessages >= 0 && indexInAgentMessages < agentMessages.length - 1) {
776
+ existingClaim.locked = true;
777
+ }
778
+ }
779
+ const existingSnapshot = claimsRef.current[message.id].stateSnapshot;
780
+ const snapshotChanged = stateSnapshot && existingSnapshot !== void 0 && !areStatesEquals(existingSnapshot, snapshot);
781
+ if (snapshot && (stateSnapshot || hasSnapshotKeys || allowEmptySnapshot) && (!claimsRef.current[message.id].locked || snapshotChanged)) {
782
+ if (!claimsRef.current[message.id].locked || snapshotChanged) {
783
+ claimsRef.current[message.id].stateSnapshot = snapshot;
784
+ const snapshotCache = __spreadValues({}, (_c = store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN]) != null ? _c : {});
785
+ const cacheKey = `${stateRenderId}::${effectiveRunId}`;
786
+ snapshotCache[cacheKey] = snapshot;
787
+ snapshotCache[`${stateRenderId}::latest`] = snapshot;
788
+ store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN] = snapshotCache;
789
+ const messageCache = __spreadValues({}, (_d = store[LAST_SNAPSHOTS_BY_MESSAGE]) != null ? _d : {});
790
+ messageCache[message.id] = { snapshot, runId: effectiveRunId };
791
+ store[LAST_SNAPSHOTS_BY_MESSAGE] = messageCache;
792
+ if (stateSnapshot) {
793
+ claimsRef.current[message.id].locked = true;
794
+ }
795
+ }
796
+ } else if (snapshotForClaim) {
797
+ const existingSnapshot2 = claimsRef.current[message.id].stateSnapshot;
798
+ if (!existingSnapshot2) {
799
+ claimsRef.current[message.id].stateSnapshot = snapshotForClaim;
800
+ const snapshotCache = __spreadValues({}, (_e = store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN]) != null ? _e : {});
801
+ const cacheKey = `${stateRenderId}::${effectiveRunId}`;
802
+ snapshotCache[cacheKey] = snapshotForClaim;
803
+ snapshotCache[`${stateRenderId}::latest`] = snapshotForClaim;
804
+ store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN] = snapshotCache;
805
+ const messageCache = __spreadValues({}, (_f = store[LAST_SNAPSHOTS_BY_MESSAGE]) != null ? _f : {});
806
+ messageCache[message.id] = { snapshot: snapshotForClaim, runId: effectiveRunId };
807
+ store[LAST_SNAPSHOTS_BY_MESSAGE] = messageCache;
808
+ }
809
+ }
810
+ return { canRender: true };
811
+ }
812
+
813
+ // src/hooks/use-coagent-state-render-bridge.tsx
531
814
  function useCoagentStateRenderBridge(agentId, props) {
532
815
  var _a;
533
- const { stateSnapshot, messageIndexInRun, message } = props;
816
+ const { stateSnapshot, message } = props;
534
817
  const { coAgentStateRenders, claimsRef } = useCoAgentStateRenders();
535
- const { agent } = (0, import_react11.useAgent)({ agentId });
536
- const [nodeName, setNodeName] = (0, import_react12.useState)(void 0);
537
- const [, forceUpdate] = (0, import_react12.useState)(0);
538
- const runId = (_a = props.runId) != null ? _a : message.runId;
539
- const effectiveRunId = runId || "pending";
540
- (0, import_react12.useEffect)(() => {
818
+ const { agent } = (0, import_react12.useAgent)({ agentId });
819
+ const [nodeName, setNodeName] = (0, import_react13.useState)(void 0);
820
+ const [, forceUpdate] = (0, import_react13.useState)(0);
821
+ (0, import_react13.useEffect)(() => {
541
822
  if (!agent)
542
823
  return;
543
824
  const subscriber = {
@@ -560,103 +841,69 @@ function useCoagentStateRenderBridge(agentId, props) {
560
841
  unsubscribe();
561
842
  };
562
843
  }, [agentId, nodeName]);
563
- const getStateRender = (0, import_react12.useCallback)(
844
+ const getStateRender = (0, import_react13.useCallback)(
564
845
  (messageId) => {
565
- return Object.entries(coAgentStateRenders).find(([stateRenderId, stateRender]) => {
846
+ return Object.entries(coAgentStateRenders).find(([stateRenderId2, stateRender2]) => {
566
847
  if (claimsRef.current[messageId]) {
567
- return stateRenderId === claimsRef.current[messageId].stateRenderId;
848
+ return stateRenderId2 === claimsRef.current[messageId].stateRenderId;
568
849
  }
569
- const matchingAgentName = stateRender.name === agentId;
570
- const matchesNodeContext = stateRender.nodeName ? stateRender.nodeName === nodeName : true;
850
+ const matchingAgentName = stateRender2.name === agentId;
851
+ const matchesNodeContext = stateRender2.nodeName ? stateRender2.nodeName === nodeName : true;
571
852
  return matchingAgentName && matchesNodeContext;
572
853
  });
573
854
  },
574
855
  [coAgentStateRenders, nodeName, agentId]
575
856
  );
576
- const handleRenderRequest = ({
857
+ const stateRenderEntry = (0, import_react13.useMemo)(() => getStateRender(message.id), [getStateRender, message.id]);
858
+ const stateRenderId = stateRenderEntry == null ? void 0 : stateRenderEntry[0];
859
+ const stateRender = stateRenderEntry == null ? void 0 : stateRenderEntry[1];
860
+ const registryMessage = __spreadProps(__spreadValues({}, message), {
861
+ runId: (_a = props.runId) != null ? _a : message.runId
862
+ });
863
+ const { canRender } = useStateRenderRegistry({
864
+ agentId,
577
865
  stateRenderId,
578
- messageId,
579
- runId: runId2,
580
- stateSnapshot: renderSnapshot
581
- }) => {
582
- if (claimsRef.current[messageId]) {
583
- const canRender = claimsRef.current[messageId].stateRenderId === stateRenderId;
584
- if (canRender && runId2 && (!claimsRef.current[messageId].runId || claimsRef.current[messageId].runId === "pending")) {
585
- claimsRef.current[messageId].runId = runId2;
586
- }
587
- return canRender;
588
- }
589
- const renderClaimedByOtherMessage = Object.values(claimsRef.current).find(
590
- (c) => c.stateRenderId === stateRenderId && (0, import_shared3.dataToUUID)(getStateWithoutConstantKeys(c.stateSnapshot)) === (0, import_shared3.dataToUUID)(getStateWithoutConstantKeys(renderSnapshot))
591
- );
592
- if (renderClaimedByOtherMessage) {
593
- if (renderSnapshot && renderClaimedByOtherMessage.stateSnapshot && !areStatesEquals(renderClaimedByOtherMessage.stateSnapshot, renderSnapshot)) {
594
- claimsRef.current[messageId] = { stateRenderId, runId: runId2 };
595
- return true;
596
- }
597
- return false;
598
- }
599
- if (!runId2) {
600
- return false;
601
- }
602
- claimsRef.current[messageId] = { stateRenderId, runId: runId2 };
603
- return true;
604
- };
605
- return (0, import_react12.useMemo)(() => {
606
- var _a2, _b, _c;
607
- if (messageIndexInRun !== 0) {
608
- return null;
609
- }
610
- const [stateRenderId, stateRender] = (_a2 = getStateRender(message.id)) != null ? _a2 : [];
866
+ message: registryMessage,
867
+ messageIndex: props.messageIndex,
868
+ stateSnapshot,
869
+ agentState: agent == null ? void 0 : agent.state,
870
+ agentMessages: agent == null ? void 0 : agent.messages,
871
+ claimsRef
872
+ });
873
+ return (0, import_react13.useMemo)(() => {
874
+ var _a2, _b;
611
875
  if (!stateRender || !stateRenderId) {
612
876
  return null;
613
877
  }
614
- const snapshot = stateSnapshot ? (0, import_shared3.parseJson)(stateSnapshot, stateSnapshot) : agent == null ? void 0 : agent.state;
615
- const canRender = handleRenderRequest({
616
- stateRenderId,
617
- messageId: message.id,
618
- runId: effectiveRunId,
619
- stateSnapshot: snapshot
620
- });
621
878
  if (!canRender) {
622
879
  return null;
623
880
  }
624
- if (snapshot) {
625
- const existingSnapshot = claimsRef.current[message.id].stateSnapshot;
626
- const snapshotChanged = stateSnapshot && existingSnapshot !== void 0 && !areStatesEquals(existingSnapshot, snapshot);
627
- if (!claimsRef.current[message.id].locked || snapshotChanged) {
628
- claimsRef.current[message.id].stateSnapshot = snapshot;
629
- if (stateSnapshot) {
630
- claimsRef.current[message.id].locked = true;
631
- }
632
- }
633
- }
634
881
  if (stateRender.handler) {
635
882
  stateRender.handler({
636
- state: stateSnapshot ? (0, import_shared3.parseJson)(stateSnapshot, stateSnapshot) : (_b = agent == null ? void 0 : agent.state) != null ? _b : {},
883
+ state: stateSnapshot ? (0, import_shared4.parseJson)(stateSnapshot, stateSnapshot) : (_a2 = agent == null ? void 0 : agent.state) != null ? _a2 : {},
637
884
  nodeName: nodeName != null ? nodeName : ""
638
885
  });
639
886
  }
640
887
  if (stateRender.render) {
641
- const status = (agent == null ? void 0 : agent.isRunning) ? "inProgress" : "complete";
888
+ const status = (agent == null ? void 0 : agent.isRunning) ? "inProgress" /* InProgress */ : "complete" /* Complete */;
642
889
  if (typeof stateRender.render === "string")
643
890
  return stateRender.render;
644
891
  return stateRender.render({
645
892
  status,
646
893
  // Always use state from claim, to make sure the state does not seem "wiped" for a fraction of a second
647
- state: (_c = claimsRef.current[message.id].stateSnapshot) != null ? _c : {},
894
+ state: (_b = claimsRef.current[message.id].stateSnapshot) != null ? _b : {},
648
895
  nodeName: nodeName != null ? nodeName : ""
649
896
  });
650
897
  }
651
898
  }, [
652
- getStateRender,
653
- stateSnapshot,
899
+ stateRender,
900
+ stateRenderId,
654
901
  agent == null ? void 0 : agent.state,
655
902
  agent == null ? void 0 : agent.isRunning,
656
903
  nodeName,
657
- effectiveRunId,
658
904
  message.id,
659
- messageIndexInRun
905
+ stateSnapshot,
906
+ canRender
660
907
  ]);
661
908
  }
662
909
  function CoAgentStateRenderBridge(props) {
@@ -672,13 +919,13 @@ function useCopilotChatInternal({
672
919
  onReloadMessages
673
920
  } = {}) {
674
921
  var _a, _b, _c;
675
- const { copilotkit } = (0, import_react14.useCopilotKit)();
922
+ const { copilotkit } = (0, import_react15.useCopilotKit)();
676
923
  const { threadId, agentSession } = useCopilotContext();
677
- const existingConfig = (0, import_react14.useCopilotChatConfiguration)();
678
- const [agentAvailable, setAgentAvailable] = (0, import_react13.useState)(false);
924
+ const existingConfig = (0, import_react15.useCopilotChatConfiguration)();
925
+ const [agentAvailable, setAgentAvailable] = (0, import_react14.useState)(false);
679
926
  const resolvedAgentId = (_a = existingConfig == null ? void 0 : existingConfig.agentId) != null ? _a : "default";
680
- const { agent } = (0, import_react14.useAgent)({ agentId: resolvedAgentId });
681
- (0, import_react13.useEffect)(() => {
927
+ const { agent } = (0, import_react15.useAgent)({ agentId: resolvedAgentId });
928
+ (0, import_react14.useEffect)(() => {
682
929
  const connect = (agent2) => __async(this, null, function* () {
683
930
  setAgentAvailable(false);
684
931
  try {
@@ -687,7 +934,7 @@ function useCopilotChatInternal({
687
934
  } catch (error) {
688
935
  if (error instanceof import_client.AGUIConnectNotImplementedError) {
689
936
  } else {
690
- throw error;
937
+ console.error("CopilotChat: connectAgent failed", error);
691
938
  }
692
939
  }
693
940
  });
@@ -698,7 +945,7 @@ function useCopilotChatInternal({
698
945
  return () => {
699
946
  };
700
947
  }, [existingConfig == null ? void 0 : existingConfig.threadId, agent, copilotkit, resolvedAgentId]);
701
- (0, import_react13.useEffect)(() => {
948
+ (0, import_react14.useEffect)(() => {
702
949
  onInProgress == null ? void 0 : onInProgress(Boolean(agent == null ? void 0 : agent.isRunning));
703
950
  }, [agent == null ? void 0 : agent.isRunning, onInProgress]);
704
951
  const interrupt = useLangGraphInterruptRender(agent);
@@ -706,7 +953,7 @@ function useCopilotChatInternal({
706
953
  agent == null ? void 0 : agent.setMessages([]);
707
954
  agent == null ? void 0 : agent.setState(null);
708
955
  };
709
- const deleteMessage = (0, import_react13.useCallback)(
956
+ const deleteMessage = (0, import_react14.useCallback)(
710
957
  (messageId) => {
711
958
  var _a2;
712
959
  const filteredMessages = ((_a2 = agent == null ? void 0 : agent.messages) != null ? _a2 : []).filter(
@@ -717,13 +964,13 @@ function useCopilotChatInternal({
717
964
  [agent == null ? void 0 : agent.setMessages, agent == null ? void 0 : agent.messages]
718
965
  );
719
966
  const latestDelete = useUpdatedRef(deleteMessage);
720
- const latestDeleteFunc = (0, import_react13.useCallback)(
967
+ const latestDeleteFunc = (0, import_react14.useCallback)(
721
968
  (messageId) => {
722
969
  return latestDelete.current(messageId);
723
970
  },
724
971
  [latestDelete]
725
972
  );
726
- const currentSuggestions = (0, import_react14.useSuggestions)({ agentId: resolvedAgentId });
973
+ const currentSuggestions = (0, import_react15.useSuggestions)({ agentId: resolvedAgentId });
727
974
  const reload = useAsyncCallback(
728
975
  (reloadMessageId) => __async(this, null, function* () {
729
976
  var _a2;
@@ -758,7 +1005,11 @@ function useCopilotChatInternal({
758
1005
  }
759
1006
  agent == null ? void 0 : agent.setMessages(historyCutoff);
760
1007
  if (agent) {
761
- copilotkit.runAgent({ agent });
1008
+ try {
1009
+ yield copilotkit.runAgent({ agent });
1010
+ } catch (error) {
1011
+ console.error("CopilotChat: runAgent failed during reload", error);
1012
+ }
762
1013
  }
763
1014
  return;
764
1015
  }),
@@ -798,7 +1049,7 @@ function useCopilotChatInternal({
798
1049
  }),
799
1050
  [latestSendMessageFunc]
800
1051
  );
801
- const latestSetMessagesFunc = (0, import_react13.useCallback)(
1052
+ const latestSetMessagesFunc = (0, import_react14.useCallback)(
802
1053
  (messages) => {
803
1054
  var _a2, _b2;
804
1055
  if (messages.every((message) => message instanceof import_runtime_client_gql2.Message)) {
@@ -821,7 +1072,7 @@ function useCopilotChatInternal({
821
1072
  }),
822
1073
  [latestReload, agent, onReloadMessages]
823
1074
  );
824
- const latestStopFunc = (0, import_react13.useCallback)(() => {
1075
+ const latestStopFunc = (0, import_react14.useCallback)(() => {
825
1076
  var _a2, _b2;
826
1077
  onStopGeneration == null ? void 0 : onStopGeneration({
827
1078
  currentAgentName: agent == null ? void 0 : agent.agentId,
@@ -830,11 +1081,11 @@ function useCopilotChatInternal({
830
1081
  return (_b2 = agent == null ? void 0 : agent.abortRun) == null ? void 0 : _b2.call(agent);
831
1082
  }, [onStopGeneration, agent]);
832
1083
  const latestReset = useUpdatedRef(reset);
833
- const latestResetFunc = (0, import_react13.useCallback)(() => {
1084
+ const latestResetFunc = (0, import_react14.useCallback)(() => {
834
1085
  return latestReset.current();
835
1086
  }, [latestReset]);
836
1087
  const lazyToolRendered = useLazyToolRenderer();
837
- const renderCustomMessage = (0, import_react14.useRenderCustomMessages)();
1088
+ const renderCustomMessage = (0, import_react15.useRenderCustomMessages)();
838
1089
  const legacyCustomMessageRenderer = useLegacyCoagentRenderer({
839
1090
  copilotkit,
840
1091
  agent,
@@ -842,7 +1093,8 @@ function useCopilotChatInternal({
842
1093
  threadId: (_b = existingConfig == null ? void 0 : existingConfig.threadId) != null ? _b : threadId
843
1094
  });
844
1095
  const allMessages = (_c = agent == null ? void 0 : agent.messages) != null ? _c : [];
845
- const resolvedMessages = (0, import_react13.useMemo)(() => {
1096
+ const resolvedMessages = (0, import_react14.useMemo)(() => {
1097
+ var _a2, _b2;
846
1098
  let processedMessages = allMessages.map((message) => {
847
1099
  if (message.role !== "assistant") {
848
1100
  return message;
@@ -855,31 +1107,78 @@ function useCopilotChatInternal({
855
1107
  }
856
1108
  }
857
1109
  const bridgeRenderer = legacyCustomMessageRenderer || renderCustomMessage ? () => {
858
- const customRender = renderCustomMessage == null ? void 0 : renderCustomMessage({
859
- message,
860
- position: "before"
861
- });
862
- if (customRender) {
863
- return customRender;
1110
+ var _a3;
1111
+ if (legacyCustomMessageRenderer) {
1112
+ return legacyCustomMessageRenderer({ message, position: "before" });
1113
+ }
1114
+ try {
1115
+ return (_a3 = renderCustomMessage == null ? void 0 : renderCustomMessage({ message, position: "before" })) != null ? _a3 : null;
1116
+ } catch (error) {
1117
+ console.warn(
1118
+ "[CopilotKit] renderCustomMessages failed, falling back to legacy renderer",
1119
+ error
1120
+ );
1121
+ return null;
864
1122
  }
865
- return legacyCustomMessageRenderer == null ? void 0 : legacyCustomMessageRenderer({ message, position: "before" });
866
1123
  } : null;
867
1124
  if (bridgeRenderer) {
868
- return __spreadProps(__spreadValues({}, message), { generativeUI: bridgeRenderer });
1125
+ return __spreadProps(__spreadValues({}, message), {
1126
+ generativeUI: bridgeRenderer,
1127
+ generativeUIPosition: "before"
1128
+ });
869
1129
  }
870
1130
  return message;
871
1131
  });
872
1132
  const hasAssistantMessages = processedMessages.some((msg) => msg.role === "assistant");
1133
+ const canUseCustomRenderer = Boolean(
1134
+ renderCustomMessage && ((_a2 = copilotkit == null ? void 0 : copilotkit.getAgent) == null ? void 0 : _a2.call(copilotkit, resolvedAgentId))
1135
+ );
1136
+ const placeholderRenderer = legacyCustomMessageRenderer ? legacyCustomMessageRenderer : canUseCustomRenderer ? renderCustomMessage : null;
1137
+ const shouldRenderPlaceholder = Boolean(agent == null ? void 0 : agent.isRunning) || Boolean((agent == null ? void 0 : agent.state) && Object.keys(agent.state).length);
1138
+ const effectiveThreadId = (_b2 = threadId != null ? threadId : agent == null ? void 0 : agent.threadId) != null ? _b2 : "default";
1139
+ let latestUserIndex = -1;
1140
+ for (let i = processedMessages.length - 1; i >= 0; i -= 1) {
1141
+ if (processedMessages[i].role === "user") {
1142
+ latestUserIndex = i;
1143
+ break;
1144
+ }
1145
+ }
1146
+ const latestUserMessageId = latestUserIndex >= 0 ? processedMessages[latestUserIndex].id : void 0;
1147
+ const currentRunId = latestUserMessageId ? copilotkit.getRunIdForMessage(resolvedAgentId, effectiveThreadId, latestUserMessageId) || `pending:${latestUserMessageId}` : void 0;
1148
+ const hasAssistantForCurrentRun = latestUserIndex >= 0 ? processedMessages.slice(latestUserIndex + 1).some((msg) => msg.role === "assistant") : hasAssistantMessages;
1149
+ if (placeholderRenderer && shouldRenderPlaceholder && !hasAssistantForCurrentRun) {
1150
+ const placeholderId = currentRunId ? `coagent-state-render-${resolvedAgentId}-${currentRunId}` : `coagent-state-render-${resolvedAgentId}`;
1151
+ const placeholderMessage = {
1152
+ id: placeholderId,
1153
+ role: "assistant",
1154
+ content: "",
1155
+ name: "coagent-state-render",
1156
+ runId: currentRunId
1157
+ };
1158
+ processedMessages = [
1159
+ ...processedMessages,
1160
+ __spreadProps(__spreadValues({}, placeholderMessage), {
1161
+ generativeUIPosition: "before",
1162
+ generativeUI: () => placeholderRenderer({
1163
+ message: placeholderMessage,
1164
+ position: "before"
1165
+ })
1166
+ })
1167
+ ];
1168
+ }
873
1169
  return processedMessages;
874
1170
  }, [
875
1171
  agent == null ? void 0 : agent.messages,
876
1172
  lazyToolRendered,
877
1173
  allMessages,
878
1174
  renderCustomMessage,
879
- // legacyCustomMessageRenderer,
880
- resolvedAgentId
1175
+ legacyCustomMessageRenderer,
1176
+ resolvedAgentId,
1177
+ copilotkit,
1178
+ agent == null ? void 0 : agent.isRunning,
1179
+ agent == null ? void 0 : agent.state
881
1180
  ]);
882
- const renderedSuggestions = (0, import_react13.useMemo)(() => {
1181
+ const renderedSuggestions = (0, import_react14.useMemo)(() => {
883
1182
  if (Array.isArray(suggestions)) {
884
1183
  return {
885
1184
  suggestions: suggestions.map((s) => __spreadProps(__spreadValues({}, s), { isLoading: false })),
@@ -914,8 +1213,8 @@ function useCopilotChatInternal({
914
1213
  };
915
1214
  }
916
1215
  function useUpdatedRef(value) {
917
- const ref = (0, import_react13.useRef)(value);
918
- (0, import_react13.useEffect)(() => {
1216
+ const ref = (0, import_react14.useRef)(value);
1217
+ (0, import_react14.useEffect)(() => {
919
1218
  ref.current = value;
920
1219
  }, [value]);
921
1220
  return ref;
@@ -926,14 +1225,15 @@ function useLegacyCoagentRenderer({
926
1225
  agentId,
927
1226
  threadId
928
1227
  }) {
929
- return (0, import_react13.useMemo)(() => {
1228
+ return (0, import_react14.useMemo)(() => {
930
1229
  if (!copilotkit || !agent) {
931
1230
  return null;
932
1231
  }
933
1232
  return ({ message, position }) => {
934
1233
  var _a;
935
1234
  const effectiveThreadId = (_a = threadId != null ? threadId : agent.threadId) != null ? _a : "default";
936
- const existingRunId = copilotkit.getRunIdForMessage(agentId, effectiveThreadId, message.id);
1235
+ const providedRunId = message.runId;
1236
+ const existingRunId = providedRunId ? providedRunId : copilotkit.getRunIdForMessage(agentId, effectiveThreadId, message.id);
937
1237
  const runId = existingRunId || `pending:${message.id}`;
938
1238
  const messageIndex = Math.max(
939
1239
  agent.messages.findIndex((msg) => msg.id === message.id),
@@ -949,7 +1249,7 @@ function useLegacyCoagentRenderer({
949
1249
  agentId,
950
1250
  stateSnapshot: message.state
951
1251
  };
952
- return (0, import_react13.createElement)(CoAgentStateRenderBridge, bridgeProps);
1252
+ return (0, import_react14.createElement)(CoAgentStateRenderBridge, bridgeProps);
953
1253
  };
954
1254
  }, [agent, agentId, copilotkit, threadId]);
955
1255
  }