kanha-ai 0.1.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/dist/index.cjs ADDED
@@ -0,0 +1,573 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var ReactMarkdown = require('react-markdown');
5
+ var jsxRuntime = require('react/jsx-runtime');
6
+
7
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
8
+
9
+ var ReactMarkdown__default = /*#__PURE__*/_interopDefault(ReactMarkdown);
10
+
11
+ // src/KanhaBot.tsx
12
+ var MODEL_LIB_PREFIX = "https://raw.githubusercontent.com/mlc-ai/binary-mlc-llm-libs/main/web-llm-models/v0_2_80";
13
+ var WASM_BY_SIZE = {
14
+ small: `${MODEL_LIB_PREFIX}/Qwen3-0.6B-q4f16_1-ctx4k_cs1k-webgpu.wasm`,
15
+ medium: `${MODEL_LIB_PREFIX}/Qwen3-1.7B-q4f16_1-ctx4k_cs1k-webgpu.wasm`,
16
+ large: `${MODEL_LIB_PREFIX}/Qwen3-4B-q4f16_1-ctx4k_cs1k-webgpu.wasm`
17
+ };
18
+ function resolveModelLib(config) {
19
+ if (config.modelLib) return config.modelLib;
20
+ const size = config.modelSize ?? "small";
21
+ const lib = WASM_BY_SIZE[size];
22
+ if (!lib) throw new Error(`Unknown model size "${size}". Provide modelLib explicitly.`);
23
+ return lib;
24
+ }
25
+ function toWebLLMModelUrl(modelUrl) {
26
+ let url = modelUrl.endsWith("/") ? modelUrl.slice(0, -1) : modelUrl;
27
+ if (!url.includes("/resolve/")) {
28
+ url += "/resolve/v1";
29
+ }
30
+ return url;
31
+ }
32
+ async function checkWebGPU() {
33
+ try {
34
+ const nav = navigator;
35
+ if (!nav.gpu) return false;
36
+ const adapter = await nav.gpu.requestAdapter();
37
+ if (!adapter) return false;
38
+ const device = await adapter.requestDevice();
39
+ return !!device;
40
+ } catch {
41
+ return false;
42
+ }
43
+ }
44
+ function stripThinkTokens(text) {
45
+ let cleaned = text.replace(/<think>[\s\S]*?<\/think>/g, "");
46
+ cleaned = cleaned.replace(/<think>[\s\S]*$/g, "");
47
+ return cleaned.trimStart();
48
+ }
49
+ function useKanhaChat(config) {
50
+ const [messages, setMessages] = react.useState([]);
51
+ const [input, setInput] = react.useState("");
52
+ const [isLoading, setIsLoading] = react.useState(false);
53
+ const [isThinking, setIsThinking] = react.useState(false);
54
+ const [mode, setMode] = react.useState("detecting");
55
+ const [loadProgress, setLoadProgress] = react.useState(0);
56
+ const [error, setError] = react.useState(null);
57
+ const engineRef = react.useRef(null);
58
+ const configRef = react.useRef(config);
59
+ configRef.current = config;
60
+ const updateAssistantMessage = react.useCallback((text) => {
61
+ const cleaned = stripThinkTokens(text);
62
+ if (!cleaned) {
63
+ setIsThinking(true);
64
+ return;
65
+ }
66
+ setIsThinking(false);
67
+ setMessages((prev) => {
68
+ const msgs = [...prev];
69
+ if (msgs[msgs.length - 1]?.role === "assistant") {
70
+ msgs[msgs.length - 1] = { role: "assistant", content: cleaned };
71
+ } else {
72
+ msgs.push({ role: "assistant", content: cleaned });
73
+ }
74
+ return msgs;
75
+ });
76
+ }, []);
77
+ react.useEffect(() => {
78
+ if (typeof window === "undefined") return;
79
+ let cancelled = false;
80
+ const init = async () => {
81
+ setMode("detecting");
82
+ const hasWebGPU = await checkWebGPU();
83
+ if (!hasWebGPU) {
84
+ setMode("error");
85
+ setError("WebGPU is not supported in this browser. Try Chrome 113+ or Edge 113+.");
86
+ return;
87
+ }
88
+ if (cancelled) return;
89
+ setMode("loading");
90
+ try {
91
+ const webllm = await import('@mlc-ai/web-llm');
92
+ const modelId = "kanha-custom-model";
93
+ const modelLib = resolveModelLib(configRef.current);
94
+ const modelUrl = toWebLLMModelUrl(configRef.current.modelUrl);
95
+ const engine = await webllm.CreateMLCEngine(modelId, {
96
+ appConfig: {
97
+ model_list: [
98
+ {
99
+ model: modelUrl,
100
+ model_id: modelId,
101
+ model_lib: modelLib,
102
+ overrides: {
103
+ context_window_size: configRef.current.contextWindowSize ?? 4096
104
+ }
105
+ }
106
+ ]
107
+ },
108
+ initProgressCallback: (report) => {
109
+ if (!cancelled) setLoadProgress(Math.round(report.progress * 100));
110
+ }
111
+ });
112
+ if (cancelled) return;
113
+ engineRef.current = engine;
114
+ setMode("ready");
115
+ } catch (err) {
116
+ if (cancelled) return;
117
+ setMode("error");
118
+ setError(
119
+ err instanceof Error ? err.message : "Failed to load AI model."
120
+ );
121
+ }
122
+ };
123
+ init();
124
+ return () => {
125
+ cancelled = true;
126
+ };
127
+ }, [config.modelUrl, config.modelLib, config.modelSize]);
128
+ const send = react.useCallback(async () => {
129
+ if (!input.trim() || mode !== "ready" || isLoading || !engineRef.current) return;
130
+ const userMsg = { role: "user", content: input.trim() };
131
+ const allMessages = [...messages, userMsg];
132
+ setMessages(allMessages);
133
+ setInput("");
134
+ setIsLoading(true);
135
+ setIsThinking(true);
136
+ setError(null);
137
+ try {
138
+ const systemMessages = configRef.current.systemPrompt ? [{ role: "system", content: configRef.current.systemPrompt }] : [];
139
+ const completion = await engineRef.current.chat.completions.create({
140
+ messages: [...systemMessages, ...allMessages],
141
+ temperature: configRef.current.temperature ?? 0.7,
142
+ max_tokens: configRef.current.maxTokens ?? 1024,
143
+ stream: true
144
+ });
145
+ let text = "";
146
+ for await (const chunk of completion) {
147
+ const delta = chunk.choices[0]?.delta?.content || "";
148
+ text += delta;
149
+ updateAssistantMessage(text);
150
+ }
151
+ } catch {
152
+ setError("Failed to generate response. Please try again.");
153
+ setMessages((prev) => [
154
+ ...prev,
155
+ { role: "assistant", content: "Sorry, I encountered an error. Please try again." }
156
+ ]);
157
+ } finally {
158
+ setIsLoading(false);
159
+ setIsThinking(false);
160
+ }
161
+ }, [input, mode, isLoading, messages, updateAssistantMessage]);
162
+ const clear = react.useCallback(() => {
163
+ setMessages([]);
164
+ setError(null);
165
+ }, []);
166
+ return {
167
+ messages,
168
+ input,
169
+ setInput,
170
+ isLoading,
171
+ isThinking,
172
+ mode,
173
+ loadProgress,
174
+ error,
175
+ send,
176
+ clear
177
+ };
178
+ }
179
+
180
+ // src/styles.ts
181
+ function fabStyle(primaryColor, position) {
182
+ return {
183
+ position: "fixed",
184
+ bottom: 24,
185
+ [position === "bottom-right" ? "right" : "left"]: 24,
186
+ width: 56,
187
+ height: 56,
188
+ borderRadius: "50%",
189
+ background: primaryColor,
190
+ color: "#fff",
191
+ border: "none",
192
+ cursor: "pointer",
193
+ display: "flex",
194
+ alignItems: "center",
195
+ justifyContent: "center",
196
+ boxShadow: "0 4px 12px rgba(0,0,0,0.15)",
197
+ zIndex: 9999,
198
+ transition: "transform 0.15s ease, box-shadow 0.15s ease"
199
+ };
200
+ }
201
+ function panelStyle(position) {
202
+ return {
203
+ position: "fixed",
204
+ bottom: 96,
205
+ [position === "bottom-right" ? "right" : "left"]: 24,
206
+ width: 384,
207
+ maxWidth: "calc(100vw - 48px)",
208
+ maxHeight: "calc(100vh - 120px)",
209
+ borderRadius: 16,
210
+ overflow: "hidden",
211
+ display: "flex",
212
+ flexDirection: "column",
213
+ boxShadow: "0 8px 30px rgba(0,0,0,0.12)",
214
+ border: "1px solid #e5e7eb",
215
+ background: "#ffffff",
216
+ zIndex: 9999,
217
+ fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif'
218
+ };
219
+ }
220
+ var headerStyle = {
221
+ padding: "16px",
222
+ color: "#fff",
223
+ display: "flex",
224
+ alignItems: "center",
225
+ justifyContent: "space-between"
226
+ };
227
+ var headerTitleStyle = {
228
+ fontWeight: 600,
229
+ fontSize: 15,
230
+ margin: 0
231
+ };
232
+ var headerSubtitleStyle = {
233
+ fontSize: 12,
234
+ opacity: 0.85,
235
+ margin: "4px 0 0"
236
+ };
237
+ var messagesContainerStyle = {
238
+ flex: 1,
239
+ overflowY: "auto",
240
+ padding: 16,
241
+ display: "flex",
242
+ flexDirection: "column",
243
+ gap: 12,
244
+ minHeight: 300,
245
+ maxHeight: 384,
246
+ background: "#fafafa"
247
+ };
248
+ var emptyStateStyle = {
249
+ display: "flex",
250
+ flexDirection: "column",
251
+ alignItems: "center",
252
+ justifyContent: "center",
253
+ height: "100%",
254
+ textAlign: "center",
255
+ color: "#6b7280",
256
+ fontSize: 14,
257
+ padding: 16
258
+ };
259
+ function userBubbleStyle(primaryColor) {
260
+ return {
261
+ maxWidth: "80%",
262
+ padding: "8px 14px",
263
+ borderRadius: 16,
264
+ background: primaryColor,
265
+ color: "#fff",
266
+ fontSize: 14,
267
+ lineHeight: 1.5,
268
+ alignSelf: "flex-end",
269
+ wordBreak: "break-word"
270
+ };
271
+ }
272
+ var assistantBubbleStyle = {
273
+ maxWidth: "80%",
274
+ padding: "8px 14px",
275
+ borderRadius: 16,
276
+ background: "#fff",
277
+ color: "#1f2937",
278
+ fontSize: 14,
279
+ lineHeight: 1.5,
280
+ border: "1px solid #e5e7eb",
281
+ alignSelf: "flex-start",
282
+ wordBreak: "break-word"
283
+ };
284
+ var inputBarStyle = {
285
+ display: "flex",
286
+ gap: 8,
287
+ padding: "12px 16px",
288
+ borderTop: "1px solid #e5e7eb",
289
+ background: "#fff"
290
+ };
291
+ var textareaStyle = {
292
+ flex: 1,
293
+ padding: "8px 12px",
294
+ border: "1px solid #e5e7eb",
295
+ borderRadius: 10,
296
+ fontSize: 14,
297
+ resize: "none",
298
+ overflow: "hidden",
299
+ outline: "none",
300
+ fontFamily: "inherit",
301
+ minHeight: 40,
302
+ maxHeight: 120,
303
+ lineHeight: 1.5
304
+ };
305
+ function sendButtonStyle(primaryColor) {
306
+ return {
307
+ padding: "8px 14px",
308
+ background: primaryColor,
309
+ color: "#fff",
310
+ border: "none",
311
+ borderRadius: 10,
312
+ cursor: "pointer",
313
+ display: "flex",
314
+ alignItems: "center",
315
+ justifyContent: "center",
316
+ flexShrink: 0,
317
+ transition: "opacity 0.15s ease"
318
+ };
319
+ }
320
+ var iconButtonStyle = {
321
+ background: "none",
322
+ border: "none",
323
+ color: "inherit",
324
+ cursor: "pointer",
325
+ padding: 4,
326
+ borderRadius: 8,
327
+ display: "flex",
328
+ alignItems: "center",
329
+ justifyContent: "center",
330
+ opacity: 0.8,
331
+ transition: "opacity 0.15s ease"
332
+ };
333
+ function suggestionButtonStyle(primaryColor) {
334
+ return {
335
+ fontSize: 13,
336
+ padding: "8px 12px",
337
+ borderRadius: 10,
338
+ border: "1px solid #e5e7eb",
339
+ background: "#fff",
340
+ color: "#374151",
341
+ cursor: "pointer",
342
+ textAlign: "left",
343
+ width: "100%",
344
+ transition: "border-color 0.15s ease"
345
+ // hover handled inline
346
+ };
347
+ }
348
+ var progressBarContainer = {
349
+ width: "60%",
350
+ height: 4,
351
+ borderRadius: 2,
352
+ background: "rgba(255,255,255,0.3)",
353
+ marginTop: 8,
354
+ overflow: "hidden"
355
+ };
356
+ function progressBarFill(progress, primaryColor) {
357
+ return {
358
+ width: `${progress}%`,
359
+ height: "100%",
360
+ borderRadius: 2,
361
+ background: primaryColor,
362
+ transition: "width 0.3s ease"
363
+ };
364
+ }
365
+ var ChatIcon = () => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "24", height: "24", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" }) });
366
+ var CloseIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
367
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
368
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
369
+ ] });
370
+ var SendIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
371
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "22", y1: "2", x2: "11", y2: "13" }),
372
+ /* @__PURE__ */ jsxRuntime.jsx("polygon", { points: "22 2 15 22 11 13 2 9 22 2" })
373
+ ] });
374
+ var TrashIcon = () => /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
375
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "3 6 5 6 21 6" }),
376
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2" })
377
+ ] });
378
+ var Spinner = ({ size = 18 }) => /* @__PURE__ */ jsxRuntime.jsx("svg", { width: size, height: size, viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", style: { animation: "kanha-spin 1s linear infinite" }, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 12a9 9 0 1 1-6.219-8.56" }) });
379
+ var spinKeyframes = `@keyframes kanha-spin { to { transform: rotate(360deg); } }`;
380
+ var bounceKeyframes = `
381
+ @keyframes kanha-bounce {
382
+ 0%, 80%, 100% { transform: translateY(0); }
383
+ 40% { transform: translateY(-4px); }
384
+ }`;
385
+ function ThinkingDots() {
386
+ const dotStyle = (delay) => ({
387
+ width: 6,
388
+ height: 6,
389
+ borderRadius: "50%",
390
+ background: "#9ca3af",
391
+ animation: `kanha-bounce 1.2s ease-in-out ${delay}ms infinite`
392
+ });
393
+ return /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "flex", gap: 3, alignItems: "center" }, children: [
394
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: dotStyle(0) }),
395
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: dotStyle(150) }),
396
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: dotStyle(300) }),
397
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { fontSize: 12, color: "#9ca3af", marginLeft: 6 }, children: "Thinking" })
398
+ ] });
399
+ }
400
+ function KanhaBot({
401
+ modelUrl,
402
+ modelLib,
403
+ modelSize,
404
+ systemPrompt,
405
+ temperature,
406
+ maxTokens,
407
+ contextWindowSize,
408
+ botName = "AI Assistant",
409
+ welcomeMessage = "Ask me anything!",
410
+ suggestions = [],
411
+ theme = {}
412
+ }) {
413
+ const primaryColor = theme.primaryColor ?? "#0d9488";
414
+ const position = theme.position ?? "bottom-right";
415
+ const {
416
+ messages,
417
+ input,
418
+ setInput,
419
+ isLoading,
420
+ isThinking,
421
+ mode,
422
+ loadProgress,
423
+ error,
424
+ send,
425
+ clear
426
+ } = useKanhaChat({
427
+ modelUrl,
428
+ modelLib,
429
+ modelSize,
430
+ systemPrompt,
431
+ temperature,
432
+ maxTokens,
433
+ contextWindowSize
434
+ });
435
+ const [isOpen, setIsOpen] = react.useState(false);
436
+ const messagesEndRef = react.useRef(null);
437
+ const textareaRef = react.useRef(null);
438
+ react.useEffect(() => {
439
+ messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
440
+ }, [messages]);
441
+ react.useEffect(() => {
442
+ if (textareaRef.current) {
443
+ textareaRef.current.style.height = "auto";
444
+ textareaRef.current.style.height = Math.min(textareaRef.current.scrollHeight, 120) + "px";
445
+ }
446
+ }, [input]);
447
+ const handleKeyPress = (e) => {
448
+ if (e.key === "Enter" && !e.shiftKey) {
449
+ e.preventDefault();
450
+ send();
451
+ }
452
+ };
453
+ const isReady = mode === "ready";
454
+ return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
455
+ /* @__PURE__ */ jsxRuntime.jsxs("style", { children: [
456
+ spinKeyframes,
457
+ bounceKeyframes
458
+ ] }),
459
+ isOpen && /* @__PURE__ */ jsxRuntime.jsxs("div", { style: panelStyle(position), children: [
460
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { ...headerStyle, background: primaryColor }, children: [
461
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
462
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: headerTitleStyle, children: botName }),
463
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: headerSubtitleStyle, children: isReady ? welcomeMessage : mode === "loading" ? `Loading AI model (${loadProgress}%)` : mode === "error" ? "Failed to load" : "Detecting capabilities..." }),
464
+ mode === "loading" && /* @__PURE__ */ jsxRuntime.jsx("div", { style: progressBarContainer, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: progressBarFill(loadProgress, "#fff") }) })
465
+ ] }),
466
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", gap: 4 }, children: [
467
+ messages.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: clear, style: iconButtonStyle, "aria-label": "Clear chat", children: /* @__PURE__ */ jsxRuntime.jsx(TrashIcon, {}) }),
468
+ /* @__PURE__ */ jsxRuntime.jsx("button", { onClick: () => setIsOpen(false), style: iconButtonStyle, "aria-label": "Close", children: /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, {}) })
469
+ ] })
470
+ ] }),
471
+ error && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { padding: "10px 16px", background: "#fef2f2", borderBottom: "1px solid #fecaca", fontSize: 13, color: "#b91c1c" }, children: error }),
472
+ /* @__PURE__ */ jsxRuntime.jsx("div", { style: messagesContainerStyle, children: messages.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { style: emptyStateStyle, children: isReady ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
473
+ /* @__PURE__ */ jsxRuntime.jsx(ChatIcon, {}),
474
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { marginTop: 12, fontWeight: 500, color: "#374151" }, children: welcomeMessage }),
475
+ suggestions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", flexDirection: "column", gap: 6, width: "100%", marginTop: 16 }, children: suggestions.map((text) => /* @__PURE__ */ jsxRuntime.jsx(
476
+ "button",
477
+ {
478
+ onClick: () => {
479
+ setInput(text);
480
+ setTimeout(send, 0);
481
+ },
482
+ style: suggestionButtonStyle(),
483
+ onMouseEnter: (e) => {
484
+ e.target.style.borderColor = primaryColor;
485
+ },
486
+ onMouseLeave: (e) => {
487
+ e.target.style.borderColor = "#e5e7eb";
488
+ },
489
+ children: text
490
+ },
491
+ text
492
+ )) })
493
+ ] }) : mode === "loading" ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
494
+ /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 32 }),
495
+ /* @__PURE__ */ jsxRuntime.jsxs("p", { style: { marginTop: 8 }, children: [
496
+ "Loading AI model (",
497
+ loadProgress,
498
+ "%)"
499
+ ] }),
500
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { fontSize: 12, marginTop: 4 }, children: "First load takes about a minute" })
501
+ ] }) : mode === "error" ? /* @__PURE__ */ jsxRuntime.jsx("p", { children: error }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
502
+ /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 32 }),
503
+ /* @__PURE__ */ jsxRuntime.jsx("p", { style: { marginTop: 8 }, children: "Detecting browser capabilities..." })
504
+ ] }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
505
+ messages.map((msg, i) => /* @__PURE__ */ jsxRuntime.jsx(
506
+ "div",
507
+ {
508
+ style: {
509
+ display: "flex",
510
+ justifyContent: msg.role === "user" ? "flex-end" : "flex-start"
511
+ },
512
+ children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: msg.role === "user" ? userBubbleStyle(primaryColor) : assistantBubbleStyle, children: msg.role === "assistant" ? /* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown__default.default, { children: msg.content }) : /* @__PURE__ */ jsxRuntime.jsx("span", { style: { whiteSpace: "pre-wrap" }, children: msg.content }) })
513
+ },
514
+ i
515
+ )),
516
+ isLoading && (isThinking || messages[messages.length - 1]?.role !== "assistant") && /* @__PURE__ */ jsxRuntime.jsx("div", { style: { display: "flex", justifyContent: "flex-start" }, children: /* @__PURE__ */ jsxRuntime.jsx("div", { style: assistantBubbleStyle, children: isThinking ? /* @__PURE__ */ jsxRuntime.jsx(ThinkingDots, {}) : /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 16 }) }) }),
517
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: messagesEndRef })
518
+ ] }) }),
519
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { style: inputBarStyle, children: [
520
+ /* @__PURE__ */ jsxRuntime.jsx(
521
+ "textarea",
522
+ {
523
+ ref: textareaRef,
524
+ value: input,
525
+ onChange: (e) => setInput(e.target.value),
526
+ onKeyDown: handleKeyPress,
527
+ placeholder: isReady ? "Type your message..." : "Waiting for model...",
528
+ disabled: !isReady || isLoading,
529
+ rows: 1,
530
+ style: {
531
+ ...textareaStyle,
532
+ opacity: !isReady ? 0.5 : 1
533
+ }
534
+ }
535
+ ),
536
+ /* @__PURE__ */ jsxRuntime.jsx(
537
+ "button",
538
+ {
539
+ onClick: send,
540
+ disabled: !isReady || isLoading || !input.trim(),
541
+ style: {
542
+ ...sendButtonStyle(primaryColor),
543
+ opacity: !isReady || isLoading || !input.trim() ? 0.5 : 1,
544
+ cursor: !isReady || isLoading || !input.trim() ? "not-allowed" : "pointer"
545
+ },
546
+ "aria-label": "Send message",
547
+ children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(Spinner, { size: 18 }) : /* @__PURE__ */ jsxRuntime.jsx(SendIcon, {})
548
+ }
549
+ )
550
+ ] })
551
+ ] }),
552
+ /* @__PURE__ */ jsxRuntime.jsx(
553
+ "button",
554
+ {
555
+ onClick: () => setIsOpen(!isOpen),
556
+ style: fabStyle(primaryColor, position),
557
+ "aria-label": "Toggle chat",
558
+ onMouseEnter: (e) => {
559
+ e.target.style.transform = "scale(1.05)";
560
+ },
561
+ onMouseLeave: (e) => {
562
+ e.target.style.transform = "scale(1)";
563
+ },
564
+ children: isOpen ? /* @__PURE__ */ jsxRuntime.jsx(CloseIcon, {}) : /* @__PURE__ */ jsxRuntime.jsx(ChatIcon, {})
565
+ }
566
+ )
567
+ ] });
568
+ }
569
+
570
+ exports.KanhaBot = KanhaBot;
571
+ exports.useKanhaChat = useKanhaChat;
572
+ //# sourceMappingURL=index.cjs.map
573
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/use-kanha-chat.ts","../src/styles.ts","../src/KanhaBot.tsx"],"names":["useState","useRef","useCallback","useEffect","jsx","jsxs","Fragment","ReactMarkdown"],"mappings":"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","file":"index.cjs","sourcesContent":["import { useState, useEffect, useRef, useCallback } from \"react\";\nimport type { Message, InferenceMode, KanhaChatConfig, KanhaChatReturn } from \"./types\";\n\nconst MODEL_LIB_PREFIX =\n \"https://raw.githubusercontent.com/mlc-ai/binary-mlc-llm-libs/main/web-llm-models/v0_2_80\";\n\nconst WASM_BY_SIZE: Record<string, string> = {\n small: `${MODEL_LIB_PREFIX}/Qwen3-0.6B-q4f16_1-ctx4k_cs1k-webgpu.wasm`,\n medium: `${MODEL_LIB_PREFIX}/Qwen3-1.7B-q4f16_1-ctx4k_cs1k-webgpu.wasm`,\n large: `${MODEL_LIB_PREFIX}/Qwen3-4B-q4f16_1-ctx4k_cs1k-webgpu.wasm`,\n};\n\nfunction resolveModelLib(config: KanhaChatConfig): string {\n if (config.modelLib) return config.modelLib;\n const size = config.modelSize ?? \"small\";\n const lib = WASM_BY_SIZE[size];\n if (!lib) throw new Error(`Unknown model size \"${size}\". Provide modelLib explicitly.`);\n return lib;\n}\n\n/**\n * Converts a storage URL into a format web-llm's cleanModelUrl won't mangle.\n * web-llm checks for /resolve/ in the URL — if missing, it appends /resolve/main/.\n * We append /resolve/v1/ so the URL passes through untouched.\n * Files must be stored at {modelUrl}/resolve/v1/{filename} in storage.\n */\nfunction toWebLLMModelUrl(modelUrl: string): string {\n let url = modelUrl.endsWith(\"/\") ? modelUrl.slice(0, -1) : modelUrl;\n if (!url.includes(\"/resolve/\")) {\n url += \"/resolve/v1\";\n }\n return url;\n}\n\nasync function checkWebGPU(): Promise<boolean> {\n try {\n const nav = navigator as Navigator & { gpu?: { requestAdapter(): Promise<unknown> } };\n if (!nav.gpu) return false;\n const adapter = (await nav.gpu.requestAdapter()) as { requestDevice(): Promise<unknown> } | null;\n if (!adapter) return false;\n const device = await adapter.requestDevice();\n return !!device;\n } catch {\n return false;\n }\n}\n\nfunction stripThinkTokens(text: string): string {\n let cleaned = text.replace(/<think>[\\s\\S]*?<\\/think>/g, \"\");\n cleaned = cleaned.replace(/<think>[\\s\\S]*$/g, \"\");\n return cleaned.trimStart();\n}\n\nexport function useKanhaChat(config: KanhaChatConfig): KanhaChatReturn {\n const [messages, setMessages] = useState<Message[]>([]);\n const [input, setInput] = useState(\"\");\n const [isLoading, setIsLoading] = useState(false);\n const [isThinking, setIsThinking] = useState(false);\n const [mode, setMode] = useState<InferenceMode>(\"detecting\");\n const [loadProgress, setLoadProgress] = useState(0);\n const [error, setError] = useState<string | null>(null);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const engineRef = useRef<any>(null);\n const configRef = useRef(config);\n configRef.current = config;\n\n const updateAssistantMessage = useCallback((text: string) => {\n const cleaned = stripThinkTokens(text);\n if (!cleaned) {\n setIsThinking(true);\n return;\n }\n setIsThinking(false);\n setMessages((prev) => {\n const msgs = [...prev];\n if (msgs[msgs.length - 1]?.role === \"assistant\") {\n msgs[msgs.length - 1] = { role: \"assistant\", content: cleaned };\n } else {\n msgs.push({ role: \"assistant\", content: cleaned });\n }\n return msgs;\n });\n }, []);\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n\n let cancelled = false;\n\n const init = async () => {\n setMode(\"detecting\");\n\n const hasWebGPU = await checkWebGPU();\n if (!hasWebGPU) {\n setMode(\"error\");\n setError(\"WebGPU is not supported in this browser. Try Chrome 113+ or Edge 113+.\");\n return;\n }\n\n if (cancelled) return;\n setMode(\"loading\");\n\n try {\n const webllm = await import(\"@mlc-ai/web-llm\");\n const modelId = \"kanha-custom-model\";\n const modelLib = resolveModelLib(configRef.current);\n const modelUrl = toWebLLMModelUrl(configRef.current.modelUrl);\n\n const engine = await webllm.CreateMLCEngine(modelId, {\n appConfig: {\n model_list: [\n {\n model: modelUrl,\n model_id: modelId,\n model_lib: modelLib,\n overrides: {\n context_window_size: configRef.current.contextWindowSize ?? 4096,\n },\n },\n ],\n },\n initProgressCallback: (report: { progress: number }) => {\n if (!cancelled) setLoadProgress(Math.round(report.progress * 100));\n },\n });\n\n if (cancelled) return;\n engineRef.current = engine;\n setMode(\"ready\");\n } catch (err) {\n if (cancelled) return;\n setMode(\"error\");\n setError(\n err instanceof Error ? err.message : \"Failed to load AI model.\"\n );\n }\n };\n\n init();\n return () => { cancelled = true; };\n }, [config.modelUrl, config.modelLib, config.modelSize]);\n\n const send = useCallback(async () => {\n if (!input.trim() || mode !== \"ready\" || isLoading || !engineRef.current) return;\n\n const userMsg: Message = { role: \"user\", content: input.trim() };\n const allMessages = [...messages, userMsg];\n setMessages(allMessages);\n setInput(\"\");\n setIsLoading(true);\n setIsThinking(true);\n setError(null);\n\n try {\n const systemMessages: Message[] = configRef.current.systemPrompt\n ? [{ role: \"system\", content: configRef.current.systemPrompt }]\n : [];\n\n const completion = await engineRef.current.chat.completions.create({\n messages: [...systemMessages, ...allMessages],\n temperature: configRef.current.temperature ?? 0.7,\n max_tokens: configRef.current.maxTokens ?? 1024,\n stream: true,\n });\n\n let text = \"\";\n for await (const chunk of completion) {\n const delta = chunk.choices[0]?.delta?.content || \"\";\n text += delta;\n updateAssistantMessage(text);\n }\n } catch {\n setError(\"Failed to generate response. Please try again.\");\n setMessages((prev) => [\n ...prev,\n { role: \"assistant\", content: \"Sorry, I encountered an error. Please try again.\" },\n ]);\n } finally {\n setIsLoading(false);\n setIsThinking(false);\n }\n }, [input, mode, isLoading, messages, updateAssistantMessage]);\n\n const clear = useCallback(() => {\n setMessages([]);\n setError(null);\n }, []);\n\n return {\n messages,\n input,\n setInput,\n isLoading,\n isThinking,\n mode,\n loadProgress,\n error,\n send,\n clear,\n };\n}\n","import type { CSSProperties } from \"react\";\n\nexport function fabStyle(\n primaryColor: string,\n position: \"bottom-right\" | \"bottom-left\",\n): CSSProperties {\n return {\n position: \"fixed\",\n bottom: 24,\n [position === \"bottom-right\" ? \"right\" : \"left\"]: 24,\n width: 56,\n height: 56,\n borderRadius: \"50%\",\n background: primaryColor,\n color: \"#fff\",\n border: \"none\",\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n boxShadow: \"0 4px 12px rgba(0,0,0,0.15)\",\n zIndex: 9999,\n transition: \"transform 0.15s ease, box-shadow 0.15s ease\",\n };\n}\n\nexport function panelStyle(position: \"bottom-right\" | \"bottom-left\"): CSSProperties {\n return {\n position: \"fixed\",\n bottom: 96,\n [position === \"bottom-right\" ? \"right\" : \"left\"]: 24,\n width: 384,\n maxWidth: \"calc(100vw - 48px)\",\n maxHeight: \"calc(100vh - 120px)\",\n borderRadius: 16,\n overflow: \"hidden\",\n display: \"flex\",\n flexDirection: \"column\",\n boxShadow: \"0 8px 30px rgba(0,0,0,0.12)\",\n border: \"1px solid #e5e7eb\",\n background: \"#ffffff\",\n zIndex: 9999,\n fontFamily: '-apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif',\n };\n}\n\nexport const headerStyle: CSSProperties = {\n padding: \"16px\",\n color: \"#fff\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"space-between\",\n};\n\nexport const headerTitleStyle: CSSProperties = {\n fontWeight: 600,\n fontSize: 15,\n margin: 0,\n};\n\nexport const headerSubtitleStyle: CSSProperties = {\n fontSize: 12,\n opacity: 0.85,\n margin: \"4px 0 0\",\n};\n\nexport const messagesContainerStyle: CSSProperties = {\n flex: 1,\n overflowY: \"auto\",\n padding: 16,\n display: \"flex\",\n flexDirection: \"column\",\n gap: 12,\n minHeight: 300,\n maxHeight: 384,\n background: \"#fafafa\",\n};\n\nexport const emptyStateStyle: CSSProperties = {\n display: \"flex\",\n flexDirection: \"column\",\n alignItems: \"center\",\n justifyContent: \"center\",\n height: \"100%\",\n textAlign: \"center\",\n color: \"#6b7280\",\n fontSize: 14,\n padding: 16,\n};\n\nexport function userBubbleStyle(primaryColor: string): CSSProperties {\n return {\n maxWidth: \"80%\",\n padding: \"8px 14px\",\n borderRadius: 16,\n background: primaryColor,\n color: \"#fff\",\n fontSize: 14,\n lineHeight: 1.5,\n alignSelf: \"flex-end\",\n wordBreak: \"break-word\",\n };\n}\n\nexport const assistantBubbleStyle: CSSProperties = {\n maxWidth: \"80%\",\n padding: \"8px 14px\",\n borderRadius: 16,\n background: \"#fff\",\n color: \"#1f2937\",\n fontSize: 14,\n lineHeight: 1.5,\n border: \"1px solid #e5e7eb\",\n alignSelf: \"flex-start\",\n wordBreak: \"break-word\",\n};\n\nexport const inputBarStyle: CSSProperties = {\n display: \"flex\",\n gap: 8,\n padding: \"12px 16px\",\n borderTop: \"1px solid #e5e7eb\",\n background: \"#fff\",\n};\n\nexport const textareaStyle: CSSProperties = {\n flex: 1,\n padding: \"8px 12px\",\n border: \"1px solid #e5e7eb\",\n borderRadius: 10,\n fontSize: 14,\n resize: \"none\",\n overflow: \"hidden\",\n outline: \"none\",\n fontFamily: \"inherit\",\n minHeight: 40,\n maxHeight: 120,\n lineHeight: 1.5,\n};\n\nexport function sendButtonStyle(primaryColor: string): CSSProperties {\n return {\n padding: \"8px 14px\",\n background: primaryColor,\n color: \"#fff\",\n border: \"none\",\n borderRadius: 10,\n cursor: \"pointer\",\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n flexShrink: 0,\n transition: \"opacity 0.15s ease\",\n };\n}\n\nexport const iconButtonStyle: CSSProperties = {\n background: \"none\",\n border: \"none\",\n color: \"inherit\",\n cursor: \"pointer\",\n padding: 4,\n borderRadius: 8,\n display: \"flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n opacity: 0.8,\n transition: \"opacity 0.15s ease\",\n};\n\nexport function suggestionButtonStyle(primaryColor: string): CSSProperties {\n return {\n fontSize: 13,\n padding: \"8px 12px\",\n borderRadius: 10,\n border: \"1px solid #e5e7eb\",\n background: \"#fff\",\n color: \"#374151\",\n cursor: \"pointer\",\n textAlign: \"left\" as const,\n width: \"100%\",\n transition: \"border-color 0.15s ease\",\n // hover handled inline\n };\n}\n\nexport const progressBarContainer: CSSProperties = {\n width: \"60%\",\n height: 4,\n borderRadius: 2,\n background: \"rgba(255,255,255,0.3)\",\n marginTop: 8,\n overflow: \"hidden\",\n};\n\nexport function progressBarFill(progress: number, primaryColor: string): CSSProperties {\n return {\n width: `${progress}%`,\n height: \"100%\",\n borderRadius: 2,\n background: primaryColor,\n transition: \"width 0.3s ease\",\n };\n}\n","import {\n useState,\n useEffect,\n useRef,\n type KeyboardEvent,\n type CSSProperties,\n} from \"react\";\nimport ReactMarkdown from \"react-markdown\";\nimport { useKanhaChat } from \"./use-kanha-chat\";\nimport type { KanhaBotProps } from \"./types\";\nimport * as s from \"./styles\";\n\n// Inline SVG icons (no icon library dependency)\nconst ChatIcon = () => (\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n);\n\nconst CloseIcon = () => (\n <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\" /><line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\" />\n </svg>\n);\n\nconst SendIcon = () => (\n <svg width=\"18\" height=\"18\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <line x1=\"22\" y1=\"2\" x2=\"11\" y2=\"13\" /><polygon points=\"22 2 15 22 11 13 2 9 22 2\" />\n </svg>\n);\n\nconst TrashIcon = () => (\n <svg width=\"16\" height=\"16\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" strokeLinecap=\"round\" strokeLinejoin=\"round\">\n <polyline points=\"3 6 5 6 21 6\" /><path d=\"M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2\" />\n </svg>\n);\n\nconst Spinner = ({ size = 18 }: { size?: number }) => (\n <svg width={size} height={size} viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"2\" style={{ animation: \"kanha-spin 1s linear infinite\" }}>\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n);\n\nconst spinKeyframes = `@keyframes kanha-spin { to { transform: rotate(360deg); } }`;\nconst bounceKeyframes = `\n@keyframes kanha-bounce {\n 0%, 80%, 100% { transform: translateY(0); }\n 40% { transform: translateY(-4px); }\n}`;\n\nfunction ThinkingDots() {\n const dotStyle = (delay: number): CSSProperties => ({\n width: 6,\n height: 6,\n borderRadius: \"50%\",\n background: \"#9ca3af\",\n animation: `kanha-bounce 1.2s ease-in-out ${delay}ms infinite`,\n });\n return (\n <span style={{ display: \"flex\", gap: 3, alignItems: \"center\" }}>\n <span style={dotStyle(0)} />\n <span style={dotStyle(150)} />\n <span style={dotStyle(300)} />\n <span style={{ fontSize: 12, color: \"#9ca3af\", marginLeft: 6 }}>Thinking</span>\n </span>\n );\n}\n\nexport function KanhaBot({\n modelUrl,\n modelLib,\n modelSize,\n systemPrompt,\n temperature,\n maxTokens,\n contextWindowSize,\n botName = \"AI Assistant\",\n welcomeMessage = \"Ask me anything!\",\n suggestions = [],\n theme = {},\n}: KanhaBotProps) {\n const primaryColor = theme.primaryColor ?? \"#0d9488\";\n const position = theme.position ?? \"bottom-right\";\n\n const {\n messages,\n input,\n setInput,\n isLoading,\n isThinking,\n mode,\n loadProgress,\n error,\n send,\n clear,\n } = useKanhaChat({\n modelUrl,\n modelLib,\n modelSize,\n systemPrompt,\n temperature,\n maxTokens,\n contextWindowSize,\n });\n\n const [isOpen, setIsOpen] = useState(false);\n const messagesEndRef = useRef<HTMLDivElement>(null);\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n\n useEffect(() => {\n messagesEndRef.current?.scrollIntoView({ behavior: \"smooth\" });\n }, [messages]);\n\n useEffect(() => {\n if (textareaRef.current) {\n textareaRef.current.style.height = \"auto\";\n textareaRef.current.style.height = Math.min(textareaRef.current.scrollHeight, 120) + \"px\";\n }\n }, [input]);\n\n const handleKeyPress = (e: KeyboardEvent) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n send();\n }\n };\n\n const isReady = mode === \"ready\";\n\n return (\n <>\n <style>{spinKeyframes}{bounceKeyframes}</style>\n\n {isOpen && (\n <div style={s.panelStyle(position)}>\n {/* Header */}\n <div style={{ ...s.headerStyle, background: primaryColor }}>\n <div>\n <p style={s.headerTitleStyle}>{botName}</p>\n <p style={s.headerSubtitleStyle}>\n {isReady\n ? welcomeMessage\n : mode === \"loading\"\n ? `Loading AI model (${loadProgress}%)`\n : mode === \"error\"\n ? \"Failed to load\"\n : \"Detecting capabilities...\"}\n </p>\n {mode === \"loading\" && (\n <div style={s.progressBarContainer}>\n <div style={s.progressBarFill(loadProgress, \"#fff\")} />\n </div>\n )}\n </div>\n <div style={{ display: \"flex\", gap: 4 }}>\n {messages.length > 0 && (\n <button onClick={clear} style={s.iconButtonStyle} aria-label=\"Clear chat\">\n <TrashIcon />\n </button>\n )}\n <button onClick={() => setIsOpen(false)} style={s.iconButtonStyle} aria-label=\"Close\">\n <CloseIcon />\n </button>\n </div>\n </div>\n\n {/* Error banner */}\n {error && (\n <div style={{ padding: \"10px 16px\", background: \"#fef2f2\", borderBottom: \"1px solid #fecaca\", fontSize: 13, color: \"#b91c1c\" }}>\n {error}\n </div>\n )}\n\n {/* Messages */}\n <div style={s.messagesContainerStyle}>\n {messages.length === 0 ? (\n <div style={s.emptyStateStyle}>\n {isReady ? (\n <>\n <ChatIcon />\n <p style={{ marginTop: 12, fontWeight: 500, color: \"#374151\" }}>\n {welcomeMessage}\n </p>\n {suggestions.length > 0 && (\n <div style={{ display: \"flex\", flexDirection: \"column\", gap: 6, width: \"100%\", marginTop: 16 }}>\n {suggestions.map((text) => (\n <button\n key={text}\n onClick={() => { setInput(text); setTimeout(send, 0); }}\n style={s.suggestionButtonStyle(primaryColor)}\n onMouseEnter={(e) => { (e.target as HTMLElement).style.borderColor = primaryColor; }}\n onMouseLeave={(e) => { (e.target as HTMLElement).style.borderColor = \"#e5e7eb\"; }}\n >\n {text}\n </button>\n ))}\n </div>\n )}\n </>\n ) : mode === \"loading\" ? (\n <>\n <Spinner size={32} />\n <p style={{ marginTop: 8 }}>Loading AI model ({loadProgress}%)</p>\n <p style={{ fontSize: 12, marginTop: 4 }}>First load takes about a minute</p>\n </>\n ) : mode === \"error\" ? (\n <p>{error}</p>\n ) : (\n <>\n <Spinner size={32} />\n <p style={{ marginTop: 8 }}>Detecting browser capabilities...</p>\n </>\n )}\n </div>\n ) : (\n <>\n {messages.map((msg, i) => (\n <div\n key={i}\n style={{\n display: \"flex\",\n justifyContent: msg.role === \"user\" ? \"flex-end\" : \"flex-start\",\n }}\n >\n <div style={msg.role === \"user\" ? s.userBubbleStyle(primaryColor) : s.assistantBubbleStyle}>\n {msg.role === \"assistant\" ? (\n <ReactMarkdown>{msg.content}</ReactMarkdown>\n ) : (\n <span style={{ whiteSpace: \"pre-wrap\" }}>{msg.content}</span>\n )}\n </div>\n </div>\n ))}\n {isLoading && (isThinking || messages[messages.length - 1]?.role !== \"assistant\") && (\n <div style={{ display: \"flex\", justifyContent: \"flex-start\" }}>\n <div style={s.assistantBubbleStyle}>\n {isThinking ? <ThinkingDots /> : <Spinner size={16} />}\n </div>\n </div>\n )}\n <div ref={messagesEndRef} />\n </>\n )}\n </div>\n\n {/* Input */}\n <div style={s.inputBarStyle}>\n <textarea\n ref={textareaRef}\n value={input}\n onChange={(e) => setInput(e.target.value)}\n onKeyDown={handleKeyPress}\n placeholder={isReady ? \"Type your message...\" : \"Waiting for model...\"}\n disabled={!isReady || isLoading}\n rows={1}\n style={{\n ...s.textareaStyle,\n opacity: !isReady ? 0.5 : 1,\n }}\n />\n <button\n onClick={send}\n disabled={!isReady || isLoading || !input.trim()}\n style={{\n ...s.sendButtonStyle(primaryColor),\n opacity: !isReady || isLoading || !input.trim() ? 0.5 : 1,\n cursor: !isReady || isLoading || !input.trim() ? \"not-allowed\" : \"pointer\",\n }}\n aria-label=\"Send message\"\n >\n {isLoading ? <Spinner size={18} /> : <SendIcon />}\n </button>\n </div>\n </div>\n )}\n\n {/* FAB */}\n <button\n onClick={() => setIsOpen(!isOpen)}\n style={s.fabStyle(primaryColor, position)}\n aria-label=\"Toggle chat\"\n onMouseEnter={(e) => { (e.target as HTMLElement).style.transform = \"scale(1.05)\"; }}\n onMouseLeave={(e) => { (e.target as HTMLElement).style.transform = \"scale(1)\"; }}\n >\n {isOpen ? <CloseIcon /> : <ChatIcon />}\n </button>\n </>\n );\n}\n"]}