@sybilion/uilib 1.3.78 → 1.3.80
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/esm/components/ui/Chat/Chat.js +2 -2
- package/dist/esm/components/ui/Chat/Chat.styl.js +1 -1
- package/dist/esm/components/ui/Chat/ChatChrome/ChatChrome.js +10 -6
- package/dist/esm/components/ui/Chat/ChatChrome/ChatChrome.styl.js +2 -2
- package/dist/esm/components/ui/Chat/ChatEmptyState/ChatEmptyState.styl.js +1 -1
- package/dist/esm/components/ui/Chat/ChatMessage/ChatMessage.js +2 -2
- package/dist/esm/components/ui/Chat/ChatPresets/ChatPresets.styl.js +1 -1
- package/dist/esm/components/ui/Chat/ChatSheet/ChatSelector.js +2 -2
- package/dist/esm/components/ui/Chat/ChatSheet/ChatSheet.js +2 -1
- package/dist/esm/components/ui/Chat/ChatSheet/useChatPanelChromeModel.js +6 -5
- package/dist/esm/components/ui/Chat/buildChatSendMessagePayload.js +3 -1
- package/dist/esm/components/ui/FileChip/FileChip.js +4 -0
- package/dist/esm/components/widgets/DriversComparisonChart/driversComparisonChart.helpers.js +3 -1
- package/dist/esm/contexts/chat-context.js +51 -5
- package/dist/esm/index.js +1 -0
- package/dist/esm/types/src/components/ui/Chat/Chat.d.ts +1 -1
- package/dist/esm/types/src/components/ui/Chat/Chat.types.d.ts +12 -0
- package/dist/esm/types/src/components/ui/Chat/ChatChrome/ChatChrome.d.ts +1 -1
- package/dist/esm/types/src/components/ui/Chat/ChatChrome/ChatChrome.types.d.ts +4 -0
- package/dist/esm/types/src/components/ui/Chat/ChatMessage/ChatMessage.d.ts +1 -1
- package/dist/esm/types/src/components/ui/Chat/ChatSheet/ChatSelector.d.ts +2 -1
- package/dist/esm/types/src/components/ui/Chat/ChatSheet/ChatSheet.d.ts +1 -1
- package/dist/esm/types/src/components/ui/Chat/ChatSheet/useChatPanelChromeModel.d.ts +5 -3
- package/dist/esm/types/src/components/ui/Chat/index.d.ts +3 -1
- package/dist/esm/types/src/components/ui/FileChip/FileChip.types.d.ts +1 -1
- package/dist/esm/types/src/contexts/chat-context.d.ts +16 -4
- package/package.json +1 -1
- package/src/components/ui/Chat/Chat.styl +4 -1
- package/src/components/ui/Chat/Chat.tsx +2 -1
- package/src/components/ui/Chat/Chat.types.ts +14 -0
- package/src/components/ui/Chat/ChatChrome/ChatChrome.styl +20 -10
- package/src/components/ui/Chat/ChatChrome/ChatChrome.styl.d.ts +2 -0
- package/src/components/ui/Chat/ChatChrome/ChatChrome.tsx +27 -10
- package/src/components/ui/Chat/ChatChrome/ChatChrome.types.ts +4 -0
- package/src/components/ui/Chat/ChatEmptyState/ChatEmptyState.styl +1 -2
- package/src/components/ui/Chat/ChatMessage/ChatMessage.tsx +9 -1
- package/src/components/ui/Chat/ChatPresets/ChatPresets.styl +5 -4
- package/src/components/ui/Chat/ChatSheet/ChatSelector.tsx +3 -1
- package/src/components/ui/Chat/ChatSheet/ChatSheet.tsx +2 -0
- package/src/components/ui/Chat/ChatSheet/useChatPanelChromeModel.tsx +24 -5
- package/src/components/ui/Chat/buildChatSendMessagePayload.ts +2 -1
- package/src/components/ui/Chat/index.ts +4 -0
- package/src/components/ui/FileChip/FileChip.tsx +11 -0
- package/src/components/ui/FileChip/FileChip.types.ts +1 -1
- package/src/components/widgets/DriversComparisonChart/driversComparisonChart.helpers.test.ts +13 -4
- package/src/components/widgets/DriversComparisonChart/driversComparisonChart.helpers.ts +2 -1
- package/src/contexts/chat-context.tsx +80 -6
- package/src/docs/pages/ChatPage.styl +6 -0
- package/src/docs/pages/ChatPage.styl.d.ts +7 -0
- package/src/docs/pages/ChatPage.tsx +30 -87
- package/src/docs/pages/ChatSlashCommandsPage.tsx +4 -4
|
@@ -7,8 +7,8 @@ import { ChatMessage } from './ChatMessage/ChatMessage.js';
|
|
|
7
7
|
import { ChatPrompt } from './ChatPrompt/ChatPrompt.js';
|
|
8
8
|
import { ChatSelector } from './ChatSheet/ChatSelector.js';
|
|
9
9
|
|
|
10
|
-
function Chat({ children, className, isEmpty, scopeId, onChatDeleted, onNewChat, ...props }) {
|
|
11
|
-
return (jsxs("div", { className: cn(S.root, className, isEmpty && S.isEmpty), ...props, children: [scopeId ? (jsx("div", { className: S.header, children: jsx(ChatSelector, { id: scopeId, onChatDeleted: onChatDeleted, onNewChat: onNewChat }) })) : null, children] }));
|
|
10
|
+
function Chat({ children, className, isEmpty, scopeId, onChatDeleted, onNewChat, hideChatSelector = false, ...props }) {
|
|
11
|
+
return (jsxs("div", { className: cn(S.root, className, isEmpty && S.isEmpty), ...props, children: [scopeId && !hideChatSelector ? (jsx("div", { className: S.header, children: jsx(ChatSelector, { id: scopeId, onChatDeleted: onChatDeleted, onNewChat: onNewChat }) })) : null, children] }));
|
|
12
12
|
}
|
|
13
13
|
Chat.Prompt = ChatPrompt;
|
|
14
14
|
Chat.Message = ChatMessage;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import styleInject from 'style-inject';
|
|
2
2
|
|
|
3
|
-
var css_248z = ".Chat_root__IWt99{background-color:var(--background);display:flex;flex-direction:column;height:100%;min-height:0}.Chat_header__ZjwP-{align-items:center;display:flex;flex-shrink:0;min-height:64px;padding:var(--p-2) var(--p-6) 0;padding-right:var(--p-12)}.Chat_isEmpty__b4ViB{
|
|
3
|
+
var css_248z = ".Chat_root__IWt99{background-color:var(--background);display:flex;flex:1;flex-direction:column;height:100%;min-height:0}.Chat_header__ZjwP-{align-items:center;display:flex;flex-shrink:0;min-height:64px;padding:var(--p-2) var(--p-6) 0;padding-right:var(--p-12)}.Chat_isEmpty__b4ViB{flex:1;min-height:0;overflow:hidden}";
|
|
4
4
|
var S = {"root":"Chat_root__IWt99","header":"Chat_header__ZjwP-","isEmpty":"Chat_isEmpty__b4ViB"};
|
|
5
5
|
styleInject(css_248z);
|
|
6
6
|
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { jsxs, jsx
|
|
1
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import cn from 'classnames';
|
|
3
3
|
import { useMemo, useState, useCallback, useEffect } from 'react';
|
|
4
4
|
import { displayLabelForBranchKeyFromMessages, humanizeBranchKey } from '../ChatMessage/presetScript.js';
|
|
@@ -10,17 +10,19 @@ import { DropZone } from '../../DropZone/DropZone.js';
|
|
|
10
10
|
import { PanelResizeHandle } from '../../Sidebar/Sidebar.js';
|
|
11
11
|
import SidebarStem from '../../Sidebar/Sidebar.styl.js';
|
|
12
12
|
import { Chat } from '../Chat.js';
|
|
13
|
+
import { MessageRole } from '../Chat.types.js';
|
|
13
14
|
import { filterToTextAttachments, isAttachmentsDropzoneEnabled, buildAcceptAttr } from '../chatAttachmentAccept.js';
|
|
14
15
|
import { extractChatAttachmentItems } from '../chatAttachmentExtract.js';
|
|
15
16
|
import S from './ChatChrome.styl.js';
|
|
16
17
|
|
|
17
|
-
function ChatChrome({ showResizeHandle, resizeHandle, onClose, isEmpty, renderPresets, messages, onQuickReply, suppressedQuickReplyKeys, isLoading, loadingLabel, scriptContinueLabel, onScriptContinue, renderMessageChart, showSyntheticBranchButtons, unusedBranchKeys, showInlinePresets, isLastMessageFromUser, scrollRef, effectiveScopeId, onPromptSubmit, onChatDeleted, onNewChat, promptPrefill, footerClassName, emptyState, allowedAttachments, allowPdfAttachments = false, onAttachmentsDropped, slashCommandItems, onSlashItemCommand, promptPlaceholder, }) {
|
|
18
|
+
function ChatChrome({ showResizeHandle, resizeHandle, onClose, isEmpty, renderPresets, messages, onQuickReply, suppressedQuickReplyKeys, isLoading, loadingLabel, scriptContinueLabel, onScriptContinue, renderMessageChart, renderSystemMessage, showSyntheticBranchButtons, unusedBranchKeys, showInlinePresets, isLastMessageFromUser, scrollRef, effectiveScopeId, onPromptSubmit, onChatDeleted, onNewChat, promptPrefill, footerClassName, emptyState, allowedAttachments, allowPdfAttachments = false, onAttachmentsDropped, slashCommandItems, onSlashItemCommand, promptPlaceholder, hideChatSelector = false, }) {
|
|
18
19
|
const filteredAllowedAttachments = useMemo(() => filterToTextAttachments(allowedAttachments), [allowedAttachments]);
|
|
19
20
|
const attachmentsDropzoneEnabled = isAttachmentsDropzoneEnabled(allowedAttachments, allowPdfAttachments);
|
|
20
21
|
const attachmentAccept = useMemo(() => buildAcceptAttr(filteredAllowedAttachments, allowPdfAttachments), [filteredAllowedAttachments, allowPdfAttachments]);
|
|
21
22
|
const [pendingAttachments, setPendingAttachments] = useState([]);
|
|
22
23
|
const [isExtractingAttachments, setIsExtractingAttachments] = useState(false);
|
|
23
24
|
const promptDisabled = isExtractingAttachments;
|
|
25
|
+
const hasInProgressSystemMessage = useMemo(() => messages.some(msg => msg.role === MessageRole.SYSTEM && msg.inProgress === true), [messages]);
|
|
24
26
|
const handleAttachmentFiles = useCallback((files) => {
|
|
25
27
|
if (promptDisabled || files.length === 0)
|
|
26
28
|
return;
|
|
@@ -74,18 +76,20 @@ function ChatChrome({ showResizeHandle, resizeHandle, onClose, isEmpty, renderPr
|
|
|
74
76
|
showInlinePresets,
|
|
75
77
|
showSyntheticBranchButtons,
|
|
76
78
|
]);
|
|
77
|
-
return (jsxs("div", { className: S.root, children: [showResizeHandle && resizeHandle ? (jsx(PanelResizeHandle, { edge: "leading", isActive: resizeHandle.isActive, startWidthPx: resizeHandle.startWidthPx, getShellWidth: resizeHandle.getShellWidth, onDragWidth: resizeHandle.onDragWidth, onDragComplete: resizeHandle.onDragComplete, className: cn(SidebarStem.sidebarResizeHandle, S.chatResizeHandle) })) : null, jsx("div", { className: S.panelHeader, children: onClose ? (jsx(Button, { type: "button", variant: "ghost", icon: true, className: S.panelClose, "aria-label": "Close chat", onClick: onClose, children: jsx(X, { className: "size-4" }) })) : null }), jsxs("div", { className: S.content, children: [attachmentsDropzoneEnabled ? (jsx(DropZone, { accept: attachmentAccept, label: "Drop text files to attach", multiple: true, ghost: true, overlayScope: "container", disabled: promptDisabled, className: S.attachmentDropzone, onFiles: handleAttachmentFiles })) : null, jsxs(Chat, { isEmpty: isEmpty, scopeId: effectiveScopeId, onChatDeleted: onChatDeleted, onNewChat: onNewChat, children: [isEmpty ? (
|
|
79
|
+
return (jsxs("div", { className: S.root, children: [showResizeHandle && resizeHandle ? (jsx(PanelResizeHandle, { edge: "leading", isActive: resizeHandle.isActive, startWidthPx: resizeHandle.startWidthPx, getShellWidth: resizeHandle.getShellWidth, onDragWidth: resizeHandle.onDragWidth, onDragComplete: resizeHandle.onDragComplete, className: cn(SidebarStem.sidebarResizeHandle, S.chatResizeHandle) })) : null, jsx("div", { className: S.panelHeader, children: onClose ? (jsx(Button, { type: "button", variant: "ghost", icon: true, className: S.panelClose, "aria-label": "Close chat", onClick: onClose, children: jsx(X, { className: "size-4" }) })) : null }), jsxs("div", { className: S.content, children: [attachmentsDropzoneEnabled ? (jsx(DropZone, { accept: attachmentAccept, label: "Drop text files to attach", multiple: true, ghost: true, overlayScope: "container", disabled: promptDisabled, className: S.attachmentDropzone, onFiles: handleAttachmentFiles })) : null, jsxs(Chat, { isEmpty: isEmpty, scopeId: effectiveScopeId, onChatDeleted: onChatDeleted, onNewChat: onNewChat, hideChatSelector: hideChatSelector, children: [isEmpty ? (jsx("div", { className: S.emptyBody, children: jsx(Chat.EmptyState, { ...emptyState }) })) : (jsx("div", { className: S.scrollWrapper, children: jsxs(Scroll, { y: true, yScrollbarClassName: S.scrollbar, className: S.scroll, innerClassName: S.scrollInner, offset: { y: { before: 56, after: 24 } }, fadeSize: "m", autoHide: true, ref: scrollRef, children: [messages.map((msg, index, arr) => {
|
|
78
80
|
const isLast = index === arr.length - 1;
|
|
79
|
-
return (jsx(Chat.Message, { role: msg.role, text: msg.text, inProgress: msg.inProgress, userTextFileAttachments: msg.userTextFileAttachments, onQuickReply: onQuickReply, suppressedQuickReplyKeys: suppressedQuickReplyKeys, quickReplyDisabled: isLoading, quickReplyHidden: Boolean(loadingLabel), isLastMessage: isLast, scriptContinue: isLast && scriptContinueLabel
|
|
81
|
+
return (jsx(Chat.Message, { message: msg, role: msg.role, text: msg.text, inProgress: msg.inProgress, userTextFileAttachments: msg.userTextFileAttachments, onQuickReply: onQuickReply, suppressedQuickReplyKeys: suppressedQuickReplyKeys, quickReplyDisabled: isLoading, quickReplyHidden: Boolean(loadingLabel), isLastMessage: isLast, scriptContinue: isLast && scriptContinueLabel
|
|
80
82
|
? { label: scriptContinueLabel }
|
|
81
83
|
: undefined, onScriptContinue: isLast && scriptContinueLabel
|
|
82
84
|
? onScriptContinue
|
|
83
|
-
: undefined, renderMessageChart: renderMessageChart }, msg.id));
|
|
85
|
+
: undefined, renderMessageChart: renderMessageChart, renderSystemMessage: renderSystemMessage }, msg.id));
|
|
84
86
|
}), showSyntheticBranchButtons ? (jsx("div", { className: S.branchRow, children: unusedBranchKeys.map(key => {
|
|
85
87
|
const label = displayLabelForBranchKeyFromMessages(key, messages) ??
|
|
86
88
|
humanizeBranchKey(key);
|
|
87
89
|
return (jsx("span", { className: S.branchBtnWrap, children: jsxs(Button, { type: "button", variant: "outline", size: "sm", disabled: isLoading, onClick: () => onQuickReply(key, label), children: [jsx(PaperPlaneRightIcon, {}), label] }) }, key));
|
|
88
|
-
}) })) : null, showInlinePresets && renderPresets('inline'), isLoading &&
|
|
90
|
+
}) })) : null, showInlinePresets && renderPresets('inline'), isLoading &&
|
|
91
|
+
!hasInProgressSystemMessage &&
|
|
92
|
+
(isLastMessageFromUser || loadingLabel) && (jsx(TextShimmer, { duration: 1, spread: 5, className: S.loader, children: loadingLabel ?? 'Thinking...' }))] }) })), isEmpty ? (jsx("div", { className: S.fixedPresets, children: renderPresets('fixed') })) : null, jsxs("div", { className: cn(S.footer, footerClassName), children: [isEmpty ? (jsx("div", { className: S.notice, children: "Forecast Assistant can make mistakes." })) : null, jsx(Chat.Prompt, { onSubmit: handlePromptSubmitWithAttachments, disabled: promptDisabled, attachments: pendingAttachments, onRemoveAttachment: handleRemoveAttachment, prefillMessage: promptPrefill ?? undefined, placeholder: promptPlaceholder, slashCommandItems: slashCommandItems, onSlashItemCommand: onSlashItemCommand, attachmentAccept: attachmentsDropzoneEnabled ? attachmentAccept : undefined, onAttachmentFiles: attachmentsDropzoneEnabled ? handleAttachmentFiles : undefined })] })] })] })] }));
|
|
89
93
|
}
|
|
90
94
|
|
|
91
95
|
export { ChatChrome };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import styleInject from 'style-inject';
|
|
2
2
|
|
|
3
|
-
var css_248z = "@media (max-width:768px){:root{--page-x-padding:var(--p-6);--page-y-padding:var(--p-6)}}.ChatChrome_root__oh4Ay{border-radius:var(--p-4);display:flex;flex-direction:column;height:100%;min-height:0;overflow:hidden;position:relative}.ChatChrome_chatResizeHandle__epfiT{background-color:var(--page-color);border-radius:2.5px;height:calc(100vh + 200px);left:0;opacity:0;position:absolute;right:auto;top:-200px;touch-action:none;transition:opacity .15s ease-out;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:5px;z-index:30}.ChatChrome_chatResizeHandle__epfiT:before{left:0;right:auto}.ChatChrome_panelHeader__Hkfit{align-items:center;display:flex;flex-shrink:0;justify-content:flex-end;min-height:70px;padding:var(--p-2) var(--p-3);position:absolute;width:100%;z-index:100}.ChatChrome_panelClose__DbKxz{flex-shrink:0}.ChatChrome_content__5qFEi{display:flex;flex:1;flex-direction:column;min-height:0;position:relative}.ChatChrome_attachmentDropzone__OC8UI{inset:0;position:absolute;z-index:200}.ChatChrome_scrollWrapper__m4HMu{flex:1;min-height:0;position:relative}.ChatChrome_scroll__oCxoJ{align-items:flex-end;height:100%;max-height:100%;max-width:100%;padding-bottom:var(--p-2);position:absolute;width:100%;z-index:3}.ChatChrome_scrollbar__Hu0aG{right:0!important}.ChatChrome_scrollInner__K9hIy{min-height:100%;padding-top:var(--p-10)}.
|
|
4
|
-
var S = {"root":"ChatChrome_root__oh4Ay","chatResizeHandle":"ChatChrome_chatResizeHandle__epfiT","panelHeader":"ChatChrome_panelHeader__Hkfit","panelClose":"ChatChrome_panelClose__DbKxz","content":"ChatChrome_content__5qFEi","attachmentDropzone":"ChatChrome_attachmentDropzone__OC8UI","scrollWrapper":"ChatChrome_scrollWrapper__m4HMu","scroll":"ChatChrome_scroll__oCxoJ","scrollbar":"ChatChrome_scrollbar__Hu0aG","scrollInner":"ChatChrome_scrollInner__K9hIy","footer":"ChatChrome_footer__a5Bpp","notice":"ChatChrome_notice__JACIw","loader":"ChatChrome_loader__9-lnf","branchRow":"ChatChrome_branchRow__NMDNv","branchBtnWrap":"ChatChrome_branchBtnWrap__aOSVP"};
|
|
3
|
+
var css_248z = "@media (max-width:768px){:root{--page-x-padding:var(--p-6);--page-y-padding:var(--p-6)}}.ChatChrome_root__oh4Ay{border-radius:var(--p-4);display:flex;flex-direction:column;height:100%;min-height:0;overflow:hidden;position:relative}.ChatChrome_chatResizeHandle__epfiT{background-color:var(--page-color);border-radius:2.5px;height:calc(100vh + 200px);left:0;opacity:0;position:absolute;right:auto;top:-200px;touch-action:none;transition:opacity .15s ease-out;-webkit-user-select:none;-moz-user-select:none;user-select:none;width:5px;z-index:30}.ChatChrome_chatResizeHandle__epfiT:before{left:0;right:auto}.ChatChrome_panelHeader__Hkfit{align-items:center;display:flex;flex-shrink:0;justify-content:flex-end;min-height:70px;padding:var(--p-2) var(--p-3);position:absolute;width:100%;z-index:100}.ChatChrome_panelClose__DbKxz{flex-shrink:0}.ChatChrome_content__5qFEi{display:flex;flex:1;flex-direction:column;min-height:0;position:relative}.ChatChrome_attachmentDropzone__OC8UI{inset:0;position:absolute;z-index:200}.ChatChrome_scrollWrapper__m4HMu{flex:1;min-height:0;position:relative}.ChatChrome_scroll__oCxoJ{align-items:flex-end;height:100%;max-height:100%;max-width:100%;padding-bottom:var(--p-2);position:absolute;width:100%;z-index:3}.ChatChrome_scrollbar__Hu0aG{right:0!important}.ChatChrome_scrollInner__K9hIy{min-height:100%;padding-top:var(--p-10)}.ChatChrome_emptyBody__f2NE8{display:flex;flex:1;flex-direction:column;min-height:0;overflow:hidden}.ChatChrome_emptyBody__f2NE8>*{flex:1;min-height:0;overflow:auto}.ChatChrome_footer__a5Bpp{backdrop-filter:blur(30px);background-color:var(--background-alpha-800);border-top:1px solid var(--border);box-shadow:0 8px 24px 0 var(--background);display:flex;flex-direction:column;flex-shrink:0;position:relative;width:100%;z-index:50}.ChatChrome_fixedPresets__bONhR{flex-shrink:0;position:relative;width:100%;z-index:10}.ChatChrome_notice__JACIw{color:var(--muted-foreground);font-size:var(--text-xs);left:0;margin-bottom:var(--p-1);pointer-events:none;position:absolute;right:0;text-align:center;top:calc(var(--p-7)*-1)}@media (max-width:768px){.ChatChrome_notice__JACIw{font-size:10px}}.ChatChrome_loader__9-lnf{color:var(--muted-foreground);margin:var(--p-2) var(--p-6) var(--p-10)}.ChatChrome_branchRow__NMDNv{display:flex;flex-wrap:wrap;gap:8px;margin-top:var(--p-6);padding:0 var(--p-6);width:100%}.ChatChrome_branchBtnWrap__aOSVP{display:inline-flex;vertical-align:middle}";
|
|
4
|
+
var S = {"root":"ChatChrome_root__oh4Ay","chatResizeHandle":"ChatChrome_chatResizeHandle__epfiT","panelHeader":"ChatChrome_panelHeader__Hkfit","panelClose":"ChatChrome_panelClose__DbKxz","content":"ChatChrome_content__5qFEi","attachmentDropzone":"ChatChrome_attachmentDropzone__OC8UI","scrollWrapper":"ChatChrome_scrollWrapper__m4HMu","scroll":"ChatChrome_scroll__oCxoJ","scrollbar":"ChatChrome_scrollbar__Hu0aG","scrollInner":"ChatChrome_scrollInner__K9hIy","emptyBody":"ChatChrome_emptyBody__f2NE8","footer":"ChatChrome_footer__a5Bpp","fixedPresets":"ChatChrome_fixedPresets__bONhR","notice":"ChatChrome_notice__JACIw","loader":"ChatChrome_loader__9-lnf","branchRow":"ChatChrome_branchRow__NMDNv","branchBtnWrap":"ChatChrome_branchBtnWrap__aOSVP"};
|
|
5
5
|
styleInject(css_248z);
|
|
6
6
|
|
|
7
7
|
export { S as default };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import styleInject from 'style-inject';
|
|
2
2
|
|
|
3
|
-
var css_248z = ".ChatEmptyState_root__j1n-C{align-items:center;color:var(--text-secondary);display:flex;flex:1;flex-direction:column;font-size:var(--text-sm);gap:var(--p-10);justify-content:center;padding:var(--p-6);text-align:center;text-wrap:balance}.ChatEmptyState_icon__YSDgv,.ChatEmptyState_icon__YSDgv>svg{height:32px;width:32px}";
|
|
3
|
+
var css_248z = ".ChatEmptyState_root__j1n-C{align-items:center;color:var(--text-secondary);display:flex;flex:1;flex-direction:column;font-size:var(--text-sm);gap:var(--p-10);justify-content:center;min-height:0;padding:var(--p-6);text-align:center;text-wrap:balance}.ChatEmptyState_icon__YSDgv,.ChatEmptyState_icon__YSDgv>svg{height:32px;width:32px}";
|
|
4
4
|
var S = {"root":"ChatEmptyState_root__j1n-C","icon":"ChatEmptyState_icon__YSDgv"};
|
|
5
5
|
styleInject(css_248z);
|
|
6
6
|
|
|
@@ -10,13 +10,13 @@ import { AgentMessageContent } from './AgentMessageContent.js';
|
|
|
10
10
|
import S from './ChatMessage.styl.js';
|
|
11
11
|
import { UserTextFileAttachmentBubble } from './UserTextFileAttachmentBubble.js';
|
|
12
12
|
|
|
13
|
-
function ChatMessage({ role, text, inProgress, userTextFileAttachments, onQuickReply, suppressedQuickReplyKeys, quickReplyDisabled, quickReplyHidden, isLastMessage = true, scriptContinue, onScriptContinue, renderMessageChart, }) {
|
|
13
|
+
function ChatMessage({ role, text, inProgress, userTextFileAttachments, onQuickReply, suppressedQuickReplyKeys, quickReplyDisabled, quickReplyHidden, isLastMessage = true, scriptContinue, onScriptContinue, renderMessageChart, message, renderSystemMessage, }) {
|
|
14
14
|
const fileAttachments = userTextFileAttachmentsFromMessage({
|
|
15
15
|
userTextFileAttachments,
|
|
16
16
|
});
|
|
17
17
|
const isAssistant = role === MessageRole.ASSISTANT;
|
|
18
18
|
const isSystem = role === MessageRole.SYSTEM;
|
|
19
|
-
return (jsx("div", { className: cn(S.root, S[`role-${role}`]), children: isSystem ? (jsx("div", { className: S.text, children: inProgress ? jsx(TextShimmer, { as: "span", children: text }) : text })) : isAssistant ? (jsx(AgentMessageContent, { text: text, onQuickReply: onQuickReply, suppressedQuickReplyKeys: suppressedQuickReplyKeys, quickReplyDisabled: quickReplyDisabled, quickReplyHidden: quickReplyHidden, isLastMessage: isLastMessage, scriptContinue: scriptContinue, onScriptContinue: onScriptContinue, renderMessageChart: renderMessageChart })) : (jsxs("div", { className: S.userColumn, children: [jsx("div", { className: S.text, children: jsx(InteractiveContent, { text: text }) }), fileAttachments.map(attachment => (jsx(UserTextFileAttachmentBubble, { attachment: attachment }, `${attachment.displayName}:${attachment.filename}`)))] })) }));
|
|
19
|
+
return (jsx("div", { className: cn(S.root, S[`role-${role}`]), children: isSystem ? (jsx("div", { className: S.text, children: inProgress ? (jsx(TextShimmer, { as: "span", children: text })) : renderSystemMessage && message ? (renderSystemMessage(message)) : (text) })) : isAssistant ? (jsx(AgentMessageContent, { text: text, onQuickReply: onQuickReply, suppressedQuickReplyKeys: suppressedQuickReplyKeys, quickReplyDisabled: quickReplyDisabled, quickReplyHidden: quickReplyHidden, isLastMessage: isLastMessage, scriptContinue: scriptContinue, onScriptContinue: onScriptContinue, renderMessageChart: renderMessageChart })) : (jsxs("div", { className: S.userColumn, children: [jsx("div", { className: S.text, children: jsx(InteractiveContent, { text: text }) }), fileAttachments.map(attachment => (jsx(UserTextFileAttachmentBubble, { attachment: attachment }, `${attachment.displayName}:${attachment.filename}`)))] })) }));
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
export { ChatMessage };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import styleInject from 'style-inject';
|
|
2
2
|
|
|
3
|
-
var css_248z = ".ChatPresets_root__Cj42o{
|
|
3
|
+
var css_248z = ".ChatPresets_root__Cj42o{flex-shrink:0;position:relative;width:100%}.ChatPresets_inlineRoot__WXVnu{margin-top:var(--p-6);position:relative;width:100%}.ChatPresets_inner__h14-q{background-color:var(--background);display:flex;flex-wrap:wrap;gap:8px;min-width:0;padding:var(--p-2) var(--p-6) var(--p-3)}.ChatPresets_innerInline__iPM2b{background-color:transparent}.ChatPresets_item__LfX5b{flex:0 1 auto;font-size:var(--text-xs);height:auto;line-height:1.4;max-width:min(300px,100%);min-height:auto;min-width:0;overflow-wrap:anywhere;padding:var(--p-3);text-align:left;white-space:break-spaces!important}";
|
|
4
4
|
var S = {"root":"ChatPresets_root__Cj42o","inlineRoot":"ChatPresets_inlineRoot__WXVnu","inner":"ChatPresets_inner__h14-q","innerInline":"ChatPresets_innerInline__iPM2b","item":"ChatPresets_item__LfX5b"};
|
|
5
5
|
styleInject(css_248z);
|
|
6
6
|
|
|
@@ -6,7 +6,7 @@ import { Button } from '../../Button/Button.js';
|
|
|
6
6
|
import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from '../../Select/Select.js';
|
|
7
7
|
import S from './ChatSelector.styl.js';
|
|
8
8
|
|
|
9
|
-
function ChatSelector({ id, className, onChatDeleted, onNewChat, }) {
|
|
9
|
+
function ChatSelector({ id, wrapperClassName, className, onChatDeleted, onNewChat, }) {
|
|
10
10
|
const { chats, currentChatId, setCurrentChatId, newChat, deleteChat } = useChatsForScopeId(id);
|
|
11
11
|
const handleValueChange = (value) => {
|
|
12
12
|
if (value === 'new') {
|
|
@@ -39,7 +39,7 @@ function ChatSelector({ id, className, onChatDeleted, onNewChat, }) {
|
|
|
39
39
|
}
|
|
40
40
|
return 'New chat';
|
|
41
41
|
};
|
|
42
|
-
return (jsxs("div", { className: S.wrapper, children: [jsx("div", { className: S.selectGrow, children: jsxs(Select, { variant: "clear", value: currentChatId?.toString() ?? '', onValueChange: handleValueChange, children: [jsx(SelectTrigger, { size: "sm", className: className ? cn(S.selectTrigger, className) : S.selectTrigger, children: jsx(SelectValue, { placeholder: "Select chat" }) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: "new", children: "+ New Chat" }), chats.map(chat => (jsx(SelectItem, { value: chat.session_id.toString(), selected: chat.session_id === currentChatId, children: getChatDisplayName(chat) }, chat.session_id)))] })] }) }), currentChatId && chats.length > 0 && (jsx(Button, { type: "button", variant: "ghost", size: "sm", className: S.deleteBtn, "aria-label": "Delete chat", onClick: handleDeleteChat, children: jsx(Trash2Icon, { size: 16 }) }))] }));
|
|
42
|
+
return (jsxs("div", { className: cn(S.wrapper, wrapperClassName), children: [jsx("div", { className: S.selectGrow, children: jsxs(Select, { variant: "clear", value: currentChatId?.toString() ?? '', onValueChange: handleValueChange, children: [jsx(SelectTrigger, { size: "sm", className: className ? cn(S.selectTrigger, className) : S.selectTrigger, children: jsx(SelectValue, { placeholder: "Select chat" }) }), jsxs(SelectContent, { children: [jsx(SelectItem, { value: "new", children: "+ New Chat" }), chats.map(chat => (jsx(SelectItem, { value: chat.session_id.toString(), selected: chat.session_id === currentChatId, children: getChatDisplayName(chat) }, chat.session_id)))] })] }) }), currentChatId && chats.length > 0 && (jsx(Button, { type: "button", variant: "ghost", size: "sm", className: S.deleteBtn, "aria-label": "Delete chat", onClick: handleDeleteChat, children: jsx(Trash2Icon, { size: 16 }) }))] }));
|
|
43
43
|
}
|
|
44
44
|
|
|
45
45
|
export { ChatSelector };
|
|
@@ -4,7 +4,7 @@ import { Button } from '../../Button/Button.js';
|
|
|
4
4
|
import { ChatChrome } from '../ChatChrome/ChatChrome.js';
|
|
5
5
|
import { useChatPanelChromeModel } from './useChatPanelChromeModel.js';
|
|
6
6
|
|
|
7
|
-
function ChatSheet({ triggerLabel = 'Open Chat', triggerAriaLabel, actionsRef, renderTrigger, presets, scopeId, onMessage, onScriptComplete, renderMessageChart, emptyState, allowedAttachments, allowPdfAttachments, onAttachmentsDropped, slashCommandItems, onSlashItemCommand, transformSendPayload, inline = false, }) {
|
|
7
|
+
function ChatSheet({ triggerLabel = 'Open Chat', triggerAriaLabel, actionsRef, renderTrigger, presets, scopeId, onMessage, onScriptComplete, renderMessageChart, renderSystemMessage, emptyState, allowedAttachments, allowPdfAttachments, onAttachmentsDropped, slashCommandItems, onSlashItemCommand, transformSendPayload, inline = false, }) {
|
|
8
8
|
const model = useChatPanelChromeModel({
|
|
9
9
|
embedAsPage: inline,
|
|
10
10
|
presets,
|
|
@@ -12,6 +12,7 @@ function ChatSheet({ triggerLabel = 'Open Chat', triggerAriaLabel, actionsRef, r
|
|
|
12
12
|
onMessage,
|
|
13
13
|
onScriptComplete,
|
|
14
14
|
renderMessageChart,
|
|
15
|
+
renderSystemMessage,
|
|
15
16
|
emptyState,
|
|
16
17
|
allowedAttachments,
|
|
17
18
|
allowPdfAttachments,
|
|
@@ -22,7 +22,7 @@ const CHAT_NEW_SHORTCUT_KEY = 'o';
|
|
|
22
22
|
const CHAT_QUERY_PARAM = 'chat';
|
|
23
23
|
const CHAT_OPEN_VALUE = 'open';
|
|
24
24
|
const PROMPT_QUERY_PARAM = 'prompt';
|
|
25
|
-
function useChatPanelChromeModel({ embedAsPage, presets, scopeId, onMessage, onScriptComplete, renderMessageChart, emptyState, allowedAttachments, allowPdfAttachments, onAttachmentsDropped, slashCommandItems, onSlashItemCommand, copyHistoryOnNewChat = false, transformSendPayload, }) {
|
|
25
|
+
function useChatPanelChromeModel({ embedAsPage, presets, scopeId, onMessage, onScriptComplete, renderMessageChart, renderSystemMessage, emptyState, allowedAttachments, allowPdfAttachments, onAttachmentsDropped, slashCommandItems, onSlashItemCommand, copyHistoryOnNewChat = false, transformSendPayload, }) {
|
|
26
26
|
const effectiveScopeId = scopeId ?? NO_SCOPE_FALLBACK;
|
|
27
27
|
const isMobile = useIsMobile();
|
|
28
28
|
const { chatPanelContainer, isOpen: sidebarNavOpen, setOpen: setSidebarNavOpen, sidebarWidthPx, chatWidthPx, setChatWidthPx, getShellWidth, chatPanelOpen: shellChatPanelOpen, setChatPanelOpen, } = useSidebar();
|
|
@@ -336,8 +336,8 @@ function useChatPanelChromeModel({ embedAsPage, presets, scopeId, onMessage, onS
|
|
|
336
336
|
}
|
|
337
337
|
setOutboundLoadingLabel(loadingLabelFromSendPayload(payload));
|
|
338
338
|
try {
|
|
339
|
-
const assistantResponse = await sendMessage(payload);
|
|
340
|
-
onMessage?.(displayTextFromSendPayload(payload), assistantResponse);
|
|
339
|
+
const { response: assistantResponse, sessionId } = await sendMessage(payload);
|
|
340
|
+
onMessage?.(displayTextFromSendPayload(payload), assistantResponse, sessionId);
|
|
341
341
|
}
|
|
342
342
|
finally {
|
|
343
343
|
setOutboundLoadingLabel(undefined);
|
|
@@ -474,8 +474,8 @@ function useChatPanelChromeModel({ embedAsPage, presets, scopeId, onMessage, onS
|
|
|
474
474
|
}
|
|
475
475
|
setOutboundLoadingLabel(loadingLabelFromSendPayload(payload));
|
|
476
476
|
try {
|
|
477
|
-
const assistantResponse = await sendMessage(payload);
|
|
478
|
-
onMessage?.(displayTextFromSendPayload(payload), assistantResponse);
|
|
477
|
+
const { response: assistantResponse, sessionId } = await sendMessage(payload);
|
|
478
|
+
onMessage?.(displayTextFromSendPayload(payload), assistantResponse, sessionId);
|
|
479
479
|
}
|
|
480
480
|
finally {
|
|
481
481
|
setOutboundLoadingLabel(undefined);
|
|
@@ -916,6 +916,7 @@ function useChatPanelChromeModel({ embedAsPage, presets, scopeId, onMessage, onS
|
|
|
916
916
|
scriptContinueLabel,
|
|
917
917
|
onScriptContinue,
|
|
918
918
|
renderMessageChart,
|
|
919
|
+
renderSystemMessage,
|
|
919
920
|
showSyntheticBranchButtons,
|
|
920
921
|
unusedBranchKeys,
|
|
921
922
|
showInlinePresets,
|
|
@@ -68,7 +68,9 @@ function displayTextFromSendPayload(message) {
|
|
|
68
68
|
}
|
|
69
69
|
/** Optional loading shimmer label from a structured send payload. */
|
|
70
70
|
function loadingLabelFromSendPayload(message) {
|
|
71
|
-
|
|
71
|
+
if (typeof message === 'string')
|
|
72
|
+
return undefined;
|
|
73
|
+
return message.loadingLabel ?? message.systemProgressLabel;
|
|
72
74
|
}
|
|
73
75
|
|
|
74
76
|
export { buildChatSendMessagePayload, displayTextFromSendPayload, loadingLabelFromSendPayload, normalizeUserTextFileAttachments };
|
|
@@ -3,6 +3,7 @@ import cn from 'classnames';
|
|
|
3
3
|
import { CsvIcon } from '../../icons/CsvIcon/CsvIcon.js';
|
|
4
4
|
import { CardHeader, CardAction } from '../Card/Card.js';
|
|
5
5
|
import { XIcon, FileTextIcon } from '@phosphor-icons/react';
|
|
6
|
+
import { LayoutDashboard } from 'lucide-react';
|
|
6
7
|
import S from './FileChip.styl.js';
|
|
7
8
|
|
|
8
9
|
const FORMAT_ICON_SIZE = 32;
|
|
@@ -10,6 +11,9 @@ function FormatIcon({ format }) {
|
|
|
10
11
|
if (format === 'csv') {
|
|
11
12
|
return jsx(CsvIcon, { size: FORMAT_ICON_SIZE });
|
|
12
13
|
}
|
|
14
|
+
if (format === 'dashboard') {
|
|
15
|
+
return (jsx(LayoutDashboard, { size: FORMAT_ICON_SIZE, "aria-hidden": true, style: { color: 'var(--muted-foreground)' } }));
|
|
16
|
+
}
|
|
13
17
|
return (jsx(FileTextIcon, { size: FORMAT_ICON_SIZE, "aria-hidden": true, style: { color: 'var(--muted-foreground)' } }));
|
|
14
18
|
}
|
|
15
19
|
function FileChipHeader({ name, format, hint, onRemove, }) {
|
package/dist/esm/components/widgets/DriversComparisonChart/driversComparisonChart.helpers.js
CHANGED
|
@@ -97,12 +97,14 @@ function shiftNormalizedSeriesBackward(series, lagMonths) {
|
|
|
97
97
|
function applyDriversComparisonViewToPayload(payload, tab) {
|
|
98
98
|
if (!payload || tab === 'lagged')
|
|
99
99
|
return payload;
|
|
100
|
+
if (!payload.target?.normalized_series)
|
|
101
|
+
return payload;
|
|
100
102
|
return {
|
|
101
103
|
target: {
|
|
102
104
|
...payload.target,
|
|
103
105
|
normalized_series: { ...payload.target.normalized_series },
|
|
104
106
|
},
|
|
105
|
-
drivers: payload.drivers.map(driver => {
|
|
107
|
+
drivers: (payload.drivers ?? []).map(driver => {
|
|
106
108
|
const lagMonths = parseLagMonthsFromLabel(resolveDriverLagLabel(driver));
|
|
107
109
|
const series = driver.normalized_series ?? {};
|
|
108
110
|
const normalized_series = lagMonths != null && lagMonths > 0
|
|
@@ -86,6 +86,7 @@ function cloneMessagesForNewSession(messages) {
|
|
|
86
86
|
.filter(message => !message.inProgress)
|
|
87
87
|
.map(message => ({
|
|
88
88
|
...message,
|
|
89
|
+
...(message.meta ? { meta: { ...message.meta } } : {}),
|
|
89
90
|
...(message.userTextFileAttachments
|
|
90
91
|
? {
|
|
91
92
|
userTextFileAttachments: message.userTextFileAttachments.map(attachment => ({ ...attachment })),
|
|
@@ -217,6 +218,7 @@ function ChatProvider({ children, userSwitchKey, sendChatMessage: sendChatMessag
|
|
|
217
218
|
? { userTextFileAttachments: attachments }
|
|
218
219
|
: {}),
|
|
219
220
|
...(options?.inProgress ? { inProgress: true } : {}),
|
|
221
|
+
...(options?.meta ? { meta: { ...options.meta } } : {}),
|
|
220
222
|
};
|
|
221
223
|
setChats(prev => {
|
|
222
224
|
const scopeChats = prev[scopeId] ?? [];
|
|
@@ -277,6 +279,9 @@ function ChatProvider({ children, userSwitchKey, sendChatMessage: sendChatMessag
|
|
|
277
279
|
(patch.role != null && patch.role !== MessageRole.SYSTEM)) {
|
|
278
280
|
delete next.inProgress;
|
|
279
281
|
}
|
|
282
|
+
if (patch.meta != null) {
|
|
283
|
+
next.meta = { ...next.meta, ...patch.meta };
|
|
284
|
+
}
|
|
280
285
|
return next;
|
|
281
286
|
}),
|
|
282
287
|
};
|
|
@@ -290,7 +295,10 @@ function ChatProvider({ children, userSwitchKey, sendChatMessage: sendChatMessag
|
|
|
290
295
|
if (userSwitchKey === null)
|
|
291
296
|
return;
|
|
292
297
|
addScopeIdToRegistry(scopeId);
|
|
293
|
-
const cloned = messages.map(message => ({
|
|
298
|
+
const cloned = messages.map(message => ({
|
|
299
|
+
...message,
|
|
300
|
+
...(message.meta ? { meta: { ...message.meta } } : {}),
|
|
301
|
+
}));
|
|
294
302
|
setChats(prev => {
|
|
295
303
|
const scopeChats = prev[scopeId] ?? [];
|
|
296
304
|
const updatedChats = scopeChats.map(chat => {
|
|
@@ -303,6 +311,24 @@ function ChatProvider({ children, userSwitchKey, sendChatMessage: sendChatMessag
|
|
|
303
311
|
return { ...prev, [scopeId]: updatedChats };
|
|
304
312
|
});
|
|
305
313
|
}, [userSwitchKey]);
|
|
314
|
+
const updateChatMeta = useCallback((scopeId, chatId, patch) => {
|
|
315
|
+
if (userSwitchKey === null)
|
|
316
|
+
return;
|
|
317
|
+
setChats(prev => {
|
|
318
|
+
const scopeChats = prev[scopeId] ?? [];
|
|
319
|
+
const updatedChats = scopeChats.map(chat => {
|
|
320
|
+
if (chat.session_id !== chatId)
|
|
321
|
+
return chat;
|
|
322
|
+
return {
|
|
323
|
+
...chat,
|
|
324
|
+
meta: { ...chat.meta, ...patch },
|
|
325
|
+
};
|
|
326
|
+
});
|
|
327
|
+
const chatsKey = getChatsKey(scopeId);
|
|
328
|
+
LS.set(chatsKey, updatedChats);
|
|
329
|
+
return { ...prev, [scopeId]: updatedChats };
|
|
330
|
+
});
|
|
331
|
+
}, [userSwitchKey]);
|
|
306
332
|
const sendMessage = useCallback(async (scopeId, message, chatId) => {
|
|
307
333
|
const targetChatId = chatId ?? getCurrentChatId(scopeId);
|
|
308
334
|
if (targetChatId === null || targetChatId === '') {
|
|
@@ -317,10 +343,19 @@ function ChatProvider({ children, userSwitchKey, sendChatMessage: sendChatMessag
|
|
|
317
343
|
userTextFileAttachments: normalizeUserTextFileAttachments(message),
|
|
318
344
|
});
|
|
319
345
|
}
|
|
346
|
+
let progressMessageId;
|
|
347
|
+
if (typeof message !== 'string' && message.systemProgressLabel) {
|
|
348
|
+
progressMessageId = addMessage(scopeId, targetChatId, MessageRole.SYSTEM, message.systemProgressLabel, { inProgress: true });
|
|
349
|
+
}
|
|
320
350
|
const pendingChatSessionId = targetChatId;
|
|
321
351
|
beginOutboundPending(scopeId, pendingChatSessionId);
|
|
352
|
+
let effectiveSessionId = pendingChatSessionId;
|
|
322
353
|
try {
|
|
323
354
|
const data = await sendChatMessageFn(apiPayload, pendingChatSessionId);
|
|
355
|
+
effectiveSessionId =
|
|
356
|
+
data.session_id && data.session_id !== pendingChatSessionId
|
|
357
|
+
? data.session_id
|
|
358
|
+
: pendingChatSessionId;
|
|
324
359
|
if (data.session_id && data.session_id !== pendingChatSessionId) {
|
|
325
360
|
setChats(prev => {
|
|
326
361
|
const scopeChats = prev[scopeId] ?? [];
|
|
@@ -333,14 +368,21 @@ function ChatProvider({ children, userSwitchKey, sendChatMessage: sendChatMessag
|
|
|
333
368
|
});
|
|
334
369
|
setCurrentChatId(scopeId, data.session_id);
|
|
335
370
|
}
|
|
336
|
-
|
|
337
|
-
|
|
371
|
+
if (progressMessageId) {
|
|
372
|
+
removeMessageById(scopeId, effectiveSessionId, progressMessageId);
|
|
373
|
+
progressMessageId = undefined;
|
|
374
|
+
}
|
|
375
|
+
addMessage(scopeId, effectiveSessionId, MessageRole.ASSISTANT, data.response);
|
|
376
|
+
return { response: data.response, sessionId: effectiveSessionId };
|
|
338
377
|
}
|
|
339
378
|
catch (error) {
|
|
379
|
+
if (progressMessageId) {
|
|
380
|
+
removeMessageById(scopeId, effectiveSessionId, progressMessageId);
|
|
381
|
+
}
|
|
340
382
|
const errorMessage = error instanceof Error
|
|
341
383
|
? error.message
|
|
342
384
|
: 'Sorry, I encountered an error processing your message. Please try again.';
|
|
343
|
-
addMessage(scopeId,
|
|
385
|
+
addMessage(scopeId, effectiveSessionId, MessageRole.ASSISTANT, errorMessage);
|
|
344
386
|
throw error;
|
|
345
387
|
}
|
|
346
388
|
finally {
|
|
@@ -348,6 +390,7 @@ function ChatProvider({ children, userSwitchKey, sendChatMessage: sendChatMessag
|
|
|
348
390
|
}
|
|
349
391
|
}, [
|
|
350
392
|
addMessage,
|
|
393
|
+
removeMessageById,
|
|
351
394
|
beginOutboundPending,
|
|
352
395
|
endOutboundPending,
|
|
353
396
|
getCurrentChatId,
|
|
@@ -381,6 +424,7 @@ function ChatProvider({ children, userSwitchKey, sendChatMessage: sendChatMessag
|
|
|
381
424
|
removeMessageById,
|
|
382
425
|
updateMessageById,
|
|
383
426
|
setChatMessages,
|
|
427
|
+
updateChatMeta,
|
|
384
428
|
sendMessage,
|
|
385
429
|
getChatsForScopeId,
|
|
386
430
|
getCurrentChatId,
|
|
@@ -441,7 +485,7 @@ function useSyncChatPanelBusy(isLoading) {
|
|
|
441
485
|
}, [isLoading, acquirePanelBusy, releasePanelBusy]);
|
|
442
486
|
}
|
|
443
487
|
function useChatsForScopeId(scopeId) {
|
|
444
|
-
const { getChatsForScopeId, getCurrentChatId, setCurrentChatId, newChat, addMessage, removeMessageById, updateMessageById, sendMessage, deleteChat, } = useChats();
|
|
488
|
+
const { getChatsForScopeId, getCurrentChatId, setCurrentChatId, newChat, addMessage, removeMessageById, updateMessageById, updateChatMeta, setChatMessages, sendMessage, deleteChat, } = useChats();
|
|
445
489
|
const chats = getChatsForScopeId(scopeId);
|
|
446
490
|
const currentChatId = getCurrentChatId(scopeId);
|
|
447
491
|
const currentChat = useChat(scopeId, currentChatId ?? undefined);
|
|
@@ -457,6 +501,8 @@ function useChatsForScopeId(scopeId) {
|
|
|
457
501
|
removeMessageById: (chatId, messageId) => removeMessageById(scopeId, chatId, messageId),
|
|
458
502
|
updateMessageById: (chatId, messageId, patch) => updateMessageById(scopeId, chatId, messageId, patch),
|
|
459
503
|
sendMessage: (message, chatId) => sendMessage(scopeId, message, chatId),
|
|
504
|
+
updateChatMeta: (chatId, patch) => updateChatMeta(scopeId, chatId, patch),
|
|
505
|
+
setChatMessages: (chatId, messages) => setChatMessages(scopeId, chatId, messages),
|
|
460
506
|
deleteChat: (sessionId) => deleteChat(scopeId, sessionId),
|
|
461
507
|
};
|
|
462
508
|
}
|
package/dist/esm/index.js
CHANGED
|
@@ -29,6 +29,7 @@ export { ChatChrome } from './components/ui/Chat/ChatChrome/ChatChrome.js';
|
|
|
29
29
|
export { TEXT_ATTACHMENT_ACCEPT_PARTS, filterToTextAttachments } from './components/ui/Chat/chatAttachmentAccept.js';
|
|
30
30
|
export { buildChatSendMessagePayload, displayTextFromSendPayload, normalizeUserTextFileAttachments } from './components/ui/Chat/buildChatSendMessagePayload.js';
|
|
31
31
|
export { sanitizeAttachmentFilename } from './components/ui/Chat/sanitizeAttachmentFilename.js';
|
|
32
|
+
export { ChatSelector } from './components/ui/Chat/ChatSheet/ChatSelector.js';
|
|
32
33
|
export { ChatSheet } from './components/ui/Chat/ChatSheet/ChatSheet.js';
|
|
33
34
|
export { useChatPanelChromeModel } from './components/ui/Chat/ChatSheet/useChatPanelChromeModel.js';
|
|
34
35
|
export { ChatMessage } from './components/ui/Chat/ChatMessage/ChatMessage.js';
|
|
@@ -2,7 +2,7 @@ import { ChatPresets } from '#uilib/components/ui/Chat/ChatPresets';
|
|
|
2
2
|
import type { ChatProps } from './Chat.types';
|
|
3
3
|
import { ChatEmptyState } from './ChatEmptyState/ChatEmptyState';
|
|
4
4
|
import { ChatMessage } from './ChatMessage';
|
|
5
|
-
export declare function Chat({ children, className, isEmpty, scopeId, onChatDeleted, onNewChat, ...props }: ChatProps): import("react/jsx-runtime").JSX.Element;
|
|
5
|
+
export declare function Chat({ children, className, isEmpty, scopeId, onChatDeleted, onNewChat, hideChatSelector, ...props }: ChatProps): import("react/jsx-runtime").JSX.Element;
|
|
6
6
|
export declare namespace Chat {
|
|
7
7
|
var Prompt: import("react").ForwardRefExoticComponent<import("./Chat.types").ChatPromptProps & import("react").RefAttributes<import(".").ChatPromptComposerHandle>>;
|
|
8
8
|
var Message: typeof ChatMessage;
|
|
@@ -21,7 +21,11 @@ export type ChatSendMessagePayload = {
|
|
|
21
21
|
omitUserMessage?: boolean;
|
|
22
22
|
/** Shimmer label while waiting on the API; defaults to "Thinking...". */
|
|
23
23
|
loadingLabel?: string;
|
|
24
|
+
/** When set, show as a SYSTEM inProgress bubble instead of the footer shimmer. */
|
|
25
|
+
systemProgressLabel?: string;
|
|
24
26
|
};
|
|
27
|
+
export type ChatMetaValue = string | number | boolean | null;
|
|
28
|
+
export type ChatMeta = Record<string, ChatMetaValue>;
|
|
25
29
|
export interface Message {
|
|
26
30
|
id: string;
|
|
27
31
|
role: MessageRole;
|
|
@@ -30,11 +34,13 @@ export interface Message {
|
|
|
30
34
|
userTextFileAttachments?: UserTextFileAttachment[];
|
|
31
35
|
/** SYSTEM-only: transient progress placeholder while work is in flight. */
|
|
32
36
|
inProgress?: boolean;
|
|
37
|
+
meta?: ChatMeta;
|
|
33
38
|
}
|
|
34
39
|
export interface Chat {
|
|
35
40
|
session_id: string;
|
|
36
41
|
name: string;
|
|
37
42
|
messages: Message[];
|
|
43
|
+
meta?: ChatMeta;
|
|
38
44
|
}
|
|
39
45
|
export interface ChatPreset {
|
|
40
46
|
id: string;
|
|
@@ -111,6 +117,10 @@ export interface ChatMessageProps {
|
|
|
111
117
|
onScriptContinue?: () => void;
|
|
112
118
|
/** Renders `[CHART]` placeholder in assistant messages (app supplies dataset chart). */
|
|
113
119
|
renderMessageChart?: () => ReactNode;
|
|
120
|
+
/** Full message for system-role render delegation. */
|
|
121
|
+
message?: Message;
|
|
122
|
+
/** When set, SYSTEM messages render via this callback instead of plain text. */
|
|
123
|
+
renderSystemMessage?: (message: Message) => ReactNode;
|
|
114
124
|
}
|
|
115
125
|
export interface ChatProps extends HTMLAttributes<HTMLDivElement> {
|
|
116
126
|
children: ReactNode;
|
|
@@ -121,4 +131,6 @@ export interface ChatProps extends HTMLAttributes<HTMLDivElement> {
|
|
|
121
131
|
onChatDeleted?: (sessionId: string) => void;
|
|
122
132
|
/** "+ New Chat" in the selector; when omitted, starts an empty session. */
|
|
123
133
|
onNewChat?: () => void;
|
|
134
|
+
/** When true, skip built-in header ChatSelector (e.g. external page-header slot). */
|
|
135
|
+
hideChatSelector?: boolean;
|
|
124
136
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ChatChromeProps } from './ChatChrome.types';
|
|
2
|
-
export declare function ChatChrome({ showResizeHandle, resizeHandle, onClose, isEmpty, renderPresets, messages, onQuickReply, suppressedQuickReplyKeys, isLoading, loadingLabel, scriptContinueLabel, onScriptContinue, renderMessageChart, showSyntheticBranchButtons, unusedBranchKeys, showInlinePresets, isLastMessageFromUser, scrollRef, effectiveScopeId, onPromptSubmit, onChatDeleted, onNewChat, promptPrefill, footerClassName, emptyState, allowedAttachments, allowPdfAttachments, onAttachmentsDropped, slashCommandItems, onSlashItemCommand, promptPlaceholder, }: ChatChromeProps): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare function ChatChrome({ showResizeHandle, resizeHandle, onClose, isEmpty, renderPresets, messages, onQuickReply, suppressedQuickReplyKeys, isLoading, loadingLabel, scriptContinueLabel, onScriptContinue, renderMessageChart, renderSystemMessage, showSyntheticBranchButtons, unusedBranchKeys, showInlinePresets, isLastMessageFromUser, scrollRef, effectiveScopeId, onPromptSubmit, onChatDeleted, onNewChat, promptPrefill, footerClassName, emptyState, allowedAttachments, allowPdfAttachments, onAttachmentsDropped, slashCommandItems, onSlashItemCommand, promptPlaceholder, hideChatSelector, }: ChatChromeProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -28,6 +28,8 @@ export interface ChatChromeProps {
|
|
|
28
28
|
scriptContinueLabel: string | undefined;
|
|
29
29
|
onScriptContinue: (() => void) | undefined;
|
|
30
30
|
renderMessageChart?: () => React.ReactNode;
|
|
31
|
+
/** When set, SYSTEM messages render via this callback instead of plain text. */
|
|
32
|
+
renderSystemMessage?: (message: Message) => React.ReactNode;
|
|
31
33
|
showSyntheticBranchButtons: boolean;
|
|
32
34
|
unusedBranchKeys: string[];
|
|
33
35
|
showInlinePresets: boolean;
|
|
@@ -54,4 +56,6 @@ export interface ChatChromeProps {
|
|
|
54
56
|
onSlashItemCommand?: SlashOnItemCommand;
|
|
55
57
|
/** Composer placeholder forwarded to `Chat.Prompt`. */
|
|
56
58
|
promptPlaceholder?: string;
|
|
59
|
+
/** When true, skip built-in header ChatSelector (e.g. external page-header slot). */
|
|
60
|
+
hideChatSelector?: boolean;
|
|
57
61
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { type ChatMessageProps } from '../Chat.types';
|
|
2
|
-
export declare function ChatMessage({ role, text, inProgress, userTextFileAttachments, onQuickReply, suppressedQuickReplyKeys, quickReplyDisabled, quickReplyHidden, isLastMessage, scriptContinue, onScriptContinue, renderMessageChart, }: ChatMessageProps): import("react/jsx-runtime").JSX.Element;
|
|
2
|
+
export declare function ChatMessage({ role, text, inProgress, userTextFileAttachments, onQuickReply, suppressedQuickReplyKeys, quickReplyDisabled, quickReplyHidden, isLastMessage, scriptContinue, onScriptContinue, renderMessageChart, message, renderSystemMessage, }: ChatMessageProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export interface ChatSelectorProps {
|
|
2
2
|
id: string;
|
|
3
|
+
wrapperClassName?: string;
|
|
3
4
|
className?: string;
|
|
4
5
|
onChatDeleted?: (sessionId: string) => void;
|
|
5
6
|
/** When set, used for "+ New Chat" instead of the default empty `newChat()`. */
|
|
6
7
|
onNewChat?: () => void;
|
|
7
8
|
}
|
|
8
|
-
export declare function ChatSelector({ id, className, onChatDeleted, onNewChat, }: ChatSelectorProps): import("react/jsx-runtime").JSX.Element;
|
|
9
|
+
export declare function ChatSelector({ id, wrapperClassName, className, onChatDeleted, onNewChat, }: ChatSelectorProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -21,4 +21,4 @@ export interface ChatSheetProps extends Omit<UseChatPanelChromeModelInput, 'embe
|
|
|
21
21
|
*/
|
|
22
22
|
inline?: boolean;
|
|
23
23
|
}
|
|
24
|
-
export declare function ChatSheet({ triggerLabel, triggerAriaLabel, actionsRef, renderTrigger, presets, scopeId, onMessage, onScriptComplete, renderMessageChart, emptyState, allowedAttachments, allowPdfAttachments, onAttachmentsDropped, slashCommandItems, onSlashItemCommand, transformSendPayload, inline, }: ChatSheetProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
export declare function ChatSheet({ triggerLabel, triggerAriaLabel, actionsRef, renderTrigger, presets, scopeId, onMessage, onScriptComplete, renderMessageChart, renderSystemMessage, emptyState, allowedAttachments, allowPdfAttachments, onAttachmentsDropped, slashCommandItems, onSlashItemCommand, transformSendPayload, inline, }: ChatSheetProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ChatPreset, type ChatSendMessagePayload, type ScriptCompletePayload } from '#uilib/components/ui/Chat/Chat.types';
|
|
1
|
+
import { ChatPreset, type ChatSendMessagePayload, type Message, type ScriptCompletePayload } from '#uilib/components/ui/Chat/Chat.types';
|
|
2
2
|
import type { SlashCommandItem, SlashOnItemCommand } from '#uilib/tiptap/slash-mention/types';
|
|
3
3
|
import type { ChatChromeProps } from '../ChatChrome';
|
|
4
4
|
import type { ChatAttachmentDropItem } from '../ChatChrome/ChatChrome.types';
|
|
@@ -10,11 +10,13 @@ export type UseChatPanelChromeModelInput = {
|
|
|
10
10
|
/** Composite chat scope (e.g. `${userId}-${datasetId}`, `${userId}-dashboard`, `${userId}-report-${reportId}`). */
|
|
11
11
|
scopeId?: string | null;
|
|
12
12
|
/** Fires after send; second arg is the assistant reply when the API call succeeded. */
|
|
13
|
-
onMessage?: (displayText: string, assistantResponse?: string) => void;
|
|
13
|
+
onMessage?: (displayText: string, assistantResponse?: string, chatSessionId?: string) => void;
|
|
14
14
|
/** Fires when a preset script has no further `[Label|branchKey]` steps (graph leaf or linear script end). */
|
|
15
15
|
onScriptComplete?: (payload: ScriptCompletePayload) => void;
|
|
16
16
|
/** Renders `[CHART]` tokens in assistant messages. */
|
|
17
17
|
renderMessageChart?: () => React.ReactNode;
|
|
18
|
+
/** When set, SYSTEM messages render via this callback instead of plain text. */
|
|
19
|
+
renderSystemMessage?: (message: Message) => React.ReactNode;
|
|
18
20
|
/** Forwarded to `ChatChrome` when the thread is empty. */
|
|
19
21
|
emptyState?: ChatEmptyStateConfig;
|
|
20
22
|
/** MIME types / extensions for text-only chat attachments (filtered by uilib allowlist). */
|
|
@@ -44,4 +46,4 @@ export type UseChatPanelChromeModelResult = {
|
|
|
44
46
|
openNewChatWithPrefill: (prompt: string) => void;
|
|
45
47
|
chatPanelContainer: HTMLElement | null;
|
|
46
48
|
};
|
|
47
|
-
export declare function useChatPanelChromeModel({ embedAsPage, presets, scopeId, onMessage, onScriptComplete, renderMessageChart, emptyState, allowedAttachments, allowPdfAttachments, onAttachmentsDropped, slashCommandItems, onSlashItemCommand, copyHistoryOnNewChat, transformSendPayload, }: UseChatPanelChromeModelInput): UseChatPanelChromeModelResult;
|
|
49
|
+
export declare function useChatPanelChromeModel({ embedAsPage, presets, scopeId, onMessage, onScriptComplete, renderMessageChart, renderSystemMessage, emptyState, allowedAttachments, allowPdfAttachments, onAttachmentsDropped, slashCommandItems, onSlashItemCommand, copyHistoryOnNewChat, transformSendPayload, }: UseChatPanelChromeModelInput): UseChatPanelChromeModelResult;
|
|
@@ -5,6 +5,8 @@ export type { ChatChromeProps, ChatChromeResizeHandleConfig, } from './ChatChrom
|
|
|
5
5
|
export { TEXT_ATTACHMENT_ACCEPT_PARTS, filterToTextAttachments, } from './chatAttachmentAccept';
|
|
6
6
|
export { buildChatSendMessagePayload, displayTextFromSendPayload, normalizeUserTextFileAttachments, } from './buildChatSendMessagePayload';
|
|
7
7
|
export { sanitizeAttachmentFilename } from './sanitizeAttachmentFilename';
|
|
8
|
+
export { ChatSelector } from './ChatSheet/ChatSelector';
|
|
9
|
+
export type { ChatSelectorProps } from './ChatSheet/ChatSelector';
|
|
8
10
|
export { ChatSheet } from './ChatSheet/ChatSheet';
|
|
9
11
|
export { useChatPanelChromeModel } from './ChatSheet/useChatPanelChromeModel';
|
|
10
12
|
export type { ChatSheetActions, ChatSheetProps } from './ChatSheet/ChatSheet';
|
|
@@ -16,7 +18,7 @@ export { CHAT_PROMPT_COMMAND_CHIP_CLASS, chatPromptChipHtml, createChatPromptCom
|
|
|
16
18
|
export type { ChatPromptComposerInsertOptions } from './ChatPrompt/ChatPromptComposer.types';
|
|
17
19
|
export { ChatPresets } from './ChatPresets';
|
|
18
20
|
export type { ChatEmptyStateConfig, ChatEmptyStateContext, ChatEmptyStateProps, } from './ChatEmptyState/ChatEmptyState.types';
|
|
19
|
-
export type { Chat as ChatType, ChatAttachmentDropItem, ChatSendMessagePayload, ChatProps, ChatPreset as ChatPresetType, Message, UserTextFileAttachment, } from './Chat.types';
|
|
21
|
+
export type { Chat as ChatType, ChatAttachmentDropItem, ChatMeta, ChatMetaValue, ChatSendMessagePayload, ChatProps, ChatPreset as ChatPresetType, Message, UserTextFileAttachment, } from './Chat.types';
|
|
20
22
|
export { MessageRole } from './Chat.types';
|
|
21
23
|
export type { SlashCommandItem, SlashItemCommandContext, SlashOnItemCommand, } from '#uilib/tiptap/slash-mention/types';
|
|
22
24
|
export { CsvIcon } from '../../icons/CsvIcon/CsvIcon';
|