agno 2.3.26__py3-none-any.whl → 2.4.1__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 (140) hide show
  1. agno/agent/__init__.py +4 -0
  2. agno/agent/agent.py +1368 -541
  3. agno/agent/remote.py +13 -0
  4. agno/db/base.py +339 -0
  5. agno/db/postgres/async_postgres.py +116 -12
  6. agno/db/postgres/postgres.py +1242 -25
  7. agno/db/postgres/schemas.py +48 -1
  8. agno/db/sqlite/async_sqlite.py +119 -4
  9. agno/db/sqlite/schemas.py +51 -0
  10. agno/db/sqlite/sqlite.py +1186 -13
  11. agno/db/utils.py +37 -1
  12. agno/integrations/discord/client.py +12 -1
  13. agno/knowledge/__init__.py +4 -0
  14. agno/knowledge/chunking/code.py +1 -1
  15. agno/knowledge/chunking/semantic.py +1 -1
  16. agno/knowledge/chunking/strategy.py +4 -0
  17. agno/knowledge/filesystem.py +412 -0
  18. agno/knowledge/knowledge.py +3722 -2182
  19. agno/knowledge/protocol.py +134 -0
  20. agno/knowledge/reader/arxiv_reader.py +2 -2
  21. agno/knowledge/reader/base.py +9 -7
  22. agno/knowledge/reader/csv_reader.py +236 -13
  23. agno/knowledge/reader/docx_reader.py +2 -2
  24. agno/knowledge/reader/field_labeled_csv_reader.py +169 -5
  25. agno/knowledge/reader/firecrawl_reader.py +2 -2
  26. agno/knowledge/reader/json_reader.py +2 -2
  27. agno/knowledge/reader/markdown_reader.py +2 -2
  28. agno/knowledge/reader/pdf_reader.py +5 -4
  29. agno/knowledge/reader/pptx_reader.py +2 -2
  30. agno/knowledge/reader/reader_factory.py +118 -1
  31. agno/knowledge/reader/s3_reader.py +2 -2
  32. agno/knowledge/reader/tavily_reader.py +2 -2
  33. agno/knowledge/reader/text_reader.py +2 -2
  34. agno/knowledge/reader/web_search_reader.py +2 -2
  35. agno/knowledge/reader/website_reader.py +5 -3
  36. agno/knowledge/reader/wikipedia_reader.py +2 -2
  37. agno/knowledge/reader/youtube_reader.py +2 -2
  38. agno/knowledge/remote_content/__init__.py +29 -0
  39. agno/knowledge/remote_content/config.py +204 -0
  40. agno/knowledge/remote_content/remote_content.py +74 -17
  41. agno/knowledge/utils.py +37 -29
  42. agno/learn/__init__.py +6 -0
  43. agno/learn/machine.py +35 -0
  44. agno/learn/schemas.py +82 -11
  45. agno/learn/stores/__init__.py +3 -0
  46. agno/learn/stores/decision_log.py +1156 -0
  47. agno/learn/stores/learned_knowledge.py +6 -6
  48. agno/models/anthropic/claude.py +24 -0
  49. agno/models/aws/bedrock.py +20 -0
  50. agno/models/base.py +60 -6
  51. agno/models/cerebras/cerebras.py +34 -2
  52. agno/models/cohere/chat.py +25 -0
  53. agno/models/google/gemini.py +50 -5
  54. agno/models/litellm/chat.py +38 -0
  55. agno/models/n1n/__init__.py +3 -0
  56. agno/models/n1n/n1n.py +57 -0
  57. agno/models/openai/chat.py +25 -1
  58. agno/models/openrouter/openrouter.py +46 -0
  59. agno/models/perplexity/perplexity.py +2 -0
  60. agno/models/response.py +16 -0
  61. agno/os/app.py +83 -44
  62. agno/os/interfaces/slack/router.py +10 -1
  63. agno/os/interfaces/whatsapp/router.py +6 -0
  64. agno/os/middleware/__init__.py +2 -0
  65. agno/os/middleware/trailing_slash.py +27 -0
  66. agno/os/router.py +1 -0
  67. agno/os/routers/agents/router.py +29 -16
  68. agno/os/routers/agents/schema.py +6 -4
  69. agno/os/routers/components/__init__.py +3 -0
  70. agno/os/routers/components/components.py +475 -0
  71. agno/os/routers/evals/schemas.py +4 -3
  72. agno/os/routers/health.py +3 -3
  73. agno/os/routers/knowledge/knowledge.py +128 -3
  74. agno/os/routers/knowledge/schemas.py +12 -0
  75. agno/os/routers/memory/schemas.py +4 -2
  76. agno/os/routers/metrics/metrics.py +9 -11
  77. agno/os/routers/metrics/schemas.py +10 -6
  78. agno/os/routers/registry/__init__.py +3 -0
  79. agno/os/routers/registry/registry.py +337 -0
  80. agno/os/routers/teams/router.py +20 -8
  81. agno/os/routers/teams/schema.py +6 -4
  82. agno/os/routers/traces/traces.py +5 -5
  83. agno/os/routers/workflows/router.py +38 -11
  84. agno/os/routers/workflows/schema.py +1 -1
  85. agno/os/schema.py +92 -26
  86. agno/os/utils.py +84 -19
  87. agno/reasoning/anthropic.py +2 -2
  88. agno/reasoning/azure_ai_foundry.py +2 -2
  89. agno/reasoning/deepseek.py +2 -2
  90. agno/reasoning/default.py +6 -7
  91. agno/reasoning/gemini.py +2 -2
  92. agno/reasoning/helpers.py +6 -7
  93. agno/reasoning/manager.py +4 -10
  94. agno/reasoning/ollama.py +2 -2
  95. agno/reasoning/openai.py +2 -2
  96. agno/reasoning/vertexai.py +2 -2
  97. agno/registry/__init__.py +3 -0
  98. agno/registry/registry.py +68 -0
  99. agno/run/agent.py +59 -0
  100. agno/run/base.py +7 -0
  101. agno/run/team.py +57 -0
  102. agno/skills/agent_skills.py +10 -3
  103. agno/team/__init__.py +3 -1
  104. agno/team/team.py +1165 -330
  105. agno/tools/duckduckgo.py +25 -71
  106. agno/tools/exa.py +0 -21
  107. agno/tools/function.py +35 -83
  108. agno/tools/knowledge.py +9 -4
  109. agno/tools/mem0.py +11 -10
  110. agno/tools/memory.py +47 -46
  111. agno/tools/parallel.py +0 -7
  112. agno/tools/reasoning.py +30 -23
  113. agno/tools/tavily.py +4 -1
  114. agno/tools/websearch.py +93 -0
  115. agno/tools/website.py +1 -1
  116. agno/tools/wikipedia.py +1 -1
  117. agno/tools/workflow.py +48 -47
  118. agno/utils/agent.py +42 -5
  119. agno/utils/events.py +160 -2
  120. agno/utils/print_response/agent.py +0 -31
  121. agno/utils/print_response/team.py +0 -2
  122. agno/utils/print_response/workflow.py +0 -2
  123. agno/utils/team.py +61 -11
  124. agno/vectordb/lancedb/lance_db.py +4 -1
  125. agno/vectordb/mongodb/mongodb.py +1 -1
  126. agno/vectordb/pgvector/pgvector.py +3 -3
  127. agno/vectordb/qdrant/qdrant.py +4 -4
  128. agno/workflow/__init__.py +3 -1
  129. agno/workflow/condition.py +0 -21
  130. agno/workflow/loop.py +0 -21
  131. agno/workflow/parallel.py +0 -21
  132. agno/workflow/router.py +0 -21
  133. agno/workflow/step.py +117 -24
  134. agno/workflow/steps.py +0 -21
  135. agno/workflow/workflow.py +427 -63
  136. {agno-2.3.26.dist-info → agno-2.4.1.dist-info}/METADATA +49 -76
  137. {agno-2.3.26.dist-info → agno-2.4.1.dist-info}/RECORD +140 -126
  138. {agno-2.3.26.dist-info → agno-2.4.1.dist-info}/WHEEL +1 -1
  139. {agno-2.3.26.dist-info → agno-2.4.1.dist-info}/licenses/LICENSE +0 -0
  140. {agno-2.3.26.dist-info → agno-2.4.1.dist-info}/top_level.txt +0 -0
