@copilotkit/react-core 1.77.0 → 1.77.2

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.
@@ -1766,7 +1766,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
1766
1766
 
1767
1767
  //#endregion
1768
1768
  //#region package.json
1769
- var version = "1.77.0";
1769
+ var version = "1.77.2";
1770
1770
 
1771
1771
  //#endregion
1772
1772
  //#region src/v2/components/CopilotKitInspector.tsx
@@ -3427,7 +3427,12 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
3427
3427
  - Use CSS Grid or Flexbox for layout. Ensure the UI looks good at any width.
3428
3428
  - Minimal transitions (150ms) for hover/focus states only. No decorative animations.
3429
3429
  - Keep the UI focused and dense — avoid excessive padding. Use compact spacing (8–12px gaps, 10–14px padding in controls).`;
3430
- const GENERATE_SANDBOXED_UI_DESCRIPTION = "Generate sandboxed UI. IMPORTANT: The generated code runs in a sandboxed iframe WITHOUT same-origin access. Do NOT use localStorage, sessionStorage, document.cookie, IndexedDB, or fetch/XMLHttpRequest to same-origin URLs. To communicate with the host application, use Websandbox.connection.remote.<functionName>(args) which returns a Promise.\n\nYou CAN use external libraries from CDNs by including <script> or <link> tags in the HTML <head> (e.g., Chart.js, D3, Three.js, x-data-spreadsheet, etc.). CDN resources load normally inside the sandbox.\n\nPARAMETER ORDER IS CRITICAL — generate parameters in exactly this order:\n1. initialHeight + placeholderMessages (shown to user while generating)\n2. css (all styles FIRST — the user sees a placeholder until CSS is complete)\n3. html (streams in live — the user watches the UI build as HTML is generated)\n4. jsFunctions (reusable helper functions)\n5. jsExpressions (applied one-by-one — the user sees each expression take effect)";
3430
+ const DEFAULT_LEARNING = Object.freeze({});
3431
+ function toLearningConfig(learning) {
3432
+ if (learning === true) return DEFAULT_LEARNING;
3433
+ if (learning === false) return void 0;
3434
+ return learning;
3435
+ }
3431
3436
  function useStableArrayProp(prop, warningMessage, isMeaningfulChange) {
3432
3437
  const empty = (0, react.useMemo)(() => [], []);
3433
3438
  const value = prop ?? empty;
@@ -3438,6 +3443,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
3438
3443
  return value;
3439
3444
  }
3440
3445
  const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY_HEADERS, credentials, messageFilter, publicApiKey, publicLicenseKey, licenseToken, properties = EMPTY_PROPERTIES, agents__unsafe_dev_only: agents = EMPTY_AGENTS, selfManagedAgents = EMPTY_AGENTS, renderToolCalls, renderActivityMessages, renderCustomMessages, frontendTools, humanInTheLoop, openGenerativeUI, enableInspector, agentId, showIntelligenceIndicator = true, useSingleEndpoint, onError, a2ui, defaultThrottleMs, debug, learning }) => {
3446
+ const learningConfig = toLearningConfig(learning);
3441
3447
  const [shouldRenderInspector, setShouldRenderInspector] = (0, react.useState)(false);
3442
3448
  const [inspectorVisible, setInspectorVisible] = (0, react.useState)(false);
3443
3449
  (0, react.useEffect)(() => {
@@ -3620,7 +3626,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
3620
3626
  if (!openGenUIActive) return [];
3621
3627
  return [{
3622
3628
  name: "generateSandboxedUi",
3623
- description: GENERATE_SANDBOXED_UI_DESCRIPTION,
3629
+ description: _copilotkit_shared.GENERATE_SANDBOXED_UI_DESCRIPTION,
3624
3630
  parameters: GenerateSandboxedUiArgsSchema,
3625
3631
  handler: async () => "UI generated",
3626
3632
  followUp: true,
@@ -3673,7 +3679,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
3673
3679
  renderActivityMessages: allActivityRenderers,
3674
3680
  renderCustomMessages: renderCustomMessagesList,
3675
3681
  debug,
3676
- learning
3682
+ learning: learningConfig
3677
3683
  });
3678
3684
  if (defaultThrottleMs !== void 0) copilotkitRef.current.setDefaultThrottleMs(defaultThrottleMs);
3679
3685
  }
@@ -3778,17 +3784,21 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
3778
3784
  useSingleEndpoint,
3779
3785
  debug
3780
3786
  ]);
3781
- const learningEnabled = learning !== void 0;
3782
- const trajectoryId = learning?.trajectoryId;
3783
- const learningContainerIdsRef = (0, react.useRef)(learning?.learningContainerIds);
3784
- (0, react.useEffect)(() => {
3785
- copilotkit.setLearningConfig(learning);
3786
- learningContainerIdsRef.current = learning?.learningContainerIds;
3787
- if (learning?.sink === void 0 && learning?.trajectoryId === void 0 && learning?.learningContainerIds !== void 0) console.warn("[CopilotKit] learningContainerIds is supported only with a custom sink. Authenticated Trajectory capture does not assign Learning Containers; remove learningContainerIds from the capture options.");
3788
- }, [copilotkit, learning]);
3789
- (0, react.useEffect)(() => {
3787
+ const learningEnabled = learningConfig !== void 0;
3788
+ const generatesTrajectoryId = learning === true;
3789
+ const suppliedTrajectoryId = learningConfig?.trajectoryId;
3790
+ const learningContainerIdsRef = (0, react.useRef)(learningConfig?.learningContainerIds);
3791
+ const generatedTrajectoryIdRef = (0, react.useRef)(void 0);
3792
+ (0, react.useEffect)(() => {
3793
+ copilotkit.setLearningConfig(learningConfig);
3794
+ learningContainerIdsRef.current = learningConfig?.learningContainerIds;
3795
+ if (learningConfig?.sink === void 0 && learningConfig?.trajectoryId === void 0 && learningConfig?.learningContainerIds !== void 0) console.warn("[CopilotKit] learningContainerIds is supported only with a custom sink. Authenticated Trajectory capture does not assign Learning Containers; remove learningContainerIds from the capture options.");
3796
+ }, [copilotkit, learningConfig]);
3797
+ (0, react.useEffect)(() => {
3798
+ if (!generatesTrajectoryId) generatedTrajectoryIdRef.current = void 0;
3790
3799
  if (!learningEnabled) return;
3791
3800
  let disposed = false;
3801
+ const trajectoryId = generatesTrajectoryId ? generatedTrajectoryIdRef.current ?? (generatedTrajectoryIdRef.current = (0, _copilotkit_shared.randomUUID)()) : suppliedTrajectoryId;
3792
3802
  if (trajectoryId !== void 0) copilotkit.startTrajectory({
3793
3803
  trajectoryId,
3794
3804
  learningContainerIds: learningContainerIdsRef.current
@@ -3802,7 +3812,8 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
3802
3812
  }, [
3803
3813
  copilotkit,
3804
3814
  learningEnabled,
3805
- trajectoryId
3815
+ generatesTrajectoryId,
3816
+ suppliedTrajectoryId
3806
3817
  ]);
3807
3818
  const didMountRef = (0, react.useRef)(false);
3808
3819
  (0, react.useEffect)(() => {
@@ -7699,8 +7710,23 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7699
7710
  }
7700
7711
  return [...acc.values()];
7701
7712
  }
7713
+ /** A row holding a single message, rendered as it would be ungrouped. */
7714
+ function messageRow(message) {
7715
+ return {
7716
+ type: "message",
7717
+ message
7718
+ };
7719
+ }
7720
+ /** A row holding a group of messages, rendered inside `wrapper`. */
7721
+ function messageGroup(group) {
7722
+ return {
7723
+ type: "group",
7724
+ ...group
7725
+ };
7726
+ }
7727
+ const GROUP_ROW_KEY_PREFIX = "copilotkit-group:";
7702
7728
  const VIRTUALIZE_THRESHOLD = 50;
7703
- function CopilotChatMessageView({ messages = [], assistantMessage, userMessage, reasoningMessage, cursor, intelligenceIndicator, isRunning = false, transformMessages, children, className, ...props }) {
7729
+ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage, reasoningMessage, cursor, intelligenceIndicator, isRunning = false, transformMessages, groupMessages, children, className, ...props }) {
7704
7730
  const isPinnedToBottom = (0, react.useContext)(ScrollPinnedContext);
7705
7731
  const renderCustomMessage = useRenderCustomMessages();
7706
7732
  const { renderActivityMessage } = useRenderActivityMessage();
@@ -7733,20 +7759,43 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7733
7759
  return copilotkit.getStateByRun(config.agentId, config.threadId, resolvedRunId);
7734
7760
  };
7735
7761
  const deduplicatedMessages = (0, react.useMemo)(() => deduplicateMessages(messages), [messages]);
7736
- const renderedMessages = (0, react.useMemo)(() => transformMessages ? transformMessages(deduplicatedMessages) : deduplicatedMessages, [deduplicatedMessages, transformMessages]);
7762
+ const transformedMessages = (0, react.useMemo)(() => transformMessages ? transformMessages(deduplicatedMessages) : deduplicatedMessages, [deduplicatedMessages, transformMessages]);
7763
+ const rows = (0, react.useMemo)(() => groupMessages ? groupMessages(transformedMessages) : transformedMessages.map(messageRow), [transformedMessages, groupMessages]);
7764
+ const renderedMessages = (0, react.useMemo)(() => groupMessages ? rows.flatMap((row) => row.type === "group" ? row.messages : [row.message]) : transformedMessages, [
7765
+ rows,
7766
+ groupMessages,
7767
+ transformedMessages
7768
+ ]);
7737
7769
  const latestRenderedId = renderedMessages[renderedMessages.length - 1]?.id;
7738
7770
  const transformDuplicateId = (0, react.useMemo)(() => {
7739
- if (process.env.NODE_ENV === "production" || !transformMessages) return;
7771
+ if (process.env.NODE_ENV === "production" || !transformMessages && !groupMessages) return;
7740
7772
  const seen = /* @__PURE__ */ new Set();
7741
7773
  for (const message of renderedMessages) {
7742
7774
  if (seen.has(message.id)) return message.id;
7743
7775
  seen.add(message.id);
7744
7776
  }
7745
- }, [renderedMessages, transformMessages]);
7777
+ }, [
7778
+ renderedMessages,
7779
+ transformMessages,
7780
+ groupMessages
7781
+ ]);
7746
7782
  (0, react.useEffect)(() => {
7747
7783
  if (transformDuplicateId === void 0) return;
7748
- console.warn(`[CopilotKit] CopilotChatMessageView: \`transformMessages\` returned more than one message with id "${transformDuplicateId}". Return each id at most once; a message you create needs its own id, stable across renders.`);
7749
- }, [transformDuplicateId]);
7784
+ console.warn(groupMessages ? `[CopilotKit] CopilotChatMessageView: the message with id "${transformDuplicateId}" renders more than once. \`groupMessages\` should place each message in at most one row, and \`transformMessages\` return each id at most once.` : `[CopilotKit] CopilotChatMessageView: \`transformMessages\` returned more than one message with id "${transformDuplicateId}". Return each id at most once; a message you create needs its own id, stable across renders.`);
7785
+ }, [transformDuplicateId, groupMessages]);
7786
+ const duplicateGroupKey = (0, react.useMemo)(() => {
7787
+ if (process.env.NODE_ENV === "production" || !groupMessages) return;
7788
+ const seen = /* @__PURE__ */ new Set();
7789
+ for (const row of rows) {
7790
+ if (row.type !== "group") continue;
7791
+ if (seen.has(row.key)) return row.key;
7792
+ seen.add(row.key);
7793
+ }
7794
+ }, [rows, groupMessages]);
7795
+ (0, react.useEffect)(() => {
7796
+ if (duplicateGroupKey === void 0) return;
7797
+ console.warn(`[CopilotKit] CopilotChatMessageView: \`groupMessages\` returned more than one group with key "${duplicateGroupKey}". Give each group its own key, stable across renders.`);
7798
+ }, [duplicateGroupKey]);
7750
7799
  const rowKeyStoreRef = (0, react.useRef)(null);
