agno 2.0.8__py3-none-any.whl → 2.0.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.
Files changed (45) hide show
  1. agno/agent/agent.py +2 -2
  2. agno/db/base.py +14 -0
  3. agno/db/dynamo/dynamo.py +107 -27
  4. agno/db/firestore/firestore.py +109 -33
  5. agno/db/gcs_json/gcs_json_db.py +100 -20
  6. agno/db/in_memory/in_memory_db.py +95 -20
  7. agno/db/json/json_db.py +101 -21
  8. agno/db/migrations/v1_to_v2.py +181 -35
  9. agno/db/mongo/mongo.py +251 -26
  10. agno/db/mysql/mysql.py +307 -6
  11. agno/db/postgres/postgres.py +279 -33
  12. agno/db/redis/redis.py +99 -22
  13. agno/db/singlestore/singlestore.py +319 -38
  14. agno/db/sqlite/sqlite.py +339 -23
  15. agno/models/anthropic/claude.py +0 -20
  16. agno/models/huggingface/huggingface.py +2 -1
  17. agno/models/ollama/chat.py +28 -2
  18. agno/models/openai/chat.py +7 -0
  19. agno/models/openai/responses.py +8 -8
  20. agno/os/interfaces/base.py +2 -0
  21. agno/os/interfaces/slack/router.py +50 -10
  22. agno/os/interfaces/slack/slack.py +6 -4
  23. agno/os/interfaces/whatsapp/router.py +7 -4
  24. agno/os/router.py +18 -0
  25. agno/os/utils.py +2 -2
  26. agno/reasoning/azure_ai_foundry.py +2 -2
  27. agno/reasoning/deepseek.py +2 -2
  28. agno/reasoning/groq.py +2 -2
  29. agno/reasoning/ollama.py +2 -2
  30. agno/reasoning/openai.py +2 -2
  31. agno/run/base.py +15 -2
  32. agno/team/team.py +0 -7
  33. agno/tools/mcp_toolbox.py +284 -0
  34. agno/tools/scrapegraph.py +58 -31
  35. agno/tools/whatsapp.py +1 -1
  36. agno/utils/print_response/agent.py +2 -2
  37. agno/utils/print_response/team.py +6 -6
  38. agno/utils/reasoning.py +22 -1
  39. agno/utils/string.py +9 -0
  40. agno/workflow/workflow.py +0 -1
  41. {agno-2.0.8.dist-info → agno-2.0.9.dist-info}/METADATA +4 -1
  42. {agno-2.0.8.dist-info → agno-2.0.9.dist-info}/RECORD +45 -44
  43. {agno-2.0.8.dist-info → agno-2.0.9.dist-info}/WHEEL +0 -0
  44. {agno-2.0.8.dist-info → agno-2.0.9.dist-info}/licenses/LICENSE +0 -0
  45. {agno-2.0.8.dist-info → agno-2.0.9.dist-info}/top_level.txt +0 -0
agno/db/redis/redis.py CHANGED
@@ -264,7 +264,7 @@ class RedisDb(BaseDb):
264
264
 
265
265
  except Exception as e:
266
266
  log_error(f"Error deleting session: {e}")
267
- return False
267
+ raise e
268
268
 
269
269
  def delete_sessions(self, session_ids: List[str]) -> None:
