feat: update codex live chat workflow

This commit is contained in:
2026-04-22 20:00:38 +09:00
parent 9e4b70f1f1
commit b0b9980a6c
70 changed files with 5178 additions and 2401 deletions

View File

@@ -8,6 +8,7 @@ import {
persistLastReceivedChatEventId,
resolveChatWebSocketUrl,
} from './chatUtils';
import { hasRegisteredAccessTokenAccess } from '../tokenAccess';
import type {
ChatActivityEvent,
ChatJobEvent,
@@ -19,7 +20,6 @@ import type {
const DISCONNECT_UI_DELAY_MS = 1500;
const PRESENCE_PING_INTERVAL_MS = 20_000;
const BACKGROUND_SOCKET_REFRESH_THRESHOLD_MS = 15_000;
type ConnectionState = 'connecting' | 'connected' | 'disconnected';
@@ -225,14 +225,13 @@ function sendPresencePing() {
);
}
function refreshSharedSocket() {
function ensureSharedSocket() {
const socket = sharedChatConnection.socketRef.current;
if (socket && socket.readyState === WebSocket.CONNECTING) {
if (socket && (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING)) {
return;
}
disconnectSharedSocket();
connectSharedSocket();
}
@@ -280,24 +279,6 @@ function stopPresenceMonitoring() {
}
}
function shouldRefreshSocketAfterResume() {
if (typeof document !== 'undefined' && document.visibilityState !== 'visible') {
return false;
}
const socket = sharedChatConnection.socketRef.current;
if (!socket || socket.readyState !== WebSocket.OPEN) {
return true;
}
if (sharedChatConnection.lastBackgroundAt === null) {
return false;
}
return Date.now() - sharedChatConnection.lastBackgroundAt >= BACKGROUND_SOCKET_REFRESH_THRESHOLD_MS;
}
function handleVisibilityChange() {
if (typeof document !== 'undefined' && document.visibilityState === 'hidden') {
sharedChatConnection.lastBackgroundAt = Date.now();
@@ -306,36 +287,24 @@ function handleVisibilityChange() {
return;
}
if (shouldRefreshSocketAfterResume()) {
refreshSharedSocket();
return;
}
ensureSharedSocket();
sendPresencePing();
sendContextUpdate(sharedChatConnection.currentContext);
}
function handlePageShow() {
if (shouldRefreshSocketAfterResume()) {
refreshSharedSocket();
return;
}
ensureSharedSocket();
sendPresencePing();
sendContextUpdate(sharedChatConnection.currentContext);
}
function handleWindowFocus() {
if (shouldRefreshSocketAfterResume()) {
refreshSharedSocket();
return;
}
ensureSharedSocket();
sendPresencePing();
}
function handleWindowOnline() {
refreshSharedSocket();
ensureSharedSocket();
}
function startPresenceMonitoring() {
@@ -444,6 +413,16 @@ function connectSharedSocket() {
return;
}
if (!hasRegisteredAccessTokenAccess()) {
clearReconnectTimer();
clearConnectTimeout();
clearDisconnectUiTimer();
stopPresenceMonitoring();
setSharedConnectionError('등록된 접근 토큰이 없어 채팅 연결을 시작하지 않았습니다.');
setSharedConnectionState('disconnected');
return;
}
const currentSocket = sharedChatConnection.socketRef.current;
if (currentSocket && (currentSocket.readyState === WebSocket.OPEN || currentSocket.readyState === WebSocket.CONNECTING)) {
@@ -496,6 +475,13 @@ function connectSharedSocket() {
return;
}
if (closeEvent?.code === 1008) {
clearReconnectTimer();
setSharedConnectionError('등록된 접근 토큰이 없어 채팅 연결이 차단되었습니다.');
setSharedConnectionState('disconnected');
return;
}
if (closeEvent?.code === 1000 && !message) {
setSharedConnectionError('');
return;