chore(repo): remove desktop app from core repo
This commit is contained in:
@@ -740,197 +740,6 @@ def gateway(
|
||||
_run_gateway(cfg, port=port)
|
||||
|
||||
|
||||
DESKTOP_BOOTSTRAP_PROVIDER = "openai_codex"
|
||||
DESKTOP_BOOTSTRAP_MODEL = "openai-codex/gpt-5.1-codex"
|
||||
|
||||
|
||||
def _desktop_provider_error_is_recoverable(error: ValueError) -> bool:
|
||||
message = str(error)
|
||||
return "No API key configured" in message or "requires api_key and api_base" in message
|
||||
|
||||
|
||||
def _desktop_provider_needs_bootstrap(config: Config) -> bool:
|
||||
from nanobot.providers.factory import make_provider
|
||||
|
||||
try:
|
||||
make_provider(config)
|
||||
return False
|
||||
except ValueError as e:
|
||||
if not _desktop_provider_error_is_recoverable(e):
|
||||
raise
|
||||
return True
|
||||
|
||||
|
||||
def _reset_desktop_config_to_unconfigured(config: Config) -> bool:
|
||||
defaults = config.agents.defaults
|
||||
changed = False
|
||||
if defaults.model_preset is not None:
|
||||
defaults.model_preset = None
|
||||
changed = True
|
||||
if defaults.provider:
|
||||
defaults.provider = ""
|
||||
changed = True
|
||||
if defaults.model:
|
||||
defaults.model = ""
|
||||
changed = True
|
||||
return changed
|
||||
|
||||
|
||||
def _is_persisted_desktop_bootstrap(config: Config) -> bool:
|
||||
defaults = config.agents.defaults
|
||||
return (
|
||||
defaults.model_preset is None
|
||||
and defaults.provider == DESKTOP_BOOTSTRAP_PROVIDER
|
||||
and defaults.model == DESKTOP_BOOTSTRAP_MODEL
|
||||
and not config.model_presets
|
||||
)
|
||||
|
||||
|
||||
def _apply_desktop_runtime_bootstrap(config: Config) -> None:
|
||||
defaults = config.agents.defaults
|
||||
config.agents.defaults.model_preset = None
|
||||
defaults.provider = DESKTOP_BOOTSTRAP_PROVIDER
|
||||
defaults.model = DESKTOP_BOOTSTRAP_MODEL
|
||||
|
||||
|
||||
def _load_or_create_desktop_config(config: str | None, workspace: str | None) -> Config:
|
||||
"""Load the desktop-owned config, creating it on first launch."""
|
||||
from nanobot.config.loader import (
|
||||
get_config_path,
|
||||
load_config,
|
||||
resolve_config_env_vars,
|
||||
save_config,
|
||||
set_config_path,
|
||||
)
|
||||
from nanobot.config.schema import Config as NanobotConfig
|
||||
|
||||
config_path = Path(config).expanduser().resolve() if config else get_config_path()
|
||||
set_config_path(config_path)
|
||||
changed = False
|
||||
if config_path.exists():
|
||||
try:
|
||||
loaded = resolve_config_env_vars(load_config(config_path))
|
||||
except ValueError as e:
|
||||
console.print(f"[red]Error: {e}[/red]")
|
||||
raise typer.Exit(1)
|
||||
else:
|
||||
loaded = NanobotConfig()
|
||||
changed = True
|
||||
|
||||
if workspace:
|
||||
workspace_path = Path(workspace).expanduser()
|
||||
loaded.agents.defaults.workspace = str(workspace_path)
|
||||
changed = True
|
||||
|
||||
if _is_persisted_desktop_bootstrap(loaded):
|
||||
changed = _reset_desktop_config_to_unconfigured(loaded) or changed
|
||||
elif _desktop_provider_needs_bootstrap(loaded):
|
||||
changed = _reset_desktop_config_to_unconfigured(loaded) or changed
|
||||
|
||||
if changed:
|
||||
save_config(loaded, config_path)
|
||||
|
||||
runtime_config = loaded.model_copy(deep=True)
|
||||
if _desktop_provider_needs_bootstrap(runtime_config):
|
||||
_apply_desktop_runtime_bootstrap(runtime_config)
|
||||
return runtime_config
|
||||
|
||||
|
||||
def _configure_desktop_gateway(
|
||||
config: Config,
|
||||
*,
|
||||
webui_port: int,
|
||||
webui_socket: str | None,
|
||||
token_issue_secret: str,
|
||||
) -> None:
|
||||
"""Force a local WebSocket-only gateway for the desktop app process."""
|
||||
config.gateway.host = "127.0.0.1"
|
||||
config.gateway.port = webui_port
|
||||
config.gateway.heartbeat.enabled = False
|
||||
|
||||
extras = dict(getattr(config.channels, "__pydantic_extra__", None) or {})
|
||||
for name, section in list(extras.items()):
|
||||
if name == "websocket":
|
||||
continue
|
||||
if isinstance(section, dict):
|
||||
extras[name] = {**section, "enabled": False}
|
||||
else:
|
||||
with suppress(Exception):
|
||||
setattr(section, "enabled", False)
|
||||
extras[name] = section
|
||||
|
||||
websocket_cfg = extras.get("websocket")
|
||||
if not isinstance(websocket_cfg, dict):
|
||||
websocket_cfg = {}
|
||||
websocket_cfg.update(
|
||||
{
|
||||
"enabled": True,
|
||||
"host": "127.0.0.1",
|
||||
"port": webui_port,
|
||||
"unix_socket_path": webui_socket or "",
|
||||
"path": "/",
|
||||
"token_issue_secret": token_issue_secret,
|
||||
"websocket_requires_token": True,
|
||||
"allow_from": ["*"],
|
||||
"streaming": True,
|
||||
}
|
||||
)
|
||||
extras["websocket"] = websocket_cfg
|
||||
config.channels.__pydantic_extra__ = extras
|
||||
|
||||
|
||||
@app.command("desktop-gateway", hidden=True)
|
||||
def desktop_gateway(
|
||||
webui_port: int = typer.Option(0, "--webui-port", min=0, max=65535),
|
||||
webui_socket: str | None = typer.Option(None, "--webui-socket", help="Unix socket path for desktop IPC"),
|
||||
token_issue_secret: str = typer.Option(..., "--token-issue-secret"),
|
||||
workspace: str | None = typer.Option(None, "--workspace", "-w", help="Desktop workspace directory"),
|
||||
config: str | None = typer.Option(None, "--config", "-c", help="Desktop config file"),
|
||||
verbose: bool = typer.Option(False, "--verbose", "-v", help="Verbose output"),
|
||||
):
|
||||
"""Start the private local gateway used by nanobot Desktop."""
|
||||
if not token_issue_secret.strip():
|
||||
console.print("[red]Error: --token-issue-secret is required[/red]")
|
||||
raise typer.Exit(1)
|
||||
if webui_port <= 0 and not (webui_socket or "").strip():
|
||||
console.print("[red]Error: --webui-port or --webui-socket is required[/red]")
|
||||
raise typer.Exit(1)
|
||||
if verbose:
|
||||
logger.remove(_log_handler_id)
|
||||
logger.add(
|
||||
sys.stderr,
|
||||
format=(
|
||||
"<green>{time:YYYY-MM-DD HH:mm:ss}</green> | "
|
||||
"<level>{level: <5}</level> | "
|
||||
"<cyan>{extra[channel]}</cyan> | "
|
||||
"<level>{message}</level>"
|
||||
),
|
||||
level="DEBUG",
|
||||
colorize=None,
|
||||
filter=lambda record: record["extra"].setdefault("channel", "-") or True,
|
||||
)
|
||||
cfg = _load_or_create_desktop_config(config, workspace)
|
||||
_configure_desktop_gateway(
|
||||
cfg,
|
||||
webui_port=webui_port,
|
||||
webui_socket=webui_socket,
|
||||
token_issue_secret=token_issue_secret,
|
||||
)
|
||||
_run_gateway(
|
||||
cfg,
|
||||
port=webui_port,
|
||||
webui_static_dist=False,
|
||||
webui_runtime_surface="native",
|
||||
webui_runtime_capabilities={
|
||||
"can_restart_engine": True,
|
||||
"can_pick_folder": True,
|
||||
"can_open_logs": True,
|
||||
"can_export_diagnostics": True,
|
||||
},
|
||||
health_server_enabled=False,
|
||||
)
|
||||
|
||||
|
||||
def _run_gateway(
|
||||
config: Config,
|
||||
*,
|
||||
|
||||
Reference in New Issue
Block a user