@copilotkit/react-core 1.57.3 → 1.58.0

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 (282) hide show
  1. package/LICENSE +21 -0
  2. package/dist/{copilotkit-CC8DjOiC.mjs → copilotkit-BIn7HE8f.mjs} +2 -2
  3. package/dist/{copilotkit-CC8DjOiC.mjs.map → copilotkit-BIn7HE8f.mjs.map} +1 -1
  4. package/dist/{copilotkit-CtXcs1ea.cjs → copilotkit-Drw-g6zA.cjs} +2 -2
  5. package/dist/{copilotkit-CtXcs1ea.cjs.map → copilotkit-Drw-g6zA.cjs.map} +1 -1
  6. package/dist/index.cjs +3 -77
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.cts +2 -2
  9. package/dist/index.d.mts +2 -2
  10. package/dist/index.mjs +3 -77
  11. package/dist/index.mjs.map +1 -1
  12. package/dist/index.umd.js +3 -77
  13. package/dist/index.umd.js.map +1 -1
  14. package/dist/v2/index.cjs +1 -1
  15. package/dist/v2/index.mjs +1 -1
  16. package/dist/v2/index.umd.js +1 -1
  17. package/dist/v2/index.umd.js.map +1 -1
  18. package/package.json +12 -13
  19. package/skills/react-core/SKILL.md +108 -0
  20. package/skills/react-core/references/agent-access.md +288 -0
  21. package/skills/react-core/references/attachments.md +291 -0
  22. package/skills/react-core/references/capabilities.md +138 -0
  23. package/skills/react-core/references/chat-components.md +221 -0
  24. package/skills/react-core/references/client-side-tools.md +358 -0
  25. package/skills/react-core/references/custom-message-renderers.md +226 -0
  26. package/skills/react-core/references/debug-mode.md +153 -0
  27. package/skills/react-core/references/human-in-the-loop.md +312 -0
  28. package/skills/react-core/references/provider-setup.md +326 -0
  29. package/skills/react-core/references/rendering-activity-messages.md +207 -0
  30. package/skills/react-core/references/rendering-tool-calls.md +319 -0
  31. package/skills/react-core/references/suggestions.md +211 -0
  32. package/skills/react-core/references/switching-agents-recipes.md +160 -0
  33. package/skills/react-core/references/switching-agents.md +231 -0
  34. package/skills/react-core/references/threads.md +226 -0
  35. package/.attw.json +0 -3
  36. package/CHANGELOG.md +0 -5043
  37. package/scripts/scope-preflight.mjs +0 -100
  38. package/src/components/CopilotListeners.tsx +0 -137
  39. package/src/components/__tests__/CopilotListeners.test.tsx +0 -38
  40. package/src/components/copilot-provider/__tests__/copilot-messages-key.test.tsx +0 -92
  41. package/src/components/copilot-provider/__tests__/copilotkit-error.test.tsx +0 -77
  42. package/src/components/copilot-provider/__tests__/error-visibility-prod.test.tsx +0 -70
  43. package/src/components/copilot-provider/__tests__/v1-explicit-threadid-bridge.test.tsx +0 -107
  44. package/src/components/copilot-provider/copilot-messages.tsx +0 -314
  45. package/src/components/copilot-provider/copilotkit-props.tsx +0 -214
  46. package/src/components/copilot-provider/copilotkit.tsx +0 -853
  47. package/src/components/copilot-provider/index.ts +0 -3
  48. package/src/components/dev-console/console-trigger.tsx +0 -283
  49. package/src/components/dev-console/developer-console-modal.tsx +0 -1016
  50. package/src/components/dev-console/icons.tsx +0 -106
  51. package/src/components/error-boundary/error-boundary.tsx +0 -99
  52. package/src/components/error-boundary/error-utils.tsx +0 -105
  53. package/src/components/index.ts +0 -1
  54. package/src/components/toast/exclamation-mark-icon.tsx +0 -27
  55. package/src/components/toast/toast-provider.tsx +0 -448
  56. package/src/components/usage-banner.tsx +0 -266
  57. package/src/context/__tests__/threads-context.test.tsx +0 -141
  58. package/src/context/coagent-state-renders-context.tsx +0 -89
  59. package/src/context/copilot-context.tsx +0 -365
  60. package/src/context/copilot-messages-context.tsx +0 -35
  61. package/src/context/index.ts +0 -22
  62. package/src/context/threads-context.tsx +0 -69
  63. package/src/hooks/__tests__/use-coagent-config.test.ts +0 -352
  64. package/src/hooks/__tests__/use-coagent-state-render-bridge.helpers.test.ts +0 -107
  65. package/src/hooks/__tests__/use-coagent-state-render.e2e.test.tsx +0 -1209
  66. package/src/hooks/__tests__/use-coagent-state-render.test.tsx +0 -356
  67. package/src/hooks/__tests__/use-copilot-chat-internal-connect.test.tsx +0 -241
  68. package/src/hooks/__tests__/use-frontend-tool-available.test.tsx +0 -72
  69. package/src/hooks/__tests__/use-frontend-tool-remount.e2e.test.tsx +0 -102
  70. package/src/hooks/index.ts +0 -33
  71. package/src/hooks/use-agent-nodename.ts +0 -33
  72. package/src/hooks/use-coagent-state-render-bridge.helpers.ts +0 -345
  73. package/src/hooks/use-coagent-state-render-bridge.tsx +0 -222
  74. package/src/hooks/use-coagent-state-render-registry.ts +0 -230
  75. package/src/hooks/use-coagent-state-render.ts +0 -163
  76. package/src/hooks/use-coagent.ts +0 -377
  77. package/src/hooks/use-configure-chat-suggestions.tsx +0 -96
  78. package/src/hooks/use-copilot-action.ts +0 -245
  79. package/src/hooks/use-copilot-additional-instructions.ts +0 -98
  80. package/src/hooks/use-copilot-authenticated-action.ts +0 -73
  81. package/src/hooks/use-copilot-chat-headless_c.ts +0 -264
  82. package/src/hooks/use-copilot-chat-suggestions.tsx +0 -134
  83. package/src/hooks/use-copilot-chat.ts +0 -132
  84. package/src/hooks/use-copilot-chat_internal.ts +0 -875
  85. package/src/hooks/use-copilot-readable.ts +0 -135
  86. package/src/hooks/use-copilot-runtime-client.ts +0 -178
  87. package/src/hooks/use-default-tool.ts +0 -13
  88. package/src/hooks/use-flat-category-store.ts +0 -109
  89. package/src/hooks/use-frontend-tool.ts +0 -113
  90. package/src/hooks/use-human-in-the-loop.ts +0 -138
  91. package/src/hooks/use-langgraph-interrupt.ts +0 -103
  92. package/src/hooks/use-lazy-tool-renderer.tsx +0 -30
  93. package/src/hooks/use-make-copilot-document-readable.ts +0 -30
  94. package/src/hooks/use-render-tool-call.ts +0 -89
  95. package/src/hooks/use-tree.ts +0 -222
  96. package/src/index.tsx +0 -7
  97. package/src/lib/copilot-task.ts +0 -215
  98. package/src/lib/index.ts +0 -1
  99. package/src/lib/status-checker.ts +0 -67
  100. package/src/setupTests.ts +0 -37
  101. package/src/test-helpers/copilot-context.ts +0 -91
  102. package/src/types/chat-suggestion-configuration.ts +0 -23
  103. package/src/types/coagent-action.ts +0 -35
  104. package/src/types/coagent-state.ts +0 -13
  105. package/src/types/crew.ts +0 -89
  106. package/src/types/document-pointer.ts +0 -7
  107. package/src/types/frontend-action.ts +0 -213
  108. package/src/types/index.ts +0 -17
  109. package/src/types/interrupt-action.ts +0 -58
  110. package/src/types/system-message.ts +0 -4
  111. package/src/utils/dev-console.ts +0 -19
  112. package/src/utils/index.ts +0 -2
  113. package/src/utils/suggestions-constants.ts +0 -8
  114. package/src/utils/utils.test.ts +0 -7
  115. package/src/utils/utils.ts +0 -6
  116. package/src/v2/__tests__/A2UIMessageRenderer.test.tsx +0 -240
  117. package/src/v2/__tests__/globalSetup.ts +0 -14
  118. package/src/v2/__tests__/setup.ts +0 -93
  119. package/src/v2/__tests__/utils/test-helpers.tsx +0 -570
  120. package/src/v2/a2ui/A2UICatalogContext.tsx +0 -79
  121. package/src/v2/a2ui/A2UIMessageRenderer.tsx +0 -294
  122. package/src/v2/a2ui/A2UIToolCallRenderer.tsx +0 -290
  123. package/src/v2/components/CopilotKitInspector.tsx +0 -52
  124. package/src/v2/components/MCPAppsActivityRenderer.tsx +0 -815
  125. package/src/v2/components/OpenGenerativeUIRenderer.tsx +0 -598
  126. package/src/v2/components/WildcardToolCallRender.tsx +0 -86
  127. package/src/v2/components/__tests__/OpenGenerativeUIRenderer.test.tsx +0 -665
  128. package/src/v2/components/chat/CopilotChat.tsx +0 -664
  129. package/src/v2/components/chat/CopilotChatAssistantMessage.tsx +0 -393
  130. package/src/v2/components/chat/CopilotChatAttachmentQueue.tsx +0 -374
  131. package/src/v2/components/chat/CopilotChatAttachmentRenderer.tsx +0 -159
  132. package/src/v2/components/chat/CopilotChatAudioRecorder.tsx +0 -350
  133. package/src/v2/components/chat/CopilotChatInput.tsx +0 -1412
  134. package/src/v2/components/chat/CopilotChatMessageView.tsx +0 -716
  135. package/src/v2/components/chat/CopilotChatReasoningMessage.tsx +0 -265
  136. package/src/v2/components/chat/CopilotChatSuggestionPill.tsx +0 -59
  137. package/src/v2/components/chat/CopilotChatSuggestionView.tsx +0 -134
  138. package/src/v2/components/chat/CopilotChatToggleButton.tsx +0 -171
  139. package/src/v2/components/chat/CopilotChatToolCallsView.tsx +0 -40
  140. package/src/v2/components/chat/CopilotChatUserMessage.tsx +0 -445
  141. package/src/v2/components/chat/CopilotChatView.tsx +0 -890
  142. package/src/v2/components/chat/CopilotModalHeader.tsx +0 -129
  143. package/src/v2/components/chat/CopilotPopup.tsx +0 -81
  144. package/src/v2/components/chat/CopilotPopupView.tsx +0 -317
  145. package/src/v2/components/chat/CopilotSidebar.tsx +0 -80
  146. package/src/v2/components/chat/CopilotSidebarView.tsx +0 -269
  147. package/src/v2/components/chat/Lightbox.tsx +0 -103
  148. package/src/v2/components/chat/__tests__/CopilotChat.absentThreadConnect.test.tsx +0 -66
  149. package/src/v2/components/chat/__tests__/CopilotChat.attachments.test.tsx +0 -168
  150. package/src/v2/components/chat/__tests__/CopilotChat.e2e.test.tsx +0 -1239
  151. package/src/v2/components/chat/__tests__/CopilotChat.onError.test.tsx +0 -73
  152. package/src/v2/components/chat/__tests__/CopilotChat.slots.e2e.test.tsx +0 -432
  153. package/src/v2/components/chat/__tests__/CopilotChat.suggestionsAlways.test.tsx +0 -183
  154. package/src/v2/components/chat/__tests__/CopilotChat.welcomeGate.test.tsx +0 -184
  155. package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.tsx +0 -649
  156. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.slots.e2e.test.tsx +0 -624
  157. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.test.tsx +0 -702
  158. package/src/v2/components/chat/__tests__/CopilotChatAssistantMessage.thumbs.test.tsx +0 -72
  159. package/src/v2/components/chat/__tests__/CopilotChatCopyButton.clipboard.test.tsx +0 -241
  160. package/src/v2/components/chat/__tests__/CopilotChatCssClasses.test.tsx +0 -107
  161. package/src/v2/components/chat/__tests__/CopilotChatInput.slots.e2e.test.tsx +0 -929
  162. package/src/v2/components/chat/__tests__/CopilotChatInput.test.tsx +0 -1567
  163. package/src/v2/components/chat/__tests__/CopilotChatMessageView.slots.e2e.test.tsx +0 -1004
  164. package/src/v2/components/chat/__tests__/CopilotChatMessageView.test.tsx +0 -279
  165. package/src/v2/components/chat/__tests__/CopilotChatPerf.e2e.test.tsx +0 -336
  166. package/src/v2/components/chat/__tests__/CopilotChatPropsRerender.e2e.test.tsx +0 -249
  167. package/src/v2/components/chat/__tests__/CopilotChatSuggestionView.slots.e2e.test.tsx +0 -530
  168. package/src/v2/components/chat/__tests__/CopilotChatToolRendering.e2e.test.tsx +0 -785
  169. package/src/v2/components/chat/__tests__/CopilotChatToolRerenders.e2e.test.tsx +0 -2416
  170. package/src/v2/components/chat/__tests__/CopilotChatUserMessage.slots.e2e.test.tsx +0 -621
  171. package/src/v2/components/chat/__tests__/CopilotChatView.connectingGate.test.tsx +0 -56
  172. package/src/v2/components/chat/__tests__/CopilotChatView.inputOverlay.test.tsx +0 -264
  173. package/src/v2/components/chat/__tests__/CopilotChatView.onClick.e2e.test.tsx +0 -853
  174. package/src/v2/components/chat/__tests__/CopilotChatView.pinToSend.test.tsx +0 -94
  175. package/src/v2/components/chat/__tests__/CopilotChatView.slots.e2e.test.tsx +0 -1050
  176. package/src/v2/components/chat/__tests__/CopilotModalHeader.slots.e2e.test.tsx +0 -484
  177. package/src/v2/components/chat/__tests__/CopilotPopupView.slots.e2e.test.tsx +0 -612
  178. package/src/v2/components/chat/__tests__/CopilotSidebarView.position.test.tsx +0 -159
  179. package/src/v2/components/chat/__tests__/CopilotSidebarView.slots.e2e.test.tsx +0 -502
  180. package/src/v2/components/chat/__tests__/MCPAppsActivityRenderer.e2e.test.tsx +0 -1068
  181. package/src/v2/components/chat/__tests__/MCPAppsProxy.e2e.test.tsx +0 -589
  182. package/src/v2/components/chat/__tests__/MCPAppsUiMessage.e2e.test.tsx +0 -403
  183. package/src/v2/components/chat/__tests__/copilot-chat-throttle.test.tsx +0 -137
  184. package/src/v2/components/chat/__tests__/normalize-auto-scroll.test.ts +0 -37
  185. package/src/v2/components/chat/__tests__/setup.ts +0 -1
  186. package/src/v2/components/chat/index.ts +0 -90
  187. package/src/v2/components/chat/last-user-message-context.ts +0 -21
  188. package/src/v2/components/chat/normalize-auto-scroll.ts +0 -17
  189. package/src/v2/components/chat/scroll-element-context.ts +0 -13
  190. package/src/v2/components/index.ts +0 -8
  191. package/src/v2/components/intelligence-indicator/IntelligenceIndicator.tsx +0 -286
  192. package/src/v2/components/intelligence-indicator/__tests__/IntelligenceIndicator.e2e.test.tsx +0 -464
  193. package/src/v2/components/intelligence-indicator/index.ts +0 -2
  194. package/src/v2/components/license-warning-banner.tsx +0 -217
  195. package/src/v2/components/ui/button.tsx +0 -124
  196. package/src/v2/components/ui/dropdown-menu.tsx +0 -258
  197. package/src/v2/components/ui/tooltip.tsx +0 -60
  198. package/src/v2/context.ts +0 -62
  199. package/src/v2/headless.ts +0 -64
  200. package/src/v2/hooks/__tests__/standard-schema-types.test.tsx +0 -152
  201. package/src/v2/hooks/__tests__/standard-schema.test.tsx +0 -282
  202. package/src/v2/hooks/__tests__/use-agent-context-timing.e2e.test.tsx +0 -140
  203. package/src/v2/hooks/__tests__/use-agent-context.test.tsx +0 -401
  204. package/src/v2/hooks/__tests__/use-agent-error-state.test.tsx +0 -44
  205. package/src/v2/hooks/__tests__/use-agent-stability.test.tsx +0 -211
  206. package/src/v2/hooks/__tests__/use-agent-throttle.test.tsx +0 -1029
  207. package/src/v2/hooks/__tests__/use-agent.e2e.test.tsx +0 -159
  208. package/src/v2/hooks/__tests__/use-attachments.test.tsx +0 -169
  209. package/src/v2/hooks/__tests__/use-capabilities.test.tsx +0 -76
  210. package/src/v2/hooks/__tests__/use-component.test.tsx +0 -126
  211. package/src/v2/hooks/__tests__/use-configure-suggestions.e2e.test.tsx +0 -696
  212. package/src/v2/hooks/__tests__/use-default-render-tool.test.tsx +0 -153
  213. package/src/v2/hooks/__tests__/use-frontend-tool-available.test.tsx +0 -167
  214. package/src/v2/hooks/__tests__/use-frontend-tool.e2e.test.tsx +0 -2148
  215. package/src/v2/hooks/__tests__/use-human-in-the-loop.e2e.test.tsx +0 -1261
  216. package/src/v2/hooks/__tests__/use-interrupt.test.tsx +0 -397
  217. package/src/v2/hooks/__tests__/use-katex-styles.test.tsx +0 -56
  218. package/src/v2/hooks/__tests__/use-keyboard-height.test.tsx +0 -192
  219. package/src/v2/hooks/__tests__/use-pin-to-send.test.tsx +0 -219
  220. package/src/v2/hooks/__tests__/use-render-custom-messages.test.tsx +0 -55
  221. package/src/v2/hooks/__tests__/use-render-tool.test.tsx +0 -259
  222. package/src/v2/hooks/__tests__/use-suggestions.e2e.test.tsx +0 -524
  223. package/src/v2/hooks/__tests__/use-threads.test.tsx +0 -757
  224. package/src/v2/hooks/__tests__/zod-regression.test.tsx +0 -311
  225. package/src/v2/hooks/index.ts +0 -24
  226. package/src/v2/hooks/use-agent-context.tsx +0 -45
  227. package/src/v2/hooks/use-agent.tsx +0 -227
  228. package/src/v2/hooks/use-attachments.tsx +0 -269
  229. package/src/v2/hooks/use-capabilities.tsx +0 -25
  230. package/src/v2/hooks/use-component.tsx +0 -91
  231. package/src/v2/hooks/use-configure-suggestions.tsx +0 -236
  232. package/src/v2/hooks/use-default-render-tool.tsx +0 -271
  233. package/src/v2/hooks/use-frontend-tool.tsx +0 -46
  234. package/src/v2/hooks/use-human-in-the-loop.tsx +0 -81
  235. package/src/v2/hooks/use-interrupt.tsx +0 -305
  236. package/src/v2/hooks/use-keyboard-height.tsx +0 -67
  237. package/src/v2/hooks/use-pin-to-send.ts +0 -94
  238. package/src/v2/hooks/use-render-activity-message.tsx +0 -72
  239. package/src/v2/hooks/use-render-custom-messages.tsx +0 -93
  240. package/src/v2/hooks/use-render-tool-call.tsx +0 -208
  241. package/src/v2/hooks/use-render-tool.tsx +0 -184
  242. package/src/v2/hooks/use-suggestions.tsx +0 -91
  243. package/src/v2/hooks/use-threads.tsx +0 -325
  244. package/src/v2/hooks/useKatexStyles.ts +0 -27
  245. package/src/v2/index.css +0 -1
  246. package/src/v2/index.ts +0 -27
  247. package/src/v2/lib/__tests__/completePartialMarkdown.test.ts +0 -495
  248. package/src/v2/lib/__tests__/processPartialHtml.test.ts +0 -112
  249. package/src/v2/lib/__tests__/renderSlot.test.tsx +0 -588
  250. package/src/v2/lib/__tests__/slots.test.ts +0 -56
  251. package/src/v2/lib/processPartialHtml.ts +0 -45
  252. package/src/v2/lib/react-core.ts +0 -156
  253. package/src/v2/lib/slots.tsx +0 -184
  254. package/src/v2/lib/transcription-client.ts +0 -184
  255. package/src/v2/lib/utils.ts +0 -8
  256. package/src/v2/providers/CopilotChatConfigurationProvider.tsx +0 -196
  257. package/src/v2/providers/CopilotKitProvider.tsx +0 -800
  258. package/src/v2/providers/SandboxFunctionsContext.ts +0 -10
  259. package/src/v2/providers/__tests__/CopilotChatConfigurationProvider.test.tsx +0 -652
  260. package/src/v2/providers/__tests__/CopilotKitProvider.license.test.tsx +0 -101
  261. package/src/v2/providers/__tests__/CopilotKitProvider.onError.test.tsx +0 -69
  262. package/src/v2/providers/__tests__/CopilotKitProvider.renderCustomMessages.e2e.test.tsx +0 -881
  263. package/src/v2/providers/__tests__/CopilotKitProvider.sandboxFunctions.test.tsx +0 -198
  264. package/src/v2/providers/__tests__/CopilotKitProvider.stability.test.tsx +0 -740
  265. package/src/v2/providers/__tests__/CopilotKitProvider.test.tsx +0 -713
  266. package/src/v2/providers/__tests__/CopilotKitProvider.wildcard.test.tsx +0 -294
  267. package/src/v2/providers/index.ts +0 -21
  268. package/src/v2/styles/globals.css +0 -349
  269. package/src/v2/types/__tests__/defineToolCallRenderer.test.tsx +0 -525
  270. package/src/v2/types/defineToolCallRenderer.ts +0 -68
  271. package/src/v2/types/frontend-tool.ts +0 -8
  272. package/src/v2/types/human-in-the-loop.ts +0 -33
  273. package/src/v2/types/index.ts +0 -8
  274. package/src/v2/types/interrupt.ts +0 -15
  275. package/src/v2/types/react-activity-message-renderer.ts +0 -27
  276. package/src/v2/types/react-custom-message-renderer.ts +0 -17
  277. package/src/v2/types/react-tool-call-renderer.ts +0 -35
  278. package/src/v2/types/sandbox-function.ts +0 -11
  279. package/tsconfig.json +0 -8
  280. package/tsdown.config.ts +0 -193
  281. package/typedoc.json +0 -4
  282. package/vitest.config.mjs +0 -31
