diff --git a/docs/commands.md b/docs/commands.md index d804481c37..6997a07628 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -118,18 +118,23 @@ agentcore deploy -y # Auto-confirm agentcore deploy -y -v # Auto-confirm with verbose output agentcore deploy --dry-run # Preview without deploying agentcore deploy --diff # Show CDK diff without deploying +agentcore deploy -y --no-express # Deploy without CloudFormation Express mode agentcore deploy --target staging -y # Deploy to a specific target agentcore deploy -y --json # JSON output ``` -| Flag | Description | -| ----------------- | --------------------------------------------- | -| `--target ` | Deployment target name (default: `"default"`) | -| `-y, --yes` | Auto-confirm prompts | -| `-v, --verbose` | Resource-level deployment events | -| `--dry-run` | Preview deployment without deploying | -| `--diff` | Show CDK diff without deploying | -| `--json` | JSON output | +| Flag | Description | +| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `--target ` | Deployment target name (default: `"default"`) | +| `-y, --yes` | Auto-confirm prompts | +| `-v, --verbose` | Resource-level deployment events | +| `--dry-run` | Preview deployment without deploying | +| `--diff` | Show CDK diff without deploying | +| `--no-express` | Deploy without CloudFormation Express mode (Express mode, the default, does not roll back a failed deploy and does not wait for resources to stabilize) | +| `--json` | JSON output | + +Projects with online eval configs always deploy without Express mode, because an online eval config needs the agent +runtime log group, which exists only after the runtime finishes starting. ### status diff --git a/npm-shrinkwrap.json b/npm-shrinkwrap.json index 715c539354..103c5d82f0 100644 --- a/npm-shrinkwrap.json +++ b/npm-shrinkwrap.json @@ -11,7 +11,7 @@ "license": "Apache-2.0", "dependencies": { "@aws-cdk/cdk-assets-lib": "^1.4.10", - "@aws-cdk/toolkit-lib": "^1.28.0", + "@aws-cdk/toolkit-lib": "^1.44.1", "@aws-sdk/client-application-signals": "^3.1003.0", "@aws-sdk/client-bedrock": "^3.1012.0", "@aws-sdk/client-bedrock-agent": "^3.1012.0", @@ -360,20 +360,21 @@ } }, "node_modules/@aws-cdk/toolkit-lib": { - "version": "1.28.0", - "resolved": "https://registry.npmjs.org/@aws-cdk/toolkit-lib/-/toolkit-lib-1.28.0.tgz", - "integrity": "sha512-L1binntiOh/+stWOVcQF1rrEpnsW5F+IM23vTXEdRfzg18FBhAWK6GsDHUnmR2G0ziQCfOJ+HK1UBfBx2gSo/w==", + "version": "1.44.1", + "resolved": "https://registry.npmjs.org/@aws-cdk/toolkit-lib/-/toolkit-lib-1.44.1.tgz", + "integrity": "sha512-15mcRdbL0a1eCyH2a5rM5CzpcLY3xkqdneJheoSLchnujMvw6fBZ15xZMlHXaL8TZkZmCciR5AeeFuQUEZV1NA==", "license": "Apache-2.0", "dependencies": { "@aws-cdk/cdk-assets-lib": "^1", - "@aws-cdk/cloud-assembly-api": "2.2.5", - "@aws-cdk/cloud-assembly-schema": ">=54.2.0", + "@aws-cdk/cloud-assembly-api": "2.5.0", + "@aws-cdk/cloud-assembly-schema": ">=55.2.0", "@aws-cdk/cloudformation-diff": "^2", "@aws-cdk/cx-api": "^2", "@aws-sdk/client-appsync": "^3", "@aws-sdk/client-bedrock-agentcore-control": "^3", "@aws-sdk/client-cloudcontrol": "^3", "@aws-sdk/client-cloudformation": "^3", + "@aws-sdk/client-cloudtrail": "^3", "@aws-sdk/client-cloudwatch-logs": "^3", "@aws-sdk/client-codebuild": "^3", "@aws-sdk/client-ec2": "^3", @@ -397,19 +398,19 @@ "@smithy/shared-ini-file-loader": "^4", "@smithy/util-retry": "^4", "@smithy/util-waiter": "^4", - "archiver": "^7.0.1", - "cdk-from-cfn": "^0.302.0", + "cdk-from-cfn": "^0.338.0", "chalk": "^4", "chokidar": "^4", + "cross-spawn": "^7.0.6", "fast-deep-equal": "^3.1.3", "fast-glob": "^3.3.3", "fs-extra": "^11", "p-limit": "^3", "picomatch": "^4", - "semver": "^7.8.1", - "split2": "^4.2.0", + "semver": "^7.8.5", "wrap-ansi": "^7", - "yaml": "^1" + "yaml": "^2", + "yazl": "^3.3.1" }, "engines": { "node": ">= 18.0.0" @@ -418,13 +419,57 @@ "@aws-cdk/cli-plugin-contract": "^2" } }, - "node_modules/@aws-cdk/toolkit-lib/node_modules/yaml": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", - "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", + "node_modules/@aws-cdk/toolkit-lib/node_modules/@aws-cdk/cloud-assembly-api": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/cloud-assembly-api/-/cloud-assembly-api-2.5.0.tgz", + "integrity": "sha512-cE19OP9Ad3f04wkvntxqMxwKXutvkVyymwiqHsvEnmBktXjdm6Ydjd2X7b9QcU3QvbL7Gdt4bc3d4STMROCjfg==", + "license": "Apache-2.0", + "dependencies": { + "json-source-map": "^0.6.1", + "jsonschema": "^1.5.0", + "semver": "^7.8.5" + }, + "engines": { + "node": ">= 18.0.0" + }, + "peerDependencies": { + "@aws-cdk/cloud-assembly-schema": ">=55.0.0" + } + }, + "node_modules/@aws-cdk/toolkit-lib/node_modules/@aws-cdk/cloud-assembly-schema": { + "version": "55.2.0", + "resolved": "https://registry.npmjs.org/@aws-cdk/cloud-assembly-schema/-/cloud-assembly-schema-55.2.0.tgz", + "integrity": "sha512-DHfYrZdyJZwWlI5sOK97X7SDc5Ow+uH3w3/qnB/ZYtY530lEsLObOoq/Z8BcJM6bAwJI6ozIgg9VYg2ot+A1jQ==", + "bundleDependencies": [ + "jsonschema", + "semver" + ], + "license": "Apache-2.0", + "dependencies": { + "jsonschema": "^1.5.0", + "semver": "^7.8.5" + }, + "engines": { + "node": ">= 18.0.0" + } + }, + "node_modules/@aws-cdk/toolkit-lib/node_modules/@aws-cdk/cloud-assembly-schema/node_modules/jsonschema": { + "version": "1.5.0", + "inBundle": true, + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/@aws-cdk/toolkit-lib/node_modules/@aws-cdk/cloud-assembly-schema/node_modules/semver": { + "version": "7.8.5", + "inBundle": true, "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">= 6" + "node": ">=10" } }, "node_modules/@aws-crypto/crc32": { @@ -582,18 +627,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/checksums/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/client-application-signals": { "version": "3.1153.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-application-signals/-/client-application-signals-3.1153.0.tgz", @@ -613,18 +646,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/client-application-signals/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/client-appsync": { "version": "3.1036.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-appsync/-/client-appsync-3.1036.0.tgz", @@ -715,18 +736,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-agent/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/client-bedrock-agentcore": { "version": "3.1153.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-agentcore/-/client-bedrock-agentcore-3.1153.0.tgz", @@ -765,30 +774,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-agentcore-control/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-bedrock-agentcore/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/client-bedrock-runtime": { "version": "3.1153.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-bedrock-runtime/-/client-bedrock-runtime-3.1153.0.tgz", @@ -812,30 +797,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/client-bedrock-runtime/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/client-bedrock/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/client-cloudcontrol": { "version": "3.1036.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudcontrol/-/client-cloudcontrol-3.1036.0.tgz", @@ -906,16 +867,23 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/client-cloudformation/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", + "node_modules/@aws-sdk/client-cloudtrail": { + "version": "3.1157.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cloudtrail/-/client-cloudtrail-3.1157.0.tgz", + "integrity": "sha512-HGMlPA/rgGyRtYm19AZa3lBEXzMoFk4tM+7gSAX7z0xjC0fDzG2yZNrQkpOiOB1HSbSlrIelrpQR6uI8cgx5RQ==", "license": "Apache-2.0", "dependencies": { + "@aws-sdk/core": "^3.978.6", + "@aws-sdk/credential-provider-node": "^3.972.89", + "@aws-sdk/types": "^3.975.0", + "@smithy/core": "^3.37.0", + "@smithy/fetch-http-handler": "^5.8.0", + "@smithy/node-http-handler": "^4.13.0", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@aws-sdk/client-cloudwatch-logs": { @@ -937,18 +905,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/client-cloudwatch-logs/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/client-codebuild": { "version": "3.1036.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-codebuild/-/client-codebuild-3.1036.0.tgz", @@ -1019,19 +975,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/client-cognito-identity-provider/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/client-ec2": { "version": "3.1036.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-ec2/-/client-ec2-3.1036.0.tgz", @@ -1205,18 +1148,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/client-efs/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/client-elastic-load-balancing-v2": { "version": "3.1036.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-elastic-load-balancing-v2/-/client-elastic-load-balancing-v2-3.1036.0.tgz", @@ -1443,18 +1374,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/client-resource-groups-tagging-api/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/client-route-53": { "version": "3.1036.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-route-53/-/client-route-53-3.1036.0.tgz", @@ -1529,18 +1448,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/client-s3/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/client-s3files": { "version": "3.1153.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3files/-/client-s3files-3.1153.0.tgz", @@ -1560,18 +1467,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/client-s3files/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/client-secrets-manager": { "version": "3.1036.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-secrets-manager/-/client-secrets-manager-3.1036.0.tgz", @@ -1743,18 +1638,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/client-sts/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/client-xray": { "version": "3.1153.0", "resolved": "https://registry.npmjs.org/@aws-sdk/client-xray/-/client-xray-3.1153.0.tgz", @@ -1774,28 +1657,16 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/client-xray/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/core": { - "version": "3.978.4", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.978.4.tgz", - "integrity": "sha512-JvGp6y9sPX8FSs2K/EmFMZcUfdkHxqGE45+oxwGC75OIh50j2e4cbx7zcR3BwNs2DSGqJdBja5h6Vy89iIDmRQ==", + "version": "3.978.6", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.978.6.tgz", + "integrity": "sha512-ykF/MiYoM15dgZwF/WLgjJXVbAK2wU6vjPigeEnOHwyUJ0rdlraO5uekecKNVPkvOnz+oju/5zljViQs1nI1FQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.974.6", + "@aws-sdk/types": "^3.975.0", "@aws-sdk/xml-builder": "^3.972.41", "@aws/lambda-invoke-store": "^0.3.0", - "@smithy/core": "^3.36.0", + "@smithy/core": "^3.37.0", "@smithy/signature-v4": "^5.7.4", "@smithy/types": "^4.19.0", "bowser": "^2.11.0", @@ -1814,147 +1685,12 @@ "node": ">=18.0.0" } }, - "node_modules/@aws-sdk/core/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-cognito-identity": { - "version": "3.972.74", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.972.74.tgz", - "integrity": "sha512-IYfhaLlWr5Y1gyhm87aChm4SkxNAiRtNuKyUyNUqQ9igyfdlp2nPeycL0Cdi88oovBqVoHim1b9NaiEDZ3DfCA==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/nested-clients": "^3.997.49", - "@aws-sdk/types": "^3.974.6", - "@smithy/core": "^3.36.0", - "@smithy/types": "^4.19.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-cognito-identity/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.972.75", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.75.tgz", - "integrity": "sha512-nc8Epg98PcYoKNx0VFlwtmZSCP+tuJ1FLWqpslET/gp4h/WYuULSJqtxppM6ywKKDdzNJPvLD7ceRfmxm3Qdxw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.978.4", - "@aws-sdk/types": "^3.974.6", - "@smithy/core": "^3.36.0", - "@smithy/types": "^4.19.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-env/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.972.77", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.77.tgz", - "integrity": "sha512-KkYFdIQwuw9IOHfEzK78slxmVWuhcm1w6YgE3V3WVxAeRRj9q5J9jlwzpY/oszWxd4SD96FTFkDdRGBdMFF2Mw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.978.4", - "@aws-sdk/types": "^3.974.6", - "@smithy/core": "^3.36.0", - "@smithy/fetch-http-handler": "^5.8.0", - "@smithy/node-http-handler": "^4.12.1", - "@smithy/types": "^4.19.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-http/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.973.20", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.973.20.tgz", - "integrity": "sha512-OSl2R/0zLkoeKEIy6oP2tu/bsSdY+DGgro2eOffMD2CcP8POv7rS14FY5Jzc5bjnqB1G9wv/aM1akHC2mdlhZw==", - "license": "Apache-2.0", - "dependencies": { - "@aws-sdk/core": "^3.978.4", - "@aws-sdk/credential-provider-env": "^3.972.75", - "@aws-sdk/credential-provider-http": "^3.972.77", - "@aws-sdk/credential-provider-login": "^3.972.82", - "@aws-sdk/credential-provider-process": "^3.972.75", - "@aws-sdk/credential-provider-sso": "^3.973.19", - "@aws-sdk/credential-provider-web-identity": "^3.972.81", - "@aws-sdk/nested-clients": "^3.997.49", - "@aws-sdk/types": "^3.974.6", - "@smithy/core": "^3.36.0", - "@smithy/credential-provider-imds": "^4.5.2", - "@smithy/types": "^4.19.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=20.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-ini/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@aws-sdk/credential-provider-login": { - "version": "3.972.82", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.82.tgz", - "integrity": "sha512-8jyDPtf1WPxeQ/5xlNpyxAD6P7YKwkYeNk8B2vFEDwkPWDvb7c3tQJG5/jbNWbF2yTMIH9tDTueBkdfovYIAPw==", + "node_modules/@aws-sdk/credential-provider-cognito-identity": { + "version": "3.972.74", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.972.74.tgz", + "integrity": "sha512-IYfhaLlWr5Y1gyhm87aChm4SkxNAiRtNuKyUyNUqQ9igyfdlp2nPeycL0Cdi88oovBqVoHim1b9NaiEDZ3DfCA==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.978.4", "@aws-sdk/nested-clients": "^3.997.49", "@aws-sdk/types": "^3.974.6", "@smithy/core": "^3.36.0", @@ -1965,33 +1701,33 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-provider-login/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.972.77", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.972.77.tgz", + "integrity": "sha512-CN6dQCDo32a8n2gvm2HBeqGV5BNI9noG96nTj5bGO2HWtt0Rucu/A8pcnJIqkzILOHSuilnCk0Do8/7h6SOXhQ==", "license": "Apache-2.0", "dependencies": { + "@aws-sdk/core": "^3.978.6", + "@aws-sdk/types": "^3.975.0", + "@smithy/core": "^3.37.0", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.972.87", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.87.tgz", - "integrity": "sha512-TKj2C0x4IMPSSOAlmeryX8fCPvvPS2pFJz2ikV9IGqyh6Ehsg4leMalCTVfV2rvMTrlGAe7X7nK0HZ3P0KZR9g==", + "node_modules/@aws-sdk/credential-provider-http": { + "version": "3.972.79", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.972.79.tgz", + "integrity": "sha512-Netsu0nnmvP2HiN1ZFQBeUu+JehQIuubqz+j2kHDgeSE4HDzniCpIZ7RzoWABq+LTcbCi9W03hywifUagoVIWQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/credential-provider-env": "^3.972.75", - "@aws-sdk/credential-provider-http": "^3.972.77", - "@aws-sdk/credential-provider-ini": "^3.973.20", - "@aws-sdk/credential-provider-process": "^3.972.75", - "@aws-sdk/credential-provider-sso": "^3.973.19", - "@aws-sdk/credential-provider-web-identity": "^3.972.81", - "@aws-sdk/types": "^3.974.6", - "@smithy/core": "^3.36.0", - "@smithy/credential-provider-imds": "^4.5.2", + "@aws-sdk/core": "^3.978.6", + "@aws-sdk/types": "^3.975.0", + "@smithy/core": "^3.37.0", + "@smithy/fetch-http-handler": "^5.8.0", + "@smithy/node-http-handler": "^4.13.0", "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, @@ -1999,27 +1735,40 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-provider-node/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.973.22", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.973.22.tgz", + "integrity": "sha512-x7/5h58cqOoZR0RWUZC7v/cJOADQR42iSIQkvU+00HVHR4jh8ZpqEgRPGf2zei59iH5qP40lL3bkq49PuWl71g==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/core": "^3.978.6", + "@aws-sdk/credential-provider-env": "^3.972.77", + "@aws-sdk/credential-provider-http": "^3.972.79", + "@aws-sdk/credential-provider-login": "^3.972.84", + "@aws-sdk/credential-provider-process": "^3.972.77", + "@aws-sdk/credential-provider-sso": "^3.973.21", + "@aws-sdk/credential-provider-web-identity": "^3.972.83", + "@aws-sdk/nested-clients": "^3.997.51", + "@aws-sdk/types": "^3.975.0", + "@smithy/core": "^3.37.0", + "@smithy/credential-provider-imds": "^4.5.2", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.972.75", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.75.tgz", - "integrity": "sha512-ZNm8T/HJNhpS8MikDVAsym8QyUSUuOUGiCkmI3TTya7G6xhOgfRLd2iK91HhQQyvRM36eo6Xm845hHVyfToA2w==", + "node_modules/@aws-sdk/credential-provider-login": { + "version": "3.972.84", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.972.84.tgz", + "integrity": "sha512-G9Ty1uIV0laEvEp2KiMbEhsuBAjgaD3KYrwVjAM5VUxpcIuPBqQI5riA7/qzrnSgYiAKQbubbgkwcqCICKCIxg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.978.4", - "@aws-sdk/types": "^3.974.6", - "@smithy/core": "^3.36.0", + "@aws-sdk/core": "^3.978.6", + "@aws-sdk/nested-clients": "^3.997.51", + "@aws-sdk/types": "^3.975.0", + "@smithy/core": "^3.37.0", "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, @@ -2027,29 +1776,37 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-provider-process/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.972.89", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.972.89.tgz", + "integrity": "sha512-O8xj7/sanrnXfFHu/LUujVBiiwn5mknYenU7xt1w6+yvhR1QoDZWXLFh1gLITaFVPtb1jWgEirC+kFNw+//tyw==", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/credential-provider-env": "^3.972.77", + "@aws-sdk/credential-provider-http": "^3.972.79", + "@aws-sdk/credential-provider-ini": "^3.973.22", + "@aws-sdk/credential-provider-process": "^3.972.77", + "@aws-sdk/credential-provider-sso": "^3.973.21", + "@aws-sdk/credential-provider-web-identity": "^3.972.83", + "@aws-sdk/types": "^3.975.0", + "@smithy/core": "^3.37.0", + "@smithy/credential-provider-imds": "^4.5.2", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.973.19", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.973.19.tgz", - "integrity": "sha512-qHGDAGesyWtRw3BapyFkYSUzVNrC1CWPS6+S2lf/MLMEkWB2gR3Bl6imVHy1nhImXKS+gcuUDzbu39BnsHJc1Q==", + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.972.77", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.972.77.tgz", + "integrity": "sha512-sWA8Jm+ASzkTxoqLizHWRbt8Gj3yZCmZ0hYdvg0uIxuLzWseYcfrDFzaSnkRWlEWSJV38rAWFimdrN0J4NR7Pg==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.978.4", - "@aws-sdk/nested-clients": "^3.997.49", - "@aws-sdk/token-providers": "3.1153.0", - "@aws-sdk/types": "^3.974.6", - "@smithy/core": "^3.36.0", + "@aws-sdk/core": "^3.978.6", + "@aws-sdk/types": "^3.975.0", + "@smithy/core": "^3.37.0", "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, @@ -2057,28 +1814,34 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-provider-sso/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.973.21", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.973.21.tgz", + "integrity": "sha512-KV2LM8fbYUhDzGEBnPwb+ISNfNlhmnpLS+y6A6VsJpg1EI9aUJ0+dRTxh2GrGdneFH0T4TiuboHxz8i6+M38JA==", "license": "Apache-2.0", "dependencies": { + "@aws-sdk/core": "^3.978.6", + "@aws-sdk/nested-clients": "^3.997.51", + "@aws-sdk/token-providers": "3.1157.0", + "@aws-sdk/types": "^3.975.0", + "@smithy/core": "^3.37.0", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.972.81", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.81.tgz", - "integrity": "sha512-nHkgkMIC6NHgqfI6UAQq5cCS4bUkNxkT+r9fXCq/X4IKfX/DHGZ8UM3T4b78OXpWK5OlzEzN4kxwyax0W/MUCA==", + "node_modules/@aws-sdk/credential-provider-sso/node_modules/@aws-sdk/token-providers": { + "version": "3.1157.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1157.0.tgz", + "integrity": "sha512-AeAzcwWRP2uANO2TjFpKjRdvOCzgfIu6YQl9Ceibd6E0gnq5dfOzujFnq2aeqgbLg4wRtXbUZE4gekCCPrz/OQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.978.4", - "@aws-sdk/nested-clients": "^3.997.49", - "@aws-sdk/types": "^3.974.6", - "@smithy/core": "^3.36.0", + "@aws-sdk/core": "^3.978.6", + "@aws-sdk/nested-clients": "^3.997.51", + "@aws-sdk/types": "^3.975.0", + "@smithy/core": "^3.37.0", "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, @@ -2086,16 +1849,21 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-provider-web-identity/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.972.83", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.972.83.tgz", + "integrity": "sha512-iekYilmo2Re51fC7gMkEfZ7jFDXwehSCmXjDESaYQsdgYhsLQFG7rTYr3GBvRIyj+Fkda2NxbZX7hAZDaFD0JQ==", "license": "Apache-2.0", "dependencies": { + "@aws-sdk/core": "^3.978.6", + "@aws-sdk/nested-clients": "^3.997.51", + "@aws-sdk/types": "^3.975.0", + "@smithy/core": "^3.37.0", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { - "node": ">=18.0.0" + "node": ">=20.0.0" } }, "node_modules/@aws-sdk/credential-providers": { @@ -2125,18 +1893,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/credential-providers/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/ec2-metadata-service": { "version": "3.1018.0", "resolved": "https://registry.npmjs.org/@aws-sdk/ec2-metadata-service/-/ec2-metadata-service-3.1018.0.tgz", @@ -2170,18 +1926,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/eventstream-handler-node/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/lib-storage": { "version": "3.1018.0", "resolved": "https://registry.npmjs.org/@aws-sdk/lib-storage/-/lib-storage-3.1018.0.tgz", @@ -2219,18 +1963,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/middleware-eventstream/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/middleware-host-header": { "version": "3.972.10", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.972.10.tgz", @@ -2326,18 +2058,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/middleware-sdk-s3/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/middleware-user-agent": { "version": "3.972.37", "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.972.37.tgz", @@ -2375,30 +2095,18 @@ "node": ">= 14.0.0" } }, - "node_modules/@aws-sdk/middleware-websocket/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/nested-clients": { - "version": "3.997.49", - "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.49.tgz", - "integrity": "sha512-zjqIqzTYLRKhT7TPJDUreK9vG9PjhmnfLCaTaqArkRT7j+Ogl0tuXB7MpSd8rlRfRT+xTOeyNFWaOfyNcf51hg==", + "version": "3.997.51", + "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.997.51.tgz", + "integrity": "sha512-DJK4iGIHWU8Jh8ODMvqFYcX9yGBMXV4tSZAvqlHF5EDd8hbmF3eFO9KIWOnA7wcQjPzEkyMMW1/FgZ9RU8oimQ==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/core": "^3.978.4", - "@aws-sdk/signature-v4-multi-region": "^3.996.48", - "@aws-sdk/types": "^3.974.6", - "@smithy/core": "^3.36.0", + "@aws-sdk/core": "^3.978.6", + "@aws-sdk/signature-v4-multi-region": "^3.996.49", + "@aws-sdk/types": "^3.975.0", + "@smithy/core": "^3.37.0", "@smithy/fetch-http-handler": "^5.8.0", - "@smithy/node-http-handler": "^4.12.1", + "@smithy/node-http-handler": "^4.13.0", "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, @@ -2406,18 +2114,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/nested-clients/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/region-config-resolver": { "version": "3.972.53", "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.972.53.tgz", @@ -2432,12 +2128,12 @@ } }, "node_modules/@aws-sdk/signature-v4-multi-region": { - "version": "3.996.48", - "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.48.tgz", - "integrity": "sha512-cFDXfEbXaGwbnpvR/DyqfxfjxpjXVRVthQLgkwvcfDS5u3+8G9WSj1X1Ag/pTRg/QOeOno1Tq3ycEdrKsCUcOA==", + "version": "3.996.49", + "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.996.49.tgz", + "integrity": "sha512-nvuAZNRrRRVCiARRKsYlQ0VnXiEQiq7vXPH+UA+LSo+kN3Djl9eo/V2r0udkw85PnsNshmv2Em1clld5M3j67w==", "license": "Apache-2.0", "dependencies": { - "@aws-sdk/types": "^3.974.6", + "@aws-sdk/types": "^3.975.0", "@smithy/signature-v4": "^5.7.4", "@smithy/types": "^4.19.0", "tslib": "^2.6.2" @@ -2446,18 +2142,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/signature-v4-multi-region/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/token-providers": { "version": "3.1153.0", "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.1153.0.tgz", @@ -2475,22 +2159,10 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/token-providers/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/types": { - "version": "3.974.6", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.974.6.tgz", - "integrity": "sha512-v/clNZzZnDxGyvpHMOGpJKVXFAExJzUNAAjaWGdcx8QAcXLGwTaOkw33p5SHAi0YAioK32xB3hWwOekRVfmfKg==", + "version": "3.975.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.975.0.tgz", + "integrity": "sha512-WQlhs6juByzWOzj5fwxOx0mPJaEqMcG/sDpl3Id61B3XhKE63xY+0QWcnG+sWR/sCfprmreyUo1lM7IKZmHMzw==", "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.19.0", @@ -2500,18 +2172,6 @@ "node": ">=20.0.0" } }, - "node_modules/@aws-sdk/types/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@aws-sdk/util-endpoints": { "version": "3.996.8", "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.996.8.tgz", @@ -4908,9 +4568,9 @@ } }, "node_modules/@smithy/core": { - "version": "3.36.0", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.36.0.tgz", - "integrity": "sha512-3hJiwG1F5t1SoXqp/yOCmYXziyx7ZVqF63S5W6YU201e/qwVaHPex+E/3vvyY9a3ORq/b+BydeNZpP2saQ9X2g==", + "version": "3.37.0", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.37.0.tgz", + "integrity": "sha512-97imTcCyiPd8k0e9+ts/Sp0W65Dn9Ti357J7M09Ov4tI8Q1JDJVFSoAJtjEVKqfHEr3Pdo2jfolqKCaaiszH0g==", "license": "Apache-2.0", "dependencies": { "@smithy/types": "^4.19.0", @@ -4920,18 +4580,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/core/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/credential-provider-imds": { "version": "4.5.2", "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.5.2.tgz", @@ -4946,18 +4594,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/credential-provider-imds/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/eventstream-codec": { "version": "4.2.14", "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.14.tgz", @@ -5042,18 +4678,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/fetch-http-handler/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/hash-node": { "version": "4.2.14", "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.14.tgz", @@ -5192,25 +4816,13 @@ } }, "node_modules/@smithy/node-http-handler": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.12.1.tgz", - "integrity": "sha512-ThMkboGeONWXAelq9FvGsuJC4rOi+qyC4/zhUF58xYpxUg5sQKx2VXZYJmtNjr4dSuBJ1HeJXETQILCz3wOHvw==", - "license": "Apache-2.0", - "dependencies": { - "@smithy/core": "^3.33.3", - "@smithy/types": "^4.18.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@smithy/node-http-handler/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.13.0.tgz", + "integrity": "sha512-/GGcPoNJ2nzGytdAanpbx7mpp9Coa8LP+/Rpmbktr8YeLuIXs9B0SEz+X3AeonHdyzOIFJdKbN7jOZ+Tj+pMGw==", "license": "Apache-2.0", "dependencies": { + "@smithy/core": "^3.37.0", + "@smithy/types": "^4.19.0", "tslib": "^2.6.2" }, "engines": { @@ -5309,18 +4921,6 @@ "node": ">=18.0.0" } }, - "node_modules/@smithy/signature-v4/node_modules/@smithy/types": { - "version": "4.19.0", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", - "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@smithy/smithy-client": { "version": "4.12.13", "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.12.13.tgz", @@ -5340,9 +4940,9 @@ } }, "node_modules/@smithy/types": { - "version": "4.16.1", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.16.1.tgz", - "integrity": "sha512-0JFs3V2y2M9tKW5na/qxe69Zv+uxLMO7QBbhxF/FHu/Gp2NFZAAL9tWl9PU02xxo07pb3G9FTyjNc6D5uZrJIg==", + "version": "4.19.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.19.0.tgz", + "integrity": "sha512-r7jh49VJxGerfAcTQA6gXcKc+98zOp/tqRwzYjgOE+iSQsP6cEU1hq2QzbuipmP68QtYdY9wKEhiCQZIzHgZ4Q==", "license": "Apache-2.0", "dependencies": { "tslib": "^2.6.2" @@ -7573,9 +7173,9 @@ } }, "node_modules/cdk-from-cfn": { - "version": "0.302.0", - "resolved": "https://registry.npmjs.org/cdk-from-cfn/-/cdk-from-cfn-0.302.0.tgz", - "integrity": "sha512-jbwwzl9yXhCpuOacrQ/jDXnsEnWE7n5UqhfnCdpGOvLhy2FqWlbk1Wd7mDwNsT/QfL3AYZqIyjYSsSLxYVjPlA==", + "version": "0.338.0", + "resolved": "https://registry.npmjs.org/cdk-from-cfn/-/cdk-from-cfn-0.338.0.tgz", + "integrity": "sha512-jIrGLU8g2CLkn4fPtaDP0QurSbtnDWiMUTykaohQRldjImhGBWRTIAO8H/yS2mMIKnJu3pN9VD1t39cIgUSbQg==", "license": "MIT OR Apache-2.0" }, "node_modules/chai": { @@ -10929,6 +10529,12 @@ "dev": true, "license": "BSD-2-Clause" }, + "node_modules/json-source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/json-source-map/-/json-source-map-0.6.1.tgz", + "integrity": "sha512-1QoztHPsMQqhDq0hlXY5ZqcEdUzxQEIxgFkKl4WUp2pgShObl+9ovi4kRh2TfvAfxAoHOJ9vIMEqk3k4iex7tg==", + "license": "MIT" + }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -14446,15 +14052,6 @@ "dev": true, "license": "CC0-1.0" }, - "node_modules/split2": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", - "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", - "license": "ISC", - "engines": { - "node": ">= 10.x" - } - }, "node_modules/stable-hash-x": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/stable-hash-x/-/stable-hash-x-0.2.0.tgz", @@ -16576,6 +16173,15 @@ "url": "https://github.com/sponsors/eemeli" } }, + "node_modules/yazl": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/yazl/-/yazl-3.3.1.tgz", + "integrity": "sha512-BbETDVWG+VcMUle37k5Fqp//7SDOK2/1+T7X8TD96M3D9G8jK5VLUdQVdVjGi8im7FGkazX7kk5hkU8X4L5Bng==", + "license": "MIT", + "dependencies": { + "buffer-crc32": "^1.0.0" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index 07eb35af9c..be83a39ba8 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,7 @@ }, "dependencies": { "@aws-cdk/cdk-assets-lib": "^1.4.10", - "@aws-cdk/toolkit-lib": "^1.28.0", + "@aws-cdk/toolkit-lib": "^1.44.1", "@aws-sdk/client-application-signals": "^3.1003.0", "@aws-sdk/client-bedrock": "^3.1012.0", "@aws-sdk/client-bedrock-agent": "^3.1012.0", diff --git a/src/cli/cdk/toolkit-lib/__tests__/wrapper.test.ts b/src/cli/cdk/toolkit-lib/__tests__/wrapper.test.ts new file mode 100644 index 0000000000..15c871c9aa --- /dev/null +++ b/src/cli/cdk/toolkit-lib/__tests__/wrapper.test.ts @@ -0,0 +1,84 @@ +import { ConflictError } from '../../../../lib'; +import { silentIoHost } from '../types.js'; +import { CdkToolkitWrapper } from '../wrapper.js'; +import { type IIoHost, StackSelectionStrategy } from '@aws-cdk/toolkit-lib'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; + +const deploySpy = vi.fn(); +let toolkitIoHost: IIoHost | undefined; + +vi.mock('@aws-cdk/toolkit-lib', async () => { + const actual = await vi.importActual('@aws-cdk/toolkit-lib'); + return { + ...actual, + Toolkit: class { + fromCdkApp = vi.fn().mockResolvedValue({}); + deploy = deploySpy; + constructor(props: { ioHost?: IIoHost }) { + toolkitIoHost = props.ioHost; + } + }, + }; +}); + +const stacks = { strategy: StackSelectionStrategy.PATTERN_MUST_MATCH, patterns: ['AgentCore-myapp-default'] }; + +async function initializedWrapper() { + const wrapper = new CdkToolkitWrapper({ + projectDir: '/tmp/agentcore-cdk', + region: 'us-west-2', + ioHost: silentIoHost, + }); + await wrapper.initialize(); + return wrapper; +} + +describe('CdkToolkitWrapper.deploy', () => { + beforeEach(() => { + deploySpy.mockReset(); + deploySpy.mockResolvedValue({ stacks: [] }); + }); + + it.each([ + { express: undefined, expected: true }, + { express: false, expected: false }, + ])('deploys with express=$expected when express is $express', async ({ express, expected }) => { + const wrapper = await initializedWrapper(); + + await expect(wrapper.deploy({ stacks, express })).resolves.toEqual({ stabilizationWarning: undefined }); + + expect(deploySpy).toHaveBeenCalledWith(expect.anything(), { stacks, express: expected }); + }); + + it('returns the Express mode stabilization warning emitted during deploy', async () => { + const wrapper = await initializedWrapper(); + deploySpy.mockImplementation(async () => { + await toolkitIoHost!.notify({ + time: new Date(), + level: 'warn', + action: 'deploy', + code: 'CDK_TOOLKIT_W5902', + message: 'ApplicationAgentRuntime is still stabilizing', + data: undefined, + }); + return { stacks: [] }; + }); + + await expect(wrapper.deploy({ stacks })).resolves.toEqual({ + stabilizationWarning: 'ApplicationAgentRuntime is still stabilizing', + }); + }); + + it('replaces the toolkit-lib ExpressStackFailPaused advice with agentcore guidance', async () => { + const wrapper = await initializedWrapper(); + const toolkitError = new Error('Run `cdk deploy --express --no-rollback` to deploy this change without rollback.'); + toolkitError.name = 'ExpressStackFailPaused'; + deploySpy.mockRejectedValue(toolkitError); + + const error = await wrapper.deploy({ stacks, express: false }).catch((e: unknown) => e); + + expect(error).toBeInstanceOf(ConflictError); + expect((error as Error).message).toContain('run `agentcore deploy` without --no-express'); + expect((error as Error).message).not.toContain('cdk deploy'); + }); +}); diff --git a/src/cli/cdk/toolkit-lib/index.ts b/src/cli/cdk/toolkit-lib/index.ts index a06620e167..d70312d79c 100644 --- a/src/cli/cdk/toolkit-lib/index.ts +++ b/src/cli/cdk/toolkit-lib/index.ts @@ -4,6 +4,7 @@ export type { CdkToolkitWrapperOptions, DeployMessage, DeployOptions, + DeployOutcome, DestroyOptions, DiffOptions, ListOptions, diff --git a/src/cli/cdk/toolkit-lib/types.ts b/src/cli/cdk/toolkit-lib/types.ts index 261e01712b..47400d8e76 100644 --- a/src/cli/cdk/toolkit-lib/types.ts +++ b/src/cli/cdk/toolkit-lib/types.ts @@ -190,7 +190,12 @@ export interface StackSelectionOptions { }; } -export type DeployOptions = StackSelectionOptions; +export type DeployOptions = StackSelectionOptions & { express?: boolean }; + +export interface DeployOutcome { + /** Express mode only: resources CloudFormation reported complete while they were still stabilizing */ + stabilizationWarning?: string; +} export type DestroyOptions = StackSelectionOptions; diff --git a/src/cli/cdk/toolkit-lib/wrapper.ts b/src/cli/cdk/toolkit-lib/wrapper.ts index 72cdec9215..28e9d656d7 100644 --- a/src/cli/cdk/toolkit-lib/wrapper.ts +++ b/src/cli/cdk/toolkit-lib/wrapper.ts @@ -1,12 +1,20 @@ -import { CONFIG_DIR } from '../../../lib'; +import { CONFIG_DIR, ConflictError } from '../../../lib'; import { CDK_APP_ENTRY, CDK_PROJECT_DIR } from '../../constants'; import { isChangesetInProgressError } from '../../errors'; -import type { CdkToolkitWrapperOptions, DeployOptions, DestroyOptions, DiffOptions, ListOptions } from './types'; +import type { + CdkToolkitWrapperOptions, + DeployOptions, + DeployOutcome, + DestroyOptions, + DiffOptions, + ListOptions, +} from './types'; import { BaseCredentials, BootstrapEnvironments, BootstrapStackParameters, type ICloudAssemblySource, + type IIoHost, Toolkit, } from '@aws-cdk/toolkit-lib'; import * as path from 'node:path'; @@ -60,6 +68,7 @@ export class CdkToolkitWrapper { private synthResult: SynthResult | null = null; private synthesizedAssembly: DisposableAssembly | null = null; private synthesizedAssemblyDir: string | null = null; + private stabilizationWarning: string | undefined; constructor(options: CdkToolkitWrapperOptions = {}) { this.projectDir = options.projectDir ?? path.join(process.cwd(), CONFIG_DIR, CDK_PROJECT_DIR); @@ -98,7 +107,7 @@ export class CdkToolkitWrapper { : undefined; this.toolkit = new Toolkit({ - ioHost: this.options.ioHost, + ioHost: this.captureStabilizationWarning(this.options.ioHost), sdkConfig, }); @@ -114,6 +123,17 @@ export class CdkToolkitWrapper { }); } + private captureStabilizationWarning(ioHost?: IIoHost): IIoHost | undefined { + if (!ioHost) return undefined; + return { + notify: msg => { + if (msg.code === 'CDK_TOOLKIT_W5902') this.stabilizationWarning = msg.message; + return ioHost.notify(msg); + }, + requestResponse: msg => ioHost.requestResponse(msg), + }; + } + /** * Ensure the toolkit is initialized. */ @@ -233,9 +253,10 @@ export class CdkToolkitWrapper { * Includes retry logic for transient changeset conflicts that can occur * when multiple operations race on the same stack. */ - async deploy(options: DeployOptions = {}) { + async deploy(options: DeployOptions = {}): Promise { const { toolkit } = this.ensureInitialized(); const source = await this.getSourceForOperation(); + this.stabilizationWarning = undefined; const maxRetries = 3; const baseDelayMs = 5000; // 5 seconds base delay @@ -243,8 +264,19 @@ export class CdkToolkitWrapper { for (let attempt = 0; attempt < maxRetries; attempt++) { try { - return await withErrorContext('deploy', () => toolkit.deploy(source, { stacks: options.stacks })); + await withErrorContext('deploy', () => + toolkit.deploy(source, { stacks: options.stacks, express: options.express ?? true }) + ); + return { stabilizationWarning: this.stabilizationWarning }; } catch (err) { + if (err instanceof Error && err.name === 'ExpressStackFailPaused') { + throw new ConflictError( + 'The last Express mode deploy of this stack failed, so CloudFormation cannot roll it back or replace ' + + 'resources until it recovers. Fix the failure and run `agentcore deploy` without --no-express. If the ' + + 'change replaces a resource, first redeploy the last configuration that worked, then apply the change.', + { cause: err } + ); + } lastError = err instanceof Error ? err : new Error(String(err)); // Only retry on changeset-in-progress errors diff --git a/src/cli/cloudformation/__tests__/stack-status.test.ts b/src/cli/cloudformation/__tests__/stack-status.test.ts index 1df83fc95f..c6336120fa 100644 --- a/src/cli/cloudformation/__tests__/stack-status.test.ts +++ b/src/cli/cloudformation/__tests__/stack-status.test.ts @@ -34,10 +34,8 @@ describe('checkStackStatus', () => { expect(result.status).toBe('CREATE_COMPLETE'); }); - it('returns canDeploy true for UPDATE_COMPLETE', async () => { - mockSend.mockResolvedValue({ - Stacks: [{ StackStatus: 'UPDATE_COMPLETE' }], - }); + it.each(['UPDATE_COMPLETE', 'CREATE_FAILED', 'UPDATE_FAILED'])('returns canDeploy true for %s', async status => { + mockSend.mockResolvedValue({ Stacks: [{ StackStatus: status }] }); const result = await checkStackStatus('us-east-1', 'MyStack'); expect(result.canDeploy).toBe(true); @@ -63,7 +61,7 @@ describe('checkStackStatus', () => { }); it('returns canDeploy false for failed status', async () => { - const failedStatuses = ['CREATE_FAILED', 'ROLLBACK_FAILED', 'DELETE_FAILED', 'UPDATE_ROLLBACK_FAILED']; + const failedStatuses = ['ROLLBACK_FAILED', 'DELETE_FAILED', 'UPDATE_ROLLBACK_FAILED']; for (const status of failedStatuses) { mockSend.mockResolvedValue({ Stacks: [{ StackStatus: status }] }); diff --git a/src/cli/cloudformation/stack-status.ts b/src/cli/cloudformation/stack-status.ts index 307d04e6bf..4b70cfbfe8 100644 --- a/src/cli/cloudformation/stack-status.ts +++ b/src/cli/cloudformation/stack-status.ts @@ -20,10 +20,10 @@ const IN_PROGRESS_STATUSES = new Set([ /** * CloudFormation stack statuses that indicate the stack is in a failed state - * and may require manual intervention. + * and may require manual intervention. CREATE_FAILED and UPDATE_FAILED are absent because + * Express mode deploys disable rollback, and CloudFormation accepts updates from both. */ const FAILED_STATUSES = new Set([ - 'CREATE_FAILED', 'ROLLBACK_FAILED', 'DELETE_FAILED', 'UPDATE_ROLLBACK_FAILED', diff --git a/src/cli/commands/deploy/__tests__/deploy.test.ts b/src/cli/commands/deploy/__tests__/deploy.test.ts index 965e4e0da0..34f598de22 100644 --- a/src/cli/commands/deploy/__tests__/deploy.test.ts +++ b/src/cli/commands/deploy/__tests__/deploy.test.ts @@ -15,6 +15,7 @@ describe('deploy --help', () => { expect(result.stdout.includes('--verbose')).toBeTruthy(); expect(result.stdout.includes('--json')).toBeTruthy(); expect(result.stdout.includes('--dry-run')).toBeTruthy(); + expect(result.stdout.includes('--no-express')).toBeTruthy(); expect(result.stdout.includes('resource-level'), 'Should describe resource-level events').toBeTruthy(); }); }); @@ -195,18 +196,22 @@ describe('runDiff', () => { }); describe('runDeploy', () => { - it('passes stack selection pattern to toolkit wrapper deploy', async () => { - let captured: unknown; - const fakeWrapper = { - deploy: (opts?: unknown) => { - captured = opts; - }, - }; - - await runDeploy(fakeWrapper as any, 'AgentCore-myapp-prod'); - - expect(captured).toEqual({ - stacks: { strategy: StackSelectionStrategy.PATTERN_MUST_MATCH, patterns: ['AgentCore-myapp-prod'] }, - }); - }); + it.each([undefined, false])( + 'passes stack selection pattern and express=%s to toolkit wrapper deploy', + async express => { + let captured: unknown; + const fakeWrapper = { + deploy: (opts?: unknown) => { + captured = opts; + }, + }; + + await runDeploy(fakeWrapper as any, 'AgentCore-myapp-prod', express); + + expect(captured).toEqual({ + stacks: { strategy: StackSelectionStrategy.PATTERN_MUST_MATCH, patterns: ['AgentCore-myapp-prod'] }, + express, + }); + } + ); }); diff --git a/src/cli/commands/deploy/__tests__/utils.test.ts b/src/cli/commands/deploy/__tests__/utils.test.ts index 256eed9861..248de033aa 100644 --- a/src/cli/commands/deploy/__tests__/utils.test.ts +++ b/src/cli/commands/deploy/__tests__/utils.test.ts @@ -26,6 +26,7 @@ describe('computeDeployAttrs', () => { policy_engine_count: 2, policy_count: 3, deploy_mode: 'diff', + is_express: false, }); }); @@ -42,6 +43,7 @@ describe('computeDeployAttrs', () => { policy_engine_count: 0, policy_count: 0, deploy_mode: 'deploy', + is_express: true, }); }); @@ -53,4 +55,13 @@ describe('computeDeployAttrs', () => { expect(attrs.memory_count).toBe(0); expect(attrs.deploy_mode).toBe('dry-run'); }); + + it.each([ + { mode: 'deploy', spec: {}, express: undefined, expected: true }, + { mode: 'deploy', spec: {}, express: false, expected: false }, + { mode: 'deploy', spec: { onlineEvalConfigs: [{}] }, express: undefined, expected: false }, + { mode: 'dry-run', spec: {}, express: undefined, expected: false }, + ] as const)('records is_express=$expected for $mode', ({ mode, spec, express, expected }) => { + expect(computeDeployAttrs(spec as Partial, mode, express).is_express).toBe(expected); + }); }); diff --git a/src/cli/commands/deploy/actions.ts b/src/cli/commands/deploy/actions.ts index 1219bb02c2..c44c39d3c3 100644 --- a/src/cli/commands/deploy/actions.ts +++ b/src/cli/commands/deploy/actions.ts @@ -12,7 +12,7 @@ import type { AgentCoreMcpSpec, DeployedState } from '../../../schema'; import { applyTargetRegionToEnv } from '../../aws'; import { validateAwsCredentials } from '../../aws/account'; import { CdkToolkitWrapper, createSwitchableIoHost } from '../../cdk/toolkit-lib'; -import type { DeployMessage, SwitchableIoHost } from '../../cdk/toolkit-lib'; +import type { DeployMessage, DeployOutcome, SwitchableIoHost } from '../../cdk/toolkit-lib'; import { buildDeployedState, getStackOutputs, @@ -35,6 +35,7 @@ import { import { getErrorMessage } from '../../errors'; import { ExecLogger } from '../../logging'; import { + EXPRESS_FALLBACK_NOTICE, MANAGED_MEMORY_DEPLOY_NOTICE, SYNC_CDK_DEPENDENCIES_STEP, assertEnvFileExists, @@ -53,6 +54,7 @@ import { hasIdentityOAuthProviders, hasManagedMemoryHarness, performStackTeardown, + resolveExpressMode, setupApiKeyProviders, setupOAuth2Providers, setupTransactionSearch, @@ -83,6 +85,7 @@ export interface ValidatedDeployOptions { verbose?: boolean; plan?: boolean; diff?: boolean; + express?: boolean; onProgress?: (step: string, status: 'start' | 'success' | 'error' | 'warn') => void; onResourceEvent?: (message: string) => void; onDeployMessage?: (message: DeployMessage) => void; @@ -168,9 +171,14 @@ export async function runDiff( diffIoHost.setOnRawMessage(null); } -export async function runDeploy(toolkitWrapper: CdkToolkitWrapper, stackName: string): Promise { - await toolkitWrapper.deploy({ +export async function runDeploy( + toolkitWrapper: CdkToolkitWrapper, + stackName: string, + express?: boolean +): Promise { + return toolkitWrapper.deploy({ stacks: { strategy: StackSelectionStrategy.PATTERN_MUST_MATCH, patterns: [stackName] }, + express, }); } @@ -570,6 +578,12 @@ export async function handleDeploy(options: ValidatedDeployOptions): Promise 0; const deployStepName = hasGateways ? 'Deploying gateways...' : 'Deploy to AWS'; @@ -584,7 +598,7 @@ export async function handleDeploy(options: ValidatedDeployOptions): Promise 0; const hasInvokable = agentNames.length > 0 || hasHarnesses; const nextSteps = hasInvokable ? [...AGENT_NEXT_STEPS] : [...MEMORY_ONLY_NEXT_STEPS]; - const notes: string[] = [...autoPaymentNotices]; + const notes: string[] = [...autoPaymentNotices, ...(stabilizationWarning ? [stabilizationWarning] : [])]; const quickCreateAuthorizations = await getQuickCreateConnectorAuthorizations({ region: target.region, projectSpec: context.projectSpec, diff --git a/src/cli/commands/deploy/command.tsx b/src/cli/commands/deploy/command.tsx index b6c3fd5252..67cbe4dddc 100644 --- a/src/cli/commands/deploy/command.tsx +++ b/src/cli/commands/deploy/command.tsx @@ -7,7 +7,7 @@ import { renderTUI } from '../../tui'; import { requireProject, requireTTY } from '../../tui/guards'; import { handleDeploy } from './actions'; import type { DeployOptions, DeployResult } from './types'; -import { DEFAULT_DEPLOY_ATTRS, computeDeployAttrs } from './utils'; +import { computeDeployAttrs } from './utils'; import { validateDeployOptions } from './validate'; import type { Command } from '@commander-js/extra-typings'; import { Text, render } from 'ink'; @@ -15,10 +15,10 @@ import React from 'react'; const SPINNER_FRAMES = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏']; -function handleDeployTUI(options: { diffMode?: boolean } = {}): Promise { +function handleDeployTUI(options: { diffMode?: boolean; express?: boolean } = {}): Promise { requireProject(); return renderTUI({ - initialRoute: { name: 'deploy', diffMode: options.diffMode }, + initialRoute: { name: 'deploy', diffMode: options.diffMode, express: options.express }, enterAltScreen: false, actionOnBack: 'exit', isInteractive: false, @@ -40,8 +40,8 @@ async function handleDeployCLI(options: DeployOptions): Promise { const mode = options.diff ? 'diff' : options.plan ? 'dry-run' : 'deploy'; const attrs = await new ConfigIO() .readProjectSpec() - .then(spec => computeDeployAttrs(spec, mode)) - .catch(() => ({ ...DEFAULT_DEPLOY_ATTRS, mode }) as const); + .then(spec => computeDeployAttrs(spec, mode, options.express)) + .catch(() => computeDeployAttrs({}, mode, options.express)); const { deployResult } = await withCommandRunTelemetry('deploy', attrs, async recorder => { const result = await executeDeploy(options).catch( @@ -142,6 +142,7 @@ async function executeDeploy(options: DeployOptions): Promise { verbose: options.verbose ?? options.diff, plan: options.plan, diff: options.diff, + express: options.express, onProgress, onResourceEvent, onNotice, @@ -220,6 +221,10 @@ export const registerDeploy = (program: Command) => { .option('--json', 'Output as JSON [non-interactive]') .option('--dry-run', 'Preview deployment without deploying [non-interactive]') .option('--diff', 'Show CDK diff without deploying [non-interactive]') + .option( + '--no-express', + 'Deploy without CloudFormation Express mode: waits for stabilization, rolls back on failure' + ) .action( async (cliOptions: { target?: string; @@ -228,6 +233,7 @@ export const registerDeploy = (program: Command) => { json?: boolean; dryRun?: boolean; diff?: boolean; + express?: boolean; }) => { try { requireProject(); @@ -247,7 +253,7 @@ export const registerDeploy = (program: Command) => { await handleDeployTUI({ diffMode: true }); } else { requireTTY(); - await handleDeployTUI(); + await handleDeployTUI({ express: cliOptions.express }); } } catch (error) { if (cliOptions.json) { diff --git a/src/cli/commands/deploy/types.ts b/src/cli/commands/deploy/types.ts index d0df81a5ee..9d8776ed88 100644 --- a/src/cli/commands/deploy/types.ts +++ b/src/cli/commands/deploy/types.ts @@ -9,6 +9,7 @@ export interface DeployOptions { json?: boolean; plan?: boolean; diff?: boolean; + express?: boolean; } export type DeployResult = Result<{ diff --git a/src/cli/commands/deploy/utils.ts b/src/cli/commands/deploy/utils.ts index d6362e114d..6d6c24a159 100644 --- a/src/cli/commands/deploy/utils.ts +++ b/src/cli/commands/deploy/utils.ts @@ -1,4 +1,5 @@ import type { AgentCoreProjectSpec } from '../../../schema'; +import { resolveExpressMode } from '../../operations/deploy/express-mode'; import type { DeployMode } from '../../telemetry/schemas/common-shapes'; export const DEFAULT_DEPLOY_ATTRS = { @@ -13,9 +14,10 @@ export const DEFAULT_DEPLOY_ATTRS = { policy_engine_count: 0, policy_count: 0, deploy_mode: 'deploy' as DeployMode, + is_express: true, }; -export function computeDeployAttrs(projectSpec: Partial, mode: DeployMode) { +export function computeDeployAttrs(projectSpec: Partial, mode: DeployMode, express = true) { const gateways = projectSpec.agentCoreGateways ?? []; const policyEngines = projectSpec.policyEngines ?? []; return { @@ -30,5 +32,6 @@ export function computeDeployAttrs(projectSpec: Partial, m policy_engine_count: policyEngines.length, policy_count: policyEngines.reduce((sum, pe) => sum + (pe.policies ?? []).length, 0), deploy_mode: mode, + is_express: mode === 'deploy' && resolveExpressMode(projectSpec, express), }; } diff --git a/src/cli/operations/deploy/__tests__/express-mode.test.ts b/src/cli/operations/deploy/__tests__/express-mode.test.ts new file mode 100644 index 0000000000..ad3aa53e4f --- /dev/null +++ b/src/cli/operations/deploy/__tests__/express-mode.test.ts @@ -0,0 +1,16 @@ +import type { AgentCoreProjectSpec } from '../../../../schema'; +import { resolveExpressMode } from '../express-mode.js'; +import { describe, expect, it } from 'vitest'; + +describe('resolveExpressMode', () => { + const withEval = { onlineEvalConfigs: [{ name: 'QualityEval' }] } as unknown as Partial; + + it.each([ + { spec: {}, express: undefined, expected: true }, + { spec: {}, express: false, expected: false }, + { spec: withEval, express: undefined, expected: false }, + { spec: withEval, express: true, expected: false }, + ])('returns $expected for express=$express', ({ spec, express, expected }) => { + expect(resolveExpressMode(spec, express)).toBe(expected); + }); +}); diff --git a/src/cli/operations/deploy/express-mode.ts b/src/cli/operations/deploy/express-mode.ts new file mode 100644 index 0000000000..6ea9bcd276 --- /dev/null +++ b/src/cli/operations/deploy/express-mode.ts @@ -0,0 +1,14 @@ +import type { AgentCoreProjectSpec } from '../../../schema'; + +export const EXPRESS_FALLBACK_NOTICE = + 'Deploying without CloudFormation Express mode: online eval configs need the agent runtime log group, ' + + 'which only exists after the runtime finishes starting.'; + +/** + * Express mode does not wait for resources to stabilize, so an online eval config can be created + * before the runtime has created the log group it reads from. Projects with online eval configs + * therefore always deploy in standard mode. + */ +export function resolveExpressMode(projectSpec: Partial, express = true): boolean { + return express && (projectSpec.onlineEvalConfigs ?? []).length === 0; +} diff --git a/src/cli/operations/deploy/index.ts b/src/cli/operations/deploy/index.ts index cc824a5295..adb563de21 100644 --- a/src/cli/operations/deploy/index.ts +++ b/src/cli/operations/deploy/index.ts @@ -84,6 +84,8 @@ export { type EnsureManagedDependenciesOptions, } from './dependency-sync'; +export { EXPRESS_FALLBACK_NOTICE, resolveExpressMode } from './express-mode'; + // Managed-memory heads-up (shared by the CLI command + TUI deploy flow + add harness) export { MANAGED_MEMORY_DEPLOY_NOTICE, diff --git a/src/cli/telemetry/schemas/__tests__/command-run.test.ts b/src/cli/telemetry/schemas/__tests__/command-run.test.ts index 597160cd53..f0d73c5d23 100644 --- a/src/cli/telemetry/schemas/__tests__/command-run.test.ts +++ b/src/cli/telemetry/schemas/__tests__/command-run.test.ts @@ -50,6 +50,7 @@ describe('COMMAND_SCHEMAS', () => { policy_engine_count: 0, policy_count: 0, deploy_mode: 'diff', + is_express: true, }; expect(COMMAND_SCHEMAS.deploy.parse(attrs)).toEqual(attrs); }); @@ -68,6 +69,7 @@ describe('COMMAND_SCHEMAS', () => { policy_engine_count: 0, policy_count: 0, deploy_mode: 'deploy', + is_express: false, }) ).toThrow(); }); @@ -86,6 +88,7 @@ describe('COMMAND_SCHEMAS', () => { policy_engine_count: 0, policy_count: 0, deploy_mode: 'deploy', + is_express: false, }) ).toThrow(); }); diff --git a/src/cli/telemetry/schemas/command-run.ts b/src/cli/telemetry/schemas/command-run.ts index bca7a0e9aa..53d7ff96cf 100644 --- a/src/cli/telemetry/schemas/command-run.ts +++ b/src/cli/telemetry/schemas/command-run.ts @@ -146,6 +146,7 @@ const DeployAttrs = safeSchema({ policy_engine_count: Count, policy_count: Count, deploy_mode: DeployModeSchema, + is_express: z.boolean(), dep_sync_outcome: DepSyncOutcome.optional(), dep_sync_changed_count: Count.optional(), dep_sync_migrated: z.boolean().optional(), diff --git a/src/cli/telemetry/schemas/common-shapes.ts b/src/cli/telemetry/schemas/common-shapes.ts index 5d4831a98f..7aa855220b 100644 --- a/src/cli/telemetry/schemas/common-shapes.ts +++ b/src/cli/telemetry/schemas/common-shapes.ts @@ -181,6 +181,7 @@ export const ATTRIBUTES = { authorizer_type: AuthorizerType, build_type: BuildType, is_dry_run: z.boolean(), + is_express: z.boolean(), credential_count: Count, credential_type: CredentialType, deploy_mode: DeployModeSchema, diff --git a/src/cli/tui/App.tsx b/src/cli/tui/App.tsx index 81795d16d5..47032c959b 100644 --- a/src/cli/tui/App.tsx +++ b/src/cli/tui/App.tsx @@ -38,7 +38,7 @@ import React, { useState } from 'react'; type Route = | { name: 'home' } | { name: 'help'; initialQuery?: string } - | { name: 'deploy'; diffMode?: boolean } + | { name: 'deploy'; diffMode?: boolean; express?: boolean } | { name: 'invoke'; sessionId?: string; @@ -234,6 +234,7 @@ function AppContent({ setRoute({ name: command } as Route)} /> diff --git a/src/cli/tui/screens/deploy/DeployScreen.tsx b/src/cli/tui/screens/deploy/DeployScreen.tsx index e3c26d58ec..172eea62a7 100644 --- a/src/cli/tui/screens/deploy/DeployScreen.tsx +++ b/src/cli/tui/screens/deploy/DeployScreen.tsx @@ -33,6 +33,8 @@ interface DeployScreenProps { preSynthesized?: PreSynthesized; /** Run CDK diff instead of deploying */ diffMode?: boolean; + /** Deploy with CloudFormation Express mode */ + express?: boolean; } /** Next steps shown after successful deployment */ @@ -56,6 +58,7 @@ export function DeployScreen({ onNavigate, preSynthesized, diffMode, + express, }: DeployScreenProps) { const { stdout } = useStdout(); const awsConfig = useAwsTargetConfig(); @@ -106,7 +109,7 @@ export function DeployScreen({ useEnvLocalCredentials, useManualCredentials, skipCredentials, - } = useDeployFlow({ preSynthesized, isInteractive, diffMode, selectedTargets }); + } = useDeployFlow({ preSynthesized, isInteractive, diffMode, express, selectedTargets }); const allSuccess = !hasError && isComplete; const skipPreflight = !!preSynthesized; diff --git a/src/cli/tui/screens/deploy/__tests__/useDeployFlow.targets.test.tsx b/src/cli/tui/screens/deploy/__tests__/useDeployFlow.targets.test.tsx index f9bc8bd1b8..165cc96273 100644 --- a/src/cli/tui/screens/deploy/__tests__/useDeployFlow.targets.test.tsx +++ b/src/cli/tui/screens/deploy/__tests__/useDeployFlow.targets.test.tsx @@ -10,6 +10,7 @@ * is scoped to ONLY the selected target's stack name via PATTERN_MUST_MATCH. */ import { toStackName } from '../../../../commands/import/import-utils'; +import { EXPRESS_FALLBACK_NOTICE } from '../../../../operations/deploy/express-mode'; import { useDeployFlow } from '../useDeployFlow'; import { StackSelectionStrategy } from '@aws-cdk/toolkit-lib'; import { render } from 'ink-testing-library'; @@ -18,7 +19,7 @@ import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; // ---- Module mocks ----------------------------------------------------------- -const deploySpy = vi.fn().mockResolvedValue(undefined); +const deploySpy = vi.fn().mockResolvedValue({}); const diffSpy = vi.fn().mockResolvedValue(undefined); const disposeSpy = vi.fn().mockResolvedValue(undefined); @@ -94,13 +95,14 @@ function makePreflight(opts: { projectName?: string; isFirstDeploy?: boolean; isTeardownDeploy?: boolean; + onlineEvalConfigs?: { name: string }[]; }) { const stackNames = opts.awsTargets.map(t => toStackName(opts.projectName ?? PROJECT_NAME, t.name)); return { phase: 'complete', steps: [], context: { - projectSpec: { name: opts.projectName ?? PROJECT_NAME, runtimes: [] }, + projectSpec: { name: opts.projectName ?? PROJECT_NAME, runtimes: [], onlineEvalConfigs: opts.onlineEvalConfigs }, awsTargets: opts.awsTargets, isTeardownDeploy: opts.isTeardownDeploy ?? false, // First-deploy skips the pre-deploy diff branch; flip it off to exercise diff scoping. @@ -130,8 +132,16 @@ function makePreflight(opts: { // Harness component: mounts the hook so its effects fire under ink-testing-library. onState (when // provided) captures the latest hook state each render so tests can assert user-facing output // (deployOutput / deployNotes) after the flow settles. -function Harness({ selectedTargets, onState }: { selectedTargets?: any[]; onState?: (state: any) => void }) { - const state = useDeployFlow({ isInteractive: true, selectedTargets }); +function Harness({ + selectedTargets, + express, + onState, +}: { + selectedTargets?: any[]; + express?: boolean; + onState?: (state: any) => void; +}) { + const state = useDeployFlow({ isInteractive: true, selectedTargets, express }); onState?.(state); return null as unknown as React.ReactElement; } @@ -301,6 +311,40 @@ describe('useDeployFlow target scoping (issue #1267)', () => { expect(arg.stacks).toBeUndefined(); }); + it.each([ + { express: undefined, onlineEvalConfigs: undefined, expected: true }, + { express: false, onlineEvalConfigs: undefined, expected: false }, + { express: undefined, onlineEvalConfigs: [{ name: 'QualityEval' }], expected: false }, + ])( + 'deploys with express=$expected for express=$express and onlineEvalConfigs=$onlineEvalConfigs', + async ({ express, onlineEvalConfigs, expected }) => { + preflightState = makePreflight({ awsTargets: [TARGET_A], onlineEvalConfigs }); + + let latest: any; + const { unmount } = render( + (latest = s)} /> + ); + await flush(); + unmount(); + + expect(deploySpy).toHaveBeenCalledTimes(1); + expect(deploySpy.mock.calls[0]![0].express).toBe(expected); + expect(latest.deployNotes.includes(EXPRESS_FALLBACK_NOTICE)).toBe(express === undefined && !expected); + } + ); + + it('shows the Express mode stabilization warning as a deploy note', async () => { + preflightState = makePreflight({ awsTargets: [TARGET_A] }); + deploySpy.mockResolvedValueOnce({ stabilizationWarning: 'Runtime ApplicationAgentRuntime is still stabilizing' }); + + let latest: any; + const { unmount } = render( (latest = s)} />); + await flush(); + unmount(); + + expect(latest.deployNotes).toContain('Runtime ApplicationAgentRuntime is still stabilizing'); + }); + it('empty picker selection fails safe (scoped to nothing), never ALL_STACKS (#1267)', async () => { // A picker that yields an empty selection must NOT resolve to undefined (→ toolkit ALL_STACKS). // It scopes to an empty PATTERN_MUST_MATCH set, which makes toolkit-lib throw NoStacksMatched diff --git a/src/cli/tui/screens/deploy/useDeployFlow.ts b/src/cli/tui/screens/deploy/useDeployFlow.ts index 26c0ed00f4..aaef26ec79 100644 --- a/src/cli/tui/screens/deploy/useDeployFlow.ts +++ b/src/cli/tui/screens/deploy/useDeployFlow.ts @@ -26,12 +26,14 @@ import { toStackName } from '../../../commands/import/import-utils'; import { getErrorMessage, isChangesetInProgressError, isExpiredTokenError } from '../../../errors'; import { ExecLogger } from '../../../logging'; import { + EXPRESS_FALLBACK_NOTICE, MANAGED_MEMORY_DEPLOY_NOTICE, cleanupPaymentCredentialProviders, formatQuickCreateConnectorAuthorization, getQuickCreateConnectorAuthorizations, hasManagedMemoryHarness, performStackTeardown, + resolveExpressMode, setupTransactionSearch, toDepSyncAttrs, } from '../../../operations/deploy'; @@ -85,6 +87,8 @@ interface DeployFlowOptions { isInteractive?: boolean; /** Run CDK diff instead of deploy */ diffMode?: boolean; + /** Deploy with CloudFormation Express mode */ + express?: boolean; /** * Targets the user chose in the multi-select picker. The vended CDK app synthesizes one stack * per configured target, so without scoping the deploy runs against ALL_STACKS (every target). @@ -157,7 +161,7 @@ function withDepSyncAttrs(attrs: T, sync: DependencySyncResult } export function useDeployFlow(options: DeployFlowOptions = {}): DeployFlowState { - const { preSynthesized, isInteractive = false, diffMode = false, selectedTargets } = options; + const { preSynthesized, isInteractive = false, diffMode = false, express, selectedTargets } = options; const skipPreflight = !!preSynthesized; // Create logger once for the entire deploy flow @@ -778,7 +782,7 @@ export function useDeployFlow(options: DeployFlowOptions = {}): DeployFlowState if (preflight.phase === 'error') { const error = preflight.lastError ?? new Error('Preflight failed'); const attrs = withDepSyncAttrs( - context ? computeDeployAttrs(context.projectSpec, 'deploy') : { ...DEFAULT_DEPLOY_ATTRS }, + computeDeployAttrs(context?.projectSpec ?? {}, 'deploy', express), preflight.dependencySyncResult ); withCommandRunTelemetry('deploy', attrs, () => ({ success: false as const, error })).catch(() => { @@ -791,7 +795,7 @@ export function useDeployFlow(options: DeployFlowOptions = {}): DeployFlowState if (!cdkToolkitWrapper) return; const attrs = withDepSyncAttrs( - context ? computeDeployAttrs(context.projectSpec, 'deploy') : { ...DEFAULT_DEPLOY_ATTRS }, + computeDeployAttrs(context?.projectSpec ?? {}, 'deploy', express), preflight.dependencySyncResult ); @@ -843,6 +847,12 @@ export function useDeployFlow(options: DeployFlowOptions = {}): DeployFlowState } } + const useExpress = resolveExpressMode(context?.projectSpec ?? {}, express); + if ((express ?? true) && !useExpress) { + logger.log(EXPRESS_FALLBACK_NOTICE); + setDeployNotes(prev => [...prev, EXPRESS_FALLBACK_NOTICE]); + } + setPublishAssetsStep(prev => ({ ...prev, status: 'running' })); setShouldStartDeploy(false); setDeployMessages([]); // Clear previous messages @@ -880,7 +890,11 @@ export function useDeployFlow(options: DeployFlowOptions = {}): DeployFlowState // Output goes to stdout via the switchable ioHost. // deployStacks restricts the deploy to the picker's selected targets; undefined (single // target or plan path) lets the assembly's lone stack deploy as before. - await cdkToolkitWrapper.deploy({ stacks: deployStacks }); + const { stabilizationWarning } = await cdkToolkitWrapper.deploy({ stacks: deployStacks, express: useExpress }); + if (stabilizationWarning) { + logger.log(stabilizationWarning, 'warn'); + setDeployNotes(prev => [...prev, stabilizationWarning]); + } // CDK deploy itself is done. Mark "Deploy to AWS" success and let post-deploy // phases (persist, hydrate KBs, auto-ingest, dataset sync, online evals, @@ -1068,6 +1082,7 @@ export function useDeployFlow(options: DeployFlowOptions = {}): DeployFlowState activeTarget, diffMode, deployStacks, + express, ]); // Start diff when preflight completes (diff mode only)