7751
7800
  rowKeyStoreRef.current ?? (rowKeyStoreRef.current = (0, _copilotkit_shared.createRowKeyStore)());
7752
7801
  const rowKeyStore = rowKeyStoreRef.current;
@@ -7754,6 +7803,31 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7754
7803
  (0, react.useLayoutEffect)(() => {
7755
7804
  (0, _copilotkit_shared.commitRowKeyStore)(rowKeyStore, renderedMessages);
7756
7805
  }, [rowKeyStore, renderedMessages]);
7806
+ const stableGroupKey = (key) => rowRenderKeys.get(key) ?? key;
7807
+ const groupStateRef = (0, react.useRef)(/* @__PURE__ */ new Map());
7808
+ const groupSettersRef = (0, react.useRef)(/* @__PURE__ */ new Map());
7809
+ const groupStateThreadRef = (0, react.useRef)(config?.threadId);
7810
+ if (groupStateThreadRef.current !== config?.threadId) {
7811
+ groupStateThreadRef.current = config?.threadId;
7812
+ groupStateRef.current = /* @__PURE__ */ new Map();
7813
+ groupSettersRef.current = /* @__PURE__ */ new Map();
7814
+ }
7815
+ const groupSetter = (key) => {
7816
+ let setter = groupSettersRef.current.get(key);
7817
+ if (!setter) {
7818
+ setter = (next) => {
7819
+ groupStateRef.current.set(key, next);
7820
+ forceUpdate();
7821
+ };
7822
+ groupSettersRef.current.set(key, setter);
7823
+ }
7824
+ return setter;
7825
+ };
7826
+ (0, react.useLayoutEffect)(() => {
7827
+ const live = /* @__PURE__ */ new Set();
7828
+ for (const row of rows) if (row.type === "group") live.add(stableGroupKey(row.key));
7829
+ for (const store of [groupStateRef.current, groupSettersRef.current]) for (const key of store.keys()) if (!live.has(key)) store.delete(key);
7830
+ }, [rows, rowRenderKeys]);
7757
7831
  if (process.env.NODE_ENV === "development" && deduplicatedMessages.length < messages.length) console.warn(`CopilotChatMessageView: Merged ${messages.length - deduplicatedMessages.length} message(s) with duplicate IDs.`);
