@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
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # ui
2
2
 
3
+ ## 1.51.3-next.7
4
+
5
+ ### Patch Changes
6
+
7
+ - 3f00a01: Fix issue causing onSubmitMessage to fire after agent response
8
+ - @copilotkit/runtime-client-gql@1.51.3-next.7
9
+ - @copilotkit/shared@1.51.3-next.7
10
+ - @copilotkitnext/core@1.51.3-next.7
11
+ - @copilotkitnext/react@1.51.3-next.7
12
+
3
13
  ## 1.51.3-next.6
4
14
 
5
15
  ### Patch Changes
@@ -0,0 +1,158 @@
1
+ import {
2
+ areStatesEquals,
3
+ getEffectiveRunId,
4
+ isPlaceholderMessageId,
5
+ isPlaceholderMessageName,
6
+ readCachedMessageEntry,
7
+ resolveClaim,
8
+ selectSnapshot
9
+ } from "./chunk-C3YJYDK4.mjs";
10
+ import {
11
+ __spreadValues
12
+ } from "./chunk-SKC7AJIV.mjs";
13
+
14
+ // src/hooks/use-coagent-state-render-registry.ts
15
+ import { useEffect } from "react";
16
+ var LAST_SNAPSHOTS_BY_RENDER_AND_RUN = "__lastSnapshotsByStateRenderIdAndRun";
17
+ var LAST_SNAPSHOTS_BY_MESSAGE = "__lastSnapshotsByMessageId";
18
+ function getClaimsStore(claimsRef) {
19
+ return claimsRef.current;
20
+ }
21
+ function getSnapshotCaches(claimsRef) {
22
+ var _a, _b;
23
+ const store = getClaimsStore(claimsRef);
24
+ return {
25
+ byStateRenderAndRun: (_a = store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN]) != null ? _a : {},
26
+ byMessageId: (_b = store[LAST_SNAPSHOTS_BY_MESSAGE]) != null ? _b : {}
27
+ };
28
+ }
29
+ function useStateRenderRegistry({
30
+ agentId,
31
+ stateRenderId,
32
+ message,
33
+ messageIndex,
34
+ stateSnapshot,
35
+ agentState,
36
+ agentMessages,
37
+ claimsRef
38
+ }) {
39
+ var _a, _b, _c, _d, _e, _f;
40
+ const store = getClaimsStore(claimsRef);
41
+ const runId = message.runId;
42
+ const cachedMessageEntry = (_a = store[LAST_SNAPSHOTS_BY_MESSAGE]) == null ? void 0 : _a[message.id];
43
+ const { runId: cachedMessageRunId } = readCachedMessageEntry(cachedMessageEntry);
44
+ const existingClaimRunId = (_b = claimsRef.current[message.id]) == null ? void 0 : _b.runId;
45
+ const effectiveRunId = getEffectiveRunId({
46
+ existingClaimRunId,
47
+ cachedMessageRunId,
48
+ runId
49
+ });
50
+ useEffect(() => {
51
+ return () => {
52
+ var _a2, _b2, _c2, _d2;
53
+ const existingClaim2 = claimsRef.current[message.id];
54
+ if ((existingClaim2 == null ? void 0 : existingClaim2.stateSnapshot) && Object.keys(existingClaim2.stateSnapshot).length > 0) {
55
+ const snapshotCache = __spreadValues({}, (_a2 = store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN]) != null ? _a2 : {});
56
+ const cacheKey = `${existingClaim2.stateRenderId}::${(_b2 = existingClaim2.runId) != null ? _b2 : "pending"}`;
57
+ snapshotCache[cacheKey] = existingClaim2.stateSnapshot;
58
+ snapshotCache[`${existingClaim2.stateRenderId}::latest`] = existingClaim2.stateSnapshot;
59
+ store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN] = snapshotCache;
60
+ const messageCache = __spreadValues({}, (_c2 = store[LAST_SNAPSHOTS_BY_MESSAGE]) != null ? _c2 : {});
61
+ messageCache[message.id] = {
62
+ snapshot: existingClaim2.stateSnapshot,
63
+ runId: (_d2 = existingClaim2.runId) != null ? _d2 : effectiveRunId
64
+ };
65
+ store[LAST_SNAPSHOTS_BY_MESSAGE] = messageCache;
66
+ }
67
+ delete claimsRef.current[message.id];
68
+ };
69
+ }, [claimsRef, effectiveRunId, message.id]);
70
+ if (!stateRenderId) {
71
+ return { canRender: false };
72
+ }
73
+ const caches = getSnapshotCaches(claimsRef);
74
+ const existingClaim = claimsRef.current[message.id];
75
+ const { snapshot, hasSnapshotKeys, allowEmptySnapshot, snapshotForClaim } = selectSnapshot({
76
+ messageId: message.id,
77
+ messageName: message.name,
78
+ allowLiveState: isPlaceholderMessageName(message.name) || isPlaceholderMessageId(message.id),
79
+ skipLatestCache: isPlaceholderMessageName(message.name) || isPlaceholderMessageId(message.id),
80
+ stateRenderId,
81
+ effectiveRunId,
82
+ stateSnapshotProp: stateSnapshot,
83
+ agentState,
84
+ agentMessages,
85
+ existingClaim,
86
+ caches
87
+ });
88
+ const resolution = resolveClaim({
89
+ claims: claimsRef.current,
90
+ context: {
91
+ agentId,
92
+ messageId: message.id,
93
+ stateRenderId,
94
+ runId: effectiveRunId,
95
+ messageIndex
96
+ },
97
+ stateSnapshot: snapshotForClaim
98
+ });
99
+ if (resolution.action === "block" /* Block */) {
100
+ return { canRender: false };
101
+ }
102
+ if (resolution.updateRunId && claimsRef.current[message.id]) {
103
+ claimsRef.current[message.id].runId = resolution.updateRunId;
104
+ }
105
+ if (resolution.nextClaim) {
106
+ claimsRef.current[message.id] = resolution.nextClaim;
107
+ }
108
+ if (resolution.lockOthers) {
109
+ Object.entries(claimsRef.current).forEach(([id, claim]) => {
110
+ if (id !== message.id && claim.stateRenderId === stateRenderId) {
111
+ claim.locked = true;
112
+ }
113
+ });
114
+ }
115
+ if (existingClaim && !existingClaim.locked && (agentMessages == null ? void 0 : agentMessages.length)) {
116
+ const indexInAgentMessages = agentMessages.findIndex((msg) => msg.id === message.id);
117
+ if (indexInAgentMessages >= 0 && indexInAgentMessages < agentMessages.length - 1) {
118
+ existingClaim.locked = true;
119
+ }
120
+ }
121
+ const existingSnapshot = claimsRef.current[message.id].stateSnapshot;
122
+ const snapshotChanged = stateSnapshot && existingSnapshot !== void 0 && !areStatesEquals(existingSnapshot, snapshot);
123
+ if (snapshot && (stateSnapshot || hasSnapshotKeys || allowEmptySnapshot) && (!claimsRef.current[message.id].locked || snapshotChanged)) {
124
+ if (!claimsRef.current[message.id].locked || snapshotChanged) {
125
+ claimsRef.current[message.id].stateSnapshot = snapshot;
126
+ const snapshotCache = __spreadValues({}, (_c = store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN]) != null ? _c : {});
127
+ const cacheKey = `${stateRenderId}::${effectiveRunId}`;
128
+ snapshotCache[cacheKey] = snapshot;
129
+ snapshotCache[`${stateRenderId}::latest`] = snapshot;
130
+ store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN] = snapshotCache;
131
+ const messageCache = __spreadValues({}, (_d = store[LAST_SNAPSHOTS_BY_MESSAGE]) != null ? _d : {});
132
+ messageCache[message.id] = { snapshot, runId: effectiveRunId };
133
+ store[LAST_SNAPSHOTS_BY_MESSAGE] = messageCache;
134
+ if (stateSnapshot) {
135
+ claimsRef.current[message.id].locked = true;
136
+ }
137
+ }
138
+ } else if (snapshotForClaim) {
139
+ const existingSnapshot2 = claimsRef.current[message.id].stateSnapshot;
140
+ if (!existingSnapshot2) {
141
+ claimsRef.current[message.id].stateSnapshot = snapshotForClaim;
142
+ const snapshotCache = __spreadValues({}, (_e = store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN]) != null ? _e : {});
143
+ const cacheKey = `${stateRenderId}::${effectiveRunId}`;
144
+ snapshotCache[cacheKey] = snapshotForClaim;
145
+ snapshotCache[`${stateRenderId}::latest`] = snapshotForClaim;
146
+ store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN] = snapshotCache;
147
+ const messageCache = __spreadValues({}, (_f = store[LAST_SNAPSHOTS_BY_MESSAGE]) != null ? _f : {});
148
+ messageCache[message.id] = { snapshot: snapshotForClaim, runId: effectiveRunId };
149
+ store[LAST_SNAPSHOTS_BY_MESSAGE] = messageCache;
150
+ }
151
+ }
152
+ return { canRender: true };
153
+ }
154
+
155
+ export {
156
+ useStateRenderRegistry
157
+ };
158
+ //# sourceMappingURL=chunk-77IVITG3.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/use-coagent-state-render-registry.ts"],"sourcesContent":["import { useEffect } from \"react\";\nimport {\n areStatesEquals,\n ClaimAction,\n getEffectiveRunId,\n isPlaceholderMessageId,\n isPlaceholderMessageName,\n readCachedMessageEntry,\n resolveClaim,\n selectSnapshot,\n type Claim,\n type ClaimsByMessageId,\n type SnapshotCaches,\n type StateRenderContext,\n} from \"./use-coagent-state-render-bridge.helpers\";\n\nexport interface StateRenderRegistryInput {\n agentId: string;\n stateRenderId?: string;\n message: { id: string; runId?: string; name?: string };\n messageIndex?: number;\n stateSnapshot?: any;\n agentState?: any;\n agentMessages?: Array<{ id: string; role?: string }>;\n claimsRef: React.MutableRefObject<Record<string, Claim>>;\n}\n\nexport interface StateRenderRegistryResult {\n canRender: boolean;\n}\n\nconst LAST_SNAPSHOTS_BY_RENDER_AND_RUN = \"__lastSnapshotsByStateRenderIdAndRun\";\nconst LAST_SNAPSHOTS_BY_MESSAGE = \"__lastSnapshotsByMessageId\";\n\ntype SnapshotByMessageEntry = { snapshot: any; runId?: string } | any;\ntype ClaimsStore = Record<string, Claim> & {\n [LAST_SNAPSHOTS_BY_RENDER_AND_RUN]?: Record<string, any>;\n [LAST_SNAPSHOTS_BY_MESSAGE]?: Record<string, SnapshotByMessageEntry>;\n};\n\nfunction getClaimsStore(\n claimsRef: React.MutableRefObject<Record<string, Claim>>,\n): ClaimsStore {\n return claimsRef.current as ClaimsStore;\n}\n\nfunction getSnapshotCaches(claimsRef: React.MutableRefObject<Record<string, Claim>>): SnapshotCaches {\n const store = getClaimsStore(claimsRef);\n return {\n byStateRenderAndRun: store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN] ?? {},\n byMessageId: store[LAST_SNAPSHOTS_BY_MESSAGE] ?? {},\n };\n}\n\nexport function useStateRenderRegistry({\n agentId,\n stateRenderId,\n message,\n messageIndex,\n stateSnapshot,\n agentState,\n agentMessages,\n claimsRef,\n}: StateRenderRegistryInput): StateRenderRegistryResult {\n const store = getClaimsStore(claimsRef);\n const runId = message.runId;\n const cachedMessageEntry = store[LAST_SNAPSHOTS_BY_MESSAGE]?.[message.id];\n const { runId: cachedMessageRunId } = readCachedMessageEntry(cachedMessageEntry);\n const existingClaimRunId = claimsRef.current[message.id]?.runId;\n const effectiveRunId = getEffectiveRunId({\n existingClaimRunId,\n cachedMessageRunId,\n runId,\n });\n\n useEffect(() => {\n return () => {\n const existingClaim = claimsRef.current[message.id];\n if (\n existingClaim?.stateSnapshot &&\n Object.keys(existingClaim.stateSnapshot).length > 0\n ) {\n const snapshotCache = {\n ...(store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN] ?? {}),\n };\n const cacheKey = `${existingClaim.stateRenderId}::${existingClaim.runId ?? \"pending\"}`;\n snapshotCache[cacheKey] = existingClaim.stateSnapshot;\n snapshotCache[`${existingClaim.stateRenderId}::latest`] = existingClaim.stateSnapshot;\n store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN] = snapshotCache;\n\n const messageCache = {\n ...(store[LAST_SNAPSHOTS_BY_MESSAGE] ?? {}),\n };\n messageCache[message.id] = {\n snapshot: existingClaim.stateSnapshot,\n runId: existingClaim.runId ?? effectiveRunId,\n };\n store[LAST_SNAPSHOTS_BY_MESSAGE] = messageCache;\n }\n delete claimsRef.current[message.id];\n };\n }, [claimsRef, effectiveRunId, message.id]);\n\n if (!stateRenderId) {\n return { canRender: false };\n }\n\n const caches = getSnapshotCaches(claimsRef);\n const existingClaim = claimsRef.current[message.id] as Claim | undefined;\n\n const { snapshot, hasSnapshotKeys, allowEmptySnapshot, snapshotForClaim } = selectSnapshot({\n messageId: message.id,\n messageName: message.name,\n allowLiveState:\n isPlaceholderMessageName(message.name) || isPlaceholderMessageId(message.id),\n skipLatestCache:\n isPlaceholderMessageName(message.name) || isPlaceholderMessageId(message.id),\n stateRenderId,\n effectiveRunId,\n stateSnapshotProp: stateSnapshot,\n agentState,\n agentMessages,\n existingClaim,\n caches,\n });\n\n const resolution = resolveClaim({\n claims: claimsRef.current as ClaimsByMessageId,\n context: {\n agentId,\n messageId: message.id,\n stateRenderId,\n runId: effectiveRunId,\n messageIndex,\n } satisfies StateRenderContext,\n stateSnapshot: snapshotForClaim,\n });\n\n if (resolution.action === ClaimAction.Block) {\n return { canRender: false };\n }\n\n if (resolution.updateRunId && claimsRef.current[message.id]) {\n claimsRef.current[message.id].runId = resolution.updateRunId;\n }\n\n if (resolution.nextClaim) {\n claimsRef.current[message.id] = resolution.nextClaim;\n }\n\n if (resolution.lockOthers) {\n Object.entries(claimsRef.current).forEach(([id, claim]) => {\n if (id !== message.id && claim.stateRenderId === stateRenderId) {\n claim.locked = true;\n }\n });\n }\n\n if (existingClaim && !existingClaim.locked && agentMessages?.length) {\n const indexInAgentMessages = agentMessages.findIndex((msg: any) => msg.id === message.id);\n if (indexInAgentMessages >= 0 && indexInAgentMessages < agentMessages.length - 1) {\n existingClaim.locked = true;\n }\n }\n\n const existingSnapshot = claimsRef.current[message.id].stateSnapshot;\n const snapshotChanged =\n stateSnapshot &&\n existingSnapshot !== undefined &&\n !areStatesEquals(existingSnapshot, snapshot);\n\n if (\n snapshot &&\n (stateSnapshot || hasSnapshotKeys || allowEmptySnapshot) &&\n (!claimsRef.current[message.id].locked || snapshotChanged)\n ) {\n if (!claimsRef.current[message.id].locked || snapshotChanged) {\n claimsRef.current[message.id].stateSnapshot = snapshot;\n const snapshotCache = {\n ...(store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN] ?? {}),\n };\n const cacheKey = `${stateRenderId}::${effectiveRunId}`;\n snapshotCache[cacheKey] = snapshot;\n snapshotCache[`${stateRenderId}::latest`] = snapshot;\n store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN] = snapshotCache;\n const messageCache = {\n ...(store[LAST_SNAPSHOTS_BY_MESSAGE] ?? {}),\n };\n messageCache[message.id] = { snapshot, runId: effectiveRunId };\n store[LAST_SNAPSHOTS_BY_MESSAGE] = messageCache;\n if (stateSnapshot) {\n claimsRef.current[message.id].locked = true;\n }\n }\n } else if (snapshotForClaim) {\n const existingSnapshot = claimsRef.current[message.id].stateSnapshot;\n if (!existingSnapshot) {\n claimsRef.current[message.id].stateSnapshot = snapshotForClaim;\n const snapshotCache = {\n ...(store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN] ?? {}),\n };\n const cacheKey = `${stateRenderId}::${effectiveRunId}`;\n snapshotCache[cacheKey] = snapshotForClaim;\n snapshotCache[`${stateRenderId}::latest`] = snapshotForClaim;\n store[LAST_SNAPSHOTS_BY_RENDER_AND_RUN] = snapshotCache;\n const messageCache = {\n ...(store[LAST_SNAPSHOTS_BY_MESSAGE] ?? {}),\n };\n messageCache[message.id] = { snapshot: snapshotForClaim, runId: effectiveRunId };\n store[LAST_SNAPSHOTS_BY_MESSAGE] = messageCache;\n }\n }\n\n return { canRender: true };\n}\n"],"mappings":"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","names":["_a","_b","_c","_d","existingClaim","existingSnapshot"]}
@@ -0,0 +1,119 @@
1
+ import {
2
+ useStateRenderRegistry
3
+ } from "./chunk-77IVITG3.mjs";
4
+ import {
5
+ useCoAgentStateRenders
6
+ } from "./chunk-QD7EID4N.mjs";
7
+ import {
8
+ __spreadProps,
9
+ __spreadValues
10
+ } from "./chunk-SKC7AJIV.mjs";
11
+
12
+ // src/hooks/use-coagent-state-render-bridge.tsx
13
+ import { useAgent } from "@copilotkitnext/react";
14
+ import { useCallback, useEffect, useMemo, useState } from "react";
15
+ import { parseJson } from "@copilotkit/shared";
16
+ function useCoagentStateRenderBridge(agentId, props) {
17
+ var _a;
18
+ const { stateSnapshot, message } = props;
19
+ const { coAgentStateRenders, claimsRef } = useCoAgentStateRenders();
20
+ const { agent } = useAgent({ agentId });
21
+ const [nodeName, setNodeName] = useState(void 0);
22
+ const [, forceUpdate] = useState(0);
23
+ useEffect(() => {
24
+ if (!agent)
25
+ return;
26
+ const subscriber = {
27
+ onStateChanged: () => {
28
+ forceUpdate((value) => value + 1);
29
+ },
30
+ onStepStartedEvent: ({ event }) => {
31
+ if (event.stepName !== nodeName) {
32
+ setNodeName(event.stepName);
33
+ }
34
+ },
35
+ onStepFinishedEvent: ({ event }) => {
36
+ if (event.stepName === nodeName) {
37
+ setNodeName(void 0);
38
+ }
39
+ }
40
+ };
41
+ const { unsubscribe } = agent.subscribe(subscriber);
42
+ return () => {
43
+ unsubscribe();
44
+ };
45
+ }, [agentId, nodeName]);
46
+ const getStateRender = useCallback(
47
+ (messageId) => {
48
+ return Object.entries(coAgentStateRenders).find(([stateRenderId2, stateRender2]) => {
49
+ if (claimsRef.current[messageId]) {
50
+ return stateRenderId2 === claimsRef.current[messageId].stateRenderId;
51
+ }
52
+ const matchingAgentName = stateRender2.name === agentId;
53
+ const matchesNodeContext = stateRender2.nodeName ? stateRender2.nodeName === nodeName : true;
54
+ return matchingAgentName && matchesNodeContext;
55
+ });
56
+ },
57
+ [coAgentStateRenders, nodeName, agentId]
58
+ );
59
+ const stateRenderEntry = useMemo(() => getStateRender(message.id), [getStateRender, message.id]);
60
+ const stateRenderId = stateRenderEntry == null ? void 0 : stateRenderEntry[0];
61
+ const stateRender = stateRenderEntry == null ? void 0 : stateRenderEntry[1];
62
+ const registryMessage = __spreadProps(__spreadValues({}, message), {
63
+ runId: (_a = props.runId) != null ? _a : message.runId
64
+ });
65
+ const { canRender } = useStateRenderRegistry({
66
+ agentId,
67
+ stateRenderId,
68
+ message: registryMessage,
69
+ messageIndex: props.messageIndex,
70
+ stateSnapshot,
71
+ agentState: agent == null ? void 0 : agent.state,
72
+ agentMessages: agent == null ? void 0 : agent.messages,
73
+ claimsRef
74
+ });
75
+ return useMemo(() => {
76
+ var _a2, _b;
77
+ if (!stateRender || !stateRenderId) {
78
+ return null;
79
+ }
80
+ if (!canRender) {
81
+ return null;
82
+ }
83
+ if (stateRender.handler) {
84
+ stateRender.handler({
85
+ state: stateSnapshot ? parseJson(stateSnapshot, stateSnapshot) : (_a2 = agent == null ? void 0 : agent.state) != null ? _a2 : {},
86
+ nodeName: nodeName != null ? nodeName : ""
87
+ });
88
+ }
89
+ if (stateRender.render) {
90
+ const status = (agent == null ? void 0 : agent.isRunning) ? "inProgress" /* InProgress */ : "complete" /* Complete */;
91
+ if (typeof stateRender.render === "string")
92
+ return stateRender.render;
93
+ return stateRender.render({
94
+ status,
95
+ // Always use state from claim, to make sure the state does not seem "wiped" for a fraction of a second
96
+ state: (_b = claimsRef.current[message.id].stateSnapshot) != null ? _b : {},
97
+ nodeName: nodeName != null ? nodeName : ""
98
+ });
99
+ }
100
+ }, [
101
+ stateRender,
102
+ stateRenderId,
103
+ agent == null ? void 0 : agent.state,
104
+ agent == null ? void 0 : agent.isRunning,
105
+ nodeName,
106
+ message.id,
107
+ stateSnapshot,
108
+ canRender
109
+ ]);
110
+ }
111
+ function CoAgentStateRenderBridge(props) {
112
+ return useCoagentStateRenderBridge(props.agentId, props);
113
+ }
114
+
115
+ export {
116
+ useCoagentStateRenderBridge,
117
+ CoAgentStateRenderBridge
118
+ };
119
+ //# sourceMappingURL=chunk-BKMJ4LC7.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/use-coagent-state-render-bridge.tsx"],"sourcesContent":["import { ReactCustomMessageRendererPosition, useAgent } from \"@copilotkitnext/react\";\nimport { useCallback, useEffect, useMemo, useState } from \"react\";\nimport type { AgentSubscriber } from \"@ag-ui/client\";\nimport { useCoAgentStateRenders } from \"../context\";\nimport { parseJson } from \"@copilotkit/shared\";\nimport { RenderStatus } from \"./use-coagent-state-render-bridge.helpers\";\nimport { useStateRenderRegistry } from \"./use-coagent-state-render-registry\";\n\n/**\n * Bridge hook that connects agent state renders to chat messages.\n *\n * ## Purpose\n * This hook finds matching state render configurations (registered via useCoAgentStateRender)\n * and returns UI to render in chat.\n * It ensures each state render appears bound to a specific message, preventing duplicates while\n * allowing re-binding when the underlying state changes significantly.\n *\n * ## Message-ID-Based Claiming System\n *\n * ### The Problem\n * Multiple bridge component instances render simultaneously (one per message). Without coordination,\n * they would all try to render the same state render, causing duplicates.\n *\n * ### The Solution: Message-ID Claims with State Comparison\n * Each state render is \"claimed\" by exactly one **message ID** (not runId):\n *\n * **Claim Structure**: `claimsRef.current[messageId] = { stateRenderId, runId, stateSnapshot, locked }`\n *\n * **Primary binding is by messageId because**:\n * - runId is not always available immediately (starts as \"pending\")\n * - messageId is the stable identifier throughout the message lifecycle\n * - Claims persist across component remounts via context ref\n *\n * ### Claiming Logic Flow\n *\n * 1. **Message already has a claim**:\n * - Check if the claim matches the current stateRenderId\n * - If yes → render (this message owns this render)\n * - Update runId if it was \"pending\" and now available\n *\n * 2. **State render claimed by another message**:\n * - Compare state snapshots (ignoring constant keys: messages, tools, copilotkit)\n * - If states are identical → block rendering (duplicate)\n * - **If states are different → allow claiming** (new data, new message)\n * - This handles cases where the same render type shows different states in different messages\n *\n * 3. **Unclaimed state render**:\n * - Only allow claiming if runId is \"pending\" (initial render)\n * - If runId is real but no claim exists → block (edge case protection)\n * - Create new claim: `claimsRef.current[messageId] = { stateRenderId, runId }`\n *\n * ### State Snapshot Locking\n *\n * Once a state snapshot is captured and locked for a message:\n * - The UI always renders with the locked snapshot (not live agent.state)\n * - Prevents UI from appearing \"wiped\" during state transitions\n * - Locked when: stateSnapshot prop is available (from message persistence)\n * - Unlocked state: can still update from live agent.state\n *\n * ### Synchronous Claiming (Ref-based)\n *\n * Claims are stored in a context-level ref (not React state):\n * - Multiple bridges render in the same tick\n * - State updates are async - would allow duplicates before update completes\n * - Ref provides immediate, synchronous claim checking\n * - Survives component remounts (stored in context, not component)\n *\n * ## Flow Example\n *\n * ```\n * Time 1: Message A renders, runId=undefined, state={progress: 50%}\n * → effectiveRunId = \"pending\"\n * → Claims: claimsRef[\"msgA\"] = { stateRenderId: \"tasks\", runId: \"pending\", stateSnapshot: {progress: 50%} }\n * → Renders UI with 50% progress\n *\n * Time 2: Message B renders, runId=undefined, same state\n * → Checks: \"tasks\" already claimed by msgA with same state\n * → Returns null (blocked - duplicate)\n *\n * Time 3: Real runId appears (e.g., \"run-123\")\n * → Updates claim: claimsRef[\"msgA\"].runId = \"run-123\"\n * → Message A continues rendering\n *\n * Time 4: Agent processes more, state={progress: 100%}\n * → Message A: locked to 50% (stateSnapshot locked)\n * → Message C renders with state={progress: 100%}\n * → Checks: \"tasks\" claimed by msgA but state is DIFFERENT (50% vs 100%)\n * → Allows new claim: claimsRef[\"msgC\"] = { stateRenderId: \"tasks\", runId: \"run-123\", stateSnapshot: {progress: 100%} }\n * → Both messages render independently with their own snapshots\n * ```\n */\nexport interface CoAgentStateRenderBridgeProps {\n message: any;\n position: ReactCustomMessageRendererPosition;\n runId: string;\n messageIndex: number;\n messageIndexInRun: number;\n numberOfMessagesInRun: number;\n agentId: string;\n stateSnapshot: any;\n}\n\nexport function useCoagentStateRenderBridge(agentId: string, props: CoAgentStateRenderBridgeProps) {\n const { stateSnapshot, message } = props;\n const { coAgentStateRenders, claimsRef } = useCoAgentStateRenders();\n const { agent } = useAgent({ agentId });\n const [nodeName, setNodeName] = useState<string | undefined>(undefined);\n const [, forceUpdate] = useState(0);\n\n useEffect(() => {\n if (!agent) return;\n const subscriber: AgentSubscriber = {\n onStateChanged: () => {\n forceUpdate((value) => value + 1);\n },\n onStepStartedEvent: ({ event }) => {\n if (event.stepName !== nodeName) {\n setNodeName(event.stepName);\n }\n },\n onStepFinishedEvent: ({ event }) => {\n if (event.stepName === nodeName) {\n setNodeName(undefined);\n }\n },\n };\n\n const { unsubscribe } = agent.subscribe(subscriber);\n return () => {\n unsubscribe();\n };\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [agentId, nodeName]);\n\n const getStateRender = useCallback(\n (messageId: string) => {\n return Object.entries(coAgentStateRenders).find(([stateRenderId, stateRender]) => {\n if (claimsRef.current[messageId]) {\n return stateRenderId === claimsRef.current[messageId].stateRenderId;\n }\n const matchingAgentName = stateRender.name === agentId;\n const matchesNodeContext = stateRender.nodeName ? stateRender.nodeName === nodeName : true;\n return matchingAgentName && matchesNodeContext;\n });\n },\n [coAgentStateRenders, nodeName, agentId],\n );\n const stateRenderEntry = useMemo(() => getStateRender(message.id), [getStateRender, message.id]);\n const stateRenderId = stateRenderEntry?.[0];\n const stateRender = stateRenderEntry?.[1];\n\n const registryMessage = {\n ...message,\n runId: props.runId ?? message.runId,\n };\n const { canRender } = useStateRenderRegistry({\n agentId,\n stateRenderId,\n message: registryMessage,\n messageIndex: props.messageIndex,\n stateSnapshot,\n agentState: agent?.state,\n agentMessages: agent?.messages,\n claimsRef,\n });\n\n return useMemo(() => {\n if (!stateRender || !stateRenderId) {\n return null;\n }\n if (!canRender) {\n return null;\n }\n\n if (stateRender.handler) {\n stateRender.handler({\n state: stateSnapshot ? parseJson(stateSnapshot, stateSnapshot) : (agent?.state ?? {}),\n nodeName: nodeName ?? \"\",\n });\n }\n\n if (stateRender.render) {\n const status = agent?.isRunning ? RenderStatus.InProgress : RenderStatus.Complete;\n\n if (typeof stateRender.render === \"string\") return stateRender.render;\n\n return stateRender.render({\n status,\n // Always use state from claim, to make sure the state does not seem \"wiped\" for a fraction of a second\n state: claimsRef.current[message.id].stateSnapshot ?? {},\n nodeName: nodeName ?? \"\",\n });\n }\n }, [\n stateRender,\n stateRenderId,\n agent?.state,\n agent?.isRunning,\n nodeName,\n message.id,\n stateSnapshot,\n canRender,\n ]);\n}\n\nexport function CoAgentStateRenderBridge(props: CoAgentStateRenderBridgeProps) {\n return useCoagentStateRenderBridge(props.agentId, props);\n}\n"],"mappings":"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","names":["stateRenderId","stateRender","_a"]}
@@ -0,0 +1,189 @@
1
+ import {
2
+ __objRest
3
+ } from "./chunk-SKC7AJIV.mjs";
4
+
5
+ // src/hooks/use-coagent-state-render-bridge.helpers.ts
6
+ import { dataToUUID, parseJson } from "@copilotkit/shared";
7
+ var RenderStatus = /* @__PURE__ */ ((RenderStatus2) => {
8
+ RenderStatus2["InProgress"] = "inProgress";
9
+ RenderStatus2["Complete"] = "complete";
10
+ return RenderStatus2;
11
+ })(RenderStatus || {});
12
+ var ClaimAction = /* @__PURE__ */ ((ClaimAction2) => {
13
+ ClaimAction2["Create"] = "create";
14
+ ClaimAction2["Override"] = "override";
15
+ ClaimAction2["Existing"] = "existing";
16
+ ClaimAction2["Block"] = "block";
17
+ return ClaimAction2;
18
+ })(ClaimAction || {});
19
+ function getStateWithoutConstantKeys(state) {
20
+ if (!state)
21
+ return {};
22
+ const _a = state, { messages, tools, copilotkit } = _a, stateWithoutConstantKeys = __objRest(_a, ["messages", "tools", "copilotkit"]);
23
+ return stateWithoutConstantKeys;
24
+ }
25
+ function areStatesEquals(a, b) {
26
+ if (a && !b || !a && b)
27
+ return false;
28
+ const _a = a, { messages, tools, copilotkit } = _a, aWithoutConstantKeys = __objRest(_a, ["messages", "tools", "copilotkit"]);
29
+ const _b = b, {
30
+ messages: bMessages,
31
+ tools: bTools,
32
+ copilotkit: bCopilotkit
33
+ } = _b, bWithoutConstantKeys = __objRest(_b, [
34
+ "messages",
35
+ "tools",
36
+ "copilotkit"
37
+ ]);
38
+ return JSON.stringify(aWithoutConstantKeys) === JSON.stringify(bWithoutConstantKeys);
39
+ }
40
+ function isPlaceholderMessageId(messageId) {
41
+ return !!messageId && messageId.startsWith("coagent-state-render-");
42
+ }
43
+ function isPlaceholderMessageName(messageName) {
44
+ return messageName === "coagent-state-render";
45
+ }
46
+ function readCachedMessageEntry(entry) {
47
+ if (!entry || typeof entry !== "object") {
48
+ return { snapshot: entry, runId: void 0 };
49
+ }
50
+ const snapshot = "snapshot" in entry ? entry.snapshot : entry;
51
+ const runId = "runId" in entry ? entry.runId : void 0;
52
+ return { snapshot, runId };
53
+ }
54
+ function getEffectiveRunId({
55
+ existingClaimRunId,
56
+ cachedMessageRunId,
57
+ runId
58
+ }) {
59
+ return existingClaimRunId || cachedMessageRunId || runId || "pending";
60
+ }
61
+ function resolveClaim({
62
+ claims,
63
+ context,
64
+ stateSnapshot
65
+ }) {
66
+ const { messageId, stateRenderId, runId, messageIndex } = context;
67
+ const existing = claims[messageId];
68
+ if (existing) {
69
+ const canRender = existing.stateRenderId === stateRenderId;
70
+ const shouldUpdateRunId = canRender && runId && (!existing.runId || existing.runId === "pending");
71
+ return {
72
+ canRender,
73
+ action: canRender ? "existing" /* Existing */ : "block" /* Block */,
74
+ updateRunId: shouldUpdateRunId ? runId : void 0
75
+ };
76
+ }
77
+ const normalizedRunId = runId != null ? runId : "pending";
78
+ const renderClaimedByOtherMessageEntry = Object.entries(claims).find(
79
+ ([, claim]) => {
80
+ var _a;
81
+ return claim.stateRenderId === stateRenderId && ((_a = claim.runId) != null ? _a : "pending") === normalizedRunId && dataToUUID(getStateWithoutConstantKeys(claim.stateSnapshot)) === dataToUUID(getStateWithoutConstantKeys(stateSnapshot));
82
+ }
83
+ );
84
+ const renderClaimedByOtherMessage = renderClaimedByOtherMessageEntry == null ? void 0 : renderClaimedByOtherMessageEntry[1];
85
+ const claimedMessageId = renderClaimedByOtherMessageEntry == null ? void 0 : renderClaimedByOtherMessageEntry[0];
86
+ if (renderClaimedByOtherMessage) {
87
+ if (messageIndex !== void 0 && renderClaimedByOtherMessage.messageIndex !== void 0 && messageIndex > renderClaimedByOtherMessage.messageIndex) {
88
+ return {
89
+ canRender: true,
90
+ action: "override" /* Override */,
91
+ nextClaim: { stateRenderId, runId, messageIndex },
92
+ lockOthers: runId === renderClaimedByOtherMessage.runId || isPlaceholderMessageId(claimedMessageId)
93
+ };
94
+ }
95
+ if (runId && renderClaimedByOtherMessage.runId && runId !== renderClaimedByOtherMessage.runId) {
96
+ return {
97
+ canRender: true,
98
+ action: "override" /* Override */,
99
+ nextClaim: { stateRenderId, runId, messageIndex },
100
+ lockOthers: isPlaceholderMessageId(claimedMessageId)
101
+ };
102
+ }
103
+ if (isPlaceholderMessageId(claimedMessageId)) {
104
+ return {
105
+ canRender: true,
106
+ action: "override" /* Override */,
107
+ nextClaim: { stateRenderId, runId, messageIndex },
108
+ lockOthers: true
109
+ };
110
+ }
111
+ if (stateSnapshot && renderClaimedByOtherMessage.stateSnapshot && !areStatesEquals(renderClaimedByOtherMessage.stateSnapshot, stateSnapshot)) {
112
+ return {
113
+ canRender: true,
114
+ action: "override" /* Override */,
115
+ nextClaim: { stateRenderId, runId }
116
+ };
117
+ }
118
+ return { canRender: false, action: "block" /* Block */ };
119
+ }
120
+ if (!runId) {
121
+ return { canRender: false, action: "block" /* Block */ };
122
+ }
123
+ return {
124
+ canRender: true,
125
+ action: "create" /* Create */,
126
+ nextClaim: { stateRenderId, runId, messageIndex }
127
+ };
128
+ }
129
+ function selectSnapshot({
130
+ messageId,
131
+ messageName,
132
+ allowLiveState,
133
+ skipLatestCache,
134
+ stateRenderId,
135
+ effectiveRunId,
136
+ stateSnapshotProp,
137
+ agentState,
138
+ agentMessages,
139
+ existingClaim,
140
+ caches
141
+ }) {
142
+ var _a, _b, _c, _d, _e, _f;
143
+ const lastAssistantId = agentMessages ? (_a = [...agentMessages].reverse().find((msg) => msg.role === "assistant")) == null ? void 0 : _a.id : void 0;
144
+ const latestSnapshot = stateRenderId !== void 0 ? caches.byStateRenderAndRun[`${stateRenderId}::latest`] : void 0;
145
+ const messageIndex = agentMessages ? agentMessages.findIndex((msg) => msg.id === messageId) : -1;
146
+ const messageRole = messageIndex >= 0 && agentMessages ? (_b = agentMessages[messageIndex]) == null ? void 0 : _b.role : void 0;
147
+ let previousUserMessageId;
148
+ if (messageIndex > 0 && agentMessages) {
149
+ for (let i = messageIndex - 1; i >= 0; i -= 1) {
150
+ if (((_c = agentMessages[i]) == null ? void 0 : _c.role) === "user") {
151
+ previousUserMessageId = (_d = agentMessages[i]) == null ? void 0 : _d.id;
152
+ break;
153
+ }
154
+ }
155
+ }
156
+ const liveStateIsStale = stateSnapshotProp === void 0 && latestSnapshot !== void 0 && agentState !== void 0 && areStatesEquals(latestSnapshot, agentState);
157
+ const shouldUseLiveState = (Boolean(allowLiveState) || !lastAssistantId || messageId === lastAssistantId) && !liveStateIsStale;
158
+ const snapshot = stateSnapshotProp ? parseJson(stateSnapshotProp, stateSnapshotProp) : shouldUseLiveState ? agentState : void 0;
159
+ const hasSnapshotKeys = !!(snapshot && Object.keys(snapshot).length > 0);
160
+ const allowEmptySnapshot = snapshot !== void 0 && !hasSnapshotKeys && (stateSnapshotProp !== void 0 || shouldUseLiveState);
161
+ const messageCacheEntry = caches.byMessageId[messageId];
162
+ const cachedMessageSnapshot = readCachedMessageEntry(messageCacheEntry).snapshot;
163
+ const cacheKey = stateRenderId !== void 0 ? `${stateRenderId}::${effectiveRunId}` : void 0;
164
+ let cachedSnapshot = cachedMessageSnapshot != null ? cachedMessageSnapshot : caches.byMessageId[messageId];
165
+ if (cachedSnapshot === void 0 && cacheKey && caches.byStateRenderAndRun[cacheKey] !== void 0) {
166
+ cachedSnapshot = caches.byStateRenderAndRun[cacheKey];
167
+ }
168
+ if (cachedSnapshot === void 0 && stateRenderId && previousUserMessageId && caches.byStateRenderAndRun[`${stateRenderId}::pending:${previousUserMessageId}`] !== void 0) {
169
+ cachedSnapshot = caches.byStateRenderAndRun[`${stateRenderId}::pending:${previousUserMessageId}`];
170
+ }
171
+ if (cachedSnapshot === void 0 && !skipLatestCache && stateRenderId && messageRole !== "assistant" && (stateSnapshotProp !== void 0 || agentState && Object.keys(agentState).length > 0)) {
172
+ cachedSnapshot = caches.byStateRenderAndRun[`${stateRenderId}::latest`];
173
+ }
174
+ 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;
175
+ return { snapshot, hasSnapshotKeys, cachedSnapshot, allowEmptySnapshot, snapshotForClaim };
176
+ }
177
+
178
+ export {
179
+ RenderStatus,
180
+ ClaimAction,
181
+ areStatesEquals,
182
+ isPlaceholderMessageId,
183
+ isPlaceholderMessageName,
184
+ readCachedMessageEntry,
185
+ getEffectiveRunId,
186
+ resolveClaim,
187
+ selectSnapshot
188
+ };
189
+ //# sourceMappingURL=chunk-C3YJYDK4.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/hooks/use-coagent-state-render-bridge.helpers.ts"],"sourcesContent":["import { dataToUUID, parseJson } from \"@copilotkit/shared\";\n\nexport enum RenderStatus {\n InProgress = \"inProgress\",\n Complete = \"complete\",\n}\n\nexport enum ClaimAction {\n Create = \"create\",\n Override = \"override\",\n Existing = \"existing\",\n Block = \"block\",\n}\n\nexport interface StateRenderContext {\n agentId: string;\n stateRenderId: string;\n messageId: string;\n runId: string;\n messageIndex?: number;\n}\n\nexport interface Claim {\n stateRenderId: string;\n runId?: string;\n stateSnapshot?: any;\n locked?: boolean;\n messageIndex?: number;\n}\n\nexport type ClaimsByMessageId = Record<string, Claim>;\n\nexport interface ClaimResolution {\n canRender: boolean;\n action: ClaimAction;\n nextClaim?: Claim;\n lockOthers?: boolean;\n updateRunId?: string;\n}\n\nexport interface SnapshotCaches {\n byStateRenderAndRun: Record<string, any>;\n byMessageId: Record<string, any>;\n}\n\nexport interface SnapshotSelectionInput {\n messageId: string;\n messageName?: string;\n allowLiveState?: boolean;\n skipLatestCache?: boolean;\n stateRenderId?: string;\n effectiveRunId: string;\n stateSnapshotProp?: any;\n agentState?: any;\n agentMessages?: Array<{ id: string; role?: string }>;\n existingClaim?: Claim;\n caches: SnapshotCaches;\n}\n\nexport interface SnapshotSelectionResult {\n snapshot?: any;\n hasSnapshotKeys: boolean;\n cachedSnapshot?: any;\n allowEmptySnapshot?: boolean;\n snapshotForClaim?: any;\n}\n\nfunction getStateWithoutConstantKeys(state: any) {\n if (!state) return {};\n const { messages, tools, copilotkit, ...stateWithoutConstantKeys } = state;\n return stateWithoutConstantKeys;\n}\n\n// Function that compares states, without the constant keys\nexport function areStatesEquals(a: any, b: any) {\n if ((a && !b) || (!a && b)) return false;\n const { messages, tools, copilotkit, ...aWithoutConstantKeys } = a;\n const {\n messages: bMessages,\n tools: bTools,\n copilotkit: bCopilotkit,\n ...bWithoutConstantKeys\n } = b;\n\n return JSON.stringify(aWithoutConstantKeys) === JSON.stringify(bWithoutConstantKeys);\n}\n\nexport function isPlaceholderMessageId(messageId: string | undefined) {\n return !!messageId && messageId.startsWith(\"coagent-state-render-\");\n}\n\nexport function isPlaceholderMessageName(messageName: string | undefined) {\n return messageName === \"coagent-state-render\";\n}\n\nexport function readCachedMessageEntry(entry: any): { snapshot?: any; runId?: string } {\n if (!entry || typeof entry !== \"object\") {\n return { snapshot: entry, runId: undefined };\n }\n const snapshot = \"snapshot\" in entry ? entry.snapshot : entry;\n const runId = \"runId\" in entry ? entry.runId : undefined;\n return { snapshot, runId };\n}\n\nexport function getEffectiveRunId({\n existingClaimRunId,\n cachedMessageRunId,\n runId,\n}: {\n existingClaimRunId?: string;\n cachedMessageRunId?: string;\n runId?: string;\n}) {\n return existingClaimRunId || cachedMessageRunId || runId || \"pending\";\n}\n\n/**\n * Resolve whether a message can claim a render slot.\n * This is a pure decision function; the caller applies claim mutations.\n */\nexport function resolveClaim({\n claims,\n context,\n stateSnapshot,\n}: {\n claims: ClaimsByMessageId;\n context: StateRenderContext;\n stateSnapshot?: any;\n}): ClaimResolution {\n const { messageId, stateRenderId, runId, messageIndex } = context;\n const existing = claims[messageId];\n\n if (existing) {\n const canRender = existing.stateRenderId === stateRenderId;\n const shouldUpdateRunId =\n canRender && runId && (!existing.runId || existing.runId === \"pending\");\n return {\n canRender,\n action: canRender ? ClaimAction.Existing : ClaimAction.Block,\n updateRunId: shouldUpdateRunId ? runId : undefined,\n };\n }\n\n const normalizedRunId = runId ?? \"pending\";\n const renderClaimedByOtherMessageEntry = Object.entries(claims).find(\n ([, claim]) =>\n claim.stateRenderId === stateRenderId &&\n (claim.runId ?? \"pending\") === normalizedRunId &&\n dataToUUID(getStateWithoutConstantKeys(claim.stateSnapshot)) ===\n dataToUUID(getStateWithoutConstantKeys(stateSnapshot)),\n );\n\n const renderClaimedByOtherMessage = renderClaimedByOtherMessageEntry?.[1];\n const claimedMessageId = renderClaimedByOtherMessageEntry?.[0];\n\n if (renderClaimedByOtherMessage) {\n if (\n messageIndex !== undefined &&\n renderClaimedByOtherMessage.messageIndex !== undefined &&\n messageIndex > renderClaimedByOtherMessage.messageIndex\n ) {\n return {\n canRender: true,\n action: ClaimAction.Override,\n nextClaim: { stateRenderId, runId, messageIndex },\n lockOthers:\n runId === renderClaimedByOtherMessage.runId || isPlaceholderMessageId(claimedMessageId),\n };\n }\n\n if (runId && renderClaimedByOtherMessage.runId && runId !== renderClaimedByOtherMessage.runId) {\n return {\n canRender: true,\n action: ClaimAction.Override,\n nextClaim: { stateRenderId, runId, messageIndex },\n lockOthers: isPlaceholderMessageId(claimedMessageId),\n };\n }\n\n if (isPlaceholderMessageId(claimedMessageId)) {\n return {\n canRender: true,\n action: ClaimAction.Override,\n nextClaim: { stateRenderId, runId, messageIndex },\n lockOthers: true,\n };\n }\n\n if (\n stateSnapshot &&\n renderClaimedByOtherMessage.stateSnapshot &&\n !areStatesEquals(renderClaimedByOtherMessage.stateSnapshot, stateSnapshot)\n ) {\n return {\n canRender: true,\n action: ClaimAction.Override,\n nextClaim: { stateRenderId, runId },\n };\n }\n\n return { canRender: false, action: ClaimAction.Block };\n }\n\n if (!runId) {\n return { canRender: false, action: ClaimAction.Block };\n }\n\n return {\n canRender: true,\n action: ClaimAction.Create,\n nextClaim: { stateRenderId, runId, messageIndex },\n };\n}\n\n/**\n * Select the best snapshot to render for this message.\n * Priority order is:\n * 1) explicit message snapshot\n * 2) live agent state (latest assistant only)\n * 3) cached snapshot for message\n * 4) cached snapshot for stateRenderId+runId\n * 5) last cached snapshot for stateRenderId\n */\nexport function selectSnapshot({\n messageId,\n messageName,\n allowLiveState,\n skipLatestCache,\n stateRenderId,\n effectiveRunId,\n stateSnapshotProp,\n agentState,\n agentMessages,\n existingClaim,\n caches,\n}: SnapshotSelectionInput): SnapshotSelectionResult {\n const lastAssistantId = agentMessages\n ? [...agentMessages].reverse().find((msg) => msg.role === \"assistant\")?.id\n : undefined;\n const latestSnapshot =\n stateRenderId !== undefined ? caches.byStateRenderAndRun[`${stateRenderId}::latest`] : undefined;\n const messageIndex = agentMessages\n ? agentMessages.findIndex((msg) => msg.id === messageId)\n : -1;\n const messageRole =\n messageIndex >= 0 && agentMessages ? agentMessages[messageIndex]?.role : undefined;\n let previousUserMessageId: string | undefined;\n if (messageIndex > 0 && agentMessages) {\n for (let i = messageIndex - 1; i >= 0; i -= 1) {\n if (agentMessages[i]?.role === \"user\") {\n previousUserMessageId = agentMessages[i]?.id;\n break;\n }\n }\n }\n const liveStateIsStale =\n stateSnapshotProp === undefined &&\n latestSnapshot !== undefined &&\n agentState !== undefined &&\n areStatesEquals(latestSnapshot, agentState);\n const shouldUseLiveState =\n (Boolean(allowLiveState) || !lastAssistantId || messageId === lastAssistantId) &&\n !liveStateIsStale;\n const snapshot = stateSnapshotProp\n ? parseJson(stateSnapshotProp, stateSnapshotProp)\n : shouldUseLiveState\n ? agentState\n : undefined;\n const hasSnapshotKeys = !!(snapshot && Object.keys(snapshot).length > 0);\n const allowEmptySnapshot =\n snapshot !== undefined &&\n !hasSnapshotKeys &&\n (stateSnapshotProp !== undefined || shouldUseLiveState);\n\n const messageCacheEntry = caches.byMessageId[messageId];\n const cachedMessageSnapshot = readCachedMessageEntry(messageCacheEntry).snapshot;\n const cacheKey =\n stateRenderId !== undefined ? `${stateRenderId}::${effectiveRunId}` : undefined;\n let cachedSnapshot = cachedMessageSnapshot ?? caches.byMessageId[messageId];\n if (cachedSnapshot === undefined && cacheKey && caches.byStateRenderAndRun[cacheKey] !== undefined) {\n cachedSnapshot = caches.byStateRenderAndRun[cacheKey];\n }\n if (\n cachedSnapshot === undefined &&\n stateRenderId &&\n previousUserMessageId &&\n caches.byStateRenderAndRun[`${stateRenderId}::pending:${previousUserMessageId}`] !==\n undefined\n ) {\n cachedSnapshot =\n caches.byStateRenderAndRun[`${stateRenderId}::pending:${previousUserMessageId}`];\n }\n if (\n cachedSnapshot === undefined &&\n !skipLatestCache &&\n stateRenderId &&\n messageRole !== \"assistant\" &&\n (stateSnapshotProp !== undefined ||\n (agentState && Object.keys(agentState).length > 0))\n ) {\n cachedSnapshot = caches.byStateRenderAndRun[`${stateRenderId}::latest`];\n }\n\n const snapshotForClaim = existingClaim?.locked\n ? existingClaim.stateSnapshot ?? cachedSnapshot\n : hasSnapshotKeys\n ? snapshot\n : existingClaim?.stateSnapshot ?? cachedSnapshot;\n\n return { snapshot, hasSnapshotKeys, cachedSnapshot, allowEmptySnapshot, snapshotForClaim };\n}\n"],"mappings":"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","names":["RenderStatus","ClaimAction"]}
@@ -16,7 +16,7 @@ import {
16
16
  } from "./chunk-YYN33GSG.mjs";
