diff --git a/src/components/microservices/code-queue-mgr/src/index.ts b/src/components/microservices/code-queue-mgr/src/index.ts index 8880d338..f40e06cd 100644 --- a/src/components/microservices/code-queue-mgr/src/index.ts +++ b/src/components/microservices/code-queue-mgr/src/index.ts @@ -591,6 +591,12 @@ function hasClaimMarkers(task: QueueTask): boolean { || task.attempts.length > 0; } +function retryableClaimedQueueState(task: QueueTask): boolean { + return (task.status === "queued" || task.status === "retry_wait") + && task.activeTurnId === null + && hasClaimMarkers(task); +} + function terminalTaskUnread(task: QueueTask): boolean { return terminalTask(task) && task.readAt === null; } @@ -1922,25 +1928,30 @@ async function retryTask(taskId: string, req: Request): Promise { `; if (rows[0] === undefined) return { task: null, changed: false }; const nextTask = rowToTask(rows[0]); - if (!terminalTask(nextTask)) return { task: nextTask, changed: false }; + const isTerminal = terminalTask(nextTask); + const isClaimedQueueRetry = retryableClaimedQueueState(nextTask); + if (!isTerminal && !isClaimedQueueRetry) return { task: nextTask, changed: false }; nextTask.status = hasClaimMarkers(nextTask) ? "retry_wait" : "queued"; nextTask.finishedAt = null; nextTask.readAt = null; nextTask.cancelRequested = false; nextTask.lastError = null; - nextTask.maxAttempts = Math.max(nextTask.maxAttempts, nextTask.attempts.length + 1); + nextTask.maxAttempts = Math.max(nextTask.maxAttempts, nextTask.currentAttempt + 1, nextTask.attempts.length + 1); nextTask.nextMode = "retry"; nextTask.nextPrompt = explicitPrompt.length > 0 ? explicitPrompt : "Manual retry requested from master code-queue-mgr. Continue the original task and produce a visible final response."; nextTask.updatedAt = queuedAt; nextTask.queueEnteredAt = queuedAt; - nextTask.output.push({ seq: outputMaxSeq(nextTask) + 1, at: queuedAt, channel: "system", text: "manual retry queued by master code-queue-mgr\n", method: "manual-retry" }); + const retryText = isClaimedQueueRetry + ? "claimed queued task normalized to retry_wait by master code-queue-mgr\n" + : "manual retry queued by master code-queue-mgr\n"; + nextTask.output.push({ seq: outputMaxSeq(nextTask) + 1, at: queuedAt, channel: "system", text: retryText, method: "manual-retry" }); nextTask.outputMaxSeq = outputMaxSeq(nextTask); await upsertTask(client, nextTask); return { task: nextTask, changed: true }; }); const task = result.task; if (task === null) return jsonResponse({ ok: false, error: "task not found" }, 404); - if (!result.changed) return jsonResponse({ ok: false, error: `task is not terminal: ${task.status}`, task: taskListResponse(task) }, 409); + if (!result.changed) return jsonResponse({ ok: false, error: `task cannot be retried from status=${task.status}`, task: taskListResponse(task) }, 409); return jsonResponse({ ok: true, task: taskListResponse(task, false), queue: await queueSummary() }, 202); }