@copilotkit/vue 1.62.0 → 1.62.2

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 (53) hide show
  1. package/PARITY.md +7 -7
  2. package/dist/index-By5nIKxT.js +1632 -0
  3. package/dist/index-By5nIKxT.js.map +1 -0
  4. package/dist/index-LFxZI63k.cjs +748 -0
  5. package/dist/index-LFxZI63k.cjs.map +1 -0
  6. package/dist/index.cjs +1 -1
  7. package/dist/index.mjs +70 -69
  8. package/dist/styles.css +1 -1
  9. package/dist/{use-render-activity-message-Bzh3Bckz.js → use-render-activity-message-DbGuwvBd.js} +3363 -3064
  10. package/dist/use-render-activity-message-DbGuwvBd.js.map +1 -0
  11. package/dist/use-render-activity-message-hlNcbV9l.cjs +85 -0
  12. package/dist/use-render-activity-message-hlNcbV9l.cjs.map +1 -0
  13. package/dist/v2/components/chat/CopilotChat.vue.d.ts.map +1 -1
  14. package/dist/v2/components/chat/CopilotModalHeader.vue.d.ts.map +1 -1
  15. package/dist/v2/components/chat/CopilotThreadsDrawer.vue.d.ts +42 -0
  16. package/dist/v2/components/chat/CopilotThreadsDrawer.vue.d.ts.map +1 -0
  17. package/dist/v2/components/chat/index.d.ts +1 -0
  18. package/dist/v2/components/chat/index.d.ts.map +1 -1
  19. package/dist/v2/components/icons/index.d.ts +1 -1
  20. package/dist/v2/components/icons/index.d.ts.map +1 -1
  21. package/dist/v2/hooks/use-agent.d.ts.map +1 -1
  22. package/dist/v2/hooks/use-threads.d.ts +12 -0
  23. package/dist/v2/hooks/use-threads.d.ts.map +1 -1
  24. package/dist/v2/index.cjs +1 -1
  25. package/dist/v2/index.mjs +44 -43
  26. package/dist/v2/lib/is-mobile-viewport.d.ts +15 -0
  27. package/dist/v2/lib/is-mobile-viewport.d.ts.map +1 -0
  28. package/dist/v2/providers/CopilotChatConfigurationProvider.vue.d.ts.map +1 -1
  29. package/dist/v2/providers/types.d.ts +24 -0
  30. package/dist/v2/providers/types.d.ts.map +1 -1
  31. package/package.json +7 -6
  32. package/src/v2/components/chat/CopilotChat.vue +22 -4
  33. package/src/v2/components/chat/CopilotModalHeader.vue +61 -2
  34. package/src/v2/components/chat/CopilotThreadsDrawer.vue +285 -0
  35. package/src/v2/components/chat/__tests__/CopilotChat.clearOnFresh.test.ts +160 -0
  36. package/src/v2/components/chat/__tests__/CopilotModalHeader.drawerLauncher.test.ts +125 -0
  37. package/src/v2/components/chat/__tests__/CopilotThreadsDrawer.ssr.test.ts +25 -0
  38. package/src/v2/components/chat/__tests__/CopilotThreadsDrawer.test.ts +835 -0
  39. package/src/v2/components/chat/index.ts +1 -0
  40. package/src/v2/components/icons/index.ts +1 -0
  41. package/src/v2/hooks/__tests__/use-agent.test.ts +60 -1
  42. package/src/v2/hooks/__tests__/use-human-in-the-loop.e2e.test.ts +4 -4
  43. package/src/v2/hooks/__tests__/use-threads.test.ts +303 -6
  44. package/src/v2/hooks/use-agent.ts +4 -1
  45. package/src/v2/hooks/use-threads.ts +137 -8
  46. package/src/v2/lib/__tests__/is-mobile-viewport.test.ts +48 -0
  47. package/src/v2/lib/is-mobile-viewport.ts +23 -0
  48. package/src/v2/providers/CopilotChatConfigurationProvider.vue +120 -4
  49. package/src/v2/providers/__tests__/CopilotChatConfigurationProvider.test.ts +105 -1
  50. package/src/v2/providers/types.ts +25 -0
  51. package/dist/use-render-activity-message-Bzh3Bckz.js.map +0 -1
  52. package/dist/use-render-activity-message-CW3vipBB.cjs +0 -85
  53. package/dist/use-render-activity-message-CW3vipBB.cjs.map +0 -1
