@cadraos/sdk 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2330 @@
1
+ 'use strict';
2
+
3
+ var react = require('react');
4
+ var jsxRuntime = require('react/jsx-runtime');
5
+ var ReactMarkdown = require('react-markdown');
6
+ var remarkGfm = require('remark-gfm');
7
+
8
+ function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
9
+
10
+ var ReactMarkdown__default = /*#__PURE__*/_interopDefault(ReactMarkdown);
11
+ var remarkGfm__default = /*#__PURE__*/_interopDefault(remarkGfm);
12
+
13
+ // src/chat/adapters/default-adapter.ts
14
+ function createDefaultAdapter(config) {
15
+ const fetchFn = config.fetch ?? fetch;
16
+ const headers = () => {
17
+ const h = {
18
+ "Content-Type": "application/json"
19
+ };
20
+ if (config.apiKey) {
21
+ h["Authorization"] = `Bearer ${config.apiKey}`;
22
+ }
23
+ if (config.orgId) {
24
+ h["X-Org-Id"] = String(config.orgId);
25
+ }
26
+ return h;
27
+ };
28
+ async function request(method, path, body) {
29
+ const url = `${config.baseUrl}${path}`;
30
+ const response = await fetchFn(url, {
31
+ method,
32
+ headers: headers(),
33
+ body: body ? JSON.stringify(body) : void 0
34
+ });
35
+ if (!response.ok) {
36
+ const errorText = await response.text();
37
+ let errorMessage = `HTTP ${response.status}: ${response.statusText}`;
38
+ try {
39
+ const errorData = JSON.parse(errorText);
40
+ if (errorData.message) {
41
+ errorMessage = errorData.message;
42
+ }
43
+ } catch {
44
+ if (errorText) {
45
+ errorMessage = errorText;
46
+ }
47
+ }
48
+ throw new Error(errorMessage);
49
+ }
50
+ const text = await response.text();
51
+ if (!text) {
52
+ return void 0;
53
+ }
54
+ return JSON.parse(text);
55
+ }
56
+ return {
57
+ // -------------------------------------------------------------------------
58
+ // Execution Methods
59
+ // -------------------------------------------------------------------------
60
+ async startExecution(input) {
61
+ return request("POST", `/agents/${input.agentId}/execute`, {
62
+ sessionId: input.sessionId,
63
+ input: input.content,
64
+ attachmentUuids: input.attachmentUuids
65
+ });
66
+ },
67
+ async sendMessage(input) {
68
+ return request("POST", `/sessions/${input.sessionId}/messages`, {
69
+ content: input.content,
70
+ attachmentUuids: input.attachmentUuids
71
+ });
72
+ },
73
+ async cancelExecution(uuid) {
74
+ await request("POST", `/executions/${uuid}/cancel`);
75
+ },
76
+ async getExecution(uuid) {
77
+ return request("GET", `/executions/${uuid}`);
78
+ },
79
+ // -------------------------------------------------------------------------
80
+ // Attachment Methods
81
+ // -------------------------------------------------------------------------
82
+ async getUploadUrl(input) {
83
+ return request("POST", `/attachments/upload-url`, {
84
+ sessionId: input.sessionId,
85
+ filename: input.filename,
86
+ mimeType: input.mimeType,
87
+ size: input.size
88
+ });
89
+ },
90
+ async confirmUpload(uuid) {
91
+ await request("POST", `/attachments/${uuid}/confirm`);
92
+ },
93
+ async getDownloadUrl(uuid) {
94
+ const result = await request("GET", `/attachments/${uuid}/download-url`);
95
+ return result.url;
96
+ },
97
+ // -------------------------------------------------------------------------
98
+ // Artifact Methods
99
+ // -------------------------------------------------------------------------
100
+ async getSessionArtifacts(sessionId) {
101
+ const result = await request("GET", `/sessions/${sessionId}/artifacts`);
102
+ return result.data ?? [];
103
+ },
104
+ // -------------------------------------------------------------------------
105
+ // Session History Methods
106
+ // -------------------------------------------------------------------------
107
+ async getSessionHistory(sessionId) {
108
+ return request("GET", `/sessions/${sessionId}`);
109
+ },
110
+ // -------------------------------------------------------------------------
111
+ // SSE Stream URL
112
+ // -------------------------------------------------------------------------
113
+ getStreamUrl(executionId) {
114
+ const url = new URL(`${config.baseUrl}/executions/${executionId}/stream`);
115
+ if (config.apiKey) {
116
+ url.searchParams.set("apiKey", config.apiKey);
117
+ }
118
+ if (config.orgId) {
119
+ url.searchParams.set("orgId", String(config.orgId));
120
+ }
121
+ return url.toString();
122
+ }
123
+ };
124
+ }
125
+ var ChatConfigContext = react.createContext(null);
126
+ function ChatConfigProvider({ config, children }) {
127
+ const adapter = react.useMemo(
128
+ () => createDefaultAdapter(config),
129
+ // eslint-disable-next-line react-hooks/exhaustive-deps
130
+ [config.baseUrl, config.apiKey, config.orgId]
131
+ );
132
+ const value = react.useMemo(() => ({ adapter }), [adapter]);
133
+ return /* @__PURE__ */ jsxRuntime.jsx(ChatConfigContext.Provider, { value, children });
134
+ }
135
+ function useChatConfig() {
136
+ const context = react.useContext(ChatConfigContext);
137
+ if (!context) {
138
+ throw new Error(
139
+ "useChatConfig must be used within ChatConfigProvider or provide adapter prop to AgentChat"
140
+ );
141
+ }
142
+ return context;
143
+ }
144
+ function useChatConfigOptional() {
145
+ return react.useContext(ChatConfigContext);
146
+ }
147
+ var STREAM_CONFIG = {
148
+ /** Maximum reconnection attempts before falling back to polling */
149
+ maxReconnectAttempts: 5,
150
+ /** Base reconnection delay in milliseconds (uses exponential backoff) */
151
+ baseReconnectDelayMs: 1e3,
152
+ /** Maximum reconnection delay in milliseconds */
153
+ maxReconnectDelayMs: 1e4,
154
+ /** Client-side activity timeout - should be 3x keepalive interval */
155
+ clientActivityTimeoutMs: 45e3
156
+ };
157
+ function useExecutionStream(options) {
158
+ const {
159
+ executionId,
160
+ getStreamUrl,
161
+ enabled = true,
162
+ onEvent,
163
+ onLog,
164
+ onToolCall,
165
+ onToolResult,
166
+ onProgress,
167
+ onComplete,
168
+ onError,
169
+ onClarification,
170
+ onConnectionChange
171
+ } = options;
172
+ const [isConnected, setIsConnected] = react.useState(false);
173
+ const [isUsingFallback, setIsUsingFallback] = react.useState(false);
174
+ const [connectionError, setConnectionError] = react.useState(null);
175
+ const eventSourceRef = react.useRef(null);
176
+ const reconnectTimeoutRef = react.useRef(null);
177
+ const activityTimeoutRef = react.useRef(null);
178
+ const reconnectAttemptsRef = react.useRef(0);
179
+ const seenEventIdsRef = react.useRef(/* @__PURE__ */ new Set());
180
+ const isTerminatedRef = react.useRef(false);
181
+ const cleanup = react.useCallback(() => {
182
+ if (reconnectTimeoutRef.current) {
183
+ clearTimeout(reconnectTimeoutRef.current);
184
+ reconnectTimeoutRef.current = null;
185
+ }
186
+ if (activityTimeoutRef.current) {
187
+ clearTimeout(activityTimeoutRef.current);
188
+ activityTimeoutRef.current = null;
189
+ }
190
+ if (eventSourceRef.current) {
191
+ eventSourceRef.current.close();
192
+ eventSourceRef.current = null;
193
+ }
194
+ seenEventIdsRef.current.clear();
195
+ setIsConnected(false);
196
+ }, []);
197
+ const resetActivityTimeout = react.useCallback(() => {
198
+ if (activityTimeoutRef.current) {
199
+ clearTimeout(activityTimeoutRef.current);
200
+ }
201
+ if (isTerminatedRef.current) return;
202
+ activityTimeoutRef.current = setTimeout(() => {
203
+ if (eventSourceRef.current) {
204
+ eventSourceRef.current.close();
205
+ eventSourceRef.current = null;
206
+ setIsConnected(false);
207
+ }
208
+ }, STREAM_CONFIG.clientActivityTimeoutMs);
209
+ }, []);
210
+ const handleEvent = react.useCallback(
211
+ (event) => {
212
+ console.log("[useExecutionStream] Event received:", event.type, event.data);
213
+ try {
214
+ resetActivityTimeout();
215
+ const parsed = JSON.parse(event.data);
216
+ console.log("[useExecutionStream] Parsed event:", parsed.type, parsed);
217
+ if (parsed.id && seenEventIdsRef.current.has(parsed.id)) {
218
+ return;
219
+ }
220
+ if (parsed.id) {
221
+ seenEventIdsRef.current.add(parsed.id);
222
+ if (seenEventIdsRef.current.size > 1e3) {
223
+ const idsArray = Array.from(seenEventIdsRef.current);
224
+ seenEventIdsRef.current = new Set(idsArray.slice(-500));
225
+ }
226
+ }
227
+ onEvent?.(parsed);
228
+ const eventType = parsed.type;
229
+ const data = parsed.data;
230
+ switch (eventType) {
231
+ case "log":
232
+ if (data.log) {
233
+ onLog?.(data.log);
234
+ if (data.log.logType === "tool_call") {
235
+ const toolName = data.log.metadata?.toolName;
236
+ const args = data.log.metadata?.inputs;
237
+ if (toolName) {
238
+ onToolCall?.(toolName, args);
239
+ }
240
+ } else if (data.log.logType === "tool_result") {
241
+ const toolName = data.log.metadata?.toolName;
242
+ const result = data.log.metadata?.output;
243
+ const durationMs = data.log.durationMs ?? 0;
244
+ if (toolName) {
245
+ onToolResult?.(toolName, result, durationMs);
246
+ }
247
+ }
248
+ }
249
+ break;
250
+ case "step":
251
+ onProgress?.({
252
+ iteration: data.iteration,
253
+ tokenUsage: data.tokenUsage,
254
+ cost: data.cost
255
+ });
256
+ break;
257
+ case "tool_call":
258
+ if (data.toolName) {
259
+ onToolCall?.(data.toolName, data.args);
260
+ }
261
+ break;
262
+ case "complete":
263
+ isTerminatedRef.current = true;
264
+ if (activityTimeoutRef.current) {
265
+ clearTimeout(activityTimeoutRef.current);
266
+ activityTimeoutRef.current = null;
267
+ }
268
+ onComplete?.();
269
+ break;
270
+ case "error":
271
+ const errorMsg = data.error || "Unknown error";
272
+ isTerminatedRef.current = true;
273
+ if (activityTimeoutRef.current) {
274
+ clearTimeout(activityTimeoutRef.current);
275
+ activityTimeoutRef.current = null;
276
+ }
277
+ onError?.(errorMsg);
278
+ break;
279
+ case "timeout":
280
+ if (data.retryable && reconnectAttemptsRef.current < STREAM_CONFIG.maxReconnectAttempts) {
281
+ reconnectAttemptsRef.current++;
282
+ const delay = Math.min(
283
+ STREAM_CONFIG.baseReconnectDelayMs * Math.pow(2, reconnectAttemptsRef.current),
284
+ STREAM_CONFIG.maxReconnectDelayMs
285
+ );
286
+ setConnectionError("Stream timeout, reconnecting...");
287
+ reconnectTimeoutRef.current = setTimeout(() => {
288
+ setConnectionError(null);
289
+ }, delay);
290
+ } else {
291
+ setConnectionError("Stream timeout, using polling");
292
+ setIsUsingFallback(true);
293
+ onConnectionChange?.(false, true);
294
+ onError?.("Stream connection timed out. Updates will continue via polling.");
295
+ }
296
+ break;
297
+ case "info":
298
+ if (data.fallback === "polling") {
299
+ setIsUsingFallback(true);
300
+ onConnectionChange?.(true, true);
301
+ }
302
+ break;
303
+ case "connected":
304
+ case "subscribed":
305
+ setIsConnected(true);
306
+ setIsUsingFallback(data.redisAvailable === false);
307
+ onConnectionChange?.(true, data.redisAvailable === false);
308
+ break;
309
+ case "clarification":
310
+ if (data.question) {
311
+ onClarification?.({
312
+ question: data.question,
313
+ reason: data.reason,
314
+ suggestedOptions: data.suggestedOptions
315
+ });
316
+ }
317
+ break;
318
+ }
319
+ } catch {
320
+ }
321
+ },
322
+ [
323
+ onEvent,
324
+ onLog,
325
+ onToolCall,
326
+ onToolResult,
327
+ onProgress,
328
+ onComplete,
329
+ onError,
330
+ onClarification,
331
+ onConnectionChange,
332
+ resetActivityTimeout
333
+ ]
334
+ );
335
+ const connect = react.useCallback(() => {
336
+ console.log("[useExecutionStream] connect called", { executionId, enabled });
337
+ if (!executionId || !enabled) {
338
+ console.log("[useExecutionStream] Skipping - executionId or enabled is falsy");
339
+ return;
340
+ }
341
+ cleanup();
342
+ isTerminatedRef.current = false;
343
+ const url = getStreamUrl(executionId);
344
+ console.log("[useExecutionStream] Connecting to:", url);
345
+ try {
346
+ const eventSource = new EventSource(url, {
347
+ withCredentials: true
348
+ });
349
+ console.log("[useExecutionStream] EventSource created");
350
+ eventSource.onopen = () => {
351
+ console.log("[useExecutionStream] EventSource onopen");
352
+ reconnectAttemptsRef.current = 0;
353
+ setConnectionError(null);
354
+ resetActivityTimeout();
355
+ };
356
+ eventSource.onerror = (err) => {
357
+ console.log("[useExecutionStream] EventSource onerror", { readyState: eventSource.readyState, err });
358
+ if (eventSource.readyState === EventSource.CLOSED) {
359
+ setIsConnected(false);
360
+ if (reconnectAttemptsRef.current < STREAM_CONFIG.maxReconnectAttempts) {
361
+ reconnectAttemptsRef.current++;
362
+ const delay = Math.min(
363
+ STREAM_CONFIG.baseReconnectDelayMs * Math.pow(2, reconnectAttemptsRef.current),
364
+ STREAM_CONFIG.maxReconnectDelayMs
365
+ );
366
+ reconnectTimeoutRef.current = setTimeout(() => {
367
+ connect();
368
+ }, delay);
369
+ } else {
370
+ setConnectionError("Connection failed, using polling");
371
+ setIsUsingFallback(true);
372
+ onConnectionChange?.(false, true);
373
+ }
374
+ }
375
+ };
376
+ const eventTypes = [
377
+ "connected",
378
+ "subscribed",
379
+ "log",
380
+ "step",
381
+ "tool_call",
382
+ "complete",
383
+ "error",
384
+ "info",
385
+ "timeout",
386
+ "clarification"
387
+ ];
388
+ for (const eventType of eventTypes) {
389
+ eventSource.addEventListener(eventType, handleEvent);
390
+ }
391
+ eventSource.onmessage = handleEvent;
392
+ eventSourceRef.current = eventSource;
393
+ } catch {
394
+ setConnectionError("Failed to connect to stream");
395
+ setIsUsingFallback(true);
396
+ onConnectionChange?.(false, true);
397
+ }
398
+ }, [executionId, enabled, getStreamUrl, cleanup, handleEvent, onConnectionChange, resetActivityTimeout]);
399
+ const disconnect = react.useCallback(() => {
400
+ cleanup();
401
+ }, [cleanup]);
402
+ const reconnect = react.useCallback(() => {
403
+ reconnectAttemptsRef.current = 0;
404
+ isTerminatedRef.current = false;
405
+ setConnectionError(null);
406
+ setIsUsingFallback(false);
407
+ connect();
408
+ }, [connect]);
409
+ react.useEffect(() => {
410
+ console.log("[useExecutionStream] useEffect triggered", { executionId, enabled });
411
+ if (executionId && enabled) {
412
+ console.log("[useExecutionStream] Calling connect()");
413
+ connect();
414
+ }
415
+ return () => {
416
+ cleanup();
417
+ };
418
+ }, [executionId, enabled, connect, cleanup]);
419
+ return {
420
+ isConnected,
421
+ isUsingFallback,
422
+ connectionError,
423
+ disconnect,
424
+ reconnect
425
+ };
426
+ }
427
+
428
+ // src/chat/hooks/useAgentChat.ts
429
+ function generateId() {
430
+ return `msg-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
431
+ }
432
+ function historyToMessage(historyMsg) {
433
+ return {
434
+ id: historyMsg.uuid,
435
+ role: historyMsg.role,
436
+ content: historyMsg.content,
437
+ timestamp: new Date(historyMsg.timestamp),
438
+ attachments: historyMsg.attachments?.map((a) => ({
439
+ uuid: a.uuid,
440
+ filename: a.filename,
441
+ mimeType: a.mimeType,
442
+ size: a.size,
443
+ category: a.category,
444
+ previewUrl: a.previewUrl,
445
+ thumbnailUrl: a.thumbnailUrl,
446
+ status: "ready"
447
+ })),
448
+ toolCalls: historyMsg.toolCalls?.map((tc) => ({
449
+ id: tc.id,
450
+ name: tc.name,
451
+ args: tc.args,
452
+ result: tc.result,
453
+ status: tc.status,
454
+ durationMs: tc.durationMs
455
+ }))
456
+ };
457
+ }
458
+ function useAgentChat(options) {
459
+ const {
460
+ agentId,
461
+ sessionId: initialSessionId,
462
+ adapter: propsAdapter,
463
+ initialMessages = [],
464
+ onMessage,
465
+ onError,
466
+ onSessionCreated,
467
+ onSessionStart,
468
+ // Deprecated, but still supported
469
+ onToolCall,
470
+ onClarification
471
+ } = options;
472
+ const contextConfig = useChatConfigOptional();
473
+ const adapter = propsAdapter ?? contextConfig?.adapter;
474
+ if (!adapter) {
475
+ throw new Error(
476
+ "No adapter provided. Use ChatConfigProvider or pass adapter prop to AgentChat."
477
+ );
478
+ }
479
+ const [messages, setMessages] = react.useState(initialMessages);
480
+ const [isLoading, setIsLoading] = react.useState(false);
481
+ const [isLoadingHistory, setIsLoadingHistory] = react.useState(false);
482
+ const [error, setError] = react.useState(null);
483
+ const [currentSessionId, setCurrentSessionId] = react.useState(initialSessionId ?? null);
484
+ const [currentExecutionId, setCurrentExecutionId] = react.useState(null);
485
+ const [clarification, setClarification] = react.useState(null);
486
+ const hasLoadedInitialSession = react.useRef(false);
487
+ const streamingContentRef = react.useRef("");
488
+ const streamingMessageIdRef = react.useRef(null);
489
+ const pendingToolCallsRef = react.useRef(/* @__PURE__ */ new Map());
490
+ const lastMessageContentRef = react.useRef("");
491
+ const updateStreamingMessage = react.useCallback((content) => {
492
+ if (!streamingMessageIdRef.current) return;
493
+ setMessages(
494
+ (prev) => prev.map(
495
+ (msg) => msg.id === streamingMessageIdRef.current ? { ...msg, content, isStreaming: true } : msg
496
+ )
497
+ );
498
+ }, []);
499
+ const updateToolCall = react.useCallback((toolCall) => {
500
+ if (!streamingMessageIdRef.current) return;
501
+ setMessages(
502
+ (prev) => prev.map((msg) => {
503
+ if (msg.id !== streamingMessageIdRef.current) return msg;
504
+ const existingIndex = msg.toolCalls?.findIndex((tc) => tc.id === toolCall.id) ?? -1;
505
+ if (existingIndex >= 0) {
506
+ const newToolCalls = [...msg.toolCalls ?? []];
507
+ newToolCalls[existingIndex] = toolCall;
508
+ return { ...msg, toolCalls: newToolCalls };
509
+ } else {
510
+ return {
511
+ ...msg,
512
+ toolCalls: [...msg.toolCalls ?? [], toolCall]
513
+ };
514
+ }
515
+ })
516
+ );
517
+ }, []);
518
+ const finalizeStreamingMessage = react.useCallback(() => {
519
+ if (!streamingMessageIdRef.current) return;
520
+ setMessages(
521
+ (prev) => prev.map(
522
+ (msg) => msg.id === streamingMessageIdRef.current ? { ...msg, isStreaming: false } : msg
523
+ )
524
+ );
525
+ streamingMessageIdRef.current = null;
526
+ streamingContentRef.current = "";
527
+ pendingToolCallsRef.current.clear();
528
+ }, []);
529
+ const handleStreamLog = react.useCallback(
530
+ (log) => {
531
+ console.log("[useAgentChat] handleStreamLog:", log.logType, log.metadata);
532
+ switch (log.logType) {
533
+ // Primary handlers for ai-saas-api worker log types
534
+ case "llm_response": {
535
+ const llmText = log.metadata?.text || log.message || "";
536
+ if (llmText) {
537
+ streamingContentRef.current = llmText;
538
+ updateStreamingMessage(llmText);
539
+ }
540
+ break;
541
+ }
542
+ case "message": {
543
+ const role = log.metadata?.role;
544
+ const content = log.metadata?.content;
545
+ if (role === "assistant" && content) {
546
+ streamingContentRef.current = content;
547
+ updateStreamingMessage(content);
548
+ }
549
+ break;
550
+ }
551
+ case "info":
552
+ case "system":
553
+ console.log("[useAgentChat] Status:", log.logType, log.message);
554
+ break;
555
+ // Legacy/fallback handlers
556
+ case "response_text":
557
+ case "text_chunk": {
558
+ const text = log.metadata?.text || log.message || "";
559
+ streamingContentRef.current += text;
560
+ updateStreamingMessage(streamingContentRef.current);
561
+ break;
562
+ }
563
+ case "tool_call": {
564
+ const toolName = log.metadata?.toolName;
565
+ const toolCallId = log.metadata?.toolCallId || `tool-${Date.now()}`;
566
+ const args = log.metadata?.inputs;
567
+ const newToolCall = {
568
+ id: toolCallId,
569
+ name: toolName,
570
+ args,
571
+ status: "running"
572
+ };
573
+ pendingToolCallsRef.current.set(toolCallId, newToolCall);
574
+ updateToolCall(newToolCall);
575
+ onToolCall?.(toolName, args);
576
+ break;
577
+ }
578
+ case "tool_result": {
579
+ const resultToolName = log.metadata?.toolName;
580
+ const resultToolCallId = log.metadata?.toolCallId;
581
+ const result = log.metadata?.output;
582
+ const durationMs = log.durationMs;
583
+ let matchedToolCall = resultToolCallId ? pendingToolCallsRef.current.get(resultToolCallId) : void 0;
584
+ if (!matchedToolCall) {
585
+ for (const [, tc] of pendingToolCallsRef.current) {
586
+ if (tc.name === resultToolName && tc.status === "running") {
587
+ matchedToolCall = tc;
588
+ break;
589
+ }
590
+ }
591
+ }
592
+ if (matchedToolCall) {
593
+ const completedToolCall = {
594
+ ...matchedToolCall,
595
+ result,
596
+ status: "completed",
597
+ durationMs
598
+ };
599
+ updateToolCall(completedToolCall);
600
+ pendingToolCallsRef.current.delete(matchedToolCall.id);
601
+ }
602
+ break;
603
+ }
604
+ case "final_response": {
605
+ const finalText = log.metadata?.response || log.message || "";
606
+ if (finalText && finalText !== streamingContentRef.current) {
607
+ streamingContentRef.current = finalText;
608
+ updateStreamingMessage(finalText);
609
+ }
610
+ break;
611
+ }
612
+ default:
613
+ console.log("[useAgentChat] Unknown log type:", log.logType, log);
614
+ }
615
+ },
616
+ [updateStreamingMessage, updateToolCall, onToolCall]
617
+ );
618
+ const handleClarification = react.useCallback(
619
+ (data) => {
620
+ setClarification(data);
621
+ onClarification?.(data);
622
+ },
623
+ [onClarification]
624
+ );
625
+ const handleComplete = react.useCallback(() => {
626
+ console.log("[useAgentChat] handleComplete called");
627
+ setIsLoading(false);
628
+ finalizeStreamingMessage();
629
+ setCurrentExecutionId(null);
630
+ }, [finalizeStreamingMessage]);
631
+ const handleError = react.useCallback(
632
+ (errorMsg) => {
633
+ console.log("[useAgentChat] handleError called:", errorMsg);
634
+ const chatError = {
635
+ code: "EXECUTION_ERROR",
636
+ message: errorMsg,
637
+ retryable: true
638
+ };
639
+ setError(chatError);
640
+ setIsLoading(false);
641
+ finalizeStreamingMessage();
642
+ setCurrentExecutionId(null);
643
+ onError?.(chatError);
644
+ },
645
+ [finalizeStreamingMessage, onError]
646
+ );
647
+ const { isConnected, disconnect } = useExecutionStream({
648
+ executionId: currentExecutionId ?? void 0,
649
+ getStreamUrl: adapter.getStreamUrl,
650
+ enabled: !!currentExecutionId,
651
+ onLog: handleStreamLog,
652
+ onClarification: handleClarification,
653
+ onComplete: handleComplete,
654
+ onError: handleError
655
+ });
656
+ const sendMessage = react.useCallback(
657
+ async (content) => {
658
+ if (!content.trim()) return;
659
+ lastMessageContentRef.current = content;
660
+ setIsLoading(true);
661
+ setError(null);
662
+ setClarification(null);
663
+ const userMessage = {
664
+ id: generateId(),
665
+ role: "user",
666
+ content: content.trim(),
667
+ timestamp: /* @__PURE__ */ new Date()
668
+ };
669
+ setMessages((prev) => [...prev, userMessage]);
670
+ onMessage?.(userMessage);
671
+ const assistantMessageId = generateId();
672
+ const assistantMessage = {
673
+ id: assistantMessageId,
674
+ role: "assistant",
675
+ content: "",
676
+ timestamp: /* @__PURE__ */ new Date(),
677
+ isStreaming: true,
678
+ toolCalls: []
679
+ };
680
+ setMessages((prev) => [...prev, assistantMessage]);
681
+ streamingMessageIdRef.current = assistantMessageId;
682
+ streamingContentRef.current = "";
683
+ try {
684
+ console.log("[useAgentChat] Starting execution...", { agentId, sessionId: currentSessionId });
685
+ const result = await adapter.startExecution({
686
+ agentId,
687
+ sessionId: currentSessionId ?? void 0,
688
+ content: content.trim()
689
+ });
690
+ console.log("[useAgentChat] Execution started:", result);
691
+ if (!currentSessionId && result.sessionId) {
692
+ setCurrentSessionId(result.sessionId);
693
+ onSessionCreated?.(result.sessionId);
694
+ onSessionStart?.(result.sessionId);
695
+ }
696
+ console.log("[useAgentChat] Setting executionId:", result.executionId);
697
+ setCurrentExecutionId(result.executionId);
698
+ } catch (err) {
699
+ console.error("[useAgentChat] Error starting execution:", err);
700
+ const errorMessage = err instanceof Error ? err.message : "Failed to send message";
701
+ handleError(errorMessage);
702
+ }
703
+ },
704
+ [
705
+ agentId,
706
+ currentSessionId,
707
+ adapter,
708
+ onMessage,
709
+ onSessionCreated,
710
+ onSessionStart,
711
+ handleError
712
+ ]
713
+ );
714
+ const respondToClarification = react.useCallback(
715
+ async (response) => {
716
+ if (!clarification) return;
717
+ setClarification(null);
718
+ await sendMessage(response);
719
+ },
720
+ [clarification, sendMessage]
721
+ );
722
+ const cancel = react.useCallback(async () => {
723
+ if (currentExecutionId) {
724
+ try {
725
+ await adapter.cancelExecution(currentExecutionId);
726
+ } catch {
727
+ }
728
+ disconnect();
729
+ setIsLoading(false);
730
+ finalizeStreamingMessage();
731
+ setCurrentExecutionId(null);
732
+ }
733
+ }, [currentExecutionId, adapter, disconnect, finalizeStreamingMessage]);
734
+ const retry = react.useCallback(() => {
735
+ if (lastMessageContentRef.current && error) {
736
+ setError(null);
737
+ sendMessage(lastMessageContentRef.current);
738
+ }
739
+ }, [error, sendMessage]);
740
+ const clearError = react.useCallback(() => {
741
+ setError(null);
742
+ }, []);
743
+ const clearMessages = react.useCallback(() => {
744
+ setMessages([]);
745
+ setCurrentSessionId(null);
746
+ hasLoadedInitialSession.current = false;
747
+ }, []);
748
+ const loadSession = react.useCallback(
749
+ async (sessionId) => {
750
+ if (!adapter.getSessionHistory) {
751
+ const loadError = {
752
+ code: "UNSUPPORTED_OPERATION",
753
+ message: "Session history loading is not supported by this adapter",
754
+ retryable: false
755
+ };
756
+ setError(loadError);
757
+ onError?.(loadError);
758
+ return;
759
+ }
760
+ setIsLoadingHistory(true);
761
+ setError(null);
762
+ try {
763
+ const history = await adapter.getSessionHistory(sessionId);
764
+ const loadedMessages = history.messages.map(historyToMessage);
765
+ setMessages(loadedMessages);
766
+ setCurrentSessionId(sessionId);
767
+ } catch (err) {
768
+ const errorMessage = err instanceof Error ? err.message : "Failed to load session history";
769
+ const loadError = {
770
+ code: "LOAD_HISTORY_ERROR",
771
+ message: errorMessage,
772
+ retryable: true
773
+ };
774
+ setError(loadError);
775
+ onError?.(loadError);
776
+ } finally {
777
+ setIsLoadingHistory(false);
778
+ }
779
+ },
780
+ [adapter, onError]
781
+ );
782
+ react.useEffect(() => {
783
+ if (initialSessionId && !hasLoadedInitialSession.current) {
784
+ hasLoadedInitialSession.current = true;
785
+ loadSession(initialSessionId);
786
+ }
787
+ }, [initialSessionId, loadSession]);
788
+ const isStreaming = react.useMemo(
789
+ () => !!currentExecutionId && isConnected,
790
+ [currentExecutionId, isConnected]
791
+ );
792
+ return {
793
+ messages,
794
+ isLoading,
795
+ isStreaming,
796
+ isLoadingHistory,
797
+ error,
798
+ sessionId: currentSessionId,
799
+ clarification,
800
+ sendMessage,
801
+ respondToClarification,
802
+ cancel,
803
+ retry,
804
+ clearError,
805
+ clearMessages,
806
+ loadSession
807
+ };
808
+ }
809
+ function cn(...classes) {
810
+ return classes.filter(Boolean).join(" ");
811
+ }
812
+ function SendIcon({ className, ...props }) {
813
+ return /* @__PURE__ */ jsxRuntime.jsx(
814
+ "svg",
815
+ {
816
+ className,
817
+ viewBox: "0 0 24 24",
818
+ fill: "none",
819
+ stroke: "currentColor",
820
+ strokeWidth: 2,
821
+ strokeLinecap: "round",
822
+ strokeLinejoin: "round",
823
+ ...props,
824
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M22 2L11 13M22 2l-7 20-4-9-9-4 20-7z" })
825
+ }
826
+ );
827
+ }
828
+ function MessageCircleIcon({ className, ...props }) {
829
+ return /* @__PURE__ */ jsxRuntime.jsx(
830
+ "svg",
831
+ {
832
+ className,
833
+ viewBox: "0 0 24 24",
834
+ fill: "none",
835
+ stroke: "currentColor",
836
+ strokeWidth: 2,
837
+ strokeLinecap: "round",
838
+ strokeLinejoin: "round",
839
+ ...props,
840
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 11.5a8.38 8.38 0 0 1-.9 3.8 8.5 8.5 0 0 1-7.6 4.7 8.38 8.38 0 0 1-3.8-.9L3 21l1.9-5.7a8.38 8.38 0 0 1-.9-3.8 8.5 8.5 0 0 1 4.7-7.6 8.38 8.38 0 0 1 3.8-.9h.5a8.48 8.48 0 0 1 8 8v.5z" })
841
+ }
842
+ );
843
+ }
844
+ function PaperclipIcon({ className, ...props }) {
845
+ return /* @__PURE__ */ jsxRuntime.jsx(
846
+ "svg",
847
+ {
848
+ className,
849
+ viewBox: "0 0 24 24",
850
+ fill: "none",
851
+ stroke: "currentColor",
852
+ strokeWidth: 2,
853
+ strokeLinecap: "round",
854
+ strokeLinejoin: "round",
855
+ ...props,
856
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" })
857
+ }
858
+ );
859
+ }
860
+ function XIcon({ className, ...props }) {
861
+ return /* @__PURE__ */ jsxRuntime.jsx(
862
+ "svg",
863
+ {
864
+ className,
865
+ viewBox: "0 0 24 24",
866
+ fill: "none",
867
+ stroke: "currentColor",
868
+ strokeWidth: 2,
869
+ strokeLinecap: "round",
870
+ strokeLinejoin: "round",
871
+ ...props,
872
+ children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 6L6 18M6 6l12 12" })
873
+ }
874
+ );
875
+ }
876
+ function CheckIcon({ className, ...props }) {
877
+ return /* @__PURE__ */ jsxRuntime.jsx(
878
+ "svg",
879
+ {
880
+ className,
881
+ viewBox: "0 0 24 24",
882
+ fill: "none",
883
+ stroke: "currentColor",
884
+ strokeWidth: 2,
885
+ strokeLinecap: "round",
886
+ strokeLinejoin: "round",
887
+ ...props,
888
+ children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20 6 9 17 4 12" })
889
+ }
890
+ );
891
+ }
892
+ function CheckCircleIcon({ className, ...props }) {
893
+ return /* @__PURE__ */ jsxRuntime.jsxs(
894
+ "svg",
895
+ {
896
+ className,
897
+ viewBox: "0 0 24 24",
898
+ fill: "none",
899
+ stroke: "currentColor",
900
+ strokeWidth: 2,
901
+ strokeLinecap: "round",
902
+ strokeLinejoin: "round",
903
+ ...props,
904
+ children: [
905
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M22 11.08V12a10 10 0 1 1-5.93-9.14" }),
906
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "22 4 12 14.01 9 11.01" })
907
+ ]
908
+ }
909
+ );
910
+ }
911
+ function CopyIcon({ className, ...props }) {
912
+ return /* @__PURE__ */ jsxRuntime.jsxs(
913
+ "svg",
914
+ {
915
+ className,
916
+ viewBox: "0 0 24 24",
917
+ fill: "none",
918
+ stroke: "currentColor",
919
+ strokeWidth: 2,
920
+ strokeLinecap: "round",
921
+ strokeLinejoin: "round",
922
+ ...props,
923
+ children: [
924
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "9", y: "9", width: "13", height: "13", rx: "2", ry: "2" }),
925
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1" })
926
+ ]
927
+ }
928
+ );
929
+ }
930
+ function ChevronDownIcon({ className, ...props }) {
931
+ return /* @__PURE__ */ jsxRuntime.jsx(
932
+ "svg",
933
+ {
934
+ className,
935
+ viewBox: "0 0 24 24",
936
+ fill: "none",
937
+ stroke: "currentColor",
938
+ strokeWidth: 2,
939
+ strokeLinecap: "round",
940
+ strokeLinejoin: "round",
941
+ ...props,
942
+ children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "6 9 12 15 18 9" })
943
+ }
944
+ );
945
+ }
946
+ function ChevronRightIcon({ className, ...props }) {
947
+ return /* @__PURE__ */ jsxRuntime.jsx(
948
+ "svg",
949
+ {
950
+ className,
951
+ viewBox: "0 0 24 24",
952
+ fill: "none",
953
+ stroke: "currentColor",
954
+ strokeWidth: 2,
955
+ strokeLinecap: "round",
956
+ strokeLinejoin: "round",
957
+ ...props,
958
+ children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "9 18 15 12 9 6" })
959
+ }
960
+ );
961
+ }
962
+ function ChevronLeftIcon({ className, ...props }) {
963
+ return /* @__PURE__ */ jsxRuntime.jsx(
964
+ "svg",
965
+ {
966
+ className,
967
+ viewBox: "0 0 24 24",
968
+ fill: "none",
969
+ stroke: "currentColor",
970
+ strokeWidth: 2,
971
+ strokeLinecap: "round",
972
+ strokeLinejoin: "round",
973
+ ...props,
974
+ children: /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "15 18 9 12 15 6" })
975
+ }
976
+ );
977
+ }
978
+ function LoadingSpinner({ className, ...props }) {
979
+ return /* @__PURE__ */ jsxRuntime.jsxs(
980
+ "svg",
981
+ {
982
+ className: cn("animate-spin", className),
983
+ viewBox: "0 0 24 24",
984
+ fill: "none",
985
+ ...props,
986
+ children: [
987
+ /* @__PURE__ */ jsxRuntime.jsx(
988
+ "circle",
989
+ {
990
+ cx: "12",
991
+ cy: "12",
992
+ r: "10",
993
+ stroke: "currentColor",
994
+ strokeWidth: "4",
995
+ strokeOpacity: "0.25"
996
+ }
997
+ ),
998
+ /* @__PURE__ */ jsxRuntime.jsx(
999
+ "path",
1000
+ {
1001
+ d: "M4 12a8 8 0 0 1 8-8",
1002
+ stroke: "currentColor",
1003
+ strokeWidth: "4",
1004
+ strokeLinecap: "round"
1005
+ }
1006
+ )
1007
+ ]
1008
+ }
1009
+ );
1010
+ }
1011
+ function AlertCircleIcon({ className, ...props }) {
1012
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1013
+ "svg",
1014
+ {
1015
+ className,
1016
+ viewBox: "0 0 24 24",
1017
+ fill: "none",
1018
+ stroke: "currentColor",
1019
+ strokeWidth: 2,
1020
+ strokeLinecap: "round",
1021
+ strokeLinejoin: "round",
1022
+ ...props,
1023
+ children: [
1024
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
1025
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
1026
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })
1027
+ ]
1028
+ }
1029
+ );
1030
+ }
1031
+ function CircleIcon({ className, ...props }) {
1032
+ return /* @__PURE__ */ jsxRuntime.jsx(
1033
+ "svg",
1034
+ {
1035
+ className,
1036
+ viewBox: "0 0 24 24",
1037
+ fill: "none",
1038
+ stroke: "currentColor",
1039
+ strokeWidth: 2,
1040
+ strokeLinecap: "round",
1041
+ strokeLinejoin: "round",
1042
+ ...props,
1043
+ children: /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" })
1044
+ }
1045
+ );
1046
+ }
1047
+ function StopCircleIcon({ className, ...props }) {
1048
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1049
+ "svg",
1050
+ {
1051
+ className,
1052
+ viewBox: "0 0 24 24",
1053
+ fill: "none",
1054
+ stroke: "currentColor",
1055
+ strokeWidth: 2,
1056
+ strokeLinecap: "round",
1057
+ strokeLinejoin: "round",
1058
+ ...props,
1059
+ children: [
1060
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
1061
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "9", y: "9", width: "6", height: "6" })
1062
+ ]
1063
+ }
1064
+ );
1065
+ }
1066
+ function ImageIcon({ className, ...props }) {
1067
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1068
+ "svg",
1069
+ {
1070
+ className,
1071
+ viewBox: "0 0 24 24",
1072
+ fill: "none",
1073
+ stroke: "currentColor",
1074
+ strokeWidth: 2,
1075
+ strokeLinecap: "round",
1076
+ strokeLinejoin: "round",
1077
+ ...props,
1078
+ children: [
1079
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
1080
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "8.5", cy: "8.5", r: "1.5" }),
1081
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "21 15 16 10 5 21" })
1082
+ ]
1083
+ }
1084
+ );
1085
+ }
1086
+ function ImagesIcon({ className, ...props }) {
1087
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1088
+ "svg",
1089
+ {
1090
+ className,
1091
+ viewBox: "0 0 24 24",
1092
+ fill: "none",
1093
+ stroke: "currentColor",
1094
+ strokeWidth: 2,
1095
+ strokeLinecap: "round",
1096
+ strokeLinejoin: "round",
1097
+ ...props,
1098
+ children: [
1099
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 22H4a2 2 0 0 1-2-2V6" }),
1100
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m22 13-1.296-1.296a2.41 2.41 0 0 0-3.408 0L11 18" }),
1101
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "8", r: "2" }),
1102
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "6", y: "2", width: "16", height: "16", rx: "2" })
1103
+ ]
1104
+ }
1105
+ );
1106
+ }
1107
+ function FileIcon({ className, ...props }) {
1108
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1109
+ "svg",
1110
+ {
1111
+ className,
1112
+ viewBox: "0 0 24 24",
1113
+ fill: "none",
1114
+ stroke: "currentColor",
1115
+ strokeWidth: 2,
1116
+ strokeLinecap: "round",
1117
+ strokeLinejoin: "round",
1118
+ ...props,
1119
+ children: [
1120
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
1121
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "14 2 14 8 20 8" })
1122
+ ]
1123
+ }
1124
+ );
1125
+ }
1126
+ function FileTextIcon({ className, ...props }) {
1127
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1128
+ "svg",
1129
+ {
1130
+ className,
1131
+ viewBox: "0 0 24 24",
1132
+ fill: "none",
1133
+ stroke: "currentColor",
1134
+ strokeWidth: 2,
1135
+ strokeLinecap: "round",
1136
+ strokeLinejoin: "round",
1137
+ ...props,
1138
+ children: [
1139
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z" }),
1140
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "14 2 14 8 20 8" }),
1141
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "16", y1: "13", x2: "8", y2: "13" }),
1142
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "16", y1: "17", x2: "8", y2: "17" }),
1143
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "10 9 9 9 8 9" })
1144
+ ]
1145
+ }
1146
+ );
1147
+ }
1148
+ function CodeIcon({ className, ...props }) {
1149
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1150
+ "svg",
1151
+ {
1152
+ className,
1153
+ viewBox: "0 0 24 24",
1154
+ fill: "none",
1155
+ stroke: "currentColor",
1156
+ strokeWidth: 2,
1157
+ strokeLinecap: "round",
1158
+ strokeLinejoin: "round",
1159
+ ...props,
1160
+ children: [
1161
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "16 18 22 12 16 6" }),
1162
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "8 6 2 12 8 18" })
1163
+ ]
1164
+ }
1165
+ );
1166
+ }
1167
+ function ZoomInIcon({ className, ...props }) {
1168
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1169
+ "svg",
1170
+ {
1171
+ className,
1172
+ viewBox: "0 0 24 24",
1173
+ fill: "none",
1174
+ stroke: "currentColor",
1175
+ strokeWidth: 2,
1176
+ strokeLinecap: "round",
1177
+ strokeLinejoin: "round",
1178
+ ...props,
1179
+ children: [
1180
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "11", cy: "11", r: "8" }),
1181
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", y1: "21", x2: "16.65", y2: "16.65" }),
1182
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "11", y1: "8", x2: "11", y2: "14" }),
1183
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", y1: "11", x2: "14", y2: "11" })
1184
+ ]
1185
+ }
1186
+ );
1187
+ }
1188
+ function ZoomOutIcon({ className, ...props }) {
1189
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1190
+ "svg",
1191
+ {
1192
+ className,
1193
+ viewBox: "0 0 24 24",
1194
+ fill: "none",
1195
+ stroke: "currentColor",
1196
+ strokeWidth: 2,
1197
+ strokeLinecap: "round",
1198
+ strokeLinejoin: "round",
1199
+ ...props,
1200
+ children: [
1201
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "11", cy: "11", r: "8" }),
1202
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", y1: "21", x2: "16.65", y2: "16.65" }),
1203
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", y1: "11", x2: "14", y2: "11" })
1204
+ ]
1205
+ }
1206
+ );
1207
+ }
1208
+ function DownloadIcon({ className, ...props }) {
1209
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1210
+ "svg",
1211
+ {
1212
+ className,
1213
+ viewBox: "0 0 24 24",
1214
+ fill: "none",
1215
+ stroke: "currentColor",
1216
+ strokeWidth: 2,
1217
+ strokeLinecap: "round",
1218
+ strokeLinejoin: "round",
1219
+ ...props,
1220
+ children: [
1221
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4" }),
1222
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "7 10 12 15 17 10" }),
1223
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "15", x2: "12", y2: "3" })
1224
+ ]
1225
+ }
1226
+ );
1227
+ }
1228
+ function ExternalLinkIcon({ className, ...props }) {
1229
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1230
+ "svg",
1231
+ {
1232
+ className,
1233
+ viewBox: "0 0 24 24",
1234
+ fill: "none",
1235
+ stroke: "currentColor",
1236
+ strokeWidth: 2,
1237
+ strokeLinecap: "round",
1238
+ strokeLinejoin: "round",
1239
+ ...props,
1240
+ children: [
1241
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" }),
1242
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "15 3 21 3 21 9" }),
1243
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "10", y1: "14", x2: "21", y2: "3" })
1244
+ ]
1245
+ }
1246
+ );
1247
+ }
1248
+ function Minimize2Icon({ className, ...props }) {
1249
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1250
+ "svg",
1251
+ {
1252
+ className,
1253
+ viewBox: "0 0 24 24",
1254
+ fill: "none",
1255
+ stroke: "currentColor",
1256
+ strokeWidth: 2,
1257
+ strokeLinecap: "round",
1258
+ strokeLinejoin: "round",
1259
+ ...props,
1260
+ children: [
1261
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "4 14 10 14 10 20" }),
1262
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "20 10 14 10 14 4" }),
1263
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "14", y1: "10", x2: "21", y2: "3" }),
1264
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
1265
+ ]
1266
+ }
1267
+ );
1268
+ }
1269
+ function Maximize2Icon({ className, ...props }) {
1270
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1271
+ "svg",
1272
+ {
1273
+ className,
1274
+ viewBox: "0 0 24 24",
1275
+ fill: "none",
1276
+ stroke: "currentColor",
1277
+ strokeWidth: 2,
1278
+ strokeLinecap: "round",
1279
+ strokeLinejoin: "round",
1280
+ ...props,
1281
+ children: [
1282
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "15 3 21 3 21 9" }),
1283
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "9 21 3 21 3 15" }),
1284
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "21", y1: "3", x2: "14", y2: "10" }),
1285
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "3", y1: "21", x2: "10", y2: "14" })
1286
+ ]
1287
+ }
1288
+ );
1289
+ }
1290
+ function BotIcon({ className, ...props }) {
1291
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1292
+ "svg",
1293
+ {
1294
+ className,
1295
+ viewBox: "0 0 24 24",
1296
+ fill: "none",
1297
+ stroke: "currentColor",
1298
+ strokeWidth: 2,
1299
+ strokeLinecap: "round",
1300
+ strokeLinejoin: "round",
1301
+ ...props,
1302
+ children: [
1303
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "11", width: "18", height: "10", rx: "2" }),
1304
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "5", r: "2" }),
1305
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 7v4" }),
1306
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "8", y1: "16", x2: "8", y2: "16" }),
1307
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "16", y1: "16", x2: "16", y2: "16" })
1308
+ ]
1309
+ }
1310
+ );
1311
+ }
1312
+ function UserIcon({ className, ...props }) {
1313
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1314
+ "svg",
1315
+ {
1316
+ className,
1317
+ viewBox: "0 0 24 24",
1318
+ fill: "none",
1319
+ stroke: "currentColor",
1320
+ strokeWidth: 2,
1321
+ strokeLinecap: "round",
1322
+ strokeLinejoin: "round",
1323
+ ...props,
1324
+ children: [
1325
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }),
1326
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "7", r: "4" })
1327
+ ]
1328
+ }
1329
+ );
1330
+ }
1331
+ function SparklesIcon({ className, ...props }) {
1332
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1333
+ "svg",
1334
+ {
1335
+ className,
1336
+ viewBox: "0 0 24 24",
1337
+ fill: "none",
1338
+ stroke: "currentColor",
1339
+ strokeWidth: 2,
1340
+ strokeLinecap: "round",
1341
+ strokeLinejoin: "round",
1342
+ ...props,
1343
+ children: [
1344
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3z" }),
1345
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 19l.5 1.5L7 21l-1.5.5L5 23l-.5-1.5L3 21l1.5-.5L5 19z" }),
1346
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M19 5l.5 1.5L21 7l-1.5.5L19 9l-.5-1.5L17 7l1.5-.5L19 5z" })
1347
+ ]
1348
+ }
1349
+ );
1350
+ }
1351
+ function ListTodoIcon({ className, ...props }) {
1352
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1353
+ "svg",
1354
+ {
1355
+ className,
1356
+ viewBox: "0 0 24 24",
1357
+ fill: "none",
1358
+ stroke: "currentColor",
1359
+ strokeWidth: 2,
1360
+ strokeLinecap: "round",
1361
+ strokeLinejoin: "round",
1362
+ ...props,
1363
+ children: [
1364
+ /* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "5", width: "6", height: "6", rx: "1" }),
1365
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m3 17 2 2 4-4" }),
1366
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M13 6h8" }),
1367
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M13 12h8" }),
1368
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M13 18h8" })
1369
+ ]
1370
+ }
1371
+ );
1372
+ }
1373
+ function HelpCircleIcon({ className, ...props }) {
1374
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1375
+ "svg",
1376
+ {
1377
+ className,
1378
+ viewBox: "0 0 24 24",
1379
+ fill: "none",
1380
+ stroke: "currentColor",
1381
+ strokeWidth: 2,
1382
+ strokeLinecap: "round",
1383
+ strokeLinejoin: "round",
1384
+ ...props,
1385
+ children: [
1386
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
1387
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M9.09 9a3 3 0 0 1 5.83 1c0 2-3 3-3 3" }),
1388
+ /* @__PURE__ */ jsxRuntime.jsx("line", { x1: "12", y1: "17", x2: "12.01", y2: "17" })
1389
+ ]
1390
+ }
1391
+ );
1392
+ }
1393
+ function DatabaseIcon({ className, ...props }) {
1394
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1395
+ "svg",
1396
+ {
1397
+ className,
1398
+ viewBox: "0 0 24 24",
1399
+ fill: "none",
1400
+ stroke: "currentColor",
1401
+ strokeWidth: 2,
1402
+ strokeLinecap: "round",
1403
+ strokeLinejoin: "round",
1404
+ ...props,
1405
+ children: [
1406
+ /* @__PURE__ */ jsxRuntime.jsx("ellipse", { cx: "12", cy: "5", rx: "9", ry: "3" }),
1407
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21 12c0 1.66-4 3-9 3s-9-1.34-9-3" }),
1408
+ /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5" })
1409
+ ]
1410
+ }
1411
+ );
1412
+ }
1413
+ function ClockIcon({ className, ...props }) {
1414
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1415
+ "svg",
1416
+ {
1417
+ className,
1418
+ viewBox: "0 0 24 24",
1419
+ fill: "none",
1420
+ stroke: "currentColor",
1421
+ strokeWidth: 2,
1422
+ strokeLinecap: "round",
1423
+ strokeLinejoin: "round",
1424
+ ...props,
1425
+ children: [
1426
+ /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "12", cy: "12", r: "10" }),
1427
+ /* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "12 6 12 12 16 14" })
1428
+ ]
1429
+ }
1430
+ );
1431
+ }
1432
+ function cn2(...classes) {
1433
+ return classes.filter(Boolean).join(" ");
1434
+ }
1435
+ function ChatContainer({
1436
+ children,
1437
+ maxHeight = "600px",
1438
+ className,
1439
+ theme = "system"
1440
+ }) {
1441
+ const maxHeightValue = typeof maxHeight === "number" ? `${maxHeight}px` : maxHeight;
1442
+ return /* @__PURE__ */ jsxRuntime.jsx(
1443
+ "div",
1444
+ {
1445
+ className: cn2(
1446
+ "flex flex-col bg-white dark:bg-gray-900 rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden",
1447
+ className
1448
+ ),
1449
+ style: { maxHeight: maxHeightValue },
1450
+ "data-theme": theme,
1451
+ children
1452
+ }
1453
+ );
1454
+ }
1455
+ function cn3(...classes) {
1456
+ return classes.filter(Boolean).join(" ");
1457
+ }
1458
+ function ChatInput({
1459
+ onSend,
1460
+ onStop,
1461
+ placeholder = "Type a message...",
1462
+ disabled = false,
1463
+ isLoading = false,
1464
+ enableAttachments = false,
1465
+ className
1466
+ }) {
1467
+ const [content, setContent] = react.useState("");
1468
+ const textareaRef = react.useRef(null);
1469
+ react.useEffect(() => {
1470
+ const textarea = textareaRef.current;
1471
+ if (textarea) {
1472
+ textarea.style.height = "auto";
1473
+ textarea.style.height = `${Math.min(textarea.scrollHeight, 200)}px`;
1474
+ }
1475
+ }, [content]);
1476
+ const handleSubmit = react.useCallback(async () => {
1477
+ const trimmedContent = content.trim();
1478
+ if (!trimmedContent || disabled || isLoading) return;
1479
+ setContent("");
1480
+ await onSend(trimmedContent);
1481
+ }, [content, disabled, isLoading, onSend]);
1482
+ const handleKeyDown = react.useCallback(
1483
+ (e) => {
1484
+ if (e.key === "Enter" && !e.shiftKey) {
1485
+ e.preventDefault();
1486
+ handleSubmit();
1487
+ }
1488
+ },
1489
+ [handleSubmit]
1490
+ );
1491
+ const handleStopClick = react.useCallback(() => {
1492
+ onStop?.();
1493
+ }, [onStop]);
1494
+ const canSend = content.trim().length > 0 && !disabled && !isLoading;
1495
+ const showStopButton = isLoading && onStop;
1496
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1497
+ "div",
1498
+ {
1499
+ className: cn3(
1500
+ "border-t border-gray-200 dark:border-gray-700 p-4",
1501
+ className
1502
+ ),
1503
+ children: [
1504
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-end gap-2", children: [
1505
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 relative", children: /* @__PURE__ */ jsxRuntime.jsx(
1506
+ "textarea",
1507
+ {
1508
+ ref: textareaRef,
1509
+ value: content,
1510
+ onChange: (e) => setContent(e.target.value),
1511
+ onKeyDown: handleKeyDown,
1512
+ placeholder,
1513
+ disabled,
1514
+ rows: 1,
1515
+ className: cn3(
1516
+ "w-full resize-none rounded-lg border px-4 py-3 text-sm",
1517
+ "border-gray-300 dark:border-gray-600",
1518
+ "bg-white dark:bg-gray-800",
1519
+ "text-gray-900 dark:text-gray-100",
1520
+ "placeholder-gray-500 dark:placeholder-gray-400",
1521
+ "focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent",
1522
+ "disabled:opacity-50 disabled:cursor-not-allowed"
1523
+ ),
1524
+ style: { minHeight: "44px", maxHeight: "200px" }
1525
+ }
1526
+ ) }),
1527
+ showStopButton ? /* @__PURE__ */ jsxRuntime.jsx(
1528
+ "button",
1529
+ {
1530
+ type: "button",
1531
+ onClick: handleStopClick,
1532
+ className: cn3(
1533
+ "flex-shrink-0 p-3 rounded-lg transition-colors",
1534
+ "bg-red-500 text-white hover:bg-red-600",
1535
+ "focus:outline-none focus:ring-2 focus:ring-red-500 focus:ring-offset-2"
1536
+ ),
1537
+ "aria-label": "Stop generation",
1538
+ children: /* @__PURE__ */ jsxRuntime.jsx(StopCircleIcon, { className: "h-5 w-5" })
1539
+ }
1540
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
1541
+ "button",
1542
+ {
1543
+ type: "button",
1544
+ onClick: handleSubmit,
1545
+ disabled: !canSend,
1546
+ className: cn3(
1547
+ "flex-shrink-0 p-3 rounded-lg transition-colors",
1548
+ canSend ? "bg-blue-500 text-white hover:bg-blue-600" : "bg-gray-200 dark:bg-gray-700 text-gray-400 dark:text-gray-500",
1549
+ "disabled:cursor-not-allowed",
1550
+ "focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2"
1551
+ ),
1552
+ "aria-label": "Send message",
1553
+ children: isLoading ? /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { className: "h-5 w-5" }) : /* @__PURE__ */ jsxRuntime.jsx(SendIcon, { className: "h-5 w-5" })
1554
+ }
1555
+ )
1556
+ ] }),
1557
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-xs text-gray-500 dark:text-gray-400", children: "Press Enter to send, Shift+Enter for new line" })
1558
+ ]
1559
+ }
1560
+ );
1561
+ }
1562
+ function cn4(...classes) {
1563
+ return classes.filter(Boolean).join(" ");
1564
+ }
1565
+ function AskUserPrompt({
1566
+ question,
1567
+ options,
1568
+ onSubmit,
1569
+ required = true,
1570
+ disabled = false,
1571
+ status = "waiting",
1572
+ className
1573
+ }) {
1574
+ const [response, setResponse] = react.useState("");
1575
+ const [selectedOption, setSelectedOption] = react.useState(null);
1576
+ const handleSubmit = react.useCallback(() => {
1577
+ const finalResponse = selectedOption || response.trim();
1578
+ if (required && !finalResponse) return;
1579
+ onSubmit(finalResponse);
1580
+ }, [selectedOption, response, required, onSubmit]);
1581
+ const handleKeyDown = react.useCallback(
1582
+ (e) => {
1583
+ if (e.key === "Enter" && !e.shiftKey) {
1584
+ e.preventDefault();
1585
+ handleSubmit();
1586
+ }
1587
+ },
1588
+ [handleSubmit]
1589
+ );
1590
+ const handleOptionSelect = react.useCallback((option) => {
1591
+ setSelectedOption((prev) => prev === option ? null : option);
1592
+ setResponse("");
1593
+ }, []);
1594
+ const isSubmitDisabled = disabled || status !== "waiting" || required && !response.trim() && !selectedOption;
1595
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1596
+ "div",
1597
+ {
1598
+ className: cn4(
1599
+ "rounded-lg border p-4 space-y-3",
1600
+ status === "waiting" ? "border-blue-200 bg-blue-50/50 dark:border-blue-800 dark:bg-blue-950/20" : "border-green-200 bg-green-50/50 dark:border-green-800 dark:bg-green-950/20",
1601
+ className
1602
+ ),
1603
+ children: [
1604
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
1605
+ /* @__PURE__ */ jsxRuntime.jsx(MessageCircleIcon, { className: "h-5 w-5 text-blue-600 dark:text-blue-400" }),
1606
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-blue-900 dark:text-blue-100", children: "Agent needs your input" }),
1607
+ /* @__PURE__ */ jsxRuntime.jsx(
1608
+ "span",
1609
+ {
1610
+ className: cn4(
1611
+ "ml-auto text-xs px-2 py-1 rounded-full font-medium",
1612
+ status === "waiting" ? "bg-blue-100 text-blue-700 dark:bg-blue-900 dark:text-blue-300" : "bg-green-100 text-green-700 dark:bg-green-900 dark:text-green-300"
1613
+ ),
1614
+ children: status === "waiting" ? "Waiting" : status === "submitted" ? "Submitted" : "Processing"
1615
+ }
1616
+ )
1617
+ ] }),
1618
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-700 dark:text-gray-300 whitespace-pre-wrap", children: question }),
1619
+ options && options.length > 0 && status === "waiting" && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: options.map((option, idx) => /* @__PURE__ */ jsxRuntime.jsx(
1620
+ "button",
1621
+ {
1622
+ type: "button",
1623
+ onClick: () => handleOptionSelect(option),
1624
+ disabled,
1625
+ className: cn4(
1626
+ "px-3 py-1.5 text-sm rounded-md border transition-all",
1627
+ selectedOption === option ? "bg-blue-600 text-white border-blue-600 hover:bg-blue-700" : "bg-white dark:bg-gray-800 border-gray-300 dark:border-gray-600 hover:bg-gray-50 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-300",
1628
+ disabled && "opacity-50 cursor-not-allowed"
1629
+ ),
1630
+ children: option
1631
+ },
1632
+ idx
1633
+ )) }),
1634
+ status === "waiting" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-2", children: [
1635
+ /* @__PURE__ */ jsxRuntime.jsx(
1636
+ "textarea",
1637
+ {
1638
+ value: response,
1639
+ onChange: (e) => {
1640
+ setResponse(e.target.value);
1641
+ setSelectedOption(null);
1642
+ },
1643
+ onKeyDown: handleKeyDown,
1644
+ placeholder: options?.length ? "Or type a custom response..." : "Type your response...",
1645
+ className: cn4(
1646
+ "flex-1 min-h-[60px] px-3 py-2 text-sm resize-none rounded-md border",
1647
+ "border-gray-300 dark:border-gray-600",
1648
+ "bg-white dark:bg-gray-800",
1649
+ "text-gray-900 dark:text-gray-100",
1650
+ "placeholder-gray-500 dark:placeholder-gray-400",
1651
+ "focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent",
1652
+ disabled && "opacity-50 cursor-not-allowed"
1653
+ ),
1654
+ disabled
1655
+ }
1656
+ ),
1657
+ /* @__PURE__ */ jsxRuntime.jsx(
1658
+ "button",
1659
+ {
1660
+ type: "button",
1661
+ onClick: handleSubmit,
1662
+ disabled: isSubmitDisabled,
1663
+ className: cn4(
1664
+ "self-end px-4 py-2 rounded-md text-white transition-colors",
1665
+ "bg-blue-600 hover:bg-blue-700",
1666
+ "disabled:opacity-50 disabled:cursor-not-allowed"
1667
+ ),
1668
+ children: /* @__PURE__ */ jsxRuntime.jsx(SendIcon, { className: "h-4 w-4" })
1669
+ }
1670
+ )
1671
+ ] }),
1672
+ status !== "waiting" && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-sm text-green-700 dark:text-green-400", children: [
1673
+ /* @__PURE__ */ jsxRuntime.jsx(CheckCircleIcon, { className: "h-4 w-4" }),
1674
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
1675
+ "Response submitted:",
1676
+ " ",
1677
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: selectedOption || response })
1678
+ ] })
1679
+ ] })
1680
+ ]
1681
+ }
1682
+ );
1683
+ }
1684
+ function cn5(...classes) {
1685
+ return classes.filter(Boolean).join(" ");
1686
+ }
1687
+ function MarkdownContent({ content, className }) {
1688
+ const components = react.useMemo(
1689
+ () => ({
1690
+ // Headers
1691
+ h1: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-2xl font-bold mt-4 mb-2 first:mt-0", children }),
1692
+ h2: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "text-xl font-bold mt-4 mb-2 first:mt-0", children }),
1693
+ h3: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("h3", { className: "text-lg font-semibold mt-3 mb-1 first:mt-0", children }),
1694
+ h4: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "text-base font-semibold mt-2 mb-1 first:mt-0", children }),
1695
+ // Paragraphs
1696
+ p: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mb-2 last:mb-0 leading-relaxed", children }),
1697
+ // Lists
1698
+ ul: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "list-disc list-inside mb-2 space-y-1", children }),
1699
+ ol: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "list-decimal list-inside mb-2 space-y-1", children }),
1700
+ li: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: "leading-relaxed", children }),
1701
+ // Links
1702
+ a: ({ href, children }) => /* @__PURE__ */ jsxRuntime.jsx(
1703
+ "a",
1704
+ {
1705
+ href,
1706
+ target: "_blank",
1707
+ rel: "noopener noreferrer",
1708
+ className: "text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300 underline",
1709
+ children
1710
+ }
1711
+ ),
1712
+ // Tables
1713
+ table: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto my-2", children: /* @__PURE__ */ jsxRuntime.jsx("table", { className: "min-w-full divide-y divide-gray-200 dark:divide-gray-700 border border-gray-200 dark:border-gray-700 rounded-lg", children }) }),
1714
+ thead: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("thead", { className: "bg-gray-50 dark:bg-gray-800", children }),
1715
+ tbody: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("tbody", { className: "bg-white dark:bg-gray-900 divide-y divide-gray-200 dark:divide-gray-700", children }),
1716
+ tr: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("tr", { children }),
1717
+ th: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("th", { className: "px-3 py-2 text-left text-xs font-medium text-gray-500 dark:text-gray-400 uppercase tracking-wider", children }),
1718
+ td: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-3 py-2 text-sm text-gray-900 dark:text-gray-100 whitespace-nowrap", children }),
1719
+ // Blockquotes
1720
+ blockquote: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("blockquote", { className: "border-l-4 border-gray-300 dark:border-gray-600 pl-4 italic text-gray-600 dark:text-gray-400 my-2", children }),
1721
+ // Horizontal rule
1722
+ hr: () => /* @__PURE__ */ jsxRuntime.jsx("hr", { className: "my-4 border-gray-200 dark:border-gray-700" }),
1723
+ // Strong and emphasis
1724
+ strong: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("strong", { className: "font-semibold", children }),
1725
+ em: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("em", { className: "italic", children }),
1726
+ // Strikethrough (GFM)
1727
+ del: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx("del", { className: "line-through text-gray-500 dark:text-gray-400", children }),
1728
+ // Code - inline and blocks
1729
+ code: ({ className: codeClassName, children, ...props }) => {
1730
+ const isCodeBlock = /language-(\w+)/.exec(codeClassName || "");
1731
+ const language = isCodeBlock ? isCodeBlock[1] : null;
1732
+ if (isCodeBlock) {
1733
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative my-2", children: [
1734
+ language && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "absolute top-0 right-0 px-2 py-1 text-xs font-mono text-gray-500 dark:text-gray-400 bg-gray-100 dark:bg-gray-800 rounded-bl rounded-tr border-b border-l border-gray-200 dark:border-gray-700", children: language }),
1735
+ /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "bg-gray-100 dark:bg-gray-800 rounded-lg p-4 overflow-x-auto text-sm", children: /* @__PURE__ */ jsxRuntime.jsx("code", { className: cn5("font-mono", codeClassName), ...props, children }) })
1736
+ ] });
1737
+ }
1738
+ return /* @__PURE__ */ jsxRuntime.jsx(
1739
+ "code",
1740
+ {
1741
+ className: "bg-gray-100 dark:bg-gray-800 text-gray-800 dark:text-gray-200 px-1.5 py-0.5 rounded text-sm font-mono",
1742
+ ...props,
1743
+ children
1744
+ }
1745
+ );
1746
+ },
1747
+ // Pre element (for code blocks)
1748
+ pre: ({ children }) => /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children }),
1749
+ // Images
1750
+ img: ({ src, alt }) => /* @__PURE__ */ jsxRuntime.jsx(
1751
+ "img",
1752
+ {
1753
+ src,
1754
+ alt: alt || "",
1755
+ className: "max-w-full h-auto rounded-lg my-2",
1756
+ loading: "lazy"
1757
+ }
1758
+ ),
1759
+ // Task lists (GFM)
1760
+ input: ({ type, checked, disabled }) => {
1761
+ if (type === "checkbox") {
1762
+ return /* @__PURE__ */ jsxRuntime.jsx(
1763
+ "input",
1764
+ {
1765
+ type: "checkbox",
1766
+ checked,
1767
+ disabled,
1768
+ readOnly: true,
1769
+ className: "mr-2 rounded border-gray-300 dark:border-gray-600"
1770
+ }
1771
+ );
1772
+ }
1773
+ return /* @__PURE__ */ jsxRuntime.jsx("input", { type });
1774
+ }
1775
+ }),
1776
+ []
1777
+ );
1778
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn5("prose prose-sm dark:prose-invert max-w-none", className), children: /* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown__default.default, { remarkPlugins: [remarkGfm__default.default], components, children: content }) });
1779
+ }
1780
+ function cn6(...classes) {
1781
+ return classes.filter(Boolean).join(" ");
1782
+ }
1783
+ function formatToolName(toolName) {
1784
+ if (!toolName) return toolName;
1785
+ const prefixesToRemove = [
1786
+ "skills_api_",
1787
+ "tools_api_",
1788
+ "tools_management_api_",
1789
+ "browse_web_browse_web_",
1790
+ "browse_web_browse_",
1791
+ "browse_web_",
1792
+ "notion_api_",
1793
+ "google_api_",
1794
+ "slack_api_",
1795
+ "github_api_",
1796
+ "search_api_",
1797
+ "file_system_",
1798
+ "code_execution_",
1799
+ "data_analysis_",
1800
+ "knowledge_base_",
1801
+ "memory_api_",
1802
+ "database_api_",
1803
+ "email_api_",
1804
+ "calendar_api_",
1805
+ "storage_api_",
1806
+ "api_"
1807
+ ];
1808
+ let cleanName = toolName;
1809
+ let foundPrefix = true;
1810
+ while (foundPrefix) {
1811
+ foundPrefix = false;
1812
+ for (const prefix of prefixesToRemove) {
1813
+ if (cleanName.toLowerCase().startsWith(prefix)) {
1814
+ cleanName = cleanName.slice(prefix.length);
1815
+ foundPrefix = true;
1816
+ break;
1817
+ }
1818
+ }
1819
+ }
1820
+ const words = cleanName.split("_");
1821
+ const uniqueWords = [];
1822
+ for (const word of words) {
1823
+ if (uniqueWords.length === 0 || uniqueWords[uniqueWords.length - 1]?.toLowerCase() !== word.toLowerCase()) {
1824
+ uniqueWords.push(word);
1825
+ }
1826
+ }
1827
+ return uniqueWords.map((word) => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase()).join(" ");
1828
+ }
1829
+ function formatDuration(ms) {
1830
+ if (ms < 1e3) {
1831
+ return `${ms}ms`;
1832
+ }
1833
+ const seconds = (ms / 1e3).toFixed(1);
1834
+ return `${seconds}s`;
1835
+ }
1836
+ function formatJsonPreview(data, maxLength = 100) {
1837
+ if (data === void 0 || data === null) {
1838
+ return String(data);
1839
+ }
1840
+ try {
1841
+ const str = JSON.stringify(data, null, 2);
1842
+ if (str.length > maxLength) {
1843
+ return str.slice(0, maxLength) + "...";
1844
+ }
1845
+ return str;
1846
+ } catch {
1847
+ return String(data);
1848
+ }
1849
+ }
1850
+ function ToolCallEntry({
1851
+ toolCall,
1852
+ className,
1853
+ showFullJson = true
1854
+ }) {
1855
+ const [isExpanded, setIsExpanded] = react.useState(false);
1856
+ const formattedName = react.useMemo(
1857
+ () => formatToolName(toolCall.name),
1858
+ [toolCall.name]
1859
+ );
1860
+ const statusIcon = react.useMemo(() => {
1861
+ switch (toolCall.status) {
1862
+ case "pending":
1863
+ return /* @__PURE__ */ jsxRuntime.jsx(ClockIcon, { className: "h-4 w-4 text-gray-400" });
1864
+ case "running":
1865
+ return /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { className: "h-4 w-4 text-blue-500" });
1866
+ case "completed":
1867
+ return /* @__PURE__ */ jsxRuntime.jsx(CheckIcon, { className: "h-4 w-4 text-green-500" });
1868
+ case "failed":
1869
+ return /* @__PURE__ */ jsxRuntime.jsx(AlertCircleIcon, { className: "h-4 w-4 text-red-500" });
1870
+ default:
1871
+ return null;
1872
+ }
1873
+ }, [toolCall.status]);
1874
+ const statusColor = react.useMemo(() => {
1875
+ switch (toolCall.status) {
1876
+ case "pending":
1877
+ return "border-gray-200 dark:border-gray-700";
1878
+ case "running":
1879
+ return "border-blue-200 dark:border-blue-800 bg-blue-50/50 dark:bg-blue-950/20";
1880
+ case "completed":
1881
+ return "border-green-200 dark:border-green-800";
1882
+ case "failed":
1883
+ return "border-red-200 dark:border-red-800 bg-red-50/50 dark:bg-red-950/20";
1884
+ default:
1885
+ return "border-gray-200 dark:border-gray-700";
1886
+ }
1887
+ }, [toolCall.status]);
1888
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1889
+ "div",
1890
+ {
1891
+ className: cn6(
1892
+ "rounded-lg border text-sm",
1893
+ statusColor,
1894
+ className
1895
+ ),
1896
+ children: [
1897
+ /* @__PURE__ */ jsxRuntime.jsxs(
1898
+ "button",
1899
+ {
1900
+ type: "button",
1901
+ onClick: () => setIsExpanded(!isExpanded),
1902
+ className: "w-full flex items-center gap-2 px-3 py-2 hover:bg-gray-50 dark:hover:bg-gray-800/50 transition-colors rounded-lg",
1903
+ children: [
1904
+ isExpanded ? /* @__PURE__ */ jsxRuntime.jsx(ChevronDownIcon, { className: "h-4 w-4 text-gray-400 flex-shrink-0" }) : /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, { className: "h-4 w-4 text-gray-400 flex-shrink-0" }),
1905
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-shrink-0", children: statusIcon }),
1906
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-gray-900 dark:text-gray-100 truncate", children: formattedName }),
1907
+ toolCall.status === "completed" && toolCall.durationMs !== void 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto text-xs text-gray-500 dark:text-gray-400 flex-shrink-0", children: formatDuration(toolCall.durationMs) }),
1908
+ toolCall.status === "failed" && toolCall.error && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto text-xs text-red-600 dark:text-red-400 truncate max-w-[150px]", children: toolCall.error })
1909
+ ]
1910
+ }
1911
+ ),
1912
+ isExpanded && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-gray-200 dark:border-gray-700 px-3 py-2 space-y-2", children: [
1913
+ toolCall.args && Object.keys(toolCall.args).length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1914
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs font-medium text-gray-500 dark:text-gray-400 mb-1", children: "Input" }),
1915
+ /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "bg-gray-100 dark:bg-gray-800 rounded p-2 text-xs overflow-x-auto font-mono text-gray-700 dark:text-gray-300", children: showFullJson ? JSON.stringify(toolCall.args, null, 2) : formatJsonPreview(toolCall.args, 200) })
1916
+ ] }),
1917
+ toolCall.status === "completed" && toolCall.result !== void 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1918
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs font-medium text-gray-500 dark:text-gray-400 mb-1", children: "Output" }),
1919
+ /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "bg-gray-100 dark:bg-gray-800 rounded p-2 text-xs overflow-x-auto font-mono text-gray-700 dark:text-gray-300 max-h-[200px]", children: showFullJson ? JSON.stringify(toolCall.result, null, 2) : formatJsonPreview(toolCall.result, 500) })
1920
+ ] }),
1921
+ toolCall.status === "failed" && toolCall.error && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
1922
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs font-medium text-red-600 dark:text-red-400 mb-1", children: "Error" }),
1923
+ /* @__PURE__ */ jsxRuntime.jsx("pre", { className: "bg-red-50 dark:bg-red-950/30 rounded p-2 text-xs overflow-x-auto font-mono text-red-700 dark:text-red-300", children: toolCall.error })
1924
+ ] })
1925
+ ] })
1926
+ ]
1927
+ }
1928
+ );
1929
+ }
1930
+ function cn7(...classes) {
1931
+ return classes.filter(Boolean).join(" ");
1932
+ }
1933
+ function ChatMessage({
1934
+ message,
1935
+ enableMarkdown = true,
1936
+ showToolCalls = true,
1937
+ className
1938
+ }) {
1939
+ const isUser = message.role === "user";
1940
+ const isAssistant = message.role === "assistant";
1941
+ const formattedTime = react.useMemo(() => {
1942
+ const date = message.timestamp instanceof Date ? message.timestamp : new Date(message.timestamp);
1943
+ return date.toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" });
1944
+ }, [message.timestamp]);
1945
+ return /* @__PURE__ */ jsxRuntime.jsxs(
1946
+ "div",
1947
+ {
1948
+ className: cn7(
1949
+ "flex gap-3 p-4",
1950
+ isUser ? "flex-row-reverse" : "flex-row",
1951
+ className
1952
+ ),
1953
+ children: [
1954
+ /* @__PURE__ */ jsxRuntime.jsx(
1955
+ "div",
1956
+ {
1957
+ className: cn7(
1958
+ "flex-shrink-0 w-8 h-8 rounded-full flex items-center justify-center",
1959
+ isUser ? "bg-blue-500 text-white" : "bg-gray-200 dark:bg-gray-700 text-gray-600 dark:text-gray-300"
1960
+ ),
1961
+ children: isUser ? /* @__PURE__ */ jsxRuntime.jsx(UserIcon, { className: "h-4 w-4" }) : /* @__PURE__ */ jsxRuntime.jsx(BotIcon, { className: "h-4 w-4" })
1962
+ }
1963
+ ),
1964
+ /* @__PURE__ */ jsxRuntime.jsxs(
1965
+ "div",
1966
+ {
1967
+ className: cn7(
1968
+ "flex-1 min-w-0 space-y-2",
1969
+ isUser ? "text-right" : "text-left"
1970
+ ),
1971
+ children: [
1972
+ /* @__PURE__ */ jsxRuntime.jsxs(
1973
+ "div",
1974
+ {
1975
+ className: cn7(
1976
+ "flex items-center gap-2 text-xs text-gray-500 dark:text-gray-400",
1977
+ isUser ? "justify-end" : "justify-start"
1978
+ ),
1979
+ children: [
1980
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: isUser ? "You" : "Assistant" }),
1981
+ /* @__PURE__ */ jsxRuntime.jsx("span", { children: formattedTime }),
1982
+ message.isStreaming && /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { className: "h-3 w-3" })
1983
+ ]
1984
+ }
1985
+ ),
1986
+ message.thinkingBlocks && message.thinkingBlocks.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: message.thinkingBlocks.map((block) => /* @__PURE__ */ jsxRuntime.jsxs(
1987
+ "div",
1988
+ {
1989
+ className: "bg-purple-50 dark:bg-purple-950/30 border border-purple-200 dark:border-purple-800 rounded-lg p-3 text-sm text-purple-800 dark:text-purple-200",
1990
+ children: [
1991
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs font-medium text-purple-600 dark:text-purple-400 mb-1", children: "Thinking..." }),
1992
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "whitespace-pre-wrap", children: block.content })
1993
+ ]
1994
+ },
1995
+ block.id
1996
+ )) }),
1997
+ message.content && /* @__PURE__ */ jsxRuntime.jsx(
1998
+ "div",
1999
+ {
2000
+ className: cn7(
2001
+ "rounded-lg p-3",
2002
+ isUser ? "bg-blue-500 text-white" : "bg-gray-100 dark:bg-gray-800 text-gray-900 dark:text-gray-100"
2003
+ ),
2004
+ children: isAssistant && enableMarkdown ? /* @__PURE__ */ jsxRuntime.jsx(MarkdownContent, { content: message.content }) : /* @__PURE__ */ jsxRuntime.jsx("p", { className: "whitespace-pre-wrap", children: message.content })
2005
+ }
2006
+ ),
2007
+ showToolCalls && message.toolCalls && message.toolCalls.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: message.toolCalls.map((toolCall) => /* @__PURE__ */ jsxRuntime.jsx(
2008
+ ToolCallEntry,
2009
+ {
2010
+ toolCall
2011
+ },
2012
+ toolCall.id
2013
+ )) }),
2014
+ message.attachments && message.attachments.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-wrap gap-2", children: message.attachments.map((attachment) => /* @__PURE__ */ jsxRuntime.jsx(
2015
+ "div",
2016
+ {
2017
+ className: "flex items-center gap-2 bg-gray-100 dark:bg-gray-800 rounded-lg px-3 py-2 text-sm",
2018
+ children: /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate max-w-[150px]", children: attachment.filename })
2019
+ },
2020
+ attachment.uuid
2021
+ )) })
2022
+ ]
2023
+ }
2024
+ )
2025
+ ]
2026
+ }
2027
+ );
2028
+ }
2029
+ function cn8(...classes) {
2030
+ return classes.filter(Boolean).join(" ");
2031
+ }
2032
+ function MessageList({
2033
+ messages,
2034
+ welcomeMessage = "Hello! How can I help you today?",
2035
+ isLoading = false,
2036
+ isStreaming = false,
2037
+ isLoadingHistory = false,
2038
+ enableMarkdown = true,
2039
+ showToolCalls = true,
2040
+ className
2041
+ }) {
2042
+ const scrollRef = react.useRef(null);
2043
+ const messagesEndRef = react.useRef(null);
2044
+ react.useEffect(() => {
2045
+ if (messagesEndRef.current) {
2046
+ messagesEndRef.current.scrollIntoView({ behavior: "smooth" });
2047
+ }
2048
+ }, [messages, isStreaming]);
2049
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2050
+ "div",
2051
+ {
2052
+ ref: scrollRef,
2053
+ className: cn8(
2054
+ "flex-1 overflow-y-auto",
2055
+ className
2056
+ ),
2057
+ children: [
2058
+ isLoadingHistory && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full p-8", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-center text-gray-500 dark:text-gray-400", children: [
2059
+ /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { className: "h-6 w-6 mx-auto mb-2" }),
2060
+ /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm", children: "Loading conversation..." })
2061
+ ] }) }),
2062
+ messages.length === 0 && !isLoading && !isLoadingHistory && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center justify-center h-full p-8", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-center text-gray-500 dark:text-gray-400", children: /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-lg", children: welcomeMessage }) }) }),
2063
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "divide-y divide-gray-100 dark:divide-gray-800", children: messages.map((message) => /* @__PURE__ */ jsxRuntime.jsx(
2064
+ ChatMessage,
2065
+ {
2066
+ message,
2067
+ enableMarkdown,
2068
+ showToolCalls
2069
+ },
2070
+ message.id
2071
+ )) }),
2072
+ isLoading && !isStreaming && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 p-4", children: [
2073
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-shrink-0 w-8 h-8 rounded-full bg-gray-200 dark:bg-gray-700 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { className: "h-4 w-4 text-gray-600 dark:text-gray-300" }) }),
2074
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-gray-500 dark:text-gray-400", children: "Thinking..." })
2075
+ ] }),
2076
+ /* @__PURE__ */ jsxRuntime.jsx("div", { ref: messagesEndRef })
2077
+ ]
2078
+ }
2079
+ );
2080
+ }
2081
+ function ErrorBanner({ error, onRetry, onDismiss }) {
2082
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3 px-4 py-3 bg-red-50 dark:bg-red-950/30 border-t border-red-200 dark:border-red-800 text-red-700 dark:text-red-300 text-sm", children: [
2083
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
2084
+ /* @__PURE__ */ jsxRuntime.jsx(AlertCircleIcon, { className: "h-4 w-4 flex-shrink-0" }),
2085
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: error.message })
2086
+ ] }),
2087
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 flex-shrink-0", children: [
2088
+ error.retryable && onRetry && /* @__PURE__ */ jsxRuntime.jsx(
2089
+ "button",
2090
+ {
2091
+ onClick: onRetry,
2092
+ className: "text-red-600 dark:text-red-400 hover:underline font-medium",
2093
+ children: "Retry"
2094
+ }
2095
+ ),
2096
+ onDismiss && /* @__PURE__ */ jsxRuntime.jsx(
2097
+ "button",
2098
+ {
2099
+ onClick: onDismiss,
2100
+ className: "p-1 hover:bg-red-100 dark:hover:bg-red-900/30 rounded",
2101
+ "aria-label": "Dismiss error",
2102
+ children: /* @__PURE__ */ jsxRuntime.jsx(XIcon, { className: "h-4 w-4" })
2103
+ }
2104
+ )
2105
+ ] })
2106
+ ] });
2107
+ }
2108
+ function AgentChat({
2109
+ agentId,
2110
+ sessionId,
2111
+ adapter,
2112
+ onMessage,
2113
+ onError,
2114
+ onSessionCreated,
2115
+ onSessionStart,
2116
+ onToolCall,
2117
+ onClarification,
2118
+ initialMessages = [],
2119
+ placeholder = "Type a message...",
2120
+ welcomeMessage = "Hello! How can I help you today?",
2121
+ maxHeight = "600px",
2122
+ className,
2123
+ theme = "system",
2124
+ enableAttachments = false,
2125
+ enableMarkdown = true,
2126
+ showToolCalls = true
2127
+ }) {
2128
+ const {
2129
+ messages,
2130
+ isLoading,
2131
+ isStreaming,
2132
+ isLoadingHistory,
2133
+ error,
2134
+ clarification,
2135
+ sendMessage,
2136
+ respondToClarification,
2137
+ cancel,
2138
+ retry,
2139
+ clearError
2140
+ } = useAgentChat({
2141
+ agentId,
2142
+ sessionId,
2143
+ adapter,
2144
+ initialMessages,
2145
+ onMessage,
2146
+ onError,
2147
+ onSessionCreated,
2148
+ onSessionStart,
2149
+ onToolCall,
2150
+ onClarification
2151
+ });
2152
+ return /* @__PURE__ */ jsxRuntime.jsxs(ChatContainer, { maxHeight, className, theme, children: [
2153
+ /* @__PURE__ */ jsxRuntime.jsx(
2154
+ MessageList,
2155
+ {
2156
+ messages,
2157
+ welcomeMessage,
2158
+ isLoading,
2159
+ isStreaming,
2160
+ isLoadingHistory,
2161
+ enableMarkdown,
2162
+ showToolCalls
2163
+ }
2164
+ ),
2165
+ clarification && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t border-gray-200 dark:border-gray-700 p-4", children: /* @__PURE__ */ jsxRuntime.jsx(
2166
+ AskUserPrompt,
2167
+ {
2168
+ question: clarification.question,
2169
+ options: clarification.suggestedOptions,
2170
+ onSubmit: respondToClarification
2171
+ }
2172
+ ) }),
2173
+ error && /* @__PURE__ */ jsxRuntime.jsx(ErrorBanner, { error, onRetry: retry, onDismiss: clearError }),
2174
+ /* @__PURE__ */ jsxRuntime.jsx(
2175
+ ChatInput,
2176
+ {
2177
+ onSend: sendMessage,
2178
+ onStop: isStreaming ? cancel : void 0,
2179
+ placeholder,
2180
+ disabled: !!clarification || isLoadingHistory,
2181
+ isLoading,
2182
+ enableAttachments
2183
+ }
2184
+ )
2185
+ ] });
2186
+ }
2187
+ function cn9(...classes) {
2188
+ return classes.filter(Boolean).join(" ");
2189
+ }
2190
+ function TodoList({
2191
+ todos,
2192
+ collapsible = true,
2193
+ defaultCollapsed = false,
2194
+ title = "Task Progress",
2195
+ className
2196
+ }) {
2197
+ const [isCollapsed, setIsCollapsed] = react.useState(defaultCollapsed);
2198
+ const stats = react.useMemo(() => {
2199
+ const total = todos.length;
2200
+ const completed = todos.filter((t) => t.status === "completed").length;
2201
+ const inProgress = todos.filter((t) => t.status === "in_progress").length;
2202
+ const pending = todos.filter((t) => t.status === "pending").length;
2203
+ const progress = total > 0 ? completed / total * 100 : 0;
2204
+ return { total, completed, inProgress, pending, progress };
2205
+ }, [todos]);
2206
+ const currentTask = react.useMemo(
2207
+ () => todos.find((t) => t.status === "in_progress"),
2208
+ [todos]
2209
+ );
2210
+ if (todos.length === 0) {
2211
+ return null;
2212
+ }
2213
+ return /* @__PURE__ */ jsxRuntime.jsxs(
2214
+ "div",
2215
+ {
2216
+ className: cn9(
2217
+ "rounded-lg border border-gray-200 dark:border-gray-700 overflow-hidden",
2218
+ className
2219
+ ),
2220
+ children: [
2221
+ /* @__PURE__ */ jsxRuntime.jsxs(
2222
+ "div",
2223
+ {
2224
+ className: cn9(
2225
+ "flex items-center gap-2 px-3 py-2 bg-gray-50 dark:bg-gray-800/50",
2226
+ collapsible && "cursor-pointer hover:bg-gray-100 dark:hover:bg-gray-800"
2227
+ ),
2228
+ onClick: collapsible ? () => setIsCollapsed(!isCollapsed) : void 0,
2229
+ children: [
2230
+ collapsible && (isCollapsed ? /* @__PURE__ */ jsxRuntime.jsx(ChevronRightIcon, { className: "h-4 w-4 text-gray-500" }) : /* @__PURE__ */ jsxRuntime.jsx(ChevronDownIcon, { className: "h-4 w-4 text-gray-500" })),
2231
+ /* @__PURE__ */ jsxRuntime.jsx(ListTodoIcon, { className: "h-4 w-4 text-gray-600 dark:text-gray-400" }),
2232
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: title }),
2233
+ /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-auto text-xs px-2 py-1 rounded-full bg-gray-200 dark:bg-gray-700 text-gray-700 dark:text-gray-300 font-medium", children: [
2234
+ stats.completed,
2235
+ "/",
2236
+ stats.total
2237
+ ] })
2238
+ ]
2239
+ }
2240
+ ),
2241
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "h-1 bg-gray-200 dark:bg-gray-700", children: /* @__PURE__ */ jsxRuntime.jsx(
2242
+ "div",
2243
+ {
2244
+ className: "h-full bg-blue-500 transition-all duration-300",
2245
+ style: { width: `${stats.progress}%` }
2246
+ }
2247
+ ) }),
2248
+ currentTask && isCollapsed && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 py-2 flex items-center gap-2 text-sm border-t border-gray-100 dark:border-gray-700", children: [
2249
+ /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { className: "h-3.5 w-3.5 text-blue-500" }),
2250
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-gray-600 dark:text-gray-400 truncate", children: currentTask.activeForm })
2251
+ ] }),
2252
+ !isCollapsed && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "divide-y divide-gray-100 dark:divide-gray-700", children: todos.map((todo, idx) => /* @__PURE__ */ jsxRuntime.jsxs(
2253
+ "li",
2254
+ {
2255
+ className: cn9(
2256
+ "px-3 py-2 flex items-start gap-2 text-sm",
2257
+ todo.status === "in_progress" && "bg-blue-50/50 dark:bg-blue-950/20",
2258
+ todo.status === "completed" && "opacity-60"
2259
+ ),
2260
+ children: [
2261
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-0.5 flex-shrink-0", children: todo.status === "completed" ? /* @__PURE__ */ jsxRuntime.jsx(CheckCircleIcon, { className: "h-4 w-4 text-green-600 dark:text-green-500" }) : todo.status === "in_progress" ? /* @__PURE__ */ jsxRuntime.jsx(LoadingSpinner, { className: "h-4 w-4 text-blue-500" }) : /* @__PURE__ */ jsxRuntime.jsx(CircleIcon, { className: "h-4 w-4 text-gray-300 dark:text-gray-600" }) }),
2262
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx(
2263
+ "p",
2264
+ {
2265
+ className: cn9(
2266
+ "text-gray-700 dark:text-gray-300",
2267
+ todo.status === "completed" && "line-through"
2268
+ ),
2269
+ children: todo.status === "in_progress" ? todo.activeForm : todo.content
2270
+ }
2271
+ ) }),
2272
+ todo.status === "in_progress" && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs px-2 py-0.5 rounded-full bg-blue-500 text-white font-medium flex-shrink-0", children: "Active" })
2273
+ ]
2274
+ },
2275
+ idx
2276
+ )) })
2277
+ ]
2278
+ }
2279
+ );
2280
+ }
2281
+
2282
+ exports.AgentChat = AgentChat;
2283
+ exports.AlertCircleIcon = AlertCircleIcon;
2284
+ exports.AskUserPrompt = AskUserPrompt;
2285
+ exports.BotIcon = BotIcon;
2286
+ exports.ChatConfigProvider = ChatConfigProvider;
2287
+ exports.ChatContainer = ChatContainer;
2288
+ exports.ChatInput = ChatInput;
2289
+ exports.ChatMessage = ChatMessage;
2290
+ exports.CheckCircleIcon = CheckCircleIcon;
2291
+ exports.CheckIcon = CheckIcon;
2292
+ exports.ChevronDownIcon = ChevronDownIcon;
2293
+ exports.ChevronLeftIcon = ChevronLeftIcon;
2294
+ exports.ChevronRightIcon = ChevronRightIcon;
2295
+ exports.CircleIcon = CircleIcon;
2296
+ exports.ClockIcon = ClockIcon;
2297
+ exports.CodeIcon = CodeIcon;
2298
+ exports.CopyIcon = CopyIcon;
2299
+ exports.DatabaseIcon = DatabaseIcon;
2300
+ exports.DownloadIcon = DownloadIcon;
2301
+ exports.ExternalLinkIcon = ExternalLinkIcon;
2302
+ exports.FileIcon = FileIcon;
2303
+ exports.FileTextIcon = FileTextIcon;
2304
+ exports.HelpCircleIcon = HelpCircleIcon;
2305
+ exports.ImageIcon = ImageIcon;
2306
+ exports.ImagesIcon = ImagesIcon;
2307
+ exports.ListTodoIcon = ListTodoIcon;
2308
+ exports.LoadingSpinner = LoadingSpinner;
2309
+ exports.MarkdownContent = MarkdownContent;
2310
+ exports.Maximize2Icon = Maximize2Icon;
2311
+ exports.MessageCircleIcon = MessageCircleIcon;
2312
+ exports.MessageList = MessageList;
2313
+ exports.Minimize2Icon = Minimize2Icon;
2314
+ exports.PaperclipIcon = PaperclipIcon;
2315
+ exports.SendIcon = SendIcon;
2316
+ exports.SparklesIcon = SparklesIcon;
2317
+ exports.StopCircleIcon = StopCircleIcon;
2318
+ exports.TodoList = TodoList;
2319
+ exports.ToolCallEntry = ToolCallEntry;
2320
+ exports.UserIcon = UserIcon;
2321
+ exports.XIcon = XIcon;
2322
+ exports.ZoomInIcon = ZoomInIcon;
2323
+ exports.ZoomOutIcon = ZoomOutIcon;
2324
+ exports.createDefaultAdapter = createDefaultAdapter;
2325
+ exports.useAgentChat = useAgentChat;
2326
+ exports.useChatConfig = useChatConfig;
2327
+ exports.useChatConfigOptional = useChatConfigOptional;
2328
+ exports.useExecutionStream = useExecutionStream;
2329
+ //# sourceMappingURL=index.cjs.map
2330
+ //# sourceMappingURL=index.cjs.map