diff --git a/collector-service/app/core_main.py b/collector-service/app/core_main.py index c18e31a..341eab6 100644 --- a/collector-service/app/core_main.py +++ b/collector-service/app/core_main.py @@ -51,6 +51,7 @@ ORCHESTRATOR_SHARED_SECRET = os.getenv("ORCHESTRATOR_SHARED_SECRET", "") CUTVIDEO_BASE_URL = os.getenv("CUTVIDEO_BASE_URL", "http://192.168.31.18:7860") CUTVIDEO_API_KEY = os.getenv("CUTVIDEO_API_KEY", "") HUOBAO_BASE_URL = os.getenv("HUOBAO_BASE_URL", "http://127.0.0.1:5678") +LIVE_RECORDER_BASE_URL = os.getenv("LIVE_RECORDER_BASE_URL", "http://192.168.31.188:19106") CUTVIDEO_BASE_CONFIG = os.getenv("CUTVIDEO_BASE_CONFIG", "example.job.yaml") CUTVIDEO_POLL_INTERVAL_SEC = int(os.getenv("CUTVIDEO_POLL_INTERVAL_SEC", "10")) CUTVIDEO_MAX_WAIT_SEC = int(os.getenv("CUTVIDEO_MAX_WAIT_SEC", "1800")) @@ -279,6 +280,15 @@ class ReviewUpdateRequest(BaseModel): highlights: str | None = None next_actions: str | None = None notes: str | None = None + + +class LiveRecorderImportRequest(BaseModel): + raw: str + + +class LiveRecorderEnabledRequest(BaseModel): + line_no: int + enabled: bool assistant_id: str | None = None @@ -1659,6 +1669,33 @@ def probe_http(url: str, path: str = "", timeout: float = 3.0) -> dict[str, Any] return tcp +def live_recorder_request(method: str, path: str, payload: dict[str, Any] | None = None, timeout: float = 20.0) -> Any: + if not LIVE_RECORDER_BASE_URL: + raise HTTPException(status_code=503, detail="LIVE_RECORDER_BASE_URL is not configured") + target_url = urljoin(LIVE_RECORDER_BASE_URL if LIVE_RECORDER_BASE_URL.endswith("/") else f"{LIVE_RECORDER_BASE_URL}/", path.lstrip("/")) + try: + response = httpx.request( + method=method.upper(), + url=target_url, + json=payload, + timeout=timeout, + follow_redirects=True, + ) + response.raise_for_status() + if "application/json" in (response.headers.get("content-type") or ""): + return response.json() + return {"ok": True, "text": response.text, "url": target_url} + except httpx.HTTPStatusError as exc: + detail: Any + try: + detail = exc.response.json() + except Exception: + detail = exc.response.text.strip() or f"http_{exc.response.status_code}" + raise HTTPException(status_code=exc.response.status_code, detail=detail) + except Exception as exc: + raise HTTPException(status_code=502, detail=f"live recorder request failed: {exc}") + + def local_model_public_base_url() -> str: if not LOCAL_OPENAI_BASE_URL: return "" @@ -1726,6 +1763,7 @@ def healthz() -> dict[str, Any]: "cutvideoBaseUrl": CUTVIDEO_BASE_URL, "cutvideoUploadTimeoutSec": CUTVIDEO_UPLOAD_TIMEOUT_SEC, "huobaoBaseUrl": HUOBAO_BASE_URL, + "liveRecorderBaseUrl": LIVE_RECORDER_BASE_URL, } @@ -1764,6 +1802,10 @@ def integrations_health(account: dict[str, Any] = Depends(require_approved)) -> "base_url": ASR_HTTP_BASE_URL, **probe_tcp(ASR_HTTP_BASE_URL), }, + "live_recorder": { + "base_url": LIVE_RECORDER_BASE_URL, + **probe_http(LIVE_RECORDER_BASE_URL, "/api/healthz"), + }, } @@ -1773,6 +1815,53 @@ def integrations_local_models(account: dict[str, Any] = Depends(require_approved return fetch_local_model_catalog() +@app.get("/v2/live-recorder/health") +def live_recorder_health(account: dict[str, Any] = Depends(require_approved)) -> dict[str, Any]: + _ = account + return live_recorder_request("GET", "/api/healthz", timeout=8.0) + + +@app.get("/v2/live-recorder/status") +def live_recorder_status(account: dict[str, Any] = Depends(require_approved)) -> Any: + _ = account + return live_recorder_request("GET", "/api/status-lite", timeout=8.0) + + +@app.post("/v2/live-recorder/url-config/import") +def live_recorder_import_urls( + request: LiveRecorderImportRequest, + account: dict[str, Any] = Depends(require_approved), +) -> Any: + _ = account + return live_recorder_request("POST", "/api/url-config/import", {"raw": request.raw}, timeout=20.0) + + +@app.post("/v2/live-recorder/url-config/set-enabled") +def live_recorder_set_enabled( + request: LiveRecorderEnabledRequest, + account: dict[str, Any] = Depends(require_approved), +) -> Any: + _ = account + return live_recorder_request( + "POST", + "/api/url-config/set-enabled", + {"line_no": request.line_no, "enabled": request.enabled}, + timeout=20.0, + ) + + +@app.post("/v2/live-recorder/recorder/start") +def live_recorder_start(account: dict[str, Any] = Depends(require_approved)) -> Any: + _ = account + return live_recorder_request("POST", "/api/recorder/start", timeout=30.0) + + +@app.post("/v2/live-recorder/recorder/stop") +def live_recorder_stop(account: dict[str, Any] = Depends(require_approved)) -> Any: + _ = account + return live_recorder_request("POST", "/api/recorder/stop", timeout=30.0) + + def seed_defaults() -> None: if not db.fetch_one("SELECT id FROM model_profiles WHERE is_default = 1 LIMIT 1"): profile_id = make_id("model")