agno/agent/remote.py CHANGED
@@ -23,6 +23,19 @@ class RemoteAgent(BaseRemote):
23
23
  # Private cache for agent config with TTL: (config, timestamp)
24
24
  _cached_agent_config: Optional[Tuple["AgentResponse", float]] = field(default=None, init=False, repr=False)
25
25
 
26
+ knowledge_filters: Optional[Dict[str, Any]] = None
27
+ enable_agentic_knowledge_filters: Optional[bool] = False
28
+ output_schema: Optional[Any] = None
29
+ store_media: bool = True
30
+ store_tool_messages: bool = True
31
+ store_history_messages: bool = True
32
+ send_media_to_model: bool = True
33
+ add_history_to_context: bool = False
34
+ num_history_runs: Optional[int] = None
35
+ num_history_messages: Optional[int] = None
36
+ debug_mode: bool = False
37
+ debug_level: Literal[1, 2] = 1
38
+
26
39
  def __init__(
27
40
  self,
28
41
  base_url: str,
agno/db/base.py CHANGED
@@ -20,6 +20,12 @@ class SessionType(str, Enum):
20
20
  WORKFLOW = "workflow"
21
21
 
22
22
 
23
+ class ComponentType(str, Enum):
24
+ AGENT = "agent"
25
+ TEAM = "team"
26
+ WORKFLOW = "workflow"
27
+
28
+
23
29
  class BaseDb(ABC):
24
30
  """Base abstract class for all our Database implementations."""
25
31
 
@@ -37,6 +43,9 @@ class BaseDb(ABC):
37
43
  traces_table: Optional[str] = None,
38
44
  spans_table: Optional[str] = None,
39
45
  versions_table: Optional[str] = None,
46
+ components_table: Optional[str] = None,
47
+ component_configs_table: Optional[str] = None,
48
+ component_links_table: Optional[str] = None,
40
49
  learnings_table: Optional[str] = None,
41
50
  id: Optional[str] = None,
42
51
  ):
