from typing import List, Optional from fastapi import APIRouter, Depends, File, Form, Request, UploadFile, WebSocket from sqlmodel import Session from core.database import get_session from schemas.dashboard import ( CommandRequest, MessageFeedbackRequest, WorkspaceFileUpdateRequest, ) from api.dashboard_router_support import DashboardRouterDeps def build_dashboard_bot_io_router(*, deps: DashboardRouterDeps) -> APIRouter: router = APIRouter() @router.post("/api/bots/{bot_id}/command") def send_command(bot_id: str, payload: CommandRequest, request: Request, session: Session = Depends(get_session)): return deps.runtime_service.send_command_for_bot( app_state=request.app.state, session=session, bot_id=bot_id, payload=payload, ) @router.get("/api/bots/{bot_id}/messages") def list_bot_messages(bot_id: str, limit: int = 200, session: Session = Depends(get_session)): return deps.bot_message_service.list_messages(session=session, bot_id=bot_id, limit=limit) @router.get("/api/bots/{bot_id}/messages/page") def list_bot_messages_page(bot_id: str, limit: Optional[int] = None, before_id: Optional[int] = None, session: Session = Depends(get_session)): return deps.bot_message_service.list_messages_page( session=session, bot_id=bot_id, limit=limit, before_id=before_id, ) @router.get("/api/bots/{bot_id}/messages/by-date") def list_bot_messages_by_date( bot_id: str, date: str, tz_offset_minutes: Optional[int] = None, limit: Optional[int] = None, session: Session = Depends(get_session), ): return deps.bot_message_service.list_messages_by_date( session=session, bot_id=bot_id, date=date, tz_offset_minutes=tz_offset_minutes, limit=limit, ) @router.put("/api/bots/{bot_id}/messages/{message_id}/feedback") def update_bot_message_feedback(bot_id: str, message_id: int, payload: MessageFeedbackRequest, session: Session = Depends(get_session)): return deps.bot_message_service.update_feedback( session=session, bot_id=bot_id, message_id=message_id, feedback=payload.feedback, ) @router.delete("/api/bots/{bot_id}/messages") def clear_bot_messages(bot_id: str, request: Request, session: Session = Depends(get_session)): return deps.runtime_service.clear_messages_for_bot(app_state=request.app.state, session=session, bot_id=bot_id) @router.post("/api/bots/{bot_id}/sessions/dashboard-direct/clear") def clear_bot_dashboard_direct_session(bot_id: str, request: Request, session: Session = Depends(get_session)): return deps.runtime_service.clear_dashboard_direct_session_for_bot( app_state=request.app.state, session=session, bot_id=bot_id, ) @router.get("/api/bots/{bot_id}/logs") def get_bot_logs(bot_id: str, tail: int = 300, request: Request = None, session: Session = Depends(get_session)): return deps.runtime_service.get_logs_for_bot( app_state=request.app.state, session=session, bot_id=bot_id, tail=tail, ) @router.get("/api/bots/{bot_id}/workspace/tree") def get_workspace_tree(bot_id: str, path: Optional[str] = None, recursive: bool = False, request: Request = None, session: Session = Depends(get_session)): return deps.workspace_service.list_tree_for_bot( app_state=request.app.state, session=session, bot_id=bot_id, path=path, recursive=recursive, ) @router.get("/api/bots/{bot_id}/workspace/file") def read_workspace_file(bot_id: str, path: str, max_bytes: int = 200000, request: Request = None, session: Session = Depends(get_session)): return deps.workspace_service.read_file_for_bot( app_state=request.app.state, session=session, bot_id=bot_id, path=path, max_bytes=max_bytes, ) @router.put("/api/bots/{bot_id}/workspace/file") def update_workspace_file(bot_id: str, path: str, payload: WorkspaceFileUpdateRequest, request: Request = None, session: Session = Depends(get_session)): return deps.workspace_service.write_markdown_for_bot( app_state=request.app.state, session=session, bot_id=bot_id, path=path, content=str(payload.content or ""), ) @router.get("/api/bots/{bot_id}/workspace/download") def download_workspace_file(bot_id: str, path: str, download: bool = False, request: Request = None, session: Session = Depends(get_session)): return deps.workspace_service.serve_file_for_bot( app_state=request.app.state, session=session, bot_id=bot_id, path=path, download=download, request=request, public=False, redirect_html_to_raw=True, ) @router.get("/public/bots/{bot_id}/workspace/download") def public_download_workspace_file(bot_id: str, path: str, download: bool = False, request: Request = None, session: Session = Depends(get_session)): return deps.workspace_service.serve_file_for_bot( app_state=request.app.state, session=session, bot_id=bot_id, path=path, download=download, request=request, public=True, redirect_html_to_raw=True, ) @router.get("/api/bots/{bot_id}/workspace/raw/{path:path}") def raw_workspace_file(bot_id: str, path: str, download: bool = False, request: Request = None, session: Session = Depends(get_session)): return deps.workspace_service.serve_file_for_bot( app_state=request.app.state, session=session, bot_id=bot_id, path=path, download=download, request=request, public=False, redirect_html_to_raw=False, ) @router.get("/public/bots/{bot_id}/workspace/raw/{path:path}") def public_raw_workspace_file(bot_id: str, path: str, download: bool = False, request: Request = None, session: Session = Depends(get_session)): return deps.workspace_service.serve_file_for_bot( app_state=request.app.state, session=session, bot_id=bot_id, path=path, download=download, request=request, public=True, redirect_html_to_raw=False, ) @router.post("/api/bots/{bot_id}/workspace/upload") async def upload_workspace_files(bot_id: str, files: List[UploadFile] = File(...), path: Optional[str] = None, request: Request = None, session: Session = Depends(get_session)): return await deps.workspace_service.upload_files_for_bot( app_state=request.app.state, session=session, bot_id=bot_id, files=files, path=path, ) @router.post("/api/bots/{bot_id}/speech/transcribe") async def transcribe_bot_speech( bot_id: str, file: UploadFile = File(...), language: Optional[str] = Form(None), session: Session = Depends(get_session), ): return await deps.speech_transcription_service.transcribe( session=session, bot_id=bot_id, file=file, language=language, ) @router.websocket("/ws/monitor/{bot_id}") async def websocket_endpoint(websocket: WebSocket, bot_id: str): await deps.app_lifecycle_service.handle_websocket(websocket, bot_id) return router