agent-framework-devui 1.0.0b251007__py3-none-any.whl → 1.0.0b251016__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of agent-framework-devui might be problematic. Click here for more details.
- agent_framework_devui/_conversations.py +473 -0
- agent_framework_devui/_discovery.py +295 -325
- agent_framework_devui/_executor.py +99 -241
- agent_framework_devui/_mapper.py +281 -78
- agent_framework_devui/_server.py +232 -239
- agent_framework_devui/_utils.py +127 -0
- agent_framework_devui/models/__init__.py +15 -10
- agent_framework_devui/models/_discovery_models.py +1 -2
- agent_framework_devui/models/_openai_custom.py +45 -90
- agent_framework_devui/ui/assets/index-CE4pGoXh.css +1 -0
- agent_framework_devui/ui/assets/index-DmL7WSFa.js +577 -0
- agent_framework_devui/ui/index.html +2 -2
- agent_framework_devui-1.0.0b251016.dist-info/METADATA +286 -0
- agent_framework_devui-1.0.0b251016.dist-info/RECORD +23 -0
- agent_framework_devui/ui/assets/index-D0SfShuZ.js +0 -445
- agent_framework_devui/ui/assets/index-WsCIE0bH.css +0 -1
- agent_framework_devui-1.0.0b251007.dist-info/METADATA +0 -172
- agent_framework_devui-1.0.0b251007.dist-info/RECORD +0 -22
- {agent_framework_devui-1.0.0b251007.dist-info → agent_framework_devui-1.0.0b251016.dist-info}/WHEEL +0 -0
- {agent_framework_devui-1.0.0b251007.dist-info → agent_framework_devui-1.0.0b251016.dist-info}/entry_points.txt +0 -0
- {agent_framework_devui-1.0.0b251007.dist-info → agent_framework_devui-1.0.0b251016.dist-info}/licenses/LICENSE +0 -0
|
@@ -5,12 +5,12 @@
|
|
|
5
5
|
import json
|
|
6
6
|
import logging
|
|
7
7
|
import os
|
|
8
|
-
import uuid
|
|
9
8
|
from collections.abc import AsyncGenerator
|
|
10
|
-
from typing import Any
|
|
9
|
+
from typing import Any
|
|
11
10
|
|
|
12
|
-
from agent_framework import
|
|
11
|
+
from agent_framework import AgentProtocol
|
|
13
12
|
|
|
13
|
+
from ._conversations import ConversationStore, InMemoryConversationStore
|
|
14
14
|
from ._discovery import EntityDiscovery
|
|
15
15
|
from ._mapper import MessageMapper
|
|
16
16
|
from ._tracing import capture_traces
|
|
@@ -29,21 +29,26 @@ class EntityNotFoundError(Exception):
|
|
|
29
29
|
class AgentFrameworkExecutor:
|
|
30
30
|
"""Executor for Agent Framework entities - agents and workflows."""
|
|
31
31
|
|
|
32
|
-
def __init__(
|
|
32
|
+
def __init__(
|
|
33
|
+
self,
|
|
34
|
+
entity_discovery: EntityDiscovery,
|
|
35
|
+
message_mapper: MessageMapper,
|
|
36
|
+
conversation_store: ConversationStore | None = None,
|
|
37
|
+
):
|
|
33
38
|
"""Initialize Agent Framework executor.
|
|
34
39
|
|
|
35
40
|
Args:
|
|
36
41
|
entity_discovery: Entity discovery instance
|
|
37
42
|
message_mapper: Message mapper instance
|
|
43
|
+
conversation_store: Optional conversation store (defaults to in-memory)
|
|
38
44
|
"""
|
|
39
45
|
self.entity_discovery = entity_discovery
|
|
40
46
|
self.message_mapper = message_mapper
|
|
41
47
|
self._setup_tracing_provider()
|
|
42
48
|
self._setup_agent_framework_tracing()
|
|
43
49
|
|
|
44
|
-
#
|
|
45
|
-
self.
|
|
46
|
-
self.agent_threads: dict[str, list[str]] = {} # agent_id -> thread_ids
|
|
50
|
+
# Use provided conversation store or default to in-memory
|
|
51
|
+
self.conversation_store = conversation_store or InMemoryConversationStore()
|
|
47
52
|
|
|
48
53
|
def _setup_tracing_provider(self) -> None:
|
|
49
54
|
"""Set up our own TracerProvider so we can add processors."""
|
|
@@ -83,199 +88,6 @@ class AgentFrameworkExecutor:
|
|
|
83
88
|
else:
|
|
84
89
|
logger.debug("ENABLE_OTEL not set, skipping observability setup")
|
|
85
90
|
|
|
86
|
-
# Thread Management Methods
|
|
87
|
-
def create_thread(self, agent_id: str) -> str:
|
|
88
|
-
"""Create new thread for agent."""
|
|
89
|
-
thread_id = f"thread_{uuid.uuid4().hex[:8]}"
|
|
90
|
-
thread = AgentThread()
|
|
91
|
-
|
|
92
|
-
self.thread_storage[thread_id] = thread
|
|
93
|
-
|
|
94
|
-
if agent_id not in self.agent_threads:
|
|
95
|
-
self.agent_threads[agent_id] = []
|
|
96
|
-
self.agent_threads[agent_id].append(thread_id)
|
|
97
|
-
|
|
98
|
-
return thread_id
|
|
99
|
-
|
|
100
|
-
def get_thread(self, thread_id: str) -> AgentThread | None:
|
|
101
|
-
"""Get AgentThread by ID."""
|
|
102
|
-
return self.thread_storage.get(thread_id)
|
|
103
|
-
|
|
104
|
-
def list_threads_for_agent(self, agent_id: str) -> list[str]:
|
|
105
|
-
"""List thread IDs for agent."""
|
|
106
|
-
return self.agent_threads.get(agent_id, [])
|
|
107
|
-
|
|
108
|
-
def get_agent_for_thread(self, thread_id: str) -> str | None:
|
|
109
|
-
"""Find which agent owns this thread."""
|
|
110
|
-
for agent_id, thread_ids in self.agent_threads.items():
|
|
111
|
-
if thread_id in thread_ids:
|
|
112
|
-
return agent_id
|
|
113
|
-
return None
|
|
114
|
-
|
|
115
|
-
def delete_thread(self, thread_id: str) -> bool:
|
|
116
|
-
"""Delete thread."""
|
|
117
|
-
if thread_id not in self.thread_storage:
|
|
118
|
-
return False
|
|
119
|
-
|
|
120
|
-
for _agent_id, thread_ids in self.agent_threads.items():
|
|
121
|
-
if thread_id in thread_ids:
|
|
122
|
-
thread_ids.remove(thread_id)
|
|
123
|
-
break
|
|
124
|
-
|
|
125
|
-
del self.thread_storage[thread_id]
|
|
126
|
-
return True
|
|
127
|
-
|
|
128
|
-
async def get_thread_messages(self, thread_id: str) -> list[dict[str, Any]]:
|
|
129
|
-
"""Get messages from a thread's message store, preserving all content types for UI display."""
|
|
130
|
-
thread = self.get_thread(thread_id)
|
|
131
|
-
if not thread or not thread.message_store:
|
|
132
|
-
return []
|
|
133
|
-
|
|
134
|
-
try:
|
|
135
|
-
# Get AgentFramework ChatMessage objects from thread
|
|
136
|
-
af_messages = await thread.message_store.list_messages()
|
|
137
|
-
|
|
138
|
-
ui_messages = []
|
|
139
|
-
for i, af_msg in enumerate(af_messages):
|
|
140
|
-
# Extract role value (handle enum)
|
|
141
|
-
role = af_msg.role.value if hasattr(af_msg.role, "value") else str(af_msg.role)
|
|
142
|
-
|
|
143
|
-
# Skip tool/function messages - only show user and assistant messages
|
|
144
|
-
if role not in ["user", "assistant"]:
|
|
145
|
-
continue
|
|
146
|
-
|
|
147
|
-
# Extract all user-facing content (text, images, files, etc.)
|
|
148
|
-
display_contents = self._extract_display_contents(af_msg.contents)
|
|
149
|
-
|
|
150
|
-
# Skip messages with no displayable content
|
|
151
|
-
if not display_contents:
|
|
152
|
-
continue
|
|
153
|
-
|
|
154
|
-
# Extract usage information if present
|
|
155
|
-
usage_data = None
|
|
156
|
-
for content in af_msg.contents:
|
|
157
|
-
content_type = getattr(content, "type", None)
|
|
158
|
-
if content_type == "usage":
|
|
159
|
-
details = getattr(content, "details", None)
|
|
160
|
-
if details:
|
|
161
|
-
usage_data = {
|
|
162
|
-
"total_tokens": getattr(details, "total_token_count", 0) or 0,
|
|
163
|
-
"prompt_tokens": getattr(details, "input_token_count", 0) or 0,
|
|
164
|
-
"completion_tokens": getattr(details, "output_token_count", 0) or 0,
|
|
165
|
-
}
|
|
166
|
-
break
|
|
167
|
-
|
|
168
|
-
ui_message = {
|
|
169
|
-
"id": af_msg.message_id or f"restored-{i}",
|
|
170
|
-
"role": role,
|
|
171
|
-
"contents": display_contents,
|
|
172
|
-
"timestamp": __import__("datetime").datetime.now().isoformat(),
|
|
173
|
-
"author_name": af_msg.author_name,
|
|
174
|
-
"message_id": af_msg.message_id,
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
# Add usage data if available
|
|
178
|
-
if usage_data:
|
|
179
|
-
ui_message["usage"] = usage_data
|
|
180
|
-
|
|
181
|
-
ui_messages.append(ui_message)
|
|
182
|
-
|
|
183
|
-
logger.info(f"Restored {len(ui_messages)} display messages for thread {thread_id}")
|
|
184
|
-
return ui_messages
|
|
185
|
-
|
|
186
|
-
except Exception as e:
|
|
187
|
-
logger.error(f"Error getting thread messages: {e}")
|
|
188
|
-
import traceback
|
|
189
|
-
|
|
190
|
-
logger.error(traceback.format_exc())
|
|
191
|
-
return []
|
|
192
|
-
|
|
193
|
-
def _extract_display_contents(self, contents: list[Any]) -> list[dict[str, Any]]:
|
|
194
|
-
"""Extract all user-facing content (text, images, files, etc.) from message contents.
|
|
195
|
-
|
|
196
|
-
Filters out internal mechanics like function calls/results while preserving
|
|
197
|
-
all content types that should be displayed in the UI.
|
|
198
|
-
"""
|
|
199
|
-
display_contents = []
|
|
200
|
-
|
|
201
|
-
for content in contents:
|
|
202
|
-
content_type = getattr(content, "type", None)
|
|
203
|
-
|
|
204
|
-
# Text content
|
|
205
|
-
if content_type == "text":
|
|
206
|
-
text = getattr(content, "text", "")
|
|
207
|
-
|
|
208
|
-
# Handle double-encoded JSON from user messages
|
|
209
|
-
if text.startswith('{"role":'):
|
|
210
|
-
try:
|
|
211
|
-
import json
|
|
212
|
-
|
|
213
|
-
parsed = json.loads(text)
|
|
214
|
-
if parsed.get("contents"):
|
|
215
|
-
for sub_content in parsed["contents"]:
|
|
216
|
-
if sub_content.get("type") == "text":
|
|
217
|
-
display_contents.append({"type": "text", "text": sub_content.get("text", "")})
|
|
218
|
-
except Exception:
|
|
219
|
-
display_contents.append({"type": "text", "text": text})
|
|
220
|
-
else:
|
|
221
|
-
display_contents.append({"type": "text", "text": text})
|
|
222
|
-
|
|
223
|
-
# Data content (images, files, PDFs, etc.)
|
|
224
|
-
elif content_type == "data":
|
|
225
|
-
display_contents.append({
|
|
226
|
-
"type": "data",
|
|
227
|
-
"uri": getattr(content, "uri", ""),
|
|
228
|
-
"media_type": getattr(content, "media_type", None),
|
|
229
|
-
})
|
|
230
|
-
|
|
231
|
-
# URI content (external links to images/files)
|
|
232
|
-
elif content_type == "uri":
|
|
233
|
-
display_contents.append({
|
|
234
|
-
"type": "uri",
|
|
235
|
-
"uri": getattr(content, "uri", ""),
|
|
236
|
-
"media_type": getattr(content, "media_type", None),
|
|
237
|
-
})
|
|
238
|
-
|
|
239
|
-
# Skip function_call, function_result, and other internal content types
|
|
240
|
-
|
|
241
|
-
return display_contents
|
|
242
|
-
|
|
243
|
-
async def serialize_thread(self, thread_id: str) -> dict[str, Any] | None:
|
|
244
|
-
"""Serialize thread state for persistence."""
|
|
245
|
-
thread = self.get_thread(thread_id)
|
|
246
|
-
if not thread:
|
|
247
|
-
return None
|
|
248
|
-
|
|
249
|
-
try:
|
|
250
|
-
# Use AgentThread's built-in serialization
|
|
251
|
-
serialized_state = await thread.serialize()
|
|
252
|
-
|
|
253
|
-
# Add our metadata
|
|
254
|
-
agent_id = self.get_agent_for_thread(thread_id)
|
|
255
|
-
serialized_state["metadata"] = {"agent_id": agent_id, "thread_id": thread_id}
|
|
256
|
-
|
|
257
|
-
return serialized_state
|
|
258
|
-
|
|
259
|
-
except Exception as e:
|
|
260
|
-
logger.error(f"Error serializing thread {thread_id}: {e}")
|
|
261
|
-
return None
|
|
262
|
-
|
|
263
|
-
async def deserialize_thread(self, thread_id: str, agent_id: str, serialized_state: dict[str, Any]) -> bool:
|
|
264
|
-
"""Deserialize thread state from persistence."""
|
|
265
|
-
try:
|
|
266
|
-
thread = await AgentThread.deserialize(serialized_state)
|
|
267
|
-
# Store the restored thread
|
|
268
|
-
self.thread_storage[thread_id] = thread
|
|
269
|
-
if agent_id not in self.agent_threads:
|
|
270
|
-
self.agent_threads[agent_id] = []
|
|
271
|
-
self.agent_threads[agent_id].append(thread_id)
|
|
272
|
-
|
|
273
|
-
return True
|
|
274
|
-
|
|
275
|
-
except Exception as e:
|
|
276
|
-
logger.error(f"Error deserializing thread {thread_id}: {e}")
|
|
277
|
-
return False
|
|
278
|
-
|
|
279
91
|
async def discover_entities(self) -> list[EntityInfo]:
|
|
280
92
|
"""Discover all available entities.
|
|
281
93
|
|
|
@@ -357,9 +169,11 @@ class AgentFrameworkExecutor:
|
|
|
357
169
|
Raw Agent Framework events and trace events
|
|
358
170
|
"""
|
|
359
171
|
try:
|
|
360
|
-
# Get entity info
|
|
172
|
+
# Get entity info
|
|
361
173
|
entity_info = self.get_entity_info(entity_id)
|
|
362
|
-
|
|
174
|
+
|
|
175
|
+
# Trigger lazy loading (will return from cache if already loaded)
|
|
176
|
+
entity_obj = await self.entity_discovery.load_entity(entity_id)
|
|
363
177
|
|
|
364
178
|
if not entity_obj:
|
|
365
179
|
raise EntityNotFoundError(f"Entity object for '{entity_id}' not found")
|
|
@@ -390,7 +204,7 @@ class AgentFrameworkExecutor:
|
|
|
390
204
|
yield {"type": "error", "message": str(e), "entity_id": entity_id}
|
|
391
205
|
|
|
392
206
|
async def _execute_agent(
|
|
393
|
-
self, agent:
|
|
207
|
+
self, agent: AgentProtocol, request: AgentFrameworkRequest, trace_collector: Any
|
|
394
208
|
) -> AsyncGenerator[Any, None]:
|
|
395
209
|
"""Execute Agent Framework agent with trace collection and optional thread support.
|
|
396
210
|
|
|
@@ -406,34 +220,51 @@ class AgentFrameworkExecutor:
|
|
|
406
220
|
# Convert input to proper ChatMessage or string
|
|
407
221
|
user_message = self._convert_input_to_chat_message(request.input)
|
|
408
222
|
|
|
409
|
-
# Get thread
|
|
223
|
+
# Get thread from conversation parameter (OpenAI standard!)
|
|
410
224
|
thread = None
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
thread = self.get_thread(
|
|
225
|
+
conversation_id = request.get_conversation_id()
|
|
226
|
+
if conversation_id:
|
|
227
|
+
thread = self.conversation_store.get_thread(conversation_id)
|
|
414
228
|
if thread:
|
|
415
|
-
logger.debug(f"Using existing
|
|
229
|
+
logger.debug(f"Using existing conversation: {conversation_id}")
|
|
416
230
|
else:
|
|
417
|
-
logger.warning(f"
|
|
231
|
+
logger.warning(f"Conversation {conversation_id} not found, proceeding without thread")
|
|
418
232
|
|
|
419
233
|
if isinstance(user_message, str):
|
|
420
234
|
logger.debug(f"Executing agent with text input: {user_message[:100]}...")
|
|
421
235
|
else:
|
|
422
236
|
logger.debug(f"Executing agent with multimodal ChatMessage: {type(user_message)}")
|
|
237
|
+
# Check if agent supports streaming
|
|
238
|
+
if hasattr(agent, "run_stream") and callable(agent.run_stream):
|
|
239
|
+
# Use Agent Framework's native streaming with optional thread
|
|
240
|
+
if thread:
|
|
241
|
+
async for update in agent.run_stream(user_message, thread=thread):
|
|
242
|
+
for trace_event in trace_collector.get_pending_events():
|
|
243
|
+
yield trace_event
|
|
423
244
|
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
245
|
+
yield update
|
|
246
|
+
else:
|
|
247
|
+
async for update in agent.run_stream(user_message):
|
|
248
|
+
for trace_event in trace_collector.get_pending_events():
|
|
249
|
+
yield trace_event
|
|
250
|
+
|
|
251
|
+
yield update
|
|
252
|
+
elif hasattr(agent, "run") and callable(agent.run):
|
|
253
|
+
# Non-streaming agent - use run() and yield complete response
|
|
254
|
+
logger.info("Agent lacks run_stream(), using run() method (non-streaming)")
|
|
255
|
+
if thread:
|
|
256
|
+
response = await agent.run(user_message, thread=thread)
|
|
257
|
+
else:
|
|
258
|
+
response = await agent.run(user_message)
|
|
429
259
|
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
for trace_event in trace_collector.get_pending_events():
|
|
434
|
-
yield trace_event
|
|
260
|
+
# Yield trace events before response
|
|
261
|
+
for trace_event in trace_collector.get_pending_events():
|
|
262
|
+
yield trace_event
|
|
435
263
|
|
|
436
|
-
|
|
264
|
+
# Yield the complete response (mapper will convert to streaming events)
|
|
265
|
+
yield response
|
|
266
|
+
else:
|
|
267
|
+
raise ValueError("Agent must implement either run() or run_stream() method")
|
|
437
268
|
|
|
438
269
|
except Exception as e:
|
|
439
270
|
logger.error(f"Error in agent execution: {e}")
|
|
@@ -455,8 +286,8 @@ class AgentFrameworkExecutor:
|
|
|
455
286
|
try:
|
|
456
287
|
# Get input data - prefer structured data from extra_body
|
|
457
288
|
input_data: str | list[Any] | dict[str, Any]
|
|
458
|
-
if request.extra_body and
|
|
459
|
-
input_data = request.extra_body.input_data
|
|
289
|
+
if request.extra_body and isinstance(request.extra_body, dict) and request.extra_body.get("input_data"):
|
|
290
|
+
input_data = request.extra_body.get("input_data") # type: ignore
|
|
460
291
|
logger.debug(f"Using structured input_data from extra_body: {type(input_data)}")
|
|
461
292
|
else:
|
|
462
293
|
input_data = request.input
|
|
@@ -483,6 +314,9 @@ class AgentFrameworkExecutor:
|
|
|
483
314
|
def _convert_input_to_chat_message(self, input_data: Any) -> Any:
|
|
484
315
|
"""Convert OpenAI Responses API input to Agent Framework ChatMessage or string.
|
|
485
316
|
|
|
317
|
+
Handles various input formats including text, images, files, and multimodal content.
|
|
318
|
+
Falls back to string extraction for simple cases.
|
|
319
|
+
|
|
486
320
|
Args:
|
|
487
321
|
input_data: OpenAI ResponseInputParam (List[ResponseInputItemParam])
|
|
488
322
|
|
|
@@ -512,6 +346,9 @@ class AgentFrameworkExecutor:
|
|
|
512
346
|
) -> Any:
|
|
513
347
|
"""Convert OpenAI ResponseInputParam to Agent Framework ChatMessage.
|
|
514
348
|
|
|
349
|
+
Processes text, images, files, and other content types from OpenAI format
|
|
350
|
+
to Agent Framework ChatMessage with appropriate content objects.
|
|
351
|
+
|
|
515
352
|
Args:
|
|
516
353
|
input_items: List of OpenAI ResponseInputItemParam objects (dicts or objects)
|
|
517
354
|
ChatMessage: ChatMessage class for creating chat messages
|
|
@@ -597,6 +434,40 @@ class AgentFrameworkExecutor:
|
|
|
597
434
|
elif file_url:
|
|
598
435
|
contents.append(DataContent(uri=file_url, media_type=media_type))
|
|
599
436
|
|
|
437
|
+
elif content_type == "function_approval_response":
|
|
438
|
+
# Handle function approval response (DevUI extension)
|
|
439
|
+
try:
|
|
440
|
+
from agent_framework import FunctionApprovalResponseContent, FunctionCallContent
|
|
441
|
+
|
|
442
|
+
request_id = content_item.get("request_id", "")
|
|
443
|
+
approved = content_item.get("approved", False)
|
|
444
|
+
function_call_data = content_item.get("function_call", {})
|
|
445
|
+
|
|
446
|
+
# Create FunctionCallContent from the function_call data
|
|
447
|
+
function_call = FunctionCallContent(
|
|
448
|
+
call_id=function_call_data.get("id", ""),
|
|
449
|
+
name=function_call_data.get("name", ""),
|
|
450
|
+
arguments=function_call_data.get("arguments", {}),
|
|
451
|
+
)
|
|
452
|
+
|
|
453
|
+
# Create FunctionApprovalResponseContent with correct signature
|
|
454
|
+
approval_response = FunctionApprovalResponseContent(
|
|
455
|
+
approved, # positional argument
|
|
456
|
+
id=request_id, # keyword argument 'id', NOT 'request_id'
|
|
457
|
+
function_call=function_call, # FunctionCallContent object
|
|
458
|
+
)
|
|
459
|
+
contents.append(approval_response)
|
|
460
|
+
logger.info(
|
|
461
|
+
f"Added FunctionApprovalResponseContent: id={request_id}, "
|
|
462
|
+
f"approved={approved}, call_id={function_call.call_id}"
|
|
463
|
+
)
|
|
464
|
+
except ImportError:
|
|
465
|
+
logger.warning(
|
|
466
|
+
"FunctionApprovalResponseContent not available in agent_framework"
|
|
467
|
+
)
|
|
468
|
+
except Exception as e:
|
|
469
|
+
logger.error(f"Failed to create FunctionApprovalResponseContent: {e}")
|
|
470
|
+
|
|
600
471
|
# Handle other OpenAI input item types as needed
|
|
601
472
|
# (tool calls, function results, etc.)
|
|
602
473
|
|
|
@@ -687,23 +558,6 @@ class AgentFrameworkExecutor:
|
|
|
687
558
|
|
|
688
559
|
return start_executor, message_types
|
|
689
560
|
|
|
690
|
-
def _select_primary_input_type(self, message_types: list[Any]) -> Any | None:
|
|
691
|
-
"""Choose the most user-friendly input type for workflow kick-off."""
|
|
692
|
-
if not message_types:
|
|
693
|
-
return None
|
|
694
|
-
|
|
695
|
-
preferred = (str, dict)
|
|
696
|
-
|
|
697
|
-
for candidate in preferred:
|
|
698
|
-
for message_type in message_types:
|
|
699
|
-
if message_type is candidate:
|
|
700
|
-
return candidate
|
|
701
|
-
origin = get_origin(message_type)
|
|
702
|
-
if origin is candidate:
|
|
703
|
-
return candidate
|
|
704
|
-
|
|
705
|
-
return message_types[0]
|
|
706
|
-
|
|
707
561
|
def _parse_structured_workflow_input(self, workflow: Any, input_data: dict[str, Any]) -> Any:
|
|
708
562
|
"""Parse structured input data for workflow execution.
|
|
709
563
|
|
|
@@ -728,7 +582,9 @@ class AgentFrameworkExecutor:
|
|
|
728
582
|
return input_data
|
|
729
583
|
|
|
730
584
|
# Get the first (primary) input type
|
|
731
|
-
|
|
585
|
+
from ._utils import select_primary_input_type
|
|
586
|
+
|
|
587
|
+
input_type = select_primary_input_type(message_types)
|
|
732
588
|
if input_type is None:
|
|
733
589
|
logger.debug("Could not select primary input type for workflow - using raw dict")
|
|
734
590
|
return input_data
|
|
@@ -764,7 +620,9 @@ class AgentFrameworkExecutor:
|
|
|
764
620
|
return raw_input
|
|
765
621
|
|
|
766
622
|
# Get the first (primary) input type
|
|
767
|
-
|
|
623
|
+
from ._utils import select_primary_input_type
|
|
624
|
+
|
|
625
|
+
input_type = select_primary_input_type(message_types)
|
|
768
626
|
if input_type is None:
|
|
769
627
|
logger.debug("Could not select primary input type for workflow - using raw string")
|
|
770
628
|
return raw_input
|