153 lines
4.8 KiB
Python
153 lines
4.8 KiB
Python
from __future__ import annotations
|
|
|
|
import platform
|
|
import sys
|
|
from dataclasses import dataclass, field
|
|
from pathlib import Path
|
|
|
|
from .deferred_init import DeferredInitResult, run_deferred_init
|
|
from .prefetch import PrefetchResult, start_keychain_prefetch, start_mdm_raw_read, start_project_scan
|
|
from .release_notes import check_for_release_notes
|
|
|
|
|
|
MIN_PYTHON_VERSION: tuple[int, int] = (3, 10)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class RuntimeRequirementCheck:
|
|
name: str
|
|
ok: bool
|
|
detail: str
|
|
|
|
|
|
def check_runtime_requirements() -> tuple[RuntimeRequirementCheck, ...]:
|
|
checks: list[RuntimeRequirementCheck] = []
|
|
py_major, py_minor = sys.version_info[:2]
|
|
py_ok = (py_major, py_minor) >= MIN_PYTHON_VERSION
|
|
checks.append(RuntimeRequirementCheck(
|
|
name='python_version',
|
|
ok=py_ok,
|
|
detail=(
|
|
f'Python {py_major}.{py_minor} >= {MIN_PYTHON_VERSION[0]}.{MIN_PYTHON_VERSION[1]}'
|
|
if py_ok
|
|
else f'Python {py_major}.{py_minor} is below required '
|
|
f'{MIN_PYTHON_VERSION[0]}.{MIN_PYTHON_VERSION[1]}'
|
|
),
|
|
))
|
|
impl = platform.python_implementation()
|
|
checks.append(RuntimeRequirementCheck(
|
|
name='python_implementation',
|
|
ok=True,
|
|
detail=impl,
|
|
))
|
|
machine = platform.machine() or 'unknown'
|
|
system = platform.system() or 'unknown'
|
|
checks.append(RuntimeRequirementCheck(
|
|
name='platform',
|
|
ok=True,
|
|
detail=f'{system} on {machine}',
|
|
))
|
|
return tuple(checks)
|
|
|
|
|
|
def _read_package_version() -> str:
|
|
try:
|
|
from importlib.metadata import version
|
|
|
|
return version('claw-code-agent')
|
|
except Exception:
|
|
return '0.0.0'
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class WorkspaceSetup:
|
|
python_version: str
|
|
implementation: str
|
|
platform_name: str
|
|
test_command: str = 'python3 -m unittest discover -s tests -v'
|
|
|
|
def startup_steps(self) -> tuple[str, ...]:
|
|
return (
|
|
'start top-level prefetch side effects',
|
|
'build workspace context',
|
|
'load mirrored command snapshot',
|
|
'load mirrored tool snapshot',
|
|
'prepare parity audit hooks',
|
|
'apply trust-gated deferred init',
|
|
)
|
|
|
|
|
|
@dataclass(frozen=True)
|
|
class SetupReport:
|
|
setup: WorkspaceSetup
|
|
prefetches: tuple[PrefetchResult, ...]
|
|
deferred_init: DeferredInitResult
|
|
trusted: bool
|
|
cwd: Path
|
|
runtime_checks: tuple[RuntimeRequirementCheck, ...] = field(default_factory=tuple)
|
|
release_notes: tuple[str, ...] = field(default_factory=tuple)
|
|
|
|
def has_blocking_issues(self) -> bool:
|
|
return any(not check.ok for check in self.runtime_checks)
|
|
|
|
def as_markdown(self) -> str:
|
|
lines = [
|
|
'# Setup Report',
|
|
'',
|
|
f'- Python: {self.setup.python_version} ({self.setup.implementation})',
|
|
f'- Platform: {self.setup.platform_name}',
|
|
f'- Trusted mode: {self.trusted}',
|
|
f'- CWD: {self.cwd}',
|
|
'',
|
|
'Runtime checks:',
|
|
*(
|
|
f'- {check.name}: {"ok" if check.ok else "FAIL"} — {check.detail}'
|
|
for check in self.runtime_checks
|
|
),
|
|
'',
|
|
'Prefetches:',
|
|
*(f'- {prefetch.name}: {prefetch.detail}' for prefetch in self.prefetches),
|
|
'',
|
|
'Deferred init:',
|
|
*self.deferred_init.as_lines(),
|
|
]
|
|
if self.release_notes:
|
|
lines.extend(['', 'Release notes (newer than last seen):'])
|
|
lines.extend(f'- {note}' for note in self.release_notes)
|
|
return '\n'.join(lines)
|
|
|
|
|
|
def build_workspace_setup() -> WorkspaceSetup:
|
|
return WorkspaceSetup(
|
|
python_version='.'.join(str(part) for part in sys.version_info[:3]),
|
|
implementation=platform.python_implementation(),
|
|
platform_name=platform.platform(),
|
|
)
|
|
|
|
|
|
def run_setup(
|
|
cwd: Path | None = None,
|
|
trusted: bool = True,
|
|
last_seen_version: str | None = None,
|
|
) -> SetupReport:
|
|
root = cwd or Path(__file__).resolve().parent.parent
|
|
prefetches = [
|
|
start_mdm_raw_read(),
|
|
start_keychain_prefetch(),
|
|
start_project_scan(root),
|
|
]
|
|
release_notes_payload = check_for_release_notes(
|
|
current_version=_read_package_version(),
|
|
last_seen_version=last_seen_version,
|
|
cwd=root,
|
|
)
|
|
return SetupReport(
|
|
setup=build_workspace_setup(),
|
|
prefetches=tuple(prefetches),
|
|
deferred_init=run_deferred_init(trusted=trusted),
|
|
trusted=trusted,
|
|
cwd=root,
|
|
runtime_checks=check_runtime_requirements(),
|
|
release_notes=tuple(release_notes_payload['releaseNotes']),
|
|
)
|