@@ -13,6 +13,7 @@ export { default as CopilotChatSuggestionView } from "./CopilotChatSuggestionVie
13
13
  export { default as CopilotChatToolCallsView } from "./CopilotChatToolCallsView.vue";
14
14
  export { default as CopilotChatUserMessage } from "./CopilotChatUserMessage.vue";
15
15
  export { default as CopilotChatView } from "./CopilotChatView.vue";
16
+ export { default as CopilotThreadsDrawer } from "./CopilotThreadsDrawer.vue";
16
17
  import _CopilotChatToggleButton from "./CopilotChatToggleButton.vue";
17
18
  import CopilotChatToggleButtonCloseIcon from "./CopilotChatToggleButtonCloseIcon";
18
19
  import CopilotChatToggleButtonOpenIcon from "./CopilotChatToggleButtonOpenIcon";
@@ -19,4 +19,5 @@ export {
19
19
  RefreshCw as IconRefreshCw,
20
20
  CheckCircle as IconCheckCircle,
21
21
  Circle as IconCircle,
22
+ PanelLeftOpen as IconPanelLeftOpen,
22
23
  } from "lucide-vue-next";
@@ -4,7 +4,10 @@ import type { AbstractAgent, Message } from "@ag-ui/client";
4
4
  import { randomUUID } from "@copilotkit/shared";
5
5
  import { useAgent } from "../use-agent";
6
6
  import { useCopilotKit } from "../../providers/useCopilotKit";
7
- import { mountWithProvider } from "../../__tests__/utils/mount";
7
+ import {
8
+ mountWithProvider,
9
+ renderWithCopilotKit,
10
+ } from "../../__tests__/utils/mount";
8
11
  import { StateCapturingAgent } from "../../__tests__/utils/agents";
9
12
 
