@copilotkit/vue 2.0.0-rc.20 → 2.0.0-rc.22

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 (193) hide show
  1. package/dist/index.cjs +1 -1
  2. package/dist/index.mjs +13 -13
  3. package/dist/use-render-activity-message-CyrhHFhA.js +16200 -0
  4. package/dist/use-render-activity-message-CyrhHFhA.js.map +1 -0
  5. package/dist/use-render-activity-message-EwHHrwQB.cjs +114 -0
  6. package/dist/use-render-activity-message-EwHHrwQB.cjs.map +1 -0
  7. package/dist/v2/components/A2UIMessageRenderer.d.ts +14 -0
  8. package/dist/v2/components/A2UIMessageRenderer.d.ts.map +1 -1
  9. package/dist/v2/components/A2UISurfaceActivityRenderer.vue.d.ts +10 -3
  10. package/dist/v2/components/A2UISurfaceActivityRenderer.vue.d.ts.map +1 -1
  11. package/dist/v2/components/CopilotKitInspector.vue.d.ts +5 -1
  12. package/dist/v2/components/CopilotKitInspector.vue.d.ts.map +1 -1
  13. package/dist/v2/components/MCPAppsActivityRenderer.d.ts.map +1 -1
  14. package/dist/v2/components/OpenGenerativeUIRenderer.d.ts +7 -21
  15. package/dist/v2/components/OpenGenerativeUIRenderer.d.ts.map +1 -1
  16. package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts +0 -5
  17. package/dist/v2/components/a2ui/A2UIBuiltInToolCallRenderer.d.ts.map +1 -1
  18. package/dist/v2/components/a2ui/A2UICatalogContext.d.ts +10 -15
  19. package/dist/v2/components/a2ui/A2UICatalogContext.d.ts.map +1 -1
  20. package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts +14 -138
  21. package/dist/v2/components/a2ui/A2UIRecoveryStates.d.ts.map +1 -1
  22. package/dist/v2/components/a2ui/catalog.d.ts.map +1 -1
  23. package/dist/v2/components/a2ui/utils.d.ts +3 -15
  24. package/dist/v2/components/a2ui/utils.d.ts.map +1 -1
  25. package/dist/v2/components/a2ui.d.ts +6 -1
  26. package/dist/v2/components/a2ui.d.ts.map +1 -1
  27. package/dist/v2/components/chat/CopilotChat.vue.d.ts.map +1 -1
  28. package/dist/v2/components/chat/CopilotChatAttachmentQueue.vue.d.ts.map +1 -1
  29. package/dist/v2/components/chat/CopilotChatAudioRecorder.vue.d.ts +4 -8
  30. package/dist/v2/components/chat/CopilotChatAudioRecorder.vue.d.ts.map +1 -1
  31. package/dist/v2/components/chat/CopilotChatInput.vue.d.ts.map +1 -1
  32. package/dist/v2/components/chat/CopilotChatLightbox.vue.d.ts.map +1 -1
  33. package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts.map +1 -1
  34. package/dist/v2/components/chat/CopilotChatToolCallGroup.vue.d.ts.map +1 -1
  35. package/dist/v2/components/chat/CopilotChatToolCallItem.vue.d.ts.map +1 -1
  36. package/dist/v2/components/chat/CopilotChatToolCallsView.vue.d.ts.map +1 -1
  37. package/dist/v2/components/chat/CopilotChatView.vue.d.ts +1 -1
  38. package/dist/v2/components/chat/CopilotChatView.vue.d.ts.map +1 -1
  39. package/dist/v2/components/chat/CopilotPopupViewInternal.vue.d.ts.map +1 -1
  40. package/dist/v2/components/chat/CopilotSidebarView.vue.d.ts +1 -1
  41. package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts +1 -1
  42. package/dist/v2/components/chat/CopilotSidebarViewInternal.vue.d.ts.map +1 -1
  43. package/dist/v2/components/chat/CopilotThreadsDrawer.vue.d.ts.map +1 -1
  44. package/dist/v2/components/chat/StreamingMarkdownDefault.vue.d.ts +1 -0
  45. package/dist/v2/components/chat/StreamingMarkdownDefault.vue.d.ts.map +1 -1
  46. package/dist/v2/components/chat/audioRecorder.d.ts +3 -4
  47. package/dist/v2/components/chat/audioRecorder.d.ts.map +1 -1
  48. package/dist/v2/components/chat/copilotChatToolCallItemRender.d.ts +3 -2
  49. package/dist/v2/components/chat/copilotChatToolCallItemRender.d.ts.map +1 -1
  50. package/dist/v2/components/chat/index.d.ts +6 -6
  51. package/dist/v2/components/chat/tool-call-display-context.d.ts +3 -1
  52. package/dist/v2/components/chat/tool-call-display-context.d.ts.map +1 -1
  53. package/dist/v2/components/chat/tool-call-group-parts.d.ts.map +1 -1
  54. package/dist/v2/components/chat/types.d.ts +1 -1
  55. package/dist/v2/components/chat/types.d.ts.map +1 -1
  56. package/dist/v2/components/chat/use-lightbox.d.ts.map +1 -1
  57. package/dist/v2/components/ui/CopilotDropdownMenuContent.vue.d.ts +1 -1
  58. package/dist/v2/components/ui/CopilotDropdownMenuContent.vue.d.ts.map +1 -1
  59. package/dist/v2/hooks/use-agent-context.d.ts +2 -3
  60. package/dist/v2/hooks/use-agent-context.d.ts.map +1 -1
  61. package/dist/v2/hooks/use-agent.d.ts +4 -1
  62. package/dist/v2/hooks/use-agent.d.ts.map +1 -1
  63. package/dist/v2/hooks/use-attachments.d.ts +7 -0
  64. package/dist/v2/hooks/use-attachments.d.ts.map +1 -1
  65. package/dist/v2/hooks/use-capabilities.d.ts.map +1 -1
  66. package/dist/v2/hooks/use-component.d.ts +1 -0
  67. package/dist/v2/hooks/use-component.d.ts.map +1 -1
  68. package/dist/v2/hooks/use-configure-suggestions.d.ts +4 -9
  69. package/dist/v2/hooks/use-configure-suggestions.d.ts.map +1 -1
  70. package/dist/v2/hooks/use-default-render-tool.d.ts.map +1 -1
  71. package/dist/v2/hooks/use-human-in-the-loop.d.ts +2 -1
  72. package/dist/v2/hooks/use-human-in-the-loop.d.ts.map +1 -1
  73. package/dist/v2/hooks/use-interrupt.d.ts +0 -1
  74. package/dist/v2/hooks/use-interrupt.d.ts.map +1 -1
  75. package/dist/v2/hooks/use-render-activity-message.d.ts.map +1 -1
  76. package/dist/v2/hooks/use-render-custom-messages.d.ts.map +1 -1
  77. package/dist/v2/hooks/use-suggestions.d.ts.map +1 -1
  78. package/dist/v2/hooks/use-threads.d.ts +0 -8
  79. package/dist/v2/hooks/use-threads.d.ts.map +1 -1
  80. package/dist/v2/index.cjs +1 -1
  81. package/dist/v2/index.mjs +1 -1
  82. package/dist/v2/lib/vue-core.d.ts +12 -11
  83. package/dist/v2/lib/vue-core.d.ts.map +1 -1
  84. package/dist/v2/providers/CopilotChatConfigurationProvider.vue.d.ts.map +1 -1
  85. package/dist/v2/providers/CopilotKitProvider.types.d.ts +9 -124
  86. package/dist/v2/providers/CopilotKitProvider.types.d.ts.map +1 -1
  87. package/dist/v2/providers/CopilotKitProvider.vue.d.ts +9 -10
  88. package/dist/v2/providers/CopilotKitProvider.vue.d.ts.map +1 -1
  89. package/dist/v2/providers/chat-configuration-store-key.d.ts +8 -0
  90. package/dist/v2/providers/chat-configuration-store-key.d.ts.map +1 -0
  91. package/dist/v2/providers/markdown-renderer.d.ts +3 -1
  92. package/dist/v2/providers/markdown-renderer.d.ts.map +1 -1
  93. package/dist/v2/providers/use-inspector-thread-override.d.ts +5 -0
  94. package/dist/v2/providers/use-inspector-thread-override.d.ts.map +1 -1
  95. package/package.json +8 -8
  96. package/src/v2/__tests__/exports.test.ts +10 -0
  97. package/src/v2/__tests__/mocks/web-inspector.ts +6 -0
  98. package/src/v2/__tests__/utils/test-helpers.ts +34 -4
  99. package/src/v2/components/A2UIMessageRenderer.ts +98 -68
  100. package/src/v2/components/A2UISurfaceActivityRenderer.vue +68 -103
  101. package/src/v2/components/CopilotKitInspector.vue +104 -51
  102. package/src/v2/components/MCPAppsActivityRenderer.ts +75 -201
  103. package/src/v2/components/OpenGenerativeUIRenderer.ts +78 -80
  104. package/src/v2/components/__tests__/A2UIMessageRenderer.test.ts +171 -8
  105. package/src/v2/components/__tests__/CopilotKitInspector.test.ts +42 -0
  106. package/src/v2/components/__tests__/OpenGenerativeUIRenderer.test.ts +9 -2
  107. package/src/v2/components/__tests__/OpenGenerativeUIToolRenderer.test.ts +38 -0
  108. package/src/v2/components/a2ui/A2UIBuiltInToolCallRenderer.ts +1 -6
  109. package/src/v2/components/a2ui/A2UICatalogContext.ts +27 -93
  110. package/src/v2/components/a2ui/A2UIRecoveryStates.ts +127 -327
  111. package/src/v2/components/a2ui/catalog.ts +2 -3
  112. package/src/v2/components/a2ui/utils.ts +13 -67
  113. package/src/v2/components/a2ui.ts +14 -21
  114. package/src/v2/components/chat/CopilotChat.vue +136 -324
  115. package/src/v2/components/chat/CopilotChatAttachmentQueue.vue +22 -45
  116. package/src/v2/components/chat/CopilotChatAudioRecorder.vue +19 -246
  117. package/src/v2/components/chat/CopilotChatInput.vue +69 -407
  118. package/src/v2/components/chat/CopilotChatLightbox.vue +10 -31
  119. package/src/v2/components/chat/CopilotChatMessageView.vue +52 -112
  120. package/src/v2/components/chat/CopilotChatToolCallGroup.vue +14 -45
  121. package/src/v2/components/chat/CopilotChatToolCallItem.vue +6 -4
  122. package/src/v2/components/chat/CopilotChatToolCallsView.vue +16 -19
  123. package/src/v2/components/chat/CopilotChatView.vue +28 -23
  124. package/src/v2/components/chat/CopilotPopupViewInternal.vue +21 -97
  125. package/src/v2/components/chat/CopilotSidebarViewInternal.vue +24 -25
  126. package/src/v2/components/chat/CopilotThreadsDrawer.vue +37 -102
  127. package/src/v2/components/chat/StreamingMarkdownDefault.vue +13 -26
  128. package/src/v2/components/chat/__tests__/CopilotChat.test.ts +12 -10
  129. package/src/v2/components/chat/__tests__/CopilotChatAttachmentQueue.test.ts +28 -0
  130. package/src/v2/components/chat/__tests__/CopilotChatInput.test.ts +56 -0
  131. package/src/v2/components/chat/__tests__/CopilotPopupView.test.ts +19 -0
  132. package/src/v2/components/chat/__tests__/CopilotSidebarView.position.test.ts +32 -8
  133. package/src/v2/components/chat/__tests__/CopilotSidebarView.test.ts +2 -1
  134. package/src/v2/components/chat/__tests__/StreamingMarkdownDefault.test.ts +54 -0
  135. package/src/v2/components/chat/audioRecorder.ts +4 -7
  136. package/src/v2/components/chat/copilotChatToolCallItemRender.ts +22 -71
  137. package/src/v2/components/chat/tool-call-display-context.ts +6 -1
  138. package/src/v2/components/chat/tool-call-group-parts.ts +13 -33
  139. package/src/v2/components/chat/types.ts +1 -1
  140. package/src/v2/components/chat/use-lightbox.ts +15 -33
  141. package/src/v2/hooks/__tests__/use-agent-error-state.test.ts +5 -3
  142. package/src/v2/hooks/__tests__/use-agent-stability.test.ts +25 -4
  143. package/src/v2/hooks/__tests__/use-agent-throttle.test.ts +5 -1
  144. package/src/v2/hooks/__tests__/use-agent.test.ts +6 -3
  145. package/src/v2/hooks/__tests__/use-component.test.ts +21 -0
  146. package/src/v2/hooks/__tests__/use-configure-suggestions.test.ts +30 -1
  147. package/src/v2/hooks/__tests__/use-default-render-tool.test.ts +10 -10
  148. package/src/v2/hooks/__tests__/use-frontend-tool.e2e.test.ts +4 -0
  149. package/src/v2/hooks/__tests__/use-human-in-the-loop.e2e.test.ts +6 -1
  150. package/src/v2/hooks/__tests__/use-human-in-the-loop.test.ts +187 -12
  151. package/src/v2/hooks/__tests__/use-interrupt.test.ts +97 -0
  152. package/src/v2/hooks/__tests__/use-render-activity-message.test.ts +2 -1
  153. package/src/v2/hooks/__tests__/use-threads.test.ts +48 -6
  154. package/src/v2/hooks/use-agent-context.ts +4 -10
  155. package/src/v2/hooks/use-agent.ts +86 -290
  156. package/src/v2/hooks/use-attachments.ts +42 -166
  157. package/src/v2/hooks/use-capabilities.ts +2 -7
  158. package/src/v2/hooks/use-component.ts +7 -4
  159. package/src/v2/hooks/use-configure-suggestions.ts +28 -218
  160. package/src/v2/hooks/use-default-render-tool.ts +34 -94
  161. package/src/v2/hooks/use-human-in-the-loop.ts +11 -80
  162. package/src/v2/hooks/use-interrupt.ts +29 -308
  163. package/src/v2/hooks/use-render-activity-message.ts +17 -20
  164. package/src/v2/hooks/use-render-custom-messages.ts +20 -63
  165. package/src/v2/hooks/use-suggestions.ts +9 -33
  166. package/src/v2/hooks/use-threads.ts +43 -273
  167. package/src/v2/lib/__tests__/vue-core-renderers.test.ts +42 -0
  168. package/src/v2/lib/vue-core.ts +67 -72
  169. package/src/v2/providers/CopilotChatConfigurationProvider.vue +48 -186
  170. package/src/v2/providers/CopilotKitProvider.types.ts +12 -127
  171. package/src/v2/providers/CopilotKitProvider.vue +188 -402
  172. package/src/v2/providers/__tests__/CopilotChatConfigurationProvider.test.ts +22 -2
  173. package/src/v2/providers/__tests__/CopilotKitProvider.a2ui.test.ts +19 -1
  174. package/src/v2/providers/__tests__/CopilotKitProvider.config.test.ts +124 -0
  175. package/src/v2/providers/__tests__/CopilotKitProvider.sandboxFunctions.test.ts +4 -1
  176. package/src/v2/providers/__tests__/CopilotKitProvider.test.ts +45 -2
  177. package/src/v2/providers/chat-configuration-store-key.ts +9 -0
  178. package/src/v2/providers/markdown-renderer.ts +7 -1
  179. package/src/v2/providers/use-inspector-thread-override.ts +22 -80
  180. package/vite.config.ts +5 -1
  181. package/vitest.config.ts +12 -7
  182. package/dist/use-render-activity-message-CsWYyd6r.cjs +0 -91
  183. package/dist/use-render-activity-message-CsWYyd6r.cjs.map +0 -1
  184. package/dist/use-render-activity-message-DntKKNdd.js +0 -17418
  185. package/dist/use-render-activity-message-DntKKNdd.js.map +0 -1
  186. package/dist/v2/components/chat/normalize-auto-scroll.d.ts +0 -3
  187. package/dist/v2/components/chat/normalize-auto-scroll.d.ts.map +0 -1
  188. package/dist/v2/lib/is-mobile-viewport.d.ts +0 -2
  189. package/dist/v2/lib/is-mobile-viewport.d.ts.map +0 -1
  190. package/src/v2/components/__tests__/A2UICatalogContext.test.ts +0 -63
  191. package/src/v2/components/a2ui/__tests__/A2UIRecoveryStates.test.ts +0 -175
  192. package/src/v2/components/chat/normalize-auto-scroll.ts +0 -3
  193. package/src/v2/lib/is-mobile-viewport.ts +0 -5
