feat: refine codex live chat context flows
This commit is contained in:
@@ -2,6 +2,7 @@ import type { Dispatch, SetStateAction } from 'react';
|
||||
import { appendClientIdHeader, getOrCreateClientId } from '../clientIdentity';
|
||||
import { getRegisteredAccessToken, hasRegisteredAccessTokenAccess } from '../tokenAccess';
|
||||
import { reportClientError } from '../errorLogApi';
|
||||
import { copyTextToClipboard } from '../../../utils/clipboard';
|
||||
import type {
|
||||
ChatActivityEvent,
|
||||
ChatConversationActivityLog,
|
||||
@@ -839,32 +840,7 @@ export async function diagnoseConnectionFailure(targetUrl: string, closeEvent?:
|
||||
}
|
||||
|
||||
export async function copyText(text: string) {
|
||||
if (typeof navigator !== 'undefined' && navigator.clipboard?.writeText) {
|
||||
await navigator.clipboard.writeText(text);
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof document === 'undefined') {
|
||||
throw new Error('클립보드를 사용할 수 없습니다.');
|
||||
}
|
||||
|
||||
const textarea = document.createElement('textarea');
|
||||
textarea.value = text;
|
||||
textarea.setAttribute('readonly', '');
|
||||
textarea.style.position = 'fixed';
|
||||
textarea.style.opacity = '0';
|
||||
document.body.appendChild(textarea);
|
||||
textarea.select();
|
||||
|
||||
try {
|
||||
const copied = document.execCommand('copy');
|
||||
|
||||
if (!copied) {
|
||||
throw new Error('복사 명령이 거부되었습니다.');
|
||||
}
|
||||
} finally {
|
||||
document.body.removeChild(textarea);
|
||||
}
|
||||
return copyTextToClipboard(text);
|
||||
}
|
||||
|
||||
export type PreviewCopyResult = 'text' | 'image' | 'url';
|
||||
@@ -1419,6 +1395,23 @@ export async function deleteChatConversationRoom(sessionId: string) {
|
||||
return response;
|
||||
}
|
||||
|
||||
export async function clearChatConversationRoom(sessionId: string) {
|
||||
const clientId = getOrCreateClientId();
|
||||
const response = await requestChatApi<{ ok: boolean; item: ChatConversationSummary }>(
|
||||
`/conversations/${encodeURIComponent(sessionId)}/clear`,
|
||||
{
|
||||
method: 'POST',
|
||||
},
|
||||
);
|
||||
|
||||
invalidateChatConversationListCache();
|
||||
|
||||
return {
|
||||
...response.item,
|
||||
notifyOffline: resolveSyncedChatOfflineNotificationSetting(response.item.sessionId, response.item.notifyOffline, clientId),
|
||||
};
|
||||
}
|
||||
|
||||
export async function deleteChatConversationRequest(sessionId: string, requestId: string) {
|
||||
const response = await requestChatApi<{ ok: boolean; deleted: boolean; sessionId: string; requestId: string }>(
|
||||
`/conversations/${encodeURIComponent(sessionId)}/requests/${encodeURIComponent(requestId)}`,
|
||||
@@ -1450,13 +1443,16 @@ function areChatMessagesEquivalent(left: ChatMessage[], right: ChatMessage[]) {
|
||||
|
||||
return left.every((message, index) => {
|
||||
const other = right[index];
|
||||
const leftParts = JSON.stringify(message.parts ?? []);
|
||||
const rightParts = JSON.stringify(other?.parts ?? []);
|
||||
|
||||
return (
|
||||
other &&
|
||||
message.id === other.id &&
|
||||
message.author === other.author &&
|
||||
message.text === other.text &&
|
||||
message.timestamp === other.timestamp
|
||||
message.timestamp === other.timestamp &&
|
||||
leftParts === rightParts
|
||||
);
|
||||
});
|
||||
}
|
||||
@@ -1491,6 +1487,7 @@ export function upsertChatMessage(previous: ChatMessage[], incoming: ChatMessage
|
||||
...existingMessage,
|
||||
...incoming,
|
||||
text: nextText,
|
||||
parts: incoming.parts ?? existingMessage.parts ?? [],
|
||||
deliveryStatus: null,
|
||||
retryCount: 0,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user