@@ -1,10 +0,0 @@
1
- import { createContext, useContext } from "react";
2
- import type { SandboxFunction } from "../types/sandbox-function";
3
-
4
- export const SandboxFunctionsContext = createContext<
5
- readonly SandboxFunction[]
6
- >([]);
7
-
8
- export function useSandboxFunctions(): readonly SandboxFunction[] {
9
- return useContext(SandboxFunctionsContext);
10
- }
@@ -1,652 +0,0 @@
1
- import React from "react";
2
- import { render, screen, fireEvent, act } from "@testing-library/react";
3
- import { describe, it, expect } from "vitest";
4
- import {
5
- CopilotChatConfigurationProvider,
6
- CopilotChatDefaultLabels,
7
- useCopilotChatConfiguration,
8
- } from "../CopilotChatConfigurationProvider";
9
- import { DEFAULT_AGENT_ID } from "@copilotkit/shared";
10
- import { CopilotKitProvider } from "../CopilotKitProvider";
11
- import { MockStepwiseAgent } from "../../__tests__/utils/test-helpers";
12
- import { CopilotChat } from "../../components/chat/CopilotChat";
13
-
14
- // Test component to access configuration
15
- function ConfigurationDisplay() {
16
- const config = useCopilotChatConfiguration();
17
- return (
18
- <div>
19
- <div data-testid="agentId">{config?.agentId || "no-config"}</div>
20
- <div data-testid="threadId">{config?.threadId || "no-config"}</div>
21
- <div data-testid="placeholder">
22
- {config?.labels.chatInputPlaceholder || "no-config"}
23
- </div>
24
- <div data-testid="copyLabel">
25
- {config?.labels.assistantMessageToolbarCopyMessageLabel || "no-config"}
26
- </div>
27
- </div>
28
- );
29
- }
30
-
31
- describe("CopilotChatConfigurationProvider", () => {
32
- describe("Basic functionality", () => {
33
- it("should provide default configuration", () => {
34
- render(
35
- <CopilotChatConfigurationProvider threadId="test-thread">
36
- <ConfigurationDisplay />
37
- </CopilotChatConfigurationProvider>,
38
- );
39
-
40
- expect(screen.getByTestId("agentId").textContent).toBe(DEFAULT_AGENT_ID);
41
- expect(screen.getByTestId("threadId").textContent).toBe("test-thread");
42
- expect(screen.getByTestId("placeholder").textContent).toBe(
43
- CopilotChatDefaultLabels.chatInputPlaceholder,
44
- );
45
- });
46
-
47
- it("should accept custom agentId", () => {
48
- render(
49
- <CopilotChatConfigurationProvider
50
- threadId="test-thread"
51
- agentId="custom-agent"
52
- >
53
- <ConfigurationDisplay />
54
- </CopilotChatConfigurationProvider>,
55
- );
56
-
57
- expect(screen.getByTestId("agentId").textContent).toBe("custom-agent");
58
- });
59
-
60
- it("should merge custom labels with defaults", () => {
61
- const customLabels = {
62
- chatInputPlaceholder: "Custom placeholder",
63
- };
64
-
65
- render(
66
- <CopilotChatConfigurationProvider
67
- threadId="test-thread"
68
- labels={customLabels}
69
- >
70
- <ConfigurationDisplay />
71
- </CopilotChatConfigurationProvider>,
72
- );
73
-
74
- expect(screen.getByTestId("placeholder").textContent).toBe(
75
- "Custom placeholder",
76
- );
77
- // Other labels should still have defaults
78
- expect(screen.getByTestId("copyLabel").textContent).toBe(
79
- CopilotChatDefaultLabels.assistantMessageToolbarCopyMessageLabel,
80
- );
81
- });
82
- });
83
-
84
- describe("Hook behavior", () => {
85
- it("should return null when no provider exists", () => {
86
- render(<ConfigurationDisplay />);
87
-
88
- expect(screen.getByTestId("agentId").textContent).toBe("no-config");
89
- expect(screen.getByTestId("threadId").textContent).toBe("no-config");
90
- expect(screen.getByTestId("placeholder").textContent).toBe("no-config");
91
- });
92
- });
93
-
94
- describe("CopilotChat priority merging", () => {
95
- it("should use defaults when no provider exists and no props passed", () => {
96
- // CopilotChat creates its own provider, so we need to check inside it
97
- // We'll check the input placeholder which uses the configuration
98
- const { container } = render(
99
- <CopilotKitProvider
100
- agents__unsafe_dev_only={{
101
- [DEFAULT_AGENT_ID]: new MockStepwiseAgent(),
102
- }}
103
- >
104
- <CopilotChat />
105
- </CopilotKitProvider>,
106
- );
107
-
108
- // Find the input element and check its placeholder
109
- const input = container.querySelector('textarea, input[type="text"]');
110
- expect(input?.getAttribute("placeholder")).toBe(
111
- CopilotChatDefaultLabels.chatInputPlaceholder,
112
- );
113
- });
114
-
115
- it("should inherit from existing provider when CopilotChat has no props", () => {
116
- const { container } = render(
117
- <CopilotKitProvider
118
- agents__unsafe_dev_only={{
119
- "outer-agent": new MockStepwiseAgent({ agentId: "outer-agent" }),
120
- }}
121
- >
122
- <CopilotChatConfigurationProvider
123
- threadId="outer-thread"
124
- agentId="outer-agent"
125
- labels={{ chatInputPlaceholder: "Outer placeholder" }}
126
- >
127
- <CopilotChat />
128
- </CopilotChatConfigurationProvider>
129
- </CopilotKitProvider>,
130
- );
131
-
132
- // Check that the input inherits the outer placeholder
133
- const input = container.querySelector('textarea, input[type="text"]');
134
- expect(input?.getAttribute("placeholder")).toBe("Outer placeholder");
135
- });
136
-
137
- it("should override existing provider with CopilotChat props", () => {
138
- const { container } = render(
139
- <CopilotKitProvider
140
- agents__unsafe_dev_only={{
141
- "inner-agent": new MockStepwiseAgent({ agentId: "inner-agent" }),
142
- }}
143
- >
144
- <CopilotChatConfigurationProvider
145
- threadId="outer-thread"
146
- agentId="outer-agent"
147
- labels={{ chatInputPlaceholder: "Outer placeholder" }}
148
- >
149
- <CopilotChat
150
- agentId="inner-agent"
151
- threadId="inner-thread"
152
- labels={{ chatInputPlaceholder: "Inner placeholder" }}
153
- />
154
- </CopilotChatConfigurationProvider>
155
- </CopilotKitProvider>,
156
- );
157
-
158
- // CopilotChat props should win - check the input placeholder
159
- const input = container.querySelector('textarea, input[type="text"]');
160
- expect(input?.getAttribute("placeholder")).toBe("Inner placeholder");
161
- });
162
-
163
- it("should merge labels correctly with priority: default < existing < props", () => {
164
- const { container } = render(
165
- <CopilotKitProvider
166
- agents__unsafe_dev_only={{
167
- [DEFAULT_AGENT_ID]: new MockStepwiseAgent(),
168
- }}
169
- >
170
- <CopilotChatConfigurationProvider
171
- threadId="outer-thread"
172
- labels={{
173
- chatInputPlaceholder: "Outer placeholder",
174
- assistantMessageToolbarCopyMessageLabel: "Outer copy",
175
- }}
176
- >
177
- <CopilotChat
178
- labels={{
179
- chatInputPlaceholder: "Inner placeholder",
180
- // Not overriding copyLabel, should inherit from outer
181
- }}
182
- />
183
- </CopilotChatConfigurationProvider>
184
- </CopilotKitProvider>,
185
- );
186
-
187
- const input = container.querySelector('textarea, input[type="text"]');
188
- expect(input?.getAttribute("placeholder")).toBe("Inner placeholder");
189
- // The copy label would be tested if we had assistant messages
190
- });
191
-
192
- it("should handle partial overrides correctly", () => {
193
- const { container } = render(
194
- <CopilotKitProvider
195
- agents__unsafe_dev_only={{
196
- "outer-agent": new MockStepwiseAgent({ agentId: "outer-agent" }),
197
- }}
198
- >
199
- <CopilotChatConfigurationProvider
200
- threadId="outer-thread"
201
- agentId="outer-agent"
202
- labels={{ chatInputPlaceholder: "Outer placeholder" }}
203
- >
204
- <CopilotChat
205
- // Only override threadId and some labels, not agentId
206
- threadId="inner-thread"
207
- labels={{
208
- chatInputPlaceholder: "Inner placeholder",
209
- }}
210
- />
211
- </CopilotChatConfigurationProvider>
212
- </CopilotKitProvider>,
213
- );
214
-
215
- // Check the placeholder was overridden
216
- const input = container.querySelector('textarea, input[type="text"]');
217
- expect(input?.getAttribute("placeholder")).toBe("Inner placeholder");
218
- // agentId and other properties would be tested through agent behavior
219
- });
220
-
221
- it("should allow accessing configuration outside CopilotChat in same provider", () => {
222
- // This shows that ConfigurationDisplay outside CopilotChat
223
- // sees the outer provider values, not the inner merged ones
224
- render(
225
- <CopilotKitProvider
226
- agents__unsafe_dev_only={{
227
- "outer-agent": new MockStepwiseAgent({ agentId: "outer-agent" }),
228
- }}
229
- >
230
- <CopilotChatConfigurationProvider
231
- threadId="outer-thread"
232
- agentId="outer-agent"
233
- labels={{ chatInputPlaceholder: "Outer placeholder" }}
234
- >
235
- <CopilotChat
236
- threadId="inner-thread"
237
- labels={{ chatInputPlaceholder: "Inner placeholder" }}
238
- />
239
- <ConfigurationDisplay />
240
- </CopilotChatConfigurationProvider>
241
- </CopilotKitProvider>,
242
- );
243
-
244
- // ConfigurationDisplay is outside CopilotChat, so it sees outer values
245
- expect(screen.getByTestId("agentId").textContent).toBe("outer-agent");
246
- expect(screen.getByTestId("threadId").textContent).toBe("outer-thread");
247
- expect(screen.getByTestId("placeholder").textContent).toBe(
248
- "Outer placeholder",
249
- );
250
- });
251
- });
252
-
253
- describe("Modal state", () => {
254
- it("should always provide setModalOpen and isModalOpen even without isModalDefaultOpen", () => {
255
- function ModalStateDisplay() {
256
- const config = useCopilotChatConfiguration();
257
- return (
258
- <div>
259
- <div data-testid="hasSetModalOpen">
260
- {config?.setModalOpen ? "yes" : "no"}
261
- </div>
262
- <div data-testid="hasIsModalOpen">
263
- {config?.isModalOpen !== undefined ? "yes" : "no"}
264
- </div>
265
- </div>
266
- );
267
- }
268
-
269
- render(
270
- <CopilotChatConfigurationProvider threadId="test-thread">
271
- <ModalStateDisplay />
272
- </CopilotChatConfigurationProvider>,
273
- );
274
-
275
- expect(screen.getByTestId("hasSetModalOpen").textContent).toBe("yes");
276
- expect(screen.getByTestId("hasIsModalOpen").textContent).toBe("yes");
277
- });
278
-
279
- it("should respect isModalDefaultOpen when provided", () => {
280
- function ModalStateDisplay() {
281
- const config = useCopilotChatConfiguration();
282
- return (
283
- <div>
284
- <div data-testid="isModalOpen">
285
- {config?.isModalOpen ? "open" : "closed"}
286
- </div>
287
- </div>
288
- );
289
- }
290
-
291
- render(
292
- <CopilotChatConfigurationProvider
293
- threadId="test-thread"
294
- isModalDefaultOpen={false}
295
- >
296
- <ModalStateDisplay />
297
- </CopilotChatConfigurationProvider>,
298
- );
299
-
300
- expect(screen.getByTestId("isModalOpen").textContent).toBe("closed");
301
- });
302
-
303
- it("should inherit parent modal state when child has no isModalDefaultOpen", () => {
304
- function ModalStateDisplay() {
305
- const config = useCopilotChatConfiguration();
306
- return (
307
- <div>
308
- <div data-testid="isModalOpen">
309
- {config?.isModalOpen ? "open" : "closed"}
310
- </div>
311
- <div data-testid="hasSetModalOpen">
312
- {config?.setModalOpen ? "yes" : "no"}
313
- </div>
314
- </div>
315
- );
316
- }
317
-
318
- render(
319
- <CopilotChatConfigurationProvider
320
- threadId="outer-thread"
321
- isModalDefaultOpen={false}
322
- >
323
- <CopilotChatConfigurationProvider threadId="inner-thread">
324
- <ModalStateDisplay />
325
- </CopilotChatConfigurationProvider>
326
- </CopilotChatConfigurationProvider>,
327
- );
328
-
329
- // Child should inherit parent's modal state (closed)
330
- expect(screen.getByTestId("isModalOpen").textContent).toBe("closed");
331
- expect(screen.getByTestId("hasSetModalOpen").textContent).toBe("yes");
332
- });
333
-
334
- it("should allow nested provider to override parent modal state with explicit isModalDefaultOpen", () => {
335
- function ModalStateDisplay() {
336
- const config = useCopilotChatConfiguration();
337
- return (
338
- <div>
339
- <div data-testid="isModalOpen">
340
- {config?.isModalOpen ? "open" : "closed"}
341
- </div>
342
- </div>
343
- );
344
- }
345
-
346
- render(
347
- <CopilotChatConfigurationProvider
348
- threadId="outer-thread"
349
- isModalDefaultOpen={true}
350
- >
351
- <CopilotChatConfigurationProvider
352
- threadId="inner-thread"
353
- isModalDefaultOpen={false}
354
- >
355
- <ModalStateDisplay />
356
- </CopilotChatConfigurationProvider>
357
- </CopilotChatConfigurationProvider>,
358
- );
359
-
360
- expect(screen.getByTestId("isModalOpen").textContent).toBe("closed");
361
- });
362
- });
363
-
364
- /**
365
- * CPK-7152: Bidirectional sync between nested providers.
366
- *
367
- * The fix must satisfy both:
368
- * Behavior A — child provider respects its own isModalDefaultOpen even
369
- * when a parent provider exists (covered by the existing
370
- * "allow nested provider to override" test above).
371
- * Behavior B — state changes in the inner provider propagate outward so
372
- * that hooks reading from an outer provider stay in sync.
373
- *
374
- * Scenarios mirror the reproduction cases in:
375
- * https://github.com/CopilotKit/deep-agent-cpk-experiments/tree/main/app/client/src/tickets/tkt-modal-default-open
376
- */
377
- describe("Bidirectional sync (CPK-7152)", () => {
378
- // Reusable probe/control component that reads the closest provider.
379
- function ModalControls({ id }: { id: string }) {
380
- const config = useCopilotChatConfiguration();
381
- return (
382
- <>
383
- <div data-testid={`${id}-state`}>{String(config?.isModalOpen)}</div>
384
- <button
385
- data-testid={`${id}-open`}
386
- onClick={() => config?.setModalOpen(true)}
387
- >
388
- open
389
- </button>
390
- <button
391
- data-testid={`${id}-close`}
392
- onClick={() => config?.setModalOpen(false)}
393
- >
394
- close
395
- </button>
396
- </>
397
- );
398
- }
399
-
400
- it("scenario-sidebar-outer-hook: inner setModalOpen propagates to outer hook (Behavior B)", () => {
401
- // Abe.Hu's layout: outer bare provider, inner provider owns explicit state.
402
- // Toggling via the inner provider should update the outer hook.
403
- render(
404
- <CopilotChatConfigurationProvider threadId="outer">
405
- {/* OuterProbe sits outside the inner provider — reads outer context */}
406
- <ModalControls id="outer" />
407
- <CopilotChatConfigurationProvider
408
- threadId="inner"
409
- isModalDefaultOpen={true}
410
- >
411
- <ModalControls id="inner" />
412
- </CopilotChatConfigurationProvider>
413
- </CopilotChatConfigurationProvider>,
414
- );
415
-
416
- expect(screen.getByTestId("outer-state").textContent).toBe("true");
417
- expect(screen.getByTestId("inner-state").textContent).toBe("true");
418
-
419
- act(() => {
420
- fireEvent.click(screen.getByTestId("inner-close"));
421
- });
422
-
423
- // Inner closed — outer hook must reflect the change.
424
- expect(screen.getByTestId("inner-state").textContent).toBe("false");
425
- expect(screen.getByTestId("outer-state").textContent).toBe("false");
426
- });
427
-
428
- it("scenario-sidebar-outer-hook: outer setModalOpen propagates to inner (parent→child sync)", () => {
429
- // If the user calls setModalOpen from the outer hook, the inner
430
- // provider (and therefore the sidebar) must respond.
431
- render(
432
- <CopilotChatConfigurationProvider
433
- threadId="outer"
434
- isModalDefaultOpen={false}
435
- >
436
- <ModalControls id="outer" />
437
- <CopilotChatConfigurationProvider
438
- threadId="inner"
439
- isModalDefaultOpen={false}
440
- >
441
- <ModalControls id="inner" />
442
- </CopilotChatConfigurationProvider>
443
- </CopilotChatConfigurationProvider>,
444
- );
445
-
446
- expect(screen.getByTestId("outer-state").textContent).toBe("false");
447
- expect(screen.getByTestId("inner-state").textContent).toBe("false");
448
-
449
- act(() => {
450
- fireEvent.click(screen.getByTestId("outer-open"));
451
- });
452
-
453
- // Outer opened — inner must follow.
454
- expect(screen.getByTestId("outer-state").textContent).toBe("true");
455
- expect(screen.getByTestId("inner-state").textContent).toBe("true");
456
- });
457
-
458
- it("scenario-nested-provider: three-level chain propagates through middle provider", () => {
459
- // Mirrors the real provider stack:
460
- // Provider 1 (user's outer, no isModalDefaultOpen)
461
- // └── Provider 2 (CopilotChat's, no isModalDefaultOpen) — "middle"
462
- // └── Provider 3 (CopilotSidebarView's, explicit isModalDefaultOpen)
463
- //
464
- // Toggling P3 must reach P1 even though P2 has no explicit default.
465
- render(
466
- <CopilotChatConfigurationProvider threadId="p1">
467
- <ModalControls id="p1" />
468
- <CopilotChatConfigurationProvider threadId="p2">
469
- {/* p2 has no isModalDefaultOpen — proxies p1's state */}
470
- <CopilotChatConfigurationProvider
471
- threadId="p3"
472
- isModalDefaultOpen={true}
473
- >
474
- <ModalControls id="p3" />
475
- </CopilotChatConfigurationProvider>
476
- </CopilotChatConfigurationProvider>
477
- </CopilotChatConfigurationProvider>,
478
- );
479
-
480
- expect(screen.getByTestId("p1-state").textContent).toBe("true");
481
- expect(screen.getByTestId("p3-state").textContent).toBe("true");
482
-
483
- act(() => {
484
- fireEvent.click(screen.getByTestId("p3-close"));
485
- });
486
-
487
- expect(screen.getByTestId("p3-state").textContent).toBe("false");
488
- expect(screen.getByTestId("p1-state").textContent).toBe("false");
489
- });
490
-
491
- it("scenario-nested-provider: Behavior A still holds after sync fix (no regression)", () => {
492
- // Explicit isModalDefaultOpen on a child must still override the
493
- // parent's current value on initial render — the sync effect must
494
- // not overwrite the child's own initial state.
495
- render(
496
- <CopilotChatConfigurationProvider
497
- threadId="outer"
498
- isModalDefaultOpen={true}
499
- >
500
- <ModalControls id="outer" />
501
- <CopilotChatConfigurationProvider
502
- threadId="inner"
503
- isModalDefaultOpen={false}
504
- >
505
- <ModalControls id="inner" />
506
- </CopilotChatConfigurationProvider>
507
- </CopilotChatConfigurationProvider>,
508
- );
509
-
510
- // Inner must start closed despite outer being open.
511
- expect(screen.getByTestId("outer-state").textContent).toBe("true");
512
- expect(screen.getByTestId("inner-state").textContent).toBe("false");
513
- });
514
- });
515
-
516
- /**
517
- * Regression coverage for the welcome-screen / /connect 404 bug
518
- * (fix/welcome-not-showing-at-all). `hasExplicitThreadId` distinguishes a
519
- * caller-chosen thread from a UUID auto-minted inside the provider chain —
520
- * consumers that only make sense against a real backend thread (/connect,
521
- * switch-flash suppression) must gate on this signal, not on !!threadId.
522
- */
523
- describe("hasExplicitThreadId", () => {
524
- function ExplicitProbe({ id = "probe" }: { id?: string } = {}) {
525
- const config = useCopilotChatConfiguration();
526
- return (
527
- <div data-testid={`${id}-explicit`}>
528
- {String(config?.hasExplicitThreadId)}
529
- </div>
530
- );
531
- }
532
-
533
- it("infers true when threadId prop is supplied and hasExplicitThreadId is omitted", () => {
534
- render(
535
- <CopilotChatConfigurationProvider threadId="customer-thread">
536
- <ExplicitProbe />
537
- </CopilotChatConfigurationProvider>,
538
- );
539
-
540
- expect(screen.getByTestId("probe-explicit").textContent).toBe("true");
541
- });
542
-
543
- it("infers false when no threadId prop is supplied and hasExplicitThreadId is omitted", () => {
544
- render(
545
- <CopilotChatConfigurationProvider>
546
- <ExplicitProbe />
547
- </CopilotChatConfigurationProvider>,
548
- );
549
-
550
- expect(screen.getByTestId("probe-explicit").textContent).toBe("false");
551
- });
552
-
553
- it("respects hasExplicitThreadId={false} even when a threadId prop is present (v1 bridge case)", () => {
554
- // The v1 <CopilotKit> wrapper always pipes a UUID through as `threadId`
555
- // (from ThreadsProvider). Without this override the provider would
556
- // mis-infer the UUID as explicit, causing /connect to 404 and the
557
- // welcome screen to stay hidden for fresh empty chats.
558
- render(
559
- <CopilotChatConfigurationProvider
560
- threadId="auto-minted-uuid"
561
- hasExplicitThreadId={false}
562
- >
563
- <ExplicitProbe />
564
- </CopilotChatConfigurationProvider>,
565
- );
566
-
567
- expect(screen.getByTestId("probe-explicit").textContent).toBe("false");
568
- });
569
-
570
- it("parent=true overrides child's hasExplicitThreadId={false} via OR inheritance", () => {
571
- // resolvedHasExplicitThreadId = ownHasExplicit || parentHasExplicit.
572
- // Once an ancestor has marked the thread as caller-chosen, descendants
573
- // cannot mask that — pinning the contract so "try to hide explicitness
574
- // from a child" doesn't silently work.
575
- render(
576
- <CopilotChatConfigurationProvider threadId="real-thread">
577
- <CopilotChatConfigurationProvider
578
- threadId="other-uuid"
579
- hasExplicitThreadId={false}
580
- >
581
- <ExplicitProbe />
582
- </CopilotChatConfigurationProvider>
583
- </CopilotChatConfigurationProvider>,
584
- );
585
-
586
- expect(screen.getByTestId("probe-explicit").textContent).toBe("true");
587
- });
588
-
589
- it("propagates through a three-level chain where the middle provider is bare", () => {
590
- // Matches the real stack: outer layout provider (no threadId) →
591
- // CopilotChat's own provider (no threadId) → inner feature provider
592
- // (explicit threadId). Explicitness must cross the empty middle.
593
- render(
594
- <CopilotChatConfigurationProvider>
595
- <CopilotChatConfigurationProvider>
596
- <CopilotChatConfigurationProvider threadId="deeply-picked-thread">
597
- <ExplicitProbe />
598
- </CopilotChatConfigurationProvider>
599
- </CopilotChatConfigurationProvider>
600
- </CopilotChatConfigurationProvider>,
601
- );
602
-
603
- expect(screen.getByTestId("probe-explicit").textContent).toBe("true");
604
- });
605
-
606
- it("non-explicit parent does not taint an explicit child", () => {
607
- render(
608
- <CopilotChatConfigurationProvider
609
- threadId="auto-uuid"
610
- hasExplicitThreadId={false}
611
- >
612
- <CopilotChatConfigurationProvider threadId="user-picked">
613
- <ExplicitProbe />
614
- </CopilotChatConfigurationProvider>
615
- </CopilotChatConfigurationProvider>,
616
- );
617
-
618
- expect(screen.getByTestId("probe-explicit").textContent).toBe("true");
619
- });
620
- });
621
-
622
- describe("Nested providers", () => {
623
- it("should handle multiple nested providers correctly", () => {
624
- render(
625
- <CopilotChatConfigurationProvider
626
- threadId="outer-thread"
627
- agentId="outer-agent"
628
- labels={{ chatInputPlaceholder: "Outer" }}
629
- >
630
- <CopilotChatConfigurationProvider
631
- threadId="middle-thread"
632
- agentId="middle-agent"
633
- labels={{ chatInputPlaceholder: "Middle" }}
634
- >
635
- <CopilotChatConfigurationProvider
636
- threadId="inner-thread"
637
- agentId="inner-agent"
638
- labels={{ chatInputPlaceholder: "Inner" }}
639
- >
640
- <ConfigurationDisplay />
641
- </CopilotChatConfigurationProvider>
642
- </CopilotChatConfigurationProvider>
643
- </CopilotChatConfigurationProvider>,
644
- );
645
-
646
- // Innermost provider should win
647
- expect(screen.getByTestId("agentId").textContent).toBe("inner-agent");
648
- expect(screen.getByTestId("threadId").textContent).toBe("inner-thread");
649
- expect(screen.getByTestId("placeholder").textContent).toBe("Inner");
650
- });
651
- });
652
- });