@@ -1,9 +1,5 @@
1
1
  <script setup lang="ts">
2
- import {
3
- GENERATE_SANDBOXED_UI_DESCRIPTION,
4
- randomUUID,
5
- ɵanySchema,
6
- } from "@copilotkit/shared";
2
+ import { ɵanySchema } from "@copilotkit/shared";
7
3
  import {
8
4
  computed,
9
5
  h,
@@ -17,31 +13,36 @@ import {
17
13
  watch,
18
14
  } from "vue";
19
15
  import type { Component, FunctionalComponent } from "vue";
20
- import type { AbstractAgent } from "@ag-ui/client";
21
- import { ToolCallStatus } from "@copilotkit/core";
16
+ import type { Catalog, ComponentApi } from "@a2ui/web_core/v0_9";
17
+ import {
18
+ ɵLearningAutoStarter,
19
+ ɵbuildHumanInTheLoopTool,
20
+ ɵhitlRenderProps,
21
+ ɵtoLearningConfig,
22
+ } from "@copilotkit/core";
22
23
  import type {
23
- CopilotKitCoreErrorCode,
24
- CopilotKitCoreSubscriber,
25
24
  CopilotKitHeadersSource,
26
25
  FrontendTool,
26
+ ɵRuntimeInfo,
27
27
  } from "@copilotkit/core";
28
28
  import {
29
- DEFAULT_OPEN_GENERATIVE_UI_DESIGN_SKILL,
30
- GENERATE_SANDBOXED_UI_TOOL_NAME,
29
+ ɵSTABLE_ARRAY_WARNINGS,
30
+ ɵbuildOpenGenerativeUIContexts,
31
+ ɵcreateOpenGenerativeUITool,
32
+ ɵisOpenGenerativeUIActive,
33
+ ɵpublicKeyHeaderDefaults,
34
+ ɵreportProviderConfigDiagnostics,
31
35
  ɵresolveLicenseState,
36
+ ɵresolveProviderConfig,
37
+ ɵtoolRendererShapeChanged,
32
38
  ɵwithHeaderDefaults,
33
39
  } from "@copilotkit/core";
34
- import { schemaToJsonSchema, shouldEnableInspector } from "@copilotkit/shared";
35
- import type {
36
- RuntimeEntitlementResponse,
37
- RuntimeLicenseStatus,
38
- } from "@copilotkit/shared";
40
+ import { shouldEnableInspector } from "@copilotkit/shared";
39
41
  import { CopilotKitCoreVue } from "../lib/vue-core";
40
42
  import { createA2UIMessageRenderer } from "../components/A2UIMessageRenderer";
41
43
  import { registerA2UIBuiltInToolCallRenderer } from "../components/a2ui/A2UIBuiltInToolCallRenderer";
42
- import { registerA2UICatalogContext } from "../components/a2ui/A2UICatalogContext";
44
+ import { registerA2UICatalog } from "../components/a2ui/A2UICatalogContext";
43
45
  import {
44
- GenerateSandboxedUiArgsSchema,
45
46
  OpenGenerativeUIActivityRenderer,
46
47
  OpenGenerativeUIActivityType,
47
48
  OpenGenerativeUIContentSchema,
@@ -63,10 +64,7 @@ import { MARKDOWN_RENDERER_KEY } from "./markdown-renderer";
63
64
  import { LicenseContextKey } from "./license-context";
64
65
  import CopilotKitInspector from "../components/CopilotKitInspector.vue";
65
66
  import LicenseWarningBanner from "../components/LicenseWarningBanner.vue";
66
- import type {
67
- CopilotKitLearningOptions,
68
- CopilotKitProviderProps,
69
- } from "./CopilotKitProvider.types";
67
+ import type { CopilotKitProviderProps } from "./CopilotKitProvider.types";
70
68
  import type {
71
69
  SandboxFunction,
72
70
  VueActivityMessageRenderer,
@@ -75,27 +73,6 @@ import type {
75
73
  VueToolCallRendererRenderProps,
76
74
  } from "../types";
77
75
 
78
- const HEADER_NAME = "X-CopilotCloud-Public-Api-Key";
79
- const COPILOT_CLOUD_CHAT_URL = "https://api.cloud.copilotkit.ai/copilotkit/v1";
80
- // Canonical A2UI viewer theme default (matches @copilotkit/a2ui-renderer).
81
- // Defined locally to avoid pulling React dependencies from a2ui-renderer.
82
- const viewerTheme: Record<string, unknown> = {};
83
-
84
- const FRONTEND_TOOLS_STABLE_WARNING =
85
- "frontendTools must be a stable array. If you want to dynamically add or remove tools, use `useFrontendTool` instead.";
86
- const HUMAN_IN_THE_LOOP_STABLE_WARNING =
87
- "humanInTheLoop must be a stable array. If you want to dynamically add or remove human-in-the-loop tools, use `useHumanInTheLoop` instead.";
88
- const RENDER_CUSTOM_MESSAGES_STABLE_WARNING =
89
- "renderCustomMessages must be a stable array.";
90
- const RENDER_ACTIVITY_MESSAGES_STABLE_WARNING =
91
- "renderActivityMessages must be a stable array.";
92
- const SANDBOX_FUNCTIONS_STABLE_WARNING =
93
- "openGenerativeUI.sandboxFunctions must be a stable array.";
94
- // Matches the message React's `useHumanInTheLoop` rejects with, so an aborted
95
- // interrupt reads the same across frameworks (see #5554).
96
- const HUMAN_IN_THE_LOOP_ABORTED_MESSAGE =
97
- "Human-in-the-loop interaction aborted";
98
-
99
76
  /** The MCP Apps renderer with `mcpApps.allowSameOriginFallback` applied. */
100
77
  const SameOriginMCPAppsActivityRenderer: FunctionalComponent = (_, { attrs }) =>
101
78
  h(MCPAppsActivityRenderer as Component, {
@@ -129,12 +106,16 @@ provide(
129
106
  );
130
107
 
131
108
  const shouldRenderInspector = ref(false);
109
+ // Follows the Inspector's own show/hide, so message actions that open it are
110
+ // hidden while a temporary dismissal hides it.
111
+ const inspectorVisible = ref(false);
132
112
 
133
113
  function updateInspectorVisibility(): void {
134
114
  shouldRenderInspector.value = shouldEnableInspector({
135
115
  enableInspector: props.enableInspector,
136
116
  isBrowser: true,
137
117
  isDevelopment: process.env.NODE_ENV === "development",
118
+ hostname: window.location?.hostname,
138
119
  });
139
120
  }
140
121
 
@@ -142,7 +123,9 @@ onMounted(updateInspectorVisibility);
142
123
  watch(() => props.enableInspector, updateInspectorVisibility);
143
124
 
144
125
  const inspectorOpenRequest = ref<VueInspectorOpenRequest | null>(null);
145
- const isInspectorEnabled = computed(() => shouldRenderInspector.value);
126
+ const isInspectorEnabled = computed(
127
+ () => shouldRenderInspector.value && inspectorVisible.value,
128
+ );
146
129
 
147
130
  function openInspector(request: VueInspectorOpenRequest) {
148
131
  inspectorOpenRequest.value = { ...request };
@@ -153,6 +136,7 @@ provide(InspectorKey, {
153
136
  openInspector,
154
137
  });
155
138
 
139
+ const initialRenderToolCalls = props.renderToolCalls ?? [];
156
140
  const initialFrontendTools = props.frontendTools;
157
141
  const initialHumanInTheLoop = props.humanInTheLoop;
158
142
  const initialRenderCustomMessages = props.renderCustomMessages;
@@ -165,11 +149,22 @@ const initialSandboxFunctions = props.openGenerativeUI?.sandboxFunctions;
165
149
  const rawEntries = <T>(entries: readonly T[] | undefined): T[] =>
166
150
  [...toRaw(entries ?? [])].map((entry) => toRaw(entry));
167
151
 
152
+ // Only the shape (agentId:name pairs) counts, so new render closures for the
153
+ // same tools do not warn.
154
+ watch(
155
+ () => props.renderToolCalls,
156
+ (next) => {
157
+ if (ɵtoolRendererShapeChanged(initialRenderToolCalls, next ?? [])) {
158
+ console.error(ɵSTABLE_ARRAY_WARNINGS.renderToolCalls);
159
+ }
160
+ },
161
+ );
162
+
168
163
  watch(
169
164
  () => props.frontendTools,
170
165
  (next) => {
171
166
  if (next !== initialFrontendTools) {
172
- console.error(FRONTEND_TOOLS_STABLE_WARNING);
167
+ console.error(ɵSTABLE_ARRAY_WARNINGS.frontendTools);
173
168
  }
174
169
  },
175
170
  );
@@ -178,7 +173,7 @@ watch(
178
173
  () => props.humanInTheLoop,
179
174
  (next) => {
180
175
  if (next !== initialHumanInTheLoop) {
181
- console.error(HUMAN_IN_THE_LOOP_STABLE_WARNING);
176
+ console.error(ɵSTABLE_ARRAY_WARNINGS.humanInTheLoop);
182
177
  }
183
178
  },
184
179
  );
@@ -187,7 +182,7 @@ watch(
187
182
  () => props.renderCustomMessages,
188
183
  (next) => {
189
184
  if (next !== initialRenderCustomMessages) {
190
- console.error(RENDER_CUSTOM_MESSAGES_STABLE_WARNING);
185
+ console.error(ɵSTABLE_ARRAY_WARNINGS.renderCustomMessages);
191
186
  }
192
187
  },
193
188
  );
@@ -196,7 +191,7 @@ watch(
196
191
  () => props.renderActivityMessages,
197
192
  (next) => {
198
193
  if (next !== initialRenderActivityMessages) {
199
- console.error(RENDER_ACTIVITY_MESSAGES_STABLE_WARNING);
194
+ console.error(ɵSTABLE_ARRAY_WARNINGS.renderActivityMessages);
200
195
  }
201
196
  },
202
197
  );
@@ -205,21 +200,30 @@ watch(
205
200
  () => props.openGenerativeUI?.sandboxFunctions,
206
201
  (next) => {
207
202
  if (next !== initialSandboxFunctions) {
208
- console.error(SANDBOX_FUNCTIONS_STABLE_WARNING);
203
+ console.error(ɵSTABLE_ARRAY_WARNINGS.sandboxFunctions);
209
204
  }
210
205
  },
211
206
  );
212
207
 
213
- const resolvedPublicKey = computed(
214
- () => props.publicApiKey ?? props.publicLicenseKey,
215
- );
216
- const mergedAgents = computed(() => ({
217
- ...props.agents__unsafe_dev_only,
218
- ...props.selfManagedAgents,
219
- }));
220
- const hasLocalAgents = computed(
221
- () => Object.keys(mergedAgents.value).length > 0,
208
+ // Key fallback, Copilot Cloud URL, transport, agent merge and the catalog
209
+ // property all come from core.
210
+ const resolvedConfig = computed(() =>
211
+ ɵresolveProviderConfig({
212
+ runtimeUrl: props.runtimeUrl,
213
+ publicApiKey: props.publicApiKey,
214
+ publicLicenseKey: props.publicLicenseKey,
215
+ useSingleEndpoint: props.useSingleEndpoint,
216
+ agents__unsafe_dev_only: props.agents__unsafe_dev_only,
217
+ selfManagedAgents: props.selfManagedAgents,
218
+ properties: props.properties,
219
+ a2uiCatalog: props.a2ui?.catalog,
220
+ }),
222
221
  );
222
+ // Strings, so dependents only re-run when the value really changes.
223
+ const resolvedPublicKey = computed(() => resolvedConfig.value.publicKey);
224
+ const chatApiEndpoint = computed(() => resolvedConfig.value.runtimeUrl);
225
+ const runtimeTransport = computed(() => resolvedConfig.value.runtimeTransport);
226
+ const mergedAgents = computed(() => resolvedConfig.value.agents);
223
227
 
224
228
  // Whether `headers` is a builder, as its own computed so that a re-render
225
229
  // merely passing a NEW function of the same kind (e.g. a fresh inline arrow)
@@ -248,122 +252,46 @@ const latestHeaders = (() =>
248
252
  const headersSource = computed<CopilotKitHeadersSource>(() =>
249
253
  ɵwithHeaderDefaults(
250
254
  isHeadersBuilder.value ? latestHeaders : props.headers,
251
- resolvedPublicKey.value ? { [HEADER_NAME]: resolvedPublicKey.value } : {},
255
+ ɵpublicKeyHeaderDefaults(resolvedPublicKey.value),
252
256
  ),
253
257
  );
254
258
 
255
- const chatApiEndpoint = computed(
256
- () =>
257
- props.runtimeUrl ??
258
- (resolvedPublicKey.value ? COPILOT_CLOUD_CHAT_URL : undefined),
259
- );
260
-
259
+ // Throws in production for a missing runtime config; otherwise warns, once
260
+ // per provider for each message.
261
+ const loggedDiagnostics = new Set<string>();
261
262
  watch(
262
- [chatApiEndpoint, resolvedPublicKey, hasLocalAgents],
263
- ([endpoint, publicKey, localAgents]) => {
264
- if (endpoint || publicKey || localAgents) return;
265
- const msg =
266
- "Missing required prop: 'runtimeUrl' or 'publicApiKey' or 'publicLicenseKey'";
267
- if (process.env.NODE_ENV === "production") {
268
- throw new Error(msg);
269
- }
270
- console.warn(msg);
263
+ () => resolvedConfig.value.diagnostics,
264
+ (diagnostics) => {
265
+ ɵreportProviderConfigDiagnostics(diagnostics, {
266
+ isProduction: process.env.NODE_ENV === "production",
267
+ logged: loggedDiagnostics,
268
+ });
271
269
  },
272
270
  { immediate: true },
273
271
  );
274
272
 
275
- /**
276
- * A human-in-the-loop tool call from the `humanInTheLoop` prop that is waiting
277
- * on the user. Keyed by tool call id so parallel interrupts on the same tool
278
- * stay independent.
279
- */
280
- type PendingHumanInTheLoop = {
281
- resolve: (result: unknown) => void;
282
- detachAbort?: () => void;
283
- };
284
-
285
- const pendingHumanInTheLoop = new Map<string, PendingHumanInTheLoop>();
286
-
287
- /** Removes a pending interaction and detaches its abort listener. */
288
- const takePendingHumanInTheLoop = (key: string) => {
289
- const pending = pendingHumanInTheLoop.get(key);
290
- if (!pending) return undefined;
291
- pending.detachAbort?.();
292
- pendingHumanInTheLoop.delete(key);
293
- return pending;
294
- };
295
-
296
273
  const processedHumanInTheLoop = computed(() => {
297
274
  const tools: FrontendTool[] = [];
298
275
  const renderToolCalls: VueToolCallRenderer<unknown>[] = [];
276
+ // Core parks each call by tool call id until the render responds. The core
277
+ // is created further down, so read its registry lazily.
278
+ const registry = () => copilotkit.value.ɵhumanInTheLoop;
299
279
 
300
280
  for (const tool of rawEntries(props.humanInTheLoop)) {
301
- tools.push({
302
- type: "human-in-the-loop",
303
- name: tool.name,
304
- description: tool.description,
305
- parameters: tool.parameters,
306
- followUp: tool.followUp,
307
- ...(tool.agentId && { agentId: tool.agentId }),
308
- // Keep the tool call pending until the render calls `respond`, matching
309
- // the `useHumanInTheLoop` composable. Resolving immediately made the HITL
310
- // UI flash and disappear without ever waiting for the user.
311
- handler: async (_args, context) => {
312
- const signal = context?.signal;
313
- const key = context?.toolCall?.id ?? tool.name;
314
-
315
- return new Promise((resolve, reject) => {
316
- // Already aborted before the handler ran — reject so core records an
317
- // explicit error tool result rather than silently resolving empty.
318
- if (signal?.aborted) {
319
- reject(new Error(HUMAN_IN_THE_LOOP_ABORTED_MESSAGE));
320
- return;
321
- }
322
-
323
- const pending: PendingHumanInTheLoop = { resolve };
324
- pendingHumanInTheLoop.set(key, pending);
325
-
326
- if (signal) {
327
- const onAbort = () => {
328
- pendingHumanInTheLoop.delete(key);
329
- reject(new Error(HUMAN_IN_THE_LOOP_ABORTED_MESSAGE));
330
- };
331
- signal.addEventListener("abort", onAbort, { once: true });
332
- pending.detachAbort = () => {
333
- signal.removeEventListener("abort", onAbort);
334
- };
335
- }
336
- });
337
- },
338
- });
339
- if (tool.render) {
340
- const ToolComponent = tool.render;
281
+ const { render: ToolComponent, ...config } = tool;
282
+ tools.push(ɵbuildHumanInTheLoopTool(config, registry) as FrontendTool);
283
+ if (ToolComponent) {
341
284
  const render: VueToolCallRenderer<unknown>["render"] = (
342
285
  renderProps: VueToolCallRendererRenderProps<unknown>,
343
- ) => {
344
- const key = renderProps.toolCallId ?? tool.name;
345
- return h(ToolComponent as Parameters<typeof h>[0], {
346
- ...renderProps,
347
- // `renderProps.name` is the tool that was actually invoked. It equals
348
- // `tool.name` for a named registration; for a wildcard (`"*"`) it is
349
- // the only place the real name exists.
350
- name: tool.name === "*" ? renderProps.name : tool.name,
351
- description: tool.description || "",
352
- agentId: tool.agentId,
353
- // `respond` is live only while the tool is executing — the one phase
354
- // with a promise waiting on the user.
355
- respond:
356
- renderProps.status === ToolCallStatus.Executing
357
- ? async (result: unknown) => {
358
- takePendingHumanInTheLoop(key)?.resolve(result);
359
- }
360
- : undefined,
361
- });
362
- };
286
+ ) =>
287
+ h(
288
+ ToolComponent as Parameters<typeof h>[0],
289
+ ɵhitlRenderProps(renderProps, tool, registry()),
290
+ );
363
291
 
364
292
  renderToolCalls.push({
365
293
  name: tool.name,
366
- args: tool.parameters ?? ɵanySchema,
294
+ args: tool.parameters,
367
295
  render,
368
296
  ...(tool.agentId && { agentId: tool.agentId }),
369
297
  } as VueToolCallRenderer<unknown>);
@@ -411,15 +339,26 @@ const allRenderToolCalls = computed(() => {
411
339
  const allRenderCustomMessages = computed(
412
340
  () => props.renderCustomMessages ?? [],
413
341
  );
414
- const runtimeA2UIEnabled = ref(false);
415
- const runtimeOpenGenerativeUIEnabled = ref(false);
416
- const runtimeLicenseStatus = ref<RuntimeLicenseStatus | undefined>(undefined);
417
- const runtimeEntitlements = ref<RuntimeEntitlementResponse | undefined>(
418
- undefined,
342
+ // Core's runtime info snapshot, projected from the core watcher below.
343
+ const runtimeInfo = shallowRef<ɵRuntimeInfo | null>(null);
344
+ const runtimeA2UIEnabled = computed(
345
+ () => runtimeInfo.value?.a2uiEnabled ?? false,
346
+ );
347
+ const runtimeOpenGenerativeUIEnabled = computed(
348
+ () => runtimeInfo.value?.openGenerativeUIEnabled ?? false,
349
+ );
350
+ const runtimeLicenseStatus = computed(() => runtimeInfo.value?.licenseStatus);
351
+ const runtimeEntitlements = computed(
352
+ () => runtimeInfo.value?.runtimeEntitlements,
419
353
  );
420
- const runtimeEntitlementRetryPending = ref(false);
421
- const openGenerativeUIActive = computed(
422
- () => runtimeOpenGenerativeUIEnabled.value || !!props.openGenerativeUI,
354
+ const runtimeEntitlementRetryPending = computed(
355
+ () => runtimeInfo.value?.runtimeEntitlementRetryPending ?? false,
356
+ );
357
+ const openGenerativeUIActive = computed(() =>
358
+ ɵisOpenGenerativeUIActive({
359
+ runtimeEnabled: runtimeOpenGenerativeUIEnabled.value,
360
+ configured: !!props.openGenerativeUI,
361
+ }),
423
362
  );
424
363
  // A catalog passed to the provider is enough to turn A2UI on: render the
425
364
  // surfaces locally and forward the catalog signal so the runtime injects the
@@ -428,14 +367,15 @@ const a2uiCatalogProvided = computed(() => !!props.a2ui?.catalog);
428
367
  const a2uiActive = computed(
429
368
  () => runtimeA2UIEnabled.value || a2uiCatalogProvided.value,
430
369
  );
370
+ // The catalog with components disabled in the Inspector removed; set by
371
+ // `registerA2UICatalog` below once the core exists.
372
+ const a2uiFilteredCatalog = shallowRef<Catalog<ComponentApi> | undefined>(
373
+ undefined,
374
+ );
431
375
  // Forward a per-run signal when the provider has an A2UI catalog so the
432
376
  // runtime can turn A2UI on (and inject the render tool) without a separate
433
377
  // `a2ui.injectA2UITool` flag on the runtime.
434
- const resolvedProperties = computed(() =>
435
- a2uiCatalogProvided.value
436
- ? { ...props.properties, a2uiCatalogAvailable: true }
437
- : props.properties,
438
- );
378
+ const resolvedProperties = computed(() => resolvedConfig.value.properties);
439
379
  const sandboxFunctions = computed<readonly SandboxFunction[]>(() =>
440
380
  rawEntries(props.openGenerativeUI?.sandboxFunctions),
441
381
  );
@@ -443,13 +383,7 @@ const builtInFrontendTools = computed<VueFrontendTool[]>(() => {
443
383
  if (!openGenerativeUIActive.value) return [];
444
384
  return [
445
385
  {
446
- name: GENERATE_SANDBOXED_UI_TOOL_NAME,
447
- description: GENERATE_SANDBOXED_UI_DESCRIPTION,
448
- parameters: GenerateSandboxedUiArgsSchema,
449
- handler: async () => "UI generated",
450
- // This acknowledgement has no side effects and is safe to reconstruct.
451
- reconnectBehavior: "resume-pending",
452
- followUp: true,
386
+ ...ɵcreateOpenGenerativeUITool(),
453
387
  render:
454
388
  OpenGenerativeUIToolRenderer as unknown as VueFrontendTool["render"],
455
389
  } as VueFrontendTool,
@@ -481,10 +415,11 @@ const builtInActivityRenderers = computed<
481
415
  if (a2uiActive.value) {
482
416
  renderers.unshift(
483
417
  createA2UIMessageRenderer({
484
- theme: props.a2ui?.theme ?? viewerTheme,
485
- catalog: props.a2ui?.catalog,
418
+ theme: props.a2ui?.theme ?? {},
419
+ catalog: a2uiFilteredCatalog.value ?? props.a2ui?.catalog,
486
420
  loadingComponent: props.a2ui?.loadingComponent,
487
421
  recovery: props.a2ui?.recovery,
422
+ onAction: props.a2ui?.onAction,
488
423
  }),
489
424
  );
490
425
  }
@@ -497,40 +432,15 @@ const allRenderActivityMessages = computed(() => [
497
432
  ...builtInActivityRenderers.value,
498
433
  ]);
499
434
 
500
- const applyDefaultThrottleMs = (core: CopilotKitCoreVue) => {
501
- if (
502
- props.defaultThrottleMs !== undefined &&
503
- (!Number.isFinite(props.defaultThrottleMs) || props.defaultThrottleMs < 0)
504
- ) {
505
- console.error(
506
- `CopilotKitProvider: defaultThrottleMs must be a non-negative finite number, got ${props.defaultThrottleMs}. useAgent hooks without an explicit throttleMs will fall back to unthrottled.`,
507
- );
508
- }
509
- core.setDefaultThrottleMs(props.defaultThrottleMs);
510
- };
511
-
512
- function toLearningConfig(
513
- learning: boolean | CopilotKitLearningOptions | undefined,
514
- ): CopilotKitLearningOptions | undefined {
515
- // `true` uses the default authenticated capture options.
516
- if (learning === true) return {};
517
- if (learning === false || learning === undefined) return undefined;
518
- // `autoStart` only controls the provider; Core never receives it.
519
- const { autoStart: _autoStart, ...config } = learning;
520
- return config;
521
- }
435
+ const learningConfig = computed(() => ɵtoLearningConfig(props.learning));
522
436
 
523
- const learningConfig = computed(() => toLearningConfig(props.learning));
524
-
525
- const createCopilotKit = () => {
526
- const core = new CopilotKitCoreVue({
437
+ const createCopilotKit = () =>
438
+ new CopilotKitCoreVue({
527
439
  runtimeUrl: chatApiEndpoint.value,
528
- runtimeTransport:
529
- props.useSingleEndpoint === true
530
- ? "single"
531
- : props.useSingleEndpoint === false
532
- ? "rest"
533
- : "auto",
440
+ // `/info` starts from `onMounted` (`connect()` below), so server-side
441
+ // setup never fetches it.
442
+ deferInitialConnection: true,
443
+ runtimeTransport: runtimeTransport.value,
534
444
  headers: headersSource.value,
535
445
  credentials: props.credentials,
536
446
  messageFilter: props.messageFilter,
@@ -541,12 +451,12 @@ const createCopilotKit = () => {
541
451
  renderActivityMessages: allRenderActivityMessages.value,
542
452
  renderCustomMessages: allRenderCustomMessages.value,
543
453
  debug: props.debug,
454
+ // Set at construction so child hooks can read it on first render. Core
455
+ // validates it.
456
+ defaultThrottleMs: props.defaultThrottleMs,
457
+ onError: props.onError,
544
458
  learning: learningConfig.value,
545
459
  });
546
- // Initialize synchronously so child hooks can read the value on first render.
547
- applyDefaultThrottleMs(core);
548
- return core;
549
- };
550
460
 
551
461
  const copilotkit = shallowRef<CopilotKitCoreVue>(createCopilotKit());
552
462
  const didMountRef = ref(false);
@@ -556,27 +466,17 @@ const executingToolCallIds = ref<ReadonlySet<string>>(new Set());
556
466
  watch(
557
467
  copilotkit,
558
468
  (core, _, onCleanup) => {
469
+ // Core keeps a call executing until its result is in the messages, so
470
+ // the status never drops back to in-progress between the two.
471
+ executingToolCallIds.value = core.executingToolCallIds;
559
472
  const sub1 = core.subscribe({
560
- onToolExecutionStart: ({
561
- toolCallId,
562
- }: Parameters<
563
- NonNullable<CopilotKitCoreSubscriber["onToolExecutionStart"]>
564
- >[0]) => {
565
- executingToolCallIds.value = new Set(executingToolCallIds.value).add(
566
- toolCallId,
567
- );
568
- },
569
- onToolExecutionEnd: ({
570
- toolCallId,
571
- }: Parameters<
572
- NonNullable<CopilotKitCoreSubscriber["onToolExecutionEnd"]>
573
- >[0]) => {
574
- setTimeout(() => {
575
- const next = new Set(executingToolCallIds.value);
576
- next.delete(toolCallId);
577
- executingToolCallIds.value = next;
578
- triggerRef(copilotkit);
579
- }, 0);
473
+ onExecutingToolCallsChanged: ({ executingToolCallIds: ids }) => {
474
+ const hasFinishedCall = ids.size < executingToolCallIds.value.size;
475
+ executingToolCallIds.value = ids;
476
+ // Core adds the result to `agent.messages` without a messages event,
477
+ // so re-read the agents once a call finishes. Not on start: that
478
+ // re-runs the agent subscriptions mid-run and drops a pending update.
479
+ if (hasFinishedCall) triggerRef(copilotkit);
580
480
  },
581
481
  });
582
482
  const sub2 = core.subscribe({
@@ -588,27 +488,21 @@ watch(
588
488
  onRenderCustomMessagesChanged: () => {
589
489
  triggerRef(copilotkit);
590
490
  },
491
+ onRenderActivityMessagesChanged: () => {
492
+ triggerRef(copilotkit);
493
+ },
591
494
  });
495
+ runtimeInfo.value = core.ɵruntimeInfo;
496
+ const unsubscribeRuntimeInfo = core.ɵsubscribeToRuntimeInfo(() => {
497
+ runtimeInfo.value = core.ɵruntimeInfo;
498
+ });
499
+ // Consumers read runtime getters off `copilotkit` directly, so every
500
+ // status event invalidates them.
592
501
  const sub4 = core.subscribe({
593
502
  onRuntimeConnectionStatusChanged: () => {
594
- runtimeA2UIEnabled.value = core.a2uiEnabled;
595
- runtimeOpenGenerativeUIEnabled.value = core.openGenerativeUIEnabled;
596
- runtimeLicenseStatus.value = core.licenseStatus;
597
- runtimeEntitlements.value = core.runtimeEntitlements;
598
- runtimeEntitlementRetryPending.value =
599
- core.runtimeEntitlementRetryPending;
600
503
  triggerRef(copilotkit);
601
504
  },
602
505
  });
603
- const sub5 = core.subscribe({
604
- onError: (event) => {
605
- void props.onError?.({
606
- error: event.error,
607
- code: event.code,
608
- context: event.context,
609
- });
610
- },
611
- });
612
506
  // `onHeadersChanged` fires only from a real `setHeaders()` call (a new
613
507
  // source), never from a builder resolving a new token — same generation
614
508
  // core bumps. Without this, nothing pokes Vue's reactivity when a source
@@ -626,7 +520,7 @@ watch(
626
520
  sub2.unsubscribe();
627
521
  sub3.unsubscribe();
628
522
  sub4.unsubscribe();
629
- sub5.unsubscribe();
523
+ unsubscribeRuntimeInfo();
630
524
  sub6.unsubscribe();
631
525
  });
632
526
  },
@@ -646,48 +540,34 @@ watch([allRenderToolCalls], ([renderToolCalls]) => {
646
540
  watch([allRenderCustomMessages], ([renderCustomMessages]) => {
647
541
  if (!didMountRef.value) return;
648
542
  copilotkit.value.setRenderCustomMessages(renderCustomMessages);
649
- triggerRef(copilotkit);
650
543
  });
651
544
 
652
545
  watch([allRenderActivityMessages], ([renderActivityMessages]) => {
653
546
  if (!didMountRef.value) return;
654
547
  copilotkit.value.setRenderActivityMessages(renderActivityMessages);
655
- triggerRef(copilotkit);
656
548
  });
657
549
 
658
- // The last `headersSource` reference actually handed to `core.setHeaders`.
659
- // `syncRuntimeConfig` runs once (unconditionally) from `onMounted` in
660
- // addition to the constructor already having applied this same value.
661
- // `HeaderSourceResolver.setSource` itself is a no-op both for an identical
662
- // function reference and for a record whose normalized values equal the
663
- // currently applied record's (see #1937), so this reference
664
- // check is now a cheap pre-filter rather than the only thing preventing a
665
- // spurious `onHeadersChanged`. It still avoids the `setHeaders` call (and
666
- // its normalize + shallow-equal work) entirely on the common path where
667
- // nothing changed.
668
- let lastAppliedHeadersSource: CopilotKitHeadersSource = headersSource.value;
669
-
550
+ // Every setter is a no-op when its value did not change (`setHeaders` too, for
551
+ // the same builder or an equal record, see #1937), so this can pass every key.
670
552
  function syncRuntimeConfig() {
671
- copilotkit.value.setRuntimeUrl(chatApiEndpoint.value);
672
- copilotkit.value.setRuntimeTransport(
673
- props.useSingleEndpoint === true
674
- ? "single"
675
- : props.useSingleEndpoint === false
676
- ? "rest"
677
- : "auto",
678
- );
679
- if (headersSource.value !== lastAppliedHeadersSource) {
680
- lastAppliedHeadersSource = headersSource.value;
681
- copilotkit.value.setHeaders(headersSource.value);
682
- }
683
- copilotkit.value.setCredentials(props.credentials);
684
- copilotkit.value.setMessageFilter(props.messageFilter);
685
- copilotkit.value.setProperties(resolvedProperties.value);
686
- copilotkit.value.setAgents__unsafe_dev_only(mergedAgents.value);
687
- copilotkit.value.setDebug(props.debug);
688
- applyDefaultThrottleMs(copilotkit.value);
553
+ copilotkit.value.ɵupdateConfig({
554
+ messageFilter: props.messageFilter,
555
+ runtimeUrl: chatApiEndpoint.value,
556
+ runtimeTransport: runtimeTransport.value,
557
+ headers: headersSource.value,
558
+ credentials: props.credentials,
559
+ properties: resolvedProperties.value,
560
+ agents__unsafe_dev_only: mergedAgents.value,
561
+ debug: props.debug,
562
+ defaultThrottleMs: props.defaultThrottleMs,
563
+ });
689
564
  }
690
565
 
566
+ watch(
567
+ () => props.onError,
568
+ (onError) => copilotkit.value.setErrorHandler(onError),
569
+ );
570
+
691
571
  watch(
692
572
  [
693
573
  () => chatApiEndpoint.value,
@@ -696,7 +576,7 @@ watch(
696
576
  () => props.messageFilter,
697
577
  () => resolvedProperties.value,
698
578
  () => mergedAgents.value,
699
- () => props.useSingleEndpoint,
579
+ () => runtimeTransport.value,
700
580
  () => props.debug,
701
581
  ],
702
582
  () => {
@@ -707,111 +587,32 @@ watch(
707
587
 
708
588
  watch(
709
589
  () => props.defaultThrottleMs,
710
- () => {
590
+ (defaultThrottleMs) => {
711
591
  if (!didMountRef.value) return;
712
- applyDefaultThrottleMs(copilotkit.value);
592
+ copilotkit.value.ɵupdateConfig({ defaultThrottleMs });
713
593
  triggerRef(copilotkit);
714
594
  },
715
595
  );
716
596
 
717
597
  onMounted(() => {
718
598
  syncRuntimeConfig();
719
- runtimeA2UIEnabled.value = copilotkit.value.a2uiEnabled;
720
- runtimeOpenGenerativeUIEnabled.value =
721
- copilotkit.value.openGenerativeUIEnabled;
722
- runtimeLicenseStatus.value = copilotkit.value.licenseStatus;
723
- runtimeEntitlements.value = copilotkit.value.runtimeEntitlements;
724
- runtimeEntitlementRetryPending.value =
725
- copilotkit.value.runtimeEntitlementRetryPending;
599
+ // The constructor deferred `/info`; start it now that we are in the browser
600
+ // (`onMounted` never runs during SSR). Idempotent.
601
+ copilotkit.value.connect();
602
+ runtimeInfo.value = copilotkit.value.ɵruntimeInfo;
726
603
  didMountRef.value = true;
727
604
  // After the runtime URL is set, so CopilotKit's own runtime traffic is never
728
- // captured. Created here, the watchers stop (and stop capture) on unmount.
729
- watchLearning();
730
- });
731
-
732
- const learningEnabled = computed(() => learningConfig.value !== undefined);
733
- // `true` is the options-free form, so only an object can opt out.
734
- const learningAutoStart = computed(
735
- () =>
736
- learningEnabled.value &&
737
- (typeof props.learning !== "object" || props.learning.autoStart !== false),
738
- );
739
- const suppliedTrajectoryId = computed(() =>
740
- learningAutoStart.value ? learningConfig.value?.trajectoryId : undefined,
741
- );
742
- const generatesTrajectoryId = computed(
743
- () => learningAutoStart.value && suppliedTrajectoryId.value === undefined,
744
- );
745
-
746
- function watchLearning() {
747
- let learningContainerIds = learningConfig.value?.learningContainerIds;
748
-
749
- watch(
750
- [learningConfig, learningAutoStart],
751
- ([config, autoStart]) => {
752
- copilotkit.value.setLearningConfig(config);
753
- learningContainerIds = config?.learningContainerIds;
754
- // Automatic starts report unsupported options in Core. With manual
755
- // starts, the provider's container option is not part of
756
- // startTrajectory() options.
757
- if (
758
- config?.sink === undefined &&
759
- !autoStart &&
760
- config?.learningContainerIds !== undefined
761
- ) {
762
- console.warn(
763
- "[CopilotKit] learningContainerIds is supported only with a custom sink. Authenticated Trajectory capture ignores it; assign Learning Spaces on the server with getTrajectoryLearningContainerIds on CopilotKitIntelligence, and remove learningContainerIds from the capture options.",
764
- );
765
- }
766
- },
767
- { immediate: true },
768
- );
769
-
770
- // Watched as a boolean so a new inline `learning` object warns once.
605
+ // captured. The provider's onUnmounted disposes the starter (stops capture).
771
606
  watch(
772
- () =>
773
- !learningAutoStart.value &&
774
- learningConfig.value?.trajectoryId !== undefined,
775
- (ignoresTrajectoryId) => {
776
- if (!ignoresTrajectoryId) return;
777
- console.warn(
778
- "[CopilotKit] learning.trajectoryId is ignored when autoStart is false; pass the ID to startTrajectory() instead.",
779
- );
607
+ () => props.learning,
608
+ (learning) => learningStarter.update(learning),
609
+ {
610
+ immediate: true,
780
611
  },
781
- { immediate: true },
782
612
  );
613
+ });
783
614
 
784
- // Runs only when these change, so option changes that keep generating keep
785
- // the generated Trajectory; generating again starts one with a new ID.
786
- watch(
787
- [learningEnabled, generatesTrajectoryId, suppliedTrajectoryId],
788
- ([enabled, generates, supplied], _previous, onCleanup) => {
789
- if (!enabled) return;
790
- let disposed = false;
791
- const core = copilotkit.value;
792
- const trajectoryId = generates ? randomUUID() : supplied;
793
- if (trajectoryId !== undefined) {
794
- void core
795
- .startTrajectory({ trajectoryId, learningContainerIds })
796
- .catch(() => {
797
- // Expected authentication/connection failures resolve with an
798
- // error result; Core reports them to LearningConfig.onError or
799
- // warns once. Consume unexpected rejections without logging
800
- // credentials or errors from a previous start after a new
801
- // Trajectory has already started.
802
- if (!disposed) {
803
- console.warn("[CopilotKit] Failed to start interaction capture.");
804
- }
805
- });
806
- }
807
- onCleanup(() => {
808
- disposed = true;
809
- core.stopTrajectory();
810
- });
811
- },
812
- { immediate: true },
813
- );
814
- }
615
+ const learningStarter = new ɵLearningAutoStarter(copilotkit.value);
815
616
 
816
617
  const a2uiTheme = computed(() => props.a2ui?.theme);
817
618
  const a2uiCatalog = computed(() => props.a2ui?.catalog);
@@ -821,11 +622,15 @@ const a2uiIncludeSchema = computed(() => props.a2ui?.includeSchema ?? true);
821
622
  // A2UI tool call renderer (progress indicator) — auto-registered when A2UI enabled
822
623
  registerA2UIBuiltInToolCallRenderer(copilotkit, () => a2uiActive.value);
823
624
 
824
- // A2UI catalog context, schema, and generation/design guidelines
825
- registerA2UICatalogContext(copilotkit, {
625
+ // A2UI catalog: component registration for the Inspector, the filtered
626
+ // catalog, and the agent context (schema, generation/design guidelines).
627
+ registerA2UICatalog(copilotkit, {
826
628
  enabled: () => a2uiActive.value,
827
629
  catalog: () => props.a2ui?.catalog,
828
630
  includeSchema: () => props.a2ui?.includeSchema ?? true,
631
+ onFilteredCatalog: (catalog) => {
632
+ a2uiFilteredCatalog.value = catalog;
633
+ },
829
634
  });
830
635
 
831
636
  const providerContextIds = ref<string[]>([]);
@@ -838,31 +643,10 @@ watch(
838
643
  ([active, functions, designSkill], _previous, onCleanup) => {
839
644
  if (!active) return;
840
645
 
841
- const ids: string[] = [];
842
- ids.push(
843
- copilotkit.value.addContext({
844
- description:
845
- "Design guidelines for the generateSandboxedUi tool. Follow these when building UI.",
846
- value: designSkill ?? DEFAULT_OPEN_GENERATIVE_UI_DESIGN_SKILL,
847
- }),
848
- );
849
-
850
- if (functions.length > 0) {
851
- const descriptors = JSON.stringify(
852
- functions.map((fn) => ({
853
- name: fn.name,
854
- description: fn.description,
855
- parameters: schemaToJsonSchema(fn.parameters),
856
- })),
857
- );
858
- ids.push(
859
- copilotkit.value.addContext({
860
- description:
861
- "Sandbox functions available in generated sandboxed UI code. Call via Websandbox.connection.remote.<functionName>(args).",
862
- value: descriptors,
863
- }),
864
- );
865
- }
646
+ const ids = ɵbuildOpenGenerativeUIContexts({
647
+ designSkill,
648
+ sandboxFunctions: functions,
649
+ }).map((entry) => copilotkit.value.addContext(entry));
866
650
 
867
651
  providerContextIds.value = ids;
868
652
  onCleanup(() => {
@@ -903,6 +687,7 @@ const licenseBannerType = computed(() => licenseState.value.bannerType);
903
687
  // subscriptions. `onUnmounted` runs after the children unmount, so their
904
688
  // cleanup still reaches a live core.
905
689
  onUnmounted(() => {
690
+ learningStarter.dispose();
906
691
  copilotkit.value.dispose();
907
692
  });
908
693
  </script>
@@ -913,6 +698,7 @@ onUnmounted(() => {
913
698
  v-if="shouldRenderInspector"
914
699
  :core="copilotkit"
915
700
  :open-request="inspectorOpenRequest"
701
+ @visibility-change="inspectorVisible = $event"
916
702
  />
917
703
  <!-- License warnings — driven by server-reported status -->
918
704
  <LicenseWarningBanner v-if="licenseBannerType" :type="licenseBannerType" />