agno 2.3.22__py3-none-any.whl → 2.3.24__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 +28 -1
- agno/agent/remote.py +1 -1
- agno/db/mongo/mongo.py +9 -1
- agno/db/mysql/async_mysql.py +5 -7
- agno/db/mysql/mysql.py +5 -7
- agno/db/mysql/schemas.py +39 -21
- agno/db/postgres/async_postgres.py +10 -2
- agno/db/postgres/postgres.py +5 -7
- agno/db/postgres/schemas.py +39 -21
- agno/db/singlestore/schemas.py +41 -21
- agno/db/singlestore/singlestore.py +14 -3
- agno/db/sqlite/async_sqlite.py +7 -2
- agno/db/sqlite/schemas.py +36 -21
- agno/db/sqlite/sqlite.py +3 -7
- agno/knowledge/chunking/markdown.py +94 -8
- agno/knowledge/chunking/semantic.py +2 -2
- agno/knowledge/knowledge.py +215 -207
- agno/models/base.py +32 -8
- agno/models/google/gemini.py +27 -4
- agno/os/routers/agents/router.py +1 -1
- agno/os/routers/evals/evals.py +2 -2
- agno/os/routers/knowledge/knowledge.py +21 -5
- agno/os/routers/knowledge/schemas.py +1 -1
- agno/os/routers/memory/memory.py +4 -4
- agno/os/routers/session/session.py +2 -2
- agno/os/routers/teams/router.py +2 -2
- agno/os/routers/traces/traces.py +3 -3
- agno/os/routers/workflows/router.py +1 -1
- agno/os/schema.py +1 -1
- agno/os/utils.py +1 -1
- agno/remote/base.py +1 -1
- agno/team/remote.py +1 -1
- agno/team/team.py +24 -4
- agno/tools/brandfetch.py +27 -18
- agno/tools/browserbase.py +150 -13
- agno/tools/crawl4ai.py +3 -0
- agno/tools/file.py +14 -13
- agno/tools/function.py +15 -2
- agno/tools/mcp/mcp.py +1 -0
- agno/tools/mlx_transcribe.py +10 -7
- agno/tools/python.py +14 -6
- agno/tools/toolkit.py +122 -23
- agno/vectordb/cassandra/cassandra.py +1 -1
- agno/vectordb/chroma/chromadb.py +1 -1
- agno/vectordb/clickhouse/clickhousedb.py +1 -1
- agno/vectordb/couchbase/couchbase.py +1 -1
- agno/vectordb/milvus/milvus.py +1 -1
- agno/vectordb/mongodb/mongodb.py +13 -3
- agno/vectordb/pgvector/pgvector.py +1 -1
- agno/vectordb/pineconedb/pineconedb.py +2 -2
- agno/vectordb/qdrant/qdrant.py +1 -1
- agno/vectordb/redis/redisdb.py +2 -2
- agno/vectordb/singlestore/singlestore.py +1 -1
- agno/vectordb/surrealdb/surrealdb.py +2 -2
- agno/vectordb/weaviate/weaviate.py +1 -1
- agno/workflow/remote.py +1 -1
- agno/workflow/workflow.py +14 -0
- {agno-2.3.22.dist-info → agno-2.3.24.dist-info}/METADATA +1 -1
- {agno-2.3.22.dist-info → agno-2.3.24.dist-info}/RECORD +62 -62
- {agno-2.3.22.dist-info → agno-2.3.24.dist-info}/WHEEL +0 -0
- {agno-2.3.22.dist-info → agno-2.3.24.dist-info}/licenses/LICENSE +0 -0
- {agno-2.3.22.dist-info → agno-2.3.24.dist-info}/top_level.txt +0 -0
agno/agent/agent.py
CHANGED
|
@@ -61,6 +61,9 @@ from agno.run.agent import (
|
|
|
61
61
|
RunOutput,
|
|
62
62
|
RunOutputEvent,
|
|
63
63
|
)
|
|
64
|
+
from agno.run.cancel import (
|
|
65
|
+
acancel_run as acancel_run_global,
|
|
66
|
+
)
|
|
64
67
|
from agno.run.cancel import (
|
|
65
68
|
acleanup_run,
|
|
66
69
|
araise_if_cancelled,
|
|
@@ -2030,6 +2033,7 @@ class Agent:
|
|
|
2030
2033
|
run_response=run_response,
|
|
2031
2034
|
run_context=run_context,
|
|
2032
2035
|
session=agent_session,
|
|
2036
|
+
async_mode=True,
|
|
2033
2037
|
)
|
|
2034
2038
|
|
|
2035
2039
|
# 6. Prepare run messages
|
|
@@ -2377,6 +2381,7 @@ class Agent:
|
|
|
2377
2381
|
run_response=run_response,
|
|
2378
2382
|
run_context=run_context,
|
|
2379
2383
|
session=agent_session,
|
|
2384
|
+
async_mode=True,
|
|
2380
2385
|
)
|
|
2381
2386
|
|
|
2382
2387
|
# 6. Prepare run messages
|
|
@@ -3297,6 +3302,9 @@ class Agent:
|
|
|
3297
3302
|
tools=tools,
|
|
3298
3303
|
tool_choice=self.tool_choice,
|
|
3299
3304
|
tool_call_limit=self.tool_call_limit,
|
|
3305
|
+
run_response=run_response,
|
|
3306
|
+
send_media_to_model=self.send_media_to_model,
|
|
3307
|
+
compression_manager=self.compression_manager if self.compress_tool_results else None,
|
|
3300
3308
|
)
|
|
3301
3309
|
|
|
3302
3310
|
# Check for cancellation after model processing
|
|
@@ -3987,6 +3995,7 @@ class Agent:
|
|
|
3987
3995
|
run_response=run_response,
|
|
3988
3996
|
run_context=run_context,
|
|
3989
3997
|
session=agent_session,
|
|
3998
|
+
async_mode=True,
|
|
3990
3999
|
)
|
|
3991
4000
|
|
|
3992
4001
|
# 6. Prepare run messages
|
|
@@ -4009,6 +4018,9 @@ class Agent:
|
|
|
4009
4018
|
tools=_tools,
|
|
4010
4019
|
tool_choice=self.tool_choice,
|
|
4011
4020
|
tool_call_limit=self.tool_call_limit,
|
|
4021
|
+
run_response=run_response,
|
|
4022
|
+
send_media_to_model=self.send_media_to_model,
|
|
4023
|
+
compression_manager=self.compression_manager if self.compress_tool_results else None,
|
|
4012
4024
|
)
|
|
4013
4025
|
# Check for cancellation after model call
|
|
4014
4026
|
await araise_if_cancelled(run_response.run_id) # type: ignore
|
|
@@ -4293,6 +4305,7 @@ class Agent:
|
|
|
4293
4305
|
run_response=run_response,
|
|
4294
4306
|
run_context=run_context,
|
|
4295
4307
|
session=agent_session,
|
|
4308
|
+
async_mode=True,
|
|
4296
4309
|
)
|
|
4297
4310
|
|
|
4298
4311
|
# 6. Prepare run messages
|
|
@@ -6514,6 +6527,7 @@ class Agent:
|
|
|
6514
6527
|
run_response: RunOutput,
|
|
6515
6528
|
run_context: RunContext,
|
|
6516
6529
|
session: AgentSession,
|
|
6530
|
+
async_mode: bool = False,
|
|
6517
6531
|
) -> List[Union[Function, dict]]:
|
|
6518
6532
|
_function_names = []
|
|
6519
6533
|
_functions: List[Union[Function, dict]] = []
|
|
@@ -6544,7 +6558,8 @@ class Agent:
|
|
|
6544
6558
|
|
|
6545
6559
|
elif isinstance(tool, Toolkit):
|
|
6546
6560
|
# For each function in the toolkit and process entrypoint
|
|
6547
|
-
|
|
6561
|
+
toolkit_functions = tool.get_async_functions() if async_mode else tool.get_functions()
|
|
6562
|
+
for name, _func in toolkit_functions.items():
|
|
6548
6563
|
if name in _function_names:
|
|
6549
6564
|
continue
|
|
6550
6565
|
_function_names.append(name)
|
|
@@ -6774,6 +6789,18 @@ class Agent:
|
|
|
6774
6789
|
"""
|
|
6775
6790
|
return cancel_run_global(run_id)
|
|
6776
6791
|
|
|
6792
|
+
@staticmethod
|
|
6793
|
+
async def acancel_run(run_id: str) -> bool:
|
|
6794
|
+
"""Cancel a running agent execution (async version).
|
|
6795
|
+
|
|
6796
|
+
Args:
|
|
6797
|
+
run_id (str): The run_id to cancel.
|
|
6798
|
+
|
|
6799
|
+
Returns:
|
|
6800
|
+
bool: True if the run was found and marked for cancellation, False otherwise.
|
|
6801
|
+
"""
|
|
6802
|
+
return await acancel_run_global(run_id)
|
|
6803
|
+
|
|
6777
6804
|
# -*- Session Database Functions
|
|
6778
6805
|
def _read_session(
|
|
6779
6806
|
self, session_id: str, session_type: SessionType = SessionType.AGENT
|
agno/agent/remote.py
CHANGED
|
@@ -488,7 +488,7 @@ class RemoteAgent(BaseRemote):
|
|
|
488
488
|
else:
|
|
489
489
|
raise ValueError("No client available")
|
|
490
490
|
|
|
491
|
-
async def
|
|
491
|
+
async def acancel_run(self, run_id: str, auth_token: Optional[str] = None) -> bool:
|
|
492
492
|
"""Cancel a running agent execution.
|
|
493
493
|
|
|
494
494
|
Args:
|
agno/db/mongo/mongo.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import time
|
|
2
2
|
from datetime import date, datetime, timedelta, timezone
|
|
3
|
+
from importlib import metadata
|
|
3
4
|
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union
|
|
4
5
|
from uuid import uuid4
|
|
5
6
|
|
|
@@ -31,10 +32,13 @@ try:
|
|
|
31
32
|
from pymongo import MongoClient, ReturnDocument
|
|
32
33
|
from pymongo.collection import Collection
|
|
33
34
|
from pymongo.database import Database
|
|
35
|
+
from pymongo.driver_info import DriverInfo
|
|
34
36
|
from pymongo.errors import OperationFailure
|
|
35
37
|
except ImportError:
|
|
36
38
|
raise ImportError("`pymongo` not installed. Please install it using `pip install pymongo`")
|
|
37
39
|
|
|
40
|
+
DRIVER_METADATA = DriverInfo(name="Agno", version=metadata.version("agno"))
|
|
41
|
+
|
|
38
42
|
|
|
39
43
|
class MongoDb(BaseDb):
|
|
40
44
|
def __init__(
|
|
@@ -92,10 +96,14 @@ class MongoDb(BaseDb):
|
|
|
92
96
|
|
|
93
97
|
_client: Optional[MongoClient] = db_client
|
|
94
98
|
if _client is None and db_url is not None:
|
|
95
|
-
_client = MongoClient(db_url)
|
|
99
|
+
_client = MongoClient(db_url, driver=DRIVER_METADATA)
|
|
96
100
|
if _client is None:
|
|
97
101
|
raise ValueError("One of db_url or db_client must be provided")
|
|
98
102
|
|
|
103
|
+
# append_metadata was added in PyMongo 4.14.0, but is a valid database name on earlier versions
|
|
104
|
+
if callable(_client.append_metadata):
|
|
105
|
+
_client.append_metadata(DRIVER_METADATA)
|
|
106
|
+
|
|
99
107
|
self.db_url: Optional[str] = db_url
|
|
100
108
|
self.db_client: MongoClient = _client
|
|
101
109
|
|
agno/db/mysql/async_mysql.py
CHANGED
|
@@ -158,7 +158,10 @@ class AsyncMySQLDb(AsyncBaseDb):
|
|
|
158
158
|
Table: SQLAlchemy Table object
|
|
159
159
|
"""
|
|
160
160
|
try:
|
|
161
|
-
|
|
161
|
+
# Pass traces_table_name and db_schema for spans table foreign key resolution
|
|
162
|
+
table_schema = get_table_schema_definition(
|
|
163
|
+
table_type, traces_table_name=self.trace_table_name, db_schema=self.db_schema
|
|
164
|
+
).copy()
|
|
162
165
|
|
|
163
166
|
log_debug(f"Creating table {self.db_schema}.{table_name} with schema: {table_schema}")
|
|
164
167
|
|
|
@@ -183,12 +186,7 @@ class AsyncMySQLDb(AsyncBaseDb):
|
|
|
183
186
|
|
|
184
187
|
# Handle foreign key constraint
|
|
185
188
|
if "foreign_key" in col_config:
|
|
186
|
-
|
|
187
|
-
# For spans table, dynamically replace the traces table reference
|
|
188
|
-
# with the actual trace table name configured for this db instance
|
|
189
|
-
if table_type == "spans" and "trace_id" in fk_ref:
|
|
190
|
-
fk_ref = f"{self.db_schema}.{self.trace_table_name}.trace_id"
|
|
191
|
-
column_args.append(ForeignKey(fk_ref))
|
|
189
|
+
column_args.append(ForeignKey(col_config["foreign_key"]))
|
|
192
190
|
|
|
193
191
|
columns.append(Column(*column_args, **column_kwargs)) # type: ignore
|
|
194
192
|
|
agno/db/mysql/mysql.py
CHANGED
|
@@ -155,7 +155,10 @@ class MySQLDb(BaseDb):
|
|
|
155
155
|
Table: SQLAlchemy Table object
|
|
156
156
|
"""
|
|
157
157
|
try:
|
|
158
|
-
|
|
158
|
+
# Pass traces_table_name and db_schema for spans table foreign key resolution
|
|
159
|
+
table_schema = get_table_schema_definition(
|
|
160
|
+
table_type, traces_table_name=self.trace_table_name, db_schema=self.db_schema
|
|
161
|
+
).copy()
|
|
159
162
|
|
|
160
163
|
columns: List[Column] = []
|
|
161
164
|
indexes: List[str] = []
|
|
@@ -178,12 +181,7 @@ class MySQLDb(BaseDb):
|
|
|
178
181
|
|
|
179
182
|
# Handle foreign key constraint
|
|
180
183
|
if "foreign_key" in col_config:
|
|
181
|
-
|
|
182
|
-
# For spans table, dynamically replace the traces table reference
|
|
183
|
-
# with the actual trace table name configured for this db instance
|
|
184
|
-
if table_type == "spans" and "trace_id" in fk_ref:
|
|
185
|
-
fk_ref = f"{self.db_schema}.{self.trace_table_name}.trace_id"
|
|
186
|
-
column_args.append(ForeignKey(fk_ref))
|
|
184
|
+
column_args.append(ForeignKey(col_config["foreign_key"]))
|
|
187
185
|
|
|
188
186
|
columns.append(Column(*column_args, **column_kwargs)) # type: ignore
|
|
189
187
|
|
agno/db/mysql/schemas.py
CHANGED
|
@@ -136,37 +136,56 @@ TRACE_TABLE_SCHEMA = {
|
|
|
136
136
|
"created_at": {"type": lambda: String(128), "nullable": False, "index": True}, # ISO 8601 datetime string
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
SPAN_TABLE_SCHEMA = {
|
|
140
|
-
"span_id": {"type": lambda: String(128), "primary_key": True, "nullable": False},
|
|
141
|
-
"trace_id": {
|
|
142
|
-
"type": lambda: String(128),
|
|
143
|
-
"nullable": False,
|
|
144
|
-
"index": True,
|
|
145
|
-
"foreign_key": "agno_traces.trace_id", # Foreign key to traces table
|
|
146
|
-
},
|
|
147
|
-
"parent_span_id": {"type": lambda: String(128), "nullable": True, "index": True},
|
|
148
|
-
"name": {"type": lambda: String(255), "nullable": False},
|
|
149
|
-
"span_kind": {"type": lambda: String(50), "nullable": False},
|
|
150
|
-
"status_code": {"type": lambda: String(50), "nullable": False},
|
|
151
|
-
"status_message": {"type": Text, "nullable": True},
|
|
152
|
-
"start_time": {"type": lambda: String(128), "nullable": False, "index": True}, # ISO 8601 datetime string
|
|
153
|
-
"end_time": {"type": lambda: String(128), "nullable": False}, # ISO 8601 datetime string
|
|
154
|
-
"duration_ms": {"type": BigInteger, "nullable": False},
|
|
155
|
-
"attributes": {"type": JSON, "nullable": True},
|
|
156
|
-
"created_at": {"type": lambda: String(128), "nullable": False, "index": True}, # ISO 8601 datetime string
|
|
157
|
-
}
|
|
158
139
|
|
|
140
|
+
def _get_span_table_schema(traces_table_name: str = "agno_traces", db_schema: str = "agno") -> dict[str, Any]:
|
|
141
|
+
"""Get the span table schema with the correct foreign key reference.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
traces_table_name: The name of the traces table to reference in the foreign key.
|
|
145
|
+
db_schema: The database schema name.
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
The span table schema dictionary.
|
|
149
|
+
"""
|
|
150
|
+
return {
|
|
151
|
+
"span_id": {"type": lambda: String(128), "primary_key": True, "nullable": False},
|
|
152
|
+
"trace_id": {
|
|
153
|
+
"type": lambda: String(128),
|
|
154
|
+
"nullable": False,
|
|
155
|
+
"index": True,
|
|
156
|
+
"foreign_key": f"{db_schema}.{traces_table_name}.trace_id",
|
|
157
|
+
},
|
|
158
|
+
"parent_span_id": {"type": lambda: String(128), "nullable": True, "index": True},
|
|
159
|
+
"name": {"type": lambda: String(255), "nullable": False},
|
|
160
|
+
"span_kind": {"type": lambda: String(50), "nullable": False},
|
|
161
|
+
"status_code": {"type": lambda: String(50), "nullable": False},
|
|
162
|
+
"status_message": {"type": Text, "nullable": True},
|
|
163
|
+
"start_time": {"type": lambda: String(128), "nullable": False, "index": True}, # ISO 8601 datetime string
|
|
164
|
+
"end_time": {"type": lambda: String(128), "nullable": False}, # ISO 8601 datetime string
|
|
165
|
+
"duration_ms": {"type": BigInteger, "nullable": False},
|
|
166
|
+
"attributes": {"type": JSON, "nullable": True},
|
|
167
|
+
"created_at": {"type": lambda: String(128), "nullable": False, "index": True}, # ISO 8601 datetime string
|
|
168
|
+
}
|
|
159
169
|
|
|
160
|
-
|
|
170
|
+
|
|
171
|
+
def get_table_schema_definition(
|
|
172
|
+
table_type: str, traces_table_name: str = "agno_traces", db_schema: str = "agno"
|
|
173
|
+
) -> dict[str, Any]:
|
|
161
174
|
"""
|
|
162
175
|
Get the expected schema definition for the given table.
|
|
163
176
|
|
|
164
177
|
Args:
|
|
165
178
|
table_type (str): The type of table to get the schema for.
|
|
179
|
+
traces_table_name (str): The name of the traces table (used for spans foreign key).
|
|
180
|
+
db_schema (str): The database schema name (used for spans foreign key).
|
|
166
181
|
|
|
167
182
|
Returns:
|
|
168
183
|
Dict[str, Any]: Dictionary containing column definitions for the table
|
|
169
184
|
"""
|
|
185
|
+
# Handle spans table specially to resolve the foreign key reference
|
|
186
|
+
if table_type == "spans":
|
|
187
|
+
return _get_span_table_schema(traces_table_name, db_schema)
|
|
188
|
+
|
|
170
189
|
schemas = {
|
|
171
190
|
"sessions": SESSION_TABLE_SCHEMA,
|
|
172
191
|
"evals": EVAL_TABLE_SCHEMA,
|
|
@@ -176,7 +195,6 @@ def get_table_schema_definition(table_type: str) -> dict[str, Any]:
|
|
|
176
195
|
"culture": CULTURAL_KNOWLEDGE_TABLE_SCHEMA,
|
|
177
196
|
"versions": VERSIONS_TABLE_SCHEMA,
|
|
178
197
|
"traces": TRACE_TABLE_SCHEMA,
|
|
179
|
-
"spans": SPAN_TABLE_SCHEMA,
|
|
180
198
|
}
|
|
181
199
|
|
|
182
200
|
schema = schemas.get(table_type, {})
|
|
@@ -31,7 +31,7 @@ from agno.utils.log import log_debug, log_error, log_info, log_warning
|
|
|
31
31
|
from agno.utils.string import sanitize_postgres_string, sanitize_postgres_strings
|
|
32
32
|
|
|
33
33
|
try:
|
|
34
|
-
from sqlalchemy import Index, String, Table, UniqueConstraint, and_, case, func, or_, update
|
|
34
|
+
from sqlalchemy import ForeignKey, Index, String, Table, UniqueConstraint, and_, case, func, or_, update
|
|
35
35
|
from sqlalchemy.dialects import postgresql
|
|
36
36
|
from sqlalchemy.dialects.postgresql import TIMESTAMP
|
|
37
37
|
from sqlalchemy.exc import ProgrammingError
|
|
@@ -192,7 +192,10 @@ class AsyncPostgresDb(AsyncBaseDb):
|
|
|
192
192
|
Table: SQLAlchemy Table object
|
|
193
193
|
"""
|
|
194
194
|
try:
|
|
195
|
-
|
|
195
|
+
# Pass traces_table_name and db_schema for spans table foreign key resolution
|
|
196
|
+
table_schema = get_table_schema_definition(
|
|
197
|
+
table_type, traces_table_name=self.trace_table_name, db_schema=self.db_schema
|
|
198
|
+
).copy()
|
|
196
199
|
|
|
197
200
|
columns: List[Column] = []
|
|
198
201
|
indexes: List[str] = []
|
|
@@ -212,6 +215,11 @@ class AsyncPostgresDb(AsyncBaseDb):
|
|
|
212
215
|
if col_config.get("unique", False):
|
|
213
216
|
column_kwargs["unique"] = True
|
|
214
217
|
unique_constraints.append(col_name)
|
|
218
|
+
|
|
219
|
+
# Handle foreign key constraint
|
|
220
|
+
if "foreign_key" in col_config:
|
|
221
|
+
column_args.append(ForeignKey(col_config["foreign_key"]))
|
|
222
|
+
|
|
215
223
|
columns.append(Column(*column_args, **column_kwargs)) # type: ignore
|
|
216
224
|
|
|
217
225
|
# Create the table object
|
agno/db/postgres/postgres.py
CHANGED
|
@@ -176,7 +176,10 @@ class PostgresDb(BaseDb):
|
|
|
176
176
|
Table: SQLAlchemy Table object
|
|
177
177
|
"""
|
|
178
178
|
try:
|
|
179
|
-
|
|
179
|
+
# Pass traces_table_name and db_schema for spans table foreign key resolution
|
|
180
|
+
table_schema = get_table_schema_definition(
|
|
181
|
+
table_type, traces_table_name=self.trace_table_name, db_schema=self.db_schema
|
|
182
|
+
).copy()
|
|
180
183
|
|
|
181
184
|
columns: List[Column] = []
|
|
182
185
|
indexes: List[str] = []
|
|
@@ -199,12 +202,7 @@ class PostgresDb(BaseDb):
|
|
|
199
202
|
|
|
200
203
|
# Handle foreign key constraint
|
|
201
204
|
if "foreign_key" in col_config:
|
|
202
|
-
|
|
203
|
-
# For spans table, dynamically replace the traces table reference
|
|
204
|
-
# with the actual trace table name configured for this db instance
|
|
205
|
-
if table_type == "spans" and "trace_id" in fk_ref:
|
|
206
|
-
fk_ref = f"{self.db_schema}.{self.trace_table_name}.trace_id"
|
|
207
|
-
column_args.append(ForeignKey(fk_ref))
|
|
205
|
+
column_args.append(ForeignKey(col_config["foreign_key"]))
|
|
208
206
|
|
|
209
207
|
columns.append(Column(*column_args, **column_kwargs)) # type: ignore
|
|
210
208
|
|
agno/db/postgres/schemas.py
CHANGED
|
@@ -137,37 +137,56 @@ TRACE_TABLE_SCHEMA = {
|
|
|
137
137
|
"created_at": {"type": String, "nullable": False, "index": True}, # ISO 8601 datetime string
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
SPAN_TABLE_SCHEMA = {
|
|
141
|
-
"span_id": {"type": String, "primary_key": True, "nullable": False},
|
|
142
|
-
"trace_id": {
|
|
143
|
-
"type": String,
|
|
144
|
-
"nullable": False,
|
|
145
|
-
"index": True,
|
|
146
|
-
"foreign_key": "agno_traces.trace_id", # Foreign key to traces table
|
|
147
|
-
},
|
|
148
|
-
"parent_span_id": {"type": String, "nullable": True, "index": True},
|
|
149
|
-
"name": {"type": String, "nullable": False},
|
|
150
|
-
"span_kind": {"type": String, "nullable": False},
|
|
151
|
-
"status_code": {"type": String, "nullable": False},
|
|
152
|
-
"status_message": {"type": Text, "nullable": True},
|
|
153
|
-
"start_time": {"type": String, "nullable": False, "index": True}, # ISO 8601 datetime string
|
|
154
|
-
"end_time": {"type": String, "nullable": False}, # ISO 8601 datetime string
|
|
155
|
-
"duration_ms": {"type": BigInteger, "nullable": False},
|
|
156
|
-
"attributes": {"type": JSONB, "nullable": True},
|
|
157
|
-
"created_at": {"type": String, "nullable": False, "index": True}, # ISO 8601 datetime string
|
|
158
|
-
}
|
|
159
140
|
|
|
141
|
+
def _get_span_table_schema(traces_table_name: str = "agno_traces", db_schema: str = "agno") -> dict[str, Any]:
|
|
142
|
+
"""Get the span table schema with the correct foreign key reference.
|
|
143
|
+
|
|
144
|
+
Args:
|
|
145
|
+
traces_table_name: The name of the traces table to reference in the foreign key.
|
|
146
|
+
db_schema: The database schema name.
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
The span table schema dictionary.
|
|
150
|
+
"""
|
|
151
|
+
return {
|
|
152
|
+
"span_id": {"type": String, "primary_key": True, "nullable": False},
|
|
153
|
+
"trace_id": {
|
|
154
|
+
"type": String,
|
|
155
|
+
"nullable": False,
|
|
156
|
+
"index": True,
|
|
157
|
+
"foreign_key": f"{db_schema}.{traces_table_name}.trace_id",
|
|
158
|
+
},
|
|
159
|
+
"parent_span_id": {"type": String, "nullable": True, "index": True},
|
|
160
|
+
"name": {"type": String, "nullable": False},
|
|
161
|
+
"span_kind": {"type": String, "nullable": False},
|
|
162
|
+
"status_code": {"type": String, "nullable": False},
|
|
163
|
+
"status_message": {"type": Text, "nullable": True},
|
|
164
|
+
"start_time": {"type": String, "nullable": False, "index": True}, # ISO 8601 datetime string
|
|
165
|
+
"end_time": {"type": String, "nullable": False}, # ISO 8601 datetime string
|
|
166
|
+
"duration_ms": {"type": BigInteger, "nullable": False},
|
|
167
|
+
"attributes": {"type": JSONB, "nullable": True},
|
|
168
|
+
"created_at": {"type": String, "nullable": False, "index": True}, # ISO 8601 datetime string
|
|
169
|
+
}
|
|
160
170
|
|
|
161
|
-
|
|
171
|
+
|
|
172
|
+
def get_table_schema_definition(
|
|
173
|
+
table_type: str, traces_table_name: str = "agno_traces", db_schema: str = "agno"
|
|
174
|
+
) -> dict[str, Any]:
|
|
162
175
|
"""
|
|
163
176
|
Get the expected schema definition for the given table.
|
|
164
177
|
|
|
165
178
|
Args:
|
|
166
179
|
table_type (str): The type of table to get the schema for.
|
|
180
|
+
traces_table_name (str): The name of the traces table (used for spans foreign key).
|
|
181
|
+
db_schema (str): The database schema name (used for spans foreign key).
|
|
167
182
|
|
|
168
183
|
Returns:
|
|
169
184
|
Dict[str, Any]: Dictionary containing column definitions for the table
|
|
170
185
|
"""
|
|
186
|
+
# Handle spans table specially to resolve the foreign key reference
|
|
187
|
+
if table_type == "spans":
|
|
188
|
+
return _get_span_table_schema(traces_table_name, db_schema)
|
|
189
|
+
|
|
171
190
|
schemas = {
|
|
172
191
|
"sessions": SESSION_TABLE_SCHEMA,
|
|
173
192
|
"evals": EVAL_TABLE_SCHEMA,
|
|
@@ -177,7 +196,6 @@ def get_table_schema_definition(table_type: str) -> dict[str, Any]:
|
|
|
177
196
|
"culture": CULTURAL_KNOWLEDGE_TABLE_SCHEMA,
|
|
178
197
|
"versions": VERSIONS_TABLE_SCHEMA,
|
|
179
198
|
"traces": TRACE_TABLE_SCHEMA,
|
|
180
|
-
"spans": SPAN_TABLE_SCHEMA,
|
|
181
199
|
}
|
|
182
200
|
|
|
183
201
|
schema = schemas.get(table_type, {})
|
agno/db/singlestore/schemas.py
CHANGED
|
@@ -131,35 +131,56 @@ TRACE_TABLE_SCHEMA = {
|
|
|
131
131
|
"created_at": {"type": lambda: String(64), "nullable": False, "index": True}, # ISO 8601 datetime string
|
|
132
132
|
}
|
|
133
133
|
|
|
134
|
-
SPAN_TABLE_SCHEMA = {
|
|
135
|
-
"span_id": {"type": lambda: String(128), "primary_key": True, "nullable": False},
|
|
136
|
-
"trace_id": {
|
|
137
|
-
"type": lambda: String(128),
|
|
138
|
-
"nullable": False,
|
|
139
|
-
"index": True,
|
|
140
|
-
"foreign_key": "agno_traces.trace_id", # Foreign key to traces table
|
|
141
|
-
},
|
|
142
|
-
"parent_span_id": {"type": lambda: String(128), "nullable": True, "index": True},
|
|
143
|
-
"name": {"type": lambda: String(512), "nullable": False},
|
|
144
|
-
"span_kind": {"type": lambda: String(50), "nullable": False},
|
|
145
|
-
"status_code": {"type": lambda: String(20), "nullable": False},
|
|
146
|
-
"status_message": {"type": Text, "nullable": True},
|
|
147
|
-
"start_time": {"type": lambda: String(64), "nullable": False, "index": True}, # ISO 8601 datetime string
|
|
148
|
-
"end_time": {"type": lambda: String(64), "nullable": False}, # ISO 8601 datetime string
|
|
149
|
-
"duration_ms": {"type": BigInteger, "nullable": False},
|
|
150
|
-
"attributes": {"type": JSON, "nullable": True},
|
|
151
|
-
"created_at": {"type": lambda: String(64), "nullable": False, "index": True}, # ISO 8601 datetime string
|
|
152
|
-
}
|
|
153
134
|
|
|
135
|
+
def _get_span_table_schema(traces_table_name: str = "agno_traces", db_schema: str = "agno") -> dict[str, Any]:
|
|
136
|
+
"""Get the span table schema with the correct foreign key reference.
|
|
137
|
+
|
|
138
|
+
Args:
|
|
139
|
+
traces_table_name: The name of the traces table to reference in the foreign key.
|
|
140
|
+
db_schema: The database schema name.
|
|
141
|
+
|
|
142
|
+
Returns:
|
|
143
|
+
The span table schema dictionary.
|
|
144
|
+
"""
|
|
145
|
+
return {
|
|
146
|
+
"span_id": {"type": lambda: String(128), "primary_key": True, "nullable": False},
|
|
147
|
+
"trace_id": {
|
|
148
|
+
"type": lambda: String(128),
|
|
149
|
+
"nullable": False,
|
|
150
|
+
"index": True,
|
|
151
|
+
"foreign_key": f"{db_schema}.{traces_table_name}.trace_id",
|
|
152
|
+
},
|
|
153
|
+
"parent_span_id": {"type": lambda: String(128), "nullable": True, "index": True},
|
|
154
|
+
"name": {"type": lambda: String(512), "nullable": False},
|
|
155
|
+
"span_kind": {"type": lambda: String(50), "nullable": False},
|
|
156
|
+
"status_code": {"type": lambda: String(20), "nullable": False},
|
|
157
|
+
"status_message": {"type": Text, "nullable": True},
|
|
158
|
+
"start_time": {"type": lambda: String(64), "nullable": False, "index": True}, # ISO 8601 datetime string
|
|
159
|
+
"end_time": {"type": lambda: String(64), "nullable": False}, # ISO 8601 datetime string
|
|
160
|
+
"duration_ms": {"type": BigInteger, "nullable": False},
|
|
161
|
+
"attributes": {"type": JSON, "nullable": True},
|
|
162
|
+
"created_at": {"type": lambda: String(64), "nullable": False, "index": True}, # ISO 8601 datetime string
|
|
163
|
+
}
|
|
154
164
|
|
|
155
|
-
|
|
165
|
+
|
|
166
|
+
def get_table_schema_definition(
|
|
167
|
+
table_type: str, traces_table_name: str = "agno_traces", db_schema: str = "agno"
|
|
168
|
+
) -> dict[str, Any]:
|
|
156
169
|
"""
|
|
157
170
|
Get the expected schema definition for the given table.
|
|
171
|
+
|
|
158
172
|
Args:
|
|
159
173
|
table_type (str): The type of table to get the schema for.
|
|
174
|
+
traces_table_name (str): The name of the traces table (used for spans foreign key).
|
|
175
|
+
db_schema (str): The database schema name (used for spans foreign key).
|
|
176
|
+
|
|
160
177
|
Returns:
|
|
161
178
|
Dict[str, Any]: Dictionary containing column definitions for the table
|
|
162
179
|
"""
|
|
180
|
+
# Handle spans table specially to resolve the foreign key reference
|
|
181
|
+
if table_type == "spans":
|
|
182
|
+
return _get_span_table_schema(traces_table_name, db_schema)
|
|
183
|
+
|
|
163
184
|
schemas = {
|
|
164
185
|
"sessions": SESSION_TABLE_SCHEMA,
|
|
165
186
|
"evals": EVAL_TABLE_SCHEMA,
|
|
@@ -169,7 +190,6 @@ def get_table_schema_definition(table_type: str) -> dict[str, Any]:
|
|
|
169
190
|
"culture": CULTURAL_KNOWLEDGE_TABLE_SCHEMA,
|
|
170
191
|
"versions": VERSIONS_TABLE_SCHEMA,
|
|
171
192
|
"traces": TRACE_TABLE_SCHEMA,
|
|
172
|
-
"spans": SPAN_TABLE_SCHEMA,
|
|
173
193
|
}
|
|
174
194
|
schema = schemas.get(table_type, {})
|
|
175
195
|
|
|
@@ -31,7 +31,7 @@ from agno.utils.log import log_debug, log_error, log_info, log_warning
|
|
|
31
31
|
from agno.utils.string import generate_id
|
|
32
32
|
|
|
33
33
|
try:
|
|
34
|
-
from sqlalchemy import Index, UniqueConstraint, and_, func, select, update
|
|
34
|
+
from sqlalchemy import ForeignKey, Index, UniqueConstraint, and_, func, select, update
|
|
35
35
|
from sqlalchemy.dialects import mysql
|
|
36
36
|
from sqlalchemy.engine import Engine, create_engine
|
|
37
37
|
from sqlalchemy.orm import scoped_session, sessionmaker
|
|
@@ -151,7 +151,10 @@ class SingleStoreDb(BaseDb):
|
|
|
151
151
|
Table: SQLAlchemy Table object with column definitions
|
|
152
152
|
"""
|
|
153
153
|
try:
|
|
154
|
-
|
|
154
|
+
# Pass traces_table_name and db_schema for spans table foreign key resolution
|
|
155
|
+
table_schema = get_table_schema_definition(
|
|
156
|
+
table_type, traces_table_name=self.trace_table_name, db_schema=self.db_schema or "agno"
|
|
157
|
+
)
|
|
155
158
|
|
|
156
159
|
columns: List[Column] = []
|
|
157
160
|
# Get the columns from the table schema
|
|
@@ -207,7 +210,10 @@ class SingleStoreDb(BaseDb):
|
|
|
207
210
|
"""
|
|
208
211
|
table_ref = f"{self.db_schema}.{table_name}" if self.db_schema else table_name
|
|
209
212
|
try:
|
|
210
|
-
|
|
213
|
+
# Pass traces_table_name and db_schema for spans table foreign key resolution
|
|
214
|
+
table_schema = get_table_schema_definition(
|
|
215
|
+
table_type, traces_table_name=self.trace_table_name, db_schema=self.db_schema or "agno"
|
|
216
|
+
).copy()
|
|
211
217
|
|
|
212
218
|
columns: List[Column] = []
|
|
213
219
|
indexes: List[str] = []
|
|
@@ -227,6 +233,11 @@ class SingleStoreDb(BaseDb):
|
|
|
227
233
|
if col_config.get("unique", False):
|
|
228
234
|
column_kwargs["unique"] = True
|
|
229
235
|
unique_constraints.append(col_name)
|
|
236
|
+
|
|
237
|
+
# Handle foreign key constraint
|
|
238
|
+
if "foreign_key" in col_config:
|
|
239
|
+
column_args.append(ForeignKey(col_config["foreign_key"]))
|
|
240
|
+
|
|
230
241
|
columns.append(Column(*column_args, **column_kwargs))
|
|
231
242
|
|
|
232
243
|
# Create the table object
|
agno/db/sqlite/async_sqlite.py
CHANGED
|
@@ -31,7 +31,7 @@ from agno.utils.log import log_debug, log_error, log_info, log_warning
|
|
|
31
31
|
from agno.utils.string import generate_id
|
|
32
32
|
|
|
33
33
|
try:
|
|
34
|
-
from sqlalchemy import Column, MetaData, String, Table, func, select, text
|
|
34
|
+
from sqlalchemy import Column, ForeignKey, MetaData, String, Table, func, select, text
|
|
35
35
|
from sqlalchemy.dialects import sqlite
|
|
36
36
|
from sqlalchemy.ext.asyncio import AsyncEngine, async_sessionmaker, create_async_engine
|
|
37
37
|
from sqlalchemy.schema import Index, UniqueConstraint
|
|
@@ -174,7 +174,8 @@ class AsyncSqliteDb(AsyncBaseDb):
|
|
|
174
174
|
Table: SQLAlchemy Table object
|
|
175
175
|
"""
|
|
176
176
|
try:
|
|
177
|
-
|
|
177
|
+
# Pass traces_table_name for spans table foreign key resolution
|
|
178
|
+
table_schema = get_table_schema_definition(table_type, traces_table_name=self.trace_table_name).copy()
|
|
178
179
|
|
|
179
180
|
columns: List[Column] = []
|
|
180
181
|
indexes: List[str] = []
|
|
@@ -196,6 +197,10 @@ class AsyncSqliteDb(AsyncBaseDb):
|
|
|
196
197
|
column_kwargs["unique"] = True
|
|
197
198
|
unique_constraints.append(col_name)
|
|
198
199
|
|
|
200
|
+
# Handle foreign key constraint
|
|
201
|
+
if "foreign_key" in col_config:
|
|
202
|
+
column_args.append(ForeignKey(col_config["foreign_key"]))
|
|
203
|
+
|
|
199
204
|
columns.append(Column(*column_args, **column_kwargs)) # type: ignore
|
|
200
205
|
|
|
201
206
|
# Create the table object
|