@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
|
@@ -268,6 +268,62 @@ const CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId,
|
|
|
268
268
|
const useCopilotChatConfiguration = () => {
|
|
269
269
|
return useContext(CopilotChatConfiguration);
|
|
270
270
|
};
|
|
271
|
+
/**
|
|
272
|
+
* Reports modal open/close requests to the host, and — when `open` is
|
|
273
|
+
* supplied — makes the modal state of an already-established chat
|
|
274
|
+
* configuration **controlled** for the subtree it wraps.
|
|
275
|
+
*
|
|
276
|
+
* This is deliberately a scope component rather than another mode inside
|
|
277
|
+
* {@link CopilotChatConfigurationProvider}. The provider resolves modal state
|
|
278
|
+
* across a nested chain (own state, parent sync, drawer mutual-exclusion, the
|
|
279
|
+
* modal-closer registry); a controlled branch inside that resolution would add
|
|
280
|
+
* a fourth interacting mode. Overriding the context for the subtree instead
|
|
281
|
+
* leaves every one of those paths untouched:
|
|
282
|
+
*
|
|
283
|
+
* - `isModalOpen` is replaced with the host's `open`, so the rendered surface
|
|
284
|
+
* follows the prop from the very first frame (no open-then-close flash).
|
|
285
|
+
* - `setModalOpen` still calls the underlying setter, so the existing
|
|
286
|
+
* parent-sync and drawer mutual-exclusion side effects continue to run, and
|
|
287
|
+
* *then* reports the request through `onOpenChange`.
|
|
288
|
+
* - The wrapped setter is registered as the modal closer, so the drawer's
|
|
289
|
+
* mobile mutual-exclusion reaches the host instead of silently flipping
|
|
290
|
+
* state that nothing displays.
|
|
291
|
+
*
|
|
292
|
+
* A host that supplies `open` and ignores `onOpenChange` gets a modal pinned
|
|
293
|
+
* to `open`, which is the standard controlled-component contract. A host that
|
|
294
|
+
* supplies only `onOpenChange` is notified while the modal keeps managing
|
|
295
|
+
* itself.
|
|
296
|
+
*
|
|
297
|
+
* Renders `children` unchanged when no chat configuration is in scope.
|
|
298
|
+
*/
|
|
299
|
+
const ControlledModalOpenScope = ({ children, open, onOpenChange }) => {
|
|
300
|
+
const parentConfig = useContext(CopilotChatConfiguration);
|
|
301
|
+
const parentSetModalOpen = parentConfig?.setModalOpen;
|
|
302
|
+
const registerModalCloser = parentConfig?.ɵregisterModalCloser;
|
|
303
|
+
const setModalOpen = useCallback((next) => {
|
|
304
|
+
parentSetModalOpen?.(next);
|
|
305
|
+
onOpenChange?.(next);
|
|
306
|
+
}, [parentSetModalOpen, onOpenChange]);
|
|
307
|
+
useEffect(() => {
|
|
308
|
+
if (!registerModalCloser) return;
|
|
309
|
+
return registerModalCloser(setModalOpen);
|
|
310
|
+
}, [registerModalCloser, setModalOpen]);
|
|
311
|
+
const configurationValue = useMemo(() => parentConfig ? {
|
|
312
|
+
...parentConfig,
|
|
313
|
+
isModalOpen: open ?? parentConfig.isModalOpen,
|
|
314
|
+
setModalOpen
|
|
315
|
+
} : null, [
|
|
316
|
+
parentConfig,
|
|
317
|
+
open,
|
|
318
|
+
setModalOpen
|
|
319
|
+
]);
|
|
320
|
+
if (!configurationValue) return /* @__PURE__ */ jsx(Fragment$1, { children });
|
|
321
|
+
return /* @__PURE__ */ jsx(CopilotChatConfiguration.Provider, {
|
|
322
|
+
value: configurationValue,
|
|
323
|
+
children
|
|
324
|
+
});
|
|
325
|
+
};
|
|
326
|
+
ControlledModalOpenScope.displayName = "ControlledModalOpenScope";
|
|
271
327
|
|
|
272
328
|
//#endregion
|
|
273
329
|
//#region src/v2/lib/utils.ts
|
|
@@ -1735,7 +1791,6 @@ async function ɵrunMcpFollowUp({ host, agent, capturedThreadId }) {
|
|
|
1735
1791
|
newMessages: []
|
|
1736
1792
|
};
|
|
1737
1793
|
}
|
|
1738
|
-
const PROTOCOL_VERSION = "2025-06-18";
|
|
1739
1794
|
function buildSandboxHTML(extraCspDomains) {
|
|
1740
1795
|
const baseScriptSrc = "'self' 'wasm-unsafe-eval' 'unsafe-inline' 'unsafe-eval' blob: data: http://localhost:* https://localhost:*";
|
|
1741
1796
|
const baseFrameSrc = "* blob: data: http://localhost:* https://localhost:*";
|
|
@@ -1847,6 +1902,13 @@ var MCPAppsRequestQueue = class {
|
|
|
1847
1902
|
}
|
|
1848
1903
|
};
|
|
1849
1904
|
const mcpAppsRequestQueue = new MCPAppsRequestQueue();
|
|
1905
|
+
const MCP_OPEN_LINK_BLOCKED_SCHEMES = new Set([
|
|
1906
|
+
"javascript:",
|
|
1907
|
+
"data:",
|
|
1908
|
+
"vbscript:",
|
|
1909
|
+
"blob:",
|
|
1910
|
+
"file:"
|
|
1911
|
+
]);
|
|
1850
1912
|
/**
|
|
1851
1913
|
* Activity type for MCP Apps events - must match the middleware's MCPAppsActivityType
|
|
1852
1914
|
*/
|
|
@@ -1862,18 +1924,32 @@ const MCPAppsActivityContentSchema = z.object({
|
|
|
1862
1924
|
serverId: z.string().optional(),
|
|
1863
1925
|
toolInput: z.record(z.string(), z.unknown()).optional()
|
|
1864
1926
|
});
|
|
1865
|
-
function isRequest(msg) {
|
|
1866
|
-
return "id" in msg && "method" in msg;
|
|
1867
|
-
}
|
|
1868
|
-
function isNotification(msg) {
|
|
1869
|
-
return !("id" in msg) && "method" in msg;
|
|
1870
|
-
}
|
|
1871
1927
|
/**
|
|
1872
1928
|
* MCP Apps Extension Activity Renderer
|
|
1873
1929
|
*
|
|
1874
1930
|
* Renders MCP Apps UI in a sandboxed iframe with full protocol support.
|
|
1875
1931
|
* Fetches resource content on-demand via proxied MCP requests.
|
|
1876
1932
|
*/
|
|
1933
|
+
/**
|
|
1934
|
+
* Permissive `ui/message` schema. ext-apps restricts the request to
|
|
1935
|
+
* `role: "user"` with no `followUp`, but CopilotKit intentionally extends
|
|
1936
|
+
* `ui/message` with `role` ("user" | "assistant") and `followUp` (documented
|
|
1937
|
+
* behavior with dedicated tests). We register our own handler (instead of the
|
|
1938
|
+
* bridge's strict `onmessage`) so those extensions survive the migration.
|
|
1939
|
+
*
|
|
1940
|
+
* Going forward, widgets SHOULD pass the extensions under
|
|
1941
|
+
* `params._meta.copilotkit`; the top-level `role`/`followUp` fields are the
|
|
1942
|
+
* legacy channel, kept for backward compatibility and slated for deprecation.
|
|
1943
|
+
*/
|
|
1944
|
+
const CopilotKitUiMessageSchema = z.object({
|
|
1945
|
+
method: z.literal("ui/message"),
|
|
1946
|
+
params: z.object({
|
|
1947
|
+
role: z.string().optional(),
|
|
1948
|
+
content: z.array(z.any()).optional(),
|
|
1949
|
+
followUp: z.boolean().optional(),
|
|
1950
|
+
_meta: z.record(z.string(), z.any()).optional()
|
|
1951
|
+
}).passthrough()
|
|
1952
|
+
});
|
|
1877
1953
|
const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, agent }) {
|
|
1878
1954
|
const { copilotkit } = useCopilotKit$1();
|
|
1879
1955
|
const containerRef = useRef(null);
|
|
@@ -1887,41 +1963,12 @@ const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, agen
|
|
|
1887
1963
|
contentRef.current = content;
|
|
1888
1964
|
const agentRef = useRef(agent);
|
|
1889
1965
|
agentRef.current = agent;
|
|
1966
|
+
const bridgeRef = useRef(null);
|
|
1890
1967
|
const fetchStateRef = useRef({
|
|
1891
1968
|
inProgress: false,
|
|
1892
1969
|
promise: null,
|
|
1893
1970
|
resourceUri: null
|
|
1894
1971
|
});
|
|
1895
|
-
const sendToIframe = useCallback((msg) => {
|
|
1896
|
-
if (iframeRef.current?.contentWindow) {
|
|
1897
|
-
console.log("[MCPAppsRenderer] Sending to iframe:", msg);
|
|
1898
|
-
iframeRef.current.contentWindow.postMessage(msg, "*");
|
|
1899
|
-
}
|
|
1900
|
-
}, []);
|
|
1901
|
-
const sendResponse = useCallback((id, result) => {
|
|
1902
|
-
sendToIframe({
|
|
1903
|
-
jsonrpc: "2.0",
|
|
1904
|
-
id,
|
|
1905
|
-
result
|
|
1906
|
-
});
|
|
1907
|
-
}, [sendToIframe]);
|
|
1908
|
-
const sendErrorResponse = useCallback((id, code, message) => {
|
|
1909
|
-
sendToIframe({
|
|
1910
|
-
jsonrpc: "2.0",
|
|
1911
|
-
id,
|
|
1912
|
-
error: {
|
|
1913
|
-
code,
|
|
1914
|
-
message
|
|
1915
|
-
}
|
|
1916
|
-
});
|
|
1917
|
-
}, [sendToIframe]);
|
|
1918
|
-
const sendNotification = useCallback((method, params) => {
|
|
1919
|
-
sendToIframe({
|
|
1920
|
-
jsonrpc: "2.0",
|
|
1921
|
-
method,
|
|
1922
|
-
params: params || {}
|
|
1923
|
-
});
|
|
1924
|
-
}, [sendToIframe]);
|
|
1925
1972
|
useEffect(() => {
|
|
1926
1973
|
const { resourceUri, serverHash, serverId } = content;
|
|
1927
1974
|
if (fetchStateRef.current.inProgress && fetchStateRef.current.resourceUri === resourceUri) {
|
|
@@ -1976,11 +2023,15 @@ const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, agen
|
|
|
1976
2023
|
const container = containerRef.current;
|
|
1977
2024
|
if (!container) return;
|
|
1978
2025
|
let mounted = true;
|
|
1979
|
-
let
|
|
1980
|
-
let initialListener = null;
|
|
2026
|
+
let bridge = null;
|
|
1981
2027
|
let createdIframe = null;
|
|
1982
2028
|
const setup = async () => {
|
|
1983
2029
|
try {
|
|
2030
|
+
const bridgeModule = await import("@modelcontextprotocol/ext-apps/app-bridge").catch((importErr) => {
|
|
2031
|
+
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 });
|
|
2032
|
+
});
|
|
2033
|
+
if (!mounted) return;
|
|
2034
|
+
const { AppBridge, PostMessageTransport } = bridgeModule;
|
|
1984
2035
|
const iframe = document.createElement("iframe");
|
|
1985
2036
|
createdIframe = iframe;
|
|
1986
2037
|
iframe.style.width = "100%";
|
|
@@ -1991,151 +2042,108 @@ const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, agen
|
|
|
1991
2042
|
iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms");
|
|
1992
2043
|
iframe.setAttribute("data-testid", "mcp-app-iframe");
|
|
1993
2044
|
iframe.setAttribute("title", "Interactive MCP application");
|
|
1994
|
-
const sandboxReady = new Promise((resolve) => {
|
|
1995
|
-
initialListener = (event) => {
|
|
1996
|
-
if (event.source === iframe.contentWindow) {
|
|
1997
|
-
if (event.data?.method === "ui/notifications/sandbox-proxy-ready") {
|
|
1998
|
-
if (initialListener) {
|
|
1999
|
-
window.removeEventListener("message", initialListener);
|
|
2000
|
-
initialListener = null;
|
|
2001
|
-
}
|
|
2002
|
-
resolve();
|
|
2003
|
-
}
|
|
2004
|
-
}
|
|
2005
|
-
};
|
|
2006
|
-
window.addEventListener("message", initialListener);
|
|
2007
|
-
});
|
|
2008
|
-
if (!mounted) {
|
|
2009
|
-
if (initialListener) {
|
|
2010
|
-
window.removeEventListener("message", initialListener);
|
|
2011
|
-
initialListener = null;
|
|
2012
|
-
}
|
|
2013
|
-
return;
|
|
2014
|
-
}
|
|
2015
2045
|
const cspDomains = fetchedResource._meta?.ui?.csp?.resourceDomains;
|
|
2016
2046
|
iframe.srcdoc = buildSandboxHTML(cspDomains);
|
|
2017
2047
|
iframeRef.current = iframe;
|
|
2018
2048
|
container.appendChild(iframe);
|
|
2019
|
-
|
|
2020
|
-
if (!
|
|
2021
|
-
console.log("[MCPAppsRenderer] Sandbox proxy ready");
|
|
2022
|
-
messageHandler = async (event) => {
|
|
2023
|
-
if (event.source !== iframe.contentWindow) return;
|
|
2024
|
-
const msg = event.data;
|
|
2025
|
-
if (!msg || typeof msg !== "object" || msg.jsonrpc !== "2.0") return;
|
|
2026
|
-
console.log("[MCPAppsRenderer] Received from iframe:", msg);
|
|
2027
|
-
if (isRequest(msg)) switch (msg.method) {
|
|
2028
|
-
case "ui/initialize":
|
|
2029
|
-
sendResponse(msg.id, {
|
|
2030
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
2031
|
-
hostInfo: {
|
|
2032
|
-
name: "CopilotKit MCP Apps Host",
|
|
2033
|
-
version: "1.0.0"
|
|
2034
|
-
},
|
|
2035
|
-
hostCapabilities: {
|
|
2036
|
-
openLinks: {},
|
|
2037
|
-
logging: {}
|
|
2038
|
-
},
|
|
2039
|
-
hostContext: {
|
|
2040
|
-
theme: "light",
|
|
2041
|
-
platform: "web"
|
|
2042
|
-
}
|
|
2043
|
-
});
|
|
2044
|
-
break;
|
|
2045
|
-
case "ui/message": {
|
|
2046
|
-
const currentAgent = agentRef.current;
|
|
2047
|
-
if (!currentAgent) {
|
|
2048
|
-
console.warn("[MCPAppsRenderer] ui/message: No agent available");
|
|
2049
|
-
sendResponse(msg.id, { isError: false });
|
|
2050
|
-
break;
|
|
2051
|
-
}
|
|
2052
|
-
try {
|
|
2053
|
-
const params = msg.params;
|
|
2054
|
-
const role = params.role || "user";
|
|
2055
|
-
const textContent = params.content?.filter((c) => c.type === "text" && c.text).map((c) => c.text).join("\n") || "";
|
|
2056
|
-
if (textContent) currentAgent.addMessage({
|
|
2057
|
-
id: crypto.randomUUID(),
|
|
2058
|
-
role,
|
|
2059
|
-
content: textContent
|
|
2060
|
-
});
|
|
2061
|
-
sendResponse(msg.id, { isError: false });
|
|
2062
|
-
if ((params.followUp ?? role === "user") && textContent) {
|
|
2063
|
-
const capturedThreadId = currentAgent.threadId || "default";
|
|
2064
|
-
mcpAppsRequestQueue.enqueue(currentAgent, () => ɵrunMcpFollowUp({
|
|
2065
|
-
host: copilotkit,
|
|
2066
|
-
agent: currentAgent,
|
|
2067
|
-
capturedThreadId
|
|
2068
|
-
})).catch((err) => console.error("[MCPAppsRenderer] ui/message agent run failed:", err));
|
|
2069
|
-
}
|
|
2070
|
-
} catch (err) {
|
|
2071
|
-
console.error("[MCPAppsRenderer] ui/message error:", err);
|
|
2072
|
-
sendResponse(msg.id, { isError: true });
|
|
2073
|
-
}
|
|
2074
|
-
break;
|
|
2075
|
-
}
|
|
2076
|
-
case "ui/open-link": {
|
|
2077
|
-
const url = msg.params?.url;
|
|
2078
|
-
if (url) {
|
|
2079
|
-
window.open(url, "_blank", "noopener,noreferrer");
|
|
2080
|
-
sendResponse(msg.id, { isError: false });
|
|
2081
|
-
} else sendErrorResponse(msg.id, -32602, "Missing url parameter");
|
|
2082
|
-
break;
|
|
2083
|
-
}
|
|
2084
|
-
case "tools/call": {
|
|
2085
|
-
const { serverHash, serverId } = contentRef.current;
|
|
2086
|
-
const currentAgent = agentRef.current;
|
|
2087
|
-
if (!serverHash) {
|
|
2088
|
-
sendErrorResponse(msg.id, -32603, "No server hash available for proxying");
|
|
2089
|
-
break;
|
|
2090
|
-
}
|
|
2091
|
-
if (!currentAgent) {
|
|
2092
|
-
sendErrorResponse(msg.id, -32603, "No agent available for proxying");
|
|
2093
|
-
break;
|
|
2094
|
-
}
|
|
2095
|
-
try {
|
|
2096
|
-
const runResult = await mcpAppsRequestQueue.enqueue(currentAgent, () => currentAgent.runAgent({ forwardedProps: { __proxiedMCPRequest: {
|
|
2097
|
-
serverHash,
|
|
2098
|
-
serverId,
|
|
2099
|
-
method: "tools/call",
|
|
2100
|
-
params: msg.params
|
|
2101
|
-
} } }));
|
|
2102
|
-
sendResponse(msg.id, runResult.result || {});
|
|
2103
|
-
} catch (err) {
|
|
2104
|
-
console.error("[MCPAppsRenderer] tools/call error:", err);
|
|
2105
|
-
sendErrorResponse(msg.id, -32603, String(err));
|
|
2106
|
-
}
|
|
2107
|
-
break;
|
|
2108
|
-
}
|
|
2109
|
-
default: sendErrorResponse(msg.id, -32601, `Method not found: ${msg.method}`);
|
|
2110
|
-
}
|
|
2111
|
-
if (isNotification(msg)) switch (msg.method) {
|
|
2112
|
-
case "ui/notifications/initialized":
|
|
2113
|
-
console.log("[MCPAppsRenderer] Inner iframe initialized");
|
|
2114
|
-
if (mounted) setIframeReady(true);
|
|
2115
|
-
break;
|
|
2116
|
-
case "ui/notifications/size-changed": {
|
|
2117
|
-
const { width, height } = msg.params || {};
|
|
2118
|
-
console.log("[MCPAppsRenderer] Size change:", {
|
|
2119
|
-
width,
|
|
2120
|
-
height
|
|
2121
|
-
});
|
|
2122
|
-
if (mounted) setIframeSize({
|
|
2123
|
-
width: typeof width === "number" ? width : void 0,
|
|
2124
|
-
height: typeof height === "number" ? height : void 0
|
|
2125
|
-
});
|
|
2126
|
-
break;
|
|
2127
|
-
}
|
|
2128
|
-
case "notifications/message":
|
|
2129
|
-
console.log("[MCPAppsRenderer] App log:", msg.params);
|
|
2130
|
-
break;
|
|
2131
|
-
}
|
|
2132
|
-
};
|
|
2133
|
-
window.addEventListener("message", messageHandler);
|
|
2049
|
+
const win = iframe.contentWindow;
|
|
2050
|
+
if (!win) throw new Error("Sandbox iframe has no contentWindow");
|
|
2134
2051
|
let html;
|
|
2135
2052
|
if (fetchedResource.text) html = fetchedResource.text;
|
|
2136
2053
|
else if (fetchedResource.blob) html = atob(fetchedResource.blob);
|
|
2137
2054
|
else throw new Error("Resource has no text or blob content");
|
|
2138
|
-
|
|
2055
|
+
bridge = new AppBridge(null, {
|
|
2056
|
+
name: "CopilotKit MCP Apps Host",
|
|
2057
|
+
version: "1.0.0"
|
|
2058
|
+
}, {
|
|
2059
|
+
openLinks: {},
|
|
2060
|
+
logging: {},
|
|
2061
|
+
message: { text: {} }
|
|
2062
|
+
}, { hostContext: {
|
|
2063
|
+
theme: "light",
|
|
2064
|
+
platform: "web"
|
|
2065
|
+
} });
|
|
2066
|
+
bridge.onsandboxready = () => {
|
|
2067
|
+
bridge?.sendSandboxResourceReady({ html });
|
|
2068
|
+
};
|
|
2069
|
+
bridge.setRequestHandler(CopilotKitUiMessageSchema, async (req) => {
|
|
2070
|
+
const currentAgent = agentRef.current;
|
|
2071
|
+
if (!currentAgent) {
|
|
2072
|
+
console.warn("[MCPAppsRenderer] ui/message: No agent available");
|
|
2073
|
+
return { isError: false };
|
|
2074
|
+
}
|
|
2075
|
+
try {
|
|
2076
|
+
const params = req.params;
|
|
2077
|
+
const ck = params._meta?.copilotkit ?? {};
|
|
2078
|
+
const role = ck.role || params.role || "user";
|
|
2079
|
+
const textContent = params.content?.filter((c) => c.type === "text" && c.text).map((c) => c.text).join("\n") || "";
|
|
2080
|
+
if (textContent) currentAgent.addMessage({
|
|
2081
|
+
id: crypto.randomUUID(),
|
|
2082
|
+
role,
|
|
2083
|
+
content: textContent
|
|
2084
|
+
});
|
|
2085
|
+
if ((ck.followUp ?? params.followUp ?? role === "user") && textContent) {
|
|
2086
|
+
const capturedThreadId = currentAgent.threadId || "default";
|
|
2087
|
+
mcpAppsRequestQueue.enqueue(currentAgent, () => ɵrunMcpFollowUp({
|
|
2088
|
+
host: copilotkit,
|
|
2089
|
+
agent: currentAgent,
|
|
2090
|
+
capturedThreadId
|
|
2091
|
+
})).catch((err) => console.error("[MCPAppsRenderer] ui/message agent run failed:", err));
|
|
2092
|
+
}
|
|
2093
|
+
return { isError: false };
|
|
2094
|
+
} catch (err) {
|
|
2095
|
+
console.error("[MCPAppsRenderer] ui/message error:", err);
|
|
2096
|
+
return { isError: true };
|
|
2097
|
+
}
|
|
2098
|
+
});
|
|
2099
|
+
bridge.onopenlink = async ({ url }) => {
|
|
2100
|
+
let parsed;
|
|
2101
|
+
try {
|
|
2102
|
+
parsed = new URL(url);
|
|
2103
|
+
} catch {
|
|
2104
|
+
console.warn("[MCPAppsRenderer] ui/open-link rejected: unparseable url");
|
|
2105
|
+
return { isError: true };
|
|
2106
|
+
}
|
|
2107
|
+
if (MCP_OPEN_LINK_BLOCKED_SCHEMES.has(parsed.protocol)) {
|
|
2108
|
+
console.warn("[MCPAppsRenderer] ui/open-link rejected: blocked scheme", parsed.protocol);
|
|
2109
|
+
return { isError: true };
|
|
2110
|
+
}
|
|
2111
|
+
window.open(url, "_blank", "noopener,noreferrer");
|
|
2112
|
+
return { isError: false };
|
|
2113
|
+
};
|
|
2114
|
+
bridge.oncalltool = async (params) => {
|
|
2115
|
+
const { serverHash, serverId } = contentRef.current;
|
|
2116
|
+
const currentAgent = agentRef.current;
|
|
2117
|
+
if (!serverHash) throw new Error("No server hash available for proxying");
|
|
2118
|
+
if (!currentAgent) throw new Error("No agent available for proxying");
|
|
2119
|
+
return (await mcpAppsRequestQueue.enqueue(currentAgent, () => currentAgent.runAgent({ forwardedProps: { __proxiedMCPRequest: {
|
|
2120
|
+
serverHash,
|
|
2121
|
+
serverId,
|
|
2122
|
+
method: "tools/call",
|
|
2123
|
+
params
|
|
2124
|
+
} } }))).result || { content: [] };
|
|
2125
|
+
};
|
|
2126
|
+
bridge.onsizechange = (p) => {
|
|
2127
|
+
if (!mounted) return;
|
|
2128
|
+
const { width, height } = p || {};
|
|
2129
|
+
setIframeSize({
|
|
2130
|
+
width: typeof width === "number" ? width : void 0,
|
|
2131
|
+
height: typeof height === "number" ? height : void 0
|
|
2132
|
+
});
|
|
2133
|
+
};
|
|
2134
|
+
bridge.oninitialized = () => {
|
|
2135
|
+
if (mounted) setIframeReady(true);
|
|
2136
|
+
};
|
|
2137
|
+
bridge.onloggingmessage = (p) => {
|
|
2138
|
+
console.log("[MCPAppsRenderer] App log:", p);
|
|
2139
|
+
};
|
|
2140
|
+
const transport = new PostMessageTransport(win, win);
|
|
2141
|
+
await bridge.connect(transport);
|
|
2142
|
+
if (!mounted) {
|
|
2143
|
+
await bridge.close();
|
|
2144
|
+
return;
|
|
2145
|
+
}
|
|
2146
|
+
bridgeRef.current = bridge;
|
|
2139
2147
|
} catch (err) {
|
|
2140
2148
|
console.error("[MCPAppsRenderer] Setup error:", err);
|
|
2141
2149
|
if (mounted) setError(err instanceof Error ? err : new Error(String(err)));
|
|
@@ -2144,11 +2152,8 @@ const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, agen
|
|
|
2144
2152
|
setup();
|
|
2145
2153
|
return () => {
|
|
2146
2154
|
mounted = false;
|
|
2147
|
-
|
|
2148
|
-
|
|
2149
|
-
initialListener = null;
|
|
2150
|
-
}
|
|
2151
|
-
if (messageHandler) window.removeEventListener("message", messageHandler);
|
|
2155
|
+
bridgeRef.current = null;
|
|
2156
|
+
bridge?.close();
|
|
2152
2157
|
if (createdIframe) {
|
|
2153
2158
|
createdIframe.remove();
|
|
2154
2159
|
createdIframe = null;
|
|
@@ -2158,9 +2163,7 @@ const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, agen
|
|
|
2158
2163
|
}, [
|
|
2159
2164
|
isLoading,
|
|
2160
2165
|
fetchedResource,
|
|
2161
|
-
|
|
2162
|
-
sendResponse,
|
|
2163
|
-
sendErrorResponse
|
|
2166
|
+
copilotkit
|
|
2164
2167
|
]);
|
|
2165
2168
|
useEffect(() => {
|
|
2166
2169
|
if (iframeRef.current) {
|
|
@@ -2172,25 +2175,11 @@ const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, agen
|
|
|
2172
2175
|
}
|
|
2173
2176
|
}, [iframeSize]);
|
|
2174
2177
|
useEffect(() => {
|
|
2175
|
-
if (iframeReady && content.toolInput) {
|
|
2176
|
-
|
|
2177
|
-
sendNotification("ui/notifications/tool-input", { arguments: content.toolInput });
|
|
2178
|
-
}
|
|
2179
|
-
}, [
|
|
2180
|
-
iframeReady,
|
|
2181
|
-
content.toolInput,
|
|
2182
|
-
sendNotification
|
|
2183
|
-
]);
|
|
2178
|
+
if (iframeReady && content.toolInput) bridgeRef.current?.sendToolInput({ arguments: content.toolInput });
|
|
2179
|
+
}, [iframeReady, content.toolInput]);
|
|
2184
2180
|
useEffect(() => {
|
|
2185
|
-
if (iframeReady && content.result)
|
|
2186
|
-
|
|
2187
|
-
sendNotification("ui/notifications/tool-result", content.result);
|
|
2188
|
-
}
|
|
2189
|
-
}, [
|
|
2190
|
-
iframeReady,
|
|
2191
|
-
content.result,
|
|
2192
|
-
sendNotification
|
|
2193
|
-
]);
|
|
2181
|
+
if (iframeReady && content.result) bridgeRef.current?.sendToolResult(content.result);
|
|
2182
|
+
}, [iframeReady, content.result]);
|
|
2194
2183
|
const borderStyle = fetchedResource?._meta?.ui?.prefersBorder === true ? {
|
|
2195
2184
|
borderRadius: "8px",
|
|
2196
2185
|
backgroundColor: "#f9f9f9",
|
|
@@ -4005,7 +3994,8 @@ function useFrontendTool(tool, deps) {
|
|
|
4005
3994
|
tool.name,
|
|
4006
3995
|
tool.available,
|
|
4007
3996
|
copilotkit,
|
|
4008
|
-
JSON.stringify(extraDeps)
|
|
3997
|
+
JSON.stringify(extraDeps),
|
|
3998
|
+
JSON.stringify(tool.webmcp ?? null)
|
|
4009
3999
|
]);
|
|
4010
4000
|
}
|
|
4011
4001
|
|
|
@@ -5460,7 +5450,7 @@ function useMemories() {
|
|
|
5460
5450
|
* at the call site.
|
|
5461
5451
|
*/
|
|
5462
5452
|
async function recordAnnotation(args) {
|
|
5463
|
-
const { runtimeUrl, headers, type, payload, threadId, occurredAt } = args;
|
|
5453
|
+
const { runtimeUrl, headers, type, payload, threadId, occurredAt, fetch: fetchImplementation = globalThis.fetch } = args;
|
|
5464
5454
|
const body = {
|
|
5465
5455
|
type,
|
|
5466
5456
|
threadId,
|
|
@@ -5468,7 +5458,7 @@ async function recordAnnotation(args) {
|
|
|
5468
5458
|
...payload !== void 0 ? { payload } : {},
|
|
5469
5459
|
...occurredAt !== void 0 ? { occurredAt } : {}
|
|
5470
5460
|
};
|
|
5471
|
-
const response = await
|
|
5461
|
+
const response = await fetchImplementation(`${runtimeUrl}/annotate`, {
|
|
5472
5462
|
method: "POST",
|
|
5473
5463
|
headers: {
|
|
5474
5464
|
"Content-Type": "application/json",
|
|
@@ -5537,6 +5527,7 @@ function useLearnFromUserAction() {
|
|
|
5537
5527
|
...input.data !== void 0 ? { data: input.data } : {}
|
|
5538
5528
|
};
|
|
5539
5529
|
return recordAnnotation({
|
|
5530
|
+
fetch: copilotkit.ɵruntimeFetch,
|
|
5540
5531
|
runtimeUrl,
|
|
5541
5532
|
headers: copilotkit.headers ?? {},
|
|
5542
5533
|
type: "user_action",
|
|
@@ -5606,6 +5597,21 @@ function useLearnFromUserActionInCurrentThread() {
|
|
|
5606
5597
|
|
|
5607
5598
|
//#endregion
|
|
5608
5599
|
//#region src/v2/hooks/use-attachments.tsx
|
|
5600
|
+
const DEFAULT_MAX_SIZE = 20 * 1024 * 1024;
|
|
5601
|
+
/**
|
|
5602
|
+
* How many uploads run at once when `maxConcurrentUploads` is unset. One, because
|
|
5603
|
+
* `onUpload` is a public callback an app may have written expecting the previous
|
|
5604
|
+
* file to have finished — concurrency is something the app asks for.
|
|
5605
|
+
*/
|
|
5606
|
+
const DEFAULT_MAX_CONCURRENT_UPLOADS = 1;
|
|
5607
|
+
/**
|
|
5608
|
+
* At least one upload at a time, whole files only; `NaN` or a non-number falls back to the
|
|
5609
|
+
* default, and `Infinity` means "no limit" — bounded in practice by how many files are queued.
|
|
5610
|
+
*/
|
|
5611
|
+
function resolveMaxConcurrentUploads(configured) {
|
|
5612
|
+
if (typeof configured !== "number" || Number.isNaN(configured)) return DEFAULT_MAX_CONCURRENT_UPLOADS;
|
|
5613
|
+
return Math.max(1, Math.floor(configured));
|
|
5614
|
+
}
|
|
5609
5615
|
/**
|
|
5610
5616
|
* Hook that manages file attachment state — uploads, drag-and-drop, paste,
|
|
5611
5617
|
* and lifecycle. All returned callbacks are referentially stable across
|
|
@@ -5621,10 +5627,62 @@ function useAttachments({ config }) {
|
|
|
5621
5627
|
configRef.current = config;
|
|
5622
5628
|
const attachmentsRef = useRef([]);
|
|
5623
5629
|
attachmentsRef.current = attachments;
|
|
5630
|
+
const uploadQueueRef = useRef([]);
|
|
5631
|
+
const activeWorkersRef = useRef(0);
|
|
5632
|
+
const uploadFile = useCallback(async (file, placeholder, cfg) => {
|
|
5633
|
+
try {
|
|
5634
|
+
let source;
|
|
5635
|
+
let uploadMetadata;
|
|
5636
|
+
if (cfg?.onUpload) {
|
|
5637
|
+
const { metadata: meta, ...uploadSource } = await cfg.onUpload(file);
|
|
5638
|
+
source = uploadSource;
|
|
5639
|
+
uploadMetadata = meta;
|
|
5640
|
+
} else source = {
|
|
5641
|
+
type: "data",
|
|
5642
|
+
value: await readFileAsBase64(file),
|
|
5643
|
+
mimeType: file.type
|
|
5644
|
+
};
|
|
5645
|
+
let thumbnail;
|
|
5646
|
+
if (placeholder.type === "video") thumbnail = await generateVideoThumbnail(file);
|
|
5647
|
+
setAttachments((prev) => prev.map((att) => att.id === placeholder.id ? {
|
|
5648
|
+
...att,
|
|
5649
|
+
source,
|
|
5650
|
+
status: "ready",
|
|
5651
|
+
thumbnail,
|
|
5652
|
+
metadata: uploadMetadata
|
|
5653
|
+
} : att));
|
|
5654
|
+
} catch (error) {
|
|
5655
|
+
setAttachments((prev) => prev.filter((att) => att.id !== placeholder.id));
|
|
5656
|
+
console.error(`[CopilotKit] Failed to upload "${file.name}":`, error);
|
|
5657
|
+
cfg?.onUploadFailed?.({
|
|
5658
|
+
reason: "upload-failed",
|
|
5659
|
+
file,
|
|
5660
|
+
message: error instanceof Error ? error.message : `Failed to upload "${file.name}"`
|
|
5661
|
+
});
|
|
5662
|
+
}
|
|
5663
|
+
}, []);
|
|
5664
|
+
const drainUploadQueue = useCallback(async () => {
|
|
5665
|
+
activeWorkersRef.current++;
|
|
5666
|
+
try {
|
|
5667
|
+
for (;;) {
|
|
5668
|
+
const item = uploadQueueRef.current.shift();
|
|
5669
|
+
if (!item) return;
|
|
5670
|
+
try {
|
|
5671
|
+
await uploadFile(item.file, item.placeholder, item.cfg);
|
|
5672
|
+
} catch (error) {
|
|
5673
|
+
console.error("[CopilotKit] Upload worker error:", error);
|
|
5674
|
+
} finally {
|
|
5675
|
+
item.settle();
|
|
5676
|
+
}
|
|
5677
|
+
}
|
|
5678
|
+
} finally {
|
|
5679
|
+
activeWorkersRef.current--;
|
|
5680
|
+
}
|
|
5681
|
+
}, [uploadFile]);
|
|
5624
5682
|
const processFiles = useCallback(async (files) => {
|
|
5625
5683
|
const cfg = configRef.current;
|
|
5626
5684
|
const accept = cfg?.accept ?? "*/*";
|
|
5627
|
-
const maxSize = cfg?.maxSize ??
|
|
5685
|
+
const maxSize = cfg?.maxSize ?? DEFAULT_MAX_SIZE;
|
|
5628
5686
|
const rejectedFiles = files.filter((file) => !matchesAcceptFilter(file, accept));
|
|
5629
5687
|
for (const file of rejectedFiles) cfg?.onUploadFailed?.({
|
|
5630
5688
|
reason: "invalid-type",
|
|
@@ -5632,6 +5690,7 @@ function useAttachments({ config }) {
|
|
|
5632
5690
|
message: `File "${file.name}" is not accepted. Supported types: ${accept}`
|
|
5633
5691
|
});
|
|
5634
5692
|
const validFiles = files.filter((file) => matchesAcceptFilter(file, accept));
|
|
5693
|
+
const queued = [];
|
|
5635
5694
|
for (const file of validFiles) {
|
|
5636
5695
|
if (exceedsMaxSize(file, maxSize)) {
|
|
5637
5696
|
cfg?.onUploadFailed?.({
|
|
@@ -5641,53 +5700,37 @@ function useAttachments({ config }) {
|
|
|
5641
5700
|
});
|
|
5642
5701
|
continue;
|
|
5643
5702
|
}
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5649
|
-
|
|
5650
|
-
|
|
5651
|
-
|
|
5652
|
-
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5656
|
-
|
|
5657
|
-
|
|
5658
|
-
|
|
5659
|
-
try {
|
|
5660
|
-
let source;
|
|
5661
|
-
let uploadMetadata;
|
|
5662
|
-
if (cfg?.onUpload) {
|
|
5663
|
-
const { metadata: meta, ...uploadSource } = await cfg.onUpload(file);
|
|
5664
|
-
source = uploadSource;
|
|
5665
|
-
uploadMetadata = meta;
|
|
5666
|
-
} else source = {
|
|
5667
|
-
type: "data",
|
|
5668
|
-
value: await readFileAsBase64(file),
|
|
5669
|
-
mimeType: file.type
|
|
5670
|
-
};
|
|
5671
|
-
let thumbnail;
|
|
5672
|
-
if (modality === "video") thumbnail = await generateVideoThumbnail(file);
|
|
5673
|
-
setAttachments((prev) => prev.map((att) => att.id === placeholderId ? {
|
|
5674
|
-
...att,
|
|
5675
|
-
source,
|
|
5676
|
-
status: "ready",
|
|
5677
|
-
thumbnail,
|
|
5678
|
-
metadata: uploadMetadata
|
|
5679
|
-
} : att));
|
|
5680
|
-
} catch (error) {
|
|
5681
|
-
setAttachments((prev) => prev.filter((att) => att.id !== placeholderId));
|
|
5682
|
-
console.error(`[CopilotKit] Failed to upload "${file.name}":`, error);
|
|
5683
|
-
cfg?.onUploadFailed?.({
|
|
5684
|
-
reason: "upload-failed",
|
|
5685
|
-
file,
|
|
5686
|
-
message: error instanceof Error ? error.message : `Failed to upload "${file.name}"`
|
|
5687
|
-
});
|
|
5688
|
-
}
|
|
5703
|
+
queued.push({
|
|
5704
|
+
file,
|
|
5705
|
+
placeholder: {
|
|
5706
|
+
id: randomUUID$1(),
|
|
5707
|
+
type: getModalityFromMimeType(file.type),
|
|
5708
|
+
source: {
|
|
5709
|
+
type: "data",
|
|
5710
|
+
value: "",
|
|
5711
|
+
mimeType: file.type
|
|
5712
|
+
},
|
|
5713
|
+
filename: file.name,
|
|
5714
|
+
size: file.size,
|
|
5715
|
+
status: "uploading"
|
|
5716
|
+
}
|
|
5717
|
+
});
|
|
5689
5718
|
}
|
|
5690
|
-
|
|
5719
|
+
if (queued.length === 0) return;
|
|
5720
|
+
setAttachments((prev) => [...prev, ...queued.map((q) => q.placeholder)]);
|
|
5721
|
+
const settled = queued.map(({ file, placeholder }) => new Promise((resolve) => {
|
|
5722
|
+
uploadQueueRef.current.push({
|
|
5723
|
+
file,
|
|
5724
|
+
placeholder,
|
|
5725
|
+
cfg,
|
|
5726
|
+
settle: resolve
|
|
5727
|
+
});
|
|
5728
|
+
}));
|
|
5729
|
+
const limit = resolveMaxConcurrentUploads(cfg?.maxConcurrentUploads);
|
|
5730
|
+
const toSpawn = Math.min(uploadQueueRef.current.length, Math.max(0, limit - activeWorkersRef.current));
|
|
5731
|
+
for (let i = 0; i < toSpawn; i++) drainUploadQueue();
|
|
5732
|
+
await Promise.all(settled);
|
|
5733
|
+
}, [drainUploadQueue]);
|
|
5691
5734
|
const handleFileUpload = useCallback(async (e) => {
|
|
5692
5735
|
if (!e.target.files?.length) return;
|
|
5693
5736
|
try {
|
|
@@ -5799,9 +5842,9 @@ const DEFAULT_CONTAINERS = ["project"];
|
|
|
5799
5842
|
* }
|
|
5800
5843
|
* ```
|
|
5801
5844
|
*
|
|
5802
|
-
* @deprecated
|
|
5803
|
-
*
|
|
5804
|
-
*
|
|
5845
|
+
* @deprecated This hook supports only the legacy plural-container annotation.
|
|
5846
|
+
* Configure `getLearningContainerId` on `CopilotKitIntelligence` for new
|
|
5847
|
+
* Intelligence runtimes.
|
|
5805
5848
|
*/
|
|
5806
5849
|
function useLearningContainers({ threadId, learningContainers }) {
|
|
5807
5850
|
const { copilotkit } = useCopilotKit();
|
|
@@ -5815,8 +5858,10 @@ function useLearningContainers({ threadId, learningContainers }) {
|
|
|
5815
5858
|
const warnedMissingUrlRef = useRef(false);
|
|
5816
5859
|
const runtimeUrlRef = useRef(copilotkit.runtimeUrl);
|
|
5817
5860
|
const headersRef = useRef(copilotkit.headers ?? {});
|
|
5861
|
+
const runtimeFetchRef = useRef(copilotkit.ɵruntimeFetch);
|
|
5818
5862
|
runtimeUrlRef.current = copilotkit.runtimeUrl;
|
|
5819
5863
|
headersRef.current = copilotkit.headers ?? {};
|
|
5864
|
+
runtimeFetchRef.current = copilotkit.ɵruntimeFetch;
|
|
5820
5865
|
const key = JSON.stringify(learningContainers);
|
|
5821
5866
|
const defaultKey = JSON.stringify(DEFAULT_CONTAINERS);
|
|
5822
5867
|
useEffect(() => {
|
|
@@ -5836,6 +5881,7 @@ function useLearningContainers({ threadId, learningContainers }) {
|
|
|
5836
5881
|
return;
|
|
5837
5882
|
}
|
|
5838
5883
|
recordAnnotation({
|
|
5884
|
+
fetch: copilotkit.ɵruntimeFetch,
|
|
5839
5885
|
runtimeUrl,
|
|
5840
5886
|
headers,
|
|
5841
5887
|
type: "set_learning_containers",
|
|
@@ -5863,6 +5909,7 @@ function useLearningContainers({ threadId, learningContainers }) {
|
|
|
5863
5909
|
const capturedRuntimeUrl = runtimeUrlRef.current;
|
|
5864
5910
|
const capturedHeaders = headersRef.current;
|
|
5865
5911
|
if (capturedRuntimeUrl) recordAnnotation({
|
|
5912
|
+
fetch: runtimeFetchRef.current,
|
|
5866
5913
|
runtimeUrl: capturedRuntimeUrl,
|
|
5867
5914
|
headers: capturedHeaders,
|
|
5868
5915
|
type: "set_learning_containers",
|
|
@@ -5905,9 +5952,9 @@ function useLearningContainers({ threadId, learningContainers }) {
|
|
|
5905
5952
|
* }
|
|
5906
5953
|
* ```
|
|
5907
5954
|
*
|
|
5908
|
-
* @deprecated
|
|
5909
|
-
*
|
|
5910
|
-
*
|
|
5955
|
+
* @deprecated This hook supports only the legacy plural-container annotation.
|
|
5956
|
+
* Configure `getLearningContainerId` on `CopilotKitIntelligence` for new
|
|
5957
|
+
* Intelligence runtimes.
|
|
5911
5958
|
*/
|
|
5912
5959
|
function useLearningContainersInCurrentThread({ learningContainers }) {
|
|
5913
5960
|
const threadId = useCopilotChatConfiguration()?.threadId;
|
|
@@ -9125,6 +9172,41 @@ const CopilotChatToggleButton = React.forwardRef(function CopilotChatToggleButto
|
|
|
9125
9172
|
});
|
|
9126
9173
|
CopilotChatToggleButton.displayName = "CopilotChatToggleButton";
|
|
9127
9174
|
|
|
9175
|
+
//#endregion
|
|
9176
|
+
//#region src/v2/components/chat/modal-open-control.tsx
|
|
9177
|
+
const ModalOpenControlContext = createContext({});
|
|
9178
|
+
/**
|
|
9179
|
+
* Carries `open` / `onOpenChange` from a prebuilt surface down to the view that
|
|
9180
|
+
* owns the modal state.
|
|
9181
|
+
*
|
|
9182
|
+
* A context is required rather than plain props because `<CopilotSidebar>`
|
|
9183
|
+
* hands its view to `<CopilotChat>` as a `chatView` **component**. Threading a
|
|
9184
|
+
* value that changes (like `open`) through that component's identity would mint
|
|
9185
|
+
* a new element type on every toggle, and React unmounts and remounts the whole
|
|
9186
|
+
* chat subtree when the element type changes. That is the remount class of bug
|
|
9187
|
+
* already fixed for `<CopilotPopup>` on resize. Context keeps the override
|
|
9188
|
+
* identity stable while still re-rendering the view when `open` changes.
|
|
9189
|
+
*/
|
|
9190
|
+
function ModalOpenControlProvider({ open, onOpenChange, children }) {
|
|
9191
|
+
const value = useMemo(() => ({
|
|
9192
|
+
open,
|
|
9193
|
+
onOpenChange
|
|
9194
|
+
}), [open, onOpenChange]);
|
|
9195
|
+
return /* @__PURE__ */ jsx(ModalOpenControlContext.Provider, {
|
|
9196
|
+
value,
|
|
9197
|
+
children
|
|
9198
|
+
});
|
|
9199
|
+
}
|
|
9200
|
+
/**
|
|
9201
|
+
* Reads the controlled open state supplied by the surrounding prebuilt
|
|
9202
|
+
* surface. Returns an empty control (uncontrolled) when there is none.
|
|
9203
|
+
*
|
|
9204
|
+
* @returns The host's `open` / `onOpenChange` pair.
|
|
9205
|
+
*/
|
|
9206
|
+
function useModalOpenControl() {
|
|
9207
|
+
return useContext(ModalOpenControlContext);
|
|
9208
|
+
}
|
|
9209
|
+
|
|
9128
9210
|
//#endregion
|
|
9129
9211
|
//#region src/v2/components/chat/CopilotModalHeader.tsx
|
|
9130
9212
|
/**
|
|
@@ -9234,15 +9316,22 @@ CopilotModalHeader.DrawerLauncher.displayName = "CopilotModalHeader.DrawerLaunch
|
|
|
9234
9316
|
const DEFAULT_SIDEBAR_WIDTH = 480;
|
|
9235
9317
|
const SIDEBAR_TRANSITION_MS = 260;
|
|
9236
9318
|
function CopilotSidebarView({ header, toggleButton, width, defaultOpen = true, position = "right", ...props }) {
|
|
9319
|
+
const { open, onOpenChange } = useModalOpenControl();
|
|
9320
|
+
const hasOpenControl = open !== void 0 || onOpenChange !== void 0;
|
|
9321
|
+
const internal = /* @__PURE__ */ jsx(CopilotSidebarViewInternal, {
|
|
9322
|
+
header,
|
|
9323
|
+
toggleButton,
|
|
9324
|
+
width,
|
|
9325
|
+
position,
|
|
9326
|
+
...props
|
|
9327
|
+
});
|
|
9237
9328
|
return /* @__PURE__ */ jsx(CopilotChatConfigurationProvider, {
|
|
9238
|
-
isModalDefaultOpen: defaultOpen,
|
|
9239
|
-
children: /* @__PURE__ */ jsx(
|
|
9240
|
-
|
|
9241
|
-
|
|
9242
|
-
|
|
9243
|
-
|
|
9244
|
-
...props
|
|
9245
|
-
})
|
|
9329
|
+
isModalDefaultOpen: open ?? defaultOpen,
|
|
9330
|
+
children: hasOpenControl ? /* @__PURE__ */ jsx(ControlledModalOpenScope, {
|
|
9331
|
+
open,
|
|
9332
|
+
onOpenChange,
|
|
9333
|
+
children: internal
|
|
9334
|
+
}) : internal
|
|
9246
9335
|
});
|
|
9247
9336
|
}
|
|
9248
9337
|
function CopilotSidebarViewInternal({ header, toggleButton, width, position = "right", ...props }) {
|
|
@@ -9306,7 +9395,7 @@ function CopilotSidebarViewInternal({ header, toggleButton, width, position = "r
|
|
|
9306
9395
|
"data-position": position,
|
|
9307
9396
|
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"),
|
|
9308
9397
|
style: {
|
|
9309
|
-
|
|
9398
|
+
"--sidebar-width": widthToCss(sidebarWidth),
|
|
9310
9399
|
paddingTop: "env(safe-area-inset-top)",
|
|
9311
9400
|
paddingBottom: "env(safe-area-inset-bottom)"
|
|
9312
9401
|
},
|
|
@@ -9368,17 +9457,24 @@ const dimensionToCss = (value, fallback) => {
|
|
|
9368
9457
|
return `${fallback}px`;
|
|
9369
9458
|
};
|
|
9370
9459
|
function CopilotPopupView({ header, toggleButton, width, height, clickOutsideToClose, defaultOpen = true, className, ...restProps }) {
|
|
9460
|
+
const { open, onOpenChange } = useModalOpenControl();
|
|
9461
|
+
const hasOpenControl = open !== void 0 || onOpenChange !== void 0;
|
|
9462
|
+
const internal = /* @__PURE__ */ jsx(CopilotPopupViewInternal, {
|
|
9463
|
+
header,
|
|
9464
|
+
toggleButton,
|
|
9465
|
+
width,
|
|
9466
|
+
height,
|
|
9467
|
+
clickOutsideToClose,
|
|
9468
|
+
className,
|
|
9469
|
+
...restProps
|
|
9470
|
+
});
|
|
9371
9471
|
return /* @__PURE__ */ jsx(CopilotChatConfigurationProvider, {
|
|
9372
|
-
isModalDefaultOpen: defaultOpen,
|
|
9373
|
-
children: /* @__PURE__ */ jsx(
|
|
9374
|
-
|
|
9375
|
-
|
|
9376
|
-
|
|
9377
|
-
|
|
9378
|
-
clickOutsideToClose,
|
|
9379
|
-
className,
|
|
9380
|
-
...restProps
|
|
9381
|
-
})
|
|
9472
|
+
isModalDefaultOpen: open ?? defaultOpen,
|
|
9473
|
+
children: hasOpenControl ? /* @__PURE__ */ jsx(ControlledModalOpenScope, {
|
|
9474
|
+
open,
|
|
9475
|
+
onOpenChange,
|
|
9476
|
+
children: internal
|
|
9477
|
+
}) : internal
|
|
9382
9478
|
});
|
|
9383
9479
|
}
|
|
9384
9480
|
function CopilotPopupViewInternal({ header, toggleButton, width, height, clickOutsideToClose, className, ...restProps }) {
|
|
@@ -9511,7 +9607,7 @@ var CopilotPopupView_default = CopilotPopupView;
|
|
|
9511
9607
|
|
|
9512
9608
|
//#endregion
|
|
9513
9609
|
//#region src/v2/components/chat/CopilotSidebar.tsx
|
|
9514
|
-
function CopilotSidebar({ header, toggleButton, defaultOpen, width, position, ...chatProps }) {
|
|
9610
|
+
function CopilotSidebar({ header, toggleButton, defaultOpen, open, onOpenChange, width, position, ...chatProps }) {
|
|
9515
9611
|
const { checkFeature } = useLicenseContext$1();
|
|
9516
9612
|
const isSidebarLicensed = checkFeature("sidebar");
|
|
9517
9613
|
useEffect(() => {
|
|
@@ -9537,11 +9633,15 @@ function CopilotSidebar({ header, toggleButton, defaultOpen, width, position, ..
|
|
|
9537
9633
|
defaultOpen,
|
|
9538
9634
|
position
|
|
9539
9635
|
]);
|
|
9540
|
-
return /* @__PURE__ */ jsxs(Fragment$1, { children: [!isSidebarLicensed && /* @__PURE__ */ jsx(InlineFeatureWarning, { featureName: "Sidebar" }), /* @__PURE__ */ jsx(
|
|
9541
|
-
|
|
9542
|
-
|
|
9543
|
-
|
|
9544
|
-
|
|
9636
|
+
return /* @__PURE__ */ jsxs(Fragment$1, { children: [!isSidebarLicensed && /* @__PURE__ */ jsx(InlineFeatureWarning, { featureName: "Sidebar" }), /* @__PURE__ */ jsx(ModalOpenControlProvider, {
|
|
9637
|
+
open,
|
|
9638
|
+
onOpenChange,
|
|
9639
|
+
children: /* @__PURE__ */ jsx(CopilotChat, {
|
|
9640
|
+
welcomeScreen: CopilotSidebarView.WelcomeScreen,
|
|
9641
|
+
...chatProps,
|
|
9642
|
+
isModalDefaultOpen: defaultOpen,
|
|
9643
|
+
chatView: SidebarViewOverride
|
|
9644
|
+
})
|
|
9545
9645
|
})] });
|
|
9546
9646
|
}
|
|
9547
9647
|
CopilotSidebar.displayName = "CopilotSidebar";
|
|
@@ -9563,7 +9663,7 @@ const PopupViewOverride = (viewProps) => {
|
|
|
9563
9663
|
});
|
|
9564
9664
|
};
|
|
9565
9665
|
const PopupViewOverrideWithStatics = Object.assign(PopupViewOverride, CopilotChatView_default);
|
|
9566
|
-
function CopilotPopup({ header, toggleButton, defaultOpen, width, height, clickOutsideToClose, ...chatProps }) {
|
|
9666
|
+
function CopilotPopup({ header, toggleButton, defaultOpen, open, onOpenChange, width, height, clickOutsideToClose, ...chatProps }) {
|
|
9567
9667
|
const { checkFeature } = useLicenseContext$1();
|
|
9568
9668
|
const isPopupLicensed = checkFeature("popup");
|
|
9569
9669
|
useEffect(() => {
|
|
@@ -9586,11 +9686,15 @@ function CopilotPopup({ header, toggleButton, defaultOpen, width, height, clickO
|
|
|
9586
9686
|
]);
|
|
9587
9687
|
return /* @__PURE__ */ jsxs(Fragment$1, { children: [!isPopupLicensed && /* @__PURE__ */ jsx(InlineFeatureWarning, { featureName: "Popup" }), /* @__PURE__ */ jsx(PopupShellPropsContext.Provider, {
|
|
9588
9688
|
value: shellProps,
|
|
9589
|
-
children: /* @__PURE__ */ jsx(
|
|
9590
|
-
|
|
9591
|
-
|
|
9592
|
-
|
|
9593
|
-
|
|
9689
|
+
children: /* @__PURE__ */ jsx(ModalOpenControlProvider, {
|
|
9690
|
+
open,
|
|
9691
|
+
onOpenChange,
|
|
9692
|
+
children: /* @__PURE__ */ jsx(CopilotChat, {
|
|
9693
|
+
welcomeScreen: CopilotPopupView_default.WelcomeScreen,
|
|
9694
|
+
...chatProps,
|
|
9695
|
+
isModalDefaultOpen: defaultOpen,
|
|
9696
|
+
chatView: PopupViewOverrideWithStatics
|
|
9697
|
+
})
|
|
9594
9698
|
})
|
|
9595
9699
|
})] });
|
|
9596
9700
|
}
|
|
@@ -10912,7 +11016,7 @@ const getErrorActions = (error) => {
|
|
|
10912
11016
|
switch (error.code) {
|
|
10913
11017
|
case CopilotKitErrorCode.MISSING_PUBLIC_API_KEY_ERROR: return { primary: {
|
|
10914
11018
|
label: "Show me how",
|
|
10915
|
-
onClick: () => window.open("https://docs.copilotkit.ai/
|
|
11019
|
+
onClick: () => window.open("https://docs.copilotkit.ai/intelligence/overview#plans-and-access", "_blank", "noopener,noreferrer")
|
|
10916
11020
|
} };
|
|
10917
11021
|
case CopilotKitErrorCode.UPGRADE_REQUIRED_ERROR: return { primary: {
|
|
10918
11022
|
label: "Upgrade",
|
|
@@ -12144,4 +12248,4 @@ function validateProps(props) {
|
|
|
12144
12248
|
|
|
12145
12249
|
//#endregion
|
|
12146
12250
|
export { useAgentContext as $, CopilotChatMessageView as A, AudioRecorderError as At, CopilotChatAssistantMessage_default as B, CopilotModalHeader as C, MCPAppsActivityContentSchema as Ct, CopilotChat as D, CopilotKitInspector as Dt, DefaultOpenIcon as E, ɵrunMcpFollowUp as Et, CopilotChatSuggestionView as F, useLearnFromUserActionInCurrentThread as G, useLearningContainersInCurrentThread as H, CopilotChatSuggestionPill as I, useThreads$1 as J, useLearnFromUserAction as K, CopilotChatReasoningMessage_default as L, IntelligenceIndicator as M, CopilotChatConfigurationProvider as Mt, getIntelligenceTurnAnchors as N, useCopilotChatConfiguration as Nt, CopilotChatView_default as O, useRenderToolCall as Ot, IntelligenceIndicatorView as P, useSuggestions as Q, CopilotChatUserMessage_default as R, CopilotSidebarView as S, useSandboxFunctions as St, DefaultCloseIcon as T, MCPAppsActivityType as Tt, useLearningContainers as U, CopilotChatToolCallsView as V, useAttachments as W, INTERRUPT_EVENT_NAME as X, useInterrupt as Y, useConfigureSuggestions as Z, WildcardToolCallRender as _, OpenGenerativeUIActivityRenderer as _t, ThreadsProvider as a, useRenderTool as at, CopilotSidebar as b, OpenGenerativeUIToolRenderer as bt, CoAgentStateRendersProvider as c, useRenderActivityMessage as ct, shouldShowDevConsole as d, useCopilotKit$1 as dt, useCapabilities as et, useToast as f, useLicenseContext$1 as ft, useCopilotContext as g, GenerateSandboxedUiArgsSchema as gt, CopilotContext as h, createA2UIMessageRenderer as ht, ThreadsContext as i, useDefaultRenderTool as it, INTELLIGENCE_TURN_HEAD as j, CopilotChatAudioRecorder as jt, CopilotChatAttachmentQueue as k, CopilotChatInput_default as kt, useCoAgentStateRenders as l, useRenderCustomMessages as lt, useCopilotMessagesContext as m, defineToolCallRenderer as mt, defaultCopilotContextCategories as n, useAgent as nt, useThreads as o, useComponent as ot, CopilotMessagesContext as p, CopilotKitCoreReact as pt, useMemories as q, CoAgentStateRenderBridge as r, useHumanInTheLoop as rt, CoAgentStateRendersContext as s, useFrontendTool as st, CopilotKit as t, UseAgentUpdate as tt, useAsyncCallback as u, CopilotKitProvider as ut, CopilotThreadsDrawer as v, OpenGenerativeUIActivityType as vt, CopilotChatToggleButton as w, MCPAppsActivityRenderer as wt, CopilotPopupView as x, SandboxFunctionsContext as xt, CopilotPopup as y, OpenGenerativeUIContentSchema as yt, CopilotChatAttachmentRenderer as z };
|
|
12147
|
-
//# sourceMappingURL=copilotkit-
|
|
12251
|
+
//# sourceMappingURL=copilotkit-B1jSvZeb.mjs.map
|