feat: proxy nas live recorder controls

This commit is contained in:
kris
2026-03-23 09:21:15 +08:00
parent 1719047ef5
commit 96ab6af9ed

View File

@@ -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")