@mcp-b/embedded-agent 0.0.1

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.
@@ -0,0 +1,4741 @@
1
+ import { c } from "react/compiler-runtime";
2
+ import { ActionBarPrimitive, AssistantModalPrimitive, AssistantRuntimeProvider, AttachmentPrimitive, BranchPickerPrimitive, ComposerPrimitive, ErrorPrimitive, MessagePrimitive, ThreadPrimitive, useAssistantApi, useAssistantState, useAssistantTool } from "@assistant-ui/react";
3
+ import { useChatRuntime } from "@assistant-ui/react-ai-sdk";
4
+ import r2wc from "@r2wc/react-to-web-component";
5
+ import { lastAssistantMessageIsCompleteWithToolCalls } from "ai";
6
+ import { ArrowDownIcon, ArrowUpIcon, CheckIcon, ChevronDownIcon, ChevronLeftIcon, ChevronRightIcon, ChevronUpIcon, CopyIcon, FileText, Loader2, Mic, MicOff, PencilIcon, Phone, PhoneOff, Plug, Plus, PlusIcon, RefreshCwIcon, Square, Volume2, X, XIcon } from "lucide-react";
7
+ import { createContext, forwardRef, memo, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
8
+ import { AnimatePresence, LazyMotion, MotionConfig, domAnimation } from "motion/react";
9
+ import * as m from "motion/react-m";
10
+ import { clsx } from "clsx";
11
+ import { twMerge } from "tailwind-merge";
12
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
13
+ import { useShallow } from "zustand/shallow";
14
+ import * as AvatarPrimitive from "@radix-ui/react-avatar";
15
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
16
+ import * as TooltipPrimitive from "@radix-ui/react-tooltip";
17
+ import { Slot, Slottable } from "@radix-ui/react-slot";
18
+ import { cva } from "class-variance-authority";
19
+ import { MarkdownTextPrimitive, unstable_memoizeMarkdownComponents, useIsMarkdownCodeBlock } from "@assistant-ui/react-markdown";
20
+ import remarkGfm from "remark-gfm";
21
+ import { Client } from "@modelcontextprotocol/sdk/client/index.js";
22
+ import { ToolListChangedNotificationSchema } from "@modelcontextprotocol/sdk/types.js";
23
+ import { TabClientTransport } from "@mcp-b/transports";
24
+ import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js";
25
+ import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js";
26
+
27
+ //#region src/lib/utils.ts
28
+ /**
29
+ * Merges Tailwind CSS classes with proper precedence handling.
30
+ * Combines clsx for conditional classes and tailwind-merge for deduplication.
31
+ */
32
+ function cn(...inputs) {
33
+ return twMerge(clsx(inputs));
34
+ }
35
+
36
+ //#endregion
37
+ //#region src/lib/constants.ts
38
+ /** Delay before auto-connecting to tab-based MCP sources (allows server initialization) */
39
+ const MCP_TAB_CONNECT_DELAY_MS = 100;
40
+ /** Number of frequency bins for audio visualization */
41
+ const AUDIO_FREQUENCY_BINS = 32;
42
+ /** Default OpenAI Realtime model */
43
+ const REALTIME_DEFAULT_MODEL = "gpt-4o-realtime-preview-2024-12-17";
44
+ /** Default voice for OpenAI Realtime */
45
+ const REALTIME_DEFAULT_VOICE = "verse";
46
+ /** Default OpenAI Realtime API URL */
47
+ const REALTIME_DEFAULT_API_URL = "https://api.openai.com/v1/realtime";
48
+ /** Interval in milliseconds for audio visualization updates (~60fps) */
49
+ const AUDIO_VISUALIZATION_INTERVAL_MS = 16;
50
+ /** Delay in milliseconds before requesting response after tool execution */
51
+ const RESPONSE_REQUEST_DELAY_MS = 150;
52
+ /** Duration to show completed tool calls before clearing (success) */
53
+ const TOOL_CALL_DISPLAY_DURATION_MS = 1500;
54
+ /** Duration to show failed tool calls before clearing (error) */
55
+ const TOOL_CALL_ERROR_DISPLAY_DURATION_MS = 3e3;
56
+ /**
57
+ * Enable debug logging for development.
58
+ * Can be enabled by setting window.__WEBMCP_DEBUG__ = true in the browser console.
59
+ * In production builds, this defaults to false.
60
+ */
61
+ const DEBUG_LOGGING_ENABLED = typeof window !== "undefined" && window.__WEBMCP_DEBUG__ === true;
62
+ /**
63
+ * Conditional debug logger that only logs when DEBUG_LOGGING_ENABLED is true.
64
+ * Can be enabled at runtime by setting window.__WEBMCP_DEBUG__ = true
65
+ *
66
+ * @param component - The component or service name for the log prefix
67
+ * @param message - The log message
68
+ * @param data - Optional data to include in the log
69
+ */
70
+ function debugLog(component, message, data) {
71
+ if (typeof window !== "undefined" && window.__WEBMCP_DEBUG__ === true) if (data !== void 0) console.log(`[${component}] ${message}`, data);
72
+ else console.log(`[${component}] ${message}`);
73
+ }
74
+
75
+ //#endregion
76
+ //#region src/services/realtime/audio-analyzer.ts
77
+ /**
78
+ * Audio analyzer for processing microphone and speaker audio streams.
79
+ * Uses Web Audio API to analyze audio levels and frequency data.
80
+ */
81
+ var AudioAnalyzer = class {
82
+ audioContext = null;
83
+ analyser = null;
84
+ source = null;
85
+ dataArray = null;
86
+ animationId = null;
87
+ /**
88
+ * Initialize the audio analyzer with a media stream
89
+ * @param stream - MediaStream to analyze (typically from microphone or speaker)
90
+ */
91
+ async initialize(stream) {
92
+ const audioTracks = stream.getAudioTracks();
93
+ debugLog("AudioAnalyzer", "Initializing with stream", {
94
+ streamId: stream.id,
95
+ audioTracks: audioTracks.length,
96
+ trackInfo: audioTracks.map((t) => ({
97
+ id: t.id,
98
+ label: t.label,
99
+ enabled: t.enabled,
100
+ muted: t.muted,
101
+ readyState: t.readyState
102
+ }))
103
+ });
104
+ this.audioContext = new AudioContext();
105
+ debugLog("AudioAnalyzer", `AudioContext created, initial state: ${this.audioContext.state}`);
106
+ try {
107
+ await this.audioContext.resume();
108
+ debugLog("AudioAnalyzer", `AudioContext after resume: ${this.audioContext.state}`);
109
+ } catch (err) {
110
+ console.warn("[AudioAnalyzer] Failed to resume AudioContext:", err);
111
+ }
112
+ this.analyser = this.audioContext.createAnalyser();
113
+ this.analyser.fftSize = 256;
114
+ this.analyser.smoothingTimeConstant = .8;
115
+ this.source = this.audioContext.createMediaStreamSource(stream);
116
+ this.source.connect(this.analyser);
117
+ const bufferLength = this.analyser.frequencyBinCount;
118
+ this.dataArray = new Uint8Array(new ArrayBuffer(bufferLength));
119
+ debugLog("AudioAnalyzer", "Setup complete", {
120
+ sampleRate: this.audioContext.sampleRate,
121
+ frequencyBinCount: bufferLength,
122
+ contextState: this.audioContext.state
123
+ });
124
+ }
125
+ getAudioLevel() {
126
+ if (!this.analyser || !this.dataArray) return 0;
127
+ this.analyser.getByteFrequencyData(this.dataArray);
128
+ let sum = 0;
129
+ for (let i = 0; i < this.dataArray.length; i++) sum += this.dataArray[i];
130
+ const average = sum / this.dataArray.length;
131
+ return Math.min(1, average / 128);
132
+ }
133
+ getFrequencyData(bins = 16) {
134
+ if (!this.analyser || !this.dataArray) return new Array(bins).fill(0);
135
+ this.analyser.getByteFrequencyData(this.dataArray);
136
+ const result = [];
137
+ const samplesPerBin = Math.floor(this.dataArray.length / bins);
138
+ for (let i = 0; i < bins; i++) {
139
+ let sum = 0;
140
+ for (let j = 0; j < samplesPerBin; j++) sum += this.dataArray[i * samplesPerBin + j];
141
+ result.push(Math.min(1, sum / samplesPerBin / 255));
142
+ }
143
+ return result;
144
+ }
145
+ startAnalysis(callback) {
146
+ const analyze = () => {
147
+ callback(this.getAudioLevel(), this.getFrequencyData());
148
+ this.animationId = requestAnimationFrame(analyze);
149
+ };
150
+ analyze();
151
+ }
152
+ stopAnalysis() {
153
+ if (this.animationId !== null) {
154
+ cancelAnimationFrame(this.animationId);
155
+ this.animationId = null;
156
+ }
157
+ }
158
+ destroy() {
159
+ this.stopAnalysis();
160
+ if (this.source) {
161
+ this.source.disconnect();
162
+ this.source = null;
163
+ }
164
+ if (this.analyser) {
165
+ this.analyser.disconnect();
166
+ this.analyser = null;
167
+ }
168
+ if (this.audioContext) {
169
+ this.audioContext.close();
170
+ this.audioContext = null;
171
+ }
172
+ this.dataArray = null;
173
+ }
174
+ };
175
+
176
+ //#endregion
177
+ //#region src/services/realtime/event-emitter.ts
178
+ var EventEmitter = class {
179
+ listeners = /* @__PURE__ */ new Map();
180
+ on(event, callback) {
181
+ if (!this.listeners.has(event)) this.listeners.set(event, /* @__PURE__ */ new Set());
182
+ const listeners = this.listeners.get(event);
183
+ if (listeners) listeners.add(callback);
184
+ }
185
+ off(event, callback) {
186
+ this.listeners.get(event)?.delete(callback);
187
+ }
188
+ emit(event, data) {
189
+ this.listeners.get(event)?.forEach((callback) => {
190
+ try {
191
+ callback(data);
192
+ } catch (error) {
193
+ console.error(`Error in event listener for ${event}:`, error);
194
+ }
195
+ });
196
+ }
197
+ removeAllListeners(event) {
198
+ if (event) this.listeners.delete(event);
199
+ else this.listeners.clear();
200
+ }
201
+ listenerCount(event) {
202
+ return this.listeners.get(event)?.size || 0;
203
+ }
204
+ };
205
+
206
+ //#endregion
207
+ //#region src/services/realtime/message-handler.ts
208
+ /**
209
+ * Type guard to check if an output item is a completed function call
210
+ */
211
+ function isCompletedFunctionCall(item) {
212
+ return item.type === "function_call" && item.status === "completed" && typeof item.name === "string" && typeof item.call_id === "string";
213
+ }
214
+ var MessageHandler = class {
215
+ isProcessingResponse = false;
216
+ pendingFunctionCalls = /* @__PURE__ */ new Set();
217
+ responseRequestTimer = null;
218
+ hasRequestedResponse = false;
219
+ constructor(toolManager, eventEmitter) {
220
+ this.toolManager = toolManager;
221
+ this.eventEmitter = eventEmitter;
222
+ }
223
+ async handleMessage(data, dataChannel) {
224
+ let msg;
225
+ try {
226
+ msg = JSON.parse(data);
227
+ } catch (error) {
228
+ console.error("Failed to parse realtime message:", error);
229
+ return;
230
+ }
231
+ switch (msg.type) {
232
+ case "response.created":
233
+ this.handleResponseCreated(msg);
234
+ break;
235
+ case "response.done":
236
+ await this.handleResponseDone(msg, dataChannel);
237
+ break;
238
+ case "response.function_call_arguments.done":
239
+ this.handleFunctionCallArguments();
240
+ break;
241
+ case "input_audio_buffer.speech_started":
242
+ case "input_audio_buffer.speech_stopped":
243
+ this.handleSpeechEvents(msg);
244
+ break;
245
+ case "response.output_audio.delta":
246
+ case "response.output_audio.done":
247
+ this.handleAudioEvents(msg);
248
+ break;
249
+ case "response.output_audio_transcript.delta":
250
+ case "response.output_audio_transcript.done":
251
+ case "response.output_text.delta":
252
+ case "response.output_text.done":
253
+ this.handleTranscriptEvents(msg);
254
+ break;
255
+ case "conversation.item.input_audio_transcription.completed":
256
+ this.handleUserTranscript(msg);
257
+ break;
258
+ case "error":
259
+ this.handleError(msg);
260
+ break;
261
+ case "session.created":
262
+ case "session.updated":
263
+ this.handleSessionEvents(msg);
264
+ break;
265
+ case "conversation.item.created":
266
+ case "input_audio_buffer.committed": break;
267
+ }
268
+ }
269
+ handleResponseCreated(_msg) {
270
+ this.isProcessingResponse = true;
271
+ this.hasRequestedResponse = false;
272
+ }
273
+ async handleResponseDone(msg, dataChannel) {
274
+ const outputItems = this.extractResponseOutput(msg.response);
275
+ if (!outputItems.some(isCompletedFunctionCall)) {
276
+ this.isProcessingResponse = false;
277
+ this.hasRequestedResponse = false;
278
+ }
279
+ if (outputItems.length > 0) {
280
+ const functionCalls = outputItems.filter(isCompletedFunctionCall).map((item) => ({
281
+ name: item.name,
282
+ call_id: item.call_id,
283
+ arguments: item.arguments ?? ""
284
+ }));
285
+ for (const functionCall of functionCalls) if (!this.pendingFunctionCalls.has(functionCall.call_id)) {
286
+ this.pendingFunctionCalls.add(functionCall.call_id);
287
+ await this.executeFunctionCall(functionCall, dataChannel);
288
+ } else console.warn(`[MessageHandler] Skipping duplicate function call: ${functionCall.name} (${functionCall.call_id})`);
289
+ if (functionCalls.length > 0 && this.pendingFunctionCalls.size === 0) this.requestResponseIfNeeded(dataChannel);
290
+ }
291
+ }
292
+ /**
293
+ * Safely extract response output array from response object
294
+ */
295
+ extractResponseOutput(response) {
296
+ if (!response || typeof response !== "object") return [];
297
+ const r = response;
298
+ if (!Array.isArray(r.output)) return [];
299
+ return r.output.filter((item) => item !== null && typeof item === "object" && typeof item.type === "string");
300
+ }
301
+ handleFunctionCallArguments() {}
302
+ handleSpeechEvents(msg) {
303
+ const eventType = msg.type === "input_audio_buffer.speech_started" ? "speech_started" : "speech_stopped";
304
+ this.eventEmitter.emit(eventType, msg);
305
+ }
306
+ handleAudioEvents(msg) {
307
+ const eventType = msg.type === "response.output_audio.delta" ? "audio_started" : "audio_stopped";
308
+ console.log(`[MessageHandler] Assistant ${eventType}`, {
309
+ type: msg.type,
310
+ hasAudio: !!msg.delta
311
+ });
312
+ this.eventEmitter.emit(eventType, msg);
313
+ }
314
+ handleTranscriptEvents(msg) {
315
+ const eventType = {
316
+ "response.output_audio_transcript.delta": "assistant_transcript",
317
+ "response.output_audio_transcript.done": "assistant_transcript_done",
318
+ "response.output_text.delta": "text",
319
+ "response.output_text.done": "text_done"
320
+ }[msg.type];
321
+ if (eventType) this.eventEmitter.emit(eventType, msg);
322
+ }
323
+ handleUserTranscript(msg) {
324
+ this.eventEmitter.emit("user_transcript_done", { text: msg.transcript });
325
+ }
326
+ handleSessionEvents(_msg) {}
327
+ handleError(msg) {
328
+ console.error("Realtime API error:", msg);
329
+ this.eventEmitter.emit("error", msg);
330
+ this.isProcessingResponse = false;
331
+ this.hasRequestedResponse = false;
332
+ if (this.responseRequestTimer) {
333
+ clearTimeout(this.responseRequestTimer);
334
+ this.responseRequestTimer = null;
335
+ }
336
+ }
337
+ async executeFunctionCall(functionCall, dataChannel) {
338
+ const { name, call_id } = functionCall;
339
+ try {
340
+ this.eventEmitter.emit("tool_call_started", { name });
341
+ const result = await this.toolManager.executeToolCall(functionCall);
342
+ if (dataChannel.readyState !== "open") {
343
+ console.error(`[MessageHandler] Cannot send tool result for ${name}: DataChannel is ${dataChannel.readyState}`);
344
+ this.eventEmitter.emit("tool_call_completed", {
345
+ name,
346
+ error: "DataChannel closed during tool execution"
347
+ });
348
+ return;
349
+ }
350
+ const response = {
351
+ type: "conversation.item.create",
352
+ item: {
353
+ type: "function_call_output",
354
+ call_id,
355
+ output: JSON.stringify(result.success ? result.data : {
356
+ error: result.error,
357
+ success: false
358
+ })
359
+ }
360
+ };
361
+ dataChannel.send(JSON.stringify(response));
362
+ this.eventEmitter.emit("tool_call_completed", {
363
+ name,
364
+ error: result.success ? void 0 : result.error
365
+ });
366
+ } catch (error) {
367
+ console.error(`[MessageHandler] Tool execution failed for ${name}:`, error);
368
+ this.sendToolError(call_id, String(error), dataChannel);
369
+ } finally {
370
+ this.pendingFunctionCalls.delete(call_id);
371
+ if (this.pendingFunctionCalls.size === 0) {
372
+ this.isProcessingResponse = false;
373
+ this.hasRequestedResponse = false;
374
+ this.requestResponseIfNeeded(dataChannel);
375
+ }
376
+ }
377
+ }
378
+ sendToolError(call_id, error, dataChannel) {
379
+ if (dataChannel.readyState !== "open") {
380
+ console.error(`[MessageHandler] Cannot send tool error: DataChannel is ${dataChannel.readyState}`);
381
+ return;
382
+ }
383
+ const errorResponse = {
384
+ type: "conversation.item.create",
385
+ item: {
386
+ type: "function_call_output",
387
+ call_id,
388
+ output: JSON.stringify({
389
+ error,
390
+ success: false
391
+ })
392
+ }
393
+ };
394
+ dataChannel.send(JSON.stringify(errorResponse));
395
+ }
396
+ requestResponseIfNeeded(dataChannel) {
397
+ if (this.responseRequestTimer) {
398
+ clearTimeout(this.responseRequestTimer);
399
+ this.responseRequestTimer = null;
400
+ }
401
+ this.responseRequestTimer = setTimeout(() => {
402
+ if (!this.isProcessingResponse && !this.hasRequestedResponse && dataChannel.readyState === "open" && this.pendingFunctionCalls.size === 0) {
403
+ this.hasRequestedResponse = true;
404
+ this.isProcessingResponse = true;
405
+ dataChannel.send(JSON.stringify({ type: "response.create" }));
406
+ }
407
+ this.responseRequestTimer = null;
408
+ }, RESPONSE_REQUEST_DELAY_MS);
409
+ }
410
+ reset() {
411
+ this.isProcessingResponse = false;
412
+ this.hasRequestedResponse = false;
413
+ this.pendingFunctionCalls.clear();
414
+ if (this.responseRequestTimer) {
415
+ clearTimeout(this.responseRequestTimer);
416
+ this.responseRequestTimer = null;
417
+ }
418
+ }
419
+ };
420
+
421
+ //#endregion
422
+ //#region src/services/realtime/tool-manager.ts
423
+ var ToolManager = class {
424
+ tools = [];
425
+ executor = null;
426
+ lastSentToolSignature = "";
427
+ setTools(tools) {
428
+ this.tools = tools;
429
+ }
430
+ setExecutor(executor) {
431
+ this.executor = executor;
432
+ }
433
+ resetSession() {
434
+ console.log("[ToolManager] resetSession called (lastSentToolSignature preserved)");
435
+ }
436
+ getToolSignature(tools) {
437
+ return tools.map((t) => t.name).sort().join("|");
438
+ }
439
+ hasToolsChanged() {
440
+ return this.getToolSignature(this.tools) !== this.lastSentToolSignature;
441
+ }
442
+ markToolsSent() {
443
+ this.lastSentToolSignature = this.getToolSignature(this.tools);
444
+ }
445
+ formatToolsForOpenAI() {
446
+ const builtInTools = [{
447
+ type: "function",
448
+ name: "list_available_tools",
449
+ description: "List all currently available tools that can be called. Use this when you need to know what tools are available or when the user asks about available capabilities.",
450
+ parameters: {
451
+ type: "object",
452
+ properties: {},
453
+ required: []
454
+ }
455
+ }];
456
+ const registeredTools = this.tools.map((tool) => ({
457
+ type: "function",
458
+ name: tool.name,
459
+ description: tool.description || `Execute ${tool.name} action`,
460
+ parameters: this.validateToolSchema(tool.inputSchema)
461
+ }));
462
+ return [...builtInTools, ...registeredTools];
463
+ }
464
+ validateToolSchema(schema) {
465
+ if (!schema) return {
466
+ type: "object",
467
+ properties: {},
468
+ required: []
469
+ };
470
+ const result = {
471
+ type: "object",
472
+ ...schema
473
+ };
474
+ if (result.type === "object") {
475
+ result.properties = result.properties || {};
476
+ if (!result.required && result.properties) result.required = Object.entries(result.properties).filter(([, prop]) => {
477
+ if (prop && typeof prop === "object") {
478
+ const p = prop;
479
+ return !p.optional && !p.nullable && p.type !== "null";
480
+ }
481
+ return false;
482
+ }).map(([key]) => key);
483
+ }
484
+ return result;
485
+ }
486
+ async executeToolCall(functionCall) {
487
+ const { name, arguments: argsString } = functionCall;
488
+ if (name === "list_available_tools") return this.executeListTools();
489
+ if (!this.executor) return {
490
+ success: false,
491
+ error: "Tool executor not configured"
492
+ };
493
+ if (!this.tools.find((t) => t.name === name)) {
494
+ console.error(`[ToolManager] Tool not found: ${name}`);
495
+ return {
496
+ success: false,
497
+ error: `Tool not found: ${name}`
498
+ };
499
+ }
500
+ let args;
501
+ try {
502
+ args = argsString ? JSON.parse(argsString) : {};
503
+ } catch (error) {
504
+ console.error("[ToolManager] Failed to parse arguments:", error);
505
+ return {
506
+ success: false,
507
+ error: "Invalid arguments format"
508
+ };
509
+ }
510
+ try {
511
+ return {
512
+ success: true,
513
+ data: await this.executor(name, args)
514
+ };
515
+ } catch (error) {
516
+ console.error(`[ToolManager] Tool execution error for ${name}:`, error);
517
+ return {
518
+ success: false,
519
+ error: String(error)
520
+ };
521
+ }
522
+ }
523
+ executeListTools() {
524
+ const toolList = this.tools.map((tool) => ({
525
+ name: tool.name,
526
+ description: tool.description || "No description available",
527
+ parameters: tool.inputSchema || {}
528
+ }));
529
+ return {
530
+ success: true,
531
+ data: {
532
+ tools: toolList,
533
+ count: toolList.length,
534
+ message: toolList.length > 0 ? `Found ${toolList.length} available tools` : "No tools currently available"
535
+ }
536
+ };
537
+ }
538
+ getChangesSummary() {
539
+ if (!this.hasToolsChanged()) return null;
540
+ const prevTools = this.lastSentToolSignature.split("|").filter(Boolean);
541
+ const currTools = this.tools.map((t) => t.name);
542
+ const prevSet = new Set(prevTools);
543
+ const currSet = new Set(currTools);
544
+ return {
545
+ added: currTools.filter((name) => !prevSet.has(name)),
546
+ removed: prevTools.filter((name) => !currSet.has(name)),
547
+ total: this.tools.length
548
+ };
549
+ }
550
+ };
551
+
552
+ //#endregion
553
+ //#region src/services/realtime/webrtc-manager.ts
554
+ function hasClientSecret(response) {
555
+ if (!response || typeof response !== "object") return false;
556
+ return typeof response.client_secret?.value === "string";
557
+ }
558
+ var WebRTCManager = class {
559
+ tokenEndpoint;
560
+ constructor(tokenEndpoint) {
561
+ this.tokenEndpoint = tokenEndpoint;
562
+ }
563
+ async createSession(config = {}) {
564
+ const model = config.model || REALTIME_DEFAULT_MODEL;
565
+ const voice = config.voice || REALTIME_DEFAULT_VOICE;
566
+ const apiUrl = config.apiUrl || REALTIME_DEFAULT_API_URL;
567
+ const ephemeralKey = await this.getEphemeralToken(model, voice);
568
+ const pc = new RTCPeerConnection();
569
+ const audioElement = this.createAudioElement();
570
+ let remoteStream = null;
571
+ pc.ontrack = (e) => {
572
+ remoteStream = e.streams[0];
573
+ audioElement.srcObject = remoteStream;
574
+ debugLog("WebRTC", "Remote audio stream received and connected to audio element", {
575
+ streamId: remoteStream.id,
576
+ tracks: remoteStream.getTracks().length
577
+ });
578
+ };
579
+ const localStream = await this.getUserMedia();
580
+ debugLog("WebRTC", "Local microphone stream acquired", {
581
+ streamId: localStream.id,
582
+ tracks: localStream.getTracks().map((t) => ({
583
+ kind: t.kind,
584
+ enabled: t.enabled,
585
+ muted: t.muted,
586
+ readyState: t.readyState
587
+ }))
588
+ });
589
+ localStream.getTracks().forEach((track) => {
590
+ pc.addTrack(track, localStream);
591
+ });
592
+ const dataChannel = pc.createDataChannel("oai-events");
593
+ const offer = await pc.createOffer();
594
+ await pc.setLocalDescription(offer);
595
+ if (!offer.sdp) throw new Error("Failed to create offer SDP");
596
+ const answer = await this.connectToOpenAI(apiUrl, model, offer.sdp, ephemeralKey);
597
+ await pc.setRemoteDescription(answer);
598
+ const cleanup = () => {
599
+ localStream.getTracks().forEach((track) => {
600
+ track.stop();
601
+ });
602
+ audioElement.remove();
603
+ dataChannel.close();
604
+ pc.close();
605
+ };
606
+ return {
607
+ pc,
608
+ dataChannel,
609
+ audioElement,
610
+ localStream,
611
+ remoteStream,
612
+ cleanup
613
+ };
614
+ }
615
+ async getEphemeralToken(model, voice) {
616
+ const response = await fetch(this.tokenEndpoint, {
617
+ method: "POST",
618
+ headers: { "Content-Type": "application/json" },
619
+ body: JSON.stringify({
620
+ model,
621
+ voice
622
+ })
623
+ });
624
+ if (!response.ok) {
625
+ const errorText = await response.text();
626
+ console.error("Failed to get ephemeral token:", errorText);
627
+ throw new Error(`Failed to get ephemeral token: ${response.statusText}`);
628
+ }
629
+ const data = await response.json();
630
+ if (!hasClientSecret(data)) throw new Error("Invalid token response format");
631
+ return data.client_secret.value;
632
+ }
633
+ createAudioElement() {
634
+ const audioElement = document.createElement("audio");
635
+ audioElement.autoplay = true;
636
+ audioElement.style.display = "none";
637
+ document.body.appendChild(audioElement);
638
+ return audioElement;
639
+ }
640
+ async getUserMedia() {
641
+ try {
642
+ return await navigator.mediaDevices.getUserMedia({ audio: {
643
+ echoCancellation: true,
644
+ noiseSuppression: true,
645
+ autoGainControl: true
646
+ } });
647
+ } catch (error) {
648
+ throw new Error(`Failed to access microphone: ${error}`);
649
+ }
650
+ }
651
+ async connectToOpenAI(baseUrl, model, sdp, ephemeralKey) {
652
+ const response = await fetch(`${baseUrl}?model=${model}`, {
653
+ method: "POST",
654
+ body: sdp,
655
+ headers: {
656
+ Authorization: `Bearer ${ephemeralKey}`,
657
+ "Content-Type": "application/sdp"
658
+ }
659
+ });
660
+ if (!response.ok) throw new Error(`Failed to establish WebRTC connection: ${response.statusText}`);
661
+ return {
662
+ type: "answer",
663
+ sdp: await response.text()
664
+ };
665
+ }
666
+ };
667
+
668
+ //#endregion
669
+ //#region src/services/realtime/openai-realtime-service.ts
670
+ /** Pre-allocated zero frequency array for performance */
671
+ const EMPTY_FREQUENCY_TEMPLATE = Object.freeze(new Array(AUDIO_FREQUENCY_BINS).fill(0));
672
+ const createZeroFrequencyArray = () => [...EMPTY_FREQUENCY_TEMPLATE];
673
+ /**
674
+ * OpenAI Realtime API Service
675
+ *
676
+ * Manages voice conversations with OpenAI's Realtime API,
677
+ * including WebRTC connections, tool integration, and message handling.
678
+ */
679
+ var OpenAIRealtimeService = class {
680
+ session = null;
681
+ webrtcManager;
682
+ toolManager;
683
+ messageHandler;
684
+ eventEmitter;
685
+ muted = false;
686
+ lastState = "disconnected";
687
+ localAnalyzer = null;
688
+ remoteAnalyzer = null;
689
+ visualizationInterval = null;
690
+ sessionStartTime = null;
691
+ onToolsChangedCallback = null;
692
+ constructor(tokenEndpoint) {
693
+ this.webrtcManager = new WebRTCManager(tokenEndpoint);
694
+ this.toolManager = new ToolManager();
695
+ this.eventEmitter = new EventEmitter();
696
+ this.messageHandler = new MessageHandler(this.toolManager, this.eventEmitter);
697
+ }
698
+ /**
699
+ * Set the tools available for the voice session
700
+ */
701
+ setTools(tools) {
702
+ this.toolManager.setTools(tools);
703
+ if (this.isSessionActive()) this.updateSessionTools();
704
+ }
705
+ /**
706
+ * Set the tool executor function
707
+ */
708
+ setToolExecutor(executor) {
709
+ this.toolManager.setExecutor(executor);
710
+ }
711
+ /**
712
+ * Register callback for when tools change
713
+ */
714
+ onToolsChanged(callback) {
715
+ this.onToolsChangedCallback = callback;
716
+ }
717
+ /**
718
+ * Start a new realtime session
719
+ */
720
+ async startSession(config = {}) {
721
+ try {
722
+ if (this.session) this.stopSession();
723
+ this.muted = false;
724
+ this.sessionStartTime = Date.now();
725
+ this.emitSessionState("connecting");
726
+ this.session = await this.webrtcManager.createSession(config);
727
+ this.setupDataChannel(this.session.dataChannel);
728
+ this.setupPeerConnectionMonitoring(this.session.pc);
729
+ if (this.session.localStream) await this.initializeLocalAnalyzer(this.session.localStream);
730
+ if (this.session.remoteStream) this.initializeRemoteAnalyzer(this.session.remoteStream);
731
+ const originalOntrack = this.session.pc.ontrack;
732
+ const session = this.session;
733
+ this.session.pc.ontrack = (e) => {
734
+ if (originalOntrack) originalOntrack.call(session.pc, e);
735
+ if (this.session) this.session.remoteStream = e.streams[0];
736
+ const remoteStream = e.streams[0];
737
+ if (!remoteStream) {
738
+ console.warn("[OpenAIRealtimeService] Received ontrack event without stream");
739
+ return;
740
+ }
741
+ this.initializeRemoteAnalyzer(remoteStream);
742
+ };
743
+ return this.session;
744
+ } catch (error) {
745
+ this.handleSessionError(error);
746
+ throw error;
747
+ }
748
+ }
749
+ /**
750
+ * Stop the current session
751
+ */
752
+ stopSession() {
753
+ let durationSeconds = 0;
754
+ if (this.sessionStartTime) durationSeconds = Math.floor((Date.now() - this.sessionStartTime) / 1e3);
755
+ if (this.visualizationInterval) {
756
+ clearInterval(this.visualizationInterval);
757
+ this.visualizationInterval = null;
758
+ }
759
+ if (this.localAnalyzer) {
760
+ this.localAnalyzer.destroy();
761
+ this.localAnalyzer = null;
762
+ }
763
+ if (this.remoteAnalyzer) {
764
+ this.remoteAnalyzer.destroy();
765
+ this.remoteAnalyzer = null;
766
+ }
767
+ if (this.session) {
768
+ this.session.cleanup();
769
+ this.session = null;
770
+ }
771
+ this.messageHandler.reset();
772
+ this.toolManager.resetSession();
773
+ this.muted = false;
774
+ this.emitSessionState("disconnected", { durationSeconds });
775
+ this.sessionStartTime = null;
776
+ }
777
+ /**
778
+ * Send a text message to the assistant
779
+ */
780
+ sendUserMessage(text) {
781
+ if (!this.isSessionActive()) throw new Error("No active session");
782
+ const message = {
783
+ type: "conversation.item.create",
784
+ item: {
785
+ type: "message",
786
+ role: "user",
787
+ content: [{
788
+ type: "input_text",
789
+ text
790
+ }]
791
+ }
792
+ };
793
+ if (!this.session) throw new Error("Session is not active");
794
+ this.session.dataChannel.send(JSON.stringify(message));
795
+ this.session.dataChannel.send(JSON.stringify({ type: "response.create" }));
796
+ }
797
+ /**
798
+ * Check if session is active
799
+ */
800
+ isSessionActive() {
801
+ return this.session !== null && this.session.dataChannel.readyState === "open";
802
+ }
803
+ /**
804
+ * Get the local audio stream
805
+ */
806
+ getLocalStream() {
807
+ return this.session?.localStream || null;
808
+ }
809
+ /**
810
+ * Get the remote audio stream
811
+ */
812
+ getRemoteStream() {
813
+ return this.session?.remoteStream || null;
814
+ }
815
+ /**
816
+ * Toggle audio mute
817
+ */
818
+ toggleMute(muted) {
819
+ if (this.session?.audioElement) this.session.audioElement.muted = muted;
820
+ this.muted = muted;
821
+ this.emitSessionState(this.lastState, { isMuted: this.muted });
822
+ }
823
+ /**
824
+ * Event handling
825
+ */
826
+ on(event, callback) {
827
+ this.eventEmitter.on(event, callback);
828
+ }
829
+ off(event, callback) {
830
+ this.eventEmitter.off(event, callback);
831
+ }
832
+ getSessionStatus() {
833
+ return {
834
+ state: this.lastState,
835
+ isActive: this.lastState === "connected",
836
+ isMuted: this.muted
837
+ };
838
+ }
839
+ /**
840
+ * Private methods
841
+ */
842
+ setupDataChannel(dataChannel) {
843
+ dataChannel.addEventListener("open", () => {
844
+ this.configureSession(dataChannel);
845
+ this.muted = false;
846
+ this.emitSessionState("connected");
847
+ });
848
+ dataChannel.addEventListener("message", (event) => {
849
+ (async () => {
850
+ try {
851
+ await this.messageHandler.handleMessage(event.data, dataChannel);
852
+ } catch (error) {
853
+ console.error("Error handling message:", error);
854
+ }
855
+ })();
856
+ });
857
+ dataChannel.addEventListener("error", (error) => {
858
+ console.error("DataChannel error:", error);
859
+ this.eventEmitter.emit("error", {
860
+ type: "datachannel_error",
861
+ error
862
+ });
863
+ });
864
+ dataChannel.addEventListener("close", () => {
865
+ this.messageHandler.reset();
866
+ this.eventEmitter.emit("session_closed", {});
867
+ });
868
+ }
869
+ setupPeerConnectionMonitoring(pc) {
870
+ pc.addEventListener("connectionstatechange", () => {
871
+ if (pc.connectionState === "failed" || pc.connectionState === "disconnected") {
872
+ console.error("Peer connection failed or disconnected");
873
+ this.messageHandler.reset();
874
+ this.eventEmitter.emit("error", {
875
+ type: "connection_error",
876
+ message: `Connection ${pc.connectionState}`
877
+ });
878
+ }
879
+ });
880
+ pc.addEventListener("iceconnectionstatechange", () => {
881
+ if (pc.iceConnectionState === "failed" || pc.iceConnectionState === "disconnected") console.error("ICE connection failed or disconnected");
882
+ });
883
+ pc.addEventListener("signalingstatechange", () => {});
884
+ }
885
+ configureSession(dataChannel) {
886
+ this.toolManager.resetSession();
887
+ const tools = this.toolManager.formatToolsForOpenAI();
888
+ this.toolManager.markToolsSent();
889
+ const sessionUpdate = {
890
+ type: "session.update",
891
+ session: {
892
+ modalities: ["text", "audio"],
893
+ instructions: this.getSessionInstructions(),
894
+ voice: "verse",
895
+ tools,
896
+ tool_choice: "auto",
897
+ turn_detection: {
898
+ type: "server_vad",
899
+ threshold: .5,
900
+ prefix_padding_ms: 300,
901
+ silence_duration_ms: 500
902
+ },
903
+ input_audio_transcription: { model: "whisper-1" }
904
+ }
905
+ };
906
+ dataChannel.send(JSON.stringify(sessionUpdate));
907
+ }
908
+ updateSessionTools() {
909
+ if (!this.session) {
910
+ console.warn("[OpenAIRealtimeService] Cannot update tools: no active session");
911
+ return;
912
+ }
913
+ if (this.session.dataChannel.readyState !== "open") {
914
+ console.warn(`[OpenAIRealtimeService] Cannot update tools: DataChannel is ${this.session.dataChannel.readyState}`);
915
+ return;
916
+ }
917
+ const changesSummary = this.toolManager.getChangesSummary();
918
+ if (!changesSummary) return;
919
+ const tools = this.toolManager.formatToolsForOpenAI();
920
+ console.log("[OpenAIRealtimeService] Sending tool update to OpenAI:", `${changesSummary.total} total tools,`, changesSummary.added.length > 0 ? `+${changesSummary.added.length} added (${changesSummary.added.slice(0, 3).join(", ")}${changesSummary.added.length > 3 ? "..." : ""})` : "", changesSummary.removed.length > 0 ? `-${changesSummary.removed.length} removed` : "");
921
+ this.toolManager.markToolsSent();
922
+ const sessionUpdate = {
923
+ type: "session.update",
924
+ session: {
925
+ tools,
926
+ tool_choice: "auto"
927
+ }
928
+ };
929
+ this.session.dataChannel.send(JSON.stringify(sessionUpdate));
930
+ }
931
+ getSessionInstructions() {
932
+ return `You are a helpful assistant with access to tools.
933
+ Use the available tools to help users with their tasks.
934
+ You can use the list_available_tools function to see what tools are currently available.
935
+ Be concise and helpful in your responses.`;
936
+ }
937
+ handleSessionError(error) {
938
+ console.error("Session error:", error);
939
+ this.emitSessionState("error", {
940
+ type: "session_error",
941
+ error: String(error)
942
+ });
943
+ this.stopSession();
944
+ }
945
+ async initializeLocalAnalyzer(stream) {
946
+ if (this.localAnalyzer) this.localAnalyzer.destroy();
947
+ this.localAnalyzer = new AudioAnalyzer();
948
+ try {
949
+ const clonedStream = new MediaStream(stream.getAudioTracks().map((t) => t.clone()));
950
+ await this.localAnalyzer.initialize(clonedStream);
951
+ this.startAudioVisualization();
952
+ } catch (error) {
953
+ console.error("[OpenAIRealtimeService] Failed to initialize local audio analyzer", error);
954
+ if (this.localAnalyzer) {
955
+ this.localAnalyzer.destroy();
956
+ this.localAnalyzer = null;
957
+ }
958
+ }
959
+ }
960
+ async initializeRemoteAnalyzer(stream) {
961
+ if (this.remoteAnalyzer) this.remoteAnalyzer.destroy();
962
+ this.remoteAnalyzer = new AudioAnalyzer();
963
+ try {
964
+ const clonedStream = new MediaStream(stream.getAudioTracks().map((t) => t.clone()));
965
+ await this.remoteAnalyzer.initialize(clonedStream);
966
+ this.startAudioVisualization();
967
+ } catch (error) {
968
+ console.error("[OpenAIRealtimeService] Failed to initialize remote audio analyzer", error);
969
+ if (this.remoteAnalyzer) {
970
+ this.remoteAnalyzer.destroy();
971
+ this.remoteAnalyzer = null;
972
+ }
973
+ }
974
+ }
975
+ startAudioVisualization() {
976
+ if (!this.localAnalyzer && !this.remoteAnalyzer) {
977
+ debugLog("OpenAIRealtimeService", "Audio visualization not started: no analyzers ready");
978
+ return;
979
+ }
980
+ if (this.visualizationInterval) clearInterval(this.visualizationInterval);
981
+ let logCounter = 0;
982
+ this.visualizationInterval = setInterval(() => {
983
+ const micLevel = this.localAnalyzer?.getAudioLevel() ?? 0;
984
+ const micFrequency = this.localAnalyzer?.getFrequencyData(AUDIO_FREQUENCY_BINS) ?? createZeroFrequencyArray();
985
+ const speakerLevel = this.remoteAnalyzer?.getAudioLevel() ?? 0;
986
+ const speakerFrequency = this.remoteAnalyzer?.getFrequencyData(AUDIO_FREQUENCY_BINS) ?? createZeroFrequencyArray();
987
+ logCounter++;
988
+ if (logCounter % 60 === 0) debugLog("OpenAIRealtimeService", "Audio levels", {
989
+ mic: micLevel.toFixed(3),
990
+ speaker: speakerLevel.toFixed(3)
991
+ });
992
+ this.eventEmitter.emit("audio_level", {
993
+ micLevel,
994
+ micFrequency,
995
+ speakerLevel,
996
+ speakerFrequency
997
+ });
998
+ }, AUDIO_VISUALIZATION_INTERVAL_MS);
999
+ }
1000
+ emitSessionState(state, extra = {}) {
1001
+ this.lastState = state;
1002
+ const payload = {
1003
+ state,
1004
+ isActive: state === "connected",
1005
+ isMuted: this.muted,
1006
+ ...extra
1007
+ };
1008
+ this.eventEmitter.emit("session_state", payload);
1009
+ switch (state) {
1010
+ case "connecting":
1011
+ this.eventEmitter.emit("session_connecting", payload);
1012
+ break;
1013
+ case "connected":
1014
+ this.eventEmitter.emit("session_connected", payload);
1015
+ break;
1016
+ case "disconnected":
1017
+ this.eventEmitter.emit("session_closed", payload);
1018
+ break;
1019
+ case "error":
1020
+ this.eventEmitter.emit("error", payload);
1021
+ break;
1022
+ default: break;
1023
+ }
1024
+ }
1025
+ };
1026
+
1027
+ //#endregion
1028
+ //#region src/services/realtime/types.ts
1029
+ /**
1030
+ * Type guard for SessionStateEventData
1031
+ */
1032
+ function isSessionStateEventData(data) {
1033
+ if (!data || typeof data !== "object") return false;
1034
+ const d = data;
1035
+ return typeof d.state === "string" && [
1036
+ "connecting",
1037
+ "connected",
1038
+ "disconnected",
1039
+ "error"
1040
+ ].includes(d.state) && typeof d.isActive === "boolean" && typeof d.isMuted === "boolean";
1041
+ }
1042
+ /**
1043
+ * Type guard for UserTranscriptEventData
1044
+ */
1045
+ function isUserTranscriptEventData(data) {
1046
+ if (!data || typeof data !== "object") return false;
1047
+ return typeof data.text === "string";
1048
+ }
1049
+ /**
1050
+ * Type guard for AssistantTranscriptEventData
1051
+ */
1052
+ function isAssistantTranscriptEventData(data) {
1053
+ if (!data || typeof data !== "object") return false;
1054
+ const d = data;
1055
+ return d.delta === void 0 || typeof d.delta === "string";
1056
+ }
1057
+ /**
1058
+ * Type guard for ToolCallStartedEventData
1059
+ */
1060
+ function isToolCallStartedEventData(data) {
1061
+ if (!data || typeof data !== "object") return false;
1062
+ return typeof data.name === "string";
1063
+ }
1064
+ /**
1065
+ * Type guard for ToolCallCompletedEventData
1066
+ */
1067
+ function isToolCallCompletedEventData(data) {
1068
+ if (!data || typeof data !== "object") return false;
1069
+ return typeof data.name === "string";
1070
+ }
1071
+ /**
1072
+ * Type guard for ErrorEventData
1073
+ */
1074
+ function isErrorEventData(data) {
1075
+ if (!data || typeof data !== "object") return false;
1076
+ const d = data;
1077
+ return typeof d.error === "string" || typeof d.message === "string" || typeof d.type === "string";
1078
+ }
1079
+ /**
1080
+ * Type guard for AudioLevelData
1081
+ */
1082
+ function isAudioLevelData(data) {
1083
+ if (!data || typeof data !== "object") return false;
1084
+ const d = data;
1085
+ return typeof d.micLevel === "number" && Array.isArray(d.micFrequency) && typeof d.speakerLevel === "number" && Array.isArray(d.speakerFrequency);
1086
+ }
1087
+
1088
+ //#endregion
1089
+ //#region src/hooks/useVoiceMode.ts
1090
+ /**
1091
+ * Voice Mode Hook
1092
+ *
1093
+ * Manages OpenAI Realtime API voice sessions with WebRTC.
1094
+ * Provides audio level streaming, transcript events, and tool call tracking.
1095
+ *
1096
+ * @example Basic usage
1097
+ * ```tsx
1098
+ * const {
1099
+ * isActive,
1100
+ * startSession,
1101
+ * stopSession,
1102
+ * toggleMute
1103
+ * } = useVoiceMode({
1104
+ * tokenEndpoint: '/api/realtime/session'
1105
+ * })
1106
+ * ```
1107
+ */
1108
+ function useVoiceMode(options) {
1109
+ const $ = c(43);
1110
+ const { tokenEndpoint, tools, toolExecutor, onConnect, onDisconnect, onError, onUserTranscript, onAssistantTranscript } = options;
1111
+ const [isActive, setIsActive] = useState(false);
1112
+ const [isConnecting, setIsConnecting] = useState(false);
1113
+ const [isMuted, setIsMuted] = useState(false);
1114
+ const [isError, setIsError] = useState(false);
1115
+ const [connectionState, setConnectionState] = useState("disconnected");
1116
+ const [audioLevel, setAudioLevel] = useState();
1117
+ const [transcript, setTranscript] = useState();
1118
+ const [toolCall, setToolCall] = useState();
1119
+ const [error, setError] = useState();
1120
+ const serviceRef = useRef(null);
1121
+ const onConnectRef = useRef(onConnect);
1122
+ const onDisconnectRef = useRef(onDisconnect);
1123
+ const onErrorRef = useRef(onError);
1124
+ const onUserTranscriptRef = useRef(onUserTranscript);
1125
+ const onAssistantTranscriptRef = useRef(onAssistantTranscript);
1126
+ let t0;
1127
+ let t1;
1128
+ if ($[0] !== onAssistantTranscript || $[1] !== onConnect || $[2] !== onDisconnect || $[3] !== onError || $[4] !== onUserTranscript) {
1129
+ t0 = () => {
1130
+ onConnectRef.current = onConnect;
1131
+ onDisconnectRef.current = onDisconnect;
1132
+ onErrorRef.current = onError;
1133
+ onUserTranscriptRef.current = onUserTranscript;
1134
+ onAssistantTranscriptRef.current = onAssistantTranscript;
1135
+ };
1136
+ t1 = [
1137
+ onConnect,
1138
+ onDisconnect,
1139
+ onError,
1140
+ onUserTranscript,
1141
+ onAssistantTranscript
1142
+ ];
1143
+ $[0] = onAssistantTranscript;
1144
+ $[1] = onConnect;
1145
+ $[2] = onDisconnect;
1146
+ $[3] = onError;
1147
+ $[4] = onUserTranscript;
1148
+ $[5] = t0;
1149
+ $[6] = t1;
1150
+ } else {
1151
+ t0 = $[5];
1152
+ t1 = $[6];
1153
+ }
1154
+ useEffect(t0, t1);
1155
+ let t2;
1156
+ if ($[7] !== tokenEndpoint) {
1157
+ t2 = () => {
1158
+ if (!serviceRef.current) serviceRef.current = new OpenAIRealtimeService(tokenEndpoint);
1159
+ return serviceRef.current;
1160
+ };
1161
+ $[7] = tokenEndpoint;
1162
+ $[8] = t2;
1163
+ } else t2 = $[8];
1164
+ const getService = t2;
1165
+ let t3;
1166
+ let t4;
1167
+ if ($[9] !== getService || $[10] !== tools) {
1168
+ t3 = () => {
1169
+ if (tools) getService().setTools(tools);
1170
+ };
1171
+ t4 = [tools, getService];
1172
+ $[9] = getService;
1173
+ $[10] = tools;
1174
+ $[11] = t3;
1175
+ $[12] = t4;
1176
+ } else {
1177
+ t3 = $[11];
1178
+ t4 = $[12];
1179
+ }
1180
+ useEffect(t3, t4);
1181
+ let t5;
1182
+ let t6;
1183
+ if ($[13] !== getService || $[14] !== toolExecutor) {
1184
+ t5 = () => {
1185
+ if (toolExecutor) getService().setToolExecutor(toolExecutor);
1186
+ };
1187
+ t6 = [toolExecutor, getService];
1188
+ $[13] = getService;
1189
+ $[14] = toolExecutor;
1190
+ $[15] = t5;
1191
+ $[16] = t6;
1192
+ } else {
1193
+ t5 = $[15];
1194
+ t6 = $[16];
1195
+ }
1196
+ useEffect(t5, t6);
1197
+ let t7;
1198
+ let t8;
1199
+ if ($[17] !== getService) {
1200
+ t7 = () => {
1201
+ const service_1 = getService();
1202
+ const handleSessionState = (data) => {
1203
+ if (!isSessionStateEventData(data)) {
1204
+ console.warn("[useVoiceMode] Invalid session state event data:", data);
1205
+ return;
1206
+ }
1207
+ setConnectionState(data.state);
1208
+ setIsActive(data.isActive);
1209
+ setIsMuted(data.isMuted);
1210
+ setIsConnecting(data.state === "connecting");
1211
+ setIsError(data.state === "error");
1212
+ if (data.state === "connected") onConnectRef.current?.();
1213
+ else if (data.state === "disconnected") onDisconnectRef.current?.(data.durationSeconds ?? 0);
1214
+ };
1215
+ const handleAudioLevel = (data_0) => {
1216
+ if (isAudioLevelData(data_0)) setAudioLevel(data_0);
1217
+ };
1218
+ const handleUserTranscript = (data_1) => {
1219
+ if (!isUserTranscriptEventData(data_1)) {
1220
+ console.warn("[useVoiceMode] Invalid user transcript event data:", data_1);
1221
+ return;
1222
+ }
1223
+ setTranscript({
1224
+ type: "user",
1225
+ text: data_1.text,
1226
+ isDone: true
1227
+ });
1228
+ onUserTranscriptRef.current?.(data_1.text);
1229
+ };
1230
+ const handleAssistantTranscript = (data_2) => {
1231
+ if (!isAssistantTranscriptEventData(data_2)) return;
1232
+ const text = data_2.delta || data_2.transcript || "";
1233
+ setTranscript((prev) => ({
1234
+ type: "assistant",
1235
+ text: prev?.type === "assistant" ? prev.text + text : text,
1236
+ isDone: false
1237
+ }));
1238
+ };
1239
+ const handleAssistantTranscriptDone = (data_3) => {
1240
+ if (!isAssistantTranscriptEventData(data_3)) return;
1241
+ const text_0 = data_3.transcript || "";
1242
+ setTranscript({
1243
+ type: "assistant",
1244
+ text: text_0,
1245
+ isDone: true
1246
+ });
1247
+ onAssistantTranscriptRef.current?.(text_0);
1248
+ };
1249
+ const handleToolCallStarted = (data_4) => {
1250
+ if (!isToolCallStartedEventData(data_4)) {
1251
+ console.warn("[useVoiceMode] Invalid tool call started event data:", data_4);
1252
+ return;
1253
+ }
1254
+ setToolCall({
1255
+ status: "started",
1256
+ toolName: data_4.name
1257
+ });
1258
+ };
1259
+ const handleToolCallCompleted = (data_5) => {
1260
+ if (!isToolCallCompletedEventData(data_5)) {
1261
+ console.warn("[useVoiceMode] Invalid tool call completed event data:", data_5);
1262
+ return;
1263
+ }
1264
+ setToolCall({
1265
+ status: "completed",
1266
+ toolName: data_5.name,
1267
+ error: data_5.error
1268
+ });
1269
+ setTimeout(() => {
1270
+ setToolCall(void 0);
1271
+ }, data_5.error ? TOOL_CALL_ERROR_DISPLAY_DURATION_MS : TOOL_CALL_DISPLAY_DURATION_MS);
1272
+ };
1273
+ const handleError = (data_6) => {
1274
+ if (!isErrorEventData(data_6)) {
1275
+ setError("Unknown error");
1276
+ setIsError(true);
1277
+ onErrorRef.current?.("Unknown error");
1278
+ return;
1279
+ }
1280
+ const errorMsg = data_6.error || data_6.message || "Unknown error";
1281
+ setError(errorMsg);
1282
+ setIsError(true);
1283
+ onErrorRef.current?.(errorMsg);
1284
+ };
1285
+ service_1.on("session_state", handleSessionState);
1286
+ service_1.on("audio_level", handleAudioLevel);
1287
+ service_1.on("user_transcript_done", handleUserTranscript);
1288
+ service_1.on("assistant_transcript", handleAssistantTranscript);
1289
+ service_1.on("assistant_transcript_done", handleAssistantTranscriptDone);
1290
+ service_1.on("tool_call_started", handleToolCallStarted);
1291
+ service_1.on("tool_call_completed", handleToolCallCompleted);
1292
+ service_1.on("error", handleError);
1293
+ return () => {
1294
+ service_1.off("session_state", handleSessionState);
1295
+ service_1.off("audio_level", handleAudioLevel);
1296
+ service_1.off("user_transcript_done", handleUserTranscript);
1297
+ service_1.off("assistant_transcript", handleAssistantTranscript);
1298
+ service_1.off("assistant_transcript_done", handleAssistantTranscriptDone);
1299
+ service_1.off("tool_call_started", handleToolCallStarted);
1300
+ service_1.off("tool_call_completed", handleToolCallCompleted);
1301
+ service_1.off("error", handleError);
1302
+ };
1303
+ };
1304
+ t8 = [getService];
1305
+ $[17] = getService;
1306
+ $[18] = t7;
1307
+ $[19] = t8;
1308
+ } else {
1309
+ t7 = $[18];
1310
+ t8 = $[19];
1311
+ }
1312
+ useEffect(t7, t8);
1313
+ let t9;
1314
+ if ($[20] !== getService) {
1315
+ t9 = async (config) => {
1316
+ try {
1317
+ setIsConnecting(true);
1318
+ setIsError(false);
1319
+ setError(void 0);
1320
+ await getService().startSession(config);
1321
+ } catch (t10$1) {
1322
+ const err = t10$1;
1323
+ setIsConnecting(false);
1324
+ setIsError(true);
1325
+ const errorMsg_0 = err instanceof Error ? err.message : "Failed to start session";
1326
+ setError(errorMsg_0);
1327
+ onErrorRef.current?.(errorMsg_0);
1328
+ }
1329
+ };
1330
+ $[20] = getService;
1331
+ $[21] = t9;
1332
+ } else t9 = $[21];
1333
+ const startSession = t9;
1334
+ let t10;
1335
+ if ($[22] !== getService) {
1336
+ t10 = () => {
1337
+ getService().stopSession();
1338
+ setAudioLevel(void 0);
1339
+ setTranscript(void 0);
1340
+ setToolCall(void 0);
1341
+ };
1342
+ $[22] = getService;
1343
+ $[23] = t10;
1344
+ } else t10 = $[23];
1345
+ const stopSession = t10;
1346
+ let t11;
1347
+ if ($[24] !== getService || $[25] !== isMuted) {
1348
+ t11 = (muted) => {
1349
+ const service_4 = getService();
1350
+ const newMuted = muted !== void 0 ? muted : !isMuted;
1351
+ service_4.toggleMute(newMuted);
1352
+ setIsMuted(newMuted);
1353
+ };
1354
+ $[24] = getService;
1355
+ $[25] = isMuted;
1356
+ $[26] = t11;
1357
+ } else t11 = $[26];
1358
+ const toggleMute = t11;
1359
+ let t12;
1360
+ if ($[27] !== getService) {
1361
+ t12 = (text_1) => {
1362
+ const service_5 = getService();
1363
+ if (service_5.isSessionActive()) service_5.sendUserMessage(text_1);
1364
+ };
1365
+ $[27] = getService;
1366
+ $[28] = t12;
1367
+ } else t12 = $[28];
1368
+ const sendMessage = t12;
1369
+ let t13;
1370
+ if ($[29] !== audioLevel || $[30] !== connectionState || $[31] !== error || $[32] !== isActive || $[33] !== isConnecting || $[34] !== isError || $[35] !== isMuted || $[36] !== sendMessage || $[37] !== startSession || $[38] !== stopSession || $[39] !== toggleMute || $[40] !== toolCall || $[41] !== transcript) {
1371
+ t13 = {
1372
+ isActive,
1373
+ isConnecting,
1374
+ isMuted,
1375
+ isError,
1376
+ connectionState,
1377
+ audioLevel,
1378
+ transcript,
1379
+ toolCall,
1380
+ error,
1381
+ startSession,
1382
+ stopSession,
1383
+ toggleMute,
1384
+ sendMessage
1385
+ };
1386
+ $[29] = audioLevel;
1387
+ $[30] = connectionState;
1388
+ $[31] = error;
1389
+ $[32] = isActive;
1390
+ $[33] = isConnecting;
1391
+ $[34] = isError;
1392
+ $[35] = isMuted;
1393
+ $[36] = sendMessage;
1394
+ $[37] = startSession;
1395
+ $[38] = stopSession;
1396
+ $[39] = toggleMute;
1397
+ $[40] = toolCall;
1398
+ $[41] = transcript;
1399
+ $[42] = t13;
1400
+ } else t13 = $[42];
1401
+ return t13;
1402
+ }
1403
+
1404
+ //#endregion
1405
+ //#region src/providers/VoiceModeProvider.tsx
1406
+ const VoiceModeContext = createContext(null);
1407
+ /**
1408
+ * Check if the browser supports WebRTC and getUserMedia
1409
+ */
1410
+ function checkVoiceModeSupport() {
1411
+ return !!(typeof window !== "undefined" && window.RTCPeerConnection && navigator.mediaDevices?.getUserMedia);
1412
+ }
1413
+ function VoiceModeProvider(t0) {
1414
+ const $ = c(15);
1415
+ const { children, tokenEndpoint, tools, toolExecutor, onConnect, onDisconnect, onError, onUserTranscript, onAssistantTranscript } = t0;
1416
+ let t1;
1417
+ if ($[0] !== onAssistantTranscript || $[1] !== onConnect || $[2] !== onDisconnect || $[3] !== onError || $[4] !== onUserTranscript || $[5] !== tokenEndpoint || $[6] !== toolExecutor || $[7] !== tools) {
1418
+ t1 = {
1419
+ tokenEndpoint,
1420
+ tools,
1421
+ toolExecutor,
1422
+ onConnect,
1423
+ onDisconnect,
1424
+ onError,
1425
+ onUserTranscript,
1426
+ onAssistantTranscript
1427
+ };
1428
+ $[0] = onAssistantTranscript;
1429
+ $[1] = onConnect;
1430
+ $[2] = onDisconnect;
1431
+ $[3] = onError;
1432
+ $[4] = onUserTranscript;
1433
+ $[5] = tokenEndpoint;
1434
+ $[6] = toolExecutor;
1435
+ $[7] = tools;
1436
+ $[8] = t1;
1437
+ } else t1 = $[8];
1438
+ const voiceMode = useVoiceMode(t1);
1439
+ let t2;
1440
+ if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
1441
+ t2 = checkVoiceModeSupport();
1442
+ $[9] = t2;
1443
+ } else t2 = $[9];
1444
+ const isSupported = t2;
1445
+ let t3;
1446
+ if ($[10] !== voiceMode) {
1447
+ t3 = {
1448
+ ...voiceMode,
1449
+ isSupported
1450
+ };
1451
+ $[10] = voiceMode;
1452
+ $[11] = t3;
1453
+ } else t3 = $[11];
1454
+ const value = t3;
1455
+ let t4;
1456
+ if ($[12] !== children || $[13] !== value) {
1457
+ t4 = /* @__PURE__ */ jsx(VoiceModeContext.Provider, {
1458
+ value,
1459
+ children
1460
+ });
1461
+ $[12] = children;
1462
+ $[13] = value;
1463
+ $[14] = t4;
1464
+ } else t4 = $[14];
1465
+ return t4;
1466
+ }
1467
+ /**
1468
+ * Hook to optionally access voice mode context (returns null if not in provider)
1469
+ */
1470
+ function useOptionalVoiceModeContext() {
1471
+ return useContext(VoiceModeContext);
1472
+ }
1473
+
1474
+ //#endregion
1475
+ //#region src/components/avatar.tsx
1476
+ function Avatar(t0) {
1477
+ const $ = c(8);
1478
+ let className;
1479
+ let props;
1480
+ if ($[0] !== t0) {
1481
+ ({className, ...props} = t0);
1482
+ $[0] = t0;
1483
+ $[1] = className;
1484
+ $[2] = props;
1485
+ } else {
1486
+ className = $[1];
1487
+ props = $[2];
1488
+ }
1489
+ let t1;
1490
+ if ($[3] !== className) {
1491
+ t1 = cn("relative flex size-8 shrink-0 overflow-hidden rounded-full", className);
1492
+ $[3] = className;
1493
+ $[4] = t1;
1494
+ } else t1 = $[4];
1495
+ let t2;
1496
+ if ($[5] !== props || $[6] !== t1) {
1497
+ t2 = /* @__PURE__ */ jsx(AvatarPrimitive.Root, {
1498
+ "data-slot": "avatar",
1499
+ className: t1,
1500
+ ...props
1501
+ });
1502
+ $[5] = props;
1503
+ $[6] = t1;
1504
+ $[7] = t2;
1505
+ } else t2 = $[7];
1506
+ return t2;
1507
+ }
1508
+ function AvatarImage(t0) {
1509
+ const $ = c(8);
1510
+ let className;
1511
+ let props;
1512
+ if ($[0] !== t0) {
1513
+ ({className, ...props} = t0);
1514
+ $[0] = t0;
1515
+ $[1] = className;
1516
+ $[2] = props;
1517
+ } else {
1518
+ className = $[1];
1519
+ props = $[2];
1520
+ }
1521
+ let t1;
1522
+ if ($[3] !== className) {
1523
+ t1 = cn("aspect-square size-full", className);
1524
+ $[3] = className;
1525
+ $[4] = t1;
1526
+ } else t1 = $[4];
1527
+ let t2;
1528
+ if ($[5] !== props || $[6] !== t1) {
1529
+ t2 = /* @__PURE__ */ jsx(AvatarPrimitive.Image, {
1530
+ "data-slot": "avatar-image",
1531
+ className: t1,
1532
+ ...props
1533
+ });
1534
+ $[5] = props;
1535
+ $[6] = t1;
1536
+ $[7] = t2;
1537
+ } else t2 = $[7];
1538
+ return t2;
1539
+ }
1540
+ function AvatarFallback(t0) {
1541
+ const $ = c(8);
1542
+ let className;
1543
+ let props;
1544
+ if ($[0] !== t0) {
1545
+ ({className, ...props} = t0);
1546
+ $[0] = t0;
1547
+ $[1] = className;
1548
+ $[2] = props;
1549
+ } else {
1550
+ className = $[1];
1551
+ props = $[2];
1552
+ }
1553
+ let t1;
1554
+ if ($[3] !== className) {
1555
+ t1 = cn("bg-muted flex size-full items-center justify-center rounded-full", className);
1556
+ $[3] = className;
1557
+ $[4] = t1;
1558
+ } else t1 = $[4];
1559
+ let t2;
1560
+ if ($[5] !== props || $[6] !== t1) {
1561
+ t2 = /* @__PURE__ */ jsx(AvatarPrimitive.Fallback, {
1562
+ "data-slot": "avatar-fallback",
1563
+ className: t1,
1564
+ ...props
1565
+ });
1566
+ $[5] = props;
1567
+ $[6] = t1;
1568
+ $[7] = t2;
1569
+ } else t2 = $[7];
1570
+ return t2;
1571
+ }
1572
+
1573
+ //#endregion
1574
+ //#region src/components/dialog.tsx
1575
+ function Dialog(t0) {
1576
+ const $ = c(4);
1577
+ let props;
1578
+ if ($[0] !== t0) {
1579
+ ({...props} = t0);
1580
+ $[0] = t0;
1581
+ $[1] = props;
1582
+ } else props = $[1];
1583
+ let t1;
1584
+ if ($[2] !== props) {
1585
+ t1 = /* @__PURE__ */ jsx(DialogPrimitive.Root, {
1586
+ "data-slot": "dialog",
1587
+ ...props
1588
+ });
1589
+ $[2] = props;
1590
+ $[3] = t1;
1591
+ } else t1 = $[3];
1592
+ return t1;
1593
+ }
1594
+ function DialogTrigger(t0) {
1595
+ const $ = c(4);
1596
+ let props;
1597
+ if ($[0] !== t0) {
1598
+ ({...props} = t0);
1599
+ $[0] = t0;
1600
+ $[1] = props;
1601
+ } else props = $[1];
1602
+ let t1;
1603
+ if ($[2] !== props) {
1604
+ t1 = /* @__PURE__ */ jsx(DialogPrimitive.Trigger, {
1605
+ "data-slot": "dialog-trigger",
1606
+ ...props
1607
+ });
1608
+ $[2] = props;
1609
+ $[3] = t1;
1610
+ } else t1 = $[3];
1611
+ return t1;
1612
+ }
1613
+ function DialogPortal(t0) {
1614
+ const $ = c(4);
1615
+ let props;
1616
+ if ($[0] !== t0) {
1617
+ ({...props} = t0);
1618
+ $[0] = t0;
1619
+ $[1] = props;
1620
+ } else props = $[1];
1621
+ let t1;
1622
+ if ($[2] !== props) {
1623
+ t1 = /* @__PURE__ */ jsx(DialogPrimitive.Portal, {
1624
+ "data-slot": "dialog-portal",
1625
+ ...props
1626
+ });
1627
+ $[2] = props;
1628
+ $[3] = t1;
1629
+ } else t1 = $[3];
1630
+ return t1;
1631
+ }
1632
+ function DialogOverlay(t0) {
1633
+ const $ = c(8);
1634
+ let className;
1635
+ let props;
1636
+ if ($[0] !== t0) {
1637
+ ({className, ...props} = t0);
1638
+ $[0] = t0;
1639
+ $[1] = className;
1640
+ $[2] = props;
1641
+ } else {
1642
+ className = $[1];
1643
+ props = $[2];
1644
+ }
1645
+ let t1;
1646
+ if ($[3] !== className) {
1647
+ t1 = cn("data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 fixed inset-0 z-50 bg-black/50", className);
1648
+ $[3] = className;
1649
+ $[4] = t1;
1650
+ } else t1 = $[4];
1651
+ let t2;
1652
+ if ($[5] !== props || $[6] !== t1) {
1653
+ t2 = /* @__PURE__ */ jsx(DialogPrimitive.Overlay, {
1654
+ "data-slot": "dialog-overlay",
1655
+ className: t1,
1656
+ ...props
1657
+ });
1658
+ $[5] = props;
1659
+ $[6] = t1;
1660
+ $[7] = t2;
1661
+ } else t2 = $[7];
1662
+ return t2;
1663
+ }
1664
+ function DialogContent(t0) {
1665
+ const $ = c(15);
1666
+ let children;
1667
+ let className;
1668
+ let props;
1669
+ let t1;
1670
+ if ($[0] !== t0) {
1671
+ ({className, children, showCloseButton: t1, ...props} = t0);
1672
+ $[0] = t0;
1673
+ $[1] = children;
1674
+ $[2] = className;
1675
+ $[3] = props;
1676
+ $[4] = t1;
1677
+ } else {
1678
+ children = $[1];
1679
+ className = $[2];
1680
+ props = $[3];
1681
+ t1 = $[4];
1682
+ }
1683
+ const showCloseButton = t1 === void 0 ? true : t1;
1684
+ let t2;
1685
+ if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
1686
+ t2 = /* @__PURE__ */ jsx(DialogOverlay, {});
1687
+ $[5] = t2;
1688
+ } else t2 = $[5];
1689
+ let t3;
1690
+ if ($[6] !== className) {
1691
+ t3 = cn("bg-background data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 sm:max-w-lg", className);
1692
+ $[6] = className;
1693
+ $[7] = t3;
1694
+ } else t3 = $[7];
1695
+ let t4;
1696
+ if ($[8] !== showCloseButton) {
1697
+ t4 = showCloseButton && /* @__PURE__ */ jsxs(DialogPrimitive.Close, {
1698
+ "data-slot": "dialog-close",
1699
+ className: "ring-offset-background focus:ring-ring data-[state=open]:bg-accent data-[state=open]:text-muted-foreground absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden disabled:pointer-events-none [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
1700
+ children: [/* @__PURE__ */ jsx(XIcon, {}), /* @__PURE__ */ jsx("span", {
1701
+ className: "sr-only",
1702
+ children: "Close"
1703
+ })]
1704
+ });
1705
+ $[8] = showCloseButton;
1706
+ $[9] = t4;
1707
+ } else t4 = $[9];
1708
+ let t5;
1709
+ if ($[10] !== children || $[11] !== props || $[12] !== t3 || $[13] !== t4) {
1710
+ t5 = /* @__PURE__ */ jsxs(DialogPortal, {
1711
+ "data-slot": "dialog-portal",
1712
+ children: [t2, /* @__PURE__ */ jsxs(DialogPrimitive.Content, {
1713
+ "data-slot": "dialog-content",
1714
+ className: t3,
1715
+ ...props,
1716
+ children: [children, t4]
1717
+ })]
1718
+ });
1719
+ $[10] = children;
1720
+ $[11] = props;
1721
+ $[12] = t3;
1722
+ $[13] = t4;
1723
+ $[14] = t5;
1724
+ } else t5 = $[14];
1725
+ return t5;
1726
+ }
1727
+ function DialogHeader(t0) {
1728
+ const $ = c(8);
1729
+ let className;
1730
+ let props;
1731
+ if ($[0] !== t0) {
1732
+ ({className, ...props} = t0);
1733
+ $[0] = t0;
1734
+ $[1] = className;
1735
+ $[2] = props;
1736
+ } else {
1737
+ className = $[1];
1738
+ props = $[2];
1739
+ }
1740
+ let t1;
1741
+ if ($[3] !== className) {
1742
+ t1 = cn("flex flex-col gap-2 text-center sm:text-left", className);
1743
+ $[3] = className;
1744
+ $[4] = t1;
1745
+ } else t1 = $[4];
1746
+ let t2;
1747
+ if ($[5] !== props || $[6] !== t1) {
1748
+ t2 = /* @__PURE__ */ jsx("div", {
1749
+ "data-slot": "dialog-header",
1750
+ className: t1,
1751
+ ...props
1752
+ });
1753
+ $[5] = props;
1754
+ $[6] = t1;
1755
+ $[7] = t2;
1756
+ } else t2 = $[7];
1757
+ return t2;
1758
+ }
1759
+ function DialogTitle(t0) {
1760
+ const $ = c(8);
1761
+ let className;
1762
+ let props;
1763
+ if ($[0] !== t0) {
1764
+ ({className, ...props} = t0);
1765
+ $[0] = t0;
1766
+ $[1] = className;
1767
+ $[2] = props;
1768
+ } else {
1769
+ className = $[1];
1770
+ props = $[2];
1771
+ }
1772
+ let t1;
1773
+ if ($[3] !== className) {
1774
+ t1 = cn("text-lg leading-none font-semibold", className);
1775
+ $[3] = className;
1776
+ $[4] = t1;
1777
+ } else t1 = $[4];
1778
+ let t2;
1779
+ if ($[5] !== props || $[6] !== t1) {
1780
+ t2 = /* @__PURE__ */ jsx(DialogPrimitive.Title, {
1781
+ "data-slot": "dialog-title",
1782
+ className: t1,
1783
+ ...props
1784
+ });
1785
+ $[5] = props;
1786
+ $[6] = t1;
1787
+ $[7] = t2;
1788
+ } else t2 = $[7];
1789
+ return t2;
1790
+ }
1791
+ function DialogDescription(t0) {
1792
+ const $ = c(8);
1793
+ let className;
1794
+ let props;
1795
+ if ($[0] !== t0) {
1796
+ ({className, ...props} = t0);
1797
+ $[0] = t0;
1798
+ $[1] = className;
1799
+ $[2] = props;
1800
+ } else {
1801
+ className = $[1];
1802
+ props = $[2];
1803
+ }
1804
+ let t1;
1805
+ if ($[3] !== className) {
1806
+ t1 = cn("text-muted-foreground text-sm", className);
1807
+ $[3] = className;
1808
+ $[4] = t1;
1809
+ } else t1 = $[4];
1810
+ let t2;
1811
+ if ($[5] !== props || $[6] !== t1) {
1812
+ t2 = /* @__PURE__ */ jsx(DialogPrimitive.Description, {
1813
+ "data-slot": "dialog-description",
1814
+ className: t1,
1815
+ ...props
1816
+ });
1817
+ $[5] = props;
1818
+ $[6] = t1;
1819
+ $[7] = t2;
1820
+ } else t2 = $[7];
1821
+ return t2;
1822
+ }
1823
+
1824
+ //#endregion
1825
+ //#region src/components/tooltip.tsx
1826
+ function TooltipProvider(t0) {
1827
+ const $ = c(6);
1828
+ let props;
1829
+ let t1;
1830
+ if ($[0] !== t0) {
1831
+ ({delayDuration: t1, ...props} = t0);
1832
+ $[0] = t0;
1833
+ $[1] = props;
1834
+ $[2] = t1;
1835
+ } else {
1836
+ props = $[1];
1837
+ t1 = $[2];
1838
+ }
1839
+ const delayDuration = t1 === void 0 ? 0 : t1;
1840
+ let t2;
1841
+ if ($[3] !== delayDuration || $[4] !== props) {
1842
+ t2 = /* @__PURE__ */ jsx(TooltipPrimitive.Provider, {
1843
+ "data-slot": "tooltip-provider",
1844
+ delayDuration,
1845
+ ...props
1846
+ });
1847
+ $[3] = delayDuration;
1848
+ $[4] = props;
1849
+ $[5] = t2;
1850
+ } else t2 = $[5];
1851
+ return t2;
1852
+ }
1853
+ function Tooltip(t0) {
1854
+ const $ = c(4);
1855
+ let props;
1856
+ if ($[0] !== t0) {
1857
+ ({...props} = t0);
1858
+ $[0] = t0;
1859
+ $[1] = props;
1860
+ } else props = $[1];
1861
+ let t1;
1862
+ if ($[2] !== props) {
1863
+ t1 = /* @__PURE__ */ jsx(TooltipProvider, { children: /* @__PURE__ */ jsx(TooltipPrimitive.Root, {
1864
+ "data-slot": "tooltip",
1865
+ ...props
1866
+ }) });
1867
+ $[2] = props;
1868
+ $[3] = t1;
1869
+ } else t1 = $[3];
1870
+ return t1;
1871
+ }
1872
+ function TooltipTrigger(t0) {
1873
+ const $ = c(4);
1874
+ let props;
1875
+ if ($[0] !== t0) {
1876
+ ({...props} = t0);
1877
+ $[0] = t0;
1878
+ $[1] = props;
1879
+ } else props = $[1];
1880
+ let t1;
1881
+ if ($[2] !== props) {
1882
+ t1 = /* @__PURE__ */ jsx(TooltipPrimitive.Trigger, {
1883
+ "data-slot": "tooltip-trigger",
1884
+ ...props
1885
+ });
1886
+ $[2] = props;
1887
+ $[3] = t1;
1888
+ } else t1 = $[3];
1889
+ return t1;
1890
+ }
1891
+ function TooltipContent(t0) {
1892
+ const $ = c(13);
1893
+ let children;
1894
+ let className;
1895
+ let props;
1896
+ let t1;
1897
+ if ($[0] !== t0) {
1898
+ ({className, sideOffset: t1, children, ...props} = t0);
1899
+ $[0] = t0;
1900
+ $[1] = children;
1901
+ $[2] = className;
1902
+ $[3] = props;
1903
+ $[4] = t1;
1904
+ } else {
1905
+ children = $[1];
1906
+ className = $[2];
1907
+ props = $[3];
1908
+ t1 = $[4];
1909
+ }
1910
+ const sideOffset = t1 === void 0 ? 0 : t1;
1911
+ let t2;
1912
+ if ($[5] !== className) {
1913
+ t2 = cn("bg-foreground text-background animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-xs text-balance", className);
1914
+ $[5] = className;
1915
+ $[6] = t2;
1916
+ } else t2 = $[6];
1917
+ let t3;
1918
+ if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
1919
+ t3 = /* @__PURE__ */ jsx(TooltipPrimitive.Arrow, { className: "bg-foreground fill-foreground z-50 size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px]" });
1920
+ $[7] = t3;
1921
+ } else t3 = $[7];
1922
+ let t4;
1923
+ if ($[8] !== children || $[9] !== props || $[10] !== sideOffset || $[11] !== t2) {
1924
+ t4 = /* @__PURE__ */ jsx(TooltipPrimitive.Portal, { children: /* @__PURE__ */ jsxs(TooltipPrimitive.Content, {
1925
+ "data-slot": "tooltip-content",
1926
+ sideOffset,
1927
+ className: t2,
1928
+ ...props,
1929
+ children: [children, t3]
1930
+ }) });
1931
+ $[8] = children;
1932
+ $[9] = props;
1933
+ $[10] = sideOffset;
1934
+ $[11] = t2;
1935
+ $[12] = t4;
1936
+ } else t4 = $[12];
1937
+ return t4;
1938
+ }
1939
+
1940
+ //#endregion
1941
+ //#region src/components/button.tsx
1942
+ const buttonVariants = cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-all disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg:not([class*='size-'])]:size-4 shrink-0 [&_svg]:shrink-0 outline-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive", {
1943
+ variants: {
1944
+ variant: {
1945
+ default: "bg-primary text-primary-foreground hover:bg-primary/90",
1946
+ destructive: "bg-destructive text-white hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
1947
+ outline: "border bg-background shadow-xs hover:bg-accent hover:text-accent-foreground dark:bg-input/30 dark:border-input dark:hover:bg-input/50",
1948
+ secondary: "bg-secondary text-secondary-foreground hover:bg-secondary/80",
1949
+ ghost: "hover:bg-accent hover:text-accent-foreground dark:hover:bg-accent/50",
1950
+ link: "text-primary underline-offset-4 hover:underline"
1951
+ },
1952
+ size: {
1953
+ default: "h-9 px-4 py-2 has-[>svg]:px-3",
1954
+ sm: "h-8 rounded-md gap-1.5 px-3 has-[>svg]:px-2.5",
1955
+ lg: "h-10 rounded-md px-6 has-[>svg]:px-4",
1956
+ icon: "size-9",
1957
+ "icon-sm": "size-8",
1958
+ "icon-lg": "size-10"
1959
+ }
1960
+ },
1961
+ defaultVariants: {
1962
+ variant: "default",
1963
+ size: "default"
1964
+ }
1965
+ });
1966
+ function Button(t0) {
1967
+ const $ = c(14);
1968
+ let className;
1969
+ let props;
1970
+ let size;
1971
+ let t1;
1972
+ let variant;
1973
+ if ($[0] !== t0) {
1974
+ ({className, variant, size, asChild: t1, ...props} = t0);
1975
+ $[0] = t0;
1976
+ $[1] = className;
1977
+ $[2] = props;
1978
+ $[3] = size;
1979
+ $[4] = t1;
1980
+ $[5] = variant;
1981
+ } else {
1982
+ className = $[1];
1983
+ props = $[2];
1984
+ size = $[3];
1985
+ t1 = $[4];
1986
+ variant = $[5];
1987
+ }
1988
+ const Comp = (t1 === void 0 ? false : t1) ? Slot : "button";
1989
+ let t2;
1990
+ if ($[6] !== className || $[7] !== size || $[8] !== variant) {
1991
+ t2 = cn(buttonVariants({
1992
+ variant,
1993
+ size,
1994
+ className
1995
+ }));
1996
+ $[6] = className;
1997
+ $[7] = size;
1998
+ $[8] = variant;
1999
+ $[9] = t2;
2000
+ } else t2 = $[9];
2001
+ let t3;
2002
+ if ($[10] !== Comp || $[11] !== props || $[12] !== t2) {
2003
+ t3 = /* @__PURE__ */ jsx(Comp, {
2004
+ "data-slot": "button",
2005
+ className: t2,
2006
+ ...props
2007
+ });
2008
+ $[10] = Comp;
2009
+ $[11] = props;
2010
+ $[12] = t2;
2011
+ $[13] = t3;
2012
+ } else t3 = $[13];
2013
+ return t3;
2014
+ }
2015
+
2016
+ //#endregion
2017
+ //#region src/components/tooltip-icon-button.tsx
2018
+ const TooltipIconButton = forwardRef((t0, ref) => {
2019
+ const $ = c(24);
2020
+ let children;
2021
+ let className;
2022
+ let rest;
2023
+ let t1;
2024
+ let tooltip;
2025
+ if ($[0] !== t0) {
2026
+ ({children, tooltip, side: t1, className, ...rest} = t0);
2027
+ $[0] = t0;
2028
+ $[1] = children;
2029
+ $[2] = className;
2030
+ $[3] = rest;
2031
+ $[4] = t1;
2032
+ $[5] = tooltip;
2033
+ } else {
2034
+ children = $[1];
2035
+ className = $[2];
2036
+ rest = $[3];
2037
+ t1 = $[4];
2038
+ tooltip = $[5];
2039
+ }
2040
+ const side = t1 === void 0 ? "bottom" : t1;
2041
+ let t2;
2042
+ if ($[6] !== className) {
2043
+ t2 = cn("aui-button-icon size-6 p-1", className);
2044
+ $[6] = className;
2045
+ $[7] = t2;
2046
+ } else t2 = $[7];
2047
+ let t3;
2048
+ if ($[8] !== children) {
2049
+ t3 = /* @__PURE__ */ jsx(Slottable, { children });
2050
+ $[8] = children;
2051
+ $[9] = t3;
2052
+ } else t3 = $[9];
2053
+ let t4;
2054
+ if ($[10] !== tooltip) {
2055
+ t4 = /* @__PURE__ */ jsx("span", {
2056
+ className: "aui-sr-only sr-only",
2057
+ children: tooltip
2058
+ });
2059
+ $[10] = tooltip;
2060
+ $[11] = t4;
2061
+ } else t4 = $[11];
2062
+ let t5;
2063
+ if ($[12] !== ref || $[13] !== rest || $[14] !== t2 || $[15] !== t3 || $[16] !== t4) {
2064
+ t5 = /* @__PURE__ */ jsx(TooltipTrigger, {
2065
+ asChild: true,
2066
+ children: /* @__PURE__ */ jsxs(Button, {
2067
+ variant: "ghost",
2068
+ size: "icon",
2069
+ ...rest,
2070
+ className: t2,
2071
+ ref,
2072
+ children: [t3, t4]
2073
+ })
2074
+ });
2075
+ $[12] = ref;
2076
+ $[13] = rest;
2077
+ $[14] = t2;
2078
+ $[15] = t3;
2079
+ $[16] = t4;
2080
+ $[17] = t5;
2081
+ } else t5 = $[17];
2082
+ let t6;
2083
+ if ($[18] !== side || $[19] !== tooltip) {
2084
+ t6 = /* @__PURE__ */ jsx(TooltipContent, {
2085
+ side,
2086
+ children: tooltip
2087
+ });
2088
+ $[18] = side;
2089
+ $[19] = tooltip;
2090
+ $[20] = t6;
2091
+ } else t6 = $[20];
2092
+ let t7;
2093
+ if ($[21] !== t5 || $[22] !== t6) {
2094
+ t7 = /* @__PURE__ */ jsxs(Tooltip, { children: [t5, t6] });
2095
+ $[21] = t5;
2096
+ $[22] = t6;
2097
+ $[23] = t7;
2098
+ } else t7 = $[23];
2099
+ return t7;
2100
+ });
2101
+ TooltipIconButton.displayName = "TooltipIconButton";
2102
+
2103
+ //#endregion
2104
+ //#region src/components/attachment.tsx
2105
+ const useFileSrc = (file) => {
2106
+ const $ = c(3);
2107
+ const [src, setSrc] = useState(void 0);
2108
+ let t0;
2109
+ let t1;
2110
+ if ($[0] !== file) {
2111
+ t0 = () => {
2112
+ if (!file) {
2113
+ setSrc(void 0);
2114
+ return;
2115
+ }
2116
+ const objectUrl = URL.createObjectURL(file);
2117
+ setSrc(objectUrl);
2118
+ return () => {
2119
+ URL.revokeObjectURL(objectUrl);
2120
+ };
2121
+ };
2122
+ t1 = [file];
2123
+ $[0] = file;
2124
+ $[1] = t0;
2125
+ $[2] = t1;
2126
+ } else {
2127
+ t0 = $[1];
2128
+ t1 = $[2];
2129
+ }
2130
+ useEffect(t0, t1);
2131
+ return src;
2132
+ };
2133
+ const useAttachmentSrc = () => {
2134
+ const { file, src: src_0 } = useAssistantState(useShallow(_temp2));
2135
+ return useFileSrc(file) ?? src_0;
2136
+ };
2137
+ const AttachmentPreview = (t0) => {
2138
+ const $ = c(2);
2139
+ const { src } = t0;
2140
+ let t1;
2141
+ if ($[0] !== src) {
2142
+ t1 = /* @__PURE__ */ jsx("img", {
2143
+ src,
2144
+ alt: "Image Preview",
2145
+ width: 1,
2146
+ height: 1,
2147
+ className: "aui-attachment-preview-image-loaded block h-auto max-h-[80vh] w-auto max-w-full object-contain"
2148
+ });
2149
+ $[0] = src;
2150
+ $[1] = t1;
2151
+ } else t1 = $[1];
2152
+ return t1;
2153
+ };
2154
+ const AttachmentPreviewDialog = (t0) => {
2155
+ const $ = c(8);
2156
+ const { children } = t0;
2157
+ const src = useAttachmentSrc();
2158
+ if (!src) return children;
2159
+ let t1;
2160
+ if ($[0] !== children) {
2161
+ t1 = /* @__PURE__ */ jsx(DialogTrigger, {
2162
+ className: "aui-attachment-preview-trigger cursor-pointer transition-colors hover:bg-accent/50",
2163
+ asChild: true,
2164
+ children
2165
+ });
2166
+ $[0] = children;
2167
+ $[1] = t1;
2168
+ } else t1 = $[1];
2169
+ let t2;
2170
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
2171
+ t2 = /* @__PURE__ */ jsx(DialogTitle, {
2172
+ className: "aui-sr-only sr-only",
2173
+ children: "Image Attachment Preview"
2174
+ });
2175
+ $[2] = t2;
2176
+ } else t2 = $[2];
2177
+ let t3;
2178
+ if ($[3] !== src) {
2179
+ t3 = /* @__PURE__ */ jsxs(DialogContent, {
2180
+ className: "aui-attachment-preview-dialog-content p-2 sm:max-w-3xl [&_svg]:text-background [&>button]:rounded-full [&>button]:bg-foreground/60 [&>button]:p-1 [&>button]:opacity-100 [&>button]:!ring-0 [&>button]:hover:[&_svg]:text-destructive",
2181
+ children: [t2, /* @__PURE__ */ jsx("div", {
2182
+ className: "aui-attachment-preview relative mx-auto flex max-h-[80dvh] w-full items-center justify-center overflow-hidden bg-background",
2183
+ children: /* @__PURE__ */ jsx(AttachmentPreview, { src })
2184
+ })]
2185
+ });
2186
+ $[3] = src;
2187
+ $[4] = t3;
2188
+ } else t3 = $[4];
2189
+ let t4;
2190
+ if ($[5] !== t1 || $[6] !== t3) {
2191
+ t4 = /* @__PURE__ */ jsxs(Dialog, { children: [t1, t3] });
2192
+ $[5] = t1;
2193
+ $[6] = t3;
2194
+ $[7] = t4;
2195
+ } else t4 = $[7];
2196
+ return t4;
2197
+ };
2198
+ const AttachmentThumb = () => {
2199
+ const $ = c(8);
2200
+ const isImage = useAssistantState(_temp3);
2201
+ const src = useAttachmentSrc();
2202
+ let t0;
2203
+ if ($[0] !== src) {
2204
+ t0 = /* @__PURE__ */ jsx(AvatarImage, {
2205
+ src,
2206
+ alt: "Attachment preview",
2207
+ className: "aui-attachment-tile-image object-cover"
2208
+ });
2209
+ $[0] = src;
2210
+ $[1] = t0;
2211
+ } else t0 = $[1];
2212
+ const t1 = isImage ? 200 : 0;
2213
+ let t2;
2214
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
2215
+ t2 = /* @__PURE__ */ jsx(FileText, { className: "aui-attachment-tile-fallback-icon size-8 text-muted-foreground" });
2216
+ $[2] = t2;
2217
+ } else t2 = $[2];
2218
+ let t3;
2219
+ if ($[3] !== t1) {
2220
+ t3 = /* @__PURE__ */ jsx(AvatarFallback, {
2221
+ delayMs: t1,
2222
+ children: t2
2223
+ });
2224
+ $[3] = t1;
2225
+ $[4] = t3;
2226
+ } else t3 = $[4];
2227
+ let t4;
2228
+ if ($[5] !== t0 || $[6] !== t3) {
2229
+ t4 = /* @__PURE__ */ jsxs(Avatar, {
2230
+ className: "aui-attachment-tile-avatar h-full w-full rounded-none",
2231
+ children: [t0, t3]
2232
+ });
2233
+ $[5] = t0;
2234
+ $[6] = t3;
2235
+ $[7] = t4;
2236
+ } else t4 = $[7];
2237
+ return t4;
2238
+ };
2239
+ const AttachmentUI = () => {
2240
+ const $ = c(17);
2241
+ const isComposer = useAssistantApi().attachment.source === "composer";
2242
+ const isImage = useAssistantState(_temp4);
2243
+ const typeLabel = useAssistantState(_temp5);
2244
+ const t0 = isImage && "aui-attachment-root-composer only:[&>#attachment-tile]:size-24";
2245
+ let t1;
2246
+ if ($[0] !== t0) {
2247
+ t1 = cn("aui-attachment-root relative", t0);
2248
+ $[0] = t0;
2249
+ $[1] = t1;
2250
+ } else t1 = $[1];
2251
+ const t2 = isComposer && "aui-attachment-tile-composer border-foreground/20";
2252
+ let t3;
2253
+ if ($[2] !== t2) {
2254
+ t3 = cn("aui-attachment-tile size-14 cursor-pointer overflow-hidden rounded-[14px] border bg-muted transition-opacity hover:opacity-75", t2);
2255
+ $[2] = t2;
2256
+ $[3] = t3;
2257
+ } else t3 = $[3];
2258
+ const t4 = `${typeLabel} attachment`;
2259
+ let t5;
2260
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
2261
+ t5 = /* @__PURE__ */ jsx(AttachmentThumb, {});
2262
+ $[4] = t5;
2263
+ } else t5 = $[4];
2264
+ let t6;
2265
+ if ($[5] !== t3 || $[6] !== t4) {
2266
+ t6 = /* @__PURE__ */ jsx(AttachmentPreviewDialog, { children: /* @__PURE__ */ jsx(TooltipTrigger, {
2267
+ asChild: true,
2268
+ children: /* @__PURE__ */ jsx("div", {
2269
+ className: t3,
2270
+ role: "button",
2271
+ id: "attachment-tile",
2272
+ "aria-label": t4,
2273
+ children: t5
2274
+ })
2275
+ }) });
2276
+ $[5] = t3;
2277
+ $[6] = t4;
2278
+ $[7] = t6;
2279
+ } else t6 = $[7];
2280
+ let t7;
2281
+ if ($[8] !== isComposer) {
2282
+ t7 = isComposer && /* @__PURE__ */ jsx(AttachmentRemove, {});
2283
+ $[8] = isComposer;
2284
+ $[9] = t7;
2285
+ } else t7 = $[9];
2286
+ let t8;
2287
+ if ($[10] !== t1 || $[11] !== t6 || $[12] !== t7) {
2288
+ t8 = /* @__PURE__ */ jsxs(AttachmentPrimitive.Root, {
2289
+ className: t1,
2290
+ children: [t6, t7]
2291
+ });
2292
+ $[10] = t1;
2293
+ $[11] = t6;
2294
+ $[12] = t7;
2295
+ $[13] = t8;
2296
+ } else t8 = $[13];
2297
+ let t9;
2298
+ if ($[14] === Symbol.for("react.memo_cache_sentinel")) {
2299
+ t9 = /* @__PURE__ */ jsx(TooltipContent, {
2300
+ side: "top",
2301
+ children: /* @__PURE__ */ jsx(AttachmentPrimitive.Name, {})
2302
+ });
2303
+ $[14] = t9;
2304
+ } else t9 = $[14];
2305
+ let t10;
2306
+ if ($[15] !== t8) {
2307
+ t10 = /* @__PURE__ */ jsxs(Tooltip, { children: [t8, t9] });
2308
+ $[15] = t8;
2309
+ $[16] = t10;
2310
+ } else t10 = $[16];
2311
+ return t10;
2312
+ };
2313
+ const AttachmentRemove = () => {
2314
+ const $ = c(1);
2315
+ let t0;
2316
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
2317
+ t0 = /* @__PURE__ */ jsx(AttachmentPrimitive.Remove, {
2318
+ asChild: true,
2319
+ children: /* @__PURE__ */ jsx(TooltipIconButton, {
2320
+ tooltip: "Remove file",
2321
+ className: "aui-attachment-tile-remove absolute top-1.5 right-1.5 size-3.5 rounded-full bg-white text-muted-foreground opacity-100 shadow-sm hover:!bg-white [&_svg]:text-black hover:[&_svg]:text-destructive",
2322
+ side: "top",
2323
+ children: /* @__PURE__ */ jsx(XIcon, { className: "aui-attachment-remove-icon size-3 dark:stroke-[2.5px]" })
2324
+ })
2325
+ });
2326
+ $[0] = t0;
2327
+ } else t0 = $[0];
2328
+ return t0;
2329
+ };
2330
+ const UserMessageAttachments = () => {
2331
+ const $ = c(1);
2332
+ let t0;
2333
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
2334
+ t0 = /* @__PURE__ */ jsx("div", {
2335
+ className: "aui-user-message-attachments-end col-span-full col-start-1 row-start-1 flex w-full flex-row justify-end gap-2",
2336
+ children: /* @__PURE__ */ jsx(MessagePrimitive.Attachments, { components: { Attachment: AttachmentUI } })
2337
+ });
2338
+ $[0] = t0;
2339
+ } else t0 = $[0];
2340
+ return t0;
2341
+ };
2342
+ const ComposerAttachments = () => {
2343
+ const $ = c(1);
2344
+ let t0;
2345
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
2346
+ t0 = /* @__PURE__ */ jsx("div", {
2347
+ className: "aui-composer-attachments mb-2 flex w-full flex-row items-center gap-2 overflow-x-auto px-1.5 pt-0.5 pb-1 empty:hidden",
2348
+ children: /* @__PURE__ */ jsx(ComposerPrimitive.Attachments, { components: { Attachment: AttachmentUI } })
2349
+ });
2350
+ $[0] = t0;
2351
+ } else t0 = $[0];
2352
+ return t0;
2353
+ };
2354
+ const ComposerAddAttachment = () => {
2355
+ const $ = c(1);
2356
+ let t0;
2357
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
2358
+ t0 = /* @__PURE__ */ jsx(ComposerPrimitive.AddAttachment, {
2359
+ asChild: true,
2360
+ children: /* @__PURE__ */ jsx(TooltipIconButton, {
2361
+ tooltip: "Add Attachment",
2362
+ side: "bottom",
2363
+ variant: "ghost",
2364
+ size: "icon",
2365
+ className: "aui-composer-add-attachment size-[34px] rounded-full p-1 text-xs font-semibold hover:bg-muted-foreground/15 dark:border-muted-foreground/15 dark:hover:bg-muted-foreground/30",
2366
+ "aria-label": "Add Attachment",
2367
+ children: /* @__PURE__ */ jsx(PlusIcon, { className: "aui-attachment-add-icon size-5 stroke-[1.5px]" })
2368
+ })
2369
+ });
2370
+ $[0] = t0;
2371
+ } else t0 = $[0];
2372
+ return t0;
2373
+ };
2374
+ function _temp$2(c$1) {
2375
+ return c$1.type === "image";
2376
+ }
2377
+ function _temp2(t0) {
2378
+ const { attachment } = t0;
2379
+ if (attachment.type !== "image") return {};
2380
+ if (attachment.file) return { file: attachment.file };
2381
+ const src = attachment.content?.filter(_temp$2)[0]?.image;
2382
+ if (!src) return {};
2383
+ return { src };
2384
+ }
2385
+ function _temp3(t0) {
2386
+ const { attachment } = t0;
2387
+ return attachment.type === "image";
2388
+ }
2389
+ function _temp4(t0) {
2390
+ const { attachment } = t0;
2391
+ return attachment.type === "image";
2392
+ }
2393
+ function _temp5(t0) {
2394
+ const { attachment: attachment_0 } = t0;
2395
+ const type = attachment_0.type;
2396
+ switch (type) {
2397
+ case "image": return "Image";
2398
+ case "document": return "Document";
2399
+ case "file": return "File";
2400
+ default: {
2401
+ const _exhaustiveCheck = type;
2402
+ throw new Error(`Unknown attachment type: ${_exhaustiveCheck}`);
2403
+ }
2404
+ }
2405
+ }
2406
+
2407
+ //#endregion
2408
+ //#region src/components/markdown-text.tsx
2409
+ const MarkdownTextImpl = () => {
2410
+ const $ = c(1);
2411
+ let t0;
2412
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
2413
+ t0 = /* @__PURE__ */ jsx(MarkdownTextPrimitive, {
2414
+ remarkPlugins: [remarkGfm],
2415
+ className: "aui-md",
2416
+ components: defaultComponents
2417
+ });
2418
+ $[0] = t0;
2419
+ } else t0 = $[0];
2420
+ return t0;
2421
+ };
2422
+ const MarkdownText = memo(MarkdownTextImpl);
2423
+ const CodeHeader = (t0) => {
2424
+ const $ = c(17);
2425
+ const { language, code } = t0;
2426
+ const { isCopied, copyToClipboard } = useCopyToClipboard();
2427
+ let t1;
2428
+ if ($[0] !== code || $[1] !== copyToClipboard || $[2] !== isCopied) {
2429
+ t1 = () => {
2430
+ if (!code || isCopied) return;
2431
+ copyToClipboard(code);
2432
+ };
2433
+ $[0] = code;
2434
+ $[1] = copyToClipboard;
2435
+ $[2] = isCopied;
2436
+ $[3] = t1;
2437
+ } else t1 = $[3];
2438
+ const onCopy = t1;
2439
+ let t2;
2440
+ if ($[4] !== language) {
2441
+ t2 = /* @__PURE__ */ jsx("span", {
2442
+ className: "aui-code-header-language lowercase [&>span]:text-xs",
2443
+ children: language
2444
+ });
2445
+ $[4] = language;
2446
+ $[5] = t2;
2447
+ } else t2 = $[5];
2448
+ let t3;
2449
+ if ($[6] !== isCopied) {
2450
+ t3 = !isCopied && /* @__PURE__ */ jsx(CopyIcon, {});
2451
+ $[6] = isCopied;
2452
+ $[7] = t3;
2453
+ } else t3 = $[7];
2454
+ let t4;
2455
+ if ($[8] !== isCopied) {
2456
+ t4 = isCopied && /* @__PURE__ */ jsx(CheckIcon, {});
2457
+ $[8] = isCopied;
2458
+ $[9] = t4;
2459
+ } else t4 = $[9];
2460
+ let t5;
2461
+ if ($[10] !== onCopy || $[11] !== t3 || $[12] !== t4) {
2462
+ t5 = /* @__PURE__ */ jsxs(TooltipIconButton, {
2463
+ tooltip: "Copy",
2464
+ onClick: onCopy,
2465
+ children: [t3, t4]
2466
+ });
2467
+ $[10] = onCopy;
2468
+ $[11] = t3;
2469
+ $[12] = t4;
2470
+ $[13] = t5;
2471
+ } else t5 = $[13];
2472
+ let t6;
2473
+ if ($[14] !== t2 || $[15] !== t5) {
2474
+ t6 = /* @__PURE__ */ jsxs("div", {
2475
+ className: "aui-code-header-root mt-2 flex items-center justify-between gap-2 rounded-t-lg bg-muted-foreground/15 px-2 py-1 text-sm font-semibold text-foreground dark:bg-muted-foreground/20",
2476
+ children: [t2, t5]
2477
+ });
2478
+ $[14] = t2;
2479
+ $[15] = t5;
2480
+ $[16] = t6;
2481
+ } else t6 = $[16];
2482
+ return t6;
2483
+ };
2484
+ const useCopyToClipboard = (t0) => {
2485
+ const $ = c(7);
2486
+ let t1;
2487
+ if ($[0] !== t0) {
2488
+ t1 = t0 === void 0 ? {} : t0;
2489
+ $[0] = t0;
2490
+ $[1] = t1;
2491
+ } else t1 = $[1];
2492
+ const { copiedDuration: t2 } = t1;
2493
+ const copiedDuration = t2 === void 0 ? 3e3 : t2;
2494
+ const [isCopied, setIsCopied] = useState(false);
2495
+ let t3;
2496
+ if ($[2] !== copiedDuration) {
2497
+ t3 = (value) => {
2498
+ if (!value) return;
2499
+ navigator.clipboard.writeText(value).then(() => {
2500
+ setIsCopied(true);
2501
+ setTimeout(() => setIsCopied(false), copiedDuration);
2502
+ });
2503
+ };
2504
+ $[2] = copiedDuration;
2505
+ $[3] = t3;
2506
+ } else t3 = $[3];
2507
+ const copyToClipboard = t3;
2508
+ let t4;
2509
+ if ($[4] !== copyToClipboard || $[5] !== isCopied) {
2510
+ t4 = {
2511
+ isCopied,
2512
+ copyToClipboard
2513
+ };
2514
+ $[4] = copyToClipboard;
2515
+ $[5] = isCopied;
2516
+ $[6] = t4;
2517
+ } else t4 = $[6];
2518
+ return t4;
2519
+ };
2520
+ const defaultComponents = unstable_memoizeMarkdownComponents({
2521
+ h1: ({ className, ...props }) => /* @__PURE__ */ jsx("h1", {
2522
+ className: cn("aui-md-h1 mb-4 scroll-m-20 text-[25px] font-extrabold tracking-tight last:mb-0", className),
2523
+ ...props
2524
+ }),
2525
+ h2: ({ className, ...props }) => /* @__PURE__ */ jsx("h2", {
2526
+ className: cn("aui-md-h2 mt-4 mb-2 scroll-m-20 text-[21px] font-semibold tracking-tight first:mt-0 last:mb-0", className),
2527
+ ...props
2528
+ }),
2529
+ h3: ({ className, ...props }) => /* @__PURE__ */ jsx("h3", {
2530
+ className: cn("aui-md-h3 mt-3 mb-2 scroll-m-20 text-[19px] font-semibold tracking-tight first:mt-0 last:mb-0", className),
2531
+ ...props
2532
+ }),
2533
+ h4: ({ className, ...props }) => /* @__PURE__ */ jsx("h4", {
2534
+ className: cn("aui-md-h4 mt-3 mb-2 scroll-m-20 text-[17px] font-semibold tracking-tight first:mt-0 last:mb-0", className),
2535
+ ...props
2536
+ }),
2537
+ h5: ({ className, ...props }) => /* @__PURE__ */ jsx("h5", {
2538
+ className: cn("aui-md-h5 my-2 text-[15px] font-semibold first:mt-0 last:mb-0", className),
2539
+ ...props
2540
+ }),
2541
+ h6: ({ className, ...props }) => /* @__PURE__ */ jsx("h6", {
2542
+ className: cn("aui-md-h6 my-2 text-[15px] font-semibold first:mt-0 last:mb-0", className),
2543
+ ...props
2544
+ }),
2545
+ p: ({ className, ...props }) => /* @__PURE__ */ jsx("p", {
2546
+ className: cn("aui-md-p mt-2 mb-2 text-[13px] leading-relaxed first:mt-0 last:mb-0", className),
2547
+ ...props
2548
+ }),
2549
+ a: ({ className, ...props }) => /* @__PURE__ */ jsx("a", {
2550
+ className: cn("aui-md-a text-[13px] font-medium text-primary underline underline-offset-4", className),
2551
+ ...props
2552
+ }),
2553
+ blockquote: ({ className, ...props }) => /* @__PURE__ */ jsx("blockquote", {
2554
+ className: cn("aui-md-blockquote text-[13px] border-l-2 pl-3 italic", className),
2555
+ ...props
2556
+ }),
2557
+ ul: ({ className, ...props }) => /* @__PURE__ */ jsx("ul", {
2558
+ className: cn("aui-md-ul text-[13px] my-2 ml-4 list-disc [&>li]:mt-1", className),
2559
+ ...props
2560
+ }),
2561
+ ol: ({ className, ...props }) => /* @__PURE__ */ jsx("ol", {
2562
+ className: cn("aui-md-ol text-[13px] my-2 ml-4 list-decimal [&>li]:mt-1", className),
2563
+ ...props
2564
+ }),
2565
+ hr: ({ className, ...props }) => /* @__PURE__ */ jsx("hr", {
2566
+ className: cn("aui-md-hr my-2 border-b", className),
2567
+ ...props
2568
+ }),
2569
+ table: ({ className, ...props }) => /* @__PURE__ */ jsx("table", {
2570
+ className: cn("aui-md-table text-[13px] my-2 w-full border-separate border-spacing-0 overflow-y-auto", className),
2571
+ ...props
2572
+ }),
2573
+ th: ({ className, ...props }) => /* @__PURE__ */ jsx("th", {
2574
+ className: cn("aui-md-th bg-muted px-2 py-1 text-left font-bold first:rounded-tl-lg last:rounded-tr-lg [&[align=center]]:text-center [&[align=right]]:text-right", className),
2575
+ ...props
2576
+ }),
2577
+ td: ({ className, ...props }) => /* @__PURE__ */ jsx("td", {
2578
+ className: cn("aui-md-td border-b border-l px-2 py-1 text-left last:border-r [&[align=center]]:text-center [&[align=right]]:text-right", className),
2579
+ ...props
2580
+ }),
2581
+ tr: ({ className, ...props }) => /* @__PURE__ */ jsx("tr", {
2582
+ className: cn("aui-md-tr m-0 border-b p-0 first:border-t [&:last-child>td:first-child]:rounded-bl-lg [&:last-child>td:last-child]:rounded-br-lg", className),
2583
+ ...props
2584
+ }),
2585
+ sup: ({ className, ...props }) => /* @__PURE__ */ jsx("sup", {
2586
+ className: cn("aui-md-sup [&>a]:text-xs [&>a]:no-underline", className),
2587
+ ...props
2588
+ }),
2589
+ pre: ({ className, ...props }) => /* @__PURE__ */ jsx("pre", {
2590
+ className: cn("aui-md-pre text-[13px] overflow-x-auto !rounded-t-none rounded-b-lg bg-black p-2 text-white", className),
2591
+ ...props
2592
+ }),
2593
+ code: function Code({ className, ...props }) {
2594
+ return /* @__PURE__ */ jsx("code", {
2595
+ className: cn(!useIsMarkdownCodeBlock() && "aui-md-inline-code text-[13px] rounded border bg-muted font-semibold", className),
2596
+ ...props
2597
+ });
2598
+ },
2599
+ CodeHeader
2600
+ });
2601
+
2602
+ //#endregion
2603
+ //#region src/lib/mcp-transport.ts
2604
+ /**
2605
+ * MCP Transport Utilities
2606
+ *
2607
+ * Shared transport creation logic for MCP sources.
2608
+ * This eliminates duplication between MCPToolsProvider and useMCPSource.
2609
+ */
2610
+ /**
2611
+ * Creates the appropriate MCP transport based on source configuration.
2612
+ *
2613
+ * @param config - The MCP source configuration
2614
+ * @param transportType - For HTTP sources, specifies whether to use HTTP or SSE transport
2615
+ * @returns A configured MCP Transport instance
2616
+ *
2617
+ * @example Tab-based transport (same-tab or iframe)
2618
+ * ```ts
2619
+ * const transport = createMCPTransport({ type: 'tab' })
2620
+ * ```
2621
+ *
2622
+ * @example HTTP transport with auth
2623
+ * ```ts
2624
+ * const transport = createMCPTransport({
2625
+ * type: 'http',
2626
+ * url: 'https://example.com/mcp',
2627
+ * authToken: 'secret'
2628
+ * }, 'http')
2629
+ * ```
2630
+ */
2631
+ function createMCPTransport(config, transportType = "http") {
2632
+ if (config.type === "tab") return new TabClientTransport({
2633
+ targetOrigin: config.targetOrigin ?? window.location.origin,
2634
+ channelId: config.channelId ?? "mcp-default"
2635
+ });
2636
+ const serverUrl = new URL(config.url);
2637
+ const headers = {
2638
+ Accept: "application/json, text/event-stream",
2639
+ ...config.customHeaders ?? {}
2640
+ };
2641
+ if (config.authToken) headers.Authorization = `Bearer ${config.authToken}`;
2642
+ const transportOptions = { requestInit: { headers } };
2643
+ if (transportType === "sse") return new SSEClientTransport(serverUrl, transportOptions);
2644
+ return new StreamableHTTPClientTransport(serverUrl, transportOptions);
2645
+ }
2646
+
2647
+ //#endregion
2648
+ //#region src/providers/MCPToolsProvider.tsx
2649
+ /**
2650
+ * MCP Tools Provider
2651
+ *
2652
+ * Simplified provider for managing tools from multiple MCP sources.
2653
+ * Sources can be tab-based (same-tab, iframes) or HTTP-based (remote servers).
2654
+ *
2655
+ * @example Basic usage
2656
+ * ```tsx
2657
+ * <MCPToolsProvider>
2658
+ * <App />
2659
+ * </MCPToolsProvider>
2660
+ * ```
2661
+ *
2662
+ * @example Using the hook
2663
+ * ```tsx
2664
+ * const { tools, addSource, callTool } = useMCPTools()
2665
+ * await addSource('remote', { type: 'http', url: 'http://localhost:8888/mcp' })
2666
+ * ```
2667
+ */
2668
+ /** Well-known source IDs */
2669
+ const SOURCE_LOCAL = "local";
2670
+ const SOURCE_REMOTE = "remote";
2671
+ const MCPToolsContext = createContext(null);
2672
+ function MCPToolsProvider({ children, autoConnectLocal = true, onToolsChange }) {
2673
+ const sourcesRef = useRef(/* @__PURE__ */ new Map());
2674
+ const [, forceUpdate] = useState({});
2675
+ const [toolsList, setToolsList] = useState([]);
2676
+ /**
2677
+ * Rebuild tools list from all sources
2678
+ */
2679
+ const rebuildTools = useCallback(() => {
2680
+ const allTools = [];
2681
+ sourcesRef.current.forEach((source) => {
2682
+ source.tools.forEach((tool) => {
2683
+ allTools.push({
2684
+ ...tool,
2685
+ _sourceId: source.id
2686
+ });
2687
+ });
2688
+ });
2689
+ setToolsList(allTools);
2690
+ }, []);
2691
+ /**
2692
+ * Get public source state (without client reference)
2693
+ */
2694
+ const getPublicSource = useCallback((source_0) => {
2695
+ return {
2696
+ id: source_0.id,
2697
+ config: source_0.config,
2698
+ state: source_0.state,
2699
+ error: source_0.error,
2700
+ tools: source_0.tools,
2701
+ resources: source_0.resources,
2702
+ resourceTemplates: source_0.resourceTemplates,
2703
+ prompts: source_0.prompts
2704
+ };
2705
+ }, []);
2706
+ /**
2707
+ * Add a new source
2708
+ */
2709
+ const addSource = useCallback(async (id, config) => {
2710
+ if (sourcesRef.current.has(id)) await removeSource(id);
2711
+ const sourceState = {
2712
+ id,
2713
+ config,
2714
+ state: "connecting",
2715
+ error: null,
2716
+ tools: [],
2717
+ resources: [],
2718
+ resourceTemplates: [],
2719
+ prompts: [],
2720
+ client: null,
2721
+ transport: null
2722
+ };
2723
+ sourcesRef.current.set(id, sourceState);
2724
+ forceUpdate({});
2725
+ try {
2726
+ const client = new Client({
2727
+ name: `MCP-Source-${id}`,
2728
+ version: "1.0.0"
2729
+ });
2730
+ const transport = createMCPTransport(config);
2731
+ await client.connect(transport);
2732
+ sourceState.client = client;
2733
+ sourceState.transport = transport;
2734
+ const { tools } = await client.listTools();
2735
+ sourceState.tools = tools;
2736
+ sourceState.state = "connected";
2737
+ client.setNotificationHandler(ToolListChangedNotificationSchema, async () => {
2738
+ try {
2739
+ sourceState.tools = (await client.listTools()).tools;
2740
+ rebuildTools();
2741
+ forceUpdate({});
2742
+ } catch (err_0) {
2743
+ console.error(`[MCPToolsProvider:${id}] Failed to update tools:`, err_0);
2744
+ }
2745
+ });
2746
+ rebuildTools();
2747
+ forceUpdate({});
2748
+ } catch (err) {
2749
+ const error = err instanceof Error ? err : new Error(String(err));
2750
+ console.error(`[MCPToolsProvider:${id}] Connection failed:`, error);
2751
+ sourceState.state = "error";
2752
+ sourceState.error = error;
2753
+ forceUpdate({});
2754
+ }
2755
+ }, [rebuildTools]);
2756
+ /**
2757
+ * Remove a source
2758
+ */
2759
+ const removeSource = useCallback(async (id_0) => {
2760
+ const source_1 = sourcesRef.current.get(id_0);
2761
+ if (!source_1) return;
2762
+ if (source_1.client) try {
2763
+ await source_1.client.close();
2764
+ } catch (err_1) {
2765
+ console.error(`[MCPToolsProvider:${id_0}] Error closing client:`, err_1);
2766
+ }
2767
+ if (source_1.transport) try {
2768
+ await source_1.transport.close();
2769
+ } catch (err_2) {
2770
+ console.error(`[MCPToolsProvider:${id_0}] Error closing transport:`, err_2);
2771
+ }
2772
+ sourcesRef.current.delete(id_0);
2773
+ rebuildTools();
2774
+ forceUpdate({});
2775
+ }, [rebuildTools]);
2776
+ /**
2777
+ * Get a source by ID
2778
+ */
2779
+ const getSource = useCallback((id_1) => {
2780
+ const source_2 = sourcesRef.current.get(id_1);
2781
+ return source_2 ? getPublicSource(source_2) : void 0;
2782
+ }, [getPublicSource]);
2783
+ /**
2784
+ * Check if a source is connected
2785
+ */
2786
+ const isConnected = useCallback((id_2) => {
2787
+ return sourcesRef.current.get(id_2)?.state === "connected";
2788
+ }, []);
2789
+ /**
2790
+ * Call a tool on a specific source
2791
+ */
2792
+ const callToolOnSource = useCallback(async (sourceId, name, args) => {
2793
+ const source_4 = sourcesRef.current.get(sourceId);
2794
+ if (!source_4?.client) throw new Error(`Source '${sourceId}' not connected`);
2795
+ return await source_4.client.callTool({
2796
+ name,
2797
+ arguments: args
2798
+ });
2799
+ }, []);
2800
+ /**
2801
+ * Call a tool (auto-routes based on tool name)
2802
+ */
2803
+ const callTool = useCallback(async (name_0, args_0) => {
2804
+ const tool_0 = toolsList.find((t) => t.name === name_0);
2805
+ if (!tool_0) throw new Error(`Tool '${name_0}' not found`);
2806
+ return callToolOnSource(tool_0._sourceId, name_0, args_0);
2807
+ }, [toolsList, callToolOnSource]);
2808
+ /**
2809
+ * Get sources map for context (public view)
2810
+ */
2811
+ const sources = useMemo(() => {
2812
+ const publicSources = /* @__PURE__ */ new Map();
2813
+ sourcesRef.current.forEach((source_5) => {
2814
+ publicSources.set(source_5.id, getPublicSource(source_5));
2815
+ });
2816
+ return publicSources;
2817
+ }, [toolsList, getPublicSource]);
2818
+ useEffect(() => {
2819
+ if (autoConnectLocal) {
2820
+ const timer = setTimeout(() => {
2821
+ addSource(SOURCE_LOCAL, { type: "tab" });
2822
+ }, MCP_TAB_CONNECT_DELAY_MS);
2823
+ return () => clearTimeout(timer);
2824
+ }
2825
+ }, [autoConnectLocal, addSource]);
2826
+ useEffect(() => {
2827
+ onToolsChange?.(toolsList);
2828
+ }, [toolsList, onToolsChange]);
2829
+ useEffect(() => {
2830
+ const sources_0 = sourcesRef;
2831
+ return () => {
2832
+ sources_0.current.forEach((source_6) => {
2833
+ if (source_6.client) source_6.client.close().catch(console.error);
2834
+ if (source_6.transport) source_6.transport.close().catch(console.error);
2835
+ });
2836
+ sources_0.current.clear();
2837
+ };
2838
+ }, []);
2839
+ const value = useMemo(() => ({
2840
+ tools: toolsList,
2841
+ sources,
2842
+ addSource,
2843
+ removeSource,
2844
+ getSource,
2845
+ isConnected,
2846
+ callTool,
2847
+ callToolOnSource
2848
+ }), [
2849
+ toolsList,
2850
+ sources,
2851
+ addSource,
2852
+ removeSource,
2853
+ getSource,
2854
+ isConnected,
2855
+ callTool,
2856
+ callToolOnSource
2857
+ ]);
2858
+ return /* @__PURE__ */ jsx(MCPToolsContext.Provider, {
2859
+ value,
2860
+ children
2861
+ });
2862
+ }
2863
+ /**
2864
+ * Hook to access MCP Tools context
2865
+ */
2866
+ function useMCPTools() {
2867
+ const context = useContext(MCPToolsContext);
2868
+ if (!context) throw new Error("useMCPTools must be used within an MCPToolsProvider");
2869
+ return context;
2870
+ }
2871
+
2872
+ //#endregion
2873
+ //#region src/components/RemoteMCPSettings.tsx
2874
+ /**
2875
+ * Remote MCP Settings
2876
+ *
2877
+ * A dialog component for managing remote MCP server connections.
2878
+ * Allows users to add, connect, and disconnect from remote MCP servers.
2879
+ */
2880
+ const RemoteMCPSettings = () => {
2881
+ const { sources, addSource, removeSource } = useMCPTools();
2882
+ const [isOpen, setIsOpen] = useState(false);
2883
+ const [url, setUrl] = useState("");
2884
+ const [isConnecting, setIsConnecting] = useState(false);
2885
+ const [error, setError] = useState(null);
2886
+ const remoteServers = [];
2887
+ sources.forEach((source, id) => {
2888
+ if (source.config.type === "http" && id !== "local") remoteServers.push({
2889
+ id,
2890
+ url: source.config.url
2891
+ });
2892
+ });
2893
+ const handleConnect = useCallback(async () => {
2894
+ if (!url.trim()) {
2895
+ setError("Please enter a URL");
2896
+ return;
2897
+ }
2898
+ try {
2899
+ new URL(url);
2900
+ } catch {
2901
+ setError("Please enter a valid URL");
2902
+ return;
2903
+ }
2904
+ setIsConnecting(true);
2905
+ setError(null);
2906
+ try {
2907
+ await addSource(remoteServers.length === 0 ? SOURCE_REMOTE : `remote-${Date.now()}`, {
2908
+ type: "http",
2909
+ url
2910
+ });
2911
+ setUrl("");
2912
+ } catch (err) {
2913
+ setError(err instanceof Error ? err.message : "Failed to connect");
2914
+ } finally {
2915
+ setIsConnecting(false);
2916
+ }
2917
+ }, [
2918
+ url,
2919
+ addSource,
2920
+ remoteServers.length
2921
+ ]);
2922
+ const handleDisconnect = useCallback(async (serverId_0) => {
2923
+ await removeSource(serverId_0);
2924
+ }, [removeSource]);
2925
+ const handleKeyDown = useCallback((e) => {
2926
+ if (e.key === "Enter" && !isConnecting) handleConnect();
2927
+ }, [handleConnect, isConnecting]);
2928
+ const connectedCount = remoteServers.filter((s) => {
2929
+ return sources.get(s.id)?.state === "connected";
2930
+ }).length;
2931
+ return /* @__PURE__ */ jsxs(Dialog, {
2932
+ open: isOpen,
2933
+ onOpenChange: setIsOpen,
2934
+ children: [/* @__PURE__ */ jsx(DialogTrigger, {
2935
+ asChild: true,
2936
+ children: /* @__PURE__ */ jsxs(TooltipIconButton, {
2937
+ tooltip: "Connect MCP Server",
2938
+ variant: "ghost",
2939
+ size: "sm",
2940
+ className: cn("gap-2 rounded-full text-muted-foreground hover:text-foreground", connectedCount > 0 && "text-green-600 dark:text-green-400"),
2941
+ children: [/* @__PURE__ */ jsx(Plug, { className: "h-4 w-4" }), connectedCount > 0 && /* @__PURE__ */ jsx("span", {
2942
+ className: "text-xs",
2943
+ children: connectedCount
2944
+ })]
2945
+ })
2946
+ }), /* @__PURE__ */ jsxs(DialogContent, {
2947
+ className: "sm:max-w-md",
2948
+ children: [/* @__PURE__ */ jsxs(DialogHeader, { children: [/* @__PURE__ */ jsx(DialogTitle, { children: "Remote MCP Servers" }), /* @__PURE__ */ jsx(DialogDescription, { children: "Connect to remote MCP servers to access their tools, resources, and prompts." })] }), /* @__PURE__ */ jsxs("div", {
2949
+ className: "space-y-4",
2950
+ children: [
2951
+ /* @__PURE__ */ jsxs("div", {
2952
+ className: "space-y-2",
2953
+ children: [
2954
+ /* @__PURE__ */ jsx("label", {
2955
+ htmlFor: "mcp-url",
2956
+ className: "text-sm font-medium",
2957
+ children: "Server URL"
2958
+ }),
2959
+ /* @__PURE__ */ jsxs("div", {
2960
+ className: "flex gap-2",
2961
+ children: [/* @__PURE__ */ jsx("input", {
2962
+ id: "mcp-url",
2963
+ type: "url",
2964
+ value: url,
2965
+ onChange: (e_0) => setUrl(e_0.target.value),
2966
+ onKeyDown: handleKeyDown,
2967
+ placeholder: "https://mcp.example.com/sse",
2968
+ disabled: isConnecting,
2969
+ className: cn("flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm transition-colors", "placeholder:text-muted-foreground", "focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring", "disabled:cursor-not-allowed disabled:opacity-50")
2970
+ }), /* @__PURE__ */ jsx(Button, {
2971
+ onClick: () => void handleConnect(),
2972
+ disabled: isConnecting || !url.trim(),
2973
+ size: "sm",
2974
+ className: "shrink-0",
2975
+ children: isConnecting ? /* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }) : /* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" })
2976
+ })]
2977
+ }),
2978
+ error && /* @__PURE__ */ jsx("p", {
2979
+ className: "text-xs text-destructive",
2980
+ children: error
2981
+ })
2982
+ ]
2983
+ }),
2984
+ remoteServers.length > 0 && /* @__PURE__ */ jsxs("div", {
2985
+ className: "space-y-2",
2986
+ children: [/* @__PURE__ */ jsx("label", {
2987
+ className: "text-sm font-medium",
2988
+ children: "Connected Servers"
2989
+ }), /* @__PURE__ */ jsx("div", {
2990
+ className: "space-y-2",
2991
+ children: remoteServers.map((server) => {
2992
+ const source_1 = sources.get(server.id);
2993
+ const isConnected = source_1?.state === "connected";
2994
+ const isLoading = source_1?.state === "connecting";
2995
+ return /* @__PURE__ */ jsxs("div", {
2996
+ className: "flex items-center gap-2 rounded-md border border-border bg-muted/50 px-3 py-2",
2997
+ children: [
2998
+ /* @__PURE__ */ jsx("div", { className: cn("h-2 w-2 shrink-0 rounded-full", isConnected && "bg-green-500", isLoading && "bg-yellow-500 animate-pulse", source_1?.state === "error" && "bg-red-500") }),
2999
+ /* @__PURE__ */ jsx("span", {
3000
+ className: "flex-1 truncate text-xs text-muted-foreground",
3001
+ children: server.url
3002
+ }),
3003
+ isConnected && source_1 && /* @__PURE__ */ jsxs("span", {
3004
+ className: "text-xs text-muted-foreground",
3005
+ children: [source_1.tools.length, " tools"]
3006
+ }),
3007
+ /* @__PURE__ */ jsx("button", {
3008
+ type: "button",
3009
+ onClick: () => void handleDisconnect(server.id),
3010
+ className: "shrink-0 rounded p-1 text-muted-foreground hover:bg-destructive/10 hover:text-destructive",
3011
+ "aria-label": "Disconnect server",
3012
+ children: isLoading ? /* @__PURE__ */ jsx(Loader2, { className: "h-3 w-3 animate-spin" }) : /* @__PURE__ */ jsx(X, { className: "h-3 w-3" })
3013
+ })
3014
+ ]
3015
+ }, server.id);
3016
+ })
3017
+ })]
3018
+ }),
3019
+ /* @__PURE__ */ jsx("p", {
3020
+ className: "text-xs text-muted-foreground",
3021
+ children: "Enter the URL of an MCP server that supports the Streamable HTTP transport (SSE)."
3022
+ })
3023
+ ]
3024
+ })]
3025
+ })]
3026
+ });
3027
+ };
3028
+
3029
+ //#endregion
3030
+ //#region src/components/tool-fallback.tsx
3031
+ const ToolFallback = (t0) => {
3032
+ const $ = c(15);
3033
+ const { toolName, argsText, result } = t0;
3034
+ const [isCollapsed, setIsCollapsed] = useState(true);
3035
+ let t1;
3036
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
3037
+ t1 = /* @__PURE__ */ jsx(CheckIcon, { className: "aui-tool-fallback-icon size-3.5 text-emerald-500" });
3038
+ $[0] = t1;
3039
+ } else t1 = $[0];
3040
+ let t2;
3041
+ if ($[1] !== toolName) {
3042
+ t2 = /* @__PURE__ */ jsx("p", {
3043
+ className: "aui-tool-fallback-title flex-grow text-sm font-medium",
3044
+ children: toolName
3045
+ });
3046
+ $[1] = toolName;
3047
+ $[2] = t2;
3048
+ } else t2 = $[2];
3049
+ let t3;
3050
+ if ($[3] !== isCollapsed) {
3051
+ t3 = /* @__PURE__ */ jsx(Button, {
3052
+ variant: "ghost",
3053
+ size: "sm",
3054
+ className: "h-6 w-6 p-0",
3055
+ onClick: () => setIsCollapsed(!isCollapsed),
3056
+ children: isCollapsed ? /* @__PURE__ */ jsx(ChevronUpIcon, { className: "size-3.5" }) : /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-3.5" })
3057
+ });
3058
+ $[3] = isCollapsed;
3059
+ $[4] = t3;
3060
+ } else t3 = $[4];
3061
+ let t4;
3062
+ if ($[5] !== t2 || $[6] !== t3) {
3063
+ t4 = /* @__PURE__ */ jsxs("div", {
3064
+ className: "aui-tool-fallback-header flex items-center gap-2 px-3",
3065
+ children: [
3066
+ t1,
3067
+ t2,
3068
+ t3
3069
+ ]
3070
+ });
3071
+ $[5] = t2;
3072
+ $[6] = t3;
3073
+ $[7] = t4;
3074
+ } else t4 = $[7];
3075
+ let t5;
3076
+ if ($[8] !== argsText || $[9] !== isCollapsed || $[10] !== result) {
3077
+ t5 = !isCollapsed && /* @__PURE__ */ jsxs("div", {
3078
+ className: "aui-tool-fallback-content flex flex-col gap-2 border-t border-border/20 pt-2",
3079
+ children: [/* @__PURE__ */ jsxs("div", {
3080
+ className: "aui-tool-fallback-args-root px-3",
3081
+ children: [/* @__PURE__ */ jsx("span", {
3082
+ className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground/70",
3083
+ children: "Input"
3084
+ }), /* @__PURE__ */ jsx("pre", {
3085
+ className: "aui-tool-fallback-args-value mt-1 max-h-40 overflow-auto rounded-lg bg-muted/30 px-2 py-1.5 font-mono text-[11px] leading-relaxed text-foreground/80 whitespace-pre-wrap",
3086
+ children: argsText
3087
+ })]
3088
+ }), result !== void 0 && /* @__PURE__ */ jsxs("div", {
3089
+ className: "aui-tool-fallback-result-root border-t border-dashed border-border/20 px-3 pt-2",
3090
+ children: [/* @__PURE__ */ jsx("span", {
3091
+ className: "text-[10px] font-medium uppercase tracking-wide text-muted-foreground/70",
3092
+ children: "Output"
3093
+ }), /* @__PURE__ */ jsx("pre", {
3094
+ className: "aui-tool-fallback-result-content mt-1 max-h-60 overflow-auto rounded-lg bg-muted/30 px-2 py-1.5 font-mono text-[11px] leading-relaxed text-foreground/80 whitespace-pre-wrap",
3095
+ children: typeof result === "string" ? result : JSON.stringify(result, null, 2)
3096
+ })]
3097
+ })]
3098
+ });
3099
+ $[8] = argsText;
3100
+ $[9] = isCollapsed;
3101
+ $[10] = result;
3102
+ $[11] = t5;
3103
+ } else t5 = $[11];
3104
+ let t6;
3105
+ if ($[12] !== t4 || $[13] !== t5) {
3106
+ t6 = /* @__PURE__ */ jsxs("div", {
3107
+ className: "aui-tool-fallback-root mb-3 flex w-full flex-col gap-2 rounded-xl border border-border/20 bg-muted/5 py-2",
3108
+ children: [t4, t5]
3109
+ });
3110
+ $[12] = t4;
3111
+ $[13] = t5;
3112
+ $[14] = t6;
3113
+ } else t6 = $[14];
3114
+ return t6;
3115
+ };
3116
+
3117
+ //#endregion
3118
+ //#region src/components/live-waveform.tsx
3119
+ const LiveWaveform = (t0) => {
3120
+ const $ = c(54);
3121
+ let barColor;
3122
+ let className;
3123
+ let manualAudioLevel;
3124
+ let props;
3125
+ let t1;
3126
+ let t10;
3127
+ let t2;
3128
+ let t3;
3129
+ let t4;
3130
+ let t5;
3131
+ let t6;
3132
+ let t7;
3133
+ let t8;
3134
+ let t9;
3135
+ if ($[0] !== t0) {
3136
+ ({active: t1, processing: t2, barWidth: t3, barGap: t4, barRadius: t5, barColor, fadeEdges: t6, fadeWidth: t7, height: t8, sensitivity: t9, mode: t10, manualAudioLevel, className, ...props} = t0);
3137
+ $[0] = t0;
3138
+ $[1] = barColor;
3139
+ $[2] = className;
3140
+ $[3] = manualAudioLevel;
3141
+ $[4] = props;
3142
+ $[5] = t1;
3143
+ $[6] = t10;
3144
+ $[7] = t2;
3145
+ $[8] = t3;
3146
+ $[9] = t4;
3147
+ $[10] = t5;
3148
+ $[11] = t6;
3149
+ $[12] = t7;
3150
+ $[13] = t8;
3151
+ $[14] = t9;
3152
+ } else {
3153
+ barColor = $[1];
3154
+ className = $[2];
3155
+ manualAudioLevel = $[3];
3156
+ props = $[4];
3157
+ t1 = $[5];
3158
+ t10 = $[6];
3159
+ t2 = $[7];
3160
+ t3 = $[8];
3161
+ t4 = $[9];
3162
+ t5 = $[10];
3163
+ t6 = $[11];
3164
+ t7 = $[12];
3165
+ t8 = $[13];
3166
+ t9 = $[14];
3167
+ }
3168
+ const active = t1 === void 0 ? false : t1;
3169
+ const processing = t2 === void 0 ? false : t2;
3170
+ const barWidth = t3 === void 0 ? 3 : t3;
3171
+ const barGap = t4 === void 0 ? 1 : t4;
3172
+ const barRadius = t5 === void 0 ? 1.5 : t5;
3173
+ const fadeEdges = t6 === void 0 ? true : t6;
3174
+ const fadeWidth = t7 === void 0 ? 24 : t7;
3175
+ const height = t8 === void 0 ? 64 : t8;
3176
+ const sensitivity = t9 === void 0 ? 1 : t9;
3177
+ const mode = t10 === void 0 ? "static" : t10;
3178
+ const canvasRef = useRef(null);
3179
+ const containerRef = useRef(null);
3180
+ let t11;
3181
+ if ($[15] === Symbol.for("react.memo_cache_sentinel")) {
3182
+ t11 = [];
3183
+ $[15] = t11;
3184
+ } else t11 = $[15];
3185
+ const historyRef = useRef(t11);
3186
+ useRef(0);
3187
+ const lastUpdateRef = useRef(0);
3188
+ const processingAnimationRef = useRef(null);
3189
+ let t12;
3190
+ if ($[16] === Symbol.for("react.memo_cache_sentinel")) {
3191
+ t12 = [];
3192
+ $[16] = t12;
3193
+ } else t12 = $[16];
3194
+ const lastActiveDataRef = useRef(t12);
3195
+ const transitionProgressRef = useRef(0);
3196
+ let t13;
3197
+ if ($[17] === Symbol.for("react.memo_cache_sentinel")) {
3198
+ t13 = [];
3199
+ $[17] = t13;
3200
+ } else t13 = $[17];
3201
+ const staticBarsRef = useRef(t13);
3202
+ const needsRedrawRef = useRef(true);
3203
+ const gradientCacheRef = useRef(null);
3204
+ const lastWidthRef = useRef(0);
3205
+ const heightStyle = typeof height === "number" ? `${height}px` : height;
3206
+ let t14;
3207
+ let t15;
3208
+ if ($[18] === Symbol.for("react.memo_cache_sentinel")) {
3209
+ t14 = () => {
3210
+ const canvas = canvasRef.current;
3211
+ const container = containerRef.current;
3212
+ if (!canvas || !container) return;
3213
+ const resizeObserver = new ResizeObserver(() => {
3214
+ const rect = container.getBoundingClientRect();
3215
+ const dpr = window.devicePixelRatio || 1;
3216
+ canvas.width = rect.width * dpr;
3217
+ canvas.height = rect.height * dpr;
3218
+ canvas.style.width = `${rect.width}px`;
3219
+ canvas.style.height = `${rect.height}px`;
3220
+ const ctx = canvas.getContext("2d");
3221
+ if (ctx) ctx.scale(dpr, dpr);
3222
+ gradientCacheRef.current = null;
3223
+ lastWidthRef.current = rect.width;
3224
+ needsRedrawRef.current = true;
3225
+ });
3226
+ resizeObserver.observe(container);
3227
+ return () => resizeObserver.disconnect();
3228
+ };
3229
+ t15 = [];
3230
+ $[18] = t14;
3231
+ $[19] = t15;
3232
+ } else {
3233
+ t14 = $[18];
3234
+ t15 = $[19];
3235
+ }
3236
+ useEffect(t14, t15);
3237
+ let t16;
3238
+ let t17;
3239
+ if ($[20] !== active || $[21] !== barGap || $[22] !== barWidth || $[23] !== mode || $[24] !== processing) {
3240
+ t16 = () => {
3241
+ if (processing && !active) {
3242
+ let time = 0;
3243
+ transitionProgressRef.current = 0;
3244
+ const animateProcessing = () => {
3245
+ time = time + .03;
3246
+ transitionProgressRef.current = Math.min(1, transitionProgressRef.current + .02);
3247
+ const processingData = [];
3248
+ const barCount = Math.floor((containerRef.current?.getBoundingClientRect().width || 200) / (barWidth + barGap));
3249
+ if (mode === "static") {
3250
+ const halfCount = Math.floor(barCount / 2);
3251
+ for (let i = 0; i < barCount; i++) {
3252
+ const normalizedPosition = (i - halfCount) / halfCount;
3253
+ const centerWeight = 1 - Math.abs(normalizedPosition) * .4;
3254
+ const wave1 = Math.sin(time * 1.5 + normalizedPosition * 3) * .25;
3255
+ const wave2 = Math.sin(time * .8 - normalizedPosition * 2) * .2;
3256
+ const wave3 = Math.cos(time * 2 + normalizedPosition) * .15;
3257
+ const processingValue = (.2 + (wave1 + wave2 + wave3)) * centerWeight;
3258
+ let finalValue = processingValue;
3259
+ if (lastActiveDataRef.current.length > 0 && transitionProgressRef.current < 1) {
3260
+ const lastDataIndex = Math.min(i, lastActiveDataRef.current.length - 1);
3261
+ finalValue = (lastActiveDataRef.current[lastDataIndex] || 0) * (1 - transitionProgressRef.current) + processingValue * transitionProgressRef.current;
3262
+ }
3263
+ processingData.push(Math.max(.05, Math.min(1, finalValue)));
3264
+ }
3265
+ } else for (let i_0 = 0; i_0 < barCount; i_0++) {
3266
+ const normalizedPosition_0 = (i_0 - barCount / 2) / (barCount / 2);
3267
+ const centerWeight_0 = 1 - Math.abs(normalizedPosition_0) * .4;
3268
+ const wave1_0 = Math.sin(time * 1.5 + i_0 * .15) * .25;
3269
+ const wave2_0 = Math.sin(time * .8 - i_0 * .1) * .2;
3270
+ const wave3_0 = Math.cos(time * 2 + i_0 * .05) * .15;
3271
+ const processingValue_0 = (.2 + (wave1_0 + wave2_0 + wave3_0)) * centerWeight_0;
3272
+ let finalValue_0 = processingValue_0;
3273
+ if (lastActiveDataRef.current.length > 0 && transitionProgressRef.current < 1) {
3274
+ const lastDataIndex_0 = Math.floor(i_0 / barCount * lastActiveDataRef.current.length);
3275
+ finalValue_0 = (lastActiveDataRef.current[lastDataIndex_0] || 0) * (1 - transitionProgressRef.current) + processingValue_0 * transitionProgressRef.current;
3276
+ }
3277
+ processingData.push(Math.max(.05, Math.min(1, finalValue_0)));
3278
+ }
3279
+ if (mode === "static") staticBarsRef.current = processingData;
3280
+ else historyRef.current = processingData;
3281
+ needsRedrawRef.current = true;
3282
+ processingAnimationRef.current = requestAnimationFrame(animateProcessing);
3283
+ };
3284
+ animateProcessing();
3285
+ return () => {
3286
+ if (processingAnimationRef.current) cancelAnimationFrame(processingAnimationRef.current);
3287
+ };
3288
+ }
3289
+ if (!active && !processing) {
3290
+ if (mode === "static" ? staticBarsRef.current.length > 0 : historyRef.current.length > 0) {
3291
+ let fadeProgress = 0;
3292
+ const fadeToIdle = () => {
3293
+ fadeProgress = fadeProgress + .03;
3294
+ if (fadeProgress < 1) {
3295
+ if (mode === "static") staticBarsRef.current = staticBarsRef.current.map((value) => value * (1 - fadeProgress));
3296
+ else historyRef.current = historyRef.current.map((value_0) => value_0 * (1 - fadeProgress));
3297
+ needsRedrawRef.current = true;
3298
+ requestAnimationFrame(fadeToIdle);
3299
+ } else if (mode === "static") staticBarsRef.current = [];
3300
+ else historyRef.current = [];
3301
+ };
3302
+ fadeToIdle();
3303
+ }
3304
+ }
3305
+ };
3306
+ t17 = [
3307
+ processing,
3308
+ active,
3309
+ barWidth,
3310
+ barGap,
3311
+ mode
3312
+ ];
3313
+ $[20] = active;
3314
+ $[21] = barGap;
3315
+ $[22] = barWidth;
3316
+ $[23] = mode;
3317
+ $[24] = processing;
3318
+ $[25] = t16;
3319
+ $[26] = t17;
3320
+ } else {
3321
+ t16 = $[25];
3322
+ t17 = $[26];
3323
+ }
3324
+ useEffect(t16, t17);
3325
+ let t18;
3326
+ let t19;
3327
+ if ($[27] !== active || $[28] !== barColor || $[29] !== barGap || $[30] !== barRadius || $[31] !== barWidth || $[32] !== fadeEdges || $[33] !== fadeWidth || $[34] !== manualAudioLevel || $[35] !== mode || $[36] !== processing || $[37] !== sensitivity) {
3328
+ t18 = () => {
3329
+ const canvas_0 = canvasRef.current;
3330
+ if (!canvas_0) return;
3331
+ const ctx_0 = canvas_0.getContext("2d");
3332
+ if (!ctx_0) return;
3333
+ let rafId;
3334
+ const animate = (currentTime) => {
3335
+ const rect_0 = canvas_0.getBoundingClientRect();
3336
+ if (active && currentTime - lastUpdateRef.current > 30) {
3337
+ lastUpdateRef.current = currentTime;
3338
+ if (manualAudioLevel !== void 0) {
3339
+ const level = Math.max(.05, Math.min(1, manualAudioLevel * sensitivity));
3340
+ if (mode === "static") {
3341
+ const barCount_0 = Math.floor(rect_0.width / (barWidth + barGap));
3342
+ const halfCount_0 = Math.floor(barCount_0 / 2);
3343
+ const newBars = [];
3344
+ for (let i_1 = halfCount_0 - 1; i_1 >= 0; i_1--) {
3345
+ const value_1 = level * (1 - Math.abs(i_1 - halfCount_0 / 2) / (halfCount_0 / 2) * .3);
3346
+ newBars.push(Math.max(.05, value_1));
3347
+ }
3348
+ for (let i_2 = 0; i_2 < halfCount_0; i_2++) {
3349
+ const value_2 = level * (1 - Math.abs(i_2 - halfCount_0 / 2) / (halfCount_0 / 2) * .3);
3350
+ newBars.push(Math.max(.05, value_2));
3351
+ }
3352
+ staticBarsRef.current = newBars;
3353
+ lastActiveDataRef.current = newBars;
3354
+ } else {
3355
+ historyRef.current.push(level);
3356
+ lastActiveDataRef.current = [...historyRef.current];
3357
+ if (historyRef.current.length > 60) historyRef.current.shift();
3358
+ }
3359
+ needsRedrawRef.current = true;
3360
+ }
3361
+ }
3362
+ if (!needsRedrawRef.current && !active) {
3363
+ rafId = requestAnimationFrame(animate);
3364
+ return;
3365
+ }
3366
+ needsRedrawRef.current = active;
3367
+ ctx_0.clearRect(0, 0, rect_0.width, rect_0.height);
3368
+ const computedBarColor = barColor || (() => {
3369
+ return getComputedStyle(canvas_0).color || "#000";
3370
+ })();
3371
+ const step = barWidth + barGap;
3372
+ const barCount_1 = Math.floor(rect_0.width / step);
3373
+ const centerY = rect_0.height / 2;
3374
+ if (mode === "static") {
3375
+ const dataToRender = processing ? staticBarsRef.current : active ? staticBarsRef.current : staticBarsRef.current.length > 0 ? staticBarsRef.current : [];
3376
+ for (let i_3 = 0; i_3 < barCount_1 && i_3 < dataToRender.length; i_3++) {
3377
+ const value_3 = dataToRender[i_3] || .1;
3378
+ const x = i_3 * step;
3379
+ const barHeight = Math.max(4, value_3 * rect_0.height * .8);
3380
+ const y = centerY - barHeight / 2;
3381
+ ctx_0.fillStyle = computedBarColor;
3382
+ ctx_0.globalAlpha = .4 + value_3 * .6;
3383
+ if (barRadius > 0) {
3384
+ ctx_0.beginPath();
3385
+ ctx_0.roundRect(x, y, barWidth, barHeight, barRadius);
3386
+ ctx_0.fill();
3387
+ } else ctx_0.fillRect(x, y, barWidth, barHeight);
3388
+ }
3389
+ } else for (let i_4 = 0; i_4 < barCount_1 && i_4 < historyRef.current.length; i_4++) {
3390
+ const dataIndex = historyRef.current.length - 1 - i_4;
3391
+ const value_4 = historyRef.current[dataIndex] || .1;
3392
+ const x_0 = rect_0.width - (i_4 + 1) * step;
3393
+ const barHeight_0 = Math.max(4, value_4 * rect_0.height * .8);
3394
+ const y_0 = centerY - barHeight_0 / 2;
3395
+ ctx_0.fillStyle = computedBarColor;
3396
+ ctx_0.globalAlpha = .4 + value_4 * .6;
3397
+ if (barRadius > 0) {
3398
+ ctx_0.beginPath();
3399
+ ctx_0.roundRect(x_0, y_0, barWidth, barHeight_0, barRadius);
3400
+ ctx_0.fill();
3401
+ } else ctx_0.fillRect(x_0, y_0, barWidth, barHeight_0);
3402
+ }
3403
+ if (fadeEdges && fadeWidth > 0 && rect_0.width > 0) {
3404
+ if (!gradientCacheRef.current || lastWidthRef.current !== rect_0.width) {
3405
+ const gradient = ctx_0.createLinearGradient(0, 0, rect_0.width, 0);
3406
+ const fadePercent = Math.min(.3, fadeWidth / rect_0.width);
3407
+ gradient.addColorStop(0, "rgba(255,255,255,1)");
3408
+ gradient.addColorStop(fadePercent, "rgba(255,255,255,0)");
3409
+ gradient.addColorStop(1 - fadePercent, "rgba(255,255,255,0)");
3410
+ gradient.addColorStop(1, "rgba(255,255,255,1)");
3411
+ gradientCacheRef.current = gradient;
3412
+ lastWidthRef.current = rect_0.width;
3413
+ }
3414
+ ctx_0.globalCompositeOperation = "destination-out";
3415
+ ctx_0.fillStyle = gradientCacheRef.current;
3416
+ ctx_0.fillRect(0, 0, rect_0.width, rect_0.height);
3417
+ ctx_0.globalCompositeOperation = "source-over";
3418
+ }
3419
+ ctx_0.globalAlpha = 1;
3420
+ rafId = requestAnimationFrame(animate);
3421
+ };
3422
+ rafId = requestAnimationFrame(animate);
3423
+ return () => {
3424
+ if (rafId) cancelAnimationFrame(rafId);
3425
+ };
3426
+ };
3427
+ t19 = [
3428
+ active,
3429
+ processing,
3430
+ sensitivity,
3431
+ barWidth,
3432
+ barGap,
3433
+ barRadius,
3434
+ barColor,
3435
+ fadeEdges,
3436
+ fadeWidth,
3437
+ mode,
3438
+ manualAudioLevel,
3439
+ 60,
3440
+ 30
3441
+ ];
3442
+ $[27] = active;
3443
+ $[28] = barColor;
3444
+ $[29] = barGap;
3445
+ $[30] = barRadius;
3446
+ $[31] = barWidth;
3447
+ $[32] = fadeEdges;
3448
+ $[33] = fadeWidth;
3449
+ $[34] = manualAudioLevel;
3450
+ $[35] = mode;
3451
+ $[36] = processing;
3452
+ $[37] = sensitivity;
3453
+ $[38] = t18;
3454
+ $[39] = t19;
3455
+ } else {
3456
+ t18 = $[38];
3457
+ t19 = $[39];
3458
+ }
3459
+ useEffect(t18, t19);
3460
+ let t20;
3461
+ if ($[40] !== className) {
3462
+ t20 = cn("relative h-full w-full", className);
3463
+ $[40] = className;
3464
+ $[41] = t20;
3465
+ } else t20 = $[41];
3466
+ let t21;
3467
+ if ($[42] !== heightStyle) {
3468
+ t21 = { height: heightStyle };
3469
+ $[42] = heightStyle;
3470
+ $[43] = t21;
3471
+ } else t21 = $[43];
3472
+ const t22 = active ? "Live audio waveform" : processing ? "Processing audio" : "Audio waveform idle";
3473
+ let t23;
3474
+ if ($[44] !== active || $[45] !== processing) {
3475
+ t23 = !active && !processing && /* @__PURE__ */ jsx("div", { className: "border-muted-foreground/20 absolute top-1/2 right-0 left-0 -translate-y-1/2 border-t-2 border-dotted" });
3476
+ $[44] = active;
3477
+ $[45] = processing;
3478
+ $[46] = t23;
3479
+ } else t23 = $[46];
3480
+ let t24;
3481
+ if ($[47] === Symbol.for("react.memo_cache_sentinel")) {
3482
+ t24 = /* @__PURE__ */ jsx("canvas", {
3483
+ className: "block h-full w-full",
3484
+ ref: canvasRef
3485
+ });
3486
+ $[47] = t24;
3487
+ } else t24 = $[47];
3488
+ let t25;
3489
+ if ($[48] !== props || $[49] !== t20 || $[50] !== t21 || $[51] !== t22 || $[52] !== t23) {
3490
+ t25 = /* @__PURE__ */ jsxs("div", {
3491
+ className: t20,
3492
+ ref: containerRef,
3493
+ style: t21,
3494
+ "aria-label": t22,
3495
+ role: "img",
3496
+ ...props,
3497
+ children: [t23, t24]
3498
+ });
3499
+ $[48] = props;
3500
+ $[49] = t20;
3501
+ $[50] = t21;
3502
+ $[51] = t22;
3503
+ $[52] = t23;
3504
+ $[53] = t25;
3505
+ } else t25 = $[53];
3506
+ return t25;
3507
+ };
3508
+
3509
+ //#endregion
3510
+ //#region src/components/voice-indicator.tsx
3511
+ function VoiceIndicator(t0) {
3512
+ const $ = c(65);
3513
+ const { isActive, isConnecting, isMuted, audioLevel, toolCall, onStart, onStop, onToggleMute, className } = t0;
3514
+ const micLevel = audioLevel?.micLevel ?? 0;
3515
+ const speakerLevel = audioLevel?.speakerLevel ?? 0;
3516
+ const toolCallStatus = toolCall?.status === "started" ? "calling" : toolCall?.status === "completed" ? toolCall.error ? "error" : "success" : "idle";
3517
+ let t1;
3518
+ if ($[0] !== toolCallStatus) {
3519
+ t1 = () => {
3520
+ switch (toolCallStatus) {
3521
+ case "calling": return "border-blue-500/60 shadow-[0_0_12px_rgba(59,130,246,0.3)]";
3522
+ case "success": return "border-green-500/60 shadow-[0_0_12px_rgba(34,197,94,0.3)]";
3523
+ case "error": return "border-red-500/60 shadow-[0_0_12px_rgba(239,68,68,0.3)]";
3524
+ default: return "border-border";
3525
+ }
3526
+ };
3527
+ $[0] = toolCallStatus;
3528
+ $[1] = t1;
3529
+ } else t1 = $[1];
3530
+ const getBorderClass = t1;
3531
+ if (!isActive && !isConnecting) {
3532
+ let t2$1;
3533
+ if ($[2] !== className) {
3534
+ t2$1 = cn("flex items-center", className);
3535
+ $[2] = className;
3536
+ $[3] = t2$1;
3537
+ } else t2$1 = $[3];
3538
+ let t3$1;
3539
+ let t4$1;
3540
+ if ($[4] === Symbol.for("react.memo_cache_sentinel")) {
3541
+ t3$1 = /* @__PURE__ */ jsx(Phone, { className: "h-4 w-4" });
3542
+ t4$1 = /* @__PURE__ */ jsx("span", {
3543
+ className: "text-xs",
3544
+ children: "Voice"
3545
+ });
3546
+ $[4] = t3$1;
3547
+ $[5] = t4$1;
3548
+ } else {
3549
+ t3$1 = $[4];
3550
+ t4$1 = $[5];
3551
+ }
3552
+ let t5$1;
3553
+ if ($[6] !== onStart) {
3554
+ t5$1 = /* @__PURE__ */ jsxs(Button, {
3555
+ variant: "outline",
3556
+ size: "sm",
3557
+ onClick: onStart,
3558
+ className: "gap-2 rounded-full",
3559
+ "aria-label": "Start voice session",
3560
+ children: [t3$1, t4$1]
3561
+ });
3562
+ $[6] = onStart;
3563
+ $[7] = t5$1;
3564
+ } else t5$1 = $[7];
3565
+ let t6$1;
3566
+ if ($[8] !== t2$1 || $[9] !== t5$1) {
3567
+ t6$1 = /* @__PURE__ */ jsx("div", {
3568
+ className: t2$1,
3569
+ children: t5$1
3570
+ });
3571
+ $[8] = t2$1;
3572
+ $[9] = t5$1;
3573
+ $[10] = t6$1;
3574
+ } else t6$1 = $[10];
3575
+ return t6$1;
3576
+ }
3577
+ let t2;
3578
+ if ($[11] !== className || $[12] !== getBorderClass) {
3579
+ t2 = cn("flex items-center gap-3 rounded-full border bg-background/95 px-3 py-2 backdrop-blur-sm transition-all duration-300", getBorderClass(), className);
3580
+ $[11] = className;
3581
+ $[12] = getBorderClass;
3582
+ $[13] = t2;
3583
+ } else t2 = $[13];
3584
+ const t3 = isMuted ? "bg-muted text-muted-foreground" : "bg-primary/10 text-primary";
3585
+ let t4;
3586
+ if ($[14] !== t3) {
3587
+ t4 = cn("flex h-8 w-8 items-center justify-center rounded-full transition-colors", t3);
3588
+ $[14] = t3;
3589
+ $[15] = t4;
3590
+ } else t4 = $[15];
3591
+ let t5;
3592
+ if ($[16] !== isMuted) {
3593
+ t5 = isMuted ? /* @__PURE__ */ jsx(MicOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Mic, { className: "h-4 w-4" });
3594
+ $[16] = isMuted;
3595
+ $[17] = t5;
3596
+ } else t5 = $[17];
3597
+ let t6;
3598
+ if ($[18] !== t4 || $[19] !== t5) {
3599
+ t6 = /* @__PURE__ */ jsx("div", {
3600
+ className: t4,
3601
+ children: t5
3602
+ });
3603
+ $[18] = t4;
3604
+ $[19] = t5;
3605
+ $[20] = t6;
3606
+ } else t6 = $[20];
3607
+ const t7 = isActive && !isMuted;
3608
+ let t8;
3609
+ if ($[21] !== isConnecting || $[22] !== micLevel || $[23] !== t7) {
3610
+ t8 = /* @__PURE__ */ jsx("div", {
3611
+ className: "h-6 w-16",
3612
+ children: /* @__PURE__ */ jsx(LiveWaveform, {
3613
+ active: t7,
3614
+ processing: isConnecting,
3615
+ manualAudioLevel: micLevel,
3616
+ barWidth: 2,
3617
+ barGap: 1,
3618
+ barRadius: 2,
3619
+ barColor: "hsl(var(--primary))",
3620
+ height: 24,
3621
+ mode: "static",
3622
+ sensitivity: 2,
3623
+ fadeEdges: false
3624
+ })
3625
+ });
3626
+ $[21] = isConnecting;
3627
+ $[22] = micLevel;
3628
+ $[23] = t7;
3629
+ $[24] = t8;
3630
+ } else t8 = $[24];
3631
+ let t9;
3632
+ if ($[25] !== t6 || $[26] !== t8) {
3633
+ t9 = /* @__PURE__ */ jsxs("div", {
3634
+ className: "flex items-center gap-2",
3635
+ children: [t6, t8]
3636
+ });
3637
+ $[25] = t6;
3638
+ $[26] = t8;
3639
+ $[27] = t9;
3640
+ } else t9 = $[27];
3641
+ let t10;
3642
+ if ($[28] === Symbol.for("react.memo_cache_sentinel")) {
3643
+ t10 = /* @__PURE__ */ jsx("div", { className: "h-6 w-px bg-border" });
3644
+ $[28] = t10;
3645
+ } else t10 = $[28];
3646
+ let t11;
3647
+ if ($[29] !== isActive || $[30] !== isConnecting || $[31] !== speakerLevel) {
3648
+ t11 = /* @__PURE__ */ jsx("div", {
3649
+ className: "h-6 w-16",
3650
+ children: /* @__PURE__ */ jsx(LiveWaveform, {
3651
+ active: isActive,
3652
+ processing: isConnecting,
3653
+ manualAudioLevel: speakerLevel,
3654
+ barWidth: 2,
3655
+ barGap: 1,
3656
+ barRadius: 2,
3657
+ barColor: "hsl(var(--muted-foreground))",
3658
+ height: 24,
3659
+ mode: "static",
3660
+ sensitivity: 2,
3661
+ fadeEdges: false
3662
+ })
3663
+ });
3664
+ $[29] = isActive;
3665
+ $[30] = isConnecting;
3666
+ $[31] = speakerLevel;
3667
+ $[32] = t11;
3668
+ } else t11 = $[32];
3669
+ let t12;
3670
+ if ($[33] === Symbol.for("react.memo_cache_sentinel")) {
3671
+ t12 = /* @__PURE__ */ jsx("div", {
3672
+ className: cn("flex h-8 w-8 items-center justify-center rounded-full bg-muted text-muted-foreground"),
3673
+ children: /* @__PURE__ */ jsx(Volume2, { className: "h-4 w-4" })
3674
+ });
3675
+ $[33] = t12;
3676
+ } else t12 = $[33];
3677
+ let t13;
3678
+ if ($[34] !== t11) {
3679
+ t13 = /* @__PURE__ */ jsxs("div", {
3680
+ className: "flex items-center gap-2",
3681
+ children: [t11, t12]
3682
+ });
3683
+ $[34] = t11;
3684
+ $[35] = t13;
3685
+ } else t13 = $[35];
3686
+ let t14;
3687
+ if ($[36] === Symbol.for("react.memo_cache_sentinel")) {
3688
+ t14 = /* @__PURE__ */ jsx("div", { className: "h-6 w-px bg-border" });
3689
+ $[36] = t14;
3690
+ } else t14 = $[36];
3691
+ const t15 = !isActive;
3692
+ const t16 = isMuted && "text-destructive hover:text-destructive";
3693
+ let t17;
3694
+ if ($[37] !== t16) {
3695
+ t17 = cn("h-8 w-8 rounded-full", t16);
3696
+ $[37] = t16;
3697
+ $[38] = t17;
3698
+ } else t17 = $[38];
3699
+ const t18 = isMuted ? "Unmute microphone" : "Mute microphone";
3700
+ let t19;
3701
+ if ($[39] !== isMuted) {
3702
+ t19 = isMuted ? /* @__PURE__ */ jsx(MicOff, { className: "h-4 w-4" }) : /* @__PURE__ */ jsx(Mic, { className: "h-4 w-4" });
3703
+ $[39] = isMuted;
3704
+ $[40] = t19;
3705
+ } else t19 = $[40];
3706
+ let t20;
3707
+ if ($[41] !== onToggleMute || $[42] !== t15 || $[43] !== t17 || $[44] !== t18 || $[45] !== t19) {
3708
+ t20 = /* @__PURE__ */ jsx(Button, {
3709
+ variant: "ghost",
3710
+ size: "icon",
3711
+ onClick: onToggleMute,
3712
+ disabled: t15,
3713
+ className: t17,
3714
+ "aria-label": t18,
3715
+ children: t19
3716
+ });
3717
+ $[41] = onToggleMute;
3718
+ $[42] = t15;
3719
+ $[43] = t17;
3720
+ $[44] = t18;
3721
+ $[45] = t19;
3722
+ $[46] = t20;
3723
+ } else t20 = $[46];
3724
+ let t21;
3725
+ if ($[47] === Symbol.for("react.memo_cache_sentinel")) {
3726
+ t21 = /* @__PURE__ */ jsx(PhoneOff, { className: "h-4 w-4" });
3727
+ $[47] = t21;
3728
+ } else t21 = $[47];
3729
+ let t22;
3730
+ if ($[48] !== onStop) {
3731
+ t22 = /* @__PURE__ */ jsx(Button, {
3732
+ variant: "ghost",
3733
+ size: "icon",
3734
+ onClick: onStop,
3735
+ className: "h-8 w-8 rounded-full text-destructive hover:bg-destructive/10 hover:text-destructive",
3736
+ "aria-label": "End voice session",
3737
+ children: t21
3738
+ });
3739
+ $[48] = onStop;
3740
+ $[49] = t22;
3741
+ } else t22 = $[49];
3742
+ let t23;
3743
+ if ($[50] !== t20 || $[51] !== t22) {
3744
+ t23 = /* @__PURE__ */ jsxs("div", {
3745
+ className: "flex items-center gap-1",
3746
+ children: [t20, t22]
3747
+ });
3748
+ $[50] = t20;
3749
+ $[51] = t22;
3750
+ $[52] = t23;
3751
+ } else t23 = $[52];
3752
+ let t24;
3753
+ if ($[53] !== toolCall || $[54] !== toolCallStatus) {
3754
+ t24 = toolCall && toolCallStatus !== "idle" && /* @__PURE__ */ jsxs("div", {
3755
+ className: cn("ml-1 flex items-center gap-1 rounded-full px-2 py-0.5 text-xs", toolCallStatus === "calling" && "bg-blue-500/10 text-blue-600", toolCallStatus === "success" && "bg-green-500/10 text-green-600", toolCallStatus === "error" && "bg-red-500/10 text-red-600"),
3756
+ children: [/* @__PURE__ */ jsx("span", { className: cn("h-1.5 w-1.5 rounded-full", toolCallStatus === "calling" && "animate-pulse bg-blue-500", toolCallStatus === "success" && "bg-green-500", toolCallStatus === "error" && "bg-red-500") }), /* @__PURE__ */ jsx("span", {
3757
+ className: "max-w-[80px] truncate",
3758
+ children: toolCall.toolName
3759
+ })]
3760
+ });
3761
+ $[53] = toolCall;
3762
+ $[54] = toolCallStatus;
3763
+ $[55] = t24;
3764
+ } else t24 = $[55];
3765
+ let t25;
3766
+ if ($[56] !== isConnecting) {
3767
+ t25 = isConnecting && /* @__PURE__ */ jsxs("div", {
3768
+ className: "ml-1 flex items-center gap-1 text-xs text-muted-foreground",
3769
+ children: [/* @__PURE__ */ jsx("span", { className: "h-1.5 w-1.5 animate-pulse rounded-full bg-amber-500" }), /* @__PURE__ */ jsx("span", { children: "Connecting..." })]
3770
+ });
3771
+ $[56] = isConnecting;
3772
+ $[57] = t25;
3773
+ } else t25 = $[57];
3774
+ let t26;
3775
+ if ($[58] !== t13 || $[59] !== t2 || $[60] !== t23 || $[61] !== t24 || $[62] !== t25 || $[63] !== t9) {
3776
+ t26 = /* @__PURE__ */ jsxs("div", {
3777
+ className: t2,
3778
+ children: [
3779
+ t9,
3780
+ t10,
3781
+ t13,
3782
+ t14,
3783
+ t23,
3784
+ t24,
3785
+ t25
3786
+ ]
3787
+ });
3788
+ $[58] = t13;
3789
+ $[59] = t2;
3790
+ $[60] = t23;
3791
+ $[61] = t24;
3792
+ $[62] = t25;
3793
+ $[63] = t9;
3794
+ $[64] = t26;
3795
+ } else t26 = $[64];
3796
+ return t26;
3797
+ }
3798
+
3799
+ //#endregion
3800
+ //#region src/components/thread-with-voice.tsx
3801
+ /**
3802
+ * Thread with Voice Mode
3803
+ *
3804
+ * Enhanced thread component that includes voice mode.
3805
+ * Replaces the composer with a voice panel when voice is active.
3806
+ */
3807
+ const ThreadWithVoice = () => {
3808
+ return /* @__PURE__ */ jsx(LazyMotion, {
3809
+ features: domAnimation,
3810
+ children: /* @__PURE__ */ jsx(MotionConfig, {
3811
+ reducedMotion: "user",
3812
+ children: /* @__PURE__ */ jsx(ThreadPrimitive.Root, {
3813
+ className: "aui-root aui-thread-root app-shell @container relative flex h-full flex-col bg-background/50",
3814
+ style: { ["--thread-max-width"]: "100%" },
3815
+ children: /* @__PURE__ */ jsxs(ThreadPrimitive.Viewport, {
3816
+ className: "aui-thread-viewport relative flex flex-1 flex-col overflow-x-auto overflow-y-scroll px-4",
3817
+ children: [
3818
+ /* @__PURE__ */ jsx(ThreadPrimitive.If, {
3819
+ empty: true,
3820
+ children: /* @__PURE__ */ jsx(ThreadWelcome, {})
3821
+ }),
3822
+ /* @__PURE__ */ jsx(ThreadPrimitive.Messages, { components: {
3823
+ UserMessage,
3824
+ EditComposer,
3825
+ AssistantMessage
3826
+ } }),
3827
+ /* @__PURE__ */ jsx(ThreadPrimitive.If, {
3828
+ empty: false,
3829
+ children: /* @__PURE__ */ jsx("div", { className: "aui-thread-viewport-spacer min-h-8 grow" })
3830
+ }),
3831
+ /* @__PURE__ */ jsx(ComposerArea, {})
3832
+ ]
3833
+ })
3834
+ })
3835
+ })
3836
+ });
3837
+ };
3838
+ /**
3839
+ * Composer area with voice indicator
3840
+ */
3841
+ const ComposerArea = () => {
3842
+ const $ = c(8);
3843
+ const voiceMode = useOptionalVoiceModeContext();
3844
+ let t0;
3845
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
3846
+ t0 = /* @__PURE__ */ jsx(ThreadScrollToBottom, {});
3847
+ $[0] = t0;
3848
+ } else t0 = $[0];
3849
+ let t1;
3850
+ if ($[1] !== voiceMode) {
3851
+ t1 = voiceMode?.isSupported && (voiceMode.isActive || voiceMode.isConnecting) && /* @__PURE__ */ jsx(m.div, {
3852
+ initial: {
3853
+ opacity: 0,
3854
+ y: 20
3855
+ },
3856
+ animate: {
3857
+ opacity: 1,
3858
+ y: 0
3859
+ },
3860
+ exit: {
3861
+ opacity: 0,
3862
+ y: -10
3863
+ },
3864
+ transition: { duration: .2 },
3865
+ className: "flex justify-center",
3866
+ children: /* @__PURE__ */ jsx(VoiceIndicator, {
3867
+ isActive: voiceMode.isActive,
3868
+ isConnecting: voiceMode.isConnecting,
3869
+ isMuted: voiceMode.isMuted,
3870
+ audioLevel: voiceMode.audioLevel,
3871
+ toolCall: voiceMode.toolCall,
3872
+ onStart: voiceMode.startSession,
3873
+ onStop: voiceMode.stopSession,
3874
+ onToggleMute: () => voiceMode.toggleMute()
3875
+ })
3876
+ });
3877
+ $[1] = voiceMode;
3878
+ $[2] = t1;
3879
+ } else t1 = $[2];
3880
+ let t2;
3881
+ if ($[3] !== t1) {
3882
+ t2 = /* @__PURE__ */ jsx(AnimatePresence, { children: t1 });
3883
+ $[3] = t1;
3884
+ $[4] = t2;
3885
+ } else t2 = $[4];
3886
+ let t3;
3887
+ if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
3888
+ t3 = /* @__PURE__ */ jsx(TextComposer, {});
3889
+ $[5] = t3;
3890
+ } else t3 = $[5];
3891
+ let t4;
3892
+ if ($[6] !== t2) {
3893
+ t4 = /* @__PURE__ */ jsxs("div", {
3894
+ className: "aui-composer-wrapper sticky bottom-0 mx-auto flex w-full max-w-[var(--thread-max-width)] flex-col gap-4 overflow-visible rounded-t-3xl pb-4 md:pb-6",
3895
+ children: [
3896
+ t0,
3897
+ t2,
3898
+ t3
3899
+ ]
3900
+ });
3901
+ $[6] = t2;
3902
+ $[7] = t4;
3903
+ } else t4 = $[7];
3904
+ return t4;
3905
+ };
3906
+ const TextComposer = () => {
3907
+ const $ = c(13);
3908
+ const voiceMode = useOptionalVoiceModeContext();
3909
+ let t0;
3910
+ let t1;
3911
+ let t2;
3912
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
3913
+ t0 = cn("aui-composer-root group/composer flex w-full flex-col overflow-hidden rounded-2xl px-3 py-2", "border border-border/40 shadow-sm backdrop-blur-md", "bg-background/80", "transition-all duration-200", "focus-within:border-ring/50 focus-within:shadow-md", "hover:border-border/60");
3914
+ t1 = /* @__PURE__ */ jsx(ComposerAttachments, {});
3915
+ t2 = /* @__PURE__ */ jsx(ComposerPrimitive.Input, {
3916
+ placeholder: "Send a message...",
3917
+ className: "aui-composer-input mt-2 max-h-24 w-full resize-none bg-transparent px-0 py-2 text-sm leading-relaxed text-foreground placeholder:text-muted-foreground/70 focus-visible:outline-none focus-visible:ring-0",
3918
+ rows: 1,
3919
+ autoFocus: true,
3920
+ "aria-label": "Message input"
3921
+ });
3922
+ $[0] = t0;
3923
+ $[1] = t1;
3924
+ $[2] = t2;
3925
+ } else {
3926
+ t0 = $[0];
3927
+ t1 = $[1];
3928
+ t2 = $[2];
3929
+ }
3930
+ let t3;
3931
+ let t4;
3932
+ if ($[3] === Symbol.for("react.memo_cache_sentinel")) {
3933
+ t3 = /* @__PURE__ */ jsx(ComposerAddAttachment, {});
3934
+ t4 = /* @__PURE__ */ jsx(RemoteMCPSettings, {});
3935
+ $[3] = t3;
3936
+ $[4] = t4;
3937
+ } else {
3938
+ t3 = $[3];
3939
+ t4 = $[4];
3940
+ }
3941
+ let t5;
3942
+ if ($[5] !== voiceMode) {
3943
+ t5 = voiceMode?.isSupported && /* @__PURE__ */ jsxs(Button, {
3944
+ variant: "ghost",
3945
+ size: "sm",
3946
+ onClick: () => voiceMode.startSession(),
3947
+ className: "gap-2 rounded-full text-muted-foreground hover:text-foreground",
3948
+ "aria-label": "Start voice session",
3949
+ children: [/* @__PURE__ */ jsx(Phone, { className: "h-4 w-4" }), /* @__PURE__ */ jsx("span", {
3950
+ className: "text-xs",
3951
+ children: "Voice"
3952
+ })]
3953
+ });
3954
+ $[5] = voiceMode;
3955
+ $[6] = t5;
3956
+ } else t5 = $[6];
3957
+ let t6;
3958
+ if ($[7] !== t5) {
3959
+ t6 = /* @__PURE__ */ jsxs("div", {
3960
+ className: "flex items-center gap-2",
3961
+ children: [
3962
+ t3,
3963
+ t4,
3964
+ t5
3965
+ ]
3966
+ });
3967
+ $[7] = t5;
3968
+ $[8] = t6;
3969
+ } else t6 = $[8];
3970
+ let t7;
3971
+ if ($[9] === Symbol.for("react.memo_cache_sentinel")) {
3972
+ t7 = /* @__PURE__ */ jsx(ThreadPrimitive.If, {
3973
+ running: false,
3974
+ children: /* @__PURE__ */ jsx(ComposerPrimitive.Send, {
3975
+ asChild: true,
3976
+ children: /* @__PURE__ */ jsx(TooltipIconButton, {
3977
+ tooltip: "Send message",
3978
+ side: "top",
3979
+ type: "submit",
3980
+ variant: "ghost",
3981
+ size: "icon",
3982
+ className: "aui-composer-send size-8 shrink-0 rounded-full border border-primary/60 bg-primary px-0 text-primary-foreground shadow-[0_12px_24px_-16px_rgba(37,99,235,0.55)] transition-shadow hover:shadow-[0_14px_24px_-14px_rgba(37,99,235,0.6)] focus-visible:ring-2 focus-visible:ring-primary/40",
3983
+ "aria-label": "Send message",
3984
+ children: /* @__PURE__ */ jsx(ArrowUpIcon, { className: "aui-composer-send-icon size-4" })
3985
+ })
3986
+ })
3987
+ });
3988
+ $[9] = t7;
3989
+ } else t7 = $[9];
3990
+ let t8;
3991
+ if ($[10] === Symbol.for("react.memo_cache_sentinel")) {
3992
+ t8 = /* @__PURE__ */ jsxs("div", {
3993
+ className: "flex items-center gap-1.5",
3994
+ children: [t7, /* @__PURE__ */ jsx(ThreadPrimitive.If, {
3995
+ running: true,
3996
+ children: /* @__PURE__ */ jsx(ComposerPrimitive.Cancel, {
3997
+ asChild: true,
3998
+ children: /* @__PURE__ */ jsx(TooltipIconButton, {
3999
+ tooltip: "Stop generating",
4000
+ side: "top",
4001
+ type: "button",
4002
+ variant: "ghost",
4003
+ size: "icon",
4004
+ className: "aui-composer-cancel size-8 shrink-0 rounded-full border border-destructive/60 bg-destructive px-0 text-destructive-foreground shadow-[0_12px_24px_-18px_rgba(220,38,38,0.55)] transition-shadow hover:shadow-[0_14px_24px_-16px_rgba(220,38,38,0.6)] focus-visible:ring-2 focus-visible:ring-destructive/40",
4005
+ "aria-label": "Stop generating",
4006
+ children: /* @__PURE__ */ jsx(Square, { className: "aui-composer-cancel-icon size-3.5" })
4007
+ })
4008
+ })
4009
+ })]
4010
+ });
4011
+ $[10] = t8;
4012
+ } else t8 = $[10];
4013
+ let t9;
4014
+ if ($[11] !== t6) {
4015
+ t9 = /* @__PURE__ */ jsxs(ComposerPrimitive.Root, {
4016
+ className: t0,
4017
+ children: [
4018
+ t1,
4019
+ t2,
4020
+ /* @__PURE__ */ jsxs("div", {
4021
+ className: "aui-composer-action-wrapper mt-2 flex items-center justify-between text-muted-foreground",
4022
+ children: [t6, t8]
4023
+ })
4024
+ ]
4025
+ });
4026
+ $[11] = t6;
4027
+ $[12] = t9;
4028
+ } else t9 = $[12];
4029
+ return t9;
4030
+ };
4031
+ const ThreadScrollToBottom = () => {
4032
+ const $ = c(1);
4033
+ let t0;
4034
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
4035
+ t0 = /* @__PURE__ */ jsx(ThreadPrimitive.ScrollToBottom, {
4036
+ asChild: true,
4037
+ children: /* @__PURE__ */ jsx(TooltipIconButton, {
4038
+ tooltip: "Scroll to bottom",
4039
+ variant: "outline",
4040
+ className: "aui-thread-scroll-to-bottom absolute -top-12 z-10 self-center rounded-full p-4 disabled:invisible dark:bg-background dark:hover:bg-accent",
4041
+ children: /* @__PURE__ */ jsx(ArrowDownIcon, {})
4042
+ })
4043
+ });
4044
+ $[0] = t0;
4045
+ } else t0 = $[0];
4046
+ return t0;
4047
+ };
4048
+ const ThreadWelcome = () => {
4049
+ const $ = c(2);
4050
+ let t0;
4051
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
4052
+ t0 = /* @__PURE__ */ jsx(m.div, {
4053
+ initial: {
4054
+ opacity: 0,
4055
+ y: 10
4056
+ },
4057
+ animate: {
4058
+ opacity: 1,
4059
+ y: 0
4060
+ },
4061
+ exit: {
4062
+ opacity: 0,
4063
+ y: 10
4064
+ },
4065
+ className: "aui-thread-welcome-message-motion-1 text-3xl font-bold tracking-tight",
4066
+ children: "Hello there!"
4067
+ });
4068
+ $[0] = t0;
4069
+ } else t0 = $[0];
4070
+ let t1;
4071
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
4072
+ t1 = /* @__PURE__ */ jsxs("div", {
4073
+ className: "aui-thread-welcome-root mx-auto my-auto flex w-full max-w-[var(--thread-max-width)] flex-grow flex-col",
4074
+ children: [/* @__PURE__ */ jsx("div", {
4075
+ className: "aui-thread-welcome-center flex w-full flex-grow flex-col items-center justify-center",
4076
+ children: /* @__PURE__ */ jsxs("div", {
4077
+ className: "aui-thread-welcome-message flex size-full flex-col justify-center px-8",
4078
+ children: [t0, /* @__PURE__ */ jsx(m.div, {
4079
+ initial: {
4080
+ opacity: 0,
4081
+ y: 10
4082
+ },
4083
+ animate: {
4084
+ opacity: 1,
4085
+ y: 0
4086
+ },
4087
+ exit: {
4088
+ opacity: 0,
4089
+ y: 10
4090
+ },
4091
+ transition: { delay: .1 },
4092
+ className: "aui-thread-welcome-message-motion-2 mt-2 text-lg text-muted-foreground",
4093
+ children: "How can I help you today?"
4094
+ })]
4095
+ })
4096
+ }), /* @__PURE__ */ jsx(ThreadSuggestions, {})]
4097
+ });
4098
+ $[1] = t1;
4099
+ } else t1 = $[1];
4100
+ return t1;
4101
+ };
4102
+ const ThreadSuggestions = () => {
4103
+ const $ = c(1);
4104
+ let t0;
4105
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
4106
+ t0 = /* @__PURE__ */ jsx("div", {
4107
+ className: "aui-thread-welcome-suggestions grid w-full gap-2 pb-4 @md:grid-cols-2",
4108
+ children: [
4109
+ {
4110
+ title: "What's the weather",
4111
+ label: "in San Francisco?",
4112
+ action: "What's the weather in San Francisco?"
4113
+ },
4114
+ {
4115
+ title: "Explain React hooks",
4116
+ label: "like useState and useEffect",
4117
+ action: "Explain React hooks like useState and useEffect"
4118
+ },
4119
+ {
4120
+ title: "Write a SQL query",
4121
+ label: "to find top customers",
4122
+ action: "Write a SQL query to find top customers"
4123
+ },
4124
+ {
4125
+ title: "Create a meal plan",
4126
+ label: "for healthy weight loss",
4127
+ action: "Create a meal plan for healthy weight loss"
4128
+ }
4129
+ ].map(_temp$1)
4130
+ });
4131
+ $[0] = t0;
4132
+ } else t0 = $[0];
4133
+ return t0;
4134
+ };
4135
+ const MessageError = () => {
4136
+ const $ = c(1);
4137
+ let t0;
4138
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
4139
+ t0 = /* @__PURE__ */ jsx(MessagePrimitive.Error, { children: /* @__PURE__ */ jsx(ErrorPrimitive.Root, {
4140
+ className: "aui-message-error-root mt-2 rounded-md border border-destructive bg-destructive/10 p-3 text-sm text-destructive dark:bg-destructive/5 dark:text-red-200",
4141
+ children: /* @__PURE__ */ jsx(ErrorPrimitive.Message, { className: "aui-message-error-message line-clamp-2" })
4142
+ }) });
4143
+ $[0] = t0;
4144
+ } else t0 = $[0];
4145
+ return t0;
4146
+ };
4147
+ const AssistantMessage = () => {
4148
+ const $ = c(2);
4149
+ let t0;
4150
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
4151
+ t0 = /* @__PURE__ */ jsxs("div", {
4152
+ className: "aui-assistant-message-content mx-2 leading-7 break-words text-foreground",
4153
+ children: [/* @__PURE__ */ jsx(MessagePrimitive.Parts, { components: {
4154
+ Text: MarkdownText,
4155
+ tools: { Fallback: ToolFallback }
4156
+ } }), /* @__PURE__ */ jsx(MessageError, {})]
4157
+ });
4158
+ $[0] = t0;
4159
+ } else t0 = $[0];
4160
+ let t1;
4161
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
4162
+ t1 = /* @__PURE__ */ jsx(MessagePrimitive.Root, {
4163
+ asChild: true,
4164
+ children: /* @__PURE__ */ jsxs("div", {
4165
+ className: "aui-assistant-message-root relative mx-auto w-full max-w-[var(--thread-max-width)] animate-in py-4 duration-200 fade-in slide-in-from-bottom-1 last:mb-24",
4166
+ "data-role": "assistant",
4167
+ children: [t0, /* @__PURE__ */ jsxs("div", {
4168
+ className: "aui-assistant-message-footer mt-2 ml-2 flex",
4169
+ children: [/* @__PURE__ */ jsx(BranchPicker, {}), /* @__PURE__ */ jsx(AssistantActionBar, {})]
4170
+ })]
4171
+ })
4172
+ });
4173
+ $[1] = t1;
4174
+ } else t1 = $[1];
4175
+ return t1;
4176
+ };
4177
+ const AssistantActionBar = () => {
4178
+ const $ = c(3);
4179
+ let t0;
4180
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
4181
+ t0 = /* @__PURE__ */ jsx(MessagePrimitive.If, {
4182
+ copied: true,
4183
+ children: /* @__PURE__ */ jsx(CheckIcon, {})
4184
+ });
4185
+ $[0] = t0;
4186
+ } else t0 = $[0];
4187
+ let t1;
4188
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
4189
+ t1 = /* @__PURE__ */ jsx(ActionBarPrimitive.Copy, {
4190
+ asChild: true,
4191
+ children: /* @__PURE__ */ jsxs(TooltipIconButton, {
4192
+ tooltip: "Copy",
4193
+ children: [t0, /* @__PURE__ */ jsx(MessagePrimitive.If, {
4194
+ copied: false,
4195
+ children: /* @__PURE__ */ jsx(CopyIcon, {})
4196
+ })]
4197
+ })
4198
+ });
4199
+ $[1] = t1;
4200
+ } else t1 = $[1];
4201
+ let t2;
4202
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
4203
+ t2 = /* @__PURE__ */ jsxs(ActionBarPrimitive.Root, {
4204
+ hideWhenRunning: true,
4205
+ autohide: "not-last",
4206
+ autohideFloat: "single-branch",
4207
+ className: "aui-assistant-action-bar-root col-start-3 row-start-2 -ml-1 flex gap-1 text-muted-foreground data-floating:absolute data-floating:rounded-md data-floating:border data-floating:bg-background data-floating:p-1 data-floating:shadow-sm",
4208
+ children: [t1, /* @__PURE__ */ jsx(ActionBarPrimitive.Reload, {
4209
+ asChild: true,
4210
+ children: /* @__PURE__ */ jsx(TooltipIconButton, {
4211
+ tooltip: "Refresh",
4212
+ children: /* @__PURE__ */ jsx(RefreshCwIcon, {})
4213
+ })
4214
+ })]
4215
+ });
4216
+ $[2] = t2;
4217
+ } else t2 = $[2];
4218
+ return t2;
4219
+ };
4220
+ const UserMessage = () => {
4221
+ const $ = c(3);
4222
+ let t0;
4223
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
4224
+ t0 = /* @__PURE__ */ jsx(UserMessageAttachments, {});
4225
+ $[0] = t0;
4226
+ } else t0 = $[0];
4227
+ let t1;
4228
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
4229
+ t1 = /* @__PURE__ */ jsx("div", {
4230
+ className: "aui-user-message-content rounded-2xl rounded-tr-sm bg-primary text-primary-foreground px-4 py-3 text-sm leading-relaxed shadow-sm",
4231
+ children: /* @__PURE__ */ jsx(MessagePrimitive.Parts, {})
4232
+ });
4233
+ $[1] = t1;
4234
+ } else t1 = $[1];
4235
+ let t2;
4236
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
4237
+ t2 = /* @__PURE__ */ jsx(MessagePrimitive.Root, {
4238
+ asChild: true,
4239
+ children: /* @__PURE__ */ jsxs("div", {
4240
+ className: "aui-user-message-root mx-auto grid w-full max-w-[var(--thread-max-width)] animate-in auto-rows-auto grid-cols-[minmax(72px,1fr)_auto] gap-y-2 px-2 py-4 duration-200 fade-in slide-in-from-bottom-1 first:mt-3 last:mb-5 [&:where(>*)]:col-start-2",
4241
+ "data-role": "user",
4242
+ children: [
4243
+ t0,
4244
+ /* @__PURE__ */ jsxs("div", {
4245
+ className: "aui-user-message-content-wrapper relative col-start-2 min-w-0 max-w-[85%]",
4246
+ children: [t1, /* @__PURE__ */ jsx("div", {
4247
+ className: "aui-user-action-bar-wrapper absolute top-1/2 left-0 -translate-x-full -translate-y-1/2 pr-2",
4248
+ children: /* @__PURE__ */ jsx(UserActionBar, {})
4249
+ })]
4250
+ }),
4251
+ /* @__PURE__ */ jsx(BranchPicker, { className: "aui-user-branch-picker col-span-full col-start-1 row-start-3 -mr-1 justify-end" })
4252
+ ]
4253
+ })
4254
+ });
4255
+ $[2] = t2;
4256
+ } else t2 = $[2];
4257
+ return t2;
4258
+ };
4259
+ const UserActionBar = () => {
4260
+ const $ = c(1);
4261
+ let t0;
4262
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
4263
+ t0 = /* @__PURE__ */ jsx(ActionBarPrimitive.Root, {
4264
+ hideWhenRunning: true,
4265
+ autohide: "not-last",
4266
+ className: "aui-user-action-bar-root flex flex-col items-end",
4267
+ children: /* @__PURE__ */ jsx(ActionBarPrimitive.Edit, {
4268
+ asChild: true,
4269
+ children: /* @__PURE__ */ jsx(TooltipIconButton, {
4270
+ tooltip: "Edit",
4271
+ className: "aui-user-action-edit p-4",
4272
+ children: /* @__PURE__ */ jsx(PencilIcon, {})
4273
+ })
4274
+ })
4275
+ });
4276
+ $[0] = t0;
4277
+ } else t0 = $[0];
4278
+ return t0;
4279
+ };
4280
+ const EditComposer = () => {
4281
+ const $ = c(3);
4282
+ let t0;
4283
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
4284
+ t0 = /* @__PURE__ */ jsx(ComposerPrimitive.Input, {
4285
+ className: "aui-edit-composer-input flex min-h-[60px] w-full resize-none bg-transparent p-4 text-foreground outline-none",
4286
+ autoFocus: true
4287
+ });
4288
+ $[0] = t0;
4289
+ } else t0 = $[0];
4290
+ let t1;
4291
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
4292
+ t1 = /* @__PURE__ */ jsx(ComposerPrimitive.Cancel, {
4293
+ asChild: true,
4294
+ children: /* @__PURE__ */ jsx(Button, {
4295
+ variant: "ghost",
4296
+ size: "sm",
4297
+ "aria-label": "Cancel edit",
4298
+ children: "Cancel"
4299
+ })
4300
+ });
4301
+ $[1] = t1;
4302
+ } else t1 = $[1];
4303
+ let t2;
4304
+ if ($[2] === Symbol.for("react.memo_cache_sentinel")) {
4305
+ t2 = /* @__PURE__ */ jsx("div", {
4306
+ className: "aui-edit-composer-wrapper mx-auto flex w-full max-w-[var(--thread-max-width)] flex-col gap-4 px-2 first:mt-4",
4307
+ children: /* @__PURE__ */ jsxs(ComposerPrimitive.Root, {
4308
+ className: "aui-edit-composer-root ml-auto flex w-full max-w-7/8 flex-col rounded-xl bg-muted",
4309
+ children: [t0, /* @__PURE__ */ jsxs("div", {
4310
+ className: "aui-edit-composer-footer mx-3 mb-3 flex items-center justify-center gap-2 self-end",
4311
+ children: [t1, /* @__PURE__ */ jsx(ComposerPrimitive.Send, {
4312
+ asChild: true,
4313
+ children: /* @__PURE__ */ jsx(Button, {
4314
+ size: "sm",
4315
+ "aria-label": "Update message",
4316
+ children: "Update"
4317
+ })
4318
+ })]
4319
+ })]
4320
+ })
4321
+ });
4322
+ $[2] = t2;
4323
+ } else t2 = $[2];
4324
+ return t2;
4325
+ };
4326
+ const BranchPicker = (t0) => {
4327
+ const $ = c(12);
4328
+ let className;
4329
+ let rest;
4330
+ if ($[0] !== t0) {
4331
+ ({className, ...rest} = t0);
4332
+ $[0] = t0;
4333
+ $[1] = className;
4334
+ $[2] = rest;
4335
+ } else {
4336
+ className = $[1];
4337
+ rest = $[2];
4338
+ }
4339
+ let t1;
4340
+ if ($[3] !== className) {
4341
+ t1 = cn("aui-branch-picker-root mr-2 -ml-2 inline-flex items-center text-xs text-muted-foreground", className);
4342
+ $[3] = className;
4343
+ $[4] = t1;
4344
+ } else t1 = $[4];
4345
+ let t2;
4346
+ if ($[5] === Symbol.for("react.memo_cache_sentinel")) {
4347
+ t2 = /* @__PURE__ */ jsx(BranchPickerPrimitive.Previous, {
4348
+ asChild: true,
4349
+ children: /* @__PURE__ */ jsx(TooltipIconButton, {
4350
+ tooltip: "Previous",
4351
+ children: /* @__PURE__ */ jsx(ChevronLeftIcon, {})
4352
+ })
4353
+ });
4354
+ $[5] = t2;
4355
+ } else t2 = $[5];
4356
+ let t3;
4357
+ if ($[6] === Symbol.for("react.memo_cache_sentinel")) {
4358
+ t3 = /* @__PURE__ */ jsx(BranchPickerPrimitive.Number, {});
4359
+ $[6] = t3;
4360
+ } else t3 = $[6];
4361
+ let t4;
4362
+ if ($[7] === Symbol.for("react.memo_cache_sentinel")) {
4363
+ t4 = /* @__PURE__ */ jsxs("span", {
4364
+ className: "aui-branch-picker-state font-medium",
4365
+ children: [
4366
+ t3,
4367
+ " / ",
4368
+ /* @__PURE__ */ jsx(BranchPickerPrimitive.Count, {})
4369
+ ]
4370
+ });
4371
+ $[7] = t4;
4372
+ } else t4 = $[7];
4373
+ let t5;
4374
+ if ($[8] === Symbol.for("react.memo_cache_sentinel")) {
4375
+ t5 = /* @__PURE__ */ jsx(BranchPickerPrimitive.Next, {
4376
+ asChild: true,
4377
+ children: /* @__PURE__ */ jsx(TooltipIconButton, {
4378
+ tooltip: "Next",
4379
+ children: /* @__PURE__ */ jsx(ChevronRightIcon, {})
4380
+ })
4381
+ });
4382
+ $[8] = t5;
4383
+ } else t5 = $[8];
4384
+ let t6;
4385
+ if ($[9] !== rest || $[10] !== t1) {
4386
+ t6 = /* @__PURE__ */ jsxs(BranchPickerPrimitive.Root, {
4387
+ hideWhenSingleBranch: true,
4388
+ className: t1,
4389
+ ...rest,
4390
+ children: [
4391
+ t2,
4392
+ t4,
4393
+ t5
4394
+ ]
4395
+ });
4396
+ $[9] = rest;
4397
+ $[10] = t1;
4398
+ $[11] = t6;
4399
+ } else t6 = $[11];
4400
+ return t6;
4401
+ };
4402
+ function _temp$1(suggestedAction, index) {
4403
+ return /* @__PURE__ */ jsx(m.div, {
4404
+ initial: {
4405
+ opacity: 0,
4406
+ y: 20
4407
+ },
4408
+ animate: {
4409
+ opacity: 1,
4410
+ y: 0
4411
+ },
4412
+ exit: {
4413
+ opacity: 0,
4414
+ y: 20
4415
+ },
4416
+ transition: { delay: .05 * index },
4417
+ className: "aui-thread-welcome-suggestion-display [&:nth-child(n+3)]:hidden @md:[&:nth-child(n+3)]:block",
4418
+ children: /* @__PURE__ */ jsx(ThreadPrimitive.Suggestion, {
4419
+ prompt: suggestedAction.action,
4420
+ send: true,
4421
+ asChild: true,
4422
+ children: /* @__PURE__ */ jsxs(Button, {
4423
+ variant: "outline",
4424
+ className: "aui-thread-welcome-suggestion h-auto w-full flex-1 flex-wrap items-start justify-start gap-1 rounded-xl border-border/50 bg-background/50 px-4 py-3 text-left text-sm transition-colors hover:bg-accent/50 hover:border-accent @md:flex-col",
4425
+ "aria-label": suggestedAction.action,
4426
+ children: [/* @__PURE__ */ jsx("span", {
4427
+ className: "aui-thread-welcome-suggestion-text-1 font-medium text-foreground",
4428
+ children: suggestedAction.title
4429
+ }), /* @__PURE__ */ jsx("span", {
4430
+ className: "aui-thread-welcome-suggestion-text-2 text-muted-foreground text-xs",
4431
+ children: suggestedAction.label
4432
+ })]
4433
+ })
4434
+ })
4435
+ }, `suggested-action-${suggestedAction.title}-${index}`);
4436
+ }
4437
+
4438
+ //#endregion
4439
+ //#region src/components/assistant-modal.tsx
4440
+ const AssistantModal = () => {
4441
+ const $ = c(2);
4442
+ let t0;
4443
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
4444
+ t0 = /* @__PURE__ */ jsx(AssistantModalPrimitive.Anchor, {
4445
+ className: "aui-root aui-modal-anchor fixed right-6 bottom-6 size-14",
4446
+ children: /* @__PURE__ */ jsx(AssistantModalPrimitive.Trigger, {
4447
+ asChild: true,
4448
+ children: /* @__PURE__ */ jsx(AssistantModalButton, {})
4449
+ })
4450
+ });
4451
+ $[0] = t0;
4452
+ } else t0 = $[0];
4453
+ let t1;
4454
+ if ($[1] === Symbol.for("react.memo_cache_sentinel")) {
4455
+ t1 = /* @__PURE__ */ jsxs(AssistantModalPrimitive.Root, { children: [t0, /* @__PURE__ */ jsx(AssistantModalPrimitive.Content, {
4456
+ sideOffset: 16,
4457
+ className: "aui-root aui-modal-content z-50 h-[600px] w-[500px] overflow-clip overscroll-contain rounded-2xl border border-border/50 bg-popover/95 backdrop-blur-xl p-0 text-popover-foreground shadow-2xl outline-none data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-bottom-1/2 data-[state=closed]:slide-out-to-right-1/2 data-[state=closed]:zoom-out-95 data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:slide-in-from-bottom-1/2 data-[state=open]:slide-in-from-right-1/2 data-[state=open]:zoom-in-95 [&>.aui-thread-root]:bg-inherit",
4458
+ children: /* @__PURE__ */ jsx(ThreadWithVoice, {})
4459
+ })] });
4460
+ $[1] = t1;
4461
+ } else t1 = $[1];
4462
+ return t1;
4463
+ };
4464
+ const AssistantModalButton = forwardRef((t0, ref) => {
4465
+ const $ = c(15);
4466
+ let rest;
4467
+ let state;
4468
+ if ($[0] !== t0) {
4469
+ ({"data-state": state, ...rest} = t0);
4470
+ $[0] = t0;
4471
+ $[1] = rest;
4472
+ $[2] = state;
4473
+ } else {
4474
+ rest = $[1];
4475
+ state = $[2];
4476
+ }
4477
+ const tooltip = state === "open" ? "Close Assistant" : "Open Assistant";
4478
+ let t1;
4479
+ let t2;
4480
+ if ($[3] !== state) {
4481
+ t1 = /* @__PURE__ */ jsx("img", {
4482
+ src: "/logo.png",
4483
+ alt: "Assistant",
4484
+ "data-state": state,
4485
+ className: "aui-modal-button-closed-icon absolute size-full object-contain drop-shadow-xl transition-all duration-300 ease-in-out hover:drop-shadow-2xl data-[state=closed]:scale-100 data-[state=closed]:rotate-0 data-[state=open]:scale-0 data-[state=open]:rotate-90"
4486
+ });
4487
+ t2 = /* @__PURE__ */ jsx(ChevronDownIcon, {
4488
+ "data-state": state,
4489
+ className: "aui-modal-button-open-icon absolute size-full rounded-full bg-primary p-3 text-primary-foreground shadow-xl transition-all duration-300 ease-in-out hover:shadow-2xl data-[state=closed]:scale-0 data-[state=closed]:-rotate-90 data-[state=open]:scale-100 data-[state=open]:rotate-0"
4490
+ });
4491
+ $[3] = state;
4492
+ $[4] = t1;
4493
+ $[5] = t2;
4494
+ } else {
4495
+ t1 = $[4];
4496
+ t2 = $[5];
4497
+ }
4498
+ let t3;
4499
+ if ($[6] !== tooltip) {
4500
+ t3 = /* @__PURE__ */ jsx("span", {
4501
+ className: "aui-sr-only sr-only",
4502
+ children: tooltip
4503
+ });
4504
+ $[6] = tooltip;
4505
+ $[7] = t3;
4506
+ } else t3 = $[7];
4507
+ let t4;
4508
+ if ($[8] !== ref || $[9] !== rest || $[10] !== t1 || $[11] !== t2 || $[12] !== t3 || $[13] !== tooltip) {
4509
+ t4 = /* @__PURE__ */ jsxs(TooltipIconButton, {
4510
+ variant: "ghost",
4511
+ tooltip,
4512
+ side: "left",
4513
+ ...rest,
4514
+ className: "aui-modal-button size-full rounded-full transition-all hover:scale-105 hover:bg-transparent active:scale-95",
4515
+ ref,
4516
+ children: [
4517
+ t1,
4518
+ t2,
4519
+ t3
4520
+ ]
4521
+ });
4522
+ $[8] = ref;
4523
+ $[9] = rest;
4524
+ $[10] = t1;
4525
+ $[11] = t2;
4526
+ $[12] = t3;
4527
+ $[13] = tooltip;
4528
+ $[14] = t4;
4529
+ } else t4 = $[14];
4530
+ return t4;
4531
+ });
4532
+ AssistantModalButton.displayName = "AssistantModalButton";
4533
+
4534
+ //#endregion
4535
+ //#region src/components/MCPToolRegistry.tsx
4536
+ /**
4537
+ * MCP Tool Registry Component
4538
+ *
4539
+ * Registers all MCP tools with the assistant-ui runtime.
4540
+ * Uses the unified callTool function which auto-routes based on tool source.
4541
+ *
4542
+ * Usage:
4543
+ * <MCPToolRegistry />
4544
+ *
4545
+ * This component should be placed inside both MCPToolsProvider and AssistantRuntimeProvider.
4546
+ */
4547
+ /**
4548
+ * Bridge component that registers a single tool with assistant-ui
4549
+ */
4550
+ const ToolBridge = ({ tool, callTool }) => {
4551
+ useAssistantTool({
4552
+ toolName: tool.name,
4553
+ description: tool.description ?? "",
4554
+ parameters: tool.inputSchema ?? {},
4555
+ execute: async (args) => {
4556
+ try {
4557
+ return (await callTool(tool.name, args)).content.map((c$1) => {
4558
+ if ("text" in c$1 && typeof c$1.text === "string") return c$1.text;
4559
+ return JSON.stringify(c$1);
4560
+ }).join("\n") || "Tool executed successfully";
4561
+ } catch (error) {
4562
+ console.error(`[ToolBridge] Tool '${tool.name}' execution failed:`, error);
4563
+ throw error;
4564
+ }
4565
+ }
4566
+ });
4567
+ return null;
4568
+ };
4569
+ /**
4570
+ * Tool registry that registers all MCP tools with assistant-ui.
4571
+ * Routes tool calls automatically based on _sourceId.
4572
+ */
4573
+ const MCPToolRegistry = () => {
4574
+ const $ = c(7);
4575
+ const { tools, callTool } = useMCPTools();
4576
+ let t0;
4577
+ if ($[0] !== callTool || $[1] !== tools) {
4578
+ let t1$1;
4579
+ if ($[3] !== callTool) {
4580
+ t1$1 = (tool) => /* @__PURE__ */ jsx(ToolBridge, {
4581
+ tool,
4582
+ callTool
4583
+ }, `${tool._sourceId}-${tool.name}`);
4584
+ $[3] = callTool;
4585
+ $[4] = t1$1;
4586
+ } else t1$1 = $[4];
4587
+ t0 = tools.map(t1$1);
4588
+ $[0] = callTool;
4589
+ $[1] = tools;
4590
+ $[2] = t0;
4591
+ } else t0 = $[2];
4592
+ let t1;
4593
+ if ($[5] !== t0) {
4594
+ t1 = /* @__PURE__ */ jsx(Fragment, { children: t0 });
4595
+ $[5] = t0;
4596
+ $[6] = t1;
4597
+ } else t1 = $[6];
4598
+ return t1;
4599
+ };
4600
+
4601
+ //#endregion
4602
+ //#region src/generated/inline-styles.ts
4603
+ /**
4604
+ * Auto-generated file - DO NOT EDIT
4605
+ * Generated by scripts/generate-inline-styles.js
4606
+ *
4607
+ * Contains the compiled CSS for the web component standalone build.
4608
+ */
4609
+ const WEBMCP_STYLES = "/*! tailwindcss v4.1.17 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0;--tw-space-y-reverse:0;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-ease:initial;--tw-scale-x:1;--tw-scale-y:1;--tw-scale-z:1}}}@layer theme{:root,:host{--font-sans:ui-sans-serif,system-ui,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",\"Segoe UI Symbol\",\"Noto Color Emoji\";--font-mono:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace;--color-red-200:oklch(88.5% .062 18.334);--color-red-500:oklch(63.7% .237 25.331);--color-red-600:oklch(57.7% .245 27.325);--color-amber-500:oklch(76.9% .188 70.08);--color-yellow-500:oklch(79.5% .184 86.047);--color-green-400:oklch(79.2% .209 151.711);--color-green-500:oklch(72.3% .219 149.579);--color-green-600:oklch(62.7% .194 149.214);--color-emerald-500:oklch(69.6% .17 162.48);--color-blue-500:oklch(62.3% .214 259.815);--color-blue-600:oklch(54.6% .245 262.881);--color-black:#000;--color-white:#fff;--spacing:.25rem;--container-md:28rem;--container-lg:32rem;--container-2xl:42rem;--container-3xl:48rem;--text-xs:.75rem;--text-xs--line-height:calc(1/.75);--text-sm:.875rem;--text-sm--line-height:calc(1.25/.875);--text-lg:1.125rem;--text-lg--line-height:calc(1.75/1.125);--text-2xl:1.5rem;--text-2xl--line-height:calc(2/1.5);--text-3xl:1.875rem;--text-3xl--line-height:calc(2.25/1.875);--font-weight-medium:500;--font-weight-semibold:600;--font-weight-bold:700;--font-weight-extrabold:800;--tracking-tight:-.025em;--tracking-wide:.025em;--leading-relaxed:1.625;--radius-xs:.125rem;--radius-2xl:1rem;--radius-3xl:1.5rem;--drop-shadow-xl:0 9px 7px #0000001a;--drop-shadow-2xl:0 25px 25px #00000026;--ease-in-out:cubic-bezier(.4,0,.2,1);--animate-spin:spin 1s linear infinite;--animate-pulse:pulse 2s cubic-bezier(.4,0,.6,1)infinite;--blur-sm:8px;--blur-md:12px;--blur-xl:24px;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4,0,.2,1);--default-font-family:var(--font-sans);--default-mono-font-family:var(--font-mono)}}@layer base{*,:after,:before,::backdrop{box-sizing:border-box;border:0 solid;margin:0;padding:0}::file-selector-button{box-sizing:border-box;border:0 solid;margin:0;padding:0}html,:host{-webkit-text-size-adjust:100%;tab-size:4;line-height:1.5;font-family:var(--default-font-family,ui-sans-serif,system-ui,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\",\"Segoe UI Symbol\",\"Noto Color Emoji\");font-feature-settings:var(--default-font-feature-settings,normal);font-variation-settings:var(--default-font-variation-settings,normal);-webkit-tap-highlight-color:transparent}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;-webkit-text-decoration:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:var(--default-mono-font-family,ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,\"Liberation Mono\",\"Courier New\",monospace);font-feature-settings:var(--default-mono-font-feature-settings,normal);font-variation-settings:var(--default-mono-font-variation-settings,normal);font-size:1em}small{font-size:80%}sub,sup{vertical-align:baseline;font-size:75%;line-height:0;position:relative}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}:-moz-focusring{outline:auto}progress{vertical-align:baseline}summary{display:list-item}ol,ul,menu{list-style:none}img,svg,video,canvas,audio,iframe,embed,object{vertical-align:middle;display:block}img,video{max-width:100%;height:auto}button,input,select,optgroup,textarea{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}::file-selector-button{font:inherit;font-feature-settings:inherit;font-variation-settings:inherit;letter-spacing:inherit;color:inherit;opacity:1;background-color:#0000;border-radius:0}:where(select:is([multiple],[size])) optgroup{font-weight:bolder}:where(select:is([multiple],[size])) optgroup option{padding-inline-start:20px}::file-selector-button{margin-inline-end:4px}::placeholder{opacity:1}@supports (not ((-webkit-appearance:-apple-pay-button))) or (contain-intrinsic-size:1px){::placeholder{color:currentColor}@supports (color:color-mix(in lab, red, red)){::placeholder{color:color-mix(in oklab,currentcolor 50%,transparent)}}}textarea{resize:vertical}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-date-and-time-value{min-height:1lh;text-align:inherit}::-webkit-datetime-edit{display:inline-flex}::-webkit-datetime-edit-fields-wrapper{padding:0}::-webkit-datetime-edit{padding-block:0}::-webkit-datetime-edit-year-field{padding-block:0}::-webkit-datetime-edit-month-field{padding-block:0}::-webkit-datetime-edit-day-field{padding-block:0}::-webkit-datetime-edit-hour-field{padding-block:0}::-webkit-datetime-edit-minute-field{padding-block:0}::-webkit-datetime-edit-second-field{padding-block:0}::-webkit-datetime-edit-millisecond-field{padding-block:0}::-webkit-datetime-edit-meridiem-field{padding-block:0}::-webkit-calendar-picker-indicator{line-height:1}:-moz-ui-invalid{box-shadow:none}button,input:where([type=button],[type=reset],[type=submit]){appearance:button}::file-selector-button{appearance:button}::-webkit-inner-spin-button{height:auto}::-webkit-outer-spin-button{height:auto}[hidden]:where(:not([hidden=until-found])){display:none!important}:root{--radius:.75rem;--background:oklch(100% 0 0);--foreground:oklch(14.1% .005 285.823);--card:oklch(100% 0 0);--card-foreground:oklch(14.1% .005 285.823);--popover:oklch(100% 0 0);--popover-foreground:oklch(14.1% .005 285.823);--primary:oklch(21% .006 285.885);--primary-foreground:oklch(98.5% 0 0);--secondary:oklch(96.7% .001 286.375);--secondary-foreground:oklch(21% .006 285.885);--muted:oklch(96.7% .001 286.375);--muted-foreground:oklch(55.2% .016 285.938);--accent:oklch(96.7% .001 286.375);--accent-foreground:oklch(21% .006 285.885);--destructive:oklch(57.7% .245 27.325);--destructive-foreground:oklch(98.5% 0 0);--border:oklch(92% .004 286.32);--input:oklch(92% .004 286.32);--ring:oklch(70.5% .015 286.067)}.dark{--background:oklch(14.1% .005 285.823);--foreground:oklch(98.5% 0 0);--card:oklch(21% .006 285.885);--card-foreground:oklch(98.5% 0 0);--popover:oklch(21% .006 285.885);--popover-foreground:oklch(98.5% 0 0);--primary:oklch(92% .004 286.32);--primary-foreground:oklch(21% .006 285.885);--secondary:oklch(27.4% .006 286.033);--secondary-foreground:oklch(98.5% 0 0);--muted:oklch(27.4% .006 286.033);--muted-foreground:oklch(70.5% .015 286.067);--accent:oklch(27.4% .006 286.033);--accent-foreground:oklch(98.5% 0 0);--destructive:oklch(70.4% .191 22.216);--destructive-foreground:oklch(98.5% 0 0);--border:oklch(100% 0 0/.1);--input:oklch(100% 0 0/.15);--ring:oklch(55.2% .016 285.938)}*{border-color:var(--border);outline-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){*{outline-color:color-mix(in oklch,var(--ring),transparent 50%)}}body{background-color:var(--background);color:var(--foreground)}}@layer components{.app-shell{z-index:0;background-color:var(--background);background-image:radial-gradient(80% 60% at -10% -10%,oklch(82% .15 270/.15),#0000),radial-gradient(60% 50% at 110% 10%,oklch(85% .1 220/.12),#0000),radial-gradient(50% 45% at 50% 120%,oklch(95% .02 250/.08),#0000);position:relative}.dark .app-shell{background-image:radial-gradient(80% 60% at -10% -10%,oklch(55% .14 270/.25),#0000),radial-gradient(60% 50% at 110% 15%,oklch(60% .12 220/.22),#0000),radial-gradient(50% 45% at 50% 120%,oklch(35% .04 250/.16),#0000)}.app-shell:before,.app-shell:after{content:\"\";pointer-events:none;filter:blur(32px);opacity:.6;z-index:-1;border-radius:9999px;position:absolute;inset:auto}.app-shell:before{background:radial-gradient(60% 60% at 40% 40%,oklch(80% .12 270/.3),#0000);width:260px;height:260px;top:-60px;left:-80px}.app-shell:after{background:radial-gradient(60% 60% at 60% 60%,oklch(84% .1 220/.25),#0000);width:300px;height:300px;bottom:-80px;right:-60px}.toolbar-surface{border-top:1px solid var(--border);background:linear-gradient(to right,var(--background),var(--background),var(--background))}@supports (color:color-mix(in lab, red, red)){.toolbar-surface{background:linear-gradient(to right,var(--background),color-mix(in oklch,var(--background),transparent 5%),var(--background))}}.toolbar-surface{-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}@supports ((-webkit-backdrop-filter:blur(12px)) or (backdrop-filter:blur(12px))){.toolbar-surface{background:var(--background)}@supports (color:color-mix(in lab, red, red)){.toolbar-surface{background:color-mix(in oklch,var(--background),transparent 20%)}}}.toolbar-surface-top{border-bottom:1px solid var(--border);background:linear-gradient(to right,var(--background),var(--background),var(--background))}@supports (color:color-mix(in lab, red, red)){.toolbar-surface-top{background:linear-gradient(to right,var(--background),color-mix(in oklch,var(--background),transparent 5%),var(--background))}}.toolbar-surface-top{-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px)}@supports ((-webkit-backdrop-filter:blur(12px)) or (backdrop-filter:blur(12px))){.toolbar-surface-top{background:var(--background)}@supports (color:color-mix(in lab, red, red)){.toolbar-surface-top{background:color-mix(in oklch,var(--background),transparent 20%)}}}.toolbar-inner{justify-content:space-between;align-items:center;padding:.5rem .75rem;display:flex}.toolbar-card{background:var(--card);justify-content:space-between;align-items:center;gap:.5rem;display:flex}@supports (color:color-mix(in lab, red, red)){.toolbar-card{background:color-mix(in oklch,var(--card),transparent 60%)}}.toolbar-card{border:1px solid var(--border);border-radius:.75rem;padding:.5rem .75rem}.toolbar-group{align-items:center;gap:.25rem;display:flex}.btn-toolbar-primary{background:linear-gradient(to right,var(--primary),var(--primary));border-radius:.75rem;align-items:center;gap:.5rem;height:2.25rem;padding:0 .75rem;display:flex}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-primary{background:linear-gradient(to right,color-mix(in oklch,var(--primary),transparent 95%),color-mix(in oklch,var(--primary),transparent 90%))}}.btn-toolbar-primary{border:1px solid var(--primary)}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-primary{border:1px solid color-mix(in oklch,var(--primary),transparent 80%)}}.btn-toolbar-primary{transition:all .2s}.btn-toolbar-primary:hover{background:linear-gradient(to right,var(--primary),var(--primary))}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-primary:hover{background:linear-gradient(to right,color-mix(in oklch,var(--primary),transparent 90%),color-mix(in oklch,var(--primary),transparent 80%))}}.btn-toolbar-icon-primary{background:linear-gradient(to bottom right,var(--primary),var(--primary));border-radius:9999px;width:2rem;height:2rem;padding:0}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-icon-primary{background:linear-gradient(to bottom right,color-mix(in oklch,var(--primary),transparent 90%),color-mix(in oklch,var(--primary),transparent 80%))}}.btn-toolbar-icon-primary{border:1px solid var(--primary)}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-icon-primary{border:1px solid color-mix(in oklch,var(--primary),transparent 70%)}}.btn-toolbar-icon-primary{transition:all .2s;box-shadow:0 1px 2px #0000000d}.btn-toolbar-icon-primary:hover{background:linear-gradient(to bottom right,var(--primary),var(--primary))}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-icon-primary:hover{background:linear-gradient(to bottom right,color-mix(in oklch,var(--primary),transparent 80%),color-mix(in oklch,var(--primary),transparent 70%))}}.btn-toolbar-icon-secondary{background:linear-gradient(to bottom right,var(--secondary),var(--secondary));border-radius:9999px;width:2rem;height:2rem;padding:0}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-icon-secondary{background:linear-gradient(to bottom right,color-mix(in oklch,var(--secondary),transparent 90%),color-mix(in oklch,var(--secondary),transparent 80%))}}.btn-toolbar-icon-secondary{border:1px solid var(--secondary)}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-icon-secondary{border:1px solid color-mix(in oklch,var(--secondary),transparent 70%)}}.btn-toolbar-icon-secondary{transition:all .2s;box-shadow:0 1px 2px #0000000d}.btn-toolbar-icon-secondary:hover{background:linear-gradient(to bottom right,var(--secondary),var(--secondary))}@supports (color:color-mix(in lab, red, red)){.btn-toolbar-icon-secondary:hover{background:linear-gradient(to bottom right,color-mix(in oklch,var(--secondary),transparent 80%),color-mix(in oklch,var(--secondary),transparent 70%))}}.badge-compact{height:1.25rem;padding:0 .5rem;font-size:10px}.badge-mini{height:1rem;padding:0 .375rem;font-size:10px}@keyframes shimmer-bg{0%{background-position:-1000px 0}to{background-position:1000px 0}}.shimmer{background:linear-gradient(90deg,#0000,#ffffff1a,#0000) 0 0/1000px 100%;animation:3s linear infinite shimmer-bg}.animate-shimmer{animation:2s linear infinite shimmer}@keyframes pulse-glow{0%,to{box-shadow:0 0 20px rgba(var(--primary),.1)}50%{box-shadow:0 0 30px rgba(var(--primary),.2)}}.pulse-glow{animation:2s ease-in-out infinite pulse-glow}@keyframes gradient-x{0%,to{background-position:0%}50%{background-position:100%}}.animate-gradient-x{animation:8s ease-in-out infinite gradient-x}.gradient-text{background:linear-gradient(to right,var(--foreground),var(--foreground))}@supports (color:color-mix(in lab, red, red)){.gradient-text{background:linear-gradient(to right,var(--foreground),color-mix(in oklch,var(--foreground),transparent 30%))}}.gradient-text{-webkit-text-fill-color:transparent;-webkit-background-clip:text;background-clip:text}.glass{background:var(--background)}@supports (color:color-mix(in lab, red, red)){.glass{background:color-mix(in oklch,var(--background),transparent 50%)}}.glass{-webkit-backdrop-filter:blur(12px);backdrop-filter:blur(12px);border:1px solid var(--border)}@supports (color:color-mix(in lab, red, red)){.glass{border:1px solid color-mix(in oklch,var(--border),transparent 50%)}}.tool-card{transition:all .3s ease-out}.tool-card:hover{transform:scale(1.02);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d}.scrollbar-thin{scrollbar-width:thin}.scrollbar-thin::-webkit-scrollbar{width:6px;height:6px}.scrollbar-thin::-webkit-scrollbar-track{background:0 0}.scrollbar-thin::-webkit-scrollbar-thumb{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.scrollbar-thin::-webkit-scrollbar-thumb{background-color:color-mix(in oklch,var(--primary),transparent 80%)}}.scrollbar-thin::-webkit-scrollbar-thumb{border-radius:3px}.scrollbar-thin::-webkit-scrollbar-thumb:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.scrollbar-thin::-webkit-scrollbar-thumb:hover{background-color:color-mix(in oklch,var(--primary),transparent 70%)}}}@layer utilities{.\\@container{container-type:inline-size}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.static{position:static}.sticky{position:sticky}.inset-0{inset:calc(var(--spacing)*0)}.-top-12{top:calc(var(--spacing)*-12)}.top-1\\.5{top:calc(var(--spacing)*1.5)}.top-1\\/2{top:50%}.top-4{top:calc(var(--spacing)*4)}.top-\\[50\\%\\]{top:50%}.right-0{right:calc(var(--spacing)*0)}.right-1\\.5{right:calc(var(--spacing)*1.5)}.right-4{right:calc(var(--spacing)*4)}.right-6{right:calc(var(--spacing)*6)}.bottom-0{bottom:calc(var(--spacing)*0)}.bottom-6{bottom:calc(var(--spacing)*6)}.left-0{left:calc(var(--spacing)*0)}.left-\\[50\\%\\]{left:50%}.z-10{z-index:10}.z-50{z-index:50}.col-span-full{grid-column:1/-1}.col-start-1{grid-column-start:1}.col-start-2{grid-column-start:2}.col-start-3{grid-column-start:3}.row-start-1{grid-row-start:1}.row-start-2{grid-row-start:2}.row-start-3{grid-row-start:3}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-0{margin:calc(var(--spacing)*0)}.mx-2{margin-inline:calc(var(--spacing)*2)}.mx-3{margin-inline:calc(var(--spacing)*3)}.mx-auto{margin-inline:auto}.my-2{margin-block:calc(var(--spacing)*2)}.my-auto{margin-block:auto}.mt-1{margin-top:calc(var(--spacing)*1)}.mt-2{margin-top:calc(var(--spacing)*2)}.mt-3{margin-top:calc(var(--spacing)*3)}.mt-4{margin-top:calc(var(--spacing)*4)}.-mr-1{margin-right:calc(var(--spacing)*-1)}.mr-2{margin-right:calc(var(--spacing)*2)}.mb-1{margin-bottom:calc(var(--spacing)*1)}.mb-2{margin-bottom:calc(var(--spacing)*2)}.mb-3{margin-bottom:calc(var(--spacing)*3)}.mb-4{margin-bottom:calc(var(--spacing)*4)}.-ml-1{margin-left:calc(var(--spacing)*-1)}.-ml-2{margin-left:calc(var(--spacing)*-2)}.ml-1{margin-left:calc(var(--spacing)*1)}.ml-2{margin-left:calc(var(--spacing)*2)}.ml-4{margin-left:calc(var(--spacing)*4)}.ml-auto{margin-left:auto}.line-clamp-2{-webkit-line-clamp:2;-webkit-box-orient:vertical;display:-webkit-box;overflow:hidden}.block{display:block}.flex{display:flex}.grid{display:grid}.inline{display:inline}.inline-flex{display:inline-flex}.table{display:table}.aspect-square{aspect-ratio:1}.size-2\\.5{width:calc(var(--spacing)*2.5);height:calc(var(--spacing)*2.5)}.size-3{width:calc(var(--spacing)*3);height:calc(var(--spacing)*3)}.size-3\\.5{width:calc(var(--spacing)*3.5);height:calc(var(--spacing)*3.5)}.size-4{width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.size-5{width:calc(var(--spacing)*5);height:calc(var(--spacing)*5)}.size-6{width:calc(var(--spacing)*6);height:calc(var(--spacing)*6)}.size-8{width:calc(var(--spacing)*8);height:calc(var(--spacing)*8)}.size-9{width:calc(var(--spacing)*9);height:calc(var(--spacing)*9)}.size-10{width:calc(var(--spacing)*10);height:calc(var(--spacing)*10)}.size-14{width:calc(var(--spacing)*14);height:calc(var(--spacing)*14)}.size-\\[34px\\]{width:34px;height:34px}.size-full{width:100%;height:100%}.h-1\\.5{height:calc(var(--spacing)*1.5)}.h-2{height:calc(var(--spacing)*2)}.h-2\\.5{height:calc(var(--spacing)*2.5)}.h-3{height:calc(var(--spacing)*3)}.h-3\\.5{height:calc(var(--spacing)*3.5)}.h-4{height:calc(var(--spacing)*4)}.h-6{height:calc(var(--spacing)*6)}.h-8{height:calc(var(--spacing)*8)}.h-9{height:calc(var(--spacing)*9)}.h-10{height:calc(var(--spacing)*10)}.h-\\[600px\\]{height:600px}.h-auto{height:auto}.h-full{height:100%}.max-h-24{max-height:calc(var(--spacing)*24)}.max-h-40{max-height:calc(var(--spacing)*40)}.max-h-60{max-height:calc(var(--spacing)*60)}.max-h-\\[80dvh\\]{max-height:80dvh}.max-h-\\[80vh\\]{max-height:80vh}.min-h-8{min-height:calc(var(--spacing)*8)}.min-h-\\[60px\\]{min-height:60px}.w-1\\.5{width:calc(var(--spacing)*1.5)}.w-2{width:calc(var(--spacing)*2)}.w-2\\.5{width:calc(var(--spacing)*2.5)}.w-3{width:calc(var(--spacing)*3)}.w-3\\.5{width:calc(var(--spacing)*3.5)}.w-4{width:calc(var(--spacing)*4)}.w-6{width:calc(var(--spacing)*6)}.w-8{width:calc(var(--spacing)*8)}.w-16{width:calc(var(--spacing)*16)}.w-\\[500px\\]{width:500px}.w-auto{width:auto}.w-fit{width:fit-content}.w-full{width:100%}.w-px{width:1px}.max-w-2xl{max-width:var(--container-2xl)}.max-w-7\\/8{max-width:87.5%}.max-w-\\[80\\%\\]{max-width:80%}.max-w-\\[80px\\]{max-width:80px}.max-w-\\[85\\%\\]{max-width:85%}.max-w-\\[calc\\(100\\%-2rem\\)\\]{max-width:calc(100% - 2rem)}.max-w-\\[var\\(--thread-max-width\\)\\]{max-width:var(--thread-max-width)}.max-w-full{max-width:100%}.min-w-0{min-width:calc(var(--spacing)*0)}.flex-1{flex:1}.shrink-0{flex-shrink:0}.flex-grow,.grow{flex-grow:1}.border-separate{border-collapse:separate}.border-spacing-0{--tw-border-spacing-x:calc(var(--spacing)*0);--tw-border-spacing-y:calc(var(--spacing)*0);border-spacing:var(--tw-border-spacing-x)var(--tw-border-spacing-y)}.origin-\\(--radix-tooltip-content-transform-origin\\){transform-origin:var(--radix-tooltip-content-transform-origin)}.-translate-x-full{--tw-translate-x:-100%;translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-x-\\[-50\\%\\]{--tw-translate-x:-50%;translate:var(--tw-translate-x)var(--tw-translate-y)}.-translate-y-1\\/2{--tw-translate-y:calc(calc(1/2*100%)*-1);translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-y-\\[-50\\%\\]{--tw-translate-y:-50%;translate:var(--tw-translate-x)var(--tw-translate-y)}.translate-y-\\[calc\\(-50\\%_-_2px\\)\\]{--tw-translate-y:calc(-50% - 2px);translate:var(--tw-translate-x)var(--tw-translate-y)}.rotate-45{rotate:45deg}.animate-pulse{animation:var(--animate-pulse)}.animate-spin{animation:var(--animate-spin)}.cursor-pointer{cursor:pointer}.touch-none{touch-action:none}.resize-none{resize:none}.scroll-m-20{scroll-margin:calc(var(--spacing)*20)}.list-decimal{list-style-type:decimal}.list-disc{list-style-type:disc}.auto-rows-auto{grid-auto-rows:auto}.grid-cols-\\[minmax\\(72px\\,1fr\\)_auto\\]{grid-template-columns:minmax(72px,1fr) auto}.flex-col{flex-direction:column}.flex-col-reverse{flex-direction:column-reverse}.flex-row{flex-direction:row}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-end{align-items:flex-end}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.justify-end{justify-content:flex-end}.justify-start{justify-content:flex-start}.gap-0\\.5{gap:calc(var(--spacing)*.5)}.gap-1{gap:calc(var(--spacing)*1)}.gap-1\\.5{gap:calc(var(--spacing)*1.5)}.gap-2{gap:calc(var(--spacing)*2)}.gap-3{gap:calc(var(--spacing)*3)}.gap-4{gap:calc(var(--spacing)*4)}:where(.space-y-1>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*1)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*1)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-2>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*2)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*2)*calc(1 - var(--tw-space-y-reverse)))}:where(.space-y-4>:not(:last-child)){--tw-space-y-reverse:0;margin-block-start:calc(calc(var(--spacing)*4)*var(--tw-space-y-reverse));margin-block-end:calc(calc(var(--spacing)*4)*calc(1 - var(--tw-space-y-reverse)))}.gap-y-2{row-gap:calc(var(--spacing)*2)}.self-center{align-self:center}.self-end{align-self:flex-end}.truncate{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.overflow-auto{overflow:auto}.overflow-clip{overflow:clip}.overflow-hidden{overflow:hidden}.overflow-visible{overflow:visible}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.overflow-y-scroll{overflow-y:scroll}.overscroll-contain{overscroll-behavior:contain}.rounded{border-radius:.25rem}.rounded-2xl{border-radius:var(--radius-2xl)}.rounded-3xl{border-radius:var(--radius-3xl)}.rounded-\\[2px\\]{border-radius:2px}.rounded-\\[14px\\]{border-radius:14px}.rounded-\\[inherit\\]{border-radius:inherit}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius)}.rounded-md{border-radius:calc(var(--radius) - 2px)}.rounded-none{border-radius:0}.rounded-xl{border-radius:calc(var(--radius) + 4px)}.rounded-xs{border-radius:var(--radius-xs)}.\\!rounded-t-none{border-top-left-radius:0!important;border-top-right-radius:0!important}.rounded-t-3xl{border-top-left-radius:var(--radius-3xl);border-top-right-radius:var(--radius-3xl)}.rounded-t-lg{border-top-left-radius:var(--radius);border-top-right-radius:var(--radius)}.rounded-tr-sm{border-top-right-radius:calc(var(--radius) - 4px)}.rounded-b-lg{border-bottom-right-radius:var(--radius);border-bottom-left-radius:var(--radius)}.border{border-style:var(--tw-border-style);border-width:1px}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-t-2{border-top-style:var(--tw-border-style);border-top-width:2px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-l{border-left-style:var(--tw-border-style);border-left-width:1px}.border-l-2{border-left-style:var(--tw-border-style);border-left-width:2px}.border-dashed{--tw-border-style:dashed;border-style:dashed}.border-dotted{--tw-border-style:dotted;border-style:dotted}.border-blue-500\\/40{border-color:#3080ff66}@supports (color:color-mix(in lab, red, red)){.border-blue-500\\/40{border-color:color-mix(in oklab,var(--color-blue-500)40%,transparent)}}.border-blue-500\\/60{border-color:#3080ff99}@supports (color:color-mix(in lab, red, red)){.border-blue-500\\/60{border-color:color-mix(in oklab,var(--color-blue-500)60%,transparent)}}.border-border,.border-border\\/20{border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.border-border\\/20{border-color:color-mix(in oklab,var(--border)20%,transparent)}}.border-border\\/40{border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.border-border\\/40{border-color:color-mix(in oklab,var(--border)40%,transparent)}}.border-border\\/50{border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.border-border\\/50{border-color:color-mix(in oklab,var(--border)50%,transparent)}}.border-destructive,.border-destructive\\/60{border-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.border-destructive\\/60{border-color:color-mix(in oklab,var(--destructive)60%,transparent)}}.border-foreground\\/20{border-color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.border-foreground\\/20{border-color:color-mix(in oklab,var(--foreground)20%,transparent)}}.border-green-500\\/40{border-color:#00c75866}@supports (color:color-mix(in lab, red, red)){.border-green-500\\/40{border-color:color-mix(in oklab,var(--color-green-500)40%,transparent)}}.border-green-500\\/60{border-color:#00c75899}@supports (color:color-mix(in lab, red, red)){.border-green-500\\/60{border-color:color-mix(in oklab,var(--color-green-500)60%,transparent)}}.border-input{border-color:var(--input)}.border-muted-foreground\\/20{border-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.border-muted-foreground\\/20{border-color:color-mix(in oklab,var(--muted-foreground)20%,transparent)}}.border-primary\\/60{border-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.border-primary\\/60{border-color:color-mix(in oklab,var(--primary)60%,transparent)}}.border-red-500\\/40{border-color:#fb2c3666}@supports (color:color-mix(in lab, red, red)){.border-red-500\\/40{border-color:color-mix(in oklab,var(--color-red-500)40%,transparent)}}.border-red-500\\/60{border-color:#fb2c3699}@supports (color:color-mix(in lab, red, red)){.border-red-500\\/60{border-color:color-mix(in oklab,var(--color-red-500)60%,transparent)}}.border-transparent{border-color:#0000}.border-white\\/10{border-color:#ffffff1a}@supports (color:color-mix(in lab, red, red)){.border-white\\/10{border-color:color-mix(in oklab,var(--color-white)10%,transparent)}}.border-t-transparent{border-top-color:#0000}.border-l-transparent{border-left-color:#0000}.bg-\\[color-mix\\(in_oklab\\,rgb\\(var\\(--background\\)\\)_20\\%\\,transparent\\)\\]{background-color:rgb(var(--background))}@supports (color:color-mix(in lab, red, red)){.bg-\\[color-mix\\(in_oklab\\,rgb\\(var\\(--background\\)\\)_20\\%\\,transparent\\)\\]{background-color:color-mix(in oklab,rgb(var(--background))20%,transparent)}}.bg-amber-500{background-color:var(--color-amber-500)}.bg-background,.bg-background\\/50{background-color:var(--background)}@supports (color:color-mix(in lab, red, red)){.bg-background\\/50{background-color:color-mix(in oklab,var(--background)50%,transparent)}}.bg-background\\/80{background-color:var(--background)}@supports (color:color-mix(in lab, red, red)){.bg-background\\/80{background-color:color-mix(in oklab,var(--background)80%,transparent)}}.bg-background\\/95{background-color:var(--background)}@supports (color:color-mix(in lab, red, red)){.bg-background\\/95{background-color:color-mix(in oklab,var(--background)95%,transparent)}}.bg-black{background-color:var(--color-black)}.bg-black\\/50{background-color:#00000080}@supports (color:color-mix(in lab, red, red)){.bg-black\\/50{background-color:color-mix(in oklab,var(--color-black)50%,transparent)}}.bg-blue-500{background-color:var(--color-blue-500)}.bg-blue-500\\/5{background-color:#3080ff0d}@supports (color:color-mix(in lab, red, red)){.bg-blue-500\\/5{background-color:color-mix(in oklab,var(--color-blue-500)5%,transparent)}}.bg-blue-500\\/10{background-color:#3080ff1a}@supports (color:color-mix(in lab, red, red)){.bg-blue-500\\/10{background-color:color-mix(in oklab,var(--color-blue-500)10%,transparent)}}.bg-border{background-color:var(--border)}.bg-destructive,.bg-destructive\\/10{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.bg-destructive\\/10{background-color:color-mix(in oklab,var(--destructive)10%,transparent)}}.bg-foreground{background-color:var(--foreground)}.bg-green-500{background-color:var(--color-green-500)}.bg-green-500\\/5{background-color:#00c7580d}@supports (color:color-mix(in lab, red, red)){.bg-green-500\\/5{background-color:color-mix(in oklab,var(--color-green-500)5%,transparent)}}.bg-green-500\\/10{background-color:#00c7581a}@supports (color:color-mix(in lab, red, red)){.bg-green-500\\/10{background-color:color-mix(in oklab,var(--color-green-500)10%,transparent)}}.bg-muted{background-color:var(--muted)}.bg-muted-foreground\\/15{background-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.bg-muted-foreground\\/15{background-color:color-mix(in oklab,var(--muted-foreground)15%,transparent)}}.bg-muted\\/5{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\\/5{background-color:color-mix(in oklab,var(--muted)5%,transparent)}}.bg-muted\\/30{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\\/30{background-color:color-mix(in oklab,var(--muted)30%,transparent)}}.bg-muted\\/50{background-color:var(--muted)}@supports (color:color-mix(in lab, red, red)){.bg-muted\\/50{background-color:color-mix(in oklab,var(--muted)50%,transparent)}}.bg-popover\\/95{background-color:var(--popover)}@supports (color:color-mix(in lab, red, red)){.bg-popover\\/95{background-color:color-mix(in oklab,var(--popover)95%,transparent)}}.bg-primary,.bg-primary\\/10{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.bg-primary\\/10{background-color:color-mix(in oklab,var(--primary)10%,transparent)}}.bg-red-500{background-color:var(--color-red-500)}.bg-red-500\\/5{background-color:#fb2c360d}@supports (color:color-mix(in lab, red, red)){.bg-red-500\\/5{background-color:color-mix(in oklab,var(--color-red-500)5%,transparent)}}.bg-red-500\\/10{background-color:#fb2c361a}@supports (color:color-mix(in lab, red, red)){.bg-red-500\\/10{background-color:color-mix(in oklab,var(--color-red-500)10%,transparent)}}.bg-secondary{background-color:var(--secondary)}.bg-transparent{background-color:#0000}.bg-white{background-color:var(--color-white)}.bg-yellow-500{background-color:var(--color-yellow-500)}.fill-foreground{fill:var(--foreground)}.stroke-\\[1\\.5px\\]{stroke-width:1.5px}.object-contain{object-fit:contain}.object-cover{object-fit:cover}.p-0{padding:calc(var(--spacing)*0)}.p-1{padding:calc(var(--spacing)*1)}.p-2{padding:calc(var(--spacing)*2)}.p-3{padding:calc(var(--spacing)*3)}.p-4{padding:calc(var(--spacing)*4)}.p-6{padding:calc(var(--spacing)*6)}.p-px{padding:1px}.px-0{padding-inline:calc(var(--spacing)*0)}.px-1\\.5{padding-inline:calc(var(--spacing)*1.5)}.px-2{padding-inline:calc(var(--spacing)*2)}.px-2\\.5{padding-inline:calc(var(--spacing)*2.5)}.px-3{padding-inline:calc(var(--spacing)*3)}.px-4{padding-inline:calc(var(--spacing)*4)}.px-5{padding-inline:calc(var(--spacing)*5)}.px-6{padding-inline:calc(var(--spacing)*6)}.px-8{padding-inline:calc(var(--spacing)*8)}.py-0\\.5{padding-block:calc(var(--spacing)*.5)}.py-1{padding-block:calc(var(--spacing)*1)}.py-1\\.5{padding-block:calc(var(--spacing)*1.5)}.py-2{padding-block:calc(var(--spacing)*2)}.py-2\\.5{padding-block:calc(var(--spacing)*2.5)}.py-3{padding-block:calc(var(--spacing)*3)}.py-4{padding-block:calc(var(--spacing)*4)}.pt-0\\.5{padding-top:calc(var(--spacing)*.5)}.pt-2{padding-top:calc(var(--spacing)*2)}.pr-2{padding-right:calc(var(--spacing)*2)}.pb-1{padding-bottom:calc(var(--spacing)*1)}.pb-4{padding-bottom:calc(var(--spacing)*4)}.pl-3{padding-left:calc(var(--spacing)*3)}.pl-4{padding-left:calc(var(--spacing)*4)}.text-center{text-align:center}.text-left{text-align:left}.font-mono{font-family:var(--font-mono)}.text-2xl{font-size:var(--text-2xl);line-height:var(--tw-leading,var(--text-2xl--line-height))}.text-3xl{font-size:var(--text-3xl);line-height:var(--tw-leading,var(--text-3xl--line-height))}.text-lg{font-size:var(--text-lg);line-height:var(--tw-leading,var(--text-lg--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\\[10px\\]{font-size:10px}.text-\\[11px\\]{font-size:11px}.text-\\[13px\\]{font-size:13px}.text-\\[15px\\]{font-size:15px}.text-\\[17px\\]{font-size:17px}.text-\\[19px\\]{font-size:19px}.text-\\[21px\\]{font-size:21px}.text-\\[25px\\]{font-size:25px}.leading-7{--tw-leading:calc(var(--spacing)*7);line-height:calc(var(--spacing)*7)}.leading-none{--tw-leading:1;line-height:1}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-bold{--tw-font-weight:var(--font-weight-bold);font-weight:var(--font-weight-bold)}.font-extrabold{--tw-font-weight:var(--font-weight-extrabold);font-weight:var(--font-weight-extrabold)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.tracking-wide{--tw-tracking:var(--tracking-wide);letter-spacing:var(--tracking-wide)}.text-balance{text-wrap:balance}.break-words{overflow-wrap:break-word}.whitespace-nowrap{white-space:nowrap}.whitespace-pre-wrap{white-space:pre-wrap}.text-background{color:var(--background)}.text-blue-600{color:var(--color-blue-600)}.text-destructive{color:var(--destructive)}.text-destructive-foreground{color:var(--destructive-foreground)}.text-emerald-500{color:var(--color-emerald-500)}.text-foreground,.text-foreground\\/80{color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.text-foreground\\/80{color:color-mix(in oklab,var(--foreground)80%,transparent)}}.text-green-600{color:var(--color-green-600)}.text-muted-foreground,.text-muted-foreground\\/65{color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\\/65{color:color-mix(in oklab,var(--muted-foreground)65%,transparent)}}.text-muted-foreground\\/70{color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.text-muted-foreground\\/70{color:color-mix(in oklab,var(--muted-foreground)70%,transparent)}}.text-popover-foreground{color:var(--popover-foreground)}.text-primary{color:var(--primary)}.text-primary-foreground{color:var(--primary-foreground)}.text-red-600{color:var(--color-red-600)}.text-secondary-foreground{color:var(--secondary-foreground)}.text-white{color:var(--color-white)}.lowercase{text-transform:lowercase}.uppercase{text-transform:uppercase}.italic{font-style:italic}.underline{text-decoration-line:underline}.underline-offset-4{text-underline-offset:4px}.opacity-70{opacity:.7}.opacity-100{opacity:1}.shadow-2xl{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\\[0_0_12px_rgba\\(34\\,197\\,94\\,0\\.3\\)\\]{--tw-shadow:0 0 12px var(--tw-shadow-color,#22c55e4d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\\[0_0_12px_rgba\\(59\\,130\\,246\\,0\\.3\\)\\]{--tw-shadow:0 0 12px var(--tw-shadow-color,#3b82f64d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\\[0_0_12px_rgba\\(239\\,68\\,68\\,0\\.3\\)\\]{--tw-shadow:0 0 12px var(--tw-shadow-color,#ef44444d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\\[0_12px_24px_-16px_rgba\\(37\\,99\\,235\\,0\\.55\\)\\]{--tw-shadow:0 12px 24px -16px var(--tw-shadow-color,#2563eb8c);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-\\[0_12px_24px_-18px_rgba\\(220\\,38\\,38\\,0\\.55\\)\\]{--tw-shadow:0 12px 24px -18px var(--tw-shadow-color,#dc26268c);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-lg{--tw-shadow:0 10px 15px -3px var(--tw-shadow-color,#0000001a),0 4px 6px -4px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-sm{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xl{--tw-shadow:0 20px 25px -5px var(--tw-shadow-color,#0000001a),0 8px 10px -6px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.shadow-xs{--tw-shadow:0 1px 2px 0 var(--tw-shadow-color,#0000000d);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.\\[box-shadow\\:inset_0_1px_2px_0_rgba\\(255\\,255\\,255\\,0\\.15\\)\\]{box-shadow:inset 0 1px 2px #ffffff26}.shadow-black\\/20{--tw-shadow-color:#0003}@supports (color:color-mix(in lab, red, red)){.shadow-black\\/20{--tw-shadow-color:color-mix(in oklab,color-mix(in oklab,var(--color-black)20%,transparent)var(--tw-shadow-alpha),transparent)}}.ring-offset-background{--tw-ring-offset-color:var(--background)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.drop-shadow-xl{--tw-drop-shadow-size:drop-shadow(0 9px 7px var(--tw-drop-shadow-color,#0000001a));--tw-drop-shadow:drop-shadow(var(--drop-shadow-xl));filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}.backdrop-blur-md{--tw-backdrop-blur:blur(var(--blur-md));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.backdrop-blur-sm{--tw-backdrop-blur:blur(var(--blur-sm));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.backdrop-blur-xl{--tw-backdrop-blur:blur(var(--blur-xl));-webkit-backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,)var(--tw-backdrop-brightness,)var(--tw-backdrop-contrast,)var(--tw-backdrop-grayscale,)var(--tw-backdrop-hue-rotate,)var(--tw-backdrop-invert,)var(--tw-backdrop-opacity,)var(--tw-backdrop-saturate,)var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-\\[color\\,box-shadow\\]{transition-property:color,box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-all{transition-property:all;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-shadow{transition-property:box-shadow;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-200{--tw-duration:.2s;transition-duration:.2s}.duration-300{--tw-duration:.3s;transition-duration:.3s}.ease-in-out{--tw-ease:var(--ease-in-out);transition-timing-function:var(--ease-in-out)}.outline-none{--tw-outline-style:none;outline-style:none}.select-none{-webkit-user-select:none;user-select:none}.placeholder\\:text-muted-foreground::placeholder,.placeholder\\:text-muted-foreground\\/70::placeholder{color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.placeholder\\:text-muted-foreground\\/70::placeholder{color:color-mix(in oklab,var(--muted-foreground)70%,transparent)}}.first\\:mt-0:first-child{margin-top:calc(var(--spacing)*0)}.first\\:mt-3:first-child{margin-top:calc(var(--spacing)*3)}.first\\:mt-4:first-child{margin-top:calc(var(--spacing)*4)}.first\\:rounded-tl-lg:first-child{border-top-left-radius:var(--radius)}.first\\:border-t:first-child{border-top-style:var(--tw-border-style);border-top-width:1px}.last\\:mb-0:last-child{margin-bottom:calc(var(--spacing)*0)}.last\\:mb-5:last-child{margin-bottom:calc(var(--spacing)*5)}.last\\:mb-24:last-child{margin-bottom:calc(var(--spacing)*24)}.last\\:rounded-tr-lg:last-child{border-top-right-radius:var(--radius)}.last\\:border-r:last-child{border-right-style:var(--tw-border-style);border-right-width:1px}.empty\\:hidden:empty{display:none}.focus-within\\:border-ring\\/50:focus-within{border-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.focus-within\\:border-ring\\/50:focus-within{border-color:color-mix(in oklab,var(--ring)50%,transparent)}}.focus-within\\:border-white\\/20:focus-within{border-color:#fff3}@supports (color:color-mix(in lab, red, red)){.focus-within\\:border-white\\/20:focus-within{border-color:color-mix(in oklab,var(--color-white)20%,transparent)}}.focus-within\\:shadow-2xl:focus-within{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-within\\:shadow-md:focus-within{--tw-shadow:0 4px 6px -1px var(--tw-shadow-color,#0000001a),0 2px 4px -2px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-within\\:ring-2:focus-within{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-within\\:shadow-black\\/30:focus-within{--tw-shadow-color:#0000004d}@supports (color:color-mix(in lab, red, red)){.focus-within\\:shadow-black\\/30:focus-within{--tw-shadow-color:color-mix(in oklab,color-mix(in oklab,var(--color-black)30%,transparent)var(--tw-shadow-alpha),transparent)}}.focus-within\\:ring-ring:focus-within{--tw-ring-color:var(--ring)}.focus-within\\:ring-offset-2:focus-within{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}@media (hover:hover){.hover\\:scale-105:hover{--tw-scale-x:105%;--tw-scale-y:105%;--tw-scale-z:105%;scale:var(--tw-scale-x)var(--tw-scale-y)}.hover\\:border-accent:hover{border-color:var(--accent)}.hover\\:border-border\\/60:hover{border-color:var(--border)}@supports (color:color-mix(in lab, red, red)){.hover\\:border-border\\/60:hover{border-color:color-mix(in oklab,var(--border)60%,transparent)}}.hover\\:border-white\\/15:hover{border-color:#ffffff26}@supports (color:color-mix(in lab, red, red)){.hover\\:border-white\\/15:hover{border-color:color-mix(in oklab,var(--color-white)15%,transparent)}}.hover\\:\\!bg-white:hover{background-color:var(--color-white)!important}.hover\\:bg-accent:hover,.hover\\:bg-accent\\/50:hover{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-accent\\/50:hover{background-color:color-mix(in oklab,var(--accent)50%,transparent)}}.hover\\:bg-destructive\\/10:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-destructive\\/10:hover{background-color:color-mix(in oklab,var(--destructive)10%,transparent)}}.hover\\:bg-destructive\\/80:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-destructive\\/80:hover{background-color:color-mix(in oklab,var(--destructive)80%,transparent)}}.hover\\:bg-destructive\\/90:hover{background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-destructive\\/90:hover{background-color:color-mix(in oklab,var(--destructive)90%,transparent)}}.hover\\:bg-muted-foreground\\/15:hover{background-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-muted-foreground\\/15:hover{background-color:color-mix(in oklab,var(--muted-foreground)15%,transparent)}}.hover\\:bg-primary\\/80:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-primary\\/80:hover{background-color:color-mix(in oklab,var(--primary)80%,transparent)}}.hover\\:bg-primary\\/90:hover{background-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-primary\\/90:hover{background-color:color-mix(in oklab,var(--primary)90%,transparent)}}.hover\\:bg-secondary\\/80:hover{background-color:var(--secondary)}@supports (color:color-mix(in lab, red, red)){.hover\\:bg-secondary\\/80:hover{background-color:color-mix(in oklab,var(--secondary)80%,transparent)}}.hover\\:bg-transparent:hover{background-color:#0000}.hover\\:text-accent-foreground:hover{color:var(--accent-foreground)}.hover\\:text-destructive:hover{color:var(--destructive)}.hover\\:text-foreground:hover{color:var(--foreground)}.hover\\:underline:hover{text-decoration-line:underline}.hover\\:opacity-75:hover{opacity:.75}.hover\\:opacity-100:hover{opacity:1}.hover\\:shadow-2xl:hover{--tw-shadow:0 25px 50px -12px var(--tw-shadow-color,#00000040);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.hover\\:shadow-\\[0_14px_24px_-14px_rgba\\(37\\,99\\,235\\,0\\.6\\)\\]:hover{--tw-shadow:0 14px 24px -14px var(--tw-shadow-color,#2563eb99);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.hover\\:shadow-\\[0_14px_24px_-16px_rgba\\(220\\,38\\,38\\,0\\.6\\)\\]:hover{--tw-shadow:0 14px 24px -16px var(--tw-shadow-color,#dc262699);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.hover\\:drop-shadow-2xl:hover{--tw-drop-shadow-size:drop-shadow(0 25px 25px var(--tw-drop-shadow-color,#00000026));--tw-drop-shadow:drop-shadow(var(--drop-shadow-2xl));filter:var(--tw-blur,)var(--tw-brightness,)var(--tw-contrast,)var(--tw-grayscale,)var(--tw-hue-rotate,)var(--tw-invert,)var(--tw-saturate,)var(--tw-sepia,)var(--tw-drop-shadow,)}}.focus\\:ring-2:focus{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus\\:ring-ring:focus{--tw-ring-color:var(--ring)}.focus\\:ring-offset-2:focus{--tw-ring-offset-width:2px;--tw-ring-offset-shadow:var(--tw-ring-inset,)0 0 0 var(--tw-ring-offset-width)var(--tw-ring-offset-color)}.focus\\:outline-hidden:focus{--tw-outline-style:none;outline-style:none}@media (forced-colors:active){.focus\\:outline-hidden:focus{outline-offset:2px;outline:2px solid #0000}}.focus\\:outline-none:focus{--tw-outline-style:none;outline-style:none}.focus-visible\\:border-ring:focus-visible{border-color:var(--ring)}.focus-visible\\:ring-0:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(0px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\\:ring-1:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(1px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\\:ring-2:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\\:ring-\\[3px\\]:focus-visible{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(3px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.focus-visible\\:ring-destructive\\/20:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\:ring-destructive\\/20:focus-visible{--tw-ring-color:color-mix(in oklab,var(--destructive)20%,transparent)}}.focus-visible\\:ring-destructive\\/40:focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\:ring-destructive\\/40:focus-visible{--tw-ring-color:color-mix(in oklab,var(--destructive)40%,transparent)}}.focus-visible\\:ring-primary\\/40:focus-visible{--tw-ring-color:var(--primary)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\:ring-primary\\/40:focus-visible{--tw-ring-color:color-mix(in oklab,var(--primary)40%,transparent)}}.focus-visible\\:ring-ring:focus-visible,.focus-visible\\:ring-ring\\/50:focus-visible{--tw-ring-color:var(--ring)}@supports (color:color-mix(in lab, red, red)){.focus-visible\\:ring-ring\\/50:focus-visible{--tw-ring-color:color-mix(in oklab,var(--ring)50%,transparent)}}.focus-visible\\:outline-1:focus-visible{outline-style:var(--tw-outline-style);outline-width:1px}.focus-visible\\:outline-none:focus-visible{--tw-outline-style:none;outline-style:none}.active\\:scale-95:active{--tw-scale-x:95%;--tw-scale-y:95%;--tw-scale-z:95%;scale:var(--tw-scale-x)var(--tw-scale-y)}.disabled\\:pointer-events-none:disabled{pointer-events:none}.disabled\\:invisible:disabled{visibility:hidden}.disabled\\:cursor-not-allowed:disabled{cursor:not-allowed}.disabled\\:opacity-50:disabled{opacity:.5}.has-\\[\\>svg\\]\\:px-2\\.5:has(>svg){padding-inline:calc(var(--spacing)*2.5)}.has-\\[\\>svg\\]\\:px-3:has(>svg){padding-inline:calc(var(--spacing)*3)}.has-\\[\\>svg\\]\\:px-4:has(>svg){padding-inline:calc(var(--spacing)*4)}.aria-invalid\\:border-destructive[aria-invalid=true]{border-color:var(--destructive)}.aria-invalid\\:ring-destructive\\/20[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.aria-invalid\\:ring-destructive\\/20[aria-invalid=true]{--tw-ring-color:color-mix(in oklab,var(--destructive)20%,transparent)}}.data-floating\\:absolute[data-floating]{position:absolute}.data-floating\\:rounded-md[data-floating]{border-radius:calc(var(--radius) - 2px)}.data-floating\\:border[data-floating]{border-style:var(--tw-border-style);border-width:1px}.data-floating\\:bg-background[data-floating]{background-color:var(--background)}.data-floating\\:p-1[data-floating]{padding:calc(var(--spacing)*1)}.data-floating\\:shadow-sm[data-floating]{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a),0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)}.data-\\[orientation\\=horizontal\\]\\:h-px[data-orientation=horizontal]{height:1px}.data-\\[orientation\\=horizontal\\]\\:w-full[data-orientation=horizontal]{width:100%}.data-\\[orientation\\=vertical\\]\\:h-full[data-orientation=vertical]{height:100%}.data-\\[orientation\\=vertical\\]\\:w-px[data-orientation=vertical]{width:1px}.data-\\[state\\=closed\\]\\:scale-0[data-state=closed]{--tw-scale-x:0%;--tw-scale-y:0%;--tw-scale-z:0%;scale:var(--tw-scale-x)var(--tw-scale-y)}.data-\\[state\\=closed\\]\\:scale-100[data-state=closed]{--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.data-\\[state\\=closed\\]\\:-rotate-90[data-state=closed]{rotate:-90deg}.data-\\[state\\=closed\\]\\:rotate-0[data-state=closed]{rotate:none}.data-\\[state\\=open\\]\\:scale-0[data-state=open]{--tw-scale-x:0%;--tw-scale-y:0%;--tw-scale-z:0%;scale:var(--tw-scale-x)var(--tw-scale-y)}.data-\\[state\\=open\\]\\:scale-100[data-state=open]{--tw-scale-x:100%;--tw-scale-y:100%;--tw-scale-z:100%;scale:var(--tw-scale-x)var(--tw-scale-y)}.data-\\[state\\=open\\]\\:rotate-0[data-state=open]{rotate:none}.data-\\[state\\=open\\]\\:rotate-90[data-state=open]{rotate:90deg}.data-\\[state\\=open\\]\\:bg-accent[data-state=open]{background-color:var(--accent)}.data-\\[state\\=open\\]\\:text-muted-foreground[data-state=open]{color:var(--muted-foreground)}@media (min-width:40rem){.sm\\:max-w-3xl{max-width:var(--container-3xl)}.sm\\:max-w-lg{max-width:var(--container-lg)}.sm\\:max-w-md{max-width:var(--container-md)}.sm\\:flex-row{flex-direction:row}.sm\\:justify-end{justify-content:flex-end}.sm\\:text-left{text-align:left}}@media (min-width:48rem){.md\\:pb-6{padding-bottom:calc(var(--spacing)*6)}}@container (min-width:28rem){.\\@md\\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.\\@md\\:flex-col{flex-direction:column}}.dark\\:border-input:is(.dark *){border-color:var(--input)}.dark\\:border-muted-foreground\\/15:is(.dark *){border-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.dark\\:border-muted-foreground\\/15:is(.dark *){border-color:color-mix(in oklab,var(--muted-foreground)15%,transparent)}}.dark\\:bg-background:is(.dark *){background-color:var(--background)}.dark\\:bg-destructive\\/5:is(.dark *){background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:bg-destructive\\/5:is(.dark *){background-color:color-mix(in oklab,var(--destructive)5%,transparent)}}.dark\\:bg-destructive\\/60:is(.dark *){background-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:bg-destructive\\/60:is(.dark *){background-color:color-mix(in oklab,var(--destructive)60%,transparent)}}.dark\\:bg-input\\/30:is(.dark *){background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\\:bg-input\\/30:is(.dark *){background-color:color-mix(in oklab,var(--input)30%,transparent)}}.dark\\:bg-muted-foreground\\/20:is(.dark *){background-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.dark\\:bg-muted-foreground\\/20:is(.dark *){background-color:color-mix(in oklab,var(--muted-foreground)20%,transparent)}}.dark\\:stroke-\\[2\\.5px\\]:is(.dark *){stroke-width:2.5px}.dark\\:text-green-400:is(.dark *){color:var(--color-green-400)}.dark\\:text-red-200:is(.dark *){color:var(--color-red-200)}@media (hover:hover){.dark\\:hover\\:bg-accent:is(.dark *):hover,.dark\\:hover\\:bg-accent\\/50:is(.dark *):hover{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.dark\\:hover\\:bg-accent\\/50:is(.dark *):hover{background-color:color-mix(in oklab,var(--accent)50%,transparent)}}.dark\\:hover\\:bg-accent\\/60:is(.dark *):hover{background-color:var(--accent)}@supports (color:color-mix(in lab, red, red)){.dark\\:hover\\:bg-accent\\/60:is(.dark *):hover{background-color:color-mix(in oklab,var(--accent)60%,transparent)}}.dark\\:hover\\:bg-input\\/50:is(.dark *):hover{background-color:var(--input)}@supports (color:color-mix(in lab, red, red)){.dark\\:hover\\:bg-input\\/50:is(.dark *):hover{background-color:color-mix(in oklab,var(--input)50%,transparent)}}.dark\\:hover\\:bg-muted-foreground\\/30:is(.dark *):hover{background-color:var(--muted-foreground)}@supports (color:color-mix(in lab, red, red)){.dark\\:hover\\:bg-muted-foreground\\/30:is(.dark *):hover{background-color:color-mix(in oklab,var(--muted-foreground)30%,transparent)}}}.dark\\:focus-visible\\:ring-destructive\\/40:is(.dark *):focus-visible{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:focus-visible\\:ring-destructive\\/40:is(.dark *):focus-visible{--tw-ring-color:color-mix(in oklab,var(--destructive)40%,transparent)}}.dark\\:aria-invalid\\:ring-destructive\\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:var(--destructive)}@supports (color:color-mix(in lab, red, red)){.dark\\:aria-invalid\\:ring-destructive\\/40:is(.dark *)[aria-invalid=true]{--tw-ring-color:color-mix(in oklab,var(--destructive)40%,transparent)}}.\\[\\&_svg\\]\\:pointer-events-none svg{pointer-events:none}.\\[\\&_svg\\]\\:shrink-0 svg{flex-shrink:0}.\\[\\&_svg\\]\\:text-background svg{color:var(--background)}.\\[\\&_svg\\]\\:text-black svg{color:var(--color-black)}@media (hover:hover){.hover\\:\\[\\&_svg\\]\\:text-destructive:hover svg{color:var(--destructive)}}.\\[\\&_svg\\:not\\(\\[class\\*\\=\\'size-\\'\\]\\)\\]\\:size-4 svg:not([class*=size-]){width:calc(var(--spacing)*4);height:calc(var(--spacing)*4)}.\\[\\&\\:last-child\\>td\\:first-child\\]\\:rounded-bl-lg:last-child>td:first-child{border-bottom-left-radius:var(--radius)}.\\[\\&\\:last-child\\>td\\:last-child\\]\\:rounded-br-lg:last-child>td:last-child{border-bottom-right-radius:var(--radius)}.\\[\\&\\:nth-child\\(n\\+3\\)\\]\\:hidden:nth-child(n+3){display:none}@container (min-width:28rem){.\\@md\\:\\[\\&\\:nth-child\\(n\\+3\\)\\]\\:block:nth-child(n+3){display:block}}.\\[\\&\\:where\\(\\>\\*\\)\\]\\:col-start-2:where(){grid-column-start:2}.only\\:\\[\\&\\>\\#attachment-tile\\]\\:size-24:only-child>#attachment-tile{width:calc(var(--spacing)*24);height:calc(var(--spacing)*24)}.\\[\\&\\>\\.aui-thread-root\\]\\:bg-inherit>.aui-thread-root{background-color:inherit}.\\[\\&\\>a\\]\\:text-xs>a{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.\\[\\&\\>a\\]\\:no-underline>a{text-decoration-line:none}.\\[\\&\\>button\\]\\:rounded-full>button{border-radius:3.40282e38px}.\\[\\&\\>button\\]\\:bg-foreground\\/60>button{background-color:var(--foreground)}@supports (color:color-mix(in lab, red, red)){.\\[\\&\\>button\\]\\:bg-foreground\\/60>button{background-color:color-mix(in oklab,var(--foreground)60%,transparent)}}.\\[\\&\\>button\\]\\:p-1>button{padding:calc(var(--spacing)*1)}.\\[\\&\\>button\\]\\:opacity-100>button{opacity:1}.\\[\\&\\>button\\]\\:\\!ring-0>button{--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(0px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor)!important;box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow)!important}@media (hover:hover){.\\[\\&\\>button\\]\\:hover\\:\\[\\&_svg\\]\\:text-destructive>button:hover svg{color:var(--destructive)}}.\\[\\&\\>li\\]\\:mt-1>li{margin-top:calc(var(--spacing)*1)}.\\[\\&\\>span\\]\\:text-xs>span{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.\\[\\&\\[align\\=center\\]\\]\\:text-center[align=center]{text-align:center}.\\[\\&\\[align\\=right\\]\\]\\:text-right[align=right]{text-align:right}}@keyframes shimmer{0%{transform:translate(-100%)}to{transform:translate(200%)}}@keyframes subtle-pulse{0%,to{opacity:1}50%{opacity:.85}}@keyframes smooth-slide-down{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}@keyframes fadeInUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}@keyframes gradient-shift{0%,to{transform:translate(0%)translateY(0%)}25%{transform:translate(100%)translateY(100%)}50%{transform:translate(100%)translateY(0%)}75%{transform:translate(0%)translateY(100%)}}@keyframes float{0%,to{transform:translateY(0)translate(0)}33%{transform:translateY(-30px)translate(20px)}66%{transform:translateY(20px)translate(-20px)}}@keyframes float-delayed{0%,to{transform:translateY(0)translate(0)}33%{transform:translateY(30px)translate(-30px)}66%{transform:translateY(-20px)translate(20px)}}.tool-card-transition{transition:all .4s cubic-bezier(.34,1.56,.64,1)}.tool-card-smooth{transition:all .35s cubic-bezier(.4,0,.2,1)}.animate-fadeInUp{opacity:0;animation:.5s ease-out forwards fadeInUp}.animate-gradient-shift{background-size:200% 200%;animation:20s ease-in-out infinite gradient-shift}.animate-float-slow{animation:20s ease-in-out infinite float}.animate-float-delayed{animation:25s ease-in-out 5s infinite float-delayed}.no-scrollbar::-webkit-scrollbar{display:none}.no-scrollbar{-ms-overflow-style:none;scrollbar-width:none}@keyframes aui-pulse{50%{opacity:.5}}:where(.aui-md[data-status=running]):empty:after,:where(.aui-md[data-status=running])>:where(:not(ol):not(ul):not(pre)):last-child:after,:where(.aui-md[data-status=running])>pre:last-child code:after,:where(.aui-md[data-status=running])>:where(:is(ol,ul):last-child)>:where(li:last-child:not(:has(*>li))):after,:where(.aui-md[data-status=running])>:where(:is(ol,ul):last-child)>:where(li:last-child)>:where(:is(ol,ul):last-child)>:where(li:last-child:not(:has(*>li))):after,:where(.aui-md[data-status=running])>:where(:is(ol,ul):last-child)>:where(li:last-child)>:where(:is(ol,ul):last-child)>:where(li:last-child)>:where(:is(ol,ul):last-child)>:where(li:last-child):after{--aui-content:\"●\";content:var(--aui-content);margin-left:.25rem;margin-right:.25rem;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;animation:2s cubic-bezier(.4,0,.6,1) infinite aui-pulse}@property --tw-border-spacing-x{syntax:\"<length>\";inherits:false;initial-value:0}@property --tw-border-spacing-y{syntax:\"<length>\";inherits:false;initial-value:0}@property --tw-translate-x{syntax:\"*\";inherits:false;initial-value:0}@property --tw-translate-y{syntax:\"*\";inherits:false;initial-value:0}@property --tw-translate-z{syntax:\"*\";inherits:false;initial-value:0}@property --tw-space-y-reverse{syntax:\"*\";inherits:false;initial-value:0}@property --tw-border-style{syntax:\"*\";inherits:false;initial-value:solid}@property --tw-leading{syntax:\"*\";inherits:false}@property --tw-font-weight{syntax:\"*\";inherits:false}@property --tw-tracking{syntax:\"*\";inherits:false}@property --tw-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:\"*\";inherits:false}@property --tw-shadow-alpha{syntax:\"<percentage>\";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:\"*\";inherits:false}@property --tw-inset-shadow-alpha{syntax:\"<percentage>\";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:\"*\";inherits:false}@property --tw-ring-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:\"*\";inherits:false}@property --tw-inset-ring-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:\"*\";inherits:false}@property --tw-ring-offset-width{syntax:\"<length>\";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:\"*\";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:\"*\";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:\"*\";inherits:false;initial-value:solid}@property --tw-blur{syntax:\"*\";inherits:false}@property --tw-brightness{syntax:\"*\";inherits:false}@property --tw-contrast{syntax:\"*\";inherits:false}@property --tw-grayscale{syntax:\"*\";inherits:false}@property --tw-hue-rotate{syntax:\"*\";inherits:false}@property --tw-invert{syntax:\"*\";inherits:false}@property --tw-opacity{syntax:\"*\";inherits:false}@property --tw-saturate{syntax:\"*\";inherits:false}@property --tw-sepia{syntax:\"*\";inherits:false}@property --tw-drop-shadow{syntax:\"*\";inherits:false}@property --tw-drop-shadow-color{syntax:\"*\";inherits:false}@property --tw-drop-shadow-alpha{syntax:\"<percentage>\";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:\"*\";inherits:false}@property --tw-backdrop-blur{syntax:\"*\";inherits:false}@property --tw-backdrop-brightness{syntax:\"*\";inherits:false}@property --tw-backdrop-contrast{syntax:\"*\";inherits:false}@property --tw-backdrop-grayscale{syntax:\"*\";inherits:false}@property --tw-backdrop-hue-rotate{syntax:\"*\";inherits:false}@property --tw-backdrop-invert{syntax:\"*\";inherits:false}@property --tw-backdrop-opacity{syntax:\"*\";inherits:false}@property --tw-backdrop-saturate{syntax:\"*\";inherits:false}@property --tw-backdrop-sepia{syntax:\"*\";inherits:false}@property --tw-duration{syntax:\"*\";inherits:false}@property --tw-ease{syntax:\"*\";inherits:false}@property --tw-scale-x{syntax:\"*\";inherits:false;initial-value:1}@property --tw-scale-y{syntax:\"*\";inherits:false;initial-value:1}@property --tw-scale-z{syntax:\"*\";inherits:false;initial-value:1}@keyframes spin{to{transform:rotate(360deg)}}@keyframes pulse{50%{opacity:.5}}";
4610
+ /**
4611
+ * Inject the WebMCP styles into the document head.
4612
+ * This is called automatically when registering the web component.
4613
+ */
4614
+ function injectStyles() {
4615
+ if (typeof document === "undefined") return;
4616
+ const styleId = "webmcp-agent-styles";
4617
+ if (document.getElementById(styleId)) return;
4618
+ const style = document.createElement("style");
4619
+ style.id = styleId;
4620
+ style.textContent = WEBMCP_STYLES;
4621
+ document.head.appendChild(style);
4622
+ }
4623
+
4624
+ //#endregion
4625
+ //#region src/web-component.tsx
4626
+ /**
4627
+ * WebMCP Agent Web Component
4628
+ *
4629
+ * A custom element wrapper for the EmbeddedAgent React component.
4630
+ * Uses @r2wc/react-to-web-component to convert React to a native web component.
4631
+ *
4632
+ * @example Usage as a custom element (standalone - styles auto-injected)
4633
+ * ```html
4634
+ * <script src="@mcp-b/embedded-agent/web-component/standalone"><\/script>
4635
+ * <webmcp-agent
4636
+ * app-id="your-app-id"
4637
+ * api-base="https://your-worker.workers.dev"
4638
+ * ></webmcp-agent>
4639
+ * ```
4640
+ *
4641
+ * @example React usage (import the component directly)
4642
+ * ```tsx
4643
+ * import { EmbeddedAgent } from '@mcp-b/embedded-agent'
4644
+ * import '@mcp-b/embedded-agent/styles'
4645
+ *
4646
+ * function App() {
4647
+ * return (
4648
+ * <EmbeddedAgent
4649
+ * appId="your-app-id"
4650
+ * apiBase="https://your-worker.workers.dev"
4651
+ * />
4652
+ * )
4653
+ * }
4654
+ * ```
4655
+ */
4656
+ /**
4657
+ * EmbeddedAgent React Component
4658
+ *
4659
+ * A fully self-contained chat widget with MCP tool support and optional voice mode.
4660
+ * Can be used as a React component or converted to a web component.
4661
+ */
4662
+ const EmbeddedAgent = (t0) => {
4663
+ const $ = c(11);
4664
+ const { appId, apiBase, tokenEndpoint, autoConnectLocal: t1, onToolsChange, onVoiceError, onVoiceConnect, onVoiceDisconnect } = t0;
4665
+ const autoConnectLocal = t1 === void 0 ? true : t1;
4666
+ let t2;
4667
+ if ($[0] === Symbol.for("react.memo_cache_sentinel")) {
4668
+ t2 = { sendAutomaticallyWhen: _temp };
4669
+ $[0] = t2;
4670
+ } else t2 = $[0];
4671
+ const runtime = useChatRuntime(t2);
4672
+ const resolvedTokenEndpoint = tokenEndpoint || (apiBase ? `${apiBase}/api/realtime/session` : void 0);
4673
+ if (appId && typeof window !== "undefined") console.debug("[WebMCP] Initialized with app_id:", appId);
4674
+ let t3;
4675
+ if ($[1] !== onVoiceConnect || $[2] !== onVoiceDisconnect || $[3] !== onVoiceError || $[4] !== resolvedTokenEndpoint || $[5] !== runtime) {
4676
+ t3 = resolvedTokenEndpoint ? /* @__PURE__ */ jsx(VoiceModeProvider, {
4677
+ tokenEndpoint: resolvedTokenEndpoint,
4678
+ onError: onVoiceError,
4679
+ onConnect: onVoiceConnect,
4680
+ onDisconnect: onVoiceDisconnect,
4681
+ children: /* @__PURE__ */ jsxs(AssistantRuntimeProvider, {
4682
+ runtime,
4683
+ children: [/* @__PURE__ */ jsx(MCPToolRegistry, {}), /* @__PURE__ */ jsx(AssistantModal, {})]
4684
+ })
4685
+ }) : /* @__PURE__ */ jsxs(AssistantRuntimeProvider, {
4686
+ runtime,
4687
+ children: [/* @__PURE__ */ jsx(MCPToolRegistry, {}), /* @__PURE__ */ jsx(AssistantModal, {})]
4688
+ });
4689
+ $[1] = onVoiceConnect;
4690
+ $[2] = onVoiceDisconnect;
4691
+ $[3] = onVoiceError;
4692
+ $[4] = resolvedTokenEndpoint;
4693
+ $[5] = runtime;
4694
+ $[6] = t3;
4695
+ } else t3 = $[6];
4696
+ let t4;
4697
+ if ($[7] !== autoConnectLocal || $[8] !== onToolsChange || $[9] !== t3) {
4698
+ t4 = /* @__PURE__ */ jsx(MCPToolsProvider, {
4699
+ autoConnectLocal,
4700
+ onToolsChange,
4701
+ children: t3
4702
+ });
4703
+ $[7] = autoConnectLocal;
4704
+ $[8] = onToolsChange;
4705
+ $[9] = t3;
4706
+ $[10] = t4;
4707
+ } else t4 = $[10];
4708
+ return t4;
4709
+ };
4710
+ /**
4711
+ * Web Component Definition
4712
+ *
4713
+ * Converts EmbeddedAgent to a custom element that can be used in any HTML page.
4714
+ * Attributes are automatically converted from kebab-case to camelCase props.
4715
+ */
4716
+ const WebMCPAgentElement = r2wc(EmbeddedAgent, { props: {
4717
+ appId: "string",
4718
+ apiBase: "string",
4719
+ tokenEndpoint: "string",
4720
+ autoConnectLocal: "boolean"
4721
+ } });
4722
+ /**
4723
+ * Register the custom element
4724
+ *
4725
+ * Call this function to register the <webmcp-agent> custom element.
4726
+ * This is automatically called when importing the web-component entry point.
4727
+ * Styles are automatically injected into the document head.
4728
+ */
4729
+ function registerWebMCPAgent(tagName = "webmcp-agent") {
4730
+ if (typeof window === "undefined") return;
4731
+ injectStyles();
4732
+ if (!customElements.get(tagName)) customElements.define(tagName, WebMCPAgentElement);
4733
+ }
4734
+ registerWebMCPAgent();
4735
+ function _temp(messages) {
4736
+ return lastAssistantMessageIsCompleteWithToolCalls(messages);
4737
+ }
4738
+
4739
+ //#endregion
4740
+ export { EmbeddedAgent, WebMCPAgentElement, registerWebMCPAgent };
4741
+ //# sourceMappingURL=web-component.js.map