@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.
- package/dist/{copilotkit-CbZGwElm.d.mts → copilotkit--Jyzm6hS.d.mts} +50 -20
- package/dist/copilotkit--Jyzm6hS.d.mts.map +1 -0
- package/dist/{copilotkit-B7aFKfQR.mjs → copilotkit-B1jSvZeb.mjs} +395 -291
- package/dist/copilotkit-B1jSvZeb.mjs.map +1 -0
- package/dist/{copilotkit-BuzP0VeG.d.cts → copilotkit-BLYaCGcz.d.cts} +50 -20
- package/dist/copilotkit-BLYaCGcz.d.cts.map +1 -0
- package/dist/{copilotkit-BE76j111.cjs → copilotkit-DcFo270Y.cjs} +395 -291
- package/dist/copilotkit-DcFo270Y.cjs.map +1 -0
- package/dist/index.cjs +5 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +5 -4
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +198 -207
- package/dist/index.umd.js.map +1 -1
- package/dist/v2/headless.cjs +58 -1
- package/dist/v2/headless.cjs.map +1 -1
- package/dist/v2/headless.mjs +59 -2
- package/dist/v2/headless.mjs.map +1 -1
- package/dist/v2/index.cjs +1 -1
- package/dist/v2/index.css +1 -1
- package/dist/v2/index.d.cts +1 -1
- package/dist/v2/index.d.mts +1 -1
- package/dist/v2/index.mjs +1 -1
- package/dist/v2/index.umd.js +395 -291
- package/dist/v2/index.umd.js.map +1 -1
- package/package.json +11 -8
- package/skills/react-core/SKILL.md +1 -1
- package/skills/react-core/references/attachments.md +20 -0
- package/skills/react-core/references/threads.md +1 -1
- package/dist/copilotkit-B7aFKfQR.mjs.map +0 -1
- package/dist/copilotkit-BE76j111.cjs.map +0 -1
- package/dist/copilotkit-BuzP0VeG.d.cts.map +0 -1
- 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
|
|
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
|
-
|
|
2050
|
-
if (!
|
|
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
|
-
|
|
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
|
-
|
|
2178
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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 ??
|
|
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
|
-
|
|
5675
|
-
|
|
5676
|
-
|
|
5677
|
-
|
|
5678
|
-
|
|
5679
|
-
|
|
5680
|
-
|
|
5681
|
-
|
|
5682
|
-
|
|
5683
|
-
|
|
5684
|
-
|
|
5685
|
-
|
|
5686
|
-
|
|
5687
|
-
|
|
5688
|
-
|
|
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
|
|
5833
|
-
*
|
|
5834
|
-
*
|
|
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
|
|
5939
|
-
*
|
|
5940
|
-
*
|
|
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)(
|
|
9270
|
-
|
|
9271
|
-
|
|
9272
|
-
|
|
9273
|
-
|
|
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
|
-
|
|
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)(
|
|
9404
|
-
|
|
9405
|
-
|
|
9406
|
-
|
|
9407
|
-
|
|
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)(
|
|
9571
|
-
|
|
9572
|
-
|
|
9573
|
-
|
|
9574
|
-
|
|
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)(
|
|
9620
|
-
|
|
9621
|
-
|
|
9622
|
-
|
|
9623
|
-
|
|
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/
|
|
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-
|
|
12796
|
+
//# sourceMappingURL=copilotkit-DcFo270Y.cjs.map
|