@copilotkit/react-core 1.10.0-next.11 → 1.10.0-next.13

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 (114) hide show
  1. package/CHANGELOG.md +15 -0
  2. package/dist/{chunk-ADZDXHVC.mjs → chunk-2GRWTU7W.mjs} +4 -4
  3. package/dist/chunk-3BASANUO.mjs +170 -0
  4. package/dist/chunk-3BASANUO.mjs.map +1 -0
  5. package/dist/{chunk-LVWV62JZ.mjs → chunk-5P46WS5M.mjs} +32 -26
  6. package/dist/chunk-5P46WS5M.mjs.map +1 -0
  7. package/dist/{chunk-OKRZF3DD.mjs → chunk-6ZLPNY7X.mjs} +2 -2
  8. package/dist/{chunk-OKRZF3DD.mjs.map → chunk-6ZLPNY7X.mjs.map} +1 -1
  9. package/dist/{chunk-COEUPDRL.mjs → chunk-BEFEBKKI.mjs} +8 -8
  10. package/dist/{chunk-QGE7U4NV.mjs → chunk-F26O2HTO.mjs} +3 -3
  11. package/dist/chunk-F26O2HTO.mjs.map +1 -0
  12. package/dist/{chunk-DLEXVOQE.mjs → chunk-GEKWHETN.mjs} +4 -4
  13. package/dist/{chunk-L6HQIJ74.mjs → chunk-JY3STRON.mjs} +8 -8
  14. package/dist/{chunk-JJDXTTEN.mjs → chunk-K4HXT453.mjs} +2 -2
  15. package/dist/{chunk-JBLMXZ3O.mjs → chunk-KH27ZS4Y.mjs} +6 -6
  16. package/dist/{chunk-TWYUYC4F.mjs → chunk-MUDXTKXE.mjs} +6 -6
  17. package/dist/{chunk-Q42NJFXR.mjs → chunk-N4VN2B5S.mjs} +5 -5
  18. package/dist/{chunk-2TSNHEIS.mjs → chunk-NTH42BY5.mjs} +5 -5
  19. package/dist/{chunk-X2DNXTME.mjs → chunk-OPRDTF4S.mjs} +4 -4
  20. package/dist/chunk-PIF5KJYI.mjs +103 -0
  21. package/dist/chunk-PIF5KJYI.mjs.map +1 -0
  22. package/dist/chunk-WSXTUD36.mjs +759 -0
  23. package/dist/chunk-WSXTUD36.mjs.map +1 -0
  24. package/dist/{chunk-IHAZJF3V.mjs → chunk-YIBUNEBN.mjs} +2 -2
  25. package/dist/chunk-YIBUNEBN.mjs.map +1 -0
  26. package/dist/components/copilot-provider/copilot-messages.mjs +3 -3
  27. package/dist/components/copilot-provider/copilotkit-props.d.ts +9 -1
  28. package/dist/components/copilot-provider/copilotkit-props.js.map +1 -1
  29. package/dist/components/copilot-provider/copilotkit.js +1047 -71
  30. package/dist/components/copilot-provider/copilotkit.js.map +1 -1
  31. package/dist/components/copilot-provider/copilotkit.mjs +11 -8
  32. package/dist/components/copilot-provider/index.js +1047 -71
  33. package/dist/components/copilot-provider/index.js.map +1 -1
  34. package/dist/components/copilot-provider/index.mjs +11 -8
  35. package/dist/components/dev-console/console-trigger.d.ts +8 -0
  36. package/dist/components/dev-console/console-trigger.js +1131 -0
  37. package/dist/components/dev-console/console-trigger.js.map +1 -0
  38. package/dist/components/dev-console/console-trigger.mjs +13 -0
  39. package/dist/components/dev-console/console-trigger.mjs.map +1 -0
  40. package/dist/components/dev-console/developer-console-modal.d.ts +10 -0
  41. package/dist/components/dev-console/developer-console-modal.js +977 -0
  42. package/dist/components/dev-console/developer-console-modal.js.map +1 -0
  43. package/dist/components/dev-console/developer-console-modal.mjs +12 -0
  44. package/dist/components/dev-console/developer-console-modal.mjs.map +1 -0
  45. package/dist/components/dev-console/icons.d.ts +9 -0
  46. package/dist/components/dev-console/icons.js +131 -0
  47. package/dist/components/dev-console/icons.js.map +1 -0
  48. package/dist/components/dev-console/icons.mjs +16 -0
  49. package/dist/components/dev-console/icons.mjs.map +1 -0
  50. package/dist/components/error-boundary/error-boundary.js +1 -1
  51. package/dist/components/error-boundary/error-boundary.js.map +1 -1
  52. package/dist/components/error-boundary/error-boundary.mjs +2 -2
  53. package/dist/components/index.js +1047 -71
  54. package/dist/components/index.js.map +1 -1
  55. package/dist/components/index.mjs +11 -8
  56. package/dist/components/usage-banner.js +1 -1
  57. package/dist/components/usage-banner.js.map +1 -1
  58. package/dist/components/usage-banner.mjs +1 -1
  59. package/dist/context/index.mjs +4 -4
  60. package/dist/hooks/index.js +1 -1
  61. package/dist/hooks/index.js.map +1 -1
  62. package/dist/hooks/index.mjs +32 -29
  63. package/dist/hooks/use-chat.mjs +4 -4
  64. package/dist/hooks/use-coagent-state-render.mjs +2 -2
  65. package/dist/hooks/use-coagent.js.map +1 -1
  66. package/dist/hooks/use-coagent.mjs +16 -13
  67. package/dist/hooks/use-copilot-action.mjs +2 -2
  68. package/dist/hooks/use-copilot-authenticated-action.mjs +3 -3
  69. package/dist/hooks/use-copilot-chat-headless_c.js +1 -1
  70. package/dist/hooks/use-copilot-chat-headless_c.js.map +1 -1
  71. package/dist/hooks/use-copilot-chat-headless_c.mjs +16 -13
  72. package/dist/hooks/use-copilot-chat.d.ts +42 -3
  73. package/dist/hooks/use-copilot-chat.js.map +1 -1
  74. package/dist/hooks/use-copilot-chat.mjs +16 -13
  75. package/dist/hooks/use-copilot-chat_internal.js.map +1 -1
  76. package/dist/hooks/use-copilot-chat_internal.mjs +15 -12
  77. package/dist/hooks/use-langgraph-interrupt-render.mjs +1 -1
  78. package/dist/hooks/use-langgraph-interrupt.js.map +1 -1
  79. package/dist/hooks/use-langgraph-interrupt.mjs +16 -13
  80. package/dist/index.js +1145 -178
  81. package/dist/index.js.map +1 -1
  82. package/dist/index.mjs +36 -33
  83. package/dist/lib/copilot-task.js.map +1 -1
  84. package/dist/lib/copilot-task.mjs +13 -10
  85. package/dist/lib/index.js.map +1 -1
  86. package/dist/lib/index.mjs +13 -10
  87. package/dist/utils/extract.js.map +1 -1
  88. package/dist/utils/extract.mjs +11 -8
  89. package/dist/utils/index.js.map +1 -1
  90. package/dist/utils/index.mjs +11 -8
  91. package/dist/utils/suggestions.js.map +1 -1
  92. package/dist/utils/suggestions.mjs +11 -8
  93. package/package.json +3 -3
  94. package/src/components/copilot-provider/copilotkit-props.tsx +10 -1
  95. package/src/components/copilot-provider/copilotkit.tsx +25 -16
  96. package/src/components/dev-console/console-trigger.tsx +190 -0
  97. package/src/components/dev-console/developer-console-modal.tsx +866 -0
  98. package/src/components/dev-console/icons.tsx +101 -0
  99. package/src/components/usage-banner.tsx +1 -1
  100. package/src/hooks/use-copilot-chat-headless_c.ts +79 -9
  101. package/src/hooks/use-copilot-chat.ts +42 -3
  102. package/dist/chunk-IHAZJF3V.mjs.map +0 -1
  103. package/dist/chunk-LVWV62JZ.mjs.map +0 -1
  104. package/dist/chunk-QGE7U4NV.mjs.map +0 -1
  105. /package/dist/{chunk-ADZDXHVC.mjs.map → chunk-2GRWTU7W.mjs.map} +0 -0
  106. /package/dist/{chunk-COEUPDRL.mjs.map → chunk-BEFEBKKI.mjs.map} +0 -0
  107. /package/dist/{chunk-DLEXVOQE.mjs.map → chunk-GEKWHETN.mjs.map} +0 -0
  108. /package/dist/{chunk-L6HQIJ74.mjs.map → chunk-JY3STRON.mjs.map} +0 -0
  109. /package/dist/{chunk-JJDXTTEN.mjs.map → chunk-K4HXT453.mjs.map} +0 -0
  110. /package/dist/{chunk-JBLMXZ3O.mjs.map → chunk-KH27ZS4Y.mjs.map} +0 -0
  111. /package/dist/{chunk-TWYUYC4F.mjs.map → chunk-MUDXTKXE.mjs.map} +0 -0
  112. /package/dist/{chunk-Q42NJFXR.mjs.map → chunk-N4VN2B5S.mjs.map} +0 -0
  113. /package/dist/{chunk-2TSNHEIS.mjs.map → chunk-NTH42BY5.mjs.map} +0 -0
  114. /package/dist/{chunk-X2DNXTME.mjs.map → chunk-OPRDTF4S.mjs.map} +0 -0
