solace-agent-mesh 1.7.1__py3-none-any.whl → 1.13.2__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of solace-agent-mesh might be problematic. Click here for more details.
- solace_agent_mesh/agent/adk/alembic/README +74 -0
- solace_agent_mesh/agent/adk/alembic/env.py +77 -0
- solace_agent_mesh/agent/adk/alembic/script.py.mako +28 -0
- solace_agent_mesh/agent/adk/alembic/versions/e2902798564d_adk_session_db_upgrade.py +52 -0
- solace_agent_mesh/agent/adk/alembic.ini +112 -0
- solace_agent_mesh/agent/adk/artifacts/filesystem_artifact_service.py +164 -0
- solace_agent_mesh/agent/adk/artifacts/s3_artifact_service.py +163 -0
- solace_agent_mesh/agent/adk/callbacks.py +752 -127
- solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +99 -7
- solace_agent_mesh/agent/adk/intelligent_mcp_callbacks.py +52 -5
- solace_agent_mesh/agent/adk/mcp_content_processor.py +1 -1
- solace_agent_mesh/agent/adk/models/lite_llm.py +34 -16
- solace_agent_mesh/agent/adk/models/oauth2_token_manager.py +24 -137
- solace_agent_mesh/agent/adk/runner.py +66 -8
- solace_agent_mesh/agent/adk/schema_migration.py +88 -0
- solace_agent_mesh/agent/adk/services.py +41 -1
- solace_agent_mesh/agent/adk/setup.py +220 -32
- solace_agent_mesh/agent/adk/stream_parser.py +229 -40
- solace_agent_mesh/agent/protocol/event_handlers.py +219 -33
- solace_agent_mesh/agent/proxies/a2a/component.py +572 -75
- solace_agent_mesh/agent/proxies/a2a/config.py +80 -4
- solace_agent_mesh/agent/proxies/base/component.py +188 -22
- solace_agent_mesh/agent/proxies/base/proxy_task_context.py +3 -1
- solace_agent_mesh/agent/sac/app.py +37 -12
- solace_agent_mesh/agent/sac/component.py +322 -52
- solace_agent_mesh/agent/sac/patch_adk.py +8 -16
- solace_agent_mesh/agent/sac/task_execution_context.py +90 -0
- solace_agent_mesh/agent/tools/__init__.py +3 -0
- solace_agent_mesh/agent/tools/audio_tools.py +3 -3
- solace_agent_mesh/agent/tools/builtin_artifact_tools.py +698 -24
- solace_agent_mesh/agent/tools/deep_research_tools.py +2161 -0
- solace_agent_mesh/agent/tools/peer_agent_tool.py +82 -15
- solace_agent_mesh/agent/tools/time_tools.py +126 -0
- solace_agent_mesh/agent/tools/tool_config_types.py +54 -2
- solace_agent_mesh/agent/tools/web_search_tools.py +279 -0
- solace_agent_mesh/agent/tools/web_tools.py +125 -17
- solace_agent_mesh/agent/utils/artifact_helpers.py +243 -5
- solace_agent_mesh/agent/utils/context_helpers.py +17 -0
- solace_agent_mesh/assets/docs/404.html +6 -6
- solace_agent_mesh/assets/docs/assets/css/{styles.906a1503.css → styles.8162edfb.css} +1 -1
- solace_agent_mesh/assets/docs/assets/js/05749d90.19ac4f35.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/15ba94aa.e186750d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/15e40e79.434bb30f.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/17896441.e612dfb4.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2279.550aa580.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/{17896441.a5e82f9b.js.LICENSE.txt → 2279.550aa580.js.LICENSE.txt} +6 -0
- solace_agent_mesh/assets/docs/assets/js/240a0364.83e37aa8.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/2e32b5e0.2f0db237.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3a6c6137.7e61915d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3ac1795d.7f7ab1c1.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/3ff0015d.e53c9b78.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/41adc471.0e95b87c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/4667dc50.bf2ad456.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/49eed117.493d6f99.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/{509e993c.4c7a1a6d.js → 509e993c.a1fbf45a.js} +1 -1
- solace_agent_mesh/assets/docs/assets/js/547e15cc.8e6da617.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/55b7b518.29d6e75d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5b8d9c11.d4eb37b8.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/5c2bd65f.1ee87753.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/60702c0e.a8bdd79b.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/64195356.09dbd087.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/66d4869e.30340bd3.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6aaedf65.7253541d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6d84eae0.fd23ba4a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/729898df.7249e9fd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/7e294c01.7c5f6906.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/8024126c.e3467286.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/81a99df0.7ed65d45.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/82fbfb93.161823a5.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/924ffdeb.975e428a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/94e8668d.16083b3f.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/9bb13469.4523ae20.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/a7d42657.a956689d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/a94703ab.3e5fbcb3.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ab9708a8.3e563275.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/c93cbaa0.0e0d8baf.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/cab03b5b.6a073091.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/cbe2e9ea.07e170dd.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e04b235d.06d23db6.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e1b6eeb4.deb2b62e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e3d9abda.1476f570.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e6f9706b.acc800d3.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/e92d0134.c147a429.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/ee0c2fe7.94d0a351.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/f284c35a.cc97854c.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/main.d634009f.js +2 -0
- solace_agent_mesh/assets/docs/assets/js/runtime~main.27bb82a7.js +1 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/agents/index.html +68 -68
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/artifact-management/index.html +50 -50
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/audio-tools/index.html +42 -42
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/data-analysis-tools/index.html +55 -55
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/embeds/index.html +75 -75
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/image-tools/index.html +81 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/index.html +67 -50
- solace_agent_mesh/assets/docs/docs/documentation/components/builtin-tools/research-tools/index.html +136 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/cli/index.html +178 -144
- solace_agent_mesh/assets/docs/docs/documentation/components/gateways/index.html +43 -42
- solace_agent_mesh/assets/docs/docs/documentation/components/index.html +20 -18
- solace_agent_mesh/assets/docs/docs/documentation/components/orchestrator/index.html +23 -23
- solace_agent_mesh/assets/docs/docs/documentation/components/platform-service/index.html +33 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/plugins/index.html +45 -45
- solace_agent_mesh/assets/docs/docs/documentation/components/projects/index.html +98 -112
- solace_agent_mesh/assets/docs/docs/documentation/components/prompts/index.html +147 -0
- solace_agent_mesh/assets/docs/docs/documentation/components/proxies/index.html +208 -125
- solace_agent_mesh/assets/docs/docs/documentation/components/speech/index.html +52 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/debugging/index.html +28 -28
- solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +29 -29
- solace_agent_mesh/assets/docs/docs/documentation/deploying/index.html +14 -14
- solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/index.html +47 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes/kubernetes-deployment-guide/index.html +197 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/logging/index.html +67 -53
- solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +17 -17
- solace_agent_mesh/assets/docs/docs/documentation/deploying/proxy_configuration/index.html +49 -0
- solace_agent_mesh/assets/docs/docs/documentation/developing/create-agents/index.html +38 -38
- solace_agent_mesh/assets/docs/docs/documentation/developing/create-gateways/index.html +87 -87
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-python-tools/index.html +67 -49
- solace_agent_mesh/assets/docs/docs/documentation/developing/creating-service-providers/index.html +17 -17
- solace_agent_mesh/assets/docs/docs/documentation/developing/evaluations/index.html +51 -51
- solace_agent_mesh/assets/docs/docs/documentation/developing/index.html +22 -22
- solace_agent_mesh/assets/docs/docs/documentation/developing/structure/index.html +27 -27
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/bedrock-agents/index.html +135 -135
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/custom-agent/index.html +66 -66
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/event-mesh-gateway/index.html +51 -51
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mcp-integration/index.html +50 -38
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/mongodb-integration/index.html +86 -86
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rag-integration/index.html +51 -51
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/rest-gateway/index.html +24 -24
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/slack-integration/index.html +30 -30
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/sql-database/index.html +44 -44
- solace_agent_mesh/assets/docs/docs/documentation/developing/tutorials/teams-integration/index.html +115 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/agent-builder/index.html +50 -23
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/connectors/index.html +29 -24
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +21 -21
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/installation/index.html +40 -37
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/openapi-tools/index.html +324 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/rbac-setup-guide/index.html +96 -66
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/secure-user-delegated-access/index.html +181 -181
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +75 -75
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/wheel-installation/index.html +27 -27
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/architecture/index.html +44 -44
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/index.html +39 -38
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/introduction/index.html +30 -30
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/try-agent-mesh/index.html +18 -18
- solace_agent_mesh/assets/docs/docs/documentation/getting-started/vibe_coding/index.html +62 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/artifact-storage/index.html +135 -114
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +37 -37
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/index.html +14 -14
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/installation/index.html +27 -25
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/large_language_models/index.html +69 -69
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/run-project/index.html +72 -72
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/session-storage/index.html +112 -112
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/user-feedback/index.html +28 -28
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-gateway-upgrade-to-0.3.0/index.html +42 -42
- solace_agent_mesh/assets/docs/docs/documentation/migrations/a2a-upgrade/a2a-technical-migration-map/index.html +20 -20
- solace_agent_mesh/assets/docs/docs/documentation/migrations/platform-service-split/index.html +85 -0
- solace_agent_mesh/assets/docs/lunr-index-1768329217460.json +1 -0
- solace_agent_mesh/assets/docs/lunr-index.json +1 -1
- solace_agent_mesh/assets/docs/search-doc-1768329217460.json +1 -0
- solace_agent_mesh/assets/docs/search-doc.json +1 -1
- solace_agent_mesh/assets/docs/sitemap.xml +1 -1
- solace_agent_mesh/cli/__init__.py +1 -1
- solace_agent_mesh/cli/commands/add_cmd/__init__.py +3 -1
- solace_agent_mesh/cli/commands/add_cmd/agent_cmd.py +6 -1
- solace_agent_mesh/cli/commands/add_cmd/proxy_cmd.py +100 -0
- solace_agent_mesh/cli/commands/eval_cmd.py +1 -1
- solace_agent_mesh/cli/commands/init_cmd/__init__.py +15 -0
- solace_agent_mesh/cli/commands/init_cmd/directory_step.py +1 -1
- solace_agent_mesh/cli/commands/init_cmd/env_step.py +30 -3
- solace_agent_mesh/cli/commands/init_cmd/orchestrator_step.py +3 -4
- solace_agent_mesh/cli/commands/init_cmd/platform_service_step.py +85 -0
- solace_agent_mesh/cli/commands/init_cmd/webui_gateway_step.py +16 -3
- solace_agent_mesh/cli/commands/plugin_cmd/add_cmd.py +2 -1
- solace_agent_mesh/cli/commands/plugin_cmd/catalog_cmd.py +1 -0
- solace_agent_mesh/cli/commands/plugin_cmd/create_cmd.py +3 -3
- solace_agent_mesh/cli/commands/run_cmd.py +64 -49
- solace_agent_mesh/cli/commands/tools_cmd.py +315 -0
- solace_agent_mesh/cli/main.py +15 -0
- solace_agent_mesh/client/webui/frontend/static/assets/{authCallback-tcIFZLis.js → authCallback-KnKMP_vb.js} +1 -1
- solace_agent_mesh/client/webui/frontend/static/assets/client-DpBL2stg.js +25 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-Cd498TV2.js +435 -0
- solace_agent_mesh/client/webui/frontend/static/assets/main-rSf8Vu29.css +1 -0
- solace_agent_mesh/client/webui/frontend/static/assets/{vendor-CINwxvwV.js → vendor-CGk8Suyh.js} +189 -94
- solace_agent_mesh/client/webui/frontend/static/auth-callback.html +3 -3
- solace_agent_mesh/client/webui/frontend/static/index.html +4 -4
- solace_agent_mesh/client/webui/frontend/static/mockServiceWorker.js +336 -0
- solace_agent_mesh/client/webui/frontend/static/ui-version.json +6 -0
- solace_agent_mesh/common/a2a/types.py +1 -1
- solace_agent_mesh/common/agent_registry.py +38 -11
- solace_agent_mesh/common/data_parts.py +124 -0
- solace_agent_mesh/common/error_handlers.py +83 -0
- solace_agent_mesh/common/exceptions.py +24 -0
- solace_agent_mesh/common/oauth/__init__.py +17 -0
- solace_agent_mesh/common/oauth/oauth_client.py +408 -0
- solace_agent_mesh/common/oauth/utils.py +50 -0
- solace_agent_mesh/common/rag_dto.py +156 -0
- solace_agent_mesh/common/sac/sam_component_base.py +73 -1
- solace_agent_mesh/common/sam_events/event_service.py +2 -2
- solace_agent_mesh/common/utils/embeds/converter.py +1 -8
- solace_agent_mesh/common/utils/embeds/modifiers.py +2 -27
- solace_agent_mesh/common/utils/embeds/resolver.py +94 -25
- solace_agent_mesh/common/utils/embeds/types.py +1 -0
- solace_agent_mesh/common/utils/log_formatters.py +20 -0
- solace_agent_mesh/common/utils/mime_helpers.py +12 -5
- solace_agent_mesh/common/utils/rbac_utils.py +69 -0
- solace_agent_mesh/common/utils/templates/__init__.py +8 -0
- solace_agent_mesh/common/utils/templates/liquid_renderer.py +210 -0
- solace_agent_mesh/common/utils/templates/template_resolver.py +161 -0
- solace_agent_mesh/config_portal/backend/common.py +12 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-CljP4_mv.js +103 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/{components-Rk0n-9cK.js → components-CaC6hG8d.js} +22 -22
- solace_agent_mesh/config_portal/frontend/static/client/assets/{entry.client-mvZjNKiz.js → entry.client-H_TM0YBt.js} +3 -3
- solace_agent_mesh/config_portal/frontend/static/client/assets/{index-DzNKzXrc.js → index-CnFykb2v.js} +16 -16
- solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-f8439d40.js +1 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-BIMqslJB.css +1 -0
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-mJmTIdIk.js +10 -0
- solace_agent_mesh/config_portal/frontend/static/client/index.html +3 -3
- solace_agent_mesh/core_a2a/service.py +3 -2
- solace_agent_mesh/gateway/adapter/base.py +28 -1
- solace_agent_mesh/gateway/adapter/types.py +9 -0
- solace_agent_mesh/gateway/base/app.py +10 -0
- solace_agent_mesh/gateway/base/auth_interface.py +103 -0
- solace_agent_mesh/gateway/base/component.py +451 -10
- solace_agent_mesh/gateway/generic/component.py +274 -30
- solace_agent_mesh/gateway/http_sse/alembic/env.py +0 -7
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_soft_delete_and_search.py +2 -43
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_default_agent_to_projects.py +2 -2
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251108_create_prompt_tables_with_sharing.py +154 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251115_add_parent_task_id.py +32 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251126_add_background_task_fields.py +47 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251202_add_versioned_fields_to_prompts.py +52 -0
- solace_agent_mesh/gateway/http_sse/alembic.ini +0 -36
- solace_agent_mesh/gateway/http_sse/app.py +23 -6
- solace_agent_mesh/gateway/http_sse/component.py +158 -73
- solace_agent_mesh/gateway/http_sse/dependencies.py +50 -57
- solace_agent_mesh/gateway/http_sse/main.py +58 -482
- solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +2 -2
- solace_agent_mesh/gateway/http_sse/repository/entities/project.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/entities/project_user.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/entities/session.py +3 -2
- solace_agent_mesh/gateway/http_sse/repository/entities/task.py +7 -0
- solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +2 -2
- solace_agent_mesh/gateway/http_sse/repository/interfaces.py +2 -2
- solace_agent_mesh/gateway/http_sse/repository/models/__init__.py +5 -0
- solace_agent_mesh/gateway/http_sse/repository/models/prompt_model.py +159 -0
- solace_agent_mesh/gateway/http_sse/repository/models/session_model.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/models/task_model.py +8 -1
- solace_agent_mesh/gateway/http_sse/repository/project_repository.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/project_user_repository.py +1 -1
- solace_agent_mesh/gateway/http_sse/repository/session_repository.py +12 -107
- solace_agent_mesh/gateway/http_sse/repository/task_repository.py +86 -2
- solace_agent_mesh/gateway/http_sse/routers/agent_cards.py +38 -7
- solace_agent_mesh/gateway/http_sse/routers/artifacts.py +113 -7
- solace_agent_mesh/gateway/http_sse/routers/auth.py +69 -132
- solace_agent_mesh/gateway/http_sse/routers/config.py +235 -10
- solace_agent_mesh/gateway/http_sse/routers/dto/project_dto.py +69 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/prompt_dto.py +255 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/session_requests.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/base_responses.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/project_responses.py +1 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +3 -2
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/version_responses.py +31 -0
- solace_agent_mesh/gateway/http_sse/routers/feedback.py +2 -2
- solace_agent_mesh/gateway/http_sse/routers/people.py +2 -2
- solace_agent_mesh/gateway/http_sse/routers/projects.py +250 -24
- solace_agent_mesh/gateway/http_sse/routers/prompts.py +1416 -0
- solace_agent_mesh/gateway/http_sse/routers/sessions.py +14 -5
- solace_agent_mesh/gateway/http_sse/routers/speech.py +355 -0
- solace_agent_mesh/gateway/http_sse/routers/sse.py +117 -4
- solace_agent_mesh/gateway/http_sse/routers/tasks.py +509 -149
- solace_agent_mesh/gateway/http_sse/routers/users.py +1 -1
- solace_agent_mesh/gateway/http_sse/routers/version.py +343 -0
- solace_agent_mesh/gateway/http_sse/routers/visualization.py +2 -1
- solace_agent_mesh/gateway/http_sse/services/audio_service.py +1227 -0
- solace_agent_mesh/gateway/http_sse/services/background_task_monitor.py +186 -0
- solace_agent_mesh/gateway/http_sse/services/data_retention_service.py +1 -1
- solace_agent_mesh/gateway/http_sse/services/feedback_service.py +1 -1
- solace_agent_mesh/gateway/http_sse/services/project_service.py +539 -12
- solace_agent_mesh/gateway/http_sse/services/prompt_builder_assistant.py +303 -0
- solace_agent_mesh/gateway/http_sse/services/session_service.py +198 -21
- solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +354 -4
- solace_agent_mesh/gateway/http_sse/sse_manager.py +280 -169
- solace_agent_mesh/gateway/http_sse/utils/artifact_copy_utils.py +370 -0
- solace_agent_mesh/gateway/http_sse/utils/stim_utils.py +41 -1
- solace_agent_mesh/services/__init__.py +0 -0
- solace_agent_mesh/services/platform/__init__.py +29 -0
- solace_agent_mesh/services/platform/alembic/env.py +85 -0
- solace_agent_mesh/services/platform/alembic/script.py.mako +28 -0
- solace_agent_mesh/services/platform/alembic.ini +109 -0
- solace_agent_mesh/services/platform/api/__init__.py +3 -0
- solace_agent_mesh/services/platform/api/dependencies.py +154 -0
- solace_agent_mesh/services/platform/api/main.py +314 -0
- solace_agent_mesh/services/platform/api/middleware.py +51 -0
- solace_agent_mesh/services/platform/api/routers/__init__.py +33 -0
- solace_agent_mesh/services/platform/api/routers/health_router.py +31 -0
- solace_agent_mesh/services/platform/app.py +215 -0
- solace_agent_mesh/services/platform/component.py +777 -0
- solace_agent_mesh/shared/__init__.py +14 -0
- solace_agent_mesh/shared/api/__init__.py +42 -0
- solace_agent_mesh/shared/auth/__init__.py +26 -0
- solace_agent_mesh/shared/auth/dependencies.py +204 -0
- solace_agent_mesh/shared/auth/middleware.py +347 -0
- solace_agent_mesh/shared/database/__init__.py +20 -0
- solace_agent_mesh/{gateway/http_sse/shared → shared/database}/base_repository.py +1 -1
- solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_exceptions.py +1 -1
- solace_agent_mesh/{gateway/http_sse/shared → shared/database}/database_helpers.py +1 -1
- solace_agent_mesh/shared/exceptions/__init__.py +36 -0
- solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exception_handlers.py +1 -1
- solace_agent_mesh/shared/utils/__init__.py +21 -0
- solace_agent_mesh/templates/logging_config_template.yaml +48 -0
- solace_agent_mesh/templates/main_orchestrator.yaml +12 -1
- solace_agent_mesh/templates/platform.yaml +49 -0
- solace_agent_mesh/templates/plugin_readme_template.md +3 -25
- solace_agent_mesh/templates/plugin_tool_config_template.yaml +109 -0
- solace_agent_mesh/templates/proxy_template.yaml +62 -0
- solace_agent_mesh/templates/webui.yaml +148 -6
- solace_agent_mesh/tools/web_search/__init__.py +18 -0
- solace_agent_mesh/tools/web_search/base.py +84 -0
- solace_agent_mesh/tools/web_search/google_search.py +247 -0
- solace_agent_mesh/tools/web_search/models.py +99 -0
- {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/METADATA +29 -8
- {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/RECORD +334 -313
- {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/WHEEL +1 -1
- solace_agent_mesh/agent/adk/adk_llm.txt +0 -226
- solace_agent_mesh/agent/adk/adk_llm_detail.txt +0 -566
- solace_agent_mesh/agent/adk/artifacts/artifacts_llm.txt +0 -171
- solace_agent_mesh/agent/adk/models/models_llm.txt +0 -189
- solace_agent_mesh/agent/agent_llm.txt +0 -369
- solace_agent_mesh/agent/agent_llm_detail.txt +0 -1702
- solace_agent_mesh/agent/protocol/protocol_llm.txt +0 -81
- solace_agent_mesh/agent/protocol/protocol_llm_detail.txt +0 -92
- solace_agent_mesh/agent/proxies/a2a/a2a_llm.txt +0 -190
- solace_agent_mesh/agent/proxies/base/base_llm.txt +0 -148
- solace_agent_mesh/agent/proxies/proxies_llm.txt +0 -283
- solace_agent_mesh/agent/sac/sac_llm.txt +0 -189
- solace_agent_mesh/agent/sac/sac_llm_detail.txt +0 -200
- solace_agent_mesh/agent/testing/testing_llm.txt +0 -58
- solace_agent_mesh/agent/testing/testing_llm_detail.txt +0 -68
- solace_agent_mesh/agent/tools/tools_llm.txt +0 -276
- solace_agent_mesh/agent/tools/tools_llm_detail.txt +0 -275
- solace_agent_mesh/agent/utils/utils_llm.txt +0 -152
- solace_agent_mesh/agent/utils/utils_llm_detail.txt +0 -149
- solace_agent_mesh/assets/docs/assets/js/05749d90.c70b2be9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/15ba94aa.92fea363.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/15e40e79.36003774.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/240a0364.c39f8388.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/2e32b5e0.33f5d75b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3a6c6137.f5940cfa.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3ac1795d.e4870a49.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3ff0015d.b63ee53a.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/547e15cc.2f7790c1.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/55b7b518.f2b1d1ba.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/5c2bd65f.45b32c2b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/64195356.c498c4d0.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/66d4869e.830d443f.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/6d84eae0.4a5fbf39.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/8024126c.fa0e7186.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/81a99df0.07034dd9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/82fbfb93.139a1a1f.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/924ffdeb.8095e148.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/94e8668d.09ed9234.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/9bb13469.dd1c9b54.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/a94703ab.0438dbc2.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/ab9708a8.245ae0ef.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/c93cbaa0.eaff365e.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/cbe2e9ea.f902fad8.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/db5d6442.3daf1696.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e04b235d.c9c50c7b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e3d9abda.d11c67a7.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e6f9706b.045d0fa1.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e92d0134.3bda61dd.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/f284c35a.5099c51e.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/main.f213fe0c.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/runtime~main.d9606d6a.js +0 -1
- solace_agent_mesh/assets/docs/docs/documentation/deploying/kubernetes-deployment/index.html +0 -47
- solace_agent_mesh/assets/docs/lunr-index-1762283454666.json +0 -1
- solace_agent_mesh/assets/docs/search-doc-1762283454666.json +0 -1
- solace_agent_mesh/cli/commands/add_cmd/add_cmd_llm.txt +0 -250
- solace_agent_mesh/cli/commands/init_cmd/init_cmd_llm.txt +0 -365
- solace_agent_mesh/cli/commands/plugin_cmd/plugin_cmd_llm.txt +0 -305
- solace_agent_mesh/client/webui/frontend/static/assets/client-CRYdKo2Q.js +0 -25
- solace_agent_mesh/client/webui/frontend/static/assets/main-CojeY_1w.css +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/main-ILja9MCG.js +0 -353
- solace_agent_mesh/common/a2a/a2a_llm.txt +0 -175
- solace_agent_mesh/common/a2a/a2a_llm_detail.txt +0 -193
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +0 -445
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm_detail.txt +0 -736
- solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +0 -330
- solace_agent_mesh/common/common_llm.txt +0 -230
- solace_agent_mesh/common/common_llm_detail.txt +0 -2562
- solace_agent_mesh/common/middleware/middleware_llm.txt +0 -174
- solace_agent_mesh/common/middleware/middleware_llm_detail.txt +0 -185
- solace_agent_mesh/common/sac/sac_llm.txt +0 -71
- solace_agent_mesh/common/sac/sac_llm_detail.txt +0 -82
- solace_agent_mesh/common/sam_events/sam_events_llm.txt +0 -104
- solace_agent_mesh/common/sam_events/sam_events_llm_detail.txt +0 -115
- solace_agent_mesh/common/services/providers/providers_llm.txt +0 -81
- solace_agent_mesh/common/services/services_llm.txt +0 -368
- solace_agent_mesh/common/services/services_llm_detail.txt +0 -459
- solace_agent_mesh/common/utils/embeds/embeds_llm.txt +0 -220
- solace_agent_mesh/common/utils/utils_llm.txt +0 -335
- solace_agent_mesh/common/utils/utils_llm_detail.txt +0 -572
- solace_agent_mesh/config_portal/frontend/static/client/assets/_index-ByU1X1HD.js +0 -98
- solace_agent_mesh/config_portal/frontend/static/client/assets/manifest-61038fc6.js +0 -1
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-BWvk5-gF.js +0 -10
- solace_agent_mesh/config_portal/frontend/static/client/assets/root-DxRwaWiE.css +0 -1
- solace_agent_mesh/core_a2a/core_a2a_llm.txt +0 -90
- solace_agent_mesh/core_a2a/core_a2a_llm_detail.txt +0 -101
- solace_agent_mesh/gateway/base/base_llm.txt +0 -226
- solace_agent_mesh/gateway/base/base_llm_detail.txt +0 -235
- solace_agent_mesh/gateway/gateway_llm.txt +0 -369
- solace_agent_mesh/gateway/gateway_llm_detail.txt +0 -3885
- solace_agent_mesh/gateway/http_sse/alembic/alembic_llm.txt +0 -345
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_fulltext_search_indexes.py +0 -92
- solace_agent_mesh/gateway/http_sse/alembic/versions/versions_llm.txt +0 -161
- solace_agent_mesh/gateway/http_sse/components/components_llm.txt +0 -105
- solace_agent_mesh/gateway/http_sse/http_sse_llm.txt +0 -299
- solace_agent_mesh/gateway/http_sse/http_sse_llm_detail.txt +0 -3278
- solace_agent_mesh/gateway/http_sse/repository/entities/entities_llm.txt +0 -221
- solace_agent_mesh/gateway/http_sse/repository/models/models_llm.txt +0 -257
- solace_agent_mesh/gateway/http_sse/repository/repository_llm.txt +0 -308
- solace_agent_mesh/gateway/http_sse/routers/dto/dto_llm.txt +0 -450
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/requests_llm.txt +0 -133
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/responses_llm.txt +0 -123
- solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +0 -312
- solace_agent_mesh/gateway/http_sse/services/services_llm.txt +0 -303
- solace_agent_mesh/gateway/http_sse/shared/__init__.py +0 -146
- solace_agent_mesh/gateway/http_sse/shared/shared_llm.txt +0 -319
- solace_agent_mesh/gateway/http_sse/utils/utils_llm.txt +0 -47
- solace_agent_mesh/llm.txt +0 -228
- solace_agent_mesh/llm_detail.txt +0 -2835
- solace_agent_mesh/solace_agent_mesh_llm.txt +0 -362
- solace_agent_mesh/solace_agent_mesh_llm_detail.txt +0 -8599
- solace_agent_mesh/templates/logging_config_template.ini +0 -45
- solace_agent_mesh/templates/templates_llm.txt +0 -147
- /solace_agent_mesh/assets/docs/assets/js/{main.f213fe0c.js.LICENSE.txt → main.d634009f.js.LICENSE.txt} +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/auth_utils.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/pagination.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/api}/response_utils.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/error_dto.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/exceptions}/exceptions.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/enums.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/timestamp_utils.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/types.py +0 -0
- /solace_agent_mesh/{gateway/http_sse/shared → shared/utils}/utils.py +0 -0
- {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-1.7.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""Centralized error handlers for Solace Agent Mesh."""
|
|
2
|
+
|
|
3
|
+
from typing import Tuple
|
|
4
|
+
from litellm.exceptions import BadRequestError
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# User-facing error messages
|
|
8
|
+
CONTEXT_LIMIT_ERROR_MESSAGE = (
|
|
9
|
+
"The conversation history has become too long for the AI model to process. "
|
|
10
|
+
"This can happen after extended conversations. "
|
|
11
|
+
"To continue, please start a new conversation."
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
DEFAULT_BAD_REQUEST_MESSAGE = (
|
|
15
|
+
"An unexpected error occurred during tool execution. "
|
|
16
|
+
"Please try your request again. If the problem persists, "
|
|
17
|
+
"contact an administrator."
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _is_context_limit_error(exception: Exception) -> bool:
|
|
22
|
+
"""
|
|
23
|
+
Detects if an exception is a context/token limit error from LiteLLM.
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
exception: The exception to check
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
True if the exception indicates a context limit error
|
|
30
|
+
"""
|
|
31
|
+
if not isinstance(exception, BadRequestError):
|
|
32
|
+
return False
|
|
33
|
+
|
|
34
|
+
error_str = str(exception).lower()
|
|
35
|
+
|
|
36
|
+
# Context limit error patterns from various LLM providers
|
|
37
|
+
context_limit_patterns = [
|
|
38
|
+
"too many tokens",
|
|
39
|
+
"expected maxlength:",
|
|
40
|
+
"input is too long",
|
|
41
|
+
"prompt is too long",
|
|
42
|
+
"prompt: length: 1..",
|
|
43
|
+
"too many input tokens",
|
|
44
|
+
]
|
|
45
|
+
|
|
46
|
+
return any(pattern in error_str for pattern in context_limit_patterns)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _get_user_friendly_error_message(exception: Exception) -> str:
|
|
50
|
+
"""
|
|
51
|
+
Returns a user-friendly error message for the given exception.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
exception: The exception to get a message for
|
|
55
|
+
|
|
56
|
+
Returns:
|
|
57
|
+
User-friendly error message string
|
|
58
|
+
"""
|
|
59
|
+
if _is_context_limit_error(exception):
|
|
60
|
+
return CONTEXT_LIMIT_ERROR_MESSAGE
|
|
61
|
+
|
|
62
|
+
if isinstance(exception, BadRequestError):
|
|
63
|
+
return f"Bad request: {exception}"
|
|
64
|
+
|
|
65
|
+
return DEFAULT_BAD_REQUEST_MESSAGE
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def get_error_message(
|
|
69
|
+
exception: BadRequestError,
|
|
70
|
+
) -> Tuple[str, bool]:
|
|
71
|
+
"""
|
|
72
|
+
Handles BadRequestError and returns error information.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
exception: The BadRequestError to handle
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
Tuple of (error_message, is_context_limit_error)
|
|
79
|
+
"""
|
|
80
|
+
is_context_limit = _is_context_limit_error(exception)
|
|
81
|
+
error_message = _get_user_friendly_error_message(exception)
|
|
82
|
+
|
|
83
|
+
return error_message, is_context_limit
|
|
@@ -23,3 +23,27 @@ class MessageSizeExceededError(Exception):
|
|
|
23
23
|
)
|
|
24
24
|
|
|
25
25
|
super().__init__(message)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class ComponentInitializationError(Exception):
|
|
29
|
+
"""Raised when a SAM component fails to initialize."""
|
|
30
|
+
|
|
31
|
+
def __init__(self, component_identifier: str, original_error: Exception, message: str = None):
|
|
32
|
+
"""Initialize the ComponentInitializationError.
|
|
33
|
+
|
|
34
|
+
Args:
|
|
35
|
+
component_identifier: The identifier of the component that failed to initialize.
|
|
36
|
+
original_error: The original exception that caused the failure.
|
|
37
|
+
message: Optional custom error message. If None, a default message
|
|
38
|
+
will be generated.
|
|
39
|
+
"""
|
|
40
|
+
self.component_identifier = component_identifier
|
|
41
|
+
self.original_error = original_error
|
|
42
|
+
|
|
43
|
+
if message is None:
|
|
44
|
+
message = (
|
|
45
|
+
f"Component {component_identifier} failed to initialize: "
|
|
46
|
+
f"{original_error}"
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
super().__init__(message)
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Common OAuth 2.0 components for Solace Agent Mesh.
|
|
2
|
+
|
|
3
|
+
This module provides pure OAuth 2.0 protocol implementations that can be
|
|
4
|
+
used across different components (LLM providers, A2A proxies, etc.) without
|
|
5
|
+
domain-specific logic.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from .oauth_client import OAuth2Client, OAuth2RetryClient
|
|
9
|
+
from .utils import calculate_expires_at, is_token_expired, validate_https_url
|
|
10
|
+
|
|
11
|
+
__all__ = [
|
|
12
|
+
"OAuth2Client",
|
|
13
|
+
"OAuth2RetryClient",
|
|
14
|
+
"calculate_expires_at",
|
|
15
|
+
"is_token_expired",
|
|
16
|
+
"validate_https_url",
|
|
17
|
+
]
|
|
@@ -0,0 +1,408 @@
|
|
|
1
|
+
"""Pure OAuth 2.0 protocol implementation.
|
|
2
|
+
|
|
3
|
+
This module provides stateless OAuth 2.0 flow implementations without any
|
|
4
|
+
caching, retry logic, or domain-specific behavior. It implements the core
|
|
5
|
+
OAuth 2.0 flows as defined in RFC 6749.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import asyncio
|
|
9
|
+
import logging
|
|
10
|
+
import random
|
|
11
|
+
from typing import Any, Dict, Optional, Union
|
|
12
|
+
|
|
13
|
+
import httpx
|
|
14
|
+
|
|
15
|
+
from .utils import calculate_expires_at
|
|
16
|
+
|
|
17
|
+
logger = logging.getLogger(__name__)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class OAuth2Client:
|
|
21
|
+
"""Pure OAuth 2.0 protocol implementation.
|
|
22
|
+
|
|
23
|
+
This class provides stateless OAuth 2.0 flow implementations without any
|
|
24
|
+
caching, retry logic, or domain-specific behavior. Each method makes a
|
|
25
|
+
single HTTP request to the token endpoint and returns the parsed response.
|
|
26
|
+
|
|
27
|
+
All OAuth 2.0 flows follow RFC 6749 specification.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
async def fetch_client_credentials_token(
|
|
31
|
+
self,
|
|
32
|
+
token_url: str,
|
|
33
|
+
client_id: str,
|
|
34
|
+
client_secret: str,
|
|
35
|
+
scope: Optional[str] = None,
|
|
36
|
+
verify: Union[bool, str] = True,
|
|
37
|
+
timeout: float = 30.0,
|
|
38
|
+
) -> Dict[str, Any]:
|
|
39
|
+
"""Execute OAuth 2.0 Client Credentials flow (RFC 6749 Section 4.4).
|
|
40
|
+
|
|
41
|
+
This flow is used for server-to-server authentication where the client
|
|
42
|
+
acts on its own behalf rather than on behalf of a user.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
token_url: OAuth 2.0 token endpoint URL
|
|
46
|
+
client_id: OAuth 2.0 client identifier
|
|
47
|
+
client_secret: OAuth 2.0 client secret
|
|
48
|
+
scope: Optional space-separated list of scopes
|
|
49
|
+
verify: SSL certificate verification (True, False, or path to CA bundle)
|
|
50
|
+
timeout: Request timeout in seconds
|
|
51
|
+
|
|
52
|
+
Returns:
|
|
53
|
+
Token response dictionary containing:
|
|
54
|
+
- access_token: The access token string
|
|
55
|
+
- expires_in: Token lifetime in seconds
|
|
56
|
+
- token_type: Token type (usually "Bearer")
|
|
57
|
+
- scope: Granted scopes (optional)
|
|
58
|
+
- expires_at: Unix timestamp when token expires (added by this method)
|
|
59
|
+
|
|
60
|
+
Raises:
|
|
61
|
+
httpx.HTTPStatusError: If the token request fails
|
|
62
|
+
ValueError: If the response is missing required fields
|
|
63
|
+
"""
|
|
64
|
+
payload = {
|
|
65
|
+
"grant_type": "client_credentials",
|
|
66
|
+
"client_id": client_id,
|
|
67
|
+
"client_secret": client_secret,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if scope:
|
|
71
|
+
payload["scope"] = scope
|
|
72
|
+
|
|
73
|
+
return await self._execute_token_request(
|
|
74
|
+
token_url=token_url,
|
|
75
|
+
payload=payload,
|
|
76
|
+
verify=verify,
|
|
77
|
+
timeout=timeout,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
async def fetch_authorization_code_token(
|
|
81
|
+
self,
|
|
82
|
+
token_url: str,
|
|
83
|
+
client_id: str,
|
|
84
|
+
client_secret: str,
|
|
85
|
+
code: str,
|
|
86
|
+
redirect_uri: str,
|
|
87
|
+
verify: Union[bool, str] = True,
|
|
88
|
+
timeout: float = 30.0,
|
|
89
|
+
) -> Dict[str, Any]:
|
|
90
|
+
"""Execute OAuth 2.0 Authorization Code flow (RFC 6749 Section 4.1).
|
|
91
|
+
|
|
92
|
+
This flow is used for user-delegated authentication where the application
|
|
93
|
+
acts on behalf of a user who has granted permission.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
token_url: OAuth 2.0 token endpoint URL
|
|
97
|
+
client_id: OAuth 2.0 client identifier
|
|
98
|
+
client_secret: OAuth 2.0 client secret
|
|
99
|
+
code: Authorization code received from authorization server
|
|
100
|
+
redirect_uri: Redirect URI used in authorization request (must match)
|
|
101
|
+
verify: SSL certificate verification (True, False, or path to CA bundle)
|
|
102
|
+
timeout: Request timeout in seconds
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
Token response dictionary containing:
|
|
106
|
+
- access_token: The access token string
|
|
107
|
+
- expires_in: Token lifetime in seconds
|
|
108
|
+
- refresh_token: Refresh token for obtaining new access tokens (optional)
|
|
109
|
+
- token_type: Token type (usually "Bearer")
|
|
110
|
+
- scope: Granted scopes (optional)
|
|
111
|
+
- expires_at: Unix timestamp when token expires (added by this method)
|
|
112
|
+
|
|
113
|
+
Raises:
|
|
114
|
+
httpx.HTTPStatusError: If the token request fails
|
|
115
|
+
ValueError: If the response is missing required fields
|
|
116
|
+
"""
|
|
117
|
+
payload = {
|
|
118
|
+
"grant_type": "authorization_code",
|
|
119
|
+
"code": code,
|
|
120
|
+
"redirect_uri": redirect_uri,
|
|
121
|
+
"client_id": client_id,
|
|
122
|
+
"client_secret": client_secret,
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return await self._execute_token_request(
|
|
126
|
+
token_url=token_url,
|
|
127
|
+
payload=payload,
|
|
128
|
+
verify=verify,
|
|
129
|
+
timeout=timeout,
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
async def fetch_refresh_token(
|
|
133
|
+
self,
|
|
134
|
+
token_url: str,
|
|
135
|
+
client_id: str,
|
|
136
|
+
client_secret: str,
|
|
137
|
+
refresh_token: str,
|
|
138
|
+
scope: Optional[str] = None,
|
|
139
|
+
verify: Union[bool, str] = True,
|
|
140
|
+
timeout: float = 30.0,
|
|
141
|
+
) -> Dict[str, Any]:
|
|
142
|
+
"""Execute OAuth 2.0 Refresh Token flow (RFC 6749 Section 6).
|
|
143
|
+
|
|
144
|
+
This flow is used to obtain a new access token using a refresh token,
|
|
145
|
+
without requiring user interaction.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
token_url: OAuth 2.0 token endpoint URL
|
|
149
|
+
client_id: OAuth 2.0 client identifier
|
|
150
|
+
client_secret: OAuth 2.0 client secret
|
|
151
|
+
refresh_token: The refresh token
|
|
152
|
+
scope: Optional space-separated list of scopes (must not exceed original grant)
|
|
153
|
+
verify: SSL certificate verification (True, False, or path to CA bundle)
|
|
154
|
+
timeout: Request timeout in seconds
|
|
155
|
+
|
|
156
|
+
Returns:
|
|
157
|
+
Token response dictionary containing:
|
|
158
|
+
- access_token: The new access token string
|
|
159
|
+
- expires_in: Token lifetime in seconds
|
|
160
|
+
- refresh_token: New refresh token (optional, may be same as input)
|
|
161
|
+
- token_type: Token type (usually "Bearer")
|
|
162
|
+
- scope: Granted scopes (optional)
|
|
163
|
+
- expires_at: Unix timestamp when token expires (added by this method)
|
|
164
|
+
|
|
165
|
+
Raises:
|
|
166
|
+
httpx.HTTPStatusError: If the token request fails
|
|
167
|
+
ValueError: If the response is missing required fields
|
|
168
|
+
"""
|
|
169
|
+
payload = {
|
|
170
|
+
"grant_type": "refresh_token",
|
|
171
|
+
"refresh_token": refresh_token,
|
|
172
|
+
"client_id": client_id,
|
|
173
|
+
"client_secret": client_secret,
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if scope:
|
|
177
|
+
payload["scope"] = scope
|
|
178
|
+
|
|
179
|
+
return await self._execute_token_request(
|
|
180
|
+
token_url=token_url,
|
|
181
|
+
payload=payload,
|
|
182
|
+
verify=verify,
|
|
183
|
+
timeout=timeout,
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
async def _execute_token_request(
|
|
187
|
+
self,
|
|
188
|
+
token_url: str,
|
|
189
|
+
payload: Dict[str, str],
|
|
190
|
+
verify: Union[bool, str],
|
|
191
|
+
timeout: float,
|
|
192
|
+
) -> Dict[str, Any]:
|
|
193
|
+
"""Execute a token request to the OAuth 2.0 token endpoint.
|
|
194
|
+
|
|
195
|
+
This is the core HTTP operation shared by all OAuth flows.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
token_url: OAuth 2.0 token endpoint URL
|
|
199
|
+
payload: Request payload (grant-specific parameters)
|
|
200
|
+
verify: SSL certificate verification
|
|
201
|
+
timeout: Request timeout in seconds
|
|
202
|
+
|
|
203
|
+
Returns:
|
|
204
|
+
Token response dictionary with added expires_at field
|
|
205
|
+
|
|
206
|
+
Raises:
|
|
207
|
+
httpx.HTTPStatusError: If the token request fails
|
|
208
|
+
ValueError: If the response is missing required fields
|
|
209
|
+
"""
|
|
210
|
+
headers = {
|
|
211
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
212
|
+
"Accept": "application/json",
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
async with httpx.AsyncClient(verify=verify) as client:
|
|
216
|
+
response = await client.post(
|
|
217
|
+
token_url,
|
|
218
|
+
data=payload,
|
|
219
|
+
headers=headers,
|
|
220
|
+
timeout=timeout,
|
|
221
|
+
)
|
|
222
|
+
response.raise_for_status()
|
|
223
|
+
|
|
224
|
+
token_data = response.json()
|
|
225
|
+
|
|
226
|
+
# Validate response contains required fields
|
|
227
|
+
if "access_token" not in token_data:
|
|
228
|
+
raise ValueError(
|
|
229
|
+
f"Token response missing 'access_token' field. "
|
|
230
|
+
f"Response keys: {list(token_data.keys())}"
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
# Add expiration timestamp for convenience
|
|
234
|
+
expires_in = token_data.get("expires_in", 3600) # Default 1 hour
|
|
235
|
+
token_data["expires_at"] = calculate_expires_at(expires_in)
|
|
236
|
+
|
|
237
|
+
return token_data
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
class OAuth2RetryClient:
|
|
241
|
+
"""OAuth 2.0 client with configurable retry logic.
|
|
242
|
+
|
|
243
|
+
This class wraps OAuth2Client and adds retry logic with exponential backoff
|
|
244
|
+
for handling transient failures. Retry behavior:
|
|
245
|
+
- 4xx errors (client errors): No retry - fail immediately
|
|
246
|
+
- 5xx errors (server errors): Retry with exponential backoff
|
|
247
|
+
- Network errors: Retry with exponential backoff
|
|
248
|
+
"""
|
|
249
|
+
|
|
250
|
+
def __init__(
|
|
251
|
+
self,
|
|
252
|
+
max_retries: int = 0,
|
|
253
|
+
backoff_base: float = 2.0,
|
|
254
|
+
backoff_jitter: bool = True,
|
|
255
|
+
):
|
|
256
|
+
"""Initialize the retry client.
|
|
257
|
+
|
|
258
|
+
Args:
|
|
259
|
+
max_retries: Maximum number of retry attempts (0 = no retries)
|
|
260
|
+
backoff_base: Base for exponential backoff (delay = base^attempt)
|
|
261
|
+
backoff_jitter: Whether to add random jitter to backoff delay
|
|
262
|
+
"""
|
|
263
|
+
self._base_client = OAuth2Client()
|
|
264
|
+
self._max_retries = max_retries
|
|
265
|
+
self._backoff_base = backoff_base
|
|
266
|
+
self._backoff_jitter = backoff_jitter
|
|
267
|
+
|
|
268
|
+
async def fetch_client_credentials_token(
|
|
269
|
+
self,
|
|
270
|
+
token_url: str,
|
|
271
|
+
client_id: str,
|
|
272
|
+
client_secret: str,
|
|
273
|
+
scope: Optional[str] = None,
|
|
274
|
+
verify: Union[bool, str] = True,
|
|
275
|
+
timeout: float = 30.0,
|
|
276
|
+
) -> Dict[str, Any]:
|
|
277
|
+
"""Execute Client Credentials flow with retry logic.
|
|
278
|
+
|
|
279
|
+
See OAuth2Client.fetch_client_credentials_token for parameter details.
|
|
280
|
+
"""
|
|
281
|
+
return await self._execute_with_retry(
|
|
282
|
+
self._base_client.fetch_client_credentials_token,
|
|
283
|
+
token_url=token_url,
|
|
284
|
+
client_id=client_id,
|
|
285
|
+
client_secret=client_secret,
|
|
286
|
+
scope=scope,
|
|
287
|
+
verify=verify,
|
|
288
|
+
timeout=timeout,
|
|
289
|
+
)
|
|
290
|
+
|
|
291
|
+
async def fetch_authorization_code_token(
|
|
292
|
+
self,
|
|
293
|
+
token_url: str,
|
|
294
|
+
client_id: str,
|
|
295
|
+
client_secret: str,
|
|
296
|
+
code: str,
|
|
297
|
+
redirect_uri: str,
|
|
298
|
+
verify: Union[bool, str] = True,
|
|
299
|
+
timeout: float = 30.0,
|
|
300
|
+
) -> Dict[str, Any]:
|
|
301
|
+
"""Execute Authorization Code flow with retry logic.
|
|
302
|
+
|
|
303
|
+
See OAuth2Client.fetch_authorization_code_token for parameter details.
|
|
304
|
+
"""
|
|
305
|
+
return await self._execute_with_retry(
|
|
306
|
+
self._base_client.fetch_authorization_code_token,
|
|
307
|
+
token_url=token_url,
|
|
308
|
+
client_id=client_id,
|
|
309
|
+
client_secret=client_secret,
|
|
310
|
+
code=code,
|
|
311
|
+
redirect_uri=redirect_uri,
|
|
312
|
+
verify=verify,
|
|
313
|
+
timeout=timeout,
|
|
314
|
+
)
|
|
315
|
+
|
|
316
|
+
async def fetch_refresh_token(
|
|
317
|
+
self,
|
|
318
|
+
token_url: str,
|
|
319
|
+
client_id: str,
|
|
320
|
+
client_secret: str,
|
|
321
|
+
refresh_token: str,
|
|
322
|
+
scope: Optional[str] = None,
|
|
323
|
+
verify: Union[bool, str] = True,
|
|
324
|
+
timeout: float = 30.0,
|
|
325
|
+
) -> Dict[str, Any]:
|
|
326
|
+
"""Execute Refresh Token flow with retry logic.
|
|
327
|
+
|
|
328
|
+
See OAuth2Client.fetch_refresh_token for parameter details.
|
|
329
|
+
"""
|
|
330
|
+
return await self._execute_with_retry(
|
|
331
|
+
self._base_client.fetch_refresh_token,
|
|
332
|
+
token_url=token_url,
|
|
333
|
+
client_id=client_id,
|
|
334
|
+
client_secret=client_secret,
|
|
335
|
+
refresh_token=refresh_token,
|
|
336
|
+
scope=scope,
|
|
337
|
+
verify=verify,
|
|
338
|
+
timeout=timeout,
|
|
339
|
+
)
|
|
340
|
+
|
|
341
|
+
async def _execute_with_retry(self, func, **kwargs) -> Dict[str, Any]:
|
|
342
|
+
"""Execute a function with retry logic.
|
|
343
|
+
|
|
344
|
+
Args:
|
|
345
|
+
func: Async function to execute
|
|
346
|
+
**kwargs: Arguments to pass to the function
|
|
347
|
+
|
|
348
|
+
Returns:
|
|
349
|
+
Result from the function
|
|
350
|
+
|
|
351
|
+
Raises:
|
|
352
|
+
Exception: Last exception if all retries are exhausted
|
|
353
|
+
"""
|
|
354
|
+
last_exception = None
|
|
355
|
+
|
|
356
|
+
for attempt in range(self._max_retries + 1):
|
|
357
|
+
try:
|
|
358
|
+
return await func(**kwargs)
|
|
359
|
+
|
|
360
|
+
except httpx.HTTPStatusError as e:
|
|
361
|
+
last_exception = e
|
|
362
|
+
# Don't retry on 4xx errors (client errors)
|
|
363
|
+
if 400 <= e.response.status_code < 500:
|
|
364
|
+
logger.error(
|
|
365
|
+
"OAuth token request failed with client error %d: %s",
|
|
366
|
+
e.response.status_code,
|
|
367
|
+
e.response.text,
|
|
368
|
+
)
|
|
369
|
+
raise
|
|
370
|
+
|
|
371
|
+
logger.warning(
|
|
372
|
+
"OAuth token request failed with status %d (attempt %d/%d): %s",
|
|
373
|
+
e.response.status_code,
|
|
374
|
+
attempt + 1,
|
|
375
|
+
self._max_retries + 1,
|
|
376
|
+
e.response.text,
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
except httpx.RequestError as e:
|
|
380
|
+
last_exception = e
|
|
381
|
+
logger.warning(
|
|
382
|
+
"OAuth token request failed (attempt %d/%d): %s",
|
|
383
|
+
attempt + 1,
|
|
384
|
+
self._max_retries + 1,
|
|
385
|
+
str(e),
|
|
386
|
+
)
|
|
387
|
+
|
|
388
|
+
except Exception as e:
|
|
389
|
+
last_exception = e
|
|
390
|
+
logger.error("Unexpected error during OAuth token fetch: %s", str(e))
|
|
391
|
+
raise
|
|
392
|
+
|
|
393
|
+
# Exponential backoff with optional jitter
|
|
394
|
+
if attempt < self._max_retries:
|
|
395
|
+
delay = self._backoff_base**attempt
|
|
396
|
+
if self._backoff_jitter:
|
|
397
|
+
delay += random.uniform(0, 1)
|
|
398
|
+
logger.info("Retrying OAuth token request in %.2f seconds", delay)
|
|
399
|
+
await asyncio.sleep(delay)
|
|
400
|
+
|
|
401
|
+
# All retries exhausted
|
|
402
|
+
logger.error(
|
|
403
|
+
"OAuth token request failed after %d attempts", self._max_retries + 1
|
|
404
|
+
)
|
|
405
|
+
if last_exception:
|
|
406
|
+
raise last_exception
|
|
407
|
+
else:
|
|
408
|
+
raise RuntimeError("OAuth token request failed after all retries")
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"""Utility functions for OAuth 2.0 operations."""
|
|
2
|
+
|
|
3
|
+
import time
|
|
4
|
+
from urllib.parse import urlparse
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def validate_https_url(url: str) -> None:
|
|
8
|
+
"""Validate that a URL uses HTTPS scheme.
|
|
9
|
+
|
|
10
|
+
OAuth 2.0 requires HTTPS for security when transmitting credentials.
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
url: The URL to validate
|
|
14
|
+
|
|
15
|
+
Raises:
|
|
16
|
+
ValueError: If the URL does not use HTTPS scheme
|
|
17
|
+
"""
|
|
18
|
+
parsed_url = urlparse(url)
|
|
19
|
+
if parsed_url.scheme != "https":
|
|
20
|
+
raise ValueError(
|
|
21
|
+
f"OAuth 2.0 URLs must use HTTPS for security. "
|
|
22
|
+
f"Got scheme: {parsed_url.scheme}"
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def calculate_expires_at(expires_in: int) -> float:
|
|
27
|
+
"""Calculate expiration timestamp from expires_in seconds.
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
expires_in: Number of seconds until token expires
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
Unix timestamp (float) when the token will expire
|
|
34
|
+
"""
|
|
35
|
+
return time.time() + expires_in
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def is_token_expired(expires_at: float, buffer_seconds: int = 0) -> bool:
|
|
39
|
+
"""Check if a token is expired or will expire within buffer time.
|
|
40
|
+
|
|
41
|
+
Args:
|
|
42
|
+
expires_at: Unix timestamp when token expires
|
|
43
|
+
buffer_seconds: Optional buffer to consider token expired early
|
|
44
|
+
(useful for proactive refresh)
|
|
45
|
+
|
|
46
|
+
Returns:
|
|
47
|
+
True if token is expired or within buffer time of expiring
|
|
48
|
+
"""
|
|
49
|
+
current_time = time.time()
|
|
50
|
+
return current_time >= (expires_at - buffer_seconds)
|