@copilotkitnext/react 1.52.0-next.6 → 1.52.0-next.8

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/dist/components/chat/CopilotChatAssistantMessage.cjs +7 -0
  2. package/dist/components/chat/CopilotChatAssistantMessage.cjs.map +1 -1
  3. package/dist/components/chat/CopilotChatAssistantMessage.d.cts.map +1 -1
  4. package/dist/components/chat/CopilotChatAssistantMessage.d.mts.map +1 -1
  5. package/dist/components/chat/CopilotChatAssistantMessage.mjs +7 -0
  6. package/dist/components/chat/CopilotChatAssistantMessage.mjs.map +1 -1
  7. package/dist/components/chat/CopilotChatInput.cjs +7 -0
  8. package/dist/components/chat/CopilotChatInput.cjs.map +1 -1
  9. package/dist/components/chat/CopilotChatInput.d.cts.map +1 -1
  10. package/dist/components/chat/CopilotChatInput.d.mts.map +1 -1
  11. package/dist/components/chat/CopilotChatInput.mjs +7 -0
  12. package/dist/components/chat/CopilotChatInput.mjs.map +1 -1
  13. package/dist/components/chat/CopilotChatMessageView.cjs +20 -5
  14. package/dist/components/chat/CopilotChatMessageView.cjs.map +1 -1
  15. package/dist/components/chat/CopilotChatMessageView.d.cts +1 -0
  16. package/dist/components/chat/CopilotChatMessageView.d.cts.map +1 -1
  17. package/dist/components/chat/CopilotChatMessageView.d.mts +1 -0
  18. package/dist/components/chat/CopilotChatMessageView.d.mts.map +1 -1
  19. package/dist/components/chat/CopilotChatMessageView.mjs +21 -6
  20. package/dist/components/chat/CopilotChatMessageView.mjs.map +1 -1
  21. package/dist/components/chat/CopilotChatSuggestionPill.cjs +1 -0
  22. package/dist/components/chat/CopilotChatSuggestionPill.cjs.map +1 -1
  23. package/dist/components/chat/CopilotChatSuggestionPill.mjs +1 -0
  24. package/dist/components/chat/CopilotChatSuggestionPill.mjs.map +1 -1
  25. package/dist/components/chat/CopilotChatSuggestionView.cjs +1 -0
  26. package/dist/components/chat/CopilotChatSuggestionView.cjs.map +1 -1
  27. package/dist/components/chat/CopilotChatSuggestionView.d.cts.map +1 -1
  28. package/dist/components/chat/CopilotChatSuggestionView.d.mts.map +1 -1
  29. package/dist/components/chat/CopilotChatSuggestionView.mjs +1 -0
  30. package/dist/components/chat/CopilotChatSuggestionView.mjs.map +1 -1
  31. package/dist/components/chat/CopilotChatToggleButton.cjs +1 -0
  32. package/dist/components/chat/CopilotChatToggleButton.cjs.map +1 -1
  33. package/dist/components/chat/CopilotChatToggleButton.mjs +1 -0
  34. package/dist/components/chat/CopilotChatToggleButton.mjs.map +1 -1
  35. package/dist/components/chat/CopilotChatUserMessage.cjs +5 -0
  36. package/dist/components/chat/CopilotChatUserMessage.cjs.map +1 -1
  37. package/dist/components/chat/CopilotChatUserMessage.d.cts.map +1 -1
  38. package/dist/components/chat/CopilotChatUserMessage.d.mts.map +1 -1
  39. package/dist/components/chat/CopilotChatUserMessage.mjs +5 -0
  40. package/dist/components/chat/CopilotChatUserMessage.mjs.map +1 -1
  41. package/dist/components/chat/CopilotChatView.cjs +6 -0
  42. package/dist/components/chat/CopilotChatView.cjs.map +1 -1
  43. package/dist/components/chat/CopilotChatView.d.cts.map +1 -1
  44. package/dist/components/chat/CopilotChatView.d.mts.map +1 -1
  45. package/dist/components/chat/CopilotChatView.mjs +6 -0
  46. package/dist/components/chat/CopilotChatView.mjs.map +1 -1
  47. package/dist/components/chat/CopilotModalHeader.cjs +3 -0
  48. package/dist/components/chat/CopilotModalHeader.cjs.map +1 -1
  49. package/dist/components/chat/CopilotModalHeader.d.cts.map +1 -1
  50. package/dist/components/chat/CopilotModalHeader.d.mts.map +1 -1
  51. package/dist/components/chat/CopilotModalHeader.mjs +3 -0
  52. package/dist/components/chat/CopilotModalHeader.mjs.map +1 -1
  53. package/dist/components/chat/CopilotPopupView.cjs +1 -0
  54. package/dist/components/chat/CopilotPopupView.cjs.map +1 -1
  55. package/dist/components/chat/CopilotPopupView.d.cts.map +1 -1
  56. package/dist/components/chat/CopilotPopupView.d.mts.map +1 -1
  57. package/dist/components/chat/CopilotPopupView.mjs +1 -0
  58. package/dist/components/chat/CopilotPopupView.mjs.map +1 -1
  59. package/dist/components/chat/CopilotSidebarView.cjs +1 -0
  60. package/dist/components/chat/CopilotSidebarView.cjs.map +1 -1
  61. package/dist/components/chat/CopilotSidebarView.d.cts.map +1 -1
  62. package/dist/components/chat/CopilotSidebarView.d.mts.map +1 -1
  63. package/dist/components/chat/CopilotSidebarView.mjs +1 -0
  64. package/dist/components/chat/CopilotSidebarView.mjs.map +1 -1
  65. package/dist/hooks/index.cjs +1 -0
  66. package/dist/hooks/index.d.cts +2 -1
  67. package/dist/hooks/index.d.mts +2 -1
  68. package/dist/hooks/index.mjs +1 -0
  69. package/dist/hooks/use-interrupt.cjs +171 -0
  70. package/dist/hooks/use-interrupt.cjs.map +1 -0
  71. package/dist/hooks/use-interrupt.d.cts +102 -0
  72. package/dist/hooks/use-interrupt.d.cts.map +1 -0
  73. package/dist/hooks/use-interrupt.d.mts +102 -0
  74. package/dist/hooks/use-interrupt.d.mts.map +1 -0
  75. package/dist/hooks/use-interrupt.mjs +170 -0
  76. package/dist/hooks/use-interrupt.mjs.map +1 -0
  77. package/dist/index.cjs +2 -0
  78. package/dist/index.d.cts +3 -1
  79. package/dist/index.d.mts +3 -1
  80. package/dist/index.mjs +2 -1
  81. package/dist/index.umd.js +233 -5
  82. package/dist/index.umd.js.map +1 -1
  83. package/dist/lib/react-core.cjs +13 -0
  84. package/dist/lib/react-core.cjs.map +1 -1
  85. package/dist/lib/react-core.d.cts +8 -0
  86. package/dist/lib/react-core.d.cts.map +1 -1
  87. package/dist/lib/react-core.d.mts +8 -0
  88. package/dist/lib/react-core.d.mts.map +1 -1
  89. package/dist/lib/react-core.mjs +13 -0
  90. package/dist/lib/react-core.mjs.map +1 -1
  91. package/dist/types/index.d.cts +2 -1
  92. package/dist/types/index.d.mts +2 -1
  93. package/dist/types/interrupt.d.cts +17 -0
  94. package/dist/types/interrupt.d.cts.map +1 -0
  95. package/dist/types/interrupt.d.mts +17 -0
  96. package/dist/types/interrupt.d.mts.map +1 -0
  97. package/package.json +6 -6
