solace-agent-mesh 1.6.1__py3-none-any.whl → 1.13.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of solace-agent-mesh might be problematic. Click here for more details.
- solace_agent_mesh/agent/adk/alembic/README +74 -0
- solace_agent_mesh/agent/adk/alembic/env.py +77 -0
- solace_agent_mesh/agent/adk/alembic/script.py.mako +28 -0
- solace_agent_mesh/agent/adk/alembic/versions/e2902798564d_adk_session_db_upgrade.py +52 -0
- solace_agent_mesh/agent/adk/alembic.ini +112 -0
- solace_agent_mesh/agent/adk/app_llm_agent.py +26 -0
- solace_agent_mesh/agent/adk/artifacts/filesystem_artifact_service.py +165 -1
- solace_agent_mesh/agent/adk/artifacts/s3_artifact_service.py +163 -0
- solace_agent_mesh/agent/adk/callbacks.py +852 -109
- solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +234 -36
- solace_agent_mesh/agent/adk/intelligent_mcp_callbacks.py +52 -5
- solace_agent_mesh/agent/adk/mcp_content_processor.py +1 -1
- solace_agent_mesh/agent/adk/models/lite_llm.py +77 -21
- solace_agent_mesh/agent/adk/models/oauth2_token_manager.py +24 -137
- solace_agent_mesh/agent/adk/runner.py +85 -20
- solace_agent_mesh/agent/adk/schema_migration.py +88 -0
- solace_agent_mesh/agent/adk/services.py +94 -18
- solace_agent_mesh/agent/adk/setup.py +281 -65
- solace_agent_mesh/agent/adk/stream_parser.py +231 -37
- solace_agent_mesh/agent/adk/tool_wrapper.py +3 -0
- solace_agent_mesh/agent/protocol/event_handlers.py +472 -137
- solace_agent_mesh/agent/proxies/a2a/app.py +3 -2
- solace_agent_mesh/agent/proxies/a2a/component.py +572 -75
- solace_agent_mesh/agent/proxies/a2a/config.py +80 -4
- solace_agent_mesh/agent/proxies/base/app.py +3 -2
- solace_agent_mesh/agent/proxies/base/component.py +188 -22
- solace_agent_mesh/agent/proxies/base/proxy_task_context.py +3 -1
- solace_agent_mesh/agent/sac/app.py +91 -3
- solace_agent_mesh/agent/sac/component.py +591 -157
- solace_agent_mesh/agent/sac/patch_adk.py +8 -16
- solace_agent_mesh/agent/sac/task_execution_context.py +146 -4
- solace_agent_mesh/agent/tools/__init__.py +3 -0
- solace_agent_mesh/agent/tools/audio_tools.py +3 -3
- solace_agent_mesh/agent/tools/builtin_artifact_tools.py +710 -171
- solace_agent_mesh/agent/tools/deep_research_tools.py +2161 -0
- solace_agent_mesh/agent/tools/dynamic_tool.py +2 -0
- solace_agent_mesh/agent/tools/peer_agent_tool.py +82 -15
- solace_agent_mesh/agent/tools/time_tools.py +126 -0
- solace_agent_mesh/agent/tools/tool_config_types.py +57 -2
- solace_agent_mesh/agent/tools/web_search_tools.py +279 -0
- solace_agent_mesh/agent/tools/web_tools.py +125 -17
- solace_agent_mesh/agent/utils/artifact_helpers.py +248 -6
- solace_agent_mesh/agent/utils/context_helpers.py +17 -0
- solace_agent_mesh/assets/docs/404.html +6 -6
- solace_agent_mesh/assets/docs/assets/css/{styles.906a1503.css → styles.8162edfb.css} +1 -1
- solace_agent_mesh/assets/docs/assets/js/05749d90.19ac4f35.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/15ba94aa.e186750d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/15e40e79.434bb30f.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/17896441.e612dfb4.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2279.550aa580.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/{17896441.a5e82f9b.js.LICENSE.txt → 2279.550aa580.js.LICENSE.txt} +6 -0
- solace_agent_mesh/assets/docs/assets/js/240a0364.83e37aa8.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2987107d.a80604f9.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2e32b5e0.2f0db237.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3a6c6137.7e61915d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3ac1795d.7f7ab1c1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3ff0015d.e53c9b78.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/41adc471.0e95b87c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/4667dc50.bf2ad456.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/49eed117.493d6f99.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{509e993c.4c7a1a6d.js → 509e993c.a1fbf45a.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/547e15cc.8e6da617.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/55b7b518.29d6e75d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5b8d9c11.d4eb37b8.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5c2bd65f.1ee87753.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/60702c0e.a8bdd79b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/631738c7.fa471607.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/64195356.09dbd087.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/66d4869e.30340bd3.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6a520c9d.b6e3f2ce.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6aaedf65.7253541d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.a5b36a60.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6d84eae0.fd23ba4a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/71da7b71.374b9d54.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/729898df.7249e9fd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/7e294c01.7c5f6906.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8024126c.e3467286.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/81a99df0.7ed65d45.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/82fbfb93.161823a5.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8b032486.91a91afc.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/924ffdeb.975e428a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/94e8668d.16083b3f.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9bb13469.4523ae20.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/a7d42657.a956689d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/a94703ab.3e5fbcb3.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ab9708a8.3e563275.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ad87452a.9d73dad6.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/c93cbaa0.0e0d8baf.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/cab03b5b.6a073091.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/cbe2e9ea.07e170dd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/da0b5bad.b62f7b08.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/dd817ffc.c37a755e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/dd81e2b8.b682e9c2.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/de915948.44a432bc.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e04b235d.06d23db6.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e1b6eeb4.deb2b62e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e3d9abda.1476f570.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e6f9706b.acc800d3.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e92d0134.c147a429.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ee0c2fe7.94d0a351.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/f284c35a.cc97854c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ff4d71f2.74710fc1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/main.d634009f.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/runtime~main.27bb82a7.js +1 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +68 -68
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +50 -50
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +42 -42
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +55 -55
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +82 -68
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/image-tools/index.html +81 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +67 -50
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/research-tools/index.html +136 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +178 -144
- solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +43 -42
- solace_agent_mesh/assets/docs/docs/documentation/components/index.html +20 -18
- solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +23 -23
- solace_agent_mesh/assets/docs/docs/documentation/components/platform-service/index.html +33 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +45 -45
- solace_agent_mesh/assets/docs/docs/documentation/components/projects/index.html +182 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/prompts/index.html +147 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +208 -125
- solace_agent_mesh/assets/docs/docs/documentation/components/speech/index.html +52 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +28 -49
- solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +29 -30
- solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +14 -14
- solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/index.html +47 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/kubernetes-deployment-guide/index.html +197 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/logging/index.html +90 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +17 -16
- solace_agent_mesh/assets/docs/docs/documentation/deploying/proxy_configuration/index.html +49 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +38 -38
- solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +162 -171
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +67 -49
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +17 -17
- solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +51 -51
- solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +22 -22
- solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +27 -27
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +135 -135
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +66 -66
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +51 -51
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +50 -38
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +86 -86
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +51 -51
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +24 -24
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +30 -30
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +44 -44
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/teams-integration/index.html +115 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/agent-builder/index.html +86 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/connectors/index.html +67 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +23 -19
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +40 -37
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/openapi-tools/index.html +324 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +112 -87
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/secure-user-delegated-access/index.html +440 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +87 -64
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/wheel-installation/index.html +62 -0
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +44 -44
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +39 -37
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +30 -30
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +18 -18
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/vibe_coding/index.html +62 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/artifact-storage/index.html +311 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +39 -42
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +14 -14
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +27 -25
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +69 -69
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +72 -72
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/session-storage/index.html +251 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/user-feedback/index.html +88 -0
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +42 -42
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +20 -20
- solace_agent_mesh/assets/docs/docs/documentation/migrations/platform-service-split/index.html +85 -0
- solace_agent_mesh/assets/docs/lunr-index-1768329217460.json +1 -0
- solace_agent_mesh/assets/docs/lunr-index.json +1 -1
- solace_agent_mesh/assets/docs/search-doc-1768329217460.json +1 -0
- solace_agent_mesh/assets/docs/search-doc.json +1 -1
- solace_agent_mesh/assets/docs/sitemap.xml +1 -1
- solace_agent_mesh/cli/__init__.py +1 -1
- solace_agent_mesh/cli/commands/add_cmd/__init__.py +3 -1
- solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +6 -1
- solace_agent_mesh/cli/commands/add_cmd/proxy_cmd.py +100 -0
- solace_agent_mesh/cli/commands/docs_cmd.py +4 -1
- solace_agent_mesh/cli/commands/eval_cmd.py +1 -1
- solace_agent_mesh/cli/commands/init_cmd/__init__.py +15 -0
- solace_agent_mesh/cli/commands/init_cmd/directory_step.py +1 -1
- solace_agent_mesh/cli/commands/init_cmd/env_step.py +30 -3
- solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +3 -4
- solace_agent_mesh/cli/commands/init_cmd/platform_service_step.py +85 -0
- solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +16 -3
- solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +2 -1
- solace_agent_mesh/cli/commands/plugin_cmd/catalog_cmd.py +1 -0
- solace_agent_mesh/cli/commands/plugin_cmd/create_cmd.py +3 -3
- solace_agent_mesh/cli/commands/run_cmd.py +64 -49
- solace_agent_mesh/cli/commands/tools_cmd.py +315 -0
- solace_agent_mesh/cli/main.py +15 -0
- solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-BTf6dqwp.js → authCallback-KnKMP_vb.js} +1 -1
- solace_agent_mesh/client/webui/frontend/static/assets/client-DpBL2stg.js +25 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-Cd498TV2.js +435 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-rSf8Vu29.css +1 -0
- solace_agent_mesh/client/webui/frontend/static/assets/vendor-CGk8Suyh.js +565 -0
- solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
- solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
- solace_agent_mesh/client/webui/frontend/static/mockServiceWorker.js +336 -0
- solace_agent_mesh/client/webui/frontend/static/ui-version.json +6 -0
- solace_agent_mesh/common/a2a/events.py +2 -1
- solace_agent_mesh/common/a2a/protocol.py +5 -0
- solace_agent_mesh/common/a2a/types.py +2 -1
- solace_agent_mesh/common/a2a_spec/schemas/artifact_creation_progress.json +23 -6
- solace_agent_mesh/common/a2a_spec/schemas/feedback_event.json +51 -0
- solace_agent_mesh/common/agent_registry.py +38 -11
- solace_agent_mesh/common/data_parts.py +144 -4
- solace_agent_mesh/common/error_handlers.py +83 -0
- solace_agent_mesh/common/exceptions.py +24 -0
- solace_agent_mesh/common/oauth/__init__.py +17 -0
- solace_agent_mesh/common/oauth/oauth_client.py +408 -0
- solace_agent_mesh/common/oauth/utils.py +50 -0
- solace_agent_mesh/common/rag_dto.py +156 -0
- solace_agent_mesh/common/sac/sam_component_base.py +97 -19
- solace_agent_mesh/common/sam_events/event_service.py +2 -2
- solace_agent_mesh/common/services/employee_service.py +1 -1
- solace_agent_mesh/common/utils/embeds/constants.py +1 -0
- solace_agent_mesh/common/utils/embeds/converter.py +1 -8
- solace_agent_mesh/common/utils/embeds/modifiers.py +4 -28
- solace_agent_mesh/common/utils/embeds/resolver.py +152 -31
- solace_agent_mesh/common/utils/embeds/types.py +9 -0
- solace_agent_mesh/common/utils/log_formatters.py +20 -0
- solace_agent_mesh/common/utils/mime_helpers.py +12 -5
- solace_agent_mesh/common/utils/pydantic_utils.py +90 -3
- solace_agent_mesh/common/utils/rbac_utils.py +69 -0
- solace_agent_mesh/common/utils/templates/__init__.py +8 -0
- solace_agent_mesh/common/utils/templates/liquid_renderer.py +210 -0
- solace_agent_mesh/common/utils/templates/template_resolver.py +161 -0
- solace_agent_mesh/config_portal/backend/common.py +12 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-CljP4_mv.js +103 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/{components-Rk0n-9cK.js → components-CaC6hG8d.js} +22 -22
- solace_agent_mesh/config_portal/frontend/static/client/assets/{entry.client-mvZjNKiz.js → entry.client-H_TM0YBt.js} +3 -3
- solace_agent_mesh/config_portal/frontend/static/client/assets/{index-DzNKzXrc.js → index-CnFykb2v.js} +16 -16
- solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-f8439d40.js +1 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-BIMqslJB.css +1 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-mJmTIdIk.js +10 -0
- solace_agent_mesh/config_portal/frontend/static/client/index.html +3 -3
- solace_agent_mesh/core_a2a/service.py +3 -2
- solace_agent_mesh/gateway/adapter/__init__.py +1 -0
- solace_agent_mesh/gateway/adapter/base.py +170 -0
- solace_agent_mesh/gateway/adapter/types.py +230 -0
- solace_agent_mesh/gateway/base/app.py +39 -2
- solace_agent_mesh/gateway/base/auth_interface.py +103 -0
- solace_agent_mesh/gateway/base/component.py +1027 -151
- solace_agent_mesh/gateway/generic/__init__.py +1 -0
- solace_agent_mesh/gateway/generic/app.py +50 -0
- solace_agent_mesh/gateway/generic/component.py +894 -0
- solace_agent_mesh/gateway/http_sse/alembic/env.py +0 -7
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_project_users_table.py +72 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_soft_delete_and_search.py +109 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_default_agent_to_projects.py +26 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_projects_table.py +135 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251108_create_prompt_tables_with_sharing.py +154 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251115_add_parent_task_id.py +32 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251126_add_background_task_fields.py +47 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251202_add_versioned_fields_to_prompts.py +52 -0
- solace_agent_mesh/gateway/http_sse/alembic.ini +0 -36
- solace_agent_mesh/gateway/http_sse/app.py +40 -11
- solace_agent_mesh/gateway/http_sse/component.py +285 -160
- solace_agent_mesh/gateway/http_sse/dependencies.py +149 -114
- solace_agent_mesh/gateway/http_sse/main.py +68 -450
- solace_agent_mesh/gateway/http_sse/repository/__init__.py +19 -1
- solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +2 -2
- solace_agent_mesh/gateway/http_sse/repository/entities/project.py +81 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/project_user.py +47 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/session.py +26 -3
- solace_agent_mesh/gateway/http_sse/repository/entities/task.py +7 -0
- solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +47 -0
- solace_agent_mesh/gateway/http_sse/repository/interfaces.py +114 -6
- solace_agent_mesh/gateway/http_sse/repository/models/__init__.py +13 -0
- solace_agent_mesh/gateway/http_sse/repository/models/project_model.py +51 -0
- solace_agent_mesh/gateway/http_sse/repository/models/project_user_model.py +75 -0
- solace_agent_mesh/gateway/http_sse/repository/models/prompt_model.py +159 -0
- solace_agent_mesh/gateway/http_sse/repository/models/session_model.py +8 -2
- solace_agent_mesh/gateway/http_sse/repository/models/task_model.py +8 -1
- solace_agent_mesh/gateway/http_sse/repository/project_repository.py +172 -0
- solace_agent_mesh/gateway/http_sse/repository/project_user_repository.py +186 -0
- solace_agent_mesh/gateway/http_sse/repository/session_repository.py +177 -11
- solace_agent_mesh/gateway/http_sse/repository/task_repository.py +86 -2
- solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +38 -7
- solace_agent_mesh/gateway/http_sse/routers/artifacts.py +256 -58
- solace_agent_mesh/gateway/http_sse/routers/auth.py +168 -134
- solace_agent_mesh/gateway/http_sse/routers/config.py +302 -8
- solace_agent_mesh/gateway/http_sse/routers/dto/project_dto.py +69 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/prompt_dto.py +255 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/project_requests.py +48 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/session_requests.py +14 -1
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/base_responses.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/project_responses.py +31 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +5 -2
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/version_responses.py +31 -0
- solace_agent_mesh/gateway/http_sse/routers/feedback.py +133 -2
- solace_agent_mesh/gateway/http_sse/routers/people.py +2 -2
- solace_agent_mesh/gateway/http_sse/routers/projects.py +768 -0
- solace_agent_mesh/gateway/http_sse/routers/prompts.py +1416 -0
- solace_agent_mesh/gateway/http_sse/routers/sessions.py +167 -7
- solace_agent_mesh/gateway/http_sse/routers/speech.py +355 -0
- solace_agent_mesh/gateway/http_sse/routers/sse.py +131 -8
- solace_agent_mesh/gateway/http_sse/routers/tasks.py +670 -18
- solace_agent_mesh/gateway/http_sse/routers/users.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/version.py +343 -0
- solace_agent_mesh/gateway/http_sse/routers/visualization.py +92 -9
- solace_agent_mesh/gateway/http_sse/services/audio_service.py +1227 -0
- solace_agent_mesh/gateway/http_sse/services/background_task_monitor.py +186 -0
- solace_agent_mesh/gateway/http_sse/services/data_retention_service.py +1 -1
- solace_agent_mesh/gateway/http_sse/services/feedback_service.py +1 -1
- solace_agent_mesh/gateway/http_sse/services/project_service.py +930 -0
- solace_agent_mesh/gateway/http_sse/services/prompt_builder_assistant.py +303 -0
- solace_agent_mesh/gateway/http_sse/services/session_service.py +361 -12
- solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +354 -4
- solace_agent_mesh/gateway/http_sse/session_manager.py +15 -15
- solace_agent_mesh/gateway/http_sse/sse_manager.py +286 -166
- solace_agent_mesh/gateway/http_sse/utils/artifact_copy_utils.py +370 -0
- solace_agent_mesh/gateway/http_sse/utils/stim_utils.py +41 -1
- solace_agent_mesh/services/__init__.py +0 -0
- solace_agent_mesh/services/platform/__init__.py +29 -0
- solace_agent_mesh/services/platform/alembic/env.py +85 -0
- solace_agent_mesh/services/platform/alembic/script.py.mako +28 -0
- solace_agent_mesh/services/platform/alembic.ini +109 -0
- solace_agent_mesh/services/platform/api/__init__.py +3 -0
- solace_agent_mesh/services/platform/api/dependencies.py +154 -0
- solace_agent_mesh/services/platform/api/main.py +314 -0
- solace_agent_mesh/services/platform/api/middleware.py +51 -0
- solace_agent_mesh/services/platform/api/routers/__init__.py +33 -0
- solace_agent_mesh/services/platform/api/routers/health_router.py +31 -0
- solace_agent_mesh/services/platform/app.py +215 -0
- solace_agent_mesh/services/platform/component.py +777 -0
- solace_agent_mesh/shared/__init__.py +14 -0
- solace_agent_mesh/shared/api/__init__.py +42 -0
- solace_agent_mesh/shared/auth/__init__.py +26 -0
- solace_agent_mesh/shared/auth/dependencies.py +204 -0
- solace_agent_mesh/shared/auth/middleware.py +347 -0
- solace_agent_mesh/shared/database/__init__.py +20 -0
- solace_agent_mesh/{gateway/http_sse/shared → shared/database}/base_repository.py +1 -1
- solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_exceptions.py +1 -1
- solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_helpers.py +1 -1
- solace_agent_mesh/shared/exceptions/__init__.py +36 -0
- solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exception_handlers.py +19 -5
- solace_agent_mesh/shared/utils/__init__.py +21 -0
- solace_agent_mesh/templates/logging_config_template.yaml +48 -0
- solace_agent_mesh/templates/main_orchestrator.yaml +12 -1
- solace_agent_mesh/templates/platform.yaml +49 -0
- solace_agent_mesh/templates/plugin_readme_template.md +3 -25
- solace_agent_mesh/templates/plugin_tool_config_template.yaml +109 -0
- solace_agent_mesh/templates/proxy_template.yaml +62 -0
- solace_agent_mesh/templates/webui.yaml +148 -6
- solace_agent_mesh/tools/web_search/__init__.py +18 -0
- solace_agent_mesh/tools/web_search/base.py +84 -0
- solace_agent_mesh/tools/web_search/google_search.py +247 -0
- solace_agent_mesh/tools/web_search/models.py +99 -0
- {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/METADATA +31 -12
- solace_agent_mesh-1.13.2.dist-info/RECORD +591 -0
- {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/WHEEL +1 -1
- solace_agent_mesh/agent/adk/adk_llm.txt +0 -232
- solace_agent_mesh/agent/adk/adk_llm_detail.txt +0 -566
- solace_agent_mesh/agent/adk/artifacts/artifacts_llm.txt +0 -171
- solace_agent_mesh/agent/adk/models/models_llm.txt +0 -142
- solace_agent_mesh/agent/agent_llm.txt +0 -378
- solace_agent_mesh/agent/agent_llm_detail.txt +0 -1702
- solace_agent_mesh/agent/protocol/protocol_llm.txt +0 -81
- solace_agent_mesh/agent/protocol/protocol_llm_detail.txt +0 -92
- solace_agent_mesh/agent/sac/sac_llm.txt +0 -189
- solace_agent_mesh/agent/sac/sac_llm_detail.txt +0 -200
- solace_agent_mesh/agent/testing/testing_llm.txt +0 -57
- solace_agent_mesh/agent/testing/testing_llm_detail.txt +0 -68
- solace_agent_mesh/agent/tools/tools_llm.txt +0 -263
- solace_agent_mesh/agent/tools/tools_llm_detail.txt +0 -274
- solace_agent_mesh/agent/utils/utils_llm.txt +0 -138
- solace_agent_mesh/agent/utils/utils_llm_detail.txt +0 -149
- solace_agent_mesh/assets/docs/assets/js/15ba94aa.932dd2db.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/240a0364.7eac6021.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/2e32b5e0.33f5d75b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3a6c6137.f5940cfa.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3ac1795d.76654dd9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3ff0015d.2be20244.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/547e15cc.2cbb060a.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/55b7b518.f2b1d1ba.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/5c2bd65f.eda4bcb2.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/631738c7.a8b1ef8b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/6a520c9d.ba015d81.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.f4b15f3b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/6d84eae0.4a5fbf39.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/71da7b71.38583438.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/8024126c.56e59919.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/81a99df0.07034dd9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/82fbfb93.139a1a1f.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/924ffdeb.8095e148.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/94e8668d.b5ddb7a1.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/9bb13469.dd1c9b54.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/a94703ab.0438dbc2.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/ab9708a8.3e6dd091.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/c93cbaa0.eaff365e.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/da0b5bad.d08a9466.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/dd817ffc.0aa9630a.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/dd81e2b8.d590bc9e.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/de915948.27d6b065.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e3d9abda.6b9493d0.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e6f9706b.e74a984d.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e92d0134.cf6d6522.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/f284c35a.42f59cdd.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/ff4d71f2.15b02f97.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/main.b12eac43.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/runtime~main.e268214e.js +0 -1
- solace_agent_mesh/assets/docs/lunr-index-1761248203150.json +0 -1
- solace_agent_mesh/assets/docs/search-doc-1761248203150.json +0 -1
- solace_agent_mesh/cli/commands/add_cmd/add_cmd_llm.txt +0 -250
- solace_agent_mesh/cli/commands/init_cmd/init_cmd_llm.txt +0 -365
- solace_agent_mesh/cli/commands/plugin_cmd/plugin_cmd_llm.txt +0 -305
- solace_agent_mesh/client/webui/frontend/static/assets/client-CaY59VuC.js +0 -25
- solace_agent_mesh/client/webui/frontend/static/assets/main-B32noGmR.js +0 -342
- solace_agent_mesh/client/webui/frontend/static/assets/main-DHJKSW1S.css +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/vendor-BEmvJSYz.js +0 -405
- solace_agent_mesh/common/a2a/a2a_llm.txt +0 -182
- solace_agent_mesh/common/a2a/a2a_llm_detail.txt +0 -193
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +0 -407
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm_detail.txt +0 -736
- solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +0 -313
- solace_agent_mesh/common/common_llm.txt +0 -251
- solace_agent_mesh/common/common_llm_detail.txt +0 -2562
- solace_agent_mesh/common/middleware/middleware_llm.txt +0 -174
- solace_agent_mesh/common/middleware/middleware_llm_detail.txt +0 -185
- solace_agent_mesh/common/sac/sac_llm.txt +0 -71
- solace_agent_mesh/common/sac/sac_llm_detail.txt +0 -82
- solace_agent_mesh/common/sam_events/sam_events_llm.txt +0 -104
- solace_agent_mesh/common/sam_events/sam_events_llm_detail.txt +0 -115
- solace_agent_mesh/common/services/providers/providers_llm.txt +0 -80
- solace_agent_mesh/common/services/services_llm.txt +0 -363
- solace_agent_mesh/common/services/services_llm_detail.txt +0 -459
- solace_agent_mesh/common/utils/embeds/embeds_llm.txt +0 -220
- solace_agent_mesh/common/utils/utils_llm.txt +0 -336
- solace_agent_mesh/common/utils/utils_llm_detail.txt +0 -572
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-ByU1X1HD.js +0 -98
- solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-61038fc6.js +0 -1
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-BWvk5-gF.js +0 -10
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-DxRwaWiE.css +0 -1
- solace_agent_mesh/core_a2a/core_a2a_llm.txt +0 -90
- solace_agent_mesh/core_a2a/core_a2a_llm_detail.txt +0 -101
- solace_agent_mesh/gateway/base/base_llm.txt +0 -224
- solace_agent_mesh/gateway/base/base_llm_detail.txt +0 -235
- solace_agent_mesh/gateway/gateway_llm.txt +0 -373
- solace_agent_mesh/gateway/gateway_llm_detail.txt +0 -3885
- solace_agent_mesh/gateway/http_sse/alembic/alembic_llm.txt +0 -295
- solace_agent_mesh/gateway/http_sse/alembic/versions/versions_llm.txt +0 -155
- solace_agent_mesh/gateway/http_sse/components/components_llm.txt +0 -105
- solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +0 -299
- solace_agent_mesh/gateway/http_sse/http_sse_llm_detail.txt +0 -3278
- solace_agent_mesh/gateway/http_sse/repository/entities/entities_llm.txt +0 -263
- solace_agent_mesh/gateway/http_sse/repository/models/models_llm.txt +0 -266
- solace_agent_mesh/gateway/http_sse/repository/repository_llm.txt +0 -340
- solace_agent_mesh/gateway/http_sse/routers/dto/dto_llm.txt +0 -346
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/requests_llm.txt +0 -83
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/responses_llm.txt +0 -107
- solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +0 -314
- solace_agent_mesh/gateway/http_sse/services/services_llm.txt +0 -297
- solace_agent_mesh/gateway/http_sse/shared/__init__.py +0 -146
- solace_agent_mesh/gateway/http_sse/shared/shared_llm.txt +0 -285
- solace_agent_mesh/gateway/http_sse/utils/utils_llm.txt +0 -47
- solace_agent_mesh/llm.txt +0 -228
- solace_agent_mesh/llm_detail.txt +0 -2835
- solace_agent_mesh/solace_agent_mesh_llm.txt +0 -362
- solace_agent_mesh/solace_agent_mesh_llm_detail.txt +0 -8599
- solace_agent_mesh/templates/logging_config_template.ini +0 -45
- solace_agent_mesh/templates/templates_llm.txt +0 -147
- solace_agent_mesh-1.6.1.dist-info/RECORD +0 -525
- /solace_agent_mesh/assets/docs/assets/js/{main.b12eac43.js.LICENSE.txt → main.d634009f.js.LICENSE.txt} +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/auth_utils.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/pagination.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/response_utils.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/error_dto.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exceptions.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/enums.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/timestamp_utils.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/types.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/utils.py +0 -0
- {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,2562 +0,0 @@
|
|
|
1
|
-
# LLM Summary Detail File
|
|
2
|
-
|
|
3
|
-
This file is a concatenation of all individual *llm.txt files found in the 'common' directory tree. Each section below corresponds to a specific directory's summary file.
|
|
4
|
-
|
|
5
|
-
================================================================================
|
|
6
|
-
|
|
7
|
-
## Section 1: solace_agent_mesh/common/a2a/a2a_llm.txt
|
|
8
|
-
|
|
9
|
-
**Source file:** `solace_agent_mesh/common/a2a/a2a_llm.txt`
|
|
10
|
-
|
|
11
|
-
# DEVELOPER GUIDE: a2a
|
|
12
|
-
|
|
13
|
-
## Quick Summary
|
|
14
|
-
The `a2a` directory provides a comprehensive abstraction layer for the A2A (Agent-to-Agent) protocol, offering helper functions for creating, consuming, and translating A2A protocol objects. It acts as a facade that insulates applications from the specifics of the underlying a2a-sdk, providing simplified interfaces for messages, artifacts, tasks, events, and protocol-level operations.
|
|
15
|
-
|
|
16
|
-
## Files Overview
|
|
17
|
-
- `__init__.py` - Main entry point exposing all commonly used A2A helpers
|
|
18
|
-
- `artifact.py` - Helpers for creating and consuming A2A Artifact objects
|
|
19
|
-
- `events.py` - Helpers for creating and consuming A2A asynchronous event objects
|
|
20
|
-
- `message.py` - Helpers for creating and consuming A2A Message and Part objects
|
|
21
|
-
- `protocol.py` - Helpers for A2A protocol-level concerns like topic construction and JSON-RPC
|
|
22
|
-
- `task.py` - Helpers for creating and consuming A2A Task objects
|
|
23
|
-
- `translation.py` - Helpers for translating between A2A protocol objects and other domains
|
|
24
|
-
- `types.py` - Custom type aliases and models for the A2A helper layer
|
|
25
|
-
|
|
26
|
-
## Developer API Reference
|
|
27
|
-
|
|
28
|
-
### __init__.py
|
|
29
|
-
**Purpose:** Main entry point that exposes all commonly used A2A helpers for easy access
|
|
30
|
-
**Import:** `from solace_agent_mesh.common.a2a import *`
|
|
31
|
-
|
|
32
|
-
This file re-exports all public functions from the other modules, allowing developers to import everything from the main package.
|
|
33
|
-
|
|
34
|
-
### artifact.py
|
|
35
|
-
**Purpose:** Provides helpers for creating and consuming A2A Artifact objects
|
|
36
|
-
**Import:** `from solace_agent_mesh.common.a2a.artifact import create_text_artifact, create_data_artifact, get_artifact_id`
|
|
37
|
-
|
|
38
|
-
**Functions:**
|
|
39
|
-
- `create_text_artifact(name: str, text: str, description: str = "", artifact_id: Optional[str] = None) -> Artifact` - Creates a new Artifact containing a single TextPart
|
|
40
|
-
- `create_data_artifact(name: str, data: dict[str, Any], description: str = "", artifact_id: Optional[str] = None) -> Artifact` - Creates a new Artifact containing a single DataPart
|
|
41
|
-
- `update_artifact_parts(artifact: Artifact, new_parts: List[ContentPart]) -> Artifact` - Returns a new Artifact with replaced parts
|
|
42
|
-
- `prepare_file_part_for_publishing(part: FilePart, mode: str, artifact_service: "BaseArtifactService", user_id: str, session_id: str, target_agent_name: str, log_identifier: str) -> Optional[FilePart]` - Prepares a FilePart for publishing based on the artifact handling mode
|
|
43
|
-
- `resolve_file_part_uri(part: FilePart, artifact_service: "BaseArtifactService", log_identifier: str) -> FilePart` - Resolves an artifact URI within a FilePart into embedded bytes
|
|
44
|
-
- `get_artifact_id(artifact: Artifact) -> str` - Safely retrieves the ID from an Artifact
|
|
45
|
-
- `get_artifact_name(artifact: Artifact) -> Optional[str]` - Safely retrieves the name from an Artifact
|
|
46
|
-
- `get_parts_from_artifact(artifact: Artifact) -> List[ContentPart]` - Extracts unwrapped content parts from an Artifact
|
|
47
|
-
|
|
48
|
-
**Usage Examples:**
|
|
49
|
-
```python
|
|
50
|
-
from solace_agent_mesh.common.a2a.artifact import create_text_artifact, get_artifact_id
|
|
51
|
-
|
|
52
|
-
# Create a text artifact
|
|
53
|
-
artifact = create_text_artifact(
|
|
54
|
-
name="My Document",
|
|
55
|
-
text="This is the content of my document",
|
|
56
|
-
description="A sample text document"
|
|
57
|
-
)
|
|
58
|
-
|
|
59
|
-
# Get artifact ID
|
|
60
|
-
artifact_id = get_artifact_id(artifact)
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
### events.py
|
|
64
|
-
**Purpose:** Provides helpers for creating and consuming A2A asynchronous event objects
|
|
65
|
-
**Import:** `from solace_agent_mesh.common.a2a.events import create_status_update, create_artifact_update`
|
|
66
|
-
|
|
67
|
-
**Functions:**
|
|
68
|
-
- `create_data_signal_event(task_id: str, context_id: str, signal_data: SignalData, agent_name: str, part_metadata: Optional[Dict[str, Any]] = None) -> TaskStatusUpdateEvent` - Creates a TaskStatusUpdateEvent from signal data
|
|
69
|
-
- `create_status_update(task_id: str, context_id: str, message: Message, is_final: bool = False, metadata: Optional[Dict[str, Any]] = None) -> TaskStatusUpdateEvent` - Creates a new TaskStatusUpdateEvent
|
|
70
|
-
- `create_artifact_update(task_id: str, context_id: str, artifact: Artifact, append: bool = False, last_chunk: bool = False, metadata: Optional[Dict[str, Any]] = None) -> TaskArtifactUpdateEvent` - Creates a new TaskArtifactUpdateEvent
|
|
71
|
-
- `get_message_from_status_update(event: TaskStatusUpdateEvent) -> Optional[Message]` - Extracts Message from TaskStatusUpdateEvent
|
|
72
|
-
- `get_data_parts_from_status_update(event: TaskStatusUpdateEvent) -> List[DataPart]` - Extracts DataPart objects from status update
|
|
73
|
-
- `get_artifact_from_artifact_update(event: TaskArtifactUpdateEvent) -> Optional[Artifact]` - Extracts Artifact from TaskArtifactUpdateEvent
|
|
74
|
-
|
|
75
|
-
**Usage Examples:**
|
|
76
|
-
```python
|
|
77
|
-
from solace_agent_mesh.common.a2a.events import create_status_update
|
|
78
|
-
from solace_agent_mesh.common.a2a.message import create_agent_text_message
|
|
79
|
-
|
|
80
|
-
# Create a status update event
|
|
81
|
-
message = create_agent_text_message("Processing your request...")
|
|
82
|
-
status_event = create_status_update(
|
|
83
|
-
task_id="task-123",
|
|
84
|
-
context_id="context-456",
|
|
85
|
-
message=message,
|
|
86
|
-
is_final=False
|
|
87
|
-
)
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
### message.py
|
|
91
|
-
**Purpose:** Provides helpers for creating and consuming A2A Message and Part objects
|
|
92
|
-
**Import:** `from solace_agent_mesh.common.a2a.message import create_agent_text_message, create_text_part, get_text_from_message`
|
|
93
|
-
|
|
94
|
-
**Functions:**
|
|
95
|
-
- `create_agent_text_message(text: str, task_id: Optional[str] = None, context_id: Optional[str] = None, message_id: Optional[str] = None) -> Message` - Creates agent message with TextPart
|
|
96
|
-
- `create_agent_data_message(data: dict[str, Any], task_id: Optional[str] = None, context_id: Optional[str] = None, message_id: Optional[str] = None, part_metadata: Optional[Dict[str, Any]] = None) -> Message` - Creates agent message with DataPart
|
|
97
|
-
- `create_agent_parts_message(parts: List[ContentPart], task_id: Optional[str] = None, context_id: Optional[str] = None, message_id: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None) -> Message` - Creates agent message with multiple parts
|
|
98
|
-
- `create_user_message(parts: List[ContentPart], task_id: Optional[str] = None, context_id: Optional[str] = None, message_id: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None) -> Message` - Creates user message with multiple parts
|
|
99
|
-
- `create_text_part(text: str, metadata: Optional[Dict[str, Any]] = None) -> TextPart` - Creates a TextPart object
|
|
100
|
-
- `create_file_part_from_uri(uri: str, name: Optional[str] = None, mime_type: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None) -> FilePart` - Creates FilePart from URI
|
|
101
|
-
- `create_file_part_from_bytes(content_bytes: bytes, name: Optional[str] = None, mime_type: Optional[str] = None, metadata: Optional[Dict[str, Any]] = None) -> FilePart` - Creates FilePart from bytes
|
|
102
|
-
- `create_data_part(data: Dict[str, Any], metadata: Optional[Dict[str, Any]] = None) -> DataPart` - Creates a DataPart object
|
|
103
|
-
- `update_message_parts(message: Message, new_parts: List[ContentPart]) -> Message` - Returns a new Message with replaced parts
|
|
104
|
-
- `get_text_from_message(message: Message, delimiter: str = "\n") -> str` - Extracts and joins all text content from Message
|
|
105
|
-
- `get_data_parts_from_message(message: Message) -> List[DataPart]` - Extracts DataPart objects from Message
|
|
106
|
-
- `get_file_parts_from_message(message: Message) -> List[FilePart]` - Extracts FilePart objects from Message
|
|
107
|
-
- `get_message_id(message: Message) -> str` - Gets message ID
|
|
108
|
-
- `get_context_id(message: Message) -> Optional[str]` - Gets context ID
|
|
109
|
-
- `get_task_id(message: Message) -> Optional[str]` - Gets task ID
|
|
110
|
-
- `get_parts_from_message(message: Message) -> List[ContentPart]` - Extracts unwrapped content parts from Message
|
|
111
|
-
- `get_text_from_text_part(part: TextPart) -> str` - Gets text from TextPart
|
|
112
|
-
- `get_data_from_data_part(part: DataPart) -> Dict[str, Any]` - Gets data from DataPart
|
|
113
|
-
- `get_metadata_from_part(part: ContentPart) -> Optional[Dict[str, Any]]` - Gets metadata from any Part
|
|
114
|
-
- `get_file_from_file_part(part: FilePart) -> Optional[Union[FileWithUri, FileWithBytes]]` - Gets File object from FilePart
|
|
115
|
-
- `get_uri_from_file_part(part: FilePart) -> Optional[str]` - Gets URI from FilePart
|
|
116
|
-
- `get_bytes_from_file_part(part: FilePart) -> Optional[bytes]` - Gets decoded bytes from FilePart
|
|
117
|
-
- `get_filename_from_file_part(part: FilePart) -> Optional[str]` - Gets filename from FilePart
|
|
118
|
-
- `get_mimetype_from_file_part(part: FilePart) -> Optional[str]` - Gets MIME type from FilePart
|
|
119
|
-
|
|
120
|
-
**Usage Examples:**
|
|
121
|
-
```python
|
|
122
|
-
from solace_agent_mesh.common.a2a.message import create_agent_text_message, create_text_part, create_user_message
|
|
123
|
-
|
|
124
|
-
# Create a simple text message
|
|
125
|
-
message = create_agent_text_message(
|
|
126
|
-
text="Hello, how can I help you?",
|
|
127
|
-
task_id="task-123",
|
|
128
|
-
context_id="context-456"
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
# Create a user message with multiple parts
|
|
132
|
-
text_part = create_text_part("Please analyze this data:")
|
|
133
|
-
data_part = create_data_part({"values": [1, 2, 3, 4, 5]})
|
|
134
|
-
user_message = create_user_message(
|
|
135
|
-
parts=[text_part, data_part],
|
|
136
|
-
task_id="task-123"
|
|
137
|
-
)
|
|
138
|
-
```
|
|
139
|
-
|
|
140
|
-
### protocol.py
|
|
141
|
-
**Purpose:** Provides helpers for A2A protocol-level concerns like topic construction and JSON-RPC
|
|
142
|
-
**Import:** `from solace_agent_mesh.common.a2a.protocol import get_agent_request_topic, create_send_message_request`
|
|
143
|
-
|
|
144
|
-
**Constants/Variables:**
|
|
145
|
-
- `A2A_VERSION: str` - Current A2A protocol version ("v1")
|
|
146
|
-
- `A2A_BASE_PATH: str` - Base path for A2A topics ("a2a/v1")
|
|
147
|
-
|
|
148
|
-
**Functions:**
|
|
149
|
-
- `get_a2a_base_topic(namespace: str) -> str` - Returns base topic prefix for A2A communication
|
|
150
|
-
- `get_discovery_topic(namespace: str) -> str` - Returns topic for agent card discovery
|
|
151
|
-
- `get_agent_request_topic(namespace: str, agent_name: str) -> str` - Returns topic for sending requests to specific agent
|
|
152
|
-
- `get_gateway_status_topic(namespace: str, gateway_id: str, task_id: str) -> str` - Returns topic for publishing status updates to gateway
|
|
153
|
-
- `get_gateway_response_topic(namespace: str, gateway_id: str, task_id: str) -> str` - Returns topic for publishing final response to gateway
|
|
154
|
-
- `get_gateway_status_subscription_topic(namespace: str, self_gateway_id: str) -> str` - Returns wildcard topic for gateway to receive status updates
|
|
155
|
-
- `get_gateway_response_subscription_topic(namespace: str, self_gateway_id: str) -> str` - Returns wildcard topic for gateway to receive responses
|
|
156
|
-
- `get_peer_agent_status_topic(namespace: str, delegating_agent_name: str, sub_task_id: str) -> str` - Returns topic for publishing status to delegating agent
|
|
157
|
-
- `get_agent_response_topic(namespace: str, delegating_agent_name: str, sub_task_id: str) -> str` - Returns topic for publishing response to delegating agent
|
|
158
|
-
- `get_agent_response_subscription_topic(namespace: str, self_agent_name: str) -> str` - Returns wildcard topic for agent to receive responses
|
|
159
|
-
- `get_agent_status_subscription_topic(namespace: str, self_agent_name: str) -> str` - Returns wildcard topic for agent to receive status updates
|
|
160
|
-
- `get_client_response_topic(namespace: str, client_id: str) -> str` - Returns topic for publishing response to client
|
|
161
|
-
- `get_client_status_topic(namespace: str, client_id: str, task_id: str) -> str` - Returns topic for publishing status to client
|
|
162
|
-
- `get_client_status_subscription_topic(namespace: str, client_id: str) -> str` - Returns wildcard topic for client to receive status
|
|
163
|
-
- `create_send_message_request(message: Message, task_id: str, metadata: Optional[Dict[str, Any]] = None) -> SendMessageRequest` - Creates SendMessageRequest object
|
|
164
|
-
- `create_send_streaming_message_request(message: Message, task_id: str, metadata: Optional[Dict[str, Any]] = None) -> SendStreamingMessageRequest` - Creates SendStreamingMessageRequest object
|
|
165
|
-
- `create_success_response(result: Any, request_id: Optional[Union[str, int]]) -> JSONRPCResponse` - Creates successful JSON-RPC response
|
|
166
|
-
- `create_internal_error_response(message: str, request_id: Optional[Union[str, int]], data: Optional[Dict[str, Any]] = None) -> JSONRPCResponse` - Creates internal error response
|
|
167
|
-
- `create_invalid_request_error_response(message: str, request_id: Optional[Union[str, int]], data: Optional[Any] = None) -> JSONRPCResponse` - Creates invalid request error response
|
|
168
|
-
- `create_cancel_task_request(task_id: str) -> CancelTaskRequest` - Creates CancelTaskRequest object
|
|
169
|
-
- `get_request_id(request: A2ARequest) -> str | int` - Gets JSON-RPC request ID
|
|
170
|
-
- `get_request_method(request: A2ARequest) -> str` - Gets JSON-RPC method name
|
|
171
|
-
- `get_message_from_send_request(request: A2ARequest) -> Optional[Message]` - Gets Message from send request
|
|
172
|
-
- `get_task_id_from_cancel_request(request: A2ARequest) -> Optional[str]` - Gets task ID from cancel request
|
|
173
|
-
- `get_response_id(response: JSONRPCResponse) -> Optional[Union[str, int]]` - Gets response ID
|
|
174
|
-
- `get_response_result(response: JSONRPCResponse) -> Optional[Any]` - Gets response result
|
|
175
|
-
- `get_response_error(response: JSONRPCResponse) -> Optional[JSONRPCError]` - Gets response error
|
|
176
|
-
- `topic_matches_subscription(topic: str, subscription: str) -> bool` - Checks if topic matches Solace subscription pattern
|
|
177
|
-
- `subscription_to_regex(subscription: str) -> str` - Converts Solace subscription to regex
|
|
178
|
-
- `extract_task_id_from_topic(topic: str, subscription_pattern: str, log_identifier: str) -> Optional[str]` - Extracts task ID from topic
|
|
179
|
-
|
|
180
|
-
**Usage Examples:**
|
|
181
|
-
```python
|
|
182
|
-
from solace_agent_mesh.common.a2a.protocol import get_agent_request_topic, create_send_message_request
|
|
183
|
-
from solace_agent_mesh.common.a2a.message import create_agent_text_message
|
|
184
|
-
|
|
185
|
-
# Get topic for sending request to an agent
|
|
186
|
-
topic = get_agent_request_topic("my-namespace", "my-agent")
|
|
187
|
-
|
|
188
|
-
# Create a send message request
|
|
189
|
-
message = create_agent_text_message("Hello agent!")
|
|
190
|
-
request = create_sen
|
|
191
|
-
|
|
192
|
-
================================================================================
|
|
193
|
-
|
|
194
|
-
## Section 2: solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt
|
|
195
|
-
|
|
196
|
-
**Source file:** `solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt`
|
|
197
|
-
|
|
198
|
-
# DEVELOPER GUIDE: a2a_spec
|
|
199
|
-
|
|
200
|
-
## Quick Summary
|
|
201
|
-
The `a2a_spec` directory contains the complete Agent-to-Agent (A2A) communication specification for the Solace Agent Mesh. It includes the main JSON schema definition (`a2a.json`) that defines all data structures, request/response types, and error codes for agent communication, plus a `schemas/` subdirectory containing specialized validation schemas for various agent signals and progress updates. Together, these provide a comprehensive framework for validating and implementing compliant agent-to-agent communication.
|
|
202
|
-
|
|
203
|
-
## Files and Subdirectories Overview
|
|
204
|
-
- **Direct files:**
|
|
205
|
-
- `a2a.json` - Complete JSON Schema specification for A2A protocol including all data types, requests, responses, and error definitions
|
|
206
|
-
- `a2a_spec_llm.txt` - Developer guide documentation for the A2A specification
|
|
207
|
-
- **Subdirectories:**
|
|
208
|
-
- `schemas/` - JSON Schema definitions for agent communication signals (progress updates, tool invocations, LLM calls, artifact creation)
|
|
209
|
-
|
|
210
|
-
## Developer API Reference
|
|
211
|
-
|
|
212
|
-
### Direct Files
|
|
213
|
-
|
|
214
|
-
#### a2a.json
|
|
215
|
-
**Purpose:** Complete JSON Schema specification defining the Agent-to-Agent communication protocol
|
|
216
|
-
**Import:** This is a JSON Schema file, typically loaded for validation purposes
|
|
217
|
-
|
|
218
|
-
**Key Schema Definitions:**
|
|
219
|
-
- **AgentCard** - Self-describing manifest for agents with capabilities, skills, and endpoints
|
|
220
|
-
- **Message** - Individual messages in agent conversations with parts (text, files, data)
|
|
221
|
-
- **Task** - Stateful operations/conversations between clients and agents
|
|
222
|
-
- **A2ARequest/A2AResponse** - All supported JSON-RPC request and response types
|
|
223
|
-
- **Security Schemes** - OAuth2, API Key, mTLS, and other authentication methods
|
|
224
|
-
- **Error Types** - Standard JSON-RPC and A2A-specific error definitions
|
|
225
|
-
|
|
226
|
-
**Core Data Structures:**
|
|
227
|
-
```typescript
|
|
228
|
-
// Agent Card - describes agent capabilities
|
|
229
|
-
AgentCard {
|
|
230
|
-
name: string
|
|
231
|
-
description: string
|
|
232
|
-
url: string
|
|
233
|
-
skills: AgentSkill[]
|
|
234
|
-
capabilities: AgentCapabilities
|
|
235
|
-
security: SecurityRequirement[]
|
|
236
|
-
// ... additional fields
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// Message - conversation content
|
|
240
|
-
Message {
|
|
241
|
-
messageId: string
|
|
242
|
-
role: "user" | "agent"
|
|
243
|
-
parts: Part[] // TextPart | FilePart | DataPart
|
|
244
|
-
taskId?: string
|
|
245
|
-
contextId?: string
|
|
246
|
-
}
|
|
247
|
-
|
|
248
|
-
// Task - stateful operation
|
|
249
|
-
Task {
|
|
250
|
-
id: string
|
|
251
|
-
contextId: string
|
|
252
|
-
status: TaskStatus
|
|
253
|
-
history?: Message[]
|
|
254
|
-
artifacts?: Artifact[]
|
|
255
|
-
}
|
|
256
|
-
```
|
|
257
|
-
|
|
258
|
-
#### a2a_spec_llm.txt
|
|
259
|
-
**Purpose:** Developer documentation and usage guide for the A2A specification
|
|
260
|
-
**Import:** Documentation file for reference
|
|
261
|
-
|
|
262
|
-
### Subdirectory APIs
|
|
263
|
-
|
|
264
|
-
#### schemas/
|
|
265
|
-
**Purpose:** Provides JSON Schema definitions for agent communication signals and progress updates
|
|
266
|
-
**Key Exports:** Schema definitions for progress tracking, tool invocations, LLM calls, and artifact creation
|
|
267
|
-
**Import Examples:**
|
|
268
|
-
```python
|
|
269
|
-
import json
|
|
270
|
-
from jsonschema import validate
|
|
271
|
-
|
|
272
|
-
# Load and use schemas for validation
|
|
273
|
-
with open('solace_agent_mesh/common/a2a_spec/schemas/agent_progress_update.json') as f:
|
|
274
|
-
progress_schema = json.load(f)
|
|
275
|
-
```
|
|
276
|
-
|
|
277
|
-
**Available Schemas:**
|
|
278
|
-
- `agent_progress_update.json` - General progress status messages
|
|
279
|
-
- `artifact_creation_progress.json` - File/artifact creation tracking with chunked data
|
|
280
|
-
- `llm_invocation.json` - LLM model invocation signals
|
|
281
|
-
- `tool_invocation_start.json` - Tool execution start notifications
|
|
282
|
-
- `tool_result.json` - Tool execution completion results
|
|
283
|
-
|
|
284
|
-
## Complete Usage Guide
|
|
285
|
-
|
|
286
|
-
### 1. Loading and Using the A2A Schema
|
|
287
|
-
|
|
288
|
-
```python
|
|
289
|
-
import json
|
|
290
|
-
from jsonschema import validate, Draft7Validator
|
|
291
|
-
|
|
292
|
-
# Load the main A2A schema
|
|
293
|
-
with open('solace_agent_mesh/common/a2a_spec/a2a.json') as f:
|
|
294
|
-
a2a_schema = json.load(f)
|
|
295
|
-
|
|
296
|
-
# Create validator for specific types
|
|
297
|
-
def validate_agent_card(card_data):
|
|
298
|
-
"""Validate an AgentCard against the schema"""
|
|
299
|
-
card_schema = a2a_schema['definitions']['AgentCard']
|
|
300
|
-
validate(instance=card_data, schema=card_schema)
|
|
301
|
-
|
|
302
|
-
def validate_message(message_data):
|
|
303
|
-
"""Validate a Message against the schema"""
|
|
304
|
-
message_schema = a2a_schema['definitions']['Message']
|
|
305
|
-
validate(instance=message_data, schema=message_schema)
|
|
306
|
-
|
|
307
|
-
def validate_request(request_data):
|
|
308
|
-
"""Validate an A2A request"""
|
|
309
|
-
request_schema = a2a_schema['definitions']['A2ARequest']
|
|
310
|
-
validate(instance=request_data, schema=request_schema)
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
### 2. Creating Valid A2A Data Structures
|
|
314
|
-
|
|
315
|
-
```python
|
|
316
|
-
# Create a valid Message
|
|
317
|
-
message = {
|
|
318
|
-
"kind": "message",
|
|
319
|
-
"messageId": "msg-123",
|
|
320
|
-
"role": "user",
|
|
321
|
-
"parts": [
|
|
322
|
-
{
|
|
323
|
-
"kind": "text",
|
|
324
|
-
"text": "Hello, can you help me with a task?"
|
|
325
|
-
}
|
|
326
|
-
]
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
# Create a SendMessage request
|
|
330
|
-
send_request = {
|
|
331
|
-
"jsonrpc": "2.0",
|
|
332
|
-
"id": "req-456",
|
|
333
|
-
"method": "message/send",
|
|
334
|
-
"params": {
|
|
335
|
-
"message": message
|
|
336
|
-
}
|
|
337
|
-
}
|
|
338
|
-
|
|
339
|
-
# Validate the request
|
|
340
|
-
validate_request(send_request)
|
|
341
|
-
```
|
|
342
|
-
|
|
343
|
-
### 3. Using Agent Communication Schemas
|
|
344
|
-
|
|
345
|
-
```python
|
|
346
|
-
import json
|
|
347
|
-
from jsonschema import validate
|
|
348
|
-
|
|
349
|
-
# Load and validate progress update
|
|
350
|
-
with open('solace_agent_mesh/common/a2a_spec/schemas/agent_progress_update.json') as f:
|
|
351
|
-
progress_schema = json.load(f)
|
|
352
|
-
|
|
353
|
-
progress_update = {
|
|
354
|
-
"type": "agent_progress_update",
|
|
355
|
-
"status_text": "Processing your request..."
|
|
356
|
-
}
|
|
357
|
-
validate(instance=progress_update, schema=progress_schema)
|
|
358
|
-
|
|
359
|
-
# Load and validate tool invocation
|
|
360
|
-
with open('solace_agent_mesh/common/a2a_spec/schemas/tool_invocation_start.json') as f:
|
|
361
|
-
tool_schema = json.load(f)
|
|
362
|
-
|
|
363
|
-
tool_invocation = {
|
|
364
|
-
"type": "tool_invocation_start",
|
|
365
|
-
"tool_name": "file_reader",
|
|
366
|
-
"tool_args": {"filepath": "/data/file.txt"},
|
|
367
|
-
"function_call_id": "call_123"
|
|
368
|
-
}
|
|
369
|
-
validate(instance=tool_invocation, schema=tool_schema)
|
|
370
|
-
|
|
371
|
-
# Load and validate tool result
|
|
372
|
-
with open('solace_agent_mesh/common/a2a_spec/schemas/tool_result.json') as f:
|
|
373
|
-
result_schema = json.load(f)
|
|
374
|
-
|
|
375
|
-
tool_result = {
|
|
376
|
-
"type": "tool_result",
|
|
377
|
-
"tool_name": "file_reader",
|
|
378
|
-
"result_data": {"content": "File contents...", "size": 1024},
|
|
379
|
-
"function_call_id": "call_123"
|
|
380
|
-
}
|
|
381
|
-
validate(instance=tool_result, schema=result_schema)
|
|
382
|
-
```
|
|
383
|
-
|
|
384
|
-
### 4. Working with Agent Cards
|
|
385
|
-
|
|
386
|
-
```python
|
|
387
|
-
# Create a complete AgentCard
|
|
388
|
-
agent_card = {
|
|
389
|
-
"name": "Document Processor",
|
|
390
|
-
"description": "Agent that processes and analyzes documents",
|
|
391
|
-
"url": "https://api.example.com/agent",
|
|
392
|
-
"version": "1.0.0",
|
|
393
|
-
"protocolVersion": "0.3.0",
|
|
394
|
-
"capabilities": {
|
|
395
|
-
"streaming": True,
|
|
396
|
-
"pushNotifications": False,
|
|
397
|
-
"stateTransitionHistory": True
|
|
398
|
-
},
|
|
399
|
-
"defaultInputModes": ["text/plain", "application/pdf"],
|
|
400
|
-
"defaultOutputModes": ["text/plain", "application/json"],
|
|
401
|
-
"skills": [
|
|
402
|
-
{
|
|
403
|
-
"id": "document-analysis",
|
|
404
|
-
"name": "Document Analysis",
|
|
405
|
-
"description": "Analyze and extract information from documents",
|
|
406
|
-
"tags": ["document", "analysis", "extraction"]
|
|
407
|
-
}
|
|
408
|
-
]
|
|
409
|
-
}
|
|
410
|
-
|
|
411
|
-
# Validate the agent card
|
|
412
|
-
validate_agent_card(agent_card)
|
|
413
|
-
```
|
|
414
|
-
|
|
415
|
-
### 5. Artifact Creation Progress Tracking
|
|
416
|
-
|
|
417
|
-
```python
|
|
418
|
-
# Load artifact creation schema
|
|
419
|
-
with open('solace_agent_mesh/common/a2a_spec/schemas/artifact_creation_progress.json') as f:
|
|
420
|
-
artifact_schema = json.load(f)
|
|
421
|
-
|
|
422
|
-
# Track artifact creation with chunked data
|
|
423
|
-
artifact_progress = {
|
|
424
|
-
"type": "artifact_creation_progress",
|
|
425
|
-
"filename": "report.pdf",
|
|
426
|
-
"bytes_saved": 1024,
|
|
427
|
-
"artifact_chunk": "JVBERi0xLjQKJcOkw7zDtsO..." # Base64 encoded chunk
|
|
428
|
-
}
|
|
429
|
-
validate(instance=artifact_progress, schema=artifact_schema)
|
|
430
|
-
```
|
|
431
|
-
|
|
432
|
-
### 6. LLM Invocation Tracking
|
|
433
|
-
|
|
434
|
-
```python
|
|
435
|
-
# Load LLM invocation schema
|
|
436
|
-
with open('solace_agent_mesh/common/a2a_spec/schemas/llm_invocation.json') as f:
|
|
437
|
-
llm_schema = json.load(f)
|
|
438
|
-
|
|
439
|
-
# Track LLM calls
|
|
440
|
-
llm_invocation = {
|
|
441
|
-
"type": "llm_invocation",
|
|
442
|
-
"request": {
|
|
443
|
-
"model": "gpt-4",
|
|
444
|
-
"messages": [{"role": "user", "content": "Analyze this data"}],
|
|
445
|
-
"temperature": 0.7
|
|
446
|
-
}
|
|
447
|
-
}
|
|
448
|
-
validate(instance=llm_invocation, schema=llm_schema)
|
|
449
|
-
```
|
|
450
|
-
|
|
451
|
-
### 7. Complete Request/Response Flow with Progress Tracking
|
|
452
|
-
|
|
453
|
-
```python
|
|
454
|
-
# 1. Create and send a message
|
|
455
|
-
message = {
|
|
456
|
-
"kind": "message",
|
|
457
|
-
"messageId": "msg-001",
|
|
458
|
-
"role": "user",
|
|
459
|
-
"parts": [{"kind": "text", "text": "Analyze this document"}]
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
request = {
|
|
463
|
-
"jsonrpc": "2.0",
|
|
464
|
-
"id": "req-001",
|
|
465
|
-
"method": "message/send",
|
|
466
|
-
"params": {
|
|
467
|
-
"message": message,
|
|
468
|
-
"configuration": {
|
|
469
|
-
"blocking": False,
|
|
470
|
-
"acceptedOutputModes": ["text/plain", "application/json"]
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
# 2. Send progress updates during processing
|
|
476
|
-
def send_progress_update(status_text):
|
|
477
|
-
progress = {
|
|
478
|
-
"type": "agent_progress_update",
|
|
479
|
-
"status_text": status_text
|
|
480
|
-
}
|
|
481
|
-
# Validate and send progress update
|
|
482
|
-
validate(instance=progress, schema=progress_schema)
|
|
483
|
-
return progress
|
|
484
|
-
|
|
485
|
-
# 3. Track tool invocations
|
|
486
|
-
def track_tool_invocation(tool_name, args, call_id):
|
|
487
|
-
invocation = {
|
|
488
|
-
"type": "tool_invocation_start",
|
|
489
|
-
"tool_name": tool_name,
|
|
490
|
-
"tool_args": args,
|
|
491
|
-
"function_call_id": call_id
|
|
492
|
-
}
|
|
493
|
-
validate(instance=invocation, schema=tool_schema)
|
|
494
|
-
return invocation
|
|
495
|
-
|
|
496
|
-
# 4. Track tool results
|
|
497
|
-
def track_tool_result(tool_name, result_data, call_id):
|
|
498
|
-
result = {
|
|
499
|
-
"type": "tool_result",
|
|
500
|
-
"tool_name": tool_name,
|
|
501
|
-
"result_data": result_data,
|
|
502
|
-
"function_call_id": call_id
|
|
503
|
-
}
|
|
504
|
-
validate(instance=result, schema=result_schema)
|
|
505
|
-
return result
|
|
506
|
-
```
|
|
507
|
-
|
|
508
|
-
### 8. Comprehensive Schema Validation Utilities
|
|
509
|
-
|
|
510
|
-
```python
|
|
511
|
-
class A2AValidator:
|
|
512
|
-
"""Utility class for A2A schema validation"""
|
|
513
|
-
|
|
514
|
-
def __init__(self, schema_dir='solace_agent_mesh/common/a2a_spec'):
|
|
515
|
-
self.schema_dir = schema_dir
|
|
516
|
-
self.main_schema = self._load_main_schema()
|
|
517
|
-
self.signal_schemas = self._load_signal_schemas()
|
|
518
|
-
|
|
519
|
-
def _load_main_schema(self):
|
|
520
|
-
with open(f'{self.schema_dir}/a2a.json') as f:
|
|
521
|
-
return json.load(f)
|
|
522
|
-
|
|
523
|
-
def _load_signal_schemas(self):
|
|
524
|
-
schemas = {}
|
|
525
|
-
schema_files = [
|
|
526
|
-
'agent_progress_update.json',
|
|
527
|
-
'artifact_creation_progress.json',
|
|
528
|
-
'llm_invocation.json',
|
|
529
|
-
'tool_invocation_start.json',
|
|
530
|
-
'tool_result.json'
|
|
531
|
-
]
|
|
532
|
-
for filename in schema_files:
|
|
533
|
-
with open(f'{self.schema_dir}/schemas/{filename}') as f:
|
|
534
|
-
schema_name = filename.replace('.json', '')
|
|
535
|
-
schemas[schema_name] = json.load(f)
|
|
536
|
-
return schemas
|
|
537
|
-
|
|
538
|
-
def validate_definition(self, data, definition_name):
|
|
539
|
-
"""Validate data against a specific A2A definition"""
|
|
540
|
-
schema = self.main_schema['definitions'][definition_name]
|
|
541
|
-
validate(instance=data, schema=schema)
|
|
542
|
-
|
|
543
|
-
def validate_signal(self, data, signal_type):
|
|
544
|
-
"""Validate agent communication signal"""
|
|
545
|
-
schema = self.signal_schemas[signal_type]
|
|
546
|
-
validate(instance=data, schema=schema)
|
|
547
|
-
|
|
548
|
-
def validate_a2a_message(self, message_data):
|
|
549
|
-
"""Validate a complete A2A message"""
|
|
550
|
-
self.validate_definition(message_data, 'Message')
|
|
551
|
-
|
|
552
|
-
def validate_agent_card(self, card_data):
|
|
553
|
-
"""Validate an agent card"""
|
|
554
|
-
self.validate_definition(card_data, 'AgentCard')
|
|
555
|
-
|
|
556
|
-
def validate_task(self, task_data):
|
|
557
|
-
"""Validate a task object"""
|
|
558
|
-
self.validate_definition(task_data, 'Task')
|
|
559
|
-
|
|
560
|
-
# Usage example
|
|
561
|
-
validator = A2AValidator()
|
|
562
|
-
|
|
563
|
-
# Validate main A2A objects
|
|
564
|
-
validator.validate_agent_card(agent_card)
|
|
565
|
-
validator.validate_a2a_message(message)
|
|
566
|
-
|
|
567
|
-
# Validate communication signals
|
|
568
|
-
validator.validate_signal(progress_update, 'agent_progress_update')
|
|
569
|
-
validator.validate_signal(tool_invocation, 'tool_invocation_start')
|
|
570
|
-
validator.validate_signal(tool_result, 'tool_result')
|
|
571
|
-
validator.validate_signal(artifact_progress, 'artifact_creation_progress')
|
|
572
|
-
validator.validate_signal(llm_invocation, 'llm_invocation')
|
|
573
|
-
```
|
|
574
|
-
|
|
575
|
-
### 9. Error Handling with A2A Error Types
|
|
576
|
-
|
|
577
|
-
```python
|
|
578
|
-
# Create A2A-specific errors using the schema definitions
|
|
579
|
-
task_not_found_error = {
|
|
580
|
-
"code": -32001,
|
|
581
|
-
"message": "Task not found",
|
|
582
|
-
"data": {"taskId": "task-123"}
|
|
583
|
-
}
|
|
584
|
-
|
|
585
|
-
content_type_error = {
|
|
586
|
-
"code": -32005,
|
|
587
|
-
"message": "Incompatible content types",
|
|
588
|
-
"data": {"requested": "image/png", "supported": ["text/plain", "application/json"]}
|
|
589
|
-
}
|
|
590
|
-
|
|
591
|
-
# Create error response
|
|
592
|
-
error_response = {
|
|
593
|
-
"jsonrpc": "2.0",
|
|
594
|
-
"id": "req-456",
|
|
595
|
-
"error": task_not_found_error
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
# Validate error response
|
|
599
|
-
validator.validate_definition(error_response, 'JSONRPCErrorResponse')
|
|
600
|
-
```
|
|
601
|
-
|
|
602
|
-
This comprehensive guide shows how to use both the main A2A specification and the specialized signal schemas together to build compliant agent-to-agent communication systems in the Solace Agent Mesh, including progress tracking, tool invocation monitoring, LLM call tracking, and artifact creation progress.
|
|
603
|
-
|
|
604
|
-
================================================================================
|
|
605
|
-
|
|
606
|
-
## Section 3: solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt
|
|
607
|
-
|
|
608
|
-
**Source file:** `solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt`
|
|
609
|
-
|
|
610
|
-
# DEVELOPER GUIDE: schemas
|
|
611
|
-
|
|
612
|
-
## Quick Summary
|
|
613
|
-
This directory contains JSON Schema definitions for various agent-to-agent (A2A) communication signals in the Solace Agent Mesh. These schemas define the structure and validation rules for different types of progress updates, tool invocations, and LLM interactions that agents can send to each other.
|
|
614
|
-
|
|
615
|
-
## Files Overview
|
|
616
|
-
- `agent_progress_update.json` - Schema for general agent progress status messages
|
|
617
|
-
- `artifact_creation_progress.json` - Schema for tracking file/artifact creation progress with chunked data
|
|
618
|
-
- `llm_invocation.json` - Schema for LLM model invocation signals with usage tracking
|
|
619
|
-
- `tool_invocation_start.json` - Schema for tool execution start notifications
|
|
620
|
-
- `tool_result.json` - Schema for tool execution completion results with optional LLM usage
|
|
621
|
-
- `schemas_llm.txt` - Previous developer guide (legacy documentation)
|
|
622
|
-
|
|
623
|
-
## Developer API Reference
|
|
624
|
-
|
|
625
|
-
### agent_progress_update.json
|
|
626
|
-
**Purpose:** Defines the schema for agent progress update signals that communicate human-readable status messages between agents.
|
|
627
|
-
|
|
628
|
-
**Import:** Load as JSON schema for validation
|
|
629
|
-
```python
|
|
630
|
-
import json
|
|
631
|
-
from jsonschema import validate
|
|
632
|
-
```
|
|
633
|
-
|
|
634
|
-
**Schema Structure:**
|
|
635
|
-
```json
|
|
636
|
-
{
|
|
637
|
-
"type": "agent_progress_update",
|
|
638
|
-
"status_text": "string"
|
|
639
|
-
}
|
|
640
|
-
```
|
|
641
|
-
|
|
642
|
-
**Properties:**
|
|
643
|
-
- `type: "agent_progress_update"` - Constant identifier for this signal type (required)
|
|
644
|
-
- `status_text: string` - Human-readable progress message (required)
|
|
645
|
-
|
|
646
|
-
**Usage Examples:**
|
|
647
|
-
```python
|
|
648
|
-
import json
|
|
649
|
-
from jsonschema import validate
|
|
650
|
-
|
|
651
|
-
# Load and use schema
|
|
652
|
-
with open('solace_agent_mesh/common/a2a_spec/schemas/agent_progress_update.json') as f:
|
|
653
|
-
schema = json.load(f)
|
|
654
|
-
|
|
655
|
-
# Valid data example
|
|
656
|
-
data = {
|
|
657
|
-
"type": "agent_progress_update",
|
|
658
|
-
"status_text": "Analyzing the report..."
|
|
659
|
-
}
|
|
660
|
-
validate(instance=data, schema=schema)
|
|
661
|
-
```
|
|
662
|
-
|
|
663
|
-
### artifact_creation_progress.json
|
|
664
|
-
**Purpose:** Defines the schema for tracking progress during file or artifact creation operations with chunked data transfer.
|
|
665
|
-
|
|
666
|
-
**Import:** Load as JSON schema for validation
|
|
667
|
-
```python
|
|
668
|
-
import json
|
|
669
|
-
from jsonschema import validate
|
|
670
|
-
```
|
|
671
|
-
|
|
672
|
-
**Schema Structure:**
|
|
673
|
-
```json
|
|
674
|
-
{
|
|
675
|
-
"type": "artifact_creation_progress",
|
|
676
|
-
"filename": "string",
|
|
677
|
-
"bytes_saved": "integer",
|
|
678
|
-
"artifact_chunk": "string"
|
|
679
|
-
}
|
|
680
|
-
```
|
|
681
|
-
|
|
682
|
-
**Properties:**
|
|
683
|
-
- `type: "artifact_creation_progress"` - Constant identifier for this signal type (required)
|
|
684
|
-
- `filename: string` - Name of the artifact being created (required)
|
|
685
|
-
- `bytes_saved: integer` - Number of bytes saved so far (required)
|
|
686
|
-
- `artifact_chunk: string` - The chunk of artifact data that was saved in this update (required)
|
|
687
|
-
|
|
688
|
-
**Usage Examples:**
|
|
689
|
-
```python
|
|
690
|
-
import json
|
|
691
|
-
from jsonschema import validate
|
|
692
|
-
|
|
693
|
-
# Load and use schema
|
|
694
|
-
with open('solace_agent_mesh/common/a2a_spec/schemas/artifact_creation_progress.json') as f:
|
|
695
|
-
schema = json.load(f)
|
|
696
|
-
|
|
697
|
-
# Valid data example
|
|
698
|
-
data = {
|
|
699
|
-
"type": "artifact_creation_progress",
|
|
700
|
-
"filename": "report.pdf",
|
|
701
|
-
"bytes_saved": 1024,
|
|
702
|
-
"artifact_chunk": "JVBERi0xLjQKJcOkw7zDtsO..."
|
|
703
|
-
}
|
|
704
|
-
validate(instance=data, schema=schema)
|
|
705
|
-
```
|
|
706
|
-
|
|
707
|
-
### llm_invocation.json
|
|
708
|
-
**Purpose:** Defines the schema for LLM invocation signals that communicate when an agent is calling a language model, including token usage tracking.
|
|
709
|
-
|
|
710
|
-
**Import:** Load as JSON schema for validation
|
|
711
|
-
```python
|
|
712
|
-
import json
|
|
713
|
-
from jsonschema import validate
|
|
714
|
-
```
|
|
715
|
-
|
|
716
|
-
**Schema Structure:**
|
|
717
|
-
```json
|
|
718
|
-
{
|
|
719
|
-
"type": "llm_invocation",
|
|
720
|
-
"request": "object",
|
|
721
|
-
"usage": {
|
|
722
|
-
"input_tokens": "integer",
|
|
723
|
-
"output_tokens": "integer",
|
|
724
|
-
"cached_input_tokens": "integer",
|
|
725
|
-
"model": "string"
|
|
726
|
-
}
|
|
727
|
-
}
|
|
728
|
-
```
|
|
729
|
-
|
|
730
|
-
**Properties:**
|
|
731
|
-
- `type: "llm_invocation"` - Constant identifier for this signal type (required)
|
|
732
|
-
- `request: object` - Sanitized representation of the LlmRequest object sent to the model (required)
|
|
733
|
-
- `usage: object` - Token usage information for this LLM call (optional)
|
|
734
|
-
- `input_tokens: integer` - Number of input/prompt tokens (required in usage)
|
|
735
|
-
- `output_tokens: integer` - Number of output/completion tokens (required in usage)
|
|
736
|
-
- `cached_input_tokens: integer` - Number of cached input tokens (optional)
|
|
737
|
-
- `model: string` - Model identifier used for this call (required in usage)
|
|
738
|
-
|
|
739
|
-
**Usage Examples:**
|
|
740
|
-
```python
|
|
741
|
-
import json
|
|
742
|
-
from jsonschema import validate
|
|
743
|
-
|
|
744
|
-
# Load and use schema
|
|
745
|
-
with open('solace_agent_mesh/common/a2a_spec/schemas/llm_invocation.json') as f:
|
|
746
|
-
schema = json.load(f)
|
|
747
|
-
|
|
748
|
-
# Valid data example with usage tracking
|
|
749
|
-
data = {
|
|
750
|
-
"type": "llm_invocation",
|
|
751
|
-
"request": {
|
|
752
|
-
"model": "gpt-4",
|
|
753
|
-
"messages": [{"role": "user", "content": "Analyze this data"}],
|
|
754
|
-
"temperature": 0.7
|
|
755
|
-
},
|
|
756
|
-
"usage": {
|
|
757
|
-
"input_tokens": 150,
|
|
758
|
-
"output_tokens": 75,
|
|
759
|
-
"cached_input_tokens": 50,
|
|
760
|
-
"model": "gpt-4"
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
validate(instance=data, schema=schema)
|
|
764
|
-
```
|
|
765
|
-
|
|
766
|
-
### tool_invocation_start.json
|
|
767
|
-
**Purpose:** Defines the schema for tool invocation start signals that notify when an agent begins executing a tool.
|
|
768
|
-
|
|
769
|
-
**Import:** Load as JSON schema for validation
|
|
770
|
-
```python
|
|
771
|
-
import json
|
|
772
|
-
from jsonschema import validate
|
|
773
|
-
```
|
|
774
|
-
|
|
775
|
-
**Schema Structure:**
|
|
776
|
-
```json
|
|
777
|
-
{
|
|
778
|
-
"type": "tool_invocation_start",
|
|
779
|
-
"tool_name": "string",
|
|
780
|
-
"tool_args": "object",
|
|
781
|
-
"function_call_id": "string"
|
|
782
|
-
}
|
|
783
|
-
```
|
|
784
|
-
|
|
785
|
-
**Properties:**
|
|
786
|
-
- `type: "tool_invocation_start"` - Constant identifier for this signal type (required)
|
|
787
|
-
- `tool_name: string` - Name of the tool being called (required)
|
|
788
|
-
- `tool_args: object` - Arguments passed to the tool (required)
|
|
789
|
-
- `function_call_id: string` - ID from the LLM's function call (required)
|
|
790
|
-
|
|
791
|
-
**Usage Examples:**
|
|
792
|
-
```python
|
|
793
|
-
import json
|
|
794
|
-
from jsonschema import validate
|
|
795
|
-
|
|
796
|
-
# Load and use schema
|
|
797
|
-
with open('solace_agent_mesh/common/a2a_spec/schemas/tool_invocation_start.json') as f:
|
|
798
|
-
schema = json.load(f)
|
|
799
|
-
|
|
800
|
-
# Valid data example
|
|
801
|
-
data = {
|
|
802
|
-
"type": "tool_invocation_start",
|
|
803
|
-
"tool_name": "file_reader",
|
|
804
|
-
"tool_args": {
|
|
805
|
-
"filepath": "/path/to/file.txt",
|
|
806
|
-
"encoding": "utf-8"
|
|
807
|
-
},
|
|
808
|
-
"function_call_id": "call_abc123"
|
|
809
|
-
}
|
|
810
|
-
validate(instance=data, schema=schema)
|
|
811
|
-
```
|
|
812
|
-
|
|
813
|
-
### tool_result.json
|
|
814
|
-
**Purpose:** Defines the schema for tool execution result signals that communicate the completion and results of tool invocations, with optional LLM usage tracking.
|
|
815
|
-
|
|
816
|
-
**Import:** Load as JSON schema for validation
|
|
817
|
-
```python
|
|
818
|
-
import json
|
|
819
|
-
from jsonschema import validate
|
|
820
|
-
```
|
|
821
|
-
|
|
822
|
-
**Schema Structure:**
|
|
823
|
-
```json
|
|
824
|
-
{
|
|
825
|
-
"type": "tool_result",
|
|
826
|
-
"tool_name": "string",
|
|
827
|
-
"result_data": "any",
|
|
828
|
-
"function_call_id": "string",
|
|
829
|
-
"llm_usage": {
|
|
830
|
-
"input_tokens": "integer",
|
|
831
|
-
"output_tokens": "integer",
|
|
832
|
-
"cached_input_tokens": "integer",
|
|
833
|
-
"model": "string"
|
|
834
|
-
}
|
|
835
|
-
}
|
|
836
|
-
```
|
|
837
|
-
|
|
838
|
-
**Properties:**
|
|
839
|
-
- `type: "tool_result"` - Constant identifier for this signal type (required)
|
|
840
|
-
- `tool_name: string` - Name of the tool that was called (required)
|
|
841
|
-
- `result_data: any` - The data returned by the tool (required, can be any type)
|
|
842
|
-
- `function_call_id: string` - ID from the LLM's function call that this result corresponds to (required)
|
|
843
|
-
- `llm_usage: object` - Token usage if this tool made LLM calls (optional)
|
|
844
|
-
- `input_tokens: integer` - Total input tokens used by tool's LLM calls (required in llm_usage)
|
|
845
|
-
- `output_tokens: integer` - Total output tokens used by tool's LLM calls (required in llm_usage)
|
|
846
|
-
- `cached_input_tokens: integer` - Number of cached input tokens (optional)
|
|
847
|
-
- `model: string` - Model identifier(s) used by the tool (required in llm_usage)
|
|
848
|
-
|
|
849
|
-
**Usage Examples:**
|
|
850
|
-
```python
|
|
851
|
-
import json
|
|
852
|
-
from jsonschema import validate
|
|
853
|
-
|
|
854
|
-
# Load and use schema
|
|
855
|
-
with open('solace_agent_mesh/common/a2a_spec/schemas/tool_result.json') as f:
|
|
856
|
-
schema = json.load(f)
|
|
857
|
-
|
|
858
|
-
# Valid data example with LLM usage
|
|
859
|
-
data = {
|
|
860
|
-
"type": "tool_result",
|
|
861
|
-
"tool_name": "web_search",
|
|
862
|
-
"result_data": {
|
|
863
|
-
"results": ["Result 1", "Result 2"],
|
|
864
|
-
"count": 2
|
|
865
|
-
},
|
|
866
|
-
"function_call_id": "call_abc123",
|
|
867
|
-
"llm_usage": {
|
|
868
|
-
"input_tokens": 200,
|
|
869
|
-
"output_tokens": 100,
|
|
870
|
-
"model": "gpt-4"
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
validate(instance=data, schema=schema)
|
|
874
|
-
```
|
|
875
|
-
|
|
876
|
-
**Common Usage Pattern:**
|
|
877
|
-
```python
|
|
878
|
-
import json
|
|
879
|
-
from jsonschema import validate
|
|
880
|
-
from pathlib import Path
|
|
881
|
-
from typing import Dict, Any
|
|
882
|
-
|
|
883
|
-
def validate_a2a_signal(signal_data: Dict[str, Any], schema_name: str) -> bool:
|
|
884
|
-
"""Validate A2A signal data against its schema."""
|
|
885
|
-
schema_path = Path(f"solace_agent_mesh/common/a2a_spec/schemas/{schema_name}.json")
|
|
886
|
-
|
|
887
|
-
with open(schema_path) as f:
|
|
888
|
-
schema = json.load(f)
|
|
889
|
-
|
|
890
|
-
try:
|
|
891
|
-
validate(instance=signal_data, schema=schema)
|
|
892
|
-
return True
|
|
893
|
-
except Exception as e:
|
|
894
|
-
print(f"Validation failed: {e}")
|
|
895
|
-
return False
|
|
896
|
-
|
|
897
|
-
def load_schema(schema_name: str) -> Dict[str, Any]:
|
|
898
|
-
"""Load a specific A2A signal schema."""
|
|
899
|
-
schema_path = Path(f"solace_agent_mesh/common/a2a_spec/schemas/{schema_name}.json")
|
|
900
|
-
with open(schema_path) as f:
|
|
901
|
-
return json.load(f)
|
|
902
|
-
|
|
903
|
-
# Example usage
|
|
904
|
-
progress_data = {
|
|
905
|
-
"type": "agent_progress_update",
|
|
906
|
-
"status_text": "Processing request..."
|
|
907
|
-
}
|
|
908
|
-
|
|
909
|
-
if validate_a2a_signal(progress_data, "agent_progress_update"):
|
|
910
|
-
print("Signal is valid!")
|
|
911
|
-
|
|
912
|
-
# Load all schemas for batch validation
|
|
913
|
-
schemas = {
|
|
914
|
-
"agent_progress": load_schema("agent_progress_update"),
|
|
915
|
-
"artifact_progress": load_schema("artifact_creation_progress"),
|
|
916
|
-
"llm_invocation": load_schema("llm_invocation"),
|
|
917
|
-
"tool_start": load_schema("tool_invocation_start"),
|
|
918
|
-
"tool_result": load_schema("tool_result")
|
|
919
|
-
}
|
|
920
|
-
```
|
|
921
|
-
|
|
922
|
-
================================================================================
|
|
923
|
-
|
|
924
|
-
## Section 4: solace_agent_mesh/common/common_llm.txt
|
|
925
|
-
|
|
926
|
-
**Source file:** `solace_agent_mesh/common/common_llm.txt`
|
|
927
|
-
|
|
928
|
-
# DEVELOPER GUIDE: common
|
|
929
|
-
|
|
930
|
-
## Quick Summary
|
|
931
|
-
The `common` directory provides the foundational infrastructure for Agent-to-Agent (A2A) communication within the Solace Agent Mesh. It establishes the core protocol, data types, and message translation logic that underpins all interactions between AI agents and gateways.
|
|
932
|
-
|
|
933
|
-
The architecture is designed for clarity and extensibility. Core, low-level definitions are located in **direct files**:
|
|
934
|
-
- `types.py` defines the canonical data structures (e.g., `Message`, `Task`, `AgentCard`).
|
|
935
|
-
- `a2a_protocol.py` handles the construction of Solace topics and the translation between A2A and Google ADK message formats.
|
|
936
|
-
- `agent_registry.py` provides a simple, thread-safe mechanism for discovering and tracking available agents.
|
|
937
|
-
|
|
938
|
-
This foundation is then leveraged by specialized **subdirectories**, which provide higher-level, ready-to-use components:
|
|
939
|
-
- `client/`: A complete client library for discovering and interacting with remote agents.
|
|
940
|
-
- `server/`: A stand-alone server implementation for building A2A-compliant agents.
|
|
941
|
-
- `middleware/`: A pluggable framework for customizing configuration and feature access.
|
|
942
|
-
- `services/`: A factory-based system for integrating identity and other external data sources.
|
|
943
|
-
- `utils/`: A collection of cross-cutting utilities for caching, logging, and dynamic content processing.
|
|
944
|
-
|
|
945
|
-
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.
|
|
946
|
-
|
|
947
|
-
## Files and Subdirectories Overview
|
|
948
|
-
- **Direct files:**
|
|
949
|
-
- `__init__.py`: Package initialization file.
|
|
950
|
-
- `a2a_protocol.py`: Handles A2A topic construction and translation between A2A and ADK message formats.
|
|
951
|
-
- `agent_registry.py`: A thread-safe registry for managing discovered agent cards.
|
|
952
|
-
- `constants.py`: Common constants used across the system.
|
|
953
|
-
- `data_parts.py`: Pydantic models for structured data payloads used in A2A DataPart objects.
|
|
954
|
-
- `exceptions.py`: Custom exceptions for Solace Agent Mesh.
|
|
955
|
-
- `types.py`: Contains all Pydantic models for A2A protocol messages, tasks, and data structures.
|
|
956
|
-
- **Subdirectories:**
|
|
957
|
-
- `a2a/`: Comprehensive abstraction layer providing helper functions for creating, consuming, and translating A2A protocol objects.
|
|
958
|
-
- `a2a_spec/`: Complete JSON Schema specification for the A2A protocol.
|
|
959
|
-
- `client/`: Provides a high-level client for discovering and communicating with remote A2A agents.
|
|
960
|
-
- `middleware/`: A pluggable framework for configuration resolution and system extensibility.
|
|
961
|
-
- `sac/`: Base component framework for Solace Agent Mesh implementations in the Solace AI Connector.
|
|
962
|
-
- `sam_events/`: System-level event messaging for session lifecycle, agent health, and configuration changes.
|
|
963
|
-
- `server/`: A complete A2A server implementation with JSON-RPC support and task management.
|
|
964
|
-
- `services/`: Provides shared services like identity management using a factory pattern.
|
|
965
|
-
- `utils/`: Contains common utility functions and an embedded expression processing system.
|
|
966
|
-
|
|
967
|
-
## Developer API Reference
|
|
968
|
-
|
|
969
|
-
### Direct Files
|
|
970
|
-
|
|
971
|
-
#### a2a_protocol.py
|
|
972
|
-
**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.
|
|
973
|
-
**Import:** `from solace_agent_mesh.common.a2a_protocol import get_agent_request_topic, translate_a2a_to_adk_content`
|
|
974
|
-
|
|
975
|
-
**Classes/Functions/Constants:**
|
|
976
|
-
- **Constants**:
|
|
977
|
-
- `A2A_VERSION: str`: The current version of the A2A protocol (e.g., "v1").
|
|
978
|
-
- `A2A_BASE_PATH: str`: The base path used in all A2A topics (e.g., "a2a/v1").
|
|
979
|
-
- **Topic Construction Functions**:
|
|
980
|
-
- `get_a2a_base_topic(namespace: str) -> str`: Returns the base topic prefix for all A2A communication.
|
|
981
|
-
- `get_discovery_topic(namespace: str) -> str`: Returns the topic for agent card discovery.
|
|
982
|
-
- `get_agent_request_topic(namespace: str, agent_name: str) -> str`: Returns the topic for sending requests to a specific agent.
|
|
983
|
-
- `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.
|
|
984
|
-
- `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.
|
|
985
|
-
- `get_client_response_topic(namespace: str, client_id: str) -> str`: Returns the topic for publishing final responses to a specific client.
|
|
986
|
-
- `get_client_status_topic(namespace: str, client_id: str, task_id: str) -> str`: Returns the topic for publishing status updates to a specific client.
|
|
987
|
-
- **Message Translation Functions**:
|
|
988
|
-
- `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.
|
|
989
|
-
- `format_adk_event_as_a2a(...) -> Tuple[Optional[JSONRPCResponse], ...]`: Translates an ADK `Event` into an A2A `JSONRPCResponse` containing a `TaskStatusUpdateEvent`.
|
|
990
|
-
- `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.
|
|
991
|
-
|
|
992
|
-
#### agent_registry.py
|
|
993
|
-
**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.
|
|
994
|
-
**Import:** `from solace_agent_mesh.common.agent_registry import AgentRegistry`
|
|
995
|
-
|
|
996
|
-
**Classes/Functions/Constants:**
|
|
997
|
-
- **`AgentRegistry`**: A thread-safe class for storing and managing agent cards.
|
|
998
|
-
- `add_or_update_agent(self, agent_card: AgentCard)`: Adds a new agent or updates an existing one.
|
|
999
|
-
- `get_agent(self, agent_name: str) -> Optional[AgentCard]`: Retrieves an agent card by its unique name.
|
|
1000
|
-
- `get_agent_names(self) -> List[str]`: Returns a sorted list of all discovered agent names.
|
|
1001
|
-
- `clear(self)`: Clears all agents from the registry.
|
|
1002
|
-
|
|
1003
|
-
#### constants.py
|
|
1004
|
-
**Purpose:** Defines common constants used throughout the Solace Agent Mesh system.
|
|
1005
|
-
**Import:** `from solace_agent_mesh.common.constants import DEFAULT_COMMUNICATION_TIMEOUT`
|
|
1006
|
-
|
|
1007
|
-
**Classes/Functions/Constants:**
|
|
1008
|
-
- `DEFAULT_COMMUNICATION_TIMEOUT: int`: Default timeout for communication operations (600 seconds / 10 minutes).
|
|
1009
|
-
- `TEXT_ARTIFACT_CONTEXT_MAX_LENGTH_CAPACITY: int`: Maximum number of characters that can be loaded from a text artifact (200,000).
|
|
1010
|
-
- `TEXT_ARTIFACT_CONTEXT_DEFAULT_LENGTH: int`: Default number of characters to load from a text artifact (100,000).
|
|
1011
|
-
|
|
1012
|
-
#### data_parts.py
|
|
1013
|
-
**Purpose:** Defines Pydantic models for structured data payloads used in A2A DataPart objects, corresponding to JSON schemas for agent communication signals.
|
|
1014
|
-
**Import:** `from solace_agent_mesh.common.data_parts import ToolInvocationStartData, LlmInvocationData`
|
|
1015
|
-
|
|
1016
|
-
**Classes/Functions/Constants:**
|
|
1017
|
-
- **`ToolInvocationStartData`**: Data model for tool invocation start signals.
|
|
1018
|
-
- `type: Literal["tool_invocation_start"]`: The constant type identifier.
|
|
1019
|
-
- `tool_name: str`: The name of the tool being called.
|
|
1020
|
-
- `tool_args: Dict[str, Any]`: The arguments passed to the tool.
|
|
1021
|
-
- `function_call_id: str`: The ID from the LLM's function call.
|
|
1022
|
-
- **`LlmInvocationData`**: Data model for LLM invocation signals.
|
|
1023
|
-
- `type: Literal["llm_invocation"]`: The constant type identifier.
|
|
1024
|
-
- `request: Dict[str, Any]`: A sanitized representation of the LlmRequest object.
|
|
1025
|
-
- `usage: Optional[Dict[str, Any]]`: Token usage information for this LLM call.
|
|
1026
|
-
- **`AgentProgressUpdateData`**: Data model for agent progress update signals.
|
|
1027
|
-
- `type: Literal["agent_progress_update"]`: The constant type identifier.
|
|
1028
|
-
- `status_text: str`: A human-readable progress message.
|
|
1029
|
-
- **`ArtifactCreationProgressData`**: Data model for artifact creation progress signals.
|
|
1030
|
-
- `type: Literal["artifact_creation_progress"]`: The constant type identifier.
|
|
1031
|
-
- `filename: str`: The name of the artifact being created.
|
|
1032
|
-
- `bytes_saved: int`: The number of bytes saved so far.
|
|
1033
|
-
- `artifact_chunk: str`: The chunk of artifact data that was saved in this progress update.
|
|
1034
|
-
- **`ToolResultData`**: Data model for tool execution result signals.
|
|
1035
|
-
- `type: Literal["tool_result"]`: The constant type identifier.
|
|
1036
|
-
- `tool_name: str`: The name of the tool that was called.
|
|
1037
|
-
- `result_data: Any`: The data returned by the tool.
|
|
1038
|
-
- `function_call_id: str`: The ID from the LLM's function call.
|
|
1039
|
-
- `llm_usage: Optional[Dict[str, Any]]`: Token usage if this tool made LLM calls.
|
|
1040
|
-
|
|
1041
|
-
#### exceptions.py
|
|
1042
|
-
**Purpose:** Defines custom exceptions specific to the Solace Agent Mesh system.
|
|
1043
|
-
**Import:** `from solace_agent_mesh.common.exceptions import MessageSizeExceededError`
|
|
1044
|
-
|
|
1045
|
-
**Classes/Functions/Constants:**
|
|
1046
|
-
- **`MessageSizeExceededError(Exception)`**: Raised when a message exceeds the maximum allowed size.
|
|
1047
|
-
- `__init__(self, actual_size: int, max_size: int, message: str = None)`: Initialize with size information.
|
|
1048
|
-
- `actual_size: int`: The actual size of the message in bytes.
|
|
1049
|
-
- `max_size: int`: The maximum allowed size in bytes.
|
|
1050
|
-
|
|
1051
|
-
#### types.py
|
|
1052
|
-
**Purpose:** Defines all the Pydantic data models that constitute the A2A protocol. These types ensure data consistency and provide validation across all components.
|
|
1053
|
-
**Import:** `from solace_agent_mesh.common.types import Message, Task, AgentCard, JSONRPCRequest, TaskState`
|
|
1054
|
-
|
|
1055
|
-
**Classes/Functions/Constants:**
|
|
1056
|
-
- **Core Data Structures**:
|
|
1057
|
-
- `Message`: Represents a message from a user or agent, containing a list of `Part` objects.
|
|
1058
|
-
- `Part`: A discriminated union of `TextPart`, `FilePart`, and `DataPart`.
|
|
1059
|
-
- `Task`: The central object representing a complete task, including its ID, status, history, and artifacts.
|
|
1060
|
-
- `TaskStatus`: Describes the current state of a task (e.g., `WORKING`, `COMPLETED`).
|
|
1061
|
-
- `TaskState(Enum)`: An enumeration of all possible task states.
|
|
1062
|
-
- `AgentCard`: A comprehensive description of an agent's identity, capabilities, and skills.
|
|
1063
|
-
- `Artifact`: Represents a task output, such as a generated file or structured data.
|
|
1064
|
-
- **JSON-RPC Structures**:
|
|
1065
|
-
- `JSONRPCRequest`: The base model for all JSON-RPC requests.
|
|
1066
|
-
- `JSONRPCResponse`: The base model for all JSON-RPC responses.
|
|
1067
|
-
- `SendTaskRequest`, `GetTaskRequest`, etc.: Specific request types inheriting from `JSONRPCRequest`.
|
|
1068
|
-
- **Error Structures**:
|
|
1069
|
-
- `JSONRPCError`: The base model for errors.
|
|
1070
|
-
- `InternalError`, `TaskNotFoundError`, etc.: Specific error types inheriting from `JSONRPCError`.
|
|
1071
|
-
|
|
1072
|
-
### Subdirectory APIs
|
|
1073
|
-
|
|
1074
|
-
#### a2a/
|
|
1075
|
-
**Purpose:** Comprehensive abstraction layer providing helper functions for creating, consuming, and translating A2A protocol objects
|
|
1076
|
-
**Key Exports:** Helper functions for messages, tasks, artifacts, events, and protocol operations
|
|
1077
|
-
**Import Examples:**
|
|
1078
|
-
```python
|
|
1079
|
-
from solace_agent_mesh.common.a2a import create_agent_text_message, create_initial_task, translate_a2a_to_adk_content
|
|
1080
|
-
from solace_agent_mesh.common.a2a.message import create_text_part, get_text_from_message
|
|
1081
|
-
from solace_agent_mesh.common.a2a.protocol import get_agent_request_topic, create_send_message_request
|
|
1082
|
-
```
|
|
1083
|
-
|
|
1084
|
-
#### a2a_spec/
|
|
1085
|
-
**Purpose:** Contains the complete Agent-to-Agent (A2A) communication specification including JSON schema definitions
|
|
1086
|
-
**Key Exports:** JSON Schema specifications for A2A protocol and agent communication signals
|
|
1087
|
-
**Import Examples:**
|
|
1088
|
-
```python
|
|
1089
|
-
import json
|
|
1090
|
-
from jsonschema import validate
|
|
1091
|
-
|
|
1092
|
-
# Load main A2A schema
|
|
1093
|
-
with open('solace_agent_mesh/common/a2a_spec/a2a.json') as f:
|
|
1094
|
-
a2a_schema = json.load(f)
|
|
1095
|
-
```
|
|
1096
|
-
|
|
1097
|
-
#### client/
|
|
1098
|
-
**Purpose:** Provides a high-level, asynchronous client library for discovering and interacting with remote A2A agents.
|
|
1099
|
-
**Key Exports:** `A2AClient`, `A2ACardResolver`
|
|
1100
|
-
**Import Examples:**
|
|
1101
|
-
```python
|
|
1102
|
-
from solace_agent_mesh.common.client import A2AClient, A2ACardResolver
|
|
1103
|
-
```
|
|
1104
|
-
|
|
1105
|
-
#### middleware/
|
|
1106
|
-
**Purpose:** A pluggable middleware framework for customizing system behavior, such as resolving user-specific configurations and feature flags.
|
|
1107
|
-
**Key Exports:** `ConfigResolver`, `MiddlewareRegistry`
|
|
1108
|
-
**Import Examples:**
|
|
1109
|
-
```python
|
|
1110
|
-
from solace_agent_mesh.common.middleware import ConfigResolver, MiddlewareRegistry
|
|
1111
|
-
```
|
|
1112
|
-
|
|
1113
|
-
#### sac/
|
|
1114
|
-
**Purpose:** Base component framework for Solace Agent Mesh implementations in the Solace AI Connector with async operations management
|
|
1115
|
-
**Key Exports:** `SamComponentBase`
|
|
1116
|
-
**Import Examples:**
|
|
1117
|
-
```python
|
|
1118
|
-
from solace_agent_mesh.common.sac.sam_component_base import SamComponentBase
|
|
1119
|
-
```
|
|
1120
|
-
|
|
1121
|
-
#### sam_events/
|
|
1122
|
-
**Purpose:** System-level event messaging for session lifecycle, agent health, and configuration changes separate from A2A task communication
|
|
1123
|
-
**Key Exports:** `SamEventService`, `SamEvent`, `SessionDeletedEvent`
|
|
1124
|
-
**Import Examples:**
|
|
1125
|
-
```python
|
|
1126
|
-
from solace_agent_mesh.common.sam_events import SamEventService, SamEvent, SessionDeletedEvent
|
|
1127
|
-
```
|
|
1128
|
-
|
|
1129
|
-
#### server/
|
|
1130
|
-
**Purpose:** A complete, stand-alone server for building A2A-compliant agents, handling HTTP requests, JSON-RPC, and task lifecycle management.
|
|
1131
|
-
**Key Exports:** `A2AServer`, `TaskManager`, `InMemoryTaskManager`
|
|
1132
|
-
**Import Examples:**
|
|
1133
|
-
```python
|
|
1134
|
-
from solace_agent_mesh.common.server import A2AServer, TaskManager, InMemoryTaskManager
|
|
1135
|
-
```
|
|
1136
|
-
|
|
1137
|
-
#### services/
|
|
1138
|
-
**Purpose:** A factory-based system for integrating external data sources for identity, employee information, and more.
|
|
1139
|
-
**Key Exports:** `BaseIdentityService`, `create_identity_service`
|
|
1140
|
-
**Import Examples:**
|
|
1141
|
-
```python
|
|
1142
|
-
from solace_agent_mesh.common.services.identity_service import create_identity_service, BaseIdentityService
|
|
1143
|
-
```
|
|
1144
|
-
|
|
1145
|
-
#### utils/
|
|
1146
|
-
**Purpose:** A collection of cross-cutting utilities for caching, logging, MIME type handling, and dynamic content processing.
|
|
1147
|
-
**Key Exports:** `InMemoryCache`, `is_text_based_mime_type`, `resolve_embeds_in_string`
|
|
1148
|
-
**Import Examples:**
|
|
1149
|
-
```python
|
|
1150
|
-
from solace_agent_mesh.common.utils.in_memory_cache import InMemoryCache
|
|
1151
|
-
from solace_agent_mesh.common.utils import is_text_based_mime_type
|
|
1152
|
-
from solace_agent_mesh.common.utils.embeds import resolve_embeds_recursively_in_string
|
|
1153
|
-
```
|
|
1154
|
-
|
|
1155
|
-
## Complete Usage Guide
|
|
1156
|
-
|
|
1157
|
-
### 1. Basic A2A Protocol Usage
|
|
1158
|
-
This example shows how to use the core protocol functions and types to build A2A communication.
|
|
1159
|
-
|
|
1160
|
-
```python
|
|
1161
|
-
import uuid
|
|
1162
|
-
from datetime import datetime, timezone
|
|
1163
|
-
from solace_agent_mesh.common.a2a_protocol import (
|
|
1164
|
-
get_agent_request_topic,
|
|
1165
|
-
get_gateway_status_topic,
|
|
1166
|
-
translate_a2a_to_adk_content
|
|
1167
|
-
)
|
|
1168
|
-
from solace_agent_mesh.common.types import (
|
|
1169
|
-
Message,
|
|
1170
|
-
TextPart,
|
|
1171
|
-
Task,
|
|
1172
|
-
TaskStatus,
|
|
1173
|
-
TaskState,
|
|
1174
|
-
AgentCard
|
|
1175
|
-
)
|
|
1176
|
-
from solace_
|
|
1177
|
-
|
|
1178
|
-
================================================================================
|
|
1179
|
-
|
|
1180
|
-
## Section 5: solace_agent_mesh/common/middleware/middleware_llm.txt
|
|
1181
|
-
|
|
1182
|
-
**Source file:** `solace_agent_mesh/common/middleware/middleware_llm.txt`
|
|
1183
|
-
|
|
1184
|
-
# DEVELOPER GUIDE: middleware
|
|
1185
|
-
|
|
1186
|
-
## Quick Summary
|
|
1187
|
-
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.
|
|
1188
|
-
|
|
1189
|
-
## Files Overview
|
|
1190
|
-
- `__init__.py`: Exposes the main public classes of the middleware package for easy importing.
|
|
1191
|
-
- `config_resolver.py`: Defines the default, permissive configuration resolution middleware.
|
|
1192
|
-
- `registry.py`: Provides the `MiddlewareRegistry` for dynamically binding custom middleware implementations.
|
|
1193
|
-
|
|
1194
|
-
## Developer API Reference
|
|
1195
|
-
|
|
1196
|
-
### __init__.py
|
|
1197
|
-
**Purpose:** This file serves as the entry point to the `middleware` package, exporting the primary public interfaces for developers to use.
|
|
1198
|
-
|
|
1199
|
-
**Import:** `from solace_agent_mesh.common.middleware import ConfigResolver, MiddlewareRegistry`
|
|
1200
|
-
|
|
1201
|
-
**Usage Examples:**
|
|
1202
|
-
```python
|
|
1203
|
-
# Import the main classes directly from the middleware package
|
|
1204
|
-
from solace_agent_mesh.common.middleware import ConfigResolver, MiddlewareRegistry
|
|
1205
|
-
|
|
1206
|
-
# Now you can use ConfigResolver and MiddlewareRegistry
|
|
1207
|
-
print(ConfigResolver)
|
|
1208
|
-
print(MiddlewareRegistry)
|
|
1209
|
-
```
|
|
1210
|
-
|
|
1211
|
-
### config_resolver.py
|
|
1212
|
-
**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.
|
|
1213
|
-
|
|
1214
|
-
**Import:** `from solace_agent_mesh.common.middleware import ConfigResolver`
|
|
1215
|
-
|
|
1216
|
-
**Classes:**
|
|
1217
|
-
- `ConfigResolver()` - A class containing static methods to resolve user-specific configuration and determine feature availability. This default implementation is permissive.
|
|
1218
|
-
- `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.
|
|
1219
|
-
- `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`.
|
|
1220
|
-
- `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}`.
|
|
1221
|
-
- `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.
|
|
1222
|
-
|
|
1223
|
-
**Usage Examples:**
|
|
1224
|
-
```python
|
|
1225
|
-
import asyncio
|
|
1226
|
-
from solace_agent_mesh.common.middleware import ConfigResolver
|
|
1227
|
-
|
|
1228
|
-
async def main():
|
|
1229
|
-
# Example user identity and base configuration
|
|
1230
|
-
user_id = "test-user@example.com"
|
|
1231
|
-
base_conf = {"api_key": "default_key", "allowed_models": ["gpt-3.5-turbo"]}
|
|
1232
|
-
|
|
1233
|
-
# 1. Resolve user configuration (default implementation returns base_conf)
|
|
1234
|
-
user_config = await ConfigResolver.resolve_user_config(
|
|
1235
|
-
user_identity=user_id,
|
|
1236
|
-
gateway_context={"gateway_id": "gw-1"},
|
|
1237
|
-
base_config=base_conf
|
|
1238
|
-
)
|
|
1239
|
-
print(f"Resolved User Config: {user_config}")
|
|
1240
|
-
|
|
1241
|
-
# 2. Check if a feature is enabled (default is always True)
|
|
1242
|
-
feature_desc = {"feature_type": "ai_tool", "function_name": "code_interpreter"}
|
|
1243
|
-
is_enabled = ConfigResolver.is_feature_enabled(
|
|
1244
|
-
user_config=user_config,
|
|
1245
|
-
feature_descriptor=feature_desc,
|
|
1246
|
-
context={}
|
|
1247
|
-
)
|
|
1248
|
-
print(f"Is Feature Enabled: {is_enabled}")
|
|
1249
|
-
|
|
1250
|
-
# 3. Validate an operation (default is always valid)
|
|
1251
|
-
op_spec = {"operation_type": "model_inference", "model": "gpt-4"}
|
|
1252
|
-
validation = ConfigResolver.validate_operation_config(
|
|
1253
|
-
user_config=user_config,
|
|
1254
|
-
operation_spec=op_spec,
|
|
1255
|
-
validation_context={}
|
|
1256
|
-
)
|
|
1257
|
-
print(f"Operation Validation: {validation}")
|
|
1258
|
-
|
|
1259
|
-
# 4. Filter available options (default returns all options)
|
|
1260
|
-
all_models = [
|
|
1261
|
-
{"name": "gpt-3.5-turbo", "provider": "openai"},
|
|
1262
|
-
{"name": "gpt-4", "provider": "openai"},
|
|
1263
|
-
]
|
|
1264
|
-
available_models = ConfigResolver.filter_available_options(
|
|
1265
|
-
user_config=user_config,
|
|
1266
|
-
available_options=all_models,
|
|
1267
|
-
filter_context={"type": "language_model"}
|
|
1268
|
-
)
|
|
1269
|
-
print(f"Filtered Options: {available_models}")
|
|
1270
|
-
|
|
1271
|
-
if __name__ == "__main__":
|
|
1272
|
-
asyncio.run(main())
|
|
1273
|
-
```
|
|
1274
|
-
|
|
1275
|
-
### registry.py
|
|
1276
|
-
**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.
|
|
1277
|
-
|
|
1278
|
-
**Import:** `from solace_agent_mesh.common.middleware import MiddlewareRegistry`
|
|
1279
|
-
|
|
1280
|
-
**Classes:**
|
|
1281
|
-
- `MiddlewareRegistry()` - A registry for managing middleware implementations. All methods are class methods.
|
|
1282
|
-
- `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.
|
|
1283
|
-
- `get_config_resolver() -> Type` - Returns the currently bound `ConfigResolver` class. If no custom resolver has been bound, it returns the default `ConfigResolver`.
|
|
1284
|
-
- `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.
|
|
1285
|
-
- `initialize_middleware()` - Executes all registered initialization callbacks. This should be called once during application startup.
|
|
1286
|
-
- `reset_bindings()` - Resets all bindings back to their defaults. This is primarily useful for testing environments.
|
|
1287
|
-
- `get_registry_status() -> Dict[str, Any]` - Returns a dictionary containing the current status of the registry, such as which resolver is bound.
|
|
1288
|
-
|
|
1289
|
-
**Usage Examples:**
|
|
1290
|
-
```python
|
|
1291
|
-
import asyncio
|
|
1292
|
-
from typing import Any, Dict, List
|
|
1293
|
-
from solace_agent_mesh.common.middleware import MiddlewareRegistry, ConfigResolver
|
|
1294
|
-
|
|
1295
|
-
# 1. Define a custom ConfigResolver implementation
|
|
1296
|
-
class MyCustomConfigResolver:
|
|
1297
|
-
"""A custom resolver that only allows 'admin' users to use 'gpt-4'."""
|
|
1298
|
-
@staticmethod
|
|
1299
|
-
async def resolve_user_config(user_identity: Any, gateway_context: Dict[str, Any], base_config: Dict[str, Any]) -> Dict[str, Any]:
|
|
1300
|
-
if user_identity == "admin":
|
|
1301
|
-
return {"role": "admin", "allowed_models": ["gpt-4", "gpt-3.5-turbo"]}
|
|
1302
|
-
return {"role": "user", "allowed_models": ["gpt-3.5-turbo"]}
|
|
1303
|
-
|
|
1304
|
-
@staticmethod
|
|
1305
|
-
def validate_operation_config(user_config: Dict, operation_spec: Dict, validation_context: Dict) -> Dict:
|
|
1306
|
-
model = operation_spec.get("model")
|
|
1307
|
-
if model and model not in user_config.get("allowed_models", []):
|
|
1308
|
-
return {"valid": False, "reason": f"Model '{model}' not allowed for this user."}
|
|
1309
|
-
return {"valid": True}
|
|
1310
|
-
|
|
1311
|
-
# Inherit other methods from the default for simplicity
|
|
1312
|
-
is_feature_enabled = ConfigResolver.is_feature_enabled
|
|
1313
|
-
filter_available_options = ConfigResolver.filter_available_options
|
|
1314
|
-
|
|
1315
|
-
# 2. Define an initialization callback
|
|
1316
|
-
def setup_custom_logging():
|
|
1317
|
-
print("Custom middleware initialization logic is running!")
|
|
1318
|
-
|
|
1319
|
-
# 3. Bind the custom components
|
|
1320
|
-
MiddlewareRegistry.bind_config_resolver(MyCustomConfigResolver)
|
|
1321
|
-
MiddlewareRegistry.register_initialization_callback(setup_custom_logging)
|
|
1322
|
-
|
|
1323
|
-
# 4. Initialize the middleware (e.g., at application startup)
|
|
1324
|
-
print("--- Initializing Middleware ---")
|
|
1325
|
-
MiddlewareRegistry.initialize_middleware()
|
|
1326
|
-
print("--- Initialization Complete ---")
|
|
1327
|
-
|
|
1328
|
-
# 5. Use the middleware system
|
|
1329
|
-
async def check_permissions():
|
|
1330
|
-
# The registry will now use MyCustomConfigResolver automatically
|
|
1331
|
-
CurrentResolver = MiddlewareRegistry.get_config_resolver()
|
|
1332
|
-
print(f"Current resolver is: {CurrentResolver.__name__}")
|
|
1333
|
-
|
|
1334
|
-
# Check an admin user
|
|
1335
|
-
admin_config = await CurrentResolver.resolve_user_config("admin", {}, {})
|
|
1336
|
-
validation_result = CurrentResolver.validate_operation_config(
|
|
1337
|
-
admin_config, {"model": "gpt-4"}, {}
|
|
1338
|
-
)
|
|
1339
|
-
print(f"Admin validation for gpt-4: {validation_result}")
|
|
1340
|
-
|
|
1341
|
-
# Check a regular user
|
|
1342
|
-
user_config = await CurrentResolver.resolve_user_config("user", {}, {})
|
|
1343
|
-
validation_result = CurrentResolver.validate_operation_config(
|
|
1344
|
-
user_config, {"model": "gpt-4"}, {}
|
|
1345
|
-
)
|
|
1346
|
-
print(f"User validation for gpt-4: {validation_result}")
|
|
1347
|
-
|
|
1348
|
-
# Run the example
|
|
1349
|
-
asyncio.run(check_permissions())
|
|
1350
|
-
|
|
1351
|
-
# 6. Check status and reset (useful for testing)
|
|
1352
|
-
print(f"\nRegistry Status: {MiddlewareRegistry.get_registry_status()}")
|
|
1353
|
-
MiddlewareRegistry.reset_bindings()
|
|
1354
|
-
print(f"Registry Status after reset: {MiddlewareRegistry.get_registry_status()}")
|
|
1355
|
-
```
|
|
1356
|
-
|
|
1357
|
-
================================================================================
|
|
1358
|
-
|
|
1359
|
-
## Section 6: solace_agent_mesh/common/sac/sac_llm.txt
|
|
1360
|
-
|
|
1361
|
-
**Source file:** `solace_agent_mesh/common/sac/sac_llm.txt`
|
|
1362
|
-
|
|
1363
|
-
# DEVELOPER GUIDE: sac
|
|
1364
|
-
|
|
1365
|
-
## Quick Summary
|
|
1366
|
-
The `sac` directory provides the base component framework for Solace Agent Mesh (SAM) implementations in the Solace AI Connector. It offers a standardized foundation for building high-level SAM components like Agents and Gateways with built-in async operations management and message publishing capabilities.
|
|
1367
|
-
|
|
1368
|
-
## Files Overview
|
|
1369
|
-
- `__init__.py` - Empty package initialization file
|
|
1370
|
-
- `sam_component_base.py` - Abstract base class providing async thread management and A2A message publishing for SAM components
|
|
1371
|
-
|
|
1372
|
-
## Developer API Reference
|
|
1373
|
-
|
|
1374
|
-
### sam_component_base.py
|
|
1375
|
-
**Purpose:** Provides an abstract base class for SAM components with managed asyncio event loops and message publishing
|
|
1376
|
-
**Import:** `from solace_agent_mesh.common.sac.sam_component_base import SamComponentBase`
|
|
1377
|
-
|
|
1378
|
-
**Classes:**
|
|
1379
|
-
- `SamComponentBase(info: Dict[str, Any], **kwargs: Any)` - Abstract base class for high-level SAM components (Agents, Gateways)
|
|
1380
|
-
- `publish_a2a_message(payload: Dict, topic: str, user_properties: Optional[Dict] = None) -> None` - Publishes A2A messages with size validation
|
|
1381
|
-
- `run() -> None` - Starts the component's dedicated async thread
|
|
1382
|
-
- `cleanup() -> None` - Cleans up resources including async thread and loop
|
|
1383
|
-
- `get_async_loop() -> Optional[asyncio.AbstractEventLoop]` - Returns the dedicated asyncio event loop
|
|
1384
|
-
- `_async_setup_and_run() -> None` - Abstract method for subclasses to implement main async logic
|
|
1385
|
-
- `_pre_async_cleanup() -> None` - Abstract method for cleanup before async loop stops
|
|
1386
|
-
- `namespace: str` - The configured namespace for the component
|
|
1387
|
-
- `max_message_size_bytes: int` - Maximum allowed message size in bytes
|
|
1388
|
-
|
|
1389
|
-
**Usage Examples:**
|
|
1390
|
-
```python
|
|
1391
|
-
from solace_agent_mesh.common.sac.sam_component_base import SamComponentBase
|
|
1392
|
-
from typing import Dict, Any
|
|
1393
|
-
import asyncio
|
|
1394
|
-
|
|
1395
|
-
class MyAgent(SamComponentBase):
|
|
1396
|
-
def __init__(self, info: Dict[str, Any], **kwargs: Any):
|
|
1397
|
-
super().__init__(info, **kwargs)
|
|
1398
|
-
# Additional initialization
|
|
1399
|
-
|
|
1400
|
-
async def _async_setup_and_run(self) -> None:
|
|
1401
|
-
"""Implement your main async logic here"""
|
|
1402
|
-
while not self.stop_signal.is_set():
|
|
1403
|
-
# Your async operations
|
|
1404
|
-
await asyncio.sleep(1)
|
|
1405
|
-
|
|
1406
|
-
def _pre_async_cleanup(self) -> None:
|
|
1407
|
-
"""Cleanup before async loop stops"""
|
|
1408
|
-
# Your cleanup logic
|
|
1409
|
-
pass
|
|
1410
|
-
|
|
1411
|
-
# Usage
|
|
1412
|
-
config = {
|
|
1413
|
-
"namespace": "my_namespace",
|
|
1414
|
-
"max_message_size_bytes": 1048576 # 1MB
|
|
1415
|
-
}
|
|
1416
|
-
agent = MyAgent(config)
|
|
1417
|
-
|
|
1418
|
-
# Publish a message
|
|
1419
|
-
payload = {"message": "Hello World"}
|
|
1420
|
-
agent.publish_a2a_message(
|
|
1421
|
-
payload=payload,
|
|
1422
|
-
topic="sam/agents/my_agent/response",
|
|
1423
|
-
user_properties={"correlation_id": "123"}
|
|
1424
|
-
)
|
|
1425
|
-
|
|
1426
|
-
# Start the component
|
|
1427
|
-
agent.run()
|
|
1428
|
-
|
|
1429
|
-
# Later, cleanup
|
|
1430
|
-
agent.cleanup()
|
|
1431
|
-
```
|
|
1432
|
-
|
|
1433
|
-
================================================================================
|
|
1434
|
-
|
|
1435
|
-
## Section 7: solace_agent_mesh/common/sam_events/sam_events_llm.txt
|
|
1436
|
-
|
|
1437
|
-
**Source file:** `solace_agent_mesh/common/sam_events/sam_events_llm.txt`
|
|
1438
|
-
|
|
1439
|
-
# DEVELOPER GUIDE: sam_events
|
|
1440
|
-
|
|
1441
|
-
## Quick Summary
|
|
1442
|
-
The `sam_events` directory provides system-level event messaging for Solace Agent Mesh (SAM). It enables clean separation between agent-to-agent (A2A) task communication and system events like session lifecycle, agent health, and configuration changes.
|
|
1443
|
-
|
|
1444
|
-
## Files Overview
|
|
1445
|
-
- `__init__.py` - Package initialization and public API exports
|
|
1446
|
-
- `event_service.py` - Core event service implementation with publishing/subscription capabilities
|
|
1447
|
-
|
|
1448
|
-
## Developer API Reference
|
|
1449
|
-
|
|
1450
|
-
### __init__.py
|
|
1451
|
-
**Purpose:** Package entry point that exports the main classes for SAM event handling
|
|
1452
|
-
**Import:** `from solace_agent_mesh.common.sam_events import SamEventService, SamEvent, SessionDeletedEvent`
|
|
1453
|
-
|
|
1454
|
-
### event_service.py
|
|
1455
|
-
**Purpose:** Implements the core event messaging service for system-level events in SAM
|
|
1456
|
-
**Import:** `from solace_agent_mesh.common.sam_events.event_service import SamEventService, SamEvent, SessionDeletedEvent`
|
|
1457
|
-
|
|
1458
|
-
**Classes:**
|
|
1459
|
-
|
|
1460
|
-
- `SamEvent(event_type: str, event_id: str, timestamp: str, source_component: str, namespace: str, data: Dict[str, Any])` - Base class for all SAM system events
|
|
1461
|
-
- `create(event_type: str, source_component: str, namespace: str, data: Dict[str, Any]) -> SamEvent` - Create a new event with auto-generated ID and timestamp
|
|
1462
|
-
- `to_dict() -> Dict[str, Any]` - Convert event to dictionary for messaging
|
|
1463
|
-
- `event_type: str` - Type of event (e.g., "session.deleted")
|
|
1464
|
-
- `event_id: str` - Unique identifier for the event
|
|
1465
|
-
- `timestamp: str` - ISO format timestamp when event was created
|
|
1466
|
-
- `source_component: str` - Component that generated the event
|
|
1467
|
-
- `namespace: str` - SAM namespace
|
|
1468
|
-
- `data: Dict[str, Any]` - Event-specific data payload
|
|
1469
|
-
|
|
1470
|
-
- `SessionDeletedEvent(SamEvent)` - Specialized event for session deletion notifications
|
|
1471
|
-
- `create(namespace: str, source_component: str, session_id: str, user_id: str, agent_id: str, gateway_id: str) -> SessionDeletedEvent` - Create a session deleted event
|
|
1472
|
-
|
|
1473
|
-
- `SamEventService(namespace: str, component_name: str, publish_func: Callable[[str, Dict, Optional[Dict]], None])` - Service for publishing and subscribing to SAM system events
|
|
1474
|
-
- `publish_event(event: SamEvent) -> bool` - Publish a system event
|
|
1475
|
-
- `publish_session_deleted(session_id: str, user_id: str, agent_id: str, gateway_id: str) -> bool` - Convenience method to publish session deleted event
|
|
1476
|
-
- `subscribe_to_events(event_type: str, handler: Callable[[SamEvent], None]) -> bool` - Subscribe to events of a specific type
|
|
1477
|
-
- `handle_incoming_event(topic: str, payload: Dict[str, Any]) -> None` - Handle incoming events from messaging system
|
|
1478
|
-
- `namespace: str` - The SAM namespace
|
|
1479
|
-
- `component_name: str` - Name of the component using this service
|
|
1480
|
-
|
|
1481
|
-
**Functions:**
|
|
1482
|
-
|
|
1483
|
-
- `SamEventService.get_event_topic(namespace: str, event_type: str) -> str` - Get the topic for a specific event type
|
|
1484
|
-
|
|
1485
|
-
**Usage Examples:**
|
|
1486
|
-
|
|
1487
|
-
```python
|
|
1488
|
-
# Basic event service setup
|
|
1489
|
-
from solace_agent_mesh.common.sam_events import SamEventService, SamEvent, SessionDeletedEvent
|
|
1490
|
-
|
|
1491
|
-
# Initialize the event service
|
|
1492
|
-
def my_publish_func(topic: str, payload: dict, headers: dict = None):
|
|
1493
|
-
# Your A2A publishing implementation
|
|
1494
|
-
pass
|
|
1495
|
-
|
|
1496
|
-
event_service = SamEventService(
|
|
1497
|
-
namespace="my_namespace",
|
|
1498
|
-
component_name="my_component",
|
|
1499
|
-
publish_func=my_publish_func
|
|
1500
|
-
)
|
|
1501
|
-
|
|
1502
|
-
# Create and publish a custom event
|
|
1503
|
-
custom_event = SamEvent.create(
|
|
1504
|
-
event_type="agent.health_check",
|
|
1505
|
-
source_component="health_monitor",
|
|
1506
|
-
namespace="my_namespace",
|
|
1507
|
-
data={"status": "healthy", "cpu_usage": 45.2}
|
|
1508
|
-
)
|
|
1509
|
-
success = event_service.publish_event(custom_event)
|
|
1510
|
-
|
|
1511
|
-
# Publish a session deleted event (convenience method)
|
|
1512
|
-
success = event_service.publish_session_deleted(
|
|
1513
|
-
session_id="sess_123",
|
|
1514
|
-
user_id="user_456",
|
|
1515
|
-
agent_id="agent_789",
|
|
1516
|
-
gateway_id="gateway_001"
|
|
1517
|
-
)
|
|
1518
|
-
|
|
1519
|
-
# Subscribe to events
|
|
1520
|
-
def handle_session_deleted(event: SamEvent):
|
|
1521
|
-
session_id = event.data["session_id"]
|
|
1522
|
-
print(f"Session {session_id} was deleted")
|
|
1523
|
-
|
|
1524
|
-
event_service.subscribe_to_events("session.deleted", handle_session_deleted)
|
|
1525
|
-
|
|
1526
|
-
# Handle incoming events (typically called by your messaging infrastructure)
|
|
1527
|
-
incoming_payload = {
|
|
1528
|
-
"event_type": "session.deleted",
|
|
1529
|
-
"event_id": "evt_123",
|
|
1530
|
-
"timestamp": "2024-01-01T12:00:00Z",
|
|
1531
|
-
"source_component": "gateway",
|
|
1532
|
-
"namespace": "my_namespace",
|
|
1533
|
-
"data": {"session_id": "sess_123", "user_id": "user_456"}
|
|
1534
|
-
}
|
|
1535
|
-
event_service.handle_incoming_event("sam/events/session/deleted", incoming_payload)
|
|
1536
|
-
|
|
1537
|
-
# Get topic for an event type
|
|
1538
|
-
topic = SamEventService.get_event_topic("my_namespace", "session.deleted")
|
|
1539
|
-
print(topic) # Returns the proper SAM events topic
|
|
1540
|
-
```
|
|
1541
|
-
|
|
1542
|
-
================================================================================
|
|
1543
|
-
|
|
1544
|
-
## Section 8: solace_agent_mesh/common/services/providers/providers_llm.txt
|
|
1545
|
-
|
|
1546
|
-
**Source file:** `solace_agent_mesh/common/services/providers/providers_llm.txt`
|
|
1547
|
-
|
|
1548
|
-
## Quick Summary
|
|
1549
|
-
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.
|
|
1550
|
-
|
|
1551
|
-
## Files Overview
|
|
1552
|
-
- `__init__.py` - Package initialization file marking the directory as a Python package
|
|
1553
|
-
- `local_file_identity_service.py` - File-based identity service implementation that reads user data from local JSON files
|
|
1554
|
-
|
|
1555
|
-
## Developer API Reference
|
|
1556
|
-
|
|
1557
|
-
### __init__.py
|
|
1558
|
-
**Purpose:** Initializes the providers package
|
|
1559
|
-
**Import:** `from solace_agent_mesh.common.services import providers`
|
|
1560
|
-
|
|
1561
|
-
This file contains no public classes or functions - it serves only as package documentation.
|
|
1562
|
-
|
|
1563
|
-
### local_file_identity_service.py
|
|
1564
|
-
**Purpose:** Provides a file-based identity service that reads user profiles from a local JSON file, ideal for development, testing, or small-scale deployments
|
|
1565
|
-
**Import:** `from solace_agent_mesh.common.services.providers.local_file_identity_service import LocalFileIdentityService`
|
|
1566
|
-
|
|
1567
|
-
**Classes:**
|
|
1568
|
-
- `LocalFileIdentityService(config: Dict[str, Any])` - Identity service that sources user data from a local JSON file
|
|
1569
|
-
- `async get_user_profile(auth_claims: Dict[str, Any]) -> Optional[Dict[str, Any]]` - Looks up a user profile using the lookup key from auth claims
|
|
1570
|
-
- `async search_users(query: str, limit: int = 10) -> List[Dict[str, Any]]` - Performs case-insensitive search on user names and emails
|
|
1571
|
-
- `file_path: str` - Path to the JSON file containing user data
|
|
1572
|
-
- `lookup_key: str` - Key used to identify users (defaults to "id")
|
|
1573
|
-
- `all_users: List[Dict[str, Any]]` - Complete list of user profiles loaded from file
|
|
1574
|
-
- `user_index: Dict[str, Dict[str, Any]]` - In-memory index mapping lookup keys to user profiles
|
|
1575
|
-
|
|
1576
|
-
**Usage Examples:**
|
|
1577
|
-
```python
|
|
1578
|
-
import asyncio
|
|
1579
|
-
import json
|
|
1580
|
-
from solace_agent_mesh.common.services.providers.local_file_identity_service import LocalFileIdentityService
|
|
1581
|
-
|
|
1582
|
-
# Create sample users.json file
|
|
1583
|
-
users_data = [
|
|
1584
|
-
{
|
|
1585
|
-
"id": "jdoe",
|
|
1586
|
-
"email": "jane.doe@example.com",
|
|
1587
|
-
"name": "Jane Doe",
|
|
1588
|
-
"title": "Senior Engineer",
|
|
1589
|
-
"manager_id": "ssmith"
|
|
1590
|
-
},
|
|
1591
|
-
{
|
|
1592
|
-
"id": "ssmith",
|
|
1593
|
-
"email": "sam.smith@example.com",
|
|
1594
|
-
"name": "Sam Smith",
|
|
1595
|
-
"title": "Engineering Manager"
|
|
1596
|
-
}
|
|
1597
|
-
]
|
|
1598
|
-
|
|
1599
|
-
with open("users.json", "w") as f:
|
|
1600
|
-
json.dump(users_data, f)
|
|
1601
|
-
|
|
1602
|
-
async def main():
|
|
1603
|
-
# Initialize the service
|
|
1604
|
-
config = {
|
|
1605
|
-
"file_path": "users.json",
|
|
1606
|
-
"lookup_key": "id" # Optional, defaults to "id"
|
|
1607
|
-
}
|
|
1608
|
-
|
|
1609
|
-
identity_service = LocalFileIdentityService(config)
|
|
1610
|
-
|
|
1611
|
-
# Get user profile by ID
|
|
1612
|
-
auth_claims = {"id": "jdoe"}
|
|
1613
|
-
profile = await identity_service.get_user_profile(auth_claims)
|
|
1614
|
-
print(f"User profile: {profile}")
|
|
1615
|
-
|
|
1616
|
-
# Search for users
|
|
1617
|
-
results = await identity_service.search_users("jane", limit=5)
|
|
1618
|
-
print(f"Search results: {results}")
|
|
1619
|
-
|
|
1620
|
-
# Handle missing user
|
|
1621
|
-
missing = await identity_service.get_user_profile({"id": "nonexistent"})
|
|
1622
|
-
print(f"Missing user: {missing}") # Returns None
|
|
1623
|
-
|
|
1624
|
-
asyncio.run(main())
|
|
1625
|
-
```
|
|
1626
|
-
|
|
1627
|
-
================================================================================
|
|
1628
|
-
|
|
1629
|
-
## Section 9: solace_agent_mesh/common/services/services_llm.txt
|
|
1630
|
-
|
|
1631
|
-
**Source file:** `solace_agent_mesh/common/services/services_llm.txt`
|
|
1632
|
-
|
|
1633
|
-
# DEVELOPER GUIDE: services
|
|
1634
|
-
|
|
1635
|
-
## Quick Summary
|
|
1636
|
-
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.
|
|
1637
|
-
|
|
1638
|
-
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. The `providers/` subdirectory contains concrete implementations, including a built-in file-based identity service, while external providers can be dynamically loaded as plugins through Python's entry points system.
|
|
1639
|
-
|
|
1640
|
-
## Files and Subdirectories Overview
|
|
1641
|
-
- **Direct files:**
|
|
1642
|
-
- `__init__.py`: Marks the directory as a Python package with shared, reusable services
|
|
1643
|
-
- `employee_service.py`: Defines the abstract contract and factory for employee data services
|
|
1644
|
-
- `identity_service.py`: Defines the abstract contract and factory for user identity services
|
|
1645
|
-
- **Subdirectories:**
|
|
1646
|
-
- `providers/`: Contains concrete implementations of the service contracts, including a file-based identity provider
|
|
1647
|
-
|
|
1648
|
-
## Developer API Reference
|
|
1649
|
-
|
|
1650
|
-
### Direct Files
|
|
1651
|
-
|
|
1652
|
-
#### employee_service.py
|
|
1653
|
-
**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.
|
|
1654
|
-
**Import:** `from solace_agent_mesh.common.services.employee_service import BaseEmployeeService, create_employee_service`
|
|
1655
|
-
|
|
1656
|
-
**Classes/Functions/Constants:**
|
|
1657
|
-
- **`class BaseEmployeeService(ABC)`**: The abstract base class for employee service providers.
|
|
1658
|
-
- **`__init__(self, config: Dict[str, Any])`**: Initializes the service, setting up configuration and an optional in-memory cache.
|
|
1659
|
-
- **`async def get_employee_dataframe(self) -> pd.DataFrame`**: (Abstract) Returns the entire employee directory as a pandas DataFrame.
|
|
1660
|
-
- **`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.
|
|
1661
|
-
- **`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.
|
|
1662
|
-
- **`async def get_employee_profile_picture(self, employee_id: str) -> Optional[str]`**: (Abstract) Fetches an employee's profile picture as a data URI string.
|
|
1663
|
-
- **`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.
|
|
1664
|
-
|
|
1665
|
-
#### identity_service.py
|
|
1666
|
-
**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.
|
|
1667
|
-
**Import:** `from solace_agent_mesh.common.services.identity_service import BaseIdentityService, create_identity_service`
|
|
1668
|
-
|
|
1669
|
-
**Classes/Functions/Constants:**
|
|
1670
|
-
- **`class BaseIdentityService(ABC)`**: The abstract base class for identity service providers.
|
|
1671
|
-
- **`__init__(self, config: Dict[str, Any])`**: Initializes the service, setting up configuration and an optional in-memory cache.
|
|
1672
|
-
- **`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.
|
|
1673
|
-
- **`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).
|
|
1674
|
-
- **`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.
|
|
1675
|
-
|
|
1676
|
-
### Subdirectory APIs
|
|
1677
|
-
|
|
1678
|
-
#### providers/
|
|
1679
|
-
**Purpose:** Contains concrete implementations of the abstract service classes, providing specific ways to fulfill service contracts such as sourcing user identity information from local files
|
|
1680
|
-
**Key Exports:** `LocalFileIdentityService`
|
|
1681
|
-
**Import Examples:**
|
|
1682
|
-
```python
|
|
1683
|
-
from solace_agent_mesh.common.services.providers.local_file_identity_service import LocalFileIdentityService
|
|
1684
|
-
```
|
|
1685
|
-
|
|
1686
|
-
## Complete Usage Guide
|
|
1687
|
-
|
|
1688
|
-
### 1. Using Service Factories (Recommended Approach)
|
|
1689
|
-
The factories are the primary way to create and use services. They abstract away the specific implementation details and handle plugin loading.
|
|
1690
|
-
|
|
1691
|
-
**Example: Creating Identity and Employee Services**
|
|
1692
|
-
|
|
1693
|
-
```python
|
|
1694
|
-
import asyncio
|
|
1695
|
-
from solace_agent_mesh.common.services.identity_service import create_identity_service
|
|
1696
|
-
from solace_agent_mesh.common.services.employee_service import create_employee_service
|
|
1697
|
-
|
|
1698
|
-
async def main():
|
|
1699
|
-
# --- Identity Service Example (using built-in provider) ---
|
|
1700
|
-
identity_config = {
|
|
1701
|
-
"type": "local_file",
|
|
1702
|
-
"file_path": "path/to/your/users.json",
|
|
1703
|
-
"lookup_key": "email", # Key to use for lookups from auth_claims
|
|
1704
|
-
"cache_ttl_seconds": 3600
|
|
1705
|
-
}
|
|
1706
|
-
identity_service = create_identity_service(identity_config)
|
|
1707
|
-
|
|
1708
|
-
if identity_service:
|
|
1709
|
-
print("Identity Service created.")
|
|
1710
|
-
# Fetch a user profile
|
|
1711
|
-
auth_claims = {"email": "jane.doe@example.com"}
|
|
1712
|
-
user_profile = await identity_service.get_user_profile(auth_claims)
|
|
1713
|
-
print(f"User Profile: {user_profile}")
|
|
1714
|
-
|
|
1715
|
-
# Search for users
|
|
1716
|
-
search_results = await identity_service.search_users("Jane")
|
|
1717
|
-
print(f"Search Results: {search_results}")
|
|
1718
|
-
|
|
1719
|
-
# --- Employee Service Example (using external plugin) ---
|
|
1720
|
-
# The 'type' must match the name of a registered plugin entry point
|
|
1721
|
-
employee_config = {
|
|
1722
|
-
"type": "bamboohr_plugin",
|
|
1723
|
-
"api_key": "your-secret-api-key",
|
|
1724
|
-
"subdomain": "your-company",
|
|
1725
|
-
"cache_ttl_seconds": 7200
|
|
1726
|
-
}
|
|
1727
|
-
employee_service = create_employee_service(employee_config)
|
|
1728
|
-
|
|
1729
|
-
if employee_service:
|
|
1730
|
-
print("\nEmployee Service created.")
|
|
1731
|
-
# Get a detailed employee profile
|
|
1732
|
-
employee_profile = await employee_service.get_employee_profile("jane.doe@example.com")
|
|
1733
|
-
print(f"Employee Profile: {employee_profile}")
|
|
1734
|
-
|
|
1735
|
-
# Get time off data
|
|
1736
|
-
time_off = await employee_service.get_time_off_data("jane.doe@example.com")
|
|
1737
|
-
print(f"Time Off Data: {time_off}")
|
|
1738
|
-
|
|
1739
|
-
# Get employee directory as DataFrame
|
|
1740
|
-
df = await employee_service.get_employee_dataframe()
|
|
1741
|
-
print(f"Employee Directory Shape: {df.shape}")
|
|
1742
|
-
|
|
1743
|
-
# Run the example
|
|
1744
|
-
asyncio.run(main())
|
|
1745
|
-
```
|
|
1746
|
-
|
|
1747
|
-
### 2. Direct Provider Instantiation
|
|
1748
|
-
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.
|
|
1749
|
-
|
|
1750
|
-
**Example: Direct Use of LocalFileIdentityService**
|
|
1751
|
-
|
|
1752
|
-
```python
|
|
1753
|
-
import asyncio
|
|
1754
|
-
import json
|
|
1755
|
-
from solace_agent_mesh.common.services.providers.local_file_identity_service import LocalFileIdentityService
|
|
1756
|
-
|
|
1757
|
-
async def main():
|
|
1758
|
-
# First, create a sample users.json file
|
|
1759
|
-
users_data = [
|
|
1760
|
-
{
|
|
1761
|
-
"id": "jdoe",
|
|
1762
|
-
"email": "jane.doe@example.com",
|
|
1763
|
-
"name": "Jane Doe",
|
|
1764
|
-
"title": "Senior Engineer",
|
|
1765
|
-
"manager_id": "ssmith"
|
|
1766
|
-
},
|
|
1767
|
-
{
|
|
1768
|
-
"id": "ssmith",
|
|
1769
|
-
"email": "sam.smith@example.com",
|
|
1770
|
-
"name": "Sam Smith",
|
|
1771
|
-
"title": "Engineering Manager"
|
|
1772
|
-
}
|
|
1773
|
-
]
|
|
1774
|
-
|
|
1775
|
-
with open("users.json", "w") as f:
|
|
1776
|
-
json.dump(users_data, f)
|
|
1777
|
-
|
|
1778
|
-
# Configuration does not need a 'type' key for direct instantiation
|
|
1779
|
-
config = {
|
|
1780
|
-
"file_path": "users.json",
|
|
1781
|
-
"lookup_key": "id",
|
|
1782
|
-
"cache_ttl_seconds": 1800
|
|
1783
|
-
}
|
|
1784
|
-
|
|
1785
|
-
# Instantiate the class directly
|
|
1786
|
-
local_service = LocalFileIdentityService(config)
|
|
1787
|
-
print("LocalFileIdentityService created directly")
|
|
1788
|
-
|
|
1789
|
-
# Get user profile by ID
|
|
1790
|
-
auth_claims = {"id": "jdoe"}
|
|
1791
|
-
profile = await local_service.get_user_profile(auth_claims)
|
|
1792
|
-
print(f"User profile: {profile}")
|
|
1793
|
-
|
|
1794
|
-
# Search for users
|
|
1795
|
-
results = await local_service.search_users("jane", limit=5)
|
|
1796
|
-
print(f"Search results: {results}")
|
|
1797
|
-
|
|
1798
|
-
asyncio.run(main())
|
|
1799
|
-
```
|
|
1800
|
-
|
|
1801
|
-
### 3. Creating Custom Service Providers
|
|
1802
|
-
To create your own service provider, inherit from the appropriate base class and implement all abstract methods.
|
|
1803
|
-
|
|
1804
|
-
**Example: Custom Employee Service Provider**
|
|
1805
|
-
|
|
1806
|
-
```python
|
|
1807
|
-
import pandas as pd
|
|
1808
|
-
from typing import Any, Dict, List, Optional
|
|
1809
|
-
from solace_agent_mesh.common.services.employee_service import BaseEmployeeService
|
|
1810
|
-
|
|
1811
|
-
class CustomEmployeeService(BaseEmployeeService):
|
|
1812
|
-
"""Custom employee service that connects to your HR system."""
|
|
1813
|
-
|
|
1814
|
-
def __init__(self, config: Dict[str, Any]):
|
|
1815
|
-
super().__init__(config)
|
|
1816
|
-
self.api_endpoint = config.get("api_endpoint")
|
|
1817
|
-
self.api_key = config.get("api_key")
|
|
1818
|
-
|
|
1819
|
-
async def get_employee_dataframe(self) -> pd.DataFrame:
|
|
1820
|
-
"""Fetch all employees and return as DataFrame."""
|
|
1821
|
-
# Your implementation here
|
|
1822
|
-
# This should return a DataFrame with canonical schema columns:
|
|
1823
|
-
# id, displayName, workEmail, jobTitle, department, location, supervisorId, hireDate, mobilePhone
|
|
1824
|
-
employees_data = [
|
|
1825
|
-
{
|
|
1826
|
-
"id": "jdoe@company.com",
|
|
1827
|
-
"displayName": "Jane Doe",
|
|
1828
|
-
"workEmail": "jdoe@company.com",
|
|
1829
|
-
"jobTitle": "Software Engineer",
|
|
1830
|
-
"department": "Engineering",
|
|
1831
|
-
"location": "San Francisco",
|
|
1832
|
-
"supervisorId": "manager@company.com",
|
|
1833
|
-
"hireDate": "2023-01-15",
|
|
1834
|
-
"mobilePhone": "+1-555-0123"
|
|
1835
|
-
}
|
|
1836
|
-
]
|
|
1837
|
-
return pd.DataFrame(employees_data)
|
|
1838
|
-
|
|
1839
|
-
async def get_employee_profile(self, employee_id: str) -> Optional[Dict[str, Any]]:
|
|
1840
|
-
"""Get single employee profile."""
|
|
1841
|
-
# Your implementation here
|
|
1842
|
-
return {
|
|
1843
|
-
"id": employee_id,
|
|
1844
|
-
"displayName": "Jane Doe",
|
|
1845
|
-
"workEmail": employee_id,
|
|
1846
|
-
"jobTitle": "Software Engineer"
|
|
1847
|
-
}
|
|
1848
|
-
|
|
1849
|
-
async def get_time_off_data(self, employee_id: str) -> List[Dict[str, Any]]:
|
|
1850
|
-
"""Get employee time off data."""
|
|
1851
|
-
# Your implementation here
|
|
1852
|
-
return [
|
|
1853
|
-
{
|
|
1854
|
-
'start': '2025-07-04',
|
|
1855
|
-
'end': '2025-07-04',
|
|
1856
|
-
'type': 'Holiday',
|
|
1857
|
-
'amount': 'full_day'
|
|
1858
|
-
}
|
|
1859
|
-
]
|
|
1860
|
-
|
|
1861
|
-
async def get_employee_profile_picture(self, employee_id: str) -> Optional[str]:
|
|
1862
|
-
"""Get employee profile picture as data URI."""
|
|
1863
|
-
# Your implementation here
|
|
1864
|
-
return None # or return "data:image/jpeg;base64,..."
|
|
1865
|
-
|
|
1866
|
-
# Usage
|
|
1867
|
-
async def use_custom_service():
|
|
1868
|
-
config = {
|
|
1869
|
-
"api_endpoint": "https://your-hr-api.com",
|
|
1870
|
-
"api_key": "your-api-key",
|
|
1871
|
-
"cache_ttl_seconds": 3600
|
|
1872
|
-
}
|
|
1873
|
-
|
|
1874
|
-
service = CustomEmployeeService(config)
|
|
1875
|
-
profile = await service.get_employee_profile("jdoe@company.com")
|
|
1876
|
-
print(f"Custom service profile: {profile}")
|
|
1877
|
-
```
|
|
1878
|
-
|
|
1879
|
-
### 4. Working with Both Services Together
|
|
1880
|
-
Often you'll want to use both identity and employee services together for comprehensive user information.
|
|
1881
|
-
|
|
1882
|
-
**Example: Combined Service Usage**
|
|
1883
|
-
|
|
1884
|
-
```python
|
|
1885
|
-
import asyncio
|
|
1886
|
-
from solace_agent_mesh.common.services.identity_service import create_identity_service
|
|
1887
|
-
from solace_agent_mesh.common.services.employee_service import create_employee_service
|
|
1888
|
-
|
|
1889
|
-
async def get_complete_user_info(user_email: str):
|
|
1890
|
-
"""Get comprehensive user information from both services."""
|
|
1891
|
-
|
|
1892
|
-
# Configure services
|
|
1893
|
-
identity_config = {
|
|
1894
|
-
"type": "local_file",
|
|
1895
|
-
"file_path": "users.json",
|
|
1896
|
-
"lookup_key": "email"
|
|
1897
|
-
}
|
|
1898
|
-
|
|
1899
|
-
employee_config = {
|
|
1900
|
-
"type": "your_hr_plugin",
|
|
1901
|
-
"api_key": "your-key"
|
|
1902
|
-
}
|
|
1903
|
-
|
|
1904
|
-
# Create services
|
|
1905
|
-
identity_service = create_identity_service(identity_config)
|
|
1906
|
-
employee_service = create_employee_service(employee_config)
|
|
1907
|
-
|
|
1908
|
-
# Gather information
|
|
1909
|
-
user_info = {}
|
|
1910
|
-
|
|
1911
|
-
if identity_service:
|
|
1912
|
-
auth_claims = {"email": user_email}
|
|
1913
|
-
identity_profile = await identity_service.get_user_profile(auth_claims)
|
|
1914
|
-
if identity_profile:
|
|
1915
|
-
user_info.update(identity_profile)
|
|
1916
|
-
|
|
1917
|
-
if employee_service:
|
|
1918
|
-
employee_profile = await employee_service.get_employee_profile(user_email)
|
|
1919
|
-
if employee_profile:
|
|
1920
|
-
user_info.update(employee_profile)
|
|
1921
|
-
|
|
1922
|
-
# Get additional employee data
|
|
1923
|
-
time_off = await employee_service.get_time_off_data(user_email)
|
|
1924
|
-
user_info["time_off"] = time_off
|
|
1925
|
-
|
|
1926
|
-
profile_pic = await employee_service.get_employee_profile_picture(user_email)
|
|
1927
|
-
if profile_pic:
|
|
1928
|
-
user_info["profile_picture"] = profile_pic
|
|
1929
|
-
|
|
1930
|
-
return user_info
|
|
1931
|
-
|
|
1932
|
-
# Usage
|
|
1933
|
-
async def main():
|
|
1934
|
-
complete_info = await get_complete_user_info("jane.doe@example.com")
|
|
1935
|
-
print(f"Complete user information: {complete_info}")
|
|
1936
|
-
|
|
1937
|
-
asyncio.run(main())
|
|
1938
|
-
```
|
|
1939
|
-
|
|
1940
|
-
### 5. Using the Built-in LocalFileIdentityService
|
|
1941
|
-
The `providers/` subdirectory includes a ready-to-use file-based identity service that's perfect for development and testing.
|
|
1942
|
-
|
|
1943
|
-
**Example: Setting up LocalFileIdentityService with Factory**
|
|
1944
|
-
|
|
1945
|
-
```python
|
|
1946
|
-
import asyncio
|
|
1947
|
-
import json
|
|
1948
|
-
from solace_agent_mesh.common.services.identity_service import create_identity_service
|
|
1949
|
-
|
|
1950
|
-
async def setup_file_based_identity():
|
|
1951
|
-
# Create sample users.json file
|
|
1952
|
-
users_data = [
|
|
1953
|
-
{
|
|
1954
|
-
"id": "jdoe",
|
|
1955
|
-
"email": "jane.doe@example.com",
|
|
1956
|
-
"name": "Jane Doe",
|
|
1957
|
-
"title": "Senior Engineer",
|
|
1958
|
-
"manager_id": "ssmith"
|
|
1959
|
-
},
|
|
1960
|
-
{
|
|
1961
|
-
"id": "ssmith",
|
|
1962
|
-
"email": "sam.smith@example.com",
|
|
1963
|
-
"name": "Sam Smith",
|
|
1964
|
-
"title": "Engineering Manager"
|
|
1965
|
-
}
|
|
1966
|
-
]
|
|
1967
|
-
|
|
1968
|
-
with open("users.json", "w") as f:
|
|
1969
|
-
json.dump(users_data, f)
|
|
1970
|
-
|
|
1971
|
-
# Use factory to create the service
|
|
1972
|
-
config = {
|
|
1973
|
-
"type": "local_file", # This triggers the built-in provider
|
|
1974
|
-
"file_path": "users.json",
|
|
1975
|
-
"lookup_key": "email", # Use email for lookups
|
|
1976
|
-
"cache_ttl_seconds": 3600
|
|
1977
|
-
}
|
|
1978
|
-
|
|
1979
|
-
identity_service = create_identity_service(config)
|
|
1980
|
-
|
|
1981
|
-
# Test the service
|
|
1982
|
-
auth_claims = {"email": "jane.doe@example.com"}
|
|
1983
|
-
profile = await identity_service.get_user_profile(auth_claims)
|
|
1984
|
-
print(f"Profile found: {profile}")
|
|
1985
|
-
|
|
1986
|
-
# Search functionality
|
|
1987
|
-
search_results = await identity_service.search_users("jane")
|
|
1988
|
-
print(f"Search results: {search_results}")
|
|
1989
|
-
|
|
1990
|
-
asyncio.run(setup_file_based_identity())
|
|
1991
|
-
```
|
|
1992
|
-
|
|
1993
|
-
This comprehensive guide shows how the services framework provides a clean, extensible way to integrate various data sources while maintaining consistent interfaces and supporting both built-in providers and external plugins through the factory pattern and plugin system.
|
|
1994
|
-
|
|
1995
|
-
================================================================================
|
|
1996
|
-
|
|
1997
|
-
## Section 10: solace_agent_mesh/common/utils/embeds/embeds_llm.txt
|
|
1998
|
-
|
|
1999
|
-
**Source file:** `solace_agent_mesh/common/utils/embeds/embeds_llm.txt`
|
|
2000
|
-
|
|
2001
|
-
# DEVELOPER GUIDE: embeds
|
|
2002
|
-
|
|
2003
|
-
## Quick Summary
|
|
2004
|
-
The `embeds` directory provides a comprehensive system for finding, parsing, and resolving embedded expressions within strings. These expressions use `«...»` syntax and can represent dynamic values like mathematical calculations, datetimes, UUIDs, or content from stored artifacts. The system supports multi-step data transformation pipelines, recursive embed resolution, and includes safety features like depth and size limits. It's designed as a core component for dynamic content generation and data processing in agent workflows.
|
|
2005
|
-
|
|
2006
|
-
## Files Overview
|
|
2007
|
-
- `__init__.py` - Main public entry point exporting key functions and constants
|
|
2008
|
-
- `constants.py` - Defines embed syntax (delimiters, separators), regex patterns, and type classifications
|
|
2009
|
-
- `converter.py` - Data format conversion and serialization functions
|
|
2010
|
-
- `evaluators.py` - Specific evaluation logic for simple embed types (math, datetime, uuid, etc.)
|
|
2011
|
-
- `modifiers.py` - Data transformation functions that can be chained together (jsonpath, slice, grep, etc.)
|
|
2012
|
-
- `resolver.py` - Core orchestration engine handling embed resolution, modifier chains, and recursion
|
|
2013
|
-
- `types.py` - DataFormat enum for tracking data types during transformations
|
|
2014
|
-
|
|
2015
|
-
## Developer API Reference
|
|
2016
|
-
|
|
2017
|
-
### __init__.py
|
|
2018
|
-
**Purpose:** Main public entry point that exports the most commonly used functions and constants from other modules.
|
|
2019
|
-
|
|
2020
|
-
**Import:** `from solace_agent_mesh.common.utils.embeds import resolve_embeds_recursively_in_string, evaluate_embed, EMBED_REGEX`
|
|
2021
|
-
|
|
2022
|
-
**Functions:**
|
|
2023
|
-
- `evaluate_embed(embed_type: str, expression: str, format_spec: Optional[str], context: Dict[str, Any], log_identifier: str, config: Optional[Dict] = None, current_depth: int = 0, visited_artifacts: Optional[Set[Tuple[str, int]]] = None) -> Union[Tuple[str, Optional[str], int], Tuple[None, str, Any]]` - Evaluates a single parsed embed expression
|
|
2024
|
-
- `resolve_embeds_in_string(text: str, context: Any, resolver_func: Callable, types_to_resolve: Set[str], log_identifier: str = "[EmbedUtil]", config: Optional[Dict[str, Any]] = None) -> Tuple[str, int, List[Tuple[int, Any]]]` - Resolves embeds in a string for a single pass (non-recursive)
|
|
2025
|
-
- `resolve_embeds_recursively_in_string(text: str, context: Any, resolver_func: Callable, types_to_resolve: Set[str], log_identifier: str, config: Optional[Dict], max_depth: int, current_depth: int = 0, visited_artifacts: Optional[Set[Tuple[str, int]]] = None, accumulated_size: int = 0, max_total_size: int = -1) -> str` - Recursively resolves all embeds in a string with depth and size limits
|
|
2026
|
-
|
|
2027
|
-
**Constants/Variables:**
|
|
2028
|
-
- `EMBED_DELIMITER_OPEN: str` - Opening delimiter (`«`)
|
|
2029
|
-
- `EMBED_DELIMITER_CLOSE: str` - Closing delimiter (`»`)
|
|
2030
|
-
- `EMBED_TYPE_SEPARATOR: str` - Type/expression separator (`:`)
|
|
2031
|
-
- `EMBED_FORMAT_SEPARATOR: str` - Format specifier separator (`|`)
|
|
2032
|
-
- `EMBED_CHAIN_DELIMITER: str` - Modifier chain separator (`>>>`)
|
|
2033
|
-
- `EMBED_REGEX: re.Pattern` - Compiled regex for finding embeds
|
|
2034
|
-
- `EARLY_EMBED_TYPES: Set[str]` - Types resolved in initial pass
|
|
2035
|
-
- `LATE_EMBED_TYPES: Set[str]` - Types resolved in subsequent pass
|
|
2036
|
-
|
|
2037
|
-
**Usage Examples:**
|
|
2038
|
-
```python
|
|
2039
|
-
from solace_agent_mesh.common.utils.embeds import resolve_embeds_recursively_in_string, evaluate_embed, EMBED_REGEX
|
|
2040
|
-
|
|
2041
|
-
# Basic embed resolution
|
|
2042
|
-
context = {
|
|
2043
|
-
"artifact_service": my_artifact_service,
|
|
2044
|
-
"session_context": {"app_name": "myapp", "user_id": "user123", "session_id": "sess456"}
|
|
2045
|
-
}
|
|
2046
|
-
|
|
2047
|
-
text = "The result is «math:10 * 1.15 | .2f» and ID is «uuid:new»"
|
|
2048
|
-
resolved = await resolve_embeds_recursively_in_string(
|
|
2049
|
-
text=text,
|
|
2050
|
-
context=context,
|
|
2051
|
-
resolver_func=evaluate_embed,
|
|
2052
|
-
types_to_resolve={"math", "uuid"},
|
|
2053
|
-
log_identifier="[MyApp]",
|
|
2054
|
-
config={},
|
|
2055
|
-
max_depth=5
|
|
2056
|
-
)
|
|
2057
|
-
```
|
|
2058
|
-
|
|
2059
|
-
### constants.py
|
|
2060
|
-
**Purpose:** Defines all static constants governing embed syntax and classification.
|
|
2061
|
-
|
|
2062
|
-
**Import:** `from solace_agent_mesh.common.utils.embeds.constants import EMBED_REGEX, EARLY_EMBED_TYPES`
|
|
2063
|
-
|
|
2064
|
-
**Constants/Variables:**
|
|
2065
|
-
- `EMBED_DELIMITER_OPEN: str` - Opening delimiter (`«`)
|
|
2066
|
-
- `EMBED_DELIMITER_CLOSE: str` - Closing delimiter (`»`)
|
|
2067
|
-
- `EMBED_TYPE_SEPARATOR: str` - Type/expression separator (`:`)
|
|
2068
|
-
- `EMBED_FORMAT_SEPARATOR: str` - Format specifier separator (`|`)
|
|
2069
|
-
- `EMBED_CHAIN_DELIMITER: str` - Modifier chain separator (`>>>`)
|
|
2070
|
-
- `EMBED_REGEX: re.Pattern` - Compiled regex with capture groups for type, expression, and format
|
|
2071
|
-
- `EARLY_EMBED_TYPES: Set[str]` - Simple embed types resolved first (`math`, `datetime`, `uuid`, `artifact_meta`, `status_update`)
|
|
2072
|
-
- `LATE_EMBED_TYPES: Set[str]` - Complex embed types resolved later (`artifact_content`)
|
|
2073
|
-
- `TEXT_CONTAINER_MIME_TYPES: Set[str]` - MIME types considered text-based
|
|
2074
|
-
|
|
2075
|
-
**Usage Examples:**
|
|
2076
|
-
```python
|
|
2077
|
-
from solace_agent_mesh.common.utils.embeds.constants import EMBED_REGEX
|
|
2078
|
-
|
|
2079
|
-
text = "Price: «math:10 * 1.15 | .2f» ID: «uuid:new»"
|
|
2080
|
-
for match in EMBED_REGEX.finditer(text):
|
|
2081
|
-
embed_type = match.group(1) # "math" or "uuid"
|
|
2082
|
-
expression = match.group(2) # "10 * 1.15 " or "new"
|
|
2083
|
-
format_spec = match.group(3) # " .2f" or None
|
|
2084
|
-
print(f"Type: {embed_type}, Expr: '{expression}', Format: '{format_spec}'")
|
|
2085
|
-
```
|
|
2086
|
-
|
|
2087
|
-
### converter.py
|
|
2088
|
-
**Purpose:** Provides data conversion between different formats and serialization to final string representations.
|
|
2089
|
-
|
|
2090
|
-
**Import:** `from solace_agent_mesh.common.utils.embeds.converter import convert_data, serialize_data`
|
|
2091
|
-
|
|
2092
|
-
**Functions:**
|
|
2093
|
-
- `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 between DataFormat types using MIME type hints
|
|
2094
|
-
- `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 to final string format (text, json, csv, datauri, or Python format specs)
|
|
2095
|
-
|
|
2096
|
-
**Usage Examples:**
|
|
2097
|
-
```python
|
|
2098
|
-
from solace_agent_mesh.common.utils.embeds.converter import convert_data, serialize_data
|
|
2099
|
-
from solace_agent_mesh.common.utils.embeds.types import DataFormat
|
|
2100
|
-
|
|
2101
|
-
# Convert CSV bytes to list of dictionaries
|
|
2102
|
-
csv_bytes = b"id,name\n1,Alice\n2,Bob"
|
|
2103
|
-
list_data, new_format, err = convert_data(
|
|
2104
|
-
current_data=csv_bytes,
|
|
2105
|
-
current_format=DataFormat.BYTES,
|
|
2106
|
-
target_format=DataFormat.LIST_OF_DICTS,
|
|
2107
|
-
original_mime_type="text/csv"
|
|
2108
|
-
)
|
|
2109
|
-
|
|
2110
|
-
# Serialize to pretty JSON
|
|
2111
|
-
json_str, err = serialize_data(
|
|
2112
|
-
data=list_data,
|
|
2113
|
-
data_format=DataFormat.LIST_OF_DICTS,
|
|
2114
|
-
target_string_format="json_pretty",
|
|
2115
|
-
original_mime_type=None
|
|
2116
|
-
)
|
|
2117
|
-
```
|
|
2118
|
-
|
|
2119
|
-
### evaluators.py
|
|
2120
|
-
**Purpose:** Contains evaluation logic for simple embed types and the evaluator registry.
|
|
2121
|
-
|
|
2122
|
-
**Import:** `from solace_agent_mesh.common.utils.embeds.evaluators import EMBED_EVALUATORS`
|
|
2123
|
-
|
|
2124
|
-
**Functions:**
|
|
2125
|
-
- `_evaluate_math_embed(expression: str, context: Any, log_identifier: str, format_spec: Optional[str] = None) -> Tuple[str, Optional[str], int]` - Evaluates mathematical expressions using asteval
|
|
2126
|
-
- `_evaluate_datetime_embed(expression: str, context: Any, log_identifier: str, format_spec: Optional[str] = None) -> Tuple[str, Optional[str], int]` - Formats current datetime
|
|
2127
|
-
- `_evaluate_uuid_embed(expression: str, context: Any, log_identifier: str, format_spec: Optional[str] = None) -> Tuple[str, Optional[str], int]` - Generates UUID4 strings
|
|
2128
|
-
- `_evaluate_artifact_meta_embed(expression: str, context: Dict[str, Any], log_identifier: str, format_spec: Optional[str] = None) -> Tuple[str, Optional[str], int]` - Loads and formats artifact metadata
|
|
2129
|
-
- `_evaluate_artifact_content_embed(expression: str, context: Any, log_identifier: str, config: Optional[Dict] = None) -> Tuple[Optional[bytes], Optional[str], Optional[str]]` - Loads raw artifact content
|
|
2130
|
-
|
|
2131
|
-
**Constants/Variables:**
|
|
2132
|
-
- `EMBED_EVALUATORS: Dict[str, Callable]` - Registry mapping embed types to evaluator functions
|
|
2133
|
-
- `MATH_SAFE_SYMBOLS: Dict[str, Any]` - Safe mathematical functions and constants for math embeds
|
|
2134
|
-
|
|
2135
|
-
**Usage Examples:**
|
|
2136
|
-
```python
|
|
2137
|
-
from solace_agent_mesh.common.utils.embeds.evaluators import EMBED_EVALUATORS
|
|
2138
|
-
|
|
2139
|
-
# Math evaluation
|
|
2140
|
-
result, error, size = EMBED_EVALUATORS["math"]("2 + 3 * 4", {}, "[Test]", ".2f")
|
|
2141
|
-
# result: "14.00", error: None, size: 5
|
|
2142
|
-
|
|
2143
|
-
# DateTime formatting
|
|
2144
|
-
result, error, size = EMBED_EVALUATORS["datetime"]("%Y-%m-%d", {}, "[Test]")
|
|
2145
|
-
# result: "2024-01-15", error: None, size: 10
|
|
2146
|
-
```
|
|
2147
|
-
|
|
2148
|
-
### modifiers.py
|
|
2149
|
-
**Purpose:** Implements data transformation functions that can be chained together in artifact_content embeds.
|
|
2150
|
-
|
|
2151
|
-
**Import:** `from solace_agent_mesh.common.utils.embeds.modifiers import MODIFIER_DEFINITIONS, _parse_modifier_chain`
|
|
2152
|
-
|
|
2153
|
-
**Functions:**
|
|
2154
|
-
- `_apply_jsonpath(current_data: Any, expression: str, mime_type: Optional[str], log_id: str) -> Tuple[Any, Optional[str], Optional[str]]` - Applies JSONPath expressions to JSON data
|
|
2155
|
-
- `_apply_select_cols(current_data: List[Dict], cols_str: str, mime_type: Optional[str], log_id: str) -> Tuple[Any, Optional[str], Optional[str]]` - Selects specific columns from tabular data
|
|
2156
|
-
- `_apply_filter_rows_eq(current_data: List[Dict], filter_spec: str, mime_type: Optional[str], log_id: str) -> Tuple[Any, Optional[str], Optional[str]]` - Filters rows by column value equality
|
|
2157
|
-
- `_apply_slice_rows(current_data: List[Dict], slice_spec: str, mime_type: Optional[str], log_id: str) -> Tuple[Any, Optional[str], Optional[str]]` - Slices rows using Python slice notation
|
|
2158
|
-
- `_apply_slice_lines(current_data: str, slice_spec: str, mime_type: Optional[str], log_id: str) -> Tuple[Any, Optional[str], Optional[str]]` - Slices text lines
|
|
2159
|
-
- `_apply_grep(current_data: str, pattern: str, mime_type: Optional[str], log_id: str) -> Tuple[Any, Optional[str], Optional[str]]` - Filters lines matching regex pattern
|
|
2160
|
-
- `_apply_head(current_data: str, n_str: str, mime_type: Optional[str], log_id: str) -> Tuple[Any, Optional[str], Optional[str]]` - Returns first N lines
|
|
2161
|
-
- `_apply_tail(current_data: str, n_str: str, mime_type: Optional[str], log_id: str) -> Tuple[Any, Optional[str], Optional[str]]` - Returns last N lines
|
|
2162
|
-
- `_apply_template(current_data: Any, template_spec: str, mime_type: Optional[str], log_id: str, context: Any) -> Tuple[Any, Optional[str], Optional[str]]` - Applies Mustache templates from artifacts
|
|
2163
|
-
- `_parse_modifier_chain(expression: str) -> Tuple[str, List[Tuple[str, str]], Optional[str]]` - Parses artifact_content expression into components
|
|
2164
|
-
|
|
2165
|
-
**Constants/Variables:**
|
|
2166
|
-
- `MODIFIER_IMPLEMENTATIONS: Dict[str, Callable]` - Registry of modifier functions
|
|
2167
|
-
- `MODIFIER_DEFINITIONS: Dict[str, Dict[str, Any]]` - Modifier metadata including accepted/produced formats
|
|
2168
|
-
|
|
2169
|
-
**Usage Examples:**
|
|
2170
|
-
```python
|
|
2171
|
-
from solace_agent_mesh.common.utils.embeds.modifiers import _parse_modifier_chain
|
|
2172
|
-
|
|
2173
|
-
# Parse a complex artifact_content expression
|
|
2174
|
-
expression = "data.csv:1 >>> select_cols:name,age >>> filter_rows_eq:age:25 >>> format:json"
|
|
2175
|
-
artifact_spec, modifiers, output_format = _parse_modifier_chain(expression)
|
|
2176
|
-
# artifact_spec: "data.csv:1"
|
|
2177
|
-
# modifiers: [("select_cols", "name,age"), ("filter_rows_eq", "age:25")]
|
|
2178
|
-
# output_format: "json"
|
|
2179
|
-
```
|
|
2180
|
-
|
|
2181
|
-
### resolver.py
|
|
2182
|
-
**Purpose:** Core orchestration engine that handles the complete embed resolution process including modifier chains and recursion.
|
|
2183
|
-
|
|
2184
|
-
**Import:** `from solace_agent_mesh.common.utils.embeds.resolver import resolve_embeds_in_string, evaluate_embed`
|
|
2185
|
-
|
|
2186
|
-
**Functions:**
|
|
2187
|
-
- `resolve_embeds_in_string(text: str, context: Any, resolver_func: Callable, types_to_resolve: Set[str], log_identifier: str = "[EmbedUtil]", config: Optional[Dict[str, Any]] = None) -> Tuple[str, int, List[Tuple[int, Any]]]` - Single-pass embed resolution with buffering support
|
|
2188
|
-
- `resolve_embeds_recursively_in_string(text: str, context: Any, resolver_func: Callable, types_to_resolve: Set[str], log_identifier: str, config: Optional[Dict], max_depth: int, current_depth: int = 0, visited_artifacts: Optional[Set[Tuple[str, int]]] = None, accumulated_size: int = 0, max_total_size: int = -1) -> str` - Recursive embed resolution with safety limits
|
|
2189
|
-
- `evaluate_embed(embed_type: str, expression: str, format_spec: Optional[str], context: Dict[str, Any], log_identifier: str, config: Optional[Dict] = None, current_depth: int = 0, visited_artifacts: Optional[Set[Tuple[str, int]]] = None) -> Union[Tuple[str, Optional[str], int], Tuple[None, str, Any]]` - Main embed evaluation dispatcher
|
|
2190
|
-
|
|
2191
|
-
**Usage Examples:**
|
|
2192
|
-
```python
|
|
2193
|
-
from solace_agent_mesh.common.utils.embeds.resolver import resolve_embeds_in_string, evaluate_embed
|
|
2194
|
-
|
|
2195
|
-
# Single-pass resolution
|
|
2196
|
-
text = "Result: «math:2+3» and «uuid:new»"
|
|
2197
|
-
context = {"artifact_service": service, "session_context": session_ctx}
|
|
2198
|
-
|
|
2199
|
-
resolved_text, processed_index, signals = await resolve_embeds_in_string(
|
|
2200
|
-
text=text,
|
|
2201
|
-
context=context,
|
|
2202
|
-
resolver_func=evaluate_embed,
|
|
2203
|
-
types_to_resolve={"math", "uuid"},
|
|
2204
|
-
log_identifier="[MyApp]",
|
|
2205
|
-
config={}
|
|
2206
|
-
)
|
|
2207
|
-
|
|
2208
|
-
# Complex artifact content with modifiers
|
|
2209
|
-
result, error, size = await evaluate_embed(
|
|
2210
|
-
embed_type="artifact_content",
|
|
2211
|
-
expression="sales.csv >>> select_cols:product,revenue >>> format:json",
|
|
2212
|
-
format_spec=None,
|
|
2213
|
-
context=context,
|
|
2214
|
-
log_identifier="[Sales]"
|
|
2215
|
-
)
|
|
2216
|
-
```
|
|
2217
|
-
|
|
2218
|
-
### types.py
|
|
2219
|
-
|
|
2220
|
-
================================================================================
|
|
2221
|
-
|
|
2222
|
-
## Section 11: solace_agent_mesh/common/utils/utils_llm.txt
|
|
2223
|
-
|
|
2224
|
-
**Source file:** `solace_agent_mesh/common/utils/utils_llm.txt`
|
|
2225
|
-
|
|
2226
|
-
## Quick Summary
|
|
2227
|
-
The `utils` directory provides essential utility functions and tools for the Solace Agent Mesh system. It contains both direct utility files for common operations (MIME type handling, caching, message validation, authentication) and a sophisticated `embeds` subdirectory that implements a dynamic expression evaluation system. The utilities work together to provide platform compatibility, security features, data processing capabilities, and dynamic content generation for agent workflows.
|
|
2228
|
-
|
|
2229
|
-
## Files and Subdirectories Overview
|
|
2230
|
-
|
|
2231
|
-
### Direct Files:
|
|
2232
|
-
- **`__init__.py`** - Main entry point exporting commonly used utilities like MIME type checking
|
|
2233
|
-
- **`artifact_utils.py`** - Utilities for working with ADK artifacts, including version resolution
|
|
2234
|
-
- **`asyncio_macos_fix.py`** - Automatic fix for asyncio subprocess issues on macOS
|
|
2235
|
-
- **`in_memory_cache.py`** - Thread-safe singleton cache with TTL support
|
|
2236
|
-
- **`initializer.py`** - Enterprise feature initialization and configuration loading
|
|
2237
|
-
- **`log_formatters.py`** - Custom logging formatters for platforms like Datadog
|
|
2238
|
-
- **`message_utils.py`** - Message size calculation and validation utilities
|
|
2239
|
-
- **`mime_helpers.py`** - MIME type classification and file extension utilities
|
|
2240
|
-
- **`push_notification_auth.py`** - JWT-based authentication for push notifications
|
|
2241
|
-
- **`pydantic_utils.py`** - Pydantic BaseModel with dict-like access for configuration
|
|
2242
|
-
- **`type_utils.py`** - Robust type checking utilities for development environments
|
|
2243
|
-
|
|
2244
|
-
### Subdirectories:
|
|
2245
|
-
- **`embeds/`** - Dynamic expression evaluation system using `«...»` syntax for mathematical calculations, datetime formatting, UUID generation, and artifact content processing
|
|
2246
|
-
|
|
2247
|
-
## Developer API Reference
|
|
2248
|
-
|
|
2249
|
-
### Direct Files
|
|
2250
|
-
|
|
2251
|
-
#### __init__.py
|
|
2252
|
-
**Purpose:** Main entry point for the utils package, exporting the most commonly used utility functions
|
|
2253
|
-
**Import:** `from solace_agent_mesh.common.utils import is_text_based_mime_type`
|
|
2254
|
-
|
|
2255
|
-
**Functions:**
|
|
2256
|
-
- `is_text_based_mime_type(mime_type: Optional[str]) -> bool` - Checks if a MIME type represents text-based content
|
|
2257
|
-
|
|
2258
|
-
#### artifact_utils.py
|
|
2259
|
-
**Purpose:** Common utility functions for working with ADK artifacts
|
|
2260
|
-
**Import:** `from solace_agent_mesh.common.utils.artifact_utils import get_latest_artifact_version`
|
|
2261
|
-
|
|
2262
|
-
**Functions:**
|
|
2263
|
-
- `get_latest_artifact_version(artifact_service: BaseArtifactService, app_name: str, user_id: str, session_id: str, filename: str) -> Optional[int]` - Resolves the latest version number for a given artifact
|
|
2264
|
-
|
|
2265
|
-
#### asyncio_macos_fix.py
|
|
2266
|
-
**Purpose:** Automatic fix for asyncio subprocess creation issues on macOS (imported for side effects)
|
|
2267
|
-
**Import:** `from solace_agent_mesh.common.utils import asyncio_macos_fix`
|
|
2268
|
-
|
|
2269
|
-
**Functions:**
|
|
2270
|
-
- `apply_macos_asyncio_fix() -> bool` - Applies the asyncio fix for macOS subprocess support
|
|
2271
|
-
- `ensure_asyncio_compatibility() -> bool` - Ensures asyncio compatibility for subprocess creation
|
|
2272
|
-
|
|
2273
|
-
#### in_memory_cache.py
|
|
2274
|
-
**Purpose:** Thread-safe singleton in-memory cache with TTL support
|
|
2275
|
-
**Import:** `from solace_agent_mesh.common.utils.in_memory_cache import InMemoryCache`
|
|
2276
|
-
|
|
2277
|
-
**Classes:**
|
|
2278
|
-
- **`InMemoryCache`** - Singleton cache class
|
|
2279
|
-
- `set(key: str, value: Any, ttl: Optional[int] = None) -> None` - Store value with optional TTL
|
|
2280
|
-
- `get(key: str, default: Any = None) -> Any` - Retrieve value or default
|
|
2281
|
-
- `delete(key: str) -> bool` - Delete specific key
|
|
2282
|
-
- `clear() -> bool` - Clear all cached data
|
|
2283
|
-
|
|
2284
|
-
#### initializer.py
|
|
2285
|
-
**Purpose:** Handles initialization of enterprise features if available
|
|
2286
|
-
**Import:** `from solace_agent_mesh.common.utils.initializer import initialize`
|
|
2287
|
-
|
|
2288
|
-
**Functions:**
|
|
2289
|
-
- `initialize() -> None` - Initializes enterprise features using SAM_AUTHORIZATION_CONFIG environment variable
|
|
2290
|
-
|
|
2291
|
-
#### log_formatters.py
|
|
2292
|
-
**Purpose:** Custom logging formatters for structured output
|
|
2293
|
-
**Import:** `from solace_agent_mesh.common.utils.log_formatters import DatadogJsonFormatter`
|
|
2294
|
-
|
|
2295
|
-
**Classes:**
|
|
2296
|
-
- **`DatadogJsonFormatter(logging.Formatter)`** - JSON formatter with Datadog-compatible attributes including trace IDs
|
|
2297
|
-
|
|
2298
|
-
#### message_utils.py
|
|
2299
|
-
**Purpose:** Message size calculation and validation utilities
|
|
2300
|
-
**Import:** `from solace_agent_mesh.common.utils.message_utils import calculate_message_size, validate_message_size`
|
|
2301
|
-
|
|
2302
|
-
**Functions:**
|
|
2303
|
-
- `calculate_message_size(payload: Dict[str, Any]) -> int` - Calculate exact message size using JSON + UTF-8 encoding
|
|
2304
|
-
- `validate_message_size(payload: Dict[str, Any], max_size_bytes: int, component_identifier: str = "Unknown") -> Tuple[bool, int]` - Validate message doesn't exceed size limits
|
|
2305
|
-
|
|
2306
|
-
**Constants:**
|
|
2307
|
-
- `MAX_UTF8_BYTES_PER_CHARACTER: int` - Maximum UTF-8 bytes per character (4)
|
|
2308
|
-
|
|
2309
|
-
#### mime_helpers.py
|
|
2310
|
-
**Purpose:** MIME type classification and file extension utilities
|
|
2311
|
-
**Import:** `from solace_agent_mesh.common.utils.mime_helpers import is_text_based_mime_type, get_extension_for_mime_type, is_text_based_file`
|
|
2312
|
-
|
|
2313
|
-
**Functions:**
|
|
2314
|
-
- `is_text_based_mime_type(mime_type: Optional[str]) -> bool` - Check if MIME type is text-based
|
|
2315
|
-
- `is_text_based_file(mime_type: Optional[str], content_bytes: Optional[bytes] = None) -> bool` - Determine if file is text-based using MIME type and content analysis
|
|
2316
|
-
- `get_extension_for_mime_type(mime_type: Optional[str], default_extension: str = ".dat") -> str` - Get file extension for MIME type
|
|
2317
|
-
|
|
2318
|
-
**Constants:**
|
|
2319
|
-
- `TEXT_CONTAINER_MIME_TYPES: Set[str]` - Set of non-text/* MIME types that contain text
|
|
2320
|
-
|
|
2321
|
-
#### push_notification_auth.py
|
|
2322
|
-
**Purpose:** JWT-based authentication for push notifications with request integrity verification
|
|
2323
|
-
**Import:** `from solace_agent_mesh.common.utils.push_notification_auth import PushNotificationSenderAuth, PushNotificationReceiverAuth`
|
|
2324
|
-
|
|
2325
|
-
**Classes:**
|
|
2326
|
-
- **`PushNotificationSenderAuth`** - Handles sending authenticated notifications
|
|
2327
|
-
- `generate_jwk() -> None` - Generate RSA key pair for signing
|
|
2328
|
-
- `handle_jwks_endpoint(request: Request) -> JSONResponse` - Serve public keys endpoint
|
|
2329
|
-
- `send_push_notification(url: str, data: dict[str, Any]) -> None` - Send authenticated notification
|
|
2330
|
-
- `verify_push_notification_url(url: str) -> bool` - Verify notification URL
|
|
2331
|
-
- **`PushNotificationReceiverAuth`** - Handles receiving and verifying notifications
|
|
2332
|
-
- `load_jwks(jwks_url: str) -> None` - Load public keys from JWKS endpoint
|
|
2333
|
-
- `verify_push_notification(request: Request) -> bool` - Verify notification authenticity
|
|
2334
|
-
|
|
2335
|
-
#### pydantic_utils.py
|
|
2336
|
-
**Purpose:** Provides a Pydantic BaseModel for SAM configuration with dict-like access
|
|
2337
|
-
**Import:** `from solace_agent_mesh.common.utils.pydantic_utils import SamConfigBase`
|
|
2338
|
-
|
|
2339
|
-
**Classes:**
|
|
2340
|
-
- **`SamConfigBase(BaseModel)`** - Pydantic BaseModel with dict-like access
|
|
2341
|
-
- `model_validate_and_clean(cls: Type[T], obj: Any) -> T` - Validates dict after removing None values
|
|
2342
|
-
- `get(key: str, default: Any = None) -> Any` - Dict-like .get() method
|
|
2343
|
-
- `__getitem__(key: str) -> Any` - Dict-like ['key'] access
|
|
2344
|
-
- `__setitem__(key: str, value: Any)` - Dict-like ['key'] = value assignment
|
|
2345
|
-
- `__contains__(key: str) -> bool` - Dict-like 'in' support
|
|
2346
|
-
- `keys()`, `values()`, `items()`, `__iter__()` - Dict-like iteration methods
|
|
2347
|
-
|
|
2348
|
-
#### type_utils.py
|
|
2349
|
-
**Purpose:** Utilities for robust type checking, especially in development environments
|
|
2350
|
-
**Import:** `from solace_agent_mesh.common.utils.type_utils import is_subclass_by_name`
|
|
2351
|
-
|
|
2352
|
-
**Functions:**
|
|
2353
|
-
- `is_subclass_by_name(cls_to_check: type, base_class_name: str) -> bool` - Checks if a class is a subclass by looking for the base class name in the MRO
|
|
2354
|
-
|
|
2355
|
-
### Subdirectory APIs
|
|
2356
|
-
|
|
2357
|
-
#### embeds/
|
|
2358
|
-
**Purpose:** Comprehensive dynamic expression evaluation system using `«...»` syntax for mathematical calculations, datetime formatting, UUID generation, and artifact content processing with transformation pipelines
|
|
2359
|
-
**Key Exports:** Main resolution functions, evaluator registry, modifier system, and type constants
|
|
2360
|
-
**Import Examples:**
|
|
2361
|
-
```python
|
|
2362
|
-
from solace_agent_mesh.common.utils.embeds import resolve_embeds_recursively_in_string, evaluate_embed, EMBED_REGEX
|
|
2363
|
-
from solace_agent_mesh.common.utils.embeds.constants import EARLY_EMBED_TYPES, LATE_EMBED_TYPES
|
|
2364
|
-
from solace_agent_mesh.common.utils.embeds.types import DataFormat
|
|
2365
|
-
```
|
|
2366
|
-
|
|
2367
|
-
## Complete Usage Guide
|
|
2368
|
-
|
|
2369
|
-
### 1. Basic Utility Operations
|
|
2370
|
-
|
|
2371
|
-
```python
|
|
2372
|
-
# Import commonly used utilities
|
|
2373
|
-
from solace_agent_mesh.common.utils import is_text_based_mime_type
|
|
2374
|
-
from solace_agent_mesh.common.utils.in_memory_cache import InMemoryCache
|
|
2375
|
-
from solace_agent_mesh.common.utils.message_utils import validate_message_size, calculate_message_size
|
|
2376
|
-
from solace_agent_mesh.common.utils.mime_helpers import get_extension_for_mime_type, is_text_based_file
|
|
2377
|
-
|
|
2378
|
-
# MIME type checking
|
|
2379
|
-
if is_text_based_mime_type("application/json"):
|
|
2380
|
-
print("JSON is text-based")
|
|
2381
|
-
|
|
2382
|
-
# File analysis with content
|
|
2383
|
-
with open("data.bin", "rb") as f:
|
|
2384
|
-
content = f.read()
|
|
2385
|
-
if is_text_based_file("application/octet-stream", content):
|
|
2386
|
-
print("File contains text despite binary MIME type")
|
|
2387
|
-
|
|
2388
|
-
# Singleton cache usage
|
|
2389
|
-
cache = InMemoryCache()
|
|
2390
|
-
cache.set("user_session", {"user_id": "123", "role": "admin"}, ttl=3600) # 1 hour TTL
|
|
2391
|
-
session_data = cache.get("user_session", {})
|
|
2392
|
-
|
|
2393
|
-
# Message size validation
|
|
2394
|
-
payload = {"message": "Hello world", "data": [1, 2, 3], "metadata": {"timestamp": "2024-01-15"}}
|
|
2395
|
-
is_valid, size = validate_message_size(payload, max_size_bytes=1024, component_identifier="MessageProcessor")
|
|
2396
|
-
if not is_valid:
|
|
2397
|
-
print(f"Message too large: {size} bytes exceeds 1024 byte limit")
|
|
2398
|
-
|
|
2399
|
-
# Get appropriate file extension
|
|
2400
|
-
extension = get_extension_for_mime_type("image/png") # Returns ".png"
|
|
2401
|
-
filename = f"image_{uuid.uuid4()}{extension}"
|
|
2402
|
-
```
|
|
2403
|
-
|
|
2404
|
-
### 2. Configuration and Type Utilities
|
|
2405
|
-
|
|
2406
|
-
```python
|
|
2407
|
-
from solace_agent_mesh.common.utils.pydantic_utils import SamConfigBase
|
|
2408
|
-
from solace_agent_mesh.common.utils.type_utils import is_subclass_by_name
|
|
2409
|
-
from pydantic import Field
|
|
2410
|
-
from typing import Optional
|
|
2411
|
-
|
|
2412
|
-
# Define configuration with Pydantic validation and dict-like access
|
|
2413
|
-
class AgentConfig(SamConfigBase):
|
|
2414
|
-
name: str
|
|
2415
|
-
timeout: int = 30
|
|
2416
|
-
debug: bool = False
|
|
2417
|
-
api_key: Optional[str] = None
|
|
2418
|
-
|
|
2419
|
-
# Load config from YAML/dict with None value cleaning
|
|
2420
|
-
config_dict = {
|
|
2421
|
-
"name": "my_agent",
|
|
2422
|
-
"timeout": None, # Will use default value of 30
|
|
2423
|
-
"debug": True,
|
|
2424
|
-
"api_key": None # Will use default value of None
|
|
2425
|
-
}
|
|
2426
|
-
|
|
2427
|
-
config = AgentConfig.model_validate_and_clean(config_dict)
|
|
2428
|
-
|
|
2429
|
-
# Use both Pydantic and dict-style access
|
|
2430
|
-
print(config.name) # Pydantic style: "my_agent"
|
|
2431
|
-
print(config["timeout"]) # Dict style: 30 (default applied)
|
|
2432
|
-
print(config.get("debug", False)) # Dict .get(): True
|
|
2433
|
-
|
|
2434
|
-
# Check if field was explicitly set
|
|
2435
|
-
if "api_key" in config:
|
|
2436
|
-
print("API key was provided")
|
|
2437
|
-
else:
|
|
2438
|
-
print("API key not provided, using default")
|
|
2439
|
-
|
|
2440
|
-
# Robust type checking for development
|
|
2441
|
-
class BaseAgent:
|
|
2442
|
-
pass
|
|
2443
|
-
|
|
2444
|
-
class MyAgent(BaseAgent):
|
|
2445
|
-
pass
|
|
2446
|
-
|
|
2447
|
-
# This works even if BaseAgent is loaded from different paths
|
|
2448
|
-
if is_subclass_by_name(MyAgent, "BaseAgent"):
|
|
2449
|
-
print("MyAgent is a BaseAgent subclass")
|
|
2450
|
-
```
|
|
2451
|
-
|
|
2452
|
-
### 3. Platform Compatibility and System Initialization
|
|
2453
|
-
|
|
2454
|
-
```python
|
|
2455
|
-
# Early in application startup - import for side effects
|
|
2456
|
-
from solace_agent_mesh.common.utils import asyncio_macos_fix # Auto-applies macOS fix
|
|
2457
|
-
from solace_agent_mesh.common.utils.initializer import initialize
|
|
2458
|
-
|
|
2459
|
-
# Initialize enterprise features if available
|
|
2460
|
-
try:
|
|
2461
|
-
initialize()
|
|
2462
|
-
print("Enterprise features initialized")
|
|
2463
|
-
except Exception as e:
|
|
2464
|
-
print(f"Running in community mode: {e}")
|
|
2465
|
-
|
|
2466
|
-
# Now asyncio subprocess creation works reliably on macOS
|
|
2467
|
-
import asyncio
|
|
2468
|
-
|
|
2469
|
-
async def run_command(cmd: str):
|
|
2470
|
-
process = await asyncio.create_subprocess_exec(
|
|
2471
|
-
*cmd.split(),
|
|
2472
|
-
stdout=asyncio.subprocess.PIPE,
|
|
2473
|
-
stderr=asyncio.subprocess.PIPE
|
|
2474
|
-
)
|
|
2475
|
-
stdout, stderr = await process.communicate()
|
|
2476
|
-
return stdout.decode(), stderr.decode(), process.returncode
|
|
2477
|
-
|
|
2478
|
-
# This will work on macOS without NotImplementedError
|
|
2479
|
-
result = await run_command("echo Hello World")
|
|
2480
|
-
```
|
|
2481
|
-
|
|
2482
|
-
### 4. Structured Logging Setup
|
|
2483
|
-
|
|
2484
|
-
```python
|
|
2485
|
-
import logging
|
|
2486
|
-
import os
|
|
2487
|
-
from solace_agent_mesh.common.utils.log_formatters import DatadogJsonFormatter
|
|
2488
|
-
|
|
2489
|
-
# Configure structured JSON logging
|
|
2490
|
-
logger = logging.getLogger("my_application")
|
|
2491
|
-
handler = logging.StreamHandler()
|
|
2492
|
-
handler.setFormatter(DatadogJsonFormatter())
|
|
2493
|
-
logger.addHandler(handler)
|
|
2494
|
-
logger.setLevel(logging.INFO)
|
|
2495
|
-
|
|
2496
|
-
# Set service name for Datadog
|
|
2497
|
-
os.environ["SERVICE_NAME"] = "my_agent_service"
|
|
2498
|
-
|
|
2499
|
-
# Log with structured data - automatically includes trace IDs if available
|
|
2500
|
-
logger.info("User action completed", extra={
|
|
2501
|
-
"user_id": "user123",
|
|
2502
|
-
"action": "file_upload",
|
|
2503
|
-
"file_size": 1024,
|
|
2504
|
-
"dd.trace_id": "abc123" # Will be included in JSON output
|
|
2505
|
-
})
|
|
2506
|
-
|
|
2507
|
-
# Output will be JSON with timestamp, level, service, code location, etc.
|
|
2508
|
-
```
|
|
2509
|
-
|
|
2510
|
-
### 5. Secure Push Notification System
|
|
2511
|
-
|
|
2512
|
-
```python
|
|
2513
|
-
from solace_agent_mesh.common.utils.push_notification_auth import (
|
|
2514
|
-
PushNotificationSenderAuth,
|
|
2515
|
-
PushNotificationReceiverAuth
|
|
2516
|
-
)
|
|
2517
|
-
from starlette.applications import Starlette
|
|
2518
|
-
from starlette.requests import Request
|
|
2519
|
-
from starlette.responses import Response, JSONResponse
|
|
2520
|
-
|
|
2521
|
-
# Sender setup and usage
|
|
2522
|
-
sender_auth = PushNotificationSenderAuth()
|
|
2523
|
-
sender_auth.generate_jwk() # Generate RSA key pair
|
|
2524
|
-
|
|
2525
|
-
async def notify_clients(event_data: dict):
|
|
2526
|
-
client_urls = ["https://client1.example.com/webhook", "https://client2.example.com/webhook"]
|
|
2527
|
-
|
|
2528
|
-
for url in client_urls:
|
|
2529
|
-
# Verify URL accepts notifications
|
|
2530
|
-
if await sender_auth.verify_push_notification_url(url):
|
|
2531
|
-
# Send authenticated notification
|
|
2532
|
-
await sender_auth.send_push_notification(url, {
|
|
2533
|
-
"event": "data_updated",
|
|
2534
|
-
"timestamp": "2024-01-15T10:30:00Z",
|
|
2535
|
-
"data": event_data
|
|
2536
|
-
})
|
|
2537
|
-
else:
|
|
2538
|
-
print(f"Failed to verify URL: {url}")
|
|
2539
|
-
|
|
2540
|
-
# Receiver setup
|
|
2541
|
-
app = Starlette()
|
|
2542
|
-
receiver_auth = PushNotificationReceiverAuth()
|
|
2543
|
-
|
|
2544
|
-
# Load sender's public keys
|
|
2545
|
-
await receiver_auth.load_jwks("https://sender.example.com/.well-known/jwks.json")
|
|
2546
|
-
|
|
2547
|
-
@app.route("/webhook", methods=["POST"])
|
|
2548
|
-
async def webhook_handler(request: Request):
|
|
2549
|
-
try:
|
|
2550
|
-
# Verify JWT signature and request integrity
|
|
2551
|
-
if await receiver_auth.verify_push_notification(request):
|
|
2552
|
-
data = await request.json()
|
|
2553
|
-
# Process authenticated notification
|
|
2554
|
-
print(f"Received verified notification: {data}")
|
|
2555
|
-
return Response("OK")
|
|
2556
|
-
else:
|
|
2557
|
-
return Response("Unauthorized", status_code=401)
|
|
2558
|
-
except Exception as e:
|
|
2559
|
-
print(f"
|
|
2560
|
-
|
|
2561
|
-
================================================================================
|
|
2562
|
-
|