@copilotkit/react-core 1.70.0 → 1.70.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 (37) hide show
  1. package/dist/{copilotkit-CbZGwElm.d.mts → copilotkit--Jyzm6hS.d.mts} +50 -20
  2. package/dist/copilotkit--Jyzm6hS.d.mts.map +1 -0
  3. package/dist/{copilotkit-B7aFKfQR.mjs → copilotkit-B1jSvZeb.mjs} +395 -291
  4. package/dist/copilotkit-B1jSvZeb.mjs.map +1 -0
  5. package/dist/{copilotkit-BuzP0VeG.d.cts → copilotkit-BLYaCGcz.d.cts} +50 -20
  6. package/dist/copilotkit-BLYaCGcz.d.cts.map +1 -0
  7. package/dist/{copilotkit-BE76j111.cjs → copilotkit-DcFo270Y.cjs} +395 -291
  8. package/dist/copilotkit-DcFo270Y.cjs.map +1 -0
  9. package/dist/index.cjs +5 -4
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +2 -2
  12. package/dist/index.d.cts.map +1 -1
  13. package/dist/index.d.mts +2 -2
  14. package/dist/index.d.mts.map +1 -1
  15. package/dist/index.mjs +5 -4
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/index.umd.js +198 -207
  18. package/dist/index.umd.js.map +1 -1
  19. package/dist/v2/headless.cjs +58 -1
  20. package/dist/v2/headless.cjs.map +1 -1
  21. package/dist/v2/headless.mjs +59 -2
  22. package/dist/v2/headless.mjs.map +1 -1
  23. package/dist/v2/index.cjs +1 -1
  24. package/dist/v2/index.css +1 -1
  25. package/dist/v2/index.d.cts +1 -1
  26. package/dist/v2/index.d.mts +1 -1
  27. package/dist/v2/index.mjs +1 -1
  28. package/dist/v2/index.umd.js +395 -291
  29. package/dist/v2/index.umd.js.map +1 -1
  30. package/package.json +11 -8
  31. package/skills/react-core/SKILL.md +1 -1
  32. package/skills/react-core/references/attachments.md +20 -0
  33. package/skills/react-core/references/threads.md +1 -1
  34. package/dist/copilotkit-B7aFKfQR.mjs.map +0 -1
  35. package/dist/copilotkit-BE76j111.cjs.map +0 -1
  36. package/dist/copilotkit-BuzP0VeG.d.cts.map +0 -1
  37. package/dist/copilotkit-CbZGwElm.d.mts.map +0 -1
@@ -298,6 +298,62 @@ const CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId,
298
298
  const useCopilotChatConfiguration = () => {
299
299
  return (0, react.useContext)(CopilotChatConfiguration);
300
300
  };
301
+ /**
302
+ * Reports modal open/close requests to the host, and — when `open` is
303
+ * supplied — makes the modal state of an already-established chat
304
+ * configuration **controlled** for the subtree it wraps.
305
+ *
306
+ * This is deliberately a scope component rather than another mode inside
307
+ * {@link CopilotChatConfigurationProvider}. The provider resolves modal state
308
+ * across a nested chain (own state, parent sync, drawer mutual-exclusion, the
309
+ * modal-closer registry); a controlled branch inside that resolution would add
310
+ * a fourth interacting mode. Overriding the context for the subtree instead
311
+ * leaves every one of those paths untouched:
312
+ *
313
+ * - `isModalOpen` is replaced with the host's `open`, so the rendered surface
314
+ * follows the prop from the very first frame (no open-then-close flash).
315
+ * - `setModalOpen` still calls the underlying setter, so the existing
316
+ * parent-sync and drawer mutual-exclusion side effects continue to run, and
317
+ * *then* reports the request through `onOpenChange`.
318
+ * - The wrapped setter is registered as the modal closer, so the drawer's
319
+ * mobile mutual-exclusion reaches the host instead of silently flipping
320
+ * state that nothing displays.
321
+ *
322
+ * A host that supplies `open` and ignores `onOpenChange` gets a modal pinned
323
+ * to `open`, which is the standard controlled-component contract. A host that
324
+ * supplies only `onOpenChange` is notified while the modal keeps managing
325
+ * itself.
326
+ *
327
+ * Renders `children` unchanged when no chat configuration is in scope.
328
+ */
329
+ const ControlledModalOpenScope = ({ children, open, onOpenChange }) => {
330
+ const parentConfig = (0, react.useContext)(CopilotChatConfiguration);
331
+ const parentSetModalOpen = parentConfig?.setModalOpen;
332
+ const registerModalCloser = parentConfig?.ɵregisterModalCloser;
333
+ const setModalOpen = (0, react.useCallback)((next) => {
334
+ parentSetModalOpen?.(next);
335
+ onOpenChange?.(next);
336
+ }, [parentSetModalOpen, onOpenChange]);
337
+ (0, react.useEffect)(() => {
338
+ if (!registerModalCloser) return;
339
+ return registerModalCloser(setModalOpen);
340
+ }, [registerModalCloser, setModalOpen]);
341
+ const configurationValue = (0, react.useMemo)(() => parentConfig ? {
342
+ ...parentConfig,
343
+ isModalOpen: open ?? parentConfig.isModalOpen,
344
+ setModalOpen
345
+ } : null, [
346
+ parentConfig,
347
+ open,
348
+ setModalOpen
349
+ ]);
350
+ if (!configurationValue) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children });
351
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfiguration.Provider, {
352
+ value: configurationValue,
353
+ children
354
+ });
355
+ };
356
+ ControlledModalOpenScope.displayName = "ControlledModalOpenScope";
301
357
 
302
358
  //#endregion
303
359
  //#region src/v2/lib/utils.ts
@@ -1765,7 +1821,6 @@ async function ɵrunMcpFollowUp({ host, agent, capturedThreadId }) {
1765
1821
  newMessages: []
1766
1822
  };
1767
1823
  }
1768
- const PROTOCOL_VERSION = "2025-06-18";
1769
1824
  function buildSandboxHTML(extraCspDomains) {
1770
1825
  const baseScriptSrc = "'self' 'wasm-unsafe-eval' 'unsafe-inline' 'unsafe-eval' blob: data: http://localhost:* https://localhost:*";
1771
1826
  const baseFrameSrc = "* blob: data: http://localhost:* https://localhost:*";
@@ -1877,6 +1932,13 @@ var MCPAppsRequestQueue = class {
1877
1932
  }
1878
1933
  };
