rdesign/frontend/node_modules/@copilotkitnext/react/dist/index.umd.js

5466 lines
234 KiB
JavaScript

"use client";
(function(global, factory) {
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@ag-ui/client'), require('react'), require('tailwind-merge'), require('lucide-react'), require('@copilotkitnext/shared'), require('react/jsx-runtime'), require('@radix-ui/react-slot'), require('class-variance-authority'), require('clsx'), require('@radix-ui/react-tooltip'), require('@radix-ui/react-dropdown-menu'), require('streamdown'), require('@copilotkitnext/core'), require('zod'), require('@lit-labs/react'), require('@copilotkit/a2ui-renderer'), require('use-stick-to-bottom'), require('ts-deepmerge')) :
typeof define === 'function' && define.amd ? define(['exports', '@ag-ui/client', 'react', 'tailwind-merge', 'lucide-react', '@copilotkitnext/shared', 'react/jsx-runtime', '@radix-ui/react-slot', 'class-variance-authority', 'clsx', '@radix-ui/react-tooltip', '@radix-ui/react-dropdown-menu', 'streamdown', '@copilotkitnext/core', 'zod', '@lit-labs/react', '@copilotkit/a2ui-renderer', 'use-stick-to-bottom', 'ts-deepmerge'], factory) :
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.CopilotKitNextReact = {}), global.AgUIClient,global.React,global.tailwindMerge,global.lucideReact,global.CopilotKitNextShared,global.ReactJsxRuntime,global.RadixReactSlot,global.classVarianceAuthority,global.clsx,global.RadixReactTooltip,global.RadixReactDropdownMenu,global.streamdown,global.CopilotKitNextCore,global.Zod,global.LitLabsReact,global.CopilotKitA2UIRenderer,global.useStickToBottom,global.tsDeepmerge));
})(this, function(exports, _ag_ui_client, react, tailwind_merge, lucide_react, _copilotkitnext_shared, react_jsx_runtime, _radix_ui_react_slot, class_variance_authority, clsx, _radix_ui_react_tooltip, _radix_ui_react_dropdown_menu, streamdown, _copilotkitnext_core, zod, _lit_labs_react, _copilotkit_a2ui_renderer, use_stick_to_bottom, ts_deepmerge) {
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
//#region \0rolldown/runtime.js
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) {
__defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
}
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
//#endregion
react = __toESM(react);
_radix_ui_react_tooltip = __toESM(_radix_ui_react_tooltip);
_radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
//#region src/providers/CopilotChatConfigurationProvider.tsx
const CopilotChatDefaultLabels = {
chatInputPlaceholder: "Type a message...",
chatInputToolbarStartTranscribeButtonLabel: "Transcribe",
chatInputToolbarCancelTranscribeButtonLabel: "Cancel",
chatInputToolbarFinishTranscribeButtonLabel: "Finish",
chatInputToolbarAddButtonLabel: "Add photos or files",
chatInputToolbarToolsButtonLabel: "Tools",
assistantMessageToolbarCopyCodeLabel: "Copy",
assistantMessageToolbarCopyCodeCopiedLabel: "Copied",
assistantMessageToolbarCopyMessageLabel: "Copy",
assistantMessageToolbarThumbsUpLabel: "Good response",
assistantMessageToolbarThumbsDownLabel: "Bad response",
assistantMessageToolbarReadAloudLabel: "Read aloud",
assistantMessageToolbarRegenerateLabel: "Regenerate",
userMessageToolbarCopyMessageLabel: "Copy",
userMessageToolbarEditMessageLabel: "Edit",
chatDisclaimerText: "AI can make mistakes. Please verify important information.",
chatToggleOpenLabel: "Open chat",
chatToggleCloseLabel: "Close chat",
modalHeaderTitle: "CopilotKit Chat",
welcomeMessageText: "How can I help you today?"
};
const CopilotChatConfiguration = (0, react.createContext)(null);
const CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId, isModalDefaultOpen }) => {
var _ref, _parentConfig$isModal, _parentConfig$setModa;
const parentConfig = (0, react.useContext)(CopilotChatConfiguration);
const mergedLabels = (0, react.useMemo)(() => {
var _parentConfig$labels;
return {
...CopilotChatDefaultLabels,
...(_parentConfig$labels = parentConfig === null || parentConfig === void 0 ? void 0 : parentConfig.labels) !== null && _parentConfig$labels !== void 0 ? _parentConfig$labels : {},
...labels !== null && labels !== void 0 ? labels : {}
};
}, [labels, parentConfig === null || parentConfig === void 0 ? void 0 : parentConfig.labels]);
const resolvedAgentId = (_ref = agentId !== null && agentId !== void 0 ? agentId : parentConfig === null || parentConfig === void 0 ? void 0 : parentConfig.agentId) !== null && _ref !== void 0 ? _ref : _copilotkitnext_shared.DEFAULT_AGENT_ID;
const resolvedThreadId = (0, react.useMemo)(() => {
if (threadId) return threadId;
if (parentConfig === null || parentConfig === void 0 ? void 0 : parentConfig.threadId) return parentConfig.threadId;
return (0, _copilotkitnext_shared.randomUUID)();
}, [threadId, parentConfig === null || parentConfig === void 0 ? void 0 : parentConfig.threadId]);
const [internalModalOpen, setInternalModalOpen] = (0, react.useState)(isModalDefaultOpen !== null && isModalDefaultOpen !== void 0 ? isModalDefaultOpen : true);
const resolvedIsModalOpen = (_parentConfig$isModal = parentConfig === null || parentConfig === void 0 ? void 0 : parentConfig.isModalOpen) !== null && _parentConfig$isModal !== void 0 ? _parentConfig$isModal : internalModalOpen;
const resolvedSetModalOpen = (_parentConfig$setModa = parentConfig === null || parentConfig === void 0 ? void 0 : parentConfig.setModalOpen) !== null && _parentConfig$setModa !== void 0 ? _parentConfig$setModa : setInternalModalOpen;
const configurationValue = (0, react.useMemo)(() => ({
labels: mergedLabels,
agentId: resolvedAgentId,
threadId: resolvedThreadId,
isModalOpen: resolvedIsModalOpen,
setModalOpen: resolvedSetModalOpen
}), [
mergedLabels,
resolvedAgentId,
resolvedThreadId,
resolvedIsModalOpen,
resolvedSetModalOpen
]);
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfiguration.Provider, {
value: configurationValue,
children
});
};
const useCopilotChatConfiguration = () => {
return (0, react.useContext)(CopilotChatConfiguration);
};
//#endregion
//#region src/lib/utils.ts
const twMerge$8 = (0, tailwind_merge.extendTailwindMerge)({ prefix: "cpk" });
function cn(...inputs) {
return twMerge$8((0, clsx.clsx)(inputs));
}
//#endregion
//#region src/components/ui/button.tsx
const buttonVariants = (0, class_variance_authority.cva)("cpk:inline-flex cpk:items-center cpk:justify-center cpk:gap-2 cpk:whitespace-nowrap cpk:rounded-md cpk:text-sm cpk:font-medium cpk:transition-all cpk:disabled:pointer-events-none cpk:disabled:opacity-50 cpk:[&_svg]:pointer-events-none cpk:[&_svg:not([class*='size-'])]:size-4 cpk:shrink-0 cpk:[&_svg]:shrink-0 cpk:outline-none cpk:focus-visible:border-ring cpk:focus-visible:ring-ring/50 cpk:focus-visible:ring-[3px] cpk:aria-invalid:ring-destructive/20 cpk:dark:aria-invalid:ring-destructive/40 cpk:aria-invalid:border-destructive", {
variants: {
variant: {
default: "cpk:bg-primary cpk:text-primary-foreground cpk:shadow-xs cpk:hover:bg-primary/90",
destructive: "cpk:bg-destructive cpk:text-white cpk:shadow-xs cpk:hover:bg-destructive/90 cpk:focus-visible:ring-destructive/20 cpk:dark:focus-visible:ring-destructive/40 cpk:dark:bg-destructive/60",
outline: "cpk:border cpk:bg-background cpk:shadow-xs cpk:hover:bg-accent cpk:hover:text-accent-foreground cpk:dark:bg-input/30 cpk:dark:border-input cpk:dark:hover:bg-input/50",
secondary: "cpk:bg-secondary cpk:text-secondary-foreground cpk:shadow-xs cpk:hover:bg-secondary/80",
ghost: "cpk:hover:bg-accent cpk:hover:text-accent-foreground cpk:dark:hover:bg-accent/50 cpk:cursor-pointer",
link: "cpk:text-primary cpk:underline-offset-4 cpk:hover:underline",
assistantMessageToolbarButton: [
"cpk:cursor-pointer",
"cpk:p-0 cpk:text-[rgb(93,93,93)] cpk:hover:bg-[#E8E8E8]",
"cpk:dark:text-[rgb(243,243,243)] cpk:dark:hover:bg-[#303030]",
"cpk:h-8 cpk:w-8",
"cpk:transition-colors",
"cpk:hover:text-[rgb(93,93,93)]",
"cpk:dark:hover:text-[rgb(243,243,243)]"
],
chatInputToolbarPrimary: [
"cpk:cursor-pointer",
"cpk:bg-black cpk:text-white",
"cpk:dark:bg-white cpk:dark:text-black cpk:dark:focus-visible:outline-white",
"cpk:rounded-full",
"cpk:transition-colors",
"cpk:focus:outline-none",
"cpk:hover:opacity-70 cpk:disabled:hover:opacity-100",
"cpk:disabled:cursor-not-allowed cpk:disabled:bg-[#00000014] cpk:disabled:text-[rgb(13,13,13)]",
"cpk:dark:disabled:bg-[#454545] cpk:dark:disabled:text-white "
],
chatInputToolbarSecondary: [
"cpk:cursor-pointer",
"cpk:bg-transparent cpk:text-[#444444]",
"cpk:dark:text-white cpk:dark:border-[#404040]",
"cpk:rounded-full",
"cpk:transition-colors",
"cpk:focus:outline-none",
"cpk:hover:bg-[#f8f8f8] cpk:hover:text-[#333333]",
"cpk:dark:hover:bg-[#404040] cpk:dark:hover:text-[#FFFFFF]",
"cpk:disabled:cursor-not-allowed cpk:disabled:opacity-50",
"cpk:disabled:hover:bg-transparent cpk:disabled:hover:text-[#444444]",
"cpk:dark:disabled:hover:bg-transparent cpk:dark:disabled:hover:text-[#CCCCCC]"
]
},
size: {
default: "cpk:h-9 cpk:px-4 cpk:py-2 cpk:has-[>svg]:px-3",
sm: "cpk:h-8 cpk:rounded-md cpk:gap-1.5 cpk:px-3 cpk:has-[>svg]:px-2.5",
lg: "cpk:h-10 cpk:rounded-md cpk:px-6 cpk:has-[>svg]:px-4",
icon: "cpk:size-9",
chatInputToolbarIcon: ["cpk:h-9 cpk:w-9 cpk:rounded-full"],
chatInputToolbarIconLabel: [
"cpk:h-9 cpk:px-3 cpk:rounded-full",
"cpk:gap-2",
"cpk:font-normal"
]
}
},
defaultVariants: {
variant: "default",
size: "default"
}
});
function Button({ className, variant, size, asChild = false, ...props }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(asChild ? _radix_ui_react_slot.Slot : "button", {
"data-slot": "button",
className: cn(buttonVariants({
variant,
size,
className
})),
...props
});
}
//#endregion
//#region src/components/ui/tooltip.tsx
function TooltipProvider({ delayDuration = 0, ...props }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_tooltip.Provider, {
"data-slot": "tooltip-provider",
delayDuration,
...props
});
}
function Tooltip({ ...props }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_tooltip.Root, {
"data-slot": "tooltip",
...props
}) });
}
function TooltipTrigger({ ...props }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_tooltip.Trigger, {
"data-slot": "tooltip-trigger",
...props
});
}
function TooltipContent({ className, sideOffset = 0, children, ...props }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_tooltip.Portal, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_radix_ui_react_tooltip.Content, {
"data-copilotkit": true,
"data-slot": "tooltip-content",
sideOffset,
className: cn("cpk:bg-primary cpk:text-primary-foreground cpk:animate-in cpk:fade-in-0 cpk:zoom-in-95 cpk:data-[state=closed]:animate-out cpk:data-[state=closed]:fade-out-0 cpk:data-[state=closed]:zoom-out-95 cpk:data-[side=bottom]:slide-in-from-top-2 cpk:data-[side=left]:slide-in-from-right-2 cpk:data-[side=right]:slide-in-from-left-2 cpk:data-[side=top]:slide-in-from-bottom-2 cpk:z-50 cpk:w-fit cpk:origin-(--radix-tooltip-content-transform-origin) cpk:rounded-md cpk:px-3 cpk:py-1.5 cpk:text-xs cpk:text-balance", className),
...props,
children: [children, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_tooltip.Arrow, { className: "cpk:bg-primary cpk:fill-primary cpk:z-50 cpk:size-2.5 cpk:translate-y-[calc(-50%_-_2px)] cpk:rotate-45 cpk:rounded-[2px]" })]
}) });
}
//#endregion
//#region src/components/ui/dropdown-menu.tsx
function DropdownMenu({ ...props }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dropdown_menu.Root, {
"data-slot": "dropdown-menu",
...props
});
}
function DropdownMenuTrigger({ ...props }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dropdown_menu.Trigger, {
"data-slot": "dropdown-menu-trigger",
...props
});
}
function DropdownMenuContent({ className, sideOffset = 4, ...props }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dropdown_menu.Portal, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dropdown_menu.Content, {
"data-copilotkit": true,
"data-slot": "dropdown-menu-content",
sideOffset,
className: cn("cpk:bg-popover cpk:text-popover-foreground cpk:data-[state=open]:animate-in cpk:data-[state=closed]:animate-out cpk:data-[state=closed]:fade-out-0 cpk:data-[state=open]:fade-in-0 cpk:data-[state=closed]:zoom-out-95 cpk:data-[state=open]:zoom-in-95 cpk:data-[side=bottom]:slide-in-from-top-2 cpk:data-[side=left]:slide-in-from-right-2 cpk:data-[side=right]:slide-in-from-left-2 cpk:data-[side=top]:slide-in-from-bottom-2 cpk:z-50 cpk:max-h-(--radix-dropdown-menu-content-available-height) cpk:min-w-[8rem] cpk:origin-(--radix-dropdown-menu-content-transform-origin) cpk:overflow-x-hidden cpk:overflow-y-auto cpk:rounded-md cpk:border cpk:p-1 cpk:shadow-md", className),
...props
}) });
}
function DropdownMenuItem({ className, inset, variant = "default", ...props }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dropdown_menu.Item, {
"data-slot": "dropdown-menu-item",
"data-inset": inset,
"data-variant": variant,
className: cn("cpk:focus:bg-accent cpk:focus:text-accent-foreground cpk:data-[variant=destructive]:text-destructive cpk:data-[variant=destructive]:focus:bg-destructive/10 cpk:dark:data-[variant=destructive]:focus:bg-destructive/20 cpk:data-[variant=destructive]:focus:text-destructive cpk:data-[variant=destructive]:*:[svg]:!text-destructive cpk:[&_svg:not([class*='text-'])]:text-muted-foreground cpk:relative cpk:flex cpk:cursor-default cpk:items-center cpk:gap-2 cpk:rounded-sm cpk:px-2 cpk:py-1.5 cpk:text-sm cpk:outline-hidden cpk:select-none cpk:data-[disabled]:pointer-events-none cpk:data-[disabled]:opacity-50 cpk:data-[inset]:pl-8 cpk:[&_svg]:pointer-events-none cpk:[&_svg]:shrink-0 cpk:[&_svg:not([class*='size-'])]:size-4", className),
...props
});
}
function DropdownMenuSeparator({ className, ...props }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dropdown_menu.Separator, {
"data-slot": "dropdown-menu-separator",
className: cn("cpk:bg-border cpk:-mx-1 cpk:my-1 cpk:h-px", className),
...props
});
}
function DropdownMenuSub({ ...props }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dropdown_menu.Sub, {
"data-slot": "dropdown-menu-sub",
...props
});
}
function DropdownMenuSubTrigger({ className, inset, children, ...props }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_radix_ui_react_dropdown_menu.SubTrigger, {
"data-slot": "dropdown-menu-sub-trigger",
"data-inset": inset,
className: cn("cpk:focus:bg-accent cpk:focus:text-accent-foreground cpk:data-[state=open]:bg-accent cpk:data-[state=open]:text-accent-foreground cpk:flex cpk:cursor-default cpk:items-center cpk:rounded-sm cpk:px-2 cpk:py-1.5 cpk:text-sm cpk:outline-hidden cpk:select-none cpk:data-[inset]:pl-8", className),
...props,
children: [children, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronRightIcon, { className: "cpk:ml-auto cpk:size-4" })]
});
}
function DropdownMenuSubContent({ className, ...props }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dropdown_menu.SubContent, {
"data-slot": "dropdown-menu-sub-content",
className: cn("cpk:bg-popover cpk:text-popover-foreground cpk:data-[state=open]:animate-in cpk:data-[state=closed]:animate-out cpk:data-[state=closed]:fade-out-0 cpk:data-[state=open]:fade-in-0 cpk:data-[state=closed]:zoom-out-95 cpk:data-[state=open]:zoom-in-95 cpk:data-[side=bottom]:slide-in-from-top-2 cpk:data-[side=left]:slide-in-from-right-2 cpk:data-[side=right]:slide-in-from-left-2 cpk:data-[side=top]:slide-in-from-bottom-2 cpk:z-50 cpk:min-w-[8rem] cpk:origin-(--radix-dropdown-menu-content-transform-origin) cpk:overflow-hidden cpk:rounded-md cpk:border cpk:p-1 cpk:shadow-lg", className),
...props
});
}
//#endregion
//#region src/components/chat/CopilotChatAudioRecorder.tsx
/** Error subclass so callers can `instanceof`-guard recorder failures */
var AudioRecorderError = class extends Error {
constructor(message) {
super(message);
this.name = "AudioRecorderError";
}
};
const CopilotChatAudioRecorder = (0, react.forwardRef)((props, ref) => {
const { className, ...divProps } = props;
const canvasRef = (0, react.useRef)(null);
const [recorderState, setRecorderState] = (0, react.useState)("idle");
const mediaRecorderRef = (0, react.useRef)(null);
const audioChunksRef = (0, react.useRef)([]);
const streamRef = (0, react.useRef)(null);
const analyserRef = (0, react.useRef)(null);
const audioContextRef = (0, react.useRef)(null);
const animationIdRef = (0, react.useRef)(null);
const amplitudeHistoryRef = (0, react.useRef)([]);
const frameCountRef = (0, react.useRef)(0);
const scrollOffsetRef = (0, react.useRef)(0);
const smoothedAmplitudeRef = (0, react.useRef)(0);
const fadeOpacityRef = (0, react.useRef)(0);
const cleanup = (0, react.useCallback)(() => {
if (animationIdRef.current) {
cancelAnimationFrame(animationIdRef.current);
animationIdRef.current = null;
}
if (mediaRecorderRef.current && mediaRecorderRef.current.state !== "inactive") try {
mediaRecorderRef.current.stop();
} catch (_unused) {}
if (streamRef.current) {
streamRef.current.getTracks().forEach((track) => track.stop());
streamRef.current = null;
}
if (audioContextRef.current && audioContextRef.current.state !== "closed") {
audioContextRef.current.close().catch(() => {});
audioContextRef.current = null;
}
mediaRecorderRef.current = null;
analyserRef.current = null;
audioChunksRef.current = [];
amplitudeHistoryRef.current = [];
frameCountRef.current = 0;
scrollOffsetRef.current = 0;
smoothedAmplitudeRef.current = 0;
fadeOpacityRef.current = 0;
}, []);
const start = (0, react.useCallback)(async () => {
if (recorderState !== "idle") throw new AudioRecorderError("Recorder is already active");
try {
const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
streamRef.current = stream;
const audioContext = new AudioContext();
audioContextRef.current = audioContext;
const source = audioContext.createMediaStreamSource(stream);
const analyser = audioContext.createAnalyser();
analyser.fftSize = 2048;
source.connect(analyser);
analyserRef.current = analyser;
const mimeType = MediaRecorder.isTypeSupported("audio/webm;codecs=opus") ? "audio/webm;codecs=opus" : MediaRecorder.isTypeSupported("audio/webm") ? "audio/webm" : MediaRecorder.isTypeSupported("audio/mp4") ? "audio/mp4" : "";
const options = mimeType ? { mimeType } : {};
const mediaRecorder = new MediaRecorder(stream, options);
mediaRecorderRef.current = mediaRecorder;
audioChunksRef.current = [];
mediaRecorder.ondataavailable = (event) => {
if (event.data.size > 0) audioChunksRef.current.push(event.data);
};
mediaRecorder.start(100);
setRecorderState("recording");
} catch (error) {
cleanup();
if (error instanceof Error && error.name === "NotAllowedError") throw new AudioRecorderError("Microphone permission denied");
if (error instanceof Error && error.name === "NotFoundError") throw new AudioRecorderError("No microphone found");
throw new AudioRecorderError(error instanceof Error ? error.message : "Failed to start recording");
}
}, [recorderState, cleanup]);
const stop = (0, react.useCallback)(() => {
return new Promise((resolve, reject) => {
const mediaRecorder = mediaRecorderRef.current;
if (!mediaRecorder || recorderState !== "recording") {
reject(new AudioRecorderError("No active recording"));
return;
}
setRecorderState("processing");
mediaRecorder.onstop = () => {
const mimeType = mediaRecorder.mimeType || "audio/webm";
const audioBlob = new Blob(audioChunksRef.current, { type: mimeType });
cleanup();
setRecorderState("idle");
resolve(audioBlob);
};
mediaRecorder.onerror = () => {
cleanup();
setRecorderState("idle");
reject(new AudioRecorderError("Recording failed"));
};
mediaRecorder.stop();
});
}, [recorderState, cleanup]);
const calculateAmplitude = (dataArray) => {
let sum = 0;
for (let i = 0; i < dataArray.length; i++) {
var _dataArray$i;
const sample = ((_dataArray$i = dataArray[i]) !== null && _dataArray$i !== void 0 ? _dataArray$i : 128) / 128 - 1;
sum += sample * sample;
}
return Math.sqrt(sum / dataArray.length);
};
(0, react.useEffect)(() => {
const canvas = canvasRef.current;
if (!canvas) return;
const ctx = canvas.getContext("2d");
if (!ctx) return;
const barWidth = 2;
const barSpacing = barWidth + 1;
const scrollSpeed = 1 / 3;
const draw = () => {
const rect = canvas.getBoundingClientRect();
const dpr = window.devicePixelRatio || 1;
if (canvas.width !== rect.width * dpr || canvas.height !== rect.height * dpr) {
canvas.width = rect.width * dpr;
canvas.height = rect.height * dpr;
ctx.scale(dpr, dpr);
}
const maxBars = Math.floor(rect.width / barSpacing) + 2;
if (analyserRef.current && recorderState === "recording") {
if (amplitudeHistoryRef.current.length === 0) amplitudeHistoryRef.current = new Array(maxBars).fill(0);
if (fadeOpacityRef.current < 1) fadeOpacityRef.current = Math.min(1, fadeOpacityRef.current + .03);
scrollOffsetRef.current += scrollSpeed;
const bufferLength = analyserRef.current.fftSize;
const dataArray = new Uint8Array(bufferLength);
analyserRef.current.getByteTimeDomainData(dataArray);
const rawAmplitude = calculateAmplitude(dataArray);
const speed = rawAmplitude > smoothedAmplitudeRef.current ? .12 : .08;
smoothedAmplitudeRef.current += (rawAmplitude - smoothedAmplitudeRef.current) * speed;
if (scrollOffsetRef.current >= barSpacing) {
scrollOffsetRef.current -= barSpacing;
amplitudeHistoryRef.current.push(smoothedAmplitudeRef.current);
if (amplitudeHistoryRef.current.length > maxBars) amplitudeHistoryRef.current = amplitudeHistoryRef.current.slice(-maxBars);
}
}
ctx.clearRect(0, 0, rect.width, rect.height);
ctx.fillStyle = getComputedStyle(canvas).color;
ctx.globalAlpha = fadeOpacityRef.current;
const centerY = rect.height / 2;
const maxAmplitude = rect.height / 2 - 2;
const history = amplitudeHistoryRef.current;
if (history.length > 0) {
const offset = scrollOffsetRef.current;
const edgeFadeWidth = 12;
for (let i = 0; i < history.length; i++) {
var _history$i;
const amplitude = (_history$i = history[i]) !== null && _history$i !== void 0 ? _history$i : 0;
const scaledAmplitude = Math.min(amplitude * 4, 1);
const barHeight = Math.max(2, scaledAmplitude * maxAmplitude * 2);
const x = rect.width - (history.length - i) * barSpacing - offset;
const y = centerY - barHeight / 2;
if (x + barWidth > 0 && x < rect.width) {
let edgeOpacity = 1;
if (x < edgeFadeWidth) edgeOpacity = Math.max(0, x / edgeFadeWidth);
else if (x > rect.width - edgeFadeWidth) edgeOpacity = Math.max(0, (rect.width - x) / edgeFadeWidth);
ctx.globalAlpha = fadeOpacityRef.current * edgeOpacity;
ctx.fillRect(x, y, barWidth, barHeight);
}
}
}
animationIdRef.current = requestAnimationFrame(draw);
};
draw();
return () => {
if (animationIdRef.current) cancelAnimationFrame(animationIdRef.current);
};
}, [recorderState]);
(0, react.useEffect)(() => {
return cleanup;
}, [cleanup]);
(0, react.useImperativeHandle)(ref, () => ({
get state() {
return recorderState;
},
start,
stop,
dispose: cleanup
}), [
recorderState,
start,
stop,
cleanup
]);
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: (0, tailwind_merge.twMerge)("cpk:w-full cpk:py-3 cpk:px-5", className),
...divProps,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("canvas", {
ref: canvasRef,
className: "cpk:block cpk:w-full cpk:h-[26px]"
})
});
});
CopilotChatAudioRecorder.displayName = "CopilotChatAudioRecorder";
//#endregion
//#region src/lib/slots.tsx
/**
* Shallow equality comparison for objects.
*/
function shallowEqual(obj1, obj2) {
const keys1 = Object.keys(obj1);
const keys2 = Object.keys(obj2);
if (keys1.length !== keys2.length) return false;
for (const key of keys1) if (obj1[key] !== obj2[key]) return false;
return true;
}
/**
* Check if a value is a React component type (function, class, forwardRef, memo, etc.)
*/
function isReactComponentType(value) {
if (typeof value === "function") return true;
if (value && typeof value === "object" && "$$typeof" in value && !react.default.isValidElement(value)) return true;
return false;
}
/**
* Internal function to render a slot value as a React element (non-memoized).
*/
function renderSlotElement(slot, DefaultComponent, props) {
if (typeof slot === "string") {
const existingClassName = props.className;
return react.default.createElement(DefaultComponent, {
...props,
className: (0, tailwind_merge.twMerge)(existingClassName, slot)
});
}
if (isReactComponentType(slot)) return react.default.createElement(slot, props);
if (slot && typeof slot === "object" && !react.default.isValidElement(slot)) return react.default.createElement(DefaultComponent, {
...props,
...slot
});
return react.default.createElement(DefaultComponent, props);
}
/**
* Internal memoized wrapper component for renderSlot.
* Uses forwardRef to support ref forwarding.
*/
const MemoizedSlotWrapper = react.default.memo(react.default.forwardRef(function MemoizedSlotWrapper(props, ref) {
const { $slot, $component, ...rest } = props;
return renderSlotElement($slot, $component, ref !== null ? {
...rest,
ref
} : rest);
}), (prev, next) => {
if (prev.$slot !== next.$slot) return false;
if (prev.$component !== next.$component) return false;
const { $slot: _ps, $component: _pc, ...prevRest } = prev;
const { $slot: _ns, $component: _nc, ...nextRest } = next;
return shallowEqual(prevRest, nextRest);
});
/**
* Renders a slot value as a memoized React element.
* Automatically prevents unnecessary re-renders using shallow prop comparison.
* Supports ref forwarding.
*
* @example
* renderSlot(customInput, CopilotChatInput, { onSubmit: handleSubmit })
*/
function renderSlot(slot, DefaultComponent, props) {
return react.default.createElement(MemoizedSlotWrapper, {
...props,
$slot: slot,
$component: DefaultComponent
});
}
//#endregion
//#region src/components/chat/CopilotChatInput.tsx
const SLASH_MENU_MAX_VISIBLE_ITEMS = 5;
const SLASH_MENU_ITEM_HEIGHT_PX = 40;
function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning = false, onStartTranscribe, onCancelTranscribe, onFinishTranscribe, onFinishTranscribeWithAudio, onAddFile, onChange, value, toolsMenu, autoFocus = true, positioning = "static", keyboardHeight = 0, containerRef, showDisclaimer, textArea, sendButton, startTranscribeButton, cancelTranscribeButton, finishTranscribeButton, addMenuButton, audioRecorder, disclaimer, children, className, ...props }) {
var _config$labels;
const isControlled = value !== void 0;
const [internalValue, setInternalValue] = (0, react.useState)(() => value !== null && value !== void 0 ? value : "");
(0, react.useEffect)(() => {
if (!isControlled && value !== void 0) setInternalValue(value);
}, [isControlled, value]);
const resolvedValue = isControlled ? value !== null && value !== void 0 ? value : "" : internalValue;
const [layout, setLayout] = (0, react.useState)("compact");
const ignoreResizeRef = (0, react.useRef)(false);
const resizeEvaluationRafRef = (0, react.useRef)(null);
const isExpanded = mode === "input" && layout === "expanded";
const [commandQuery, setCommandQuery] = (0, react.useState)(null);
const [slashHighlightIndex, setSlashHighlightIndex] = (0, react.useState)(0);
const inputRef = (0, react.useRef)(null);
const gridRef = (0, react.useRef)(null);
const addButtonContainerRef = (0, react.useRef)(null);
const actionsContainerRef = (0, react.useRef)(null);
const audioRecorderRef = (0, react.useRef)(null);
const slashMenuRef = (0, react.useRef)(null);
const config = useCopilotChatConfiguration();
const labels = (_config$labels = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels !== void 0 ? _config$labels : CopilotChatDefaultLabels;
const previousModalStateRef = (0, react.useRef)(void 0);
const measurementCanvasRef = (0, react.useRef)(null);
const measurementsRef = (0, react.useRef)({
singleLineHeight: 0,
maxHeight: 0,
paddingLeft: 0,
paddingRight: 0
});
const commandItems = (0, react.useMemo)(() => {
const entries = [];
const seen = /* @__PURE__ */ new Set();
const pushItem = (item) => {
if (item === "-") return;
if (item.items && item.items.length > 0) {
for (const nested of item.items) pushItem(nested);
return;
}
if (!seen.has(item.label)) {
seen.add(item.label);
entries.push(item);
}
};
if (onAddFile) pushItem({
label: labels.chatInputToolbarAddButtonLabel,
action: onAddFile
});
if (toolsMenu && toolsMenu.length > 0) for (const item of toolsMenu) pushItem(item);
return entries;
}, [
labels.chatInputToolbarAddButtonLabel,
onAddFile,
toolsMenu
]);
const filteredCommands = (0, react.useMemo)(() => {
if (commandQuery === null) return [];
if (commandItems.length === 0) return [];
const query = commandQuery.trim().toLowerCase();
if (query.length === 0) return commandItems;
const startsWith = [];
const contains = [];
for (const item of commandItems) {
const label = item.label.toLowerCase();
if (label.startsWith(query)) startsWith.push(item);
else if (label.includes(query)) contains.push(item);
}
return [...startsWith, ...contains];
}, [commandItems, commandQuery]);
(0, react.useEffect)(() => {
if (!autoFocus) {
previousModalStateRef.current = config === null || config === void 0 ? void 0 : config.isModalOpen;
return;
}
if ((config === null || config === void 0 ? void 0 : config.isModalOpen) && !previousModalStateRef.current) {
var _inputRef$current;
(_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 || _inputRef$current.focus();
}
previousModalStateRef.current = config === null || config === void 0 ? void 0 : config.isModalOpen;
}, [config === null || config === void 0 ? void 0 : config.isModalOpen, autoFocus]);
(0, react.useEffect)(() => {
if (commandItems.length === 0 && commandQuery !== null) setCommandQuery(null);
}, [commandItems.length, commandQuery]);
const previousCommandQueryRef = (0, react.useRef)(null);
(0, react.useEffect)(() => {
if (commandQuery !== null && commandQuery !== previousCommandQueryRef.current && filteredCommands.length > 0) setSlashHighlightIndex(0);
previousCommandQueryRef.current = commandQuery;
}, [commandQuery, filteredCommands.length]);
(0, react.useEffect)(() => {
if (commandQuery === null) {
setSlashHighlightIndex(0);
return;
}
if (filteredCommands.length === 0) setSlashHighlightIndex(-1);
else if (slashHighlightIndex < 0 || slashHighlightIndex >= filteredCommands.length) setSlashHighlightIndex(0);
}, [
commandQuery,
filteredCommands,
slashHighlightIndex
]);
(0, react.useEffect)(() => {
const recorder = audioRecorderRef.current;
if (!recorder) return;
if (mode === "transcribe") recorder.start().catch(console.error);
else if (recorder.state === "recording") recorder.stop().catch(console.error);
}, [mode]);
(0, react.useEffect)(() => {
if (mode !== "input") {
setLayout("compact");
setCommandQuery(null);
}
}, [mode]);
const updateSlashState = (0, react.useCallback)((value) => {
if (commandItems.length === 0) {
setCommandQuery((prev) => prev === null ? prev : null);
return;
}
if (value.startsWith("/")) {
var _value$split$;
const query = ((_value$split$ = value.split(/\r?\n/, 1)[0]) !== null && _value$split$ !== void 0 ? _value$split$ : "").slice(1);
setCommandQuery((prev) => prev === query ? prev : query);
} else setCommandQuery((prev) => prev === null ? prev : null);
}, [commandItems.length]);
(0, react.useEffect)(() => {
updateSlashState(resolvedValue);
}, [resolvedValue, updateSlashState]);
const handleChange = (e) => {
const nextValue = e.target.value;
if (!isControlled) setInternalValue(nextValue);
onChange === null || onChange === void 0 || onChange(nextValue);
updateSlashState(nextValue);
};
const clearInputValue = (0, react.useCallback)(() => {
if (!isControlled) setInternalValue("");
if (onChange) onChange("");
}, [isControlled, onChange]);
const runCommand = (0, react.useCallback)((item) => {
var _item$action;
clearInputValue();
(_item$action = item.action) === null || _item$action === void 0 || _item$action.call(item);
setCommandQuery(null);
setSlashHighlightIndex(0);
requestAnimationFrame(() => {
var _inputRef$current2;
(_inputRef$current2 = inputRef.current) === null || _inputRef$current2 === void 0 || _inputRef$current2.focus();
});
}, [clearInputValue]);
const handleKeyDown = (e) => {
if (commandQuery !== null && mode === "input") {
if (e.key === "ArrowDown") {
if (filteredCommands.length > 0) {
e.preventDefault();
setSlashHighlightIndex((prev) => {
if (filteredCommands.length === 0) return prev;
return prev === -1 ? 0 : (prev + 1) % filteredCommands.length;
});
}
return;
}
if (e.key === "ArrowUp") {
if (filteredCommands.length > 0) {
e.preventDefault();
setSlashHighlightIndex((prev) => {
if (filteredCommands.length === 0) return prev;
if (prev === -1) return filteredCommands.length - 1;
return prev <= 0 ? filteredCommands.length - 1 : prev - 1;
});
}
return;
}
if (e.key === "Enter") {
const selected = slashHighlightIndex >= 0 ? filteredCommands[slashHighlightIndex] : void 0;
if (selected) {
e.preventDefault();
runCommand(selected);
return;
}
}
if (e.key === "Escape") {
e.preventDefault();
setCommandQuery(null);
return;
}
}
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
if (isProcessing) onStop === null || onStop === void 0 || onStop();
else send();
}
};
const send = () => {
if (!onSubmitMessage) return;
const trimmed = resolvedValue.trim();
if (!trimmed) return;
onSubmitMessage(trimmed);
if (!isControlled) {
setInternalValue("");
onChange === null || onChange === void 0 || onChange("");
}
if (inputRef.current) inputRef.current.focus();
};
const BoundTextArea = renderSlot(textArea, CopilotChatInput.TextArea, {
ref: inputRef,
value: resolvedValue,
onChange: handleChange,
onKeyDown: handleKeyDown,
autoFocus,
className: (0, tailwind_merge.twMerge)("cpk:w-full cpk:py-3", isExpanded ? "cpk:px-5" : "cpk:pr-5")
});
const isProcessing = mode !== "transcribe" && isRunning;
const canSend = resolvedValue.trim().length > 0 && !!onSubmitMessage;
const canStop = !!onStop;
const handleSendButtonClick = () => {
if (isProcessing) {
onStop === null || onStop === void 0 || onStop();
return;
}
send();
};
const BoundAudioRecorder = renderSlot(audioRecorder, CopilotChatAudioRecorder, { ref: audioRecorderRef });
const BoundSendButton = renderSlot(sendButton, CopilotChatInput.SendButton, {
onClick: handleSendButtonClick,
disabled: isProcessing ? !canStop : !canSend,
children: isProcessing && canStop ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Square, { className: "cpk:size-[18px] cpk:fill-current" }) : void 0
});
const BoundStartTranscribeButton = renderSlot(startTranscribeButton, CopilotChatInput.StartTranscribeButton, { onClick: onStartTranscribe });
const BoundCancelTranscribeButton = renderSlot(cancelTranscribeButton, CopilotChatInput.CancelTranscribeButton, { onClick: onCancelTranscribe });
const handleFinishTranscribe = (0, react.useCallback)(async () => {
const recorder = audioRecorderRef.current;
if (recorder && recorder.state === "recording") try {
const audioBlob = await recorder.stop();
if (onFinishTranscribeWithAudio) await onFinishTranscribeWithAudio(audioBlob);
} catch (error) {
console.error("Failed to stop recording:", error);
}
onFinishTranscribe === null || onFinishTranscribe === void 0 || onFinishTranscribe();
}, [onFinishTranscribe, onFinishTranscribeWithAudio]);
const BoundFinishTranscribeButton = renderSlot(finishTranscribeButton, CopilotChatInput.FinishTranscribeButton, { onClick: handleFinishTranscribe });
const BoundAddMenuButton = renderSlot(addMenuButton, CopilotChatInput.AddMenuButton, {
disabled: mode === "transcribe",
onAddFile,
toolsMenu
});
const BoundDisclaimer = renderSlot(disclaimer, CopilotChatInput.Disclaimer, {});
const shouldShowDisclaimer = showDisclaimer !== null && showDisclaimer !== void 0 ? showDisclaimer : positioning === "absolute";
if (children) {
const childProps = {
textArea: BoundTextArea,
audioRecorder: BoundAudioRecorder,
sendButton: BoundSendButton,
startTranscribeButton: BoundStartTranscribeButton,
cancelTranscribeButton: BoundCancelTranscribeButton,
finishTranscribeButton: BoundFinishTranscribeButton,
addMenuButton: BoundAddMenuButton,
disclaimer: BoundDisclaimer,
onSubmitMessage,
onStop,
isRunning,
onStartTranscribe,
onCancelTranscribe,
onFinishTranscribe,
onAddFile,
mode,
toolsMenu,
autoFocus,
positioning,
keyboardHeight,
showDisclaimer: shouldShowDisclaimer
};
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-copilotkit": true,
style: { display: "contents" },
children: children(childProps)
});
}
const handleContainerClick = (e) => {
const target = e.target;
if (target.tagName !== "BUTTON" && !target.closest("button") && inputRef.current && mode === "input") inputRef.current.focus();
};
const ensureMeasurements = (0, react.useCallback)(() => {
const textarea = inputRef.current;
if (!textarea) return;
const previousValue = textarea.value;
const previousHeight = textarea.style.height;
textarea.style.height = "auto";
const computedStyle = window.getComputedStyle(textarea);
const paddingLeft = parseFloat(computedStyle.paddingLeft) || 0;
const paddingRight = parseFloat(computedStyle.paddingRight) || 0;
const paddingTop = parseFloat(computedStyle.paddingTop) || 0;
const paddingBottom = parseFloat(computedStyle.paddingBottom) || 0;
textarea.value = "";
const singleLineHeight = textarea.scrollHeight;
textarea.value = previousValue;
const maxHeight = (singleLineHeight - paddingTop - paddingBottom) * 5 + paddingTop + paddingBottom;
measurementsRef.current = {
singleLineHeight,
maxHeight,
paddingLeft,
paddingRight
};
textarea.style.height = previousHeight;
textarea.style.maxHeight = `${maxHeight}px`;
}, []);
const adjustTextareaHeight = (0, react.useCallback)(() => {
const textarea = inputRef.current;
if (!textarea) return 0;
if (measurementsRef.current.singleLineHeight === 0) ensureMeasurements();
const { maxHeight } = measurementsRef.current;
if (maxHeight) textarea.style.maxHeight = `${maxHeight}px`;
textarea.style.height = "auto";
const scrollHeight = textarea.scrollHeight;
if (maxHeight) textarea.style.height = `${Math.min(scrollHeight, maxHeight)}px`;
else textarea.style.height = `${scrollHeight}px`;
return scrollHeight;
}, [ensureMeasurements]);
const updateLayout = (0, react.useCallback)((nextLayout) => {
setLayout((prev) => {
if (prev === nextLayout) return prev;
ignoreResizeRef.current = true;
return nextLayout;
});
}, []);
const evaluateLayout = (0, react.useCallback)(() => {
if (mode !== "input") {
updateLayout("compact");
return;
}
if (typeof window !== "undefined" && typeof window.matchMedia === "function") {
if (window.matchMedia("(max-width: 767px)").matches) {
ensureMeasurements();
adjustTextareaHeight();
updateLayout("expanded");
return;
}
}
const textarea = inputRef.current;
const grid = gridRef.current;
const addContainer = addButtonContainerRef.current;
const actionsContainer = actionsContainerRef.current;
if (!textarea || !grid || !addContainer || !actionsContainer) return;
if (measurementsRef.current.singleLineHeight === 0) ensureMeasurements();
const scrollHeight = adjustTextareaHeight();
const baseline = measurementsRef.current.singleLineHeight;
const hasExplicitBreak = resolvedValue.includes("\n");
const renderedMultiline = baseline > 0 ? scrollHeight > baseline + 1 : false;
let shouldExpand = hasExplicitBreak || renderedMultiline;
if (!shouldExpand) {
const gridStyles = window.getComputedStyle(grid);
const paddingLeft = parseFloat(gridStyles.paddingLeft) || 0;
const paddingRight = parseFloat(gridStyles.paddingRight) || 0;
const columnGap = parseFloat(gridStyles.columnGap) || 0;
const gridAvailableWidth = grid.clientWidth - paddingLeft - paddingRight;
if (gridAvailableWidth > 0) {
var _measurementCanvasRef;
const addWidth = addContainer.getBoundingClientRect().width;
const actionsWidth = actionsContainer.getBoundingClientRect().width;
const compactWidth = Math.max(gridAvailableWidth - addWidth - actionsWidth - columnGap * 2, 0);
const canvas = (_measurementCanvasRef = measurementCanvasRef.current) !== null && _measurementCanvasRef !== void 0 ? _measurementCanvasRef : document.createElement("canvas");
if (!measurementCanvasRef.current) measurementCanvasRef.current = canvas;
const context = canvas.getContext("2d");
if (context) {
const textareaStyles = window.getComputedStyle(textarea);
context.font = textareaStyles.font || `${textareaStyles.fontStyle} ${textareaStyles.fontVariant} ${textareaStyles.fontWeight} ${textareaStyles.fontSize}/${textareaStyles.lineHeight} ${textareaStyles.fontFamily}`;
const compactInnerWidth = Math.max(compactWidth - (measurementsRef.current.paddingLeft || 0) - (measurementsRef.current.paddingRight || 0), 0);
if (compactInnerWidth > 0) {
const lines = resolvedValue.length > 0 ? resolvedValue.split("\n") : [""];
let longestWidth = 0;
for (const line of lines) {
const metrics = context.measureText(line || " ");
if (metrics.width > longestWidth) longestWidth = metrics.width;
}
if (longestWidth > compactInnerWidth) shouldExpand = true;
}
}
}
}
updateLayout(shouldExpand ? "expanded" : "compact");
}, [
adjustTextareaHeight,
ensureMeasurements,
mode,
resolvedValue,
updateLayout
]);
(0, react.useLayoutEffect)(() => {
evaluateLayout();
}, [evaluateLayout]);
(0, react.useEffect)(() => {
if (typeof ResizeObserver === "undefined") return;
const textarea = inputRef.current;
const grid = gridRef.current;
const addContainer = addButtonContainerRef.current;
const actionsContainer = actionsContainerRef.current;
if (!textarea || !grid || !addContainer || !actionsContainer) return;
const scheduleEvaluation = () => {
if (ignoreResizeRef.current) {
ignoreResizeRef.current = false;
return;
}
if (typeof window === "undefined") {
evaluateLayout();
return;
}
if (resizeEvaluationRafRef.current !== null) cancelAnimationFrame(resizeEvaluationRafRef.current);
resizeEvaluationRafRef.current = window.requestAnimationFrame(() => {
resizeEvaluationRafRef.current = null;
evaluateLayout();
});
};
const observer = new ResizeObserver(() => {
scheduleEvaluation();
});
observer.observe(grid);
observer.observe(addContainer);
observer.observe(actionsContainer);
observer.observe(textarea);
return () => {
observer.disconnect();
if (typeof window !== "undefined" && resizeEvaluationRafRef.current !== null) {
cancelAnimationFrame(resizeEvaluationRafRef.current);
resizeEvaluationRafRef.current = null;
}
};
}, [evaluateLayout]);
const slashMenuVisible = commandQuery !== null && commandItems.length > 0;
(0, react.useEffect)(() => {
var _slashMenuRef$current;
if (!slashMenuVisible || slashHighlightIndex < 0) return;
const active = (_slashMenuRef$current = slashMenuRef.current) === null || _slashMenuRef$current === void 0 ? void 0 : _slashMenuRef$current.querySelector(`[data-slash-index="${slashHighlightIndex}"]`);
active === null || active === void 0 || active.scrollIntoView({ block: "nearest" });
}, [slashMenuVisible, slashHighlightIndex]);
const slashMenu = slashMenuVisible ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-testid": "copilot-slash-menu",
role: "listbox",
"aria-label": "Slash commands",
ref: slashMenuRef,
className: "cpk:absolute cpk:bottom-full cpk:left-0 cpk:right-0 cpk:z-30 cpk:mb-2 cpk:max-h-64 cpk:overflow-y-auto cpk:rounded-lg cpk:border cpk:border-border cpk:bg-white cpk:shadow-lg cpk:dark:border-[#3a3a3a] cpk:dark:bg-[#1f1f1f]",
style: { maxHeight: `${SLASH_MENU_MAX_VISIBLE_ITEMS * SLASH_MENU_ITEM_HEIGHT_PX}px` },
children: filteredCommands.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:px-3 cpk:py-2 cpk:text-sm cpk:text-muted-foreground",
children: "No commands found"
}) : filteredCommands.map((item, index) => {
const isActive = index === slashHighlightIndex;
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
type: "button",
role: "option",
"aria-selected": isActive,
"data-active": isActive ? "true" : void 0,
"data-slash-index": index,
className: (0, tailwind_merge.twMerge)("cpk:w-full cpk:px-3 cpk:py-2 cpk:text-left cpk:text-sm cpk:transition-colors", "cpk:hover:bg-muted cpk:dark:hover:bg-[#2f2f2f]", isActive ? "cpk:bg-muted cpk:dark:bg-[#2f2f2f]" : "cpk:bg-transparent"),
onMouseEnter: () => setSlashHighlightIndex(index),
onMouseDown: (event) => {
event.preventDefault();
runCommand(item);
},
children: item.label
}, `${item.label}-${index}`);
})
}) : null;
const inputPill = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-testid": "copilot-chat-input",
className: (0, tailwind_merge.twMerge)("copilotKitInput", "cpk:flex cpk:w-full cpk:flex-col cpk:items-center cpk:justify-center", "cpk:cursor-text", "cpk:overflow-visible cpk:bg-clip-padding cpk:contain-inline-size", "cpk:bg-white cpk:dark:bg-[#303030]", "cpk:shadow-[0_4px_4px_0_#0000000a,0_0_1px_0_#0000009e] cpk:rounded-[28px]"),
onClick: handleContainerClick,
"data-layout": isExpanded ? "expanded" : "compact",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
ref: gridRef,
className: (0, tailwind_merge.twMerge)("cpk:grid cpk:w-full cpk:gap-x-3 cpk:gap-y-3 cpk:px-3 cpk:py-2", isExpanded ? "cpk:grid-cols-[auto_minmax(0,1fr)_auto] cpk:grid-rows-[auto_auto]" : "cpk:grid-cols-[auto_minmax(0,1fr)_auto] cpk:items-center"),
"data-layout": isExpanded ? "expanded" : "compact",
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
ref: addButtonContainerRef,
className: (0, tailwind_merge.twMerge)("cpk:flex cpk:items-center", isExpanded ? "cpk:row-start-2" : "cpk:row-start-1", "cpk:col-start-1"),
children: BoundAddMenuButton
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: (0, tailwind_merge.twMerge)("cpk:relative cpk:flex cpk:min-w-0 cpk:flex-col cpk:min-h-[50px] cpk:justify-center", isExpanded ? "cpk:col-span-3 cpk:row-start-1" : "cpk:col-start-2 cpk:row-start-1"),
children: mode === "transcribe" ? BoundAudioRecorder : mode === "processing" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:flex cpk:w-full cpk:items-center cpk:justify-center cpk:py-3 cpk:px-5",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Loader2, { className: "cpk:size-[26px] cpk:animate-spin cpk:text-muted-foreground" })
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [BoundTextArea, slashMenu] })
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
ref: actionsContainerRef,
className: (0, tailwind_merge.twMerge)("cpk:flex cpk:items-center cpk:justify-end cpk:gap-2", isExpanded ? "cpk:col-start-3 cpk:row-start-2" : "cpk:col-start-3 cpk:row-start-1"),
children: mode === "transcribe" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [onCancelTranscribe && BoundCancelTranscribeButton, onFinishTranscribe && BoundFinishTranscribeButton] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [onStartTranscribe && BoundStartTranscribeButton, BoundSendButton] })
})
]
})
});
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
"data-copilotkit": true,
ref: containerRef,
className: cn(positioning === "absolute" && "cpk:absolute cpk:bottom-0 cpk:left-0 cpk:right-0 cpk:z-20 cpk:pointer-events-none", className),
style: {
transform: keyboardHeight > 0 ? `translateY(-${keyboardHeight}px)` : void 0,
transition: "transform 0.2s ease-out"
},
...props,
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:max-w-3xl cpk:mx-auto cpk:py-0 cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-4 cpk:pointer-events-auto",
children: inputPill
}), shouldShowDisclaimer && BoundDisclaimer]
});
}
(function(_CopilotChatInput) {
_CopilotChatInput.SendButton = ({ className, children, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:mr-[10px]",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
type: "button",
"data-testid": "copilot-send-button",
variant: "chatInputToolbarPrimary",
size: "chatInputToolbarIcon",
className,
...props,
children: children !== null && children !== void 0 ? children : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ArrowUp, { className: "cpk:size-[18px]" })
})
});
const ToolbarButton = _CopilotChatInput.ToolbarButton = ({ icon, labelKey, defaultClassName, className, ...props }) => {
var _config$labels2;
const config = useCopilotChatConfiguration();
const labels = (_config$labels2 = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels2 !== void 0 ? _config$labels2 : CopilotChatDefaultLabels;
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Tooltip, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipTrigger, {
asChild: true,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
type: "button",
variant: "chatInputToolbarSecondary",
size: "chatInputToolbarIcon",
className: (0, tailwind_merge.twMerge)(defaultClassName, className),
...props,
children: icon
})
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipContent, {
side: "bottom",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: labels[labelKey] })
})] });
};
_CopilotChatInput.StartTranscribeButton = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
"data-testid": "copilot-start-transcribe-button",
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Mic, { className: "cpk:size-[18px]" }),
labelKey: "chatInputToolbarStartTranscribeButtonLabel",
defaultClassName: "cpk:mr-2",
...props
});
_CopilotChatInput.CancelTranscribeButton = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
"data-testid": "copilot-cancel-transcribe-button",
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.X, { className: "cpk:size-[18px]" }),
labelKey: "chatInputToolbarCancelTranscribeButtonLabel",
defaultClassName: "cpk:mr-2",
...props
});
_CopilotChatInput.FinishTranscribeButton = (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
"data-testid": "copilot-finish-transcribe-button",
icon: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: "cpk:size-[18px]" }),
labelKey: "chatInputToolbarFinishTranscribeButtonLabel",
defaultClassName: "cpk:mr-[10px]",
...props
});
_CopilotChatInput.AddMenuButton = ({ className, toolsMenu, onAddFile, disabled, ...props }) => {
var _config$labels3;
const config = useCopilotChatConfiguration();
const labels = (_config$labels3 = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels3 !== void 0 ? _config$labels3 : CopilotChatDefaultLabels;
const menuItems = (0, react.useMemo)(() => {
const items = [];
if (onAddFile) items.push({
label: labels.chatInputToolbarAddButtonLabel,
action: onAddFile
});
if (toolsMenu && toolsMenu.length > 0) {
if (items.length > 0) items.push("-");
for (const item of toolsMenu) if (item === "-") {
if (items.length === 0 || items[items.length - 1] === "-") continue;
items.push(item);
} else items.push(item);
while (items.length > 0 && items[items.length - 1] === "-") items.pop();
}
return items;
}, [
onAddFile,
toolsMenu,
labels.chatInputToolbarAddButtonLabel
]);
const renderMenuItems = (0, react.useCallback)((items) => items.map((item, index) => {
if (item === "-") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DropdownMenuSeparator, {}, `separator-${index}`);
if (item.items && item.items.length > 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(DropdownMenuSub, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(DropdownMenuSubTrigger, { children: item.label }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DropdownMenuSubContent, { children: renderMenuItems(item.items) })] }, `group-${index}`);
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DropdownMenuItem, {
onClick: item.action,
children: item.label
}, `item-${index}`);
}), []);
const hasMenuItems = menuItems.length > 0;
const isDisabled = disabled || !hasMenuItems;
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(DropdownMenu, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Tooltip, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipTrigger, {
asChild: true,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DropdownMenuTrigger, {
asChild: true,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
type: "button",
"data-testid": "copilot-add-menu-button",
variant: "chatInputToolbarSecondary",
size: "chatInputToolbarIcon",
className: (0, tailwind_merge.twMerge)("cpk:ml-1", className),
disabled: isDisabled,
...props,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Plus, { className: "cpk:size-[20px]" })
})
})
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipContent, {
side: "bottom",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
className: "cpk:flex cpk:items-center cpk:gap-1 cpk:text-xs cpk:font-medium",
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Add files and more" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
className: "cpk:rounded cpk:bg-[#4a4a4a] cpk:px-1 cpk:py-[1px] cpk:font-mono cpk:text-[11px] cpk:text-white cpk:dark:bg-[#e0e0e0] cpk:dark:text-black",
children: "/"
})]
})
})] }), hasMenuItems && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DropdownMenuContent, {
side: "top",
align: "start",
children: renderMenuItems(menuItems)
})] });
};
_CopilotChatInput.TextArea = (0, react.forwardRef)(function TextArea({ style, className, autoFocus, placeholder, ...props }, ref) {
var _config$labels4;
const internalTextareaRef = (0, react.useRef)(null);
const config = useCopilotChatConfiguration();
const labels = (_config$labels4 = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels4 !== void 0 ? _config$labels4 : CopilotChatDefaultLabels;
(0, react.useImperativeHandle)(ref, () => internalTextareaRef.current);
(0, react.useEffect)(() => {
const textarea = internalTextareaRef.current;
if (!textarea) return;
const handleFocus = () => {
setTimeout(() => {
textarea.scrollIntoView({
behavior: "smooth",
block: "nearest"
});
}, 300);
};
textarea.addEventListener("focus", handleFocus);
return () => textarea.removeEventListener("focus", handleFocus);
}, []);
(0, react.useEffect)(() => {
if (autoFocus) {
var _internalTextareaRef$;
(_internalTextareaRef$ = internalTextareaRef.current) === null || _internalTextareaRef$ === void 0 || _internalTextareaRef$.focus();
}
}, [autoFocus]);
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
ref: internalTextareaRef,
"data-testid": "copilot-chat-textarea",
placeholder: placeholder !== null && placeholder !== void 0 ? placeholder : labels.chatInputPlaceholder,
className: (0, tailwind_merge.twMerge)("cpk:bg-transparent cpk:outline-none cpk:antialiased cpk:font-regular cpk:leading-relaxed cpk:text-[16px] cpk:placeholder:text-[#00000077] cpk:dark:placeholder:text-[#fffc]", className),
style: {
overflow: "auto",
resize: "none",
...style
},
rows: 1,
...props
});
});
_CopilotChatInput.AudioRecorder = CopilotChatAudioRecorder;
_CopilotChatInput.Disclaimer = ({ className, ...props }) => {
var _config$labels5;
const config = useCopilotChatConfiguration();
const labels = (_config$labels5 = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels5 !== void 0 ? _config$labels5 : CopilotChatDefaultLabels;
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: cn("cpk:text-center cpk:text-xs cpk:text-muted-foreground cpk:py-3 cpk:px-4 cpk:max-w-3xl cpk:mx-auto", className),
...props,
children: labels.chatDisclaimerText
});
};
})(CopilotChatInput || (CopilotChatInput = {}));
CopilotChatInput.TextArea.displayName = "CopilotChatInput.TextArea";
CopilotChatInput.SendButton.displayName = "CopilotChatInput.SendButton";
CopilotChatInput.ToolbarButton.displayName = "CopilotChatInput.ToolbarButton";
CopilotChatInput.StartTranscribeButton.displayName = "CopilotChatInput.StartTranscribeButton";
CopilotChatInput.CancelTranscribeButton.displayName = "CopilotChatInput.CancelTranscribeButton";
CopilotChatInput.FinishTranscribeButton.displayName = "CopilotChatInput.FinishTranscribeButton";
CopilotChatInput.AddMenuButton.displayName = "CopilotChatInput.AddMenuButton";
CopilotChatInput.Disclaimer.displayName = "CopilotChatInput.Disclaimer";
var CopilotChatInput_default = CopilotChatInput;
//#endregion
//#region src/hooks/useKatexStyles.ts
let injected = false;
/**
* Dynamically injects KaTeX CSS at runtime to avoid the Next.js
* "Global CSS cannot be imported from within node_modules" build error.
*
* Uses a singleton flag so the stylesheet is only injected once.
*/
function useKatexStyles() {
(0, react.useEffect)(() => {
if (injected || typeof document === "undefined") return;
injected = true;
import("katex/dist/katex.min.css").catch(() => {});
}, []);
}
//#endregion
//#region src/components/CopilotKitInspector.tsx
const CopilotKitInspector = ({ core, ...rest }) => {
const [InspectorComponent, setInspectorComponent] = react.useState(null);
react.useEffect(() => {
let mounted = true;
import("@copilotkitnext/web-inspector").then((mod) => {
var _mod$defineWebInspect;
(_mod$defineWebInspect = mod.defineWebInspector) === null || _mod$defineWebInspect === void 0 || _mod$defineWebInspect.call(mod);
const Component = (0, _lit_labs_react.createComponent)({
tagName: mod.WEB_INSPECTOR_TAG,
elementClass: mod.WebInspectorElement,
react
});
if (mounted) setInspectorComponent(() => Component);
});
return () => {
mounted = false;
};
}, []);
if (!InspectorComponent) return null;
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InspectorComponent, {
...rest,
core: core !== null && core !== void 0 ? core : null
});
};
CopilotKitInspector.displayName = "CopilotKitInspector";
//#endregion
//#region \0@oxc-project+runtime@0.112.0/helpers/typeof.js
function _typeof(o) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function(o) {
return typeof o;
} : function(o) {
return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o;
}, _typeof(o);
}
//#endregion
//#region \0@oxc-project+runtime@0.112.0/helpers/toPrimitive.js
function toPrimitive(t, r) {
if ("object" != _typeof(t) || !t) return t;
var e = t[Symbol.toPrimitive];
if (void 0 !== e) {
var i = e.call(t, r || "default");
if ("object" != _typeof(i)) return i;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return ("string" === r ? String : Number)(t);
}
//#endregion
//#region \0@oxc-project+runtime@0.112.0/helpers/toPropertyKey.js
function toPropertyKey(t) {
var i = toPrimitive(t, "string");
return "symbol" == _typeof(i) ? i : i + "";
}
//#endregion
//#region \0@oxc-project+runtime@0.112.0/helpers/defineProperty.js
function _defineProperty(e, r, t) {
return (r = toPropertyKey(r)) in e ? Object.defineProperty(e, r, {
value: t,
enumerable: !0,
configurable: !0,
writable: !0
}) : e[r] = t, e;
}
//#endregion
//#region src/components/MCPAppsActivityRenderer.tsx
const PROTOCOL_VERSION = "2025-06-18";
function buildSandboxHTML(extraCspDomains) {
const baseScriptSrc = "'self' 'wasm-unsafe-eval' 'unsafe-inline' 'unsafe-eval' blob: data: http://localhost:* https://localhost:*";
const baseFrameSrc = "* blob: data: http://localhost:* https://localhost:*";
const extra = (extraCspDomains === null || extraCspDomains === void 0 ? void 0 : extraCspDomains.length) ? " " + extraCspDomains.join(" ") : "";
return `<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src * data: blob: 'unsafe-inline'; media-src * blob: data:; font-src * blob: data:; script-src ${baseScriptSrc + extra}; style-src * blob: data: 'unsafe-inline'; connect-src *; frame-src ${baseFrameSrc + extra}; base-uri 'self';" />
<style>html,body{margin:0;padding:0;height:100%;width:100%;overflow:hidden}*{box-sizing:border-box}iframe{background-color:transparent;border:none;padding:0;overflow:hidden;width:100%;height:100%}</style>
</head>
<body>
<script>
if(window.self===window.top){throw new Error("This file must be used in an iframe.")}
const inner=document.createElement("iframe");
inner.style="width:100%;height:100%;border:none;";
inner.setAttribute("sandbox","allow-scripts allow-same-origin allow-forms");
document.body.appendChild(inner);
window.addEventListener("message",async(event)=>{
if(event.source===window.parent){
if(event.data&&event.data.method==="ui/notifications/sandbox-resource-ready"){
const{html,sandbox}=event.data.params;
if(typeof sandbox==="string")inner.setAttribute("sandbox",sandbox);
if(typeof html==="string")inner.srcdoc=html;
}else if(inner&&inner.contentWindow){
inner.contentWindow.postMessage(event.data,"*");
}
}else if(event.source===inner.contentWindow){
window.parent.postMessage(event.data,"*");
}
});
window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-ready",params:{}},"*");
<\/script>
</body>
</html>`;
}
/**
* Queue for serializing MCP app requests to an agent.
* Ensures requests wait for the agent to stop running and are processed one at a time.
*/
var MCPAppsRequestQueue = class {
constructor() {
_defineProperty(this, "queues", /* @__PURE__ */ new Map());
_defineProperty(this, "processing", /* @__PURE__ */ new Map());
}
/**
* Add a request to the queue for a specific agent thread.
* Returns a promise that resolves when the request completes.
*/
async enqueue(agent, request) {
const threadId = agent.threadId || "default";
return new Promise((resolve, reject) => {
let queue = this.queues.get(threadId);
if (!queue) {
queue = [];
this.queues.set(threadId, queue);
}
queue.push({
execute: request,
resolve,
reject
});
this.processQueue(threadId, agent);
});
}
async processQueue(threadId, agent) {
if (this.processing.get(threadId)) return;
this.processing.set(threadId, true);
try {
const queue = this.queues.get(threadId);
if (!queue) return;
while (queue.length > 0) {
const item = queue[0];
try {
await this.waitForAgentIdle(agent);
const result = await item.execute();
item.resolve(result);
} catch (error) {
item.reject(error instanceof Error ? error : new Error(String(error)));
}
queue.shift();
}
} finally {
this.processing.set(threadId, false);
}
}
waitForAgentIdle(agent) {
return new Promise((resolve) => {
if (!agent.isRunning) {
resolve();
return;
}
let done = false;
const finish = () => {
if (done) return;
done = true;
clearInterval(checkInterval);
sub.unsubscribe();
resolve();
};
const sub = agent.subscribe({
onRunFinalized: finish,
onRunFailed: finish
});
const checkInterval = setInterval(() => {
if (!agent.isRunning) finish();
}, 500);
});
}
};
const mcpAppsRequestQueue = new MCPAppsRequestQueue();
/**
* Activity type for MCP Apps events - must match the middleware's MCPAppsActivityType
*/
const MCPAppsActivityType = "mcp-apps";
const MCPAppsActivityContentSchema = zod.z.object({
result: zod.z.object({
content: zod.z.array(zod.z.any()).optional(),
structuredContent: zod.z.any().optional(),
isError: zod.z.boolean().optional()
}),
resourceUri: zod.z.string(),
serverHash: zod.z.string(),
serverId: zod.z.string().optional(),
toolInput: zod.z.record(zod.z.unknown()).optional()
});
function isRequest(msg) {
return "id" in msg && "method" in msg;
}
function isNotification(msg) {
return !("id" in msg) && "method" in msg;
}
/**
* MCP Apps Extension Activity Renderer
*
* Renders MCP Apps UI in a sandboxed iframe with full protocol support.
* Fetches resource content on-demand via proxied MCP requests.
*/
const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, agent }) {
var _fetchedResource$_met2;
const containerRef = (0, react.useRef)(null);
const iframeRef = (0, react.useRef)(null);
const [iframeReady, setIframeReady] = (0, react.useState)(false);
const [error, setError] = (0, react.useState)(null);
const [isLoading, setIsLoading] = (0, react.useState)(true);
const [iframeSize, setIframeSize] = (0, react.useState)({});
const [fetchedResource, setFetchedResource] = (0, react.useState)(null);
const contentRef = (0, react.useRef)(content);
contentRef.current = content;
const agentRef = (0, react.useRef)(agent);
agentRef.current = agent;
const fetchStateRef = (0, react.useRef)({
inProgress: false,
promise: null,
resourceUri: null
});
const sendToIframe = (0, react.useCallback)((msg) => {
var _iframeRef$current;
if ((_iframeRef$current = iframeRef.current) === null || _iframeRef$current === void 0 ? void 0 : _iframeRef$current.contentWindow) {
console.log("[MCPAppsRenderer] Sending to iframe:", msg);
iframeRef.current.contentWindow.postMessage(msg, "*");
}
}, []);
const sendResponse = (0, react.useCallback)((id, result) => {
sendToIframe({
jsonrpc: "2.0",
id,
result
});
}, [sendToIframe]);
const sendErrorResponse = (0, react.useCallback)((id, code, message) => {
sendToIframe({
jsonrpc: "2.0",
id,
error: {
code,
message
}
});
}, [sendToIframe]);
const sendNotification = (0, react.useCallback)((method, params) => {
sendToIframe({
jsonrpc: "2.0",
method,
params: params || {}
});
}, [sendToIframe]);
(0, react.useEffect)(() => {
const { resourceUri, serverHash, serverId } = content;
if (fetchStateRef.current.inProgress && fetchStateRef.current.resourceUri === resourceUri) {
var _fetchStateRef$curren;
(_fetchStateRef$curren = fetchStateRef.current.promise) === null || _fetchStateRef$curren === void 0 || _fetchStateRef$curren.then((resource) => {
if (resource) {
setFetchedResource(resource);
setIsLoading(false);
}
}).catch((err) => {
setError(err instanceof Error ? err : new Error(String(err)));
setIsLoading(false);
});
return;
}
if (!agent) {
setError(/* @__PURE__ */ new Error("No agent available to fetch resource"));
setIsLoading(false);
return;
}
fetchStateRef.current.inProgress = true;
fetchStateRef.current.resourceUri = resourceUri;
const fetchPromise = (async () => {
try {
var _resultData$contents;
const resultData = (await mcpAppsRequestQueue.enqueue(agent, () => agent.runAgent({ forwardedProps: { __proxiedMCPRequest: {
serverHash,
serverId,
method: "resources/read",
params: { uri: resourceUri }
} } }))).result;
const resource = resultData === null || resultData === void 0 || (_resultData$contents = resultData.contents) === null || _resultData$contents === void 0 ? void 0 : _resultData$contents[0];
if (!resource) throw new Error("No resource content in response");
return resource;
} catch (err) {
console.error("[MCPAppsRenderer] Failed to fetch resource:", err);
throw err;
} finally {
fetchStateRef.current.inProgress = false;
}
})();
fetchStateRef.current.promise = fetchPromise;
fetchPromise.then((resource) => {
if (resource) {
setFetchedResource(resource);
setIsLoading(false);
}
}).catch((err) => {
setError(err instanceof Error ? err : new Error(String(err)));
setIsLoading(false);
});
}, [agent, content]);
(0, react.useEffect)(() => {
if (isLoading || !fetchedResource) return;
const container = containerRef.current;
if (!container) return;
let mounted = true;
let messageHandler = null;
let initialListener = null;
let createdIframe = null;
const setup = async () => {
try {
var _fetchedResource$_met;
const iframe = document.createElement("iframe");
createdIframe = iframe;
iframe.style.width = "100%";
iframe.style.height = "100px";
iframe.style.border = "none";
iframe.style.backgroundColor = "transparent";
iframe.style.display = "block";
iframe.setAttribute("sandbox", "allow-scripts allow-same-origin allow-forms");
const sandboxReady = new Promise((resolve) => {
initialListener = (event) => {
if (event.source === iframe.contentWindow) {
var _event$data;
if (((_event$data = event.data) === null || _event$data === void 0 ? void 0 : _event$data.method) === "ui/notifications/sandbox-proxy-ready") {
if (initialListener) {
window.removeEventListener("message", initialListener);
initialListener = null;
}
resolve();
}
}
};
window.addEventListener("message", initialListener);
});
if (!mounted) {
if (initialListener) {
window.removeEventListener("message", initialListener);
initialListener = null;
}
return;
}
iframe.srcdoc = buildSandboxHTML((_fetchedResource$_met = fetchedResource._meta) === null || _fetchedResource$_met === void 0 || (_fetchedResource$_met = _fetchedResource$_met.ui) === null || _fetchedResource$_met === void 0 || (_fetchedResource$_met = _fetchedResource$_met.csp) === null || _fetchedResource$_met === void 0 ? void 0 : _fetchedResource$_met.resourceDomains);
iframeRef.current = iframe;
container.appendChild(iframe);
await sandboxReady;
if (!mounted) return;
console.log("[MCPAppsRenderer] Sandbox proxy ready");
messageHandler = async (event) => {
if (event.source !== iframe.contentWindow) return;
const msg = event.data;
if (!msg || typeof msg !== "object" || msg.jsonrpc !== "2.0") return;
console.log("[MCPAppsRenderer] Received from iframe:", msg);
if (isRequest(msg)) switch (msg.method) {
case "ui/initialize":
sendResponse(msg.id, {
protocolVersion: PROTOCOL_VERSION,
hostInfo: {
name: "CopilotKit MCP Apps Host",
version: "1.0.0"
},
hostCapabilities: {
openLinks: {},
logging: {}
},
hostContext: {
theme: "light",
platform: "web"
}
});
break;
case "ui/message": {
const currentAgent = agentRef.current;
if (!currentAgent) {
console.warn("[MCPAppsRenderer] ui/message: No agent available");
sendResponse(msg.id, { isError: false });
break;
}
try {
var _params$content;
const params = msg.params;
const textContent = ((_params$content = params.content) === null || _params$content === void 0 ? void 0 : _params$content.filter((c) => c.type === "text" && c.text).map((c) => c.text).join("\n")) || "";
if (textContent) currentAgent.addMessage({
id: crypto.randomUUID(),
role: params.role || "user",
content: textContent
});
sendResponse(msg.id, { isError: false });
} catch (err) {
console.error("[MCPAppsRenderer] ui/message error:", err);
sendResponse(msg.id, { isError: true });
}
break;
}
case "ui/open-link": {
var _msg$params;
const url = (_msg$params = msg.params) === null || _msg$params === void 0 ? void 0 : _msg$params.url;
if (url) {
window.open(url, "_blank", "noopener,noreferrer");
sendResponse(msg.id, { isError: false });
} else sendErrorResponse(msg.id, -32602, "Missing url parameter");
break;
}
case "tools/call": {
const { serverHash, serverId } = contentRef.current;
const currentAgent = agentRef.current;
if (!serverHash) {
sendErrorResponse(msg.id, -32603, "No server hash available for proxying");
break;
}
if (!currentAgent) {
sendErrorResponse(msg.id, -32603, "No agent available for proxying");
break;
}
try {
const runResult = await mcpAppsRequestQueue.enqueue(currentAgent, () => currentAgent.runAgent({ forwardedProps: { __proxiedMCPRequest: {
serverHash,
serverId,
method: "tools/call",
params: msg.params
} } }));
sendResponse(msg.id, runResult.result || {});
} catch (err) {
console.error("[MCPAppsRenderer] tools/call error:", err);
sendErrorResponse(msg.id, -32603, String(err));
}
break;
}
default: sendErrorResponse(msg.id, -32601, `Method not found: ${msg.method}`);
}
if (isNotification(msg)) switch (msg.method) {
case "ui/notifications/initialized":
console.log("[MCPAppsRenderer] Inner iframe initialized");
if (mounted) setIframeReady(true);
break;
case "ui/notifications/size-changed": {
const { width, height } = msg.params || {};
console.log("[MCPAppsRenderer] Size change:", {
width,
height
});
if (mounted) setIframeSize({
width: typeof width === "number" ? width : void 0,
height: typeof height === "number" ? height : void 0
});
break;
}
case "notifications/message":
console.log("[MCPAppsRenderer] App log:", msg.params);
break;
}
};
window.addEventListener("message", messageHandler);
let html;
if (fetchedResource.text) html = fetchedResource.text;
else if (fetchedResource.blob) html = atob(fetchedResource.blob);
else throw new Error("Resource has no text or blob content");
sendNotification("ui/notifications/sandbox-resource-ready", { html });
} catch (err) {
console.error("[MCPAppsRenderer] Setup error:", err);
if (mounted) setError(err instanceof Error ? err : new Error(String(err)));
}
};
setup();
return () => {
mounted = false;
if (initialListener) {
window.removeEventListener("message", initialListener);
initialListener = null;
}
if (messageHandler) window.removeEventListener("message", messageHandler);
if (createdIframe) {
createdIframe.remove();
createdIframe = null;
}
iframeRef.current = null;
};
}, [
isLoading,
fetchedResource,
sendNotification,
sendResponse,
sendErrorResponse
]);
(0, react.useEffect)(() => {
if (iframeRef.current) {
if (iframeSize.width !== void 0) {
iframeRef.current.style.minWidth = `min(${iframeSize.width}px, 100%)`;
iframeRef.current.style.width = "100%";
}
if (iframeSize.height !== void 0) iframeRef.current.style.height = `${iframeSize.height}px`;
}
}, [iframeSize]);
(0, react.useEffect)(() => {
if (iframeReady && content.toolInput) {
console.log("[MCPAppsRenderer] Sending tool input:", content.toolInput);
sendNotification("ui/notifications/tool-input", { arguments: content.toolInput });
}
}, [
iframeReady,
content.toolInput,
sendNotification
]);
(0, react.useEffect)(() => {
if (iframeReady && content.result) {
console.log("[MCPAppsRenderer] Sending tool result:", content.result);
sendNotification("ui/notifications/tool-result", content.result);
}
}, [
iframeReady,
content.result,
sendNotification
]);
const borderStyle = (fetchedResource === null || fetchedResource === void 0 || (_fetchedResource$_met2 = fetchedResource._meta) === null || _fetchedResource$_met2 === void 0 || (_fetchedResource$_met2 = _fetchedResource$_met2.ui) === null || _fetchedResource$_met2 === void 0 ? void 0 : _fetchedResource$_met2.prefersBorder) === true ? {
borderRadius: "8px",
backgroundColor: "#f9f9f9",
border: "1px solid #e0e0e0"
} : {};
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
ref: containerRef,
style: {
width: "100%",
height: iframeSize.height ? `${iframeSize.height}px` : "auto",
minHeight: "100px",
overflow: "hidden",
position: "relative",
...borderStyle
},
children: [isLoading && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
style: {
padding: "1rem",
color: "#666"
},
children: "Loading..."
}), error && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
style: {
color: "red",
padding: "1rem"
},
children: ["Error: ", error.message]
})]
});
};
//#endregion
//#region src/a2ui/A2UIMessageRenderer.tsx
let initialized = false;
function ensureInitialized() {
if (!initialized) {
(0, _copilotkit_a2ui_renderer.initializeDefaultCatalog)();
(0, _copilotkit_a2ui_renderer.injectStyles)();
initialized = true;
}
}
function createA2UIMessageRenderer(options) {
const { theme } = options;
return {
activityType: "a2ui-surface",
content: zod.z.any(),
render: ({ content, agent }) => {
ensureInitialized();
const [operations, setOperations] = (0, react.useState)([]);
const lastSignatureRef = (0, react.useRef)(null);
const { copilotkit } = useCopilotKit();
(0, react.useEffect)(() => {
if (!content || !Array.isArray(content.operations)) {
lastSignatureRef.current = null;
setOperations([]);
return;
}
const incoming = content.operations;
const signature = stringifyOperations(incoming);
if (signature && signature === lastSignatureRef.current) return;
lastSignatureRef.current = signature;
setOperations(incoming);
}, [content]);
const groupedOperations = (0, react.useMemo)(() => {
const groups = /* @__PURE__ */ new Map();
for (const operation of operations) {
var _getOperationSurfaceI;
const surfaceId = (_getOperationSurfaceI = getOperationSurfaceId(operation)) !== null && _getOperationSurfaceI !== void 0 ? _getOperationSurfaceI : _copilotkit_a2ui_renderer.DEFAULT_SURFACE_ID;
if (!groups.has(surfaceId)) groups.set(surfaceId, []);
groups.get(surfaceId).push(operation);
}
return groups;
}, [operations]);
if (!groupedOperations.size) return null;
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:flex cpk:min-h-0 cpk:flex-1 cpk:flex-col cpk:gap-6 cpk:overflow-auto cpk:py-6",
children: Array.from(groupedOperations.entries()).map(([surfaceId, ops]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReactSurfaceHost, {
surfaceId,
operations: ops,
theme,
agent,
copilotkit
}, surfaceId))
});
}
};
}
/**
* Renders a single A2UI surface using the React renderer.
* Wraps A2UIProvider + A2UIRenderer and bridges actions back to CopilotKit.
*/
function ReactSurfaceHost({ surfaceId, operations, theme, agent, copilotkit }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:flex cpk:w-full cpk:flex-none cpk:flex-col cpk:gap-4",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_copilotkit_a2ui_renderer.A2UIProvider, {
onAction: (0, react.useCallback)(async (message) => {
if (!agent) return;
try {
var _copilotkit$propertie;
console.info("[A2UI] Action dispatched", message.userAction);
copilotkit.setProperties({
...(_copilotkit$propertie = copilotkit.properties) !== null && _copilotkit$propertie !== void 0 ? _copilotkit$propertie : {},
a2uiAction: message
});
await copilotkit.runAgent({ agent });
} finally {
if (copilotkit.properties) {
const { a2uiAction, ...rest } = copilotkit.properties;
copilotkit.setProperties(rest);
}
}
}, [agent, copilotkit]),
theme,
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SurfaceMessageProcessor, {
surfaceId,
operations
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_copilotkit_a2ui_renderer.A2UIRenderer, {
surfaceId,
className: "cpk:flex cpk:flex-1"
})]
})
});
}
/**
* Processes A2UI operations into the provider's message processor.
* Must be a child of A2UIProvider to access the actions context.
*/
function SurfaceMessageProcessor({ surfaceId, operations }) {
const { processMessages } = (0, _copilotkit_a2ui_renderer.useA2UIActions)();
const lastProcessedRef = (0, react.useRef)("");
(0, react.useEffect)(() => {
const key = `${surfaceId}-${JSON.stringify(operations)}`;
if (key === lastProcessedRef.current) return;
lastProcessedRef.current = key;
processMessages(operations);
}, [
processMessages,
surfaceId,
operations
]);
return null;
}
function getOperationSurfaceId(operation) {
var _ref, _ref2, _ref3, _operation$beginRende, _operation$beginRende2, _operation$surfaceUpd, _operation$dataModelU, _operation$deleteSurf;
if (!operation || typeof operation !== "object") return null;
if (typeof operation.surfaceId === "string") return operation.surfaceId;
return (_ref = (_ref2 = (_ref3 = (_operation$beginRende = operation === null || operation === void 0 || (_operation$beginRende2 = operation.beginRendering) === null || _operation$beginRende2 === void 0 ? void 0 : _operation$beginRende2.surfaceId) !== null && _operation$beginRende !== void 0 ? _operation$beginRende : operation === null || operation === void 0 || (_operation$surfaceUpd = operation.surfaceUpdate) === null || _operation$surfaceUpd === void 0 ? void 0 : _operation$surfaceUpd.surfaceId) !== null && _ref3 !== void 0 ? _ref3 : operation === null || operation === void 0 || (_operation$dataModelU = operation.dataModelUpdate) === null || _operation$dataModelU === void 0 ? void 0 : _operation$dataModelU.surfaceId) !== null && _ref2 !== void 0 ? _ref2 : operation === null || operation === void 0 || (_operation$deleteSurf = operation.deleteSurface) === null || _operation$deleteSurf === void 0 ? void 0 : _operation$deleteSurf.surfaceId) !== null && _ref !== void 0 ? _ref : null;
}
function stringifyOperations(ops) {
try {
return JSON.stringify(ops);
} catch (error) {
return null;
}
}
//#endregion
//#region src/lib/react-core.ts
var CopilotKitCoreReact = class extends _copilotkitnext_core.CopilotKitCore {
constructor(config) {
var _config$renderToolCal, _config$renderCustomM, _config$renderActivit;
super(config);
_defineProperty(this, "_renderToolCalls", []);
_defineProperty(this, "_hookRenderToolCalls", /* @__PURE__ */ new Map());
_defineProperty(this, "_cachedMergedRenderToolCalls", null);
_defineProperty(this, "_renderCustomMessages", []);
_defineProperty(this, "_renderActivityMessages", []);
_defineProperty(this, "_interruptElement", null);
this._renderToolCalls = (_config$renderToolCal = config.renderToolCalls) !== null && _config$renderToolCal !== void 0 ? _config$renderToolCal : [];
this._renderCustomMessages = (_config$renderCustomM = config.renderCustomMessages) !== null && _config$renderCustomM !== void 0 ? _config$renderCustomM : [];
this._renderActivityMessages = (_config$renderActivit = config.renderActivityMessages) !== null && _config$renderActivit !== void 0 ? _config$renderActivit : [];
}
get renderCustomMessages() {
return this._renderCustomMessages;
}
get renderActivityMessages() {
return this._renderActivityMessages;
}
get renderToolCalls() {
if (this._hookRenderToolCalls.size === 0) return this._renderToolCalls;
if (this._cachedMergedRenderToolCalls) return this._cachedMergedRenderToolCalls;
const merged = /* @__PURE__ */ new Map();
for (const rc of this._renderToolCalls) {
var _rc$agentId;
merged.set(`${(_rc$agentId = rc.agentId) !== null && _rc$agentId !== void 0 ? _rc$agentId : ""}:${rc.name}`, rc);
}
for (const [key, rc] of this._hookRenderToolCalls) merged.set(key, rc);
this._cachedMergedRenderToolCalls = Array.from(merged.values());
return this._cachedMergedRenderToolCalls;
}
setRenderActivityMessages(renderers) {
this._renderActivityMessages = renderers;
}
setRenderCustomMessages(renderers) {
this._renderCustomMessages = renderers;
}
setRenderToolCalls(renderToolCalls) {
this._renderToolCalls = renderToolCalls;
this._cachedMergedRenderToolCalls = null;
this._notifyRenderToolCallsChanged();
}
addHookRenderToolCall(entry) {
var _entry$agentId;
const key = `${(_entry$agentId = entry.agentId) !== null && _entry$agentId !== void 0 ? _entry$agentId : ""}:${entry.name}`;
this._hookRenderToolCalls.set(key, entry);
this._cachedMergedRenderToolCalls = null;
this._notifyRenderToolCallsChanged();
}
removeHookRenderToolCall(name, agentId) {
const key = `${agentId !== null && agentId !== void 0 ? agentId : ""}:${name}`;
if (this._hookRenderToolCalls.delete(key)) {
this._cachedMergedRenderToolCalls = null;
this._notifyRenderToolCallsChanged();
}
}
_notifyRenderToolCallsChanged() {
this.notifySubscribers((subscriber) => {
const reactSubscriber = subscriber;
if (reactSubscriber.onRenderToolCallsChanged) reactSubscriber.onRenderToolCallsChanged({
copilotkit: this,
renderToolCalls: this.renderToolCalls
});
}, "Subscriber onRenderToolCallsChanged error:");
}
get interruptElement() {
return this._interruptElement;
}
setInterruptElement(element) {
this._interruptElement = element;
this.notifySubscribers((subscriber) => {
var _reactSubscriber$onIn;
const reactSubscriber = subscriber;
(_reactSubscriber$onIn = reactSubscriber.onInterruptElementChanged) === null || _reactSubscriber$onIn === void 0 || _reactSubscriber$onIn.call(reactSubscriber, {
copilotkit: this,
interruptElement: this._interruptElement
});
}, "Subscriber onInterruptElementChanged error:");
}
subscribe(subscriber) {
return super.subscribe(subscriber);
}
/**
* Wait for pending React state updates before the follow-up agent run.
*
* When a frontend tool handler calls setState(), React 18 batches the update
* and schedules a commit via its internal scheduler (MessageChannel). The
* useAgentContext hook registers context via useLayoutEffect, which runs
* synchronously after React commits that batch.
*
* Awaiting a zero-delay timeout yields to the macrotask queue. React's
* MessageChannel task runs first, committing the pending state and running
* useLayoutEffect (which updates the context store). The follow-up runAgent
* call then reads fresh context.
*/
async waitForPendingFrameworkUpdates() {
await new Promise((resolve) => setTimeout(resolve, 0));
}
};
//#endregion
//#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 !== null && prop !== void 0 ? 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) => {
var _rc$agentId, _rc$name;
return `${(_rc$agentId = rc === null || rc === void 0 ? void 0 : rc.agentId) !== null && _rc$agentId !== void 0 ? _rc$agentId : ""}:${(_rc$name = rc === null || rc === void 0 ? void 0 : rc.name) !== null && _rc$name !== void 0 ? _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: MCPAppsActivityType,
content: MCPAppsActivityContentSchema,
render: MCPAppsActivityRenderer
}];
if (runtimeA2UIEnabled) {
var _a2ui$theme;
renderers.unshift(createA2UIMessageRenderer({ theme: (_a2ui$theme = a2ui === null || a2ui === void 0 ? void 0 : a2ui.theme) !== null && _a2ui$theme !== void 0 ? _a2ui$theme : _copilotkit_a2ui_renderer.viewerTheme }));
}
return renderers;
}, [runtimeA2UIEnabled, a2ui]);
const allActivityRenderers = (0, react.useMemo)(() => {
return [...renderActivityMessagesList, ...builtInActivityRenderers];
}, [renderActivityMessagesList, builtInActivityRenderers]);
const resolvedPublicKey = publicApiKey !== null && publicApiKey !== void 0 ? 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 !== null && runtimeUrl !== void 0 ? 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 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) => {
var _onErrorRef$current;
(_onErrorRef$current = onErrorRef.current) === null || _onErrorRef$current === void 0 || _onErrorRef$current.call(onErrorRef, {
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)(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
//#region src/hooks/use-render-tool-call.tsx
/**
* Memoized component that renders a single tool call.
* This prevents unnecessary re-renders when parent components update
* but the tool call data hasn't changed.
*/
const ToolCallRenderer = react.default.memo(function ToolCallRenderer({ toolCall, toolMessage, RenderComponent, isExecuting }) {
const args = (0, react.useMemo)(() => (0, _copilotkitnext_shared.partialJSONParse)(toolCall.function.arguments), [toolCall.function.arguments]);
const toolName = toolCall.function.name;
if (toolMessage) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
name: toolName,
args,
status: _copilotkitnext_core.ToolCallStatus.Complete,
result: toolMessage.content
});
else if (isExecuting) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
name: toolName,
args,
status: _copilotkitnext_core.ToolCallStatus.Executing,
result: void 0
});
else return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
name: toolName,
args,
status: _copilotkitnext_core.ToolCallStatus.InProgress,
result: void 0
});
}, (prevProps, nextProps) => {
var _prevProps$toolMessag, _nextProps$toolMessag;
if (prevProps.toolCall.id !== nextProps.toolCall.id) return false;
if (prevProps.toolCall.function.name !== nextProps.toolCall.function.name) return false;
if (prevProps.toolCall.function.arguments !== nextProps.toolCall.function.arguments) return false;
if (((_prevProps$toolMessag = prevProps.toolMessage) === null || _prevProps$toolMessag === void 0 ? void 0 : _prevProps$toolMessag.content) !== ((_nextProps$toolMessag = nextProps.toolMessage) === null || _nextProps$toolMessag === void 0 ? void 0 : _nextProps$toolMessag.content)) return false;
if (prevProps.isExecuting !== nextProps.isExecuting) return false;
if (prevProps.RenderComponent !== nextProps.RenderComponent) return false;
return true;
});
/**
* Hook that returns a function to render tool calls based on the render functions
* defined in CopilotKitProvider.
*
* @returns A function that takes a tool call and optional tool message and returns the rendered component
*/
function useRenderToolCall() {
var _config$agentId;
const { copilotkit, executingToolCallIds } = useCopilotKit();
const config = useCopilotChatConfiguration();
const agentId = (_config$agentId = config === null || config === void 0 ? void 0 : config.agentId) !== null && _config$agentId !== void 0 ? _config$agentId : _copilotkitnext_shared.DEFAULT_AGENT_ID;
const renderToolCalls = (0, react.useSyncExternalStore)((callback) => {
return copilotkit.subscribe({ onRenderToolCallsChanged: callback }).unsubscribe;
}, () => copilotkit.renderToolCalls, () => copilotkit.renderToolCalls);
return (0, react.useCallback)(({ toolCall, toolMessage }) => {
const exactMatches = renderToolCalls.filter((rc) => rc.name === toolCall.function.name);
const renderConfig = exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || renderToolCalls.find((rc) => rc.name === "*");
if (!renderConfig) return null;
const RenderComponent = renderConfig.render;
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolCallRenderer, {
toolCall,
toolMessage,
RenderComponent,
isExecuting: executingToolCallIds.has(toolCall.id)
}, toolCall.id);
}, [
renderToolCalls,
executingToolCallIds,
agentId
]);
}
//#endregion
//#region src/hooks/use-render-custom-messages.tsx
function useRenderCustomMessages() {
const { copilotkit } = useCopilotKit();
const config = useCopilotChatConfiguration();
if (!config) return null;
const { agentId, threadId } = config;
const customMessageRenderers = copilotkit.renderCustomMessages.filter((renderer) => renderer.agentId === void 0 || renderer.agentId === agentId).sort((a, b) => {
const aHasAgent = a.agentId !== void 0;
if (aHasAgent === (b.agentId !== void 0)) return 0;
return aHasAgent ? -1 : 1;
});
return function(params) {
var _copilotkit$getRunIdF;
if (!customMessageRenderers.length) return null;
const { message, position } = params;
const resolvedRunId = (_copilotkit$getRunIdF = copilotkit.getRunIdForMessage(agentId, threadId, message.id)) !== null && _copilotkit$getRunIdF !== void 0 ? _copilotkit$getRunIdF : copilotkit.getRunIdsForThread(agentId, threadId).slice(-1)[0];
const runId = resolvedRunId !== null && resolvedRunId !== void 0 ? resolvedRunId : `missing-run-id:${message.id}`;
const agent = copilotkit.getAgent(agentId);
if (!agent) throw new Error("Agent not found");
const messagesIdsInRun = resolvedRunId ? agent.messages.filter((msg) => copilotkit.getRunIdForMessage(agentId, threadId, msg.id) === resolvedRunId).map((msg) => msg.id) : [message.id];
const rawMessageIndex = agent.messages.findIndex((msg) => msg.id === message.id);
const messageIndex = rawMessageIndex >= 0 ? rawMessageIndex : 0;
const messageIndexInRun = resolvedRunId ? Math.max(messagesIdsInRun.indexOf(message.id), 0) : 0;
const numberOfMessagesInRun = resolvedRunId ? messagesIdsInRun.length : 1;
const stateSnapshot = resolvedRunId ? copilotkit.getStateByRun(agentId, threadId, resolvedRunId) : void 0;
let result = null;
for (const renderer of customMessageRenderers) {
if (!renderer.render) continue;
const Component = renderer.render;
result = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, {
message,
position,
runId,
messageIndex,
messageIndexInRun,
numberOfMessagesInRun,
agentId,
stateSnapshot
}, `${runId}-${message.id}-${position}`);
if (result) break;
}
return result;
};
}
//#endregion
//#region src/hooks/use-render-activity-message.tsx
function useRenderActivityMessage() {
var _config$agentId;
const { copilotkit } = useCopilotKit();
const config = useCopilotChatConfiguration();
const agentId = (_config$agentId = config === null || config === void 0 ? void 0 : config.agentId) !== null && _config$agentId !== void 0 ? _config$agentId : _copilotkitnext_shared.DEFAULT_AGENT_ID;
const renderers = copilotkit.renderActivityMessages;
const findRenderer = (0, react.useCallback)((activityType) => {
var _ref, _ref2, _matches$find;
if (!renderers.length) return null;
const matches = renderers.filter((renderer) => renderer.activityType === activityType);
return (_ref = (_ref2 = (_matches$find = matches.find((candidate) => candidate.agentId === agentId)) !== null && _matches$find !== void 0 ? _matches$find : matches.find((candidate) => candidate.agentId === void 0)) !== null && _ref2 !== void 0 ? _ref2 : renderers.find((candidate) => candidate.activityType === "*")) !== null && _ref !== void 0 ? _ref : null;
}, [agentId, renderers]);
const renderActivityMessage = (0, react.useCallback)((message) => {
const renderer = findRenderer(message.activityType);
if (!renderer) return null;
const parseResult = renderer.content.safeParse(message.content);
if (!parseResult.success) {
console.warn(`Failed to parse content for activity message '${message.activityType}':`, parseResult.error);
return null;
}
const Component = renderer.render;
const agent = copilotkit.getAgent(agentId);
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, {
activityType: message.activityType,
content: parseResult.data,
message,
agent
}, message.id);
}, [
agentId,
copilotkit,
findRenderer
]);
return (0, react.useMemo)(() => ({
renderActivityMessage,
findRenderer
}), [renderActivityMessage, findRenderer]);
}
//#endregion
//#region src/hooks/use-frontend-tool.tsx
const EMPTY_DEPS$1 = [];
function useFrontendTool(tool, deps) {
const { copilotkit } = useCopilotKit();
const extraDeps = deps !== null && deps !== void 0 ? deps : EMPTY_DEPS$1;
(0, react.useEffect)(() => {
const name = tool.name;
if (copilotkit.getTool({
toolName: name,
agentId: tool.agentId
})) {
console.warn(`Tool '${name}' already exists for agent '${tool.agentId || "global"}'. Overriding with latest registration.`);
copilotkit.removeTool(name, tool.agentId);
}
copilotkit.addTool(tool);
if (tool.render && tool.parameters) copilotkit.addHookRenderToolCall({
name,
args: tool.parameters,
agentId: tool.agentId,
render: tool.render
});
return () => {
copilotkit.removeTool(name, tool.agentId);
};
}, [
tool.name,
tool.available,
copilotkit,
extraDeps.length,
...extraDeps
]);
}
//#endregion
//#region src/hooks/use-component.tsx
/**
* Registers a React component as a frontend tool renderer in chat.
*
* This hook is a convenience wrapper around `useFrontendTool` that:
* - builds a model-facing tool description,
* - forwards optional schema parameters (any Standard Schema V1 compatible library),
* - renders your component with tool call parameters.
*
* Use this when you want to display a typed visual component for a tool call
* without manually wiring a full frontend tool object.
*
* When `parameters` is provided, render props are inferred from the schema.
* When omitted, the render component may accept any props.
*
* @typeParam TSchema - Schema describing tool parameters, or `undefined` when no schema is given.
* @param config - Tool registration config.
* @param deps - Optional dependencies to refresh registration (same semantics as `useEffect`).
*
* @example
* ```tsx
* // Without parameters — render accepts any props
* useComponent({
* name: "showGreeting",
* render: ({ message }: { message: string }) => <div>{message}</div>,
* });
* ```
*
* @example
* ```tsx
* // With parameters — render props inferred from schema
* useComponent({
* name: "showWeatherCard",
* parameters: z.object({ city: z.string() }),
* render: ({ city }) => <div>{city}</div>,
* });
* ```
*
* @example
* ```tsx
* useComponent(
* {
* name: "renderProfile",
* parameters: z.object({ userId: z.string() }),
* render: ProfileCard,
* agentId: "support-agent",
* },
* [selectedAgentId],
* );
* ```
*/
function useComponent(config, deps) {
const prefix = `Use this tool to display the "${config.name}" component in the chat. This tool renders a visual UI component for the user.`;
const fullDescription = config.description ? `${prefix}\n\n${config.description}` : prefix;
useFrontendTool({
name: config.name,
description: fullDescription,
parameters: config.parameters,
render: ({ args }) => {
const Component = config.render;
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, { ...args });
},
agentId: config.agentId
}, deps);
}
//#endregion
//#region src/types/defineToolCallRenderer.ts
function defineToolCallRenderer(def) {
const argsSchema = def.name === "*" && !def.args ? zod.z.any() : def.args;
return {
name: def.name,
args: argsSchema,
render: def.render,
...def.agentId ? { agentId: def.agentId } : {}
};
}
//#endregion
//#region src/hooks/use-render-tool.tsx
const EMPTY_DEPS = [];
/**
* Registers a renderer entry in CopilotKit's `renderToolCalls` registry.
*
* Key behavior:
* - deduplicates by `agentId:name` (latest registration wins),
* - keeps renderer entries on cleanup so historical chat tool calls can still render,
* - refreshes registration when `deps` change.
*
* @typeParam S - Schema type describing tool call parameters.
* @param config - Renderer config for wildcard or named tools.
* @param deps - Optional dependencies to refresh registration.
*
* @example
* ```tsx
* useRenderTool(
* {
* name: "searchDocs",
* parameters: z.object({ query: z.string() }),
* render: ({ status, parameters, result }) => {
* if (status === "executing") return <div>Searching {parameters.query}</div>;
* if (status === "complete") return <div>{result}</div>;
* return <div>Preparing...</div>;
* },
* },
* [],
* );
* ```
*
* @example
* ```tsx
* useRenderTool(
* {
* name: "summarize",
* parameters: z.object({ text: z.string() }),
* agentId: "research-agent",
* render: ({ name, status }) => <div>{name}: {status}</div>,
* },
* [selectedAgentId],
* );
* ```
*/
function useRenderTool(config, deps) {
const { copilotkit } = useCopilotKit();
const extraDeps = deps !== null && deps !== void 0 ? deps : EMPTY_DEPS;
(0, react.useEffect)(() => {
const renderer = config.name === "*" && !config.parameters ? defineToolCallRenderer({
name: "*",
render: (props) => config.render({
...props,
parameters: props.args
}),
...config.agentId ? { agentId: config.agentId } : {}
}) : defineToolCallRenderer({
name: config.name,
args: config.parameters,
render: (props) => config.render({
...props,
parameters: props.args
}),
...config.agentId ? { agentId: config.agentId } : {}
});
copilotkit.addHookRenderToolCall(renderer);
}, [
config.name,
copilotkit,
extraDeps.length,
...extraDeps
]);
}
//#endregion
//#region src/hooks/use-default-render-tool.tsx
/**
* Registers a wildcard (`"*"`) tool-call renderer via `useRenderTool`.
*
* - Call with no config to use CopilotKit's built-in default tool-call card.
* - Pass `config.render` to replace the default UI with your own fallback renderer.
*
* This is useful when you want a generic renderer for tools that do not have a
* dedicated `useRenderTool({ name: "..." })` registration.
*
* @param config - Optional custom wildcard render function.
* @param deps - Optional dependencies to refresh registration.
*
* @example
* ```tsx
* useDefaultRenderTool();
* ```
*
* @example
* ```tsx
* useDefaultRenderTool({
* render: ({ name, status }) => <div>{name}: {status}</div>,
* });
* ```
*
* @example
* ```tsx
* useDefaultRenderTool(
* {
* render: ({ name, result }) => (
* <ToolEventRow title={name} payload={result} compact={compactMode} />
* ),
* },
* [compactMode],
* );
* ```
*/
function useDefaultRenderTool(config, deps) {
var _config$render;
useRenderTool({
name: "*",
render: (_config$render = config === null || config === void 0 ? void 0 : config.render) !== null && _config$render !== void 0 ? _config$render : DefaultToolCallRenderer
}, deps);
}
function DefaultToolCallRenderer({ name, parameters, status, result }) {
const [isExpanded, setIsExpanded] = (0, react.useState)(false);
const statusString = String(status);
const isActive = statusString === "inProgress" || statusString === "executing";
const isComplete = statusString === "complete";
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
style: {
marginTop: "8px",
paddingBottom: "8px"
},
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
style: {
borderRadius: "12px",
border: "1px solid #e4e4e7",
backgroundColor: "#fafafa",
padding: "14px 16px"
},
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
onClick: () => setIsExpanded(!isExpanded),
style: {
display: "flex",
alignItems: "center",
justifyContent: "space-between",
gap: "10px",
cursor: "pointer",
userSelect: "none"
},
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
style: {
display: "flex",
alignItems: "center",
gap: "8px",
minWidth: 0
},
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
style: {
height: "14px",
width: "14px",
color: "#71717a",
transition: "transform 0.15s",
transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)",
flexShrink: 0
},
fill: "none",
viewBox: "0 0 24 24",
strokeWidth: 2,
stroke: "currentColor",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
strokeLinecap: "round",
strokeLinejoin: "round",
d: "M8.25 4.5l7.5 7.5-7.5 7.5"
})
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: {
display: "inline-block",
height: "8px",
width: "8px",
borderRadius: "50%",
backgroundColor: isActive ? "#f59e0b" : isComplete ? "#10b981" : "#a1a1aa",
flexShrink: 0
} }),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
style: {
fontSize: "13px",
fontWeight: 600,
color: "#18181b",
overflow: "hidden",
textOverflow: "ellipsis",
whiteSpace: "nowrap"
},
children: name
})
]
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
style: {
display: "inline-flex",
alignItems: "center",
borderRadius: "9999px",
padding: "2px 8px",
fontSize: "11px",
fontWeight: 500,
backgroundColor: isActive ? "#fef3c7" : isComplete ? "#d1fae5" : "#f4f4f5",
color: isActive ? "#92400e" : isComplete ? "#065f46" : "#3f3f46",
flexShrink: 0
},
children: isActive ? "Running" : isComplete ? "Done" : status
})]
}), isExpanded && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
style: {
marginTop: "12px",
display: "grid",
gap: "12px"
},
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
style: {
fontSize: "10px",
textTransform: "uppercase",
letterSpacing: "0.05em",
color: "#71717a"
},
children: "Arguments"
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
style: {
marginTop: "6px",
maxHeight: "200px",
overflow: "auto",
borderRadius: "6px",
backgroundColor: "#f4f4f5",
padding: "10px",
fontSize: "11px",
lineHeight: 1.6,
color: "#27272a",
whiteSpace: "pre-wrap",
wordBreak: "break-word"
},
children: JSON.stringify(parameters !== null && parameters !== void 0 ? parameters : {}, null, 2)
})] }), result !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
style: {
fontSize: "10px",
textTransform: "uppercase",
letterSpacing: "0.05em",
color: "#71717a"
},
children: "Result"
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
style: {
marginTop: "6px",
maxHeight: "200px",
overflow: "auto",
borderRadius: "6px",
backgroundColor: "#f4f4f5",
padding: "10px",
fontSize: "11px",
lineHeight: 1.6,
color: "#27272a",
whiteSpace: "pre-wrap",
wordBreak: "break-word"
},
children: typeof result === "string" ? result : JSON.stringify(result, null, 2)
})] })]
})]
})
});
}
//#endregion
//#region src/hooks/use-human-in-the-loop.tsx
function useHumanInTheLoop(tool, deps) {
const { copilotkit } = useCopilotKit();
const resolvePromiseRef = (0, react.useRef)(null);
const respond = (0, react.useCallback)(async (result) => {
if (resolvePromiseRef.current) {
resolvePromiseRef.current(result);
resolvePromiseRef.current = null;
}
}, []);
const handler = (0, react.useCallback)(async () => {
return new Promise((resolve) => {
resolvePromiseRef.current = resolve;
});
}, []);
const RenderComponent = (0, react.useCallback)((props) => {
const ToolComponent = tool.render;
if (props.status === "inProgress") {
const enhancedProps = {
...props,
name: tool.name,
description: tool.description || "",
respond: void 0
};
return react.default.createElement(ToolComponent, enhancedProps);
} else if (props.status === "executing") {
const enhancedProps = {
...props,
name: tool.name,
description: tool.description || "",
respond
};
return react.default.createElement(ToolComponent, enhancedProps);
} else if (props.status === "complete") {
const enhancedProps = {
...props,
name: tool.name,
description: tool.description || "",
respond: void 0
};
return react.default.createElement(ToolComponent, enhancedProps);
}
return react.default.createElement(ToolComponent, props);
}, [
tool.render,
tool.name,
tool.description,
respond
]);
useFrontendTool({
...tool,
handler,
render: RenderComponent
}, deps);
(0, react.useEffect)(() => {
return () => {
copilotkit.removeHookRenderToolCall(tool.name, tool.agentId);
};
}, [
copilotkit,
tool.name,
tool.agentId
]);
}
//#endregion
//#region src/hooks/use-agent.tsx
let UseAgentUpdate = /* @__PURE__ */ function(UseAgentUpdate) {
UseAgentUpdate["OnMessagesChanged"] = "OnMessagesChanged";
UseAgentUpdate["OnStateChanged"] = "OnStateChanged";
UseAgentUpdate["OnRunStatusChanged"] = "OnRunStatusChanged";
return UseAgentUpdate;
}({});
const ALL_UPDATES = [
UseAgentUpdate.OnMessagesChanged,
UseAgentUpdate.OnStateChanged,
UseAgentUpdate.OnRunStatusChanged
];
function useAgent({ agentId, updates } = {}) {
var _agentId;
(_agentId = agentId) !== null && _agentId !== void 0 || (agentId = _copilotkitnext_shared.DEFAULT_AGENT_ID);
const { copilotkit } = useCopilotKit();
const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
const updateFlags = (0, react.useMemo)(() => updates !== null && updates !== void 0 ? updates : ALL_UPDATES, [JSON.stringify(updates)]);
const provisionalAgentCache = (0, react.useRef)(/* @__PURE__ */ new Map());
const agent = (0, react.useMemo)(() => {
var _copilotkit$agents;
const existing = copilotkit.getAgent(agentId);
if (existing) {
provisionalAgentCache.current.delete(agentId);
return existing;
}
const isRuntimeConfigured = copilotkit.runtimeUrl !== void 0;
const status = copilotkit.runtimeConnectionStatus;
if (isRuntimeConfigured && (status === _copilotkitnext_core.CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === _copilotkitnext_core.CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
const cached = provisionalAgentCache.current.get(agentId);
if (cached) {
cached.headers = { ...copilotkit.headers };
return cached;
}
const provisional = new _copilotkitnext_core.ProxiedCopilotRuntimeAgent({
runtimeUrl: copilotkit.runtimeUrl,
agentId,
transport: copilotkit.runtimeTransport
});
provisional.headers = { ...copilotkit.headers };
provisionalAgentCache.current.set(agentId, provisional);
return provisional;
}
if (isRuntimeConfigured && status === _copilotkitnext_core.CopilotKitCoreRuntimeConnectionStatus.Error) {
const provisional = new _copilotkitnext_core.ProxiedCopilotRuntimeAgent({
runtimeUrl: copilotkit.runtimeUrl,
agentId,
transport: copilotkit.runtimeTransport
});
provisional.headers = { ...copilotkit.headers };
return provisional;
}
const knownAgents = Object.keys((_copilotkit$agents = copilotkit.agents) !== null && _copilotkit$agents !== void 0 ? _copilotkit$agents : {});
const runtimePart = isRuntimeConfigured ? `runtimeUrl=${copilotkit.runtimeUrl}` : "no runtimeUrl";
throw new Error(`useAgent: Agent '${agentId}' not found after runtime sync (${runtimePart}). ` + (knownAgents.length ? `Known agents: [${knownAgents.join(", ")}]` : "No agents registered.") + " Verify your runtime /info and/or agents__unsafe_dev_only.");
}, [
agentId,
copilotkit.agents,
copilotkit.runtimeConnectionStatus,
copilotkit.runtimeUrl,
copilotkit.runtimeTransport,
JSON.stringify(copilotkit.headers)
]);
(0, react.useEffect)(() => {
if (updateFlags.length === 0) return;
const handlers = {};
if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) handlers.onMessagesChanged = () => {
forceUpdate();
};
if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = forceUpdate;
if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
handlers.onRunInitialized = forceUpdate;
handlers.onRunFinalized = forceUpdate;
handlers.onRunFailed = forceUpdate;
}
const subscription = agent.subscribe(handlers);
return () => subscription.unsubscribe();
}, [
agent,
forceUpdate,
JSON.stringify(updateFlags)
]);
return { agent };
}
//#endregion
//#region src/hooks/use-agent-context.tsx
function useAgentContext(context) {
const { description, value } = context;
const { copilotkit } = useCopilotKit();
const stringValue = (0, react.useMemo)(() => {
if (typeof value === "string") return value;
return JSON.stringify(value);
}, [value]);
(0, react.useLayoutEffect)(() => {
if (!copilotkit) return;
const id = copilotkit.addContext({
description,
value: stringValue
});
return () => {
copilotkit.removeContext(id);
};
}, [
description,
stringValue,
copilotkit
]);
}
//#endregion
//#region src/hooks/use-suggestions.tsx
function useSuggestions({ agentId } = {}) {
const { copilotkit } = useCopilotKit();
const config = useCopilotChatConfiguration();
const resolvedAgentId = (0, react.useMemo)(() => {
var _ref;
return (_ref = agentId !== null && agentId !== void 0 ? agentId : config === null || config === void 0 ? void 0 : config.agentId) !== null && _ref !== void 0 ? _ref : _copilotkitnext_shared.DEFAULT_AGENT_ID;
}, [agentId, config === null || config === void 0 ? void 0 : config.agentId]);
const [suggestions, setSuggestions] = (0, react.useState)(() => {
return copilotkit.getSuggestions(resolvedAgentId).suggestions;
});
const [isLoading, setIsLoading] = (0, react.useState)(() => {
return copilotkit.getSuggestions(resolvedAgentId).isLoading;
});
(0, react.useEffect)(() => {
const result = copilotkit.getSuggestions(resolvedAgentId);
setSuggestions(result.suggestions);
setIsLoading(result.isLoading);
}, [copilotkit, resolvedAgentId]);
(0, react.useEffect)(() => {
const subscription = copilotkit.subscribe({
onSuggestionsChanged: ({ agentId: changedAgentId, suggestions }) => {
if (changedAgentId !== resolvedAgentId) return;
setSuggestions(suggestions);
},
onSuggestionsStartedLoading: ({ agentId: changedAgentId }) => {
if (changedAgentId !== resolvedAgentId) return;
setIsLoading(true);
},
onSuggestionsFinishedLoading: ({ agentId: changedAgentId }) => {
if (changedAgentId !== resolvedAgentId) return;
setIsLoading(false);
},
onSuggestionsConfigChanged: () => {
const result = copilotkit.getSuggestions(resolvedAgentId);
setSuggestions(result.suggestions);
setIsLoading(result.isLoading);
}
});
return () => {
subscription.unsubscribe();
};
}, [copilotkit, resolvedAgentId]);
return {
suggestions,
reloadSuggestions: (0, react.useCallback)(() => {
copilotkit.reloadSuggestions(resolvedAgentId);
}, [copilotkit, resolvedAgentId]),
clearSuggestions: (0, react.useCallback)(() => {
copilotkit.clearSuggestions(resolvedAgentId);
}, [copilotkit, resolvedAgentId]),
isLoading
};
}
//#endregion
//#region src/hooks/use-configure-suggestions.tsx
function useConfigureSuggestions(config, deps) {
const { copilotkit } = useCopilotKit();
const chatConfig = useCopilotChatConfiguration();
const extraDeps = deps !== null && deps !== void 0 ? deps : [];
const resolvedConsumerAgentId = (0, react.useMemo)(() => {
var _chatConfig$agentId;
return (_chatConfig$agentId = chatConfig === null || chatConfig === void 0 ? void 0 : chatConfig.agentId) !== null && _chatConfig$agentId !== void 0 ? _chatConfig$agentId : _copilotkitnext_shared.DEFAULT_AGENT_ID;
}, [chatConfig === null || chatConfig === void 0 ? void 0 : chatConfig.agentId]);
const rawConsumerAgentId = (0, react.useMemo)(() => config ? config.consumerAgentId : void 0, [config]);
const normalizationCacheRef = (0, react.useRef)({
serialized: null,
config: null
});
const { normalizedConfig, serializedConfig } = (0, react.useMemo)(() => {
if (!config) {
normalizationCacheRef.current = {
serialized: null,
config: null
};
return {
normalizedConfig: null,
serializedConfig: null
};
}
if (config.available === "disabled") {
normalizationCacheRef.current = {
serialized: null,
config: null
};
return {
normalizedConfig: null,
serializedConfig: null
};
}
let built;
if (isDynamicConfig(config)) built = { ...config };
else {
const normalizedSuggestions = normalizeStaticSuggestions(config.suggestions);
built = {
...config,
suggestions: normalizedSuggestions
};
}
const serialized = JSON.stringify(built);
const cache = normalizationCacheRef.current;
if (cache.serialized === serialized && cache.config) return {
normalizedConfig: cache.config,
serializedConfig: serialized
};
normalizationCacheRef.current = {
serialized,
config: built
};
return {
normalizedConfig: built,
serializedConfig: serialized
};
}, [
config,
resolvedConsumerAgentId,
...extraDeps
]);
const latestConfigRef = (0, react.useRef)(null);
latestConfigRef.current = normalizedConfig;
const previousSerializedConfigRef = (0, react.useRef)(null);
const targetAgentId = (0, react.useMemo)(() => {
if (!normalizedConfig) return resolvedConsumerAgentId;
const consumer = normalizedConfig.consumerAgentId;
if (!consumer || consumer === "*") return resolvedConsumerAgentId;
return consumer;
}, [normalizedConfig, resolvedConsumerAgentId]);
const isGlobalConfig = rawConsumerAgentId === void 0 || rawConsumerAgentId === "*";
const requestReload = (0, react.useCallback)(() => {
if (!normalizedConfig) return;
if (isGlobalConfig) {
var _copilotkit$agents;
const agents = Object.values((_copilotkit$agents = copilotkit.agents) !== null && _copilotkit$agents !== void 0 ? _copilotkit$agents : {});
for (const entry of agents) {
const agentId = entry.agentId;
if (!agentId) continue;
if (!entry.isRunning) copilotkit.reloadSuggestions(agentId);
}
return;
}
if (!targetAgentId) return;
copilotkit.reloadSuggestions(targetAgentId);
}, [
copilotkit,
isGlobalConfig,
normalizedConfig,
targetAgentId
]);
(0, react.useEffect)(() => {
if (!serializedConfig || !latestConfigRef.current) return;
const id = copilotkit.addSuggestionsConfig(latestConfigRef.current);
requestReload();
return () => {
copilotkit.removeSuggestionsConfig(id);
};
}, [
copilotkit,
serializedConfig,
requestReload
]);
(0, react.useEffect)(() => {
if (!normalizedConfig) {
previousSerializedConfigRef.current = null;
return;
}
if (serializedConfig && previousSerializedConfigRef.current === serializedConfig) return;
if (serializedConfig) previousSerializedConfigRef.current = serializedConfig;
requestReload();
}, [
normalizedConfig,
requestReload,
serializedConfig
]);
(0, react.useEffect)(() => {
if (!normalizedConfig || extraDeps.length === 0) return;
requestReload();
}, [
extraDeps.length,
normalizedConfig,
requestReload,
...extraDeps
]);
}
function isDynamicConfig(config) {
return "instructions" in config;
}
function normalizeStaticSuggestions(suggestions) {
return suggestions.map((suggestion) => {
var _suggestion$isLoading;
return {
...suggestion,
isLoading: (_suggestion$isLoading = suggestion.isLoading) !== null && _suggestion$isLoading !== void 0 ? _suggestion$isLoading : false
};
});
}
//#endregion
//#region src/hooks/use-interrupt.tsx
const INTERRUPT_EVENT_NAME = "on_interrupt";
function isPromiseLike(value) {
return (typeof value === "object" || typeof value === "function") && value !== null && typeof Reflect.get(value, "then") === "function";
}
/**
* Handles agent interrupts (`on_interrupt`) with optional filtering, preprocessing, and resume behavior.
*
* The hook listens to custom events on the active agent, stores interrupt payloads per run,
* and surfaces a render callback once the run finalizes. Call `resolve` from your UI to resume
* execution with user-provided data.
*
* - `renderInChat: true` (default): the element is published into `<CopilotChat>` and this hook returns `void`.
* - `renderInChat: false`: the hook returns the interrupt element so you can place it anywhere in your component tree.
*
* `event.value` is typed as `any` since the interrupt payload shape depends on your agent.
* Type-narrow it in your callbacks (e.g. `handler`, `enabled`, `render`) as needed.
*
* @typeParam TResult - Inferred from `handler` return type. Exposed as `result` in `render`.
* @param config - Interrupt configuration (renderer, optional handler/filter, and render mode).
* @returns When `renderInChat` is `false`, returns the interrupt element (or `null` when idle).
* Otherwise returns `void` and publishes the element into chat. In `render`, `result` is always
* either the handler's resolved return value or `null` (including when no handler is provided,
* when filtering skips the interrupt, or when handler execution fails).
*
* @example
* ```tsx
* import { useInterrupt } from "@copilotkitnext/react";
*
* function InterruptUI() {
* useInterrupt({
* render: ({ event, resolve }) => (
* <div>
* <p>{event.value.question}</p>
* <button onClick={() => resolve({ approved: true })}>Approve</button>
* <button onClick={() => resolve({ approved: false })}>Reject</button>
* </div>
* ),
* });
*
* return null;
* }
* ```
*
* @example
* ```tsx
* import { useInterrupt } from "@copilotkitnext/react";
*
* function CustomPanel() {
* const interruptElement = useInterrupt({
* renderInChat: false,
* enabled: (event) => event.value.startsWith("approval:"),
* handler: async ({ event }) => ({ label: event.value.toUpperCase() }),
* render: ({ event, result, resolve }) => (
* <aside>
* <strong>{result?.label ?? ""}</strong>
* <button onClick={() => resolve({ value: event.value })}>Continue</button>
* </aside>
* ),
* });
*
* return <>{interruptElement}</>;
* }
* ```
*/
function useInterrupt(config) {
const { copilotkit } = useCopilotKit();
const { agent } = useAgent({ agentId: config.agentId });
const [pendingEvent, setPendingEvent] = (0, react.useState)(null);
const [handlerResult, setHandlerResult] = (0, react.useState)(null);
(0, react.useEffect)(() => {
let localInterrupt = null;
const subscription = agent.subscribe({
onCustomEvent: ({ event }) => {
if (event.name === INTERRUPT_EVENT_NAME) localInterrupt = {
name: event.name,
value: event.value
};
},
onRunStartedEvent: () => {
localInterrupt = null;
setPendingEvent(null);
},
onRunFinalized: () => {
if (localInterrupt) {
setPendingEvent(localInterrupt);
localInterrupt = null;
}
},
onRunFailed: () => {
localInterrupt = null;
}
});
return () => subscription.unsubscribe();
}, [agent]);
const resolve = (0, react.useCallback)((response) => {
setPendingEvent(null);
copilotkit.runAgent({
agent,
forwardedProps: { command: { resume: response } }
});
}, [agent, copilotkit]);
(0, react.useEffect)(() => {
if (!pendingEvent) {
setHandlerResult(null);
return;
}
if (config.enabled && !config.enabled(pendingEvent)) {
setHandlerResult(null);
return;
}
const handler = config.handler;
if (!handler) {
setHandlerResult(null);
return;
}
let cancelled = false;
const maybePromise = handler({
event: pendingEvent,
resolve
});
if (isPromiseLike(maybePromise)) Promise.resolve(maybePromise).then((resolved) => {
if (!cancelled) setHandlerResult(resolved);
}).catch(() => {
if (!cancelled) setHandlerResult(null);
});
else setHandlerResult(maybePromise);
return () => {
cancelled = true;
};
}, [
pendingEvent,
config.enabled,
config.handler,
resolve
]);
const element = (0, react.useMemo)(() => {
if (!pendingEvent) return null;
if (config.enabled && !config.enabled(pendingEvent)) return null;
return config.render({
event: pendingEvent,
result: handlerResult,
resolve
});
}, [
pendingEvent,
handlerResult,
config.enabled,
config.render,
resolve
]);
(0, react.useEffect)(() => {
if (config.renderInChat === false) return;
copilotkit.setInterruptElement(element);
return () => copilotkit.setInterruptElement(null);
}, [
element,
config.renderInChat,
copilotkit
]);
if (config.renderInChat === false) return element;
}
//#endregion
//#region src/components/chat/CopilotChatToolCallsView.tsx
function CopilotChatToolCallsView({ message, messages = [] }) {
const renderToolCall = useRenderToolCall();
if (!message.toolCalls || message.toolCalls.length === 0) return null;
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: message.toolCalls.map((toolCall) => {
const toolMessage = messages.find((m) => m.role === "tool" && m.toolCallId === toolCall.id);
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.default.Fragment, { children: renderToolCall({
toolCall,
toolMessage
}) }, toolCall.id);
}) });
}
//#endregion
//#region src/components/chat/CopilotChatAssistantMessage.tsx
function CopilotChatAssistantMessage({ message, messages, isRunning, onThumbsUp, onThumbsDown, onReadAloud, onRegenerate, additionalToolbarItems, toolbarVisible = true, markdownRenderer, toolbar, copyButton, thumbsUpButton, thumbsDownButton, readAloudButton, regenerateButton, toolCallsView, children, className, ...props }) {
var _messages;
useKatexStyles();
const boundMarkdownRenderer = renderSlot(markdownRenderer, CopilotChatAssistantMessage.MarkdownRenderer, { content: message.content || "" });
const boundCopyButton = renderSlot(copyButton, CopilotChatAssistantMessage.CopyButton, { onClick: async () => {
if (message.content) try {
await navigator.clipboard.writeText(message.content);
} catch (err) {
console.error("Failed to copy message:", err);
}
} });
const boundThumbsUpButton = renderSlot(thumbsUpButton, CopilotChatAssistantMessage.ThumbsUpButton, { onClick: onThumbsUp });
const boundThumbsDownButton = renderSlot(thumbsDownButton, CopilotChatAssistantMessage.ThumbsDownButton, { onClick: onThumbsDown });
const boundReadAloudButton = renderSlot(readAloudButton, CopilotChatAssistantMessage.ReadAloudButton, { onClick: onReadAloud });
const boundRegenerateButton = renderSlot(regenerateButton, CopilotChatAssistantMessage.RegenerateButton, { onClick: onRegenerate });
const boundToolbar = renderSlot(toolbar, CopilotChatAssistantMessage.Toolbar, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
className: "cpk:flex cpk:items-center cpk:gap-1",
children: [
boundCopyButton,
(onThumbsUp || thumbsUpButton) && boundThumbsUpButton,
(onThumbsDown || thumbsDownButton) && boundThumbsDownButton,
(onReadAloud || readAloudButton) && boundReadAloudButton,
(onRegenerate || regenerateButton) && boundRegenerateButton,
additionalToolbarItems
]
}) });
const boundToolCallsView = renderSlot(toolCallsView, CopilotChatToolCallsView, {
message,
messages
});
const hasContent = !!(message.content && message.content.trim().length > 0);
const isLatestAssistantMessage = message.role === "assistant" && (messages === null || messages === void 0 || (_messages = messages[messages.length - 1]) === null || _messages === void 0 ? void 0 : _messages.id) === message.id;
const shouldShowToolbar = toolbarVisible && hasContent && !(isRunning && isLatestAssistantMessage);
if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-copilotkit": true,
style: { display: "contents" },
children: children({
markdownRenderer: boundMarkdownRenderer,
toolbar: boundToolbar,
toolCallsView: boundToolCallsView,
copyButton: boundCopyButton,
thumbsUpButton: boundThumbsUpButton,
thumbsDownButton: boundThumbsDownButton,
readAloudButton: boundReadAloudButton,
regenerateButton: boundRegenerateButton,
message,
messages,
isRunning,
onThumbsUp,
onThumbsDown,
onReadAloud,
onRegenerate,
additionalToolbarItems,
toolbarVisible: shouldShowToolbar
})
});
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
"data-copilotkit": true,
"data-testid": "copilot-assistant-message",
className: (0, tailwind_merge.twMerge)("copilotKitMessage copilotKitAssistantMessage", className),
...props,
"data-message-id": message.id,
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:prose cpk:max-w-full cpk:break-words cpk:dark:prose-invert",
children: boundMarkdownRenderer
}),
boundToolCallsView,
shouldShowToolbar && boundToolbar
]
});
}
(function(_CopilotChatAssistantMessage) {
_CopilotChatAssistantMessage.MarkdownRenderer = ({ content, className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(streamdown.Streamdown, {
className,
...props,
children: content !== null && content !== void 0 ? content : ""
});
_CopilotChatAssistantMessage.Toolbar = ({ className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-testid": "copilot-assistant-toolbar",
className: (0, tailwind_merge.twMerge)("cpk:w-full cpk:bg-transparent cpk:flex cpk:items-center cpk:-ml-[5px] cpk:-mt-[0px]", className),
...props
});
const ToolbarButton = _CopilotChatAssistantMessage.ToolbarButton = ({ title, children, ...props }) => {
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Tooltip, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipTrigger, {
asChild: true,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
type: "button",
variant: "assistantMessageToolbarButton",
"aria-label": title,
...props,
children
})
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipContent, {
side: "bottom",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: title })
})] });
};
_CopilotChatAssistantMessage.CopyButton = ({ className, title, onClick, ...props }) => {
var _config$labels;
const config = useCopilotChatConfiguration();
const labels = (_config$labels = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels !== void 0 ? _config$labels : CopilotChatDefaultLabels;
const [copied, setCopied] = (0, react.useState)(false);
const handleClick = (event) => {
setCopied(true);
setTimeout(() => setCopied(false), 2e3);
if (onClick) onClick(event);
};
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
"data-testid": "copilot-copy-button",
title: title || labels.assistantMessageToolbarCopyMessageLabel,
onClick: handleClick,
className,
...props,
children: copied ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: "cpk:size-[18px]" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Copy, { className: "cpk:size-[18px]" })
});
};
_CopilotChatAssistantMessage.ThumbsUpButton = ({ title, ...props }) => {
var _config$labels2;
const config = useCopilotChatConfiguration();
const labels = (_config$labels2 = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels2 !== void 0 ? _config$labels2 : CopilotChatDefaultLabels;
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
"data-testid": "copilot-thumbs-up-button",
title: title || labels.assistantMessageToolbarThumbsUpLabel,
...props,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ThumbsUp, { className: "cpk:size-[18px]" })
});
};
_CopilotChatAssistantMessage.ThumbsDownButton = ({ title, ...props }) => {
var _config$labels3;
const config = useCopilotChatConfiguration();
const labels = (_config$labels3 = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels3 !== void 0 ? _config$labels3 : CopilotChatDefaultLabels;
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
"data-testid": "copilot-thumbs-down-button",
title: title || labels.assistantMessageToolbarThumbsDownLabel,
...props,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ThumbsDown, { className: "cpk:size-[18px]" })
});
};
_CopilotChatAssistantMessage.ReadAloudButton = ({ title, ...props }) => {
var _config$labels4;
const config = useCopilotChatConfiguration();
const labels = (_config$labels4 = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels4 !== void 0 ? _config$labels4 : CopilotChatDefaultLabels;
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
"data-testid": "copilot-read-aloud-button",
title: title || labels.assistantMessageToolbarReadAloudLabel,
...props,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Volume2, { className: "cpk:size-[20px]" })
});
};
_CopilotChatAssistantMessage.RegenerateButton = ({ title, ...props }) => {
var _config$labels5;
const config = useCopilotChatConfiguration();
const labels = (_config$labels5 = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels5 !== void 0 ? _config$labels5 : CopilotChatDefaultLabels;
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
"data-testid": "copilot-regenerate-button",
title: title || labels.assistantMessageToolbarRegenerateLabel,
...props,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.RefreshCw, { className: "cpk:size-[18px]" })
});
};
})(CopilotChatAssistantMessage || (CopilotChatAssistantMessage = {}));
CopilotChatAssistantMessage.MarkdownRenderer.displayName = "CopilotChatAssistantMessage.MarkdownRenderer";
CopilotChatAssistantMessage.Toolbar.displayName = "CopilotChatAssistantMessage.Toolbar";
CopilotChatAssistantMessage.CopyButton.displayName = "CopilotChatAssistantMessage.CopyButton";
CopilotChatAssistantMessage.ThumbsUpButton.displayName = "CopilotChatAssistantMessage.ThumbsUpButton";
CopilotChatAssistantMessage.ThumbsDownButton.displayName = "CopilotChatAssistantMessage.ThumbsDownButton";
CopilotChatAssistantMessage.ReadAloudButton.displayName = "CopilotChatAssistantMessage.ReadAloudButton";
CopilotChatAssistantMessage.RegenerateButton.displayName = "CopilotChatAssistantMessage.RegenerateButton";
var CopilotChatAssistantMessage_default = CopilotChatAssistantMessage;
//#endregion
//#region src/components/chat/CopilotChatUserMessage.tsx
function flattenUserMessageContent(content) {
if (!content) return "";
if (typeof content === "string") return content;
return content.map((part) => {
if (part && typeof part === "object" && "type" in part && part.type === "text" && typeof part.text === "string") return part.text;
return "";
}).filter((text) => text.length > 0).join("\n");
}
function CopilotChatUserMessage({ message, onEditMessage, branchIndex, numberOfBranches, onSwitchToBranch, additionalToolbarItems, messageRenderer, toolbar, copyButton, editButton, branchNavigation, children, className, ...props }) {
const flattenedContent = (0, react.useMemo)(() => flattenUserMessageContent(message.content), [message.content]);
const BoundMessageRenderer = renderSlot(messageRenderer, CopilotChatUserMessage.MessageRenderer, { content: flattenedContent });
const BoundCopyButton = renderSlot(copyButton, CopilotChatUserMessage.CopyButton, { onClick: async () => {
if (flattenedContent) try {
await navigator.clipboard.writeText(flattenedContent);
} catch (err) {
console.error("Failed to copy message:", err);
}
} });
const BoundEditButton = renderSlot(editButton, CopilotChatUserMessage.EditButton, { onClick: () => onEditMessage === null || onEditMessage === void 0 ? void 0 : onEditMessage({ message }) });
const BoundBranchNavigation = renderSlot(branchNavigation, CopilotChatUserMessage.BranchNavigation, {
currentBranch: branchIndex,
numberOfBranches,
onSwitchToBranch,
message
});
const showBranchNavigation = numberOfBranches && numberOfBranches > 1 && onSwitchToBranch;
const BoundToolbar = renderSlot(toolbar, CopilotChatUserMessage.Toolbar, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
className: "cpk:flex cpk:items-center cpk:gap-1 cpk:justify-end",
children: [
additionalToolbarItems,
BoundCopyButton,
onEditMessage && BoundEditButton,
showBranchNavigation && BoundBranchNavigation
]
}) });
if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-copilotkit": true,
style: { display: "contents" },
children: children({
messageRenderer: BoundMessageRenderer,
toolbar: BoundToolbar,
copyButton: BoundCopyButton,
editButton: BoundEditButton,
branchNavigation: BoundBranchNavigation,
message,
branchIndex,
numberOfBranches,
additionalToolbarItems
})
});
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
"data-copilotkit": true,
"data-testid": "copilot-user-message",
className: (0, tailwind_merge.twMerge)("copilotKitMessage copilotKitUserMessage cpk:flex cpk:flex-col cpk:items-end cpk:group cpk:pt-10", className),
"data-message-id": message.id,
...props,
children: [BoundMessageRenderer, BoundToolbar]
});
}
(function(_CopilotChatUserMessage) {
_CopilotChatUserMessage.Container = ({ children, className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: (0, tailwind_merge.twMerge)("cpk:flex cpk:flex-col cpk:items-end cpk:group", className),
...props,
children
});
_CopilotChatUserMessage.MessageRenderer = ({ content, className }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: (0, tailwind_merge.twMerge)("cpk:prose cpk:dark:prose-invert cpk:bg-muted cpk:relative cpk:max-w-[80%] cpk:rounded-[18px] cpk:px-4 cpk:py-1.5 cpk:data-[multiline]:py-3 cpk:inline-block cpk:whitespace-pre-wrap", className),
children: content
});
_CopilotChatUserMessage.Toolbar = ({ className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-testid": "copilot-user-toolbar",
className: (0, tailwind_merge.twMerge)("cpk:w-full cpk:bg-transparent cpk:flex cpk:items-center cpk:justify-end cpk:-mr-[5px] cpk:mt-[4px] cpk:invisible cpk:group-hover:visible", className),
...props
});
const ToolbarButton = _CopilotChatUserMessage.ToolbarButton = ({ title, children, className, ...props }) => {
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Tooltip, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipTrigger, {
asChild: true,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
type: "button",
variant: "assistantMessageToolbarButton",
"aria-label": title,
className: (0, tailwind_merge.twMerge)(className),
...props,
children
})
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipContent, {
side: "bottom",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: title })
})] });
};
_CopilotChatUserMessage.CopyButton = ({ className, title, onClick, ...props }) => {
var _config$labels;
const config = useCopilotChatConfiguration();
const labels = (_config$labels = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels !== void 0 ? _config$labels : CopilotChatDefaultLabels;
const [copied, setCopied] = (0, react.useState)(false);
const handleClick = (event) => {
setCopied(true);
setTimeout(() => setCopied(false), 2e3);
if (onClick) onClick(event);
};
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
"data-testid": "copilot-user-copy-button",
title: title || labels.userMessageToolbarCopyMessageLabel,
onClick: handleClick,
className,
...props,
children: copied ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: "cpk:size-[18px]" }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Copy, { className: "cpk:size-[18px]" })
});
};
_CopilotChatUserMessage.EditButton = ({ className, title, ...props }) => {
var _config$labels2;
const config = useCopilotChatConfiguration();
const labels = (_config$labels2 = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels2 !== void 0 ? _config$labels2 : CopilotChatDefaultLabels;
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
"data-testid": "copilot-edit-button",
title: title || labels.userMessageToolbarEditMessageLabel,
className,
...props,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Edit, { className: "cpk:size-[18px]" })
});
};
_CopilotChatUserMessage.BranchNavigation = ({ className, currentBranch = 0, numberOfBranches = 1, onSwitchToBranch, message, ...props }) => {
if (!numberOfBranches || numberOfBranches <= 1 || !onSwitchToBranch) return null;
const canGoPrev = currentBranch > 0;
const canGoNext = currentBranch < numberOfBranches - 1;
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
"data-testid": "copilot-branch-navigation",
className: (0, tailwind_merge.twMerge)("cpk:flex cpk:items-center cpk:gap-1", className),
...props,
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
type: "button",
variant: "assistantMessageToolbarButton",
onClick: () => onSwitchToBranch === null || onSwitchToBranch === void 0 ? void 0 : onSwitchToBranch({
branchIndex: currentBranch - 1,
numberOfBranches,
message
}),
disabled: !canGoPrev,
className: "cpk:h-6 cpk:w-6 cpk:p-0",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronLeft, { className: "cpk:size-[20px]" })
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
className: "cpk:text-sm cpk:text-muted-foreground cpk:px-0 cpk:font-medium",
children: [
currentBranch + 1,
"/",
numberOfBranches
]
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
type: "button",
variant: "assistantMessageToolbarButton",
onClick: () => onSwitchToBranch === null || onSwitchToBranch === void 0 ? void 0 : onSwitchToBranch({
branchIndex: currentBranch + 1,
numberOfBranches,
message
}),
disabled: !canGoNext,
className: "cpk:h-6 cpk:w-6 cpk:p-0",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronRight, { className: "cpk:size-[20px]" })
})
]
});
};
})(CopilotChatUserMessage || (CopilotChatUserMessage = {}));
CopilotChatUserMessage.Container.displayName = "CopilotChatUserMessage.Container";
CopilotChatUserMessage.MessageRenderer.displayName = "CopilotChatUserMessage.MessageRenderer";
CopilotChatUserMessage.Toolbar.displayName = "CopilotChatUserMessage.Toolbar";
CopilotChatUserMessage.ToolbarButton.displayName = "CopilotChatUserMessage.ToolbarButton";
CopilotChatUserMessage.CopyButton.displayName = "CopilotChatUserMessage.CopyButton";
CopilotChatUserMessage.EditButton.displayName = "CopilotChatUserMessage.EditButton";
CopilotChatUserMessage.BranchNavigation.displayName = "CopilotChatUserMessage.BranchNavigation";
var CopilotChatUserMessage_default = CopilotChatUserMessage;
//#endregion
//#region src/components/chat/CopilotChatReasoningMessage.tsx
/**
* Formats an elapsed duration (in seconds) to a human-readable string.
*/
function formatDuration(seconds) {
if (seconds < 1) return "a few seconds";
if (seconds < 60) return `${Math.round(seconds)} seconds`;
const mins = Math.floor(seconds / 60);
const secs = Math.round(seconds % 60);
if (secs === 0) return `${mins} minute${mins > 1 ? "s" : ""}`;
return `${mins}m ${secs}s`;
}
function CopilotChatReasoningMessage({ message, messages, isRunning, header, contentView, toggle, children, className, ...props }) {
var _messages;
const isLatest = (messages === null || messages === void 0 || (_messages = messages[messages.length - 1]) === null || _messages === void 0 ? void 0 : _messages.id) === message.id;
const isStreaming = !!(isRunning && isLatest);
const hasContent = !!(message.content && message.content.length > 0);
const startTimeRef = (0, react.useRef)(null);
const [elapsed, setElapsed] = (0, react.useState)(0);
(0, react.useEffect)(() => {
if (isStreaming && startTimeRef.current === null) startTimeRef.current = Date.now();
if (!isStreaming && startTimeRef.current !== null) {
setElapsed((Date.now() - startTimeRef.current) / 1e3);
return;
}
if (!isStreaming) return;
const timer = setInterval(() => {
if (startTimeRef.current !== null) setElapsed((Date.now() - startTimeRef.current) / 1e3);
}, 1e3);
return () => clearInterval(timer);
}, [isStreaming]);
const [isOpen, setIsOpen] = (0, react.useState)(isStreaming);
(0, react.useEffect)(() => {
if (isStreaming) setIsOpen(true);
else setIsOpen(false);
}, [isStreaming]);
const label = isStreaming ? "Thinking…" : `Thought for ${formatDuration(elapsed)}`;
const boundHeader = renderSlot(header, CopilotChatReasoningMessage.Header, {
isOpen,
label,
hasContent,
isStreaming,
onClick: hasContent ? () => setIsOpen((prev) => !prev) : void 0
});
const boundContent = renderSlot(contentView, CopilotChatReasoningMessage.Content, {
isStreaming,
hasContent,
children: message.content
});
const boundToggle = renderSlot(toggle, CopilotChatReasoningMessage.Toggle, {
isOpen,
children: boundContent
});
if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-copilotkit": true,
style: { display: "contents" },
children: children({
header: boundHeader,
contentView: boundContent,
toggle: boundToggle,
message,
messages,
isRunning
})
});
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
className: (0, tailwind_merge.twMerge)("cpk:my-1", className),
"data-message-id": message.id,
...props,
children: [boundHeader, boundToggle]
});
}
(function(_CopilotChatReasoningMessage) {
_CopilotChatReasoningMessage.Header = ({ isOpen, label = "Thoughts", hasContent, isStreaming, className, children: headerChildren, ...headerProps }) => {
const isExpandable = !!hasContent;
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
type: "button",
className: (0, tailwind_merge.twMerge)("cpk:inline-flex cpk:items-center cpk:gap-1 cpk:py-1 cpk:text-sm cpk:text-muted-foreground cpk:transition-colors cpk:select-none", isExpandable ? "cpk:hover:text-foreground cpk:cursor-pointer" : "cpk:cursor-default", className),
"aria-expanded": isExpandable ? isOpen : void 0,
...headerProps,
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
className: "cpk:font-medium",
children: label
}),
isStreaming && !hasContent && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
className: "cpk:inline-flex cpk:items-center cpk:ml-1",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "cpk:w-1.5 cpk:h-1.5 cpk:rounded-full cpk:bg-muted-foreground cpk:animate-pulse" })
}),
headerChildren,
isExpandable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronRight, { className: (0, tailwind_merge.twMerge)("cpk:size-3.5 cpk:shrink-0 cpk:transition-transform cpk:duration-200", isOpen && "cpk:rotate-90") })
]
});
};
_CopilotChatReasoningMessage.Content = ({ isStreaming, hasContent, className, children: contentChildren, ...contentProps }) => {
if (!hasContent && !isStreaming) return null;
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: (0, tailwind_merge.twMerge)("cpk:pb-2 cpk:pt-1", className),
...contentProps,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
className: "cpk:text-sm cpk:text-muted-foreground",
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(streamdown.Streamdown, { children: typeof contentChildren === "string" ? contentChildren : "" }), isStreaming && hasContent && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
className: "cpk:inline-flex cpk:items-center cpk:ml-1 cpk:align-middle",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "cpk:w-2 cpk:h-2 cpk:rounded-full cpk:bg-muted-foreground cpk:animate-pulse-cursor" })
})]
})
});
};
_CopilotChatReasoningMessage.Toggle = ({ isOpen, className, children: toggleChildren, ...toggleProps }) => {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: (0, tailwind_merge.twMerge)("cpk:grid cpk:transition-[grid-template-rows] cpk:duration-200 cpk:ease-in-out", className),
style: { gridTemplateRows: isOpen ? "1fr" : "0fr" },
...toggleProps,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:overflow-hidden",
children: toggleChildren
})
});
};
})(CopilotChatReasoningMessage || (CopilotChatReasoningMessage = {}));
CopilotChatReasoningMessage.Header.displayName = "CopilotChatReasoningMessage.Header";
CopilotChatReasoningMessage.Content.displayName = "CopilotChatReasoningMessage.Content";
CopilotChatReasoningMessage.Toggle.displayName = "CopilotChatReasoningMessage.Toggle";
var CopilotChatReasoningMessage_default = CopilotChatReasoningMessage;
//#endregion
//#region src/components/chat/CopilotChatSuggestionPill.tsx
const baseClasses = "group cpk:inline-flex cpk:h-7 cpk:sm:h-8 cpk:items-center cpk:gap-1 cpk:sm:gap-1.5 cpk:rounded-full cpk:border cpk:border-border/60 cpk:bg-background cpk:px-2.5 cpk:sm:px-3 cpk:text-[11px] cpk:sm:text-xs cpk:leading-none cpk:text-foreground cpk:transition-colors cpk:cursor-pointer cpk:hover:bg-accent/60 cpk:hover:text-foreground cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-ring cpk:focus-visible:ring-offset-2 cpk:focus-visible:ring-offset-background cpk:disabled:cursor-not-allowed cpk:disabled:text-muted-foreground cpk:disabled:hover:bg-background cpk:disabled:hover:text-muted-foreground cpk:pointer-events-auto";
const labelClasses = "cpk:whitespace-nowrap cpk:font-medium cpk:leading-none";
const CopilotChatSuggestionPill = react.default.forwardRef(function CopilotChatSuggestionPill({ className, children, icon, isLoading, type, ...props }, ref) {
const showIcon = !isLoading && icon;
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
ref,
"data-copilotkit": true,
"data-testid": "copilot-suggestion",
"data-slot": "suggestion-pill",
className: cn(baseClasses, className),
type: type !== null && type !== void 0 ? type : "button",
"aria-busy": isLoading || void 0,
disabled: isLoading || props.disabled,
...props,
children: [isLoading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
className: "cpk:flex cpk:h-3.5 cpk:sm:h-4 cpk:w-3.5 cpk:sm:w-4 cpk:items-center cpk:justify-center cpk:text-muted-foreground",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Loader2, {
className: "cpk:h-3.5 cpk:sm:h-4 cpk:w-3.5 cpk:sm:w-4 cpk:animate-spin",
"aria-hidden": "true"
})
}) : showIcon && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
className: "cpk:flex cpk:h-3.5 cpk:sm:h-4 cpk:w-3.5 cpk:sm:w-4 cpk:items-center cpk:justify-center cpk:text-muted-foreground",
children: icon
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
className: labelClasses,
children
})]
});
});
CopilotChatSuggestionPill.displayName = "CopilotChatSuggestionPill";
//#endregion
//#region src/components/chat/CopilotChatSuggestionView.tsx
const DefaultContainer = react.default.forwardRef(function DefaultContainer({ className, ...props }, ref) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
ref,
"data-copilotkit": true,
"data-testid": "copilot-suggestions",
className: cn("cpk:flex cpk:flex-wrap cpk:items-center cpk:gap-1.5 cpk:sm:gap-2 cpk:pl-0 cpk:pr-4 cpk:sm:px-0 cpk:pointer-events-none", className),
...props
});
});
const CopilotChatSuggestionView = react.default.forwardRef(function CopilotChatSuggestionView({ suggestions, onSelectSuggestion, loadingIndexes, container, suggestion: suggestionSlot, className, children, ...restProps }, ref) {
const loadingSet = react.default.useMemo(() => {
if (!loadingIndexes || loadingIndexes.length === 0) return /* @__PURE__ */ new Set();
return new Set(loadingIndexes);
}, [loadingIndexes]);
const ContainerElement = renderSlot(container, DefaultContainer, {
ref,
className,
...restProps
});
const suggestionElements = suggestions.map((suggestion, index) => {
const isLoading = loadingSet.has(index) || suggestion.isLoading === true;
const pill = renderSlot(suggestionSlot, CopilotChatSuggestionPill, {
children: suggestion.title,
isLoading,
type: "button",
onClick: () => onSelectSuggestion === null || onSelectSuggestion === void 0 ? void 0 : onSelectSuggestion(suggestion, index)
});
return react.default.cloneElement(pill, { key: `${suggestion.title}-${index}` });
});
const boundContainer = react.default.cloneElement(ContainerElement, void 0, suggestionElements);
if (typeof children === "function") {
var _suggestions$0$title, _suggestions$, _suggestions$2;
const sampleSuggestion = renderSlot(suggestionSlot, CopilotChatSuggestionPill, {
children: (_suggestions$0$title = (_suggestions$ = suggestions[0]) === null || _suggestions$ === void 0 ? void 0 : _suggestions$.title) !== null && _suggestions$0$title !== void 0 ? _suggestions$0$title : "",
isLoading: suggestions.length > 0 ? loadingSet.has(0) || ((_suggestions$2 = suggestions[0]) === null || _suggestions$2 === void 0 ? void 0 : _suggestions$2.isLoading) === true : false,
type: "button"
});
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-copilotkit": true,
style: { display: "contents" },
children: children({
container: boundContainer,
suggestion: sampleSuggestion,
suggestions,
onSelectSuggestion,
loadingIndexes,
className,
...restProps
})
});
}
if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
"data-copilotkit": true,
style: { display: "contents" },
children: [boundContainer, children]
});
return boundContainer;
});
CopilotChatSuggestionView.displayName = "CopilotChatSuggestionView";
//#endregion
//#region src/components/chat/CopilotChatMessageView.tsx
/**
* Memoized wrapper for assistant messages to prevent re-renders when other messages change.
*/
const MemoizedAssistantMessage = react.default.memo(function MemoizedAssistantMessage({ message, messages, isRunning, AssistantMessageComponent, slotProps }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AssistantMessageComponent, {
message,
messages,
isRunning,
...slotProps
});
}, (prevProps, nextProps) => {
var _nextProps$messages;
if (prevProps.message.id !== nextProps.message.id) return false;
if (prevProps.message.content !== nextProps.message.content) return false;
const prevToolCalls = prevProps.message.toolCalls;
const nextToolCalls = nextProps.message.toolCalls;
if ((prevToolCalls === null || prevToolCalls === void 0 ? void 0 : prevToolCalls.length) !== (nextToolCalls === null || nextToolCalls === void 0 ? void 0 : nextToolCalls.length)) return false;
if (prevToolCalls && nextToolCalls) for (let i = 0; i < prevToolCalls.length; i++) {
const prevTc = prevToolCalls[i];
const nextTc = nextToolCalls[i];
if (!prevTc || !nextTc) return false;
if (prevTc.id !== nextTc.id) return false;
if (prevTc.function.arguments !== nextTc.function.arguments) return false;
}
if (prevToolCalls && prevToolCalls.length > 0) {
const toolCallIds = new Set(prevToolCalls.map((tc) => tc.id));
const prevToolResults = prevProps.messages.filter((m) => m.role === "tool" && toolCallIds.has(m.toolCallId));
const nextToolResults = nextProps.messages.filter((m) => m.role === "tool" && toolCallIds.has(m.toolCallId));
if (prevToolResults.length !== nextToolResults.length) return false;
for (let i = 0; i < prevToolResults.length; i++) if (prevToolResults[i].content !== nextToolResults[i].content) return false;
}
if (((_nextProps$messages = nextProps.messages[nextProps.messages.length - 1]) === null || _nextProps$messages === void 0 ? void 0 : _nextProps$messages.id) === nextProps.message.id && prevProps.isRunning !== nextProps.isRunning) return false;
if (prevProps.AssistantMessageComponent !== nextProps.AssistantMessageComponent) return false;
if (prevProps.slotProps !== nextProps.slotProps) return false;
return true;
});
/**
* Memoized wrapper for user messages to prevent re-renders when other messages change.
*/
const MemoizedUserMessage = react.default.memo(function MemoizedUserMessage({ message, UserMessageComponent, slotProps }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UserMessageComponent, {
message,
...slotProps
});
}, (prevProps, nextProps) => {
if (prevProps.message.id !== nextProps.message.id) return false;
if (prevProps.message.content !== nextProps.message.content) return false;
if (prevProps.UserMessageComponent !== nextProps.UserMessageComponent) return false;
if (prevProps.slotProps !== nextProps.slotProps) return false;
return true;
});
/**
* Memoized wrapper for activity messages to prevent re-renders when other messages change.
*/
const MemoizedActivityMessage = react.default.memo(function MemoizedActivityMessage({ message, renderActivityMessage }) {
return renderActivityMessage(message);
}, (prevProps, nextProps) => {
if (prevProps.message.id !== nextProps.message.id) return false;
if (prevProps.message.activityType !== nextProps.message.activityType) return false;
if (JSON.stringify(prevProps.message.content) !== JSON.stringify(nextProps.message.content)) return false;
return true;
});
/**
* Memoized wrapper for reasoning messages to prevent re-renders when other messages change.
*/
const MemoizedReasoningMessage = react.default.memo(function MemoizedReasoningMessage({ message, messages, isRunning, ReasoningMessageComponent, slotProps }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReasoningMessageComponent, {
message,
messages,
isRunning,
...slotProps
});
}, (prevProps, nextProps) => {
var _prevProps$messages, _nextProps$messages2;
if (prevProps.message.id !== nextProps.message.id) return false;
if (prevProps.message.content !== nextProps.message.content) return false;
const prevIsLatest = ((_prevProps$messages = prevProps.messages[prevProps.messages.length - 1]) === null || _prevProps$messages === void 0 ? void 0 : _prevProps$messages.id) === prevProps.message.id;
const nextIsLatest = ((_nextProps$messages2 = nextProps.messages[nextProps.messages.length - 1]) === null || _nextProps$messages2 === void 0 ? void 0 : _nextProps$messages2.id) === nextProps.message.id;
if (prevIsLatest !== nextIsLatest) return false;
if (nextIsLatest && prevProps.isRunning !== nextProps.isRunning) return false;
if (prevProps.ReasoningMessageComponent !== nextProps.ReasoningMessageComponent) return false;
if (prevProps.slotProps !== nextProps.slotProps) return false;
return true;
});
/**
* Memoized wrapper for custom messages to prevent re-renders when other messages change.
*/
const MemoizedCustomMessage = react.default.memo(function MemoizedCustomMessage({ message, position, renderCustomMessage }) {
return renderCustomMessage({
message,
position
});
}, (prevProps, nextProps) => {
if (prevProps.message.id !== nextProps.message.id) return false;
if (prevProps.position !== nextProps.position) return false;
if (prevProps.message.content !== nextProps.message.content) return false;
if (prevProps.message.role !== nextProps.message.role) return false;
if (JSON.stringify(prevProps.stateSnapshot) !== JSON.stringify(nextProps.stateSnapshot)) return false;
return true;
});
function CopilotChatMessageView({ messages = [], assistantMessage, userMessage, reasoningMessage, cursor, isRunning = false, children, className, ...props }) {
const renderCustomMessage = useRenderCustomMessages();
const { renderActivityMessage } = useRenderActivityMessage();
const { copilotkit } = useCopilotKit();
const config = useCopilotChatConfiguration();
const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
(0, react.useEffect)(() => {
if (!(config === null || config === void 0 ? void 0 : config.agentId)) return;
const agent = copilotkit.getAgent(config.agentId);
if (!agent) return;
const subscription = agent.subscribe({ onStateChanged: forceUpdate });
return () => subscription.unsubscribe();
}, [
config === null || config === void 0 ? void 0 : config.agentId,
copilotkit,
forceUpdate
]);
const [interruptElement, setInterruptElement] = (0, react.useState)(null);
(0, react.useEffect)(() => {
setInterruptElement(copilotkit.interruptElement);
const subscription = copilotkit.subscribe({ onInterruptElementChanged: ({ interruptElement }) => {
setInterruptElement(interruptElement);
} });
return () => subscription.unsubscribe();
}, [copilotkit]);
const getStateSnapshotForMessage = (messageId) => {
var _copilotkit$getRunIdF;
if (!config) return void 0;
const resolvedRunId = (_copilotkit$getRunIdF = copilotkit.getRunIdForMessage(config.agentId, config.threadId, messageId)) !== null && _copilotkit$getRunIdF !== void 0 ? _copilotkit$getRunIdF : copilotkit.getRunIdsForThread(config.agentId, config.threadId).slice(-1)[0];
if (!resolvedRunId) return void 0;
return copilotkit.getStateByRun(config.agentId, config.threadId, resolvedRunId);
};
const deduplicatedMessages = [...new Map(messages.map((m) => [m.id, m])).values()];
if (process.env.NODE_ENV === "development" && deduplicatedMessages.length < messages.length) console.warn(`CopilotChatMessageView: Deduplicated ${messages.length - deduplicatedMessages.length} message(s) with duplicate IDs.`);
const messageElements = deduplicatedMessages.flatMap((message) => {
const elements = [];
const stateSnapshot = getStateSnapshotForMessage(message.id);
if (renderCustomMessage) elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedCustomMessage, {
message,
position: "before",
renderCustomMessage,
stateSnapshot
}, `${message.id}-custom-before`));
if (message.role === "assistant") {
let AssistantComponent = CopilotChatAssistantMessage_default;
let assistantSlotProps;
if (isReactComponentType(assistantMessage)) AssistantComponent = assistantMessage;
else if (typeof assistantMessage === "string") assistantSlotProps = { className: assistantMessage };
else if (assistantMessage && typeof assistantMessage === "object") assistantSlotProps = assistantMessage;
elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedAssistantMessage, {
message,
messages,
isRunning,
AssistantMessageComponent: AssistantComponent,
slotProps: assistantSlotProps
}, message.id));
} else if (message.role === "user") {
let UserComponent = CopilotChatUserMessage_default;
let userSlotProps;
if (isReactComponentType(userMessage)) UserComponent = userMessage;
else if (typeof userMessage === "string") userSlotProps = { className: userMessage };
else if (userMessage && typeof userMessage === "object") userSlotProps = userMessage;
elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedUserMessage, {
message,
UserMessageComponent: UserComponent,
slotProps: userSlotProps
}, message.id));
} else if (message.role === "activity") {
const activityMsg = message;
elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedActivityMessage, {
message: activityMsg,
renderActivityMessage
}, message.id));
} else if (message.role === "reasoning") {
let ReasoningComponent = CopilotChatReasoningMessage_default;
let reasoningSlotProps;
if (isReactComponentType(reasoningMessage)) ReasoningComponent = reasoningMessage;
else if (typeof reasoningMessage === "string") reasoningSlotProps = { className: reasoningMessage };
else if (reasoningMessage && typeof reasoningMessage === "object") reasoningSlotProps = reasoningMessage;
elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedReasoningMessage, {
message,
messages,
isRunning,
ReasoningMessageComponent: ReasoningComponent,
slotProps: reasoningSlotProps
}, message.id));
}
if (renderCustomMessage) elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedCustomMessage, {
message,
position: "after",
renderCustomMessage,
stateSnapshot
}, `${message.id}-custom-after`));
return elements;
}).filter(Boolean);
if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-copilotkit": true,
style: { display: "contents" },
children: children({
messageElements,
messages,
isRunning,
interruptElement
})
});
const lastMessage = messages[messages.length - 1];
const showCursor = isRunning && (lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.role) !== "reasoning";
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
"data-copilotkit": true,
"data-testid": "copilot-message-list",
className: (0, tailwind_merge.twMerge)("copilotKitMessages cpk:flex cpk:flex-col", className),
...props,
children: [
messageElements,
interruptElement,
showCursor && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:mt-2",
children: renderSlot(cursor, CopilotChatMessageView.Cursor, {})
})
]
});
}
CopilotChatMessageView.Cursor = function Cursor({ className, ...props }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-testid": "copilot-loading-cursor",
className: (0, tailwind_merge.twMerge)("cpk:w-[11px] cpk:h-[11px] cpk:rounded-full cpk:bg-foreground cpk:animate-pulse-cursor cpk:ml-1", className),
...props
});
};
//#endregion
//#region src/hooks/use-keyboard-height.tsx
/**
* Hook to detect mobile keyboard appearance and calculate available viewport height.
* Uses the Visual Viewport API to track keyboard state on mobile devices.
*
* @returns KeyboardState object with keyboard information
*/
function useKeyboardHeight() {
const [keyboardState, setKeyboardState] = (0, react.useState)({
isKeyboardOpen: false,
keyboardHeight: 0,
availableHeight: typeof window !== "undefined" ? window.innerHeight : 0,
viewportHeight: typeof window !== "undefined" ? window.innerHeight : 0
});
(0, react.useEffect)(() => {
if (typeof window === "undefined") return;
const visualViewport = window.visualViewport;
if (!visualViewport) return;
const updateKeyboardState = () => {
const layoutHeight = window.innerHeight;
const visualHeight = visualViewport.height;
const keyboardHeight = Math.max(0, layoutHeight - visualHeight);
setKeyboardState({
isKeyboardOpen: keyboardHeight > 150,
keyboardHeight,
availableHeight: visualHeight,
viewportHeight: layoutHeight
});
};
updateKeyboardState();
visualViewport.addEventListener("resize", updateKeyboardState);
visualViewport.addEventListener("scroll", updateKeyboardState);
return () => {
visualViewport.removeEventListener("resize", updateKeyboardState);
visualViewport.removeEventListener("scroll", updateKeyboardState);
};
}, []);
return keyboardState;
}
//#endregion
//#region src/components/chat/CopilotChatView.tsx
const FEATHER_HEIGHT = 96;
function CopilotChatView({ messageView, input, scrollView, suggestionView, welcomeScreen, messages = [], autoScroll = true, isRunning = false, suggestions, suggestionLoadingIndexes, onSelectSuggestion, onSubmitMessage, onStop, inputMode, inputValue, onInputChange, onStartTranscribe, onCancelTranscribe, onFinishTranscribe, onFinishTranscribeWithAudio, disclaimer, children, className, ...props }) {
const inputContainerRef = (0, react.useRef)(null);
const [inputContainerHeight, setInputContainerHeight] = (0, react.useState)(0);
const [isResizing, setIsResizing] = (0, react.useState)(false);
const resizeTimeoutRef = (0, react.useRef)(null);
const { isKeyboardOpen, keyboardHeight, availableHeight } = useKeyboardHeight();
(0, react.useEffect)(() => {
const element = inputContainerRef.current;
if (!element) return;
const resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) {
const newHeight = entry.contentRect.height;
setInputContainerHeight((prevHeight) => {
if (newHeight !== prevHeight) {
setIsResizing(true);
if (resizeTimeoutRef.current) clearTimeout(resizeTimeoutRef.current);
resizeTimeoutRef.current = setTimeout(() => {
setIsResizing(false);
}, 250);
return newHeight;
}
return prevHeight;
});
}
});
resizeObserver.observe(element);
setInputContainerHeight(element.offsetHeight);
return () => {
resizeObserver.disconnect();
if (resizeTimeoutRef.current) clearTimeout(resizeTimeoutRef.current);
};
}, []);
const BoundMessageView = renderSlot(messageView, CopilotChatMessageView, {
messages,
isRunning
});
const BoundInput = renderSlot(input, CopilotChatInput_default, {
onSubmitMessage,
onStop,
mode: inputMode,
value: inputValue,
onChange: onInputChange,
isRunning,
onStartTranscribe,
onCancelTranscribe,
onFinishTranscribe,
onFinishTranscribeWithAudio,
positioning: "absolute",
keyboardHeight: isKeyboardOpen ? keyboardHeight : 0,
containerRef: inputContainerRef,
showDisclaimer: true,
...disclaimer !== void 0 ? { disclaimer } : {}
});
const hasSuggestions = Array.isArray(suggestions) && suggestions.length > 0;
const BoundSuggestionView = hasSuggestions ? renderSlot(suggestionView, CopilotChatSuggestionView, {
suggestions,
loadingIndexes: suggestionLoadingIndexes,
onSelectSuggestion,
className: "cpk:mb-3 cpk:lg:ml-4 cpk:lg:mr-4 cpk:ml-0 cpk:mr-0"
}) : null;
const BoundScrollView = renderSlot(scrollView, CopilotChatView.ScrollView, {
autoScroll,
inputContainerHeight,
isResizing,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
style: { paddingBottom: `${inputContainerHeight + FEATHER_HEIGHT + (hasSuggestions ? 4 : 32)}px` },
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
className: "cpk:max-w-3xl cpk:mx-auto",
children: [BoundMessageView, hasSuggestions ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:pl-0 cpk:pr-4 cpk:sm:px-0 cpk:mt-4",
children: BoundSuggestionView
}) : null]
})
})
});
if (messages.length === 0 && !(welcomeScreen === false)) {
const BoundInputForWelcome = renderSlot(input, CopilotChatInput_default, {
onSubmitMessage,
onStop,
mode: inputMode,
value: inputValue,
onChange: onInputChange,
isRunning,
onStartTranscribe,
onCancelTranscribe,
onFinishTranscribe,
onFinishTranscribeWithAudio,
positioning: "static",
showDisclaimer: true,
...disclaimer !== void 0 ? { disclaimer } : {}
});
const BoundWelcomeScreen = renderSlot(welcomeScreen === true ? void 0 : welcomeScreen, CopilotChatView.WelcomeScreen, {
input: BoundInputForWelcome,
suggestionView: BoundSuggestionView !== null && BoundSuggestionView !== void 0 ? BoundSuggestionView : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, {})
});
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-copilotkit": true,
"data-testid": "copilot-chat",
"data-copilot-running": isRunning ? "true" : "false",
className: (0, tailwind_merge.twMerge)("copilotKitChat cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
...props,
children: BoundWelcomeScreen
});
}
if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-copilotkit": true,
style: { display: "contents" },
children: children({
messageView: BoundMessageView,
input: BoundInput,
scrollView: BoundScrollView,
suggestionView: BoundSuggestionView !== null && BoundSuggestionView !== void 0 ? BoundSuggestionView : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, {})
})
});
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
"data-copilotkit": true,
"data-testid": "copilot-chat",
"data-copilot-running": isRunning ? "true" : "false",
className: (0, tailwind_merge.twMerge)("copilotKitChat cpk:relative cpk:h-full", className),
...props,
children: [BoundScrollView, BoundInput]
});
}
(function(_CopilotChatView) {
const ScrollContent = ({ children, scrollToBottomButton, feather, inputContainerHeight, isResizing }) => {
const { isAtBottom, scrollToBottom } = (0, use_stick_to_bottom.useStickToBottomContext)();
const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(use_stick_to_bottom.StickToBottom.Content, {
className: "cpk:overflow-y-scroll cpk:overflow-x-hidden",
style: {
flex: "1 1 0%",
minHeight: 0
},
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
children
})
}),
BoundFeather,
!isAtBottom && !isResizing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none",
style: { bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px` },
children: renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () => scrollToBottom() })
})
] });
};
_CopilotChatView.ScrollView = ({ children, autoScroll = true, scrollToBottomButton, feather, inputContainerHeight = 0, isResizing = false, className, ...props }) => {
const [hasMounted, setHasMounted] = (0, react.useState)(false);
const { scrollRef, contentRef, scrollToBottom } = (0, use_stick_to_bottom.useStickToBottom)();
const [showScrollButton, setShowScrollButton] = (0, react.useState)(false);
(0, react.useEffect)(() => {
setHasMounted(true);
}, []);
(0, react.useEffect)(() => {
if (autoScroll) return;
const scrollElement = scrollRef.current;
if (!scrollElement) return;
const checkScroll = () => {
setShowScrollButton(!(scrollElement.scrollHeight - scrollElement.scrollTop - scrollElement.clientHeight < 10));
};
checkScroll();
scrollElement.addEventListener("scroll", checkScroll);
const resizeObserver = new ResizeObserver(checkScroll);
resizeObserver.observe(scrollElement);
return () => {
scrollElement.removeEventListener("scroll", checkScroll);
resizeObserver.disconnect();
};
}, [scrollRef, autoScroll]);
if (!hasMounted) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:overflow-y-scroll cpk:overflow-x-hidden",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
children
})
});
if (!autoScroll) {
const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
ref: scrollRef,
className: cn("cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:overflow-y-scroll cpk:overflow-x-hidden cpk:relative", className),
...props,
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
ref: contentRef,
className: "cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
children
}),
BoundFeather,
showScrollButton && !isResizing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none",
style: { bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px` },
children: renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () => scrollToBottom() })
})
]
});
}
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(use_stick_to_bottom.StickToBottom, {
className: cn("cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:relative", className),
resize: "smooth",
initial: "smooth",
...props,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScrollContent, {
scrollToBottomButton,
feather,
inputContainerHeight,
isResizing,
children
})
});
};
_CopilotChatView.ScrollToBottomButton = ({ className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
"data-testid": "copilot-scroll-to-bottom",
variant: "outline",
size: "sm",
className: (0, tailwind_merge.twMerge)("cpk:rounded-full cpk:w-10 cpk:h-10 cpk:p-0 cpk:pointer-events-auto", "cpk:bg-white cpk:dark:bg-gray-900", "cpk:shadow-lg cpk:border cpk:border-gray-200 cpk:dark:border-gray-700", "cpk:hover:bg-gray-50 cpk:dark:hover:bg-gray-800", "cpk:flex cpk:items-center cpk:justify-center cpk:cursor-pointer", className),
...props,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.ChevronDown, { className: "cpk:w-4 cpk:h-4 cpk:text-gray-600 cpk:dark:text-white" })
});
_CopilotChatView.Feather = ({ className, style, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: cn("cpk:absolute cpk:bottom-0 cpk:left-0 cpk:right-4 cpk:h-24 cpk:pointer-events-none cpk:z-10 cpk:bg-gradient-to-t", "cpk:from-white cpk:via-white cpk:to-transparent", "cpk:dark:from-[rgb(33,33,33)] cpk:dark:via-[rgb(33,33,33)]", className),
style,
...props
});
_CopilotChatView.WelcomeMessage = ({ className, ...props }) => {
var _config$labels;
const config = useCopilotChatConfiguration();
const labels = (_config$labels = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels !== void 0 ? _config$labels : CopilotChatDefaultLabels;
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
className: cn("cpk:text-xl cpk:sm:text-2xl cpk:font-medium cpk:text-foreground cpk:text-center", className),
...props,
children: labels.welcomeMessageText
});
};
_CopilotChatView.WelcomeScreen = ({ welcomeMessage, input, suggestionView, className, children, ...props }) => {
const BoundWelcomeMessage = renderSlot(welcomeMessage, CopilotChatView.WelcomeMessage, {});
if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-copilotkit": true,
style: { display: "contents" },
children: children({
welcomeMessage: BoundWelcomeMessage,
input,
suggestionView,
className,
...props
})
});
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-testid": "copilot-welcome-screen",
className: cn("cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4", className),
...props,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
className: "cpk:w-full cpk:max-w-3xl cpk:flex cpk:flex-col cpk:items-center",
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:mb-6",
children: BoundWelcomeMessage
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:w-full",
children: input
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:mt-4 cpk:flex cpk:justify-center",
children: suggestionView
})
]
})
});
};
})(CopilotChatView || (CopilotChatView = {}));
var CopilotChatView_default = CopilotChatView;
//#endregion
//#region src/lib/transcription-client.ts
/**
* Convert a Blob to a base64 string
*/
async function blobToBase64(blob) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => {
const base64 = reader.result.split(",")[1];
resolve(base64 !== null && base64 !== void 0 ? base64 : "");
};
reader.onerror = () => reject(/* @__PURE__ */ new Error("Failed to read audio data"));
reader.readAsDataURL(blob);
});
}
/**
* Check if an error response matches our expected format
*/
function isTranscriptionErrorResponse(data) {
return typeof data === "object" && data !== null && "error" in data && "message" in data && typeof data.error === "string" && typeof data.message === "string";
}
/**
* Parse error info from a transcription error response
*/
function parseTranscriptionError(response) {
var _response$retryable;
return {
code: response.error,
message: response.message,
retryable: (_response$retryable = response.retryable) !== null && _response$retryable !== void 0 ? _response$retryable : false
};
}
/**
* Custom error type for transcription failures.
* Extends Error with transcription-specific info for contextual error handling.
*/
var TranscriptionError = class extends Error {
constructor(info) {
super(info.message);
_defineProperty(this, "info", void 0);
this.name = "TranscriptionError";
this.info = info;
}
};
/**
* Transcribe an audio blob using the CopilotKit runtime
*
* Supports both REST mode (multipart/form-data) and single-endpoint mode (base64 JSON)
*
* @throws {TranscriptionError} When transcription fails with typed error information
*/
async function transcribeAudio(core, audioBlob, filename = "recording.webm") {
const runtimeUrl = core.runtimeUrl;
if (!runtimeUrl) throw new TranscriptionError({
code: _copilotkitnext_shared.TranscriptionErrorCode.INVALID_REQUEST,
message: "Runtime URL is not configured",
retryable: false
});
const headers = { ...core.headers };
let response;
try {
if (core.runtimeTransport === "single") {
const base64Audio = await blobToBase64(audioBlob);
headers["Content-Type"] = "application/json";
response = await fetch(runtimeUrl, {
method: "POST",
headers,
body: JSON.stringify({
method: "transcribe",
body: {
audio: base64Audio,
mimeType: audioBlob.type || "audio/webm",
filename
}
})
});
} else {
delete headers["Content-Type"];
const formData = new FormData();
formData.append("audio", audioBlob, filename);
response = await fetch(`${runtimeUrl}/transcribe`, {
method: "POST",
headers,
body: formData
});
}
} catch (error) {
throw new TranscriptionError({
code: _copilotkitnext_shared.TranscriptionErrorCode.NETWORK_ERROR,
message: error instanceof Error ? error.message : "Network request failed",
retryable: true
});
}
if (!response.ok) {
let errorData;
try {
errorData = await response.json();
} catch (_unused) {
throw new TranscriptionError({
code: _copilotkitnext_shared.TranscriptionErrorCode.PROVIDER_ERROR,
message: `HTTP ${response.status}: ${response.statusText}`,
retryable: response.status >= 500
});
}
if (isTranscriptionErrorResponse(errorData)) throw new TranscriptionError(parseTranscriptionError(errorData));
throw new TranscriptionError({
code: _copilotkitnext_shared.TranscriptionErrorCode.PROVIDER_ERROR,
message: typeof errorData === "object" && errorData !== null && "message" in errorData ? String(errorData.message) : "Transcription failed",
retryable: response.status >= 500
});
}
return await response.json();
}
//#endregion
//#region src/components/chat/CopilotChat.tsx
function CopilotChat({ agentId, threadId, labels, chatView, onError, ...props }) {
var _ref;
const existingConfig = useCopilotChatConfiguration();
const resolvedAgentId = (_ref = agentId !== null && agentId !== void 0 ? agentId : existingConfig === null || existingConfig === void 0 ? void 0 : existingConfig.agentId) !== null && _ref !== void 0 ? _ref : _copilotkitnext_shared.DEFAULT_AGENT_ID;
const resolvedThreadId = (0, react.useMemo)(() => {
var _ref2;
return (_ref2 = threadId !== null && threadId !== void 0 ? threadId : existingConfig === null || existingConfig === void 0 ? void 0 : existingConfig.threadId) !== null && _ref2 !== void 0 ? _ref2 : (0, _copilotkitnext_shared.randomUUID)();
}, [threadId, existingConfig === null || existingConfig === void 0 ? void 0 : existingConfig.threadId]);
const { agent } = useAgent({ agentId: resolvedAgentId });
const { copilotkit } = useCopilotKit();
const { suggestions: autoSuggestions } = useSuggestions({ agentId: resolvedAgentId });
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) => {
var _event$context, _event$context2;
if (((_event$context = event.context) === null || _event$context === void 0 ? void 0 : _event$context.agentId) === resolvedAgentId || !((_event$context2 = event.context) === null || _event$context2 === void 0 ? void 0 : _event$context2.agentId)) {
var _onErrorRef$current;
(_onErrorRef$current = onErrorRef.current) === null || _onErrorRef$current === void 0 || _onErrorRef$current.call(onErrorRef, {
error: event.error,
code: event.code,
context: event.context
});
}
} });
return () => {
subscription.unsubscribe();
};
}, [copilotkit, resolvedAgentId]);
const [transcribeMode, setTranscribeMode] = (0, react.useState)("input");
const [inputValue, setInputValue] = (0, react.useState)("");
const [transcriptionError, setTranscriptionError] = (0, react.useState)(null);
const [isTranscribing, setIsTranscribing] = (0, react.useState)(false);
const isTranscriptionEnabled = copilotkit.audioFileTranscriptionEnabled;
const isMediaRecorderSupported = typeof window !== "undefined" && typeof MediaRecorder !== "undefined";
const { messageView: providedMessageView, suggestionView: providedSuggestionView, onStop: providedStopHandler, ...restProps } = props;
(0, react.useEffect)(() => {
let detached = false;
const connectAbortController = new AbortController();
if (agent instanceof _ag_ui_client.HttpAgent) agent.abortController = connectAbortController;
const connect = async (agent) => {
try {
await copilotkit.connectAgent({ agent });
} catch (error) {
if (detached) return;
console.error("CopilotChat: connectAgent failed", error);
}
};
agent.threadId = resolvedThreadId;
connect(agent);
return () => {
detached = true;
connectAbortController.abort();
agent.detachActiveRun();
};
}, [
resolvedThreadId,
agent,
resolvedAgentId
]);
const onSubmitInput = (0, react.useCallback)(async (value) => {
agent.addMessage({
id: (0, _copilotkitnext_shared.randomUUID)(),
role: "user",
content: value
});
setInputValue("");
try {
await copilotkit.runAgent({ agent });
} catch (error) {
console.error("CopilotChat: runAgent failed", error);
}
}, [agent]);
const handleSelectSuggestion = (0, react.useCallback)(async (suggestion) => {
agent.addMessage({
id: (0, _copilotkitnext_shared.randomUUID)(),
role: "user",
content: suggestion.message
});
try {
await copilotkit.runAgent({ agent });
} catch (error) {
console.error("CopilotChat: runAgent failed after selecting suggestion", error);
}
}, [agent]);
const stopCurrentRun = (0, react.useCallback)(() => {
try {
copilotkit.stopAgent({ agent });
} catch (error) {
console.error("CopilotChat: stopAgent failed", error);
try {
agent.abortRun();
} catch (abortError) {
console.error("CopilotChat: abortRun fallback failed", abortError);
}
}
}, [agent]);
const handleStartTranscribe = (0, react.useCallback)(() => {
setTranscriptionError(null);
setTranscribeMode("transcribe");
}, []);
const handleCancelTranscribe = (0, react.useCallback)(() => {
setTranscriptionError(null);
setTranscribeMode("input");
}, []);
const handleFinishTranscribe = (0, react.useCallback)(() => {
setTranscribeMode("input");
}, []);
const handleFinishTranscribeWithAudio = (0, react.useCallback)(async (audioBlob) => {
setIsTranscribing(true);
try {
setTranscriptionError(null);
const result = await transcribeAudio(copilotkit, audioBlob);
setInputValue((prev) => {
const trimmedPrev = prev.trim();
if (trimmedPrev) return `${trimmedPrev} ${result.text}`;
return result.text;
});
} catch (error) {
console.error("CopilotChat: Transcription failed", error);
if (error instanceof TranscriptionError) {
const { code, retryable, message } = error.info;
switch (code) {
case _copilotkitnext_shared.TranscriptionErrorCode.RATE_LIMITED:
setTranscriptionError("Too many requests. Please wait a moment.");
break;
case _copilotkitnext_shared.TranscriptionErrorCode.AUTH_FAILED:
setTranscriptionError("Authentication error. Please check your configuration.");
break;
case _copilotkitnext_shared.TranscriptionErrorCode.AUDIO_TOO_LONG:
setTranscriptionError("Recording is too long. Please try a shorter recording.");
break;
case _copilotkitnext_shared.TranscriptionErrorCode.AUDIO_TOO_SHORT:
setTranscriptionError("Recording is too short. Please try again.");
break;
case _copilotkitnext_shared.TranscriptionErrorCode.INVALID_AUDIO_FORMAT:
setTranscriptionError("Audio format not supported.");
break;
case _copilotkitnext_shared.TranscriptionErrorCode.SERVICE_NOT_CONFIGURED:
setTranscriptionError("Transcription service is not available.");
break;
case _copilotkitnext_shared.TranscriptionErrorCode.NETWORK_ERROR:
setTranscriptionError("Network error. Please check your connection.");
break;
default: setTranscriptionError(retryable ? "Transcription failed. Please try again." : message);
}
} else setTranscriptionError("Transcription failed. Please try again.");
} finally {
setIsTranscribing(false);
}
}, []);
(0, react.useEffect)(() => {
if (transcriptionError) {
const timer = setTimeout(() => {
setTranscriptionError(null);
}, 5e3);
return () => clearTimeout(timer);
}
}, [transcriptionError]);
const mergedProps = (0, ts_deepmerge.merge)({
isRunning: agent.isRunning,
suggestions: autoSuggestions,
onSelectSuggestion: handleSelectSuggestion,
suggestionView: providedSuggestionView
}, {
...restProps,
...typeof providedMessageView === "string" ? { messageView: { className: providedMessageView } } : providedMessageView !== void 0 ? { messageView: providedMessageView } : {}
});
const hasMessages = agent.messages.length > 0;
const effectiveStopHandler = agent.isRunning && hasMessages ? providedStopHandler !== null && providedStopHandler !== void 0 ? providedStopHandler : stopCurrentRun : providedStopHandler;
const showTranscription = isTranscriptionEnabled && isMediaRecorderSupported;
const effectiveMode = isTranscribing ? "processing" : transcribeMode;
const RenderedChatView = renderSlot(chatView, CopilotChatView, (0, ts_deepmerge.merge)(mergedProps, {
messages: (0, react.useMemo)(() => [...agent.messages], [JSON.stringify(agent.messages)]),
onSubmitMessage: onSubmitInput,
onStop: effectiveStopHandler,
inputMode: effectiveMode,
inputValue,
onInputChange: setInputValue,
onStartTranscribe: showTranscription ? handleStartTranscribe : void 0,
onCancelTranscribe: showTranscription ? handleCancelTranscribe : void 0,
onFinishTranscribe: showTranscription ? handleFinishTranscribe : void 0,
onFinishTranscribeWithAudio: showTranscription ? handleFinishTranscribeWithAudio : void 0
}));
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CopilotChatConfigurationProvider, {
agentId: resolvedAgentId,
threadId: resolvedThreadId,
labels,
children: [transcriptionError && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
style: {
position: "absolute",
bottom: "100px",
left: "50%",
transform: "translateX(-50%)",
backgroundColor: "#ef4444",
color: "white",
padding: "8px 16px",
borderRadius: "8px",
fontSize: "14px",
zIndex: 50
},
children: transcriptionError
}), RenderedChatView]
});
}
(function(_CopilotChat) {
_CopilotChat.View = CopilotChatView;
})(CopilotChat || (CopilotChat = {}));
//#endregion
//#region src/components/chat/CopilotChatToggleButton.tsx
const DefaultOpenIcon = ({ className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.MessageCircle, {
className: cn("cpk:h-6 cpk:w-6", className),
strokeWidth: 1.75,
fill: "currentColor",
...props
});
const DefaultCloseIcon = ({ className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.X, {
className: cn("cpk:h-6 cpk:w-6", className),
strokeWidth: 1.75,
...props
});
DefaultOpenIcon.displayName = "CopilotChatToggleButton.OpenIcon";
DefaultCloseIcon.displayName = "CopilotChatToggleButton.CloseIcon";
const ICON_TRANSITION_STYLE = Object.freeze({ transition: "opacity 120ms ease-out, transform 260ms cubic-bezier(0.22, 1, 0.36, 1)" });
const ICON_WRAPPER_BASE = "cpk:pointer-events-none cpk:absolute cpk:inset-0 cpk:flex cpk:items-center cpk:justify-center cpk:will-change-transform";
const BUTTON_BASE_CLASSES = cn("copilotKitButton", "cpk:fixed cpk:bottom-6 cpk:right-6 cpk:z-[1100] cpk:flex cpk:h-14 cpk:w-14 cpk:items-center cpk:justify-center", "cpk:rounded-full cpk:border cpk:border-primary cpk:bg-primary cpk:text-primary-foreground", "cpk:shadow-sm cpk:transition-all cpk:duration-200 cpk:ease-out", "cpk:hover:scale-[1.04] cpk:hover:shadow-md", "cpk:cursor-pointer", "cpk:active:scale-[0.96]", "cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-primary/50 cpk:focus-visible:ring-offset-2 cpk:focus-visible:ring-offset-background", "cpk:disabled:pointer-events-none cpk:disabled:opacity-60");
const CopilotChatToggleButton = react.default.forwardRef(function CopilotChatToggleButton({ openIcon, closeIcon, className, ...buttonProps }, ref) {
var _configuration$labels, _configuration$isModa, _configuration$setMod;
const { onClick, type, disabled, ...restProps } = buttonProps;
const configuration = useCopilotChatConfiguration();
const labels = (_configuration$labels = configuration === null || configuration === void 0 ? void 0 : configuration.labels) !== null && _configuration$labels !== void 0 ? _configuration$labels : CopilotChatDefaultLabels;
const [fallbackOpen, setFallbackOpen] = (0, react.useState)(false);
const isOpen = (_configuration$isModa = configuration === null || configuration === void 0 ? void 0 : configuration.isModalOpen) !== null && _configuration$isModa !== void 0 ? _configuration$isModa : fallbackOpen;
const setModalOpen = (_configuration$setMod = configuration === null || configuration === void 0 ? void 0 : configuration.setModalOpen) !== null && _configuration$setMod !== void 0 ? _configuration$setMod : setFallbackOpen;
const handleClick = (event) => {
if (disabled) return;
if (onClick) onClick(event);
if (event.defaultPrevented) return;
setModalOpen(!isOpen);
};
const renderedOpenIcon = renderSlot(openIcon, DefaultOpenIcon, {
className: "cpk:h-6 cpk:w-6",
"aria-hidden": true,
focusable: false
});
const renderedCloseIcon = renderSlot(closeIcon, DefaultCloseIcon, {
className: "cpk:h-6 cpk:w-6",
"aria-hidden": true,
focusable: false
});
const openIconElement = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
"aria-hidden": "true",
"data-slot": "chat-toggle-button-open-icon",
className: ICON_WRAPPER_BASE,
style: {
...ICON_TRANSITION_STYLE,
opacity: isOpen ? 0 : 1,
transform: `scale(${isOpen ? .75 : 1}) rotate(${isOpen ? 90 : 0}deg)`
},
children: renderedOpenIcon
});
const closeIconElement = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
"aria-hidden": "true",
"data-slot": "chat-toggle-button-close-icon",
className: ICON_WRAPPER_BASE,
style: {
...ICON_TRANSITION_STYLE,
opacity: isOpen ? 1 : 0,
transform: `scale(${isOpen ? 1 : .75}) rotate(${isOpen ? 0 : -90}deg)`
},
children: renderedCloseIcon
});
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
ref,
type: type !== null && type !== void 0 ? type : "button",
"data-copilotkit": true,
"data-testid": "copilot-chat-toggle",
"data-slot": "chat-toggle-button",
"data-state": isOpen ? "open" : "closed",
className: cn(BUTTON_BASE_CLASSES, className),
"aria-label": isOpen ? labels.chatToggleCloseLabel : labels.chatToggleOpenLabel,
"aria-pressed": isOpen,
disabled,
onClick: handleClick,
...restProps,
children: [openIconElement, closeIconElement]
});
});
CopilotChatToggleButton.displayName = "CopilotChatToggleButton";
//#endregion
//#region src/components/chat/CopilotModalHeader.tsx
function CopilotModalHeader({ title, titleContent, closeButton, children, className, ...rest }) {
var _configuration$labels;
const configuration = useCopilotChatConfiguration();
const fallbackTitle = (_configuration$labels = configuration === null || configuration === void 0 ? void 0 : configuration.labels.modalHeaderTitle) !== null && _configuration$labels !== void 0 ? _configuration$labels : CopilotChatDefaultLabels.modalHeaderTitle;
const resolvedTitle = title !== null && title !== void 0 ? title : fallbackTitle;
const handleClose = (0, react.useCallback)(() => {
var _configuration$setMod;
configuration === null || configuration === void 0 || (_configuration$setMod = configuration.setModalOpen) === null || _configuration$setMod === void 0 || _configuration$setMod.call(configuration, false);
}, [configuration]);
const BoundTitle = renderSlot(titleContent, CopilotModalHeader.Title, { children: resolvedTitle });
const BoundCloseButton = renderSlot(closeButton, CopilotModalHeader.CloseButton, { onClick: handleClose });
if (children) return children({
titleContent: BoundTitle,
closeButton: BoundCloseButton,
title: resolvedTitle,
...rest
});
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("header", {
"data-testid": "copilot-modal-header",
"data-slot": "copilot-modal-header",
className: cn("copilotKitHeader", "cpk:flex cpk:items-center cpk:justify-between cpk:border-b cpk:border-border cpk:px-4 cpk:py-4", "cpk:bg-background/95 cpk:backdrop-blur cpk:supports-[backdrop-filter]:bg-background/80", className),
...rest,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
className: "cpk:flex cpk:w-full cpk:items-center cpk:gap-2",
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:flex-1",
"aria-hidden": "true"
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:flex cpk:flex-1 cpk:justify-center cpk:text-center",
children: BoundTitle
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:flex cpk:flex-1 cpk:justify-end",
children: BoundCloseButton
})
]
})
});
}
CopilotModalHeader.displayName = "CopilotModalHeader";
(function(_CopilotModalHeader) {
_CopilotModalHeader.Title = ({ children, className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-testid": "copilot-header-title",
className: cn("cpk:w-full cpk:text-base cpk:font-medium cpk:leading-none cpk:tracking-tight cpk:text-foreground", className),
...props,
children
});
_CopilotModalHeader.CloseButton = ({ className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
type: "button",
"data-testid": "copilot-close-button",
className: cn("cpk:inline-flex cpk:size-8 cpk:items-center cpk:justify-center cpk:rounded-full cpk:text-muted-foreground cpk:transition cpk:cursor-pointer", "cpk:hover:bg-muted cpk:hover:text-foreground cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-ring", className),
"aria-label": "Close",
...props,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.X, {
className: "cpk:h-4 cpk:w-4",
"aria-hidden": "true"
})
});
})(CopilotModalHeader || (CopilotModalHeader = {}));
CopilotModalHeader.Title.displayName = "CopilotModalHeader.Title";
CopilotModalHeader.CloseButton.displayName = "CopilotModalHeader.CloseButton";
//#endregion
//#region src/components/chat/CopilotSidebarView.tsx
const DEFAULT_SIDEBAR_WIDTH = 480;
const SIDEBAR_TRANSITION_MS = 260;
function CopilotSidebarView({ header, toggleButton, width, defaultOpen = true, ...props }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfigurationProvider, {
isModalDefaultOpen: defaultOpen,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotSidebarViewInternal, {
header,
toggleButton,
width,
...props
})
});
}
function CopilotSidebarViewInternal({ header, toggleButton, width, ...props }) {
var _configuration$isModa;
const configuration = useCopilotChatConfiguration();
const isSidebarOpen = (_configuration$isModa = configuration === null || configuration === void 0 ? void 0 : configuration.isModalOpen) !== null && _configuration$isModa !== void 0 ? _configuration$isModa : false;
const sidebarRef = (0, react.useRef)(null);
const [sidebarWidth, setSidebarWidth] = (0, react.useState)(width !== null && width !== void 0 ? width : DEFAULT_SIDEBAR_WIDTH);
const widthToCss = (w) => {
return typeof w === "number" ? `${w}px` : w;
};
const widthToMargin = (w) => {
if (typeof w === "number") return `${w}px`;
return w;
};
(0, react.useEffect)(() => {
if (width !== void 0) return;
if (typeof window === "undefined") return;
const element = sidebarRef.current;
if (!element) return;
const updateWidth = () => {
const rect = element.getBoundingClientRect();
if (rect.width > 0) setSidebarWidth(rect.width);
};
updateWidth();
if (typeof ResizeObserver !== "undefined") {
const observer = new ResizeObserver(() => updateWidth());
observer.observe(element);
return () => observer.disconnect();
}
window.addEventListener("resize", updateWidth);
return () => window.removeEventListener("resize", updateWidth);
}, [width]);
const hasMounted = (0, react.useRef)(false);
(0, react.useLayoutEffect)(() => {
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
if (!window.matchMedia("(min-width: 768px)").matches) return;
if (isSidebarOpen) {
if (hasMounted.current) document.body.style.transition = `margin-inline-end ${SIDEBAR_TRANSITION_MS}ms ease`;
document.body.style.marginInlineEnd = widthToMargin(sidebarWidth);
} else if (hasMounted.current) {
document.body.style.transition = `margin-inline-end ${SIDEBAR_TRANSITION_MS}ms ease`;
document.body.style.marginInlineEnd = "";
}
hasMounted.current = true;
return () => {
document.body.style.marginInlineEnd = "";
document.body.style.transition = "";
};
}, [isSidebarOpen, sidebarWidth]);
const headerElement = renderSlot(header, CopilotModalHeader, {});
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [renderSlot(toggleButton, CopilotChatToggleButton, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("aside", {
ref: sidebarRef,
"data-copilotkit": true,
"data-testid": "copilot-sidebar",
"data-copilot-sidebar": true,
className: cn("copilotKitSidebar copilotKitWindow", "cpk:fixed cpk:right-0 cpk:top-0 cpk:z-[1200] cpk:flex", "cpk:h-[100vh] cpk:h-[100dvh] cpk:max-h-screen", "cpk:w-full", "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" : "cpk:translate-x-full cpk:pointer-events-none"),
style: {
["--sidebar-width"]: widthToCss(sidebarWidth),
paddingTop: "env(safe-area-inset-top)",
paddingBottom: "env(safe-area-inset-bottom)"
},
"aria-hidden": !isSidebarOpen,
"aria-label": "Copilot chat sidebar",
role: "complementary",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
className: "cpk:flex cpk:h-full cpk:w-full cpk:flex-col cpk:overflow-hidden",
children: [headerElement, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:flex-1 cpk:overflow-hidden",
"data-sidebar-chat": true,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatView_default, { ...props })
})]
})
})] });
}
CopilotSidebarView.displayName = "CopilotSidebarView";
(function(_CopilotSidebarView) {
_CopilotSidebarView.WelcomeScreen = ({ welcomeMessage, input, suggestionView, className, children, ...props }) => {
const BoundWelcomeMessage = renderSlot(welcomeMessage, CopilotChatView_default.WelcomeMessage, {});
if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-copilotkit": true,
style: { display: "contents" },
children: children({
welcomeMessage: BoundWelcomeMessage,
input,
suggestionView,
className,
...props
})
});
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
className: cn("cpk:h-full cpk:flex cpk:flex-col", className),
...props,
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4",
children: BoundWelcomeMessage
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:px-8 cpk:pb-4",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
className: "cpk:max-w-3xl cpk:mx-auto",
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:mb-4 cpk:flex cpk:justify-center",
children: suggestionView
}), input]
})
})]
});
};
})(CopilotSidebarView || (CopilotSidebarView = {}));
//#endregion
//#region src/components/chat/CopilotPopupView.tsx
const DEFAULT_POPUP_WIDTH = 420;
const DEFAULT_POPUP_HEIGHT = 560;
const dimensionToCss = (value, fallback) => {
if (typeof value === "number" && Number.isFinite(value)) return `${value}px`;
if (typeof value === "string" && value.trim().length > 0) return value;
return `${fallback}px`;
};
function CopilotPopupView({ header, toggleButton, width, height, clickOutsideToClose, defaultOpen = true, className, ...restProps }) {
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfigurationProvider, {
isModalDefaultOpen: defaultOpen,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotPopupViewInternal, {
header,
toggleButton,
width,
height,
clickOutsideToClose,
className,
...restProps
})
});
}
function CopilotPopupViewInternal({ header, toggleButton, width, height, clickOutsideToClose, className, ...restProps }) {
var _configuration$isModa, _configuration$labels;
const configuration = useCopilotChatConfiguration();
const isPopupOpen = (_configuration$isModa = configuration === null || configuration === void 0 ? void 0 : configuration.isModalOpen) !== null && _configuration$isModa !== void 0 ? _configuration$isModa : false;
const setModalOpen = configuration === null || configuration === void 0 ? void 0 : configuration.setModalOpen;
const labels = (_configuration$labels = configuration === null || configuration === void 0 ? void 0 : configuration.labels) !== null && _configuration$labels !== void 0 ? _configuration$labels : CopilotChatDefaultLabels;
const containerRef = (0, react.useRef)(null);
const [isRendered, setIsRendered] = (0, react.useState)(isPopupOpen);
const [isAnimatingOut, setIsAnimatingOut] = (0, react.useState)(false);
(0, react.useEffect)(() => {
if (isPopupOpen) {
setIsRendered(true);
setIsAnimatingOut(false);
return;
}
if (!isRendered) return;
setIsAnimatingOut(true);
const timeout = setTimeout(() => {
setIsRendered(false);
setIsAnimatingOut(false);
}, 200);
return () => clearTimeout(timeout);
}, [isPopupOpen, isRendered]);
(0, react.useEffect)(() => {
if (!isPopupOpen) return;
if (typeof window === "undefined") return;
const handleKeyDown = (event) => {
if (event.key === "Escape") {
event.preventDefault();
setModalOpen === null || setModalOpen === void 0 || setModalOpen(false);
}
};
window.addEventListener("keydown", handleKeyDown);
return () => window.removeEventListener("keydown", handleKeyDown);
}, [isPopupOpen, setModalOpen]);
(0, react.useEffect)(() => {
if (!isPopupOpen) return;
const focusTimer = setTimeout(() => {
const container = containerRef.current;
if (container && !container.contains(document.activeElement)) container.focus({ preventScroll: true });
}, 200);
return () => clearTimeout(focusTimer);
}, [isPopupOpen]);
(0, react.useEffect)(() => {
if (!isPopupOpen || !clickOutsideToClose) return;
if (typeof document === "undefined") return;
const handlePointerDown = (event) => {
const target = event.target;
if (!target) return;
const container = containerRef.current;
if (container === null || container === void 0 ? void 0 : container.contains(target)) return;
const toggleButton = document.querySelector("[data-slot='chat-toggle-button']");
if (toggleButton && toggleButton.contains(target)) return;
setModalOpen === null || setModalOpen === void 0 || setModalOpen(false);
};
document.addEventListener("pointerdown", handlePointerDown);
return () => document.removeEventListener("pointerdown", handlePointerDown);
}, [
isPopupOpen,
clickOutsideToClose,
setModalOpen
]);
const headerElement = (0, react.useMemo)(() => renderSlot(header, CopilotModalHeader, {}), [header]);
const toggleButtonElement = (0, react.useMemo)(() => renderSlot(toggleButton, CopilotChatToggleButton, {}), [toggleButton]);
const resolvedWidth = dimensionToCss(width, DEFAULT_POPUP_WIDTH);
const resolvedHeight = dimensionToCss(height, DEFAULT_POPUP_HEIGHT);
const popupStyle = (0, react.useMemo)(() => ({
"--copilot-popup-width": resolvedWidth,
"--copilot-popup-height": resolvedHeight,
"--copilot-popup-max-width": "calc(100vw - 3rem)",
"--copilot-popup-max-height": "calc(100dvh - 7.5rem)",
paddingTop: "env(safe-area-inset-top)",
paddingBottom: "env(safe-area-inset-bottom)",
paddingLeft: "env(safe-area-inset-left)",
paddingRight: "env(safe-area-inset-right)"
}), [resolvedHeight, resolvedWidth]);
const popupAnimationClass = isPopupOpen && !isAnimatingOut ? "cpk:pointer-events-auto cpk:translate-y-0 cpk:opacity-100 cpk:md:scale-100" : "cpk:pointer-events-none cpk:translate-y-4 cpk:opacity-0 cpk:md:translate-y-5 cpk:md:scale-[0.95]";
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [toggleButtonElement, isRendered ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-copilotkit": true,
className: cn("cpk:fixed cpk:inset-0 cpk:z-[1200] cpk:flex cpk:max-w-full cpk:flex-col cpk:items-stretch", "cpk:md:inset-auto cpk:md:bottom-24 cpk:md:right-6 cpk:md:items-end cpk:md:gap-4"),
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
ref: containerRef,
tabIndex: -1,
role: "dialog",
"aria-label": labels.modalHeaderTitle,
"data-testid": "copilot-popup",
"data-copilot-popup": true,
className: cn("copilotKitPopup copilotKitWindow", "cpk:relative cpk:flex cpk:h-full cpk:w-full cpk:flex-col cpk:overflow-hidden cpk:bg-background cpk:text-foreground", "cpk:origin-bottom cpk:focus:outline-none cpk:transform-gpu cpk:transition-transform cpk:transition-opacity cpk:duration-200 cpk:ease-out", "cpk:md:transition-transform cpk:md:transition-opacity", "cpk:rounded-none cpk:border cpk:border-border/0 cpk:shadow-none cpk:ring-0", "cpk:md:h-[var(--copilot-popup-height)] cpk:md:w-[var(--copilot-popup-width)]", "cpk:md:max-h-[var(--copilot-popup-max-height)] cpk:md:max-w-[var(--copilot-popup-max-width)]", "cpk:md:origin-bottom-right cpk:md:rounded-2xl cpk:md:border-border cpk:md:shadow-xl cpk:md:ring-1 cpk:md:ring-border/40", popupAnimationClass),
style: popupStyle,
children: [headerElement, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:flex-1 cpk:overflow-hidden",
"data-popup-chat": true,
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatView_default, {
...restProps,
className: cn("cpk:h-full cpk:min-h-0", className)
})
})]
})
}) : null] });
}
CopilotPopupView.displayName = "CopilotPopupView";
(function(_CopilotPopupView) {
_CopilotPopupView.WelcomeScreen = ({ welcomeMessage, input, suggestionView, className, children, ...props }) => {
const BoundWelcomeMessage = renderSlot(welcomeMessage, CopilotChatView_default.WelcomeMessage, {});
if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
"data-copilotkit": true,
style: { display: "contents" },
children: children({
welcomeMessage: BoundWelcomeMessage,
input,
suggestionView,
className,
...props
})
});
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
className: cn("cpk:h-full cpk:flex cpk:flex-col", className),
...props,
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:flex-1 cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:px-4",
children: BoundWelcomeMessage
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:mb-4 cpk:flex cpk:justify-center cpk:px-4",
children: suggestionView
}), input] })]
});
};
})(CopilotPopupView || (CopilotPopupView = {}));
var CopilotPopupView_default = CopilotPopupView;
//#endregion
//#region src/components/chat/CopilotSidebar.tsx
function CopilotSidebar({ header, toggleButton, defaultOpen, width, ...chatProps }) {
const SidebarViewOverride = (0, react.useMemo)(() => {
const Component = (viewProps) => {
const { header: viewHeader, toggleButton: viewToggleButton, width: viewWidth, defaultOpen: viewDefaultOpen, ...restProps } = viewProps;
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotSidebarView, {
...restProps,
header: header !== null && header !== void 0 ? header : viewHeader,
toggleButton: toggleButton !== null && toggleButton !== void 0 ? toggleButton : viewToggleButton,
width: width !== null && width !== void 0 ? width : viewWidth,
defaultOpen: defaultOpen !== null && defaultOpen !== void 0 ? defaultOpen : viewDefaultOpen
});
};
return Object.assign(Component, CopilotChatView_default);
}, [
header,
toggleButton,
width,
defaultOpen
]);
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChat, {
welcomeScreen: CopilotSidebarView.WelcomeScreen,
...chatProps,
chatView: SidebarViewOverride
});
}
CopilotSidebar.displayName = "CopilotSidebar";
//#endregion
//#region src/components/chat/CopilotPopup.tsx
function CopilotPopup({ header, toggleButton, defaultOpen, width, height, clickOutsideToClose, ...chatProps }) {
const PopupViewOverride = (0, react.useMemo)(() => {
const Component = (viewProps) => {
const { header: viewHeader, toggleButton: viewToggleButton, width: viewWidth, height: viewHeight, clickOutsideToClose: viewClickOutsideToClose, defaultOpen: viewDefaultOpen, ...restProps } = viewProps;
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotPopupView_default, {
...restProps,
header: header !== null && header !== void 0 ? header : viewHeader,
toggleButton: toggleButton !== null && toggleButton !== void 0 ? toggleButton : viewToggleButton,
width: width !== null && width !== void 0 ? width : viewWidth,
height: height !== null && height !== void 0 ? height : viewHeight,
clickOutsideToClose: clickOutsideToClose !== null && clickOutsideToClose !== void 0 ? clickOutsideToClose : viewClickOutsideToClose,
defaultOpen: defaultOpen !== null && defaultOpen !== void 0 ? defaultOpen : viewDefaultOpen
});
};
return Object.assign(Component, CopilotChatView_default);
}, [
clickOutsideToClose,
header,
toggleButton,
height,
width,
defaultOpen
]);
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChat, {
welcomeScreen: CopilotPopupView_default.WelcomeScreen,
...chatProps,
chatView: PopupViewOverride
});
}
CopilotPopup.displayName = "CopilotPopup";
//#endregion
//#region src/components/WildcardToolCallRender.tsx
const WildcardToolCallRender = defineToolCallRenderer({
name: "*",
render: ({ args, result, name, status }) => {
const [isExpanded, setIsExpanded] = (0, react.useState)(false);
const statusString = String(status);
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:mt-2 cpk:pb-2",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
className: "cpk:rounded-xl cpk:border cpk:border-zinc-200/60 cpk:dark:border-zinc-800/60 cpk:bg-white/70 cpk:dark:bg-zinc-900/50 cpk:shadow-sm cpk:backdrop-blur cpk:p-4",
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
className: "cpk:flex cpk:items-center cpk:justify-between cpk:gap-3 cpk:cursor-pointer",
onClick: () => setIsExpanded(!isExpanded),
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
className: "cpk:flex cpk:items-center cpk:gap-2 cpk:min-w-0",
children: [
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
className: `cpk:h-4 cpk:w-4 cpk:text-zinc-500 cpk:dark:text-zinc-400 cpk:transition-transform ${isExpanded ? "cpk:rotate-90" : ""}`,
fill: "none",
viewBox: "0 0 24 24",
strokeWidth: 2,
stroke: "currentColor",
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
strokeLinecap: "round",
strokeLinejoin: "round",
d: "M8.25 4.5l7.5 7.5-7.5 7.5"
})
}),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: "cpk:inline-block cpk:h-2 cpk:w-2 cpk:rounded-full cpk:bg-blue-500" }),
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
className: "cpk:truncate cpk:text-sm cpk:font-medium cpk:text-zinc-900 cpk:dark:text-zinc-100",
children: name
})
]
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
className: `cpk:inline-flex cpk:items-center cpk:rounded-full cpk:px-2 cpk:py-1 cpk:text-xs cpk:font-medium ${statusString === "inProgress" || statusString === "executing" ? "cpk:bg-amber-100 cpk:text-amber-800 cpk:dark:bg-amber-500/15 cpk:dark:text-amber-400" : statusString === "complete" ? "cpk:bg-emerald-100 cpk:text-emerald-800 cpk:dark:bg-emerald-500/15 cpk:dark:text-emerald-400" : "cpk:bg-zinc-100 cpk:text-zinc-800 cpk:dark:bg-zinc-700/40 cpk:dark:text-zinc-300"}`,
children: String(status)
})]
}), isExpanded && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
className: "cpk:mt-3 cpk:grid cpk:gap-4",
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:text-xs cpk:uppercase cpk:tracking-wide cpk:text-zinc-500 cpk:dark:text-zinc-400",
children: "Arguments"
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
className: "cpk:mt-2 cpk:max-h-64 cpk:overflow-auto cpk:rounded-md cpk:bg-zinc-50 cpk:dark:bg-zinc-800/60 cpk:p-3 cpk:text-xs cpk:leading-relaxed cpk:text-zinc-800 cpk:dark:text-zinc-200 cpk:whitespace-pre-wrap cpk:break-words",
children: JSON.stringify(args !== null && args !== void 0 ? args : {}, null, 2)
})] }), result !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
className: "cpk:text-xs cpk:uppercase cpk:tracking-wide cpk:text-zinc-500 cpk:dark:text-zinc-400",
children: "Result"
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
className: "cpk:mt-2 cpk:max-h-64 cpk:overflow-auto cpk:rounded-md cpk:bg-zinc-50 cpk:dark:bg-zinc-800/60 cpk:p-3 cpk:text-xs cpk:leading-relaxed cpk:text-zinc-800 cpk:dark:text-zinc-200 cpk:whitespace-pre-wrap cpk:break-words",
children: typeof result === "string" ? result : JSON.stringify(result, null, 2)
})] })]
})]
})
});
}
});
//#endregion
exports.AudioRecorderError = AudioRecorderError;
Object.defineProperty(exports, 'CopilotChat', {
enumerable: true,
get: function () {
return CopilotChat;
}
});
exports.CopilotChatAssistantMessage = CopilotChatAssistantMessage_default;
exports.CopilotChatAudioRecorder = CopilotChatAudioRecorder;
exports.CopilotChatConfigurationProvider = CopilotChatConfigurationProvider;
exports.CopilotChatInput = CopilotChatInput_default;
exports.CopilotChatMessageView = CopilotChatMessageView;
exports.CopilotChatReasoningMessage = CopilotChatReasoningMessage_default;
exports.CopilotChatSuggestionPill = CopilotChatSuggestionPill;
exports.CopilotChatSuggestionView = CopilotChatSuggestionView;
exports.CopilotChatToggleButton = CopilotChatToggleButton;
exports.CopilotChatToggleButtonCloseIcon = DefaultCloseIcon;
exports.CopilotChatToggleButtonOpenIcon = DefaultOpenIcon;
exports.CopilotChatToolCallsView = CopilotChatToolCallsView;
exports.CopilotChatUserMessage = CopilotChatUserMessage_default;
exports.CopilotChatView = CopilotChatView_default;
exports.CopilotKitCoreReact = CopilotKitCoreReact;
exports.CopilotKitInspector = CopilotKitInspector;
exports.CopilotKitProvider = CopilotKitProvider;
Object.defineProperty(exports, 'CopilotModalHeader', {
enumerable: true,
get: function () {
return CopilotModalHeader;
}
});
exports.CopilotPopup = CopilotPopup;
Object.defineProperty(exports, 'CopilotPopupView', {
enumerable: true,
get: function () {
return CopilotPopupView;
}
});
exports.CopilotSidebar = CopilotSidebar;
Object.defineProperty(exports, 'CopilotSidebarView', {
enumerable: true,
get: function () {
return CopilotSidebarView;
}
});
exports.MCPAppsActivityContentSchema = MCPAppsActivityContentSchema;
exports.MCPAppsActivityRenderer = MCPAppsActivityRenderer;
exports.MCPAppsActivityType = MCPAppsActivityType;
exports.UseAgentUpdate = UseAgentUpdate;
exports.WildcardToolCallRender = WildcardToolCallRender;
exports.createA2UIMessageRenderer = createA2UIMessageRenderer;
exports.defineToolCallRenderer = defineToolCallRenderer;
exports.useAgent = useAgent;
exports.useAgentContext = useAgentContext;
exports.useComponent = useComponent;
exports.useConfigureSuggestions = useConfigureSuggestions;
exports.useCopilotChatConfiguration = useCopilotChatConfiguration;
exports.useCopilotKit = useCopilotKit;
exports.useDefaultRenderTool = useDefaultRenderTool;
exports.useFrontendTool = useFrontendTool;
exports.useHumanInTheLoop = useHumanInTheLoop;
exports.useInterrupt = useInterrupt;
exports.useRenderActivityMessage = useRenderActivityMessage;
exports.useRenderCustomMessages = useRenderCustomMessages;
exports.useRenderTool = useRenderTool;
exports.useRenderToolCall = useRenderToolCall;
exports.useSuggestions = useSuggestions;
Object.keys(_ag_ui_client).forEach(function (k) {
if (k !== 'default' && !Object.prototype.hasOwnProperty.call(exports, k)) Object.defineProperty(exports, k, {
enumerable: true,
get: function () { return _ag_ui_client[k]; }
});
});
});
//# sourceMappingURL=index.umd.js.map