7758
7832
  const { Component: AssistantComponent, slotProps: assistantSlotProps } = (0, react.useMemo)(() => resolveSlotComponent(assistantMessage, CopilotChatAssistantMessage_default), [assistantMessage]);
7759
7833
  const agentId = config?.agentId;
@@ -7793,7 +7867,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7793
7867
  (0, react.useEffect)(() => {
7794
7868
  if (process.env.NODE_ENV === "production" || !childrenDisabledVirtualization || warnedChildrenRef.current) return;
7795
7869
  warnedChildrenRef.current = true;
7796
- console.warn(`[CopilotKit] CopilotChatMessageView: the \`children\` render prop disables virtualization, so all ${renderedMessages.length} messages are mounted. ` + (transformMessages ? "`transformMessages` keeps virtualization on by itself; drop `children` to use it." : "To reshape the list and keep virtualization, use `transformMessages` instead."));
7870
+ console.warn(`[CopilotKit] CopilotChatMessageView: the \`children\` render prop disables virtualization, so all ${renderedMessages.length} messages are mounted. ` + (transformMessages || groupMessages ? "`transformMessages` and `groupMessages` keep virtualization on by themselves; drop `children` to use them." : "To reshape the list and keep virtualization, use `transformMessages` instead, or `groupMessages` to render several messages as one row."));
7797
7871
  }, [
7798
7872
  childrenDisabledVirtualization,
7799
7873
  renderedMessages.length,
@@ -7833,7 +7907,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7833
7907
  return item.start < (instance.scrollOffset ?? 0) + scrollAdjustments;
7834
7908
  }, []);
