Spaces:
Running
Running
| """会话持久化 API:/v1/xtc/sessions | |
| - POST /v1/xtc/sessions 创建会话 | |
| - GET /v1/xtc/sessions 列出我的会话 | |
| - GET /v1/xtc/sessions/{id} 获取会话详情 | |
| - PUT /v1/xtc/sessions/{id} 更新(标题) | |
| - DELETE /v1/xtc/sessions/{id} 删除 | |
| - POST /v1/xtc/sessions/{id}/messages 追加消息 | |
| - GET /v1/xtc/sessions/{id}/messages 列出消息 | |
| """ | |
| from __future__ import annotations | |
| from typing import Optional | |
| from fastapi import APIRouter, Body, Depends, Query, Request | |
| from ..auth import require_access_key | |
| from ..errors import HttpError | |
| from ..services import session_store | |
| from ._common import ok_with_cors | |
| router = APIRouter(prefix="/v1/xtc/sessions", tags=["sessions"]) | |
| async def create_session( | |
| body: dict = Body(default={}), | |
| access_key: str = Depends(require_access_key), | |
| ): | |
| sess = session_store.create_session( | |
| access_key=access_key, | |
| title=body.get("title"), | |
| provider=body.get("provider"), | |
| model=body.get("model"), | |
| ) | |
| return ok_with_cors({"session": sess}) | |
| async def list_sessions( | |
| access_key: str = Depends(require_access_key), | |
| limit: int = Query(default=50, ge=1, le=200), | |
| offset: int = Query(default=0, ge=0), | |
| ): | |
| items = session_store.list_sessions(access_key=access_key, limit=limit, offset=offset) | |
| return ok_with_cors({"items": items, "count": len(items)}) | |
| async def get_session( | |
| session_id: str, | |
| access_key: str = Depends(require_access_key), | |
| ): | |
| sess = session_store.get_session(session_id, access_key=access_key) | |
| if not sess: | |
| raise HttpError(f"session not found: {session_id}", status=404, code="not_found") | |
| return ok_with_cors({"session": sess}) | |
| async def update_session( | |
| session_id: str, | |
| body: dict = Body(default={}), | |
| access_key: str = Depends(require_access_key), | |
| ): | |
| sess = session_store.update_session( | |
| session_id, title=body.get("title"), access_key=access_key | |
| ) | |
| if not sess: | |
| raise HttpError(f"session not found: {session_id}", status=404, code="not_found") | |
| return ok_with_cors({"session": sess}) | |
| async def delete_session( | |
| session_id: str, | |
| access_key: str = Depends(require_access_key), | |
| ): | |
| ok = session_store.delete_session(session_id, access_key=access_key) | |
| if not ok: | |
| raise HttpError(f"session not found: {session_id}", status=404, code="not_found") | |
| return ok_with_cors({"deleted": True, "id": session_id}) | |
| async def append_message( | |
| session_id: str, | |
| body: dict = Body(default={}), | |
| access_key: str = Depends(require_access_key), | |
| ): | |
| if not session_store.get_session(session_id, access_key=access_key): | |
| raise HttpError(f"session not found: {session_id}", status=404, code="not_found") | |
| role = body.get("role") or "user" | |
| if role not in ("user", "assistant", "system"): | |
| raise HttpError("role must be user/assistant/system", status=400, code="bad_request") | |
| content = body.get("content") | |
| if content is None: | |
| raise HttpError("content is required", status=400, code="bad_request") | |
| msg = session_store.append_message( | |
| session_id=session_id, | |
| role=role, | |
| content=str(content), | |
| thought=body.get("thought"), | |
| provider=body.get("provider"), | |
| model=body.get("model"), | |
| file_keys=body.get("file_keys"), | |
| ) | |
| return ok_with_cors({"message": msg}) | |
| async def list_messages( | |
| session_id: str, | |
| access_key: str = Depends(require_access_key), | |
| ): | |
| if not session_store.get_session(session_id, access_key=access_key): | |
| raise HttpError(f"session not found: {session_id}", status=404, code="not_found") | |
| msgs = session_store.list_messages(session_id) | |
| return ok_with_cors({"messages": msgs or [], "count": len(msgs or [])}) | |