270
270
  """Delete multiple sessions from Redis.
@@ -288,6 +288,7 @@ class RedisDb(BaseDb):
288
288
 
289
289
  except Exception as e:
290
290
  log_error(f"Error deleting sessions: {e}")
291
+ raise e
291
292
 
292
293
  def get_session(
293
294
  self,
@@ -334,7 +335,7 @@ class RedisDb(BaseDb):
334
335
 
335
336
  except Exception as e:
336
337
  log_error(f"Exception reading session: {e}")
337
- return None
338
+ raise e
338
339
 
339
340
  # TODO: optimizable
340
341
  def get_sessions(
@@ -415,7 +416,7 @@ class RedisDb(BaseDb):
415
416
 
416
417
  except Exception as e:
417
418
  log_error(f"Exception reading sessions: {e}")
418
- return [], 0
419
+ raise e
419
420
 
420
421
  def rename_session(
421
422
  self, session_id: str, session_type: SessionType, session_name: str, deserialize: Optional[bool] = True
@@ -465,7 +466,7 @@ class RedisDb(BaseDb):
465
466
 
466
467
  except Exception as e:
467
468
  log_error(f"Error renaming session: {e}")
468
- return None
469
+ raise e
469
470
 
470
471
  def upsert_session(
471
472
  self, session: Session, deserialize: Optional[bool] = True
@@ -585,7 +586,44 @@ class RedisDb(BaseDb):
585
586
 
586
587
  except Exception as e:
587
588
  log_error(f"Error upserting session: {e}")
588
- return None
589
+ raise e
590
+
591
+ def upsert_sessions(
592
+ self, sessions: List[Session], deserialize: Optional[bool] = True
593
+ ) -> List[Union[Session, Dict[str, Any]]]:
594
+ """
595
+ Bulk upsert multiple sessions for improved performance on large datasets.
596
+
597
+ Args:
598
+ sessions (List[Session]): List of sessions to upsert.
599
+ deserialize (Optional[bool]): Whether to deserialize the sessions. Defaults to True.
600
+
601
+ Returns:
602
+ List[Union[Session, Dict[str, Any]]]: List of upserted sessions.
603
+
604
+ Raises:
605
+ Exception: If an error occurs during bulk upsert.
606
+ """
607
+ if not sessions:
608
+ return []
609
+
610
+ try:
611
+ log_info(
612
+ f"RedisDb doesn't support efficient bulk operations, falling back to individual upserts for {len(sessions)} sessions"
613
+ )
614
+
615
+ # Fall back to individual upserts
616
+ results = []
617
+ for session in sessions:
618
+ if session is not None:
619
+ result = self.upsert_session(session, deserialize=deserialize)
620
+ if result is not None:
621
+ results.append(result)
622
+ return results
623
+
624
+ except Exception as e:
625
+ log_error(f"Exception during bulk session upsert: {e}")
626
+ return []
589
627
 
590
628
  # -- Memory methods --
591
629
 
@@ -611,6 +649,7 @@ class RedisDb(BaseDb):
611
649
 
612
650
  except Exception as e:
613
651
  log_error(f"Error deleting user memory: {e}")
652
+ raise e
614
653
 
615
654
  def delete_user_memories(self, memory_ids: List[str]) -> None:
616
655
  """Delete user memories from Redis.
@@ -629,6 +668,7 @@ class RedisDb(BaseDb):
629
668
 
630
669
  except Exception as e:
631
670
  log_error(f"Error deleting user memories: {e}")
671
+ raise e
632
672
 
633
673
  def get_all_memory_topics(self) -> List[str]:
634
674
  """Get all memory topics from Redis.
@@ -649,7 +689,7 @@ class RedisDb(BaseDb):
649
689
 
650
690
  except Exception as e:
651
691
  log_error(f"Exception reading memory topics: {e}")
652
- return []
692
+ raise e
653
693
 
654
694
  def get_user_memory(
655
695
  self, memory_id: str, deserialize: Optional[bool] = True
@@ -674,7 +714,7 @@ class RedisDb(BaseDb):
674
714
 
675
715
  except Exception as e:
676
716
  log_error(f"Exception reading memory: {e}")
677
- return None
717
+ raise e
678
718
 
679
719
  def get_user_memories(
680
720
  self,
@@ -747,7 +787,7 @@ class RedisDb(BaseDb):
747
787
 
748
788
  except Exception as e:
749
789
  log_error(f"Exception reading memories: {e}")
750
- return [] if deserialize else ([], 0)
790
+ raise e
751
791
 
752
792
  def get_user_memory_stats(
753
793
  self,
@@ -801,7 +841,7 @@ class RedisDb(BaseDb):
801
841
 
802
842
  except Exception as e:
803
843
  log_error(f"Exception getting user memory stats: {e}")
804
- return [], 0
844
+ raise e
805
845
 
806
846
  def upsert_user_memory(
807
847
  self, memory: UserMemory, deserialize: Optional[bool] = True
@@ -842,7 +882,44 @@ class RedisDb(BaseDb):
842
882
 
843
883
  except Exception as e:
844
884
  log_error(f"Error upserting user memory: {e}")
845
- return None
885
+ raise e
886
+
887
+ def upsert_memories(
888
+ self, memories: List[UserMemory], deserialize: Optional[bool] = True
889
+ ) -> List[Union[UserMemory, Dict[str, Any]]]:
890
+ """
891
+ Bulk upsert multiple user memories for improved performance on large datasets.
892
+
893
+ Args:
894
+ memories (List[UserMemory]): List of memories to upsert.
895
+ deserialize (Optional[bool]): Whether to deserialize the memories. Defaults to True.
896
+
897
+ Returns:
898
+ List[Union[UserMemory, Dict[str, Any]]]: List of upserted memories.
899
+
900
+ Raises:
901
+ Exception: If an error occurs during bulk upsert.
902
+ """
903
+ if not memories:
904
+ return []
905
+
906
+ try:
907
+ log_info(
908
+ f"RedisDb doesn't support efficient bulk operations, falling back to individual upserts for {len(memories)} memories"
909
+ )
910
+
911
+ # Fall back to individual upserts
912
+ results = []
913
+ for memory in memories:
914
+ if memory is not None:
915
+ result = self.upsert_user_memory(memory, deserialize=deserialize)
916
+ if result is not None:
917
+ results.append(result)
918
+ return results
919
+
920
+ except Exception as e:
921
+ log_error(f"Exception during bulk memory upsert: {e}")
922
+ return []
846
923
 
847
924
  def clear_memories(self) -> None:
848
925
  """Delete all memories from the database.
