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/utils/agent.py
CHANGED
|
@@ -1,14 +1,32 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
from asyncio import Future, Task
|
|
2
|
-
from typing import
|
|
3
|
+
from typing import (
|
|
4
|
+
TYPE_CHECKING,
|
|
5
|
+
Any,
|
|
6
|
+
AsyncIterator,
|
|
7
|
+
Awaitable,
|
|
8
|
+
Callable,
|
|
9
|
+
Dict,
|
|
10
|
+
Iterator,
|
|
11
|
+
List,
|
|
12
|
+
Optional,
|
|
13
|
+
Sequence,
|
|
14
|
+
Type,
|
|
15
|
+
Union,
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
from pydantic import BaseModel
|
|
3
19
|
|
|
4
20
|
from agno.media import Audio, File, Image, Video
|
|
5
21
|
from agno.models.message import Message
|
|
6
22
|
from agno.models.metrics import Metrics
|
|
7
23
|
from agno.models.response import ModelResponse
|
|
24
|
+
from agno.run import RunContext
|
|
8
25
|
from agno.run.agent import RunEvent, RunInput, RunOutput, RunOutputEvent
|
|
9
26
|
from agno.run.team import RunOutputEvent as TeamRunOutputEvent
|
|
10
27
|
from agno.run.team import TeamRunOutput
|
|
11
28
|
from agno.session import AgentSession, TeamSession, WorkflowSession
|
|
29
|
+
from agno.utils.common import is_typed_dict, validate_typed_dict
|
|
12
30
|
from agno.utils.events import (
|
|
13
31
|
create_memory_update_completed_event,
|
|
14
32
|
create_memory_update_started_event,
|
|
@@ -23,9 +41,10 @@ if TYPE_CHECKING:
|
|
|
23
41
|
from agno.team.team import Team
|
|
24
42
|
|
|
25
43
|
|
|
26
|
-
async def
|
|
44
|
+
async def await_for_open_threads(
|
|
27
45
|
memory_task: Optional[Task] = None,
|
|
28
46
|
cultural_knowledge_task: Optional[Task] = None,
|
|
47
|
+
learning_task: Optional[Task] = None,
|
|
29
48
|
) -> None:
|
|
30
49
|
if memory_task is not None:
|
|
31
50
|
try:
|
|
@@ -39,9 +58,17 @@ async def await_for_background_tasks(
|
|
|
39
58
|
except Exception as e:
|
|
40
59
|
log_warning(f"Error in cultural knowledge creation: {str(e)}")
|
|
41
60
|
|
|
61
|
+
if learning_task is not None:
|
|
62
|
+
try:
|
|
63
|
+
await learning_task
|
|
64
|
+
except Exception as e:
|
|
65
|
+
log_warning(f"Error in learning extraction: {str(e)}")
|
|
42
66
|
|
|
43
|
-
|
|
44
|
-
|
|
67
|
+
|
|
68
|
+
def wait_for_open_threads(
|
|
69
|
+
memory_future: Optional[Future] = None,
|
|
70
|
+
cultural_knowledge_future: Optional[Future] = None,
|
|
71
|
+
learning_future: Optional[Future] = None,
|
|
45
72
|
) -> None:
|
|
46
73
|
if memory_future is not None:
|
|
47
74
|
try:
|
|
@@ -56,14 +83,22 @@ def wait_for_background_tasks(
|
|
|
56
83
|
except Exception as e:
|
|
57
84
|
log_warning(f"Error in cultural knowledge creation: {str(e)}")
|
|
58
85
|
|
|
86
|
+
if learning_future is not None:
|
|
87
|
+
try:
|
|
88
|
+
learning_future.result()
|
|
89
|
+
except Exception as e:
|
|
90
|
+
log_warning(f"Error in learning extraction: {str(e)}")
|
|
59
91
|
|
|
60
|
-
|
|
92
|
+
|
|
93
|
+
async def await_for_thread_tasks_stream(
|
|
61
94
|
run_response: Union[RunOutput, TeamRunOutput],
|
|
62
95
|
memory_task: Optional[Task] = None,
|
|
63
96
|
cultural_knowledge_task: Optional[Task] = None,
|
|
97
|
+
learning_task: Optional[Task] = None,
|
|
64
98
|
stream_events: bool = False,
|
|
65
99
|
events_to_skip: Optional[List[RunEvent]] = None,
|
|
66
100
|
store_events: bool = False,
|
|
101
|
+
get_memories_callback: Optional[Callable[[], Union[Optional[List[Any]], Awaitable[Optional[List[Any]]]]]] = None,
|
|
67
102
|
) -> AsyncIterator[RunOutputEvent]:
|
|
68
103
|
if memory_task is not None:
|
|
69
104
|
if stream_events:
|
|
@@ -86,16 +121,29 @@ async def await_for_background_tasks_stream(
|
|
|
86
121
|
except Exception as e:
|
|
87
122
|
log_warning(f"Error in memory creation: {str(e)}")
|
|
88
123
|
if stream_events:
|
|
124
|
+
# Get memories after update if callback provided
|
|
125
|
+
memories = None
|
|
126
|
+
if get_memories_callback is not None:
|
|
127
|
+
try:
|
|
128
|
+
result = get_memories_callback()
|
|
129
|
+
# Handle both sync and async callbacks
|
|
130
|
+
if asyncio.iscoroutine(result):
|
|
131
|
+
memories = await result
|
|
132
|
+
else:
|
|
133
|
+
memories = result
|
|
134
|
+
except Exception as e:
|
|
135
|
+
log_warning(f"Error getting memories: {str(e)}")
|
|
136
|
+
|
|
89
137
|
if isinstance(run_response, TeamRunOutput):
|
|
90
138
|
yield handle_event( # type: ignore
|
|
91
|
-
create_team_memory_update_completed_event(from_run_response=run_response),
|
|
139
|
+
create_team_memory_update_completed_event(from_run_response=run_response, memories=memories),
|
|
92
140
|
run_response,
|
|
93
141
|
events_to_skip=events_to_skip, # type: ignore
|
|
94
142
|
store_events=store_events,
|
|
95
143
|
)
|
|
96
144
|
else:
|
|
97
145
|
yield handle_event( # type: ignore
|
|
98
|
-
create_memory_update_completed_event(from_run_response=run_response),
|
|
146
|
+
create_memory_update_completed_event(from_run_response=run_response, memories=memories),
|
|
99
147
|
run_response,
|
|
100
148
|
events_to_skip=events_to_skip, # type: ignore
|
|
101
149
|
store_events=store_events,
|
|
@@ -107,14 +155,22 @@ async def await_for_background_tasks_stream(
|
|
|
107
155
|
except Exception as e:
|
|
108
156
|
log_warning(f"Error in cultural knowledge creation: {str(e)}")
|
|
109
157
|
|
|
158
|
+
if learning_task is not None:
|
|
159
|
+
try:
|
|
160
|
+
await learning_task
|
|
161
|
+
except Exception as e:
|
|
162
|
+
log_warning(f"Error in learning extraction: {str(e)}")
|
|
163
|
+
|
|
110
164
|
|
|
111
|
-
def
|
|
165
|
+
def wait_for_thread_tasks_stream(
|
|
112
166
|
run_response: Union[TeamRunOutput, RunOutput],
|
|
113
167
|
memory_future: Optional[Future] = None,
|
|
114
168
|
cultural_knowledge_future: Optional[Future] = None,
|
|
169
|
+
learning_future: Optional[Future] = None,
|
|
115
170
|
stream_events: bool = False,
|
|
116
171
|
events_to_skip: Optional[List[RunEvent]] = None,
|
|
117
172
|
store_events: bool = False,
|
|
173
|
+
get_memories_callback: Optional[Callable[[], Optional[List[Any]]]] = None,
|
|
118
174
|
) -> Iterator[Union[RunOutputEvent, TeamRunOutputEvent]]:
|
|
119
175
|
if memory_future is not None:
|
|
120
176
|
if stream_events:
|
|
@@ -137,16 +193,24 @@ def wait_for_background_tasks_stream(
|
|
|
137
193
|
except Exception as e:
|
|
138
194
|
log_warning(f"Error in memory creation: {str(e)}")
|
|
139
195
|
if stream_events:
|
|
196
|
+
# Get memories after update if callback provided
|
|
197
|
+
memories = None
|
|
198
|
+
if get_memories_callback is not None:
|
|
199
|
+
try:
|
|
200
|
+
memories = get_memories_callback()
|
|
201
|
+
except Exception as e:
|
|
202
|
+
log_warning(f"Error getting memories: {str(e)}")
|
|
203
|
+
|
|
140
204
|
if isinstance(run_response, TeamRunOutput):
|
|
141
205
|
yield handle_event( # type: ignore
|
|
142
|
-
create_team_memory_update_completed_event(from_run_response=run_response),
|
|
206
|
+
create_team_memory_update_completed_event(from_run_response=run_response, memories=memories),
|
|
143
207
|
run_response,
|
|
144
208
|
events_to_skip=events_to_skip, # type: ignore
|
|
145
209
|
store_events=store_events,
|
|
146
210
|
)
|
|
147
211
|
else:
|
|
148
212
|
yield handle_event( # type: ignore
|
|
149
|
-
create_memory_update_completed_event(from_run_response=run_response),
|
|
213
|
+
create_memory_update_completed_event(from_run_response=run_response, memories=memories),
|
|
150
214
|
run_response,
|
|
151
215
|
events_to_skip=events_to_skip, # type: ignore
|
|
152
216
|
store_events=store_events,
|
|
@@ -160,6 +224,12 @@ def wait_for_background_tasks_stream(
|
|
|
160
224
|
except Exception as e:
|
|
161
225
|
log_warning(f"Error in cultural knowledge creation: {str(e)}")
|
|
162
226
|
|
|
227
|
+
if learning_future is not None:
|
|
228
|
+
try:
|
|
229
|
+
learning_future.result()
|
|
230
|
+
except Exception as e:
|
|
231
|
+
log_warning(f"Error in learning extraction: {str(e)}")
|
|
232
|
+
|
|
163
233
|
|
|
164
234
|
def collect_joint_images(
|
|
165
235
|
run_input: Optional[RunInput] = None,
|
|
@@ -818,3 +888,174 @@ async def aget_chat_history_util(entity: Union["Agent", "Team"], session_id: str
|
|
|
818
888
|
raise Exception("Session not found")
|
|
819
889
|
|
|
820
890
|
return session.get_chat_history() # type: ignore
|
|
891
|
+
|
|
892
|
+
|
|
893
|
+
def execute_instructions(
|
|
894
|
+
instructions: Callable,
|
|
895
|
+
agent: Optional[Union["Agent", "Team"]] = None,
|
|
896
|
+
team: Optional["Team"] = None,
|
|
897
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
898
|
+
run_context: Optional[RunContext] = None,
|
|
899
|
+
) -> Union[str, List[str]]:
|
|
900
|
+
"""Execute the instructions function."""
|
|
901
|
+
import inspect
|
|
902
|
+
|
|
903
|
+
signature = inspect.signature(instructions)
|
|
904
|
+
instruction_args: Dict[str, Any] = {}
|
|
905
|
+
|
|
906
|
+
# Check for agent parameter
|
|
907
|
+
if "agent" in signature.parameters:
|
|
908
|
+
instruction_args["agent"] = agent
|
|
909
|
+
|
|
910
|
+
if "team" in signature.parameters:
|
|
911
|
+
instruction_args["team"] = team
|
|
912
|
+
|
|
913
|
+
# Check for session_state parameter
|
|
914
|
+
if "session_state" in signature.parameters:
|
|
915
|
+
instruction_args["session_state"] = session_state if session_state is not None else {}
|
|
916
|
+
|
|
917
|
+
# Check for run_context parameter
|
|
918
|
+
if "run_context" in signature.parameters:
|
|
919
|
+
instruction_args["run_context"] = run_context or None
|
|
920
|
+
|
|
921
|
+
# Run the instructions function, await if it's awaitable, otherwise run directly (in thread)
|
|
922
|
+
if inspect.iscoroutinefunction(instructions):
|
|
923
|
+
raise Exception("Instructions function is async, use `agent.arun()` instead")
|
|
924
|
+
|
|
925
|
+
# Run the instructions function
|
|
926
|
+
return instructions(**instruction_args)
|
|
927
|
+
|
|
928
|
+
|
|
929
|
+
def execute_system_message(
|
|
930
|
+
system_message: Callable,
|
|
931
|
+
agent: Optional[Union["Agent", "Team"]] = None,
|
|
932
|
+
team: Optional["Team"] = None,
|
|
933
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
934
|
+
run_context: Optional[RunContext] = None,
|
|
935
|
+
) -> str:
|
|
936
|
+
"""Execute the system message function."""
|
|
937
|
+
import inspect
|
|
938
|
+
|
|
939
|
+
signature = inspect.signature(system_message)
|
|
940
|
+
system_message_args: Dict[str, Any] = {}
|
|
941
|
+
|
|
942
|
+
# Check for agent parameter
|
|
943
|
+
if "agent" in signature.parameters:
|
|
944
|
+
system_message_args["agent"] = agent
|
|
945
|
+
if "team" in signature.parameters:
|
|
946
|
+
system_message_args["team"] = team
|
|
947
|
+
if inspect.iscoroutinefunction(system_message):
|
|
948
|
+
raise ValueError("System message function is async, use `agent.arun()` instead")
|
|
949
|
+
|
|
950
|
+
return system_message(**system_message_args)
|
|
951
|
+
|
|
952
|
+
|
|
953
|
+
async def aexecute_instructions(
|
|
954
|
+
instructions: Callable,
|
|
955
|
+
agent: Optional[Union["Agent", "Team"]] = None,
|
|
956
|
+
team: Optional["Team"] = None,
|
|
957
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
958
|
+
run_context: Optional[RunContext] = None,
|
|
959
|
+
) -> Union[str, List[str]]:
|
|
960
|
+
"""Execute the instructions function."""
|
|
961
|
+
import inspect
|
|
962
|
+
|
|
963
|
+
signature = inspect.signature(instructions)
|
|
964
|
+
instruction_args: Dict[str, Any] = {}
|
|
965
|
+
|
|
966
|
+
# Check for agent parameter
|
|
967
|
+
if "agent" in signature.parameters:
|
|
968
|
+
instruction_args["agent"] = agent
|
|
969
|
+
if "team" in signature.parameters:
|
|
970
|
+
instruction_args["team"] = team
|
|
971
|
+
|
|
972
|
+
# Check for session_state parameter
|
|
973
|
+
if "session_state" in signature.parameters:
|
|
974
|
+
instruction_args["session_state"] = session_state if session_state is not None else {}
|
|
975
|
+
|
|
976
|
+
# Check for run_context parameter
|
|
977
|
+
if "run_context" in signature.parameters:
|
|
978
|
+
instruction_args["run_context"] = run_context or None
|
|
979
|
+
|
|
980
|
+
if inspect.iscoroutinefunction(instructions):
|
|
981
|
+
return await instructions(**instruction_args)
|
|
982
|
+
else:
|
|
983
|
+
return instructions(**instruction_args)
|
|
984
|
+
|
|
985
|
+
|
|
986
|
+
async def aexecute_system_message(
|
|
987
|
+
system_message: Callable,
|
|
988
|
+
agent: Optional[Union["Agent", "Team"]] = None,
|
|
989
|
+
team: Optional["Team"] = None,
|
|
990
|
+
session_state: Optional[Dict[str, Any]] = None,
|
|
991
|
+
run_context: Optional[RunContext] = None,
|
|
992
|
+
) -> str:
|
|
993
|
+
import inspect
|
|
994
|
+
|
|
995
|
+
signature = inspect.signature(system_message)
|
|
996
|
+
system_message_args: Dict[str, Any] = {}
|
|
997
|
+
|
|
998
|
+
# Check for agent parameter
|
|
999
|
+
if "agent" in signature.parameters:
|
|
1000
|
+
system_message_args["agent"] = agent
|
|
1001
|
+
if "team" in signature.parameters:
|
|
1002
|
+
system_message_args["team"] = team
|
|
1003
|
+
|
|
1004
|
+
if inspect.iscoroutinefunction(system_message):
|
|
1005
|
+
return await system_message(**system_message_args)
|
|
1006
|
+
else:
|
|
1007
|
+
return system_message(**system_message_args)
|
|
1008
|
+
|
|
1009
|
+
|
|
1010
|
+
def validate_input(
|
|
1011
|
+
input: Union[str, List, Dict, Message, BaseModel], input_schema: Optional[Type[BaseModel]] = None
|
|
1012
|
+
) -> Union[str, List, Dict, Message, BaseModel]:
|
|
1013
|
+
"""Parse and validate input against input_schema if provided, otherwise return input as-is"""
|
|
1014
|
+
if input_schema is None:
|
|
1015
|
+
return input # Return input unchanged if no schema is set
|
|
1016
|
+
|
|
1017
|
+
if input is None:
|
|
1018
|
+
raise ValueError("Input required when input_schema is set")
|
|
1019
|
+
|
|
1020
|
+
# Handle Message objects - extract content
|
|
1021
|
+
if isinstance(input, Message):
|
|
1022
|
+
input = input.content # type: ignore
|
|
1023
|
+
|
|
1024
|
+
# If input is a string, convert it to a dict
|
|
1025
|
+
if isinstance(input, str):
|
|
1026
|
+
import json
|
|
1027
|
+
|
|
1028
|
+
try:
|
|
1029
|
+
input = json.loads(input)
|
|
1030
|
+
except Exception as e:
|
|
1031
|
+
raise ValueError(f"Failed to parse input. Is it a valid JSON string?: {e}")
|
|
1032
|
+
|
|
1033
|
+
# Case 1: Message is already a BaseModel instance
|
|
1034
|
+
if isinstance(input, BaseModel):
|
|
1035
|
+
if isinstance(input, input_schema):
|
|
1036
|
+
try:
|
|
1037
|
+
return input
|
|
1038
|
+
except Exception as e:
|
|
1039
|
+
raise ValueError(f"BaseModel validation failed: {str(e)}")
|
|
1040
|
+
else:
|
|
1041
|
+
# Different BaseModel types
|
|
1042
|
+
raise ValueError(f"Expected {input_schema.__name__} but got {type(input).__name__}")
|
|
1043
|
+
|
|
1044
|
+
# Case 2: Message is a dict
|
|
1045
|
+
elif isinstance(input, dict):
|
|
1046
|
+
try:
|
|
1047
|
+
# Check if the schema is a TypedDict
|
|
1048
|
+
if is_typed_dict(input_schema):
|
|
1049
|
+
validated_dict = validate_typed_dict(input, input_schema)
|
|
1050
|
+
return validated_dict
|
|
1051
|
+
else:
|
|
1052
|
+
validated_model = input_schema(**input)
|
|
1053
|
+
return validated_model
|
|
1054
|
+
except Exception as e:
|
|
1055
|
+
raise ValueError(f"Failed to parse dict into {input_schema.__name__}: {str(e)}")
|
|
1056
|
+
|
|
1057
|
+
# Case 3: Other types not supported for structured input
|
|
1058
|
+
else:
|
|
1059
|
+
raise ValueError(
|
|
1060
|
+
f"Cannot validate {type(input)} against input_schema. Expected dict or {input_schema.__name__} instance."
|
|
1061
|
+
)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
from cryptography.hazmat.primitives import serialization
|
|
2
|
+
from cryptography.hazmat.primitives.asymmetric import rsa
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def generate_rsa_keys():
|
|
6
|
+
"""Generate RSA key pair for RS256 JWT signing/verification."""
|
|
7
|
+
private_key = rsa.generate_private_key(public_exponent=65537, key_size=2048)
|
|
8
|
+
|
|
9
|
+
# Private key PEM (used by auth server to sign tokens)
|
|
10
|
+
private_pem = private_key.private_bytes(
|
|
11
|
+
encoding=serialization.Encoding.PEM,
|
|
12
|
+
format=serialization.PrivateFormat.PKCS8,
|
|
13
|
+
encryption_algorithm=serialization.NoEncryption(),
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# Public key PEM (used by AgentOS to verify tokens)
|
|
17
|
+
public_pem = private_key.public_key().public_bytes(
|
|
18
|
+
encoding=serialization.Encoding.PEM,
|
|
19
|
+
format=serialization.PublicFormat.SubjectPublicKeyInfo,
|
|
20
|
+
)
|
|
21
|
+
|
|
22
|
+
return private_pem.decode("utf-8"), public_pem.decode("utf-8")
|
agno/utils/dttm.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
from datetime import datetime, timezone
|
|
2
|
+
from typing import Union
|
|
2
3
|
|
|
3
4
|
|
|
4
5
|
def current_datetime() -> datetime:
|
|
@@ -11,3 +12,35 @@ def current_datetime_utc() -> datetime:
|
|
|
11
12
|
|
|
12
13
|
def current_datetime_utc_str() -> str:
|
|
13
14
|
return current_datetime_utc().strftime("%Y-%m-%dT%H:%M:%S")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def now_epoch_s() -> int:
|
|
18
|
+
return int(datetime.now(timezone.utc).timestamp())
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def to_epoch_s(value: Union[int, float, str, datetime]) -> int:
|
|
22
|
+
"""Normalize various datetime representations to epoch seconds (UTC)."""
|
|
23
|
+
|
|
24
|
+
if isinstance(value, (int, float)):
|
|
25
|
+
# assume value is already in seconds
|
|
26
|
+
return int(value)
|
|
27
|
+
|
|
28
|
+
if isinstance(value, datetime):
|
|
29
|
+
dt = value
|
|
30
|
+
if dt.tzinfo is None:
|
|
31
|
+
dt = dt.replace(tzinfo=timezone.utc)
|
|
32
|
+
return int(dt.timestamp())
|
|
33
|
+
|
|
34
|
+
if isinstance(value, str):
|
|
35
|
+
s = value.strip()
|
|
36
|
+
if s.endswith("Z"):
|
|
37
|
+
s = s[:-1] + "+00:00"
|
|
38
|
+
try:
|
|
39
|
+
dt = datetime.fromisoformat(s)
|
|
40
|
+
except ValueError as e:
|
|
41
|
+
raise ValueError(f"Unsupported datetime string: {value!r}") from e
|
|
42
|
+
if dt.tzinfo is None:
|
|
43
|
+
dt = dt.replace(tzinfo=timezone.utc)
|
|
44
|
+
return int(dt.timestamp())
|
|
45
|
+
|
|
46
|
+
raise TypeError(f"Unsupported datetime value: {type(value)}")
|