protocols.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. """
  2. Trace 存储协议。
  3. 使用 Protocol 约束 Runner、Sub-Agent、资源预算和 API 依赖的存储能力,
  4. 使文件系统或未来的数据库实现可替换而不改上层调用。
  5. """
  6. from typing import Protocol, List, Optional, Dict, Any, runtime_checkable
  7. from .models import Trace, Message
  8. from .goal_models import GoalTree, Goal
  9. @runtime_checkable
  10. class TraceStore(Protocol):
  11. """Trace、Message、GoalTree 与 Recursive 树级用量的统一存储接口。
  12. Runner 负责主路径读写,Sub-Agent 用父子过滤查询直接孩子,预算控制器读写根树用量。"""
  13. # ===== Trace 操作 =====
  14. async def create_trace(self, trace: Trace) -> str:
  15. """
  16. 创建新的 Trace
  17. Args:
  18. trace: Trace 对象
  19. Returns:
  20. trace_id
  21. """
  22. ...
  23. async def get_trace(self, trace_id: str) -> Optional[Trace]:
  24. """获取 Trace"""
  25. ...
  26. async def update_trace(self, trace_id: str, **updates) -> None:
  27. """
  28. 更新 Trace
  29. Args:
  30. trace_id: Trace ID
  31. **updates: 要更新的字段
  32. """
  33. ...
  34. async def list_traces(
  35. self,
  36. mode: Optional[str] = None,
  37. agent_type: Optional[str] = None,
  38. uid: Optional[str] = None,
  39. status: Optional[str] = None,
  40. limit: int = 50,
  41. parent_trace_id: Optional[str] = None,
  42. created_by_tool: Optional[str] = None,
  43. ) -> List[Trace]:
  44. """按条件列出 Trace,过滤必须在 limit 之前完成。
  45. Recursive Spawn Guard 用 parent_trace_id + created_by_tool 精确统计直接业务孩子。"""
  46. ...
  47. # ===== Recursive 树级资源用量 =====
  48. async def get_resource_usage(
  49. self,
  50. root_trace_id: str,
  51. ) -> Optional[Dict[str, Any]]:
  52. """读取 Recursive 根 Trace 的树级累计用量。
  53. ResourceBudgetController 在预留 Agent/LLM 或登记 Token/成本前后调用。"""
  54. ...
  55. async def replace_resource_usage(
  56. self,
  57. root_trace_id: str,
  58. usage: Dict[str, Any],
  59. ) -> None:
  60. """原子替换 Recursive 根 Trace 的树级累计用量。
  61. ResourceBudgetController 在单进程根树锁内调用,存储实现需避免留下半写入快照。"""
  62. ...
  63. async def get_candidate_ledger(
  64. self,
  65. root_trace_id: str,
  66. ) -> Optional[Dict[str, Any]]:
  67. """Read the root Trace's framework-owned candidate ledger."""
  68. ...
  69. async def replace_candidate_ledger(
  70. self,
  71. root_trace_id: str,
  72. ledger: Dict[str, Any],
  73. ) -> None:
  74. """Atomically replace the root Trace's candidate ledger."""
  75. ...
  76. # ===== GoalTree 操作 =====
  77. async def get_goal_tree(self, trace_id: str) -> Optional[GoalTree]:
  78. """
  79. 获取 GoalTree
  80. Args:
  81. trace_id: Trace ID
  82. Returns:
  83. GoalTree 对象,如果不存在返回 None
  84. """
  85. ...
  86. async def update_goal_tree(self, trace_id: str, tree: GoalTree) -> None:
  87. """
  88. 更新完整 GoalTree
  89. Args:
  90. trace_id: Trace ID
  91. tree: GoalTree 对象
  92. """
  93. ...
  94. async def add_goal(self, trace_id: str, goal: Goal) -> None:
  95. """
  96. 添加 Goal 到 GoalTree
  97. Args:
  98. trace_id: Trace ID
  99. goal: Goal 对象
  100. """
  101. ...
  102. async def update_goal(self, trace_id: str, goal_id: str, **updates) -> None:
  103. """
  104. 更新 Goal 字段
  105. Args:
  106. trace_id: Trace ID
  107. goal_id: Goal ID
  108. **updates: 要更新的字段(如 status, summary, self_stats, cumulative_stats)
  109. """
  110. ...
  111. # ===== Message 操作 =====
  112. async def add_message(self, message: Message) -> str:
  113. """
  114. 添加 Message
  115. 自动更新关联 Goal 的 stats(self_stats 和祖先的 cumulative_stats)
  116. Args:
  117. message: Message 对象
  118. Returns:
  119. message_id
  120. """
  121. ...
  122. async def get_message(self, message_id: str) -> Optional[Message]:
  123. """获取 Message"""
  124. ...
  125. async def get_trace_messages(
  126. self,
  127. trace_id: str,
  128. ) -> List[Message]:
  129. """
  130. 获取 Trace 的所有 Messages(按 sequence 排序)
  131. 返回该 Trace 下所有消息(包含所有分支)。
  132. 如需获取特定主路径的消息,使用 get_main_path_messages()。
  133. Args:
  134. trace_id: Trace ID
  135. Returns:
  136. Message 列表
  137. """
  138. ...
  139. async def get_main_path_messages(
  140. self,
  141. trace_id: str,
  142. head_sequence: int
  143. ) -> List[Message]:
  144. """
  145. 获取主路径上的消息(从 head_sequence 沿 parent_sequence 链回溯到 root)
  146. Args:
  147. trace_id: Trace ID
  148. head_sequence: 主路径头节点的 sequence
  149. Returns:
  150. 按 sequence 正序排列的主路径 Message 列表
  151. """
  152. ...
  153. async def get_messages_by_goal(
  154. self,
  155. trace_id: str,
  156. goal_id: str
  157. ) -> List[Message]:
  158. """
  159. 获取指定 Goal 关联的所有 Messages
  160. Args:
  161. trace_id: Trace ID
  162. goal_id: Goal ID
  163. Returns:
  164. Message 列表
  165. """
  166. ...
  167. async def update_message(self, message_id: str, **updates) -> None:
  168. """
  169. 更新 Message 字段(用于状态变更、错误记录等)
  170. Args:
  171. message_id: Message ID
  172. **updates: 要更新的字段
  173. """
  174. ...
  175. async def abandon_messages_after(self, trace_id: str, cutoff_sequence: int) -> List[str]:
  176. """
  177. 将 cutoff_sequence 之后的所有 active 消息标记为 abandoned(回溯专用)
  178. Args:
  179. trace_id: Trace ID
  180. cutoff_sequence: 截断点(该 sequence 及之前的消息保留)
  181. Returns:
  182. 被标记为 abandoned 的 message_id 列表
  183. """
  184. ...
  185. # ===== 事件流操作(用于 WebSocket 断线续传)=====
  186. async def get_events(
  187. self,
  188. trace_id: str,
  189. since_event_id: int = 0
  190. ) -> List[Dict[str, Any]]:
  191. """
  192. 获取事件流(用于 WS 断线续传)
  193. Args:
  194. trace_id: Trace ID
  195. since_event_id: 从哪个事件 ID 开始(0 表示全部)
  196. Returns:
  197. 事件列表(按 event_id 排序)
  198. """
  199. ...
  200. async def append_event(
  201. self,
  202. trace_id: str,
  203. event_type: str,
  204. payload: Dict[str, Any]
  205. ) -> int:
  206. """
  207. 追加事件,返回 event_id
  208. Args:
  209. trace_id: Trace ID
  210. event_type: 事件类型
  211. payload: 事件数据
  212. Returns:
  213. event_id: 新事件的 ID
  214. """
  215. ...
  216. async def get_tool_approval_batch(self, trace_id: str):
  217. """Load the persisted approval batch for a Trace, if any."""
  218. ...
  219. async def replace_tool_approval_batch(self, trace_id: str, batch) -> None:
  220. """Atomically replace a Trace's tool approval batch."""
  221. ...
  222. async def mark_reflections_consumed(
  223. self,
  224. trace_id: str,
  225. reflections: List[Dict[str, Any]],
  226. consumed_at: str,
  227. ) -> int:
  228. """Atomically mark selected reflection cognition events consumed."""
  229. ...
  230. async def write_message_attachment(
  231. self,
  232. trace_id: str,
  233. message_id: str,
  234. *,
  235. suffix: str,
  236. data: bytes,
  237. ):
  238. """Atomically persist a Message-owned binary attachment."""
  239. ...