Split out of #12945 so the delivered part has a closable scope. #12945 stays open for the package case.
Problem
BackendEndpointScanner.scan_all_endpoints() walks backend_dir / "api" only, but the router registries also mount routers from sibling packages. Six of them are plain module files:
services.advanced_workflow.routes -> /advanced-workflow
services.autoresearch.routes -> /autoresearch
services.workflow_automation.routes -> /workflow-automation
routers.code_completion -> /code-completion
routers.model_management -> /code-completion/model
routers.feedback -> /code-completion/feedback
None of their routes were discovered, so every frontend call to one was reported as targeting a missing endpoint.
The prefix must be carried explicitly
_parse_config_tuple_registry stores the full dotted path (_module_prefix_map["services.advanced_workflow.routes"]), but _scan_file resolves a file's prefix via _get_module_prefix(), which tries the path relative to project_root and then py_file.stem. For services/advanced_workflow/routes.py the stem is routes, which matches nothing — so simply feeding these files into the existing loop discovers the routes under /api instead of /api/advanced-workflow.
Scope
Module files only. Registry entries naming a package are excluded and tracked in #12945 — see that issue for why applying a package's prefix per-submodule is actively wrong.
Done when
- Routes from the six module-form registry entries are discovered under their registered prefixes.
- No increase in scanned paths absent from
app.openapi().
Split out of #12945 so the delivered part has a closable scope. #12945 stays open for the package case.
Problem
BackendEndpointScanner.scan_all_endpoints()walksbackend_dir / "api"only, but the router registries also mount routers from sibling packages. Six of them are plain module files:None of their routes were discovered, so every frontend call to one was reported as targeting a missing endpoint.
The prefix must be carried explicitly
_parse_config_tuple_registrystores the full dotted path (_module_prefix_map["services.advanced_workflow.routes"]), but_scan_fileresolves a file's prefix via_get_module_prefix(), which tries the path relative toproject_rootand thenpy_file.stem. Forservices/advanced_workflow/routes.pythe stem isroutes, which matches nothing — so simply feeding these files into the existing loop discovers the routes under/apiinstead of/api/advanced-workflow.Scope
Module files only. Registry entries naming a package are excluded and tracked in #12945 — see that issue for why applying a package's prefix per-submodule is actively wrong.
Done when
app.openapi().