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/redis/utils.py
CHANGED
|
@@ -3,14 +3,15 @@
|
|
|
3
3
|
import json
|
|
4
4
|
import time
|
|
5
5
|
from datetime import date, datetime, timedelta, timezone
|
|
6
|
-
from typing import Any, Dict, List, Optional
|
|
6
|
+
from typing import Any, Dict, List, Optional, Union
|
|
7
7
|
from uuid import UUID
|
|
8
8
|
|
|
9
9
|
from agno.db.schemas.culture import CulturalKnowledge
|
|
10
|
+
from agno.db.utils import get_sort_value
|
|
10
11
|
from agno.utils.log import log_warning
|
|
11
12
|
|
|
12
13
|
try:
|
|
13
|
-
from redis import Redis
|
|
14
|
+
from redis import Redis, RedisCluster
|
|
14
15
|
except ImportError:
|
|
15
16
|
raise ImportError("`redis` not installed. Please install it using `pip install redis`")
|
|
16
17
|
|
|
@@ -51,7 +52,7 @@ def generate_index_key(prefix: str, table_type: str, index_field: str, index_val
|
|
|
51
52
|
return f"{prefix}:{table_type}:index:{index_field}:{index_value}"
|
|
52
53
|
|
|
53
54
|
|
|
54
|
-
def get_all_keys_for_table(redis_client: Redis, prefix: str, table_type: str) -> List[str]:
|
|
55
|
+
def get_all_keys_for_table(redis_client: Union[Redis, RedisCluster], prefix: str, table_type: str) -> List[str]:
|
|
55
56
|
"""Get all relevant keys for the given table type.
|
|
56
57
|
|
|
57
58
|
Args:
|
|
@@ -80,21 +81,36 @@ def get_all_keys_for_table(redis_client: Redis, prefix: str, table_type: str) ->
|
|
|
80
81
|
def apply_sorting(
|
|
81
82
|
records: List[Dict[str, Any]], sort_by: Optional[str] = None, sort_order: Optional[str] = None
|
|
82
83
|
) -> List[Dict[str, Any]]:
|
|
83
|
-
|
|
84
|
-
|
|
84
|
+
"""Apply sorting to the given records list.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
records: The list of dictionaries to sort
|
|
88
|
+
sort_by: The field to sort by
|
|
89
|
+
sort_order: The sort order ('asc' or 'desc')
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
The sorted list
|
|
85
93
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
return
|
|
94
|
+
Note:
|
|
95
|
+
If sorting by "updated_at", will fallback to "created_at" in case of None.
|
|
96
|
+
"""
|
|
97
|
+
if sort_by is None or not records:
|
|
98
|
+
return records
|
|
91
99
|
|
|
92
100
|
try:
|
|
93
|
-
|
|
94
|
-
|
|
101
|
+
is_descending = sort_order == "desc"
|
|
102
|
+
|
|
103
|
+
# Sort using the helper function that handles updated_at -> created_at fallback
|
|
104
|
+
sorted_records = sorted(
|
|
105
|
+
records,
|
|
106
|
+
key=lambda x: (get_sort_value(x, sort_by) is None, get_sort_value(x, sort_by)),
|
|
107
|
+
reverse=is_descending,
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
return sorted_records
|
|
95
111
|
|
|
96
112
|
except Exception as e:
|
|
97
|
-
log_warning(f"Error sorting
|
|
113
|
+
log_warning(f"Error sorting Redis records: {e}")
|
|
98
114
|
return records
|
|
99
115
|
|
|
100
116
|
|
|
@@ -130,7 +146,7 @@ def apply_filters(records: List[Dict[str, Any]], conditions: Dict[str, Any]) ->
|
|
|
130
146
|
|
|
131
147
|
|
|
132
148
|
def create_index_entries(
|
|
133
|
-
redis_client: Redis,
|
|
149
|
+
redis_client: Union[Redis, RedisCluster],
|
|
134
150
|
prefix: str,
|
|
135
151
|
table_type: str,
|
|
136
152
|
record_id: str,
|
|
@@ -144,7 +160,7 @@ def create_index_entries(
|
|
|
144
160
|
|
|
145
161
|
|
|
146
162
|
def remove_index_entries(
|
|
147
|
-
redis_client: Redis,
|
|
163
|
+
redis_client: Union[Redis, RedisCluster],
|
|
148
164
|
prefix: str,
|
|
149
165
|
table_type: str,
|
|
150
166
|
record_id: str,
|
agno/db/schemas/evals.py
CHANGED
agno/db/schemas/memory.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
|
-
from datetime import datetime
|
|
2
|
+
from datetime import datetime
|
|
3
3
|
from typing import Any, Dict, List, Optional
|
|
4
4
|
|
|
5
|
+
from agno.utils.dttm import now_epoch_s, to_epoch_s
|
|
6
|
+
|
|
5
7
|
|
|
6
8
|
@dataclass
|
|
7
9
|
class UserMemory:
|
|
@@ -12,18 +14,28 @@ class UserMemory:
|
|
|
12
14
|
topics: Optional[List[str]] = None
|
|
13
15
|
user_id: Optional[str] = None
|
|
14
16
|
input: Optional[str] = None
|
|
15
|
-
|
|
17
|
+
created_at: Optional[int] = None
|
|
18
|
+
updated_at: Optional[int] = None
|
|
16
19
|
feedback: Optional[str] = None
|
|
17
20
|
|
|
18
21
|
agent_id: Optional[str] = None
|
|
19
22
|
team_id: Optional[str] = None
|
|
20
23
|
|
|
24
|
+
def __post_init__(self) -> None:
|
|
25
|
+
"""Automatically set/normalize created_at and updated_at."""
|
|
26
|
+
self.created_at = now_epoch_s() if self.created_at is None else to_epoch_s(self.created_at)
|
|
27
|
+
if self.updated_at is not None:
|
|
28
|
+
self.updated_at = to_epoch_s(self.updated_at)
|
|
29
|
+
|
|
21
30
|
def to_dict(self) -> Dict[str, Any]:
|
|
31
|
+
created_at = datetime.fromtimestamp(self.created_at).isoformat() if self.created_at is not None else None
|
|
32
|
+
updated_at = datetime.fromtimestamp(self.updated_at).isoformat() if self.updated_at is not None else created_at
|
|
22
33
|
_dict = {
|
|
23
34
|
"memory_id": self.memory_id,
|
|
24
35
|
"memory": self.memory,
|
|
25
36
|
"topics": self.topics,
|
|
26
|
-
"
|
|
37
|
+
"created_at": created_at,
|
|
38
|
+
"updated_at": updated_at,
|
|
27
39
|
"input": self.input,
|
|
28
40
|
"user_id": self.user_id,
|
|
29
41
|
"agent_id": self.agent_id,
|
|
@@ -36,11 +48,10 @@ class UserMemory:
|
|
|
36
48
|
def from_dict(cls, data: Dict[str, Any]) -> "UserMemory":
|
|
37
49
|
data = dict(data)
|
|
38
50
|
|
|
39
|
-
#
|
|
40
|
-
if
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
data["updated_at"] = datetime.fromisoformat(updated_at)
|
|
51
|
+
# Preserve 0 and None explicitly; only process if key exists
|
|
52
|
+
if "created_at" in data and data["created_at"] is not None:
|
|
53
|
+
data["created_at"] = to_epoch_s(data["created_at"])
|
|
54
|
+
if "updated_at" in data and data["updated_at"] is not None:
|
|
55
|
+
data["updated_at"] = to_epoch_s(data["updated_at"])
|
|
45
56
|
|
|
46
57
|
return cls(**data)
|
agno/db/singlestore/schemas.py
CHANGED
|
@@ -39,6 +39,8 @@ USER_MEMORY_TABLE_SCHEMA = {
|
|
|
39
39
|
"team_id": {"type": lambda: String(128), "nullable": True},
|
|
40
40
|
"user_id": {"type": lambda: String(128), "nullable": True, "index": True},
|
|
41
41
|
"topics": {"type": JSON, "nullable": True},
|
|
42
|
+
"feedback": {"type": Text, "nullable": True},
|
|
43
|
+
"created_at": {"type": BigInteger, "nullable": False, "index": True},
|
|
42
44
|
"updated_at": {"type": BigInteger, "nullable": True, "index": True},
|
|
43
45
|
}
|
|
44
46
|
|
|
@@ -106,14 +108,79 @@ CULTURAL_KNOWLEDGE_TABLE_SCHEMA = {
|
|
|
106
108
|
}
|
|
107
109
|
|
|
108
110
|
|
|
109
|
-
|
|
111
|
+
VERSIONS_TABLE_SCHEMA = {
|
|
112
|
+
"table_name": {"type": lambda: String(128), "nullable": False, "primary_key": True},
|
|
113
|
+
"version": {"type": lambda: String(10), "nullable": False},
|
|
114
|
+
"created_at": {"type": lambda: String(128), "nullable": False, "index": True},
|
|
115
|
+
"updated_at": {"type": lambda: String(128), "nullable": True},
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
TRACE_TABLE_SCHEMA = {
|
|
119
|
+
"trace_id": {"type": lambda: String(128), "primary_key": True, "nullable": False},
|
|
120
|
+
"name": {"type": lambda: String(512), "nullable": False},
|
|
121
|
+
"status": {"type": lambda: String(20), "nullable": False, "index": True},
|
|
122
|
+
"start_time": {"type": lambda: String(64), "nullable": False, "index": True}, # ISO 8601 datetime string
|
|
123
|
+
"end_time": {"type": lambda: String(64), "nullable": False}, # ISO 8601 datetime string
|
|
124
|
+
"duration_ms": {"type": BigInteger, "nullable": False},
|
|
125
|
+
"run_id": {"type": lambda: String(128), "nullable": True, "index": True},
|
|
126
|
+
"session_id": {"type": lambda: String(128), "nullable": True, "index": True},
|
|
127
|
+
"user_id": {"type": lambda: String(128), "nullable": True, "index": True},
|
|
128
|
+
"agent_id": {"type": lambda: String(128), "nullable": True, "index": True},
|
|
129
|
+
"team_id": {"type": lambda: String(128), "nullable": True, "index": True},
|
|
130
|
+
"workflow_id": {"type": lambda: String(128), "nullable": True, "index": True},
|
|
131
|
+
"created_at": {"type": lambda: String(64), "nullable": False, "index": True}, # ISO 8601 datetime string
|
|
132
|
+
}
|
|
133
|
+
|
|
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
|
+
}
|
|
164
|
+
|
|
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]:
|
|
110
169
|
"""
|
|
111
170
|
Get the expected schema definition for the given table.
|
|
171
|
+
|
|
112
172
|
Args:
|
|
113
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
|
+
|
|
114
177
|
Returns:
|
|
115
178
|
Dict[str, Any]: Dictionary containing column definitions for the table
|
|
116
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
|
+
|
|
117
184
|
schemas = {
|
|
118
185
|
"sessions": SESSION_TABLE_SCHEMA,
|
|
119
186
|
"evals": EVAL_TABLE_SCHEMA,
|
|
@@ -121,6 +188,8 @@ def get_table_schema_definition(table_type: str) -> dict[str, Any]:
|
|
|
121
188
|
"memories": USER_MEMORY_TABLE_SCHEMA,
|
|
122
189
|
"knowledge": KNOWLEDGE_TABLE_SCHEMA,
|
|
123
190
|
"culture": CULTURAL_KNOWLEDGE_TABLE_SCHEMA,
|
|
191
|
+
"versions": VERSIONS_TABLE_SCHEMA,
|
|
192
|
+
"traces": TRACE_TABLE_SCHEMA,
|
|
124
193
|
}
|
|
125
194
|
schema = schemas.get(table_type, {})
|
|
126
195
|
|