@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,7 +1,7 @@
1
1
  import { computed, onScopeDispose, shallowRef, watch } from "vue";
2
2
  import type { ComputedRef, Ref } from "vue";
3
- import { buildResumeArray, isInterruptExpired } from "@ag-ui/client";
4
- import type { Interrupt, RunAgentResult } from "@ag-ui/client";
3
+ import type { Interrupt } from "@ag-ui/client";
4
+ import { ɵInterruptController } from "@copilotkit/core";
5
5
  import { useCopilotKit } from "../providers/useCopilotKit";
6
6
  import { useAgent } from "./use-agent";
7
7
  import type {
@@ -19,21 +19,6 @@ export type {
19
19
  Interrupt,
20
20
  };
21
21
 
22
- const INTERRUPT_EVENT_NAME = "on_interrupt";
23
-
24
- /** Internal accumulator response shape consumed by buildResumeArray. */
25
- type ResumeResponse =
26
- | { status: "resolved"; payload?: unknown }
27
- | { status: "cancelled" };
28
-
29
- /**
30
- * Normalized pending interrupt. `legacy` carries the custom-event payload;
31
- * `standard` carries the AG-UI `outcome:"interrupt"` interrupts array.
32
- */
33
- type PendingInterrupt =
34
- | { kind: "legacy"; event: InterruptEvent }
35
- | { kind: "standard"; interrupts: Interrupt[] };
36
-
37
22
  type InterruptHandlerFn<TValue, TResult> = (
38
23
  props: InterruptHandlerProps<TValue>,
39
24
  ) => TResult | PromiseLike<TResult>;
@@ -75,38 +60,6 @@ export interface UseInterruptResult<TValue = unknown, TResult = never> {
75
60
  > | null>;
76
61
  }
77
62
 
78
- export function isPromiseLike<TValue>(
79
- value: TValue | PromiseLike<TValue>,
80
- ): value is PromiseLike<TValue> {
81
- return (
82
- (typeof value === "object" || typeof value === "function") &&
83
- value !== null &&
84
- typeof Reflect.get(value, "then") === "function"
85
- );
86
- }
87
-
88
- function normalizeAsyncResult<TValue>(
89
- value: PromiseLike<TValue>,
90
- ): Promise<TValue> {
91
- if (value instanceof Promise) {
92
- return value;
93
- }
94
-
95
- return new Promise<TValue>((resolve, reject) => {
96
- try {
97
- value.then(resolve, reject);
98
- } catch (error) {
99
- reject(error);
100
- }
101
- });
102
- }
103
-
104
- /** Derive the legacy-compatible `event` for any pending interrupt. */
105
- function toLegacyEvent(pending: PendingInterrupt): InterruptEvent {
106
- if (pending.kind === "legacy") return pending.event;
107
- return { name: INTERRUPT_EVENT_NAME, value: pending.interrupts[0] };
108
- }
109
-
110
63
  /**
111
64
  * Vue composable for handling agent interrupts with optional filtering,
112
65
  * preprocessing, and resume behavior.
@@ -131,262 +84,33 @@ export function useInterrupt<TValue = unknown, TResult = never>(
131
84
  ): UseInterruptResult<TValue, TResult> {
132
85
  const { copilotkit } = useCopilotKit();
133
86
  const { agent } = useAgent({ agentId: config.agentId });
134
- const pending = shallowRef<PendingInterrupt | null>(null);
135
- const result = shallowRef<InterruptResult<TValue, TResult>>(null);
136
-
137
- // Accumulated per-interrupt responses for the current standard interrupt set.
138
- const responses: Record<string, ResumeResponse> = {};
139
-
140
- watch(
141
- agent,
142
- (resolvedAgent, _previousAgent, onCleanup) => {
143
- if (!resolvedAgent) {
144
- pending.value = null;
145
- result.value = null;
146
- return;
147
- }
148
87
 
149
- let localLegacy: InterruptEvent<TValue> | null = null;
150
- let localStandard: Interrupt[] | null = null;
151
-
152
- const subscription = resolvedAgent.subscribe({
153
- onCustomEvent: ({ event }) => {
154
- if (event.name === INTERRUPT_EVENT_NAME) {
155
- localLegacy = {
156
- name: event.name,
157
- value: event.value as TValue,
158
- };
159
- }
160
- },
161
- onRunFinishedEvent: (params) => {
162
- if (params.outcome === "interrupt") {
163
- localStandard = params.interrupts;
164
- }
165
- },
166
- onRunStartedEvent: () => {
167
- localLegacy = null;
168
- localStandard = null;
169
- // Reset accumulated responses for the new run.
170
- for (const k of Object.keys(responses)) {
171
- delete responses[k];
172
- }
173
- pending.value = null;
174
- },
175
- onRunFinalized: () => {
176
- // Standard wins if both somehow appear for one run.
177
- if (localStandard && localStandard.length > 0) {
178
- pending.value = { kind: "standard", interrupts: localStandard };
179
- } else if (localLegacy) {
180
- pending.value = { kind: "legacy", event: localLegacy };
181
- }
182
- localLegacy = null;
183
- localStandard = null;
184
- },
185
- onRunFailed: () => {
186
- localLegacy = null;
187
- localStandard = null;
188
- for (const k of Object.keys(responses)) {
189
- delete responses[k];
190
- }
191
- pending.value = null;
192
- },
193
- });
194
-
195
- onCleanup(() => subscription.unsubscribe());
88
+ const controller = new ɵInterruptController<
89
+ TValue,
90
+ InterruptResult<TValue, TResult>
91
+ >(
92
+ { runAgent: (params) => copilotkit.value.runAgent(params) },
93
+ {
94
+ enabled: (event) => config.enabled?.(event) ?? true,
95
+ handler: (props) => (config.handler ? config.handler(props) : null),
196
96
  },
197
- { immediate: true },
198
97
  );
199
-
200
- /** Submit the accumulated standard responses once all open interrupts are addressed. */
201
- const submitStandardIfComplete = async (
202
- interrupts: Interrupt[],
203
- ): Promise<RunAgentResult | void> => {
204
- const allAddressed = interrupts.every((i) => responses[i.id]);
205
- if (!allAddressed) return;
206
-
207
- const expired = interrupts.find((i) => isInterruptExpired(i));
208
- if (expired) {
209
- console.error(
210
- `[CopilotKit] useInterrupt: interrupt ${expired.id} expired at ${expired.expiresAt}; not resuming.`,
211
- );
212
- for (const k of Object.keys(responses)) {
213
- delete responses[k];
214
- }
215
- pending.value = null;
216
- return;
217
- }
218
-
219
- const resume = buildResumeArray(interrupts, responses);
220
- for (const k of Object.keys(responses)) {
221
- delete responses[k];
222
- }
223
- const resolvedAgent = agent.value;
224
- if (!resolvedAgent) return;
225
- try {
226
- return await copilotkit.value.runAgent({ agent: resolvedAgent, resume });
227
- } catch (err) {
228
- console.error(
229
- "[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing",
230
- err,
231
- );
232
- pending.value = null;
233
- throw err;
234
- }
235
- };
236
-
237
- const resolve: InterruptResolveFn = async (payload?, interruptId?) => {
238
- const current = pending.value;
239
- if (!current) return;
240
-
241
- const resolvedAgent = agent.value;
242
- if (!resolvedAgent) return;
243
-
244
- if (current.kind === "legacy") {
245
- const interruptEventValue = current.event.value;
246
- try {
247
- return await copilotkit.value.runAgent({
248
- agent: resolvedAgent,
249
- forwardedProps: {
250
- command: {
251
- resume: payload,
252
- interruptEvent: interruptEventValue,
253
- },
254
- },
255
- });
256
- } catch (err) {
257
- console.error(
258
- "[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing",
259
- err,
260
- );
261
- pending.value = null;
262
- throw err;
263
- }
264
- }
265
-
266
- if (current.interrupts.length > 1 && interruptId === undefined) {
267
- console.warn(
268
- `[CopilotKit] useInterrupt: resolve()/cancel() called without an interruptId while ${current.interrupts.length} interrupts are open; defaulting to the first. Pass an interruptId to address a specific interrupt.`,
269
- );
270
- }
271
- const id = interruptId ?? current.interrupts[0]?.id;
272
- if (!id) return;
273
- responses[id] = { status: "resolved", payload };
274
- return submitStandardIfComplete(current.interrupts);
275
- };
276
-
277
- const cancel: InterruptCancelFn = async (interruptId?) => {
278
- const current = pending.value;
279
- if (!current) return;
280
-
281
- if (current.kind === "legacy") {
282
- // Legacy interrupts have no cancel semantics; dismiss without resuming.
283
- console.warn(
284
- "[CopilotKit] useInterrupt: cancel() is not supported for legacy on_interrupt interrupts; dismissing.",
285
- );
286
- pending.value = null;
287
- return;
288
- }
289
-
290
- if (current.interrupts.length > 1 && interruptId === undefined) {
291
- console.warn(
292
- `[CopilotKit] useInterrupt: resolve()/cancel() called without an interruptId while ${current.interrupts.length} interrupts are open; defaulting to the first. Pass an interruptId to address a specific interrupt.`,
293
- );
294
- }
295
- const id = interruptId ?? current.interrupts[0]?.id;
296
- if (!id) return;
297
- responses[id] = { status: "cancelled" };
298
- return submitStandardIfComplete(current.interrupts);
299
- };
300
-
301
- // Keep resolveInterrupt and cancelInterrupt as aliases for back-compat.
302
- const resolveInterrupt: InterruptResolveFn = resolve;
303
- const cancelInterrupt: InterruptCancelFn = cancel;
98
+ const snapshot = shallowRef(controller.getSnapshot());
99
+ controller.subscribe(() => {
100
+ snapshot.value = controller.getSnapshot();
101
+ });
304
102
 
305
103
  watch(
306
- pending,
307
- (currentPending, _previous, onCleanup) => {
308
- if (!currentPending) {
309
- result.value = null;
310
- return;
311
- }
312
- const legacyEvent = toLegacyEvent(
313
- currentPending,
314
- ) as InterruptEvent<TValue>;
315
- if (config.enabled && !config.enabled(legacyEvent)) {
316
- result.value = null;
317
- return;
318
- }
319
- const handler = config.handler;
320
- if (!handler) {
321
- result.value = null;
322
- return;
323
- }
324
-
325
- let cancelled = false;
326
- const maybePromise = handler({
327
- event: legacyEvent,
328
- interrupt:
329
- currentPending.kind === "standard"
330
- ? (currentPending.interrupts[0] ?? null)
331
- : null,
332
- interrupts:
333
- currentPending.kind === "standard" ? currentPending.interrupts : [],
334
- resolve,
335
- cancel,
336
- });
337
-
338
- if (isPromiseLike(maybePromise)) {
339
- normalizeAsyncResult(maybePromise)
340
- .then((resolved) => {
341
- if (!cancelled) {
342
- result.value = resolved;
343
- }
344
- })
345
- .catch((err) => {
346
- if (!cancelled) {
347
- console.error("[CopilotKit] useInterrupt handler failed:", err);
348
- result.value = null;
349
- }
350
- });
351
- } else {
352
- result.value = maybePromise;
353
- }
354
-
355
- onCleanup(() => {
356
- cancelled = true;
357
- });
104
+ agent,
105
+ (resolvedAgent) => {
106
+ if (resolvedAgent) controller.connect(resolvedAgent);
107
+ else controller.disconnect();
358
108
  },
359
109
  { immediate: true },
360
110
  );
361
111
 
362
- // Compute the legacy-compat "interrupt" ref for existing consumers (InterruptEvent shape).
363
- const interrupt = computed<InterruptEvent<TValue> | null>(() => {
364
- if (!pending.value) return null;
365
- return toLegacyEvent(pending.value) as InterruptEvent<TValue>;
366
- });
367
-
368
- const slotProps = computed<InterruptRenderProps<
369
- TValue,
370
- InterruptResult<TValue, TResult>
371
- > | null>(() => {
372
- const currentPending = pending.value;
373
- if (!currentPending) return null;
374
- const legacyEvent = toLegacyEvent(currentPending) as InterruptEvent<TValue>;
375
- if (config.enabled && !config.enabled(legacyEvent)) return null;
376
-
377
- return {
378
- event: legacyEvent,
379
- interrupt:
380
- currentPending.kind === "standard"
381
- ? (currentPending.interrupts[0] ?? null)
382
- : null,
383
- interrupts:
384
- currentPending.kind === "standard" ? currentPending.interrupts : [],
385
- result: result.value,
386
- resolve,
387
- cancel,
388
- };
389
- });
112
+ const { resolve, cancel } = controller;
113
+ const slotProps = computed(() => snapshot.value.renderProps);
390
114
 
391
115
  watch(
392
116
  [() => copilotkit.value, slotProps, () => config.renderInChat !== false],
@@ -395,10 +119,7 @@ export function useInterrupt<TValue = unknown, TResult = never>(
395
119
  return;
396
120
  }
397
121
 
398
- core.setInterruptState(
399
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
400
- nextSlotProps as InterruptRenderProps<any, any> | null,
401
- );
122
+ core.setInterruptState(nextSlotProps);
402
123
  const publishedState = nextSlotProps;
403
124
 
404
125
  onCleanup(() => {
@@ -420,17 +141,17 @@ export function useInterrupt<TValue = unknown, TResult = never>(
420
141
  }
421
142
  });
422
143
 
144
+ onScopeDispose(() => controller.dispose());
145
+
423
146
  return {
424
- interrupt: interrupt as unknown as Ref<InterruptEvent<TValue> | null>,
425
- result: result as Ref<InterruptResult<TValue, TResult>>,
147
+ interrupt: computed(() => slotProps.value?.event ?? null),
148
+ result: computed(() => snapshot.value.result),
426
149
  hasInterrupt: computed(() => slotProps.value !== null),
427
150
  resolve,
428
- resolveInterrupt,
151
+ // Aliases kept for back-compat.
152
+ resolveInterrupt: resolve,
429
153
  cancel,
430
- cancelInterrupt,
431
- slotProps: slotProps as ComputedRef<InterruptRenderProps<
432
- TValue,
433
- InterruptResult<TValue, TResult>
434
- > | null>,
154
+ cancelInterrupt: cancel,
155
+ slotProps,
435
156
  };
436
157
  }
@@ -1,7 +1,11 @@
1
1
  import { computed } from "vue";
2
2
  import type { Component } from "vue";
3
3
  import type { ActivityMessage } from "@ag-ui/core";
4
- import { ɵresolveActivityRenderer } from "@copilotkit/core";
4
+ import {
5
+ ɵdescribeActivityRendererFailure,
6
+ ɵfindActivityRenderer,
7
+ ɵmatchActivityRenderer,
8
+ } from "@copilotkit/core";
5
9
  import { DEFAULT_AGENT_ID } from "@copilotkit/shared";
6
10
  import { useCopilotKit } from "../providers/useCopilotKit";
7
11
  import { useCopilotChatConfiguration } from "../providers/useCopilotChatConfiguration";
@@ -22,21 +26,14 @@ export function useRenderActivityMessage() {
22
26
  const agentId = computed(() => config.value?.agentId ?? DEFAULT_AGENT_ID);
23
27
 
24
28
  function findRenderer(activityType: string) {
25
- const renderers = copilotkit.value.renderActivityMessages;
26
- const matches = renderers.filter(
27
- (renderer) => renderer.activityType === activityType,
28
- );
29
-
30
- return (
31
- matches.find((candidate) => candidate.agentId === agentId.value) ??
32
- matches.find((candidate) => candidate.agentId === undefined) ??
33
- renderers.find((candidate) => candidate.activityType === "*") ??
34
- null
35
- );
29
+ return ɵfindActivityRenderer(copilotkit.value.renderActivityMessages, {
30
+ activityType,
31
+ agentId: agentId.value,
32
+ });
36
33
  }
37
34
 
38
35
  function renderActivityMessage(message: ActivityMessage) {
39
- const match = ɵresolveActivityRenderer(
36
+ const match = ɵmatchActivityRenderer(
40
37
  copilotkit.value.renderActivityMessages,
41
38
  {
42
39
  activityType: message.activityType,
@@ -45,13 +42,13 @@ export function useRenderActivityMessage() {
45
42
  },
46
43
  );
47
44
 
48
- if (!match) {
49
- if (findRenderer(message.activityType)) {
50
- console.warn(
51
- `Failed to validate content for activity message ` +
52
- `'${message.activityType}'.`,
53
- );
54
- }
45
+ if (!match.ok) {
46
+ // Explain why a message that has a renderer drew nothing.
47
+ const warning = ɵdescribeActivityRendererFailure(
48
+ message.activityType,
49
+ match,
50
+ );
51
+ if (warning) console.warn(warning.message, ...warning.details);
55
52
  return null;
56
53
  }
57
54
 
@@ -1,6 +1,8 @@
1
1
  import type { Message } from "@ag-ui/core";
2
- import { ɵresolveCustomMessageRenderers } from "@copilotkit/core";
3
- import { DEFAULT_AGENT_ID } from "@copilotkit/shared";
2
+ import {
3
+ ɵgetCustomMessageRenderProps,
4
+ ɵresolveCustomMessageRenderContext,
5
+ } from "@copilotkit/core";
4
6
  import { useCopilotKit } from "../providers/useCopilotKit";
5
7
  import { useCopilotChatConfiguration } from "../providers/useCopilotChatConfiguration";
6
8
  import type {
@@ -34,74 +36,29 @@ export function useRenderCustomMessages() {
34
36
  const configValue = config.value;
35
37
  if (!configValue) return null;
36
38
 
37
- const agentId = configValue.agentId || DEFAULT_AGENT_ID;
38
- const { threadId } = configValue;
39
39
  const core = copilotkit.value;
40
-
41
- const customMessageRenderers = ɵresolveCustomMessageRenderers(
40
+ const { agentId, renderers } = ɵresolveCustomMessageRenderContext(
42
41
  core.renderCustomMessages,
43
- agentId,
42
+ configValue.agentId,
44
43
  );
44
+ // Agent-scoped renderers come first. Use the first one that has a
45
+ // render function.
46
+ const selected = renderers.find((candidate) => candidate.render);
47
+ if (!selected) return null;
45
48
 
46
- if (!customMessageRenderers.length) {
47
- return null;
48
- }
49
-
50
- const { message, position } = params;
51
- const resolvedRunId =
52
- core.getRunIdForMessage(agentId, threadId, message.id) ??
53
- core.getRunIdsForThread(agentId, threadId).slice(-1)[0];
54
- const runId = resolvedRunId ?? `missing-run-id:${message.id}`;
55
49
  const agent = core.getAgent(agentId);
56
- if (!agent) {
57
- return null;
58
- }
59
-
60
- const messagesIdsInRun = resolvedRunId
61
- ? agent.messages
62
- .filter(
63
- (msg) =>
64
- core.getRunIdForMessage(agentId, threadId, msg.id) ===
65
- resolvedRunId,
66
- )
67
- .map((msg) => msg.id)
68
- : [message.id];
50
+ if (!agent) return null;
69
51
 
70
- const rawMessageIndex = agent.messages.findIndex(
71
- (msg) => msg.id === message.id,
52
+ const props: VueCustomMessageRendererProps = ɵgetCustomMessageRenderProps(
53
+ core,
54
+ {
55
+ agentId,
56
+ threadId: configValue.threadId,
57
+ agent,
58
+ message: params.message,
59
+ position: params.position,
60
+ },
72
61
  );
73
- if (rawMessageIndex < 0) {
74
- console.warn(
75
- `[CopilotKit] useRenderCustomMessages: message "${message.id}" ` +
76
- `not found in agent "${agentId}" messages`,
77
- );
78
- }
79
- const messageIndex = Math.max(0, rawMessageIndex);
80
- const messageIndexInRun = resolvedRunId
81
- ? Math.max(messagesIdsInRun.indexOf(message.id), 0)
82
- : 0;
83
- const numberOfMessagesInRun = resolvedRunId ? messagesIdsInRun.length : 1;
84
- const stateSnapshot = resolvedRunId
85
- ? core.getStateByRun(agentId, threadId, resolvedRunId)
86
- : undefined;
87
-
88
- const props: VueCustomMessageRendererProps = {
89
- message,
90
- position,
91
- runId,
92
- messageIndex,
93
- messageIndexInRun,
94
- numberOfMessagesInRun,
95
- agentId,
96
- stateSnapshot,
97
- };
98
-
99
- // Agent-scoped renderers come first. Use the first one that has a
100
- // render function.
101
- const selected = customMessageRenderers.find(
102
- (candidate) => candidate.render,
103
- );
104
- if (!selected) return null;
105
62
 
106
63
  return { renderer: selected.render, props };
107
64
  };
@@ -1,6 +1,10 @@
1
1
  import { computed, ref, toValue, watch } from "vue";
2
2
  import type { MaybeRefOrGetter, Ref } from "vue";
3
- import type { Suggestion } from "@copilotkit/core";
3
+ import { ɵsubscribeToAgentSuggestions } from "@copilotkit/core";
4
+ import type {
5
+ CopilotKitCoreGetSuggestionsResult,
6
+ Suggestion,
7
+ } from "@copilotkit/core";
4
8
  import { useCopilotKit } from "../providers/useCopilotKit";
5
9
  import { useCopilotChatConfiguration } from "../providers/useCopilotChatConfiguration";
6
10
  import { DEFAULT_AGENT_ID } from "@copilotkit/shared";
@@ -40,44 +44,16 @@ export function useSuggestions(
40
44
 
41
45
  const suggestions = ref<Suggestion[]>([]);
42
46
  const isLoading = ref(false);
43
-
44
- const initState = () => {
45
- const result = copilotkit.value.getSuggestions(resolvedAgentId.value);
47
+ const apply = (result: CopilotKitCoreGetSuggestionsResult) => {
46
48
  suggestions.value = result.suggestions;
47
49
  isLoading.value = result.isLoading;
48
50
  };
49
51
 
50
- watch([() => copilotkit.value, resolvedAgentId], () => initState(), {
51
- immediate: true,
52
- });
53
-
54
52
  watch(
55
53
  [() => copilotkit.value, resolvedAgentId],
56
- (_newValues, _old, onCleanup) => {
57
- const core = copilotkit.value;
58
- const agentId = resolvedAgentId.value;
59
- const sub = core.subscribe({
60
- onSuggestionsChanged: ({ agentId: changedAgentId, suggestions: s }) => {
61
- if (changedAgentId !== agentId) return;
62
- suggestions.value = s;
63
- const result = core.getSuggestions(agentId);
64
- isLoading.value = result.isLoading;
65
- },
66
- onSuggestionsStartedLoading: ({ agentId: changedAgentId }) => {
67
- if (changedAgentId !== agentId) return;
68
- isLoading.value = true;
69
- },
70
- onSuggestionsFinishedLoading: ({ agentId: changedAgentId }) => {
71
- if (changedAgentId !== agentId) return;
72
- isLoading.value = false;
73
- },
74
- onSuggestionsConfigChanged: () => {
75
- const result = core.getSuggestions(agentId);
76
- suggestions.value = result.suggestions;
77
- isLoading.value = result.isLoading;
78
- },
79
- });
80
- onCleanup(() => sub.unsubscribe());
54
+ ([core, agentId], _old, onCleanup) => {
55
+ apply(core.getSuggestions(agentId));
56
+ onCleanup(ɵsubscribeToAgentSuggestions(core, agentId, apply));
81
57
  },
82
58
  { immediate: true },
83
59
  );