Files
Agent-System/web/src/lib/taskRunReconnect.ts
T
weichenandCursor 9daf3b7a10 fix(web): replay task phases after refresh and keep interrupted resumable
Progress lived only in the open SSE stream, and interrupted history was shown as completed so the card could not be continued.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-21 06:21:09 +00:00

41 lines
1.3 KiB
TypeScript

/**
* 长任务断线自动重试:用显式 reconnectRunId 跨 attempt 保留,
* 禁止依赖 setState updater / 已被清空的 stream.runId。
*/
export function resolveReconnectRunId(input: {
attemptIndex: number;
optsReconnectRunId?: string | null;
}): string | undefined {
const fromOpts = input.optsReconnectRunId?.trim();
if (fromOpts) return fromOpts;
// attempt 0 且无显式 id → 允许新 POST;重试必须靠 opts 传入
return undefined;
}
export function shouldSubscribeExistingRun(status: string | null | undefined): boolean {
return status === 'running' || status === 'pending';
}
export function isRemoteTaskTerminal(status: string | null | undefined): boolean {
return (
status === 'completed' ||
status === 'pending_author_confirmation' ||
status === 'quality_failed' ||
status === 'blocked_pending_governance' ||
status === 'interrupted'
);
}
/** 自动重试调度时把已知 runId 写入下一轮 opts,避免 abort 后丢失。 */
export function nextAttemptOpts<T extends { reconnectRunId?: string }>(
opts: T | undefined,
retainedRunId: string | undefined,
): T & { reconnectRunId?: string } {
const base = { ...(opts || ({} as T)) };
if (retainedRunId) {
return { ...base, reconnectRunId: retainedRunId };
}
return base;
}