agent-framework-devui 1.0.0b251001__tar.gz → 1.0.0b251007__tar.gz
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-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/PKG-INFO +3 -3
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/README.md +1 -1
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/agent_framework_devui/_discovery.py +98 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/agent_framework_devui/_executor.py +88 -81
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/agent_framework_devui/_mapper.py +37 -61
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/agent_framework_devui/_server.py +62 -15
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/agent_framework_devui/_session.py +3 -3
- agent_framework_devui-1.0.0b251007/agent_framework_devui/_utils.py +421 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/agent_framework_devui/models/_discovery_models.py +7 -0
- agent_framework_devui-1.0.0b251007/agent_framework_devui/ui/agentframework.svg +33 -0
- agent_framework_devui-1.0.0b251007/agent_framework_devui/ui/assets/index-D0SfShuZ.js +445 -0
- agent_framework_devui-1.0.0b251007/agent_framework_devui/ui/assets/index-WsCIE0bH.css +1 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/agent_framework_devui/ui/index.html +3 -3
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/dev.md +23 -2
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/README.md +17 -5
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/index.html +1 -1
- agent_framework_devui-1.0.0b251007/frontend/public/agentframework.svg +33 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/App.tsx +200 -121
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/agent/agent-view.tsx +192 -82
- agent_framework_devui-1.0.0b251007/frontend/src/components/shared/agent-details-modal.tsx +219 -0
- agent_framework_devui-1.0.0b251007/frontend/src/components/shared/app-header.tsx +82 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/shared/debug-panel.tsx +21 -3
- agent_framework_devui-1.0.0b251007/frontend/src/components/shared/workflow-details-modal.tsx +168 -0
- agent_framework_devui-1.0.0b251007/frontend/src/components/ui/toast.tsx +89 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/workflow/workflow-input-form.tsx +235 -31
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/workflow/workflow-view.tsx +18 -89
- agent_framework_devui-1.0.0b251007/frontend/src/lib/utils.ts +6 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/services/api.ts +24 -9
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/types/index.ts +11 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/pyproject.toml +2 -2
- agent_framework_devui-1.0.0b251007/samples/weather_agent_azure/agent.py +133 -0
- agent_framework_devui-1.0.0b251007/samples/workflow_agents/__init__.py +7 -0
- agent_framework_devui-1.0.0b251007/samples/workflow_agents/workflow.py +167 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/tests/test_execution.py +64 -0
- agent_framework_devui-1.0.0b251007/tests/test_mapper.py +186 -0
- agent_framework_devui-1.0.0b251007/tests/test_schema_generation.py +137 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/tests/test_server.py +41 -0
- agent_framework_devui-1.0.0b251001/agent_framework_devui/ui/assets/index-D1AmQWga.css +0 -1
- agent_framework_devui-1.0.0b251001/agent_framework_devui/ui/assets/index-DPEaaIdK.js +0 -435
- agent_framework_devui-1.0.0b251001/frontend/src/components/shared/app-header.tsx +0 -54
- agent_framework_devui-1.0.0b251001/samples/weather_agent_azure/agent.py +0 -71
- agent_framework_devui-1.0.0b251001/tests/test_mapper.py +0 -419
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/.gitignore +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/LICENSE +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/agent_framework_devui/__init__.py +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/agent_framework_devui/_cli.py +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/agent_framework_devui/_tracing.py +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/agent_framework_devui/models/__init__.py +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/agent_framework_devui/models/_openai_custom.py +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/agent_framework_devui/ui/vite.svg +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/docs/devuiscreen.png +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/.gitignore +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/components.json +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/eslint.config.js +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/package.json +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/public/vite.svg +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/App.css +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/assets/react.svg +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/gallery/gallery-view.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/gallery/index.ts +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/message_renderer/ContentRenderer.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/message_renderer/MessageRenderer.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/message_renderer/StreamingRenderer.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/message_renderer/index.ts +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/message_renderer/types.ts +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/mode-toggle.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/shared/about-modal.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/shared/entity-selector.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/shared/settings-modal.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/theme-provider.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/ui/attachment-gallery.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/ui/badge.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/ui/button.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/ui/card.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/ui/checkbox.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/ui/dialog.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/ui/dropdown-menu.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/ui/file-upload.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/ui/input.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/ui/label.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/ui/loading-spinner.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/ui/loading-state.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/ui/scroll-area.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/ui/select.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/ui/tabs.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/ui/textarea.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/workflow/executor-node.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/components/workflow/workflow-flow.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/data/gallery/index.ts +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/data/gallery/sample-entities.ts +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/hooks/useWorkflowEventCorrelation.ts +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/index.css +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/main.tsx +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/types/agent-framework.ts +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/types/openai.ts +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/types/workflow.ts +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/utils/simple-layout.ts +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/utils/workflow-utils.ts +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/src/vite-env.d.ts +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/tsconfig.app.json +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/tsconfig.json +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/tsconfig.node.json +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/vite.config.ts +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/frontend/yarn.lock +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/samples/__init__.py +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/samples/fanout_workflow/__init__.py +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/samples/fanout_workflow/workflow.py +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/samples/foundry_agent/__init__.py +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/samples/foundry_agent/agent.py +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/samples/in_memory_mode.py +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/samples/spam_workflow/__init__.py +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/samples/spam_workflow/workflow.py +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/samples/weather_agent/__init__.py +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/samples/weather_agent/agent.py +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/samples/weather_agent_azure/__init__.py +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/tests/capture_messages.py +0 -0
- {agent_framework_devui-1.0.0b251001 → agent_framework_devui-1.0.0b251007}/tests/test_discovery.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agent-framework-devui
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.0b251007
|
|
4
4
|
Summary: Debug UI for Microsoft Agent Framework with OpenAI-compatible API server.
|
|
5
5
|
Author-email: Microsoft <af-support@microsoft.com>
|
|
6
6
|
Requires-Python: >=3.10
|
|
@@ -23,7 +23,7 @@ Requires-Dist: pytest>=7.0.0 ; extra == "all"
|
|
|
23
23
|
Requires-Dist: watchdog>=3.0.0 ; extra == "all"
|
|
24
24
|
Requires-Dist: pytest>=7.0.0 ; extra == "dev"
|
|
25
25
|
Requires-Dist: watchdog>=3.0.0 ; extra == "dev"
|
|
26
|
-
Project-URL: homepage, https://
|
|
26
|
+
Project-URL: homepage, https://github.com/microsoft/agent-framework
|
|
27
27
|
Project-URL: issues, https://github.com/microsoft/agent-framework/issues
|
|
28
28
|
Project-URL: release_notes, https://github.com/microsoft/agent-framework/releases?q=tag%3Apython-1&expanded=true
|
|
29
29
|
Project-URL: source, https://github.com/microsoft/agent-framework/tree/main/python
|
|
@@ -43,7 +43,7 @@ A lightweight, standalone sample app interface for running entities (agents/work
|
|
|
43
43
|
|
|
44
44
|
```bash
|
|
45
45
|
# Install
|
|
46
|
-
pip install agent-framework-devui
|
|
46
|
+
pip install agent-framework-devui --pre
|
|
47
47
|
```
|
|
48
48
|
|
|
49
49
|
You can also launch it programmatically
|
|
@@ -134,6 +134,52 @@ class EntityDiscovery:
|
|
|
134
134
|
# Extract tools/executors using Agent Framework specific logic
|
|
135
135
|
tools_list = await self._extract_tools_from_object(entity_object, entity_type)
|
|
136
136
|
|
|
137
|
+
# Extract agent-specific fields (for agents only)
|
|
138
|
+
instructions = None
|
|
139
|
+
model = None
|
|
140
|
+
chat_client_type = None
|
|
141
|
+
context_providers_list = None
|
|
142
|
+
middleware_list = None
|
|
143
|
+
|
|
144
|
+
if entity_type == "agent":
|
|
145
|
+
# Try to get instructions
|
|
146
|
+
if hasattr(entity_object, "chat_options") and hasattr(entity_object.chat_options, "instructions"):
|
|
147
|
+
instructions = entity_object.chat_options.instructions
|
|
148
|
+
|
|
149
|
+
# Try to get model - check both chat_options and chat_client
|
|
150
|
+
if (
|
|
151
|
+
hasattr(entity_object, "chat_options")
|
|
152
|
+
and hasattr(entity_object.chat_options, "model_id")
|
|
153
|
+
and entity_object.chat_options.model_id
|
|
154
|
+
):
|
|
155
|
+
model = entity_object.chat_options.model_id
|
|
156
|
+
elif hasattr(entity_object, "chat_client") and hasattr(entity_object.chat_client, "model_id"):
|
|
157
|
+
model = entity_object.chat_client.model_id
|
|
158
|
+
|
|
159
|
+
# Try to get chat client type
|
|
160
|
+
if hasattr(entity_object, "chat_client"):
|
|
161
|
+
chat_client_type = entity_object.chat_client.__class__.__name__
|
|
162
|
+
|
|
163
|
+
# Try to get context providers
|
|
164
|
+
if (
|
|
165
|
+
hasattr(entity_object, "context_provider")
|
|
166
|
+
and entity_object.context_provider
|
|
167
|
+
and hasattr(entity_object.context_provider, "__class__")
|
|
168
|
+
):
|
|
169
|
+
context_providers_list = [entity_object.context_provider.__class__.__name__]
|
|
170
|
+
|
|
171
|
+
# Try to get middleware
|
|
172
|
+
if hasattr(entity_object, "middleware") and entity_object.middleware:
|
|
173
|
+
middleware_list = []
|
|
174
|
+
for m in entity_object.middleware:
|
|
175
|
+
# Try multiple ways to get a good name for middleware
|
|
176
|
+
if hasattr(m, "__name__"): # Function or callable
|
|
177
|
+
middleware_list.append(m.__name__)
|
|
178
|
+
elif hasattr(m, "__class__"): # Class instance
|
|
179
|
+
middleware_list.append(m.__class__.__name__)
|
|
180
|
+
else:
|
|
181
|
+
middleware_list.append(str(m))
|
|
182
|
+
|
|
137
183
|
# Create EntityInfo with Agent Framework specifics
|
|
138
184
|
return EntityInfo(
|
|
139
185
|
id=entity_id,
|
|
@@ -142,6 +188,11 @@ class EntityDiscovery:
|
|
|
142
188
|
type=entity_type,
|
|
143
189
|
framework="agent_framework",
|
|
144
190
|
tools=[str(tool) for tool in (tools_list or [])],
|
|
191
|
+
instructions=instructions,
|
|
192
|
+
model_id=model,
|
|
193
|
+
chat_client_type=chat_client_type,
|
|
194
|
+
context_providers=context_providers_list,
|
|
195
|
+
middleware=middleware_list,
|
|
145
196
|
executors=tools_list if entity_type == "workflow" else [],
|
|
146
197
|
input_schema={"type": "string"}, # Default schema
|
|
147
198
|
start_executor_id=tools_list[0] if tools_list and entity_type == "workflow" else None,
|
|
@@ -446,6 +497,48 @@ class EntityDiscovery:
|
|
|
446
497
|
if tools:
|
|
447
498
|
tools_union = [tool for tool in tools]
|
|
448
499
|
|
|
500
|
+
# Extract agent-specific fields (for agents only)
|
|
501
|
+
instructions = None
|
|
502
|
+
model = None
|
|
503
|
+
chat_client_type = None
|
|
504
|
+
context_providers_list = None
|
|
505
|
+
middleware_list = None
|
|
506
|
+
|
|
507
|
+
if obj_type == "agent":
|
|
508
|
+
# Try to get instructions
|
|
509
|
+
if hasattr(obj, "chat_options") and hasattr(obj.chat_options, "instructions"):
|
|
510
|
+
instructions = obj.chat_options.instructions
|
|
511
|
+
|
|
512
|
+
# Try to get model - check both chat_options and chat_client
|
|
513
|
+
if hasattr(obj, "chat_options") and hasattr(obj.chat_options, "model_id") and obj.chat_options.model_id:
|
|
514
|
+
model = obj.chat_options.model_id
|
|
515
|
+
elif hasattr(obj, "chat_client") and hasattr(obj.chat_client, "model_id"):
|
|
516
|
+
model = obj.chat_client.model_id
|
|
517
|
+
|
|
518
|
+
# Try to get chat client type
|
|
519
|
+
if hasattr(obj, "chat_client"):
|
|
520
|
+
chat_client_type = obj.chat_client.__class__.__name__
|
|
521
|
+
|
|
522
|
+
# Try to get context providers
|
|
523
|
+
if (
|
|
524
|
+
hasattr(obj, "context_provider")
|
|
525
|
+
and obj.context_provider
|
|
526
|
+
and hasattr(obj.context_provider, "__class__")
|
|
527
|
+
):
|
|
528
|
+
context_providers_list = [obj.context_provider.__class__.__name__]
|
|
529
|
+
|
|
530
|
+
# Try to get middleware
|
|
531
|
+
if hasattr(obj, "middleware") and obj.middleware:
|
|
532
|
+
middleware_list = []
|
|
533
|
+
for m in obj.middleware:
|
|
534
|
+
# Try multiple ways to get a good name for middleware
|
|
535
|
+
if hasattr(m, "__name__"): # Function or callable
|
|
536
|
+
middleware_list.append(m.__name__)
|
|
537
|
+
elif hasattr(m, "__class__"): # Class instance
|
|
538
|
+
middleware_list.append(m.__class__.__name__)
|
|
539
|
+
else:
|
|
540
|
+
middleware_list.append(str(m))
|
|
541
|
+
|
|
449
542
|
entity_info = EntityInfo(
|
|
450
543
|
id=entity_id,
|
|
451
544
|
type=obj_type,
|
|
@@ -453,6 +546,11 @@ class EntityDiscovery:
|
|
|
453
546
|
framework="agent_framework",
|
|
454
547
|
description=description,
|
|
455
548
|
tools=tools_union,
|
|
549
|
+
instructions=instructions,
|
|
550
|
+
model_id=model,
|
|
551
|
+
chat_client_type=chat_client_type,
|
|
552
|
+
context_providers=context_providers_list,
|
|
553
|
+
middleware=middleware_list,
|
|
456
554
|
metadata={
|
|
457
555
|
"module_path": module_path,
|
|
458
556
|
"entity_type": obj_type,
|
|
@@ -7,7 +7,7 @@ import logging
|
|
|
7
7
|
import os
|
|
8
8
|
import uuid
|
|
9
9
|
from collections.abc import AsyncGenerator
|
|
10
|
-
from typing import Any
|
|
10
|
+
from typing import Any, get_origin
|
|
11
11
|
|
|
12
12
|
from agent_framework import AgentThread
|
|
13
13
|
|
|
@@ -151,6 +151,20 @@ class AgentFrameworkExecutor:
|
|
|
151
151
|
if not display_contents:
|
|
152
152
|
continue
|
|
153
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
|
+
|
|
154
168
|
ui_message = {
|
|
155
169
|
"id": af_msg.message_id or f"restored-{i}",
|
|
156
170
|
"role": role,
|
|
@@ -160,6 +174,10 @@ class AgentFrameworkExecutor:
|
|
|
160
174
|
"message_id": af_msg.message_id,
|
|
161
175
|
}
|
|
162
176
|
|
|
177
|
+
# Add usage data if available
|
|
178
|
+
if usage_data:
|
|
179
|
+
ui_message["usage"] = usage_data
|
|
180
|
+
|
|
163
181
|
ui_messages.append(ui_message)
|
|
164
182
|
|
|
165
183
|
logger.info(f"Restored {len(ui_messages)} display messages for thread {thread_id}")
|
|
@@ -638,6 +656,54 @@ class AgentFrameworkExecutor:
|
|
|
638
656
|
logger.warning(f"Error parsing workflow input: {e}")
|
|
639
657
|
return raw_input
|
|
640
658
|
|
|
659
|
+
def _get_start_executor_message_types(self, workflow: Any) -> tuple[Any | None, list[Any]]:
|
|
660
|
+
"""Return start executor and its declared input types."""
|
|
661
|
+
try:
|
|
662
|
+
start_executor = workflow.get_start_executor()
|
|
663
|
+
except Exception as exc: # pragma: no cover - defensive logging path
|
|
664
|
+
logger.debug(f"Unable to access workflow start executor: {exc}")
|
|
665
|
+
return None, []
|
|
666
|
+
|
|
667
|
+
if not start_executor:
|
|
668
|
+
return None, []
|
|
669
|
+
|
|
670
|
+
message_types: list[Any] = []
|
|
671
|
+
|
|
672
|
+
try:
|
|
673
|
+
input_types = getattr(start_executor, "input_types", None)
|
|
674
|
+
except Exception as exc: # pragma: no cover - defensive logging path
|
|
675
|
+
logger.debug(f"Failed to read executor input_types: {exc}")
|
|
676
|
+
else:
|
|
677
|
+
if input_types:
|
|
678
|
+
message_types = list(input_types)
|
|
679
|
+
|
|
680
|
+
if not message_types and hasattr(start_executor, "_handlers"):
|
|
681
|
+
try:
|
|
682
|
+
handlers = start_executor._handlers
|
|
683
|
+
if isinstance(handlers, dict):
|
|
684
|
+
message_types = list(handlers.keys())
|
|
685
|
+
except Exception as exc: # pragma: no cover - defensive logging path
|
|
686
|
+
logger.debug(f"Failed to read executor handlers: {exc}")
|
|
687
|
+
|
|
688
|
+
return start_executor, message_types
|
|
689
|
+
|
|
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
|
+
|
|
641
707
|
def _parse_structured_workflow_input(self, workflow: Any, input_data: dict[str, Any]) -> Any:
|
|
642
708
|
"""Parse structured input data for workflow execution.
|
|
643
709
|
|
|
@@ -649,59 +715,30 @@ class AgentFrameworkExecutor:
|
|
|
649
715
|
Parsed input for workflow
|
|
650
716
|
"""
|
|
651
717
|
try:
|
|
718
|
+
from ._utils import parse_input_for_type
|
|
719
|
+
|
|
652
720
|
# Get the start executor and its input type
|
|
653
|
-
start_executor =
|
|
654
|
-
if not start_executor
|
|
721
|
+
start_executor, message_types = self._get_start_executor_message_types(workflow)
|
|
722
|
+
if not start_executor:
|
|
655
723
|
logger.debug("Cannot determine input type for workflow - using raw dict")
|
|
656
724
|
return input_data
|
|
657
725
|
|
|
658
|
-
message_types = list(start_executor._handlers.keys())
|
|
659
726
|
if not message_types:
|
|
660
727
|
logger.debug("No message types found for start executor - using raw dict")
|
|
661
728
|
return input_data
|
|
662
729
|
|
|
663
730
|
# Get the first (primary) input type
|
|
664
|
-
input_type = message_types
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
if input_type is dict:
|
|
731
|
+
input_type = self._select_primary_input_type(message_types)
|
|
732
|
+
if input_type is None:
|
|
733
|
+
logger.debug("Could not select primary input type for workflow - using raw dict")
|
|
668
734
|
return input_data
|
|
669
735
|
|
|
670
|
-
#
|
|
671
|
-
|
|
672
|
-
try:
|
|
673
|
-
if isinstance(input_data, input_type):
|
|
674
|
-
return input_data
|
|
675
|
-
if "input" in input_data:
|
|
676
|
-
return input_type(input_data["input"])
|
|
677
|
-
if len(input_data) == 1:
|
|
678
|
-
value = next(iter(input_data.values()))
|
|
679
|
-
return input_type(value)
|
|
680
|
-
return input_data
|
|
681
|
-
except (ValueError, TypeError) as e:
|
|
682
|
-
logger.warning(f"Failed to convert input to {input_type}: {e}")
|
|
683
|
-
return input_data
|
|
684
|
-
|
|
685
|
-
# If it's a Pydantic model, validate and create instance
|
|
686
|
-
if hasattr(input_type, "model_validate"):
|
|
687
|
-
try:
|
|
688
|
-
return input_type.model_validate(input_data)
|
|
689
|
-
except Exception as e:
|
|
690
|
-
logger.warning(f"Failed to validate input as {input_type}: {e}")
|
|
691
|
-
return input_data
|
|
692
|
-
|
|
693
|
-
# If it's a dataclass or other type with annotations
|
|
694
|
-
elif hasattr(input_type, "__annotations__"):
|
|
695
|
-
try:
|
|
696
|
-
return input_type(**input_data)
|
|
697
|
-
except Exception as e:
|
|
698
|
-
logger.warning(f"Failed to create {input_type} from input data: {e}")
|
|
699
|
-
return input_data
|
|
736
|
+
# Use consolidated parsing logic from _utils
|
|
737
|
+
return parse_input_for_type(input_data, input_type)
|
|
700
738
|
|
|
701
739
|
except Exception as e:
|
|
702
740
|
logger.warning(f"Error parsing structured workflow input: {e}")
|
|
703
|
-
|
|
704
|
-
return input_data
|
|
741
|
+
return input_data
|
|
705
742
|
|
|
706
743
|
def _parse_raw_workflow_input(self, workflow: Any, raw_input: str) -> Any:
|
|
707
744
|
"""Parse raw input string based on workflow's expected input type.
|
|
@@ -714,57 +751,27 @@ class AgentFrameworkExecutor:
|
|
|
714
751
|
Parsed input for workflow
|
|
715
752
|
"""
|
|
716
753
|
try:
|
|
754
|
+
from ._utils import parse_input_for_type
|
|
755
|
+
|
|
717
756
|
# Get the start executor and its input type
|
|
718
|
-
start_executor =
|
|
719
|
-
if not start_executor
|
|
757
|
+
start_executor, message_types = self._get_start_executor_message_types(workflow)
|
|
758
|
+
if not start_executor:
|
|
720
759
|
logger.debug("Cannot determine input type for workflow - using raw string")
|
|
721
760
|
return raw_input
|
|
722
761
|
|
|
723
|
-
message_types = list(start_executor._handlers.keys())
|
|
724
762
|
if not message_types:
|
|
725
763
|
logger.debug("No message types found for start executor - using raw string")
|
|
726
764
|
return raw_input
|
|
727
765
|
|
|
728
766
|
# Get the first (primary) input type
|
|
729
|
-
input_type = message_types
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
if input_type is str:
|
|
767
|
+
input_type = self._select_primary_input_type(message_types)
|
|
768
|
+
if input_type is None:
|
|
769
|
+
logger.debug("Could not select primary input type for workflow - using raw string")
|
|
733
770
|
return raw_input
|
|
734
771
|
|
|
735
|
-
#
|
|
736
|
-
|
|
737
|
-
try:
|
|
738
|
-
# First try to parse as JSON
|
|
739
|
-
if raw_input.strip().startswith("{"):
|
|
740
|
-
return input_type.model_validate_json(raw_input)
|
|
741
|
-
|
|
742
|
-
# Try common field names
|
|
743
|
-
common_fields = ["message", "text", "input", "data", "content"]
|
|
744
|
-
for field in common_fields:
|
|
745
|
-
try:
|
|
746
|
-
return input_type(**{field: raw_input})
|
|
747
|
-
except Exception as e:
|
|
748
|
-
logger.debug(f"Failed to parse input using field '{field}': {e}")
|
|
749
|
-
continue
|
|
750
|
-
|
|
751
|
-
# Last resort: try default constructor
|
|
752
|
-
return input_type()
|
|
753
|
-
|
|
754
|
-
except Exception as e:
|
|
755
|
-
logger.debug(f"Failed to parse input as {input_type}: {e}")
|
|
756
|
-
|
|
757
|
-
# If it's a dataclass, try JSON parsing
|
|
758
|
-
elif hasattr(input_type, "__annotations__"):
|
|
759
|
-
try:
|
|
760
|
-
if raw_input.strip().startswith("{"):
|
|
761
|
-
parsed = json.loads(raw_input)
|
|
762
|
-
return input_type(**parsed)
|
|
763
|
-
except Exception as e:
|
|
764
|
-
logger.debug(f"Failed to parse input as {input_type}: {e}")
|
|
772
|
+
# Use consolidated parsing logic from _utils
|
|
773
|
+
return parse_input_for_type(raw_input, input_type)
|
|
765
774
|
|
|
766
775
|
except Exception as e:
|
|
767
|
-
logger.debug(f"Error
|
|
768
|
-
|
|
769
|
-
# Fallback: return raw string
|
|
770
|
-
return raw_input
|
|
776
|
+
logger.debug(f"Error parsing workflow input: {e}")
|
|
777
|
+
return raw_input
|
|
@@ -6,7 +6,6 @@ import json
|
|
|
6
6
|
import logging
|
|
7
7
|
import uuid
|
|
8
8
|
from collections.abc import Sequence
|
|
9
|
-
from dataclasses import asdict, is_dataclass
|
|
10
9
|
from datetime import datetime
|
|
11
10
|
from typing import Any, Union
|
|
12
11
|
|
|
@@ -97,8 +96,18 @@ class MessageMapper:
|
|
|
97
96
|
# Import Agent Framework types for proper isinstance checks
|
|
98
97
|
try:
|
|
99
98
|
from agent_framework import AgentRunResponseUpdate, WorkflowEvent
|
|
99
|
+
from agent_framework._workflows._events import AgentRunUpdateEvent
|
|
100
|
+
|
|
101
|
+
# Handle AgentRunUpdateEvent - workflow event wrapping AgentRunResponseUpdate
|
|
102
|
+
# This must be checked BEFORE generic WorkflowEvent check
|
|
103
|
+
if isinstance(raw_event, AgentRunUpdateEvent):
|
|
104
|
+
# Extract the AgentRunResponseUpdate from the event's data attribute
|
|
105
|
+
if raw_event.data and isinstance(raw_event.data, AgentRunResponseUpdate):
|
|
106
|
+
return await self._convert_agent_update(raw_event.data, context)
|
|
107
|
+
# If no data, treat as generic workflow event
|
|
108
|
+
return await self._convert_workflow_event(raw_event, context)
|
|
100
109
|
|
|
101
|
-
# Handle agent updates (AgentRunResponseUpdate)
|
|
110
|
+
# Handle agent updates (AgentRunResponseUpdate) - for direct agent execution
|
|
102
111
|
if isinstance(raw_event, AgentRunResponseUpdate):
|
|
103
112
|
return await self._convert_agent_update(raw_event, context)
|
|
104
113
|
|
|
@@ -258,13 +267,22 @@ class MessageMapper:
|
|
|
258
267
|
List of OpenAI response stream events
|
|
259
268
|
"""
|
|
260
269
|
try:
|
|
261
|
-
|
|
270
|
+
# Get event data and serialize if it's a SerializationMixin
|
|
271
|
+
event_data = getattr(event, "data", None)
|
|
272
|
+
if event_data is not None and hasattr(event_data, "to_dict"):
|
|
273
|
+
# SerializationMixin objects - convert to dict for JSON serialization
|
|
274
|
+
try:
|
|
275
|
+
event_data = event_data.to_dict()
|
|
276
|
+
except Exception as e:
|
|
277
|
+
logger.debug(f"Failed to serialize event data with to_dict(): {e}")
|
|
278
|
+
event_data = str(event_data)
|
|
279
|
+
|
|
262
280
|
# Create structured workflow event
|
|
263
281
|
workflow_event = ResponseWorkflowEventComplete(
|
|
264
282
|
type="response.workflow_event.complete",
|
|
265
283
|
data={
|
|
266
284
|
"event_type": event.__class__.__name__,
|
|
267
|
-
"data":
|
|
285
|
+
"data": event_data,
|
|
268
286
|
"executor_id": getattr(event, "executor_id", None),
|
|
269
287
|
"timestamp": datetime.now().isoformat(),
|
|
270
288
|
},
|
|
@@ -280,59 +298,6 @@ class MessageMapper:
|
|
|
280
298
|
logger.warning(f"Error converting workflow event: {e}")
|
|
281
299
|
return [await self._create_error_event(str(e), context)]
|
|
282
300
|
|
|
283
|
-
def _serialize_payload(self, value: Any) -> Any:
|
|
284
|
-
"""Best-effort JSON serialization for workflow payloads."""
|
|
285
|
-
if value is None:
|
|
286
|
-
return None
|
|
287
|
-
if isinstance(value, (str, int, float, bool)):
|
|
288
|
-
return value
|
|
289
|
-
if isinstance(value, (list, tuple, set)):
|
|
290
|
-
return [self._serialize_payload(item) for item in value]
|
|
291
|
-
if isinstance(value, dict):
|
|
292
|
-
return {str(k): self._serialize_payload(v) for k, v in value.items()}
|
|
293
|
-
if is_dataclass(value) and not isinstance(value, type):
|
|
294
|
-
try:
|
|
295
|
-
return self._serialize_payload(asdict(value))
|
|
296
|
-
except Exception as exc:
|
|
297
|
-
logger.debug("Failed to serialize dataclass payload: %s", exc)
|
|
298
|
-
model_dump_method = getattr(value, "model_dump", None)
|
|
299
|
-
if model_dump_method is not None and callable(model_dump_method):
|
|
300
|
-
try:
|
|
301
|
-
dumped = model_dump_method()
|
|
302
|
-
return self._serialize_payload(dumped)
|
|
303
|
-
except Exception as exc:
|
|
304
|
-
logger.debug("Failed to serialize payload via model_dump: %s", exc)
|
|
305
|
-
dict_method = getattr(value, "dict", None)
|
|
306
|
-
if dict_method is not None and callable(dict_method):
|
|
307
|
-
try:
|
|
308
|
-
dict_result = dict_method()
|
|
309
|
-
return self._serialize_payload(dict_result)
|
|
310
|
-
except Exception as exc:
|
|
311
|
-
logger.debug("Failed to serialize payload via dict(): %s", exc)
|
|
312
|
-
to_dict_method = getattr(value, "to_dict", None)
|
|
313
|
-
if to_dict_method is not None and callable(to_dict_method):
|
|
314
|
-
try:
|
|
315
|
-
to_dict_result = to_dict_method()
|
|
316
|
-
return self._serialize_payload(to_dict_result)
|
|
317
|
-
except Exception as exc:
|
|
318
|
-
logger.debug("Failed to serialize payload via to_dict(): %s", exc)
|
|
319
|
-
model_dump_json_method = getattr(value, "model_dump_json", None)
|
|
320
|
-
if model_dump_json_method is not None and callable(model_dump_json_method):
|
|
321
|
-
try:
|
|
322
|
-
json_str = model_dump_json_method()
|
|
323
|
-
if isinstance(json_str, (str, bytes, bytearray)):
|
|
324
|
-
return json.loads(json_str)
|
|
325
|
-
except Exception as exc:
|
|
326
|
-
logger.debug("Failed to serialize payload via model_dump_json: %s", exc)
|
|
327
|
-
if hasattr(value, "__dict__"):
|
|
328
|
-
try:
|
|
329
|
-
return self._serialize_payload({
|
|
330
|
-
key: self._serialize_payload(val) for key, val in value.__dict__.items() if not key.startswith("_")
|
|
331
|
-
})
|
|
332
|
-
except Exception as exc:
|
|
333
|
-
logger.debug("Failed to serialize payload via __dict__: %s", exc)
|
|
334
|
-
return str(value)
|
|
335
|
-
|
|
336
301
|
# Content type mappers - implementing our comprehensive mapping plan
|
|
337
302
|
|
|
338
303
|
async def _map_text_content(self, content: Any, context: dict[str, Any]) -> ResponseTextDeltaEvent:
|
|
@@ -409,13 +374,24 @@ class MessageMapper:
|
|
|
409
374
|
context["usage_data"] = []
|
|
410
375
|
context["usage_data"].append(content)
|
|
411
376
|
|
|
377
|
+
# Extract usage from UsageContent.details (UsageDetails object)
|
|
378
|
+
details = getattr(content, "details", None)
|
|
379
|
+
total_tokens = 0
|
|
380
|
+
prompt_tokens = 0
|
|
381
|
+
completion_tokens = 0
|
|
382
|
+
|
|
383
|
+
if details:
|
|
384
|
+
total_tokens = getattr(details, "total_token_count", 0) or 0
|
|
385
|
+
prompt_tokens = getattr(details, "input_token_count", 0) or 0
|
|
386
|
+
completion_tokens = getattr(details, "output_token_count", 0) or 0
|
|
387
|
+
|
|
412
388
|
return ResponseUsageEventComplete(
|
|
413
389
|
type="response.usage.complete",
|
|
414
390
|
data={
|
|
415
|
-
"usage_data":
|
|
416
|
-
"total_tokens":
|
|
417
|
-
"completion_tokens":
|
|
418
|
-
"prompt_tokens":
|
|
391
|
+
"usage_data": details.to_dict() if details and hasattr(details, "to_dict") else {},
|
|
392
|
+
"total_tokens": total_tokens,
|
|
393
|
+
"completion_tokens": completion_tokens,
|
|
394
|
+
"prompt_tokens": prompt_tokens,
|
|
419
395
|
"timestamp": datetime.now().isoformat(),
|
|
420
396
|
},
|
|
421
397
|
item_id=context["item_id"],
|
|
@@ -7,7 +7,7 @@ import json
|
|
|
7
7
|
import logging
|
|
8
8
|
from collections.abc import AsyncGenerator
|
|
9
9
|
from contextlib import asynccontextmanager
|
|
10
|
-
from typing import Any
|
|
10
|
+
from typing import Any, get_origin
|
|
11
11
|
|
|
12
12
|
from fastapi import FastAPI, HTTPException, Request
|
|
13
13
|
from fastapi.middleware.cors import CORSMiddleware
|
|
@@ -23,6 +23,47 @@ from .models._discovery_models import DiscoveryResponse, EntityInfo
|
|
|
23
23
|
logger = logging.getLogger(__name__)
|
|
24
24
|
|
|
25
25
|
|
|
26
|
+
def _extract_executor_message_types(executor: Any) -> list[Any]:
|
|
27
|
+
"""Return declared input types for the given executor."""
|
|
28
|
+
message_types: list[Any] = []
|
|
29
|
+
|
|
30
|
+
try:
|
|
31
|
+
input_types = getattr(executor, "input_types", None)
|
|
32
|
+
except Exception as exc: # pragma: no cover - defensive logging path
|
|
33
|
+
logger.debug(f"Failed to access executor input_types: {exc}")
|
|
34
|
+
else:
|
|
35
|
+
if input_types:
|
|
36
|
+
message_types = list(input_types)
|
|
37
|
+
|
|
38
|
+
if not message_types and hasattr(executor, "_handlers"):
|
|
39
|
+
try:
|
|
40
|
+
handlers = executor._handlers
|
|
41
|
+
if isinstance(handlers, dict):
|
|
42
|
+
message_types = list(handlers.keys())
|
|
43
|
+
except Exception as exc: # pragma: no cover - defensive logging path
|
|
44
|
+
logger.debug(f"Failed to read executor handlers: {exc}")
|
|
45
|
+
|
|
46
|
+
return message_types
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _select_primary_input_type(message_types: list[Any]) -> Any | None:
|
|
50
|
+
"""Choose the most user-friendly input type for rendering workflow inputs."""
|
|
51
|
+
if not message_types:
|
|
52
|
+
return None
|
|
53
|
+
|
|
54
|
+
preferred = (str, dict)
|
|
55
|
+
|
|
56
|
+
for candidate in preferred:
|
|
57
|
+
for message_type in message_types:
|
|
58
|
+
if message_type is candidate:
|
|
59
|
+
return candidate
|
|
60
|
+
origin = get_origin(message_type)
|
|
61
|
+
if origin is candidate:
|
|
62
|
+
return candidate
|
|
63
|
+
|
|
64
|
+
return message_types[0]
|
|
65
|
+
|
|
66
|
+
|
|
26
67
|
class DevServer:
|
|
27
68
|
"""Development Server - OpenAI compatible API server for debugging agents."""
|
|
28
69
|
|
|
@@ -222,24 +263,30 @@ class DevServer:
|
|
|
222
263
|
start_executor_id = ""
|
|
223
264
|
|
|
224
265
|
try:
|
|
266
|
+
from ._utils import generate_input_schema
|
|
267
|
+
|
|
225
268
|
start_executor = entity_obj.get_start_executor()
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
269
|
+
except Exception as e:
|
|
270
|
+
logger.debug(f"Could not extract input info for workflow {entity_id}: {e}")
|
|
271
|
+
else:
|
|
272
|
+
if start_executor:
|
|
273
|
+
start_executor_id = getattr(start_executor, "executor_id", "") or getattr(
|
|
274
|
+
start_executor, "id", ""
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
message_types = _extract_executor_message_types(start_executor)
|
|
278
|
+
input_type = _select_primary_input_type(message_types)
|
|
279
|
+
|
|
280
|
+
if input_type:
|
|
230
281
|
input_type_name = getattr(input_type, "__name__", str(input_type))
|
|
231
282
|
|
|
232
|
-
#
|
|
233
|
-
|
|
234
|
-
input_schema = {"type": "string"}
|
|
235
|
-
elif input_type is dict:
|
|
236
|
-
input_schema = {"type": "object"}
|
|
237
|
-
elif hasattr(input_type, "model_json_schema"):
|
|
238
|
-
input_schema = input_type.model_json_schema()
|
|
283
|
+
# Generate schema using comprehensive schema generation
|
|
284
|
+
input_schema = generate_input_schema(input_type)
|
|
239
285
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
286
|
+
if not input_schema:
|
|
287
|
+
input_schema = {"type": "string"}
|
|
288
|
+
if input_type_name == "Unknown":
|
|
289
|
+
input_type_name = "string"
|
|
243
290
|
|
|
244
291
|
# Get executor list
|
|
245
292
|
executor_list = []
|
|
@@ -67,7 +67,7 @@ class SessionManager:
|
|
|
67
67
|
logger.debug(f"Closed session: {session_id}")
|
|
68
68
|
|
|
69
69
|
def add_request_record(
|
|
70
|
-
self, session_id: str, entity_id: str, executor_name: str, request_input: Any,
|
|
70
|
+
self, session_id: str, entity_id: str, executor_name: str, request_input: Any, model_id: str
|
|
71
71
|
) -> str:
|
|
72
72
|
"""Add a request record to a session.
|
|
73
73
|
|
|
@@ -76,7 +76,7 @@ class SessionManager:
|
|
|
76
76
|
entity_id: ID of the entity being executed
|
|
77
77
|
executor_name: Name of the executor
|
|
78
78
|
request_input: Input for the request
|
|
79
|
-
|
|
79
|
+
model_id: Model name
|
|
80
80
|
|
|
81
81
|
Returns:
|
|
82
82
|
Request ID
|
|
@@ -91,7 +91,7 @@ class SessionManager:
|
|
|
91
91
|
"entity_id": entity_id,
|
|
92
92
|
"executor": executor_name,
|
|
93
93
|
"input": request_input,
|
|
94
|
-
"
|
|
94
|
+
"model_id": model_id,
|
|
95
95
|
"stream": True,
|
|
96
96
|
}
|
|
97
97
|
session["requests"].append(request_record)
|