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

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-BAhbpSDh.js +16200 -0
  4. package/dist/use-render-activity-message-BAhbpSDh.js.map +1 -0
  5. package/dist/use-render-activity-message-DJ6q1qHV.cjs +114 -0
  6. package/dist/use-render-activity-message-DJ6q1qHV.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
@@ -119,6 +119,23 @@ describe("CopilotChatConfigurationProvider", () => {
119
119
  expect(wrapper.find("[data-testid=placeholder]").text()).toBe("Inner");
120
120
  });
121
121
 
122
+ it("a nested non-explicit seed yields to the parent's thread, like React", () => {
123
+ const Display = makeDisplay();
124
+ const wrapper = mount(CopilotChatConfigurationProvider, {
125
+ props: { threadId: "outer-thread" },
126
+ slots: {
127
+ default: () =>
128
+ h(
129
+ CopilotChatConfigurationProvider,
130
+ { threadId: "inner-seed", hasExplicitThreadId: false },
131
+ { default: () => h(Display) },
132
+ ),
133
+ },
134
+ });
135
+
136
+ expect(wrapper.find("[data-testid=thread]").text()).toBe("outer-thread");
137
+ });
138
+
122
139
  it("creates and mutates modal state when isModalDefaultOpen is provided", async () => {
123
140
  const Toggle = defineComponent({
124
141
  setup() {
@@ -398,9 +415,12 @@ describe("CopilotChatConfiguration drawer-awareness", () => {
398
415
  });
399
416
 
400
417
  describe("CopilotChatConfiguration modal-setter presence contract", () => {
401
- it("bare provider (no isModalDefaultOpen, no parent) exposes setModalOpen as undefined", () => {
418
+ it("bare provider (no isModalDefaultOpen, no parent) owns a modal that starts open, like React", async () => {
402
419
  const cfg = harness({ threadId: "thread-1" });
403
- expect(cfg().setModalOpen).toBeUndefined();
420
+ expect(cfg().isModalOpen).toBe(true);
421
+ cfg().setModalOpen?.(false);
422
+ await nextTick();
423
+ expect(cfg().isModalOpen).toBe(false);
404
424
  });
405
425
 
406
426
  it("provider with isModalDefaultOpen exposes a working setModalOpen", async () => {
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, it } from "vitest";
2
- import { defineComponent, h, ref } from "vue";
2
+ import { defineComponent, h, nextTick, ref } from "vue";
3
3
  import { mount } from "@vue/test-utils";
4
4
  import { z } from "zod-v3";
5
5
  import { Catalog } from "@a2ui/web_core/v0_9";
@@ -125,4 +125,22 @@ describe("CopilotKitProvider a2ui catalog context", () => {
125
125
  expect(value).toContain(" - FlightCard:\n {");
126
126
  expect(value).toContain('"airline"');
127
127
  });
128
+
129
+ it("registers the catalog's components with core for the Inspector", () => {
130
+ const { observedCore } = mountProvider({
131
+ a2ui: { catalog: makeCustomCatalog() },
132
+ });
133
+ expect(
134
+ observedCore.value?.catalogComponents.map((component) => component.name),
135
+ ).toEqual(["FlightCard"]);
136
+ });
137
+
138
+ it("stops advertising a component the Inspector disables", async () => {
139
+ const { observedCore } = mountProvider({
140
+ a2ui: { catalog: makeCustomCatalog() },
141
+ });
142
+ observedCore.value?.setCatalogComponentEnabled("FlightCard", false);
143
+ await nextTick();
144
+ expect(capabilitiesValue(observedCore.value)).not.toContain("FlightCard");
145
+ });
128
146
  });
@@ -0,0 +1,124 @@
1
+ import { afterEach, describe, expect, it, vi } from "vitest";
2
+ import { createSSRApp } from "vue";
3
+ import { mount } from "@vue/test-utils";
4
+ import { renderToString } from "vue/server-renderer";
5
+ import CopilotKitProvider from "../CopilotKitProvider.vue";
6
+
7
+ const RUNTIME_URL = "https://runtime.example/api/copilotkit";
8
+ const SHAPE_WARNING =
9
+ "renderToolCalls must be a stable array. If you want to dynamically add or remove tools, use `useFrontendTool` instead.";
10
+
11
+ function stubInfoFetch() {
12
+ const fetchMock = vi.fn(async () => {
13
+ throw new Error("network failure");
14
+ });
15
+ vi.stubGlobal("fetch", fetchMock);
16
+ return () =>
17
+ fetchMock.mock.calls.filter(([url]) => String(url).includes("/info"));
18
+ }
19
+
20
+ /** A tool call renderer shape: only `name` and `agentId` matter here. */
21
+ function renderer(name: string) {
22
+ return { name, args: undefined, render: () => null };
23
+ }
24
+
25
+ afterEach(() => {
26
+ vi.unstubAllGlobals();
27
+ vi.restoreAllMocks();
28
+ });
29
+
30
+ describe("CopilotKitProvider (Vue) runtime connection", () => {
31
+ it("does not fetch /info during server-side rendering", async () => {
32
+ const infoCalls = stubInfoFetch();
33
+ await renderToString(
34
+ createSSRApp(CopilotKitProvider, { runtimeUrl: RUNTIME_URL }),
35
+ );
36
+ await new Promise((resolve) => setTimeout(resolve, 20));
37
+ expect(infoCalls()).toHaveLength(0);
38
+ });
39
+
40
+ it("fetches /info once the provider mounts", async () => {
41
+ vi.spyOn(console, "error").mockImplementation(() => {});
42
+ const infoCalls = stubInfoFetch();
43
+ const wrapper = mount(CopilotKitProvider, {
44
+ props: { runtimeUrl: RUNTIME_URL },
45
+ });
46
+ await vi.waitFor(() => expect(infoCalls().length).toBeGreaterThan(0));
47
+ wrapper.unmount();
48
+ });
49
+ });
50
+
51
+ describe("CopilotKitProvider (Vue) errors", () => {
52
+ it("logs core errors when no onError is given", async () => {
53
+ stubInfoFetch();
54
+ const error = vi.spyOn(console, "error").mockImplementation(() => {});
55
+ const wrapper = mount(CopilotKitProvider, {
56
+ props: { runtimeUrl: RUNTIME_URL },
57
+ });
58
+ await vi.waitFor(() =>
59
+ expect(error).toHaveBeenCalledWith(
60
+ "[CopilotKit] Error (runtime_info_fetch_failed):",
61
+ expect.any(Error),
62
+ expect.anything(),
63
+ ),
64
+ );
65
+ wrapper.unmount();
66
+ });
67
+
68
+ it("reports an invalid defaultThrottleMs once, from core", () => {
69
+ const error = vi.spyOn(console, "error").mockImplementation(() => {});
70
+ const wrapper = mount(CopilotKitProvider, {
71
+ props: { runtimeUrl: RUNTIME_URL, defaultThrottleMs: -1 },
72
+ });
73
+ const providerCopies = error.mock.calls.filter(
74
+ ([message]) =>
75
+ typeof message === "string" &&
76
+ message.startsWith("CopilotKitProvider: defaultThrottleMs"),
77
+ );
78
+ const coreReports = error.mock.calls.filter(
79
+ ([message]) =>
80
+ typeof message === "string" &&
81
+ message.startsWith("CopilotKitCore.setDefaultThrottleMs"),
82
+ );
83
+ expect(providerCopies).toEqual([]);
84
+ expect(coreReports.length).toBeGreaterThan(0);
85
+ wrapper.unmount();
86
+ });
87
+ });
88
+
89
+ describe("CopilotKitProvider (Vue) renderToolCalls warning", () => {
90
+ it("warns when the renderToolCalls shape changes", async () => {
91
+ const error = vi.spyOn(console, "error").mockImplementation(() => {});
92
+ const wrapper = mount(CopilotKitProvider, {
93
+ props: { runtimeUrl: RUNTIME_URL, renderToolCalls: [renderer("a")] },
94
+ });
95
+ await wrapper.setProps({ renderToolCalls: [renderer("b")] });
96
+ expect(error).toHaveBeenCalledWith(SHAPE_WARNING);
97
+ wrapper.unmount();
98
+ });
99
+
100
+ it("does not warn for a new array with the same tools", async () => {
101
+ const error = vi.spyOn(console, "error").mockImplementation(() => {});
102
+ const wrapper = mount(CopilotKitProvider, {
103
+ props: { runtimeUrl: RUNTIME_URL, renderToolCalls: [renderer("a")] },
104
+ });
105
+ await wrapper.setProps({ renderToolCalls: [renderer("a")] });
106
+ expect(error).not.toHaveBeenCalledWith(SHAPE_WARNING);
107
+ wrapper.unmount();
108
+ });
109
+ });
110
+
111
+ describe("CopilotKitProvider (Vue) config diagnostics", () => {
112
+ it("warns about a missing runtime config once", async () => {
113
+ const warn = vi.spyOn(console, "warn").mockImplementation(() => {});
114
+ const wrapper = mount(CopilotKitProvider, { props: {} });
115
+ await wrapper.setProps({ properties: { tenant: "acme" } });
116
+ const missing = warn.mock.calls.filter(
117
+ ([message]) =>
118
+ message ===
119
+ "Missing required prop: 'runtimeUrl' or 'publicApiKey' or 'publicLicenseKey'",
120
+ );
121
+ expect(missing).toHaveLength(1);
122
+ wrapper.unmount();
123
+ });
124
+ });
@@ -79,7 +79,10 @@ describe("CopilotKitProvider sandbox functions", () => {
79
79
  },
80
80
  });
81
81
  const sandboxContext = findSandboxContext(observedCore.value!.context);
82
- expect(sandboxContext).toBeDefined();
82
+ // The same model-visible call form React and Angular send.
83
+ expect(sandboxContext?.description).toBe(
84
+ "Sandbox functions available in generated sandboxed UI code. Call via: await Websandbox.connection.remote.<functionName>(args)",
85
+ );
83
86
  });
84
87
 
85
88
  it("does not register agent context when sandbox functions are empty", () => {
@@ -5,11 +5,12 @@ import {
5
5
  createSSRApp,
6
6
  defineComponent,
7
7
  h,
8
+ inject,
8
9
  nextTick,
9
10
  ref,
10
11
  watchEffect,
11
12
  } from "vue";
12
- import type { VNode } from "vue";
13
+ import type { ComputedRef, VNode } from "vue";
13
14
  import { renderToString } from "vue/server-renderer";
14
15
  import type {
15
16
  CopilotKitCoreSubscriber,
@@ -23,6 +24,7 @@ import { defineWebInspector } from "@copilotkit/web-inspector";
23
24
  import { z } from "zod";
24
25
  import CopilotKitProvider from "../CopilotKitProvider.vue";
25
26
  import { useCopilotKit } from "../useCopilotKit";
27
+ import { InspectorKey } from "../keys";
26
28
  import type { VueFrontendTool } from "../../types";
27
29
  import type { VueHumanInTheLoop } from "../../types";
28
30
  import { mountWithProvider } from "../../__tests__/utils/mount";
@@ -838,7 +840,7 @@ describe("CopilotKitProvider", () => {
838
840
  vi.stubEnv("NODE_ENV", "development");
839
841
  });
840
842
 
841
- it("renders by default on any development host and passes the provider core before connection", async () => {
843
+ it("renders by default on a loopback development host and passes the provider core before connection", async () => {
842
844
  let providerCore: CopilotKitCoreContextValue | null = null;
843
845
  const Probe = defineComponent({
844
846
  setup() {
@@ -872,6 +874,47 @@ describe("CopilotKitProvider", () => {
872
874
  view.unmount();
873
875
  });
874
876
 
877
+ it("never renders or loads on a remote development host, even when explicitly enabled", async () => {
878
+ vi.stubGlobal("location", new URL("http://192.168.1.25:3000"));
879
+ const view = render(CopilotKitProvider, {
880
+ props: { runtimeUrl: "/api/copilotkit", enableInspector: true },
881
+ slots: { default: "child" },
882
+ });
883
+
884
+ await settleInspectorLoad();
885
+ expect(view.container.querySelector("cpk-web-inspector")).toBeNull();
886
+ expect(defineWebInspector).not.toHaveBeenCalled();
887
+ view.unmount();
888
+ });
889
+
890
+ it("enables Inspector message actions only while the Inspector is shown", async () => {
891
+ let isInspectorEnabled: ComputedRef<boolean> | undefined;
892
+ const Probe = defineComponent({
893
+ setup() {
894
+ isInspectorEnabled = inject(InspectorKey)?.isInspectorEnabled;
895
+ return () => null;
896
+ },
897
+ });
898
+ const view = render(CopilotKitProvider, {
899
+ props: { runtimeUrl: "/api/copilotkit" },
900
+ slots: { default: Probe },
901
+ });
902
+
903
+ await waitFor(() => {
904
+ expect(isInspectorEnabled?.value).toBe(true);
905
+ });
906
+ const inspector = view.container.querySelector("cpk-web-inspector")!;
907
+ inspector.dispatchEvent(
908
+ new CustomEvent("cpk-inspector-visibility-change", {
909
+ detail: { visible: false },
910
+ }),
911
+ );
912
+ await nextTick();
913
+ expect(isInspectorEnabled?.value).toBe(false);
914
+ expect(inspector.isConnected).toBe(true);
915
+ view.unmount();
916
+ });
917
+
875
918
  it("does not render or load when explicitly disabled in development", async () => {
876
919
  const view = render(CopilotKitProvider, {
877
920
  props: {
@@ -0,0 +1,9 @@
1
+ import type { InjectionKey } from "vue";
2
+ import type { ɵChatConfigurationStore } from "@copilotkit/core";
3
+
4
+ /**
5
+ * The nearest `CopilotChatConfigurationProvider`'s core store, so a nested
6
+ * provider can link its own store to it.
7
+ */
8
+ export const ChatConfigurationStoreKey: InjectionKey<ɵChatConfigurationStore> =
9
+ Symbol("CopilotChatConfigurationStore");
@@ -1,6 +1,10 @@
1
1
  import { inject } from "vue";
2
2
  import type { Component, InjectionKey } from "vue";
3
- import type { VueStreamingMarkdownNodeRenderers } from "@copilotkit/markdown/vue";
3
+ import type {
4
+ VueStreamingMarkdownCitationClickHandler,
5
+ VueStreamingMarkdownLinkClickHandler,
6
+ VueStreamingMarkdownNodeRenderers,
7
+ } from "@copilotkit/markdown/vue";
4
8
  import type { StreamingMarkdownParserOptions } from "@copilotkit/markdown";
5
9
 
6
10
  /** Config for the built-in Vue default renderer (pass instead of a component). */
@@ -9,6 +13,8 @@ export interface DefaultMarkdownRendererProps {
9
13
  caret?: boolean;
10
14
  options?: Partial<StreamingMarkdownParserOptions>;
11
15
  class?: string;
16
+ onLinkClick?: VueStreamingMarkdownLinkClickHandler;
17
+ onCitationClick?: VueStreamingMarkdownCitationClickHandler;
12
18
  }
13
19
 
14
20
  export type MarkdownRendererValue = Component | DefaultMarkdownRendererProps;
@@ -1,20 +1,12 @@
1
- import { computed, onBeforeUnmount, ref, watch } from "vue";
1
+ import { computed, onBeforeUnmount, shallowRef, watch } from "vue";
2
2
  import type { Ref } from "vue";
3
- import {
4
- emitInspectorActiveThread,
5
- emitInspectorViewThreadResult,
6
- isInspectorThreadBridgeEnabled,
7
- onInspectorStopViewing,
8
- onInspectorViewThread,
9
- } from "@copilotkit/core";
10
-
11
- type InspectorOverride = {
12
- requestId: string;
13
- threadId: string;
14
- agentId: string;
15
- previousThreadId: string;
16
- };
3
+ import { ɵInspectorThreadOverride } from "@copilotkit/core";
17
4
 
5
+ /**
6
+ * Apply the Inspector's "view this thread" requests to a chat. Core's
7
+ * `ɵInspectorThreadOverride` owns the state machine; this composable binds it
8
+ * to the component's lifetime and Vue reactivity.
9
+ */
18
10
  export function useInspectorThreadOverride(args: {
19
11
  agentId: Ref<string>;
20
12
  baseThreadId: Ref<string>;
@@ -23,77 +15,27 @@ export function useInspectorThreadOverride(args: {
23
15
  inspectorRequestId: Ref<string | null>;
24
16
  failInspectorOverride: (requestId: string) => void;
25
17
  } {
26
- const override = ref<InspectorOverride | null>(null);
27
-
28
- const restoreOverride = (
29
- current: InspectorOverride,
30
- nextThreadId: string,
31
- ) => {
32
- override.value = null;
33
- emitInspectorActiveThread({
34
- requestId: current.requestId,
35
- threadId: nextThreadId,
36
- agentId: current.agentId,
37
- source: "app",
38
- });
39
- };
40
-
41
- const failInspectorOverride = (requestId: string) => {
42
- const current = override.value;
43
- if (!current || current.requestId !== requestId) return;
44
- emitInspectorViewThreadResult({
45
- requestId,
46
- threadId: current.threadId,
47
- agentId: current.agentId,
48
- ok: false,
49
- reason: "connect-failed",
50
- });
51
- restoreOverride(current, current.previousThreadId);
52
- };
53
-
54
- if (isInspectorThreadBridgeEnabled()) {
55
- const offView = onInspectorViewThread((payload) => {
56
- if (payload.agentId !== args.agentId.value) return false;
57
- override.value = override.value
58
- ? { ...override.value, ...payload }
59
- : {
60
- ...payload,
61
- previousThreadId: args.baseThreadId.value,
62
- };
63
- emitInspectorViewThreadResult({ ...payload, ok: true });
64
- emitInspectorActiveThread({ ...payload, source: "override" });
65
- return true;
66
- });
67
-
68
- const offStop = onInspectorStopViewing((payload) => {
69
- const current = override.value;
70
- if (!current) return;
71
- if (payload.requestId !== current.requestId) return;
72
- if (payload.agentId !== current.agentId) return;
73
- restoreOverride(current, current.previousThreadId);
74
- });
75
-
76
- onBeforeUnmount(() => {
77
- offView();
78
- offStop();
79
- });
80
- }
18
+ const controller = new ɵInspectorThreadOverride({
19
+ agentId: args.agentId.value,
20
+ baseThreadId: args.baseThreadId.value,
21
+ });
22
+ const override = shallowRef(controller.getSnapshot());
23
+ const unsubscribe = controller.subscribe(() => {
24
+ override.value = controller.getSnapshot();
25
+ });
81
26
 
82
27
  watch([args.agentId, args.baseThreadId], ([agentId, baseThreadId]) => {
83
- const current = override.value;
84
- if (!current) return;
85
- if (agentId !== current.agentId) {
86
- restoreOverride(current, current.previousThreadId);
87
- return;
88
- }
89
- if (baseThreadId === current.previousThreadId) return;
90
- if (baseThreadId === current.threadId) return;
91
- restoreOverride(current, baseThreadId);
28
+ controller.update({ agentId, baseThreadId });
29
+ });
30
+
31
+ onBeforeUnmount(() => {
32
+ unsubscribe();
33
+ controller.dispose();
92
34
  });
93
35
 
94
36
  return {
95
37
  inspectorThreadId: computed(() => override.value?.threadId ?? null),
96
38
  inspectorRequestId: computed(() => override.value?.requestId ?? null),
97
- failInspectorOverride,
39
+ failInspectorOverride: controller.fail,
98
40
  };
99
41
  }
package/vite.config.ts CHANGED
@@ -30,6 +30,9 @@ export default defineConfig({
30
30
  "@ag-ui/core",
31
31
  // The framework-neutral A2UI catalog description subpath (no React).
32
32
  "@copilotkit/a2ui-renderer/catalog-schema",
33
+ // The framework-neutral A2UI engine subpath (no React).
34
+ "@copilotkit/a2ui-renderer/engine",
35
+ "@copilotkit/a2ui-renderer/engine-core",
33
36
  // Core and its `/styles` subpath, so the stylesheet isn't bundled here.
34
37
  /^@copilotkit\/core(\/.*)?$/,
35
38
  // Keep the shared MCP Apps host + its subpaths external. The root entry
@@ -40,7 +43,8 @@ export default defineConfig({
40
43
  // statically for activity registration.
41
44
  /^@copilotkit\/mcp-apps-renderer(\/.*)?$/,
42
45
  "@copilotkit/shared",
43
- "@copilotkit/web-inspector",
46
+ // The Inspector and its `/mount` subpath stay runtime imports.
47
+ /^@copilotkit\/web-inspector(\/.*)?$/,
44
48
  // Keep @copilotkit/web-components (the Lit drawer element) + its subpaths
45
49
  // external. It's a runtime dependency loaded via the drawer wrapper's
46
50
  // client-only dynamic import; bundling it inline would ship a duplicate
package/vitest.config.ts CHANGED
@@ -12,12 +12,17 @@ export default defineConfig({
12
12
  reporters: [["default", { summary: false }]],
13
13
  },
14
14
  resolve: {
15
- alias: {
16
- "@": resolve(__dirname, "./src"),
17
- "@copilotkit/web-inspector": resolve(
18
- __dirname,
19
- "./src/v2/__tests__/mocks/web-inspector.ts",
20
- ),
21
- },
15
+ // Exact match, so the real `@copilotkit/web-inspector/mount` subpath
16
+ // still resolves while the Inspector bundle itself is mocked.
17
+ alias: [
18
+ { find: "@", replacement: resolve(__dirname, "./src") },
19
+ {
20
+ find: /^@copilotkit\/web-inspector$/,
21
+ replacement: resolve(
22
+ __dirname,
23
+ "./src/v2/__tests__/mocks/web-inspector.ts",
24
+ ),
25
+ },
26
+ ],
22
27
  },
23
28
  });