7835
7909
  const virtualizer = (0, _tanstack_react_virtual.useVirtualizer)({
7836
- count: shouldVirtualize ? renderedMessages.length : 0,
7910
+ count: shouldVirtualize ? rows.length : 0,
7837
7911
  getScrollElement: () => scrollElement,
7838
7912
  estimateSize: estimateRowSize,
7839
7913
  overscan: 5,
@@ -7846,8 +7920,8 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7846
7920
  isPinnedToBottomRef.current = isPinnedToBottom;
7847
7921
  virtualizer.shouldAdjustScrollPositionOnItemSizeChange = shouldAdjustScrollOnResize;
7848
7922
  (0, react.useLayoutEffect)(() => {
7849
- if (!shouldVirtualize || !renderedMessages.length) return;
7850
- virtualizer.scrollToIndex(renderedMessages.length - 1, { align: "end" });
7923
+ if (!shouldVirtualize || !rows.length) return;
7924
+ virtualizer.scrollToIndex(rows.length - 1, { align: "end" });
7851
7925
  }, [shouldVirtualize, firstMessageId]);
7852
7926
  const intelligenceTurnAnchors = (0, react.useMemo)(() => getIntelligenceTurnAnchors(deduplicatedMessages, renderedMessages), [deduplicatedMessages, renderedMessages]);
7853
7927
  const renderMessageBlock = (message) => {
@@ -7899,7 +7973,20 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7899
7973
  }, `intelligence-${intelligenceTurnId}`));
7900
7974
  return elements.filter(Boolean);
7901
7975
  };
