@copilotkit/vue 1.69.1 → 1.69.3

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 (54) hide show
  1. package/PARITY.md +1 -1
  2. package/README.md +7 -0
  3. package/dist/index.cjs +1 -1
  4. package/dist/index.cjs.map +1 -1
  5. package/dist/index.mjs +14 -14
  6. package/dist/use-render-activity-message-DMY6Krn-.cjs +85 -0
  7. package/dist/use-render-activity-message-DMY6Krn-.cjs.map +1 -0
  8. package/dist/{use-render-activity-message-CADUB--8.js → use-render-activity-message-W2lbqLZH.js} +4000 -4285
  9. package/dist/use-render-activity-message-W2lbqLZH.js.map +1 -0
  10. package/dist/v2/components/CopilotKitInspector.vue.d.ts.map +1 -1
  11. package/dist/v2/components/OpenGenerativeUIRenderer.d.ts.map +1 -1
  12. package/dist/v2/components/chat/CopilotChatAssistantMessage.vue.d.ts.map +1 -1
  13. package/dist/v2/components/chat/CopilotChatInput.vue.d.ts +0 -18
  14. package/dist/v2/components/chat/CopilotChatInput.vue.d.ts.map +1 -1
  15. package/dist/v2/components/chat/CopilotChatMessageView.vue.d.ts.map +1 -1
  16. package/dist/v2/components/chat/CopilotChatReasoningMessage.vue.d.ts.map +1 -1
  17. package/dist/v2/components/chat/CopilotChatToolCallsView.vue.d.ts.map +1 -1
  18. package/dist/v2/components/icons/index.d.ts +1 -1
  19. package/dist/v2/components/icons/index.d.ts.map +1 -1
  20. package/dist/v2/index.cjs +1 -1
  21. package/dist/v2/index.mjs +1 -1
  22. package/dist/v2/providers/CopilotKitProvider.types.d.ts +10 -9
  23. package/dist/v2/providers/CopilotKitProvider.types.d.ts.map +1 -1
  24. package/dist/v2/providers/CopilotKitProvider.vue.d.ts +1 -1
  25. package/dist/v2/providers/CopilotKitProvider.vue.d.ts.map +1 -1
  26. package/dist/v2/providers/keys.d.ts +1 -27
  27. package/dist/v2/providers/keys.d.ts.map +1 -1
  28. package/dist/v2/providers/types.d.ts +0 -3
  29. package/dist/v2/providers/types.d.ts.map +1 -1
  30. package/package.json +5 -5
  31. package/src/v2/__tests__/mocks/web-inspector.ts +32 -1
  32. package/src/v2/components/CopilotKitInspector.vue +34 -14
  33. package/src/v2/components/OpenGenerativeUIRenderer.ts +1 -42
  34. package/src/v2/components/__tests__/CopilotKitInspector.test.ts +31 -6
  35. package/src/v2/components/chat/CopilotChatAssistantMessage.vue +1 -52
  36. package/src/v2/components/chat/CopilotChatMessageView.vue +23 -57
  37. package/src/v2/components/chat/CopilotChatReasoningMessage.vue +32 -68
  38. package/src/v2/components/chat/CopilotChatToolCallsView.vue +16 -70
  39. package/src/v2/components/icons/__tests__/icons.test.ts +0 -2
  40. package/src/v2/components/icons/index.ts +0 -1
  41. package/src/v2/providers/CopilotKitProvider.types.ts +10 -9
  42. package/src/v2/providers/CopilotKitProvider.vue +15 -73
  43. package/src/v2/providers/__tests__/CopilotKitProvider.test.ts +148 -37
  44. package/src/v2/providers/keys.ts +1 -33
  45. package/src/v2/providers/types.ts +0 -3
  46. package/dist/use-render-activity-message-BtaJ2iQc.cjs +0 -97
  47. package/dist/use-render-activity-message-BtaJ2iQc.cjs.map +0 -1
  48. package/dist/use-render-activity-message-CADUB--8.js.map +0 -1
  49. package/dist/v2/components/chat/SaveSnippetBeside.vue.d.ts +0 -20
  50. package/dist/v2/components/chat/SaveSnippetBeside.vue.d.ts.map +0 -1
  51. package/dist/v2/components/chat/save-snippet-beside.d.ts +0 -20
  52. package/dist/v2/components/chat/save-snippet-beside.d.ts.map +0 -1
  53. package/src/v2/components/chat/SaveSnippetBeside.vue +0 -82
  54. package/src/v2/components/chat/save-snippet-beside.ts +0 -84
