基座(cad_mcp_frame): - 新增 RecvOneFrame: 以 '\n' 为消息边界分帧,去掉单次 recv(2048) 限制(上限 8MB); 用 select 短探测兼容不发 '\n' 的旧客户端;clientSocket 设 SO_RCVTIMEO 防卸载卡死 - JSON-RPC id 支持 string/number;无 id 的通知不回包 - isError 映射: 协议级错误保留顶层 error,工具执行错误转 result.isError=true - 响应补 '\n' 作为消息边界 Agent(新增 dwg_review 包): - mcp_client: 唯一 TCP/JSON-RPC 封装(单飞锁/分帧/重试/兼容 error 与 isError) - cad_tools: 从 tools/list 动态建表,含 15 个只读白名单 - phases: planning -> evidence -> review(受控只读取证子循环)-> report - annotator: 批注回写 AI_REVIEW 层,支持 dry-run 与撤销 - config: 配置全部走环境变量;Windows 下回退读注册表以读到新设的系统变量 其它: 新增 verify_mcp_frame.py 验证脚本;.gitignore 补 Python/AutoCAD 锁文件规则; ai.memory 记录架构决策与实测结论
40 lines
1.2 KiB
Python
40 lines
1.2 KiB
Python
"""阶段 1:全局规划。
|
|
|
|
收集图纸概览 + 识别图框,按阅读顺序排序,产出审查计划。
|
|
"""
|
|
|
|
from ..mcp_client import result_json
|
|
|
|
|
|
def _sort_frames(frames):
|
|
"""按阅读顺序排序:先上后下(max_y 降序)、再左后右(min_x 升序)。"""
|
|
|
|
def key(frame):
|
|
bbox = frame.get("bbox") or [0, 0, 0, 0]
|
|
return (-round(float(bbox[3]), 3), round(float(bbox[0]), 3))
|
|
|
|
return sorted(frames, key=key)
|
|
|
|
|
|
def plan(ctx):
|
|
"""返回 {drawing_info, layers, layouts, frames}。"""
|
|
drawing_info = result_json(ctx.tools.call("get_drawing_info", {}), {})
|
|
layers = result_json(ctx.tools.call("get_layers", {"count_entities": True}), {})
|
|
layouts = result_json(ctx.tools.call("get_layouts", {}), {})
|
|
|
|
frames_data = result_json(
|
|
ctx.tools.call("detect_drawing_frames", {"min_confidence": 0.3}), {}
|
|
)
|
|
frames = frames_data.get("items", []) if isinstance(frames_data, dict) else []
|
|
|
|
frames = _sort_frames(frames)
|
|
if ctx.max_frames > 0:
|
|
frames = frames[: ctx.max_frames]
|
|
|
|
return {
|
|
"drawing_info": drawing_info,
|
|
"layers": layers,
|
|
"layouts": layouts,
|
|
"frames": frames,
|
|
}
|