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,74 @@
|
|
|
1
|
+
# ADK Database Schema Migrations
|
|
2
|
+
|
|
3
|
+
This directory contains Alembic migrations for Google ADK database schema compatibility.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
Migrations are automatically executed on agent startup when using SQL session services. This ensures your database schema stays compatible with the installed version of Google ADK.
|
|
8
|
+
|
|
9
|
+
## How It Works
|
|
10
|
+
|
|
11
|
+
1. **Automatic Migration**: When an agent starts with `session_service.type: sql`, the migration system automatically runs
|
|
12
|
+
2. **Schema Detection**: Alembic compares ADK's model definitions against your actual database schema
|
|
13
|
+
3. **Safe Updates**: Only missing columns/tables are added - existing data is never modified or deleted
|
|
14
|
+
4. **Version Tracking**: Migration history is tracked in the `alembic_version` table in your database
|
|
15
|
+
|
|
16
|
+
## Migration Files
|
|
17
|
+
|
|
18
|
+
Migrations are stored in the `versions/` subdirectory:
|
|
19
|
+
- Each file represents a specific schema change
|
|
20
|
+
- Files are named with revision ID + description
|
|
21
|
+
- Migrations run in chronological order
|
|
22
|
+
|
|
23
|
+
## Creating New Migrations
|
|
24
|
+
|
|
25
|
+
When Google releases a new ADK version with schema changes:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# Navigate to this directory
|
|
29
|
+
cd src/solace_agent_mesh/agent/adk
|
|
30
|
+
|
|
31
|
+
# Generate migration (auto-detects schema differences)
|
|
32
|
+
alembic revision --autogenerate -m "Update for ADK x.x.x"
|
|
33
|
+
|
|
34
|
+
# Review the generated migration in versions/
|
|
35
|
+
# Then commit it to version control
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Official ADK Resources
|
|
39
|
+
|
|
40
|
+
**Example Migration:**
|
|
41
|
+
- https://github.com/google/adk-python/tree/main/contributing/samples/migrate_session_db
|
|
42
|
+
|
|
43
|
+
**Migration Script:**
|
|
44
|
+
```bash
|
|
45
|
+
curl -fsSL https://raw.githubusercontent.com/google/adk-python/main/scripts/db_migration.sh
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**Documentation:**
|
|
49
|
+
- ADK Repository: https://github.com/google/adk-python
|
|
50
|
+
- ADK Releases: https://github.com/google/adk-python/releases
|
|
51
|
+
|
|
52
|
+
## Troubleshooting
|
|
53
|
+
|
|
54
|
+
### Manual Migration
|
|
55
|
+
|
|
56
|
+
To run migrations manually:
|
|
57
|
+
```bash
|
|
58
|
+
cd src/solace_agent_mesh/agent/adk
|
|
59
|
+
alembic upgrade head
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### View Migration Status
|
|
63
|
+
|
|
64
|
+
```bash
|
|
65
|
+
cd src/solace_agent_mesh/agent/adk
|
|
66
|
+
alembic current
|
|
67
|
+
alembic history
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Schema Source
|
|
71
|
+
|
|
72
|
+
All schema definitions come from:
|
|
73
|
+
- Module: `google.adk.sessions.database_session_service`
|
|
74
|
+
- Models: `StorageSession`, `StorageEvent`, `StorageAppState`, `StorageUserState`
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
from sqlalchemy import engine_from_config
|
|
2
|
+
from sqlalchemy import pool
|
|
3
|
+
|
|
4
|
+
from alembic import context
|
|
5
|
+
|
|
6
|
+
# this is the Alembic Config object, which provides
|
|
7
|
+
# access to the values within the .ini file in use.
|
|
8
|
+
config = context.config
|
|
9
|
+
|
|
10
|
+
# add your model's MetaData object here
|
|
11
|
+
# for 'autogenerate' support
|
|
12
|
+
from google.adk.sessions.database_session_service import Base
|
|
13
|
+
# target_metadata = mymodel.Base.metadata
|
|
14
|
+
target_metadata = Base.metadata
|
|
15
|
+
|
|
16
|
+
# other values from the config, defined by the needs of env.py,
|
|
17
|
+
# can be acquired:
|
|
18
|
+
# my_important_option = config.get_main_option("my_important_option")
|
|
19
|
+
# ... etc.
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def run_migrations_offline() -> None:
|
|
23
|
+
"""Run migrations in 'offline' mode.
|
|
24
|
+
|
|
25
|
+
This configures the context with just a URL
|
|
26
|
+
and not an Engine, though an Engine is acceptable
|
|
27
|
+
here as well. By skipping the Engine creation
|
|
28
|
+
we don't even need a DBAPI to be available.
|
|
29
|
+
|
|
30
|
+
Calls to context.execute() here emit the given string to the
|
|
31
|
+
script output.
|
|
32
|
+
|
|
33
|
+
"""
|
|
34
|
+
url = config.get_main_option("sqlalchemy.url")
|
|
35
|
+
context.configure(
|
|
36
|
+
url=url,
|
|
37
|
+
target_metadata=target_metadata,
|
|
38
|
+
literal_binds=True,
|
|
39
|
+
dialect_opts={"paramstyle": "named"},
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
with context.begin_transaction():
|
|
43
|
+
context.run_migrations()
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def run_migrations_online() -> None:
|
|
47
|
+
"""Run migrations in 'online' mode, using existing connection.
|
|
48
|
+
|
|
49
|
+
In this scenario we need to create an Engine
|
|
50
|
+
and associate a connection with the context.
|
|
51
|
+
|
|
52
|
+
"""
|
|
53
|
+
# Check if we have an engine passed from the calling code
|
|
54
|
+
connectable = config.attributes.get('connection', None)
|
|
55
|
+
if connectable is None:
|
|
56
|
+
# Fallback: create engine from config (for CLI usage)
|
|
57
|
+
from sqlalchemy import engine_from_config
|
|
58
|
+
connectable = engine_from_config(
|
|
59
|
+
config.get_section(config.config_ini_section, {}),
|
|
60
|
+
prefix="sqlalchemy.",
|
|
61
|
+
poolclass=pool.NullPool,
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
with connectable.connect() as connection:
|
|
65
|
+
context.configure(
|
|
66
|
+
connection=connection,
|
|
67
|
+
target_metadata=target_metadata
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
with context.begin_transaction():
|
|
71
|
+
context.run_migrations()
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
if context.is_offline_mode():
|
|
75
|
+
run_migrations_offline()
|
|
76
|
+
else:
|
|
77
|
+
run_migrations_online()
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"""${message}
|
|
2
|
+
|
|
3
|
+
Revision ID: ${up_revision}
|
|
4
|
+
Revises: ${down_revision | comma,n}
|
|
5
|
+
Create Date: ${create_date}
|
|
6
|
+
|
|
7
|
+
"""
|
|
8
|
+
from typing import Sequence, Union
|
|
9
|
+
|
|
10
|
+
from alembic import op
|
|
11
|
+
import sqlalchemy as sa
|
|
12
|
+
${imports if imports else ""}
|
|
13
|
+
|
|
14
|
+
# revision identifiers, used by Alembic.
|
|
15
|
+
revision: str = ${repr(up_revision)}
|
|
16
|
+
down_revision: Union[str, Sequence[str], None] = ${repr(down_revision)}
|
|
17
|
+
branch_labels: Union[str, Sequence[str], None] = ${repr(branch_labels)}
|
|
18
|
+
depends_on: Union[str, Sequence[str], None] = ${repr(depends_on)}
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def upgrade() -> None:
|
|
22
|
+
"""Upgrade schema."""
|
|
23
|
+
${upgrades if upgrades else "pass"}
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def downgrade() -> None:
|
|
27
|
+
"""Downgrade schema."""
|
|
28
|
+
${downgrades if downgrades else "pass"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import google.adk.sessions.database_session_service
|
|
2
|
+
"""ADK session DB upgrade
|
|
3
|
+
|
|
4
|
+
Revision ID: e2902798564d
|
|
5
|
+
Revises:
|
|
6
|
+
Create Date: 2025-11-12 10:59:41.286752
|
|
7
|
+
|
|
8
|
+
"""
|
|
9
|
+
from typing import Sequence, Union
|
|
10
|
+
|
|
11
|
+
from alembic import op
|
|
12
|
+
import sqlalchemy as sa
|
|
13
|
+
from sqlalchemy import inspect
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
# revision identifiers, used by Alembic.
|
|
17
|
+
revision: str = 'e2902798564d'
|
|
18
|
+
down_revision: Union[str, Sequence[str], None] = None
|
|
19
|
+
branch_labels: Union[str, Sequence[str], None] = None
|
|
20
|
+
depends_on: Union[str, Sequence[str], None] = None
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def column_exists(table_name: str, column_name: str) -> bool:
|
|
24
|
+
"""Check if a column exists in a table."""
|
|
25
|
+
bind = op.get_bind()
|
|
26
|
+
inspector = inspect(bind)
|
|
27
|
+
columns = [col['name'] for col in inspector.get_columns(table_name)]
|
|
28
|
+
return column_name in columns
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def upgrade() -> None:
|
|
32
|
+
"""Upgrade schema."""
|
|
33
|
+
if not column_exists('events', 'custom_metadata'):
|
|
34
|
+
op.add_column('events', sa.Column('custom_metadata', google.adk.sessions.database_session_service.DynamicJSON(), nullable=True))
|
|
35
|
+
|
|
36
|
+
if not column_exists('events', 'usage_metadata'):
|
|
37
|
+
op.add_column('events', sa.Column('usage_metadata', google.adk.sessions.database_session_service.DynamicJSON(), nullable=True))
|
|
38
|
+
|
|
39
|
+
if not column_exists('events', 'citation_metadata'):
|
|
40
|
+
op.add_column('events', sa.Column('citation_metadata', google.adk.sessions.database_session_service.DynamicJSON(), nullable=True))
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
def downgrade() -> None:
|
|
44
|
+
"""Downgrade schema."""
|
|
45
|
+
if column_exists('events', 'citation_metadata'):
|
|
46
|
+
op.drop_column('events', 'citation_metadata')
|
|
47
|
+
|
|
48
|
+
if column_exists('events', 'usage_metadata'):
|
|
49
|
+
op.drop_column('events', 'usage_metadata')
|
|
50
|
+
|
|
51
|
+
if column_exists('events', 'custom_metadata'):
|
|
52
|
+
op.drop_column('events', 'custom_metadata')
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# A generic, single database configuration.
|
|
2
|
+
|
|
3
|
+
[alembic]
|
|
4
|
+
# path to migration scripts.
|
|
5
|
+
# this is typically a path given in POSIX (e.g. forward slashes)
|
|
6
|
+
# format, relative to the token %(here)s which refers to the location of this
|
|
7
|
+
# ini file
|
|
8
|
+
script_location = %(here)s/alembic
|
|
9
|
+
|
|
10
|
+
# template used to generate migration file names; The default value is %%(rev)s_%%(slug)s
|
|
11
|
+
# Uncomment the line below if you want the files to be prepended with date and time
|
|
12
|
+
# see https://alembic.sqlalchemy.org/en/latest/tutorial.html#editing-the-ini-file
|
|
13
|
+
# for all available tokens
|
|
14
|
+
# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s
|
|
15
|
+
|
|
16
|
+
# sys.path path, will be prepended to sys.path if present.
|
|
17
|
+
# defaults to the current working directory. for multiple paths, the path separator
|
|
18
|
+
# is defined by "path_separator" below.
|
|
19
|
+
prepend_sys_path = .
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
# timezone to use when rendering the date within the migration file
|
|
23
|
+
# as well as the filename.
|
|
24
|
+
# If specified, requires the python>=3.9 or backports.zoneinfo library and tzdata library.
|
|
25
|
+
# Any required deps can installed by adding `alembic[tz]` to the pip requirements
|
|
26
|
+
# string value is passed to ZoneInfo()
|
|
27
|
+
# leave blank for localtime
|
|
28
|
+
# timezone =
|
|
29
|
+
|
|
30
|
+
# max length of characters to apply to the "slug" field
|
|
31
|
+
# truncate_slug_length = 40
|
|
32
|
+
|
|
33
|
+
# set to 'true' to run the environment during
|
|
34
|
+
# the 'revision' command, regardless of autogenerate
|
|
35
|
+
# revision_environment = false
|
|
36
|
+
|
|
37
|
+
# set to 'true' to allow .pyc and .pyo files without
|
|
38
|
+
# a source .py file to be detected as revisions in the
|
|
39
|
+
# versions/ directory
|
|
40
|
+
# sourceless = false
|
|
41
|
+
|
|
42
|
+
# version location specification; This defaults
|
|
43
|
+
# to <script_location>/versions. When using multiple version
|
|
44
|
+
# directories, initial revisions must be specified with --version-path.
|
|
45
|
+
# The path separator used here should be the separator specified by "path_separator"
|
|
46
|
+
# below.
|
|
47
|
+
# version_locations = %(here)s/bar:%(here)s/bat:%(here)s/alembic/versions
|
|
48
|
+
|
|
49
|
+
# path_separator; This indicates what character is used to split lists of file
|
|
50
|
+
# paths, including version_locations and prepend_sys_path within configparser
|
|
51
|
+
# files such as alembic.ini.
|
|
52
|
+
# The default rendered in new alembic.ini files is "os", which uses os.pathsep
|
|
53
|
+
# to provide os-dependent path splitting.
|
|
54
|
+
#
|
|
55
|
+
# Note that in order to support legacy alembic.ini files, this default does NOT
|
|
56
|
+
# take place if path_separator is not present in alembic.ini. If this
|
|
57
|
+
# option is omitted entirely, fallback logic is as follows:
|
|
58
|
+
#
|
|
59
|
+
# 1. Parsing of the version_locations option falls back to using the legacy
|
|
60
|
+
# "version_path_separator" key, which if absent then falls back to the legacy
|
|
61
|
+
# behavior of splitting on spaces and/or commas.
|
|
62
|
+
# 2. Parsing of the prepend_sys_path option falls back to the legacy
|
|
63
|
+
# behavior of splitting on spaces, commas, or colons.
|
|
64
|
+
#
|
|
65
|
+
# Valid values for path_separator are:
|
|
66
|
+
#
|
|
67
|
+
# path_separator = :
|
|
68
|
+
# path_separator = ;
|
|
69
|
+
# path_separator = space
|
|
70
|
+
# path_separator = newline
|
|
71
|
+
#
|
|
72
|
+
# Use os.pathsep. Default configuration used for new projects.
|
|
73
|
+
path_separator = os
|
|
74
|
+
|
|
75
|
+
# set to 'true' to search source files recursively
|
|
76
|
+
# in each "version_locations" directory
|
|
77
|
+
# new in Alembic version 1.10
|
|
78
|
+
# recursive_version_locations = false
|
|
79
|
+
|
|
80
|
+
# the output encoding used when revision files
|
|
81
|
+
# are written from script.py.mako
|
|
82
|
+
# output_encoding = utf-8
|
|
83
|
+
|
|
84
|
+
# database URL. This is consumed by the user-maintained env.py script only.
|
|
85
|
+
# other means of configuring database URLs may be customized within the env.py
|
|
86
|
+
# file.
|
|
87
|
+
# Note: This will be set programmatically at runtime
|
|
88
|
+
sqlalchemy.url =
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
[post_write_hooks]
|
|
92
|
+
# post_write_hooks defines scripts or Python functions that are run
|
|
93
|
+
# on newly generated revision scripts. See the documentation for further
|
|
94
|
+
# detail and examples
|
|
95
|
+
|
|
96
|
+
# format using "black" - use the console_scripts runner, against the "black" entrypoint
|
|
97
|
+
# hooks = black
|
|
98
|
+
# black.type = console_scripts
|
|
99
|
+
# black.entrypoint = black
|
|
100
|
+
# black.options = -l 79 REVISION_SCRIPT_FILENAME
|
|
101
|
+
|
|
102
|
+
# lint with attempts to fix using "ruff" - use the module runner, against the "ruff" module
|
|
103
|
+
# hooks = ruff
|
|
104
|
+
# ruff.type = module
|
|
105
|
+
# ruff.module = ruff
|
|
106
|
+
# ruff.options = check --fix REVISION_SCRIPT_FILENAME
|
|
107
|
+
|
|
108
|
+
# Alternatively, use the exec runner to execute a binary found on your PATH
|
|
109
|
+
# hooks = ruff
|
|
110
|
+
# ruff.type = exec
|
|
111
|
+
# ruff.executable = ruff
|
|
112
|
+
# ruff.options = check --fix REVISION_SCRIPT_FILENAME
|
|
@@ -10,6 +10,7 @@ import shutil
|
|
|
10
10
|
import unicodedata
|
|
11
11
|
|
|
12
12
|
from google.adk.artifacts import BaseArtifactService
|
|
13
|
+
from google.adk.artifacts.base_artifact_service import ArtifactVersion
|
|
13
14
|
from google.genai import types as adk_types
|
|
14
15
|
from typing_extensions import override
|
|
15
16
|
|
|
@@ -372,6 +373,169 @@ class FilesystemArtifactService(BaseArtifactService):
|
|
|
372
373
|
logger.debug("%sFound versions: %s", log_prefix, sorted_versions)
|
|
373
374
|
return sorted_versions
|
|
374
375
|
|
|
376
|
+
@override
|
|
377
|
+
async def list_artifact_versions(
|
|
378
|
+
self,
|
|
379
|
+
*,
|
|
380
|
+
app_name: str,
|
|
381
|
+
user_id: str,
|
|
382
|
+
filename: str,
|
|
383
|
+
session_id: str,
|
|
384
|
+
) -> list[ArtifactVersion]:
|
|
385
|
+
"""Lists all versions and their metadata for a specific artifact."""
|
|
386
|
+
log_prefix = f"[FSArtifact:ListArtifactVersions:{filename}] "
|
|
387
|
+
filename = self._normalize_filename_unicode(filename)
|
|
388
|
+
artifact_dir = self._get_artifact_dir(app_name, user_id, session_id, filename)
|
|
389
|
+
artifact_versions = []
|
|
390
|
+
|
|
391
|
+
if not await asyncio.to_thread(os.path.isdir, artifact_dir):
|
|
392
|
+
logger.debug("%sArtifact directory not found: %s", log_prefix, artifact_dir)
|
|
393
|
+
return []
|
|
394
|
+
|
|
395
|
+
try:
|
|
396
|
+
for item in await asyncio.to_thread(os.listdir, artifact_dir):
|
|
397
|
+
item_path = os.path.join(artifact_dir, item)
|
|
398
|
+
if await asyncio.to_thread(os.path.isfile, item_path) and item.isdigit():
|
|
399
|
+
version_num = int(item)
|
|
400
|
+
version_path = self._get_version_path(artifact_dir, version_num)
|
|
401
|
+
metadata_path = self._get_metadata_path(artifact_dir, version_num)
|
|
402
|
+
|
|
403
|
+
# Read metadata
|
|
404
|
+
try:
|
|
405
|
+
|
|
406
|
+
def _read_metadata():
|
|
407
|
+
with open(metadata_path, encoding="utf-8") as f:
|
|
408
|
+
return json.load(f)
|
|
409
|
+
|
|
410
|
+
metadata = await asyncio.to_thread(_read_metadata)
|
|
411
|
+
mime_type = metadata.get("mime_type", "application/octet-stream")
|
|
412
|
+
|
|
413
|
+
# Get file creation time
|
|
414
|
+
stat_info = await asyncio.to_thread(os.stat, version_path)
|
|
415
|
+
create_time = stat_info.st_ctime
|
|
416
|
+
|
|
417
|
+
# Create ArtifactVersion object
|
|
418
|
+
artifact_version = ArtifactVersion(
|
|
419
|
+
version=version_num,
|
|
420
|
+
canonical_uri=f"file://{version_path}",
|
|
421
|
+
mime_type=mime_type,
|
|
422
|
+
create_time=create_time,
|
|
423
|
+
custom_metadata={},
|
|
424
|
+
)
|
|
425
|
+
artifact_versions.append(artifact_version)
|
|
426
|
+
|
|
427
|
+
except (OSError, json.JSONDecodeError) as e:
|
|
428
|
+
logger.warning(
|
|
429
|
+
"%sFailed to read metadata for version %d: %s",
|
|
430
|
+
log_prefix,
|
|
431
|
+
version_num,
|
|
432
|
+
e,
|
|
433
|
+
)
|
|
434
|
+
continue
|
|
435
|
+
|
|
436
|
+
except OSError as e:
|
|
437
|
+
logger.error(
|
|
438
|
+
"%sError listing versions in directory '%s': %s",
|
|
439
|
+
log_prefix,
|
|
440
|
+
artifact_dir,
|
|
441
|
+
e,
|
|
442
|
+
)
|
|
443
|
+
return []
|
|
444
|
+
|
|
445
|
+
# Sort by version number
|
|
446
|
+
artifact_versions.sort(key=lambda av: av.version)
|
|
447
|
+
logger.debug("%sFound %d artifact versions", log_prefix, len(artifact_versions))
|
|
448
|
+
return artifact_versions
|
|
449
|
+
|
|
450
|
+
@override
|
|
451
|
+
async def get_artifact_version(
|
|
452
|
+
self,
|
|
453
|
+
*,
|
|
454
|
+
app_name: str,
|
|
455
|
+
user_id: str,
|
|
456
|
+
filename: str,
|
|
457
|
+
session_id: str,
|
|
458
|
+
version: int | None = None,
|
|
459
|
+
) -> ArtifactVersion | None:
|
|
460
|
+
"""Gets the metadata for a specific version of an artifact."""
|
|
461
|
+
log_prefix = f"[FSArtifact:GetArtifactVersion:{filename}] "
|
|
462
|
+
filename = self._normalize_filename_unicode(filename)
|
|
463
|
+
artifact_dir = self._get_artifact_dir(app_name, user_id, session_id, filename)
|
|
464
|
+
|
|
465
|
+
if not await asyncio.to_thread(os.path.isdir, artifact_dir):
|
|
466
|
+
logger.debug("%sArtifact directory not found: %s", log_prefix, artifact_dir)
|
|
467
|
+
return None
|
|
468
|
+
|
|
469
|
+
# Determine which version to load
|
|
470
|
+
load_version = version
|
|
471
|
+
if load_version is None:
|
|
472
|
+
versions = await self.list_versions(
|
|
473
|
+
app_name=app_name,
|
|
474
|
+
user_id=user_id,
|
|
475
|
+
session_id=session_id,
|
|
476
|
+
filename=filename,
|
|
477
|
+
)
|
|
478
|
+
if not versions:
|
|
479
|
+
logger.debug("%sNo versions found for artifact.", log_prefix)
|
|
480
|
+
return None
|
|
481
|
+
load_version = max(versions)
|
|
482
|
+
logger.debug("%sGetting latest version: %d", log_prefix, load_version)
|
|
483
|
+
else:
|
|
484
|
+
logger.debug("%sGetting specified version: %d", log_prefix, load_version)
|
|
485
|
+
|
|
486
|
+
version_path = self._get_version_path(artifact_dir, load_version)
|
|
487
|
+
metadata_path = self._get_metadata_path(artifact_dir, load_version)
|
|
488
|
+
|
|
489
|
+
if not await asyncio.to_thread(
|
|
490
|
+
os.path.exists, version_path
|
|
491
|
+
) or not await asyncio.to_thread(os.path.exists, metadata_path):
|
|
492
|
+
logger.warning(
|
|
493
|
+
"%sData or metadata file missing for version %d.",
|
|
494
|
+
log_prefix,
|
|
495
|
+
load_version,
|
|
496
|
+
)
|
|
497
|
+
return None
|
|
498
|
+
|
|
499
|
+
try:
|
|
500
|
+
# Read metadata
|
|
501
|
+
def _read_metadata():
|
|
502
|
+
with open(metadata_path, encoding="utf-8") as f:
|
|
503
|
+
return json.load(f)
|
|
504
|
+
|
|
505
|
+
metadata = await asyncio.to_thread(_read_metadata)
|
|
506
|
+
mime_type = metadata.get("mime_type", "application/octet-stream")
|
|
507
|
+
|
|
508
|
+
# Get file creation time
|
|
509
|
+
stat_info = await asyncio.to_thread(os.stat, version_path)
|
|
510
|
+
create_time = stat_info.st_ctime
|
|
511
|
+
|
|
512
|
+
# Create and return ArtifactVersion object
|
|
513
|
+
artifact_version = ArtifactVersion(
|
|
514
|
+
version=load_version,
|
|
515
|
+
canonical_uri=f"file://{version_path}",
|
|
516
|
+
mime_type=mime_type,
|
|
517
|
+
create_time=create_time,
|
|
518
|
+
custom_metadata={},
|
|
519
|
+
)
|
|
520
|
+
|
|
521
|
+
logger.info(
|
|
522
|
+
"%sRetrieved metadata for artifact '%s' version %d",
|
|
523
|
+
log_prefix,
|
|
524
|
+
filename,
|
|
525
|
+
load_version,
|
|
526
|
+
)
|
|
527
|
+
return artifact_version
|
|
528
|
+
|
|
529
|
+
except (OSError, json.JSONDecodeError) as e:
|
|
530
|
+
logger.error(
|
|
531
|
+
"%sFailed to get metadata for artifact '%s' version %d: %s",
|
|
532
|
+
log_prefix,
|
|
533
|
+
filename,
|
|
534
|
+
load_version,
|
|
535
|
+
e,
|
|
536
|
+
)
|
|
537
|
+
return None
|
|
538
|
+
|
|
375
539
|
def _normalize_filename_unicode(self, filename: str) -> str:
|
|
376
540
|
"""
|
|
377
541
|
Normalizes Unicode characters in a filename to their standard form.
|
|
@@ -10,6 +10,7 @@ import boto3
|
|
|
10
10
|
from botocore.client import BaseClient
|
|
11
11
|
from botocore.exceptions import BotoCoreError, ClientError, NoCredentialsError
|
|
12
12
|
from google.adk.artifacts import BaseArtifactService
|
|
13
|
+
from google.adk.artifacts.base_artifact_service import ArtifactVersion
|
|
13
14
|
from google.genai import types as adk_types
|
|
14
15
|
from typing_extensions import override
|
|
15
16
|
|
|
@@ -444,3 +445,165 @@ class S3ArtifactService(BaseArtifactService):
|
|
|
444
445
|
sorted_versions = sorted(versions)
|
|
445
446
|
logger.debug("%sFound versions: %s", log_prefix, sorted_versions)
|
|
446
447
|
return sorted_versions
|
|
448
|
+
|
|
449
|
+
@override
|
|
450
|
+
async def list_artifact_versions(
|
|
451
|
+
self,
|
|
452
|
+
*,
|
|
453
|
+
app_name: str,
|
|
454
|
+
user_id: str,
|
|
455
|
+
filename: str,
|
|
456
|
+
session_id: str,
|
|
457
|
+
) -> list[ArtifactVersion]:
|
|
458
|
+
"""Lists all versions and their metadata for a specific artifact."""
|
|
459
|
+
log_prefix = f"[S3Artifact:ListArtifactVersions:{filename}] "
|
|
460
|
+
filename = self._normalize_filename_unicode(filename)
|
|
461
|
+
app_name = app_name.strip('/')
|
|
462
|
+
|
|
463
|
+
# Get the prefix for this specific artifact (without version)
|
|
464
|
+
prefix = self._get_object_key(app_name, user_id, session_id, filename, "")
|
|
465
|
+
artifact_versions = []
|
|
466
|
+
|
|
467
|
+
try:
|
|
468
|
+
|
|
469
|
+
def _list_objects():
|
|
470
|
+
paginator = self.s3.get_paginator("list_objects_v2")
|
|
471
|
+
return paginator.paginate(Bucket=self.bucket_name, Prefix=prefix)
|
|
472
|
+
|
|
473
|
+
pages = await asyncio.to_thread(_list_objects)
|
|
474
|
+
for page in pages:
|
|
475
|
+
for obj in page.get("Contents", []):
|
|
476
|
+
parts = obj["Key"].split("/")
|
|
477
|
+
if len(parts) >= 5: # scope/user/session_or_user/filename/version
|
|
478
|
+
try:
|
|
479
|
+
version_num = int(parts[4])
|
|
480
|
+
|
|
481
|
+
# Get object metadata
|
|
482
|
+
def _head_object():
|
|
483
|
+
return self.s3.head_object(
|
|
484
|
+
Bucket=self.bucket_name, Key=obj["Key"]
|
|
485
|
+
)
|
|
486
|
+
|
|
487
|
+
metadata_response = await asyncio.to_thread(_head_object)
|
|
488
|
+
|
|
489
|
+
# Extract information
|
|
490
|
+
mime_type = metadata_response.get(
|
|
491
|
+
"ContentType", "application/octet-stream"
|
|
492
|
+
)
|
|
493
|
+
# S3 LastModified is a datetime object, convert to timestamp
|
|
494
|
+
create_time = obj.get("LastModified").timestamp()
|
|
495
|
+
|
|
496
|
+
# Create ArtifactVersion object
|
|
497
|
+
artifact_version = ArtifactVersion(
|
|
498
|
+
version=version_num,
|
|
499
|
+
canonical_uri=f"s3://{self.bucket_name}/{obj['Key']}",
|
|
500
|
+
mime_type=mime_type,
|
|
501
|
+
create_time=create_time,
|
|
502
|
+
custom_metadata={},
|
|
503
|
+
)
|
|
504
|
+
artifact_versions.append(artifact_version)
|
|
505
|
+
|
|
506
|
+
except (ValueError, ClientError) as e:
|
|
507
|
+
logger.warning(
|
|
508
|
+
"%sFailed to process version from key '%s': %s",
|
|
509
|
+
log_prefix,
|
|
510
|
+
obj["Key"],
|
|
511
|
+
e,
|
|
512
|
+
)
|
|
513
|
+
continue
|
|
514
|
+
|
|
515
|
+
except ClientError as e:
|
|
516
|
+
logger.error(
|
|
517
|
+
"%sError listing versions with prefix '%s': %s",
|
|
518
|
+
log_prefix,
|
|
519
|
+
prefix,
|
|
520
|
+
e,
|
|
521
|
+
)
|
|
522
|
+
return []
|
|
523
|
+
|
|
524
|
+
# Sort by version number
|
|
525
|
+
artifact_versions.sort(key=lambda av: av.version)
|
|
526
|
+
logger.debug("%sFound %d artifact versions", log_prefix, len(artifact_versions))
|
|
527
|
+
return artifact_versions
|
|
528
|
+
|
|
529
|
+
@override
|
|
530
|
+
async def get_artifact_version(
|
|
531
|
+
self,
|
|
532
|
+
*,
|
|
533
|
+
app_name: str,
|
|
534
|
+
user_id: str,
|
|
535
|
+
filename: str,
|
|
536
|
+
session_id: str,
|
|
537
|
+
version: int | None = None,
|
|
538
|
+
) -> ArtifactVersion | None:
|
|
539
|
+
"""Gets the metadata for a specific version of an artifact."""
|
|
540
|
+
log_prefix = f"[S3Artifact:GetArtifactVersion:{filename}] "
|
|
541
|
+
filename = self._normalize_filename_unicode(filename)
|
|
542
|
+
app_name = app_name.strip('/')
|
|
543
|
+
|
|
544
|
+
# Determine which version to get
|
|
545
|
+
load_version = version
|
|
546
|
+
if load_version is None:
|
|
547
|
+
versions = await self.list_versions(
|
|
548
|
+
app_name=app_name,
|
|
549
|
+
user_id=user_id,
|
|
550
|
+
session_id=session_id,
|
|
551
|
+
filename=filename,
|
|
552
|
+
)
|
|
553
|
+
if not versions:
|
|
554
|
+
logger.debug("%sNo versions found for artifact.", log_prefix)
|
|
555
|
+
return None
|
|
556
|
+
load_version = max(versions)
|
|
557
|
+
logger.debug("%sGetting latest version: %d", log_prefix, load_version)
|
|
558
|
+
else:
|
|
559
|
+
logger.debug("%sGetting specified version: %d", log_prefix, load_version)
|
|
560
|
+
|
|
561
|
+
object_key = self._get_object_key(
|
|
562
|
+
app_name, user_id, session_id, filename, load_version
|
|
563
|
+
)
|
|
564
|
+
|
|
565
|
+
try:
|
|
566
|
+
|
|
567
|
+
def _head_object():
|
|
568
|
+
return self.s3.head_object(Bucket=self.bucket_name, Key=object_key)
|
|
569
|
+
|
|
570
|
+
response = await asyncio.to_thread(_head_object)
|
|
571
|
+
|
|
572
|
+
# Extract information
|
|
573
|
+
mime_type = response.get("ContentType", "application/octet-stream")
|
|
574
|
+
# S3 LastModified is a datetime object, convert to timestamp
|
|
575
|
+
create_time = response.get("LastModified").timestamp()
|
|
576
|
+
|
|
577
|
+
# Create and return ArtifactVersion object
|
|
578
|
+
artifact_version = ArtifactVersion(
|
|
579
|
+
version=load_version,
|
|
580
|
+
canonical_uri=f"s3://{self.bucket_name}/{object_key}",
|
|
581
|
+
mime_type=mime_type,
|
|
582
|
+
create_time=create_time,
|
|
583
|
+
custom_metadata={},
|
|
584
|
+
)
|
|
585
|
+
|
|
586
|
+
logger.info(
|
|
587
|
+
"%sRetrieved metadata for artifact '%s' version %d",
|
|
588
|
+
log_prefix,
|
|
589
|
+
filename,
|
|
590
|
+
load_version,
|
|
591
|
+
)
|
|
592
|
+
return artifact_version
|
|
593
|
+
|
|
594
|
+
except ClientError as e:
|
|
595
|
+
error_code = e.response.get("Error", {}).get("Code", "Unknown")
|
|
596
|
+
if error_code == "NoSuchKey" or error_code == "404":
|
|
597
|
+
logger.debug(
|
|
598
|
+
"%sArtifact version not found: %s", log_prefix, object_key
|
|
599
|
+
)
|
|
600
|
+
return None
|
|
601
|
+
else:
|
|
602
|
+
logger.error(
|
|
603
|
+
"%sFailed to get metadata for artifact '%s' version %d: %s",
|
|
604
|
+
log_prefix,
|
|
605
|
+
filename,
|
|
606
|
+
load_version,
|
|
607
|
+
e,
|
|
608
|
+
)
|
|
609
|
+
return None
|