agno 2.4.0__py3-none-any.whl → 2.4.2__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/db/firestore/firestore.py +58 -65
- agno/db/mysql/async_mysql.py +47 -55
- agno/db/postgres/async_postgres.py +52 -61
- agno/db/postgres/postgres.py +25 -12
- agno/db/sqlite/async_sqlite.py +52 -61
- agno/db/sqlite/sqlite.py +24 -11
- agno/integrations/discord/client.py +12 -1
- agno/knowledge/knowledge.py +1511 -47
- agno/knowledge/reader/csv_reader.py +231 -8
- agno/knowledge/reader/field_labeled_csv_reader.py +167 -3
- agno/knowledge/reader/reader_factory.py +8 -1
- agno/knowledge/remote_content/__init__.py +33 -0
- agno/knowledge/remote_content/config.py +266 -0
- agno/knowledge/remote_content/remote_content.py +105 -17
- agno/models/base.py +12 -2
- agno/models/cerebras/cerebras.py +34 -2
- agno/models/n1n/__init__.py +3 -0
- agno/models/n1n/n1n.py +57 -0
- agno/models/ollama/__init__.py +2 -0
- agno/models/ollama/responses.py +100 -0
- agno/models/openai/__init__.py +2 -0
- agno/models/openai/chat.py +18 -1
- agno/models/openai/open_responses.py +46 -0
- agno/models/openrouter/__init__.py +2 -0
- agno/models/openrouter/responses.py +146 -0
- agno/models/perplexity/perplexity.py +2 -0
- agno/os/interfaces/slack/router.py +10 -1
- agno/os/interfaces/whatsapp/router.py +6 -0
- agno/os/routers/components/components.py +10 -1
- agno/os/routers/knowledge/knowledge.py +125 -0
- agno/os/routers/knowledge/schemas.py +12 -0
- agno/run/agent.py +2 -0
- agno/team/team.py +20 -4
- agno/vectordb/lightrag/lightrag.py +7 -6
- agno/vectordb/milvus/milvus.py +79 -48
- agno/vectordb/pgvector/pgvector.py +3 -3
- {agno-2.4.0.dist-info → agno-2.4.2.dist-info}/METADATA +4 -1
- {agno-2.4.0.dist-info → agno-2.4.2.dist-info}/RECORD +41 -35
- {agno-2.4.0.dist-info → agno-2.4.2.dist-info}/WHEEL +1 -1
- {agno-2.4.0.dist-info → agno-2.4.2.dist-info}/licenses/LICENSE +0 -0
- {agno-2.4.0.dist-info → agno-2.4.2.dist-info}/top_level.txt +0 -0
agno/db/sqlite/async_sqlite.py
CHANGED
|
@@ -263,95 +263,86 @@ class AsyncSqliteDb(AsyncBaseDb):
|
|
|
263
263
|
|
|
264
264
|
async def _get_table(self, table_type: str, create_table_if_not_found: Optional[bool] = False) -> Optional[Table]:
|
|
265
265
|
if table_type == "sessions":
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
)
|
|
266
|
+
self.session_table = await self._get_or_create_table(
|
|
267
|
+
table_name=self.session_table_name,
|
|
268
|
+
table_type=table_type,
|
|
269
|
+
create_table_if_not_found=create_table_if_not_found,
|
|
270
|
+
)
|
|
272
271
|
return self.session_table
|
|
273
272
|
|
|
274
273
|
elif table_type == "memories":
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
)
|
|
274
|
+
self.memory_table = await self._get_or_create_table(
|
|
275
|
+
table_name=self.memory_table_name,
|
|
276
|
+
table_type="memories",
|
|
277
|
+
create_table_if_not_found=create_table_if_not_found,
|
|
278
|
+
)
|
|
281
279
|
return self.memory_table
|
|
282
280
|
|
|
283
281
|
elif table_type == "metrics":
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
)
|
|
282
|
+
self.metrics_table = await self._get_or_create_table(
|
|
283
|
+
table_name=self.metrics_table_name,
|
|
284
|
+
table_type="metrics",
|
|
285
|
+
create_table_if_not_found=create_table_if_not_found,
|
|
286
|
+
)
|
|
290
287
|
return self.metrics_table
|
|
291
288
|
|
|
292
289
|
elif table_type == "evals":
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
)
|
|
290
|
+
self.eval_table = await self._get_or_create_table(
|
|
291
|
+
table_name=self.eval_table_name,
|
|
292
|
+
table_type="evals",
|
|
293
|
+
create_table_if_not_found=create_table_if_not_found,
|
|
294
|
+
)
|
|
299
295
|
return self.eval_table
|
|
300
296
|
|
|
301
297
|
elif table_type == "knowledge":
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
)
|
|
298
|
+
self.knowledge_table = await self._get_or_create_table(
|
|
299
|
+
table_name=self.knowledge_table_name,
|
|
300
|
+
table_type="knowledge",
|
|
301
|
+
create_table_if_not_found=create_table_if_not_found,
|
|
302
|
+
)
|
|
308
303
|
return self.knowledge_table
|
|
309
304
|
|
|
310
305
|
elif table_type == "culture":
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
)
|
|
306
|
+
self.culture_table = await self._get_or_create_table(
|
|
307
|
+
table_name=self.culture_table_name,
|
|
308
|
+
table_type="culture",
|
|
309
|
+
create_table_if_not_found=create_table_if_not_found,
|
|
310
|
+
)
|
|
317
311
|
return self.culture_table
|
|
318
312
|
|
|
319
313
|
elif table_type == "versions":
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
)
|
|
314
|
+
self.versions_table = await self._get_or_create_table(
|
|
315
|
+
table_name=self.versions_table_name,
|
|
316
|
+
table_type="versions",
|
|
317
|
+
create_table_if_not_found=create_table_if_not_found,
|
|
318
|
+
)
|
|
326
319
|
return self.versions_table
|
|
327
320
|
|
|
328
321
|
elif table_type == "traces":
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
)
|
|
322
|
+
self.traces_table = await self._get_or_create_table(
|
|
323
|
+
table_name=self.trace_table_name,
|
|
324
|
+
table_type="traces",
|
|
325
|
+
create_table_if_not_found=create_table_if_not_found,
|
|
326
|
+
)
|
|
335
327
|
return self.traces_table
|
|
336
328
|
|
|
337
329
|
elif table_type == "spans":
|
|
338
|
-
|
|
339
|
-
|
|
330
|
+
# Ensure traces table exists first (spans has FK to traces)
|
|
331
|
+
if create_table_if_not_found:
|
|
340
332
|
await self._get_table(table_type="traces", create_table_if_not_found=True)
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
333
|
+
self.spans_table = await self._get_or_create_table(
|
|
334
|
+
table_name=self.span_table_name,
|
|
335
|
+
table_type="spans",
|
|
336
|
+
create_table_if_not_found=create_table_if_not_found,
|
|
337
|
+
)
|
|
346
338
|
return self.spans_table
|
|
347
339
|
|
|
348
340
|
elif table_type == "learnings":
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
)
|
|
341
|
+
self.learnings_table = await self._get_or_create_table(
|
|
342
|
+
table_name=self.learnings_table_name,
|
|
343
|
+
table_type="learnings",
|
|
344
|
+
create_table_if_not_found=create_table_if_not_found,
|
|
345
|
+
)
|
|
355
346
|
return self.learnings_table
|
|
356
347
|
|
|
357
348
|
else:
|
agno/db/sqlite/sqlite.py
CHANGED
|
@@ -3475,7 +3475,7 @@ class SqliteDb(BaseDb):
|
|
|
3475
3475
|
|
|
3476
3476
|
Args:
|
|
3477
3477
|
component_id: The component ID.
|
|
3478
|
-
version: Specific version number. If None, uses current.
|
|
3478
|
+
version: Specific version number. If None, uses current or latest draft.
|
|
3479
3479
|
label: Config label to lookup. Ignored if version is provided.
|
|
3480
3480
|
|
|
3481
3481
|
Returns:
|
|
@@ -3490,16 +3490,22 @@ class SqliteDb(BaseDb):
|
|
|
3490
3490
|
|
|
3491
3491
|
with self.Session() as sess:
|
|
3492
3492
|
# Always verify component exists and is not deleted
|
|
3493
|
-
|
|
3494
|
-
|
|
3495
|
-
components_table.c.
|
|
3496
|
-
|
|
3493
|
+
component_row = (
|
|
3494
|
+
sess.execute(
|
|
3495
|
+
select(components_table.c.current_version, components_table.c.component_id).where(
|
|
3496
|
+
components_table.c.component_id == component_id,
|
|
3497
|
+
components_table.c.deleted_at.is_(None),
|
|
3498
|
+
)
|
|
3497
3499
|
)
|
|
3498
|
-
|
|
3500
|
+
.mappings()
|
|
3501
|
+
.one_or_none()
|
|
3502
|
+
)
|
|
3499
3503
|
|
|
3500
|
-
if
|
|
3504
|
+
if component_row is None:
|
|
3501
3505
|
return None
|
|
3502
3506
|
|
|
3507
|
+
current_version = component_row["current_version"]
|
|
3508
|
+
|
|
3503
3509
|
if version is not None:
|
|
3504
3510
|
stmt = select(configs_table).where(
|
|
3505
3511
|
configs_table.c.component_id == component_id,
|
|
@@ -3510,12 +3516,19 @@ class SqliteDb(BaseDb):
|
|
|
3510
3516
|
configs_table.c.component_id == component_id,
|
|
3511
3517
|
configs_table.c.label == label,
|
|
3512
3518
|
)
|
|
3513
|
-
|
|
3514
|
-
|
|
3515
|
-
return None
|
|
3519
|
+
elif current_version is not None:
|
|
3520
|
+
# Use the current published version
|
|
3516
3521
|
stmt = select(configs_table).where(
|
|
3517
3522
|
configs_table.c.component_id == component_id,
|
|
3518
|
-
configs_table.c.version ==
|
|
3523
|
+
configs_table.c.version == current_version,
|
|
3524
|
+
)
|
|
3525
|
+
else:
|
|
3526
|
+
# No current_version set (draft only) - get the latest version
|
|
3527
|
+
stmt = (
|
|
3528
|
+
select(configs_table)
|
|
3529
|
+
.where(configs_table.c.component_id == component_id)
|
|
3530
|
+
.order_by(configs_table.c.version.desc())
|
|
3531
|
+
.limit(1)
|
|
3519
3532
|
)
|
|
3520
3533
|
|
|
3521
3534
|
result = sess.execute(stmt).fetchone()
|
|
@@ -7,7 +7,7 @@ import requests
|
|
|
7
7
|
from agno.agent.agent import Agent, RunOutput
|
|
8
8
|
from agno.media import Audio, File, Image, Video
|
|
9
9
|
from agno.team.team import Team, TeamRunOutput
|
|
10
|
-
from agno.utils.log import log_info, log_warning
|
|
10
|
+
from agno.utils.log import log_error, log_info, log_warning
|
|
11
11
|
from agno.utils.message import get_text_from_message
|
|
12
12
|
|
|
13
13
|
try:
|
|
@@ -126,6 +126,11 @@ class DiscordClient:
|
|
|
126
126
|
audio=[Audio(url=message_audio)] if message_audio else None,
|
|
127
127
|
files=[File(content=message_file)] if message_file else None,
|
|
128
128
|
)
|
|
129
|
+
if agent_response.status == "ERROR":
|
|
130
|
+
log_error(agent_response.content)
|
|
131
|
+
agent_response.content = (
|
|
132
|
+
"Sorry, there was an error processing your message. Please try again later."
|
|
133
|
+
)
|
|
129
134
|
await self._handle_response_in_thread(agent_response, thread)
|
|
130
135
|
elif self.team:
|
|
131
136
|
self.team.additional_context = additional_context
|
|
@@ -138,6 +143,12 @@ class DiscordClient:
|
|
|
138
143
|
audio=[Audio(url=message_audio)] if message_audio else None,
|
|
139
144
|
files=[File(content=message_file)] if message_file else None,
|
|
140
145
|
)
|
|
146
|
+
if team_response.status == "ERROR":
|
|
147
|
+
log_error(team_response.content)
|
|
148
|
+
team_response.content = (
|
|
149
|
+
"Sorry, there was an error processing your message. Please try again later."
|
|
150
|
+
)
|
|
151
|
+
|
|
141
152
|
await self._handle_response_in_thread(team_response, thread)
|
|
142
153
|
|
|
143
154
|
async def handle_hitl(
|