@@ -4,7 +4,6 @@ import {
4
4
  defineComponent,
5
5
  getCurrentInstance,
6
6
  h,
7
- inject,
8
7
  onBeforeUnmount,
9
8
  onMounted,
10
9
  ref,
@@ -14,7 +13,6 @@ import { StreamMarkdown } from "streamdown-vue";
14
13
  import { useCopilotChatConfiguration } from "../../providers/useCopilotChatConfiguration";
15
14
  import { CopilotChatDefaultLabels } from "../../providers/types";
16
15
  import {
17
- IconBookmark,
18
16
  IconCheck,
19
17
  IconCopy,
20
18
  IconDownload,
@@ -36,7 +34,6 @@ import type {
36
34
  CopilotChatAssistantMessageToolbarSlotProps,
37
35
  } from "./types";
38
36
  import { useKatexStyles } from "../../hooks/use-katex-styles";
39
- import { InspectorKey } from "../../providers/keys";
40
37
 
41
38
  useKatexStyles();
42
39
 
@@ -91,10 +88,6 @@ const emit = defineEmits<{
91
88
 
92
89
  const config = useCopilotChatConfiguration();
93
90
  const labels = computed(() => config.value?.labels ?? CopilotChatDefaultLabels);
94
- const inspector = inject(InspectorKey, null);
95
- const isLocalInspectorEnabled = computed(
96
- () => inspector?.isLocalInspectorEnabled.value === true,
97
- );
98
91
  const instance = getCurrentInstance();
99
92
  const copied = ref(false);
100
93
  let copiedResetTimeout: ReturnType<typeof setTimeout> | null = null;
@@ -668,31 +661,10 @@ const isLatestAssistantMessage = computed(
668
661
  const shouldShowToolbar = computed(
669
662
  () =>
670
663
  props.toolbarVisible &&
671
- (hasContent.value || isLocalInspectorEnabled.value) &&
664
+ hasContent.value &&
672
665
  !(props.isRunning && isLatestAssistantMessage.value),
673
666
  );
674
667
 
675
- function handleViewInspector() {
676
- inspector?.openInspector({
677
- messageId: props.message.id,
678
- threadId: config.value?.threadId,
679
- agentId: config.value?.agentId,
680
- });
681
- }
682
-
683
- function handleSaveSnippet() {
684
- if (!hasContent.value) {
685
- return;
686
- }
687
- void inspector?.saveEventSnippet({
688
- kind: "text",
689
- messageId: props.message.id,
690
- content: props.message.content ?? "",
691
- threadId: config.value?.threadId,
692
- agentId: config.value?.agentId,
693
- });
694
- }
695
-
696
668
  function resetCopiedStateWithDelay() {
697
669
  if (copiedResetTimeout) {
698
670
  clearTimeout(copiedResetTimeout);
@@ -842,29 +814,6 @@ onBeforeUnmount(() => {
842
814
  </button>
843
815
  </slot>
844
816
 
845
- <button
846
- v-if="isLocalInspectorEnabled"
847
- data-testid="copilot-inspector-button"
848
- type="button"
849
- :class="toolbarButtonClass"
850
- :aria-label="`${labels.assistantMessageToolbarInspectorLabel} (${labels.assistantMessageToolbarInspectorLocalOnlyLabel})`"
851
- :title="`${labels.assistantMessageToolbarInspectorLabel} (${labels.assistantMessageToolbarInspectorLocalOnlyLabel})`"
852
- @click="handleViewInspector"
853
- >
854
- I
855
- </button>
856
- <button
857
- v-if="isLocalInspectorEnabled && hasContent"
858
- data-testid="copilot-save-snippet-button"
859
- type="button"
860
- :class="toolbarButtonClass"
861
- :aria-label="`${labels.assistantMessageToolbarSaveSnippetLabel} (${labels.assistantMessageToolbarInspectorLocalOnlyLabel})`"
862
- :title="`${labels.assistantMessageToolbarSaveSnippetLabel} (${labels.assistantMessageToolbarInspectorLocalOnlyLabel})`"
863
- @click="handleSaveSnippet"
864
- >
865
- <IconBookmark class="cpk:size-[18px]" />
866
- </button>
867
-
868
817
  <slot
869
818
  v-if="hasThumbsUp"
870
819
  name="thumbs-up-button"
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { computed, inject, ref, useSlots, watch } from "vue";
2
+ import { computed, ref, useSlots, watch } from "vue";
3
3
  import type { Component } from "vue";
4
4
  import type {
5
5
  ActivityMessage,
@@ -19,9 +19,6 @@ import { useCopilotChatConfiguration } from "../../providers/useCopilotChatConfi
19
19
  import CopilotChatAssistantMessage from "./CopilotChatAssistantMessage.vue";
20
20
  import CopilotChatReasoningMessage from "./CopilotChatReasoningMessage.vue";
21
21
  import CopilotChatUserMessage from "./CopilotChatUserMessage.vue";
22
- import { InspectorKey } from "../../providers/keys";
23
- import { IconBookmark } from "../icons";
24
- import SaveSnippetBeside from "./SaveSnippetBeside.vue";
25
22
 
26
23
  interface MessageMetaProps {
27
24
  message: Message;
@@ -41,23 +38,6 @@ interface ActivitySlotProps {
41
38
  agent: unknown;
42
39
  }
43
40
 
44
- const inspector = inject(InspectorKey, null);
45
- const canSaveActivity = (message: ActivityMessage) =>
46
- inspector?.isLocalInspectorEnabled.value === true &&
47
- (message.activityType === "a2ui-surface" ||
48
- message.activityType === "open-generative-ui");
49
-
50
- function saveActivitySnippet(message: ActivityMessage) {
51
- void inspector?.saveEventSnippet({
52
- kind: "activity",
53
- messageId: message.id,
54
- activityType: message.activityType,
55
- content: message.content,
56
- threadId: config.value?.threadId,
57
- agentId: config.value?.agentId,
58
- });
59
- }
60
-
61
41
  type InterruptSlotProps = InterruptRenderProps<unknown, unknown>;
62
42
  type CustomMessagePosition = VueCustomMessageRendererProps["position"];
63
43
  type ResolvedCustomMessageRenderer = {
@@ -434,42 +414,28 @@ function resolveToolMessage(
434
414
  />
435
415
  </slot>
436
416
 
437
- <div v-else-if="message.role === 'activity'">
438
- <SaveSnippetBeside :enabled="canSaveActivity(message)">
439
- <slot
440
- :name="getActivitySlotName(message.activityType)"
441
- :activity-type="message.activityType"
442
- :content="message.content"
443
- :message="message"
444
- :agent="resolvedThreadAgent"
445
- >
446
- <slot
447
- name="activity-message"
448
- :activity-type="message.activityType"
449
- :content="message.content"
450
- :message="message"
451
- :agent="resolvedThreadAgent"
452
- >
453
- <component
454
- v-if="resolveActivityRenderer(message)"
455
- :is="resolveActivityRenderer(message)!.renderer"
456
- v-bind="resolveActivityRenderer(message)!.props"
457
- />
458
- </slot>
459
- </slot>
460
- <template #save>
461
- <button
462
- type="button"
463
- class="cpk:inline-flex cpk:h-8 cpk:w-8 cpk:items-center cpk:justify-center cpk:rounded-md cpk:p-0 cpk:text-[rgb(93,93,93)] cpk:hover:bg-[#E8E8E8] cpk:dark:text-[rgb(243,243,243)] cpk:dark:hover:bg-[#303030]"
464
- data-testid="copilot-activity-save-snippet-button"
465
- :aria-label="`${config?.labels.assistantMessageToolbarSaveSnippetLabel ?? 'Save as snippet'} (Local Only)`"
466
- @click="saveActivitySnippet(message)"
467
- >
468
- <IconBookmark class="cpk:size-[18px]" />
469
- </button>
470
- </template>
471
- </SaveSnippetBeside>
472
- </div>
417
+ <slot
418
+ v-else-if="message.role === 'activity'"
419
+ :name="getActivitySlotName(message.activityType)"
420
+ :activity-type="message.activityType"
421
+ :content="message.content"
422
+ :message="message"
423
+ :agent="resolvedThreadAgent"
424
+ >
425
+ <slot
426
+ name="activity-message"
427
+ :activity-type="message.activityType"
428
+ :content="message.content"
429
+ :message="message"
430
+ :agent="resolvedThreadAgent"
431
+ >
432
+ <component
433
+ v-if="resolveActivityRenderer(message)"
434
+ :is="resolveActivityRenderer(message)!.renderer"
435
+ v-bind="resolveActivityRenderer(message)!.props"
436
+ />
437
+ </slot>
438
+ </slot>
473
439
 
474
440
  <slot
475
441
  v-if="componentSlots['message-after']"
@@ -1,11 +1,8 @@
1
1
  <script setup lang="ts">
2
- import { computed, inject, onBeforeUnmount, ref, watch } from "vue";
2
+ import { computed, onBeforeUnmount, ref, watch } from "vue";
3
3
  import type { Message, ReasoningMessage } from "@ag-ui/core";
4
4
  import { StreamMarkdown } from "streamdown-vue";
5
- import { IconBookmark, IconChevronRight } from "../icons";
6
- import { InspectorKey } from "../../providers/keys";
7
- import { useCopilotChatConfiguration } from "../../providers/useCopilotChatConfiguration";
8
- import { CopilotChatDefaultLabels } from "../../providers/types";
5
+ import { IconChevronRight } from "../icons";
9
6
 
10
7
  const props = withDefaults(
11
8
  defineProps<{
@@ -142,27 +139,6 @@ function toggleOpen() {
142
139
  userToggledDuringStreaming.value = true;
143
140
  isOpen.value = !isOpen.value;
144
141
  }
145
-
146
- const inspector = inject(InspectorKey, null);
147
- const chatConfiguration = useCopilotChatConfiguration();
148
- const canSaveReasoning = computed(
149
- () => inspector?.isLocalInspectorEnabled.value === true && hasContent.value,
150
- );
151
- const saveLabel = computed(
152
- () =>
153
- chatConfiguration.value?.labels.assistantMessageToolbarSaveSnippetLabel ??
154
- CopilotChatDefaultLabels.assistantMessageToolbarSaveSnippetLabel,
155
- );
156
-
157
- function saveReasoningSnippet() {
158
- void inspector?.saveEventSnippet({
159
- kind: "reasoning",
160
- messageId: props.message.id,
161
- content: normalizedContent.value,
162
- threadId: chatConfiguration.value?.threadId,
163
- agentId: chatConfiguration.value?.agentId,
164
- });
165
- }
166
142
  </script>
167
143
 
168
144
  <template>
@@ -193,53 +169,41 @@ function saveReasoningSnippet() {
193
169
  },
194
170
  }"
195
171
  >
196
- <div class="cpk:flex cpk:items-center cpk:gap-1">
197
- <slot
198
- name="header"
199
- :is-open="isOpen"
200
- :label="label"
201
- :has-content="hasContent"
202
- :is-streaming="isStreaming"
203
- :on-click="hasContent ? toggleOpen : undefined"
172
+ <slot
173
+ name="header"
174
+ :is-open="isOpen"
175
+ :label="label"
176
+ :has-content="hasContent"
177
+ :is-streaming="isStreaming"
178
+ :on-click="hasContent ? toggleOpen : undefined"
179
+ >
180
+ <button
181
+ type="button"
182
+ class="cpk:inline-flex cpk:items-center cpk:gap-1 cpk:py-1 cpk:text-sm cpk:text-muted-foreground cpk:transition-colors cpk:select-none"
183
+ :class="
184
+ hasContent
185
+ ? 'cpk:hover:text-foreground cpk:cursor-pointer'
186
+ : 'cpk:cursor-default'
187
+ "
188
+ :aria-expanded="hasContent ? isOpen : undefined"
189
+ @click="hasContent ? toggleOpen() : undefined"
204
190
  >
205
- <button
206
- type="button"
207
- class="cpk:inline-flex cpk:items-center cpk:gap-1 cpk:py-1 cpk:text-sm cpk:text-muted-foreground cpk:transition-colors cpk:select-none"
208
- :class="
209
- hasContent
210
- ? 'cpk:hover:text-foreground cpk:cursor-pointer'
211
- : 'cpk:cursor-default'
212
- "
213
- :aria-expanded="hasContent ? isOpen : undefined"
214
- @click="hasContent ? toggleOpen() : undefined"
191
+ <span class="cpk:font-medium">{{ label }}</span>
192
+ <span
193
+ v-if="isStreaming && !hasContent"
194
+ class="cpk:inline-flex cpk:items-center cpk:ml-1"
215
195
  >
216
- <span class="cpk:font-medium">{{ label }}</span>
217
196
  <span
218
- v-if="isStreaming && !hasContent"
219
- class="cpk:inline-flex cpk:items-center cpk:ml-1"
220
- >
221
- <span
222
- class="cpk:w-1.5 cpk:h-1.5 cpk:rounded-full cpk:bg-muted-foreground cpk:animate-pulse"
223
- />
224
- </span>
225
- <IconChevronRight
226
- v-if="hasContent"
227
- class="cpk:size-3.5 cpk:shrink-0 cpk:transition-transform cpk:duration-200"
228
- :class="{ 'cpk:rotate-90': isOpen }"
197
+ class="cpk:w-1.5 cpk:h-1.5 cpk:rounded-full cpk:bg-muted-foreground cpk:animate-pulse"
229
198
  />
230
- </button>
231
- </slot>
232
- <button
233
- v-if="canSaveReasoning"
234
- type="button"
235
- class="cpk:inline-flex cpk:h-8 cpk:w-8 cpk:items-center cpk:justify-center cpk:rounded-md cpk:p-0 cpk:text-[rgb(93,93,93)] cpk:hover:bg-[#E8E8E8] cpk:dark:text-[rgb(243,243,243)] cpk:dark:hover:bg-[#303030]"
236
- data-testid="copilot-save-snippet-button"
237
- :aria-label="`${saveLabel} (Local Only)`"
238
- @click="saveReasoningSnippet"
239
- >
240
- <IconBookmark class="cpk:size-[18px]" />
199
+ </span>
200
+ <IconChevronRight
201
+ v-if="hasContent"
202
+ class="cpk:size-3.5 cpk:shrink-0 cpk:transition-transform cpk:duration-200"
203
+ :class="{ 'cpk:rotate-90': isOpen }"
204
+ />
241
205
  </button>
242
- </div>
206
+ </slot>
243
207
 
244
208
  <slot
245
209
  name="toggle"
@@ -1,15 +1,10 @@
1
1
  <script setup lang="ts">
2
- import { inject, useSlots } from "vue";
2
+ import { useSlots } from "vue";
3
3
  import type { AssistantMessage, Message } from "@ag-ui/core";
4
4
  import type { CopilotChatToolCallRenderSlotProps } from "./types";
5
5
  import CopilotChatToolCallItem from "./CopilotChatToolCallItem.vue";
6
- import SaveSnippetBeside from "./SaveSnippetBeside.vue";
7
- import { InspectorKey } from "../../providers/keys";
8
- import { useCopilotChatConfiguration } from "../../providers/useCopilotChatConfiguration";
9
- import { CopilotChatDefaultLabels } from "../../providers/types";
10
- import { IconBookmark } from "../icons";
11
6
 
12
- const props = withDefaults(
7
+ withDefaults(
13
8
  defineProps<{
14
9
  message: AssistantMessage;
15
10
  messages?: Message[];
@@ -34,70 +29,21 @@ const componentSlots = useSlots() as Record<
34
29
  function getForwardedSlotNames(): ToolCallSlotName[] {
35
30
  return Object.keys(componentSlots) as ToolCallSlotName[];
36
31
  }
37
-
38
- // A streaming tool call has truncated arguments. Do not offer to capture it
39
- // until the JSON is complete, or the snippet holds a broken partial payload.
40
- function hasCompleteArgs(args: string | undefined): boolean {
41
- const trimmed = (args ?? "").trim();
42
- if (!trimmed) {
43
- return true;
44
- }
45
- try {
46
- JSON.parse(trimmed);
47
- return true;
48
- } catch {
49
- return false;
50
- }
51
- }
52
-
53
- const inspector = inject(InspectorKey, null);
54
- const chatConfiguration = useCopilotChatConfiguration();
55
- const canSave = (toolCall: { function: { arguments: string } }) =>
56
- inspector?.isLocalInspectorEnabled.value === true &&
57
- hasCompleteArgs(toolCall.function.arguments);
58
- const saveLabel = () =>
59
- chatConfiguration.value?.labels.assistantMessageToolbarSaveSnippetLabel ??
60
- CopilotChatDefaultLabels.assistantMessageToolbarSaveSnippetLabel;
61
-
62
- function saveToolCall(toolCall: {
63
- id: string;
64
- function: { name: string; arguments: string };
65
- }) {
66
- void inspector?.saveEventSnippet({
67
- kind: "tool-call",
68
- messageId: props.message.id,
69
- toolCallId: toolCall.id,
70
- toolName: toolCall.function.name,
71
- argsJson: toolCall.function.arguments || "{}",
72
- threadId: chatConfiguration.value?.threadId,
73
- agentId: chatConfiguration.value?.agentId,
74
- });
75
- }
76
32
  </script>
77
33
 
78
34
  <template>
79
- <div v-for="toolCall in message.toolCalls ?? []" :key="toolCall.id">
80
- <SaveSnippetBeside :enabled="canSave(toolCall)">
81
- <CopilotChatToolCallItem :tool-call="toolCall" :messages="messages">
82
- <template
83
- v-for="slotName in getForwardedSlotNames()"
84
- :key="slotName"
85
- #[slotName]="slotProps"
86
- >
87
- <slot :name="slotName" v-bind="slotProps ?? {}" />
88
- </template>
89
- </CopilotChatToolCallItem>
90
- <template #save>
91
- <button
92
- type="button"
93
- class="cpk:inline-flex cpk:h-8 cpk:w-8 cpk:items-center cpk:justify-center cpk:rounded-md cpk:p-0 cpk:text-[rgb(93,93,93)] cpk:hover:bg-[#E8E8E8] cpk:dark:text-[rgb(243,243,243)] cpk:dark:hover:bg-[#303030]"
94
- data-testid="copilot-tool-save-snippet-button"
95
- :aria-label="`${saveLabel()} (Local Only)`"
96
- @click="saveToolCall(toolCall)"
97
- >
98
- <IconBookmark class="cpk:size-[18px]" />
99
- </button>
100
- </template>
101
- </SaveSnippetBeside>
102
- </div>
35
+ <CopilotChatToolCallItem
36
+ v-for="toolCall in message.toolCalls ?? []"
37
+ :key="toolCall.id"
38
+ :tool-call="toolCall"
39
+ :messages="messages"
40
+ >
41
+ <template
42
+ v-for="slotName in getForwardedSlotNames()"
43
+ :key="slotName"
44
+ #[slotName]="slotProps"
45
+ >
46
+ <slot :name="slotName" v-bind="slotProps ?? {}" />
47
+ </template>
48
+ </CopilotChatToolCallItem>
103
49
  </template>
@@ -2,7 +2,6 @@ import { describe, expect, it } from "vitest";
2
2
  import { mount } from "@vue/test-utils";
3
3
  import {
4
4
  IconArrowUp,
5
- IconBookmark,
6
5
  IconCheck,
7
6
  IconCheckCircle,
8
7
  IconChevronDown,
@@ -32,7 +31,6 @@ describe("icons adapter", () => {
32
31
  IconPlus,
33
32
  IconMic,
34
33
  IconArrowUp,
35
- IconBookmark,
36
34
  IconCheck,
37
35
  IconSquare,
38
36
  IconLoader2,
@@ -5,7 +5,6 @@ export {
5
5
  Plus as IconPlus,
6
6
  Mic as IconMic,
7
7
  ArrowUp as IconArrowUp,
8
- Bookmark as IconBookmark,
9
8
  Check as IconCheck,
10
9
  Square as IconSquare,
11
10
  Loader2 as IconLoader2,
@@ -37,7 +37,17 @@ export interface CopilotKitProviderProps {
37
37
  sandboxFunctions?: SandboxFunction[];
38
38
  designSkill?: string;
39
39
  };
40
+ /**
41
+ * @deprecated This prop no longer controls the Inspector. Use
42
+ * `enableInspector` instead.
43
+ */
40
44
  showDevConsole?: boolean | "auto";
45
+ /**
46
+ * Disable the CopilotKit Inspector in development.
47
+ * The Inspector is enabled by default in development browser builds and is
48
+ * always disabled in production and during server rendering.
49
+ */
50
+ enableInspector?: boolean;
41
51
  onError?: (event: {
42
52
  error: Error;
43
53
  code: CopilotKitCoreErrorCode;
@@ -49,15 +59,6 @@ export interface CopilotKitProviderProps {
49
59
  loadingComponent?: Component;
50
60
  includeSchema?: boolean;
51
61
  };
52
- /**
53
- * Default anchor corner for the inspector button and window.
54
- * Only used on first load before the user drags to a custom position.
55
- * Defaults to `{ horizontal: "right", vertical: "top" }`.
56
- */
57
- inspectorDefaultAnchor?: {
58
- horizontal: "left" | "right";
59
- vertical: "top" | "bottom";
60
- };
61
62
  /**
62
63
  * Enable debug logging for the client-side event pipeline.
63
64
  *
@@ -15,7 +15,7 @@ import type {
15
15
  CopilotKitCoreSubscriber,
16
16
  FrontendTool,
17
17
  } from "@copilotkit/core";
18
- import { schemaToJsonSchema } from "@copilotkit/shared";
18
+ import { schemaToJsonSchema, shouldEnableInspector } from "@copilotkit/shared";
19
19
  import type { RuntimeLicenseStatus } from "@copilotkit/shared";
20
20
  import { zodToJsonSchema } from "zod-to-json-schema";
21
21
  import { CopilotKitCoreVue } from "../lib/vue-core";
@@ -35,7 +35,7 @@ import {
35
35
  MCPAppsActivityType,
36
36
  } from "../components/MCPAppsActivityRenderer";
37
37
  import { CopilotKitKey, InspectorKey, SandboxFunctionsKey } from "./keys";
38
- import type { VueInspectorOpenRequest, VueInspectorSaveRequest } from "./keys";
38
+ import type { VueInspectorOpenRequest } from "./keys";
39
39
  import {
40
40
  LicenseContextKey,
41
41
  createLicenseContextValue,
@@ -54,7 +54,6 @@ import type {
54
54
 
55
55
  const HEADER_NAME = "X-CopilotCloud-Public-Api-Key";
56
56
  const COPILOT_CLOUD_CHAT_URL = "https://api.cloud.copilotkit.ai/copilotkit/v1";
57
-
58
57
  // Canonical A2UI viewer theme default (matches @copilotkit/a2ui-renderer).
59
58
  // Defined locally to avoid pulling React dependencies from a2ui-renderer.
60
59
  const viewerTheme: Record<string, unknown> = {};
@@ -104,90 +103,34 @@ const props = withDefaults(defineProps<CopilotKitProviderProps>(), {
104
103
  renderCustomMessages: () => [],
105
104
  renderActivityMessages: () => [],
106
105
  openGenerativeUI: undefined,
107
- showDevConsole: false,
108
106
  useSingleEndpoint: undefined,
109
107
  a2ui: undefined,
108
+ enableInspector: undefined,
110
109
  });
111
110
 
112
111
  const shouldRenderInspector = ref(false);
113
- // Mounting the overlay follows showDevConsole. The in-chat affordances are
114
- // narrower: a dev build on localhost only, so `showDevConsole: true` on a
115
- // staging URL never puts a bookmark into a production chat. Matches React.
116
- const canShowLocalInspectorAction = ref(false);
117
-
118
- const updateInspectorVisibility = () => {
119
- const isLocalhost =
120
- typeof window !== "undefined" &&
121
- new Set(["localhost", "127.0.0.1"]).has(window.location?.hostname ?? "");
122
- canShowLocalInspectorAction.value =
123
- process.env.NODE_ENV === "development" && isLocalhost;
124
-
125
- if (props.showDevConsole === true) {
126
- shouldRenderInspector.value = true;
127
- return;
128
- }
129
- if (props.showDevConsole === "auto") {
130
- shouldRenderInspector.value = isLocalhost;
131
- if (!isLocalhost) {
132
- canShowLocalInspectorAction.value = false;
133
- }
134
- return;
135
- }
136
- shouldRenderInspector.value = false;
137
- canShowLocalInspectorAction.value = false;
138
- };
139
112
 
140
- watch(() => props.showDevConsole, updateInspectorVisibility, {
141
- immediate: true,
142
- });
113
+ function updateInspectorVisibility(): void {
114
+ shouldRenderInspector.value = shouldEnableInspector({
115
+ enableInspector: props.enableInspector,
116
+ isBrowser: true,
117
+ isDevelopment: process.env.NODE_ENV === "development",
118
+ });
119
+ }
120
+
121
+ onMounted(updateInspectorVisibility);
122
+ watch(() => props.enableInspector, updateInspectorVisibility);
143
123
 
144
124
  const inspectorOpenRequest = ref<VueInspectorOpenRequest | null>(null);
145
- const isLocalInspectorEnabled = computed(
146
- () => shouldRenderInspector.value && canShowLocalInspectorAction.value,
147
- );
125
+ const isInspectorEnabled = computed(() => shouldRenderInspector.value);
148
126
 
149
127
  function openInspector(request: VueInspectorOpenRequest) {
150
128
  inspectorOpenRequest.value = { ...request };
151
129
  }
152
130
 
153
- async function saveEventSnippet(request: VueInspectorSaveRequest) {
154
- try {
155
- const mod = await import("@copilotkit/web-inspector");
156
- const threadId = request.threadId ?? "inspector-snippet";
157
- const runId = `inspector-snippet-${Date.now()}`;
158
- const compiled = mod.compileChatSnippet({
159
- ...request,
160
- threadId,
161
- runId,
162
- });
163
- const now = new Date().toISOString();
164
- const snippet = {
165
- id: crypto.randomUUID(),
166
- name: compiled.name,
167
- recipe: compiled.recipe,
168
- events: compiled.events,
169
- createdAt: now,
170
- updatedAt: now,
171
- };
172
- mod.upsertEventSnippet(snippet);
173
- openInspector({
174
- messageId: request.messageId,
175
- threadId: request.threadId,
176
- agentId: request.agentId,
177
- menu: "event-snippets",
178
- snippetId: snippet.id,
179
- });
180
- } catch (error) {
181
- // Compile can throw on bad args, and storage can throw QuotaExceededError.
182
- // Callers fire this as `void saveEventSnippet(...)`, so report it here.
183
- console.error("[CopilotKit] Could not save the event snippet.", error);
184
- }
185
- }
186
-
187
131
  provide(InspectorKey, {
188
- isLocalInspectorEnabled,
132
+ isInspectorEnabled,
189
133
  openInspector,
190
- saveEventSnippet,
191
134
  });
192
135
 
193
136
  const initialFrontendTools = props.frontendTools;
@@ -715,7 +658,6 @@ const showExpiringBanner = computed(
715
658
  <CopilotKitInspector
716
659
  v-if="shouldRenderInspector"
717
660
  :core="copilotkit"
718
- :default-anchor="props.inspectorDefaultAnchor"
719
661
  :open-request="inspectorOpenRequest"
720
662
  />
721
663
  <!-- License warnings — driven by server-reported status -->