agentkernel 0.8.0__tar.gz → 0.8.1__tar.gz
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.
- {agentkernel-0.8.0 → agentkernel-0.8.1}/PKG-INFO +1 -1
- {agentkernel-0.8.0 → agentkernel-0.8.1}/pyproject.toml +1 -1
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/cli/cli.py +28 -2
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/base.py +134 -1
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/framework/adk/adk.py +89 -36
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/framework/crewai/crewai.py +8 -6
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/framework/langgraph/langgraph.py +33 -2
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/framework/openai/openai.py +20 -8
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/framework/pydanticai/pydanticai.py +20 -2
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/framework/smolagents/smolagents.py +14 -1
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/skills/ak-add-capabilities/SKILL.md +58 -23
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/skills/ak-add-capabilities/evals/evals.json +16 -1
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/skills/ak-add-integration/SKILL.md +8 -8
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/skills/ak-add-integration/evals/evals.json +1 -1
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/skills/ak-build/SKILL.md +1 -1
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/skills/ak-build/evals/evals.json +1 -1
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/skills/ak-cloud-deploy/SKILL.md +19 -19
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/skills/ak-cloud-deploy/evals/evals.json +1 -1
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/skills/ak-init/SKILL.md +2 -2
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/skills/ak-init/evals/evals.json +2 -2
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/skills/ak-test/SKILL.md +2 -2
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/skills/ak-test/evals/evals.json +1 -1
- agentkernel-0.8.1/src/agentkernel/trace/langfuse/langgraph.py +49 -0
- agentkernel-0.8.0/src/agentkernel/trace/langfuse/langgraph.py +0 -70
- {agentkernel-0.8.0 → agentkernel-0.8.1}/README.md +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/adk.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/api/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/api/a2a/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/api/a2a/a2a.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/api/a2a/handler.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/api/handler.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/api/http.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/api/mcp/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/api/mcp/akmcp.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/api/thread.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/auth/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/auth/handler.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/auth.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/aws.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/azure.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/cli/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/cli/ak.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/builder.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/chat_service.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/config.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/hooks.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/logger.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/model.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/module.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/multimodal/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/multimodal/factory.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/multimodal/hooks.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/multimodal/storage/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/multimodal/storage/base.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/multimodal/storage/dynamodb.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/multimodal/storage/in_memory.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/multimodal/storage/redis.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/multimodal/storage/session_cache.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/multimodal/storage/storage_manager.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/multimodal/tools.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/runtime.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/service.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/session/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/session/base.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/session/cosmosdb.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/session/dynamodb.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/session/firestore.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/session/in_memory.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/session/redis.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/session/serde.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/session/valkey.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/thread/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/thread/authoriser.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/thread/manager.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/thread/model.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/thread/naming.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/thread/store/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/thread/store/base.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/thread/store/cosmosdb.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/thread/store/dynamodb.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/thread/store/firestore.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/thread/store/in_memory.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/thread/store/redis.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/tool.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/util/config_yaml_util.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/util/driver/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/util/driver/base.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/util/driver/cosmosdb.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/util/driver/dynamodb.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/util/driver/firestore.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/util/driver/redis.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/util/driver/redis_like.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/util/driver/valkey.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/util/error_util.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/util/factory.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/core/util/key_value_cache.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/crewai.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/containerized/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/containerized/akagentrunner.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/containerized/akoutputconsumer.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/containerized/core/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/containerized/core/sqs_consumer.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/containerized/ecs_io_handler.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/containerized/ecs_queue_handler.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/core/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/core/response_store/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/core/response_store/dynamodb.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/core/response_store/handler.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/core/response_store/redis.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/core/response_store/valkey.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/core/sqs_handler.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/core/websocket_service.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/serverless/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/serverless/akagentrunner.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/serverless/akauthorizer.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/serverless/aklambda.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/serverless/akresponsehandler.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/serverless/akwsconnectionhandler.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/serverless/core/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/serverless/core/router/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/serverless/core/router/common.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/serverless/core/router/rest_lambda.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/serverless/core/router/ws_lambda.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/aws/serverless/core/sqs_consumer.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/azure/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/azure/akfunction.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/common/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/common/queue_consumer.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/common/queue_handler.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/common/queue_request_handler.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/common/response_store.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/common/thread_runner.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/common/websocket_connection_store.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/gcp/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/gcp/akauthorizer.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/deployment/gcp/akcloudrun.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/framework/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/framework/adk/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/framework/crewai/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/framework/langgraph/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/framework/openai/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/framework/pydanticai/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/framework/smolagents/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/gcp.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/gmail.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/guardrail/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/guardrail/bedrock.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/guardrail/guardrail.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/guardrail/openai.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/guardrail/walledai.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/instagram.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/gmail/README.md +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/gmail/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/gmail/gmail_chat.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/instagram/README.md +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/instagram/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/instagram/instagram_chat.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/messenger/README.md +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/messenger/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/messenger/messenger_chat.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/slack/README.md +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/slack/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/slack/slack_chat.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/teams/README.md +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/teams/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/teams/teams_chat.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/telegram/README.md +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/telegram/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/telegram/telegram_chat.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/whatsapp/README.md +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/whatsapp/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/integration/whatsapp/whatsapp_chat.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/knowledgebase/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/knowledgebase/base.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/knowledgebase/chroma.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/knowledgebase/knowledgebuilder.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/knowledgebase/neo4j.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/knowledgebase/starburst.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/langgraph.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/mcp.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/messenger.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/openai.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/pydanticai.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/base.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/broker/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/broker/base.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/broker/embedded.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/broker/thread.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/broker/worker.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/errors.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/factory.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/hooks.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/manager.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/model.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/principal.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/providers/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/providers/daytona.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/providers/docker.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/providers/e2b.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/providers/ec2_ssm.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/providers/local_subprocess.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/testing.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/sandbox/tools.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/skills/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/skills/skills.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/slack.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/smolagents.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/teams.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/telegram.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/test/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/test/config.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/test/test.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/base.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/langfuse/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/langfuse/adk.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/langfuse/crewai.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/langfuse/langfuse.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/langfuse/openai.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/langfuse/pydanticai.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/langfuse/smolagents.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/logfire/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/logfire/adk.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/logfire/crewai.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/logfire/langgraph.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/logfire/logfire.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/logfire/openai.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/logfire/pydanticai.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/logfire/smolagents.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/openllmetry/__init__.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/openllmetry/adk.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/openllmetry/crewai.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/openllmetry/langgraph.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/openllmetry/openai.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/openllmetry/openllmetry.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/openllmetry/pydanticai.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/openllmetry/smolagents.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/trace/trace.py +0 -0
- {agentkernel-0.8.0 → agentkernel-0.8.1}/src/agentkernel/whatsapp.py +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import logging
|
|
3
3
|
import readline # Enables line editing and history features for input() in the CLI
|
|
4
|
+
import threading
|
|
4
5
|
|
|
5
6
|
from ..core import AgentService
|
|
6
|
-
from ..core.config import AKConfig
|
|
7
7
|
|
|
8
8
|
ak_cli_logger = logging.getLogger("ak.cli")
|
|
9
9
|
|
|
@@ -47,6 +47,32 @@ class CLI:
|
|
|
47
47
|
self._print(f" {agent.name}")
|
|
48
48
|
self._print()
|
|
49
49
|
|
|
50
|
+
@staticmethod
|
|
51
|
+
async def _ainput(prompt: str) -> str:
|
|
52
|
+
"""
|
|
53
|
+
Reads a line of input without blocking the event loop, so background tasks keep running between turns.
|
|
54
|
+
The reader is a daemon thread, so Ctrl+C exits instead of waiting on a thread parked in `input()`.
|
|
55
|
+
:param prompt: The prompt to display to the user.
|
|
56
|
+
:return: The line entered by the user.
|
|
57
|
+
"""
|
|
58
|
+
loop = asyncio.get_running_loop()
|
|
59
|
+
future: asyncio.Future[str] = loop.create_future()
|
|
60
|
+
|
|
61
|
+
def resolve(setter, value):
|
|
62
|
+
if not future.done():
|
|
63
|
+
setter(value)
|
|
64
|
+
|
|
65
|
+
def read():
|
|
66
|
+
try:
|
|
67
|
+
line = input(prompt)
|
|
68
|
+
except BaseException as e: # noqa: BLE001 - relayed to the awaiting caller
|
|
69
|
+
loop.call_soon_threadsafe(resolve, future.set_exception, e)
|
|
70
|
+
else:
|
|
71
|
+
loop.call_soon_threadsafe(resolve, future.set_result, line)
|
|
72
|
+
|
|
73
|
+
threading.Thread(target=read, daemon=True, name="ak-cli-input").start()
|
|
74
|
+
return await future
|
|
75
|
+
|
|
50
76
|
async def run(self):
|
|
51
77
|
self._print("AgentKernel CLI (type !help for commands or !quit to exit):")
|
|
52
78
|
self._service.select()
|
|
@@ -57,7 +83,7 @@ class CLI:
|
|
|
57
83
|
while True:
|
|
58
84
|
try:
|
|
59
85
|
name = self._service.agent.name if self._service.agent else "none"
|
|
60
|
-
prompt =
|
|
86
|
+
prompt = await self._ainput(f"({name}) >> ")
|
|
61
87
|
if not prompt.strip():
|
|
62
88
|
continue
|
|
63
89
|
if prompt.startswith("!"):
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import asyncio
|
|
2
2
|
import contextvars
|
|
3
|
+
import copy
|
|
3
4
|
import logging
|
|
5
|
+
import pickle
|
|
4
6
|
from abc import ABC, abstractmethod
|
|
5
|
-
from collections.abc import AsyncGenerator, Iterator
|
|
7
|
+
from collections.abc import AsyncGenerator, Iterator, Mapping
|
|
6
8
|
from enum import Enum
|
|
7
9
|
from typing import Any, ClassVar, Self, cast
|
|
8
10
|
|
|
@@ -10,6 +12,8 @@ from .hooks import PostHook, PreHook
|
|
|
10
12
|
from .model import AgentReply, AgentRequest
|
|
11
13
|
from .util.key_value_cache import KeyValueCache
|
|
12
14
|
|
|
15
|
+
_log = logging.getLogger("ak.core.runner")
|
|
16
|
+
|
|
13
17
|
|
|
14
18
|
class Session:
|
|
15
19
|
"""
|
|
@@ -39,6 +43,7 @@ class Session:
|
|
|
39
43
|
|
|
40
44
|
VOLATILE_CACHE = "v_cache"
|
|
41
45
|
NON_VOLATILE_CACHE = "nv_cache"
|
|
46
|
+
FRAMEWORK_CONTEXT = "framework_context"
|
|
42
47
|
|
|
43
48
|
current_session: ClassVar[contextvars.ContextVar[Self | None]] = contextvars.ContextVar("current_session", default=None)
|
|
44
49
|
|
|
@@ -157,6 +162,35 @@ class Session:
|
|
|
157
162
|
"""
|
|
158
163
|
return cast(KeyValueCache, self.get(Session.Keys.NON_VOLATILE_CACHE.value))
|
|
159
164
|
|
|
165
|
+
def get_framework_context(self) -> dict | None:
|
|
166
|
+
"""
|
|
167
|
+
Returns the live per-run framework context dict, so hooks can edit it in place.
|
|
168
|
+
Never auto-creates the key: absent means "nothing injected", {} means "injected but empty".
|
|
169
|
+
:return: The stored framework context dict, or None when the key is absent.
|
|
170
|
+
"""
|
|
171
|
+
return self.get(Session.Keys.FRAMEWORK_CONTEXT.value)
|
|
172
|
+
|
|
173
|
+
def set_framework_context(self, context: dict) -> dict:
|
|
174
|
+
"""
|
|
175
|
+
Seeds or replaces the per-run framework context carried across turns.
|
|
176
|
+
:param context: The context dict to store. Must be picklable, since sessions are persisted with pickle.
|
|
177
|
+
:return: The stored context dict.
|
|
178
|
+
:raises TypeError: If context is not a dict.
|
|
179
|
+
"""
|
|
180
|
+
if not isinstance(context, dict):
|
|
181
|
+
raise TypeError(
|
|
182
|
+
f"Session '{self._id}' framework_context must be a dict, got "
|
|
183
|
+
f"{type(context).__name__}. The reserved framework_context key carries a "
|
|
184
|
+
f"per-run context/state dict; wrap the value in a dict before setting it."
|
|
185
|
+
)
|
|
186
|
+
return self.set(Session.Keys.FRAMEWORK_CONTEXT.value, context)
|
|
187
|
+
|
|
188
|
+
def clear_framework_context(self) -> None:
|
|
189
|
+
"""
|
|
190
|
+
Deletes the per-run framework context, so nothing is injected on the next turn.
|
|
191
|
+
"""
|
|
192
|
+
self.delete(Session.Keys.FRAMEWORK_CONTEXT.value)
|
|
193
|
+
|
|
160
194
|
def set(self, key: str, value: Any) -> Any:
|
|
161
195
|
"""
|
|
162
196
|
Sets a session data object for the specified key.
|
|
@@ -220,6 +254,92 @@ class Runner(ABC):
|
|
|
220
254
|
"""
|
|
221
255
|
return self._name
|
|
222
256
|
|
|
257
|
+
def _load_framework_context(self, session: Session | None) -> dict | None:
|
|
258
|
+
"""
|
|
259
|
+
Loads the per-run framework context to inject into this run.
|
|
260
|
+
Returns a deep copy, so a failed run leaves the stored context intact.
|
|
261
|
+
:param session: The session to read the framework context from, or None.
|
|
262
|
+
:return: A deep copy of the stored dict, or None when nothing is stored.
|
|
263
|
+
:raises TypeError: If the stored value is not a dict.
|
|
264
|
+
"""
|
|
265
|
+
if session is None:
|
|
266
|
+
return None
|
|
267
|
+
stored = session.get_framework_context()
|
|
268
|
+
if stored is None:
|
|
269
|
+
return None
|
|
270
|
+
if not isinstance(stored, dict):
|
|
271
|
+
raise TypeError(
|
|
272
|
+
f"Session '{session.id}' framework_context must be a dict, got "
|
|
273
|
+
f"{type(stored).__name__}. The reserved framework_context key carries a "
|
|
274
|
+
f"per-run context/state dict; wrap the value in a dict before setting it."
|
|
275
|
+
)
|
|
276
|
+
return copy.deepcopy(stored)
|
|
277
|
+
|
|
278
|
+
def _store_framework_context(self, session: Session | None, incoming: dict | None, produced: Mapping[str, Any] | None) -> None:
|
|
279
|
+
"""
|
|
280
|
+
Merges the framework's post-run state over the context loaded this turn and stores the result.
|
|
281
|
+
Keys the framework touched win; untouched caller keys are preserved. No-op when nothing was loaded.
|
|
282
|
+
:param session: The session to write the merged context back to, or None.
|
|
283
|
+
:param incoming: The context loaded this turn, or None when nothing was stored.
|
|
284
|
+
:param produced: The framework's post-run state, or None.
|
|
285
|
+
"""
|
|
286
|
+
if session is None or incoming is None:
|
|
287
|
+
return
|
|
288
|
+
merged = dict(incoming)
|
|
289
|
+
if produced:
|
|
290
|
+
merged.update(produced)
|
|
291
|
+
self._ensure_framework_context_picklable(session, merged)
|
|
292
|
+
session.set_framework_context(merged)
|
|
293
|
+
|
|
294
|
+
@staticmethod
|
|
295
|
+
def _not_picklable(value: Any) -> bool:
|
|
296
|
+
"""
|
|
297
|
+
Checks whether the given value can be pickled.
|
|
298
|
+
:param value: The value to test.
|
|
299
|
+
:return: True if the value cannot be pickled.
|
|
300
|
+
"""
|
|
301
|
+
try:
|
|
302
|
+
pickle.dumps(value)
|
|
303
|
+
return False
|
|
304
|
+
except Exception:
|
|
305
|
+
return True
|
|
306
|
+
|
|
307
|
+
@classmethod
|
|
308
|
+
def _ensure_framework_context_picklable(cls, session: Session, ctx: Mapping[str, Any]) -> None:
|
|
309
|
+
"""
|
|
310
|
+
Fails fast if the context cannot be pickled, before it can break the session store.
|
|
311
|
+
:param session: The session whose id is named in the error.
|
|
312
|
+
:param ctx: The framework context to validate.
|
|
313
|
+
:raises TypeError: If any value in ctx is not pickle-serializable.
|
|
314
|
+
"""
|
|
315
|
+
try:
|
|
316
|
+
pickle.dumps(ctx)
|
|
317
|
+
except Exception as exc:
|
|
318
|
+
offender = next(
|
|
319
|
+
(f"{k!r} ({type(v).__name__})" for k, v in ctx.items() if cls._not_picklable(v)),
|
|
320
|
+
"<unknown key>",
|
|
321
|
+
)
|
|
322
|
+
raise TypeError(
|
|
323
|
+
f"Session '{session.id}' framework_context is not picklable; "
|
|
324
|
+
f"offending entry: {offender}. framework_context values must be "
|
|
325
|
+
f"pickle-serializable so the session can be persisted."
|
|
326
|
+
) from exc
|
|
327
|
+
|
|
328
|
+
@staticmethod
|
|
329
|
+
def _log_framework_context_stream_failure(session: Session | None, error: Exception) -> None:
|
|
330
|
+
"""
|
|
331
|
+
Logs a framework context write-back failure at the end of a streamed run instead of raising it.
|
|
332
|
+
Raising here would surface as a transport error and skip the turn's session store.
|
|
333
|
+
:param session: The session whose write-back failed.
|
|
334
|
+
:param error: The exception raised while producing or storing the context.
|
|
335
|
+
"""
|
|
336
|
+
session_id = session.id if session is not None else "<none>"
|
|
337
|
+
_log.error(
|
|
338
|
+
f"Session '{session_id}': framework_context write-back was skipped at the end of a "
|
|
339
|
+
f"streamed run; the previously stored context is left intact. Error: {error}",
|
|
340
|
+
exc_info=error,
|
|
341
|
+
)
|
|
342
|
+
|
|
223
343
|
@abstractmethod
|
|
224
344
|
async def run(self, agent: Any, session: Session, requests: list[AgentRequest]) -> AgentReply:
|
|
225
345
|
"""
|
|
@@ -351,3 +471,16 @@ class Agent(ABC):
|
|
|
351
471
|
|
|
352
472
|
for tool in SystemToolFactory.get_all(self.name):
|
|
353
473
|
self.attach_tool(tool.func)
|
|
474
|
+
|
|
475
|
+
@staticmethod
|
|
476
|
+
def _append_tools(agent: Any, wrapped: list[Any]) -> None:
|
|
477
|
+
"""
|
|
478
|
+
Appends already-wrapped tools to a framework agent's list-based `tools` attribute, skipping duplicates.
|
|
479
|
+
:param agent: The framework-native agent holding the `tools` attribute.
|
|
480
|
+
:param wrapped: The wrapped tools to attach.
|
|
481
|
+
"""
|
|
482
|
+
for w in wrapped:
|
|
483
|
+
if not hasattr(agent, "tools") or agent.tools is None:
|
|
484
|
+
agent.tools = []
|
|
485
|
+
if w not in agent.tools:
|
|
486
|
+
agent.tools.append(w)
|
|
@@ -13,7 +13,7 @@ from google.adk.agents import BaseAgent
|
|
|
13
13
|
from google.adk.agents.run_config import RunConfig, StreamingMode
|
|
14
14
|
from google.adk.events import Event, EventActions
|
|
15
15
|
from google.adk.runners import Runner
|
|
16
|
-
from google.adk.sessions import BaseSessionService, InMemorySessionService
|
|
16
|
+
from google.adk.sessions import BaseSessionService, InMemorySessionService, State
|
|
17
17
|
from google.adk.tools import FunctionTool, ToolContext
|
|
18
18
|
from google.genai import types
|
|
19
19
|
from pydantic import ValidationError
|
|
@@ -76,6 +76,21 @@ class GoogleADKSession:
|
|
|
76
76
|
)
|
|
77
77
|
await self._session_service.append_event(self._session, event)
|
|
78
78
|
|
|
79
|
+
async def get_state(self) -> dict:
|
|
80
|
+
"""
|
|
81
|
+
Returns the caller-visible ADK session state, stripping the AK-internal ``ak_tool_context`` id and the
|
|
82
|
+
``app:`` / ``user:`` / ``temp:`` prefixed keys that are not session-scoped.
|
|
83
|
+
:return: The accumulated session state, or an empty dict when no session exists.
|
|
84
|
+
"""
|
|
85
|
+
if self._session is None:
|
|
86
|
+
return {}
|
|
87
|
+
refreshed = await self._session_service.get_session(
|
|
88
|
+
app_name=self._session.app_name, user_id=self._session.user_id, session_id=self._session.id
|
|
89
|
+
)
|
|
90
|
+
state = dict(getattr(refreshed, "state", {}) or {})
|
|
91
|
+
state.pop("ak_tool_context", None)
|
|
92
|
+
return {k: v for k, v in state.items() if not k.startswith((State.APP_PREFIX, State.USER_PREFIX, State.TEMP_PREFIX))}
|
|
93
|
+
|
|
79
94
|
|
|
80
95
|
class GoogleADKRunner(BaseRunner):
|
|
81
96
|
def __init__(self):
|
|
@@ -131,7 +146,7 @@ class GoogleADKRunner(BaseRunner):
|
|
|
131
146
|
parts.append(types.Part(file_data=types.FileData(file_uri=base64_data)))
|
|
132
147
|
continue
|
|
133
148
|
|
|
134
|
-
if base64_data.startswith(
|
|
149
|
+
if base64_data.startswith("data:"):
|
|
135
150
|
mime_type = base64_data.split(";")[0][5:]
|
|
136
151
|
else:
|
|
137
152
|
if not req.mime_type:
|
|
@@ -143,15 +158,19 @@ class GoogleADKRunner(BaseRunner):
|
|
|
143
158
|
|
|
144
159
|
return prompt, parts
|
|
145
160
|
|
|
146
|
-
async def _setup_session_context(
|
|
161
|
+
async def _setup_session_context(
|
|
162
|
+
self, agent: Any, session: Session, requests: list[AgentRequest], injected: dict | None = None
|
|
163
|
+
) -> tuple[str, Runner, AKToolContext, GoogleADKSession]:
|
|
147
164
|
"""
|
|
148
165
|
Setup ADK session and tool context.
|
|
149
166
|
:param agent: The ADK agent.
|
|
150
167
|
:param session: The AgentKernel session.
|
|
151
168
|
:param requests: The requests.
|
|
152
|
-
:
|
|
153
|
-
|
|
154
|
-
the
|
|
169
|
+
:param injected: The per-run framework context to seed into the ADK session state, or None.
|
|
170
|
+
:return: Tuple of (user_id, runner, tool_context, adk_session). The caller is responsible for
|
|
171
|
+
entering/exiting the returned tool_context around the runner's actual execution, since
|
|
172
|
+
tools invoked by the agent look up this context by id from the cache while the agent is
|
|
173
|
+
running. The returned adk_session lets the caller read state back without re-fetching.
|
|
155
174
|
"""
|
|
156
175
|
app_name = "AgentKernel"
|
|
157
176
|
user_id = "AgentKernel"
|
|
@@ -159,10 +178,13 @@ class GoogleADKRunner(BaseRunner):
|
|
|
159
178
|
|
|
160
179
|
ctx: AKToolContext = AKToolContext(Runtime.current(), agent, session, requests)
|
|
161
180
|
await adk_session.create_session(app_name=app_name, user_id=user_id, session_id=session.id)
|
|
162
|
-
|
|
181
|
+
# Assigned last so a caller key of the same name cannot replace the id tools resolve their context by.
|
|
182
|
+
state = dict(injected or {})
|
|
183
|
+
state["ak_tool_context"] = ctx.id
|
|
184
|
+
await adk_session.update_session_state(ctx.id, agent.name, state)
|
|
163
185
|
|
|
164
186
|
runner = Runner(agent=agent.agent, app_name=app_name, session_service=adk_session.session_service)
|
|
165
|
-
return user_id, runner, ctx
|
|
187
|
+
return user_id, runner, ctx, adk_session
|
|
166
188
|
|
|
167
189
|
@staticmethod
|
|
168
190
|
async def get_response(runner: Runner, user_id: str, session_id: str, parts: list[types.Part]) -> str:
|
|
@@ -178,15 +200,12 @@ class GoogleADKRunner(BaseRunner):
|
|
|
178
200
|
response_text = ""
|
|
179
201
|
|
|
180
202
|
if hasattr(runner, "run_async"):
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
break
|
|
188
|
-
finally:
|
|
189
|
-
await events.aclose()
|
|
203
|
+
# Drain the stream instead of breaking early: stopping early cancels ADK's still-running root agent
|
|
204
|
+
# task, and with sub-agents the last final response is the one to return.
|
|
205
|
+
async for event in runner.run_async(user_id=user_id, session_id=session_id, new_message=new_message):
|
|
206
|
+
if event.is_final_response() and event.content and event.content.parts:
|
|
207
|
+
text_parts = [p.text for p in event.content.parts if hasattr(p, "text") and p.text]
|
|
208
|
+
response_text = " ".join(text_parts) if text_parts else ""
|
|
190
209
|
else:
|
|
191
210
|
for event in runner.run(user_id=user_id, session_id=session_id, new_message=new_message):
|
|
192
211
|
if event.is_final_response() and event.content and event.content.parts:
|
|
@@ -203,16 +222,24 @@ class GoogleADKRunner(BaseRunner):
|
|
|
203
222
|
:param requests: The requests to the agent.
|
|
204
223
|
:return: The result of the agent's execution.
|
|
205
224
|
"""
|
|
225
|
+
prompt = ""
|
|
206
226
|
try:
|
|
207
227
|
prompt, parts = self._process_requests(requests)
|
|
208
228
|
|
|
209
229
|
if not parts:
|
|
210
230
|
return AgentReplyText(response="Sorry. No valid content found in the requests")
|
|
211
231
|
|
|
212
|
-
|
|
232
|
+
incoming = self._load_framework_context(session)
|
|
233
|
+
user_id, runner, ctx, adk_session = await self._setup_session_context(agent, session, requests, incoming)
|
|
213
234
|
with ctx:
|
|
214
235
|
reply = await self.get_response(runner=runner, session_id=session.id, parts=parts, user_id=user_id)
|
|
215
236
|
|
|
237
|
+
# Write back the full ADK state, so keys a tool added during the run also round-trip. Done after
|
|
238
|
+
# the run, so a framework error leaves the stored context intact.
|
|
239
|
+
if incoming is not None:
|
|
240
|
+
produced = await adk_session.get_state()
|
|
241
|
+
self._store_framework_context(session, incoming, produced)
|
|
242
|
+
|
|
216
243
|
output_schema = getattr(agent.agent, "output_schema", None)
|
|
217
244
|
if output_schema is not None:
|
|
218
245
|
try:
|
|
@@ -237,7 +264,8 @@ class GoogleADKRunner(BaseRunner):
|
|
|
237
264
|
if not parts:
|
|
238
265
|
return
|
|
239
266
|
|
|
240
|
-
|
|
267
|
+
incoming = self._load_framework_context(session)
|
|
268
|
+
user_id, runner, ctx, adk_session = await self._setup_session_context(agent, session, requests, incoming)
|
|
241
269
|
new_message = types.Content(role="user", parts=parts)
|
|
242
270
|
run_config = RunConfig(streaming_mode=StreamingMode.SSE)
|
|
243
271
|
|
|
@@ -257,6 +285,15 @@ class GoogleADKRunner(BaseRunner):
|
|
|
257
285
|
if chunk:
|
|
258
286
|
yield chunk
|
|
259
287
|
|
|
288
|
+
# Only after the stream drains normally, so a disconnect or mid-stream error leaves the stored
|
|
289
|
+
# context intact. Deliberately not in a finally.
|
|
290
|
+
if incoming is not None:
|
|
291
|
+
try:
|
|
292
|
+
produced = await adk_session.get_state()
|
|
293
|
+
self._store_framework_context(session, incoming, produced)
|
|
294
|
+
except Exception as e:
|
|
295
|
+
self._log_framework_context_stream_failure(session, e)
|
|
296
|
+
|
|
260
297
|
|
|
261
298
|
class GoogleADKAgent(AKBaseAgent):
|
|
262
299
|
"""
|
|
@@ -293,9 +330,8 @@ class GoogleADKAgent(AKBaseAgent):
|
|
|
293
330
|
Appends the given prompt text to the ADK agent's description.
|
|
294
331
|
Called by the base Agent._setup_system_prompt() at init when multimodal is enabled.
|
|
295
332
|
"""
|
|
296
|
-
if hasattr(self._agent, "description") and self._agent.description:
|
|
297
|
-
|
|
298
|
-
self._agent.description += "\n" + prompt
|
|
333
|
+
if hasattr(self._agent, "description") and self._agent.description and prompt not in self._agent.description:
|
|
334
|
+
self._agent.description += "\n" + prompt
|
|
299
335
|
|
|
300
336
|
def attach_tool(self, tool: Any) -> None:
|
|
301
337
|
"""
|
|
@@ -304,12 +340,7 @@ class GoogleADKAgent(AKBaseAgent):
|
|
|
304
340
|
:param tool: Raw Python callable or already-wrapped ADK FunctionTool.
|
|
305
341
|
"""
|
|
306
342
|
# Delegate to the tool builder to handle binding
|
|
307
|
-
|
|
308
|
-
for w in wrapped:
|
|
309
|
-
if not hasattr(self._agent, "tools") or self._agent.tools is None:
|
|
310
|
-
self._agent.tools = []
|
|
311
|
-
if w not in self._agent.tools:
|
|
312
|
-
self._agent.tools.append(w)
|
|
343
|
+
self._append_tools(self._agent, GoogleADKToolBuilder.bind([tool]))
|
|
313
344
|
|
|
314
345
|
def get_a2a_card(self):
|
|
315
346
|
"""
|
|
@@ -410,15 +441,40 @@ class GoogleADKToolBuilder(ToolBuilder):
|
|
|
410
441
|
if not callable(func):
|
|
411
442
|
raise TypeError(f"Expected a callable, got {type(func).__name__}")
|
|
412
443
|
|
|
444
|
+
signature = inspect.signature(func)
|
|
445
|
+
parameters = list(signature.parameters.values())
|
|
446
|
+
|
|
447
|
+
# ADK-aware tools declare `tool_context` themselves and expect the live ADK
|
|
448
|
+
# context to reach them, so it has to be forwarded. Generic tools do not, and
|
|
449
|
+
# for those the parameter is consumed here purely to activate the AK context.
|
|
450
|
+
declares_tool_context = "tool_context" in signature.parameters
|
|
451
|
+
tool_context_position = list(signature.parameters).index("tool_context") if declares_tool_context else -1
|
|
452
|
+
|
|
453
|
+
def forwarded_kwargs(args: tuple[Any, ...], kwargs: dict[str, Any], tool_context: ToolContext | None) -> dict[str, Any]:
|
|
454
|
+
"""
|
|
455
|
+
Builds the keyword arguments for the wrapped function.
|
|
456
|
+
|
|
457
|
+
:param args: Positional arguments the wrapper was called with.
|
|
458
|
+
:param kwargs: Keyword arguments the wrapper was called with.
|
|
459
|
+
:param tool_context: The ADK tool context supplied to the wrapper.
|
|
460
|
+
:return: The keyword arguments to pass to the wrapped function.
|
|
461
|
+
"""
|
|
462
|
+
if not declares_tool_context or "tool_context" in kwargs:
|
|
463
|
+
return kwargs
|
|
464
|
+
# The caller already bound tool_context positionally; do not bind it twice.
|
|
465
|
+
if len(args) > tool_context_position:
|
|
466
|
+
return kwargs
|
|
467
|
+
return {**kwargs, "tool_context": tool_context}
|
|
468
|
+
|
|
413
469
|
if asyncio.iscoroutinefunction(func):
|
|
414
470
|
|
|
415
471
|
@functools.wraps(func)
|
|
416
|
-
async def wrapper(*args: Any, tool_context: ToolContext, **kwargs: Any) -> Any:
|
|
472
|
+
async def wrapper(*args: Any, tool_context: ToolContext | None = None, **kwargs: Any) -> Any:
|
|
417
473
|
tctx: AKToolContext | None = None
|
|
418
474
|
try:
|
|
419
475
|
if tool_context and tool_context.state and tool_context.state.get("ak_tool_context"):
|
|
420
476
|
tctx = AKToolContext.fetch(tool_context.state["ak_tool_context"]).set()
|
|
421
|
-
return await func(*args, **kwargs)
|
|
477
|
+
return await func(*args, **forwarded_kwargs(args, kwargs, tool_context))
|
|
422
478
|
finally:
|
|
423
479
|
if tctx:
|
|
424
480
|
tctx.reset()
|
|
@@ -426,23 +482,20 @@ class GoogleADKToolBuilder(ToolBuilder):
|
|
|
426
482
|
else:
|
|
427
483
|
|
|
428
484
|
@functools.wraps(func)
|
|
429
|
-
def wrapper(*args: Any, tool_context: ToolContext, **kwargs: Any) -> Any:
|
|
485
|
+
def wrapper(*args: Any, tool_context: ToolContext | None = None, **kwargs: Any) -> Any:
|
|
430
486
|
tctx: AKToolContext | None = None
|
|
431
487
|
try:
|
|
432
488
|
if tool_context and tool_context.state and tool_context.state.get("ak_tool_context"):
|
|
433
489
|
tctx = AKToolContext.fetch(tool_context.state["ak_tool_context"]).set()
|
|
434
|
-
return func(*args, **kwargs)
|
|
490
|
+
return func(*args, **forwarded_kwargs(args, kwargs, tool_context))
|
|
435
491
|
finally:
|
|
436
492
|
if tctx:
|
|
437
493
|
tctx.reset()
|
|
438
494
|
|
|
439
|
-
signature = inspect.signature(func)
|
|
440
|
-
parameters = list(signature.parameters.values())
|
|
441
|
-
|
|
442
495
|
# Only add a tool_context parameter if the original function does not already
|
|
443
496
|
# declare one, and insert it before any **kwargs (VAR_KEYWORD) parameter to
|
|
444
497
|
# maintain a valid inspect.Signature ordering.
|
|
445
|
-
if
|
|
498
|
+
if not declares_tool_context:
|
|
446
499
|
tool_context_param = inspect.Parameter(
|
|
447
500
|
"tool_context",
|
|
448
501
|
kind=inspect.Parameter.KEYWORD_ONLY,
|
|
@@ -273,6 +273,8 @@ class CrewAIRunner(Runner):
|
|
|
273
273
|
"""
|
|
274
274
|
super().__init__(FRAMEWORK)
|
|
275
275
|
self._log = logging.getLogger("ak.crewai.runner")
|
|
276
|
+
self._context_warned = False
|
|
277
|
+
"""Whether the unsupported-framework_context warning was already logged."""
|
|
276
278
|
|
|
277
279
|
def _transcript(self, session: Session) -> list[str] | None:
|
|
278
280
|
"""
|
|
@@ -375,6 +377,11 @@ class CrewAIRunner(Runner):
|
|
|
375
377
|
verbose=False,
|
|
376
378
|
memory=memory,
|
|
377
379
|
)
|
|
380
|
+
# CrewAI's kickoff(inputs=...) are template-interpolation variables, not a context/state object, so
|
|
381
|
+
# there is no per-run caller-state slot. Warn once, and leave the stored context untouched.
|
|
382
|
+
if not self._context_warned and session is not None and session.get_framework_context():
|
|
383
|
+
self._log.warning("framework_context is set but CrewAI does not support per-run caller context/state; ignoring it.")
|
|
384
|
+
self._context_warned = True
|
|
378
385
|
reply = await crew.kickoff_async(inputs={})
|
|
379
386
|
if isinstance(getattr(reply, "pydantic", None), BaseModel):
|
|
380
387
|
agent_reply: AgentReply = AgentReplyAny(content=reply.pydantic.model_dump(mode="json"), prompt=prompt)
|
|
@@ -510,12 +517,7 @@ class CrewAIAgent(BaseAgent):
|
|
|
510
517
|
:param tool: Raw Python callable or already-wrapped CrewAI tool.
|
|
511
518
|
"""
|
|
512
519
|
# Delegate to the tool builder to handle binding
|
|
513
|
-
|
|
514
|
-
for w in wrapped:
|
|
515
|
-
if not hasattr(self.agent, "tools") or self.agent.tools is None:
|
|
516
|
-
self.agent.tools = []
|
|
517
|
-
if w not in self.agent.tools:
|
|
518
|
-
self.agent.tools.append(w)
|
|
520
|
+
self._append_tools(self.agent, CrewAIToolBuilder.bind([tool]))
|
|
519
521
|
|
|
520
522
|
def override_system_prompt(self, prompt: str) -> None:
|
|
521
523
|
"""
|
|
@@ -371,6 +371,7 @@ class LangGraphRunner(BaseRunner):
|
|
|
371
371
|
:param requests: The requests to the agent.
|
|
372
372
|
:return: The result of the agent's execution.
|
|
373
373
|
"""
|
|
374
|
+
prompt = ""
|
|
374
375
|
context: ToolContext | None = None
|
|
375
376
|
try:
|
|
376
377
|
context = ToolContext(Runtime.current(), agent, session, requests).set()
|
|
@@ -387,10 +388,24 @@ class LangGraphRunner(BaseRunner):
|
|
|
387
388
|
|
|
388
389
|
config, messages = self._prepare_session_and_messages(agent, session, prompt)
|
|
389
390
|
|
|
391
|
+
# Spread the context's top-level keys into the input state so they map onto the graph's state
|
|
392
|
+
# channels. `messages` is written last so a caller key cannot replace it.
|
|
393
|
+
incoming = self._load_framework_context(session)
|
|
394
|
+
input_state: dict[str, Any] = {}
|
|
395
|
+
if incoming:
|
|
396
|
+
input_state.update(incoming)
|
|
397
|
+
input_state["messages"] = messages
|
|
398
|
+
|
|
390
399
|
result = await agent.agent.ainvoke(
|
|
391
|
-
input=
|
|
400
|
+
input=input_state,
|
|
392
401
|
config=config,
|
|
393
402
|
)
|
|
403
|
+
|
|
404
|
+
# Only keys the graph declares as state channels come back on `result`; the rest keep their value.
|
|
405
|
+
if incoming is not None:
|
|
406
|
+
produced = {k: result[k] for k in incoming if k in result}
|
|
407
|
+
self._store_framework_context(session, incoming, produced)
|
|
408
|
+
|
|
394
409
|
structured = AgentReplyAny.from_output(result.get("structured_response"), prompt)
|
|
395
410
|
if structured is not None:
|
|
396
411
|
return structured
|
|
@@ -423,8 +438,14 @@ class LangGraphRunner(BaseRunner):
|
|
|
423
438
|
|
|
424
439
|
config, messages = self._prepare_session_and_messages(agent, session, prompt)
|
|
425
440
|
|
|
441
|
+
incoming = self._load_framework_context(session)
|
|
442
|
+
input_state: dict[str, Any] = {}
|
|
443
|
+
if incoming:
|
|
444
|
+
input_state.update(incoming)
|
|
445
|
+
input_state["messages"] = messages
|
|
446
|
+
|
|
426
447
|
async for event in agent.agent.astream_events(
|
|
427
|
-
input=
|
|
448
|
+
input=input_state,
|
|
428
449
|
config=config,
|
|
429
450
|
version="v2",
|
|
430
451
|
):
|
|
@@ -436,6 +457,16 @@ class LangGraphRunner(BaseRunner):
|
|
|
436
457
|
for item in content:
|
|
437
458
|
if isinstance(item, dict) and item.get("text"):
|
|
438
459
|
yield item["text"]
|
|
460
|
+
|
|
461
|
+
# astream_events yields events, not a final state, so read the state back once the stream drains
|
|
462
|
+
# normally. A disconnect or mid-stream error unwinds first, leaving the stored context intact.
|
|
463
|
+
if incoming is not None:
|
|
464
|
+
try:
|
|
465
|
+
state = await agent.agent.aget_state(config)
|
|
466
|
+
produced = {k: state.values[k] for k in incoming if k in state.values}
|
|
467
|
+
self._store_framework_context(session, incoming, produced)
|
|
468
|
+
except Exception as e:
|
|
469
|
+
self._log_framework_context_stream_failure(session, e)
|
|
439
470
|
finally:
|
|
440
471
|
if context is not None:
|
|
441
472
|
context.reset()
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
2
|
|
|
3
|
+
import copy
|
|
3
4
|
from collections.abc import AsyncGenerator
|
|
4
5
|
from typing import Any, Callable, List
|
|
5
6
|
|
|
@@ -171,6 +172,7 @@ class OpenAIRunner(BaseRunner):
|
|
|
171
172
|
:param requests: The requests to the agent.
|
|
172
173
|
:return: The result of the agent's execution.
|
|
173
174
|
"""
|
|
175
|
+
prompt = ""
|
|
174
176
|
context: ToolContext | None = None
|
|
175
177
|
try:
|
|
176
178
|
context = ToolContext(Runtime.current(), agent, session, requests).set()
|
|
@@ -180,7 +182,13 @@ class OpenAIRunner(BaseRunner):
|
|
|
180
182
|
return AgentReplyText(response="Sorry. No valid content found in the requests")
|
|
181
183
|
|
|
182
184
|
input_data, session_to_use = self._get_run_input(agent, session, prompt, message_content)
|
|
183
|
-
|
|
185
|
+
# Injected as the run context, so tools read and write it via RunContextWrapper.context.
|
|
186
|
+
# A deep copy is passed in so tools mutating it in place don't also mutate `incoming`.
|
|
187
|
+
incoming = self._load_framework_context(session)
|
|
188
|
+
produced = copy.deepcopy(incoming)
|
|
189
|
+
reply = (await Runner.run(agent.agent, input_data, session=session_to_use, context=produced)).final_output
|
|
190
|
+
|
|
191
|
+
self._store_framework_context(session, incoming, produced)
|
|
184
192
|
|
|
185
193
|
structured = AgentReplyAny.from_output(reply, prompt)
|
|
186
194
|
if structured is not None:
|
|
@@ -211,12 +219,21 @@ class OpenAIRunner(BaseRunner):
|
|
|
211
219
|
return
|
|
212
220
|
|
|
213
221
|
input_data, session_to_use = self._get_run_input(agent, session, prompt, message_content)
|
|
214
|
-
|
|
222
|
+
incoming = self._load_framework_context(session)
|
|
223
|
+
produced = copy.deepcopy(incoming)
|
|
224
|
+
result = Runner.run_streamed(agent.agent, input_data, session=session_to_use, context=produced)
|
|
215
225
|
|
|
216
226
|
async for event in result.stream_events():
|
|
217
227
|
if event.type == "raw_response_event" and isinstance(event.data, ResponseTextDeltaEvent):
|
|
218
228
|
if event.data.delta:
|
|
219
229
|
yield event.data.delta
|
|
230
|
+
|
|
231
|
+
# Only after the stream drains normally, so a disconnect or framework error leaves the stored
|
|
232
|
+
# context intact. Deliberately not in a finally.
|
|
233
|
+
try:
|
|
234
|
+
self._store_framework_context(session, incoming, produced)
|
|
235
|
+
except Exception as e:
|
|
236
|
+
self._log_framework_context_stream_failure(session, e)
|
|
220
237
|
finally:
|
|
221
238
|
if context is not None:
|
|
222
239
|
context.reset()
|
|
@@ -268,12 +285,7 @@ class OpenAIAgent(BaseAgent):
|
|
|
268
285
|
:param tool: Raw Python callable or already-wrapped OpenAI function_tool.
|
|
269
286
|
"""
|
|
270
287
|
# Delegate to the tool builder to handle binding
|
|
271
|
-
|
|
272
|
-
for w in wrapped:
|
|
273
|
-
if not hasattr(self._agent, "tools") or self._agent.tools is None:
|
|
274
|
-
self._agent.tools = []
|
|
275
|
-
if w not in self._agent.tools:
|
|
276
|
-
self._agent.tools.append(w)
|
|
288
|
+
self._append_tools(self._agent, OpenAIToolBuilder.bind([tool]))
|
|
277
289
|
|
|
278
290
|
def get_a2a_card(self):
|
|
279
291
|
"""
|