package/dist/index.umd.js CHANGED
@@ -1018,6 +1018,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
1018
1018
  })
1019
1019
  }) : null;
1020
1020
  const inputPill = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1021
+ "data-testid": "copilot-chat-input",
1021
1022
  className: (0, tailwind_merge.twMerge)("cpk:flex cpk:w-full cpk:flex-col cpk:items-center cpk:justify-center", "cpk:cursor-text", "cpk:overflow-visible cpk:bg-clip-padding cpk:contain-inline-size", "cpk:bg-white cpk:dark:bg-[#303030]", "cpk:shadow-[0_4px_4px_0_#0000000a,0_0_1px_0_#0000009e] cpk:rounded-[28px]"),
1022
1023
  onClick: handleContainerClick,
1023
1024
  "data-layout": isExpanded ? "expanded" : "compact",
@@ -1066,6 +1067,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
1066
1067
  className: "cpk:mr-[10px]",
1067
1068
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
1068
1069
  type: "button",
1070
+ "data-testid": "copilot-send-button",
1069
1071
  variant: "chatInputToolbarPrimary",
1070
1072
  size: "chatInputToolbarIcon",
1071
1073
  className,
@@ -1093,18 +1095,21 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
1093
1095
  })] });
1094
1096
  };
1095
1097
  _CopilotChatInput.StartTranscribeButton = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
