@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.
- package/README.md +401 -0
- package/dist/chat/index.cjs +2330 -0
- package/dist/chat/index.cjs.map +1 -0
- package/dist/chat/index.d.cts +974 -0
- package/dist/chat/index.d.ts +974 -0
- package/dist/chat/index.js +2277 -0
- package/dist/chat/index.js.map +1 -0
- package/dist/index.cjs +1913 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +1904 -0
- package/dist/index.d.ts +1904 -0
- package/dist/index.js +1901 -0
- package/dist/index.js.map +1 -0
- package/package.json +97 -0
|
@@ -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
|