@copilotkitnext/react 1.53.1-next.1 → 1.54.0-next.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/a2ui/A2UIMessageRenderer.cjs +132 -0
- package/dist/a2ui/A2UIMessageRenderer.cjs.map +1 -0
- package/dist/a2ui/A2UIMessageRenderer.d.cts +11 -0
- package/dist/a2ui/A2UIMessageRenderer.d.cts.map +1 -0
- package/dist/a2ui/A2UIMessageRenderer.d.mts +11 -0
- package/dist/a2ui/A2UIMessageRenderer.d.mts.map +1 -0
- package/dist/a2ui/A2UIMessageRenderer.mjs +131 -0
- package/dist/a2ui/A2UIMessageRenderer.mjs.map +1 -0
- package/dist/components/chat/CopilotChatAssistantMessage.cjs +2 -1
- package/dist/components/chat/CopilotChatAssistantMessage.cjs.map +1 -1
- package/dist/components/chat/CopilotChatAssistantMessage.d.cts.map +1 -1
- package/dist/components/chat/CopilotChatAssistantMessage.d.mts +0 -1
- package/dist/components/chat/CopilotChatAssistantMessage.d.mts.map +1 -1
- package/dist/components/chat/CopilotChatAssistantMessage.mjs +2 -1
- package/dist/components/chat/CopilotChatAssistantMessage.mjs.map +1 -1
- package/dist/hooks/use-component.cjs +4 -4
- package/dist/hooks/use-component.cjs.map +1 -1
- package/dist/hooks/use-component.d.cts +7 -7
- package/dist/hooks/use-component.d.cts.map +1 -1
- package/dist/hooks/use-component.d.mts +7 -7
- package/dist/hooks/use-component.d.mts.map +1 -1
- package/dist/hooks/use-component.mjs +4 -4
- package/dist/hooks/use-component.mjs.map +1 -1
- package/dist/hooks/use-render-activity-message.cjs +1 -1
- package/dist/hooks/use-render-activity-message.mjs +1 -1
- package/dist/hooks/use-render-custom-messages.cjs +1 -1
- package/dist/hooks/use-render-custom-messages.mjs +1 -1
- package/dist/hooks/use-render-tool.cjs +1 -1
- package/dist/hooks/use-render-tool.cjs.map +1 -1
- package/dist/hooks/use-render-tool.d.cts +13 -12
- package/dist/hooks/use-render-tool.d.cts.map +1 -1
- package/dist/hooks/use-render-tool.d.mts +13 -12
- package/dist/hooks/use-render-tool.d.mts.map +1 -1
- package/dist/hooks/use-render-tool.mjs +1 -1
- package/dist/hooks/use-render-tool.mjs.map +1 -1
- package/dist/hooks/useKatexStyles.cjs +24 -0
- package/dist/hooks/useKatexStyles.cjs.map +1 -0
- package/dist/hooks/useKatexStyles.mjs +23 -0
- package/dist/hooks/useKatexStyles.mjs.map +1 -0
- package/dist/index.cjs +3 -1
- package/dist/index.d.cts +3 -1
- package/dist/index.d.mts +3 -1
- package/dist/index.mjs +3 -2
- package/dist/index.umd.js +175 -15
- package/dist/index.umd.js.map +1 -1
- package/dist/providers/CopilotKitProvider.cjs +21 -6
- package/dist/providers/CopilotKitProvider.cjs.map +1 -1
- package/dist/providers/CopilotKitProvider.d.cts +21 -0
- package/dist/providers/CopilotKitProvider.d.cts.map +1 -1
- package/dist/providers/CopilotKitProvider.d.mts +21 -0
- package/dist/providers/CopilotKitProvider.d.mts.map +1 -1
- package/dist/providers/CopilotKitProvider.mjs +21 -6
- package/dist/providers/CopilotKitProvider.mjs.map +1 -1
- package/dist/types/defineToolCallRenderer.cjs.map +1 -1
- package/dist/types/defineToolCallRenderer.d.cts +5 -5
- package/dist/types/defineToolCallRenderer.d.cts.map +1 -1
- package/dist/types/defineToolCallRenderer.d.mts +5 -5
- package/dist/types/defineToolCallRenderer.d.mts.map +1 -1
- package/dist/types/defineToolCallRenderer.mjs.map +1 -1
- package/dist/types/react-activity-message-renderer.d.cts +2 -2
- package/dist/types/react-activity-message-renderer.d.cts.map +1 -1
- package/dist/types/react-activity-message-renderer.d.mts +2 -2
- package/dist/types/react-activity-message-renderer.d.mts.map +1 -1
- package/dist/types/react-tool-call-renderer.d.cts +2 -2
- package/dist/types/react-tool-call-renderer.d.cts.map +1 -1
- package/dist/types/react-tool-call-renderer.d.mts +2 -2
- package/dist/types/react-tool-call-renderer.d.mts.map +1 -1
- package/package.json +10 -7
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
|
|
2
|
+
require('../providers/index.cjs');
|
|
3
|
+
const require_CopilotKitProvider = require('../providers/CopilotKitProvider.cjs');
|
|
4
|
+
let react = require("react");
|
|
5
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
6
|
+
let zod = require("zod");
|
|
7
|
+
let _copilotkit_a2ui_renderer = require("@copilotkit/a2ui-renderer");
|
|
8
|
+
|
|
9
|
+
//#region src/a2ui/A2UIMessageRenderer.tsx
|
|
10
|
+
let initialized = false;
|
|
11
|
+
function ensureInitialized() {
|
|
12
|
+
if (!initialized) {
|
|
13
|
+
(0, _copilotkit_a2ui_renderer.initializeDefaultCatalog)();
|
|
14
|
+
(0, _copilotkit_a2ui_renderer.injectStyles)();
|
|
15
|
+
initialized = true;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function createA2UIMessageRenderer(options) {
|
|
19
|
+
const { theme } = options;
|
|
20
|
+
return {
|
|
21
|
+
activityType: "a2ui-surface",
|
|
22
|
+
content: zod.z.any(),
|
|
23
|
+
render: ({ content, agent }) => {
|
|
24
|
+
ensureInitialized();
|
|
25
|
+
const [operations, setOperations] = (0, react.useState)([]);
|
|
26
|
+
const lastSignatureRef = (0, react.useRef)(null);
|
|
27
|
+
const { copilotkit } = require_CopilotKitProvider.useCopilotKit();
|
|
28
|
+
(0, react.useEffect)(() => {
|
|
29
|
+
if (!content || !Array.isArray(content.operations)) {
|
|
30
|
+
lastSignatureRef.current = null;
|
|
31
|
+
setOperations([]);
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const incoming = content.operations;
|
|
35
|
+
const signature = stringifyOperations(incoming);
|
|
36
|
+
if (signature && signature === lastSignatureRef.current) return;
|
|
37
|
+
lastSignatureRef.current = signature;
|
|
38
|
+
setOperations(incoming);
|
|
39
|
+
}, [content]);
|
|
40
|
+
const groupedOperations = (0, react.useMemo)(() => {
|
|
41
|
+
const groups = /* @__PURE__ */ new Map();
|
|
42
|
+
for (const operation of operations) {
|
|
43
|
+
const surfaceId = getOperationSurfaceId(operation) ?? _copilotkit_a2ui_renderer.DEFAULT_SURFACE_ID;
|
|
44
|
+
if (!groups.has(surfaceId)) groups.set(surfaceId, []);
|
|
45
|
+
groups.get(surfaceId).push(operation);
|
|
46
|
+
}
|
|
47
|
+
return groups;
|
|
48
|
+
}, [operations]);
|
|
49
|
+
if (!groupedOperations.size) return null;
|
|
50
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
51
|
+
className: "cpk:flex cpk:min-h-0 cpk:flex-1 cpk:flex-col cpk:gap-6 cpk:overflow-auto cpk:py-6",
|
|
52
|
+
children: Array.from(groupedOperations.entries()).map(([surfaceId, ops]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReactSurfaceHost, {
|
|
53
|
+
surfaceId,
|
|
54
|
+
operations: ops,
|
|
55
|
+
theme,
|
|
56
|
+
agent,
|
|
57
|
+
copilotkit
|
|
58
|
+
}, surfaceId))
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Renders a single A2UI surface using the React renderer.
|
|
65
|
+
* Wraps A2UIProvider + A2UIRenderer and bridges actions back to CopilotKit.
|
|
66
|
+
*/
|
|
67
|
+
function ReactSurfaceHost({ surfaceId, operations, theme, agent, copilotkit }) {
|
|
68
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
69
|
+
className: "cpk:flex cpk:w-full cpk:flex-none cpk:overflow-hidden cpk:rounded-lg cpk:bg-white/5 cpk:p-4",
|
|
70
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_copilotkit_a2ui_renderer.A2UIProvider, {
|
|
71
|
+
onAction: (0, react.useCallback)(async (message) => {
|
|
72
|
+
if (!agent) return;
|
|
73
|
+
try {
|
|
74
|
+
console.info("[A2UI] Action dispatched", message.userAction);
|
|
75
|
+
copilotkit.setProperties({
|
|
76
|
+
...copilotkit.properties ?? {},
|
|
77
|
+
a2uiAction: message
|
|
78
|
+
});
|
|
79
|
+
await copilotkit.runAgent({ agent });
|
|
80
|
+
} finally {
|
|
81
|
+
if (copilotkit.properties) {
|
|
82
|
+
const { a2uiAction, ...rest } = copilotkit.properties;
|
|
83
|
+
copilotkit.setProperties(rest);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}, [agent, copilotkit]),
|
|
87
|
+
theme,
|
|
88
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SurfaceMessageProcessor, {
|
|
89
|
+
surfaceId,
|
|
90
|
+
operations
|
|
91
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_copilotkit_a2ui_renderer.A2UIRenderer, {
|
|
92
|
+
surfaceId,
|
|
93
|
+
className: "cpk:flex cpk:flex-1"
|
|
94
|
+
})]
|
|
95
|
+
})
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Processes A2UI operations into the provider's message processor.
|
|
100
|
+
* Must be a child of A2UIProvider to access the actions context.
|
|
101
|
+
*/
|
|
102
|
+
function SurfaceMessageProcessor({ surfaceId, operations }) {
|
|
103
|
+
const { processMessages } = (0, _copilotkit_a2ui_renderer.useA2UIActions)();
|
|
104
|
+
const lastProcessedRef = (0, react.useRef)("");
|
|
105
|
+
(0, react.useEffect)(() => {
|
|
106
|
+
const key = `${surfaceId}-${JSON.stringify(operations)}`;
|
|
107
|
+
if (key === lastProcessedRef.current) return;
|
|
108
|
+
lastProcessedRef.current = key;
|
|
109
|
+
processMessages(operations);
|
|
110
|
+
}, [
|
|
111
|
+
processMessages,
|
|
112
|
+
surfaceId,
|
|
113
|
+
operations
|
|
114
|
+
]);
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
function getOperationSurfaceId(operation) {
|
|
118
|
+
if (!operation || typeof operation !== "object") return null;
|
|
119
|
+
if (typeof operation.surfaceId === "string") return operation.surfaceId;
|
|
120
|
+
return operation?.beginRendering?.surfaceId ?? operation?.surfaceUpdate?.surfaceId ?? operation?.dataModelUpdate?.surfaceId ?? operation?.deleteSurface?.surfaceId ?? null;
|
|
121
|
+
}
|
|
122
|
+
function stringifyOperations(ops) {
|
|
123
|
+
try {
|
|
124
|
+
return JSON.stringify(ops);
|
|
125
|
+
} catch (error) {
|
|
126
|
+
return null;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
//#endregion
|
|
131
|
+
exports.createA2UIMessageRenderer = createA2UIMessageRenderer;
|
|
132
|
+
//# sourceMappingURL=A2UIMessageRenderer.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"A2UIMessageRenderer.cjs","names":["z","useCopilotKit","DEFAULT_SURFACE_ID","A2UIProvider","A2UIRenderer"],"sources":["../../src/a2ui/A2UIMessageRenderer.tsx"],"sourcesContent":["import { useCopilotKit } from \"../providers\";\nimport type { ReactActivityMessageRenderer } from \"../types/react-activity-message-renderer\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { z } from \"zod\";\nimport {\n A2UIProvider,\n useA2UIActions,\n A2UIRenderer,\n initializeDefaultCatalog,\n injectStyles,\n DEFAULT_SURFACE_ID,\n} from \"@copilotkit/a2ui-renderer\";\nimport type { Theme, A2UIClientEventMessage } from \"@copilotkit/a2ui-renderer\";\n\n// Initialize the React renderer's component catalog and styles once\nlet initialized = false;\nfunction ensureInitialized() {\n if (!initialized) {\n initializeDefaultCatalog();\n injectStyles();\n initialized = true;\n }\n}\n\nexport type A2UIMessageRendererOptions = {\n theme: Theme;\n};\n\nexport function createA2UIMessageRenderer(\n options: A2UIMessageRendererOptions,\n): ReactActivityMessageRenderer<any> {\n const { theme } = options;\n\n return {\n activityType: \"a2ui-surface\",\n content: z.any(),\n render: ({ content, agent }) => {\n ensureInitialized();\n\n const [operations, setOperations] = useState<any[]>([]);\n const lastSignatureRef = useRef<string | null>(null);\n const { copilotkit } = useCopilotKit();\n\n useEffect(() => {\n if (!content || !Array.isArray(content.operations)) {\n lastSignatureRef.current = null;\n setOperations([]);\n return;\n }\n\n const incoming = content.operations as any[];\n const signature = stringifyOperations(incoming);\n\n if (signature && signature === lastSignatureRef.current) {\n return;\n }\n\n lastSignatureRef.current = signature;\n setOperations(incoming);\n }, [content]);\n\n // Group operations by surface ID\n const groupedOperations = useMemo(() => {\n const groups = new Map<string, any[]>();\n\n for (const operation of operations) {\n const surfaceId =\n getOperationSurfaceId(operation) ?? DEFAULT_SURFACE_ID;\n\n if (!groups.has(surfaceId)) {\n groups.set(surfaceId, []);\n }\n groups.get(surfaceId)!.push(operation);\n }\n\n return groups;\n }, [operations]);\n\n if (!groupedOperations.size) {\n return null;\n }\n\n return (\n <div className=\"cpk:flex cpk:min-h-0 cpk:flex-1 cpk:flex-col cpk:gap-6 cpk:overflow-auto cpk:py-6\">\n {Array.from(groupedOperations.entries()).map(([surfaceId, ops]) => (\n <ReactSurfaceHost\n key={surfaceId}\n surfaceId={surfaceId}\n operations={ops}\n theme={theme}\n agent={agent}\n copilotkit={copilotkit}\n />\n ))}\n </div>\n );\n },\n };\n}\n\ntype ReactSurfaceHostProps = {\n surfaceId: string;\n operations: any[];\n theme: Theme;\n agent: any;\n copilotkit: any;\n};\n\n/**\n * Renders a single A2UI surface using the React renderer.\n * Wraps A2UIProvider + A2UIRenderer and bridges actions back to CopilotKit.\n */\nfunction ReactSurfaceHost({\n surfaceId,\n operations,\n theme,\n agent,\n copilotkit,\n}: ReactSurfaceHostProps) {\n // Bridge: when the React renderer dispatches an action, send it to CopilotKit\n const handleAction = useCallback(\n async (message: A2UIClientEventMessage) => {\n if (!agent) return;\n\n try {\n console.info(\"[A2UI] Action dispatched\", message.userAction);\n\n copilotkit.setProperties({\n ...(copilotkit.properties ?? {}),\n a2uiAction: message,\n });\n\n await copilotkit.runAgent({ agent });\n } finally {\n if (copilotkit.properties) {\n const { a2uiAction, ...rest } = copilotkit.properties;\n copilotkit.setProperties(rest);\n }\n }\n },\n [agent, copilotkit],\n );\n\n return (\n <div className=\"cpk:flex cpk:w-full cpk:flex-none cpk:overflow-hidden cpk:rounded-lg cpk:bg-white/5 cpk:p-4\">\n <A2UIProvider onAction={handleAction} theme={theme}>\n <SurfaceMessageProcessor\n surfaceId={surfaceId}\n operations={operations}\n />\n <A2UIRenderer surfaceId={surfaceId} className=\"cpk:flex cpk:flex-1\" />\n </A2UIProvider>\n </div>\n );\n}\n\n/**\n * Processes A2UI operations into the provider's message processor.\n * Must be a child of A2UIProvider to access the actions context.\n */\nfunction SurfaceMessageProcessor({\n surfaceId,\n operations,\n}: {\n surfaceId: string;\n operations: any[];\n}) {\n const { processMessages } = useA2UIActions();\n const lastProcessedRef = useRef<string>(\"\");\n\n useEffect(() => {\n const key = `${surfaceId}-${JSON.stringify(operations)}`;\n if (key === lastProcessedRef.current) return;\n lastProcessedRef.current = key;\n\n processMessages(operations);\n }, [processMessages, surfaceId, operations]);\n\n return null;\n}\n\nfunction getOperationSurfaceId(operation: any): string | null {\n if (!operation || typeof operation !== \"object\") {\n return null;\n }\n\n if (typeof operation.surfaceId === \"string\") {\n return operation.surfaceId;\n }\n\n return (\n operation?.beginRendering?.surfaceId ??\n operation?.surfaceUpdate?.surfaceId ??\n operation?.dataModelUpdate?.surfaceId ??\n operation?.deleteSurface?.surfaceId ??\n null\n );\n}\n\nfunction stringifyOperations(ops: any[]): string | null {\n try {\n return JSON.stringify(ops);\n } catch (error) {\n return null;\n }\n}\n"],"mappings":";;;;;;;;;AAeA,IAAI,cAAc;AAClB,SAAS,oBAAoB;AAC3B,KAAI,CAAC,aAAa;AAChB,2DAA0B;AAC1B,+CAAc;AACd,gBAAc;;;AAQlB,SAAgB,0BACd,SACmC;CACnC,MAAM,EAAE,UAAU;AAElB,QAAO;EACL,cAAc;EACd,SAASA,MAAE,KAAK;EAChB,SAAS,EAAE,SAAS,YAAY;AAC9B,sBAAmB;GAEnB,MAAM,CAAC,YAAY,qCAAiC,EAAE,CAAC;GACvD,MAAM,qCAAyC,KAAK;GACpD,MAAM,EAAE,eAAeC,0CAAe;AAEtC,8BAAgB;AACd,QAAI,CAAC,WAAW,CAAC,MAAM,QAAQ,QAAQ,WAAW,EAAE;AAClD,sBAAiB,UAAU;AAC3B,mBAAc,EAAE,CAAC;AACjB;;IAGF,MAAM,WAAW,QAAQ;IACzB,MAAM,YAAY,oBAAoB,SAAS;AAE/C,QAAI,aAAa,cAAc,iBAAiB,QAC9C;AAGF,qBAAiB,UAAU;AAC3B,kBAAc,SAAS;MACtB,CAAC,QAAQ,CAAC;GAGb,MAAM,6CAAkC;IACtC,MAAM,yBAAS,IAAI,KAAoB;AAEvC,SAAK,MAAM,aAAa,YAAY;KAClC,MAAM,YACJ,sBAAsB,UAAU,IAAIC;AAEtC,SAAI,CAAC,OAAO,IAAI,UAAU,CACxB,QAAO,IAAI,WAAW,EAAE,CAAC;AAE3B,YAAO,IAAI,UAAU,CAAE,KAAK,UAAU;;AAGxC,WAAO;MACN,CAAC,WAAW,CAAC;AAEhB,OAAI,CAAC,kBAAkB,KACrB,QAAO;AAGT,UACE,2CAAC;IAAI,WAAU;cACZ,MAAM,KAAK,kBAAkB,SAAS,CAAC,CAAC,KAAK,CAAC,WAAW,SACxD,2CAAC;KAEY;KACX,YAAY;KACL;KACA;KACK;OALP,UAML,CACF;KACE;;EAGX;;;;;;AAeH,SAAS,iBAAiB,EACxB,WACA,YACA,OACA,OACA,cACwB;AAyBxB,QACE,2CAAC;EAAI,WAAU;YACb,4CAACC;GAAa,iCAxBhB,OAAO,YAAoC;AACzC,QAAI,CAAC,MAAO;AAEZ,QAAI;AACF,aAAQ,KAAK,4BAA4B,QAAQ,WAAW;AAE5D,gBAAW,cAAc;MACvB,GAAI,WAAW,cAAc,EAAE;MAC/B,YAAY;MACb,CAAC;AAEF,WAAM,WAAW,SAAS,EAAE,OAAO,CAAC;cAC5B;AACR,SAAI,WAAW,YAAY;MACzB,MAAM,EAAE,YAAY,GAAG,SAAS,WAAW;AAC3C,iBAAW,cAAc,KAAK;;;MAIpC,CAAC,OAAO,WAAW,CACpB;GAIgD;cAC3C,2CAAC;IACY;IACC;KACZ,EACF,2CAACC;IAAwB;IAAW,WAAU;KAAwB;IACzD;GACX;;;;;;AAQV,SAAS,wBAAwB,EAC/B,WACA,cAIC;CACD,MAAM,EAAE,mEAAoC;CAC5C,MAAM,qCAAkC,GAAG;AAE3C,4BAAgB;EACd,MAAM,MAAM,GAAG,UAAU,GAAG,KAAK,UAAU,WAAW;AACtD,MAAI,QAAQ,iBAAiB,QAAS;AACtC,mBAAiB,UAAU;AAE3B,kBAAgB,WAAW;IAC1B;EAAC;EAAiB;EAAW;EAAW,CAAC;AAE5C,QAAO;;AAGT,SAAS,sBAAsB,WAA+B;AAC5D,KAAI,CAAC,aAAa,OAAO,cAAc,SACrC,QAAO;AAGT,KAAI,OAAO,UAAU,cAAc,SACjC,QAAO,UAAU;AAGnB,QACE,WAAW,gBAAgB,aAC3B,WAAW,eAAe,aAC1B,WAAW,iBAAiB,aAC5B,WAAW,eAAe,aAC1B;;AAIJ,SAAS,oBAAoB,KAA2B;AACtD,KAAI;AACF,SAAO,KAAK,UAAU,IAAI;UACnB,OAAO;AACd,SAAO"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ReactActivityMessageRenderer } from "../types/react-activity-message-renderer.cjs";
|
|
2
|
+
import { Theme } from "@copilotkit/a2ui-renderer";
|
|
3
|
+
|
|
4
|
+
//#region src/a2ui/A2UIMessageRenderer.d.ts
|
|
5
|
+
type A2UIMessageRendererOptions = {
|
|
6
|
+
theme: Theme;
|
|
7
|
+
};
|
|
8
|
+
declare function createA2UIMessageRenderer(options: A2UIMessageRendererOptions): ReactActivityMessageRenderer<any>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { A2UIMessageRendererOptions, createA2UIMessageRenderer };
|
|
11
|
+
//# sourceMappingURL=A2UIMessageRenderer.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"A2UIMessageRenderer.d.cts","names":[],"sources":["../../src/a2ui/A2UIMessageRenderer.tsx"],"mappings":";;;;KAwBY,0BAAA;EACV,KAAA,EAAO,KAAA;AAAA;AAAA,iBAGO,yBAAA,CACd,OAAA,EAAS,0BAAA,GACR,4BAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ReactActivityMessageRenderer } from "../types/react-activity-message-renderer.mjs";
|
|
2
|
+
import { Theme } from "@copilotkit/a2ui-renderer";
|
|
3
|
+
|
|
4
|
+
//#region src/a2ui/A2UIMessageRenderer.d.ts
|
|
5
|
+
type A2UIMessageRendererOptions = {
|
|
6
|
+
theme: Theme;
|
|
7
|
+
};
|
|
8
|
+
declare function createA2UIMessageRenderer(options: A2UIMessageRendererOptions): ReactActivityMessageRenderer<any>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { A2UIMessageRendererOptions, createA2UIMessageRenderer };
|
|
11
|
+
//# sourceMappingURL=A2UIMessageRenderer.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"A2UIMessageRenderer.d.mts","names":[],"sources":["../../src/a2ui/A2UIMessageRenderer.tsx"],"mappings":";;;;KAwBY,0BAAA;EACV,KAAA,EAAO,KAAA;AAAA;AAAA,iBAGO,yBAAA,CACd,OAAA,EAAS,0BAAA,GACR,4BAAA"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import "../providers/index.mjs";
|
|
2
|
+
import { useCopilotKit } from "../providers/CopilotKitProvider.mjs";
|
|
3
|
+
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { A2UIProvider, A2UIRenderer, DEFAULT_SURFACE_ID, initializeDefaultCatalog, injectStyles, useA2UIActions } from "@copilotkit/a2ui-renderer";
|
|
7
|
+
|
|
8
|
+
//#region src/a2ui/A2UIMessageRenderer.tsx
|
|
9
|
+
let initialized = false;
|
|
10
|
+
function ensureInitialized() {
|
|
11
|
+
if (!initialized) {
|
|
12
|
+
initializeDefaultCatalog();
|
|
13
|
+
injectStyles();
|
|
14
|
+
initialized = true;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function createA2UIMessageRenderer(options) {
|
|
18
|
+
const { theme } = options;
|
|
19
|
+
return {
|
|
20
|
+
activityType: "a2ui-surface",
|
|
21
|
+
content: z.any(),
|
|
22
|
+
render: ({ content, agent }) => {
|
|
23
|
+
ensureInitialized();
|
|
24
|
+
const [operations, setOperations] = useState([]);
|
|
25
|
+
const lastSignatureRef = useRef(null);
|
|
26
|
+
const { copilotkit } = useCopilotKit();
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (!content || !Array.isArray(content.operations)) {
|
|
29
|
+
lastSignatureRef.current = null;
|
|
30
|
+
setOperations([]);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const incoming = content.operations;
|
|
34
|
+
const signature = stringifyOperations(incoming);
|
|
35
|
+
if (signature && signature === lastSignatureRef.current) return;
|
|
36
|
+
lastSignatureRef.current = signature;
|
|
37
|
+
setOperations(incoming);
|
|
38
|
+
}, [content]);
|
|
39
|
+
const groupedOperations = useMemo(() => {
|
|
40
|
+
const groups = /* @__PURE__ */ new Map();
|
|
41
|
+
for (const operation of operations) {
|
|
42
|
+
const surfaceId = getOperationSurfaceId(operation) ?? DEFAULT_SURFACE_ID;
|
|
43
|
+
if (!groups.has(surfaceId)) groups.set(surfaceId, []);
|
|
44
|
+
groups.get(surfaceId).push(operation);
|
|
45
|
+
}
|
|
46
|
+
return groups;
|
|
47
|
+
}, [operations]);
|
|
48
|
+
if (!groupedOperations.size) return null;
|
|
49
|
+
return /* @__PURE__ */ jsx("div", {
|
|
50
|
+
className: "cpk:flex cpk:min-h-0 cpk:flex-1 cpk:flex-col cpk:gap-6 cpk:overflow-auto cpk:py-6",
|
|
51
|
+
children: Array.from(groupedOperations.entries()).map(([surfaceId, ops]) => /* @__PURE__ */ jsx(ReactSurfaceHost, {
|
|
52
|
+
surfaceId,
|
|
53
|
+
operations: ops,
|
|
54
|
+
theme,
|
|
55
|
+
agent,
|
|
56
|
+
copilotkit
|
|
57
|
+
}, surfaceId))
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Renders a single A2UI surface using the React renderer.
|
|
64
|
+
* Wraps A2UIProvider + A2UIRenderer and bridges actions back to CopilotKit.
|
|
65
|
+
*/
|
|
66
|
+
function ReactSurfaceHost({ surfaceId, operations, theme, agent, copilotkit }) {
|
|
67
|
+
return /* @__PURE__ */ jsx("div", {
|
|
68
|
+
className: "cpk:flex cpk:w-full cpk:flex-none cpk:overflow-hidden cpk:rounded-lg cpk:bg-white/5 cpk:p-4",
|
|
69
|
+
children: /* @__PURE__ */ jsxs(A2UIProvider, {
|
|
70
|
+
onAction: useCallback(async (message) => {
|
|
71
|
+
if (!agent) return;
|
|
72
|
+
try {
|
|
73
|
+
console.info("[A2UI] Action dispatched", message.userAction);
|
|
74
|
+
copilotkit.setProperties({
|
|
75
|
+
...copilotkit.properties ?? {},
|
|
76
|
+
a2uiAction: message
|
|
77
|
+
});
|
|
78
|
+
await copilotkit.runAgent({ agent });
|
|
79
|
+
} finally {
|
|
80
|
+
if (copilotkit.properties) {
|
|
81
|
+
const { a2uiAction, ...rest } = copilotkit.properties;
|
|
82
|
+
copilotkit.setProperties(rest);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}, [agent, copilotkit]),
|
|
86
|
+
theme,
|
|
87
|
+
children: [/* @__PURE__ */ jsx(SurfaceMessageProcessor, {
|
|
88
|
+
surfaceId,
|
|
89
|
+
operations
|
|
90
|
+
}), /* @__PURE__ */ jsx(A2UIRenderer, {
|
|
91
|
+
surfaceId,
|
|
92
|
+
className: "cpk:flex cpk:flex-1"
|
|
93
|
+
})]
|
|
94
|
+
})
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Processes A2UI operations into the provider's message processor.
|
|
99
|
+
* Must be a child of A2UIProvider to access the actions context.
|
|
100
|
+
*/
|
|
101
|
+
function SurfaceMessageProcessor({ surfaceId, operations }) {
|
|
102
|
+
const { processMessages } = useA2UIActions();
|
|
103
|
+
const lastProcessedRef = useRef("");
|
|
104
|
+
useEffect(() => {
|
|
105
|
+
const key = `${surfaceId}-${JSON.stringify(operations)}`;
|
|
106
|
+
if (key === lastProcessedRef.current) return;
|
|
107
|
+
lastProcessedRef.current = key;
|
|
108
|
+
processMessages(operations);
|
|
109
|
+
}, [
|
|
110
|
+
processMessages,
|
|
111
|
+
surfaceId,
|
|
112
|
+
operations
|
|
113
|
+
]);
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
function getOperationSurfaceId(operation) {
|
|
117
|
+
if (!operation || typeof operation !== "object") return null;
|
|
118
|
+
if (typeof operation.surfaceId === "string") return operation.surfaceId;
|
|
119
|
+
return operation?.beginRendering?.surfaceId ?? operation?.surfaceUpdate?.surfaceId ?? operation?.dataModelUpdate?.surfaceId ?? operation?.deleteSurface?.surfaceId ?? null;
|
|
120
|
+
}
|
|
121
|
+
function stringifyOperations(ops) {
|
|
122
|
+
try {
|
|
123
|
+
return JSON.stringify(ops);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
//#endregion
|
|
130
|
+
export { createA2UIMessageRenderer };
|
|
131
|
+
//# sourceMappingURL=A2UIMessageRenderer.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"A2UIMessageRenderer.mjs","names":[],"sources":["../../src/a2ui/A2UIMessageRenderer.tsx"],"sourcesContent":["import { useCopilotKit } from \"../providers\";\nimport type { ReactActivityMessageRenderer } from \"../types/react-activity-message-renderer\";\nimport { useCallback, useEffect, useMemo, useRef, useState } from \"react\";\nimport { z } from \"zod\";\nimport {\n A2UIProvider,\n useA2UIActions,\n A2UIRenderer,\n initializeDefaultCatalog,\n injectStyles,\n DEFAULT_SURFACE_ID,\n} from \"@copilotkit/a2ui-renderer\";\nimport type { Theme, A2UIClientEventMessage } from \"@copilotkit/a2ui-renderer\";\n\n// Initialize the React renderer's component catalog and styles once\nlet initialized = false;\nfunction ensureInitialized() {\n if (!initialized) {\n initializeDefaultCatalog();\n injectStyles();\n initialized = true;\n }\n}\n\nexport type A2UIMessageRendererOptions = {\n theme: Theme;\n};\n\nexport function createA2UIMessageRenderer(\n options: A2UIMessageRendererOptions,\n): ReactActivityMessageRenderer<any> {\n const { theme } = options;\n\n return {\n activityType: \"a2ui-surface\",\n content: z.any(),\n render: ({ content, agent }) => {\n ensureInitialized();\n\n const [operations, setOperations] = useState<any[]>([]);\n const lastSignatureRef = useRef<string | null>(null);\n const { copilotkit } = useCopilotKit();\n\n useEffect(() => {\n if (!content || !Array.isArray(content.operations)) {\n lastSignatureRef.current = null;\n setOperations([]);\n return;\n }\n\n const incoming = content.operations as any[];\n const signature = stringifyOperations(incoming);\n\n if (signature && signature === lastSignatureRef.current) {\n return;\n }\n\n lastSignatureRef.current = signature;\n setOperations(incoming);\n }, [content]);\n\n // Group operations by surface ID\n const groupedOperations = useMemo(() => {\n const groups = new Map<string, any[]>();\n\n for (const operation of operations) {\n const surfaceId =\n getOperationSurfaceId(operation) ?? DEFAULT_SURFACE_ID;\n\n if (!groups.has(surfaceId)) {\n groups.set(surfaceId, []);\n }\n groups.get(surfaceId)!.push(operation);\n }\n\n return groups;\n }, [operations]);\n\n if (!groupedOperations.size) {\n return null;\n }\n\n return (\n <div className=\"cpk:flex cpk:min-h-0 cpk:flex-1 cpk:flex-col cpk:gap-6 cpk:overflow-auto cpk:py-6\">\n {Array.from(groupedOperations.entries()).map(([surfaceId, ops]) => (\n <ReactSurfaceHost\n key={surfaceId}\n surfaceId={surfaceId}\n operations={ops}\n theme={theme}\n agent={agent}\n copilotkit={copilotkit}\n />\n ))}\n </div>\n );\n },\n };\n}\n\ntype ReactSurfaceHostProps = {\n surfaceId: string;\n operations: any[];\n theme: Theme;\n agent: any;\n copilotkit: any;\n};\n\n/**\n * Renders a single A2UI surface using the React renderer.\n * Wraps A2UIProvider + A2UIRenderer and bridges actions back to CopilotKit.\n */\nfunction ReactSurfaceHost({\n surfaceId,\n operations,\n theme,\n agent,\n copilotkit,\n}: ReactSurfaceHostProps) {\n // Bridge: when the React renderer dispatches an action, send it to CopilotKit\n const handleAction = useCallback(\n async (message: A2UIClientEventMessage) => {\n if (!agent) return;\n\n try {\n console.info(\"[A2UI] Action dispatched\", message.userAction);\n\n copilotkit.setProperties({\n ...(copilotkit.properties ?? {}),\n a2uiAction: message,\n });\n\n await copilotkit.runAgent({ agent });\n } finally {\n if (copilotkit.properties) {\n const { a2uiAction, ...rest } = copilotkit.properties;\n copilotkit.setProperties(rest);\n }\n }\n },\n [agent, copilotkit],\n );\n\n return (\n <div className=\"cpk:flex cpk:w-full cpk:flex-none cpk:overflow-hidden cpk:rounded-lg cpk:bg-white/5 cpk:p-4\">\n <A2UIProvider onAction={handleAction} theme={theme}>\n <SurfaceMessageProcessor\n surfaceId={surfaceId}\n operations={operations}\n />\n <A2UIRenderer surfaceId={surfaceId} className=\"cpk:flex cpk:flex-1\" />\n </A2UIProvider>\n </div>\n );\n}\n\n/**\n * Processes A2UI operations into the provider's message processor.\n * Must be a child of A2UIProvider to access the actions context.\n */\nfunction SurfaceMessageProcessor({\n surfaceId,\n operations,\n}: {\n surfaceId: string;\n operations: any[];\n}) {\n const { processMessages } = useA2UIActions();\n const lastProcessedRef = useRef<string>(\"\");\n\n useEffect(() => {\n const key = `${surfaceId}-${JSON.stringify(operations)}`;\n if (key === lastProcessedRef.current) return;\n lastProcessedRef.current = key;\n\n processMessages(operations);\n }, [processMessages, surfaceId, operations]);\n\n return null;\n}\n\nfunction getOperationSurfaceId(operation: any): string | null {\n if (!operation || typeof operation !== \"object\") {\n return null;\n }\n\n if (typeof operation.surfaceId === \"string\") {\n return operation.surfaceId;\n }\n\n return (\n operation?.beginRendering?.surfaceId ??\n operation?.surfaceUpdate?.surfaceId ??\n operation?.dataModelUpdate?.surfaceId ??\n operation?.deleteSurface?.surfaceId ??\n null\n );\n}\n\nfunction stringifyOperations(ops: any[]): string | null {\n try {\n return JSON.stringify(ops);\n } catch (error) {\n return null;\n }\n}\n"],"mappings":";;;;;;;;AAeA,IAAI,cAAc;AAClB,SAAS,oBAAoB;AAC3B,KAAI,CAAC,aAAa;AAChB,4BAA0B;AAC1B,gBAAc;AACd,gBAAc;;;AAQlB,SAAgB,0BACd,SACmC;CACnC,MAAM,EAAE,UAAU;AAElB,QAAO;EACL,cAAc;EACd,SAAS,EAAE,KAAK;EAChB,SAAS,EAAE,SAAS,YAAY;AAC9B,sBAAmB;GAEnB,MAAM,CAAC,YAAY,iBAAiB,SAAgB,EAAE,CAAC;GACvD,MAAM,mBAAmB,OAAsB,KAAK;GACpD,MAAM,EAAE,eAAe,eAAe;AAEtC,mBAAgB;AACd,QAAI,CAAC,WAAW,CAAC,MAAM,QAAQ,QAAQ,WAAW,EAAE;AAClD,sBAAiB,UAAU;AAC3B,mBAAc,EAAE,CAAC;AACjB;;IAGF,MAAM,WAAW,QAAQ;IACzB,MAAM,YAAY,oBAAoB,SAAS;AAE/C,QAAI,aAAa,cAAc,iBAAiB,QAC9C;AAGF,qBAAiB,UAAU;AAC3B,kBAAc,SAAS;MACtB,CAAC,QAAQ,CAAC;GAGb,MAAM,oBAAoB,cAAc;IACtC,MAAM,yBAAS,IAAI,KAAoB;AAEvC,SAAK,MAAM,aAAa,YAAY;KAClC,MAAM,YACJ,sBAAsB,UAAU,IAAI;AAEtC,SAAI,CAAC,OAAO,IAAI,UAAU,CACxB,QAAO,IAAI,WAAW,EAAE,CAAC;AAE3B,YAAO,IAAI,UAAU,CAAE,KAAK,UAAU;;AAGxC,WAAO;MACN,CAAC,WAAW,CAAC;AAEhB,OAAI,CAAC,kBAAkB,KACrB,QAAO;AAGT,UACE,oBAAC;IAAI,WAAU;cACZ,MAAM,KAAK,kBAAkB,SAAS,CAAC,CAAC,KAAK,CAAC,WAAW,SACxD,oBAAC;KAEY;KACX,YAAY;KACL;KACA;KACK;OALP,UAML,CACF;KACE;;EAGX;;;;;;AAeH,SAAS,iBAAiB,EACxB,WACA,YACA,OACA,OACA,cACwB;AAyBxB,QACE,oBAAC;EAAI,WAAU;YACb,qBAAC;GAAa,UAzBG,YACnB,OAAO,YAAoC;AACzC,QAAI,CAAC,MAAO;AAEZ,QAAI;AACF,aAAQ,KAAK,4BAA4B,QAAQ,WAAW;AAE5D,gBAAW,cAAc;MACvB,GAAI,WAAW,cAAc,EAAE;MAC/B,YAAY;MACb,CAAC;AAEF,WAAM,WAAW,SAAS,EAAE,OAAO,CAAC;cAC5B;AACR,SAAI,WAAW,YAAY;MACzB,MAAM,EAAE,YAAY,GAAG,SAAS,WAAW;AAC3C,iBAAW,cAAc,KAAK;;;MAIpC,CAAC,OAAO,WAAW,CACpB;GAIgD;cAC3C,oBAAC;IACY;IACC;KACZ,EACF,oBAAC;IAAwB;IAAW,WAAU;KAAwB;IACzD;GACX;;;;;;AAQV,SAAS,wBAAwB,EAC/B,WACA,cAIC;CACD,MAAM,EAAE,oBAAoB,gBAAgB;CAC5C,MAAM,mBAAmB,OAAe,GAAG;AAE3C,iBAAgB;EACd,MAAM,MAAM,GAAG,UAAU,GAAG,KAAK,UAAU,WAAW;AACtD,MAAI,QAAQ,iBAAiB,QAAS;AACtC,mBAAiB,UAAU;AAE3B,kBAAgB,WAAW;IAC1B;EAAC;EAAiB;EAAW;EAAW,CAAC;AAE5C,QAAO;;AAGT,SAAS,sBAAsB,WAA+B;AAC5D,KAAI,CAAC,aAAa,OAAO,cAAc,SACrC,QAAO;AAGT,KAAI,OAAO,UAAU,cAAc,SACjC,QAAO,UAAU;AAGnB,QACE,WAAW,gBAAgB,aAC3B,WAAW,eAAe,aAC1B,WAAW,iBAAiB,aAC5B,WAAW,eAAe,aAC1B;;AAIJ,SAAS,oBAAoB,KAA2B;AACtD,KAAI;AACF,SAAO,KAAK,UAAU,IAAI;UACnB,OAAO;AACd,SAAO"}
|
|
@@ -3,16 +3,17 @@ const require_CopilotChatConfigurationProvider = require('../../providers/Copilo
|
|
|
3
3
|
const require_button = require('../ui/button.cjs');
|
|
4
4
|
const require_tooltip = require('../ui/tooltip.cjs');
|
|
5
5
|
const require_slots = require('../../lib/slots.cjs');
|
|
6
|
+
const require_useKatexStyles = require('../../hooks/useKatexStyles.cjs');
|
|
6
7
|
const require_CopilotChatToolCallsView = require('./CopilotChatToolCallsView.cjs');
|
|
7
8
|
let react = require("react");
|
|
8
9
|
let tailwind_merge = require("tailwind-merge");
|
|
9
10
|
let lucide_react = require("lucide-react");
|
|
10
11
|
let react_jsx_runtime = require("react/jsx-runtime");
|
|
11
|
-
require("katex/dist/katex.min.css");
|
|
12
12
|
let streamdown = require("streamdown");
|
|
13
13
|
|
|
14
14
|
//#region src/components/chat/CopilotChatAssistantMessage.tsx
|
|
15
15
|
function CopilotChatAssistantMessage({ message, messages, isRunning, onThumbsUp, onThumbsDown, onReadAloud, onRegenerate, additionalToolbarItems, toolbarVisible = true, markdownRenderer, toolbar, copyButton, thumbsUpButton, thumbsDownButton, readAloudButton, regenerateButton, toolCallsView, children, className, ...props }) {
|
|
16
|
+
require_useKatexStyles.useKatexStyles();
|
|
16
17
|
const boundMarkdownRenderer = require_slots.renderSlot(markdownRenderer, CopilotChatAssistantMessage.MarkdownRenderer, { content: message.content || "" });
|
|
17
18
|
const boundCopyButton = require_slots.renderSlot(copyButton, CopilotChatAssistantMessage.CopyButton, { onClick: async () => {
|
|
18
19
|
if (message.content) try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotChatAssistantMessage.cjs","names":["renderSlot","CopilotChatToolCallsView","Streamdown","Tooltip","TooltipTrigger","Button","TooltipContent","useCopilotChatConfiguration","CopilotChatDefaultLabels","Check","Copy","ThumbsUp","ThumbsDown","Volume2","RefreshCw"],"sources":["../../../src/components/chat/CopilotChatAssistantMessage.tsx"],"sourcesContent":["import { AssistantMessage, Message } from \"@ag-ui/core\";\nimport { useState } from \"react\";\nimport {\n Copy,\n Check,\n ThumbsUp,\n ThumbsDown,\n Volume2,\n RefreshCw,\n} from \"lucide-react\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport \"katex/dist/katex.min.css\";\nimport { WithSlots, renderSlot } from \"@/lib/slots\";\nimport { Streamdown } from \"streamdown\";\nimport CopilotChatToolCallsView from \"./CopilotChatToolCallsView\";\n\nexport type CopilotChatAssistantMessageProps = WithSlots<\n {\n markdownRenderer: typeof CopilotChatAssistantMessage.MarkdownRenderer;\n toolbar: typeof CopilotChatAssistantMessage.Toolbar;\n copyButton: typeof CopilotChatAssistantMessage.CopyButton;\n thumbsUpButton: typeof CopilotChatAssistantMessage.ThumbsUpButton;\n thumbsDownButton: typeof CopilotChatAssistantMessage.ThumbsDownButton;\n readAloudButton: typeof CopilotChatAssistantMessage.ReadAloudButton;\n regenerateButton: typeof CopilotChatAssistantMessage.RegenerateButton;\n toolCallsView: typeof CopilotChatToolCallsView;\n },\n {\n onThumbsUp?: (message: AssistantMessage) => void;\n onThumbsDown?: (message: AssistantMessage) => void;\n onReadAloud?: (message: AssistantMessage) => void;\n onRegenerate?: (message: AssistantMessage) => void;\n message: AssistantMessage;\n messages?: Message[];\n isRunning?: boolean;\n additionalToolbarItems?: React.ReactNode;\n toolbarVisible?: boolean;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport function CopilotChatAssistantMessage({\n message,\n messages,\n isRunning,\n onThumbsUp,\n onThumbsDown,\n onReadAloud,\n onRegenerate,\n additionalToolbarItems,\n toolbarVisible = true,\n markdownRenderer,\n toolbar,\n copyButton,\n thumbsUpButton,\n thumbsDownButton,\n readAloudButton,\n regenerateButton,\n toolCallsView,\n children,\n className,\n ...props\n}: CopilotChatAssistantMessageProps) {\n const boundMarkdownRenderer = renderSlot(\n markdownRenderer,\n CopilotChatAssistantMessage.MarkdownRenderer,\n {\n content: message.content || \"\",\n },\n );\n\n const boundCopyButton = renderSlot(\n copyButton,\n CopilotChatAssistantMessage.CopyButton,\n {\n onClick: async () => {\n if (message.content) {\n try {\n await navigator.clipboard.writeText(message.content);\n } catch (err) {\n console.error(\"Failed to copy message:\", err);\n }\n }\n },\n },\n );\n\n const boundThumbsUpButton = renderSlot(\n thumbsUpButton,\n CopilotChatAssistantMessage.ThumbsUpButton,\n {\n onClick: onThumbsUp,\n },\n );\n\n const boundThumbsDownButton = renderSlot(\n thumbsDownButton,\n CopilotChatAssistantMessage.ThumbsDownButton,\n {\n onClick: onThumbsDown,\n },\n );\n\n const boundReadAloudButton = renderSlot(\n readAloudButton,\n CopilotChatAssistantMessage.ReadAloudButton,\n {\n onClick: onReadAloud,\n },\n );\n\n const boundRegenerateButton = renderSlot(\n regenerateButton,\n CopilotChatAssistantMessage.RegenerateButton,\n {\n onClick: onRegenerate,\n },\n );\n\n const boundToolbar = renderSlot(\n toolbar,\n CopilotChatAssistantMessage.Toolbar,\n {\n children: (\n <div className=\"cpk:flex cpk:items-center cpk:gap-1\">\n {boundCopyButton}\n {(onThumbsUp || thumbsUpButton) && boundThumbsUpButton}\n {(onThumbsDown || thumbsDownButton) && boundThumbsDownButton}\n {(onReadAloud || readAloudButton) && boundReadAloudButton}\n {(onRegenerate || regenerateButton) && boundRegenerateButton}\n {additionalToolbarItems}\n </div>\n ),\n },\n );\n\n const boundToolCallsView = renderSlot(\n toolCallsView,\n CopilotChatToolCallsView,\n {\n message,\n messages,\n },\n );\n\n // Don't show toolbar if message has no content (only tool calls)\n const hasContent = !!(message.content && message.content.trim().length > 0);\n const isLatestAssistantMessage =\n message.role === \"assistant\" &&\n messages?.[messages.length - 1]?.id === message.id;\n const shouldShowToolbar =\n toolbarVisible && hasContent && !(isRunning && isLatestAssistantMessage);\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n markdownRenderer: boundMarkdownRenderer,\n toolbar: boundToolbar,\n toolCallsView: boundToolCallsView,\n copyButton: boundCopyButton,\n thumbsUpButton: boundThumbsUpButton,\n thumbsDownButton: boundThumbsDownButton,\n readAloudButton: boundReadAloudButton,\n regenerateButton: boundRegenerateButton,\n message,\n messages,\n isRunning,\n onThumbsUp,\n onThumbsDown,\n onReadAloud,\n onRegenerate,\n additionalToolbarItems,\n toolbarVisible: shouldShowToolbar,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-assistant-message\"\n className={twMerge(\n \"copilotKitMessage copilotKitAssistantMessage\",\n className,\n )}\n {...props}\n data-message-id={message.id}\n >\n <div className=\"cpk:prose cpk:max-w-full cpk:break-words cpk:dark:prose-invert\">\n {boundMarkdownRenderer}\n </div>\n {boundToolCallsView}\n {shouldShowToolbar && boundToolbar}\n </div>\n );\n}\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace CopilotChatAssistantMessage {\n export const MarkdownRenderer: React.FC<\n Omit<React.ComponentProps<typeof Streamdown>, \"children\"> & {\n content: string;\n }\n > = ({ content, className, ...props }) => (\n <Streamdown className={className} {...props}>\n {content ?? \"\"}\n </Streamdown>\n );\n\n export const Toolbar: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n ...props\n }) => (\n <div\n data-testid=\"copilot-assistant-toolbar\"\n className={twMerge(\n \"cpk:w-full cpk:bg-transparent cpk:flex cpk:items-center cpk:-ml-[5px] cpk:-mt-[0px]\",\n className,\n )}\n {...props}\n />\n );\n\n export const ToolbarButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement> & {\n title: string;\n children: React.ReactNode;\n }\n > = ({ title, children, ...props }) => {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n type=\"button\"\n variant=\"assistantMessageToolbarButton\"\n aria-label={title}\n {...props}\n >\n {children}\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">\n <p>{title}</p>\n </TooltipContent>\n </Tooltip>\n );\n };\n\n export const CopyButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, title, onClick, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n const [copied, setCopied] = useState(false);\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n\n if (onClick) {\n onClick(event);\n }\n };\n\n return (\n <ToolbarButton\n data-testid=\"copilot-copy-button\"\n title={title || labels.assistantMessageToolbarCopyMessageLabel}\n onClick={handleClick}\n className={className}\n {...props}\n >\n {copied ? (\n <Check className=\"cpk:size-[18px]\" />\n ) : (\n <Copy className=\"cpk:size-[18px]\" />\n )}\n </ToolbarButton>\n );\n };\n\n export const ThumbsUpButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-thumbs-up-button\"\n title={title || labels.assistantMessageToolbarThumbsUpLabel}\n {...props}\n >\n <ThumbsUp className=\"cpk:size-[18px]\" />\n </ToolbarButton>\n );\n };\n\n export const ThumbsDownButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-thumbs-down-button\"\n title={title || labels.assistantMessageToolbarThumbsDownLabel}\n {...props}\n >\n <ThumbsDown className=\"cpk:size-[18px]\" />\n </ToolbarButton>\n );\n };\n\n export const ReadAloudButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-read-aloud-button\"\n title={title || labels.assistantMessageToolbarReadAloudLabel}\n {...props}\n >\n <Volume2 className=\"cpk:size-[20px]\" />\n </ToolbarButton>\n );\n };\n\n export const RegenerateButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-regenerate-button\"\n title={title || labels.assistantMessageToolbarRegenerateLabel}\n {...props}\n >\n <RefreshCw className=\"cpk:size-[18px]\" />\n </ToolbarButton>\n );\n };\n}\n\nCopilotChatAssistantMessage.MarkdownRenderer.displayName =\n \"CopilotChatAssistantMessage.MarkdownRenderer\";\nCopilotChatAssistantMessage.Toolbar.displayName =\n \"CopilotChatAssistantMessage.Toolbar\";\nCopilotChatAssistantMessage.CopyButton.displayName =\n \"CopilotChatAssistantMessage.CopyButton\";\nCopilotChatAssistantMessage.ThumbsUpButton.displayName =\n \"CopilotChatAssistantMessage.ThumbsUpButton\";\nCopilotChatAssistantMessage.ThumbsDownButton.displayName =\n \"CopilotChatAssistantMessage.ThumbsDownButton\";\nCopilotChatAssistantMessage.ReadAloudButton.displayName =\n \"CopilotChatAssistantMessage.ReadAloudButton\";\nCopilotChatAssistantMessage.RegenerateButton.displayName =\n \"CopilotChatAssistantMessage.RegenerateButton\";\n\nexport default CopilotChatAssistantMessage;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CopilotChatAssistantMessage.cjs","names":["renderSlot","CopilotChatToolCallsView","Streamdown","Tooltip","TooltipTrigger","Button","TooltipContent","useCopilotChatConfiguration","CopilotChatDefaultLabels","Check","Copy","ThumbsUp","ThumbsDown","Volume2","RefreshCw"],"sources":["../../../src/components/chat/CopilotChatAssistantMessage.tsx"],"sourcesContent":["import { AssistantMessage, Message } from \"@ag-ui/core\";\nimport { useState } from \"react\";\nimport {\n Copy,\n Check,\n ThumbsUp,\n ThumbsDown,\n Volume2,\n RefreshCw,\n} from \"lucide-react\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport { useKatexStyles } from \"@/hooks/useKatexStyles\";\nimport { WithSlots, renderSlot } from \"@/lib/slots\";\nimport { Streamdown } from \"streamdown\";\nimport CopilotChatToolCallsView from \"./CopilotChatToolCallsView\";\n\nexport type CopilotChatAssistantMessageProps = WithSlots<\n {\n markdownRenderer: typeof CopilotChatAssistantMessage.MarkdownRenderer;\n toolbar: typeof CopilotChatAssistantMessage.Toolbar;\n copyButton: typeof CopilotChatAssistantMessage.CopyButton;\n thumbsUpButton: typeof CopilotChatAssistantMessage.ThumbsUpButton;\n thumbsDownButton: typeof CopilotChatAssistantMessage.ThumbsDownButton;\n readAloudButton: typeof CopilotChatAssistantMessage.ReadAloudButton;\n regenerateButton: typeof CopilotChatAssistantMessage.RegenerateButton;\n toolCallsView: typeof CopilotChatToolCallsView;\n },\n {\n onThumbsUp?: (message: AssistantMessage) => void;\n onThumbsDown?: (message: AssistantMessage) => void;\n onReadAloud?: (message: AssistantMessage) => void;\n onRegenerate?: (message: AssistantMessage) => void;\n message: AssistantMessage;\n messages?: Message[];\n isRunning?: boolean;\n additionalToolbarItems?: React.ReactNode;\n toolbarVisible?: boolean;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport function CopilotChatAssistantMessage({\n message,\n messages,\n isRunning,\n onThumbsUp,\n onThumbsDown,\n onReadAloud,\n onRegenerate,\n additionalToolbarItems,\n toolbarVisible = true,\n markdownRenderer,\n toolbar,\n copyButton,\n thumbsUpButton,\n thumbsDownButton,\n readAloudButton,\n regenerateButton,\n toolCallsView,\n children,\n className,\n ...props\n}: CopilotChatAssistantMessageProps) {\n useKatexStyles();\n\n const boundMarkdownRenderer = renderSlot(\n markdownRenderer,\n CopilotChatAssistantMessage.MarkdownRenderer,\n {\n content: message.content || \"\",\n },\n );\n\n const boundCopyButton = renderSlot(\n copyButton,\n CopilotChatAssistantMessage.CopyButton,\n {\n onClick: async () => {\n if (message.content) {\n try {\n await navigator.clipboard.writeText(message.content);\n } catch (err) {\n console.error(\"Failed to copy message:\", err);\n }\n }\n },\n },\n );\n\n const boundThumbsUpButton = renderSlot(\n thumbsUpButton,\n CopilotChatAssistantMessage.ThumbsUpButton,\n {\n onClick: onThumbsUp,\n },\n );\n\n const boundThumbsDownButton = renderSlot(\n thumbsDownButton,\n CopilotChatAssistantMessage.ThumbsDownButton,\n {\n onClick: onThumbsDown,\n },\n );\n\n const boundReadAloudButton = renderSlot(\n readAloudButton,\n CopilotChatAssistantMessage.ReadAloudButton,\n {\n onClick: onReadAloud,\n },\n );\n\n const boundRegenerateButton = renderSlot(\n regenerateButton,\n CopilotChatAssistantMessage.RegenerateButton,\n {\n onClick: onRegenerate,\n },\n );\n\n const boundToolbar = renderSlot(\n toolbar,\n CopilotChatAssistantMessage.Toolbar,\n {\n children: (\n <div className=\"cpk:flex cpk:items-center cpk:gap-1\">\n {boundCopyButton}\n {(onThumbsUp || thumbsUpButton) && boundThumbsUpButton}\n {(onThumbsDown || thumbsDownButton) && boundThumbsDownButton}\n {(onReadAloud || readAloudButton) && boundReadAloudButton}\n {(onRegenerate || regenerateButton) && boundRegenerateButton}\n {additionalToolbarItems}\n </div>\n ),\n },\n );\n\n const boundToolCallsView = renderSlot(\n toolCallsView,\n CopilotChatToolCallsView,\n {\n message,\n messages,\n },\n );\n\n // Don't show toolbar if message has no content (only tool calls)\n const hasContent = !!(message.content && message.content.trim().length > 0);\n const isLatestAssistantMessage =\n message.role === \"assistant\" &&\n messages?.[messages.length - 1]?.id === message.id;\n const shouldShowToolbar =\n toolbarVisible && hasContent && !(isRunning && isLatestAssistantMessage);\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n markdownRenderer: boundMarkdownRenderer,\n toolbar: boundToolbar,\n toolCallsView: boundToolCallsView,\n copyButton: boundCopyButton,\n thumbsUpButton: boundThumbsUpButton,\n thumbsDownButton: boundThumbsDownButton,\n readAloudButton: boundReadAloudButton,\n regenerateButton: boundRegenerateButton,\n message,\n messages,\n isRunning,\n onThumbsUp,\n onThumbsDown,\n onReadAloud,\n onRegenerate,\n additionalToolbarItems,\n toolbarVisible: shouldShowToolbar,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-assistant-message\"\n className={twMerge(\n \"copilotKitMessage copilotKitAssistantMessage\",\n className,\n )}\n {...props}\n data-message-id={message.id}\n >\n <div className=\"cpk:prose cpk:max-w-full cpk:break-words cpk:dark:prose-invert\">\n {boundMarkdownRenderer}\n </div>\n {boundToolCallsView}\n {shouldShowToolbar && boundToolbar}\n </div>\n );\n}\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace CopilotChatAssistantMessage {\n export const MarkdownRenderer: React.FC<\n Omit<React.ComponentProps<typeof Streamdown>, \"children\"> & {\n content: string;\n }\n > = ({ content, className, ...props }) => (\n <Streamdown className={className} {...props}>\n {content ?? \"\"}\n </Streamdown>\n );\n\n export const Toolbar: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n ...props\n }) => (\n <div\n data-testid=\"copilot-assistant-toolbar\"\n className={twMerge(\n \"cpk:w-full cpk:bg-transparent cpk:flex cpk:items-center cpk:-ml-[5px] cpk:-mt-[0px]\",\n className,\n )}\n {...props}\n />\n );\n\n export const ToolbarButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement> & {\n title: string;\n children: React.ReactNode;\n }\n > = ({ title, children, ...props }) => {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n type=\"button\"\n variant=\"assistantMessageToolbarButton\"\n aria-label={title}\n {...props}\n >\n {children}\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">\n <p>{title}</p>\n </TooltipContent>\n </Tooltip>\n );\n };\n\n export const CopyButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, title, onClick, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n const [copied, setCopied] = useState(false);\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n\n if (onClick) {\n onClick(event);\n }\n };\n\n return (\n <ToolbarButton\n data-testid=\"copilot-copy-button\"\n title={title || labels.assistantMessageToolbarCopyMessageLabel}\n onClick={handleClick}\n className={className}\n {...props}\n >\n {copied ? (\n <Check className=\"cpk:size-[18px]\" />\n ) : (\n <Copy className=\"cpk:size-[18px]\" />\n )}\n </ToolbarButton>\n );\n };\n\n export const ThumbsUpButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-thumbs-up-button\"\n title={title || labels.assistantMessageToolbarThumbsUpLabel}\n {...props}\n >\n <ThumbsUp className=\"cpk:size-[18px]\" />\n </ToolbarButton>\n );\n };\n\n export const ThumbsDownButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-thumbs-down-button\"\n title={title || labels.assistantMessageToolbarThumbsDownLabel}\n {...props}\n >\n <ThumbsDown className=\"cpk:size-[18px]\" />\n </ToolbarButton>\n );\n };\n\n export const ReadAloudButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-read-aloud-button\"\n title={title || labels.assistantMessageToolbarReadAloudLabel}\n {...props}\n >\n <Volume2 className=\"cpk:size-[20px]\" />\n </ToolbarButton>\n );\n };\n\n export const RegenerateButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-regenerate-button\"\n title={title || labels.assistantMessageToolbarRegenerateLabel}\n {...props}\n >\n <RefreshCw className=\"cpk:size-[18px]\" />\n </ToolbarButton>\n );\n };\n}\n\nCopilotChatAssistantMessage.MarkdownRenderer.displayName =\n \"CopilotChatAssistantMessage.MarkdownRenderer\";\nCopilotChatAssistantMessage.Toolbar.displayName =\n \"CopilotChatAssistantMessage.Toolbar\";\nCopilotChatAssistantMessage.CopyButton.displayName =\n \"CopilotChatAssistantMessage.CopyButton\";\nCopilotChatAssistantMessage.ThumbsUpButton.displayName =\n \"CopilotChatAssistantMessage.ThumbsUpButton\";\nCopilotChatAssistantMessage.ThumbsDownButton.displayName =\n \"CopilotChatAssistantMessage.ThumbsDownButton\";\nCopilotChatAssistantMessage.ReadAloudButton.displayName =\n \"CopilotChatAssistantMessage.ReadAloudButton\";\nCopilotChatAssistantMessage.RegenerateButton.displayName =\n \"CopilotChatAssistantMessage.RegenerateButton\";\n\nexport default CopilotChatAssistantMessage;\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotChatAssistantMessage.d.cts","names":[],"sources":["../../../src/components/chat/CopilotChatAssistantMessage.tsx"],"mappings":";;;;;;;KA0BY,gCAAA,GAAmC,SAAA;EAE3C,gBAAA,SAAyB,2BAAA,CAA4B,gBAAA;EACrD,OAAA,SAAgB,2BAAA,CAA4B,OAAA;EAC5C,UAAA,SAAmB,2BAAA,CAA4B,UAAA;EAC/C,cAAA,SAAuB,2BAAA,CAA4B,cAAA;EACnD,gBAAA,SAAyB,2BAAA,CAA4B,gBAAA;EACrD,eAAA,SAAwB,2BAAA,CAA4B,eAAA;EACpD,gBAAA,SAAyB,2BAAA,CAA4B,gBAAA;EACrD,aAAA,SAAsB,wBAAA;AAAA;EAGtB,UAAA,IAAc,OAAA,EAAS,gBAAA;EACvB,YAAA,IAAgB,OAAA,EAAS,gBAAA;EACzB,WAAA,IAAe,OAAA,EAAS,gBAAA;EACxB,YAAA,IAAgB,OAAA,EAAS,gBAAA;EACzB,OAAA,EAAS,gBAAA;EACT,QAAA,GAAW,OAAA;EACX,SAAA;EACA,sBAAA,GAAyB,KAAA,CAAM,SAAA;EAC/B,cAAA;AAAA,IACE,KAAA,CAAM,cAAA,CAAe,cAAA;AAAA,iBAGX,2BAAA,CAAA;EACd,OAAA;EACA,QAAA;EACA,SAAA;EACA,UAAA;EACA,YAAA;EACA,WAAA;EACA,YAAA;EACA,sBAAA;EACA,cAAA;EACA,gBAAA;EACA,OAAA;EACA,UAAA;EACA,cAAA;EACA,gBAAA;EACA,eAAA;EACA,gBAAA;EACA,aAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,gCAAA,GAAgC,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"CopilotChatAssistantMessage.d.cts","names":[],"sources":["../../../src/components/chat/CopilotChatAssistantMessage.tsx"],"mappings":";;;;;;;KA0BY,gCAAA,GAAmC,SAAA;EAE3C,gBAAA,SAAyB,2BAAA,CAA4B,gBAAA;EACrD,OAAA,SAAgB,2BAAA,CAA4B,OAAA;EAC5C,UAAA,SAAmB,2BAAA,CAA4B,UAAA;EAC/C,cAAA,SAAuB,2BAAA,CAA4B,cAAA;EACnD,gBAAA,SAAyB,2BAAA,CAA4B,gBAAA;EACrD,eAAA,SAAwB,2BAAA,CAA4B,eAAA;EACpD,gBAAA,SAAyB,2BAAA,CAA4B,gBAAA;EACrD,aAAA,SAAsB,wBAAA;AAAA;EAGtB,UAAA,IAAc,OAAA,EAAS,gBAAA;EACvB,YAAA,IAAgB,OAAA,EAAS,gBAAA;EACzB,WAAA,IAAe,OAAA,EAAS,gBAAA;EACxB,YAAA,IAAgB,OAAA,EAAS,gBAAA;EACzB,OAAA,EAAS,gBAAA;EACT,QAAA,GAAW,OAAA;EACX,SAAA;EACA,sBAAA,GAAyB,KAAA,CAAM,SAAA;EAC/B,cAAA;AAAA,IACE,KAAA,CAAM,cAAA,CAAe,cAAA;AAAA,iBAGX,2BAAA,CAAA;EACd,OAAA;EACA,QAAA;EACA,SAAA;EACA,UAAA;EACA,YAAA;EACA,WAAA;EACA,YAAA;EACA,sBAAA;EACA,cAAA;EACA,gBAAA;EACA,OAAA;EACA,UAAA;EACA,cAAA;EACA,gBAAA;EACA,eAAA;EACA,gBAAA;EACA,aAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,gCAAA,GAAgC,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,kBA4IlB,2BAAA;EAAA,MACF,gBAAA,EAAkB,KAAA,CAAM,EAAA,CACnC,IAAA,CAAK,KAAA,CAAM,cAAA,QAAsB,UAAA;IAC/B,OAAA;EAAA;EAAA,MAQS,OAAA,EAAS,KAAA,CAAM,EAAA,CAAG,KAAA,CAAM,cAAA,CAAe,cAAA;EAAA,MAcvC,aAAA,EAAe,KAAA,CAAM,EAAA,CAChC,KAAA,CAAM,oBAAA,CAAqB,iBAAA;IACzB,KAAA;IACA,QAAA,EAAU,KAAA,CAAM,SAAA;EAAA;EAAA,MAsBP,UAAA,EAAY,KAAA,CAAM,EAAA,CAC7B,KAAA,CAAM,oBAAA,CAAqB,iBAAA;EAAA,MAgChB,cAAA,EAAgB,KAAA,CAAM,EAAA,CACjC,KAAA,CAAM,oBAAA,CAAqB,iBAAA;EAAA,MAehB,gBAAA,EAAkB,KAAA,CAAM,EAAA,CACnC,KAAA,CAAM,oBAAA,CAAqB,iBAAA;EAAA,MAehB,eAAA,EAAiB,KAAA,CAAM,EAAA,CAClC,KAAA,CAAM,oBAAA,CAAqB,iBAAA;EAAA,MAehB,gBAAA,EAAkB,KAAA,CAAM,EAAA,CACnC,KAAA,CAAM,oBAAA,CAAqB,iBAAA;AAAA"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { WithSlots } from "../../lib/slots.mjs";
|
|
2
2
|
import { CopilotChatToolCallsView } from "./CopilotChatToolCallsView.mjs";
|
|
3
3
|
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
4
|
-
import "katex/dist/katex.min.css";
|
|
5
4
|
import { Streamdown } from "streamdown";
|
|
6
5
|
import { AssistantMessage, Message } from "@ag-ui/core";
|
|
7
6
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotChatAssistantMessage.d.mts","names":[],"sources":["../../../src/components/chat/CopilotChatAssistantMessage.tsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"CopilotChatAssistantMessage.d.mts","names":[],"sources":["../../../src/components/chat/CopilotChatAssistantMessage.tsx"],"mappings":";;;;;;;KA0BY,gCAAA,GAAmC,SAAA;EAE3C,gBAAA,SAAyB,2BAAA,CAA4B,gBAAA;EACrD,OAAA,SAAgB,2BAAA,CAA4B,OAAA;EAC5C,UAAA,SAAmB,2BAAA,CAA4B,UAAA;EAC/C,cAAA,SAAuB,2BAAA,CAA4B,cAAA;EACnD,gBAAA,SAAyB,2BAAA,CAA4B,gBAAA;EACrD,eAAA,SAAwB,2BAAA,CAA4B,eAAA;EACpD,gBAAA,SAAyB,2BAAA,CAA4B,gBAAA;EACrD,aAAA,SAAsB,wBAAA;AAAA;EAGtB,UAAA,IAAc,OAAA,EAAS,gBAAA;EACvB,YAAA,IAAgB,OAAA,EAAS,gBAAA;EACzB,WAAA,IAAe,OAAA,EAAS,gBAAA;EACxB,YAAA,IAAgB,OAAA,EAAS,gBAAA;EACzB,OAAA,EAAS,gBAAA;EACT,QAAA,GAAW,OAAA;EACX,SAAA;EACA,sBAAA,GAAyB,KAAA,CAAM,SAAA;EAC/B,cAAA;AAAA,IACE,KAAA,CAAM,cAAA,CAAe,cAAA;AAAA,iBAGX,2BAAA,CAAA;EACd,OAAA;EACA,QAAA;EACA,SAAA;EACA,UAAA;EACA,YAAA;EACA,WAAA;EACA,YAAA;EACA,sBAAA;EACA,cAAA;EACA,gBAAA;EACA,OAAA;EACA,UAAA;EACA,cAAA;EACA,gBAAA;EACA,eAAA;EACA,gBAAA;EACA,aAAA;EACA,QAAA;EACA,SAAA;EAAA,GACG;AAAA,GACF,gCAAA,GAAgC,kBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,kBA4IlB,2BAAA;EAAA,MACF,gBAAA,EAAkB,KAAA,CAAM,EAAA,CACnC,IAAA,CAAK,KAAA,CAAM,cAAA,QAAsB,UAAA;IAC/B,OAAA;EAAA;EAAA,MAQS,OAAA,EAAS,KAAA,CAAM,EAAA,CAAG,KAAA,CAAM,cAAA,CAAe,cAAA;EAAA,MAcvC,aAAA,EAAe,KAAA,CAAM,EAAA,CAChC,KAAA,CAAM,oBAAA,CAAqB,iBAAA;IACzB,KAAA;IACA,QAAA,EAAU,KAAA,CAAM,SAAA;EAAA;EAAA,MAsBP,UAAA,EAAY,KAAA,CAAM,EAAA,CAC7B,KAAA,CAAM,oBAAA,CAAqB,iBAAA;EAAA,MAgChB,cAAA,EAAgB,KAAA,CAAM,EAAA,CACjC,KAAA,CAAM,oBAAA,CAAqB,iBAAA;EAAA,MAehB,gBAAA,EAAkB,KAAA,CAAM,EAAA,CACnC,KAAA,CAAM,oBAAA,CAAqB,iBAAA;EAAA,MAehB,eAAA,EAAiB,KAAA,CAAM,EAAA,CAClC,KAAA,CAAM,oBAAA,CAAqB,iBAAA;EAAA,MAehB,gBAAA,EAAkB,KAAA,CAAM,EAAA,CACnC,KAAA,CAAM,oBAAA,CAAqB,iBAAA;AAAA"}
|
|
@@ -2,16 +2,17 @@ import { CopilotChatDefaultLabels, useCopilotChatConfiguration } from "../../pro
|
|
|
2
2
|
import { Button } from "../ui/button.mjs";
|
|
3
3
|
import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip.mjs";
|
|
4
4
|
import { renderSlot } from "../../lib/slots.mjs";
|
|
5
|
+
import { useKatexStyles } from "../../hooks/useKatexStyles.mjs";
|
|
5
6
|
import CopilotChatToolCallsView from "./CopilotChatToolCallsView.mjs";
|
|
6
7
|
import { useState } from "react";
|
|
7
8
|
import { twMerge } from "tailwind-merge";
|
|
8
9
|
import { Check, Copy, RefreshCw, ThumbsDown, ThumbsUp, Volume2 } from "lucide-react";
|
|
9
10
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
10
|
-
import "katex/dist/katex.min.css";
|
|
11
11
|
import { Streamdown } from "streamdown";
|
|
12
12
|
|
|
13
13
|
//#region src/components/chat/CopilotChatAssistantMessage.tsx
|
|
14
14
|
function CopilotChatAssistantMessage({ message, messages, isRunning, onThumbsUp, onThumbsDown, onReadAloud, onRegenerate, additionalToolbarItems, toolbarVisible = true, markdownRenderer, toolbar, copyButton, thumbsUpButton, thumbsDownButton, readAloudButton, regenerateButton, toolCallsView, children, className, ...props }) {
|
|
15
|
+
useKatexStyles();
|
|
15
16
|
const boundMarkdownRenderer = renderSlot(markdownRenderer, CopilotChatAssistantMessage.MarkdownRenderer, { content: message.content || "" });
|
|
16
17
|
const boundCopyButton = renderSlot(copyButton, CopilotChatAssistantMessage.CopyButton, { onClick: async () => {
|
|
17
18
|
if (message.content) try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"CopilotChatAssistantMessage.mjs","names":[],"sources":["../../../src/components/chat/CopilotChatAssistantMessage.tsx"],"sourcesContent":["import { AssistantMessage, Message } from \"@ag-ui/core\";\nimport { useState } from \"react\";\nimport {\n Copy,\n Check,\n ThumbsUp,\n ThumbsDown,\n Volume2,\n RefreshCw,\n} from \"lucide-react\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport \"katex/dist/katex.min.css\";\nimport { WithSlots, renderSlot } from \"@/lib/slots\";\nimport { Streamdown } from \"streamdown\";\nimport CopilotChatToolCallsView from \"./CopilotChatToolCallsView\";\n\nexport type CopilotChatAssistantMessageProps = WithSlots<\n {\n markdownRenderer: typeof CopilotChatAssistantMessage.MarkdownRenderer;\n toolbar: typeof CopilotChatAssistantMessage.Toolbar;\n copyButton: typeof CopilotChatAssistantMessage.CopyButton;\n thumbsUpButton: typeof CopilotChatAssistantMessage.ThumbsUpButton;\n thumbsDownButton: typeof CopilotChatAssistantMessage.ThumbsDownButton;\n readAloudButton: typeof CopilotChatAssistantMessage.ReadAloudButton;\n regenerateButton: typeof CopilotChatAssistantMessage.RegenerateButton;\n toolCallsView: typeof CopilotChatToolCallsView;\n },\n {\n onThumbsUp?: (message: AssistantMessage) => void;\n onThumbsDown?: (message: AssistantMessage) => void;\n onReadAloud?: (message: AssistantMessage) => void;\n onRegenerate?: (message: AssistantMessage) => void;\n message: AssistantMessage;\n messages?: Message[];\n isRunning?: boolean;\n additionalToolbarItems?: React.ReactNode;\n toolbarVisible?: boolean;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport function CopilotChatAssistantMessage({\n message,\n messages,\n isRunning,\n onThumbsUp,\n onThumbsDown,\n onReadAloud,\n onRegenerate,\n additionalToolbarItems,\n toolbarVisible = true,\n markdownRenderer,\n toolbar,\n copyButton,\n thumbsUpButton,\n thumbsDownButton,\n readAloudButton,\n regenerateButton,\n toolCallsView,\n children,\n className,\n ...props\n}: CopilotChatAssistantMessageProps) {\n const boundMarkdownRenderer = renderSlot(\n markdownRenderer,\n CopilotChatAssistantMessage.MarkdownRenderer,\n {\n content: message.content || \"\",\n },\n );\n\n const boundCopyButton = renderSlot(\n copyButton,\n CopilotChatAssistantMessage.CopyButton,\n {\n onClick: async () => {\n if (message.content) {\n try {\n await navigator.clipboard.writeText(message.content);\n } catch (err) {\n console.error(\"Failed to copy message:\", err);\n }\n }\n },\n },\n );\n\n const boundThumbsUpButton = renderSlot(\n thumbsUpButton,\n CopilotChatAssistantMessage.ThumbsUpButton,\n {\n onClick: onThumbsUp,\n },\n );\n\n const boundThumbsDownButton = renderSlot(\n thumbsDownButton,\n CopilotChatAssistantMessage.ThumbsDownButton,\n {\n onClick: onThumbsDown,\n },\n );\n\n const boundReadAloudButton = renderSlot(\n readAloudButton,\n CopilotChatAssistantMessage.ReadAloudButton,\n {\n onClick: onReadAloud,\n },\n );\n\n const boundRegenerateButton = renderSlot(\n regenerateButton,\n CopilotChatAssistantMessage.RegenerateButton,\n {\n onClick: onRegenerate,\n },\n );\n\n const boundToolbar = renderSlot(\n toolbar,\n CopilotChatAssistantMessage.Toolbar,\n {\n children: (\n <div className=\"cpk:flex cpk:items-center cpk:gap-1\">\n {boundCopyButton}\n {(onThumbsUp || thumbsUpButton) && boundThumbsUpButton}\n {(onThumbsDown || thumbsDownButton) && boundThumbsDownButton}\n {(onReadAloud || readAloudButton) && boundReadAloudButton}\n {(onRegenerate || regenerateButton) && boundRegenerateButton}\n {additionalToolbarItems}\n </div>\n ),\n },\n );\n\n const boundToolCallsView = renderSlot(\n toolCallsView,\n CopilotChatToolCallsView,\n {\n message,\n messages,\n },\n );\n\n // Don't show toolbar if message has no content (only tool calls)\n const hasContent = !!(message.content && message.content.trim().length > 0);\n const isLatestAssistantMessage =\n message.role === \"assistant\" &&\n messages?.[messages.length - 1]?.id === message.id;\n const shouldShowToolbar =\n toolbarVisible && hasContent && !(isRunning && isLatestAssistantMessage);\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n markdownRenderer: boundMarkdownRenderer,\n toolbar: boundToolbar,\n toolCallsView: boundToolCallsView,\n copyButton: boundCopyButton,\n thumbsUpButton: boundThumbsUpButton,\n thumbsDownButton: boundThumbsDownButton,\n readAloudButton: boundReadAloudButton,\n regenerateButton: boundRegenerateButton,\n message,\n messages,\n isRunning,\n onThumbsUp,\n onThumbsDown,\n onReadAloud,\n onRegenerate,\n additionalToolbarItems,\n toolbarVisible: shouldShowToolbar,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-assistant-message\"\n className={twMerge(\n \"copilotKitMessage copilotKitAssistantMessage\",\n className,\n )}\n {...props}\n data-message-id={message.id}\n >\n <div className=\"cpk:prose cpk:max-w-full cpk:break-words cpk:dark:prose-invert\">\n {boundMarkdownRenderer}\n </div>\n {boundToolCallsView}\n {shouldShowToolbar && boundToolbar}\n </div>\n );\n}\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace CopilotChatAssistantMessage {\n export const MarkdownRenderer: React.FC<\n Omit<React.ComponentProps<typeof Streamdown>, \"children\"> & {\n content: string;\n }\n > = ({ content, className, ...props }) => (\n <Streamdown className={className} {...props}>\n {content ?? \"\"}\n </Streamdown>\n );\n\n export const Toolbar: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n ...props\n }) => (\n <div\n data-testid=\"copilot-assistant-toolbar\"\n className={twMerge(\n \"cpk:w-full cpk:bg-transparent cpk:flex cpk:items-center cpk:-ml-[5px] cpk:-mt-[0px]\",\n className,\n )}\n {...props}\n />\n );\n\n export const ToolbarButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement> & {\n title: string;\n children: React.ReactNode;\n }\n > = ({ title, children, ...props }) => {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n type=\"button\"\n variant=\"assistantMessageToolbarButton\"\n aria-label={title}\n {...props}\n >\n {children}\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">\n <p>{title}</p>\n </TooltipContent>\n </Tooltip>\n );\n };\n\n export const CopyButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, title, onClick, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n const [copied, setCopied] = useState(false);\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n\n if (onClick) {\n onClick(event);\n }\n };\n\n return (\n <ToolbarButton\n data-testid=\"copilot-copy-button\"\n title={title || labels.assistantMessageToolbarCopyMessageLabel}\n onClick={handleClick}\n className={className}\n {...props}\n >\n {copied ? (\n <Check className=\"cpk:size-[18px]\" />\n ) : (\n <Copy className=\"cpk:size-[18px]\" />\n )}\n </ToolbarButton>\n );\n };\n\n export const ThumbsUpButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-thumbs-up-button\"\n title={title || labels.assistantMessageToolbarThumbsUpLabel}\n {...props}\n >\n <ThumbsUp className=\"cpk:size-[18px]\" />\n </ToolbarButton>\n );\n };\n\n export const ThumbsDownButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-thumbs-down-button\"\n title={title || labels.assistantMessageToolbarThumbsDownLabel}\n {...props}\n >\n <ThumbsDown className=\"cpk:size-[18px]\" />\n </ToolbarButton>\n );\n };\n\n export const ReadAloudButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-read-aloud-button\"\n title={title || labels.assistantMessageToolbarReadAloudLabel}\n {...props}\n >\n <Volume2 className=\"cpk:size-[20px]\" />\n </ToolbarButton>\n );\n };\n\n export const RegenerateButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-regenerate-button\"\n title={title || labels.assistantMessageToolbarRegenerateLabel}\n {...props}\n >\n <RefreshCw className=\"cpk:size-[18px]\" />\n </ToolbarButton>\n );\n };\n}\n\nCopilotChatAssistantMessage.MarkdownRenderer.displayName =\n \"CopilotChatAssistantMessage.MarkdownRenderer\";\nCopilotChatAssistantMessage.Toolbar.displayName =\n \"CopilotChatAssistantMessage.Toolbar\";\nCopilotChatAssistantMessage.CopyButton.displayName =\n \"CopilotChatAssistantMessage.CopyButton\";\nCopilotChatAssistantMessage.ThumbsUpButton.displayName =\n \"CopilotChatAssistantMessage.ThumbsUpButton\";\nCopilotChatAssistantMessage.ThumbsDownButton.displayName =\n \"CopilotChatAssistantMessage.ThumbsDownButton\";\nCopilotChatAssistantMessage.ReadAloudButton.displayName =\n \"CopilotChatAssistantMessage.ReadAloudButton\";\nCopilotChatAssistantMessage.RegenerateButton.displayName =\n \"CopilotChatAssistantMessage.RegenerateButton\";\n\nexport default CopilotChatAssistantMessage;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"CopilotChatAssistantMessage.mjs","names":[],"sources":["../../../src/components/chat/CopilotChatAssistantMessage.tsx"],"sourcesContent":["import { AssistantMessage, Message } from \"@ag-ui/core\";\nimport { useState } from \"react\";\nimport {\n Copy,\n Check,\n ThumbsUp,\n ThumbsDown,\n Volume2,\n RefreshCw,\n} from \"lucide-react\";\nimport {\n useCopilotChatConfiguration,\n CopilotChatDefaultLabels,\n} from \"@/providers/CopilotChatConfigurationProvider\";\nimport { twMerge } from \"tailwind-merge\";\nimport { Button } from \"@/components/ui/button\";\nimport {\n Tooltip,\n TooltipContent,\n TooltipTrigger,\n} from \"@/components/ui/tooltip\";\nimport { useKatexStyles } from \"@/hooks/useKatexStyles\";\nimport { WithSlots, renderSlot } from \"@/lib/slots\";\nimport { Streamdown } from \"streamdown\";\nimport CopilotChatToolCallsView from \"./CopilotChatToolCallsView\";\n\nexport type CopilotChatAssistantMessageProps = WithSlots<\n {\n markdownRenderer: typeof CopilotChatAssistantMessage.MarkdownRenderer;\n toolbar: typeof CopilotChatAssistantMessage.Toolbar;\n copyButton: typeof CopilotChatAssistantMessage.CopyButton;\n thumbsUpButton: typeof CopilotChatAssistantMessage.ThumbsUpButton;\n thumbsDownButton: typeof CopilotChatAssistantMessage.ThumbsDownButton;\n readAloudButton: typeof CopilotChatAssistantMessage.ReadAloudButton;\n regenerateButton: typeof CopilotChatAssistantMessage.RegenerateButton;\n toolCallsView: typeof CopilotChatToolCallsView;\n },\n {\n onThumbsUp?: (message: AssistantMessage) => void;\n onThumbsDown?: (message: AssistantMessage) => void;\n onReadAloud?: (message: AssistantMessage) => void;\n onRegenerate?: (message: AssistantMessage) => void;\n message: AssistantMessage;\n messages?: Message[];\n isRunning?: boolean;\n additionalToolbarItems?: React.ReactNode;\n toolbarVisible?: boolean;\n } & React.HTMLAttributes<HTMLDivElement>\n>;\n\nexport function CopilotChatAssistantMessage({\n message,\n messages,\n isRunning,\n onThumbsUp,\n onThumbsDown,\n onReadAloud,\n onRegenerate,\n additionalToolbarItems,\n toolbarVisible = true,\n markdownRenderer,\n toolbar,\n copyButton,\n thumbsUpButton,\n thumbsDownButton,\n readAloudButton,\n regenerateButton,\n toolCallsView,\n children,\n className,\n ...props\n}: CopilotChatAssistantMessageProps) {\n useKatexStyles();\n\n const boundMarkdownRenderer = renderSlot(\n markdownRenderer,\n CopilotChatAssistantMessage.MarkdownRenderer,\n {\n content: message.content || \"\",\n },\n );\n\n const boundCopyButton = renderSlot(\n copyButton,\n CopilotChatAssistantMessage.CopyButton,\n {\n onClick: async () => {\n if (message.content) {\n try {\n await navigator.clipboard.writeText(message.content);\n } catch (err) {\n console.error(\"Failed to copy message:\", err);\n }\n }\n },\n },\n );\n\n const boundThumbsUpButton = renderSlot(\n thumbsUpButton,\n CopilotChatAssistantMessage.ThumbsUpButton,\n {\n onClick: onThumbsUp,\n },\n );\n\n const boundThumbsDownButton = renderSlot(\n thumbsDownButton,\n CopilotChatAssistantMessage.ThumbsDownButton,\n {\n onClick: onThumbsDown,\n },\n );\n\n const boundReadAloudButton = renderSlot(\n readAloudButton,\n CopilotChatAssistantMessage.ReadAloudButton,\n {\n onClick: onReadAloud,\n },\n );\n\n const boundRegenerateButton = renderSlot(\n regenerateButton,\n CopilotChatAssistantMessage.RegenerateButton,\n {\n onClick: onRegenerate,\n },\n );\n\n const boundToolbar = renderSlot(\n toolbar,\n CopilotChatAssistantMessage.Toolbar,\n {\n children: (\n <div className=\"cpk:flex cpk:items-center cpk:gap-1\">\n {boundCopyButton}\n {(onThumbsUp || thumbsUpButton) && boundThumbsUpButton}\n {(onThumbsDown || thumbsDownButton) && boundThumbsDownButton}\n {(onReadAloud || readAloudButton) && boundReadAloudButton}\n {(onRegenerate || regenerateButton) && boundRegenerateButton}\n {additionalToolbarItems}\n </div>\n ),\n },\n );\n\n const boundToolCallsView = renderSlot(\n toolCallsView,\n CopilotChatToolCallsView,\n {\n message,\n messages,\n },\n );\n\n // Don't show toolbar if message has no content (only tool calls)\n const hasContent = !!(message.content && message.content.trim().length > 0);\n const isLatestAssistantMessage =\n message.role === \"assistant\" &&\n messages?.[messages.length - 1]?.id === message.id;\n const shouldShowToolbar =\n toolbarVisible && hasContent && !(isRunning && isLatestAssistantMessage);\n\n if (children) {\n return (\n <div data-copilotkit style={{ display: \"contents\" }}>\n {children({\n markdownRenderer: boundMarkdownRenderer,\n toolbar: boundToolbar,\n toolCallsView: boundToolCallsView,\n copyButton: boundCopyButton,\n thumbsUpButton: boundThumbsUpButton,\n thumbsDownButton: boundThumbsDownButton,\n readAloudButton: boundReadAloudButton,\n regenerateButton: boundRegenerateButton,\n message,\n messages,\n isRunning,\n onThumbsUp,\n onThumbsDown,\n onReadAloud,\n onRegenerate,\n additionalToolbarItems,\n toolbarVisible: shouldShowToolbar,\n })}\n </div>\n );\n }\n\n return (\n <div\n data-copilotkit\n data-testid=\"copilot-assistant-message\"\n className={twMerge(\n \"copilotKitMessage copilotKitAssistantMessage\",\n className,\n )}\n {...props}\n data-message-id={message.id}\n >\n <div className=\"cpk:prose cpk:max-w-full cpk:break-words cpk:dark:prose-invert\">\n {boundMarkdownRenderer}\n </div>\n {boundToolCallsView}\n {shouldShowToolbar && boundToolbar}\n </div>\n );\n}\n\n// eslint-disable-next-line @typescript-eslint/no-namespace\nexport namespace CopilotChatAssistantMessage {\n export const MarkdownRenderer: React.FC<\n Omit<React.ComponentProps<typeof Streamdown>, \"children\"> & {\n content: string;\n }\n > = ({ content, className, ...props }) => (\n <Streamdown className={className} {...props}>\n {content ?? \"\"}\n </Streamdown>\n );\n\n export const Toolbar: React.FC<React.HTMLAttributes<HTMLDivElement>> = ({\n className,\n ...props\n }) => (\n <div\n data-testid=\"copilot-assistant-toolbar\"\n className={twMerge(\n \"cpk:w-full cpk:bg-transparent cpk:flex cpk:items-center cpk:-ml-[5px] cpk:-mt-[0px]\",\n className,\n )}\n {...props}\n />\n );\n\n export const ToolbarButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement> & {\n title: string;\n children: React.ReactNode;\n }\n > = ({ title, children, ...props }) => {\n return (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n type=\"button\"\n variant=\"assistantMessageToolbarButton\"\n aria-label={title}\n {...props}\n >\n {children}\n </Button>\n </TooltipTrigger>\n <TooltipContent side=\"bottom\">\n <p>{title}</p>\n </TooltipContent>\n </Tooltip>\n );\n };\n\n export const CopyButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ className, title, onClick, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n const [copied, setCopied] = useState(false);\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n\n if (onClick) {\n onClick(event);\n }\n };\n\n return (\n <ToolbarButton\n data-testid=\"copilot-copy-button\"\n title={title || labels.assistantMessageToolbarCopyMessageLabel}\n onClick={handleClick}\n className={className}\n {...props}\n >\n {copied ? (\n <Check className=\"cpk:size-[18px]\" />\n ) : (\n <Copy className=\"cpk:size-[18px]\" />\n )}\n </ToolbarButton>\n );\n };\n\n export const ThumbsUpButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-thumbs-up-button\"\n title={title || labels.assistantMessageToolbarThumbsUpLabel}\n {...props}\n >\n <ThumbsUp className=\"cpk:size-[18px]\" />\n </ToolbarButton>\n );\n };\n\n export const ThumbsDownButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-thumbs-down-button\"\n title={title || labels.assistantMessageToolbarThumbsDownLabel}\n {...props}\n >\n <ThumbsDown className=\"cpk:size-[18px]\" />\n </ToolbarButton>\n );\n };\n\n export const ReadAloudButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-read-aloud-button\"\n title={title || labels.assistantMessageToolbarReadAloudLabel}\n {...props}\n >\n <Volume2 className=\"cpk:size-[20px]\" />\n </ToolbarButton>\n );\n };\n\n export const RegenerateButton: React.FC<\n React.ButtonHTMLAttributes<HTMLButtonElement>\n > = ({ title, ...props }) => {\n const config = useCopilotChatConfiguration();\n const labels = config?.labels ?? CopilotChatDefaultLabels;\n return (\n <ToolbarButton\n data-testid=\"copilot-regenerate-button\"\n title={title || labels.assistantMessageToolbarRegenerateLabel}\n {...props}\n >\n <RefreshCw className=\"cpk:size-[18px]\" />\n </ToolbarButton>\n );\n };\n}\n\nCopilotChatAssistantMessage.MarkdownRenderer.displayName =\n \"CopilotChatAssistantMessage.MarkdownRenderer\";\nCopilotChatAssistantMessage.Toolbar.displayName =\n \"CopilotChatAssistantMessage.Toolbar\";\nCopilotChatAssistantMessage.CopyButton.displayName =\n \"CopilotChatAssistantMessage.CopyButton\";\nCopilotChatAssistantMessage.ThumbsUpButton.displayName =\n \"CopilotChatAssistantMessage.ThumbsUpButton\";\nCopilotChatAssistantMessage.ThumbsDownButton.displayName =\n \"CopilotChatAssistantMessage.ThumbsDownButton\";\nCopilotChatAssistantMessage.ReadAloudButton.displayName =\n \"CopilotChatAssistantMessage.ReadAloudButton\";\nCopilotChatAssistantMessage.RegenerateButton.displayName =\n \"CopilotChatAssistantMessage.RegenerateButton\";\n\nexport default CopilotChatAssistantMessage;\n"],"mappings":"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"}
|
|
@@ -8,16 +8,16 @@ let react_jsx_runtime = require("react/jsx-runtime");
|
|
|
8
8
|
*
|
|
9
9
|
* This hook is a convenience wrapper around `useFrontendTool` that:
|
|
10
10
|
* - builds a model-facing tool description,
|
|
11
|
-
* - forwards optional
|
|
11
|
+
* - forwards optional schema parameters (any Standard Schema V1 compatible library),
|
|
12
12
|
* - renders your component with tool call parameters.
|
|
13
13
|
*
|
|
14
14
|
* Use this when you want to display a typed visual component for a tool call
|
|
15
15
|
* without manually wiring a full frontend tool object.
|
|
16
16
|
*
|
|
17
|
-
* When `parameters` is provided, render props are inferred from the schema
|
|
18
|
-
*
|
|
17
|
+
* When `parameters` is provided, render props are inferred from the schema.
|
|
18
|
+
* When omitted, the render component may accept any props.
|
|
19
19
|
*
|
|
20
|
-
* @typeParam TSchema -
|
|
20
|
+
* @typeParam TSchema - Schema describing tool parameters, or `undefined` when no schema is given.
|
|
21
21
|
* @param config - Tool registration config.
|
|
22
22
|
* @param deps - Optional dependencies to refresh registration (same semantics as `useEffect`).
|
|
23
23
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-component.cjs","names":[],"sources":["../../src/hooks/use-component.tsx"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"use-component.cjs","names":[],"sources":["../../src/hooks/use-component.tsx"],"sourcesContent":["import type {\n StandardSchemaV1,\n InferSchemaOutput,\n} from \"@copilotkitnext/shared\";\nimport type { ComponentType } from \"react\";\nimport { useFrontendTool } from \"./use-frontend-tool\";\n\ntype InferRenderProps<T> = T extends StandardSchemaV1\n ? InferSchemaOutput<T>\n : any;\n\n/**\n * Registers a React component as a frontend tool renderer in chat.\n *\n * This hook is a convenience wrapper around `useFrontendTool` that:\n * - builds a model-facing tool description,\n * - forwards optional schema parameters (any Standard Schema V1 compatible library),\n * - renders your component with tool call parameters.\n *\n * Use this when you want to display a typed visual component for a tool call\n * without manually wiring a full frontend tool object.\n *\n * When `parameters` is provided, render props are inferred from the schema.\n * When omitted, the render component may accept any props.\n *\n * @typeParam TSchema - Schema describing tool parameters, or `undefined` when no schema is given.\n * @param config - Tool registration config.\n * @param deps - Optional dependencies to refresh registration (same semantics as `useEffect`).\n *\n * @example\n * ```tsx\n * // Without parameters — render accepts any props\n * useComponent({\n * name: \"showGreeting\",\n * render: ({ message }: { message: string }) => <div>{message}</div>,\n * });\n * ```\n *\n * @example\n * ```tsx\n * // With parameters — render props inferred from schema\n * useComponent({\n * name: \"showWeatherCard\",\n * parameters: z.object({ city: z.string() }),\n * render: ({ city }) => <div>{city}</div>,\n * });\n * ```\n *\n * @example\n * ```tsx\n * useComponent(\n * {\n * name: \"renderProfile\",\n * parameters: z.object({ userId: z.string() }),\n * render: ProfileCard,\n * agentId: \"support-agent\",\n * },\n * [selectedAgentId],\n * );\n * ```\n */\nexport function useComponent<\n TSchema extends StandardSchemaV1 | undefined = undefined,\n>(\n config: {\n name: string;\n description?: string;\n parameters?: TSchema;\n render: ComponentType<NoInfer<InferRenderProps<TSchema>>>;\n agentId?: string;\n },\n deps?: ReadonlyArray<unknown>,\n): void {\n const prefix = `Use this tool to display the \"${config.name}\" component in the chat. This tool renders a visual UI component for the user.`;\n const fullDescription = config.description\n ? `${prefix}\\n\\n${config.description}`\n : prefix;\n\n useFrontendTool(\n {\n name: config.name,\n description: fullDescription,\n parameters: config.parameters,\n render: ({ args }: { args: unknown }) => {\n const Component = config.render;\n return <Component {...(args as InferRenderProps<TSchema>)} />;\n },\n agentId: config.agentId,\n },\n deps,\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6DA,SAAgB,aAGd,QAOA,MACM;CACN,MAAM,SAAS,iCAAiC,OAAO,KAAK;CAC5D,MAAM,kBAAkB,OAAO,cAC3B,GAAG,OAAO,MAAM,OAAO,gBACvB;AAEJ,2CACE;EACE,MAAM,OAAO;EACb,aAAa;EACb,YAAY,OAAO;EACnB,SAAS,EAAE,WAA8B;GACvC,MAAM,YAAY,OAAO;AACzB,UAAO,2CAAC,aAAU,GAAK,OAAsC;;EAE/D,SAAS,OAAO;EACjB,EACD,KACD"}
|