1098
+ "data-testid": "copilot-start-transcribe-button",
1096
1099
  icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Mic, { className: "cpk:size-[18px]" }),
1097
1100
  labelKey: "chatInputToolbarStartTranscribeButtonLabel",
1098
1101
  defaultClassName: "cpk:mr-2",
1099
1102
  ...props
1100
1103
  });
1101
1104
  _CopilotChatInput.CancelTranscribeButton = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
1105
+ "data-testid": "copilot-cancel-transcribe-button",
1102
1106
  icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.X, { className: "cpk:size-[18px]" }),
1103
1107
  labelKey: "chatInputToolbarCancelTranscribeButtonLabel",
1104
1108
  defaultClassName: "cpk:mr-2",
1105
1109
  ...props
1106
1110
  });
1107
1111
  _CopilotChatInput.FinishTranscribeButton = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
1112
+ "data-testid": "copilot-finish-transcribe-button",
1108
1113
  icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: "cpk:size-[18px]" }),
1109
1114
  labelKey: "chatInputToolbarFinishTranscribeButtonLabel",
1110
1115
  defaultClassName: "cpk:mr-[10px]",
@@ -1150,6 +1155,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
1150
1155
  asChild: true,
1151
1156
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
1152
1157
  type: "button",
1158
+ "data-testid": "copilot-add-menu-button",
1153
1159
  variant: "chatInputToolbarSecondary",
1154
1160
  size: "chatInputToolbarIcon",
1155
1161
  className: (0, tailwind_merge.twMerge)("cpk:ml-1", className),
@@ -1201,6 +1207,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
1201
1207
  }, [autoFocus]);
1202
1208
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
1203
1209
  ref: internalTextareaRef,
1210
+ "data-testid": "copilot-chat-textarea",
1204
1211
  placeholder: placeholder !== null && placeholder !== void 0 ? placeholder : labels.chatInputPlaceholder,
1205
1212
  className: (0, tailwind_merge.twMerge)("cpk:bg-transparent cpk:outline-none cpk:antialiased cpk:font-regular cpk:leading-relaxed cpk:text-[16px] cpk:placeholder:text-[#00000077] cpk:dark:placeholder:text-[#fffc]", className),
1206
1213
  style: {
@@ -1798,6 +1805,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1798
1805
  _defineProperty(this, "_renderToolCalls", []);
1799
1806
  _defineProperty(this, "_renderCustomMessages", []);
1800
1807
  _defineProperty(this, "_renderActivityMessages", []);
1808
+ _defineProperty(this, "_interruptElement", null);
1801
1809
  this._renderToolCalls = (_config$renderToolCal = config.renderToolCalls) !== null && _config$renderToolCal !== void 0 ? _config$renderToolCal : [];
1802
1810
  this._renderCustomMessages = (_config$renderCustomM = config.renderCustomMessages) !== null && _config$renderCustomM !== void 0 ? _config$renderCustomM : [];
1803
1811
  this._renderActivityMessages = (_config$renderActivit = config.renderActivityMessages) !== null && _config$renderActivit !== void 0 ? _config$renderActivit : [];
@@ -1821,6 +1829,20 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1821
1829
  });
1822
1830
  }, "Subscriber onRenderToolCallsChanged error:");
1823
1831
  }
1832
+ get interruptElement() {
1833
+ return this._interruptElement;
1834
+ }
1835
+ setInterruptElement(element) {
1836
+ this._interruptElement = element;
1837
+ this.notifySubscribers((subscriber) => {
1838
+ var _reactSubscriber$onIn;
1839
+ const reactSubscriber = subscriber;
1840
+ (_reactSubscriber$onIn = reactSubscriber.onInterruptElementChanged) === null || _reactSubscriber$onIn === void 0 || _reactSubscriber$onIn.call(reactSubscriber, {
1841
+ copilotkit: this,
1842
+ interruptElement: this._interruptElement
1843
+ });
1844
+ }, "Subscriber onInterruptElementChanged error:");
1845
+ }
1824
1846
  subscribe(subscriber) {
1825
1847
  return super.subscribe(subscriber);
1826
1848
  }
@@ -2956,6 +2978,170 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2956
2978
  });
2957
2979
  }
2958
2980
 
