flowdit-chatbot-library 1.0.0 → 1.0.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/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/styles.css +280 -93
- package/dist/utilities/API.d.ts +1 -0
- package/dist/utilities/API.d.ts.map +1 -1
- package/dist/utilities/API.js.map +1 -1
- package/dist/views/ConversationHistory.d.ts +15 -0
- package/dist/views/ConversationHistory.d.ts.map +1 -0
- package/dist/views/ConversationHistory.js +75 -0
- package/dist/views/ConversationHistory.js.map +1 -0
- package/dist/views/fullscreen/index.d.ts +8 -1
- package/dist/views/fullscreen/index.d.ts.map +1 -1
- package/dist/views/fullscreen/index.functions.d.ts.map +1 -1
- package/dist/views/fullscreen/index.functions.js +8 -1
- package/dist/views/fullscreen/index.functions.js.map +1 -1
- package/dist/views/fullscreen/index.js +350 -205
- package/dist/views/fullscreen/index.js.map +1 -1
- package/package.json +11 -2
- package/LICENSE +0 -21
- package/README.md +0 -218
|
@@ -24,8 +24,32 @@ export const FullScreenChat = () => {
|
|
|
24
24
|
// =========================================
|
|
25
25
|
// State Definitions
|
|
26
26
|
// =========================================
|
|
27
|
-
//
|
|
28
|
-
const [
|
|
27
|
+
// -- Session states --
|
|
28
|
+
const [sessions, setSessions] = useState([
|
|
29
|
+
{ id: uuidv4(), title: 'New Chat', messages: [], createdAt: Date.now() }
|
|
30
|
+
]);
|
|
31
|
+
const [activeSessionId, setActiveSessionId] = useState(sessions[0].id);
|
|
32
|
+
const [isSidebarOpen, setIsSidebarOpen] = useState(true);
|
|
33
|
+
// Sync messages with active session
|
|
34
|
+
const activeSession = sessions.find(s => s.id === activeSessionId) || sessions[0];
|
|
35
|
+
const messages = activeSession?.messages || [];
|
|
36
|
+
const setMessages = (updateFn) => {
|
|
37
|
+
setSessions(prev => prev.map(s => {
|
|
38
|
+
if (s.id === activeSessionId) {
|
|
39
|
+
const newMessages = typeof updateFn === 'function' ? updateFn(s.messages) : updateFn;
|
|
40
|
+
// Auto-generate title if it's the first user message
|
|
41
|
+
let newTitle = s.title;
|
|
42
|
+
if (s.title === 'New Chat' && newMessages.length > 0) {
|
|
43
|
+
const firstUserMsg = newMessages.find(m => m.role === 'user');
|
|
44
|
+
if (firstUserMsg) {
|
|
45
|
+
newTitle = firstUserMsg.content.slice(0, 30) + (firstUserMsg.content.length > 30 ? '...' : '');
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return { ...s, messages: newMessages, title: newTitle };
|
|
49
|
+
}
|
|
50
|
+
return s;
|
|
51
|
+
}));
|
|
52
|
+
};
|
|
29
53
|
// Current value of the input textarea
|
|
30
54
|
const [input, setInput] = useState("");
|
|
31
55
|
// Flag indicating if a response is currently being streamed from the API
|
|
@@ -53,8 +77,8 @@ export const FullScreenChat = () => {
|
|
|
53
77
|
const animationFrameRef = useRef(null);
|
|
54
78
|
// Timestamp of the last character added for animation timing control
|
|
55
79
|
const lastCharTimeRef = useRef(0);
|
|
56
|
-
// Unique ID for the current conversation session
|
|
57
|
-
const conversationIdRef = useRef(
|
|
80
|
+
// Unique ID for the current conversation session (synced with activeSessionId)
|
|
81
|
+
const conversationIdRef = useRef(activeSessionId);
|
|
58
82
|
// Reference to the textarea element for auto-resizing
|
|
59
83
|
const textareaRef = useRef(null);
|
|
60
84
|
// Tracks the previous animation ID to detect message switches
|
|
@@ -71,6 +95,13 @@ export const FullScreenChat = () => {
|
|
|
71
95
|
// =========================================
|
|
72
96
|
// Effects
|
|
73
97
|
// =========================================
|
|
98
|
+
/**
|
|
99
|
+
* Effect: Sync conversationIdRef with activeSessionId.
|
|
100
|
+
*/
|
|
101
|
+
useEffect(() => {
|
|
102
|
+
conversationIdRef.current = activeSessionId;
|
|
103
|
+
console.log("Active session changed, synced conversationIdRef:", activeSessionId);
|
|
104
|
+
}, [activeSessionId]);
|
|
74
105
|
/**
|
|
75
106
|
* Effect: Handle clicks outside of dropdowns to close them.
|
|
76
107
|
*/
|
|
@@ -346,61 +377,154 @@ export const FullScreenChat = () => {
|
|
|
346
377
|
setStreamingComplete
|
|
347
378
|
});
|
|
348
379
|
};
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
380
|
+
/**
|
|
381
|
+
* Retries the last failed message generation.
|
|
382
|
+
* Finds the last user message and re-sends it after removing the failed assistant message.
|
|
383
|
+
*/
|
|
384
|
+
const handleRetry = () => {
|
|
385
|
+
// 1. Find the last user message
|
|
386
|
+
const userMessages = messages.filter(m => m.role === 'user');
|
|
387
|
+
if (userMessages.length === 0)
|
|
388
|
+
return;
|
|
389
|
+
const lastUserMessage = userMessages[userMessages.length - 1];
|
|
390
|
+
// 2. Remove the failed assistant message AND the last user message
|
|
391
|
+
// (handleSend will re-add the user message, so this prevents duplication)
|
|
392
|
+
setMessages(prev => {
|
|
393
|
+
const reversedIdx = [...prev].reverse().findIndex(m => m.id === lastUserMessage.id);
|
|
394
|
+
if (reversedIdx === -1)
|
|
395
|
+
return prev.filter(m => !m.hasError);
|
|
396
|
+
const actualIdx = prev.length - 1 - reversedIdx;
|
|
397
|
+
return prev.filter((m, idx) => !m.hasError && idx !== actualIdx);
|
|
398
|
+
});
|
|
399
|
+
// 3. Clear any animation state
|
|
400
|
+
setAnimatingMessageId(null);
|
|
401
|
+
setDisplayedChars("");
|
|
402
|
+
charBufferRef.current = "";
|
|
403
|
+
// 4. Re-send
|
|
404
|
+
handleSend(lastUserMessage.content);
|
|
405
|
+
};
|
|
406
|
+
const createNewChat = () => {
|
|
407
|
+
const newId = uuidv4();
|
|
408
|
+
setSessions(prev => [
|
|
409
|
+
{ id: newId, title: 'New Chat', messages: [], createdAt: Date.now() },
|
|
410
|
+
...prev
|
|
411
|
+
]);
|
|
412
|
+
setActiveSessionId(newId);
|
|
413
|
+
charBufferRef.current = "";
|
|
414
|
+
setDisplayedChars("");
|
|
415
|
+
setStreamingComplete(false);
|
|
416
|
+
setAnimatingMessageId(null);
|
|
417
|
+
setUserScrolledUp(false);
|
|
418
|
+
conversationIdRef.current = newId;
|
|
419
|
+
};
|
|
420
|
+
const deleteSession = (id, e) => {
|
|
421
|
+
e.stopPropagation();
|
|
422
|
+
if (sessions.length === 1) {
|
|
423
|
+
const newId = uuidv4();
|
|
424
|
+
setSessions([{ id: newId, title: 'New Chat', messages: [], createdAt: Date.now() }]);
|
|
425
|
+
setActiveSessionId(newId);
|
|
426
|
+
}
|
|
427
|
+
else {
|
|
428
|
+
const newSessions = sessions.filter(s => s.id !== id);
|
|
429
|
+
setSessions(newSessions);
|
|
430
|
+
if (activeSessionId === id) {
|
|
431
|
+
setActiveSessionId(newSessions[0].id);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
};
|
|
435
|
+
return (React.createElement("div", { className: `chat-gpt-interface ${isSidebarOpen ? 'sidebar-open' : 'sidebar-closed'}` },
|
|
436
|
+
isSidebarOpen && React.createElement("div", { className: "sidebar-overlay", onClick: () => setIsSidebarOpen(false) }),
|
|
437
|
+
React.createElement("aside", { className: `chat-sidebar ${isSidebarOpen ? 'open' : ''}` },
|
|
438
|
+
React.createElement("div", { className: "sidebar-header" },
|
|
439
|
+
React.createElement("button", { className: "new-chat-sidebar-btn", onClick: createNewChat },
|
|
440
|
+
React.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
441
|
+
React.createElement("path", { d: "M12 5v14M5 12h14" })),
|
|
442
|
+
React.createElement("span", null, "New Chat")),
|
|
443
|
+
React.createElement("button", { className: "sidebar-toggle-mobile", onClick: () => setIsSidebarOpen(false) },
|
|
444
|
+
React.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
|
|
445
|
+
React.createElement("path", { d: "M18 6L6 18M6 6l12 12" })))),
|
|
446
|
+
React.createElement("div", { className: "sidebar-history" },
|
|
447
|
+
React.createElement("div", { className: "history-label" }, "Recent Chats"),
|
|
448
|
+
sessions.map(s => (React.createElement("div", { key: s.id, className: `history-item ${s.id === activeSessionId ? 'active' : ''}`, onClick: () => {
|
|
449
|
+
setActiveSessionId(s.id);
|
|
450
|
+
if (window.innerWidth < 768)
|
|
451
|
+
setIsSidebarOpen(false);
|
|
452
|
+
} },
|
|
453
|
+
React.createElement("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "item-icon" },
|
|
454
|
+
React.createElement("path", { d: "M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" })),
|
|
455
|
+
React.createElement("span", { className: "item-title" }, s.title),
|
|
456
|
+
React.createElement("button", { className: "delete-btn", onClick: (e) => deleteSession(s.id, e) },
|
|
457
|
+
React.createElement("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
|
|
458
|
+
React.createElement("path", { d: "M3 6h18M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2" }))))))),
|
|
459
|
+
React.createElement("div", { className: "sidebar-footer" },
|
|
460
|
+
React.createElement("div", { className: "user-profile" },
|
|
461
|
+
React.createElement("div", { className: "user-avatar-small" },
|
|
462
|
+
React.createElement("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2" },
|
|
366
463
|
React.createElement("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }),
|
|
367
|
-
React.createElement("circle", { cx: "12", cy: "7", r: "4" })))
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
React.createElement("
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
React.createElement("
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
464
|
+
React.createElement("circle", { cx: "12", cy: "7", r: "4" }))),
|
|
465
|
+
React.createElement("span", { className: "user-name" }, "Ibaa Ibrahim")))),
|
|
466
|
+
React.createElement("main", { className: "chat-main" },
|
|
467
|
+
React.createElement("header", { className: "chat-header" },
|
|
468
|
+
React.createElement("button", { className: "sidebar-toggle-btn", onClick: () => setIsSidebarOpen(!isSidebarOpen) },
|
|
469
|
+
React.createElement("svg", { width: "20", height: "20", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
470
|
+
React.createElement("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }),
|
|
471
|
+
React.createElement("line", { x1: "9", y1: "3", x2: "9", y2: "21" }))),
|
|
472
|
+
React.createElement("div", { className: "header-title" }, activeSession.title),
|
|
473
|
+
React.createElement("div", { className: "header-actions" })),
|
|
474
|
+
React.createElement("div", { className: "chat-scroll-area", ref: chatContainerRef, onScroll: handleScroll },
|
|
475
|
+
messages.length === 0 ? (React.createElement("div", { className: "empty-state-container" },
|
|
476
|
+
React.createElement("div", { className: "empty-state-content" },
|
|
477
|
+
React.createElement("div", { className: "logo-placeholder" },
|
|
478
|
+
React.createElement("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "1.5" },
|
|
479
|
+
React.createElement("path", { d: "M12 2a10 10 0 1 0 10 10A10 10 0 0 0 12 2zm0 18a8 8 0 1 1 8-8 8 8 0 0 1-8 8z" }),
|
|
480
|
+
React.createElement("path", { d: "M12 6v6l4 2" }))),
|
|
481
|
+
React.createElement("h2", null, "How can I help you today?"),
|
|
482
|
+
React.createElement("div", { className: "capabilities-grid" },
|
|
483
|
+
React.createElement("div", { className: "capability-card" }, "Generate a checklist for a project"),
|
|
484
|
+
React.createElement("div", { className: "capability-card" }, "Analyze this data set"),
|
|
485
|
+
React.createElement("div", { className: "capability-card" }, "Translate text to Spanish"))))) : (messages.map((m) => {
|
|
486
|
+
const isUser = m.role === "user";
|
|
487
|
+
return (React.createElement("div", { key: m.id, className: `message-row ${m.role}` },
|
|
488
|
+
React.createElement("div", { className: "message-content-container" },
|
|
489
|
+
React.createElement("div", { className: `avatar ${isUser ? 'user-avatar' : 'assistant-avatar'}` }, isUser ? (React.createElement("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
490
|
+
React.createElement("path", { d: "M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2" }),
|
|
491
|
+
React.createElement("circle", { cx: "12", cy: "7", r: "4" }))) : (React.createElement("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
492
|
+
React.createElement("rect", { x: "3", y: "11", width: "18", height: "10", rx: "2" }),
|
|
493
|
+
React.createElement("circle", { cx: "12", cy: "5", r: "2" }),
|
|
494
|
+
React.createElement("path", { d: "M12 7v4" }),
|
|
495
|
+
React.createElement("line", { x1: "8", y1: "16", x2: "8", y2: "16" }),
|
|
496
|
+
React.createElement("line", { x1: "16", y1: "16", x2: "16", y2: "16" })))),
|
|
497
|
+
React.createElement("div", { className: "text-content" }, isUser ? (React.createElement("p", { style: { whiteSpace: 'pre-wrap' } }, m.content)) : (React.createElement(React.Fragment, null,
|
|
498
|
+
!m.content && !m.status && !m.hasError && (React.createElement("div", { className: "typing-indicator", style: {
|
|
499
|
+
display: 'flex',
|
|
500
|
+
gap: '4px',
|
|
501
|
+
padding: '8px 0'
|
|
502
|
+
} },
|
|
503
|
+
React.createElement("span", { className: "dot", style: {
|
|
504
|
+
width: '8px',
|
|
505
|
+
height: '8px',
|
|
506
|
+
backgroundColor: '#94a3b8',
|
|
507
|
+
borderRadius: '50%',
|
|
508
|
+
animation: 'typingDot 1.4s infinite ease-in-out',
|
|
509
|
+
animationDelay: '0s'
|
|
510
|
+
} }),
|
|
511
|
+
React.createElement("span", { className: "dot", style: {
|
|
512
|
+
width: '8px',
|
|
513
|
+
height: '8px',
|
|
514
|
+
backgroundColor: '#94a3b8',
|
|
515
|
+
borderRadius: '50%',
|
|
516
|
+
animation: 'typingDot 1.4s infinite ease-in-out',
|
|
517
|
+
animationDelay: '0.2s'
|
|
518
|
+
} }),
|
|
519
|
+
React.createElement("span", { className: "dot", style: {
|
|
520
|
+
width: '8px',
|
|
521
|
+
height: '8px',
|
|
522
|
+
backgroundColor: '#94a3b8',
|
|
523
|
+
borderRadius: '50%',
|
|
524
|
+
animation: 'typingDot 1.4s infinite ease-in-out',
|
|
525
|
+
animationDelay: '0.4s'
|
|
526
|
+
} }),
|
|
527
|
+
React.createElement("style", null, `
|
|
404
528
|
@keyframes typingDot {
|
|
405
529
|
0%, 60%, 100% {
|
|
406
530
|
transform: translateY(0);
|
|
@@ -412,158 +536,179 @@ export const FullScreenChat = () => {
|
|
|
412
536
|
}
|
|
413
537
|
}
|
|
414
538
|
`))),
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
}
|
|
467
|
-
|
|
468
|
-
|
|
539
|
+
m.hasError && (React.createElement("div", { className: "error-message-container", style: {
|
|
540
|
+
display: 'flex',
|
|
541
|
+
flexDirection: 'column',
|
|
542
|
+
gap: '12px',
|
|
543
|
+
padding: '12px',
|
|
544
|
+
background: 'rgba(239, 68, 68, 0.1)',
|
|
545
|
+
border: '1px solid rgba(239, 68, 68, 0.2)',
|
|
546
|
+
borderRadius: '12px',
|
|
547
|
+
marginTop: '8px'
|
|
548
|
+
} },
|
|
549
|
+
React.createElement("div", { style: { display: 'flex', alignItems: 'center', gap: '8px', color: '#ef4444', fontSize: '0.9rem' } },
|
|
550
|
+
React.createElement("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
551
|
+
React.createElement("circle", { cx: "12", cy: "12", r: "10" }),
|
|
552
|
+
React.createElement("line", { x1: "12", y1: "8", x2: "12", y2: "12" }),
|
|
553
|
+
React.createElement("line", { x1: "12", y1: "16", x2: "12.01", y2: "16" })),
|
|
554
|
+
React.createElement("span", null, "Failed to get a response. Please try again.")),
|
|
555
|
+
React.createElement("button", { onClick: () => handleRetry(), style: {
|
|
556
|
+
alignSelf: 'flex-start',
|
|
557
|
+
background: '#ef4444',
|
|
558
|
+
color: 'white',
|
|
559
|
+
border: 'none',
|
|
560
|
+
padding: '6px 14px',
|
|
561
|
+
borderRadius: '6px',
|
|
562
|
+
fontSize: '0.85rem',
|
|
563
|
+
fontWeight: 500,
|
|
564
|
+
cursor: 'pointer',
|
|
565
|
+
display: 'flex',
|
|
566
|
+
alignItems: 'center',
|
|
567
|
+
gap: '6px',
|
|
568
|
+
transition: 'background 0.2s'
|
|
569
|
+
}, onMouseOver: (e) => { e.currentTarget.style.background = '#dc2626'; }, onMouseOut: (e) => { e.currentTarget.style.background = '#ef4444'; } },
|
|
570
|
+
React.createElement("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
571
|
+
React.createElement("path", { d: "M21 2v6h-6" }),
|
|
572
|
+
React.createElement("path", { d: "M3 12a9 9 0 0 1 15-6.7L21 8M3 12a9 9 0 0 0 15 6.7L21 16" }),
|
|
573
|
+
React.createElement("path", { d: "M3 22v-6h6" })),
|
|
574
|
+
"Retry"))),
|
|
575
|
+
React.createElement(ReactMarkdown, null, m.content),
|
|
576
|
+
m.role === 'assistant' && (() => {
|
|
577
|
+
console.log(`🔍 Button visibility for message ${m.id}:`, {
|
|
578
|
+
hasToolCalls: !!m.toolCalls,
|
|
579
|
+
toolCallsLength: m.toolCalls?.length || 0,
|
|
580
|
+
toolCalls: m.toolCalls,
|
|
581
|
+
animationComplete: m.animationComplete,
|
|
582
|
+
shouldShow: !!(m.toolCalls && m.toolCalls.length > 0 && m.animationComplete)
|
|
583
|
+
});
|
|
584
|
+
return null;
|
|
585
|
+
})(),
|
|
586
|
+
m.toolCalls && m.toolCalls.length > 0 && m.animationComplete && (React.createElement("div", { className: "tool-actions", style: { marginTop: '12px', display: 'flex', gap: '8px', flexWrap: 'wrap' } }, m.toolCalls.map((tool, idx) => (React.createElement("button", { key: idx, onClick: () => {
|
|
587
|
+
const handler = TOOL_HANDLERS[tool.tool];
|
|
588
|
+
if (handler && tool.data)
|
|
589
|
+
handler(tool.data);
|
|
590
|
+
}, style: {
|
|
591
|
+
background: 'linear-gradient(135deg, #6366f1 0%, #4f46e5 100%)',
|
|
592
|
+
border: 'none',
|
|
593
|
+
padding: '8px 16px',
|
|
594
|
+
borderRadius: '8px',
|
|
595
|
+
color: 'white',
|
|
596
|
+
fontSize: '0.85rem',
|
|
597
|
+
fontWeight: 500,
|
|
598
|
+
cursor: 'pointer',
|
|
599
|
+
display: 'flex',
|
|
600
|
+
alignItems: 'center',
|
|
601
|
+
gap: '6px',
|
|
602
|
+
boxShadow: '0 4px 6px -1px rgba(99, 102, 241, 0.3)',
|
|
603
|
+
transition: 'transform 0.2s, box-shadow 0.2s'
|
|
604
|
+
}, onMouseOver: (e) => { e.currentTarget.style.transform = 'translateY(-1px)'; }, onMouseOut: (e) => { e.currentTarget.style.transform = 'translateY(0)'; } },
|
|
605
|
+
React.createElement("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
606
|
+
React.createElement("path", { d: "M20 6L9 17l-5-5" })),
|
|
607
|
+
"View ",
|
|
608
|
+
tool.tool === 'generate_checklist' ? 'Checklist' : 'Result'))))),
|
|
609
|
+
m.status && (React.createElement("div", { className: "agent-status-indicator", style: {
|
|
610
|
+
marginTop: '8px',
|
|
611
|
+
fontSize: '0.8rem',
|
|
612
|
+
color: '#64748b',
|
|
613
|
+
display: 'flex',
|
|
614
|
+
alignItems: 'center',
|
|
615
|
+
gap: '6px',
|
|
616
|
+
fontStyle: 'italic'
|
|
617
|
+
} },
|
|
618
|
+
React.createElement("span", { className: "pulsing-dot", style: {
|
|
619
|
+
width: '6px',
|
|
620
|
+
height: '6px',
|
|
621
|
+
backgroundColor: '#6366f1',
|
|
622
|
+
borderRadius: '50%',
|
|
623
|
+
display: 'inline-block',
|
|
624
|
+
animation: 'pulse 1.5s infinite'
|
|
625
|
+
} }),
|
|
626
|
+
m.status,
|
|
627
|
+
React.createElement("style", null, `
|
|
469
628
|
@keyframes pulse {
|
|
470
629
|
0% { transform: scale(0.95); opacity: 0.7; }
|
|
471
630
|
50% { transform: scale(1.15); opacity: 1; }
|
|
472
631
|
100% { transform: scale(0.95); opacity: 0.7; }
|
|
473
632
|
}
|
|
474
633
|
`)))))))));
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
React.createElement("
|
|
514
|
-
React.createElement("
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
React.createElement("
|
|
521
|
-
React.createElement("div", { className: "
|
|
522
|
-
React.createElement("
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
React.createElement("
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
React.createElement("span", { className: "chevron" },
|
|
555
|
-
React.createElement("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
556
|
-
React.createElement("polyline", { points: "18 15 12 9 6 15" }))),
|
|
557
|
-
React.createElement("span", null, "GPT 4o-mini (High)")))),
|
|
558
|
-
React.createElement("div", { className: "right-controls" },
|
|
559
|
-
React.createElement("button", { className: `send-btn-circle ${input.trim() || isStreaming || animatingMessageId ? 'active' : ''}`, onClick: (isStreaming || animatingMessageId) ? handleStop : () => handleSend(input), disabled: (!input.trim() && !isStreaming && !animatingMessageId) }, (isStreaming || animatingMessageId) ? (
|
|
560
|
-
// Stop Square
|
|
561
|
-
React.createElement("svg", { viewBox: "0 0 24 24", fill: "currentColor" },
|
|
562
|
-
React.createElement("rect", { x: "3", y: "3", width: "18", height: "18", rx: "2", ry: "2" }))) : (
|
|
563
|
-
// Right Arrow
|
|
564
|
-
React.createElement("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
565
|
-
React.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" }),
|
|
566
|
-
React.createElement("polyline", { points: "12 5 19 12 12 19" })))))))),
|
|
567
|
-
React.createElement("div", { className: "footer-text" }, "Allowed to generate up to 2000 tokens per request."))));
|
|
634
|
+
})),
|
|
635
|
+
React.createElement("div", { ref: scrollEndRef })),
|
|
636
|
+
React.createElement("div", { className: "input-area-container" },
|
|
637
|
+
userScrolledUp && messages.length > 0 && (React.createElement("button", { className: "scroll-bottom-btn", onClick: handleScrollToBottom },
|
|
638
|
+
React.createElement("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
639
|
+
React.createElement("polyline", { points: "7 13 12 18 17 13" }),
|
|
640
|
+
React.createElement("polyline", { points: "7 6 12 11 17 6" })))),
|
|
641
|
+
React.createElement("div", { className: "input-wrapper" },
|
|
642
|
+
React.createElement("div", { className: "input-box user-specific-design" },
|
|
643
|
+
React.createElement("div", { className: "input-top-row" },
|
|
644
|
+
React.createElement("textarea", { ref: textareaRef, rows: 1, placeholder: "Ask anything (Ctrl+L), @ to mention, / for workflows", value: input, onChange: (e) => setInput(e.target.value), disabled: isStreaming || animatingMessageId !== null, onKeyDown: (e) => {
|
|
645
|
+
if (e.key === "Enter" && !e.shiftKey && !isStreaming && !animatingMessageId) {
|
|
646
|
+
e.preventDefault();
|
|
647
|
+
handleSend(input);
|
|
648
|
+
}
|
|
649
|
+
} })),
|
|
650
|
+
React.createElement("div", { className: "input-bottom-row" },
|
|
651
|
+
React.createElement("div", { className: "left-controls" },
|
|
652
|
+
React.createElement("div", { className: "tools-section" },
|
|
653
|
+
React.createElement("div", { className: `tools-menu custom-dropdown-menu ${activeDropdown === 'tools' ? 'show' : ''}` },
|
|
654
|
+
React.createElement("div", { className: "tool-option", onClick: () => setActiveDropdown(null) },
|
|
655
|
+
React.createElement("span", { className: "icon-box purple" },
|
|
656
|
+
React.createElement("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
657
|
+
React.createElement("path", { d: "M9 11l3 3L22 4" }),
|
|
658
|
+
React.createElement("path", { d: "M21 12v7a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h11" }))),
|
|
659
|
+
React.createElement("div", { className: "text" },
|
|
660
|
+
React.createElement("span", { className: "title" }, "Checklist"))),
|
|
661
|
+
React.createElement("div", { className: "tool-option", onClick: () => setActiveDropdown(null) },
|
|
662
|
+
React.createElement("span", { className: "icon-box blue" },
|
|
663
|
+
React.createElement("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
664
|
+
React.createElement("circle", { cx: "12", cy: "12", r: "10" }),
|
|
665
|
+
React.createElement("line", { x1: "2", y1: "12", x2: "22", y2: "12" }),
|
|
666
|
+
React.createElement("path", { d: "M12 2a15.3 15.3 0 0 1 4 10 15.3 15.3 0 0 1-4 10 15.3 15.3 0 0 1-4-10 15.3 15.3 0 0 1 4-10z" }))),
|
|
667
|
+
React.createElement("div", { className: "text" },
|
|
668
|
+
React.createElement("span", { className: "title" }, "Translate"))),
|
|
669
|
+
React.createElement("div", { className: "tool-option", onClick: () => setActiveDropdown(null) },
|
|
670
|
+
React.createElement("div", { className: "text", style: { paddingLeft: '4px', fontSize: '11px', color: '#666' } }, "More coming soon..."))),
|
|
671
|
+
React.createElement("button", { className: `control-btn plus-btn dropdown-trigger ${activeDropdown === 'tools' ? 'active' : ''}`, onClick: () => setActiveDropdown(activeDropdown === 'tools' ? null : 'tools'), title: "Add attachment / Tools" },
|
|
672
|
+
React.createElement("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
673
|
+
React.createElement("line", { x1: "12", y1: "5", x2: "12", y2: "19" }),
|
|
674
|
+
React.createElement("line", { x1: "5", y1: "12", x2: "19", y2: "12" })))),
|
|
675
|
+
React.createElement("div", { className: "tools-section" },
|
|
676
|
+
React.createElement("div", { className: `tools-menu custom-dropdown-menu ${activeDropdown === 'mode' ? 'show' : ''}`, style: { width: '120px' } },
|
|
677
|
+
React.createElement("div", { className: "tool-option", onClick: () => setActiveDropdown(null) },
|
|
678
|
+
React.createElement("div", { className: "text" },
|
|
679
|
+
React.createElement("span", { className: "title" }, "Fast"))),
|
|
680
|
+
React.createElement("div", { className: "tool-option", onClick: () => setActiveDropdown(null) },
|
|
681
|
+
React.createElement("div", { className: "text" },
|
|
682
|
+
React.createElement("span", { className: "title" }, "Balanced")))),
|
|
683
|
+
React.createElement("button", { className: `mode-pill-btn dropdown-trigger ${activeDropdown === 'mode' ? 'active-mode' : ''}`, onClick: () => setActiveDropdown(activeDropdown === 'mode' ? null : 'mode') },
|
|
684
|
+
React.createElement("span", { className: "chevron" },
|
|
685
|
+
React.createElement("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
686
|
+
React.createElement("polyline", { points: "18 15 12 9 6 15" }))),
|
|
687
|
+
React.createElement("span", null, "Fast"))),
|
|
688
|
+
React.createElement("div", { className: "tools-section" },
|
|
689
|
+
React.createElement("div", { className: `tools-menu custom-dropdown-menu ${activeDropdown === 'model' ? 'show' : ''}`, style: { width: '200px' } },
|
|
690
|
+
React.createElement("div", { className: "tool-option", onClick: () => setActiveDropdown(null) },
|
|
691
|
+
React.createElement("div", { className: "text" },
|
|
692
|
+
React.createElement("span", { className: "title" }, "GPT 4o-mini"))),
|
|
693
|
+
React.createElement("div", { className: "tool-option", onClick: () => setActiveDropdown(null) },
|
|
694
|
+
React.createElement("div", { className: "text" },
|
|
695
|
+
React.createElement("span", { className: "title" }, "GPT 4o"))),
|
|
696
|
+
React.createElement("div", { className: "tool-option", onClick: () => setActiveDropdown(null) },
|
|
697
|
+
React.createElement("div", { className: "text" },
|
|
698
|
+
React.createElement("span", { className: "title" }, "Gemini Pro 1.5")))),
|
|
699
|
+
React.createElement("button", { className: `mode-pill-btn active-mode dropdown-trigger ${activeDropdown === 'model' ? 'active-mode' : ''}`, onClick: () => setActiveDropdown(activeDropdown === 'model' ? null : 'model') },
|
|
700
|
+
React.createElement("span", { className: "chevron" },
|
|
701
|
+
React.createElement("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
702
|
+
React.createElement("polyline", { points: "18 15 12 9 6 15" }))),
|
|
703
|
+
React.createElement("span", null, "GPT 4o-mini (High)")))),
|
|
704
|
+
React.createElement("div", { className: "right-controls" },
|
|
705
|
+
React.createElement("button", { className: `send-btn-circle ${input.trim() || isStreaming || animatingMessageId ? 'active' : ''}`, onClick: (isStreaming || animatingMessageId) ? handleStop : () => handleSend(input), disabled: (!input.trim() && !isStreaming && !animatingMessageId) }, (isStreaming || animatingMessageId) ? (
|
|
706
|
+
// Stop Square
|
|
707
|
+
React.createElement("svg", { viewBox: "0 0 24 24", fill: "currentColor" },
|
|
708
|
+
React.createElement("rect", { x: "7", y: "7", width: "10", height: "10", rx: "1.5" }))) : (
|
|
709
|
+
// Up Arrow (ChatGPT style)
|
|
710
|
+
React.createElement("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "3", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
711
|
+
React.createElement("path", { d: "M12 19V5M5 12l7-7 7 7" })))))))),
|
|
712
|
+
React.createElement("div", { className: "footer-text" }, "Token budget and context are managed automatically.")))));
|
|
568
713
|
};
|
|
569
714
|
//# sourceMappingURL=index.js.map
|