| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811 |
- """把本项目按 Run 落盘的业务文件投影成上游查看器使用的只读视图。"""
- from __future__ import annotations
- import hashlib
- import json
- import mimetypes
- import re
- from dataclasses import dataclass
- from datetime import datetime, timezone
- from pathlib import Path
- from typing import Any, Iterable
- PROJECT_ROOT = Path(__file__).resolve().parents[2]
- DEFAULT_RUN_ROOT = PROJECT_ROOT / "demo_output"
- def _load_json(path: Path, default: Any = None) -> Any:
- try:
- return json.loads(path.read_text(encoding="utf-8"))
- except (FileNotFoundError, json.JSONDecodeError, OSError):
- return default
- def _stable_id(value: str) -> int:
- """生成低于 JavaScript MAX_SAFE_INTEGER 的稳定数字 ID。"""
- return int(hashlib.sha256(value.encode("utf-8")).hexdigest()[:13], 16)
- def _iso(timestamp: float | None) -> str | None:
- if timestamp is None:
- return None
- return datetime.fromtimestamp(timestamp, tz=timezone.utc).isoformat()
- def _clip(value: Any, limit: int = 240) -> str:
- if value is None:
- return ""
- if not isinstance(value, str):
- value = json.dumps(value, ensure_ascii=False, default=str)
- return value if len(value) <= limit else value[: limit - 1] + "…"
- def _viewer_status(value: Any) -> str:
- normalized = str(value or "").upper()
- if normalized in {"COMPLETED", "PASS", "SUCCESS", "SUCCEEDED"} or (
- normalized.endswith("_COMPLETED")
- ):
- return "success"
- if normalized in {"FAILED", "FAIL", "ERROR"}:
- return "failed"
- return "running"
- def _files(root: Path, pattern: str) -> list[Path]:
- return sorted(root.glob(pattern))
- def _version(path: Path) -> int:
- match = re.search(r"\.v(\d+)\.json$", path.name)
- return int(match.group(1)) if match else 0
- def _latest_by_subject(paths: Iterable[Path]) -> dict[str, Path]:
- """按 ``Subject.vN.json`` 的 Subject 选择最新正式版本。"""
- result: dict[str, Path] = {}
- for path in paths:
- subject = re.sub(r"\.v\d+$", "", path.stem)
- current = result.get(subject)
- if current is None or _version(path) > _version(current):
- result[subject] = path
- return result
- def _mtime_bounds(root: Path) -> tuple[float | None, float | None]:
- values = [
- path.stat().st_mtime
- for path in root.rglob("*")
- if path.is_file() and path.name != ".run.lock"
- ]
- return (min(values), max(values)) if values else (None, None)
- def _input_block(
- key: str,
- title: str,
- value: Any,
- *,
- source: str = "",
- images: Iterable[str] = (),
- ) -> dict[str, Any]:
- return {
- "key": key,
- "name": key,
- "title": title,
- "hint": source,
- "source": source,
- "filled": value not in (None, "", [], {}),
- "text": _clip(value, 1600),
- "images": list(images),
- }
- def _node_card(
- index: int,
- *,
- node_type: str,
- label: str,
- summary: Any,
- ok: bool | None = None,
- detail: Any = None,
- tool_call_id: str = "",
- ) -> dict[str, Any]:
- return {
- "seq": index,
- "kind": "node",
- "fanout_group": "",
- "card": {
- "i": index,
- "type": node_type,
- "label": label,
- "summary": _clip(summary, 300),
- "ok": ok,
- "images": [],
- "branch": "",
- "node_id": None,
- "tool_call_id": tool_call_id,
- "io": None,
- "calls": [],
- "reasoning": "",
- "tokens": "",
- "detail": detail if detail is not None else summary,
- },
- }
- @dataclass(frozen=True)
- class RunRef:
- numeric_id: int
- key: str
- path: Path
- kind: str
- class FileRunStore:
- """扫描 ``demo_output``,不读取或修改数据库、Checkpoint。"""
- def __init__(self, run_root: Path | None = None):
- self.run_root = (run_root or DEFAULT_RUN_ROOT).resolve()
- def discover(self) -> list[RunRef]:
- if not self.run_root.is_dir():
- return []
- refs: list[RunRef] = []
- for path in sorted(self.run_root.iterdir()):
- if not path.is_dir():
- continue
- kind = self._kind(path)
- if kind is None:
- continue
- refs.append(
- RunRef(
- numeric_id=_stable_id(path.name),
- key=path.name,
- path=path.resolve(),
- kind=kind,
- )
- )
- return sorted(
- refs,
- key=lambda item: _mtime_bounds(item.path)[1] or 0,
- reverse=True,
- )
- def get(self, numeric_id: int) -> RunRef:
- for ref in self.discover():
- if ref.numeric_id == numeric_id:
- return ref
- raise KeyError(numeric_id)
- @staticmethod
- def _kind(path: Path) -> str | None:
- if (path / "run_summary.json").is_file() or (
- path / "global_data_stage_delivery.json"
- ).is_file():
- return "global_data"
- if _files(path, "production_plans/production_dag.v*.json"):
- return "segment"
- return None
- def brief(self, ref: RunRef) -> dict[str, Any]:
- start, end = _mtime_bounds(ref.path)
- if ref.kind == "global_data":
- summary = _load_json(ref.path / "run_summary.json", {}) or {}
- stage_delivery = _load_json(
- ref.path / "global_data_stage_delivery.json", {}
- ) or {}
- metrics = _load_json(ref.path / "run_metrics.json", {}) or {}
- totals = metrics.get("model_totals") or {}
- invocation = metrics.get("run_invocations") or {}
- duration_ms = invocation.get("total_duration_ms")
- plan = self._latest_plan(ref.path)
- raw_status = (
- summary.get("status")
- or stage_delivery.get("status")
- or "RUNNING"
- )
- tasks = (plan or {}).get("tasks") or []
- plan_version = int(
- (plan or {}).get("plan_version") or 1
- )
- task_reports = [
- _load_json(
- ref.path
- / "validation_results"
- / f"{task.get('task_id')}.v{plan_version}.json",
- {},
- ) or {}
- for task in tasks
- ]
- task_passed = sum(
- report.get("verdict") == "PASS"
- for report in task_reports
- )
- task_failed = sum(
- report.get("verdict") == "FAIL"
- for report in task_reports
- )
- return {
- "id": ref.numeric_id,
- "run_key": ref.key,
- "run_kind": ref.kind,
- "agent_name": "global_data",
- "model_name": self._model_names(metrics),
- "objective": (plan or {}).get("goal") or ref.key,
- "status": _viewer_status(raw_status),
- "raw_status": raw_status,
- "business_label": f"Global Data · {len(tasks)} 个资料任务",
- "business_progress": (
- f"{task_passed} 已通过"
- + (f" · {task_failed} 未通过" if task_failed else "")
- ),
- "parent_run_id": None,
- "start_time": _iso(start),
- "end_time": _iso(end),
- "duration_sec": (
- round(float(duration_ms) / 1000, 1)
- if isinstance(duration_ms, (int, float))
- else None
- ),
- "step_count": len(summary.get("event_log") or []),
- "replan_count": summary.get("replan_count") or 0,
- "input_tokens": totals.get("input_tokens") or 0,
- "output_tokens": totals.get("output_tokens") or 0,
- "cost_usd": totals.get("reported_cost_usd") or 0,
- "cost_status": (
- "reported"
- if totals.get("reported_cost_usd") is not None
- else "unavailable"
- ),
- }
- plan = self._latest_production_plan(ref.path) or {}
- run_summary = _load_json(
- ref.path / "production_run_summary.json", {}
- ) or {}
- reports = _files(ref.path, "segment_validation_results/*.v*.json")
- summaries = _files(ref.path, "segment_summaries/*.v*.json")
- metrics = _load_json(ref.path / "run_metrics.json", {}) or {}
- totals = metrics.get("model_totals") or {}
- latest_reports = [
- _load_json(path, {}) or {}
- for path in _latest_by_subject(reports).values()
- ]
- segments = plan.get("segments") or []
- segment_passed = sum(
- report.get("verdict") == "PASS"
- for report in latest_reports
- )
- segment_failed = sum(
- report.get("verdict") == "FAIL"
- for report in latest_reports
- )
- raw_status = run_summary.get("status") or "RUNNING"
- if not run_summary and reports:
- verdicts = [
- (_load_json(path, {}) or {}).get("verdict") for path in reports
- ]
- raw_status = "COMPLETED" if verdicts and all(
- value == "PASS" for value in verdicts
- ) else "FAILED"
- elif not run_summary and summaries:
- raw_status = (_load_json(summaries[-1], {}) or {}).get(
- "status", "RUNNING"
- )
- return {
- "id": ref.numeric_id,
- "run_key": ref.key,
- "run_kind": ref.kind,
- "agent_name": "segment_production",
- "model_name": self._model_names(metrics),
- "objective": plan.get("summary") or f"Production Segment · {ref.key}",
- "status": _viewer_status(raw_status),
- "raw_status": raw_status,
- "business_label": f"Production · {len(segments)} 个 Segment",
- "business_progress": (
- (
- f"停在 {run_summary.get('current_segment_id')} · "
- f"{run_summary.get('phase')}"
- )
- if run_summary.get("current_segment_id")
- else (
- f"{segment_passed} 已通过"
- + (
- f" · {segment_failed} 未通过"
- if segment_failed else ""
- )
- )
- ),
- "parent_run_id": None,
- "start_time": _iso(start),
- "end_time": _iso(end),
- "duration_sec": (
- round(end - start, 1)
- if start is not None and end is not None
- else None
- ),
- "step_count": len(_files(ref.path, "tool_operations/*.json")),
- "replan_count": 0,
- "input_tokens": totals.get("input_tokens") or 0,
- "output_tokens": totals.get("output_tokens") or 0,
- "cost_usd": totals.get("reported_cost_usd") or 0,
- "cost_status": (
- "reported"
- if totals.get("reported_cost_usd") is not None
- else "unavailable"
- ),
- }
- @staticmethod
- def _model_names(metrics: dict[str, Any]) -> str:
- names: list[str] = []
- for item in (metrics.get("models") or {}).values():
- for name in item.get("models") or []:
- if name and name not in names:
- names.append(str(name))
- return " · ".join(names)
- @staticmethod
- def _latest_plan(run_dir: Path) -> dict[str, Any] | None:
- plans = _files(run_dir, "plans/global_data_dag.v*.json")
- return _load_json(plans[-1], {}) if plans else None
- @staticmethod
- def _latest_production_plan(
- run_dir: Path,
- ) -> dict[str, Any] | None:
- plans = _files(
- run_dir,
- "production_plans/production_dag.v*.json",
- )
- if not plans:
- return None
- latest = max(
- plans,
- key=lambda path: int(
- re.search(r"\.v(\d+)\.json$", path.name).group(1)
- ),
- )
- return _load_json(latest, {})
- def detail(self, ref: RunRef) -> dict[str, Any]:
- result = self.brief(ref)
- if ref.kind == "global_data":
- summary = _load_json(ref.path / "run_summary.json", {}) or {}
- delivery = _load_json(
- ref.path / "global_data_stage_delivery.json", {}
- ) or {}
- result.update(
- {
- "final_output": delivery.get("summary"),
- "error_message": summary.get("error"),
- "input_payload": {
- "input_path": summary.get("input_path"),
- "input_sha256": summary.get("input_sha256"),
- "protocol_version": summary.get("protocol_version"),
- },
- "overview": self._global_overview(ref, summary),
- "steps": self._global_steps(summary),
- }
- )
- else:
- plan = self._latest_production_plan(ref.path) or {}
- summary = _load_json(
- ref.path / "production_run_summary.json", {}
- ) or {}
- result.update(
- {
- "final_output": self._segment_final_output(ref),
- "error_message": summary.get("error"),
- "input_payload": plan,
- "overview": self._segment_overview(ref),
- "steps": self._segment_steps(ref),
- }
- )
- result["business_story"] = self._business_story(ref)
- return result
- def _global_overview(
- self, ref: RunRef, summary: dict[str, Any]
- ) -> dict[str, int]:
- plans = _files(ref.path, "plans/global_data_dag.v*.json")
- latest = _load_json(plans[-1], {}) if plans else {}
- tasks = (latest or {}).get("tasks") or []
- version = int((latest or {}).get("plan_version") or len(plans) or 1)
- reports = [
- _load_json(
- ref.path
- / "validation_results"
- / f"{task.get('task_id')}.v{version}.json",
- {},
- )
- or {}
- for task in tasks
- ]
- result_files = _files(ref.path, "executor_results/Task*.v*.json")
- distinct_tasks = {
- re.sub(r"\.v\d+$", "", path.stem) for path in result_files
- }
- return {
- "plan_rounds": len(plans),
- "execute_rounds": int(
- summary.get("executor_calls") or len(result_files)
- ),
- "task_count": len(tasks),
- "passed": sum(report.get("verdict") == "PASS" for report in reports),
- "failed": sum(report.get("verdict") == "FAIL" for report in reports),
- "retries": max(len(result_files) - len(distinct_tasks), 0),
- }
- def _segment_overview(self, ref: RunRef) -> dict[str, int]:
- plan = self._latest_production_plan(ref.path) or {}
- packages = _files(ref.path, "segment_packages/*.json")
- latest_reports = {
- segment_id: _load_json(path, {}) or {}
- for segment_id, path in _latest_by_subject(
- _files(ref.path, "segment_validation_results/*.v*.json")
- ).items()
- }
- reports = list(latest_reports.values())
- return {
- "plan_rounds": len(
- _files(
- ref.path,
- "production_plans/production_dag.v*.json",
- )
- ),
- "execute_rounds": len(_files(ref.path, "tool_operations/*.json")),
- "task_count": len(plan.get("segments") or packages),
- "passed": sum(report.get("verdict") == "PASS" for report in reports),
- "failed": sum(report.get("verdict") == "FAIL" for report in reports),
- "retries": 0,
- }
- @staticmethod
- def _global_steps(summary: dict[str, Any]) -> list[dict[str, Any]]:
- steps = []
- for index, message in enumerate(summary.get("event_log") or [], start=1):
- lower = message.lower()
- if "planner" in lower:
- node_type = "plan"
- elif "executor" in lower:
- node_type = "execute"
- elif "validator" in lower or "验收" in message:
- node_type = "validate"
- elif "预处理" in message:
- node_type = "preprocess"
- elif "完成" in message:
- node_type = "finalize"
- else:
- node_type = "route"
- steps.append(
- {
- "step_id": index,
- "step_index": index,
- "node_type": node_type,
- "content": message,
- "delta": {"event": message},
- "input_tokens": 0,
- "output_tokens": 0,
- "created_at": None,
- }
- )
- return steps
- def _segment_steps(self, ref: RunRef) -> list[dict[str, Any]]:
- steps: list[dict[str, Any]] = []
- package_paths = _files(ref.path, "segment_packages/*.json")
- if package_paths:
- package = _load_json(package_paths[0], {}) or {}
- steps.append(
- {
- "step_id": 1,
- "step_index": 1,
- "node_type": "prepare_segment",
- "content": f"物化 {package.get('segment_id', 'Segment')} Package",
- "delta": package,
- "input_tokens": 0,
- "output_tokens": 0,
- "created_at": _iso(package_paths[0].stat().st_mtime),
- }
- )
- for index, path in enumerate(
- _files(ref.path, "tool_operations/*.json"), start=2
- ):
- operation = _load_json(path, {}) or {}
- steps.append(
- {
- "step_id": index,
- "step_index": index,
- "node_type": "execute",
- "content": (
- f"{operation.get('tool_name', 'tool')} · "
- f"{operation.get('status', 'UNKNOWN')}"
- ),
- "delta": operation,
- "input_tokens": 0,
- "output_tokens": 0,
- "created_at": _iso(path.stat().st_mtime),
- }
- )
- return steps
- @staticmethod
- def _segment_final_output(ref: RunRef) -> Any:
- final_delivery = _load_json(
- ref.path / "final_production_delivery.json", None
- )
- if final_delivery:
- return final_delivery
- summary = _load_json(
- ref.path / "production_run_summary.json", {}
- ) or {}
- reports = _files(ref.path, "segment_validation_results/*.v*.json")
- if reports:
- return _load_json(reports[-1], {})
- if summary.get("status") == "FAILED":
- return {
- "status": "FAILED",
- "phase": summary.get("phase"),
- "failure_code": summary.get("failure_code"),
- "message": summary.get("error") or summary.get("event"),
- }
- packages = _files(ref.path, "segment_packages/*.json")
- if packages:
- package = _load_json(packages[-1], {}) or {}
- return {
- "status": "RUNNING",
- "segment_id": package.get("segment_id"),
- "message": "Segment 已物化,尚无终态 ValidationReport",
- }
- return None
- def _business_story(self, ref: RunRef) -> dict[str, Any]:
- if ref.kind == "global_data":
- return self._global_business_story(ref)
- return self._production_business_story(ref)
- def _artifact_item(
- self, ref: RunRef, artifact: dict[str, Any]
- ) -> dict[str, Any]:
- uri = artifact.get("uri") or artifact.get("source_uri")
- return {
- "label": (
- artifact.get("description")
- or artifact.get("artifact_id")
- or artifact.get("artifact_type")
- or "正式产物"
- ),
- "detail": " · ".join(
- str(value)
- for value in (
- artifact.get("artifact_type"),
- artifact.get("mime_type"),
- )
- if value
- ),
- "source": artifact.get("artifact_id") or "",
- "media_url": self.media_url(ref, uri),
- }
- @staticmethod
- def _criteria(report: dict[str, Any]) -> list[dict[str, Any]]:
- source = (
- report.get("criterion_results")
- or report.get("requirement_results")
- or report.get("checks")
- or []
- )
- return [
- {
- "label": (
- item.get("expectation_id")
- or item.get("requirement_id")
- or item.get("name")
- or item.get("verification_capability")
- or f"判断项 {index}"
- ),
- "verdict": item.get("verdict") or item.get("status") or "UNKNOWN",
- "reason": item.get("reason") or item.get("summary") or "",
- "evidence": item.get("evidence") or [],
- }
- for index, item in enumerate(source, start=1)
- if isinstance(item, dict)
- ]
- def _global_business_story(self, ref: RunRef) -> dict[str, Any]:
- summary = _load_json(ref.path / "run_summary.json", {}) or {}
- delivery = _load_json(
- ref.path / "global_data_stage_delivery.json", {}
- ) or {}
- plan_paths = _files(ref.path, "plans/global_data_dag.v*.json")
- rounds: list[dict[str, Any]] = []
- for round_index, plan_path in enumerate(plan_paths, start=1):
- plan = _load_json(plan_path, {}) or {}
- version = int(plan.get("plan_version") or _version(plan_path) or 1)
- steps: list[dict[str, Any]] = []
- for task in self._ordered_tasks(ref, plan.get("tasks") or []):
- task_id = str(task.get("task_id") or "")
- execution = _load_json(
- ref.path
- / "executor_results"
- / f"{task_id}.v{version}.json",
- {},
- ) or {}
- report = _load_json(
- ref.path
- / "validation_results"
- / f"{task_id}.v{version}.json",
- {},
- ) or {}
- verdict = report.get("verdict")
- status = (
- "success" if verdict == "PASS"
- else "failed" if verdict == "FAIL"
- else "running" if execution
- else "pending"
- )
- basis = [
- {
- "label": "业务来源",
- "detail": source,
- "source": source,
- }
- for source in task.get("source_paths") or []
- ]
- basis.extend(
- {
- "label": "验收目标",
- "detail": expectation,
- "source": expectation,
- }
- for expectation in task.get("expectation_ids") or []
- )
- basis.extend(
- {
- "label": "前置依赖",
- "detail": dependency,
- "source": dependency,
- }
- for dependency in task.get("depends_on") or []
- )
- outputs = [
- self._artifact_item(ref, artifact)
- for artifact in execution.get("artifacts") or []
- if isinstance(artifact, dict)
- ]
- steps.append(
- {
- "id": task_id,
- "stage": "GLOBAL DATA",
- "title": task.get("objective") or task_id,
- "status": status,
- "action": (
- execution.get("summary")
- or "已纳入本轮计划,尚未形成正式执行交付。"
- ),
- "reason": task.get("reason") or "",
- "basis": basis,
- "judgment": {
- "verdict": verdict or "PENDING",
- "summary": (
- report.get("summary")
- or "尚无独立 Validator 判断。"
- ),
- "criteria": self._criteria(report),
- },
- "outputs": outputs,
- "tools": [
- {
- "name": call.get("tool_name") or "tool",
- "status": (
- "SUCCEEDED"
- if call.get("success") is True
- else "FAILED"
- if call.get("success") is False
- else "UNKNOWN"
- ),
- "detail": call.get("output_excerpt") or "",
- }
- for call in execution.get("tool_calls") or []
- if isinstance(call, dict)
- ],
- }
- )
- if round_index == len(plan_paths):
- stage_paths = _files(
- ref.path, "stage_validation_results/global_data.v*.json"
- )
- if stage_paths:
- stage_report = _load_json(stage_paths[-1], {}) or {}
- stage_verdict = stage_report.get("verdict")
- steps.append(
- {
- "id": "GLOBAL_DATA_STAGE",
- "stage": "STAGE GATE",
- "title": "判断 Global Data 是否可交付给 Production",
- "status": (
- "success" if stage_verdict == "PASS"
- else "failed" if stage_verdict == "FAIL"
- else "running"
- ),
- "action": "汇总所有 Task 的正式产物,检查覆盖、冲突与未解决项。",
- "reason": "单个素材通过不等于整套生产输入完整,阶段门负责做跨 Task 的最终判断。",
- "basis": [
- {
- "label": "阶段输入",
- "detail": f"{len(plan.get('tasks') or [])} 个 Task 的正式交付与独立验收",
- "source": stage_paths[-1].name,
- }
- ],
- "judgment": {
- "verdict": stage_verdict or "PENDING",
- "summary": stage_report.get("summary") or "",
- "criteria": self._criteria(stage_report),
- },
- "outputs": [
- {
- "label": "Global Data Stage Delivery",
- "detail": delivery.get("summary") or "",
- "source": "global_data_stage_delivery.json",
- "media_url": None,
- }
- ] if delivery else [],
- "tools": [],
- }
- )
- passed = sum(step["status"] == "success" for step in steps)
- failed = sum(step["status"] == "failed" for step in steps)
- rounds.append(
- {
- "index": round_index,
- "title": f"Global Data Plan v{version}",
- "status": (
- "failed" if failed
- else "success" if steps and passed == len(steps)
- else "running"
- ),
- "summary": (
- plan.get("revision_summary")
- or plan.get("goal")
- or "Global Data 规划与验收"
- ),
- "steps": steps,
- }
- )
- raw_status = (
- summary.get("status") or delivery.get("status") or "RUNNING"
- )
- return {
- "kind": "global_data",
- "protocol_version": (
- summary.get("protocol_version")
- or (self._latest_plan(ref.path) or {}).get("schema_version")
- or ""
- ),
- "status": _viewer_status(raw_status),
- "phase": summary.get("phase") or "GLOBAL_DATA",
- "headline": "把 Production 需要的共享素材与约束准备完整",
- "conclusion": (
- delivery.get("summary")
- or summary.get("error")
- or "运行尚未形成阶段交付。"
- ),
- "failure": (
- {
- "code": summary.get("failure_code") or "GLOBAL_DATA_FAILED",
- "message": summary.get("error") or "",
- "stage": summary.get("phase") or "GLOBAL_DATA",
- }
- if _viewer_status(raw_status) == "failed"
- else None
- ),
- "rounds": rounds,
- }
- @staticmethod
- def _operation_segment(operation: dict[str, Any]) -> str:
- operation_id = str(
- operation.get("operation_scope")
- or operation.get("operation_id")
- or ""
- )
- match = re.search(r":(Segment[^:]+):v\d+:", operation_id)
- return match.group(1) if match else ""
- def _production_business_story(self, ref: RunRef) -> dict[str, Any]:
- summary = _load_json(
- ref.path / "production_run_summary.json", {}
- ) or {}
- plan_paths = _files(
- ref.path, "production_plans/production_dag.v*.json"
- )
- all_operations = [
- _load_json(path, {}) or {}
- for path in _files(ref.path, "tool_operations/*.json")
- ]
- rounds: list[dict[str, Any]] = []
- for round_index, plan_path in enumerate(plan_paths, start=1):
- plan = _load_json(plan_path, {}) or {}
- version = int(plan.get("plan_version") or _version(plan_path) or 1)
- steps: list[dict[str, Any]] = []
- for segment in plan.get("segments") or []:
- segment_id = str(segment.get("segment_id") or "")
- package_path = (
- ref.path
- / "segment_packages"
- / f"{segment_id}.v{version}.json"
- )
- package = _load_json(package_path, {}) or {}
- delivery_paths = _files(
- ref.path,
- f"segment_deliveries/{segment_id}.v*.json",
- )
- report_paths = _files(
- ref.path,
- f"segment_validation_results/{segment_id}.v*.json",
- )
- delivery = (
- _load_json(delivery_paths[-1], {}) or {}
- if delivery_paths else {}
- )
- report = (
- _load_json(report_paths[-1], {}) or {}
- if report_paths else {}
- )
- operations = [
- item
- for item in all_operations
- if self._operation_segment(item) == segment_id
- ]
- is_failed_segment = (
- summary.get("status") == "FAILED"
- and summary.get("current_segment_id") == segment_id
- )
- verdict = report.get("verdict")
- status = (
- "success" if verdict == "PASS"
- else "failed" if verdict == "FAIL" or is_failed_segment
- else "running" if package or operations
- else "pending"
- )
- artifact_inputs = (
- package.get("artifact_inputs")
- or segment.get("artifact_inputs")
- or []
- )
- basis = []
- for item in artifact_inputs:
- if not isinstance(item, dict):
- continue
- basis.append(
- {
- "label": (
- item.get("usage")
- or item.get("artifact_id")
- or "正式素材"
- ),
- "detail": (
- item.get("artifact_id")
- or item.get("input_id")
- or _clip(item.get("value"), 180)
- ),
- "source": (
- item.get("source_path")
- or item.get("artifact_id")
- or ""
- ),
- "media_url": self.media_url(
- ref, item.get("uri") or item.get("source_uri")
- ),
- }
- )
- basis.extend(
- {
- "label": "前置 Segment",
- "detail": dependency,
- "source": dependency,
- }
- for dependency in (
- segment.get("depends_on")
- or package.get("dependencies")
- or []
- )
- )
- outputs = [
- self._artifact_item(ref, artifact)
- for artifact in delivery.get("artifacts") or []
- if isinstance(artifact, dict)
- ]
- judgment_summary = report.get("summary") or ""
- judgment_verdict = verdict or "PENDING"
- if is_failed_segment:
- judgment_verdict = "FAIL"
- judgment_summary = (
- summary.get("error")
- or summary.get("event")
- or "Segment 执行失败。"
- )
- steps.append(
- {
- "id": segment_id,
- "stage": "PRODUCTION",
- "title": (
- segment.get("objective")
- or package.get("objective")
- or f"生产 {segment_id}"
- ),
- "status": status,
- "action": (
- delivery.get("summary")
- or (
- f"执行了 {len(operations)} 次媒体工具操作,"
- "但尚未形成合法 Segment Delivery。"
- if operations else
- "已规划,尚未进入正式生产。"
- )
- ),
- "reason": (
- f"完成时间线 {(
- package.get('timeline')
- or segment.get('timeline')
- or {}
- ).get('start_ms', '?')}–{(
- package.get('timeline')
- or segment.get('timeline')
- or {}
- ).get('end_ms', '?')} ms 的独立可验收片段。"
- ),
- "basis": basis,
- "judgment": {
- "verdict": judgment_verdict,
- "summary": (
- judgment_summary
- or "尚无正式 Segment ValidationReport。"
- ),
- "criteria": self._criteria(report),
- },
- "outputs": outputs,
- "tools": [
- {
- "name": operation.get("tool_name") or "tool",
- "status": operation.get("status") or "UNKNOWN",
- "detail": _clip(operation.get("result"), 360),
- }
- for operation in sorted(
- operations,
- key=lambda item: item.get("ordinal") or 0,
- )
- ],
- }
- )
- failed = sum(step["status"] == "failed" for step in steps)
- passed = sum(step["status"] == "success" for step in steps)
- rounds.append(
- {
- "index": round_index,
- "title": f"Production Plan v{version}",
- "status": (
- "failed" if failed
- else "success" if steps and passed == len(steps)
- else "running"
- ),
- "summary": (
- plan.get("revision_summary")
- or plan.get("summary")
- or f"按 {len(steps)} 个 Segment 组织正式生产"
- ),
- "steps": steps,
- }
- )
- raw_status = summary.get("status") or "RUNNING"
- return {
- "kind": "production",
- "protocol_version": (
- summary.get("schema_version")
- or (self._latest_production_plan(ref.path) or {}).get(
- "schema_version"
- )
- or ""
- ),
- "status": _viewer_status(raw_status),
- "phase": summary.get("phase") or "PRODUCTION",
- "headline": "按 Segment 生产、独立验收,再决定是否进入最终交付",
- "conclusion": (
- summary.get("event")
- or summary.get("error")
- or "运行尚未形成正式 Production 结论。"
- ),
- "failure": (
- {
- "code": summary.get("failure_code") or "PRODUCTION_FAILED",
- "message": summary.get("error") or summary.get("event") or "",
- "stage": summary.get("phase") or "PRODUCTION",
- }
- if _viewer_status(raw_status) == "failed"
- else None
- ),
- "rounds": rounds,
- }
- def snapshots(self, ref: RunRef) -> dict[str, Any]:
- if ref.kind == "global_data":
- snapshots = self._global_snapshots(ref)
- else:
- snapshots = self._segment_snapshots(ref)
- return {
- "run_id": ref.numeric_id,
- "run_key": ref.key,
- "objective": self.brief(ref)["objective"],
- "status": self.brief(ref)["status"],
- "snapshots": snapshots,
- }
- def _global_snapshots(self, ref: RunRef) -> list[dict[str, Any]]:
- paths = _files(ref.path, "plans/global_data_dag.v*.json")
- output: list[dict[str, Any]] = []
- previous_ids: set[str] = set()
- for index, path in enumerate(paths):
- plan = _load_json(path, {}) or {}
- version = plan.get("plan_version") or index + 1
- tasks = plan.get("tasks") or []
- current_ids = {str(item.get("task_id")) for item in tasks}
- added = sorted(current_ids - previous_ids)
- removed = sorted(previous_ids - current_ids)
- nodes = [
- self._snapshot_task(ref, task, version) for task in tasks
- ]
- output.append(
- {
- "loop_index": index,
- "kind": "initial" if index == 0 else "replan",
- "title": f"Plan v{version}",
- "step_id": index + 1,
- "step_index": index + 1,
- "is_final": index == len(paths) - 1,
- "created_at": _iso(path.stat().st_mtime),
- "reasoning": plan.get("revision_summary") or plan.get("goal"),
- "tree_changed": bool(added or removed),
- "diff": {
- "added": added,
- "removed": removed,
- "modified": [],
- },
- "lessons_added": [],
- "lessons_cumulative": [],
- "tree": {"nodes": nodes},
- "node_change": {
- **{item: "added" for item in added},
- **{item: "removed" for item in removed},
- },
- "round_execution": None,
- }
- )
- previous_ids = current_ids
- return output
- def _snapshot_task(
- self, ref: RunRef, task: dict[str, Any], version: int
- ) -> dict[str, Any]:
- task_id = str(task.get("task_id") or "")
- delivery = _load_json(
- ref.path / "executor_results" / f"{task_id}.v{version}.json", {}
- ) or {}
- report = _load_json(
- ref.path / "validation_results" / f"{task_id}.v{version}.json", {}
- ) or {}
- verdict = report.get("verdict")
- status = "completed" if verdict == "PASS" else (
- "failed" if verdict == "FAIL" else "pending"
- )
- return {
- "step_id": task_id,
- "task_id": task_id,
- "parent_id": None,
- "name": task.get("objective") or task_id,
- "goal": task.get("reason") or "",
- "status": status,
- "kind": task.get("skill_id"),
- "acceptance": task.get("expectation_ids") or [],
- "inputs": task.get("depends_on") or [],
- "stage": "GLOBAL_DATA",
- "category": task.get("deliverable_type") or "",
- "executing": False,
- "result": (
- {
- "summary": delivery.get("summary") or report.get("summary"),
- "product_url": None,
- "product_text": None,
- "verdict": report,
- "attempts": 1,
- }
- if delivery or report
- else None
- ),
- "exec_step_id": None,
- "tools": [
- item.get("tool_name")
- for item in delivery.get("tool_calls") or []
- if item.get("tool_name")
- ],
- "trace_summary": {
- "llm": 0,
- "tool": len(delivery.get("tool_calls") or []),
- },
- }
- def _segment_snapshots(self, ref: RunRef) -> list[dict[str, Any]]:
- plan = self._latest_production_plan(ref.path) or {}
- packages = [
- _load_json(path, {}) or {}
- for path in _files(ref.path, "segment_packages/*.json")
- ]
- nodes = []
- for package in packages:
- segment_id = package.get("segment_id") or "Segment"
- reports = _files(
- ref.path,
- f"segment_validation_results/{segment_id}.v*.json",
- )
- report = _load_json(reports[-1], {}) if reports else {}
- verdict = (report or {}).get("verdict")
- nodes.append(
- {
- "step_id": segment_id,
- "task_id": segment_id,
- "parent_id": None,
- "name": segment_id,
- "goal": f"生产并验收 {segment_id}",
- "status": (
- "completed" if verdict == "PASS"
- else "failed" if verdict == "FAIL"
- else "running"
- ),
- "kind": "segment-production",
- "acceptance": [],
- "inputs": [
- item.get("input_id")
- for item in package.get("production_inputs") or []
- ],
- "stage": "PRODUCTION",
- "category": "video",
- "executing": verdict is None,
- "result": report or None,
- "exec_step_id": None,
- "tools": [],
- "trace_summary": {"llm": 0, "tool": 0},
- }
- )
- return [
- {
- "loop_index": 0,
- "kind": "initial",
- "title": f"Production Plan v{plan.get('plan_version', 1)}",
- "step_id": 1,
- "step_index": 1,
- "is_final": self.brief(ref)["status"] != "running",
- "created_at": None,
- "reasoning": plan.get("summary") or "",
- "tree_changed": True,
- "diff": {
- "added": [node["step_id"] for node in nodes],
- "removed": [],
- "modified": [],
- },
- "lessons_added": [],
- "lessons_cumulative": [],
- "tree": {"nodes": nodes},
- "node_change": {
- node["step_id"]: "added" for node in nodes
- },
- "round_execution": None,
- }
- ]
- def flat(self, ref: RunRef, round_index: int | None) -> dict[str, Any]:
- if ref.kind == "global_data":
- return self._global_flat(ref, round_index)
- return self._segment_flat(ref, round_index)
- @staticmethod
- def _module_def(
- module_id: int,
- key: str,
- *,
- name: str,
- summary: str,
- tools: Iterable[str] = (),
- inputs: Iterable[tuple[str, str]] = (),
- model: str = "",
- refs: Iterable[tuple[str, str]] = (),
- ) -> dict[str, Any]:
- return {
- "id": module_id,
- "module_key": key,
- "kind": "agent",
- "name": name,
- "summary": summary,
- "spec": {
- "node_kind": "agent",
- "summary": summary,
- "system_prompt": "",
- "input_schema": [
- {
- "key": input_key,
- "name": input_key,
- "title": title,
- "required": True,
- "source": title,
- }
- for input_key, title in inputs
- ],
- "tools": [{"name": value} for value in tools],
- "model": model,
- },
- "view": None,
- "fingerprint": hashlib.sha256(
- f"{key}:{summary}".encode("utf-8")
- ).hexdigest()[:8],
- "refs": [
- {
- "node_key": node_key,
- "to_module_key": target,
- "seq": index,
- "title": target,
- "cardinality": "one",
- "fanout_over": "",
- }
- for index, (node_key, target) in enumerate(refs)
- ],
- }
- @staticmethod
- def _instance(
- instance_id: int,
- module_id: int,
- module_key: str,
- *,
- label: str,
- task_id: str | None,
- ok: bool | None,
- inputs: list[dict[str, Any]],
- output: Any,
- flow: list[dict[str, Any]],
- used_tools: Iterable[str] = (),
- images: Iterable[str] = (),
- ) -> dict[str, Any]:
- return {
- "id": instance_id,
- "module_id": module_id,
- "module_key": module_key,
- "label": label,
- "task_id": task_id,
- "step_id": task_id,
- "step_index": instance_id,
- "branch": "",
- "ok": ok,
- "input": {"blocks": inputs},
- "output": {
- "data": output,
- "ok": ok,
- "images": list(images),
- } if output is not None else None,
- "timing": {"sec": None},
- "tokens": "",
- "caller": None,
- "used_tools": sorted(set(used_tools)),
- "flow": flow,
- }
- def _global_flat(
- self, ref: RunRef, round_index: int | None
- ) -> dict[str, Any]:
- plans = _files(ref.path, "plans/global_data_dag.v*.json")
- metrics = _load_json(ref.path / "run_metrics.json", {}) or {}
- model = self._model_names(metrics)
- module_defs = {
- 1: self._module_def(
- 1, "production.global_data.plan",
- name="Global Data Planner",
- summary="读取 Production Brief,生成或修订完整 Global Data DAG。",
- inputs=(("brief", "Production Brief"),),
- model=model,
- ),
- 2: self._module_def(
- 2, "production.global_data.execute",
- name="Global Data Executor",
- summary="按 TaskPackage 与 Skill 白名单执行一个 Task。",
- inputs=(("task", "TaskPackage"),),
- model=model,
- ),
- 3: self._module_def(
- 3, "production.global_data.validate_task",
- name="Task Validator",
- summary="在独立上下文中逐项验收 Executor Delivery。",
- inputs=(("delivery", "Executor Delivery"),),
- model=model,
- ),
- 4: self._module_def(
- 4, "production.global_data.validate_stage",
- name="Stage Validator",
- summary="全部 Task 通过后检查阶段完整性、冲突和漏项。",
- inputs=(("plan", "Global Data Plan"), ("tasks", "PASS Deliveries")),
- model=model,
- ),
- }
- rounds: list[dict[str, Any]] = []
- for index, path in enumerate(plans):
- if round_index is not None and index != round_index:
- continue
- plan = _load_json(path, {}) or {}
- version = int(plan.get("plan_version") or index + 1)
- instances: list[dict[str, Any]] = []
- next_id = (index + 1) * 1000
- next_id += 1
- planner_id = next_id
- instances.append(
- self._instance(
- planner_id, 1, "production.global_data.plan",
- label=f"Plan v{version}",
- task_id=None,
- ok=True,
- inputs=[
- _input_block(
- "brief", "Production Brief",
- plan.get("goal"), source="production_brief.json",
- )
- ],
- output=plan,
- flow=[
- _node_card(
- 0, node_type="llm", label="规划",
- summary=plan.get("revision_summary") or plan.get("goal"),
- ok=True, detail=plan,
- )
- ],
- )
- )
- entry_ids = [planner_id]
- for task in self._ordered_tasks(ref, plan.get("tasks") or []):
- task_id = str(task.get("task_id"))
- delivery = _load_json(
- ref.path / "executor_results" / f"{task_id}.v{version}.json",
- {},
- ) or {}
- report = _load_json(
- ref.path / "validation_results" / f"{task_id}.v{version}.json",
- {},
- ) or {}
- next_id += 1
- executor_id = next_id
- tools = [
- item.get("tool_name")
- for item in delivery.get("tool_calls") or []
- if item.get("tool_name")
- ]
- flow = [
- _node_card(
- flow_index,
- node_type="tool",
- label=call.get("tool_name") or "tool",
- summary=call.get("output_excerpt"),
- ok=call.get("success"),
- detail={
- "input": call.get("arguments"),
- "output": call.get("output_excerpt"),
- },
- tool_call_id=call.get("tool_call_id") or "",
- )
- for flow_index, call in enumerate(
- delivery.get("tool_calls") or []
- )
- ]
- if not flow and delivery:
- flow = [
- _node_card(
- 0,
- node_type="tool",
- label="确定性交付",
- summary=delivery.get("summary") or "已写入交付结果",
- ok=True,
- detail=delivery,
- )
- ]
- delivery_view = self._delivery_view(ref, delivery)
- image_urls = [
- artifact["browser_uri"]
- for artifact in (delivery_view or {}).get("artifacts") or []
- if str(
- artifact.get("mime_type")
- or artifact.get("media_type")
- or ""
- ).startswith("image/")
- and artifact.get("browser_uri")
- ]
- instances.append(
- self._instance(
- executor_id, 2, "production.global_data.execute",
- label=task.get("objective") or task_id,
- task_id=task_id,
- ok=bool(delivery),
- inputs=[
- _input_block(
- "task", "TaskPackage", task,
- source=f"tasks/{task_id}.v{version}.json",
- )
- ],
- output=delivery_view,
- flow=flow or [
- _node_card(
- 0, node_type="note", label="等待执行",
- summary="尚无 Executor Delivery", ok=None,
- )
- ],
- used_tools=tools,
- images=image_urls,
- )
- )
- entry_ids.append(executor_id)
- next_id += 1
- validator_id = next_id
- instances.append(
- self._instance(
- validator_id, 3,
- "production.global_data.validate_task",
- label=f"{task_id} 验收",
- task_id=task_id,
- ok=report.get("verdict") == "PASS" if report else None,
- inputs=[
- _input_block(
- "delivery", "Executor Delivery",
- delivery.get("summary"),
- source=f"executor_results/{task_id}.v{version}.json",
- )
- ],
- output=report or None,
- flow=[
- _node_card(
- 0, node_type="llm", label="独立验收",
- summary=report.get("summary") or "尚无验收报告",
- ok=(
- report.get("verdict") == "PASS"
- if report else None
- ),
- detail=report or None,
- )
- ],
- )
- )
- entry_ids.append(validator_id)
- stage_paths = _files(
- ref.path,
- f"stage_validation_results/global_data.v{version}.json",
- )
- if stage_paths:
- stage = _load_json(stage_paths[-1], {}) or {}
- next_id += 1
- stage_id = next_id
- instances.append(
- self._instance(
- stage_id, 4, "production.global_data.validate_stage",
- label="Global Data Stage 验收",
- task_id=None,
- ok=stage.get("verdict") == "PASS",
- inputs=[
- _input_block(
- "plan", "Global Data Plan", f"v{version}",
- source=path.name,
- ),
- _input_block(
- "tasks", "PASS Deliveries",
- [item.get("task_id") for item in plan.get("tasks") or []],
- source="executor_results/",
- ),
- ],
- output=stage,
- flow=[
- _node_card(
- 0, node_type="llm", label="阶段总验收",
- summary=stage.get("summary"),
- ok=stage.get("verdict") == "PASS",
- detail=stage,
- )
- ],
- )
- )
- entry_ids.append(stage_id)
- rounds.append(
- {"index": index, "entry_ids": entry_ids, "instances": instances}
- )
- root = {
- "id": 0,
- "module_id": 0,
- "module_key": "production.global_data.workflow",
- "label": "Global Data 0.3",
- "task_id": None,
- "step_id": None,
- "step_index": 0,
- "branch": "",
- "ok": self.brief(ref)["status"] == "success",
- "input": {"blocks": []},
- "output": None,
- "timing": {"sec": self.brief(ref)["duration_sec"]},
- "tokens": "",
- "caller": None,
- "used_tools": [],
- "flow": [],
- "module": {
- "id": 0,
- "module_key": "production.global_data.workflow",
- "kind": "workflow",
- "name": "Global Data Workflow",
- "summary": "Preprocess → Plan → Execute → Validate → Replan/Finalize",
- "spec": {},
- "view": None,
- "fingerprint": "0.3",
- "refs": [],
- },
- }
- return {
- "run_id": ref.numeric_id,
- "run_key": ref.key,
- "root": root,
- "modules": module_defs,
- "round_count": len(plans),
- "rounds": rounds,
- }
- @staticmethod
- def _ordered_tasks(
- ref: RunRef, tasks: list[dict[str, Any]]
- ) -> list[dict[str, Any]]:
- summary = _load_json(ref.path / "run_summary.json", {}) or {}
- order: list[str] = []
- for event in summary.get("event_log") or []:
- match = re.search(r"(Task\d+)", event)
- if match and match.group(1) not in order:
- order.append(match.group(1))
- rank = {task_id: index for index, task_id in enumerate(order)}
- return sorted(
- tasks,
- key=lambda item: (
- rank.get(str(item.get("task_id")), len(rank)),
- str(item.get("task_id")),
- ),
- )
- def _delivery_view(
- self, ref: RunRef, delivery: dict[str, Any]
- ) -> dict[str, Any] | None:
- if not delivery:
- return None
- result = dict(delivery)
- result["artifacts"] = [
- {
- **artifact,
- "browser_uri": self.media_url(ref, artifact.get("uri")),
- }
- for artifact in delivery.get("artifacts") or []
- ]
- return result
- def _segment_flat(
- self, ref: RunRef, round_index: int | None
- ) -> dict[str, Any]:
- plan = self._latest_production_plan(ref.path) or {}
- packages = [
- (path, _load_json(path, {}) or {})
- for path in _files(ref.path, "segment_packages/*.json")
- ]
- modules = {
- 11: self._module_def(
- 11, "production.segment.execute",
- name="Segment Executor",
- summary="按 SegmentPackage 生产镜头、声音、字幕和最终片段。",
- inputs=(("package", "SegmentPackage"),),
- ),
- 12: self._module_def(
- 12, "production.segment.validate",
- name="Segment Validator",
- summary="确定性证据前检后,独立判断六项 Segment 质量。",
- inputs=(("delivery", "Segment Delivery"),),
- ),
- }
- instances: list[dict[str, Any]] = []
- entry_ids: list[int] = []
- all_operations = [
- _load_json(path, {}) or {}
- for path in _files(ref.path, "tool_operations/*.json")
- ]
- for index, (package_path, package) in enumerate(packages):
- segment_id = str(package.get("segment_id") or f"Segment{index + 1}")
- executor_id = 2000 + index * 10 + 1
- operations = [
- operation
- for operation in all_operations
- if self._operation_segment(operation) == segment_id
- ]
- flow = [
- _node_card(
- flow_index,
- node_type="tool",
- label=operation.get("tool_name") or "tool",
- summary=operation.get("status"),
- ok=(
- True
- if operation.get("status") == "SUCCEEDED"
- else False
- if operation.get("status") == "FAILED"
- else None
- ),
- detail=operation,
- )
- for flow_index, operation in enumerate(operations)
- ]
- deliveries = _files(
- ref.path, f"segment_deliveries/{segment_id}.v*.json"
- )
- delivery = _load_json(deliveries[-1], {}) if deliveries else {}
- instances.append(
- self._instance(
- executor_id, 11, "production.segment.execute",
- label=segment_id,
- task_id=segment_id,
- ok=bool(delivery) if deliveries else None,
- inputs=[
- _input_block(
- "package", "SegmentPackage", package,
- source=str(package_path.relative_to(ref.path)),
- )
- ],
- output=delivery or None,
- flow=flow or [
- _node_card(
- 0, node_type="note", label="等待执行",
- summary="尚未形成 Segment Delivery", ok=None,
- )
- ],
- used_tools=[
- item.get("tool_name")
- for item in operations
- if item.get("tool_name")
- ],
- )
- )
- entry_ids.append(executor_id)
- reports = _files(
- ref.path,
- f"segment_validation_results/{segment_id}.v*.json",
- )
- if reports:
- report = _load_json(reports[-1], {}) or {}
- validator_id = executor_id + 1
- instances.append(
- self._instance(
- validator_id, 12, "production.segment.validate",
- label=f"{segment_id} 验收",
- task_id=segment_id,
- ok=report.get("verdict") == "PASS",
- inputs=[
- _input_block(
- "delivery", "Segment Delivery",
- delivery, source=deliveries[-1].name,
- )
- ],
- output=report,
- flow=[
- _node_card(
- 0, node_type="llm", label="六项独立验收",
- summary=report.get("summary"),
- ok=report.get("verdict") == "PASS",
- detail=report,
- )
- ],
- )
- )
- entry_ids.append(validator_id)
- rounds = (
- [{"index": 0, "entry_ids": entry_ids, "instances": instances}]
- if round_index in (None, 0)
- else []
- )
- protocol_version = str(plan.get("schema_version") or "unknown")
- root = {
- "id": 10,
- "module_id": 10,
- "module_key": "production.segment.workflow",
- "label": (
- f"Production {protocol_version} · "
- f"{plan.get('plan_id', ref.key)}"
- ),
- "task_id": None,
- "step_id": None,
- "step_index": 0,
- "branch": "",
- "ok": self.brief(ref)["status"] == "success",
- "input": {"blocks": []},
- "output": None,
- "timing": {"sec": self.brief(ref)["duration_sec"]},
- "tokens": "",
- "caller": None,
- "used_tools": [],
- "flow": [],
- "module": {
- "id": 10,
- "module_key": "production.segment.workflow",
- "kind": "workflow",
- "name": "Segment Workflow",
- "summary": "SegmentPackage → Executor → Validator",
- "spec": {},
- "view": None,
- "fingerprint": protocol_version,
- "refs": [],
- },
- }
- return {
- "run_id": ref.numeric_id,
- "run_key": ref.key,
- "root": root,
- "modules": modules,
- "round_count": 1,
- "rounds": rounds,
- }
- def media_path(self, ref: RunRef, relative: str) -> Path:
- candidate = (ref.path / relative).resolve()
- if not candidate.is_relative_to(ref.path) or not candidate.is_file():
- raise FileNotFoundError(relative)
- return candidate
- def media_url(self, ref: RunRef, uri: Any) -> str | None:
- if not isinstance(uri, str) or not uri:
- return None
- try:
- path = Path(uri).resolve()
- relative = path.relative_to(ref.path)
- except (ValueError, OSError):
- return uri if uri.startswith(("http://", "https://")) else None
- return f"/api/runs/{ref.numeric_id}/media/{relative.as_posix()}"
- def tools(self) -> dict[str, Any]:
- from production_build_agents.tools.registry import (
- create_default_tool_registry,
- )
- # ToolRegistry 没有只读定义接口;从 Skill 白名单和工具 README 返回稳定说明,
- # 不实例化远端客户端,也不触发环境校验。
- names = {
- "read_production_brief",
- "search_tool",
- "inspect_tool",
- "run_tool",
- "probe_media",
- "view_images",
- "extract_frames",
- "publish_media_reference",
- "transcribe_audio",
- "create_ass_subtitles",
- "inspect_ass_subtitles",
- "render_ass_subtitles",
- "audio_trim",
- "mix_audio_tracks",
- "video_trim",
- "video_concat",
- "video_mux_audio",
- }
- _ = create_default_tool_registry # 保留到实现正式定义投影时使用。
- return {
- name: {
- "description": "Production Build 运行时工具",
- "params": [],
- }
- for name in sorted(names)
- }
- def media_type(path: Path) -> str:
- return mimetypes.guess_type(path.name)[0] or "application/octet-stream"
|