agno 2.2.13__py3-none-any.whl → 2.4.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/__init__.py +6 -0
- agno/agent/agent.py +5252 -3145
- agno/agent/remote.py +525 -0
- agno/api/api.py +2 -0
- agno/client/__init__.py +3 -0
- agno/client/a2a/__init__.py +10 -0
- agno/client/a2a/client.py +554 -0
- agno/client/a2a/schemas.py +112 -0
- agno/client/a2a/utils.py +369 -0
- agno/client/os.py +2669 -0
- agno/compression/__init__.py +3 -0
- agno/compression/manager.py +247 -0
- agno/culture/manager.py +2 -2
- agno/db/base.py +927 -6
- agno/db/dynamo/dynamo.py +788 -2
- agno/db/dynamo/schemas.py +128 -0
- agno/db/dynamo/utils.py +26 -3
- agno/db/firestore/firestore.py +674 -50
- agno/db/firestore/schemas.py +41 -0
- agno/db/firestore/utils.py +25 -10
- agno/db/gcs_json/gcs_json_db.py +506 -3
- agno/db/gcs_json/utils.py +14 -2
- agno/db/in_memory/in_memory_db.py +203 -4
- agno/db/in_memory/utils.py +14 -2
- agno/db/json/json_db.py +498 -2
- agno/db/json/utils.py +14 -2
- agno/db/migrations/manager.py +199 -0
- agno/db/migrations/utils.py +19 -0
- agno/db/migrations/v1_to_v2.py +54 -16
- agno/db/migrations/versions/__init__.py +0 -0
- agno/db/migrations/versions/v2_3_0.py +977 -0
- agno/db/mongo/async_mongo.py +1013 -39
- agno/db/mongo/mongo.py +684 -4
- agno/db/mongo/schemas.py +48 -0
- agno/db/mongo/utils.py +17 -0
- agno/db/mysql/__init__.py +2 -1
- agno/db/mysql/async_mysql.py +2958 -0
- agno/db/mysql/mysql.py +722 -53
- agno/db/mysql/schemas.py +77 -11
- agno/db/mysql/utils.py +151 -8
- agno/db/postgres/async_postgres.py +1254 -137
- agno/db/postgres/postgres.py +2316 -93
- agno/db/postgres/schemas.py +153 -21
- agno/db/postgres/utils.py +22 -7
- agno/db/redis/redis.py +531 -3
- agno/db/redis/schemas.py +36 -0
- agno/db/redis/utils.py +31 -15
- agno/db/schemas/evals.py +1 -0
- agno/db/schemas/memory.py +20 -9
- agno/db/singlestore/schemas.py +70 -1
- agno/db/singlestore/singlestore.py +737 -74
- agno/db/singlestore/utils.py +13 -3
- agno/db/sqlite/async_sqlite.py +1069 -89
- agno/db/sqlite/schemas.py +133 -1
- agno/db/sqlite/sqlite.py +2203 -165
- agno/db/sqlite/utils.py +21 -11
- agno/db/surrealdb/models.py +25 -0
- agno/db/surrealdb/surrealdb.py +603 -1
- agno/db/utils.py +60 -0
- agno/eval/__init__.py +26 -3
- agno/eval/accuracy.py +25 -12
- agno/eval/agent_as_judge.py +871 -0
- agno/eval/base.py +29 -0
- agno/eval/performance.py +10 -4
- agno/eval/reliability.py +22 -13
- agno/eval/utils.py +2 -1
- agno/exceptions.py +42 -0
- agno/hooks/__init__.py +3 -0
- agno/hooks/decorator.py +164 -0
- agno/integrations/discord/client.py +13 -2
- agno/knowledge/__init__.py +4 -0
- agno/knowledge/chunking/code.py +90 -0
- agno/knowledge/chunking/document.py +65 -4
- agno/knowledge/chunking/fixed.py +4 -1
- agno/knowledge/chunking/markdown.py +102 -11
- agno/knowledge/chunking/recursive.py +2 -2
- agno/knowledge/chunking/semantic.py +130 -48
- agno/knowledge/chunking/strategy.py +18 -0
- agno/knowledge/embedder/azure_openai.py +0 -1
- agno/knowledge/embedder/google.py +1 -1
- agno/knowledge/embedder/mistral.py +1 -1
- agno/knowledge/embedder/nebius.py +1 -1
- agno/knowledge/embedder/openai.py +16 -12
- agno/knowledge/filesystem.py +412 -0
- agno/knowledge/knowledge.py +4261 -1199
- agno/knowledge/protocol.py +134 -0
- agno/knowledge/reader/arxiv_reader.py +3 -2
- agno/knowledge/reader/base.py +9 -7
- agno/knowledge/reader/csv_reader.py +91 -42
- agno/knowledge/reader/docx_reader.py +9 -10
- agno/knowledge/reader/excel_reader.py +225 -0
- agno/knowledge/reader/field_labeled_csv_reader.py +38 -48
- agno/knowledge/reader/firecrawl_reader.py +3 -2
- agno/knowledge/reader/json_reader.py +16 -22
- agno/knowledge/reader/markdown_reader.py +15 -14
- agno/knowledge/reader/pdf_reader.py +33 -28
- agno/knowledge/reader/pptx_reader.py +9 -10
- agno/knowledge/reader/reader_factory.py +135 -1
- agno/knowledge/reader/s3_reader.py +8 -16
- agno/knowledge/reader/tavily_reader.py +3 -3
- agno/knowledge/reader/text_reader.py +15 -14
- agno/knowledge/reader/utils/__init__.py +17 -0
- agno/knowledge/reader/utils/spreadsheet.py +114 -0
- agno/knowledge/reader/web_search_reader.py +8 -65
- agno/knowledge/reader/website_reader.py +16 -13
- agno/knowledge/reader/wikipedia_reader.py +36 -3
- agno/knowledge/reader/youtube_reader.py +3 -2
- 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/knowledge/utils.py +76 -22
- agno/learn/__init__.py +71 -0
- agno/learn/config.py +463 -0
- agno/learn/curate.py +185 -0
- agno/learn/machine.py +725 -0
- agno/learn/schemas.py +1114 -0
- agno/learn/stores/__init__.py +38 -0
- agno/learn/stores/decision_log.py +1156 -0
- agno/learn/stores/entity_memory.py +3275 -0
- agno/learn/stores/learned_knowledge.py +1583 -0
- agno/learn/stores/protocol.py +117 -0
- agno/learn/stores/session_context.py +1217 -0
- agno/learn/stores/user_memory.py +1495 -0
- agno/learn/stores/user_profile.py +1220 -0
- agno/learn/utils.py +209 -0
- agno/media.py +22 -6
- agno/memory/__init__.py +14 -1
- agno/memory/manager.py +223 -8
- agno/memory/strategies/__init__.py +15 -0
- agno/memory/strategies/base.py +66 -0
- agno/memory/strategies/summarize.py +196 -0
- agno/memory/strategies/types.py +37 -0
- agno/models/aimlapi/aimlapi.py +17 -0
- agno/models/anthropic/claude.py +434 -59
- agno/models/aws/bedrock.py +121 -20
- agno/models/aws/claude.py +131 -274
- agno/models/azure/ai_foundry.py +10 -6
- agno/models/azure/openai_chat.py +33 -10
- agno/models/base.py +1162 -561
- agno/models/cerebras/cerebras.py +120 -24
- agno/models/cerebras/cerebras_openai.py +21 -2
- agno/models/cohere/chat.py +65 -6
- agno/models/cometapi/cometapi.py +18 -1
- agno/models/dashscope/dashscope.py +2 -3
- agno/models/deepinfra/deepinfra.py +18 -1
- agno/models/deepseek/deepseek.py +69 -3
- agno/models/fireworks/fireworks.py +18 -1
- agno/models/google/gemini.py +959 -89
- agno/models/google/utils.py +22 -0
- agno/models/groq/groq.py +48 -18
- agno/models/huggingface/huggingface.py +17 -6
- agno/models/ibm/watsonx.py +16 -6
- agno/models/internlm/internlm.py +18 -1
- agno/models/langdb/langdb.py +13 -1
- agno/models/litellm/chat.py +88 -9
- agno/models/litellm/litellm_openai.py +18 -1
- agno/models/message.py +24 -5
- agno/models/meta/llama.py +40 -13
- agno/models/meta/llama_openai.py +22 -21
- agno/models/metrics.py +12 -0
- agno/models/mistral/mistral.py +8 -4
- agno/models/n1n/__init__.py +3 -0
- agno/models/n1n/n1n.py +57 -0
- agno/models/nebius/nebius.py +6 -7
- agno/models/nvidia/nvidia.py +20 -3
- agno/models/ollama/__init__.py +2 -0
- agno/models/ollama/chat.py +17 -6
- agno/models/ollama/responses.py +100 -0
- agno/models/openai/__init__.py +2 -0
- agno/models/openai/chat.py +117 -26
- agno/models/openai/open_responses.py +46 -0
- agno/models/openai/responses.py +110 -32
- agno/models/openrouter/__init__.py +2 -0
- agno/models/openrouter/openrouter.py +67 -2
- agno/models/openrouter/responses.py +146 -0
- agno/models/perplexity/perplexity.py +19 -1
- agno/models/portkey/portkey.py +7 -6
- agno/models/requesty/requesty.py +19 -2
- agno/models/response.py +20 -2
- agno/models/sambanova/sambanova.py +20 -3
- agno/models/siliconflow/siliconflow.py +19 -2
- agno/models/together/together.py +20 -3
- agno/models/vercel/v0.py +20 -3
- agno/models/vertexai/claude.py +124 -4
- agno/models/vllm/vllm.py +19 -14
- agno/models/xai/xai.py +19 -2
- agno/os/app.py +467 -137
- agno/os/auth.py +253 -5
- agno/os/config.py +22 -0
- agno/os/interfaces/a2a/a2a.py +7 -6
- agno/os/interfaces/a2a/router.py +635 -26
- agno/os/interfaces/a2a/utils.py +32 -33
- agno/os/interfaces/agui/agui.py +5 -3
- agno/os/interfaces/agui/router.py +26 -16
- agno/os/interfaces/agui/utils.py +97 -57
- agno/os/interfaces/base.py +7 -7
- agno/os/interfaces/slack/router.py +16 -7
- agno/os/interfaces/slack/slack.py +7 -7
- agno/os/interfaces/whatsapp/router.py +35 -7
- agno/os/interfaces/whatsapp/security.py +3 -1
- agno/os/interfaces/whatsapp/whatsapp.py +11 -8
- agno/os/managers.py +326 -0
- agno/os/mcp.py +652 -79
- agno/os/middleware/__init__.py +4 -0
- agno/os/middleware/jwt.py +718 -115
- agno/os/middleware/trailing_slash.py +27 -0
- agno/os/router.py +105 -1558
- agno/os/routers/agents/__init__.py +3 -0
- agno/os/routers/agents/router.py +655 -0
- agno/os/routers/agents/schema.py +288 -0
- agno/os/routers/components/__init__.py +3 -0
- agno/os/routers/components/components.py +475 -0
- agno/os/routers/database.py +155 -0
- agno/os/routers/evals/evals.py +111 -18
- agno/os/routers/evals/schemas.py +38 -5
- agno/os/routers/evals/utils.py +80 -11
- agno/os/routers/health.py +3 -3
- agno/os/routers/knowledge/knowledge.py +284 -35
- agno/os/routers/knowledge/schemas.py +14 -2
- agno/os/routers/memory/memory.py +274 -11
- agno/os/routers/memory/schemas.py +44 -3
- agno/os/routers/metrics/metrics.py +30 -15
- 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/session/session.py +143 -14
- agno/os/routers/teams/__init__.py +3 -0
- agno/os/routers/teams/router.py +550 -0
- agno/os/routers/teams/schema.py +280 -0
- agno/os/routers/traces/__init__.py +3 -0
- agno/os/routers/traces/schemas.py +414 -0
- agno/os/routers/traces/traces.py +549 -0
- agno/os/routers/workflows/__init__.py +3 -0
- agno/os/routers/workflows/router.py +757 -0
- agno/os/routers/workflows/schema.py +139 -0
- agno/os/schema.py +157 -584
- agno/os/scopes.py +469 -0
- agno/os/settings.py +3 -0
- agno/os/utils.py +574 -185
- agno/reasoning/anthropic.py +85 -1
- agno/reasoning/azure_ai_foundry.py +93 -1
- agno/reasoning/deepseek.py +102 -2
- agno/reasoning/default.py +6 -7
- agno/reasoning/gemini.py +87 -3
- agno/reasoning/groq.py +109 -2
- agno/reasoning/helpers.py +6 -7
- agno/reasoning/manager.py +1238 -0
- agno/reasoning/ollama.py +93 -1
- agno/reasoning/openai.py +115 -1
- agno/reasoning/vertexai.py +85 -1
- agno/registry/__init__.py +3 -0
- agno/registry/registry.py +68 -0
- agno/remote/__init__.py +3 -0
- agno/remote/base.py +581 -0
- agno/run/__init__.py +2 -4
- agno/run/agent.py +134 -19
- agno/run/base.py +49 -1
- agno/run/cancel.py +65 -52
- agno/run/cancellation_management/__init__.py +9 -0
- agno/run/cancellation_management/base.py +78 -0
- agno/run/cancellation_management/in_memory_cancellation_manager.py +100 -0
- agno/run/cancellation_management/redis_cancellation_manager.py +236 -0
- agno/run/requirement.py +181 -0
- agno/run/team.py +111 -19
- agno/run/workflow.py +2 -1
- agno/session/agent.py +57 -92
- agno/session/summary.py +1 -1
- agno/session/team.py +62 -115
- agno/session/workflow.py +353 -57
- agno/skills/__init__.py +17 -0
- agno/skills/agent_skills.py +377 -0
- agno/skills/errors.py +32 -0
- agno/skills/loaders/__init__.py +4 -0
- agno/skills/loaders/base.py +27 -0
- agno/skills/loaders/local.py +216 -0
- agno/skills/skill.py +65 -0
- agno/skills/utils.py +107 -0
- agno/skills/validator.py +277 -0
- agno/table.py +10 -0
- agno/team/__init__.py +5 -1
- agno/team/remote.py +447 -0
- agno/team/team.py +3769 -2202
- agno/tools/brandfetch.py +27 -18
- agno/tools/browserbase.py +225 -16
- agno/tools/crawl4ai.py +3 -0
- agno/tools/duckduckgo.py +25 -71
- agno/tools/exa.py +0 -21
- agno/tools/file.py +14 -13
- agno/tools/file_generation.py +12 -6
- agno/tools/firecrawl.py +15 -7
- agno/tools/function.py +94 -113
- agno/tools/google_bigquery.py +11 -2
- agno/tools/google_drive.py +4 -3
- agno/tools/knowledge.py +9 -4
- agno/tools/mcp/mcp.py +301 -18
- agno/tools/mcp/multi_mcp.py +269 -14
- agno/tools/mem0.py +11 -10
- agno/tools/memory.py +47 -46
- agno/tools/mlx_transcribe.py +10 -7
- agno/tools/models/nebius.py +5 -5
- agno/tools/models_labs.py +20 -10
- agno/tools/nano_banana.py +151 -0
- agno/tools/parallel.py +0 -7
- agno/tools/postgres.py +76 -36
- agno/tools/python.py +14 -6
- agno/tools/reasoning.py +30 -23
- agno/tools/redshift.py +406 -0
- agno/tools/shopify.py +1519 -0
- agno/tools/spotify.py +919 -0
- agno/tools/tavily.py +4 -1
- agno/tools/toolkit.py +253 -18
- agno/tools/websearch.py +93 -0
- agno/tools/website.py +1 -1
- agno/tools/wikipedia.py +1 -1
- agno/tools/workflow.py +56 -48
- agno/tools/yfinance.py +12 -11
- agno/tracing/__init__.py +12 -0
- agno/tracing/exporter.py +161 -0
- agno/tracing/schemas.py +276 -0
- agno/tracing/setup.py +112 -0
- agno/utils/agent.py +251 -10
- agno/utils/cryptography.py +22 -0
- agno/utils/dttm.py +33 -0
- agno/utils/events.py +264 -7
- agno/utils/hooks.py +111 -3
- agno/utils/http.py +161 -2
- agno/utils/mcp.py +49 -8
- agno/utils/media.py +22 -1
- agno/utils/models/ai_foundry.py +9 -2
- agno/utils/models/claude.py +20 -5
- agno/utils/models/cohere.py +9 -2
- agno/utils/models/llama.py +9 -2
- agno/utils/models/mistral.py +4 -2
- agno/utils/os.py +0 -0
- agno/utils/print_response/agent.py +99 -16
- agno/utils/print_response/team.py +223 -24
- agno/utils/print_response/workflow.py +0 -2
- agno/utils/prompts.py +8 -6
- agno/utils/remote.py +23 -0
- agno/utils/response.py +1 -13
- agno/utils/string.py +91 -2
- agno/utils/team.py +62 -12
- agno/utils/tokens.py +657 -0
- agno/vectordb/base.py +15 -2
- agno/vectordb/cassandra/cassandra.py +1 -1
- agno/vectordb/chroma/__init__.py +2 -1
- agno/vectordb/chroma/chromadb.py +468 -23
- agno/vectordb/clickhouse/clickhousedb.py +1 -1
- agno/vectordb/couchbase/couchbase.py +6 -2
- agno/vectordb/lancedb/lance_db.py +7 -38
- agno/vectordb/lightrag/lightrag.py +7 -6
- agno/vectordb/milvus/milvus.py +118 -84
- agno/vectordb/mongodb/__init__.py +2 -1
- agno/vectordb/mongodb/mongodb.py +14 -31
- agno/vectordb/pgvector/pgvector.py +120 -66
- agno/vectordb/pineconedb/pineconedb.py +2 -19
- agno/vectordb/qdrant/__init__.py +2 -1
- agno/vectordb/qdrant/qdrant.py +33 -56
- agno/vectordb/redis/__init__.py +2 -1
- agno/vectordb/redis/redisdb.py +19 -31
- agno/vectordb/singlestore/singlestore.py +17 -9
- agno/vectordb/surrealdb/surrealdb.py +2 -38
- agno/vectordb/weaviate/__init__.py +2 -1
- agno/vectordb/weaviate/weaviate.py +7 -3
- agno/workflow/__init__.py +5 -1
- agno/workflow/agent.py +2 -2
- agno/workflow/condition.py +12 -10
- agno/workflow/loop.py +28 -9
- agno/workflow/parallel.py +21 -13
- agno/workflow/remote.py +362 -0
- agno/workflow/router.py +12 -9
- agno/workflow/step.py +261 -36
- agno/workflow/steps.py +12 -8
- agno/workflow/types.py +40 -77
- agno/workflow/workflow.py +939 -213
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/METADATA +134 -181
- agno-2.4.3.dist-info/RECORD +677 -0
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/WHEEL +1 -1
- agno/tools/googlesearch.py +0 -98
- agno/tools/memori.py +0 -339
- agno-2.2.13.dist-info/RECORD +0 -575
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/licenses/LICENSE +0 -0
- {agno-2.2.13.dist-info → agno-2.4.3.dist-info}/top_level.txt +0 -0
agno/db/gcs_json/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 agno.db.schemas.culture import CulturalKnowledge
|
|
9
|
+
from agno.db.utils import get_sort_value
|
|
9
10
|
from agno.utils.log import log_debug
|
|
10
11
|
|
|
11
12
|
|
|
@@ -21,6 +22,9 @@ def apply_sorting(
|
|
|
21
22
|
|
|
22
23
|
Returns:
|
|
23
24
|
The sorted list
|
|
25
|
+
|
|
26
|
+
Note:
|
|
27
|
+
If sorting by "updated_at", will fallback to "created_at" in case of None.
|
|
24
28
|
"""
|
|
25
29
|
if sort_by is None or not data:
|
|
26
30
|
return data
|
|
@@ -31,8 +35,16 @@ def apply_sorting(
|
|
|
31
35
|
return data
|
|
32
36
|
|
|
33
37
|
try:
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
is_descending = sort_order != "asc" if sort_order else True
|
|
39
|
+
|
|
40
|
+
# Sort using the helper function that handles updated_at -> created_at fallback
|
|
41
|
+
sorted_records = sorted(
|
|
42
|
+
data,
|
|
43
|
+
key=lambda x: (get_sort_value(x, sort_by) is None, get_sort_value(x, sort_by)),
|
|
44
|
+
reverse=is_descending,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
return sorted_records
|
|
36
48
|
except Exception as e:
|
|
37
49
|
log_debug(f"Error sorting data by '{sort_by}': {e}")
|
|
38
50
|
return data
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import time
|
|
2
2
|
from copy import deepcopy
|
|
3
3
|
from datetime import date, datetime, timedelta, timezone
|
|
4
|
-
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
4
|
+
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple, Union
|
|
5
5
|
from uuid import uuid4
|
|
6
6
|
|
|
7
7
|
from agno.db.base import BaseDb, SessionType
|
|
@@ -20,6 +20,9 @@ from agno.db.schemas.memory import UserMemory
|
|
|
20
20
|
from agno.session import AgentSession, Session, TeamSession, WorkflowSession
|
|
21
21
|
from agno.utils.log import log_debug, log_error, log_info, log_warning
|
|
22
22
|
|
|
23
|
+
if TYPE_CHECKING:
|
|
24
|
+
from agno.tracing.schemas import Span, Trace
|
|
25
|
+
|
|
23
26
|
|
|
24
27
|
class InMemoryDb(BaseDb):
|
|
25
28
|
def __init__(self):
|
|
@@ -38,8 +41,15 @@ class InMemoryDb(BaseDb):
|
|
|
38
41
|
"""In-memory implementation, always returns True."""
|
|
39
42
|
return True
|
|
40
43
|
|
|
41
|
-
|
|
44
|
+
def get_latest_schema_version(self):
|
|
45
|
+
"""Get the latest version of the database schema."""
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
def upsert_schema_version(self, version: str) -> None:
|
|
49
|
+
"""Upsert the schema version into the database."""
|
|
50
|
+
pass
|
|
42
51
|
|
|
52
|
+
# -- Session methods --
|
|
43
53
|
def delete_session(self, session_id: str) -> bool:
|
|
44
54
|
"""Delete a session from in-memory storage.
|
|
45
55
|
|
|
@@ -513,13 +523,14 @@ class InMemoryDb(BaseDb):
|
|
|
513
523
|
raise e
|
|
514
524
|
|
|
515
525
|
def get_user_memory_stats(
|
|
516
|
-
self, limit: Optional[int] = None, page: Optional[int] = None
|
|
526
|
+
self, limit: Optional[int] = None, page: Optional[int] = None, user_id: Optional[str] = None
|
|
517
527
|
) -> Tuple[List[Dict[str, Any]], int]:
|
|
518
528
|
"""Get user memory statistics.
|
|
519
529
|
|
|
520
530
|
Args:
|
|
521
531
|
limit (Optional[int]): Maximum number of stats to return.
|
|
522
532
|
page (Optional[int]): Page number for pagination.
|
|
533
|
+
user_id (Optional[str]): User ID for filtering.
|
|
523
534
|
|
|
524
535
|
Returns:
|
|
525
536
|
Tuple[List[Dict[str, Any]], int]: List of user memory statistics and total count.
|
|
@@ -532,7 +543,9 @@ class InMemoryDb(BaseDb):
|
|
|
532
543
|
|
|
533
544
|
for memory in self._memories:
|
|
534
545
|
memory_user_id = memory.get("user_id")
|
|
535
|
-
|
|
546
|
+
# filter by user_id if provided
|
|
547
|
+
if user_id is not None and memory_user_id != user_id:
|
|
548
|
+
continue
|
|
536
549
|
if memory_user_id:
|
|
537
550
|
if memory_user_id not in user_stats:
|
|
538
551
|
user_stats[memory_user_id] = {
|
|
@@ -1158,3 +1171,189 @@ class InMemoryDb(BaseDb):
|
|
|
1158
1171
|
except Exception as e:
|
|
1159
1172
|
log_error(f"Error upserting cultural knowledge: {e}")
|
|
1160
1173
|
raise e
|
|
1174
|
+
|
|
1175
|
+
# --- Traces ---
|
|
1176
|
+
def upsert_trace(self, trace: "Trace") -> None:
|
|
1177
|
+
"""Create or update a single trace record in the database.
|
|
1178
|
+
|
|
1179
|
+
Args:
|
|
1180
|
+
trace: The Trace object to store (one per trace_id).
|
|
1181
|
+
"""
|
|
1182
|
+
raise NotImplementedError
|
|
1183
|
+
|
|
1184
|
+
def get_trace(
|
|
1185
|
+
self,
|
|
1186
|
+
trace_id: Optional[str] = None,
|
|
1187
|
+
run_id: Optional[str] = None,
|
|
1188
|
+
):
|
|
1189
|
+
"""Get a single trace by trace_id or other filters.
|
|
1190
|
+
|
|
1191
|
+
Args:
|
|
1192
|
+
trace_id: The unique trace identifier.
|
|
1193
|
+
run_id: Filter by run ID (returns first match).
|
|
1194
|
+
|
|
1195
|
+
Returns:
|
|
1196
|
+
Optional[Trace]: The trace if found, None otherwise.
|
|
1197
|
+
|
|
1198
|
+
Note:
|
|
1199
|
+
If multiple filters are provided, trace_id takes precedence.
|
|
1200
|
+
For other filters, the most recent trace is returned.
|
|
1201
|
+
"""
|
|
1202
|
+
raise NotImplementedError
|
|
1203
|
+
|
|
1204
|
+
def get_traces(
|
|
1205
|
+
self,
|
|
1206
|
+
run_id: Optional[str] = None,
|
|
1207
|
+
session_id: Optional[str] = None,
|
|
1208
|
+
user_id: Optional[str] = None,
|
|
1209
|
+
agent_id: Optional[str] = None,
|
|
1210
|
+
team_id: Optional[str] = None,
|
|
1211
|
+
workflow_id: Optional[str] = None,
|
|
1212
|
+
status: Optional[str] = None,
|
|
1213
|
+
start_time: Optional[datetime] = None,
|
|
1214
|
+
end_time: Optional[datetime] = None,
|
|
1215
|
+
limit: Optional[int] = 20,
|
|
1216
|
+
page: Optional[int] = 1,
|
|
1217
|
+
) -> tuple[List, int]:
|
|
1218
|
+
"""Get traces matching the provided filters.
|
|
1219
|
+
|
|
1220
|
+
Args:
|
|
1221
|
+
run_id: Filter by run ID.
|
|
1222
|
+
session_id: Filter by session ID.
|
|
1223
|
+
user_id: Filter by user ID.
|
|
1224
|
+
agent_id: Filter by agent ID.
|
|
1225
|
+
team_id: Filter by team ID.
|
|
1226
|
+
workflow_id: Filter by workflow ID.
|
|
1227
|
+
status: Filter by status (OK, ERROR, UNSET).
|
|
1228
|
+
start_time: Filter traces starting after this datetime.
|
|
1229
|
+
end_time: Filter traces ending before this datetime.
|
|
1230
|
+
limit: Maximum number of traces to return per page.
|
|
1231
|
+
page: Page number (1-indexed).
|
|
1232
|
+
|
|
1233
|
+
Returns:
|
|
1234
|
+
tuple[List[Trace], int]: Tuple of (list of matching traces, total count).
|
|
1235
|
+
"""
|
|
1236
|
+
raise NotImplementedError
|
|
1237
|
+
|
|
1238
|
+
def get_trace_stats(
|
|
1239
|
+
self,
|
|
1240
|
+
user_id: Optional[str] = None,
|
|
1241
|
+
agent_id: Optional[str] = None,
|
|
1242
|
+
team_id: Optional[str] = None,
|
|
1243
|
+
workflow_id: Optional[str] = None,
|
|
1244
|
+
start_time: Optional[datetime] = None,
|
|
1245
|
+
end_time: Optional[datetime] = None,
|
|
1246
|
+
limit: Optional[int] = 20,
|
|
1247
|
+
page: Optional[int] = 1,
|
|
1248
|
+
) -> tuple[List[Dict[str, Any]], int]:
|
|
1249
|
+
"""Get trace statistics grouped by session.
|
|
1250
|
+
|
|
1251
|
+
Args:
|
|
1252
|
+
user_id: Filter by user ID.
|
|
1253
|
+
agent_id: Filter by agent ID.
|
|
1254
|
+
team_id: Filter by team ID.
|
|
1255
|
+
workflow_id: Filter by workflow ID.
|
|
1256
|
+
start_time: Filter sessions with traces created after this datetime.
|
|
1257
|
+
end_time: Filter sessions with traces created before this datetime.
|
|
1258
|
+
limit: Maximum number of sessions to return per page.
|
|
1259
|
+
page: Page number (1-indexed).
|
|
1260
|
+
|
|
1261
|
+
Returns:
|
|
1262
|
+
tuple[List[Dict], int]: Tuple of (list of session stats dicts, total count).
|
|
1263
|
+
Each dict contains: session_id, user_id, agent_id, team_id, workflow_id, total_traces,
|
|
1264
|
+
first_trace_at, last_trace_at.
|
|
1265
|
+
"""
|
|
1266
|
+
raise NotImplementedError
|
|
1267
|
+
|
|
1268
|
+
# --- Spans ---
|
|
1269
|
+
def create_span(self, span: "Span") -> None:
|
|
1270
|
+
"""Create a single span in the database.
|
|
1271
|
+
|
|
1272
|
+
Args:
|
|
1273
|
+
span: The Span object to store.
|
|
1274
|
+
"""
|
|
1275
|
+
raise NotImplementedError
|
|
1276
|
+
|
|
1277
|
+
def create_spans(self, spans: List) -> None:
|
|
1278
|
+
"""Create multiple spans in the database as a batch.
|
|
1279
|
+
|
|
1280
|
+
Args:
|
|
1281
|
+
spans: List of Span objects to store.
|
|
1282
|
+
"""
|
|
1283
|
+
raise NotImplementedError
|
|
1284
|
+
|
|
1285
|
+
def get_span(self, span_id: str):
|
|
1286
|
+
"""Get a single span by its span_id.
|
|
1287
|
+
|
|
1288
|
+
Args:
|
|
1289
|
+
span_id: The unique span identifier.
|
|
1290
|
+
|
|
1291
|
+
Returns:
|
|
1292
|
+
Optional[Span]: The span if found, None otherwise.
|
|
1293
|
+
"""
|
|
1294
|
+
raise NotImplementedError
|
|
1295
|
+
|
|
1296
|
+
def get_spans(
|
|
1297
|
+
self,
|
|
1298
|
+
trace_id: Optional[str] = None,
|
|
1299
|
+
parent_span_id: Optional[str] = None,
|
|
1300
|
+
limit: Optional[int] = 1000,
|
|
1301
|
+
) -> List:
|
|
1302
|
+
"""Get spans matching the provided filters.
|
|
1303
|
+
|
|
1304
|
+
Args:
|
|
1305
|
+
trace_id: Filter by trace ID.
|
|
1306
|
+
parent_span_id: Filter by parent span ID.
|
|
1307
|
+
limit: Maximum number of spans to return.
|
|
1308
|
+
|
|
1309
|
+
Returns:
|
|
1310
|
+
List[Span]: List of matching spans.
|
|
1311
|
+
"""
|
|
1312
|
+
raise NotImplementedError
|
|
1313
|
+
|
|
1314
|
+
# -- Learning methods (stubs) --
|
|
1315
|
+
def get_learning(
|
|
1316
|
+
self,
|
|
1317
|
+
learning_type: str,
|
|
1318
|
+
user_id: Optional[str] = None,
|
|
1319
|
+
agent_id: Optional[str] = None,
|
|
1320
|
+
team_id: Optional[str] = None,
|
|
1321
|
+
session_id: Optional[str] = None,
|
|
1322
|
+
namespace: Optional[str] = None,
|
|
1323
|
+
entity_id: Optional[str] = None,
|
|
1324
|
+
entity_type: Optional[str] = None,
|
|
1325
|
+
) -> Optional[Dict[str, Any]]:
|
|
1326
|
+
raise NotImplementedError("Learning methods not yet implemented for InMemoryDb")
|
|
1327
|
+
|
|
1328
|
+
def upsert_learning(
|
|
1329
|
+
self,
|
|
1330
|
+
id: str,
|
|
1331
|
+
learning_type: str,
|
|
1332
|
+
content: Dict[str, Any],
|
|
1333
|
+
user_id: Optional[str] = None,
|
|
1334
|
+
agent_id: Optional[str] = None,
|
|
1335
|
+
team_id: Optional[str] = None,
|
|
1336
|
+
session_id: Optional[str] = None,
|
|
1337
|
+
namespace: Optional[str] = None,
|
|
1338
|
+
entity_id: Optional[str] = None,
|
|
1339
|
+
entity_type: Optional[str] = None,
|
|
1340
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
1341
|
+
) -> None:
|
|
1342
|
+
raise NotImplementedError("Learning methods not yet implemented for InMemoryDb")
|
|
1343
|
+
|
|
1344
|
+
def delete_learning(self, id: str) -> bool:
|
|
1345
|
+
raise NotImplementedError("Learning methods not yet implemented for InMemoryDb")
|
|
1346
|
+
|
|
1347
|
+
def get_learnings(
|
|
1348
|
+
self,
|
|
1349
|
+
learning_type: Optional[str] = None,
|
|
1350
|
+
user_id: Optional[str] = None,
|
|
1351
|
+
agent_id: Optional[str] = None,
|
|
1352
|
+
team_id: Optional[str] = None,
|
|
1353
|
+
session_id: Optional[str] = None,
|
|
1354
|
+
namespace: Optional[str] = None,
|
|
1355
|
+
entity_id: Optional[str] = None,
|
|
1356
|
+
entity_type: Optional[str] = None,
|
|
1357
|
+
limit: Optional[int] = None,
|
|
1358
|
+
) -> List[Dict[str, Any]]:
|
|
1359
|
+
raise NotImplementedError("Learning methods not yet implemented for InMemoryDb")
|
agno/db/in_memory/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 agno.db.schemas.culture import CulturalKnowledge
|
|
9
|
+
from agno.db.utils import get_sort_value
|
|
9
10
|
from agno.utils.log import log_debug
|
|
10
11
|
|
|
11
12
|
|
|
@@ -21,6 +22,9 @@ def apply_sorting(
|
|
|
21
22
|
|
|
22
23
|
Returns:
|
|
23
24
|
The sorted list
|
|
25
|
+
|
|
26
|
+
Note:
|
|
27
|
+
If sorting by "updated_at", will fallback to "created_at" in case of None.
|
|
24
28
|
"""
|
|
25
29
|
if sort_by is None or not data:
|
|
26
30
|
return data
|
|
@@ -31,8 +35,16 @@ def apply_sorting(
|
|
|
31
35
|
return data
|
|
32
36
|
|
|
33
37
|
try:
|
|
34
|
-
|
|
35
|
-
|
|
38
|
+
is_descending = sort_order != "asc" if sort_order else True
|
|
39
|
+
|
|
40
|
+
# Sort using the helper function that handles updated_at -> created_at fallback
|
|
41
|
+
sorted_records = sorted(
|
|
42
|
+
data,
|
|
43
|
+
key=lambda x: (get_sort_value(x, sort_by) is None, get_sort_value(x, sort_by)),
|
|
44
|
+
reverse=is_descending,
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
return sorted_records
|
|
36
48
|
except Exception as e:
|
|
37
49
|
log_debug(f"Error sorting data by '{sort_by}': {e}")
|
|
38
50
|
return data
|