7902
- const messageElements = shouldVirtualize ? [] : renderedMessages.flatMap(renderMessageBlock);
7976
+ const rowKey = (row) => row.type === "group" ? `${GROUP_ROW_KEY_PREFIX}${stableGroupKey(row.key)}` : rowRenderKeys.get(row.message.id) ?? row.message.id;
7977
+ const renderRow = (row) => {
7978
+ if (row.type === "message") return renderMessageBlock(row.message);
7979
+ const Wrapper = row.wrapper;
7980
+ const stateKey = stableGroupKey(row.key);
7981
+ return [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Wrapper, {
7982
+ groupKey: row.key,
7983
+ messages: row.messages,
7984
+ state: groupStateRef.current.get(stateKey),
7985
+ setState: groupSetter(stateKey),
7986
+ children: row.messages.flatMap(renderMessageBlock)
7987
+ }, rowKey(row))];
7988
+ };
7989
+ const messageElements = shouldVirtualize ? [] : rows.flatMap(renderRow);
7903
7990
  if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7904
7991
  "data-copilotkit": true,
7905
7992
  style: { display: "contents" },
@@ -7924,7 +8011,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7924
8011
  position: "relative"
7925
8012
  },
7926
8013
  children: virtualizer.getVirtualItems().map((virtualItem) => {
7927
- const message = renderedMessages[virtualItem.index];
8014
+ const row = rows[virtualItem.index];
7928
8015
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
7929
8016
  "data-index": virtualItem.index,
7930
8017
  ref: virtualizer.measureElement,
@@ -7935,8 +8022,8 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
7935
8022
  width: "100%",
7936
8023
  transform: `translateY(${virtualItem.start}px)`
7937
8024
  },
7938
- children: renderMessageBlock(message)
7939
- }, rowRenderKeys.get(message.id) ?? message.id);
8025
+ children: renderRow(row)
8026
+ }, rowKey(row));
7940
8027
  })
7941
8028
  }) : messageElements,
7942
8029
  interruptElement,
@@ -9004,6 +9091,29 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
9004
9091
  const [lastConnectedThreadId, setLastConnectedThreadId] = (0, react.useState)(null);
9005
9092
  const isConnecting = hasExplicitThreadId && lastConnectedThreadId !== resolvedThreadId;
9006
9093
  const activeConnectCountRef = (0, react.useRef)(0);
9094
+ const pendingConnectionsRef = (0, react.useRef)(/* @__PURE__ */ new Map());
9095
+ const failedConnectionsRef = (0, react.useRef)(/* @__PURE__ */ new WeakSet());
9096
+ const submissionQueueRef = (0, react.useRef)(Promise.resolve());
9097
+ const trackConnection = (0, react.useCallback)((connectingAgent, connect) => {
9098
+ const selection = previousThreadRef.current;
9099
+ const connectingThreadId = connectingAgent.threadId;
9100
+ let failed = false;
9101
+ const subscription = copilotkit.subscribe({ onError: (event) => {
9102
+ if (selection?.active && previousThreadRef.current === selection && event.context?.agentId === connectingAgent.agentId && (!event.context.threadId || event.context.threadId === connectingThreadId) && (event.code === _copilotkit_core.CopilotKitCoreErrorCode.AGENT_CONNECT_FAILED || event.code === _copilotkit_core.CopilotKitCoreErrorCode.AGENT_RUN_FAILED_EVENT)) failed = true;
9103
+ } });
9104
+ const pending = connect().catch((error) => {
9105
+ failed = true;
9106
+ console.error("CopilotChat: connection failed", error);
9107
+ }).finally(() => {
9108
+ subscription.unsubscribe();
9109
+ if (pendingConnectionsRef.current.get(connectingAgent) === pending) {
9110
+ pendingConnectionsRef.current.delete(connectingAgent);
9111
+ if (selection?.active && previousThreadRef.current === selection) if (failed) failedConnectionsRef.current.add(connectingAgent);
9112
+ else failedConnectionsRef.current.delete(connectingAgent);
9113
+ }
9114
+ });
9115
+ pendingConnectionsRef.current.set(connectingAgent, pending);
9116
+ }, [copilotkit]);
9007
9117
  const pendingRunActivityReconnectRef = (0, react.useRef)(false);
9008
9118
  const runActivityReconnectGenerationRef = (0, react.useRef)(0);
9009
9119
  const activeLocalRunIdsRef = (0, react.useRef)(/* @__PURE__ */ new Set());
@@ -9063,9 +9173,12 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
9063
9173
  const selection = {
9064
9174
  threadId: resolvedThreadId,
9065
9175
  inspectorRequestId,
9066
- agent
9176
+ agent,
9177
+ active: true
9067
9178
  };
9068
9179
  previousThreadRef.current = selection;
9180
+ submissionQueueRef.current = Promise.resolve();
9181
+ failedConnectionsRef.current.delete(agent);
9069
9182
  const discardedThreadId = previousThread?.agent === agent ? previousThread.threadId : agent.threadId;
9070
9183
  if (inspectorTransition) if (typeof copilotkit.stopAgent === "function") copilotkit.stopAgent({ agent });
