-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathagui.py
More file actions
150 lines (127 loc) · 4.58 KB
/
Copy pathagui.py
File metadata and controls
150 lines (127 loc) · 4.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import json
import logging
import uuid
from typing import Any, AsyncIterator, Dict, List
from ag_ui.core import (
Event,
Message,
RunAgentInput,
RunErrorEvent,
RunFinishedEvent,
RunStartedEvent,
TextMessageContentEvent,
TextMessageEndEvent,
TextMessageStartEvent,
ToolCallArgsEvent,
ToolCallEndEvent,
ToolCallResultEvent,
ToolCallStartEvent,
)
from agent_loop import Chunk
logger = logging.getLogger(__name__)
def to_openai_messages(messages: List[Message]) -> List[Dict[str, Any]]:
"""Convert AG-UI protocol messages to OpenAI-compatible message format."""
openai_messages = []
for msg in messages:
openai_msg: Dict[str, Any] = {
"role": msg.role,
"content": msg.content or "",
}
# Add optional name field if present
if hasattr(msg, "name") and msg.name:
openai_msg["name"] = msg.name
# Handle tool_calls for assistant messages
if hasattr(msg, "tool_calls") and msg.tool_calls:
openai_msg["tool_calls"] = [
{
"id": tool_call.id,
"type": tool_call.type,
"function": {
"name": tool_call.function.name,
"arguments": tool_call.function.arguments,
},
}
for tool_call in msg.tool_calls
]
# Handle tool_call_id for tool messages
if hasattr(msg, "tool_call_id") and msg.tool_call_id:
openai_msg["tool_call_id"] = msg.tool_call_id
openai_messages.append(openai_msg)
return openai_messages
async def stream_agui_events(
chunks: AsyncIterator[Chunk], run_agent_input: RunAgentInput
) -> AsyncIterator[Event]:
"""
Stream AG-UI protocol events from a stream of Chunk objects.
"""
yield RunStartedEvent(
thread_id=run_agent_input.thread_id,
run_id=run_agent_input.run_id,
parent_run_id=run_agent_input.parent_run_id,
input=run_agent_input,
)
msg_id = str(uuid.uuid4())
text_message_started = False
try:
async for chunk in chunks:
if chunk.type == "text" and chunk.content:
# Start text message if not already started
if not text_message_started:
yield TextMessageStartEvent(message_id=msg_id)
text_message_started = True
yield TextMessageContentEvent(
message_id=msg_id,
delta=chunk.content,
)
elif chunk.type == "tool_call" and chunk.tool_call:
# End any pending text message before tool call
if text_message_started:
yield TextMessageEndEvent(message_id=msg_id)
text_message_started = False
msg_id = str(uuid.uuid4())
tc = chunk.tool_call
yield ToolCallStartEvent(
tool_call_id=tc.tool_call_id,
tool_call_name=tc.tool_name,
)
yield ToolCallArgsEvent(
tool_call_id=tc.tool_call_id,
delta=json.dumps(tc.tool_arguments, ensure_ascii=False),
)
yield ToolCallEndEvent(
tool_call_id=tc.tool_call_id,
)
elif chunk.type == "tool_call_result":
yield ToolCallResultEvent(
message_id=str(uuid.uuid4()),
tool_call_id=chunk.tool_call.tool_call_id,
content=str(chunk.tool_result),
role="tool",
)
except Exception as e:
logger.warning(f"Error streaming AG-UI events: {e}", exc_info=True)
# End any pending text message
if text_message_started:
yield TextMessageEndEvent(message_id=msg_id)
yield RunErrorEvent(
message=f"Failed to stream events due to an unexpected error: {str(e)}",
code="error_in_agent_loop",
)
return
# End any pending text message
if text_message_started:
yield TextMessageEndEvent(message_id=msg_id)
yield RunFinishedEvent(
thread_id=run_agent_input.thread_id,
run_id=run_agent_input.run_id,
)
def to_sse_data(event: Event) -> str:
"""
Convert an AG-UI Event to Server-Sent Events (SSE) data format.
"""
data = event.model_dump(
mode="json",
exclude_none=True,
by_alias=True,
)
return f"data: {json.dumps(data, ensure_ascii=False)}\n\n"