@@ -50,8 +59,52 @@ class BaseDb(ABC):
50
59
  self.trace_table_name = traces_table or "agno_traces"
51
60
  self.span_table_name = spans_table or "agno_spans"
52
61
  self.versions_table_name = versions_table or "agno_schema_versions"
62
+ self.components_table_name = components_table or "agno_components"
63
+ self.component_configs_table_name = component_configs_table or "agno_component_configs"
64
+ self.component_links_table_name = component_links_table or "agno_component_links"
53
65
  self.learnings_table_name = learnings_table or "agno_learnings"
54
66
 
67
+ def to_dict(self) -> Dict[str, Any]:
68
+ """
69
+ Serialize common DB fields (table names + id). Subclasses may extend this.
70
+ """
71
+ return {
72
+ "id": self.id,
73
+ "session_table": self.session_table_name,
74
+ "culture_table": self.culture_table_name,
75
+ "memory_table": self.memory_table_name,
76
+ "metrics_table": self.metrics_table_name,
77
+ "eval_table": self.eval_table_name,
78
+ "knowledge_table": self.knowledge_table_name,
79
+ "traces_table": self.trace_table_name,
80
+ "spans_table": self.span_table_name,
81
+ "versions_table": self.versions_table_name,
82
+ "components_table": self.components_table_name,
83
+ "component_configs_table": self.component_configs_table_name,
84
+ "component_links_table": self.component_links_table_name,
85
+ }
86
+
87
+ @classmethod
88
+ def from_dict(cls, data: Dict[str, Any]) -> "BaseDb":
89
+ """
90
+ Reconstruct using only fields defined in BaseDb. Subclasses should override this.
91
+ """
92
+ return cls(
93
+ session_table=data.get("session_table"),
94
+ culture_table=data.get("culture_table"),
95
+ memory_table=data.get("memory_table"),
96
+ metrics_table=data.get("metrics_table"),
97
+ eval_table=data.get("eval_table"),
98
+ knowledge_table=data.get("knowledge_table"),
99
+ traces_table=data.get("traces_table"),
100
+ spans_table=data.get("spans_table"),
101
+ versions_table=data.get("versions_table"),
102
+ components_table=data.get("components_table"),
103
+ component_configs_table=data.get("component_configs_table"),
104
+ component_links_table=data.get("component_links_table"),
105
+ id=data.get("id"),
106
+ )
107
+
55
108
  @abstractmethod
56
109
  def table_exists(self, table_name: str) -> bool:
57
110
  raise NotImplementedError