@@ -1,20 +1,23 @@
1
1
  import {
2
2
  reloadSuggestions
3
- } from "../chunk-LVWV62JZ.mjs";
4
- import "../chunk-TWYUYC4F.mjs";
5
- import "../chunk-Q42NJFXR.mjs";
3
+ } from "../chunk-5P46WS5M.mjs";
4
+ import "../chunk-N4VN2B5S.mjs";
5
+ import "../chunk-MUDXTKXE.mjs";
6
+ import "../chunk-3BASANUO.mjs";
7
+ import "../chunk-WSXTUD36.mjs";
8
+ import "../chunk-PIF5KJYI.mjs";
6
9
  import "../chunk-2IDV5OHF.mjs";
7
10
  import "../chunk-PMAFHQ7P.mjs";
8
11
  import "../chunk-5FHSUKQL.mjs";
9
12
  import "../chunk-RKTVJRK7.mjs";
10
- import "../chunk-ZLQVRPDS.mjs";
11
- import "../chunk-OKRZF3DD.mjs";
12
- import "../chunk-N4WEHORG.mjs";
13
- import "../chunk-O7ARI5CV.mjs";
14
13
  import "../chunk-FAUNHSQU.mjs";
15
14
  import "../chunk-ICIK2BSB.mjs";
16
- import "../chunk-TEMLWRRT.mjs";
15
+ import "../chunk-N4WEHORG.mjs";
16
+ import "../chunk-O7ARI5CV.mjs";
17
17
  import "../chunk-EFL5OBKN.mjs";
