11from sqlalchemy .orm import Session
2+ from typing import AsyncIterator
23
34from app .models .chat_message import ChatMessage
45from app .schemas .enums .sender_type import SenderType
56from app .models .chat_session import ChatSession
7+ from ag_ui .core import (
8+ RunAgentInput ,
9+ RunStartedEvent ,
10+ TextMessageStartEvent ,
11+ TextMessageContentEvent ,
12+ TextMessageEndEvent ,
13+ RunFinishedEvent ,
14+ MessagesSnapshotEvent ,
15+ AssistantMessage ,
16+ TextInputContent ,
17+ EventEncoder
18+ )
19+
620
721def assistant_reply (text : str ) -> str :
822 return f"Respuesta del asistente a: { text } "
@@ -45,4 +59,97 @@ def create_user_message(
4559 db .commit ()
4660 db .refresh (assistant_msg )
4761
48- return assistant_msg , session_id
62+ return assistant_msg , session_id
63+
64+
65+ async def process_agent_message (
66+ db : Session ,
67+ payload : RunAgentInput
68+ ) -> AsyncIterator [str ]:
69+ """Process agent message and generate AG-UI protocol events.
70+
71+ Args:
72+ db: Database session
73+ payload: RunAgentInput containing the user's message and context
74+
75+ Yields:
76+ AG-UI protocol events as encoded strings
77+ """
78+ encoder = EventEncoder ()
79+
80+ try :
81+ # Extract the user message from the messages list
82+ user_message_text = ""
83+ if payload .messages :
84+ last_message = payload .messages [- 1 ]
85+ if hasattr (last_message , 'content' ):
86+ if isinstance (last_message .content , list ) and len (last_message .content ) > 0 :
87+ user_message_text = last_message .content [0 ].text
88+ elif isinstance (last_message .content , str ):
89+ user_message_text = last_message .content
90+
91+ # Use thread_id as session_id (AG-UI uses thread_id for conversation tracking)
92+ session_id = payload .thread_id if hasattr (payload , 'thread_id' ) else None
93+
94+ # Emit RUN_STARTED event
95+ run_started = RunStartedEvent (
96+ run_id = payload .run_id ,
97+ thread_id = payload .thread_id
98+ )
99+ yield encoder .encode (run_started )
100+
101+ # Process the message through the service
102+ assistant_msg , session_id = create_user_message (
103+ db = db ,
104+ message = user_message_text ,
105+ session_id = session_id
106+ )
107+
108+ # Generate a unique message ID for the assistant response
109+ message_id = f"msg_{ payload .run_id } "
110+
111+ # Emit TEXT_MESSAGE_START event
112+ text_start = TextMessageStartEvent (
113+ run_id = payload .run_id ,
114+ message_id = message_id
115+ )
116+ yield encoder .encode (text_start )
117+
118+ # Emit TEXT_MESSAGE_CONTENT event with the assistant's response
119+ text_content = TextMessageContentEvent (
120+ run_id = payload .run_id ,
121+ message_id = message_id ,
122+ content = assistant_msg .message
123+ )
124+ yield encoder .encode (text_content )
125+
126+ # Emit TEXT_MESSAGE_END event
127+ text_end = TextMessageEndEvent (
128+ run_id = payload .run_id ,
129+ message_id = message_id
130+ )
131+ yield encoder .encode (text_end )
132+
133+ # Emit MESSAGES_SNAPSHOT event with the full conversation
134+ messages_snapshot = MessagesSnapshotEvent (
135+ run_id = payload .run_id ,
136+ messages = [
137+ * payload .messages , # Include previous messages
138+ AssistantMessage (
139+ id = message_id ,
140+ content = [TextInputContent (text = assistant_msg .message )]
141+ )
142+ ]
143+ )
144+ yield encoder .encode (messages_snapshot )
145+
146+ # Emit RUN_FINISHED event
147+ run_finished = RunFinishedEvent (
148+ run_id = payload .run_id
149+ )
150+ yield encoder .encode (run_finished )
151+
152+ except Exception as e :
153+ # In case of error, we should emit a RUN_ERROR event
154+ # For now, we'll just re-raise the exception
155+ raise
0 commit comments