9071
9184
  else agent.abortRun?.();
@@ -9103,6 +9216,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
9103
9216
  }
9104
9217
  return () => {
9105
9218
  active = false;
9219
+ selection.active = false;
9106
9220
  };
9107
9221
  }
9108
9222
  let detached = false;
@@ -9116,8 +9230,8 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
9116
9230
  await copilotkit.connectAgent({ agent: agentToConnect });
9117
9231
  } catch (error) {
9118
9232
  if (detached) return;
9119
- console.error("CopilotChat: connectAgent failed", error);
9120
9233
  if (inspectorRequestId) failInspectorOverride(inspectorRequestId);
9234
+ throw error;
9121
9235
  } finally {
9122
9236
  if (!detached) (typeof requestAnimationFrame === "function" ? requestAnimationFrame : (cb) => setTimeout(cb, 16))(() => {
9123
9237
  if (!detached) setLastConnectedThreadId(resolvedThreadId);
@@ -9133,8 +9247,9 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
9133
9247
  }
9134
9248
  }
9135
9249
  };
9136
- connect(agent);
9250
+ trackConnection(agent, () => connect(agent));
9137
9251
  return () => {
9252
+ selection.active = false;
9138
9253
  detached = true;
9139
9254
  connectAbortController.abort();
9140
9255
  const detach = agent.detachActiveRun().catch(() => {});
@@ -9197,7 +9312,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
9197
9312
  await copilotkit.connectAgent({ agent });
9198
9313
  didConnect = true;
9199
9314
  } catch (error) {
9200
- if (!detached) console.error("CopilotChat: run activity reconnect failed", error);
9315
+ if (!detached) throw error;
9201
9316
  } finally {
9202
9317
  if (wakeRunId) {
9203
9318
  activeWakeRunIdsRef.current.delete(wakeRunId);
@@ -9207,7 +9322,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
9207
9322
  wakeReconnectActive = false;
9208
9323
  if (!detached && runActivityReconnectGenerationRef.current === generation && activeConnectCountRef.current === 0 && pendingRunActivityReconnectRef.current) {
9209
9324
  pendingRunActivityReconnectRef.current = false;
9210
- connect();
9325
+ trackConnection(agent, connect);
9211
9326
  }
9212
9327
  }
9213
9328
  };
@@ -9223,7 +9338,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
9223
9338
  return;
9224
9339
  }
9225
9340
  pendingRunActivityReconnectRef.current = false;
9226
- connect();
9341
+ trackConnection(agent, connect);
9227
9342
  };
9228
9343
  const subscription = threadStore.subscribeToRunActivity((notification) => {
9229
9344
  if (notification.threadId !== resolvedThreadId) return;
@@ -9266,6 +9381,18 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
9266
9381
  rememberRecentlyWakeRunId
9267
9382
  ]);
9268
9383
  const waitForActiveRunToSettle = (0, react.useCallback)(async () => {
9384
+ const selection = previousThreadRef.current;
9385
+ const isCurrentSelection = () => selection?.active && previousThreadRef.current === selection;
9386
+ let connection = pendingConnectionsRef.current.get(agent);
9387
+ while (connection && isCurrentSelection()) {
9388
+ await connection;
9389
+ connection = pendingConnectionsRef.current.get(agent);
9390
+ }
9391
+ if (!isCurrentSelection()) return false;
9392
+ if (failedConnectionsRef.current.has(agent)) {
9393
+ setTranscriptionError("Could not load saved conversation. Reopen the thread and try again.");
9394
+ return "failed";
9395
+ }
9269
9396
  const maybeAware = agent;
9270
9397
  const activeRunCompletionPromise = (0, _copilotkit_core.isRunCompletionAware)(maybeAware) ? maybeAware.activeRunCompletionPromise : void 0;
9271
9398
  if (agent.isRunning && activeRunCompletionPromise) try {
@@ -9273,7 +9400,18 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
9273
9400
  } catch (error) {
9274
9401
  console.error("CopilotChat: in-flight run rejected while queuing send", error);
9275
9402
  }
9403
+ return isCurrentSelection();
9276
9404
  }, [agent]);
