Skip to content

What Changed

Choose a tag to compare

@chauncygu chauncygu released this 17 Apr 03:27
· 260 commits to main since this release
cf696e2
  • Apr 16, 2026 (v3.05.74): Web UI production hardening — persistence, multi-user auth, ops endpoints, JS module split, pytest suite

    • SQLite persistence (web/db.py, web/models.py) — SQLAlchemy-backed store with 4 tables: users, chat_sessions, messages, api_credentials. Sessions + message history now survive server restarts (previously in-memory only, lost on restart). DB file at ~/.cheetahclaws/web.db (0600). Config key CHEETAHCLAWS_WEB_DB overrides the path.
    • Multi-user auth (web/auth.py) — replaced single generated password with full accounts: bcrypt password hashing (passlib) + stateless JWT cookies (PyJWT, HS256, 7-day TTL). JWT signing secret persisted to ~/.cheetahclaws/web_secret (0600) so logins survive restarts. New endpoints: POST /api/auth/register (first user becomes admin), POST /api/auth/login, POST /api/auth/logout, GET /api/auth/whoami, GET /api/auth/bootstrap (first-run routing). Legacy POST /api/auth kept for the terminal password page.
    • Session CRUD — new PATCH /api/sessions/{id} to rename, DELETE /api/sessions/{id} to remove, GET /api/sessions/{id}/export to download conversation as Markdown. Auto-titling from first user message. Cross-user isolation enforced even on in-memory cache hits (one session hit patched after smoke test revealed the leak).
    • Structured JSON logging (web/logging_setup.py) — logging + custom JSON formatter emits one record per line to stderr, e.g. {"ts":..., "level":"info", "logger":"web.server", "msg":"req", "method":"POST", "path":"/api/auth/login", "status":200, "dur_ms":259, "user_id":1}. Every HTTP response auto-logs method/path/status/dur_ms/user_id/peer. Level controlled by CHEETAHCLAWS_LOG_LEVEL env (default INFO).
    • Ops endpointsGET /health returns {ok, db, uptime_s} (503 if DB unreachable); GET /metrics returns Prometheus v0.0.4 text with cheetahclaws_{uptime_seconds, requests_total, requests_4xx, requests_5xx, auth_logins_total, auth_logins_failed, auth_registrations_total, users_total, ws_connections_total}. Unauthenticated so Prometheus/k8s probes can hit them.
    • JS module split (web/static/js/) — monolithic 1813-line chat.html → 552 lines of HTML + 9 vanilla JS modules (chat.js core class, util.js, auth.js, sidebar.js, tools.js, approval.js, settings.js, welcome.js, init.js) loaded via plain <script src> tags. Prototype-mixin pattern (Object.assign(ChatApp.prototype, {...})) keeps app.foo() call sites unchanged. No bundler, no build step.
    • ETag + conditional caching — JS/CSS/HTML served with Cache-Control: no-cache, must-revalidate + weak ETag (mtime-size). Browser gets 304 when unchanged, fresh content after any edit. Binary assets keep 24h cache. Path traversal blocked by resolved-path is_relative_to check.
    • pytest suite (tests/test_web_api.py) — 21 end-to-end HTTP tests using httpx: bootstrap/register/login/whoami/logout, sessions CRUD + export + markdown, cross-user isolation, persistence after cache clear, /health, /metrics counter deltas, CORS preflight, auth gating of every endpoint. Spins the real server in a thread on a random port, DB truncated between tests. Runs in ~5s. pytest tests/test_web_api.py.
    • Sidebar UX — chat sessions now show title + relative time ("just now", "12m ago", "3d ago") + message count + busy dot. Search box filters by title/id on the client. Right-click (or long-press) gives a context menu: Rename / Export Markdown / Delete. Footer shows current username + Sign out link.
    • Register-or-login on first visit — chat UI now calls /api/auth/bootstrap on load; if no user exists it shows a "Create your first account" form (first registration becomes admin), otherwise the "Sign in" form. Username + password instead of a single server-generated password.
    • Theme: light default + system auto:root now carries the light palette; @media (prefers-color-scheme: dark) swaps in the dark palette when the user hasn't explicitly chosen a theme. Toggle button cycles system → light → dark → system, icon reflects the effective theme, title tooltip spells out the current mode. Inline pre-paint script in <head> sets data-theme before first paint to avoid FOUC.
    • Auto port selectioncheetahclaws --web (no --port) now tries 8080 first; on EADDRINUSE it binds :0 and lets the kernel pick a free port, banner reports the real URL. Explicit --port N binds exactly N or fails loudly (user intent preserved). --port argparse default changed from 8080None as a sentinel.
    • Favicon + MIME polishweb/static/favicon.{png,ico} cropped from docs/logo-5.png (leaping cheetah, transparent background, multi-size ICO 16/32/48). Served from root as /favicon.ico for browser defaults. MIME table extended with .ico (image/vnd.microsoft.icon), .svg, .jpg, .woff, .woff2.
    • Welcome dashboard rebalanced — old 5-card "Bridges & Media" row (ragged in 2×2 grid) split into two 4-card sections: Bridges (Telegram · WeChat · Slack · Monitor) and Multi-Modal Media (Voice Input · Vision · Copy Output · Export). /cwd added to Development Tools. Tagline changed to "Personal AI Assistant · Support Any Model · Autonomous 24/7".
    • Bridges commands in Chat UI/telegram, /wechat (+/weixin alias), /slack, /voice now registered in web/api.py's slash registry (previously only the terminal REPL had them), so clicking the dashboard cards actually runs the command.
    • New extraspip install 'cheetahclaws[web]' installs sqlalchemy>=2.0, passlib[bcrypt]>=1.7.4, PyJWT>=2.8.0. CLI-only installs remain dependency-free. [all] extra updated. Add web ui demos.
    • Version bumped to 3.05.74.
  • Apr 16, 2026 (v3.05.73): Web UI — browser-based Chat UI + structured event API

    • Web Chat UI (web/chat.html) — cheetahclaws --web now serves a rich browser-based chat interface at /chat alongside the existing PTY terminal at /. Features: real-time streaming via Server-Sent Events (SSE), collapsible tool cards with status badges, inline permission approval buttons (Allow/Deny), activity indicator (spinner + state labels for Thinking/Running/Processing), Markdown rendering with XSS sanitization (marked.js bundled), dark/light theme toggle with localStorage persistence, mobile-responsive layout with sidebar overlay.
    • Structured event API (web/api.py) — new ChatSession class bridges agent.run() generator to WebSocket/SSE event streams following the same pattern as the Telegram/Slack/WeChat bridges. Events: text_chunk, thinking_chunk, tool_start, tool_end, permission_request, permission_response, turn_done, command_result, interactive_menu, input_request, status, error. Event buffer with replay for late-joining subscribers.
    • 8 new API endpointsPOST /api/prompt (submit prompt or slash command), WS /api/events (real-time event stream), POST /api/approve (permission response), GET /api/sessions (list sessions), GET /api/sessions/{id} (session details + message history), GET/PATCH /api/config (read/write config), GET /api/models (list all 11 providers and models), POST /api/auth (login, sets HttpOnly cookie).
    • Settings panel — click ⚙ to open: model selector grouped by 11 providers (Anthropic, OpenAI, Gemini, Ollama, DeepSeek, Qwen, etc.), permission mode dropdown, thinking/verbose toggles, max tokens input, per-provider API key management with status indicators, quick action buttons (Compact/Status/Cost/Context), terminal link for fallback.
    • Slash command support in Chat UI — all 45+ commands work. Quick commands (/status, /help, /model, /context) return results instantly via POST response. Long-running commands (/brainstorm, /worker, /plan, /agent) stream events in real-time via SSE (server keeps HTTP connection open). /ssj renders a clickable 12-item interactive menu. /brainstorm (no args) shows a topic input box before starting.
    • SSJ sub-commands/ssj debate, /ssj commit, /ssj readme, /ssj scan, /ssj propose, /ssj review now run directly as agent queries without showing the interactive menu. The menu only appears for /ssj (no args).
    • Feature dashboard — welcome page shows 24 feature cards organized in 6 categories (Core, Agent Features, Session & Memory, Multi-Model, Development Tools, Bridges & Media) with 7 clickable quick-command chips.
    • Security hardeninghmac.compare_digest() for timing-safe token comparison, XSS sanitization (HTML tags escaped before Markdown rendering), CORS restricted to request Origin echo (no wildcard), HttpOnly + SameSite=Strict cookies, auth checked before WebSocket upgrade, _BufferedSocket wrapper replaces fragile sock.recv monkey-patching.
    • Session management — chat sessions with idle timeout (30 min), background reaper for orphaned sessions, session list in sidebar with message count and busy indicator, click to switch, "+" to create new.
    • Web bridge integrationRuntimeContext extended with web_input_event, web_input_value, in_web_turn fields. tools/interaction.py routes permission prompts to web bridge via threading.Event synchronization. commands/advanced.py detects web turns and skips interactive prompts (uses defaults like Telegram bridge).
    • Thread-safe stdout streaming_ThreadLocalStdout intercepts print() only from the target command thread, broadcasts as text_chunk events. Other threads unaffected.
    • pyproject.toml packagingweb package added to packages list, *.js, *.css, *.html added to package-data. Static assets (xterm.min.js, marked.min.js, chat.html) correctly included in pip install distributions.
    • Docs — new Web UI Guide (304 lines): quick start, full feature list, settings panel, API reference with JSON examples for all 8 endpoints and 12 event types, architecture notes, troubleshooting. README updated with Web UI section, feature table entry, CLI options, and examples.
    • Version bumped to 3.05.73.