solace-agent-mesh 1.11.2__py3-none-any.whl → 1.12.0__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.
- solace_agent_mesh/agent/adk/callbacks.py +177 -10
- solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +3 -0
- solace_agent_mesh/agent/adk/models/lite_llm.py +34 -16
- solace_agent_mesh/agent/adk/runner.py +66 -8
- solace_agent_mesh/agent/adk/setup.py +61 -26
- solace_agent_mesh/agent/protocol/event_handlers.py +48 -0
- solace_agent_mesh/agent/proxies/a2a/component.py +27 -0
- solace_agent_mesh/agent/sac/component.py +84 -2
- solace_agent_mesh/agent/tools/builtin_artifact_tools.py +41 -22
- solace_agent_mesh/agent/tools/peer_agent_tool.py +19 -12
- solace_agent_mesh/agent/tools/tool_config_types.py +21 -1
- solace_agent_mesh/agent/utils/artifact_helpers.py +54 -0
- solace_agent_mesh/assets/docs/404.html +3 -3
- solace_agent_mesh/assets/docs/assets/js/15ba94aa.e186750d.js +1 -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.28b7c67b.js → 3ac1795d.dc006e20.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/3ff0015d.f08618fb.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/4667dc50.bf2ad456.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/547e15cc.8e6da617.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/64195356.09dbd087.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/66d4869e.30340bd3.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.95be65d4.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/ab9708a8.3e563275.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/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.08fab659.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/main.b241af3e.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/runtime~main.4ca7d2e2.js +1 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +4 -4
- 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 +14 -12
- solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +30 -9
- solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/index.html +6 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +4 -4
- 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 +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/projects/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/prompts/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/components/speech/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +5 -5
- solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/deploying/{kubernetes-deployment → kubernetes}/index.html +6 -6
- 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 +11 -6
- solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/deploying/proxy_configuration/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +23 -5
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +17 -8
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/teams-integration/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/agent-builder/index.html +5 -5
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/connectors/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/openapi-tools/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/secure-user-delegated-access/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/wheel-installation/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +6 -5
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +4 -4
- 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 +25 -4
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/session-storage/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/user-feedback/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +4 -4
- solace_agent_mesh/assets/docs/docs/documentation/migrations/platform-service-split/index.html +85 -0
- solace_agent_mesh/assets/docs/lunr-index-1767712284328.json +1 -0
- solace_agent_mesh/assets/docs/lunr-index.json +1 -1
- solace_agent_mesh/assets/docs/search-doc-1767712284328.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/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 +29 -2
- solace_agent_mesh/cli/commands/init_cmd/platform_service_step.py +85 -0
- solace_agent_mesh/cli/commands/tools_cmd.py +315 -0
- solace_agent_mesh/cli/main.py +2 -0
- solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-Dj3JtK42.js → authCallback-8Nihi8rv.js} +1 -1
- solace_agent_mesh/client/webui/frontend/static/assets/{client-ZKk9kEJ5.js → client-DYtZN8p-.js} +1 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main-BYGUHQMk.js +435 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-D2CSH1bp.css +1 -0
- solace_agent_mesh/client/webui/frontend/static/assets/{vendor-BNV4kZN0.js → vendor-XBWAmrun.js} +106 -101
- 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/ui-version.json +1 -1
- 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 +28 -0
- solace_agent_mesh/common/error_handlers.py +83 -0
- solace_agent_mesh/common/sam_events/event_service.py +2 -2
- solace_agent_mesh/config_portal/backend/common.py +2 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-ZV-jX48T.js +103 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/{manifest-ba77705e.js → manifest-ce5bc5da.js} +1 -1
- solace_agent_mesh/config_portal/frontend/static/client/index.html +1 -1
- 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/auth_interface.py +103 -0
- solace_agent_mesh/gateway/base/component.py +68 -1
- solace_agent_mesh/gateway/generic/component.py +195 -30
- solace_agent_mesh/gateway/http_sse/app.py +23 -6
- solace_agent_mesh/gateway/http_sse/component.py +9 -61
- solace_agent_mesh/gateway/http_sse/dependencies.py +9 -51
- solace_agent_mesh/gateway/http_sse/main.py +28 -418
- 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 +2 -2
- 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/prompt_model.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/models/session_model.py +1 -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 +4 -4
- solace_agent_mesh/gateway/http_sse/repository/task_repository.py +2 -2
- solace_agent_mesh/gateway/http_sse/routers/artifacts.py +16 -15
- solace_agent_mesh/gateway/http_sse/routers/auth.py +61 -132
- solace_agent_mesh/gateway/http_sse/routers/config.py +12 -8
- 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/session_responses.py +2 -2
- 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 +2 -1
- solace_agent_mesh/gateway/http_sse/routers/prompts.py +2 -1
- solace_agent_mesh/gateway/http_sse/routers/sessions.py +3 -3
- solace_agent_mesh/gateway/http_sse/routers/speech.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/tasks.py +3 -2
- solace_agent_mesh/gateway/http_sse/routers/users.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/visualization.py +2 -1
- solace_agent_mesh/gateway/http_sse/services/background_task_monitor.py +1 -1
- 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/session_service.py +4 -4
- solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +1 -1
- solace_agent_mesh/services/platform/__init__.py +23 -12
- solace_agent_mesh/services/platform/api/dependencies.py +23 -16
- solace_agent_mesh/services/platform/api/main.py +118 -43
- solace_agent_mesh/services/platform/api/routers/__init__.py +12 -3
- solace_agent_mesh/services/platform/api/routers/health_router.py +31 -0
- solace_agent_mesh/services/platform/app.py +101 -7
- solace_agent_mesh/services/platform/component.py +552 -33
- 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 +291 -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/platform.yaml +49 -0
- solace_agent_mesh/templates/webui.yaml +12 -3
- {solace_agent_mesh-1.11.2.dist-info → solace_agent_mesh-1.12.0.dist-info}/METADATA +2 -1
- {solace_agent_mesh-1.11.2.dist-info → solace_agent_mesh-1.12.0.dist-info}/RECORD +214 -258
- 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/15ba94aa.92fea363.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/240a0364.9ad94d1b.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/3ff0015d.2ddc75c0.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/547e15cc.2f7790c1.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/5c2bd65f.90a87880.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/64195356.c498c4d0.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/66d4869e.b77431fc.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/8024126c.fa0e7186.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/81a99df0.2484b8d9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/9bb13469.b2333011.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/ab9708a8.245ae0ef.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/db5d6442.3daf1696.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e04b235d.52cb25ed.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e1b6eeb4.b1068f9b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e6f9706b.4488e34c.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e92d0134.3bda61dd.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/f284c35a.250993bf.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/main.7acf7ace.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/runtime~main.9e0813a2.js +0 -1
- solace_agent_mesh/assets/docs/lunr-index-1765810064709.json +0 -1
- solace_agent_mesh/assets/docs/search-doc-1765810064709.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/main-BcUaNZ-Q.css +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main-vjch4RYc.js +0 -435
- 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-DiOiAjzL.js +0 -103
- 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/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/templates_llm.txt +0 -147
- /solace_agent_mesh/assets/docs/assets/js/{main.7acf7ace.js.LICENSE.txt → main.b241af3e.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.11.2.dist-info → solace_agent_mesh-1.12.0.dist-info}/WHEEL +0 -0
- {solace_agent_mesh-1.11.2.dist-info → solace_agent_mesh-1.12.0.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-1.11.2.dist-info → solace_agent_mesh-1.12.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Shared utilities for Solace Agent Mesh.
|
|
3
|
+
|
|
4
|
+
This module contains utilities used by both gateways and services:
|
|
5
|
+
- API utilities (pagination, responses, auth)
|
|
6
|
+
- Database utilities (repositories, exceptions, helpers)
|
|
7
|
+
- Exception handling
|
|
8
|
+
- Common utilities (timestamps, enums, types)
|
|
9
|
+
|
|
10
|
+
Architecture:
|
|
11
|
+
- GATEWAYS (http_sse, slack, webhook) import from shared/
|
|
12
|
+
- SERVICES (platform) import from shared/
|
|
13
|
+
- No cross-dependencies between gateways and services
|
|
14
|
+
"""
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"""
|
|
2
|
+
API utilities for REST endpoints.
|
|
3
|
+
|
|
4
|
+
Provides:
|
|
5
|
+
- Pagination patterns (PaginationParams, PaginatedResponse, DataResponse)
|
|
6
|
+
- Response utilities (create_data_response, create_paginated_response)
|
|
7
|
+
- Auth utilities (get_current_user)
|
|
8
|
+
|
|
9
|
+
Note: Error responses are handled by exception_handlers in shared.exceptions
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from .pagination import (
|
|
13
|
+
PaginationParams,
|
|
14
|
+
PaginatedResponse,
|
|
15
|
+
DataResponse,
|
|
16
|
+
PaginationMeta,
|
|
17
|
+
Meta,
|
|
18
|
+
get_pagination_or_default,
|
|
19
|
+
DEFAULT_PAGE_NUMBER,
|
|
20
|
+
DEFAULT_PAGE_SIZE,
|
|
21
|
+
MAX_PAGE_SIZE,
|
|
22
|
+
)
|
|
23
|
+
from .response_utils import (
|
|
24
|
+
create_data_response,
|
|
25
|
+
create_paginated_response,
|
|
26
|
+
)
|
|
27
|
+
from .auth_utils import get_current_user
|
|
28
|
+
|
|
29
|
+
__all__ = [
|
|
30
|
+
"PaginationParams",
|
|
31
|
+
"PaginatedResponse",
|
|
32
|
+
"DataResponse",
|
|
33
|
+
"PaginationMeta",
|
|
34
|
+
"Meta",
|
|
35
|
+
"get_pagination_or_default",
|
|
36
|
+
"DEFAULT_PAGE_NUMBER",
|
|
37
|
+
"DEFAULT_PAGE_SIZE",
|
|
38
|
+
"MAX_PAGE_SIZE",
|
|
39
|
+
"create_data_response",
|
|
40
|
+
"create_paginated_response",
|
|
41
|
+
"get_current_user",
|
|
42
|
+
]
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Authentication and authorization dependencies.
|
|
3
|
+
|
|
4
|
+
Provides FastAPI dependencies for:
|
|
5
|
+
- User authentication (extracting current user from request)
|
|
6
|
+
- Authorization (scope-based validation)
|
|
7
|
+
- User configuration resolution
|
|
8
|
+
|
|
9
|
+
Works with both gateways and services.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from .dependencies import (
|
|
13
|
+
get_current_user,
|
|
14
|
+
get_config_resolver,
|
|
15
|
+
get_user_config,
|
|
16
|
+
ValidatedUserConfig,
|
|
17
|
+
ComponentWithAuth,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"get_current_user",
|
|
22
|
+
"get_config_resolver",
|
|
23
|
+
"get_user_config",
|
|
24
|
+
"ValidatedUserConfig",
|
|
25
|
+
"ComponentWithAuth",
|
|
26
|
+
]
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Shared authentication dependencies for both gateways and services.
|
|
3
|
+
|
|
4
|
+
Provides FastAPI dependencies for:
|
|
5
|
+
- User authentication (get_current_user)
|
|
6
|
+
- Authorization/scope validation (ValidatedUserConfig)
|
|
7
|
+
- Config resolution (get_config_resolver, get_user_config)
|
|
8
|
+
|
|
9
|
+
These work with any component that implements the required interface:
|
|
10
|
+
- get_config_resolver() -> ConfigResolver
|
|
11
|
+
- get_namespace() -> str
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import logging
|
|
15
|
+
from typing import Any, Protocol
|
|
16
|
+
|
|
17
|
+
from fastapi import Depends, HTTPException, Request, status
|
|
18
|
+
from solace_agent_mesh.common.middleware.config_resolver import ConfigResolver
|
|
19
|
+
|
|
20
|
+
log = logging.getLogger(__name__)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class ComponentWithAuth(Protocol):
|
|
24
|
+
"""
|
|
25
|
+
Protocol for components that support authentication and authorization.
|
|
26
|
+
|
|
27
|
+
Both WebUIBackendComponent (gateway) and PlatformServiceComponent (service)
|
|
28
|
+
implement this interface.
|
|
29
|
+
"""
|
|
30
|
+
def get_config_resolver(self) -> ConfigResolver: ...
|
|
31
|
+
def get_namespace(self) -> str: ...
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def get_current_user(request: Request) -> dict:
|
|
35
|
+
"""
|
|
36
|
+
Extract authenticated user from request state.
|
|
37
|
+
|
|
38
|
+
The user is set by OAuth middleware during request processing.
|
|
39
|
+
Works with both gateway and service contexts.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
request: FastAPI Request object
|
|
43
|
+
|
|
44
|
+
Returns:
|
|
45
|
+
Dictionary containing user information (id, email, name, authenticated, etc.)
|
|
46
|
+
|
|
47
|
+
Raises:
|
|
48
|
+
HTTPException: 401 if user is not authenticated
|
|
49
|
+
"""
|
|
50
|
+
if not hasattr(request.state, "user") or not request.state.user:
|
|
51
|
+
raise HTTPException(
|
|
52
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
53
|
+
detail="Authentication required",
|
|
54
|
+
)
|
|
55
|
+
return request.state.user
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
def _get_component_from_context() -> ComponentWithAuth:
|
|
59
|
+
"""
|
|
60
|
+
Get component instance from either gateway or service context.
|
|
61
|
+
|
|
62
|
+
Tries platform service first, then falls back to http_sse gateway.
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
Component instance implementing ComponentWithAuth protocol
|
|
66
|
+
|
|
67
|
+
Raises:
|
|
68
|
+
HTTPException: 503 if no component is available
|
|
69
|
+
"""
|
|
70
|
+
try:
|
|
71
|
+
from solace_agent_mesh.services.platform.api.dependencies import platform_component_instance
|
|
72
|
+
if platform_component_instance is not None:
|
|
73
|
+
return platform_component_instance
|
|
74
|
+
except ImportError:
|
|
75
|
+
pass
|
|
76
|
+
|
|
77
|
+
try:
|
|
78
|
+
from solace_agent_mesh.gateway.http_sse.dependencies import sac_component_instance
|
|
79
|
+
if sac_component_instance is not None:
|
|
80
|
+
return sac_component_instance
|
|
81
|
+
except ImportError:
|
|
82
|
+
pass
|
|
83
|
+
|
|
84
|
+
raise HTTPException(
|
|
85
|
+
status_code=status.HTTP_503_SERVICE_UNAVAILABLE,
|
|
86
|
+
detail="Component not initialized"
|
|
87
|
+
)
|
|
88
|
+
|
|
89
|
+
|
|
90
|
+
def get_config_resolver() -> ConfigResolver:
|
|
91
|
+
"""
|
|
92
|
+
Get ConfigResolver from current component context.
|
|
93
|
+
|
|
94
|
+
Works with both gateway and service components.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
ConfigResolver instance for authorization checks
|
|
98
|
+
"""
|
|
99
|
+
component = _get_component_from_context()
|
|
100
|
+
return component.get_config_resolver()
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
async def get_user_config(
|
|
104
|
+
request: Request,
|
|
105
|
+
user: dict = Depends(get_current_user),
|
|
106
|
+
config_resolver: ConfigResolver = Depends(get_config_resolver),
|
|
107
|
+
) -> dict[str, Any]:
|
|
108
|
+
"""
|
|
109
|
+
Get user configuration including profile and permissions.
|
|
110
|
+
|
|
111
|
+
Works with both gateway and service components.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
request: FastAPI Request object
|
|
115
|
+
user: Authenticated user (from get_current_user dependency)
|
|
116
|
+
config_resolver: ConfigResolver (from get_config_resolver dependency)
|
|
117
|
+
|
|
118
|
+
Returns:
|
|
119
|
+
Dictionary containing user configuration and permissions
|
|
120
|
+
"""
|
|
121
|
+
component = _get_component_from_context()
|
|
122
|
+
user_id = user.get("id")
|
|
123
|
+
|
|
124
|
+
log.debug(f"get_user_config called for user_id: {user_id}")
|
|
125
|
+
|
|
126
|
+
namespace = component.get_namespace()
|
|
127
|
+
|
|
128
|
+
app_config = {}
|
|
129
|
+
if hasattr(component, "component_config"):
|
|
130
|
+
app_config = getattr(component, "component_config", {}).get("app_config", {})
|
|
131
|
+
|
|
132
|
+
gateway_context = {}
|
|
133
|
+
if hasattr(component, "gateway_id"):
|
|
134
|
+
gateway_context = {
|
|
135
|
+
"gateway_id": component.gateway_id,
|
|
136
|
+
"gateway_app_config": app_config,
|
|
137
|
+
"request": request,
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
return await config_resolver.resolve_user_config(
|
|
141
|
+
user_id, gateway_context, app_config
|
|
142
|
+
)
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
class ValidatedUserConfig:
|
|
146
|
+
"""
|
|
147
|
+
FastAPI dependency for scope-based authorization.
|
|
148
|
+
|
|
149
|
+
Validates that the current user has required scopes before allowing access.
|
|
150
|
+
Works with both gateways (http_sse) and services (platform).
|
|
151
|
+
|
|
152
|
+
Args:
|
|
153
|
+
required_scopes: List of scope strings required for authorization
|
|
154
|
+
|
|
155
|
+
Raises:
|
|
156
|
+
HTTPException: 403 if user lacks required scopes
|
|
157
|
+
|
|
158
|
+
Example:
|
|
159
|
+
@router.post("/agents")
|
|
160
|
+
async def create_agent(
|
|
161
|
+
user_config: dict = Depends(ValidatedUserConfig(["sam:agents:create"])),
|
|
162
|
+
):
|
|
163
|
+
# Only users with sam:agents:create scope can access
|
|
164
|
+
...
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
def __init__(self, required_scopes: list[str]):
|
|
168
|
+
self.required_scopes = required_scopes
|
|
169
|
+
|
|
170
|
+
async def __call__(
|
|
171
|
+
self,
|
|
172
|
+
request: Request,
|
|
173
|
+
config_resolver: ConfigResolver = Depends(get_config_resolver),
|
|
174
|
+
user_config: dict[str, Any] = Depends(get_user_config),
|
|
175
|
+
) -> dict[str, Any]:
|
|
176
|
+
user_id = user_config.get("user_profile", {}).get("id")
|
|
177
|
+
|
|
178
|
+
log.debug(
|
|
179
|
+
f"ValidatedUserConfig called for user_id: {user_id} with required scopes: {self.required_scopes}"
|
|
180
|
+
)
|
|
181
|
+
|
|
182
|
+
if not config_resolver.is_feature_enabled(
|
|
183
|
+
user_config,
|
|
184
|
+
{"tool_metadata": {"required_scopes": self.required_scopes}},
|
|
185
|
+
{},
|
|
186
|
+
):
|
|
187
|
+
log.warning(
|
|
188
|
+
f"Authorization denied for user '{user_id}'. Required scopes: {self.required_scopes}"
|
|
189
|
+
)
|
|
190
|
+
raise HTTPException(
|
|
191
|
+
status_code=status.HTTP_403_FORBIDDEN,
|
|
192
|
+
detail=f"Not authorized. Required scopes: {self.required_scopes}",
|
|
193
|
+
)
|
|
194
|
+
|
|
195
|
+
return user_config
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
__all__ = [
|
|
199
|
+
"get_current_user",
|
|
200
|
+
"get_config_resolver",
|
|
201
|
+
"get_user_config",
|
|
202
|
+
"ValidatedUserConfig",
|
|
203
|
+
"ComponentWithAuth",
|
|
204
|
+
]
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
"""
|
|
2
|
+
OAuth2 authentication middleware for both gateways and services.
|
|
3
|
+
|
|
4
|
+
Provides reusable OAuth2 token validation middleware that works with any
|
|
5
|
+
component that has OAuth configuration.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import httpx
|
|
9
|
+
import logging
|
|
10
|
+
from fastapi import Request as FastAPIRequest
|
|
11
|
+
from fastapi.responses import JSONResponse
|
|
12
|
+
from fastapi import status
|
|
13
|
+
|
|
14
|
+
log = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _extract_access_token(request: FastAPIRequest) -> str:
|
|
18
|
+
"""
|
|
19
|
+
Extract access token from request (header, session, or query param).
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
request: FastAPI request object
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
Access token string if found, None otherwise
|
|
26
|
+
"""
|
|
27
|
+
auth_header = request.headers.get("Authorization")
|
|
28
|
+
if auth_header and auth_header.startswith("Bearer "):
|
|
29
|
+
return auth_header[7:]
|
|
30
|
+
|
|
31
|
+
try:
|
|
32
|
+
if "access_token" in request.session:
|
|
33
|
+
log.debug("AuthMiddleware: Found token in session.")
|
|
34
|
+
return request.session["access_token"]
|
|
35
|
+
except AssertionError:
|
|
36
|
+
log.debug("AuthMiddleware: Could not access request.session.")
|
|
37
|
+
|
|
38
|
+
if "token" in request.query_params:
|
|
39
|
+
return request.query_params["token"]
|
|
40
|
+
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
async def _validate_token(
|
|
45
|
+
auth_service_url: str, auth_provider: str, access_token: str
|
|
46
|
+
) -> bool:
|
|
47
|
+
"""
|
|
48
|
+
Validate token with external OAuth service.
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
auth_service_url: Base URL of OAuth service
|
|
52
|
+
auth_provider: OAuth provider name (azure, google, okta, etc.)
|
|
53
|
+
access_token: Bearer token to validate
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
True if token is valid, False otherwise
|
|
57
|
+
"""
|
|
58
|
+
async with httpx.AsyncClient() as client:
|
|
59
|
+
validation_response = await client.post(
|
|
60
|
+
f"{auth_service_url}/is_token_valid",
|
|
61
|
+
json={"provider": auth_provider},
|
|
62
|
+
headers={"Authorization": f"Bearer {access_token}"},
|
|
63
|
+
)
|
|
64
|
+
return validation_response.status_code == 200
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
async def _get_user_info(
|
|
68
|
+
auth_service_url: str, auth_provider: str, access_token: str
|
|
69
|
+
) -> dict:
|
|
70
|
+
"""
|
|
71
|
+
Get user info from OAuth service.
|
|
72
|
+
|
|
73
|
+
Args:
|
|
74
|
+
auth_service_url: Base URL of OAuth service
|
|
75
|
+
auth_provider: OAuth provider name
|
|
76
|
+
access_token: Bearer token
|
|
77
|
+
|
|
78
|
+
Returns:
|
|
79
|
+
User info dictionary if successful, None otherwise
|
|
80
|
+
"""
|
|
81
|
+
async with httpx.AsyncClient() as client:
|
|
82
|
+
userinfo_response = await client.get(
|
|
83
|
+
f"{auth_service_url}/user_info?provider={auth_provider}",
|
|
84
|
+
headers={"Authorization": f"Bearer {access_token}"},
|
|
85
|
+
)
|
|
86
|
+
|
|
87
|
+
if userinfo_response.status_code != 200:
|
|
88
|
+
return None
|
|
89
|
+
|
|
90
|
+
return userinfo_response.json()
|
|
91
|
+
|
|
92
|
+
|
|
93
|
+
def _extract_user_identifier(user_info: dict) -> str:
|
|
94
|
+
"""Extract user identifier from OAuth user info."""
|
|
95
|
+
user_identifier = (
|
|
96
|
+
user_info.get("sub")
|
|
97
|
+
or user_info.get("client_id")
|
|
98
|
+
or user_info.get("username")
|
|
99
|
+
or user_info.get("oid")
|
|
100
|
+
or user_info.get("preferred_username")
|
|
101
|
+
or user_info.get("upn")
|
|
102
|
+
or user_info.get("unique_name")
|
|
103
|
+
or user_info.get("email")
|
|
104
|
+
or user_info.get("name")
|
|
105
|
+
or user_info.get("azp")
|
|
106
|
+
or user_info.get("user_id")
|
|
107
|
+
)
|
|
108
|
+
|
|
109
|
+
if user_identifier and user_identifier.lower() == "unknown":
|
|
110
|
+
log.warning("AuthMiddleware: IDP returned 'Unknown' as user identifier. Using fallback.")
|
|
111
|
+
return "sam_dev_user"
|
|
112
|
+
|
|
113
|
+
return user_identifier
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def _extract_user_details(user_info: dict, user_identifier: str) -> tuple:
|
|
117
|
+
"""Extract email and display name from OAuth user info."""
|
|
118
|
+
email_from_auth = (
|
|
119
|
+
user_info.get("email")
|
|
120
|
+
or user_info.get("preferred_username")
|
|
121
|
+
or user_info.get("upn")
|
|
122
|
+
or user_identifier
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
display_name = (
|
|
126
|
+
user_info.get("name")
|
|
127
|
+
or user_info.get("given_name", "") + " " + user_info.get("family_name", "")
|
|
128
|
+
or user_info.get("preferred_username")
|
|
129
|
+
or user_identifier
|
|
130
|
+
).strip()
|
|
131
|
+
|
|
132
|
+
return email_from_auth, display_name
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
async def _create_user_state(
|
|
136
|
+
user_identifier: str, email_from_auth: str, display_name: str
|
|
137
|
+
) -> dict:
|
|
138
|
+
"""Create user state dictionary from OAuth info."""
|
|
139
|
+
final_user_id = user_identifier or email_from_auth or "sam_dev_user"
|
|
140
|
+
if not final_user_id or final_user_id.lower() in ["unknown", "null", "none", ""]:
|
|
141
|
+
final_user_id = "sam_dev_user"
|
|
142
|
+
log.warning("AuthMiddleware: Had to use fallback user ID due to invalid identifier")
|
|
143
|
+
|
|
144
|
+
return {
|
|
145
|
+
"id": final_user_id,
|
|
146
|
+
"email": email_from_auth or final_user_id,
|
|
147
|
+
"name": display_name or final_user_id,
|
|
148
|
+
"authenticated": True,
|
|
149
|
+
"auth_method": "oidc",
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
|
|
153
|
+
def create_oauth_middleware(component):
|
|
154
|
+
"""
|
|
155
|
+
Create OAuth2 authentication middleware for any component (gateway or service).
|
|
156
|
+
|
|
157
|
+
Works with any component that has:
|
|
158
|
+
- external_auth_service_url config
|
|
159
|
+
- external_auth_provider config
|
|
160
|
+
- use_authorization config
|
|
161
|
+
|
|
162
|
+
Args:
|
|
163
|
+
component: Component instance (gateway or service)
|
|
164
|
+
|
|
165
|
+
Returns:
|
|
166
|
+
AuthMiddleware class configured for the component
|
|
167
|
+
"""
|
|
168
|
+
|
|
169
|
+
class AuthMiddleware:
|
|
170
|
+
def __init__(self, app, component):
|
|
171
|
+
self.app = app
|
|
172
|
+
self.component = component
|
|
173
|
+
|
|
174
|
+
async def __call__(self, scope, receive, send):
|
|
175
|
+
if scope["type"] != "http":
|
|
176
|
+
await self.app(scope, receive, send)
|
|
177
|
+
return
|
|
178
|
+
|
|
179
|
+
request = FastAPIRequest(scope, receive)
|
|
180
|
+
|
|
181
|
+
if not request.url.path.startswith("/api"):
|
|
182
|
+
await self.app(scope, receive, send)
|
|
183
|
+
return
|
|
184
|
+
|
|
185
|
+
skip_paths = [
|
|
186
|
+
"/api/v1/config",
|
|
187
|
+
"/api/v1/auth/callback",
|
|
188
|
+
"/api/v1/auth/tool/callback",
|
|
189
|
+
"/api/v1/auth/login",
|
|
190
|
+
"/api/v1/auth/refresh",
|
|
191
|
+
"/api/v1/csrf-token",
|
|
192
|
+
"/health",
|
|
193
|
+
]
|
|
194
|
+
|
|
195
|
+
if any(request.url.path.startswith(path) for path in skip_paths):
|
|
196
|
+
await self.app(scope, receive, send)
|
|
197
|
+
return
|
|
198
|
+
|
|
199
|
+
if request.method == "OPTIONS":
|
|
200
|
+
await self.app(scope, receive, send)
|
|
201
|
+
return
|
|
202
|
+
|
|
203
|
+
use_auth = self.component.get_config("frontend_use_authorization", False)
|
|
204
|
+
|
|
205
|
+
if use_auth:
|
|
206
|
+
if await self._handle_authenticated_request(request, scope, receive, send):
|
|
207
|
+
return
|
|
208
|
+
else:
|
|
209
|
+
request.state.user = {
|
|
210
|
+
"id": "sam_dev_user",
|
|
211
|
+
"name": "Sam Dev User",
|
|
212
|
+
"email": "sam@dev.local",
|
|
213
|
+
"authenticated": True,
|
|
214
|
+
"auth_method": "development",
|
|
215
|
+
}
|
|
216
|
+
log.debug("AuthMiddleware: Set development user (frontend_use_authorization=false)")
|
|
217
|
+
|
|
218
|
+
await self.app(scope, receive, send)
|
|
219
|
+
|
|
220
|
+
async def _handle_authenticated_request(self, request, scope, receive, send) -> bool:
|
|
221
|
+
"""
|
|
222
|
+
Handle authentication for a request.
|
|
223
|
+
|
|
224
|
+
Returns:
|
|
225
|
+
True if an error response was sent (caller should not continue),
|
|
226
|
+
False if authentication succeeded (caller should proceed with app).
|
|
227
|
+
"""
|
|
228
|
+
access_token = _extract_access_token(request)
|
|
229
|
+
|
|
230
|
+
if not access_token:
|
|
231
|
+
log.warning("AuthMiddleware: No access token found. Returning 401.")
|
|
232
|
+
response = JSONResponse(
|
|
233
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
234
|
+
content={
|
|
235
|
+
"detail": "Not authenticated",
|
|
236
|
+
"error_type": "authentication_required",
|
|
237
|
+
},
|
|
238
|
+
)
|
|
239
|
+
await response(scope, receive, send)
|
|
240
|
+
return True
|
|
241
|
+
|
|
242
|
+
auth_service_url = getattr(self.component, "external_auth_service_url", None)
|
|
243
|
+
auth_provider = getattr(self.component, "external_auth_provider", "generic")
|
|
244
|
+
|
|
245
|
+
if not auth_service_url:
|
|
246
|
+
log.error("Auth service URL not configured.")
|
|
247
|
+
response = JSONResponse(
|
|
248
|
+
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
249
|
+
content={"detail": "Auth service not configured"},
|
|
250
|
+
)
|
|
251
|
+
await response(scope, receive, send)
|
|
252
|
+
return True
|
|
253
|
+
|
|
254
|
+
if not await _validate_token(auth_service_url, auth_provider, access_token):
|
|
255
|
+
log.warning("AuthMiddleware: Token validation failed")
|
|
256
|
+
response = JSONResponse(
|
|
257
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
258
|
+
content={"detail": "Invalid token", "error_type": "invalid_token"},
|
|
259
|
+
)
|
|
260
|
+
await response(scope, receive, send)
|
|
261
|
+
return True
|
|
262
|
+
|
|
263
|
+
user_info = await _get_user_info(auth_service_url, auth_provider, access_token)
|
|
264
|
+
if not user_info:
|
|
265
|
+
log.warning("AuthMiddleware: Failed to get user info")
|
|
266
|
+
response = JSONResponse(
|
|
267
|
+
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
268
|
+
content={"detail": "Could not retrieve user info"},
|
|
269
|
+
)
|
|
270
|
+
await response(scope, receive, send)
|
|
271
|
+
return True
|
|
272
|
+
|
|
273
|
+
user_identifier = _extract_user_identifier(user_info)
|
|
274
|
+
email_from_auth, display_name = _extract_user_details(user_info, user_identifier)
|
|
275
|
+
|
|
276
|
+
request.state.user = await _create_user_state(
|
|
277
|
+
user_identifier, email_from_auth, display_name
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
log.debug(f"AuthMiddleware: Authenticated user: {request.state.user['id']}")
|
|
281
|
+
return False
|
|
282
|
+
|
|
283
|
+
return AuthMiddleware
|
|
284
|
+
|
|
285
|
+
|
|
286
|
+
__all__ = [
|
|
287
|
+
"create_oauth_middleware",
|
|
288
|
+
"_extract_access_token",
|
|
289
|
+
"_validate_token",
|
|
290
|
+
"_get_user_info",
|
|
291
|
+
]
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Database utilities for repositories and data access.
|
|
3
|
+
|
|
4
|
+
Provides:
|
|
5
|
+
- Base repository classes (PaginatedRepository, ValidationMixin)
|
|
6
|
+
- Database exception handlers
|
|
7
|
+
- Database helpers (SimpleJSON type)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from .base_repository import PaginatedRepository, ValidationMixin
|
|
11
|
+
from .database_exceptions import DatabaseExceptionHandler, DatabaseErrorDecorator
|
|
12
|
+
from .database_helpers import SimpleJSON
|
|
13
|
+
|
|
14
|
+
__all__ = [
|
|
15
|
+
"PaginatedRepository",
|
|
16
|
+
"ValidationMixin",
|
|
17
|
+
"DatabaseExceptionHandler",
|
|
18
|
+
"DatabaseErrorDecorator",
|
|
19
|
+
"SimpleJSON",
|
|
20
|
+
]
|
|
@@ -8,7 +8,7 @@ that can be properly handled by the API layer.
|
|
|
8
8
|
|
|
9
9
|
from typing import Optional, Dict, List
|
|
10
10
|
from sqlalchemy.exc import IntegrityError, SQLAlchemyError, OperationalError, DatabaseError
|
|
11
|
-
from .exceptions import ValidationError, DataIntegrityError, EntityAlreadyExistsError
|
|
11
|
+
from ..exceptions.exceptions import ValidationError, DataIntegrityError, EntityAlreadyExistsError
|
|
12
12
|
|
|
13
13
|
|
|
14
14
|
class DatabaseExceptionHandler:
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Exception types and handlers for consistent error handling.
|
|
3
|
+
|
|
4
|
+
Provides:
|
|
5
|
+
- Business exception types (ValidationError, EntityNotFoundError, etc.)
|
|
6
|
+
- FastAPI exception handlers
|
|
7
|
+
- Error DTOs for API responses
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from .exceptions import (
|
|
11
|
+
WebUIBackendException,
|
|
12
|
+
ValidationError,
|
|
13
|
+
EntityNotFoundError,
|
|
14
|
+
EntityAlreadyExistsError,
|
|
15
|
+
BusinessRuleViolationError,
|
|
16
|
+
ConfigurationError,
|
|
17
|
+
DataIntegrityError,
|
|
18
|
+
ExternalServiceError,
|
|
19
|
+
EntityOperation,
|
|
20
|
+
)
|
|
21
|
+
from .exception_handlers import register_exception_handlers
|
|
22
|
+
from .error_dto import EventErrorDTO
|
|
23
|
+
|
|
24
|
+
__all__ = [
|
|
25
|
+
"WebUIBackendException",
|
|
26
|
+
"ValidationError",
|
|
27
|
+
"EntityNotFoundError",
|
|
28
|
+
"EntityAlreadyExistsError",
|
|
29
|
+
"BusinessRuleViolationError",
|
|
30
|
+
"ConfigurationError",
|
|
31
|
+
"DataIntegrityError",
|
|
32
|
+
"ExternalServiceError",
|
|
33
|
+
"EntityOperation",
|
|
34
|
+
"register_exception_handlers",
|
|
35
|
+
"EventErrorDTO",
|
|
36
|
+
]
|
|
@@ -193,7 +193,7 @@ def register_exception_handlers(app):
|
|
|
193
193
|
|
|
194
194
|
Example:
|
|
195
195
|
from fastapi import FastAPI
|
|
196
|
-
from solace_agent_mesh.
|
|
196
|
+
from solace_agent_mesh.shared.exceptions.exception_handlers import register_exception_handlers
|
|
197
197
|
|
|
198
198
|
app = FastAPI()
|
|
199
199
|
register_exception_handlers(app)
|