9405
+ const enqueueSubmission = (0, react.useCallback)((submit) => {
9406
+ const selection = previousThreadRef.current;
9407
+ const pending = submissionQueueRef.current.then(async () => {
9408
+ if (selection?.active && previousThreadRef.current === selection) await submit();
9409
+ }).catch((error) => {
9410
+ console.error("CopilotChat: queued submission failed", error);
9411
+ });
9412
+ submissionQueueRef.current = pending;
9413
+ return pending;
9414
+ }, []);
9277
9415
  const onSubmitInput = (0, react.useCallback)(async (value) => {
9278
9416
  if (selectedAttachmentsRef.current.some((a) => a.status === "uploading")) {
9279
9417
  console.error("[CopilotKit] Cannot send while attachments are uploading (pre-await guard)");
@@ -9281,92 +9419,102 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
9281
9419
  return;
9282
9420
  }
9283
9421
  setInputValue("");
9284
- await waitForActiveRunToSettle();
9285
- if (selectedAttachmentsRef.current.some((a) => a.status === "uploading")) {
9286
- console.error("[CopilotKit] Cannot send while attachments are uploading (post-await re-check)");
9287
- setTranscriptionError("Cannot send while attachments are uploading.");
9288
- setInputValue(value);
9289
- return;
9290
- }
9291
- const readyAttachments = consumeAttachments();
9292
- if (readyAttachments.length > 0) {
9293
- const contentParts = [];
9294
- if (value.trim()) contentParts.push({
9295
- type: "text",
9296
- text: value
9297
- });
9298
- for (const att of readyAttachments) contentParts.push((0, _copilotkit_shared.createAttachmentContent)(att));
9299
- agent.addMessage({
9422
+ await enqueueSubmission(async () => {
9423
+ const ready = await waitForActiveRunToSettle();
9424
+ if (ready !== true) {
9425
+ if (ready === "failed") setInputValue(value);
9426
+ return;
9427
+ }
9428
+ if (selectedAttachmentsRef.current.some((a) => a.status === "uploading")) {
9429
+ console.error("[CopilotKit] Cannot send while attachments are uploading (post-await re-check)");
9430
+ setTranscriptionError("Cannot send while attachments are uploading.");
9431
+ setInputValue(value);
9432
+ return;
9433
+ }
9434
+ const readyAttachments = consumeAttachments();
9435
+ if (readyAttachments.length > 0) {
9436
+ const contentParts = [];
9437
+ if (value.trim()) contentParts.push({
9438
+ type: "text",
9439
+ text: value
9440
+ });
9441
+ for (const att of readyAttachments) contentParts.push((0, _copilotkit_shared.createAttachmentContent)(att));
9442
+ agent.addMessage({
9443
+ id: (0, _copilotkit_shared.randomUUID)(),
9444
+ role: "user",
9445
+ content: contentParts
9446
+ });
9447
+ } else agent.addMessage({
9300
9448
  id: (0, _copilotkit_shared.randomUUID)(),
9301
9449
  role: "user",
9302
- content: contentParts
9303
- });
9304
- } else agent.addMessage({
9305
- id: (0, _copilotkit_shared.randomUUID)(),
9306
- role: "user",
9307
- content: value
9308
- });
9309
- const localRunId = hasNativeIntelligenceRunActivity ? (0, _copilotkit_shared.randomUUID)() : void 0;
9310
- if (localRunId) activeLocalRunIdsRef.current.add(localRunId);
9311
- try {
9312
- await copilotkit.runAgent({
9313
- agent,
9314
- ...localRunId !== void 0 ? { runId: localRunId } : {}
9450
+ content: value
9315
9451
  });
9316
- } catch (error) {
9317
- console.error("CopilotChat: runAgent failed", error);
9318
- } finally {
9319
- if (localRunId) {
9320
- activeLocalRunIdsRef.current.delete(localRunId);
9321
- rememberRecentlyLocalRunId(localRunId);
9322
- }
9323
- if (pendingRunActivityReconnectRef.current && activeLocalRunIdsRef.current.size === 0 && activeConnectCountRef.current === 0) {
9324
- const startReconnect = startRunActivityReconnectRef.current;
9325
- if (startReconnect) {
9326
- pendingRunActivityReconnectRef.current = false;
9327
- startReconnect(runActivityReconnectGenerationRef.current);
9452
+ const localRunId = hasNativeIntelligenceRunActivity ? (0, _copilotkit_shared.randomUUID)() : void 0;
9453
+ if (localRunId) activeLocalRunIdsRef.current.add(localRunId);
9454
+ try {
9455
+ await copilotkit.runAgent({
9456
+ agent,
9457
+ ...localRunId !== void 0 ? { runId: localRunId } : {}
9458
+ });
9459
+ } catch (error) {
9460
+ console.error("CopilotChat: runAgent failed", error);
9461
+ } finally {
9462
+ if (localRunId) {
9463
+ activeLocalRunIdsRef.current.delete(localRunId);
9464
+ rememberRecentlyLocalRunId(localRunId);
9465
+ }
9466
+ if (pendingRunActivityReconnectRef.current && activeLocalRunIdsRef.current.size === 0 && activeConnectCountRef.current === 0) {
9467
+ const startReconnect = startRunActivityReconnectRef.current;
9468
+ if (startReconnect) {
9469
+ pendingRunActivityReconnectRef.current = false;
9470
+ startReconnect(runActivityReconnectGenerationRef.current);
9471
+ }
9328
9472
  }
9329
9473
  }
9330
- }
9474
+ });
9331
9475
  }, [
9332
9476
  agent,
9333
9477
  consumeAttachments,
9334
9478
  waitForActiveRunToSettle,
9479
+ enqueueSubmission,
9335
9480
  hasNativeIntelligenceRunActivity,
9336
9481
  rememberRecentlyLocalRunId
9337
9482
  ]);
9338
9483
  const handleSelectSuggestion = (0, react.useCallback)(async (suggestion) => {
9339
- await waitForActiveRunToSettle();
9340
- agent.addMessage({
9341
- id: (0, _copilotkit_shared.randomUUID)(),
9342
- role: "user",
9343
- content: suggestion.message
9344
- });
9345
- const localRunId = hasNativeIntelligenceRunActivity ? (0, _copilotkit_shared.randomUUID)() : void 0;
9346
- if (localRunId) activeLocalRunIdsRef.current.add(localRunId);
9347
- try {
9348
- await copilotkit.runAgent({
9349
- agent,
9350
- ...localRunId !== void 0 ? { runId: localRunId } : {}
9484
+ await enqueueSubmission(async () => {
9485
+ if (await waitForActiveRunToSettle() !== true) return;
9486
+ agent.addMessage({
9487
+ id: (0, _copilotkit_shared.randomUUID)(),
9488
+ role: "user",
9489
+ content: suggestion.message
9351
9490
  });
9352
- } catch (error) {
9353
- console.error("CopilotChat: runAgent failed after selecting suggestion", error);
9354
- } finally {
9355
- if (localRunId) {
9356
- activeLocalRunIdsRef.current.delete(localRunId);
9357
- rememberRecentlyLocalRunId(localRunId);
9358
- }
9359
- if (pendingRunActivityReconnectRef.current && activeLocalRunIdsRef.current.size === 0 && activeConnectCountRef.current === 0) {
9360
- const startReconnect = startRunActivityReconnectRef.current;
9361
- if (startReconnect) {
9362
- pendingRunActivityReconnectRef.current = false;
9363
- startReconnect(runActivityReconnectGenerationRef.current);
9491
+ const localRunId = hasNativeIntelligenceRunActivity ? (0, _copilotkit_shared.randomUUID)() : void 0;
9492
+ if (localRunId) activeLocalRunIdsRef.current.add(localRunId);
9493
+ try {
9494
+ await copilotkit.runAgent({
9495
+ agent,
9496
+ ...localRunId !== void 0 ? { runId: localRunId } : {}
9497
+ });
9498
+ } catch (error) {
9499
+ console.error("CopilotChat: runAgent failed after selecting suggestion", error);
9500
+ } finally {
9501
+ if (localRunId) {
9502
+ activeLocalRunIdsRef.current.delete(localRunId);
9503
+ rememberRecentlyLocalRunId(localRunId);
9504
+ }
9505
+ if (pendingRunActivityReconnectRef.current && activeLocalRunIdsRef.current.size === 0 && activeConnectCountRef.current === 0) {
9506
+ const startReconnect = startRunActivityReconnectRef.current;
9507
+ if (startReconnect) {
9508
+ pendingRunActivityReconnectRef.current = false;
9509
+ startReconnect(runActivityReconnectGenerationRef.current);
9510
+ }
9364
9511
  }
9365
9512
  }
9366
- }
9513
+ });
9367
9514
  }, [
9368
9515
  agent,
9369
9516
  waitForActiveRunToSettle,
9517
+ enqueueSubmission,
9370
9518
  hasNativeIntelligenceRunActivity,
9371
9519
  rememberRecentlyLocalRunId
9372
9520
  ]);
@@ -13747,6 +13895,8 @@ Object.defineProperty(exports, 'mergeMetadata', {
13747
13895
  return _ag_ui_client.mergeMetadata;
13748
13896
  }
13749
13897
  });
13898
+ exports.messageGroup = messageGroup;
13899
+ exports.messageRow = messageRow;
13750
13900
  Object.defineProperty(exports, 'ofType', {
13751
13901
  enumerable: true,
13752
13902
  get: function () {