Keep goals active on model capacity errors

This commit is contained in:
Eric Traut
2026-07-05 09:11:57 -07:00
parent be33f80bc6
commit 5dd9458d2d
2 changed files with 34 additions and 0 deletions

View File

@@ -303,6 +303,9 @@ where
};
let reason = match input.error {
// Capacity retries do not consume the user's token budget, so
// leave the goal active for the idle continuation.
CodexErrorInfo::ServerOverloaded => return,
CodexErrorInfo::UsageLimitExceeded => ActiveGoalStopReason::UsageLimit,
// The turn has ended because the error was non-retryable or its
// retries were exhausted. Block the goal to prevent automatic

View File

@@ -603,6 +603,37 @@ async fn turn_error_blocks_goal() -> anyhow::Result<()> {
Ok(())
}
#[tokio::test]
async fn server_overloaded_error_keeps_goal_active() -> anyhow::Result<()> {
let runtime = test_runtime().await?;
let thread_id = test_thread_id()?;
seed_thread_metadata(runtime.as_ref(), thread_id).await?;
let harness = GoalExtensionHarness::new(runtime.clone(), thread_id).await?;
harness.start_turn("turn-1", &TokenUsage::default()).await;
let tools = harness.tools();
tool_by_name(&tools, "create_goal")
.handle(tool_call(
"create_goal",
"call-create-goal",
json!({ "objective": "ship goal extension backend" }),
))
.await?;
harness
.notify_turn_error("turn-1", CodexErrorInfo::ServerOverloaded)
.await;
harness.stop_turn("turn-1").await;
let goal = runtime
.thread_goals()
.get_thread_goal(thread_id)
.await?
.ok_or_else(|| anyhow::anyhow!("goal should exist"))?;
assert_eq!(codex_state::ThreadGoalStatus::Active, goal.status);
Ok(())
}
#[tokio::test]
async fn usage_limit_budget_limited_goal_accounts_remaining_progress() -> anyhow::Result<()> {
let runtime = test_runtime().await?;