agentspan 0.0.3__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.
- agentspan/__init__.py +3 -0
- agentspan/agents/__init__.py +198 -0
- agentspan/agents/_internal/__init__.py +4 -0
- agentspan/agents/_internal/model_parser.py +85 -0
- agentspan/agents/_internal/provider_registry.py +60 -0
- agentspan/agents/_internal/schema_utils.py +141 -0
- agentspan/agents/agent.py +461 -0
- agentspan/agents/code_execution_config.py +243 -0
- agentspan/agents/code_executor.py +521 -0
- agentspan/agents/config_serializer.py +337 -0
- agentspan/agents/ext.py +265 -0
- agentspan/agents/frameworks/__init__.py +18 -0
- agentspan/agents/frameworks/serializer.py +335 -0
- agentspan/agents/guardrail.py +398 -0
- agentspan/agents/handoff.py +133 -0
- agentspan/agents/memory.py +109 -0
- agentspan/agents/result.py +517 -0
- agentspan/agents/run.py +393 -0
- agentspan/agents/runtime/__init__.py +9 -0
- agentspan/agents/runtime/_dispatch.py +223 -0
- agentspan/agents/runtime/config.py +116 -0
- agentspan/agents/runtime/http_client.py +214 -0
- agentspan/agents/runtime/mcp_discovery.py +162 -0
- agentspan/agents/runtime/runtime.py +2981 -0
- agentspan/agents/runtime/tool_registry.py +79 -0
- agentspan/agents/runtime/worker_manager.py +121 -0
- agentspan/agents/semantic_memory.py +253 -0
- agentspan/agents/termination.py +306 -0
- agentspan/agents/tool.py +633 -0
- agentspan/agents/tracing.py +246 -0
- agentspan-0.0.3.dist-info/METADATA +373 -0
- agentspan-0.0.3.dist-info/RECORD +34 -0
- agentspan-0.0.3.dist-info/WHEEL +5 -0
- agentspan-0.0.3.dist-info/top_level.txt +1 -0
agentspan/__init__.py
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
# Copyright (c) 2025 AgentSpan
|
|
2
|
+
# Licensed under the MIT License. See LICENSE file in the project root for details.
|
|
3
|
+
|
|
4
|
+
"""Conductor Agents SDK — durable, scalable, observable AI agents.
|
|
5
|
+
|
|
6
|
+
This is the public API surface. Import everything you need from here::
|
|
7
|
+
|
|
8
|
+
from agentspan.agents import Agent, AgentRuntime, tool
|
|
9
|
+
|
|
10
|
+
Quick start::
|
|
11
|
+
|
|
12
|
+
from agentspan.agents import Agent, AgentRuntime, tool
|
|
13
|
+
|
|
14
|
+
@tool
|
|
15
|
+
def get_weather(city: str) -> str:
|
|
16
|
+
\"\"\"Get current weather for a city.\"\"\"
|
|
17
|
+
return f"72F and sunny in {city}"
|
|
18
|
+
|
|
19
|
+
agent = Agent(name="weatherbot", model="openai/gpt-4o", tools=[get_weather])
|
|
20
|
+
|
|
21
|
+
with AgentRuntime() as runtime:
|
|
22
|
+
result = runtime.run(agent, "What's the weather in NYC?")
|
|
23
|
+
print(result.output)
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
# Core primitive
|
|
27
|
+
from agentspan.agents.agent import Agent, AgentDef, PromptTemplate, Strategy, agent
|
|
28
|
+
|
|
29
|
+
# Tool decorator and constructors
|
|
30
|
+
from agentspan.agents.tool import (
|
|
31
|
+
ToolContext,
|
|
32
|
+
ToolDef,
|
|
33
|
+
agent_tool,
|
|
34
|
+
audio_tool,
|
|
35
|
+
http_tool,
|
|
36
|
+
image_tool,
|
|
37
|
+
mcp_tool,
|
|
38
|
+
pdf_tool,
|
|
39
|
+
tool,
|
|
40
|
+
video_tool,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
# MCP discovery utilities
|
|
44
|
+
from agentspan.agents.runtime.mcp_discovery import clear_discovery_cache
|
|
45
|
+
|
|
46
|
+
# Execution API
|
|
47
|
+
from agentspan.agents.run import (
|
|
48
|
+
plan,
|
|
49
|
+
run,
|
|
50
|
+
run_async,
|
|
51
|
+
shutdown,
|
|
52
|
+
start,
|
|
53
|
+
start_async,
|
|
54
|
+
stream,
|
|
55
|
+
stream_async,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
# Runtime (for context manager and advanced usage)
|
|
59
|
+
from agentspan.agents.runtime.config import AgentConfig
|
|
60
|
+
from agentspan.agents.runtime.runtime import AgentRuntime
|
|
61
|
+
|
|
62
|
+
# Result types
|
|
63
|
+
from agentspan.agents.result import (
|
|
64
|
+
AgentEvent,
|
|
65
|
+
AgentHandle,
|
|
66
|
+
AgentResult,
|
|
67
|
+
AgentStatus,
|
|
68
|
+
AgentStream,
|
|
69
|
+
AsyncAgentStream,
|
|
70
|
+
EventType,
|
|
71
|
+
TokenUsage,
|
|
72
|
+
)
|
|
73
|
+
|
|
74
|
+
# Guardrails
|
|
75
|
+
from agentspan.agents.guardrail import (
|
|
76
|
+
Guardrail,
|
|
77
|
+
GuardrailDef,
|
|
78
|
+
GuardrailResult,
|
|
79
|
+
LLMGuardrail,
|
|
80
|
+
OnFail,
|
|
81
|
+
Position,
|
|
82
|
+
RegexGuardrail,
|
|
83
|
+
guardrail,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
# Termination conditions
|
|
87
|
+
from agentspan.agents.termination import (
|
|
88
|
+
MaxMessageTermination,
|
|
89
|
+
StopMessageTermination,
|
|
90
|
+
TerminationCondition,
|
|
91
|
+
TerminationResult,
|
|
92
|
+
TextMentionTermination,
|
|
93
|
+
TokenUsageTermination,
|
|
94
|
+
)
|
|
95
|
+
|
|
96
|
+
# Memory
|
|
97
|
+
from agentspan.agents.memory import ConversationMemory
|
|
98
|
+
from agentspan.agents.semantic_memory import MemoryEntry, MemoryStore, SemanticMemory
|
|
99
|
+
|
|
100
|
+
# Code execution
|
|
101
|
+
from agentspan.agents.code_execution_config import CodeExecutionConfig
|
|
102
|
+
from agentspan.agents.code_executor import (
|
|
103
|
+
CodeExecutor,
|
|
104
|
+
DockerCodeExecutor,
|
|
105
|
+
ExecutionResult,
|
|
106
|
+
JupyterCodeExecutor,
|
|
107
|
+
LocalCodeExecutor,
|
|
108
|
+
ServerlessCodeExecutor,
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
# Handoff conditions (for swarm strategy)
|
|
112
|
+
from agentspan.agents.handoff import HandoffCondition, OnCondition, OnTextMention, OnToolResult
|
|
113
|
+
|
|
114
|
+
# Extended agent types
|
|
115
|
+
from agentspan.agents.ext import GPTAssistantAgent, UserProxyAgent
|
|
116
|
+
|
|
117
|
+
# Tracing (optional — only activates if opentelemetry is installed)
|
|
118
|
+
from agentspan.agents.tracing import is_tracing_enabled
|
|
119
|
+
|
|
120
|
+
__all__ = [
|
|
121
|
+
# Core
|
|
122
|
+
"Agent",
|
|
123
|
+
"AgentDef",
|
|
124
|
+
"PromptTemplate",
|
|
125
|
+
"Strategy",
|
|
126
|
+
"agent",
|
|
127
|
+
"AgentRuntime",
|
|
128
|
+
"AgentConfig",
|
|
129
|
+
# Extended agent types
|
|
130
|
+
"UserProxyAgent",
|
|
131
|
+
"GPTAssistantAgent",
|
|
132
|
+
# Tools
|
|
133
|
+
"tool",
|
|
134
|
+
"ToolDef",
|
|
135
|
+
"ToolContext",
|
|
136
|
+
"agent_tool",
|
|
137
|
+
"http_tool",
|
|
138
|
+
"mcp_tool",
|
|
139
|
+
"image_tool",
|
|
140
|
+
"audio_tool",
|
|
141
|
+
"video_tool",
|
|
142
|
+
"pdf_tool",
|
|
143
|
+
"clear_discovery_cache",
|
|
144
|
+
# Convenience execution (uses a singleton AgentRuntime)
|
|
145
|
+
"plan",
|
|
146
|
+
"run",
|
|
147
|
+
"run_async",
|
|
148
|
+
"shutdown",
|
|
149
|
+
"start",
|
|
150
|
+
"start_async",
|
|
151
|
+
"stream",
|
|
152
|
+
"stream_async",
|
|
153
|
+
# Results
|
|
154
|
+
"AgentResult",
|
|
155
|
+
"AgentHandle",
|
|
156
|
+
"AgentStatus",
|
|
157
|
+
"AgentStream",
|
|
158
|
+
"AsyncAgentStream",
|
|
159
|
+
"AgentEvent",
|
|
160
|
+
"EventType",
|
|
161
|
+
"TokenUsage",
|
|
162
|
+
# Guardrails
|
|
163
|
+
"guardrail",
|
|
164
|
+
"Guardrail",
|
|
165
|
+
"GuardrailDef",
|
|
166
|
+
"GuardrailResult",
|
|
167
|
+
"OnFail",
|
|
168
|
+
"Position",
|
|
169
|
+
"RegexGuardrail",
|
|
170
|
+
"LLMGuardrail",
|
|
171
|
+
# Termination conditions
|
|
172
|
+
"TerminationCondition",
|
|
173
|
+
"TerminationResult",
|
|
174
|
+
"TextMentionTermination",
|
|
175
|
+
"StopMessageTermination",
|
|
176
|
+
"MaxMessageTermination",
|
|
177
|
+
"TokenUsageTermination",
|
|
178
|
+
# Memory
|
|
179
|
+
"ConversationMemory",
|
|
180
|
+
"SemanticMemory",
|
|
181
|
+
"MemoryStore",
|
|
182
|
+
"MemoryEntry",
|
|
183
|
+
# Code execution
|
|
184
|
+
"CodeExecutionConfig",
|
|
185
|
+
"CodeExecutor",
|
|
186
|
+
"LocalCodeExecutor",
|
|
187
|
+
"DockerCodeExecutor",
|
|
188
|
+
"JupyterCodeExecutor",
|
|
189
|
+
"ServerlessCodeExecutor",
|
|
190
|
+
"ExecutionResult",
|
|
191
|
+
# Handoff conditions
|
|
192
|
+
"HandoffCondition",
|
|
193
|
+
"OnToolResult",
|
|
194
|
+
"OnTextMention",
|
|
195
|
+
"OnCondition",
|
|
196
|
+
# Tracing
|
|
197
|
+
"is_tracing_enabled",
|
|
198
|
+
]
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
# Copyright (c) 2025 AgentSpan
|
|
2
|
+
# Licensed under the MIT License. See LICENSE file in the project root for details.
|
|
3
|
+
|
|
4
|
+
"""Parse ``"provider/model"`` strings into (provider, model) tuples.
|
|
5
|
+
|
|
6
|
+
Conductor's :class:`LlmChatComplete` requires separate ``llm_provider`` and
|
|
7
|
+
``model`` arguments. This module handles the unified format used by the
|
|
8
|
+
agents SDK.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
from dataclasses import dataclass
|
|
14
|
+
from typing import Optional
|
|
15
|
+
|
|
16
|
+
# Known Conductor LLM provider names.
|
|
17
|
+
KNOWN_PROVIDERS = frozenset({
|
|
18
|
+
"openai",
|
|
19
|
+
"azure_openai",
|
|
20
|
+
"anthropic",
|
|
21
|
+
"google_gemini",
|
|
22
|
+
"google_vertex_ai",
|
|
23
|
+
"aws_bedrock",
|
|
24
|
+
"cohere",
|
|
25
|
+
"mistral",
|
|
26
|
+
"groq",
|
|
27
|
+
"perplexity",
|
|
28
|
+
"hugging_face",
|
|
29
|
+
"deepseek",
|
|
30
|
+
})
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
@dataclass(frozen=True)
|
|
34
|
+
class ParsedModel:
|
|
35
|
+
"""Result of parsing a ``"provider/model"`` string.
|
|
36
|
+
|
|
37
|
+
Attributes:
|
|
38
|
+
provider: The Conductor integration name (e.g. ``"openai"``).
|
|
39
|
+
model: The model identifier (e.g. ``"gpt-4o"``).
|
|
40
|
+
"""
|
|
41
|
+
|
|
42
|
+
provider: str
|
|
43
|
+
model: str
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def parse_model(model_string: str) -> ParsedModel:
|
|
47
|
+
"""Parse a ``"provider/model"`` string.
|
|
48
|
+
|
|
49
|
+
Args:
|
|
50
|
+
model_string: A string in ``"provider/model"`` format, e.g.
|
|
51
|
+
``"openai/gpt-4o"`` or ``"anthropic/claude-sonnet-4-20250514"``.
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
A :class:`ParsedModel` with separate ``provider`` and ``model`` fields.
|
|
55
|
+
|
|
56
|
+
Raises:
|
|
57
|
+
ValueError: If the string is not in the expected format.
|
|
58
|
+
|
|
59
|
+
Examples::
|
|
60
|
+
|
|
61
|
+
>>> parse_model("openai/gpt-4o")
|
|
62
|
+
ParsedModel(provider='openai', model='gpt-4o')
|
|
63
|
+
|
|
64
|
+
>>> parse_model("anthropic/claude-sonnet-4-20250514")
|
|
65
|
+
ParsedModel(provider='anthropic', model='claude-sonnet-4-20250514')
|
|
66
|
+
|
|
67
|
+
>>> parse_model("azure_openai/gpt-4o")
|
|
68
|
+
ParsedModel(provider='azure_openai', model='gpt-4o')
|
|
69
|
+
"""
|
|
70
|
+
if "/" not in model_string:
|
|
71
|
+
raise ValueError(
|
|
72
|
+
f"Invalid model format {model_string!r}. "
|
|
73
|
+
"Expected 'provider/model' (e.g. 'openai/gpt-4o')"
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
parts = model_string.split("/", 1)
|
|
77
|
+
provider = parts[0].strip()
|
|
78
|
+
model = parts[1].strip()
|
|
79
|
+
|
|
80
|
+
if not provider:
|
|
81
|
+
raise ValueError(f"Empty provider in model string {model_string!r}")
|
|
82
|
+
if not model:
|
|
83
|
+
raise ValueError(f"Empty model name in model string {model_string!r}")
|
|
84
|
+
|
|
85
|
+
return ParsedModel(provider=provider, model=model)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Copyright (c) 2025 AgentSpan
|
|
2
|
+
# Licensed under the MIT License. See LICENSE file in the project root for details.
|
|
3
|
+
|
|
4
|
+
"""Provider registry — metadata for auto-registering LLM integrations.
|
|
5
|
+
|
|
6
|
+
Maps known LLM provider names (as used in ``"provider/model"`` strings) to the
|
|
7
|
+
configuration required to create integrations on the Conductor server.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
from dataclasses import dataclass
|
|
13
|
+
from typing import Dict, Optional
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@dataclass(frozen=True)
|
|
17
|
+
class ProviderSpec:
|
|
18
|
+
"""Metadata for an LLM provider integration.
|
|
19
|
+
|
|
20
|
+
Attributes:
|
|
21
|
+
name: SDK provider name (matches :data:`model_parser.KNOWN_PROVIDERS`).
|
|
22
|
+
integration_type: Conductor server ``type`` field for the integration.
|
|
23
|
+
display_name: Human-readable provider name.
|
|
24
|
+
api_key_env: Environment variable that holds the provider's API key.
|
|
25
|
+
"""
|
|
26
|
+
|
|
27
|
+
name: str
|
|
28
|
+
integration_type: str
|
|
29
|
+
display_name: str
|
|
30
|
+
api_key_env: str
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
PROVIDER_REGISTRY: Dict[str, ProviderSpec] = {
|
|
34
|
+
"openai": ProviderSpec(
|
|
35
|
+
name="openai",
|
|
36
|
+
integration_type="openai",
|
|
37
|
+
display_name="OpenAI",
|
|
38
|
+
api_key_env="OPENAI_API_KEY",
|
|
39
|
+
),
|
|
40
|
+
"anthropic": ProviderSpec(
|
|
41
|
+
name="anthropic",
|
|
42
|
+
integration_type="anthropic",
|
|
43
|
+
display_name="Anthropic",
|
|
44
|
+
api_key_env="ANTHROPIC_API_KEY",
|
|
45
|
+
),
|
|
46
|
+
"google_gemini": ProviderSpec(
|
|
47
|
+
name="google_gemini",
|
|
48
|
+
integration_type="google_gemini",
|
|
49
|
+
display_name="Google Gemini",
|
|
50
|
+
api_key_env="GOOGLE_GEMINI_API_KEY",
|
|
51
|
+
),
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
def get_provider_spec(provider_name: str) -> Optional[ProviderSpec]:
|
|
56
|
+
"""Look up a provider spec by name.
|
|
57
|
+
|
|
58
|
+
Returns ``None`` if the provider is not in the registry.
|
|
59
|
+
"""
|
|
60
|
+
return PROVIDER_REGISTRY.get(provider_name)
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Copyright (c) 2025 AgentSpan
|
|
2
|
+
# Licensed under the MIT License. See LICENSE file in the project root for details.
|
|
3
|
+
|
|
4
|
+
"""JSON Schema generation from Python type hints, Pydantic models, and dataclasses.
|
|
5
|
+
|
|
6
|
+
Wraps ``conductor.client.automator.json_schema_generator`` and adds support
|
|
7
|
+
for Pydantic ``BaseModel`` classes.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from __future__ import annotations
|
|
11
|
+
|
|
12
|
+
import inspect
|
|
13
|
+
from typing import Any, Callable, Dict, Optional, get_type_hints
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# ── Type-hint → JSON Schema mapping ────────────────────────────────────
|
|
17
|
+
|
|
18
|
+
_PYTHON_TYPE_TO_JSON = {
|
|
19
|
+
str: {"type": "string"},
|
|
20
|
+
int: {"type": "integer"},
|
|
21
|
+
float: {"type": "number"},
|
|
22
|
+
bool: {"type": "boolean"},
|
|
23
|
+
list: {"type": "array"},
|
|
24
|
+
dict: {"type": "object"},
|
|
25
|
+
type(None): {"type": "null"},
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _type_to_json_schema(annotation: Any) -> Dict[str, Any]:
|
|
30
|
+
"""Convert a Python type annotation to a JSON Schema fragment."""
|
|
31
|
+
if annotation is inspect.Parameter.empty or annotation is Any:
|
|
32
|
+
return {}
|
|
33
|
+
|
|
34
|
+
# Direct mapping
|
|
35
|
+
if annotation in _PYTHON_TYPE_TO_JSON:
|
|
36
|
+
return dict(_PYTHON_TYPE_TO_JSON[annotation])
|
|
37
|
+
|
|
38
|
+
# Handle Optional[X] (Union[X, None])
|
|
39
|
+
origin = getattr(annotation, "__origin__", None)
|
|
40
|
+
args = getattr(annotation, "__args__", ())
|
|
41
|
+
|
|
42
|
+
if origin is type(None):
|
|
43
|
+
return {"type": "null"}
|
|
44
|
+
|
|
45
|
+
# Union types (including Optional)
|
|
46
|
+
import typing
|
|
47
|
+
if origin is getattr(typing, "Union", None):
|
|
48
|
+
non_none = [a for a in args if a is not type(None)]
|
|
49
|
+
if len(non_none) == 1:
|
|
50
|
+
return _type_to_json_schema(non_none[0])
|
|
51
|
+
return {}
|
|
52
|
+
|
|
53
|
+
# List[X]
|
|
54
|
+
if origin is list:
|
|
55
|
+
schema: Dict[str, Any] = {"type": "array"}
|
|
56
|
+
if args:
|
|
57
|
+
schema["items"] = _type_to_json_schema(args[0])
|
|
58
|
+
return schema
|
|
59
|
+
|
|
60
|
+
# Dict[str, X]
|
|
61
|
+
if origin is dict:
|
|
62
|
+
schema = {"type": "object"}
|
|
63
|
+
if len(args) >= 2:
|
|
64
|
+
schema["additionalProperties"] = _type_to_json_schema(args[1])
|
|
65
|
+
return schema
|
|
66
|
+
|
|
67
|
+
return {}
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# ── Function → JSON Schema ─────────────────────────────────────────────
|
|
71
|
+
|
|
72
|
+
def schema_from_function(func: Callable[..., Any]) -> Dict[str, Any]:
|
|
73
|
+
"""Generate input/output JSON Schemas from a Python function's signature.
|
|
74
|
+
|
|
75
|
+
Uses type hints and docstring to produce schemas compatible with
|
|
76
|
+
Conductor's ``ToolSpec.input_schema``.
|
|
77
|
+
|
|
78
|
+
Args:
|
|
79
|
+
func: The function to analyse.
|
|
80
|
+
|
|
81
|
+
Returns:
|
|
82
|
+
A dict with ``"input"`` and ``"output"`` keys, each containing a
|
|
83
|
+
JSON Schema dict.
|
|
84
|
+
"""
|
|
85
|
+
sig = inspect.signature(func)
|
|
86
|
+
try:
|
|
87
|
+
hints = get_type_hints(func)
|
|
88
|
+
except Exception:
|
|
89
|
+
hints = {}
|
|
90
|
+
|
|
91
|
+
# Build input schema
|
|
92
|
+
properties: Dict[str, Any] = {}
|
|
93
|
+
required: list[str] = []
|
|
94
|
+
|
|
95
|
+
for name, param in sig.parameters.items():
|
|
96
|
+
if name in ("self", "cls", "context"):
|
|
97
|
+
continue
|
|
98
|
+
|
|
99
|
+
prop = _type_to_json_schema(hints.get(name, param.annotation))
|
|
100
|
+
if not prop:
|
|
101
|
+
prop = {}
|
|
102
|
+
|
|
103
|
+
# Use docstring for parameter descriptions (simple extraction)
|
|
104
|
+
properties[name] = prop
|
|
105
|
+
|
|
106
|
+
if param.default is inspect.Parameter.empty:
|
|
107
|
+
required.append(name)
|
|
108
|
+
|
|
109
|
+
input_schema: Dict[str, Any] = {
|
|
110
|
+
"type": "object",
|
|
111
|
+
"properties": properties,
|
|
112
|
+
}
|
|
113
|
+
if required:
|
|
114
|
+
input_schema["required"] = required
|
|
115
|
+
|
|
116
|
+
# Build output schema
|
|
117
|
+
return_type = hints.get("return", sig.return_annotation)
|
|
118
|
+
output_schema = _type_to_json_schema(return_type) if return_type is not inspect.Parameter.empty else {}
|
|
119
|
+
|
|
120
|
+
return {"input": input_schema, "output": output_schema}
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def schema_from_pydantic(model_class: type) -> Dict[str, Any]:
|
|
124
|
+
"""Generate a JSON Schema from a Pydantic ``BaseModel`` class.
|
|
125
|
+
|
|
126
|
+
Args:
|
|
127
|
+
model_class: A Pydantic ``BaseModel`` subclass.
|
|
128
|
+
|
|
129
|
+
Returns:
|
|
130
|
+
The JSON Schema dict produced by Pydantic's ``model_json_schema()``.
|
|
131
|
+
|
|
132
|
+
Raises:
|
|
133
|
+
TypeError: If *model_class* is not a Pydantic ``BaseModel``.
|
|
134
|
+
"""
|
|
135
|
+
if hasattr(model_class, "model_json_schema"):
|
|
136
|
+
# Pydantic v2
|
|
137
|
+
return model_class.model_json_schema()
|
|
138
|
+
elif hasattr(model_class, "schema"):
|
|
139
|
+
# Pydantic v1
|
|
140
|
+
return model_class.schema()
|
|
141
|
+
raise TypeError(f"{model_class} is not a Pydantic BaseModel")
|