solace-agent-mesh 1.7.1__py3-none-any.whl → 1.13.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of solace-agent-mesh might be problematic. Click here for more details.
- solace_agent_mesh/agent/adk/alembic/README +74 -0
- solace_agent_mesh/agent/adk/alembic/env.py +77 -0
- solace_agent_mesh/agent/adk/alembic/script.py.mako +28 -0
- solace_agent_mesh/agent/adk/alembic/versions/e2902798564d_adk_session_db_upgrade.py +52 -0
- solace_agent_mesh/agent/adk/alembic.ini +112 -0
- solace_agent_mesh/agent/adk/artifacts/filesystem_artifact_service.py +164 -0
- solace_agent_mesh/agent/adk/artifacts/s3_artifact_service.py +163 -0
- solace_agent_mesh/agent/adk/callbacks.py +752 -127
- solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +99 -7
- solace_agent_mesh/agent/adk/intelligent_mcp_callbacks.py +52 -5
- solace_agent_mesh/agent/adk/mcp_content_processor.py +1 -1
- solace_agent_mesh/agent/adk/models/lite_llm.py +34 -16
- solace_agent_mesh/agent/adk/models/oauth2_token_manager.py +24 -137
- solace_agent_mesh/agent/adk/runner.py +66 -8
- solace_agent_mesh/agent/adk/schema_migration.py +88 -0
- solace_agent_mesh/agent/adk/services.py +41 -1
- solace_agent_mesh/agent/adk/setup.py +220 -32
- solace_agent_mesh/agent/adk/stream_parser.py +229 -40
- solace_agent_mesh/agent/protocol/event_handlers.py +219 -33
- solace_agent_mesh/agent/proxies/a2a/component.py +572 -75
- solace_agent_mesh/agent/proxies/a2a/config.py +80 -4
- solace_agent_mesh/agent/proxies/base/component.py +188 -22
- solace_agent_mesh/agent/proxies/base/proxy_task_context.py +3 -1
- solace_agent_mesh/agent/sac/app.py +37 -12
- solace_agent_mesh/agent/sac/component.py +322 -52
- solace_agent_mesh/agent/sac/patch_adk.py +8 -16
- solace_agent_mesh/agent/sac/task_execution_context.py +90 -0
- solace_agent_mesh/agent/tools/__init__.py +3 -0
- solace_agent_mesh/agent/tools/audio_tools.py +3 -3
- solace_agent_mesh/agent/tools/builtin_artifact_tools.py +698 -24
- solace_agent_mesh/agent/tools/deep_research_tools.py +2161 -0
- solace_agent_mesh/agent/tools/peer_agent_tool.py +82 -15
- solace_agent_mesh/agent/tools/time_tools.py +126 -0
- solace_agent_mesh/agent/tools/tool_config_types.py +54 -2
- solace_agent_mesh/agent/tools/web_search_tools.py +279 -0
- solace_agent_mesh/agent/tools/web_tools.py +125 -17
- solace_agent_mesh/agent/utils/artifact_helpers.py +243 -5
- solace_agent_mesh/agent/utils/context_helpers.py +17 -0
- solace_agent_mesh/assets/docs/404.html +6 -6
- solace_agent_mesh/assets/docs/assets/css/{styles.906a1503.css → styles.8162edfb.css} +1 -1
- solace_agent_mesh/assets/docs/assets/js/05749d90.19ac4f35.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/15ba94aa.e186750d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/15e40e79.434bb30f.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/17896441.e612dfb4.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2279.550aa580.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/{17896441.a5e82f9b.js.LICENSE.txt → 2279.550aa580.js.LICENSE.txt} +6 -0
- solace_agent_mesh/assets/docs/assets/js/240a0364.83e37aa8.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2e32b5e0.2f0db237.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3a6c6137.7e61915d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3ac1795d.7f7ab1c1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3ff0015d.e53c9b78.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/41adc471.0e95b87c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/4667dc50.bf2ad456.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/49eed117.493d6f99.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{509e993c.4c7a1a6d.js → 509e993c.a1fbf45a.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/547e15cc.8e6da617.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/55b7b518.29d6e75d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5b8d9c11.d4eb37b8.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5c2bd65f.1ee87753.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/60702c0e.a8bdd79b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/64195356.09dbd087.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/66d4869e.30340bd3.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6aaedf65.7253541d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6d84eae0.fd23ba4a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/729898df.7249e9fd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/7e294c01.7c5f6906.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8024126c.e3467286.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/81a99df0.7ed65d45.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/82fbfb93.161823a5.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/924ffdeb.975e428a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/94e8668d.16083b3f.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9bb13469.4523ae20.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/a7d42657.a956689d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/a94703ab.3e5fbcb3.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ab9708a8.3e563275.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/c93cbaa0.0e0d8baf.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/cab03b5b.6a073091.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/cbe2e9ea.07e170dd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e04b235d.06d23db6.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e1b6eeb4.deb2b62e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e3d9abda.1476f570.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e6f9706b.acc800d3.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e92d0134.c147a429.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ee0c2fe7.94d0a351.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/f284c35a.cc97854c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/main.d634009f.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/runtime~main.27bb82a7.js +1 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +68 -68
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +50 -50
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +42 -42
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +55 -55
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +75 -75
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/image-tools/index.html +81 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +67 -50
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/research-tools/index.html +136 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +178 -144
- solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +43 -42
- solace_agent_mesh/assets/docs/docs/documentation/components/index.html +20 -18
- solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +23 -23
- solace_agent_mesh/assets/docs/docs/documentation/components/platform-service/index.html +33 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +45 -45
- solace_agent_mesh/assets/docs/docs/documentation/components/projects/index.html +98 -112
- solace_agent_mesh/assets/docs/docs/documentation/components/prompts/index.html +147 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +208 -125
- solace_agent_mesh/assets/docs/docs/documentation/components/speech/index.html +52 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +28 -28
- solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +29 -29
- solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +14 -14
- solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/index.html +47 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/kubernetes-deployment-guide/index.html +197 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/logging/index.html +67 -53
- solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +17 -17
- solace_agent_mesh/assets/docs/docs/documentation/deploying/proxy_configuration/index.html +49 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +38 -38
- solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +87 -87
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +67 -49
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +17 -17
- solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +51 -51
- solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +22 -22
- solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +27 -27
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +135 -135
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +66 -66
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +51 -51
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +50 -38
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +86 -86
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +51 -51
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +24 -24
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +30 -30
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +44 -44
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/teams-integration/index.html +115 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/agent-builder/index.html +50 -23
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/connectors/index.html +29 -24
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +21 -21
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +40 -37
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/openapi-tools/index.html +324 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +96 -66
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/secure-user-delegated-access/index.html +181 -181
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +75 -75
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/wheel-installation/index.html +27 -27
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +44 -44
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +39 -38
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +30 -30
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +18 -18
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/vibe_coding/index.html +62 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/artifact-storage/index.html +135 -114
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +37 -37
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +14 -14
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +27 -25
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +69 -69
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +72 -72
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/session-storage/index.html +112 -112
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/user-feedback/index.html +28 -28
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +42 -42
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +20 -20
- solace_agent_mesh/assets/docs/docs/documentation/migrations/platform-service-split/index.html +85 -0
- solace_agent_mesh/assets/docs/lunr-index-1768329217460.json +1 -0
- solace_agent_mesh/assets/docs/lunr-index.json +1 -1
- solace_agent_mesh/assets/docs/search-doc-1768329217460.json +1 -0
- solace_agent_mesh/assets/docs/search-doc.json +1 -1
- solace_agent_mesh/assets/docs/sitemap.xml +1 -1
- solace_agent_mesh/cli/__init__.py +1 -1
- solace_agent_mesh/cli/commands/add_cmd/__init__.py +3 -1
- solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +6 -1
- solace_agent_mesh/cli/commands/add_cmd/proxy_cmd.py +100 -0
- solace_agent_mesh/cli/commands/eval_cmd.py +1 -1
- solace_agent_mesh/cli/commands/init_cmd/__init__.py +15 -0
- solace_agent_mesh/cli/commands/init_cmd/directory_step.py +1 -1
- solace_agent_mesh/cli/commands/init_cmd/env_step.py +30 -3
- solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +3 -4
- solace_agent_mesh/cli/commands/init_cmd/platform_service_step.py +85 -0
- solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +16 -3
- solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +2 -1
- solace_agent_mesh/cli/commands/plugin_cmd/catalog_cmd.py +1 -0
- solace_agent_mesh/cli/commands/plugin_cmd/create_cmd.py +3 -3
- solace_agent_mesh/cli/commands/run_cmd.py +64 -49
- solace_agent_mesh/cli/commands/tools_cmd.py +315 -0
- solace_agent_mesh/cli/main.py +15 -0
- solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-tcIFZLis.js → authCallback-KnKMP_vb.js} +1 -1
- solace_agent_mesh/client/webui/frontend/static/assets/client-DpBL2stg.js +25 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-Cd498TV2.js +435 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-rSf8Vu29.css +1 -0
- solace_agent_mesh/client/webui/frontend/static/assets/{vendor-CINwxvwV.js → vendor-CGk8Suyh.js} +189 -94
- solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
- solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
- solace_agent_mesh/client/webui/frontend/static/mockServiceWorker.js +336 -0
- solace_agent_mesh/client/webui/frontend/static/ui-version.json +6 -0
- solace_agent_mesh/common/a2a/types.py +1 -1
- solace_agent_mesh/common/agent_registry.py +38 -11
- solace_agent_mesh/common/data_parts.py +124 -0
- solace_agent_mesh/common/error_handlers.py +83 -0
- solace_agent_mesh/common/exceptions.py +24 -0
- solace_agent_mesh/common/oauth/__init__.py +17 -0
- solace_agent_mesh/common/oauth/oauth_client.py +408 -0
- solace_agent_mesh/common/oauth/utils.py +50 -0
- solace_agent_mesh/common/rag_dto.py +156 -0
- solace_agent_mesh/common/sac/sam_component_base.py +73 -1
- solace_agent_mesh/common/sam_events/event_service.py +2 -2
- solace_agent_mesh/common/utils/embeds/converter.py +1 -8
- solace_agent_mesh/common/utils/embeds/modifiers.py +2 -27
- solace_agent_mesh/common/utils/embeds/resolver.py +94 -25
- solace_agent_mesh/common/utils/embeds/types.py +1 -0
- solace_agent_mesh/common/utils/log_formatters.py +20 -0
- solace_agent_mesh/common/utils/mime_helpers.py +12 -5
- solace_agent_mesh/common/utils/rbac_utils.py +69 -0
- solace_agent_mesh/common/utils/templates/__init__.py +8 -0
- solace_agent_mesh/common/utils/templates/liquid_renderer.py +210 -0
- solace_agent_mesh/common/utils/templates/template_resolver.py +161 -0
- solace_agent_mesh/config_portal/backend/common.py +12 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-CljP4_mv.js +103 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/{components-Rk0n-9cK.js → components-CaC6hG8d.js} +22 -22
- solace_agent_mesh/config_portal/frontend/static/client/assets/{entry.client-mvZjNKiz.js → entry.client-H_TM0YBt.js} +3 -3
- solace_agent_mesh/config_portal/frontend/static/client/assets/{index-DzNKzXrc.js → index-CnFykb2v.js} +16 -16
- solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-f8439d40.js +1 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-BIMqslJB.css +1 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-mJmTIdIk.js +10 -0
- solace_agent_mesh/config_portal/frontend/static/client/index.html +3 -3
- solace_agent_mesh/core_a2a/service.py +3 -2
- solace_agent_mesh/gateway/adapter/base.py +28 -1
- solace_agent_mesh/gateway/adapter/types.py +9 -0
- solace_agent_mesh/gateway/base/app.py +10 -0
- solace_agent_mesh/gateway/base/auth_interface.py +103 -0
- solace_agent_mesh/gateway/base/component.py +451 -10
- solace_agent_mesh/gateway/generic/component.py +274 -30
- solace_agent_mesh/gateway/http_sse/alembic/env.py +0 -7
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_soft_delete_and_search.py +2 -43
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_default_agent_to_projects.py +2 -2
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251108_create_prompt_tables_with_sharing.py +154 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251115_add_parent_task_id.py +32 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251126_add_background_task_fields.py +47 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251202_add_versioned_fields_to_prompts.py +52 -0
- solace_agent_mesh/gateway/http_sse/alembic.ini +0 -36
- solace_agent_mesh/gateway/http_sse/app.py +23 -6
- solace_agent_mesh/gateway/http_sse/component.py +158 -73
- solace_agent_mesh/gateway/http_sse/dependencies.py +50 -57
- solace_agent_mesh/gateway/http_sse/main.py +58 -482
- solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +2 -2
- solace_agent_mesh/gateway/http_sse/repository/entities/project.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/entities/project_user.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/entities/session.py +3 -2
- solace_agent_mesh/gateway/http_sse/repository/entities/task.py +7 -0
- solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +2 -2
- solace_agent_mesh/gateway/http_sse/repository/interfaces.py +2 -2
- solace_agent_mesh/gateway/http_sse/repository/models/__init__.py +5 -0
- solace_agent_mesh/gateway/http_sse/repository/models/prompt_model.py +159 -0
- solace_agent_mesh/gateway/http_sse/repository/models/session_model.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/models/task_model.py +8 -1
- solace_agent_mesh/gateway/http_sse/repository/project_repository.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/project_user_repository.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/session_repository.py +12 -107
- solace_agent_mesh/gateway/http_sse/repository/task_repository.py +86 -2
- solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +38 -7
- solace_agent_mesh/gateway/http_sse/routers/artifacts.py +113 -7
- solace_agent_mesh/gateway/http_sse/routers/auth.py +69 -132
- solace_agent_mesh/gateway/http_sse/routers/config.py +235 -10
- solace_agent_mesh/gateway/http_sse/routers/dto/project_dto.py +69 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/prompt_dto.py +255 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/session_requests.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/base_responses.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/project_responses.py +1 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +3 -2
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/version_responses.py +31 -0
- solace_agent_mesh/gateway/http_sse/routers/feedback.py +2 -2
- solace_agent_mesh/gateway/http_sse/routers/people.py +2 -2
- solace_agent_mesh/gateway/http_sse/routers/projects.py +250 -24
- solace_agent_mesh/gateway/http_sse/routers/prompts.py +1416 -0
- solace_agent_mesh/gateway/http_sse/routers/sessions.py +14 -5
- solace_agent_mesh/gateway/http_sse/routers/speech.py +355 -0
- solace_agent_mesh/gateway/http_sse/routers/sse.py +117 -4
- solace_agent_mesh/gateway/http_sse/routers/tasks.py +509 -149
- solace_agent_mesh/gateway/http_sse/routers/users.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/version.py +343 -0
- solace_agent_mesh/gateway/http_sse/routers/visualization.py +2 -1
- solace_agent_mesh/gateway/http_sse/services/audio_service.py +1227 -0
- solace_agent_mesh/gateway/http_sse/services/background_task_monitor.py +186 -0
- solace_agent_mesh/gateway/http_sse/services/data_retention_service.py +1 -1
- solace_agent_mesh/gateway/http_sse/services/feedback_service.py +1 -1
- solace_agent_mesh/gateway/http_sse/services/project_service.py +539 -12
- solace_agent_mesh/gateway/http_sse/services/prompt_builder_assistant.py +303 -0
- solace_agent_mesh/gateway/http_sse/services/session_service.py +198 -21
- solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +354 -4
- solace_agent_mesh/gateway/http_sse/sse_manager.py +280 -169
- solace_agent_mesh/gateway/http_sse/utils/artifact_copy_utils.py +370 -0
- solace_agent_mesh/gateway/http_sse/utils/stim_utils.py +41 -1
- solace_agent_mesh/services/__init__.py +0 -0
- solace_agent_mesh/services/platform/__init__.py +29 -0
- solace_agent_mesh/services/platform/alembic/env.py +85 -0
- solace_agent_mesh/services/platform/alembic/script.py.mako +28 -0
- solace_agent_mesh/services/platform/alembic.ini +109 -0
- solace_agent_mesh/services/platform/api/__init__.py +3 -0
- solace_agent_mesh/services/platform/api/dependencies.py +154 -0
- solace_agent_mesh/services/platform/api/main.py +314 -0
- solace_agent_mesh/services/platform/api/middleware.py +51 -0
- solace_agent_mesh/services/platform/api/routers/__init__.py +33 -0
- solace_agent_mesh/services/platform/api/routers/health_router.py +31 -0
- solace_agent_mesh/services/platform/app.py +215 -0
- solace_agent_mesh/services/platform/component.py +777 -0
- solace_agent_mesh/shared/__init__.py +14 -0
- solace_agent_mesh/shared/api/__init__.py +42 -0
- solace_agent_mesh/shared/auth/__init__.py +26 -0
- solace_agent_mesh/shared/auth/dependencies.py +204 -0
- solace_agent_mesh/shared/auth/middleware.py +347 -0
- solace_agent_mesh/shared/database/__init__.py +20 -0
- solace_agent_mesh/{gateway/http_sse/shared → shared/database}/base_repository.py +1 -1
- solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_exceptions.py +1 -1
- solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_helpers.py +1 -1
- solace_agent_mesh/shared/exceptions/__init__.py +36 -0
- solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exception_handlers.py +1 -1
- solace_agent_mesh/shared/utils/__init__.py +21 -0
- solace_agent_mesh/templates/logging_config_template.yaml +48 -0
- solace_agent_mesh/templates/main_orchestrator.yaml +12 -1
- solace_agent_mesh/templates/platform.yaml +49 -0
- solace_agent_mesh/templates/plugin_readme_template.md +3 -25
- solace_agent_mesh/templates/plugin_tool_config_template.yaml +109 -0
- solace_agent_mesh/templates/proxy_template.yaml +62 -0
- solace_agent_mesh/templates/webui.yaml +148 -6
- solace_agent_mesh/tools/web_search/__init__.py +18 -0
- solace_agent_mesh/tools/web_search/base.py +84 -0
- solace_agent_mesh/tools/web_search/google_search.py +247 -0
- solace_agent_mesh/tools/web_search/models.py +99 -0
- {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/METADATA +29 -8
- {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/RECORD +334 -313
- {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/WHEEL +1 -1
- solace_agent_mesh/agent/adk/adk_llm.txt +0 -226
- solace_agent_mesh/agent/adk/adk_llm_detail.txt +0 -566
- solace_agent_mesh/agent/adk/artifacts/artifacts_llm.txt +0 -171
- solace_agent_mesh/agent/adk/models/models_llm.txt +0 -189
- solace_agent_mesh/agent/agent_llm.txt +0 -369
- solace_agent_mesh/agent/agent_llm_detail.txt +0 -1702
- solace_agent_mesh/agent/protocol/protocol_llm.txt +0 -81
- solace_agent_mesh/agent/protocol/protocol_llm_detail.txt +0 -92
- solace_agent_mesh/agent/proxies/a2a/a2a_llm.txt +0 -190
- solace_agent_mesh/agent/proxies/base/base_llm.txt +0 -148
- solace_agent_mesh/agent/proxies/proxies_llm.txt +0 -283
- solace_agent_mesh/agent/sac/sac_llm.txt +0 -189
- solace_agent_mesh/agent/sac/sac_llm_detail.txt +0 -200
- solace_agent_mesh/agent/testing/testing_llm.txt +0 -58
- solace_agent_mesh/agent/testing/testing_llm_detail.txt +0 -68
- solace_agent_mesh/agent/tools/tools_llm.txt +0 -276
- solace_agent_mesh/agent/tools/tools_llm_detail.txt +0 -275
- solace_agent_mesh/agent/utils/utils_llm.txt +0 -152
- solace_agent_mesh/agent/utils/utils_llm_detail.txt +0 -149
- solace_agent_mesh/assets/docs/assets/js/05749d90.c70b2be9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/15ba94aa.92fea363.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/15e40e79.36003774.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/240a0364.c39f8388.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/2e32b5e0.33f5d75b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3a6c6137.f5940cfa.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3ac1795d.e4870a49.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3ff0015d.b63ee53a.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/547e15cc.2f7790c1.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/55b7b518.f2b1d1ba.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/5c2bd65f.45b32c2b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/64195356.c498c4d0.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/66d4869e.830d443f.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/6d84eae0.4a5fbf39.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/8024126c.fa0e7186.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/81a99df0.07034dd9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/82fbfb93.139a1a1f.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/924ffdeb.8095e148.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/94e8668d.09ed9234.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/9bb13469.dd1c9b54.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/a94703ab.0438dbc2.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/ab9708a8.245ae0ef.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/c93cbaa0.eaff365e.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/cbe2e9ea.f902fad8.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/db5d6442.3daf1696.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e04b235d.c9c50c7b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e3d9abda.d11c67a7.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e6f9706b.045d0fa1.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e92d0134.3bda61dd.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/f284c35a.5099c51e.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/main.f213fe0c.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/runtime~main.d9606d6a.js +0 -1
- solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes-deployment/index.html +0 -47
- solace_agent_mesh/assets/docs/lunr-index-1762283454666.json +0 -1
- solace_agent_mesh/assets/docs/search-doc-1762283454666.json +0 -1
- solace_agent_mesh/cli/commands/add_cmd/add_cmd_llm.txt +0 -250
- solace_agent_mesh/cli/commands/init_cmd/init_cmd_llm.txt +0 -365
- solace_agent_mesh/cli/commands/plugin_cmd/plugin_cmd_llm.txt +0 -305
- solace_agent_mesh/client/webui/frontend/static/assets/client-CRYdKo2Q.js +0 -25
- solace_agent_mesh/client/webui/frontend/static/assets/main-CojeY_1w.css +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main-ILja9MCG.js +0 -353
- solace_agent_mesh/common/a2a/a2a_llm.txt +0 -175
- solace_agent_mesh/common/a2a/a2a_llm_detail.txt +0 -193
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +0 -445
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm_detail.txt +0 -736
- solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +0 -330
- solace_agent_mesh/common/common_llm.txt +0 -230
- solace_agent_mesh/common/common_llm_detail.txt +0 -2562
- solace_agent_mesh/common/middleware/middleware_llm.txt +0 -174
- solace_agent_mesh/common/middleware/middleware_llm_detail.txt +0 -185
- solace_agent_mesh/common/sac/sac_llm.txt +0 -71
- solace_agent_mesh/common/sac/sac_llm_detail.txt +0 -82
- solace_agent_mesh/common/sam_events/sam_events_llm.txt +0 -104
- solace_agent_mesh/common/sam_events/sam_events_llm_detail.txt +0 -115
- solace_agent_mesh/common/services/providers/providers_llm.txt +0 -81
- solace_agent_mesh/common/services/services_llm.txt +0 -368
- solace_agent_mesh/common/services/services_llm_detail.txt +0 -459
- solace_agent_mesh/common/utils/embeds/embeds_llm.txt +0 -220
- solace_agent_mesh/common/utils/utils_llm.txt +0 -335
- solace_agent_mesh/common/utils/utils_llm_detail.txt +0 -572
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-ByU1X1HD.js +0 -98
- solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-61038fc6.js +0 -1
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-BWvk5-gF.js +0 -10
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-DxRwaWiE.css +0 -1
- solace_agent_mesh/core_a2a/core_a2a_llm.txt +0 -90
- solace_agent_mesh/core_a2a/core_a2a_llm_detail.txt +0 -101
- solace_agent_mesh/gateway/base/base_llm.txt +0 -226
- solace_agent_mesh/gateway/base/base_llm_detail.txt +0 -235
- solace_agent_mesh/gateway/gateway_llm.txt +0 -369
- solace_agent_mesh/gateway/gateway_llm_detail.txt +0 -3885
- solace_agent_mesh/gateway/http_sse/alembic/alembic_llm.txt +0 -345
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_fulltext_search_indexes.py +0 -92
- solace_agent_mesh/gateway/http_sse/alembic/versions/versions_llm.txt +0 -161
- solace_agent_mesh/gateway/http_sse/components/components_llm.txt +0 -105
- solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +0 -299
- solace_agent_mesh/gateway/http_sse/http_sse_llm_detail.txt +0 -3278
- solace_agent_mesh/gateway/http_sse/repository/entities/entities_llm.txt +0 -221
- solace_agent_mesh/gateway/http_sse/repository/models/models_llm.txt +0 -257
- solace_agent_mesh/gateway/http_sse/repository/repository_llm.txt +0 -308
- solace_agent_mesh/gateway/http_sse/routers/dto/dto_llm.txt +0 -450
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/requests_llm.txt +0 -133
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/responses_llm.txt +0 -123
- solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +0 -312
- solace_agent_mesh/gateway/http_sse/services/services_llm.txt +0 -303
- solace_agent_mesh/gateway/http_sse/shared/__init__.py +0 -146
- solace_agent_mesh/gateway/http_sse/shared/shared_llm.txt +0 -319
- solace_agent_mesh/gateway/http_sse/utils/utils_llm.txt +0 -47
- solace_agent_mesh/llm.txt +0 -228
- solace_agent_mesh/llm_detail.txt +0 -2835
- solace_agent_mesh/solace_agent_mesh_llm.txt +0 -362
- solace_agent_mesh/solace_agent_mesh_llm_detail.txt +0 -8599
- solace_agent_mesh/templates/logging_config_template.ini +0 -45
- solace_agent_mesh/templates/templates_llm.txt +0 -147
- /solace_agent_mesh/assets/docs/assets/js/{main.f213fe0c.js.LICENSE.txt → main.d634009f.js.LICENSE.txt} +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/auth_utils.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/pagination.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/response_utils.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/error_dto.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exceptions.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/enums.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/timestamp_utils.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/types.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/utils.py +0 -0
- {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Pydantic models for RAG (Retrieval-Augmented Generation) metadata.
|
|
3
|
+
Handles automatic conversion between snake_case (backend) and camelCase (frontend).
|
|
4
|
+
|
|
5
|
+
This module is placed in common/ to be shared across different components
|
|
6
|
+
(agent tools, gateway, etc.) without creating cross-layer dependencies.
|
|
7
|
+
"""
|
|
8
|
+
|
|
9
|
+
from typing import Any, Dict, List, Optional
|
|
10
|
+
from pydantic import BaseModel, Field
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class RAGSourceResponse(BaseModel):
|
|
14
|
+
"""Schema for RAG source with automatic snake_case to camelCase conversion"""
|
|
15
|
+
citation_id: str = Field(..., alias="citationId", description="Unique citation ID")
|
|
16
|
+
file_id: Optional[str] = Field(None, alias="fileId", description="File identifier")
|
|
17
|
+
filename: Optional[str] = Field(None, description="Filename or title")
|
|
18
|
+
title: Optional[str] = Field(None, description="Source title")
|
|
19
|
+
source_type: Optional[str] = Field(None, alias="sourceType", description="Type of source (web, kb, etc.)")
|
|
20
|
+
source_url: Optional[str] = Field(None, alias="sourceUrl", description="Source URL")
|
|
21
|
+
url: Optional[str] = Field(None, description="Alternative URL field")
|
|
22
|
+
content_preview: str = Field(..., alias="contentPreview", description="Preview of content")
|
|
23
|
+
relevance_score: float = Field(..., alias="relevanceScore", description="Relevance score (0-1)")
|
|
24
|
+
retrieved_at: Optional[str] = Field(None, alias="retrievedAt", description="Timestamp when retrieved")
|
|
25
|
+
metadata: Dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
|
|
26
|
+
|
|
27
|
+
class Config:
|
|
28
|
+
from_attributes = True
|
|
29
|
+
populate_by_name = True # Accept both snake_case and camelCase
|
|
30
|
+
by_alias = True # Serialize using aliases (camelCase)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class RAGQueryInfo(BaseModel):
|
|
34
|
+
"""Schema for query information in RAG metadata"""
|
|
35
|
+
query: str = Field(..., description="Search query")
|
|
36
|
+
timestamp: str = Field(..., description="Query timestamp")
|
|
37
|
+
source_citation_ids: List[str] = Field(..., alias="sourceCitationIds", description="Citation IDs for this query")
|
|
38
|
+
|
|
39
|
+
class Config:
|
|
40
|
+
populate_by_name = True
|
|
41
|
+
by_alias = True
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
class RAGMetadata(BaseModel):
|
|
45
|
+
"""Schema for RAG metadata"""
|
|
46
|
+
queries: Optional[List[RAGQueryInfo]] = Field(None, description="Query breakdown for timeline")
|
|
47
|
+
|
|
48
|
+
class Config:
|
|
49
|
+
populate_by_name = True
|
|
50
|
+
by_alias = True
|
|
51
|
+
extra = "allow" # Allow additional fields
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class RAGSearchResultResponse(BaseModel):
|
|
55
|
+
"""Schema for RAG search result with automatic snake_case to camelCase conversion"""
|
|
56
|
+
query: str = Field(..., description="Search query")
|
|
57
|
+
title: Optional[str] = Field(None, description="Human-readable title for the research (generated by LLM)")
|
|
58
|
+
search_type: str = Field(..., alias="searchType", description="Type of search (file_search, kb_search, deep_research, web_search)")
|
|
59
|
+
turn_number: Optional[int] = Field(None, alias="turnNumber", description="Turn number for citation tracking")
|
|
60
|
+
timestamp: str = Field(..., description="Search timestamp")
|
|
61
|
+
sources: List[RAGSourceResponse] = Field(default_factory=list, description="List of sources")
|
|
62
|
+
task_id: Optional[str] = Field(None, alias="taskId", description="Associated task ID")
|
|
63
|
+
metadata: Optional[RAGMetadata] = Field(None, description="Additional metadata")
|
|
64
|
+
|
|
65
|
+
class Config:
|
|
66
|
+
from_attributes = True
|
|
67
|
+
populate_by_name = True
|
|
68
|
+
by_alias = True
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def create_rag_source(
|
|
72
|
+
citation_id: str,
|
|
73
|
+
content_preview: str,
|
|
74
|
+
relevance_score: float,
|
|
75
|
+
file_id: Optional[str] = None,
|
|
76
|
+
filename: Optional[str] = None,
|
|
77
|
+
title: Optional[str] = None,
|
|
78
|
+
source_type: Optional[str] = None,
|
|
79
|
+
source_url: Optional[str] = None,
|
|
80
|
+
url: Optional[str] = None,
|
|
81
|
+
retrieved_at: Optional[str] = None,
|
|
82
|
+
metadata: Optional[Dict[str, Any]] = None
|
|
83
|
+
) -> Dict[str, Any]:
|
|
84
|
+
"""
|
|
85
|
+
Helper function to create a RAG source dict that will be automatically
|
|
86
|
+
converted to camelCase when serialized through RAGSourceResponse.
|
|
87
|
+
|
|
88
|
+
Returns a dict that can be passed to RAGSourceResponse for serialization.
|
|
89
|
+
"""
|
|
90
|
+
source = RAGSourceResponse(
|
|
91
|
+
citation_id=citation_id,
|
|
92
|
+
file_id=file_id,
|
|
93
|
+
filename=filename,
|
|
94
|
+
title=title,
|
|
95
|
+
source_type=source_type,
|
|
96
|
+
source_url=source_url,
|
|
97
|
+
url=url,
|
|
98
|
+
content_preview=content_preview,
|
|
99
|
+
relevance_score=relevance_score,
|
|
100
|
+
retrieved_at=retrieved_at,
|
|
101
|
+
metadata=metadata or {}
|
|
102
|
+
)
|
|
103
|
+
return source.model_dump(by_alias=True)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def create_rag_search_result(
|
|
107
|
+
query: str,
|
|
108
|
+
search_type: str,
|
|
109
|
+
timestamp: str,
|
|
110
|
+
sources: List[Dict[str, Any]],
|
|
111
|
+
task_id: Optional[str] = None,
|
|
112
|
+
turn_number: Optional[int] = None,
|
|
113
|
+
metadata: Optional[Dict[str, Any]] = None,
|
|
114
|
+
title: Optional[str] = None
|
|
115
|
+
) -> Dict[str, Any]:
|
|
116
|
+
"""
|
|
117
|
+
Helper function to create a RAG search result dict that will be automatically
|
|
118
|
+
converted to camelCase when serialized through RAGSearchResultResponse.
|
|
119
|
+
|
|
120
|
+
Args:
|
|
121
|
+
query: Search query
|
|
122
|
+
search_type: Type of search (file_search, kb_search, deep_research, web_search)
|
|
123
|
+
timestamp: Search timestamp
|
|
124
|
+
sources: List of source dicts (will be converted to RAGSourceResponse)
|
|
125
|
+
task_id: Optional task ID
|
|
126
|
+
turn_number: Optional turn number
|
|
127
|
+
metadata: Optional metadata dict
|
|
128
|
+
title: Optional human-readable title (generated by LLM for deep research)
|
|
129
|
+
|
|
130
|
+
Returns a dict with camelCase keys ready for frontend consumption.
|
|
131
|
+
"""
|
|
132
|
+
# Convert source dicts to RAGSourceResponse for proper serialization
|
|
133
|
+
source_responses = [RAGSourceResponse(**src) for src in sources]
|
|
134
|
+
|
|
135
|
+
# Create metadata if provided
|
|
136
|
+
rag_metadata = None
|
|
137
|
+
if metadata:
|
|
138
|
+
# Convert queries if present
|
|
139
|
+
if "queries" in metadata:
|
|
140
|
+
query_infos = [RAGQueryInfo(**q) for q in metadata["queries"]]
|
|
141
|
+
rag_metadata = RAGMetadata(queries=query_infos, **{k: v for k, v in metadata.items() if k != "queries"})
|
|
142
|
+
else:
|
|
143
|
+
rag_metadata = RAGMetadata(**metadata)
|
|
144
|
+
|
|
145
|
+
result = RAGSearchResultResponse(
|
|
146
|
+
query=query,
|
|
147
|
+
title=title,
|
|
148
|
+
search_type=search_type,
|
|
149
|
+
timestamp=timestamp,
|
|
150
|
+
sources=source_responses,
|
|
151
|
+
task_id=task_id,
|
|
152
|
+
turn_number=turn_number,
|
|
153
|
+
metadata=rag_metadata
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
return result.model_dump(by_alias=True)
|
|
@@ -5,13 +5,15 @@ Base Component class for SAM implementations in the Solace AI Connector.
|
|
|
5
5
|
import logging
|
|
6
6
|
import abc
|
|
7
7
|
import asyncio
|
|
8
|
+
import concurrent.futures
|
|
8
9
|
import threading
|
|
9
10
|
import functools
|
|
11
|
+
import time
|
|
10
12
|
from typing import Any, Optional
|
|
11
13
|
|
|
12
14
|
from solace_ai_connector.components.component_base import ComponentBase
|
|
13
15
|
|
|
14
|
-
from ..exceptions import MessageSizeExceededError
|
|
16
|
+
from ..exceptions import ComponentInitializationError, MessageSizeExceededError
|
|
15
17
|
from ..utils.message_utils import validate_message_size
|
|
16
18
|
|
|
17
19
|
log = logging.getLogger(__name__)
|
|
@@ -219,6 +221,50 @@ class SamComponentBase(ComponentBase, abc.ABC):
|
|
|
219
221
|
self.log_identifier,
|
|
220
222
|
timer_id,
|
|
221
223
|
)
|
|
224
|
+
elif event.event_type == EventType.CACHE_EXPIRY:
|
|
225
|
+
import asyncio
|
|
226
|
+
import inspect
|
|
227
|
+
|
|
228
|
+
cache_data = event.data
|
|
229
|
+
handler = self.handle_cache_expiry_event
|
|
230
|
+
|
|
231
|
+
# Check if the handler is async
|
|
232
|
+
if inspect.iscoroutinefunction(handler):
|
|
233
|
+
# Schedule async handler on the event loop
|
|
234
|
+
if self._async_loop and self._async_loop.is_running():
|
|
235
|
+
async def handle_async():
|
|
236
|
+
await handler(cache_data)
|
|
237
|
+
|
|
238
|
+
try:
|
|
239
|
+
future = asyncio.run_coroutine_threadsafe(
|
|
240
|
+
handle_async(),
|
|
241
|
+
self._async_loop
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
def on_done(f):
|
|
245
|
+
try:
|
|
246
|
+
f.result()
|
|
247
|
+
except Exception as e:
|
|
248
|
+
log.error(
|
|
249
|
+
"%s Error in async cache expiry handler: %s",
|
|
250
|
+
self.log_identifier,
|
|
251
|
+
e,
|
|
252
|
+
exc_info=True
|
|
253
|
+
)
|
|
254
|
+
future.add_done_callback(on_done)
|
|
255
|
+
except RuntimeError as e:
|
|
256
|
+
log.error(
|
|
257
|
+
"%s Failed to schedule async CACHE_EXPIRY handler (event loop may be stopping): %s",
|
|
258
|
+
self.log_identifier,
|
|
259
|
+
e
|
|
260
|
+
)
|
|
261
|
+
else:
|
|
262
|
+
log.error(
|
|
263
|
+
"%s Cannot handle async CACHE_EXPIRY: event loop not available",
|
|
264
|
+
self.log_identifier
|
|
265
|
+
)
|
|
266
|
+
else:
|
|
267
|
+
handler(cache_data)
|
|
222
268
|
else:
|
|
223
269
|
# Pass other event types to parent class
|
|
224
270
|
super().process_event(event)
|
|
@@ -357,6 +403,12 @@ class SamComponentBase(ComponentBase, abc.ABC):
|
|
|
357
403
|
list(payload.keys()) if isinstance(payload, dict) else "not_dict"
|
|
358
404
|
)
|
|
359
405
|
|
|
406
|
+
# Create user_properties if it doesn't exist
|
|
407
|
+
if user_properties is None:
|
|
408
|
+
user_properties = {}
|
|
409
|
+
|
|
410
|
+
user_properties["timestamp"] = int(time.time() * 1000)
|
|
411
|
+
|
|
360
412
|
# Validate message size
|
|
361
413
|
is_valid, actual_size = validate_message_size(
|
|
362
414
|
payload, self.max_message_size_bytes, self.log_identifier
|
|
@@ -508,6 +560,26 @@ class SamComponentBase(ComponentBase, abc.ABC):
|
|
|
508
560
|
"%s Async operations thread already running.", self.log_identifier
|
|
509
561
|
)
|
|
510
562
|
|
|
563
|
+
# Monitor async initialization without blocking (critical for multi-agent processes)
|
|
564
|
+
if hasattr(self, '_async_init_future') and self._async_init_future is not None:
|
|
565
|
+
log.info("%s Setting up async initialization monitoring...", self.log_identifier)
|
|
566
|
+
|
|
567
|
+
def handle_init_completion(future):
|
|
568
|
+
"""Non-blocking callback for initialization completion."""
|
|
569
|
+
try:
|
|
570
|
+
future.result() # Raises if init failed
|
|
571
|
+
log.info("%s Async initialization completed successfully.", self.log_identifier)
|
|
572
|
+
except Exception as init_error:
|
|
573
|
+
error_msg = f"{self.log_identifier} Async initialization failed: {init_error}"
|
|
574
|
+
log.error(error_msg, exc_info=init_error)
|
|
575
|
+
self.stop_signal.set()
|
|
576
|
+
self._async_init_error = ComponentInitializationError(
|
|
577
|
+
self.log_identifier, init_error, error_msg
|
|
578
|
+
)
|
|
579
|
+
|
|
580
|
+
self._async_init_future.add_done_callback(handle_init_completion)
|
|
581
|
+
log.info("%s Async initialization monitoring active (non-blocking).", self.log_identifier)
|
|
582
|
+
|
|
511
583
|
super().run()
|
|
512
584
|
log.info("%s SamComponentBase run method finished.", self.log_identifier)
|
|
513
585
|
|
|
@@ -45,9 +45,9 @@ class SamEvent:
|
|
|
45
45
|
@dataclass
|
|
46
46
|
class SessionDeletedEvent(SamEvent):
|
|
47
47
|
"""System event for session deletion."""
|
|
48
|
-
|
|
48
|
+
|
|
49
49
|
@classmethod
|
|
50
|
-
def create(cls, namespace: str, source_component: str, session_id: str,
|
|
50
|
+
def create(cls, namespace: str, source_component: str, session_id: str,
|
|
51
51
|
user_id: str, agent_id: str, gateway_id: str) -> "SessionDeletedEvent":
|
|
52
52
|
"""Create a session deleted event."""
|
|
53
53
|
data = {
|
|
@@ -14,12 +14,7 @@ from ..mime_helpers import is_text_based_mime_type
|
|
|
14
14
|
|
|
15
15
|
log = logging.getLogger(__name__)
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
import yaml
|
|
19
|
-
|
|
20
|
-
PYYAML_AVAILABLE = True
|
|
21
|
-
except ImportError:
|
|
22
|
-
PYYAML_AVAILABLE = False
|
|
17
|
+
import yaml
|
|
23
18
|
|
|
24
19
|
|
|
25
20
|
def _parse_string_to_list_of_dicts(
|
|
@@ -63,8 +58,6 @@ def _parse_string_to_list_of_dicts(
|
|
|
63
58
|
reader = csv.DictReader(string_io)
|
|
64
59
|
return list(reader), None
|
|
65
60
|
elif "yaml" in normalized_mime_type or "yml" in normalized_mime_type:
|
|
66
|
-
if not PYYAML_AVAILABLE:
|
|
67
|
-
return None, "YAML parsing skipped: 'PyYAML' not installed."
|
|
68
61
|
parsed_yaml = yaml.safe_load(data_string)
|
|
69
62
|
if isinstance(parsed_yaml, list) and all(
|
|
70
63
|
isinstance(item, dict) for item in parsed_yaml
|
|
@@ -10,19 +10,8 @@ from .constants import EARLY_EMBED_TYPES, LATE_EMBED_TYPES
|
|
|
10
10
|
|
|
11
11
|
log = logging.getLogger(__name__)
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
JSONPATH_NG_AVAILABLE = True
|
|
17
|
-
except ImportError:
|
|
18
|
-
JSONPATH_NG_AVAILABLE = False
|
|
19
|
-
|
|
20
|
-
try:
|
|
21
|
-
import pystache
|
|
22
|
-
|
|
23
|
-
PYSTACHE_AVAILABLE = True
|
|
24
|
-
except ImportError:
|
|
25
|
-
PYSTACHE_AVAILABLE = False
|
|
13
|
+
from jsonpath_ng.ext import parse as jsonpath_parse
|
|
14
|
+
import pystache
|
|
26
15
|
|
|
27
16
|
from google.adk.artifacts import BaseArtifactService
|
|
28
17
|
|
|
@@ -45,13 +34,6 @@ def _apply_jsonpath(
|
|
|
45
34
|
Tuple: (result_data, original_mime_type, error_string)
|
|
46
35
|
result_data is typically a list of matched values.
|
|
47
36
|
"""
|
|
48
|
-
if not JSONPATH_NG_AVAILABLE:
|
|
49
|
-
return (
|
|
50
|
-
current_data,
|
|
51
|
-
mime_type,
|
|
52
|
-
"JSONPath modifier skipped: 'jsonpath-ng' not installed.",
|
|
53
|
-
)
|
|
54
|
-
|
|
55
37
|
if not isinstance(current_data, (dict, list)):
|
|
56
38
|
return (
|
|
57
39
|
current_data,
|
|
@@ -457,13 +439,6 @@ async def _apply_template(
|
|
|
457
439
|
"""
|
|
458
440
|
from .resolver import resolve_embeds_recursively_in_string, evaluate_embed
|
|
459
441
|
|
|
460
|
-
if not PYSTACHE_AVAILABLE:
|
|
461
|
-
return (
|
|
462
|
-
current_data,
|
|
463
|
-
mime_type,
|
|
464
|
-
"Template modifier skipped: 'pystache' not installed.",
|
|
465
|
-
)
|
|
466
|
-
|
|
467
442
|
if not isinstance(current_data, (dict, list, str)):
|
|
468
443
|
return (
|
|
469
444
|
current_data,
|
|
@@ -26,11 +26,7 @@ from ..mime_helpers import is_text_based_mime_type
|
|
|
26
26
|
|
|
27
27
|
log = logging.getLogger(__name__)
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
import yaml
|
|
31
|
-
from .converter import PYYAML_AVAILABLE
|
|
32
|
-
except ImportError:
|
|
33
|
-
PYYAML_AVAILABLE = False
|
|
29
|
+
import yaml
|
|
34
30
|
|
|
35
31
|
|
|
36
32
|
def _log_data_state(
|
|
@@ -184,7 +180,7 @@ async def _evaluate_artifact_content_embed_with_chain(
|
|
|
184
180
|
current_format = DataFormat.STRING
|
|
185
181
|
_log_data_state(
|
|
186
182
|
log_identifier,
|
|
187
|
-
f"[Depth:{current_depth}] After Recursive Resolution",
|
|
183
|
+
f"[Depth:{current_depth}] After Recursive Resolution (including templates)",
|
|
188
184
|
current_data,
|
|
189
185
|
current_format,
|
|
190
186
|
original_mime_type,
|
|
@@ -232,25 +228,17 @@ async def _evaluate_artifact_content_embed_with_chain(
|
|
|
232
228
|
original_mime_type,
|
|
233
229
|
)
|
|
234
230
|
elif "yaml" in normalized_mime_type or "yml" in normalized_mime_type:
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
except yaml.YAMLError:
|
|
245
|
-
log.warning(
|
|
246
|
-
"%s [Depth:%d] Failed to pre-parse as YAML despite MIME type '%s'. Content will be treated as STRING.",
|
|
247
|
-
log_identifier,
|
|
248
|
-
current_depth,
|
|
249
|
-
original_mime_type,
|
|
250
|
-
)
|
|
251
|
-
else:
|
|
231
|
+
try:
|
|
232
|
+
current_data = yaml.safe_load(current_data)
|
|
233
|
+
current_format = DataFormat.JSON_OBJECT
|
|
234
|
+
log.info(
|
|
235
|
+
"%s [Depth:%d] Pre-parsed string as YAML (now JSON_OBJECT).",
|
|
236
|
+
log_identifier,
|
|
237
|
+
current_depth,
|
|
238
|
+
)
|
|
239
|
+
except yaml.YAMLError:
|
|
252
240
|
log.warning(
|
|
253
|
-
"%s [Depth:%d]
|
|
241
|
+
"%s [Depth:%d] Failed to pre-parse as YAML despite MIME type '%s'. Content will be treated as STRING.",
|
|
254
242
|
log_identifier,
|
|
255
243
|
current_depth,
|
|
256
244
|
original_mime_type,
|
|
@@ -677,6 +665,34 @@ async def resolve_embeds_in_string(
|
|
|
677
665
|
len(final_text),
|
|
678
666
|
)
|
|
679
667
|
|
|
668
|
+
# If resolving late embeds, also resolve template blocks
|
|
669
|
+
# Templates are considered late embeds since they need artifact service access
|
|
670
|
+
if LATE_EMBED_TYPES.intersection(types_to_resolve):
|
|
671
|
+
try:
|
|
672
|
+
from ..templates import resolve_template_blocks_in_string
|
|
673
|
+
|
|
674
|
+
artifact_service = context.get("artifact_service")
|
|
675
|
+
session_context = context.get("session_context")
|
|
676
|
+
|
|
677
|
+
if artifact_service and session_context:
|
|
678
|
+
log.debug(
|
|
679
|
+
"%s Resolving template blocks after late embed resolution.",
|
|
680
|
+
log_identifier,
|
|
681
|
+
)
|
|
682
|
+
final_text = await resolve_template_blocks_in_string(
|
|
683
|
+
text=final_text,
|
|
684
|
+
artifact_service=artifact_service,
|
|
685
|
+
session_context=session_context,
|
|
686
|
+
log_identifier=f"{log_identifier}[TemplateResolve]",
|
|
687
|
+
)
|
|
688
|
+
except Exception as template_err:
|
|
689
|
+
log.warning(
|
|
690
|
+
"%s Failed to resolve template blocks: %s",
|
|
691
|
+
log_identifier,
|
|
692
|
+
template_err,
|
|
693
|
+
)
|
|
694
|
+
# Continue with final_text as-is
|
|
695
|
+
|
|
680
696
|
return final_text, processed_until_index, signals_found
|
|
681
697
|
|
|
682
698
|
|
|
@@ -797,7 +813,39 @@ async def resolve_embeds_recursively_in_string(
|
|
|
797
813
|
last_end = end
|
|
798
814
|
|
|
799
815
|
resolved_parts.append(text[last_end:])
|
|
800
|
-
|
|
816
|
+
result_text = "".join(resolved_parts)
|
|
817
|
+
|
|
818
|
+
# If resolving late embeds, also resolve template blocks
|
|
819
|
+
# Templates are considered late embeds since they need artifact service access
|
|
820
|
+
if LATE_EMBED_TYPES.intersection(types_to_resolve):
|
|
821
|
+
try:
|
|
822
|
+
from ..templates import resolve_template_blocks_in_string
|
|
823
|
+
|
|
824
|
+
artifact_service = context.get("artifact_service")
|
|
825
|
+
session_context = context.get("session_context")
|
|
826
|
+
|
|
827
|
+
if artifact_service and session_context:
|
|
828
|
+
log.debug(
|
|
829
|
+
"%s [Depth:%d] Resolving template blocks after late embed resolution.",
|
|
830
|
+
log_identifier,
|
|
831
|
+
current_depth,
|
|
832
|
+
)
|
|
833
|
+
result_text = await resolve_template_blocks_in_string(
|
|
834
|
+
text=result_text,
|
|
835
|
+
artifact_service=artifact_service,
|
|
836
|
+
session_context=session_context,
|
|
837
|
+
log_identifier=f"{log_identifier}[TemplateResolve]",
|
|
838
|
+
)
|
|
839
|
+
except Exception as template_err:
|
|
840
|
+
log.warning(
|
|
841
|
+
"%s [Depth:%d] Failed to resolve template blocks: %s",
|
|
842
|
+
log_identifier,
|
|
843
|
+
current_depth,
|
|
844
|
+
template_err,
|
|
845
|
+
)
|
|
846
|
+
# Continue with result_text as-is
|
|
847
|
+
|
|
848
|
+
return result_text
|
|
801
849
|
|
|
802
850
|
|
|
803
851
|
async def evaluate_embed(
|
|
@@ -873,6 +921,27 @@ async def evaluate_embed(
|
|
|
873
921
|
)
|
|
874
922
|
output_format = format_spec
|
|
875
923
|
|
|
924
|
+
# Check if this is a deep research report artifact
|
|
925
|
+
# Deep research reports should be rendered by the frontend component, not resolved inline
|
|
926
|
+
filename_part = artifact_spec.split(":")[0] if ":" in artifact_spec else artifact_spec
|
|
927
|
+
is_deep_research_report = filename_part.lower().endswith("_report.md")
|
|
928
|
+
|
|
929
|
+
if is_deep_research_report and resolution_mode == ResolutionMode.A2A_MESSAGE_TO_USER:
|
|
930
|
+
# Parse version from artifact_spec
|
|
931
|
+
parts = artifact_spec.strip().split(":", 1)
|
|
932
|
+
filename = parts[0]
|
|
933
|
+
version = parts[1] if len(parts) > 1 else "latest"
|
|
934
|
+
log.info(
|
|
935
|
+
"%s Detected deep research report artifact '%s'. Signaling for frontend rendering instead of inline resolution.",
|
|
936
|
+
log_identifier,
|
|
937
|
+
filename,
|
|
938
|
+
)
|
|
939
|
+
return (
|
|
940
|
+
None,
|
|
941
|
+
"SIGNAL_DEEP_RESEARCH_REPORT",
|
|
942
|
+
{"filename": filename, "version": version},
|
|
943
|
+
)
|
|
944
|
+
|
|
876
945
|
result = await _evaluate_artifact_content_embed_with_chain(
|
|
877
946
|
artifact_spec_from_directive=artifact_spec,
|
|
878
947
|
modifiers_from_directive=modifiers,
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
import json
|
|
3
3
|
import os
|
|
4
|
+
import warnings
|
|
4
5
|
from datetime import datetime, timezone
|
|
5
6
|
import traceback
|
|
6
7
|
|
|
@@ -8,9 +9,28 @@ import traceback
|
|
|
8
9
|
class DatadogJsonFormatter(logging.Formatter):
|
|
9
10
|
"""
|
|
10
11
|
Custom formatter to output logs in Datadog-compatible JSON format.
|
|
12
|
+
|
|
13
|
+
. deprecated::
|
|
14
|
+
This formatter is deprecated. Please use pythonjsonlogger.json.JsonFormatter instead.
|
|
15
|
+
For details, consult https://solacelabs.github.io/solace-agent-mesh/docs/documentation/deploying/logging#structured-logging
|
|
16
|
+
|
|
17
|
+
Example:
|
|
18
|
+
formatters:
|
|
19
|
+
jsonFormatter:
|
|
20
|
+
"()": pythonjsonlogger.json.JsonFormatter
|
|
21
|
+
format: "%(timestamp)s %(levelname)s %(threadName)s %(name)s %(message)s"
|
|
11
22
|
"""
|
|
12
23
|
|
|
13
24
|
def format(self, record):
|
|
25
|
+
# Emit deprecation warning once
|
|
26
|
+
if not hasattr(self.__class__, '_deprecation_warned'):
|
|
27
|
+
warnings.warn(
|
|
28
|
+
"DatadogJsonFormatter is deprecated and will be removed in a future version. "
|
|
29
|
+
"Please use pythonjsonlogger.json.JsonFormatter instead. For details, consult https://solacelabs.github.io/solace-agent-mesh/docs/documentation/deploying/logging#structured-logging",
|
|
30
|
+
DeprecationWarning,
|
|
31
|
+
stacklevel=2
|
|
32
|
+
)
|
|
33
|
+
self.__class__._deprecation_warned = True
|
|
14
34
|
log_entry = {
|
|
15
35
|
"timestamp": datetime.fromtimestamp(
|
|
16
36
|
record.created, tz=timezone.utc
|
|
@@ -23,6 +23,8 @@ _TEXT_BASED_SUBTYPE_WHOLE = {
|
|
|
23
23
|
"json",
|
|
24
24
|
"xml",
|
|
25
25
|
"yaml",
|
|
26
|
+
"x-yaml",
|
|
27
|
+
"yml",
|
|
26
28
|
"csv",
|
|
27
29
|
"javascript",
|
|
28
30
|
"ecmascript",
|
|
@@ -48,6 +50,7 @@ _TEXT_BASED_SUBTYPE_SUFFIXES_AFTER_PLUS = {
|
|
|
48
50
|
"xhtml",
|
|
49
51
|
}
|
|
50
52
|
|
|
53
|
+
|
|
51
54
|
def is_text_based_mime_type(mime_type: Optional[str]) -> bool:
|
|
52
55
|
"""
|
|
53
56
|
Checks if a given MIME type is considered text-based.
|
|
@@ -72,7 +75,9 @@ def is_text_based_mime_type(mime_type: Optional[str]) -> bool:
|
|
|
72
75
|
return False
|
|
73
76
|
|
|
74
77
|
|
|
75
|
-
def is_text_based_file(
|
|
78
|
+
def is_text_based_file(
|
|
79
|
+
mime_type: Optional[str], content_bytes: Optional[bytes] = None
|
|
80
|
+
) -> bool:
|
|
76
81
|
"""
|
|
77
82
|
Determines if a file is text-based based on its MIME type and content.
|
|
78
83
|
Args:
|
|
@@ -83,10 +88,10 @@ def is_text_based_file(mime_type: Optional[str], content_bytes: Optional[bytes]
|
|
|
83
88
|
"""
|
|
84
89
|
if not mime_type:
|
|
85
90
|
return False
|
|
86
|
-
|
|
91
|
+
|
|
87
92
|
normalized_mime_type = mime_type.lower().strip()
|
|
88
93
|
primary_type, _, subtype = normalized_mime_type.partition("/")
|
|
89
|
-
|
|
94
|
+
|
|
90
95
|
if primary_type in _TEXT_BASED_PRIMARY_TYPES:
|
|
91
96
|
return True
|
|
92
97
|
elif subtype in _TEXT_BASED_SUBTYPE_WHOLE:
|
|
@@ -95,14 +100,16 @@ def is_text_based_file(mime_type: Optional[str], content_bytes: Optional[bytes]
|
|
|
95
100
|
specific_format = subtype.split("+")[-1]
|
|
96
101
|
if specific_format in _TEXT_BASED_SUBTYPE_SUFFIXES_AFTER_PLUS:
|
|
97
102
|
return True
|
|
98
|
-
elif
|
|
103
|
+
elif (
|
|
104
|
+
normalized_mime_type == "application/octet-stream" and content_bytes is not None
|
|
105
|
+
):
|
|
99
106
|
try:
|
|
100
107
|
sample_size = min(1024, len(content_bytes))
|
|
101
108
|
content_bytes[:sample_size].decode("utf-8")
|
|
102
109
|
return True
|
|
103
110
|
except UnicodeDecodeError:
|
|
104
111
|
return False
|
|
105
|
-
|
|
112
|
+
|
|
106
113
|
return False
|
|
107
114
|
|
|
108
115
|
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"""
|
|
2
|
+
RBAC utility functions for agent access control.
|
|
3
|
+
|
|
4
|
+
Provides common validation logic for enforcing agent access permissions
|
|
5
|
+
across gateways and agent components.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import logging
|
|
9
|
+
from typing import Dict, Any
|
|
10
|
+
|
|
11
|
+
from ..middleware.registry import MiddlewareRegistry
|
|
12
|
+
|
|
13
|
+
log = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def validate_agent_access(
|
|
17
|
+
user_config: Dict[str, Any],
|
|
18
|
+
target_agent_name: str,
|
|
19
|
+
validation_context: Dict[str, Any],
|
|
20
|
+
log_identifier: str = "[RBAC]",
|
|
21
|
+
) -> None:
|
|
22
|
+
"""
|
|
23
|
+
Validates that a user has permission to access a target agent.
|
|
24
|
+
|
|
25
|
+
Uses the middleware ConfigResolver to check if the user has the required
|
|
26
|
+
agent:{target_agent}:delegate scope. Raises PermissionError if access is denied.
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
user_config: User configuration dict containing scopes (from ConfigResolver.resolve_user_config)
|
|
30
|
+
target_agent_name: Name of the agent being accessed
|
|
31
|
+
validation_context: Additional context for validation (e.g., gateway_id, delegating_agent)
|
|
32
|
+
log_identifier: Logging prefix for error messages
|
|
33
|
+
|
|
34
|
+
Raises:
|
|
35
|
+
PermissionError: If the user does not have the required agent:*:delegate scope
|
|
36
|
+
"""
|
|
37
|
+
config_resolver = MiddlewareRegistry.get_config_resolver()
|
|
38
|
+
operation_spec = {
|
|
39
|
+
"operation_type": "agent_access",
|
|
40
|
+
"target_agent": target_agent_name,
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
validation_result = config_resolver.validate_operation_config(
|
|
44
|
+
user_config, operation_spec, validation_context
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
if not validation_result.get("valid", False):
|
|
48
|
+
reason = validation_result.get(
|
|
49
|
+
"reason", f"Access denied to agent '{target_agent_name}'"
|
|
50
|
+
)
|
|
51
|
+
required_scopes = validation_result.get("required_scopes", [])
|
|
52
|
+
|
|
53
|
+
log.warning(
|
|
54
|
+
"%s Access to agent '%s' denied. Required scopes: %s. Reason: %s",
|
|
55
|
+
log_identifier,
|
|
56
|
+
target_agent_name,
|
|
57
|
+
required_scopes,
|
|
58
|
+
reason,
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
raise PermissionError(
|
|
62
|
+
f"Access denied to agent '{target_agent_name}'. Required scopes: {required_scopes}"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
log.debug(
|
|
66
|
+
"%s Access to agent '%s' granted.",
|
|
67
|
+
log_identifier,
|
|
68
|
+
target_agent_name,
|
|
69
|
+
)
|