@@ -859,9 +936,8 @@ class RedisDb(BaseDb):
859
936
  self.redis_client.delete(*keys)
860
937
 
861
938
  except Exception as e:
862
- from agno.utils.log import log_warning
863
-
864
- log_warning(f"Exception deleting all memories: {e}")
939
+ log_error(f"Exception deleting all memories: {e}")
940
+ raise e
865
941
 
866
942
  # -- Metrics methods --
867
943
 
@@ -899,7 +975,7 @@ class RedisDb(BaseDb):
899
975
 
900
976
  except Exception as e:
901
977
  log_error(f"Error reading sessions for metrics: {e}")
902
- return []
978
+ raise e
903
979
 
904
980
  def _get_metrics_calculation_starting_date(self) -> Optional[date]:
905
981
  """Get the first date for which metrics calculation is needed.
@@ -936,7 +1012,7 @@ class RedisDb(BaseDb):
936
1012
 
937
1013
  except Exception as e:
938
1014
  log_error(f"Error getting metrics starting date: {e}")
939
- return None
1015
+ raise e
940
1016
 
941
1017
  def calculate_metrics(self) -> Optional[list[dict]]:
942
1018
  """Calculate metrics for all dates without complete metrics.
@@ -1043,7 +1119,7 @@ class RedisDb(BaseDb):
1043
1119
 
1044
1120
  except Exception as e:
1045
1121
  log_error(f"Error getting metrics: {e}")
1046
- return [], None
1122
+ raise e
1047
1123
 
1048
1124
  # -- Knowledge methods --
1049
1125
 
@@ -1061,6 +1137,7 @@ class RedisDb(BaseDb):
1061
1137
 
1062
1138
  except Exception as e:
1063
1139
  log_error(f"Error deleting knowledge content: {e}")
1140
+ raise e
1064
1141
 
1065
1142
  def get_knowledge_content(self, id: str) -> Optional[KnowledgeRow]:
1066
1143
  """Get a knowledge row from the database.
@@ -1083,7 +1160,7 @@ class RedisDb(BaseDb):
1083
1160
 
1084
1161
  except Exception as e:
1085
1162
  log_error(f"Error getting knowledge content: {e}")
1086
- return None
1163
+ raise e
1087
1164
 
1088
1165
  def get_knowledge_contents(
1089
1166
  self,
@@ -1126,7 +1203,7 @@ class RedisDb(BaseDb):
1126
1203
 
1127
1204
  except Exception as e:
1128
1205
  log_error(f"Error getting knowledge contents: {e}")
1129
- return [], 0
1206
+ raise e
1130
1207
 
1131
1208
  def upsert_knowledge_content(self, knowledge_row: KnowledgeRow):
1132
1209
  """Upsert knowledge content in the database.
@@ -1148,7 +1225,7 @@ class RedisDb(BaseDb):
1148
1225
 
1149
1226
  except Exception as e:
1150
1227
  log_error(f"Error upserting knowledge content: {e}")
1151
- return None
1228
+ raise e
1152
1229
 
1153
1230
  # -- Eval methods --
1154
1231
 
@@ -1181,7 +1258,7 @@ class RedisDb(BaseDb):
1181
1258
 
1182
1259
  except Exception as e:
1183
1260
  log_error(f"Error creating eval run: {e}")
1184
- return None
1261
+ raise e
1185
1262
 
1186
1263
  def delete_eval_run(self, eval_run_id: str) -> None:
1187
1264
  """Delete an eval run from Redis.
@@ -1256,7 +1333,7 @@ class RedisDb(BaseDb):
1256
1333
 
1257
1334
  except Exception as e:
1258
1335
  log_error(f"Exception getting eval run {eval_run_id}: {e}")
1259
- return None
1336
+ raise e
1260
1337
 
1261
1338
  def get_eval_runs(
1262
1339
  self,
@@ -1332,7 +1409,7 @@ class RedisDb(BaseDb):
1332
1409
 
1333
1410
  except Exception as e:
1334
1411
  log_error(f"Exception getting eval runs: {e}")
1335
- return []
1412
+ raise e
1336
1413
 
1337
1414
  def rename_eval_run(
1338
1415
  self, eval_run_id: str, name: str, deserialize: Optional[bool] = True