@@ -499,6 +552,292 @@ class BaseDb(ABC):
499
552
  def upsert_cultural_knowledge(self, cultural_knowledge: CulturalKnowledge) -> Optional[CulturalKnowledge]:
500
553
  raise NotImplementedError
501
554
 
555
+ # --- Components (Optional) ---
556
+ # These methods are optional. Override in subclasses to enable component persistence.
557
+ def get_component(
558
+ self,
559
+ component_id: str,
560
+ component_type: Optional[ComponentType] = None,
561
+ ) -> Optional[Dict[str, Any]]:
562
+ """Get a component by ID.
563
+
564
+ Args:
565
+ component_id: The component ID.
566
+ component_type: Optional filter by type (agent|team|workflow).
567
+
568
+ Returns:
569
+ Component dictionary or None if not found.
570
+ """
571
+ raise NotImplementedError
572
+
573
+ def upsert_component(
574
+ self,
575
+ component_id: str,
576
+ component_type: Optional[ComponentType] = None,
577
+ name: Optional[str] = None,
578
+ description: Optional[str] = None,
579
+ metadata: Optional[Dict[str, Any]] = None,
580
+ ) -> Dict[str, Any]:
581
+ """Create or update a component.
582
+
583
+ Args:
584
+ component_id: Unique identifier.
585
+ component_type: Type (agent|team|workflow). Required for create, optional for update.
586
+ name: Display name.
587
+ description: Optional description.
588
+ metadata: Optional metadata dict.
589
+
590
+ Returns:
591
+ Created/updated component dictionary.
592
+
593
+ Raises:
594
+ ValueError: If creating and component_type is not provided.
595
+ """
596
+ raise NotImplementedError
597
+
598
+ def delete_component(
599
+ self,
600
+ component_id: str,
601
+ hard_delete: bool = False,
602
+ ) -> bool:
603
+ """Delete a component and all its configs/links.
604
+
605
+ Args:
606
+ component_id: The component ID.
607
+ hard_delete: If True, permanently delete. Otherwise soft-delete.
608
+
609
+ Returns:
610
+ True if deleted, False if not found or already deleted.
611
+ """
612
+ raise NotImplementedError
613
+
614
+ def list_components(
615
+ self,
616
+ component_type: Optional[ComponentType] = None,
617
+ include_deleted: bool = False,
618
+ limit: int = 20,
619
+ offset: int = 0,
620
+ ) -> Tuple[List[Dict[str, Any]], int]:
621
+ """List components with pagination.
622
+
623
+ Args:
624
+ component_type: Filter by type (agent|team|workflow).
625
+ include_deleted: Include soft-deleted components.
626
+ limit: Maximum number of items to return.
627
+ offset: Number of items to skip.
628
+
629
+ Returns:
630
+ Tuple of (list of component dicts, total count).
631
+ """
632
+ raise NotImplementedError
633
+
634
+ def create_component_with_config(
635
+ self,
636
+ component_id: str,
637
+ component_type: ComponentType,
638
+ name: Optional[str],
639
+ config: Dict[str, Any],
640
+ description: Optional[str] = None,
641
+ metadata: Optional[Dict[str, Any]] = None,
642
+ label: Optional[str] = None,
643
+ stage: str = "draft",
644
+ notes: Optional[str] = None,
645
+ links: Optional[List[Dict[str, Any]]] = None,
646
+ ) -> Tuple[Dict[str, Any], Dict[str, Any]]:
647
+ """Create a component with its initial config atomically.
648
+
649
+ Args:
650
+ component_id: Unique identifier.
651
+ component_type: Type (agent|team|workflow).
652
+ name: Display name.
653
+ config: The config data.
654
+ description: Optional description.
655
+ metadata: Optional metadata dict.
656
+ label: Optional config label.
657
+ stage: "draft" or "published".
658
+ notes: Optional notes.
659
+ links: Optional list of links. Each must have child_version set.
660
+
661
+ Returns:
662
+ Tuple of (component dict, config dict).
663
+
664
+ Raises:
665
+ ValueError: If component already exists, invalid stage, or link missing child_version.
666
+ """
667
+ raise NotImplementedError
668
+
669
+ # --- Component Configs (Optional) ---
670
+ def get_config(
671
+ self,
672
+ component_id: str,
673
+ version: Optional[int] = None,
674
+ label: Optional[str] = None,
675
+ ) -> Optional[Dict[str, Any]]:
676
+ """Get a config by component ID and version or label.
677
+
678
+ Args:
679
+ component_id: The component ID.
680
+ version: Specific version number. If None, uses current.
681
+ label: Config label to lookup. Ignored if version is provided.
682
+
683
+ Returns:
684
+ Config dictionary or None if not found.
685
+ """
686
+ raise NotImplementedError
687
+
688
+ def upsert_config(
689
+ self,
690
+ component_id: str,
691
+ config: Optional[Dict[str, Any]] = None,
692
+ version: Optional[int] = None,
693
+ label: Optional[str] = None,
694
+ stage: Optional[str] = None,
695
+ notes: Optional[str] = None,
696
+ links: Optional[List[Dict[str, Any]]] = None,
697
+ ) -> Dict[str, Any]:
698
+ """Create or update a config version for a component.
699
+
700
+ Rules:
701
+ - Draft configs can be edited freely
702
+ - Published configs are immutable
703
+ - Publishing a config automatically sets it as current_version
704
+
705
+ Args:
706
+ component_id: The component ID.
707
+ config: The config data. Required for create, optional for update.
708
+ version: If None, creates new version. If provided, updates that version.
709
+ label: Optional human-readable label.
710
+ stage: "draft" or "published". Defaults to "draft" for new configs.
711
+ notes: Optional notes.
712
+ links: Optional list of links. Each link must have child_version set.
713
+
714
+ Returns:
715
+ Created/updated config dictionary.
716
+
717
+ Raises:
718
+ ValueError: If component doesn't exist, version not found, label conflict,
719
+ or attempting to update a published config.
720
+ """
721
+ raise NotImplementedError
722
+
723
+ def delete_config(
724
+ self,
725
+ component_id: str,
726
+ version: int,
727
+ ) -> bool:
728
+ """Delete a specific config version.
729
+
730
+ Only draft configs can be deleted. Published configs are immutable.
731
+ Cannot delete the current version.
732
+
733
+ Args:
734
+ component_id: The component ID.
735
+ version: The version to delete.
736
+
737
+ Returns:
738
+ True if deleted, False if not found.
739
+
740
+ Raises:
741
+ ValueError: If attempting to delete a published or current config.
742
+ """
743
+ raise NotImplementedError
744
+
745
+ def list_configs(
746
+ self,
747
+ component_id: str,
748
+ include_config: bool = False,
749
+ ) -> List[Dict[str, Any]]:
750
+ """List all config versions for a component.
751
+
752
+ Args:
753
+ component_id: The component ID.
754
+ include_config: If True, include full config blob. Otherwise just metadata.
755
+
756
+ Returns:
757
+ List of config dictionaries, newest first.
758
+ Returns empty list if component not found or deleted.
759
+ """
760
+ raise NotImplementedError
761
+
762
+ def set_current_version(
763
+ self,
764
+ component_id: str,
765
+ version: int,
766
+ ) -> bool:
767
+ """Set a specific published version as current.
768
+
769
+ Only published configs can be set as current. This is used for
770
+ rollback scenarios where you want to switch to a previous
771
+ published version.
772
+
773
+ Args:
774
+ component_id: The component ID.
775
+ version: The version to set as current (must be published).
776
+
777
+ Returns:
778
+ True if successful, False if component or version not found.
779
+
780
+ Raises:
781
+ ValueError: If attempting to set a draft config as current.
782
+ """
783
+ raise NotImplementedError
784
+
785
+ # --- Component Links (Optional) ---
786
+ def get_links(
787
+ self,
788
+ component_id: str,
789
+ version: int,
790
+ link_kind: Optional[str] = None,
791
+ ) -> List[Dict[str, Any]]:
792
+ """Get links for a config version.
793
+
794
+ Args:
795
+ component_id: The component ID.
796
+ version: The config version.
797
+ link_kind: Optional filter by link kind (member|step).
798
+
799
+ Returns:
800
+ List of link dictionaries, ordered by position.
801
+ """
802
+ raise NotImplementedError
803
+
804
+ def get_dependents(
805
+ self,
806
+ component_id: str,
807
+ version: Optional[int] = None,
808
+ ) -> List[Dict[str, Any]]:
809
+ """Find all components that reference this component.
810
+
811
+ Args:
812
+ component_id: The component ID to find dependents of.
813
+ version: Optional specific version. If None, finds links to any version.
814
+
815
+ Returns:
816
+ List of link dictionaries showing what depends on this component.
817
+ """
818
+ raise NotImplementedError
819
+
820
+ def load_component_graph(
821
+ self,
822
+ component_id: str,
823
+ version: Optional[int] = None,
824
+ label: Optional[str] = None,
825
+ ) -> Optional[Dict[str, Any]]:
826
+ """Load a component with its full resolved graph.
827
+
828
+ Handles cycles by returning a stub with cycle_detected=True.
829
+
830
+ Args:
831
+ component_id: The component ID.
832
+ version: Specific version or None for current.
833
+ label: Optional label of the component.
834
+
835
+ Returns:
836
+ Dictionary with component, config, children, and resolved_versions.
837
+ Returns None if component not found.
838
+ """
839
+ raise NotImplementedError
840
+
502
841
  # --- Learnings ---
