solace-agent-mesh 1.7.1__py3-none-any.whl → 1.13.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of solace-agent-mesh might be problematic. Click here for more details.
- solace_agent_mesh/agent/adk/alembic/README +74 -0
- solace_agent_mesh/agent/adk/alembic/env.py +77 -0
- solace_agent_mesh/agent/adk/alembic/script.py.mako +28 -0
- solace_agent_mesh/agent/adk/alembic/versions/e2902798564d_adk_session_db_upgrade.py +52 -0
- solace_agent_mesh/agent/adk/alembic.ini +112 -0
- solace_agent_mesh/agent/adk/artifacts/filesystem_artifact_service.py +164 -0
- solace_agent_mesh/agent/adk/artifacts/s3_artifact_service.py +163 -0
- solace_agent_mesh/agent/adk/callbacks.py +752 -127
- solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +99 -7
- solace_agent_mesh/agent/adk/intelligent_mcp_callbacks.py +52 -5
- solace_agent_mesh/agent/adk/mcp_content_processor.py +1 -1
- solace_agent_mesh/agent/adk/models/lite_llm.py +34 -16
- solace_agent_mesh/agent/adk/models/oauth2_token_manager.py +24 -137
- solace_agent_mesh/agent/adk/runner.py +66 -8
- solace_agent_mesh/agent/adk/schema_migration.py +88 -0
- solace_agent_mesh/agent/adk/services.py +41 -1
- solace_agent_mesh/agent/adk/setup.py +220 -32
- solace_agent_mesh/agent/adk/stream_parser.py +229 -40
- solace_agent_mesh/agent/protocol/event_handlers.py +219 -33
- solace_agent_mesh/agent/proxies/a2a/component.py +572 -75
- solace_agent_mesh/agent/proxies/a2a/config.py +80 -4
- solace_agent_mesh/agent/proxies/base/component.py +188 -22
- solace_agent_mesh/agent/proxies/base/proxy_task_context.py +3 -1
- solace_agent_mesh/agent/sac/app.py +37 -12
- solace_agent_mesh/agent/sac/component.py +322 -52
- solace_agent_mesh/agent/sac/patch_adk.py +8 -16
- solace_agent_mesh/agent/sac/task_execution_context.py +90 -0
- solace_agent_mesh/agent/tools/__init__.py +3 -0
- solace_agent_mesh/agent/tools/audio_tools.py +3 -3
- solace_agent_mesh/agent/tools/builtin_artifact_tools.py +698 -24
- solace_agent_mesh/agent/tools/deep_research_tools.py +2161 -0
- solace_agent_mesh/agent/tools/peer_agent_tool.py +82 -15
- solace_agent_mesh/agent/tools/time_tools.py +126 -0
- solace_agent_mesh/agent/tools/tool_config_types.py +54 -2
- solace_agent_mesh/agent/tools/web_search_tools.py +279 -0
- solace_agent_mesh/agent/tools/web_tools.py +125 -17
- solace_agent_mesh/agent/utils/artifact_helpers.py +243 -5
- solace_agent_mesh/agent/utils/context_helpers.py +17 -0
- solace_agent_mesh/assets/docs/404.html +6 -6
- solace_agent_mesh/assets/docs/assets/css/{styles.906a1503.css → styles.8162edfb.css} +1 -1
- solace_agent_mesh/assets/docs/assets/js/05749d90.19ac4f35.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/15ba94aa.e186750d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/15e40e79.434bb30f.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/17896441.e612dfb4.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2279.550aa580.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/{17896441.a5e82f9b.js.LICENSE.txt → 2279.550aa580.js.LICENSE.txt} +6 -0
- solace_agent_mesh/assets/docs/assets/js/240a0364.83e37aa8.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2e32b5e0.2f0db237.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3a6c6137.7e61915d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3ac1795d.7f7ab1c1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3ff0015d.e53c9b78.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/41adc471.0e95b87c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/4667dc50.bf2ad456.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/49eed117.493d6f99.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{509e993c.4c7a1a6d.js → 509e993c.a1fbf45a.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/547e15cc.8e6da617.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/55b7b518.29d6e75d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5b8d9c11.d4eb37b8.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5c2bd65f.1ee87753.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/60702c0e.a8bdd79b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/64195356.09dbd087.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/66d4869e.30340bd3.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6aaedf65.7253541d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6d84eae0.fd23ba4a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/729898df.7249e9fd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/7e294c01.7c5f6906.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8024126c.e3467286.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/81a99df0.7ed65d45.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/82fbfb93.161823a5.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/924ffdeb.975e428a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/94e8668d.16083b3f.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9bb13469.4523ae20.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/a7d42657.a956689d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/a94703ab.3e5fbcb3.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ab9708a8.3e563275.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/c93cbaa0.0e0d8baf.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/cab03b5b.6a073091.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/cbe2e9ea.07e170dd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e04b235d.06d23db6.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e1b6eeb4.deb2b62e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e3d9abda.1476f570.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e6f9706b.acc800d3.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e92d0134.c147a429.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ee0c2fe7.94d0a351.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/f284c35a.cc97854c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/main.d634009f.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/runtime~main.27bb82a7.js +1 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +68 -68
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +50 -50
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +42 -42
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +55 -55
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +75 -75
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/image-tools/index.html +81 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +67 -50
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/research-tools/index.html +136 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +178 -144
- solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +43 -42
- solace_agent_mesh/assets/docs/docs/documentation/components/index.html +20 -18
- solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +23 -23
- solace_agent_mesh/assets/docs/docs/documentation/components/platform-service/index.html +33 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +45 -45
- solace_agent_mesh/assets/docs/docs/documentation/components/projects/index.html +98 -112
- solace_agent_mesh/assets/docs/docs/documentation/components/prompts/index.html +147 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +208 -125
- solace_agent_mesh/assets/docs/docs/documentation/components/speech/index.html +52 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +28 -28
- solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +29 -29
- solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +14 -14
- solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/index.html +47 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/kubernetes-deployment-guide/index.html +197 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/logging/index.html +67 -53
- solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +17 -17
- solace_agent_mesh/assets/docs/docs/documentation/deploying/proxy_configuration/index.html +49 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +38 -38
- solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +87 -87
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +67 -49
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +17 -17
- solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +51 -51
- solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +22 -22
- solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +27 -27
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +135 -135
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +66 -66
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +51 -51
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +50 -38
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +86 -86
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +51 -51
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +24 -24
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +30 -30
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +44 -44
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/teams-integration/index.html +115 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/agent-builder/index.html +50 -23
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/connectors/index.html +29 -24
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +21 -21
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +40 -37
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/openapi-tools/index.html +324 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +96 -66
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/secure-user-delegated-access/index.html +181 -181
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +75 -75
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/wheel-installation/index.html +27 -27
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +44 -44
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +39 -38
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +30 -30
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +18 -18
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/vibe_coding/index.html +62 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/artifact-storage/index.html +135 -114
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +37 -37
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +14 -14
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +27 -25
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +69 -69
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +72 -72
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/session-storage/index.html +112 -112
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/user-feedback/index.html +28 -28
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +42 -42
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +20 -20
- solace_agent_mesh/assets/docs/docs/documentation/migrations/platform-service-split/index.html +85 -0
- solace_agent_mesh/assets/docs/lunr-index-1768329217460.json +1 -0
- solace_agent_mesh/assets/docs/lunr-index.json +1 -1
- solace_agent_mesh/assets/docs/search-doc-1768329217460.json +1 -0
- solace_agent_mesh/assets/docs/search-doc.json +1 -1
- solace_agent_mesh/assets/docs/sitemap.xml +1 -1
- solace_agent_mesh/cli/__init__.py +1 -1
- solace_agent_mesh/cli/commands/add_cmd/__init__.py +3 -1
- solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +6 -1
- solace_agent_mesh/cli/commands/add_cmd/proxy_cmd.py +100 -0
- solace_agent_mesh/cli/commands/eval_cmd.py +1 -1
- solace_agent_mesh/cli/commands/init_cmd/__init__.py +15 -0
- solace_agent_mesh/cli/commands/init_cmd/directory_step.py +1 -1
- solace_agent_mesh/cli/commands/init_cmd/env_step.py +30 -3
- solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +3 -4
- solace_agent_mesh/cli/commands/init_cmd/platform_service_step.py +85 -0
- solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +16 -3
- solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +2 -1
- solace_agent_mesh/cli/commands/plugin_cmd/catalog_cmd.py +1 -0
- solace_agent_mesh/cli/commands/plugin_cmd/create_cmd.py +3 -3
- solace_agent_mesh/cli/commands/run_cmd.py +64 -49
- solace_agent_mesh/cli/commands/tools_cmd.py +315 -0
- solace_agent_mesh/cli/main.py +15 -0
- solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-tcIFZLis.js → authCallback-KnKMP_vb.js} +1 -1
- solace_agent_mesh/client/webui/frontend/static/assets/client-DpBL2stg.js +25 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-Cd498TV2.js +435 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-rSf8Vu29.css +1 -0
- solace_agent_mesh/client/webui/frontend/static/assets/{vendor-CINwxvwV.js → vendor-CGk8Suyh.js} +189 -94
- solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
- solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
- solace_agent_mesh/client/webui/frontend/static/mockServiceWorker.js +336 -0
- solace_agent_mesh/client/webui/frontend/static/ui-version.json +6 -0
- solace_agent_mesh/common/a2a/types.py +1 -1
- solace_agent_mesh/common/agent_registry.py +38 -11
- solace_agent_mesh/common/data_parts.py +124 -0
- solace_agent_mesh/common/error_handlers.py +83 -0
- solace_agent_mesh/common/exceptions.py +24 -0
- solace_agent_mesh/common/oauth/__init__.py +17 -0
- solace_agent_mesh/common/oauth/oauth_client.py +408 -0
- solace_agent_mesh/common/oauth/utils.py +50 -0
- solace_agent_mesh/common/rag_dto.py +156 -0
- solace_agent_mesh/common/sac/sam_component_base.py +73 -1
- solace_agent_mesh/common/sam_events/event_service.py +2 -2
- solace_agent_mesh/common/utils/embeds/converter.py +1 -8
- solace_agent_mesh/common/utils/embeds/modifiers.py +2 -27
- solace_agent_mesh/common/utils/embeds/resolver.py +94 -25
- solace_agent_mesh/common/utils/embeds/types.py +1 -0
- solace_agent_mesh/common/utils/log_formatters.py +20 -0
- solace_agent_mesh/common/utils/mime_helpers.py +12 -5
- solace_agent_mesh/common/utils/rbac_utils.py +69 -0
- solace_agent_mesh/common/utils/templates/__init__.py +8 -0
- solace_agent_mesh/common/utils/templates/liquid_renderer.py +210 -0
- solace_agent_mesh/common/utils/templates/template_resolver.py +161 -0
- solace_agent_mesh/config_portal/backend/common.py +12 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-CljP4_mv.js +103 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/{components-Rk0n-9cK.js → components-CaC6hG8d.js} +22 -22
- solace_agent_mesh/config_portal/frontend/static/client/assets/{entry.client-mvZjNKiz.js → entry.client-H_TM0YBt.js} +3 -3
- solace_agent_mesh/config_portal/frontend/static/client/assets/{index-DzNKzXrc.js → index-CnFykb2v.js} +16 -16
- solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-f8439d40.js +1 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-BIMqslJB.css +1 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-mJmTIdIk.js +10 -0
- solace_agent_mesh/config_portal/frontend/static/client/index.html +3 -3
- solace_agent_mesh/core_a2a/service.py +3 -2
- solace_agent_mesh/gateway/adapter/base.py +28 -1
- solace_agent_mesh/gateway/adapter/types.py +9 -0
- solace_agent_mesh/gateway/base/app.py +10 -0
- solace_agent_mesh/gateway/base/auth_interface.py +103 -0
- solace_agent_mesh/gateway/base/component.py +451 -10
- solace_agent_mesh/gateway/generic/component.py +274 -30
- solace_agent_mesh/gateway/http_sse/alembic/env.py +0 -7
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_soft_delete_and_search.py +2 -43
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_default_agent_to_projects.py +2 -2
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251108_create_prompt_tables_with_sharing.py +154 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251115_add_parent_task_id.py +32 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251126_add_background_task_fields.py +47 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251202_add_versioned_fields_to_prompts.py +52 -0
- solace_agent_mesh/gateway/http_sse/alembic.ini +0 -36
- solace_agent_mesh/gateway/http_sse/app.py +23 -6
- solace_agent_mesh/gateway/http_sse/component.py +158 -73
- solace_agent_mesh/gateway/http_sse/dependencies.py +50 -57
- solace_agent_mesh/gateway/http_sse/main.py +58 -482
- solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +2 -2
- solace_agent_mesh/gateway/http_sse/repository/entities/project.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/entities/project_user.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/entities/session.py +3 -2
- solace_agent_mesh/gateway/http_sse/repository/entities/task.py +7 -0
- solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +2 -2
- solace_agent_mesh/gateway/http_sse/repository/interfaces.py +2 -2
- solace_agent_mesh/gateway/http_sse/repository/models/__init__.py +5 -0
- solace_agent_mesh/gateway/http_sse/repository/models/prompt_model.py +159 -0
- solace_agent_mesh/gateway/http_sse/repository/models/session_model.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/models/task_model.py +8 -1
- solace_agent_mesh/gateway/http_sse/repository/project_repository.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/project_user_repository.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/session_repository.py +12 -107
- solace_agent_mesh/gateway/http_sse/repository/task_repository.py +86 -2
- solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +38 -7
- solace_agent_mesh/gateway/http_sse/routers/artifacts.py +113 -7
- solace_agent_mesh/gateway/http_sse/routers/auth.py +69 -132
- solace_agent_mesh/gateway/http_sse/routers/config.py +235 -10
- solace_agent_mesh/gateway/http_sse/routers/dto/project_dto.py +69 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/prompt_dto.py +255 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/session_requests.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/base_responses.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/project_responses.py +1 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +3 -2
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/version_responses.py +31 -0
- solace_agent_mesh/gateway/http_sse/routers/feedback.py +2 -2
- solace_agent_mesh/gateway/http_sse/routers/people.py +2 -2
- solace_agent_mesh/gateway/http_sse/routers/projects.py +250 -24
- solace_agent_mesh/gateway/http_sse/routers/prompts.py +1416 -0
- solace_agent_mesh/gateway/http_sse/routers/sessions.py +14 -5
- solace_agent_mesh/gateway/http_sse/routers/speech.py +355 -0
- solace_agent_mesh/gateway/http_sse/routers/sse.py +117 -4
- solace_agent_mesh/gateway/http_sse/routers/tasks.py +509 -149
- solace_agent_mesh/gateway/http_sse/routers/users.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/version.py +343 -0
- solace_agent_mesh/gateway/http_sse/routers/visualization.py +2 -1
- solace_agent_mesh/gateway/http_sse/services/audio_service.py +1227 -0
- solace_agent_mesh/gateway/http_sse/services/background_task_monitor.py +186 -0
- solace_agent_mesh/gateway/http_sse/services/data_retention_service.py +1 -1
- solace_agent_mesh/gateway/http_sse/services/feedback_service.py +1 -1
- solace_agent_mesh/gateway/http_sse/services/project_service.py +539 -12
- solace_agent_mesh/gateway/http_sse/services/prompt_builder_assistant.py +303 -0
- solace_agent_mesh/gateway/http_sse/services/session_service.py +198 -21
- solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +354 -4
- solace_agent_mesh/gateway/http_sse/sse_manager.py +280 -169
- solace_agent_mesh/gateway/http_sse/utils/artifact_copy_utils.py +370 -0
- solace_agent_mesh/gateway/http_sse/utils/stim_utils.py +41 -1
- solace_agent_mesh/services/__init__.py +0 -0
- solace_agent_mesh/services/platform/__init__.py +29 -0
- solace_agent_mesh/services/platform/alembic/env.py +85 -0
- solace_agent_mesh/services/platform/alembic/script.py.mako +28 -0
- solace_agent_mesh/services/platform/alembic.ini +109 -0
- solace_agent_mesh/services/platform/api/__init__.py +3 -0
- solace_agent_mesh/services/platform/api/dependencies.py +154 -0
- solace_agent_mesh/services/platform/api/main.py +314 -0
- solace_agent_mesh/services/platform/api/middleware.py +51 -0
- solace_agent_mesh/services/platform/api/routers/__init__.py +33 -0
- solace_agent_mesh/services/platform/api/routers/health_router.py +31 -0
- solace_agent_mesh/services/platform/app.py +215 -0
- solace_agent_mesh/services/platform/component.py +777 -0
- solace_agent_mesh/shared/__init__.py +14 -0
- solace_agent_mesh/shared/api/__init__.py +42 -0
- solace_agent_mesh/shared/auth/__init__.py +26 -0
- solace_agent_mesh/shared/auth/dependencies.py +204 -0
- solace_agent_mesh/shared/auth/middleware.py +347 -0
- solace_agent_mesh/shared/database/__init__.py +20 -0
- solace_agent_mesh/{gateway/http_sse/shared → shared/database}/base_repository.py +1 -1
- solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_exceptions.py +1 -1
- solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_helpers.py +1 -1
- solace_agent_mesh/shared/exceptions/__init__.py +36 -0
- solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exception_handlers.py +1 -1
- solace_agent_mesh/shared/utils/__init__.py +21 -0
- solace_agent_mesh/templates/logging_config_template.yaml +48 -0
- solace_agent_mesh/templates/main_orchestrator.yaml +12 -1
- solace_agent_mesh/templates/platform.yaml +49 -0
- solace_agent_mesh/templates/plugin_readme_template.md +3 -25
- solace_agent_mesh/templates/plugin_tool_config_template.yaml +109 -0
- solace_agent_mesh/templates/proxy_template.yaml +62 -0
- solace_agent_mesh/templates/webui.yaml +148 -6
- solace_agent_mesh/tools/web_search/__init__.py +18 -0
- solace_agent_mesh/tools/web_search/base.py +84 -0
- solace_agent_mesh/tools/web_search/google_search.py +247 -0
- solace_agent_mesh/tools/web_search/models.py +99 -0
- {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/METADATA +29 -8
- {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/RECORD +334 -313
- {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/WHEEL +1 -1
- solace_agent_mesh/agent/adk/adk_llm.txt +0 -226
- solace_agent_mesh/agent/adk/adk_llm_detail.txt +0 -566
- solace_agent_mesh/agent/adk/artifacts/artifacts_llm.txt +0 -171
- solace_agent_mesh/agent/adk/models/models_llm.txt +0 -189
- solace_agent_mesh/agent/agent_llm.txt +0 -369
- solace_agent_mesh/agent/agent_llm_detail.txt +0 -1702
- solace_agent_mesh/agent/protocol/protocol_llm.txt +0 -81
- solace_agent_mesh/agent/protocol/protocol_llm_detail.txt +0 -92
- solace_agent_mesh/agent/proxies/a2a/a2a_llm.txt +0 -190
- solace_agent_mesh/agent/proxies/base/base_llm.txt +0 -148
- solace_agent_mesh/agent/proxies/proxies_llm.txt +0 -283
- solace_agent_mesh/agent/sac/sac_llm.txt +0 -189
- solace_agent_mesh/agent/sac/sac_llm_detail.txt +0 -200
- solace_agent_mesh/agent/testing/testing_llm.txt +0 -58
- solace_agent_mesh/agent/testing/testing_llm_detail.txt +0 -68
- solace_agent_mesh/agent/tools/tools_llm.txt +0 -276
- solace_agent_mesh/agent/tools/tools_llm_detail.txt +0 -275
- solace_agent_mesh/agent/utils/utils_llm.txt +0 -152
- solace_agent_mesh/agent/utils/utils_llm_detail.txt +0 -149
- solace_agent_mesh/assets/docs/assets/js/05749d90.c70b2be9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/15ba94aa.92fea363.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/15e40e79.36003774.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/240a0364.c39f8388.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/2e32b5e0.33f5d75b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3a6c6137.f5940cfa.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3ac1795d.e4870a49.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3ff0015d.b63ee53a.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/547e15cc.2f7790c1.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/55b7b518.f2b1d1ba.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/5c2bd65f.45b32c2b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/64195356.c498c4d0.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/66d4869e.830d443f.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/6d84eae0.4a5fbf39.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/8024126c.fa0e7186.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/81a99df0.07034dd9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/82fbfb93.139a1a1f.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/924ffdeb.8095e148.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/94e8668d.09ed9234.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/9bb13469.dd1c9b54.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/a94703ab.0438dbc2.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/ab9708a8.245ae0ef.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/c93cbaa0.eaff365e.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/cbe2e9ea.f902fad8.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/db5d6442.3daf1696.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e04b235d.c9c50c7b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e3d9abda.d11c67a7.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e6f9706b.045d0fa1.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e92d0134.3bda61dd.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/f284c35a.5099c51e.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/main.f213fe0c.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/runtime~main.d9606d6a.js +0 -1
- solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes-deployment/index.html +0 -47
- solace_agent_mesh/assets/docs/lunr-index-1762283454666.json +0 -1
- solace_agent_mesh/assets/docs/search-doc-1762283454666.json +0 -1
- solace_agent_mesh/cli/commands/add_cmd/add_cmd_llm.txt +0 -250
- solace_agent_mesh/cli/commands/init_cmd/init_cmd_llm.txt +0 -365
- solace_agent_mesh/cli/commands/plugin_cmd/plugin_cmd_llm.txt +0 -305
- solace_agent_mesh/client/webui/frontend/static/assets/client-CRYdKo2Q.js +0 -25
- solace_agent_mesh/client/webui/frontend/static/assets/main-CojeY_1w.css +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main-ILja9MCG.js +0 -353
- solace_agent_mesh/common/a2a/a2a_llm.txt +0 -175
- solace_agent_mesh/common/a2a/a2a_llm_detail.txt +0 -193
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +0 -445
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm_detail.txt +0 -736
- solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +0 -330
- solace_agent_mesh/common/common_llm.txt +0 -230
- solace_agent_mesh/common/common_llm_detail.txt +0 -2562
- solace_agent_mesh/common/middleware/middleware_llm.txt +0 -174
- solace_agent_mesh/common/middleware/middleware_llm_detail.txt +0 -185
- solace_agent_mesh/common/sac/sac_llm.txt +0 -71
- solace_agent_mesh/common/sac/sac_llm_detail.txt +0 -82
- solace_agent_mesh/common/sam_events/sam_events_llm.txt +0 -104
- solace_agent_mesh/common/sam_events/sam_events_llm_detail.txt +0 -115
- solace_agent_mesh/common/services/providers/providers_llm.txt +0 -81
- solace_agent_mesh/common/services/services_llm.txt +0 -368
- solace_agent_mesh/common/services/services_llm_detail.txt +0 -459
- solace_agent_mesh/common/utils/embeds/embeds_llm.txt +0 -220
- solace_agent_mesh/common/utils/utils_llm.txt +0 -335
- solace_agent_mesh/common/utils/utils_llm_detail.txt +0 -572
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-ByU1X1HD.js +0 -98
- solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-61038fc6.js +0 -1
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-BWvk5-gF.js +0 -10
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-DxRwaWiE.css +0 -1
- solace_agent_mesh/core_a2a/core_a2a_llm.txt +0 -90
- solace_agent_mesh/core_a2a/core_a2a_llm_detail.txt +0 -101
- solace_agent_mesh/gateway/base/base_llm.txt +0 -226
- solace_agent_mesh/gateway/base/base_llm_detail.txt +0 -235
- solace_agent_mesh/gateway/gateway_llm.txt +0 -369
- solace_agent_mesh/gateway/gateway_llm_detail.txt +0 -3885
- solace_agent_mesh/gateway/http_sse/alembic/alembic_llm.txt +0 -345
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_fulltext_search_indexes.py +0 -92
- solace_agent_mesh/gateway/http_sse/alembic/versions/versions_llm.txt +0 -161
- solace_agent_mesh/gateway/http_sse/components/components_llm.txt +0 -105
- solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +0 -299
- solace_agent_mesh/gateway/http_sse/http_sse_llm_detail.txt +0 -3278
- solace_agent_mesh/gateway/http_sse/repository/entities/entities_llm.txt +0 -221
- solace_agent_mesh/gateway/http_sse/repository/models/models_llm.txt +0 -257
- solace_agent_mesh/gateway/http_sse/repository/repository_llm.txt +0 -308
- solace_agent_mesh/gateway/http_sse/routers/dto/dto_llm.txt +0 -450
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/requests_llm.txt +0 -133
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/responses_llm.txt +0 -123
- solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +0 -312
- solace_agent_mesh/gateway/http_sse/services/services_llm.txt +0 -303
- solace_agent_mesh/gateway/http_sse/shared/__init__.py +0 -146
- solace_agent_mesh/gateway/http_sse/shared/shared_llm.txt +0 -319
- solace_agent_mesh/gateway/http_sse/utils/utils_llm.txt +0 -47
- solace_agent_mesh/llm.txt +0 -228
- solace_agent_mesh/llm_detail.txt +0 -2835
- solace_agent_mesh/solace_agent_mesh_llm.txt +0 -362
- solace_agent_mesh/solace_agent_mesh_llm_detail.txt +0 -8599
- solace_agent_mesh/templates/logging_config_template.ini +0 -45
- solace_agent_mesh/templates/templates_llm.txt +0 -147
- /solace_agent_mesh/assets/docs/assets/js/{main.f213fe0c.js.LICENSE.txt → main.d634009f.js.LICENSE.txt} +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/auth_utils.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/pagination.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/response_utils.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/error_dto.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exceptions.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/enums.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/timestamp_utils.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/types.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/utils.py +0 -0
- {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import logging
|
|
2
2
|
from typing import Optional
|
|
3
3
|
from fastapi import APIRouter, Body, Depends, HTTPException, Query, status
|
|
4
|
+
from pydantic import ValidationError
|
|
4
5
|
from sqlalchemy.orm import Session
|
|
5
6
|
|
|
6
7
|
from ..dependencies import get_session_business_service, get_db
|
|
7
8
|
from ..services.session_service import SessionService
|
|
8
|
-
from
|
|
9
|
-
from
|
|
10
|
-
from
|
|
9
|
+
from solace_agent_mesh.shared.api.auth_utils import get_current_user
|
|
10
|
+
from solace_agent_mesh.shared.api.pagination import DataResponse, PaginatedResponse, PaginationParams
|
|
11
|
+
from solace_agent_mesh.shared.api.response_utils import create_data_response
|
|
11
12
|
from .dto.requests.session_requests import (
|
|
12
13
|
GetSessionRequest,
|
|
13
14
|
UpdateSessionRequest,
|
|
@@ -53,6 +54,7 @@ async def get_all_sessions(
|
|
|
53
54
|
agent_id=session_domain.agent_id,
|
|
54
55
|
project_id=session_domain.project_id,
|
|
55
56
|
project_name=session_domain.project_name,
|
|
57
|
+
has_running_background_task=session_domain.has_running_background_task,
|
|
56
58
|
created_time=session_domain.created_time,
|
|
57
59
|
updated_time=session_domain.updated_time,
|
|
58
60
|
)
|
|
@@ -79,7 +81,7 @@ async def search_sessions(
|
|
|
79
81
|
session_service: SessionService = Depends(get_session_business_service),
|
|
80
82
|
):
|
|
81
83
|
"""
|
|
82
|
-
Search sessions by name
|
|
84
|
+
Search sessions by name/title only.
|
|
83
85
|
"""
|
|
84
86
|
user_id = user.get("id")
|
|
85
87
|
log.info(
|
|
@@ -105,6 +107,7 @@ async def search_sessions(
|
|
|
105
107
|
agent_id=session_domain.agent_id,
|
|
106
108
|
project_id=session_domain.project_id,
|
|
107
109
|
project_name=session_domain.project_name,
|
|
110
|
+
has_running_background_task=session_domain.has_running_background_task,
|
|
108
111
|
created_time=session_domain.created_time,
|
|
109
112
|
updated_time=session_domain.updated_time,
|
|
110
113
|
)
|
|
@@ -474,6 +477,11 @@ async def update_session_name(
|
|
|
474
477
|
|
|
475
478
|
except HTTPException:
|
|
476
479
|
raise
|
|
480
|
+
except ValidationError as e:
|
|
481
|
+
log.warning("Pydantic validation error updating session %s: %s", session_id, e)
|
|
482
|
+
raise HTTPException(
|
|
483
|
+
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY, detail=str(e)
|
|
484
|
+
) from e
|
|
477
485
|
except ValueError as e:
|
|
478
486
|
log.warning("Validation error updating session %s: %s", session_id, e)
|
|
479
487
|
raise HTTPException(
|
|
@@ -556,6 +564,7 @@ async def move_session_to_project(
|
|
|
556
564
|
):
|
|
557
565
|
"""
|
|
558
566
|
Move a session to a different project or remove from project.
|
|
567
|
+
When moving to a project, artifacts from that project are immediately copied to the session.
|
|
559
568
|
"""
|
|
560
569
|
user_id = user.get("id")
|
|
561
570
|
log.info(
|
|
@@ -575,7 +584,7 @@ async def move_session_to_project(
|
|
|
575
584
|
status_code=status.HTTP_404_NOT_FOUND, detail=SESSION_NOT_FOUND_MSG
|
|
576
585
|
)
|
|
577
586
|
|
|
578
|
-
updated_session = session_service.move_session_to_project(
|
|
587
|
+
updated_session = await session_service.move_session_to_project(
|
|
579
588
|
db=db,
|
|
580
589
|
session_id=session_id,
|
|
581
590
|
user_id=user_id,
|
|
@@ -0,0 +1,355 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Speech API routes for STT and TTS functionality.
|
|
3
|
+
"""
|
|
4
|
+
|
|
5
|
+
from typing import Optional
|
|
6
|
+
from fastapi import APIRouter, Depends, File, Form, HTTPException, UploadFile
|
|
7
|
+
from fastapi.responses import StreamingResponse, Response
|
|
8
|
+
from pydantic import BaseModel
|
|
9
|
+
|
|
10
|
+
from solace_ai_connector.common.log import log
|
|
11
|
+
|
|
12
|
+
from ..services.audio_service import AudioService
|
|
13
|
+
from ..dependencies import get_audio_service
|
|
14
|
+
from solace_agent_mesh.shared.api.auth_utils import get_current_user
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
router = APIRouter()
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class TTSRequest(BaseModel):
|
|
21
|
+
"""Request model for text-to-speech"""
|
|
22
|
+
input: str
|
|
23
|
+
voice: Optional[str] = None
|
|
24
|
+
messageId: Optional[str] = None
|
|
25
|
+
provider: Optional[str] = None
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class StreamTTSRequest(BaseModel):
|
|
29
|
+
"""Request model for streaming text-to-speech"""
|
|
30
|
+
input: str
|
|
31
|
+
voice: Optional[str] = None
|
|
32
|
+
runId: Optional[str] = None
|
|
33
|
+
provider: Optional[str] = None
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@router.post("/stt")
|
|
37
|
+
async def speech_to_text(
|
|
38
|
+
audio: UploadFile = File(...),
|
|
39
|
+
provider: Optional[str] = Form(None),
|
|
40
|
+
language: Optional[str] = Form(None),
|
|
41
|
+
user: dict = Depends(get_current_user),
|
|
42
|
+
audio_service: AudioService = Depends(get_audio_service)
|
|
43
|
+
):
|
|
44
|
+
"""
|
|
45
|
+
Transcribe audio to text using configured STT service.
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
audio: Audio file (wav, mp3, webm, ogg)
|
|
49
|
+
provider: Optional provider override (openai, azure)
|
|
50
|
+
language: Optional language code (e.g., "en-US", "es-ES")
|
|
51
|
+
user: Current authenticated user
|
|
52
|
+
audio_service: Audio service instance
|
|
53
|
+
|
|
54
|
+
Returns:
|
|
55
|
+
JSON with transcribed text:
|
|
56
|
+
{
|
|
57
|
+
"text": "transcribed text",
|
|
58
|
+
"language": "en",
|
|
59
|
+
"duration": 5.2
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
Raises:
|
|
63
|
+
HTTPException: If transcription fails
|
|
64
|
+
"""
|
|
65
|
+
log.info(
|
|
66
|
+
"[SpeechAPI] STT request from user=%s, filename=%s, provider=%s, language=%s",
|
|
67
|
+
user.get("user_id"),
|
|
68
|
+
audio.filename,
|
|
69
|
+
provider,
|
|
70
|
+
language
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
try:
|
|
74
|
+
# Validate content type
|
|
75
|
+
if not audio.content_type or not audio.content_type.startswith("audio/"):
|
|
76
|
+
raise HTTPException(
|
|
77
|
+
415,
|
|
78
|
+
f"Unsupported media type: {audio.content_type}. Expected audio/*"
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
result = await audio_service.transcribe_audio(
|
|
82
|
+
audio_file=audio,
|
|
83
|
+
user_id=user.get("user_id", "anonymous"),
|
|
84
|
+
session_id=user.get("session_id", "default"),
|
|
85
|
+
app_name=user.get("app_name", "webui"),
|
|
86
|
+
provider=provider,
|
|
87
|
+
language=language
|
|
88
|
+
)
|
|
89
|
+
|
|
90
|
+
return result.to_dict()
|
|
91
|
+
|
|
92
|
+
except HTTPException:
|
|
93
|
+
raise
|
|
94
|
+
except Exception as e:
|
|
95
|
+
log.exception("[SpeechAPI] STT error: %s", e)
|
|
96
|
+
raise HTTPException(500, f"Transcription failed: {str(e)}")
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
@router.post("/tts")
|
|
100
|
+
async def text_to_speech(
|
|
101
|
+
request: TTSRequest,
|
|
102
|
+
user: dict = Depends(get_current_user),
|
|
103
|
+
audio_service: AudioService = Depends(get_audio_service)
|
|
104
|
+
):
|
|
105
|
+
"""
|
|
106
|
+
Convert text to speech using configured TTS service.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
request: TTS request with text and voice
|
|
110
|
+
user: Current authenticated user
|
|
111
|
+
audio_service: Audio service instance
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
Audio data as MP3
|
|
115
|
+
|
|
116
|
+
Raises:
|
|
117
|
+
HTTPException: If generation fails
|
|
118
|
+
"""
|
|
119
|
+
log.info(
|
|
120
|
+
"[SpeechAPI] TTS request from user=%s, text_len=%d, voice=%s",
|
|
121
|
+
user.get("user_id"),
|
|
122
|
+
len(request.input),
|
|
123
|
+
request.voice
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
try:
|
|
127
|
+
# Validate input
|
|
128
|
+
if not request.input or not request.input.strip():
|
|
129
|
+
raise HTTPException(400, "Input text is required")
|
|
130
|
+
|
|
131
|
+
if len(request.input) > 10000:
|
|
132
|
+
raise HTTPException(
|
|
133
|
+
413,
|
|
134
|
+
"Text too long (max 10000 characters). Use /tts/stream for longer text."
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
audio_data = await audio_service.generate_speech(
|
|
138
|
+
text=request.input,
|
|
139
|
+
voice=request.voice,
|
|
140
|
+
user_id=user.get("user_id", "anonymous"),
|
|
141
|
+
session_id=user.get("session_id", "default"),
|
|
142
|
+
app_name=user.get("app_name", "webui"),
|
|
143
|
+
message_id=request.messageId,
|
|
144
|
+
provider=request.provider # NEW: Pass provider from request
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
return Response(
|
|
148
|
+
content=audio_data,
|
|
149
|
+
media_type="audio/mpeg"
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
except HTTPException:
|
|
153
|
+
raise
|
|
154
|
+
except Exception as e:
|
|
155
|
+
log.exception("[SpeechAPI] TTS error: %s", e)
|
|
156
|
+
raise HTTPException(500, f"TTS generation failed: {str(e)}")
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
@router.post("/tts/stream")
|
|
160
|
+
async def stream_audio(
|
|
161
|
+
request: StreamTTSRequest,
|
|
162
|
+
user: dict = Depends(get_current_user),
|
|
163
|
+
audio_service: AudioService = Depends(get_audio_service)
|
|
164
|
+
):
|
|
165
|
+
"""
|
|
166
|
+
Stream TTS audio for long text (>4096 chars).
|
|
167
|
+
Uses chunking and streaming for better UX.
|
|
168
|
+
|
|
169
|
+
Args:
|
|
170
|
+
request: Stream TTS request with text and voice
|
|
171
|
+
user: Current authenticated user
|
|
172
|
+
audio_service: Audio service instance
|
|
173
|
+
|
|
174
|
+
Returns:
|
|
175
|
+
Streaming audio response
|
|
176
|
+
|
|
177
|
+
Raises:
|
|
178
|
+
HTTPException: If generation fails
|
|
179
|
+
"""
|
|
180
|
+
log.info(
|
|
181
|
+
"[SpeechAPI] TTS stream request from user=%s, text_len=%d",
|
|
182
|
+
user.get("user_id"),
|
|
183
|
+
len(request.input)
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
try:
|
|
187
|
+
# Validate input
|
|
188
|
+
if not request.input or not request.input.strip():
|
|
189
|
+
raise HTTPException(400, "Input text is required")
|
|
190
|
+
|
|
191
|
+
# Add max length validation to prevent abuse (100KB max for streaming)
|
|
192
|
+
if len(request.input) > 100000:
|
|
193
|
+
raise HTTPException(
|
|
194
|
+
413,
|
|
195
|
+
"Text too long (max 100000 characters for streaming)"
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
async def audio_generator():
|
|
199
|
+
async for chunk in audio_service.stream_speech(
|
|
200
|
+
text=request.input,
|
|
201
|
+
voice=request.voice,
|
|
202
|
+
user_id=user.get("user_id", "anonymous"),
|
|
203
|
+
session_id=user.get("session_id", "default"),
|
|
204
|
+
app_name=user.get("app_name", "webui"),
|
|
205
|
+
provider=request.provider # Pass provider from request
|
|
206
|
+
):
|
|
207
|
+
yield chunk
|
|
208
|
+
|
|
209
|
+
return StreamingResponse(
|
|
210
|
+
audio_generator(),
|
|
211
|
+
media_type="audio/mpeg",
|
|
212
|
+
headers={
|
|
213
|
+
"Content-Disposition": f"inline; filename=tts_stream_{request.runId or 'audio'}.mp3",
|
|
214
|
+
"Cache-Control": "no-cache"
|
|
215
|
+
}
|
|
216
|
+
)
|
|
217
|
+
|
|
218
|
+
except HTTPException:
|
|
219
|
+
raise
|
|
220
|
+
except Exception as e:
|
|
221
|
+
log.exception("[SpeechAPI] TTS stream error: %s", e)
|
|
222
|
+
raise HTTPException(500, f"TTS streaming failed: {str(e)}")
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
@router.get("/voices")
|
|
226
|
+
async def get_voices(
|
|
227
|
+
provider: Optional[str] = None, # NEW: Accept provider as query parameter
|
|
228
|
+
user: dict = Depends(get_current_user),
|
|
229
|
+
audio_service: AudioService = Depends(get_audio_service)
|
|
230
|
+
):
|
|
231
|
+
"""
|
|
232
|
+
Get available TTS voices based on configuration and provider.
|
|
233
|
+
|
|
234
|
+
Args:
|
|
235
|
+
provider: Optional provider filter (azure, gemini)
|
|
236
|
+
user: Current authenticated user
|
|
237
|
+
audio_service: Audio service instance
|
|
238
|
+
|
|
239
|
+
Returns:
|
|
240
|
+
JSON with available voices:
|
|
241
|
+
{
|
|
242
|
+
"voices": ["Kore", "Puck", "Zephyr", ...],
|
|
243
|
+
"default": "Kore"
|
|
244
|
+
}
|
|
245
|
+
"""
|
|
246
|
+
log.debug("[SpeechAPI] Voices request from user=%s, provider=%s", user.get("user_id"), provider)
|
|
247
|
+
|
|
248
|
+
try:
|
|
249
|
+
voices = await audio_service.get_available_voices(provider=provider) # Pass provider
|
|
250
|
+
|
|
251
|
+
# Get default voice from config
|
|
252
|
+
config = audio_service.get_speech_config()
|
|
253
|
+
default_voice = config.get("voice", "Kore")
|
|
254
|
+
|
|
255
|
+
return {
|
|
256
|
+
"voices": voices,
|
|
257
|
+
"default": default_voice
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
except Exception as e:
|
|
261
|
+
log.exception("[SpeechAPI] Error getting voices: %s", e)
|
|
262
|
+
raise HTTPException(500, f"Failed to get voices: {str(e)}")
|
|
263
|
+
|
|
264
|
+
|
|
265
|
+
@router.get("/config")
|
|
266
|
+
async def get_speech_config(
|
|
267
|
+
user: dict = Depends(get_current_user),
|
|
268
|
+
audio_service: AudioService = Depends(get_audio_service)
|
|
269
|
+
):
|
|
270
|
+
"""
|
|
271
|
+
Get speech configuration for frontend initialization.
|
|
272
|
+
|
|
273
|
+
Args:
|
|
274
|
+
user: Current authenticated user
|
|
275
|
+
audio_service: Audio service instance
|
|
276
|
+
|
|
277
|
+
Returns:
|
|
278
|
+
JSON with speech configuration:
|
|
279
|
+
{
|
|
280
|
+
"sttExternal": true,
|
|
281
|
+
"ttsExternal": true,
|
|
282
|
+
"speechToText": true,
|
|
283
|
+
"textToSpeech": true,
|
|
284
|
+
"engineSTT": "external",
|
|
285
|
+
"engineTTS": "external",
|
|
286
|
+
"voice": "Kore",
|
|
287
|
+
"playbackRate": 1.0,
|
|
288
|
+
"cacheTTS": true,
|
|
289
|
+
...
|
|
290
|
+
}
|
|
291
|
+
"""
|
|
292
|
+
log.debug("[SpeechAPI] Config request from user=%s", user.get("user_id"))
|
|
293
|
+
|
|
294
|
+
try:
|
|
295
|
+
config = audio_service.get_speech_config()
|
|
296
|
+
return config
|
|
297
|
+
|
|
298
|
+
except Exception as e:
|
|
299
|
+
log.exception("[SpeechAPI] Error getting config: %s", e)
|
|
300
|
+
raise HTTPException(500, f"Failed to get config: {str(e)}")
|
|
301
|
+
|
|
302
|
+
|
|
303
|
+
@router.post("/voice-sample")
|
|
304
|
+
async def get_voice_sample(
|
|
305
|
+
voice: str = Form(...),
|
|
306
|
+
provider: Optional[str] = Form(None),
|
|
307
|
+
user: dict = Depends(get_current_user),
|
|
308
|
+
audio_service: AudioService = Depends(get_audio_service)
|
|
309
|
+
):
|
|
310
|
+
"""
|
|
311
|
+
Generate a sample audio for a specific voice to preview before selection.
|
|
312
|
+
|
|
313
|
+
Args:
|
|
314
|
+
voice: Voice name to sample
|
|
315
|
+
provider: Optional provider (azure, gemini)
|
|
316
|
+
user: Current authenticated user
|
|
317
|
+
audio_service: Audio service instance
|
|
318
|
+
|
|
319
|
+
Returns:
|
|
320
|
+
Audio data as MP3
|
|
321
|
+
|
|
322
|
+
Raises:
|
|
323
|
+
HTTPException: If generation fails
|
|
324
|
+
"""
|
|
325
|
+
log.debug("[SpeechAPI] Voice sample request from user=%s, voice=%s, provider=%s",
|
|
326
|
+
user.get("user_id"), voice, provider)
|
|
327
|
+
|
|
328
|
+
try:
|
|
329
|
+
# Validate voice parameter
|
|
330
|
+
if not voice or not voice.strip():
|
|
331
|
+
raise HTTPException(400, "Voice parameter is required")
|
|
332
|
+
|
|
333
|
+
# Generate a sample text based on provider
|
|
334
|
+
sample_text = "Hello! This is a sample of my voice. I hope you find it pleasant to listen to."
|
|
335
|
+
|
|
336
|
+
audio_data = await audio_service.generate_speech(
|
|
337
|
+
text=sample_text,
|
|
338
|
+
voice=voice,
|
|
339
|
+
user_id=user.get("user_id", "anonymous"),
|
|
340
|
+
session_id=user.get("session_id", "default"),
|
|
341
|
+
app_name=user.get("app_name", "webui"),
|
|
342
|
+
message_id=f"voice_sample_{voice}",
|
|
343
|
+
provider=provider
|
|
344
|
+
)
|
|
345
|
+
|
|
346
|
+
return Response(
|
|
347
|
+
content=audio_data,
|
|
348
|
+
media_type="audio/mpeg"
|
|
349
|
+
)
|
|
350
|
+
|
|
351
|
+
except HTTPException:
|
|
352
|
+
raise
|
|
353
|
+
except Exception as e:
|
|
354
|
+
log.exception("[SpeechAPI] Voice sample error: %s", e)
|
|
355
|
+
raise HTTPException(500, f"Voice sample generation failed: {str(e)}")
|
|
@@ -5,12 +5,14 @@ API Router for Server-Sent Events (SSE) subscriptions.
|
|
|
5
5
|
import logging
|
|
6
6
|
import asyncio
|
|
7
7
|
import json
|
|
8
|
-
from fastapi import APIRouter, Depends, Request as FastAPIRequest, HTTPException, status
|
|
8
|
+
from fastapi import APIRouter, Depends, Request as FastAPIRequest, HTTPException, status, Query
|
|
9
|
+
from sqlalchemy.orm import Session as DBSession
|
|
9
10
|
|
|
10
11
|
from sse_starlette.sse import EventSourceResponse
|
|
11
12
|
|
|
12
13
|
from ....gateway.http_sse.sse_manager import SSEManager
|
|
13
|
-
from ....gateway.http_sse.dependencies import get_sse_manager
|
|
14
|
+
from ....gateway.http_sse.dependencies import get_sse_manager, get_db
|
|
15
|
+
from ....gateway.http_sse.repository.task_repository import TaskRepository
|
|
14
16
|
|
|
15
17
|
log = logging.getLogger(__name__)
|
|
16
18
|
trace_logger = logging.getLogger("sam_trace")
|
|
@@ -23,16 +25,32 @@ router = APIRouter()
|
|
|
23
25
|
async def subscribe_to_task_events(
|
|
24
26
|
task_id: str,
|
|
25
27
|
request: FastAPIRequest,
|
|
28
|
+
reconnect: bool = Query(False, description="Whether this is a reconnection attempt"),
|
|
29
|
+
last_event_timestamp: int = Query(0, description="Timestamp of last received event for replay"),
|
|
26
30
|
sse_manager: SSEManager = Depends(get_sse_manager),
|
|
31
|
+
db: DBSession = Depends(get_db),
|
|
27
32
|
):
|
|
28
33
|
"""
|
|
29
34
|
Establishes an SSE connection to receive real-time updates for a specific task.
|
|
35
|
+
|
|
36
|
+
Args:
|
|
37
|
+
task_id: The task to monitor
|
|
38
|
+
reconnect: If true, replay missed events before streaming live
|
|
39
|
+
last_event_timestamp: Timestamp of last received event (for replay)
|
|
30
40
|
"""
|
|
31
41
|
log_prefix = "[GET /api/v1/sse/subscribe/%s] " % task_id
|
|
32
|
-
log.debug("%sClient requesting SSE subscription.", log_prefix)
|
|
42
|
+
log.debug("%sClient requesting SSE subscription (reconnect=%s).", log_prefix, reconnect)
|
|
33
43
|
|
|
34
44
|
connection_queue: asyncio.Queue = None
|
|
35
45
|
try:
|
|
46
|
+
# Check if this is a background task
|
|
47
|
+
repo = TaskRepository()
|
|
48
|
+
task = repo.find_by_id(db, task_id)
|
|
49
|
+
is_background_task = task and task.background_execution_enabled
|
|
50
|
+
|
|
51
|
+
if is_background_task:
|
|
52
|
+
log.info("%sTask %s is a background task.", log_prefix, task_id)
|
|
53
|
+
|
|
36
54
|
connection_queue = await sse_manager.create_sse_connection(task_id)
|
|
37
55
|
log.debug("%sSSE connection queue created.", log_prefix)
|
|
38
56
|
|
|
@@ -42,6 +60,87 @@ async def subscribe_to_task_events(
|
|
|
42
60
|
try:
|
|
43
61
|
yield {"comment": "SSE connection established"}
|
|
44
62
|
log.debug("%sSent initial SSE comment.", log_prefix)
|
|
63
|
+
|
|
64
|
+
# If reconnecting, replay missed events from database
|
|
65
|
+
# For background tasks, always replay ALL events from the beginning
|
|
66
|
+
# to ensure the frontend can reconstruct the full message content
|
|
67
|
+
# after a browser refresh
|
|
68
|
+
if reconnect:
|
|
69
|
+
replay_from_timestamp = last_event_timestamp if last_event_timestamp > 0 else 0
|
|
70
|
+
|
|
71
|
+
# For background tasks, always replay from the beginning
|
|
72
|
+
# This handles the case where the browser was refreshed and
|
|
73
|
+
# the accumulated message content was lost
|
|
74
|
+
if is_background_task:
|
|
75
|
+
replay_from_timestamp = 0
|
|
76
|
+
log.info("%sBackground task reconnection - replaying ALL events from beginning", log_prefix)
|
|
77
|
+
else:
|
|
78
|
+
log.info("%sReplaying events since timestamp %d", log_prefix, replay_from_timestamp)
|
|
79
|
+
|
|
80
|
+
task_with_events = repo.find_by_id_with_events(db, task_id)
|
|
81
|
+
if task_with_events:
|
|
82
|
+
_, events = task_with_events
|
|
83
|
+
# Use >= for timestamp 0 to include all events
|
|
84
|
+
missed_events = [e for e in events if e.created_time > replay_from_timestamp]
|
|
85
|
+
log.info("%sReplaying %d missed events", log_prefix, len(missed_events))
|
|
86
|
+
|
|
87
|
+
# For background tasks, filter out intermediate artifact update events
|
|
88
|
+
# to prevent duplicate artifacts in chat. Only keep the final task response
|
|
89
|
+
# which contains the complete artifact list.
|
|
90
|
+
if is_background_task:
|
|
91
|
+
# Find if there's a final task response
|
|
92
|
+
has_final_response = any(
|
|
93
|
+
e.direction == "response" and
|
|
94
|
+
"result" in e.payload and
|
|
95
|
+
e.payload.get("result", {}).get("kind") == "task"
|
|
96
|
+
for e in missed_events
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
if has_final_response:
|
|
100
|
+
# Filter out artifact-update events since the final response contains all artifacts
|
|
101
|
+
filtered_events = []
|
|
102
|
+
for e in missed_events:
|
|
103
|
+
if e.direction == "response" and "result" in e.payload:
|
|
104
|
+
result = e.payload.get("result", {})
|
|
105
|
+
if result.get("kind") == "artifact-update":
|
|
106
|
+
log.debug(
|
|
107
|
+
"%sFiltering out intermediate artifact-update event during replay",
|
|
108
|
+
log_prefix
|
|
109
|
+
)
|
|
110
|
+
continue
|
|
111
|
+
filtered_events.append(e)
|
|
112
|
+
missed_events = filtered_events
|
|
113
|
+
log.info(
|
|
114
|
+
"%sFiltered to %d events (removed intermediate artifact updates)",
|
|
115
|
+
log_prefix,
|
|
116
|
+
len(missed_events)
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
for event in missed_events:
|
|
120
|
+
# The payload is already a JSON-RPC response, just need to determine event type
|
|
121
|
+
# and yield it in the same format as live events
|
|
122
|
+
event_type = "status_update" # Default
|
|
123
|
+
|
|
124
|
+
# Determine event type from the payload structure
|
|
125
|
+
if event.direction == "response":
|
|
126
|
+
# Check if it's a final response (Task object) or status update
|
|
127
|
+
if "result" in event.payload:
|
|
128
|
+
result = event.payload.get("result", {})
|
|
129
|
+
if result.get("kind") == "task":
|
|
130
|
+
event_type = "final_response"
|
|
131
|
+
elif result.get("kind") == "status-update":
|
|
132
|
+
event_type = "status_update"
|
|
133
|
+
elif result.get("kind") == "artifact-update":
|
|
134
|
+
event_type = "artifact_update"
|
|
135
|
+
|
|
136
|
+
# Yield the event in SSE format
|
|
137
|
+
# The payload is already the complete JSON-RPC response
|
|
138
|
+
yield {
|
|
139
|
+
"event": event_type,
|
|
140
|
+
"data": json.dumps(event.payload)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
log.info("%sFinished replaying missed events", log_prefix)
|
|
45
144
|
|
|
46
145
|
loop_count = 0
|
|
47
146
|
while True:
|
|
@@ -55,7 +154,16 @@ async def subscribe_to_task_events(
|
|
|
55
154
|
"%sRequest disconnected status: %s", log_prefix, disconnected
|
|
56
155
|
)
|
|
57
156
|
if disconnected:
|
|
58
|
-
|
|
157
|
+
if is_background_task:
|
|
158
|
+
log.info(
|
|
159
|
+
"%sClient disconnected from background task %s. Draining buffers and exiting SSE stream.",
|
|
160
|
+
log_prefix,
|
|
161
|
+
task_id
|
|
162
|
+
)
|
|
163
|
+
# For background tasks, we need to drain the buffers to prevent overflow
|
|
164
|
+
# The task will continue running, but we stop consuming events
|
|
165
|
+
else:
|
|
166
|
+
log.info("%sClient disconnected. Breaking loop.", log_prefix)
|
|
59
167
|
break
|
|
60
168
|
|
|
61
169
|
try:
|
|
@@ -135,6 +243,11 @@ async def subscribe_to_task_events(
|
|
|
135
243
|
if connection_queue:
|
|
136
244
|
await sse_manager.remove_sse_connection(task_id, connection_queue)
|
|
137
245
|
log.info("%sRemoved SSE connection queue from manager.", log_prefix)
|
|
246
|
+
|
|
247
|
+
# If this was a background task, drain the buffer to prevent overflow
|
|
248
|
+
if is_background_task:
|
|
249
|
+
await sse_manager.drain_buffer_for_background_task(task_id)
|
|
250
|
+
log.info("%sDrained buffer for background task %s", log_prefix, task_id)
|
|
138
251
|
|
|
139
252
|
return EventSourceResponse(event_generator())
|
|
140
253
|
|