mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
202 lines
5.6 KiB
Python
202 lines
5.6 KiB
Python
"""
|
|
Stream Processing Routes
|
|
|
|
API endpoints for processing agent LLM streams through
|
|
transcription and extraction pipelines.
|
|
"""
|
|
|
|
from typing import Any
|
|
|
|
from fastapi import APIRouter, HTTPException, Request, status
|
|
|
|
from roboco.api.deps import CurrentAgentContext, CurrentAgentId, PermissionServiceDep
|
|
from roboco.api.schemas.stream import (
|
|
ExtractedMessageResponse,
|
|
ExtractionResponse,
|
|
ExtractRequest,
|
|
StreamChunkRequest,
|
|
StreamCompleteRequest,
|
|
TranscriptionStatsResponse,
|
|
)
|
|
from roboco.models import MessageType
|
|
from roboco.models.message import RawStream
|
|
|
|
router = APIRouter()
|
|
|
|
|
|
# =============================================================================
|
|
# STREAM PROCESSING ROUTES
|
|
# =============================================================================
|
|
|
|
|
|
@router.post("/chunk", status_code=status.HTTP_202_ACCEPTED)
|
|
async def process_chunk(
|
|
request: Request,
|
|
body: StreamChunkRequest,
|
|
agent_id: CurrentAgentId,
|
|
) -> dict[str, Any]:
|
|
"""
|
|
Process a raw LLM stream chunk.
|
|
|
|
Chunks are buffered until ready for extraction.
|
|
Returns buffer status.
|
|
"""
|
|
transcription = request.app.state.transcription
|
|
if not transcription:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="Transcription service not available",
|
|
)
|
|
|
|
# Create RawStream from request
|
|
raw_stream = RawStream(
|
|
agent_id=agent_id,
|
|
channel_id=body.channel_id,
|
|
connection_id=body.session_id, # Use session as connection
|
|
chunk=body.chunk,
|
|
)
|
|
|
|
# Process chunk
|
|
buffer = await transcription.process_chunk(raw_stream)
|
|
|
|
return {
|
|
"status": "buffered",
|
|
"ready_for_extraction": buffer is not None,
|
|
"buffer_size": buffer.char_count if buffer else 0,
|
|
}
|
|
|
|
|
|
@router.post("/complete", status_code=status.HTTP_200_OK)
|
|
async def complete_stream(
|
|
request: Request,
|
|
body: StreamCompleteRequest,
|
|
agent_id: CurrentAgentId,
|
|
) -> dict[str, Any]:
|
|
"""
|
|
Mark a stream as complete.
|
|
|
|
Returns the final buffer content for extraction.
|
|
"""
|
|
transcription = request.app.state.transcription
|
|
if not transcription:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="Transcription service not available",
|
|
)
|
|
|
|
buffer = await transcription.process_stream_complete(
|
|
agent_id=agent_id,
|
|
session_id=body.session_id,
|
|
)
|
|
|
|
if buffer:
|
|
content = await transcription.flush_buffer(agent_id, body.session_id)
|
|
return {
|
|
"status": "completed",
|
|
"content_length": len(content) if content else 0,
|
|
"content": content,
|
|
}
|
|
|
|
return {
|
|
"status": "no_content",
|
|
"content_length": 0,
|
|
"content": None,
|
|
}
|
|
|
|
|
|
@router.post("/extract", response_model=ExtractionResponse)
|
|
async def extract_messages(
|
|
request: Request,
|
|
body: ExtractRequest,
|
|
agent_id: CurrentAgentId,
|
|
) -> ExtractionResponse:
|
|
"""
|
|
Extract structured messages from raw content.
|
|
|
|
Returns list of extracted messages with their types.
|
|
"""
|
|
extraction = request.app.state.extraction
|
|
if not extraction:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="Extraction service not available",
|
|
)
|
|
|
|
result = await extraction.process_buffer(
|
|
content=body.content,
|
|
agent_id=agent_id,
|
|
channel_id=body.channel_id,
|
|
session_id=body.session_id,
|
|
group_id=body.group_id,
|
|
task_id=body.task_id,
|
|
)
|
|
|
|
return ExtractionResponse(
|
|
message_count=result.message_count,
|
|
messages=[
|
|
ExtractedMessageResponse(
|
|
id=msg.id,
|
|
type=msg.type.value if isinstance(msg.type, MessageType) else msg.type,
|
|
content=msg.content,
|
|
content_length=msg.content_length,
|
|
confidence=msg.confidence,
|
|
)
|
|
for msg in result.messages
|
|
],
|
|
types_extracted=[
|
|
t.value if isinstance(t, MessageType) else t for t in result.types_extracted
|
|
],
|
|
)
|
|
|
|
|
|
@router.get("/stats", response_model=TranscriptionStatsResponse)
|
|
async def get_transcription_stats(
|
|
request: Request,
|
|
) -> TranscriptionStatsResponse:
|
|
"""
|
|
Get transcription service statistics.
|
|
"""
|
|
transcription = request.app.state.transcription
|
|
if not transcription:
|
|
raise HTTPException(
|
|
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
detail="Transcription service not available",
|
|
)
|
|
|
|
stats = transcription.get_stats()
|
|
return TranscriptionStatsResponse(**stats)
|
|
|
|
|
|
# =============================================================================
|
|
# PERMISSION CHECK ROUTES
|
|
# =============================================================================
|
|
|
|
|
|
@router.get("/permissions")
|
|
async def get_my_permissions(
|
|
agent: CurrentAgentContext,
|
|
permissions: PermissionServiceDep,
|
|
) -> dict[str, Any]:
|
|
"""
|
|
Get permission summary for the current agent.
|
|
|
|
Returns accessible channels, allowed actions, etc.
|
|
"""
|
|
return permissions.check_all(agent)
|
|
|
|
|
|
@router.get("/permissions/channel/{channel_name}")
|
|
async def check_channel_permission(
|
|
channel_name: str,
|
|
agent: CurrentAgentContext,
|
|
permissions: PermissionServiceDep,
|
|
) -> dict[str, Any]:
|
|
"""
|
|
Check permissions for a specific channel.
|
|
"""
|
|
return {
|
|
"channel": channel_name,
|
|
"can_read": permissions.can_read_channel(agent, channel_name),
|
|
"can_write": permissions.can_write_channel(agent, channel_name),
|
|
}
|