17
17
  import {
18
18
  CoAgentStateRenderBridge
19
- } from "./chunk-3X3I7OJV.mjs";
19
+ } from "./chunk-BKMJ4LC7.mjs";
20
20
  import {
21
21
  ThreadsProvider,
22
22
  useThreads
@@ -33,9 +33,10 @@ import {
33
33
  } from "./chunk-6ZLPNY7X.mjs";
34
34
  import {
35
35
  CoAgentStateRendersProvider
36
- } from "./chunk-FDOMAPJY.mjs";
36
+ } from "./chunk-QD7EID4N.mjs";
37
37
  import {
38
- CopilotContext
38
+ CopilotContext,
39
+ useCopilotContext
39
40
  } from "./chunk-AFNWX62Q.mjs";
40
41
  import {
41
42
  __async,
@@ -49,7 +50,8 @@ import {
49
50
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
50
51
  import {
51
52
  CopilotChatConfigurationProvider,
52
- CopilotKitProvider as CopilotKitNextProvider
53
+ CopilotKitProvider as CopilotKitNextProvider,
54
+ useCopilotKit
53
55
  } from "@copilotkitnext/react";
54
56
  import { flushSync } from "react-dom";
55
57
  import {
@@ -76,6 +78,45 @@ function CopilotKit(_a) {
76
78
  })
77
79
  ) }) }) });