2981
+ //#endregion
2982
+ //#region src/hooks/use-interrupt.tsx
2983
+ const INTERRUPT_EVENT_NAME = "on_interrupt";
2984
+ function isPromiseLike(value) {
2985
+ return (typeof value === "object" || typeof value === "function") && value !== null && typeof Reflect.get(value, "then") === "function";
2986
+ }
2987
+ /**
2988
+ * Handles agent interrupts (`on_interrupt`) with optional filtering, preprocessing, and resume behavior.
2989
+ *
2990
+ * The hook listens to custom events on the active agent, stores interrupt payloads per run,
2991
+ * and surfaces a render callback once the run finalizes. Call `resolve` from your UI to resume
2992
+ * execution with user-provided data.
2993
+ *
2994
+ * - `renderInChat: true` (default): the element is published into `<CopilotChat>` and this hook returns `void`.
2995
+ * - `renderInChat: false`: the hook returns the interrupt element so you can place it anywhere in your component tree.
2996
+ *
2997
+ * `event.value` is typed as `any` since the interrupt payload shape depends on your agent.
2998
+ * Type-narrow it in your callbacks (e.g. `handler`, `enabled`, `render`) as needed.
2999
+ *
3000
+ * @typeParam TResult - Inferred from `handler` return type. Exposed as `result` in `render`.
3001
+ * @param config - Interrupt configuration (renderer, optional handler/filter, and render mode).
3002
+ * @returns When `renderInChat` is `false`, returns the interrupt element (or `null` when idle).
3003
+ * Otherwise returns `void` and publishes the element into chat. In `render`, `result` is always
3004
+ * either the handler's resolved return value or `null` (including when no handler is provided,
3005
+ * when filtering skips the interrupt, or when handler execution fails).
3006
+ *
3007
+ * @example
3008
+ * ```tsx
3009
+ * import { useInterrupt } from "@copilotkitnext/react";
3010
+ *
3011
+ * function InterruptUI() {
3012
+ * useInterrupt({
3013
+ * render: ({ event, resolve }) => (
3014
+ * <div>
3015
+ * <p>{event.value.question}</p>
3016
+ * <button onClick={() => resolve({ approved: true })}>Approve</button>
3017
+ * <button onClick={() => resolve({ approved: false })}>Reject</button>
3018
+ * </div>
3019
+ * ),
3020
+ * });
3021
+ *
3022
+ * return null;
3023
+ * }
3024
+ * ```
3025
+ *
3026
+ * @example
3027
+ * ```tsx
3028
+ * import { useInterrupt } from "@copilotkitnext/react";
3029
+ *
3030
+ * function CustomPanel() {
3031
+ * const interruptElement = useInterrupt({
3032
+ * renderInChat: false,
3033
+ * enabled: (event) => event.value.startsWith("approval:"),
3034
+ * handler: async ({ event }) => ({ label: event.value.toUpperCase() }),
3035
+ * render: ({ event, result, resolve }) => (
3036
+ * <aside>
3037
+ * <strong>{result?.label ?? ""}</strong>
3038
+ * <button onClick={() => resolve({ value: event.value })}>Continue</button>
3039
+ * </aside>
3040
+ * ),
3041
+ * });
3042
+ *
3043
+ * return <>{interruptElement}</>;
3044
+ * }
3045
+ * ```
3046
+ */
3047
+ function useInterrupt(config) {
3048
+ const { copilotkit } = useCopilotKit();
3049
+ const { agent } = useAgent({ agentId: config.agentId });
3050
+ const [pendingEvent, setPendingEvent] = (0, react.useState)(null);
3051
+ const [handlerResult, setHandlerResult] = (0, react.useState)(null);
3052
+ (0, react.useEffect)(() => {
3053
+ let localInterrupt = null;
3054
+ const subscription = agent.subscribe({
3055
+ onCustomEvent: ({ event }) => {
3056
+ if (event.name === INTERRUPT_EVENT_NAME) localInterrupt = {
3057
+ name: event.name,
3058
+ value: event.value
3059
+ };
3060
+ },
3061
+ onRunStartedEvent: () => {
3062
+ localInterrupt = null;
3063
+ setPendingEvent(null);
3064
+ },
3065
+ onRunFinalized: () => {
3066
+ if (localInterrupt) {
3067
+ setPendingEvent(localInterrupt);
3068
+ localInterrupt = null;
3069
+ }
3070
+ },
3071
+ onRunFailed: () => {
3072
+ localInterrupt = null;
3073
+ }
3074
+ });
3075
+ return () => subscription.unsubscribe();
3076
+ }, [agent]);
3077
+ const resolve = (0, react.useCallback)((response) => {
3078
+ setPendingEvent(null);
3079
+ copilotkit.runAgent({
3080
+ agent,
3081
+ forwardedProps: { command: { resume: response } }
3082
+ });
3083
+ }, [agent, copilotkit]);
3084
+ (0, react.useEffect)(() => {
3085
+ if (!pendingEvent) {
3086
+ setHandlerResult(null);
3087
+ return;
3088
+ }
3089
+ if (config.enabled && !config.enabled(pendingEvent)) {
3090
+ setHandlerResult(null);
3091
+ return;
3092
+ }
3093
+ const handler = config.handler;
3094
+ if (!handler) {
3095
+ setHandlerResult(null);
3096
+ return;
3097
+ }
3098
+ let cancelled = false;
3099
+ const maybePromise = handler({
3100
+ event: pendingEvent,
3101
+ resolve
3102
+ });
3103
+ if (isPromiseLike(maybePromise)) Promise.resolve(maybePromise).then((resolved) => {
3104
+ if (!cancelled) setHandlerResult(resolved);
3105
+ }).catch(() => {
3106
+ if (!cancelled) setHandlerResult(null);
3107
+ });
3108
+ else setHandlerResult(maybePromise);
3109
+ return () => {
3110
+ cancelled = true;
3111
+ };
3112
+ }, [
3113
+ pendingEvent,
3114
+ config.enabled,
3115
+ config.handler,
3116
+ resolve
3117
+ ]);
3118
+ const element = (0, react.useMemo)(() => {
3119
+ if (!pendingEvent) return null;
3120
+ if (config.enabled && !config.enabled(pendingEvent)) return null;
3121
+ return config.render({
3122
+ event: pendingEvent,
3123
+ result: handlerResult,
3124
+ resolve
3125
+ });
3126
+ }, [
3127
+ pendingEvent,
3128
+ handlerResult,
3129
+ config.enabled,
3130
+ config.render,
3131
+ resolve
3132
+ ]);
3133
+ (0, react.useEffect)(() => {
3134
+ if (config.renderInChat === false) return;
3135
+ copilotkit.setInterruptElement(element);
3136
+ return () => copilotkit.setInterruptElement(null);
3137
+ }, [
3138
+ element,
3139
+ config.renderInChat,
3140
+ copilotkit
3141
+ ]);
3142
+ if (config.renderInChat === false) return element;
3143
+ }
3144
+
2959
3145
  //#endregion
