projector.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. from __future__ import annotations
  2. import re
  3. from collections.abc import Callable
  4. from typing import Any
  5. from .implementation import (
  6. project_branch_output,
  7. project_creative,
  8. project_data_decision,
  9. project_domain_info,
  10. project_implementation_task,
  11. project_multipath_decision,
  12. )
  13. from .planning import (
  14. project_implementation_plan,
  15. project_objective,
  16. project_round_goal,
  17. )
  18. from .results import project_final_result, project_round_result
  19. from .summaries import (
  20. project_branch_summary,
  21. project_missing_convergence,
  22. project_missing_round_evaluation,
  23. project_round_summary,
  24. )
  25. from .retrieval import (
  26. project_direct_group,
  27. project_event,
  28. project_retrieval_agent,
  29. project_retrieval_stage,
  30. )
  31. class CardDataNotFound(LookupError):
  32. pass
  33. class CardBusinessDataProjector:
  34. """Read-only application projector for one card's complete data flow.
  35. The HTTP adapter supplies plain bundle/view dictionaries and a lazy event
  36. loader. The projector has no database or FastAPI dependency.
  37. """
  38. def project(
  39. self,
  40. detail_ref: str,
  41. *,
  42. bundle: dict[str, Any],
  43. view: dict[str, Any],
  44. load_event: Callable[[int], dict[str, Any]],
  45. ) -> dict[str, Any]:
  46. ref = str(detail_ref or "").strip()
  47. try:
  48. if ref == "run:objective":
  49. return project_objective(bundle, view, load_event)
  50. if ref in {"run:final-result", "artifact:base:current", "base:current"}:
  51. return project_final_result("run:final-result", bundle, view)
  52. if ref.startswith("event:"):
  53. return project_event(ref, load_event)
  54. if ref.startswith("retrieval-direct:"):
  55. return project_direct_group(ref, view, load_event)
  56. if ref.startswith("retrieval-agent:"):
  57. return project_retrieval_agent(ref, view, load_event)
  58. if ref.startswith("data-decision:"):
  59. return project_data_decision(ref, bundle, view, load_event)
  60. if ref.startswith("creative:"):
  61. return project_creative(ref, bundle, view, load_event)
  62. if ref.startswith("multipath-decision:"):
  63. return project_multipath_decision(ref, bundle, view, load_event)
  64. if ref.startswith("domain-info:"):
  65. return project_domain_info(ref, bundle)
  66. match = re.fullmatch(r"round:(\d+)", ref)
  67. if match:
  68. return project_round_summary(
  69. ref, int(match.group(1)), bundle, view, load_event
  70. )
  71. match = re.fullmatch(r"round:(\d+):branch:(\d+)", ref)
  72. if match:
  73. return project_branch_summary(
  74. ref,
  75. int(match.group(1)),
  76. int(match.group(2)),
  77. bundle,
  78. view,
  79. load_event,
  80. )
  81. match = re.fullmatch(r"round:(\d+):(goal|plan|result)", ref)
  82. if match:
  83. round_index = int(match.group(1))
  84. role = match.group(2)
  85. if role == "goal":
  86. return project_round_goal(ref, round_index, bundle, view, load_event)
  87. if role == "plan":
  88. return project_implementation_plan(ref, round_index, bundle, view, load_event)
  89. return project_round_result(ref, round_index, bundle, view, load_event)
  90. match = re.fullmatch(r"round:(\d+):evaluation", ref)
  91. if match:
  92. return project_missing_round_evaluation(
  93. ref, int(match.group(1)), bundle, view
  94. )
  95. match = re.fullmatch(
  96. r"round:(\d+):[^:]+:(review|decision)-missing", ref
  97. )
  98. if match:
  99. return project_missing_convergence(
  100. ref,
  101. int(match.group(1)),
  102. match.group(2),
  103. view,
  104. )
  105. match = re.fullmatch(r"round:(\d+):branch:(\d+):(task|retrieval|output)", ref)
  106. if match:
  107. round_index, branch_id = int(match.group(1)), int(match.group(2))
  108. role = match.group(3)
  109. if role == "task":
  110. return project_implementation_task(ref, round_index, branch_id, bundle, view, load_event)
  111. if role == "retrieval":
  112. return project_retrieval_stage(ref, round_index, branch_id, view, load_event)
  113. return project_branch_output(ref, round_index, branch_id, bundle, view)
  114. except KeyError as exc:
  115. raise CardDataNotFound(f"未找到卡片数据 {ref}") from exc
  116. raise CardDataNotFound(f"未找到卡片数据 {ref}")