@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.
- package/README.md +29 -0
- package/dist/embed.iife.js +5 -0
- package/dist/index.d.ts +1153 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7030 -0
- package/dist/index.js.map +1 -0
- package/dist/styles/globals.css +2 -0
- package/dist/web-component-standalone.iife.js +6 -0
- package/dist/web-component.d.ts +56 -0
- package/dist/web-component.d.ts.map +1 -0
- package/dist/web-component.js +4741 -0
- package/dist/web-component.js.map +1 -0
- package/package.json +102 -0
|
@@ -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
|