solace-agent-mesh 1.7.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/artifacts/filesystem_artifact_service.py +164 -0
- solace_agent_mesh/agent/adk/artifacts/s3_artifact_service.py +163 -0
- solace_agent_mesh/agent/adk/callbacks.py +752 -127
- solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +99 -7
- 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 +34 -16
- solace_agent_mesh/agent/adk/models/oauth2_token_manager.py +24 -137
- solace_agent_mesh/agent/adk/runner.py +66 -8
- solace_agent_mesh/agent/adk/schema_migration.py +88 -0
- solace_agent_mesh/agent/adk/services.py +41 -1
- solace_agent_mesh/agent/adk/setup.py +220 -32
- solace_agent_mesh/agent/adk/stream_parser.py +229 -40
- solace_agent_mesh/agent/protocol/event_handlers.py +219 -33
- 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/component.py +188 -22
- solace_agent_mesh/agent/proxies/base/proxy_task_context.py +3 -1
- solace_agent_mesh/agent/sac/app.py +37 -12
- solace_agent_mesh/agent/sac/component.py +322 -52
- solace_agent_mesh/agent/sac/patch_adk.py +8 -16
- solace_agent_mesh/agent/sac/task_execution_context.py +90 -0
- 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 +698 -24
- solace_agent_mesh/agent/tools/deep_research_tools.py +2161 -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 +54 -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 +243 -5
- 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/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/64195356.09dbd087.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/66d4869e.30340bd3.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6aaedf65.7253541d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6d84eae0.fd23ba4a.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/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/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/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/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 +75 -75
- 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 +98 -112
- 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 -28
- solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +29 -29
- 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 +67 -53
- solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +17 -17
- 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 +87 -87
- 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 +50 -23
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/connectors/index.html +29 -24
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +21 -21
- 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 +96 -66
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/secure-user-delegated-access/index.html +181 -181
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +75 -75
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/wheel-installation/index.html +27 -27
- 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 -38
- 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 +135 -114
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +37 -37
- 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 +112 -112
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/user-feedback/index.html +28 -28
- 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/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-tcIFZLis.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-CINwxvwV.js → vendor-CGk8Suyh.js} +189 -94
- 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/types.py +1 -1
- solace_agent_mesh/common/agent_registry.py +38 -11
- solace_agent_mesh/common/data_parts.py +124 -0
- 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 +73 -1
- solace_agent_mesh/common/sam_events/event_service.py +2 -2
- solace_agent_mesh/common/utils/embeds/converter.py +1 -8
- solace_agent_mesh/common/utils/embeds/modifiers.py +2 -27
- solace_agent_mesh/common/utils/embeds/resolver.py +94 -25
- solace_agent_mesh/common/utils/embeds/types.py +1 -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/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/base.py +28 -1
- solace_agent_mesh/gateway/adapter/types.py +9 -0
- solace_agent_mesh/gateway/base/app.py +10 -0
- solace_agent_mesh/gateway/base/auth_interface.py +103 -0
- solace_agent_mesh/gateway/base/component.py +451 -10
- solace_agent_mesh/gateway/generic/component.py +274 -30
- solace_agent_mesh/gateway/http_sse/alembic/env.py +0 -7
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_soft_delete_and_search.py +2 -43
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_default_agent_to_projects.py +2 -2
- 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 +23 -6
- solace_agent_mesh/gateway/http_sse/component.py +158 -73
- solace_agent_mesh/gateway/http_sse/dependencies.py +50 -57
- solace_agent_mesh/gateway/http_sse/main.py +58 -482
- solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +2 -2
- solace_agent_mesh/gateway/http_sse/repository/entities/project.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/entities/project_user.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/entities/session.py +3 -2
- solace_agent_mesh/gateway/http_sse/repository/entities/task.py +7 -0
- solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +2 -2
- solace_agent_mesh/gateway/http_sse/repository/interfaces.py +2 -2
- solace_agent_mesh/gateway/http_sse/repository/models/__init__.py +5 -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 +1 -1
- solace_agent_mesh/gateway/http_sse/repository/models/task_model.py +8 -1
- solace_agent_mesh/gateway/http_sse/repository/project_repository.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/project_user_repository.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/session_repository.py +12 -107
- 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 +113 -7
- solace_agent_mesh/gateway/http_sse/routers/auth.py +69 -132
- solace_agent_mesh/gateway/http_sse/routers/config.py +235 -10
- 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/session_requests.py +1 -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 +1 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +3 -2
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/version_responses.py +31 -0
- solace_agent_mesh/gateway/http_sse/routers/feedback.py +2 -2
- solace_agent_mesh/gateway/http_sse/routers/people.py +2 -2
- solace_agent_mesh/gateway/http_sse/routers/projects.py +250 -24
- solace_agent_mesh/gateway/http_sse/routers/prompts.py +1416 -0
- solace_agent_mesh/gateway/http_sse/routers/sessions.py +14 -5
- solace_agent_mesh/gateway/http_sse/routers/speech.py +355 -0
- solace_agent_mesh/gateway/http_sse/routers/sse.py +117 -4
- solace_agent_mesh/gateway/http_sse/routers/tasks.py +509 -149
- 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 +2 -1
- 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 +539 -12
- solace_agent_mesh/gateway/http_sse/services/prompt_builder_assistant.py +303 -0
- solace_agent_mesh/gateway/http_sse/services/session_service.py +198 -21
- solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +354 -4
- solace_agent_mesh/gateway/http_sse/sse_manager.py +280 -169
- 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 +1 -1
- 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.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/METADATA +29 -8
- {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/RECORD +334 -313
- {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/WHEEL +1 -1
- solace_agent_mesh/agent/adk/adk_llm.txt +0 -226
- 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 -189
- solace_agent_mesh/agent/agent_llm.txt +0 -369
- 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/proxies/a2a/a2a_llm.txt +0 -190
- solace_agent_mesh/agent/proxies/base/base_llm.txt +0 -148
- solace_agent_mesh/agent/proxies/proxies_llm.txt +0 -283
- 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 -58
- solace_agent_mesh/agent/testing/testing_llm_detail.txt +0 -68
- solace_agent_mesh/agent/tools/tools_llm.txt +0 -276
- solace_agent_mesh/agent/tools/tools_llm_detail.txt +0 -275
- solace_agent_mesh/agent/utils/utils_llm.txt +0 -152
- solace_agent_mesh/agent/utils/utils_llm_detail.txt +0 -149
- solace_agent_mesh/assets/docs/assets/js/05749d90.c70b2be9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/15ba94aa.92fea363.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/15e40e79.36003774.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/240a0364.c39f8388.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.e4870a49.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3ff0015d.b63ee53a.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/547e15cc.2f7790c1.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/55b7b518.f2b1d1ba.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/5c2bd65f.45b32c2b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/64195356.c498c4d0.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/66d4869e.830d443f.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/6d84eae0.4a5fbf39.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/8024126c.fa0e7186.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.09ed9234.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.245ae0ef.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/c93cbaa0.eaff365e.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/cbe2e9ea.f902fad8.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/db5d6442.3daf1696.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e04b235d.c9c50c7b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e3d9abda.d11c67a7.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e6f9706b.045d0fa1.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e92d0134.3bda61dd.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/f284c35a.5099c51e.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/main.f213fe0c.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/runtime~main.d9606d6a.js +0 -1
- solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes-deployment/index.html +0 -47
- solace_agent_mesh/assets/docs/lunr-index-1762283454666.json +0 -1
- solace_agent_mesh/assets/docs/search-doc-1762283454666.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-CRYdKo2Q.js +0 -25
- solace_agent_mesh/client/webui/frontend/static/assets/main-CojeY_1w.css +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main-ILja9MCG.js +0 -353
- solace_agent_mesh/common/a2a/a2a_llm.txt +0 -175
- solace_agent_mesh/common/a2a/a2a_llm_detail.txt +0 -193
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +0 -445
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm_detail.txt +0 -736
- solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +0 -330
- solace_agent_mesh/common/common_llm.txt +0 -230
- 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 -81
- solace_agent_mesh/common/services/services_llm.txt +0 -368
- 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 -335
- 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 -226
- solace_agent_mesh/gateway/base/base_llm_detail.txt +0 -235
- solace_agent_mesh/gateway/gateway_llm.txt +0 -369
- solace_agent_mesh/gateway/gateway_llm_detail.txt +0 -3885
- solace_agent_mesh/gateway/http_sse/alembic/alembic_llm.txt +0 -345
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_fulltext_search_indexes.py +0 -92
- solace_agent_mesh/gateway/http_sse/alembic/versions/versions_llm.txt +0 -161
- 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 -221
- solace_agent_mesh/gateway/http_sse/repository/models/models_llm.txt +0 -257
- solace_agent_mesh/gateway/http_sse/repository/repository_llm.txt +0 -308
- solace_agent_mesh/gateway/http_sse/routers/dto/dto_llm.txt +0 -450
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/requests_llm.txt +0 -133
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/responses_llm.txt +0 -123
- solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +0 -312
- solace_agent_mesh/gateway/http_sse/services/services_llm.txt +0 -303
- solace_agent_mesh/gateway/http_sse/shared/__init__.py +0 -146
- solace_agent_mesh/gateway/http_sse/shared/shared_llm.txt +0 -319
- 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/assets/docs/assets/js/{main.f213fe0c.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.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/licenses/LICENSE +0 -0
solace_agent_mesh/llm_detail.txt
DELETED
|
@@ -1,2835 +0,0 @@
|
|
|
1
|
-
# LLM Summary Detail File
|
|
2
|
-
|
|
3
|
-
This file is a concatenation of all individual *llm.txt files found in the directory tree. Each section below corresponds to a specific directory's summary file.
|
|
4
|
-
|
|
5
|
-
================================================================================
|
|
6
|
-
|
|
7
|
-
## Section 1: agent/adk/adk_llm.txt
|
|
8
|
-
|
|
9
|
-
**Source file:** `agent/adk/adk_llm.txt`
|
|
10
|
-
|
|
11
|
-
Here is the comprehensive developer guide for the `adk` directory.
|
|
12
|
-
|
|
13
|
-
## Quick Summary
|
|
14
|
-
The `adk` directory serves as the core integration layer between the Solace AI Connector framework and Google's Agent Development Kit (ADK). It provides the essential components for building, configuring, and running sophisticated AI agents within a Solace messaging environment.
|
|
15
|
-
|
|
16
|
-
The architecture is designed for modularity and extensibility. The `setup.py` module acts as the main configuration hub, using factory functions from `services.py` to initialize pluggable services (like `FilesystemArtifactService` for artifact storage) and loading tools (Python functions, MCP tools) via the `ADKToolWrapper`.
|
|
17
|
-
|
|
18
|
-
Once initialized, the `AppLlmAgent` (a custom agent class) is managed by the `runner.py` module, which handles the asynchronous task execution loop. The agent's behavior is dynamically augmented at runtime by a rich set of callbacks from `callbacks.py`. These callbacks inject dynamic instructions, manage large tool responses, log events to Solace, and handle advanced features like streaming artifact creation and auto-continuation of conversations. The `models/` subdirectory provides the concrete LLM clients, with `LiteLlm` offering broad compatibility with various model providers.
|
|
19
|
-
|
|
20
|
-
## Files and Subdirectories Overview
|
|
21
|
-
- **Direct files:**
|
|
22
|
-
- `__init__.py`: Standard Python package initializer.
|
|
23
|
-
- `app_llm_agent.py`: Defines a custom `LlmAgent` subclass that holds a reference to its host component.
|
|
24
|
-
- `callbacks.py`: Provides a rich set of ADK callback functions for dynamic instructions, metadata injection, and Solace integration.
|
|
25
|
-
- `filesystem_artifact_service.py`: A local filesystem-based implementation of ADK's `BaseArtifactService`.
|
|
26
|
-
- `invocation_monitor.py`: A utility for monitoring and logging agent invocations to YAML files for debugging.
|
|
27
|
-
- `runner.py`: Manages the asynchronous execution of ADK agent tasks, including cancellation support.
|
|
28
|
-
- `services.py`: Contains factory functions for initializing ADK services (session, artifact, memory) based on configuration.
|
|
29
|
-
- `setup.py`: Handles the high-level initialization of the ADK agent, tools, and runner.
|
|
30
|
-
- `stream_parser.py`: An internal utility for parsing fenced artifact blocks from an LLM's streaming response.
|
|
31
|
-
- `tool_wrapper.py`: A wrapper for Python functions to make them compatible with ADK, handling embed resolution and config injection.
|
|
32
|
-
- **Subdirectories:**
|
|
33
|
-
- `models/`: Contains concrete `BaseLlm` implementations for interfacing with various LLM providers.
|
|
34
|
-
|
|
35
|
-
## Developer API Reference
|
|
36
|
-
|
|
37
|
-
### Direct Files
|
|
38
|
-
|
|
39
|
-
#### app_llm_agent.py
|
|
40
|
-
**Purpose:** A custom `LlmAgent` subclass that includes a reference to its hosting component, allowing callbacks and tools to access host-level configurations and services.
|
|
41
|
-
**Import:** `from agent.adk.app_llm_agent import AppLlmAgent`
|
|
42
|
-
|
|
43
|
-
**Classes/Functions/Constants:**
|
|
44
|
-
- `AppLlmAgent(host_component: Any = None, **kwargs)`: A custom `LlmAgent` that can be linked to a host component. The `host_component` is set post-initialization and is excluded from serialization.
|
|
45
|
-
|
|
46
|
-
#### callbacks.py
|
|
47
|
-
**Purpose:** Provides a suite of ADK callback functions that hook into the agent's lifecycle to inject custom logic. These are typically not called directly but are assigned to the agent during setup.
|
|
48
|
-
**Import:** `from agent.adk import callbacks`
|
|
49
|
-
|
|
50
|
-
**Classes/Functions/Constants:**
|
|
51
|
-
- `inject_dynamic_instructions_callback(...)`: Injects instructions into the prompt based on host configuration, active tools, and peer agents.
|
|
52
|
-
- `manage_large_mcp_tool_responses_callback(...)`: Intercepts large tool responses, saves them as artifacts, and returns a truncated summary to the LLM.
|
|
53
|
-
- `after_tool_callback_inject_metadata(...)`: After a tool creates an artifact, this loads its metadata and injects it into the tool response.
|
|
54
|
-
- `process_artifact_blocks_callback(...)`: Processes streaming text to identify and save fenced artifact blocks (e.g., `«««save_artifact:...»»»`).
|
|
55
|
-
- `auto_continue_on_max_tokens_callback(...)`: Automatically continues a conversation if the LLM response was interrupted due to token limits.
|
|
56
|
-
- `notify_tool_invocation_start_callback(...)`: Sends a status update over Solace when a tool is about to be invoked.
|
|
57
|
-
- `solace_llm_invocation_callback(...)`: Sends a status update over Solace when the agent calls the LLM.
|
|
58
|
-
|
|
59
|
-
#### filesystem_artifact_service.py
|
|
60
|
-
**Purpose:** An implementation of `BaseArtifactService` that stores artifacts on the local filesystem, organized by scope, user, and session.
|
|
61
|
-
**Import:** `from agent.adk.filesystem_artifact_service import FilesystemArtifactService`
|
|
62
|
-
|
|
63
|
-
**Classes/Functions/Constants:**
|
|
64
|
-
- `FilesystemArtifactService(base_path: str, scope_identifier: str)`: A service for managing artifacts on the local disk.
|
|
65
|
-
- `async save_artifact(...) -> int`: Saves an artifact and returns its version number.
|
|
66
|
-
- `async load_artifact(...) -> Optional[adk_types.Part]`: Loads a specific version of an artifact, or the latest if unspecified.
|
|
67
|
-
- `async list_artifact_keys(...) -> List[str]`: Lists the names of all artifacts for a given user/session.
|
|
68
|
-
- `async delete_artifact(...)`: Deletes an artifact and all its versions.
|
|
69
|
-
|
|
70
|
-
#### invocation_monitor.py
|
|
71
|
-
**Purpose:** A debugging utility that logs the entire lifecycle of an agent invocation, from the initial request to the final response, into a structured YAML file.
|
|
72
|
-
**Import:** `from agent.adk.invocation_monitor import InvocationMonitor`
|
|
73
|
-
|
|
74
|
-
**Classes/Functions/Constants:**
|
|
75
|
-
- `InvocationMonitor()`: A class that monitors and logs agent message flows.
|
|
76
|
-
- `log_message_event(direction: str, topic: str, payload: any, ...)`: Logs a single message event. The monitor automatically starts and stops logging based on topic patterns.
|
|
77
|
-
- `cleanup()`: Finalizes any active logging sessions.
|
|
78
|
-
|
|
79
|
-
#### runner.py
|
|
80
|
-
**Purpose:** Provides the core asynchronous task execution logic for the ADK agent, including robust cancellation handling.
|
|
81
|
-
**Import:** `from agent.adk.runner import run_adk_async_task_thread_wrapper, TaskCancelledError`
|
|
82
|
-
|
|
83
|
-
**Classes/Functions/Constants:**
|
|
84
|
-
- `run_adk_async_task_thread_wrapper(component, adk_session, adk_content, ...)`: A high-level wrapper that runs an ADK task in a separate thread and handles all cleanup and error finalization.
|
|
85
|
-
- `TaskCancelledError(Exception)`: Custom exception raised when an agent task is cancelled externally.
|
|
86
|
-
|
|
87
|
-
#### services.py
|
|
88
|
-
**Purpose:** Provides factory functions to initialize the various ADK services based on the agent's configuration file.
|
|
89
|
-
**Import:** `from agent.adk.services import initialize_session_service, initialize_artifact_service, initialize_memory_service`
|
|
90
|
-
|
|
91
|
-
**Classes/Functions/Constants:**
|
|
92
|
-
- `initialize_session_service(component) -> BaseSessionService`: Creates a session service (e.g., `InMemorySessionService`).
|
|
93
|
-
- `initialize_artifact_service(component) -> BaseArtifactService`: Creates an artifact service (e.g., `FilesystemArtifactService`, `GcsArtifactService`).
|
|
94
|
-
- `initialize_memory_service(component) -> BaseMemoryService`: Creates a memory service (e.g., `InMemoryMemoryService`).
|
|
95
|
-
|
|
96
|
-
#### setup.py
|
|
97
|
-
**Purpose:** The main entry point for configuring and instantiating the ADK agent and its dependencies. These functions tie all the other modules together.
|
|
98
|
-
**Import:** `from agent.adk.setup import load_adk_tools, initialize_adk_agent, initialize_adk_runner`
|
|
99
|
-
|
|
100
|
-
**Classes/Functions/Constants:**
|
|
101
|
-
- `async load_adk_tools(component) -> Tuple[...]`: Loads all configured tools, including Python functions, MCP tools, and built-ins, wrapping them with `ADKToolWrapper`.
|
|
102
|
-
- `initialize_adk_agent(component, loaded_explicit_tools, ...)`: Creates an `AppLlmAgent` instance, assigns all the necessary callbacks from `callbacks.py`, and attaches the tools.
|
|
103
|
-
- `initialize_adk_
|
|
104
|
-
|
|
105
|
-
================================================================================
|
|
106
|
-
|
|
107
|
-
## Section 2: agent/adk/models/models_llm.txt
|
|
108
|
-
|
|
109
|
-
**Source file:** `agent/adk/models/models_llm.txt`
|
|
110
|
-
|
|
111
|
-
Here is the developer guide for the `models` directory.
|
|
112
|
-
|
|
113
|
-
## Quick Summary
|
|
114
|
-
This directory contains concrete implementations of the `BaseLlm` interface, acting as wrappers or clients for various Large Language Model APIs. These classes translate the ADK's standard `LlmRequest` into the format required by the specific LLM backend and parse the backend's response back into a standard `LlmResponse`.
|
|
115
|
-
|
|
116
|
-
## Files Overview
|
|
117
|
-
- `lite_llm.py`: An LLM client that uses the `litellm` library to support a wide variety of models from different providers.
|
|
118
|
-
|
|
119
|
-
## Developer API Reference
|
|
120
|
-
|
|
121
|
-
### lite_llm.py
|
|
122
|
-
**Purpose:** Provides the `LiteLlm` class, a `BaseLlm` implementation that interfaces with hundreds of LLM models through the `litellm` library. This allows developers to use models from providers like OpenAI, Anthropic, Vertex AI, etc., by simply changing the model string. Environment variables required by the target model provider must be set.
|
|
123
|
-
|
|
124
|
-
**Import:** `from google.adk.models.lite_llm import LiteLlm`
|
|
125
|
-
|
|
126
|
-
**Classes:**
|
|
127
|
-
- `LiteLlm(model: str, **kwargs)` - Wrapper around `litellm` that can be used with any model it supports.
|
|
128
|
-
- `__init__(self, model: str, **kwargs)` - Initializes the `LiteLlm` client.
|
|
129
|
-
- **model**: The name of the model as recognized by `litellm` (e.g., `"vertex_ai/gemini-1.5-pro-preview-0409"`, `"claude-3-opus-20240229"`, `"gpt-4-turbo"`).
|
|
130
|
-
- **\*\*kwargs**: Additional arguments to pass directly to the `litellm.completion` or `litellm.acompletion` API on every call.
|
|
131
|
-
- `async generate_content_async(llm_request: LlmRequest, stream: bool = False) -> AsyncGenerator[LlmResponse, None]` - Sends a request to the configured LLM and yields one or more responses.
|
|
132
|
-
- **llm_request**: The request object containing conversation history, tool definitions, and configuration.
|
|
133
|
-
- **stream**: If `True`, yields partial responses as they become available. If `False`, yields a single, complete response.
|
|
134
|
-
- **Returns**: An async generator that yields `LlmResponse` objects.
|
|
135
|
-
- `supported_models() -> list[str]` - Provides a list of supported models. For `LiteLlm`, this returns an empty list because `litellm` supports a vast and dynamic set of models. Refer to the `litellm` documentation for a complete list.
|
|
136
|
-
|
|
137
|
-
**Usage Examples:**
|
|
138
|
-
```python
|
|
139
|
-
import asyncio
|
|
140
|
-
import os
|
|
141
|
-
from google.adk.models.lite_llm import LiteLlm
|
|
142
|
-
from google.adk.models.llm_request import LlmRequest, LlmConfig
|
|
143
|
-
from google.adk.models.types import Content, Part
|
|
144
|
-
|
|
145
|
-
# Example using a Vertex AI model via litellm.
|
|
146
|
-
# Set environment variables required by the provider.
|
|
147
|
-
# os.environ["VERTEXAI_PROJECT"] = "your-gcp-project-id"
|
|
148
|
-
# os.environ["VERTEXAI_LOCATION"] = "your-gcp-location"
|
|
149
|
-
|
|
150
|
-
# Example using an OpenAI model via litellm.
|
|
151
|
-
# os.environ["OPENAI_API_KEY"] = "your-openai-api-key"
|
|
152
|
-
|
|
153
|
-
async def main():
|
|
154
|
-
# Instantiate the LiteLlm client with a specific model.
|
|
155
|
-
# Any additional kwargs are passed to litellm's completion call.
|
|
156
|
-
llm = LiteLlm(
|
|
157
|
-
model="gpt-4-turbo",
|
|
158
|
-
temperature=0.5,
|
|
159
|
-
max_tokens=150
|
|
160
|
-
)
|
|
161
|
-
|
|
162
|
-
# Construct a request to the LLM
|
|
163
|
-
request = LlmRequest(
|
|
164
|
-
contents=[
|
|
165
|
-
Content(
|
|
166
|
-
role="user",
|
|
167
|
-
parts=[Part.from_text("Why is the sky blue?")]
|
|
168
|
-
)
|
|
169
|
-
],
|
|
170
|
-
config=LlmConfig(
|
|
171
|
-
# The temperature set in the constructor can be overridden here
|
|
172
|
-
temperature=0.7
|
|
173
|
-
)
|
|
174
|
-
)
|
|
175
|
-
|
|
176
|
-
print("--- Non-streaming example ---")
|
|
177
|
-
# Get a single, complete response
|
|
178
|
-
async for response in llm.generate_content_async(request, stream=False):
|
|
179
|
-
if response.text:
|
|
180
|
-
print(response.text)
|
|
181
|
-
if response.usage_metadata:
|
|
182
|
-
print(f"Token usage: {response.usage_metadata.total_token_count}")
|
|
183
|
-
|
|
184
|
-
print("\n--- Streaming example ---")
|
|
185
|
-
# Get a stream of partial responses
|
|
186
|
-
full_response_text = ""
|
|
187
|
-
async for response in llm.generate_content_async(request, stream=True):
|
|
188
|
-
if response.text:
|
|
189
|
-
print(response.text, end="", flush=True)
|
|
190
|
-
full_response_text += response.text
|
|
191
|
-
if response.usage_metadata:
|
|
192
|
-
# Usage metadata is typically sent with the final chunk
|
|
193
|
-
print(f"\nToken usage: {response.usage_metadata.total_token_count}")
|
|
194
|
-
|
|
195
|
-
if __name__ == "__main__":
|
|
196
|
-
# To run this example, you need to have the necessary environment variables set
|
|
197
|
-
# for the model you choose (e.g., OPENAI_API_KEY).
|
|
198
|
-
# You would also need to install the required provider packages, e.g.,
|
|
199
|
-
# pip install litellm[openai]
|
|
200
|
-
#
|
|
201
|
-
# Since this is an async function, we run it with asyncio.
|
|
202
|
-
# asyncio.run(main())
|
|
203
|
-
pass
|
|
204
|
-
```
|
|
205
|
-
|
|
206
|
-
================================================================================
|
|
207
|
-
|
|
208
|
-
## Section 3: agent/agent_llm.txt
|
|
209
|
-
|
|
210
|
-
**Source file:** `agent/agent_llm.txt`
|
|
211
|
-
|
|
212
|
-
Here is the comprehensive developer guide for the `agent` directory.
|
|
213
|
-
|
|
214
|
-
## Quick Summary
|
|
215
|
-
The `agent` directory provides a comprehensive framework for hosting Google ADK (Agent Development Kit) agents within the Solace AI Connector ecosystem. It bridges ADK agents with the A2A (Agent-to-Agent) protocol over Solace messaging, enabling distributed agent communication, task delegation, and rich tool functionality.
|
|
216
|
-
|
|
217
|
-
The architecture is modular, consisting of several key components:
|
|
218
|
-
* **`sac/` (Solace AI Connector):** The main entry point, providing the `SamAgentApp` and `SamAgentComponent` to host the agent and manage its lifecycle and communication over the Solace event mesh.
|
|
219
|
-
* **`adk/` (Agent Development Kit):** The core integration layer with Google's ADK. It defines the custom `AppLlmAgent`, manages asynchronous task execution, and provides a rich set of callbacks to augment agent behavior.
|
|
220
|
-
* **`tools/`:** A comprehensive and extensible library of tools available to the agent, covering data analysis, artifact management, web requests, multimedia processing, and inter-agent communication.
|
|
221
|
-
* **`protocol/`:** The underlying implementation of the A2A (Agent-to-Agent) communication protocol, handling message routing and event processing.
|
|
222
|
-
* **`utils/`:** A collection of helper modules for common tasks like artifact management, configuration parsing, and context handling.
|
|
223
|
-
* **`testing/`:** Utilities to aid in debugging and testing custom agent implementations.
|
|
224
|
-
|
|
225
|
-
These components work together to create a robust environment where an ADK agent can be configured with specific instructions and tools, communicate with other agents, and execute complex tasks in a distributed, event-driven manner.
|
|
226
|
-
|
|
227
|
-
## Files and Subdirectories Overview
|
|
228
|
-
- **Direct files:**
|
|
229
|
-
- `__init__.py`: An empty file that marks the `agent` directory as a Python package.
|
|
230
|
-
- **Subdirectories:**
|
|
231
|
-
- `adk/`: Provides the core integration layer with Google's ADK, including custom agents, services, and callbacks.
|
|
232
|
-
- `protocol/`: Implements the A2A protocol event handlers for message routing and agent communication.
|
|
233
|
-
- `sac/`: Contains the Solace AI Connector app and component implementations for hosting ADK agents.
|
|
234
|
-
- `testing/`: Provides utilities for testing the A2A framework and debugging agent behavior.
|
|
235
|
-
- `tools/`: A comprehensive, registry-based tool library for AI agents.
|
|
236
|
-
- `utils/`: Contains helper utilities for configuration, context handling, and artifact management.
|
|
237
|
-
|
|
238
|
-
## Developer API Reference
|
|
239
|
-
|
|
240
|
-
### Direct Files
|
|
241
|
-
|
|
242
|
-
#### __init__.py
|
|
243
|
-
**Purpose:** Standard Python package initializer. It allows the `agent` directory to be treated as a package.
|
|
244
|
-
**Import:** `import agent`
|
|
245
|
-
|
|
246
|
-
**Classes/Functions/Constants:** [None]
|
|
247
|
-
|
|
248
|
-
### Subdirectory APIs
|
|
249
|
-
|
|
250
|
-
#### adk/
|
|
251
|
-
**Purpose:** Provides the core integration layer between the Solace AI Connector and Google's ADK.
|
|
252
|
-
**Key Exports:** `App
|
|
253
|
-
|
|
254
|
-
================================================================================
|
|
255
|
-
|
|
256
|
-
## Section 4: agent/protocol/protocol_llm.txt
|
|
257
|
-
|
|
258
|
-
**Source file:** `agent/protocol/protocol_llm.txt`
|
|
259
|
-
|
|
260
|
-
## Quick Summary
|
|
261
|
-
The `protocol` directory implements the core logic for Agent-to-Agent (A2A) communication. It handles receiving and processing requests, responses, and discovery messages (Agent Cards) over the Solace event mesh. It acts as the bridge between the A2A protocol and the underlying Google ADK execution environment.
|
|
262
|
-
|
|
263
|
-
## Files Overview
|
|
264
|
-
- `__init__.py` - An empty file that marks the directory as a Python package.
|
|
265
|
-
- `event_handlers.py` - Contains the primary logic for handling all A2A protocol events, including routing incoming messages to the correct processors, managing task execution, and handling agent discovery.
|
|
266
|
-
|
|
267
|
-
## Developer API Reference
|
|
268
|
-
|
|
269
|
-
### __init__.py
|
|
270
|
-
**Purpose:** Standard Python package initialization file.
|
|
271
|
-
**Import:** `from src.solace_agent_mesh.agent.protocol import *`
|
|
272
|
-
|
|
273
|
-
This is an empty package initialization file and has no public interfaces.
|
|
274
|
-
|
|
275
|
-
### event_handlers.py
|
|
276
|
-
**Purpose:** This file is the central hub for processing all events related to the A2A protocol. It receives events from the Solace AI Connector framework, determines their type (e.g., new task request, peer agent response, discovery message, timer), and routes them to the appropriate handler function. It manages the lifecycle of tasks, from initiation and cancellation to handling responses from peer agents.
|
|
277
|
-
**Import:** `from src.solace_agent_mesh.agent.protocol.event_handlers import process_event, handle_a2a_request, handle_agent_card_message, handle_a2a_response, publish_agent_card`
|
|
278
|
-
|
|
279
|
-
**Functions:**
|
|
280
|
-
- `process_event(component: "SamAgentComponent", event: Event
|
|
281
|
-
|
|
282
|
-
================================================================================
|
|
283
|
-
|
|
284
|
-
## Section 5: agent/sac/sac_llm.txt
|
|
285
|
-
|
|
286
|
-
**Source file:** `agent/sac/sac_llm.txt`
|
|
287
|
-
|
|
288
|
-
## Quick Summary
|
|
289
|
-
The `sac` (Solace AI Connector) directory provides the core implementation for hosting a Google ADK (Agent Development Kit) agent within the Solace AI Connector framework. It acts as a bridge, enabling ADK agents to communicate using the A2A (Agent-to-Agent) protocol over Solace messaging. This allows for the creation of distributed, collaborative agent systems where agents can delegate tasks, share information, and work together to solve complex problems.
|
|
290
|
-
|
|
291
|
-
The main components are `SamAgentApp`, which handles the initial setup and configuration, and `SamAgentComponent`, which hosts the ADK agent instance, manages its lifecycle, and translates between the A2A protocol and the ADK's internal event model.
|
|
292
|
-
|
|
293
|
-
## Files Overview
|
|
294
|
-
- `__init__.py`: An empty file that marks the `sac` directory as a Python package.
|
|
295
|
-
- `app.py`: Defines a custom SAC `App` class that automatically configures Solace subscriptions and broker settings for A2A communication.
|
|
296
|
-
- `component.py`: The main SAC `Component` that hosts the ADK agent, manages its lifecycle, and handles all A2A protocol messaging.
|
|
297
|
-
- `patch_adk.py`: Contains runtime patches for the Google ADK library to enhance or correct its behavior for this specific use case.
|
|
298
|
-
- `task_execution_context.py`: A state management class that encapsulates all runtime information for a single, in-flight A2A task.
|
|
299
|
-
|
|
300
|
-
## Developer API Reference
|
|
301
|
-
|
|
302
|
-
---
|
|
303
|
-
### __init__.py
|
|
304
|
-
**Purpose:** A standard Python file that makes the `sac` directory a package, allowing its modules to be imported.
|
|
305
|
-
**Import:** This file is not meant to be imported from directly.
|
|
306
|
-
|
|
307
|
-
---
|
|
308
|
-
### app.py
|
|
309
|
-
**Purpose:** Provides a custom SAC `App` class (`SamAgentApp`) that simplifies the configuration of an A2A agent. It automatically generates the required Solace topic subscriptions and configures the message broker based on the provided `namespace` and `agent_name` in the configuration file. This class is the main entry point for running an agent host.
|
|
310
|
-
**Import:** `from src.solace_agent_mesh.agent.sac.app import SamAgentApp`
|
|
311
|
-
|
|
312
|
-
**Classes:**
|
|
313
|
-
- `SamAgentApp(app_info: Dict[str, Any], **kwargs)` - A custom App class for the SAM Agent Host. It handles namespace prefixing, automatic subscription generation, and programmatic definition of the `SamAgentComponent`.
|
|
314
|
-
- `app_schema: Dict` - A class attribute that defines the comprehensive configuration schema for the agent host. This schema is used by the SAC framework to validate the application's YAML configuration file, ensuring all required parameters are present and correctly typed.
|
|
315
|
-
|
|
316
|
-
**Constants/Variables:**
|
|
317
|
-
- `info: Dict[str, str]` - A dictionary containing metadata about the `SamAgentApp` class, required by the SAC framework for discovery.
|
|
318
|
-
|
|
319
|
-
**Usage Examples:**
|
|
320
|
-
```python
|
|
321
|
-
# The SamAgentApp is typically instantiated by the Solace AI Connector framework,
|
|
322
|
-
# not directly by a developer. The framework reads a YAML configuration file,
|
|
323
|
-
# validates it against the app_schema, and passes the resulting configuration
|
|
324
|
-
# to the SamAgentApp constructor.
|
|
325
|
-
|
|
326
|
-
# --- Example agent-config.yaml ---
|
|
327
|
-
# app:
|
|
328
|
-
# class_name: src.solace_agent_mesh.agent.sac.app.SamAgentApp
|
|
329
|
-
# app_config:
|
|
330
|
-
# namespace: "my-org/production"
|
|
331
|
-
# agent_name: "customer-support-agent"
|
|
332
|
-
# model: "gemini-1.5-pro-latest"
|
|
333
|
-
# tools:
|
|
334
|
-
# - tool_type: "builtin"
|
|
335
|
-
# tool_name: "file_search"
|
|
336
|
-
# agent_card:
|
|
337
|
-
# description: "An agent that can answer questions about customer accounts."
|
|
338
|
-
# agent_card_publishing:
|
|
339
|
-
# interval_seconds: 60
|
|
340
|
-
# agent_discovery:
|
|
341
|
-
# enabled: true
|
|
342
|
-
# inter_agent_communication:
|
|
343
|
-
# allow_list: ["*"]
|
|
344
|
-
# request_timeout_seconds: 45
|
|
345
|
-
# session_service:
|
|
346
|
-
# type: "memory"
|
|
347
|
-
# # ... other configuration parameters
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
---
|
|
351
|
-
### component.py
|
|
352
|
-
**Purpose:** This is the core component that hosts a Google ADK agent and bridges its communication to the A2A protocol over Solace. It handles incoming task requests, manages the agent's lifecycle, processes ADK events, orchestrates tool calls (including peer agent delegation), and sends status updates and final responses. Developers can interact with this component's state and lifecycle via custom initialization and cleanup functions.
|
|
353
|
-
**Import:** `from src.solace_agent_mesh.agent.sac.component import SamAgentComponent`
|
|
354
|
-
|
|
355
|
-
**Classes:**
|
|
356
|
-
- `SamAgentComponent(**kwargs)` - A Solace AI Connector component that hosts a Google ADK agent and communicates via the A2A protocol.
|
|
357
|
-
- `process_event(self, event: Event)` - The main entry point for all events from the SAC framework (e.g., incoming messages, timers). This method orchestrates the processing of A2A requests.
|
|
358
|
-
- `handle_timer_event(self, timer_data: Dict[str, Any])` - Handles scheduled timer events, primarily used for periodically publishing the agent's discovery card.
|
|
359
|
-
- `handle_cache_expiry_event(self, cache_data: Dict[str, Any])` - Handles cache expiry events, used to detect timeouts for requests sent to peer agents.
|
|
360
|
-
- `finalize_task_success(self, a2a_context: Dict)` - An async method that finalizes a task successfully, sending the final `COMPLETED` response.
|
|
361
|
-
- `finalize_task_canceled(self, a2a_context: Dict)` - Finalizes a task as `CANCELED` and sends the corresponding response.
|
|
362
|
-
- `finalize_task_error(self, exception: Exception, a2a_context: Dict)` - An async method that finalizes a task as `FAILED`, sending an error response.
|
|
363
|
-
- `cleanup(self)` - Cleans up all resources when the component is shut down, including stopping the async loop and calling any custom cleanup functions.
|
|
364
|
-
- `set_agent_specific_state(self, key: str, value: Any)` - Sets a key-value pair in a dedicated state dictionary. This is intended for use within a custom `agent_init_function` to store state (e.g., database connections, API clients) that can be accessed by tools.
|
|
365
|
-
- `get_agent_specific_state(self, key: str, default: Optional[Any] = None) -> Any` - Retrieves a value from the agent-specific state dictionary. This is intended for use by tools or a custom `agent_cleanup_function`.
|
|
366
|
-
- `get_async_loop(self) -> Optional[asyncio.AbstractEventLoop]` - Returns the dedicated asyncio event loop used by the component for all its asynchronous operations. This is useful for scheduling custom async work from synchronous code (e.g., tools).
|
|
367
|
-
- `set_agent_system_instruction_string(self, instruction_string: str) -> None` - Sets a static string to be injected into the agent's system prompt. This should be called from a custom `agent_init_function`.
|
|
368
|
-
- `set_agent_system_instruction_callback(self, callback_function: Callable[[CallbackContext, LlmRequest], Optional[str]]) -> None` - Sets a callback function to dynamically generate parts of the system prompt at runtime. This should be called from a custom `agent_init_function`.
|
|
369
|
-
- `get_gateway_id(self) -> str` - Returns a unique identifier for this agent host instance, typically the agent's name.
|
|
370
|
-
- `submit_a2a_task(self, target_agent_name: str, a2a_message: A2AMessage, original_session_id: str, main_logical_task_id: str, user_id: str, user_config: Dict[str, Any], sub_task_id: str, function_call_id: Optional[str] = None) -> str` - Submits a task to a peer agent in a non-blocking way. This is the core mechanism for agent delegation. Returns the `sub_task_id` used for correlation.
|
|
371
|
-
- `get_agent_context(self) -> Dict[str, Any]` - Returns a dictionary containing context about the agent, used for interactions with the middleware system.
|
|
372
|
-
|
|
373
|
-
**Constants/Variables:**
|
|
374
|
-
- `info: Dict` - A dictionary containing metadata about the `SamAgentComponent` class, required by the SAC framework.
|
|
375
|
-
- `CORRELATION_DATA_PREFIX: str` - A public constant string used as a prefix for cache keys when tracking peer-to-peer requests.
|
|
376
|
-
- `HOST_COMPONENT_VERSION: str` - The version string of the host component.
|
|
377
|
-
|
|
378
|
-
**Usage Examples:**
|
|
379
|
-
```python
|
|
380
|
-
# This component is instantiated by the SamAgentApp. Developers interact with it
|
|
381
|
-
# primarily through custom init/cleanup functions and by building tools that
|
|
382
|
-
# may need access to its state or methods.
|
|
383
|
-
|
|
384
|
-
# --- In a custom init module (e.g., my_agent_init.py) ---
|
|
385
|
-
import asyncio
|
|
386
|
-
from src.solace_agent_mesh.agent.sac.component import SamAgentComponent
|
|
387
|
-
from src.solace_agent_mesh.common.types import A2AMessage, TextPart
|
|
388
|
-
|
|
389
|
-
# This function would be configured in the agent's YAML config
|
|
390
|
-
def initialize_my_agent(host_component: SamAgentComponent, config: dict):
|
|
391
|
-
"""Custom initialization function for the agent."""
|
|
392
|
-
print("Initializing my custom agent...")
|
|
393
|
-
|
|
394
|
-
================================================================================
|
|
395
|
-
|
|
396
|
-
## Section 6: agent/testing/testing_llm.txt
|
|
397
|
-
|
|
398
|
-
**Source file:** `agent/testing/testing_llm.txt`
|
|
399
|
-
|
|
400
|
-
## Quick Summary
|
|
401
|
-
|
|
402
|
-
The `testing` directory provides a suite of utilities designed to facilitate the testing of the A2A (Agent-to-Agent) framework. Its primary function is to offer tools that simplify debugging and validation of agent interactions during test runs, particularly for declarative tests.
|
|
403
|
-
|
|
404
|
-
## Files Overview
|
|
405
|
-
|
|
406
|
-
- `__init__.py`: Marks the directory as a Python package.
|
|
407
|
-
- `debug_utils.py`: Provides helper functions for debugging test failures, most notably a pretty-printer for A2A event histories.
|
|
408
|
-
|
|
409
|
-
## Developer API Reference
|
|
410
|
-
|
|
411
|
-
### debug_utils.py
|
|
412
|
-
|
|
413
|
-
**Purpose:** This module contains utilities to help developers debug failing tests by providing human-readable representations of complex data structures, such as the event history from an A2A task.
|
|
414
|
-
|
|
415
|
-
**Import:** `from agent.testing.debug_utils import pretty_print_event_history`
|
|
416
|
-
|
|
417
|
-
**Functions:**
|
|
418
|
-
|
|
419
|
-
- `pretty_print_event_history(event_history: List[Dict[str, Any]], max_string_length: int = 200) -> None`
|
|
420
|
-
Formats and prints a list of A2A event payloads to the console in a structured, readable format. It intelligently parses different event types (status updates, final responses, errors) and truncates long strings to keep the output concise. This is invaluable for quickly diagnosing why a test failed by inspecting the sequence of events leading up to the failure.
|
|
421
|
-
|
|
422
|
-
**Usage Examples:**
|
|
423
|
-
|
|
424
|
-
```python
|
|
425
|
-
# Show how to import and use the main classes/functions
|
|
426
|
-
from agent.testing.debug_utils import pretty_print_event_history
|
|
427
|
-
from typing import List, Dict, Any
|
|
428
|
-
|
|
429
|
-
# Example event history captured during a test run
|
|
430
|
-
sample_event_history: List[Dict[str, Any]] = [
|
|
431
|
-
{
|
|
432
|
-
"result": {
|
|
433
|
-
"status": {
|
|
434
|
-
"state": "EXECUTING",
|
|
435
|
-
"message": {
|
|
436
|
-
"parts": [
|
|
437
|
-
{"type": "text", "text": "Okay, I am starting the process to find the latest sales report."}
|
|
438
|
-
]
|
|
439
|
-
},
|
|
440
|
-
},
|
|
441
|
-
"final": False,
|
|
442
|
-
}
|
|
443
|
-
},
|
|
444
|
-
{
|
|
445
|
-
"result": {
|
|
446
|
-
"artifact": {
|
|
447
|
-
"name": "sales_report_q4.pdf",
|
|
448
|
-
"parts": [
|
|
449
|
-
{
|
|
450
|
-
"type": "file",
|
|
451
|
-
"file": {
|
|
452
|
-
"name": "sales_report_q4.pdf",
|
|
453
|
-
"mimeType": "application/pdf",
|
|
454
|
-
"uri": "file://path/to/sales_report_q4.pdf"
|
|
455
|
-
}
|
|
456
|
-
}
|
|
457
|
-
]
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
},
|
|
461
|
-
{
|
|
462
|
-
"error": {
|
|
463
|
-
"code": "INTERNAL_ERROR",
|
|
464
|
-
"message": "Failed to access the database due to a connection timeout. The database server at db.example.com might be down or unreachable. Please check the server status and network connectivity."
|
|
465
|
-
}
|
|
466
|
-
},
|
|
467
|
-
{
|
|
468
|
-
"result": {
|
|
469
|
-
"status": {
|
|
470
|
-
"state": "FAILED",
|
|
471
|
-
"message": {
|
|
472
|
-
"parts": [
|
|
473
|
-
{"type": "text", "text": "I encountered an error and could not complete the task."}
|
|
474
|
-
]
|
|
475
|
-
}
|
|
476
|
-
},
|
|
477
|
-
"sessionId": "task-12345",
|
|
478
|
-
}
|
|
479
|
-
}
|
|
480
|
-
]
|
|
481
|
-
|
|
482
|
-
# In a test's `tearDown` or `except` block, you can print the history.
|
|
483
|
-
print("A test failed! Dumping the event history for review:")
|
|
484
|
-
pretty_print_event_history(sample_event_history, max_string_length=100)
|
|
485
|
-
|
|
486
|
-
# Example with no events
|
|
487
|
-
print("\n--- Example with no events ---")
|
|
488
|
-
pretty_print_event_history([])
|
|
489
|
-
```
|
|
490
|
-
|
|
491
|
-
================================================================================
|
|
492
|
-
|
|
493
|
-
## Section 7: agent/tools/tools_llm.txt
|
|
494
|
-
|
|
495
|
-
**Source file:** `agent/tools/tools_llm.txt`
|
|
496
|
-
|
|
497
|
-
## Quick Summary
|
|
498
|
-
The `tools` directory contains the complete set of built-in tools available to the agent. It follows a declarative, registry-based pattern where each tool module defines its functions and registers them with a central `tool_registry`. This allows for automatic discovery and dynamic availability of tools based on configuration and agent capabilities. The tools cover a wide range of functionalities including artifact management, audio/image processing, data analysis, web requests, and inter-agent communication.
|
|
499
|
-
|
|
500
|
-
## Files Overview
|
|
501
|
-
- `__init__.py`: Imports all tool modules, triggering their registration with the central registry.
|
|
502
|
-
- `audio_tools.py`: Provides tools for text-to-speech (TTS), multi-speaker TTS, audio concatenation, and transcription.
|
|
503
|
-
- `builtin_artifact_tools.py`: Contains core tools for creating, listing, loading, modifying, and deleting artifacts.
|
|
504
|
-
- `builtin_data_analysis_tools.py`: Offers tools for generating charts from Plotly configurations.
|
|
505
|
-
- `general_agent_tools.py`: Includes general-purpose utilities like file-to-markdown conversion and Mermaid diagram generation.
|
|
506
|
-
- `image_tools.py`: Provides tools for image generation, editing, and vision-based description of images and audio.
|
|
507
|
-
- `peer_agent_tool.py`: Defines the `PeerAgentTool` class for delegating tasks to other agents.
|
|
508
|
-
- `registry.py`: Implements the singleton `tool_registry` for managing all tool definitions.
|
|
509
|
-
- `test_tools.py`: Contains tools specifically for testing agent behavior, such as delays and failures.
|
|
510
|
-
- `tool_definition.py`: Defines the `BuiltinTool` Pydantic model used for declaring tools.
|
|
511
|
-
- `web_tools.py`: Contains a tool for making HTTP requests to external web resources.
|
|
512
|
-
|
|
513
|
-
## Developer API Reference
|
|
514
|
-
|
|
515
|
-
### __init__.py
|
|
516
|
-
**Purpose:** This file ensures that all built-in tool modules are imported when the `tools` package is loaded. This is crucial for the declarative tool registration pattern, as it triggers the `tool_registry.register()` calls within each tool module.
|
|
517
|
-
**Import:** `import src.solace_agent_mesh.agent.tools`
|
|
518
|
-
|
|
519
|
-
**Usage Examples:**
|
|
520
|
-
```python
|
|
521
|
-
# Importing the tools package is sufficient to register all built-in tools.
|
|
522
|
-
import src.solace_agent_mesh.agent.tools
|
|
523
|
-
|
|
524
|
-
# You can then access the registry to see all registered tools.
|
|
525
|
-
from src.solace_agent_mesh.agent.tools.registry import tool_registry
|
|
526
|
-
all_tools = tool_registry.get_all_tools()
|
|
527
|
-
print(f"Registered {len(all_tools)} tools.")
|
|
528
|
-
```
|
|
529
|
-
|
|
530
|
-
### audio_tools.py
|
|
531
|
-
**Purpose:** This file provides a collection of tools for audio processing, including text-to-speech (TTS) generation, audio concatenation, and transcription.
|
|
532
|
-
**Import:** `from src.solace_agent_mesh.agent.tools.audio_tools import select_voice, text_to_speech, multi_speaker_text_to_speech, concatenate_audio, transcribe_audio`
|
|
533
|
-
|
|
534
|
-
**Functions:**
|
|
535
|
-
- `select_voice(gender: Optional[str] = None, tone: Optional[str] = None, exclude_voices: Optional[List[str]] = None, tool_context: ToolContext = None, tool_config: Optional[Dict[str, Any]] = None) -> Dict[str, Any]` - Selects a suitable voice name based on criteria like gender and tone. Use this to get a consistent voice name that can be passed to the `text_to_speech` tool for multiple calls.
|
|
536
|
-
- `text_to_speech(text: str, output_filename: Optional[str] = None, voice_name: Optional[str] = None, gender: Optional[str] = None, tone: Optional[str] = None, language: Optional[str] = None, tool_context: ToolContext = None, tool_config: Optional[Dict[str, Any]] = None) -> Dict[str, Any]` - Converts text to speech using Gemini TTS API and saves as an MP3 artifact.
|
|
537
|
-
- `multi_speaker_text_to_speech(conversation_text: str, output_filename: Optional[str] = None, speaker_configs: Optional[List[Dict[str, str]]] = None, language: Optional[str] = None, tool_context: ToolContext = None, tool_config: Optional[Dict[str, Any]] = None) -> Dict[str, Any]` - Converts conversation text with speaker labels to speech using multiple voices.
|
|
538
|
-
- `concatenate_audio(clips_to_join: List[Dict[str, Any]], output_filename: Optional[str] = None, tool_context: ToolContext = None, tool_config: Optional[Dict[str, Any]] = None) -> Dict[str, Any]` - Combines multiple audio artifacts in a specified order into a single audio file, with optional pauses.
|
|
539
|
-
- `transcribe_audio(audio_filename: str, tool_context: ToolContext = None, tool_config: Optional[Dict[str, Any]] = None) -> Dict[str, Any]` - Transcribes an audio recording using an OpenAI-compatible audio transcription API.
|
|
540
|
-
|
|
541
|
-
**Constants/Variables:**
|
|
542
|
-
- `ALL_AVAILABLE_VOICES: List[str]` - A list of all available voice names for TTS.
|
|
543
|
-
- `SUPPORTED_LANGUAGES: Dict[str, str]` - A mapping of common language names to their BCP-47 codes.
|
|
544
|
-
- `VOICE_TONE_MAPPING: Dict[str, List[str]]` - A dictionary mapping descriptive tones to lists of voice names.
|
|
545
|
-
- `GENDER_TO_VOICE_MAPPING: Dict[str, List[str]]` - A dictionary mapping genders ('male', 'female', 'neutral') to lists of voice names.
|
|
546
|
-
|
|
547
|
-
**Usage Examples:**
|
|
548
|
-
```python
|
|
549
|
-
# Assume 'tool_context' is a valid ToolContext object.
|
|
550
|
-
|
|
551
|
-
# 1. Generate a simple audio file
|
|
552
|
-
tts_result = await text_to_speech(
|
|
553
|
-
text="Welcome to the developer guide.",
|
|
554
|
-
output_filename="welcome.mp3",
|
|
555
|
-
gender="female",
|
|
556
|
-
tone="friendly",
|
|
557
|
-
language="en-US",
|
|
558
|
-
tool_context=tool_context
|
|
559
|
-
)
|
|
560
|
-
print(tts_result)
|
|
561
|
-
|
|
562
|
-
# 2. Generate a multi-speaker conversation
|
|
563
|
-
convo_result = await multi_speaker_text_to_speech(
|
|
564
|
-
conversation_text="SpeakerA: How are you?\nSpeakerB: I am fine, thank you.",
|
|
565
|
-
speaker_configs=[
|
|
566
|
-
{"name": "SpeakerA", "gender": "male", "tone": "warm"},
|
|
567
|
-
{"name": "SpeakerB", "gender": "female", "tone": "bright"}
|
|
568
|
-
],
|
|
569
|
-
output_filename="dialogue.mp3",
|
|
570
|
-
tool_context=tool_context
|
|
571
|
-
)
|
|
572
|
-
print(convo_result)
|
|
573
|
-
|
|
574
|
-
# 3. Concatenate the generated audio files
|
|
575
|
-
concat_result = await concatenate_audio(
|
|
576
|
-
clips_to_join=[
|
|
577
|
-
{"filename": "welcome.mp3:1", "pause_after_ms": 500},
|
|
578
|
-
{"filename": "dialogue.mp3:1"}
|
|
579
|
-
],
|
|
580
|
-
output_filename="combined_audio.mp3",
|
|
581
|
-
tool_context=tool_context
|
|
582
|
-
)
|
|
583
|
-
print(concat_result)
|
|
584
|
-
|
|
585
|
-
# 4. Transcribe the combined audio
|
|
586
|
-
transcribe_result = await transcribe_audio(
|
|
587
|
-
audio_filename="combined_audio.mp3:1",
|
|
588
|
-
tool_context=tool_context
|
|
589
|
-
)
|
|
590
|
-
print(transcribe_result)
|
|
591
|
-
```
|
|
592
|
-
|
|
593
|
-
### builtin_artifact_tools.py
|
|
594
|
-
**Purpose:** This file provides the core tools for artifact management, allowing the agent to create, read, list, update, and delete data artifacts within the current session.
|
|
595
|
-
**Import:** `from src.solace_agent_mesh.agent.tools.builtin_artifact_tools import list_artifacts, load_artifact, signal_artifact_for_return, append_to_artifact, apply_embed_and_create_artifact, extract_content_from_artifact, delete_artifact`
|
|
596
|
-
|
|
597
|
-
**Functions:**
|
|
598
|
-
- `list_artifacts(tool_context: ToolContext = None) -> Dict[str, Any]` - Lists all available data artifact filenames and their versions for the current session.
|
|
599
|
-
- `load_artifact(filename: str, version: int, load_metadata_only: bool = False, max_content_length: Optional[int] = None, tool_context: ToolContext = None) -> Dict[str, Any]` - Loads the content or metadata of a specific artifact version.
|
|
600
|
-
- `signal_artifact_for_return(filename: str, version: int, tool_context: ToolContext = None
|
|
601
|
-
|
|
602
|
-
================================================================================
|
|
603
|
-
|
|
604
|
-
## Section 8: agent/utils/utils_llm.txt
|
|
605
|
-
|
|
606
|
-
**Source file:** `agent/utils/utils_llm.txt`
|
|
607
|
-
|
|
608
|
-
## Quick Summary
|
|
609
|
-
The `utils` directory provides a collection of helper modules designed to support the core functionality of the agent. These utilities encapsulate common, reusable logic for tasks such as artifact management (saving, loading, schema inference), configuration parsing, and safe interaction with the ADK's invocation context.
|
|
610
|
-
|
|
611
|
-
## Files Overview
|
|
612
|
-
- `__init__.py` - An empty file that marks the directory as a Python package.
|
|
613
|
-
- `artifact_helpers.py` - Provides functions for creating, retrieving, and managing artifacts and their associated metadata.
|
|
614
|
-
- `config_parser.py` - Contains helpers for parsing and validating agent and app configurations.
|
|
615
|
-
- `context_helpers.py` - Offers utility functions for safely extracting data from ADK callback and invocation contexts.
|
|
616
|
-
|
|
617
|
-
## Developer API Reference
|
|
618
|
-
|
|
619
|
-
### artifact_helpers.py
|
|
620
|
-
**Purpose:** This module offers a comprehensive set of asynchronous functions for interacting with an artifact storage service. It handles saving artifacts with automatically generated metadata, inferring schemas for common data types, loading artifact content or just metadata, and listing available artifacts.
|
|
621
|
-
**Import:** `from src.solace_agent_mesh.agent.utils.artifact_helpers import is_filename_safe, ensure_correct_extension, save_artifact_with_metadata, load_artifact_content_or_metadata, get_latest_artifact_version, get_artifact_info_list, format_metadata_for_llm, decode_and_get_bytes`
|
|
622
|
-
|
|
623
|
-
**Functions:**
|
|
624
|
-
- `is_filename_safe(filename: str) -> bool` - Checks if a filename is safe for artifact creation (e.g., no path traversal).
|
|
625
|
-
- `ensure_correct_extension(filename_from_llm: str, desired_extension: str) -> str` - Corrects or adds the desired file extension to a filename.
|
|
626
|
-
- `save_artifact_with_metadata(artifact_service: BaseArtifactService, app_name: str, user_id: str, session_id: str, filename: str, content_bytes: bytes, mime_type: str, metadata_dict: Dict[str, Any], timestamp: datetime.datetime, explicit_schema: Optional[Dict] = None, schema_inference_depth: int = 2, schema_max_keys: int = 20, tool_context: Optional["ToolContext"] = None) -> Dict[str, Any]` - Asynchronously saves a data artifact and a corresponding metadata artifact, with optional schema inference.
|
|
627
|
-
- `format_metadata_for_llm(metadata: Dict[str, Any]) -> str` - Formats an artifact's metadata dictionary into a human-readable, LLM-friendly string.
|
|
628
|
-
- `decode_and_get_bytes(content_str: str, mime_type: str, log_identifier: str) -> Tuple[bytes, str]` - Decodes a string into bytes, handling base64 for binary MIME types and falling back to UTF-8 for text.
|
|
629
|
-
- `get_latest_artifact_version(artifact_service: BaseArtifactService, app_name: str, user_id: str, session_id: str, filename: str) -> Optional[int]` - Asynchronously retrieves the latest version number for a given artifact.
|
|
630
|
-
- `get_artifact_info_list(artifact_service: BaseArtifactService, app_name: str, user_id: str, session_id: str) -> List[ArtifactInfo]` - Asynchronously retrieves a list of detailed `ArtifactInfo` objects for all artifacts in the current context.
|
|
631
|
-
- `load_artifact_content_or_metadata(artifact_service: BaseArtifactService, app_name: str, user_id: str, session_id: str, filename: str, version: Union[int, str], load_metadata_only: bool = False, return_raw_bytes: bool = False, max_content_length: Optional[int] = None, component: Optional[Any] = None, encoding: str = "utf-8", error_handling: str = "strict") -> Dict[str, Any]` - Asynchronously loads an artifact's content or just its metadata for a specific version.
|
|
632
|
-
|
|
633
|
-
**Constants/Variables:**
|
|
634
|
-
- `METADATA_SUFFIX: str` - The suffix used for metadata files, `".metadata.json"`.
|
|
635
|
-
- `DEFAULT_SCHEMA_MAX_KEYS: int` - The default maximum number of keys to inspect when inferring a schema for a dictionary (default: 20).
|
|
636
|
-
|
|
637
|
-
**Usage Examples:**
|
|
638
|
-
```python
|
|
639
|
-
import asyncio
|
|
640
|
-
import datetime
|
|
641
|
-
from typing import Dict, Any, Optional, List, Union
|
|
642
|
-
from google.adk.artifacts import BaseArtifactService, MemoryArtifactService
|
|
643
|
-
from src.solace_agent_mesh.agent.utils.artifact_helpers import (
|
|
644
|
-
save_artifact_with_metadata,
|
|
645
|
-
load_artifact_content_or_metadata,
|
|
646
|
-
get_artifact_info_list,
|
|
647
|
-
ensure_correct_extension
|
|
648
|
-
)
|
|
649
|
-
|
|
650
|
-
# Assume 'service' is an instance of a BaseArtifactService implementation
|
|
651
|
-
service = MemoryArtifactService()
|
|
652
|
-
app_name = "my_app"
|
|
653
|
-
user_id = "user-1"
|
|
654
|
-
session_id = "session-1"
|
|
655
|
-
|
|
656
|
-
async def manage_artifacts():
|
|
657
|
-
# 1. Ensure the filename from an LLM has the correct extension
|
|
658
|
-
safe_filename = ensure_correct_extension("quarterly_report", "csv") # -> "quarterly_report.csv"
|
|
659
|
-
|
|
660
|
-
# 2. Save an artifact with some metadata
|
|
661
|
-
csv_content = b"id,name\n1,Alice\n2,Bob"
|
|
662
|
-
save_result = await save_artifact_with_metadata(
|
|
663
|
-
artifact_service=service,
|
|
664
|
-
app_name=app_name,
|
|
665
|
-
user_id=user_id,
|
|
666
|
-
session_id=session_id,
|
|
667
|
-
filename=safe_filename,
|
|
668
|
-
content_bytes=csv_content,
|
|
669
|
-
mime_type="text/csv",
|
|
670
|
-
metadata_dict={"source": "manual_upload", "description": "User sales data"},
|
|
671
|
-
timestamp=datetime.datetime.now(datetime.timezone.utc)
|
|
672
|
-
)
|
|
673
|
-
print(f"Save result: {save_result}")
|
|
674
|
-
|
|
675
|
-
# 3. Load the content of the artifact we just saved
|
|
676
|
-
loaded_artifact = await load_artifact_content_or_metadata(
|
|
677
|
-
artifact_service=service,
|
|
678
|
-
app_name=app_name,
|
|
679
|
-
user_id=user_id,
|
|
680
|
-
session_id=session_id,
|
|
681
|
-
filename=safe_filename,
|
|
682
|
-
version="latest"
|
|
683
|
-
)
|
|
684
|
-
if loaded_artifact.get("status") == "success":
|
|
685
|
-
print(f"Loaded content: {loaded_artifact.get('content')}")
|
|
686
|
-
|
|
687
|
-
# 4. List all available artifacts
|
|
688
|
-
all_artifacts = await get_artifact_info_list(
|
|
689
|
-
artifact_service=service,
|
|
690
|
-
app_name=app_name,
|
|
691
|
-
user_id=user_id,
|
|
692
|
-
session_id=session_id
|
|
693
|
-
)
|
|
694
|
-
for artifact in all_artifacts:
|
|
695
|
-
print(f"Found artifact: {artifact.filename} (v{artifact.version})")
|
|
696
|
-
|
|
697
|
-
# To run the async example
|
|
698
|
-
# asyncio.run(manage_artifacts())
|
|
699
|
-
```
|
|
700
|
-
|
|
701
|
-
### config_parser.py
|
|
702
|
-
**Purpose:** This module provides a utility to resolve configuration values that can be either a static string or a dynamic, callable "invoke" block. This is primarily used for parsing the agent's `instruction` configuration.
|
|
703
|
-
**Import:** `from src.solace_agent_mesh.agent.utils.config_parser import resolve_instruction_provider`
|
|
704
|
-
|
|
705
|
-
**Functions:**
|
|
706
|
-
- `resolve_instruction_provider(component, config_value: Any) -> Union[str, Callable[[ReadonlyContext], str]]` - Resolves an instruction from a configuration value. If the value is a string, it's returned directly. If it's a dictionary with an "invoke" key that resolves to a callable, the callable is returned.
|
|
707
|
-
|
|
708
|
-
**Usage Examples:**
|
|
709
|
-
```python
|
|
710
|
-
# Assume 'my_agent_component' is an instance of an agent component
|
|
711
|
-
# and it has a method 'get_config'
|
|
712
|
-
|
|
713
|
-
# Example 1: Config value is a simple string
|
|
714
|
-
config_str = "You are a helpful assistant."
|
|
715
|
-
instruction = resolve_instruction_provider(my_agent_component, config_str)
|
|
716
|
-
# instruction is "You are a helpful assistant."
|
|
717
|
-
|
|
718
|
-
# Example 2: Config value is a callable (e.g., from a YAML 'invoke' block)
|
|
719
|
-
def instruction_provider(context):
|
|
720
|
-
return f"Assistant for user {context.user_id}"
|
|
721
|
-
|
|
722
|
-
instruction_func = resolve_instruction_provider(my_agent_component, instruction_provider)
|
|
723
|
-
# instruction_func is the instruction_provider function
|
|
724
|
-
```
|
|
725
|
-
|
|
726
|
-
### context_helpers.py
|
|
727
|
-
**Purpose:** This module provides safe and stable helper functions to extract information from the ADK's `CallbackContext` and other invocation context objects, abstracting away internal attribute access.
|
|
728
|
-
**Import:** `from src.solace_agent_mesh.agent.utils.context_helpers import get_session_from_callback_context, get_original_session_id`
|
|
729
|
-
|
|
730
|
-
**Functions:**
|
|
731
|
-
- `get_session_from_callback_context(callback_context: CallbackContext) -> Session` - Safely retrieves the persistent `Session` object from a `CallbackContext`.
|
|
732
|
-
- `get_original_session_id(invocation_context: Any) -> str` - Extracts the base session ID from a context, stripping any suffixes added after a colon (e.g., "session123:tool456" -> "session123").
|
|
733
|
-
|
|
734
|
-
**Usage Examples:**
|
|
735
|
-
```python
|
|
736
|
-
from google.adk.agents.callback_context import CallbackContext
|
|
737
|
-
from google.adk.sessions import Session, SessionId
|
|
738
|
-
from src.solace_agent_mesh.agent.utils.context_helpers import get_session_from_callback_context, get_original_session_id
|
|
739
|
-
|
|
740
|
-
# Mock context objects for demonstration
|
|
741
|
-
class MockInvocationContext:
|
|
742
|
-
def __init__(self, session_id_str: str):
|
|
743
|
-
self.session = Session(id=SessionId(session_id_str))
|
|
744
|
-
|
|
745
|
-
# 1. Get the full session object from a callback context
|
|
746
|
-
# In a real tool, 'callback_context' is provided by the ADK
|
|
747
|
-
mock_callback_context = CallbackContext(_invocation_context=MockInvocationContext("session123:tool456"))
|
|
748
|
-
session_obj = get_session_from_callback_context(mock_callback_context)
|
|
749
|
-
print(f"Full Session ID: {session_obj.id}") # -> "session123:tool456"
|
|
750
|
-
|
|
751
|
-
# 2. Get the original session ID from an invocation context
|
|
752
|
-
# In a real tool, this comes from 'tool_context._invocation_context'
|
|
753
|
-
mock_inv_context = MockInvocationContext("session123:tool456")
|
|
754
|
-
original_id = get_original_session_id(mock_inv_context)
|
|
755
|
-
print(f"Original Session ID: {original_id}") # -> "session123"
|
|
756
|
-
|
|
757
|
-
# Works with simple IDs too
|
|
758
|
-
mock_inv_context_simple = MockInvocationContext("session789")
|
|
759
|
-
original_id_simple = get_original_session_id(mock_inv_context_simple)
|
|
760
|
-
print(f"Original Session ID (simple): {original_id_simple}") # -> "session789
|
|
761
|
-
|
|
762
|
-
================================================================================
|
|
763
|
-
|
|
764
|
-
## Section 9: common/client/client_llm.txt
|
|
765
|
-
|
|
766
|
-
**Source file:** `common/client/client_llm.txt`
|
|
767
|
-
|
|
768
|
-
## Quick Summary
|
|
769
|
-
The `client` directory provides a Python-based client library for Agent-to-Agent (A2A) communication. It allows developers to discover remote agent capabilities via an "Agent Card" and then interact with that agent by sending tasks, receiving streaming responses, and managing the task lifecycle (getting status, cancelling, setting callbacks).
|
|
770
|
-
|
|
771
|
-
## Files Overview
|
|
772
|
-
- `__init__.py`: Exposes the primary `A2AClient` and `A2ACardResolver` classes for easy importing.
|
|
773
|
-
- `card_resolver.py`: Contains the `A2ACardResolver` class, used to discover and fetch an agent's capabilities from a well-known endpoint.
|
|
774
|
-
- `client.py`: Contains the main `A2AClient` class for all communication with a remote agent, including sending tasks and managing them.
|
|
775
|
-
|
|
776
|
-
## Developer API Reference
|
|
777
|
-
|
|
778
|
-
### __init__.py
|
|
779
|
-
**Purpose:** This file makes the main client classes available directly under the `client` package, simplifying imports for developers.
|
|
780
|
-
**Import:** `from src.solace_agent_mesh.common.client import A2AClient, A2ACardResolver`
|
|
781
|
-
|
|
782
|
-
**Constants/Variables:**
|
|
783
|
-
- `__all__: list[str]` - A list of the public objects that are exported from this module: `["A2AClient", "A2ACardResolver"]`.
|
|
784
|
-
|
|
785
|
-
---
|
|
786
|
-
|
|
787
|
-
### card_resolver.py
|
|
788
|
-
**Purpose:** This file provides a utility to resolve and fetch an agent's "Agent Card". The Agent Card is a JSON file that describes the agent's capabilities, its endpoint URL, and other metadata.
|
|
789
|
-
**Import:** `from src.solace_agent_mesh.common.client import A2ACardResolver`
|
|
790
|
-
|
|
791
|
-
**Classes:**
|
|
792
|
-
- `A2ACardResolver(base_url: str, agent_card_path: str = "/.well-known/agent.json")` - A client to discover and fetch an agent's capability card.
|
|
793
|
-
- `get_agent_card() -> AgentCard` - Makes an HTTP GET request to the constructed agent card URL, parses the JSON response, and returns it as an `AgentCard` object. Raises `A2AClientHTTPError` on network/status errors and `A2AClientJSONError` on parsing errors.
|
|
794
|
-
|
|
795
|
-
**Usage Examples:**
|
|
796
|
-
```python
|
|
797
|
-
from src.solace_agent_mesh.common.client import A2ACardResolver
|
|
798
|
-
from src.solace_agent_mesh.common.types import AgentCard, A2AClientHTTPError
|
|
799
|
-
|
|
800
|
-
# --- Example 1: Standard usage ---
|
|
801
|
-
# Create a resolver for an agent hosted at a specific domain
|
|
802
|
-
resolver = A2ACardResolver(base_url="https://some-agent.ai")
|
|
803
|
-
|
|
804
|
-
try:
|
|
805
|
-
# Fetch the agent's capability card from the default path
|
|
806
|
-
# (https://some-agent.ai/.well-known/agent.json)
|
|
807
|
-
agent_card: AgentCard = resolver.get_agent_card()
|
|
808
|
-
print(f"Successfully fetched card for agent: {agent_card.name}")
|
|
809
|
-
print(f"Agent API URL: {agent_card.url}")
|
|
810
|
-
print(f"Supported capabilities: {agent_card.capabilities}")
|
|
811
|
-
|
|
812
|
-
except A2AClientHTTPError as e:
|
|
813
|
-
print(f"Error fetching agent card: {e.status_code} - {e.message}")
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
# --- Example 2: Using a custom path for the agent card ---
|
|
817
|
-
custom_path_resolver = A2ACardResolver(
|
|
818
|
-
base_url="https://another-agent.com",
|
|
819
|
-
agent_card_path="/api/v1/agent-info.json"
|
|
820
|
-
)
|
|
821
|
-
# This will fetch from https://another-agent.com/api/v1/agent-info.json
|
|
822
|
-
custom_agent_card = custom_path_resolver.get_agent_card()
|
|
823
|
-
print(f"Agent name from custom path: {custom_agent_card.name}")
|
|
824
|
-
```
|
|
825
|
-
|
|
826
|
-
---
|
|
827
|
-
|
|
828
|
-
### client.py
|
|
829
|
-
**Purpose:** This file contains the core `A2AClient`, which is used to communicate with a remote agent's API endpoint. It handles sending various types of JSON-RPC requests for task management. All methods are asynchronous.
|
|
830
|
-
**Import:** `from src.solace_agent_mesh.common.client import A2AClient`
|
|
831
|
-
|
|
832
|
-
**Classes:**
|
|
833
|
-
- `A2AClient(agent_card: AgentCard = None, url: str = None)` - The main client for interacting with a remote agent. You must provide either an `AgentCard` object (from `A2ACardResolver`) or a direct `url` string to its API endpoint.
|
|
834
|
-
- `async send_task(self, payload: dict[str, Any]) -> SendTaskResponse` - Sends a task to the agent for processing. The `payload` should contain the action and its parameters. Returns a response typically containing a `task_id`.
|
|
835
|
-
- `async send_task_streaming(self, payload: dict[str, Any]) -> AsyncIterable[SendTaskStreamingResponse]` - Sends a task that is expected to return a stream of events (Server-Sent Events). The `payload` is the same as `send_task`. Returns an async iterator that yields response chunks as they arrive.
|
|
836
|
-
- `async get_task(self, payload: dict[str, Any]) -> GetTaskResponse` - Retrieves the current status and/or result of a previously submitted task. The `payload` must contain the `task_id`.
|
|
837
|
-
- `async cancel_task(self, payload: dict[str, Any]) -> CancelTaskResponse` - Requests the cancellation of a running task. The `payload` must contain the `task_id`.
|
|
838
|
-
- `async set_task_callback(self, payload: dict[str, Any]) -> SetTaskPushNotificationResponse` - Sets a callback URL for a specific task. The agent will send a notification to this URL upon task completion. The `payload` must contain the `task_id` and `callback_url`.
|
|
839
|
-
- `async get_task_callback(self, payload: dict[str, Any]) -> GetTaskPushNotificationResponse` - Retrieves the currently configured callback URL for a task. The `payload` must contain the `task_id`.
|
|
840
|
-
|
|
841
|
-
**Usage Examples:**
|
|
842
|
-
```python
|
|
843
|
-
import asyncio
|
|
844
|
-
from src.solace_agent_mesh.common.client import A2AClient, A2ACardResolver
|
|
845
|
-
|
|
846
|
-
# Assume these types are available for type hinting
|
|
847
|
-
# from src.solace_agent_mesh.common.types import SendTaskResponse, SendTaskStreamingResponse
|
|
848
|
-
|
|
849
|
-
async def main():
|
|
850
|
-
# First, discover the agent's capabilities and endpoint URL
|
|
851
|
-
resolver = A2ACardResolver(base_url="https://some-agent.ai")
|
|
852
|
-
agent_card = resolver.get_agent_card()
|
|
853
|
-
|
|
854
|
-
# --- Initialization ---
|
|
855
|
-
# Method 1: Initialize client using the discovered AgentCard
|
|
856
|
-
client = A2AClient(agent_card=agent_card)
|
|
857
|
-
|
|
858
|
-
# Method 2: Initialize client with a direct URL (if known)
|
|
859
|
-
# client = A2AClient(url="https://some-agent.ai/api/v1/a2a")
|
|
860
|
-
|
|
861
|
-
# --- Send a simple task ---
|
|
862
|
-
print("--- Sending a simple task ---")
|
|
863
|
-
task_payload = {"action": "summarize_text", "text": "A long article..."}
|
|
864
|
-
send_response = await client.send_task(payload=task_payload)
|
|
865
|
-
task_id = send_response.result.task_id
|
|
866
|
-
print(f"Task created with ID: {task_id}")
|
|
867
|
-
|
|
868
|
-
# --- Get task status ---
|
|
869
|
-
print("\n--- Checking task status ---")
|
|
870
|
-
status_response = await client.get_task(payload={"task_id": task_id})
|
|
871
|
-
print(f"Task status: {status_response.result.status}")
|
|
872
|
-
|
|
873
|
-
# --- Send a streaming task ---
|
|
874
|
-
print("\n--- Sending a streaming task ---")
|
|
875
|
-
stream_payload = {"action": "generate_story", "prompt": "A robot who discovers music"}
|
|
876
|
-
async for chunk in client.send_task_streaming(payload=stream_payload):
|
|
877
|
-
# Each chunk is a SendTaskStreamingResponse object
|
|
878
|
-
print(f"Received stream chunk: {chunk.result.content_chunk}")
|
|
879
|
-
|
|
880
|
-
# --- Set a callback URL for the task ---
|
|
881
|
-
print("\n--- Setting a callback URL ---")
|
|
882
|
-
await client.set_task_callback(
|
|
883
|
-
payload={"task_id": task_id, "callback_url": "https://my-app.com/webhook"}
|
|
884
|
-
)
|
|
885
|
-
print("Callback URL set.")
|
|
886
|
-
|
|
887
|
-
# --- Cancel a task ---
|
|
888
|
-
print("\n--- Cancelling a task ---")
|
|
889
|
-
cancel_response = await client.cancel_task(payload={"task_id": task_id})
|
|
890
|
-
print(f"Task cancellation requested. Success: {cancel_response.result.cancelled}")
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
if __name__ == "__main__":
|
|
894
|
-
# Note: In a real application, you would use a running event loop.
|
|
895
|
-
# This example assumes the agent endpoint is available and working.
|
|
896
|
-
# To run this, you would need a live agent to connect to.
|
|
897
|
-
# asyncio.run(main())
|
|
898
|
-
print("Developer guide example executed.")
|
|
899
|
-
|
|
900
|
-
```
|
|
901
|
-
|
|
902
|
-
================================================================================
|
|
903
|
-
|
|
904
|
-
## Section 10: common/common_llm.txt
|
|
905
|
-
|
|
906
|
-
**Source file:** `common/common_llm.txt`
|
|
907
|
-
|
|
908
|
-
Here is the comprehensive developer guide for the `common` directory.
|
|
909
|
-
|
|
910
|
-
## Quick Summary
|
|
911
|
-
The `common` directory provides the foundational infrastructure for Agent-to-Agent (A2A) communication within the Solace AI Connector. It establishes the core protocol, data types, and message translation logic that underpins all interactions between AI agents and gateways.
|
|
912
|
-
|
|
913
|
-
The architecture is designed for clarity and extensibility. Core, low-level definitions are located in **direct files**:
|
|
914
|
-
* `types.py` defines the canonical data structures (e.g., `Message`, `Task`, `AgentCard`).
|
|
915
|
-
* `a2a_protocol.py` handles the construction of Solace topics and the translation between A2A and Google ADK message formats.
|
|
916
|
-
* `agent_registry.py` provides a simple, thread-safe mechanism for discovering and tracking available agents.
|
|
917
|
-
|
|
918
|
-
This foundation is then leveraged by specialized **subdirectories**, which provide higher-level, ready-to-use components:
|
|
919
|
-
* `client/`: A complete client library for discovering and interacting with remote agents.
|
|
920
|
-
* `server/`: A stand-alone server implementation for building A2A-compliant agents.
|
|
921
|
-
* `middleware/`: A pluggable framework for customizing configuration and feature access.
|
|
922
|
-
* `services/`: A factory-based system for integrating identity and other external data sources.
|
|
923
|
-
* `utils/`: A collection of cross-cutting utilities for caching, logging, and dynamic content processing.
|
|
924
|
-
|
|
925
|
-
Together, these components form a cohesive ecosystem, enabling developers to either build new agents from scratch using the `server` components or interact with existing agents using the `client` library, all while relying on the same underlying protocol and types.
|
|
926
|
-
|
|
927
|
-
## Files and Subdirectories Overview
|
|
928
|
-
- **Direct files:**
|
|
929
|
-
- `__init__.py`: Package initialization file.
|
|
930
|
-
- `a2a_protocol.py`: Handles A2A topic construction and translation between A2A and ADK message formats.
|
|
931
|
-
- `agent_registry.py`: A thread-safe registry for managing discovered agent cards.
|
|
932
|
-
- `types.py`: Contains all Pydantic models for A2A protocol messages, tasks, and data structures.
|
|
933
|
-
- **Subdirectories:**
|
|
934
|
-
- `client/`: Provides a high-level client for discovering and communicating with remote A2A agents.
|
|
935
|
-
- `middleware/`: A pluggable framework for configuration resolution and system extensibility.
|
|
936
|
-
- `server/`: A complete A2A server implementation with JSON-RPC support and task management.
|
|
937
|
-
- `services/`: Provides shared services like identity management using a factory pattern.
|
|
938
|
-
- `utils/`: Contains common utility functions and an embedded expression processing system.
|
|
939
|
-
|
|
940
|
-
## Developer API Reference
|
|
941
|
-
|
|
942
|
-
### Direct Files
|
|
943
|
-
|
|
944
|
-
#### a2a_protocol.py
|
|
945
|
-
**Purpose:** Provides the core functions for constructing Solace topics according to the A2A specification and for translating messages between the A2A format and the Google ADK format.
|
|
946
|
-
**Import:** `from common.a2a_protocol import get_agent_request_topic, translate_a2a_to_adk_content`
|
|
947
|
-
|
|
948
|
-
**Classes/Functions/Constants:**
|
|
949
|
-
* **Constants**:
|
|
950
|
-
* `A2A_VERSION: str`: The current version of the A2A protocol (e.g., "v1").
|
|
951
|
-
* `A2A_BASE_PATH: str`: The base path used in all A2A topics (e.g., "a2a/v1").
|
|
952
|
-
* **Topic Construction Functions**:
|
|
953
|
-
* `get_a2a_base_topic(namespace: str) -> str`: Returns the base topic prefix for all A2A communication.
|
|
954
|
-
* `get_discovery_topic(namespace: str) -> str`: Returns the topic for agent card discovery.
|
|
955
|
-
* `get_agent_request_topic(namespace: str, agent_name: str) -> str`: Returns the topic for sending requests to a specific agent.
|
|
956
|
-
* `get_gateway_status_topic(namespace: str, gateway_id: str, task_id: str) -> str`: Returns the topic for an agent to publish status updates to a gateway.
|
|
957
|
-
* `get_gateway_response_topic(namespace: str, gateway_id: str, task_id: str) -> str`: Returns the topic for an agent to publish final responses to a gateway.
|
|
958
|
-
* `get_client_response_topic(namespace: str, client_id: str) -> str`: Returns the topic for publishing final responses to a specific client.
|
|
959
|
-
* `get_client_status_topic(namespace: str, client_id: str, task_id: str) -> str`: Returns the topic for publishing status updates to a specific client.
|
|
960
|
-
* ... and various functions for subscription topics (e.g., `get_gateway_status_subscription_topic`).
|
|
961
|
-
* **Message Translation Functions**:
|
|
962
|
-
* `translate_a2a_to_adk_content(a2a_message: A2AMessage, log_identifier: str) -> adk_types.Content`: Translates an A2A `Message` object into the Google ADK `Content` format.
|
|
963
|
-
* `format_adk_event_as_a2a(...) -> Tuple[Optional[JSONRPCResponse], ...]`: Translates an ADK `Event` into an A2A `JSONRPCResponse` containing a `TaskStatusUpdateEvent`.
|
|
964
|
-
* `format_and_route_adk_event(...) -> Tuple[Optional[Dict], Optional[str], ...]`: A higher-level wrapper that formats an ADK event and determines the correct Solace topic to publish it to.
|
|
965
|
-
|
|
966
|
-
#### agent_registry.py
|
|
967
|
-
**Purpose:** Provides a simple, thread-safe, in-memory store for discovered `AgentCard` objects. This is useful for components that need to keep track of available agents in the network.
|
|
968
|
-
**Import:** `from common.agent_registry import AgentRegistry`
|
|
969
|
-
|
|
970
|
-
**Classes/Functions/Constants:**
|
|
971
|
-
* **`AgentRegistry`**: A thread-safe class for storing and managing agent cards.
|
|
972
|
-
* `add_or_update_agent(self, agent_card: AgentCard)`: Adds a new agent or updates an existing one.
|
|
973
|
-
* `get_agent(self, agent_name: str) -> Optional[AgentCard]`: Retrieves an agent card by its unique name.
|
|
974
|
-
* `get_agent_names(self) -> List[str]`: Returns a sorted list of all discovered agent names.
|
|
975
|
-
* `clear(self)`: Clears all agents from the registry.
|
|
976
|
-
|
|
977
|
-
#### types.py
|
|
978
|
-
**Purpose:** Defines all the Pydantic data models that constitute the A2A protocol. These types ensure data consistency and provide validation across all components.
|
|
979
|
-
**Import:** `from common.types import Message, Task, AgentCard, JSONRPCRequest, TaskState`
|
|
980
|
-
|
|
981
|
-
**Classes/Functions/Constants:**
|
|
982
|
-
* **Core Data Structures**:
|
|
983
|
-
* `Message`: Represents a message from a user or agent, containing a list of `Part` objects.
|
|
984
|
-
* `Part`: A discriminated union of `TextPart`, `FilePart`, and `DataPart`.
|
|
985
|
-
* `Task`: The central object representing a complete task, including its ID, status, history, and artifacts.
|
|
986
|
-
* `TaskStatus`: Describes the current state of a task (e.g., `WORKING`, `COMPLETED`).
|
|
987
|
-
* `TaskState(Enum)`: An enumeration of all possible task states.
|
|
988
|
-
* `AgentCard`: A comprehensive description of an agent's identity, capabilities, and skills.
|
|
989
|
-
* `Artifact`: Represents a task output, such as a generated file or structured data.
|
|
990
|
-
* **JSON-RPC Structures**:
|
|
991
|
-
* `JSONRPCRequest`: The base model for all JSON-RPC requests.
|
|
992
|
-
* `JSONRPCResponse`: The base model for all JSON-RPC responses.
|
|
993
|
-
* `SendTaskRequest`, `GetTaskRequest`, etc.: Specific request types inheriting from `JSONRPCRequest`.
|
|
994
|
-
* **Error Structures**:
|
|
995
|
-
* `JSONRPCError`: The base model for errors.
|
|
996
|
-
* `InternalError`, `TaskNotFoundError`, etc.: Specific error types inheriting from `JSONRPCError`.
|
|
997
|
-
|
|
998
|
-
### Subdirectory APIs
|
|
999
|
-
|
|
1000
|
-
#### client/
|
|
1001
|
-
**Purpose:** Provides a high-level, asynchronous client library for discovering and interacting with remote A2A agents.
|
|
1002
|
-
**Key Exports:** `A2AClient`, `A2ACardResolver`
|
|
1003
|
-
**Import Examples:**
|
|
1004
|
-
```python
|
|
1005
|
-
from common.client import A2AClient, A2ACardResolver
|
|
1006
|
-
```
|
|
1007
|
-
|
|
1008
|
-
#### middleware/
|
|
1009
|
-
**Purpose:** A pluggable middleware framework for customizing system behavior, such as resolving user-specific configurations and feature flags.
|
|
1010
|
-
**Key Exports:** `ConfigResolver`, `MiddlewareRegistry`
|
|
1011
|
-
**Import Examples:**
|
|
1012
|
-
```python
|
|
1013
|
-
from common.middleware import ConfigResolver, MiddlewareRegistry
|
|
1014
|
-
```
|
|
1015
|
-
|
|
1016
|
-
#### server/
|
|
1017
|
-
**Purpose:** A complete, stand-alone server for building A2A-compliant agents, handling HTTP requests, JSON-RPC, and task lifecycle management.
|
|
1018
|
-
**Key Exports:** `A2AServer`, `TaskManager`, `InMemoryTaskManager`
|
|
1019
|
-
**Import Examples:**
|
|
1020
|
-
```python
|
|
1021
|
-
from common.server import A2AServer, TaskManager, InMemoryTaskManager
|
|
1022
|
-
```
|
|
1023
|
-
|
|
1024
|
-
#### services/
|
|
1025
|
-
**Purpose:** A factory-based system for integrating external data sources for identity, employee information, and more.
|
|
1026
|
-
**Key Exports:** `BaseIdentityService`, `create_identity_service`
|
|
1027
|
-
**Import Examples:**
|
|
1028
|
-
```python
|
|
1029
|
-
from common.services.identity_service import create_identity_service, BaseIdentityService
|
|
1030
|
-
```
|
|
1031
|
-
|
|
1032
|
-
#### utils/
|
|
1033
|
-
**Purpose:** A collection of cross-cutting utilities for caching, logging, MIME type handling, and dynamic content processing.
|
|
1034
|
-
**Key Exports:** `InMemoryCache`, `is_text_based_mime_type`, `resolve_embeds_in_string`
|
|
1035
|
-
**Import Examples:**
|
|
1036
|
-
```python
|
|
1037
|
-
from common.utils.in_memory_cache import InMemoryCache
|
|
1038
|
-
from common.utils import is_text_based_mime_type
|
|
1039
|
-
from common.utils.embeds import resolve_embeds_in_string
|
|
1040
|
-
```
|
|
1041
|
-
|
|
1042
|
-
## Complete Usage Guide
|
|
1043
|
-
These examples demonstrate how to use the components from the `common` directory to build and interact with A2A agents.
|
|
1044
|
-
|
|
1045
|
-
### 1. How to import and use classes from direct files
|
|
1046
|
-
This example shows basic usage of the protocol, types, and agent registry, which form the foundation of any A2A component.
|
|
1047
|
-
|
|
1048
|
-
```python
|
|
1049
|
-
import uuid
|
|
1050
|
-
from common.a2a_protocol import get_agent_request_topic, get_gateway_status_topic
|
|
1051
|
-
from common.types import AgentCard,
|
|
1052
|
-
|
|
1053
|
-
================================================================================
|
|
1054
|
-
|
|
1055
|
-
## Section 11: common/middleware/middleware_llm.txt
|
|
1056
|
-
|
|
1057
|
-
**Source file:** `common/middleware/middleware_llm.txt`
|
|
1058
|
-
|
|
1059
|
-
Here is the DEVELOPER GUIDE for the `middleware` directory.
|
|
1060
|
-
|
|
1061
|
-
## Quick Summary
|
|
1062
|
-
The `middleware` directory provides a pluggable framework for system components that can be extended or replaced at runtime. It offers a registry system to dynamically bind custom implementations for core functionalities like configuration resolution. The default implementations provide permissive behavior, making them suitable for development and testing environments where all features are enabled by default.
|
|
1063
|
-
|
|
1064
|
-
## Files Overview
|
|
1065
|
-
- `__init__.py`: Exposes the main public classes of the middleware package for easy importing.
|
|
1066
|
-
- `config_resolver.py`: Defines the default, permissive configuration resolution middleware.
|
|
1067
|
-
- `registry.py`: Provides the `MiddlewareRegistry` for dynamically binding custom middleware implementations.
|
|
1068
|
-
|
|
1069
|
-
## Developer API Reference
|
|
1070
|
-
|
|
1071
|
-
### __init__.py
|
|
1072
|
-
**Purpose:** This file serves as the entry point to the `middleware` package, exporting the primary public interfaces for developers to use.
|
|
1073
|
-
|
|
1074
|
-
**Usage Examples:**
|
|
1075
|
-
```python
|
|
1076
|
-
# Import the main classes directly from the middleware package
|
|
1077
|
-
from solace_ai_connector.common.middleware import ConfigResolver, MiddlewareRegistry
|
|
1078
|
-
|
|
1079
|
-
# Now you can use ConfigResolver and MiddlewareRegistry
|
|
1080
|
-
print(ConfigResolver)
|
|
1081
|
-
print(MiddlewareRegistry)
|
|
1082
|
-
```
|
|
1083
|
-
|
|
1084
|
-
---
|
|
1085
|
-
|
|
1086
|
-
### config_resolver.py
|
|
1087
|
-
**Purpose:** This file provides a pluggable interface for resolving user-specific configuration and determining feature availability. The default `ConfigResolver` class is permissive, allowing all operations and enabling all features, which is ideal for development or simple deployments.
|
|
1088
|
-
|
|
1089
|
-
**Import:** `from solace_ai_connector.common.middleware import ConfigResolver`
|
|
1090
|
-
|
|
1091
|
-
**Classes:**
|
|
1092
|
-
- `ConfigResolver()` - A class containing static methods to resolve user-specific configuration and determine feature availability. This default implementation is permissive.
|
|
1093
|
-
- `resolve_user_config(user_identity: Any, gateway_context: Dict[str, Any], base_config: Dict[str, Any]) -> Dict[str, Any]` - (async) Resolves user-specific configuration. The default implementation returns the `base_config` unchanged.
|
|
1094
|
-
- `is_feature_enabled(user_config: Dict[str, Any], feature_descriptor: Dict[str, Any], context: Dict[str, Any]) -> bool` - Checks if a feature is enabled for a user. The default implementation always returns `True`.
|
|
1095
|
-
- `validate_operation_config(user_config: Dict[str, Any], operation_spec: Dict[str, Any], validation_context: Dict[str, Any]) -> Dict[str, Any]` - Validates if an operation is allowed for a user. The default implementation always returns a dictionary with `{'valid': True}`.
|
|
1096
|
-
- `filter_available_options(user_config: Dict[str, Any], available_options: List[Dict[str, Any]], filter_context: Dict[str, Any]) -> List[Dict[str, Any]]` - Filters a list of options based on user permissions. The default implementation returns the original `available_options` list.
|
|
1097
|
-
|
|
1098
|
-
**Usage Examples:**
|
|
1099
|
-
```python
|
|
1100
|
-
import asyncio
|
|
1101
|
-
from solace_ai_connector.common.middleware import ConfigResolver
|
|
1102
|
-
|
|
1103
|
-
async def main():
|
|
1104
|
-
# Example user identity and base configuration
|
|
1105
|
-
user_id = "test-user@example.com"
|
|
1106
|
-
base_conf = {"api_key": "default_key", "allowed_models": ["gpt-3.5-turbo"]}
|
|
1107
|
-
|
|
1108
|
-
# 1. Resolve user configuration (default implementation returns base_conf)
|
|
1109
|
-
user_config = await ConfigResolver.resolve_user_config(
|
|
1110
|
-
user_identity=user_id,
|
|
1111
|
-
gateway_context={"gateway_id": "gw-1"},
|
|
1112
|
-
base_config=base_conf
|
|
1113
|
-
)
|
|
1114
|
-
print(f"Resolved User Config: {user_config}")
|
|
1115
|
-
|
|
1116
|
-
# 2. Check if a feature is enabled (default is always True)
|
|
1117
|
-
feature_desc = {"feature_type": "ai_tool", "function_name": "code_interpreter"}
|
|
1118
|
-
is_enabled = ConfigResolver.is_feature_enabled(
|
|
1119
|
-
user_config=user_config,
|
|
1120
|
-
feature_descriptor=feature_desc,
|
|
1121
|
-
context={}
|
|
1122
|
-
)
|
|
1123
|
-
print(f"Is Feature Enabled: {is_enabled}")
|
|
1124
|
-
|
|
1125
|
-
# 3. Validate an operation (default is always valid)
|
|
1126
|
-
op_spec = {"operation_type": "model_inference", "model": "gpt-4"}
|
|
1127
|
-
validation = ConfigResolver.validate_operation_config(
|
|
1128
|
-
user_config=user_config,
|
|
1129
|
-
operation_spec=op_spec,
|
|
1130
|
-
validation_context={}
|
|
1131
|
-
)
|
|
1132
|
-
print(f"Operation Validation: {validation}")
|
|
1133
|
-
|
|
1134
|
-
# 4. Filter available options (default returns all options)
|
|
1135
|
-
all_models = [
|
|
1136
|
-
{"name": "gpt-3.5-turbo", "provider": "openai"},
|
|
1137
|
-
{"name": "gpt-4", "provider": "openai"},
|
|
1138
|
-
]
|
|
1139
|
-
available_models = ConfigResolver.filter_available_options(
|
|
1140
|
-
user_config=user_config,
|
|
1141
|
-
available_options=all_models,
|
|
1142
|
-
filter_context={"type": "language_model"}
|
|
1143
|
-
)
|
|
1144
|
-
print(f"Filtered Options: {available_models}")
|
|
1145
|
-
|
|
1146
|
-
if __name__ == "__main__":
|
|
1147
|
-
asyncio.run(main())
|
|
1148
|
-
```
|
|
1149
|
-
|
|
1150
|
-
---
|
|
1151
|
-
|
|
1152
|
-
### registry.py
|
|
1153
|
-
**Purpose:** This file provides the `MiddlewareRegistry`, a static class that allows developers to dynamically bind, or "plug in," their own custom middleware implementations at runtime. This is the core of the pluggable system.
|
|
1154
|
-
|
|
1155
|
-
**Import:** `from solace_ai_connector.common.middleware import MiddlewareRegistry`
|
|
1156
|
-
|
|
1157
|
-
**Classes:**
|
|
1158
|
-
- `MiddlewareRegistry()` - A registry for managing middleware implementations. All methods are class methods.
|
|
1159
|
-
- `bind_config_resolver(resolver_class: Type)` - Binds a custom class that implements the `ConfigResolver` interface. This new class will be used for all subsequent configuration resolution calls.
|
|
1160
|
-
- `get_config_resolver() -> Type` - Returns the currently bound `ConfigResolver` class. If no custom resolver has been bound, it returns the default `ConfigResolver`.
|
|
1161
|
-
- `register_initialization_callback(callback: callable)` - Registers a function to be executed when `initialize_middleware()` is called. Useful for setting up custom middleware components at application startup.
|
|
1162
|
-
- `initialize_middleware()` - Executes all registered initialization callbacks. This should be called once during application startup.
|
|
1163
|
-
- `reset_bindings()` - Resets all bindings back to their defaults. This is primarily useful for testing environments.
|
|
1164
|
-
- `get_registry_status() -> Dict[str, Any]` - Returns a dictionary containing the current status of the registry, such as which resolver is bound.
|
|
1165
|
-
|
|
1166
|
-
**Usage Examples:**
|
|
1167
|
-
```python
|
|
1168
|
-
import asyncio
|
|
1169
|
-
from typing import Any, Dict, List
|
|
1170
|
-
from solace_ai_connector.common.middleware import MiddlewareRegistry, ConfigResolver
|
|
1171
|
-
|
|
1172
|
-
# 1. Define a custom ConfigResolver implementation
|
|
1173
|
-
class MyCustomConfigResolver:
|
|
1174
|
-
"""A custom resolver that only allows 'admin' users to use 'gpt-4'."""
|
|
1175
|
-
@staticmethod
|
|
1176
|
-
async def resolve_user_config(user_identity: Any, **kwargs) -> Dict[str, Any]:
|
|
1177
|
-
if user_identity == "admin":
|
|
1178
|
-
return {"role": "admin", "allowed_models": ["gpt-4", "gpt-3.5-turbo"]}
|
|
1179
|
-
return {"role": "user", "allowed_models": ["gpt-3.5-turbo"]}
|
|
1180
|
-
|
|
1181
|
-
@staticmethod
|
|
1182
|
-
def validate_operation_config(user_config: Dict, operation_spec: Dict, **kwargs) -> Dict:
|
|
1183
|
-
model = operation_spec.get("model")
|
|
1184
|
-
if model and model not in user_config.get("allowed_models", []):
|
|
1185
|
-
return {"valid": False, "reason": f"Model '{model}' not allowed for this user."}
|
|
1186
|
-
return {"valid": True}
|
|
1187
|
-
|
|
1188
|
-
# Inherit other methods from the default for simplicity
|
|
1189
|
-
is_feature_enabled = ConfigResolver.is_feature_enabled
|
|
1190
|
-
filter_available_options = ConfigResolver.filter_available_options
|
|
1191
|
-
|
|
1192
|
-
# 2. Define an initialization callback
|
|
1193
|
-
def setup_custom_logging():
|
|
1194
|
-
print("Custom middleware initialization logic is running!")
|
|
1195
|
-
|
|
1196
|
-
# 3. Bind the custom components
|
|
1197
|
-
MiddlewareRegistry.bind_config_resolver(MyCustomConfigResolver)
|
|
1198
|
-
MiddlewareRegistry.register_initialization_callback(setup_custom_logging)
|
|
1199
|
-
|
|
1200
|
-
# 4. Initialize the middleware (e.g., at application startup)
|
|
1201
|
-
print("--- Initializing Middleware ---")
|
|
1202
|
-
MiddlewareRegistry.initialize_middleware()
|
|
1203
|
-
print("--- Initialization Complete ---")
|
|
1204
|
-
|
|
1205
|
-
# 5. Use the middleware system
|
|
1206
|
-
async def check_permissions():
|
|
1207
|
-
# The registry will now use MyCustomConfigResolver automatically
|
|
1208
|
-
CurrentResolver = MiddlewareRegistry.get_config_resolver()
|
|
1209
|
-
print(f"Current resolver is: {CurrentResolver.__name__}")
|
|
1210
|
-
|
|
1211
|
-
# Check an admin user
|
|
1212
|
-
admin_config = await CurrentResolver.resolve_user_config("admin")
|
|
1213
|
-
validation_result = CurrentResolver.validate_operation_config(
|
|
1214
|
-
admin_config, {"model": "gpt-4"}
|
|
1215
|
-
)
|
|
1216
|
-
print(f"Admin validation for gpt-4: {validation_result}")
|
|
1217
|
-
|
|
1218
|
-
# Check a regular user
|
|
1219
|
-
user_config = await CurrentResolver.resolve_user_config("user")
|
|
1220
|
-
validation_result = CurrentResolver.validate_operation_config(
|
|
1221
|
-
user_config, {"model": "gpt-4"}
|
|
1222
|
-
)
|
|
1223
|
-
print(f"User validation for gpt-4: {validation_result}")
|
|
1224
|
-
|
|
1225
|
-
# Run the example
|
|
1226
|
-
asyncio.run(check_permissions())
|
|
1227
|
-
|
|
1228
|
-
# 6. Check status and reset (useful for testing)
|
|
1229
|
-
print(f"\nRegistry Status: {MiddlewareRegistry.get_registry_status()}")
|
|
1230
|
-
MiddlewareRegistry.reset_bindings()
|
|
1231
|
-
print(f"Registry Status after reset: {MiddlewareRegistry.get_registry_status()}")
|
|
1232
|
-
```
|
|
1233
|
-
|
|
1234
|
-
================================================================================
|
|
1235
|
-
|
|
1236
|
-
## Section 12: common/server/server_llm.txt
|
|
1237
|
-
|
|
1238
|
-
**Source file:** `common/server/server_llm.txt`
|
|
1239
|
-
|
|
1240
|
-
## Quick Summary
|
|
1241
|
-
The `server` directory provides a complete, stand-alone Agent-to-Agent (A2A) communication server. It is built using Starlette and implements the JSON-RPC 2.0 protocol for handling various task-related requests, including standard request-response, task streaming via Server-Sent Events (SSE), and push notification management. It features an extensible task management system with a default in-memory implementation.
|
|
1242
|
-
|
|
1243
|
-
## Files Overview
|
|
1244
|
-
- `__init__.py`: Exposes the primary public classes (`A2AServer`, `TaskManager`, `InMemoryTaskManager`) for easy access.
|
|
1245
|
-
- `server.py`: Contains the main `A2AServer` class, which sets up the Starlette web application, defines HTTP endpoints, and routes incoming A2A requests to the task manager.
|
|
1246
|
-
- `task_manager.py`: Defines the `TaskManager` abstract base class, which outlines the contract for handling all task operations, and provides a concrete `InMemoryTaskManager` implementation.
|
|
1247
|
-
- `utils.py`: A collection of utility functions for creating standardized error responses and checking modality compatibility.
|
|
1248
|
-
|
|
1249
|
-
## Developer API Reference
|
|
1250
|
-
|
|
1251
|
-
### __init__.py
|
|
1252
|
-
**Purpose:** This file makes the core server components available for direct import from the `server` package, simplifying access for developers.
|
|
1253
|
-
**Import:** `from solace_ai_connector.common.server import A2AServer, TaskManager, InMemoryTaskManager`
|
|
1254
|
-
|
|
1255
|
-
---
|
|
1256
|
-
|
|
1257
|
-
### server.py
|
|
1258
|
-
**Purpose:** Implements the core HTTP server for Agent-to-Agent (A2A) communication. It handles JSON-RPC request parsing, routing to the appropriate task manager methods, and response generation, including support for Server-Sent Events (SSE).
|
|
1259
|
-
**Import:** `from solace_ai_connector.common.server import A2AServer`
|
|
1260
|
-
|
|
1261
|
-
**Classes:**
|
|
1262
|
-
- `A2AServer(host: str = "0.0.0.0", port: int = 5000, endpoint: str = "/", agent_card: AgentCard = None, task_manager: TaskManager = None)` - A Starlette-based web server that exposes A2A endpoints.
|
|
1263
|
-
- `start() -> None` - Starts the web server using uvicorn. Raises a `ValueError` if `agent_card` or `task_manager` are not set.
|
|
1264
|
-
- `host: str` - The host address the server will bind to.
|
|
1265
|
-
- `port: int` - The port the server will listen on.
|
|
1266
|
-
- `endpoint: str` - The main API endpoint path for receiving JSON-RPC requests.
|
|
1267
|
-
- `task_manager: TaskManager` - The handler responsible for all task-related business logic.
|
|
1268
|
-
- `agent_card: AgentCard` - The metadata for the agent, served at `/.well-known/agent.json`.
|
|
1269
|
-
|
|
1270
|
-
**Usage Examples:**
|
|
1271
|
-
```python
|
|
1272
|
-
# main.py
|
|
1273
|
-
from solace_ai_connector.common.server import A2AServer, InMemoryTaskManager
|
|
1274
|
-
from solace_ai_connector.common.types import AgentCard
|
|
1275
|
-
|
|
1276
|
-
# 1. Define the agent's capabilities and metadata
|
|
1277
|
-
my_agent_card = AgentCard(
|
|
1278
|
-
id="my-awesome-agent-v1",
|
|
1279
|
-
name="Awesome Agent",
|
|
1280
|
-
version="1.0.0",
|
|
1281
|
-
description="An agent that does awesome things.",
|
|
1282
|
-
documentation_url="https://example.com/docs",
|
|
1283
|
-
supported_tasks=["summarize", "translate"],
|
|
1284
|
-
input_modalities=["text/plain"],
|
|
1285
|
-
output_modalities=["text/plain"]
|
|
1286
|
-
)
|
|
1287
|
-
|
|
1288
|
-
# 2. Instantiate a task manager (or use your own custom implementation)
|
|
1289
|
-
# This example uses a basic in-memory manager.
|
|
1290
|
-
# For a real agent, you would extend InMemoryTaskManager to implement your logic.
|
|
1291
|
-
class MyAgentTaskManager(InMemoryTaskManager):
|
|
1292
|
-
async def on_send_task(self, request):
|
|
1293
|
-
# Implement your agent's logic here
|
|
1294
|
-
pass
|
|
1295
|
-
async def on_send_task_subscribe(self, request):
|
|
1296
|
-
# Implement your agent's streaming logic here
|
|
1297
|
-
pass
|
|
1298
|
-
|
|
1299
|
-
task_manager = MyAgentTaskManager()
|
|
1300
|
-
|
|
1301
|
-
# 3. Create and configure the server
|
|
1302
|
-
server = A2AServer(
|
|
1303
|
-
host="127.0.0.1",
|
|
1304
|
-
port=8080,
|
|
1305
|
-
endpoint="/api/v1/a2a",
|
|
1306
|
-
agent_card=my_agent_card,
|
|
1307
|
-
task_manager=task_manager
|
|
1308
|
-
)
|
|
1309
|
-
|
|
1310
|
-
# 4. Start the server
|
|
1311
|
-
if __name__ == "__main__":
|
|
1312
|
-
print("Starting A2A Server...")
|
|
1313
|
-
server.start()
|
|
1314
|
-
```
|
|
1315
|
-
|
|
1316
|
-
---
|
|
1317
|
-
|
|
1318
|
-
### task_manager.py
|
|
1319
|
-
**Purpose:** Defines the abstract interface for task management and provides a ready-to-use, in-memory implementation. This is the core component for implementing an agent's business logic.
|
|
1320
|
-
**Import:** `from solace_ai_connector.common.server import TaskManager, InMemoryTaskManager`
|
|
1321
|
-
|
|
1322
|
-
**Classes:**
|
|
1323
|
-
- `TaskManager()` - An abstract base class that defines the interface for handling all A2A task-related operations. Developers must implement these methods in a subclass.
|
|
1324
|
-
- `on_get_task(request: GetTaskRequest) -> GetTaskResponse` - Handles a request to retrieve the status and details of a task.
|
|
1325
|
-
- `on_cancel_task(request: CancelTaskRequest) -> CancelTaskResponse` - Handles a request to cancel an ongoing task.
|
|
1326
|
-
- `on_send_task(request: SendTaskRequest) -> SendTaskResponse` - Handles a standard request-response task submission.
|
|
1327
|
-
- `on_send_task_subscribe(request: SendTaskStreamingRequest) -> Union[AsyncIterable[SendTaskStreamingResponse], JSONRPCResponse]` - Handles a task submission that requires a streaming response (SSE).
|
|
1328
|
-
- `on_set_task_push_notification(request: SetTaskPushNotificationRequest) -> SetTaskPushNotificationResponse` - Handles a request to configure push notifications for a task.
|
|
1329
|
-
- `on_get_task_push_notification(request: GetTaskPushNotificationRequest) -> GetTaskPushNotificationResponse` - Handles a request to retrieve the push notification configuration for a task.
|
|
1330
|
-
- `on_resubscribe_to_task(request: TaskResubscriptionRequest) -> Union[AsyncIterable[SendTaskResponse], JSONRPCResponse]` - Handles a request to resubscribe to a streaming task.
|
|
1331
|
-
|
|
1332
|
-
- `InMemoryTaskManager()` - A concrete implementation of `TaskManager` that stores tasks and push notification configurations in memory. It provides helper methods to manage task state and SSE subscriptions. It is designed to be extended.
|
|
1333
|
-
- `upsert_task(task_send_params: TaskSendParams) -> Task` - Creates a new task or retrieves an existing one by its ID, adding the new message to its history.
|
|
1334
|
-
- `update_store(task_id: str, status: TaskStatus, artifacts: list[Artifact]) -> Task` - Updates the status, message history, and artifacts of a specific task.
|
|
1335
|
-
- `set_push_notification_info(task_id: str, notification_config: PushNotificationConfig) -> None` - Stores the push notification configuration for a given task.
|
|
1336
|
-
- `get_push_notification_info(task_id: str) -> PushNotificationConfig` - Retrieves the push notification configuration for a given task.
|
|
1337
|
-
- `has_push_notification_info(task_id: str) -> bool` - Checks if a push notification configuration exists for a task.
|
|
1338
|
-
- `setup_sse_consumer(task_id: str, is_resubscribe: bool = False) -> asyncio.Queue` - Creates and registers an `asyncio.Queue` for a new SSE subscriber for a given task.
|
|
1339
|
-
- `enqueue_events_for_sse(task_id: str, task_update_event: Any) -> None` - Puts a new event (e.g., `TaskStatusUpdateEvent`) into the queues of all active SSE subscribers for a task.
|
|
1340
|
-
- `dequeue_events_for_sse(request_id: str, task_id: str, sse_event_queue: asyncio.Queue) -> AsyncIterable[SendTaskStreamingResponse]` - An async generator that yields events from an SSE queue, wrapping them in `SendTaskStreamingResponse` objects.
|
|
1341
|
-
|
|
1342
|
-
**Usage Examples:**
|
|
1343
|
-
```python
|
|
1344
|
-
# custom_task_manager.py
|
|
1345
|
-
import asyncio
|
|
1346
|
-
from solace_ai_connector.common.server import InMemoryTaskManager
|
|
1347
|
-
from solace_ai_connector.common.types import (
|
|
1348
|
-
SendTaskRequest, SendTaskResponse, Task, TaskStatus, TaskState,
|
|
1349
|
-
SendTaskStreamingRequest, SendTaskStreamingResponse, TaskStatusUpdateEvent
|
|
1350
|
-
)
|
|
1351
|
-
from typing import AsyncIterable, Union
|
|
1352
|
-
|
|
1353
|
-
class MyCustomTaskManager(InMemoryTaskManager):
|
|
1354
|
-
# Implement the core logic for a standard task
|
|
1355
|
-
async def on_send_task(self, request: SendTaskRequest) -> SendTaskResponse:
|
|
1356
|
-
task = await self.upsert_task(request.params)
|
|
1357
|
-
print(f"Received task {task.id} with message: {request.params.message.content}")
|
|
1358
|
-
|
|
1359
|
-
# Simulate work
|
|
1360
|
-
await asyncio.sleep(2)
|
|
1361
|
-
|
|
1362
|
-
# Update task status to completed
|
|
1363
|
-
final_status = TaskStatus(state=TaskState.COMPLETED)
|
|
1364
|
-
await self.update_store(task.id, final_status, [])
|
|
1365
|
-
|
|
1366
|
-
return SendTaskResponse(id=request.id, result=task)
|
|
1367
|
-
|
|
1368
|
-
# Implement the core logic for a streaming task
|
|
1369
|
-
async def on_send_task_subscribe(
|
|
1370
|
-
self, request: SendTaskStreamingRequest
|
|
1371
|
-
) -> Union[AsyncIterable[SendTaskStreamingResponse], JSONRPCResponse]:
|
|
1372
|
-
|
|
1373
|
-
await self.upsert_task(request.params)
|
|
1374
|
-
sse_queue = await self.setup_sse_consumer(request.params.id)
|
|
1375
|
-
|
|
1376
|
-
# Start the background task processing
|
|
1377
|
-
asyncio.create_task(self._process_streaming_task(request.params.id))
|
|
1378
|
-
|
|
1379
|
-
# Return the async generator that will stream responses
|
|
1380
|
-
return self.dequeue_events_for_sse(request.id, request.params.id, sse_queue)
|
|
1381
|
-
|
|
1382
|
-
async def _process_streaming_task(self, task_id: str):
|
|
1383
|
-
# Simulate streaming work
|
|
1384
|
-
for i in range(5):
|
|
1385
|
-
await asyncio.sleep(1)
|
|
1386
|
-
update = TaskStatusUpdateEvent(
|
|
1387
|
-
status=TaskStatus(state=TaskState.IN_PROGRESS),
|
|
1388
|
-
message={"content": f"Step {i+1} complete"}
|
|
1389
|
-
)
|
|
1390
|
-
# Enqueue the update for all subscribers
|
|
1391
|
-
await self.enqueue_events_for_sse(task_id, update)
|
|
1392
|
-
|
|
1393
|
-
# Send final event
|
|
1394
|
-
final_update = TaskStatusUpdateEvent(
|
|
1395
|
-
status=TaskStatus(state=TaskState.COMPLETED),
|
|
1396
|
-
final=True
|
|
1397
|
-
)
|
|
1398
|
-
await self.enqueue_events_for_sse(task_id, final_update)
|
|
1399
|
-
```
|
|
1400
|
-
|
|
1401
|
-
---
|
|
1402
|
-
|
|
1403
|
-
### utils.py
|
|
1404
|
-
**Purpose:** Provides common utility functions used within the server, primarily for creating standardized JSON-RPC error responses and performing compatibility checks.
|
|
1405
|
-
**Import:** `from solace_ai_connector.common.server.utils import are_modalities_compatible, new_incompatible_types_error, new_not_implemented_error`
|
|
1406
|
-
|
|
1407
|
-
**Functions:**
|
|
1408
|
-
- `are_modalities_compatible(server_output_
|
|
1409
|
-
|
|
1410
|
-
================================================================================
|
|
1411
|
-
|
|
1412
|
-
## Section 13: common/services/providers/providers_llm.txt
|
|
1413
|
-
|
|
1414
|
-
**Source file:** `common/services/providers/providers_llm.txt`
|
|
1415
|
-
|
|
1416
|
-
## Quick Summary
|
|
1417
|
-
This directory contains concrete implementations (providers) for the abstract services defined in the parent `services` package. These providers offer specific ways to fulfill service contracts, such as sourcing user identity information from a local file.
|
|
1418
|
-
|
|
1419
|
-
## Files Overview
|
|
1420
|
-
- `__init__.py`: Marks the directory as a Python package.
|
|
1421
|
-
- `local_file_identity_service.py`: An identity service implementation that reads user data from a local JSON file.
|
|
1422
|
-
|
|
1423
|
-
## Developer API Reference
|
|
1424
|
-
|
|
1425
|
-
### __init__.py
|
|
1426
|
-
**Purpose:** Initializes the `providers` package.
|
|
1427
|
-
**Import:** `from solace_ai_connector.common.services import providers`
|
|
1428
|
-
|
|
1429
|
-
This file contains no public classes or functions.
|
|
1430
|
-
|
|
1431
|
-
---
|
|
1432
|
-
|
|
1433
|
-
### local_file_identity_service.py
|
|
1434
|
-
**Purpose:** Provides a simple, file-based identity service that reads user profiles from a local JSON file. It's ideal for development, testing, or small-scale deployments where a full-fledged identity provider is not available.
|
|
1435
|
-
**Import:** `from solace_ai_connector.common.services.providers.local_file_identity_service import LocalFileIdentityService`
|
|
1436
|
-
|
|
1437
|
-
**Classes:**
|
|
1438
|
-
- `LocalFileIdentityService(config: Dict[str, Any])` - An identity service that sources user data from a local JSON file. The `config` dictionary must contain a `file_path` key.
|
|
1439
|
-
- `async get_user_profile(auth_claims: Dict[str, Any]) -> Optional[Dict[str, Any]]` - Looks up a user profile from the in-memory index. The lookup is performed using the `lookup_key` (configured during initialization) present in the `auth_claims` dictionary.
|
|
1440
|
-
- `async search_users(query: str, limit: int = 10) -> List[Dict[str, Any]]` - Performs a simple, case-insensitive search across user names and emails. Returns a list of matching user profiles.
|
|
1441
|
-
- `file_path: str` - The path to the JSON file containing the user data.
|
|
1442
|
-
- `lookup_key: str` - The key within the user profile objects and `auth_claims` used to identify a user. Defaults to `"id"`.
|
|
1443
|
-
- `all_users: List[Dict[str, Any]]` - The complete list of all user profiles loaded from the file.
|
|
1444
|
-
- `user_index: Dict[str, Dict[str, Any]]` - An in-memory dictionary mapping the `lookup_key` value to the corresponding user profile for fast lookups.
|
|
1445
|
-
|
|
1446
|
-
**Usage Examples:**
|
|
1447
|
-
```python
|
|
1448
|
-
import asyncio
|
|
1449
|
-
import json
|
|
1450
|
-
import os
|
|
1451
|
-
from typing import Dict, Any, Optional, List
|
|
1452
|
-
|
|
1453
|
-
# Assume this is the identity service class from the file
|
|
1454
|
-
from solace_ai_connector.common.services.providers.local_file_identity_service import LocalFileIdentityService
|
|
1455
|
-
|
|
1456
|
-
# --- Setup: Create a dummy users.json for the example ---
|
|
1457
|
-
users_data = [
|
|
1458
|
-
{
|
|
1459
|
-
"id": "jdoe",
|
|
1460
|
-
"email": "jane.doe@example.com",
|
|
1461
|
-
"name": "Jane Doe",
|
|
1462
|
-
"title": "Senior Engineer",
|
|
1463
|
-
"manager_id": "ssmith"
|
|
1464
|
-
},
|
|
1465
|
-
{
|
|
1466
|
-
"id": "ssmith",
|
|
1467
|
-
"email": "sam.smith@example.com",
|
|
1468
|
-
"name": "Sam Smith",
|
|
1469
|
-
"title": "Engineering Manager",
|
|
1470
|
-
"manager_id": None
|
|
1471
|
-
}
|
|
1472
|
-
]
|
|
1473
|
-
file_path = "users.json"
|
|
1474
|
-
with open(file_path, "w") as f:
|
|
1475
|
-
json.dump(users_data, f)
|
|
1476
|
-
# --- End Setup ---
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
async def main():
|
|
1480
|
-
# 1. Configure the service
|
|
1481
|
-
# The 'file_path' is required. 'lookup_key' is optional (defaults to 'id').
|
|
1482
|
-
config = {
|
|
1483
|
-
"file_path": file_path,
|
|
1484
|
-
"lookup_key": "id"
|
|
1485
|
-
}
|
|
1486
|
-
|
|
1487
|
-
# 2. Initialize the service
|
|
1488
|
-
identity_service = LocalFileIdentityService(config)
|
|
1489
|
-
print(f"Service initialized. Loaded {len(identity_service.all_users)} users.")
|
|
1490
|
-
|
|
1491
|
-
# 3. Get a specific user profile
|
|
1492
|
-
print("\n--- Getting user profile for id 'jdoe' ---")
|
|
1493
|
-
auth_claims = {"id": "jdoe"}
|
|
1494
|
-
profile = await identity_service.get_user_profile(auth_claims)
|
|
1495
|
-
if profile:
|
|
1496
|
-
print(f"Found profile: {profile}")
|
|
1497
|
-
else:
|
|
1498
|
-
print("Profile not found.")
|
|
1499
|
-
|
|
1500
|
-
# 4. Search for users by name
|
|
1501
|
-
print("\n--- Searching for users with 'sam' in their name ---")
|
|
1502
|
-
search_results = await identity_service.search_users(query="sam", limit=5)
|
|
1503
|
-
print(f"Found {len(search_results)} user(s): {search_results}")
|
|
1504
|
-
|
|
1505
|
-
# 5. Handle a case where the user is not found
|
|
1506
|
-
print("\n--- Getting user profile for non-existent id 'nobody' ---")
|
|
1507
|
-
not_found_profile = await identity_service.get_user_profile({"id": "nobody"})
|
|
1508
|
-
print(f"Profile for 'nobody': {not_found_profile}")
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
if __name__ == "__main__":
|
|
1512
|
-
asyncio.run(main())
|
|
1513
|
-
# Clean up the dummy file
|
|
1514
|
-
os.remove(file_path)
|
|
1515
|
-
|
|
1516
|
-
# Expected output:
|
|
1517
|
-
#
|
|
1518
|
-
# Service initialized. Loaded 2 users.
|
|
1519
|
-
#
|
|
1520
|
-
# --- Getting user profile for id 'jdoe' ---
|
|
1521
|
-
# Found profile: {'id': 'jdoe', 'email': 'jane.doe@example.com', 'name': 'Jane Doe', 'title': 'Senior Engineer', 'manager_id': 'ssmith'}
|
|
1522
|
-
#
|
|
1523
|
-
# --- Searching for users with 'sam' in their name ---
|
|
1524
|
-
# Found 1 user(s): [{'id': 'ssmith', 'name': 'Sam Smith', 'email': 'sam.smith@example.com', 'title': 'Engineering Manager'}]
|
|
1525
|
-
#
|
|
1526
|
-
# --- Getting user profile for non-existent id 'nobody' ---
|
|
1527
|
-
# Profile for 'nobody': None
|
|
1528
|
-
```
|
|
1529
|
-
|
|
1530
|
-
================================================================================
|
|
1531
|
-
|
|
1532
|
-
## Section 14: common/services/services_llm.txt
|
|
1533
|
-
|
|
1534
|
-
**Source file:** `common/services/services_llm.txt`
|
|
1535
|
-
|
|
1536
|
-
## Quick Summary
|
|
1537
|
-
The `services` directory provides a modular and extensible framework for integrating external data sources related to identity and employee information into the Solace AI Connector. It is built on a provider pattern, defining abstract base classes (`BaseIdentityService`, `BaseEmployeeService`) that establish a clear contract for what data and functionality a service must provide.
|
|
1538
|
-
|
|
1539
|
-
The core architecture revolves around factory functions (`create_identity_service`, `create_employee_service`) that instantiate specific service providers based on a configuration dictionary. This allows the application to remain decoupled from the concrete implementations. Providers can be either built-in (like the file-based identity service located in the `providers/` subdirectory) or dynamically loaded as external plugins, making the system highly flexible and easy to extend.
|
|
1540
|
-
|
|
1541
|
-
## Files and Subdirectories Overview
|
|
1542
|
-
- **Direct files:**
|
|
1543
|
-
- `__init__.py`: Marks the directory as a Python package.
|
|
1544
|
-
- `employee_service.py`: Defines the abstract contract and factory for employee data services.
|
|
1545
|
-
- `identity_service.py`: Defines the abstract contract and factory for user identity services.
|
|
1546
|
-
- **Subdirectories:**
|
|
1547
|
-
- `providers/`: Contains concrete implementations of the service contracts, such as a file-based identity provider.
|
|
1548
|
-
|
|
1549
|
-
## Developer API Reference
|
|
1550
|
-
|
|
1551
|
-
### Direct Files
|
|
1552
|
-
|
|
1553
|
-
#### employee_service.py
|
|
1554
|
-
**Purpose:** Defines the abstract base class (`BaseEmployeeService`) that all employee service providers must implement, and a factory function (`create_employee_service`) to instantiate them. It enforces a canonical schema for employee data to ensure consistency across different providers.
|
|
1555
|
-
**Import:** `from solace_ai_connector.common.services import BaseEmployeeService, create_employee_service`
|
|
1556
|
-
|
|
1557
|
-
**Classes/Functions/Constants:**
|
|
1558
|
-
- **`class BaseEmployeeService(ABC)`**: The abstract base class for employee service providers.
|
|
1559
|
-
- **`__init__(self, config: Dict[str, Any])`**: Initializes the service, setting up configuration and an optional in-memory cache.
|
|
1560
|
-
- **`async def get_employee_dataframe(self) -> pd.DataFrame`**: (Abstract) Returns the entire employee directory as a pandas DataFrame.
|
|
1561
|
-
- **`async def get_employee_profile(self, employee_id: str) -> Optional[Dict[str, Any]]`**: (Abstract) Fetches the profile for a single employee, conforming to the canonical schema.
|
|
1562
|
-
- **`async def get_time_off_data(self, employee_id: str) -> List[Dict[str, Any]]`**: (Abstract) Retrieves a list of time-off entries for an employee.
|
|
1563
|
-
- **`async def get_employee_profile_picture(self, employee_id: str) -> Optional[str]`**: (Abstract) Fetches an employee's profile picture as a data URI string.
|
|
1564
|
-
- **`def create_employee_service(config: Optional[Dict[str, Any]]) -> Optional[BaseEmployeeService]`**: A factory function that dynamically loads and instantiates an employee service provider based on the `type` specified in the configuration. It primarily uses Python's entry points to find and load external plugins.
|
|
1565
|
-
|
|
1566
|
-
#### identity_service.py
|
|
1567
|
-
**Purpose:** Defines the abstract base class (`BaseIdentityService`) for identity providers and a factory function (`create_identity_service`) to create instances of them. This service is used for user lookups and profile enrichment.
|
|
1568
|
-
**Import:** `from solace_ai_connector.common.services import BaseIdentityService, create_identity_service`
|
|
1569
|
-
|
|
1570
|
-
**Classes/Functions/Constants:**
|
|
1571
|
-
- **`class BaseIdentityService(ABC)`**: The abstract base class for identity service providers.
|
|
1572
|
-
- **`__init__(self, config: Dict[str, Any])`**: Initializes the service, setting up configuration and an optional in-memory cache.
|
|
1573
|
-
- **`async def get_user_profile(self, auth_claims: Dict[str, Any]) -> Optional[Dict[str, Any]]`**: (Abstract) Fetches additional profile details for an authenticated user based on claims.
|
|
1574
|
-
- **`async def search_users(self, query: str, limit: int = 10) -> List[Dict[str, Any]]`**: (Abstract) Searches for users based on a query string (e.g., for autocomplete).
|
|
1575
|
-
- **`def create_identity_service(config: Optional[Dict[str, Any]]) -> Optional[BaseIdentityService]`**: A factory function that instantiates an identity service provider. It has special handling for the built-in `local_file` provider and uses Python entry points for all other provider types.
|
|
1576
|
-
|
|
1577
|
-
### Subdirectory APIs
|
|
1578
|
-
|
|
1579
|
-
#### providers/
|
|
1580
|
-
**Purpose:** This subdirectory contains concrete implementations of the abstract service classes. It ships with a built-in provider for the `IdentityService` that is useful for development and testing.
|
|
1581
|
-
**Key Exports:** `LocalFileIdentityService`
|
|
1582
|
-
**Import Examples:**
|
|
1583
|
-
```python
|
|
1584
|
-
# Typically, you would use the factory function.
|
|
1585
|
-
# But for direct instantiation (e.g., in tests), you can do this:
|
|
1586
|
-
from solace_ai_connector.common.services.providers import LocalFileIdentityService
|
|
1587
|
-
```
|
|
1588
|
-
|
|
1589
|
-
## Complete Usage Guide
|
|
1590
|
-
The following examples demonstrate how to use the services framework, from basic instantiation using factories to creating custom providers.
|
|
1591
|
-
|
|
1592
|
-
### 1. How to Use the Service Factories (Recommended)
|
|
1593
|
-
The factories are the primary way to create and use services. They abstract away the specific implementation details.
|
|
1594
|
-
|
|
1595
|
-
**Example: Creating a File-Based Identity Service and a Plugin-Based Employee Service**
|
|
1596
|
-
|
|
1597
|
-
```python
|
|
1598
|
-
import asyncio
|
|
1599
|
-
from solace_ai_connector.common.services import create_identity_service, create_employee_service
|
|
1600
|
-
|
|
1601
|
-
# Assume you have a users.json file for the identity service
|
|
1602
|
-
# and a plugin installed for the employee service.
|
|
1603
|
-
|
|
1604
|
-
async def main():
|
|
1605
|
-
# --- Identity Service Example (using a built-in provider) ---
|
|
1606
|
-
identity_config = {
|
|
1607
|
-
"type": "local_file",
|
|
1608
|
-
"file_path": "path/to/your/users.json",
|
|
1609
|
-
"lookup_key": "email", # Key to use for lookups from auth_claims
|
|
1610
|
-
"cache_ttl_seconds": 3600
|
|
1611
|
-
}
|
|
1612
|
-
identity_service = create_identity_service(identity_config)
|
|
1613
|
-
|
|
1614
|
-
if identity_service:
|
|
1615
|
-
print("Identity Service created.")
|
|
1616
|
-
# Fetch a user profile
|
|
1617
|
-
auth_claims = {"email": "jane.doe@example.com"}
|
|
1618
|
-
user_profile = await identity_service.get_user_profile(auth_claims)
|
|
1619
|
-
print(f"User Profile: {user_profile}")
|
|
1620
|
-
|
|
1621
|
-
# Search for users
|
|
1622
|
-
search_results = await identity_service.search_users("Jane")
|
|
1623
|
-
print(f"Search Results: {search_results}")
|
|
1624
|
-
|
|
1625
|
-
# --- Employee Service Example (using an external plugin) ---
|
|
1626
|
-
# The 'type' must match the name of a registered plugin entry point.
|
|
1627
|
-
employee_config = {
|
|
1628
|
-
"type": "bamboohr_plugin",
|
|
1629
|
-
"api_key": "your-secret-api-key",
|
|
1630
|
-
"subdomain": "your-company",
|
|
1631
|
-
"cache_ttl_seconds": 7200
|
|
1632
|
-
}
|
|
1633
|
-
employee_service = create_employee_service(employee_config)
|
|
1634
|
-
|
|
1635
|
-
if employee_service:
|
|
1636
|
-
print("\nEmployee Service created.")
|
|
1637
|
-
# Get a detailed employee profile
|
|
1638
|
-
employee_profile = await employee_service.get_employee_profile("jane.doe@example.com")
|
|
1639
|
-
print(f"Employee Profile: {employee_profile}")
|
|
1640
|
-
|
|
1641
|
-
# Get time off data
|
|
1642
|
-
time_off = await employee_service.get_time_off_data("jane.doe@example.com")
|
|
1643
|
-
print(f"Time Off Data: {time_off}")
|
|
1644
|
-
|
|
1645
|
-
# To run this example:
|
|
1646
|
-
# asyncio.run(main())
|
|
1647
|
-
```
|
|
1648
|
-
|
|
1649
|
-
### 2. How to Use Functionality from Subdirectories
|
|
1650
|
-
While factories are preferred, you can instantiate providers from the `providers/` directory directly. This is useful for testing or when you know you will always use a specific built-in provider.
|
|
1651
|
-
|
|
1652
|
-
**Example: Direct Instantiation of `LocalFileIdentityService`**
|
|
1653
|
-
|
|
1654
|
-
```python
|
|
1655
|
-
import asyncio
|
|
1656
|
-
from solace_ai_connector.common.services.providers import LocalFileIdentityService
|
|
1657
|
-
|
|
1658
|
-
async def main():
|
|
1659
|
-
# Configuration does not need a 'type' key for direct instantiation
|
|
1660
|
-
config = {
|
|
1661
|
-
"file_path": "path/to/your/users.json",
|
|
1662
|
-
"lookup_key": "id"
|
|
1663
|
-
}
|
|
1664
|
-
|
|
1665
|
-
# Instantiate the class directly
|
|
1666
|
-
local_service = LocalFileIdentityService(config)
|
|
1667
|
-
print("LocalFileIdentityService
|
|
1668
|
-
|
|
1669
|
-
================================================================================
|
|
1670
|
-
|
|
1671
|
-
## Section 15: common/utils/embeds/embeds_llm.txt
|
|
1672
|
-
|
|
1673
|
-
**Source file:** `common/utils/embeds/embeds_llm.txt`
|
|
1674
|
-
|
|
1675
|
-
Here is the developer guide for the `embeds` directory.
|
|
1676
|
-
|
|
1677
|
-
## Quick Summary
|
|
1678
|
-
The `embeds` directory provides a system for finding, parsing, and resolving embedded expressions within strings. These expressions, denoted by `«...»`, can represent dynamic values like mathematical calculations, datetimes, or content from stored artifacts. The system supports multi-step data transformation pipelines on artifact content, recursive embed resolution, and safety features like depth and size limits. It is a core component for dynamic content generation and data processing.
|
|
1679
|
-
|
|
1680
|
-
## Files Overview
|
|
1681
|
-
- `__init__.py`: Exports the primary public functions and constants for easy access.
|
|
1682
|
-
- `constants.py`: Defines the syntax (delimiters, separators), regular expressions, and type classifications for embeds.
|
|
1683
|
-
- `converter.py`: Provides functions for converting data between different formats (e.g., bytes, string, JSON) and for serializing data into a final string representation.
|
|
1684
|
-
- `evaluators.py`: Contains the specific logic for evaluating simple embed types like `math`, `datetime`, and `uuid`.
|
|
1685
|
-
- `modifiers.py`: Implements a library of data transformation functions (e.g., `jsonpath`, `slice_rows`, `grep`) that can be chained together.
|
|
1686
|
-
- `resolver.py`: The core engine that orchestrates the entire embed resolution process, including handling modifier chains and recursion.
|
|
1687
|
-
- `types.py`: Defines the `DataFormat` enum used to track data types during transformations.
|
|
1688
|
-
|
|
1689
|
-
## Developer API Reference
|
|
1690
|
-
|
|
1691
|
-
### __init__.py
|
|
1692
|
-
**Purpose:** This module serves as the main public entry point for the `embeds` package, exporting the most commonly used functions and constants from the other modules. Developers should typically import from here.
|
|
1693
|
-
|
|
1694
|
-
**Import:** `from src.solace_agent_mesh.common.utils.embeds import resolve_embeds_recursively_in_string, evaluate_embed, EMBED_REGEX`
|
|
1695
|
-
|
|
1696
|
-
*(Note: Detailed documentation is available under each source file's section.)*
|
|
1697
|
-
|
|
1698
|
-
**Classes:**
|
|
1699
|
-
- None
|
|
1700
|
-
|
|
1701
|
-
**Functions:**
|
|
1702
|
-
- `evaluate_embed(...)`: Evaluates a single, parsed embed expression.
|
|
1703
|
-
- `resolve_embeds_in_string(...)`: Resolves embeds in a string for a single pass (non-recursive).
|
|
1704
|
-
- `resolve_embeds_recursively_in_string(...)`: Recursively finds and resolves all embeds in a string, respecting depth and size limits.
|
|
1705
|
-
|
|
1706
|
-
**Constants/Variables:**
|
|
1707
|
-
- `EMBED_DELIMITER_OPEN: str`: The opening delimiter for an embed (`«`).
|
|
1708
|
-
- `EMBED_DELIMITER_CLOSE: str`: The closing delimiter for an embed (`»`).
|
|
1709
|
-
- `EMBED_TYPE_SEPARATOR: str`: The separator between an embed's type and its expression (`:`).
|
|
1710
|
-
- `EMBED_FORMAT_SEPARATOR: str`: The separator for an optional format specifier (`|`).
|
|
1711
|
-
- `EMBED_CHAIN_DELIMITER: str`: The separator for modifier steps in an `artifact_content` chain (`>>>`).
|
|
1712
|
-
- `EMBED_REGEX: re.Pattern`: The compiled regular expression used to find embeds.
|
|
1713
|
-
- `EARLY_EMBED_TYPES: Set[str]`: A set of embed types that are resolved in an initial pass.
|
|
1714
|
-
- `LATE_EMBED_TYPES: Set[str]`: A set of embed types (like `artifact_content`) resolved in a subsequent pass.
|
|
1715
|
-
|
|
1716
|
-
---
|
|
1717
|
-
### constants.py
|
|
1718
|
-
**Purpose:** This file defines all the static constants that govern the syntax and classification of embeds. This includes delimiters, separators, the master regular expression for parsing, and sets that categorize embed types for phased resolution.
|
|
1719
|
-
|
|
1720
|
-
**Import:** `from src.solace_agent_mesh.common.utils.embeds.constants import EMBED_REGEX, EARLY_EMBED_TYPES`
|
|
1721
|
-
|
|
1722
|
-
**Classes:**
|
|
1723
|
-
- None
|
|
1724
|
-
|
|
1725
|
-
**Functions:**
|
|
1726
|
-
- None
|
|
1727
|
-
|
|
1728
|
-
**Constants/Variables:**
|
|
1729
|
-
- `EMBED_DELIMITER_OPEN: str`: The character that marks the beginning of an embed (`«`).
|
|
1730
|
-
- `EMBED_DELIMITER_CLOSE: str`: The character that marks the end of an embed (`»`).
|
|
1731
|
-
- `EMBED_TYPE_SEPARATOR: str`: The character separating the embed type from its expression (`:`).
|
|
1732
|
-
- `EMBED_FORMAT_SEPARATOR: str`: The character separating an expression from its optional format specifier (`|`).
|
|
1733
|
-
- `EMBED_CHAIN_DELIMITER: str`: The string separating transformation steps in an `artifact_content` embed (`>>>`).
|
|
1734
|
-
- `EMBED_REGEX: re.Pattern`: A compiled regular expression to find and capture the `type`, `expression`, and optional `format` from an embed string.
|
|
1735
|
-
- `EARLY_EMBED_TYPES: Set[str]`: A set of embed types (`math`, `datetime`, etc.) that are resolved first, as they are generally simple, self-contained, and do not involve recursion.
|
|
1736
|
-
- `LATE_EMBED_TYPES: Set[str]`: A set of embed types (`artifact_content`) that are resolved later, as they can be complex, involve I/O, and may contain further embeds that require recursive resolution.
|
|
1737
|
-
- `TEXT_CONTAINER_MIME_TYPES: Set[str]`: A set of MIME types that are considered to contain text and can be safely decoded to a string.
|
|
1738
|
-
|
|
1739
|
-
**Usage Examples:**
|
|
1740
|
-
```python
|
|
1741
|
-
import re
|
|
1742
|
-
from src.solace_agent_mesh.common.utils.embeds.constants import EMBED_REGEX
|
|
1743
|
-
|
|
1744
|
-
text = "The price is «math:10 * 1.15 | .2f» and the ID is «uuid:new»."
|
|
1745
|
-
|
|
1746
|
-
for match in EMBED_REGEX.finditer(text):
|
|
1747
|
-
embed_type = match.group(1)
|
|
1748
|
-
expression = match.group(2)
|
|
1749
|
-
format_spec = match.group(3) # This will be None if not present
|
|
1750
|
-
print(f"Type: {embed_type}, Expression: '{expression}', Format: '{format_spec}'")
|
|
1751
|
-
|
|
1752
|
-
# Expected Output:
|
|
1753
|
-
# Type: math, Expression: '10 * 1.15 ', Format: ' .2f'
|
|
1754
|
-
# Type: uuid, Expression: 'new', Format: 'None'
|
|
1755
|
-
```
|
|
1756
|
-
|
|
1757
|
-
---
|
|
1758
|
-
### converter.py
|
|
1759
|
-
**Purpose:** This file provides the core logic for data conversion and serialization. It can transform data between different `DataFormat` representations (e.g., `BYTES` to `STRING`, `STRING` to `LIST_OF_DICTS`) and serialize any format into a final string representation (e.g., `json`, `csv`, `datauri`).
|
|
1760
|
-
|
|
1761
|
-
**Import:** `from src.solace_agent_mesh.common.utils.embeds.converter import convert_data, serialize_data`
|
|
1762
|
-
|
|
1763
|
-
**Classes:**
|
|
1764
|
-
- None
|
|
1765
|
-
|
|
1766
|
-
**Functions:**
|
|
1767
|
-
- `convert_data(current_data: Any, current_format: Optional[DataFormat], target_format: DataFormat, log_id: str = "[Converter]", original_mime_type: Optional[str] = None) -> Tuple[Any, DataFormat, Optional[str]]`: Converts data from a source format to a target format. It uses `original_mime_type` as a hint for parsing (e.g., knowing that a string is JSON or CSV). Returns a tuple of `(converted_data, resulting_format, error_message)`.
|
|
1768
|
-
- `serialize_data(data: Any, data_format: Optional[DataFormat], target_string_format: Optional[str], original_mime_type: Optional[str], log_id: str = "[Serializer]") -> Tuple[str, Optional[str]]`: Serializes data from any `DataFormat` into a final string. `target_string_format` can be a keyword like `"json"`, `"csv"`, `"datauri"`, or a Python format specifier for numbers (e.g., `".2f"`). Returns a tuple of `(serialized_string, error_message)`.
|
|
1769
|
-
|
|
1770
|
-
**Constants/Variables:**
|
|
1771
|
-
- None
|
|
1772
|
-
|
|
1773
|
-
**Usage Examples:**
|
|
1774
|
-
```python
|
|
1775
|
-
from src.solace_agent_mesh.common.utils.embeds.converter import convert_data, serialize_data
|
|
1776
|
-
from src.solace_agent_mesh.common.utils.embeds.types import DataFormat
|
|
1777
|
-
|
|
1778
|
-
# Example 1: Convert CSV bytes to a list of dictionaries
|
|
1779
|
-
csv_bytes = b"id,name\n1,Alice\n2,Bob"
|
|
1780
|
-
list_of_dicts, new_format, err = convert_data(
|
|
1781
|
-
current_data=csv_bytes,
|
|
1782
|
-
current_format=DataFormat.BYTES,
|
|
1783
|
-
target_format=DataFormat.LIST_OF_DICTS,
|
|
1784
|
-
original_mime_type="text/csv"
|
|
1785
|
-
)
|
|
1786
|
-
if not err:
|
|
1787
|
-
print(f"Converted data: {list_of_dicts}")
|
|
1788
|
-
# Converted data: [{'id': '1', 'name': 'Alice'}, {'id': '2', 'name': 'Bob'}]
|
|
1789
|
-
|
|
1790
|
-
# Example 2: Serialize the list of dictionaries back to a pretty JSON string
|
|
1791
|
-
json_string, err = serialize_data(
|
|
1792
|
-
data=list_of_dicts,
|
|
1793
|
-
data_format=DataFormat.LIST_OF_DICTS,
|
|
1794
|
-
target_string_format="json_pretty",
|
|
1795
|
-
original_mime_type=None
|
|
1796
|
-
)
|
|
1797
|
-
if not err:
|
|
1798
|
-
print(f"Serialized JSON:\n{json_string}")
|
|
1799
|
-
|
|
1800
|
-
================================================================================
|
|
1801
|
-
|
|
1802
|
-
## Section 16: common/utils/utils_llm.txt
|
|
1803
|
-
|
|
1804
|
-
**Source file:** `common/utils/utils_llm.txt`
|
|
1805
|
-
|
|
1806
|
-
Here is the comprehensive developer guide for the `utils` directory.
|
|
1807
|
-
|
|
1808
|
-
## Quick Summary
|
|
1809
|
-
The `utils` directory provides a collection of essential, cross-cutting utilities for the Solace AI Connector. Its purpose is to offer robust, reusable solutions for common application needs, including caching, platform compatibility, secure communication, logging, and dynamic content generation.
|
|
1810
|
-
|
|
1811
|
-
The architecture consists of standalone utility files for specific tasks and a more complex, self-contained subdirectory for advanced functionality. Direct files provide services like a thread-safe in-memory cache (`in_memory_cache.py`), JWT-based authentication for push notifications (`push_notification_auth.py`), custom logging formatters (`log_formatters.py`), and a critical patch for asyncio on macOS (`asyncio_macos_fix.py`).
|
|
1812
|
-
|
|
1813
|
-
The `embeds` subdirectory provides a powerful system for finding, parsing, and resolving dynamic expressions embedded within strings. These utilities are designed to work together. For instance, a request handler might use `mime_helpers` to validate content type, use the `embeds` system to process the content, and then store the result in the `InMemoryCache` to optimize future requests.
|
|
1814
|
-
|
|
1815
|
-
## Files and Subdirectories Overview
|
|
1816
|
-
- **Direct files:**
|
|
1817
|
-
- `__init__.py`: Exposes key utility functions from the package for convenient access.
|
|
1818
|
-
- `asyncio_macos_fix.py`: Automatically applies a patch to fix asyncio subprocess issues on macOS.
|
|
1819
|
-
- `in_memory_cache.py`: Implements a thread-safe, singleton in-memory cache with TTL support.
|
|
1820
|
-
- `log_formatters.py`: Provides custom logging formatters, such as a Datadog-compatible JSON formatter.
|
|
1821
|
-
- `mime_helpers.py`: Contains helper functions to classify and identify text-based MIME types.
|
|
1822
|
-
- `push_notification_auth.py`: Implements JWT-based authentication for sending and receiving push notifications.
|
|
1823
|
-
|
|
1824
|
-
- **Subdirectories:**
|
|
1825
|
-
- `embeds/`: Provides a comprehensive system for processing embedded dynamic expressions (e.g., math, datetimes, artifact content).
|
|
1826
|
-
|
|
1827
|
-
## Developer API Reference
|
|
1828
|
-
|
|
1829
|
-
### Direct Files
|
|
1830
|
-
|
|
1831
|
-
#### __init__.py
|
|
1832
|
-
**Purpose:** Serves as the main entry point for the `utils` package, exporting the most common utility functions for easy importing.
|
|
1833
|
-
**Import:** `from solace_ai_connector.common.utils import is_text_based_mime_type`
|
|
1834
|
-
|
|
1835
|
-
**Classes/Functions/Constants:**
|
|
1836
|
-
* `is_text_based_mime_type(mime_type: Optional[str]) -> bool`: Checks if a given MIME type is considered text-based.
|
|
1837
|
-
|
|
1838
|
-
#### asyncio_macos_fix.py
|
|
1839
|
-
**Purpose:** Provides a targeted, automatic fix for a `NotImplementedError` that occurs when creating subprocesses with asyncio on macOS. This module is imported for its side effects and should be loaded early in the application's lifecycle.
|
|
1840
|
-
**Import:** `from solace_ai_connector.common.utils import asyncio_macos_fix` (Importing the module is sufficient to apply the patch).
|
|
1841
|
-
|
|
1842
|
-
**Classes/Functions/Constants:**
|
|
1843
|
-
* `ensure_asyncio_compatibility() -> bool`: The core function that applies the patch. It is called automatically when the module is first imported.
|
|
1844
|
-
|
|
1845
|
-
#### in_memory_cache.py
|
|
1846
|
-
**Purpose:** Provides a simple, thread-safe, in-memory cache implemented as a singleton. It's useful for storing frequently accessed data with an optional time-to-live (TTL).
|
|
1847
|
-
**Import:** `from solace_ai_connector.common.utils.in_memory_cache import InMemoryCache`
|
|
1848
|
-
|
|
1849
|
-
**Classes/Functions/Constants:**
|
|
1850
|
-
* **`InMemoryCache`**: A singleton class for caching.
|
|
1851
|
-
* `set(self, key: str, value: Any, ttl: Optional[int] = None) -> None`: Sets a key-value pair with an optional TTL in seconds.
|
|
1852
|
-
* `get(self, key: str, default: Any = None) -> Any`: Retrieves a value by its key, returning a default if the key is not found or has expired.
|
|
1853
|
-
* `delete(self, key: str) -> bool`: Deletes a key-value pair from the cache.
|
|
1854
|
-
* `clear(self) -> bool`: Removes all items from the cache.
|
|
1855
|
-
|
|
1856
|
-
#### log_formatters.py
|
|
1857
|
-
**Purpose:** Contains custom logging formatters to structure log output for specific platforms, such as Datadog.
|
|
1858
|
-
**Import:** `from solace_ai_connector.common.utils.log_formatters import DatadogJsonFormatter`
|
|
1859
|
-
|
|
1860
|
-
**Classes/Functions/Constants:**
|
|
1861
|
-
* **`DatadogJsonFormatter(logging.Formatter)`**: A formatter that outputs log records as a JSON string, compatible with Datadog's standard log attributes. It automatically includes tracing information (`dd.trace_id`, `dd.span_id`) if available.
|
|
1862
|
-
|
|
1863
|
-
#### mime_helpers.py
|
|
1864
|
-
**Purpose:** Provides utilities for handling and classifying MIME types, with a focus on identifying which types represent text-based content.
|
|
1865
|
-
**Import:** `from solace_ai_connector.common.utils.mime_helpers import is_text_based_mime_type, TEXT_CONTAINER_MIME_TYPES`
|
|
1866
|
-
|
|
1867
|
-
**Classes/Functions/Constants:**
|
|
1868
|
-
* `is_text_based_mime_type(mime_type: Optional[str]) -> bool`: Returns `True` if the MIME type starts with `text/` or is in the list of known text-based application types (like `application/json`).
|
|
1869
|
-
* `TEXT_CONTAINER_MIME_TYPES: Set[str]`: A set of non-`text/*` MIME types that are considered to contain text (e.g., `application/json`, `application/yaml`).
|
|
1870
|
-
|
|
1871
|
-
#### push_notification_auth.py
|
|
1872
|
-
**Purpose:**
|
|
1873
|
-
|
|
1874
|
-
================================================================================
|
|
1875
|
-
|
|
1876
|
-
## Section 17: core_a2a/core_a2a_llm.txt
|
|
1877
|
-
|
|
1878
|
-
**Source file:** `core_a2a/core_a2a_llm.txt`
|
|
1879
|
-
|
|
1880
|
-
# DEVELOPER GUIDE: core_a2a
|
|
1881
|
-
|
|
1882
|
-
## Quick Summary
|
|
1883
|
-
The `core_a2a` directory provides a reusable service layer for core Agent-to-Agent (A2A) interactions. It handles task submission (both regular and streaming), task cancellation, and agent discovery processing while being decoupled from specific gateway implementations and SAC messaging details.
|
|
1884
|
-
|
|
1885
|
-
## Files Overview
|
|
1886
|
-
- `__init__.py` - Package initialization file for the core A2A service layer
|
|
1887
|
-
- `service.py` - Main service class that encapsulates A2A protocol logic and agent registry operations
|
|
1888
|
-
|
|
1889
|
-
## Developer API Reference
|
|
1890
|
-
|
|
1891
|
-
### __init__.py
|
|
1892
|
-
**Purpose:** Package initialization for the core A2A service layer
|
|
1893
|
-
**Import:** `import core_a2a`
|
|
1894
|
-
|
|
1895
|
-
No public classes, functions, or constants defined.
|
|
1896
|
-
|
|
1897
|
-
### service.py
|
|
1898
|
-
**Purpose:** Provides the main CoreA2AService class for handling A2A protocol operations
|
|
1899
|
-
**Import:** `from core_a2a.service import CoreA2AService`
|
|
1900
|
-
|
|
1901
|
-
**Classes:**
|
|
1902
|
-
- `CoreA2AService(agent_registry: AgentRegistry, namespace: str)` - Main service class for A2A operations
|
|
1903
|
-
- `submit_task(agent_name: str, a2a_message: A2AMessage, session_id: str, client_id: str, reply_to_topic: str, user_id: str = "default_user", a2a_user_scopes: Optional[List[str]] = None, metadata_override: Optional[Dict[str, Any]] = None) -> Tuple[str, Dict, Dict]` - Constructs topic, payload, and user properties for non-streaming task requests
|
|
1904
|
-
- `submit_streaming_task(agent_name: str, a2a_message: A2AMessage, session_id: str, client_id: str, reply_to_topic: str, status_to_topic: str, user_id: str = "default_user", a2a_user_scopes: Optional[List[str]] = None, metadata_override: Optional[Dict[str, Any]] = None) -> Tuple[str, Dict, Dict]` - Constructs topic, payload, and user properties for streaming task requests
|
|
1905
|
-
- `cancel_task(agent_name: str, task_id: str, client_id: str, user_id: str = "default_user") -> Tuple[str, Dict, Dict]` - Constructs topic, payload, and user properties for task cancellation
|
|
1906
|
-
- `get_agent(agent_name: str) -> Optional[AgentCard]` - Retrieves a specific agent card by name from the registry
|
|
1907
|
-
- `get_all_agents() -> List[AgentCard]` - Retrieves all currently discovered agent cards from the registry
|
|
1908
|
-
- `process_discovery_message(agent_card: AgentCard)` - Processes an incoming agent card discovery message
|
|
1909
|
-
- `agent_registry: AgentRegistry` - The shared agent registry instance
|
|
1910
|
-
- `namespace: str` - The namespace string
|
|
1911
|
-
- `log_identifier: str` - Identifier used for logging
|
|
1912
|
-
|
|
1913
|
-
**Functions:**
|
|
1914
|
-
None (all functionality is encapsulated in the CoreA2AService class)
|
|
1915
|
-
|
|
1916
|
-
**Constants/Variables:**
|
|
1917
|
-
None
|
|
1918
|
-
|
|
1919
|
-
**Usage Examples:**
|
|
1920
|
-
```python
|
|
1921
|
-
# Import required dependencies
|
|
1922
|
-
from core_a2a.service import CoreA2AService
|
|
1923
|
-
from common.agent_registry import AgentRegistry
|
|
1924
|
-
from common.types import A2AMessage, AgentCard
|
|
1925
|
-
|
|
1926
|
-
# Initialize the service
|
|
1927
|
-
agent_registry = AgentRegistry()
|
|
1928
|
-
namespace = "my_NAMESPACE"
|
|
1929
|
-
service = CoreA2AService(agent_registry, namespace)
|
|
1930
|
-
|
|
1931
|
-
# Submit a regular task
|
|
1932
|
-
message = A2AMessage(parts=[{"type": "text", "content": "Hello"}])
|
|
1933
|
-
topic, payload, user_props = service.submit_task(
|
|
1934
|
-
agent_name="my_agent",
|
|
1935
|
-
a2a_message=message,
|
|
1936
|
-
session_id="session_123",
|
|
1937
|
-
client_id="client_456",
|
|
1938
|
-
reply_to_topic="responses/client_456",
|
|
1939
|
-
user_id="user_789"
|
|
1940
|
-
)
|
|
1941
|
-
|
|
1942
|
-
# Submit a streaming task
|
|
1943
|
-
topic, payload, user_props = service.submit_streaming_task(
|
|
1944
|
-
agent_name="my_agent",
|
|
1945
|
-
a2a_message=message,
|
|
1946
|
-
session_id="session_123",
|
|
1947
|
-
client_id="client_456",
|
|
1948
|
-
reply_to_topic="responses/client_456",
|
|
1949
|
-
status_to_topic="status/client_456",
|
|
1950
|
-
user_id="user_789"
|
|
1951
|
-
)
|
|
1952
|
-
|
|
1953
|
-
# Cancel a task
|
|
1954
|
-
topic, payload, user_props = service.cancel_task(
|
|
1955
|
-
agent_name="my_agent",
|
|
1956
|
-
task_id="task-abc123",
|
|
1957
|
-
client_id="client_456"
|
|
1958
|
-
)
|
|
1959
|
-
|
|
1960
|
-
# Get agent information
|
|
1961
|
-
agent = service.get_agent("my_agent")
|
|
1962
|
-
all_agents = service.get_all_agents()
|
|
1963
|
-
|
|
1964
|
-
# Process discovery message
|
|
1965
|
-
agent_card = AgentCard(name="new_agent", description="A new agent")
|
|
1966
|
-
service.process_discovery_message(agent_card)
|
|
1967
|
-
```
|
|
1968
|
-
|
|
1969
|
-
================================================================================
|
|
1970
|
-
|
|
1971
|
-
## Section 18: gateway/base/base_llm.txt
|
|
1972
|
-
|
|
1973
|
-
**Source file:** `gateway/base/base_llm.txt`
|
|
1974
|
-
|
|
1975
|
-
## Quick Summary
|
|
1976
|
-
The `base` directory provides the foundational, abstract classes for building Gateway implementations within the Solace AI Connector. It establishes a framework for handling common gateway tasks such as application configuration, Solace broker integration, A2A (Agent-to-Agent) message protocol handling, and managing the lifecycle of requests from external platforms. Developers should subclass `BaseGatewayApp` and `BaseGatewayComponent` to create a new gateway.
|
|
1977
|
-
|
|
1978
|
-
## Files Overview
|
|
1979
|
-
- `__init__.py`: Marks the directory as a Python package.
|
|
1980
|
-
- `app.py`: Contains the base application class (`BaseGatewayApp`) that handles configuration, schema merging, and broker setup.
|
|
1981
|
-
- `component.py`: Contains the core logic class (`BaseGatewayComponent`) for processing A2A messages and integrating with external platforms.
|
|
1982
|
-
- `task_context.py`: Provides a thread-safe manager for mapping A2A task IDs to their original request context.
|
|
1983
|
-
|
|
1984
|
-
## Developer API Reference
|
|
1985
|
-
|
|
1986
|
-
### __init__.py
|
|
1987
|
-
**Purpose:** Initializes the `gateway.base` Python package.
|
|
1988
|
-
**Import:** `from gateway.base import ...`
|
|
1989
|
-
|
|
1990
|
-
---
|
|
1991
|
-
|
|
1992
|
-
### app.py
|
|
1993
|
-
**Purpose:** Provides the base application class for gateway implementations. It automates configuration schema merging, Solace broker setup (including topic subscriptions and queue creation), and component instantiation.
|
|
1994
|
-
**Import:** `from gateway.base.app import BaseGatewayApp, BaseGatewayComponent`
|
|
1995
|
-
|
|
1996
|
-
**Classes:**
|
|
1997
|
-
- `BaseGatewayComponent(ComponentBase)` - A base class marker for gateway components. Subclasses of `BaseGatewayComponent` from `component.py` inherit from this.
|
|
1998
|
-
- `BaseGatewayApp(app_info: Dict[str, Any], **kwargs)` - The main application class to be subclassed for a new gateway.
|
|
1999
|
-
- `_get_gateway_component_class(self) -> Type[BaseGatewayComponent]` - **[Abstract Method]** Must be implemented by subclasses to return the specific gateway component class that will handle the core logic.
|
|
2000
|
-
- `namespace: str` - The absolute topic prefix for A2A communication (e.g., 'myorg/dev').
|
|
2001
|
-
- `gateway_id: str` - The unique ID for this gateway instance. Auto-generated if not provided.
|
|
2002
|
-
- `artifact_service_config: Dict` - Configuration for the shared ADK Artifact Service.
|
|
2003
|
-
- `enable_embed_resolution: bool` - Flag to enable or disable late-stage 'artifact_content' embed resolution.
|
|
2004
|
-
- `gateway_max_artifact_resolve_size_bytes: int` - Maximum size for resolving individual or recursively embedded artifacts.
|
|
2005
|
-
- `gateway_recursive_embed_depth: int` - Maximum depth for recursively resolving 'artifact_content' embeds.
|
|
2006
|
-
|
|
2007
|
-
**Constants/Variables:**
|
|
2008
|
-
- `BASE_GATEWAY_APP_SCHEMA: Dict[str, List[Dict[str, Any]]]` - The base configuration schema dictionary that is automatically merged with subclass-specific parameters.
|
|
2009
|
-
- `SPECIFIC_APP_SCHEMA_PARAMS_ATTRIBUTE_NAME: str` - The class attribute name (`"SPECIFIC_APP_SCHEMA_PARAMS"`) that subclasses should use to define their own configuration parameters.
|
|
2010
|
-
|
|
2011
|
-
**Usage Examples:**
|
|
2012
|
-
```python
|
|
2013
|
-
# In your custom gateway's app.py
|
|
2014
|
-
|
|
2015
|
-
from typing import Type, List, Dict, Any
|
|
2016
|
-
from gateway.base.app import BaseGatewayApp
|
|
2017
|
-
from .component import MyGatewayComponent # Your custom component
|
|
2018
|
-
|
|
2019
|
-
class MyGatewayApp(BaseGatewayApp):
|
|
2020
|
-
"""
|
|
2021
|
-
A custom gateway application for My Platform.
|
|
2022
|
-
"""
|
|
2023
|
-
# Define additional configuration parameters specific to this gateway
|
|
2024
|
-
SPECIFIC_APP_SCHEMA_PARAMS: List[Dict[str, Any]] = [
|
|
2025
|
-
{
|
|
2026
|
-
"name": "my_platform_api_key",
|
|
2027
|
-
"required": True,
|
|
2028
|
-
"type": "string",
|
|
2029
|
-
"description": "API key for connecting to My Platform."
|
|
2030
|
-
}
|
|
2031
|
-
]
|
|
2032
|
-
|
|
2033
|
-
def _get_gateway_component_class(self) -> Type[MyGatewayComponent]:
|
|
2034
|
-
"""
|
|
2035
|
-
Returns our custom component class.
|
|
2036
|
-
"""
|
|
2037
|
-
return MyGatewayComponent
|
|
2038
|
-
|
|
2039
|
-
# To run this app (typically via a YAML configuration file):
|
|
2040
|
-
# app_config = {
|
|
2041
|
-
# "name": "my-gateway-app",
|
|
2042
|
-
# "app_class": MyGatewayApp,
|
|
2043
|
-
# "app_config": {
|
|
2044
|
-
# "namespace": "myorg/prod",
|
|
2045
|
-
# "gateway_id": "my-gateway-instance-01",
|
|
2046
|
-
# "artifact_service": {
|
|
2047
|
-
# "type": "local_file",
|
|
2048
|
-
# "base_path": "/data/artifacts"
|
|
2049
|
-
# },
|
|
2050
|
-
# "my_platform_api_key": "secret-key-here"
|
|
2051
|
-
# }
|
|
2052
|
-
# }
|
|
2053
|
-
# app = MyGatewayApp(app_info=app_config)
|
|
2054
|
-
# app.run()
|
|
2055
|
-
```
|
|
2056
|
-
|
|
2057
|
-
---
|
|
2058
|
-
|
|
2059
|
-
### component.py
|
|
2060
|
-
**Purpose:** Provides the abstract base class for gateway components. This class contains the core logic for handling the A2A protocol, managing services (identity, artifacts), and defining the interface for interaction with an external platform (e.g., a web server, a chat application).
|
|
2061
|
-
**Import:** `from gateway.base.component import BaseGatewayComponent`
|
|
2062
|
-
|
|
2063
|
-
**Classes:**
|
|
2064
|
-
- `BaseGatewayComponent(**kwargs: Any)` - The abstract base class for gateway components. Developers must subclass this and implement the abstract methods.
|
|
2065
|
-
- **Public Methods:**
|
|
2066
|
-
- `publish_a2a_message(self, topic: str, payload: Dict, user_properties: Optional[Dict] = None) -> None` - Publishes a message to the Solace broker for A2A communication.
|
|
2067
|
-
- `authenticate_and_enrich_user(self, external_event_data: Any) -> Optional[Dict[str, Any]]` - Orchestrates the full user authentication and identity enrichment flow by calling `_extract_initial_claims` and the configured Identity Service.
|
|
2068
|
-
- `submit_a2a_task(self, target_agent_name: str, a2a_parts: List[A2APart], external_request_context: Dict[str, Any], user_identity: Any, is_streaming: bool = True, api_version: str = "v2") -> str` - Submits a task to a target agent, handling user configuration resolution, message creation, and context storage. Returns the generated `task_id`.
|
|
2069
|
-
- `run(self) -> None` - Starts the component's asynchronous operations, including the message processor loop and the external platform listener.
|
|
2070
|
-
- `cleanup(self) -> None` - Cleans up all resources, stops listeners, and shuts down background threads.
|
|
2071
|
-
- **Abstract Methods (Must be Implemented by Subclasses):**
|
|
2072
|
-
- `_extract_initial_claims(self, external_event_data: Any) -> Optional[Dict[str, Any]]` - Extracts primary identity claims (e.g., user ID) from a platform-specific event. Must return a dict with an 'id' key, or None if auth fails.
|
|
2073
|
-
- `_start_listener(self) -> None` - Starts the listener for the external platform (e.g., start a web server, connect to a WebSocket).
|
|
2074
|
-
- `_stop_listener(self) -> None` - Stops the listener for the external platform.
|
|
2075
|
-
- `_translate_external_input(self, external_event: Any) -> Tuple[str, List[A2APart], Dict[str, Any]]` - Translates an incoming event from the external platform into a format the A2A protocol understands: `(target_agent_name, list_of_a2a_parts, external_request_context)`.
|
|
2076
|
-
- `_send_update_to_external(self, external_request_context: Dict[str, Any], event_data: Union[TaskStatusUpdateEvent, TaskArtifactUpdateEvent], is_final_chunk_of_update: bool) -> None` - Sends a streaming update (e.g., a status message or an artifact) back to the external platform.
|
|
2077
|
-
- `_send_final_response_to_external(self, external_request_context: Dict[str, Any], task_data: Task) -> None` - Sends the final, complete response of a task back to the external platform.
|
|
2078
|
-
- `_send_error_to_external(self, external_request_context: Dict[str, Any], error_data: JSONRPCError) -> None` - Sends an error message back to the external platform.
|
|
2079
|
-
|
|
2080
|
-
**Usage Examples:**
|
|
2081
|
-
```python
|
|
2082
|
-
# In your custom gateway's component.py
|
|
2083
|
-
|
|
2084
|
-
from typing import Any, Dict, List, Optional, Tuple, Union
|
|
2085
|
-
from gateway.base.component import BaseGatewayComponent
|
|
2086
|
-
from ...common.types import (
|
|
2087
|
-
Part as A2APart, TextPart, Task, TaskStatusUpdateEvent,
|
|
2088
|
-
TaskArtifactUpdateEvent, JSONRPCError
|
|
2089
|
-
)
|
|
2090
|
-
|
|
2091
|
-
class MyGatewayComponent(BaseGatewayComponent):
|
|
2092
|
-
# This is a simplified example. A real implementation would
|
|
2093
|
-
#
|
|
2094
|
-
|
|
2095
|
-
================================================================================
|
|
2096
|
-
|
|
2097
|
-
## Section 19: gateway/gateway_llm.txt
|
|
2098
|
-
|
|
2099
|
-
**Source file:** `gateway/gateway_llm.txt`
|
|
2100
|
-
|
|
2101
|
-
Here is the comprehensive developer guide for the `gateway` directory.
|
|
2102
|
-
|
|
2103
|
-
## Quick Summary
|
|
2104
|
-
The `gateway` directory provides a comprehensive framework for building gateway implementations that bridge external platforms with the Solace AI Connector's A2A (Agent-to-Agent) messaging system. The architecture consists of a foundational base framework and three specialized gateway implementations: HTTP/SSE for web interfaces, Slack for team collaboration, and Webhook for external system integration. All gateways share common patterns for authentication, message translation, and real-time communication while providing platform-specific features.
|
|
2105
|
-
|
|
2106
|
-
## Files and Subdirectories Overview
|
|
2107
|
-
- **Direct files:**
|
|
2108
|
-
- `__init__.py`: Marks the directory as a Python package.
|
|
2109
|
-
- **Subdirectories:**
|
|
2110
|
-
- `base/`: Foundational classes and utilities for building all gateway implementations.
|
|
2111
|
-
- `http_sse/`: A complete HTTP/SSE gateway with a FastAPI web server for real-time web UI backends.
|
|
2112
|
-
- `slack/`: A gateway for integrating with the Slack collaboration platform.
|
|
2113
|
-
- `webhook/`: A universal webhook gateway for receiving HTTP requests from external systems.
|
|
2114
|
-
|
|
2115
|
-
## Developer API Reference
|
|
2116
|
-
|
|
2117
|
-
### Direct Files
|
|
2118
|
-
|
|
2119
|
-
#### __init__.py
|
|
2120
|
-
**Purpose:** Initializes the `gateway` module, making it a Python package.
|
|
2121
|
-
**Import:** `from gateway import ...`
|
|
2122
|
-
|
|
2123
|
-
**Classes/Functions/Constants:**
|
|
2124
|
-
This file is empty and contains no direct exports.
|
|
2125
|
-
|
|
2126
|
-
### Subdirectory APIs
|
|
2127
|
-
|
|
2128
|
-
#### base/
|
|
2129
|
-
**Purpose:** Provides the foundational, abstract classes for building all Gateway implementations. It establishes a framework for configuration, A2A message handling, and managing the lifecycle of requests from external platforms.
|
|
2130
|
-
**Key Exports:** `BaseGatewayApp`, `BaseGatewayComponent`, `TaskContextManager`
|
|
2131
|
-
**Import Examples:**
|
|
2132
|
-
```python
|
|
2133
|
-
from gateway.base.app import BaseGatewayApp
|
|
2134
|
-
from gateway.base.component import BaseGatewayComponent
|
|
2135
|
-
from gateway.base.task_context import TaskContextManager
|
|
2136
|
-
```
|
|
2137
|
-
|
|
2138
|
-
**Key Modules:**
|
|
2139
|
-
|
|
2140
|
-
* **`app.py`**:
|
|
2141
|
-
* **`BaseGatewayApp`**: The main application class to be subclassed for a new gateway. It automates configuration schema merging, Solace broker setup, and component instantiation.
|
|
2142
|
-
* `_get_gateway_component_class(self)`: **[Abstract Method]** Subclasses must implement this to return their specific gateway component class.
|
|
2143
|
-
|
|
2144
|
-
* **`component.py`**:
|
|
2145
|
-
* **`BaseGatewayComponent`**: The abstract base class for gateway logic. Subclasses implement the abstract methods to define how the gateway interacts with its specific external platform.
|
|
2146
|
-
* **Public Methods**:
|
|
2147
|
-
* `submit_a2a_task(...)`: The primary method for submitting a task to an agent on behalf of an external user.
|
|
2148
|
-
* `publish_a2a_message(...)`: A lower-level method to publish any message to the A2A message bus.
|
|
2149
|
-
* **Abstract Methods to Implement**:
|
|
2150
|
-
* `_extract_initial_claims(self, external_event_data)`: Extracts user identity from a platform-specific event.
|
|
2151
|
-
* `_start_listener(self)` / `_stop_listener(self)`: Manages the lifecycle of the external platform listener (e.g., a web server).
|
|
2152
|
-
* `_translate_external_input(self, external_event)`: Translates an incoming event from the external platform into the A2A protocol format.
|
|
2153
|
-
* `_send_update_to_external(...)`: Sends a streaming update back to the external platform.
|
|
2154
|
-
* `_send_final_response_to_external(...)`: Sends the final task result back to the external platform.
|
|
2155
|
-
* `_send_error_to_external(...)`: Sends an error message back to the external platform.
|
|
2156
|
-
|
|
2157
|
-
* **`task_context.py`**:
|
|
2158
|
-
* **`TaskContextManager`**: A thread-safe dictionary-like class for mapping A2A task IDs to the original request context from the external platform. This is crucial for routing responses back to the correct user/channel/thread.
|
|
2159
|
-
|
|
2160
|
-
#### http_sse/
|
|
2161
|
-
**Purpose:** Implements a complete HTTP/SSE gateway to serve a web-based user interface, bridging web protocols with the backend A2A messaging fabric.
|
|
2162
|
-
**Key Exports:** `WebUIBackendApp`, `WebUIBackendComponent`, `SSEManager`, `SessionManager`, and various dependency injectors.
|
|
2163
|
-
**Import Examples:**
|
|
2164
|
-
```python
|
|
2165
|
-
from gateway.http_sse.app import WebUIBackendApp
|
|
2166
|
-
from gateway.http_sse.component import WebUIBackendComponent
|
|
2167
|
-
from gateway.http_sse.sse_manager import SSEManager
|
|
2168
|
-
from gateway.http_sse.session_manager import SessionManager
|
|
2169
|
-
from gateway.http_sse.dependencies import get_agent_service, get_task_service, get_user_id
|
|
2170
|
-
```
|
|
2171
|
-
|
|
2172
|
-
**Key Modules & Exports:**
|
|
2173
|
-
|
|
2174
|
-
* **`app.py`**:
|
|
2175
|
-
* **`WebUIBackendApp`**: The main SAC App class that defines the configuration schema and launches the `WebUIBackendComponent`.
|
|
2176
|
-
* **`component.py`**:
|
|
2177
|
-
* **`WebUIBackendComponent`**: The core component that hosts the FastAPI server, manages shared state, and implements the A2A translation logic for HTTP requests.
|
|
2178
|
-
* **`session_manager.py`**:
|
|
2179
|
-
* **`SessionManager`**: Manages web user sessions, creating and tracking unique A2A client and session IDs from HTTP requests.
|
|
2180
|
-
* **`sse_manager.py`**:
|
|
2181
|
-
* **`SSEManager`**: Manages Server-Sent Event (SSE) connections, allowing for real-time, streaming updates to be pushed from the server to connected web clients.
|
|
2182
|
-
* **`dependencies.py`**:
|
|
2183
|
-
* Provides FastAPI dependency injectors for giving API routers safe access to shared resources (e.g., `get_agent_service`, `get_task_service`, `get_sac_component`).
|
|
2184
|
-
* **`services/`**:
|
|
2185
|
-
* **`AgentService`**, **`TaskService`**: Contain the business logic for interacting with agents and managing tasks, respectively. These are accessed via the dependency injectors.
|
|
2186
|
-
|
|
2187
|
-
#### slack/
|
|
2188
|
-
**Purpose:** Provides a gateway for integrating the Solace AI Connector with the Slack collaboration platform, enabling bot interactions within Slack channels and threads.
|
|
2189
|
-
**Key Exports:** `SlackGatewayApp`, `SlackGatewayComponent`, and various utility functions.
|
|
2190
|
-
**Import Examples:**
|
|
2191
|
-
```python
|
|
2192
|
-
from gateway.slack.app import SlackGatewayApp
|
|
2193
|
-
from gateway.slack.component import SlackGatewayComponent
|
|
2194
|
-
from gateway.slack.utils import generate_a2a_session_id, send_slack_message, correct_slack_markdown
|
|
2195
|
-
```
|
|
2196
|
-
|
|
2197
|
-
#### webhook/
|
|
2198
|
-
**Purpose:** Provides a universal webhook gateway for receiving HTTP requests from external systems and triggering A2A tasks. It is highly configurable for different authentication methods, payload formats, and target agents.
|
|
2199
|
-
**Key Exports:** `WebhookGatewayApp`, `WebhookGatewayComponent`
|
|
2200
|
-
**Import Examples:**
|
|
2201
|
-
```python
|
|
2202
|
-
from gateway.webhook.app import WebhookGatewayApp
|
|
2203
|
-
from gateway.webhook.component import WebhookGatewayComponent
|
|
2204
|
-
from gateway.webhook.dependencies import get_sac_component
|
|
2205
|
-
```
|
|
2206
|
-
|
|
2207
|
-
## Complete Usage Guide
|
|
2208
|
-
This guide provides practical examples of how to use the components and frameworks within the `gateway` directory.
|
|
2209
|
-
|
|
2210
|
-
### 1. How to Create a Custom Gateway
|
|
2211
|
-
This example shows how to use the `base` module to build a new gateway for a hypothetical external platform.
|
|
2212
|
-
|
|
2213
|
-
```python
|
|
2214
|
-
# my_gateway/app.py
|
|
2215
|
-
from gateway.base.app import BaseGatewayApp
|
|
2216
|
-
from .component import MyGatewayComponent
|
|
2217
|
-
|
|
2218
|
-
class MyGatewayApp(BaseGatewayApp):
|
|
2219
|
-
"""Defines the application and its configuration for My Platform."""
|
|
2220
|
-
SPECIFIC_APP_SCHEMA_PARAMS = [
|
|
2221
|
-
{
|
|
2222
|
-
"name": "my_platform_api_key",
|
|
2223
|
-
"required": True,
|
|
2224
|
-
"type": "string",
|
|
2225
|
-
"
|
|
2226
|
-
|
|
2227
|
-
================================================================================
|
|
2228
|
-
|
|
2229
|
-
## Section 20: gateway/http_sse/components/components_llm.txt
|
|
2230
|
-
|
|
2231
|
-
**Source file:** `gateway/http_sse/components/components_llm.txt`
|
|
2232
|
-
|
|
2233
|
-
## Quick Summary
|
|
2234
|
-
This directory contains components for the HTTP SSE (Server-Sent Events) gateway, designed to work within the Solace AI Connector (SAC) framework. The primary component forwards messages received from the Solace broker to an internal queue, enabling real-time visualization in a web-based user interface.
|
|
2235
|
-
|
|
2236
|
-
## Files Overview
|
|
2237
|
-
- `__init__.py`: Makes the `VisualizationForwarderComponent` class directly importable from the `components` package.
|
|
2238
|
-
- `visualization_forwarder_component.py`: Defines a component that forwards messages from a broker input to a Python `queue.Queue` for visualization.
|
|
2239
|
-
|
|
2240
|
-
## Developer API Reference
|
|
2241
|
-
|
|
2242
|
-
### __init__.py
|
|
2243
|
-
**Purpose:** Exposes the public components of this directory for easy importing.
|
|
2244
|
-
**Import:** `from gateway.http_sse.components import VisualizationForwarderComponent`
|
|
2245
|
-
|
|
2246
|
-
**Exports:**
|
|
2247
|
-
- `VisualizationForwarderComponent`: The main component class for forwarding messages to a visualization queue.
|
|
2248
|
-
|
|
2249
|
-
---
|
|
2250
|
-
|
|
2251
|
-
### visualization_forwarder_component.py
|
|
2252
|
-
**Purpose:** A Solace AI Connector (SAC) component that listens for messages from a `BrokerInput` and forwards them to a specified Python `queue.Queue`. This is primarily used to send data to the Web UI for real-time display.
|
|
2253
|
-
**Import:** `from gateway.http_sse.components.visualization_forwarder_component import VisualizationForwarderComponent`
|
|
2254
|
-
|
|
2255
|
-
**Classes:**
|
|
2256
|
-
- `VisualizationForwarderComponent(**kwargs: Any)` - A component that forwards messages to a target queue. It is initialized with configuration parameters, most importantly `target_queue_ref`.
|
|
2257
|
-
- `invoke(self, message: SolaceMessage, data: Dict[str, Any]) -> None` - The core method called by the SAC framework for each incoming message. It formats the data and places it onto the target queue. This method should not be called directly by developers; the framework handles its execution.
|
|
2258
|
-
|
|
2259
|
-
**Constants/Variables:**
|
|
2260
|
-
- `info: Dict` - A metadata dictionary required by the SAC framework. It describes the component's configuration parameters, input schema, and purpose. This is for framework use and not for direct interaction.
|
|
2261
|
-
|
|
2262
|
-
**Usage Examples:**
|
|
2263
|
-
```python
|
|
2264
|
-
import queue
|
|
2265
|
-
from gateway.http_sse.components import VisualizationForwarderComponent
|
|
2266
|
-
from solace_ai_connector.common.message import Message as SolaceMessage
|
|
2267
|
-
|
|
2268
|
-
# 1. Create a target queue that will receive the forwarded messages.
|
|
2269
|
-
# This queue is typically managed by another component, like a Web UI backend.
|
|
2270
|
-
visualization_queue = queue.Queue()
|
|
2271
|
-
|
|
2272
|
-
# 2. Instantiate the component, providing a reference to the target queue.
|
|
2273
|
-
# This is usually done within a SAC flow configuration file.
|
|
2274
|
-
forwarder = VisualizationForwarderComponent(
|
|
2275
|
-
name="my_forwarder",
|
|
2276
|
-
target_queue_ref=visualization_queue
|
|
2277
|
-
)
|
|
2278
|
-
|
|
2279
|
-
# 3. The `invoke` method is called automatically by the SAC framework when a message
|
|
2280
|
-
# arrives from a connected BrokerInput component.
|
|
2281
|
-
|
|
2282
|
-
# Example of what the consuming component would get from the queue:
|
|
2283
|
-
# A dictionary containing the message topic, payload, and other details.
|
|
2284
|
-
#
|
|
2285
|
-
# if not visualization_queue.empty():
|
|
2286
|
-
# forwarded_data = visualization_queue.get()
|
|
2287
|
-
# print(f"Received topic: {forwarded_data['topic']}")
|
|
2288
|
-
# print(f"Received payload: {forwarded_data['payload']}")
|
|
2289
|
-
#
|
|
2290
|
-
# Expected structure of `forwarded_data`:
|
|
2291
|
-
# {
|
|
2292
|
-
# "topic": "some/broker/topic",
|
|
2293
|
-
# "payload": {"key": "value"},
|
|
2294
|
-
# "user_properties": {"prop1": "value1"},
|
|
2295
|
-
# "_original_broker_message": <SolaceMessage object>
|
|
2296
|
-
# }
|
|
2297
|
-
```
|
|
2298
|
-
|
|
2299
|
-
================================================================================
|
|
2300
|
-
|
|
2301
|
-
## Section 21: gateway/http_sse/http_sse_llm.txt
|
|
2302
|
-
|
|
2303
|
-
**Source file:** `gateway/http_sse/http_sse_llm.txt`
|
|
2304
|
-
|
|
2305
|
-
Here is the comprehensive developer guide for the `http_sse` directory.
|
|
2306
|
-
|
|
2307
|
-
## Quick Summary
|
|
2308
|
-
The `http_sse` directory implements a complete HTTP/SSE (Server-Sent Events) gateway for the A2A (Agent-to-Agent) system. Its primary purpose is to serve a web-based user interface and act as a bridge between standard web protocols (HTTP, WebSockets/SSE) and the backend A2A messaging fabric.
|
|
2309
|
-
|
|
2310
|
-
The architecture is centered around the `WebUIBackendComponent`, a custom Solace AI Connector (SAC) component that hosts an embedded FastAPI web server. This component manages shared state and resources, such as the `SSEManager` for real-time updates, the `SessionManager` for user sessions, and the `AgentRegistry` for discovering available agents.
|
|
2311
|
-
|
|
2312
|
-
Subdirectories organize the functionality:
|
|
2313
|
-
- `routers/` defines the REST API endpoints (e.g., `/tasks`, `/agents`).
|
|
2314
|
-
- `services/` contains the business logic that the API endpoints call.
|
|
2315
|
-
- `dependencies.py` uses FastAPI's dependency injection system to provide the routers and services with safe access to the shared resources managed by the main component.
|
|
2316
|
-
- `components/` contains specialized SAC components, for example, to forward A2A messages for real-time visualization.
|
|
2317
|
-
|
|
2318
|
-
This design creates a clean separation of concerns, where the web layer (FastAPI) is decoupled from the core messaging and state management layer (SAC Component).
|
|
2319
|
-
|
|
2320
|
-
## Files and Subdirectories Overview
|
|
2321
|
-
- **Direct files:**
|
|
2322
|
-
- `__init__.py`: Standard Python package initializer.
|
|
2323
|
-
- `app.py`: Defines the main SAC `WebUIBackendApp`, which specifies configuration and launches the component.
|
|
2324
|
-
- `component.py`: The core SAC component that hosts the FastAPI server and manages all shared resources and A2A logic.
|
|
2325
|
-
- `dependencies.py`: Provides FastAPI dependency injectors for accessing shared resources like services and managers.
|
|
2326
|
-
- `main.py`: The main FastAPI application instance, including middleware, router mounting, and exception handling.
|
|
2327
|
-
- `session_manager.py`: Manages web user sessions and maps them to unique A2A client and session IDs.
|
|
2328
|
-
- `sse_manager.py`: Manages Server-Sent Event (SSE) connections for streaming real-time updates to clients.
|
|
2329
|
-
- **Subdirectories:**
|
|
2330
|
-
- `components/`: Contains specialized SAC components, such as for forwarding messages to the visualization system.
|
|
2331
|
-
- `routers/`: Defines the FastAPI `APIRouter` modules for all REST API endpoints.
|
|
2332
|
-
- `services/`: Encapsulates business logic for agents, tasks, and other domain-specific operations.
|
|
2333
|
-
|
|
2334
|
-
## Developer API Reference
|
|
2335
|
-
|
|
2336
|
-
### Direct Files
|
|
2337
|
-
|
|
2338
|
-
#### app.py
|
|
2339
|
-
**Purpose:** This file defines the `WebUIBackendApp`, a custom SAC (Solace AI Connector) App class. It is responsible for defining the configuration schema for the entire HTTP/SSE gateway and programmatically creating the `WebUIBackendComponent`.
|
|
2340
|
-
**Import:** `from gateway.http_sse.app import WebUIBackendApp`
|
|
2341
|
-
|
|
2342
|
-
**Classes/Functions/Constants:**
|
|
2343
|
-
- **`WebUIBackendApp(BaseGatewayApp)`**: The main application class. It extends `BaseGatewayApp` and adds a list of WebUI-specific configuration parameters to the application schema.
|
|
2344
|
-
- **`SPECIFIC_APP_SCHEMA_PARAMS: List[Dict[str, Any]]`**: A constant list defining the configuration parameters specific to the HTTP/SSE gateway, such as `session_secret_key`, `fastapi_host`, `fastapi_port`, and various frontend-related settings.
|
|
2345
|
-
|
|
2346
|
-
#### component.py
|
|
2347
|
-
**Purpose:** This is the core component of the gateway. It hosts the FastAPI server, manages all shared state (like the SSE and Session managers), handles the lifecycle of the web server, and implements the logic for translating between external HTTP requests and internal A2A messages.
|
|
2348
|
-
**Import:** `from gateway.http_sse.component import WebUIBackendComponent`
|
|
2349
|
-
|
|
2350
|
-
**Classes/Functions/Constants:**
|
|
2351
|
-
- **`WebUIBackendComponent(BaseGatewayComponent)`**: The main component class. Developers will primarily interact with its instances via the dependency injection system.
|
|
2352
|
-
- **Public Accessor Methods (for Dependencies):**
|
|
2353
|
-
- `get_sse_manager() -> SSEManager`: Returns the shared `SSEManager` instance.
|
|
2354
|
-
- `get_session_manager() -> SessionManager`: Returns the shared `SessionManager` instance.
|
|
2355
|
-
- `get_agent_registry() -> AgentRegistry`: Returns the shared `AgentRegistry` instance.
|
|
2356
|
-
- `get_core_a2a_service() -> CoreA2AService`: Returns the core service for creating A2A messages.
|
|
2357
|
-
- `get_shared_artifact_service() -> Optional[BaseArtifactService]`: Returns the service for artifact storage.
|
|
2358
|
-
- `get_namespace() -> str`: Returns the configured namespace.
|
|
2359
|
-
- `get_gateway_id() -> str`: Returns the unique ID of this gateway.
|
|
2360
|
-
- **Core Logic Methods:**
|
|
2361
|
-
- `publish_a2a(topic: str, payload: Dict, user_properties: Optional[Dict] = None)`: Publishes a message onto the A2A messaging fabric. This is the primary method for sending data to agents.
|
|
2362
|
-
- **Gateway-Development-Kit (GDK) Hooks:** These methods implement the `BaseGatewayComponent` abstract interface.
|
|
2363
|
-
- `_start_listener()`: Starts the FastAPI/Uvicorn server.
|
|
2364
|
-
- `_stop_listener()`: Stops the FastAPI/Uvicorn server.
|
|
2365
|
-
- `_translate_external_input(...)`: Translates an incoming HTTP request (e.g., form data with files) into a structured A2A message (`List[A2APart]`).
|
|
2366
|
-
- `_send_update_to_external(...)`: Sends an intermediate status update from an agent back to the client via SSE.
|
|
2367
|
-
-
|
|
2368
|
-
|
|
2369
|
-
================================================================================
|
|
2370
|
-
|
|
2371
|
-
## Section 22: gateway/http_sse/routers/routers_llm.txt
|
|
2372
|
-
|
|
2373
|
-
**Source file:** `gateway/http_sse/routers/routers_llm.txt`
|
|
2374
|
-
|
|
2375
|
-
Here is the DEVELOPER GUIDE for the `routers` directory.
|
|
2376
|
-
|
|
2377
|
-
## Quick Summary
|
|
2378
|
-
The `routers` directory contains FastAPI `APIRouter` modules that define the REST API endpoints for the HTTP SSE Gateway. Each file groups endpoints by a specific domain of functionality, such as agent discovery, artifact management, user authentication, task submission, and real-time event streaming. These routers are the primary interface for frontend applications and other clients to interact with the gateway.
|
|
2379
|
-
|
|
2380
|
-
## Files Overview
|
|
2381
|
-
- `__init__.py`: Marks the directory as a Python package.
|
|
2382
|
-
- `agents.py`: API endpoints for discovering available A2A agents.
|
|
2383
|
-
- `artifacts.py`: REST endpoints for managing session-specific artifacts (upload, download, list, delete).
|
|
2384
|
-
- `auth.py`: Endpoints for handling the user authentication flow (login, callback, refresh, CSRF).
|
|
2385
|
-
- `config.py`: API endpoint for providing configuration settings to the frontend application.
|
|
2386
|
-
- `people.py`: API endpoints for user search functionality, typically for autocomplete features.
|
|
2387
|
-
- `sessions.py`: API endpoints for managing user sessions (creating new sessions, getting current session info).
|
|
2388
|
-
- `sse.py`: The Server-Sent Events (SSE) endpoint for streaming real-time task updates to the client.
|
|
2389
|
-
- `tasks.py`: API endpoints for submitting tasks to agents and managing their lifecycle (e.g., cancellation).
|
|
2390
|
-
- `users.py`: API endpoint for retrieving information about the currently authenticated user.
|
|
2391
|
-
- `visualization.py`: API endpoints for managing A2A message visualization streams for monitoring and debugging.
|
|
2392
|
-
|
|
2393
|
-
## Developer API Reference
|
|
2394
|
-
|
|
2395
|
-
### agents.py
|
|
2396
|
-
**Purpose:** Provides REST endpoints for agent discovery.
|
|
2397
|
-
**Import:** `from src.solace_agent_mesh.gateway.http_sse.routers.agents import router`
|
|
2398
|
-
|
|
2399
|
-
**Functions:**
|
|
2400
|
-
- `get_discovered_agents() -> List[AgentCard]`: Retrieves a list of all currently discovered and available A2A agents. The `AgentCard` type contains details about each agent.
|
|
2401
|
-
|
|
2402
|
-
**Usage Examples:**
|
|
2403
|
-
```python
|
|
2404
|
-
# To include this router in a FastAPI application
|
|
2405
|
-
from fastapi import FastAPI
|
|
2406
|
-
from src.solace_agent_mesh.gateway.http_sse.routers.agents import router
|
|
2407
|
-
|
|
2408
|
-
app = FastAPI()
|
|
2409
|
-
app.include_router(router, prefix="/api/v1")
|
|
2410
|
-
|
|
2411
|
-
# A client would make a GET request to /api/v1/agents
|
|
2412
|
-
|
|
2413
|
-
================================================================================
|
|
2414
|
-
|
|
2415
|
-
## Section 23: gateway/http_sse/services/services_llm.txt
|
|
2416
|
-
|
|
2417
|
-
**Source file:** `gateway/http_sse/services/services_llm.txt`
|
|
2418
|
-
|
|
2419
|
-
Here is the developer guide for the `services` directory.
|
|
2420
|
-
|
|
2421
|
-
## Quick Summary
|
|
2422
|
-
The `services` directory contains the business logic layer for the HTTP SSE Gateway. It encapsulates core functionalities by providing high-level services for agent management, user identity searches, and A2A (Agent-to-Agent) task operations. These services abstract the complexities of interacting with the agent registry, external identity providers, and the underlying A2A messaging protocol.
|
|
2423
|
-
|
|
2424
|
-
## Files Overview
|
|
2425
|
-
- `__init__.py` - Marks the directory as a Python package.
|
|
2426
|
-
- `agent_service.py` - Service for retrieving information about discovered A2A agents.
|
|
2427
|
-
- `people_service.py` - Service for searching for users via a configured identity service.
|
|
2428
|
-
- `task_service.py` - Service for handling the cancellation of tasks with A2A agents.
|
|
2429
|
-
|
|
2430
|
-
## Developer API Reference
|
|
2431
|
-
|
|
2432
|
-
### __init__.py
|
|
2433
|
-
**Purpose:** This file marks the `services` directory as a Python package, allowing its modules to be imported.
|
|
2434
|
-
**Import:** N/A - No public interfaces.
|
|
2435
|
-
|
|
2436
|
-
---
|
|
2437
|
-
|
|
2438
|
-
### agent_service.py
|
|
2439
|
-
**Purpose:** Provides high-level methods for accessing information about discovered A2A agents from the shared `AgentRegistry`.
|
|
2440
|
-
**Import:** `from src.solace_agent_mesh.gateway.http_sse.services.agent_service import AgentService`
|
|
2441
|
-
|
|
2442
|
-
**Classes:**
|
|
2443
|
-
- `AgentService(agent_registry: AgentRegistry)` - A service that provides methods for accessing information about discovered A2A agents.
|
|
2444
|
-
- `get_all_agents() -> List[AgentCard]` - Retrieves all currently discovered and registered agent cards from the registry.
|
|
2445
|
-
- `get_agent_by_name(agent_name: str) -> Optional[AgentCard]` - Retrieves a specific agent card by its unique name. Returns `None` if the agent is not found.
|
|
2446
|
-
|
|
2447
|
-
**Usage Examples:**
|
|
2448
|
-
```python
|
|
2449
|
-
from typing import List, Optional
|
|
2450
|
-
from src.solace_agent_mesh.gateway.http_sse.services.agent_service import AgentService
|
|
2451
|
-
from src.solace_agent_mesh.common.agent_registry import AgentRegistry
|
|
2452
|
-
from src.solace_agent_mesh.common.types import AgentCard
|
|
2453
|
-
|
|
2454
|
-
# In a real application, AgentRegistry would be a shared instance.
|
|
2455
|
-
# For this example, we'll create a new one and populate it.
|
|
2456
|
-
agent_registry = AgentRegistry()
|
|
2457
|
-
my_agent_card = AgentCard(name="data-analyzer", description="Analyzes data files.")
|
|
2458
|
-
agent_registry.register_agent(my_agent_card)
|
|
2459
|
-
|
|
2460
|
-
# 1. Initialize the service with the agent registry
|
|
2461
|
-
agent_service = AgentService(agent_registry=agent_registry)
|
|
2462
|
-
|
|
2463
|
-
# 2. Get all available agents
|
|
2464
|
-
all_agents = agent_service.get_all_agents()
|
|
2465
|
-
print(f"Found {len(all_agents)} agent(s).")
|
|
2466
|
-
for agent in all_agents:
|
|
2467
|
-
print(f"- Agent: {agent.name}, Description: {agent.description}")
|
|
2468
|
-
|
|
2469
|
-
# 3. Get a specific agent by name
|
|
2470
|
-
found_agent = agent_service.get_agent_by_name("data-analyzer")
|
|
2471
|
-
if found_agent:
|
|
2472
|
-
print(f"\nSuccessfully retrieved agent: {found_agent.name}")
|
|
2473
|
-
else:
|
|
2474
|
-
print("\nCould not find agent 'data-analyzer'.")
|
|
2475
|
-
|
|
2476
|
-
# 4. Try to get a non-existent agent
|
|
2477
|
-
missing_agent = agent_service.get_agent_by_name("non-existent-agent")
|
|
2478
|
-
print(f"Result for 'non-existent-agent': {missing_agent}")
|
|
2479
|
-
```
|
|
2480
|
-
|
|
2481
|
-
---
|
|
2482
|
-
|
|
2483
|
-
### people_service.py
|
|
2484
|
-
**Purpose:** Acts as a layer on top of a configured `IdentityService` to provide user search functionality. If no identity service is configured, it gracefully returns empty results.
|
|
2485
|
-
**Import:** `from src.solace_agent_mesh.gateway.http_sse.services.people_service import PeopleService`
|
|
2486
|
-
|
|
2487
|
-
**Classes:**
|
|
2488
|
-
- `PeopleService(identity_service: Optional[BaseIdentityService])` - A service for searching and retrieving user information.
|
|
2489
|
-
- `search_for_users(query: str, limit: int = 10) -> List[Dict[str, Any]]` - Asynchronously searches for users via the identity service. Returns an empty list if the query is too short, no identity service is configured, or an error occurs.
|
|
2490
|
-
|
|
2491
|
-
**Usage Examples:**
|
|
2492
|
-
```python
|
|
2493
|
-
import asyncio
|
|
2494
|
-
from typing import Any, Dict, List, Optional
|
|
2495
|
-
from src.solace_agent_mesh.gateway.http_sse.services.people_service import PeopleService
|
|
2496
|
-
from src.solace_agent_mesh.common.services.identity_service import BaseIdentityService
|
|
2497
|
-
|
|
2498
|
-
# Define a mock identity service for the example
|
|
2499
|
-
class MockIdentityService(BaseIdentityService):
|
|
2500
|
-
async def search_users(self, query: str, limit: int) -> List[Dict[str, Any]]:
|
|
2501
|
-
print(f"MockIdentityService: Searching for '{query}' with limit {limit}")
|
|
2502
|
-
all_users = [
|
|
2503
|
-
{"id": "jdoe", "name": "John Doe", "email": "j.doe@example.com"},
|
|
2504
|
-
{"id": "jsmith", "name": "Jane Smith", "email": "j.smith@example.com"},
|
|
2505
|
-
]
|
|
2506
|
-
return [user for user in all_users if query.lower() in user["name"].lower()][:limit]
|
|
2507
|
-
|
|
2508
|
-
async def main():
|
|
2509
|
-
# 1. Initialize with a configured identity service
|
|
2510
|
-
identity_service = MockIdentityService()
|
|
2511
|
-
people_service = PeopleService(identity_service=identity_service)
|
|
2512
|
-
|
|
2513
|
-
# 2. Search for users
|
|
2514
|
-
users = await people_service.search_for_users("john", limit=5)
|
|
2515
|
-
print(f"Found {len(users)} user(s): {users}")
|
|
2516
|
-
|
|
2517
|
-
# 3. Initialize without an identity service
|
|
2518
|
-
people_service_no_id = PeopleService(identity_service=None)
|
|
2519
|
-
|
|
2520
|
-
# 4. Search will return an empty list
|
|
2521
|
-
empty_results = await people_service_no_id.search_for_users("jane")
|
|
2522
|
-
print(f"Results with no identity service: {empty_results}")
|
|
2523
|
-
|
|
2524
|
-
if __name__ == "__main__":
|
|
2525
|
-
asyncio.run(main())
|
|
2526
|
-
```
|
|
2527
|
-
|
|
2528
|
-
---
|
|
2529
|
-
|
|
2530
|
-
### task_service.py
|
|
2531
|
-
**Purpose:** Handles the business logic for cancelling A2A tasks. It uses `CoreA2AService` to construct the cancellation message and a provided publisher function to send it over the messaging fabric.
|
|
2532
|
-
**Import:** `from src.solace_agent_mesh.gateway.http_sse.services.task_service import TaskService, PublishFunc`
|
|
2533
|
-
|
|
2534
|
-
**Classes:**
|
|
2535
|
-
- `TaskService(core_a2a_service: CoreA2AService, publish_func: PublishFunc, namespace: str, gateway_id: str, sse_manager: SSEManager, task_context_map: Dict[str, Dict], task_context_lock: threading.Lock, app_name: str)` - A service for managing A2A task operations.
|
|
2536
|
-
- `cancel_task(agent_name: str, task_id: str, client_id: str, user_id: str = "web_user") -> None` - Asynchronously constructs and publishes an A2A `CancelTaskRequest` message for a specific task.
|
|
2537
|
-
|
|
2538
|
-
**Type Aliases:**
|
|
2539
|
-
- `PublishFunc: Callable[[str, Dict, Optional[Dict]], None]` - A callable that sends a message. It takes a topic, a payload dictionary, and optional user properties.
|
|
2540
|
-
|
|
2541
|
-
**Usage Examples:**
|
|
2542
|
-
```python
|
|
2543
|
-
import asyncio
|
|
2544
|
-
import threading
|
|
2545
|
-
from typing import Callable, Dict, Optional
|
|
2546
|
-
|
|
2547
|
-
from src.solace_agent_mesh.gateway.http_sse.services.task_service import TaskService, PublishFunc
|
|
2548
|
-
from src.solace_agent_mesh.core_a2a.service import CoreA2AService
|
|
2549
|
-
from src.solace_agent_mesh.gateway.http_sse.sse_manager import SSEManager
|
|
2550
|
-
|
|
2551
|
-
# Mock dependencies for the example
|
|
2552
|
-
class MockCoreA2AService(CoreA2AService):
|
|
2553
|
-
def cancel_task(self, agent_name, task_id, client_id, user_id):
|
|
2554
|
-
topic = f"a2a/request/{agent_name}/cancelTask"
|
|
2555
|
-
payload = {"taskId": task_id}
|
|
2556
|
-
user_props = {"clientId": client_id, "userId": user_id}
|
|
2557
|
-
return topic, payload, user_props
|
|
2558
|
-
|
|
2559
|
-
def my_publish_func(topic: str, payload: Dict, user_properties: Optional[Dict]):
|
|
2560
|
-
print("\n--- Publishing Message ---")
|
|
2561
|
-
print(f"Topic: {topic}")
|
|
2562
|
-
print(f"Payload: {payload}")
|
|
2563
|
-
print(f"User Properties: {user_properties}")
|
|
2564
|
-
print("------------------------")
|
|
2565
|
-
|
|
2566
|
-
async def main():
|
|
2567
|
-
# 1. Set up dependencies
|
|
2568
|
-
core_a2a_service = MockCoreA2AService()
|
|
2569
|
-
sse_manager = SSEManager()
|
|
2570
|
-
task_context_map = {}
|
|
2571
|
-
task_context_lock = threading.Lock()
|
|
2572
|
-
|
|
2573
|
-
# 2. Initialize TaskService
|
|
2574
|
-
task_service = TaskService(
|
|
2575
|
-
core_a2a_service=core_a2a_service,
|
|
2576
|
-
publish_func=my_publish_func,
|
|
2577
|
-
namespace="my-namespace",
|
|
2578
|
-
gateway_id="gateway-01",
|
|
2579
|
-
sse_manager=sse_manager,
|
|
2580
|
-
task_context_map=task_context_map,
|
|
2581
|
-
task_context_lock=task_context_lock,
|
|
2582
|
-
app_name="my-app"
|
|
2583
|
-
)
|
|
2584
|
-
|
|
2585
|
-
# 3. Call the cancel_task method
|
|
2586
|
-
print("Requesting task cancellation...")
|
|
2587
|
-
await task_service.cancel_task(
|
|
2588
|
-
agent_name="report-generator",
|
|
2589
|
-
task_id="task-12345",
|
|
2590
|
-
client_id="client-abcde",
|
|
2591
|
-
user_id="test.user"
|
|
2592
|
-
)
|
|
2593
|
-
print("Task cancellation request sent.")
|
|
2594
|
-
|
|
2595
|
-
if __name__ == "__main__":
|
|
2596
|
-
asyncio.run(main())
|
|
2597
|
-
```
|
|
2598
|
-
|
|
2599
|
-
================================================================================
|
|
2600
|
-
|
|
2601
|
-
## Section 24: llm.txt
|
|
2602
|
-
|
|
2603
|
-
**Source file:** `llm.txt`
|
|
2604
|
-
|
|
2605
|
-
Here is the comprehensive developer guide for the `src` directory.
|
|
2606
|
-
|
|
2607
|
-
## Quick Summary
|
|
2608
|
-
The `src` directory serves as the main source code root for the Solace AI Connector, containing four primary subsystems that work together to enable comprehensive AI agent communication and hosting. The `agent` directory provides a complete framework for hosting Google ADK agents with A2A protocol support, the `common` directory offers foundational A2A protocol infrastructure and utilities, the `core_a2a` directory provides a reusable service layer for core A2A operations, and the `gateway` directory implements various gateway patterns for external platform integration. These components work together to create a distributed AI agent ecosystem with real-time communication, task delegation, and multi-platform integration capabilities.
|
|
2609
|
-
|
|
2610
|
-
## Files and Subdirectories Overview
|
|
2611
|
-
- **Direct files:**
|
|
2612
|
-
- `__init__.py`: Empty package initialization file.
|
|
2613
|
-
- **Subdirectories:**
|
|
2614
|
-
- `agent/`: Complete ADK agent hosting framework with A2A protocol integration and comprehensive tool library.
|
|
2615
|
-
- `common/`: Foundational A2A protocol infrastructure, type systems, and client/server implementations.
|
|
2616
|
-
- `core_a2a/`: Reusable service layer for core A2A interactions and agent registry operations.
|
|
2617
|
-
- `gateway/`: Gateway framework with HTTP/SSE, Slack, and Webhook implementations for external platform integration.
|
|
2618
|
-
|
|
2619
|
-
## Developer API Reference
|
|
2620
|
-
|
|
2621
|
-
### Direct Files
|
|
2622
|
-
|
|
2623
|
-
#### __init__.py
|
|
2624
|
-
**Purpose:** Standard Python package initializer. It allows the `src` directory and its subdirectories to be treated as a package.
|
|
2625
|
-
**Import:** `from src import agent, common, gateway`
|
|
2626
|
-
|
|
2627
|
-
**Classes/Functions/Constants:**
|
|
2628
|
-
This file is empty and has no public interfaces.
|
|
2629
|
-
|
|
2630
|
-
### Subdirectory APIs
|
|
2631
|
-
|
|
2632
|
-
#### agent/
|
|
2633
|
-
**Purpose:** Provides a complete framework for hosting Google ADK agents with A2A protocol support and a comprehensive, extensible tool library.
|
|
2634
|
-
**Key Exports:** `SamAgentApp`, `SamAgentComponent`, `AppLlmAgent`, and a wide array of built-in tools for data analysis, web requests, multimedia processing, and inter-agent communication.
|
|
2635
|
-
**Import Examples:**
|
|
2636
|
-
```python
|
|
2637
|
-
from src.solace_agent_mesh.agent.sac.app import SamAgentApp
|
|
2638
|
-
from src.solace_agent_mesh.agent.sac.component import SamAgentComponent
|
|
2639
|
-
from src.solace_agent_mesh.agent.adk.app_llm_agent import AppLlmAgent
|
|
2640
|
-
from src.solace_agent_mesh.agent.tools.builtin_data_analysis_tools import query_data_with_sql
|
|
2641
|
-
from src.solace_agent_mesh.agent.tools.peer_agent_tool import PeerAgentTool
|
|
2642
|
-
from src.solace_agent_mesh.agent.tools.web_tools import web_request
|
|
2643
|
-
from src.solace_agent_mesh.agent.tools.image_tools import create_image_from_description
|
|
2644
|
-
```
|
|
2645
|
-
|
|
2646
|
-
#### common/
|
|
2647
|
-
**Purpose:** Provides the foundational infrastructure for Agent-to-Agent (A2A) communication, including the core protocol, data types, message translation, and client/server implementations.
|
|
2648
|
-
**Key Exports:** A2A protocol functions, Pydantic type definitions (`Message`, `Task`, `AgentCard`), `A2AClient` for interacting with agents, `A2AServer` for building agents, and various utilities.
|
|
2649
|
-
**Import Examples:**
|
|
2650
|
-
```python
|
|
2651
|
-
from src.solace_agent_mesh.common.a2a_protocol import get_agent_request_topic
|
|
2652
|
-
from src.solace_agent_mesh.common.types import Message, Task, AgentCard, TextPart
|
|
2653
|
-
from src.solace_agent_mesh.common.client import A2AClient, A2ACardResolver
|
|
2654
|
-
from src.solace_agent_mesh.common.server import A2AServer, InMemoryTaskManager
|
|
2655
|
-
from src.solace_agent_mesh.common.agent_registry import AgentRegistry
|
|
2656
|
-
from src.solace_agent_mesh.common.utils.embeds import resolve_embeds_in_string
|
|
2657
|
-
```
|
|
2658
|
-
|
|
2659
|
-
#### core_a2a/
|
|
2660
|
-
**Purpose:** Provides a reusable, decoupled service layer for core A2A interactions, handling task submission, cancellation, and agent discovery.
|
|
2661
|
-
**Key Exports:** `CoreA2AService` for managing A2A protocol logic without being tied to a specific gateway or messaging implementation.
|
|
2662
|
-
**Import Examples:**
|
|
2663
|
-
```python
|
|
2664
|
-
from src.solace_agent_mesh.core_a2a.service import CoreA2AService
|
|
2665
|
-
```
|
|
2666
|
-
|
|
2667
|
-
#### gateway/
|
|
2668
|
-
**Purpose:** Provides a framework and multiple implementations for building gateways that bridge external platforms (like web UIs, Slack, or webhooks) with the A2A messaging system.
|
|
2669
|
-
**Key Exports:** `BaseGatewayApp` and `BaseGatewayComponent` for creating custom gateways, and concrete implementations like `WebUIBackendApp`, `SlackGatewayApp`, and `WebhookGatewayApp`.
|
|
2670
|
-
**Import Examples:**
|
|
2671
|
-
```python
|
|
2672
|
-
from src.solace_agent_mesh.gateway.base.app import BaseGatewayApp
|
|
2673
|
-
from src.solace_agent_mesh.gateway.http_sse.app import WebUIBackendApp
|
|
2674
|
-
from src.solace_agent_mesh.gateway.slack.app import SlackGatewayApp
|
|
2675
|
-
from src.solace_agent_mesh.gateway.webhook.app import WebhookGatewayApp
|
|
2676
|
-
from src.solace_agent_mesh.gateway.base.authorization_service import ConfigurableRbacAuthorizationService
|
|
2677
|
-
```
|
|
2678
|
-
|
|
2679
|
-
## Complete Usage Guide
|
|
2680
|
-
This guide demonstrates how the different subdirectories within `src` work together to build a complete, distributed AI agent system.
|
|
2681
|
-
|
|
2682
|
-
### 1. How to import and use functionality from subdirectories
|
|
2683
|
-
The following examples show how to import and instantiate components from each major subdirectory.
|
|
2684
|
-
|
|
2685
|
-
```python
|
|
2686
|
-
# 1. Import from the 'agent' directory to create an AI agent
|
|
2687
|
-
from src.solace_agent_mesh.agent.sac.app import SamAgentApp
|
|
2688
|
-
|
|
2689
|
-
# 2. Import from the 'common' and 'core_a2a' directories for protocol infrastructure
|
|
2690
|
-
from src.solace_agent_mesh.common.agent_registry import AgentRegistry
|
|
2691
|
-
from src.solace_agent_mesh.common.types import AgentCard, AgentCapabilities, AgentSkill
|
|
2692
|
-
from src.solace_agent_mesh.core_a2a.service import CoreA2AService
|
|
2693
|
-
|
|
2694
|
-
# 3. Import from the 'gateway' directory to create interfaces
|
|
2695
|
-
from src.solace_agent_mesh.gateway.http_sse.app import WebUIBackendApp
|
|
2696
|
-
from src.solace_agent_mesh.gateway.slack.app import SlackGatewayApp
|
|
2697
|
-
from src.solace_agent_mesh.gateway.webhook.app import WebhookGatewayApp
|
|
2698
|
-
|
|
2699
|
-
# 4. Import tools from the 'agent/tools' subdirectory
|
|
2700
|
-
from src.solace_agent_mesh.agent.tools.peer_agent_tool import PeerAgentTool
|
|
2701
|
-
from src.solace_agent_mesh.agent.tools.builtin_data_analysis_tools import query_data_with_sql
|
|
2702
|
-
```
|
|
2703
|
-
|
|
2704
|
-
### 2. How different parts work together
|
|
2705
|
-
This section shows a step-by-step process for building a system, illustrating the synergy between the components.
|
|
2706
|
-
|
|
2707
|
-
#### Step 1: Create an ADK-powered agent (`agent/`)
|
|
2708
|
-
First, define and configure an agent. This agent will automatically be equipped with a rich set of tools and A2A communication capabilities.
|
|
2709
|
-
|
|
2710
|
-
```python
|
|
2711
|
-
# File: my_system.py
|
|
2712
|
-
from src.solace_agent_mesh.agent.sac.app import SamAgentApp
|
|
2713
|
-
|
|
2714
|
-
# Configure the agent with all capabilities
|
|
2715
|
-
agent_config = {
|
|
2716
|
-
"name": "data-analyst-agent",
|
|
2717
|
-
"app_config": {
|
|
2718
|
-
"namespace": "myorg/ai-agents",
|
|
2719
|
-
"agent_name": "data_analyst",
|
|
2720
|
-
"model": "gemini-1.5-pro",
|
|
2721
|
-
"instruction": "You are a data analysis expert with access to SQL, charting, web tools, and peer collaboration.",
|
|
2722
|
-
"agent_card": {
|
|
2723
|
-
"description": "AI agent for comprehensive data analysis and reporting",
|
|
2724
|
-
"capabilities": ["data_analysis", "web_research", "chart_generation", "peer_collaboration"]
|
|
2725
|
-
},
|
|
2726
|
-
"agent_card_publishing": {"interval_seconds": 30},
|
|
2727
|
-
"agent_discovery": {"enabled": True},
|
|
2728
|
-
"inter_agent_communication": {"allow_list": ["*"]}
|
|
2729
|
-
}
|
|
2730
|
-
}
|
|
2731
|
-
|
|
2732
|
-
# Create the agent app (in a real scenario, this is run by the SAC framework)
|
|
2733
|
-
agent_app = SamAgentApp(agent_config)
|
|
2734
|
-
```
|
|
2735
|
-
|
|
2736
|
-
#### Step 2: Set Up A2A Protocol Infrastructure (`common/` and `core_a2a/`)
|
|
2737
|
-
Next, set up the core services that manage agent discovery and task routing. This is often handled by the gateway components but can be used directly.
|
|
2738
|
-
|
|
2739
|
-
```python
|
|
2740
|
-
# File: my_system.py (continued)
|
|
2741
|
-
from src.solace_agent_mesh.common.agent_registry import AgentRegistry
|
|
2742
|
-
from src.solace_agent_mesh.common.types import AgentCard, AgentCapabilities, AgentSkill
|
|
2743
|
-
from src.solace_agent_mesh.core_a2a.service import CoreA2AService
|
|
2744
|
-
|
|
2745
|
-
# Initialize a shared agent registry
|
|
2746
|
-
agent_registry = AgentRegistry()
|
|
2747
|
-
|
|
2748
|
-
# Create the core A2A service, which uses the registry
|
|
2749
|
-
namespace = "myorg/ai-agents"
|
|
2750
|
-
a2a_service = CoreA2AService(agent_registry, namespace)
|
|
2751
|
-
|
|
2752
|
-
# Manually register an agent's capabilities (this is usually done automatically by the agent itself)
|
|
2753
|
-
data_analyst_card = AgentCard(
|
|
2754
|
-
name="data_analyst",
|
|
2755
|
-
display_name="Data Analyst",
|
|
2756
|
-
description="AI agent for data analysis",
|
|
2757
|
-
url=f"a2a://{namespace}/data_analyst",
|
|
2758
|
-
version="1.0.0",
|
|
2759
|
-
capabilities=AgentCapabilities(streaming=True, pushNotifications=True),
|
|
2760
|
-
skills=[AgentSkill(id="sql_analysis", name="SQL Data Analysis")]
|
|
2761
|
-
)
|
|
2762
|
-
a2a_service.process_discovery_message(data_analyst_card)
|
|
2763
|
-
```
|
|
2764
|
-
|
|
2765
|
-
#### Step 3: Create Gateway Integrations (`gateway/`)
|
|
2766
|
-
Create one or more gateways to expose the agent(s) to external platforms.
|
|
2767
|
-
|
|
2768
|
-
```python
|
|
2769
|
-
# File: my_system.py (continued)
|
|
2770
|
-
from src.solace_agent_mesh.gateway.http_sse.app import WebUIBackendApp
|
|
2771
|
-
from src.solace_agent_mesh.gateway.slack.app import SlackGatewayApp
|
|
2772
|
-
|
|
2773
|
-
# Web UI Gateway for browser-based interactions
|
|
2774
|
-
webui_config = {
|
|
2775
|
-
"name": "web-gateway",
|
|
2776
|
-
"app_config": {
|
|
2777
|
-
"namespace": "myorg/ai-agents",
|
|
2778
|
-
"gateway_id": "web-ui-gateway",
|
|
2779
|
-
"session_secret_key": "a-very-secret-key",
|
|
2780
|
-
"fastapi_host": "0.0.0.0",
|
|
2781
|
-
"fastapi_port": 8080,
|
|
2782
|
-
"artifact_service": {"type": "local_file", "base_path": "./artifacts"}
|
|
2783
|
-
}
|
|
2784
|
-
}
|
|
2785
|
-
webui_app = WebUIBackendApp(webui_config)
|
|
2786
|
-
|
|
2787
|
-
# Slack Gateway for team collaboration
|
|
2788
|
-
slack_config = {
|
|
2789
|
-
"name": "slack-gateway",
|
|
2790
|
-
"app_config": {
|
|
2791
|
-
"namespace": "myorg/ai-agents",
|
|
2792
|
-
"gateway_id": "slack-gateway",
|
|
2793
|
-
"slack_bot_token": "${SLACK_BOT_TOKEN}",
|
|
2794
|
-
"slack_app_token": "${SLACK_APP_TOKEN}",
|
|
2795
|
-
"default_agent_name": "data_analyst"
|
|
2796
|
-
}
|
|
2797
|
-
}
|
|
2798
|
-
slack_app = SlackGatewayApp(slack_config)
|
|
2799
|
-
```
|
|
2800
|
-
|
|
2801
|
-
### 3. Common usage patterns
|
|
2802
|
-
|
|
2803
|
-
#### Pattern 1: Inter-Agent Communication
|
|
2804
|
-
An agent can use the `PeerAgentTool` (from `agent/tools/`) to delegate tasks to other agents, leveraging the `common/` protocol infrastructure.
|
|
2805
|
-
|
|
2806
|
-
```python
|
|
2807
|
-
# This code would run within an agent's tool execution context.
|
|
2808
|
-
from src.solace_agent_mesh.agent.tools.peer_agent_tool import PeerAgentTool
|
|
2809
|
-
|
|
2810
|
-
async def analyze_and_delegate_report(component, tool_context):
|
|
2811
|
-
# Assume 'component' is the SamAgentComponent instance hosting the current agent.
|
|
2812
|
-
|
|
2813
|
-
# Step 1: Perform local analysis (using another tool)
|
|
2814
|
-
# ... analysis_result = await query_data_with_sql(...) ...
|
|
2815
|
-
|
|
2816
|
-
# Step 2: Delegate report generation to a specialist agent
|
|
2817
|
-
peer_tool = PeerAgentTool(
|
|
2818
|
-
target_agent_name="report_generator",
|
|
2819
|
-
host_component=component
|
|
2820
|
-
)
|
|
2821
|
-
|
|
2822
|
-
report_result = await peer_tool.run_async(
|
|
2823
|
-
args={
|
|
2824
|
-
"task_description": "Generate a professional PDF report from this analysis",
|
|
2825
|
-
"analysis_data": "artifact://analysis_result.json",
|
|
2826
|
-
"report_format": "PDF"
|
|
2827
|
-
},
|
|
2828
|
-
tool_context=tool_context
|
|
2829
|
-
)
|
|
2830
|
-
|
|
2831
|
-
return report_result
|
|
2832
|
-
```
|
|
2833
|
-
|
|
2834
|
-
================================================================================
|
|
2835
|
-
|