github →

New request

#1907: refactor(routes): split 8584-line api/routes.py into per-domain modules

We'll provision a sandbox, run an agent against the issue, and open a draft PR. You can pull the branch and iterate from there.

Issue
enhancementcleanup

Summary

api/routes.py is 8,584 lines, 203 function definitions, dispatching every HTTP path through long if/elif chains. The file is the single biggest merge-conflict surface in the repo and exceeds the comfortable working set of any tool that loads files into a single buffer.

Numbers (v0.51.21)

$ wc -l api/routes.py
8584 api/routes.py

$ grep -c "^def " api/routes.py
203

The file contains the dispatch table for sessions, chat, files, cron, MCP, providers, profiles, kanban, oauth, onboarding, workspace, and approvals — concerns that have natural module boundaries and already have separate files for their implementation (api/streaming.py, api/profiles.py, api/kanban_bridge.py, api/onboarding.py, api/oauth.py, api/providers.py, etc.) but get wired up via routes.py.

Why it matters

  1. Merge conflicts — every contributor PR that adds an endpoint touches the same dispatch chain. Routine.
  2. Reading cost — agents and humans both pay full-file load cost for any handler change. The Claude/Opus/GPT load tax on this file alone is non-trivial when used as review context.
  3. Test isolation — handlers in the same module share the import surface; touching one route imports everything routes.py imports.
  4. Surfaces the real coupling — once split, cross-module imports become explicit and the actual coupling graph shows up.

Proposed shape

Split into api/routes/ package with one module per domain, plus a thin api/routes/__init__.py that aggregates the dispatch table:

api/routes/
  __init__.py            # main dispatch entry, imports all submodules, exposes handle_get/handle_post
  _common.py             # _check_csrf, j(), bad(), shared helpers
  sessions.py            # session CRUD, list, search, /retry, /undo
  chat.py                # /api/chat/start, /api/chat/cancel, /api/chat/stream
  files.py               # workspace file browser, upload, preview
  cron.py                # cron job CRUD, run, pause
  mcp.py                 # MCP server CRUD, tool list
  providers.py           # provider settings, credential edit
  profiles.py            # profile CRUD, switch
  kanban.py              # kanban routes (delegates to kanban_bridge)
  oauth.py               # oauth callback handlers
  onboarding.py          # wizard steps
  workspace.py           # workspace CRUD, list
  approvals.py           # /api/approval/*

Constraints:

  • _check_csrf and the small set of helpers that all handlers use stay in _common.py
  • Module-level imports must be stable to avoid cold-start regressions (the current giant file is import-heavy at module load — splitting may surface ordering issues)
  • All existing test paths continue to work — routes resolve to the same callables, no API contract change

Risk / scope

  • M2 architectural — no behavior change, all tests should continue to pass
  • ~5-10 PR sequence, one module per PR, each landable independently
  • First PR is the scaffolding (api/routes/__init__.py + _common.py + one moved domain like approvals.py to validate the pattern)
  • Test suite (4810 tests) is the safety net — any regression shows up as a route handler going missing

Reporter

Architecture review, May 8 2026 — flagged as the highest-leverage non-bug refactor: every contributor touches it, every agent reads it, every merge conflict involves it.

Labels

enhancement, architecture, refactor, M2

Assessmentadvisory
chore●● medium95% confidence

Splitting the monolithic 8,584-line api/routes.py into per-domain modules is a straight internal refactor to reduce conflicts and improve modularity.

Likely files
  • api/routes.py
  • api/routes/__init__.py
  • api/routes/sessions.py
  • api/routes/chat.py
  • api/routes/oauth.py
  • api/routes/profiles.py
  • api/routes/mcp.py
  • api/routes/workspace.py
  • api/routes/kanban.py
Create the request

This opens a fresh agent run and a draft PR for issue #1907.

Cancel