* polish: streamline nav, extract inline styles, improve tablet UX - Restructure desktop nav from 8+ flat links + overflow dropdown into 5 grouped dropdowns (Core, Agents, Intel, System, More) matching the mobile menu structure to reduce decision fatigue - Extract all inline styles from mission_control.html and base.html notification elements into mission-control.css with semantic classes - Replace JS-built innerHTML with secure DOM construction in notification loader and chat history - Add CONNECTING state to connection indicator (amber) instead of showing OFFLINE before WebSocket connects - Add tablet breakpoint (1024px) with larger touch targets for Apple Pencil / stylus use and safe-area padding for iPad toolbar - Add active-link highlighting in desktop dropdown menus - Rename "Mission Control" page title to "System Overview" to disambiguate from the chat home page - Add "Home — Timmy Time" page title to index.html https://claude.ai/code/session_015uPUoKyYa8M2UAcyk5Gt6h * fix(security): move auth-gate credentials to environment variables Hardcoded username, password, and HMAC secret in auth-gate.py replaced with os.environ lookups. Startup now refuses to run if any variable is unset. Added AUTH_GATE_SECRET/USER/PASS to .env.example. https://claude.ai/code/session_015uPUoKyYa8M2UAcyk5Gt6h * refactor(tooling): migrate from black+isort+bandit to ruff Replace three separate linting/formatting tools with a single ruff invocation. Updates tox.ini (lint, format, pre-push, pre-commit envs), .pre-commit-config.yaml, and CI workflow. Fixes all ruff errors including unused imports, missing raise-from, and undefined names. Ruff config maps existing bandit skips to equivalent S-rules. https://claude.ai/code/session_015uPUoKyYa8M2UAcyk5Gt6h --------- Co-authored-by: Claude <noreply@anthropic.com>
52 lines
1.4 KiB
Python
52 lines
1.4 KiB
Python
"""Serve-mode CLI — run Timmy as an API service.
|
|
|
|
Usage:
|
|
timmy-serve start [--port 8402]
|
|
timmy-serve status
|
|
"""
|
|
|
|
import typer
|
|
|
|
app = typer.Typer(help="Timmy Serve — sovereign AI agent API")
|
|
|
|
|
|
@app.command()
|
|
def start(
|
|
port: int = typer.Option(8402, "--port", "-p", help="Port for the serve API"),
|
|
host: str = typer.Option("0.0.0.0", "--host", "-h", help="Host to bind to"),
|
|
price: int = typer.Option(100, "--price", help="Price per request in sats"),
|
|
dry_run: bool = typer.Option(False, "--dry-run", help="Print config and exit (for testing)"),
|
|
):
|
|
"""Start Timmy in serve mode."""
|
|
typer.echo(f"Starting Timmy Serve on {host}:{port}")
|
|
typer.echo(f"L402 payment proxy active — {price} sats per request")
|
|
typer.echo("Press Ctrl-C to stop")
|
|
|
|
typer.echo("\nEndpoints:")
|
|
typer.echo(" POST /serve/chat — Chat with Timmy")
|
|
typer.echo(" GET /serve/invoice — Request an invoice")
|
|
typer.echo(" GET /serve/status — Service status")
|
|
typer.echo(" GET /health — Health check")
|
|
|
|
if dry_run:
|
|
typer.echo("\n(Dry run mode - not starting server)")
|
|
return
|
|
|
|
import uvicorn
|
|
|
|
from timmy_serve.app import create_timmy_serve_app
|
|
|
|
serve_app = create_timmy_serve_app()
|
|
uvicorn.run(serve_app, host=host, port=port)
|
|
|
|
|
|
@app.command()
|
|
def status():
|
|
"""Show serve-mode status."""
|
|
typer.echo("Timmy Serve — Status")
|
|
typer.echo(" Service: active")
|
|
|
|
|
|
def main():
|
|
app()
|