muse-agent-example/工具/环境预检.py
zizi 367d01db21 W06 模型宿主、角色、预算与流式合同:模型宿主合同、角色策略冻结、预算预留结算与流式回合证据。
按 R2 串行阶段整理提交;包内文件为该阶段交付(含后续小增量),状态以工作包清单为准。
2026-09-10 19:25:41 +08:00

103 lines
4.0 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
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(主())