2960
3146
  //#region src/components/chat/CopilotChatToolCallsView.tsx
2961
3147
  function CopilotChatToolCallsView({ message, messages = [] }) {
@@ -3029,6 +3215,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3029
3215
  });
3030
3216
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3031
3217
  "data-copilotkit": true,
3218
+ "data-testid": "copilot-assistant-message",
3032
3219
  className: (0, tailwind_merge.twMerge)(className),
3033
3220
  ...props,
3034
3221
  "data-message-id": message.id,
@@ -3049,6 +3236,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3049
3236
  children: content !== null && content !== void 0 ? content : ""
3050
3237
  });
3051
3238
  _CopilotChatAssistantMessage.Toolbar = ({ className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3239
+ "data-testid": "copilot-assistant-toolbar",
3052
3240
  className: (0, tailwind_merge.twMerge)("cpk:w-full cpk:bg-transparent cpk:flex cpk:items-center cpk:-ml-[5px] cpk:-mt-[0px]", className),
3053
3241
  ...props
3054
3242
  });
@@ -3078,6 +3266,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3078
3266
  if (onClick) onClick(event);
3079
3267
  };
3080
3268
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
3269
+ "data-testid": "copilot-copy-button",
3081
3270
  title: title || labels.assistantMessageToolbarCopyMessageLabel,
3082
3271
  onClick: handleClick,
3083
3272
  className,
@@ -3090,6 +3279,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3090
3279
  const config = useCopilotChatConfiguration();
3091
3280
  const labels = (_config$labels2 = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels2 !== void 0 ? _config$labels2 : CopilotChatDefaultLabels;
3092
3281
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
3282
+ "data-testid": "copilot-thumbs-up-button",
3093
3283
  title: title || labels.assistantMessageToolbarThumbsUpLabel,
3094
3284
  ...props,
3095
3285
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ThumbsUp, { className: "cpk:size-[18px]" })
@@ -3100,6 +3290,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3100
3290
  const config = useCopilotChatConfiguration();
