mirror of
https://github.com/siteboon/claudecodeui.git
synced 2026-06-09 07:05:51 +08:00
Compare commits
2 Commits
feature/fi
...
fix/codex-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0299beccb9 | ||
|
|
f4a1614a0a |
@@ -455,7 +455,7 @@ async function sandboxCommand(args) {
|
|||||||
await new Promise(resolve => setTimeout(resolve, 5000));
|
await new Promise(resolve => setTimeout(resolve, 5000));
|
||||||
|
|
||||||
console.log(`${c.info('▶')} Launching CloudCLI web server...`);
|
console.log(`${c.info('▶')} Launching CloudCLI web server...`);
|
||||||
sbx(['exec', opts.name, 'bash', '-c', 'cloudcli start --port 3001 &']);
|
sbx(['exec', opts.name, 'bash', '-c', 'nohup cloudcli start --port 3001 > /tmp/cloudcli-ui.log 2>&1 & disown']);
|
||||||
|
|
||||||
console.log(`${c.info('▶')} Forwarding port ${opts.port} → 3001...`);
|
console.log(`${c.info('▶')} Forwarding port ${opts.port} → 3001...`);
|
||||||
try {
|
try {
|
||||||
@@ -554,7 +554,7 @@ async function sandboxCommand(args) {
|
|||||||
|
|
||||||
// Step 3: Start CloudCLI inside the sandbox
|
// Step 3: Start CloudCLI inside the sandbox
|
||||||
console.log(`${c.info('▶')} Launching CloudCLI web server...`);
|
console.log(`${c.info('▶')} Launching CloudCLI web server...`);
|
||||||
sbx(['exec', opts.name, 'bash', '-c', 'cloudcli start --port 3001 &']);
|
sbx(['exec', opts.name, 'bash', '-c', 'nohup cloudcli start --port 3001 > /tmp/cloudcli-ui.log 2>&1 & disown']);
|
||||||
|
|
||||||
// Step 4: Forward port
|
// Step 4: Forward port
|
||||||
console.log(`${c.info('▶')} Forwarding port ${opts.port} → 3001...`);
|
console.log(`${c.info('▶')} Forwarding port ${opts.port} → 3001...`);
|
||||||
|
|||||||
@@ -279,6 +279,16 @@ export async function queryCodex(command, options = {}, ws) {
|
|||||||
startedAt: new Date().toISOString()
|
startedAt: new Date().toISOString()
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
const markSessionFinished = (id) => {
|
||||||
|
if (!id) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const session = activeCodexSessions.get(id);
|
||||||
|
if (session && session.status !== 'aborted') {
|
||||||
|
session.status = 'completed';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Existing sessions can be tracked immediately; new sessions are tracked after thread.started.
|
// Existing sessions can be tracked immediately; new sessions are tracked after thread.started.
|
||||||
if (capturedSessionId) {
|
if (capturedSessionId) {
|
||||||
@@ -324,6 +334,10 @@ export async function queryCodex(command, options = {}, ws) {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event.type === 'turn.completed' || event.type === 'turn.failed') {
|
||||||
|
markSessionFinished(capturedSessionId || sessionId);
|
||||||
|
}
|
||||||
|
|
||||||
const transformed = transformCodexEvent(event);
|
const transformed = transformCodexEvent(event);
|
||||||
|
|
||||||
// Normalize the transformed event into NormalizedMessage(s) via adapter
|
// Normalize the transformed event into NormalizedMessage(s) via adapter
|
||||||
@@ -354,6 +368,8 @@ export async function queryCodex(command, options = {}, ws) {
|
|||||||
|
|
||||||
// Send completion event
|
// Send completion event
|
||||||
if (!terminalFailure) {
|
if (!terminalFailure) {
|
||||||
|
markSessionFinished(capturedSessionId || sessionId);
|
||||||
|
|
||||||
sendMessage(ws, createNormalizedMessage({
|
sendMessage(ws, createNormalizedMessage({
|
||||||
kind: 'complete',
|
kind: 'complete',
|
||||||
actualSessionId: capturedSessionId || thread.id || sessionId || null,
|
actualSessionId: capturedSessionId || thread.id || sessionId || null,
|
||||||
|
|||||||
@@ -98,6 +98,7 @@ export function useChatRealtimeHandlers({
|
|||||||
}: UseChatRealtimeHandlersArgs) {
|
}: UseChatRealtimeHandlersArgs) {
|
||||||
const paletteOps = usePaletteOps();
|
const paletteOps = usePaletteOps();
|
||||||
const lastProcessedMessageRef = useRef<LatestChatMessage | null>(null);
|
const lastProcessedMessageRef = useRef<LatestChatMessage | null>(null);
|
||||||
|
const terminalSessionIdsRef = useRef<Set<string>>(new Set());
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!latestMessage) return;
|
if (!latestMessage) return;
|
||||||
@@ -151,6 +152,17 @@ export function useChatRealtimeHandlers({
|
|||||||
const isCurrentSession =
|
const isCurrentSession =
|
||||||
statusSessionId === currentSessionId || (selectedSession && statusSessionId === selectedSession.id);
|
statusSessionId === currentSessionId || (selectedSession && statusSessionId === selectedSession.id);
|
||||||
|
|
||||||
|
if (msg.isProcessing && terminalSessionIdsRef.current.has(statusSessionId)) {
|
||||||
|
onSessionInactive?.(statusSessionId);
|
||||||
|
onSessionNotProcessing?.(statusSessionId);
|
||||||
|
if (isCurrentSession) {
|
||||||
|
setIsLoading(false);
|
||||||
|
setCanAbortSession(false);
|
||||||
|
setClaudeStatus(null);
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (msg.isProcessing) {
|
if (msg.isProcessing) {
|
||||||
onSessionActive?.(statusSessionId);
|
onSessionActive?.(statusSessionId);
|
||||||
onSessionProcessing?.(statusSessionId);
|
onSessionProcessing?.(statusSessionId);
|
||||||
@@ -180,6 +192,10 @@ export function useChatRealtimeHandlers({
|
|||||||
|
|
||||||
const sid = msg.sessionId || activeViewSessionId;
|
const sid = msg.sessionId || activeViewSessionId;
|
||||||
|
|
||||||
|
if (sid && msg.kind === 'session_created') {
|
||||||
|
terminalSessionIdsRef.current.delete(sid);
|
||||||
|
}
|
||||||
|
|
||||||
// --- Streaming: buffer for performance ---
|
// --- Streaming: buffer for performance ---
|
||||||
if (msg.kind === 'stream_delta') {
|
if (msg.kind === 'stream_delta') {
|
||||||
const text = msg.content || '';
|
const text = msg.content || '';
|
||||||
@@ -258,6 +274,10 @@ export function useChatRealtimeHandlers({
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 'complete': {
|
case 'complete': {
|
||||||
|
if (sid) {
|
||||||
|
terminalSessionIdsRef.current.add(sid);
|
||||||
|
}
|
||||||
|
|
||||||
// Flush any remaining streaming state
|
// Flush any remaining streaming state
|
||||||
if (streamTimerRef.current) {
|
if (streamTimerRef.current) {
|
||||||
clearTimeout(streamTimerRef.current);
|
clearTimeout(streamTimerRef.current);
|
||||||
@@ -313,6 +333,10 @@ export function useChatRealtimeHandlers({
|
|||||||
}
|
}
|
||||||
|
|
||||||
case 'error': {
|
case 'error': {
|
||||||
|
if (sid) {
|
||||||
|
terminalSessionIdsRef.current.add(sid);
|
||||||
|
}
|
||||||
|
|
||||||
setIsLoading(false);
|
setIsLoading(false);
|
||||||
setCanAbortSession(false);
|
setCanAbortSession(false);
|
||||||
setClaudeStatus(null);
|
setClaudeStatus(null);
|
||||||
|
|||||||
@@ -131,6 +131,8 @@ export function useChatSessionState({
|
|||||||
const pendingInitialScrollRef = useRef(true);
|
const pendingInitialScrollRef = useRef(true);
|
||||||
const messagesOffsetRef = useRef(0);
|
const messagesOffsetRef = useRef(0);
|
||||||
const scrollPositionRef = useRef({ height: 0, top: 0 });
|
const scrollPositionRef = useRef({ height: 0, top: 0 });
|
||||||
|
const previousProcessingSessionsRef = useRef<Set<string> | null>(null);
|
||||||
|
const previousProcessingSessionViewIdRef = useRef<string | null>(null);
|
||||||
const loadAllFinishedTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
const loadAllFinishedTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||||
const loadAllOverlayTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
const loadAllOverlayTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||||
const lastLoadedSessionKeyRef = useRef<string | null>(null);
|
const lastLoadedSessionKeyRef = useRef<string | null>(null);
|
||||||
@@ -693,9 +695,17 @@ export function useChatSessionState({
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const activeViewSessionId = selectedSession?.id || currentSessionId;
|
const activeViewSessionId = selectedSession?.id || currentSessionId;
|
||||||
|
const previousProcessingSessions = previousProcessingSessionsRef.current;
|
||||||
|
const previousProcessingSessionViewId = previousProcessingSessionViewIdRef.current;
|
||||||
|
previousProcessingSessionsRef.current = processingSessions ?? null;
|
||||||
|
previousProcessingSessionViewIdRef.current = activeViewSessionId ?? null;
|
||||||
|
|
||||||
if (!activeViewSessionId || !processingSessions) return;
|
if (!activeViewSessionId || !processingSessions) return;
|
||||||
|
|
||||||
|
const activeViewSessionChanged = previousProcessingSessionViewId !== activeViewSessionId;
|
||||||
|
const wasProcessing = previousProcessingSessions?.has(activeViewSessionId) ?? false;
|
||||||
const shouldBeProcessing = processingSessions.has(activeViewSessionId);
|
const shouldBeProcessing = processingSessions.has(activeViewSessionId);
|
||||||
if (shouldBeProcessing && !isLoading) {
|
if (shouldBeProcessing && (!wasProcessing || activeViewSessionChanged) && !isLoading) {
|
||||||
setIsLoading(true);
|
setIsLoading(true);
|
||||||
setCanAbortSession(true);
|
setCanAbortSession(true);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user