oclaw/runtime/orchestration/protocol.py
oliver 4a23b715a2 重构仓库目录为统一的 runtime 分层并清理历史 openclaw 残留。
本次迁移将网关/通道/工具/技能/脚本与协议资源集中到新结构,统一路径常量与脚本转发机制,减少顶层噪音并保证运行与测试行为一致。

Made-with: Cursor
2026-04-25 01:24:23 +08:00

119 lines
3.4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

from __future__ import annotations
from dataclasses import dataclass, field
from typing import Any
TaskKind = str
RiskLevel = str
@dataclass(frozen=True)
class AgentTask:
session_id: str
user_text: str
attachments: list[dict[str, Any]] = field(default_factory=list)
kind: TaskKind = "generalist"
risk_level: RiskLevel = "low"
specialist: str = "generalist"
metadata: dict[str, Any] = field(default_factory=dict)
@dataclass(frozen=True)
class RoutingDecision:
kind: TaskKind
specialist: str
risk_level: RiskLevel
reason: str
# 规范说明:
# - specialist: 路由/计划层使用的专家标识(例如 ops / generalist)
# - expert: 工具目录名(例如 network_ops / generalist)
# - tool_tags: 运行期开关过滤(例如 ops / system)
@dataclass(frozen=True)
class PlanStep:
step_id: str
specialist: str
objective: str
input_text: str
depends_on: list[str] = field(default_factory=list)
@dataclass(frozen=True)
class ManagerPlan:
plan_id: str
strategy: str
steps: list[PlanStep] = field(default_factory=list)
raw_text: str = ""
@dataclass(frozen=True)
class SpecialistToolTrace:
"""单条工具调用摘要(专家会话内执行,用于交付给总控的可追溯信息)。"""
name: str
ok: bool
latency_ms: int = 0
@dataclass(frozen=True)
class SpecialistDelivery:
"""
专家 → 总控(Core)的结构化交付。
- answer_text:面向用户的专家结论(已结合工具结果,与 output_text 对齐)。
- tool_traces:本步内在专家侧实际执行的工具摘要(非总控直接执行)。
"""
version: int = 1
specialist: str = ""
step_id: str = ""
answer_text: str = ""
tool_traces: tuple[SpecialistToolTrace, ...] = ()
notes: str = ""
def format_specialist_handoff_for_core(res: "SpecialistResult") -> str:
"""将专家结果格式化为总控合并提示中的单步条目(可读 + 明示 handoff 边界)。"""
if res.delivery and res.delivery.answer_text.strip():
d = res.delivery
lines = [
f"### handoff v{d.version} step={d.step_id} specialist={d.specialist}",
"role=specialist_completed",
f"answer_for_user:\n{d.answer_text.strip()}",
]
if d.tool_traces:
parts = []
for t in d.tool_traces:
parts.append(f"{t.name}(ok={t.ok}, {t.latency_ms}ms)")
lines.append(f"tools_executed_inside_specialist: " + "; ".join(parts))
else:
lines.append("tools_executed_inside_specialist: (none)")
if (d.notes or "").strip():
lines.append(f"notes: {d.notes.strip()}")
lines.append(
"instruction_for_core: 专家已基于工具输出整理 answer_for_user;请仅做合并、润色与一致性检查,勿编造与工具矛盾的事实。"
)
return "\n".join(lines)
return f"[{res.specialist}/{res.step_id}] {res.output_text}"
@dataclass(frozen=True)
class SpecialistResult:
step_id: str
specialist: str
success: bool
output_text: str
latency_ms: int
metadata: dict[str, Any] = field(default_factory=dict)
delivery: SpecialistDelivery | None = None
@dataclass(frozen=True)
class FinalDecision:
plan_id: str
summary: str
confidence: float
references: list[str] = field(default_factory=list)