4b6817381b
Benchmark image — build + push to ECR (any adapter) / build + push (push) Waiting to run
CI / quality (ubuntu-latest) (push) Waiting to run
CI / test (tools-runtime) (push) Waiting to run
CI / test (e2e-general) (push) Waiting to run
CI / test (cli-runtime) (push) Waiting to run
CI / test (e2e-provider-and-openclaw) (push) Waiting to run
CI / test (integrations-and-misc) (push) Waiting to run
CI / coverage-report (push) Blocked by required conditions
CI / test-kubernetes (push) Waiting to run
CI / should-run-thorough (push) Waiting to run
CI / test-thorough (cloudwatch-demo) (push) Blocked by required conditions
CI / test-thorough (flink-ecs) (push) Blocked by required conditions
CI / test-thorough (upstream-lambda) (push) Blocked by required conditions
CI / test-thorough (prefect-ecs-fargate) (push) Blocked by required conditions
CodeQL / Analyze (python) (push) Waiting to run
Release / build-binaries (zip, opensre.exe, onefile, windows-latest, windows-x64) (push) Blocked by required conditions
Release / publish-release (push) Blocked by required conditions
Release / publish-main-release (push) Blocked by required conditions
Release / prepare (push) Waiting to run
Release / verify (push) Blocked by required conditions
Release / build-python-dist (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, macos-15-intel, darwin-x64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, macos-latest, darwin-arm64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04, linux-x64) (push) Blocked by required conditions
Release / build-binaries (tar.gz, opensre, onedir, ubuntu-22.04-arm, linux-arm64) (push) Blocked by required conditions
Synthetic Deterministic Tests / Synthetic offline (deterministic) (push) Waiting to run
Interactive Shell Live (PR + post-merge) / turn-checks (no-LLM) (push) Waiting to run
Interactive Shell Live (PR + post-merge) / turn-live shard ${{ matrix.shard_index }} (push) Waiting to run
CI (OpenClaw E2E) / openclaw test (push) Has been cancelled
131 lines
3.7 KiB
Python
131 lines
3.7 KiB
Python
"""Root Click group: lazy command registration and Rich help rendering.
|
|
|
|
Kept separate from ``surfaces.cli.__main__`` so the entrypoint stays a thin
|
|
wiring module. Command modules are only imported on first access to keep CLI
|
|
startup (and especially the "just launch the shell" path) fast.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from collections.abc import Iterator, Mapping
|
|
from typing import Any, TypeVar, overload
|
|
|
|
import click
|
|
|
|
_GetDefault = TypeVar("_GetDefault")
|
|
|
|
|
|
class ThemeParamType(click.ParamType):
|
|
"""Validate theme names without importing terminal UI dependencies at startup."""
|
|
|
|
name = "theme"
|
|
|
|
def _choices(self) -> tuple[str, ...]:
|
|
from platform.terminal.theme import list_theme_names
|
|
|
|
return list_theme_names()
|
|
|
|
def convert(
|
|
self,
|
|
value: object,
|
|
param: click.Parameter | None,
|
|
ctx: click.Context | None,
|
|
) -> str:
|
|
normalized = str(value).strip().lower()
|
|
choices = self._choices()
|
|
if normalized in choices:
|
|
return normalized
|
|
return self.fail(
|
|
f"{value!r} is not one of: {', '.join(choices)}.",
|
|
param,
|
|
ctx,
|
|
)
|
|
|
|
|
|
class LazyCommandsDict(dict[str, click.Command]):
|
|
"""Click command mapping that loads the command tree on first read."""
|
|
|
|
def __init__(self, owner: LazyRichGroup, initial: Mapping[str, click.Command]) -> None:
|
|
super().__init__(initial)
|
|
self._owner = owner
|
|
|
|
def _ensure(self) -> None:
|
|
self._owner.ensure_commands_registered()
|
|
|
|
def __contains__(self, key: object) -> bool:
|
|
self._ensure()
|
|
return super().__contains__(key)
|
|
|
|
def __iter__(self) -> Iterator[str]:
|
|
self._ensure()
|
|
return super().__iter__()
|
|
|
|
def __len__(self) -> int:
|
|
self._ensure()
|
|
return super().__len__()
|
|
|
|
def __getitem__(self, key: str) -> click.Command:
|
|
self._ensure()
|
|
return super().__getitem__(key)
|
|
|
|
@overload
|
|
def get(self, key: str, default: None = None, /) -> click.Command | None:
|
|
pass
|
|
|
|
@overload
|
|
def get(self, key: str, default: click.Command, /) -> click.Command:
|
|
pass
|
|
|
|
@overload
|
|
def get(self, key: str, default: _GetDefault, /) -> click.Command | _GetDefault:
|
|
pass
|
|
|
|
def get(self, key: str, default: object = None, /) -> object:
|
|
self._ensure()
|
|
return super().get(key, default)
|
|
|
|
def keys(self) -> Any:
|
|
self._ensure()
|
|
return super().keys()
|
|
|
|
def values(self) -> Any:
|
|
self._ensure()
|
|
return super().values()
|
|
|
|
def items(self) -> Any:
|
|
self._ensure()
|
|
return super().items()
|
|
|
|
|
|
class LazyRichGroup(click.Group):
|
|
"""Root CLI group with lazy command registration and Rich help rendering."""
|
|
|
|
_commands_registered: bool
|
|
|
|
def __init__(self, *args: Any, **kwargs: Any) -> None:
|
|
super().__init__(*args, **kwargs)
|
|
self._commands_registered = False
|
|
self.commands = LazyCommandsDict(self, self.commands)
|
|
|
|
def ensure_commands_registered(self) -> None:
|
|
if self._commands_registered:
|
|
return
|
|
self._commands_registered = True
|
|
from surfaces.cli.commands import register_commands
|
|
|
|
register_commands(self)
|
|
|
|
def list_commands(self, ctx: click.Context) -> list[str]:
|
|
self.ensure_commands_registered()
|
|
return super().list_commands(ctx)
|
|
|
|
def get_command(self, ctx: click.Context, cmd_name: str) -> click.Command | None:
|
|
self.ensure_commands_registered()
|
|
return super().get_command(ctx, cmd_name)
|
|
|
|
def format_help(self, ctx: click.Context, _formatter: click.HelpFormatter) -> None:
|
|
assert isinstance(ctx.command, click.Group)
|
|
from surfaces.interactive_shell.ui.layout import render_help
|
|
|
|
render_help(ctx.command)
|