@hef2024/llmasaservice-ui 0.20.1 → 0.20.3
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.css +66 -0
- package/dist/index.d.mts +3 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +177 -16
- package/dist/index.mjs +177 -16
- package/package.json +1 -1
- package/src/AIAgentPanel.tsx +146 -9
- package/src/AIChatPanel.css +82 -0
- package/src/AIChatPanel.tsx +82 -6
- package/src/components/ui/ToolInfoModal.tsx +3 -0
- package/src/hooks/useAgentRegistry.ts +0 -1
package/src/AIChatPanel.css
CHANGED
|
@@ -1575,6 +1575,88 @@
|
|
|
1575
1575
|
font-size: 10px;
|
|
1576
1576
|
}
|
|
1577
1577
|
|
|
1578
|
+
/* Detail Section Title Row (with toggle) */
|
|
1579
|
+
.ai-chat-context-popover__detail-section-title-row {
|
|
1580
|
+
display: flex;
|
|
1581
|
+
align-items: center;
|
|
1582
|
+
gap: 12px;
|
|
1583
|
+
flex: 1;
|
|
1584
|
+
min-width: 0;
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
/* Disabled Section Styling */
|
|
1588
|
+
.ai-chat-context-popover__detail-section--disabled {
|
|
1589
|
+
opacity: 0.6;
|
|
1590
|
+
}
|
|
1591
|
+
|
|
1592
|
+
.ai-chat-context-popover__detail-section--disabled .ai-chat-context-popover__detail-section-title {
|
|
1593
|
+
text-decoration: line-through;
|
|
1594
|
+
opacity: 0.7;
|
|
1595
|
+
}
|
|
1596
|
+
|
|
1597
|
+
/* Context Toggle Switch */
|
|
1598
|
+
.ai-chat-context-toggle {
|
|
1599
|
+
position: relative;
|
|
1600
|
+
display: inline-flex;
|
|
1601
|
+
width: 36px;
|
|
1602
|
+
height: 20px;
|
|
1603
|
+
cursor: pointer;
|
|
1604
|
+
user-select: none;
|
|
1605
|
+
flex-shrink: 0;
|
|
1606
|
+
}
|
|
1607
|
+
|
|
1608
|
+
.ai-chat-context-toggle__input {
|
|
1609
|
+
opacity: 0;
|
|
1610
|
+
width: 0;
|
|
1611
|
+
height: 0;
|
|
1612
|
+
position: absolute;
|
|
1613
|
+
}
|
|
1614
|
+
|
|
1615
|
+
.ai-chat-context-toggle__slider {
|
|
1616
|
+
position: absolute;
|
|
1617
|
+
top: 0;
|
|
1618
|
+
left: 0;
|
|
1619
|
+
right: 0;
|
|
1620
|
+
bottom: 0;
|
|
1621
|
+
background-color: #cbd5e1;
|
|
1622
|
+
transition: background-color 0.2s ease;
|
|
1623
|
+
border-radius: 20px;
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
.ai-chat-context-toggle__slider:before {
|
|
1627
|
+
position: absolute;
|
|
1628
|
+
content: "";
|
|
1629
|
+
height: 16px;
|
|
1630
|
+
width: 16px;
|
|
1631
|
+
left: 2px;
|
|
1632
|
+
bottom: 2px;
|
|
1633
|
+
background-color: white;
|
|
1634
|
+
transition: transform 0.2s ease;
|
|
1635
|
+
border-radius: 50%;
|
|
1636
|
+
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
|
|
1637
|
+
}
|
|
1638
|
+
|
|
1639
|
+
.ai-chat-context-toggle__input:checked + .ai-chat-context-toggle__slider {
|
|
1640
|
+
background-color: #3b82f6;
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
.ai-chat-context-toggle__input:checked + .ai-chat-context-toggle__slider:before {
|
|
1644
|
+
transform: translateX(16px);
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
.ai-chat-context-toggle:hover .ai-chat-context-toggle__slider {
|
|
1648
|
+
opacity: 0.9;
|
|
1649
|
+
}
|
|
1650
|
+
|
|
1651
|
+
/* Dark theme toggle */
|
|
1652
|
+
.dark-theme .ai-chat-context-toggle__slider {
|
|
1653
|
+
background-color: #4b5563;
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
.dark-theme .ai-chat-context-toggle__input:checked + .ai-chat-context-toggle__slider {
|
|
1657
|
+
background-color: #60a5fa;
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1578
1660
|
/* Detail Content */
|
|
1579
1661
|
.ai-chat-context-popover__detail-content {
|
|
1580
1662
|
margin: 0;
|
package/src/AIChatPanel.tsx
CHANGED
|
@@ -88,6 +88,8 @@ export interface AIChatPanelProps {
|
|
|
88
88
|
totalContextTokens?: number;
|
|
89
89
|
maxContextTokens?: number;
|
|
90
90
|
enableContextDetailView?: boolean;
|
|
91
|
+
disabledSectionIds?: Set<string>;
|
|
92
|
+
onToggleSection?: (sectionId: string, enabled: boolean) => void;
|
|
91
93
|
|
|
92
94
|
// Callback when a new conversation is created via API
|
|
93
95
|
onConversationCreated?: (conversationId: string) => void;
|
|
@@ -295,6 +297,8 @@ interface ChatInputProps {
|
|
|
295
297
|
totalContextTokens?: number;
|
|
296
298
|
maxContextTokens?: number;
|
|
297
299
|
enableContextDetailView?: boolean;
|
|
300
|
+
disabledSectionIds?: Set<string>;
|
|
301
|
+
onToggleSection?: (sectionId: string, enabled: boolean) => void;
|
|
298
302
|
onContextViewerToggle?: () => void;
|
|
299
303
|
}
|
|
300
304
|
|
|
@@ -313,11 +317,14 @@ const ChatInput = React.memo<ChatInputProps>(({
|
|
|
313
317
|
totalContextTokens = 0,
|
|
314
318
|
maxContextTokens = 8000,
|
|
315
319
|
enableContextDetailView = false,
|
|
320
|
+
disabledSectionIds = new Set(),
|
|
321
|
+
onToggleSection,
|
|
316
322
|
}) => {
|
|
317
323
|
const [inputValue, setInputValue] = useState('');
|
|
318
324
|
const [dropdownOpen, setDropdownOpen] = useState(false);
|
|
319
325
|
const [contextViewerOpen, setContextViewerOpen] = useState(false);
|
|
320
326
|
const [contextViewMode, setContextViewMode] = useState<'summary' | 'detail'>('summary');
|
|
327
|
+
const [expandedSectionId, setExpandedSectionId] = useState<string | null>(null);
|
|
321
328
|
const textareaRef = useRef<HTMLTextAreaElement | null>(null);
|
|
322
329
|
const containerRef = useRef<HTMLDivElement | null>(null);
|
|
323
330
|
const contextPopoverRef = useRef<HTMLDivElement | null>(null);
|
|
@@ -363,6 +370,7 @@ const ChatInput = React.memo<ChatInputProps>(({
|
|
|
363
370
|
if (contextPopoverRef.current && !contextPopoverRef.current.contains(event.target as Node)) {
|
|
364
371
|
setContextViewerOpen(false);
|
|
365
372
|
setContextViewMode('summary');
|
|
373
|
+
setExpandedSectionId(null);
|
|
366
374
|
}
|
|
367
375
|
};
|
|
368
376
|
if (contextViewerOpen) {
|
|
@@ -466,6 +474,9 @@ const ChatInput = React.memo<ChatInputProps>(({
|
|
|
466
474
|
setContextViewerOpen(!contextViewerOpen);
|
|
467
475
|
if (!contextViewerOpen) {
|
|
468
476
|
setContextViewMode('summary');
|
|
477
|
+
setExpandedSectionId(null);
|
|
478
|
+
} else {
|
|
479
|
+
setExpandedSectionId(null);
|
|
469
480
|
}
|
|
470
481
|
}}
|
|
471
482
|
type="button"
|
|
@@ -488,7 +499,10 @@ const ChatInput = React.memo<ChatInputProps>(({
|
|
|
488
499
|
<span className="ai-chat-context-popover__title">Context</span>
|
|
489
500
|
<button
|
|
490
501
|
className="ai-chat-context-popover__close"
|
|
491
|
-
onClick={() =>
|
|
502
|
+
onClick={() => {
|
|
503
|
+
setContextViewerOpen(false);
|
|
504
|
+
setExpandedSectionId(null);
|
|
505
|
+
}}
|
|
492
506
|
type="button"
|
|
493
507
|
>
|
|
494
508
|
×
|
|
@@ -517,6 +531,7 @@ const ChatInput = React.memo<ChatInputProps>(({
|
|
|
517
531
|
className={`ai-chat-context-popover__section-item ${enableContextDetailView ? 'ai-chat-context-popover__section-item--clickable' : ''}`}
|
|
518
532
|
onClick={() => {
|
|
519
533
|
if (enableContextDetailView) {
|
|
534
|
+
setExpandedSectionId(section.id);
|
|
520
535
|
setContextViewMode('detail');
|
|
521
536
|
}
|
|
522
537
|
}}
|
|
@@ -532,7 +547,10 @@ const ChatInput = React.memo<ChatInputProps>(({
|
|
|
532
547
|
{enableContextDetailView && (
|
|
533
548
|
<button
|
|
534
549
|
className="ai-chat-context-popover__expand-btn"
|
|
535
|
-
onClick={() =>
|
|
550
|
+
onClick={() => {
|
|
551
|
+
setExpandedSectionId(null);
|
|
552
|
+
setContextViewMode('detail');
|
|
553
|
+
}}
|
|
536
554
|
type="button"
|
|
537
555
|
>
|
|
538
556
|
View details →
|
|
@@ -547,7 +565,10 @@ const ChatInput = React.memo<ChatInputProps>(({
|
|
|
547
565
|
<div className="ai-chat-context-popover__header">
|
|
548
566
|
<button
|
|
549
567
|
className="ai-chat-context-popover__back"
|
|
550
|
-
onClick={() =>
|
|
568
|
+
onClick={() => {
|
|
569
|
+
setContextViewMode('summary');
|
|
570
|
+
setExpandedSectionId(null);
|
|
571
|
+
}}
|
|
551
572
|
type="button"
|
|
552
573
|
>
|
|
553
574
|
← Back
|
|
@@ -555,7 +576,10 @@ const ChatInput = React.memo<ChatInputProps>(({
|
|
|
555
576
|
<span className="ai-chat-context-popover__title">Context Details</span>
|
|
556
577
|
<button
|
|
557
578
|
className="ai-chat-context-popover__close"
|
|
558
|
-
onClick={() =>
|
|
579
|
+
onClick={() => {
|
|
580
|
+
setContextViewerOpen(false);
|
|
581
|
+
setExpandedSectionId(null);
|
|
582
|
+
}}
|
|
559
583
|
type="button"
|
|
560
584
|
>
|
|
561
585
|
×
|
|
@@ -580,10 +604,35 @@ const ChatInput = React.memo<ChatInputProps>(({
|
|
|
580
604
|
<div className="ai-chat-context-popover__detail-sections">
|
|
581
605
|
{contextSections.map((section) => {
|
|
582
606
|
const format = detectFormat(section.data);
|
|
607
|
+
const isEnabled = !disabledSectionIds.has(section.id);
|
|
583
608
|
return (
|
|
584
|
-
<details
|
|
609
|
+
<details
|
|
610
|
+
key={section.id}
|
|
611
|
+
className={`ai-chat-context-popover__detail-section ${!isEnabled ? 'ai-chat-context-popover__detail-section--disabled' : ''}`}
|
|
612
|
+
open={expandedSectionId === section.id}
|
|
613
|
+
>
|
|
585
614
|
<summary className="ai-chat-context-popover__detail-section-header">
|
|
586
|
-
<
|
|
615
|
+
<div className="ai-chat-context-popover__detail-section-title-row">
|
|
616
|
+
<span className="ai-chat-context-popover__detail-section-title">{section.title}</span>
|
|
617
|
+
<label
|
|
618
|
+
className="ai-chat-context-toggle"
|
|
619
|
+
onClick={(e) => e.stopPropagation()}
|
|
620
|
+
title={isEnabled ? "Disable this context section" : "Enable this context section"}
|
|
621
|
+
>
|
|
622
|
+
<input
|
|
623
|
+
type="checkbox"
|
|
624
|
+
checked={isEnabled}
|
|
625
|
+
onChange={(e) => {
|
|
626
|
+
e.stopPropagation();
|
|
627
|
+
if (onToggleSection) {
|
|
628
|
+
onToggleSection(section.id, !isEnabled);
|
|
629
|
+
}
|
|
630
|
+
}}
|
|
631
|
+
className="ai-chat-context-toggle__input"
|
|
632
|
+
/>
|
|
633
|
+
<span className="ai-chat-context-toggle__slider"></span>
|
|
634
|
+
</label>
|
|
635
|
+
</div>
|
|
587
636
|
<span className="ai-chat-context-popover__detail-section-meta">
|
|
588
637
|
<code>{`{{${section.id}}}`}</code>
|
|
589
638
|
<span>~{section.tokens || Math.ceil(JSON.stringify(section.data).length / 4)}</span>
|
|
@@ -701,6 +750,8 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
701
750
|
totalContextTokens = 0,
|
|
702
751
|
maxContextTokens = 8000,
|
|
703
752
|
enableContextDetailView = false,
|
|
753
|
+
disabledSectionIds: propDisabledSectionIds,
|
|
754
|
+
onToggleSection: propOnToggleSection,
|
|
704
755
|
onConversationCreated,
|
|
705
756
|
// UI Customization Props
|
|
706
757
|
cssUrl,
|
|
@@ -770,6 +821,11 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
770
821
|
const [sessionApprovedTools, setSessionApprovedTools] = useState<string[]>([]);
|
|
771
822
|
const [alwaysApprovedTools, setAlwaysApprovedTools] = useState<string[]>([]);
|
|
772
823
|
|
|
824
|
+
// Context section toggle state (disabled sections)
|
|
825
|
+
// Use internal state only if prop is not provided
|
|
826
|
+
const [internalDisabledSectionIds, setInternalDisabledSectionIds] = useState<Set<string>>(new Set());
|
|
827
|
+
const disabledSectionIds = propDisabledSectionIds ?? internalDisabledSectionIds;
|
|
828
|
+
|
|
773
829
|
// Email capture mode effect - like ChatPanel
|
|
774
830
|
useEffect(() => {
|
|
775
831
|
setShowEmailPanel(customerEmailCaptureMode !== 'HIDE');
|
|
@@ -891,6 +947,24 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
891
947
|
};
|
|
892
948
|
}, []);
|
|
893
949
|
|
|
950
|
+
// Handle toggling context sections on/off
|
|
951
|
+
const handleToggleSection = useCallback((sectionId: string, enabled: boolean) => {
|
|
952
|
+
// Use prop callback if provided, otherwise use internal state
|
|
953
|
+
if (propOnToggleSection) {
|
|
954
|
+
propOnToggleSection(sectionId, enabled);
|
|
955
|
+
} else {
|
|
956
|
+
setInternalDisabledSectionIds(prev => {
|
|
957
|
+
const next = new Set(prev);
|
|
958
|
+
if (enabled) {
|
|
959
|
+
next.delete(sectionId);
|
|
960
|
+
} else {
|
|
961
|
+
next.add(sectionId);
|
|
962
|
+
}
|
|
963
|
+
return next;
|
|
964
|
+
});
|
|
965
|
+
}
|
|
966
|
+
}, [propOnToggleSection]);
|
|
967
|
+
|
|
894
968
|
// Ensure a conversation exists before sending the first message
|
|
895
969
|
// This creates a conversation on the server and returns the conversation ID
|
|
896
970
|
const ensureConversation = useCallback(() => {
|
|
@@ -2633,6 +2707,8 @@ const AIChatPanel: React.FC<AIChatPanelProps> = ({
|
|
|
2633
2707
|
totalContextTokens={totalContextTokens}
|
|
2634
2708
|
maxContextTokens={maxContextTokens}
|
|
2635
2709
|
enableContextDetailView={enableContextDetailView}
|
|
2710
|
+
disabledSectionIds={disabledSectionIds}
|
|
2711
|
+
onToggleSection={handleToggleSection}
|
|
2636
2712
|
/>
|
|
2637
2713
|
|
|
2638
2714
|
{/* Footer */}
|