codexmobile-relay / client /src /hooks /useTurnRefresh.js
Codex
deploy: CodexMobile Relay
90f0300
Raw
History Blame Contribute Delete
3.22 kB
import { useEffect } from 'react';
import { hasAssistantResultForTurn } from '../app-core-utils.js';
import {
removeActivityMessagesForTurn,
upsertStatusMessage
} from '../app-message-state.js';
import { apiFetch } from '../api.js';
export function useTurnRefresh(app, runRegistry) {
function clearTurnRefreshTimer(turnId) {
if (!turnId) {
return;
}
const timer = app.turnRefreshTimersRef.current.get(turnId);
if (timer) {
window.clearTimeout(timer);
app.turnRefreshTimersRef.current.delete(turnId);
}
}
const refreshMessagesForPayload = async (payload) => {
if (!payload?.sessionId || !runRegistry.payloadMatchesCurrentConversation(payload)) {
return false;
}
try {
const data = await apiFetch(`/api/sessions/${encodeURIComponent(payload.sessionId)}/messages?limit=120`);
if (data.messages?.length && hasAssistantResultForTurn(data.messages, payload)) {
app.setMessages(data.messages);
return true;
}
} catch {
return false;
}
return false;
};
const finalizeTurnWithoutAssistant = (payload) => {
if (!payload?.turnId) {
return;
}
clearTurnRefreshTimer(payload.turnId);
app.setMessages((current) =>
upsertStatusMessage(current, {
...payload,
kind: 'turn',
status: 'completed',
label: '任务已完成',
detail: payload.error || payload.detail || ''
})
);
runRegistry.clearRun(payload);
};
const markTurnCompleted = (payload, detail = '结果同步中') => {
if (!payload?.turnId) {
return;
}
app.setMessages((current) => {
if (hasAssistantResultForTurn(current, payload)) {
return removeActivityMessagesForTurn(current, payload);
}
return upsertStatusMessage(current, {
...payload,
kind: 'turn',
status: 'running',
label: '正在思考中',
detail
});
});
};
function scheduleTurnRefresh(payload, attempt = 0) {
const turnId = payload?.turnId;
if (!turnId || !payload?.sessionId || !runRegistry.payloadMatchesCurrentConversation(payload)) {
return;
}
clearTurnRefreshTimer(turnId);
const delays = [300, 800, 1500, 2500, 4000, 6500, 10000, 15000, 22000, 30000, 30000];
const delay = delays[attempt];
if (delay === undefined) {
finalizeTurnWithoutAssistant(payload);
return;
}
const timer = window.setTimeout(async () => {
if (!runRegistry.payloadMatchesCurrentConversation(payload)) {
return;
}
const loaded = await refreshMessagesForPayload(payload);
if (loaded) {
clearTurnRefreshTimer(turnId);
runRegistry.clearRun(payload);
return;
}
scheduleTurnRefresh(payload, attempt + 1);
}, delay);
app.turnRefreshTimersRef.current.set(turnId, timer);
}
useEffect(
() => () => {
for (const timer of app.turnRefreshTimersRef.current.values()) {
window.clearTimeout(timer);
}
app.turnRefreshTimersRef.current.clear();
},
[app.turnRefreshTimersRef]
);
return {
clearTurnRefreshTimer,
markTurnCompleted,
scheduleTurnRefresh
};
}