agno 2.2.7__py3-none-any.whl → 2.2.9__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 +23 -15
- agno/db/base.py +23 -0
- agno/db/dynamo/dynamo.py +20 -25
- agno/db/dynamo/schemas.py +1 -0
- agno/db/firestore/firestore.py +11 -0
- agno/db/gcs_json/gcs_json_db.py +4 -0
- agno/db/in_memory/in_memory_db.py +4 -0
- agno/db/json/json_db.py +4 -0
- agno/db/mongo/async_mongo.py +27 -0
- agno/db/mongo/mongo.py +25 -0
- agno/db/mysql/mysql.py +26 -1
- agno/db/postgres/async_postgres.py +26 -1
- agno/db/postgres/postgres.py +26 -1
- agno/db/redis/redis.py +4 -0
- agno/db/singlestore/singlestore.py +24 -0
- agno/db/sqlite/async_sqlite.py +25 -1
- agno/db/sqlite/sqlite.py +25 -1
- agno/db/surrealdb/surrealdb.py +13 -1
- agno/knowledge/reader/docx_reader.py +0 -1
- agno/models/azure/ai_foundry.py +2 -1
- agno/models/cerebras/cerebras.py +3 -2
- agno/models/openai/chat.py +2 -1
- agno/models/openai/responses.py +2 -1
- agno/os/app.py +112 -50
- agno/os/config.py +1 -0
- agno/os/interfaces/agui/router.py +9 -0
- agno/os/interfaces/agui/utils.py +49 -3
- agno/os/mcp.py +8 -8
- agno/os/router.py +27 -9
- agno/os/routers/evals/evals.py +12 -7
- agno/os/routers/memory/memory.py +18 -10
- agno/os/routers/metrics/metrics.py +6 -4
- agno/os/routers/session/session.py +21 -11
- agno/os/utils.py +57 -11
- agno/team/team.py +26 -21
- agno/vectordb/__init__.py +1 -2
- agno/vectordb/mongodb/__init__.py +7 -1
- agno/vectordb/redis/__init__.py +4 -0
- {agno-2.2.7.dist-info → agno-2.2.9.dist-info}/METADATA +11 -13
- {agno-2.2.7.dist-info → agno-2.2.9.dist-info}/RECORD +43 -43
- {agno-2.2.7.dist-info → agno-2.2.9.dist-info}/WHEEL +0 -0
- {agno-2.2.7.dist-info → agno-2.2.9.dist-info}/licenses/LICENSE +0 -0
- {agno-2.2.7.dist-info → agno-2.2.9.dist-info}/top_level.txt +0 -0
agno/os/routers/evals/evals.py
CHANGED
|
@@ -34,7 +34,7 @@ logger = logging.getLogger(__name__)
|
|
|
34
34
|
|
|
35
35
|
|
|
36
36
|
def get_eval_router(
|
|
37
|
-
dbs: dict[str, Union[BaseDb, AsyncBaseDb]],
|
|
37
|
+
dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]],
|
|
38
38
|
agents: Optional[List[Agent]] = None,
|
|
39
39
|
teams: Optional[List[Team]] = None,
|
|
40
40
|
settings: AgnoAPISettings = AgnoAPISettings(),
|
|
@@ -56,7 +56,7 @@ def get_eval_router(
|
|
|
56
56
|
|
|
57
57
|
def attach_routes(
|
|
58
58
|
router: APIRouter,
|
|
59
|
-
dbs: dict[str, Union[BaseDb, AsyncBaseDb]],
|
|
59
|
+
dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]],
|
|
60
60
|
agents: Optional[List[Agent]] = None,
|
|
61
61
|
teams: Optional[List[Team]] = None,
|
|
62
62
|
) -> APIRouter:
|
|
@@ -115,8 +115,9 @@ def attach_routes(
|
|
|
115
115
|
sort_by: Optional[str] = Query(default="created_at", description="Field to sort by"),
|
|
116
116
|
sort_order: Optional[SortOrder] = Query(default="desc", description="Sort order (asc or desc)"),
|
|
117
117
|
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
118
|
+
table: Optional[str] = Query(default=None, description="The database table to use"),
|
|
118
119
|
) -> PaginatedResponse[EvalSchema]:
|
|
119
|
-
db = get_db(dbs, db_id)
|
|
120
|
+
db = await get_db(dbs, db_id, table)
|
|
120
121
|
|
|
121
122
|
if isinstance(db, AsyncBaseDb):
|
|
122
123
|
db = cast(AsyncBaseDb, db)
|
|
@@ -198,8 +199,9 @@ def attach_routes(
|
|
|
198
199
|
async def get_eval_run(
|
|
199
200
|
eval_run_id: str,
|
|
200
201
|
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
202
|
+
table: Optional[str] = Query(default=None, description="Table to query eval run from"),
|
|
201
203
|
) -> EvalSchema:
|
|
202
|
-
db = get_db(dbs, db_id)
|
|
204
|
+
db = await get_db(dbs, db_id, table)
|
|
203
205
|
if isinstance(db, AsyncBaseDb):
|
|
204
206
|
db = cast(AsyncBaseDb, db)
|
|
205
207
|
eval_run = await db.get_eval_run(eval_run_id=eval_run_id, deserialize=False)
|
|
@@ -224,9 +226,10 @@ def attach_routes(
|
|
|
224
226
|
async def delete_eval_runs(
|
|
225
227
|
request: DeleteEvalRunsRequest,
|
|
226
228
|
db_id: Optional[str] = Query(default=None, description="Database ID to use for deletion"),
|
|
229
|
+
table: Optional[str] = Query(default=None, description="Table to use for deletion"),
|
|
227
230
|
) -> None:
|
|
228
231
|
try:
|
|
229
|
-
db = get_db(dbs, db_id)
|
|
232
|
+
db = await get_db(dbs, db_id, table)
|
|
230
233
|
if isinstance(db, AsyncBaseDb):
|
|
231
234
|
db = cast(AsyncBaseDb, db)
|
|
232
235
|
await db.delete_eval_runs(eval_run_ids=request.eval_run_ids)
|
|
@@ -277,9 +280,10 @@ def attach_routes(
|
|
|
277
280
|
eval_run_id: str,
|
|
278
281
|
request: UpdateEvalRunRequest,
|
|
279
282
|
db_id: Optional[str] = Query(default=None, description="The ID of the database to use"),
|
|
283
|
+
table: Optional[str] = Query(default=None, description="Table to use for rename operation"),
|
|
280
284
|
) -> EvalSchema:
|
|
281
285
|
try:
|
|
282
|
-
db = get_db(dbs, db_id)
|
|
286
|
+
db = await get_db(dbs, db_id, table)
|
|
283
287
|
if isinstance(db, AsyncBaseDb):
|
|
284
288
|
db = cast(AsyncBaseDb, db)
|
|
285
289
|
eval_run = await db.rename_eval_run(eval_run_id=eval_run_id, name=request.name, deserialize=False)
|
|
@@ -336,8 +340,9 @@ def attach_routes(
|
|
|
336
340
|
async def run_eval(
|
|
337
341
|
eval_run_input: EvalRunInput,
|
|
338
342
|
db_id: Optional[str] = Query(default=None, description="Database ID to use for evaluation"),
|
|
343
|
+
table: Optional[str] = Query(default=None, description="Table to use for evaluation"),
|
|
339
344
|
) -> Optional[EvalSchema]:
|
|
340
|
-
db = get_db(dbs, db_id)
|
|
345
|
+
db = await get_db(dbs, db_id, table)
|
|
341
346
|
|
|
342
347
|
if eval_run_input.agent_id and eval_run_input.team_id:
|
|
343
348
|
raise HTTPException(status_code=400, detail="Only one of agent_id or team_id must be provided")
|
agno/os/routers/memory/memory.py
CHANGED
|
@@ -32,7 +32,7 @@ logger = logging.getLogger(__name__)
|
|
|
32
32
|
|
|
33
33
|
|
|
34
34
|
def get_memory_router(
|
|
35
|
-
dbs: dict[str, Union[BaseDb, AsyncBaseDb]], settings: AgnoAPISettings = AgnoAPISettings(), **kwargs
|
|
35
|
+
dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]], settings: AgnoAPISettings = AgnoAPISettings(), **kwargs
|
|
36
36
|
) -> APIRouter:
|
|
37
37
|
"""Create memory router with comprehensive OpenAPI documentation for user memory management endpoints."""
|
|
38
38
|
router = APIRouter(
|
|
@@ -49,7 +49,7 @@ def get_memory_router(
|
|
|
49
49
|
return attach_routes(router=router, dbs=dbs)
|
|
50
50
|
|
|
51
51
|
|
|
52
|
-
def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]]) -> APIRouter:
|
|
52
|
+
def attach_routes(router: APIRouter, dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]]) -> APIRouter:
|
|
53
53
|
@router.post(
|
|
54
54
|
"/memories",
|
|
55
55
|
response_model=UserMemorySchema,
|
|
@@ -85,6 +85,7 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
85
85
|
request: Request,
|
|
86
86
|
payload: UserMemoryCreateSchema,
|
|
87
87
|
db_id: Optional[str] = Query(default=None, description="Database ID to use for memory storage"),
|
|
88
|
+
table: Optional[str] = Query(default=None, description="Table to use for memory storage"),
|
|
88
89
|
) -> UserMemorySchema:
|
|
89
90
|
if hasattr(request.state, "user_id"):
|
|
90
91
|
user_id = request.state.user_id
|
|
@@ -93,7 +94,7 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
93
94
|
if payload.user_id is None:
|
|
94
95
|
raise HTTPException(status_code=400, detail="User ID is required")
|
|
95
96
|
|
|
96
|
-
db = get_db(dbs, db_id)
|
|
97
|
+
db = await get_db(dbs, db_id, table)
|
|
97
98
|
|
|
98
99
|
if isinstance(db, AsyncBaseDb):
|
|
99
100
|
db = cast(AsyncBaseDb, db)
|
|
@@ -138,8 +139,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
138
139
|
memory_id: str = Path(description="Memory ID to delete"),
|
|
139
140
|
user_id: Optional[str] = Query(default=None, description="User ID to delete memory for"),
|
|
140
141
|
db_id: Optional[str] = Query(default=None, description="Database ID to use for deletion"),
|
|
142
|
+
table: Optional[str] = Query(default=None, description="Table to use for deletion"),
|
|
141
143
|
) -> None:
|
|
142
|
-
db = get_db(dbs, db_id)
|
|
144
|
+
db = await get_db(dbs, db_id, table)
|
|
143
145
|
if isinstance(db, AsyncBaseDb):
|
|
144
146
|
db = cast(AsyncBaseDb, db)
|
|
145
147
|
await db.delete_user_memory(memory_id=memory_id, user_id=user_id)
|
|
@@ -164,8 +166,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
164
166
|
async def delete_memories(
|
|
165
167
|
request: DeleteMemoriesRequest,
|
|
166
168
|
db_id: Optional[str] = Query(default=None, description="Database ID to use for deletion"),
|
|
169
|
+
table: Optional[str] = Query(default=None, description="Table to use for deletion"),
|
|
167
170
|
) -> None:
|
|
168
|
-
db = get_db(dbs, db_id)
|
|
171
|
+
db = await get_db(dbs, db_id, table)
|
|
169
172
|
if isinstance(db, AsyncBaseDb):
|
|
170
173
|
db = cast(AsyncBaseDb, db)
|
|
171
174
|
await db.delete_user_memories(memory_ids=request.memory_ids, user_id=request.user_id)
|
|
@@ -217,8 +220,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
217
220
|
sort_by: Optional[str] = Query(default="updated_at", description="Field to sort memories by"),
|
|
218
221
|
sort_order: Optional[SortOrder] = Query(default="desc", description="Sort order (asc or desc)"),
|
|
219
222
|
db_id: Optional[str] = Query(default=None, description="Database ID to query memories from"),
|
|
223
|
+
table: Optional[str] = Query(default=None, description="The database table to use"),
|
|
220
224
|
) -> PaginatedResponse[UserMemorySchema]:
|
|
221
|
-
db = get_db(dbs, db_id)
|
|
225
|
+
db = await get_db(dbs, db_id, table)
|
|
222
226
|
|
|
223
227
|
if hasattr(request.state, "user_id"):
|
|
224
228
|
user_id = request.state.user_id
|
|
@@ -294,8 +298,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
294
298
|
memory_id: str = Path(description="Memory ID to retrieve"),
|
|
295
299
|
user_id: Optional[str] = Query(default=None, description="User ID to query memory for"),
|
|
296
300
|
db_id: Optional[str] = Query(default=None, description="Database ID to query memory from"),
|
|
301
|
+
table: Optional[str] = Query(default=None, description="Table to query memory from"),
|
|
297
302
|
) -> UserMemorySchema:
|
|
298
|
-
db = get_db(dbs, db_id)
|
|
303
|
+
db = await get_db(dbs, db_id, table)
|
|
299
304
|
|
|
300
305
|
if hasattr(request.state, "user_id"):
|
|
301
306
|
user_id = request.state.user_id
|
|
@@ -343,8 +348,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
343
348
|
)
|
|
344
349
|
async def get_topics(
|
|
345
350
|
db_id: Optional[str] = Query(default=None, description="Database ID to query topics from"),
|
|
351
|
+
table: Optional[str] = Query(default=None, description="Table to query topics from"),
|
|
346
352
|
) -> List[str]:
|
|
347
|
-
db = get_db(dbs, db_id)
|
|
353
|
+
db = await get_db(dbs, db_id, table)
|
|
348
354
|
if isinstance(db, AsyncBaseDb):
|
|
349
355
|
db = cast(AsyncBaseDb, db)
|
|
350
356
|
return await db.get_all_memory_topics()
|
|
@@ -389,6 +395,7 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
389
395
|
payload: UserMemoryCreateSchema,
|
|
390
396
|
memory_id: str = Path(description="Memory ID to update"),
|
|
391
397
|
db_id: Optional[str] = Query(default=None, description="Database ID to use for update"),
|
|
398
|
+
table: Optional[str] = Query(default=None, description="Table to use for update"),
|
|
392
399
|
) -> UserMemorySchema:
|
|
393
400
|
if hasattr(request.state, "user_id"):
|
|
394
401
|
user_id = request.state.user_id
|
|
@@ -397,7 +404,7 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
397
404
|
if payload.user_id is None:
|
|
398
405
|
raise HTTPException(status_code=400, detail="User ID is required")
|
|
399
406
|
|
|
400
|
-
db = get_db(dbs, db_id)
|
|
407
|
+
db = await get_db(dbs, db_id, table)
|
|
401
408
|
|
|
402
409
|
if isinstance(db, AsyncBaseDb):
|
|
403
410
|
db = cast(AsyncBaseDb, db)
|
|
@@ -459,8 +466,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
459
466
|
limit: Optional[int] = Query(default=20, description="Number of user statistics to return per page"),
|
|
460
467
|
page: Optional[int] = Query(default=1, description="Page number for pagination"),
|
|
461
468
|
db_id: Optional[str] = Query(default=None, description="Database ID to query statistics from"),
|
|
469
|
+
table: Optional[str] = Query(default=None, description="Table to query statistics from"),
|
|
462
470
|
) -> PaginatedResponse[UserStatsSchema]:
|
|
463
|
-
db = get_db(dbs, db_id)
|
|
471
|
+
db = await get_db(dbs, db_id, table)
|
|
464
472
|
try:
|
|
465
473
|
if isinstance(db, AsyncBaseDb):
|
|
466
474
|
db = cast(AsyncBaseDb, db)
|
|
@@ -22,7 +22,7 @@ logger = logging.getLogger(__name__)
|
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
def get_metrics_router(
|
|
25
|
-
dbs: dict[str, Union[BaseDb, AsyncBaseDb]], settings: AgnoAPISettings = AgnoAPISettings(), **kwargs
|
|
25
|
+
dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]], settings: AgnoAPISettings = AgnoAPISettings(), **kwargs
|
|
26
26
|
) -> APIRouter:
|
|
27
27
|
"""Create metrics router with comprehensive OpenAPI documentation for system metrics and analytics endpoints."""
|
|
28
28
|
router = APIRouter(
|
|
@@ -39,7 +39,7 @@ def get_metrics_router(
|
|
|
39
39
|
return attach_routes(router=router, dbs=dbs)
|
|
40
40
|
|
|
41
41
|
|
|
42
|
-
def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]]) -> APIRouter:
|
|
42
|
+
def attach_routes(router: APIRouter, dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]]) -> APIRouter:
|
|
43
43
|
@router.get(
|
|
44
44
|
"/metrics",
|
|
45
45
|
response_model=MetricsResponse,
|
|
@@ -99,9 +99,10 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
99
99
|
default=None, description="Ending date for metrics range (YYYY-MM-DD format)"
|
|
100
100
|
),
|
|
101
101
|
db_id: Optional[str] = Query(default=None, description="Database ID to query metrics from"),
|
|
102
|
+
table: Optional[str] = Query(default=None, description="The database table to use"),
|
|
102
103
|
) -> MetricsResponse:
|
|
103
104
|
try:
|
|
104
|
-
db = get_db(dbs, db_id)
|
|
105
|
+
db = await get_db(dbs, db_id, table)
|
|
105
106
|
if isinstance(db, AsyncBaseDb):
|
|
106
107
|
db = cast(AsyncBaseDb, db)
|
|
107
108
|
metrics, latest_updated_at = await db.get_metrics(starting_date=starting_date, ending_date=ending_date)
|
|
@@ -169,9 +170,10 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
169
170
|
)
|
|
170
171
|
async def calculate_metrics(
|
|
171
172
|
db_id: Optional[str] = Query(default=None, description="Database ID to use for metrics calculation"),
|
|
173
|
+
table: Optional[str] = Query(default=None, description="Table to use for metrics calculation"),
|
|
172
174
|
) -> List[DayAggregatedMetrics]:
|
|
173
175
|
try:
|
|
174
|
-
db = get_db(dbs, db_id)
|
|
176
|
+
db = await get_db(dbs, db_id, table)
|
|
175
177
|
if isinstance(db, AsyncBaseDb):
|
|
176
178
|
db = cast(AsyncBaseDb, db)
|
|
177
179
|
result = await db.calculate_metrics()
|
|
@@ -35,7 +35,7 @@ logger = logging.getLogger(__name__)
|
|
|
35
35
|
|
|
36
36
|
|
|
37
37
|
def get_session_router(
|
|
38
|
-
dbs: dict[str, Union[BaseDb, AsyncBaseDb]], settings: AgnoAPISettings = AgnoAPISettings()
|
|
38
|
+
dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]], settings: AgnoAPISettings = AgnoAPISettings()
|
|
39
39
|
) -> APIRouter:
|
|
40
40
|
"""Create session router with comprehensive OpenAPI documentation for session management endpoints."""
|
|
41
41
|
session_router = APIRouter(
|
|
@@ -52,7 +52,7 @@ def get_session_router(
|
|
|
52
52
|
return attach_routes(router=session_router, dbs=dbs)
|
|
53
53
|
|
|
54
54
|
|
|
55
|
-
def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]]) -> APIRouter:
|
|
55
|
+
def attach_routes(router: APIRouter, dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]]) -> APIRouter:
|
|
56
56
|
@router.get(
|
|
57
57
|
"/sessions",
|
|
58
58
|
response_model=PaginatedResponse[SessionSchema],
|
|
@@ -89,6 +89,7 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
89
89
|
},
|
|
90
90
|
},
|
|
91
91
|
400: {"description": "Invalid session type or filter parameters", "model": BadRequestResponse},
|
|
92
|
+
404: {"description": "Not found", "model": NotFoundResponse},
|
|
92
93
|
422: {"description": "Validation error in query parameters", "model": ValidationErrorResponse},
|
|
93
94
|
},
|
|
94
95
|
)
|
|
@@ -109,8 +110,12 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
109
110
|
sort_by: Optional[str] = Query(default="created_at", description="Field to sort sessions by"),
|
|
110
111
|
sort_order: Optional[SortOrder] = Query(default="desc", description="Sort order (asc or desc)"),
|
|
111
112
|
db_id: Optional[str] = Query(default=None, description="Database ID to query sessions from"),
|
|
113
|
+
table: Optional[str] = Query(default=None, description="The database table to use"),
|
|
112
114
|
) -> PaginatedResponse[SessionSchema]:
|
|
113
|
-
|
|
115
|
+
try:
|
|
116
|
+
db = await get_db(dbs, db_id, table)
|
|
117
|
+
except Exception as e:
|
|
118
|
+
raise HTTPException(status_code=404, detail=f"{e}")
|
|
114
119
|
|
|
115
120
|
if hasattr(request.state, "user_id"):
|
|
116
121
|
user_id = request.state.user_id
|
|
@@ -202,7 +207,7 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
202
207
|
),
|
|
203
208
|
db_id: Optional[str] = Query(default=None, description="Database ID to create session in"),
|
|
204
209
|
) -> Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema]:
|
|
205
|
-
db = get_db(dbs, db_id)
|
|
210
|
+
db = await get_db(dbs, db_id)
|
|
206
211
|
|
|
207
212
|
# Get user_id from request state if available (from auth middleware)
|
|
208
213
|
user_id = create_session_request.user_id
|
|
@@ -373,8 +378,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
373
378
|
),
|
|
374
379
|
user_id: Optional[str] = Query(default=None, description="User ID to query session from"),
|
|
375
380
|
db_id: Optional[str] = Query(default=None, description="Database ID to query session from"),
|
|
381
|
+
table: Optional[str] = Query(default=None, description="Table to query session from"),
|
|
376
382
|
) -> Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema]:
|
|
377
|
-
db = get_db(dbs, db_id)
|
|
383
|
+
db = await get_db(dbs, db_id, table)
|
|
378
384
|
|
|
379
385
|
if hasattr(request.state, "user_id"):
|
|
380
386
|
user_id = request.state.user_id
|
|
@@ -528,8 +534,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
528
534
|
description="Filter runs created before this Unix timestamp (epoch time in seconds)",
|
|
529
535
|
),
|
|
530
536
|
db_id: Optional[str] = Query(default=None, description="Database ID to query runs from"),
|
|
537
|
+
table: Optional[str] = Query(default=None, description="Table to query runs from"),
|
|
531
538
|
) -> List[Union[RunSchema, TeamRunSchema, WorkflowRunSchema]]:
|
|
532
|
-
db = get_db(dbs, db_id)
|
|
539
|
+
db = await get_db(dbs, db_id, table)
|
|
533
540
|
|
|
534
541
|
if hasattr(request.state, "user_id"):
|
|
535
542
|
user_id = request.state.user_id
|
|
@@ -644,7 +651,7 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
644
651
|
user_id: Optional[str] = Query(default=None, description="User ID to query run from"),
|
|
645
652
|
db_id: Optional[str] = Query(default=None, description="Database ID to query run from"),
|
|
646
653
|
) -> Union[RunSchema, TeamRunSchema, WorkflowRunSchema]:
|
|
647
|
-
db = get_db(dbs, db_id)
|
|
654
|
+
db = await get_db(dbs, db_id)
|
|
648
655
|
|
|
649
656
|
if hasattr(request.state, "user_id"):
|
|
650
657
|
user_id = request.state.user_id
|
|
@@ -702,8 +709,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
702
709
|
async def delete_session(
|
|
703
710
|
session_id: str = Path(description="Session ID to delete"),
|
|
704
711
|
db_id: Optional[str] = Query(default=None, description="Database ID to use for deletion"),
|
|
712
|
+
table: Optional[str] = Query(default=None, description="Table to use for deletion"),
|
|
705
713
|
) -> None:
|
|
706
|
-
db = get_db(dbs, db_id)
|
|
714
|
+
db = await get_db(dbs, db_id, table)
|
|
707
715
|
if isinstance(db, AsyncBaseDb):
|
|
708
716
|
db = cast(AsyncBaseDb, db)
|
|
709
717
|
await db.delete_session(session_id=session_id)
|
|
@@ -734,11 +742,12 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
734
742
|
default=SessionType.AGENT, description="Default session type filter", alias="type"
|
|
735
743
|
),
|
|
736
744
|
db_id: Optional[str] = Query(default=None, description="Database ID to use for deletion"),
|
|
745
|
+
table: Optional[str] = Query(default=None, description="Table to use for deletion"),
|
|
737
746
|
) -> None:
|
|
738
747
|
if len(request.session_ids) != len(request.session_types):
|
|
739
748
|
raise HTTPException(status_code=400, detail="Session IDs and session types must have the same length")
|
|
740
749
|
|
|
741
|
-
db = get_db(dbs, db_id)
|
|
750
|
+
db = await get_db(dbs, db_id, table)
|
|
742
751
|
if isinstance(db, AsyncBaseDb):
|
|
743
752
|
db = cast(AsyncBaseDb, db)
|
|
744
753
|
await db.delete_sessions(session_ids=request.session_ids)
|
|
@@ -840,8 +849,9 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
840
849
|
),
|
|
841
850
|
session_name: str = Body(embed=True, description="New name for the session"),
|
|
842
851
|
db_id: Optional[str] = Query(default=None, description="Database ID to use for rename operation"),
|
|
852
|
+
table: Optional[str] = Query(default=None, description="Table to use for rename operation"),
|
|
843
853
|
) -> Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema]:
|
|
844
|
-
db = get_db(dbs, db_id)
|
|
854
|
+
db = await get_db(dbs, db_id, table)
|
|
845
855
|
if isinstance(db, AsyncBaseDb):
|
|
846
856
|
db = cast(AsyncBaseDb, db)
|
|
847
857
|
session = await db.rename_session(
|
|
@@ -926,7 +936,7 @@ def attach_routes(router: APIRouter, dbs: dict[str, Union[BaseDb, AsyncBaseDb]])
|
|
|
926
936
|
user_id: Optional[str] = Query(default=None, description="User ID"),
|
|
927
937
|
db_id: Optional[str] = Query(default=None, description="Database ID to use for update operation"),
|
|
928
938
|
) -> Union[AgentSessionDetailSchema, TeamSessionDetailSchema, WorkflowSessionDetailSchema]:
|
|
929
|
-
db = get_db(dbs, db_id)
|
|
939
|
+
db = await get_db(dbs, db_id)
|
|
930
940
|
|
|
931
941
|
if hasattr(request.state, "user_id"):
|
|
932
942
|
user_id = request.state.user_id
|
agno/os/utils.py
CHANGED
|
@@ -19,23 +19,69 @@ from agno.utils.log import logger
|
|
|
19
19
|
from agno.workflow.workflow import Workflow
|
|
20
20
|
|
|
21
21
|
|
|
22
|
-
def get_db(
|
|
23
|
-
|
|
22
|
+
async def get_db(
|
|
23
|
+
dbs: dict[str, list[Union[BaseDb, AsyncBaseDb]]], db_id: Optional[str] = None, table: Optional[str] = None
|
|
24
|
+
) -> Union[BaseDb, AsyncBaseDb]:
|
|
25
|
+
"""Return the database with the given ID and/or table, or the first database if no ID/table is provided."""
|
|
26
|
+
|
|
27
|
+
if table and not db_id:
|
|
28
|
+
raise HTTPException(status_code=400, detail="The db_id query parameter is required when passing a table")
|
|
29
|
+
|
|
30
|
+
async def _has_table(db: Union[BaseDb, AsyncBaseDb], table_name: str) -> bool:
|
|
31
|
+
"""Check if this database has the specified table (configured and actually exists)."""
|
|
32
|
+
# First check if table name is configured
|
|
33
|
+
is_configured = (
|
|
34
|
+
hasattr(db, "session_table_name")
|
|
35
|
+
and db.session_table_name == table_name
|
|
36
|
+
or hasattr(db, "memory_table_name")
|
|
37
|
+
and db.memory_table_name == table_name
|
|
38
|
+
or hasattr(db, "metrics_table_name")
|
|
39
|
+
and db.metrics_table_name == table_name
|
|
40
|
+
or hasattr(db, "eval_table_name")
|
|
41
|
+
and db.eval_table_name == table_name
|
|
42
|
+
or hasattr(db, "knowledge_table_name")
|
|
43
|
+
and db.knowledge_table_name == table_name
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
if not is_configured:
|
|
47
|
+
return False
|
|
48
|
+
|
|
49
|
+
# Then check if table actually exists in the database
|
|
50
|
+
try:
|
|
51
|
+
if isinstance(db, AsyncBaseDb):
|
|
52
|
+
# For async databases, await the check
|
|
53
|
+
return await db.table_exists(table_name)
|
|
54
|
+
else:
|
|
55
|
+
# For sync databases, call directly
|
|
56
|
+
return db.table_exists(table_name)
|
|
57
|
+
except (NotImplementedError, AttributeError):
|
|
58
|
+
# If table_exists not implemented, fall back to configuration check
|
|
59
|
+
return is_configured
|
|
60
|
+
|
|
61
|
+
# If db_id is provided, first find the database with that ID
|
|
62
|
+
if db_id:
|
|
63
|
+
target_db_list = dbs.get(db_id)
|
|
64
|
+
if not target_db_list:
|
|
65
|
+
raise HTTPException(status_code=404, detail=f"No database found with id '{db_id}'")
|
|
66
|
+
|
|
67
|
+
# If table is also specified, search through all databases with this ID to find one with the table
|
|
68
|
+
if table:
|
|
69
|
+
for db in target_db_list:
|
|
70
|
+
if await _has_table(db, table):
|
|
71
|
+
return db
|
|
72
|
+
raise HTTPException(status_code=404, detail=f"No database with id '{db_id}' has table '{table}'")
|
|
73
|
+
|
|
74
|
+
# If no table specified, return the first database with this ID
|
|
75
|
+
return target_db_list[0]
|
|
24
76
|
|
|
25
77
|
# Raise if multiple databases are provided but no db_id is provided
|
|
26
|
-
if
|
|
78
|
+
if len(dbs) > 1:
|
|
27
79
|
raise HTTPException(
|
|
28
80
|
status_code=400, detail="The db_id query parameter is required when using multiple databases"
|
|
29
81
|
)
|
|
30
82
|
|
|
31
|
-
#
|
|
32
|
-
|
|
33
|
-
db = dbs.get(db_id)
|
|
34
|
-
if not db:
|
|
35
|
-
raise HTTPException(status_code=404, detail=f"Database with id '{db_id}' not found")
|
|
36
|
-
else:
|
|
37
|
-
db = next(iter(dbs.values()))
|
|
38
|
-
return db
|
|
83
|
+
# Return the first (and only) database
|
|
84
|
+
return next(db for dbs in dbs.values() for db in dbs)
|
|
39
85
|
|
|
40
86
|
|
|
41
87
|
def get_knowledge_instance_by_db_id(knowledge_instances: List[Knowledge], db_id: Optional[str] = None) -> Knowledge:
|
agno/team/team.py
CHANGED
|
@@ -802,13 +802,10 @@ class Team:
|
|
|
802
802
|
member.team_id = self.id
|
|
803
803
|
member.set_id()
|
|
804
804
|
|
|
805
|
-
# Inherit team
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
log_info(
|
|
810
|
-
f"Agent '{member.name or member.id}' inheriting {model_type} from Team: {getattr(self, model_type).id}"
|
|
811
|
-
)
|
|
805
|
+
# Inherit team primary model if agent has no explicit model
|
|
806
|
+
if member.model is None and self.model is not None:
|
|
807
|
+
member.model = self.model
|
|
808
|
+
log_info(f"Agent '{member.name or member.id}' inheriting model from Team: {self.model.id}")
|
|
812
809
|
|
|
813
810
|
elif isinstance(member, Team):
|
|
814
811
|
member.parent_team_id = self.id
|
|
@@ -1458,7 +1455,7 @@ class Team:
|
|
|
1458
1455
|
add_session_state_to_context: Optional[bool] = None,
|
|
1459
1456
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
1460
1457
|
stream_events: bool = False,
|
|
1461
|
-
|
|
1458
|
+
yield_run_output: bool = False,
|
|
1462
1459
|
debug_mode: Optional[bool] = None,
|
|
1463
1460
|
**kwargs: Any,
|
|
1464
1461
|
) -> Iterator[Union[TeamRunOutputEvent, RunOutputEvent, TeamRunOutput]]:
|
|
@@ -1701,7 +1698,7 @@ class Team:
|
|
|
1701
1698
|
if stream_events:
|
|
1702
1699
|
yield completed_event
|
|
1703
1700
|
|
|
1704
|
-
if
|
|
1701
|
+
if yield_run_output:
|
|
1705
1702
|
yield run_response
|
|
1706
1703
|
|
|
1707
1704
|
# Log Team Telemetry
|
|
@@ -1778,7 +1775,8 @@ class Team:
|
|
|
1778
1775
|
dependencies: Optional[Dict[str, Any]] = None,
|
|
1779
1776
|
metadata: Optional[Dict[str, Any]] = None,
|
|
1780
1777
|
debug_mode: Optional[bool] = None,
|
|
1781
|
-
yield_run_response: bool = False,
|
|
1778
|
+
yield_run_response: bool = False, # To be deprecated: use yield_run_output instead
|
|
1779
|
+
yield_run_output: bool = False,
|
|
1782
1780
|
**kwargs: Any,
|
|
1783
1781
|
) -> Iterator[Union[RunOutputEvent, TeamRunOutputEvent]]: ...
|
|
1784
1782
|
|
|
@@ -1804,7 +1802,8 @@ class Team:
|
|
|
1804
1802
|
dependencies: Optional[Dict[str, Any]] = None,
|
|
1805
1803
|
metadata: Optional[Dict[str, Any]] = None,
|
|
1806
1804
|
debug_mode: Optional[bool] = None,
|
|
1807
|
-
yield_run_response: bool = False,
|
|
1805
|
+
yield_run_response: bool = False, # To be deprecated: use yield_run_output instead
|
|
1806
|
+
yield_run_output: bool = False,
|
|
1808
1807
|
**kwargs: Any,
|
|
1809
1808
|
) -> Union[TeamRunOutput, Iterator[Union[RunOutputEvent, TeamRunOutputEvent]]]:
|
|
1810
1809
|
"""Run the Team and return the response."""
|
|
@@ -1948,6 +1947,8 @@ class Team:
|
|
|
1948
1947
|
last_exception = None
|
|
1949
1948
|
num_attempts = retries + 1
|
|
1950
1949
|
|
|
1950
|
+
yield_run_output = yield_run_output or yield_run_response # For backwards compatibility
|
|
1951
|
+
|
|
1951
1952
|
for attempt in range(num_attempts):
|
|
1952
1953
|
# Initialize the current run
|
|
1953
1954
|
|
|
@@ -1964,7 +1965,7 @@ class Team:
|
|
|
1964
1965
|
add_session_state_to_context=add_session_state,
|
|
1965
1966
|
response_format=response_format,
|
|
1966
1967
|
stream_events=stream_events,
|
|
1967
|
-
|
|
1968
|
+
yield_run_output=yield_run_output,
|
|
1968
1969
|
debug_mode=debug_mode,
|
|
1969
1970
|
**kwargs,
|
|
1970
1971
|
)
|
|
@@ -2270,7 +2271,7 @@ class Team:
|
|
|
2270
2271
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
2271
2272
|
stream_events: bool = False,
|
|
2272
2273
|
stream_intermediate_steps: bool = False,
|
|
2273
|
-
|
|
2274
|
+
yield_run_output: bool = False,
|
|
2274
2275
|
add_dependencies_to_context: Optional[bool] = None,
|
|
2275
2276
|
add_session_state_to_context: Optional[bool] = None,
|
|
2276
2277
|
add_history_to_context: Optional[bool] = None,
|
|
@@ -2545,7 +2546,7 @@ class Team:
|
|
|
2545
2546
|
if stream_events:
|
|
2546
2547
|
yield completed_event
|
|
2547
2548
|
|
|
2548
|
-
if
|
|
2549
|
+
if yield_run_output:
|
|
2549
2550
|
yield run_response
|
|
2550
2551
|
|
|
2551
2552
|
# Log Team Telemetry
|
|
@@ -2631,7 +2632,8 @@ class Team:
|
|
|
2631
2632
|
dependencies: Optional[Dict[str, Any]] = None,
|
|
2632
2633
|
metadata: Optional[Dict[str, Any]] = None,
|
|
2633
2634
|
debug_mode: Optional[bool] = None,
|
|
2634
|
-
yield_run_response: bool = False,
|
|
2635
|
+
yield_run_response: bool = False, # To be deprecated: use yield_run_output instead
|
|
2636
|
+
yield_run_output: bool = False,
|
|
2635
2637
|
**kwargs: Any,
|
|
2636
2638
|
) -> AsyncIterator[Union[RunOutputEvent, TeamRunOutputEvent]]: ...
|
|
2637
2639
|
|
|
@@ -2657,7 +2659,8 @@ class Team:
|
|
|
2657
2659
|
dependencies: Optional[Dict[str, Any]] = None,
|
|
2658
2660
|
metadata: Optional[Dict[str, Any]] = None,
|
|
2659
2661
|
debug_mode: Optional[bool] = None,
|
|
2660
|
-
yield_run_response: bool = False,
|
|
2662
|
+
yield_run_response: bool = False, # To be deprecated: use yield_run_output instead
|
|
2663
|
+
yield_run_output: bool = False,
|
|
2661
2664
|
**kwargs: Any,
|
|
2662
2665
|
) -> Union[TeamRunOutput, AsyncIterator[Union[RunOutputEvent, TeamRunOutputEvent]]]:
|
|
2663
2666
|
"""Run the Team asynchronously and return the response."""
|
|
@@ -2783,6 +2786,8 @@ class Team:
|
|
|
2783
2786
|
last_exception = None
|
|
2784
2787
|
num_attempts = retries + 1
|
|
2785
2788
|
|
|
2789
|
+
yield_run_output = yield_run_output or yield_run_response # For backwards compatibility
|
|
2790
|
+
|
|
2786
2791
|
for attempt in range(num_attempts):
|
|
2787
2792
|
# Run the team
|
|
2788
2793
|
try:
|
|
@@ -2798,7 +2803,7 @@ class Team:
|
|
|
2798
2803
|
add_session_state_to_context=add_session_state,
|
|
2799
2804
|
response_format=response_format,
|
|
2800
2805
|
stream_events=stream_events,
|
|
2801
|
-
|
|
2806
|
+
yield_run_output=yield_run_output,
|
|
2802
2807
|
debug_mode=debug_mode,
|
|
2803
2808
|
**kwargs,
|
|
2804
2809
|
)
|
|
@@ -6988,7 +6993,7 @@ class Team:
|
|
|
6988
6993
|
knowledge_filters=run_context.knowledge_filters
|
|
6989
6994
|
if not member_agent.knowledge_filters and member_agent.knowledge
|
|
6990
6995
|
else None,
|
|
6991
|
-
|
|
6996
|
+
yield_run_output=True,
|
|
6992
6997
|
)
|
|
6993
6998
|
member_agent_run_response = None
|
|
6994
6999
|
for member_agent_run_output_event in member_agent_run_response_stream:
|
|
@@ -7118,7 +7123,7 @@ class Team:
|
|
|
7118
7123
|
knowledge_filters=run_context.knowledge_filters
|
|
7119
7124
|
if not member_agent.knowledge_filters and member_agent.knowledge
|
|
7120
7125
|
else None,
|
|
7121
|
-
|
|
7126
|
+
yield_run_output=True,
|
|
7122
7127
|
)
|
|
7123
7128
|
member_agent_run_response = None
|
|
7124
7129
|
async for member_agent_run_response_event in member_agent_run_response_stream:
|
|
@@ -7234,7 +7239,7 @@ class Team:
|
|
|
7234
7239
|
add_dependencies_to_context=add_dependencies_to_context,
|
|
7235
7240
|
add_session_state_to_context=add_session_state_to_context,
|
|
7236
7241
|
metadata=run_context.metadata,
|
|
7237
|
-
|
|
7242
|
+
yield_run_output=True,
|
|
7238
7243
|
)
|
|
7239
7244
|
member_agent_run_response = None
|
|
7240
7245
|
for member_agent_run_response_chunk in member_agent_run_response_stream:
|
|
@@ -7350,7 +7355,7 @@ class Team:
|
|
|
7350
7355
|
add_dependencies_to_context=add_dependencies_to_context,
|
|
7351
7356
|
add_session_state_to_context=add_session_state_to_context,
|
|
7352
7357
|
metadata=run_context.metadata,
|
|
7353
|
-
|
|
7358
|
+
yield_run_output=True,
|
|
7354
7359
|
)
|
|
7355
7360
|
member_agent_run_response = None
|
|
7356
7361
|
try:
|
agno/vectordb/__init__.py
CHANGED