将 Demo 录制收敛为三条独立链路,并重做联调台 UI。

移除 demo_orch 统一编排,改为 recording_demo 与 live/simulated 服务;客户端拆分为静态资源,以模式卡片与 chip 耗材覆盖三链路联调,并同步测试与文档。

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Kevin
2026-05-21 16:50:23 +08:00
parent 09885b4184
commit 153c91f8ff
16 changed files with 2030 additions and 1364 deletions

View File

@@ -1,7 +1,7 @@
"""FastAPI → 算法子进程调用链单元测试。
覆盖两条生产路径:
1. ``POST /internal/demo/video-batch-surgery`` → ``VideoBatchRunner`` → ``subprocess.run``reference bundle ``main.py``
1. ``POST /internal/demo/offline-batch`` → ``VideoBatchRunner`` → ``subprocess.run``reference bundle ``main.py``
2. ``POST /client/surgeries/start`` → ``CameraSessionManager`` → ``asyncio.create_subprocess_exec````python -m app.algorithm_runner``
"""
@@ -22,7 +22,7 @@ from httpx import ASGITransport, AsyncClient
from app.api import router as api_router
from app.config import Settings
from app.dependencies import build_container, get_surgery_pipeline, get_voice_terminal_hub
from app.routers import demo_orch
from app.routers import recording_demo
from app.services.video.session_manager import CameraSessionManager
from app.services.video_batch_runner import VideoBatchRunner, build_reference_command
from tests.test_video_batch_runner import _complete_result_tsv_body, _write_minimal_reference_bundle
@@ -65,7 +65,7 @@ def test_video_batch_endpoint_invokes_reference_bundle_subprocess(
reference_bundle: Path,
sqlite_session_factory,
) -> None:
monkeypatch.setattr(demo_orch.settings, "demo_orchestrator_enabled", True)
monkeypatch.setattr(recording_demo.settings, "demo_orchestrator_enabled", True)
monkeypatch.setattr(
"app.services.video_batch_runner.resolve_reference_bundle_dir",
lambda _override=None: reference_bundle.resolve(),
@@ -75,7 +75,7 @@ def test_video_batch_endpoint_invokes_reference_bundle_subprocess(
lambda _bundle: True,
)
monkeypatch.setattr(
demo_orch,
recording_demo,
"VideoBatchRunner",
lambda: VideoBatchRunner(
bundle_dir=reference_bundle,
@@ -89,14 +89,14 @@ def test_video_batch_endpoint_invokes_reference_bundle_subprocess(
_fake_reference_subprocess_run(captured),
)
container = build_container(demo_orch.settings, session_factory=sqlite_session_factory)
container = build_container(recording_demo.settings, session_factory=sqlite_session_factory)
app = FastAPI()
app.include_router(demo_orch.router)
app.include_router(recording_demo.router)
app.dependency_overrides[get_surgery_pipeline] = lambda: container.surgery_pipeline
client = TestClient(app)
res = client.post(
"/internal/demo/video-batch-surgery",
"/internal/demo/offline-batch",
data={
"surgery_id": "100001",
"candidate_consumables_json": '["耗材1"]',
@@ -198,7 +198,10 @@ async def test_start_surgery_endpoint_spawns_algorithm_runner_subprocess(
async def _noop_voice_assign(*args: Any, **kwargs: Any) -> None:
return None
monkeypatch.setattr("app.api.assign_voice_terminal_after_recording_started", _noop_voice_assign)
monkeypatch.setattr(
"app.services.recording_live.assign_voice_terminal_after_recording_started",
_noop_voice_assign,
)
app = FastAPI()
app.include_router(api_router)