Install and update artemis-use with task diagnostics and plugin guidance. Preserve cross-device file receipts, review canonical reports, guard stage transitions and reduce small history summaries. Improve exploration lifecycle, request recovery and browser live connections.
152 lines
5.8 KiB
Python
152 lines
5.8 KiB
Python
"""Flash's exit-only acceptance check uses the same read-only Checker as Pro."""
|
|
|
|
import asyncio
|
|
from pathlib import Path
|
|
|
|
from artemis.agents.checker.checker import run_final_check
|
|
from artemis.context import ArtemisContext
|
|
from artemis.graph.checkpoints import (
|
|
RunOutcome,
|
|
TestSummary,
|
|
final_check_enabled,
|
|
publish_checker_event,
|
|
verdict_payloads,
|
|
write_run_outcome,
|
|
)
|
|
from artemis.runtime.case_result import CaseTestResult, resolve_case_result
|
|
from artemis.utils.logger import get_logger
|
|
from artemis.utils.notes import save_verified_note
|
|
|
|
logger = get_logger(__name__)
|
|
|
|
|
|
async def settle_flash_outcome(
|
|
ctx: ArtemisContext,
|
|
goal: str,
|
|
execution_report: dict,
|
|
*,
|
|
final_report_received: bool = False,
|
|
) -> dict:
|
|
"""Check once at exit, without operating the device or rerunning the task."""
|
|
stop_capture = getattr(ctx, "on_execution_review", None)
|
|
if stop_capture:
|
|
await stop_capture()
|
|
status = str(execution_report.get("status") or "failed")
|
|
result = None
|
|
delivery = None
|
|
report_review = None
|
|
if status == "completed" or final_report_received:
|
|
body = execution_report.get("explanation")
|
|
directory = getattr(getattr(ctx, "data_engine", None), "base_dir", None)
|
|
if isinstance(body, str) and body.strip() and isinstance(directory, (str, Path)):
|
|
try:
|
|
receipt = save_verified_note(directory, "output", body)
|
|
delivery = {
|
|
**receipt,
|
|
"report_path": receipt["path"],
|
|
"allow_report_corrections": True,
|
|
}
|
|
except (OSError, ValueError) as exc:
|
|
logger.warning(f"Flash 最终答复保存失败:{exc}")
|
|
delivery = {"ok": False, "verified": False, "error": str(exc)}
|
|
if final_check_enabled(ctx):
|
|
timeout = float(getattr(ctx.execution_setup, "checkpoint_timeout", 180.0))
|
|
publish_checker_event(
|
|
ctx,
|
|
{
|
|
"event": "attempt_started",
|
|
"phase": "final",
|
|
"attempt_id": "final#1",
|
|
"checkpoint_id": "final",
|
|
"check_items": [],
|
|
"status": "running",
|
|
},
|
|
)
|
|
try:
|
|
report = await asyncio.wait_for(
|
|
run_final_check(
|
|
ctx,
|
|
goal=goal,
|
|
plan_text="",
|
|
ledger=[],
|
|
check_items=[],
|
|
attempt_id="final#1",
|
|
execution_report=execution_report,
|
|
report_delivery=delivery,
|
|
),
|
|
timeout=timeout,
|
|
)
|
|
result = report.test_result
|
|
if report.report_corrections and directory:
|
|
from artemis.agents.checker.report_review import apply_report_review
|
|
|
|
try:
|
|
report_review = apply_report_review(
|
|
directory, execution_report, report.report_corrections
|
|
)
|
|
except (OSError, ValueError) as exc:
|
|
report_review = {"applied": False, "reason": str(exc)}
|
|
logger.warning(f"报告复核修改未保存:{exc}")
|
|
publish_checker_event(
|
|
ctx,
|
|
{
|
|
"event": "attempt_finished",
|
|
"phase": "final",
|
|
"attempt_id": "final#1",
|
|
"checkpoint_id": "final",
|
|
"status": "done",
|
|
"verdicts": verdict_payloads(report.verdicts),
|
|
"test_result": result.model_dump() if result else None,
|
|
"route": "end",
|
|
},
|
|
)
|
|
except Exception as exc:
|
|
detail = (
|
|
f"超过 {timeout:g} 秒"
|
|
if isinstance(exc, TimeoutError)
|
|
else f"{type(exc).__name__}: {exc}"
|
|
)
|
|
logger.warning(f"Flash 测试验收未完成:{detail}")
|
|
result = CaseTestResult(
|
|
status="inconclusive", reason=f"操作已结束,但测试验收未完成:{detail}。"
|
|
)
|
|
publish_checker_event(
|
|
ctx,
|
|
{
|
|
"event": "attempt_finished",
|
|
"phase": "final",
|
|
"attempt_id": "final#1",
|
|
"checkpoint_id": "final",
|
|
"status": "error",
|
|
"error": result.reason,
|
|
"route": "end",
|
|
},
|
|
)
|
|
else:
|
|
result = CaseTestResult(
|
|
status="inconclusive", reason="已关闭最终检查,未进行测试结果验收。"
|
|
)
|
|
|
|
outcome = RunOutcome(
|
|
task_status="completed" if status == "completed" else "blocked", tests=TestSummary()
|
|
)
|
|
payload = outcome.model_dump()
|
|
if report_review:
|
|
payload["report_review"] = report_review
|
|
if result:
|
|
payload["test_result"] = result.model_dump()
|
|
resolved = resolve_case_result(payload, status, str(execution_report.get("explanation") or ""))
|
|
payload["test_result"] = resolved.model_dump() if resolved else None
|
|
if ctx.data_engine:
|
|
write_run_outcome(
|
|
ctx.data_engine.base_dir,
|
|
outcome,
|
|
{
|
|
"test_result": payload["test_result"],
|
|
**({"report_review": report_review} if report_review else {}),
|
|
},
|
|
)
|
|
publish_checker_event(ctx, {"event": "run_outcome", "phase": "outcome", **payload})
|
|
ctx.run_outcome = payload
|
|
return payload
|