agno 2.1.9__py3-none-any.whl → 2.2.0__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.
- agno/agent/agent.py +2048 -1204
- agno/culture/__init__.py +3 -0
- agno/culture/manager.py +954 -0
- agno/db/async_postgres/async_postgres.py +232 -0
- agno/db/async_postgres/schemas.py +15 -0
- agno/db/async_postgres/utils.py +58 -0
- agno/db/base.py +83 -6
- agno/db/dynamo/dynamo.py +162 -0
- agno/db/dynamo/schemas.py +44 -0
- agno/db/dynamo/utils.py +59 -0
- agno/db/firestore/firestore.py +231 -0
- agno/db/firestore/schemas.py +10 -0
- agno/db/firestore/utils.py +96 -0
- agno/db/gcs_json/gcs_json_db.py +190 -0
- agno/db/gcs_json/utils.py +58 -0
- agno/db/in_memory/in_memory_db.py +118 -0
- agno/db/in_memory/utils.py +58 -0
- agno/db/json/json_db.py +129 -0
- agno/db/json/utils.py +58 -0
- agno/db/mongo/mongo.py +222 -0
- agno/db/mongo/schemas.py +10 -0
- agno/db/mongo/utils.py +59 -0
- agno/db/mysql/mysql.py +232 -1
- agno/db/mysql/schemas.py +14 -0
- agno/db/mysql/utils.py +58 -0
- agno/db/postgres/postgres.py +242 -0
- agno/db/postgres/schemas.py +15 -0
- agno/db/postgres/utils.py +58 -0
- agno/db/redis/redis.py +181 -0
- agno/db/redis/schemas.py +14 -0
- agno/db/redis/utils.py +58 -0
- agno/db/schemas/__init__.py +2 -1
- agno/db/schemas/culture.py +120 -0
- agno/db/singlestore/schemas.py +14 -0
- agno/db/singlestore/singlestore.py +231 -0
- agno/db/singlestore/utils.py +58 -0
- agno/db/sqlite/schemas.py +14 -0
- agno/db/sqlite/sqlite.py +274 -7
- agno/db/sqlite/utils.py +62 -0
- agno/db/surrealdb/models.py +51 -1
- agno/db/surrealdb/surrealdb.py +154 -0
- agno/db/surrealdb/utils.py +61 -1
- agno/knowledge/reader/field_labeled_csv_reader.py +0 -2
- agno/memory/manager.py +28 -11
- agno/models/anthropic/claude.py +2 -2
- agno/models/message.py +0 -1
- agno/models/ollama/chat.py +7 -2
- agno/os/app.py +29 -7
- agno/os/interfaces/a2a/router.py +2 -2
- agno/os/interfaces/agui/router.py +2 -2
- agno/os/router.py +7 -7
- agno/os/routers/evals/schemas.py +31 -31
- agno/os/routers/health.py +6 -2
- agno/os/routers/knowledge/schemas.py +49 -47
- agno/os/routers/memory/schemas.py +16 -16
- agno/os/routers/metrics/schemas.py +16 -16
- agno/os/routers/session/session.py +382 -7
- agno/os/schema.py +254 -231
- agno/os/utils.py +1 -1
- agno/run/agent.py +49 -1
- agno/run/team.py +43 -0
- agno/session/summary.py +45 -13
- agno/session/team.py +90 -5
- agno/team/team.py +1118 -857
- agno/tools/gmail.py +59 -14
- agno/utils/agent.py +372 -0
- agno/utils/events.py +144 -2
- agno/utils/print_response/agent.py +10 -6
- agno/utils/print_response/team.py +6 -4
- agno/utils/print_response/workflow.py +7 -5
- agno/utils/team.py +9 -8
- agno/workflow/condition.py +17 -9
- agno/workflow/loop.py +18 -10
- agno/workflow/parallel.py +14 -6
- agno/workflow/router.py +17 -9
- agno/workflow/step.py +14 -6
- agno/workflow/steps.py +14 -6
- agno/workflow/workflow.py +245 -122
- {agno-2.1.9.dist-info → agno-2.2.0.dist-info}/METADATA +60 -23
- {agno-2.1.9.dist-info → agno-2.2.0.dist-info}/RECORD +83 -79
- {agno-2.1.9.dist-info → agno-2.2.0.dist-info}/WHEEL +0 -0
- {agno-2.1.9.dist-info → agno-2.2.0.dist-info}/licenses/LICENSE +0 -0
- {agno-2.1.9.dist-info → agno-2.2.0.dist-info}/top_level.txt +0 -0
agno/os/routers/evals/schemas.py
CHANGED
|
@@ -2,7 +2,7 @@ from dataclasses import asdict
|
|
|
2
2
|
from datetime import datetime, timezone
|
|
3
3
|
from typing import Any, Dict, List, Optional
|
|
4
4
|
|
|
5
|
-
from pydantic import BaseModel
|
|
5
|
+
from pydantic import BaseModel, Field
|
|
6
6
|
|
|
7
7
|
from agno.db.schemas.evals import EvalType
|
|
8
8
|
from agno.eval import AccuracyResult, PerformanceResult, ReliabilityResult
|
|
@@ -12,43 +12,43 @@ from agno.eval.reliability import ReliabilityEval
|
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class EvalRunInput(BaseModel):
|
|
15
|
-
agent_id: Optional[str] = None
|
|
16
|
-
team_id: Optional[str] = None
|
|
17
|
-
|
|
18
|
-
model_id: Optional[str] = None
|
|
19
|
-
model_provider: Optional[str] = None
|
|
20
|
-
eval_type: EvalType
|
|
21
|
-
input: str
|
|
22
|
-
additional_guidelines: Optional[str] = None
|
|
23
|
-
additional_context: Optional[str] = None
|
|
24
|
-
num_iterations:
|
|
25
|
-
name: Optional[str] = None
|
|
15
|
+
agent_id: Optional[str] = Field(None, description="Agent ID to evaluate")
|
|
16
|
+
team_id: Optional[str] = Field(None, description="Team ID to evaluate")
|
|
17
|
+
|
|
18
|
+
model_id: Optional[str] = Field(None, description="Model ID to use for evaluation")
|
|
19
|
+
model_provider: Optional[str] = Field(None, description="Model provider name")
|
|
20
|
+
eval_type: EvalType = Field(..., description="Type of evaluation to run (accuracy, performance, or reliability)")
|
|
21
|
+
input: str = Field(..., description="Input text/query for the evaluation", min_length=1)
|
|
22
|
+
additional_guidelines: Optional[str] = Field(None, description="Additional guidelines for the evaluation")
|
|
23
|
+
additional_context: Optional[str] = Field(None, description="Additional context for the evaluation")
|
|
24
|
+
num_iterations: int = Field(1, description="Number of times to run the evaluation", ge=1, le=100)
|
|
25
|
+
name: Optional[str] = Field(None, description="Name for this evaluation run")
|
|
26
26
|
|
|
27
27
|
# Accuracy eval specific fields
|
|
28
|
-
expected_output: Optional[str] = None
|
|
28
|
+
expected_output: Optional[str] = Field(None, description="Expected output for accuracy evaluation")
|
|
29
29
|
|
|
30
30
|
# Performance eval specific fields
|
|
31
|
-
warmup_runs:
|
|
31
|
+
warmup_runs: int = Field(0, description="Number of warmup runs before measuring performance", ge=0, le=10)
|
|
32
32
|
|
|
33
33
|
# Reliability eval specific fields
|
|
34
|
-
expected_tool_calls: Optional[List[str]] = None
|
|
34
|
+
expected_tool_calls: Optional[List[str]] = Field(None, description="Expected tool calls for reliability evaluation")
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
class EvalSchema(BaseModel):
|
|
38
|
-
id: str
|
|
39
|
-
|
|
40
|
-
agent_id: Optional[str] = None
|
|
41
|
-
model_id: Optional[str] = None
|
|
42
|
-
model_provider: Optional[str] = None
|
|
43
|
-
team_id: Optional[str] = None
|
|
44
|
-
workflow_id: Optional[str] = None
|
|
45
|
-
name: Optional[str] = None
|
|
46
|
-
evaluated_component_name: Optional[str] = None
|
|
47
|
-
eval_type: EvalType
|
|
48
|
-
eval_data: Dict[str, Any]
|
|
49
|
-
eval_input: Optional[Dict[str, Any]] = None
|
|
50
|
-
created_at: Optional[datetime] = None
|
|
51
|
-
updated_at: Optional[datetime] = None
|
|
38
|
+
id: str = Field(..., description="Unique identifier for the evaluation run")
|
|
39
|
+
|
|
40
|
+
agent_id: Optional[str] = Field(None, description="Agent ID that was evaluated")
|
|
41
|
+
model_id: Optional[str] = Field(None, description="Model ID used in evaluation")
|
|
42
|
+
model_provider: Optional[str] = Field(None, description="Model provider name")
|
|
43
|
+
team_id: Optional[str] = Field(None, description="Team ID that was evaluated")
|
|
44
|
+
workflow_id: Optional[str] = Field(None, description="Workflow ID that was evaluated")
|
|
45
|
+
name: Optional[str] = Field(None, description="Name of the evaluation run")
|
|
46
|
+
evaluated_component_name: Optional[str] = Field(None, description="Name of the evaluated component")
|
|
47
|
+
eval_type: EvalType = Field(..., description="Type of evaluation (accuracy, performance, or reliability)")
|
|
48
|
+
eval_data: Dict[str, Any] = Field(..., description="Evaluation results and metrics")
|
|
49
|
+
eval_input: Optional[Dict[str, Any]] = Field(None, description="Input parameters used for the evaluation")
|
|
50
|
+
created_at: Optional[datetime] = Field(None, description="Timestamp when evaluation was created")
|
|
51
|
+
updated_at: Optional[datetime] = Field(None, description="Timestamp when evaluation was last updated")
|
|
52
52
|
|
|
53
53
|
@classmethod
|
|
54
54
|
def from_dict(cls, eval_run: Dict[str, Any]) -> "EvalSchema":
|
|
@@ -135,8 +135,8 @@ class EvalSchema(BaseModel):
|
|
|
135
135
|
|
|
136
136
|
|
|
137
137
|
class DeleteEvalRunsRequest(BaseModel):
|
|
138
|
-
eval_run_ids: List[str]
|
|
138
|
+
eval_run_ids: List[str] = Field(..., description="List of evaluation run IDs to delete", min_length=1)
|
|
139
139
|
|
|
140
140
|
|
|
141
141
|
class UpdateEvalRunRequest(BaseModel):
|
|
142
|
-
name: str
|
|
142
|
+
name: str = Field(..., description="New name for the evaluation run", min_length=1, max_length=255)
|
agno/os/routers/health.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from datetime import datetime, timezone
|
|
2
|
+
|
|
1
3
|
from fastapi import APIRouter
|
|
2
4
|
|
|
3
5
|
from agno.os.schema import HealthResponse
|
|
@@ -6,6 +8,8 @@ from agno.os.schema import HealthResponse
|
|
|
6
8
|
def get_health_router() -> APIRouter:
|
|
7
9
|
router = APIRouter(tags=["Health"])
|
|
8
10
|
|
|
11
|
+
started_time_stamp = datetime.now(timezone.utc).timestamp()
|
|
12
|
+
|
|
9
13
|
@router.get(
|
|
10
14
|
"/health",
|
|
11
15
|
operation_id="health_check",
|
|
@@ -15,11 +19,11 @@ def get_health_router() -> APIRouter:
|
|
|
15
19
|
responses={
|
|
16
20
|
200: {
|
|
17
21
|
"description": "API is healthy and operational",
|
|
18
|
-
"content": {"application/json": {"example": {"status": "ok"}}},
|
|
22
|
+
"content": {"application/json": {"example": {"status": "ok", "instantiated_at": "1760169236.778903"}}},
|
|
19
23
|
}
|
|
20
24
|
},
|
|
21
25
|
)
|
|
22
26
|
async def health_check() -> HealthResponse:
|
|
23
|
-
return HealthResponse(status="ok")
|
|
27
|
+
return HealthResponse(status="ok", instantiated_at=str(started_time_stamp))
|
|
24
28
|
|
|
25
29
|
return router
|
|
@@ -16,23 +16,23 @@ class ContentStatus(str, Enum):
|
|
|
16
16
|
class ContentStatusResponse(BaseModel):
|
|
17
17
|
"""Response model for content status endpoint."""
|
|
18
18
|
|
|
19
|
-
status: ContentStatus
|
|
20
|
-
status_message: str = ""
|
|
19
|
+
status: ContentStatus = Field(..., description="Current processing status of the content")
|
|
20
|
+
status_message: str = Field("", description="Status message or error details")
|
|
21
21
|
|
|
22
22
|
|
|
23
23
|
class ContentResponseSchema(BaseModel):
|
|
24
|
-
id: str
|
|
25
|
-
name: Optional[str] = None
|
|
26
|
-
description: Optional[str] = None
|
|
27
|
-
type: Optional[str] = None
|
|
28
|
-
size: Optional[str] = None
|
|
29
|
-
linked_to: Optional[str] = None
|
|
30
|
-
metadata: Optional[dict] = None
|
|
31
|
-
access_count: Optional[int] = None
|
|
32
|
-
status: Optional[ContentStatus] = None
|
|
33
|
-
status_message: Optional[str] = None
|
|
34
|
-
created_at: Optional[datetime] = None
|
|
35
|
-
updated_at: Optional[datetime] = None
|
|
24
|
+
id: str = Field(..., description="Unique identifier for the content")
|
|
25
|
+
name: Optional[str] = Field(None, description="Name of the content")
|
|
26
|
+
description: Optional[str] = Field(None, description="Description of the content")
|
|
27
|
+
type: Optional[str] = Field(None, description="MIME type of the content")
|
|
28
|
+
size: Optional[str] = Field(None, description="Size of the content in bytes")
|
|
29
|
+
linked_to: Optional[str] = Field(None, description="ID of related content if linked")
|
|
30
|
+
metadata: Optional[dict] = Field(None, description="Additional metadata as key-value pairs")
|
|
31
|
+
access_count: Optional[int] = Field(None, description="Number of times content has been accessed", ge=0)
|
|
32
|
+
status: Optional[ContentStatus] = Field(None, description="Processing status of the content")
|
|
33
|
+
status_message: Optional[str] = Field(None, description="Status message or error details")
|
|
34
|
+
created_at: Optional[datetime] = Field(None, description="Timestamp when content was created")
|
|
35
|
+
updated_at: Optional[datetime] = Field(None, description="Timestamp when content was last updated")
|
|
36
36
|
|
|
37
37
|
@classmethod
|
|
38
38
|
def from_dict(cls, content: Dict[str, Any]) -> "ContentResponseSchema":
|
|
@@ -99,37 +99,39 @@ class ContentUpdateSchema(BaseModel):
|
|
|
99
99
|
|
|
100
100
|
|
|
101
101
|
class ReaderSchema(BaseModel):
|
|
102
|
-
id: str
|
|
103
|
-
name: Optional[str] = None
|
|
104
|
-
description: Optional[str] = None
|
|
105
|
-
chunkers: Optional[List[str]] = None
|
|
102
|
+
id: str = Field(..., description="Unique identifier for the reader")
|
|
103
|
+
name: Optional[str] = Field(None, description="Name of the reader")
|
|
104
|
+
description: Optional[str] = Field(None, description="Description of the reader's capabilities")
|
|
105
|
+
chunkers: Optional[List[str]] = Field(None, description="List of supported chunking strategies")
|
|
106
106
|
|
|
107
107
|
|
|
108
108
|
class ChunkerSchema(BaseModel):
|
|
109
|
-
key: str
|
|
110
|
-
name: Optional[str] = None
|
|
111
|
-
description: Optional[str] = None
|
|
109
|
+
key: str = Field(..., description="Unique key for the chunker")
|
|
110
|
+
name: Optional[str] = Field(None, description="Name of the chunker")
|
|
111
|
+
description: Optional[str] = Field(None, description="Description of the chunking strategy")
|
|
112
112
|
|
|
113
113
|
|
|
114
114
|
class VectorDbSchema(BaseModel):
|
|
115
|
-
id: str
|
|
116
|
-
name: Optional[str] = None
|
|
117
|
-
description: Optional[str] = None
|
|
118
|
-
search_types: Optional[List[str]] =
|
|
115
|
+
id: str = Field(..., description="Unique identifier for the vector database")
|
|
116
|
+
name: Optional[str] = Field(None, description="Name of the vector database")
|
|
117
|
+
description: Optional[str] = Field(None, description="Description of the vector database")
|
|
118
|
+
search_types: Optional[List[str]] = Field(
|
|
119
|
+
None, description="List of supported search types (vector, keyword, hybrid)"
|
|
120
|
+
)
|
|
119
121
|
|
|
120
122
|
|
|
121
123
|
class VectorSearchResult(BaseModel):
|
|
122
124
|
"""Schema for search result documents."""
|
|
123
125
|
|
|
124
|
-
id: str
|
|
125
|
-
content: str
|
|
126
|
-
name: Optional[str] = None
|
|
127
|
-
meta_data: Optional[Dict[str, Any]] = None
|
|
128
|
-
usage: Optional[Dict[str, Any]] = None
|
|
129
|
-
reranking_score: Optional[float] = None
|
|
130
|
-
content_id: Optional[str] = None
|
|
131
|
-
content_origin: Optional[str] = None
|
|
132
|
-
size: Optional[int] = None
|
|
126
|
+
id: str = Field(..., description="Unique identifier for the search result document")
|
|
127
|
+
content: str = Field(..., description="Content text of the document")
|
|
128
|
+
name: Optional[str] = Field(None, description="Name of the document")
|
|
129
|
+
meta_data: Optional[Dict[str, Any]] = Field(None, description="Metadata associated with the document")
|
|
130
|
+
usage: Optional[Dict[str, Any]] = Field(None, description="Usage statistics (e.g., token counts)")
|
|
131
|
+
reranking_score: Optional[float] = Field(None, description="Reranking score for relevance", ge=0.0, le=1.0)
|
|
132
|
+
content_id: Optional[str] = Field(None, description="ID of the source content")
|
|
133
|
+
content_origin: Optional[str] = Field(None, description="Origin URL or source of the content")
|
|
134
|
+
size: Optional[int] = Field(None, description="Size of the content in bytes", ge=0)
|
|
133
135
|
|
|
134
136
|
@classmethod
|
|
135
137
|
def from_document(cls, document) -> "VectorSearchResult":
|
|
@@ -153,23 +155,23 @@ class VectorSearchRequestSchema(BaseModel):
|
|
|
153
155
|
class Meta(BaseModel):
|
|
154
156
|
"""Inline metadata schema for pagination."""
|
|
155
157
|
|
|
156
|
-
limit:
|
|
157
|
-
page:
|
|
158
|
+
limit: int = Field(20, description="Number of results per page", ge=1, le=100)
|
|
159
|
+
page: int = Field(1, description="Page number", ge=1)
|
|
158
160
|
|
|
159
|
-
query: str = Field(..., description="The search query")
|
|
160
|
-
db_id: Optional[str] = Field(None, description="The content database
|
|
161
|
-
vector_db_ids: Optional[List[str]] = Field(None, description="List of vector database
|
|
162
|
-
search_type: Optional[str] = Field(None, description="The type of search to perform")
|
|
163
|
-
max_results: Optional[int] = Field(None, description="The maximum number of results to return")
|
|
164
|
-
filters: Optional[Dict[str, Any]] = Field(None, description="
|
|
161
|
+
query: str = Field(..., description="The search query text")
|
|
162
|
+
db_id: Optional[str] = Field(None, description="The content database ID to search in")
|
|
163
|
+
vector_db_ids: Optional[List[str]] = Field(None, description="List of vector database IDs to search in")
|
|
164
|
+
search_type: Optional[str] = Field(None, description="The type of search to perform (vector, keyword, hybrid)")
|
|
165
|
+
max_results: Optional[int] = Field(None, description="The maximum number of results to return", ge=1, le=1000)
|
|
166
|
+
filters: Optional[Dict[str, Any]] = Field(None, description="Filters to apply to the search results")
|
|
165
167
|
meta: Optional[Meta] = Field(
|
|
166
168
|
None, description="Pagination metadata. Limit and page number to return a subset of results."
|
|
167
169
|
)
|
|
168
170
|
|
|
169
171
|
|
|
170
172
|
class ConfigResponseSchema(BaseModel):
|
|
171
|
-
readers: Optional[Dict[str, ReaderSchema]] = None
|
|
172
|
-
readersForType: Optional[Dict[str, List[str]]] = None
|
|
173
|
-
chunkers: Optional[Dict[str, ChunkerSchema]] = None
|
|
174
|
-
filters: Optional[List[str]] = None
|
|
175
|
-
vector_dbs: Optional[List[VectorDbSchema]] = None
|
|
173
|
+
readers: Optional[Dict[str, ReaderSchema]] = Field(None, description="Available content readers")
|
|
174
|
+
readersForType: Optional[Dict[str, List[str]]] = Field(None, description="Mapping of content types to reader IDs")
|
|
175
|
+
chunkers: Optional[Dict[str, ChunkerSchema]] = Field(None, description="Available chunking strategies")
|
|
176
|
+
filters: Optional[List[str]] = Field(None, description="Available filter tags")
|
|
177
|
+
vector_dbs: Optional[List[VectorDbSchema]] = Field(None, description="Configured vector databases")
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
from datetime import datetime, timezone
|
|
2
2
|
from typing import Any, Dict, List, Optional
|
|
3
3
|
|
|
4
|
-
from pydantic import BaseModel
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class DeleteMemoriesRequest(BaseModel):
|
|
8
|
-
memory_ids: List[str]
|
|
9
|
-
user_id: Optional[str] = None
|
|
8
|
+
memory_ids: List[str] = Field(..., description="List of memory IDs to delete", min_length=1)
|
|
9
|
+
user_id: Optional[str] = Field(None, description="User ID to filter memories for deletion")
|
|
10
10
|
|
|
11
11
|
|
|
12
12
|
class UserMemorySchema(BaseModel):
|
|
13
|
-
memory_id: str
|
|
14
|
-
memory: str
|
|
15
|
-
topics: Optional[List[str]]
|
|
13
|
+
memory_id: str = Field(..., description="Unique identifier for the memory")
|
|
14
|
+
memory: str = Field(..., description="Memory content text", min_length=1)
|
|
15
|
+
topics: Optional[List[str]] = Field(None, description="Topics or tags associated with the memory")
|
|
16
16
|
|
|
17
|
-
agent_id: Optional[str]
|
|
18
|
-
team_id: Optional[str]
|
|
19
|
-
user_id: Optional[str]
|
|
17
|
+
agent_id: Optional[str] = Field(None, description="Agent ID associated with this memory")
|
|
18
|
+
team_id: Optional[str] = Field(None, description="Team ID associated with this memory")
|
|
19
|
+
user_id: Optional[str] = Field(None, description="User ID who owns this memory")
|
|
20
20
|
|
|
21
|
-
updated_at: Optional[datetime]
|
|
21
|
+
updated_at: Optional[datetime] = Field(None, description="Timestamp when memory was last updated")
|
|
22
22
|
|
|
23
23
|
@classmethod
|
|
24
24
|
def from_dict(cls, memory_dict: Dict[str, Any]) -> "UserMemorySchema":
|
|
@@ -36,17 +36,17 @@ class UserMemorySchema(BaseModel):
|
|
|
36
36
|
class UserMemoryCreateSchema(BaseModel):
|
|
37
37
|
"""Define the payload expected for creating a new user memory"""
|
|
38
38
|
|
|
39
|
-
memory: str
|
|
40
|
-
user_id: Optional[str] = None
|
|
41
|
-
topics: Optional[List[str]] = None
|
|
39
|
+
memory: str = Field(..., description="Memory content text", min_length=1, max_length=5000)
|
|
40
|
+
user_id: Optional[str] = Field(None, description="User ID who owns this memory")
|
|
41
|
+
topics: Optional[List[str]] = Field(None, description="Topics or tags to categorize the memory")
|
|
42
42
|
|
|
43
43
|
|
|
44
44
|
class UserStatsSchema(BaseModel):
|
|
45
45
|
"""Schema for user memory statistics"""
|
|
46
46
|
|
|
47
|
-
user_id: str
|
|
48
|
-
total_memories: int
|
|
49
|
-
last_memory_updated_at: Optional[datetime] = None
|
|
47
|
+
user_id: str = Field(..., description="User ID")
|
|
48
|
+
total_memories: int = Field(..., description="Total number of memories for this user", ge=0)
|
|
49
|
+
last_memory_updated_at: Optional[datetime] = Field(None, description="Timestamp of the most recent memory update")
|
|
50
50
|
|
|
51
51
|
@classmethod
|
|
52
52
|
def from_dict(cls, user_stats_dict: Dict[str, Any]) -> "UserStatsSchema":
|
|
@@ -1,27 +1,27 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
2
|
from typing import Any, Dict, List, Optional
|
|
3
3
|
|
|
4
|
-
from pydantic import BaseModel
|
|
4
|
+
from pydantic import BaseModel, Field
|
|
5
5
|
|
|
6
6
|
|
|
7
7
|
class DayAggregatedMetrics(BaseModel):
|
|
8
8
|
"""Aggregated metrics for a given day"""
|
|
9
9
|
|
|
10
|
-
id: str
|
|
10
|
+
id: str = Field(..., description="Unique identifier for the metrics record")
|
|
11
11
|
|
|
12
|
-
agent_runs_count: int
|
|
13
|
-
agent_sessions_count: int
|
|
14
|
-
team_runs_count: int
|
|
15
|
-
team_sessions_count: int
|
|
16
|
-
workflow_runs_count: int
|
|
17
|
-
workflow_sessions_count: int
|
|
18
|
-
users_count: int
|
|
19
|
-
token_metrics: Dict[str, Any]
|
|
20
|
-
model_metrics: List[Dict[str, Any]]
|
|
12
|
+
agent_runs_count: int = Field(..., description="Total number of agent runs", ge=0)
|
|
13
|
+
agent_sessions_count: int = Field(..., description="Total number of agent sessions", ge=0)
|
|
14
|
+
team_runs_count: int = Field(..., description="Total number of team runs", ge=0)
|
|
15
|
+
team_sessions_count: int = Field(..., description="Total number of team sessions", ge=0)
|
|
16
|
+
workflow_runs_count: int = Field(..., description="Total number of workflow runs", ge=0)
|
|
17
|
+
workflow_sessions_count: int = Field(..., description="Total number of workflow sessions", ge=0)
|
|
18
|
+
users_count: int = Field(..., description="Total number of unique users", ge=0)
|
|
19
|
+
token_metrics: Dict[str, Any] = Field(..., description="Token usage metrics (input, output, cached, etc.)")
|
|
20
|
+
model_metrics: List[Dict[str, Any]] = Field(..., description="Metrics grouped by model (model_id, provider, count)")
|
|
21
21
|
|
|
22
|
-
date: datetime
|
|
23
|
-
created_at: int
|
|
24
|
-
updated_at: int
|
|
22
|
+
date: datetime = Field(..., description="Date for which these metrics are aggregated")
|
|
23
|
+
created_at: int = Field(..., description="Unix timestamp when metrics were created", ge=0)
|
|
24
|
+
updated_at: int = Field(..., description="Unix timestamp when metrics were last updated", ge=0)
|
|
25
25
|
|
|
26
26
|
@classmethod
|
|
27
27
|
def from_dict(cls, metrics_dict: Dict[str, Any]) -> "DayAggregatedMetrics":
|
|
@@ -43,5 +43,5 @@ class DayAggregatedMetrics(BaseModel):
|
|
|
43
43
|
|
|
44
44
|
|
|
45
45
|
class MetricsResponse(BaseModel):
|
|
46
|
-
metrics: List[DayAggregatedMetrics]
|
|
47
|
-
updated_at: Optional[datetime]
|
|
46
|
+
metrics: List[DayAggregatedMetrics] = Field(..., description="List of daily aggregated metrics")
|
|
47
|
+
updated_at: Optional[datetime] = Field(None, description="Timestamp of the most recent metrics update")
|