"""回放入口:与生产写路径共用 muse.flow.dispatch.run_dispatch。""" from __future__ import annotations import json from pathlib import Path from typing import Any, Callable, Iterable, Mapping from muse.flow.dispatch import run_dispatch as production_run_dispatch from muse.store import get_run def replay_run( run_id: str, *, spec_path: str | Path, repo_root: str | Path, policy: Any, new_run_id: str, run_dir: str | Path, connect_factory: Callable[..., Any] | None = None, launcher: Callable[..., Iterable] | None = None, sqlite_path: str | Path | None = None, ) -> tuple[dict[str, Any], int, dict[str, Any]]: """取历史 input_json 证明后,走生产 flow 入口重跑。""" prior = get_run(run_id, sqlite_path) if prior is None: raise ValueError(f"run 不存在: {run_id}") receipt, code = production_run_dispatch( spec_path, repo_root=repo_root, policy=policy, run_id=new_run_id, run_dir=run_dir, connect_factory=connect_factory, launcher=launcher, trigger_source="replay_eval", sqlite_path=sqlite_path, ) replayed = get_run(new_run_id, sqlite_path) or {} return receipt, code, { "prior_input": json.loads(prior["input_json"]), "replay_input": json.loads(replayed.get("input_json") or "{}"), "prior_output": prior["output_text"], "replay_output": replayed.get("output_text", ""), }