idun-agent-schema 0.1.3__py3-none-any.whl → 0.1.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of idun-agent-schema might be problematic. Click here for more details.

@@ -1,131 +1,131 @@
1
- """DTOs for Manager operations."""
2
-
3
- from datetime import datetime
4
- from typing import Any
5
- from uuid import UUID
6
-
7
- from pydantic import BaseModel, Field
8
-
9
- from .domain import AgentFramework, TenantPlan
10
-
11
-
12
- class AgentCreateDTO(BaseModel):
13
- """DTO for creating an agent in the application layer."""
14
-
15
- name: str = Field(..., min_length=1, max_length=255)
16
- description: str | None = Field(None, max_length=1000)
17
- framework: AgentFramework
18
- config: dict[str, Any] = Field(default_factory=dict)
19
- environment_variables: dict[str, str] = Field(default_factory=dict)
20
- tags: list[str] = Field(default_factory=list)
21
- tenant_id: UUID
22
-
23
-
24
- class AgentUpdateDTO(BaseModel):
25
- """DTO for updating an existing agent."""
26
-
27
- name: str | None = Field(None, min_length=1, max_length=255)
28
- description: str | None = Field(None, max_length=1000)
29
- config: dict[str, Any] | None = None
30
- environment_variables: dict[str, str] | None = None
31
- tags: list[str] | None = None
32
-
33
-
34
- class AgentDeploymentDTO(BaseModel):
35
- """DTO describing deployment details for an agent."""
36
-
37
- agent_id: UUID
38
- container_id: str
39
- endpoint: str
40
- status: str
41
- framework: str
42
- deployed_at: datetime | None = None
43
-
44
-
45
- class AgentHealthDTO(BaseModel):
46
- """DTO representing health metrics for an agent instance."""
47
-
48
- agent_id: UUID
49
- status: str
50
- uptime: str | None = None
51
- cpu_usage: str | None = None
52
- memory_usage: str | None = None
53
- last_activity: str | None = None
54
- error: str | None = None
55
-
56
-
57
- class AgentRunCreateDTO(BaseModel):
58
- """DTO for creating a new agent run."""
59
-
60
- agent_id: UUID
61
- tenant_id: UUID
62
- input_data: dict[str, Any]
63
- trace_id: str | None = None
64
-
65
-
66
- class AgentMetricsDTO(BaseModel):
67
- """DTO for aggregated performance metrics of an agent."""
68
-
69
- agent_id: UUID
70
- total_runs: int
71
- success_rate: float | None = Field(None, ge=0.0, le=1.0)
72
- avg_response_time_ms: float | None = Field(None, ge=0)
73
- last_run_at: datetime | None = None
74
-
75
-
76
- class TenantCreateDTO(BaseModel):
77
- """DTO for creating a tenant."""
78
-
79
- name: str = Field(..., min_length=1, max_length=255)
80
- slug: str = Field(..., min_length=1, max_length=100)
81
- email: str = Field(..., description="Primary contact email")
82
- website: str | None = None
83
- plan: TenantPlan = Field(default=TenantPlan.FREE)
84
-
85
-
86
- class TenantUpdateDTO(BaseModel):
87
- """DTO for updating tenant metadata and settings."""
88
-
89
- name: str | None = Field(None, min_length=1, max_length=255)
90
- email: str | None = None
91
- website: str | None = None
92
- settings: dict[str, Any] | None = None
93
-
94
-
95
- class TenantUsageDTO(BaseModel):
96
- """DTO summarizing a tenant's resource usage and quotas."""
97
-
98
- tenant_id: UUID
99
- current_agents: int
100
- max_agents: int
101
- current_runs_this_month: int
102
- max_runs_per_month: int
103
- current_storage_mb: float
104
- max_storage_mb: int
105
- usage_percentage: dict[str, float]
106
-
107
-
108
- class TenantQuotaDTO(BaseModel):
109
- """DTO for updating tenant quotas."""
110
-
111
- max_agents: int | None = None
112
- max_runs_per_month: int | None = None
113
- max_storage_mb: int | None = None
114
-
115
-
116
- class TenantUserCreateDTO(BaseModel):
117
- """DTO for adding a user to a tenant."""
118
-
119
- tenant_id: UUID
120
- user_id: str
121
- email: str
122
- role: str = Field(default="member")
123
- permissions: list[str] = Field(default_factory=list)
124
-
125
-
126
- class TenantUserUpdateDTO(BaseModel):
127
- """DTO for updating tenant user fields."""
128
-
129
- role: str | None = None
130
- permissions: list[str] | None = None
131
- is_active: bool | None = None
1
+ """DTOs for Manager operations."""
2
+
3
+ from datetime import datetime
4
+ from typing import Any
5
+ from uuid import UUID
6
+
7
+ from pydantic import BaseModel, Field
8
+
9
+ from .domain import AgentFramework, TenantPlan
10
+
11
+
12
+ class AgentCreateDTO(BaseModel):
13
+ """DTO for creating an agent in the application layer."""
14
+
15
+ name: str = Field(..., min_length=1, max_length=255)
16
+ description: str | None = Field(None, max_length=1000)
17
+ framework: AgentFramework
18
+ config: dict[str, Any] = Field(default_factory=dict)
19
+ environment_variables: dict[str, str] = Field(default_factory=dict)
20
+ tags: list[str] = Field(default_factory=list)
21
+ tenant_id: UUID
22
+
23
+
24
+ class AgentUpdateDTO(BaseModel):
25
+ """DTO for updating an existing agent."""
26
+
27
+ name: str | None = Field(None, min_length=1, max_length=255)
28
+ description: str | None = Field(None, max_length=1000)
29
+ config: dict[str, Any] | None = None
30
+ environment_variables: dict[str, str] | None = None
31
+ tags: list[str] | None = None
32
+
33
+
34
+ class AgentDeploymentDTO(BaseModel):
35
+ """DTO describing deployment details for an agent."""
36
+
37
+ agent_id: UUID
38
+ container_id: str
39
+ endpoint: str
40
+ status: str
41
+ framework: str
42
+ deployed_at: datetime | None = None
43
+
44
+
45
+ class AgentHealthDTO(BaseModel):
46
+ """DTO representing health metrics for an agent instance."""
47
+
48
+ agent_id: UUID
49
+ status: str
50
+ uptime: str | None = None
51
+ cpu_usage: str | None = None
52
+ memory_usage: str | None = None
53
+ last_activity: str | None = None
54
+ error: str | None = None
55
+
56
+
57
+ class AgentRunCreateDTO(BaseModel):
58
+ """DTO for creating a new agent run."""
59
+
60
+ agent_id: UUID
61
+ tenant_id: UUID
62
+ input_data: dict[str, Any]
63
+ trace_id: str | None = None
64
+
65
+
66
+ class AgentMetricsDTO(BaseModel):
67
+ """DTO for aggregated performance metrics of an agent."""
68
+
69
+ agent_id: UUID
70
+ total_runs: int
71
+ success_rate: float | None = Field(None, ge=0.0, le=1.0)
72
+ avg_response_time_ms: float | None = Field(None, ge=0)
73
+ last_run_at: datetime | None = None
74
+
75
+
76
+ class TenantCreateDTO(BaseModel):
77
+ """DTO for creating a tenant."""
78
+
79
+ name: str = Field(..., min_length=1, max_length=255)
80
+ slug: str = Field(..., min_length=1, max_length=100)
81
+ email: str = Field(..., description="Primary contact email")
82
+ website: str | None = None
83
+ plan: TenantPlan = Field(default=TenantPlan.FREE)
84
+
85
+
86
+ class TenantUpdateDTO(BaseModel):
87
+ """DTO for updating tenant metadata and settings."""
88
+
89
+ name: str | None = Field(None, min_length=1, max_length=255)
90
+ email: str | None = None
91
+ website: str | None = None
92
+ settings: dict[str, Any] | None = None
93
+
94
+
95
+ class TenantUsageDTO(BaseModel):
96
+ """DTO summarizing a tenant's resource usage and quotas."""
97
+
98
+ tenant_id: UUID
99
+ current_agents: int
100
+ max_agents: int
101
+ current_runs_this_month: int
102
+ max_runs_per_month: int
103
+ current_storage_mb: float
104
+ max_storage_mb: int
105
+ usage_percentage: dict[str, float]
106
+
107
+
108
+ class TenantQuotaDTO(BaseModel):
109
+ """DTO for updating tenant quotas."""
110
+
111
+ max_agents: int | None = None
112
+ max_runs_per_month: int | None = None
113
+ max_storage_mb: int | None = None
114
+
115
+
116
+ class TenantUserCreateDTO(BaseModel):
117
+ """DTO for adding a user to a tenant."""
118
+
119
+ tenant_id: UUID
120
+ user_id: str
121
+ email: str
122
+ role: str = Field(default="member")
123
+ permissions: list[str] = Field(default_factory=list)
124
+
125
+
126
+ class TenantUserUpdateDTO(BaseModel):
127
+ """DTO for updating tenant user fields."""
128
+
129
+ role: str | None = None
130
+ permissions: list[str] | None = None
131
+ is_active: bool | None = None
@@ -1,22 +1,22 @@
1
- """RFC 9457 Problem Details model (shared)."""
2
-
3
- from typing import Any
4
-
5
- from pydantic import BaseModel, Field
6
-
7
-
8
- class ProblemDetail(BaseModel):
9
- """RFC 9457 Problem Details model."""
10
-
11
- type: str = Field(default="about:blank")
12
- title: str = Field()
13
- status: int = Field()
14
- detail: str | None = Field(default=None)
15
- instance: str | None = Field(default=None)
16
-
17
- # Extension members
18
- timestamp: str | None = Field(default=None)
19
- request_id: str | None = Field(default=None)
20
- errors: dict[str, Any] | None = Field(default=None)
21
-
22
- model_config = {"extra": "allow"}
1
+ """RFC 9457 Problem Details model (shared)."""
2
+
3
+ from typing import Any
4
+
5
+ from pydantic import BaseModel, Field
6
+
7
+
8
+ class ProblemDetail(BaseModel):
9
+ """RFC 9457 Problem Details model."""
10
+
11
+ type: str = Field(default="about:blank")
12
+ title: str = Field()
13
+ status: int = Field()
14
+ detail: str | None = Field(default=None)
15
+ instance: str | None = Field(default=None)
16
+
17
+ # Extension members
18
+ timestamp: str | None = Field(default=None)
19
+ request_id: str | None = Field(default=None)
20
+ errors: dict[str, Any] | None = Field(default=None)
21
+
22
+ model_config = {"extra": "allow"}
@@ -1,161 +1,161 @@
1
- """Application settings schemas using Pydantic Settings v2."""
2
-
3
- from typing import Literal
4
-
5
- from pydantic import Field, field_validator
6
- from pydantic_settings import BaseSettings, SettingsConfigDict
7
-
8
-
9
- class DatabaseSettings(BaseSettings):
10
- """Database configuration settings for the Manager service."""
11
-
12
- url: str = Field(
13
- default="postgresql+asyncpg://postgres:postgres@localhost:55432/idun_agents"
14
- )
15
- echo: bool = Field(default=False)
16
- pool_size: int = Field(default=10)
17
- max_overflow: int = Field(default=20)
18
- pool_pre_ping: bool = Field(default=True)
19
-
20
- model_config = SettingsConfigDict(env_prefix="DATABASE_", env_file=".env")
21
-
22
-
23
- class RedisSettings(BaseSettings):
24
- """Redis cache settings."""
25
-
26
- url: str = Field(default="redis://localhost:6379/0")
27
- max_connections: int = Field(default=20)
28
-
29
- model_config = SettingsConfigDict(env_prefix="REDIS_", env_file=".env")
30
-
31
-
32
- class AuthSettings(BaseSettings):
33
- """Authentication and OIDC-related configuration."""
34
-
35
- provider_type: Literal["okta", "auth0", "entra", "google"] = Field(default="auth0")
36
- issuer: str = Field(default="")
37
- client_id: str = Field(default="")
38
- client_secret: str = Field(default="")
39
- audience: str | None = Field(default=None)
40
- redirect_uri: str | None = Field(default=None)
41
- scopes: list[str] = Field(default_factory=lambda: ["openid", "profile", "email"])
42
-
43
- allowed_algs: list[str] = Field(default_factory=lambda: ["RS256", "RS512", "ES256"])
44
- jwks_cache_ttl: int = Field(default=300)
45
- clock_skew_seconds: int = Field(default=60)
46
- expected_audiences: list[str] = Field(default_factory=list)
47
-
48
- claim_user_id_path: list[str] | None = Field(default=None)
49
- claim_email_path: list[str] | None = Field(default=None)
50
- claim_roles_paths: list[list[str]] | None = Field(default=None)
51
- claim_groups_paths: list[list[str]] | None = Field(default=None)
52
- claim_workspace_ids_paths: list[list[str]] | None = Field(default=None)
53
-
54
- @field_validator("claim_user_id_path", "claim_email_path", mode="before")
55
- @classmethod
56
- def _string_to_list(cls, v):
57
- if isinstance(v, str) and v.strip().startswith("#"):
58
- return None
59
- return v
60
-
61
- @field_validator(
62
- "claim_roles_paths",
63
- "claim_groups_paths",
64
- "claim_workspace_ids_paths",
65
- mode="before",
66
- )
67
- @classmethod
68
- def _string_to_list_of_lists(cls, v):
69
- if isinstance(v, str) and v.strip().startswith("#"):
70
- return None
71
- return v
72
-
73
- model_config = SettingsConfigDict(
74
- env_prefix="AUTH_", env_file=".env", extra="ignore"
75
- )
76
-
77
- @field_validator("issuer")
78
- @classmethod
79
- def validate_issuer(cls, v: str) -> str:
80
- """Validate that issuer is either empty or a URL."""
81
- if not v:
82
- return v
83
- if not v.startswith("http"):
84
- raise ValueError("issuer must be a URL")
85
- return v
86
-
87
-
88
- class ObservabilitySettings(BaseSettings):
89
- """OpenTelemetry and logging settings."""
90
-
91
- otel_service_name: str = Field(default="idun-agent-manager")
92
- otel_exporter_endpoint: str | None = Field(default=None)
93
- otel_exporter_headers: str | None = Field(default=None)
94
- log_level: str = Field(default="INFO")
95
- log_format: str = Field(default="json")
96
-
97
- model_config = SettingsConfigDict(env_prefix="OTEL_", env_file=".env")
98
-
99
-
100
- class CelerySettings(BaseSettings):
101
- """Celery broker/result backend settings."""
102
-
103
- broker_url: str = Field(default="redis://localhost:6379/1")
104
- result_backend: str = Field(default="redis://localhost:6379/2")
105
- task_serializer: str = Field(default="json")
106
- result_serializer: str = Field(default="json")
107
- accept_content: list[str] = Field(default=["json"])
108
- timezone: str = Field(default="UTC")
109
-
110
- model_config = SettingsConfigDict(env_prefix="CELERY_", env_file=".env")
111
-
112
-
113
- class APISettings(BaseSettings):
114
- """API metadata, CORS, and rate limiting settings."""
115
-
116
- title: str = Field(default="Idun Agent Manager API")
117
- description: str = Field(default="Modern FastAPI backend for managing AI agents")
118
- version: str = Field(default="0.1.0")
119
- docs_url: str = Field(default="/docs")
120
- redoc_url: str = Field(default="/redoc")
121
- openapi_url: str = Field(default="/openapi.json")
122
- cors_origins: list[str] = Field(
123
- default=["http://localhost:3000", "http://localhost:8080"]
124
- )
125
- cors_methods: list[str] = Field(default=["*"])
126
- cors_headers: list[str] = Field(default=["*"])
127
- rate_limit_enabled: bool = Field(default=True)
128
- rate_limit_requests: int = Field(default=100)
129
- rate_limit_window: int = Field(default=60)
130
-
131
- model_config = SettingsConfigDict(
132
- env_prefix="API_", env_file=".env", extra="ignore"
133
- )
134
-
135
-
136
- class Settings(BaseSettings):
137
- """Top-level application settings composed of sub-settings."""
138
-
139
- environment: str = Field(default="development")
140
- debug: bool = Field(default=False)
141
- testing: bool = Field(default=False)
142
- host: str = Field(default="0.0.0.0")
143
- port: int = Field(default=8000)
144
- workers: int = Field(default=1)
145
- reload: bool = Field(default=False)
146
- is_development: bool = Field(default=True)
147
-
148
- database: DatabaseSettings = Field(default_factory=DatabaseSettings)
149
- redis: RedisSettings = Field(default_factory=RedisSettings)
150
- auth: AuthSettings = Field(default_factory=AuthSettings)
151
- observability: ObservabilitySettings = Field(default_factory=ObservabilitySettings)
152
- celery: CelerySettings = Field(default_factory=CelerySettings)
153
- api: APISettings = Field(default_factory=APISettings)
154
-
155
- model_config = SettingsConfigDict(
156
- env_file=".env",
157
- env_file_encoding="utf-8",
158
- env_nested_delimiter="__",
159
- case_sensitive=False,
160
- extra="ignore",
161
- )
1
+ """Application settings schemas using Pydantic Settings v2."""
2
+
3
+ from typing import Literal
4
+
5
+ from pydantic import Field, field_validator
6
+ from pydantic_settings import BaseSettings, SettingsConfigDict
7
+
8
+
9
+ class DatabaseSettings(BaseSettings):
10
+ """Database configuration settings for the Manager service."""
11
+
12
+ url: str = Field(
13
+ default="postgresql+asyncpg://postgres:postgres@localhost:55432/idun_agents"
14
+ )
15
+ echo: bool = Field(default=False)
16
+ pool_size: int = Field(default=10)
17
+ max_overflow: int = Field(default=20)
18
+ pool_pre_ping: bool = Field(default=True)
19
+
20
+ model_config = SettingsConfigDict(env_prefix="DATABASE_", env_file=".env")
21
+
22
+
23
+ class RedisSettings(BaseSettings):
24
+ """Redis cache settings."""
25
+
26
+ url: str = Field(default="redis://localhost:6379/0")
27
+ max_connections: int = Field(default=20)
28
+
29
+ model_config = SettingsConfigDict(env_prefix="REDIS_", env_file=".env")
30
+
31
+
32
+ class AuthSettings(BaseSettings):
33
+ """Authentication and OIDC-related configuration."""
34
+
35
+ provider_type: Literal["okta", "auth0", "entra", "google"] = Field(default="auth0")
36
+ issuer: str = Field(default="")
37
+ client_id: str = Field(default="")
38
+ client_secret: str = Field(default="")
39
+ audience: str | None = Field(default=None)
40
+ redirect_uri: str | None = Field(default=None)
41
+ scopes: list[str] = Field(default_factory=lambda: ["openid", "profile", "email"])
42
+
43
+ allowed_algs: list[str] = Field(default_factory=lambda: ["RS256", "RS512", "ES256"])
44
+ jwks_cache_ttl: int = Field(default=300)
45
+ clock_skew_seconds: int = Field(default=60)
46
+ expected_audiences: list[str] = Field(default_factory=list)
47
+
48
+ claim_user_id_path: list[str] | None = Field(default=None)
49
+ claim_email_path: list[str] | None = Field(default=None)
50
+ claim_roles_paths: list[list[str]] | None = Field(default=None)
51
+ claim_groups_paths: list[list[str]] | None = Field(default=None)
52
+ claim_workspace_ids_paths: list[list[str]] | None = Field(default=None)
53
+
54
+ @field_validator("claim_user_id_path", "claim_email_path", mode="before")
55
+ @classmethod
56
+ def _string_to_list(cls, v):
57
+ if isinstance(v, str) and v.strip().startswith("#"):
58
+ return None
59
+ return v
60
+
61
+ @field_validator(
62
+ "claim_roles_paths",
63
+ "claim_groups_paths",
64
+ "claim_workspace_ids_paths",
65
+ mode="before",
66
+ )
67
+ @classmethod
68
+ def _string_to_list_of_lists(cls, v):
69
+ if isinstance(v, str) and v.strip().startswith("#"):
70
+ return None
71
+ return v
72
+
73
+ model_config = SettingsConfigDict(
74
+ env_prefix="AUTH_", env_file=".env", extra="ignore"
75
+ )
76
+
77
+ @field_validator("issuer")
78
+ @classmethod
79
+ def validate_issuer(cls, v: str) -> str:
80
+ """Validate that issuer is either empty or a URL."""
81
+ if not v:
82
+ return v
83
+ if not v.startswith("http"):
84
+ raise ValueError("issuer must be a URL")
85
+ return v
86
+
87
+
88
+ class ObservabilitySettings(BaseSettings):
89
+ """OpenTelemetry and logging settings."""
90
+
91
+ otel_service_name: str = Field(default="idun-agent-manager")
92
+ otel_exporter_endpoint: str | None = Field(default=None)
93
+ otel_exporter_headers: str | None = Field(default=None)
94
+ log_level: str = Field(default="INFO")
95
+ log_format: str = Field(default="json")
96
+
97
+ model_config = SettingsConfigDict(env_prefix="OTEL_", env_file=".env")
98
+
99
+
100
+ class CelerySettings(BaseSettings):
101
+ """Celery broker/result backend settings."""
102
+
103
+ broker_url: str = Field(default="redis://localhost:6379/1")
104
+ result_backend: str = Field(default="redis://localhost:6379/2")
105
+ task_serializer: str = Field(default="json")
106
+ result_serializer: str = Field(default="json")
107
+ accept_content: list[str] = Field(default=["json"])
108
+ timezone: str = Field(default="UTC")
109
+
110
+ model_config = SettingsConfigDict(env_prefix="CELERY_", env_file=".env")
111
+
112
+
113
+ class APISettings(BaseSettings):
114
+ """API metadata, CORS, and rate limiting settings."""
115
+
116
+ title: str = Field(default="Idun Agent Manager API")
117
+ description: str = Field(default="Modern FastAPI backend for managing AI agents")
118
+ version: str = Field(default="0.1.0")
119
+ docs_url: str = Field(default="/docs")
120
+ redoc_url: str = Field(default="/redoc")
121
+ openapi_url: str = Field(default="/openapi.json")
122
+ cors_origins: list[str] = Field(
123
+ default=["http://localhost:3000", "http://localhost:8080"]
124
+ )
125
+ cors_methods: list[str] = Field(default=["*"])
126
+ cors_headers: list[str] = Field(default=["*"])
127
+ rate_limit_enabled: bool = Field(default=True)
128
+ rate_limit_requests: int = Field(default=100)
129
+ rate_limit_window: int = Field(default=60)
130
+
131
+ model_config = SettingsConfigDict(
132
+ env_prefix="API_", env_file=".env", extra="ignore"
133
+ )
134
+
135
+
136
+ class Settings(BaseSettings):
137
+ """Top-level application settings composed of sub-settings."""
138
+
139
+ environment: str = Field(default="development")
140
+ debug: bool = Field(default=False)
141
+ testing: bool = Field(default=False)
142
+ host: str = Field(default="0.0.0.0")
143
+ port: int = Field(default=8000)
144
+ workers: int = Field(default=1)
145
+ reload: bool = Field(default=False)
146
+ is_development: bool = Field(default=True)
147
+
148
+ database: DatabaseSettings = Field(default_factory=DatabaseSettings)
149
+ redis: RedisSettings = Field(default_factory=RedisSettings)
150
+ auth: AuthSettings = Field(default_factory=AuthSettings)
151
+ observability: ObservabilitySettings = Field(default_factory=ObservabilitySettings)
152
+ celery: CelerySettings = Field(default_factory=CelerySettings)
153
+ api: APISettings = Field(default_factory=APISettings)
154
+
155
+ model_config = SettingsConfigDict(
156
+ env_file=".env",
157
+ env_file_encoding="utf-8",
158
+ env_nested_delimiter="__",
159
+ case_sensitive=False,
160
+ extra="ignore",
161
+ )
@@ -1,5 +1,5 @@
1
- """Shared cross-cutting schemas used by both Engine and Manager."""
2
-
3
- from .observability import ObservabilityConfig
4
-
5
- __all__ = ["ObservabilityConfig"]
1
+ """Shared cross-cutting schemas used by both Engine and Manager."""
2
+
3
+ from .observability import ObservabilityConfig
4
+
5
+ __all__ = ["ObservabilityConfig"]