503
842
  @abstractmethod
504
843
  def get_learning(
@@ -1,5 +1,4 @@
1
1
  import time
2
- import warnings
3
2
  from datetime import date, datetime, timedelta, timezone
4
3
  from typing import TYPE_CHECKING, Any, Dict, List, Optional, Sequence, Tuple, Union, cast
5
4
  from uuid import uuid4
@@ -7,7 +6,7 @@ from uuid import uuid4
7
6
  if TYPE_CHECKING:
8
7
  from agno.tracing.schemas import Span, Trace
9
8
 
10
- from agno.db.base import AsyncBaseDb, SessionType
9
+ from agno.db.base import AsyncBaseDb, ComponentType, SessionType
11
10
  from agno.db.migrations.manager import MigrationManager
12
11
  from agno.db.postgres.schemas import get_table_schema_definition
13
12
  from agno.db.postgres.utils import (
@@ -60,7 +59,6 @@ class AsyncPostgresDb(AsyncBaseDb):
60
59
  versions_table: Optional[str] = None,
61
60
  learnings_table: Optional[str] = None,
62
61
  create_schema: bool = True,
63
- db_id: Optional[str] = None, # Deprecated, use id instead.
64
62
  ):
65
63
  """
66
64
  Async interface for interacting with a PostgreSQL database.
@@ -96,21 +94,14 @@ class AsyncPostgresDb(AsyncBaseDb):
96
94
  learnings_table (Optional[str]): Name of the table to store learnings.
97
95
  create_schema (bool): Whether to automatically create the database schema if it doesn't exist.
98
96
  Set to False if schema is managed externally (e.g., via migrations). Defaults to True.
99
- db_id: Deprecated, use id instead.
100
97
 
101
98
  Raises:
102
99
  ValueError: If neither db_url nor db_engine is provided.
103
100
  ValueError: If none of the tables are provided.
104
101
  """
105
- if db_id is not None:
106
- warnings.warn(
107
- "The 'db_id' parameter is deprecated and will be removed in future versions. Use 'id' instead.",
108
- DeprecationWarning,
109
- stacklevel=2,
110
- )
111
102
 
112
103
  super().__init__(
113
- id=id or db_id,
104
+ id=id,
114
105
  session_table=session_table,
115
106
  memory_table=memory_table,
116
107
  metrics_table=metrics_table,
@@ -2876,7 +2867,7 @@ class AsyncPostgresDb(AsyncBaseDb):
2876
2867
  async with self.async_session_factory() as sess, sess.begin():
2877
2868
  stmt = table.delete().where(table.c.learning_id == id)
2878
2869
  result = await sess.execute(stmt)
2879
- return result.rowcount > 0
2870
+ return getattr(result, "rowcount", 0) > 0
2880
2871
 
2881
2872
  except Exception as e:
2882
2873
  log_debug(f"Error deleting learning: {e}")
@@ -2947,3 +2938,116 @@ class AsyncPostgresDb(AsyncBaseDb):
2947
2938
  except Exception as e:
2948
2939
  log_debug(f"Error getting learnings: {e}")
2949
2940
  return []
2941
+
2942
+ # --- Components (Not yet supported for async) ---
2943
+ def get_component(
2944
+ self,
2945
+ component_id: str,
2946
+ component_type: Optional[ComponentType] = None,
2947
+ ) -> Optional[Dict[str, Any]]:
2948
+ raise NotImplementedError("Component methods not yet supported for async databases")
2949
+
2950
+ def upsert_component(
2951
+ self,
2952
+ component_id: str,
2953
+ component_type: Optional[ComponentType] = None,
2954
+ name: Optional[str] = None,
2955
+ description: Optional[str] = None,
2956
+ metadata: Optional[Dict[str, Any]] = None,
2957
+ ) -> Dict[str, Any]:
2958
+ raise NotImplementedError("Component methods not yet supported for async databases")
2959
+
2960
+ def delete_component(
2961
+ self,
2962
+ component_id: str,
2963
+ hard_delete: bool = False,
2964
+ ) -> bool:
2965
+ raise NotImplementedError("Component methods not yet supported for async databases")
2966
+
2967
+ def list_components(
2968
+ self,
2969
+ component_type: Optional[ComponentType] = None,
2970
+ include_deleted: bool = False,
2971
+ limit: int = 20,
2972
+ offset: int = 0,
2973
+ ) -> Tuple[List[Dict[str, Any]], int]:
2974
+ raise NotImplementedError("Component methods not yet supported for async databases")
2975
+
2976
+ def create_component_with_config(
2977
+ self,
2978
+ component_id: str,
2979
+ component_type: ComponentType,
2980
+ name: Optional[str],
2981
+ config: Dict[str, Any],
2982
+ description: Optional[str] = None,
2983
+ metadata: Optional[Dict[str, Any]] = None,
2984
+ label: Optional[str] = None,
2985
+ stage: str = "draft",
2986
+ notes: Optional[str] = None,
2987
+ links: Optional[List[Dict[str, Any]]] = None,
2988
+ ) -> Tuple[Dict[str, Any], Dict[str, Any]]:
2989
+ raise NotImplementedError("Component methods not yet supported for async databases")
2990
+
2991
+ def get_config(
2992
+ self,
2993
+ component_id: str,
2994
+ version: Optional[int] = None,
2995
+ label: Optional[str] = None,
2996
+ ) -> Optional[Dict[str, Any]]:
2997
+ raise NotImplementedError("Component methods not yet supported for async databases")
2998
+
2999
+ def upsert_config(
3000
+ self,
3001
+ component_id: str,
3002
+ config: Optional[Dict[str, Any]] = None,
3003
+ version: Optional[int] = None,
3004
+ label: Optional[str] = None,
3005
+ stage: Optional[str] = None,
3006
+ notes: Optional[str] = None,
3007
+ links: Optional[List[Dict[str, Any]]] = None,
3008
+ ) -> Dict[str, Any]:
3009
+ raise NotImplementedError("Component methods not yet supported for async databases")
3010
+
3011
+ def delete_config(
3012
+ self,
3013
+ component_id: str,
3014
+ version: int,
3015
+ ) -> bool:
3016
+ raise NotImplementedError("Component methods not yet supported for async databases")
3017
+
3018
+ def list_configs(
3019
+ self,
3020
+ component_id: str,
3021
+ include_config: bool = False,
3022
+ ) -> List[Dict[str, Any]]:
3023
+ raise NotImplementedError("Component methods not yet supported for async databases")
3024
+
3025
+ def set_current_version(
3026
+ self,
3027
+ component_id: str,
3028
+ version: int,
3029
+ ) -> bool:
3030
+ raise NotImplementedError("Component methods not yet supported for async databases")
3031
+
3032
+ def get_links(
3033
+ self,
3034
+ component_id: str,
3035
+ version: int,
3036
+ link_kind: Optional[str] = None,
3037
+ ) -> List[Dict[str, Any]]:
3038
+ raise NotImplementedError("Component methods not yet supported for async databases")
3039
+
3040
+ def get_dependents(
3041
+ self,
3042
+ component_id: str,
3043
+ version: Optional[int] = None,
3044
+ ) -> List[Dict[str, Any]]:
3045
+ raise NotImplementedError("Component methods not yet supported for async databases")
3046
+
3047
+ def load_component_graph(
3048
+ self,
3049
+ component_id: str,
3050
+ version: Optional[int] = None,
3051
+ label: Optional[str] = None,
3052
+ ) -> Optional[Dict[str, Any]]:
3053
+ raise NotImplementedError("Component methods not yet supported for async databases")