1879
1934
  const mcpAppsRequestQueue = new MCPAppsRequestQueue();
1935
+ const MCP_OPEN_LINK_BLOCKED_SCHEMES = new Set([
1936
+ "javascript:",
1937
+ "data:",
1938
+ "vbscript:",
1939
+ "blob:",
1940
+ "file:"
1941
+ ]);
1880
1942
  /**
1881
1943
  * Activity type for MCP Apps events - must match the middleware's MCPAppsActivityType
1882
1944
  */
@@ -1892,18 +1954,32 @@ const MCPAppsActivityContentSchema = zod.z.object({
1892
1954
  serverId: zod.z.string().optional(),
1893
1955
  toolInput: zod.z.record(zod.z.string(), zod.z.unknown()).optional()
1894
1956
  });
1895
- function isRequest(msg) {
1896
- return "id" in msg && "method" in msg;
1897
- }
1898
- function isNotification(msg) {
1899
- return !("id" in msg) && "method" in msg;
1900
- }
1901
1957
  /**
1902
1958
  * MCP Apps Extension Activity Renderer
1903
1959
  *
1904
1960
  * Renders MCP Apps UI in a sandboxed iframe with full protocol support.
1905
1961
  * Fetches resource content on-demand via proxied MCP requests.
1906
1962
  */