3101
3291
  const labels = (_config$labels3 = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels3 !== void 0 ? _config$labels3 : CopilotChatDefaultLabels;
3102
3292
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
3293
+ "data-testid": "copilot-thumbs-down-button",
3103
3294
  title: title || labels.assistantMessageToolbarThumbsDownLabel,
3104
3295
  ...props,
3105
3296
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ThumbsDown, { className: "cpk:size-[18px]" })
@@ -3110,6 +3301,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3110
3301
  const config = useCopilotChatConfiguration();
3111
3302
  const labels = (_config$labels4 = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels4 !== void 0 ? _config$labels4 : CopilotChatDefaultLabels;
3112
3303
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
3304
+ "data-testid": "copilot-read-aloud-button",
3113
3305
  title: title || labels.assistantMessageToolbarReadAloudLabel,
3114
3306
  ...props,
3115
3307
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Volume2, { className: "cpk:size-[20px]" })
@@ -3120,6 +3312,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3120
3312
  const config = useCopilotChatConfiguration();
3121
3313
  const labels = (_config$labels5 = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels5 !== void 0 ? _config$labels5 : CopilotChatDefaultLabels;
3122
3314
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
3315
+ "data-testid": "copilot-regenerate-button",
3123
3316
  title: title || labels.assistantMessageToolbarRegenerateLabel,
3124
3317
  ...props,
3125
3318
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.RefreshCw, { className: "cpk:size-[18px]" })
@@ -3189,6 +3382,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3189
3382
  });
3190
3383
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3191
3384
  "data-copilotkit": true,
3385
+ "data-testid": "copilot-user-message",
3192
3386
  className: (0, tailwind_merge.twMerge)("cpk:flex cpk:flex-col cpk:items-end cpk:group cpk:pt-10", className),
3193
3387
  "data-message-id": message.id,
3194
3388
  ...props,
@@ -3206,6 +3400,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3206
3400
  children: content
3207
3401
  });
3208
3402
  _CopilotChatUserMessage.Toolbar = ({ className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3403
+ "data-testid": "copilot-user-toolbar",
3209
3404
  className: (0, tailwind_merge.twMerge)("cpk:w-full cpk:bg-transparent cpk:flex cpk:items-center cpk:justify-end cpk:-mr-[5px] cpk:mt-[4px] cpk:invisible cpk:group-hover:visible", className),
3210
3405
  ...props
3211
3406
  });
@@ -3236,6 +3431,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3236
3431
  if (onClick) onClick(event);
3237
3432
  };
3238
3433
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
3434
+ "data-testid": "copilot-user-copy-button",
3239
3435
  title: title || labels.userMessageToolbarCopyMessageLabel,
3240
3436
  onClick: handleClick,
3241
3437
  className,
@@ -3248,6 +3444,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3248
3444
  const config = useCopilotChatConfiguration();
3249
3445
  const labels = (_config$labels2 = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels2 !== void 0 ? _config$labels2 : CopilotChatDefaultLabels;
3250
3446
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
3447
+ "data-testid": "copilot-edit-button",
3251
3448
  title: title || labels.userMessageToolbarEditMessageLabel,
3252
3449
  className,
3253
3450
  ...props,
@@ -3259,6 +3456,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3259
3456
  const canGoPrev = currentBranch > 0;
3260
3457
  const canGoNext = currentBranch < numberOfBranches - 1;
3261
3458
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3459
+ "data-testid": "copilot-branch-navigation",
3262
3460
  className: (0, tailwind_merge.twMerge)("cpk:flex cpk:items-center cpk:gap-1", className),
3263
3461
  ...props,
3264
3462
  children: [
@@ -3442,6 +3640,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3442
3640
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
3443
3641
  ref,
3444
3642
  "data-copilotkit": true,
3643
+ "data-testid": "copilot-suggestion",
3445
3644
  "data-slot": "suggestion-pill",
3446
3645
  className: cn(baseClasses, className),
3447
3646
  type: type !== null && type !== void 0 ? type : "button",
@@ -3471,6 +3670,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3471
3670
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3472
3671
  ref,
3473
3672
  "data-copilotkit": true,
3673
+ "data-testid": "copilot-suggestions",
3474
3674
  className: cn("cpk:flex cpk:flex-wrap cpk:items-center cpk:gap-1.5 cpk:sm:gap-2 cpk:pl-0 cpk:pr-4 cpk:sm:px-0 cpk:pointer-events-none", className),
3475
3675
  ...props
3476
3676
  });
@@ -3645,6 +3845,14 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3645
3845
  copilotkit,
3646
3846
  forceUpdate
3647
3847
  ]);
