solace-agent-mesh 1.6.1__py3-none-any.whl → 1.13.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of solace-agent-mesh might be problematic. Click here for more details.
- solace_agent_mesh/agent/adk/alembic/README +74 -0
- solace_agent_mesh/agent/adk/alembic/env.py +77 -0
- solace_agent_mesh/agent/adk/alembic/script.py.mako +28 -0
- solace_agent_mesh/agent/adk/alembic/versions/e2902798564d_adk_session_db_upgrade.py +52 -0
- solace_agent_mesh/agent/adk/alembic.ini +112 -0
- solace_agent_mesh/agent/adk/app_llm_agent.py +26 -0
- solace_agent_mesh/agent/adk/artifacts/filesystem_artifact_service.py +165 -1
- solace_agent_mesh/agent/adk/artifacts/s3_artifact_service.py +163 -0
- solace_agent_mesh/agent/adk/callbacks.py +852 -109
- solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +234 -36
- solace_agent_mesh/agent/adk/intelligent_mcp_callbacks.py +52 -5
- solace_agent_mesh/agent/adk/mcp_content_processor.py +1 -1
- solace_agent_mesh/agent/adk/models/lite_llm.py +77 -21
- solace_agent_mesh/agent/adk/models/oauth2_token_manager.py +24 -137
- solace_agent_mesh/agent/adk/runner.py +85 -20
- solace_agent_mesh/agent/adk/schema_migration.py +88 -0
- solace_agent_mesh/agent/adk/services.py +94 -18
- solace_agent_mesh/agent/adk/setup.py +281 -65
- solace_agent_mesh/agent/adk/stream_parser.py +231 -37
- solace_agent_mesh/agent/adk/tool_wrapper.py +3 -0
- solace_agent_mesh/agent/protocol/event_handlers.py +472 -137
- solace_agent_mesh/agent/proxies/a2a/app.py +3 -2
- solace_agent_mesh/agent/proxies/a2a/component.py +572 -75
- solace_agent_mesh/agent/proxies/a2a/config.py +80 -4
- solace_agent_mesh/agent/proxies/base/app.py +3 -2
- solace_agent_mesh/agent/proxies/base/component.py +188 -22
- solace_agent_mesh/agent/proxies/base/proxy_task_context.py +3 -1
- solace_agent_mesh/agent/sac/app.py +91 -3
- solace_agent_mesh/agent/sac/component.py +591 -157
- solace_agent_mesh/agent/sac/patch_adk.py +8 -16
- solace_agent_mesh/agent/sac/task_execution_context.py +146 -4
- solace_agent_mesh/agent/tools/__init__.py +3 -0
- solace_agent_mesh/agent/tools/audio_tools.py +3 -3
- solace_agent_mesh/agent/tools/builtin_artifact_tools.py +710 -171
- solace_agent_mesh/agent/tools/deep_research_tools.py +2161 -0
- solace_agent_mesh/agent/tools/dynamic_tool.py +2 -0
- solace_agent_mesh/agent/tools/peer_agent_tool.py +82 -15
- solace_agent_mesh/agent/tools/time_tools.py +126 -0
- solace_agent_mesh/agent/tools/tool_config_types.py +57 -2
- solace_agent_mesh/agent/tools/web_search_tools.py +279 -0
- solace_agent_mesh/agent/tools/web_tools.py +125 -17
- solace_agent_mesh/agent/utils/artifact_helpers.py +248 -6
- solace_agent_mesh/agent/utils/context_helpers.py +17 -0
- solace_agent_mesh/assets/docs/404.html +6 -6
- solace_agent_mesh/assets/docs/assets/css/{styles.906a1503.css → styles.8162edfb.css} +1 -1
- solace_agent_mesh/assets/docs/assets/js/05749d90.19ac4f35.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/15ba94aa.e186750d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/15e40e79.434bb30f.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/17896441.e612dfb4.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2279.550aa580.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/{17896441.a5e82f9b.js.LICENSE.txt → 2279.550aa580.js.LICENSE.txt} +6 -0
- solace_agent_mesh/assets/docs/assets/js/240a0364.83e37aa8.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2987107d.a80604f9.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2e32b5e0.2f0db237.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3a6c6137.7e61915d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3ac1795d.7f7ab1c1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3ff0015d.e53c9b78.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/41adc471.0e95b87c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/4667dc50.bf2ad456.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/49eed117.493d6f99.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{509e993c.4c7a1a6d.js → 509e993c.a1fbf45a.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/547e15cc.8e6da617.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/55b7b518.29d6e75d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5b8d9c11.d4eb37b8.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5c2bd65f.1ee87753.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/60702c0e.a8bdd79b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/631738c7.fa471607.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/64195356.09dbd087.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/66d4869e.30340bd3.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6a520c9d.b6e3f2ce.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6aaedf65.7253541d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.a5b36a60.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6d84eae0.fd23ba4a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/71da7b71.374b9d54.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/729898df.7249e9fd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/7e294c01.7c5f6906.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8024126c.e3467286.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/81a99df0.7ed65d45.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/82fbfb93.161823a5.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8b032486.91a91afc.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/924ffdeb.975e428a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/94e8668d.16083b3f.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9bb13469.4523ae20.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/a7d42657.a956689d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/a94703ab.3e5fbcb3.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ab9708a8.3e563275.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ad87452a.9d73dad6.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/c93cbaa0.0e0d8baf.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/cab03b5b.6a073091.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/cbe2e9ea.07e170dd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/da0b5bad.b62f7b08.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/dd817ffc.c37a755e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/dd81e2b8.b682e9c2.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/de915948.44a432bc.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e04b235d.06d23db6.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e1b6eeb4.deb2b62e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e3d9abda.1476f570.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e6f9706b.acc800d3.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e92d0134.c147a429.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ee0c2fe7.94d0a351.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/f284c35a.cc97854c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ff4d71f2.74710fc1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/main.d634009f.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/runtime~main.27bb82a7.js +1 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +68 -68
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +50 -50
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +42 -42
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +55 -55
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +82 -68
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/image-tools/index.html +81 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +67 -50
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/research-tools/index.html +136 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +178 -144
- solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +43 -42
- solace_agent_mesh/assets/docs/docs/documentation/components/index.html +20 -18
- solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +23 -23
- solace_agent_mesh/assets/docs/docs/documentation/components/platform-service/index.html +33 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +45 -45
- solace_agent_mesh/assets/docs/docs/documentation/components/projects/index.html +182 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/prompts/index.html +147 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +208 -125
- solace_agent_mesh/assets/docs/docs/documentation/components/speech/index.html +52 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +28 -49
- solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +29 -30
- solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +14 -14
- solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/index.html +47 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/kubernetes-deployment-guide/index.html +197 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/logging/index.html +90 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +17 -16
- solace_agent_mesh/assets/docs/docs/documentation/deploying/proxy_configuration/index.html +49 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +38 -38
- solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +162 -171
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +67 -49
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +17 -17
- solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +51 -51
- solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +22 -22
- solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +27 -27
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +135 -135
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +66 -66
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +51 -51
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +50 -38
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +86 -86
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +51 -51
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +24 -24
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +30 -30
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +44 -44
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/teams-integration/index.html +115 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/agent-builder/index.html +86 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/connectors/index.html +67 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +23 -19
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +40 -37
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/openapi-tools/index.html +324 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +112 -87
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/secure-user-delegated-access/index.html +440 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +87 -64
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/wheel-installation/index.html +62 -0
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +44 -44
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +39 -37
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +30 -30
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +18 -18
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/vibe_coding/index.html +62 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/artifact-storage/index.html +311 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +39 -42
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +14 -14
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +27 -25
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +69 -69
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +72 -72
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/session-storage/index.html +251 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/user-feedback/index.html +88 -0
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +42 -42
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +20 -20
- solace_agent_mesh/assets/docs/docs/documentation/migrations/platform-service-split/index.html +85 -0
- solace_agent_mesh/assets/docs/lunr-index-1768329217460.json +1 -0
- solace_agent_mesh/assets/docs/lunr-index.json +1 -1
- solace_agent_mesh/assets/docs/search-doc-1768329217460.json +1 -0
- solace_agent_mesh/assets/docs/search-doc.json +1 -1
- solace_agent_mesh/assets/docs/sitemap.xml +1 -1
- solace_agent_mesh/cli/__init__.py +1 -1
- solace_agent_mesh/cli/commands/add_cmd/__init__.py +3 -1
- solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +6 -1
- solace_agent_mesh/cli/commands/add_cmd/proxy_cmd.py +100 -0
- solace_agent_mesh/cli/commands/docs_cmd.py +4 -1
- solace_agent_mesh/cli/commands/eval_cmd.py +1 -1
- solace_agent_mesh/cli/commands/init_cmd/__init__.py +15 -0
- solace_agent_mesh/cli/commands/init_cmd/directory_step.py +1 -1
- solace_agent_mesh/cli/commands/init_cmd/env_step.py +30 -3
- solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +3 -4
- solace_agent_mesh/cli/commands/init_cmd/platform_service_step.py +85 -0
- solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +16 -3
- solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +2 -1
- solace_agent_mesh/cli/commands/plugin_cmd/catalog_cmd.py +1 -0
- solace_agent_mesh/cli/commands/plugin_cmd/create_cmd.py +3 -3
- solace_agent_mesh/cli/commands/run_cmd.py +64 -49
- solace_agent_mesh/cli/commands/tools_cmd.py +315 -0
- solace_agent_mesh/cli/main.py +15 -0
- solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-BTf6dqwp.js → authCallback-KnKMP_vb.js} +1 -1
- solace_agent_mesh/client/webui/frontend/static/assets/client-DpBL2stg.js +25 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-Cd498TV2.js +435 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-rSf8Vu29.css +1 -0
- solace_agent_mesh/client/webui/frontend/static/assets/vendor-CGk8Suyh.js +565 -0
- solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
- solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
- solace_agent_mesh/client/webui/frontend/static/mockServiceWorker.js +336 -0
- solace_agent_mesh/client/webui/frontend/static/ui-version.json +6 -0
- solace_agent_mesh/common/a2a/events.py +2 -1
- solace_agent_mesh/common/a2a/protocol.py +5 -0
- solace_agent_mesh/common/a2a/types.py +2 -1
- solace_agent_mesh/common/a2a_spec/schemas/artifact_creation_progress.json +23 -6
- solace_agent_mesh/common/a2a_spec/schemas/feedback_event.json +51 -0
- solace_agent_mesh/common/agent_registry.py +38 -11
- solace_agent_mesh/common/data_parts.py +144 -4
- solace_agent_mesh/common/error_handlers.py +83 -0
- solace_agent_mesh/common/exceptions.py +24 -0
- solace_agent_mesh/common/oauth/__init__.py +17 -0
- solace_agent_mesh/common/oauth/oauth_client.py +408 -0
- solace_agent_mesh/common/oauth/utils.py +50 -0
- solace_agent_mesh/common/rag_dto.py +156 -0
- solace_agent_mesh/common/sac/sam_component_base.py +97 -19
- solace_agent_mesh/common/sam_events/event_service.py +2 -2
- solace_agent_mesh/common/services/employee_service.py +1 -1
- solace_agent_mesh/common/utils/embeds/constants.py +1 -0
- solace_agent_mesh/common/utils/embeds/converter.py +1 -8
- solace_agent_mesh/common/utils/embeds/modifiers.py +4 -28
- solace_agent_mesh/common/utils/embeds/resolver.py +152 -31
- solace_agent_mesh/common/utils/embeds/types.py +9 -0
- solace_agent_mesh/common/utils/log_formatters.py +20 -0
- solace_agent_mesh/common/utils/mime_helpers.py +12 -5
- solace_agent_mesh/common/utils/pydantic_utils.py +90 -3
- solace_agent_mesh/common/utils/rbac_utils.py +69 -0
- solace_agent_mesh/common/utils/templates/__init__.py +8 -0
- solace_agent_mesh/common/utils/templates/liquid_renderer.py +210 -0
- solace_agent_mesh/common/utils/templates/template_resolver.py +161 -0
- solace_agent_mesh/config_portal/backend/common.py +12 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-CljP4_mv.js +103 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/{components-Rk0n-9cK.js → components-CaC6hG8d.js} +22 -22
- solace_agent_mesh/config_portal/frontend/static/client/assets/{entry.client-mvZjNKiz.js → entry.client-H_TM0YBt.js} +3 -3
- solace_agent_mesh/config_portal/frontend/static/client/assets/{index-DzNKzXrc.js → index-CnFykb2v.js} +16 -16
- solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-f8439d40.js +1 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-BIMqslJB.css +1 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-mJmTIdIk.js +10 -0
- solace_agent_mesh/config_portal/frontend/static/client/index.html +3 -3
- solace_agent_mesh/core_a2a/service.py +3 -2
- solace_agent_mesh/gateway/adapter/__init__.py +1 -0
- solace_agent_mesh/gateway/adapter/base.py +170 -0
- solace_agent_mesh/gateway/adapter/types.py +230 -0
- solace_agent_mesh/gateway/base/app.py +39 -2
- solace_agent_mesh/gateway/base/auth_interface.py +103 -0
- solace_agent_mesh/gateway/base/component.py +1027 -151
- solace_agent_mesh/gateway/generic/__init__.py +1 -0
- solace_agent_mesh/gateway/generic/app.py +50 -0
- solace_agent_mesh/gateway/generic/component.py +894 -0
- solace_agent_mesh/gateway/http_sse/alembic/env.py +0 -7
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_project_users_table.py +72 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_soft_delete_and_search.py +109 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_default_agent_to_projects.py +26 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_projects_table.py +135 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251108_create_prompt_tables_with_sharing.py +154 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251115_add_parent_task_id.py +32 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251126_add_background_task_fields.py +47 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251202_add_versioned_fields_to_prompts.py +52 -0
- solace_agent_mesh/gateway/http_sse/alembic.ini +0 -36
- solace_agent_mesh/gateway/http_sse/app.py +40 -11
- solace_agent_mesh/gateway/http_sse/component.py +285 -160
- solace_agent_mesh/gateway/http_sse/dependencies.py +149 -114
- solace_agent_mesh/gateway/http_sse/main.py +68 -450
- solace_agent_mesh/gateway/http_sse/repository/__init__.py +19 -1
- solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +2 -2
- solace_agent_mesh/gateway/http_sse/repository/entities/project.py +81 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/project_user.py +47 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/session.py +26 -3
- solace_agent_mesh/gateway/http_sse/repository/entities/task.py +7 -0
- solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +47 -0
- solace_agent_mesh/gateway/http_sse/repository/interfaces.py +114 -6
- solace_agent_mesh/gateway/http_sse/repository/models/__init__.py +13 -0
- solace_agent_mesh/gateway/http_sse/repository/models/project_model.py +51 -0
- solace_agent_mesh/gateway/http_sse/repository/models/project_user_model.py +75 -0
- solace_agent_mesh/gateway/http_sse/repository/models/prompt_model.py +159 -0
- solace_agent_mesh/gateway/http_sse/repository/models/session_model.py +8 -2
- solace_agent_mesh/gateway/http_sse/repository/models/task_model.py +8 -1
- solace_agent_mesh/gateway/http_sse/repository/project_repository.py +172 -0
- solace_agent_mesh/gateway/http_sse/repository/project_user_repository.py +186 -0
- solace_agent_mesh/gateway/http_sse/repository/session_repository.py +177 -11
- solace_agent_mesh/gateway/http_sse/repository/task_repository.py +86 -2
- solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +38 -7
- solace_agent_mesh/gateway/http_sse/routers/artifacts.py +256 -58
- solace_agent_mesh/gateway/http_sse/routers/auth.py +168 -134
- solace_agent_mesh/gateway/http_sse/routers/config.py +302 -8
- solace_agent_mesh/gateway/http_sse/routers/dto/project_dto.py +69 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/prompt_dto.py +255 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/project_requests.py +48 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/session_requests.py +14 -1
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/base_responses.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/project_responses.py +31 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +5 -2
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/version_responses.py +31 -0
- solace_agent_mesh/gateway/http_sse/routers/feedback.py +133 -2
- solace_agent_mesh/gateway/http_sse/routers/people.py +2 -2
- solace_agent_mesh/gateway/http_sse/routers/projects.py +768 -0
- solace_agent_mesh/gateway/http_sse/routers/prompts.py +1416 -0
- solace_agent_mesh/gateway/http_sse/routers/sessions.py +167 -7
- solace_agent_mesh/gateway/http_sse/routers/speech.py +355 -0
- solace_agent_mesh/gateway/http_sse/routers/sse.py +131 -8
- solace_agent_mesh/gateway/http_sse/routers/tasks.py +670 -18
- solace_agent_mesh/gateway/http_sse/routers/users.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/version.py +343 -0
- solace_agent_mesh/gateway/http_sse/routers/visualization.py +92 -9
- solace_agent_mesh/gateway/http_sse/services/audio_service.py +1227 -0
- solace_agent_mesh/gateway/http_sse/services/background_task_monitor.py +186 -0
- solace_agent_mesh/gateway/http_sse/services/data_retention_service.py +1 -1
- solace_agent_mesh/gateway/http_sse/services/feedback_service.py +1 -1
- solace_agent_mesh/gateway/http_sse/services/project_service.py +930 -0
- solace_agent_mesh/gateway/http_sse/services/prompt_builder_assistant.py +303 -0
- solace_agent_mesh/gateway/http_sse/services/session_service.py +361 -12
- solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +354 -4
- solace_agent_mesh/gateway/http_sse/session_manager.py +15 -15
- solace_agent_mesh/gateway/http_sse/sse_manager.py +286 -166
- solace_agent_mesh/gateway/http_sse/utils/artifact_copy_utils.py +370 -0
- solace_agent_mesh/gateway/http_sse/utils/stim_utils.py +41 -1
- solace_agent_mesh/services/__init__.py +0 -0
- solace_agent_mesh/services/platform/__init__.py +29 -0
- solace_agent_mesh/services/platform/alembic/env.py +85 -0
- solace_agent_mesh/services/platform/alembic/script.py.mako +28 -0
- solace_agent_mesh/services/platform/alembic.ini +109 -0
- solace_agent_mesh/services/platform/api/__init__.py +3 -0
- solace_agent_mesh/services/platform/api/dependencies.py +154 -0
- solace_agent_mesh/services/platform/api/main.py +314 -0
- solace_agent_mesh/services/platform/api/middleware.py +51 -0
- solace_agent_mesh/services/platform/api/routers/__init__.py +33 -0
- solace_agent_mesh/services/platform/api/routers/health_router.py +31 -0
- solace_agent_mesh/services/platform/app.py +215 -0
- solace_agent_mesh/services/platform/component.py +777 -0
- solace_agent_mesh/shared/__init__.py +14 -0
- solace_agent_mesh/shared/api/__init__.py +42 -0
- solace_agent_mesh/shared/auth/__init__.py +26 -0
- solace_agent_mesh/shared/auth/dependencies.py +204 -0
- solace_agent_mesh/shared/auth/middleware.py +347 -0
- solace_agent_mesh/shared/database/__init__.py +20 -0
- solace_agent_mesh/{gateway/http_sse/shared → shared/database}/base_repository.py +1 -1
- solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_exceptions.py +1 -1
- solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_helpers.py +1 -1
- solace_agent_mesh/shared/exceptions/__init__.py +36 -0
- solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exception_handlers.py +19 -5
- solace_agent_mesh/shared/utils/__init__.py +21 -0
- solace_agent_mesh/templates/logging_config_template.yaml +48 -0
- solace_agent_mesh/templates/main_orchestrator.yaml +12 -1
- solace_agent_mesh/templates/platform.yaml +49 -0
- solace_agent_mesh/templates/plugin_readme_template.md +3 -25
- solace_agent_mesh/templates/plugin_tool_config_template.yaml +109 -0
- solace_agent_mesh/templates/proxy_template.yaml +62 -0
- solace_agent_mesh/templates/webui.yaml +148 -6
- solace_agent_mesh/tools/web_search/__init__.py +18 -0
- solace_agent_mesh/tools/web_search/base.py +84 -0
- solace_agent_mesh/tools/web_search/google_search.py +247 -0
- solace_agent_mesh/tools/web_search/models.py +99 -0
- {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/METADATA +31 -12
- solace_agent_mesh-1.13.2.dist-info/RECORD +591 -0
- {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/WHEEL +1 -1
- solace_agent_mesh/agent/adk/adk_llm.txt +0 -232
- solace_agent_mesh/agent/adk/adk_llm_detail.txt +0 -566
- solace_agent_mesh/agent/adk/artifacts/artifacts_llm.txt +0 -171
- solace_agent_mesh/agent/adk/models/models_llm.txt +0 -142
- solace_agent_mesh/agent/agent_llm.txt +0 -378
- solace_agent_mesh/agent/agent_llm_detail.txt +0 -1702
- solace_agent_mesh/agent/protocol/protocol_llm.txt +0 -81
- solace_agent_mesh/agent/protocol/protocol_llm_detail.txt +0 -92
- solace_agent_mesh/agent/sac/sac_llm.txt +0 -189
- solace_agent_mesh/agent/sac/sac_llm_detail.txt +0 -200
- solace_agent_mesh/agent/testing/testing_llm.txt +0 -57
- solace_agent_mesh/agent/testing/testing_llm_detail.txt +0 -68
- solace_agent_mesh/agent/tools/tools_llm.txt +0 -263
- solace_agent_mesh/agent/tools/tools_llm_detail.txt +0 -274
- solace_agent_mesh/agent/utils/utils_llm.txt +0 -138
- solace_agent_mesh/agent/utils/utils_llm_detail.txt +0 -149
- solace_agent_mesh/assets/docs/assets/js/15ba94aa.932dd2db.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/240a0364.7eac6021.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/2e32b5e0.33f5d75b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3a6c6137.f5940cfa.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3ac1795d.76654dd9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3ff0015d.2be20244.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/547e15cc.2cbb060a.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/55b7b518.f2b1d1ba.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/5c2bd65f.eda4bcb2.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/631738c7.a8b1ef8b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/6a520c9d.ba015d81.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.f4b15f3b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/6d84eae0.4a5fbf39.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/71da7b71.38583438.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/8024126c.56e59919.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/81a99df0.07034dd9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/82fbfb93.139a1a1f.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/924ffdeb.8095e148.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/94e8668d.b5ddb7a1.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/9bb13469.dd1c9b54.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/a94703ab.0438dbc2.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/ab9708a8.3e6dd091.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/c93cbaa0.eaff365e.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/da0b5bad.d08a9466.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/dd817ffc.0aa9630a.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/dd81e2b8.d590bc9e.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/de915948.27d6b065.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e3d9abda.6b9493d0.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e6f9706b.e74a984d.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e92d0134.cf6d6522.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/f284c35a.42f59cdd.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/ff4d71f2.15b02f97.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/main.b12eac43.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/runtime~main.e268214e.js +0 -1
- solace_agent_mesh/assets/docs/lunr-index-1761248203150.json +0 -1
- solace_agent_mesh/assets/docs/search-doc-1761248203150.json +0 -1
- solace_agent_mesh/cli/commands/add_cmd/add_cmd_llm.txt +0 -250
- solace_agent_mesh/cli/commands/init_cmd/init_cmd_llm.txt +0 -365
- solace_agent_mesh/cli/commands/plugin_cmd/plugin_cmd_llm.txt +0 -305
- solace_agent_mesh/client/webui/frontend/static/assets/client-CaY59VuC.js +0 -25
- solace_agent_mesh/client/webui/frontend/static/assets/main-B32noGmR.js +0 -342
- solace_agent_mesh/client/webui/frontend/static/assets/main-DHJKSW1S.css +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/vendor-BEmvJSYz.js +0 -405
- solace_agent_mesh/common/a2a/a2a_llm.txt +0 -182
- solace_agent_mesh/common/a2a/a2a_llm_detail.txt +0 -193
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +0 -407
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm_detail.txt +0 -736
- solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +0 -313
- solace_agent_mesh/common/common_llm.txt +0 -251
- solace_agent_mesh/common/common_llm_detail.txt +0 -2562
- solace_agent_mesh/common/middleware/middleware_llm.txt +0 -174
- solace_agent_mesh/common/middleware/middleware_llm_detail.txt +0 -185
- solace_agent_mesh/common/sac/sac_llm.txt +0 -71
- solace_agent_mesh/common/sac/sac_llm_detail.txt +0 -82
- solace_agent_mesh/common/sam_events/sam_events_llm.txt +0 -104
- solace_agent_mesh/common/sam_events/sam_events_llm_detail.txt +0 -115
- solace_agent_mesh/common/services/providers/providers_llm.txt +0 -80
- solace_agent_mesh/common/services/services_llm.txt +0 -363
- solace_agent_mesh/common/services/services_llm_detail.txt +0 -459
- solace_agent_mesh/common/utils/embeds/embeds_llm.txt +0 -220
- solace_agent_mesh/common/utils/utils_llm.txt +0 -336
- solace_agent_mesh/common/utils/utils_llm_detail.txt +0 -572
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-ByU1X1HD.js +0 -98
- solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-61038fc6.js +0 -1
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-BWvk5-gF.js +0 -10
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-DxRwaWiE.css +0 -1
- solace_agent_mesh/core_a2a/core_a2a_llm.txt +0 -90
- solace_agent_mesh/core_a2a/core_a2a_llm_detail.txt +0 -101
- solace_agent_mesh/gateway/base/base_llm.txt +0 -224
- solace_agent_mesh/gateway/base/base_llm_detail.txt +0 -235
- solace_agent_mesh/gateway/gateway_llm.txt +0 -373
- solace_agent_mesh/gateway/gateway_llm_detail.txt +0 -3885
- solace_agent_mesh/gateway/http_sse/alembic/alembic_llm.txt +0 -295
- solace_agent_mesh/gateway/http_sse/alembic/versions/versions_llm.txt +0 -155
- solace_agent_mesh/gateway/http_sse/components/components_llm.txt +0 -105
- solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +0 -299
- solace_agent_mesh/gateway/http_sse/http_sse_llm_detail.txt +0 -3278
- solace_agent_mesh/gateway/http_sse/repository/entities/entities_llm.txt +0 -263
- solace_agent_mesh/gateway/http_sse/repository/models/models_llm.txt +0 -266
- solace_agent_mesh/gateway/http_sse/repository/repository_llm.txt +0 -340
- solace_agent_mesh/gateway/http_sse/routers/dto/dto_llm.txt +0 -346
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/requests_llm.txt +0 -83
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/responses_llm.txt +0 -107
- solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +0 -314
- solace_agent_mesh/gateway/http_sse/services/services_llm.txt +0 -297
- solace_agent_mesh/gateway/http_sse/shared/__init__.py +0 -146
- solace_agent_mesh/gateway/http_sse/shared/shared_llm.txt +0 -285
- solace_agent_mesh/gateway/http_sse/utils/utils_llm.txt +0 -47
- solace_agent_mesh/llm.txt +0 -228
- solace_agent_mesh/llm_detail.txt +0 -2835
- solace_agent_mesh/solace_agent_mesh_llm.txt +0 -362
- solace_agent_mesh/solace_agent_mesh_llm_detail.txt +0 -8599
- solace_agent_mesh/templates/logging_config_template.ini +0 -45
- solace_agent_mesh/templates/templates_llm.txt +0 -147
- solace_agent_mesh-1.6.1.dist-info/RECORD +0 -525
- /solace_agent_mesh/assets/docs/assets/js/{main.b12eac43.js.LICENSE.txt → main.d634009f.js.LICENSE.txt} +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/auth_utils.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/pagination.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/response_utils.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/error_dto.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exceptions.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/enums.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/timestamp_utils.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/types.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/utils.py +0 -0
- {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,79 +2,87 @@
|
|
|
2
2
|
Custom Solace AI Connector Component to Host Google ADK Agents via A2A Protocol.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
import logging
|
|
6
|
-
from typing import Any, Dict, Optional, Union, Callable, List, Tuple, TYPE_CHECKING
|
|
7
5
|
import asyncio
|
|
8
|
-
import functools
|
|
9
|
-
import threading
|
|
10
6
|
import concurrent.futures
|
|
11
7
|
import fnmatch
|
|
12
|
-
import
|
|
8
|
+
import functools
|
|
9
|
+
import inspect
|
|
13
10
|
import json
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
from
|
|
11
|
+
import logging
|
|
12
|
+
import threading
|
|
13
|
+
import time
|
|
14
|
+
from typing import TYPE_CHECKING, Any, Callable, Dict, List, Optional, Tuple, Union
|
|
15
|
+
|
|
16
|
+
from litellm.exceptions import BadRequestError
|
|
17
|
+
|
|
18
|
+
from ...common.error_handlers import get_error_message
|
|
18
19
|
|
|
19
|
-
from solace_ai_connector.common.utils import import_module
|
|
20
|
-
import inspect
|
|
21
|
-
from pydantic import BaseModel, ValidationError
|
|
22
|
-
from google.adk.agents.invocation_context import (
|
|
23
|
-
LlmCallsLimitExceededError,
|
|
24
|
-
)
|
|
25
|
-
from google.adk.agents import RunConfig
|
|
26
|
-
from google.adk.agents.run_config import StreamingMode
|
|
27
|
-
from google.adk.sessions import BaseSessionService
|
|
28
|
-
from google.adk.artifacts import BaseArtifactService
|
|
29
|
-
from google.adk.memory import BaseMemoryService
|
|
30
|
-
from google.adk.agents import LlmAgent
|
|
31
|
-
from google.adk.runners import Runner
|
|
32
|
-
from google.adk.models import LlmResponse
|
|
33
|
-
from google.adk.agents.readonly_context import ReadonlyContext
|
|
34
|
-
from google.adk.events import Event as ADKEvent
|
|
35
|
-
from google.adk.agents.callback_context import CallbackContext
|
|
36
|
-
from google.adk.models.llm_request import LlmRequest
|
|
37
|
-
from google.genai import types as adk_types
|
|
38
|
-
from google.adk.tools.mcp_tool import MCPToolset
|
|
39
20
|
from a2a.types import (
|
|
40
21
|
AgentCard,
|
|
41
|
-
Artifact as A2AArtifact,
|
|
42
|
-
Message as A2AMessage,
|
|
43
22
|
MessageSendParams,
|
|
44
23
|
SendMessageRequest,
|
|
45
24
|
TaskState,
|
|
46
25
|
TaskStatus,
|
|
47
26
|
TaskStatusUpdateEvent,
|
|
48
27
|
)
|
|
49
|
-
from
|
|
50
|
-
from
|
|
51
|
-
from
|
|
52
|
-
from
|
|
28
|
+
from a2a.types import Artifact as A2AArtifact
|
|
29
|
+
from a2a.types import Message as A2AMessage
|
|
30
|
+
from google.adk.agents import LlmAgent, RunConfig
|
|
31
|
+
from google.adk.agents.callback_context import CallbackContext
|
|
32
|
+
from google.adk.agents.invocation_context import LlmCallsLimitExceededError
|
|
33
|
+
from google.adk.agents.readonly_context import ReadonlyContext
|
|
34
|
+
from google.adk.agents.run_config import StreamingMode
|
|
35
|
+
from google.adk.artifacts import BaseArtifactService
|
|
36
|
+
from google.adk.auth.credential_service.base_credential_service import (
|
|
37
|
+
BaseCredentialService,
|
|
38
|
+
)
|
|
39
|
+
from google.adk.events import Event as ADKEvent
|
|
40
|
+
from google.adk.memory import BaseMemoryService
|
|
41
|
+
from google.adk.models import LlmResponse
|
|
42
|
+
from google.adk.models.llm_request import LlmRequest
|
|
43
|
+
from google.adk.runners import Runner
|
|
44
|
+
from google.adk.sessions import BaseSessionService
|
|
45
|
+
from google.adk.tools.mcp_tool import MCPToolset
|
|
46
|
+
from google.adk.tools.openapi_tool import OpenAPIToolset
|
|
47
|
+
from google.genai import types as adk_types
|
|
48
|
+
from pydantic import BaseModel, ValidationError
|
|
49
|
+
from solace_ai_connector.common.event import Event, EventType
|
|
50
|
+
from solace_ai_connector.common.message import Message as SolaceMessage
|
|
51
|
+
from solace_ai_connector.common.utils import import_module
|
|
52
|
+
|
|
53
|
+
from ...agent.adk.runner import TaskCancelledError, run_adk_async_task_thread_wrapper
|
|
53
54
|
from ...agent.adk.services import (
|
|
54
|
-
initialize_session_service,
|
|
55
55
|
initialize_artifact_service,
|
|
56
|
+
initialize_credential_service,
|
|
56
57
|
initialize_memory_service,
|
|
58
|
+
initialize_session_service,
|
|
57
59
|
)
|
|
58
60
|
from ...agent.adk.setup import (
|
|
59
|
-
load_adk_tools,
|
|
60
61
|
initialize_adk_agent,
|
|
61
62
|
initialize_adk_runner,
|
|
63
|
+
load_adk_tools,
|
|
62
64
|
)
|
|
63
|
-
from ...agent.protocol.event_handlers import
|
|
64
|
-
process_event,
|
|
65
|
-
publish_agent_card,
|
|
66
|
-
)
|
|
67
|
-
from ...agent.adk.runner import run_adk_async_task_thread_wrapper, TaskCancelledError
|
|
65
|
+
from ...agent.protocol.event_handlers import process_event, publish_agent_card
|
|
68
66
|
from ...agent.tools.peer_agent_tool import (
|
|
69
67
|
CORRELATION_DATA_PREFIX,
|
|
70
|
-
PeerAgentTool,
|
|
71
68
|
PEER_TOOL_PREFIX,
|
|
69
|
+
PeerAgentTool,
|
|
72
70
|
)
|
|
73
|
-
from ...common.middleware.registry import MiddlewareRegistry
|
|
74
|
-
from ...common.constants import DEFAULT_COMMUNICATION_TIMEOUT, HEALTH_CHECK_TTL_SECONDS, HEALTH_CHECK_INTERVAL_SECONDS
|
|
75
71
|
from ...agent.tools.registry import tool_registry
|
|
76
|
-
from ...
|
|
72
|
+
from ...agent.utils.config_parser import resolve_instruction_provider
|
|
73
|
+
from ...common import a2a
|
|
74
|
+
from ...common.a2a.translation import format_and_route_adk_event
|
|
77
75
|
from ...common.agent_registry import AgentRegistry
|
|
76
|
+
from ...common.constants import (
|
|
77
|
+
DEFAULT_COMMUNICATION_TIMEOUT,
|
|
78
|
+
HEALTH_CHECK_INTERVAL_SECONDS,
|
|
79
|
+
HEALTH_CHECK_TTL_SECONDS,
|
|
80
|
+
)
|
|
81
|
+
from ...common.a2a.types import ArtifactInfo
|
|
82
|
+
from ...common.data_parts import AgentProgressUpdateData, ArtifactSavedData
|
|
83
|
+
from ...common.middleware.registry import MiddlewareRegistry
|
|
84
|
+
from ...common.sac.sam_component_base import SamComponentBase
|
|
85
|
+
from ...common.utils.rbac_utils import validate_agent_access
|
|
78
86
|
|
|
79
87
|
log = logging.getLogger(__name__)
|
|
80
88
|
|
|
@@ -128,8 +136,12 @@ class SamAgentComponent(SamComponentBase):
|
|
|
128
136
|
|
|
129
137
|
super().__init__(info, **kwargs)
|
|
130
138
|
self.agent_name = self.get_config("agent_name")
|
|
131
|
-
log.info(
|
|
132
|
-
|
|
139
|
+
log.info(
|
|
140
|
+
"%s Initializing agent: %s (A2A ADK Host Component)...",
|
|
141
|
+
self.log_identifier,
|
|
142
|
+
self.agent_name,
|
|
143
|
+
)
|
|
144
|
+
|
|
133
145
|
# Initialize the agent registry for health tracking
|
|
134
146
|
self.agent_registry = AgentRegistry()
|
|
135
147
|
try:
|
|
@@ -226,7 +238,6 @@ class SamAgentComponent(SamComponentBase):
|
|
|
226
238
|
"max_message_size_bytes", 10_000_000
|
|
227
239
|
)
|
|
228
240
|
|
|
229
|
-
log.info("%s Configuration retrieved successfully.", self.log_identifier)
|
|
230
241
|
except Exception as e:
|
|
231
242
|
log.error(
|
|
232
243
|
"%s Failed to retrieve configuration via get_config: %s",
|
|
@@ -237,6 +248,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
237
248
|
self.session_service: BaseSessionService = None
|
|
238
249
|
self.artifact_service: BaseArtifactService = None
|
|
239
250
|
self.memory_service: BaseMemoryService = None
|
|
251
|
+
self.credential_service: Optional[BaseCredentialService] = None
|
|
240
252
|
self.adk_agent: LlmAgent = None
|
|
241
253
|
self.runner: Runner = None
|
|
242
254
|
self.agent_card_tool_manifest: List[Dict[str, Any]] = []
|
|
@@ -265,9 +277,10 @@ class SamAgentComponent(SamComponentBase):
|
|
|
265
277
|
self.session_service = initialize_session_service(self)
|
|
266
278
|
self.artifact_service = initialize_artifact_service(self)
|
|
267
279
|
self.memory_service = initialize_memory_service(self)
|
|
280
|
+
self.credential_service = initialize_credential_service(self)
|
|
268
281
|
|
|
269
282
|
log.info(
|
|
270
|
-
"%s Synchronous ADK services
|
|
283
|
+
"%s Initialized Synchronous ADK services.", self.log_identifier
|
|
271
284
|
)
|
|
272
285
|
except Exception as service_err:
|
|
273
286
|
log.exception(
|
|
@@ -279,6 +292,18 @@ class SamAgentComponent(SamComponentBase):
|
|
|
279
292
|
f"Failed to initialize synchronous ADK services: {service_err}"
|
|
280
293
|
) from service_err
|
|
281
294
|
|
|
295
|
+
# initialize enterprise features if available
|
|
296
|
+
try:
|
|
297
|
+
from solace_agent_mesh_enterprise.init_enterprise_component import (
|
|
298
|
+
init_enterprise_component_features,
|
|
299
|
+
)
|
|
300
|
+
|
|
301
|
+
init_enterprise_component_features(self)
|
|
302
|
+
except ImportError:
|
|
303
|
+
# Community edition
|
|
304
|
+
# Contact Solace support for enterprise features
|
|
305
|
+
pass
|
|
306
|
+
|
|
282
307
|
from .app import (
|
|
283
308
|
AgentInitCleanupConfig,
|
|
284
309
|
) # delayed import to avoid circular dependency
|
|
@@ -403,30 +428,10 @@ class SamAgentComponent(SamComponentBase):
|
|
|
403
428
|
# We still need a future to signal completion from the async thread.
|
|
404
429
|
self._async_init_future = concurrent.futures.Future()
|
|
405
430
|
|
|
406
|
-
publish_interval_sec = self.agent_card_publishing_config.get(
|
|
407
|
-
"interval_seconds"
|
|
408
|
-
)
|
|
409
|
-
if publish_interval_sec and publish_interval_sec > 0:
|
|
410
|
-
log.info(
|
|
411
|
-
"%s Scheduling agent card publishing every %d seconds.",
|
|
412
|
-
self.log_identifier,
|
|
413
|
-
publish_interval_sec,
|
|
414
|
-
)
|
|
415
|
-
# Register timer with callback
|
|
416
|
-
self.add_timer(
|
|
417
|
-
delay_ms=1000,
|
|
418
|
-
timer_id=self._card_publish_timer_id,
|
|
419
|
-
interval_ms=publish_interval_sec * 1000,
|
|
420
|
-
callback=lambda timer_data: publish_agent_card(self),
|
|
421
|
-
)
|
|
422
|
-
else:
|
|
423
|
-
log.warning(
|
|
424
|
-
"%s Agent card publishing interval not configured or invalid, card will not be published periodically.",
|
|
425
|
-
self.log_identifier,
|
|
426
|
-
)
|
|
427
|
-
|
|
428
431
|
# Set up health check timer if enabled
|
|
429
|
-
health_check_interval_seconds = self.agent_discovery_config.get(
|
|
432
|
+
health_check_interval_seconds = self.agent_discovery_config.get(
|
|
433
|
+
"health_check_interval_seconds", HEALTH_CHECK_INTERVAL_SECONDS
|
|
434
|
+
)
|
|
430
435
|
if health_check_interval_seconds > 0:
|
|
431
436
|
log.info(
|
|
432
437
|
"%s Scheduling agent health check every %d seconds.",
|
|
@@ -444,9 +449,9 @@ class SamAgentComponent(SamComponentBase):
|
|
|
444
449
|
"%s Agent health check interval not configured or invalid, health checks will not run periodically.",
|
|
445
450
|
self.log_identifier,
|
|
446
451
|
)
|
|
447
|
-
|
|
452
|
+
|
|
448
453
|
log.info(
|
|
449
|
-
"%s
|
|
454
|
+
"%s Initialized agent: %s",
|
|
450
455
|
self.log_identifier,
|
|
451
456
|
self.agent_name,
|
|
452
457
|
)
|
|
@@ -484,6 +489,16 @@ class SamAgentComponent(SamComponentBase):
|
|
|
484
489
|
event = Event(EventType.MESSAGE, message)
|
|
485
490
|
await process_event(self, event)
|
|
486
491
|
|
|
492
|
+
def handle_timer_event(self, timer_data: Dict[str, Any]):
|
|
493
|
+
"""Handles timer events for agent card publishing and health checks."""
|
|
494
|
+
log.debug("%s Received timer event: %s", self.log_identifier, timer_data)
|
|
495
|
+
timer_id = timer_data.get("timer_id")
|
|
496
|
+
|
|
497
|
+
if timer_id == self._card_publish_timer_id:
|
|
498
|
+
publish_agent_card(self)
|
|
499
|
+
elif timer_id == self.HEALTH_CHECK_TIMER_ID:
|
|
500
|
+
self._check_agent_health()
|
|
501
|
+
|
|
487
502
|
async def handle_cache_expiry_event(self, cache_data: Dict[str, Any]):
|
|
488
503
|
"""
|
|
489
504
|
Handles cache expiry events for peer timeouts by calling the atomic claim helper.
|
|
@@ -523,6 +538,83 @@ class SamAgentComponent(SamComponentBase):
|
|
|
523
538
|
sub_task_id,
|
|
524
539
|
)
|
|
525
540
|
|
|
541
|
+
async def get_main_task_context(
|
|
542
|
+
self, logical_task_id: str
|
|
543
|
+
) -> Optional["TaskExecutionContext"]:
|
|
544
|
+
"""
|
|
545
|
+
Retrieves the main task context for a given logical task ID.
|
|
546
|
+
|
|
547
|
+
This method is used when the current agent is the target agent for the task.
|
|
548
|
+
It returns the TaskExecutionContext which contains the full task state including
|
|
549
|
+
a2a_context, active_peer_sub_tasks, and other task execution details.
|
|
550
|
+
|
|
551
|
+
Args:
|
|
552
|
+
logical_task_id: The unique logical ID of the task
|
|
553
|
+
|
|
554
|
+
Returns:
|
|
555
|
+
The TaskExecutionContext if the task is active, None otherwise
|
|
556
|
+
|
|
557
|
+
Raises:
|
|
558
|
+
ValueError: If logical_task_id is None or empty
|
|
559
|
+
"""
|
|
560
|
+
if not logical_task_id:
|
|
561
|
+
raise ValueError("logical_task_id cannot be None or empty")
|
|
562
|
+
|
|
563
|
+
with self.active_tasks_lock:
|
|
564
|
+
active_task_context = self.active_tasks.get(logical_task_id)
|
|
565
|
+
if active_task_context is None:
|
|
566
|
+
log.warning(
|
|
567
|
+
f"No active task context found for logical_task_id: {logical_task_id}"
|
|
568
|
+
)
|
|
569
|
+
return None
|
|
570
|
+
|
|
571
|
+
return active_task_context
|
|
572
|
+
|
|
573
|
+
async def get_all_sub_task_correlation_data_from_logical_task_id(
|
|
574
|
+
self, logical_task_id: str
|
|
575
|
+
) -> list[dict[str, Any]]:
|
|
576
|
+
"""
|
|
577
|
+
Retrieves correlation data for all active peer sub-tasks of a given logical task.
|
|
578
|
+
|
|
579
|
+
This method is used when forwarding requests to other agents in an A2A workflow.
|
|
580
|
+
It returns a list of correlation data dictionaries, each containing information
|
|
581
|
+
about a peer sub-task including peer_task_id, peer_agent_name, and original_task_context.
|
|
582
|
+
|
|
583
|
+
Args:
|
|
584
|
+
logical_task_id: The unique logical ID of the parent task
|
|
585
|
+
|
|
586
|
+
Returns:
|
|
587
|
+
List of correlation data dictionaries for active peer sub-tasks.
|
|
588
|
+
Returns empty list if no active peer sub-tasks exist.
|
|
589
|
+
|
|
590
|
+
Raises:
|
|
591
|
+
ValueError: If logical_task_id is None or empty
|
|
592
|
+
"""
|
|
593
|
+
if not logical_task_id:
|
|
594
|
+
raise ValueError("logical_task_id cannot be None or empty")
|
|
595
|
+
|
|
596
|
+
with self.active_tasks_lock:
|
|
597
|
+
active_task_context = self.active_tasks.get(logical_task_id)
|
|
598
|
+
if active_task_context is None:
|
|
599
|
+
log.warning(
|
|
600
|
+
f"No active task context found for logical_task_id: {logical_task_id}"
|
|
601
|
+
)
|
|
602
|
+
return []
|
|
603
|
+
|
|
604
|
+
active_peer_sub_tasks = active_task_context.active_peer_sub_tasks
|
|
605
|
+
if not active_peer_sub_tasks:
|
|
606
|
+
log.debug(
|
|
607
|
+
f"No active peer sub-tasks found for logical_task_id: {logical_task_id}"
|
|
608
|
+
)
|
|
609
|
+
return []
|
|
610
|
+
|
|
611
|
+
results = []
|
|
612
|
+
for sub_task_id, correlation_data in active_peer_sub_tasks.items():
|
|
613
|
+
if sub_task_id is not None and correlation_data is not None:
|
|
614
|
+
results.append(correlation_data)
|
|
615
|
+
|
|
616
|
+
return results
|
|
617
|
+
|
|
526
618
|
async def _get_correlation_data_for_sub_task(
|
|
527
619
|
self, sub_task_id: str
|
|
528
620
|
) -> Optional[Dict[str, Any]]:
|
|
@@ -653,6 +745,14 @@ class SamAgentComponent(SamComponentBase):
|
|
|
653
745
|
paused_invocation_id = correlation_data.get("invocation_id")
|
|
654
746
|
log_retrigger = f"{self.log_identifier}[RetriggerManager:{logical_task_id}]"
|
|
655
747
|
|
|
748
|
+
# Clear paused state - task is resuming now
|
|
749
|
+
task_context.set_paused(False)
|
|
750
|
+
log.debug(
|
|
751
|
+
"%s Task %s resuming from paused state with peer responses.",
|
|
752
|
+
log_retrigger,
|
|
753
|
+
logical_task_id,
|
|
754
|
+
)
|
|
755
|
+
|
|
656
756
|
try:
|
|
657
757
|
effective_session_id = original_task_context.get("effective_session_id")
|
|
658
758
|
user_id = original_task_context.get("user_id")
|
|
@@ -683,13 +783,8 @@ class SamAgentComponent(SamComponentBase):
|
|
|
683
783
|
log_retrigger,
|
|
684
784
|
len(new_response_parts),
|
|
685
785
|
)
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
author=self.agent_name,
|
|
689
|
-
content=adk_types.Content(role="tool", parts=new_response_parts),
|
|
690
|
-
)
|
|
691
|
-
await self.session_service.append_event(
|
|
692
|
-
session=session, event=new_adk_event
|
|
786
|
+
new_tool_response_content = adk_types.Content(
|
|
787
|
+
role="tool", parts=new_response_parts
|
|
693
788
|
)
|
|
694
789
|
|
|
695
790
|
# Always use SSE streaming mode for the ADK runner, even on re-trigger.
|
|
@@ -708,7 +803,12 @@ class SamAgentComponent(SamComponentBase):
|
|
|
708
803
|
)
|
|
709
804
|
try:
|
|
710
805
|
await run_adk_async_task_thread_wrapper(
|
|
711
|
-
self,
|
|
806
|
+
self,
|
|
807
|
+
session,
|
|
808
|
+
new_tool_response_content,
|
|
809
|
+
run_config,
|
|
810
|
+
original_task_context,
|
|
811
|
+
append_context_event=False,
|
|
712
812
|
)
|
|
713
813
|
finally:
|
|
714
814
|
log.info(
|
|
@@ -897,12 +997,13 @@ class SamAgentComponent(SamComponentBase):
|
|
|
897
997
|
)
|
|
898
998
|
if peer_tool_instance.name not in llm_request.tools_dict:
|
|
899
999
|
peer_tools_to_add.append(peer_tool_instance)
|
|
900
|
-
description
|
|
901
|
-
|
|
902
|
-
|
|
1000
|
+
# Get enhanced description from the tool instance
|
|
1001
|
+
# which includes capabilities, skills, and tools
|
|
1002
|
+
enhanced_desc = peer_tool_instance._build_enhanced_description(
|
|
1003
|
+
agent_card
|
|
903
1004
|
)
|
|
904
1005
|
allowed_peer_descriptions.append(
|
|
905
|
-
f"
|
|
1006
|
+
f"\n### `peer_{peer_name}`\n{enhanced_desc}"
|
|
906
1007
|
)
|
|
907
1008
|
except Exception as e:
|
|
908
1009
|
log.error(
|
|
@@ -915,12 +1016,18 @@ class SamAgentComponent(SamComponentBase):
|
|
|
915
1016
|
if allowed_peer_descriptions:
|
|
916
1017
|
peer_list_str = "\n".join(allowed_peer_descriptions)
|
|
917
1018
|
instruction_text = (
|
|
918
|
-
"
|
|
919
|
-
"
|
|
920
|
-
"
|
|
921
|
-
"
|
|
922
|
-
"
|
|
923
|
-
"
|
|
1019
|
+
"## Peer Agent Delegation\n\n"
|
|
1020
|
+
"You can delegate tasks to other specialized agents if they are better suited.\n\n"
|
|
1021
|
+
"**How to delegate:**\n"
|
|
1022
|
+
"- Use the `peer_<agent_name>(task_description: str)` tool for delegation\n"
|
|
1023
|
+
"- Replace `<agent_name>` with the actual name of the target agent\n"
|
|
1024
|
+
"- Provide a clear and detailed `task_description` for the peer agent\n"
|
|
1025
|
+
"- **Important:** The peer agent does not have access to your session history, "
|
|
1026
|
+
"so you must provide all required context necessary to fulfill the request\n\n"
|
|
1027
|
+
"IMPORTANT: When a peer agent's response contains citation markers like [[cite:search0]], [[cite:file1]], etc., "
|
|
1028
|
+
"you MUST preserve these markers in your response to the user. These markers link to source references and are "
|
|
1029
|
+
"essential for proper attribution. Include them exactly as they appear in the peer's response. DO NOT repeat them without markers.\n\n"
|
|
1030
|
+
"## Available Peer Agents\n"
|
|
924
1031
|
f"{peer_list_str}"
|
|
925
1032
|
)
|
|
926
1033
|
callback_context.state["peer_tool_instructions"] = instruction_text
|
|
@@ -1434,6 +1541,70 @@ class SamAgentComponent(SamComponentBase):
|
|
|
1434
1541
|
)
|
|
1435
1542
|
return False
|
|
1436
1543
|
|
|
1544
|
+
async def notify_artifact_saved(
|
|
1545
|
+
self,
|
|
1546
|
+
artifact_info: ArtifactInfo,
|
|
1547
|
+
a2a_context: Dict[str, Any],
|
|
1548
|
+
function_call_id: Optional[str] = None,
|
|
1549
|
+
) -> None:
|
|
1550
|
+
"""
|
|
1551
|
+
Publishes an artifact saved notification signal.
|
|
1552
|
+
|
|
1553
|
+
This is a separate event from ArtifactCreationProgressData and does not
|
|
1554
|
+
follow the start->updates->end protocol. It's a single notification that
|
|
1555
|
+
an artifact has been successfully saved to storage.
|
|
1556
|
+
|
|
1557
|
+
Args:
|
|
1558
|
+
artifact_info: Information about the saved artifact
|
|
1559
|
+
a2a_context: The A2A context dictionary for the current task
|
|
1560
|
+
function_call_id: Optional function call ID if artifact was created by a tool
|
|
1561
|
+
"""
|
|
1562
|
+
log_identifier = (
|
|
1563
|
+
f"{self.log_identifier}[ArtifactSaved:{artifact_info.filename}]"
|
|
1564
|
+
)
|
|
1565
|
+
|
|
1566
|
+
try:
|
|
1567
|
+
# Create artifact saved signal
|
|
1568
|
+
artifact_signal = ArtifactSavedData(
|
|
1569
|
+
type="artifact_saved",
|
|
1570
|
+
filename=artifact_info.filename,
|
|
1571
|
+
version=artifact_info.version,
|
|
1572
|
+
mime_type=artifact_info.mime_type or "application/octet-stream",
|
|
1573
|
+
size_bytes=artifact_info.size,
|
|
1574
|
+
description=artifact_info.description,
|
|
1575
|
+
function_call_id=function_call_id,
|
|
1576
|
+
)
|
|
1577
|
+
|
|
1578
|
+
# Create and publish status update event
|
|
1579
|
+
logical_task_id = a2a_context.get("logical_task_id")
|
|
1580
|
+
context_id = a2a_context.get("contextId")
|
|
1581
|
+
|
|
1582
|
+
status_update_event = a2a.create_data_signal_event(
|
|
1583
|
+
task_id=logical_task_id,
|
|
1584
|
+
context_id=context_id,
|
|
1585
|
+
signal_data=artifact_signal,
|
|
1586
|
+
agent_name=self.agent_name,
|
|
1587
|
+
)
|
|
1588
|
+
|
|
1589
|
+
await self._publish_status_update_with_buffer_flush(
|
|
1590
|
+
status_update_event,
|
|
1591
|
+
a2a_context,
|
|
1592
|
+
skip_buffer_flush=False,
|
|
1593
|
+
)
|
|
1594
|
+
|
|
1595
|
+
log.debug(
|
|
1596
|
+
"%s Published artifact saved notification for '%s' v%s.",
|
|
1597
|
+
log_identifier,
|
|
1598
|
+
artifact_info.filename,
|
|
1599
|
+
artifact_info.version,
|
|
1600
|
+
)
|
|
1601
|
+
except Exception as e:
|
|
1602
|
+
log.error(
|
|
1603
|
+
"%s Failed to publish artifact saved notification: %s",
|
|
1604
|
+
log_identifier,
|
|
1605
|
+
e,
|
|
1606
|
+
)
|
|
1607
|
+
|
|
1437
1608
|
async def _publish_status_update_with_buffer_flush(
|
|
1438
1609
|
self,
|
|
1439
1610
|
status_update_event: TaskStatusUpdateEvent,
|
|
@@ -1514,7 +1685,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
1514
1685
|
payload_to_publish, target_topic, a2a_context, user_properties
|
|
1515
1686
|
)
|
|
1516
1687
|
|
|
1517
|
-
log.
|
|
1688
|
+
log.debug(
|
|
1518
1689
|
"%s Published %s status update to %s.",
|
|
1519
1690
|
log_identifier,
|
|
1520
1691
|
status_type,
|
|
@@ -1627,10 +1798,47 @@ class SamAgentComponent(SamComponentBase):
|
|
|
1627
1798
|
is_run_based_session = a2a_context.get("is_run_based_session", False)
|
|
1628
1799
|
is_final_turn_event = not adk_event.partial
|
|
1629
1800
|
|
|
1801
|
+
try:
|
|
1802
|
+
from solace_agent_mesh_enterprise.auth.tool_auth import (
|
|
1803
|
+
handle_tool_auth_event,
|
|
1804
|
+
)
|
|
1805
|
+
|
|
1806
|
+
auth_status_update = await handle_tool_auth_event(
|
|
1807
|
+
adk_event, self, a2a_context
|
|
1808
|
+
)
|
|
1809
|
+
if auth_status_update:
|
|
1810
|
+
await self._publish_status_update_with_buffer_flush(
|
|
1811
|
+
auth_status_update,
|
|
1812
|
+
a2a_context,
|
|
1813
|
+
skip_buffer_flush=False,
|
|
1814
|
+
)
|
|
1815
|
+
return
|
|
1816
|
+
except ImportError:
|
|
1817
|
+
pass
|
|
1818
|
+
|
|
1630
1819
|
if not is_final_turn_event:
|
|
1631
1820
|
if adk_event.content and adk_event.content.parts:
|
|
1632
1821
|
for part in adk_event.content.parts:
|
|
1633
1822
|
if part.text is not None:
|
|
1823
|
+
# Check if this is a new turn by comparing invocation_id
|
|
1824
|
+
if adk_event.invocation_id:
|
|
1825
|
+
task_context.check_and_update_invocation(
|
|
1826
|
+
adk_event.invocation_id
|
|
1827
|
+
)
|
|
1828
|
+
is_first_text = task_context.is_first_text_in_turn()
|
|
1829
|
+
should_add_spacing = task_context.should_add_turn_spacing()
|
|
1830
|
+
|
|
1831
|
+
# Add spacing if this is the first text of a new turn
|
|
1832
|
+
# We add it BEFORE the text, regardless of current buffer content
|
|
1833
|
+
if should_add_spacing and is_first_text:
|
|
1834
|
+
# Add double newline to separate turns (new paragraph)
|
|
1835
|
+
task_context.append_to_streaming_buffer("\n\n")
|
|
1836
|
+
log.debug(
|
|
1837
|
+
"%s Added turn spacing before new invocation %s",
|
|
1838
|
+
log_id_main,
|
|
1839
|
+
adk_event.invocation_id,
|
|
1840
|
+
)
|
|
1841
|
+
|
|
1634
1842
|
task_context.append_to_streaming_buffer(part.text)
|
|
1635
1843
|
log.debug(
|
|
1636
1844
|
"%s Appended text to buffer. New buffer size: %d bytes",
|
|
@@ -1655,7 +1863,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
1655
1863
|
)
|
|
1656
1864
|
|
|
1657
1865
|
if buffer_has_content and (batching_disabled or threshold_met):
|
|
1658
|
-
log.
|
|
1866
|
+
log.debug(
|
|
1659
1867
|
"%s Partial event triggered buffer flush due to size/batching config.",
|
|
1660
1868
|
log_id_main,
|
|
1661
1869
|
)
|
|
@@ -1678,7 +1886,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
1678
1886
|
else:
|
|
1679
1887
|
buffer_content = task_context.get_streaming_buffer_content()
|
|
1680
1888
|
if buffer_content:
|
|
1681
|
-
log.
|
|
1889
|
+
log.debug(
|
|
1682
1890
|
"%s Final event triggered flush of remaining buffer content.",
|
|
1683
1891
|
log_id_main,
|
|
1684
1892
|
)
|
|
@@ -1712,7 +1920,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
1712
1920
|
|
|
1713
1921
|
if a2a_payload and target_topic:
|
|
1714
1922
|
self._publish_a2a_event(a2a_payload, target_topic, a2a_context)
|
|
1715
|
-
log.
|
|
1923
|
+
log.debug(
|
|
1716
1924
|
"%s Published final turn event (e.g., tool call) to %s.",
|
|
1717
1925
|
log_id_main,
|
|
1718
1926
|
target_topic,
|
|
@@ -1769,7 +1977,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
1769
1977
|
log_id,
|
|
1770
1978
|
len(signals_found),
|
|
1771
1979
|
)
|
|
1772
|
-
for _signal_index, signal_data_tuple in signals_found:
|
|
1980
|
+
for _signal_index, signal_data_tuple, _placeholder in signals_found:
|
|
1773
1981
|
if (
|
|
1774
1982
|
isinstance(signal_data_tuple, tuple)
|
|
1775
1983
|
and len(signal_data_tuple) == 3
|
|
@@ -1785,6 +1993,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
1785
1993
|
await self._publish_agent_status_signal_update(
|
|
1786
1994
|
status_text, a2a_context
|
|
1787
1995
|
)
|
|
1996
|
+
resolved_text = resolved_text.replace(_placeholder, "")
|
|
1788
1997
|
|
|
1789
1998
|
return resolved_text, unprocessed_tail
|
|
1790
1999
|
|
|
@@ -1998,9 +2207,14 @@ class SamAgentComponent(SamComponentBase):
|
|
|
1998
2207
|
For STREAMING tasks, it uses the content of the last ADK event.
|
|
1999
2208
|
"""
|
|
2000
2209
|
logical_task_id = a2a_context.get("logical_task_id")
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
|
|
2210
|
+
|
|
2211
|
+
# Retrieve the original Solace message from TaskExecutionContext
|
|
2212
|
+
original_message: Optional[SolaceMessage] = None
|
|
2213
|
+
with self.active_tasks_lock:
|
|
2214
|
+
task_context = self.active_tasks.get(logical_task_id)
|
|
2215
|
+
if task_context:
|
|
2216
|
+
original_message = task_context.get_original_solace_message()
|
|
2217
|
+
|
|
2004
2218
|
log.info(
|
|
2005
2219
|
"%s Finalizing task %s successfully.", self.log_identifier, logical_task_id
|
|
2006
2220
|
)
|
|
@@ -2074,6 +2288,19 @@ class SamAgentComponent(SamComponentBase):
|
|
|
2074
2288
|
self.log_identifier,
|
|
2075
2289
|
len(task_context.produced_artifacts),
|
|
2076
2290
|
)
|
|
2291
|
+
else:
|
|
2292
|
+
if not task_context:
|
|
2293
|
+
log.warning(
|
|
2294
|
+
"%s TaskExecutionContext not found for task %s during finalization, cannot attach produced artifacts.",
|
|
2295
|
+
self.log_identifier,
|
|
2296
|
+
logical_task_id,
|
|
2297
|
+
)
|
|
2298
|
+
else:
|
|
2299
|
+
log.debug(
|
|
2300
|
+
"%s No produced artifacts to attach for task %s.",
|
|
2301
|
+
self.log_identifier,
|
|
2302
|
+
logical_task_id,
|
|
2303
|
+
)
|
|
2077
2304
|
|
|
2078
2305
|
# Add token usage summary
|
|
2079
2306
|
if task_context:
|
|
@@ -2194,9 +2421,14 @@ class SamAgentComponent(SamComponentBase):
|
|
|
2194
2421
|
Called by the background ADK thread wrapper when a task is cancelled.
|
|
2195
2422
|
"""
|
|
2196
2423
|
logical_task_id = a2a_context.get("logical_task_id")
|
|
2197
|
-
|
|
2198
|
-
|
|
2199
|
-
|
|
2424
|
+
|
|
2425
|
+
# Retrieve the original Solace message from TaskExecutionContext
|
|
2426
|
+
original_message: Optional[SolaceMessage] = None
|
|
2427
|
+
with self.active_tasks_lock:
|
|
2428
|
+
task_context = self.active_tasks.get(logical_task_id)
|
|
2429
|
+
if task_context:
|
|
2430
|
+
original_message = task_context.get_original_solace_message()
|
|
2431
|
+
|
|
2200
2432
|
log.info(
|
|
2201
2433
|
"%s Finalizing task %s as CANCELED.", self.log_identifier, logical_task_id
|
|
2202
2434
|
)
|
|
@@ -2398,9 +2630,14 @@ class SamAgentComponent(SamComponentBase):
|
|
|
2398
2630
|
Sends a COMPLETED status with an informative message.
|
|
2399
2631
|
"""
|
|
2400
2632
|
logical_task_id = a2a_context.get("logical_task_id")
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2633
|
+
|
|
2634
|
+
# Retrieve the original Solace message from TaskExecutionContext
|
|
2635
|
+
original_message: Optional[SolaceMessage] = None
|
|
2636
|
+
with self.active_tasks_lock:
|
|
2637
|
+
task_context = self.active_tasks.get(logical_task_id)
|
|
2638
|
+
if task_context:
|
|
2639
|
+
original_message = task_context.get_original_solace_message()
|
|
2640
|
+
|
|
2404
2641
|
log.info(
|
|
2405
2642
|
"%s Finalizing task %s as COMPLETED (LLM call limit reached).",
|
|
2406
2643
|
self.log_identifier,
|
|
@@ -2477,9 +2714,14 @@ class SamAgentComponent(SamComponentBase):
|
|
|
2477
2714
|
Called by the background ADK thread wrapper.
|
|
2478
2715
|
"""
|
|
2479
2716
|
logical_task_id = a2a_context.get("logical_task_id")
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
|
|
2717
|
+
|
|
2718
|
+
# Retrieve the original Solace message from TaskExecutionContext
|
|
2719
|
+
original_message: Optional[SolaceMessage] = None
|
|
2720
|
+
with self.active_tasks_lock:
|
|
2721
|
+
task_context = self.active_tasks.get(logical_task_id)
|
|
2722
|
+
if task_context:
|
|
2723
|
+
original_message = task_context.get_original_solace_message()
|
|
2724
|
+
|
|
2483
2725
|
log.error(
|
|
2484
2726
|
"%s Finalizing task %s with error: %s",
|
|
2485
2727
|
self.log_identifier,
|
|
@@ -2496,11 +2738,24 @@ class SamAgentComponent(SamComponentBase):
|
|
|
2496
2738
|
peer_reply_topic = a2a_context.get("replyToTopic")
|
|
2497
2739
|
namespace = self.get_config("namespace")
|
|
2498
2740
|
|
|
2741
|
+
# Detect context limit errors and provide user-friendly message
|
|
2742
|
+
error_message = "An unexpected error occurred during tool execution. Please try your request again. If the problem persists, contact an administrator."
|
|
2743
|
+
|
|
2744
|
+
if isinstance(exception, BadRequestError):
|
|
2745
|
+
# Use centralized error handler
|
|
2746
|
+
error_message, is_context_limit = get_error_message(exception)
|
|
2747
|
+
|
|
2748
|
+
if is_context_limit:
|
|
2749
|
+
log.error(
|
|
2750
|
+
"%s Context limit exceeded for task %s. Error: %s",
|
|
2751
|
+
self.log_identifier,
|
|
2752
|
+
logical_task_id,
|
|
2753
|
+
exception,
|
|
2754
|
+
)
|
|
2755
|
+
|
|
2499
2756
|
failed_status = a2a.create_task_status(
|
|
2500
2757
|
state=TaskState.failed,
|
|
2501
|
-
message=a2a.create_agent_text_message(
|
|
2502
|
-
text="An unexpected error occurred during tool execution. Please try your request again. If the problem persists, contact an administrator."
|
|
2503
|
-
),
|
|
2758
|
+
message=a2a.create_agent_text_message(text=error_message),
|
|
2504
2759
|
)
|
|
2505
2760
|
|
|
2506
2761
|
final_task = a2a.create_final_task(
|
|
@@ -2622,9 +2877,15 @@ class SamAgentComponent(SamComponentBase):
|
|
|
2622
2877
|
log_id,
|
|
2623
2878
|
e,
|
|
2624
2879
|
)
|
|
2625
|
-
|
|
2626
|
-
|
|
2627
|
-
|
|
2880
|
+
# Retrieve the original Solace message from TaskExecutionContext for fallback NACK
|
|
2881
|
+
original_message: Optional[SolaceMessage] = None
|
|
2882
|
+
with self.active_tasks_lock:
|
|
2883
|
+
task_context = self.active_tasks.get(logical_task_id)
|
|
2884
|
+
if task_context:
|
|
2885
|
+
original_message = (
|
|
2886
|
+
task_context.get_original_solace_message()
|
|
2887
|
+
)
|
|
2888
|
+
|
|
2628
2889
|
if original_message:
|
|
2629
2890
|
try:
|
|
2630
2891
|
original_message.call_negative_acknowledgements()
|
|
@@ -2805,6 +3066,17 @@ class SamAgentComponent(SamComponentBase):
|
|
|
2805
3066
|
main_task_id,
|
|
2806
3067
|
)
|
|
2807
3068
|
|
|
3069
|
+
# Validate agent access is allowed
|
|
3070
|
+
validate_agent_access(
|
|
3071
|
+
user_config=user_config,
|
|
3072
|
+
target_agent_name=target_agent_name,
|
|
3073
|
+
validation_context={
|
|
3074
|
+
"delegating_agent": self.get_config("agent_name"),
|
|
3075
|
+
"source": "agent_delegation",
|
|
3076
|
+
},
|
|
3077
|
+
log_identifier=log_identifier_helper,
|
|
3078
|
+
)
|
|
3079
|
+
|
|
2808
3080
|
peer_request_topic = self._get_agent_request_topic(target_agent_name)
|
|
2809
3081
|
|
|
2810
3082
|
# Create a compliant SendMessageRequest
|
|
@@ -2825,6 +3097,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
2825
3097
|
"replyTo": reply_to_topic,
|
|
2826
3098
|
"a2aStatusTopic": status_topic,
|
|
2827
3099
|
"userId": user_id,
|
|
3100
|
+
"delegating_agent_name": delegating_agent_name,
|
|
2828
3101
|
}
|
|
2829
3102
|
if isinstance(user_config, dict):
|
|
2830
3103
|
user_properties["a2aUserConfig"] = user_config
|
|
@@ -2954,6 +3227,31 @@ class SamAgentComponent(SamComponentBase):
|
|
|
2954
3227
|
or "No description available.",
|
|
2955
3228
|
}
|
|
2956
3229
|
)
|
|
3230
|
+
elif isinstance(tool, OpenAPIToolset):
|
|
3231
|
+
try:
|
|
3232
|
+
log.debug(
|
|
3233
|
+
"%s Retrieving tools from OpenAPIToolset for Agent %s...",
|
|
3234
|
+
self.log_identifier,
|
|
3235
|
+
self.agent_name,
|
|
3236
|
+
)
|
|
3237
|
+
openapi_tools = await tool.get_tools()
|
|
3238
|
+
except Exception as e:
|
|
3239
|
+
log.error(
|
|
3240
|
+
"%s Error retrieving tools from OpenAPIToolset for Agent Card %s: %s",
|
|
3241
|
+
self.log_identifier,
|
|
3242
|
+
self.agent_name,
|
|
3243
|
+
e,
|
|
3244
|
+
)
|
|
3245
|
+
continue
|
|
3246
|
+
for openapi_tool in openapi_tools:
|
|
3247
|
+
tool_manifest.append(
|
|
3248
|
+
{
|
|
3249
|
+
"id": openapi_tool.name,
|
|
3250
|
+
"name": openapi_tool.name,
|
|
3251
|
+
"description": openapi_tool.description
|
|
3252
|
+
or "No description available.",
|
|
3253
|
+
}
|
|
3254
|
+
)
|
|
2957
3255
|
else:
|
|
2958
3256
|
tool_name = getattr(tool, "name", getattr(tool, "__name__", None))
|
|
2959
3257
|
if tool_name is not None:
|
|
@@ -3011,6 +3309,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
3011
3309
|
"%s _perform_async_init: _async_init_future is None or already done before signaling failure.",
|
|
3012
3310
|
self.log_identifier,
|
|
3013
3311
|
)
|
|
3312
|
+
raise e
|
|
3014
3313
|
|
|
3015
3314
|
def cleanup(self):
|
|
3016
3315
|
"""Clean up resources on component shutdown."""
|
|
@@ -3139,6 +3438,80 @@ class SamAgentComponent(SamComponentBase):
|
|
|
3139
3438
|
"""Returns the dedicated asyncio event loop for this component's async tasks."""
|
|
3140
3439
|
return self._async_loop
|
|
3141
3440
|
|
|
3441
|
+
def publish_data_signal_from_thread(
|
|
3442
|
+
self,
|
|
3443
|
+
a2a_context: Dict[str, Any],
|
|
3444
|
+
signal_data: BaseModel,
|
|
3445
|
+
skip_buffer_flush: bool = False,
|
|
3446
|
+
log_identifier: Optional[str] = None,
|
|
3447
|
+
) -> bool:
|
|
3448
|
+
"""
|
|
3449
|
+
Publishes a data signal status update from any thread by scheduling it on the async loop.
|
|
3450
|
+
|
|
3451
|
+
This is a convenience method for tools and callbacks that need to publish status updates
|
|
3452
|
+
but are not running in an async context. It handles:
|
|
3453
|
+
1. Extracting task_id and context_id from a2a_context
|
|
3454
|
+
2. Creating the status update event
|
|
3455
|
+
3. Checking if the async loop is available and running
|
|
3456
|
+
4. Scheduling the publish operation on the async loop
|
|
3457
|
+
|
|
3458
|
+
Args:
|
|
3459
|
+
a2a_context: The A2A context dictionary containing logical_task_id and contextId
|
|
3460
|
+
signal_data: A Pydantic BaseModel instance (e.g., AgentProgressUpdateData,
|
|
3461
|
+
DeepResearchProgressData, ArtifactCreationProgressData)
|
|
3462
|
+
skip_buffer_flush: If True, skip buffer flushing before publishing
|
|
3463
|
+
log_identifier: Optional log identifier for debugging
|
|
3464
|
+
|
|
3465
|
+
Returns:
|
|
3466
|
+
bool: True if the publish was successfully scheduled, False otherwise
|
|
3467
|
+
"""
|
|
3468
|
+
from ...common import a2a
|
|
3469
|
+
|
|
3470
|
+
log_id = log_identifier or f"{self.log_identifier}[PublishDataSignal]"
|
|
3471
|
+
|
|
3472
|
+
if not a2a_context:
|
|
3473
|
+
log.error("%s No a2a_context provided. Cannot publish data signal.", log_id)
|
|
3474
|
+
return False
|
|
3475
|
+
|
|
3476
|
+
logical_task_id = a2a_context.get("logical_task_id")
|
|
3477
|
+
context_id = a2a_context.get("contextId")
|
|
3478
|
+
|
|
3479
|
+
if not logical_task_id:
|
|
3480
|
+
log.error("%s No logical_task_id in a2a_context. Cannot publish data signal.", log_id)
|
|
3481
|
+
return False
|
|
3482
|
+
|
|
3483
|
+
# Create status update event using the standard data signal pattern
|
|
3484
|
+
status_update_event = a2a.create_data_signal_event(
|
|
3485
|
+
task_id=logical_task_id,
|
|
3486
|
+
context_id=context_id,
|
|
3487
|
+
signal_data=signal_data,
|
|
3488
|
+
agent_name=self.agent_name,
|
|
3489
|
+
)
|
|
3490
|
+
|
|
3491
|
+
# Get the async loop and schedule the publish
|
|
3492
|
+
loop = self.get_async_loop()
|
|
3493
|
+
if loop and loop.is_running():
|
|
3494
|
+
asyncio.run_coroutine_threadsafe(
|
|
3495
|
+
self._publish_status_update_with_buffer_flush(
|
|
3496
|
+
status_update_event,
|
|
3497
|
+
a2a_context,
|
|
3498
|
+
skip_buffer_flush=skip_buffer_flush,
|
|
3499
|
+
),
|
|
3500
|
+
loop,
|
|
3501
|
+
)
|
|
3502
|
+
log.debug(
|
|
3503
|
+
"%s Scheduled data signal status update (type: %s).",
|
|
3504
|
+
log_id,
|
|
3505
|
+
type(signal_data).__name__,
|
|
3506
|
+
)
|
|
3507
|
+
return True
|
|
3508
|
+
else:
|
|
3509
|
+
log.error(
|
|
3510
|
+
"%s Async loop not available or not running. Cannot publish data signal.",
|
|
3511
|
+
log_id,
|
|
3512
|
+
)
|
|
3513
|
+
return False
|
|
3514
|
+
|
|
3142
3515
|
def set_agent_system_instruction_string(self, instruction_string: str) -> None:
|
|
3143
3516
|
"""
|
|
3144
3517
|
Sets a static string to be injected into the LLM system prompt.
|
|
@@ -3180,79 +3553,93 @@ class SamAgentComponent(SamComponentBase):
|
|
|
3180
3553
|
For now, using the agent name, but could be made more robust (e.g., hostname + agent name).
|
|
3181
3554
|
"""
|
|
3182
3555
|
return self.agent_name
|
|
3183
|
-
|
|
3556
|
+
|
|
3184
3557
|
def _check_agent_health(self):
|
|
3185
3558
|
"""
|
|
3186
3559
|
Checks the health of peer agents and de-registers unresponsive ones.
|
|
3187
3560
|
This is called periodically by the health check timer.
|
|
3188
3561
|
Uses TTL-based expiration to determine if an agent is unresponsive.
|
|
3189
3562
|
"""
|
|
3190
|
-
|
|
3563
|
+
|
|
3191
3564
|
log.debug("%s Performing agent health check...", self.log_identifier)
|
|
3192
|
-
|
|
3193
|
-
ttl_seconds = self.agent_discovery_config.get(
|
|
3194
|
-
|
|
3195
|
-
|
|
3565
|
+
|
|
3566
|
+
ttl_seconds = self.agent_discovery_config.get(
|
|
3567
|
+
"health_check_ttl_seconds", HEALTH_CHECK_TTL_SECONDS
|
|
3568
|
+
)
|
|
3569
|
+
health_check_interval = self.agent_discovery_config.get(
|
|
3570
|
+
"health_check_interval_seconds", HEALTH_CHECK_INTERVAL_SECONDS
|
|
3571
|
+
)
|
|
3572
|
+
|
|
3196
3573
|
log.debug(
|
|
3197
3574
|
"%s Health check configuration: interval=%d seconds, TTL=%d seconds",
|
|
3198
3575
|
self.log_identifier,
|
|
3199
3576
|
health_check_interval,
|
|
3200
|
-
ttl_seconds
|
|
3577
|
+
ttl_seconds,
|
|
3201
3578
|
)
|
|
3202
3579
|
|
|
3203
3580
|
# Validate configuration values
|
|
3204
|
-
if
|
|
3581
|
+
if (
|
|
3582
|
+
ttl_seconds <= 0
|
|
3583
|
+
or health_check_interval <= 0
|
|
3584
|
+
or ttl_seconds < health_check_interval
|
|
3585
|
+
):
|
|
3205
3586
|
log.error(
|
|
3206
3587
|
"%s agent_health_check_ttl_seconds (%d) and agent_health_check_interval_seconds (%d) must be positive and TTL must be greater than interval.",
|
|
3207
3588
|
self.log_identifier,
|
|
3208
3589
|
ttl_seconds,
|
|
3209
|
-
health_check_interval
|
|
3590
|
+
health_check_interval,
|
|
3591
|
+
)
|
|
3592
|
+
raise ValueError(
|
|
3593
|
+
f"Invalid health check configuration. agent_health_check_ttl_seconds ({ttl_seconds}) and agent_health_check_interval_seconds ({health_check_interval}) must be positive and TTL must be greater than interval."
|
|
3210
3594
|
)
|
|
3211
|
-
|
|
3212
|
-
|
|
3595
|
+
|
|
3213
3596
|
# Get all agent names from the registry
|
|
3214
3597
|
agent_names = self.agent_registry.get_agent_names()
|
|
3215
3598
|
total_agents = len(agent_names)
|
|
3216
3599
|
agents_to_deregister = []
|
|
3217
|
-
|
|
3218
|
-
log.debug(
|
|
3219
|
-
|
|
3600
|
+
|
|
3601
|
+
log.debug(
|
|
3602
|
+
"%s Checking health of %d peer agents", self.log_identifier, total_agents
|
|
3603
|
+
)
|
|
3604
|
+
|
|
3220
3605
|
for agent_name in agent_names:
|
|
3221
3606
|
# Skip our own agent
|
|
3222
3607
|
if agent_name == self.agent_name:
|
|
3223
3608
|
continue
|
|
3224
|
-
|
|
3609
|
+
|
|
3225
3610
|
# Check if the agent's TTL has expired
|
|
3226
|
-
is_expired, time_since_last_seen = self.agent_registry.check_ttl_expired(
|
|
3227
|
-
|
|
3611
|
+
is_expired, time_since_last_seen = self.agent_registry.check_ttl_expired(
|
|
3612
|
+
agent_name, ttl_seconds
|
|
3613
|
+
)
|
|
3614
|
+
|
|
3228
3615
|
if is_expired:
|
|
3229
3616
|
log.warning(
|
|
3230
3617
|
"%s Agent '%s' TTL has expired. De-registering. Time since last seen: %d seconds (TTL: %d seconds)",
|
|
3231
3618
|
self.log_identifier,
|
|
3232
3619
|
agent_name,
|
|
3233
3620
|
time_since_last_seen,
|
|
3234
|
-
ttl_seconds
|
|
3621
|
+
ttl_seconds,
|
|
3235
3622
|
)
|
|
3236
3623
|
agents_to_deregister.append(agent_name)
|
|
3237
|
-
|
|
3624
|
+
|
|
3238
3625
|
# De-register unresponsive agents
|
|
3239
3626
|
for agent_name in agents_to_deregister:
|
|
3240
3627
|
self._deregister_agent(agent_name)
|
|
3241
|
-
|
|
3628
|
+
|
|
3242
3629
|
log.debug(
|
|
3243
3630
|
"%s Agent health check completed. Total agents: %d, De-registered: %d",
|
|
3244
3631
|
self.log_identifier,
|
|
3245
3632
|
total_agents,
|
|
3246
|
-
len(agents_to_deregister)
|
|
3633
|
+
len(agents_to_deregister),
|
|
3247
3634
|
)
|
|
3248
|
-
|
|
3635
|
+
|
|
3249
3636
|
def _deregister_agent(self, agent_name: str):
|
|
3250
3637
|
"""
|
|
3251
3638
|
De-registers an agent from the registry and publishes a de-registration event.
|
|
3252
3639
|
"""
|
|
3253
3640
|
# Remove from registry
|
|
3254
3641
|
registry_removed = self.agent_registry.remove_agent(agent_name)
|
|
3255
|
-
|
|
3642
|
+
|
|
3256
3643
|
# Always remove from peer_agents regardless of registry result
|
|
3257
3644
|
peer_removed = False
|
|
3258
3645
|
if agent_name in self.peer_agents:
|
|
@@ -3261,18 +3648,18 @@ class SamAgentComponent(SamComponentBase):
|
|
|
3261
3648
|
log.info(
|
|
3262
3649
|
"%s Removed agent '%s' from peer_agents dictionary",
|
|
3263
3650
|
self.log_identifier,
|
|
3264
|
-
agent_name
|
|
3651
|
+
agent_name,
|
|
3265
3652
|
)
|
|
3266
|
-
|
|
3653
|
+
|
|
3267
3654
|
# Publish de-registration event if agent was in either data structure
|
|
3268
3655
|
if registry_removed or peer_removed:
|
|
3269
3656
|
try:
|
|
3270
3657
|
# Create a de-registration event topic
|
|
3271
3658
|
namespace = self.get_config("namespace")
|
|
3272
3659
|
deregistration_topic = f"{namespace}/a2a/events/agent/deregistered"
|
|
3273
|
-
|
|
3660
|
+
|
|
3274
3661
|
current_time = time.time()
|
|
3275
|
-
|
|
3662
|
+
|
|
3276
3663
|
# Create the payload
|
|
3277
3664
|
deregistration_payload = {
|
|
3278
3665
|
"event_type": "agent.deregistered",
|
|
@@ -3280,28 +3667,27 @@ class SamAgentComponent(SamComponentBase):
|
|
|
3280
3667
|
"reason": "health_check_failure",
|
|
3281
3668
|
"metadata": {
|
|
3282
3669
|
"timestamp": current_time,
|
|
3283
|
-
"deregistered_by": self.agent_name
|
|
3284
|
-
}
|
|
3670
|
+
"deregistered_by": self.agent_name,
|
|
3671
|
+
},
|
|
3285
3672
|
}
|
|
3286
|
-
|
|
3673
|
+
|
|
3287
3674
|
# Publish the event
|
|
3288
3675
|
self.publish_a2a_message(
|
|
3289
|
-
payload=deregistration_payload,
|
|
3290
|
-
topic=deregistration_topic
|
|
3676
|
+
payload=deregistration_payload, topic=deregistration_topic
|
|
3291
3677
|
)
|
|
3292
|
-
|
|
3678
|
+
|
|
3293
3679
|
log.info(
|
|
3294
3680
|
"%s Published de-registration event for agent '%s' to topic '%s'",
|
|
3295
3681
|
self.log_identifier,
|
|
3296
3682
|
agent_name,
|
|
3297
|
-
deregistration_topic
|
|
3683
|
+
deregistration_topic,
|
|
3298
3684
|
)
|
|
3299
3685
|
except Exception as e:
|
|
3300
3686
|
log.error(
|
|
3301
3687
|
"%s Failed to publish de-registration event for agent '%s': %s",
|
|
3302
3688
|
self.log_identifier,
|
|
3303
3689
|
agent_name,
|
|
3304
|
-
e
|
|
3690
|
+
e,
|
|
3305
3691
|
)
|
|
3306
3692
|
|
|
3307
3693
|
async def _resolve_early_embeds_and_handle_signals(
|
|
@@ -3356,11 +3742,12 @@ class SamAgentComponent(SamComponentBase):
|
|
|
3356
3742
|
resolver_config = context_for_embeds["config"]
|
|
3357
3743
|
|
|
3358
3744
|
try:
|
|
3745
|
+
from ...common.utils.embeds.constants import EARLY_EMBED_TYPES
|
|
3746
|
+
from ...common.utils.embeds.types import ResolutionMode
|
|
3359
3747
|
from ...common.utils.embeds.resolver import (
|
|
3360
|
-
resolve_embeds_in_string,
|
|
3361
3748
|
evaluate_embed,
|
|
3749
|
+
resolve_embeds_in_string,
|
|
3362
3750
|
)
|
|
3363
|
-
from ...common.utils.embeds.constants import EARLY_EMBED_TYPES
|
|
3364
3751
|
|
|
3365
3752
|
resolved_text, processed_until_index, signals_found = (
|
|
3366
3753
|
await resolve_embeds_in_string(
|
|
@@ -3368,6 +3755,7 @@ class SamAgentComponent(SamComponentBase):
|
|
|
3368
3755
|
context=context_for_embeds,
|
|
3369
3756
|
resolver_func=evaluate_embed,
|
|
3370
3757
|
types_to_resolve=EARLY_EMBED_TYPES,
|
|
3758
|
+
resolution_mode=ResolutionMode.TOOL_PARAMETER,
|
|
3371
3759
|
log_identifier=method_context_log_identifier,
|
|
3372
3760
|
config=resolver_config,
|
|
3373
3761
|
)
|
|
@@ -3387,16 +3775,62 @@ class SamAgentComponent(SamComponentBase):
|
|
|
3387
3775
|
)
|
|
3388
3776
|
return raw_text, [], ""
|
|
3389
3777
|
|
|
3778
|
+
def _publish_agent_card(self) -> None:
|
|
3779
|
+
"""
|
|
3780
|
+
Schedules periodic publishing of the agent card based on configuration.
|
|
3781
|
+
"""
|
|
3782
|
+
try:
|
|
3783
|
+
publish_interval_sec = self.agent_card_publishing_config.get(
|
|
3784
|
+
"interval_seconds"
|
|
3785
|
+
)
|
|
3786
|
+
if publish_interval_sec and publish_interval_sec > 0:
|
|
3787
|
+
log.info(
|
|
3788
|
+
"%s Scheduling agent card publishing every %d seconds.",
|
|
3789
|
+
self.log_identifier,
|
|
3790
|
+
publish_interval_sec,
|
|
3791
|
+
)
|
|
3792
|
+
# Register timer with callback
|
|
3793
|
+
self.add_timer(
|
|
3794
|
+
delay_ms=1000,
|
|
3795
|
+
timer_id=self._card_publish_timer_id,
|
|
3796
|
+
interval_ms=publish_interval_sec * 1000,
|
|
3797
|
+
callback=lambda timer_data: publish_agent_card(self),
|
|
3798
|
+
)
|
|
3799
|
+
else:
|
|
3800
|
+
log.warning(
|
|
3801
|
+
"%s Agent card publishing interval not configured or invalid, card will not be published periodically.",
|
|
3802
|
+
self.log_identifier,
|
|
3803
|
+
)
|
|
3804
|
+
except Exception as e:
|
|
3805
|
+
log.exception(
|
|
3806
|
+
"%s Error during _publish_agent_card setup: %s",
|
|
3807
|
+
self.log_identifier,
|
|
3808
|
+
e,
|
|
3809
|
+
)
|
|
3810
|
+
raise e
|
|
3811
|
+
|
|
3390
3812
|
async def _async_setup_and_run(self) -> None:
|
|
3391
3813
|
"""
|
|
3392
3814
|
Main async logic for the agent component.
|
|
3393
3815
|
This is called by the base class's `_run_async_operations`.
|
|
3394
3816
|
"""
|
|
3395
|
-
|
|
3396
|
-
|
|
3817
|
+
try:
|
|
3818
|
+
# Call base class to initialize Trust Manager
|
|
3819
|
+
await super()._async_setup_and_run()
|
|
3820
|
+
|
|
3821
|
+
# Perform agent-specific async initialization
|
|
3822
|
+
await self._perform_async_init()
|
|
3823
|
+
|
|
3824
|
+
self._publish_agent_card()
|
|
3397
3825
|
|
|
3398
|
-
|
|
3399
|
-
|
|
3826
|
+
except Exception as e:
|
|
3827
|
+
log.exception(
|
|
3828
|
+
"%s Error during _async_setup_and_run: %s",
|
|
3829
|
+
self.log_identifier,
|
|
3830
|
+
e,
|
|
3831
|
+
)
|
|
3832
|
+
self.cleanup()
|
|
3833
|
+
raise e
|
|
3400
3834
|
|
|
3401
3835
|
def _pre_async_cleanup(self) -> None:
|
|
3402
3836
|
"""
|