18
+ import "../chunk-6ZLPNY7X.mjs";
19
+ import "../chunk-TEMLWRRT.mjs";
20
+ import "../chunk-ZLQVRPDS.mjs";
18
21
  import "../chunk-SKC7AJIV.mjs";
19
22
  export {
20
23
  reloadSuggestions
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "publishConfig": {
10
10
  "access": "public"
11
11
  },
12
- "version": "1.10.0-next.11",
12
+ "version": "1.10.0-next.13",
13
13
  "sideEffects": false,
14
14
  "main": "./dist/index.js",
15
15
  "module": "./dist/index.mjs",
@@ -47,8 +47,8 @@
47
47
  "@scarf/scarf": "^1.3.0",
48
48
  "react-markdown": "^8.0.7",
49
49
  "untruncate-json": "^0.0.1",
50
- "@copilotkit/runtime-client-gql": "1.10.0-next.11",
51
- "@copilotkit/shared": "1.10.0-next.11"
50
+ "@copilotkit/runtime-client-gql": "1.10.0-next.13",
51
+ "@copilotkit/shared": "1.10.0-next.13"
52
52
  },
53
53
  "keywords": [
54
54
  "copilotkit",
@@ -8,10 +8,19 @@ import { CopilotErrorHandler } from "@copilotkit/shared";
8
8
 
9
9
  export interface CopilotKitProps {
10
10
  /**
11
- * Your Copilot Cloud API key. Don't have it yet? Go to https://cloud.copilotkit.ai and get one for free.
11
+ * Your Copilot Cloud API key.
12
+ *
13
+ * Don't have it yet? Go to https://cloud.copilotkit.ai and get one for free.
12
14
  */
13
15
  publicApiKey?: string;
14
16
 
17
+ /**
18
+ * Your public license key for accessing premium CopilotKit features.
19
+ *
20
+ * Don't have it yet? Go to https://cloud.copilotkit.ai and get one for free.
21
+ */
22
+ publicLicenseKey?: string;
23
+
15
24
  /**
16
25
  * Restrict input to a specific topic.
17
26
  * @deprecated Use `guardrails_c` instead to control input restrictions
@@ -51,15 +51,17 @@ import {
51
51
  LangGraphInterruptAction,
52
52
  LangGraphInterruptActionSetterArgs,
53
53
  } from "../../types/interrupt-action";
54
- import { StatusChecker } from "../../lib/status-checker";
55
- import { SuggestionItem } from "../../utils/suggestions";
54
+ import { ConsoleTrigger } from "../dev-console/console-trigger";
56
55
 
57
56
  export function CopilotKit({ children, ...props }: CopilotKitProps) {
58
57
  const enabled = shouldShowDevConsole(props.showDevConsole);
59
58
 
59
+ // Use API key if provided, otherwise use the license key
60
+ const publicApiKey = props.publicApiKey || props.publicLicenseKey;
61
+
60
62
  return (
61
63
  <ToastProvider enabled={enabled}>
62
- <CopilotErrorBoundary publicApiKey={props.publicApiKey} showUsageBanner={enabled}>
64
+ <CopilotErrorBoundary publicApiKey={publicApiKey} showUsageBanner={enabled}>
63
65
  <CopilotKitInternal {...props}>{children}</CopilotKitInternal>
64
66
  </CopilotErrorBoundary>
65
67
  </ToastProvider>
@@ -74,6 +76,9 @@ export function CopilotKitInternal(cpkProps: CopilotKitProps) {
74
76
  */
75
77
  validateProps(cpkProps);
76
78
 
79
+ // Use license key as API key if provided, otherwise use the API key
80
+ const publicApiKey = props.publicLicenseKey || props.publicApiKey;
81
+
77
82
  const chatApiEndpoint = props.runtimeUrl || COPILOT_CLOUD_CHAT_URL;
78
83
 
79
84
  const [actions, setActions] = useState<Record<string, FrontendAction<any>>>({});
@@ -99,10 +104,6 @@ export function CopilotKitInternal(cpkProps: CopilotKitProps) {
99
104
  allElements: allDocuments,
100
105
  } = useFlatCategoryStore<DocumentPointer>();
101
106
 
102
- const statusChecker = useMemo(() => new StatusChecker(), []);
103
-
104
- const [usageBannerStatus, setUsageBannerStatus] = useState<any>(null);
105
-
106
107
  // Compute all the functions and properties that we need to pass
107
108
  const setAction = useCallback((id: string, action: FrontendAction<any>) => {
108
109
  setActions((prevPoints) => {
@@ -206,7 +207,7 @@ export function CopilotKitInternal(cpkProps: CopilotKitProps) {
206
207
  // get the appropriate CopilotApiConfig from the props
207
208
  const copilotApiConfig: CopilotApiConfig = useMemo(() => {
208
209
  let cloud: CopilotCloudConfig | undefined = undefined;
209
- if (props.publicApiKey) {
210
+ if (publicApiKey) {
210
211
  cloud = {
211
212
  guardrails: {
212
213
  input: {
@@ -221,7 +222,7 @@ export function CopilotKitInternal(cpkProps: CopilotKitProps) {
221
222
  }
222
223
 
223
224
  return {
224
- publicApiKey: props.publicApiKey,
225
+ publicApiKey: publicApiKey,
225
226
  ...(cloud ? { cloud } : {}),
226
227
  chatApiEndpoint: chatApiEndpoint,
227
228
  headers: props.headers || {},
@@ -231,7 +232,7 @@ export function CopilotKitInternal(cpkProps: CopilotKitProps) {
231
232
  credentials: props.credentials,
232
233
  };
233
234
  }, [
234
- props.publicApiKey,
235
+ publicApiKey,
235
236
  props.headers,
236
237
  props.properties,
237
238
  props.transcribeAudioUrl,
@@ -269,7 +270,7 @@ export function CopilotKitInternal(cpkProps: CopilotKitProps) {
269
270
 
270
271
  const runtimeClient = useCopilotRuntimeClient({
271
272
  url: copilotApiConfig.chatApiEndpoint,
272
- publicApiKey: copilotApiConfig.publicApiKey,
273
+ publicApiKey: publicApiKey,
273
274
  headers,
274
275
  credentials: copilotApiConfig.credentials,
275
276
  showDevConsole: shouldShowDevConsole(props.showDevConsole),
@@ -491,7 +492,10 @@ export function CopilotKitInternal(cpkProps: CopilotKitProps) {
491
492
  }}
492
493
  >
493
494
  <MessagesTapProvider>
494
- <CopilotMessages>{memoizedChildren}</CopilotMessages>
495
+ <CopilotMessages>
496
+ {memoizedChildren}
497
+ {showDevConsole && <ConsoleTrigger />}
498
+ </CopilotMessages>
495
499
  </MessagesTapProvider>
496
500
  {bannerError && showDevConsole && (
497
501
  <UsageBanner
@@ -544,13 +548,18 @@ function formatFeatureName(featureName: string): string {
544
548
  function validateProps(props: CopilotKitProps): never | void {
545
549
  const cloudFeatures = Object.keys(props).filter((key) => key.endsWith("_c"));
546
550
 
547
- if (!props.runtimeUrl && !props.publicApiKey) {
548
- throw new ConfigurationError("Missing required prop: 'runtimeUrl' or 'publicApiKey'");
551
+ // Check if we have either a runtimeUrl or one of the API keys
552
+ const hasApiKey = props.publicApiKey || props.publicLicenseKey;
553
+
554
+ if (!props.runtimeUrl && !hasApiKey) {
555
+ throw new ConfigurationError(
556
+ "Missing required prop: 'runtimeUrl' or 'publicApiKey' or 'publicLicenseKey'",
557
+ );
549
558
  }
550
559
 
551
- if (cloudFeatures.length > 0 && !props.publicApiKey) {
560
+ if (cloudFeatures.length > 0 && !hasApiKey) {
552
561
  throw new MissingPublicApiKeyError(
553
- `Missing required prop: 'publicApiKey' to use cloud features: ${cloudFeatures
562
+ `Missing required prop: 'publicApiKey' or 'publicLicenseKey' to use cloud features: ${cloudFeatures
554
563
  .map(formatFeatureName)
555
564
  .join(", ")}`,
556
565
  );
@@ -0,0 +1,190 @@
1
+ "use client";
2
+
3
+ import React, { useState, useEffect, useRef } from "react";
4
+ import { useCopilotContext } from "../../context/copilot-context";
5
+ import { CopilotKitIcon } from "./icons";
6
+ import { DeveloperConsoleModal } from "./developer-console-modal";
7
+
8
+ interface ConsoleTriggerProps {
9
+ position?: "bottom-left" | "bottom-right";
10
+ }
11
+
12
+ export function ConsoleTrigger({ position = "bottom-right" }: ConsoleTriggerProps) {
13
+ const context = useCopilotContext();
14
+ const hasApiKey = Boolean(context.copilotApiConfig.publicApiKey);
15
+ const [isModalOpen, setIsModalOpen] = useState(false);
16
+ const [isHovered, setIsHovered] = useState(false);
17
+ const [isDragging, setIsDragging] = useState(false);
18
+ const [buttonPosition, setButtonPosition] = useState<{ x: number; y: number } | null>(null);
19
+ const [mounted, setMounted] = useState(false);
20
+
21
+ const dragRef = useRef<{
22
+ startX: number;
23
+ startY: number;
24
+ buttonX: number;
25
+ buttonY: number;
26
+ } | null>(null);
27
+ const buttonRef = useRef<HTMLButtonElement>(null);
28
+
29
+ // Initialize on client side only
30
+ useEffect(() => {
31
+ setMounted(true);
32
+ if (typeof window !== "undefined" && !buttonPosition) {
33
+ const buttonSize = 60;
34
+ const margin = 24;
35
+
36
+ const initialPosition = {
37
+ x: margin,
38
+ y: window.innerHeight - buttonSize - margin,
39
+ };
40
+
41
+ setButtonPosition(initialPosition);
42
+ }
43
+ }, [position]);
44
+
45
+ const handleMouseDown = (e: React.MouseEvent) => {
46
+ e.preventDefault();
47
+ if (!buttonPosition) return;
48
+
49
+ dragRef.current = {
50
+ startX: e.clientX,
51
+ startY: e.clientY,
52
+ buttonX: buttonPosition.x,
53
+ buttonY: buttonPosition.y,
54
+ };
55
+ setIsDragging(true);
56
+ };
57
+
58
+ useEffect(() => {
59
+ if (!isDragging) return;
60
+
61
+ const handleMouseMove = (e: MouseEvent) => {
62
+ e.preventDefault();
63
+ e.stopPropagation();
64
+
65
+ if (!dragRef.current) return;
66
+
67
+ const deltaX = e.clientX - dragRef.current.startX;
68
+ const deltaY = e.clientY - dragRef.current.startY;
69
+
70
+ // Calculate new position
71
+ let newX = dragRef.current.buttonX + deltaX;
72
+ let newY = dragRef.current.buttonY + deltaY;
73
+
74
+ // Keep button within viewport bounds
75
+ newX = Math.max(0, Math.min(newX, window.innerWidth - 60));
76
+ newY = Math.max(0, Math.min(newY, window.innerHeight - 60));
77
+
78
+ setButtonPosition({ x: newX, y: newY });
79
+ };
80
+
81
+ const handleMouseUp = (e: MouseEvent) => {
82
+ e.preventDefault();
83
+ e.stopPropagation();
84
+ setIsDragging(false);
85
+ dragRef.current = null;
86
+ };
87
+
88
+ // Use capture phase to intercept events before they reach other handlers
89
+ document.addEventListener("mousemove", handleMouseMove, { capture: true, passive: false });
90
+ document.addEventListener("mouseup", handleMouseUp, { capture: true, passive: false });
91
+
92
+ return () => {
93
+ document.removeEventListener("mousemove", handleMouseMove, { capture: true });
94
+ document.removeEventListener("mouseup", handleMouseUp, { capture: true });
95
+ };
96
+ }, [isDragging]);
97
+
98
+ // Don't render until mounted and position is initialized
99
+ if (!mounted || !buttonPosition) {
100
+ return null;
101
+ }
102
+
103
+ return (
104
+ <>
105
+ <button
106
+ ref={buttonRef}
107
+ onClick={() => {
108
+ if (!isDragging) {
109
+ setIsModalOpen(true);
110
+ }
111
+ }}
112
+ onMouseDown={handleMouseDown}
113
+ onMouseEnter={() => setIsHovered(true)}
114
+ onMouseLeave={() => setIsHovered(false)}
115
+ style={{
116
+ position: "fixed",
117
+ left: `${buttonPosition.x}px`,
118
+ top: `${buttonPosition.y}px`,
119
+ zIndex: 2147483647,
120
+ width: "60px",
121
+ height: "60px",
122
+ background: isDragging ? "#000000" : isHovered ? "#111111" : "#000000",
123
+ color: "white",
124
+ borderRadius: "50%",
125
+ boxShadow: isDragging
126
+ ? "0 8px 32px rgba(0, 0, 0, 0.6), 0 4px 16px rgba(0, 0, 0, 0.4)"
127
+ : isHovered
128
+ ? "0 12px 40px rgba(0, 0, 0, 0.7), 0 6px 20px rgba(0, 0, 0, 0.5)"
129
+ : "0 6px 20px rgba(0, 0, 0, 0.5), 0 3px 10px rgba(0, 0, 0, 0.3)",
130
+ transition: isDragging ? "none" : "all 0.3s cubic-bezier(0.4, 0, 0.2, 1)",
131
+ display: "flex",
132
+ alignItems: "center",
133
+ justifyContent: "center",
134
+ border: "none",
135
+ cursor: isDragging ? "grabbing" : "grab",
136
+ opacity: 1,
137
+ userSelect: "none",
138
+ transform: isDragging ? "scale(1.05)" : isHovered ? "scale(1.1)" : "scale(1)",
139
+ backdropFilter: "blur(10px)",
140
+ pointerEvents: "auto",
141
+ isolation: "isolate",
142
+ }}
143
+ title={
144
+ hasApiKey
145
+ ? "Open Developer Console (Drag to move)"
146
+ : "Developer Console (API Key Required, Drag to move)"
147
+ }
148
+ >
149
+ <div
150
+ style={{
151
+ width: "28px",
152
+ height: "28px",
153
+ display: "flex",
154
+ alignItems: "center",
155
+ justifyContent: "center",
156
+ filter: "drop-shadow(0 2px 4px rgba(0,0,0,0.2))",
157
+ }}
158
+ >
159
+ <CopilotKitIcon />
160
+ </div>
161
+ {!hasApiKey && (
162
+ <div
163
+ style={{
164
+ position: "absolute",
165
+ top: "-2px",
166
+ right: "-2px",
167
+ width: "18px",
168
+ height: "18px",
169
+ background: "linear-gradient(135deg, #ff6b6b 0%, #ee5a24 100%)",
170
+ borderRadius: "50%",
171
+ display: "flex",
172
+ alignItems: "center",
173
+ justifyContent: "center",
174
+ boxShadow: "0 2px 8px rgba(255, 107, 107, 0.4)",
175
+ border: "2px solid white",
176
+ }}
177
+ >
178
+ <span style={{ fontSize: "10px", color: "white", fontWeight: "bold" }}>!</span>
179
+ </div>
180
+ )}
181
+ </button>
182
+
183
+ <DeveloperConsoleModal
184
+ isOpen={isModalOpen}
185
+ onClose={() => setIsModalOpen(false)}
186
+ hasApiKey={hasApiKey}
187
+ />
188
+ </>
189
+ );
190
+ }