3848
+ const [interruptElement, setInterruptElement] = (0, react.useState)(null);
3849
+ (0, react.useEffect)(() => {
3850
+ setInterruptElement(copilotkit.interruptElement);
3851
+ const subscription = copilotkit.subscribe({ onInterruptElementChanged: ({ interruptElement }) => {
3852
+ setInterruptElement(interruptElement);
3853
+ } });
3854
+ return () => subscription.unsubscribe();
3855
+ }, [copilotkit]);
3648
3856
  const getStateSnapshotForMessage = (messageId) => {
3649
3857
  var _copilotkit$getRunIdF;
3650
3858
  if (!config) return void 0;
@@ -3719,23 +3927,30 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3719
3927
  children: children({
3720
3928
  messageElements,
3721
3929
  messages,
3722
- isRunning
3930
+ isRunning,
3931
+ interruptElement
3723
3932
  })
3724
3933
  });
3725
3934
  const lastMessage = messages[messages.length - 1];
3726
3935
  const showCursor = isRunning && (lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.role) !== "reasoning";
3727
3936
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3728
3937
  "data-copilotkit": true,
3938
+ "data-testid": "copilot-message-list",
3729
3939
  className: (0, tailwind_merge.twMerge)("cpk:flex cpk:flex-col", className),
3730
3940
  ...props,
3731
- children: [messageElements, showCursor && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3732
- className: "cpk:mt-2",
3733
- children: renderSlot(cursor, CopilotChatMessageView.Cursor, {})
3734
- })]
3941
+ children: [
3942
+ messageElements,
3943
+ interruptElement,
3944
+ showCursor && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3945
+ className: "cpk:mt-2",
3946
+ children: renderSlot(cursor, CopilotChatMessageView.Cursor, {})
3947
+ })
3948
+ ]
3735
3949
  });
3736
3950
  }
3737
3951
  CopilotChatMessageView.Cursor = function Cursor({ className, ...props }) {
3738
3952
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3953
+ "data-testid": "copilot-loading-cursor",
3739
3954
  className: (0, tailwind_merge.twMerge)("cpk:w-[11px] cpk:h-[11px] cpk:rounded-full cpk:bg-foreground cpk:animate-pulse-cursor cpk:ml-1", className),
3740
3955
  ...props
3741
3956
  });
@@ -3880,6 +4095,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3880
4095
  });
3881
4096
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3882
4097
  "data-copilotkit": true,
4098
+ "data-testid": "copilot-chat",
4099
+ "data-copilot-running": isRunning ? "true" : "false",
3883
4100
  className: (0, tailwind_merge.twMerge)("cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
3884
4101
  ...props,
3885
4102
  children: BoundWelcomeScreen
@@ -3897,6 +4114,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3897
4114
  });
3898
4115
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3899
4116
  "data-copilotkit": true,
4117
+ "data-testid": "copilot-chat",
4118
+ "data-copilot-running": isRunning ? "true" : "false",
3900
4119
  className: (0, tailwind_merge.twMerge)("cpk:relative cpk:h-full", className),
3901
4120
  ...props,
3902
4121
  children: [BoundScrollView, BoundInput]
@@ -3992,6 +4211,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3992
4211
  });
3993
4212
  };
3994
4213
  _CopilotChatView.ScrollToBottomButton = ({ className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
4214
+ "data-testid": "copilot-scroll-to-bottom",
3995
4215
  variant: "outline",
3996
4216
  size: "sm",
3997
4217
  className: (0, tailwind_merge.twMerge)("cpk:rounded-full cpk:w-10 cpk:h-10 cpk:p-0 cpk:pointer-events-auto", "cpk:bg-white cpk:dark:bg-gray-900", "cpk:shadow-lg cpk:border cpk:border-gray-200 cpk:dark:border-gray-700", "cpk:hover:bg-gray-50 cpk:dark:hover:bg-gray-800", "cpk:flex cpk:items-center cpk:justify-center cpk:cursor-pointer", className),
@@ -4027,6 +4247,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
4027
4247
  })
4028
4248
  });
4029
4249
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4250
+ "data-testid": "copilot-welcome-screen",
4030
4251
  className: cn("cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4", className),
4031
4252
  ...props,
4032
4253
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
@@ -4420,6 +4641,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
4420
4641
  ref,
4421
4642
  type: type !== null && type !== void 0 ? type : "button",
4422
4643
  "data-copilotkit": true,
4644
+ "data-testid": "copilot-chat-toggle",
4423
4645
  "data-slot": "chat-toggle-button",
4424
4646
  "data-state": isOpen ? "open" : "closed",
