84 lines
2.8 KiB
Python
84 lines
2.8 KiB
Python
from __future__ import annotations
|
|
|
|
from .common import (
|
|
Any,
|
|
Check,
|
|
InstallerError,
|
|
Path,
|
|
Runner,
|
|
Which,
|
|
_load_json_object,
|
|
_project_root,
|
|
asdict,
|
|
shutil,
|
|
subprocess,
|
|
)
|
|
from .project import _venv_python_path, inspect_project
|
|
|
|
|
|
def doctor_project(
|
|
project_root: str | Path | None = None,
|
|
*,
|
|
runner: Runner = subprocess.run,
|
|
which: Which = shutil.which,
|
|
python_version: tuple[int, int, int] | None = None,
|
|
) -> dict[str, Any]:
|
|
root = _project_root(project_root)
|
|
inspection = inspect_project(root, which=which, python_version=python_version)
|
|
checks = [Check(**item) for item in inspection["checks"]]
|
|
|
|
config_path = root / "config.json"
|
|
if config_path.is_file():
|
|
try:
|
|
config = _load_json_object(config_path)
|
|
env_name = config.get("env")
|
|
config_ok = isinstance(env_name, str) and bool(env_name.strip())
|
|
detail = f"config env is {env_name!r}" if config_ok else "config.json has no non-empty env"
|
|
except InstallerError as error:
|
|
config_ok = False
|
|
detail = str(error)
|
|
else:
|
|
config_ok = False
|
|
detail = "config.json is missing; run prepare"
|
|
checks.append(Check("configured_env", config_ok, True, detail))
|
|
|
|
uv_bin = which("uv")
|
|
if uv_bin:
|
|
commands = (
|
|
[uv_bin, "lock", "--check"],
|
|
[
|
|
str(_venv_python_path(root)),
|
|
"-c",
|
|
"import mcp; import nocobase_crm_mcp",
|
|
],
|
|
)
|
|
labels = ("lockfile", "python_environment")
|
|
for label, command in zip(labels, commands, strict=True):
|
|
try:
|
|
result = runner(command, cwd=str(root), capture_output=True, text=True, check=False)
|
|
ok = result.returncode == 0
|
|
detail = "passed" if ok else f"failed with exit code {result.returncode}"
|
|
except OSError as error:
|
|
ok = False
|
|
detail = str(error)
|
|
checks.append(Check(label, ok, True, detail))
|
|
else:
|
|
checks.extend(
|
|
[
|
|
Check("lockfile", False, True, "uv was not found on PATH"),
|
|
Check("python_environment", False, True, "uv was not found on PATH"),
|
|
]
|
|
)
|
|
|
|
return {
|
|
"ok": all(check.ok for check in checks if check.required),
|
|
"scope": "local-installation",
|
|
"projectRoot": str(root),
|
|
"checks": [asdict(check) for check in checks],
|
|
"remainingVerification": [
|
|
"Have the installation Agent verify the saved env through nb CLI's default redacted info output.",
|
|
"Register the generated stdio MCP configuration in the user's client.",
|
|
"Call the MCP tool crm_health and require ok=true.",
|
|
],
|
|
}
|