solace-agent-mesh 1.6.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/app_llm_agent.py +26 -0
- solace_agent_mesh/agent/adk/artifacts/filesystem_artifact_service.py +165 -1
- solace_agent_mesh/agent/adk/artifacts/s3_artifact_service.py +163 -0
- solace_agent_mesh/agent/adk/callbacks.py +852 -109
- solace_agent_mesh/agent/adk/embed_resolving_mcp_toolset.py +234 -36
- 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 +77 -21
- solace_agent_mesh/agent/adk/models/oauth2_token_manager.py +24 -137
- solace_agent_mesh/agent/adk/runner.py +85 -20
- solace_agent_mesh/agent/adk/schema_migration.py +88 -0
- solace_agent_mesh/agent/adk/services.py +94 -18
- solace_agent_mesh/agent/adk/setup.py +281 -65
- solace_agent_mesh/agent/adk/stream_parser.py +231 -37
- solace_agent_mesh/agent/adk/tool_wrapper.py +3 -0
- solace_agent_mesh/agent/protocol/event_handlers.py +472 -137
- solace_agent_mesh/agent/proxies/a2a/app.py +3 -2
- 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/app.py +3 -2
- 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 +91 -3
- solace_agent_mesh/agent/sac/component.py +591 -157
- solace_agent_mesh/agent/sac/patch_adk.py +8 -16
- solace_agent_mesh/agent/sac/task_execution_context.py +146 -4
- 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 +710 -171
- solace_agent_mesh/agent/tools/deep_research_tools.py +2161 -0
- solace_agent_mesh/agent/tools/dynamic_tool.py +2 -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 +57 -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 +248 -6
- 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/2987107d.a80604f9.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/631738c7.fa471607.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/6a520c9d.b6e3f2ce.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6aaedf65.7253541d.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.a5b36a60.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/6d84eae0.fd23ba4a.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/71da7b71.374b9d54.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/8b032486.91a91afc.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/ad87452a.9d73dad6.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/da0b5bad.b62f7b08.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/dd817ffc.c37a755e.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/dd81e2b8.b682e9c2.js +1 -0
- solace_agent_mesh/assets/docs/assets/js/de915948.44a432bc.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/ff4d71f2.74710fc1.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 +82 -68
- 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 +182 -0
- 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 -49
- solace_agent_mesh/assets/docs/docs/documentation/deploying/deployment-options/index.html +29 -30
- 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 +90 -0
- solace_agent_mesh/assets/docs/docs/documentation/deploying/observability/index.html +17 -16
- 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 +162 -171
- 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 +86 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/connectors/index.html +67 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/index.html +23 -19
- 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 +112 -87
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/secure-user-delegated-access/index.html +440 -0
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/single-sign-on/index.html +87 -64
- solace_agent_mesh/assets/docs/docs/documentation/enterprise/wheel-installation/index.html +62 -0
- 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 -37
- 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 +311 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/configurations/index.html +39 -42
- 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 +251 -0
- solace_agent_mesh/assets/docs/docs/documentation/installing-and-configuring/user-feedback/index.html +88 -0
- 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/docs_cmd.py +4 -1
- 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-BTf6dqwp.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-CGk8Suyh.js +565 -0
- 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/events.py +2 -1
- solace_agent_mesh/common/a2a/protocol.py +5 -0
- solace_agent_mesh/common/a2a/types.py +2 -1
- solace_agent_mesh/common/a2a_spec/schemas/artifact_creation_progress.json +23 -6
- solace_agent_mesh/common/a2a_spec/schemas/feedback_event.json +51 -0
- solace_agent_mesh/common/agent_registry.py +38 -11
- solace_agent_mesh/common/data_parts.py +144 -4
- 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 +97 -19
- solace_agent_mesh/common/sam_events/event_service.py +2 -2
- solace_agent_mesh/common/services/employee_service.py +1 -1
- solace_agent_mesh/common/utils/embeds/constants.py +1 -0
- solace_agent_mesh/common/utils/embeds/converter.py +1 -8
- solace_agent_mesh/common/utils/embeds/modifiers.py +4 -28
- solace_agent_mesh/common/utils/embeds/resolver.py +152 -31
- solace_agent_mesh/common/utils/embeds/types.py +9 -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/pydantic_utils.py +90 -3
- 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/__init__.py +1 -0
- solace_agent_mesh/gateway/adapter/base.py +170 -0
- solace_agent_mesh/gateway/adapter/types.py +230 -0
- solace_agent_mesh/gateway/base/app.py +39 -2
- solace_agent_mesh/gateway/base/auth_interface.py +103 -0
- solace_agent_mesh/gateway/base/component.py +1027 -151
- solace_agent_mesh/gateway/generic/__init__.py +1 -0
- solace_agent_mesh/gateway/generic/app.py +50 -0
- solace_agent_mesh/gateway/generic/component.py +894 -0
- solace_agent_mesh/gateway/http_sse/alembic/env.py +0 -7
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_project_users_table.py +72 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251023_add_soft_delete_and_search.py +109 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_default_agent_to_projects.py +26 -0
- solace_agent_mesh/gateway/http_sse/alembic/versions/20251024_add_projects_table.py +135 -0
- 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 +40 -11
- solace_agent_mesh/gateway/http_sse/component.py +285 -160
- solace_agent_mesh/gateway/http_sse/dependencies.py +149 -114
- solace_agent_mesh/gateway/http_sse/main.py +68 -450
- solace_agent_mesh/gateway/http_sse/repository/__init__.py +19 -1
- solace_agent_mesh/gateway/http_sse/repository/chat_task_repository.py +2 -2
- solace_agent_mesh/gateway/http_sse/repository/entities/project.py +81 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/project_user.py +47 -0
- solace_agent_mesh/gateway/http_sse/repository/entities/session.py +26 -3
- solace_agent_mesh/gateway/http_sse/repository/entities/task.py +7 -0
- solace_agent_mesh/gateway/http_sse/repository/feedback_repository.py +47 -0
- solace_agent_mesh/gateway/http_sse/repository/interfaces.py +114 -6
- solace_agent_mesh/gateway/http_sse/repository/models/__init__.py +13 -0
- solace_agent_mesh/gateway/http_sse/repository/models/project_model.py +51 -0
- solace_agent_mesh/gateway/http_sse/repository/models/project_user_model.py +75 -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 +8 -2
- solace_agent_mesh/gateway/http_sse/repository/models/task_model.py +8 -1
- solace_agent_mesh/gateway/http_sse/repository/project_repository.py +172 -0
- solace_agent_mesh/gateway/http_sse/repository/project_user_repository.py +186 -0
- solace_agent_mesh/gateway/http_sse/repository/session_repository.py +177 -11
- 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 +256 -58
- solace_agent_mesh/gateway/http_sse/routers/auth.py +168 -134
- solace_agent_mesh/gateway/http_sse/routers/config.py +302 -8
- 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/project_requests.py +48 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/session_requests.py +14 -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 +31 -0
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/session_responses.py +5 -2
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/version_responses.py +31 -0
- solace_agent_mesh/gateway/http_sse/routers/feedback.py +133 -2
- solace_agent_mesh/gateway/http_sse/routers/people.py +2 -2
- solace_agent_mesh/gateway/http_sse/routers/projects.py +768 -0
- solace_agent_mesh/gateway/http_sse/routers/prompts.py +1416 -0
- solace_agent_mesh/gateway/http_sse/routers/sessions.py +167 -7
- solace_agent_mesh/gateway/http_sse/routers/speech.py +355 -0
- solace_agent_mesh/gateway/http_sse/routers/sse.py +131 -8
- solace_agent_mesh/gateway/http_sse/routers/tasks.py +670 -18
- 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 +92 -9
- 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 +930 -0
- solace_agent_mesh/gateway/http_sse/services/prompt_builder_assistant.py +303 -0
- solace_agent_mesh/gateway/http_sse/services/session_service.py +361 -12
- solace_agent_mesh/gateway/http_sse/services/task_logger_service.py +354 -4
- solace_agent_mesh/gateway/http_sse/session_manager.py +15 -15
- solace_agent_mesh/gateway/http_sse/sse_manager.py +286 -166
- 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 +19 -5
- 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.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/METADATA +31 -12
- solace_agent_mesh-1.13.2.dist-info/RECORD +591 -0
- {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/WHEEL +1 -1
- solace_agent_mesh/agent/adk/adk_llm.txt +0 -232
- 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 -142
- solace_agent_mesh/agent/agent_llm.txt +0 -378
- 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/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 -57
- solace_agent_mesh/agent/testing/testing_llm_detail.txt +0 -68
- solace_agent_mesh/agent/tools/tools_llm.txt +0 -263
- solace_agent_mesh/agent/tools/tools_llm_detail.txt +0 -274
- solace_agent_mesh/agent/utils/utils_llm.txt +0 -138
- solace_agent_mesh/agent/utils/utils_llm_detail.txt +0 -149
- solace_agent_mesh/assets/docs/assets/js/15ba94aa.932dd2db.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/17896441.a5e82f9b.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/240a0364.7eac6021.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.76654dd9.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/3ff0015d.2be20244.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/547e15cc.2cbb060a.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/55b7b518.f2b1d1ba.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/5c2bd65f.eda4bcb2.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/631738c7.a8b1ef8b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/6a520c9d.ba015d81.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/6ad8f0bd.f4b15f3b.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/6d84eae0.4a5fbf39.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/71da7b71.38583438.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/8024126c.56e59919.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.b5ddb7a1.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.3e6dd091.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/c93cbaa0.eaff365e.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/da0b5bad.d08a9466.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/dd817ffc.0aa9630a.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/dd81e2b8.d590bc9e.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/de915948.27d6b065.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e3d9abda.6b9493d0.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e6f9706b.e74a984d.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/e92d0134.cf6d6522.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/f284c35a.42f59cdd.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/ff4d71f2.15b02f97.js +0 -1
- solace_agent_mesh/assets/docs/assets/js/main.b12eac43.js +0 -2
- solace_agent_mesh/assets/docs/assets/js/runtime~main.e268214e.js +0 -1
- solace_agent_mesh/assets/docs/lunr-index-1761248203150.json +0 -1
- solace_agent_mesh/assets/docs/search-doc-1761248203150.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-CaY59VuC.js +0 -25
- solace_agent_mesh/client/webui/frontend/static/assets/main-B32noGmR.js +0 -342
- solace_agent_mesh/client/webui/frontend/static/assets/main-DHJKSW1S.css +0 -1
- solace_agent_mesh/client/webui/frontend/static/assets/vendor-BEmvJSYz.js +0 -405
- solace_agent_mesh/common/a2a/a2a_llm.txt +0 -182
- solace_agent_mesh/common/a2a/a2a_llm_detail.txt +0 -193
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm.txt +0 -407
- solace_agent_mesh/common/a2a_spec/a2a_spec_llm_detail.txt +0 -736
- solace_agent_mesh/common/a2a_spec/schemas/schemas_llm.txt +0 -313
- solace_agent_mesh/common/common_llm.txt +0 -251
- 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 -80
- solace_agent_mesh/common/services/services_llm.txt +0 -363
- 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 -336
- 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 -224
- solace_agent_mesh/gateway/base/base_llm_detail.txt +0 -235
- solace_agent_mesh/gateway/gateway_llm.txt +0 -373
- solace_agent_mesh/gateway/gateway_llm_detail.txt +0 -3885
- solace_agent_mesh/gateway/http_sse/alembic/alembic_llm.txt +0 -295
- solace_agent_mesh/gateway/http_sse/alembic/versions/versions_llm.txt +0 -155
- 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 -263
- solace_agent_mesh/gateway/http_sse/repository/models/models_llm.txt +0 -266
- solace_agent_mesh/gateway/http_sse/repository/repository_llm.txt +0 -340
- solace_agent_mesh/gateway/http_sse/routers/dto/dto_llm.txt +0 -346
- solace_agent_mesh/gateway/http_sse/routers/dto/requests/requests_llm.txt +0 -83
- solace_agent_mesh/gateway/http_sse/routers/dto/responses/responses_llm.txt +0 -107
- solace_agent_mesh/gateway/http_sse/routers/routers_llm.txt +0 -314
- solace_agent_mesh/gateway/http_sse/services/services_llm.txt +0 -297
- solace_agent_mesh/gateway/http_sse/shared/__init__.py +0 -146
- solace_agent_mesh/gateway/http_sse/shared/shared_llm.txt +0 -285
- 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-1.6.1.dist-info/RECORD +0 -525
- /solace_agent_mesh/assets/docs/assets/js/{main.b12eac43.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.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/entry_points.txt +0 -0
- {solace_agent_mesh-1.6.1.dist-info → solace_agent_mesh-1.13.2.dist-info}/licenses/LICENSE +0 -0
|
@@ -10,7 +10,7 @@ import uuid
|
|
|
10
10
|
import json
|
|
11
11
|
import re
|
|
12
12
|
import fnmatch
|
|
13
|
-
from typing import Any, Dict, Optional, Union, TYPE_CHECKING
|
|
13
|
+
from typing import Any, Dict, List, Optional, Tuple, Union, TYPE_CHECKING
|
|
14
14
|
from datetime import datetime, timezone
|
|
15
15
|
from google.adk.tools import ToolContext
|
|
16
16
|
|
|
@@ -32,6 +32,7 @@ from ...common.utils.embeds import (
|
|
|
32
32
|
EMBED_REGEX,
|
|
33
33
|
EMBED_CHAIN_DELIMITER,
|
|
34
34
|
)
|
|
35
|
+
from ...common.utils.embeds.types import ResolutionMode
|
|
35
36
|
from ...agent.utils.context_helpers import get_original_session_id
|
|
36
37
|
from ...agent.adk.models.lite_llm import LiteLlm
|
|
37
38
|
from google.adk.models import LlmRequest
|
|
@@ -43,6 +44,7 @@ log = logging.getLogger(__name__)
|
|
|
43
44
|
CATEGORY_NAME = "Artifact Management"
|
|
44
45
|
CATEGORY_DESCRIPTION = "List, read, create, update, and delete artifacts."
|
|
45
46
|
|
|
47
|
+
|
|
46
48
|
async def _internal_create_artifact(
|
|
47
49
|
filename: str,
|
|
48
50
|
content: str,
|
|
@@ -173,6 +175,7 @@ async def _internal_create_artifact(
|
|
|
173
175
|
timestamp=timestamp_for_artifact,
|
|
174
176
|
schema_max_keys=max_keys_to_use,
|
|
175
177
|
tool_context=tool_context,
|
|
178
|
+
suppress_visualization_signal=True, # Fenced blocks handle their own visualization signals
|
|
176
179
|
)
|
|
177
180
|
log.info(
|
|
178
181
|
"%s Result from save_artifact_with_metadata: %s", log_identifier, result
|
|
@@ -360,6 +363,7 @@ async def load_artifact(
|
|
|
360
363
|
version: int,
|
|
361
364
|
load_metadata_only: bool = False,
|
|
362
365
|
max_content_length: Optional[int] = None,
|
|
366
|
+
include_line_numbers: bool = False,
|
|
363
367
|
tool_context: ToolContext = None,
|
|
364
368
|
) -> Dict[str, Any]:
|
|
365
369
|
"""
|
|
@@ -371,10 +375,13 @@ async def load_artifact(
|
|
|
371
375
|
|
|
372
376
|
Args:
|
|
373
377
|
filename: The name of the artifact to load. May contain embeds.
|
|
374
|
-
version: The specific version number to load. Must be explicitly provided.
|
|
378
|
+
version: The specific version number to load. Must be explicitly provided. Versions are 0-indexed.
|
|
375
379
|
load_metadata_only (bool): If True, load only the metadata JSON. Default False.
|
|
376
380
|
max_content_length (Optional[int]): Maximum character length for text content.
|
|
377
381
|
If None, uses app configuration. Range: 100-100,000.
|
|
382
|
+
include_line_numbers (bool): If True, prefix each line with its 1-based line number
|
|
383
|
+
followed by a TAB character for LLM viewing. Line numbers
|
|
384
|
+
are not stored in the artifact. Default False.
|
|
378
385
|
tool_context: The context provided by the ADK framework.
|
|
379
386
|
|
|
380
387
|
Returns:
|
|
@@ -413,6 +420,7 @@ async def load_artifact(
|
|
|
413
420
|
version=version,
|
|
414
421
|
load_metadata_only=load_metadata_only,
|
|
415
422
|
max_content_length=max_content_length,
|
|
423
|
+
include_line_numbers=include_line_numbers,
|
|
416
424
|
component=host_component,
|
|
417
425
|
log_identifier_prefix="[BuiltinArtifactTool:load_artifact]",
|
|
418
426
|
)
|
|
@@ -451,121 +459,6 @@ async def load_artifact(
|
|
|
451
459
|
}
|
|
452
460
|
|
|
453
461
|
|
|
454
|
-
async def signal_artifact_for_return(
|
|
455
|
-
filename: str,
|
|
456
|
-
version: int,
|
|
457
|
-
tool_context: ToolContext = None,
|
|
458
|
-
) -> Dict[str, Any]:
|
|
459
|
-
"""
|
|
460
|
-
Signals that a specific version of an artifact should be returned to the
|
|
461
|
-
original caller as part of the final task result.
|
|
462
|
-
|
|
463
|
-
Args:
|
|
464
|
-
filename: The name of the artifact to return. May contain embeds.
|
|
465
|
-
version: The specific version number to return. Must be explicitly provided.
|
|
466
|
-
"""
|
|
467
|
-
if not tool_context:
|
|
468
|
-
return {
|
|
469
|
-
"status": "error",
|
|
470
|
-
"filename": filename,
|
|
471
|
-
"version": version,
|
|
472
|
-
"message": "ToolContext is missing.",
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
log_identifier = (
|
|
476
|
-
f"[BuiltinArtifactTool:signal_artifact_for_return:{filename}:{version}]"
|
|
477
|
-
)
|
|
478
|
-
log.debug("%s Processing request after potential embed resolution.", log_identifier)
|
|
479
|
-
|
|
480
|
-
if version is None:
|
|
481
|
-
return {
|
|
482
|
-
"status": "error",
|
|
483
|
-
"filename": filename,
|
|
484
|
-
"version": None,
|
|
485
|
-
"message": "Version parameter is required. Use list_artifacts() to find available versions.",
|
|
486
|
-
}
|
|
487
|
-
|
|
488
|
-
try:
|
|
489
|
-
inv_context = tool_context._invocation_context
|
|
490
|
-
artifact_service = inv_context.artifact_service
|
|
491
|
-
host_component = getattr(inv_context.agent, "host_component", None)
|
|
492
|
-
|
|
493
|
-
if not artifact_service:
|
|
494
|
-
raise ValueError("ArtifactService is not available in the context.")
|
|
495
|
-
if not host_component:
|
|
496
|
-
raise ValueError("Host component is not available.")
|
|
497
|
-
|
|
498
|
-
app_name = inv_context.app_name
|
|
499
|
-
user_id = inv_context.user_id
|
|
500
|
-
session_id = get_original_session_id(inv_context)
|
|
501
|
-
|
|
502
|
-
versions = await artifact_service.list_versions(
|
|
503
|
-
app_name=app_name,
|
|
504
|
-
user_id=user_id,
|
|
505
|
-
session_id=session_id,
|
|
506
|
-
filename=filename,
|
|
507
|
-
)
|
|
508
|
-
if version not in versions:
|
|
509
|
-
raise FileNotFoundError(
|
|
510
|
-
f"Artifact '{filename}' version {version} not found."
|
|
511
|
-
)
|
|
512
|
-
|
|
513
|
-
a2a_context = tool_context.state.get("a2a_context", {})
|
|
514
|
-
logical_task_id = a2a_context.get("logical_task_id")
|
|
515
|
-
if not logical_task_id:
|
|
516
|
-
raise ValueError("Could not determine logical_task_id for signaling.")
|
|
517
|
-
|
|
518
|
-
with host_component.active_tasks_lock:
|
|
519
|
-
task_execution_context = host_component.active_tasks.get(logical_task_id)
|
|
520
|
-
|
|
521
|
-
if not task_execution_context:
|
|
522
|
-
raise ValueError(
|
|
523
|
-
f"TaskExecutionContext not found for task {logical_task_id}."
|
|
524
|
-
)
|
|
525
|
-
|
|
526
|
-
signal_data = {"filename": filename, "version": version}
|
|
527
|
-
task_execution_context.add_artifact_signal(signal_data)
|
|
528
|
-
|
|
529
|
-
log.info(
|
|
530
|
-
"%s Added artifact signal to TaskExecutionContext for task %s.",
|
|
531
|
-
log_identifier,
|
|
532
|
-
logical_task_id,
|
|
533
|
-
)
|
|
534
|
-
|
|
535
|
-
# Also add a placeholder to state_delta. This acts as a trigger
|
|
536
|
-
# for the host component to check the cache at the end of the turn.
|
|
537
|
-
# The key is unique to avoid collisions, but the content is just a placeholder.
|
|
538
|
-
trigger_key = f"temp:a2a_return_artifact:{uuid.uuid4().hex}"
|
|
539
|
-
tool_context.actions.state_delta[trigger_key] = {"triggered": True}
|
|
540
|
-
log.debug(
|
|
541
|
-
"%s Set state_delta trigger key '%s' to ensure signal processing.",
|
|
542
|
-
log_identifier,
|
|
543
|
-
trigger_key,
|
|
544
|
-
)
|
|
545
|
-
|
|
546
|
-
return {
|
|
547
|
-
"status": "success",
|
|
548
|
-
"message": f"Artifact '{filename}' (version {version}) has been signaled for return.",
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
except FileNotFoundError as fnf_err:
|
|
552
|
-
log.warning("%s Artifact not found: %s", log_identifier, fnf_err)
|
|
553
|
-
return {
|
|
554
|
-
"status": "error",
|
|
555
|
-
"filename": filename,
|
|
556
|
-
"version": version,
|
|
557
|
-
"message": str(fnf_err),
|
|
558
|
-
}
|
|
559
|
-
except Exception as e:
|
|
560
|
-
log.exception("%s Error signaling artifact for return: %s", log_identifier, e)
|
|
561
|
-
return {
|
|
562
|
-
"status": "error",
|
|
563
|
-
"filename": filename,
|
|
564
|
-
"version": version,
|
|
565
|
-
"message": f"Failed to signal artifact for return: {e}",
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
|
|
569
462
|
async def apply_embed_and_create_artifact(
|
|
570
463
|
output_filename: str,
|
|
571
464
|
embed_directive: str,
|
|
@@ -659,6 +552,7 @@ async def apply_embed_and_create_artifact(
|
|
|
659
552
|
format_spec=format_spec,
|
|
660
553
|
context=gateway_context,
|
|
661
554
|
log_identifier=log_identifier,
|
|
555
|
+
resolution_mode=ResolutionMode.TOOL_PARAMETER,
|
|
662
556
|
config=embed_config,
|
|
663
557
|
)
|
|
664
558
|
|
|
@@ -976,7 +870,7 @@ async def extract_content_from_artifact(
|
|
|
976
870
|
mime_type=normalized_source_mime_type,
|
|
977
871
|
content_bytes=source_artifact_content_bytes,
|
|
978
872
|
)
|
|
979
|
-
|
|
873
|
+
|
|
980
874
|
if is_text_based:
|
|
981
875
|
try:
|
|
982
876
|
artifact_text_content = source_artifact_content_bytes.decode("utf-8")
|
|
@@ -1648,17 +1542,20 @@ async def _notify_artifact_save(
|
|
|
1648
1542
|
tool_context: ToolContext = None, # Keep tool_context for signature consistency
|
|
1649
1543
|
) -> Dict[str, Any]:
|
|
1650
1544
|
"""
|
|
1651
|
-
|
|
1652
|
-
has been successfully saved. It performs no actions and simply returns its
|
|
1653
|
-
arguments to get the result into the ADK history.
|
|
1545
|
+
CRITICAL: _notify_artifact_save is automatically invoked by the system as a side-effect when you create artifacts. You should NEVER call this tool yourself. The system will call it for you and provide the results in your next turn. If you manually invoke it, you are making an error."
|
|
1654
1546
|
"""
|
|
1655
|
-
return {
|
|
1547
|
+
return {
|
|
1548
|
+
"filename": filename,
|
|
1549
|
+
"version": version,
|
|
1550
|
+
"status": status,
|
|
1551
|
+
"message": "Artifact has been created and provided to the requester",
|
|
1552
|
+
}
|
|
1656
1553
|
|
|
1657
1554
|
|
|
1658
1555
|
_notify_artifact_save_tool_def = BuiltinTool(
|
|
1659
1556
|
name="_notify_artifact_save",
|
|
1660
1557
|
implementation=_notify_artifact_save,
|
|
1661
|
-
description="
|
|
1558
|
+
description="CRITICAL: _notify_artifact_save is automatically invoked by the system as a side-effect when you create artifacts. You should NEVER call this tool yourself. The system will call it for you and provide the results in your next turn. If you manually invoke it, you are making an error.",
|
|
1662
1559
|
category="internal",
|
|
1663
1560
|
required_scopes=[], # No scopes needed for an internal notification tool
|
|
1664
1561
|
parameters=adk_types.Schema(
|
|
@@ -1730,7 +1627,7 @@ list_artifacts_tool_def = BuiltinTool(
|
|
|
1730
1627
|
load_artifact_tool_def = BuiltinTool(
|
|
1731
1628
|
name="load_artifact",
|
|
1732
1629
|
implementation=load_artifact,
|
|
1733
|
-
description="Loads the content or metadata of a specific artifact version. If load_metadata_only is True, loads the full metadata dictionary. Otherwise, loads text content (potentially truncated) or a summary for binary types.",
|
|
1630
|
+
description="Loads the content or metadata of a specific artifact version. If load_metadata_only is True, loads the full metadata dictionary. Otherwise, loads text content (potentially truncated) or a summary for binary types. Line numbers can be optionally included for precise line range identification.",
|
|
1734
1631
|
category="artifact_management",
|
|
1735
1632
|
category_name=CATEGORY_NAME,
|
|
1736
1633
|
category_description=CATEGORY_DESCRIPTION,
|
|
@@ -1756,30 +1653,10 @@ load_artifact_tool_def = BuiltinTool(
|
|
|
1756
1653
|
description="Optional. Maximum character length for text content. If None, uses app configuration. Range: 100-100,000.",
|
|
1757
1654
|
nullable=True,
|
|
1758
1655
|
),
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
)
|
|
1764
|
-
|
|
1765
|
-
signal_artifact_for_return_tool_def = BuiltinTool(
|
|
1766
|
-
name="signal_artifact_for_return",
|
|
1767
|
-
implementation=signal_artifact_for_return,
|
|
1768
|
-
description="Signals the host component to return a specific artifact version to the original caller of the task. This tool does not load the artifact content itself; it just flags it for return.",
|
|
1769
|
-
category="artifact_management",
|
|
1770
|
-
category_name=CATEGORY_NAME,
|
|
1771
|
-
category_description=CATEGORY_DESCRIPTION,
|
|
1772
|
-
required_scopes=["tool:artifact:signal_return"],
|
|
1773
|
-
parameters=adk_types.Schema(
|
|
1774
|
-
type=adk_types.Type.OBJECT,
|
|
1775
|
-
properties={
|
|
1776
|
-
"filename": adk_types.Schema(
|
|
1777
|
-
type=adk_types.Type.STRING,
|
|
1778
|
-
description="The name of the artifact to return. May contain embeds.",
|
|
1779
|
-
),
|
|
1780
|
-
"version": adk_types.Schema(
|
|
1781
|
-
type=adk_types.Type.INTEGER,
|
|
1782
|
-
description="The specific version number to return. Use list_artifacts() first to find available versions.",
|
|
1656
|
+
"include_line_numbers": adk_types.Schema(
|
|
1657
|
+
type=adk_types.Type.BOOLEAN,
|
|
1658
|
+
description="If True, prefix each line with its 1-based line number followed by a TAB character. Line numbers are for LLM viewing only and are not stored in the artifact. Default False.",
|
|
1659
|
+
nullable=True,
|
|
1783
1660
|
),
|
|
1784
1661
|
},
|
|
1785
1662
|
required=["filename", "version"],
|
|
@@ -1857,7 +1734,6 @@ tool_registry.register(_notify_artifact_save_tool_def)
|
|
|
1857
1734
|
tool_registry.register(append_to_artifact_tool_def)
|
|
1858
1735
|
tool_registry.register(list_artifacts_tool_def)
|
|
1859
1736
|
tool_registry.register(load_artifact_tool_def)
|
|
1860
|
-
tool_registry.register(signal_artifact_for_return_tool_def)
|
|
1861
1737
|
tool_registry.register(apply_embed_and_create_artifact_tool_def)
|
|
1862
1738
|
tool_registry.register(extract_content_from_artifact_tool_def)
|
|
1863
1739
|
|
|
@@ -1865,18 +1741,20 @@ tool_registry.register(extract_content_from_artifact_tool_def)
|
|
|
1865
1741
|
async def delete_artifact(
|
|
1866
1742
|
filename: str,
|
|
1867
1743
|
version: Optional[int] = None,
|
|
1744
|
+
confirm_delete: bool = False,
|
|
1868
1745
|
tool_context: ToolContext = None,
|
|
1869
1746
|
) -> Dict[str, Any]:
|
|
1870
1747
|
"""
|
|
1871
|
-
Deletes
|
|
1748
|
+
Deletes all versions of an artifact. Version-specific deletion is not currently supported.
|
|
1872
1749
|
|
|
1873
1750
|
Args:
|
|
1874
1751
|
filename: The name of the artifact to delete.
|
|
1875
|
-
version:
|
|
1752
|
+
version: Reserved for future use. Currently not supported - returns error if specified.
|
|
1753
|
+
confirm_delete: Must be set to True to confirm deletion. If False, returns confirmation prompt.
|
|
1876
1754
|
tool_context: The context provided by the ADK framework.
|
|
1877
1755
|
|
|
1878
1756
|
Returns:
|
|
1879
|
-
A dictionary indicating the result of the deletion.
|
|
1757
|
+
A dictionary indicating the result of the deletion or requesting confirmation.
|
|
1880
1758
|
"""
|
|
1881
1759
|
if not tool_context:
|
|
1882
1760
|
return {
|
|
@@ -1885,9 +1763,7 @@ async def delete_artifact(
|
|
|
1885
1763
|
"message": "ToolContext is missing, cannot delete artifact.",
|
|
1886
1764
|
}
|
|
1887
1765
|
|
|
1888
|
-
log_identifier =
|
|
1889
|
-
f"[BuiltinArtifactTool:delete_artifact:{filename}:{version or 'all'}]"
|
|
1890
|
-
)
|
|
1766
|
+
log_identifier = f"[BuiltinArtifactTool:delete_artifact:{filename}]"
|
|
1891
1767
|
log.debug("%s Processing request.", log_identifier)
|
|
1892
1768
|
|
|
1893
1769
|
try:
|
|
@@ -1905,14 +1781,32 @@ async def delete_artifact(
|
|
|
1905
1781
|
"ArtifactService does not support deleting artifacts."
|
|
1906
1782
|
)
|
|
1907
1783
|
|
|
1784
|
+
# Error if version-specific deletion requested (not currently supported)
|
|
1908
1785
|
if version is not None:
|
|
1909
|
-
|
|
1910
|
-
"
|
|
1911
|
-
"
|
|
1912
|
-
|
|
1913
|
-
version,
|
|
1914
|
-
|
|
1786
|
+
return {
|
|
1787
|
+
"status": "error",
|
|
1788
|
+
"filename": filename,
|
|
1789
|
+
"version_requested": version,
|
|
1790
|
+
"message": f"Deleting a specific version ({version}) is not currently supported. Only deletion of ALL versions is supported. To delete all versions, omit 'version' and set confirm_delete=True.",
|
|
1791
|
+
}
|
|
1915
1792
|
|
|
1793
|
+
# Get version list for confirmation message
|
|
1794
|
+
versions = await artifact_service.list_versions(
|
|
1795
|
+
app_name=app_name, user_id=user_id, session_id=session_id, filename=filename
|
|
1796
|
+
)
|
|
1797
|
+
|
|
1798
|
+
# Require confirmation before deleting
|
|
1799
|
+
if not confirm_delete:
|
|
1800
|
+
count = len(versions) if versions else "unknown number of"
|
|
1801
|
+
return {
|
|
1802
|
+
"status": "confirmation_required",
|
|
1803
|
+
"filename": filename,
|
|
1804
|
+
"version_count": len(versions) if versions else None,
|
|
1805
|
+
"versions": versions,
|
|
1806
|
+
"message": f"WARNING: This operation is irreversible and will permanently delete artifact '{filename}' and ALL {count} version(s). To proceed, call this tool again with confirm_delete=True.",
|
|
1807
|
+
}
|
|
1808
|
+
|
|
1809
|
+
# Proceed with deletion
|
|
1916
1810
|
await artifact_service.delete_artifact(
|
|
1917
1811
|
app_name=app_name,
|
|
1918
1812
|
user_id=user_id,
|
|
@@ -1920,17 +1814,12 @@ async def delete_artifact(
|
|
|
1920
1814
|
filename=filename,
|
|
1921
1815
|
)
|
|
1922
1816
|
|
|
1923
|
-
log.info(
|
|
1924
|
-
"%s Successfully deleted artifact '%s' version '%s'.",
|
|
1925
|
-
log_identifier,
|
|
1926
|
-
filename,
|
|
1927
|
-
version or "all",
|
|
1928
|
-
)
|
|
1817
|
+
log.info("%s Successfully deleted artifact '%s'.", log_identifier, filename)
|
|
1929
1818
|
return {
|
|
1930
1819
|
"status": "success",
|
|
1931
1820
|
"filename": filename,
|
|
1932
|
-
"
|
|
1933
|
-
"message": f"Artifact '{filename}'
|
|
1821
|
+
"versions_deleted": len(versions) if versions else None,
|
|
1822
|
+
"message": f"Artifact '{filename}' deleted successfully.",
|
|
1934
1823
|
}
|
|
1935
1824
|
|
|
1936
1825
|
except FileNotFoundError as e:
|
|
@@ -1954,7 +1843,7 @@ async def delete_artifact(
|
|
|
1954
1843
|
delete_artifact_tool_def = BuiltinTool(
|
|
1955
1844
|
name="delete_artifact",
|
|
1956
1845
|
implementation=delete_artifact,
|
|
1957
|
-
description="Deletes
|
|
1846
|
+
description="Deletes all versions of an artifact. IMPORTANT: Requires explicit confirmation via confirm_delete=True parameter. The first call without confirmation will return details about what will be deleted.",
|
|
1958
1847
|
category="artifact_management",
|
|
1959
1848
|
category_name=CATEGORY_NAME,
|
|
1960
1849
|
category_description=CATEGORY_DESCRIPTION,
|
|
@@ -1968,7 +1857,12 @@ delete_artifact_tool_def = BuiltinTool(
|
|
|
1968
1857
|
),
|
|
1969
1858
|
"version": adk_types.Schema(
|
|
1970
1859
|
type=adk_types.Type.INTEGER,
|
|
1971
|
-
description="
|
|
1860
|
+
description="Reserved for future use. Version-specific deletion is not currently supported - will return error if specified.",
|
|
1861
|
+
nullable=True,
|
|
1862
|
+
),
|
|
1863
|
+
"confirm_delete": adk_types.Schema(
|
|
1864
|
+
type=adk_types.Type.BOOLEAN,
|
|
1865
|
+
description="Must be set to True to actually perform the deletion. If False or omitted, returns a confirmation prompt with details about what will be deleted (including version count).",
|
|
1972
1866
|
nullable=True,
|
|
1973
1867
|
),
|
|
1974
1868
|
},
|
|
@@ -1978,3 +1872,648 @@ delete_artifact_tool_def = BuiltinTool(
|
|
|
1978
1872
|
)
|
|
1979
1873
|
|
|
1980
1874
|
tool_registry.register(delete_artifact_tool_def)
|
|
1875
|
+
|
|
1876
|
+
|
|
1877
|
+
def _perform_single_replacement(
|
|
1878
|
+
content: str,
|
|
1879
|
+
search_expr: str,
|
|
1880
|
+
replace_expr: str,
|
|
1881
|
+
is_regex: bool,
|
|
1882
|
+
regex_flags: str,
|
|
1883
|
+
log_identifier: str,
|
|
1884
|
+
strict_match_validation: bool = False,
|
|
1885
|
+
) -> Tuple[str, int, Optional[str]]:
|
|
1886
|
+
"""
|
|
1887
|
+
Performs a single search-and-replace operation.
|
|
1888
|
+
|
|
1889
|
+
Args:
|
|
1890
|
+
content: The text content to search/replace in
|
|
1891
|
+
search_expr: The search pattern (literal or regex)
|
|
1892
|
+
replace_expr: The replacement text
|
|
1893
|
+
is_regex: If True, search_expr is treated as regex
|
|
1894
|
+
regex_flags: Flags for regex behavior ('g', 'i', 'm', 's')
|
|
1895
|
+
log_identifier: Logging prefix
|
|
1896
|
+
strict_match_validation: If True, error on multiple matches without 'g' flag (for batch mode)
|
|
1897
|
+
|
|
1898
|
+
Returns:
|
|
1899
|
+
tuple: (new_content, match_count, error_message)
|
|
1900
|
+
error_message is None on success
|
|
1901
|
+
"""
|
|
1902
|
+
match_count = 0
|
|
1903
|
+
new_content = content
|
|
1904
|
+
|
|
1905
|
+
if is_regex:
|
|
1906
|
+
# Parse regex flags
|
|
1907
|
+
flags_value = 0
|
|
1908
|
+
global_replace = False
|
|
1909
|
+
|
|
1910
|
+
if regex_flags:
|
|
1911
|
+
for flag_char in regex_flags.lower():
|
|
1912
|
+
if flag_char == "g":
|
|
1913
|
+
global_replace = True
|
|
1914
|
+
elif flag_char == "i":
|
|
1915
|
+
flags_value |= re.IGNORECASE
|
|
1916
|
+
elif flag_char == "m":
|
|
1917
|
+
flags_value |= re.MULTILINE
|
|
1918
|
+
elif flag_char == "s":
|
|
1919
|
+
flags_value |= re.DOTALL
|
|
1920
|
+
else:
|
|
1921
|
+
log.warning(
|
|
1922
|
+
"%s Ignoring unrecognized regexp flag: '%s'",
|
|
1923
|
+
log_identifier,
|
|
1924
|
+
flag_char,
|
|
1925
|
+
)
|
|
1926
|
+
|
|
1927
|
+
# Convert JavaScript-style capture groups ($1, $2) to Python style (\1, \2)
|
|
1928
|
+
# Also handle escaped dollar signs ($$) -> literal $
|
|
1929
|
+
python_replace_expr = replace_expr
|
|
1930
|
+
# First, protect escaped dollars: $$ -> a placeholder
|
|
1931
|
+
python_replace_expr = python_replace_expr.replace("$$", "\x00DOLLAR\x00")
|
|
1932
|
+
# Convert capture groups: $1 -> \1
|
|
1933
|
+
python_replace_expr = re.sub(r"\$(\d+)", r"\\\1", python_replace_expr)
|
|
1934
|
+
# Restore escaped dollars: placeholder -> $
|
|
1935
|
+
python_replace_expr = python_replace_expr.replace("\x00DOLLAR\x00", "$")
|
|
1936
|
+
|
|
1937
|
+
try:
|
|
1938
|
+
# Compile the regex pattern
|
|
1939
|
+
pattern = re.compile(search_expr, flags_value)
|
|
1940
|
+
|
|
1941
|
+
# Count matches first
|
|
1942
|
+
match_count = len(pattern.findall(content))
|
|
1943
|
+
|
|
1944
|
+
if match_count == 0:
|
|
1945
|
+
return content, 0, f"No matches found"
|
|
1946
|
+
|
|
1947
|
+
# Check for multiple matches without global flag (only in strict mode for batch operations)
|
|
1948
|
+
if strict_match_validation and match_count > 1 and not global_replace:
|
|
1949
|
+
return (
|
|
1950
|
+
content,
|
|
1951
|
+
match_count,
|
|
1952
|
+
f"Multiple matches found ({match_count}) but global flag 'g' not set",
|
|
1953
|
+
)
|
|
1954
|
+
|
|
1955
|
+
# Perform replacement
|
|
1956
|
+
count_limit = 0 if global_replace else 1
|
|
1957
|
+
new_content = pattern.sub(python_replace_expr, content, count=count_limit)
|
|
1958
|
+
|
|
1959
|
+
return new_content, match_count, None
|
|
1960
|
+
|
|
1961
|
+
except re.error as regex_err:
|
|
1962
|
+
return content, 0, f"Invalid regular expression: {regex_err}"
|
|
1963
|
+
|
|
1964
|
+
else:
|
|
1965
|
+
# Literal string replacement
|
|
1966
|
+
match_count = content.count(search_expr)
|
|
1967
|
+
|
|
1968
|
+
if match_count == 0:
|
|
1969
|
+
return content, 0, f"No matches found"
|
|
1970
|
+
|
|
1971
|
+
# Replace all occurrences for literal mode
|
|
1972
|
+
new_content = content.replace(search_expr, replace_expr)
|
|
1973
|
+
return new_content, match_count, None
|
|
1974
|
+
|
|
1975
|
+
|
|
1976
|
+
async def artifact_search_and_replace_regex(
|
|
1977
|
+
filename: str,
|
|
1978
|
+
search_expression: Optional[str] = None,
|
|
1979
|
+
replace_expression: Optional[str] = None,
|
|
1980
|
+
is_regexp: bool = False,
|
|
1981
|
+
version: Optional[str] = "latest",
|
|
1982
|
+
regexp_flags: Optional[str] = "",
|
|
1983
|
+
new_filename: Optional[str] = None,
|
|
1984
|
+
new_description: Optional[str] = None,
|
|
1985
|
+
replacements: Optional[List[Dict[str, Any]]] = None,
|
|
1986
|
+
tool_context: ToolContext = None,
|
|
1987
|
+
) -> Dict[str, Any]:
|
|
1988
|
+
"""
|
|
1989
|
+
Performs search and replace on an artifact's text content using either
|
|
1990
|
+
literal string matching or regular expressions. Note that this is run once across the entire artifact.
|
|
1991
|
+
If multiple replacements are needed, then set the 'g' flag in regexp_flags.
|
|
1992
|
+
|
|
1993
|
+
Handling Multi-line Search and Replace:
|
|
1994
|
+
|
|
1995
|
+
When searching for or replacing text that spans multiple lines:
|
|
1996
|
+
|
|
1997
|
+
- In literal mode (is_regexp=false): Include actual newline characters directly in your search_expression
|
|
1998
|
+
and replace_expression parameters. Do NOT use escape sequences like \n - the tool will search for those
|
|
1999
|
+
literal characters. Multi-line parameter values are fully supported in the XML parameter format.
|
|
2000
|
+
|
|
2001
|
+
- In regex mode (is_regexp=true): Use the regex pattern \n to match newline characters in your pattern.
|
|
2002
|
+
|
|
2003
|
+
For multiple independent replacements:
|
|
2004
|
+
|
|
2005
|
+
Use the replacements array parameter to perform all replacements atomically in a single tool call, which is more efficient than multiple sequential calls.
|
|
2006
|
+
|
|
2007
|
+
Args:
|
|
2008
|
+
filename: The name of the artifact to search/replace in.
|
|
2009
|
+
search_expression: The pattern to search for (regex if is_regexp=true, literal otherwise).
|
|
2010
|
+
replace_expression: The replacement text. For regex mode, supports capture groups ($1, $2, etc.). Use $$ to insert a literal dollar sign
|
|
2011
|
+
is_regexp: If True, treat search_expression as a regular expression. If False, treat as literal string.
|
|
2012
|
+
version: The version of the artifact to operate on. Can be an integer version number as a string or 'latest'. Defaults to 'latest'.
|
|
2013
|
+
regexp_flags: Flags for regex behavior (only used when is_regexp=true).
|
|
2014
|
+
String of letters: 'g' (global/replace-all), 'i' (case-insensitive), 'm' (multiline), 's' (dotall).
|
|
2015
|
+
Defaults to empty string (no flags).
|
|
2016
|
+
new_filename: Optional. If provided, saves the result as a new artifact with this name.
|
|
2017
|
+
new_description: Optional. Description for the new/updated artifact.
|
|
2018
|
+
|
|
2019
|
+
Returns:
|
|
2020
|
+
A dictionary containing the result status, filename, version, match count, and any error messages.
|
|
2021
|
+
"""
|
|
2022
|
+
if not tool_context:
|
|
2023
|
+
return {
|
|
2024
|
+
"status": "error",
|
|
2025
|
+
"filename": filename,
|
|
2026
|
+
"message": "ToolContext is missing, cannot perform search and replace.",
|
|
2027
|
+
}
|
|
2028
|
+
|
|
2029
|
+
log_identifier = (
|
|
2030
|
+
f"[BuiltinArtifactTool:artifact_search_and_replace_regex:{filename}:{version}]"
|
|
2031
|
+
)
|
|
2032
|
+
log.debug("%s Processing request.", log_identifier)
|
|
2033
|
+
|
|
2034
|
+
# Validate parameter combinations
|
|
2035
|
+
if replacements is not None and (
|
|
2036
|
+
search_expression is not None or replace_expression is not None
|
|
2037
|
+
):
|
|
2038
|
+
return {
|
|
2039
|
+
"status": "error",
|
|
2040
|
+
"filename": filename,
|
|
2041
|
+
"message": "Cannot provide both 'replacements' array and individual 'search_expression'/'replace_expression'. Use one or the other.",
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2044
|
+
if replacements is None and (
|
|
2045
|
+
search_expression is None or replace_expression is None
|
|
2046
|
+
):
|
|
2047
|
+
return {
|
|
2048
|
+
"status": "error",
|
|
2049
|
+
"filename": filename,
|
|
2050
|
+
"message": "Must provide either 'replacements' array or both 'search_expression' and 'replace_expression'.",
|
|
2051
|
+
}
|
|
2052
|
+
|
|
2053
|
+
if replacements is not None:
|
|
2054
|
+
if not isinstance(replacements, list) or len(replacements) == 0:
|
|
2055
|
+
return {
|
|
2056
|
+
"status": "error",
|
|
2057
|
+
"filename": filename,
|
|
2058
|
+
"message": "replacements must be a non-empty array.",
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
# Validate each replacement entry
|
|
2062
|
+
for idx, repl in enumerate(replacements):
|
|
2063
|
+
if not isinstance(repl, dict):
|
|
2064
|
+
return {
|
|
2065
|
+
"status": "error",
|
|
2066
|
+
"filename": filename,
|
|
2067
|
+
"message": f"Replacement at index {idx} must be a dictionary.",
|
|
2068
|
+
}
|
|
2069
|
+
if "search" not in repl or "replace" not in repl or "is_regexp" not in repl:
|
|
2070
|
+
return {
|
|
2071
|
+
"status": "error",
|
|
2072
|
+
"filename": filename,
|
|
2073
|
+
"message": f"Replacement at index {idx} missing required fields: 'search', 'replace', 'is_regexp'.",
|
|
2074
|
+
}
|
|
2075
|
+
|
|
2076
|
+
# Validate inputs for single replacement mode
|
|
2077
|
+
if replacements is None and not search_expression:
|
|
2078
|
+
return {
|
|
2079
|
+
"status": "error",
|
|
2080
|
+
"filename": filename,
|
|
2081
|
+
"message": "search_expression cannot be empty.",
|
|
2082
|
+
}
|
|
2083
|
+
|
|
2084
|
+
# Determine output filename
|
|
2085
|
+
output_filename = new_filename if new_filename else filename
|
|
2086
|
+
|
|
2087
|
+
if new_filename and not is_filename_safe(new_filename):
|
|
2088
|
+
return {
|
|
2089
|
+
"status": "error",
|
|
2090
|
+
"filename": filename,
|
|
2091
|
+
"message": f"Invalid new_filename: '{new_filename}'. Filename must not contain path separators or traversal sequences.",
|
|
2092
|
+
}
|
|
2093
|
+
|
|
2094
|
+
try:
|
|
2095
|
+
inv_context = tool_context._invocation_context
|
|
2096
|
+
artifact_service = inv_context.artifact_service
|
|
2097
|
+
if not artifact_service:
|
|
2098
|
+
raise ValueError("ArtifactService is not available in the context.")
|
|
2099
|
+
|
|
2100
|
+
app_name = inv_context.app_name
|
|
2101
|
+
user_id = inv_context.user_id
|
|
2102
|
+
session_id = get_original_session_id(inv_context)
|
|
2103
|
+
host_component = getattr(inv_context.agent, "host_component", None)
|
|
2104
|
+
|
|
2105
|
+
# Load the source artifact
|
|
2106
|
+
log.debug(
|
|
2107
|
+
"%s Loading artifact '%s' version '%s'.", log_identifier, filename, version
|
|
2108
|
+
)
|
|
2109
|
+
load_result = await load_artifact_content_or_metadata(
|
|
2110
|
+
artifact_service=artifact_service,
|
|
2111
|
+
app_name=app_name,
|
|
2112
|
+
user_id=user_id,
|
|
2113
|
+
session_id=session_id,
|
|
2114
|
+
filename=filename,
|
|
2115
|
+
version=version,
|
|
2116
|
+
return_raw_bytes=True,
|
|
2117
|
+
component=host_component,
|
|
2118
|
+
log_identifier_prefix=log_identifier,
|
|
2119
|
+
)
|
|
2120
|
+
|
|
2121
|
+
if load_result.get("status") != "success":
|
|
2122
|
+
return {
|
|
2123
|
+
"status": "error",
|
|
2124
|
+
"filename": filename,
|
|
2125
|
+
"version": version,
|
|
2126
|
+
"message": f"Failed to load artifact: {load_result.get('message', 'Unknown error')}",
|
|
2127
|
+
}
|
|
2128
|
+
|
|
2129
|
+
source_bytes = load_result.get("raw_bytes")
|
|
2130
|
+
source_mime_type = load_result.get("mime_type", "application/octet-stream")
|
|
2131
|
+
actual_version = load_result.get("version", version)
|
|
2132
|
+
|
|
2133
|
+
# Verify it's a text-based artifact
|
|
2134
|
+
if not is_text_based_file(source_mime_type, source_bytes):
|
|
2135
|
+
return {
|
|
2136
|
+
"status": "error",
|
|
2137
|
+
"filename": filename,
|
|
2138
|
+
"version": actual_version,
|
|
2139
|
+
"message": f"Cannot perform search and replace on binary artifact of type '{source_mime_type}'. This tool only works with text-based content.",
|
|
2140
|
+
}
|
|
2141
|
+
|
|
2142
|
+
# Decode the content
|
|
2143
|
+
try:
|
|
2144
|
+
original_content = source_bytes.decode("utf-8")
|
|
2145
|
+
except UnicodeDecodeError as decode_err:
|
|
2146
|
+
log.error(
|
|
2147
|
+
"%s Failed to decode artifact content as UTF-8: %s",
|
|
2148
|
+
log_identifier,
|
|
2149
|
+
decode_err,
|
|
2150
|
+
)
|
|
2151
|
+
return {
|
|
2152
|
+
"status": "error",
|
|
2153
|
+
"filename": filename,
|
|
2154
|
+
"version": actual_version,
|
|
2155
|
+
"message": f"Failed to decode artifact content as UTF-8: {decode_err}",
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
# Perform the search and replace
|
|
2159
|
+
if replacements:
|
|
2160
|
+
# Batch mode
|
|
2161
|
+
log.info(
|
|
2162
|
+
"%s Processing batch of %d replacements.",
|
|
2163
|
+
log_identifier,
|
|
2164
|
+
len(replacements),
|
|
2165
|
+
)
|
|
2166
|
+
|
|
2167
|
+
current_content = original_content
|
|
2168
|
+
replacement_results = []
|
|
2169
|
+
total_matches = 0
|
|
2170
|
+
|
|
2171
|
+
for idx, repl in enumerate(replacements):
|
|
2172
|
+
search_expr = repl["search"]
|
|
2173
|
+
replace_expr = repl["replace"]
|
|
2174
|
+
is_regex = repl["is_regexp"]
|
|
2175
|
+
regex_flags = repl.get("regexp_flags", "")
|
|
2176
|
+
|
|
2177
|
+
# Perform replacement on current state (with strict validation for batch mode)
|
|
2178
|
+
new_content, match_count, error_msg = _perform_single_replacement(
|
|
2179
|
+
current_content,
|
|
2180
|
+
search_expr,
|
|
2181
|
+
replace_expr,
|
|
2182
|
+
is_regex,
|
|
2183
|
+
regex_flags,
|
|
2184
|
+
log_identifier,
|
|
2185
|
+
strict_match_validation=True,
|
|
2186
|
+
)
|
|
2187
|
+
|
|
2188
|
+
if error_msg:
|
|
2189
|
+
# Rollback - return error with details
|
|
2190
|
+
log.warning(
|
|
2191
|
+
"%s Batch replacement failed at index %d: %s",
|
|
2192
|
+
log_identifier,
|
|
2193
|
+
idx,
|
|
2194
|
+
error_msg,
|
|
2195
|
+
)
|
|
2196
|
+
|
|
2197
|
+
# Mark all as skipped
|
|
2198
|
+
all_results = replacement_results + [
|
|
2199
|
+
{
|
|
2200
|
+
"search": repl["search"],
|
|
2201
|
+
"match_count": match_count,
|
|
2202
|
+
"status": "error",
|
|
2203
|
+
"error": error_msg,
|
|
2204
|
+
}
|
|
2205
|
+
]
|
|
2206
|
+
# Add remaining as skipped
|
|
2207
|
+
for i in range(idx + 1, len(replacements)):
|
|
2208
|
+
all_results.append(
|
|
2209
|
+
{
|
|
2210
|
+
"search": replacements[i]["search"],
|
|
2211
|
+
"match_count": 0,
|
|
2212
|
+
"status": "skipped",
|
|
2213
|
+
}
|
|
2214
|
+
)
|
|
2215
|
+
|
|
2216
|
+
return {
|
|
2217
|
+
"status": "error",
|
|
2218
|
+
"filename": filename,
|
|
2219
|
+
"version": actual_version,
|
|
2220
|
+
"message": f"Batch replacement failed: No changes applied due to error in replacement {idx + 1}",
|
|
2221
|
+
"replacement_results": all_results,
|
|
2222
|
+
"failed_replacement": {
|
|
2223
|
+
"index": idx,
|
|
2224
|
+
"search": search_expr,
|
|
2225
|
+
"error": error_msg,
|
|
2226
|
+
},
|
|
2227
|
+
}
|
|
2228
|
+
|
|
2229
|
+
# Success - update state and continue
|
|
2230
|
+
current_content = new_content
|
|
2231
|
+
total_matches += match_count
|
|
2232
|
+
replacement_results.append(
|
|
2233
|
+
{
|
|
2234
|
+
"search": search_expr,
|
|
2235
|
+
"match_count": match_count,
|
|
2236
|
+
"status": "success",
|
|
2237
|
+
}
|
|
2238
|
+
)
|
|
2239
|
+
|
|
2240
|
+
log.debug(
|
|
2241
|
+
"%s Replacement %d/%d succeeded: %d matches",
|
|
2242
|
+
log_identifier,
|
|
2243
|
+
idx + 1,
|
|
2244
|
+
len(replacements),
|
|
2245
|
+
match_count,
|
|
2246
|
+
)
|
|
2247
|
+
|
|
2248
|
+
# All replacements succeeded
|
|
2249
|
+
final_content = current_content
|
|
2250
|
+
total_replacements = len(replacements)
|
|
2251
|
+
|
|
2252
|
+
log.info(
|
|
2253
|
+
"%s Batch replacement succeeded: %d operations, %d total matches",
|
|
2254
|
+
log_identifier,
|
|
2255
|
+
total_replacements,
|
|
2256
|
+
total_matches,
|
|
2257
|
+
)
|
|
2258
|
+
|
|
2259
|
+
else:
|
|
2260
|
+
# Single replacement mode (backward compatible)
|
|
2261
|
+
final_content, match_count, error_msg = _perform_single_replacement(
|
|
2262
|
+
original_content,
|
|
2263
|
+
search_expression,
|
|
2264
|
+
replace_expression,
|
|
2265
|
+
is_regexp,
|
|
2266
|
+
regexp_flags,
|
|
2267
|
+
log_identifier,
|
|
2268
|
+
)
|
|
2269
|
+
|
|
2270
|
+
if error_msg:
|
|
2271
|
+
# Check if it's a "no matches" error specifically
|
|
2272
|
+
if match_count == 0 and "No matches found" in error_msg:
|
|
2273
|
+
return {
|
|
2274
|
+
"status": "no_matches",
|
|
2275
|
+
"filename": filename,
|
|
2276
|
+
"version": actual_version,
|
|
2277
|
+
"match_count": 0,
|
|
2278
|
+
"message": f"No matches found for pattern '{search_expression}'. Artifact not modified.",
|
|
2279
|
+
}
|
|
2280
|
+
else:
|
|
2281
|
+
return {
|
|
2282
|
+
"status": "error",
|
|
2283
|
+
"filename": filename,
|
|
2284
|
+
"version": actual_version,
|
|
2285
|
+
"message": error_msg,
|
|
2286
|
+
}
|
|
2287
|
+
|
|
2288
|
+
total_replacements = 1
|
|
2289
|
+
total_matches = match_count
|
|
2290
|
+
replacement_results = None
|
|
2291
|
+
|
|
2292
|
+
# Prepare metadata for the new/updated artifact
|
|
2293
|
+
if replacements:
|
|
2294
|
+
new_metadata = {
|
|
2295
|
+
"source": f"artifact_search_and_replace_regex (batch) from '{filename}' v{actual_version}",
|
|
2296
|
+
"total_replacements": total_replacements,
|
|
2297
|
+
"total_matches": total_matches,
|
|
2298
|
+
}
|
|
2299
|
+
else:
|
|
2300
|
+
new_metadata = {
|
|
2301
|
+
"source": f"artifact_search_and_replace_regex from '{filename}' v{actual_version}",
|
|
2302
|
+
"search_expression": search_expression,
|
|
2303
|
+
"replace_expression": replace_expression,
|
|
2304
|
+
"is_regexp": is_regexp,
|
|
2305
|
+
"match_count": match_count,
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2308
|
+
if regexp_flags and is_regexp:
|
|
2309
|
+
new_metadata["regexp_flags"] = regexp_flags
|
|
2310
|
+
|
|
2311
|
+
if new_description:
|
|
2312
|
+
new_metadata["description"] = new_description
|
|
2313
|
+
elif not new_filename:
|
|
2314
|
+
# If updating the same artifact, preserve original description if available
|
|
2315
|
+
try:
|
|
2316
|
+
metadata_load_result = await load_artifact_content_or_metadata(
|
|
2317
|
+
artifact_service=artifact_service,
|
|
2318
|
+
app_name=app_name,
|
|
2319
|
+
user_id=user_id,
|
|
2320
|
+
session_id=session_id,
|
|
2321
|
+
filename=filename,
|
|
2322
|
+
version=actual_version,
|
|
2323
|
+
load_metadata_only=True,
|
|
2324
|
+
component=host_component,
|
|
2325
|
+
log_identifier_prefix=log_identifier,
|
|
2326
|
+
)
|
|
2327
|
+
if metadata_load_result.get("status") == "success":
|
|
2328
|
+
original_metadata = metadata_load_result.get("metadata", {})
|
|
2329
|
+
if "description" in original_metadata:
|
|
2330
|
+
new_metadata["description"] = original_metadata["description"]
|
|
2331
|
+
except Exception as meta_err:
|
|
2332
|
+
log.warning(
|
|
2333
|
+
"%s Could not load original metadata to preserve description: %s",
|
|
2334
|
+
log_identifier,
|
|
2335
|
+
meta_err,
|
|
2336
|
+
)
|
|
2337
|
+
|
|
2338
|
+
# Save the result
|
|
2339
|
+
new_content_bytes = final_content.encode("utf-8")
|
|
2340
|
+
schema_max_keys = (
|
|
2341
|
+
host_component.get_config("schema_max_keys", DEFAULT_SCHEMA_MAX_KEYS)
|
|
2342
|
+
if host_component
|
|
2343
|
+
else DEFAULT_SCHEMA_MAX_KEYS
|
|
2344
|
+
)
|
|
2345
|
+
|
|
2346
|
+
save_result = await save_artifact_with_metadata(
|
|
2347
|
+
artifact_service=artifact_service,
|
|
2348
|
+
app_name=app_name,
|
|
2349
|
+
user_id=user_id,
|
|
2350
|
+
session_id=session_id,
|
|
2351
|
+
filename=output_filename,
|
|
2352
|
+
content_bytes=new_content_bytes,
|
|
2353
|
+
mime_type=source_mime_type,
|
|
2354
|
+
metadata_dict=new_metadata,
|
|
2355
|
+
timestamp=datetime.now(timezone.utc),
|
|
2356
|
+
schema_max_keys=schema_max_keys,
|
|
2357
|
+
tool_context=tool_context,
|
|
2358
|
+
)
|
|
2359
|
+
|
|
2360
|
+
if save_result.get("status") not in ["success", "partial_success"]:
|
|
2361
|
+
log.error(
|
|
2362
|
+
"%s Failed to save modified artifact: %s",
|
|
2363
|
+
log_identifier,
|
|
2364
|
+
save_result.get("message"),
|
|
2365
|
+
)
|
|
2366
|
+
return {
|
|
2367
|
+
"status": "error",
|
|
2368
|
+
"filename": filename,
|
|
2369
|
+
"version": actual_version,
|
|
2370
|
+
"message": f"Search and replace succeeded, but failed to save result: {save_result.get('message')}",
|
|
2371
|
+
}
|
|
2372
|
+
|
|
2373
|
+
result_version = save_result.get("data_version")
|
|
2374
|
+
log.info(
|
|
2375
|
+
"%s Successfully saved modified artifact '%s' as version %s.",
|
|
2376
|
+
log_identifier,
|
|
2377
|
+
output_filename,
|
|
2378
|
+
result_version,
|
|
2379
|
+
)
|
|
2380
|
+
|
|
2381
|
+
# Return appropriate response based on mode
|
|
2382
|
+
if replacements:
|
|
2383
|
+
return {
|
|
2384
|
+
"status": "success",
|
|
2385
|
+
"source_filename": filename,
|
|
2386
|
+
"source_version": actual_version,
|
|
2387
|
+
"output_filename": output_filename,
|
|
2388
|
+
"output_version": result_version,
|
|
2389
|
+
"total_replacements": total_replacements,
|
|
2390
|
+
"replacement_results": replacement_results,
|
|
2391
|
+
"total_matches": total_matches,
|
|
2392
|
+
"message": f"Batch replacement completed: {total_replacements} operations, {total_matches} total matches",
|
|
2393
|
+
}
|
|
2394
|
+
else:
|
|
2395
|
+
# Compute replacements_made for backward compatibility
|
|
2396
|
+
# For literal replacements, all matches are replaced
|
|
2397
|
+
# For regex without 'g' flag, only first match is replaced
|
|
2398
|
+
global_replace = "g" in (regexp_flags or "")
|
|
2399
|
+
replacements_made = (
|
|
2400
|
+
match_count if not is_regexp or global_replace else min(match_count, 1)
|
|
2401
|
+
)
|
|
2402
|
+
|
|
2403
|
+
return {
|
|
2404
|
+
"status": "success",
|
|
2405
|
+
"source_filename": filename,
|
|
2406
|
+
"source_version": actual_version,
|
|
2407
|
+
"output_filename": output_filename,
|
|
2408
|
+
"output_version": result_version,
|
|
2409
|
+
"match_count": match_count,
|
|
2410
|
+
"replacements_made": replacements_made,
|
|
2411
|
+
"message": f"Successfully performed {'regex' if is_regexp else 'literal'} search and replace. "
|
|
2412
|
+
f"Found {match_count} match(es), saved result as '{output_filename}' v{result_version}.",
|
|
2413
|
+
}
|
|
2414
|
+
|
|
2415
|
+
except FileNotFoundError as fnf_err:
|
|
2416
|
+
log.warning("%s Artifact not found: %s", log_identifier, fnf_err)
|
|
2417
|
+
return {
|
|
2418
|
+
"status": "error",
|
|
2419
|
+
"filename": filename,
|
|
2420
|
+
"version": version,
|
|
2421
|
+
"message": f"Artifact not found: {fnf_err}",
|
|
2422
|
+
}
|
|
2423
|
+
except Exception as e:
|
|
2424
|
+
log.exception(
|
|
2425
|
+
"%s Unexpected error during search and replace: %s", log_identifier, e
|
|
2426
|
+
)
|
|
2427
|
+
return {
|
|
2428
|
+
"status": "error",
|
|
2429
|
+
"filename": filename,
|
|
2430
|
+
"version": version,
|
|
2431
|
+
"message": f"Unexpected error: {e}",
|
|
2432
|
+
}
|
|
2433
|
+
|
|
2434
|
+
|
|
2435
|
+
artifact_search_and_replace_regex_tool_def = BuiltinTool(
|
|
2436
|
+
name="artifact_search_and_replace_regex",
|
|
2437
|
+
implementation=artifact_search_and_replace_regex,
|
|
2438
|
+
description="Performs search and replace on an artifact's text content using either literal string matching or regular expressions. Supports both single replacements and atomic batch replacements for efficiency.",
|
|
2439
|
+
category="artifact_management",
|
|
2440
|
+
category_name=CATEGORY_NAME,
|
|
2441
|
+
category_description=CATEGORY_DESCRIPTION,
|
|
2442
|
+
required_scopes=["tool:artifact:load", "tool:artifact:create"],
|
|
2443
|
+
parameters=adk_types.Schema(
|
|
2444
|
+
type=adk_types.Type.OBJECT,
|
|
2445
|
+
properties={
|
|
2446
|
+
"filename": adk_types.Schema(
|
|
2447
|
+
type=adk_types.Type.STRING,
|
|
2448
|
+
description="The name of the artifact to search/replace in.",
|
|
2449
|
+
),
|
|
2450
|
+
"search_expression": adk_types.Schema(
|
|
2451
|
+
type=adk_types.Type.STRING,
|
|
2452
|
+
description="The pattern to search for (single replacement mode). If is_regexp is true, this is treated as a regular expression. Otherwise, it's a literal string. Do not use if 'replacements' is provided.",
|
|
2453
|
+
nullable=True,
|
|
2454
|
+
),
|
|
2455
|
+
"replace_expression": adk_types.Schema(
|
|
2456
|
+
type=adk_types.Type.STRING,
|
|
2457
|
+
description="The replacement text (single replacement mode). For regex mode, supports capture group references using $1, $2, etc. Use $$ to insert a literal dollar sign. Do not use if 'replacements' is provided.",
|
|
2458
|
+
nullable=True,
|
|
2459
|
+
),
|
|
2460
|
+
"is_regexp": adk_types.Schema(
|
|
2461
|
+
type=adk_types.Type.BOOLEAN,
|
|
2462
|
+
description="If true, treat search_expression as a regular expression. If false, treat as literal string. Only used in single replacement mode.",
|
|
2463
|
+
nullable=True,
|
|
2464
|
+
),
|
|
2465
|
+
"version": adk_types.Schema(
|
|
2466
|
+
type=adk_types.Type.STRING,
|
|
2467
|
+
description="The version of the artifact to operate on. Can be an integer version number or 'latest'. Defaults to 'latest'.",
|
|
2468
|
+
nullable=True,
|
|
2469
|
+
),
|
|
2470
|
+
"regexp_flags": adk_types.Schema(
|
|
2471
|
+
type=adk_types.Type.STRING,
|
|
2472
|
+
description="Flags for regex behavior (only used when is_regexp=true in single mode). String of letters: 'g' (global/replace all), 'i' (case-insensitive), 'm' (multiline), 's' (dotall). Example: 'gim'. Defaults to empty string.",
|
|
2473
|
+
nullable=True,
|
|
2474
|
+
),
|
|
2475
|
+
"new_filename": adk_types.Schema(
|
|
2476
|
+
type=adk_types.Type.STRING,
|
|
2477
|
+
description="Optional. If provided, saves the result as a new artifact with this name instead of creating a new version of the original.",
|
|
2478
|
+
nullable=True,
|
|
2479
|
+
),
|
|
2480
|
+
"new_description": adk_types.Schema(
|
|
2481
|
+
type=adk_types.Type.STRING,
|
|
2482
|
+
description="Optional. Description for the new/updated artifact.",
|
|
2483
|
+
nullable=True,
|
|
2484
|
+
),
|
|
2485
|
+
"replacements": adk_types.Schema(
|
|
2486
|
+
type=adk_types.Type.ARRAY,
|
|
2487
|
+
items=adk_types.Schema(
|
|
2488
|
+
type=adk_types.Type.OBJECT,
|
|
2489
|
+
properties={
|
|
2490
|
+
"search": adk_types.Schema(
|
|
2491
|
+
type=adk_types.Type.STRING,
|
|
2492
|
+
description="The search pattern (literal string or regex).",
|
|
2493
|
+
),
|
|
2494
|
+
"replace": adk_types.Schema(
|
|
2495
|
+
type=adk_types.Type.STRING,
|
|
2496
|
+
description="The replacement text. For regex mode, supports $1, $2, etc. Use $$ for literal $.",
|
|
2497
|
+
),
|
|
2498
|
+
"is_regexp": adk_types.Schema(
|
|
2499
|
+
type=adk_types.Type.BOOLEAN,
|
|
2500
|
+
description="If true, 'search' is a regex pattern. If false, literal string.",
|
|
2501
|
+
),
|
|
2502
|
+
"regexp_flags": adk_types.Schema(
|
|
2503
|
+
type=adk_types.Type.STRING,
|
|
2504
|
+
description="Flags for regex: 'g' (global), 'i' (case-insensitive), 'm' (multiline), 's' (dotall). Default: ''.",
|
|
2505
|
+
nullable=True,
|
|
2506
|
+
),
|
|
2507
|
+
},
|
|
2508
|
+
required=["search", "replace", "is_regexp"],
|
|
2509
|
+
),
|
|
2510
|
+
description="Optional. Array of replacement operations to perform atomically. Each operation is processed sequentially on the cumulative result. If any operation fails, all changes are rolled back. Do not use with 'search_expression' or 'replace_expression'.",
|
|
2511
|
+
nullable=True,
|
|
2512
|
+
),
|
|
2513
|
+
},
|
|
2514
|
+
required=["filename"],
|
|
2515
|
+
),
|
|
2516
|
+
examples=[],
|
|
2517
|
+
)
|
|
2518
|
+
|
|
2519
|
+
tool_registry.register(artifact_search_and_replace_regex_tool_def)
|