app.py python
62 lines 2.2 KB
Raw
sha256:8d7f41aafae41deee70035a92f93602ef1722a290153597451e5932af503a42c docs: queue board-identity follow-ups so they survive the session Human 59 minutes ago
1 """``overseer app`` command (§Q0.4)."""
2
3 from __future__ import annotations
4
5 import sys
6 import webbrowser
7 from argparse import Namespace
8 from pathlib import Path
9
10 from cli.context import CliContext
11 from cli.paths import PathEscapeError, resolve_repo_root
12 from tools.app.bind import DEFAULT_PORT, port_is_available, validate_bind_address
13 from tools.app.server import run_app_server
14
15
16 def _print_startup_banner(config_bind: str, port: int, session: str, csrf: str) -> None:
17 host = "127.0.0.1" if config_bind in {"127.0.0.1", "localhost"} else "[::1]"
18 url = f"http://{host}:{port}/"
19 print("ok app listening", file=sys.stderr)
20 print(f"url: {url}", file=sys.stderr)
21 print(f"session_credential: {session}", file=sys.stderr)
22 print(f"csrf_token: {csrf}", file=sys.stderr)
23
24
25 def run_app(args: Namespace, ctx: CliContext) -> int:
26 """Start the local loopback web UI."""
27 try:
28 repo_root = resolve_repo_root(cwd=ctx.cwd, repo_arg=args.repo, command="app")
29 except PathEscapeError:
30 ctx.output.error("refused: repo path outside allowed root")
31 return 4
32
33 if not (repo_root / ".overseer").is_dir():
34 ctx.output.error("not initialized — run ok init first")
35 return 2
36
37 bind = validate_bind_address(args.bind)
38 if bind is None:
39 ctx.output.error("refused: bind address must be loopback (127.0.0.1, localhost, or ::1)")
40 return 2
41
42 port = int(args.port)
43 if port < 1 or port > 65535:
44 ctx.output.error("refused: port must be between 1 and 65535")
45 return 2
46
47 if not port_is_available(bind, port):
48 ctx.output.error(f"refused: port {port} is already in use")
49 return 2
50
51 open_browser = bool(args.open)
52 captured: dict[str, str] = {}
53
54 def on_ready(config, _addr: str) -> None:
55 captured["session"] = config.session_credential
56 captured["csrf"] = config.csrf_token
57 _print_startup_banner(bind, port, config.session_credential, config.csrf_token)
58 if open_browser:
59 host = "127.0.0.1" if bind in {"127.0.0.1", "localhost"} else "[::1]"
60 webbrowser.open(f"http://{host}:{port}/")
61
62 return run_app_server(repo_root=repo_root, bind=bind, port=port, ctx=ctx, on_ready=on_ready)
File History 1 commit
sha256:8d7f41aafae41deee70035a92f93602ef1722a290153597451e5932af503a42c docs: queue board-identity follow-ups so they survive the session Human 59 minutes ago