현재 작업 상태 저장
This commit is contained in:
parent
07cc67761e
commit
6bd91b0d5e
674 changed files with 8726 additions and 298 deletions
|
|
@ -221,9 +221,40 @@ def _is_local_origin(origin: str) -> bool:
|
|||
return host in {"localhost", "127.0.0.1", "::1"}
|
||||
|
||||
|
||||
def _frontend_origin_map() -> dict[str, str]:
|
||||
mapped: dict[str, str] = {}
|
||||
for api_host, frontend_origin in settings.frontend_origin_map.items():
|
||||
host = (api_host or "").strip().lower().rstrip(".")
|
||||
origin = _url_origin(frontend_origin)
|
||||
if host and origin:
|
||||
mapped[host] = origin
|
||||
return mapped
|
||||
|
||||
|
||||
def _dev_login_extra_origins() -> set[str]:
|
||||
return {
|
||||
origin
|
||||
for value in settings.auth_dev_login_extra_origins
|
||||
if (origin := _url_origin(value))
|
||||
}
|
||||
|
||||
|
||||
def _dev_login_extra_hosts() -> set[str]:
|
||||
return {
|
||||
host
|
||||
for origin in _dev_login_extra_origins()
|
||||
if (host := (urlsplit(origin).hostname or "").lower())
|
||||
}
|
||||
|
||||
|
||||
def _is_dev_login_allowed_origin(origin: str) -> bool:
|
||||
host = (urlsplit(origin).hostname or "").lower()
|
||||
return _is_local_origin(origin) or origin in _dev_login_extra_origins() or host in _dev_login_extra_hosts()
|
||||
|
||||
|
||||
def _configured_frontend_origins() -> list[str]:
|
||||
origins: list[str] = []
|
||||
for value in [settings.frontend_base_url, *settings.cors_origins]:
|
||||
for value in [settings.frontend_base_url, *settings.frontend_origin_map.values(), *settings.cors_origins]:
|
||||
origin = _url_origin(value)
|
||||
if origin and origin not in origins:
|
||||
origins.append(origin)
|
||||
|
|
@ -243,8 +274,8 @@ def _frontend_origin_for_request(request: Request | None = None) -> str:
|
|||
forwarded_host = request.headers.get("x-forwarded-host")
|
||||
host = (forwarded_host or request.headers.get("host") or "").split(",", 1)[0].strip()
|
||||
hostname = host.rsplit(":", 1)[0].lower() if host else ""
|
||||
if hostname == "api-vignette.chanpaca.net":
|
||||
return "https://vignette.chanpaca.net"
|
||||
if mapped_origin := _frontend_origin_map().get(hostname):
|
||||
return mapped_origin
|
||||
if hostname in {"localhost", "127.0.0.1", "::1"}:
|
||||
return fallback
|
||||
|
||||
|
|
@ -348,15 +379,24 @@ def _dev_login_available(request: Request) -> bool:
|
|||
if settings.environment != "dev" or not settings.auth_dev_login_enabled:
|
||||
return False
|
||||
|
||||
if _dev_login_extra_origins():
|
||||
return True
|
||||
|
||||
saw_browser_origin = False
|
||||
for header_name in ("origin", "referer"):
|
||||
origin = _url_origin(request.headers.get(header_name))
|
||||
if origin and not _is_local_origin(origin):
|
||||
return False
|
||||
if origin:
|
||||
saw_browser_origin = True
|
||||
if not _is_dev_login_allowed_origin(origin):
|
||||
return False
|
||||
|
||||
if not saw_browser_origin and _dev_login_extra_origins():
|
||||
return True
|
||||
|
||||
forwarded_host = request.headers.get("x-forwarded-host")
|
||||
host = (forwarded_host or request.headers.get("host") or "").split(",", 1)[0].strip()
|
||||
origin = _url_origin(f"http://{host}") if host else None
|
||||
return bool(origin and _is_local_origin(origin))
|
||||
return bool(origin and _is_dev_login_allowed_origin(origin))
|
||||
|
||||
|
||||
@router.get("/config", response_model=AuthConfigResponse)
|
||||
|
|
|
|||
|
|
@ -381,8 +381,14 @@ async def _load_session_or_404(
|
|||
principal: Principal,
|
||||
*,
|
||||
allow_ended: bool = False,
|
||||
include_turn_evaluation: bool = False,
|
||||
) -> InProcSession:
|
||||
sess = await session_persistence.load_session(session_id, principal, allow_ended=True)
|
||||
sess = await session_persistence.load_session(
|
||||
session_id,
|
||||
principal,
|
||||
allow_ended=True,
|
||||
include_turn_evaluation=include_turn_evaluation,
|
||||
)
|
||||
if sess is not None:
|
||||
store.put(sess)
|
||||
elif runtime_fallback_allowed():
|
||||
|
|
@ -874,7 +880,11 @@ async def get_session_detail(
|
|||
) -> SessionDetailResponse:
|
||||
"""Return a learner-owned session with transcript for resume/history."""
|
||||
_ensure_learner(principal)
|
||||
sess = await _load_session_or_404(session_id, principal, allow_ended=True)
|
||||
sess = await _load_session_or_404(
|
||||
session_id,
|
||||
principal,
|
||||
allow_ended=True,
|
||||
)
|
||||
return _session_detail(sess, review_ready=await _review_ready(sess, principal))
|
||||
|
||||
|
||||
|
|
@ -951,7 +961,12 @@ async def get_session_review(
|
|||
) -> SessionReviewResponse:
|
||||
"""Return a learner-safe review built only from the stored session transcript."""
|
||||
_ensure_learner(principal)
|
||||
sess = await _load_session_or_404(session_id, principal, allow_ended=True)
|
||||
sess = await _load_session_or_404(
|
||||
session_id,
|
||||
principal,
|
||||
allow_ended=True,
|
||||
include_turn_evaluation=True,
|
||||
)
|
||||
visible_turns = _learner_visible_turns(sess)
|
||||
hidden_turns = len(visible_turns) != len(sess.turns)
|
||||
|
||||
|
|
|
|||
|
|
@ -49,11 +49,13 @@ _MAX_AUDIO_BYTES = 10 * 1024 * 1024
|
|||
async def voice_health() -> JSONResponse:
|
||||
"""Return voice service readiness."""
|
||||
available = voice_service.is_available()
|
||||
tts_provider = voice_service.tts_provider()
|
||||
body = {
|
||||
"status": "ok" if available else "degraded",
|
||||
"available": available,
|
||||
"stt_model": voice_svc.STT_MODEL,
|
||||
"tts_model": voice_svc.TTS_MODEL,
|
||||
"tts_provider": tts_provider,
|
||||
"reason": None if available else "OPENAI_API_KEY is not configured",
|
||||
}
|
||||
return JSONResponse(body, status_code=200 if available else 503)
|
||||
|
|
@ -108,6 +110,7 @@ async def voice_ws(websocket: WebSocket) -> None:
|
|||
"session_id": session_id,
|
||||
"voice": voice_preset.openai_voice,
|
||||
"preset": voice_preset.preset,
|
||||
"tts_provider": voice_service.tts_provider(),
|
||||
"state": "idle",
|
||||
**bind_meta,
|
||||
},
|
||||
|
|
@ -374,7 +377,12 @@ async def _run_turn_and_speak(
|
|||
# TTS speaking state comes before chunk metadata and binary audio.
|
||||
await _safe_send_json(
|
||||
websocket,
|
||||
{"type": "state", "state": "speaking", "voice": voice_preset.openai_voice},
|
||||
{
|
||||
"type": "state",
|
||||
"state": "speaking",
|
||||
"voice": voice_preset.openai_voice,
|
||||
"tts_provider": voice_service.tts_provider(),
|
||||
},
|
||||
)
|
||||
try:
|
||||
n = 0
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue