solace-agent-mesh 1.4.12__py3-none-any.whl → 1.5.1__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/adk_llm.txt +3 -4
- solace_agent_mesh/agent/adk/adk_llm_detail.txt +566 -0
- solace_agent_mesh/agent/adk/artifacts/artifacts_llm.txt +1 -1
- solace_agent_mesh/agent/adk/callbacks.py +56 -5
- solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +3 -1
- solace_agent_mesh/agent/adk/intelligent_mcp_callbacks.py +2 -1
- solace_agent_mesh/agent/adk/mcp_content_processor.py +2 -1
- solace_agent_mesh/agent/adk/models/lite_llm.py +1 -0
- solace_agent_mesh/agent/adk/models/models_llm.txt +1 -2
- solace_agent_mesh/agent/adk/runner.py +3 -1
- solace_agent_mesh/agent/adk/services.py +4 -1
- solace_agent_mesh/agent/adk/setup.py +3 -1
- solace_agent_mesh/agent/adk/tool_wrapper.py +2 -2
- solace_agent_mesh/agent/agent_llm.txt +1 -1
- solace_agent_mesh/agent/agent_llm_detail.txt +1702 -0
- solace_agent_mesh/agent/protocol/event_handlers.py +4 -14
- solace_agent_mesh/agent/protocol/protocol_llm.txt +15 -2
- solace_agent_mesh/agent/protocol/protocol_llm_detail.txt +92 -0
- solace_agent_mesh/agent/sac/app.py +3 -1
- solace_agent_mesh/agent/sac/component.py +55 -22
- solace_agent_mesh/agent/sac/sac_llm.txt +15 -1
- solace_agent_mesh/agent/sac/sac_llm_detail.txt +200 -0
- solace_agent_mesh/agent/sac/task_execution_context.py +73 -0
- solace_agent_mesh/agent/testing/testing_llm_detail.txt +68 -0
- solace_agent_mesh/agent/tools/audio_tools.py +2 -1
- solace_agent_mesh/agent/tools/builtin_artifact_tools.py +3 -1
- solace_agent_mesh/agent/tools/builtin_data_analysis_tools.py +3 -1
- solace_agent_mesh/agent/tools/dynamic_tool.py +2 -1
- solace_agent_mesh/agent/tools/general_agent_tools.py +2 -1
- solace_agent_mesh/agent/tools/image_tools.py +2 -1
- solace_agent_mesh/agent/tools/peer_agent_tool.py +2 -1
- solace_agent_mesh/agent/tools/registry.py +3 -1
- solace_agent_mesh/agent/tools/test_tools.py +2 -1
- solace_agent_mesh/agent/tools/tools_llm.txt +148 -154
- solace_agent_mesh/agent/tools/tools_llm_detail.txt +274 -0
- solace_agent_mesh/agent/tools/web_tools.py +2 -1
- solace_agent_mesh/agent/utils/artifact_helpers.py +3 -1
- solace_agent_mesh/agent/utils/config_parser.py +3 -1
- solace_agent_mesh/agent/utils/utils_llm.txt +1 -1
- solace_agent_mesh/agent/utils/utils_llm_detail.txt +149 -0
- solace_agent_mesh/assets/docs/404.html +3 -3
- solace_agent_mesh/assets/docs/assets/js/{b7006a3a.73a79653.js → 032c2d61.f3d37824.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/0bcf40b7.c019ad46.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/15ba94aa.932dd2db.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2131ec11.5c7a1f6e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{2334.622a6395.js → 2334.1cf50a20.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/240a0364.7eac6021.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2e32b5e0.33f5d75b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/341393d4.0fac2613.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{3624.b524e433.js → 3624.0eaa1fd0.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/3a6c6137.f5940cfa.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3ac1795d.76654dd9.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3ff0015d.2be20244.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/509e993c.4c7a1a6d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/547e15cc.2cbb060a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/55b7b518.f2b1d1ba.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5c2bd65f.e49689dd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6063ff4c.ef84f702.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/631738c7.a8b1ef8b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6a520c9d.ba015d81.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.39d5851d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6d84eae0.4a5fbf39.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6fdfefc7.99de744e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/71da7b71.804d6567.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/722f809d.965da774.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/742f027b.46c07808.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/77cf947d.64c9bd6c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8024126c.56e59919.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/81a99df0.07034dd9.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/82fbfb93.139a1a1f.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{8591.d7c16be6.js → 8591.5d015485.js} +2 -2
- solace_agent_mesh/assets/docs/assets/js/{8731.49e930c2.js → 8731.6c1dbf0c.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/945fb41e.6f4cdffd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/94e8668d.b5ddb7a1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9bb13469.dd1c9b54.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9e9d0a82.dd810042.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ab9708a8.3e6dd091.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ad71b5ed.60668e9e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/c198a0dc.8f31f867.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/c93cbaa0.eaff365e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/da0b5bad.9d369087.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/db924877.cbc66f02.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/dd817ffc.0aa9630a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/dd81e2b8.d590bc9e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/de5f4c65.e8241890.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/de915948.139b4b9c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e3d9abda.2b916f9e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e6f9706b.582a78ca.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e92d0134.cf6d6522.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/f284c35a.5766a13d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ff4d71f2.9c0297a6.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/main.bd3c34f3.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/runtime~main.18dc45dd.js +1 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +143 -0
- solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/artifact-management/index.html +7 -7
- solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/audio-tools/index.html +7 -7
- solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/data-analysis-tools/index.html +8 -8
- solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/embeds/index.html +6 -6
- solace_agent_mesh/assets/docs/docs/documentation/{user-guide → components}/builtin-tools/index.html +11 -11
- solace_agent_mesh/assets/docs/docs/documentation/{concepts → components}/cli/index.html +25 -25
- solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +91 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/index.html +29 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +55 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +110 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +104 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +57 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +25 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +59 -0
- solace_agent_mesh/assets/docs/docs/documentation/{user-guide → developing}/create-agents/index.html +113 -152
- solace_agent_mesh/assets/docs/docs/documentation/{user-guide → developing}/create-gateways/index.html +9 -9
- solace_agent_mesh/assets/docs/docs/documentation/{user-guide → developing}/creating-python-tools/index.html +12 -12
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +54 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +32 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +55 -0
- solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/bedrock-agents/index.html +25 -25
- solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/custom-agent/index.html +13 -13
- solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/event-mesh-gateway/index.html +11 -11
- solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/mcp-integration/index.html +10 -10
- solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/mongodb-integration/index.html +13 -13
- solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/rag-integration/index.html +13 -13
- solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/rest-gateway/index.html +10 -10
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +72 -0
- solace_agent_mesh/assets/docs/docs/documentation/{tutorials → developing/tutorials}/sql-database/index.html +14 -14
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +33 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +83 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +222 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +161 -0
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +75 -0
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +53 -0
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +35 -100
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +41 -0
- solace_agent_mesh/assets/docs/docs/documentation/{getting-started → installing-and-configuring}/configurations/index.html +56 -50
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +25 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +76 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +63 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +142 -0
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +100 -0
- solace_agent_mesh/assets/docs/docs/documentation/{Migrations/A2A Upgrade To 0.3.0/a2a-technical-migration-map/index.html → migrations/a2a-upgrade/a2a-technical-migration-map/index.html} +10 -11
- solace_agent_mesh/assets/docs/img/solace-logo.png +0 -0
- solace_agent_mesh/assets/docs/lunr-index-1760121512891.json +1 -0
- solace_agent_mesh/assets/docs/lunr-index.json +1 -1
- solace_agent_mesh/assets/docs/search-doc-1760121512891.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/client/webui/frontend/static/assets/{authCallback-j1LW-wlq.js → authCallback-DwrxZE0E.js} +1 -1
- solace_agent_mesh/client/webui/frontend/static/assets/{client-B9p_nFNA.js → client-DarGQzyw.js} +1 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main-2nd1gbaH.js +339 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-DoKXctCM.css +1 -0
- solace_agent_mesh/client/webui/frontend/static/assets/{vendor-CS5YMf8a.js → vendor-BKIeiHj_.js} +80 -70
- 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/common/a2a/a2a_llm.txt +1 -1
- solace_agent_mesh/common/a2a/a2a_llm_detail.txt +193 -0
- solace_agent_mesh/common/a2a/artifact.py +2 -1
- solace_agent_mesh/common/a2a/protocol.py +3 -2
- solace_agent_mesh/common/a2a/translation.py +3 -1
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +1 -1
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm_detail.txt +736 -0
- solace_agent_mesh/common/a2a_spec/schemas/llm_invocation.json +23 -0
- solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +93 -15
- solace_agent_mesh/common/a2a_spec/schemas/tool_result.json +23 -0
- solace_agent_mesh/common/common_llm.txt +24 -39
- solace_agent_mesh/common/common_llm_detail.txt +2562 -0
- solace_agent_mesh/common/data_parts.py +9 -1
- solace_agent_mesh/common/middleware/config_resolver.py +3 -1
- solace_agent_mesh/common/middleware/middleware_llm_detail.txt +185 -0
- solace_agent_mesh/common/middleware/registry.py +3 -1
- solace_agent_mesh/common/sac/sac_llm.txt +1 -1
- solace_agent_mesh/common/sac/sac_llm_detail.txt +82 -0
- solace_agent_mesh/common/sac/sam_component_base.py +2 -1
- solace_agent_mesh/common/sam_events/event_service.py +3 -2
- solace_agent_mesh/common/sam_events/sam_events_llm.txt +104 -0
- solace_agent_mesh/common/sam_events/sam_events_llm_detail.txt +115 -0
- solace_agent_mesh/common/services/employee_service.py +3 -1
- solace_agent_mesh/common/services/identity_service.py +2 -1
- solace_agent_mesh/common/services/providers/local_file_identity_service.py +2 -1
- solace_agent_mesh/common/services/services_llm.txt +57 -6
- solace_agent_mesh/common/services/services_llm_detail.txt +459 -0
- solace_agent_mesh/common/utils/artifact_utils.py +3 -1
- solace_agent_mesh/common/utils/asyncio_macos_fix.py +3 -1
- solace_agent_mesh/common/utils/embeds/converter.py +3 -1
- solace_agent_mesh/common/utils/embeds/embeds_llm.txt +1 -1
- solace_agent_mesh/common/utils/embeds/evaluators.py +2 -1
- solace_agent_mesh/common/utils/embeds/modifiers.py +3 -2
- solace_agent_mesh/common/utils/embeds/resolver.py +2 -1
- solace_agent_mesh/common/utils/initializer.py +3 -1
- solace_agent_mesh/common/utils/message_utils.py +2 -1
- solace_agent_mesh/common/utils/push_notification_auth.py +3 -2
- solace_agent_mesh/common/utils/utils_llm.txt +75 -87
- solace_agent_mesh/common/utils/utils_llm_detail.txt +572 -0
- solace_agent_mesh/core_a2a/core_a2a_llm_detail.txt +101 -0
- solace_agent_mesh/core_a2a/service.py +2 -2
- solace_agent_mesh/gateway/base/app.py +3 -2
- solace_agent_mesh/gateway/base/base_llm.txt +1 -1
- solace_agent_mesh/gateway/base/base_llm_detail.txt +235 -0
- solace_agent_mesh/gateway/base/component.py +3 -1
- solace_agent_mesh/gateway/base/task_context.py +2 -1
- solace_agent_mesh/gateway/gateway_llm.txt +242 -235
- solace_agent_mesh/gateway/gateway_llm_detail.txt +3885 -0
- solace_agent_mesh/gateway/http_sse/alembic/alembic_llm.txt +295 -0
- solace_agent_mesh/gateway/http_sse/alembic/env.py +10 -1
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251006_98882922fa59_add_tasks_events_feedback_chat_tasks.py +190 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/versions_llm.txt +155 -0
- solace_agent_mesh/gateway/http_sse/alembic.ini +1 -1
- solace_agent_mesh/gateway/http_sse/app.py +150 -3
- solace_agent_mesh/gateway/http_sse/component.py +372 -61
- solace_agent_mesh/gateway/http_sse/components/components_llm.txt +46 -6
- solace_agent_mesh/gateway/http_sse/components/task_logger_forwarder.py +109 -0
- solace_agent_mesh/gateway/http_sse/components/visualization_forwarder_component.py +4 -2
- solace_agent_mesh/gateway/http_sse/dependencies.py +119 -27
- solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +172 -172
- solace_agent_mesh/gateway/http_sse/http_sse_llm_detail.txt +3278 -0
- solace_agent_mesh/gateway/http_sse/main.py +149 -42
- solace_agent_mesh/gateway/http_sse/repository/__init__.py +3 -12
- solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +103 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/__init__.py +5 -3
- solace_agent_mesh/gateway/http_sse/repository/entities/chat_task.py +75 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/entities_llm.txt +263 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/feedback.py +20 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/session_history.py +0 -16
- solace_agent_mesh/gateway/http_sse/repository/entities/task.py +25 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/task_event.py +21 -0
- solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +81 -0
- solace_agent_mesh/gateway/http_sse/repository/interfaces.py +73 -18
- solace_agent_mesh/gateway/http_sse/repository/models/__init__.py +9 -5
- solace_agent_mesh/gateway/http_sse/repository/models/chat_task_model.py +31 -0
- solace_agent_mesh/gateway/http_sse/repository/models/feedback_model.py +21 -0
- solace_agent_mesh/gateway/http_sse/repository/models/models_llm.txt +266 -0
- solace_agent_mesh/gateway/http_sse/repository/models/session_model.py +3 -3
- solace_agent_mesh/gateway/http_sse/repository/models/task_event_model.py +25 -0
- solace_agent_mesh/gateway/http_sse/repository/models/task_model.py +32 -0
- solace_agent_mesh/gateway/http_sse/repository/repository_llm.txt +340 -0
- solace_agent_mesh/gateway/http_sse/repository/session_repository.py +4 -53
- solace_agent_mesh/gateway/http_sse/repository/task_repository.py +173 -0
- solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +3 -2
- solace_agent_mesh/gateway/http_sse/routers/artifacts.py +3 -3
- solace_agent_mesh/gateway/http_sse/routers/auth.py +3 -1
- solace_agent_mesh/gateway/http_sse/routers/config.py +29 -6
- solace_agent_mesh/gateway/http_sse/routers/dto/dto_llm.txt +346 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/__init__.py +3 -3
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/requests_llm.txt +83 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/session_requests.py +2 -10
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/task_requests.py +58 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/__init__.py +5 -3
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/responses_llm.txt +107 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +1 -15
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/task_responses.py +30 -0
- solace_agent_mesh/gateway/http_sse/routers/feedback.py +37 -0
- solace_agent_mesh/gateway/http_sse/routers/people.py +3 -1
- solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +255 -204
- solace_agent_mesh/gateway/http_sse/routers/sessions.py +223 -41
- solace_agent_mesh/gateway/http_sse/routers/sse.py +3 -2
- solace_agent_mesh/gateway/http_sse/routers/tasks.py +170 -43
- solace_agent_mesh/gateway/http_sse/routers/users.py +3 -1
- solace_agent_mesh/gateway/http_sse/routers/visualization.py +2 -1
- solace_agent_mesh/gateway/http_sse/services/agent_card_service.py +3 -1
- solace_agent_mesh/gateway/http_sse/services/data_retention_service.py +273 -0
- solace_agent_mesh/gateway/http_sse/services/feedback_service.py +242 -0
- solace_agent_mesh/gateway/http_sse/services/people_service.py +2 -82
- solace_agent_mesh/gateway/http_sse/services/services_llm.txt +177 -13
- solace_agent_mesh/gateway/http_sse/services/session_service.py +154 -85
- solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +318 -0
- solace_agent_mesh/gateway/http_sse/services/task_service.py +3 -2
- solace_agent_mesh/gateway/http_sse/session_manager.py +2 -1
- solace_agent_mesh/gateway/http_sse/shared/exception_handlers.py +25 -14
- solace_agent_mesh/gateway/http_sse/shared/shared_llm.txt +285 -0
- solace_agent_mesh/gateway/http_sse/shared/types.py +7 -0
- solace_agent_mesh/gateway/http_sse/sse_event_buffer.py +2 -1
- solace_agent_mesh/gateway/http_sse/sse_manager.py +2 -2
- solace_agent_mesh/gateway/http_sse/utils/__init__.py +1 -0
- solace_agent_mesh/gateway/http_sse/utils/stim_utils.py +32 -0
- solace_agent_mesh/gateway/http_sse/utils/utils_llm.txt +47 -0
- solace_agent_mesh/solace_agent_mesh_llm.txt +1 -1
- solace_agent_mesh/solace_agent_mesh_llm_detail.txt +8599 -0
- solace_agent_mesh/templates/gateway_app_template.py +4 -2
- solace_agent_mesh/templates/gateway_component_template.py +3 -1
- solace_agent_mesh/templates/logging_config_template.ini +22 -45
- solace_agent_mesh/templates/plugin_tools_template.py +2 -2
- {solace_agent_mesh-1.4.12.dist-info → solace_agent_mesh-1.5.1.dist-info}/METADATA +2 -2
- solace_agent_mesh-1.5.1.dist-info/RECORD +504 -0
- solace_agent_mesh/agent/adk/invocation_monitor.py +0 -295
- solace_agent_mesh/assets/docs/assets/images/sac-flows-80d5b603c6aafd33e87945680ce0abf3.png +0 -0
- solace_agent_mesh/assets/docs/assets/images/sac_parts_of_a_component-cb3d0424b1d0c17734c5435cca6b4082.png +0 -0
- solace_agent_mesh/assets/docs/assets/js/04989206.a248f00c.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/0e682baa.d54b8668.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/1023fc19.8a8a9309.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/1523c6b4.2645ef68.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/166ab619.e27886d9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/1c6e87d2.e056b7e0.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/21ceee5f.3bf39250.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/2a9cab12.2afaee76.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/332e10b5.f7629851.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3d406171.5560fdf9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/42b3f8d8.508ae8db.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/442a8107.b5c2532a.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/453a82a6.3c6bb61d.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/483cef9a.4736f2d8.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/4c2787c2.c1290a40.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/55f47984.bcd00a86.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/5b4258a4.fdfd2325.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/664b740a.ba305a89.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/75384d09.c19e8b51.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/768e31b0.9abcdc48.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/85387663.be2bc838.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/945fb41e.16e00776.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/9a09e75d.92de8cf5.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/9eff14a2.d62aad71.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/a12a4955.25fbed32.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/a3a92b25.af35e313.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/aba87c2f.4ddf32f2.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/ae0e903d.5fe5203f.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/ae4415af.16cc58d3.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/bac0be12.17de4316.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/c2c06897.87cb1f47.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/c835a94d.ce21f0bf.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/cc969b05.feef7dcc.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/cd3d4052.a19e7d78.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/ced92a13.fb92e7ca.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/cee5d587.47904f5e.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/d6a81ee7.829198f1.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/f284c35a.ed8dd236.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/f897a61a.126663fe.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/fbfa3e75.e144b16c.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/main.f67fc9f4.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/runtime~main.40527046.js +0 -1
- solace_agent_mesh/assets/docs/docs/documentation/Enterprise/installation/index.html +0 -46
- solace_agent_mesh/assets/docs/docs/documentation/Enterprise/rbac-setup-guilde/index.html +0 -201
- solace_agent_mesh/assets/docs/docs/documentation/Enterprise/single-sign-on/index.html +0 -25
- solace_agent_mesh/assets/docs/docs/documentation/Migrations/A2A Upgrade To 0.3.0/a2a-gateway-upgrade-to-0.3.0/index.html +0 -105
- solace_agent_mesh/assets/docs/docs/documentation/concepts/agents/index.html +0 -144
- solace_agent_mesh/assets/docs/docs/documentation/concepts/architecture/index.html +0 -91
- solace_agent_mesh/assets/docs/docs/documentation/concepts/gateways/index.html +0 -91
- solace_agent_mesh/assets/docs/docs/documentation/concepts/orchestrator/index.html +0 -55
- solace_agent_mesh/assets/docs/docs/documentation/concepts/plugins/index.html +0 -111
- solace_agent_mesh/assets/docs/docs/documentation/deployment/debugging/index.html +0 -77
- solace_agent_mesh/assets/docs/docs/documentation/deployment/deploy/index.html +0 -48
- solace_agent_mesh/assets/docs/docs/documentation/deployment/observability/index.html +0 -54
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/component-overview/index.html +0 -45
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/configurations/litellm_models/index.html +0 -49
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/installation/index.html +0 -76
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/quick-start/index.html +0 -73
- solace_agent_mesh/assets/docs/docs/documentation/tutorials/slack-integration/index.html +0 -72
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/creating-service-providers/index.html +0 -54
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/solace-ai-connector/index.html +0 -69
- solace_agent_mesh/assets/docs/docs/documentation/user-guide/structure/index.html +0 -59
- solace_agent_mesh/assets/docs/lunr-index-1759936913198.json +0 -1
- solace_agent_mesh/assets/docs/search-doc-1759936913198.json +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main-ChRwcV89.css +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main-DnnE01OM.js +0 -339
- solace_agent_mesh/gateway/http_sse/repository/entities/message.py +0 -41
- solace_agent_mesh/gateway/http_sse/repository/message_repository.py +0 -84
- solace_agent_mesh/gateway/http_sse/repository/models/message_model.py +0 -45
- solace_agent_mesh-1.4.12.dist-info/RECORD +0 -448
- /solace_agent_mesh/assets/docs/assets/js/{8591.d7c16be6.js.LICENSE.txt → 8591.5d015485.js.LICENSE.txt} +0 -0
- /solace_agent_mesh/assets/docs/assets/js/{main.f67fc9f4.js.LICENSE.txt → main.bd3c34f3.js.LICENSE.txt} +0 -0
- {solace_agent_mesh-1.4.12.dist-info → solace_agent_mesh-1.5.1.dist-info}/WHEEL +0 -0
- {solace_agent_mesh-1.4.12.dist-info → solace_agent_mesh-1.5.1.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-1.4.12.dist-info → solace_agent_mesh-1.5.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import logging
|
|
1
2
|
import os
|
|
2
3
|
from pathlib import Path
|
|
3
4
|
from typing import TYPE_CHECKING
|
|
@@ -14,7 +15,6 @@ from fastapi import status
|
|
|
14
15
|
from fastapi.exceptions import RequestValidationError
|
|
15
16
|
from fastapi.middleware.cors import CORSMiddleware
|
|
16
17
|
from fastapi.responses import JSONResponse
|
|
17
|
-
from solace_ai_connector.common.log import log
|
|
18
18
|
from starlette.middleware.sessions import SessionMiddleware
|
|
19
19
|
from starlette.staticfiles import StaticFiles
|
|
20
20
|
|
|
@@ -29,6 +29,7 @@ from ...gateway.http_sse.routers import (
|
|
|
29
29
|
sse,
|
|
30
30
|
tasks,
|
|
31
31
|
visualization,
|
|
32
|
+
feedback,
|
|
32
33
|
)
|
|
33
34
|
from .routers.sessions import router as session_router
|
|
34
35
|
from .routers.tasks import router as task_router
|
|
@@ -37,12 +38,17 @@ from .routers.users import router as user_router
|
|
|
37
38
|
if TYPE_CHECKING:
|
|
38
39
|
from gateway.http_sse.component import WebUIBackendComponent
|
|
39
40
|
|
|
41
|
+
log = logging.getLogger(__name__)
|
|
42
|
+
|
|
40
43
|
app = FastAPI(
|
|
41
44
|
title="A2A Web UI Backend",
|
|
42
45
|
version="1.0.0", # Updated to reflect simplified architecture
|
|
43
46
|
description="Backend API and SSE server for the A2A Web UI, hosted by Solace AI Connector.",
|
|
44
47
|
)
|
|
45
48
|
|
|
49
|
+
# Global flag to track if dependencies have been initialized
|
|
50
|
+
_dependencies_initialized = False
|
|
51
|
+
|
|
46
52
|
|
|
47
53
|
def _extract_access_token(request: FastAPIRequest) -> str:
|
|
48
54
|
auth_header = request.headers.get("Authorization")
|
|
@@ -62,7 +68,9 @@ def _extract_access_token(request: FastAPIRequest) -> str:
|
|
|
62
68
|
return None
|
|
63
69
|
|
|
64
70
|
|
|
65
|
-
async def _validate_token(
|
|
71
|
+
async def _validate_token(
|
|
72
|
+
auth_service_url: str, auth_provider: str, access_token: str
|
|
73
|
+
) -> bool:
|
|
66
74
|
async with httpx.AsyncClient() as client:
|
|
67
75
|
validation_response = await client.post(
|
|
68
76
|
f"{auth_service_url}/is_token_valid",
|
|
@@ -72,7 +80,9 @@ async def _validate_token(auth_service_url: str, auth_provider: str, access_toke
|
|
|
72
80
|
return validation_response.status_code == 200
|
|
73
81
|
|
|
74
82
|
|
|
75
|
-
async def _get_user_info(
|
|
83
|
+
async def _get_user_info(
|
|
84
|
+
auth_service_url: str, auth_provider: str, access_token: str
|
|
85
|
+
) -> dict:
|
|
76
86
|
async with httpx.AsyncClient() as client:
|
|
77
87
|
userinfo_response = await client.get(
|
|
78
88
|
f"{auth_service_url}/user_info?provider={auth_provider}",
|
|
@@ -100,7 +110,9 @@ def _extract_user_identifier(user_info: dict) -> str:
|
|
|
100
110
|
)
|
|
101
111
|
|
|
102
112
|
if user_identifier and user_identifier.lower() == "unknown":
|
|
103
|
-
log.warning(
|
|
113
|
+
log.warning(
|
|
114
|
+
"AuthMiddleware: IDP returned 'Unknown' as user identifier. Using fallback."
|
|
115
|
+
)
|
|
104
116
|
return "sam_dev_user"
|
|
105
117
|
|
|
106
118
|
return user_identifier
|
|
@@ -124,7 +136,9 @@ def _extract_user_details(user_info: dict, user_identifier: str) -> tuple:
|
|
|
124
136
|
return email_from_auth, display_name
|
|
125
137
|
|
|
126
138
|
|
|
127
|
-
async def _create_user_state_without_identity_service(
|
|
139
|
+
async def _create_user_state_without_identity_service(
|
|
140
|
+
user_identifier: str, email_from_auth: str, display_name: str
|
|
141
|
+
) -> dict:
|
|
128
142
|
final_user_id = user_identifier or email_from_auth or "sam_dev_user"
|
|
129
143
|
if not final_user_id or final_user_id.lower() in ["unknown", "null", "none", ""]:
|
|
130
144
|
final_user_id = "sam_dev_user"
|
|
@@ -146,7 +160,13 @@ async def _create_user_state_without_identity_service(user_identifier: str, emai
|
|
|
146
160
|
}
|
|
147
161
|
|
|
148
162
|
|
|
149
|
-
async def _create_user_state_with_identity_service(
|
|
163
|
+
async def _create_user_state_with_identity_service(
|
|
164
|
+
identity_service,
|
|
165
|
+
user_identifier: str,
|
|
166
|
+
email_from_auth: str,
|
|
167
|
+
display_name: str,
|
|
168
|
+
user_info: dict,
|
|
169
|
+
) -> dict:
|
|
150
170
|
lookup_value = email_from_auth if "@" in email_from_auth else user_identifier
|
|
151
171
|
user_profile = await identity_service.get_user_profile(
|
|
152
172
|
{identity_service.lookup_key: lookup_value, "user_info": user_info}
|
|
@@ -186,24 +206,35 @@ def _create_auth_middleware(component):
|
|
|
186
206
|
return
|
|
187
207
|
|
|
188
208
|
skip_paths = [
|
|
189
|
-
"/api/v1/config",
|
|
190
|
-
"/api/v1/auth/
|
|
209
|
+
"/api/v1/config",
|
|
210
|
+
"/api/v1/auth/callback",
|
|
211
|
+
"/api/v1/auth/login",
|
|
212
|
+
"/api/v1/auth/refresh",
|
|
213
|
+
"/api/v1/csrf-token",
|
|
214
|
+
"/health",
|
|
191
215
|
]
|
|
192
216
|
|
|
193
217
|
if any(request.url.path.startswith(path) for path in skip_paths):
|
|
194
218
|
await self.app(scope, receive, send)
|
|
195
219
|
return
|
|
196
220
|
|
|
197
|
-
use_auth = dependencies.api_config and dependencies.api_config.get(
|
|
221
|
+
use_auth = dependencies.api_config and dependencies.api_config.get(
|
|
222
|
+
"frontend_use_authorization"
|
|
223
|
+
)
|
|
198
224
|
|
|
199
225
|
if use_auth:
|
|
200
226
|
await self._handle_authenticated_request(request, scope, receive, send)
|
|
201
227
|
else:
|
|
202
228
|
request.state.user = {
|
|
203
|
-
"id": "sam_dev_user",
|
|
204
|
-
"
|
|
229
|
+
"id": "sam_dev_user",
|
|
230
|
+
"name": "Sam Dev User",
|
|
231
|
+
"email": "sam@dev.local",
|
|
232
|
+
"authenticated": True,
|
|
233
|
+
"auth_method": "development",
|
|
205
234
|
}
|
|
206
|
-
log.debug(
|
|
235
|
+
log.debug(
|
|
236
|
+
"AuthMiddleware: Set development user state with id: sam_dev_user"
|
|
237
|
+
)
|
|
207
238
|
|
|
208
239
|
await self.app(scope, receive, send)
|
|
209
240
|
|
|
@@ -214,13 +245,18 @@ def _create_auth_middleware(component):
|
|
|
214
245
|
log.warning("AuthMiddleware: No access token found. Returning 401.")
|
|
215
246
|
response = JSONResponse(
|
|
216
247
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
217
|
-
content={
|
|
248
|
+
content={
|
|
249
|
+
"detail": "Not authenticated",
|
|
250
|
+
"error_type": "authentication_required",
|
|
251
|
+
},
|
|
218
252
|
)
|
|
219
253
|
await response(scope, receive, send)
|
|
220
254
|
return
|
|
221
255
|
|
|
222
256
|
try:
|
|
223
|
-
auth_service_url = dependencies.api_config.get(
|
|
257
|
+
auth_service_url = dependencies.api_config.get(
|
|
258
|
+
"external_auth_service_url"
|
|
259
|
+
)
|
|
224
260
|
auth_provider = dependencies.api_config.get("external_auth_provider")
|
|
225
261
|
|
|
226
262
|
if not auth_service_url:
|
|
@@ -232,47 +268,85 @@ def _create_auth_middleware(component):
|
|
|
232
268
|
await response(scope, receive, send)
|
|
233
269
|
return
|
|
234
270
|
|
|
235
|
-
if not await _validate_token(
|
|
271
|
+
if not await _validate_token(
|
|
272
|
+
auth_service_url, auth_provider, access_token
|
|
273
|
+
):
|
|
236
274
|
log.warning("AuthMiddleware: Token validation failed")
|
|
237
275
|
response = JSONResponse(
|
|
238
276
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
239
|
-
content={
|
|
277
|
+
content={
|
|
278
|
+
"detail": "Invalid token",
|
|
279
|
+
"error_type": "invalid_token",
|
|
280
|
+
},
|
|
240
281
|
)
|
|
241
282
|
await response(scope, receive, send)
|
|
242
283
|
return
|
|
243
284
|
|
|
244
|
-
user_info = await _get_user_info(
|
|
285
|
+
user_info = await _get_user_info(
|
|
286
|
+
auth_service_url, auth_provider, access_token
|
|
287
|
+
)
|
|
245
288
|
if not user_info:
|
|
246
|
-
log.warning(
|
|
289
|
+
log.warning(
|
|
290
|
+
"AuthMiddleware: Failed to get user info from external auth service"
|
|
291
|
+
)
|
|
247
292
|
response = JSONResponse(
|
|
248
293
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
249
|
-
content={
|
|
294
|
+
content={
|
|
295
|
+
"detail": "Could not retrieve user info from auth provider",
|
|
296
|
+
"error_type": "user_info_failed",
|
|
297
|
+
},
|
|
250
298
|
)
|
|
251
299
|
await response(scope, receive, send)
|
|
252
300
|
return
|
|
253
301
|
|
|
254
302
|
user_identifier = _extract_user_identifier(user_info)
|
|
255
|
-
if not user_identifier or user_identifier.lower() in [
|
|
256
|
-
|
|
303
|
+
if not user_identifier or user_identifier.lower() in [
|
|
304
|
+
"null",
|
|
305
|
+
"none",
|
|
306
|
+
"",
|
|
307
|
+
]:
|
|
308
|
+
log.error(
|
|
309
|
+
"AuthMiddleware: No valid user identifier from OAuth provider"
|
|
310
|
+
)
|
|
257
311
|
response = JSONResponse(
|
|
258
312
|
status_code=status.HTTP_401_UNAUTHORIZED,
|
|
259
|
-
content={
|
|
313
|
+
content={
|
|
314
|
+
"detail": "OAuth provider returned no valid user identifier",
|
|
315
|
+
"error_type": "invalid_user_identifier_from_provider",
|
|
316
|
+
},
|
|
260
317
|
)
|
|
261
318
|
await response(scope, receive, send)
|
|
262
319
|
return
|
|
263
320
|
|
|
264
|
-
email_from_auth, display_name = _extract_user_details(
|
|
321
|
+
email_from_auth, display_name = _extract_user_details(
|
|
322
|
+
user_info, user_identifier
|
|
323
|
+
)
|
|
265
324
|
|
|
266
325
|
identity_service = self.component.identity_service
|
|
267
326
|
if not identity_service:
|
|
268
|
-
request.state.user =
|
|
327
|
+
request.state.user = (
|
|
328
|
+
await _create_user_state_without_identity_service(
|
|
329
|
+
user_identifier, email_from_auth, display_name
|
|
330
|
+
)
|
|
331
|
+
)
|
|
269
332
|
else:
|
|
270
|
-
user_state = await _create_user_state_with_identity_service(
|
|
333
|
+
user_state = await _create_user_state_with_identity_service(
|
|
334
|
+
identity_service,
|
|
335
|
+
user_identifier,
|
|
336
|
+
email_from_auth,
|
|
337
|
+
display_name,
|
|
338
|
+
user_info,
|
|
339
|
+
)
|
|
271
340
|
if not user_state:
|
|
272
|
-
log.error(
|
|
341
|
+
log.error(
|
|
342
|
+
"AuthMiddleware: User authenticated but not found in internal IdentityService"
|
|
343
|
+
)
|
|
273
344
|
response = JSONResponse(
|
|
274
345
|
status_code=status.HTTP_403_FORBIDDEN,
|
|
275
|
-
content={
|
|
346
|
+
content={
|
|
347
|
+
"detail": "User not authorized for this application",
|
|
348
|
+
"error_type": "not_authorized",
|
|
349
|
+
},
|
|
276
350
|
)
|
|
277
351
|
await response(scope, receive, send)
|
|
278
352
|
return
|
|
@@ -287,10 +361,14 @@ def _create_auth_middleware(component):
|
|
|
287
361
|
await response(scope, receive, send)
|
|
288
362
|
return
|
|
289
363
|
except Exception as exc:
|
|
290
|
-
log.error(
|
|
364
|
+
log.error(
|
|
365
|
+
"An unexpected error occurred during token validation: %s", exc
|
|
366
|
+
)
|
|
291
367
|
response = JSONResponse(
|
|
292
368
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
|
293
|
-
content={
|
|
369
|
+
content={
|
|
370
|
+
"detail": "An internal error occurred during authentication"
|
|
371
|
+
},
|
|
294
372
|
)
|
|
295
373
|
await response(scope, receive, send)
|
|
296
374
|
return
|
|
@@ -343,10 +421,14 @@ def _run_community_migrations(database_url: str) -> None:
|
|
|
343
421
|
except Exception as migration_error:
|
|
344
422
|
log.error("Community migration failed: %s", migration_error)
|
|
345
423
|
log.error("Check database connectivity and permissions")
|
|
346
|
-
raise RuntimeError(
|
|
424
|
+
raise RuntimeError(
|
|
425
|
+
f"Community database migration failed: {migration_error}"
|
|
426
|
+
) from migration_error
|
|
347
427
|
|
|
348
428
|
|
|
349
|
-
def _run_enterprise_migrations(
|
|
429
|
+
def _run_enterprise_migrations(
|
|
430
|
+
component: "WebUIBackendComponent", database_url: str
|
|
431
|
+
) -> None:
|
|
350
432
|
"""
|
|
351
433
|
Run migrations for enterprise features like advanced analytics, audit logs, etc.
|
|
352
434
|
This is optional and only runs if the enterprise package is available.
|
|
@@ -420,7 +502,15 @@ def setup_dependencies(component: "WebUIBackendComponent", database_url: str = N
|
|
|
420
502
|
backward compatibility with existing API contracts.
|
|
421
503
|
|
|
422
504
|
If database_url is None, runs in compatibility mode with in-memory sessions.
|
|
505
|
+
|
|
506
|
+
This function is idempotent and safe to call multiple times.
|
|
423
507
|
"""
|
|
508
|
+
global _dependencies_initialized
|
|
509
|
+
|
|
510
|
+
if _dependencies_initialized:
|
|
511
|
+
log.debug("[setup_dependencies] Dependencies already initialized, skipping")
|
|
512
|
+
return
|
|
513
|
+
|
|
424
514
|
dependencies.set_component_instance(component)
|
|
425
515
|
|
|
426
516
|
if database_url:
|
|
@@ -441,6 +531,9 @@ def setup_dependencies(component: "WebUIBackendComponent", database_url: str = N
|
|
|
441
531
|
_setup_routers()
|
|
442
532
|
_setup_static_files()
|
|
443
533
|
|
|
534
|
+
_dependencies_initialized = True
|
|
535
|
+
log.info("[setup_dependencies] Dependencies initialization complete")
|
|
536
|
+
|
|
444
537
|
|
|
445
538
|
def _setup_middleware(component: "WebUIBackendComponent") -> None:
|
|
446
539
|
allowed_origins = component.get_cors_origins()
|
|
@@ -467,39 +560,50 @@ def _setup_routers() -> None:
|
|
|
467
560
|
|
|
468
561
|
app.include_router(session_router, prefix=api_prefix, tags=["Sessions"])
|
|
469
562
|
app.include_router(user_router, prefix=f"{api_prefix}/users", tags=["Users"])
|
|
470
|
-
app.include_router(task_router, prefix=f"{api_prefix}/tasks", tags=["Tasks"])
|
|
471
563
|
app.include_router(config.router, prefix=api_prefix, tags=["Config"])
|
|
472
564
|
app.include_router(agent_cards.router, prefix=api_prefix, tags=["Agent Cards"])
|
|
473
|
-
app.include_router(tasks.router, prefix=api_prefix, tags=["
|
|
565
|
+
app.include_router(tasks.router, prefix=api_prefix, tags=["Tasks"])
|
|
474
566
|
app.include_router(sse.router, prefix=f"{api_prefix}/sse", tags=["SSE"])
|
|
475
|
-
app.include_router(
|
|
476
|
-
|
|
567
|
+
app.include_router(
|
|
568
|
+
artifacts.router, prefix=f"{api_prefix}/artifacts", tags=["Artifacts"]
|
|
569
|
+
)
|
|
570
|
+
app.include_router(
|
|
571
|
+
visualization.router,
|
|
572
|
+
prefix=f"{api_prefix}/visualization",
|
|
573
|
+
tags=["Visualization"],
|
|
574
|
+
)
|
|
477
575
|
app.include_router(people.router, prefix=api_prefix, tags=["People"])
|
|
478
576
|
app.include_router(auth.router, prefix=api_prefix, tags=["Auth"])
|
|
577
|
+
app.include_router(feedback.router, prefix=api_prefix, tags=["Feedback"])
|
|
479
578
|
log.info("Legacy routers mounted for endpoints not yet migrated")
|
|
480
579
|
|
|
481
580
|
# Register shared exception handlers from community repo
|
|
482
581
|
from .shared.exception_handlers import register_exception_handlers
|
|
582
|
+
|
|
483
583
|
register_exception_handlers(app)
|
|
484
584
|
log.info("Registered shared exception handlers from community repo")
|
|
485
585
|
|
|
486
586
|
# Mount enterprise routers if available
|
|
487
587
|
try:
|
|
488
|
-
from solace_agent_mesh_enterprise.webui_backend.routers import
|
|
588
|
+
from solace_agent_mesh_enterprise.webui_backend.routers import (
|
|
589
|
+
get_enterprise_routers,
|
|
590
|
+
)
|
|
489
591
|
|
|
490
592
|
enterprise_routers = get_enterprise_routers()
|
|
491
593
|
for router_config in enterprise_routers:
|
|
492
594
|
app.include_router(
|
|
493
595
|
router_config["router"],
|
|
494
596
|
prefix=router_config["prefix"],
|
|
495
|
-
tags=router_config["tags"]
|
|
597
|
+
tags=router_config["tags"],
|
|
496
598
|
)
|
|
497
599
|
log.info("Mounted %d enterprise routers", len(enterprise_routers))
|
|
498
600
|
|
|
499
601
|
except ImportError:
|
|
500
602
|
log.debug("No enterprise package detected - skipping enterprise routers")
|
|
501
603
|
except ModuleNotFoundError:
|
|
502
|
-
log.debug(
|
|
604
|
+
log.debug(
|
|
605
|
+
"Enterprise module not found - skipping enterprise routers and exception handlers"
|
|
606
|
+
)
|
|
503
607
|
except Exception as e:
|
|
504
608
|
log.warning("Failed to load enterprise routers and exception handlers: %s", e)
|
|
505
609
|
|
|
@@ -535,7 +639,7 @@ async def http_exception_handler(request: FastAPIRequest, exc: HTTPException):
|
|
|
535
639
|
Returns JSON-RPC format for tasks/SSE endpoints, REST format for others.
|
|
536
640
|
"""
|
|
537
641
|
log.warning(
|
|
538
|
-
"HTTP Exception: Status=%s, Detail=%s, Request: %s %s",
|
|
642
|
+
"HTTP Exception Handler triggered: Status=%s, Detail=%s, Request: %s %s",
|
|
539
643
|
exc.status_code,
|
|
540
644
|
exc.detail,
|
|
541
645
|
request.method,
|
|
@@ -594,7 +698,7 @@ async def validation_exception_handler(
|
|
|
594
698
|
Handles Pydantic validation errors with format detection.
|
|
595
699
|
"""
|
|
596
700
|
log.warning(
|
|
597
|
-
"
|
|
701
|
+
"Validation Exception Handler triggered: %s, Request: %s %s",
|
|
598
702
|
exc.errors(),
|
|
599
703
|
request.method,
|
|
600
704
|
request.url,
|
|
@@ -603,7 +707,7 @@ async def validation_exception_handler(
|
|
|
603
707
|
message="Invalid request parameters", data=exc.errors(), request_id=None
|
|
604
708
|
)
|
|
605
709
|
return JSONResponse(
|
|
606
|
-
status_code=status.
|
|
710
|
+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,
|
|
607
711
|
content=response.model_dump(exclude_none=True),
|
|
608
712
|
)
|
|
609
713
|
|
|
@@ -614,7 +718,10 @@ async def generic_exception_handler(request: FastAPIRequest, exc: Exception):
|
|
|
614
718
|
Handles any other unexpected exceptions with format detection.
|
|
615
719
|
"""
|
|
616
720
|
log.exception(
|
|
617
|
-
"
|
|
721
|
+
"Generic Exception Handler triggered: %s, Request: %s %s",
|
|
722
|
+
exc,
|
|
723
|
+
request.method,
|
|
724
|
+
request.url,
|
|
618
725
|
)
|
|
619
726
|
error_obj = a2a.create_internal_error(
|
|
620
727
|
message="An unexpected server error occurred: %s" % type(exc).__name__
|
|
@@ -3,35 +3,26 @@ Repository layer containing all data access logic organized by entity type.
|
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
5
|
# Interfaces
|
|
6
|
-
from .interfaces import
|
|
6
|
+
from .interfaces import ISessionRepository
|
|
7
7
|
|
|
8
8
|
# Implementations
|
|
9
|
-
from .message_repository import MessageRepository
|
|
10
9
|
from .session_repository import SessionRepository
|
|
11
10
|
|
|
12
11
|
# Entities (re-exported for convenience)
|
|
13
12
|
from .entities.session import Session
|
|
14
|
-
from .entities.message import Message
|
|
15
|
-
from .entities.session_history import SessionHistory
|
|
16
13
|
|
|
17
14
|
# Models (re-exported for convenience)
|
|
18
15
|
from .models.base import Base
|
|
19
16
|
from .models.session_model import SessionModel
|
|
20
|
-
from .models.message_model import MessageModel
|
|
21
17
|
|
|
22
18
|
__all__ = [
|
|
23
19
|
# Interfaces
|
|
24
|
-
"IMessageRepository",
|
|
25
20
|
"ISessionRepository",
|
|
26
21
|
# Implementations
|
|
27
|
-
"MessageRepository",
|
|
28
22
|
"SessionRepository",
|
|
29
23
|
# Entities
|
|
30
|
-
"
|
|
31
|
-
"Session",
|
|
32
|
-
"SessionHistory",
|
|
24
|
+
"Session",
|
|
33
25
|
# Models
|
|
34
26
|
"Base",
|
|
35
|
-
"MessageModel",
|
|
36
27
|
"SessionModel",
|
|
37
|
-
]
|
|
28
|
+
]
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ChatTask repository implementation using SQLAlchemy.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import List, Optional
|
|
6
|
+
|
|
7
|
+
from sqlalchemy.orm import Session as DBSession
|
|
8
|
+
|
|
9
|
+
from ..shared import now_epoch_ms
|
|
10
|
+
from ..shared.types import SessionId, UserId
|
|
11
|
+
from .entities import ChatTask
|
|
12
|
+
from .interfaces import IChatTaskRepository
|
|
13
|
+
from .models import ChatTaskModel
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class ChatTaskRepository(IChatTaskRepository):
|
|
17
|
+
"""SQLAlchemy implementation of chat task repository."""
|
|
18
|
+
|
|
19
|
+
def __init__(self, db: DBSession):
|
|
20
|
+
self.db = db
|
|
21
|
+
|
|
22
|
+
def save(self, task: ChatTask) -> ChatTask:
|
|
23
|
+
"""Save or update a chat task (upsert)."""
|
|
24
|
+
existing = self.db.query(ChatTaskModel).filter(
|
|
25
|
+
ChatTaskModel.id == task.id
|
|
26
|
+
).first()
|
|
27
|
+
|
|
28
|
+
if existing:
|
|
29
|
+
# Update existing task - store strings directly
|
|
30
|
+
existing.user_message = task.user_message
|
|
31
|
+
existing.message_bubbles = task.message_bubbles # Already a string
|
|
32
|
+
existing.task_metadata = task.task_metadata # Already a string
|
|
33
|
+
existing.updated_time = now_epoch_ms()
|
|
34
|
+
else:
|
|
35
|
+
# Create new task - store strings directly
|
|
36
|
+
model = ChatTaskModel(
|
|
37
|
+
id=task.id,
|
|
38
|
+
session_id=task.session_id,
|
|
39
|
+
user_id=task.user_id,
|
|
40
|
+
user_message=task.user_message,
|
|
41
|
+
message_bubbles=task.message_bubbles, # Already a string
|
|
42
|
+
task_metadata=task.task_metadata, # Already a string
|
|
43
|
+
created_time=task.created_time,
|
|
44
|
+
updated_time=task.updated_time
|
|
45
|
+
)
|
|
46
|
+
self.db.add(model)
|
|
47
|
+
|
|
48
|
+
self.db.commit()
|
|
49
|
+
|
|
50
|
+
# Reload to get updated values
|
|
51
|
+
model = self.db.query(ChatTaskModel).filter(
|
|
52
|
+
ChatTaskModel.id == task.id
|
|
53
|
+
).first()
|
|
54
|
+
|
|
55
|
+
return self._model_to_entity(model)
|
|
56
|
+
|
|
57
|
+
def find_by_session(
|
|
58
|
+
self,
|
|
59
|
+
session_id: SessionId,
|
|
60
|
+
user_id: UserId
|
|
61
|
+
) -> List[ChatTask]:
|
|
62
|
+
"""Find all tasks for a session."""
|
|
63
|
+
models = self.db.query(ChatTaskModel).filter(
|
|
64
|
+
ChatTaskModel.session_id == session_id,
|
|
65
|
+
ChatTaskModel.user_id == user_id
|
|
66
|
+
).order_by(ChatTaskModel.created_time.asc()).all()
|
|
67
|
+
|
|
68
|
+
return [self._model_to_entity(m) for m in models]
|
|
69
|
+
|
|
70
|
+
def find_by_id(
|
|
71
|
+
self,
|
|
72
|
+
task_id: str,
|
|
73
|
+
user_id: UserId
|
|
74
|
+
) -> Optional[ChatTask]:
|
|
75
|
+
"""Find a specific task."""
|
|
76
|
+
model = self.db.query(ChatTaskModel).filter(
|
|
77
|
+
ChatTaskModel.id == task_id,
|
|
78
|
+
ChatTaskModel.user_id == user_id
|
|
79
|
+
).first()
|
|
80
|
+
|
|
81
|
+
return self._model_to_entity(model) if model else None
|
|
82
|
+
|
|
83
|
+
def delete_by_session(self, session_id: SessionId) -> bool:
|
|
84
|
+
"""Delete all tasks for a session."""
|
|
85
|
+
result = self.db.query(ChatTaskModel).filter(
|
|
86
|
+
ChatTaskModel.session_id == session_id
|
|
87
|
+
).delete()
|
|
88
|
+
self.db.commit()
|
|
89
|
+
return result > 0
|
|
90
|
+
|
|
91
|
+
def _model_to_entity(self, model: ChatTaskModel) -> ChatTask:
|
|
92
|
+
"""Convert SQLAlchemy model to domain entity."""
|
|
93
|
+
# No deserialization - just pass strings through
|
|
94
|
+
return ChatTask(
|
|
95
|
+
id=model.id,
|
|
96
|
+
session_id=model.session_id,
|
|
97
|
+
user_id=model.user_id,
|
|
98
|
+
user_message=model.user_message,
|
|
99
|
+
message_bubbles=model.message_bubbles, # String (opaque)
|
|
100
|
+
task_metadata=model.task_metadata, # String (opaque)
|
|
101
|
+
created_time=model.created_time,
|
|
102
|
+
updated_time=model.updated_time
|
|
103
|
+
)
|
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
Domain entities for the repository layer.
|
|
3
3
|
"""
|
|
4
4
|
|
|
5
|
-
from .
|
|
5
|
+
from .chat_task import ChatTask
|
|
6
|
+
from .feedback import Feedback
|
|
6
7
|
from .session import Session
|
|
7
|
-
from .
|
|
8
|
+
from .task import Task
|
|
9
|
+
from .task_event import TaskEvent
|
|
8
10
|
|
|
9
|
-
__all__ = ["
|
|
11
|
+
__all__ = ["ChatTask", "Feedback", "Session", "Task", "TaskEvent"]
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"""
|
|
2
|
+
ChatTask domain entity.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
import json
|
|
6
|
+
from typing import Any, Dict, Optional
|
|
7
|
+
|
|
8
|
+
from pydantic import BaseModel, ConfigDict, field_validator
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class ChatTask(BaseModel):
|
|
12
|
+
"""ChatTask domain entity with business logic."""
|
|
13
|
+
|
|
14
|
+
model_config = ConfigDict(from_attributes=True)
|
|
15
|
+
|
|
16
|
+
id: str
|
|
17
|
+
session_id: str
|
|
18
|
+
user_id: str
|
|
19
|
+
user_message: Optional[str] = None
|
|
20
|
+
message_bubbles: str # JSON string (opaque to backend)
|
|
21
|
+
task_metadata: Optional[str] = None # JSON string (opaque to backend)
|
|
22
|
+
created_time: int
|
|
23
|
+
updated_time: Optional[int] = None
|
|
24
|
+
|
|
25
|
+
@field_validator("message_bubbles")
|
|
26
|
+
@classmethod
|
|
27
|
+
def validate_message_bubbles(cls, v: str) -> str:
|
|
28
|
+
"""Validate that message_bubbles is a non-empty JSON string."""
|
|
29
|
+
if not v or not v.strip():
|
|
30
|
+
raise ValueError("message_bubbles cannot be empty")
|
|
31
|
+
|
|
32
|
+
# Validate it's valid JSON (but don't validate structure)
|
|
33
|
+
try:
|
|
34
|
+
parsed = json.loads(v)
|
|
35
|
+
if not isinstance(parsed, list) or len(parsed) == 0:
|
|
36
|
+
raise ValueError("message_bubbles must be a non-empty JSON array")
|
|
37
|
+
except json.JSONDecodeError as e:
|
|
38
|
+
raise ValueError(f"message_bubbles must be valid JSON: {e}")
|
|
39
|
+
|
|
40
|
+
return v
|
|
41
|
+
|
|
42
|
+
@field_validator("task_metadata")
|
|
43
|
+
@classmethod
|
|
44
|
+
def validate_task_metadata(cls, v: Optional[str]) -> Optional[str]:
|
|
45
|
+
"""Validate that task_metadata is valid JSON if provided."""
|
|
46
|
+
if v is None or not v.strip():
|
|
47
|
+
return None
|
|
48
|
+
|
|
49
|
+
# Validate it's valid JSON (but don't validate structure)
|
|
50
|
+
try:
|
|
51
|
+
json.loads(v)
|
|
52
|
+
except json.JSONDecodeError as e:
|
|
53
|
+
raise ValueError(f"task_metadata must be valid JSON: {e}")
|
|
54
|
+
|
|
55
|
+
return v
|
|
56
|
+
|
|
57
|
+
def add_feedback(self, feedback_type: str, feedback_text: Optional[str] = None) -> None:
|
|
58
|
+
"""Add or update feedback for this task."""
|
|
59
|
+
# Parse metadata, update, re-serialize
|
|
60
|
+
metadata = json.loads(self.task_metadata) if self.task_metadata else {}
|
|
61
|
+
|
|
62
|
+
metadata["feedback"] = {
|
|
63
|
+
"type": feedback_type,
|
|
64
|
+
"text": feedback_text,
|
|
65
|
+
"submitted": True
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
self.task_metadata = json.dumps(metadata)
|
|
69
|
+
|
|
70
|
+
def get_feedback(self) -> Optional[Dict[str, Any]]:
|
|
71
|
+
"""Get feedback for this task."""
|
|
72
|
+
if self.task_metadata:
|
|
73
|
+
metadata = json.loads(self.task_metadata)
|
|
74
|
+
return metadata.get("feedback")
|
|
75
|
+
return None
|