@sybilion/uilib 1.3.87 → 1.3.89
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/ChatMessage/AgentMessageContent.helpers.js +29 -21
- package/dist/esm/components/ui/Chat/ChatMessage/ChatMessage.js +2 -1
- package/dist/esm/components/ui/Chat/ChatSheet/ChatSheet.js +1 -0
- package/dist/esm/components/ui/Chat/ChatSheet/useChatPanelChromeModel.js +36 -10
- package/dist/esm/components/ui/Sidebar/Sidebar.js +23 -7
- package/dist/esm/contexts/chat-context.js +180 -205
- package/dist/esm/contexts/chatPersistence.js +6 -18
- package/dist/esm/contexts/chatSessionStorage.js +245 -0
- package/dist/esm/lib/dashboard-spec/jsonDashboardFence.js +80 -0
- package/dist/esm/types/src/components/ui/Chat/ChatEmptyState/ChatEmptyState.types.d.ts +5 -1
- package/dist/esm/types/src/components/ui/Chat/ChatMessage/AgentMessageContent.helpers.d.ts +1 -5
- package/dist/esm/types/src/components/ui/Chat/ChatMessage/AgentMessageContent.helpers.test.d.ts +1 -0
- package/dist/esm/types/src/components/ui/Chat/ChatSheet/ChatSheet.d.ts +2 -0
- package/dist/esm/types/src/components/ui/Chat/ChatSheet/useChatPanelChromeModel.d.ts +8 -1
- package/dist/esm/types/src/components/ui/Chat/index.d.ts +1 -1
- package/dist/esm/types/src/components/ui/Sidebar/Sidebar.d.ts +2 -0
- package/dist/esm/types/src/contexts/chat-context.d.ts +6 -0
- package/dist/esm/types/src/contexts/chatPersistence.d.ts +4 -1
- package/dist/esm/types/src/contexts/chatSessionStorage.d.ts +32 -0
- package/dist/esm/types/src/contexts/chatSessionStorage.test.d.ts +1 -0
- package/dist/esm/types/src/lib/dashboard-spec/jsonDashboardFence.d.ts +9 -0
- package/dist/esm/types/src/lib/dashboard-spec/stripJsonDashboardFences.d.ts +1 -2
- package/dist/esm/types/src/lib/dashboard-spec/stripJsonDashboardFences.test.d.ts +1 -0
- package/package.json +1 -1
- package/src/components/ui/Chat/ChatEmptyState/ChatEmptyState.types.ts +9 -1
- package/src/components/ui/Chat/ChatMessage/AgentMessageContent.helpers.test.tsx +25 -0
- package/src/components/ui/Chat/ChatMessage/AgentMessageContent.helpers.tsx +35 -26
- package/src/components/ui/Chat/ChatMessage/ChatMessage.tsx +2 -1
- package/src/components/ui/Chat/ChatSheet/ChatSheet.tsx +3 -0
- package/src/components/ui/Chat/ChatSheet/useChatPanelChromeModel.tsx +55 -10
- package/src/components/ui/Chat/index.ts +1 -0
- package/src/components/ui/Sidebar/Sidebar.tsx +27 -8
- package/src/contexts/chat-context.tsx +253 -220
- package/src/contexts/chatPersistence.test.ts +11 -0
- package/src/contexts/chatPersistence.ts +22 -6
- package/src/contexts/chatSessionStorage.test.ts +125 -0
- package/src/contexts/chatSessionStorage.ts +321 -0
- package/src/lib/dashboard-spec/jsonDashboardFence.ts +98 -0
- package/src/lib/dashboard-spec/stripJsonDashboardFences.test.ts +84 -0
- package/src/lib/dashboard-spec/stripJsonDashboardFences.ts +5 -6
- package/dist/esm/lib/dashboard-spec/stripJsonDashboardFences.js +0 -7
|
@@ -13,6 +13,8 @@ export type ChatSheetActions = {
|
|
|
13
13
|
openNewChat: () => void;
|
|
14
14
|
/** Starts a new chat, opens the panel, and pre-fills the composer (user sends manually). */
|
|
15
15
|
openNewChatWithPrefill: (prompt: string) => void;
|
|
16
|
+
/** Starts a new chat, opens panel, and sends prompt immediately. */
|
|
17
|
+
openNewChatAndSubmit: (prompt: string) => void;
|
|
16
18
|
};
|
|
17
19
|
|
|
18
20
|
export interface ChatSheetProps extends Omit<
|
|
@@ -79,6 +81,7 @@ export function ChatSheet({
|
|
|
79
81
|
model.onOpenChange(true);
|
|
80
82
|
},
|
|
81
83
|
openNewChatWithPrefill: model.openNewChatWithPrefill,
|
|
84
|
+
openNewChatAndSubmit: model.openNewChatAndSubmit,
|
|
82
85
|
};
|
|
83
86
|
}
|
|
84
87
|
|
|
@@ -51,7 +51,10 @@ import {
|
|
|
51
51
|
} from '../../Sidebar/Sidebar';
|
|
52
52
|
import { Chat } from '../Chat';
|
|
53
53
|
import type { ChatChromeProps } from '../ChatChrome';
|
|
54
|
-
import type {
|
|
54
|
+
import type {
|
|
55
|
+
ChatAttachmentDropItem,
|
|
56
|
+
ChatPresetsRenderOptions,
|
|
57
|
+
} from '../ChatChrome/ChatChrome.types';
|
|
55
58
|
import type { ChatEmptyStateConfig } from '../ChatEmptyState/ChatEmptyState.types';
|
|
56
59
|
import type { ChatEmptyStateProps } from '../ChatEmptyState/ChatEmptyState.types';
|
|
57
60
|
import {
|
|
@@ -108,6 +111,11 @@ export type UseChatPanelChromeModelInput = {
|
|
|
108
111
|
| string
|
|
109
112
|
| ChatSendMessagePayload
|
|
110
113
|
| Promise<string | ChatSendMessagePayload>;
|
|
114
|
+
/**
|
|
115
|
+
* When true, preset clicks always use the API send path (skip local `answer` /
|
|
116
|
+
* script demo). Use on /reports/new where first message must hit transformSendPayload.
|
|
117
|
+
*/
|
|
118
|
+
submitPresetsViaApi?: boolean;
|
|
111
119
|
};
|
|
112
120
|
|
|
113
121
|
export type UseChatPanelChromeModelResult = {
|
|
@@ -118,6 +126,8 @@ export type UseChatPanelChromeModelResult = {
|
|
|
118
126
|
newChat: () => void;
|
|
119
127
|
/** New session + open panel + one-shot composer pre-fill (does not send). */
|
|
120
128
|
openNewChatWithPrefill: (prompt: string) => void;
|
|
129
|
+
/** New session + open panel + immediate send. */
|
|
130
|
+
openNewChatAndSubmit: (prompt: string) => void;
|
|
121
131
|
chatPanelContainer: HTMLElement | null;
|
|
122
132
|
};
|
|
123
133
|
|
|
@@ -160,6 +170,7 @@ export function useChatPanelChromeModel({
|
|
|
160
170
|
onSlashItemCommand,
|
|
161
171
|
copyHistoryOnNewChat = false,
|
|
162
172
|
transformSendPayload,
|
|
173
|
+
submitPresetsViaApi = false,
|
|
163
174
|
}: UseChatPanelChromeModelInput): UseChatPanelChromeModelResult {
|
|
164
175
|
const effectiveScopeId = scopeId ?? NO_SCOPE_FALLBACK;
|
|
165
176
|
const isMobile = useIsMobile();
|
|
@@ -209,6 +220,10 @@ export function useChatPanelChromeModel({
|
|
|
209
220
|
);
|
|
210
221
|
/** Deduplicate Strict Mode double `useEffect` on the same mount. */
|
|
211
222
|
const promptParamHandledInEffectRef = useRef(false);
|
|
223
|
+
const pendingOpenChatAndSubmitRef = useRef<{
|
|
224
|
+
sessionId: string;
|
|
225
|
+
prompt: string;
|
|
226
|
+
} | null>(null);
|
|
212
227
|
const prevShellChatPanelOpenRef = useRef(shellChatPanelOpen);
|
|
213
228
|
/** This instance requested shell chat width (ignore other ChatSheet instances on the page). */
|
|
214
229
|
const openedShellChatRef = useRef(false);
|
|
@@ -405,6 +420,23 @@ export function useChatPanelChromeModel({
|
|
|
405
420
|
[startEmptyNewChat, onOpenChange],
|
|
406
421
|
);
|
|
407
422
|
|
|
423
|
+
const openNewChatAndSubmit = useCallback(
|
|
424
|
+
(prompt: string) => {
|
|
425
|
+
const sessionId = startEmptyNewChat();
|
|
426
|
+
if (sessionId == null) {
|
|
427
|
+
logger.warn('Chat submit: sign in to use the assistant.');
|
|
428
|
+
return;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
const trimmed = prompt.trim();
|
|
432
|
+
if (!trimmed) return;
|
|
433
|
+
|
|
434
|
+
pendingOpenChatAndSubmitRef.current = { sessionId, prompt: trimmed };
|
|
435
|
+
onOpenChange(true);
|
|
436
|
+
},
|
|
437
|
+
[startEmptyNewChat, onOpenChange],
|
|
438
|
+
);
|
|
439
|
+
|
|
408
440
|
/**
|
|
409
441
|
* App link: `?prompt=…` — open panel, pre-fill composer, strip param (read once on mount
|
|
410
442
|
* from `location.search`). If the selected session already has messages, `newChat()` first.
|
|
@@ -567,7 +599,7 @@ export function useChatPanelChromeModel({
|
|
|
567
599
|
try {
|
|
568
600
|
const { response: assistantResponse, sessionId } =
|
|
569
601
|
await sendMessage(payload);
|
|
570
|
-
onMessage?.(
|
|
602
|
+
await onMessage?.(
|
|
571
603
|
displayTextFromSendPayload(payload),
|
|
572
604
|
assistantResponse,
|
|
573
605
|
sessionId,
|
|
@@ -735,7 +767,7 @@ export function useChatPanelChromeModel({
|
|
|
735
767
|
try {
|
|
736
768
|
const { response: assistantResponse, sessionId } =
|
|
737
769
|
await sendMessage(payload);
|
|
738
|
-
onMessage?.(
|
|
770
|
+
await onMessage?.(
|
|
739
771
|
displayTextFromSendPayload(payload),
|
|
740
772
|
assistantResponse,
|
|
741
773
|
sessionId,
|
|
@@ -763,23 +795,31 @@ export function useChatPanelChromeModel({
|
|
|
763
795
|
],
|
|
764
796
|
);
|
|
765
797
|
|
|
798
|
+
useEffect(() => {
|
|
799
|
+
const pending = pendingOpenChatAndSubmitRef.current;
|
|
800
|
+
if (!pending || currentChatId !== pending.sessionId) return;
|
|
801
|
+
pendingOpenChatAndSubmitRef.current = null;
|
|
802
|
+
void handlePromptSubmit(pending.prompt);
|
|
803
|
+
}, [currentChatId, handlePromptSubmit]);
|
|
804
|
+
|
|
766
805
|
const submitPreset = useCallback(
|
|
767
|
-
async (preset: ChatPreset) => {
|
|
806
|
+
async (preset: ChatPreset, options?: { message?: string }) => {
|
|
768
807
|
const script = preset.script;
|
|
769
808
|
const scriptGraph = isPresetScriptGraph(script);
|
|
770
809
|
const hasLinearScript = Array.isArray(script) && script.length > 0;
|
|
771
810
|
const hasReplies =
|
|
772
811
|
preset.replies && Object.keys(preset.replies).length > 0;
|
|
773
812
|
const isLocalDemo =
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
813
|
+
!submitPresetsViaApi &&
|
|
814
|
+
(hasLinearScript ||
|
|
815
|
+
scriptGraph ||
|
|
816
|
+
Boolean(preset.answer?.trim()) ||
|
|
817
|
+
Boolean(hasReplies));
|
|
778
818
|
|
|
779
819
|
if (!isLocalDemo) {
|
|
780
820
|
if (!currentChatId) return;
|
|
781
821
|
endLocalDemoFlow(currentChatId);
|
|
782
|
-
await handlePromptSubmit(preset.text);
|
|
822
|
+
await handlePromptSubmit(options?.message ?? preset.text);
|
|
783
823
|
return;
|
|
784
824
|
}
|
|
785
825
|
|
|
@@ -862,6 +902,7 @@ export function useChatPanelChromeModel({
|
|
|
862
902
|
handlePromptSubmit,
|
|
863
903
|
addMessage,
|
|
864
904
|
presetsWithFreeform,
|
|
905
|
+
submitPresetsViaApi,
|
|
865
906
|
],
|
|
866
907
|
);
|
|
867
908
|
|
|
@@ -1089,7 +1130,10 @@ export function useChatPanelChromeModel({
|
|
|
1089
1130
|
})
|
|
1090
1131
|
) {
|
|
1091
1132
|
// Chat open uses `startViewTransition`; nested transition here aborts first → AbortError overlay.
|
|
1092
|
-
setSidebarNavOpen(false, {
|
|
1133
|
+
setSidebarNavOpen(false, {
|
|
1134
|
+
viewTransition: false,
|
|
1135
|
+
layoutAutoClose: true,
|
|
1136
|
+
});
|
|
1093
1137
|
}
|
|
1094
1138
|
};
|
|
1095
1139
|
|
|
@@ -1301,6 +1345,7 @@ export function useChatPanelChromeModel({
|
|
|
1301
1345
|
toggleOpen,
|
|
1302
1346
|
newChat: startEmptyNewChat,
|
|
1303
1347
|
openNewChatWithPrefill,
|
|
1348
|
+
openNewChatAndSubmit,
|
|
1304
1349
|
chatPanelContainer,
|
|
1305
1350
|
};
|
|
1306
1351
|
}
|
|
@@ -93,7 +93,11 @@ function readInitialChatWidthPx(): number {
|
|
|
93
93
|
type SetPanelWidthOptions = { persist?: boolean };
|
|
94
94
|
|
|
95
95
|
/** Pass `viewTransition: false` to avoid nesting `document.startViewTransition` (e.g. chat open already animating). */
|
|
96
|
-
export type SetSidebarOpenOptions = {
|
|
96
|
+
export type SetSidebarOpenOptions = {
|
|
97
|
+
viewTransition?: boolean;
|
|
98
|
+
/** Nav closed for layout (chat/width); restore when chat closes — do not persist closed cookie. */
|
|
99
|
+
layoutAutoClose?: boolean;
|
|
100
|
+
};
|
|
97
101
|
|
|
98
102
|
type SidebarContextProps = {
|
|
99
103
|
isOpen: boolean;
|
|
@@ -178,6 +182,8 @@ function SidebarProvider({
|
|
|
178
182
|
const [chatPanelOpen, _setChatPanelOpen] = useState(false);
|
|
179
183
|
const sidebarWidthRef = useRef(sidebarWidthPx);
|
|
180
184
|
const chatWidthRef = useRef(chatWidthPx);
|
|
185
|
+
/** Left nav was auto-closed because chat opened on a narrow shell; reopen when chat closes. */
|
|
186
|
+
const sidebarAutoClosedForChatRef = useRef(false);
|
|
181
187
|
sidebarWidthRef.current = sidebarWidthPx;
|
|
182
188
|
chatWidthRef.current = chatWidthPx;
|
|
183
189
|
|
|
@@ -332,10 +338,8 @@ function SidebarProvider({
|
|
|
332
338
|
window.dispatchEvent(new CustomEvent(DISMISS_CHAT_FOR_LAYOUT_EVENT));
|
|
333
339
|
}
|
|
334
340
|
} else if (openingChat && isOpen) {
|
|
341
|
+
sidebarAutoClosedForChatRef.current = true;
|
|
335
342
|
setIsOpen(false);
|
|
336
|
-
if (getCookiePreferences(userId)?.functional) {
|
|
337
|
-
setCookie('isSidebarOpen', 'false', 60 * 60 * 24 * 7);
|
|
338
|
-
}
|
|
339
343
|
}
|
|
340
344
|
},
|
|
341
345
|
[
|
|
@@ -345,7 +349,6 @@ function SidebarProvider({
|
|
|
345
349
|
chatPanelOpen,
|
|
346
350
|
sidebarWidthPx,
|
|
347
351
|
chatWidthPx,
|
|
348
|
-
userId,
|
|
349
352
|
],
|
|
350
353
|
);
|
|
351
354
|
|
|
@@ -353,16 +356,32 @@ function SidebarProvider({
|
|
|
353
356
|
(open: boolean) => {
|
|
354
357
|
if (open) {
|
|
355
358
|
closeOppositeSidebarIfNoSpace(false, true);
|
|
359
|
+
_setChatPanelOpen(true);
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
_setChatPanelOpen(false);
|
|
363
|
+
if (sidebarAutoClosedForChatRef.current) {
|
|
364
|
+
sidebarAutoClosedForChatRef.current = false;
|
|
365
|
+
setIsOpen(true);
|
|
366
|
+
if (getCookiePreferences(userId)?.functional) {
|
|
367
|
+
setCookie('isSidebarOpen', 'true', 60 * 60 * 24 * 7);
|
|
368
|
+
}
|
|
356
369
|
}
|
|
357
|
-
_setChatPanelOpen(open);
|
|
358
370
|
},
|
|
359
|
-
[closeOppositeSidebarIfNoSpace],
|
|
371
|
+
[closeOppositeSidebarIfNoSpace, userId],
|
|
360
372
|
);
|
|
361
373
|
|
|
362
374
|
const setOpen = useCallback(
|
|
363
375
|
(value: boolean, options?: SetSidebarOpenOptions) => {
|
|
376
|
+
const layoutAutoClose = options?.layoutAutoClose === true;
|
|
377
|
+
|
|
364
378
|
if (value) {
|
|
379
|
+
sidebarAutoClosedForChatRef.current = false;
|
|
365
380
|
closeOppositeSidebarIfNoSpace(true, false);
|
|
381
|
+
} else if (layoutAutoClose) {
|
|
382
|
+
sidebarAutoClosedForChatRef.current = true;
|
|
383
|
+
} else {
|
|
384
|
+
sidebarAutoClosedForChatRef.current = false;
|
|
366
385
|
}
|
|
367
386
|
|
|
368
387
|
const useViewTransition =
|
|
@@ -379,7 +398,7 @@ function SidebarProvider({
|
|
|
379
398
|
setIsOpen(value);
|
|
380
399
|
}
|
|
381
400
|
|
|
382
|
-
if (getCookiePreferences(userId)?.functional) {
|
|
401
|
+
if (!layoutAutoClose && getCookiePreferences(userId)?.functional) {
|
|
383
402
|
setCookie('isSidebarOpen', value.toString(), 60 * 60 * 24 * 7);
|
|
384
403
|
}
|
|
385
404
|
},
|