@runtypelabs/persona 1.36.0
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/README.md +1080 -0
- package/dist/index.cjs +140 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2626 -0
- package/dist/index.d.ts +2626 -0
- package/dist/index.global.js +1843 -0
- package/dist/index.global.js.map +1 -0
- package/dist/index.js +140 -0
- package/dist/index.js.map +1 -0
- package/dist/install.global.js +2 -0
- package/dist/install.global.js.map +1 -0
- package/dist/widget.css +1627 -0
- package/package.json +79 -0
- package/src/@types/idiomorph.d.ts +37 -0
- package/src/client.test.ts +387 -0
- package/src/client.ts +1589 -0
- package/src/components/composer-builder.ts +530 -0
- package/src/components/feedback.ts +379 -0
- package/src/components/forms.ts +170 -0
- package/src/components/header-builder.ts +455 -0
- package/src/components/header-layouts.ts +303 -0
- package/src/components/launcher.ts +193 -0
- package/src/components/message-bubble.ts +528 -0
- package/src/components/messages.ts +54 -0
- package/src/components/panel.ts +204 -0
- package/src/components/reasoning-bubble.ts +144 -0
- package/src/components/registry.ts +87 -0
- package/src/components/suggestions.ts +97 -0
- package/src/components/tool-bubble.ts +288 -0
- package/src/defaults.ts +321 -0
- package/src/index.ts +175 -0
- package/src/install.ts +284 -0
- package/src/plugins/registry.ts +77 -0
- package/src/plugins/types.ts +95 -0
- package/src/postprocessors.ts +194 -0
- package/src/runtime/init.ts +162 -0
- package/src/session.ts +376 -0
- package/src/styles/tailwind.css +20 -0
- package/src/styles/widget.css +1627 -0
- package/src/types.ts +1635 -0
- package/src/ui.ts +3341 -0
- package/src/utils/actions.ts +227 -0
- package/src/utils/attachment-manager.ts +384 -0
- package/src/utils/code-generators.test.ts +500 -0
- package/src/utils/code-generators.ts +1806 -0
- package/src/utils/component-middleware.ts +137 -0
- package/src/utils/component-parser.ts +119 -0
- package/src/utils/constants.ts +16 -0
- package/src/utils/content.ts +306 -0
- package/src/utils/dom.ts +25 -0
- package/src/utils/events.ts +41 -0
- package/src/utils/formatting.test.ts +166 -0
- package/src/utils/formatting.ts +470 -0
- package/src/utils/icons.ts +92 -0
- package/src/utils/message-id.ts +37 -0
- package/src/utils/morph.ts +36 -0
- package/src/utils/positioning.ts +17 -0
- package/src/utils/storage.ts +72 -0
- package/src/utils/theme.ts +105 -0
- package/src/widget.css +1 -0
- package/widget.css +1 -0
|
@@ -0,0 +1,288 @@
|
|
|
1
|
+
import { createElement } from "../utils/dom";
|
|
2
|
+
import { AgentWidgetMessage, AgentWidgetConfig } from "../types";
|
|
3
|
+
import { formatUnknownValue, describeToolTitle } from "../utils/formatting";
|
|
4
|
+
import { renderLucideIcon } from "../utils/icons";
|
|
5
|
+
|
|
6
|
+
// Expansion state per widget instance
|
|
7
|
+
export const toolExpansionState = new Set<string>();
|
|
8
|
+
|
|
9
|
+
// Helper function to update tool bubble UI after expansion state changes
|
|
10
|
+
export const updateToolBubbleUI = (messageId: string, bubble: HTMLElement, config?: AgentWidgetConfig): void => {
|
|
11
|
+
const expanded = toolExpansionState.has(messageId);
|
|
12
|
+
const toolCallConfig = config?.toolCall ?? {};
|
|
13
|
+
const header = bubble.querySelector('button[data-expand-header="true"]') as HTMLElement;
|
|
14
|
+
const content = bubble.querySelector('.tvw-border-t') as HTMLElement;
|
|
15
|
+
|
|
16
|
+
if (!header || !content) return;
|
|
17
|
+
|
|
18
|
+
header.setAttribute("aria-expanded", expanded ? "true" : "false");
|
|
19
|
+
|
|
20
|
+
// Find toggle icon container - it's the direct child div of headerMeta (which has tvw-ml-auto)
|
|
21
|
+
const headerMeta = header.querySelector('.tvw-ml-auto') as HTMLElement;
|
|
22
|
+
const toggleIcon = headerMeta?.querySelector(':scope > .tvw-flex.tvw-items-center') as HTMLElement;
|
|
23
|
+
if (toggleIcon) {
|
|
24
|
+
toggleIcon.innerHTML = "";
|
|
25
|
+
const iconColor = toolCallConfig.toggleTextColor || toolCallConfig.headerTextColor || "currentColor";
|
|
26
|
+
const chevronIcon = renderLucideIcon(expanded ? "chevron-up" : "chevron-down", 16, iconColor, 2);
|
|
27
|
+
if (chevronIcon) {
|
|
28
|
+
toggleIcon.appendChild(chevronIcon);
|
|
29
|
+
} else {
|
|
30
|
+
toggleIcon.textContent = expanded ? "Hide" : "Show";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
content.style.display = expanded ? "" : "none";
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
export const createToolBubble = (message: AgentWidgetMessage, config?: AgentWidgetConfig): HTMLElement => {
|
|
38
|
+
const tool = message.toolCall;
|
|
39
|
+
const toolCallConfig = config?.toolCall ?? {};
|
|
40
|
+
|
|
41
|
+
const bubble = createElement(
|
|
42
|
+
"div",
|
|
43
|
+
[
|
|
44
|
+
"vanilla-message-bubble",
|
|
45
|
+
"vanilla-tool-bubble",
|
|
46
|
+
"tvw-w-full",
|
|
47
|
+
"tvw-max-w-[85%]",
|
|
48
|
+
"tvw-rounded-2xl",
|
|
49
|
+
"tvw-bg-cw-surface",
|
|
50
|
+
"tvw-border",
|
|
51
|
+
"tvw-border-cw-message-border",
|
|
52
|
+
"tvw-text-cw-primary",
|
|
53
|
+
"tvw-shadow-sm",
|
|
54
|
+
"tvw-overflow-hidden",
|
|
55
|
+
"tvw-px-0",
|
|
56
|
+
"tvw-py-0"
|
|
57
|
+
].join(" ")
|
|
58
|
+
);
|
|
59
|
+
// Set id for idiomorph matching
|
|
60
|
+
bubble.id = `bubble-${message.id}`;
|
|
61
|
+
bubble.setAttribute("data-message-id", message.id);
|
|
62
|
+
|
|
63
|
+
// Apply bubble-level styles
|
|
64
|
+
if (toolCallConfig.backgroundColor) {
|
|
65
|
+
bubble.style.backgroundColor = toolCallConfig.backgroundColor;
|
|
66
|
+
}
|
|
67
|
+
if (toolCallConfig.borderColor) {
|
|
68
|
+
bubble.style.borderColor = toolCallConfig.borderColor;
|
|
69
|
+
}
|
|
70
|
+
if (toolCallConfig.borderWidth) {
|
|
71
|
+
bubble.style.borderWidth = toolCallConfig.borderWidth;
|
|
72
|
+
}
|
|
73
|
+
if (toolCallConfig.borderRadius) {
|
|
74
|
+
bubble.style.borderRadius = toolCallConfig.borderRadius;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (!tool) {
|
|
78
|
+
return bubble;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let expanded = toolExpansionState.has(message.id);
|
|
82
|
+
const header = createElement(
|
|
83
|
+
"button",
|
|
84
|
+
"tvw-flex tvw-w-full tvw-items-center tvw-justify-between tvw-gap-3 tvw-bg-transparent tvw-px-4 tvw-py-3 tvw-text-left tvw-cursor-pointer tvw-border-none"
|
|
85
|
+
) as HTMLButtonElement;
|
|
86
|
+
header.type = "button";
|
|
87
|
+
header.setAttribute("aria-expanded", expanded ? "true" : "false");
|
|
88
|
+
header.setAttribute("data-expand-header", "true");
|
|
89
|
+
header.setAttribute("data-bubble-type", "tool");
|
|
90
|
+
|
|
91
|
+
// Apply header styles
|
|
92
|
+
if (toolCallConfig.headerBackgroundColor) {
|
|
93
|
+
header.style.backgroundColor = toolCallConfig.headerBackgroundColor;
|
|
94
|
+
}
|
|
95
|
+
if (toolCallConfig.headerPaddingX) {
|
|
96
|
+
header.style.paddingLeft = toolCallConfig.headerPaddingX;
|
|
97
|
+
header.style.paddingRight = toolCallConfig.headerPaddingX;
|
|
98
|
+
}
|
|
99
|
+
if (toolCallConfig.headerPaddingY) {
|
|
100
|
+
header.style.paddingTop = toolCallConfig.headerPaddingY;
|
|
101
|
+
header.style.paddingBottom = toolCallConfig.headerPaddingY;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
const headerContent = createElement("div", "tvw-flex tvw-flex-col tvw-text-left");
|
|
105
|
+
const title = createElement("span", "tvw-text-xs tvw-text-cw-primary");
|
|
106
|
+
if (toolCallConfig.headerTextColor) {
|
|
107
|
+
title.style.color = toolCallConfig.headerTextColor;
|
|
108
|
+
}
|
|
109
|
+
title.textContent = describeToolTitle(tool);
|
|
110
|
+
headerContent.appendChild(title);
|
|
111
|
+
|
|
112
|
+
const toggleIcon = createElement("div", "tvw-flex tvw-items-center");
|
|
113
|
+
const iconColor = toolCallConfig.toggleTextColor || toolCallConfig.headerTextColor || "currentColor";
|
|
114
|
+
const chevronIcon = renderLucideIcon(expanded ? "chevron-up" : "chevron-down", 16, iconColor, 2);
|
|
115
|
+
if (chevronIcon) {
|
|
116
|
+
toggleIcon.appendChild(chevronIcon);
|
|
117
|
+
} else {
|
|
118
|
+
// Fallback to text if icon fails
|
|
119
|
+
toggleIcon.textContent = expanded ? "Hide" : "Show";
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const headerMeta = createElement("div", "tvw-flex tvw-items-center tvw-gap-2 tvw-ml-auto");
|
|
123
|
+
headerMeta.append(toggleIcon);
|
|
124
|
+
|
|
125
|
+
header.append(headerContent, headerMeta);
|
|
126
|
+
|
|
127
|
+
const content = createElement(
|
|
128
|
+
"div",
|
|
129
|
+
"tvw-border-t tvw-border-gray-200 tvw-bg-gray-50 tvw-space-y-3 tvw-px-4 tvw-py-3"
|
|
130
|
+
);
|
|
131
|
+
content.style.display = expanded ? "" : "none";
|
|
132
|
+
|
|
133
|
+
// Apply content styles
|
|
134
|
+
if (toolCallConfig.contentBackgroundColor) {
|
|
135
|
+
content.style.backgroundColor = toolCallConfig.contentBackgroundColor;
|
|
136
|
+
}
|
|
137
|
+
if (toolCallConfig.contentTextColor) {
|
|
138
|
+
content.style.color = toolCallConfig.contentTextColor;
|
|
139
|
+
}
|
|
140
|
+
if (toolCallConfig.contentPaddingX) {
|
|
141
|
+
content.style.paddingLeft = toolCallConfig.contentPaddingX;
|
|
142
|
+
content.style.paddingRight = toolCallConfig.contentPaddingX;
|
|
143
|
+
}
|
|
144
|
+
if (toolCallConfig.contentPaddingY) {
|
|
145
|
+
content.style.paddingTop = toolCallConfig.contentPaddingY;
|
|
146
|
+
content.style.paddingBottom = toolCallConfig.contentPaddingY;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Add tool name at the top of content
|
|
150
|
+
if (tool.name) {
|
|
151
|
+
const toolName = createElement("div", "tvw-text-xs tvw-text-cw-muted tvw-italic");
|
|
152
|
+
if (toolCallConfig.contentTextColor) {
|
|
153
|
+
toolName.style.color = toolCallConfig.contentTextColor;
|
|
154
|
+
} else if (toolCallConfig.headerTextColor) {
|
|
155
|
+
toolName.style.color = toolCallConfig.headerTextColor;
|
|
156
|
+
}
|
|
157
|
+
toolName.textContent = tool.name;
|
|
158
|
+
content.appendChild(toolName);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (tool.args !== undefined) {
|
|
162
|
+
const argsBlock = createElement("div", "tvw-space-y-1");
|
|
163
|
+
const argsLabel = createElement(
|
|
164
|
+
"div",
|
|
165
|
+
"tvw-text-xs tvw-text-cw-muted"
|
|
166
|
+
);
|
|
167
|
+
if (toolCallConfig.labelTextColor) {
|
|
168
|
+
argsLabel.style.color = toolCallConfig.labelTextColor;
|
|
169
|
+
}
|
|
170
|
+
argsLabel.textContent = "Arguments";
|
|
171
|
+
const argsPre = createElement(
|
|
172
|
+
"pre",
|
|
173
|
+
"tvw-max-h-48 tvw-overflow-auto tvw-whitespace-pre-wrap tvw-rounded-lg tvw-border tvw-border-gray-100 tvw-bg-white tvw-px-3 tvw-py-2 tvw-text-xs tvw-text-cw-primary"
|
|
174
|
+
);
|
|
175
|
+
// Ensure font size matches header text (0.75rem / 12px)
|
|
176
|
+
argsPre.style.fontSize = "0.75rem";
|
|
177
|
+
argsPre.style.lineHeight = "1rem";
|
|
178
|
+
if (toolCallConfig.codeBlockBackgroundColor) {
|
|
179
|
+
argsPre.style.backgroundColor = toolCallConfig.codeBlockBackgroundColor;
|
|
180
|
+
}
|
|
181
|
+
if (toolCallConfig.codeBlockBorderColor) {
|
|
182
|
+
argsPre.style.borderColor = toolCallConfig.codeBlockBorderColor;
|
|
183
|
+
}
|
|
184
|
+
if (toolCallConfig.codeBlockTextColor) {
|
|
185
|
+
argsPre.style.color = toolCallConfig.codeBlockTextColor;
|
|
186
|
+
}
|
|
187
|
+
argsPre.textContent = formatUnknownValue(tool.args);
|
|
188
|
+
argsBlock.append(argsLabel, argsPre);
|
|
189
|
+
content.appendChild(argsBlock);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
if (tool.chunks && tool.chunks.length) {
|
|
193
|
+
const logsBlock = createElement("div", "tvw-space-y-1");
|
|
194
|
+
const logsLabel = createElement(
|
|
195
|
+
"div",
|
|
196
|
+
"tvw-text-xs tvw-text-cw-muted"
|
|
197
|
+
);
|
|
198
|
+
if (toolCallConfig.labelTextColor) {
|
|
199
|
+
logsLabel.style.color = toolCallConfig.labelTextColor;
|
|
200
|
+
}
|
|
201
|
+
logsLabel.textContent = "Activity";
|
|
202
|
+
const logsPre = createElement(
|
|
203
|
+
"pre",
|
|
204
|
+
"tvw-max-h-48 tvw-overflow-auto tvw-whitespace-pre-wrap tvw-rounded-lg tvw-border tvw-border-gray-100 tvw-bg-white tvw-px-3 tvw-py-2 tvw-text-xs tvw-text-cw-primary"
|
|
205
|
+
);
|
|
206
|
+
// Ensure font size matches header text (0.75rem / 12px)
|
|
207
|
+
logsPre.style.fontSize = "0.75rem";
|
|
208
|
+
logsPre.style.lineHeight = "1rem";
|
|
209
|
+
if (toolCallConfig.codeBlockBackgroundColor) {
|
|
210
|
+
logsPre.style.backgroundColor = toolCallConfig.codeBlockBackgroundColor;
|
|
211
|
+
}
|
|
212
|
+
if (toolCallConfig.codeBlockBorderColor) {
|
|
213
|
+
logsPre.style.borderColor = toolCallConfig.codeBlockBorderColor;
|
|
214
|
+
}
|
|
215
|
+
if (toolCallConfig.codeBlockTextColor) {
|
|
216
|
+
logsPre.style.color = toolCallConfig.codeBlockTextColor;
|
|
217
|
+
}
|
|
218
|
+
logsPre.textContent = tool.chunks.join("\n");
|
|
219
|
+
logsBlock.append(logsLabel, logsPre);
|
|
220
|
+
content.appendChild(logsBlock);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
if (tool.status === "complete" && tool.result !== undefined) {
|
|
224
|
+
const resultBlock = createElement("div", "tvw-space-y-1");
|
|
225
|
+
const resultLabel = createElement(
|
|
226
|
+
"div",
|
|
227
|
+
"tvw-text-xs tvw-text-cw-muted"
|
|
228
|
+
);
|
|
229
|
+
if (toolCallConfig.labelTextColor) {
|
|
230
|
+
resultLabel.style.color = toolCallConfig.labelTextColor;
|
|
231
|
+
}
|
|
232
|
+
resultLabel.textContent = "Result";
|
|
233
|
+
const resultPre = createElement(
|
|
234
|
+
"pre",
|
|
235
|
+
"tvw-max-h-48 tvw-overflow-auto tvw-whitespace-pre-wrap tvw-rounded-lg tvw-border tvw-border-gray-100 tvw-bg-white tvw-px-3 tvw-py-2 tvw-text-xs tvw-text-cw-primary"
|
|
236
|
+
);
|
|
237
|
+
// Ensure font size matches header text (0.75rem / 12px)
|
|
238
|
+
resultPre.style.fontSize = "0.75rem";
|
|
239
|
+
resultPre.style.lineHeight = "1rem";
|
|
240
|
+
if (toolCallConfig.codeBlockBackgroundColor) {
|
|
241
|
+
resultPre.style.backgroundColor = toolCallConfig.codeBlockBackgroundColor;
|
|
242
|
+
}
|
|
243
|
+
if (toolCallConfig.codeBlockBorderColor) {
|
|
244
|
+
resultPre.style.borderColor = toolCallConfig.codeBlockBorderColor;
|
|
245
|
+
}
|
|
246
|
+
if (toolCallConfig.codeBlockTextColor) {
|
|
247
|
+
resultPre.style.color = toolCallConfig.codeBlockTextColor;
|
|
248
|
+
}
|
|
249
|
+
resultPre.textContent = formatUnknownValue(tool.result);
|
|
250
|
+
resultBlock.append(resultLabel, resultPre);
|
|
251
|
+
content.appendChild(resultBlock);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
if (tool.status === "complete" && typeof tool.duration === "number") {
|
|
255
|
+
const duration = createElement(
|
|
256
|
+
"div",
|
|
257
|
+
"tvw-text-xs tvw-text-cw-muted"
|
|
258
|
+
);
|
|
259
|
+
if (toolCallConfig.contentTextColor) {
|
|
260
|
+
duration.style.color = toolCallConfig.contentTextColor;
|
|
261
|
+
}
|
|
262
|
+
duration.textContent = `Duration: ${tool.duration}ms`;
|
|
263
|
+
content.appendChild(duration);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
const applyToolExpansion = () => {
|
|
267
|
+
header.setAttribute("aria-expanded", expanded ? "true" : "false");
|
|
268
|
+
// Update chevron icon
|
|
269
|
+
toggleIcon.innerHTML = "";
|
|
270
|
+
const iconColor = toolCallConfig.toggleTextColor || toolCallConfig.headerTextColor || "currentColor";
|
|
271
|
+
const chevronIcon = renderLucideIcon(expanded ? "chevron-up" : "chevron-down", 16, iconColor, 2);
|
|
272
|
+
if (chevronIcon) {
|
|
273
|
+
toggleIcon.appendChild(chevronIcon);
|
|
274
|
+
} else {
|
|
275
|
+
// Fallback to text if icon fails
|
|
276
|
+
toggleIcon.textContent = expanded ? "Hide" : "Show";
|
|
277
|
+
}
|
|
278
|
+
content.style.display = expanded ? "" : "none";
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
applyToolExpansion();
|
|
282
|
+
|
|
283
|
+
bubble.append(header, content);
|
|
284
|
+
return bubble;
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
|
package/src/defaults.ts
ADDED
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
import type { AgentWidgetConfig, AgentWidgetTheme } from "./types";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Default light theme colors
|
|
5
|
+
*/
|
|
6
|
+
export const DEFAULT_LIGHT_THEME: AgentWidgetTheme = {
|
|
7
|
+
primary: "#111827",
|
|
8
|
+
accent: "#1d4ed8",
|
|
9
|
+
surface: "#ffffff",
|
|
10
|
+
muted: "#6b7280",
|
|
11
|
+
container: "#f8fafc",
|
|
12
|
+
border: "#f1f5f9",
|
|
13
|
+
divider: "#f1f5f9",
|
|
14
|
+
messageBorder: "#f1f5f9",
|
|
15
|
+
inputBackground: "#ffffff",
|
|
16
|
+
callToAction: "#000000",
|
|
17
|
+
callToActionBackground: "#ffffff",
|
|
18
|
+
sendButtonBackgroundColor: "#111827",
|
|
19
|
+
sendButtonTextColor: "#ffffff",
|
|
20
|
+
sendButtonBorderColor: "#60a5fa",
|
|
21
|
+
closeButtonColor: "#6b7280",
|
|
22
|
+
closeButtonBackgroundColor: "transparent",
|
|
23
|
+
closeButtonBorderColor: "",
|
|
24
|
+
clearChatIconColor: "#6b7280",
|
|
25
|
+
clearChatBackgroundColor: "transparent",
|
|
26
|
+
clearChatBorderColor: "transparent",
|
|
27
|
+
micIconColor: "#111827",
|
|
28
|
+
micBackgroundColor: "transparent",
|
|
29
|
+
micBorderColor: "transparent",
|
|
30
|
+
recordingIconColor: "#ffffff",
|
|
31
|
+
recordingBackgroundColor: "#ef4444",
|
|
32
|
+
recordingBorderColor: "transparent",
|
|
33
|
+
inputFontFamily: "sans-serif",
|
|
34
|
+
inputFontWeight: "400",
|
|
35
|
+
radiusSm: "0.75rem",
|
|
36
|
+
radiusMd: "1rem",
|
|
37
|
+
radiusLg: "1.5rem",
|
|
38
|
+
launcherRadius: "9999px",
|
|
39
|
+
buttonRadius: "9999px",
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Default dark theme colors
|
|
44
|
+
*/
|
|
45
|
+
export const DEFAULT_DARK_THEME: AgentWidgetTheme = {
|
|
46
|
+
primary: "#f9fafb",
|
|
47
|
+
accent: "#3b82f6",
|
|
48
|
+
surface: "#1f2937",
|
|
49
|
+
muted: "#9ca3af",
|
|
50
|
+
container: "#111827",
|
|
51
|
+
border: "#374151",
|
|
52
|
+
divider: "#374151",
|
|
53
|
+
messageBorder: "#374151",
|
|
54
|
+
inputBackground: "#111827",
|
|
55
|
+
callToAction: "#ffffff",
|
|
56
|
+
callToActionBackground: "#374151",
|
|
57
|
+
sendButtonBackgroundColor: "#3b82f6",
|
|
58
|
+
sendButtonTextColor: "#ffffff",
|
|
59
|
+
sendButtonBorderColor: "#60a5fa",
|
|
60
|
+
closeButtonColor: "#9ca3af",
|
|
61
|
+
closeButtonBackgroundColor: "transparent",
|
|
62
|
+
closeButtonBorderColor: "",
|
|
63
|
+
clearChatIconColor: "#9ca3af",
|
|
64
|
+
clearChatBackgroundColor: "transparent",
|
|
65
|
+
clearChatBorderColor: "transparent",
|
|
66
|
+
micIconColor: "#f9fafb",
|
|
67
|
+
micBackgroundColor: "transparent",
|
|
68
|
+
micBorderColor: "transparent",
|
|
69
|
+
recordingIconColor: "#ffffff",
|
|
70
|
+
recordingBackgroundColor: "#ef4444",
|
|
71
|
+
recordingBorderColor: "transparent",
|
|
72
|
+
inputFontFamily: "sans-serif",
|
|
73
|
+
inputFontWeight: "400",
|
|
74
|
+
radiusSm: "0.75rem",
|
|
75
|
+
radiusMd: "1rem",
|
|
76
|
+
radiusLg: "1.5rem",
|
|
77
|
+
launcherRadius: "9999px",
|
|
78
|
+
buttonRadius: "9999px",
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Default widget configuration
|
|
83
|
+
* Single source of truth for all default values
|
|
84
|
+
*/
|
|
85
|
+
export const DEFAULT_WIDGET_CONFIG: Partial<AgentWidgetConfig> = {
|
|
86
|
+
apiUrl: "http://localhost:43111/api/chat/dispatch",
|
|
87
|
+
// Client token mode defaults (optional, only used when clientToken is set)
|
|
88
|
+
clientToken: undefined,
|
|
89
|
+
theme: DEFAULT_LIGHT_THEME,
|
|
90
|
+
darkTheme: DEFAULT_DARK_THEME,
|
|
91
|
+
colorScheme: "light",
|
|
92
|
+
launcher: {
|
|
93
|
+
enabled: true,
|
|
94
|
+
title: "Chat Assistant",
|
|
95
|
+
subtitle: "Here to help you get answers fast",
|
|
96
|
+
agentIconText: "💬",
|
|
97
|
+
position: "bottom-right",
|
|
98
|
+
width: "min(400px, calc(100vw - 24px))",
|
|
99
|
+
heightOffset: 0,
|
|
100
|
+
autoExpand: false,
|
|
101
|
+
callToActionIconHidden: false,
|
|
102
|
+
agentIconSize: "40px",
|
|
103
|
+
headerIconSize: "40px",
|
|
104
|
+
closeButtonSize: "32px",
|
|
105
|
+
callToActionIconName: "arrow-up-right",
|
|
106
|
+
callToActionIconText: "",
|
|
107
|
+
callToActionIconSize: "32px",
|
|
108
|
+
callToActionIconPadding: "5px",
|
|
109
|
+
callToActionIconColor: "#000000",
|
|
110
|
+
callToActionIconBackgroundColor: "#ffffff",
|
|
111
|
+
closeButtonColor: "#6b7280",
|
|
112
|
+
closeButtonBackgroundColor: "transparent",
|
|
113
|
+
clearChat: {
|
|
114
|
+
iconColor: "#6b7280",
|
|
115
|
+
backgroundColor: "transparent",
|
|
116
|
+
borderColor: "transparent",
|
|
117
|
+
enabled: true,
|
|
118
|
+
placement: "inline",
|
|
119
|
+
iconName: "refresh-cw",
|
|
120
|
+
size: "32px",
|
|
121
|
+
showTooltip: true,
|
|
122
|
+
tooltipText: "Clear chat",
|
|
123
|
+
paddingX: "0px",
|
|
124
|
+
paddingY: "0px",
|
|
125
|
+
},
|
|
126
|
+
headerIconHidden: false,
|
|
127
|
+
border: "1px solid #e5e7eb",
|
|
128
|
+
shadow: "0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -4px rgba(0, 0, 0, 0.1)",
|
|
129
|
+
},
|
|
130
|
+
copy: {
|
|
131
|
+
welcomeTitle: "Hello 👋",
|
|
132
|
+
welcomeSubtitle: "Ask anything about your account or products.",
|
|
133
|
+
inputPlaceholder: "How can I help...",
|
|
134
|
+
sendButtonLabel: "Send",
|
|
135
|
+
},
|
|
136
|
+
sendButton: {
|
|
137
|
+
borderWidth: "0px",
|
|
138
|
+
paddingX: "12px",
|
|
139
|
+
paddingY: "10px",
|
|
140
|
+
backgroundColor: "#111827",
|
|
141
|
+
textColor: "#ffffff",
|
|
142
|
+
borderColor: "#60a5fa",
|
|
143
|
+
useIcon: true,
|
|
144
|
+
iconText: "↑",
|
|
145
|
+
size: "40px",
|
|
146
|
+
showTooltip: true,
|
|
147
|
+
tooltipText: "Send message",
|
|
148
|
+
iconName: "send",
|
|
149
|
+
},
|
|
150
|
+
statusIndicator: {
|
|
151
|
+
visible: true,
|
|
152
|
+
idleText: "Online",
|
|
153
|
+
connectingText: "Connecting…",
|
|
154
|
+
connectedText: "Streaming…",
|
|
155
|
+
errorText: "Offline",
|
|
156
|
+
},
|
|
157
|
+
voiceRecognition: {
|
|
158
|
+
enabled: true,
|
|
159
|
+
pauseDuration: 2000,
|
|
160
|
+
iconName: "mic",
|
|
161
|
+
iconSize: "39px",
|
|
162
|
+
borderWidth: "0px",
|
|
163
|
+
paddingX: "9px",
|
|
164
|
+
paddingY: "14px",
|
|
165
|
+
iconColor: "#111827",
|
|
166
|
+
backgroundColor: "transparent",
|
|
167
|
+
borderColor: "transparent",
|
|
168
|
+
recordingIconColor: "#ffffff",
|
|
169
|
+
recordingBackgroundColor: "#ef4444",
|
|
170
|
+
recordingBorderColor: "transparent",
|
|
171
|
+
showTooltip: true,
|
|
172
|
+
tooltipText: "Start voice recognition",
|
|
173
|
+
},
|
|
174
|
+
features: {
|
|
175
|
+
showReasoning: true,
|
|
176
|
+
showToolCalls: true,
|
|
177
|
+
},
|
|
178
|
+
suggestionChips: [
|
|
179
|
+
"What can you help me with?",
|
|
180
|
+
"Tell me about your features",
|
|
181
|
+
"How does this work?",
|
|
182
|
+
],
|
|
183
|
+
suggestionChipsConfig: {
|
|
184
|
+
fontFamily: "sans-serif",
|
|
185
|
+
fontWeight: "500",
|
|
186
|
+
paddingX: "12px",
|
|
187
|
+
paddingY: "6px",
|
|
188
|
+
},
|
|
189
|
+
layout: {
|
|
190
|
+
header: {
|
|
191
|
+
layout: "default",
|
|
192
|
+
showIcon: true,
|
|
193
|
+
showTitle: true,
|
|
194
|
+
showSubtitle: true,
|
|
195
|
+
showCloseButton: true,
|
|
196
|
+
showClearChat: true,
|
|
197
|
+
},
|
|
198
|
+
messages: {
|
|
199
|
+
layout: "bubble",
|
|
200
|
+
avatar: {
|
|
201
|
+
show: false,
|
|
202
|
+
position: "left",
|
|
203
|
+
},
|
|
204
|
+
timestamp: {
|
|
205
|
+
show: false,
|
|
206
|
+
position: "below",
|
|
207
|
+
},
|
|
208
|
+
groupConsecutive: false,
|
|
209
|
+
},
|
|
210
|
+
slots: {},
|
|
211
|
+
},
|
|
212
|
+
markdown: {
|
|
213
|
+
options: {
|
|
214
|
+
gfm: true,
|
|
215
|
+
breaks: true,
|
|
216
|
+
},
|
|
217
|
+
disableDefaultStyles: false,
|
|
218
|
+
},
|
|
219
|
+
messageActions: {
|
|
220
|
+
enabled: true,
|
|
221
|
+
showCopy: true,
|
|
222
|
+
showUpvote: false, // Requires backend - disabled by default
|
|
223
|
+
showDownvote: false, // Requires backend - disabled by default
|
|
224
|
+
visibility: "hover",
|
|
225
|
+
align: "right",
|
|
226
|
+
layout: "pill-inside",
|
|
227
|
+
},
|
|
228
|
+
debug: false,
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Helper to deep merge user config with defaults
|
|
233
|
+
* This ensures all default values are present while allowing selective overrides
|
|
234
|
+
*/
|
|
235
|
+
export function mergeWithDefaults(
|
|
236
|
+
config?: Partial<AgentWidgetConfig>
|
|
237
|
+
): Partial<AgentWidgetConfig> {
|
|
238
|
+
if (!config) return DEFAULT_WIDGET_CONFIG;
|
|
239
|
+
|
|
240
|
+
return {
|
|
241
|
+
...DEFAULT_WIDGET_CONFIG,
|
|
242
|
+
...config,
|
|
243
|
+
theme: {
|
|
244
|
+
...DEFAULT_WIDGET_CONFIG.theme,
|
|
245
|
+
...config.theme,
|
|
246
|
+
},
|
|
247
|
+
darkTheme: {
|
|
248
|
+
...DEFAULT_WIDGET_CONFIG.darkTheme,
|
|
249
|
+
...config.darkTheme,
|
|
250
|
+
},
|
|
251
|
+
launcher: {
|
|
252
|
+
...DEFAULT_WIDGET_CONFIG.launcher,
|
|
253
|
+
...config.launcher,
|
|
254
|
+
clearChat: {
|
|
255
|
+
...DEFAULT_WIDGET_CONFIG.launcher?.clearChat,
|
|
256
|
+
...config.launcher?.clearChat,
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
copy: {
|
|
260
|
+
...DEFAULT_WIDGET_CONFIG.copy,
|
|
261
|
+
...config.copy,
|
|
262
|
+
},
|
|
263
|
+
sendButton: {
|
|
264
|
+
...DEFAULT_WIDGET_CONFIG.sendButton,
|
|
265
|
+
...config.sendButton,
|
|
266
|
+
},
|
|
267
|
+
statusIndicator: {
|
|
268
|
+
...DEFAULT_WIDGET_CONFIG.statusIndicator,
|
|
269
|
+
...config.statusIndicator,
|
|
270
|
+
},
|
|
271
|
+
voiceRecognition: {
|
|
272
|
+
...DEFAULT_WIDGET_CONFIG.voiceRecognition,
|
|
273
|
+
...config.voiceRecognition,
|
|
274
|
+
},
|
|
275
|
+
features: {
|
|
276
|
+
...DEFAULT_WIDGET_CONFIG.features,
|
|
277
|
+
...config.features,
|
|
278
|
+
},
|
|
279
|
+
suggestionChips: config.suggestionChips ?? DEFAULT_WIDGET_CONFIG.suggestionChips,
|
|
280
|
+
suggestionChipsConfig: {
|
|
281
|
+
...DEFAULT_WIDGET_CONFIG.suggestionChipsConfig,
|
|
282
|
+
...config.suggestionChipsConfig,
|
|
283
|
+
},
|
|
284
|
+
layout: {
|
|
285
|
+
...DEFAULT_WIDGET_CONFIG.layout,
|
|
286
|
+
...config.layout,
|
|
287
|
+
header: {
|
|
288
|
+
...DEFAULT_WIDGET_CONFIG.layout?.header,
|
|
289
|
+
...config.layout?.header,
|
|
290
|
+
},
|
|
291
|
+
messages: {
|
|
292
|
+
...DEFAULT_WIDGET_CONFIG.layout?.messages,
|
|
293
|
+
...config.layout?.messages,
|
|
294
|
+
avatar: {
|
|
295
|
+
...DEFAULT_WIDGET_CONFIG.layout?.messages?.avatar,
|
|
296
|
+
...config.layout?.messages?.avatar,
|
|
297
|
+
},
|
|
298
|
+
timestamp: {
|
|
299
|
+
...DEFAULT_WIDGET_CONFIG.layout?.messages?.timestamp,
|
|
300
|
+
...config.layout?.messages?.timestamp,
|
|
301
|
+
},
|
|
302
|
+
},
|
|
303
|
+
slots: {
|
|
304
|
+
...DEFAULT_WIDGET_CONFIG.layout?.slots,
|
|
305
|
+
...config.layout?.slots,
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
markdown: {
|
|
309
|
+
...DEFAULT_WIDGET_CONFIG.markdown,
|
|
310
|
+
...config.markdown,
|
|
311
|
+
options: {
|
|
312
|
+
...DEFAULT_WIDGET_CONFIG.markdown?.options,
|
|
313
|
+
...config.markdown?.options,
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
messageActions: {
|
|
317
|
+
...DEFAULT_WIDGET_CONFIG.messageActions,
|
|
318
|
+
...config.messageActions,
|
|
319
|
+
},
|
|
320
|
+
};
|
|
321
|
+
}
|