78
80
  }
81
+ function CopilotKitErrorBridge() {
82
+ const { copilotkit } = useCopilotKit();
83
+ const { onError, copilotApiConfig } = useCopilotContext();
84
+ useEffect(() => {
85
+ if (!copilotkit)
86
+ return;
87
+ const subscription = copilotkit.subscribe({
88
+ onError: (event) => __async(this, null, function* () {
89
+ const errorEvent = {
90
+ type: "error",
91
+ timestamp: Date.now(),
92
+ context: __spreadValues({
93
+ source: "agent",
94
+ request: {
95
+ operation: event.code || "unknown",
96
+ url: copilotApiConfig == null ? void 0 : copilotApiConfig.chatApiEndpoint,
97
+ startTime: Date.now()
98
+ },
99
+ technical: {
100
+ environment: "browser",
101
+ userAgent: typeof navigator !== "undefined" ? navigator.userAgent : void 0,
102
+ stackTrace: event.error.stack
103
+ }
104
+ }, event.context),
105
+ error: event.error
106
+ };
107
+ try {
108
+ yield onError(errorEvent);
109
+ } catch (handlerError) {
110
+ console.error("Error in onError handler:", handlerError);
111
+ }
112
+ })
113
+ });
114
+ return () => {
115
+ subscription.unsubscribe();
116
+ };
117
+ }, [copilotkit, onError, copilotApiConfig]);
118
+ return null;
119
+ }
79
120
  function CopilotKitInternal(cpkProps) {
80
121
  var _b;
81
122
  const _a = cpkProps, { children } = _a, props = __objRest(_a, ["children"]);
@@ -478,6 +519,7 @@ ${nonDocumentStrings}`;
478
519
  },
479
520
  children: [
480
521
  /* @__PURE__ */ jsx(CopilotListeners, {}),
522
+ /* @__PURE__ */ jsx(CopilotKitErrorBridge, {}),
481
523
  /* @__PURE__ */ jsxs(CoAgentStateRendersProvider, { children: [
482
524
  /* @__PURE__ */ jsx(MessagesTapProvider, { children: /* @__PURE__ */ jsxs(CopilotMessages, { children: [
483
525
  memoizedChildren,
@@ -548,4 +590,4 @@ export {
548
590
  CopilotKitInternal,
549
591
  defaultCopilotContextCategories
550
592
  };
551
- //# sourceMappingURL=chunk-GIU66J37.mjs.map
593
+ //# sourceMappingURL=chunk-DQXCQWSG.mjs.map