alloy-runtime-types 0.1.0__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.
- alloy_runtime_types-0.1.0/PKG-INFO +35 -0
- alloy_runtime_types-0.1.0/README.md +18 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/__init__.py +1 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/__init__.py +1 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/admin.py +25 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/agents.py +362 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/api_keys.py +124 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/audio.py +9 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/auth.py +132 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/billing.py +141 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/content.py +245 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/credentials.py +277 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/generation.py +644 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/knowledge.py +1221 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/mcp_servers.py +258 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/messages.py +80 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/models.py +54 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/organization_credentials.py +95 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/organizations.py +30 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/pipeline.py +336 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/pipeline_costs.py +108 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/render.py +54 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/schedule.py +446 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/schemas.py +194 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/sessions.py +197 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/structured_filter.py +70 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/tags.py +101 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/templates.py +273 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/tool_configs.py +120 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/tools.py +24 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/dtos/users.py +70 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/enums/__init__.py +1 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/enums/agent_enums.py +12 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/enums/api_key_scope.py +33 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/enums/content_enums.py +24 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/enums/member_role.py +12 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/enums/ownership_scope.py +9 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/enums/provider.py +102 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/enums/schema_enums.py +8 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/enums/template_enums.py +19 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/enums/tool_service.py +50 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/parsing/__init__.py +0 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types/parsing/filter_parser.py +49 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types.egg-info/PKG-INFO +35 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types.egg-info/SOURCES.txt +52 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types.egg-info/dependency_links.txt +1 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types.egg-info/requires.txt +1 -0
- alloy_runtime_types-0.1.0/alloy_runtime_types.egg-info/top_level.txt +1 -0
- alloy_runtime_types-0.1.0/pyproject.toml +43 -0
- alloy_runtime_types-0.1.0/setup.cfg +4 -0
- alloy_runtime_types-0.1.0/tests/test_api_key_dto.py +232 -0
- alloy_runtime_types-0.1.0/tests/test_audio_dto.py +48 -0
- alloy_runtime_types-0.1.0/tests/test_mcp_servers_dto.py +337 -0
- alloy_runtime_types-0.1.0/tests/test_pipeline_dto.py +39 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: alloy-runtime-types
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Type definitions and DTOs for Alloy Runtime
|
|
5
|
+
Author-email: Grant Jordan <gjordan1997@gmail.com>
|
|
6
|
+
Project-URL: Repository, https://github.com/alloy-runtime/alloy-runtime
|
|
7
|
+
Project-URL: Issues, https://github.com/alloy-runtime/alloy-runtime/issues
|
|
8
|
+
Keywords: alloy,api,dto,python,types
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
13
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
14
|
+
Requires-Python: >=3.13
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
Requires-Dist: pydantic>=2.12.3
|
|
17
|
+
|
|
18
|
+
# alloy-runtime-types
|
|
19
|
+
|
|
20
|
+
Shared DTOs, enums, and parsing helpers for Alloy Runtime Python clients.
|
|
21
|
+
|
|
22
|
+
## Install
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
pip install alloy-runtime-types
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## What it includes
|
|
29
|
+
|
|
30
|
+
- Pydantic request and response models used by the SDK and CLI.
|
|
31
|
+
- Shared enums for ownership scope, providers, and tool metadata.
|
|
32
|
+
- Parsing helpers used by higher-level packages.
|
|
33
|
+
|
|
34
|
+
This package is published separately so `alloy-runtime-sdk` and `alloy-runtime-cli`
|
|
35
|
+
can be installed cleanly from PyPI without a workspace checkout.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# alloy-runtime-types
|
|
2
|
+
|
|
3
|
+
Shared DTOs, enums, and parsing helpers for Alloy Runtime Python clients.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install alloy-runtime-types
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## What it includes
|
|
12
|
+
|
|
13
|
+
- Pydantic request and response models used by the SDK and CLI.
|
|
14
|
+
- Shared enums for ownership scope, providers, and tool metadata.
|
|
15
|
+
- Parsing helpers used by higher-level packages.
|
|
16
|
+
|
|
17
|
+
This package is published separately so `alloy-runtime-sdk` and `alloy-runtime-cli`
|
|
18
|
+
can be installed cleanly from PyPI without a workspace checkout.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Empty per project convention - import directly from submodules
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Empty per project convention - import directly from submodules
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""DTOs for admin operations."""
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class SyncModelsRequest(BaseModel):
|
|
7
|
+
"""Request to sync AI models from external providers."""
|
|
8
|
+
|
|
9
|
+
pass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ProviderSyncResult(BaseModel):
|
|
13
|
+
"""Results from syncing a single provider source."""
|
|
14
|
+
|
|
15
|
+
models_synced: int
|
|
16
|
+
providers_synced: int
|
|
17
|
+
error: str | None = None
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class SyncModelsResponse(BaseModel):
|
|
21
|
+
"""Aggregated sync results from all provider sources."""
|
|
22
|
+
|
|
23
|
+
total_models_synced: int
|
|
24
|
+
total_providers_synced: int
|
|
25
|
+
by_source: dict[str, ProviderSyncResult]
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
"""DTOs for agent operations."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from typing import Any
|
|
5
|
+
from uuid import UUID
|
|
6
|
+
|
|
7
|
+
from pydantic import BaseModel, Field, model_validator
|
|
8
|
+
from typing_extensions import Self
|
|
9
|
+
|
|
10
|
+
from alloy_runtime_types.dtos.generation import GenerationParameters
|
|
11
|
+
from alloy_runtime_types.dtos.mcp_servers import (
|
|
12
|
+
AgentMCPServerConfig,
|
|
13
|
+
AgentMCPServerResponse,
|
|
14
|
+
)
|
|
15
|
+
from alloy_runtime_types.enums.ownership_scope import OwnershipScope
|
|
16
|
+
from alloy_runtime_types.enums.provider import Provider
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class AgentModelConfig(BaseModel):
|
|
20
|
+
"""Configuration for an agent model."""
|
|
21
|
+
|
|
22
|
+
provider_key: Provider = Field(min_length=1)
|
|
23
|
+
provider_model_name: str = Field(min_length=1)
|
|
24
|
+
preference_order: int = Field(default=0, ge=0)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class AgentToolConfig(BaseModel):
|
|
28
|
+
"""Configuration for an agent tool.
|
|
29
|
+
|
|
30
|
+
Configuration can come from either:
|
|
31
|
+
- Inline config (config field): Direct configuration dict
|
|
32
|
+
- Config reference (tool_config_id): Reference to a reusable ToolConfig
|
|
33
|
+
|
|
34
|
+
These are mutually exclusive - at most one can be set.
|
|
35
|
+
|
|
36
|
+
The tool_alias enables multiple instances of the same tool per agent.
|
|
37
|
+
It defaults to tool_id when not provided and is used as the OpenAI function name.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
tool_id: str = Field(min_length=1)
|
|
41
|
+
tool_alias: str | None = Field(
|
|
42
|
+
default=None,
|
|
43
|
+
min_length=1,
|
|
44
|
+
description="Unique alias for this tool instance within the agent. "
|
|
45
|
+
"Used as the OpenAI function name. Defaults to tool_id if not provided.",
|
|
46
|
+
)
|
|
47
|
+
org_credential_id: UUID | None = None
|
|
48
|
+
is_enabled: bool = True
|
|
49
|
+
tool_order: int = Field(default=0, ge=0)
|
|
50
|
+
config: dict[str, Any] | None = Field(
|
|
51
|
+
default=None,
|
|
52
|
+
description="Inline tool configuration. Validated against tool's parameter_schema.",
|
|
53
|
+
)
|
|
54
|
+
tool_config_id: UUID | None = Field(
|
|
55
|
+
default=None,
|
|
56
|
+
description="Reference to a reusable ToolConfig. Mutually exclusive with config.",
|
|
57
|
+
)
|
|
58
|
+
llm_instruction: str | None = Field(
|
|
59
|
+
default=None,
|
|
60
|
+
description="Optional instruction appended to tool description for LLM. "
|
|
61
|
+
"Provides per-agent hints about when/how to use this tool.",
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
@model_validator(mode="after")
|
|
65
|
+
def validate_config_exclusivity(self) -> Self:
|
|
66
|
+
"""Ensure config and tool_config_id are mutually exclusive."""
|
|
67
|
+
if self.config is not None and self.tool_config_id is not None:
|
|
68
|
+
raise ValueError(
|
|
69
|
+
"Cannot specify both config and tool_config_id. Provide one or neither."
|
|
70
|
+
)
|
|
71
|
+
return self
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def effective_alias(self) -> str:
|
|
75
|
+
"""Return tool_alias if set, otherwise tool_id."""
|
|
76
|
+
return self.tool_alias if self.tool_alias else self.tool_id
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class CreateAgentRequest(BaseModel):
|
|
80
|
+
"""Request to create a new agent."""
|
|
81
|
+
|
|
82
|
+
name: str = Field(min_length=1)
|
|
83
|
+
models: list[AgentModelConfig] = Field(min_length=1)
|
|
84
|
+
tags: list[str] = Field(
|
|
85
|
+
default_factory=list,
|
|
86
|
+
description="List of tag paths to associate with this agent. Required for user and organization scoped agents. Must be empty for global agents.",
|
|
87
|
+
)
|
|
88
|
+
scope: OwnershipScope = Field(default=OwnershipScope.USER)
|
|
89
|
+
base_agent_id: UUID | None = None
|
|
90
|
+
description: str | None = None
|
|
91
|
+
system_instruction_template: str | UUID | None = Field(
|
|
92
|
+
default=None,
|
|
93
|
+
description="System instruction template identifier - can be UUID or template name. "
|
|
94
|
+
"Names are resolved with priority: user-owned > org-owned > global.",
|
|
95
|
+
)
|
|
96
|
+
system_instruction_version_id: UUID | None = None
|
|
97
|
+
input_schema_id: UUID | None = None
|
|
98
|
+
output_schema_id: UUID | None = None
|
|
99
|
+
output_schema: dict[str, Any] | None = None
|
|
100
|
+
default_request_headers: dict[str, str] | None = None
|
|
101
|
+
generation_params: GenerationParameters | None = Field(
|
|
102
|
+
default=None,
|
|
103
|
+
description="Default generation parameters for this agent",
|
|
104
|
+
)
|
|
105
|
+
tools: list[AgentToolConfig] | None = None
|
|
106
|
+
mcp_servers: list[AgentMCPServerConfig] | None = None
|
|
107
|
+
|
|
108
|
+
@model_validator(mode="after")
|
|
109
|
+
def validate_output_schema_exclusivity(self) -> Self:
|
|
110
|
+
"""Ensure output_schema_id and output_schema are mutually exclusive."""
|
|
111
|
+
if self.output_schema_id is not None and self.output_schema is not None:
|
|
112
|
+
raise ValueError(
|
|
113
|
+
"Cannot specify both output_schema_id and output_schema. "
|
|
114
|
+
"Provide one or neither."
|
|
115
|
+
)
|
|
116
|
+
return self
|
|
117
|
+
|
|
118
|
+
@model_validator(mode="after")
|
|
119
|
+
def validate_tool_alias_uniqueness(self) -> Self:
|
|
120
|
+
"""Ensure tool_alias is unique within the tools list."""
|
|
121
|
+
if self.tools:
|
|
122
|
+
aliases = [t.effective_alias for t in self.tools]
|
|
123
|
+
if len(aliases) != len(set(aliases)):
|
|
124
|
+
raise ValueError(
|
|
125
|
+
"Each tool must have a unique tool_alias. "
|
|
126
|
+
"Duplicate aliases found in tools list."
|
|
127
|
+
)
|
|
128
|
+
return self
|
|
129
|
+
|
|
130
|
+
@model_validator(mode="after")
|
|
131
|
+
def validate_mcp_server_id_uniqueness(self) -> Self:
|
|
132
|
+
"""Ensure mcp_server_id is unique within the mcp_servers list."""
|
|
133
|
+
if self.mcp_servers:
|
|
134
|
+
ids = [m.mcp_server_id for m in self.mcp_servers]
|
|
135
|
+
if len(ids) != len(set(ids)):
|
|
136
|
+
raise ValueError(
|
|
137
|
+
"Duplicate mcp_server_id found in mcp_servers list. "
|
|
138
|
+
"Each MCP server can only be attached once."
|
|
139
|
+
)
|
|
140
|
+
return self
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
class AgentModelResponse(BaseModel):
|
|
144
|
+
"""Response model for agent model configuration."""
|
|
145
|
+
|
|
146
|
+
agent_id: UUID
|
|
147
|
+
provider_key: Provider
|
|
148
|
+
provider_model_name: str
|
|
149
|
+
preference_order: int
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
class AgentToolResponse(BaseModel):
|
|
153
|
+
"""Response model for agent tool configuration."""
|
|
154
|
+
|
|
155
|
+
agent_id: UUID
|
|
156
|
+
tool_alias: str = Field(description="Unique alias for this tool within the agent")
|
|
157
|
+
tool_id: str = Field(description="Tool implementation ID (references ai.tools.id)")
|
|
158
|
+
org_credential_id: UUID | None
|
|
159
|
+
is_enabled: bool
|
|
160
|
+
tool_order: int
|
|
161
|
+
config: dict[str, Any] | None = None
|
|
162
|
+
tool_config_id: UUID | None = None
|
|
163
|
+
tool_config_name: str | None = Field(
|
|
164
|
+
default=None,
|
|
165
|
+
description="Name of the referenced ToolConfig (convenience field for display)",
|
|
166
|
+
)
|
|
167
|
+
llm_instruction: str | None = Field(
|
|
168
|
+
default=None,
|
|
169
|
+
description="Optional instruction appended to tool description for LLM",
|
|
170
|
+
)
|
|
171
|
+
created_at: datetime
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
class AgentTagResponse(BaseModel):
|
|
175
|
+
"""Response model for agent tag."""
|
|
176
|
+
|
|
177
|
+
tag_id: UUID
|
|
178
|
+
tag_path: str
|
|
179
|
+
display_name: str
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
class CreateAgentResponse(BaseModel):
|
|
183
|
+
"""Response after creating an agent."""
|
|
184
|
+
|
|
185
|
+
id: UUID
|
|
186
|
+
name: str
|
|
187
|
+
organization_id: UUID | None
|
|
188
|
+
user_id: UUID | None
|
|
189
|
+
base_agent_id: UUID | None
|
|
190
|
+
description: str | None
|
|
191
|
+
system_instruction_version_id: UUID | None
|
|
192
|
+
input_schema_id: UUID | None
|
|
193
|
+
output_schema_id: UUID | None
|
|
194
|
+
default_request_headers: dict[str, str] | None
|
|
195
|
+
generation_params: GenerationParameters | None = None
|
|
196
|
+
created_at: datetime
|
|
197
|
+
updated_at: datetime
|
|
198
|
+
models: list[AgentModelResponse]
|
|
199
|
+
tools: list[AgentToolResponse]
|
|
200
|
+
mcp_servers: list[AgentMCPServerResponse] = []
|
|
201
|
+
tags: list[AgentTagResponse]
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class UpdateAgentRequest(BaseModel):
|
|
205
|
+
"""Request to update an existing agent.
|
|
206
|
+
|
|
207
|
+
All fields are optional - None means no change to that field.
|
|
208
|
+
"""
|
|
209
|
+
|
|
210
|
+
name: str | None = Field(default=None, min_length=1)
|
|
211
|
+
description: str | None = None
|
|
212
|
+
models: list[AgentModelConfig] | None = None
|
|
213
|
+
tags: list[str] | None = Field(
|
|
214
|
+
default=None,
|
|
215
|
+
description="List of tag paths to associate with this agent. If provided, replaces all existing tags.",
|
|
216
|
+
)
|
|
217
|
+
system_instruction_template: str | UUID | None = Field(
|
|
218
|
+
default=None,
|
|
219
|
+
description="System instruction template identifier - can be UUID or template name. "
|
|
220
|
+
"Names are resolved with priority: user-owned > org-owned > global.",
|
|
221
|
+
)
|
|
222
|
+
system_instruction_version_id: UUID | None = None
|
|
223
|
+
input_schema_id: UUID | None = None
|
|
224
|
+
output_schema_id: UUID | None = None
|
|
225
|
+
output_schema: dict[str, Any] | None = None
|
|
226
|
+
default_request_headers: dict[str, str] | None = None
|
|
227
|
+
generation_params: GenerationParameters | None = Field(
|
|
228
|
+
default=None,
|
|
229
|
+
description="Default generation parameters for this agent",
|
|
230
|
+
)
|
|
231
|
+
tools: list[AgentToolConfig] | None = None
|
|
232
|
+
mcp_servers: list[AgentMCPServerConfig] | None = None
|
|
233
|
+
|
|
234
|
+
@model_validator(mode="after")
|
|
235
|
+
def validate_output_schema_exclusivity(self) -> Self:
|
|
236
|
+
"""Ensure output_schema_id and output_schema are mutually exclusive."""
|
|
237
|
+
if self.output_schema_id is not None and self.output_schema is not None:
|
|
238
|
+
raise ValueError(
|
|
239
|
+
"Cannot specify both output_schema_id and output_schema. "
|
|
240
|
+
"Provide one or neither."
|
|
241
|
+
)
|
|
242
|
+
return self
|
|
243
|
+
|
|
244
|
+
@model_validator(mode="after")
|
|
245
|
+
def validate_tool_alias_uniqueness(self) -> Self:
|
|
246
|
+
"""Ensure tool_alias is unique within the tools list."""
|
|
247
|
+
if self.tools:
|
|
248
|
+
aliases = [t.effective_alias for t in self.tools]
|
|
249
|
+
if len(aliases) != len(set(aliases)):
|
|
250
|
+
raise ValueError(
|
|
251
|
+
"Each tool must have a unique tool_alias. "
|
|
252
|
+
"Duplicate aliases found in tools list."
|
|
253
|
+
)
|
|
254
|
+
return self
|
|
255
|
+
|
|
256
|
+
@model_validator(mode="after")
|
|
257
|
+
def validate_mcp_server_id_uniqueness(self) -> Self:
|
|
258
|
+
"""Ensure mcp_server_id is unique within the mcp_servers list."""
|
|
259
|
+
if self.mcp_servers:
|
|
260
|
+
ids = [m.mcp_server_id for m in self.mcp_servers]
|
|
261
|
+
if len(ids) != len(set(ids)):
|
|
262
|
+
raise ValueError(
|
|
263
|
+
"Duplicate mcp_server_id found in mcp_servers list. "
|
|
264
|
+
"Each MCP server can only be attached once."
|
|
265
|
+
)
|
|
266
|
+
return self
|
|
267
|
+
|
|
268
|
+
|
|
269
|
+
# Response type alias - update returns same structure as create
|
|
270
|
+
UpdateAgentResponse = CreateAgentResponse
|
|
271
|
+
|
|
272
|
+
|
|
273
|
+
# ============================================================================
|
|
274
|
+
# List Agents DTOs
|
|
275
|
+
# ============================================================================
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
class AgentSummary(BaseModel):
|
|
279
|
+
"""Summary of an agent for list responses."""
|
|
280
|
+
|
|
281
|
+
id: UUID
|
|
282
|
+
name: str
|
|
283
|
+
description: str | None
|
|
284
|
+
organization_id: UUID | None
|
|
285
|
+
user_id: UUID | None
|
|
286
|
+
model_count: int
|
|
287
|
+
system_instruction_version_id: UUID | None
|
|
288
|
+
input_schema_id: UUID | None
|
|
289
|
+
output_schema_id: UUID | None
|
|
290
|
+
created_at: datetime
|
|
291
|
+
updated_at: datetime
|
|
292
|
+
usage_count: int | None = Field(
|
|
293
|
+
default=None,
|
|
294
|
+
description="Number of named sessions using this agent. Only populated when sort_by=usage.",
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
|
|
298
|
+
class ListAgentsResponse(BaseModel):
|
|
299
|
+
"""Response for listing agents."""
|
|
300
|
+
|
|
301
|
+
agents: list[AgentSummary]
|
|
302
|
+
total: int
|
|
303
|
+
|
|
304
|
+
|
|
305
|
+
# ============================================================================
|
|
306
|
+
# Get Agent DTO
|
|
307
|
+
# ============================================================================
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
class GetAgentResponse(BaseModel):
|
|
311
|
+
"""Response for getting a single agent with full details."""
|
|
312
|
+
|
|
313
|
+
id: UUID
|
|
314
|
+
name: str
|
|
315
|
+
organization_id: UUID | None
|
|
316
|
+
user_id: UUID | None
|
|
317
|
+
base_agent_id: UUID | None
|
|
318
|
+
description: str | None
|
|
319
|
+
system_instruction_version_id: UUID | None
|
|
320
|
+
input_schema_id: UUID | None
|
|
321
|
+
output_schema_id: UUID | None
|
|
322
|
+
default_request_headers: dict[str, str] | None
|
|
323
|
+
generation_params: GenerationParameters | None = None
|
|
324
|
+
created_at: datetime
|
|
325
|
+
updated_at: datetime
|
|
326
|
+
models: list[AgentModelResponse]
|
|
327
|
+
tools: list[AgentToolResponse]
|
|
328
|
+
tags: list[AgentTagResponse]
|
|
329
|
+
mcp_servers: list[AgentMCPServerResponse] = []
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
# ============================================================================
|
|
333
|
+
# Delete Agent DTOs
|
|
334
|
+
# ============================================================================
|
|
335
|
+
|
|
336
|
+
|
|
337
|
+
class DeletedAgentResponse(BaseModel):
|
|
338
|
+
"""Response model for a deleted agent's final state."""
|
|
339
|
+
|
|
340
|
+
id: UUID
|
|
341
|
+
name: str
|
|
342
|
+
organization_id: UUID | None
|
|
343
|
+
user_id: UUID | None
|
|
344
|
+
base_agent_id: UUID | None
|
|
345
|
+
description: str | None
|
|
346
|
+
system_instruction_version_id: UUID | None
|
|
347
|
+
input_schema_id: UUID | None
|
|
348
|
+
output_schema_id: UUID | None
|
|
349
|
+
default_request_headers: dict[str, str] | None
|
|
350
|
+
generation_params: GenerationParameters | None = None
|
|
351
|
+
created_at: datetime
|
|
352
|
+
updated_at: datetime
|
|
353
|
+
models: list[AgentModelResponse]
|
|
354
|
+
tools: list[AgentToolResponse]
|
|
355
|
+
mcp_servers: list[AgentMCPServerResponse] = []
|
|
356
|
+
tags: list[AgentTagResponse]
|
|
357
|
+
|
|
358
|
+
|
|
359
|
+
class DeleteAgentResponse(BaseModel):
|
|
360
|
+
"""Response after deleting an agent."""
|
|
361
|
+
|
|
362
|
+
deleted_agent: DeletedAgentResponse
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
"""DTOs for API key management operations."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from uuid import UUID
|
|
5
|
+
|
|
6
|
+
from pydantic import BaseModel, Field, field_validator
|
|
7
|
+
|
|
8
|
+
from alloy_runtime_types.enums.api_key_scope import CANONICAL_SCOPE_ORDER, ApiKeyScope
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CreateApiKeyRequest(BaseModel):
|
|
12
|
+
"""Request to create a new API key.
|
|
13
|
+
|
|
14
|
+
Requires explicit non-empty scopes. Duplicates are normalized to unique set
|
|
15
|
+
in canonical order: read, update, delete, use.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
scopes: list[ApiKeyScope] = Field(
|
|
19
|
+
...,
|
|
20
|
+
description="Permission scopes for the API key (non-empty, normalized to unique set)",
|
|
21
|
+
min_length=1,
|
|
22
|
+
)
|
|
23
|
+
description: str | None = Field(
|
|
24
|
+
default=None,
|
|
25
|
+
max_length=500,
|
|
26
|
+
description="User-visible label for the key",
|
|
27
|
+
)
|
|
28
|
+
expires_at: datetime | None = Field(
|
|
29
|
+
default=None,
|
|
30
|
+
description="Optional expiration timestamp",
|
|
31
|
+
)
|
|
32
|
+
|
|
33
|
+
@field_validator("scopes")
|
|
34
|
+
@classmethod
|
|
35
|
+
def normalize_scopes(cls, value: list[ApiKeyScope]) -> list[ApiKeyScope]:
|
|
36
|
+
"""Normalize scopes to unique set in canonical order."""
|
|
37
|
+
# Remove duplicates while preserving order
|
|
38
|
+
seen: set[ApiKeyScope] = set()
|
|
39
|
+
unique: list[ApiKeyScope] = []
|
|
40
|
+
for scope in value:
|
|
41
|
+
if scope not in seen:
|
|
42
|
+
seen.add(scope)
|
|
43
|
+
unique.append(scope)
|
|
44
|
+
|
|
45
|
+
# Sort by canonical order
|
|
46
|
+
return sorted(unique, key=lambda s: CANONICAL_SCOPE_ORDER.index(s))
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class CreateApiKeyResponse(BaseModel):
|
|
50
|
+
"""Response after creating an API key.
|
|
51
|
+
|
|
52
|
+
Returns the plaintext key once. Never exposes hashed_key.
|
|
53
|
+
"""
|
|
54
|
+
|
|
55
|
+
id: UUID
|
|
56
|
+
key: str # Plaintext, only returned once
|
|
57
|
+
prefix: str
|
|
58
|
+
description: str | None
|
|
59
|
+
scopes: list[ApiKeyScope]
|
|
60
|
+
created_at: datetime
|
|
61
|
+
expires_at: datetime | None = None
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
class ApiKeyResponse(BaseModel):
|
|
65
|
+
"""Common response shape for API key data."""
|
|
66
|
+
|
|
67
|
+
id: UUID
|
|
68
|
+
prefix: str
|
|
69
|
+
description: str | None
|
|
70
|
+
scopes: list[ApiKeyScope]
|
|
71
|
+
created_at: datetime
|
|
72
|
+
expires_at: datetime | None = None
|
|
73
|
+
last_used_at: datetime | None = None
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
class ListApiKeysResponse(BaseModel):
|
|
77
|
+
"""Response listing all API keys for authenticated user."""
|
|
78
|
+
|
|
79
|
+
keys: list[ApiKeyResponse]
|
|
80
|
+
total: int
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class UpdateApiKeyRequest(BaseModel):
|
|
84
|
+
"""Request to update an existing API key.
|
|
85
|
+
|
|
86
|
+
All fields are optional - only provided fields are updated.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
description: str | None = Field(
|
|
90
|
+
default=None,
|
|
91
|
+
max_length=500,
|
|
92
|
+
description="User-visible label for the key",
|
|
93
|
+
)
|
|
94
|
+
expires_at: datetime | None = Field(
|
|
95
|
+
default=None,
|
|
96
|
+
description="Expiration timestamp (set to None to remove expiration)",
|
|
97
|
+
)
|
|
98
|
+
scopes: list[ApiKeyScope] | None = Field(
|
|
99
|
+
default=None,
|
|
100
|
+
description="Permission scopes (non-empty if provided, normalized to unique set)",
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
@field_validator("scopes")
|
|
104
|
+
@classmethod
|
|
105
|
+
def normalize_scopes(
|
|
106
|
+
cls, value: list[ApiKeyScope] | None
|
|
107
|
+
) -> list[ApiKeyScope] | None:
|
|
108
|
+
"""Normalize scopes to unique set in canonical order if provided."""
|
|
109
|
+
if value is None:
|
|
110
|
+
return None
|
|
111
|
+
|
|
112
|
+
if len(value) == 0:
|
|
113
|
+
raise ValueError("scopes must be non-empty if provided")
|
|
114
|
+
|
|
115
|
+
# Remove duplicates while preserving order
|
|
116
|
+
seen: set[ApiKeyScope] = set()
|
|
117
|
+
unique: list[ApiKeyScope] = []
|
|
118
|
+
for scope in value:
|
|
119
|
+
if scope not in seen:
|
|
120
|
+
seen.add(scope)
|
|
121
|
+
unique.append(scope)
|
|
122
|
+
|
|
123
|
+
# Sort by canonical order
|
|
124
|
+
return sorted(unique, key=lambda s: CANONICAL_SCOPE_ORDER.index(s))
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"""DTOs for audio transcription endpoints."""
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AudioTranscriptResponse(BaseModel):
|
|
7
|
+
"""Response containing transcribed text from audio."""
|
|
8
|
+
|
|
9
|
+
text: str = Field(min_length=1, description="Transcribed text from audio")
|