@xinghunm/ai-chat 1.3.3 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +86 -30
- package/dist/index.d.mts +72 -1
- package/dist/index.d.ts +72 -1
- package/dist/index.js +505 -33
- package/dist/index.mjs +505 -33
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -46,7 +46,7 @@ __export(src_exports, {
|
|
|
46
46
|
module.exports = __toCommonJS(src_exports);
|
|
47
47
|
|
|
48
48
|
// src/components/ai-chat/index.tsx
|
|
49
|
-
var
|
|
49
|
+
var import_react21 = require("react");
|
|
50
50
|
var import_styled17 = __toESM(require("@emotion/styled"));
|
|
51
51
|
var import_compass_ui4 = require("@xinghunm/compass-ui");
|
|
52
52
|
|
|
@@ -100,7 +100,10 @@ var DEFAULT_AI_CHAT_LABELS = {
|
|
|
100
100
|
modelUnavailable: "No model available",
|
|
101
101
|
skillLoading: "Loading skills...",
|
|
102
102
|
skillEmpty: "No matching skills",
|
|
103
|
-
removeSkillAriaLabel: "Remove skill"
|
|
103
|
+
removeSkillAriaLabel: "Remove skill",
|
|
104
|
+
sessionHistoryLoading: "Loading conversations...",
|
|
105
|
+
sessionHistoryLoadFailed: "Failed to load conversations",
|
|
106
|
+
sessionHistoryEmpty: "No conversations yet"
|
|
104
107
|
};
|
|
105
108
|
|
|
106
109
|
// src/lib/chat-session.ts
|
|
@@ -128,6 +131,20 @@ var createDraftChatSession = ({
|
|
|
128
131
|
// src/store/chat-store.ts
|
|
129
132
|
var DEFAULT_CHAT_SESSION_TITLE = "New Chat";
|
|
130
133
|
var IMAGE_MESSAGE_SESSION_TITLE = "Image message";
|
|
134
|
+
var createHistoryMessagePaginationState = (page) => ({
|
|
135
|
+
previousCursor: page?.previousCursor ?? null,
|
|
136
|
+
hasMorePrevious: page?.hasMorePrevious ?? Boolean(page && page.previousCursor !== null),
|
|
137
|
+
isLoadingPrevious: false,
|
|
138
|
+
error: null
|
|
139
|
+
});
|
|
140
|
+
var normalizeHistoryMessages = (sessionId, messages) => messages.map((message) => ({ ...message, sessionId }));
|
|
141
|
+
var mergeOlderHistoryMessages = (sessionId, olderMessages, currentMessages) => {
|
|
142
|
+
const currentMessageIds = new Set(currentMessages.map((message) => message.id));
|
|
143
|
+
const uniqueOlderMessages = normalizeHistoryMessages(sessionId, olderMessages).filter(
|
|
144
|
+
(message) => !currentMessageIds.has(message.id)
|
|
145
|
+
);
|
|
146
|
+
return [...uniqueOlderMessages, ...currentMessages];
|
|
147
|
+
};
|
|
131
148
|
var resolveSessionTitleFromMessage = (message) => {
|
|
132
149
|
const trimmedContent = message.content.trim();
|
|
133
150
|
if (trimmedContent) {
|
|
@@ -230,6 +247,9 @@ var createChatStore = (initialState) => (0, import_vanilla.createStore)((set, ge
|
|
|
230
247
|
isStreamingBySession: {},
|
|
231
248
|
isStoppingBySession: {},
|
|
232
249
|
errorBySession: {},
|
|
250
|
+
sessionMessageLoadStatusBySession: {},
|
|
251
|
+
sessionMessageLoadErrorBySession: {},
|
|
252
|
+
historyMessagePaginationBySession: {},
|
|
233
253
|
// ---- Session management ------------------------------------------------
|
|
234
254
|
createSession: (session) => {
|
|
235
255
|
const state = get();
|
|
@@ -243,6 +263,15 @@ var createChatStore = (initialState) => (0, import_vanilla.createStore)((set, ge
|
|
|
243
263
|
const nextErrorBySession = { ...state.errorBySession };
|
|
244
264
|
const nextIsStreamingBySession = { ...state.isStreamingBySession };
|
|
245
265
|
const nextIsStoppingBySession = { ...state.isStoppingBySession };
|
|
266
|
+
const nextSessionMessageLoadStatusBySession = {
|
|
267
|
+
...state.sessionMessageLoadStatusBySession
|
|
268
|
+
};
|
|
269
|
+
const nextSessionMessageLoadErrorBySession = {
|
|
270
|
+
...state.sessionMessageLoadErrorBySession
|
|
271
|
+
};
|
|
272
|
+
const nextHistoryMessagePaginationBySession = {
|
|
273
|
+
...state.historyMessagePaginationBySession
|
|
274
|
+
};
|
|
246
275
|
const sid = session.sessionId;
|
|
247
276
|
if (nextMessagesBySession[sid] === void 0)
|
|
248
277
|
nextMessagesBySession[sid] = [];
|
|
@@ -252,13 +281,25 @@ var createChatStore = (initialState) => (0, import_vanilla.createStore)((set, ge
|
|
|
252
281
|
nextIsStreamingBySession[sid] = false;
|
|
253
282
|
if (nextIsStoppingBySession[sid] === void 0)
|
|
254
283
|
nextIsStoppingBySession[sid] = false;
|
|
284
|
+
if (nextSessionMessageLoadStatusBySession[sid] === void 0) {
|
|
285
|
+
nextSessionMessageLoadStatusBySession[sid] = "loaded";
|
|
286
|
+
}
|
|
287
|
+
if (nextSessionMessageLoadErrorBySession[sid] === void 0) {
|
|
288
|
+
nextSessionMessageLoadErrorBySession[sid] = null;
|
|
289
|
+
}
|
|
290
|
+
if (nextHistoryMessagePaginationBySession[sid] === void 0) {
|
|
291
|
+
nextHistoryMessagePaginationBySession[sid] = createHistoryMessagePaginationState();
|
|
292
|
+
}
|
|
255
293
|
set({
|
|
256
294
|
sessions: nextSessions,
|
|
257
295
|
activeSessionId: sid,
|
|
258
296
|
messagesBySession: nextMessagesBySession,
|
|
259
297
|
errorBySession: nextErrorBySession,
|
|
260
298
|
isStreamingBySession: nextIsStreamingBySession,
|
|
261
|
-
isStoppingBySession: nextIsStoppingBySession
|
|
299
|
+
isStoppingBySession: nextIsStoppingBySession,
|
|
300
|
+
sessionMessageLoadStatusBySession: nextSessionMessageLoadStatusBySession,
|
|
301
|
+
sessionMessageLoadErrorBySession: nextSessionMessageLoadErrorBySession,
|
|
302
|
+
historyMessagePaginationBySession: nextHistoryMessagePaginationBySession
|
|
262
303
|
});
|
|
263
304
|
},
|
|
264
305
|
startNewChat: () => {
|
|
@@ -313,6 +354,27 @@ var createChatStore = (initialState) => (0, import_vanilla.createStore)((set, ge
|
|
|
313
354
|
nextErrorBySession[nextSessionId] = nextErrorBySession[previousSessionId] ?? null;
|
|
314
355
|
delete nextErrorBySession[previousSessionId];
|
|
315
356
|
}
|
|
357
|
+
const nextSessionMessageLoadStatusBySession = {
|
|
358
|
+
...state.sessionMessageLoadStatusBySession
|
|
359
|
+
};
|
|
360
|
+
if (previousSessionId in nextSessionMessageLoadStatusBySession) {
|
|
361
|
+
nextSessionMessageLoadStatusBySession[nextSessionId] = nextSessionMessageLoadStatusBySession[previousSessionId] ?? "idle";
|
|
362
|
+
delete nextSessionMessageLoadStatusBySession[previousSessionId];
|
|
363
|
+
}
|
|
364
|
+
const nextSessionMessageLoadErrorBySession = {
|
|
365
|
+
...state.sessionMessageLoadErrorBySession
|
|
366
|
+
};
|
|
367
|
+
if (previousSessionId in nextSessionMessageLoadErrorBySession) {
|
|
368
|
+
nextSessionMessageLoadErrorBySession[nextSessionId] = nextSessionMessageLoadErrorBySession[previousSessionId] ?? null;
|
|
369
|
+
delete nextSessionMessageLoadErrorBySession[previousSessionId];
|
|
370
|
+
}
|
|
371
|
+
const nextHistoryMessagePaginationBySession = {
|
|
372
|
+
...state.historyMessagePaginationBySession
|
|
373
|
+
};
|
|
374
|
+
if (previousSessionId in nextHistoryMessagePaginationBySession) {
|
|
375
|
+
nextHistoryMessagePaginationBySession[nextSessionId] = nextHistoryMessagePaginationBySession[previousSessionId] ?? createHistoryMessagePaginationState();
|
|
376
|
+
delete nextHistoryMessagePaginationBySession[previousSessionId];
|
|
377
|
+
}
|
|
316
378
|
const nextActiveSessionId = state.activeSessionId === previousSessionId ? nextSessionId : state.activeSessionId;
|
|
317
379
|
set({
|
|
318
380
|
sessions: nextSessions,
|
|
@@ -321,6 +383,9 @@ var createChatStore = (initialState) => (0, import_vanilla.createStore)((set, ge
|
|
|
321
383
|
isStreamingBySession: nextIsStreamingBySession,
|
|
322
384
|
isStoppingBySession: nextIsStoppingBySession,
|
|
323
385
|
errorBySession: nextErrorBySession,
|
|
386
|
+
sessionMessageLoadStatusBySession: nextSessionMessageLoadStatusBySession,
|
|
387
|
+
sessionMessageLoadErrorBySession: nextSessionMessageLoadErrorBySession,
|
|
388
|
+
historyMessagePaginationBySession: nextHistoryMessagePaginationBySession,
|
|
324
389
|
activeSessionId: nextActiveSessionId
|
|
325
390
|
});
|
|
326
391
|
},
|
|
@@ -334,6 +399,61 @@ var createChatStore = (initialState) => (0, import_vanilla.createStore)((set, ge
|
|
|
334
399
|
);
|
|
335
400
|
set({ sessions: nextSessions });
|
|
336
401
|
},
|
|
402
|
+
hydrateHistorySessions: (sessions) => {
|
|
403
|
+
const state = get();
|
|
404
|
+
const localSessions = state.sessions.filter(
|
|
405
|
+
(session) => isDraftChatSessionId(session.sessionId)
|
|
406
|
+
);
|
|
407
|
+
const localSessionIds = new Set(localSessions.map((session) => session.sessionId));
|
|
408
|
+
const nextSessions = [
|
|
409
|
+
...localSessions,
|
|
410
|
+
...sessions.filter((session) => !localSessionIds.has(session.sessionId)).map((session) => ({
|
|
411
|
+
...session,
|
|
412
|
+
mode: session.mode ?? DEFAULT_CHAT_AGENT_MODE
|
|
413
|
+
}))
|
|
414
|
+
];
|
|
415
|
+
const nextMessagesBySession = { ...state.messagesBySession };
|
|
416
|
+
const nextErrorBySession = { ...state.errorBySession };
|
|
417
|
+
const nextIsStreamingBySession = { ...state.isStreamingBySession };
|
|
418
|
+
const nextIsStoppingBySession = { ...state.isStoppingBySession };
|
|
419
|
+
const nextSessionMessageLoadStatusBySession = {
|
|
420
|
+
...state.sessionMessageLoadStatusBySession
|
|
421
|
+
};
|
|
422
|
+
const nextSessionMessageLoadErrorBySession = {
|
|
423
|
+
...state.sessionMessageLoadErrorBySession
|
|
424
|
+
};
|
|
425
|
+
const nextHistoryMessagePaginationBySession = {
|
|
426
|
+
...state.historyMessagePaginationBySession
|
|
427
|
+
};
|
|
428
|
+
nextSessions.forEach((session) => {
|
|
429
|
+
const sid = session.sessionId;
|
|
430
|
+
if (nextErrorBySession[sid] === void 0)
|
|
431
|
+
nextErrorBySession[sid] = null;
|
|
432
|
+
if (nextIsStreamingBySession[sid] === void 0)
|
|
433
|
+
nextIsStreamingBySession[sid] = false;
|
|
434
|
+
if (nextIsStoppingBySession[sid] === void 0)
|
|
435
|
+
nextIsStoppingBySession[sid] = false;
|
|
436
|
+
if (nextSessionMessageLoadStatusBySession[sid] === void 0) {
|
|
437
|
+
nextSessionMessageLoadStatusBySession[sid] = "idle";
|
|
438
|
+
}
|
|
439
|
+
if (nextSessionMessageLoadErrorBySession[sid] === void 0) {
|
|
440
|
+
nextSessionMessageLoadErrorBySession[sid] = null;
|
|
441
|
+
}
|
|
442
|
+
if (nextHistoryMessagePaginationBySession[sid] === void 0) {
|
|
443
|
+
nextHistoryMessagePaginationBySession[sid] = createHistoryMessagePaginationState();
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
set({
|
|
447
|
+
sessions: nextSessions,
|
|
448
|
+
messagesBySession: nextMessagesBySession,
|
|
449
|
+
errorBySession: nextErrorBySession,
|
|
450
|
+
isStreamingBySession: nextIsStreamingBySession,
|
|
451
|
+
isStoppingBySession: nextIsStoppingBySession,
|
|
452
|
+
sessionMessageLoadStatusBySession: nextSessionMessageLoadStatusBySession,
|
|
453
|
+
sessionMessageLoadErrorBySession: nextSessionMessageLoadErrorBySession,
|
|
454
|
+
historyMessagePaginationBySession: nextHistoryMessagePaginationBySession
|
|
455
|
+
});
|
|
456
|
+
},
|
|
337
457
|
// ---- Message operations ------------------------------------------------
|
|
338
458
|
appendMessage: (sessionId, message) => {
|
|
339
459
|
const state = get();
|
|
@@ -360,6 +480,92 @@ var createChatStore = (initialState) => (0, import_vanilla.createStore)((set, ge
|
|
|
360
480
|
isStreamingBySession: nextIsStreamingBySession
|
|
361
481
|
});
|
|
362
482
|
},
|
|
483
|
+
hydrateHistorySessionMessages: (sessionId, messages) => {
|
|
484
|
+
const state = get();
|
|
485
|
+
set({
|
|
486
|
+
messagesBySession: {
|
|
487
|
+
...state.messagesBySession,
|
|
488
|
+
[sessionId]: normalizeHistoryMessages(sessionId, messages)
|
|
489
|
+
},
|
|
490
|
+
sessionMessageLoadStatusBySession: {
|
|
491
|
+
...state.sessionMessageLoadStatusBySession,
|
|
492
|
+
[sessionId]: "loaded"
|
|
493
|
+
},
|
|
494
|
+
sessionMessageLoadErrorBySession: {
|
|
495
|
+
...state.sessionMessageLoadErrorBySession,
|
|
496
|
+
[sessionId]: null
|
|
497
|
+
},
|
|
498
|
+
historyMessagePaginationBySession: {
|
|
499
|
+
...state.historyMessagePaginationBySession,
|
|
500
|
+
[sessionId]: createHistoryMessagePaginationState()
|
|
501
|
+
}
|
|
502
|
+
});
|
|
503
|
+
},
|
|
504
|
+
hydrateHistorySessionMessagesPage: (sessionId, page) => {
|
|
505
|
+
const state = get();
|
|
506
|
+
set({
|
|
507
|
+
messagesBySession: {
|
|
508
|
+
...state.messagesBySession,
|
|
509
|
+
[sessionId]: normalizeHistoryMessages(sessionId, page.messages)
|
|
510
|
+
},
|
|
511
|
+
sessionMessageLoadStatusBySession: {
|
|
512
|
+
...state.sessionMessageLoadStatusBySession,
|
|
513
|
+
[sessionId]: "loaded"
|
|
514
|
+
},
|
|
515
|
+
sessionMessageLoadErrorBySession: {
|
|
516
|
+
...state.sessionMessageLoadErrorBySession,
|
|
517
|
+
[sessionId]: null
|
|
518
|
+
},
|
|
519
|
+
historyMessagePaginationBySession: {
|
|
520
|
+
...state.historyMessagePaginationBySession,
|
|
521
|
+
[sessionId]: createHistoryMessagePaginationState(page)
|
|
522
|
+
}
|
|
523
|
+
});
|
|
524
|
+
},
|
|
525
|
+
prependHistorySessionMessagesPage: (sessionId, page) => {
|
|
526
|
+
const state = get();
|
|
527
|
+
set({
|
|
528
|
+
messagesBySession: {
|
|
529
|
+
...state.messagesBySession,
|
|
530
|
+
[sessionId]: mergeOlderHistoryMessages(
|
|
531
|
+
sessionId,
|
|
532
|
+
page.messages,
|
|
533
|
+
state.messagesBySession[sessionId] ?? []
|
|
534
|
+
)
|
|
535
|
+
},
|
|
536
|
+
historyMessagePaginationBySession: {
|
|
537
|
+
...state.historyMessagePaginationBySession,
|
|
538
|
+
[sessionId]: createHistoryMessagePaginationState(page)
|
|
539
|
+
}
|
|
540
|
+
});
|
|
541
|
+
},
|
|
542
|
+
setHistorySessionPreviousMessagesLoadStatus: (sessionId, isLoading, error2 = null) => {
|
|
543
|
+
const state = get();
|
|
544
|
+
const current = state.historyMessagePaginationBySession[sessionId] ?? createHistoryMessagePaginationState();
|
|
545
|
+
set({
|
|
546
|
+
historyMessagePaginationBySession: {
|
|
547
|
+
...state.historyMessagePaginationBySession,
|
|
548
|
+
[sessionId]: {
|
|
549
|
+
...current,
|
|
550
|
+
isLoadingPrevious: isLoading,
|
|
551
|
+
error: error2
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
});
|
|
555
|
+
},
|
|
556
|
+
setHistorySessionMessageLoadStatus: (sessionId, status, error2 = null) => {
|
|
557
|
+
const state = get();
|
|
558
|
+
set({
|
|
559
|
+
sessionMessageLoadStatusBySession: {
|
|
560
|
+
...state.sessionMessageLoadStatusBySession,
|
|
561
|
+
[sessionId]: status
|
|
562
|
+
},
|
|
563
|
+
sessionMessageLoadErrorBySession: {
|
|
564
|
+
...state.sessionMessageLoadErrorBySession,
|
|
565
|
+
[sessionId]: error2
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
},
|
|
363
569
|
startStreamingMessage: (sessionId, message) => {
|
|
364
570
|
const state = get();
|
|
365
571
|
set({
|
|
@@ -807,6 +1013,10 @@ var AiChatProvider = (props) => {
|
|
|
807
1013
|
handleQuestionnaireSubmit,
|
|
808
1014
|
handleConfirmationSubmit,
|
|
809
1015
|
messageRenderOrder,
|
|
1016
|
+
historySessionList,
|
|
1017
|
+
onLoadMoreSessions,
|
|
1018
|
+
onSelectHistorySession,
|
|
1019
|
+
onLoadMoreHistoryMessages,
|
|
810
1020
|
enableImageAttachments = true,
|
|
811
1021
|
children
|
|
812
1022
|
} = props;
|
|
@@ -883,7 +1093,11 @@ var AiChatProvider = (props) => {
|
|
|
883
1093
|
handleConfirmationSubmit,
|
|
884
1094
|
messageRenderOrder,
|
|
885
1095
|
transformStreamPacket: defaultTransformStreamPacket,
|
|
886
|
-
enableImageAttachments
|
|
1096
|
+
enableImageAttachments,
|
|
1097
|
+
historySessionList,
|
|
1098
|
+
onLoadMoreSessions,
|
|
1099
|
+
onSelectHistorySession,
|
|
1100
|
+
onLoadMoreHistoryMessages
|
|
887
1101
|
}),
|
|
888
1102
|
[
|
|
889
1103
|
axiosInstance,
|
|
@@ -893,8 +1107,12 @@ var AiChatProvider = (props) => {
|
|
|
893
1107
|
enableImageAttachments,
|
|
894
1108
|
handleConfirmationSubmit,
|
|
895
1109
|
handleQuestionnaireSubmit,
|
|
1110
|
+
historySessionList,
|
|
896
1111
|
labels,
|
|
897
1112
|
messageRenderOrder,
|
|
1113
|
+
onLoadMoreSessions,
|
|
1114
|
+
onLoadMoreHistoryMessages,
|
|
1115
|
+
onSelectHistorySession,
|
|
898
1116
|
renderMessageBlock,
|
|
899
1117
|
sendRef,
|
|
900
1118
|
retryRef,
|
|
@@ -3206,15 +3424,11 @@ var Bubble = import_styled7.default.article`
|
|
|
3206
3424
|
|
|
3207
3425
|
&[data-role='user'] {
|
|
3208
3426
|
width: auto;
|
|
3209
|
-
max-width:
|
|
3427
|
+
max-width: 100%;
|
|
3210
3428
|
margin-left: auto;
|
|
3211
|
-
padding:
|
|
3212
|
-
|
|
3213
|
-
|
|
3214
|
-
border: 1px solid rgba(255, 255, 255, 0.07);
|
|
3215
|
-
box-shadow:
|
|
3216
|
-
inset 0 1px 0 rgba(255, 255, 255, 0.03),
|
|
3217
|
-
0 12px 30px rgba(0, 0, 0, 0.18);
|
|
3429
|
+
padding: 8px 12px;
|
|
3430
|
+
background: #282825;
|
|
3431
|
+
border-radius: 16px;
|
|
3218
3432
|
}
|
|
3219
3433
|
`;
|
|
3220
3434
|
var Header2 = import_styled7.default.div`
|
|
@@ -3546,6 +3760,7 @@ var HeroSubtitle = import_styled8.default.p`
|
|
|
3546
3760
|
// src/components/chat-thread/index.tsx
|
|
3547
3761
|
var import_jsx_runtime10 = require("@emotion/react/jsx-runtime");
|
|
3548
3762
|
var CHAT_THREAD_PINNED_THRESHOLD_PX = 32;
|
|
3763
|
+
var CHAT_THREAD_LOAD_PREVIOUS_THRESHOLD_PX = 80;
|
|
3549
3764
|
var isThreadPinnedToBottom = (container) => container.scrollHeight - container.clientHeight - container.scrollTop <= CHAT_THREAD_PINNED_THRESHOLD_PX;
|
|
3550
3765
|
var renderChatMessage = ({
|
|
3551
3766
|
message,
|
|
@@ -3619,9 +3834,13 @@ var ChatThreadView = ({
|
|
|
3619
3834
|
historyMessages,
|
|
3620
3835
|
streamingMessage,
|
|
3621
3836
|
error: error2,
|
|
3837
|
+
isLoadingPreviousMessages = false,
|
|
3838
|
+
previousMessagesError,
|
|
3622
3839
|
retryButtonLabel,
|
|
3623
3840
|
scrollToLatestLabel,
|
|
3841
|
+
sessionHistoryLoadingLabel,
|
|
3624
3842
|
onRetry,
|
|
3843
|
+
onLoadPreviousMessages,
|
|
3625
3844
|
onConfirmationSubmit,
|
|
3626
3845
|
onQuestionnaireSubmit,
|
|
3627
3846
|
renderMessageBlock
|
|
@@ -3636,6 +3855,7 @@ var ChatThreadView = ({
|
|
|
3636
3855
|
const latestHistoryMessage = historyMessages[historyMessages.length - 1];
|
|
3637
3856
|
const latestTurnRef = (0, import_react11.useRef)(null);
|
|
3638
3857
|
const reservedSpaceFrameRef = (0, import_react11.useRef)(null);
|
|
3858
|
+
const isLoadingPreviousRef = (0, import_react11.useRef)(false);
|
|
3639
3859
|
const isPinnedRef = (0, import_react11.useRef)(true);
|
|
3640
3860
|
const lastHistoryMessageIdRef = (0, import_react11.useRef)(latestHistoryMessage?.id);
|
|
3641
3861
|
const lastStreamingMessageIdRef = (0, import_react11.useRef)(streamingMessage?.id);
|
|
@@ -3682,17 +3902,45 @@ var ChatThreadView = ({
|
|
|
3682
3902
|
},
|
|
3683
3903
|
[markThreadPinned, scrollToBottom]
|
|
3684
3904
|
);
|
|
3905
|
+
const handleLoadPreviousMessages = (0, import_react11.useCallback)(async () => {
|
|
3906
|
+
const container = containerRef.current;
|
|
3907
|
+
if (!container || !onLoadPreviousMessages || isLoadingPreviousMessages) {
|
|
3908
|
+
return;
|
|
3909
|
+
}
|
|
3910
|
+
if (isLoadingPreviousRef.current) {
|
|
3911
|
+
return;
|
|
3912
|
+
}
|
|
3913
|
+
isLoadingPreviousRef.current = true;
|
|
3914
|
+
const previousScrollHeight = container.scrollHeight;
|
|
3915
|
+
const previousScrollTop = container.scrollTop;
|
|
3916
|
+
try {
|
|
3917
|
+
await onLoadPreviousMessages();
|
|
3918
|
+
} catch {
|
|
3919
|
+
return;
|
|
3920
|
+
} finally {
|
|
3921
|
+
isLoadingPreviousRef.current = false;
|
|
3922
|
+
}
|
|
3923
|
+
window.requestAnimationFrame(() => {
|
|
3924
|
+
const nextContainer = containerRef.current;
|
|
3925
|
+
if (!nextContainer)
|
|
3926
|
+
return;
|
|
3927
|
+
nextContainer.scrollTop = nextContainer.scrollHeight - previousScrollHeight + previousScrollTop;
|
|
3928
|
+
});
|
|
3929
|
+
}, [isLoadingPreviousMessages, onLoadPreviousMessages]);
|
|
3685
3930
|
const handleContainerScroll = (0, import_react11.useCallback)(() => {
|
|
3686
3931
|
const container = containerRef.current;
|
|
3687
3932
|
if (!container)
|
|
3688
3933
|
return;
|
|
3934
|
+
if (onLoadPreviousMessages && container.scrollTop <= CHAT_THREAD_LOAD_PREVIOUS_THRESHOLD_PX) {
|
|
3935
|
+
void handleLoadPreviousMessages();
|
|
3936
|
+
}
|
|
3689
3937
|
const nextPinned = isThreadPinnedToBottom(container);
|
|
3690
3938
|
isPinnedRef.current = nextPinned;
|
|
3691
3939
|
setIsDetached(!nextPinned);
|
|
3692
3940
|
if (nextPinned) {
|
|
3693
3941
|
setPendingNewMessageCount(0);
|
|
3694
3942
|
}
|
|
3695
|
-
}, []);
|
|
3943
|
+
}, [handleLoadPreviousMessages, onLoadPreviousMessages]);
|
|
3696
3944
|
(0, import_react11.useLayoutEffect)(() => {
|
|
3697
3945
|
const nextHistoryMessageId = latestHistoryMessage?.id;
|
|
3698
3946
|
if (lastHistoryMessageIdRef.current === nextHistoryMessageId) {
|
|
@@ -3820,6 +4068,8 @@ var ChatThreadView = ({
|
|
|
3820
4068
|
}, [latestTurn, scrollToBottom]);
|
|
3821
4069
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(ThreadViewport, { children: [
|
|
3822
4070
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(Container, { ref: containerRef, "data-testid": "chat-thread", onScroll: handleContainerScroll, children: [
|
|
4071
|
+
isLoadingPreviousMessages ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PreviousMessagesStateRow, { "data-testid": "chat-thread-loading-previous", children: sessionHistoryLoadingLabel }) : null,
|
|
4072
|
+
previousMessagesError ? /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(PreviousMessagesStateRow, { "data-testid": "chat-thread-load-previous-error", children: previousMessagesError }) : null,
|
|
3823
4073
|
conversationTurns.map((turn, turnIndex) => {
|
|
3824
4074
|
const isLatestTurn = turnIndex === conversationTurns.length - 1;
|
|
3825
4075
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
|
|
@@ -3876,14 +4126,25 @@ var EMPTY_MESSAGES = [];
|
|
|
3876
4126
|
var ChatThread = () => {
|
|
3877
4127
|
const activeSessionId = useChatStore((s) => s.activeSessionId);
|
|
3878
4128
|
const hasSessions = useChatStore((s) => s.sessions.length > 0);
|
|
3879
|
-
const
|
|
3880
|
-
(s) => s.sessions.find((
|
|
4129
|
+
const activeSession = useChatStore(
|
|
4130
|
+
(s) => s.sessions.find((session) => session.sessionId === s.activeSessionId)
|
|
3881
4131
|
);
|
|
4132
|
+
const activeSessionMode = activeSession?.mode ?? DEFAULT_CHAT_AGENT_MODE;
|
|
3882
4133
|
const messages = useChatStore(
|
|
3883
4134
|
(s) => s.messagesBySession[s.activeSessionId ?? ""] ?? EMPTY_MESSAGES
|
|
3884
4135
|
);
|
|
4136
|
+
const sessionMessageLoadStatus = useChatStore(
|
|
4137
|
+
(s) => s.sessionMessageLoadStatusBySession[s.activeSessionId ?? ""]
|
|
4138
|
+
);
|
|
3885
4139
|
const streamingMessage = useChatStore((s) => s.streamingMessageBySession[s.activeSessionId ?? ""]);
|
|
3886
4140
|
const error2 = useChatStore((s) => s.errorBySession[s.activeSessionId ?? ""]);
|
|
4141
|
+
const historyMessagePagination = useChatStore(
|
|
4142
|
+
(s) => s.historyMessagePaginationBySession[s.activeSessionId ?? ""]
|
|
4143
|
+
);
|
|
4144
|
+
const prependHistorySessionMessagesPage = useChatStore((s) => s.prependHistorySessionMessagesPage);
|
|
4145
|
+
const setHistorySessionPreviousMessagesLoadStatus = useChatStore(
|
|
4146
|
+
(s) => s.setHistorySessionPreviousMessagesLoadStatus
|
|
4147
|
+
);
|
|
3887
4148
|
const updateQA = useChatStore((s) => s.updateQuestionnaireAnswers);
|
|
3888
4149
|
const clearSessionError = useChatStore((s) => s.clearSessionError);
|
|
3889
4150
|
const {
|
|
@@ -3892,6 +4153,7 @@ var ChatThread = () => {
|
|
|
3892
4153
|
renderMessageBlock,
|
|
3893
4154
|
handleQuestionnaireSubmit: customQuestionnaireSubmit,
|
|
3894
4155
|
handleConfirmationSubmit: customConfirmationSubmit,
|
|
4156
|
+
onLoadMoreHistoryMessages,
|
|
3895
4157
|
labels
|
|
3896
4158
|
} = useChatContext();
|
|
3897
4159
|
const handleRetry = (0, import_react11.useCallback)(() => {
|
|
@@ -3954,6 +4216,42 @@ var ChatThread = () => {
|
|
|
3954
4216
|
},
|
|
3955
4217
|
[activeSessionId, activeSessionMode, sendRef, customConfirmationSubmit]
|
|
3956
4218
|
);
|
|
4219
|
+
const handleLoadPreviousMessages = (0, import_react11.useCallback)(async () => {
|
|
4220
|
+
if (!activeSession || !onLoadMoreHistoryMessages || !historyMessagePagination?.hasMorePrevious || !historyMessagePagination.previousCursor || historyMessagePagination.isLoadingPrevious) {
|
|
4221
|
+
return;
|
|
4222
|
+
}
|
|
4223
|
+
setHistorySessionPreviousMessagesLoadStatus(activeSession.sessionId, true);
|
|
4224
|
+
try {
|
|
4225
|
+
const page = await onLoadMoreHistoryMessages({
|
|
4226
|
+
session: activeSession,
|
|
4227
|
+
cursor: historyMessagePagination.previousCursor
|
|
4228
|
+
});
|
|
4229
|
+
if (page) {
|
|
4230
|
+
prependHistorySessionMessagesPage(activeSession.sessionId, page);
|
|
4231
|
+
return;
|
|
4232
|
+
}
|
|
4233
|
+
setHistorySessionPreviousMessagesLoadStatus(activeSession.sessionId, false);
|
|
4234
|
+
} catch (error3) {
|
|
4235
|
+
setHistorySessionPreviousMessagesLoadStatus(
|
|
4236
|
+
activeSession.sessionId,
|
|
4237
|
+
false,
|
|
4238
|
+
error3 instanceof Error ? error3.message : String(error3)
|
|
4239
|
+
);
|
|
4240
|
+
throw error3;
|
|
4241
|
+
}
|
|
4242
|
+
}, [
|
|
4243
|
+
activeSession,
|
|
4244
|
+
historyMessagePagination,
|
|
4245
|
+
onLoadMoreHistoryMessages,
|
|
4246
|
+
prependHistorySessionMessagesPage,
|
|
4247
|
+
setHistorySessionPreviousMessagesLoadStatus
|
|
4248
|
+
]);
|
|
4249
|
+
const canLoadPreviousMessages = Boolean(
|
|
4250
|
+
activeSession && onLoadMoreHistoryMessages && historyMessagePagination?.hasMorePrevious && historyMessagePagination.previousCursor && !historyMessagePagination.isLoadingPrevious
|
|
4251
|
+
);
|
|
4252
|
+
if (hasSessions && sessionMessageLoadStatus === "loading" && messages.length === 0 && !streamingMessage) {
|
|
4253
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ThreadStateViewport, { "data-testid": "chat-thread-loading-state", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ThreadStateText, { children: labels.sessionHistoryLoading }) });
|
|
4254
|
+
}
|
|
3957
4255
|
if (!hasSessions || messages.length === 0 && !streamingMessage) {
|
|
3958
4256
|
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ChatThreadEmptyState, {});
|
|
3959
4257
|
}
|
|
@@ -3964,9 +4262,13 @@ var ChatThread = () => {
|
|
|
3964
4262
|
historyMessages: messages,
|
|
3965
4263
|
streamingMessage,
|
|
3966
4264
|
error: error2,
|
|
4265
|
+
isLoadingPreviousMessages: historyMessagePagination?.isLoadingPrevious,
|
|
4266
|
+
previousMessagesError: historyMessagePagination?.error,
|
|
3967
4267
|
retryButtonLabel: labels.retryButton,
|
|
3968
4268
|
scrollToLatestLabel: labels.scrollToLatest,
|
|
4269
|
+
sessionHistoryLoadingLabel: labels.sessionHistoryLoading,
|
|
3969
4270
|
onRetry: handleRetry,
|
|
4271
|
+
onLoadPreviousMessages: canLoadPreviousMessages ? handleLoadPreviousMessages : void 0,
|
|
3970
4272
|
onConfirmationSubmit: handleConfirmation,
|
|
3971
4273
|
onQuestionnaireSubmit: handleQuestionnaireSubmit,
|
|
3972
4274
|
renderMessageBlock
|
|
@@ -3980,6 +4282,18 @@ var ThreadViewport = import_styled9.default.div`
|
|
|
3980
4282
|
flex: 1;
|
|
3981
4283
|
min-height: 0;
|
|
3982
4284
|
`;
|
|
4285
|
+
var ThreadStateViewport = import_styled9.default.div`
|
|
4286
|
+
display: flex;
|
|
4287
|
+
flex: 1;
|
|
4288
|
+
min-height: 0;
|
|
4289
|
+
align-items: center;
|
|
4290
|
+
justify-content: center;
|
|
4291
|
+
padding: 24px;
|
|
4292
|
+
`;
|
|
4293
|
+
var ThreadStateText = import_styled9.default.div`
|
|
4294
|
+
color: var(--text-secondary, rgba(255, 255, 255, 0.64));
|
|
4295
|
+
font-size: 14px;
|
|
4296
|
+
`;
|
|
3983
4297
|
var Container = import_styled9.default.div`
|
|
3984
4298
|
display: flex;
|
|
3985
4299
|
flex: 1;
|
|
@@ -3987,7 +4301,7 @@ var Container = import_styled9.default.div`
|
|
|
3987
4301
|
gap: 18px;
|
|
3988
4302
|
min-height: 0;
|
|
3989
4303
|
overflow: auto;
|
|
3990
|
-
padding: 24px
|
|
4304
|
+
padding: 24px 16px 88px;
|
|
3991
4305
|
overscroll-behavior: contain;
|
|
3992
4306
|
|
|
3993
4307
|
&::-webkit-scrollbar {
|
|
@@ -4006,10 +4320,23 @@ var Container = import_styled9.default.div`
|
|
|
4006
4320
|
var MessageSlot = import_styled9.default.div`
|
|
4007
4321
|
display: flex;
|
|
4008
4322
|
`;
|
|
4323
|
+
var PreviousMessagesStateRow = import_styled9.default.div`
|
|
4324
|
+
width: 100%;
|
|
4325
|
+
max-width: var(--chat-content-max-width, 48rem);
|
|
4326
|
+
margin-right: auto;
|
|
4327
|
+
margin-left: auto;
|
|
4328
|
+
color: var(--text-secondary, rgba(255, 255, 255, 0.64));
|
|
4329
|
+
font-size: 13px;
|
|
4330
|
+
text-align: center;
|
|
4331
|
+
`;
|
|
4009
4332
|
var ConversationTurn = import_styled9.default.div`
|
|
4010
4333
|
display: flex;
|
|
4011
4334
|
flex-direction: column;
|
|
4012
4335
|
gap: 18px;
|
|
4336
|
+
width: 100%;
|
|
4337
|
+
max-width: var(--chat-content-max-width, 48rem);
|
|
4338
|
+
margin-right: auto;
|
|
4339
|
+
margin-left: auto;
|
|
4013
4340
|
`;
|
|
4014
4341
|
var ErrorText = import_styled9.default.div`
|
|
4015
4342
|
color: #ff7b72;
|
|
@@ -7797,7 +8124,7 @@ var PrimaryButton = (0, import_styled13.default)(import_compass_ui3.Button)`
|
|
|
7797
8124
|
min-width: 24px;
|
|
7798
8125
|
width: 24px;
|
|
7799
8126
|
height: 24px;
|
|
7800
|
-
background: ${({ $canSend }) => $canSend ? "#fcfbf8" : "rgba(
|
|
8127
|
+
background: ${({ $canSend }) => $canSend ? "#fcfbf8" : "rgba(252,251,248,0.3);"};
|
|
7801
8128
|
color: ${({ $canSend }) => $canSend ? "#5b5448" : "rgba(255, 255, 255, 0.72)"};
|
|
7802
8129
|
border-radius: 12px;
|
|
7803
8130
|
border: 1px solid ${({ $canSend }) => $canSend ? "rgba(198, 188, 170, 0.38)" : "transparent"};
|
|
@@ -7808,7 +8135,7 @@ var PrimaryButton = (0, import_styled13.default)(import_compass_ui3.Button)`
|
|
|
7808
8135
|
}
|
|
7809
8136
|
|
|
7810
8137
|
&:hover:not(:disabled) {
|
|
7811
|
-
background: ${({ $canSend }) => $canSend ? "#f7f4ec" : "rgba(
|
|
8138
|
+
background: ${({ $canSend }) => $canSend ? "#f7f4ec" : "rgba(252,251,248,0.3);"};
|
|
7812
8139
|
color: ${({ $canSend }) => $canSend ? "#4f493f" : "rgba(255, 255, 255, 0.72)"};
|
|
7813
8140
|
border-color: ${({ $canSend }) => $canSend ? "rgba(198, 188, 170, 0.46)" : "transparent"};
|
|
7814
8141
|
}
|
|
@@ -7876,7 +8203,7 @@ var StopSpinner = import_styled13.default.span`
|
|
|
7876
8203
|
var import_jsx_runtime16 = require("@emotion/react/jsx-runtime");
|
|
7877
8204
|
var CHAT_COMPOSER_LINE_HEIGHT_PX = 20;
|
|
7878
8205
|
var CHAT_COMPOSER_MAX_ROWS = 7;
|
|
7879
|
-
var CHAT_COMPOSER_PADDING_TOP_PX =
|
|
8206
|
+
var CHAT_COMPOSER_PADDING_TOP_PX = 12;
|
|
7880
8207
|
var CHAT_COMPOSER_PADDING_BOTTOM_PX = 12;
|
|
7881
8208
|
var CHAT_COMPOSER_PADDING_BLOCK_PX = CHAT_COMPOSER_PADDING_TOP_PX + CHAT_COMPOSER_PADDING_BOTTOM_PX;
|
|
7882
8209
|
var CHAT_COMPOSER_MIN_ROWS = 4;
|
|
@@ -8111,6 +8438,10 @@ var ChatComposerView = ({
|
|
|
8111
8438
|
setActiveSkillNavigation({ queryKey: "", index: 0 });
|
|
8112
8439
|
};
|
|
8113
8440
|
const handleKeyDown = (event) => {
|
|
8441
|
+
const isImeComposing = event.nativeEvent.isComposing || event.keyCode === 229;
|
|
8442
|
+
if (event.key === "Enter" && isImeComposing) {
|
|
8443
|
+
return;
|
|
8444
|
+
}
|
|
8114
8445
|
if (skillQueryMatch) {
|
|
8115
8446
|
if (event.key === "ArrowDown" && filteredSkills.length > 0) {
|
|
8116
8447
|
event.preventDefault();
|
|
@@ -8388,7 +8719,7 @@ var Surface = import_styled14.default.div`
|
|
|
8388
8719
|
'input'
|
|
8389
8720
|
'footer';
|
|
8390
8721
|
width: 100%;
|
|
8391
|
-
max-width:
|
|
8722
|
+
max-width: var(--chat-content-max-width, 48rem);
|
|
8392
8723
|
margin: 0 auto;
|
|
8393
8724
|
background: var(--border-color);
|
|
8394
8725
|
border-radius: 20px;
|
|
@@ -8649,6 +8980,7 @@ var SkillButton = import_styled14.default.button`
|
|
|
8649
8980
|
`;
|
|
8650
8981
|
|
|
8651
8982
|
// src/components/chat-conversation-list/index.tsx
|
|
8983
|
+
var import_react20 = require("react");
|
|
8652
8984
|
var import_styled16 = __toESM(require("@emotion/styled"));
|
|
8653
8985
|
|
|
8654
8986
|
// src/components/chat-conversation-list/components/chat-session-item.tsx
|
|
@@ -8662,6 +8994,7 @@ var ChatSessionItem = (0, import_react19.memo)(
|
|
|
8662
8994
|
{
|
|
8663
8995
|
type: "button",
|
|
8664
8996
|
"data-active": isActive,
|
|
8997
|
+
"data-testid": `chat-session-item-${session.sessionId}`,
|
|
8665
8998
|
onClick: () => onClick(session.sessionId),
|
|
8666
8999
|
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(SessionMeta, { children: [
|
|
8667
9000
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(SessionTitle, { children: session.title }),
|
|
@@ -8709,14 +9042,130 @@ var ModeBadge = import_styled15.default.span`
|
|
|
8709
9042
|
background: rgba(255, 255, 255, 0.04);
|
|
8710
9043
|
`;
|
|
8711
9044
|
|
|
9045
|
+
// src/components/chat-conversation-list/lib/history-session-selection.ts
|
|
9046
|
+
var shouldLoadHistorySessionMessages = ({
|
|
9047
|
+
sessionId,
|
|
9048
|
+
messagesBySession,
|
|
9049
|
+
loadStatusBySession,
|
|
9050
|
+
isStreamingBySession
|
|
9051
|
+
}) => {
|
|
9052
|
+
if (isStreamingBySession[sessionId])
|
|
9053
|
+
return false;
|
|
9054
|
+
if (loadStatusBySession[sessionId] === "loading")
|
|
9055
|
+
return false;
|
|
9056
|
+
if (loadStatusBySession[sessionId] === "error")
|
|
9057
|
+
return true;
|
|
9058
|
+
if (loadStatusBySession[sessionId] === "loaded")
|
|
9059
|
+
return false;
|
|
9060
|
+
return messagesBySession[sessionId] === void 0;
|
|
9061
|
+
};
|
|
9062
|
+
|
|
8712
9063
|
// src/components/chat-conversation-list/index.tsx
|
|
8713
9064
|
var import_jsx_runtime18 = require("@emotion/react/jsx-runtime");
|
|
9065
|
+
var SCROLL_LOAD_MORE_THRESHOLD_PX = 80;
|
|
9066
|
+
var shouldLoadMoreSessions = ({
|
|
9067
|
+
scrollTop,
|
|
9068
|
+
clientHeight,
|
|
9069
|
+
scrollHeight,
|
|
9070
|
+
threshold = SCROLL_LOAD_MORE_THRESHOLD_PX
|
|
9071
|
+
}) => scrollHeight - scrollTop - clientHeight <= threshold;
|
|
9072
|
+
var isHistorySessionMessagesPage = (value) => typeof value === "object" && value !== null && Array.isArray(value.messages);
|
|
8714
9073
|
var ChatConversationList = () => {
|
|
8715
|
-
const { labels } = useChatContext();
|
|
8716
|
-
const
|
|
9074
|
+
const { labels, historySessionList, onLoadMoreSessions, onSelectHistorySession, store } = useChatContext();
|
|
9075
|
+
const localSessions = useChatStore((s) => s.sessions);
|
|
8717
9076
|
const activeSessionId = useChatStore((s) => s.activeSessionId);
|
|
8718
9077
|
const startNewChat = useChatStore((s) => s.startNewChat);
|
|
8719
9078
|
const setActiveSession = useChatStore((s) => s.setActiveSession);
|
|
9079
|
+
const hydrateHistorySessions = useChatStore((s) => s.hydrateHistorySessions);
|
|
9080
|
+
const hydrateHistorySessionMessages = useChatStore((s) => s.hydrateHistorySessionMessages);
|
|
9081
|
+
const hydrateHistorySessionMessagesPage = useChatStore((s) => s.hydrateHistorySessionMessagesPage);
|
|
9082
|
+
const setHistorySessionMessageLoadStatus = useChatStore(
|
|
9083
|
+
(s) => s.setHistorySessionMessageLoadStatus
|
|
9084
|
+
);
|
|
9085
|
+
const isLoadingMoreRef = (0, import_react20.useRef)(false);
|
|
9086
|
+
const hasSeenLoadingMoreRef = (0, import_react20.useRef)(false);
|
|
9087
|
+
(0, import_react20.useEffect)(() => {
|
|
9088
|
+
if (!historySessionList)
|
|
9089
|
+
return;
|
|
9090
|
+
hydrateHistorySessions(historySessionList.sessions);
|
|
9091
|
+
}, [historySessionList, hydrateHistorySessions]);
|
|
9092
|
+
(0, import_react20.useEffect)(() => {
|
|
9093
|
+
if (historySessionList?.isLoading) {
|
|
9094
|
+
hasSeenLoadingMoreRef.current = true;
|
|
9095
|
+
return;
|
|
9096
|
+
}
|
|
9097
|
+
if (hasSeenLoadingMoreRef.current) {
|
|
9098
|
+
hasSeenLoadingMoreRef.current = false;
|
|
9099
|
+
isLoadingMoreRef.current = false;
|
|
9100
|
+
}
|
|
9101
|
+
}, [historySessionList?.isLoading]);
|
|
9102
|
+
(0, import_react20.useEffect)(() => {
|
|
9103
|
+
isLoadingMoreRef.current = false;
|
|
9104
|
+
hasSeenLoadingMoreRef.current = false;
|
|
9105
|
+
}, [historySessionList?.sessions.length, historySessionList?.hasMore]);
|
|
9106
|
+
const sessions = (0, import_react20.useMemo)(() => {
|
|
9107
|
+
if (!historySessionList) {
|
|
9108
|
+
return localSessions;
|
|
9109
|
+
}
|
|
9110
|
+
const localSessionIds = new Set(localSessions.map((session) => session.sessionId));
|
|
9111
|
+
return [
|
|
9112
|
+
...localSessions,
|
|
9113
|
+
...historySessionList.sessions.filter((session) => !localSessionIds.has(session.sessionId))
|
|
9114
|
+
];
|
|
9115
|
+
}, [historySessionList, localSessions]);
|
|
9116
|
+
const handleSessionListScroll = (event) => {
|
|
9117
|
+
if (!historySessionList?.hasMore || historySessionList.isLoading || !onLoadMoreSessions || isLoadingMoreRef.current) {
|
|
9118
|
+
return;
|
|
9119
|
+
}
|
|
9120
|
+
const target = event.currentTarget;
|
|
9121
|
+
if (shouldLoadMoreSessions({
|
|
9122
|
+
scrollTop: target.scrollTop,
|
|
9123
|
+
clientHeight: target.clientHeight,
|
|
9124
|
+
scrollHeight: target.scrollHeight
|
|
9125
|
+
})) {
|
|
9126
|
+
isLoadingMoreRef.current = true;
|
|
9127
|
+
void Promise.resolve(onLoadMoreSessions()).catch(() => {
|
|
9128
|
+
isLoadingMoreRef.current = false;
|
|
9129
|
+
hasSeenLoadingMoreRef.current = false;
|
|
9130
|
+
});
|
|
9131
|
+
}
|
|
9132
|
+
};
|
|
9133
|
+
const handleSelectSession = async (sessionId) => {
|
|
9134
|
+
setActiveSession(sessionId);
|
|
9135
|
+
const session = sessions.find((item) => item.sessionId === sessionId);
|
|
9136
|
+
if (!session || !onSelectHistorySession) {
|
|
9137
|
+
return;
|
|
9138
|
+
}
|
|
9139
|
+
const state = store.getState();
|
|
9140
|
+
const shouldLoad = shouldLoadHistorySessionMessages({
|
|
9141
|
+
sessionId,
|
|
9142
|
+
messagesBySession: state.messagesBySession,
|
|
9143
|
+
loadStatusBySession: state.sessionMessageLoadStatusBySession,
|
|
9144
|
+
isStreamingBySession: state.isStreamingBySession
|
|
9145
|
+
});
|
|
9146
|
+
if (!shouldLoad) {
|
|
9147
|
+
return;
|
|
9148
|
+
}
|
|
9149
|
+
setHistorySessionMessageLoadStatus(sessionId, "loading");
|
|
9150
|
+
try {
|
|
9151
|
+
const result = await onSelectHistorySession(session);
|
|
9152
|
+
if (Array.isArray(result)) {
|
|
9153
|
+
hydrateHistorySessionMessages(sessionId, result);
|
|
9154
|
+
return;
|
|
9155
|
+
}
|
|
9156
|
+
if (isHistorySessionMessagesPage(result)) {
|
|
9157
|
+
hydrateHistorySessionMessagesPage(sessionId, result);
|
|
9158
|
+
return;
|
|
9159
|
+
}
|
|
9160
|
+
setHistorySessionMessageLoadStatus(sessionId, "loaded");
|
|
9161
|
+
} catch (error2) {
|
|
9162
|
+
setHistorySessionMessageLoadStatus(
|
|
9163
|
+
sessionId,
|
|
9164
|
+
"error",
|
|
9165
|
+
error2 instanceof Error ? error2.message : String(error2)
|
|
9166
|
+
);
|
|
9167
|
+
}
|
|
9168
|
+
};
|
|
8720
9169
|
const modeLabels = {
|
|
8721
9170
|
ask: labels.modeLabelAsk,
|
|
8722
9171
|
plan: labels.modeLabelPlan,
|
|
@@ -8727,16 +9176,21 @@ var ChatConversationList = () => {
|
|
|
8727
9176
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Title3, { children: "Sessions" }),
|
|
8728
9177
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)(CreateButton, { type: "button", "data-testid": "chat-create-session", onClick: startNewChat, children: labels.newChat })
|
|
8729
9178
|
] }),
|
|
8730
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.
|
|
8731
|
-
|
|
8732
|
-
|
|
8733
|
-
|
|
8734
|
-
|
|
8735
|
-
|
|
8736
|
-
|
|
8737
|
-
|
|
8738
|
-
|
|
8739
|
-
|
|
9179
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(List2, { "data-testid": "chat-session-list", onScroll: handleSessionListScroll, children: [
|
|
9180
|
+
sessions.map((session) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(
|
|
9181
|
+
ChatSessionItem,
|
|
9182
|
+
{
|
|
9183
|
+
session,
|
|
9184
|
+
isActive: activeSessionId === session.sessionId,
|
|
9185
|
+
modeLabel: modeLabels[session.mode ?? DEFAULT_CHAT_AGENT_MODE] ?? "",
|
|
9186
|
+
onClick: (sessionId) => void handleSelectSession(sessionId)
|
|
9187
|
+
},
|
|
9188
|
+
session.sessionId
|
|
9189
|
+
)),
|
|
9190
|
+
historySessionList?.isLoading ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(StateRow, { "data-testid": "chat-session-history-loading", children: labels.sessionHistoryLoading }) : null,
|
|
9191
|
+
historySessionList?.error ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(StateRow, { "data-testid": "chat-session-history-error", children: historySessionList.error || labels.sessionHistoryLoadFailed }) : null,
|
|
9192
|
+
historySessionList && !historySessionList.isLoading && !historySessionList.error && sessions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(StateRow, { "data-testid": "chat-session-history-empty", children: labels.sessionHistoryEmpty }) : null
|
|
9193
|
+
] })
|
|
8740
9194
|
] });
|
|
8741
9195
|
};
|
|
8742
9196
|
var Container3 = import_styled16.default.aside`
|
|
@@ -8774,6 +9228,11 @@ var List2 = import_styled16.default.div`
|
|
|
8774
9228
|
gap: 8px;
|
|
8775
9229
|
overflow: auto;
|
|
8776
9230
|
`;
|
|
9231
|
+
var StateRow = import_styled16.default.div`
|
|
9232
|
+
padding: 12px;
|
|
9233
|
+
font-size: 13px;
|
|
9234
|
+
color: var(--text-secondary);
|
|
9235
|
+
`;
|
|
8777
9236
|
|
|
8778
9237
|
// src/components/ai-chat/index.tsx
|
|
8779
9238
|
var import_jsx_runtime19 = require("@emotion/react/jsx-runtime");
|
|
@@ -8835,7 +9294,7 @@ var AiChatWorkspaceContent = ({
|
|
|
8835
9294
|
})
|
|
8836
9295
|
);
|
|
8837
9296
|
const shouldShowComposerOnly = showComposerOnlyBeforeFirstMessage && !showConversationList && !isConversationStarted;
|
|
8838
|
-
(0,
|
|
9297
|
+
(0, import_react21.useEffect)(() => {
|
|
8839
9298
|
onConversationStartedChange?.(isConversationStarted);
|
|
8840
9299
|
}, [isConversationStarted, onConversationStartedChange]);
|
|
8841
9300
|
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(Root, { "data-testid": "ai-chat", children: [
|
|
@@ -8974,12 +9433,25 @@ var Root = import_styled17.default.div`
|
|
|
8974
9433
|
overflow: hidden;
|
|
8975
9434
|
`;
|
|
8976
9435
|
var Workspace = import_styled17.default.section`
|
|
9436
|
+
--chat-layout-rem: 16px;
|
|
9437
|
+
--chat-content-margin: calc(var(--chat-layout-rem) * 1);
|
|
9438
|
+
--chat-content-max-width: calc(var(--chat-layout-rem) * 40);
|
|
9439
|
+
|
|
8977
9440
|
flex: 1;
|
|
8978
9441
|
display: flex;
|
|
8979
9442
|
flex-direction: column;
|
|
8980
9443
|
gap: 12px;
|
|
8981
9444
|
min-height: 0;
|
|
8982
9445
|
overflow: hidden;
|
|
9446
|
+
|
|
9447
|
+
@media (min-width: 640px) {
|
|
9448
|
+
--chat-content-margin: calc(var(--chat-layout-rem) * 1.5);
|
|
9449
|
+
}
|
|
9450
|
+
|
|
9451
|
+
@media (min-width: 1024px) {
|
|
9452
|
+
--chat-content-margin: calc(var(--chat-layout-rem) * 4);
|
|
9453
|
+
--chat-content-max-width: calc(var(--chat-layout-rem) * 48);
|
|
9454
|
+
}
|
|
8983
9455
|
`;
|
|
8984
9456
|
var QuickActionsRow = import_styled17.default.div`
|
|
8985
9457
|
display: flex;
|