Skip to content

Commit b778065

Browse files
committed
修复评测超时清理的逐阶段预算与输出分离
1 parent 5058b29 commit b778065

22 files changed

Lines changed: 2266 additions & 184 deletions

.github/workflows/ci.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,19 @@ jobs:
247247
packages/eval/harbor
248248
npm --workspace @maka/eval run test:egress-proxy:live
249249
250+
- name: Install Harbor lifecycle test dependencies
251+
if: contains(steps.plan.outputs.standard_workspaces, 'packages/eval')
252+
run: |
253+
python3 -m venv "$RUNNER_TEMP/maka-harbor-lifecycle"
254+
"$RUNNER_TEMP/maka-harbor-lifecycle/bin/python" -m pip install --disable-pip-version-check 'harbor==0.20.0'
255+
256+
- name: Run real Harbor lifecycle tests
257+
if: contains(steps.plan.outputs.standard_workspaces, 'packages/eval')
258+
env:
259+
MAKA_EVAL_HARBOR_LIFECYCLE_TEST: '1'
260+
run: |
261+
"$RUNNER_TEMP/maka-harbor-lifecycle/bin/python" packages/eval/harbor/test_harbor_trial_lifecycle.py
262+
250263
- name: Run Runtime Host tests
251264
if: steps.plan.outputs.runtime_host == 'true'
252265
run: npm --workspace @maka/runtime-host run test:dist

packages/cli/src/__tests__/runtime-host-operator-command.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,7 @@ describe('Runtime Host operator commands', () => {
419419
'collaboration.turn-request.acknowledge',
420420
'collaboration.turn-request.create',
421421
'host.upgrade.prepare',
422+
'hosted.execution.admit',
422423
'hosted.execution.cancel',
423424
'hosted.execution.start',
424425
'peer.mesh.close',

packages/eval/harbor/relay_agent.py

Lines changed: 365 additions & 79 deletions
Large diffs are not rendered by default.

packages/eval/harbor/run_trial.py

Lines changed: 84 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,12 @@
2424
import importlib
2525
import importlib.metadata
2626
import json
27+
import math
2728
import os
2829
import signal
2930
import sys
3031
from pathlib import Path
31-
from typing import AsyncIterator
32+
from typing import Any, AsyncIterator
3233

3334
FRAMEWORK_VERSION_MISMATCH_EXIT_CODE = 78
3435

@@ -145,6 +146,7 @@ async def run_trial(framework: str, expected_version: str, config_file: Path) ->
145146
publish_ready_task(namespace, target)
146147
else:
147148
trial = await trial_type.create(config)
149+
bind_framework_timeout_budget(framework, trial)
148150
await trial.run()
149151
finally:
150152
config_file.unlink(missing_ok=True)
@@ -162,6 +164,87 @@ def apply_subject_egress_policy(task: object) -> None:
162164
agent.allowed_hosts = [allowed_host]
163165

164166

167+
def resolved_framework_timeout_ms(config: object, default_timeout: float | None) -> int | None:
168+
base_timeout = config.agent.override_timeout_sec or default_timeout
169+
if base_timeout is None:
170+
return None
171+
maximum = config.agent.max_timeout_sec or float("inf")
172+
multiplier = (
173+
config.agent_timeout_multiplier
174+
if config.agent_timeout_multiplier is not None
175+
else config.timeout_multiplier
176+
)
177+
timeout_ms = math.floor(min(base_timeout, maximum) * multiplier * 1000)
178+
if timeout_ms <= 0:
179+
raise RuntimeError("framework agent timeout is shorter than one millisecond")
180+
return timeout_ms
181+
182+
183+
def bind_framework_timeout_budget(framework: str, trial: object) -> None:
184+
"""Set the RelayAgent cleanup budget from each framework's effective phase timeout."""
185+
186+
if framework == "harbor":
187+
original = getattr(trial, "_run_agent_phase", None)
188+
agent = getattr(trial, "agent", None)
189+
if not callable(original) or not hasattr(agent, "set_framework_timeout_ms"):
190+
raise RuntimeError("Harbor timeout integration is unavailable")
191+
192+
async def run_agent_phase(*args: Any, **kwargs: Any) -> Any:
193+
timeout_sec = kwargs.get("timeout_sec")
194+
agent.set_framework_timeout_ms(
195+
None if timeout_sec is None else math.floor(timeout_sec * 1000)
196+
)
197+
return await original(*args, **kwargs)
198+
199+
trial._run_agent_phase = run_agent_phase
200+
return
201+
202+
if framework == "pier":
203+
agent = getattr(trial, "_agent", None)
204+
execution = getattr(trial, "_execution", None)
205+
run_agent = getattr(trial, "_execute_agent", None)
206+
run_step_agent = getattr(trial, "_execute_step_agent", None)
207+
resolve_step_timeout = getattr(trial, "_resolve_step_timeout", None)
208+
if (
209+
not hasattr(agent, "set_framework_timeout_ms")
210+
or execution is None
211+
or not callable(run_agent)
212+
or not callable(run_step_agent)
213+
or not callable(resolve_step_timeout)
214+
):
215+
raise RuntimeError("Pier timeout integration is unavailable")
216+
217+
async def execute_agent() -> Any:
218+
timeout_sec = execution.agent_timeout_sec
219+
agent.set_framework_timeout_ms(
220+
None if timeout_sec is None else math.floor(timeout_sec * 1000)
221+
)
222+
return await run_agent()
223+
224+
async def execute_step_agent(step: object, result: object) -> Any:
225+
default_timeout = (
226+
step.agent.timeout_sec
227+
if step.agent.timeout_sec is not None
228+
else trial._task.config.agent.timeout_sec
229+
)
230+
timeout_sec = resolve_step_timeout(
231+
override=trial.config.agent.override_timeout_sec,
232+
default=default_timeout,
233+
max_val=trial.config.agent.max_timeout_sec,
234+
specific_multiplier=trial.config.agent_timeout_multiplier,
235+
)
236+
agent.set_framework_timeout_ms(
237+
None if timeout_sec is None else math.floor(timeout_sec * 1000)
238+
)
239+
return await run_step_agent(step, result)
240+
241+
trial._execute_agent = execute_agent
242+
trial._execute_step_agent = execute_step_agent
243+
return
244+
245+
raise RuntimeError("framework must be harbor or pier")
246+
247+
165248
async def create_harbor_trial(trial_type: type, config: object) -> object:
166249
trial_type._resolve_agent_skills(config)
167250
task, task_download_result = await trial_type._load_task(config)

0 commit comments

Comments
 (0)