10
13
  describe("useAgent", () => {
@@ -37,6 +40,62 @@ describe("useAgent", () => {
37
40
  expect(wrapper.find("[data-testid=agent-id]").text()).toBe("test-agent");
38
41
  });
39
42
 
43
+ it("uses agentId from chat configuration when no agentId prop is provided", () => {
44
+ const mockAgent = new StateCapturingAgent([], "configured-agent");
45
+
46
+ const Child = defineComponent({
47
+ setup() {
48
+ const { agent } = useAgent();
49
+ return () =>
50
+ h(
51
+ "span",
52
+ { "data-testid": "agent-id" },
53
+ agent.value?.agentId ?? "none",
54
+ );
55
+ },
56
+ });
57
+
58
+ const { wrapper } = renderWithCopilotKit(() => h(Child), {
59
+ agentId: "configured-agent",
60
+ agents: {
61
+ "configured-agent": mockAgent as unknown as AbstractAgent,
62
+ },
63
+ });
64
+
65
+ expect(wrapper.find("[data-testid=agent-id]").text()).toBe(
66
+ "configured-agent",
67
+ );
68
+ });
69
+
70
+ it("uses explicit agentId over chat configuration", () => {
71
+ const configuredAgent = new StateCapturingAgent([], "configured-agent");
72
+ const explicitAgent = new StateCapturingAgent([], "explicit-agent");
73
+
74
+ const Child = defineComponent({
75
+ setup() {
76
+ const { agent } = useAgent({ agentId: "explicit-agent" });
77
+ return () =>
78
+ h(
79
+ "span",
80
+ { "data-testid": "agent-id" },
81
+ agent.value?.agentId ?? "none",
82
+ );
83
+ },
84
+ });
85
+
86
+ const { wrapper } = renderWithCopilotKit(() => h(Child), {
87
+ agentId: "configured-agent",
88
+ agents: {
89
+ "configured-agent": configuredAgent as unknown as AbstractAgent,
90
+ "explicit-agent": explicitAgent as unknown as AbstractAgent,
91
+ },
92
+ });
93
+
94
+ expect(wrapper.find("[data-testid=agent-id]").text()).toBe(
95
+ "explicit-agent",
96
+ );
97
+ });
98
+
40
99
  it("passes state set through useAgent into run input", async () => {
41
100
  const mockAgent = new StateCapturingAgent(
42
101
  [{ newMessages: [] }],
@@ -944,13 +944,13 @@ describe("HITL Thread Reconnection Bug", () => {
944
944
  expect(screen.getByTestId("hitl-action").textContent).toBe("delete");
945
945
  });
946
946
 
947
+ // Core-level coverage asserts that passive replay does not re-invoke local
948
+ // frontend handlers for replayed assistant tool calls.
947
949
  await waitFor(() => {
948
- expect(screen.getByTestId("hitl-status").textContent).toBe(
949
- ToolCallStatus.Executing,
950
+ expect(screen.getByTestId("hitl-status").textContent).toMatch(
951
+ /^(executing|inProgress)$/,
950
952
  );
951
953
  });
952
-
953
- expect(screen.getByTestId("hitl-respond")).toBeDefined();
954
954
  });
955
955
 
956
956
  it("should handle tool call after connect (fresh run)", async () => {
@@ -22,6 +22,7 @@ type ThreadState = {
22
22
  error: Error | null;
23
23
  hasNextPage: boolean;
24
24
  isFetchingNextPage: boolean;
25
+ isMutating: boolean;
25
26
  context: {
26
27
  runtimeUrl: string;
27
28
  headers: Record<string, string>;
@@ -107,6 +108,7 @@ vi.mock("@copilotkit/core", () => {
107
108
  error: null,
108
109
  hasNextPage: false,
109
110
  isFetchingNextPage: false,
111
+ isMutating: false,
110
112
  context: null,
111
113
  };
112
114
  private listeners = new Set<() => void>();
@@ -121,6 +123,7 @@ vi.mock("@copilotkit/core", () => {
121
123
  error: null,
122
124
  hasNextPage: false,
123
125
  isFetchingNextPage: false,
126
+ isMutating: false,
124
127
  context: null,
125
128
  };
126
129
  if (this.socket) {
@@ -266,6 +269,27 @@ vi.mock("@copilotkit/core", () => {
266
269
  });
267
270
  }
268
271
 
272
+ async unarchiveThread(threadId: string): Promise<void> {
273
+ const context = this.requireContext();
274
+ await fetchMock(`${context.runtimeUrl}/threads/${threadId}/unarchive`, {
275
+ method: "POST",
276
+ headers: context.headers,
277
+ body: JSON.stringify({
278
+ agentId: context.agentId,
279
+ }),
280
+ });
281
+ }
282
+
283
+ refetchThreads(): void {
284
+ if (!this.state.context) return;
285
+ void this.fetchThreads(this.state.context);
286
+ }
287
+
288
+ startNewThread(): void {
289
+ // Test double: mirrors the real store's "reset to a fresh thread" no-op
290
+ // shape closely enough for surface-presence assertions.
291
+ }
292
+
269
293
  fetchNextPage(): void {
270
294
  this.state.isFetchingNextPage = true;
271
295
  this.notify();
@@ -319,6 +343,7 @@ vi.mock("@copilotkit/core", () => {
319
343
  ɵselectThreadsError: select((state) => state.error),
320
344
  ɵselectHasNextPage: select((state) => state.hasNextPage),
321
345
  ɵselectIsFetchingNextPage: select((state) => state.isFetchingNextPage),
346
+ ɵselectIsMutating: select((state) => state.isMutating),
322
347
  };
323
348
  });
324
349
 
@@ -336,22 +361,48 @@ function getDispatchedContexts(): Array<ThreadState["context"]> {
336
361
  return threadMocks.dispatchedContexts;
337
362
  }
338
363
 
364
+ type ThreadEndpointRuntimeInfo = {
365
+ list: boolean;
366
+ inspect: boolean;
367
+ mutations: boolean;
368
+ realtimeMetadata: boolean;
369
+ };
370
+
371
+ const supportedThreadEndpoints: ThreadEndpointRuntimeInfo = {
372
+ list: true,
373
+ inspect: true,
374
+ mutations: true,
375
+ realtimeMetadata: true,
376
+ };
377
+
378
+ type MockCopilotKit = {
379
+ runtimeUrl: string | undefined;
380
+ runtimeConnectionStatus: CopilotKitCoreRuntimeConnectionStatus;
381
+ headers: Record<string, string>;
382
+ intelligence: { wsUrl?: string } | undefined;
383
+ threadEndpoints: ThreadEndpointRuntimeInfo | undefined;
384
+ registerThreadStore: ReturnType<typeof vi.fn>;
385
+ unregisterThreadStore: ReturnType<typeof vi.fn>;
386
+ };
387
+
339
388
  function setupCopilotKit(
340
389
  runtimeUrl: string | undefined = "http://localhost:4000",
341
390
  runtimeConnectionStatus: CopilotKitCoreRuntimeConnectionStatus = CopilotKitCoreRuntimeConnectionStatus.Connected,
391
+ overrides: Partial<
392
+ Pick<MockCopilotKit, "threadEndpoints" | "intelligence">
393
+ > = {},
342
394
  ) {
343
- const copilotkit = ref<{
344
- runtimeUrl: string | undefined;
345
- runtimeConnectionStatus: CopilotKitCoreRuntimeConnectionStatus;
346
- headers: Record<string, string>;
347
- intelligence: { wsUrl?: string } | undefined;
348
- }>({
395
+ const copilotkit = ref<MockCopilotKit>({
349
396
  runtimeUrl,
350
397
  runtimeConnectionStatus,
351
398
  headers: { Authorization: "Bearer test-token" },
352
399
  intelligence: {
353
400
  wsUrl: "ws://localhost:4000/client",
354
401
  },
402
+ threadEndpoints: supportedThreadEndpoints,
403
+ registerThreadStore: vi.fn(),
404
+ unregisterThreadStore: vi.fn(),
405
+ ...overrides,
355
406
  });
356
407
  mockUseCopilotKit.mockReturnValue({ copilotkit });
357
408
  return copilotkit;
@@ -399,6 +450,7 @@ function mountHook(
399
450
  agentId: string | Ref<string>;
400
451
  includeArchived?: boolean | Ref<boolean | undefined>;
401
452
  limit?: number | Ref<number | undefined>;
453
+ enabled?: boolean | Ref<boolean | undefined>;
402
454
  } = defaultInput,
403
455
  ) {
404
456
  let result: UseThreadsResult | undefined;
@@ -1038,4 +1090,249 @@ describe("useThreads", () => {
1038
1090
  ]);
1039
1091
  });
1040
1092
  });
1093
+
1094
+ describe("useThreads augmented surface", () => {
1095
+ it("exposes listError, isMutating, and the missing mutations/actions", async () => {
1096
+ fetchMock
1097
+ .mockReturnValueOnce(
1098
+ jsonResponse({ threads: sampleThreads, joinCode: "jc-1" }),
1099
+ )
1100
+ .mockReturnValueOnce(jsonResponse({ joinToken: "jt-1" }));
1101
+
1102
+ const { getResult } = mountHook();
1103
+
1104
+ await vi.waitFor(() => {
1105
+ expect(getResult().isLoading.value).toBe(false);
1106
+ });
1107
+
1108
+ expect(getResult().listError).toBeDefined();
1109
+ expect(getResult().listError.value).toBeNull();
1110
+ expect(getResult().isMutating).toBeDefined();
1111
+ expect(getResult().isMutating.value).toBe(false);
1112
+ expect(typeof getResult().unarchiveThread).toBe("function");
1113
+ expect(typeof getResult().refetchThreads).toBe("function");
1114
+ expect(typeof getResult().startNewThread).toBe("function");
1115
+ });
1116
+
1117
+ it("listError excludes the dev 'Runtime URL is not configured' error", async () => {
1118
+ // No runtimeUrl -> `error` is the dev string, but `listError` stays null.
1119
+ setupCopilotKit("");
1120
+
1121
+ const { getResult } = mountHook();
1122
+
1123
+ await nextTick();
1124
+
1125
+ expect(getResult().error.value).toBeInstanceOf(Error);
1126
+ expect(getResult().error.value?.message).toBe(
1127
+ "Runtime URL is not configured",
1128
+ );
1129
+ expect(getResult().listError.value).toBeNull();
1130
+ });
1131
+
1132
+ it("unarchiveThread calls through to the store's unarchive contract", async () => {
1133
+ fetchMock
1134
+ .mockReturnValueOnce(
1135
+ jsonResponse({ threads: sampleThreads, joinCode: "jc-1" }),
1136
+ )
1137
+ .mockReturnValueOnce(jsonResponse({ joinToken: "jt-1" }))
1138
+ .mockReturnValueOnce(jsonResponse({}));
1139
+
1140
+ const { getResult } = mountHook();
1141
+
1142
+ await vi.waitFor(() => {
1143
+ expect(getResult().isLoading.value).toBe(false);
1144
+ });
1145
+
1146
+ await getResult().unarchiveThread("t-1");
1147
+
1148
+ const [url, options] = fetchMock.mock.calls[2];
1149
+ expect(url).toContain("/threads/t-1/unarchive");
1150
+ expect(options.method).toBe("POST");
1151
+ expect(JSON.parse(options.body)).toMatchObject({
1152
+ agentId: "agent-1",
1153
+ });
1154
+ });
1155
+
1156
+ it("does not dispatch a context (or fetch) when enabled is false", async () => {
1157
+ const { getResult } = mountHook({ ...defaultInput, enabled: false });
1158
+
1159
+ await nextTick();
1160
+
1161
+ expect(fetchMock).not.toHaveBeenCalled();
1162
+ expect(getResult().threads.value).toEqual([]);
1163
+ const lastDispatched = getDispatchedContexts().at(-1);
1164
+ expect(lastDispatched).toBeNull();
1165
+ // A disabled consumer must not be stuck in a permanent loading state:
1166
+ // preConnectLoading must factor in `enabled`, otherwise isLoading would
1167
+ // stay true forever since hasDispatchedContext never gets set.
1168
+ expect(getResult().isLoading.value).toBe(false);
1169
+ });
1170
+
1171
+ it("re-arms the pre-connect loading indicator when enabled toggles false -> true", async () => {
1172
+ const enabled = ref(false);
1173
+
1174
+ fetchMock
1175
+ .mockReturnValueOnce(
1176
+ jsonResponse({ threads: sampleThreads, joinCode: "jc-1" }),
1177
+ )
1178
+ .mockReturnValueOnce(jsonResponse({ joinToken: "jt-1" }));
1179
+
1180
+ const { getResult } = mountHook({ ...defaultInput, enabled });
1181
+
1182
+ await nextTick();
1183
+
1184
+ // Disabled: inert, not loading, no fetch.
1185
+ expect(getResult().isLoading.value).toBe(false);
1186
+ expect(fetchMock).not.toHaveBeenCalled();
1187
+ expect(getDispatchedContexts().at(-1)).toBeNull();
1188
+
1189
+ // Re-enable: the pre-connect loading indicator must re-arm (i.e.
1190
+ // hasDispatchedContext was reset to false on disable) so consumers see
1191
+ // isLoading=true again rather than a stale empty-list flash while the
1192
+ // new context dispatch/fetch is in flight.
1193
+ enabled.value = true;
1194
+ await nextTick();
1195
+
1196
+ expect(getResult().isLoading.value).toBe(true);
1197
+
1198
+ await vi.waitFor(() => {
1199
+ expect(getResult().isLoading.value).toBe(false);
1200
+ });
1201
+
1202
+ expect(fetchMock).toHaveBeenCalledWith(
1203
+ expect.stringContaining("/threads?agentId=agent-1"),
1204
+ expect.objectContaining({ method: "GET" }),
1205
+ );
1206
+ const nonNullContexts = getDispatchedContexts().filter(
1207
+ (context) => context !== null,
1208
+ );
1209
+ expect(nonNullContexts).toHaveLength(1);
1210
+ });
1211
+ });
1212
+
1213
+ describe("thread store registration (core registry)", () => {
1214
+ it("registers the thread store with core when enabled", async () => {
1215
+ const copilotkit = setupCopilotKit();
1216
+
1217
+ fetchMock
1218
+ .mockReturnValueOnce(
1219
+ jsonResponse({ threads: sampleThreads, joinCode: "jc-1" }),
1220
+ )
1221
+ .mockReturnValueOnce(jsonResponse({ joinToken: "jt-1" }));
1222
+
1223
+ mountHook();
1224
+
1225
+ await vi.waitFor(() => {
1226
+ expect(copilotkit.value.registerThreadStore).toHaveBeenCalledWith(
1227
+ "agent-1",
1228
+ expect.objectContaining({ select: expect.any(Function) }),
1229
+ );
1230
+ });
1231
+ });
1232
+
1233
+ it("does not register the thread store when disabled (avoids evicting a live store for the same agent)", async () => {
1234
+ const copilotkit = setupCopilotKit();
1235
+
1236
+ mountHook({ ...defaultInput, enabled: false });
1237
+
1238
+ await nextTick();
1239
+
1240
+ expect(copilotkit.value.registerThreadStore).not.toHaveBeenCalled();
1241
+ });
1242
+
1243
+ it("unregisters the thread store with core on unmount", async () => {
1244
+ const copilotkit = setupCopilotKit();
1245
+
1246
+ fetchMock
1247
+ .mockReturnValueOnce(
1248
+ jsonResponse({ threads: sampleThreads, joinCode: "jc-1" }),
1249
+ )
1250
+ .mockReturnValueOnce(jsonResponse({ joinToken: "jt-1" }));
1251
+
1252
+ const { wrapper } = mountHook();
1253
+
1254
+ await vi.waitFor(() => {
1255
+ expect(copilotkit.value.registerThreadStore).toHaveBeenCalled();
1256
+ });
1257
+
1258
+ wrapper.unmount();
1259
+
1260
+ expect(copilotkit.value.unregisterThreadStore).toHaveBeenCalledWith(
1261
+ "agent-1",
1262
+ );
1263
+ });
1264
+ });
1265
+
1266
+ describe("threadEndpoints gating", () => {
1267
+ it("does not fetch when the runtime does not advertise the list endpoint and surfaces the endpoints-unavailable error", async () => {
1268
+ setupCopilotKit(
1269
+ "http://localhost:4000",
1270
+ CopilotKitCoreRuntimeConnectionStatus.Connected,
1271
+ {
1272
+ threadEndpoints: {
1273
+ list: false,
1274
+ inspect: false,
1275
+ mutations: false,
1276
+ realtimeMetadata: false,
1277
+ },
1278
+ intelligence: undefined,
1279
+ },
1280
+ );
1281
+
1282
+ const { getResult } = mountHook();
1283
+
1284
+ await vi.waitFor(() => {
1285
+ expect(getResult().isLoading.value).toBe(false);
1286
+ });
1287
+
1288
+ expect(fetchMock).not.toHaveBeenCalled();
1289
+ expect(getResult().threads.value).toEqual([]);
1290
+ const lastDispatched = getDispatchedContexts().at(-1);
1291
+ expect(lastDispatched).toBeNull();
1292
+ expect(getResult().error.value?.message).toBe(
1293
+ "Thread endpoints are not available on this CopilotKit runtime",
1294
+ );
1295
+ // The config error must NOT leak into the user-facing list error.
1296
+ expect(getResult().listError.value).toBeNull();
1297
+ });
1298
+
1299
+ it("rejects mutations locally when the runtime reports mutations are unsupported", async () => {
1300
+ setupCopilotKit(
1301
+ "http://localhost:4000",
1302
+ CopilotKitCoreRuntimeConnectionStatus.Connected,
1303
+ {
1304
+ threadEndpoints: {
1305
+ list: true,
1306
+ inspect: true,
1307
+ mutations: false,
1308
+ realtimeMetadata: false,
1309
+ },
1310
+ intelligence: undefined,
1311
+ },
1312
+ );
1313
+ fetchMock.mockReturnValueOnce(jsonResponse({ threads: sampleThreads }));
1314
+
1315
+ const { getResult } = mountHook();
1316
+
1317
+ await vi.waitFor(() => {
1318
+ expect(getResult().isLoading.value).toBe(false);
1319
+ });
1320
+
1321
+ fetchMock.mockClear();
1322
+
1323
+ await expect(getResult().renameThread("t-1", "Renamed")).rejects.toThrow(
1324
+ "Thread mutations are not available on this CopilotKit runtime",
1325
+ );
1326
+ await expect(getResult().archiveThread("t-1")).rejects.toThrow(
1327
+ "Thread mutations are not available on this CopilotKit runtime",
1328
+ );
1329
+ await expect(getResult().unarchiveThread("t-1")).rejects.toThrow(
1330
+ "Thread mutations are not available on this CopilotKit runtime",
1331
+ );
1332
+ await expect(getResult().deleteThread("t-1")).rejects.toThrow(
1333
+ "Thread mutations are not available on this CopilotKit runtime",
1334
+ );
1335
+ expect(fetchMock).not.toHaveBeenCalled();
1336
+ });
1337
+ });
1041
1338
  });
@@ -128,8 +128,11 @@ function getOrCreateThreadClone(
128
128
  * ```
129
129
  */
130
130
  export function useAgent(props: UseAgentProps = {}) {
131
- const agentId = computed(() => toValue(props.agentId) ?? DEFAULT_AGENT_ID);
132
131
  const chatConfig = useCopilotChatConfiguration();
132
+ const agentId = computed(
133
+ () =>
134
+ toValue(props.agentId) ?? chatConfig.value?.agentId ?? DEFAULT_AGENT_ID,
135
+ );
133
136
  const threadId = computed(
134
137
  () => toValue(props.threadId) ?? chatConfig.value?.threadId,
135
138
  );