feat: 长任务无敌补齐三件:连续失败上限 + worker退出审计 + 配额恢复自动续跑
1. host goal 循环连续失败护栏:3 轮连续失败即中断出口, 任务记 interrupted、可断点续跑,不再无限空转 (2026-10-29 实弹:断点后 274 轮全失败)。 2. worker 退出杀残留路径补审计 worker_shutdown_interrupted, detail 为任务 id,与 sweep_interrupted 同口径。 3. 配额中断自动恢复:每轮现查配额,仍超限/查不到时留 在 interrupted 不重排队,下轮再查;现查为 None 时 (新月份/额度上调/无价上限重置)才 CAS 回 queued。 单测:配额仍超限不动、配额恢复续跑、连续 3 轮失败停转。
This commit is contained in:
1 parent
88fcfeebd3
commit
ae3aff8602
4 files changed
+100
-6
No files matched your search
@@ -920,6 +920,33 @@ class GoalLoopLongTaskTest(unittest.TestCase):
|
||||
saved = host.load_state(state_path)
|
||||
self.assertEqual(saved["tasks"]["g"]["goal_rounds_done"], 2)
|
||||
|
||||
def test_goal_consecutive_failed_turns_stop_spinning(self):
|
||||
# 不限轮次 + 瞬间失败轮次会无限空转(2026-10-29 实弹:
|
||||
# 断点后 274 轮全失败);3 轮连续失败即中断出口。
|
||||
class FakeServer:
|
||||
def __init__(self):
|
||||
self.calls = 0
|
||||
|
||||
def run_turn(self, thread_id, prompt, model=None, effort=None,
|
||||
sandbox=None, timeout=None):
|
||||
self.calls += 1
|
||||
return {"status": "failed", "text": "",
|
||||
"turn_id": "f%d" % self.calls}
|
||||
|
||||
with tempfile.TemporaryDirectory() as tmp:
|
||||
state_path = os.path.join(tmp, "host-state.json")
|
||||
state = {"tasks": {}, "automations": []}
|
||||
task = self._task(tmp)
|
||||
state["tasks"]["g"] = task
|
||||
srv = FakeServer()
|
||||
result = host.run_goal_loop(srv, state, state_path,
|
||||
task, "make it", None, 0, "m",
|
||||
"low", None, cfg={}, timeout=600)
|
||||
self.assertEqual(srv.calls, 3)
|
||||
self.assertTrue(result["interrupted"])
|
||||
self.assertEqual(task["status"], "interrupted")
|
||||
self.assertIn("连续 3 轮", task["goal_interrupted_reason"])
|
||||
|
||||
def test_goal_resume_continues_from_checkpoint(self):
|
||||
class FakeServer:
|
||||
def __init__(self):
|
||||
|
||||
Reference in new issue
Block a user