4425
4647
  className: cn(BUTTON_BASE_CLASSES, className),
@@ -4453,6 +4675,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
4453
4675
  ...rest
4454
4676
  });
4455
4677
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", {
4678
+ "data-testid": "copilot-modal-header",
4456
4679
  "data-slot": "copilot-modal-header",
4457
4680
  className: cn("cpk:flex cpk:items-center cpk:justify-between cpk:border-b cpk:border-border cpk:px-4 cpk:py-4", "cpk:bg-background/95 cpk:backdrop-blur cpk:supports-[backdrop-filter]:bg-background/80", className),
4458
4681
  ...rest,
@@ -4478,12 +4701,14 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
4478
4701
  CopilotModalHeader.displayName = "CopilotModalHeader";
4479
4702
  (function(_CopilotModalHeader) {
4480
4703
  _CopilotModalHeader.Title = ({ children, className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4704
+ "data-testid": "copilot-header-title",
4481
4705
  className: cn("cpk:w-full cpk:text-base cpk:font-medium cpk:leading-none cpk:tracking-tight cpk:text-foreground", className),
4482
4706
  ...props,
4483
4707
  children
4484
4708
  });
4485
4709
  _CopilotModalHeader.CloseButton = ({ className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
4486
4710
  type: "button",
4711
+ "data-testid": "copilot-close-button",
4487
4712
  className: cn("cpk:inline-flex cpk:size-8 cpk:items-center cpk:justify-center cpk:rounded-full cpk:text-muted-foreground cpk:transition cpk:cursor-pointer", "cpk:hover:bg-muted cpk:hover:text-foreground cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-ring", className),
4488
4713
  "aria-label": "Close",
4489
4714
  ...props,
@@ -4563,6 +4788,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
4563
4788
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [renderSlot(toggleButton, CopilotChatToggleButton, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("aside", {
4564
4789
  ref: sidebarRef,
4565
4790
  "data-copilotkit": true,
4791
+ "data-testid": "copilot-sidebar",
4566
4792
  "data-copilot-sidebar": true,
4567
4793
  className: cn("cpk:fixed cpk:right-0 cpk:top-0 cpk:z-[1200] cpk:flex", "cpk:h-[100vh] cpk:h-[100dvh] cpk:max-h-screen", "cpk:w-full", "cpk:border-l cpk:border-border cpk:bg-background cpk:text-foreground cpk:shadow-xl", "cpk:transition-transform cpk:duration-300 cpk:ease-out", isSidebarOpen ? "cpk:translate-x-0" : "cpk:translate-x-full cpk:pointer-events-none"),
4568
4794
  style: {
@@ -4726,6 +4952,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
4726
4952
  tabIndex: -1,
4727
4953
  role: "dialog",
4728
4954
  "aria-label": labels.modalHeaderTitle,
4955
+ "data-testid": "copilot-popup",
4729
4956
  "data-copilot-popup": true,
4730
4957
  className: cn("cpk:relative cpk:flex cpk:h-full cpk:w-full cpk:flex-col cpk:overflow-hidden cpk:bg-background cpk:text-foreground", "cpk:origin-bottom cpk:focus:outline-none cpk:transform-gpu cpk:transition-transform cpk:transition-opacity cpk:duration-200 cpk:ease-out", "cpk:md:transition-transform cpk:md:transition-opacity", "cpk:rounded-none cpk:border cpk:border-border/0 cpk:shadow-none cpk:ring-0", "cpk:md:h-[var(--copilot-popup-height)] cpk:md:w-[var(--copilot-popup-width)]", "cpk:md:max-h-[var(--copilot-popup-max-height)] cpk:md:max-w-[var(--copilot-popup-max-width)]", "cpk:md:origin-bottom-right cpk:md:rounded-2xl cpk:md:border-border cpk:md:shadow-xl cpk:md:ring-1 cpk:md:ring-border/40", popupAnimationClass),
4731
4958
  style: popupStyle,
@@ -4952,6 +5179,7 @@ exports.useCopilotKit = useCopilotKit;
4952
5179
  exports.useDefaultRenderTool = useDefaultRenderTool;
4953
5180
  exports.useFrontendTool = useFrontendTool;
4954
5181
  exports.useHumanInTheLoop = useHumanInTheLoop;
5182
+ exports.useInterrupt = useInterrupt;
4955
5183
  exports.useRenderActivityMessage = useRenderActivityMessage;
4956
5184
  exports.useRenderCustomMessages = useRenderCustomMessages;
4957
5185
  exports.useRenderTool = useRenderTool;