agno 2.2.8__py3-none-any.whl → 2.2.10__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 +37 -19
- 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 +127 -65
- 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 +33 -23
- agno/vectordb/mongodb/__init__.py +7 -1
- agno/vectordb/redis/__init__.py +4 -0
- agno/workflow/agent.py +2 -2
- agno/workflow/condition.py +26 -4
- agno/workflow/loop.py +9 -0
- agno/workflow/parallel.py +39 -16
- agno/workflow/router.py +25 -4
- agno/workflow/step.py +162 -91
- agno/workflow/steps.py +9 -0
- agno/workflow/workflow.py +26 -22
- {agno-2.2.8.dist-info → agno-2.2.10.dist-info}/METADATA +11 -13
- {agno-2.2.8.dist-info → agno-2.2.10.dist-info}/RECORD +50 -50
- {agno-2.2.8.dist-info → agno-2.2.10.dist-info}/WHEEL +0 -0
- {agno-2.2.8.dist-info → agno-2.2.10.dist-info}/licenses/LICENSE +0 -0
- {agno-2.2.8.dist-info → agno-2.2.10.dist-info}/top_level.txt +0 -0
agno/agent/agent.py
CHANGED
|
@@ -1140,7 +1140,7 @@ class Agent:
|
|
|
1140
1140
|
add_session_state_to_context: Optional[bool] = None,
|
|
1141
1141
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
1142
1142
|
stream_events: bool = False,
|
|
1143
|
-
|
|
1143
|
+
yield_run_output: Optional[bool] = None,
|
|
1144
1144
|
debug_mode: Optional[bool] = None,
|
|
1145
1145
|
**kwargs: Any,
|
|
1146
1146
|
) -> Iterator[Union[RunOutputEvent, RunOutput]]:
|
|
@@ -1410,7 +1410,7 @@ class Agent:
|
|
|
1410
1410
|
if stream_events:
|
|
1411
1411
|
yield completed_event # type: ignore
|
|
1412
1412
|
|
|
1413
|
-
if
|
|
1413
|
+
if yield_run_output:
|
|
1414
1414
|
yield run_response
|
|
1415
1415
|
|
|
1416
1416
|
# Log Agent Telemetry
|
|
@@ -1454,6 +1454,7 @@ class Agent:
|
|
|
1454
1454
|
user_id: Optional[str] = None,
|
|
1455
1455
|
session_id: Optional[str] = None,
|
|
1456
1456
|
session_state: Optional[Dict[str, Any]] = None,
|
|
1457
|
+
run_context: Optional[RunContext] = None,
|
|
1457
1458
|
audio: Optional[Sequence[Audio]] = None,
|
|
1458
1459
|
images: Optional[Sequence[Image]] = None,
|
|
1459
1460
|
videos: Optional[Sequence[Video]] = None,
|
|
@@ -1480,6 +1481,7 @@ class Agent:
|
|
|
1480
1481
|
user_id: Optional[str] = None,
|
|
1481
1482
|
session_id: Optional[str] = None,
|
|
1482
1483
|
session_state: Optional[Dict[str, Any]] = None,
|
|
1484
|
+
run_context: Optional[RunContext] = None,
|
|
1483
1485
|
audio: Optional[Sequence[Audio]] = None,
|
|
1484
1486
|
images: Optional[Sequence[Image]] = None,
|
|
1485
1487
|
videos: Optional[Sequence[Video]] = None,
|
|
@@ -1491,7 +1493,8 @@ class Agent:
|
|
|
1491
1493
|
add_session_state_to_context: Optional[bool] = None,
|
|
1492
1494
|
dependencies: Optional[Dict[str, Any]] = None,
|
|
1493
1495
|
metadata: Optional[Dict[str, Any]] = None,
|
|
1494
|
-
yield_run_response: bool = False,
|
|
1496
|
+
yield_run_response: bool = False, # To be deprecated: use yield_run_output instead
|
|
1497
|
+
yield_run_output: bool = False,
|
|
1495
1498
|
debug_mode: Optional[bool] = None,
|
|
1496
1499
|
**kwargs: Any,
|
|
1497
1500
|
) -> Iterator[Union[RunOutputEvent, RunOutput]]: ...
|
|
@@ -1506,6 +1509,7 @@ class Agent:
|
|
|
1506
1509
|
user_id: Optional[str] = None,
|
|
1507
1510
|
session_id: Optional[str] = None,
|
|
1508
1511
|
session_state: Optional[Dict[str, Any]] = None,
|
|
1512
|
+
run_context: Optional[RunContext] = None,
|
|
1509
1513
|
audio: Optional[Sequence[Audio]] = None,
|
|
1510
1514
|
images: Optional[Sequence[Image]] = None,
|
|
1511
1515
|
videos: Optional[Sequence[Video]] = None,
|
|
@@ -1517,7 +1521,8 @@ class Agent:
|
|
|
1517
1521
|
add_session_state_to_context: Optional[bool] = None,
|
|
1518
1522
|
dependencies: Optional[Dict[str, Any]] = None,
|
|
1519
1523
|
metadata: Optional[Dict[str, Any]] = None,
|
|
1520
|
-
yield_run_response: bool =
|
|
1524
|
+
yield_run_response: Optional[bool] = None, # To be deprecated: use yield_run_output instead
|
|
1525
|
+
yield_run_output: Optional[bool] = None,
|
|
1521
1526
|
debug_mode: Optional[bool] = None,
|
|
1522
1527
|
**kwargs: Any,
|
|
1523
1528
|
) -> Union[RunOutput, Iterator[Union[RunOutputEvent, RunOutput]]]:
|
|
@@ -1579,7 +1584,7 @@ class Agent:
|
|
|
1579
1584
|
dependencies = dependencies if dependencies is not None else self.dependencies
|
|
1580
1585
|
|
|
1581
1586
|
# Initialize run context
|
|
1582
|
-
run_context = RunContext(
|
|
1587
|
+
run_context = run_context or RunContext(
|
|
1583
1588
|
run_id=run_id,
|
|
1584
1589
|
session_id=session_id,
|
|
1585
1590
|
user_id=user_id,
|
|
@@ -1655,6 +1660,8 @@ class Agent:
|
|
|
1655
1660
|
last_exception = None
|
|
1656
1661
|
num_attempts = retries + 1
|
|
1657
1662
|
|
|
1663
|
+
yield_run_output = yield_run_output or yield_run_response # For backwards compatibility
|
|
1664
|
+
|
|
1658
1665
|
for attempt in range(num_attempts):
|
|
1659
1666
|
try:
|
|
1660
1667
|
if stream:
|
|
@@ -1668,7 +1675,7 @@ class Agent:
|
|
|
1668
1675
|
add_session_state_to_context=add_session_state,
|
|
1669
1676
|
response_format=response_format,
|
|
1670
1677
|
stream_events=stream_events,
|
|
1671
|
-
|
|
1678
|
+
yield_run_output=yield_run_output,
|
|
1672
1679
|
debug_mode=debug_mode,
|
|
1673
1680
|
**kwargs,
|
|
1674
1681
|
)
|
|
@@ -2009,7 +2016,7 @@ class Agent:
|
|
|
2009
2016
|
add_session_state_to_context: Optional[bool] = None,
|
|
2010
2017
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
2011
2018
|
stream_events: bool = False,
|
|
2012
|
-
|
|
2019
|
+
yield_run_output: Optional[bool] = None,
|
|
2013
2020
|
debug_mode: Optional[bool] = None,
|
|
2014
2021
|
**kwargs: Any,
|
|
2015
2022
|
) -> AsyncIterator[Union[RunOutputEvent, RunOutput]]:
|
|
@@ -2307,7 +2314,7 @@ class Agent:
|
|
|
2307
2314
|
if stream_events:
|
|
2308
2315
|
yield completed_event # type: ignore
|
|
2309
2316
|
|
|
2310
|
-
if
|
|
2317
|
+
if yield_run_output:
|
|
2311
2318
|
yield run_response
|
|
2312
2319
|
|
|
2313
2320
|
# Log Agent Telemetry
|
|
@@ -2370,6 +2377,7 @@ class Agent:
|
|
|
2370
2377
|
user_id: Optional[str] = None,
|
|
2371
2378
|
session_id: Optional[str] = None,
|
|
2372
2379
|
session_state: Optional[Dict[str, Any]] = None,
|
|
2380
|
+
run_context: Optional[RunContext] = None,
|
|
2373
2381
|
audio: Optional[Sequence[Audio]] = None,
|
|
2374
2382
|
images: Optional[Sequence[Image]] = None,
|
|
2375
2383
|
videos: Optional[Sequence[Video]] = None,
|
|
@@ -2395,6 +2403,7 @@ class Agent:
|
|
|
2395
2403
|
stream: Literal[True] = True,
|
|
2396
2404
|
user_id: Optional[str] = None,
|
|
2397
2405
|
session_id: Optional[str] = None,
|
|
2406
|
+
run_context: Optional[RunContext] = None,
|
|
2398
2407
|
audio: Optional[Sequence[Audio]] = None,
|
|
2399
2408
|
images: Optional[Sequence[Image]] = None,
|
|
2400
2409
|
videos: Optional[Sequence[Video]] = None,
|
|
@@ -2408,7 +2417,8 @@ class Agent:
|
|
|
2408
2417
|
add_session_state_to_context: Optional[bool] = None,
|
|
2409
2418
|
dependencies: Optional[Dict[str, Any]] = None,
|
|
2410
2419
|
metadata: Optional[Dict[str, Any]] = None,
|
|
2411
|
-
yield_run_response: Optional[bool] = None,
|
|
2420
|
+
yield_run_response: Optional[bool] = None, # To be deprecated: use yield_run_output instead
|
|
2421
|
+
yield_run_output: Optional[bool] = None,
|
|
2412
2422
|
debug_mode: Optional[bool] = None,
|
|
2413
2423
|
**kwargs: Any,
|
|
2414
2424
|
) -> AsyncIterator[Union[RunOutputEvent, RunOutput]]: ...
|
|
@@ -2421,6 +2431,7 @@ class Agent:
|
|
|
2421
2431
|
user_id: Optional[str] = None,
|
|
2422
2432
|
session_id: Optional[str] = None,
|
|
2423
2433
|
session_state: Optional[Dict[str, Any]] = None,
|
|
2434
|
+
run_context: Optional[RunContext] = None,
|
|
2424
2435
|
audio: Optional[Sequence[Audio]] = None,
|
|
2425
2436
|
images: Optional[Sequence[Image]] = None,
|
|
2426
2437
|
videos: Optional[Sequence[Video]] = None,
|
|
@@ -2434,7 +2445,8 @@ class Agent:
|
|
|
2434
2445
|
add_session_state_to_context: Optional[bool] = None,
|
|
2435
2446
|
dependencies: Optional[Dict[str, Any]] = None,
|
|
2436
2447
|
metadata: Optional[Dict[str, Any]] = None,
|
|
2437
|
-
yield_run_response: Optional[bool] = None,
|
|
2448
|
+
yield_run_response: Optional[bool] = None, # To be deprecated: use yield_run_output instead
|
|
2449
|
+
yield_run_output: Optional[bool] = None,
|
|
2438
2450
|
debug_mode: Optional[bool] = None,
|
|
2439
2451
|
**kwargs: Any,
|
|
2440
2452
|
) -> Union[RunOutput, AsyncIterator[RunOutputEvent]]:
|
|
@@ -2524,7 +2536,7 @@ class Agent:
|
|
|
2524
2536
|
merge_dictionaries(metadata, self.metadata)
|
|
2525
2537
|
|
|
2526
2538
|
# Initialize run context
|
|
2527
|
-
run_context = RunContext(
|
|
2539
|
+
run_context = run_context or RunContext(
|
|
2528
2540
|
run_id=run_id,
|
|
2529
2541
|
session_id=session_id,
|
|
2530
2542
|
user_id=user_id,
|
|
@@ -2559,6 +2571,8 @@ class Agent:
|
|
|
2559
2571
|
last_exception = None
|
|
2560
2572
|
num_attempts = retries + 1
|
|
2561
2573
|
|
|
2574
|
+
yield_run_output = yield_run_output or yield_run_response # For backwards compatibility
|
|
2575
|
+
|
|
2562
2576
|
for attempt in range(num_attempts):
|
|
2563
2577
|
try:
|
|
2564
2578
|
# Pass the new run_response to _arun
|
|
@@ -2569,7 +2583,7 @@ class Agent:
|
|
|
2569
2583
|
user_id=user_id,
|
|
2570
2584
|
response_format=response_format,
|
|
2571
2585
|
stream_events=stream_events,
|
|
2572
|
-
|
|
2586
|
+
yield_run_output=yield_run_output,
|
|
2573
2587
|
session_id=session_id,
|
|
2574
2588
|
add_history_to_context=add_history,
|
|
2575
2589
|
add_dependencies_to_context=add_dependencies,
|
|
@@ -2684,6 +2698,7 @@ class Agent:
|
|
|
2684
2698
|
stream_intermediate_steps: Optional[bool] = None,
|
|
2685
2699
|
user_id: Optional[str] = None,
|
|
2686
2700
|
session_id: Optional[str] = None,
|
|
2701
|
+
run_context: Optional[RunContext] = None,
|
|
2687
2702
|
retries: Optional[int] = None,
|
|
2688
2703
|
knowledge_filters: Optional[Dict[str, Any]] = None,
|
|
2689
2704
|
dependencies: Optional[Dict[str, Any]] = None,
|
|
@@ -2701,6 +2716,7 @@ class Agent:
|
|
|
2701
2716
|
stream_events: Whether to stream all events.
|
|
2702
2717
|
user_id: The user id to continue the run for.
|
|
2703
2718
|
session_id: The session id to continue the run for.
|
|
2719
|
+
run_context: The run context to use for the run.
|
|
2704
2720
|
retries: The number of retries to continue the run for.
|
|
2705
2721
|
knowledge_filters: The knowledge filters to use for the run.
|
|
2706
2722
|
dependencies: The dependencies to use for the run.
|
|
@@ -2741,7 +2757,7 @@ class Agent:
|
|
|
2741
2757
|
dependencies = dependencies if dependencies is not None else self.dependencies
|
|
2742
2758
|
|
|
2743
2759
|
# Initialize run context
|
|
2744
|
-
run_context = RunContext(
|
|
2760
|
+
run_context = run_context or RunContext(
|
|
2745
2761
|
run_id=run_id, # type: ignore
|
|
2746
2762
|
session_id=session_id,
|
|
2747
2763
|
user_id=user_id,
|
|
@@ -3243,12 +3259,13 @@ class Agent:
|
|
|
3243
3259
|
stream_intermediate_steps: Optional[bool] = None,
|
|
3244
3260
|
user_id: Optional[str] = None,
|
|
3245
3261
|
session_id: Optional[str] = None,
|
|
3262
|
+
run_context: Optional[RunContext] = None,
|
|
3246
3263
|
retries: Optional[int] = None,
|
|
3247
3264
|
knowledge_filters: Optional[Dict[str, Any]] = None,
|
|
3248
3265
|
dependencies: Optional[Dict[str, Any]] = None,
|
|
3249
3266
|
metadata: Optional[Dict[str, Any]] = None,
|
|
3250
3267
|
debug_mode: Optional[bool] = None,
|
|
3251
|
-
|
|
3268
|
+
yield_run_output: bool = False,
|
|
3252
3269
|
**kwargs,
|
|
3253
3270
|
) -> Union[RunOutput, AsyncIterator[Union[RunOutputEvent, RunOutput]]]:
|
|
3254
3271
|
"""Continue a previous run.
|
|
@@ -3261,12 +3278,13 @@ class Agent:
|
|
|
3261
3278
|
stream_events: Whether to stream all events.
|
|
3262
3279
|
user_id: The user id to continue the run for.
|
|
3263
3280
|
session_id: The session id to continue the run for.
|
|
3281
|
+
run_context: The run context to use for the run.
|
|
3264
3282
|
retries: The number of retries to continue the run for.
|
|
3265
3283
|
knowledge_filters: The knowledge filters to use for the run.
|
|
3266
3284
|
dependencies: The dependencies to use for continuing the run.
|
|
3267
3285
|
metadata: The metadata to use for continuing the run.
|
|
3268
3286
|
debug_mode: Whether to enable debug mode.
|
|
3269
|
-
|
|
3287
|
+
yield_run_output: Whether to yield the run response.
|
|
3270
3288
|
(deprecated) stream_intermediate_steps: Whether to stream all steps.
|
|
3271
3289
|
"""
|
|
3272
3290
|
if run_response is None and run_id is None:
|
|
@@ -3327,7 +3345,7 @@ class Agent:
|
|
|
3327
3345
|
self.model = cast(Model, self.model)
|
|
3328
3346
|
|
|
3329
3347
|
# Initialize run context
|
|
3330
|
-
run_context = RunContext(
|
|
3348
|
+
run_context = run_context or RunContext(
|
|
3331
3349
|
run_id=run_id, # type: ignore
|
|
3332
3350
|
session_id=session_id,
|
|
3333
3351
|
user_id=user_id,
|
|
@@ -3351,7 +3369,7 @@ class Agent:
|
|
|
3351
3369
|
session_id=session_id,
|
|
3352
3370
|
response_format=response_format,
|
|
3353
3371
|
stream_events=stream_events,
|
|
3354
|
-
|
|
3372
|
+
yield_run_output=yield_run_output,
|
|
3355
3373
|
debug_mode=debug_mode,
|
|
3356
3374
|
**kwargs,
|
|
3357
3375
|
)
|
|
@@ -3620,7 +3638,7 @@ class Agent:
|
|
|
3620
3638
|
user_id: Optional[str] = None,
|
|
3621
3639
|
response_format: Optional[Union[Dict, Type[BaseModel]]] = None,
|
|
3622
3640
|
stream_events: bool = False,
|
|
3623
|
-
|
|
3641
|
+
yield_run_output: bool = False,
|
|
3624
3642
|
debug_mode: Optional[bool] = None,
|
|
3625
3643
|
**kwargs,
|
|
3626
3644
|
) -> AsyncIterator[Union[RunOutputEvent, RunOutput]]:
|
|
@@ -3860,7 +3878,7 @@ class Agent:
|
|
|
3860
3878
|
if stream_events:
|
|
3861
3879
|
yield completed_event # type: ignore
|
|
3862
3880
|
|
|
3863
|
-
if
|
|
3881
|
+
if yield_run_output:
|
|
3864
3882
|
yield run_response
|
|
3865
3883
|
|
|
3866
3884
|
# Log Agent Telemetry
|
agno/db/base.py
CHANGED
|
@@ -38,6 +38,14 @@ class BaseDb(ABC):
|
|
|
38
38
|
self.eval_table_name = eval_table or "agno_eval_runs"
|
|
39
39
|
self.knowledge_table_name = knowledge_table or "agno_knowledge"
|
|
40
40
|
|
|
41
|
+
@abstractmethod
|
|
42
|
+
def table_exists(self, table_name: str) -> bool:
|
|
43
|
+
raise NotImplementedError
|
|
44
|
+
|
|
45
|
+
def _create_all_tables(self) -> None:
|
|
46
|
+
"""Create all tables for this database."""
|
|
47
|
+
pass
|
|
48
|
+
|
|
41
49
|
# --- Sessions ---
|
|
42
50
|
@abstractmethod
|
|
43
51
|
def delete_session(self, session_id: str) -> bool:
|
|
@@ -328,6 +336,21 @@ class AsyncBaseDb(ABC):
|
|
|
328
336
|
self.knowledge_table_name = knowledge_table or "agno_knowledge"
|
|
329
337
|
self.culture_table_name = culture_table or "agno_culture"
|
|
330
338
|
|
|
339
|
+
@abstractmethod
|
|
340
|
+
async def table_exists(self, table_name: str) -> bool:
|
|
341
|
+
"""Check if a table with the given name exists in this database.
|
|
342
|
+
|
|
343
|
+
Default implementation returns True if the table name is configured.
|
|
344
|
+
Subclasses should override this to perform actual existence checks.
|
|
345
|
+
|
|
346
|
+
Args:
|
|
347
|
+
table_name: Name of the table to check
|
|
348
|
+
|
|
349
|
+
Returns:
|
|
350
|
+
bool: True if the table exists, False otherwise
|
|
351
|
+
"""
|
|
352
|
+
raise NotImplementedError
|
|
353
|
+
|
|
331
354
|
# --- Sessions ---
|
|
332
355
|
@abstractmethod
|
|
333
356
|
async def delete_session(self, session_id: str) -> bool:
|
agno/db/dynamo/dynamo.py
CHANGED
|
@@ -112,27 +112,8 @@ class DynamoDb(BaseDb):
|
|
|
112
112
|
session = boto3.Session(**session_kwargs)
|
|
113
113
|
self.client = session.client("dynamodb")
|
|
114
114
|
|
|
115
|
-
def
|
|
116
|
-
|
|
117
|
-
(self.session_table_name, "sessions"),
|
|
118
|
-
(self.memory_table_name, "memories"),
|
|
119
|
-
(self.metrics_table_name, "metrics"),
|
|
120
|
-
(self.eval_table_name, "evals"),
|
|
121
|
-
(self.knowledge_table_name, "knowledge_sources"),
|
|
122
|
-
]
|
|
123
|
-
|
|
124
|
-
for table_name, table_type in tables_to_create:
|
|
125
|
-
if table_name:
|
|
126
|
-
try:
|
|
127
|
-
schema = get_table_schema_definition(table_type)
|
|
128
|
-
schema["TableName"] = table_name
|
|
129
|
-
create_table_if_not_exists(self.client, table_name, schema)
|
|
130
|
-
|
|
131
|
-
except Exception as e:
|
|
132
|
-
log_error(f"Failed to create table {table_name}: {e}")
|
|
133
|
-
|
|
134
|
-
def _table_exists(self, table_name: str) -> bool:
|
|
135
|
-
"""Check if a DynamoDB table with the given name exists.
|
|
115
|
+
def table_exists(self, table_name: str) -> bool:
|
|
116
|
+
"""Check if a DynamoDB table exists.
|
|
136
117
|
|
|
137
118
|
Args:
|
|
138
119
|
table_name: The name of the table to check
|
|
@@ -145,9 +126,23 @@ class DynamoDb(BaseDb):
|
|
|
145
126
|
return True
|
|
146
127
|
except self.client.exceptions.ResourceNotFoundException:
|
|
147
128
|
return False
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
129
|
+
|
|
130
|
+
def _create_all_tables(self):
|
|
131
|
+
"""Create all configured DynamoDB tables if they don't exist."""
|
|
132
|
+
tables_to_create = [
|
|
133
|
+
("sessions", self.session_table_name),
|
|
134
|
+
("memories", self.memory_table_name),
|
|
135
|
+
("metrics", self.metrics_table_name),
|
|
136
|
+
("evals", self.eval_table_name),
|
|
137
|
+
("knowledge", self.knowledge_table_name),
|
|
138
|
+
("culture", self.culture_table_name),
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
for table_type, table_name in tables_to_create:
|
|
142
|
+
if not self.table_exists(table_name):
|
|
143
|
+
schema = get_table_schema_definition(table_type)
|
|
144
|
+
schema["TableName"] = table_name
|
|
145
|
+
create_table_if_not_exists(self.client, table_name, schema)
|
|
151
146
|
|
|
152
147
|
def _get_table(self, table_type: str, create_table_if_not_found: Optional[bool] = True) -> Optional[str]:
|
|
153
148
|
"""
|
|
@@ -180,7 +175,7 @@ class DynamoDb(BaseDb):
|
|
|
180
175
|
raise ValueError(f"Unknown table type: {table_type}")
|
|
181
176
|
|
|
182
177
|
# Check if table exists, create if it doesn't
|
|
183
|
-
if not self.
|
|
178
|
+
if not self.table_exists(table_name) and create_table_if_not_found:
|
|
184
179
|
schema = get_table_schema_definition(table_type)
|
|
185
180
|
schema["TableName"] = table_name
|
|
186
181
|
create_table_if_not_exists(self.client, table_name, schema)
|
agno/db/dynamo/schemas.py
CHANGED
|
@@ -176,6 +176,7 @@ KNOWLEDGE_TABLE_SCHEMA = {
|
|
|
176
176
|
"KeySchema": [{"AttributeName": "id", "KeyType": "HASH"}],
|
|
177
177
|
"AttributeDefinitions": [
|
|
178
178
|
{"AttributeName": "id", "AttributeType": "S"},
|
|
179
|
+
{"AttributeName": "user_id", "AttributeType": "S"},
|
|
179
180
|
{"AttributeName": "type", "AttributeType": "S"},
|
|
180
181
|
{"AttributeName": "status", "AttributeType": "S"},
|
|
181
182
|
{"AttributeName": "created_at", "AttributeType": "N"},
|
agno/db/firestore/firestore.py
CHANGED
|
@@ -89,6 +89,17 @@ class FirestoreDb(BaseDb):
|
|
|
89
89
|
|
|
90
90
|
# -- DB methods --
|
|
91
91
|
|
|
92
|
+
def table_exists(self, table_name: str) -> bool:
|
|
93
|
+
"""Check if a collection with the given name exists in the Firestore database.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
table_name: Name of the collection to check
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
bool: True if the collection exists in the database, False otherwise
|
|
100
|
+
"""
|
|
101
|
+
return table_name in self.db_client.list_collections()
|
|
102
|
+
|
|
92
103
|
def _get_collection(self, table_type: str, create_collection_if_not_found: Optional[bool] = True):
|
|
93
104
|
"""Get or create a collection based on table type.
|
|
94
105
|
|
agno/db/gcs_json/gcs_json_db.py
CHANGED
|
@@ -83,6 +83,10 @@ class GcsJsonDb(BaseDb):
|
|
|
83
83
|
self.client = gcs.Client(project=project, credentials=credentials)
|
|
84
84
|
self.bucket = self.client.bucket(self.bucket_name)
|
|
85
85
|
|
|
86
|
+
def table_exists(self, table_name: str) -> bool:
|
|
87
|
+
"""JSON implementation, always returns True."""
|
|
88
|
+
return True
|
|
89
|
+
|
|
86
90
|
def _get_blob_name(self, filename: str) -> str:
|
|
87
91
|
"""Get the full blob name including prefix for a given filename."""
|
|
88
92
|
return f"{self.prefix}{filename}.json"
|
|
@@ -34,6 +34,10 @@ class InMemoryDb(BaseDb):
|
|
|
34
34
|
self._knowledge: List[Dict[str, Any]] = []
|
|
35
35
|
self._cultural_knowledge: List[Dict[str, Any]] = []
|
|
36
36
|
|
|
37
|
+
def table_exists(self, table_name: str) -> bool:
|
|
38
|
+
"""In-memory implementation, always returns True."""
|
|
39
|
+
return True
|
|
40
|
+
|
|
37
41
|
# -- Session methods --
|
|
38
42
|
|
|
39
43
|
def delete_session(self, session_id: str) -> bool:
|
agno/db/json/json_db.py
CHANGED
|
@@ -66,6 +66,10 @@ class JsonDb(BaseDb):
|
|
|
66
66
|
# Create the directory where the JSON files will be stored, if it doesn't exist
|
|
67
67
|
self.db_path = Path(db_path or os.path.join(os.getcwd(), "agno_json_db"))
|
|
68
68
|
|
|
69
|
+
def table_exists(self, table_name: str) -> bool:
|
|
70
|
+
"""JSON implementation, always returns True."""
|
|
71
|
+
return True
|
|
72
|
+
|
|
69
73
|
def _read_json_file(self, filename: str, create_table_if_not_found: Optional[bool] = True) -> List[Dict[str, Any]]:
|
|
70
74
|
"""Read data from a JSON file, creating it if it doesn't exist.
|
|
71
75
|
|
agno/db/mongo/async_mongo.py
CHANGED
|
@@ -99,6 +99,33 @@ class AsyncMongoDb(AsyncBaseDb):
|
|
|
99
99
|
self._database: Optional[AsyncIOMotorDatabase] = None
|
|
100
100
|
self._event_loop: Optional[asyncio.AbstractEventLoop] = None
|
|
101
101
|
|
|
102
|
+
async def table_exists(self, table_name: str) -> bool:
|
|
103
|
+
"""Check if a collection with the given name exists in the MongoDB database.
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
table_name: Name of the collection to check
|
|
107
|
+
|
|
108
|
+
Returns:
|
|
109
|
+
bool: True if the collection exists in the database, False otherwise
|
|
110
|
+
"""
|
|
111
|
+
collection_names = await self.database.list_collection_names()
|
|
112
|
+
return table_name in collection_names
|
|
113
|
+
|
|
114
|
+
async def _create_all_tables(self):
|
|
115
|
+
"""Create all configured MongoDB collections if they don't exist."""
|
|
116
|
+
collections_to_create = [
|
|
117
|
+
("sessions", self.session_table_name),
|
|
118
|
+
("memories", self.memory_table_name),
|
|
119
|
+
("metrics", self.metrics_table_name),
|
|
120
|
+
("evals", self.eval_table_name),
|
|
121
|
+
("knowledge", self.knowledge_table_name),
|
|
122
|
+
("culture", self.culture_table_name),
|
|
123
|
+
]
|
|
124
|
+
|
|
125
|
+
for collection_type, collection_name in collections_to_create:
|
|
126
|
+
if collection_name and not await self.table_exists(collection_name):
|
|
127
|
+
await self._get_collection(collection_type, create_collection_if_not_found=True)
|
|
128
|
+
|
|
102
129
|
def _ensure_client(self) -> AsyncIOMotorClient:
|
|
103
130
|
"""
|
|
104
131
|
Ensure the Motor client is valid for the current event loop.
|
agno/db/mongo/mongo.py
CHANGED
|
@@ -100,6 +100,31 @@ class MongoDb(BaseDb):
|
|
|
100
100
|
return self._database
|
|
101
101
|
|
|
102
102
|
# -- DB methods --
|
|
103
|
+
def table_exists(self, table_name: str) -> bool:
|
|
104
|
+
"""Check if a collection with the given name exists in the MongoDB database.
|
|
105
|
+
|
|
106
|
+
Args:
|
|
107
|
+
table_name: Name of the collection to check
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
bool: True if the collection exists in the database, False otherwise
|
|
111
|
+
"""
|
|
112
|
+
return table_name in self.database.list_collection_names()
|
|
113
|
+
|
|
114
|
+
def _create_all_tables(self):
|
|
115
|
+
"""Create all configured MongoDB collections if they don't exist."""
|
|
116
|
+
collections_to_create = [
|
|
117
|
+
("sessions", self.session_table_name),
|
|
118
|
+
("memories", self.memory_table_name),
|
|
119
|
+
("metrics", self.metrics_table_name),
|
|
120
|
+
("evals", self.eval_table_name),
|
|
121
|
+
("knowledge", self.knowledge_table_name),
|
|
122
|
+
("culture", self.culture_table_name),
|
|
123
|
+
]
|
|
124
|
+
|
|
125
|
+
for collection_type, collection_name in collections_to_create:
|
|
126
|
+
if collection_name and not self.table_exists(collection_name):
|
|
127
|
+
self._get_collection(collection_type, create_collection_if_not_found=True)
|
|
103
128
|
|
|
104
129
|
def _get_collection(
|
|
105
130
|
self, table_type: str, create_collection_if_not_found: Optional[bool] = True
|
agno/db/mysql/mysql.py
CHANGED
|
@@ -107,6 +107,18 @@ class MySQLDb(BaseDb):
|
|
|
107
107
|
self.Session: scoped_session = scoped_session(sessionmaker(bind=self.db_engine))
|
|
108
108
|
|
|
109
109
|
# -- DB methods --
|
|
110
|
+
def table_exists(self, table_name: str) -> bool:
|
|
111
|
+
"""Check if a table with the given name exists in the MySQL database.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
table_name: Name of the table to check
|
|
115
|
+
|
|
116
|
+
Returns:
|
|
117
|
+
bool: True if the table exists in the database, False otherwise
|
|
118
|
+
"""
|
|
119
|
+
with self.Session() as sess:
|
|
120
|
+
return is_table_available(session=sess, table_name=table_name, db_schema=self.db_schema)
|
|
121
|
+
|
|
110
122
|
def _create_table(self, table_name: str, table_type: str, db_schema: str) -> Table:
|
|
111
123
|
"""
|
|
112
124
|
Create a table with the appropriate schema based on the table type.
|
|
@@ -191,13 +203,26 @@ class MySQLDb(BaseDb):
|
|
|
191
203
|
except Exception as e:
|
|
192
204
|
log_error(f"Error creating index {idx.name}: {e}")
|
|
193
205
|
|
|
194
|
-
|
|
206
|
+
log_debug(f"Successfully created table {db_schema}.{table_name}")
|
|
195
207
|
return table
|
|
196
208
|
|
|
197
209
|
except Exception as e:
|
|
198
210
|
log_error(f"Could not create table {db_schema}.{table_name}: {e}")
|
|
199
211
|
raise
|
|
200
212
|
|
|
213
|
+
def _create_all_tables(self):
|
|
214
|
+
"""Create all tables for the database."""
|
|
215
|
+
tables_to_create = [
|
|
216
|
+
(self.session_table_name, "sessions"),
|
|
217
|
+
(self.memory_table_name, "memories"),
|
|
218
|
+
(self.metrics_table_name, "metrics"),
|
|
219
|
+
(self.eval_table_name, "evals"),
|
|
220
|
+
(self.knowledge_table_name, "knowledge"),
|
|
221
|
+
]
|
|
222
|
+
|
|
223
|
+
for table_name, table_type in tables_to_create:
|
|
224
|
+
self._create_table(table_name=table_name, table_type=table_type, db_schema=self.db_schema)
|
|
225
|
+
|
|
201
226
|
def _get_table(self, table_type: str, create_table_if_not_found: Optional[bool] = False) -> Optional[Table]:
|
|
202
227
|
if table_type == "sessions":
|
|
203
228
|
self.session_table = self._get_or_create_table(
|
|
@@ -102,6 +102,31 @@ class AsyncPostgresDb(AsyncBaseDb):
|
|
|
102
102
|
self.async_session_factory = async_sessionmaker(bind=self.db_engine)
|
|
103
103
|
|
|
104
104
|
# -- DB methods --
|
|
105
|
+
async def table_exists(self, table_name: str) -> bool:
|
|
106
|
+
"""Check if a table with the given name exists in the Postgres database.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
table_name: Name of the table to check
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
bool: True if the table exists in the database, False otherwise
|
|
113
|
+
"""
|
|
114
|
+
async with self.async_session_factory() as sess:
|
|
115
|
+
return await ais_table_available(session=sess, table_name=table_name, db_schema=self.db_schema)
|
|
116
|
+
|
|
117
|
+
async def _create_all_tables(self):
|
|
118
|
+
"""Create all tables for the database."""
|
|
119
|
+
tables_to_create = [
|
|
120
|
+
(self.session_table_name, "sessions"),
|
|
121
|
+
(self.memory_table_name, "memories"),
|
|
122
|
+
(self.metrics_table_name, "metrics"),
|
|
123
|
+
(self.eval_table_name, "evals"),
|
|
124
|
+
(self.knowledge_table_name, "knowledge"),
|
|
125
|
+
]
|
|
126
|
+
|
|
127
|
+
for table_name, table_type in tables_to_create:
|
|
128
|
+
await self._create_table(table_name=table_name, table_type=table_type, db_schema=self.db_schema)
|
|
129
|
+
|
|
105
130
|
async def _create_table(self, table_name: str, table_type: str, db_schema: str) -> Table:
|
|
106
131
|
"""
|
|
107
132
|
Create a table with the appropriate schema based on the table type.
|
|
@@ -180,7 +205,7 @@ class AsyncPostgresDb(AsyncBaseDb):
|
|
|
180
205
|
except Exception as e:
|
|
181
206
|
log_error(f"Error creating index {idx.name}: {e}")
|
|
182
207
|
|
|
183
|
-
|
|
208
|
+
log_debug(f"Successfully created table {table_name} in schema {db_schema}")
|
|
184
209
|
return table
|
|
185
210
|
|
|
186
211
|
except Exception as e:
|
agno/db/postgres/postgres.py
CHANGED
|
@@ -106,6 +106,31 @@ class PostgresDb(BaseDb):
|
|
|
106
106
|
self.Session: scoped_session = scoped_session(sessionmaker(bind=self.db_engine))
|
|
107
107
|
|
|
108
108
|
# -- DB methods --
|
|
109
|
+
def table_exists(self, table_name: str) -> bool:
|
|
110
|
+
"""Check if a table with the given name exists in the Postgres database.
|
|
111
|
+
|
|
112
|
+
Args:
|
|
113
|
+
table_name: Name of the table to check
|
|
114
|
+
|
|
115
|
+
Returns:
|
|
116
|
+
bool: True if the table exists in the database, False otherwise
|
|
117
|
+
"""
|
|
118
|
+
with self.Session() as sess:
|
|
119
|
+
return is_table_available(session=sess, table_name=table_name, db_schema=self.db_schema)
|
|
120
|
+
|
|
121
|
+
def _create_all_tables(self):
|
|
122
|
+
"""Create all tables for the database."""
|
|
123
|
+
tables_to_create = [
|
|
124
|
+
(self.session_table_name, "sessions"),
|
|
125
|
+
(self.memory_table_name, "memories"),
|
|
126
|
+
(self.metrics_table_name, "metrics"),
|
|
127
|
+
(self.eval_table_name, "evals"),
|
|
128
|
+
(self.knowledge_table_name, "knowledge"),
|
|
129
|
+
]
|
|
130
|
+
|
|
131
|
+
for table_name, table_type in tables_to_create:
|
|
132
|
+
self._create_table(table_name=table_name, table_type=table_type, db_schema=self.db_schema)
|
|
133
|
+
|
|
109
134
|
def _create_table(self, table_name: str, table_type: str, db_schema: str) -> Table:
|
|
110
135
|
"""
|
|
111
136
|
Create a table with the appropriate schema based on the table type.
|
|
@@ -184,7 +209,7 @@ class PostgresDb(BaseDb):
|
|
|
184
209
|
except Exception as e:
|
|
185
210
|
log_error(f"Error creating index {idx.name}: {e}")
|
|
186
211
|
|
|
187
|
-
|
|
212
|
+
log_debug(f"Successfully created table {table_name} in schema {db_schema}")
|
|
188
213
|
return table
|
|
189
214
|
|
|
190
215
|
except Exception as e:
|
agno/db/redis/redis.py
CHANGED
|
@@ -100,6 +100,10 @@ class RedisDb(BaseDb):
|
|
|
100
100
|
|
|
101
101
|
# -- DB methods --
|
|
102
102
|
|
|
103
|
+
def table_exists(self, table_name: str) -> bool:
|
|
104
|
+
"""Redis implementation, always returns True."""
|
|
105
|
+
return True
|
|
106
|
+
|
|
103
107
|
def _get_table_name(self, table_type: str) -> str:
|
|
104
108
|
"""Get the active table name for the given table type."""
|
|
105
109
|
if table_type == "sessions":
|