274 lines
11 KiB
JavaScript
274 lines
11 KiB
JavaScript
"use client";
|
|
|
|
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
const require_CopilotKitInspector = require('../components/CopilotKitInspector.cjs');
|
|
const require_MCPAppsActivityRenderer = require('../components/MCPAppsActivityRenderer.cjs');
|
|
const require_A2UIMessageRenderer = require('../a2ui/A2UIMessageRenderer.cjs');
|
|
const require_react_core = require('../lib/react-core.cjs');
|
|
let react = require("react");
|
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
let zod = require("zod");
|
|
let _copilotkit_a2ui_renderer = require("@copilotkit/a2ui-renderer");
|
|
|
|
//#region src/providers/CopilotKitProvider.tsx
|
|
const HEADER_NAME = "X-CopilotCloud-Public-Api-Key";
|
|
const COPILOT_CLOUD_CHAT_URL = "https://api.cloud.copilotkit.ai/copilotkit/v1";
|
|
const CopilotKitContext = (0, react.createContext)({
|
|
copilotkit: null,
|
|
executingToolCallIds: /* @__PURE__ */ new Set()
|
|
});
|
|
function useStableArrayProp(prop, warningMessage, isMeaningfulChange) {
|
|
const empty = (0, react.useMemo)(() => [], []);
|
|
const value = prop ?? empty;
|
|
const initial = (0, react.useRef)(value);
|
|
(0, react.useEffect)(() => {
|
|
if (warningMessage && value !== initial.current && (isMeaningfulChange ? isMeaningfulChange(initial.current, value) : true)) console.error(warningMessage);
|
|
}, [value, warningMessage]);
|
|
return value;
|
|
}
|
|
const CopilotKitProvider = ({ children, runtimeUrl, headers = {}, credentials, publicApiKey, publicLicenseKey, properties = {}, agents__unsafe_dev_only: agents = {}, selfManagedAgents = {}, renderToolCalls, renderActivityMessages, renderCustomMessages, frontendTools, humanInTheLoop, showDevConsole = false, useSingleEndpoint = false, onError, a2ui }) => {
|
|
const [shouldRenderInspector, setShouldRenderInspector] = (0, react.useState)(false);
|
|
const [runtimeA2UIEnabled, setRuntimeA2UIEnabled] = (0, react.useState)(false);
|
|
(0, react.useEffect)(() => {
|
|
if (typeof window === "undefined") return;
|
|
if (showDevConsole === true) setShouldRenderInspector(true);
|
|
else if (showDevConsole === "auto") if (new Set(["localhost", "127.0.0.1"]).has(window.location.hostname)) setShouldRenderInspector(true);
|
|
else setShouldRenderInspector(false);
|
|
else setShouldRenderInspector(false);
|
|
}, [showDevConsole]);
|
|
const renderToolCallsList = useStableArrayProp(renderToolCalls, "renderToolCalls must be a stable array. If you want to dynamically add or remove tools, use `useFrontendTool` instead.", (initial, next) => {
|
|
const key = (rc) => `${rc?.agentId ?? ""}:${rc?.name ?? ""}`;
|
|
const setFrom = (arr) => new Set(arr.map(key));
|
|
const a = setFrom(initial);
|
|
const b = setFrom(next);
|
|
if (a.size !== b.size) return true;
|
|
for (const k of a) if (!b.has(k)) return true;
|
|
return false;
|
|
});
|
|
const renderCustomMessagesList = useStableArrayProp(renderCustomMessages, "renderCustomMessages must be a stable array.");
|
|
const renderActivityMessagesList = useStableArrayProp(renderActivityMessages, "renderActivityMessages must be a stable array.");
|
|
const builtInActivityRenderers = (0, react.useMemo)(() => {
|
|
const renderers = [{
|
|
activityType: require_MCPAppsActivityRenderer.MCPAppsActivityType,
|
|
content: require_MCPAppsActivityRenderer.MCPAppsActivityContentSchema,
|
|
render: require_MCPAppsActivityRenderer.MCPAppsActivityRenderer
|
|
}];
|
|
if (runtimeA2UIEnabled) renderers.unshift(require_A2UIMessageRenderer.createA2UIMessageRenderer({ theme: a2ui?.theme ?? _copilotkit_a2ui_renderer.viewerTheme }));
|
|
return renderers;
|
|
}, [runtimeA2UIEnabled, a2ui]);
|
|
const allActivityRenderers = (0, react.useMemo)(() => {
|
|
return [...renderActivityMessagesList, ...builtInActivityRenderers];
|
|
}, [renderActivityMessagesList, builtInActivityRenderers]);
|
|
const resolvedPublicKey = publicApiKey ?? publicLicenseKey;
|
|
const mergedAgents = (0, react.useMemo)(() => ({
|
|
...agents,
|
|
...selfManagedAgents
|
|
}), [agents, selfManagedAgents]);
|
|
const hasLocalAgents = mergedAgents && Object.keys(mergedAgents).length > 0;
|
|
const mergedHeaders = (0, react.useMemo)(() => {
|
|
if (!resolvedPublicKey) return headers;
|
|
if (headers[HEADER_NAME]) return headers;
|
|
return {
|
|
...headers,
|
|
[HEADER_NAME]: resolvedPublicKey
|
|
};
|
|
}, [headers, resolvedPublicKey]);
|
|
if (!runtimeUrl && !resolvedPublicKey && !hasLocalAgents) {
|
|
const message = "Missing required prop: 'runtimeUrl' or 'publicApiKey' or 'publicLicenseKey'";
|
|
if (process.env.NODE_ENV === "production") throw new Error(message);
|
|
else console.warn(message);
|
|
}
|
|
const chatApiEndpoint = runtimeUrl ?? (resolvedPublicKey ? COPILOT_CLOUD_CHAT_URL : void 0);
|
|
const frontendToolsList = useStableArrayProp(frontendTools, "frontendTools must be a stable array. If you want to dynamically add or remove tools, use `useFrontendTool` instead.");
|
|
const humanInTheLoopList = useStableArrayProp(humanInTheLoop, "humanInTheLoop must be a stable array. If you want to dynamically add or remove human-in-the-loop tools, use `useHumanInTheLoop` instead.");
|
|
const processedHumanInTheLoopTools = (0, react.useMemo)(() => {
|
|
const processedTools = [];
|
|
const processedRenderToolCalls = [];
|
|
humanInTheLoopList.forEach((tool) => {
|
|
const frontendTool = {
|
|
name: tool.name,
|
|
description: tool.description,
|
|
parameters: tool.parameters,
|
|
followUp: tool.followUp,
|
|
...tool.agentId && { agentId: tool.agentId },
|
|
handler: async () => {
|
|
return new Promise((resolve) => {
|
|
console.warn(`Human-in-the-loop tool '${tool.name}' called but no interactive handler is set up.`);
|
|
resolve(void 0);
|
|
});
|
|
}
|
|
};
|
|
processedTools.push(frontendTool);
|
|
if (tool.render) processedRenderToolCalls.push({
|
|
name: tool.name,
|
|
args: tool.parameters,
|
|
render: tool.render,
|
|
...tool.agentId && { agentId: tool.agentId }
|
|
});
|
|
});
|
|
return {
|
|
tools: processedTools,
|
|
renderToolCalls: processedRenderToolCalls
|
|
};
|
|
}, [humanInTheLoopList]);
|
|
const allTools = (0, react.useMemo)(() => {
|
|
const tools = [];
|
|
tools.push(...frontendToolsList);
|
|
tools.push(...processedHumanInTheLoopTools.tools);
|
|
return tools;
|
|
}, [frontendToolsList, processedHumanInTheLoopTools]);
|
|
const allRenderToolCalls = (0, react.useMemo)(() => {
|
|
const combined = [...renderToolCallsList];
|
|
frontendToolsList.forEach((tool) => {
|
|
if (tool.render) {
|
|
const args = tool.parameters || (tool.name === "*" ? zod.z.any() : void 0);
|
|
if (args) combined.push({
|
|
name: tool.name,
|
|
args,
|
|
render: tool.render
|
|
});
|
|
}
|
|
});
|
|
combined.push(...processedHumanInTheLoopTools.renderToolCalls);
|
|
return combined;
|
|
}, [
|
|
renderToolCallsList,
|
|
frontendToolsList,
|
|
processedHumanInTheLoopTools
|
|
]);
|
|
const copilotkitRef = (0, react.useRef)(null);
|
|
if (copilotkitRef.current === null) copilotkitRef.current = new require_react_core.CopilotKitCoreReact({
|
|
runtimeUrl: chatApiEndpoint,
|
|
runtimeTransport: useSingleEndpoint ? "single" : "rest",
|
|
headers: mergedHeaders,
|
|
credentials,
|
|
properties,
|
|
agents__unsafe_dev_only: mergedAgents,
|
|
tools: allTools,
|
|
renderToolCalls: allRenderToolCalls,
|
|
renderActivityMessages: allActivityRenderers,
|
|
renderCustomMessages: renderCustomMessagesList
|
|
});
|
|
const copilotkit = copilotkitRef.current;
|
|
(0, react.useEffect)(() => {
|
|
const subscription = copilotkit.subscribe({ onRuntimeConnectionStatusChanged: () => {
|
|
setRuntimeA2UIEnabled(copilotkit.a2uiEnabled);
|
|
} });
|
|
return () => {
|
|
subscription.unsubscribe();
|
|
};
|
|
}, [copilotkit]);
|
|
const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
|
|
(0, react.useEffect)(() => {
|
|
const subscription = copilotkit.subscribe({ onRenderToolCallsChanged: () => {
|
|
forceUpdate();
|
|
} });
|
|
return () => {
|
|
subscription.unsubscribe();
|
|
};
|
|
}, [copilotkit]);
|
|
const [executingToolCallIds, setExecutingToolCallIds] = (0, react.useState)(() => /* @__PURE__ */ new Set());
|
|
(0, react.useEffect)(() => {
|
|
const subscription = copilotkit.subscribe({
|
|
onToolExecutionStart: ({ toolCallId }) => {
|
|
setExecutingToolCallIds((prev) => {
|
|
if (prev.has(toolCallId)) return prev;
|
|
const next = new Set(prev);
|
|
next.add(toolCallId);
|
|
return next;
|
|
});
|
|
},
|
|
onToolExecutionEnd: ({ toolCallId }) => {
|
|
setExecutingToolCallIds((prev) => {
|
|
if (!prev.has(toolCallId)) return prev;
|
|
const next = new Set(prev);
|
|
next.delete(toolCallId);
|
|
return next;
|
|
});
|
|
}
|
|
});
|
|
return () => {
|
|
subscription.unsubscribe();
|
|
};
|
|
}, [copilotkit]);
|
|
const onErrorRef = (0, react.useRef)(onError);
|
|
(0, react.useEffect)(() => {
|
|
onErrorRef.current = onError;
|
|
}, [onError]);
|
|
(0, react.useEffect)(() => {
|
|
if (!onErrorRef.current) return;
|
|
const subscription = copilotkit.subscribe({ onError: (event) => {
|
|
onErrorRef.current?.({
|
|
error: event.error,
|
|
code: event.code,
|
|
context: event.context
|
|
});
|
|
} });
|
|
return () => {
|
|
subscription.unsubscribe();
|
|
};
|
|
}, [copilotkit]);
|
|
(0, react.useEffect)(() => {
|
|
copilotkit.setRuntimeUrl(chatApiEndpoint);
|
|
copilotkit.setRuntimeTransport(useSingleEndpoint ? "single" : "rest");
|
|
copilotkit.setHeaders(mergedHeaders);
|
|
copilotkit.setCredentials(credentials);
|
|
copilotkit.setProperties(properties);
|
|
copilotkit.setAgents__unsafe_dev_only(mergedAgents);
|
|
}, [
|
|
copilotkit,
|
|
chatApiEndpoint,
|
|
mergedHeaders,
|
|
credentials,
|
|
properties,
|
|
mergedAgents,
|
|
useSingleEndpoint
|
|
]);
|
|
const didMountRef = (0, react.useRef)(false);
|
|
(0, react.useEffect)(() => {
|
|
if (!didMountRef.current) return;
|
|
copilotkit.setTools(allTools);
|
|
}, [copilotkit, allTools]);
|
|
(0, react.useEffect)(() => {
|
|
if (!didMountRef.current) return;
|
|
copilotkit.setRenderToolCalls(allRenderToolCalls);
|
|
}, [copilotkit, allRenderToolCalls]);
|
|
(0, react.useEffect)(() => {
|
|
if (!didMountRef.current) return;
|
|
copilotkit.setRenderActivityMessages(allActivityRenderers);
|
|
}, [copilotkit, allActivityRenderers]);
|
|
(0, react.useEffect)(() => {
|
|
if (!didMountRef.current) return;
|
|
copilotkit.setRenderCustomMessages(renderCustomMessagesList);
|
|
}, [copilotkit, renderCustomMessagesList]);
|
|
(0, react.useEffect)(() => {
|
|
didMountRef.current = true;
|
|
}, []);
|
|
const contextValue = (0, react.useMemo)(() => ({
|
|
copilotkit,
|
|
executingToolCallIds
|
|
}), [copilotkit, executingToolCallIds]);
|
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CopilotKitContext.Provider, {
|
|
value: contextValue,
|
|
children: [children, shouldRenderInspector ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_CopilotKitInspector.CopilotKitInspector, { core: copilotkit }) : null]
|
|
});
|
|
};
|
|
const useCopilotKit = () => {
|
|
const context = (0, react.useContext)(CopilotKitContext);
|
|
const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
|
|
if (!context) throw new Error("useCopilotKit must be used within CopilotKitProvider");
|
|
(0, react.useEffect)(() => {
|
|
const subscription = context.copilotkit.subscribe({ onRuntimeConnectionStatusChanged: () => {
|
|
forceUpdate();
|
|
} });
|
|
return () => {
|
|
subscription.unsubscribe();
|
|
};
|
|
}, []);
|
|
return context;
|
|
};
|
|
|
|
//#endregion
|
|
exports.CopilotKitProvider = CopilotKitProvider;
|
|
exports.useCopilotKit = useCopilotKit;
|
|
//# sourceMappingURL=CopilotKitProvider.cjs.map
|