fix: G10 断点续跑透传 model_provider(sub2api 续跑失败修法)
断点续跑容器不带 --model-provider 时 Server 的 provider 表里 没有 sub2api,thread/resume 报 provider not found(probe15 实弹)。 Docker/Local 断点方法加可选 model_provider 并转发,worker 两处 调用点传 gateway_provider;补单测断言断点命令含 --model-provider sub2api(旧代码下两新测试 1 失败 1 报错)。
This commit is contained in:
1 parent
0ef896c317
commit
a19b1567bb
3 files changed
+96
-8
No files matched your search
+17
-6
@@ -494,7 +494,8 @@ class LocalExecutor(Executor):
|
||||
return self._goal_result_from_runner(
|
||||
task["id"], self._run_local(cmd, extra_env))
|
||||
|
||||
def goal_resume_breakpoint_task(self, task) -> dict:
|
||||
def goal_resume_breakpoint_task(self, task,
|
||||
model_provider=None) -> dict:
|
||||
"""G10:调 host.py goal-resume(无 --goal-text)断点续跑。
|
||||
|
||||
命令:host.py goal-resume --task <host 名>。不传
|
||||
@@ -502,14 +503,18 @@ class LocalExecutor(Executor):
|
||||
goal/verify_command/goal_max_rounds,从
|
||||
goal_rounds_done 的下一轮接着跑同一循环,不开新循环、
|
||||
不新建 worktree、不重置轮次。结论解析与 goal_task 同款。
|
||||
(worker 只以 (task) 一个参数调本地断点方法,与 Docker
|
||||
断点方法的签名不同,不要顺手统一。)
|
||||
model_provider 可选但 worker 必须传:首轮 thread 在该
|
||||
provider 下创建,续跑不带同一 --model-provider 时
|
||||
thread/resume 报 provider not found(与 Docker 断点
|
||||
方法同 bug,2026-10-29 probe15 实弹)。(task) 单参
|
||||
调用仍可用;与 Docker 断点方法的签名不同,不要顺手统一。
|
||||
"""
|
||||
if not isinstance(task, dict) or task.get("id") is None:
|
||||
raise ValueError("任务缺少 id")
|
||||
cmd = self._base_command(model=task.get("model"),
|
||||
effort=task.get("effort"),
|
||||
approval=task.get("approval"))
|
||||
approval=task.get("approval"),
|
||||
model_provider=model_provider)
|
||||
cmd += ["goal-resume", "--task", self._host_name(task)]
|
||||
return self._goal_result_from_runner(
|
||||
task["id"], self.runner(cmd))
|
||||
@@ -1424,19 +1429,25 @@ class DockerExecutor(Executor):
|
||||
|
||||
def goal_resume_breakpoint_task(self, task, timeout=None,
|
||||
extra_mounts=None, network=None,
|
||||
extra_env=None) -> dict:
|
||||
extra_env=None,
|
||||
model_provider=None) -> dict:
|
||||
"""G10:容器内调 host.py goal-resume(无 --goal-text)
|
||||
断点续跑,与 LocalExecutor.goal_resume_breakpoint_task
|
||||
同语义(从 goal_rounds_done 下一轮接着跑,不开新循环)。
|
||||
解析与容器内 goal_resume_task 同款;真 Docker 实弹
|
||||
未做,命令形状由单测覆盖。
|
||||
model_provider 必须透传:首轮 thread 在该 provider 下
|
||||
创建,续跑容器不带同一 --model-provider 时 Server 的
|
||||
provider 表里没有它,thread/resume 报 provider not found
|
||||
(2026-10-29 probe15 实弹)。
|
||||
"""
|
||||
if not isinstance(task, dict) or task.get("id") is None:
|
||||
raise ValueError("任务缺少 id")
|
||||
inner = self._inner_host_command(
|
||||
"goal-resume", "--task", self._host_name(task),
|
||||
model=task.get("model"), effort=task.get("effort"),
|
||||
approval=task.get("approval"))
|
||||
approval=task.get("approval"),
|
||||
model_provider=model_provider)
|
||||
cmd = self.build_run_command(task, inner,
|
||||
extra_mounts=extra_mounts,
|
||||
network=network,
|
||||
|
||||
@@ -414,6 +414,82 @@ class P1WorkerTestCase(unittest.TestCase):
|
||||
self.assertIn("goal-resume", cmd)
|
||||
self.assertNotIn("--goal-text", cmd)
|
||||
|
||||
# 12b. 断点续跑透传 model_provider:首轮 thread 在该
|
||||
# provider 下创建,续跑命令必须带同一 --model-provider,
|
||||
# 否则 thread/resume 因 provider 表里没有它而失败
|
||||
# (2026-10-29 probe15 实弹:sub2api not found)。
|
||||
def test_goal_resume_breakpoint_forwards_model_provider(self):
|
||||
docker_calls = []
|
||||
|
||||
def dfake(cmd, timeout=None):
|
||||
docker_calls.append(list(cmd))
|
||||
return SimpleNamespace(
|
||||
returncode=0,
|
||||
stdout="goal met after rounds\n"
|
||||
"usage input=10 cached=0 cache_write=0 output=5 "
|
||||
"reasoning=0 total=15 completions=1\n",
|
||||
stderr="")
|
||||
|
||||
task = {"id": "T1", "prompt": "orig goal"}
|
||||
docker = DockerExecutor(runner=dfake, env=FAKE_ENV)
|
||||
with mock.patch("cloud.sandbox.shutil.which",
|
||||
return_value="/usr/bin/docker"):
|
||||
docker.goal_resume_breakpoint_task(
|
||||
task, model_provider="sub2api")
|
||||
cmd = docker_calls[-1]
|
||||
self.assertIn("goal-resume", cmd)
|
||||
self.assertNotIn("--goal-text", cmd)
|
||||
self.assertIn("--model-provider", cmd)
|
||||
self.assertIn("sub2api", cmd)
|
||||
# 不传 provider 时不带该 flag(透传语义,不是强制默认值)。
|
||||
docker_calls.clear()
|
||||
with mock.patch("cloud.sandbox.shutil.which",
|
||||
return_value="/usr/bin/docker"):
|
||||
docker.goal_resume_breakpoint_task(task)
|
||||
self.assertNotIn("--model-provider", docker_calls[-1])
|
||||
|
||||
calls = []
|
||||
|
||||
def fake(cmd):
|
||||
calls.append(list(cmd))
|
||||
return SimpleNamespace(
|
||||
returncode=0,
|
||||
stdout="goal met after rounds\n"
|
||||
"usage input=10 cached=0 cache_write=0 output=5 "
|
||||
"reasoning=0 total=15 completions=1\n",
|
||||
stderr="")
|
||||
|
||||
local = LocalExecutor("/fake/host.py", runner=fake)
|
||||
local.goal_resume_breakpoint_task(task, model_provider="sub2api")
|
||||
self.assertIn("--model-provider", calls[-1])
|
||||
self.assertIn("sub2api", calls[-1])
|
||||
|
||||
# 12c. worker 本地断点调用点透传网关 provider:run_one
|
||||
# 认领 goal_resume_pending 任务后,本地断点命令必须带
|
||||
# 网关解析出的 --model-provider(Docker 调用点同理,
|
||||
# 沙箱级已覆盖命令形状)。
|
||||
def test_worker_local_breakpoint_forwards_gateway_provider(self):
|
||||
def fake(cmd):
|
||||
self.calls.append(list(cmd))
|
||||
return SimpleNamespace(
|
||||
returncode=0,
|
||||
stdout="goal met after rounds\n"
|
||||
"usage input=10 cached=0 cache_write=0 output=5 "
|
||||
"reasoning=0 total=15 completions=1\n",
|
||||
stderr="")
|
||||
|
||||
worker = self._worker(runner=fake)
|
||||
worker._ensure_gateway = lambda task: ("sub2api", {})
|
||||
_insert_task(self.db_path, "T1", goal_mode=1,
|
||||
goal="orig goal", goal_max_rounds=3,
|
||||
goal_resume_pending=1,
|
||||
model="gpt-5.6-terra")
|
||||
worker.run_one()
|
||||
self.assertEqual(_status(self.db_path, "T1"), "completed")
|
||||
self.assertTrue(any(
|
||||
"--model-provider" in cmd and "sub2api" in cmd
|
||||
for cmd in self.calls))
|
||||
|
||||
# 13. 开新目标:goal-resume 带 --goal-text(旧行为保留)
|
||||
def test_goal_resume_new_goal_keeps_goal_text(self):
|
||||
calls = []
|
||||
|
||||
+3
-2
@@ -3029,7 +3029,8 @@ class Worker:
|
||||
extra_mounts=tenant_mounts,
|
||||
network=tenant_network,
|
||||
extra_env=_merge_env(proxy_env,
|
||||
gateway_env)),
|
||||
gateway_env),
|
||||
model_provider=gateway_provider),
|
||||
quota_check)
|
||||
elif task.get("_resume"):
|
||||
# P1 断点续跑传 None(不传 --goal-text,
|
||||
@@ -3091,7 +3092,7 @@ class Worker:
|
||||
if task.get("_goal_resume_breakpoint") and isinstance(
|
||||
self.executor, LocalExecutor):
|
||||
result = self.executor.goal_resume_breakpoint_task(
|
||||
task)
|
||||
task, model_provider=gateway_provider)
|
||||
elif task.get("_goal_resume_breakpoint"):
|
||||
# 假执行器/CloudExecutor 没有断点方法时
|
||||
# 绝不回落成 goal(会撞已存在)或
|
||||
|
||||
Reference in new issue
Block a user