agno 2.3.26__py3-none-any.whl → 2.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agno/agent/__init__.py +4 -0
- agno/agent/agent.py +1368 -541
- agno/agent/remote.py +13 -0
- agno/db/base.py +339 -0
- agno/db/postgres/async_postgres.py +116 -12
- agno/db/postgres/postgres.py +1229 -25
- agno/db/postgres/schemas.py +48 -1
- agno/db/sqlite/async_sqlite.py +119 -4
- agno/db/sqlite/schemas.py +51 -0
- agno/db/sqlite/sqlite.py +1173 -13
- agno/db/utils.py +37 -1
- agno/knowledge/__init__.py +4 -0
- agno/knowledge/chunking/code.py +1 -1
- agno/knowledge/chunking/semantic.py +1 -1
- agno/knowledge/chunking/strategy.py +4 -0
- agno/knowledge/filesystem.py +412 -0
- agno/knowledge/knowledge.py +2767 -2254
- agno/knowledge/protocol.py +134 -0
- agno/knowledge/reader/arxiv_reader.py +2 -2
- agno/knowledge/reader/base.py +9 -7
- agno/knowledge/reader/csv_reader.py +5 -5
- agno/knowledge/reader/docx_reader.py +2 -2
- agno/knowledge/reader/field_labeled_csv_reader.py +2 -2
- agno/knowledge/reader/firecrawl_reader.py +2 -2
- agno/knowledge/reader/json_reader.py +2 -2
- agno/knowledge/reader/markdown_reader.py +2 -2
- agno/knowledge/reader/pdf_reader.py +5 -4
- agno/knowledge/reader/pptx_reader.py +2 -2
- agno/knowledge/reader/reader_factory.py +110 -0
- agno/knowledge/reader/s3_reader.py +2 -2
- agno/knowledge/reader/tavily_reader.py +2 -2
- agno/knowledge/reader/text_reader.py +2 -2
- agno/knowledge/reader/web_search_reader.py +2 -2
- agno/knowledge/reader/website_reader.py +5 -3
- agno/knowledge/reader/wikipedia_reader.py +2 -2
- agno/knowledge/reader/youtube_reader.py +2 -2
- agno/knowledge/utils.py +37 -29
- agno/learn/__init__.py +6 -0
- agno/learn/machine.py +35 -0
- agno/learn/schemas.py +82 -11
- agno/learn/stores/__init__.py +3 -0
- agno/learn/stores/decision_log.py +1156 -0
- agno/learn/stores/learned_knowledge.py +6 -6
- agno/models/anthropic/claude.py +24 -0
- agno/models/aws/bedrock.py +20 -0
- agno/models/base.py +48 -4
- agno/models/cohere/chat.py +25 -0
- agno/models/google/gemini.py +50 -5
- agno/models/litellm/chat.py +38 -0
- agno/models/openai/chat.py +7 -0
- agno/models/openrouter/openrouter.py +46 -0
- agno/models/response.py +16 -0
- agno/os/app.py +83 -44
- agno/os/middleware/__init__.py +2 -0
- agno/os/middleware/trailing_slash.py +27 -0
- agno/os/router.py +1 -0
- agno/os/routers/agents/router.py +29 -16
- agno/os/routers/agents/schema.py +6 -4
- agno/os/routers/components/__init__.py +3 -0
- agno/os/routers/components/components.py +466 -0
- agno/os/routers/evals/schemas.py +4 -3
- agno/os/routers/health.py +3 -3
- agno/os/routers/knowledge/knowledge.py +3 -3
- agno/os/routers/memory/schemas.py +4 -2
- agno/os/routers/metrics/metrics.py +9 -11
- agno/os/routers/metrics/schemas.py +10 -6
- agno/os/routers/registry/__init__.py +3 -0
- agno/os/routers/registry/registry.py +337 -0
- agno/os/routers/teams/router.py +20 -8
- agno/os/routers/teams/schema.py +6 -4
- agno/os/routers/traces/traces.py +5 -5
- agno/os/routers/workflows/router.py +38 -11
- agno/os/routers/workflows/schema.py +1 -1
- agno/os/schema.py +92 -26
- agno/os/utils.py +84 -19
- agno/reasoning/anthropic.py +2 -2
- agno/reasoning/azure_ai_foundry.py +2 -2
- agno/reasoning/deepseek.py +2 -2
- agno/reasoning/default.py +6 -7
- agno/reasoning/gemini.py +2 -2
- agno/reasoning/helpers.py +6 -7
- agno/reasoning/manager.py +4 -10
- agno/reasoning/ollama.py +2 -2
- agno/reasoning/openai.py +2 -2
- agno/reasoning/vertexai.py +2 -2
- agno/registry/__init__.py +3 -0
- agno/registry/registry.py +68 -0
- agno/run/agent.py +57 -0
- agno/run/base.py +7 -0
- agno/run/team.py +57 -0
- agno/skills/agent_skills.py +10 -3
- agno/team/__init__.py +3 -1
- agno/team/team.py +1145 -326
- agno/tools/duckduckgo.py +25 -71
- agno/tools/exa.py +0 -21
- agno/tools/function.py +35 -83
- agno/tools/knowledge.py +9 -4
- agno/tools/mem0.py +11 -10
- agno/tools/memory.py +47 -46
- agno/tools/parallel.py +0 -7
- agno/tools/reasoning.py +30 -23
- agno/tools/tavily.py +4 -1
- agno/tools/websearch.py +93 -0
- agno/tools/website.py +1 -1
- agno/tools/wikipedia.py +1 -1
- agno/tools/workflow.py +48 -47
- agno/utils/agent.py +42 -5
- agno/utils/events.py +160 -2
- agno/utils/print_response/agent.py +0 -31
- agno/utils/print_response/team.py +0 -2
- agno/utils/print_response/workflow.py +0 -2
- agno/utils/team.py +61 -11
- agno/vectordb/lancedb/lance_db.py +4 -1
- agno/vectordb/mongodb/mongodb.py +1 -1
- agno/vectordb/qdrant/qdrant.py +4 -4
- agno/workflow/__init__.py +3 -1
- agno/workflow/condition.py +0 -21
- agno/workflow/loop.py +0 -21
- agno/workflow/parallel.py +0 -21
- agno/workflow/router.py +0 -21
- agno/workflow/step.py +117 -24
- agno/workflow/steps.py +0 -21
- agno/workflow/workflow.py +427 -63
- {agno-2.3.26.dist-info → agno-2.4.0.dist-info}/METADATA +46 -76
- {agno-2.3.26.dist-info → agno-2.4.0.dist-info}/RECORD +128 -117
- {agno-2.3.26.dist-info → agno-2.4.0.dist-info}/WHEEL +0 -0
- {agno-2.3.26.dist-info → agno-2.4.0.dist-info}/licenses/LICENSE +0 -0
- {agno-2.3.26.dist-info → agno-2.4.0.dist-info}/top_level.txt +0 -0
agno/db/postgres/schemas.py
CHANGED
|
@@ -4,7 +4,7 @@ from typing import Any
|
|
|
4
4
|
|
|
5
5
|
try:
|
|
6
6
|
from sqlalchemy.dialects.postgresql import JSONB
|
|
7
|
-
from sqlalchemy.types import BigInteger, Boolean, Date, String, Text
|
|
7
|
+
from sqlalchemy.types import BigInteger, Boolean, Date, Integer, String, Text
|
|
8
8
|
except ImportError:
|
|
9
9
|
raise ImportError("`sqlalchemy` not installed. Please install it using `pip install sqlalchemy`")
|
|
10
10
|
|
|
@@ -169,6 +169,50 @@ def _get_span_table_schema(traces_table_name: str = "agno_traces", db_schema: st
|
|
|
169
169
|
}
|
|
170
170
|
|
|
171
171
|
|
|
172
|
+
COMPONENT_TABLE_SCHEMA = {
|
|
173
|
+
"component_id": {"type": String, "primary_key": True},
|
|
174
|
+
"component_type": {"type": String, "nullable": False, "index": True}, # agent|team|workflow
|
|
175
|
+
"name": {"type": String, "nullable": True, "index": True},
|
|
176
|
+
"description": {"type": Text, "nullable": True},
|
|
177
|
+
"current_version": {"type": Integer, "nullable": True, "index": True},
|
|
178
|
+
"metadata": {"type": JSONB, "nullable": True},
|
|
179
|
+
"created_at": {"type": BigInteger, "nullable": False, "index": True},
|
|
180
|
+
"updated_at": {"type": BigInteger, "nullable": True},
|
|
181
|
+
"deleted_at": {"type": BigInteger, "nullable": True},
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
COMPONENT_CONFIGS_TABLE_SCHEMA = {
|
|
185
|
+
"component_id": {"type": String, "primary_key": True, "foreign_key": "components.component_id"},
|
|
186
|
+
"version": {"type": Integer, "primary_key": True},
|
|
187
|
+
"label": {"type": String, "nullable": True}, # stable|v1.2.0|pre-refactor
|
|
188
|
+
"stage": {"type": String, "nullable": False, "default": "draft", "index": True}, # draft|published
|
|
189
|
+
"config": {"type": JSONB, "nullable": False},
|
|
190
|
+
"notes": {"type": Text, "nullable": True},
|
|
191
|
+
"created_at": {"type": BigInteger, "nullable": False, "index": True},
|
|
192
|
+
"updated_at": {"type": BigInteger, "nullable": True},
|
|
193
|
+
"deleted_at": {"type": BigInteger, "nullable": True},
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
COMPONENT_LINKS_TABLE_SCHEMA = {
|
|
197
|
+
"parent_component_id": {"type": String, "nullable": False},
|
|
198
|
+
"parent_version": {"type": Integer, "nullable": False},
|
|
199
|
+
"link_kind": {"type": String, "nullable": False, "index": True},
|
|
200
|
+
"link_key": {"type": String, "nullable": False},
|
|
201
|
+
"child_component_id": {"type": String, "nullable": False, "foreign_key": "components.component_id"},
|
|
202
|
+
"child_version": {"type": Integer, "nullable": True},
|
|
203
|
+
"position": {"type": Integer, "nullable": False},
|
|
204
|
+
"meta": {"type": JSONB, "nullable": True},
|
|
205
|
+
"created_at": {"type": BigInteger, "nullable": True, "index": True},
|
|
206
|
+
"updated_at": {"type": BigInteger, "nullable": True},
|
|
207
|
+
"__primary_key__": ["parent_component_id", "parent_version", "link_kind", "link_key"],
|
|
208
|
+
"__foreign_keys__": [
|
|
209
|
+
{
|
|
210
|
+
"columns": ["parent_component_id", "parent_version"],
|
|
211
|
+
"ref_table": "component_configs",
|
|
212
|
+
"ref_columns": ["component_id", "version"],
|
|
213
|
+
}
|
|
214
|
+
],
|
|
215
|
+
}
|
|
172
216
|
LEARNINGS_TABLE_SCHEMA = {
|
|
173
217
|
"learning_id": {"type": String, "primary_key": True, "nullable": False},
|
|
174
218
|
"learning_type": {"type": String, "nullable": False, "index": True},
|
|
@@ -214,6 +258,9 @@ def get_table_schema_definition(
|
|
|
214
258
|
"culture": CULTURAL_KNOWLEDGE_TABLE_SCHEMA,
|
|
215
259
|
"versions": VERSIONS_TABLE_SCHEMA,
|
|
216
260
|
"traces": TRACE_TABLE_SCHEMA,
|
|
261
|
+
"components": COMPONENT_TABLE_SCHEMA,
|
|
262
|
+
"component_configs": COMPONENT_CONFIGS_TABLE_SCHEMA,
|
|
263
|
+
"component_links": COMPONENT_LINKS_TABLE_SCHEMA,
|
|
217
264
|
"learnings": LEARNINGS_TABLE_SCHEMA,
|
|
218
265
|
}
|
|
219
266
|
|
agno/db/sqlite/async_sqlite.py
CHANGED
|
@@ -7,7 +7,7 @@ from uuid import uuid4
|
|
|
7
7
|
if TYPE_CHECKING:
|
|
8
8
|
from agno.tracing.schemas import Span, Trace
|
|
9
9
|
|
|
10
|
-
from agno.db.base import AsyncBaseDb, SessionType
|
|
10
|
+
from agno.db.base import AsyncBaseDb, ComponentType, SessionType
|
|
11
11
|
from agno.db.migrations.manager import MigrationManager
|
|
12
12
|
from agno.db.schemas.culture import CulturalKnowledge
|
|
13
13
|
from agno.db.schemas.evals import EvalFilterType, EvalRunRecord, EvalType
|
|
@@ -362,7 +362,7 @@ class AsyncSqliteDb(AsyncBaseDb):
|
|
|
362
362
|
table_name: str,
|
|
363
363
|
table_type: str,
|
|
364
364
|
create_table_if_not_found: Optional[bool] = False,
|
|
365
|
-
) -> Table:
|
|
365
|
+
) -> Optional[Table]:
|
|
366
366
|
"""
|
|
367
367
|
Check if the table exists and is valid, else create it.
|
|
368
368
|
|
|
@@ -376,7 +376,9 @@ class AsyncSqliteDb(AsyncBaseDb):
|
|
|
376
376
|
async with self.async_session_factory() as sess, sess.begin():
|
|
377
377
|
table_is_available = await ais_table_available(session=sess, table_name=table_name)
|
|
378
378
|
|
|
379
|
-
if
|
|
379
|
+
if not table_is_available:
|
|
380
|
+
if not create_table_if_not_found:
|
|
381
|
+
return None
|
|
380
382
|
return await self._create_table(table_name=table_name, table_type=table_type)
|
|
381
383
|
|
|
382
384
|
# SQLite version of table validation (no schema)
|
|
@@ -3090,7 +3092,7 @@ class AsyncSqliteDb(AsyncBaseDb):
|
|
|
3090
3092
|
async with self.async_session_factory() as sess, sess.begin():
|
|
3091
3093
|
stmt = table.delete().where(table.c.learning_id == id)
|
|
3092
3094
|
result = await sess.execute(stmt)
|
|
3093
|
-
return result
|
|
3095
|
+
return getattr(result, "rowcount", 0) > 0
|
|
3094
3096
|
|
|
3095
3097
|
except Exception as e:
|
|
3096
3098
|
log_debug(f"Error deleting learning: {e}")
|
|
@@ -3165,3 +3167,116 @@ class AsyncSqliteDb(AsyncBaseDb):
|
|
|
3165
3167
|
except Exception as e:
|
|
3166
3168
|
log_debug(f"Error getting learnings: {e}")
|
|
3167
3169
|
return []
|
|
3170
|
+
|
|
3171
|
+
# --- Components (Not yet supported for async) ---
|
|
3172
|
+
def get_component(
|
|
3173
|
+
self,
|
|
3174
|
+
component_id: str,
|
|
3175
|
+
component_type: Optional[ComponentType] = None,
|
|
3176
|
+
) -> Optional[Dict[str, Any]]:
|
|
3177
|
+
raise NotImplementedError("Component methods not yet supported for async databases")
|
|
3178
|
+
|
|
3179
|
+
def upsert_component(
|
|
3180
|
+
self,
|
|
3181
|
+
component_id: str,
|
|
3182
|
+
component_type: Optional[ComponentType] = None,
|
|
3183
|
+
name: Optional[str] = None,
|
|
3184
|
+
description: Optional[str] = None,
|
|
3185
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
3186
|
+
) -> Dict[str, Any]:
|
|
3187
|
+
raise NotImplementedError("Component methods not yet supported for async databases")
|
|
3188
|
+
|
|
3189
|
+
def delete_component(
|
|
3190
|
+
self,
|
|
3191
|
+
component_id: str,
|
|
3192
|
+
hard_delete: bool = False,
|
|
3193
|
+
) -> bool:
|
|
3194
|
+
raise NotImplementedError("Component methods not yet supported for async databases")
|
|
3195
|
+
|
|
3196
|
+
def list_components(
|
|
3197
|
+
self,
|
|
3198
|
+
component_type: Optional[ComponentType] = None,
|
|
3199
|
+
include_deleted: bool = False,
|
|
3200
|
+
limit: int = 20,
|
|
3201
|
+
offset: int = 0,
|
|
3202
|
+
) -> Tuple[List[Dict[str, Any]], int]:
|
|
3203
|
+
raise NotImplementedError("Component methods not yet supported for async databases")
|
|
3204
|
+
|
|
3205
|
+
def create_component_with_config(
|
|
3206
|
+
self,
|
|
3207
|
+
component_id: str,
|
|
3208
|
+
component_type: ComponentType,
|
|
3209
|
+
name: Optional[str],
|
|
3210
|
+
config: Dict[str, Any],
|
|
3211
|
+
description: Optional[str] = None,
|
|
3212
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
3213
|
+
label: Optional[str] = None,
|
|
3214
|
+
stage: str = "draft",
|
|
3215
|
+
notes: Optional[str] = None,
|
|
3216
|
+
links: Optional[List[Dict[str, Any]]] = None,
|
|
3217
|
+
) -> Tuple[Dict[str, Any], Dict[str, Any]]:
|
|
3218
|
+
raise NotImplementedError("Component methods not yet supported for async databases")
|
|
3219
|
+
|
|
3220
|
+
def get_config(
|
|
3221
|
+
self,
|
|
3222
|
+
component_id: str,
|
|
3223
|
+
version: Optional[int] = None,
|
|
3224
|
+
label: Optional[str] = None,
|
|
3225
|
+
) -> Optional[Dict[str, Any]]:
|
|
3226
|
+
raise NotImplementedError("Component methods not yet supported for async databases")
|
|
3227
|
+
|
|
3228
|
+
def upsert_config(
|
|
3229
|
+
self,
|
|
3230
|
+
component_id: str,
|
|
3231
|
+
config: Optional[Dict[str, Any]] = None,
|
|
3232
|
+
version: Optional[int] = None,
|
|
3233
|
+
label: Optional[str] = None,
|
|
3234
|
+
stage: Optional[str] = None,
|
|
3235
|
+
notes: Optional[str] = None,
|
|
3236
|
+
links: Optional[List[Dict[str, Any]]] = None,
|
|
3237
|
+
) -> Dict[str, Any]:
|
|
3238
|
+
raise NotImplementedError("Component methods not yet supported for async databases")
|
|
3239
|
+
|
|
3240
|
+
def delete_config(
|
|
3241
|
+
self,
|
|
3242
|
+
component_id: str,
|
|
3243
|
+
version: int,
|
|
3244
|
+
) -> bool:
|
|
3245
|
+
raise NotImplementedError("Component methods not yet supported for async databases")
|
|
3246
|
+
|
|
3247
|
+
def list_configs(
|
|
3248
|
+
self,
|
|
3249
|
+
component_id: str,
|
|
3250
|
+
include_config: bool = False,
|
|
3251
|
+
) -> List[Dict[str, Any]]:
|
|
3252
|
+
raise NotImplementedError("Component methods not yet supported for async databases")
|
|
3253
|
+
|
|
3254
|
+
def set_current_version(
|
|
3255
|
+
self,
|
|
3256
|
+
component_id: str,
|
|
3257
|
+
version: int,
|
|
3258
|
+
) -> bool:
|
|
3259
|
+
raise NotImplementedError("Component methods not yet supported for async databases")
|
|
3260
|
+
|
|
3261
|
+
def get_links(
|
|
3262
|
+
self,
|
|
3263
|
+
component_id: str,
|
|
3264
|
+
version: int,
|
|
3265
|
+
link_kind: Optional[str] = None,
|
|
3266
|
+
) -> List[Dict[str, Any]]:
|
|
3267
|
+
raise NotImplementedError("Component methods not yet supported for async databases")
|
|
3268
|
+
|
|
3269
|
+
def get_dependents(
|
|
3270
|
+
self,
|
|
3271
|
+
component_id: str,
|
|
3272
|
+
version: Optional[int] = None,
|
|
3273
|
+
) -> List[Dict[str, Any]]:
|
|
3274
|
+
raise NotImplementedError("Component methods not yet supported for async databases")
|
|
3275
|
+
|
|
3276
|
+
def load_component_graph(
|
|
3277
|
+
self,
|
|
3278
|
+
component_id: str,
|
|
3279
|
+
version: Optional[int] = None,
|
|
3280
|
+
label: Optional[str] = None,
|
|
3281
|
+
) -> Optional[Dict[str, Any]]:
|
|
3282
|
+
raise NotImplementedError("Component methods not yet supported for async databases")
|
agno/db/sqlite/schemas.py
CHANGED
|
@@ -162,6 +162,54 @@ VERSIONS_TABLE_SCHEMA = {
|
|
|
162
162
|
"updated_at": {"type": String, "nullable": True},
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
+
COMPONENTS_TABLE_SCHEMA = {
|
|
166
|
+
"component_id": {"type": String, "primary_key": True},
|
|
167
|
+
"component_type": {"type": String, "nullable": False, "index": True}, # agent|team|workflow
|
|
168
|
+
"name": {"type": String, "nullable": False, "index": True},
|
|
169
|
+
"description": {"type": String, "nullable": True},
|
|
170
|
+
"current_version": {"type": BigInteger, "nullable": True, "index": True},
|
|
171
|
+
"metadata": {"type": JSON, "nullable": True},
|
|
172
|
+
"created_at": {"type": BigInteger, "nullable": False, "index": True},
|
|
173
|
+
"updated_at": {"type": BigInteger, "nullable": True},
|
|
174
|
+
"deleted_at": {"type": BigInteger, "nullable": True},
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
COMPONENT_CONFIGS_TABLE_SCHEMA = {
|
|
178
|
+
"component_id": {"type": String, "nullable": False},
|
|
179
|
+
"version": {"type": BigInteger, "nullable": False},
|
|
180
|
+
"label": {"type": String, "nullable": True}, # stable|v1.2.0|pre-refactor
|
|
181
|
+
"stage": {"type": String, "nullable": False, "default": "draft", "index": True}, # draft|published
|
|
182
|
+
"config": {"type": JSON, "nullable": False},
|
|
183
|
+
"notes": {"type": String, "nullable": True},
|
|
184
|
+
"created_at": {"type": BigInteger, "nullable": False, "index": True},
|
|
185
|
+
"updated_at": {"type": BigInteger, "nullable": True},
|
|
186
|
+
"_unique_constraints": [
|
|
187
|
+
{
|
|
188
|
+
"name": "uq_config_component_version",
|
|
189
|
+
"columns": ["component_id", "version"],
|
|
190
|
+
},
|
|
191
|
+
],
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
COMPONENT_LINKS_TABLE_SCHEMA = {
|
|
195
|
+
"parent_component_id": {"type": String, "nullable": False},
|
|
196
|
+
"parent_version": {"type": BigInteger, "nullable": False},
|
|
197
|
+
"link_kind": {"type": String, "nullable": False, "index": True},
|
|
198
|
+
"link_key": {"type": String, "nullable": False},
|
|
199
|
+
"child_component_id": {"type": String, "nullable": False},
|
|
200
|
+
"child_version": {"type": BigInteger, "nullable": True},
|
|
201
|
+
"position": {"type": BigInteger, "nullable": False},
|
|
202
|
+
"meta": {"type": JSON, "nullable": True},
|
|
203
|
+
"created_at": {"type": BigInteger, "nullable": True, "index": True},
|
|
204
|
+
"updated_at": {"type": BigInteger, "nullable": True},
|
|
205
|
+
"_unique_constraints": [
|
|
206
|
+
{
|
|
207
|
+
"name": "uq_link_parent_kind_key",
|
|
208
|
+
"columns": ["parent_component_id", "parent_version", "link_kind", "link_key"],
|
|
209
|
+
},
|
|
210
|
+
],
|
|
211
|
+
}
|
|
212
|
+
|
|
165
213
|
LEARNINGS_TABLE_SCHEMA = {
|
|
166
214
|
"learning_id": {"type": String, "primary_key": True, "nullable": False},
|
|
167
215
|
"learning_type": {"type": String, "nullable": False, "index": True},
|
|
@@ -204,6 +252,9 @@ def get_table_schema_definition(table_type: str, traces_table_name: str = "agno_
|
|
|
204
252
|
"traces": TRACE_TABLE_SCHEMA,
|
|
205
253
|
"culture": CULTURAL_KNOWLEDGE_TABLE_SCHEMA,
|
|
206
254
|
"versions": VERSIONS_TABLE_SCHEMA,
|
|
255
|
+
"components": COMPONENTS_TABLE_SCHEMA,
|
|
256
|
+
"component_configs": COMPONENT_CONFIGS_TABLE_SCHEMA,
|
|
257
|
+
"component_links": COMPONENT_LINKS_TABLE_SCHEMA,
|
|
207
258
|
"learnings": LEARNINGS_TABLE_SCHEMA,
|
|
208
259
|
}
|
|
209
260
|
schema = schemas.get(table_type, {})
|