103 lines
4.0 KiB
Python
103 lines
4.0 KiB
Python
"""核对已安装资源、显式配置和本地宿主;不会发起模型调用。"""
|
||
|
||
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(主())
|