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