nanobot/nanobot/api/runtime.py
Xubin Ren fe0717b385
feat(webui): add guided setup flows
* feat(channels): add guided setup flows

* test(channels): preserve setup config values

* fix(channels): reflect saved setup state

* refactor(channels): simplify setup state metadata

* fix(channels): harden setup lifecycle

* refactor(channels): centralize setup contracts

* fix(channels): route setup actions through webui shim

* fix(channels): adapt settings for compact screens

* fix(models): preserve default preset display

* feat(models): add curated Codex catalog

* fix(webui): stop attached gateway on interrupt

* fix(webui): simplify apps catalog

* docs(webui): clarify apps and runtime features

* feat(settings): add guided capability setup

* fix(webui): harden setup and managed services

* test: keep managed runtime checks portable

* test: scope POSIX runtime coverage

* fix(webui): simplify file settings

* feat(files): bundle document reading

* fix(webui): harden setup request boundaries

* fix(webui): prevent channel setup status squeeze

* fix(settings): group provider compatibility aliases

* refactor(settings): remove redundant setup surfaces

* fix(webui): harden guided setup lifecycle

* fix(webui): preserve channel setup compatibility
2026-07-13 13:11:46 +08:00

61 lines
1.7 KiB
Python

"""Background process control for the WebUI-managed OpenAI-compatible API."""
from __future__ import annotations
import hashlib
import sys
from dataclasses import dataclass
from pathlib import Path
from nanobot.process_runtime import (
ManagedProcessRuntime,
ProcessRuntimePaths,
ProcessStartOptions,
)
@dataclass(frozen=True)
class ApiStartOptions(ProcessStartOptions):
"""Options needed to start a managed ``nanobot serve`` process."""
host: str = "127.0.0.1"
def api_runtime_paths(config_path: Path) -> ProcessRuntimePaths:
"""Return isolated state and log paths for one API process."""
resolved = config_path.expanduser().resolve(strict=False)
suffix = hashlib.sha256(str(resolved).encode("utf-8")).hexdigest()[:16]
run_dir = resolved.parent / "run"
logs_dir = resolved.parent / "logs"
return ProcessRuntimePaths(
run_dir=run_dir,
logs_dir=logs_dir,
state_path=run_dir / f"api.{suffix}.json",
log_path=logs_dir / f"api.{suffix}.log",
)
class ApiRuntime(ManagedProcessRuntime):
"""Manage a WebUI-controlled OpenAI-compatible API process."""
service_name = "api"
def _build_child_command(self, options: ApiStartOptions) -> list[str]:
command = [
self.python_executable or sys.executable,
"-m",
"nanobot",
"serve",
"--host",
options.host,
"--port",
str(options.port),
]
if options.verbose:
command.append("--verbose")
if options.workspace:
command.extend(["--workspace", options.workspace])
if options.config_path:
command.extend(["--config", options.config_path])
return command