feat(cli): serve 新增 --no-ui 纯 API 模式

- --no-ui:不托管 Web UI 前端(根路径 404),仅 /api/v1/* REST 接口,
  且不自动打开浏览器——给 AI Agent / 程序化调用省去前端资源
- create_app/_create_app 新增 enable_ui 参数(默认 True 行为不变)
- 测试锁定:no-ui 模式无 web-ui Mount 且 API 路由完整;四道门禁全绿
  (ruff / ruff format / mypy / 1079 tests),实测根路径 404 + API 正常
This commit is contained in:
GitHub
2026-09-01 18:33:49 +08:00
parent 9d206c121b
commit ac4ac6b2aa
4 changed files with 42 additions and 5 deletions
+21
View File
@@ -556,3 +556,24 @@ def test_openapi_schema_generated():
# they are verified in test_full_app_routes_registered instead.
# Just ensure REST paths are present.
assert "/api/v1/fund-flow" in schema["paths"]
def test_create_app_no_ui_mode():
"""--no-ui 纯 API 模式:不挂载 Web UI 静态托管,API 路由完整。"""
pytest.importorskip("fastapi")
from easy_tdx.web import create_app
app = create_app(enable_ui=False)
# 无 web-ui 静态 MountFastAPI 0.141+ 顶层 Mount 不受 _IncludedRouter 影响)
mounts = [r for r in app.routes if type(r).__name__ == "Mount"]
assert all(getattr(m, "name", "") != "web-ui" for m in mounts)
# API 路由完整可用
paths = list(app.openapi()["paths"].keys())
assert any("/api/v1/security" in p for p in paths)
assert any("/api/v1/watchlist" in p for p in paths)
# 对照:默认模式挂载 web-ui(dist 存在时)
app_ui = create_app()
mounts_ui = [r for r in app_ui.routes if type(r).__name__ == "Mount"]
assert any(getattr(m, "name", "") == "web-ui" for m in mounts_ui)