Kucatoo-Code · Wiki

Web UI & REST API

The Flask app serves the console pages and a JSON/SSE REST API. Page routes live in routes_pages.py; the query stream in routes_query.py; workspaces/usage in routes_workspaces.py; the file explorer in routes_files.py; guest tokens in guests.py (+ management routes in routes_status.py).

Pages

Path Handler Notes
/ index() (routes_pages.py:57) Renders templates/index.html. Injects cache-bust versions = file mtimes for css/js (routes_pages.py:35-54). API_TOKEN is injected into the page only when the request already presented a valid token; otherwise the page renders a token input and JS keeps it in localStorage (routes_pages.py:75-88). remote_mode (env KUCATOO_REMOTE=1) hides the :5001 supervisor controls.
/help help_page() (routes_pages.py:95) Static help: Direct/Agent, Tools, Memory, etc.
/vision vision_page() (routes_pages.py:103) Qwen text-to-image generation/editing.
/video video_page() (routes_pages.py:111) MiniMax-H3 text/image-to-video.
/wiki, /wiki/<slug> wiki_index() / wiki_page() (routes_pages.py:163-182) Renders docs/wiki/*.md server-side via markdown-it (commonmark + tables, raw HTML disabled); slugs must be alnum/-/_; the page list is built from each file's first # heading with INDEX sorted first. ```mermaid fences render client-side.
POST /api/theme api_theme() (routes_pages.py:186) Persist dark/light in the Flask session.

Main page layout (templates/index.html)

Header: theme/font-size controls, Direct vs Agent toggle, agent-mode selector (explore / plan / write_test / write_no_test; index.html:49-64), links to Vision/Video/Help/Wiki, temperature slider, API-token input (only when API_TOKEN is set), server Start/Stop/Restart (via the supervisor on :5001, hidden when remote), role + guest-quota badges.

Workspace bar (index.html:139-204): workspace dropdown + tree picker, New/Subdir buttons, collapsible stats panel, and the voice header control (status dot, connect button, STS model/voice/verbosity selects, timer, cost readout).

Main area is a 4-column grid (<main class="app-main">, index.html:209):

  1. Model column (app-col-models, index.html:212) — model list card, description, per-model prompt options.
  2. Prompt column (app-col-prompt, index.html:280) — prompt textarea, drop zone, voice wake chip + cheat-sheet popover, dictation panel.
  3. Response column (app-col-response, index.html:472) — streamed output, run stats, approval/question cards.
  4. Console column (app-col-console, index.html:576) — tabbed capability console (below).

Hidden auxiliary columns: voice-commands column (app-col-voice, index.html:262), tool/skill runner columns (toolRunCol/skillRunCol, index.html:984,995), and the trace-analysis aside (traceAnalysisPanel, index.html:1065).

Console tabs

data-tab buttons at index.html:579-588: Tools (enable for agent runs / run directly), Sites (registered sites, ports, dev→beta→prod staging), Memory (STM/MTM/LTM recall + remember), Skills (browse/execute), Files (workspace explorer), Usage (per-project costs, per-query drill-down), Audio (provider TTS/STT/STS settings, personas, cloning, spend), Status (harness health/cost + guest-token management), History (completed runs).

Query API + SSE event stream

POST /api/query (routes_query.py:212) — body fields: prompt (required), model, use_agent, agent_type (react/planner/reflective), tools, temperature, session_id, mode (explore/plan/write_test/write_no_test; invalid → explore; forced to explore when the active workspace is the app's own source tree, routes_query.py:230), auto_confirm, images (≤4 data-URLs, ≤10 MB total), context_files (≤20 workspace-relative text files, 200 KB total, 20 KB kept per file, routes_query.py:97-101), reasoning_effort, thinking, memory_recall, max_steps (default 60), max_time_sec (0 = unlimited).

Response: text/event-stream with SSE_HEADERS (Cache-Control: no-cache, X-Accel-Buffering: no, Connection: keep-alive, streaming.py:109). Wire format: data: {"event": <name>, "data": <payload>}\n\n (streaming.py:38-46).

SSE event types

Event Emitted when Payload
content Text delta (direct mode: token chunks; agent mode: output chunks) string
reasoning Thinking-model reasoning delta, real-time via queue pump (routes_query.py:725) string
memory_proposal A "remember …" intent short-circuits the model call (routes_query.py:605-616) {fact}
thought Agent step thought; only new suffixes re-emitted (routes_query.py:1046-1055) string
tool_call Agent ACTING transition, deduped per step+action (routes_query.py:1058-1065) {action, input}
step Agent step on status transitions only AgentStep dict
observation Tool result on the OBSERVING transition string
permission_request Confirmation-gated tool with auto_confirm off (routes_query.py:951) {request_id, action, detail}
question Agent ask_user (routes_query.py:970) {request_id, text, choices, multi}
cap_warning Time/step/token budget threshold crossed (routes_query.py:1081) {kind, pct, elapsed, budget, message}
error Stream failure string
done Terminal. Direct: {model_used, cost_usd, tokens{prompt,completion,total,cached}, elapsed, estimated} (routes_query.py:865). Agent adds {agent_type, tokens.context_prompt, plan_file, stop_reason, resumable, max_time_sec} (routes_query.py:1247) object

Related endpoints: POST /api/permissions/respond ({request_id, approved} or {request_id, answer}, routes_query.py:356); POST /api/agent/auto-approve flips auto_confirm_tools on a live run (404 when none, routes_query.py:380); POST /api/agent/instruct queues a mid-run instruction (routes_query.py:402); POST /api/agent/continue resumes a capped run from its persisted message history as a fresh SSE stream (routes_query.py:426). Plan-mode runs persist output to Plan-N.md in the workspace root (routes_query.py:71-89).

Workspaces + usage stats

A workspace is any subdirectory of the workspaces root (WORKSPACE_DIR env, else <parent of data dir>/workspace, routes_workspaces.py:57). Activation calls set_workspace_root() and persists to <DATA_DIR>/active_workspace.json (routes_workspaces.py:405).

Every finished query (direct, agent, or audio) appends one JSONL record to <DATA_DIR>/workspace_stats/<slug>.jsonl via record_workspace_stats() (routes_workspaces.py:112). Keys: workspace rel path, or project:<name> for a registered projects.json root (_usage_rel_for, routes_workspaces.py:83).

Files API (routes_files.py)

All paths are resolved inside the active workspace via resolve_path() — traversal is rejected (routes_files.py:43). .git, venv, .venv, __pycache__, node_modules, .kucatoo_backups are excluded from listings/zips/backups (routes_files.py:34).

Guest tokens

guests.py is a SQLite store at <DATA_DIR>/guests.db, one guest_tokens table, no ORM (guests.py:21-33). Tokens are 32-byte urlsafe random strings with primary-key exact lookup (no enumeration). Defaults (env-overridable): GUEST_DEFAULT_DAYS=2, GUEST_DEFAULT_QUERIES=10, GUEST_DEFAULT_TOKENS=50000 (guests.py:76-86). GUEST_MODELS (default deepseek-v4-flash,glm-5.2) is the guest model allowlist (guests.py:195).

Enforcement path:

Management (owner/token role, routes_status.py:156-184): GET /api/guests lists all tokens with computed expired flag; POST /api/guests mints one ({label, days, max_queries, max_tokens}) and returns the share link <host>/?token=<token>; POST /api/guests/<token>/revoke revokes (idempotent).

Full REST route table

The table below is generated by scripts/wiki_tables.py — do not hand-edit; re-run the script to refresh.

<!-- AUTO:routes -->

Route Methods
/ GET
/api/agent/auto-approve POST
/api/agent/continue POST
/api/agent/instruct POST
/api/agents GET
/api/analysis/ask POST
/api/analysis/log GET
/api/analysis/response POST
/api/analysis/save POST
/api/analysis/series POST
/api/audio/clone-voice POST
/api/audio/omni-voices GET
/api/audio/pricing GET
/api/audio/settings GET
/api/audio/settings POST
/api/audio/tts POST
/api/audio/voice-key GET
/api/audio/voice-session-end POST
/api/audio/voices GET
/api/audio/voices/<path:voice_id> DELETE
/api/auth/me GET
/api/auth/settings GET,POST
/api/billing/change POST
/api/billing/checkout POST
/api/billing/clients GET
/api/billing/manage GET
/api/billing/webhook POST
/api/domains GET
/api/domains/detect POST
/api/drive/backup POST
/api/drive/callback GET
/api/drive/connect GET
/api/drive/status GET
/api/eval/run POST
/api/eval/runs GET
/api/eval/suites GET
/api/feedback POST
/api/files/backup POST
/api/files/backups GET
/api/files/delete POST
/api/files/gitignore POST
/api/files/image GET
/api/files/list GET
/api/files/mkdir POST
/api/files/read GET
/api/files/restore POST
/api/files/upload POST
/api/files/write POST
/api/files/zip POST
/api/fly/apps GET
/api/fly/change-tier POST
/api/fly/destroy POST
/api/fly/provision POST
/api/fly/provision-status/<name> GET
/api/fly/sweep POST
/api/fly/terminate POST
/api/fly/terminate-undo POST
/api/guards GET
/api/guests GET,POST
/api/guests/<token>/revoke POST
/api/history GET
/api/hosting/hook POST
/api/job-runs GET
/api/job-runs/<execution_id> DELETE
/api/loop/balance GET
/api/loop/history GET
/api/loop/policy
/api/loop/policy GET
/api/loop/run POST
/api/loop/runs GET
/api/memory GET
/api/memory/candidates GET
/api/memory/commit POST
/api/memory/remember POST
/api/memory/stats GET
/api/models GET
/api/permissions/respond POST
/api/profile-loop/status GET
/api/profile-proposals GET
/api/profile-proposals/<name> GET
/api/profile-proposals/<name>/adopt POST
/api/profile-proposals/<name>/dismiss POST
/api/profile-proposals/<name>/estimate GET
/api/profile-proposals/<name>/evaluate POST
/api/projects GET
/api/projects/activate POST
/api/prompt/tighten POST
/api/query POST
/api/save/prompt POST
/api/save/response POST
/api/schedules GET
/api/schedules POST
/api/schedules/<sid>
/api/schedules/<sid> DELETE
/api/schedules/<sid>/run POST
/api/server/stop POST
/api/settings/domain DELETE
/api/settings/domain GET
/api/settings/domain POST
/api/settings/domain/verify POST
/api/settings/keys GET
/api/settings/keys POST
/api/settings/keys/<provider> DELETE
/api/settings/tiers
/api/settings/tiers GET
/api/sites GET
/api/sites/backup POST
/api/sites/log GET
/api/sites/promote POST
/api/sites/start POST
/api/sites/stop POST
/api/sites/tags GET
/api/sites/worktree POST
/api/skills GET
/api/skills/commit POST
/api/skills/examples GET
/api/skills/examples/reset POST
/api/skills/execute POST
/api/status GET
/api/storage/open/<kind> POST
/api/storage/paths GET
/api/stt/assist POST
/api/theme POST
/api/tools GET
/api/tools/examples GET
/api/tools/examples/reset POST
/api/tools/execute POST
/api/trace/analyze POST
/api/trace/ask POST
/api/trace/save POST
/api/trace/settings GET
/api/trace/settings POST
/api/trace/state GET
/api/traces GET
/api/video/enhance-prompt POST
/api/video/query POST
/api/video/regenerate POST
/api/vision/gallery GET
/api/vision/gallery/delete POST
/api/vision/gallery/download POST
/api/vision/query POST
/api/wiki/history GET
/api/wiki/history/<name> GET
/api/wiki/search GET
/api/workflows/approve POST
/api/workflows/definitions GET
/api/workflows/executions GET
/api/workspaces GET
/api/workspaces/activate POST
/api/workspaces/create POST
/api/workspaces/stats GET
/api/workspaces/tree GET
/api/workspaces/usage GET
/api/workspaces/usage/export GET
/audio/<path:filename> GET
/auth/callback GET
/auth/google GET
/auth/login GET
/auth/logout GET
/billing/return GET
/favicon.ico GET
/help GET
/images/<path:filename> GET
/jobs GET
/prompts/<path:filename> GET
/responses/<path:filename> GET
/settings GET
/video GET
/videos/<path:filename> GET
/vision GET
/wiki GET
/wiki/<slug> GET
<!-- /AUTO:routes -->

verified against code: 2026-08-09