"""核对已安装资源、显式配置和本地宿主;不会发起模型调用。""" from __future__ import annotations import argparse import json import os import subprocess import tempfile from pathlib import Path from muse.共享.错误 import Muse错误, 配置错误 from muse.启动 import 构建 from muse.资源加载 import 核对资源, 读取能力目录 from muse.配置 import 读取配置 def 检查Pi(node: Path, cli: Path, 预期版本: str) -> dict: if not node.is_file() or not cli.is_file(): raise 配置错误("Node或Pi入口不存在;需要明确的本地可执行路径") 结果 = subprocess.run( [str(node), "--version"], capture_output=True, text=True, timeout=10, check=True ) node_version = 结果.stdout.strip().removeprefix("v") parts = tuple(int(v) for v in node_version.split(".")) if parts < (22, 19, 0): raise 配置错误("当前Pi需要Node至少22.19.0;不能使用shell默认旧版本") with tempfile.TemporaryDirectory(prefix="muse-pi-preflight-") as 临时: 环境 = { **os.environ, "PI_CODING_AGENT_DIR": 临时, "PI_OFFLINE": "1", "PI_TELEMETRY": "0", } 结果 = subprocess.run( [str(node), str(cli), "--version"], cwd=临时, env=环境, capture_output=True, text=True, timeout=15, check=True, ) 实际 = 结果.stdout.strip() if 实际 != 预期版本: raise 配置错误("Pi实际版本与显式要求不符") return {"node_version": node_version, "pi_version": 实际, "state": "version_verified"} def 主() -> int: 解析 = argparse.ArgumentParser(description="检查固定资源和明确选择的运行依赖,不调用模型") 解析.add_argument("--配置", type=Path) 解析.add_argument("--数据库", action="store_true", help="明确执行所给配置的数据库连接检查") 解析.add_argument("--node", type=Path) 解析.add_argument("--pi", type=Path) 解析.add_argument("--pi-version") 参数 = 解析.parse_args() if 参数.数据库 and 参数.配置 is None: 解析.error("数据库检查需要明确配置") if any((参数.node, 参数.pi, 参数.pi_version)) and not all( (参数.node, 参数.pi, 参数.pi_version) ): 解析.error("Pi检查必须同时给出node、pi和pi-version") try: 清单 = 核对资源() 能力 = 读取能力目录() 报告 = { "resource_build_id": 清单["构建身份"], "resource_label": 清单["发布身份"], "package_version": 清单["代码版本"], "resources_verified": len(清单["资源"]), "roles": sorted(能力["role"]), "operations": sorted(能力["operation"]), "database": "not_checked", "host": {"state": "not_checked"}, "model_calls": 0, } if 参数.配置: 配置 = 读取配置(参数.配置) if 配置.资源发布身份 != 清单["构建身份"]: raise 配置错误("配置必须固定当前资源构建身份;先无配置运行预检取得身份") if 参数.数据库: 构建(配置).要求数据库().检查连接() 报告["database"] = "connection_verified" if 参数.node: 报告["host"] = 检查Pi(参数.node.resolve(), 参数.pi.resolve(), 参数.pi_version) print(json.dumps(报告, ensure_ascii=False, indent=2)) return 0 except Muse错误 as exc: print(json.dumps(exc.呈现(), ensure_ascii=False)) except (OSError, ValueError, KeyError, subprocess.SubprocessError): print( json.dumps( {"code": "PREFLIGHT_FAILED", "message": "资源或宿主检查失败,未验证项目不计通过"}, ensure_ascii=False, ) ) return 1 if __name__ == "__main__": raise SystemExit(主())