add interrupt detection, SSE event, and resume schemas

This commit is contained in:
CREDO23 2026-02-10 15:35:42 +02:00
parent c9542c8603
commit 9751918e41
3 changed files with 34 additions and 1 deletions

View file

@ -7,7 +7,7 @@ These schemas follow the assistant-ui ThreadHistoryAdapter pattern:
""" """
from datetime import datetime from datetime import datetime
from typing import Any from typing import Any, Literal
from uuid import UUID from uuid import UUID
from pydantic import BaseModel, ConfigDict, Field from pydantic import BaseModel, ConfigDict, Field
@ -193,6 +193,16 @@ class RegenerateRequest(BaseModel):
mentioned_surfsense_doc_ids: list[int] | None = None mentioned_surfsense_doc_ids: list[int] | None = None
class ResumeDecision(BaseModel):
type: Literal["approve", "edit", "reject"]
edited_action: dict[str, Any] | None = None
class ResumeRequest(BaseModel):
search_space_id: int
decisions: list[ResumeDecision]
# ============================================================================= # =============================================================================
# Public Chat Snapshot Schemas # Public Chat Snapshot Schemas
# ============================================================================= # =============================================================================

View file

@ -504,6 +504,18 @@ class VercelStreamingService:
}, },
) )
def format_interrupt_request(self, interrupt_value: dict[str, Any]) -> str:
"""Format an interrupt request for human-in-the-loop approval.
Args:
interrupt_value: The interrupt payload from HumanInTheLoopMiddleware
containing action_requests and review_configs.
Returns:
str: SSE formatted interrupt request data part
"""
return self.format_data("interrupt-request", interrupt_value)
# ========================================================================= # =========================================================================
# Error Part # Error Part
# ========================================================================= # =========================================================================

View file

@ -1175,6 +1175,17 @@ async def stream_new_chat(
if completion_event: if completion_event:
yield completion_event yield completion_event
# Check if the graph was interrupted (human-in-the-loop)
state = await agent.aget_state(config)
is_interrupted = state.tasks and any(task.interrupts for task in state.tasks)
if is_interrupted:
interrupt_value = state.tasks[0].interrupts[0].value
yield streaming_service.format_interrupt_request(interrupt_value)
yield streaming_service.format_finish_step()
yield streaming_service.format_finish()
yield streaming_service.format_done()
return
# Generate LLM title for new chats after first response # Generate LLM title for new chats after first response
# Check if this is the first assistant response by counting existing assistant messages # Check if this is the first assistant response by counting existing assistant messages
from sqlalchemy import func from sqlalchemy import func