fix(atlas): stop stalled boulder continuations
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -9,6 +9,7 @@ import { createInternalAgentContinuationTextPart, resolveInheritedPromptTools }
|
||||
import { dispatchInternalPrompt } from "../shared/prompt-async-gate"
|
||||
import { HOOK_NAME } from "./hook-name"
|
||||
import { BOULDER_CONTINUATION_PROMPT } from "./system-reminder-templates"
|
||||
import { markContinuationInjectedAwaitingToolProgress } from "./tool-progress"
|
||||
import { resolveRecentPromptContextForSession } from "./recent-model-resolver"
|
||||
import type { BackgroundTaskStatusProvider, SessionState } from "./types"
|
||||
|
||||
@@ -122,6 +123,7 @@ export async function injectBoulderContinuation(input: {
|
||||
}
|
||||
|
||||
sessionState.promptFailureCount = 0
|
||||
markContinuationInjectedAwaitingToolProgress(sessionState)
|
||||
log(`[${HOOK_NAME}] Boulder continuation injected`, { sessionID })
|
||||
return "injected"
|
||||
} catch (err) {
|
||||
|
||||
@@ -96,6 +96,7 @@ export function createAtlasEventHandler(input: {
|
||||
const deletedState = sessions.get(sessionID)
|
||||
if (deletedState?.pendingRetryTimer) {
|
||||
clearTimeout(deletedState.pendingRetryTimer)
|
||||
deletedState.pendingRetryTimer = undefined
|
||||
}
|
||||
sessions.delete(sessionID)
|
||||
log(`[${HOOK_NAME}] Session deleted: cleaned up`, { sessionID })
|
||||
@@ -109,6 +110,7 @@ export function createAtlasEventHandler(input: {
|
||||
const compactedState = sessions.get(sessionID)
|
||||
if (compactedState?.pendingRetryTimer) {
|
||||
clearTimeout(compactedState.pendingRetryTimer)
|
||||
compactedState.pendingRetryTimer = undefined
|
||||
}
|
||||
sessions.delete(sessionID)
|
||||
log(`[${HOOK_NAME}] Session compacted: cleaned up`, { sessionID })
|
||||
|
||||
@@ -25,6 +25,11 @@ import { injectBoulderContinuation } from "./boulder-continuation-injector"
|
||||
import { HOOK_NAME } from "./hook-name"
|
||||
import { resolveActiveBoulderSession } from "./resolve-active-boulder-session"
|
||||
import { BOULDER_COMPLETE_PROMPT } from "./system-reminder-templates"
|
||||
import {
|
||||
markContinuationStalled,
|
||||
shouldAbortForNoToolProgress,
|
||||
updateNoToolProgressIterations,
|
||||
} from "./tool-progress"
|
||||
import type { AtlasHookOptions, SessionState } from "./types"
|
||||
|
||||
const CONTINUATION_COOLDOWN_MS = 5000
|
||||
@@ -172,6 +177,7 @@ function scheduleRetry(input: {
|
||||
sessionState.pendingRetryTimer = undefined
|
||||
|
||||
if (sessionState.promptFailureCount >= MAX_CONSECUTIVE_PROMPT_FAILURES) return
|
||||
if (sessionState.stalledContinuationReason) return
|
||||
if (sessionState.waitingForFinalWaveApproval) return
|
||||
|
||||
const now = Date.now()
|
||||
@@ -352,6 +358,30 @@ export async function handleAtlasSessionIdle(input: {
|
||||
return
|
||||
}
|
||||
|
||||
if (sessionState.stalledContinuationReason) {
|
||||
log(`[${HOOK_NAME}] Skipped: boulder continuation stalled`, {
|
||||
sessionID,
|
||||
reason: sessionState.stalledContinuationReason,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
const noProgressIterations = updateNoToolProgressIterations(sessionState)
|
||||
if (shouldAbortForNoToolProgress(sessionState)) {
|
||||
markContinuationStalled(sessionState, boulderState.plan_name)
|
||||
if (sessionState.pendingRetryTimer) {
|
||||
clearTimeout(sessionState.pendingRetryTimer)
|
||||
sessionState.pendingRetryTimer = undefined
|
||||
}
|
||||
log(`[${HOOK_NAME}] Aborting boulder continuation after repeated no-tool-progress iterations`, {
|
||||
sessionID,
|
||||
plan: boulderState.plan_name,
|
||||
noProgressIterations,
|
||||
reason: sessionState.stalledContinuationReason,
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
if (sessionState.lastEventWasAbortError) {
|
||||
sessionState.lastEventWasAbortError = false
|
||||
log(`[${HOOK_NAME}] Skipped: abort error immediately before idle`, { sessionID })
|
||||
|
||||
@@ -22,6 +22,7 @@ import { DIRECT_WORK_REMINDER } from "./system-reminder-templates"
|
||||
import { isOmoPath } from "./omo-path"
|
||||
import { resolvePreferredSessionId, resolveTaskContext } from "./task-context"
|
||||
import { extractSessionIdFromMetadata, extractSessionIdFromOutput, validateSubagentSessionId } from "./subagent-session-id"
|
||||
import { didToolMakeProgress, isTangibleProgressTool, recordToolProgress } from "./tool-progress"
|
||||
import {
|
||||
buildCompletionGate,
|
||||
buildFinalWaveApprovalReminder,
|
||||
@@ -142,6 +143,10 @@ export function createToolExecuteAfterHandler(input: {
|
||||
return
|
||||
}
|
||||
|
||||
if (toolInput.sessionID && isTangibleProgressTool(toolInput.tool) && didToolMakeProgress(toolOutput)) {
|
||||
recordToolProgress(getState(toolInput.sessionID))
|
||||
}
|
||||
|
||||
if (!(await resolveIsCallerOrchestrator(toolInput.sessionID))) {
|
||||
return
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user