uipath-openai-agents 0.0.1__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.
- uipath_openai_agents/__init__.py +7 -0
- uipath_openai_agents/_cli/__init__.py +1 -0
- uipath_openai_agents/_cli/_templates/AGENTS.md.template +21 -0
- uipath_openai_agents/_cli/_templates/main.py.template +28 -0
- uipath_openai_agents/_cli/_templates/openai_agents.json.template +5 -0
- uipath_openai_agents/_cli/cli_new.py +81 -0
- uipath_openai_agents/chat/__init__.py +5 -0
- uipath_openai_agents/chat/openai.py +242 -0
- uipath_openai_agents/chat/supported_models.py +78 -0
- uipath_openai_agents/middlewares.py +8 -0
- uipath_openai_agents/py.typed +0 -0
- uipath_openai_agents/runtime/__init__.py +40 -0
- uipath_openai_agents/runtime/_serialize.py +51 -0
- uipath_openai_agents/runtime/_sqlite.py +190 -0
- uipath_openai_agents/runtime/_telemetry.py +32 -0
- uipath_openai_agents/runtime/agent.py +201 -0
- uipath_openai_agents/runtime/config.py +55 -0
- uipath_openai_agents/runtime/errors.py +48 -0
- uipath_openai_agents/runtime/factory.py +353 -0
- uipath_openai_agents/runtime/runtime.py +532 -0
- uipath_openai_agents/runtime/schema.py +490 -0
- uipath_openai_agents/runtime/storage.py +357 -0
- uipath_openai_agents-0.0.1.dist-info/METADATA +53 -0
- uipath_openai_agents-0.0.1.dist-info/RECORD +26 -0
- uipath_openai_agents-0.0.1.dist-info/WHEEL +4 -0
- uipath_openai_agents-0.0.1.dist-info/entry_points.txt +5 -0
|
@@ -0,0 +1,490 @@
|
|
|
1
|
+
"""Schema extraction utilities for OpenAI Agents."""
|
|
2
|
+
|
|
3
|
+
import inspect
|
|
4
|
+
from typing import Any, get_args, get_origin, get_type_hints
|
|
5
|
+
|
|
6
|
+
from agents import Agent
|
|
7
|
+
from pydantic import BaseModel, TypeAdapter
|
|
8
|
+
from uipath.runtime.schema import (
|
|
9
|
+
UiPathRuntimeEdge,
|
|
10
|
+
UiPathRuntimeGraph,
|
|
11
|
+
UiPathRuntimeNode,
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
def _is_pydantic_model(type_hint: Any) -> bool:
|
|
16
|
+
"""
|
|
17
|
+
Check if a type hint is a Pydantic BaseModel.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
type_hint: A type hint from type annotations
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
True if the type is a Pydantic model, False otherwise
|
|
24
|
+
"""
|
|
25
|
+
try:
|
|
26
|
+
# Direct check
|
|
27
|
+
if inspect.isclass(type_hint) and issubclass(type_hint, BaseModel):
|
|
28
|
+
return True
|
|
29
|
+
|
|
30
|
+
# Handle generic types (e.g., Optional[Model])
|
|
31
|
+
origin = get_origin(type_hint)
|
|
32
|
+
if origin is not None:
|
|
33
|
+
args = get_args(type_hint)
|
|
34
|
+
for arg in args:
|
|
35
|
+
if inspect.isclass(arg) and issubclass(arg, BaseModel):
|
|
36
|
+
return True
|
|
37
|
+
|
|
38
|
+
except TypeError:
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
return False
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _extract_schema_from_callable(callable_obj: Any) -> dict[str, Any] | None:
|
|
45
|
+
"""
|
|
46
|
+
Extract input/output schemas from a callable's type annotations.
|
|
47
|
+
|
|
48
|
+
Args:
|
|
49
|
+
callable_obj: A callable object (function, async function, etc.)
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
Dictionary with input and output schemas if type hints are found,
|
|
53
|
+
None otherwise
|
|
54
|
+
"""
|
|
55
|
+
if not callable(callable_obj):
|
|
56
|
+
return None
|
|
57
|
+
|
|
58
|
+
try:
|
|
59
|
+
# Get type hints from the callable
|
|
60
|
+
type_hints = get_type_hints(callable_obj)
|
|
61
|
+
|
|
62
|
+
if not type_hints:
|
|
63
|
+
return None
|
|
64
|
+
|
|
65
|
+
# Get function signature to identify parameters
|
|
66
|
+
sig = inspect.signature(callable_obj)
|
|
67
|
+
params = list(sig.parameters.values())
|
|
68
|
+
|
|
69
|
+
# Find the first parameter (usually the input)
|
|
70
|
+
input_type = None
|
|
71
|
+
|
|
72
|
+
for param in params:
|
|
73
|
+
if param.name in ("self", "cls"):
|
|
74
|
+
continue
|
|
75
|
+
if param.name in type_hints:
|
|
76
|
+
input_type = type_hints[param.name]
|
|
77
|
+
break
|
|
78
|
+
|
|
79
|
+
# Get return type
|
|
80
|
+
return_type = type_hints.get("return")
|
|
81
|
+
|
|
82
|
+
schema: dict[str, Any] = {
|
|
83
|
+
"input": {"type": "object", "properties": {}, "required": []},
|
|
84
|
+
"output": {"type": "object", "properties": {}, "required": []},
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
# Extract input schema from Pydantic model
|
|
88
|
+
if input_type and _is_pydantic_model(input_type):
|
|
89
|
+
adapter = TypeAdapter(input_type)
|
|
90
|
+
input_schema = adapter.json_schema()
|
|
91
|
+
unpacked_input = _resolve_refs(input_schema)
|
|
92
|
+
|
|
93
|
+
schema["input"]["properties"] = _process_nullable_types(
|
|
94
|
+
unpacked_input.get("properties", {})
|
|
95
|
+
)
|
|
96
|
+
schema["input"]["required"] = unpacked_input.get("required", [])
|
|
97
|
+
|
|
98
|
+
# Add title and description if available
|
|
99
|
+
if "title" in unpacked_input:
|
|
100
|
+
schema["input"]["title"] = unpacked_input["title"]
|
|
101
|
+
if "description" in unpacked_input:
|
|
102
|
+
schema["input"]["description"] = unpacked_input["description"]
|
|
103
|
+
|
|
104
|
+
# Extract output schema from Pydantic model
|
|
105
|
+
if return_type and _is_pydantic_model(return_type):
|
|
106
|
+
adapter = TypeAdapter(return_type)
|
|
107
|
+
output_schema = adapter.json_schema()
|
|
108
|
+
unpacked_output = _resolve_refs(output_schema)
|
|
109
|
+
|
|
110
|
+
schema["output"]["properties"] = _process_nullable_types(
|
|
111
|
+
unpacked_output.get("properties", {})
|
|
112
|
+
)
|
|
113
|
+
schema["output"]["required"] = unpacked_output.get("required", [])
|
|
114
|
+
|
|
115
|
+
# Add title and description if available
|
|
116
|
+
if "title" in unpacked_output:
|
|
117
|
+
schema["output"]["title"] = unpacked_output["title"]
|
|
118
|
+
if "description" in unpacked_output:
|
|
119
|
+
schema["output"]["description"] = unpacked_output["description"]
|
|
120
|
+
|
|
121
|
+
# Only return schema if we found at least one Pydantic model
|
|
122
|
+
if schema["input"]["properties"] or schema["output"]["properties"]:
|
|
123
|
+
return schema
|
|
124
|
+
|
|
125
|
+
except Exception:
|
|
126
|
+
# If schema extraction fails, return None to fall back to default
|
|
127
|
+
pass
|
|
128
|
+
|
|
129
|
+
return None
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
def get_entrypoints_schema(
|
|
133
|
+
agent: Agent, loaded_object: Any | None = None
|
|
134
|
+
) -> dict[str, Any]:
|
|
135
|
+
"""
|
|
136
|
+
Extract input/output schema from an OpenAI Agent.
|
|
137
|
+
|
|
138
|
+
Prioritizes the agent's native output_type attribute (OpenAI Agents pattern),
|
|
139
|
+
with optional fallback to wrapper function type hints (UiPath pattern).
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
agent: An OpenAI Agent instance
|
|
143
|
+
loaded_object: Optional original loaded object (function/callable) with type annotations
|
|
144
|
+
|
|
145
|
+
Returns:
|
|
146
|
+
Dictionary with input and output schemas
|
|
147
|
+
"""
|
|
148
|
+
schema = {
|
|
149
|
+
"input": {"type": "object", "properties": {}, "required": []},
|
|
150
|
+
"output": {"type": "object", "properties": {}, "required": []},
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
# Extract input schema - check agent's context type or use default messages
|
|
154
|
+
# For OpenAI Agents, input is typically messages (string or list of message objects)
|
|
155
|
+
schema["input"] = {
|
|
156
|
+
"type": "object",
|
|
157
|
+
"properties": {
|
|
158
|
+
"message": {
|
|
159
|
+
"anyOf": [
|
|
160
|
+
{"type": "string"},
|
|
161
|
+
{
|
|
162
|
+
"type": "array",
|
|
163
|
+
"items": {"type": "object"},
|
|
164
|
+
},
|
|
165
|
+
],
|
|
166
|
+
"title": "Message",
|
|
167
|
+
"description": "User message(s) to send to the agent",
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
"required": ["message"],
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
# Extract output schema - PRIORITY 1: Agent's output_type (native OpenAI Agents pattern)
|
|
174
|
+
output_type = getattr(agent, "output_type", None)
|
|
175
|
+
output_extracted = False
|
|
176
|
+
|
|
177
|
+
# Unwrap AgentOutputSchema if present (OpenAI Agents SDK wrapper)
|
|
178
|
+
# Check for AgentOutputSchema by looking for 'schema' attribute on non-type instances
|
|
179
|
+
if (
|
|
180
|
+
output_type is not None
|
|
181
|
+
and hasattr(output_type, "schema")
|
|
182
|
+
and not isinstance(output_type, type)
|
|
183
|
+
):
|
|
184
|
+
# This is an AgentOutputSchema wrapper instance, extract the actual model
|
|
185
|
+
output_type = output_type.schema
|
|
186
|
+
|
|
187
|
+
if output_type is not None and _is_pydantic_model(output_type):
|
|
188
|
+
try:
|
|
189
|
+
adapter = TypeAdapter(output_type)
|
|
190
|
+
output_schema = adapter.json_schema()
|
|
191
|
+
|
|
192
|
+
# Resolve references and handle nullable types
|
|
193
|
+
unpacked_output = _resolve_refs(output_schema)
|
|
194
|
+
schema["output"]["properties"] = _process_nullable_types(
|
|
195
|
+
unpacked_output.get("properties", {})
|
|
196
|
+
)
|
|
197
|
+
schema["output"]["required"] = unpacked_output.get("required", [])
|
|
198
|
+
|
|
199
|
+
# Add title and description if available
|
|
200
|
+
if "title" in unpacked_output:
|
|
201
|
+
schema["output"]["title"] = unpacked_output["title"]
|
|
202
|
+
if "description" in unpacked_output:
|
|
203
|
+
schema["output"]["description"] = unpacked_output["description"]
|
|
204
|
+
|
|
205
|
+
output_extracted = True
|
|
206
|
+
except Exception:
|
|
207
|
+
# Continue to fallback if extraction fails
|
|
208
|
+
pass
|
|
209
|
+
|
|
210
|
+
# Extract output schema - PRIORITY 2: Wrapper function type hints (UiPath pattern)
|
|
211
|
+
# This allows UiPath-specific patterns where agents are wrapped in typed functions
|
|
212
|
+
if not output_extracted and loaded_object is not None:
|
|
213
|
+
wrapper_schema = _extract_schema_from_callable(loaded_object)
|
|
214
|
+
if wrapper_schema is not None:
|
|
215
|
+
# Use the wrapper's output schema, but keep the default input (messages)
|
|
216
|
+
schema["output"] = wrapper_schema["output"]
|
|
217
|
+
output_extracted = True
|
|
218
|
+
|
|
219
|
+
# Fallback: Default output schema for agents without explicit output_type
|
|
220
|
+
if not output_extracted:
|
|
221
|
+
schema["output"] = {
|
|
222
|
+
"type": "object",
|
|
223
|
+
"properties": {
|
|
224
|
+
"result": {
|
|
225
|
+
"title": "Result",
|
|
226
|
+
"description": "The agent's response",
|
|
227
|
+
"anyOf": [
|
|
228
|
+
{"type": "string"},
|
|
229
|
+
{"type": "object"},
|
|
230
|
+
{
|
|
231
|
+
"type": "array",
|
|
232
|
+
"items": {"type": "object"},
|
|
233
|
+
},
|
|
234
|
+
],
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
"required": ["result"],
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
return schema
|
|
241
|
+
|
|
242
|
+
|
|
243
|
+
def get_agent_schema(agent: Agent) -> UiPathRuntimeGraph:
|
|
244
|
+
"""
|
|
245
|
+
Extract graph structure from an OpenAI Agent.
|
|
246
|
+
|
|
247
|
+
OpenAI Agents can delegate to other agents through handoffs,
|
|
248
|
+
creating a hierarchical agent structure.
|
|
249
|
+
|
|
250
|
+
Args:
|
|
251
|
+
agent: An OpenAI Agent instance
|
|
252
|
+
|
|
253
|
+
Returns:
|
|
254
|
+
UiPathRuntimeGraph with nodes and edges representing the agent structure
|
|
255
|
+
"""
|
|
256
|
+
nodes: list[UiPathRuntimeNode] = []
|
|
257
|
+
edges: list[UiPathRuntimeEdge] = []
|
|
258
|
+
|
|
259
|
+
# Start node
|
|
260
|
+
nodes.append(
|
|
261
|
+
UiPathRuntimeNode(
|
|
262
|
+
id="__start__",
|
|
263
|
+
name="__start__",
|
|
264
|
+
type="__start__",
|
|
265
|
+
subgraph=None,
|
|
266
|
+
)
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
# Main agent node (always type "model" since it's an LLM)
|
|
270
|
+
agent_name = getattr(agent, "name", "agent")
|
|
271
|
+
nodes.append(
|
|
272
|
+
UiPathRuntimeNode(
|
|
273
|
+
id=agent_name,
|
|
274
|
+
name=agent_name,
|
|
275
|
+
type="model",
|
|
276
|
+
subgraph=None,
|
|
277
|
+
)
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
# Connect start to main agent
|
|
281
|
+
edges.append(
|
|
282
|
+
UiPathRuntimeEdge(
|
|
283
|
+
source="__start__",
|
|
284
|
+
target=agent_name,
|
|
285
|
+
label="input",
|
|
286
|
+
)
|
|
287
|
+
)
|
|
288
|
+
|
|
289
|
+
# Add tool nodes if tools are available
|
|
290
|
+
tools = getattr(agent, "tools", None) or []
|
|
291
|
+
if tools:
|
|
292
|
+
for tool in tools:
|
|
293
|
+
# Extract tool name - handle various tool types
|
|
294
|
+
tool_name = _get_tool_name(tool)
|
|
295
|
+
if tool_name:
|
|
296
|
+
nodes.append(
|
|
297
|
+
UiPathRuntimeNode(
|
|
298
|
+
id=tool_name,
|
|
299
|
+
name=tool_name,
|
|
300
|
+
type="tool",
|
|
301
|
+
subgraph=None,
|
|
302
|
+
)
|
|
303
|
+
)
|
|
304
|
+
# Bidirectional edges: agent calls tool, tool returns to agent
|
|
305
|
+
edges.append(
|
|
306
|
+
UiPathRuntimeEdge(
|
|
307
|
+
source=agent_name,
|
|
308
|
+
target=tool_name,
|
|
309
|
+
label="tool_call",
|
|
310
|
+
)
|
|
311
|
+
)
|
|
312
|
+
edges.append(
|
|
313
|
+
UiPathRuntimeEdge(
|
|
314
|
+
source=tool_name,
|
|
315
|
+
target=agent_name,
|
|
316
|
+
label="tool_result",
|
|
317
|
+
)
|
|
318
|
+
)
|
|
319
|
+
|
|
320
|
+
# Add handoff agents as nodes
|
|
321
|
+
handoffs = getattr(agent, "handoffs", None) or []
|
|
322
|
+
if handoffs:
|
|
323
|
+
for handoff_agent in handoffs:
|
|
324
|
+
handoff_name = getattr(handoff_agent, "name", None)
|
|
325
|
+
if handoff_name:
|
|
326
|
+
nodes.append(
|
|
327
|
+
UiPathRuntimeNode(
|
|
328
|
+
id=handoff_name,
|
|
329
|
+
name=handoff_name,
|
|
330
|
+
type="model",
|
|
331
|
+
subgraph=None, # Handoff agents are peers, not subgraphs
|
|
332
|
+
)
|
|
333
|
+
)
|
|
334
|
+
# Handoff edges
|
|
335
|
+
edges.append(
|
|
336
|
+
UiPathRuntimeEdge(
|
|
337
|
+
source=agent_name,
|
|
338
|
+
target=handoff_name,
|
|
339
|
+
label="handoff",
|
|
340
|
+
)
|
|
341
|
+
)
|
|
342
|
+
edges.append(
|
|
343
|
+
UiPathRuntimeEdge(
|
|
344
|
+
source=handoff_name,
|
|
345
|
+
target=agent_name,
|
|
346
|
+
label="handoff_complete",
|
|
347
|
+
)
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
# End node
|
|
351
|
+
nodes.append(
|
|
352
|
+
UiPathRuntimeNode(
|
|
353
|
+
id="__end__",
|
|
354
|
+
name="__end__",
|
|
355
|
+
type="__end__",
|
|
356
|
+
subgraph=None,
|
|
357
|
+
)
|
|
358
|
+
)
|
|
359
|
+
|
|
360
|
+
# Connect agent to end
|
|
361
|
+
edges.append(
|
|
362
|
+
UiPathRuntimeEdge(
|
|
363
|
+
source=agent_name,
|
|
364
|
+
target="__end__",
|
|
365
|
+
label="output",
|
|
366
|
+
)
|
|
367
|
+
)
|
|
368
|
+
|
|
369
|
+
return UiPathRuntimeGraph(nodes=nodes, edges=edges)
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
def _get_tool_name(tool: Any) -> str | None:
|
|
373
|
+
"""
|
|
374
|
+
Extract the name of a tool from various tool types.
|
|
375
|
+
|
|
376
|
+
Args:
|
|
377
|
+
tool: A tool object (could be a function, class, or tool instance)
|
|
378
|
+
|
|
379
|
+
Returns:
|
|
380
|
+
The tool name as a string, or None if it cannot be determined
|
|
381
|
+
"""
|
|
382
|
+
# Try common attributes for tool names
|
|
383
|
+
if hasattr(tool, "name"):
|
|
384
|
+
return str(tool.name)
|
|
385
|
+
if hasattr(tool, "__name__"):
|
|
386
|
+
return str(tool.__name__)
|
|
387
|
+
if hasattr(tool, "tool_name"):
|
|
388
|
+
return str(tool.tool_name)
|
|
389
|
+
|
|
390
|
+
# For class-based tools, try to get class name
|
|
391
|
+
if hasattr(tool, "__class__"):
|
|
392
|
+
class_name = tool.__class__.__name__
|
|
393
|
+
# Remove common suffixes like "Tool" for cleaner names
|
|
394
|
+
if class_name.endswith("Tool"):
|
|
395
|
+
return class_name[:-4].lower()
|
|
396
|
+
return class_name.lower()
|
|
397
|
+
|
|
398
|
+
return None
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
def _resolve_refs(
|
|
402
|
+
schema: dict[str, Any],
|
|
403
|
+
root: dict[str, Any] | None = None,
|
|
404
|
+
visited: set[str] | None = None,
|
|
405
|
+
) -> dict[str, Any]:
|
|
406
|
+
"""
|
|
407
|
+
Recursively resolves $ref references in a JSON schema.
|
|
408
|
+
|
|
409
|
+
Args:
|
|
410
|
+
schema: The schema dictionary to resolve
|
|
411
|
+
root: The root schema for reference resolution
|
|
412
|
+
visited: Set of visited references to detect circular dependencies
|
|
413
|
+
|
|
414
|
+
Returns:
|
|
415
|
+
Resolved schema dictionary
|
|
416
|
+
"""
|
|
417
|
+
if root is None:
|
|
418
|
+
root = schema
|
|
419
|
+
|
|
420
|
+
if visited is None:
|
|
421
|
+
visited = set()
|
|
422
|
+
|
|
423
|
+
if isinstance(schema, dict):
|
|
424
|
+
if "$ref" in schema:
|
|
425
|
+
ref_path = schema["$ref"]
|
|
426
|
+
|
|
427
|
+
if ref_path in visited:
|
|
428
|
+
# Circular dependency detected
|
|
429
|
+
return {
|
|
430
|
+
"type": "object",
|
|
431
|
+
"description": f"Circular reference to {ref_path}",
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
visited.add(ref_path)
|
|
435
|
+
|
|
436
|
+
# Resolve the reference - handle both #/definitions/ and #/$defs/ formats
|
|
437
|
+
ref_parts = ref_path.lstrip("#/").split("/")
|
|
438
|
+
ref_schema = root
|
|
439
|
+
for part in ref_parts:
|
|
440
|
+
ref_schema = ref_schema.get(part, {})
|
|
441
|
+
|
|
442
|
+
result = _resolve_refs(ref_schema, root, visited)
|
|
443
|
+
|
|
444
|
+
# Remove from visited after resolution
|
|
445
|
+
visited.discard(ref_path)
|
|
446
|
+
|
|
447
|
+
return result
|
|
448
|
+
|
|
449
|
+
return {k: _resolve_refs(v, root, visited) for k, v in schema.items()}
|
|
450
|
+
|
|
451
|
+
elif isinstance(schema, list):
|
|
452
|
+
return [_resolve_refs(item, root, visited) for item in schema]
|
|
453
|
+
|
|
454
|
+
return schema
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
def _process_nullable_types(properties: dict[str, Any]) -> dict[str, Any]:
|
|
458
|
+
"""
|
|
459
|
+
Process properties to handle nullable types correctly.
|
|
460
|
+
|
|
461
|
+
This matches the original implementation that adds "nullable": True
|
|
462
|
+
instead of simplifying the schema structure.
|
|
463
|
+
|
|
464
|
+
Args:
|
|
465
|
+
properties: The properties dictionary from a schema
|
|
466
|
+
|
|
467
|
+
Returns:
|
|
468
|
+
Processed properties with nullable types marked
|
|
469
|
+
"""
|
|
470
|
+
result = {}
|
|
471
|
+
for name, prop in properties.items():
|
|
472
|
+
if "anyOf" in prop:
|
|
473
|
+
types = [item.get("type") for item in prop["anyOf"] if "type" in item]
|
|
474
|
+
if "null" in types:
|
|
475
|
+
non_null_types = [t for t in types if t != "null"]
|
|
476
|
+
if len(non_null_types) == 1:
|
|
477
|
+
result[name] = {"type": non_null_types[0], "nullable": True}
|
|
478
|
+
else:
|
|
479
|
+
result[name] = {"type": non_null_types, "nullable": True}
|
|
480
|
+
else:
|
|
481
|
+
result[name] = prop
|
|
482
|
+
else:
|
|
483
|
+
result[name] = prop
|
|
484
|
+
return result
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
__all__ = [
|
|
488
|
+
"get_entrypoints_schema",
|
|
489
|
+
"get_agent_schema",
|
|
490
|
+
]
|