agno 2.2.1__py3-none-any.whl → 2.2.3__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 +735 -574
- agno/culture/manager.py +22 -24
- agno/db/async_postgres/__init__.py +1 -1
- agno/db/dynamo/dynamo.py +0 -2
- agno/db/firestore/firestore.py +0 -2
- agno/db/gcs_json/gcs_json_db.py +0 -4
- agno/db/gcs_json/utils.py +0 -24
- agno/db/in_memory/in_memory_db.py +0 -3
- agno/db/json/json_db.py +4 -10
- agno/db/json/utils.py +0 -24
- agno/db/mongo/__init__.py +15 -1
- agno/db/mongo/async_mongo.py +1999 -0
- agno/db/mongo/mongo.py +0 -2
- agno/db/mysql/mysql.py +0 -3
- agno/db/postgres/__init__.py +1 -1
- agno/db/{async_postgres → postgres}/async_postgres.py +19 -22
- agno/db/postgres/postgres.py +7 -10
- agno/db/postgres/utils.py +106 -2
- agno/db/redis/redis.py +0 -2
- agno/db/singlestore/singlestore.py +0 -3
- agno/db/sqlite/__init__.py +2 -1
- agno/db/sqlite/async_sqlite.py +2269 -0
- agno/db/sqlite/sqlite.py +0 -2
- agno/db/sqlite/utils.py +96 -0
- agno/db/surrealdb/surrealdb.py +0 -6
- agno/knowledge/knowledge.py +3 -3
- agno/knowledge/reader/reader_factory.py +16 -0
- agno/knowledge/reader/tavily_reader.py +194 -0
- agno/memory/manager.py +28 -25
- agno/models/anthropic/claude.py +63 -6
- agno/models/base.py +251 -32
- agno/models/response.py +69 -0
- agno/os/router.py +7 -5
- agno/os/routers/memory/memory.py +2 -1
- agno/os/routers/memory/schemas.py +5 -2
- agno/os/schema.py +25 -20
- agno/os/utils.py +9 -2
- agno/run/agent.py +23 -30
- agno/run/base.py +17 -1
- agno/run/team.py +23 -29
- agno/run/workflow.py +17 -12
- agno/session/agent.py +3 -0
- agno/session/summary.py +4 -1
- agno/session/team.py +1 -1
- agno/team/team.py +599 -367
- agno/tools/dalle.py +2 -4
- agno/tools/eleven_labs.py +23 -25
- agno/tools/function.py +40 -0
- agno/tools/mcp/__init__.py +10 -0
- agno/tools/mcp/mcp.py +324 -0
- agno/tools/mcp/multi_mcp.py +347 -0
- agno/tools/mcp/params.py +24 -0
- agno/tools/slack.py +18 -3
- agno/tools/tavily.py +146 -0
- agno/utils/agent.py +366 -1
- agno/utils/mcp.py +92 -2
- agno/utils/media.py +166 -1
- agno/utils/print_response/workflow.py +17 -1
- agno/utils/team.py +89 -1
- agno/workflow/step.py +0 -1
- agno/workflow/types.py +10 -15
- {agno-2.2.1.dist-info → agno-2.2.3.dist-info}/METADATA +28 -25
- {agno-2.2.1.dist-info → agno-2.2.3.dist-info}/RECORD +66 -62
- agno/db/async_postgres/schemas.py +0 -139
- agno/db/async_postgres/utils.py +0 -347
- agno/tools/mcp.py +0 -679
- {agno-2.2.1.dist-info → agno-2.2.3.dist-info}/WHEEL +0 -0
- {agno-2.2.1.dist-info → agno-2.2.3.dist-info}/licenses/LICENSE +0 -0
- {agno-2.2.1.dist-info → agno-2.2.3.dist-info}/top_level.txt +0 -0
agno/db/mongo/mongo.py
CHANGED
|
@@ -291,8 +291,6 @@ class MongoDb(BaseDb):
|
|
|
291
291
|
query = {"session_id": session_id}
|
|
292
292
|
if user_id is not None:
|
|
293
293
|
query["user_id"] = user_id
|
|
294
|
-
if session_type is not None:
|
|
295
|
-
query["session_type"] = session_type
|
|
296
294
|
|
|
297
295
|
result = collection.find_one(query)
|
|
298
296
|
if result is None:
|
agno/db/mysql/mysql.py
CHANGED
|
@@ -387,9 +387,6 @@ class MySQLDb(BaseDb):
|
|
|
387
387
|
|
|
388
388
|
if user_id is not None:
|
|
389
389
|
stmt = stmt.where(table.c.user_id == user_id)
|
|
390
|
-
if session_type is not None:
|
|
391
|
-
session_type_value = session_type.value if isinstance(session_type, SessionType) else session_type
|
|
392
|
-
stmt = stmt.where(table.c.session_type == session_type_value)
|
|
393
390
|
result = sess.execute(stmt).fetchone()
|
|
394
391
|
if result is None:
|
|
395
392
|
return None
|
agno/db/postgres/__init__.py
CHANGED
|
@@ -3,20 +3,20 @@ from datetime import date, datetime, timedelta, timezone
|
|
|
3
3
|
from typing import Any, Dict, List, Optional, Sequence, Tuple, Union
|
|
4
4
|
from uuid import uuid4
|
|
5
5
|
|
|
6
|
-
from agno.db.
|
|
7
|
-
from agno.db.
|
|
6
|
+
from agno.db.base import AsyncBaseDb, SessionType
|
|
7
|
+
from agno.db.postgres.schemas import get_table_schema_definition
|
|
8
|
+
from agno.db.postgres.utils import (
|
|
9
|
+
abulk_upsert_metrics,
|
|
10
|
+
acreate_schema,
|
|
11
|
+
ais_table_available,
|
|
12
|
+
ais_valid_table,
|
|
8
13
|
apply_sorting,
|
|
9
|
-
bulk_upsert_metrics,
|
|
10
14
|
calculate_date_metrics,
|
|
11
|
-
create_schema,
|
|
12
15
|
deserialize_cultural_knowledge,
|
|
13
16
|
fetch_all_sessions_data,
|
|
14
17
|
get_dates_to_calculate_metrics_for,
|
|
15
|
-
is_table_available,
|
|
16
|
-
is_valid_table,
|
|
17
18
|
serialize_cultural_knowledge,
|
|
18
19
|
)
|
|
19
|
-
from agno.db.base import AsyncBaseDb, SessionType
|
|
20
20
|
from agno.db.schemas.culture import CulturalKnowledge
|
|
21
21
|
from agno.db.schemas.evals import EvalFilterType, EvalRunRecord, EvalType
|
|
22
22
|
from agno.db.schemas.knowledge import KnowledgeRow
|
|
@@ -148,7 +148,7 @@ class AsyncPostgresDb(AsyncBaseDb):
|
|
|
148
148
|
table.append_constraint(Index(idx_name, idx_col))
|
|
149
149
|
|
|
150
150
|
async with self.async_session_factory() as sess, sess.begin():
|
|
151
|
-
await
|
|
151
|
+
await acreate_schema(session=sess, db_schema=db_schema)
|
|
152
152
|
|
|
153
153
|
# Create table
|
|
154
154
|
async with self.db_engine.begin() as conn:
|
|
@@ -241,12 +241,12 @@ class AsyncPostgresDb(AsyncBaseDb):
|
|
|
241
241
|
"""
|
|
242
242
|
|
|
243
243
|
async with self.async_session_factory() as sess, sess.begin():
|
|
244
|
-
table_is_available = await
|
|
244
|
+
table_is_available = await ais_table_available(session=sess, table_name=table_name, db_schema=db_schema)
|
|
245
245
|
|
|
246
246
|
if not table_is_available:
|
|
247
247
|
return await self._create_table(table_name=table_name, table_type=table_type, db_schema=db_schema)
|
|
248
248
|
|
|
249
|
-
if not await
|
|
249
|
+
if not await ais_valid_table(
|
|
250
250
|
db_engine=self.db_engine,
|
|
251
251
|
table_name=table_name,
|
|
252
252
|
table_type=table_type,
|
|
@@ -288,7 +288,7 @@ class AsyncPostgresDb(AsyncBaseDb):
|
|
|
288
288
|
delete_stmt = table.delete().where(table.c.session_id == session_id)
|
|
289
289
|
result = await sess.execute(delete_stmt)
|
|
290
290
|
|
|
291
|
-
if result.rowcount == 0:
|
|
291
|
+
if result.rowcount == 0: # type: ignore
|
|
292
292
|
log_debug(f"No session found to delete with session_id: {session_id} in table {table.name}")
|
|
293
293
|
return False
|
|
294
294
|
|
|
@@ -317,7 +317,7 @@ class AsyncPostgresDb(AsyncBaseDb):
|
|
|
317
317
|
delete_stmt = table.delete().where(table.c.session_id.in_(session_ids))
|
|
318
318
|
result = await sess.execute(delete_stmt)
|
|
319
319
|
|
|
320
|
-
log_debug(f"Successfully deleted {result.rowcount} sessions")
|
|
320
|
+
log_debug(f"Successfully deleted {result.rowcount} sessions") # type: ignore
|
|
321
321
|
|
|
322
322
|
except Exception as e:
|
|
323
323
|
log_error(f"Error deleting sessions: {e}")
|
|
@@ -354,9 +354,6 @@ class AsyncPostgresDb(AsyncBaseDb):
|
|
|
354
354
|
|
|
355
355
|
if user_id is not None:
|
|
356
356
|
stmt = stmt.where(table.c.user_id == user_id)
|
|
357
|
-
if session_type is not None:
|
|
358
|
-
session_type_value = session_type.value if isinstance(session_type, SessionType) else session_type
|
|
359
|
-
stmt = stmt.where(table.c.session_type == session_type_value)
|
|
360
357
|
result = await sess.execute(stmt)
|
|
361
358
|
row = result.fetchone()
|
|
362
359
|
if row is None:
|
|
@@ -712,7 +709,7 @@ class AsyncPostgresDb(AsyncBaseDb):
|
|
|
712
709
|
delete_stmt = table.delete().where(table.c.memory_id == memory_id)
|
|
713
710
|
result = await sess.execute(delete_stmt)
|
|
714
711
|
|
|
715
|
-
success = result.rowcount > 0
|
|
712
|
+
success = result.rowcount > 0 # type: ignore
|
|
716
713
|
if success:
|
|
717
714
|
log_debug(f"Successfully deleted user memory id: {memory_id}")
|
|
718
715
|
else:
|
|
@@ -737,10 +734,10 @@ class AsyncPostgresDb(AsyncBaseDb):
|
|
|
737
734
|
delete_stmt = table.delete().where(table.c.memory_id.in_(memory_ids))
|
|
738
735
|
result = await sess.execute(delete_stmt)
|
|
739
736
|
|
|
740
|
-
if result.rowcount == 0:
|
|
737
|
+
if result.rowcount == 0: # type: ignore
|
|
741
738
|
log_debug(f"No user memories found with ids: {memory_ids}")
|
|
742
739
|
else:
|
|
743
|
-
log_debug(f"Successfully deleted {result.rowcount} user memories")
|
|
740
|
+
log_debug(f"Successfully deleted {result.rowcount} user memories") # type: ignore
|
|
744
741
|
|
|
745
742
|
except Exception as e:
|
|
746
743
|
log_error(f"Error deleting user memories: {e}")
|
|
@@ -1387,7 +1384,7 @@ class AsyncPostgresDb(AsyncBaseDb):
|
|
|
1387
1384
|
|
|
1388
1385
|
if metrics_records:
|
|
1389
1386
|
async with self.async_session_factory() as sess, sess.begin():
|
|
1390
|
-
results = await
|
|
1387
|
+
results = await abulk_upsert_metrics(session=sess, table=table, metrics_records=metrics_records)
|
|
1391
1388
|
|
|
1392
1389
|
log_debug("Updated metrics calculations")
|
|
1393
1390
|
|
|
@@ -1649,7 +1646,7 @@ class AsyncPostgresDb(AsyncBaseDb):
|
|
|
1649
1646
|
stmt = table.delete().where(table.c.run_id == eval_run_id)
|
|
1650
1647
|
result = await sess.execute(stmt)
|
|
1651
1648
|
|
|
1652
|
-
if result.rowcount == 0:
|
|
1649
|
+
if result.rowcount == 0: # type: ignore
|
|
1653
1650
|
log_warning(f"No eval run found with ID: {eval_run_id}")
|
|
1654
1651
|
else:
|
|
1655
1652
|
log_debug(f"Deleted eval run with ID: {eval_run_id}")
|
|
@@ -1670,10 +1667,10 @@ class AsyncPostgresDb(AsyncBaseDb):
|
|
|
1670
1667
|
stmt = table.delete().where(table.c.run_id.in_(eval_run_ids))
|
|
1671
1668
|
result = await sess.execute(stmt)
|
|
1672
1669
|
|
|
1673
|
-
if result.rowcount == 0:
|
|
1670
|
+
if result.rowcount == 0: # type: ignore
|
|
1674
1671
|
log_warning(f"No eval runs found with IDs: {eval_run_ids}")
|
|
1675
1672
|
else:
|
|
1676
|
-
log_debug(f"Deleted {result.rowcount} eval runs")
|
|
1673
|
+
log_debug(f"Deleted {result.rowcount} eval runs") # type: ignore
|
|
1677
1674
|
|
|
1678
1675
|
except Exception as e:
|
|
1679
1676
|
log_error(f"Error deleting eval runs {eval_run_ids}: {e}")
|
agno/db/postgres/postgres.py
CHANGED
|
@@ -10,12 +10,12 @@ from agno.db.postgres.utils import (
|
|
|
10
10
|
bulk_upsert_metrics,
|
|
11
11
|
calculate_date_metrics,
|
|
12
12
|
create_schema,
|
|
13
|
-
|
|
13
|
+
deserialize_cultural_knowledge,
|
|
14
14
|
fetch_all_sessions_data,
|
|
15
15
|
get_dates_to_calculate_metrics_for,
|
|
16
16
|
is_table_available,
|
|
17
17
|
is_valid_table,
|
|
18
|
-
|
|
18
|
+
serialize_cultural_knowledge,
|
|
19
19
|
)
|
|
20
20
|
from agno.db.schemas.culture import CulturalKnowledge
|
|
21
21
|
from agno.db.schemas.evals import EvalFilterType, EvalRunRecord, EvalType
|
|
@@ -383,9 +383,6 @@ class PostgresDb(BaseDb):
|
|
|
383
383
|
|
|
384
384
|
if user_id is not None:
|
|
385
385
|
stmt = stmt.where(table.c.user_id == user_id)
|
|
386
|
-
if session_type is not None:
|
|
387
|
-
session_type_value = session_type.value if isinstance(session_type, SessionType) else session_type
|
|
388
|
-
stmt = stmt.where(table.c.session_type == session_type_value)
|
|
389
386
|
result = sess.execute(stmt).fetchone()
|
|
390
387
|
if result is None:
|
|
391
388
|
return None
|
|
@@ -2030,7 +2027,7 @@ class PostgresDb(BaseDb):
|
|
|
2030
2027
|
if not db_row or not deserialize:
|
|
2031
2028
|
return db_row
|
|
2032
2029
|
|
|
2033
|
-
return
|
|
2030
|
+
return deserialize_cultural_knowledge(db_row)
|
|
2034
2031
|
|
|
2035
2032
|
except Exception as e:
|
|
2036
2033
|
log_error(f"Exception reading from cultural knowledge table: {e}")
|
|
@@ -2104,7 +2101,7 @@ class PostgresDb(BaseDb):
|
|
|
2104
2101
|
if not deserialize:
|
|
2105
2102
|
return db_rows, total_count
|
|
2106
2103
|
|
|
2107
|
-
return [
|
|
2104
|
+
return [deserialize_cultural_knowledge(row) for row in db_rows]
|
|
2108
2105
|
|
|
2109
2106
|
except Exception as e:
|
|
2110
2107
|
log_error(f"Error reading from cultural knowledge table: {e}")
|
|
@@ -2134,7 +2131,7 @@ class PostgresDb(BaseDb):
|
|
|
2134
2131
|
cultural_knowledge.id = str(uuid4())
|
|
2135
2132
|
|
|
2136
2133
|
# Serialize content, categories, and notes into a JSON dict for DB storage
|
|
2137
|
-
content_dict =
|
|
2134
|
+
content_dict = serialize_cultural_knowledge(cultural_knowledge)
|
|
2138
2135
|
|
|
2139
2136
|
with self.Session() as sess, sess.begin():
|
|
2140
2137
|
stmt = postgresql.insert(table).values(
|
|
@@ -2149,7 +2146,7 @@ class PostgresDb(BaseDb):
|
|
|
2149
2146
|
agent_id=cultural_knowledge.agent_id,
|
|
2150
2147
|
team_id=cultural_knowledge.team_id,
|
|
2151
2148
|
)
|
|
2152
|
-
stmt = stmt.on_conflict_do_update(
|
|
2149
|
+
stmt = stmt.on_conflict_do_update( # type: ignore
|
|
2153
2150
|
index_elements=["id"],
|
|
2154
2151
|
set_=dict(
|
|
2155
2152
|
name=cultural_knowledge.name,
|
|
@@ -2173,7 +2170,7 @@ class PostgresDb(BaseDb):
|
|
|
2173
2170
|
if not db_row or not deserialize:
|
|
2174
2171
|
return db_row
|
|
2175
2172
|
|
|
2176
|
-
return
|
|
2173
|
+
return deserialize_cultural_knowledge(db_row)
|
|
2177
2174
|
|
|
2178
2175
|
except Exception as e:
|
|
2179
2176
|
log_error(f"Error upserting cultural knowledge: {e}")
|
agno/db/postgres/utils.py
CHANGED
|
@@ -6,6 +6,7 @@ from typing import Any, Dict, List, Optional
|
|
|
6
6
|
from uuid import uuid4
|
|
7
7
|
|
|
8
8
|
from sqlalchemy import Engine
|
|
9
|
+
from sqlalchemy.ext.asyncio import AsyncEngine, AsyncSession
|
|
9
10
|
|
|
10
11
|
from agno.db.postgres.schemas import get_table_schema_definition
|
|
11
12
|
from agno.db.schemas.culture import CulturalKnowledge
|
|
@@ -63,6 +64,20 @@ def create_schema(session: Session, db_schema: str) -> None:
|
|
|
63
64
|
log_warning(f"Could not create schema {db_schema}: {e}")
|
|
64
65
|
|
|
65
66
|
|
|
67
|
+
async def acreate_schema(session: AsyncSession, db_schema: str) -> None:
|
|
68
|
+
"""Create the database schema if it doesn't exist.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
session: The SQLAlchemy session to use
|
|
72
|
+
db_schema (str): The definition of the database schema to create
|
|
73
|
+
"""
|
|
74
|
+
try:
|
|
75
|
+
log_debug(f"Creating schema if not exists: {db_schema}")
|
|
76
|
+
await session.execute(text(f"CREATE SCHEMA IF NOT EXISTS {db_schema};"))
|
|
77
|
+
except Exception as e:
|
|
78
|
+
log_warning(f"Could not create schema {db_schema}: {e}")
|
|
79
|
+
|
|
80
|
+
|
|
66
81
|
def is_table_available(session: Session, table_name: str, db_schema: str) -> bool:
|
|
67
82
|
"""
|
|
68
83
|
Check if a table with the given name exists in the given schema.
|
|
@@ -82,6 +97,24 @@ def is_table_available(session: Session, table_name: str, db_schema: str) -> boo
|
|
|
82
97
|
return False
|
|
83
98
|
|
|
84
99
|
|
|
100
|
+
async def ais_table_available(session: AsyncSession, table_name: str, db_schema: str) -> bool:
|
|
101
|
+
"""
|
|
102
|
+
Check if a table with the given name exists in the given schema.
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
bool: True if the table exists, False otherwise.
|
|
106
|
+
"""
|
|
107
|
+
try:
|
|
108
|
+
exists_query = text(
|
|
109
|
+
"SELECT 1 FROM information_schema.tables WHERE table_schema = :schema AND table_name = :table"
|
|
110
|
+
)
|
|
111
|
+
exists = (await session.execute(exists_query, {"schema": db_schema, "table": table_name})).scalar() is not None
|
|
112
|
+
return exists
|
|
113
|
+
except Exception as e:
|
|
114
|
+
log_error(f"Error checking if table exists: {e}")
|
|
115
|
+
return False
|
|
116
|
+
|
|
117
|
+
|
|
85
118
|
def is_valid_table(db_engine: Engine, table_name: str, table_type: str, db_schema: str) -> bool:
|
|
86
119
|
"""
|
|
87
120
|
Check if the existing table has the expected column names.
|
|
@@ -114,6 +147,44 @@ def is_valid_table(db_engine: Engine, table_name: str, table_type: str, db_schem
|
|
|
114
147
|
return False
|
|
115
148
|
|
|
116
149
|
|
|
150
|
+
async def ais_valid_table(db_engine: AsyncEngine, table_name: str, table_type: str, db_schema: str) -> bool:
|
|
151
|
+
"""
|
|
152
|
+
Check if the existing table has the expected column names.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
table_name (str): Name of the table to validate
|
|
156
|
+
schema (str): Database schema name
|
|
157
|
+
|
|
158
|
+
Returns:
|
|
159
|
+
bool: True if table has all expected columns, False otherwise
|
|
160
|
+
"""
|
|
161
|
+
try:
|
|
162
|
+
expected_table_schema = get_table_schema_definition(table_type)
|
|
163
|
+
expected_columns = {col_name for col_name in expected_table_schema.keys() if not col_name.startswith("_")}
|
|
164
|
+
|
|
165
|
+
# Get existing columns from the async engine
|
|
166
|
+
async with db_engine.connect() as conn:
|
|
167
|
+
existing_columns = await conn.run_sync(_get_table_columns, table_name, db_schema)
|
|
168
|
+
|
|
169
|
+
# Check if all expected columns exist
|
|
170
|
+
missing_columns = expected_columns - existing_columns
|
|
171
|
+
if missing_columns:
|
|
172
|
+
log_warning(f"Missing columns {missing_columns} in table {db_schema}.{table_name}")
|
|
173
|
+
return False
|
|
174
|
+
|
|
175
|
+
return True
|
|
176
|
+
except Exception as e:
|
|
177
|
+
log_error(f"Error validating table schema for {db_schema}.{table_name}: {e}")
|
|
178
|
+
return False
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
def _get_table_columns(conn, table_name: str, db_schema: str) -> set[str]:
|
|
182
|
+
"""Helper function to get table columns using sync inspector."""
|
|
183
|
+
inspector = inspect(conn)
|
|
184
|
+
columns_info = inspector.get_columns(table_name, schema=db_schema)
|
|
185
|
+
return {col["name"] for col in columns_info}
|
|
186
|
+
|
|
187
|
+
|
|
117
188
|
# -- Metrics util methods --
|
|
118
189
|
def bulk_upsert_metrics(session: Session, table: Table, metrics_records: list[dict]) -> list[dict]:
|
|
119
190
|
"""Bulk upsert metrics into the database.
|
|
@@ -148,6 +219,39 @@ def bulk_upsert_metrics(session: Session, table: Table, metrics_records: list[di
|
|
|
148
219
|
return results # type: ignore
|
|
149
220
|
|
|
150
221
|
|
|
222
|
+
async def abulk_upsert_metrics(session: AsyncSession, table: Table, metrics_records: list[dict]) -> list[dict]:
|
|
223
|
+
"""Bulk upsert metrics into the database.
|
|
224
|
+
|
|
225
|
+
Args:
|
|
226
|
+
table (Table): The table to upsert into.
|
|
227
|
+
metrics_records (list[dict]): The metrics records to upsert.
|
|
228
|
+
|
|
229
|
+
Returns:
|
|
230
|
+
list[dict]: The upserted metrics records.
|
|
231
|
+
"""
|
|
232
|
+
if not metrics_records:
|
|
233
|
+
return []
|
|
234
|
+
|
|
235
|
+
results = []
|
|
236
|
+
stmt = postgresql.insert(table)
|
|
237
|
+
|
|
238
|
+
# Columns to update in case of conflict
|
|
239
|
+
update_columns = {
|
|
240
|
+
col.name: stmt.excluded[col.name]
|
|
241
|
+
for col in table.columns
|
|
242
|
+
if col.name not in ["id", "date", "created_at", "aggregation_period"]
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
stmt = stmt.on_conflict_do_update(index_elements=["date", "aggregation_period"], set_=update_columns).returning( # type: ignore
|
|
246
|
+
table
|
|
247
|
+
)
|
|
248
|
+
result = await session.execute(stmt, metrics_records)
|
|
249
|
+
results = [row._mapping for row in result.fetchall()]
|
|
250
|
+
await session.commit()
|
|
251
|
+
|
|
252
|
+
return results # type: ignore
|
|
253
|
+
|
|
254
|
+
|
|
151
255
|
def calculate_date_metrics(date_to_process: date, sessions_data: dict) -> dict:
|
|
152
256
|
"""Calculate metrics for the given single date.
|
|
153
257
|
|
|
@@ -282,7 +386,7 @@ def get_dates_to_calculate_metrics_for(starting_date: date) -> list[date]:
|
|
|
282
386
|
|
|
283
387
|
|
|
284
388
|
# -- Cultural Knowledge util methods --
|
|
285
|
-
def
|
|
389
|
+
def serialize_cultural_knowledge(cultural_knowledge: CulturalKnowledge) -> Dict[str, Any]:
|
|
286
390
|
"""Serialize a CulturalKnowledge object for database storage.
|
|
287
391
|
|
|
288
392
|
Converts the model's separate content, categories, and notes fields
|
|
@@ -305,7 +409,7 @@ def serialize_cultural_knowledge_for_db(cultural_knowledge: CulturalKnowledge) -
|
|
|
305
409
|
return content_dict if content_dict else {}
|
|
306
410
|
|
|
307
411
|
|
|
308
|
-
def
|
|
412
|
+
def deserialize_cultural_knowledge(db_row: Dict[str, Any]) -> CulturalKnowledge:
|
|
309
413
|
"""Deserialize a database row to a CulturalKnowledge object.
|
|
310
414
|
|
|
311
415
|
The database stores content as a JSON dict containing content, categories, and notes.
|
agno/db/redis/redis.py
CHANGED
|
@@ -327,8 +327,6 @@ class RedisDb(BaseDb):
|
|
|
327
327
|
# Apply filters
|
|
328
328
|
if user_id is not None and session.get("user_id") != user_id:
|
|
329
329
|
return None
|
|
330
|
-
if session_type is not None and session.get("session_type") != session_type:
|
|
331
|
-
return None
|
|
332
330
|
|
|
333
331
|
if not deserialize:
|
|
334
332
|
return session
|
|
@@ -469,9 +469,6 @@ class SingleStoreDb(BaseDb):
|
|
|
469
469
|
|
|
470
470
|
if user_id is not None:
|
|
471
471
|
stmt = stmt.where(table.c.user_id == user_id)
|
|
472
|
-
if session_type is not None:
|
|
473
|
-
session_type_value = session_type.value if isinstance(session_type, SessionType) else session_type
|
|
474
|
-
stmt = stmt.where(table.c.session_type == session_type_value)
|
|
475
472
|
result = sess.execute(stmt).fetchone()
|
|
476
473
|
if result is None:
|
|
477
474
|
return None
|
agno/db/sqlite/__init__.py
CHANGED