agentcore-cli 0.31.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agentcore/__init__.py +1 -0
- agentcore/agent_inspector/NOTICE +9 -0
- agentcore/agent_inspector/favicon.svg +60 -0
- agentcore/agent_inspector/index.css +1 -0
- agentcore/agent_inspector/index.html +14 -0
- agentcore/agent_inspector/index.js +289 -0
- agentcore/assets/AGENTS.md +60 -0
- agentcore/assets/README.md +108 -0
- agentcore/assets/agents/AGENTS.md +218 -0
- agentcore/assets/cdk/.prettierrc +8 -0
- agentcore/assets/cdk/README.md +26 -0
- agentcore/assets/cdk/bin/cdk.ts +216 -0
- agentcore/assets/cdk/cdk.json +88 -0
- agentcore/assets/cdk/gitignore.template +9 -0
- agentcore/assets/cdk/jest.config.js +9 -0
- agentcore/assets/cdk/lib/cdk-stack.ts +291 -0
- agentcore/assets/cdk/npmignore.template +6 -0
- agentcore/assets/cdk/package.json +30 -0
- agentcore/assets/cdk/test/cdk.test.ts +31 -0
- agentcore/assets/cdk/tsconfig.json +28 -0
- agentcore/assets/container/python/Dockerfile +47 -0
- agentcore/assets/container/python/dockerignore.template +27 -0
- agentcore/assets/container/typescript/Dockerfile +25 -0
- agentcore/assets/container/typescript/dockerignore.template +24 -0
- agentcore/assets/datasets/predefined-v1.jsonl +3 -0
- agentcore/assets/datasets/simulated-v1.jsonl +3 -0
- agentcore/assets/evaluators/autoevals-lambda/execution-role-policy.json +15 -0
- agentcore/assets/evaluators/autoevals-lambda/lambda_function.py +37 -0
- agentcore/assets/evaluators/autoevals-lambda/pyproject.toml +22 -0
- agentcore/assets/evaluators/deepeval-lambda/execution-role-policy.json +15 -0
- agentcore/assets/evaluators/deepeval-lambda/lambda_function.py +29 -0
- agentcore/assets/evaluators/deepeval-lambda/pyproject.toml +19 -0
- agentcore/assets/evaluators/python-lambda/execution-role-policy.json +10 -0
- agentcore/assets/evaluators/python-lambda/lambda_function.py +19 -0
- agentcore/assets/evaluators/python-lambda/pyproject.toml +15 -0
- agentcore/assets/harness/invoke.py.template +74 -0
- agentcore/assets/mcp/python/README.md +27 -0
- agentcore/assets/mcp/python/pyproject.toml +22 -0
- agentcore/assets/mcp/python/server.py +117 -0
- agentcore/assets/mcp/python-lambda/README.md +22 -0
- agentcore/assets/mcp/python-lambda/handler.py +144 -0
- agentcore/assets/mcp/python-lambda/pyproject.toml +15 -0
- agentcore/assets/python/a2a/googleadk/base/README.md +22 -0
- agentcore/assets/python/a2a/googleadk/base/gitignore.template +41 -0
- agentcore/assets/python/a2a/googleadk/base/main.py +124 -0
- agentcore/assets/python/a2a/googleadk/base/model/__init__.py +1 -0
- agentcore/assets/python/a2a/googleadk/base/model/load.py +41 -0
- agentcore/assets/python/a2a/googleadk/base/pyproject.toml +22 -0
- agentcore/assets/python/a2a/langchain_langgraph/base/README.md +22 -0
- agentcore/assets/python/a2a/langchain_langgraph/base/gitignore.template +41 -0
- agentcore/assets/python/a2a/langchain_langgraph/base/main.py +144 -0
- agentcore/assets/python/a2a/langchain_langgraph/base/model/__init__.py +1 -0
- agentcore/assets/python/a2a/langchain_langgraph/base/model/load.py +123 -0
- agentcore/assets/python/a2a/langchain_langgraph/base/pyproject.toml +26 -0
- agentcore/assets/python/a2a/strands/base/README.md +22 -0
- agentcore/assets/python/a2a/strands/base/gitignore.template +41 -0
- agentcore/assets/python/a2a/strands/base/main.py +113 -0
- agentcore/assets/python/a2a/strands/base/model/__init__.py +1 -0
- agentcore/assets/python/a2a/strands/base/model/load.py +123 -0
- agentcore/assets/python/a2a/strands/base/pyproject.toml +23 -0
- agentcore/assets/python/a2a/strands/capabilities/memory/__init__.py +1 -0
- agentcore/assets/python/a2a/strands/capabilities/memory/session.py +46 -0
- agentcore/assets/python/agui/googleadk/base/README.md +30 -0
- agentcore/assets/python/agui/googleadk/base/gitignore.template +41 -0
- agentcore/assets/python/agui/googleadk/base/main.py +91 -0
- agentcore/assets/python/agui/googleadk/base/model/__init__.py +1 -0
- agentcore/assets/python/agui/googleadk/base/model/load.py +41 -0
- agentcore/assets/python/agui/googleadk/base/pyproject.toml +25 -0
- agentcore/assets/python/agui/langchain_langgraph/base/README.md +22 -0
- agentcore/assets/python/agui/langchain_langgraph/base/gitignore.template +41 -0
- agentcore/assets/python/agui/langchain_langgraph/base/main.py +130 -0
- agentcore/assets/python/agui/langchain_langgraph/base/model/__init__.py +1 -0
- agentcore/assets/python/agui/langchain_langgraph/base/model/load.py +123 -0
- agentcore/assets/python/agui/langchain_langgraph/base/pyproject.toml +31 -0
- agentcore/assets/python/agui/strands/base/README.md +22 -0
- agentcore/assets/python/agui/strands/base/gitignore.template +41 -0
- agentcore/assets/python/agui/strands/base/main.py +105 -0
- agentcore/assets/python/agui/strands/base/model/__init__.py +1 -0
- agentcore/assets/python/agui/strands/base/model/load.py +123 -0
- agentcore/assets/python/agui/strands/base/pyproject.toml +27 -0
- agentcore/assets/python/agui/strands/capabilities/memory/__init__.py +1 -0
- agentcore/assets/python/agui/strands/capabilities/memory/session.py +46 -0
- agentcore/assets/python/http/autogen/base/README.md +45 -0
- agentcore/assets/python/http/autogen/base/gitignore.template +41 -0
- agentcore/assets/python/http/autogen/base/main.py +145 -0
- agentcore/assets/python/http/autogen/base/mcp_client/__init__.py +1 -0
- agentcore/assets/python/http/autogen/base/mcp_client/client.py +28 -0
- agentcore/assets/python/http/autogen/base/model/__init__.py +1 -0
- agentcore/assets/python/http/autogen/base/model/load.py +136 -0
- agentcore/assets/python/http/autogen/base/pyproject.toml +34 -0
- agentcore/assets/python/http/bma/base/Dockerfile +41 -0
- agentcore/assets/python/http/bma/base/README.md +178 -0
- agentcore/assets/python/http/bma/base/client.py +200 -0
- agentcore/assets/python/http/bma/base/lifecycle/server.py +641 -0
- agentcore/assets/python/http/bma/base/otel/collector.yaml +69 -0
- agentcore/assets/python/http/bma/base/plugins/acr-report/.codex-plugin/plugin.json +6 -0
- agentcore/assets/python/http/bma/base/plugins/acr-report/skills/acr-report/SKILL.md +16 -0
- agentcore/assets/python/http/bma/base/policies/bma-acr-policy.json +11 -0
- agentcore/assets/python/http/bma/base/policies/bma-session-policy.json +35 -0
- agentcore/assets/python/http/bma/base/policies/bma-session-trust.json +20 -0
- agentcore/assets/python/http/bma/base/pyproject.toml +21 -0
- agentcore/assets/python/http/googleadk/base/README.md +45 -0
- agentcore/assets/python/http/googleadk/base/gitignore.template +41 -0
- agentcore/assets/python/http/googleadk/base/main.py +207 -0
- agentcore/assets/python/http/googleadk/base/mcp_client/__init__.py +1 -0
- agentcore/assets/python/http/googleadk/base/mcp_client/client.py +75 -0
- agentcore/assets/python/http/googleadk/base/model/__init__.py +1 -0
- agentcore/assets/python/http/googleadk/base/model/load.py +41 -0
- agentcore/assets/python/http/googleadk/base/pyproject.toml +24 -0
- agentcore/assets/python/http/langchain_langgraph/base/README.md +45 -0
- agentcore/assets/python/http/langchain_langgraph/base/gitignore.template +41 -0
- agentcore/assets/python/http/langchain_langgraph/base/main.py +227 -0
- agentcore/assets/python/http/langchain_langgraph/base/mcp_client/__init__.py +1 -0
- agentcore/assets/python/http/langchain_langgraph/base/mcp_client/client.py +79 -0
- agentcore/assets/python/http/langchain_langgraph/base/model/__init__.py +1 -0
- agentcore/assets/python/http/langchain_langgraph/base/model/load.py +123 -0
- agentcore/assets/python/http/langchain_langgraph/base/pyproject.toml +38 -0
- agentcore/assets/python/http/openaiagents/base/README.md +45 -0
- agentcore/assets/python/http/openaiagents/base/gitignore.template +41 -0
- agentcore/assets/python/http/openaiagents/base/main.py +200 -0
- agentcore/assets/python/http/openaiagents/base/mcp_client/__init__.py +1 -0
- agentcore/assets/python/http/openaiagents/base/mcp_client/client.py +74 -0
- agentcore/assets/python/http/openaiagents/base/model/__init__.py +1 -0
- agentcore/assets/python/http/openaiagents/base/model/load.py +37 -0
- agentcore/assets/python/http/openaiagents/base/pyproject.toml +21 -0
- agentcore/assets/python/http/strands/base/README.md +46 -0
- agentcore/assets/python/http/strands/base/gitignore.template +41 -0
- agentcore/assets/python/http/strands/base/main.py +714 -0
- agentcore/assets/python/http/strands/base/mcp_client/__init__.py +1 -0
- agentcore/assets/python/http/strands/base/mcp_client/client.py +116 -0
- agentcore/assets/python/http/strands/base/model/__init__.py +1 -0
- agentcore/assets/python/http/strands/base/model/load.py +239 -0
- agentcore/assets/python/http/strands/base/model/mantle_compat.py +21 -0
- agentcore/assets/python/http/strands/base/pyproject.toml +31 -0
- agentcore/assets/python/http/strands/base/skills/fetcher.py +279 -0
- agentcore/assets/python/http/strands/capabilities/execution-limits/hooks/execution_limits.py +54 -0
- agentcore/assets/python/http/strands/capabilities/memory/__init__.py +1 -0
- agentcore/assets/python/http/strands/capabilities/memory/session.py +47 -0
- agentcore/assets/python/http/strands/capabilities/payments/__init__.py +4 -0
- agentcore/assets/python/http/strands/capabilities/payments/payments.py +142 -0
- agentcore/assets/python/mcp/standalone/base/README.md +36 -0
- agentcore/assets/python/mcp/standalone/base/gitignore.template +41 -0
- agentcore/assets/python/mcp/standalone/base/main.py +83 -0
- agentcore/assets/python/mcp/standalone/base/pyproject.toml +16 -0
- agentcore/assets/typescript/.gitkeep +0 -0
- agentcore/assets/typescript/http/strands/base/README.md +42 -0
- agentcore/assets/typescript/http/strands/base/gitignore.template +22 -0
- agentcore/assets/typescript/http/strands/base/main.ts +149 -0
- agentcore/assets/typescript/http/strands/base/mcp_client/client.ts +11 -0
- agentcore/assets/typescript/http/strands/base/model/load.ts +102 -0
- agentcore/assets/typescript/http/strands/base/package.json +38 -0
- agentcore/assets/typescript/http/strands/base/tsconfig.json +19 -0
- agentcore/assets/typescript/http/strands/capabilities/memory/memory.ts +52 -0
- agentcore/assets/typescript/http/vercelai/base/README.md +42 -0
- agentcore/assets/typescript/http/vercelai/base/gitignore.template +22 -0
- agentcore/assets/typescript/http/vercelai/base/main.ts +70 -0
- agentcore/assets/typescript/http/vercelai/base/model/load.ts +121 -0
- agentcore/assets/typescript/http/vercelai/base/package.json +35 -0
- agentcore/assets/typescript/http/vercelai/base/tsconfig.json +19 -0
- agentcore/aws/__init__.py +263 -0
- agentcore/aws/_aws_errors.py +72 -0
- agentcore/aws/_http.py +176 -0
- agentcore/aws/_util.py +37 -0
- agentcore/aws/account.py +165 -0
- agentcore/aws/agentcore.py +971 -0
- agentcore/aws/agentcore_ab_tests.py +230 -0
- agentcore/aws/agentcore_batch_evaluation.py +227 -0
- agentcore/aws/agentcore_config_bundles.py +220 -0
- agentcore/aws/agentcore_control.py +994 -0
- agentcore/aws/agentcore_datasets.py +222 -0
- agentcore/aws/agentcore_harness.py +330 -0
- agentcore/aws/agentcore_payments.py +430 -0
- agentcore/aws/agentcore_recommendation.py +140 -0
- agentcore/aws/agui_parser.py +131 -0
- agentcore/aws/agui_types.py +342 -0
- agentcore/aws/api_client.py +87 -0
- agentcore/aws/arn.py +18 -0
- agentcore/aws/aws_context.py +23 -0
- agentcore/aws/bedrock.py +44 -0
- agentcore/aws/bedrock_agent.py +129 -0
- agentcore/aws/bedrock_import.py +252 -0
- agentcore/aws/bedrock_import_types.py +111 -0
- agentcore/aws/cloudwatch.py +136 -0
- agentcore/aws/connect_shell.py +266 -0
- agentcore/aws/iam.py +41 -0
- agentcore/aws/partition.py +58 -0
- agentcore/aws/policy_generation.py +116 -0
- agentcore/aws/region.py +54 -0
- agentcore/aws/retry.py +27 -0
- agentcore/aws/shell_framer.py +136 -0
- agentcore/aws/stage_endpoint.py +39 -0
- agentcore/aws/target_region.py +54 -0
- agentcore/aws/transaction_search.py +97 -0
- agentcore/cdk/__init__.py +10 -0
- agentcore/cdk/constants.py +13 -0
- agentcore/cdk/local_cdk_project.py +48 -0
- agentcore/cdk/toolkit.py +706 -0
- agentcore/cli/__init__.py +0 -0
- agentcore/cli/commands/__init__.py +0 -0
- agentcore/cli/commands/_jobs_common.py +39 -0
- agentcore/cli/commands/_run_wizards.py +639 -0
- agentcore/cli/commands/add/__init__.py +37 -0
- agentcore/cli/commands/add/_commander.py +52 -0
- agentcore/cli/commands/add/_common.py +47 -0
- agentcore/cli/commands/add/agent_wizard.py +528 -0
- agentcore/cli/commands/add/auth_options.py +154 -0
- agentcore/cli/commands/add/skill_action.py +105 -0
- agentcore/cli/commands/add/skill_command.py +87 -0
- agentcore/cli/commands/add/tool_action.py +160 -0
- agentcore/cli/commands/add/tool_command.py +117 -0
- agentcore/cli/commands/add/validate.py +333 -0
- agentcore/cli/commands/capacity_provider/__init__.py +86 -0
- agentcore/cli/commands/capacity_provider/action.py +114 -0
- agentcore/cli/commands/capacity_provider/constants.py +22 -0
- agentcore/cli/commands/config.py +91 -0
- agentcore/cli/commands/config_bundle.py +251 -0
- agentcore/cli/commands/create/__init__.py +643 -0
- agentcore/cli/commands/create/action.py +406 -0
- agentcore/cli/commands/create/dependencies.py +91 -0
- agentcore/cli/commands/create/harness_validate.py +82 -0
- agentcore/cli/commands/create/validate.py +195 -0
- agentcore/cli/commands/create/wizard.py +127 -0
- agentcore/cli/commands/dataset.py +119 -0
- agentcore/cli/commands/deploy/__init__.py +31 -0
- agentcore/cli/commands/deploy/_guards.py +25 -0
- agentcore/cli/commands/deploy/actions.py +840 -0
- agentcore/cli/commands/deploy/command.py +349 -0
- agentcore/cli/commands/deploy/progress.py +115 -0
- agentcore/cli/commands/deploy/types.py +68 -0
- agentcore/cli/commands/deploy/utils.py +43 -0
- agentcore/cli/commands/deploy/validate.py +21 -0
- agentcore/cli/commands/dev/__init__.py +5 -0
- agentcore/cli/commands/dev/_deps.py +50 -0
- agentcore/cli/commands/dev/browser_mode.py +270 -0
- agentcore/cli/commands/dev/command.py +450 -0
- agentcore/cli/commands/dev/terminal_mode.py +379 -0
- agentcore/cli/commands/exec/__init__.py +29 -0
- agentcore/cli/commands/exec/action.py +442 -0
- agentcore/cli/commands/exec/command.py +206 -0
- agentcore/cli/commands/exec/types.py +35 -0
- agentcore/cli/commands/export/__init__.py +114 -0
- agentcore/cli/commands/export/constants.py +21 -0
- agentcore/cli/commands/export/fetch_harness_spec.py +234 -0
- agentcore/cli/commands/export/harness_action.py +385 -0
- agentcore/cli/commands/export/harness_mapper.py +868 -0
- agentcore/cli/commands/export/harness_resolver.py +95 -0
- agentcore/cli/commands/export/types.py +90 -0
- agentcore/cli/commands/export/wizard.py +97 -0
- agentcore/cli/commands/feedback/__init__.py +69 -0
- agentcore/cli/commands/feedback/action.py +30 -0
- agentcore/cli/commands/feedback/consent_prompt.py +35 -0
- agentcore/cli/commands/feedback/wizard.py +49 -0
- agentcore/cli/commands/fetch/__init__.py +69 -0
- agentcore/cli/commands/fetch/action.py +62 -0
- agentcore/cli/commands/help.py +65 -0
- agentcore/cli/commands/import_/__init__.py +167 -0
- agentcore/cli/commands/import_/_js.py +72 -0
- agentcore/cli/commands/import_/actions.py +457 -0
- agentcore/cli/commands/import_/constants.py +45 -0
- agentcore/cli/commands/import_/import_evaluator.py +140 -0
- agentcore/cli/commands/import_/import_gateway.py +520 -0
- agentcore/cli/commands/import_/import_memory.py +128 -0
- agentcore/cli/commands/import_/import_online_eval.py +165 -0
- agentcore/cli/commands/import_/import_pipeline.py +145 -0
- agentcore/cli/commands/import_/import_runtime.py +214 -0
- agentcore/cli/commands/import_/import_utils.py +410 -0
- agentcore/cli/commands/import_/phase1_update.py +110 -0
- agentcore/cli/commands/import_/phase2_import.py +206 -0
- agentcore/cli/commands/import_/resource_import.py +228 -0
- agentcore/cli/commands/import_/template_utils.py +148 -0
- agentcore/cli/commands/import_/types.py +150 -0
- agentcore/cli/commands/import_/yaml_parser.py +265 -0
- agentcore/cli/commands/init.py +196 -0
- agentcore/cli/commands/invoke/__init__.py +32 -0
- agentcore/cli/commands/invoke/_deps.py +73 -0
- agentcore/cli/commands/invoke/action.py +840 -0
- agentcore/cli/commands/invoke/command.py +490 -0
- agentcore/cli/commands/invoke/constants.py +40 -0
- agentcore/cli/commands/invoke/guards.py +23 -0
- agentcore/cli/commands/invoke/interactive.py +604 -0
- agentcore/cli/commands/invoke/resolve.py +149 -0
- agentcore/cli/commands/invoke/resolve_prompt.py +60 -0
- agentcore/cli/commands/invoke/types.py +61 -0
- agentcore/cli/commands/invoke/validate.py +33 -0
- agentcore/cli/commands/job_actions.py +239 -0
- agentcore/cli/commands/job_history.py +380 -0
- agentcore/cli/commands/logs/__init__.py +53 -0
- agentcore/cli/commands/logs/action.py +159 -0
- agentcore/cli/commands/logs/filter_pattern.py +17 -0
- agentcore/cli/commands/logs/guards.py +51 -0
- agentcore/cli/commands/logs_evals.py +42 -0
- agentcore/cli/commands/package.py +118 -0
- agentcore/cli/commands/remove/__init__.py +172 -0
- agentcore/cli/commands/remove/skill_command.py +131 -0
- agentcore/cli/commands/remove/tool_command.py +59 -0
- agentcore/cli/commands/run.py +808 -0
- agentcore/cli/commands/run_ingest.py +97 -0
- agentcore/cli/commands/shared/__init__.py +0 -0
- agentcore/cli/commands/shared/arn_utils.py +9 -0
- agentcore/cli/commands/shared/filesystem_utils.py +421 -0
- agentcore/cli/commands/shared/header_utils.py +87 -0
- agentcore/cli/commands/shared/indexed_key_parser.py +76 -0
- agentcore/cli/commands/shared/lifecycle_utils.py +72 -0
- agentcore/cli/commands/shared/region_utils.py +20 -0
- agentcore/cli/commands/shared/vpc_utils.py +99 -0
- agentcore/cli/commands/status/__init__.py +30 -0
- agentcore/cli/commands/status/_guards.py +25 -0
- agentcore/cli/commands/status/action.py +741 -0
- agentcore/cli/commands/status/command.py +321 -0
- agentcore/cli/commands/status/constants.py +36 -0
- agentcore/cli/commands/status/format_knowledge_base.py +111 -0
- agentcore/cli/commands/telemetry.py +79 -0
- agentcore/cli/commands/traces/__init__.py +155 -0
- agentcore/cli/commands/traces/action.py +123 -0
- agentcore/cli/commands/update/__init__.py +63 -0
- agentcore/cli/commands/update/action.py +164 -0
- agentcore/cli/commands/validate.py +165 -0
- agentcore/cli/constants.py +96 -0
- agentcore/cli/errors.py +118 -0
- agentcore/cli/external_requirements/__init__.py +67 -0
- agentcore/cli/external_requirements/checks.py +280 -0
- agentcore/cli/external_requirements/detect.py +55 -0
- agentcore/cli/external_requirements/versions.py +57 -0
- agentcore/cli/groups.py +23 -0
- agentcore/cli/interactive.py +85 -0
- agentcore/cli/main.py +137 -0
- agentcore/cli/naming.py +11 -0
- agentcore/cli/notices.py +42 -0
- agentcore/cli/project.py +34 -0
- agentcore/cli/run_command.py +27 -0
- agentcore/cli/tree.py +135 -0
- agentcore/cli/update_notifier.py +123 -0
- agentcore/cli/variadic.py +50 -0
- agentcore/cloudformation/__init__.py +84 -0
- agentcore/cloudformation/bootstrap.py +64 -0
- agentcore/cloudformation/logical_ids.py +37 -0
- agentcore/cloudformation/outputs.py +566 -0
- agentcore/cloudformation/stack_discovery.py +75 -0
- agentcore/cloudformation/stack_events.py +107 -0
- agentcore/cloudformation/stack_status.py +98 -0
- agentcore/cloudformation/types.py +44 -0
- agentcore/lib/__init__.py +68 -0
- agentcore/lib/constants.py +77 -0
- agentcore/lib/dependency_management/__init__.py +23 -0
- agentcore/lib/dependency_management/messages.py +92 -0
- agentcore/lib/dependency_management/plan.py +98 -0
- agentcore/lib/dependency_management/semver.py +137 -0
- agentcore/lib/dependency_management/sync.py +139 -0
- agentcore/lib/dependency_management/types.py +56 -0
- agentcore/lib/errors/__init__.py +5 -0
- agentcore/lib/errors/types.py +352 -0
- agentcore/lib/errors/validation.py +121 -0
- agentcore/lib/packaging/__init__.py +81 -0
- agentcore/lib/packaging/build_args.py +23 -0
- agentcore/lib/packaging/build_context.py +26 -0
- agentcore/lib/packaging/build_context_dockerignore.py +45 -0
- agentcore/lib/packaging/container.py +95 -0
- agentcore/lib/packaging/helpers.py +289 -0
- agentcore/lib/packaging/node.py +153 -0
- agentcore/lib/packaging/python.py +135 -0
- agentcore/lib/packaging/types.py +69 -0
- agentcore/lib/packaging/uv.py +45 -0
- agentcore/lib/result.py +104 -0
- agentcore/lib/schemas/__init__.py +1 -0
- agentcore/lib/schemas/io/__init__.py +27 -0
- agentcore/lib/schemas/io/config_io.py +458 -0
- agentcore/lib/schemas/io/global_config.py +239 -0
- agentcore/lib/schemas/io/path_resolver.py +132 -0
- agentcore/lib/secrets/__init__.py +18 -0
- agentcore/lib/secrets/cipher.py +70 -0
- agentcore/lib/secrets/key_provider.py +163 -0
- agentcore/lib/secrets/sensitive_keys.py +55 -0
- agentcore/lib/time_constants.py +4 -0
- agentcore/lib/utils/__init__.py +47 -0
- agentcore/lib/utils/aws_account.py +15 -0
- agentcore/lib/utils/credentials.py +68 -0
- agentcore/lib/utils/dotenv.py +32 -0
- agentcore/lib/utils/env.py +105 -0
- agentcore/lib/utils/json_format.py +29 -0
- agentcore/lib/utils/json_rpc.py +22 -0
- agentcore/lib/utils/platform.py +33 -0
- agentcore/lib/utils/polling.py +86 -0
- agentcore/lib/utils/subprocess.py +135 -0
- agentcore/lib/utils/time_parser.py +48 -0
- agentcore/lib/utils/validation.py +106 -0
- agentcore/logging/__init__.py +10 -0
- agentcore/logging/_common.py +77 -0
- agentcore/logging/cdk_io_host.py +36 -0
- agentcore/logging/create_logger.py +107 -0
- agentcore/logging/dev_logger.py +63 -0
- agentcore/logging/exec_logger.py +159 -0
- agentcore/logging/invoke_logger.py +154 -0
- agentcore/logging/remove_logger.py +95 -0
- agentcore/operations/__init__.py +0 -0
- agentcore/operations/agent/__init__.py +0 -0
- agentcore/operations/agent/config_bundle_defaults.py +31 -0
- agentcore/operations/agent/generate/__init__.py +28 -0
- agentcore/operations/agent/generate/schema_mapper.py +319 -0
- agentcore/operations/agent/generate/types.py +172 -0
- agentcore/operations/agent/generate/write_agent_to_project.py +67 -0
- agentcore/operations/agent/import_/__init__.py +31 -0
- agentcore/operations/agent/import_/base_translator.py +449 -0
- agentcore/operations/agent/import_/constants.py +23 -0
- agentcore/operations/agent/import_/execute.py +127 -0
- agentcore/operations/agent/import_/langgraph_translator.py +294 -0
- agentcore/operations/agent/import_/pyproject_generator.py +73 -0
- agentcore/operations/agent/import_/strands_translator.py +289 -0
- agentcore/operations/config_bundle/__init__.py +1 -0
- agentcore/operations/config_bundle/bundle_name_variants.py +9 -0
- agentcore/operations/config_bundle/diff_versions.py +52 -0
- agentcore/operations/config_bundle/resolve_bundle.py +65 -0
- agentcore/operations/connectors/__init__.py +3 -0
- agentcore/operations/connectors/translators.py +63 -0
- agentcore/operations/dataset/__init__.py +21 -0
- agentcore/operations/dataset/delete.py +7 -0
- agentcore/operations/dataset/publish.py +16 -0
- agentcore/operations/dataset/pull.py +21 -0
- agentcore/operations/dataset/push.py +201 -0
- agentcore/operations/dataset/resolve_dataset.py +65 -0
- agentcore/operations/dataset/status.py +18 -0
- agentcore/operations/dataset/wait.py +25 -0
- agentcore/operations/deploy/__init__.py +152 -0
- agentcore/operations/deploy/backfill_vpc_id.py +90 -0
- agentcore/operations/deploy/change_detection.py +84 -0
- agentcore/operations/deploy/constants.py +58 -0
- agentcore/operations/deploy/dependency_sync.py +105 -0
- agentcore/operations/deploy/ensure_target.py +30 -0
- agentcore/operations/deploy/gateway_status.py +44 -0
- agentcore/operations/deploy/managed_memory_notice.py +36 -0
- agentcore/operations/deploy/payment_connector_authorization.py +106 -0
- agentcore/operations/deploy/post_deploy_datasets.py +96 -0
- agentcore/operations/deploy/post_deploy_knowledge_bases.py +104 -0
- agentcore/operations/deploy/post_deploy_observability.py +28 -0
- agentcore/operations/deploy/post_deploy_online_evals.py +60 -0
- agentcore/operations/deploy/pre_deploy_identity.py +505 -0
- agentcore/operations/deploy/preflight.py +385 -0
- agentcore/operations/deploy/region_override.py +45 -0
- agentcore/operations/deploy/teardown.py +153 -0
- agentcore/operations/dev/__init__.py +61 -0
- agentcore/operations/dev/_http.py +79 -0
- agentcore/operations/dev/_server.py +165 -0
- agentcore/operations/dev/codezip_dev_server.py +151 -0
- agentcore/operations/dev/config.py +128 -0
- agentcore/operations/dev/constants.py +9 -0
- agentcore/operations/dev/container_dev_server.py +237 -0
- agentcore/operations/dev/container_runtime.py +37 -0
- agentcore/operations/dev/dev_server.py +244 -0
- agentcore/operations/dev/gateway_env.py +25 -0
- agentcore/operations/dev/invoke.py +214 -0
- agentcore/operations/dev/invoke_a2a.py +204 -0
- agentcore/operations/dev/invoke_agui.py +88 -0
- agentcore/operations/dev/invoke_mcp.py +145 -0
- agentcore/operations/dev/invoke_types.py +30 -0
- agentcore/operations/dev/load_dev_env.py +26 -0
- agentcore/operations/dev/memory_env.py +19 -0
- agentcore/operations/dev/otel/__init__.py +5 -0
- agentcore/operations/dev/otel/collector.py +234 -0
- agentcore/operations/dev/otel/transforms.py +331 -0
- agentcore/operations/dev/payment_env.py +50 -0
- agentcore/operations/dev/server.py +28 -0
- agentcore/operations/dev/sse_transform.py +30 -0
- agentcore/operations/dev/utils.py +152 -0
- agentcore/operations/dev/web_ui/__init__.py +31 -0
- agentcore/operations/dev/web_ui/constants.py +25 -0
- agentcore/operations/dev/web_ui/handlers/__init__.py +36 -0
- agentcore/operations/dev/web_ui/handlers/_common.py +36 -0
- agentcore/operations/dev/web_ui/handlers/_deployed.py +37 -0
- agentcore/operations/dev/web_ui/handlers/a2a_proxy.py +37 -0
- agentcore/operations/dev/web_ui/handlers/cloudwatch_traces.py +71 -0
- agentcore/operations/dev/web_ui/handlers/harness_invocation.py +89 -0
- agentcore/operations/dev/web_ui/handlers/harness_utils.py +95 -0
- agentcore/operations/dev/web_ui/handlers/invocations.py +327 -0
- agentcore/operations/dev/web_ui/handlers/mcp_proxy.py +119 -0
- agentcore/operations/dev/web_ui/handlers/memory.py +84 -0
- agentcore/operations/dev/web_ui/handlers/resources.py +351 -0
- agentcore/operations/dev/web_ui/handlers/start.py +182 -0
- agentcore/operations/dev/web_ui/handlers/status.py +25 -0
- agentcore/operations/dev/web_ui/handlers/traces.py +50 -0
- agentcore/operations/dev/web_ui/run_web_ui.py +60 -0
- agentcore/operations/dev/web_ui/web_server.py +297 -0
- agentcore/operations/eval/__init__.py +8 -0
- agentcore/operations/eval/list_eval_runs.py +18 -0
- agentcore/operations/eval/logs_eval.py +119 -0
- agentcore/operations/eval/pause_resume.py +90 -0
- agentcore/operations/eval/run_eval.py +354 -0
- agentcore/operations/eval/shared/__init__.py +0 -0
- agentcore/operations/eval/shared/dataset_loader.py +68 -0
- agentcore/operations/eval/shared/dataset_session_provider.py +122 -0
- agentcore/operations/eval/shared/evaluator_runner.py +89 -0
- agentcore/operations/eval/shared/scenario_executor.py +71 -0
- agentcore/operations/eval/shared/span_collector.py +255 -0
- agentcore/operations/eval/storage.py +67 -0
- agentcore/operations/feedback/__init__.py +21 -0
- agentcore/operations/feedback/aperture_client.py +98 -0
- agentcore/operations/feedback/build_payload.py +97 -0
- agentcore/operations/feedback/constants.py +26 -0
- agentcore/operations/feedback/submit_feedback.py +150 -0
- agentcore/operations/fetch_access/__init__.py +36 -0
- agentcore/operations/fetch_access/_target.py +17 -0
- agentcore/operations/fetch_access/fetch_gateway_token.py +75 -0
- agentcore/operations/fetch_access/fetch_harness_token.py +72 -0
- agentcore/operations/fetch_access/fetch_runtime_token.py +76 -0
- agentcore/operations/fetch_access/list_agents.py +18 -0
- agentcore/operations/fetch_access/list_gateways.py +26 -0
- agentcore/operations/fetch_access/list_harnesses.py +23 -0
- agentcore/operations/fetch_access/oauth_token.py +162 -0
- agentcore/operations/fetch_access/types.py +34 -0
- agentcore/operations/harness/__init__.py +1 -0
- agentcore/operations/harness/orphan.py +84 -0
- agentcore/operations/harness/skill_utils.py +56 -0
- agentcore/operations/identity/__init__.py +33 -0
- agentcore/operations/identity/api_key_credential_provider.py +68 -0
- agentcore/operations/identity/oauth2_credential_provider.py +95 -0
- agentcore/operations/ingest/__init__.py +184 -0
- agentcore/operations/init/__init__.py +3 -0
- agentcore/operations/init/files.py +59 -0
- agentcore/operations/insights/__init__.py +21 -0
- agentcore/operations/insights/insights_storage.py +67 -0
- agentcore/operations/insights/run_insights.py +148 -0
- agentcore/operations/invoke/__init__.py +5 -0
- agentcore/operations/invoke/resolve_agent_context.py +85 -0
- agentcore/operations/jobs/__init__.py +38 -0
- agentcore/operations/jobs/ab_test/__init__.py +0 -0
- agentcore/operations/jobs/ab_test/build_options.py +126 -0
- agentcore/operations/jobs/ab_test/format.py +121 -0
- agentcore/operations/jobs/ab_test/handler.py +412 -0
- agentcore/operations/jobs/ab_test/promote.py +142 -0
- agentcore/operations/jobs/ab_test/resolve.py +221 -0
- agentcore/operations/jobs/batch_evaluation/__init__.py +0 -0
- agentcore/operations/jobs/batch_evaluation/build_source.py +68 -0
- agentcore/operations/jobs/batch_evaluation/dataset_phase1.py +95 -0
- agentcore/operations/jobs/batch_evaluation/format.py +58 -0
- agentcore/operations/jobs/batch_evaluation/handler.py +203 -0
- agentcore/operations/jobs/insights/__init__.py +0 -0
- agentcore/operations/jobs/insights/format.py +65 -0
- agentcore/operations/jobs/insights/handler.py +178 -0
- agentcore/operations/jobs/recommendation/__init__.py +0 -0
- agentcore/operations/jobs/recommendation/apply_to_bundle.py +76 -0
- agentcore/operations/jobs/recommendation/build_config.py +271 -0
- agentcore/operations/jobs/recommendation/fetch_session_spans.py +93 -0
- agentcore/operations/jobs/recommendation/format.py +77 -0
- agentcore/operations/jobs/recommendation/handler.py +331 -0
- agentcore/operations/jobs/shared/__init__.py +0 -0
- agentcore/operations/jobs/shared/constants.py +85 -0
- agentcore/operations/jobs/shared/engine.py +187 -0
- agentcore/operations/jobs/shared/format.py +104 -0
- agentcore/operations/jobs/shared/region.py +34 -0
- agentcore/operations/jobs/shared/resolve_agent_state.py +30 -0
- agentcore/operations/jobs/shared/storage.py +117 -0
- agentcore/operations/jobs/shared/wait.py +30 -0
- agentcore/operations/knowledge_base/__init__.py +33 -0
- agentcore/operations/knowledge_base/connector_config.py +105 -0
- agentcore/operations/knowledge_base/hydrate_data_sources.py +59 -0
- agentcore/operations/mcp/__init__.py +4 -0
- agentcore/operations/memory/__init__.py +13 -0
- agentcore/operations/memory/_records.py +72 -0
- agentcore/operations/memory/list_memory_records.py +45 -0
- agentcore/operations/memory/retrieve_memory_records.py +52 -0
- agentcore/operations/node/__init__.py +15 -0
- agentcore/operations/node/setup.py +36 -0
- agentcore/operations/python/__init__.py +17 -0
- agentcore/operations/python/setup.py +47 -0
- agentcore/operations/resolve_agent.py +159 -0
- agentcore/operations/session/__init__.py +86 -0
- agentcore/operations/traces/__init__.py +29 -0
- agentcore/operations/traces/get_trace.py +202 -0
- agentcore/operations/traces/insights_query.py +74 -0
- agentcore/operations/traces/list_traces.py +46 -0
- agentcore/operations/traces/trace_url.py +25 -0
- agentcore/operations/traces/types.py +55 -0
- agentcore/primitives/__init__.py +0 -0
- agentcore/primitives/_gateway_target_wizard.py +293 -0
- agentcore/primitives/_gateway_validation.py +442 -0
- agentcore/primitives/_harness_cli.py +557 -0
- agentcore/primitives/_harness_validation.py +163 -0
- agentcore/primitives/_harness_wizard.py +726 -0
- agentcore/primitives/_knowledge_base_wizard.py +259 -0
- agentcore/primitives/_payment_wizard.py +331 -0
- agentcore/primitives/_policy_form.py +160 -0
- agentcore/primitives/agent.py +817 -0
- agentcore/primitives/auth_utils.py +77 -0
- agentcore/primitives/base.py +178 -0
- agentcore/primitives/capacity_provider.py +501 -0
- agentcore/primitives/config_bundle.py +329 -0
- agentcore/primitives/credential.py +387 -0
- agentcore/primitives/credential_utils.py +45 -0
- agentcore/primitives/dataset.py +211 -0
- agentcore/primitives/deployed_gateways.py +34 -0
- agentcore/primitives/evaluator.py +909 -0
- agentcore/primitives/gateway.py +496 -0
- agentcore/primitives/gateway_target.py +988 -0
- agentcore/primitives/harness.py +706 -0
- agentcore/primitives/knowledge_base.py +477 -0
- agentcore/primitives/memory.py +387 -0
- agentcore/primitives/online_eval_config.py +365 -0
- agentcore/primitives/online_insights.py +275 -0
- agentcore/primitives/payment_connector.py +427 -0
- agentcore/primitives/payment_eligible.py +20 -0
- agentcore/primitives/payment_manager.py +605 -0
- agentcore/primitives/payment_validation.py +68 -0
- agentcore/primitives/policy.py +622 -0
- agentcore/primitives/policy_engine.py +358 -0
- agentcore/primitives/registry.py +56 -0
- agentcore/primitives/runtime_endpoint.py +361 -0
- agentcore/primitives/secret_flag_warning.py +17 -0
- agentcore/schema/__init__.py +14 -0
- agentcore/schema/_zod.py +395 -0
- agentcore/schema/constants.py +306 -0
- agentcore/schema/schemas/__init__.py +40 -0
- agentcore/schema/schemas/agent_env.py +545 -0
- agentcore/schema/schemas/agentcore_project.py +530 -0
- agentcore/schema/schemas/auth.py +286 -0
- agentcore/schema/schemas/aws_targets.py +72 -0
- agentcore/schema/schemas/connections.py +187 -0
- agentcore/schema/schemas/deployed_state.py +322 -0
- agentcore/schema/schemas/mcp.py +650 -0
- agentcore/schema/schemas/mcp_defs.py +54 -0
- agentcore/schema/schemas/primitives/__init__.py +52 -0
- agentcore/schema/schemas/primitives/ab_test.py +162 -0
- agentcore/schema/schemas/primitives/capacity_provider.py +214 -0
- agentcore/schema/schemas/primitives/config_bundle.py +48 -0
- agentcore/schema/schemas/primitives/dataset.py +55 -0
- agentcore/schema/schemas/primitives/evaluator.py +171 -0
- agentcore/schema/schemas/primitives/harness.py +710 -0
- agentcore/schema/schemas/primitives/knowledge_base.py +90 -0
- agentcore/schema/schemas/primitives/memory.py +113 -0
- agentcore/schema/schemas/primitives/online_eval_config.py +77 -0
- agentcore/schema/schemas/primitives/payment.py +114 -0
- agentcore/schema/schemas/primitives/policy.py +83 -0
- agentcore/schema/schemas/primitives/tags.py +50 -0
- agentcore/schema/schemas/zod_util.py +5 -0
- agentcore/schema/types/__init__.py +3 -0
- agentcore/schema/types/path.py +16 -0
- agentcore/templates/__init__.py +115 -0
- agentcore/templates/_handlebars.py +782 -0
- agentcore/templates/_js.py +164 -0
- agentcore/templates/base_renderer.py +107 -0
- agentcore/templates/cdk_renderer.py +129 -0
- agentcore/templates/evaluator_renderer.py +39 -0
- agentcore/templates/gateway_target_renderer.py +69 -0
- agentcore/templates/llm_context/README.md +16 -0
- agentcore/templates/llm_context/agentcore.ts +685 -0
- agentcore/templates/llm_context/aws-targets.ts +51 -0
- agentcore/templates/profiles.py +151 -0
- agentcore/templates/render.py +92 -0
- agentcore/templates/renderers.py +83 -0
- agentcore/templates/schema_assets.py +23 -0
- agentcore/templates/template_root.py +28 -0
- agentcore/templates/types.py +192 -0
- agentcore_cli-0.31.1.dist-info/METADATA +84 -0
- agentcore_cli-0.31.1.dist-info/RECORD +655 -0
- agentcore_cli-0.31.1.dist-info/WHEEL +4 -0
- agentcore_cli-0.31.1.dist-info/entry_points.txt +2 -0
- agentcore_cli-0.31.1.dist-info/licenses/LICENSE +175 -0
- agentcore_cli-0.31.1.dist-info/licenses/NOTICE +88 -0
|
@@ -0,0 +1,840 @@
|
|
|
1
|
+
"""Deploy orchestration (port of ``commands/deploy/actions.ts``)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from collections.abc import Callable, Mapping
|
|
7
|
+
from dataclasses import dataclass
|
|
8
|
+
from typing import Any, Literal
|
|
9
|
+
|
|
10
|
+
from agentcore.aws.account import validate_aws_credentials
|
|
11
|
+
from agentcore.aws.target_region import apply_target_region_to_env
|
|
12
|
+
from agentcore.cdk.toolkit import (
|
|
13
|
+
CdkToolkitWrapper,
|
|
14
|
+
DeployMessage,
|
|
15
|
+
SwitchableIoHost,
|
|
16
|
+
create_switchable_io_host,
|
|
17
|
+
pattern_must_match,
|
|
18
|
+
)
|
|
19
|
+
from agentcore.cli.commands.deploy.types import DeployResult
|
|
20
|
+
from agentcore.cli.errors import get_error_message, is_changeset_in_progress_error, is_stack_in_progress_error
|
|
21
|
+
from agentcore.cloudformation import outputs as cfn_outputs
|
|
22
|
+
from agentcore.lib.dependency_management.types import DependencySyncResult
|
|
23
|
+
from agentcore.lib.errors.types import DependencySyncError, ResourceNotFoundError, ValidationError, to_error
|
|
24
|
+
from agentcore.lib.result import Err, Ok
|
|
25
|
+
from agentcore.lib.schemas.io.config_io import ConfigIO, to_jsonable
|
|
26
|
+
from agentcore.lib.utils.credentials import SecureCredentials
|
|
27
|
+
from agentcore.logging.exec_logger import ExecLogger
|
|
28
|
+
from agentcore.operations.deploy import (
|
|
29
|
+
backfill_vpc_id,
|
|
30
|
+
change_detection,
|
|
31
|
+
dependency_sync,
|
|
32
|
+
ensure_target,
|
|
33
|
+
gateway_status,
|
|
34
|
+
post_deploy_datasets,
|
|
35
|
+
post_deploy_knowledge_bases,
|
|
36
|
+
post_deploy_observability,
|
|
37
|
+
post_deploy_online_evals,
|
|
38
|
+
pre_deploy_identity,
|
|
39
|
+
preflight,
|
|
40
|
+
teardown,
|
|
41
|
+
)
|
|
42
|
+
from agentcore.operations.deploy import managed_memory_notice as memory_notice
|
|
43
|
+
from agentcore.operations.deploy import payment_connector_authorization as pca
|
|
44
|
+
from agentcore.operations.harness.orphan import find_orphan_harnesses
|
|
45
|
+
from agentcore.operations.knowledge_base.hydrate_data_sources import hydrate_knowledge_base_data_sources
|
|
46
|
+
|
|
47
|
+
StepStatus = Literal["start", "success", "error", "warn"]
|
|
48
|
+
|
|
49
|
+
AGENT_NEXT_STEPS = ["agentcore invoke", "agentcore status"]
|
|
50
|
+
MEMORY_ONLY_NEXT_STEPS = ["agentcore add agent", "agentcore status"]
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
@dataclass
|
|
54
|
+
class ValidatedDeployOptions:
|
|
55
|
+
target: str
|
|
56
|
+
auto_confirm: bool = False
|
|
57
|
+
verbose: bool = False
|
|
58
|
+
plan: bool = False
|
|
59
|
+
diff: bool = False
|
|
60
|
+
on_progress: Callable[[str, StepStatus], None] | None = None
|
|
61
|
+
on_resource_event: Callable[[str], None] | None = None
|
|
62
|
+
on_deploy_message: Callable[[DeployMessage], None] | None = None
|
|
63
|
+
# One-shot user-facing notice (e.g. managed-memory heads-up), always surfaced.
|
|
64
|
+
on_notice: Callable[[str], None] | None = None
|
|
65
|
+
# --- interactive-mode hooks (replace the Ink TUI's confirm/credential screens) ---
|
|
66
|
+
# Asked instead of failing when a teardown deploy runs without --yes.
|
|
67
|
+
confirm_teardown: Callable[[], bool] | None = None
|
|
68
|
+
# Asked instead of failing when bootstrap is needed without --yes; False skips bootstrapping.
|
|
69
|
+
confirm_bootstrap: Callable[[], bool] | None = None
|
|
70
|
+
# Credentials entered at the prompt (not persisted); override .env.local values.
|
|
71
|
+
runtime_credentials: SecureCredentials | None = None
|
|
72
|
+
# The prompt's "skip" choice: don't set up API key / OAuth providers.
|
|
73
|
+
skip_identity_setup: bool = False
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
def to_stack_name(project_name: str, target_name: str) -> str:
|
|
77
|
+
"""Matches ``toStackName`` in the vended ``bin/cdk.ts`` (underscores -> dashes)."""
|
|
78
|
+
return f"AgentCore-{project_name.replace('_', '-')}-{target_name.replace('_', '-')}"
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
@dataclass(frozen=True)
|
|
82
|
+
class HarnessVersionDrift:
|
|
83
|
+
name: str
|
|
84
|
+
to: int
|
|
85
|
+
from_: int | None = None
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def compute_harness_version_drift(
|
|
89
|
+
prev: Mapping[str, Any] | None, next_: Mapping[str, Mapping[str, Any]]
|
|
90
|
+
) -> list[HarnessVersionDrift]:
|
|
91
|
+
"""Harnesses whose (emitted) config version changed or appeared since the previous deploy."""
|
|
92
|
+
|
|
93
|
+
def version(record: Any) -> int | None:
|
|
94
|
+
if record is None:
|
|
95
|
+
return None
|
|
96
|
+
if isinstance(record, Mapping):
|
|
97
|
+
return record.get("harnessVersion")
|
|
98
|
+
return getattr(record, "harness_version", None)
|
|
99
|
+
|
|
100
|
+
notes = []
|
|
101
|
+
for name, record in next_.items():
|
|
102
|
+
to = version(record)
|
|
103
|
+
if to is None:
|
|
104
|
+
continue
|
|
105
|
+
frm = version((prev or {}).get(name))
|
|
106
|
+
if frm != to:
|
|
107
|
+
notes.append(HarnessVersionDrift(name=name, to=to, from_=frm))
|
|
108
|
+
return notes
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def select_target_stack(stack_names: list[str], project_name: str, target_name: str) -> Ok[str] | Err[ValidationError]:
|
|
112
|
+
"""The synthesized stack for the deployed target (never blindly ``stack_names[0]``)."""
|
|
113
|
+
if not stack_names:
|
|
114
|
+
return Err(ValidationError("No stacks found to deploy"))
|
|
115
|
+
expected = to_stack_name(project_name, target_name)
|
|
116
|
+
if expected not in stack_names:
|
|
117
|
+
return Err(
|
|
118
|
+
ValidationError(
|
|
119
|
+
f"Synthesized stacks [{', '.join(stack_names)}] do not include the stack for target "
|
|
120
|
+
f'"{target_name}" (expected "{expected}").'
|
|
121
|
+
)
|
|
122
|
+
)
|
|
123
|
+
return Ok(expected)
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def run_diff(toolkit_wrapper: CdkToolkitWrapper, stack_name: str, io_host: SwitchableIoHost | None = None) -> None:
|
|
127
|
+
host = io_host or create_switchable_io_host()
|
|
128
|
+
has_content = False
|
|
129
|
+
|
|
130
|
+
def on_raw(code: str, _level: str, message: str, _data: Any = None) -> None:
|
|
131
|
+
nonlocal has_content
|
|
132
|
+
if not message:
|
|
133
|
+
return
|
|
134
|
+
# I4002: formatted diff per stack, I4001: overall diff summary
|
|
135
|
+
if code in ("CDK_TOOLKIT_I4002", "CDK_TOOLKIT_I4001"):
|
|
136
|
+
has_content = True
|
|
137
|
+
print(message)
|
|
138
|
+
|
|
139
|
+
host.set_on_raw_message(on_raw)
|
|
140
|
+
host.set_verbose(True)
|
|
141
|
+
if toolkit_wrapper.io_host is not host:
|
|
142
|
+
toolkit_wrapper.io_host = host
|
|
143
|
+
toolkit_wrapper.diff(pattern_must_match(stack_name))
|
|
144
|
+
if not has_content:
|
|
145
|
+
print("No stack differences detected.")
|
|
146
|
+
host.set_verbose(False)
|
|
147
|
+
host.set_on_raw_message(None)
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def run_deploy(toolkit_wrapper: CdkToolkitWrapper, stack_name: str) -> None:
|
|
151
|
+
toolkit_wrapper.deploy(pattern_must_match(stack_name))
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
def _resources_json(state: Any, target_name: str) -> dict[str, Any]:
|
|
155
|
+
if state is None:
|
|
156
|
+
return {}
|
|
157
|
+
data = to_jsonable(state)
|
|
158
|
+
return ((data.get("targets") or {}).get(target_name) or {}).get("resources") or {}
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def handle_deploy(options: ValidatedDeployOptions) -> DeployResult:
|
|
162
|
+
toolkit_wrapper: CdkToolkitWrapper | None = None
|
|
163
|
+
restore_env: Callable[[], None] | None = None
|
|
164
|
+
# Preview modes revert the vpcId backfill on every exit path (success, early return, or raise).
|
|
165
|
+
preview_restore: Callable[[], None] | None = None
|
|
166
|
+
logger = ExecLogger(command="deploy")
|
|
167
|
+
current_step = ""
|
|
168
|
+
sync_result: DependencySyncResult | None = None
|
|
169
|
+
|
|
170
|
+
def start_step(name: str) -> None:
|
|
171
|
+
nonlocal current_step
|
|
172
|
+
current_step = name
|
|
173
|
+
logger.start_step(name)
|
|
174
|
+
if options.on_progress:
|
|
175
|
+
options.on_progress(name, "start")
|
|
176
|
+
|
|
177
|
+
def end_step(status: Literal["success", "error", "warn"], message: str | None = None) -> None:
|
|
178
|
+
logger.end_step(status, message)
|
|
179
|
+
if options.on_progress:
|
|
180
|
+
options.on_progress(current_step, status)
|
|
181
|
+
|
|
182
|
+
def fail(error: BaseException) -> DeployResult:
|
|
183
|
+
logger.finalize(False)
|
|
184
|
+
return DeployResult(
|
|
185
|
+
success=False, error=error, log_path=logger.get_relative_log_path(), dependency_sync_result=sync_result
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
try:
|
|
189
|
+
config_io = ConfigIO()
|
|
190
|
+
|
|
191
|
+
# Fresh projects have an empty aws-targets.json; non-interactive deploys auto-populate one.
|
|
192
|
+
start_step("Load deployment target")
|
|
193
|
+
ensure_target.ensure_default_deployment_target(config_io)
|
|
194
|
+
targets = config_io.resolve_aws_deployment_targets()
|
|
195
|
+
target = next((t for t in targets if t.name == options.target), None)
|
|
196
|
+
if target is None:
|
|
197
|
+
end_step("error", f'Target "{options.target}" not found')
|
|
198
|
+
message = f'Target "{options.target}" not found in aws-targets.json'
|
|
199
|
+
if not targets:
|
|
200
|
+
# The default target is created from the detected AWS account; no account means no credentials.
|
|
201
|
+
message += (
|
|
202
|
+
". No AWS account could be detected to create it: configure credentials "
|
|
203
|
+
"(e.g. `aws sso login --profile <name>` or `aws configure`) and try again."
|
|
204
|
+
)
|
|
205
|
+
return fail(ResourceNotFoundError(message))
|
|
206
|
+
# Make the target region authoritative for SDK and CDK calls (aws/agentcore-cli#924).
|
|
207
|
+
restore_env = apply_target_region_to_env(target.region)
|
|
208
|
+
end_step("success")
|
|
209
|
+
|
|
210
|
+
gateway_specs: list[Any] = []
|
|
211
|
+
try:
|
|
212
|
+
gateway_specs = list(config_io.read_project_spec().agent_core_gateways or [])
|
|
213
|
+
except Exception: # noqa: BLE001 - project read failed: no gateways
|
|
214
|
+
pass
|
|
215
|
+
|
|
216
|
+
start_step("Validate project")
|
|
217
|
+
context = preflight.validate_project(target)
|
|
218
|
+
end_step("success")
|
|
219
|
+
spec = context.project_spec
|
|
220
|
+
|
|
221
|
+
# Preview-build harnesses aren't CFN-managed; warn (skipped on teardown, which warns differently).
|
|
222
|
+
orphan_warnings: list[str] = []
|
|
223
|
+
if not context.is_teardown_deploy:
|
|
224
|
+
try:
|
|
225
|
+
pre_state = config_io.read_deployed_state()
|
|
226
|
+
except Exception: # noqa: BLE001
|
|
227
|
+
pre_state = None
|
|
228
|
+
for orphan in find_orphan_harnesses(pre_state):
|
|
229
|
+
warning = (
|
|
230
|
+
f'Harness "{orphan.name}" was created by the preview build and is not managed by '
|
|
231
|
+
"CloudFormation. This deploy won't touch it, and it keeps incurring cost. To migrate it "
|
|
232
|
+
f"to GA, run `agentcore remove harness {orphan.name} --keep` (deletes the old resource "
|
|
233
|
+
"but keeps it in agentcore.json), then deploy again so it's recreated under CloudFormation. "
|
|
234
|
+
"Use --discard instead if you no longer want it."
|
|
235
|
+
)
|
|
236
|
+
logger.log(warning, "warn")
|
|
237
|
+
orphan_warnings.append(warning)
|
|
238
|
+
|
|
239
|
+
if context.is_teardown_deploy and not options.auto_confirm:
|
|
240
|
+
if options.confirm_teardown is None or not options.confirm_teardown():
|
|
241
|
+
return fail(
|
|
242
|
+
ValidationError(
|
|
243
|
+
"This will delete all deployed resources and the CloudFormation stack. "
|
|
244
|
+
"Run with --yes to confirm teardown."
|
|
245
|
+
)
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
if context.is_teardown_deploy:
|
|
249
|
+
start_step("Validate AWS credentials")
|
|
250
|
+
validate_aws_credentials(target)
|
|
251
|
+
end_step("success")
|
|
252
|
+
|
|
253
|
+
# Pin agentcore/cdk/package.json. Previews are check-only; teardown never blocks on pinning.
|
|
254
|
+
is_preview = options.plan or options.diff
|
|
255
|
+
start_step(dependency_sync.SYNC_CDK_DEPENDENCIES_STEP)
|
|
256
|
+
try:
|
|
257
|
+
sync_result = dependency_sync.ensure_managed_dependencies(
|
|
258
|
+
context.cdk_project, check_only=is_preview, treat_skew_as_warning=context.is_teardown_deploy
|
|
259
|
+
)
|
|
260
|
+
except Exception as sync_err:
|
|
261
|
+
if not (context.is_teardown_deploy and isinstance(sync_err, DependencySyncError)):
|
|
262
|
+
sync_result = dependency_sync.failed_sync_result()
|
|
263
|
+
raise
|
|
264
|
+
sync_result = dependency_sync.teardown_sync_failure_result(sync_err)
|
|
265
|
+
for warning in sync_result.warnings:
|
|
266
|
+
logger.log(warning, "warn")
|
|
267
|
+
if sync_result.notice:
|
|
268
|
+
logger.log(sync_result.notice)
|
|
269
|
+
if options.on_notice:
|
|
270
|
+
options.on_notice(sync_result.notice)
|
|
271
|
+
end_step("warn" if sync_result.outcome == "failure-suppressed" else "success")
|
|
272
|
+
|
|
273
|
+
start_step("Build CDK project")
|
|
274
|
+
preflight.build_cdk_project(context.cdk_project)
|
|
275
|
+
end_step("success")
|
|
276
|
+
|
|
277
|
+
# Identity providers before synth (the CDK app reads credential ARNs from deployed state).
|
|
278
|
+
identity_kms_key_arn: str | None = None
|
|
279
|
+
env_check = pre_deploy_identity.assert_env_file_exists(spec, config_io.get_config_root())
|
|
280
|
+
if not env_check.success:
|
|
281
|
+
return fail(env_check.error)
|
|
282
|
+
|
|
283
|
+
# Runtime credentials from the process env (non-interactive deploy with -y).
|
|
284
|
+
env_credentials = {
|
|
285
|
+
c.env_var_name: os.environ[c.env_var_name]
|
|
286
|
+
for c in pre_deploy_identity.get_all_credentials(spec)
|
|
287
|
+
if os.environ.get(c.env_var_name)
|
|
288
|
+
}
|
|
289
|
+
runtime_credentials = SecureCredentials(env_credentials) if env_credentials else None
|
|
290
|
+
if options.runtime_credentials is not None:
|
|
291
|
+
runtime_credentials = (
|
|
292
|
+
runtime_credentials.merge(options.runtime_credentials)
|
|
293
|
+
if runtime_credentials
|
|
294
|
+
else options.runtime_credentials
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
deployed_credentials: dict[str, dict[str, Any]] = {}
|
|
298
|
+
|
|
299
|
+
if pre_deploy_identity.has_identity_api_providers(spec) and not options.skip_identity_setup:
|
|
300
|
+
start_step("Creating credentials...")
|
|
301
|
+
identity_result = pre_deploy_identity.setup_api_key_providers(
|
|
302
|
+
project_spec=spec,
|
|
303
|
+
config_base_dir=config_io.get_config_root(),
|
|
304
|
+
region=target.region,
|
|
305
|
+
runtime_credentials=runtime_credentials,
|
|
306
|
+
enable_kms_encryption=True,
|
|
307
|
+
)
|
|
308
|
+
if identity_result.has_errors:
|
|
309
|
+
failed = next((r for r in identity_result.results if r.status == "error" and r.error), None)
|
|
310
|
+
end_step("error", str(failed.error) if failed else "Identity setup failed")
|
|
311
|
+
return fail(
|
|
312
|
+
failed.error if failed else RuntimeError("unknown error occurred when setting up api key providers")
|
|
313
|
+
)
|
|
314
|
+
identity_kms_key_arn = identity_result.kms_key_arn
|
|
315
|
+
for r in identity_result.results:
|
|
316
|
+
if r.credential_provider_arn:
|
|
317
|
+
deployed_credentials[r.provider_name] = {"credentialProviderArn": r.credential_provider_arn}
|
|
318
|
+
end_step("success")
|
|
319
|
+
|
|
320
|
+
if pre_deploy_identity.has_identity_o_auth_providers(spec) and not options.skip_identity_setup:
|
|
321
|
+
start_step("Creating OAuth credentials...")
|
|
322
|
+
oauth_result = pre_deploy_identity.setup_o_auth2_providers(
|
|
323
|
+
project_spec=spec,
|
|
324
|
+
config_base_dir=config_io.get_config_root(),
|
|
325
|
+
region=target.region,
|
|
326
|
+
runtime_credentials=runtime_credentials,
|
|
327
|
+
)
|
|
328
|
+
if oauth_result.has_errors:
|
|
329
|
+
# Detailed error goes to the log; the step message is sanitized (no OAuth details).
|
|
330
|
+
failed_oauth = next((r for r in oauth_result.results if r.status == "error" and r.error), None)
|
|
331
|
+
logger.log(f"OAuth setup error: {failed_oauth.error if failed_oauth else 'unknown'}", "error")
|
|
332
|
+
end_step("error", "OAuth credential setup failed. Check the log for details.")
|
|
333
|
+
return fail(
|
|
334
|
+
failed_oauth.error
|
|
335
|
+
if failed_oauth
|
|
336
|
+
else RuntimeError("an unexpected error ocurred when setting up oauth providers")
|
|
337
|
+
)
|
|
338
|
+
for r in oauth_result.results:
|
|
339
|
+
if r.credential_provider_arn:
|
|
340
|
+
record: dict[str, Any] = {"credentialProviderArn": r.credential_provider_arn}
|
|
341
|
+
if r.client_secret_arn is not None:
|
|
342
|
+
record["clientSecretArn"] = r.client_secret_arn
|
|
343
|
+
if r.callback_url is not None:
|
|
344
|
+
record["callbackUrl"] = r.callback_url
|
|
345
|
+
deployed_credentials[r.provider_name] = record
|
|
346
|
+
end_step("success")
|
|
347
|
+
|
|
348
|
+
# Payment credential providers stay imperative; manager/connector/roles come from CDK.
|
|
349
|
+
if pre_deploy_identity.has_payment_credential_providers(spec):
|
|
350
|
+
start_step("Setting up payment credentials...")
|
|
351
|
+
payment_result = pre_deploy_identity.setup_payment_credential_providers(
|
|
352
|
+
project_spec=spec,
|
|
353
|
+
config_base_dir=config_io.get_config_root(),
|
|
354
|
+
region=target.region,
|
|
355
|
+
runtime_credentials=runtime_credentials,
|
|
356
|
+
)
|
|
357
|
+
if payment_result.has_errors:
|
|
358
|
+
messages = "; ".join(str(e) for e in payment_result.errors)
|
|
359
|
+
end_step("error", messages)
|
|
360
|
+
logger.log(f"Payment credential setup errors: {messages}", "error")
|
|
361
|
+
return fail(
|
|
362
|
+
payment_result.errors[0]
|
|
363
|
+
if payment_result.errors
|
|
364
|
+
else RuntimeError("payment deploy preflight steps failed")
|
|
365
|
+
)
|
|
366
|
+
for name, provider in payment_result.credential_providers.items():
|
|
367
|
+
deployed_credentials[name] = {"credentialProviderArn": provider.credential_provider_arn}
|
|
368
|
+
end_step("success")
|
|
369
|
+
|
|
370
|
+
# Credential ARNs go to deployed state before synth so the template can read them.
|
|
371
|
+
if deployed_credentials:
|
|
372
|
+
try:
|
|
373
|
+
existing_pre = to_jsonable(config_io.read_deployed_state())
|
|
374
|
+
except Exception: # noqa: BLE001
|
|
375
|
+
existing_pre = {"targets": {}}
|
|
376
|
+
target_state = (existing_pre.get("targets") or {}).get(target.name) or {"resources": {}}
|
|
377
|
+
resources = target_state.setdefault("resources", {}) or {}
|
|
378
|
+
target_state["resources"] = resources
|
|
379
|
+
resources["credentials"] = deployed_credentials
|
|
380
|
+
if identity_kms_key_arn:
|
|
381
|
+
resources["identityKmsKeyArn"] = identity_kms_key_arn
|
|
382
|
+
config_io.write_deployed_state(
|
|
383
|
+
{**existing_pre, "targets": {**(existing_pre.get("targets") or {}), target.name: target_state}}
|
|
384
|
+
)
|
|
385
|
+
|
|
386
|
+
# vpcId backfill for pre-existing Container+VPC configs (reverted after synth in previews).
|
|
387
|
+
backfill = backfill_vpc_id.backfill_container_vpc_ids(config_io, spec, target.region, not is_preview)
|
|
388
|
+
if is_preview:
|
|
389
|
+
preview_restore = backfill.restore
|
|
390
|
+
if backfill.backfilled:
|
|
391
|
+
logger.log(
|
|
392
|
+
f"Resolved networkConfig.vpcId for Container+VPC build(s): {', '.join(backfill.backfilled)}", "info"
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
start_step("Synthesize CloudFormation")
|
|
396
|
+
io_host = create_switchable_io_host() if (options.verbose or options.on_deploy_message) else None
|
|
397
|
+
synth_result = preflight.synthesize_cdk(context.cdk_project, io_host=io_host, region=target.region)
|
|
398
|
+
toolkit_wrapper = synth_result.toolkit_wrapper
|
|
399
|
+
selection = select_target_stack(synth_result.stack_names, spec.name, target.name)
|
|
400
|
+
if not selection.success:
|
|
401
|
+
end_step("error", str(selection.error))
|
|
402
|
+
return fail(selection.error)
|
|
403
|
+
stack_name = selection.value
|
|
404
|
+
end_step("success")
|
|
405
|
+
|
|
406
|
+
start_step("Check bootstrap status")
|
|
407
|
+
bootstrap_check = preflight.check_bootstrap_needed(context.aws_targets)
|
|
408
|
+
if bootstrap_check.needs_bootstrap:
|
|
409
|
+
if options.auto_confirm:
|
|
410
|
+
logger.log("Bootstrap needed, auto-confirming...")
|
|
411
|
+
preflight.bootstrap_environment(toolkit_wrapper, target)
|
|
412
|
+
elif options.confirm_bootstrap is not None:
|
|
413
|
+
if options.confirm_bootstrap():
|
|
414
|
+
logger.log("Bootstrap needed, confirmed by user...")
|
|
415
|
+
preflight.bootstrap_environment(toolkit_wrapper, target)
|
|
416
|
+
else:
|
|
417
|
+
logger.log("Bootstrap skipped by user", "warn")
|
|
418
|
+
else:
|
|
419
|
+
end_step("error", "Bootstrap required")
|
|
420
|
+
return fail(ValidationError("AWS environment needs bootstrapping. Run with --yes to auto-bootstrap."))
|
|
421
|
+
end_step("success")
|
|
422
|
+
|
|
423
|
+
# Scope to this target's stack so a sibling target's failed stack can't block the deploy.
|
|
424
|
+
start_step("Check stack status")
|
|
425
|
+
deployability = preflight.check_stack_deployability(target.region, [stack_name])
|
|
426
|
+
if not deployability.can_deploy:
|
|
427
|
+
end_step("error", deployability.message)
|
|
428
|
+
return fail(RuntimeError(deployability.message or "Stack is not in a deployable state"))
|
|
429
|
+
end_step("success")
|
|
430
|
+
|
|
431
|
+
if options.plan:
|
|
432
|
+
logger.finalize(True)
|
|
433
|
+
toolkit_wrapper.dispose()
|
|
434
|
+
toolkit_wrapper = None
|
|
435
|
+
return DeployResult(
|
|
436
|
+
success=True,
|
|
437
|
+
target_name=target.name,
|
|
438
|
+
stack_name=stack_name,
|
|
439
|
+
log_path=logger.get_relative_log_path(),
|
|
440
|
+
dependency_sync_result=sync_result,
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
if options.diff:
|
|
444
|
+
start_step("Run CDK diff")
|
|
445
|
+
run_diff(toolkit_wrapper, stack_name, io_host)
|
|
446
|
+
end_step("success")
|
|
447
|
+
logger.finalize(True)
|
|
448
|
+
toolkit_wrapper.dispose()
|
|
449
|
+
toolkit_wrapper = None
|
|
450
|
+
return DeployResult(
|
|
451
|
+
success=True,
|
|
452
|
+
target_name=target.name,
|
|
453
|
+
stack_name=stack_name,
|
|
454
|
+
log_path=logger.get_relative_log_path(),
|
|
455
|
+
dependency_sync_result=sync_result,
|
|
456
|
+
)
|
|
457
|
+
|
|
458
|
+
if not context.is_teardown_deploy and memory_notice.has_managed_memory_harness(config_io, spec.harnesses):
|
|
459
|
+
logger.log(memory_notice.MANAGED_MEMORY_DEPLOY_NOTICE)
|
|
460
|
+
if options.on_notice:
|
|
461
|
+
options.on_notice(memory_notice.MANAGED_MEMORY_DEPLOY_NOTICE)
|
|
462
|
+
|
|
463
|
+
has_gateways = len(gateway_specs) > 0
|
|
464
|
+
start_step("Deploying gateways..." if has_gateways else "Deploy to AWS")
|
|
465
|
+
|
|
466
|
+
if io_host is not None and (options.on_resource_event or options.on_deploy_message):
|
|
467
|
+
|
|
468
|
+
def on_message(msg: DeployMessage) -> None:
|
|
469
|
+
if options.on_resource_event:
|
|
470
|
+
options.on_resource_event(msg.message)
|
|
471
|
+
if options.on_deploy_message:
|
|
472
|
+
options.on_deploy_message(msg)
|
|
473
|
+
|
|
474
|
+
io_host.set_on_message(on_message)
|
|
475
|
+
io_host.set_verbose(True)
|
|
476
|
+
|
|
477
|
+
try:
|
|
478
|
+
run_deploy(toolkit_wrapper, stack_name)
|
|
479
|
+
except Exception as deploy_err:
|
|
480
|
+
if is_changeset_in_progress_error(deploy_err):
|
|
481
|
+
logger.log("Changeset conflict detected - another deployment may be in progress", "warn")
|
|
482
|
+
elif is_stack_in_progress_error(deploy_err):
|
|
483
|
+
logger.log("Stack is busy with another operation - wait for it to finish and retry", "warn")
|
|
484
|
+
raise
|
|
485
|
+
|
|
486
|
+
if io_host is not None:
|
|
487
|
+
io_host.set_verbose(False)
|
|
488
|
+
io_host.set_on_message(None)
|
|
489
|
+
end_step("success")
|
|
490
|
+
|
|
491
|
+
if context.is_teardown_deploy:
|
|
492
|
+
try:
|
|
493
|
+
existing_for_teardown = config_io.read_deployed_state()
|
|
494
|
+
except Exception: # noqa: BLE001
|
|
495
|
+
existing_for_teardown = None
|
|
496
|
+
existing_payments = _resources_json(existing_for_teardown, target.name).get("payments")
|
|
497
|
+
if existing_payments:
|
|
498
|
+
start_step("Clean up payment credentials")
|
|
499
|
+
try:
|
|
500
|
+
pre_deploy_identity.cleanup_payment_credential_providers(
|
|
501
|
+
region=target.region, payments=existing_payments
|
|
502
|
+
)
|
|
503
|
+
end_step("success")
|
|
504
|
+
except Exception as cleanup_err: # noqa: BLE001 - best-effort
|
|
505
|
+
end_step("error", f"Payment cleanup: {get_error_message(cleanup_err)}")
|
|
506
|
+
|
|
507
|
+
start_step("Tear down stack")
|
|
508
|
+
torn = teardown.perform_stack_teardown(target.name, toolkit_wrapper)
|
|
509
|
+
if not torn.success:
|
|
510
|
+
end_step("error", str(torn.error))
|
|
511
|
+
return fail(torn.error)
|
|
512
|
+
end_step("success")
|
|
513
|
+
logger.finalize(True)
|
|
514
|
+
return DeployResult(
|
|
515
|
+
success=True,
|
|
516
|
+
target_name=target.name,
|
|
517
|
+
stack_name=stack_name,
|
|
518
|
+
log_path=logger.get_relative_log_path(),
|
|
519
|
+
dependency_sync_result=sync_result,
|
|
520
|
+
)
|
|
521
|
+
|
|
522
|
+
# ---- Persist deployment state -------------------------------------------------------
|
|
523
|
+
start_step("Persist deployment state")
|
|
524
|
+
outputs = cfn_outputs.get_stack_outputs(target.region, stack_name)
|
|
525
|
+
agent_names = [a.name for a in spec.runtimes or []]
|
|
526
|
+
agents = cfn_outputs.parse_agent_outputs(outputs, agent_names, stack_name)
|
|
527
|
+
|
|
528
|
+
memory_names = [m.name for m in spec.memories or []]
|
|
529
|
+
memories = cfn_outputs.parse_memory_outputs(outputs, memory_names)
|
|
530
|
+
if memory_names and len(memories) != len(memory_names):
|
|
531
|
+
logger.log(f"Deployed-state missing outputs for {len(memory_names) - len(memories)} memory(ies).", "warn")
|
|
532
|
+
|
|
533
|
+
evaluators = cfn_outputs.parse_evaluator_outputs(outputs, [e.name for e in spec.evaluators or []])
|
|
534
|
+
online_eval_configs = cfn_outputs.parse_online_eval_outputs(
|
|
535
|
+
outputs,
|
|
536
|
+
[{"name": c.name, "agent": c.agent, "endpoint": c.endpoint} for c in spec.online_eval_configs or []],
|
|
537
|
+
)
|
|
538
|
+
engine_specs = spec.policy_engines or []
|
|
539
|
+
policy_engines = cfn_outputs.parse_policy_engine_outputs(outputs, [pe.name for pe in engine_specs])
|
|
540
|
+
policies = cfn_outputs.parse_policy_outputs(
|
|
541
|
+
outputs, [{"engineName": pe.name, "policyName": p.name} for pe in engine_specs for p in pe.policies]
|
|
542
|
+
)
|
|
543
|
+
endpoint_specs = [
|
|
544
|
+
{"agentName": r.name, "endpointName": ep} for r in spec.runtimes or [] for ep in (r.endpoints or {})
|
|
545
|
+
]
|
|
546
|
+
runtime_endpoints = cfn_outputs.parse_runtime_endpoint_outputs(outputs, endpoint_specs)
|
|
547
|
+
|
|
548
|
+
all_gateways = cfn_outputs.parse_gateway_outputs(outputs, {g.name: g for g in gateway_specs})
|
|
549
|
+
http_gateway_names = {g.name for g in gateway_specs if getattr(g, "protocol_type", None) == "None"}
|
|
550
|
+
gateways = {n: s for n, s in all_gateways.items() if n not in http_gateway_names}
|
|
551
|
+
http_gateways = {n: s for n, s in all_gateways.items() if n in http_gateway_names}
|
|
552
|
+
|
|
553
|
+
datasets = cfn_outputs.parse_dataset_outputs(outputs, [d.name for d in spec.datasets or []])
|
|
554
|
+
capacity_providers = cfn_outputs.parse_capacity_provider_outputs(
|
|
555
|
+
outputs, [cp.name for cp in spec.capacity_providers or []]
|
|
556
|
+
)
|
|
557
|
+
config_bundles = cfn_outputs.parse_config_bundle_outputs(outputs, [b.name for b in spec.config_bundles or []])
|
|
558
|
+
|
|
559
|
+
kb_specs = spec.knowledge_bases or []
|
|
560
|
+
kb_names = [kb.name for kb in kb_specs]
|
|
561
|
+
knowledge_bases = cfn_outputs.parse_knowledge_base_outputs(outputs, kb_names)
|
|
562
|
+
if kb_names and len(knowledge_bases) != len(kb_names):
|
|
563
|
+
logger.log(
|
|
564
|
+
f"Deployed-state missing outputs for {len(kb_names) - len(knowledge_bases)} knowledge base(s).", "warn"
|
|
565
|
+
)
|
|
566
|
+
if knowledge_bases:
|
|
567
|
+
try:
|
|
568
|
+
hydrate_knowledge_base_data_sources(
|
|
569
|
+
knowledge_bases=knowledge_bases, knowledge_base_specs=kb_specs, region=target.region
|
|
570
|
+
)
|
|
571
|
+
except Exception as hydrate_err: # noqa: BLE001
|
|
572
|
+
logger.log(f"Failed to hydrate knowledge base data sources: {get_error_message(hydrate_err)}", "warn")
|
|
573
|
+
|
|
574
|
+
payment_specs = []
|
|
575
|
+
for p in spec.payments or []:
|
|
576
|
+
connectors = []
|
|
577
|
+
for c in p.connectors:
|
|
578
|
+
if c.provision_mode == "QUICK_CREATE":
|
|
579
|
+
connectors.append({"name": c.name, "provisionMode": "QUICK_CREATE"})
|
|
580
|
+
else:
|
|
581
|
+
connector: dict[str, Any] = {"name": c.name}
|
|
582
|
+
if c.provision_mode:
|
|
583
|
+
connector["provisionMode"] = c.provision_mode
|
|
584
|
+
connector["credentialProviderArn"] = (deployed_credentials.get(c.credential_name) or {}).get(
|
|
585
|
+
"credentialProviderArn"
|
|
586
|
+
)
|
|
587
|
+
connector["credentialProviderName"] = c.credential_name
|
|
588
|
+
connectors.append(connector)
|
|
589
|
+
payment_specs.append(
|
|
590
|
+
{
|
|
591
|
+
"name": p.name,
|
|
592
|
+
"authorizerType": p.authorizer_type,
|
|
593
|
+
"autoPayment": p.auto_payment,
|
|
594
|
+
"paymentToolAllowlist": p.payment_tool_allowlist,
|
|
595
|
+
"networkPreferences": p.network_preferences,
|
|
596
|
+
"connectors": connectors,
|
|
597
|
+
}
|
|
598
|
+
)
|
|
599
|
+
payments = cfn_outputs.parse_payment_outputs(outputs, payment_specs) if payment_specs else None
|
|
600
|
+
|
|
601
|
+
deployed_harnesses = cfn_outputs.parse_harness_outputs(
|
|
602
|
+
outputs, [h.name for h in spec.harnesses or []], on_warn=lambda m: logger.log(m, "warn")
|
|
603
|
+
)
|
|
604
|
+
end_step("success")
|
|
605
|
+
|
|
606
|
+
deploy_hash: str | None = None
|
|
607
|
+
try:
|
|
608
|
+
deploy_hash = change_detection.compute_project_deploy_hash(config_io)
|
|
609
|
+
except Exception: # noqa: BLE001 - best-effort
|
|
610
|
+
pass
|
|
611
|
+
|
|
612
|
+
try:
|
|
613
|
+
existing_state = config_io.read_deployed_state()
|
|
614
|
+
except Exception: # noqa: BLE001
|
|
615
|
+
existing_state = None
|
|
616
|
+
existing_resources = _resources_json(existing_state, target.name)
|
|
617
|
+
prev_harness_records = existing_resources.get("harnesses")
|
|
618
|
+
|
|
619
|
+
deployed_state = cfn_outputs.build_deployed_state(
|
|
620
|
+
target_name=target.name,
|
|
621
|
+
stack_name=stack_name,
|
|
622
|
+
agents=agents,
|
|
623
|
+
gateways=gateways,
|
|
624
|
+
http_gateways=http_gateways or None,
|
|
625
|
+
existing_state=existing_state,
|
|
626
|
+
identity_kms_key_arn=identity_kms_key_arn,
|
|
627
|
+
credentials=deployed_credentials,
|
|
628
|
+
memories=memories,
|
|
629
|
+
evaluators=evaluators,
|
|
630
|
+
online_eval_configs=online_eval_configs,
|
|
631
|
+
policy_engines=policy_engines,
|
|
632
|
+
policies=policies,
|
|
633
|
+
harnesses=deployed_harnesses,
|
|
634
|
+
runtime_endpoints=runtime_endpoints,
|
|
635
|
+
datasets=datasets,
|
|
636
|
+
config_bundles=config_bundles,
|
|
637
|
+
knowledge_bases=knowledge_bases,
|
|
638
|
+
payments=payments,
|
|
639
|
+
capacity_providers=capacity_providers,
|
|
640
|
+
ab_test_names=[t.name for t in spec.ab_tests or []],
|
|
641
|
+
)
|
|
642
|
+
target_resources = deployed_state["targets"][target.name]["resources"]
|
|
643
|
+
if deploy_hash:
|
|
644
|
+
target_resources["deployHash"] = deploy_hash
|
|
645
|
+
|
|
646
|
+
# CFN succeeded; a failed local write must leave a recovery trail.
|
|
647
|
+
try:
|
|
648
|
+
config_io.write_deployed_state(deployed_state)
|
|
649
|
+
except Exception as write_err:
|
|
650
|
+
logger.log(
|
|
651
|
+
f"WARNING: deploy succeeded but writing agentcore/deployed-state.json failed: {write_err}.\n"
|
|
652
|
+
f" Stack: {stack_name} (region: {target.region})\n"
|
|
653
|
+
" AWS resources are running but the CLI cannot track them locally.\n"
|
|
654
|
+
" Recovery options:\n"
|
|
655
|
+
" 1) Fix the local I/O problem (disk space / permissions on agentcore/) and run "
|
|
656
|
+
"`agentcore status` to refresh.\n"
|
|
657
|
+
" 2) If you want to teardown what was deployed: `aws cloudformation delete-stack "
|
|
658
|
+
f"--stack-name {stack_name} --region {target.region}`"
|
|
659
|
+
)
|
|
660
|
+
raise
|
|
661
|
+
|
|
662
|
+
for drift in compute_harness_version_drift(prev_harness_records, deployed_harnesses):
|
|
663
|
+
logger.log(
|
|
664
|
+
f"Harness {drift.name}: config updated (v{drift.from_} → v{drift.to})"
|
|
665
|
+
if drift.from_ is not None
|
|
666
|
+
else f"Harness {drift.name}: deployed (v{drift.to})"
|
|
667
|
+
)
|
|
668
|
+
|
|
669
|
+
if gateways:
|
|
670
|
+
urls = ", ".join(f"{name}: {gw['gatewayArn']}" for name, gw in gateways.items())
|
|
671
|
+
logger.log(f"Gateway URLs: {urls}")
|
|
672
|
+
for gw in gateways.values():
|
|
673
|
+
for status in gateway_status.get_gateway_target_statuses(gw["gatewayId"], target.region):
|
|
674
|
+
logger.log(f" {status.name}: {gateway_status.format_target_status(status.status)}")
|
|
675
|
+
|
|
676
|
+
end_step("success")
|
|
677
|
+
|
|
678
|
+
post_deploy_warnings: list[str] = []
|
|
679
|
+
|
|
680
|
+
# Auto-payment posture is informational (notes, exit 0), never a partial-failure warning.
|
|
681
|
+
auto_payment_notices = []
|
|
682
|
+
for manager in spec.payments or []:
|
|
683
|
+
if manager.auto_payment is not False:
|
|
684
|
+
limit = manager.default_spend_limit or "10.00"
|
|
685
|
+
auto_payment_notices.append(
|
|
686
|
+
f'Payment manager "{manager.name}": auto-payment is ENABLED — the agent will settle '
|
|
687
|
+
f"402 responses automatically up to the per-session spend limit (${limit}) with no "
|
|
688
|
+
"human approval. Set --auto-payment false on the manager to require manual approval."
|
|
689
|
+
)
|
|
690
|
+
|
|
691
|
+
# Enable only newly deployed online eval configs (don't re-enable ones a user disabled).
|
|
692
|
+
deployed_online_evals = target_resources.get("onlineEvalConfigs") or {}
|
|
693
|
+
previous_online_evals = existing_resources.get("onlineEvalConfigs") or {}
|
|
694
|
+
new_online_evals = [c for c in spec.online_eval_configs or [] if c.name not in previous_online_evals]
|
|
695
|
+
if new_online_evals and deployed_online_evals:
|
|
696
|
+
enable_result = post_deploy_online_evals.enable_online_eval_configs(
|
|
697
|
+
region=target.region,
|
|
698
|
+
online_eval_configs=new_online_evals,
|
|
699
|
+
deployed_online_eval_configs=deployed_online_evals,
|
|
700
|
+
)
|
|
701
|
+
if enable_result.has_errors:
|
|
702
|
+
errors = [r for r in enable_result.results if r.status == "error"]
|
|
703
|
+
logger.log(
|
|
704
|
+
"Online eval enable warnings: " + "; ".join(f'"{e.config_name}": {e.error}' for e in errors), "warn"
|
|
705
|
+
)
|
|
706
|
+
post_deploy_warnings.extend(f'Online eval "{e.config_name}": {e.error}' for e in errors)
|
|
707
|
+
|
|
708
|
+
dataset_specs = spec.datasets or []
|
|
709
|
+
deployed_datasets = target_resources.get("datasets") or {}
|
|
710
|
+
if dataset_specs and deployed_datasets:
|
|
711
|
+
ds_result = post_deploy_datasets.sync_datasets(
|
|
712
|
+
region=target.region,
|
|
713
|
+
datasets=dataset_specs,
|
|
714
|
+
deployed_datasets=deployed_datasets,
|
|
715
|
+
config_base_dir=config_io.get_config_root(),
|
|
716
|
+
)
|
|
717
|
+
if any(r.status == "synced" for r in ds_result.results):
|
|
718
|
+
try:
|
|
719
|
+
updated = to_jsonable(config_io.read_deployed_state())
|
|
720
|
+
except Exception: # noqa: BLE001
|
|
721
|
+
updated = deployed_state
|
|
722
|
+
updated_resources = ((updated.get("targets") or {}).get(target.name) or {}).get("resources")
|
|
723
|
+
if updated_resources is not None:
|
|
724
|
+
updated_resources["datasets"] = ds_result.updated_datasets
|
|
725
|
+
config_io.write_deployed_state(updated)
|
|
726
|
+
deployed_state = updated
|
|
727
|
+
target_resources = updated_resources
|
|
728
|
+
if ds_result.has_errors:
|
|
729
|
+
errors = [r for r in ds_result.results if r.status == "error"]
|
|
730
|
+
logger.log(
|
|
731
|
+
"Dataset sync warnings: " + "; ".join(f'"{e.dataset_name}": {e.error}' for e in errors), "warn"
|
|
732
|
+
)
|
|
733
|
+
post_deploy_warnings.extend(f'Dataset "{e.dataset_name}": {e.error}' for e in errors)
|
|
734
|
+
for r in ds_result.results:
|
|
735
|
+
if r.status == "synced":
|
|
736
|
+
logger.log(
|
|
737
|
+
f'Dataset "{r.dataset_name}": +{r.added} added, ~{r.updated} updated, -{r.deleted} deleted'
|
|
738
|
+
)
|
|
739
|
+
|
|
740
|
+
if kb_specs:
|
|
741
|
+
start_step("Auto-ingest knowledge bases")
|
|
742
|
+
ingest_result = post_deploy_knowledge_bases.auto_ingest_knowledge_bases(
|
|
743
|
+
region=target.region,
|
|
744
|
+
knowledge_bases=kb_specs,
|
|
745
|
+
deployed_knowledge_bases=target_resources.get("knowledgeBases") or {},
|
|
746
|
+
previous_knowledge_bases=existing_resources.get("knowledgeBases"),
|
|
747
|
+
target_name=target.name,
|
|
748
|
+
deployed_state=deployed_state,
|
|
749
|
+
project_root=os.path.abspath(os.path.join(config_io.get_config_root(), "..")),
|
|
750
|
+
on_progress=lambda msg: logger.log(msg),
|
|
751
|
+
)
|
|
752
|
+
kb_records = target_resources.get("knowledgeBases")
|
|
753
|
+
if kb_records:
|
|
754
|
+
for r in ingest_result.results:
|
|
755
|
+
if r.status == "started" and r.new_sources_hash and r.knowledge_base_name in kb_records:
|
|
756
|
+
kb_records[r.knowledge_base_name]["sourcesHash"] = r.new_sources_hash
|
|
757
|
+
config_io.write_deployed_state(deployed_state)
|
|
758
|
+
for r in ingest_result.results:
|
|
759
|
+
if r.status == "started":
|
|
760
|
+
logger.log(
|
|
761
|
+
f'Knowledge base "{r.knowledge_base_name}": ingestion started for '
|
|
762
|
+
f"{r.started_job_count} data source(s)"
|
|
763
|
+
)
|
|
764
|
+
elif r.status == "skipped":
|
|
765
|
+
logger.log(f'Knowledge base "{r.knowledge_base_name}": skipped ({r.reason})')
|
|
766
|
+
else:
|
|
767
|
+
logger.log(f'Knowledge base "{r.knowledge_base_name}": {r.error}', "warn")
|
|
768
|
+
post_deploy_warnings.append(f'Knowledge base "{r.knowledge_base_name}": {r.error}')
|
|
769
|
+
end_step("error" if ingest_result.has_errors else "success")
|
|
770
|
+
|
|
771
|
+
has_invokable = bool(agent_names) or bool(spec.harnesses)
|
|
772
|
+
next_steps = list(AGENT_NEXT_STEPS if has_invokable else MEMORY_ONLY_NEXT_STEPS)
|
|
773
|
+
notes = list(auto_payment_notices)
|
|
774
|
+
quick_create = pca.get_quick_create_connector_authorizations(
|
|
775
|
+
region=target.region, project_spec=spec, payments=payments
|
|
776
|
+
)
|
|
777
|
+
notes.extend(pca.format_quick_create_connector_authorization(q) for q in quick_create)
|
|
778
|
+
|
|
779
|
+
has_python_agent = any(
|
|
780
|
+
(a.entrypoint or "").endswith(".py") or ".py:" in (a.entrypoint or "") for a in spec.runtimes or []
|
|
781
|
+
)
|
|
782
|
+
if (agent_names or has_gateways) and has_python_agent:
|
|
783
|
+
try:
|
|
784
|
+
ts_result = post_deploy_observability.setup_transaction_search(
|
|
785
|
+
region=target.region, account_id=target.account, agent_names=agent_names, has_gateways=has_gateways
|
|
786
|
+
)
|
|
787
|
+
if not ts_result.success:
|
|
788
|
+
logger.log(f"Transaction search setup warning: {ts_result.error}", "warn")
|
|
789
|
+
else:
|
|
790
|
+
notes.append(
|
|
791
|
+
"Transaction search enabled. It takes ~10 minutes for transaction search to be fully "
|
|
792
|
+
"active and for traces from invocations to be indexed."
|
|
793
|
+
)
|
|
794
|
+
except Exception as ts_err: # noqa: BLE001
|
|
795
|
+
logger.log(f"Transaction search setup failed: {get_error_message(ts_err)}", "warn")
|
|
796
|
+
|
|
797
|
+
logger.finalize(True)
|
|
798
|
+
all_warnings = [*orphan_warnings, *post_deploy_warnings]
|
|
799
|
+
return DeployResult(
|
|
800
|
+
success=True,
|
|
801
|
+
target_name=target.name,
|
|
802
|
+
stack_name=stack_name,
|
|
803
|
+
outputs=cfn_outputs.omit_payment_authorization_outputs(outputs),
|
|
804
|
+
log_path=logger.get_relative_log_path(),
|
|
805
|
+
next_steps=next_steps,
|
|
806
|
+
notes=notes,
|
|
807
|
+
post_deploy_warnings=all_warnings or None,
|
|
808
|
+
dependency_sync_result=sync_result,
|
|
809
|
+
)
|
|
810
|
+
except Exception as exc: # noqa: BLE001 - every failure becomes a result, as upstream
|
|
811
|
+
logger.log(get_error_message(exc), "error")
|
|
812
|
+
return fail(to_error(exc))
|
|
813
|
+
finally:
|
|
814
|
+
# Each cleanup step runs regardless of earlier failures.
|
|
815
|
+
if toolkit_wrapper is not None:
|
|
816
|
+
try:
|
|
817
|
+
toolkit_wrapper.dispose()
|
|
818
|
+
except Exception as dispose_err: # noqa: BLE001
|
|
819
|
+
logger.log(f"CDK toolkit dispose failed: {get_error_message(dispose_err)}", "warn")
|
|
820
|
+
if preview_restore is not None:
|
|
821
|
+
try:
|
|
822
|
+
preview_restore()
|
|
823
|
+
except Exception as restore_err: # noqa: BLE001
|
|
824
|
+
logger.log(f"Failed to revert preview vpcId backfill: {get_error_message(restore_err)}", "warn")
|
|
825
|
+
if restore_env is not None:
|
|
826
|
+
restore_env()
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
__all__ = [
|
|
830
|
+
"AGENT_NEXT_STEPS",
|
|
831
|
+
"MEMORY_ONLY_NEXT_STEPS",
|
|
832
|
+
"HarnessVersionDrift",
|
|
833
|
+
"ValidatedDeployOptions",
|
|
834
|
+
"compute_harness_version_drift",
|
|
835
|
+
"handle_deploy",
|
|
836
|
+
"run_deploy",
|
|
837
|
+
"run_diff",
|
|
838
|
+
"select_target_stack",
|
|
839
|
+
"to_stack_name",
|
|
840
|
+
]
|