chore: test deploy snapshot
This commit is contained in:
@@ -3049,6 +3049,19 @@ export function MainChatPanel({
|
||||
const requestItems = Array.isArray(requestItemsState) ? requestItemsState : [];
|
||||
const isCreatingImportedDraftConversationRef = useRef(false);
|
||||
const hasAttemptedInitialConversationRef = useRef(false);
|
||||
const pendingConversationSummaryUpdatesRef = useRef(
|
||||
new Map<
|
||||
string,
|
||||
{
|
||||
incomingMessage: ChatMessage;
|
||||
hasMeaningfulCodexResponse: boolean;
|
||||
hasPendingAttentionResponse: boolean;
|
||||
isForegroundSession: boolean;
|
||||
responseTimestamp: string;
|
||||
}
|
||||
>(),
|
||||
);
|
||||
const conversationSummaryUpdateFrameRef = useRef<number | null>(null);
|
||||
const setDraft = useCallback((value: SetStateAction<string>) => {
|
||||
const nextValue = typeof value === 'function' ? value(draftRef.current) : value;
|
||||
draftRef.current = nextValue;
|
||||
@@ -3066,6 +3079,63 @@ export function MainChatPanel({
|
||||
const setDraftValue = useCallback((value: string) => {
|
||||
setDraft(value);
|
||||
}, [setDraft]);
|
||||
|
||||
const enqueueConversationSummaryUpdate = useCallback(
|
||||
(payload: {
|
||||
sessionId: string;
|
||||
incomingMessage: ChatMessage;
|
||||
hasMeaningfulCodexResponse: boolean;
|
||||
hasPendingAttentionResponse: boolean;
|
||||
isForegroundSession: boolean;
|
||||
responseTimestamp: string;
|
||||
}) => {
|
||||
pendingConversationSummaryUpdatesRef.current.set(payload.sessionId, payload);
|
||||
|
||||
if (conversationSummaryUpdateFrameRef.current !== null) {
|
||||
return;
|
||||
}
|
||||
|
||||
conversationSummaryUpdateFrameRef.current = window.requestAnimationFrame(() => {
|
||||
conversationSummaryUpdateFrameRef.current = null;
|
||||
const batchedUpdates = new Map(pendingConversationSummaryUpdatesRef.current);
|
||||
pendingConversationSummaryUpdatesRef.current.clear();
|
||||
|
||||
if (batchedUpdates.size === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
setConversationItems((previous) =>
|
||||
sortChatConversationSummaries(
|
||||
previous.map((item) => {
|
||||
const update = batchedUpdates.get(item.sessionId);
|
||||
|
||||
if (!update) {
|
||||
return item;
|
||||
}
|
||||
|
||||
return {
|
||||
...item,
|
||||
lastMessagePreview: createConversationPreviewText(update.incomingMessage.text),
|
||||
lastResponsePreview:
|
||||
update.incomingMessage.author === 'codex' && !isPreparingChatReplyText(update.incomingMessage.text)
|
||||
? createConversationPreviewText(update.incomingMessage.text)
|
||||
: item.lastResponsePreview,
|
||||
lastMessageAt: update.responseTimestamp,
|
||||
updatedAt: update.responseTimestamp,
|
||||
hasUnreadResponse:
|
||||
update.hasMeaningfulCodexResponse && !update.isForegroundSession ? true : item.hasUnreadResponse,
|
||||
hasPendingAttention:
|
||||
update.hasPendingAttentionResponse && update.incomingMessage.author === 'codex'
|
||||
? true
|
||||
: item.hasPendingAttention,
|
||||
};
|
||||
}),
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
[setConversationItems],
|
||||
);
|
||||
const setRequestItems = useCallback((next: SetStateAction<ChatConversationRequest[]>) => {
|
||||
setRequestItemsState((previous) => {
|
||||
const safePrevious = Array.isArray(previous) ? previous : [];
|
||||
@@ -3092,6 +3162,14 @@ export function MainChatPanel({
|
||||
activeSessionIdRef.current = activeSessionId;
|
||||
}, [activeSessionId]);
|
||||
|
||||
useEffect(() => {
|
||||
return () => {
|
||||
if (conversationSummaryUpdateFrameRef.current !== null) {
|
||||
window.cancelAnimationFrame(conversationSummaryUpdateFrameRef.current);
|
||||
}
|
||||
};
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (mode !== 'live' || location.pathname !== chatRoutePath) {
|
||||
return;
|
||||
@@ -4337,28 +4415,14 @@ export function MainChatPanel({
|
||||
});
|
||||
const responseTimestamp = new Date().toISOString();
|
||||
|
||||
setConversationItems((previous) =>
|
||||
sortChatConversationSummaries(
|
||||
previous.map((item) =>
|
||||
item.sessionId === sessionId
|
||||
? {
|
||||
...item,
|
||||
lastMessagePreview: createConversationPreviewText(incomingMessage.text),
|
||||
lastResponsePreview:
|
||||
incomingMessage.author === 'codex' && !isPreparingChatReplyText(incomingMessage.text)
|
||||
? createConversationPreviewText(incomingMessage.text)
|
||||
: item.lastResponsePreview,
|
||||
lastMessageAt: responseTimestamp,
|
||||
updatedAt: responseTimestamp,
|
||||
hasUnreadResponse:
|
||||
hasMeaningfulCodexResponse && !isForegroundSession ? true : item.hasUnreadResponse,
|
||||
hasPendingAttention:
|
||||
hasPendingAttentionResponse && incomingMessage.author === 'codex' ? true : item.hasPendingAttention,
|
||||
}
|
||||
: item,
|
||||
),
|
||||
),
|
||||
);
|
||||
enqueueConversationSummaryUpdate({
|
||||
sessionId,
|
||||
incomingMessage,
|
||||
hasMeaningfulCodexResponse,
|
||||
hasPendingAttentionResponse,
|
||||
isForegroundSession,
|
||||
responseTimestamp,
|
||||
});
|
||||
|
||||
const eventConversation = conversationItemsRef.current.find((item) => item.sessionId === sessionId) ?? null;
|
||||
|
||||
|
||||
@@ -521,6 +521,12 @@ type MessageRenderPayload = {
|
||||
promptTargets: Extract<ChatMessagePart, { type: 'prompt' }>[];
|
||||
};
|
||||
|
||||
type MessageRenderPayloadCacheEntry = {
|
||||
messageText: string;
|
||||
messageParts: ChatMessagePart[] | undefined;
|
||||
payload: MessageRenderPayload;
|
||||
};
|
||||
|
||||
const RANK_LINE_PATTERN = /(?:\b(?:rank|score)\b|랭크|점수)\s*[:=]?\s*[-+]?\d+(?:\.\d+)?(?:e[-+]?\d+)?\b/i;
|
||||
const TITLE_VALUE_PATTERN = /^(?:[-*]\s*)?(?:\d+\.\s*)?(?:title|제목)\s*[:=-]\s*(.+)$/i;
|
||||
const LINK_VALUE_PATTERN = /^(?:[-*]\s*)?(?:\d+\.\s*)?(?:link|url|href|링크)\s*[:=-]\s*(https?:\/\/\S+|\/\S+)$/i;
|
||||
@@ -3654,6 +3660,7 @@ export function ChatConversationView({
|
||||
const suppressImmediateSendClickRef = useRef(false);
|
||||
const composerDraftValueRef = useRef(draft);
|
||||
const lastSyncedComposerDraftRef = useRef(draft);
|
||||
const messageRenderPayloadCacheRef = useRef(new Map<number, MessageRenderPayloadCacheEntry>());
|
||||
|
||||
const setComposerDraftValue = (nextValue: string) => {
|
||||
composerDraftValueRef.current = nextValue;
|
||||
@@ -3788,6 +3795,10 @@ export function ChatConversationView({
|
||||
forceComposerDraftSync();
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
messageRenderPayloadCacheRef.current.clear();
|
||||
}, [sessionId]);
|
||||
|
||||
const shouldShowConversationLoadingOverlay = isConversationLoading && visibleMessages.length === 0;
|
||||
|
||||
const orderedMessages = useMemo(() => {
|
||||
@@ -3954,14 +3965,44 @@ export function ChatConversationView({
|
||||
|
||||
setExpandedSystemExecutionActivityRequestId(null);
|
||||
}, [systemExecutionDisplayMode]);
|
||||
const messageRenderPayloadById = useMemo(
|
||||
() =>
|
||||
new Map(
|
||||
orderedMessages.map((message) => [message.id, extractMessageRenderPayload(message)] as const),
|
||||
),
|
||||
[orderedMessages],
|
||||
const getCachedMessageRenderPayload = useCallback(
|
||||
(message: ChatMessage) => {
|
||||
const cached = messageRenderPayloadCacheRef.current.get(message.id);
|
||||
|
||||
if (cached && cached.messageText === message.text && cached.messageParts === message.parts) {
|
||||
return cached.payload;
|
||||
}
|
||||
|
||||
const payload = extractMessageRenderPayload(message);
|
||||
messageRenderPayloadCacheRef.current.set(message.id, {
|
||||
messageText: message.text,
|
||||
messageParts: message.parts,
|
||||
payload,
|
||||
});
|
||||
return payload;
|
||||
},
|
||||
[],
|
||||
);
|
||||
|
||||
const messageRenderPayloadById = useMemo(() => {
|
||||
const activeMessageIds = new Set<number>();
|
||||
const nextMap = new Map<number, MessageRenderPayload>();
|
||||
|
||||
orderedMessages.forEach((message) => {
|
||||
activeMessageIds.add(message.id);
|
||||
nextMap.set(message.id, getCachedMessageRenderPayload(message));
|
||||
});
|
||||
|
||||
const cachedMessageIds = Array.from(messageRenderPayloadCacheRef.current.keys());
|
||||
cachedMessageIds.forEach((messageId) => {
|
||||
if (!activeMessageIds.has(messageId)) {
|
||||
messageRenderPayloadCacheRef.current.delete(messageId);
|
||||
}
|
||||
});
|
||||
|
||||
return nextMap;
|
||||
}, [orderedMessages, getCachedMessageRenderPayload]);
|
||||
|
||||
useEffect(() => {
|
||||
setOpenedPreviewUrls([]);
|
||||
setExpandedGroupIds([]);
|
||||
|
||||
Reference in New Issue
Block a user