1963
+ /**
1964
+ * Permissive `ui/message` schema. ext-apps restricts the request to
1965
+ * `role: "user"` with no `followUp`, but CopilotKit intentionally extends
1966
+ * `ui/message` with `role` ("user" | "assistant") and `followUp` (documented
1967
+ * behavior with dedicated tests). We register our own handler (instead of the
1968
+ * bridge's strict `onmessage`) so those extensions survive the migration.
1969
+ *
1970
+ * Going forward, widgets SHOULD pass the extensions under
1971
+ * `params._meta.copilotkit`; the top-level `role`/`followUp` fields are the
1972
+ * legacy channel, kept for backward compatibility and slated for deprecation.
1973
+ */
1974
+ const CopilotKitUiMessageSchema = zod.z.object({
1975
+ method: zod.z.literal("ui/message"),
1976
+ params: zod.z.object({
1977
+ role: zod.z.string().optional(),
1978
+ content: zod.z.array(zod.z.any()).optional(),
1979
+ followUp: zod.z.boolean().optional(),
1980
+ _meta: zod.z.record(zod.z.string(), zod.z.any()).optional()
1981
+ }).passthrough()
1982
+ });
1907
1983
  const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, agent }) {
1908
1984
  const { copilotkit } = (0, _copilotkit_react_core_v2_context.useCopilotKit)();
1909
1985
  const containerRef = (0, react.useRef)(null);
@@ -1917,41 +1993,12 @@ const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, agen
1917
1993
  contentRef.current = content;
1918
1994
  const agentRef = (0, react.useRef)(agent);
1919
1995
  agentRef.current = agent;
1996
+ const bridgeRef = (0, react.useRef)(null);
1920
1997
  const fetchStateRef = (0, react.useRef)({
1921
1998
  inProgress: false,
1922
1999
  promise: null,
1923
2000
  resourceUri: null
1924
2001
  });
1925
- const sendToIframe = (0, react.useCallback)((msg) => {
1926
- if (iframeRef.current?.contentWindow) {
1927
- console.log("[MCPAppsRenderer] Sending to iframe:", msg);
1928
- iframeRef.current.contentWindow.postMessage(msg, "*");
1929
- }
1930
- }, []);
1931
- const sendResponse = (0, react.useCallback)((id, result) => {
1932
- sendToIframe({
1933
- jsonrpc: "2.0",
1934
- id,
1935
- result
1936
- });
1937
- }, [sendToIframe]);
1938
- const sendErrorResponse = (0, react.useCallback)((id, code, message) => {
1939
- sendToIframe({
1940
- jsonrpc: "2.0",
1941
- id,
1942
- error: {
1943
- code,
1944
- message
1945
- }
1946
- });
1947
- }, [sendToIframe]);
1948
- const sendNotification = (0, react.useCallback)((method, params) => {
1949
- sendToIframe({
1950
- jsonrpc: "2.0",
1951
- method,
1952
- params: params || {}
1953
- });
1954
- }, [sendToIframe]);
1955
2002
  (0, react.useEffect)(() => {
1956
2003
  const { resourceUri, serverHash, serverId } = content;
1957
2004
  if (fetchStateRef.current.inProgress && fetchStateRef.current.resourceUri === resourceUri) {
@@ -2006,11 +2053,15 @@ const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, agen
2006
2053
  const container = containerRef.current;
2007
2054
  if (!container) return;
2008
2055
  let mounted = true;
2009
- let messageHandler = null;
2010
- let initialListener = null;
2056
+ let bridge = null;
2011
2057
  let createdIframe = null;
2012
2058
  const setup = async () => {
2013
2059
  try {
2060
+ const bridgeModule = await import("@modelcontextprotocol/ext-apps/app-bridge").catch((importErr) => {
2061
+ throw new Error("MCP Apps require '@modelcontextprotocol/ext-apps' and its peer '@modelcontextprotocol/sdk'. Install them with: npm install @modelcontextprotocol/ext-apps @modelcontextprotocol/sdk", { cause: importErr });
2062
+ });
2063
+ if (!mounted) return;
2064
+ const { AppBridge, PostMessageTransport } = bridgeModule;
2014
2065
  const iframe = document.createElement("iframe");
2015
2066
  createdIframe = iframe;
2016
2067
  iframe.style.width = "100%";
@@ -2021,151 +2072,108 @@ const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, agen
2021
2072
  iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms");
2022
2073
  iframe.setAttribute("data-testid", "mcp-app-iframe");
2023
2074
  iframe.setAttribute("title", "Interactive MCP application");
2024
- const sandboxReady = new Promise((resolve) => {
2025
- initialListener = (event) => {
2026
- if (event.source === iframe.contentWindow) {
2027
- if (event.data?.method === "ui/notifications/sandbox-proxy-ready") {
2028
- if (initialListener) {
2029
- window.removeEventListener("message", initialListener);
2030
- initialListener = null;
2031
- }
2032
- resolve();
2033
- }
2034
- }
2035
- };
2036
- window.addEventListener("message", initialListener);
2037
- });
2038
- if (!mounted) {
2039
- if (initialListener) {
2040
- window.removeEventListener("message", initialListener);
2041
- initialListener = null;
2042
- }
2043
- return;
2044
- }
2045
2075
  const cspDomains = fetchedResource._meta?.ui?.csp?.resourceDomains;
2046
2076
  iframe.srcdoc = buildSandboxHTML(cspDomains);
2047
2077
  iframeRef.current = iframe;
2048
2078
  container.appendChild(iframe);
2049
- await sandboxReady;
2050
- if (!mounted) return;
2051
- console.log("[MCPAppsRenderer] Sandbox proxy ready");
2052
- messageHandler = async (event) => {
2053
- if (event.source !== iframe.contentWindow) return;
2054
- const msg = event.data;
2055
- if (!msg || typeof msg !== "object" || msg.jsonrpc !== "2.0") return;
2056
- console.log("[MCPAppsRenderer] Received from iframe:", msg);
2057
- if (isRequest(msg)) switch (msg.method) {
2058
- case "ui/initialize":
2059
- sendResponse(msg.id, {
2060
- protocolVersion: PROTOCOL_VERSION,
2061
- hostInfo: {
2062
- name: "CopilotKit MCP Apps Host",
2063
- version: "1.0.0"
2064
- },
2065
- hostCapabilities: {
2066
- openLinks: {},
2067
- logging: {}
2068
- },
2069
- hostContext: {
2070
- theme: "light",
2071
- platform: "web"
2072
- }
2073
- });
2074
- break;
2075
- case "ui/message": {
2076
- const currentAgent = agentRef.current;
2077
- if (!currentAgent) {
2078
- console.warn("[MCPAppsRenderer] ui/message: No agent available");
2079
- sendResponse(msg.id, { isError: false });
2080
- break;
2081
- }
2082
- try {
2083
- const params = msg.params;
2084
- const role = params.role || "user";
2085
- const textContent = params.content?.filter((c) => c.type === "text" && c.text).map((c) => c.text).join("\n") || "";
2086
- if (textContent) currentAgent.addMessage({
2087
- id: crypto.randomUUID(),
2088
- role,
2089
- content: textContent
2090
- });
2091
- sendResponse(msg.id, { isError: false });
2092
- if ((params.followUp ?? role === "user") && textContent) {
2093
- const capturedThreadId = currentAgent.threadId || "default";
2094
- mcpAppsRequestQueue.enqueue(currentAgent, () => ɵrunMcpFollowUp({
2095
- host: copilotkit,
2096
- agent: currentAgent,
2097
- capturedThreadId
2098
- })).catch((err) => console.error("[MCPAppsRenderer] ui/message agent run failed:", err));
2099
- }
2100
- } catch (err) {
2101
- console.error("[MCPAppsRenderer] ui/message error:", err);
2102
- sendResponse(msg.id, { isError: true });
2103
- }
2104
- break;
2105
- }
2106
- case "ui/open-link": {
2107
- const url = msg.params?.url;
2108
- if (url) {
2109
- window.open(url, "_blank", "noopener,noreferrer");
2110
- sendResponse(msg.id, { isError: false });
2111
- } else sendErrorResponse(msg.id, -32602, "Missing url parameter");
2112
- break;
2113
- }
2114
- case "tools/call": {
2115
- const { serverHash, serverId } = contentRef.current;
2116
- const currentAgent = agentRef.current;
2117
- if (!serverHash) {
2118
- sendErrorResponse(msg.id, -32603, "No server hash available for proxying");
2119
- break;
2120
- }
2121
- if (!currentAgent) {
2122
- sendErrorResponse(msg.id, -32603, "No agent available for proxying");
2123
- break;
2124
- }
2125
- try {
2126
- const runResult = await mcpAppsRequestQueue.enqueue(currentAgent, () => currentAgent.runAgent({ forwardedProps: { __proxiedMCPRequest: {
2127
- serverHash,
2128
- serverId,
2129
- method: "tools/call",
2130
- params: msg.params
2131
- } } }));
2132
- sendResponse(msg.id, runResult.result || {});
2133
- } catch (err) {
2134
- console.error("[MCPAppsRenderer] tools/call error:", err);
2135
- sendErrorResponse(msg.id, -32603, String(err));
2136
- }
2137
- break;
2138
- }
2139
- default: sendErrorResponse(msg.id, -32601, `Method not found: ${msg.method}`);
2140
- }
2141
- if (isNotification(msg)) switch (msg.method) {
2142
- case "ui/notifications/initialized":
2143
- console.log("[MCPAppsRenderer] Inner iframe initialized");
2144
- if (mounted) setIframeReady(true);
2145
- break;
2146
- case "ui/notifications/size-changed": {
2147
- const { width, height } = msg.params || {};
2148
- console.log("[MCPAppsRenderer] Size change:", {
2149
- width,
2150
- height
2151
- });
2152
- if (mounted) setIframeSize({
2153
- width: typeof width === "number" ? width : void 0,
2154
- height: typeof height === "number" ? height : void 0
2155
- });
2156
- break;
2157
- }
2158
- case "notifications/message":
2159
- console.log("[MCPAppsRenderer] App log:", msg.params);
2160
- break;
2161
- }
2162
- };
2163
- window.addEventListener("message", messageHandler);
2079
+ const win = iframe.contentWindow;
2080
+ if (!win) throw new Error("Sandbox iframe has no contentWindow");
2164
2081
  let html;
2165
2082
  if (fetchedResource.text) html = fetchedResource.text;
2166
2083
  else if (fetchedResource.blob) html = atob(fetchedResource.blob);
2167
2084
  else throw new Error("Resource has no text or blob content");
2168
- sendNotification("ui/notifications/sandbox-resource-ready", { html });
2085
+ bridge = new AppBridge(null, {
2086
+ name: "CopilotKit MCP Apps Host",
2087
+ version: "1.0.0"
2088
+ }, {
2089
+ openLinks: {},
2090
+ logging: {},
2091
+ message: { text: {} }
2092
+ }, { hostContext: {
2093
+ theme: "light",
2094
+ platform: "web"
2095
+ } });
2096
+ bridge.onsandboxready = () => {
2097
+ bridge?.sendSandboxResourceReady({ html });
2098
+ };
2099
+ bridge.setRequestHandler(CopilotKitUiMessageSchema, async (req) => {
2100
+ const currentAgent = agentRef.current;
2101
+ if (!currentAgent) {
2102
+ console.warn("[MCPAppsRenderer] ui/message: No agent available");
2103
+ return { isError: false };
2104
+ }
2105
+ try {
2106
+ const params = req.params;
2107
+ const ck = params._meta?.copilotkit ?? {};
2108
+ const role = ck.role || params.role || "user";
2109
+ const textContent = params.content?.filter((c) => c.type === "text" && c.text).map((c) => c.text).join("\n") || "";
2110
+ if (textContent) currentAgent.addMessage({
2111
+ id: crypto.randomUUID(),
2112
+ role,
2113
+ content: textContent
2114
+ });
2115
+ if ((ck.followUp ?? params.followUp ?? role === "user") && textContent) {
2116
+ const capturedThreadId = currentAgent.threadId || "default";
2117
+ mcpAppsRequestQueue.enqueue(currentAgent, () => ɵrunMcpFollowUp({
2118
+ host: copilotkit,
2119
+ agent: currentAgent,
2120
+ capturedThreadId
2121
+ })).catch((err) => console.error("[MCPAppsRenderer] ui/message agent run failed:", err));
2122
+ }
2123
+ return { isError: false };
2124
+ } catch (err) {
2125
+ console.error("[MCPAppsRenderer] ui/message error:", err);
2126
+ return { isError: true };
2127
+ }
2128
+ });
2129
+ bridge.onopenlink = async ({ url }) => {
2130
+ let parsed;
2131
+ try {
2132
+ parsed = new URL(url);
2133
+ } catch {
2134
+ console.warn("[MCPAppsRenderer] ui/open-link rejected: unparseable url");
2135
+ return { isError: true };
2136
+ }
2137
+ if (MCP_OPEN_LINK_BLOCKED_SCHEMES.has(parsed.protocol)) {
2138
+ console.warn("[MCPAppsRenderer] ui/open-link rejected: blocked scheme", parsed.protocol);
2139
+ return { isError: true };
2140
+ }
2141
+ window.open(url, "_blank", "noopener,noreferrer");
2142
+ return { isError: false };
2143
+ };
2144
+ bridge.oncalltool = async (params) => {
2145
+ const { serverHash, serverId } = contentRef.current;
2146
+ const currentAgent = agentRef.current;
2147
+ if (!serverHash) throw new Error("No server hash available for proxying");
2148
+ if (!currentAgent) throw new Error("No agent available for proxying");
2149
+ return (await mcpAppsRequestQueue.enqueue(currentAgent, () => currentAgent.runAgent({ forwardedProps: { __proxiedMCPRequest: {
2150
+ serverHash,
2151
+ serverId,
2152
+ method: "tools/call",
2153
+ params
2154
+ } } }))).result || { content: [] };
2155
+ };
2156
+ bridge.onsizechange = (p) => {
2157
+ if (!mounted) return;
2158
+ const { width, height } = p || {};
2159
+ setIframeSize({
2160
+ width: typeof width === "number" ? width : void 0,
2161
+ height: typeof height === "number" ? height : void 0
2162
+ });
2163
+ };
2164
+ bridge.oninitialized = () => {
2165
+ if (mounted) setIframeReady(true);
2166
+ };
2167
+ bridge.onloggingmessage = (p) => {
2168
+ console.log("[MCPAppsRenderer] App log:", p);
2169
+ };
2170
+ const transport = new PostMessageTransport(win, win);
2171
+ await bridge.connect(transport);
2172
+ if (!mounted) {
2173
+ await bridge.close();
2174
+ return;
2175
+ }
2176
+ bridgeRef.current = bridge;
2169
2177
  } catch (err) {
2170
2178
  console.error("[MCPAppsRenderer] Setup error:", err);
2171
2179
  if (mounted) setError(err instanceof Error ? err : new Error(String(err)));
@@ -2174,11 +2182,8 @@ const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, agen
2174
2182
  setup();
2175
2183
  return () => {
2176
2184
  mounted = false;
2177
- if (initialListener) {
2178
- window.removeEventListener("message", initialListener);
2179
- initialListener = null;
2180
- }
2181
- if (messageHandler) window.removeEventListener("message", messageHandler);
2185
+ bridgeRef.current = null;
2186
+ bridge?.close();
2182
2187
  if (createdIframe) {
2183
2188
  createdIframe.remove();
2184
2189
  createdIframe = null;
@@ -2188,9 +2193,7 @@ const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, agen
2188
2193
  }, [
2189
2194
  isLoading,
2190
2195
  fetchedResource,
2191
- sendNotification,
2192
- sendResponse,
2193
- sendErrorResponse
2196
+ copilotkit
2194
2197
  ]);
2195
2198
  (0, react.useEffect)(() => {
2196
2199
  if (iframeRef.current) {
@@ -2202,25 +2205,11 @@ const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, agen
2202
2205
  }
2203
2206
  }, [iframeSize]);
2204
2207
  (0, react.useEffect)(() => {
2205
- if (iframeReady && content.toolInput) {
2206
- console.log("[MCPAppsRenderer] Sending tool input:", content.toolInput);
2207
- sendNotification("ui/notifications/tool-input", { arguments: content.toolInput });
2208
- }
2209
- }, [
2210
- iframeReady,
2211
- content.toolInput,
2212
- sendNotification
2213
- ]);
2208
+ if (iframeReady && content.toolInput) bridgeRef.current?.sendToolInput({ arguments: content.toolInput });
2209
+ }, [iframeReady, content.toolInput]);
2214
2210
  (0, react.useEffect)(() => {
2215
- if (iframeReady && content.result) {
2216
- console.log("[MCPAppsRenderer] Sending tool result:", content.result);
2217
- sendNotification("ui/notifications/tool-result", content.result);
2218
- }
2219
- }, [
2220
- iframeReady,
2221
- content.result,
2222
- sendNotification
2223
- ]);
2211
+ if (iframeReady && content.result) bridgeRef.current?.sendToolResult(content.result);
2212
+ }, [iframeReady, content.result]);
2224
2213
  const borderStyle = fetchedResource?._meta?.ui?.prefersBorder === true ? {
2225
2214
  borderRadius: "8px",
2226
2215
  backgroundColor: "#f9f9f9",
@@ -4035,7 +4024,8 @@ function useFrontendTool(tool, deps) {
4035
4024
  tool.name,
4036
4025
  tool.available,
4037
4026
  copilotkit,
4038
- JSON.stringify(extraDeps)
4027
+ JSON.stringify(extraDeps),
4028
+ JSON.stringify(tool.webmcp ?? null)
4039
4029
  ]);
4040
4030
  }
4041
4031
 
@@ -5490,7 +5480,7 @@ function useMemories() {
5490
5480
  * at the call site.
5491
5481
  */
5492
5482
  async function recordAnnotation(args) {
5493
- const { runtimeUrl, headers, type, payload, threadId, occurredAt } = args;
5483
+ const { runtimeUrl, headers, type, payload, threadId, occurredAt, fetch: fetchImplementation = globalThis.fetch } = args;
5494
5484
  const body = {
5495
5485
  type,
5496
5486
  threadId,
@@ -5498,7 +5488,7 @@ async function recordAnnotation(args) {
5498
5488
  ...payload !== void 0 ? { payload } : {},
5499
5489
  ...occurredAt !== void 0 ? { occurredAt } : {}
5500
5490
  };
5501
- const response = await fetch(`${runtimeUrl}/annotate`, {
5491
+ const response = await fetchImplementation(`${runtimeUrl}/annotate`, {
5502
5492
  method: "POST",
5503
5493
  headers: {
5504
5494
  "Content-Type": "application/json",
@@ -5567,6 +5557,7 @@ function useLearnFromUserAction() {
5567
5557
  ...input.data !== void 0 ? { data: input.data } : {}
5568
5558
  };
5569
5559
  return recordAnnotation({
5560
+ fetch: copilotkit.ɵruntimeFetch,
5570
5561
  runtimeUrl,
5571
5562
  headers: copilotkit.headers ?? {},
5572
5563
  type: "user_action",
@@ -5636,6 +5627,21 @@ function useLearnFromUserActionInCurrentThread() {
5636
5627
 
5637
5628
  //#endregion
5638
5629
  //#region src/v2/hooks/use-attachments.tsx
5630
+ const DEFAULT_MAX_SIZE = 20 * 1024 * 1024;
5631
+ /**
5632
+ * How many uploads run at once when `maxConcurrentUploads` is unset. One, because
5633
+ * `onUpload` is a public callback an app may have written expecting the previous
5634
+ * file to have finished — concurrency is something the app asks for.
5635
+ */
5636
+ const DEFAULT_MAX_CONCURRENT_UPLOADS = 1;
5637
+ /**
5638
+ * At least one upload at a time, whole files only; `NaN` or a non-number falls back to the
5639
+ * default, and `Infinity` means "no limit" — bounded in practice by how many files are queued.
5640
+ */
5641
+ function resolveMaxConcurrentUploads(configured) {
5642
+ if (typeof configured !== "number" || Number.isNaN(configured)) return DEFAULT_MAX_CONCURRENT_UPLOADS;
5643
+ return Math.max(1, Math.floor(configured));
5644
+ }
5639
5645
  /**
5640
5646
  * Hook that manages file attachment state — uploads, drag-and-drop, paste,
5641
5647
  * and lifecycle. All returned callbacks are referentially stable across
@@ -5651,10 +5657,62 @@ function useAttachments({ config }) {
5651
5657
  configRef.current = config;
5652
5658
  const attachmentsRef = (0, react.useRef)([]);
5653
5659
  attachmentsRef.current = attachments;
5660
+ const uploadQueueRef = (0, react.useRef)([]);
5661
+ const activeWorkersRef = (0, react.useRef)(0);
5662
+ const uploadFile = (0, react.useCallback)(async (file, placeholder, cfg) => {
5663
+ try {
5664
+ let source;
5665
+ let uploadMetadata;
5666
+ if (cfg?.onUpload) {
5667
+ const { metadata: meta, ...uploadSource } = await cfg.onUpload(file);
5668
+ source = uploadSource;
5669
+ uploadMetadata = meta;
5670
+ } else source = {
5671
+ type: "data",
5672
+ value: await (0, _copilotkit_shared.readFileAsBase64)(file),
5673
+ mimeType: file.type
5674
+ };
5675
+ let thumbnail;
5676
+ if (placeholder.type === "video") thumbnail = await (0, _copilotkit_shared.generateVideoThumbnail)(file);
5677
+ setAttachments((prev) => prev.map((att) => att.id === placeholder.id ? {
5678
+ ...att,
5679
+ source,
5680
+ status: "ready",
5681
+ thumbnail,
5682
+ metadata: uploadMetadata
5683
+ } : att));
5684
+ } catch (error) {
5685
+ setAttachments((prev) => prev.filter((att) => att.id !== placeholder.id));
5686
+ console.error(`[CopilotKit] Failed to upload "${file.name}":`, error);
5687
+ cfg?.onUploadFailed?.({
5688
+ reason: "upload-failed",
5689
+ file,
5690
+ message: error instanceof Error ? error.message : `Failed to upload "${file.name}"`
5691
+ });
5692
+ }
5693
+ }, []);
5694
+ const drainUploadQueue = (0, react.useCallback)(async () => {
5695
+ activeWorkersRef.current++;
5696
+ try {
5697
+ for (;;) {
5698
+ const item = uploadQueueRef.current.shift();
5699
+ if (!item) return;
5700
+ try {
5701
+ await uploadFile(item.file, item.placeholder, item.cfg);
5702
+ } catch (error) {
5703
+ console.error("[CopilotKit] Upload worker error:", error);
5704
+ } finally {
5705
+ item.settle();
5706
+ }
5707
+ }
5708
+ } finally {
5709
+ activeWorkersRef.current--;
5710
+ }
5711
+ }, [uploadFile]);
5654
5712
  const processFiles = (0, react.useCallback)(async (files) => {
5655
5713
  const cfg = configRef.current;
5656
5714
  const accept = cfg?.accept ?? "*/*";
5657
- const maxSize = cfg?.maxSize ?? 20 * 1024 * 1024;
5715
+ const maxSize = cfg?.maxSize ?? DEFAULT_MAX_SIZE;
5658
5716
  const rejectedFiles = files.filter((file) => !(0, _copilotkit_shared.matchesAcceptFilter)(file, accept));
5659
5717
  for (const file of rejectedFiles) cfg?.onUploadFailed?.({
5660
5718
  reason: "invalid-type",
@@ -5662,6 +5720,7 @@ function useAttachments({ config }) {
5662
5720
  message: `File "${file.name}" is not accepted. Supported types: ${accept}`
5663
5721
  });
5664
5722
  const validFiles = files.filter((file) => (0, _copilotkit_shared.matchesAcceptFilter)(file, accept));
5723
+ const queued = [];
5665
5724
  for (const file of validFiles) {
5666
5725
  if ((0, _copilotkit_shared.exceedsMaxSize)(file, maxSize)) {
5667
5726
  cfg?.onUploadFailed?.({
@@ -5671,53 +5730,37 @@ function useAttachments({ config }) {
5671
5730
  });
5672
5731
  continue;
5673
5732
  }
5674
- const modality = (0, _copilotkit_shared.getModalityFromMimeType)(file.type);
5675
- const placeholderId = (0, _copilotkit_shared.randomUUID)();
5676
- const placeholder = {
5677
- id: placeholderId,
5678
- type: modality,
5679
- source: {
5680
- type: "data",
5681
- value: "",
5682
- mimeType: file.type
5683
- },
5684
- filename: file.name,
5685
- size: file.size,
5686
- status: "uploading"
5687
- };
5688
- setAttachments((prev) => [...prev, placeholder]);
5689
- try {
5690
- let source;
5691
- let uploadMetadata;
5692
- if (cfg?.onUpload) {
5693
- const { metadata: meta, ...uploadSource } = await cfg.onUpload(file);
5694
- source = uploadSource;
5695
- uploadMetadata = meta;
5696
- } else source = {
5697
- type: "data",
5698
- value: await (0, _copilotkit_shared.readFileAsBase64)(file),
5699
- mimeType: file.type
5700
- };
5701
- let thumbnail;
5702
- if (modality === "video") thumbnail = await (0, _copilotkit_shared.generateVideoThumbnail)(file);
5703
- setAttachments((prev) => prev.map((att) => att.id === placeholderId ? {
5704
- ...att,
5705
- source,
5706
- status: "ready",
5707
- thumbnail,
5708
- metadata: uploadMetadata
5709
- } : att));
5710
- } catch (error) {
5711
- setAttachments((prev) => prev.filter((att) => att.id !== placeholderId));
5712
- console.error(`[CopilotKit] Failed to upload "${file.name}":`, error);
5713
- cfg?.onUploadFailed?.({
5714
- reason: "upload-failed",
5715
- file,
5716
- message: error instanceof Error ? error.message : `Failed to upload "${file.name}"`
5717
- });
5718
- }
5733
+ queued.push({
5734
+ file,
5735
+ placeholder: {
5736
+ id: (0, _copilotkit_shared.randomUUID)(),
5737
+ type: (0, _copilotkit_shared.getModalityFromMimeType)(file.type),
5738
+ source: {
5739
+ type: "data",
5740
+ value: "",
5741
+ mimeType: file.type
5742
+ },
5743
+ filename: file.name,
5744
+ size: file.size,
5745
+ status: "uploading"
5746
+ }
5747
+ });
5719
5748
  }
5720
- }, []);
5749
+ if (queued.length === 0) return;
5750
+ setAttachments((prev) => [...prev, ...queued.map((q) => q.placeholder)]);
5751
+ const settled = queued.map(({ file, placeholder }) => new Promise((resolve) => {
5752
+ uploadQueueRef.current.push({
5753
+ file,
5754
+ placeholder,
5755
+ cfg,
5756
+ settle: resolve
5757
+ });
5758
+ }));
5759
+ const limit = resolveMaxConcurrentUploads(cfg?.maxConcurrentUploads);
5760
+ const toSpawn = Math.min(uploadQueueRef.current.length, Math.max(0, limit - activeWorkersRef.current));
5761
+ for (let i = 0; i < toSpawn; i++) drainUploadQueue();
5762
+ await Promise.all(settled);
5763
+ }, [drainUploadQueue]);
5721
5764
  const handleFileUpload = (0, react.useCallback)(async (e) => {
5722
5765
  if (!e.target.files?.length) return;
5723
5766
  try {
@@ -5829,9 +5872,9 @@ const DEFAULT_CONTAINERS = ["project"];
5829
5872
  * }
5830
5873
  * ```
5831
5874
  *
5832
- * @deprecated Legacy plural-container annotation compatibility only. New
5833
- * Intelligence runtimes assign one container with `ɵlearning.containerId` on
5834
- * `CopilotRuntime`.
5875
+ * @deprecated This hook supports only the legacy plural-container annotation.
5876
+ * Configure `getLearningContainerId` on `CopilotKitIntelligence` for new
5877
+ * Intelligence runtimes.
5835
5878
  */
5836
5879
  function useLearningContainers({ threadId, learningContainers }) {
5837
5880
  const { copilotkit } = (0, _copilotkit_react_core_v2_context.useCopilotKit)();
@@ -5845,8 +5888,10 @@ function useLearningContainers({ threadId, learningContainers }) {
5845
5888
  const warnedMissingUrlRef = (0, react.useRef)(false);
5846
5889
  const runtimeUrlRef = (0, react.useRef)(copilotkit.runtimeUrl);
5847
5890
  const headersRef = (0, react.useRef)(copilotkit.headers ?? {});
5891
+ const runtimeFetchRef = (0, react.useRef)(copilotkit.ɵruntimeFetch);
5848
5892
  runtimeUrlRef.current = copilotkit.runtimeUrl;
5849
5893
  headersRef.current = copilotkit.headers ?? {};
5894
+ runtimeFetchRef.current = copilotkit.ɵruntimeFetch;
5850
5895
  const key = JSON.stringify(learningContainers);
5851
5896
  const defaultKey = JSON.stringify(DEFAULT_CONTAINERS);
5852
5897
  (0, react.useEffect)(() => {
@@ -5866,6 +5911,7 @@ function useLearningContainers({ threadId, learningContainers }) {
5866
5911
  return;
5867
5912
  }
5868
5913
  recordAnnotation({
5914
+ fetch: copilotkit.ɵruntimeFetch,
5869
5915
  runtimeUrl,
5870
5916
  headers,
5871
5917
  type: "set_learning_containers",
@@ -5893,6 +5939,7 @@ function useLearningContainers({ threadId, learningContainers }) {
5893
5939
  const capturedRuntimeUrl = runtimeUrlRef.current;
5894
5940
  const capturedHeaders = headersRef.current;
5895
5941
  if (capturedRuntimeUrl) recordAnnotation({
5942
+ fetch: runtimeFetchRef.current,
5896
5943
  runtimeUrl: capturedRuntimeUrl,
5897
5944
  headers: capturedHeaders,
5898
5945
  type: "set_learning_containers",
@@ -5935,9 +5982,9 @@ function useLearningContainers({ threadId, learningContainers }) {
5935
5982
  * }
5936
5983
  * ```
5937
5984
  *
5938
- * @deprecated Legacy plural-container annotation compatibility only. New
5939
- * Intelligence runtimes assign one container with `ɵlearning.containerId` on
5940
- * `CopilotRuntime`.
5985
+ * @deprecated This hook supports only the legacy plural-container annotation.
5986
+ * Configure `getLearningContainerId` on `CopilotKitIntelligence` for new
5987
+ * Intelligence runtimes.
5941
5988
  */
5942
5989
  function useLearningContainersInCurrentThread({ learningContainers }) {
5943
5990
  const threadId = useCopilotChatConfiguration()?.threadId;
@@ -9155,6 +9202,41 @@ const CopilotChatToggleButton = react.default.forwardRef(function CopilotChatTog
9155
9202
  });
9156
9203
  CopilotChatToggleButton.displayName = "CopilotChatToggleButton";
9157
9204
 
9205
+ //#endregion
9206
+ //#region src/v2/components/chat/modal-open-control.tsx
9207
+ const ModalOpenControlContext = (0, react.createContext)({});
9208
+ /**
9209
+ * Carries `open` / `onOpenChange` from a prebuilt surface down to the view that
9210
+ * owns the modal state.
9211
+ *
9212
+ * A context is required rather than plain props because `<CopilotSidebar>`
9213
+ * hands its view to `<CopilotChat>` as a `chatView` **component**. Threading a
9214
+ * value that changes (like `open`) through that component's identity would mint
9215
+ * a new element type on every toggle, and React unmounts and remounts the whole
9216
+ * chat subtree when the element type changes. That is the remount class of bug
9217
+ * already fixed for `<CopilotPopup>` on resize. Context keeps the override
9218
+ * identity stable while still re-rendering the view when `open` changes.
9219
+ */
9220
+ function ModalOpenControlProvider({ open, onOpenChange, children }) {
9221
+ const value = (0, react.useMemo)(() => ({
9222
+ open,
9223
+ onOpenChange
9224
+ }), [open, onOpenChange]);
9225
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModalOpenControlContext.Provider, {
9226
+ value,
9227
+ children
9228
+ });
9229
+ }
9230
+ /**
9231
+ * Reads the controlled open state supplied by the surrounding prebuilt
9232
+ * surface. Returns an empty control (uncontrolled) when there is none.
9233
+ *
9234
+ * @returns The host's `open` / `onOpenChange` pair.
9235
+ */
9236
+ function useModalOpenControl() {
9237
+ return (0, react.useContext)(ModalOpenControlContext);
9238
+ }
9239
+
9158
9240
  //#endregion
9159
9241
  //#region src/v2/components/chat/CopilotModalHeader.tsx
9160
9242
  /**
@@ -9264,15 +9346,22 @@ CopilotModalHeader.DrawerLauncher.displayName = "CopilotModalHeader.DrawerLaunch
9264
9346
  const DEFAULT_SIDEBAR_WIDTH = 480;
9265
9347
  const SIDEBAR_TRANSITION_MS = 260;
9266
9348
  function CopilotSidebarView({ header, toggleButton, width, defaultOpen = true, position = "right", ...props }) {
9349
+ const { open, onOpenChange } = useModalOpenControl();
9350
+ const hasOpenControl = open !== void 0 || onOpenChange !== void 0;
9351
+ const internal = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotSidebarViewInternal, {
9352
+ header,
9353
+ toggleButton,
9354
+ width,
9355
+ position,
9356
+ ...props
9357
+ });
9267
9358
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfigurationProvider, {
9268
- isModalDefaultOpen: defaultOpen,
9269
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotSidebarViewInternal, {
9270
- header,
9271
- toggleButton,
9272
- width,
9273
- position,
9274
- ...props
9275
- })
9359
+ isModalDefaultOpen: open ?? defaultOpen,
9360
+ children: hasOpenControl ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ControlledModalOpenScope, {
9361
+ open,
9362
+ onOpenChange,
9363
+ children: internal
9364
+ }) : internal
9276
9365
  });
9277
9366
  }
9278
9367
  function CopilotSidebarViewInternal({ header, toggleButton, width, position = "right", ...props }) {
@@ -9336,7 +9425,7 @@ function CopilotSidebarViewInternal({ header, toggleButton, width, position = "r
9336
9425
  "data-position": position,
9337
9426
  className: cn("copilotKitSidebar copilotKitWindow", "cpk:fixed cpk:top-0 cpk:z-[1200] cpk:flex", position === "left" ? "cpk:left-0" : "cpk:right-0", "cpk:h-[100vh] cpk:h-[100dvh] cpk:max-h-screen", "cpk:w-full", position === "left" ? "cpk:border-r" : "cpk:border-l", "cpk:border-border cpk:bg-background cpk:text-foreground cpk:shadow-xl", "cpk:transition-transform cpk:duration-300 cpk:ease-out", isSidebarOpen ? "cpk:translate-x-0" : position === "left" ? "cpk:-translate-x-full cpk:pointer-events-none" : "cpk:translate-x-full cpk:pointer-events-none"),
9338
9427
  style: {
9339
- ["--sidebar-width"]: widthToCss(sidebarWidth),
9428
+ "--sidebar-width": widthToCss(sidebarWidth),
9340
9429
  paddingTop: "env(safe-area-inset-top)",
9341
9430
  paddingBottom: "env(safe-area-inset-bottom)"
9342
9431
  },
@@ -9398,17 +9487,24 @@ const dimensionToCss = (value, fallback) => {
9398
9487
  return `${fallback}px`;
9399
9488
  };
9400
9489
  function CopilotPopupView({ header, toggleButton, width, height, clickOutsideToClose, defaultOpen = true, className, ...restProps }) {
9490
+ const { open, onOpenChange } = useModalOpenControl();
9491
+ const hasOpenControl = open !== void 0 || onOpenChange !== void 0;
9492
+ const internal = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotPopupViewInternal, {
9493
+ header,
9494
+ toggleButton,
9495
+ width,
9496
+ height,
9497
+ clickOutsideToClose,
9498
+ className,
9499
+ ...restProps
9500
+ });
9401
9501
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfigurationProvider, {
9402
- isModalDefaultOpen: defaultOpen,
9403
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotPopupViewInternal, {
9404
- header,
9405
- toggleButton,
9406
- width,
9407
- height,
9408
- clickOutsideToClose,
9409
- className,
9410
- ...restProps
9411
- })
9502
+ isModalDefaultOpen: open ?? defaultOpen,
9503
+ children: hasOpenControl ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ControlledModalOpenScope, {
9504
+ open,
9505
+ onOpenChange,
9506
+ children: internal
9507
+ }) : internal
9412
9508
  });
9413
9509
  }
9414
9510
  function CopilotPopupViewInternal({ header, toggleButton, width, height, clickOutsideToClose, className, ...restProps }) {
@@ -9541,7 +9637,7 @@ var CopilotPopupView_default = CopilotPopupView;
9541
9637
 
9542
9638
  //#endregion
9543
9639
  //#region src/v2/components/chat/CopilotSidebar.tsx
9544
- function CopilotSidebar({ header, toggleButton, defaultOpen, width, position, ...chatProps }) {
9640
+ function CopilotSidebar({ header, toggleButton, defaultOpen, open, onOpenChange, width, position, ...chatProps }) {
9545
9641
  const { checkFeature } = (0, _copilotkit_react_core_v2_context.useLicenseContext)();
9546
9642
  const isSidebarLicensed = checkFeature("sidebar");
9547
9643
  (0, react.useEffect)(() => {
@@ -9567,11 +9663,15 @@ function CopilotSidebar({ header, toggleButton, defaultOpen, width, position, ..
9567
9663
  defaultOpen,
9568
9664
  position
9569
9665
  ]);
9570
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [!isSidebarLicensed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InlineFeatureWarning, { featureName: "Sidebar" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChat, {
9571
- welcomeScreen: CopilotSidebarView.WelcomeScreen,
9572
- ...chatProps,
9573
- isModalDefaultOpen: defaultOpen,
9574
- chatView: SidebarViewOverride
9666
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [!isSidebarLicensed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InlineFeatureWarning, { featureName: "Sidebar" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModalOpenControlProvider, {
9667
+ open,
9668
+ onOpenChange,
9669
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChat, {
9670
+ welcomeScreen: CopilotSidebarView.WelcomeScreen,
9671
+ ...chatProps,
9672
+ isModalDefaultOpen: defaultOpen,
9673
+ chatView: SidebarViewOverride
9674
+ })
9575
9675
  })] });
9576
9676
  }
9577
9677
  CopilotSidebar.displayName = "CopilotSidebar";
@@ -9593,7 +9693,7 @@ const PopupViewOverride = (viewProps) => {
9593
9693
  });
9594
9694
  };
9595
9695
  const PopupViewOverrideWithStatics = Object.assign(PopupViewOverride, CopilotChatView_default);
9596
- function CopilotPopup({ header, toggleButton, defaultOpen, width, height, clickOutsideToClose, ...chatProps }) {
9696
+ function CopilotPopup({ header, toggleButton, defaultOpen, open, onOpenChange, width, height, clickOutsideToClose, ...chatProps }) {
9597
9697
  const { checkFeature } = (0, _copilotkit_react_core_v2_context.useLicenseContext)();
9598
9698
  const isPopupLicensed = checkFeature("popup");
9599
9699
  (0, react.useEffect)(() => {
@@ -9616,11 +9716,15 @@ function CopilotPopup({ header, toggleButton, defaultOpen, width, height, clickO
9616
9716
  ]);
9617
9717
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [!isPopupLicensed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InlineFeatureWarning, { featureName: "Popup" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PopupShellPropsContext.Provider, {
9618
9718
  value: shellProps,
9619
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChat, {
9620
- welcomeScreen: CopilotPopupView_default.WelcomeScreen,
9621
- ...chatProps,
9622
- isModalDefaultOpen: defaultOpen,
9623
- chatView: PopupViewOverrideWithStatics
9719
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModalOpenControlProvider, {
9720
+ open,
9721
+ onOpenChange,
9722
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChat, {
9723
+ welcomeScreen: CopilotPopupView_default.WelcomeScreen,
9724
+ ...chatProps,
9725
+ isModalDefaultOpen: defaultOpen,
9726
+ chatView: PopupViewOverrideWithStatics
9727
+ })
9624
9728
  })
9625
9729
  })] });
9626
9730
  }
@@ -10942,7 +11046,7 @@ const getErrorActions = (error) => {
10942
11046
  switch (error.code) {
10943
11047
  case _copilotkit_shared.CopilotKitErrorCode.MISSING_PUBLIC_API_KEY_ERROR: return { primary: {
10944
11048
  label: "Show me how",
10945
- onClick: () => window.open("https://docs.copilotkit.ai/premium/overview#getting-access", "_blank", "noopener,noreferrer")
11049
+ onClick: () => window.open("https://docs.copilotkit.ai/intelligence/overview#plans-and-access", "_blank", "noopener,noreferrer")
10946
11050
  } };
10947
11051
  case _copilotkit_shared.CopilotKitErrorCode.UPGRADE_REQUIRED_ERROR: return { primary: {
10948
11052
  label: "Upgrade",
@@ -12689,4 +12793,4 @@ Object.defineProperty(exports, 'ɵrunMcpFollowUp', {
12689
12793
  return ɵrunMcpFollowUp;
12690
12794
  }
12691
12795
  });
12692
- //# sourceMappingURL=copilotkit-BE76j111.cjs.map
12796
+ //# sourceMappingURL=copilotkit-DcFo270Y.cjs.map