diff --git a/model/aws/bcmpricingcalculator/LICENSE.txt b/model/aws/bcmpricingcalculator/LICENSE.txt new file mode 100644 index 000000000..6720f5e28 --- /dev/null +++ b/model/aws/bcmpricingcalculator/LICENSE.txt @@ -0,0 +1,14 @@ +Copyright (C) 2026 System Initiative, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . diff --git a/model/aws/bcmpricingcalculator/README.md b/model/aws/bcmpricingcalculator/README.md new file mode 100644 index 000000000..21e49b7bf --- /dev/null +++ b/model/aws/bcmpricingcalculator/README.md @@ -0,0 +1,66 @@ +# @swamp/aws/bcmpricingcalculator + +Auto-generated [swamp](https://github.com/systeminit/swamp) extension models for +AWS BCMPRICINGCALCULATOR resources. + +Each model represents a single AWS resource (e.g., a VPC, an S3 bucket, an IAM +role). Models have **domain properties** that you configure (the desired state) +and **resource properties** that reflect the live state in AWS. Available +methods: + +- **create** — provision the resource in AWS using the configured properties +- **get** — fetch the current state of a specific resource by identifier +- **update** — apply property changes to an existing resource +- **delete** — remove the resource from AWS +- **sync** — refresh all resource properties from AWS + +Use `swamp model type describe @swamp/aws/bcmpricingcalculator/bill_scenario` to +see the full list of configurable properties and available methods for this +model. + +## Authentication + +These models use the AWS SDK v3 default credential chain. Credentials are +resolved in the following order: + +1. **Environment variables** — `AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY` + + optional `AWS_SESSION_TOKEN` +2. **SSO credentials** — `aws sso login` +3. **Shared credentials file** — `~/.aws/credentials` +4. **Shared config file** — `~/.aws/config` (profiles, `credential_process`, + SSO) +5. **ECS container credentials** — task IAM role +6. **EC2 instance metadata** — instance profile + +### Region + +The `AWS_REGION` environment variable controls which region resources are +created and managed in. Defaults to `us-east-1` if not set. + +### Setup + +```bash +export AWS_REGION=us-east-1 +export AWS_ACCESS_KEY_ID=AKIA... +export AWS_SECRET_ACCESS_KEY=wJal... +``` + +## Usage + +```bash +# Create a new bill_scenario model +swamp model create @swamp/aws/bcmpricingcalculator/bill_scenario my-bill_scenario + +# Edit the model to configure its properties +swamp model edit my-bill_scenario + +# Create the resource in AWS +swamp model method run my-bill_scenario create + +# Sync current state from AWS +swamp model method run my-bill_scenario sync +``` + +## License + +AGPLv3 — see [LICENSE.txt](./LICENSE.txt). diff --git a/model/aws/bcmpricingcalculator/deno.json b/model/aws/bcmpricingcalculator/deno.json new file mode 100644 index 000000000..15892302f --- /dev/null +++ b/model/aws/bcmpricingcalculator/deno.json @@ -0,0 +1,7 @@ +{ + "imports": { + "zod": "npm:zod@4.3.6", + "@aws-sdk/client-cloudcontrol": "npm:@aws-sdk/client-cloudcontrol@3.1021.0", + "fast-json-patch": "npm:fast-json-patch@3.1.1" + } +} diff --git a/model/aws/bcmpricingcalculator/deno.lock b/model/aws/bcmpricingcalculator/deno.lock new file mode 100644 index 000000000..ded86fbb9 --- /dev/null +++ b/model/aws/bcmpricingcalculator/deno.lock @@ -0,0 +1,777 @@ +{ + "version": "5", + "specifiers": { + "npm:@aws-sdk/client-cloudcontrol@3.1021.0": "3.1021.0", + "npm:fast-json-patch@3.1.1": "3.1.1", + "npm:zod@4.3.6": "4.3.6" + }, + "npm": { + "@aws-crypto/sha256-browser@5.2.0": { + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "dependencies": [ + "@aws-crypto/sha256-js", + "@aws-crypto/supports-web-crypto", + "@aws-crypto/util", + "@aws-sdk/types", + "@aws-sdk/util-locate-window", + "@smithy/util-utf8@2.3.0", + "tslib" + ] + }, + "@aws-crypto/sha256-js@5.2.0": { + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "dependencies": [ + "@aws-crypto/util", + "@aws-sdk/types", + "tslib" + ] + }, + "@aws-crypto/supports-web-crypto@5.2.0": { + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "dependencies": [ + "tslib" + ] + }, + "@aws-crypto/util@5.2.0": { + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dependencies": [ + "@aws-sdk/types", + "@smithy/util-utf8@2.3.0", + "tslib" + ] + }, + "@aws-sdk/client-cloudcontrol@3.1021.0": { + "integrity": "sha512-VbrIC3iT4OveHdkjYdMdwGk60YNOmN0OsL1QEuEjOwUmjq1aYRzgtjNb9fGR9a8CWhGA7yjqWDaUeNJ+wUGzMw==", + "dependencies": [ + "@aws-crypto/sha256-browser", + "@aws-crypto/sha256-js", + "@aws-sdk/core", + "@aws-sdk/credential-provider-node", + "@aws-sdk/middleware-host-header", + "@aws-sdk/middleware-logger", + "@aws-sdk/middleware-recursion-detection", + "@aws-sdk/middleware-user-agent", + "@aws-sdk/region-config-resolver", + "@aws-sdk/types", + "@aws-sdk/util-endpoints", + "@aws-sdk/util-user-agent-browser", + "@aws-sdk/util-user-agent-node", + "@smithy/config-resolver", + "@smithy/core", + "@smithy/fetch-http-handler", + "@smithy/hash-node", + "@smithy/invalid-dependency", + "@smithy/middleware-content-length", + "@smithy/middleware-endpoint", + "@smithy/middleware-retry", + "@smithy/middleware-serde", + "@smithy/middleware-stack", + "@smithy/node-config-provider", + "@smithy/node-http-handler", + "@smithy/protocol-http", + "@smithy/smithy-client", + "@smithy/types", + "@smithy/url-parser", + "@smithy/util-base64", + "@smithy/util-body-length-browser", + "@smithy/util-body-length-node", + "@smithy/util-defaults-mode-browser", + "@smithy/util-defaults-mode-node", + "@smithy/util-endpoints", + "@smithy/util-middleware", + "@smithy/util-retry", + "@smithy/util-utf8@4.2.2", + "@smithy/util-waiter", + "tslib" + ] + }, + "@aws-sdk/core@3.973.27": { + "integrity": "sha512-CUZ5m8hwMCH6OYI4Li/WgMfIEx10Q2PLI9Y3XOUTPGZJ53aZ0007jCv+X/ywsaERyKPdw5MRZWk877roQksQ4A==", + "dependencies": [ + "@aws-sdk/types", + "@aws-sdk/xml-builder", + "@smithy/core", + "@smithy/node-config-provider", + "@smithy/property-provider", + "@smithy/protocol-http", + "@smithy/signature-v4", + "@smithy/smithy-client", + "@smithy/types", + "@smithy/util-base64", + "@smithy/util-middleware", + "@smithy/util-utf8@4.2.2", + "tslib" + ] + }, + "@aws-sdk/credential-provider-env@3.972.25": { + "integrity": "sha512-6QfI0wv4jpG5CrdO/AO0JfZ2ux+tKwJPrUwmvxXF50vI5KIypKVGNF6b4vlkYEnKumDTI1NX2zUBi8JoU5QU3A==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/types", + "@smithy/property-provider", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/credential-provider-http@3.972.27": { + "integrity": "sha512-3V3Usj9Gs93h865DqN4M2NWJhC5kXU9BvZskfN3+69omuYlE3TZxOEcVQtBGLOloJB7BVfJKXVLqeNhOzHqSlQ==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/types", + "@smithy/fetch-http-handler", + "@smithy/node-http-handler", + "@smithy/property-provider", + "@smithy/protocol-http", + "@smithy/smithy-client", + "@smithy/types", + "@smithy/util-stream", + "tslib" + ] + }, + "@aws-sdk/credential-provider-ini@3.972.29": { + "integrity": "sha512-SiBuAnXecCbT/OpAf3vqyI/AVE3mTaYr9ShXLybxZiPLBiPCCOIWSGAtYYGQWMRvobBTiqOewaB+wcgMMZI2Aw==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/credential-provider-env", + "@aws-sdk/credential-provider-http", + "@aws-sdk/credential-provider-login", + "@aws-sdk/credential-provider-process", + "@aws-sdk/credential-provider-sso", + "@aws-sdk/credential-provider-web-identity", + "@aws-sdk/nested-clients", + "@aws-sdk/types", + "@smithy/credential-provider-imds", + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/credential-provider-login@3.972.29": { + "integrity": "sha512-OGOslTbOlxXexKMqhxCEbBQbUIfuhGxU5UXw3Fm56ypXHvrXH4aTt/xb5Y884LOoteP1QST1lVZzHfcTnWhiPQ==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/nested-clients", + "@aws-sdk/types", + "@smithy/property-provider", + "@smithy/protocol-http", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/credential-provider-node@3.972.30": { + "integrity": "sha512-FMnAnWxc8PG+ZrZ2OBKzY4luCUJhe9CG0B9YwYr4pzrYGLXBS2rl+UoUvjGbAwiptxRL6hyA3lFn03Bv1TLqTw==", + "dependencies": [ + "@aws-sdk/credential-provider-env", + "@aws-sdk/credential-provider-http", + "@aws-sdk/credential-provider-ini", + "@aws-sdk/credential-provider-process", + "@aws-sdk/credential-provider-sso", + "@aws-sdk/credential-provider-web-identity", + "@aws-sdk/types", + "@smithy/credential-provider-imds", + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/credential-provider-process@3.972.25": { + "integrity": "sha512-HR7ynNRdNhNsdVCOCegy1HsfsRzozCOPtD3RzzT1JouuaHobWyRfJzCBue/3jP7gECHt+kQyZUvwg/cYLWurNQ==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/types", + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/credential-provider-sso@3.972.29": { + "integrity": "sha512-HWv4SEq3jZDYPlwryZVef97+U8CxxRos5mK8sgGO1dQaFZpV5giZLzqGE5hkDmh2csYcBO2uf5XHjPTpZcJlig==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/nested-clients", + "@aws-sdk/token-providers", + "@aws-sdk/types", + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/credential-provider-web-identity@3.972.29": { + "integrity": "sha512-PdMBza1WEKEUPFEmMGCfnU2RYCz9MskU2e8JxjyUOsMKku7j9YaDKvbDi2dzC0ihFoM6ods2SbhfAAro+Gwlew==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/nested-clients", + "@aws-sdk/types", + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/middleware-host-header@3.972.9": { + "integrity": "sha512-je5vRdNw4SkuTnmRbFZLdye4sQ0faLt8kwka5wnnSU30q1mHO4X+idGEJOOE+Tn1ME7Oryn05xxkDvIb3UaLaQ==", + "dependencies": [ + "@aws-sdk/types", + "@smithy/protocol-http", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/middleware-logger@3.972.9": { + "integrity": "sha512-HsVgDrruhqI28RkaXALm8grJ7Agc1wF6Et0xh6pom8NdO2VdO/SD9U/tPwUjewwK/pVoka+EShBxyCvgsPCtog==", + "dependencies": [ + "@aws-sdk/types", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/middleware-recursion-detection@3.972.10": { + "integrity": "sha512-RVQQbq5orQ/GHUnXvqEOj2HHPBJm+mM+ySwZKS5UaLBwra5ugRtiH09PLUoOZRl7a1YzaOzXSuGbn9iD5j60WQ==", + "dependencies": [ + "@aws-sdk/types", + "@aws/lambda-invoke-store", + "@smithy/protocol-http", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/middleware-user-agent@3.972.29": { + "integrity": "sha512-f/sIRzuTfEjg6NsbMYvye2VsmnQoNgntntleQyx5uGacUYzszbfIlO3GcI6G6daWUmTm0IDZc11qMHWwF0o0mQ==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/types", + "@aws-sdk/util-endpoints", + "@smithy/core", + "@smithy/protocol-http", + "@smithy/types", + "@smithy/util-retry", + "tslib" + ] + }, + "@aws-sdk/nested-clients@3.996.19": { + "integrity": "sha512-uFkmCDXvmQYLanlYdOFS0+MQWkrj9wPMt/ZCc/0J0fjPim6F5jBVBmEomvGY/j77ILW6GTPwN22Jc174Mhkw6Q==", + "dependencies": [ + "@aws-crypto/sha256-browser", + "@aws-crypto/sha256-js", + "@aws-sdk/core", + "@aws-sdk/middleware-host-header", + "@aws-sdk/middleware-logger", + "@aws-sdk/middleware-recursion-detection", + "@aws-sdk/middleware-user-agent", + "@aws-sdk/region-config-resolver", + "@aws-sdk/types", + "@aws-sdk/util-endpoints", + "@aws-sdk/util-user-agent-browser", + "@aws-sdk/util-user-agent-node", + "@smithy/config-resolver", + "@smithy/core", + "@smithy/fetch-http-handler", + "@smithy/hash-node", + "@smithy/invalid-dependency", + "@smithy/middleware-content-length", + "@smithy/middleware-endpoint", + "@smithy/middleware-retry", + "@smithy/middleware-serde", + "@smithy/middleware-stack", + "@smithy/node-config-provider", + "@smithy/node-http-handler", + "@smithy/protocol-http", + "@smithy/smithy-client", + "@smithy/types", + "@smithy/url-parser", + "@smithy/util-base64", + "@smithy/util-body-length-browser", + "@smithy/util-body-length-node", + "@smithy/util-defaults-mode-browser", + "@smithy/util-defaults-mode-node", + "@smithy/util-endpoints", + "@smithy/util-middleware", + "@smithy/util-retry", + "@smithy/util-utf8@4.2.2", + "tslib" + ] + }, + "@aws-sdk/region-config-resolver@3.972.11": { + "integrity": "sha512-6Q8B1dcx6BBqUTY1Mc/eROKA0FImEEY5VPSd6AGPEUf0ErjExz4snVqa9kNJSoVDV1rKaNf3qrWojgcKW+SdDg==", + "dependencies": [ + "@aws-sdk/types", + "@smithy/config-resolver", + "@smithy/node-config-provider", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/token-providers@3.1026.0": { + "integrity": "sha512-Ieq/HiRrbEtrYP387Nes0XlR7H1pJiJOZKv+QyQzMYpvTiDs0VKy2ZB3E2Zf+aFovWmeE7lRE4lXyF7dYM6GgA==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/nested-clients", + "@aws-sdk/types", + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/types@3.973.7": { + "integrity": "sha512-reXRwoJ6CfChoqAsBszUYajAF8Z2LRE+CRcKocvFSMpIiLOtYU3aJ9trmn6VVPAzbbY5LXF+FfmUslbXk1SYFg==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/util-endpoints@3.996.6": { + "integrity": "sha512-2nUQ+2ih7CShuKHpGSIYvvAIOHy52dOZguYG36zptBukhw6iFwcvGfG0tes0oZFWQqEWvgZe9HLWaNlvXGdOrg==", + "dependencies": [ + "@aws-sdk/types", + "@smithy/types", + "@smithy/url-parser", + "@smithy/util-endpoints", + "tslib" + ] + }, + "@aws-sdk/util-locate-window@3.965.5": { + "integrity": "sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==", + "dependencies": [ + "tslib" + ] + }, + "@aws-sdk/util-user-agent-browser@3.972.9": { + "integrity": "sha512-sn/LMzTbGjYqCCF24390WxPd6hkpoSptiUn5DzVp4cD71yqw+yGEGm1YCxyEoPXyc8qciM8UzLJcZBFslxo5Uw==", + "dependencies": [ + "@aws-sdk/types", + "@smithy/types", + "bowser", + "tslib" + ] + }, + "@aws-sdk/util-user-agent-node@3.973.15": { + "integrity": "sha512-fYn3s9PtKdgQkczGZCFMgkNEe8aq1JCVbnRqjqN9RSVW43xn2RV9xdcZ3z01a48Jpkuh/xCmBKJxdLOo4Ozg7w==", + "dependencies": [ + "@aws-sdk/middleware-user-agent", + "@aws-sdk/types", + "@smithy/node-config-provider", + "@smithy/types", + "@smithy/util-config-provider", + "tslib" + ] + }, + "@aws-sdk/xml-builder@3.972.17": { + "integrity": "sha512-Ra7hjqAZf1OXRRMueB13qex7mFJRDK/pgCvdSFemXBT8KCGnQDPoKzHY1SjN+TjJVmnpSF14W5tJ1vDamFu+Gg==", + "dependencies": [ + "@smithy/types", + "fast-xml-parser", + "tslib" + ] + }, + "@aws/lambda-invoke-store@0.2.4": { + "integrity": "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==" + }, + "@smithy/config-resolver@4.4.14": { + "integrity": "sha512-N55f8mPEccpzKetUagdvmAy8oohf0J5cuj9jLI1TaSceRlq0pJsIZepY3kmAXAhyxqXPV6hDerDQhqQPKWgAoQ==", + "dependencies": [ + "@smithy/node-config-provider", + "@smithy/types", + "@smithy/util-config-provider", + "@smithy/util-endpoints", + "@smithy/util-middleware", + "tslib" + ] + }, + "@smithy/core@3.23.14": { + "integrity": "sha512-vJ0IhpZxZAkFYOegMKSrxw7ujhhT2pass/1UEcZ4kfl5srTAqtPU5I7MdYQoreVas3204ykCiNhY1o7Xlz6Yyg==", + "dependencies": [ + "@smithy/protocol-http", + "@smithy/types", + "@smithy/url-parser", + "@smithy/util-base64", + "@smithy/util-body-length-browser", + "@smithy/util-middleware", + "@smithy/util-stream", + "@smithy/util-utf8@4.2.2", + "@smithy/uuid", + "tslib" + ] + }, + "@smithy/credential-provider-imds@4.2.13": { + "integrity": "sha512-wboCPijzf6RJKLOvnjDAiBxGSmSnGXj35o5ZAWKDaHa/cvQ5U3ZJ13D4tMCE8JG4dxVAZFy/P0x/V9CwwdfULQ==", + "dependencies": [ + "@smithy/node-config-provider", + "@smithy/property-provider", + "@smithy/types", + "@smithy/url-parser", + "tslib" + ] + }, + "@smithy/fetch-http-handler@5.3.16": { + "integrity": "sha512-nYDRUIvNd4mFmuXraRWt6w5UsZTNqtj4hXJA/iiOD4tuseIdLP9Lq38teH/SZTcIFCa2f+27o7hYpIsWktJKEQ==", + "dependencies": [ + "@smithy/protocol-http", + "@smithy/querystring-builder", + "@smithy/types", + "@smithy/util-base64", + "tslib" + ] + }, + "@smithy/hash-node@4.2.13": { + "integrity": "sha512-4/oy9h0jjmY80a2gOIo75iLl8TOPhmtx4E2Hz+PfMjvx/vLtGY4TMU/35WRyH2JHPfT5CVB38u4JRow7gnmzJA==", + "dependencies": [ + "@smithy/types", + "@smithy/util-buffer-from@4.2.2", + "@smithy/util-utf8@4.2.2", + "tslib" + ] + }, + "@smithy/invalid-dependency@4.2.13": { + "integrity": "sha512-jvC0RB/8BLj2SMIkY0Npl425IdnxZJxInpZJbu563zIRnVjpDMXevU3VMCRSabaLB0kf/eFIOusdGstrLJ8IDg==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/is-array-buffer@2.2.0": { + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/is-array-buffer@4.2.2": { + "integrity": "sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/middleware-content-length@4.2.13": { + "integrity": "sha512-IPMLm/LE4AZwu6qiE8Rr8vJsWhs9AtOdySRXrOM7xnvclp77Tyh7hMs/FRrMf26kgIe67vFJXXOSmVxS7oKeig==", + "dependencies": [ + "@smithy/protocol-http", + "@smithy/types", + "tslib" + ] + }, + "@smithy/middleware-endpoint@4.4.29": { + "integrity": "sha512-R9Q/58U+qBiSARGWbAbFLczECg/RmysRksX6Q8BaQEpt75I7LI6WGDZnjuC9GXSGKljEbA7N118LhGaMbfrTXw==", + "dependencies": [ + "@smithy/core", + "@smithy/middleware-serde", + "@smithy/node-config-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "@smithy/url-parser", + "@smithy/util-middleware", + "tslib" + ] + }, + "@smithy/middleware-retry@4.5.0": { + "integrity": "sha512-/NzISn4grj/BRFVua/xnQwF+7fakYZgimpw2dfmlPgcqecBMKxpB9g5mLYRrmBD5OrPoODokw4Vi1hrSR4zRyw==", + "dependencies": [ + "@smithy/core", + "@smithy/node-config-provider", + "@smithy/protocol-http", + "@smithy/service-error-classification", + "@smithy/smithy-client", + "@smithy/types", + "@smithy/util-middleware", + "@smithy/util-retry", + "@smithy/uuid", + "tslib" + ] + }, + "@smithy/middleware-serde@4.2.17": { + "integrity": "sha512-0T2mcaM6v9W1xku86Dk0bEW7aEseG6KenFkPK98XNw0ZhOqOiD1MrMsdnQw9QsL3/Oa85T53iSMlm0SZdSuIEQ==", + "dependencies": [ + "@smithy/core", + "@smithy/protocol-http", + "@smithy/types", + "tslib" + ] + }, + "@smithy/middleware-stack@4.2.13": { + "integrity": "sha512-g72jN/sGDLyTanrCLH9fhg3oysO3f7tQa6eWWsMyn2BiYNCgjF24n4/I9wff/5XidFvjj9ilipAoQrurTUrLvw==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/node-config-provider@4.3.13": { + "integrity": "sha512-iGxQ04DsKXLckbgnX4ipElrOTk+IHgTyu0q0WssZfYhDm9CQWHmu6cOeI5wmWRxpXbBDhIIfXMWz5tPEtcVqbw==", + "dependencies": [ + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@smithy/node-http-handler@4.5.2": { + "integrity": "sha512-/oD7u8M0oj2ZTFw7GkuuHWpIxtWdLlnyNkbrWcyVYhd5RJNDuczdkb0wfnQICyNFrVPlr8YHOhamjNy3zidhmA==", + "dependencies": [ + "@smithy/protocol-http", + "@smithy/querystring-builder", + "@smithy/types", + "tslib" + ] + }, + "@smithy/property-provider@4.2.13": { + "integrity": "sha512-bGzUCthxRmezuxkbu9wD33wWg9KX3hJpCXpQ93vVkPrHn9ZW6KNNdY5xAUWNuRCwQ+VyboFuWirG1lZhhkcyRQ==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/protocol-http@5.3.13": { + "integrity": "sha512-+HsmuJUF4u8POo6s8/a2Yb/AQ5t/YgLovCuHF9oxbocqv+SZ6gd8lC2duBFiCA/vFHoHQhoq7QjqJqZC6xOxxg==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/querystring-builder@4.2.13": { + "integrity": "sha512-tG4aOYFCZdPMjbgfhnIQ322H//ojujldp1SrHPHpBSb3NqgUp3dwiUGRJzie87hS1DYwWGqDuPaowoDF+rYCbQ==", + "dependencies": [ + "@smithy/types", + "@smithy/util-uri-escape", + "tslib" + ] + }, + "@smithy/querystring-parser@4.2.13": { + "integrity": "sha512-hqW3Q4P+CDzUyQ87GrboGMeD7XYNMOF+CuTwu936UQRB/zeYn3jys8C3w+wMkDfY7CyyyVwZQ5cNFoG0x1pYmA==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/service-error-classification@4.2.13": { + "integrity": "sha512-a0s8XZMfOC/qpqq7RCPvJlk93rWFrElH6O++8WJKz0FqnA4Y7fkNi/0mnGgSH1C4x6MFsuBA8VKu4zxFrMe5Vw==", + "dependencies": [ + "@smithy/types" + ] + }, + "@smithy/shared-ini-file-loader@4.4.8": { + "integrity": "sha512-VZCZx2bZasxdqxVgEAhREvDSlkatTPnkdWy1+Kiy8w7kYPBosW0V5IeDwzDUMvWBt56zpK658rx1cOBFOYaPaw==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/signature-v4@5.3.13": { + "integrity": "sha512-YpYSyM0vMDwKbHD/JA7bVOF6kToVRpa+FM5ateEVRpsTNu564g1muBlkTubXhSKKYXInhpADF46FPyrZcTLpXg==", + "dependencies": [ + "@smithy/is-array-buffer@4.2.2", + "@smithy/protocol-http", + "@smithy/types", + "@smithy/util-hex-encoding", + "@smithy/util-middleware", + "@smithy/util-uri-escape", + "@smithy/util-utf8@4.2.2", + "tslib" + ] + }, + "@smithy/smithy-client@4.12.9": { + "integrity": "sha512-ovaLEcTU5olSeHcRXcxV6viaKtpkHZumn6Ps0yn7dRf2rRSfy794vpjOtrWDO0d1auDSvAqxO+lyhERSXQ03EQ==", + "dependencies": [ + "@smithy/core", + "@smithy/middleware-endpoint", + "@smithy/middleware-stack", + "@smithy/protocol-http", + "@smithy/types", + "@smithy/util-stream", + "tslib" + ] + }, + "@smithy/types@4.14.0": { + "integrity": "sha512-OWgntFLW88kx2qvf/c/67Vno1yuXm/f9M7QFAtVkkO29IJXGBIg0ycEaBTH0kvCtwmvZxRujrgP5a86RvsXJAQ==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/url-parser@4.2.13": { + "integrity": "sha512-2G03yoboIRZlZze2+PT4GZEjgwQsJjUgn6iTsvxA02bVceHR6vp4Cuk7TUnPFWKF+ffNUk3kj4COwkENS2K3vw==", + "dependencies": [ + "@smithy/querystring-parser", + "@smithy/types", + "tslib" + ] + }, + "@smithy/util-base64@4.3.2": { + "integrity": "sha512-XRH6b0H/5A3SgblmMa5ErXQ2XKhfbQB+Fm/oyLZ2O2kCUrwgg55bU0RekmzAhuwOjA9qdN5VU2BprOvGGUkOOQ==", + "dependencies": [ + "@smithy/util-buffer-from@4.2.2", + "@smithy/util-utf8@4.2.2", + "tslib" + ] + }, + "@smithy/util-body-length-browser@4.2.2": { + "integrity": "sha512-JKCrLNOup3OOgmzeaKQwi4ZCTWlYR5H4Gm1r2uTMVBXoemo1UEghk5vtMi1xSu2ymgKVGW631e2fp9/R610ZjQ==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/util-body-length-node@4.2.3": { + "integrity": "sha512-ZkJGvqBzMHVHE7r/hcuCxlTY8pQr1kMtdsVPs7ex4mMU+EAbcXppfo5NmyxMYi2XU49eqaz56j2gsk4dHHPG/g==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/util-buffer-from@2.2.0": { + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dependencies": [ + "@smithy/is-array-buffer@2.2.0", + "tslib" + ] + }, + "@smithy/util-buffer-from@4.2.2": { + "integrity": "sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q==", + "dependencies": [ + "@smithy/is-array-buffer@4.2.2", + "tslib" + ] + }, + "@smithy/util-config-provider@4.2.2": { + "integrity": "sha512-dWU03V3XUprJwaUIFVv4iOnS1FC9HnMHDfUrlNDSh4315v0cWyaIErP8KiqGVbf5z+JupoVpNM7ZB3jFiTejvQ==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/util-defaults-mode-browser@4.3.45": { + "integrity": "sha512-ag9sWc6/nWZAuK3Wm9KlFJUnRkXLrXn33RFjIAmCTFThqLHY+7wCst10BGq56FxslsDrjhSie46c8OULS+BiIw==", + "dependencies": [ + "@smithy/property-provider", + "@smithy/smithy-client", + "@smithy/types", + "tslib" + ] + }, + "@smithy/util-defaults-mode-node@4.2.49": { + "integrity": "sha512-jlN6vHwE8gY5AfiFBavtD3QtCX2f7lM3BKkz7nFKSNfFR5nXLXLg6sqXTJEEyDwtxbztIDBQCfjsGVXlIru2lQ==", + "dependencies": [ + "@smithy/config-resolver", + "@smithy/credential-provider-imds", + "@smithy/node-config-provider", + "@smithy/property-provider", + "@smithy/smithy-client", + "@smithy/types", + "tslib" + ] + }, + "@smithy/util-endpoints@3.3.4": { + "integrity": "sha512-BKoR/ubPp9KNKFxPpg1J28N1+bgu8NGAtJblBP7yHy8yQPBWhIAv9+l92SlQLpolGm71CVO+btB60gTgzT0wog==", + "dependencies": [ + "@smithy/node-config-provider", + "@smithy/types", + "tslib" + ] + }, + "@smithy/util-hex-encoding@4.2.2": { + "integrity": "sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/util-middleware@4.2.13": { + "integrity": "sha512-GTooyrlmRTqvUen4eK7/K1p6kryF7bnDfq6XsAbIsf2mo51B/utaH+XThY6dKgNCWzMAaH/+OLmqaBuLhLWRow==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/util-retry@4.3.0": { + "integrity": "sha512-tSOPQNT/4KfbvqeMovWC3g23KSYy8czHd3tlN+tOYVNIDLSfxIsrPJihYi5TpNcoV789KWtgChUVedh2y6dDPg==", + "dependencies": [ + "@smithy/service-error-classification", + "@smithy/types", + "tslib" + ] + }, + "@smithy/util-stream@4.5.22": { + "integrity": "sha512-3H8iq/0BfQjUs2/4fbHZ9aG9yNzcuZs24LPkcX1Q7Z+qpqaGM8+qbGmE8zo9m2nCRgamyvS98cHdcWvR6YUsew==", + "dependencies": [ + "@smithy/fetch-http-handler", + "@smithy/node-http-handler", + "@smithy/types", + "@smithy/util-base64", + "@smithy/util-buffer-from@4.2.2", + "@smithy/util-hex-encoding", + "@smithy/util-utf8@4.2.2", + "tslib" + ] + }, + "@smithy/util-uri-escape@4.2.2": { + "integrity": "sha512-2kAStBlvq+lTXHyAZYfJRb/DfS3rsinLiwb+69SstC9Vb0s9vNWkRwpnj918Pfi85mzi42sOqdV72OLxWAISnw==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/util-utf8@2.3.0": { + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dependencies": [ + "@smithy/util-buffer-from@2.2.0", + "tslib" + ] + }, + "@smithy/util-utf8@4.2.2": { + "integrity": "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw==", + "dependencies": [ + "@smithy/util-buffer-from@4.2.2", + "tslib" + ] + }, + "@smithy/util-waiter@4.2.15": { + "integrity": "sha512-oUt9o7n8hBv3BL56sLSneL0XeigZSuem0Hr78JaoK33D9oKieyCvVP8eTSe3j7g2mm/S1DvzxKieG7JEWNJUNg==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/uuid@1.1.2": { + "integrity": "sha512-O/IEdcCUKkubz60tFbGA7ceITTAJsty+lBjNoorP4Z6XRqaFb/OjQjZODophEcuq68nKm6/0r+6/lLQ+XVpk8g==", + "dependencies": [ + "tslib" + ] + }, + "bowser@2.14.1": { + "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==" + }, + "fast-json-patch@3.1.1": { + "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==" + }, + "fast-xml-builder@1.1.4": { + "integrity": "sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg==", + "dependencies": [ + "path-expression-matcher" + ] + }, + "fast-xml-parser@5.5.8": { + "integrity": "sha512-Z7Fh2nVQSb2d+poDViM063ix2ZGt9jmY1nWhPfHBOK2Hgnb/OW3P4Et3P/81SEej0J7QbWtJqxO05h8QYfK7LQ==", + "dependencies": [ + "fast-xml-builder", + "path-expression-matcher", + "strnum" + ], + "bin": true + }, + "path-expression-matcher@1.4.0": { + "integrity": "sha512-s4DQMxIdhj3jLFWd9LxHOplj4p9yQ4ffMGowFf3cpEgrrJjEhN0V5nxw4Ye1EViAGDoL4/1AeO6qHpqYPOzE4Q==" + }, + "strnum@2.2.3": { + "integrity": "sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg==" + }, + "tslib@2.8.1": { + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "zod@4.3.6": { + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==" + } + }, + "workspace": { + "dependencies": [ + "npm:@aws-sdk/client-cloudcontrol@3.1021.0", + "npm:fast-json-patch@3.1.1", + "npm:zod@4.3.6" + ] + } +} diff --git a/model/aws/bcmpricingcalculator/extensions/models/_lib/aws.ts b/model/aws/bcmpricingcalculator/extensions/models/_lib/aws.ts new file mode 100644 index 000000000..8a0d63606 --- /dev/null +++ b/model/aws/bcmpricingcalculator/extensions/models/_lib/aws.ts @@ -0,0 +1,395 @@ +// Auto-generated shared helper for AWS CloudControl extension models. +// Do not edit manually. Re-generate with: deno task generate:aws + +import { + CloudControlClient, + CreateResourceCommand, + DeleteResourceCommand, + GetResourceCommand, + GetResourceRequestStatusCommand, + UpdateResourceCommand, +} from "@aws-sdk/client-cloudcontrol"; +import jsonpatch from "fast-json-patch"; + +function createClient(): CloudControlClient { + return new CloudControlClient({ + region: Deno.env.get("AWS_REGION") || "us-east-1", + }); +} + +function delay(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +function isThrottlingError(error: unknown): boolean { + const msg = error instanceof Error ? error.message : String(error); + const name = error instanceof Error ? error.name : ""; + return ( + msg.includes("Throttling") || + msg.includes("TooManyRequests") || + msg.includes("RequestLimitExceeded") || + name === "ThrottlingException" + ); +} + +export function isResourceNotFoundError(error: unknown): boolean { + const msg = error instanceof Error ? error.message : String(error); + const name = error instanceof Error ? error.name : ""; + return ( + msg.includes("was not found") || + msg.includes("does not exist") || + name === "ResourceNotFoundException" + ); +} + +async function withRetry( + operation: () => Promise, + operationName: string, + maxAttempts = 20, +): Promise { + const baseDelay = 1000; + const maxDelay = 90000; + + for (let attempt = 0; attempt < maxAttempts; attempt++) { + try { + return await operation(); + } catch (error) { + if (isThrottlingError(error) && attempt < maxAttempts - 1) { + const exponentialDelay = Math.min( + baseDelay * Math.pow(2, attempt), + maxDelay, + ); + const jitter = Math.random() * 0.3 * exponentialDelay; + console.log( + `[${operationName}] Throttled on attempt ${attempt + 1}, waiting ${ + Math.round(exponentialDelay + jitter) + }ms`, + ); + await delay(exponentialDelay + jitter); + continue; + } + throw error; + } + } + throw new Error(`${operationName} failed after ${maxAttempts} attempts`); +} + +async function pollOperationStatus( + client: CloudControlClient, + requestToken: string, + operationName: string, +): Promise<{ status: string; identifier?: string; message?: string }> { + const baseDelay = 1000; + const maxDelay = 90000; + + for (let attempt = 0; attempt < 60; attempt++) { + const response = await withRetry( + () => + client.send( + new GetResourceRequestStatusCommand({ + RequestToken: requestToken, + }), + ), + `${operationName} status poll`, + ); + + const status = response.ProgressEvent?.OperationStatus; + if (status === "SUCCESS") { + return { + status: "SUCCESS", + identifier: response.ProgressEvent?.Identifier, + }; + } + if (status === "FAILED") { + return { + status: "FAILED", + message: response.ProgressEvent?.StatusMessage || + response.ProgressEvent?.ErrorCode, + }; + } + if (status === "CANCEL_COMPLETE") { + return { + status: "CANCEL_COMPLETE", + message: "Operation cancelled by API or AWS", + }; + } + + const exponentialDelay = Math.min( + baseDelay * Math.pow(2, attempt), + maxDelay, + ); + const jitter = Math.random() * 0.3 * exponentialDelay; + console.log( + `[${operationName}] IN_PROGRESS, waiting ${ + Math.round(exponentialDelay + jitter) + }ms (poll ${attempt + 1})`, + ); + await delay(exponentialDelay + jitter); + } + + throw new Error(`${operationName} timed out after polling`); +} + +/** + * Create an AWS resource via CloudControl API. + * Sends CreateResourceCommand, polls until complete, then reads the resource. + * Returns the resource properties. + */ +export async function createResource( + typeName: string, + desiredState: Record, +): Promise> { + const client = createClient(); + + console.log(`[CREATE] Starting create for ${typeName}`); + + const response = await withRetry( + () => + client.send( + new CreateResourceCommand({ + TypeName: typeName, + DesiredState: JSON.stringify(desiredState), + }), + ), + `${typeName} create`, + ); + + if (!response.ProgressEvent?.RequestToken) { + throw new Error(`${typeName} creation failed: no request token returned`); + } + + const requestToken = response.ProgressEvent.RequestToken; + console.log(`[CREATE] Got request token: ${requestToken}`); + + const pollResult = await pollOperationStatus( + client, + requestToken, + `${typeName} create`, + ); + + if (pollResult.status === "FAILED") { + throw new Error( + `${typeName} creation failed: ${pollResult.message || "Unknown error"}`, + ); + } + if (pollResult.status === "CANCEL_COMPLETE") { + throw new Error( + `${typeName} creation cancelled: ${pollResult.message}`, + ); + } + + const identifier = pollResult.identifier; + if (!identifier) { + throw new Error( + `${typeName} creation succeeded but no identifier returned`, + ); + } + + console.log(`[CREATE] Success, fetching resource ${identifier}`); + + const getResponse = await withRetry( + () => + client.send( + new GetResourceCommand({ + TypeName: typeName, + Identifier: identifier, + }), + ), + `${typeName} create get-resource`, + ); + + if (!getResponse.ResourceDescription?.Properties) { + throw new Error(`Failed to get ${typeName} details after creation`); + } + + return JSON.parse(getResponse.ResourceDescription.Properties); +} + +/** + * Read an AWS resource via CloudControl API. + * Returns the resource properties, or throws if not found. + */ +export async function readResource( + typeName: string, + identifier: string, +): Promise> { + const client = createClient(); + + console.log(`[READ] Fetching ${typeName} identifier: ${identifier}`); + + const response = await withRetry( + () => + client.send( + new GetResourceCommand({ + TypeName: typeName, + Identifier: identifier, + }), + ), + `${typeName} read`, + ); + + if (!response.ResourceDescription?.Properties) { + throw new Error(`Failed to get ${typeName} details`); + } + + return JSON.parse(response.ResourceDescription.Properties); +} + +/** + * Update an AWS resource via CloudControl API. + * Reads current state, computes JSON patch (filtering createOnlyProperties), + * sends UpdateResourceCommand, polls, then reads the updated resource. + */ +export async function updateResource( + typeName: string, + identifier: string, + currentState: Record, + desiredState: Record, + createOnlyProperties?: string[], +): Promise> { + const client = createClient(); + const createOnlySet = new Set(createOnlyProperties ?? []); + + console.log( + `[UPDATE] Starting update for ${typeName} identifier: ${identifier}`, + ); + + // Compute JSON patch, filtering out create-only properties + const rawPatch = jsonpatch.compare(currentState, desiredState); + const patch = rawPatch.filter((op: { path: string }) => { + const topLevelProp = op.path.split("/")[1]; + if (topLevelProp && createOnlySet.has(topLevelProp)) { + console.log(`[UPDATE] Skipping create-only property: ${topLevelProp}`); + return false; + } + return true; + }); + + if (patch.length === 0) { + console.log(`[UPDATE] No changes detected, returning current state`); + return currentState; + } + + console.log(`[UPDATE] Applying ${patch.length} patch operations`); + + const response = await withRetry( + () => + client.send( + new UpdateResourceCommand({ + TypeName: typeName, + Identifier: identifier, + PatchDocument: JSON.stringify(patch), + }), + ), + `${typeName} update`, + ); + + if (!response.ProgressEvent?.RequestToken) { + throw new Error(`${typeName} update failed: no request token returned`); + } + + const requestToken = response.ProgressEvent.RequestToken; + console.log(`[UPDATE] Got request token: ${requestToken}`); + + const pollResult = await pollOperationStatus( + client, + requestToken, + `${typeName} update`, + ); + + if (pollResult.status === "FAILED") { + throw new Error( + `${typeName} update failed: ${pollResult.message || "Unknown error"}`, + ); + } + if (pollResult.status === "CANCEL_COMPLETE") { + throw new Error(`${typeName} update cancelled: ${pollResult.message}`); + } + + const resultIdentifier = pollResult.identifier || identifier; + console.log(`[UPDATE] Success, fetching resource ${resultIdentifier}`); + + const getResponse = await withRetry( + () => + client.send( + new GetResourceCommand({ + TypeName: typeName, + Identifier: resultIdentifier, + }), + ), + `${typeName} update get-resource`, + ); + + if (!getResponse.ResourceDescription?.Properties) { + throw new Error(`Failed to get ${typeName} details after update`); + } + + return JSON.parse(getResponse.ResourceDescription.Properties); +} + +/** + * Delete an AWS resource via CloudControl API. + * Returns { existed: true } on success, { existed: false } if already gone. + */ +export async function deleteResource( + typeName: string, + identifier: string, +): Promise<{ existed: boolean }> { + const client = createClient(); + + console.log( + `[DELETE] Starting delete for ${typeName} identifier: ${identifier}`, + ); + + try { + const response = await withRetry( + () => + client.send( + new DeleteResourceCommand({ + TypeName: typeName, + Identifier: identifier, + }), + ), + `${typeName} delete`, + ); + + if (!response.ProgressEvent?.RequestToken) { + throw new Error(`${typeName} deletion failed: no request token returned`); + } + + const requestToken = response.ProgressEvent.RequestToken; + console.log(`[DELETE] Got request token: ${requestToken}`); + + const pollResult = await pollOperationStatus( + client, + requestToken, + `${typeName} delete`, + ); + + if (pollResult.status === "FAILED") { + if ( + pollResult.message && + (pollResult.message.includes("was not found") || + pollResult.message.includes("does not exist")) + ) { + return { existed: false }; + } + throw new Error( + `${typeName} deletion failed: ${pollResult.message || "Unknown error"}`, + ); + } + + if (pollResult.status === "CANCEL_COMPLETE") { + throw new Error( + `${typeName} deletion cancelled: ${pollResult.message}`, + ); + } + + return { existed: true }; + } catch (error: unknown) { + if (isResourceNotFoundError(error)) { + return { existed: false }; + } + throw error; + } +} diff --git a/model/aws/bcmpricingcalculator/extensions/models/bill_scenario.ts b/model/aws/bcmpricingcalculator/extensions/models/bill_scenario.ts new file mode 100644 index 000000000..d48baa450 --- /dev/null +++ b/model/aws/bcmpricingcalculator/extensions/models/bill_scenario.ts @@ -0,0 +1,266 @@ +// Auto-generated extension model for @swamp/aws/bcmpricingcalculator/bill-scenario +// Do not edit manually. Re-generate with: deno task generate:aws + +// deno-lint-ignore-file no-explicit-any + +import { z } from "zod"; +import { + createResource, + deleteResource, + isResourceNotFoundError, + readResource, + updateResource, +} from "./_lib/aws.ts"; + +export const TagSchema = z.object({ + Key: z.string().min(1).max(128), + Value: z.string().min(0).max(256), +}); + +const GlobalArgsSchema = z.object({ + name: z.string().describe( + "Instance name for this resource (used as the unique identifier in the factory pattern)", + ), + Name: z.string().min(1).max(64).describe("The name of the bill scenario") + .optional(), + BillInterval: z.object({ + Start: z.string().optional(), + End: z.string().optional(), + }).describe("The time period covered by the bill scenario").optional(), + ExpiresAt: z.string().describe("The timestamp when the bill scenario expires") + .optional(), + CostCategoryGroupSharingPreferenceArn: z.string().regex( + new RegExp("^arn:aws[a-z-]*:ce::[0-9]{12}:costcategory/[a-f0-9-]{36}$"), + ).describe("The ARN of the cost category group sharing preference") + .optional(), + GroupSharingPreference: z.enum(["OPEN", "PRIORITIZED", "RESTRICTED"]) + .describe("The group sharing preference for the bill scenario").optional(), + Tags: z.array(TagSchema).describe( + "An array of key-value pairs to apply to this resource", + ).optional(), +}); + +const StateSchema = z.object({ + Arn: z.string(), + Id: z.string().optional(), + Name: z.string().optional(), + BillInterval: z.object({ + Start: z.string(), + End: z.string(), + }).optional(), + Status: z.string().optional(), + CreatedAt: z.string().optional(), + ExpiresAt: z.string().optional(), + FailureMessage: z.string().optional(), + CostCategoryGroupSharingPreferenceArn: z.string().optional(), + GroupSharingPreference: z.string().optional(), + Tags: z.array(TagSchema).optional(), +}).passthrough(); + +type StateData = z.infer; + +const InputsSchema = z.object({ + name: z.string().optional(), + Name: z.string().min(1).max(64).describe("The name of the bill scenario") + .optional(), + BillInterval: z.object({ + Start: z.string().optional(), + End: z.string().optional(), + }).describe("The time period covered by the bill scenario").optional(), + ExpiresAt: z.string().describe("The timestamp when the bill scenario expires") + .optional(), + CostCategoryGroupSharingPreferenceArn: z.string().regex( + new RegExp("^arn:aws[a-z-]*:ce::[0-9]{12}:costcategory/[a-f0-9-]{36}$"), + ).describe("The ARN of the cost category group sharing preference") + .optional(), + GroupSharingPreference: z.enum(["OPEN", "PRIORITIZED", "RESTRICTED"]) + .describe("The group sharing preference for the bill scenario").optional(), + Tags: z.array(TagSchema).describe( + "An array of key-value pairs to apply to this resource", + ).optional(), +}); + +export const model = { + type: "@swamp/aws/bcmpricingcalculator/bill-scenario", + version: "2026.04.08.1", + globalArguments: GlobalArgsSchema, + inputsSchema: InputsSchema, + resources: { + state: { + description: "BcmPricingCalculator BillScenario resource state", + schema: StateSchema, + lifetime: "infinite", + garbageCollection: 10, + }, + }, + methods: { + create: { + description: "Create a BcmPricingCalculator BillScenario", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const desiredState: Record = {}; + for (const [key, value] of Object.entries(g)) { + if (key === "name") continue; + if (value !== undefined) desiredState[key] = value; + } + const result = await createResource( + "AWS::BcmPricingCalculator::BillScenario", + desiredState, + ) as StateData; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + get: { + description: "Get a BcmPricingCalculator BillScenario", + arguments: z.object({ + identifier: z.string().describe( + "The primary identifier of the BcmPricingCalculator BillScenario", + ), + }), + execute: async (args: { identifier: string }, context: any) => { + const result = await readResource( + "AWS::BcmPricingCalculator::BillScenario", + args.identifier, + ) as StateData; + const instanceName = + (context.globalArgs.name?.toString() ?? args.identifier).replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + update: { + description: "Update a BcmPricingCalculator BillScenario", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const content = await context.dataRepository.getContent( + context.modelType, + context.modelId, + instanceName, + ); + if (!content) { + throw new Error("No existing state found - run create or get first"); + } + const existing = JSON.parse(new TextDecoder().decode(content)); + const identifier = existing.Arn?.toString(); + if (!identifier) { + throw new Error("No identifier found in existing state"); + } + const currentState = await readResource( + "AWS::BcmPricingCalculator::BillScenario", + identifier, + ) as StateData; + const desiredState: Record = { ...currentState }; + for (const [key, value] of Object.entries(g)) { + if (key === "name") continue; + if (value !== undefined) desiredState[key] = value; + } + const result = await updateResource( + "AWS::BcmPricingCalculator::BillScenario", + identifier, + currentState, + desiredState, + ); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + delete: { + description: "Delete a BcmPricingCalculator BillScenario", + arguments: z.object({ + identifier: z.string().describe( + "The primary identifier of the BcmPricingCalculator BillScenario", + ), + }), + execute: async (args: { identifier: string }, context: any) => { + const { existed } = await deleteResource( + "AWS::BcmPricingCalculator::BillScenario", + args.identifier, + ); + const instanceName = + (context.globalArgs.name?.toString() ?? args.identifier).replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource("state", instanceName, { + identifier: args.identifier, + existed, + status: existed ? "deleted" : "not_found", + deletedAt: new Date().toISOString(), + }); + return { dataHandles: [handle] }; + }, + }, + sync: { + description: "Sync BcmPricingCalculator BillScenario state from AWS", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const content = await context.dataRepository.getContent( + context.modelType, + context.modelId, + instanceName, + ); + if (!content) { + throw new Error("No existing state found - run create or get first"); + } + const existing = JSON.parse(new TextDecoder().decode(content)); + const identifier = existing.Arn?.toString(); + if (!identifier) { + throw new Error("No identifier found in existing state"); + } + try { + const result = await readResource( + "AWS::BcmPricingCalculator::BillScenario", + identifier, + ) as StateData; + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + } catch (error: unknown) { + if (isResourceNotFoundError(error)) { + const handle = await context.writeResource("state", instanceName, { + identifier, + status: "not_found", + syncedAt: new Date().toISOString(), + }); + return { dataHandles: [handle] }; + } + throw error; + } + }, + }, + }, +}; diff --git a/model/aws/bcmpricingcalculator/manifest.yaml b/model/aws/bcmpricingcalculator/manifest.yaml new file mode 100644 index 000000000..911144f38 --- /dev/null +++ b/model/aws/bcmpricingcalculator/manifest.yaml @@ -0,0 +1,17 @@ +# Auto-generated manifest. Re-generate with the appropriate deno task. +manifestVersion: 1 +name: "@swamp/aws/bcmpricingcalculator" +version: "2026.04.08.1" +description: "AWS BCMPRICINGCALCULATOR infrastructure models" +labels: + - aws + - bcmpricingcalculator + - cloud + - infrastructure +releaseNotes: | + - Added: bill_scenario +models: + - bill_scenario.ts +additionalFiles: + - LICENSE.txt + - README.md diff --git a/model/aws/bedrock/extensions/models/data_automation_library.ts b/model/aws/bedrock/extensions/models/data_automation_library.ts new file mode 100644 index 000000000..5e99bbdb1 --- /dev/null +++ b/model/aws/bedrock/extensions/models/data_automation_library.ts @@ -0,0 +1,266 @@ +// Auto-generated extension model for @swamp/aws/bedrock/data-automation-library +// Do not edit manually. Re-generate with: deno task generate:aws + +// deno-lint-ignore-file no-explicit-any + +import { z } from "zod"; +import { + createResource, + deleteResource, + isResourceNotFoundError, + readResource, + updateResource, +} from "./_lib/aws.ts"; + +export const TagSchema = z.object({ + Key: z.string().min(1).max(128).regex(new RegExp("^[a-zA-Z0-9\\s._:/=+@-]*$")) + .describe("Tag key"), + Value: z.string().min(0).max(256).regex( + new RegExp("^[a-zA-Z0-9\\s._:/=+@-]*$"), + ).describe("Tag value"), +}); + +const GlobalArgsSchema = z.object({ + name: z.string().describe( + "Instance name for this resource (used as the unique identifier in the factory pattern)", + ), + EncryptionConfiguration: z.object({ + KmsKeyId: z.string().min(1).max(2048).regex( + new RegExp("^[A-Za-z0-9][A-Za-z0-9:_/+=,@.-]+$"), + ).describe("KMS Key Identifier"), + KmsEncryptionContext: z.record( + z.string(), + z.string().min(1).max(2000).regex(new RegExp("^.*\\S.*$")), + ).describe("KMS Encryption Context").optional(), + }).describe("KMS Encryption Configuration").optional(), + LibraryDescription: z.string().min(0).max(300).describe( + "Description of the DataAutomationLibrary", + ).optional(), + LibraryName: z.string().min(1).max(128).regex(new RegExp("^[a-zA-Z0-9-_]+$")) + .describe("Name of the DataAutomationLibrary"), + Tags: z.array(TagSchema).describe("List of tags").optional(), +}); + +const StateSchema = z.object({ + CreationTime: z.string().optional(), + EncryptionConfiguration: z.object({ + KmsKeyId: z.string(), + KmsEncryptionContext: z.record(z.string(), z.unknown()), + }).optional(), + EntityTypes: z.array(z.object({ + EntityType: z.string(), + EntityMetadata: z.string(), + })).optional(), + LibraryArn: z.string(), + LibraryDescription: z.string().optional(), + LibraryName: z.string().optional(), + Status: z.string().optional(), + Tags: z.array(TagSchema).optional(), +}).passthrough(); + +type StateData = z.infer; + +const InputsSchema = z.object({ + name: z.string().optional(), + EncryptionConfiguration: z.object({ + KmsKeyId: z.string().min(1).max(2048).regex( + new RegExp("^[A-Za-z0-9][A-Za-z0-9:_/+=,@.-]+$"), + ).describe("KMS Key Identifier").optional(), + KmsEncryptionContext: z.record( + z.string(), + z.string().min(1).max(2000).regex(new RegExp("^.*\\S.*$")), + ).describe("KMS Encryption Context").optional(), + }).describe("KMS Encryption Configuration").optional(), + LibraryDescription: z.string().min(0).max(300).describe( + "Description of the DataAutomationLibrary", + ).optional(), + LibraryName: z.string().min(1).max(128).regex(new RegExp("^[a-zA-Z0-9-_]+$")) + .describe("Name of the DataAutomationLibrary").optional(), + Tags: z.array(TagSchema).describe("List of tags").optional(), +}); + +export const model = { + type: "@swamp/aws/bedrock/data-automation-library", + version: "2026.04.08.1", + globalArguments: GlobalArgsSchema, + inputsSchema: InputsSchema, + resources: { + state: { + description: "Bedrock DataAutomationLibrary resource state", + schema: StateSchema, + lifetime: "infinite", + garbageCollection: 10, + }, + }, + methods: { + create: { + description: "Create a Bedrock DataAutomationLibrary", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const desiredState: Record = {}; + for (const [key, value] of Object.entries(g)) { + if (key === "name") continue; + if (value !== undefined) desiredState[key] = value; + } + const result = await createResource( + "AWS::Bedrock::DataAutomationLibrary", + desiredState, + ) as StateData; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + get: { + description: "Get a Bedrock DataAutomationLibrary", + arguments: z.object({ + identifier: z.string().describe( + "The primary identifier of the Bedrock DataAutomationLibrary", + ), + }), + execute: async (args: { identifier: string }, context: any) => { + const result = await readResource( + "AWS::Bedrock::DataAutomationLibrary", + args.identifier, + ) as StateData; + const instanceName = + (context.globalArgs.name?.toString() ?? args.identifier).replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + update: { + description: "Update a Bedrock DataAutomationLibrary", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const content = await context.dataRepository.getContent( + context.modelType, + context.modelId, + instanceName, + ); + if (!content) { + throw new Error("No existing state found - run create or get first"); + } + const existing = JSON.parse(new TextDecoder().decode(content)); + const identifier = existing.LibraryArn?.toString(); + if (!identifier) { + throw new Error("No identifier found in existing state"); + } + const currentState = await readResource( + "AWS::Bedrock::DataAutomationLibrary", + identifier, + ) as StateData; + const desiredState: Record = { ...currentState }; + for (const [key, value] of Object.entries(g)) { + if (key === "name") continue; + if (value !== undefined) desiredState[key] = value; + } + const result = await updateResource( + "AWS::Bedrock::DataAutomationLibrary", + identifier, + currentState, + desiredState, + ["EncryptionConfiguration", "LibraryName"], + ); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + delete: { + description: "Delete a Bedrock DataAutomationLibrary", + arguments: z.object({ + identifier: z.string().describe( + "The primary identifier of the Bedrock DataAutomationLibrary", + ), + }), + execute: async (args: { identifier: string }, context: any) => { + const { existed } = await deleteResource( + "AWS::Bedrock::DataAutomationLibrary", + args.identifier, + ); + const instanceName = + (context.globalArgs.name?.toString() ?? args.identifier).replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource("state", instanceName, { + identifier: args.identifier, + existed, + status: existed ? "deleted" : "not_found", + deletedAt: new Date().toISOString(), + }); + return { dataHandles: [handle] }; + }, + }, + sync: { + description: "Sync Bedrock DataAutomationLibrary state from AWS", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const content = await context.dataRepository.getContent( + context.modelType, + context.modelId, + instanceName, + ); + if (!content) { + throw new Error("No existing state found - run create or get first"); + } + const existing = JSON.parse(new TextDecoder().decode(content)); + const identifier = existing.LibraryArn?.toString(); + if (!identifier) { + throw new Error("No identifier found in existing state"); + } + try { + const result = await readResource( + "AWS::Bedrock::DataAutomationLibrary", + identifier, + ) as StateData; + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + } catch (error: unknown) { + if (isResourceNotFoundError(error)) { + const handle = await context.writeResource("state", instanceName, { + identifier, + status: "not_found", + syncedAt: new Date().toISOString(), + }); + return { dataHandles: [handle] }; + } + throw error; + } + }, + }, + }, +}; diff --git a/model/aws/bedrock/extensions/models/enforced_guardrail_configuration.ts b/model/aws/bedrock/extensions/models/enforced_guardrail_configuration.ts new file mode 100644 index 000000000..69a0e16a2 --- /dev/null +++ b/model/aws/bedrock/extensions/models/enforced_guardrail_configuration.ts @@ -0,0 +1,306 @@ +// Auto-generated extension model for @swamp/aws/bedrock/enforced-guardrail-configuration +// Do not edit manually. Re-generate with: deno task generate:aws + +// deno-lint-ignore-file no-explicit-any + +import { z } from "zod"; +import { + createResource, + deleteResource, + isResourceNotFoundError, + readResource, + updateResource, +} from "./_lib/aws.ts"; + +const GlobalArgsSchema = z.object({ + name: z.string().describe( + "Instance name for this resource (used as the unique identifier in the factory pattern)", + ), + GuardrailIdentifier: z.string().min(0).max(2048).regex( + new RegExp( + "^(([a-z0-9]+)|(arn:aws(-[^:]+)?:bedrock:[a-z0-9-]{1,20}:[0-9]{12}:guardrail/[a-z0-9]+))$", + ), + ).describe("Identifier for the guardrail, could be the ID or the ARN"), + GuardrailVersion: z.string().regex(new RegExp("^[1-9][0-9]{0,7}$")).describe( + "Numerical guardrail version (not DRAFT)", + ), + SelectiveContentGuarding: z.object({ + System: z.enum(["SELECTIVE", "COMPREHENSIVE"]).describe( + "Selective guarding mode for system prompts", + ).optional(), + Messages: z.enum(["SELECTIVE", "COMPREHENSIVE"]).describe( + "Selective guarding mode for user messages", + ).optional(), + }).describe("Selective content guarding controls for enforced guardrails") + .optional(), + ModelEnforcement: z.object({ + IncludedModels: z.array( + z.string().regex( + new RegExp( + "^(ALL|([a-z0-9-]{1,63}[.]{1}[a-z0-9-]{1,63})([:][a-z0-9-]{1,63}){0,2}(/[a-z0-9]{12}){0,1})$", + ), + ), + ).describe("Models to enforce the guardrail on"), + ExcludedModels: z.array( + z.string().regex( + new RegExp( + "^([a-z0-9-]{1,63}[.]{1}[a-z0-9-]{1,63})([:][a-z0-9-]{1,63}){0,2}(/[a-z0-9]{12}){0,1}$", + ), + ), + ).describe( + "Models to exclude from enforcement. If a model is in both lists, it is excluded", + ), + }).describe( + "Model-specific information for the enforced guardrail configuration. If not present, the configuration is enforced on all models", + ).optional(), +}); + +const StateSchema = z.object({ + ConfigId: z.string(), + GuardrailIdentifier: z.string().optional(), + GuardrailVersion: z.string().optional(), + SelectiveContentGuarding: z.object({ + System: z.string(), + Messages: z.string(), + }).optional(), + ModelEnforcement: z.object({ + IncludedModels: z.array(z.string()), + ExcludedModels: z.array(z.string()), + }).optional(), + GuardrailArn: z.string().optional(), + GuardrailId: z.string().optional(), + CreatedAt: z.string().optional(), + CreatedBy: z.string().optional(), + UpdatedAt: z.string().optional(), + UpdatedBy: z.string().optional(), + Owner: z.string().optional(), +}).passthrough(); + +type StateData = z.infer; + +const InputsSchema = z.object({ + name: z.string().optional(), + GuardrailIdentifier: z.string().min(0).max(2048).regex( + new RegExp( + "^(([a-z0-9]+)|(arn:aws(-[^:]+)?:bedrock:[a-z0-9-]{1,20}:[0-9]{12}:guardrail/[a-z0-9]+))$", + ), + ).describe("Identifier for the guardrail, could be the ID or the ARN") + .optional(), + GuardrailVersion: z.string().regex(new RegExp("^[1-9][0-9]{0,7}$")).describe( + "Numerical guardrail version (not DRAFT)", + ).optional(), + SelectiveContentGuarding: z.object({ + System: z.enum(["SELECTIVE", "COMPREHENSIVE"]).describe( + "Selective guarding mode for system prompts", + ).optional(), + Messages: z.enum(["SELECTIVE", "COMPREHENSIVE"]).describe( + "Selective guarding mode for user messages", + ).optional(), + }).describe("Selective content guarding controls for enforced guardrails") + .optional(), + ModelEnforcement: z.object({ + IncludedModels: z.array( + z.string().regex( + new RegExp( + "^(ALL|([a-z0-9-]{1,63}[.]{1}[a-z0-9-]{1,63})([:][a-z0-9-]{1,63}){0,2}(/[a-z0-9]{12}){0,1})$", + ), + ), + ).describe("Models to enforce the guardrail on").optional(), + ExcludedModels: z.array( + z.string().regex( + new RegExp( + "^([a-z0-9-]{1,63}[.]{1}[a-z0-9-]{1,63})([:][a-z0-9-]{1,63}){0,2}(/[a-z0-9]{12}){0,1}$", + ), + ), + ).describe( + "Models to exclude from enforcement. If a model is in both lists, it is excluded", + ).optional(), + }).describe( + "Model-specific information for the enforced guardrail configuration. If not present, the configuration is enforced on all models", + ).optional(), +}); + +export const model = { + type: "@swamp/aws/bedrock/enforced-guardrail-configuration", + version: "2026.04.08.1", + globalArguments: GlobalArgsSchema, + inputsSchema: InputsSchema, + resources: { + state: { + description: "Bedrock EnforcedGuardrailConfiguration resource state", + schema: StateSchema, + lifetime: "infinite", + garbageCollection: 10, + }, + }, + methods: { + create: { + description: "Create a Bedrock EnforcedGuardrailConfiguration", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const desiredState: Record = {}; + for (const [key, value] of Object.entries(g)) { + if (key === "name") continue; + if (value !== undefined) desiredState[key] = value; + } + const result = await createResource( + "AWS::Bedrock::EnforcedGuardrailConfiguration", + desiredState, + ) as StateData; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + get: { + description: "Get a Bedrock EnforcedGuardrailConfiguration", + arguments: z.object({ + identifier: z.string().describe( + "The primary identifier of the Bedrock EnforcedGuardrailConfiguration", + ), + }), + execute: async (args: { identifier: string }, context: any) => { + const result = await readResource( + "AWS::Bedrock::EnforcedGuardrailConfiguration", + args.identifier, + ) as StateData; + const instanceName = + (context.globalArgs.name?.toString() ?? args.identifier).replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + update: { + description: "Update a Bedrock EnforcedGuardrailConfiguration", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const content = await context.dataRepository.getContent( + context.modelType, + context.modelId, + instanceName, + ); + if (!content) { + throw new Error("No existing state found - run create or get first"); + } + const existing = JSON.parse(new TextDecoder().decode(content)); + const identifier = existing.ConfigId?.toString(); + if (!identifier) { + throw new Error("No identifier found in existing state"); + } + const currentState = await readResource( + "AWS::Bedrock::EnforcedGuardrailConfiguration", + identifier, + ) as StateData; + const desiredState: Record = { ...currentState }; + for (const [key, value] of Object.entries(g)) { + if (key === "name") continue; + if (value !== undefined) desiredState[key] = value; + } + const result = await updateResource( + "AWS::Bedrock::EnforcedGuardrailConfiguration", + identifier, + currentState, + desiredState, + ); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + delete: { + description: "Delete a Bedrock EnforcedGuardrailConfiguration", + arguments: z.object({ + identifier: z.string().describe( + "The primary identifier of the Bedrock EnforcedGuardrailConfiguration", + ), + }), + execute: async (args: { identifier: string }, context: any) => { + const { existed } = await deleteResource( + "AWS::Bedrock::EnforcedGuardrailConfiguration", + args.identifier, + ); + const instanceName = + (context.globalArgs.name?.toString() ?? args.identifier).replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource("state", instanceName, { + identifier: args.identifier, + existed, + status: existed ? "deleted" : "not_found", + deletedAt: new Date().toISOString(), + }); + return { dataHandles: [handle] }; + }, + }, + sync: { + description: "Sync Bedrock EnforcedGuardrailConfiguration state from AWS", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const content = await context.dataRepository.getContent( + context.modelType, + context.modelId, + instanceName, + ); + if (!content) { + throw new Error("No existing state found - run create or get first"); + } + const existing = JSON.parse(new TextDecoder().decode(content)); + const identifier = existing.ConfigId?.toString(); + if (!identifier) { + throw new Error("No identifier found in existing state"); + } + try { + const result = await readResource( + "AWS::Bedrock::EnforcedGuardrailConfiguration", + identifier, + ) as StateData; + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + } catch (error: unknown) { + if (isResourceNotFoundError(error)) { + const handle = await context.writeResource("state", instanceName, { + identifier, + status: "not_found", + syncedAt: new Date().toISOString(), + }); + return { dataHandles: [handle] }; + } + throw error; + } + }, + }, + }, +}; diff --git a/model/aws/bedrock/extensions/models/resource_policy.ts b/model/aws/bedrock/extensions/models/resource_policy.ts new file mode 100644 index 000000000..235883d61 --- /dev/null +++ b/model/aws/bedrock/extensions/models/resource_policy.ts @@ -0,0 +1,223 @@ +// Auto-generated extension model for @swamp/aws/bedrock/resource-policy +// Do not edit manually. Re-generate with: deno task generate:aws + +// deno-lint-ignore-file no-explicit-any + +import { z } from "zod"; +import { + createResource, + deleteResource, + isResourceNotFoundError, + readResource, + updateResource, +} from "./_lib/aws.ts"; + +const GlobalArgsSchema = z.object({ + ResourceArn: z.string().min(1).max(2048).regex( + new RegExp( + "^arn:aws(-[a-z]+)*:bedrock:[a-z0-9-]+:[0-9]{12}:(guardrail|guardrail-profile)/[a-z0-9]+$", + ), + ).describe("The ARN of the Bedrock Guardrail or Guardrail Profile resource"), + PolicyDocument: z.string().describe( + "The IAM policy document defining access permissions for the guardrail and guardrail profile resources", + ), +}); + +const StateSchema = z.object({ + ResourceArn: z.string(), + PolicyDocument: z.string().optional(), +}).passthrough(); + +type StateData = z.infer; + +const InputsSchema = z.object({ + ResourceArn: z.string().min(1).max(2048).regex( + new RegExp( + "^arn:aws(-[a-z]+)*:bedrock:[a-z0-9-]+:[0-9]{12}:(guardrail|guardrail-profile)/[a-z0-9]+$", + ), + ).describe("The ARN of the Bedrock Guardrail or Guardrail Profile resource") + .optional(), + PolicyDocument: z.string().describe( + "The IAM policy document defining access permissions for the guardrail and guardrail profile resources", + ).optional(), +}); + +export const model = { + type: "@swamp/aws/bedrock/resource-policy", + version: "2026.04.08.1", + globalArguments: GlobalArgsSchema, + inputsSchema: InputsSchema, + resources: { + state: { + description: "Bedrock ResourcePolicy resource state", + schema: StateSchema, + lifetime: "infinite", + garbageCollection: 10, + }, + }, + methods: { + create: { + description: "Create a Bedrock ResourcePolicy", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const desiredState: Record = {}; + for (const [key, value] of Object.entries(g)) { + if (value !== undefined) desiredState[key] = value; + } + const result = await createResource( + "AWS::Bedrock::ResourcePolicy", + desiredState, + ) as StateData; + const instanceName = + ((result.ResourceArn ?? g.ResourceArn)?.toString() ?? "current") + .replace(/[\/\\]/g, "_").replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + get: { + description: "Get a Bedrock ResourcePolicy", + arguments: z.object({ + identifier: z.string().describe( + "The primary identifier of the Bedrock ResourcePolicy", + ), + }), + execute: async (args: { identifier: string }, context: any) => { + const result = await readResource( + "AWS::Bedrock::ResourcePolicy", + args.identifier, + ) as StateData; + const instanceName = + ((result.ResourceArn ?? context.globalArgs.ResourceArn)?.toString() ?? + args.identifier).replace(/[\/\\]/g, "_").replace(/\.\./g, "_") + .replace(/\0/g, ""); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + update: { + description: "Update a Bedrock ResourcePolicy", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const instanceName = (g.ResourceArn?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const content = await context.dataRepository.getContent( + context.modelType, + context.modelId, + instanceName, + ); + if (!content) { + throw new Error("No existing state found - run create or get first"); + } + const existing = JSON.parse(new TextDecoder().decode(content)); + const identifier = existing.ResourceArn?.toString(); + if (!identifier) { + throw new Error("No identifier found in existing state"); + } + const currentState = await readResource( + "AWS::Bedrock::ResourcePolicy", + identifier, + ) as StateData; + const desiredState: Record = { ...currentState }; + for (const [key, value] of Object.entries(g)) { + if (value !== undefined) desiredState[key] = value; + } + const result = await updateResource( + "AWS::Bedrock::ResourcePolicy", + identifier, + currentState, + desiredState, + ["ResourceArn"], + ); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + delete: { + description: "Delete a Bedrock ResourcePolicy", + arguments: z.object({ + identifier: z.string().describe( + "The primary identifier of the Bedrock ResourcePolicy", + ), + }), + execute: async (args: { identifier: string }, context: any) => { + const { existed } = await deleteResource( + "AWS::Bedrock::ResourcePolicy", + args.identifier, + ); + const instanceName = + (context.globalArgs.ResourceArn?.toString() ?? args.identifier) + .replace(/[\/\\]/g, "_").replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource("state", instanceName, { + identifier: args.identifier, + existed, + status: existed ? "deleted" : "not_found", + deletedAt: new Date().toISOString(), + }); + return { dataHandles: [handle] }; + }, + }, + sync: { + description: "Sync Bedrock ResourcePolicy state from AWS", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const instanceName = (g.ResourceArn?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const content = await context.dataRepository.getContent( + context.modelType, + context.modelId, + instanceName, + ); + if (!content) { + throw new Error("No existing state found - run create or get first"); + } + const existing = JSON.parse(new TextDecoder().decode(content)); + const identifier = existing.ResourceArn?.toString(); + if (!identifier) { + throw new Error("No identifier found in existing state"); + } + try { + const result = await readResource( + "AWS::Bedrock::ResourcePolicy", + identifier, + ) as StateData; + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + } catch (error: unknown) { + if (isResourceNotFoundError(error)) { + const handle = await context.writeResource("state", instanceName, { + identifier, + status: "not_found", + syncedAt: new Date().toISOString(), + }); + return { dataHandles: [handle] }; + } + throw error; + } + }, + }, + }, +}; diff --git a/model/aws/bedrock/manifest.yaml b/model/aws/bedrock/manifest.yaml index a9b753b14..e756e731f 100644 --- a/model/aws/bedrock/manifest.yaml +++ b/model/aws/bedrock/manifest.yaml @@ -1,7 +1,7 @@ # Auto-generated manifest. Re-generate with the appropriate deno task. manifestVersion: 1 name: "@swamp/aws/bedrock" -version: "2026.04.03.2" +version: "2026.04.08.1" description: "AWS BEDROCK infrastructure models" labels: - aws @@ -9,7 +9,7 @@ labels: - cloud - infrastructure releaseNotes: | - - Updated: agent, agent_alias, application_inference_profile, automated_reasoning_policy, automated_reasoning_policy_version, blueprint, data_automation_project, data_source, flow, flow_alias, flow_version, guardrail, guardrail_version, intelligent_prompt_router, knowledge_base, prompt, prompt_version + - Added: data_automation_library, enforced_guardrail_configuration, resource_policy models: - agent.ts - agent_alias.ts @@ -17,8 +17,10 @@ models: - automated_reasoning_policy.ts - automated_reasoning_policy_version.ts - blueprint.ts + - data_automation_library.ts - data_automation_project.ts - data_source.ts + - enforced_guardrail_configuration.ts - flow.ts - flow_alias.ts - flow_version.ts @@ -28,6 +30,7 @@ models: - knowledge_base.ts - prompt.ts - prompt_version.ts + - resource_policy.ts additionalFiles: - LICENSE.txt - README.md diff --git a/model/aws/braket/LICENSE.txt b/model/aws/braket/LICENSE.txt new file mode 100644 index 000000000..6720f5e28 --- /dev/null +++ b/model/aws/braket/LICENSE.txt @@ -0,0 +1,14 @@ +Copyright (C) 2026 System Initiative, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . diff --git a/model/aws/braket/README.md b/model/aws/braket/README.md new file mode 100644 index 000000000..e5602da44 --- /dev/null +++ b/model/aws/braket/README.md @@ -0,0 +1,65 @@ +# @swamp/aws/braket + +Auto-generated [swamp](https://github.com/systeminit/swamp) extension models for +AWS BRAKET resources. + +Each model represents a single AWS resource (e.g., a VPC, an S3 bucket, an IAM +role). Models have **domain properties** that you configure (the desired state) +and **resource properties** that reflect the live state in AWS. Available +methods: + +- **create** — provision the resource in AWS using the configured properties +- **get** — fetch the current state of a specific resource by identifier +- **update** — apply property changes to an existing resource +- **delete** — remove the resource from AWS +- **sync** — refresh all resource properties from AWS + +Use `swamp model type describe @swamp/aws/braket/spending_limit` to see the full +list of configurable properties and available methods for this model. + +## Authentication + +These models use the AWS SDK v3 default credential chain. Credentials are +resolved in the following order: + +1. **Environment variables** — `AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY` + + optional `AWS_SESSION_TOKEN` +2. **SSO credentials** — `aws sso login` +3. **Shared credentials file** — `~/.aws/credentials` +4. **Shared config file** — `~/.aws/config` (profiles, `credential_process`, + SSO) +5. **ECS container credentials** — task IAM role +6. **EC2 instance metadata** — instance profile + +### Region + +The `AWS_REGION` environment variable controls which region resources are +created and managed in. Defaults to `us-east-1` if not set. + +### Setup + +```bash +export AWS_REGION=us-east-1 +export AWS_ACCESS_KEY_ID=AKIA... +export AWS_SECRET_ACCESS_KEY=wJal... +``` + +## Usage + +```bash +# Create a new spending_limit model +swamp model create @swamp/aws/braket/spending_limit my-spending_limit + +# Edit the model to configure its properties +swamp model edit my-spending_limit + +# Create the resource in AWS +swamp model method run my-spending_limit create + +# Sync current state from AWS +swamp model method run my-spending_limit sync +``` + +## License + +AGPLv3 — see [LICENSE.txt](./LICENSE.txt). diff --git a/model/aws/braket/deno.json b/model/aws/braket/deno.json new file mode 100644 index 000000000..15892302f --- /dev/null +++ b/model/aws/braket/deno.json @@ -0,0 +1,7 @@ +{ + "imports": { + "zod": "npm:zod@4.3.6", + "@aws-sdk/client-cloudcontrol": "npm:@aws-sdk/client-cloudcontrol@3.1021.0", + "fast-json-patch": "npm:fast-json-patch@3.1.1" + } +} diff --git a/model/aws/braket/deno.lock b/model/aws/braket/deno.lock new file mode 100644 index 000000000..ded86fbb9 --- /dev/null +++ b/model/aws/braket/deno.lock @@ -0,0 +1,777 @@ +{ + "version": "5", + "specifiers": { + "npm:@aws-sdk/client-cloudcontrol@3.1021.0": "3.1021.0", + "npm:fast-json-patch@3.1.1": "3.1.1", + "npm:zod@4.3.6": "4.3.6" + }, + "npm": { + "@aws-crypto/sha256-browser@5.2.0": { + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "dependencies": [ + "@aws-crypto/sha256-js", + "@aws-crypto/supports-web-crypto", + "@aws-crypto/util", + "@aws-sdk/types", + "@aws-sdk/util-locate-window", + "@smithy/util-utf8@2.3.0", + "tslib" + ] + }, + "@aws-crypto/sha256-js@5.2.0": { + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "dependencies": [ + "@aws-crypto/util", + "@aws-sdk/types", + "tslib" + ] + }, + "@aws-crypto/supports-web-crypto@5.2.0": { + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "dependencies": [ + "tslib" + ] + }, + "@aws-crypto/util@5.2.0": { + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dependencies": [ + "@aws-sdk/types", + "@smithy/util-utf8@2.3.0", + "tslib" + ] + }, + "@aws-sdk/client-cloudcontrol@3.1021.0": { + "integrity": "sha512-VbrIC3iT4OveHdkjYdMdwGk60YNOmN0OsL1QEuEjOwUmjq1aYRzgtjNb9fGR9a8CWhGA7yjqWDaUeNJ+wUGzMw==", + "dependencies": [ + "@aws-crypto/sha256-browser", + "@aws-crypto/sha256-js", + "@aws-sdk/core", + "@aws-sdk/credential-provider-node", + "@aws-sdk/middleware-host-header", + "@aws-sdk/middleware-logger", + "@aws-sdk/middleware-recursion-detection", + "@aws-sdk/middleware-user-agent", + "@aws-sdk/region-config-resolver", + "@aws-sdk/types", + "@aws-sdk/util-endpoints", + "@aws-sdk/util-user-agent-browser", + "@aws-sdk/util-user-agent-node", + "@smithy/config-resolver", + "@smithy/core", + "@smithy/fetch-http-handler", + "@smithy/hash-node", + "@smithy/invalid-dependency", + "@smithy/middleware-content-length", + "@smithy/middleware-endpoint", + "@smithy/middleware-retry", + "@smithy/middleware-serde", + "@smithy/middleware-stack", + "@smithy/node-config-provider", + "@smithy/node-http-handler", + "@smithy/protocol-http", + "@smithy/smithy-client", + "@smithy/types", + "@smithy/url-parser", + "@smithy/util-base64", + "@smithy/util-body-length-browser", + "@smithy/util-body-length-node", + "@smithy/util-defaults-mode-browser", + "@smithy/util-defaults-mode-node", + "@smithy/util-endpoints", + "@smithy/util-middleware", + "@smithy/util-retry", + "@smithy/util-utf8@4.2.2", + "@smithy/util-waiter", + "tslib" + ] + }, + "@aws-sdk/core@3.973.27": { + "integrity": "sha512-CUZ5m8hwMCH6OYI4Li/WgMfIEx10Q2PLI9Y3XOUTPGZJ53aZ0007jCv+X/ywsaERyKPdw5MRZWk877roQksQ4A==", + "dependencies": [ + "@aws-sdk/types", + "@aws-sdk/xml-builder", + "@smithy/core", + "@smithy/node-config-provider", + "@smithy/property-provider", + "@smithy/protocol-http", + "@smithy/signature-v4", + "@smithy/smithy-client", + "@smithy/types", + "@smithy/util-base64", + "@smithy/util-middleware", + "@smithy/util-utf8@4.2.2", + "tslib" + ] + }, + "@aws-sdk/credential-provider-env@3.972.25": { + "integrity": "sha512-6QfI0wv4jpG5CrdO/AO0JfZ2ux+tKwJPrUwmvxXF50vI5KIypKVGNF6b4vlkYEnKumDTI1NX2zUBi8JoU5QU3A==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/types", + "@smithy/property-provider", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/credential-provider-http@3.972.27": { + "integrity": "sha512-3V3Usj9Gs93h865DqN4M2NWJhC5kXU9BvZskfN3+69omuYlE3TZxOEcVQtBGLOloJB7BVfJKXVLqeNhOzHqSlQ==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/types", + "@smithy/fetch-http-handler", + "@smithy/node-http-handler", + "@smithy/property-provider", + "@smithy/protocol-http", + "@smithy/smithy-client", + "@smithy/types", + "@smithy/util-stream", + "tslib" + ] + }, + "@aws-sdk/credential-provider-ini@3.972.29": { + "integrity": "sha512-SiBuAnXecCbT/OpAf3vqyI/AVE3mTaYr9ShXLybxZiPLBiPCCOIWSGAtYYGQWMRvobBTiqOewaB+wcgMMZI2Aw==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/credential-provider-env", + "@aws-sdk/credential-provider-http", + "@aws-sdk/credential-provider-login", + "@aws-sdk/credential-provider-process", + "@aws-sdk/credential-provider-sso", + "@aws-sdk/credential-provider-web-identity", + "@aws-sdk/nested-clients", + "@aws-sdk/types", + "@smithy/credential-provider-imds", + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/credential-provider-login@3.972.29": { + "integrity": "sha512-OGOslTbOlxXexKMqhxCEbBQbUIfuhGxU5UXw3Fm56ypXHvrXH4aTt/xb5Y884LOoteP1QST1lVZzHfcTnWhiPQ==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/nested-clients", + "@aws-sdk/types", + "@smithy/property-provider", + "@smithy/protocol-http", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/credential-provider-node@3.972.30": { + "integrity": "sha512-FMnAnWxc8PG+ZrZ2OBKzY4luCUJhe9CG0B9YwYr4pzrYGLXBS2rl+UoUvjGbAwiptxRL6hyA3lFn03Bv1TLqTw==", + "dependencies": [ + "@aws-sdk/credential-provider-env", + "@aws-sdk/credential-provider-http", + "@aws-sdk/credential-provider-ini", + "@aws-sdk/credential-provider-process", + "@aws-sdk/credential-provider-sso", + "@aws-sdk/credential-provider-web-identity", + "@aws-sdk/types", + "@smithy/credential-provider-imds", + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/credential-provider-process@3.972.25": { + "integrity": "sha512-HR7ynNRdNhNsdVCOCegy1HsfsRzozCOPtD3RzzT1JouuaHobWyRfJzCBue/3jP7gECHt+kQyZUvwg/cYLWurNQ==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/types", + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/credential-provider-sso@3.972.29": { + "integrity": "sha512-HWv4SEq3jZDYPlwryZVef97+U8CxxRos5mK8sgGO1dQaFZpV5giZLzqGE5hkDmh2csYcBO2uf5XHjPTpZcJlig==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/nested-clients", + "@aws-sdk/token-providers", + "@aws-sdk/types", + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/credential-provider-web-identity@3.972.29": { + "integrity": "sha512-PdMBza1WEKEUPFEmMGCfnU2RYCz9MskU2e8JxjyUOsMKku7j9YaDKvbDi2dzC0ihFoM6ods2SbhfAAro+Gwlew==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/nested-clients", + "@aws-sdk/types", + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/middleware-host-header@3.972.9": { + "integrity": "sha512-je5vRdNw4SkuTnmRbFZLdye4sQ0faLt8kwka5wnnSU30q1mHO4X+idGEJOOE+Tn1ME7Oryn05xxkDvIb3UaLaQ==", + "dependencies": [ + "@aws-sdk/types", + "@smithy/protocol-http", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/middleware-logger@3.972.9": { + "integrity": "sha512-HsVgDrruhqI28RkaXALm8grJ7Agc1wF6Et0xh6pom8NdO2VdO/SD9U/tPwUjewwK/pVoka+EShBxyCvgsPCtog==", + "dependencies": [ + "@aws-sdk/types", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/middleware-recursion-detection@3.972.10": { + "integrity": "sha512-RVQQbq5orQ/GHUnXvqEOj2HHPBJm+mM+ySwZKS5UaLBwra5ugRtiH09PLUoOZRl7a1YzaOzXSuGbn9iD5j60WQ==", + "dependencies": [ + "@aws-sdk/types", + "@aws/lambda-invoke-store", + "@smithy/protocol-http", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/middleware-user-agent@3.972.29": { + "integrity": "sha512-f/sIRzuTfEjg6NsbMYvye2VsmnQoNgntntleQyx5uGacUYzszbfIlO3GcI6G6daWUmTm0IDZc11qMHWwF0o0mQ==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/types", + "@aws-sdk/util-endpoints", + "@smithy/core", + "@smithy/protocol-http", + "@smithy/types", + "@smithy/util-retry", + "tslib" + ] + }, + "@aws-sdk/nested-clients@3.996.19": { + "integrity": "sha512-uFkmCDXvmQYLanlYdOFS0+MQWkrj9wPMt/ZCc/0J0fjPim6F5jBVBmEomvGY/j77ILW6GTPwN22Jc174Mhkw6Q==", + "dependencies": [ + "@aws-crypto/sha256-browser", + "@aws-crypto/sha256-js", + "@aws-sdk/core", + "@aws-sdk/middleware-host-header", + "@aws-sdk/middleware-logger", + "@aws-sdk/middleware-recursion-detection", + "@aws-sdk/middleware-user-agent", + "@aws-sdk/region-config-resolver", + "@aws-sdk/types", + "@aws-sdk/util-endpoints", + "@aws-sdk/util-user-agent-browser", + "@aws-sdk/util-user-agent-node", + "@smithy/config-resolver", + "@smithy/core", + "@smithy/fetch-http-handler", + "@smithy/hash-node", + "@smithy/invalid-dependency", + "@smithy/middleware-content-length", + "@smithy/middleware-endpoint", + "@smithy/middleware-retry", + "@smithy/middleware-serde", + "@smithy/middleware-stack", + "@smithy/node-config-provider", + "@smithy/node-http-handler", + "@smithy/protocol-http", + "@smithy/smithy-client", + "@smithy/types", + "@smithy/url-parser", + "@smithy/util-base64", + "@smithy/util-body-length-browser", + "@smithy/util-body-length-node", + "@smithy/util-defaults-mode-browser", + "@smithy/util-defaults-mode-node", + "@smithy/util-endpoints", + "@smithy/util-middleware", + "@smithy/util-retry", + "@smithy/util-utf8@4.2.2", + "tslib" + ] + }, + "@aws-sdk/region-config-resolver@3.972.11": { + "integrity": "sha512-6Q8B1dcx6BBqUTY1Mc/eROKA0FImEEY5VPSd6AGPEUf0ErjExz4snVqa9kNJSoVDV1rKaNf3qrWojgcKW+SdDg==", + "dependencies": [ + "@aws-sdk/types", + "@smithy/config-resolver", + "@smithy/node-config-provider", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/token-providers@3.1026.0": { + "integrity": "sha512-Ieq/HiRrbEtrYP387Nes0XlR7H1pJiJOZKv+QyQzMYpvTiDs0VKy2ZB3E2Zf+aFovWmeE7lRE4lXyF7dYM6GgA==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/nested-clients", + "@aws-sdk/types", + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/types@3.973.7": { + "integrity": "sha512-reXRwoJ6CfChoqAsBszUYajAF8Z2LRE+CRcKocvFSMpIiLOtYU3aJ9trmn6VVPAzbbY5LXF+FfmUslbXk1SYFg==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/util-endpoints@3.996.6": { + "integrity": "sha512-2nUQ+2ih7CShuKHpGSIYvvAIOHy52dOZguYG36zptBukhw6iFwcvGfG0tes0oZFWQqEWvgZe9HLWaNlvXGdOrg==", + "dependencies": [ + "@aws-sdk/types", + "@smithy/types", + "@smithy/url-parser", + "@smithy/util-endpoints", + "tslib" + ] + }, + "@aws-sdk/util-locate-window@3.965.5": { + "integrity": "sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==", + "dependencies": [ + "tslib" + ] + }, + "@aws-sdk/util-user-agent-browser@3.972.9": { + "integrity": "sha512-sn/LMzTbGjYqCCF24390WxPd6hkpoSptiUn5DzVp4cD71yqw+yGEGm1YCxyEoPXyc8qciM8UzLJcZBFslxo5Uw==", + "dependencies": [ + "@aws-sdk/types", + "@smithy/types", + "bowser", + "tslib" + ] + }, + "@aws-sdk/util-user-agent-node@3.973.15": { + "integrity": "sha512-fYn3s9PtKdgQkczGZCFMgkNEe8aq1JCVbnRqjqN9RSVW43xn2RV9xdcZ3z01a48Jpkuh/xCmBKJxdLOo4Ozg7w==", + "dependencies": [ + "@aws-sdk/middleware-user-agent", + "@aws-sdk/types", + "@smithy/node-config-provider", + "@smithy/types", + "@smithy/util-config-provider", + "tslib" + ] + }, + "@aws-sdk/xml-builder@3.972.17": { + "integrity": "sha512-Ra7hjqAZf1OXRRMueB13qex7mFJRDK/pgCvdSFemXBT8KCGnQDPoKzHY1SjN+TjJVmnpSF14W5tJ1vDamFu+Gg==", + "dependencies": [ + "@smithy/types", + "fast-xml-parser", + "tslib" + ] + }, + "@aws/lambda-invoke-store@0.2.4": { + "integrity": "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==" + }, + "@smithy/config-resolver@4.4.14": { + "integrity": "sha512-N55f8mPEccpzKetUagdvmAy8oohf0J5cuj9jLI1TaSceRlq0pJsIZepY3kmAXAhyxqXPV6hDerDQhqQPKWgAoQ==", + "dependencies": [ + "@smithy/node-config-provider", + "@smithy/types", + "@smithy/util-config-provider", + "@smithy/util-endpoints", + "@smithy/util-middleware", + "tslib" + ] + }, + "@smithy/core@3.23.14": { + "integrity": "sha512-vJ0IhpZxZAkFYOegMKSrxw7ujhhT2pass/1UEcZ4kfl5srTAqtPU5I7MdYQoreVas3204ykCiNhY1o7Xlz6Yyg==", + "dependencies": [ + "@smithy/protocol-http", + "@smithy/types", + "@smithy/url-parser", + "@smithy/util-base64", + "@smithy/util-body-length-browser", + "@smithy/util-middleware", + "@smithy/util-stream", + "@smithy/util-utf8@4.2.2", + "@smithy/uuid", + "tslib" + ] + }, + "@smithy/credential-provider-imds@4.2.13": { + "integrity": "sha512-wboCPijzf6RJKLOvnjDAiBxGSmSnGXj35o5ZAWKDaHa/cvQ5U3ZJ13D4tMCE8JG4dxVAZFy/P0x/V9CwwdfULQ==", + "dependencies": [ + "@smithy/node-config-provider", + "@smithy/property-provider", + "@smithy/types", + "@smithy/url-parser", + "tslib" + ] + }, + "@smithy/fetch-http-handler@5.3.16": { + "integrity": "sha512-nYDRUIvNd4mFmuXraRWt6w5UsZTNqtj4hXJA/iiOD4tuseIdLP9Lq38teH/SZTcIFCa2f+27o7hYpIsWktJKEQ==", + "dependencies": [ + "@smithy/protocol-http", + "@smithy/querystring-builder", + "@smithy/types", + "@smithy/util-base64", + "tslib" + ] + }, + "@smithy/hash-node@4.2.13": { + "integrity": "sha512-4/oy9h0jjmY80a2gOIo75iLl8TOPhmtx4E2Hz+PfMjvx/vLtGY4TMU/35WRyH2JHPfT5CVB38u4JRow7gnmzJA==", + "dependencies": [ + "@smithy/types", + "@smithy/util-buffer-from@4.2.2", + "@smithy/util-utf8@4.2.2", + "tslib" + ] + }, + "@smithy/invalid-dependency@4.2.13": { + "integrity": "sha512-jvC0RB/8BLj2SMIkY0Npl425IdnxZJxInpZJbu563zIRnVjpDMXevU3VMCRSabaLB0kf/eFIOusdGstrLJ8IDg==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/is-array-buffer@2.2.0": { + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/is-array-buffer@4.2.2": { + "integrity": "sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/middleware-content-length@4.2.13": { + "integrity": "sha512-IPMLm/LE4AZwu6qiE8Rr8vJsWhs9AtOdySRXrOM7xnvclp77Tyh7hMs/FRrMf26kgIe67vFJXXOSmVxS7oKeig==", + "dependencies": [ + "@smithy/protocol-http", + "@smithy/types", + "tslib" + ] + }, + "@smithy/middleware-endpoint@4.4.29": { + "integrity": "sha512-R9Q/58U+qBiSARGWbAbFLczECg/RmysRksX6Q8BaQEpt75I7LI6WGDZnjuC9GXSGKljEbA7N118LhGaMbfrTXw==", + "dependencies": [ + "@smithy/core", + "@smithy/middleware-serde", + "@smithy/node-config-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "@smithy/url-parser", + "@smithy/util-middleware", + "tslib" + ] + }, + "@smithy/middleware-retry@4.5.0": { + "integrity": "sha512-/NzISn4grj/BRFVua/xnQwF+7fakYZgimpw2dfmlPgcqecBMKxpB9g5mLYRrmBD5OrPoODokw4Vi1hrSR4zRyw==", + "dependencies": [ + "@smithy/core", + "@smithy/node-config-provider", + "@smithy/protocol-http", + "@smithy/service-error-classification", + "@smithy/smithy-client", + "@smithy/types", + "@smithy/util-middleware", + "@smithy/util-retry", + "@smithy/uuid", + "tslib" + ] + }, + "@smithy/middleware-serde@4.2.17": { + "integrity": "sha512-0T2mcaM6v9W1xku86Dk0bEW7aEseG6KenFkPK98XNw0ZhOqOiD1MrMsdnQw9QsL3/Oa85T53iSMlm0SZdSuIEQ==", + "dependencies": [ + "@smithy/core", + "@smithy/protocol-http", + "@smithy/types", + "tslib" + ] + }, + "@smithy/middleware-stack@4.2.13": { + "integrity": "sha512-g72jN/sGDLyTanrCLH9fhg3oysO3f7tQa6eWWsMyn2BiYNCgjF24n4/I9wff/5XidFvjj9ilipAoQrurTUrLvw==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/node-config-provider@4.3.13": { + "integrity": "sha512-iGxQ04DsKXLckbgnX4ipElrOTk+IHgTyu0q0WssZfYhDm9CQWHmu6cOeI5wmWRxpXbBDhIIfXMWz5tPEtcVqbw==", + "dependencies": [ + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@smithy/node-http-handler@4.5.2": { + "integrity": "sha512-/oD7u8M0oj2ZTFw7GkuuHWpIxtWdLlnyNkbrWcyVYhd5RJNDuczdkb0wfnQICyNFrVPlr8YHOhamjNy3zidhmA==", + "dependencies": [ + "@smithy/protocol-http", + "@smithy/querystring-builder", + "@smithy/types", + "tslib" + ] + }, + "@smithy/property-provider@4.2.13": { + "integrity": "sha512-bGzUCthxRmezuxkbu9wD33wWg9KX3hJpCXpQ93vVkPrHn9ZW6KNNdY5xAUWNuRCwQ+VyboFuWirG1lZhhkcyRQ==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/protocol-http@5.3.13": { + "integrity": "sha512-+HsmuJUF4u8POo6s8/a2Yb/AQ5t/YgLovCuHF9oxbocqv+SZ6gd8lC2duBFiCA/vFHoHQhoq7QjqJqZC6xOxxg==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/querystring-builder@4.2.13": { + "integrity": "sha512-tG4aOYFCZdPMjbgfhnIQ322H//ojujldp1SrHPHpBSb3NqgUp3dwiUGRJzie87hS1DYwWGqDuPaowoDF+rYCbQ==", + "dependencies": [ + "@smithy/types", + "@smithy/util-uri-escape", + "tslib" + ] + }, + "@smithy/querystring-parser@4.2.13": { + "integrity": "sha512-hqW3Q4P+CDzUyQ87GrboGMeD7XYNMOF+CuTwu936UQRB/zeYn3jys8C3w+wMkDfY7CyyyVwZQ5cNFoG0x1pYmA==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/service-error-classification@4.2.13": { + "integrity": "sha512-a0s8XZMfOC/qpqq7RCPvJlk93rWFrElH6O++8WJKz0FqnA4Y7fkNi/0mnGgSH1C4x6MFsuBA8VKu4zxFrMe5Vw==", + "dependencies": [ + "@smithy/types" + ] + }, + "@smithy/shared-ini-file-loader@4.4.8": { + "integrity": "sha512-VZCZx2bZasxdqxVgEAhREvDSlkatTPnkdWy1+Kiy8w7kYPBosW0V5IeDwzDUMvWBt56zpK658rx1cOBFOYaPaw==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/signature-v4@5.3.13": { + "integrity": "sha512-YpYSyM0vMDwKbHD/JA7bVOF6kToVRpa+FM5ateEVRpsTNu564g1muBlkTubXhSKKYXInhpADF46FPyrZcTLpXg==", + "dependencies": [ + "@smithy/is-array-buffer@4.2.2", + "@smithy/protocol-http", + "@smithy/types", + "@smithy/util-hex-encoding", + "@smithy/util-middleware", + "@smithy/util-uri-escape", + "@smithy/util-utf8@4.2.2", + "tslib" + ] + }, + "@smithy/smithy-client@4.12.9": { + "integrity": "sha512-ovaLEcTU5olSeHcRXcxV6viaKtpkHZumn6Ps0yn7dRf2rRSfy794vpjOtrWDO0d1auDSvAqxO+lyhERSXQ03EQ==", + "dependencies": [ + "@smithy/core", + "@smithy/middleware-endpoint", + "@smithy/middleware-stack", + "@smithy/protocol-http", + "@smithy/types", + "@smithy/util-stream", + "tslib" + ] + }, + "@smithy/types@4.14.0": { + "integrity": "sha512-OWgntFLW88kx2qvf/c/67Vno1yuXm/f9M7QFAtVkkO29IJXGBIg0ycEaBTH0kvCtwmvZxRujrgP5a86RvsXJAQ==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/url-parser@4.2.13": { + "integrity": "sha512-2G03yoboIRZlZze2+PT4GZEjgwQsJjUgn6iTsvxA02bVceHR6vp4Cuk7TUnPFWKF+ffNUk3kj4COwkENS2K3vw==", + "dependencies": [ + "@smithy/querystring-parser", + "@smithy/types", + "tslib" + ] + }, + "@smithy/util-base64@4.3.2": { + "integrity": "sha512-XRH6b0H/5A3SgblmMa5ErXQ2XKhfbQB+Fm/oyLZ2O2kCUrwgg55bU0RekmzAhuwOjA9qdN5VU2BprOvGGUkOOQ==", + "dependencies": [ + "@smithy/util-buffer-from@4.2.2", + "@smithy/util-utf8@4.2.2", + "tslib" + ] + }, + "@smithy/util-body-length-browser@4.2.2": { + "integrity": "sha512-JKCrLNOup3OOgmzeaKQwi4ZCTWlYR5H4Gm1r2uTMVBXoemo1UEghk5vtMi1xSu2ymgKVGW631e2fp9/R610ZjQ==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/util-body-length-node@4.2.3": { + "integrity": "sha512-ZkJGvqBzMHVHE7r/hcuCxlTY8pQr1kMtdsVPs7ex4mMU+EAbcXppfo5NmyxMYi2XU49eqaz56j2gsk4dHHPG/g==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/util-buffer-from@2.2.0": { + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dependencies": [ + "@smithy/is-array-buffer@2.2.0", + "tslib" + ] + }, + "@smithy/util-buffer-from@4.2.2": { + "integrity": "sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q==", + "dependencies": [ + "@smithy/is-array-buffer@4.2.2", + "tslib" + ] + }, + "@smithy/util-config-provider@4.2.2": { + "integrity": "sha512-dWU03V3XUprJwaUIFVv4iOnS1FC9HnMHDfUrlNDSh4315v0cWyaIErP8KiqGVbf5z+JupoVpNM7ZB3jFiTejvQ==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/util-defaults-mode-browser@4.3.45": { + "integrity": "sha512-ag9sWc6/nWZAuK3Wm9KlFJUnRkXLrXn33RFjIAmCTFThqLHY+7wCst10BGq56FxslsDrjhSie46c8OULS+BiIw==", + "dependencies": [ + "@smithy/property-provider", + "@smithy/smithy-client", + "@smithy/types", + "tslib" + ] + }, + "@smithy/util-defaults-mode-node@4.2.49": { + "integrity": "sha512-jlN6vHwE8gY5AfiFBavtD3QtCX2f7lM3BKkz7nFKSNfFR5nXLXLg6sqXTJEEyDwtxbztIDBQCfjsGVXlIru2lQ==", + "dependencies": [ + "@smithy/config-resolver", + "@smithy/credential-provider-imds", + "@smithy/node-config-provider", + "@smithy/property-provider", + "@smithy/smithy-client", + "@smithy/types", + "tslib" + ] + }, + "@smithy/util-endpoints@3.3.4": { + "integrity": "sha512-BKoR/ubPp9KNKFxPpg1J28N1+bgu8NGAtJblBP7yHy8yQPBWhIAv9+l92SlQLpolGm71CVO+btB60gTgzT0wog==", + "dependencies": [ + "@smithy/node-config-provider", + "@smithy/types", + "tslib" + ] + }, + "@smithy/util-hex-encoding@4.2.2": { + "integrity": "sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/util-middleware@4.2.13": { + "integrity": "sha512-GTooyrlmRTqvUen4eK7/K1p6kryF7bnDfq6XsAbIsf2mo51B/utaH+XThY6dKgNCWzMAaH/+OLmqaBuLhLWRow==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/util-retry@4.3.0": { + "integrity": "sha512-tSOPQNT/4KfbvqeMovWC3g23KSYy8czHd3tlN+tOYVNIDLSfxIsrPJihYi5TpNcoV789KWtgChUVedh2y6dDPg==", + "dependencies": [ + "@smithy/service-error-classification", + "@smithy/types", + "tslib" + ] + }, + "@smithy/util-stream@4.5.22": { + "integrity": "sha512-3H8iq/0BfQjUs2/4fbHZ9aG9yNzcuZs24LPkcX1Q7Z+qpqaGM8+qbGmE8zo9m2nCRgamyvS98cHdcWvR6YUsew==", + "dependencies": [ + "@smithy/fetch-http-handler", + "@smithy/node-http-handler", + "@smithy/types", + "@smithy/util-base64", + "@smithy/util-buffer-from@4.2.2", + "@smithy/util-hex-encoding", + "@smithy/util-utf8@4.2.2", + "tslib" + ] + }, + "@smithy/util-uri-escape@4.2.2": { + "integrity": "sha512-2kAStBlvq+lTXHyAZYfJRb/DfS3rsinLiwb+69SstC9Vb0s9vNWkRwpnj918Pfi85mzi42sOqdV72OLxWAISnw==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/util-utf8@2.3.0": { + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dependencies": [ + "@smithy/util-buffer-from@2.2.0", + "tslib" + ] + }, + "@smithy/util-utf8@4.2.2": { + "integrity": "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw==", + "dependencies": [ + "@smithy/util-buffer-from@4.2.2", + "tslib" + ] + }, + "@smithy/util-waiter@4.2.15": { + "integrity": "sha512-oUt9o7n8hBv3BL56sLSneL0XeigZSuem0Hr78JaoK33D9oKieyCvVP8eTSe3j7g2mm/S1DvzxKieG7JEWNJUNg==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/uuid@1.1.2": { + "integrity": "sha512-O/IEdcCUKkubz60tFbGA7ceITTAJsty+lBjNoorP4Z6XRqaFb/OjQjZODophEcuq68nKm6/0r+6/lLQ+XVpk8g==", + "dependencies": [ + "tslib" + ] + }, + "bowser@2.14.1": { + "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==" + }, + "fast-json-patch@3.1.1": { + "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==" + }, + "fast-xml-builder@1.1.4": { + "integrity": "sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg==", + "dependencies": [ + "path-expression-matcher" + ] + }, + "fast-xml-parser@5.5.8": { + "integrity": "sha512-Z7Fh2nVQSb2d+poDViM063ix2ZGt9jmY1nWhPfHBOK2Hgnb/OW3P4Et3P/81SEej0J7QbWtJqxO05h8QYfK7LQ==", + "dependencies": [ + "fast-xml-builder", + "path-expression-matcher", + "strnum" + ], + "bin": true + }, + "path-expression-matcher@1.4.0": { + "integrity": "sha512-s4DQMxIdhj3jLFWd9LxHOplj4p9yQ4ffMGowFf3cpEgrrJjEhN0V5nxw4Ye1EViAGDoL4/1AeO6qHpqYPOzE4Q==" + }, + "strnum@2.2.3": { + "integrity": "sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg==" + }, + "tslib@2.8.1": { + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "zod@4.3.6": { + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==" + } + }, + "workspace": { + "dependencies": [ + "npm:@aws-sdk/client-cloudcontrol@3.1021.0", + "npm:fast-json-patch@3.1.1", + "npm:zod@4.3.6" + ] + } +} diff --git a/model/aws/braket/extensions/models/_lib/aws.ts b/model/aws/braket/extensions/models/_lib/aws.ts new file mode 100644 index 000000000..8a0d63606 --- /dev/null +++ b/model/aws/braket/extensions/models/_lib/aws.ts @@ -0,0 +1,395 @@ +// Auto-generated shared helper for AWS CloudControl extension models. +// Do not edit manually. Re-generate with: deno task generate:aws + +import { + CloudControlClient, + CreateResourceCommand, + DeleteResourceCommand, + GetResourceCommand, + GetResourceRequestStatusCommand, + UpdateResourceCommand, +} from "@aws-sdk/client-cloudcontrol"; +import jsonpatch from "fast-json-patch"; + +function createClient(): CloudControlClient { + return new CloudControlClient({ + region: Deno.env.get("AWS_REGION") || "us-east-1", + }); +} + +function delay(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +function isThrottlingError(error: unknown): boolean { + const msg = error instanceof Error ? error.message : String(error); + const name = error instanceof Error ? error.name : ""; + return ( + msg.includes("Throttling") || + msg.includes("TooManyRequests") || + msg.includes("RequestLimitExceeded") || + name === "ThrottlingException" + ); +} + +export function isResourceNotFoundError(error: unknown): boolean { + const msg = error instanceof Error ? error.message : String(error); + const name = error instanceof Error ? error.name : ""; + return ( + msg.includes("was not found") || + msg.includes("does not exist") || + name === "ResourceNotFoundException" + ); +} + +async function withRetry( + operation: () => Promise, + operationName: string, + maxAttempts = 20, +): Promise { + const baseDelay = 1000; + const maxDelay = 90000; + + for (let attempt = 0; attempt < maxAttempts; attempt++) { + try { + return await operation(); + } catch (error) { + if (isThrottlingError(error) && attempt < maxAttempts - 1) { + const exponentialDelay = Math.min( + baseDelay * Math.pow(2, attempt), + maxDelay, + ); + const jitter = Math.random() * 0.3 * exponentialDelay; + console.log( + `[${operationName}] Throttled on attempt ${attempt + 1}, waiting ${ + Math.round(exponentialDelay + jitter) + }ms`, + ); + await delay(exponentialDelay + jitter); + continue; + } + throw error; + } + } + throw new Error(`${operationName} failed after ${maxAttempts} attempts`); +} + +async function pollOperationStatus( + client: CloudControlClient, + requestToken: string, + operationName: string, +): Promise<{ status: string; identifier?: string; message?: string }> { + const baseDelay = 1000; + const maxDelay = 90000; + + for (let attempt = 0; attempt < 60; attempt++) { + const response = await withRetry( + () => + client.send( + new GetResourceRequestStatusCommand({ + RequestToken: requestToken, + }), + ), + `${operationName} status poll`, + ); + + const status = response.ProgressEvent?.OperationStatus; + if (status === "SUCCESS") { + return { + status: "SUCCESS", + identifier: response.ProgressEvent?.Identifier, + }; + } + if (status === "FAILED") { + return { + status: "FAILED", + message: response.ProgressEvent?.StatusMessage || + response.ProgressEvent?.ErrorCode, + }; + } + if (status === "CANCEL_COMPLETE") { + return { + status: "CANCEL_COMPLETE", + message: "Operation cancelled by API or AWS", + }; + } + + const exponentialDelay = Math.min( + baseDelay * Math.pow(2, attempt), + maxDelay, + ); + const jitter = Math.random() * 0.3 * exponentialDelay; + console.log( + `[${operationName}] IN_PROGRESS, waiting ${ + Math.round(exponentialDelay + jitter) + }ms (poll ${attempt + 1})`, + ); + await delay(exponentialDelay + jitter); + } + + throw new Error(`${operationName} timed out after polling`); +} + +/** + * Create an AWS resource via CloudControl API. + * Sends CreateResourceCommand, polls until complete, then reads the resource. + * Returns the resource properties. + */ +export async function createResource( + typeName: string, + desiredState: Record, +): Promise> { + const client = createClient(); + + console.log(`[CREATE] Starting create for ${typeName}`); + + const response = await withRetry( + () => + client.send( + new CreateResourceCommand({ + TypeName: typeName, + DesiredState: JSON.stringify(desiredState), + }), + ), + `${typeName} create`, + ); + + if (!response.ProgressEvent?.RequestToken) { + throw new Error(`${typeName} creation failed: no request token returned`); + } + + const requestToken = response.ProgressEvent.RequestToken; + console.log(`[CREATE] Got request token: ${requestToken}`); + + const pollResult = await pollOperationStatus( + client, + requestToken, + `${typeName} create`, + ); + + if (pollResult.status === "FAILED") { + throw new Error( + `${typeName} creation failed: ${pollResult.message || "Unknown error"}`, + ); + } + if (pollResult.status === "CANCEL_COMPLETE") { + throw new Error( + `${typeName} creation cancelled: ${pollResult.message}`, + ); + } + + const identifier = pollResult.identifier; + if (!identifier) { + throw new Error( + `${typeName} creation succeeded but no identifier returned`, + ); + } + + console.log(`[CREATE] Success, fetching resource ${identifier}`); + + const getResponse = await withRetry( + () => + client.send( + new GetResourceCommand({ + TypeName: typeName, + Identifier: identifier, + }), + ), + `${typeName} create get-resource`, + ); + + if (!getResponse.ResourceDescription?.Properties) { + throw new Error(`Failed to get ${typeName} details after creation`); + } + + return JSON.parse(getResponse.ResourceDescription.Properties); +} + +/** + * Read an AWS resource via CloudControl API. + * Returns the resource properties, or throws if not found. + */ +export async function readResource( + typeName: string, + identifier: string, +): Promise> { + const client = createClient(); + + console.log(`[READ] Fetching ${typeName} identifier: ${identifier}`); + + const response = await withRetry( + () => + client.send( + new GetResourceCommand({ + TypeName: typeName, + Identifier: identifier, + }), + ), + `${typeName} read`, + ); + + if (!response.ResourceDescription?.Properties) { + throw new Error(`Failed to get ${typeName} details`); + } + + return JSON.parse(response.ResourceDescription.Properties); +} + +/** + * Update an AWS resource via CloudControl API. + * Reads current state, computes JSON patch (filtering createOnlyProperties), + * sends UpdateResourceCommand, polls, then reads the updated resource. + */ +export async function updateResource( + typeName: string, + identifier: string, + currentState: Record, + desiredState: Record, + createOnlyProperties?: string[], +): Promise> { + const client = createClient(); + const createOnlySet = new Set(createOnlyProperties ?? []); + + console.log( + `[UPDATE] Starting update for ${typeName} identifier: ${identifier}`, + ); + + // Compute JSON patch, filtering out create-only properties + const rawPatch = jsonpatch.compare(currentState, desiredState); + const patch = rawPatch.filter((op: { path: string }) => { + const topLevelProp = op.path.split("/")[1]; + if (topLevelProp && createOnlySet.has(topLevelProp)) { + console.log(`[UPDATE] Skipping create-only property: ${topLevelProp}`); + return false; + } + return true; + }); + + if (patch.length === 0) { + console.log(`[UPDATE] No changes detected, returning current state`); + return currentState; + } + + console.log(`[UPDATE] Applying ${patch.length} patch operations`); + + const response = await withRetry( + () => + client.send( + new UpdateResourceCommand({ + TypeName: typeName, + Identifier: identifier, + PatchDocument: JSON.stringify(patch), + }), + ), + `${typeName} update`, + ); + + if (!response.ProgressEvent?.RequestToken) { + throw new Error(`${typeName} update failed: no request token returned`); + } + + const requestToken = response.ProgressEvent.RequestToken; + console.log(`[UPDATE] Got request token: ${requestToken}`); + + const pollResult = await pollOperationStatus( + client, + requestToken, + `${typeName} update`, + ); + + if (pollResult.status === "FAILED") { + throw new Error( + `${typeName} update failed: ${pollResult.message || "Unknown error"}`, + ); + } + if (pollResult.status === "CANCEL_COMPLETE") { + throw new Error(`${typeName} update cancelled: ${pollResult.message}`); + } + + const resultIdentifier = pollResult.identifier || identifier; + console.log(`[UPDATE] Success, fetching resource ${resultIdentifier}`); + + const getResponse = await withRetry( + () => + client.send( + new GetResourceCommand({ + TypeName: typeName, + Identifier: resultIdentifier, + }), + ), + `${typeName} update get-resource`, + ); + + if (!getResponse.ResourceDescription?.Properties) { + throw new Error(`Failed to get ${typeName} details after update`); + } + + return JSON.parse(getResponse.ResourceDescription.Properties); +} + +/** + * Delete an AWS resource via CloudControl API. + * Returns { existed: true } on success, { existed: false } if already gone. + */ +export async function deleteResource( + typeName: string, + identifier: string, +): Promise<{ existed: boolean }> { + const client = createClient(); + + console.log( + `[DELETE] Starting delete for ${typeName} identifier: ${identifier}`, + ); + + try { + const response = await withRetry( + () => + client.send( + new DeleteResourceCommand({ + TypeName: typeName, + Identifier: identifier, + }), + ), + `${typeName} delete`, + ); + + if (!response.ProgressEvent?.RequestToken) { + throw new Error(`${typeName} deletion failed: no request token returned`); + } + + const requestToken = response.ProgressEvent.RequestToken; + console.log(`[DELETE] Got request token: ${requestToken}`); + + const pollResult = await pollOperationStatus( + client, + requestToken, + `${typeName} delete`, + ); + + if (pollResult.status === "FAILED") { + if ( + pollResult.message && + (pollResult.message.includes("was not found") || + pollResult.message.includes("does not exist")) + ) { + return { existed: false }; + } + throw new Error( + `${typeName} deletion failed: ${pollResult.message || "Unknown error"}`, + ); + } + + if (pollResult.status === "CANCEL_COMPLETE") { + throw new Error( + `${typeName} deletion cancelled: ${pollResult.message}`, + ); + } + + return { existed: true }; + } catch (error: unknown) { + if (isResourceNotFoundError(error)) { + return { existed: false }; + } + throw error; + } +} diff --git a/model/aws/braket/extensions/models/spending_limit.ts b/model/aws/braket/extensions/models/spending_limit.ts new file mode 100644 index 000000000..54e4247a3 --- /dev/null +++ b/model/aws/braket/extensions/models/spending_limit.ts @@ -0,0 +1,269 @@ +// Auto-generated extension model for @swamp/aws/braket/spending-limit +// Do not edit manually. Re-generate with: deno task generate:aws + +// deno-lint-ignore-file no-explicit-any + +import { z } from "zod"; +import { + createResource, + deleteResource, + isResourceNotFoundError, + readResource, + updateResource, +} from "./_lib/aws.ts"; + +export const TagSchema = z.object({ + Key: z.string().min(1).max(128).describe("The key name of the tag."), + Value: z.string().min(0).max(256).describe("The value for the tag."), +}); + +const GlobalArgsSchema = z.object({ + name: z.string().describe( + "Instance name for this resource (used as the unique identifier in the factory pattern)", + ), + DeviceArn: z.string().min(1).max(256).describe( + "The Amazon Resource Name (ARN) of the quantum device to apply the spending limit to.", + ), + SpendingLimit: z.string().min(1).regex(new RegExp("^\\d+(\\.\\d{1,2})?$")) + .describe( + "The maximum amount that can be spent on the specified device, in USD.", + ), + TimePeriod: z.object({ + StartAt: z.string().describe( + "The start date and time for the spending limit period, in ISO 8601 format.", + ), + EndAt: z.string().describe( + "The end date and time for the spending limit period, in ISO 8601 format.", + ), + }).describe( + "Defines a time range for spending limits, specifying when the limit is active.", + ).optional(), + Tags: z.array(TagSchema).describe("The tags to apply to the spending limit.") + .optional(), +}); + +const StateSchema = z.object({ + SpendingLimitArn: z.string(), + DeviceArn: z.string().optional(), + SpendingLimit: z.string().optional(), + TimePeriod: z.object({ + StartAt: z.string(), + EndAt: z.string(), + }).optional(), + QueuedSpend: z.string().optional(), + TotalSpend: z.string().optional(), + CreatedAt: z.string().optional(), + UpdatedAt: z.string().optional(), + Tags: z.array(TagSchema).optional(), +}).passthrough(); + +type StateData = z.infer; + +const InputsSchema = z.object({ + name: z.string().optional(), + DeviceArn: z.string().min(1).max(256).describe( + "The Amazon Resource Name (ARN) of the quantum device to apply the spending limit to.", + ).optional(), + SpendingLimit: z.string().min(1).regex(new RegExp("^\\d+(\\.\\d{1,2})?$")) + .describe( + "The maximum amount that can be spent on the specified device, in USD.", + ).optional(), + TimePeriod: z.object({ + StartAt: z.string().describe( + "The start date and time for the spending limit period, in ISO 8601 format.", + ).optional(), + EndAt: z.string().describe( + "The end date and time for the spending limit period, in ISO 8601 format.", + ).optional(), + }).describe( + "Defines a time range for spending limits, specifying when the limit is active.", + ).optional(), + Tags: z.array(TagSchema).describe("The tags to apply to the spending limit.") + .optional(), +}); + +export const model = { + type: "@swamp/aws/braket/spending-limit", + version: "2026.04.08.1", + globalArguments: GlobalArgsSchema, + inputsSchema: InputsSchema, + resources: { + state: { + description: "Braket SpendingLimit resource state", + schema: StateSchema, + lifetime: "infinite", + garbageCollection: 10, + }, + }, + methods: { + create: { + description: "Create a Braket SpendingLimit", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const desiredState: Record = {}; + for (const [key, value] of Object.entries(g)) { + if (key === "name") continue; + if (value !== undefined) desiredState[key] = value; + } + const result = await createResource( + "AWS::Braket::SpendingLimit", + desiredState, + ) as StateData; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + get: { + description: "Get a Braket SpendingLimit", + arguments: z.object({ + identifier: z.string().describe( + "The primary identifier of the Braket SpendingLimit", + ), + }), + execute: async (args: { identifier: string }, context: any) => { + const result = await readResource( + "AWS::Braket::SpendingLimit", + args.identifier, + ) as StateData; + const instanceName = + (context.globalArgs.name?.toString() ?? args.identifier).replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + update: { + description: "Update a Braket SpendingLimit", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const content = await context.dataRepository.getContent( + context.modelType, + context.modelId, + instanceName, + ); + if (!content) { + throw new Error("No existing state found - run create or get first"); + } + const existing = JSON.parse(new TextDecoder().decode(content)); + const identifier = existing.SpendingLimitArn?.toString(); + if (!identifier) { + throw new Error("No identifier found in existing state"); + } + const currentState = await readResource( + "AWS::Braket::SpendingLimit", + identifier, + ) as StateData; + const desiredState: Record = { ...currentState }; + for (const [key, value] of Object.entries(g)) { + if (key === "name") continue; + if (value !== undefined) desiredState[key] = value; + } + const result = await updateResource( + "AWS::Braket::SpendingLimit", + identifier, + currentState, + desiredState, + ["DeviceArn"], + ); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + delete: { + description: "Delete a Braket SpendingLimit", + arguments: z.object({ + identifier: z.string().describe( + "The primary identifier of the Braket SpendingLimit", + ), + }), + execute: async (args: { identifier: string }, context: any) => { + const { existed } = await deleteResource( + "AWS::Braket::SpendingLimit", + args.identifier, + ); + const instanceName = + (context.globalArgs.name?.toString() ?? args.identifier).replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource("state", instanceName, { + identifier: args.identifier, + existed, + status: existed ? "deleted" : "not_found", + deletedAt: new Date().toISOString(), + }); + return { dataHandles: [handle] }; + }, + }, + sync: { + description: "Sync Braket SpendingLimit state from AWS", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const content = await context.dataRepository.getContent( + context.modelType, + context.modelId, + instanceName, + ); + if (!content) { + throw new Error("No existing state found - run create or get first"); + } + const existing = JSON.parse(new TextDecoder().decode(content)); + const identifier = existing.SpendingLimitArn?.toString(); + if (!identifier) { + throw new Error("No identifier found in existing state"); + } + try { + const result = await readResource( + "AWS::Braket::SpendingLimit", + identifier, + ) as StateData; + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + } catch (error: unknown) { + if (isResourceNotFoundError(error)) { + const handle = await context.writeResource("state", instanceName, { + identifier, + status: "not_found", + syncedAt: new Date().toISOString(), + }); + return { dataHandles: [handle] }; + } + throw error; + } + }, + }, + }, +}; diff --git a/model/aws/braket/manifest.yaml b/model/aws/braket/manifest.yaml new file mode 100644 index 000000000..e2e9f5605 --- /dev/null +++ b/model/aws/braket/manifest.yaml @@ -0,0 +1,17 @@ +# Auto-generated manifest. Re-generate with the appropriate deno task. +manifestVersion: 1 +name: "@swamp/aws/braket" +version: "2026.04.08.1" +description: "AWS BRAKET infrastructure models" +labels: + - aws + - braket + - cloud + - infrastructure +releaseNotes: | + - Added: spending_limit +models: + - spending_limit.ts +additionalFiles: + - LICENSE.txt + - README.md diff --git a/model/aws/ecs/extensions/models/task_definition.ts b/model/aws/ecs/extensions/models/task_definition.ts index e0d75916c..ae3e63649 100644 --- a/model/aws/ecs/extensions/models/task_definition.ts +++ b/model/aws/ecs/extensions/models/task_definition.ts @@ -60,6 +60,13 @@ export const EFSVolumeConfigurationSchema = z.object({ ).optional(), }); +export const S3FilesVolumeConfigurationSchema = z.object({ + FileSystemArn: z.string(), + AccessPointArn: z.string().optional(), + RootDirectory: z.string().optional(), + TransitEncryptionPort: z.number().int().optional(), +}); + export const HostVolumePropertiesSchema = z.object({ SourcePath: z.string().describe( "When the host parameter is used, specify a sourcePath to declare the path on the host container instance that's presented to the container. If this parameter is empty, then the Docker daemon has assigned a host path for you. If the host parameter contains a sourcePath file location, then the data volume persists at the specified location on the host container instance until you delete it manually. If the sourcePath value doesn't exist on the host container instance, the Docker daemon creates it. If the location does exist, the contents of the source path folder are exported. If you're using the Fargate launch type, the sourcePath parameter is not supported.", @@ -109,6 +116,7 @@ export const VolumeSchema = z.object({ EFSVolumeConfiguration: EFSVolumeConfigurationSchema.describe( "This parameter is specified when you use an Amazon Elastic File System file system for task storage.", ).optional(), + S3FilesVolumeConfiguration: S3FilesVolumeConfigurationSchema.optional(), Host: HostVolumePropertiesSchema.describe( "This parameter is specified when you use bind mount host volumes. The contents of the host parameter determine whether your bind mount host volume persists on the host container instance and where it's stored. If the host parameter is empty, then the Docker daemon assigns a host path for your data volume. However, the data isn't guaranteed to persist after the containers that are associated with it stop running. Windows containers can mount whole directories on the same drive as $env:ProgramData. Windows containers can't mount directories on a different drive, and mount point can't be across drives. For example, you can mount C:\\my\\path:C:\\my\\path and D:\\:D:\\, but not D:\\my\\path:C:\\my\\path or D:\\:C:\\my\\path.", ).optional(), @@ -668,7 +676,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/aws/ecs/task-definition", - version: "2026.04.03.2", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.2", @@ -685,6 +693,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, diff --git a/model/aws/ecs/manifest.yaml b/model/aws/ecs/manifest.yaml index 7bcac8117..b78184853 100644 --- a/model/aws/ecs/manifest.yaml +++ b/model/aws/ecs/manifest.yaml @@ -1,7 +1,7 @@ # Auto-generated manifest. Re-generate with the appropriate deno task. manifestVersion: 1 name: "@swamp/aws/ecs" -version: "2026.04.03.3" +version: "2026.04.08.1" description: "AWS ECS infrastructure models" labels: - aws @@ -9,7 +9,7 @@ labels: - cloud - infrastructure releaseNotes: | - - Updated: capacity_provider, cluster, cluster_capacity_provider_associations, daemon, daemon_task_definition, express_gateway_service, primary_task_set, service, task_definition, task_set + - Updated: task_definition models: - capacity_provider.ts - cluster.ts diff --git a/model/aws/fsx/extensions/models/s3access_point_attachment.ts b/model/aws/fsx/extensions/models/s3access_point_attachment.ts index 4be6d213f..27197dc0d 100644 --- a/model/aws/fsx/extensions/models/s3access_point_attachment.ts +++ b/model/aws/fsx/extensions/models/s3access_point_attachment.ts @@ -127,6 +127,7 @@ const StateSchema = z.object({ VpcConfiguration: S3AccessPointVpcConfigurationSchema, Policy: z.string(), }).optional(), + Lifecycle: z.string().optional(), }).passthrough(); type StateData = z.infer; @@ -174,7 +175,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/aws/fsx/s3access-point-attachment", - version: "2026.04.03.2", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -191,6 +192,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, diff --git a/model/aws/fsx/manifest.yaml b/model/aws/fsx/manifest.yaml index b15474888..457fae042 100644 --- a/model/aws/fsx/manifest.yaml +++ b/model/aws/fsx/manifest.yaml @@ -1,7 +1,7 @@ # Auto-generated manifest. Re-generate with the appropriate deno task. manifestVersion: 1 name: "@swamp/aws/fsx" -version: "2026.04.03.2" +version: "2026.04.08.1" description: "AWS FSX infrastructure models" labels: - aws @@ -9,7 +9,7 @@ labels: - cloud - infrastructure releaseNotes: | - - Updated: data_repository_association, s3access_point_attachment + - Updated: s3access_point_attachment models: - data_repository_association.ts - s3access_point_attachment.ts diff --git a/model/aws/lambda/extensions/models/function.ts b/model/aws/lambda/extensions/models/function.ts index dc5232811..5d3a678f1 100644 --- a/model/aws/lambda/extensions/models/function.ts +++ b/model/aws/lambda/extensions/models/function.ts @@ -199,6 +199,7 @@ const GlobalArgsSchema = z.object({ S3Key: z.string().min(1).max(1024).describe( "The Amazon S3 key of the deployment package.", ).optional(), + S3ObjectStorageMode: z.enum(["COPY", "REFERENCE"]).optional(), ImageUri: z.string().describe( "URI of a [container image](https://docs.aws.amazon.com/lambda/latest/dg/lambda-images.html) in the Amazon ECR registry.", ).optional(), @@ -321,6 +322,7 @@ const StateSchema = z.object({ S3Bucket: z.string(), ZipFile: z.string(), S3Key: z.string(), + S3ObjectStorageMode: z.string(), ImageUri: z.string(), }).optional(), Role: z.string().optional(), @@ -494,6 +496,7 @@ const InputsSchema = z.object({ S3Key: z.string().min(1).max(1024).describe( "The Amazon S3 key of the deployment package.", ).optional(), + S3ObjectStorageMode: z.enum(["COPY", "REFERENCE"]).optional(), ImageUri: z.string().describe( "URI of a [container image](https://docs.aws.amazon.com/lambda/latest/dg/lambda-images.html) in the Amazon ECR registry.", ).optional(), @@ -554,7 +557,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/aws/lambda/function", - version: "2026.04.03.2", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -571,6 +574,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, diff --git a/model/aws/lambda/manifest.yaml b/model/aws/lambda/manifest.yaml index e0d353f41..0ef7dc4a2 100644 --- a/model/aws/lambda/manifest.yaml +++ b/model/aws/lambda/manifest.yaml @@ -1,7 +1,7 @@ # Auto-generated manifest. Re-generate with the appropriate deno task. manifestVersion: 1 name: "@swamp/aws/lambda" -version: "2026.04.03.2" +version: "2026.04.08.1" description: "AWS LAMBDA infrastructure models" labels: - aws @@ -9,7 +9,7 @@ labels: - cloud - infrastructure releaseNotes: | - - Updated: alias, capacity_provider, code_signing_config, event_invoke_config, event_source_mapping, function, layer_version, layer_version_permission, permission, url, version + - Updated: function models: - alias.ts - capacity_provider.ts diff --git a/model/aws/observabilityadmin/extensions/models/organization_telemetry_rule.ts b/model/aws/observabilityadmin/extensions/models/organization_telemetry_rule.ts index a5d42482e..250ecdd85 100644 --- a/model/aws/observabilityadmin/extensions/models/organization_telemetry_rule.ts +++ b/model/aws/observabilityadmin/extensions/models/organization_telemetry_rule.ts @@ -188,10 +188,11 @@ const GlobalArgsSchema = z.object({ "AWS::CloudTrail", "AWS::EKS::Cluster", "AWS::ElasticLoadBalancingV2::LoadBalancer", + "AWS::EC2::Instance", ]).describe( "Resource Type associated with the Organization Telemetry Rule", ), - TelemetryType: z.enum(["Logs"]).describe( + TelemetryType: z.enum(["Logs", "Metrics"]).describe( "Telemetry Type associated with the Organization Telemetry Rule", ), TelemetrySourceTypes: z.array( @@ -247,9 +248,10 @@ const InputsSchema = z.object({ "AWS::CloudTrail", "AWS::EKS::Cluster", "AWS::ElasticLoadBalancingV2::LoadBalancer", + "AWS::EC2::Instance", ]).describe("Resource Type associated with the Organization Telemetry Rule") .optional(), - TelemetryType: z.enum(["Logs"]).describe( + TelemetryType: z.enum(["Logs", "Metrics"]).describe( "Telemetry Type associated with the Organization Telemetry Rule", ).optional(), TelemetrySourceTypes: z.array( @@ -280,7 +282,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/aws/observabilityadmin/organization-telemetry-rule", - version: "2026.04.03.2", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -297,6 +299,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, diff --git a/model/aws/observabilityadmin/extensions/models/telemetry_rule.ts b/model/aws/observabilityadmin/extensions/models/telemetry_rule.ts index 096954995..8e45e7144 100644 --- a/model/aws/observabilityadmin/extensions/models/telemetry_rule.ts +++ b/model/aws/observabilityadmin/extensions/models/telemetry_rule.ts @@ -193,11 +193,12 @@ const GlobalArgsSchema = z.object({ "AWS::CloudTrail", "AWS::EKS::Cluster", "AWS::ElasticLoadBalancingV2::LoadBalancer", + "AWS::EC2::Instance", "AWS::BedrockAgentCore::Runtime", "AWS::BedrockAgentCore::Browser", "AWS::BedrockAgentCore::CodeInterpreter", ]).describe("Resource Type associated with the Telemetry Rule"), - TelemetryType: z.enum(["Logs", "Traces"]).describe( + TelemetryType: z.enum(["Logs", "Traces", "Metrics"]).describe( "Telemetry Type associated with the Telemetry Rule", ), TelemetrySourceTypes: z.array( @@ -249,11 +250,12 @@ const InputsSchema = z.object({ "AWS::CloudTrail", "AWS::EKS::Cluster", "AWS::ElasticLoadBalancingV2::LoadBalancer", + "AWS::EC2::Instance", "AWS::BedrockAgentCore::Runtime", "AWS::BedrockAgentCore::Browser", "AWS::BedrockAgentCore::CodeInterpreter", ]).describe("Resource Type associated with the Telemetry Rule").optional(), - TelemetryType: z.enum(["Logs", "Traces"]).describe( + TelemetryType: z.enum(["Logs", "Traces", "Metrics"]).describe( "Telemetry Type associated with the Telemetry Rule", ).optional(), TelemetrySourceTypes: z.array( @@ -281,7 +283,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/aws/observabilityadmin/telemetry-rule", - version: "2026.04.03.2", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -298,6 +300,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, diff --git a/model/aws/observabilityadmin/manifest.yaml b/model/aws/observabilityadmin/manifest.yaml index 2f4a64a15..e78f427c5 100644 --- a/model/aws/observabilityadmin/manifest.yaml +++ b/model/aws/observabilityadmin/manifest.yaml @@ -1,7 +1,7 @@ # Auto-generated manifest. Re-generate with the appropriate deno task. manifestVersion: 1 name: "@swamp/aws/observabilityadmin" -version: "2026.04.03.2" +version: "2026.04.08.1" description: "AWS OBSERVABILITYADMIN infrastructure models" labels: - aws @@ -9,7 +9,7 @@ labels: - cloud - infrastructure releaseNotes: | - - Updated: organization_centralization_rule, organization_telemetry_rule, s3table_integration, telemetry_enrichment, telemetry_pipelines, telemetry_rule + - Updated: organization_telemetry_rule, telemetry_rule models: - organization_centralization_rule.ts - organization_telemetry_rule.ts diff --git a/model/aws/s3files/LICENSE.txt b/model/aws/s3files/LICENSE.txt new file mode 100644 index 000000000..6720f5e28 --- /dev/null +++ b/model/aws/s3files/LICENSE.txt @@ -0,0 +1,14 @@ +Copyright (C) 2026 System Initiative, Inc. + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . diff --git a/model/aws/s3files/README.md b/model/aws/s3files/README.md new file mode 100644 index 000000000..4524de75d --- /dev/null +++ b/model/aws/s3files/README.md @@ -0,0 +1,65 @@ +# @swamp/aws/s3files + +Auto-generated [swamp](https://github.com/systeminit/swamp) extension models for +AWS S3FILES resources. + +Each model represents a single AWS resource (e.g., a VPC, an S3 bucket, an IAM +role). Models have **domain properties** that you configure (the desired state) +and **resource properties** that reflect the live state in AWS. Available +methods: + +- **create** — provision the resource in AWS using the configured properties +- **get** — fetch the current state of a specific resource by identifier +- **update** — apply property changes to an existing resource +- **delete** — remove the resource from AWS +- **sync** — refresh all resource properties from AWS + +Use `swamp model type describe @swamp/aws/s3files/access_point` to see the full +list of configurable properties and available methods for this model. + +## Authentication + +These models use the AWS SDK v3 default credential chain. Credentials are +resolved in the following order: + +1. **Environment variables** — `AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY` + + optional `AWS_SESSION_TOKEN` +2. **SSO credentials** — `aws sso login` +3. **Shared credentials file** — `~/.aws/credentials` +4. **Shared config file** — `~/.aws/config` (profiles, `credential_process`, + SSO) +5. **ECS container credentials** — task IAM role +6. **EC2 instance metadata** — instance profile + +### Region + +The `AWS_REGION` environment variable controls which region resources are +created and managed in. Defaults to `us-east-1` if not set. + +### Setup + +```bash +export AWS_REGION=us-east-1 +export AWS_ACCESS_KEY_ID=AKIA... +export AWS_SECRET_ACCESS_KEY=wJal... +``` + +## Usage + +```bash +# Create a new access_point model +swamp model create @swamp/aws/s3files/access_point my-access_point + +# Edit the model to configure its properties +swamp model edit my-access_point + +# Create the resource in AWS +swamp model method run my-access_point create + +# Sync current state from AWS +swamp model method run my-access_point sync +``` + +## License + +AGPLv3 — see [LICENSE.txt](./LICENSE.txt). diff --git a/model/aws/s3files/deno.json b/model/aws/s3files/deno.json new file mode 100644 index 000000000..15892302f --- /dev/null +++ b/model/aws/s3files/deno.json @@ -0,0 +1,7 @@ +{ + "imports": { + "zod": "npm:zod@4.3.6", + "@aws-sdk/client-cloudcontrol": "npm:@aws-sdk/client-cloudcontrol@3.1021.0", + "fast-json-patch": "npm:fast-json-patch@3.1.1" + } +} diff --git a/model/aws/s3files/deno.lock b/model/aws/s3files/deno.lock new file mode 100644 index 000000000..ded86fbb9 --- /dev/null +++ b/model/aws/s3files/deno.lock @@ -0,0 +1,777 @@ +{ + "version": "5", + "specifiers": { + "npm:@aws-sdk/client-cloudcontrol@3.1021.0": "3.1021.0", + "npm:fast-json-patch@3.1.1": "3.1.1", + "npm:zod@4.3.6": "4.3.6" + }, + "npm": { + "@aws-crypto/sha256-browser@5.2.0": { + "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==", + "dependencies": [ + "@aws-crypto/sha256-js", + "@aws-crypto/supports-web-crypto", + "@aws-crypto/util", + "@aws-sdk/types", + "@aws-sdk/util-locate-window", + "@smithy/util-utf8@2.3.0", + "tslib" + ] + }, + "@aws-crypto/sha256-js@5.2.0": { + "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==", + "dependencies": [ + "@aws-crypto/util", + "@aws-sdk/types", + "tslib" + ] + }, + "@aws-crypto/supports-web-crypto@5.2.0": { + "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==", + "dependencies": [ + "tslib" + ] + }, + "@aws-crypto/util@5.2.0": { + "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==", + "dependencies": [ + "@aws-sdk/types", + "@smithy/util-utf8@2.3.0", + "tslib" + ] + }, + "@aws-sdk/client-cloudcontrol@3.1021.0": { + "integrity": "sha512-VbrIC3iT4OveHdkjYdMdwGk60YNOmN0OsL1QEuEjOwUmjq1aYRzgtjNb9fGR9a8CWhGA7yjqWDaUeNJ+wUGzMw==", + "dependencies": [ + "@aws-crypto/sha256-browser", + "@aws-crypto/sha256-js", + "@aws-sdk/core", + "@aws-sdk/credential-provider-node", + "@aws-sdk/middleware-host-header", + "@aws-sdk/middleware-logger", + "@aws-sdk/middleware-recursion-detection", + "@aws-sdk/middleware-user-agent", + "@aws-sdk/region-config-resolver", + "@aws-sdk/types", + "@aws-sdk/util-endpoints", + "@aws-sdk/util-user-agent-browser", + "@aws-sdk/util-user-agent-node", + "@smithy/config-resolver", + "@smithy/core", + "@smithy/fetch-http-handler", + "@smithy/hash-node", + "@smithy/invalid-dependency", + "@smithy/middleware-content-length", + "@smithy/middleware-endpoint", + "@smithy/middleware-retry", + "@smithy/middleware-serde", + "@smithy/middleware-stack", + "@smithy/node-config-provider", + "@smithy/node-http-handler", + "@smithy/protocol-http", + "@smithy/smithy-client", + "@smithy/types", + "@smithy/url-parser", + "@smithy/util-base64", + "@smithy/util-body-length-browser", + "@smithy/util-body-length-node", + "@smithy/util-defaults-mode-browser", + "@smithy/util-defaults-mode-node", + "@smithy/util-endpoints", + "@smithy/util-middleware", + "@smithy/util-retry", + "@smithy/util-utf8@4.2.2", + "@smithy/util-waiter", + "tslib" + ] + }, + "@aws-sdk/core@3.973.27": { + "integrity": "sha512-CUZ5m8hwMCH6OYI4Li/WgMfIEx10Q2PLI9Y3XOUTPGZJ53aZ0007jCv+X/ywsaERyKPdw5MRZWk877roQksQ4A==", + "dependencies": [ + "@aws-sdk/types", + "@aws-sdk/xml-builder", + "@smithy/core", + "@smithy/node-config-provider", + "@smithy/property-provider", + "@smithy/protocol-http", + "@smithy/signature-v4", + "@smithy/smithy-client", + "@smithy/types", + "@smithy/util-base64", + "@smithy/util-middleware", + "@smithy/util-utf8@4.2.2", + "tslib" + ] + }, + "@aws-sdk/credential-provider-env@3.972.25": { + "integrity": "sha512-6QfI0wv4jpG5CrdO/AO0JfZ2ux+tKwJPrUwmvxXF50vI5KIypKVGNF6b4vlkYEnKumDTI1NX2zUBi8JoU5QU3A==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/types", + "@smithy/property-provider", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/credential-provider-http@3.972.27": { + "integrity": "sha512-3V3Usj9Gs93h865DqN4M2NWJhC5kXU9BvZskfN3+69omuYlE3TZxOEcVQtBGLOloJB7BVfJKXVLqeNhOzHqSlQ==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/types", + "@smithy/fetch-http-handler", + "@smithy/node-http-handler", + "@smithy/property-provider", + "@smithy/protocol-http", + "@smithy/smithy-client", + "@smithy/types", + "@smithy/util-stream", + "tslib" + ] + }, + "@aws-sdk/credential-provider-ini@3.972.29": { + "integrity": "sha512-SiBuAnXecCbT/OpAf3vqyI/AVE3mTaYr9ShXLybxZiPLBiPCCOIWSGAtYYGQWMRvobBTiqOewaB+wcgMMZI2Aw==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/credential-provider-env", + "@aws-sdk/credential-provider-http", + "@aws-sdk/credential-provider-login", + "@aws-sdk/credential-provider-process", + "@aws-sdk/credential-provider-sso", + "@aws-sdk/credential-provider-web-identity", + "@aws-sdk/nested-clients", + "@aws-sdk/types", + "@smithy/credential-provider-imds", + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/credential-provider-login@3.972.29": { + "integrity": "sha512-OGOslTbOlxXexKMqhxCEbBQbUIfuhGxU5UXw3Fm56ypXHvrXH4aTt/xb5Y884LOoteP1QST1lVZzHfcTnWhiPQ==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/nested-clients", + "@aws-sdk/types", + "@smithy/property-provider", + "@smithy/protocol-http", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/credential-provider-node@3.972.30": { + "integrity": "sha512-FMnAnWxc8PG+ZrZ2OBKzY4luCUJhe9CG0B9YwYr4pzrYGLXBS2rl+UoUvjGbAwiptxRL6hyA3lFn03Bv1TLqTw==", + "dependencies": [ + "@aws-sdk/credential-provider-env", + "@aws-sdk/credential-provider-http", + "@aws-sdk/credential-provider-ini", + "@aws-sdk/credential-provider-process", + "@aws-sdk/credential-provider-sso", + "@aws-sdk/credential-provider-web-identity", + "@aws-sdk/types", + "@smithy/credential-provider-imds", + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/credential-provider-process@3.972.25": { + "integrity": "sha512-HR7ynNRdNhNsdVCOCegy1HsfsRzozCOPtD3RzzT1JouuaHobWyRfJzCBue/3jP7gECHt+kQyZUvwg/cYLWurNQ==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/types", + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/credential-provider-sso@3.972.29": { + "integrity": "sha512-HWv4SEq3jZDYPlwryZVef97+U8CxxRos5mK8sgGO1dQaFZpV5giZLzqGE5hkDmh2csYcBO2uf5XHjPTpZcJlig==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/nested-clients", + "@aws-sdk/token-providers", + "@aws-sdk/types", + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/credential-provider-web-identity@3.972.29": { + "integrity": "sha512-PdMBza1WEKEUPFEmMGCfnU2RYCz9MskU2e8JxjyUOsMKku7j9YaDKvbDi2dzC0ihFoM6ods2SbhfAAro+Gwlew==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/nested-clients", + "@aws-sdk/types", + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/middleware-host-header@3.972.9": { + "integrity": "sha512-je5vRdNw4SkuTnmRbFZLdye4sQ0faLt8kwka5wnnSU30q1mHO4X+idGEJOOE+Tn1ME7Oryn05xxkDvIb3UaLaQ==", + "dependencies": [ + "@aws-sdk/types", + "@smithy/protocol-http", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/middleware-logger@3.972.9": { + "integrity": "sha512-HsVgDrruhqI28RkaXALm8grJ7Agc1wF6Et0xh6pom8NdO2VdO/SD9U/tPwUjewwK/pVoka+EShBxyCvgsPCtog==", + "dependencies": [ + "@aws-sdk/types", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/middleware-recursion-detection@3.972.10": { + "integrity": "sha512-RVQQbq5orQ/GHUnXvqEOj2HHPBJm+mM+ySwZKS5UaLBwra5ugRtiH09PLUoOZRl7a1YzaOzXSuGbn9iD5j60WQ==", + "dependencies": [ + "@aws-sdk/types", + "@aws/lambda-invoke-store", + "@smithy/protocol-http", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/middleware-user-agent@3.972.29": { + "integrity": "sha512-f/sIRzuTfEjg6NsbMYvye2VsmnQoNgntntleQyx5uGacUYzszbfIlO3GcI6G6daWUmTm0IDZc11qMHWwF0o0mQ==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/types", + "@aws-sdk/util-endpoints", + "@smithy/core", + "@smithy/protocol-http", + "@smithy/types", + "@smithy/util-retry", + "tslib" + ] + }, + "@aws-sdk/nested-clients@3.996.19": { + "integrity": "sha512-uFkmCDXvmQYLanlYdOFS0+MQWkrj9wPMt/ZCc/0J0fjPim6F5jBVBmEomvGY/j77ILW6GTPwN22Jc174Mhkw6Q==", + "dependencies": [ + "@aws-crypto/sha256-browser", + "@aws-crypto/sha256-js", + "@aws-sdk/core", + "@aws-sdk/middleware-host-header", + "@aws-sdk/middleware-logger", + "@aws-sdk/middleware-recursion-detection", + "@aws-sdk/middleware-user-agent", + "@aws-sdk/region-config-resolver", + "@aws-sdk/types", + "@aws-sdk/util-endpoints", + "@aws-sdk/util-user-agent-browser", + "@aws-sdk/util-user-agent-node", + "@smithy/config-resolver", + "@smithy/core", + "@smithy/fetch-http-handler", + "@smithy/hash-node", + "@smithy/invalid-dependency", + "@smithy/middleware-content-length", + "@smithy/middleware-endpoint", + "@smithy/middleware-retry", + "@smithy/middleware-serde", + "@smithy/middleware-stack", + "@smithy/node-config-provider", + "@smithy/node-http-handler", + "@smithy/protocol-http", + "@smithy/smithy-client", + "@smithy/types", + "@smithy/url-parser", + "@smithy/util-base64", + "@smithy/util-body-length-browser", + "@smithy/util-body-length-node", + "@smithy/util-defaults-mode-browser", + "@smithy/util-defaults-mode-node", + "@smithy/util-endpoints", + "@smithy/util-middleware", + "@smithy/util-retry", + "@smithy/util-utf8@4.2.2", + "tslib" + ] + }, + "@aws-sdk/region-config-resolver@3.972.11": { + "integrity": "sha512-6Q8B1dcx6BBqUTY1Mc/eROKA0FImEEY5VPSd6AGPEUf0ErjExz4snVqa9kNJSoVDV1rKaNf3qrWojgcKW+SdDg==", + "dependencies": [ + "@aws-sdk/types", + "@smithy/config-resolver", + "@smithy/node-config-provider", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/token-providers@3.1026.0": { + "integrity": "sha512-Ieq/HiRrbEtrYP387Nes0XlR7H1pJiJOZKv+QyQzMYpvTiDs0VKy2ZB3E2Zf+aFovWmeE7lRE4lXyF7dYM6GgA==", + "dependencies": [ + "@aws-sdk/core", + "@aws-sdk/nested-clients", + "@aws-sdk/types", + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/types@3.973.7": { + "integrity": "sha512-reXRwoJ6CfChoqAsBszUYajAF8Z2LRE+CRcKocvFSMpIiLOtYU3aJ9trmn6VVPAzbbY5LXF+FfmUslbXk1SYFg==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@aws-sdk/util-endpoints@3.996.6": { + "integrity": "sha512-2nUQ+2ih7CShuKHpGSIYvvAIOHy52dOZguYG36zptBukhw6iFwcvGfG0tes0oZFWQqEWvgZe9HLWaNlvXGdOrg==", + "dependencies": [ + "@aws-sdk/types", + "@smithy/types", + "@smithy/url-parser", + "@smithy/util-endpoints", + "tslib" + ] + }, + "@aws-sdk/util-locate-window@3.965.5": { + "integrity": "sha512-WhlJNNINQB+9qtLtZJcpQdgZw3SCDCpXdUJP7cToGwHbCWCnRckGlc6Bx/OhWwIYFNAn+FIydY8SZ0QmVu3xTQ==", + "dependencies": [ + "tslib" + ] + }, + "@aws-sdk/util-user-agent-browser@3.972.9": { + "integrity": "sha512-sn/LMzTbGjYqCCF24390WxPd6hkpoSptiUn5DzVp4cD71yqw+yGEGm1YCxyEoPXyc8qciM8UzLJcZBFslxo5Uw==", + "dependencies": [ + "@aws-sdk/types", + "@smithy/types", + "bowser", + "tslib" + ] + }, + "@aws-sdk/util-user-agent-node@3.973.15": { + "integrity": "sha512-fYn3s9PtKdgQkczGZCFMgkNEe8aq1JCVbnRqjqN9RSVW43xn2RV9xdcZ3z01a48Jpkuh/xCmBKJxdLOo4Ozg7w==", + "dependencies": [ + "@aws-sdk/middleware-user-agent", + "@aws-sdk/types", + "@smithy/node-config-provider", + "@smithy/types", + "@smithy/util-config-provider", + "tslib" + ] + }, + "@aws-sdk/xml-builder@3.972.17": { + "integrity": "sha512-Ra7hjqAZf1OXRRMueB13qex7mFJRDK/pgCvdSFemXBT8KCGnQDPoKzHY1SjN+TjJVmnpSF14W5tJ1vDamFu+Gg==", + "dependencies": [ + "@smithy/types", + "fast-xml-parser", + "tslib" + ] + }, + "@aws/lambda-invoke-store@0.2.4": { + "integrity": "sha512-iY8yvjE0y651BixKNPgmv1WrQc+GZ142sb0z4gYnChDDY2YqI4P/jsSopBWrKfAt7LOJAkOXt7rC/hms+WclQQ==" + }, + "@smithy/config-resolver@4.4.14": { + "integrity": "sha512-N55f8mPEccpzKetUagdvmAy8oohf0J5cuj9jLI1TaSceRlq0pJsIZepY3kmAXAhyxqXPV6hDerDQhqQPKWgAoQ==", + "dependencies": [ + "@smithy/node-config-provider", + "@smithy/types", + "@smithy/util-config-provider", + "@smithy/util-endpoints", + "@smithy/util-middleware", + "tslib" + ] + }, + "@smithy/core@3.23.14": { + "integrity": "sha512-vJ0IhpZxZAkFYOegMKSrxw7ujhhT2pass/1UEcZ4kfl5srTAqtPU5I7MdYQoreVas3204ykCiNhY1o7Xlz6Yyg==", + "dependencies": [ + "@smithy/protocol-http", + "@smithy/types", + "@smithy/url-parser", + "@smithy/util-base64", + "@smithy/util-body-length-browser", + "@smithy/util-middleware", + "@smithy/util-stream", + "@smithy/util-utf8@4.2.2", + "@smithy/uuid", + "tslib" + ] + }, + "@smithy/credential-provider-imds@4.2.13": { + "integrity": "sha512-wboCPijzf6RJKLOvnjDAiBxGSmSnGXj35o5ZAWKDaHa/cvQ5U3ZJ13D4tMCE8JG4dxVAZFy/P0x/V9CwwdfULQ==", + "dependencies": [ + "@smithy/node-config-provider", + "@smithy/property-provider", + "@smithy/types", + "@smithy/url-parser", + "tslib" + ] + }, + "@smithy/fetch-http-handler@5.3.16": { + "integrity": "sha512-nYDRUIvNd4mFmuXraRWt6w5UsZTNqtj4hXJA/iiOD4tuseIdLP9Lq38teH/SZTcIFCa2f+27o7hYpIsWktJKEQ==", + "dependencies": [ + "@smithy/protocol-http", + "@smithy/querystring-builder", + "@smithy/types", + "@smithy/util-base64", + "tslib" + ] + }, + "@smithy/hash-node@4.2.13": { + "integrity": "sha512-4/oy9h0jjmY80a2gOIo75iLl8TOPhmtx4E2Hz+PfMjvx/vLtGY4TMU/35WRyH2JHPfT5CVB38u4JRow7gnmzJA==", + "dependencies": [ + "@smithy/types", + "@smithy/util-buffer-from@4.2.2", + "@smithy/util-utf8@4.2.2", + "tslib" + ] + }, + "@smithy/invalid-dependency@4.2.13": { + "integrity": "sha512-jvC0RB/8BLj2SMIkY0Npl425IdnxZJxInpZJbu563zIRnVjpDMXevU3VMCRSabaLB0kf/eFIOusdGstrLJ8IDg==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/is-array-buffer@2.2.0": { + "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/is-array-buffer@4.2.2": { + "integrity": "sha512-n6rQ4N8Jj4YTQO3YFrlgZuwKodf4zUFs7EJIWH86pSCWBaAtAGBFfCM7Wx6D2bBJ2xqFNxGBSrUWswT3M0VJow==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/middleware-content-length@4.2.13": { + "integrity": "sha512-IPMLm/LE4AZwu6qiE8Rr8vJsWhs9AtOdySRXrOM7xnvclp77Tyh7hMs/FRrMf26kgIe67vFJXXOSmVxS7oKeig==", + "dependencies": [ + "@smithy/protocol-http", + "@smithy/types", + "tslib" + ] + }, + "@smithy/middleware-endpoint@4.4.29": { + "integrity": "sha512-R9Q/58U+qBiSARGWbAbFLczECg/RmysRksX6Q8BaQEpt75I7LI6WGDZnjuC9GXSGKljEbA7N118LhGaMbfrTXw==", + "dependencies": [ + "@smithy/core", + "@smithy/middleware-serde", + "@smithy/node-config-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "@smithy/url-parser", + "@smithy/util-middleware", + "tslib" + ] + }, + "@smithy/middleware-retry@4.5.0": { + "integrity": "sha512-/NzISn4grj/BRFVua/xnQwF+7fakYZgimpw2dfmlPgcqecBMKxpB9g5mLYRrmBD5OrPoODokw4Vi1hrSR4zRyw==", + "dependencies": [ + "@smithy/core", + "@smithy/node-config-provider", + "@smithy/protocol-http", + "@smithy/service-error-classification", + "@smithy/smithy-client", + "@smithy/types", + "@smithy/util-middleware", + "@smithy/util-retry", + "@smithy/uuid", + "tslib" + ] + }, + "@smithy/middleware-serde@4.2.17": { + "integrity": "sha512-0T2mcaM6v9W1xku86Dk0bEW7aEseG6KenFkPK98XNw0ZhOqOiD1MrMsdnQw9QsL3/Oa85T53iSMlm0SZdSuIEQ==", + "dependencies": [ + "@smithy/core", + "@smithy/protocol-http", + "@smithy/types", + "tslib" + ] + }, + "@smithy/middleware-stack@4.2.13": { + "integrity": "sha512-g72jN/sGDLyTanrCLH9fhg3oysO3f7tQa6eWWsMyn2BiYNCgjF24n4/I9wff/5XidFvjj9ilipAoQrurTUrLvw==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/node-config-provider@4.3.13": { + "integrity": "sha512-iGxQ04DsKXLckbgnX4ipElrOTk+IHgTyu0q0WssZfYhDm9CQWHmu6cOeI5wmWRxpXbBDhIIfXMWz5tPEtcVqbw==", + "dependencies": [ + "@smithy/property-provider", + "@smithy/shared-ini-file-loader", + "@smithy/types", + "tslib" + ] + }, + "@smithy/node-http-handler@4.5.2": { + "integrity": "sha512-/oD7u8M0oj2ZTFw7GkuuHWpIxtWdLlnyNkbrWcyVYhd5RJNDuczdkb0wfnQICyNFrVPlr8YHOhamjNy3zidhmA==", + "dependencies": [ + "@smithy/protocol-http", + "@smithy/querystring-builder", + "@smithy/types", + "tslib" + ] + }, + "@smithy/property-provider@4.2.13": { + "integrity": "sha512-bGzUCthxRmezuxkbu9wD33wWg9KX3hJpCXpQ93vVkPrHn9ZW6KNNdY5xAUWNuRCwQ+VyboFuWirG1lZhhkcyRQ==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/protocol-http@5.3.13": { + "integrity": "sha512-+HsmuJUF4u8POo6s8/a2Yb/AQ5t/YgLovCuHF9oxbocqv+SZ6gd8lC2duBFiCA/vFHoHQhoq7QjqJqZC6xOxxg==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/querystring-builder@4.2.13": { + "integrity": "sha512-tG4aOYFCZdPMjbgfhnIQ322H//ojujldp1SrHPHpBSb3NqgUp3dwiUGRJzie87hS1DYwWGqDuPaowoDF+rYCbQ==", + "dependencies": [ + "@smithy/types", + "@smithy/util-uri-escape", + "tslib" + ] + }, + "@smithy/querystring-parser@4.2.13": { + "integrity": "sha512-hqW3Q4P+CDzUyQ87GrboGMeD7XYNMOF+CuTwu936UQRB/zeYn3jys8C3w+wMkDfY7CyyyVwZQ5cNFoG0x1pYmA==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/service-error-classification@4.2.13": { + "integrity": "sha512-a0s8XZMfOC/qpqq7RCPvJlk93rWFrElH6O++8WJKz0FqnA4Y7fkNi/0mnGgSH1C4x6MFsuBA8VKu4zxFrMe5Vw==", + "dependencies": [ + "@smithy/types" + ] + }, + "@smithy/shared-ini-file-loader@4.4.8": { + "integrity": "sha512-VZCZx2bZasxdqxVgEAhREvDSlkatTPnkdWy1+Kiy8w7kYPBosW0V5IeDwzDUMvWBt56zpK658rx1cOBFOYaPaw==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/signature-v4@5.3.13": { + "integrity": "sha512-YpYSyM0vMDwKbHD/JA7bVOF6kToVRpa+FM5ateEVRpsTNu564g1muBlkTubXhSKKYXInhpADF46FPyrZcTLpXg==", + "dependencies": [ + "@smithy/is-array-buffer@4.2.2", + "@smithy/protocol-http", + "@smithy/types", + "@smithy/util-hex-encoding", + "@smithy/util-middleware", + "@smithy/util-uri-escape", + "@smithy/util-utf8@4.2.2", + "tslib" + ] + }, + "@smithy/smithy-client@4.12.9": { + "integrity": "sha512-ovaLEcTU5olSeHcRXcxV6viaKtpkHZumn6Ps0yn7dRf2rRSfy794vpjOtrWDO0d1auDSvAqxO+lyhERSXQ03EQ==", + "dependencies": [ + "@smithy/core", + "@smithy/middleware-endpoint", + "@smithy/middleware-stack", + "@smithy/protocol-http", + "@smithy/types", + "@smithy/util-stream", + "tslib" + ] + }, + "@smithy/types@4.14.0": { + "integrity": "sha512-OWgntFLW88kx2qvf/c/67Vno1yuXm/f9M7QFAtVkkO29IJXGBIg0ycEaBTH0kvCtwmvZxRujrgP5a86RvsXJAQ==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/url-parser@4.2.13": { + "integrity": "sha512-2G03yoboIRZlZze2+PT4GZEjgwQsJjUgn6iTsvxA02bVceHR6vp4Cuk7TUnPFWKF+ffNUk3kj4COwkENS2K3vw==", + "dependencies": [ + "@smithy/querystring-parser", + "@smithy/types", + "tslib" + ] + }, + "@smithy/util-base64@4.3.2": { + "integrity": "sha512-XRH6b0H/5A3SgblmMa5ErXQ2XKhfbQB+Fm/oyLZ2O2kCUrwgg55bU0RekmzAhuwOjA9qdN5VU2BprOvGGUkOOQ==", + "dependencies": [ + "@smithy/util-buffer-from@4.2.2", + "@smithy/util-utf8@4.2.2", + "tslib" + ] + }, + "@smithy/util-body-length-browser@4.2.2": { + "integrity": "sha512-JKCrLNOup3OOgmzeaKQwi4ZCTWlYR5H4Gm1r2uTMVBXoemo1UEghk5vtMi1xSu2ymgKVGW631e2fp9/R610ZjQ==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/util-body-length-node@4.2.3": { + "integrity": "sha512-ZkJGvqBzMHVHE7r/hcuCxlTY8pQr1kMtdsVPs7ex4mMU+EAbcXppfo5NmyxMYi2XU49eqaz56j2gsk4dHHPG/g==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/util-buffer-from@2.2.0": { + "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==", + "dependencies": [ + "@smithy/is-array-buffer@2.2.0", + "tslib" + ] + }, + "@smithy/util-buffer-from@4.2.2": { + "integrity": "sha512-FDXD7cvUoFWwN6vtQfEta540Y/YBe5JneK3SoZg9bThSoOAC/eGeYEua6RkBgKjGa/sz6Y+DuBZj3+YEY21y4Q==", + "dependencies": [ + "@smithy/is-array-buffer@4.2.2", + "tslib" + ] + }, + "@smithy/util-config-provider@4.2.2": { + "integrity": "sha512-dWU03V3XUprJwaUIFVv4iOnS1FC9HnMHDfUrlNDSh4315v0cWyaIErP8KiqGVbf5z+JupoVpNM7ZB3jFiTejvQ==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/util-defaults-mode-browser@4.3.45": { + "integrity": "sha512-ag9sWc6/nWZAuK3Wm9KlFJUnRkXLrXn33RFjIAmCTFThqLHY+7wCst10BGq56FxslsDrjhSie46c8OULS+BiIw==", + "dependencies": [ + "@smithy/property-provider", + "@smithy/smithy-client", + "@smithy/types", + "tslib" + ] + }, + "@smithy/util-defaults-mode-node@4.2.49": { + "integrity": "sha512-jlN6vHwE8gY5AfiFBavtD3QtCX2f7lM3BKkz7nFKSNfFR5nXLXLg6sqXTJEEyDwtxbztIDBQCfjsGVXlIru2lQ==", + "dependencies": [ + "@smithy/config-resolver", + "@smithy/credential-provider-imds", + "@smithy/node-config-provider", + "@smithy/property-provider", + "@smithy/smithy-client", + "@smithy/types", + "tslib" + ] + }, + "@smithy/util-endpoints@3.3.4": { + "integrity": "sha512-BKoR/ubPp9KNKFxPpg1J28N1+bgu8NGAtJblBP7yHy8yQPBWhIAv9+l92SlQLpolGm71CVO+btB60gTgzT0wog==", + "dependencies": [ + "@smithy/node-config-provider", + "@smithy/types", + "tslib" + ] + }, + "@smithy/util-hex-encoding@4.2.2": { + "integrity": "sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/util-middleware@4.2.13": { + "integrity": "sha512-GTooyrlmRTqvUen4eK7/K1p6kryF7bnDfq6XsAbIsf2mo51B/utaH+XThY6dKgNCWzMAaH/+OLmqaBuLhLWRow==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/util-retry@4.3.0": { + "integrity": "sha512-tSOPQNT/4KfbvqeMovWC3g23KSYy8czHd3tlN+tOYVNIDLSfxIsrPJihYi5TpNcoV789KWtgChUVedh2y6dDPg==", + "dependencies": [ + "@smithy/service-error-classification", + "@smithy/types", + "tslib" + ] + }, + "@smithy/util-stream@4.5.22": { + "integrity": "sha512-3H8iq/0BfQjUs2/4fbHZ9aG9yNzcuZs24LPkcX1Q7Z+qpqaGM8+qbGmE8zo9m2nCRgamyvS98cHdcWvR6YUsew==", + "dependencies": [ + "@smithy/fetch-http-handler", + "@smithy/node-http-handler", + "@smithy/types", + "@smithy/util-base64", + "@smithy/util-buffer-from@4.2.2", + "@smithy/util-hex-encoding", + "@smithy/util-utf8@4.2.2", + "tslib" + ] + }, + "@smithy/util-uri-escape@4.2.2": { + "integrity": "sha512-2kAStBlvq+lTXHyAZYfJRb/DfS3rsinLiwb+69SstC9Vb0s9vNWkRwpnj918Pfi85mzi42sOqdV72OLxWAISnw==", + "dependencies": [ + "tslib" + ] + }, + "@smithy/util-utf8@2.3.0": { + "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==", + "dependencies": [ + "@smithy/util-buffer-from@2.2.0", + "tslib" + ] + }, + "@smithy/util-utf8@4.2.2": { + "integrity": "sha512-75MeYpjdWRe8M5E3AW0O4Cx3UadweS+cwdXjwYGBW5h/gxxnbeZ877sLPX/ZJA9GVTlL/qG0dXP29JWFCD1Ayw==", + "dependencies": [ + "@smithy/util-buffer-from@4.2.2", + "tslib" + ] + }, + "@smithy/util-waiter@4.2.15": { + "integrity": "sha512-oUt9o7n8hBv3BL56sLSneL0XeigZSuem0Hr78JaoK33D9oKieyCvVP8eTSe3j7g2mm/S1DvzxKieG7JEWNJUNg==", + "dependencies": [ + "@smithy/types", + "tslib" + ] + }, + "@smithy/uuid@1.1.2": { + "integrity": "sha512-O/IEdcCUKkubz60tFbGA7ceITTAJsty+lBjNoorP4Z6XRqaFb/OjQjZODophEcuq68nKm6/0r+6/lLQ+XVpk8g==", + "dependencies": [ + "tslib" + ] + }, + "bowser@2.14.1": { + "integrity": "sha512-tzPjzCxygAKWFOJP011oxFHs57HzIhOEracIgAePE4pqB3LikALKnSzUyU4MGs9/iCEUuHlAJTjTc5M+u7YEGg==" + }, + "fast-json-patch@3.1.1": { + "integrity": "sha512-vf6IHUX2SBcA+5/+4883dsIjpBTqmfBjmYiWK1savxQmFk4JfBMLa7ynTYOs1Rolp/T1betJxHiGD3g1Mn8lUQ==" + }, + "fast-xml-builder@1.1.4": { + "integrity": "sha512-f2jhpN4Eccy0/Uz9csxh3Nu6q4ErKxf0XIsasomfOihuSUa3/xw6w8dnOtCDgEItQFJG8KyXPzQXzcODDrrbOg==", + "dependencies": [ + "path-expression-matcher" + ] + }, + "fast-xml-parser@5.5.8": { + "integrity": "sha512-Z7Fh2nVQSb2d+poDViM063ix2ZGt9jmY1nWhPfHBOK2Hgnb/OW3P4Et3P/81SEej0J7QbWtJqxO05h8QYfK7LQ==", + "dependencies": [ + "fast-xml-builder", + "path-expression-matcher", + "strnum" + ], + "bin": true + }, + "path-expression-matcher@1.4.0": { + "integrity": "sha512-s4DQMxIdhj3jLFWd9LxHOplj4p9yQ4ffMGowFf3cpEgrrJjEhN0V5nxw4Ye1EViAGDoL4/1AeO6qHpqYPOzE4Q==" + }, + "strnum@2.2.3": { + "integrity": "sha512-oKx6RUCuHfT3oyVjtnrmn19H1SiCqgJSg+54XqURKp5aCMbrXrhLjRN9TjuwMjiYstZ0MzDrHqkGZ5dFTKd+zg==" + }, + "tslib@2.8.1": { + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==" + }, + "zod@4.3.6": { + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==" + } + }, + "workspace": { + "dependencies": [ + "npm:@aws-sdk/client-cloudcontrol@3.1021.0", + "npm:fast-json-patch@3.1.1", + "npm:zod@4.3.6" + ] + } +} diff --git a/model/aws/s3files/extensions/models/_lib/aws.ts b/model/aws/s3files/extensions/models/_lib/aws.ts new file mode 100644 index 000000000..8a0d63606 --- /dev/null +++ b/model/aws/s3files/extensions/models/_lib/aws.ts @@ -0,0 +1,395 @@ +// Auto-generated shared helper for AWS CloudControl extension models. +// Do not edit manually. Re-generate with: deno task generate:aws + +import { + CloudControlClient, + CreateResourceCommand, + DeleteResourceCommand, + GetResourceCommand, + GetResourceRequestStatusCommand, + UpdateResourceCommand, +} from "@aws-sdk/client-cloudcontrol"; +import jsonpatch from "fast-json-patch"; + +function createClient(): CloudControlClient { + return new CloudControlClient({ + region: Deno.env.get("AWS_REGION") || "us-east-1", + }); +} + +function delay(ms: number): Promise { + return new Promise((resolve) => setTimeout(resolve, ms)); +} + +function isThrottlingError(error: unknown): boolean { + const msg = error instanceof Error ? error.message : String(error); + const name = error instanceof Error ? error.name : ""; + return ( + msg.includes("Throttling") || + msg.includes("TooManyRequests") || + msg.includes("RequestLimitExceeded") || + name === "ThrottlingException" + ); +} + +export function isResourceNotFoundError(error: unknown): boolean { + const msg = error instanceof Error ? error.message : String(error); + const name = error instanceof Error ? error.name : ""; + return ( + msg.includes("was not found") || + msg.includes("does not exist") || + name === "ResourceNotFoundException" + ); +} + +async function withRetry( + operation: () => Promise, + operationName: string, + maxAttempts = 20, +): Promise { + const baseDelay = 1000; + const maxDelay = 90000; + + for (let attempt = 0; attempt < maxAttempts; attempt++) { + try { + return await operation(); + } catch (error) { + if (isThrottlingError(error) && attempt < maxAttempts - 1) { + const exponentialDelay = Math.min( + baseDelay * Math.pow(2, attempt), + maxDelay, + ); + const jitter = Math.random() * 0.3 * exponentialDelay; + console.log( + `[${operationName}] Throttled on attempt ${attempt + 1}, waiting ${ + Math.round(exponentialDelay + jitter) + }ms`, + ); + await delay(exponentialDelay + jitter); + continue; + } + throw error; + } + } + throw new Error(`${operationName} failed after ${maxAttempts} attempts`); +} + +async function pollOperationStatus( + client: CloudControlClient, + requestToken: string, + operationName: string, +): Promise<{ status: string; identifier?: string; message?: string }> { + const baseDelay = 1000; + const maxDelay = 90000; + + for (let attempt = 0; attempt < 60; attempt++) { + const response = await withRetry( + () => + client.send( + new GetResourceRequestStatusCommand({ + RequestToken: requestToken, + }), + ), + `${operationName} status poll`, + ); + + const status = response.ProgressEvent?.OperationStatus; + if (status === "SUCCESS") { + return { + status: "SUCCESS", + identifier: response.ProgressEvent?.Identifier, + }; + } + if (status === "FAILED") { + return { + status: "FAILED", + message: response.ProgressEvent?.StatusMessage || + response.ProgressEvent?.ErrorCode, + }; + } + if (status === "CANCEL_COMPLETE") { + return { + status: "CANCEL_COMPLETE", + message: "Operation cancelled by API or AWS", + }; + } + + const exponentialDelay = Math.min( + baseDelay * Math.pow(2, attempt), + maxDelay, + ); + const jitter = Math.random() * 0.3 * exponentialDelay; + console.log( + `[${operationName}] IN_PROGRESS, waiting ${ + Math.round(exponentialDelay + jitter) + }ms (poll ${attempt + 1})`, + ); + await delay(exponentialDelay + jitter); + } + + throw new Error(`${operationName} timed out after polling`); +} + +/** + * Create an AWS resource via CloudControl API. + * Sends CreateResourceCommand, polls until complete, then reads the resource. + * Returns the resource properties. + */ +export async function createResource( + typeName: string, + desiredState: Record, +): Promise> { + const client = createClient(); + + console.log(`[CREATE] Starting create for ${typeName}`); + + const response = await withRetry( + () => + client.send( + new CreateResourceCommand({ + TypeName: typeName, + DesiredState: JSON.stringify(desiredState), + }), + ), + `${typeName} create`, + ); + + if (!response.ProgressEvent?.RequestToken) { + throw new Error(`${typeName} creation failed: no request token returned`); + } + + const requestToken = response.ProgressEvent.RequestToken; + console.log(`[CREATE] Got request token: ${requestToken}`); + + const pollResult = await pollOperationStatus( + client, + requestToken, + `${typeName} create`, + ); + + if (pollResult.status === "FAILED") { + throw new Error( + `${typeName} creation failed: ${pollResult.message || "Unknown error"}`, + ); + } + if (pollResult.status === "CANCEL_COMPLETE") { + throw new Error( + `${typeName} creation cancelled: ${pollResult.message}`, + ); + } + + const identifier = pollResult.identifier; + if (!identifier) { + throw new Error( + `${typeName} creation succeeded but no identifier returned`, + ); + } + + console.log(`[CREATE] Success, fetching resource ${identifier}`); + + const getResponse = await withRetry( + () => + client.send( + new GetResourceCommand({ + TypeName: typeName, + Identifier: identifier, + }), + ), + `${typeName} create get-resource`, + ); + + if (!getResponse.ResourceDescription?.Properties) { + throw new Error(`Failed to get ${typeName} details after creation`); + } + + return JSON.parse(getResponse.ResourceDescription.Properties); +} + +/** + * Read an AWS resource via CloudControl API. + * Returns the resource properties, or throws if not found. + */ +export async function readResource( + typeName: string, + identifier: string, +): Promise> { + const client = createClient(); + + console.log(`[READ] Fetching ${typeName} identifier: ${identifier}`); + + const response = await withRetry( + () => + client.send( + new GetResourceCommand({ + TypeName: typeName, + Identifier: identifier, + }), + ), + `${typeName} read`, + ); + + if (!response.ResourceDescription?.Properties) { + throw new Error(`Failed to get ${typeName} details`); + } + + return JSON.parse(response.ResourceDescription.Properties); +} + +/** + * Update an AWS resource via CloudControl API. + * Reads current state, computes JSON patch (filtering createOnlyProperties), + * sends UpdateResourceCommand, polls, then reads the updated resource. + */ +export async function updateResource( + typeName: string, + identifier: string, + currentState: Record, + desiredState: Record, + createOnlyProperties?: string[], +): Promise> { + const client = createClient(); + const createOnlySet = new Set(createOnlyProperties ?? []); + + console.log( + `[UPDATE] Starting update for ${typeName} identifier: ${identifier}`, + ); + + // Compute JSON patch, filtering out create-only properties + const rawPatch = jsonpatch.compare(currentState, desiredState); + const patch = rawPatch.filter((op: { path: string }) => { + const topLevelProp = op.path.split("/")[1]; + if (topLevelProp && createOnlySet.has(topLevelProp)) { + console.log(`[UPDATE] Skipping create-only property: ${topLevelProp}`); + return false; + } + return true; + }); + + if (patch.length === 0) { + console.log(`[UPDATE] No changes detected, returning current state`); + return currentState; + } + + console.log(`[UPDATE] Applying ${patch.length} patch operations`); + + const response = await withRetry( + () => + client.send( + new UpdateResourceCommand({ + TypeName: typeName, + Identifier: identifier, + PatchDocument: JSON.stringify(patch), + }), + ), + `${typeName} update`, + ); + + if (!response.ProgressEvent?.RequestToken) { + throw new Error(`${typeName} update failed: no request token returned`); + } + + const requestToken = response.ProgressEvent.RequestToken; + console.log(`[UPDATE] Got request token: ${requestToken}`); + + const pollResult = await pollOperationStatus( + client, + requestToken, + `${typeName} update`, + ); + + if (pollResult.status === "FAILED") { + throw new Error( + `${typeName} update failed: ${pollResult.message || "Unknown error"}`, + ); + } + if (pollResult.status === "CANCEL_COMPLETE") { + throw new Error(`${typeName} update cancelled: ${pollResult.message}`); + } + + const resultIdentifier = pollResult.identifier || identifier; + console.log(`[UPDATE] Success, fetching resource ${resultIdentifier}`); + + const getResponse = await withRetry( + () => + client.send( + new GetResourceCommand({ + TypeName: typeName, + Identifier: resultIdentifier, + }), + ), + `${typeName} update get-resource`, + ); + + if (!getResponse.ResourceDescription?.Properties) { + throw new Error(`Failed to get ${typeName} details after update`); + } + + return JSON.parse(getResponse.ResourceDescription.Properties); +} + +/** + * Delete an AWS resource via CloudControl API. + * Returns { existed: true } on success, { existed: false } if already gone. + */ +export async function deleteResource( + typeName: string, + identifier: string, +): Promise<{ existed: boolean }> { + const client = createClient(); + + console.log( + `[DELETE] Starting delete for ${typeName} identifier: ${identifier}`, + ); + + try { + const response = await withRetry( + () => + client.send( + new DeleteResourceCommand({ + TypeName: typeName, + Identifier: identifier, + }), + ), + `${typeName} delete`, + ); + + if (!response.ProgressEvent?.RequestToken) { + throw new Error(`${typeName} deletion failed: no request token returned`); + } + + const requestToken = response.ProgressEvent.RequestToken; + console.log(`[DELETE] Got request token: ${requestToken}`); + + const pollResult = await pollOperationStatus( + client, + requestToken, + `${typeName} delete`, + ); + + if (pollResult.status === "FAILED") { + if ( + pollResult.message && + (pollResult.message.includes("was not found") || + pollResult.message.includes("does not exist")) + ) { + return { existed: false }; + } + throw new Error( + `${typeName} deletion failed: ${pollResult.message || "Unknown error"}`, + ); + } + + if (pollResult.status === "CANCEL_COMPLETE") { + throw new Error( + `${typeName} deletion cancelled: ${pollResult.message}`, + ); + } + + return { existed: true }; + } catch (error: unknown) { + if (isResourceNotFoundError(error)) { + return { existed: false }; + } + throw error; + } +} diff --git a/model/aws/s3files/extensions/models/access_point.ts b/model/aws/s3files/extensions/models/access_point.ts new file mode 100644 index 000000000..7764b470e --- /dev/null +++ b/model/aws/s3files/extensions/models/access_point.ts @@ -0,0 +1,332 @@ +// Auto-generated extension model for @swamp/aws/s3files/access-point +// Do not edit manually. Re-generate with: deno task generate:aws + +// deno-lint-ignore-file no-explicit-any + +import { z } from "zod"; +import { + createResource, + deleteResource, + isResourceNotFoundError, + readResource, + updateResource, +} from "./_lib/aws.ts"; + +export const AccessPointTagSchema = z.object({ + Key: z.string().min(1).max(128).optional(), + Value: z.string().max(256).optional(), +}); + +export const CreationPermissionsSchema = z.object({ + OwnerUid: z.string().regex(new RegExp("^[0-9]+$")).describe( + "Specifies the POSIX user ID to apply to the RootDirectory. Accepts values from 0 to 2^32 (4294967295).", + ), + OwnerGid: z.string().regex(new RegExp("^[0-9]+$")).describe( + "Specifies the POSIX group ID to apply to the RootDirectory. Accepts values from 0 to 2^32 (4294967295).", + ), + Permissions: z.string().regex(new RegExp("^[0-7]{3,4}$")).describe( + "Specifies the POSIX permissions to apply to the RootDirectory, in the format of an octal number representing the file's mode bits.", + ), +}); + +const GlobalArgsSchema = z.object({ + name: z.string().describe( + "Instance name for this resource (used as the unique identifier in the factory pattern)", + ), + ClientToken: z.string().min(1).max(64).regex(new RegExp("^(.+)$")).describe( + "(optional) A string of up to 64 ASCII characters that Amazon EFS uses to ensure idempotent creation.", + ).optional(), + Tags: z.array(AccessPointTagSchema).optional(), + FileSystemId: z.string().max(128).regex( + new RegExp( + "^(arn:aws[-a-z]*:s3files:[0-9a-z-:]+:file-system/fs-[0-9a-f]{17,40}|fs-[0-9a-f]{17,40})$", + ), + ).describe( + "The ID of the S3 Files file system that the access point provides access to.", + ), + PosixUser: z.object({ + Uid: z.string().regex(new RegExp("^[0-9]+$")).describe( + "The POSIX user ID used for all file system operations using this access point.", + ), + Gid: z.string().regex(new RegExp("^[0-9]+$")).describe( + "The POSIX group ID used for all file system operations using this access point.", + ), + SecondaryGids: z.array(z.string().regex(new RegExp("^[0-9]+$"))).describe( + "Secondary POSIX group IDs used for all file system operations using this access point.", + ).optional(), + }).describe( + "The operating system user and group applied to all compute drive requests made using the access point.", + ).optional(), + RootDirectory: z.object({ + Path: z.string().min(1).max(100).regex( + new RegExp("^(\\/|(\\/(?!\\.)+[^$#<>;;`|&?{}^*/\\n]+){1,4})$"), + ).describe( + "Specifies the path on the EFS file system to expose as the root directory to NFS clients using the access point to access the EFS file system. A path can have up to four subdirectories. If the specified path does not exist, you are required to provide the CreationPermissions.", + ).optional(), + CreationPermissions: CreationPermissionsSchema.describe( + "(Optional) Specifies the POSIX IDs and permissions to apply to the access point's RootDirectory. If the RootDirectory>Path specified does not exist, EFS creates the root directory using the CreationPermissions settings when a client connects to an access point. When specifying the CreationPermissions, you must provide values for all properties. If you do not provide CreationPermissions and the specified RootDirectory>Path does not exist, attempts to mount the file system using the access point will fail.", + ).optional(), + }).describe( + "Specifies the directory on the Amazon EFS file system that the access point exposes as the root directory of your file system to NFS clients using the access point. The clients using the access point can only access the root directory and below. If the RootDirectory>Path specified does not exist, EFS creates it and applies the CreationPermissions settings when a client connects to an access point. When specifying a RootDirectory, you need to provide the Path, and the CreationPermissions is optional.", + ).optional(), +}); + +const StateSchema = z.object({ + AccessPointId: z.string(), + AccessPointArn: z.string().optional(), + ClientToken: z.string().optional(), + Tags: z.array(AccessPointTagSchema).optional(), + FileSystemId: z.string().optional(), + PosixUser: z.object({ + Uid: z.string(), + Gid: z.string(), + SecondaryGids: z.array(z.string()), + }).optional(), + RootDirectory: z.object({ + Path: z.string(), + CreationPermissions: CreationPermissionsSchema, + }).optional(), + Status: z.string().optional(), + OwnerId: z.string().optional(), +}).passthrough(); + +type StateData = z.infer; + +const InputsSchema = z.object({ + name: z.string().optional(), + ClientToken: z.string().min(1).max(64).regex(new RegExp("^(.+)$")).describe( + "(optional) A string of up to 64 ASCII characters that Amazon EFS uses to ensure idempotent creation.", + ).optional(), + Tags: z.array(AccessPointTagSchema).optional(), + FileSystemId: z.string().max(128).regex( + new RegExp( + "^(arn:aws[-a-z]*:s3files:[0-9a-z-:]+:file-system/fs-[0-9a-f]{17,40}|fs-[0-9a-f]{17,40})$", + ), + ).describe( + "The ID of the S3 Files file system that the access point provides access to.", + ).optional(), + PosixUser: z.object({ + Uid: z.string().regex(new RegExp("^[0-9]+$")).describe( + "The POSIX user ID used for all file system operations using this access point.", + ).optional(), + Gid: z.string().regex(new RegExp("^[0-9]+$")).describe( + "The POSIX group ID used for all file system operations using this access point.", + ).optional(), + SecondaryGids: z.array(z.string().regex(new RegExp("^[0-9]+$"))).describe( + "Secondary POSIX group IDs used for all file system operations using this access point.", + ).optional(), + }).describe( + "The operating system user and group applied to all compute drive requests made using the access point.", + ).optional(), + RootDirectory: z.object({ + Path: z.string().min(1).max(100).regex( + new RegExp("^(\\/|(\\/(?!\\.)+[^$#<>;;`|&?{}^*/\\n]+){1,4})$"), + ).describe( + "Specifies the path on the EFS file system to expose as the root directory to NFS clients using the access point to access the EFS file system. A path can have up to four subdirectories. If the specified path does not exist, you are required to provide the CreationPermissions.", + ).optional(), + CreationPermissions: CreationPermissionsSchema.describe( + "(Optional) Specifies the POSIX IDs and permissions to apply to the access point's RootDirectory. If the RootDirectory>Path specified does not exist, EFS creates the root directory using the CreationPermissions settings when a client connects to an access point. When specifying the CreationPermissions, you must provide values for all properties. If you do not provide CreationPermissions and the specified RootDirectory>Path does not exist, attempts to mount the file system using the access point will fail.", + ).optional(), + }).describe( + "Specifies the directory on the Amazon EFS file system that the access point exposes as the root directory of your file system to NFS clients using the access point. The clients using the access point can only access the root directory and below. If the RootDirectory>Path specified does not exist, EFS creates it and applies the CreationPermissions settings when a client connects to an access point. When specifying a RootDirectory, you need to provide the Path, and the CreationPermissions is optional.", + ).optional(), +}); + +export const model = { + type: "@swamp/aws/s3files/access-point", + version: "2026.04.08.1", + globalArguments: GlobalArgsSchema, + inputsSchema: InputsSchema, + resources: { + state: { + description: "S3Files AccessPoint resource state", + schema: StateSchema, + lifetime: "infinite", + garbageCollection: 10, + }, + }, + methods: { + create: { + description: "Create a S3Files AccessPoint", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const desiredState: Record = {}; + for (const [key, value] of Object.entries(g)) { + if (key === "name") continue; + if (value !== undefined) desiredState[key] = value; + } + const result = await createResource( + "AWS::S3Files::AccessPoint", + desiredState, + ) as StateData; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + get: { + description: "Get a S3Files AccessPoint", + arguments: z.object({ + identifier: z.string().describe( + "The primary identifier of the S3Files AccessPoint", + ), + }), + execute: async (args: { identifier: string }, context: any) => { + const result = await readResource( + "AWS::S3Files::AccessPoint", + args.identifier, + ) as StateData; + const instanceName = + (context.globalArgs.name?.toString() ?? args.identifier).replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + update: { + description: "Update a S3Files AccessPoint", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const content = await context.dataRepository.getContent( + context.modelType, + context.modelId, + instanceName, + ); + if (!content) { + throw new Error("No existing state found - run create or get first"); + } + const existing = JSON.parse(new TextDecoder().decode(content)); + const identifier = existing.AccessPointId?.toString(); + if (!identifier) { + throw new Error("No identifier found in existing state"); + } + const currentState = await readResource( + "AWS::S3Files::AccessPoint", + identifier, + ) as StateData; + const desiredState: Record = { ...currentState }; + for (const [key, value] of Object.entries(g)) { + if (key === "name") continue; + if (value !== undefined) desiredState[key] = value; + } + const result = await updateResource( + "AWS::S3Files::AccessPoint", + identifier, + currentState, + desiredState, + [ + "FileSystemId", + "ClientToken", + "PosixUser", + "Uid", + "Gid", + "SecondaryGids", + "RootDirectory", + "Path", + "CreationPermissions", + "OwnerUid", + "OwnerGid", + "Permissions", + ], + ); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + delete: { + description: "Delete a S3Files AccessPoint", + arguments: z.object({ + identifier: z.string().describe( + "The primary identifier of the S3Files AccessPoint", + ), + }), + execute: async (args: { identifier: string }, context: any) => { + const { existed } = await deleteResource( + "AWS::S3Files::AccessPoint", + args.identifier, + ); + const instanceName = + (context.globalArgs.name?.toString() ?? args.identifier).replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource("state", instanceName, { + identifier: args.identifier, + existed, + status: existed ? "deleted" : "not_found", + deletedAt: new Date().toISOString(), + }); + return { dataHandles: [handle] }; + }, + }, + sync: { + description: "Sync S3Files AccessPoint state from AWS", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const content = await context.dataRepository.getContent( + context.modelType, + context.modelId, + instanceName, + ); + if (!content) { + throw new Error("No existing state found - run create or get first"); + } + const existing = JSON.parse(new TextDecoder().decode(content)); + const identifier = existing.AccessPointId?.toString(); + if (!identifier) { + throw new Error("No identifier found in existing state"); + } + try { + const result = await readResource( + "AWS::S3Files::AccessPoint", + identifier, + ) as StateData; + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + } catch (error: unknown) { + if (isResourceNotFoundError(error)) { + const handle = await context.writeResource("state", instanceName, { + identifier, + status: "not_found", + syncedAt: new Date().toISOString(), + }); + return { dataHandles: [handle] }; + } + throw error; + } + }, + }, + }, +}; diff --git a/model/aws/s3files/extensions/models/file_system.ts b/model/aws/s3files/extensions/models/file_system.ts new file mode 100644 index 000000000..d5d1e1574 --- /dev/null +++ b/model/aws/s3files/extensions/models/file_system.ts @@ -0,0 +1,297 @@ +// Auto-generated extension model for @swamp/aws/s3files/file-system +// Do not edit manually. Re-generate with: deno task generate:aws + +// deno-lint-ignore-file no-explicit-any + +import { z } from "zod"; +import { + createResource, + deleteResource, + isResourceNotFoundError, + readResource, + updateResource, +} from "./_lib/aws.ts"; + +export const TagSchema = z.object({ + Key: z.string().min(1).max(128).regex( + new RegExp("^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]+)$", "u"), + ), + Value: z.string().max(256).regex( + new RegExp("^([\\p{L}\\p{Z}\\p{N}_.:/=+\\-@]*)$", "u"), + ), +}); + +export const ImportDataRuleSchema = z.object({ + Prefix: z.string().min(0).max(1024).regex(new RegExp("^(|.*/)$")), + Trigger: z.enum(["ON_DIRECTORY_FIRST_ACCESS", "ON_FILE_ACCESS"]), + SizeLessThan: z.number().int().min(0).max(52673613135872), +}); + +export const ExpirationDataRuleSchema = z.object({ + DaysAfterLastAccess: z.number().int().min(1).max(365), +}); + +const GlobalArgsSchema = z.object({ + name: z.string().describe( + "Instance name for this resource (used as the unique identifier in the factory pattern)", + ), + Tags: z.array(TagSchema).optional(), + KmsKeyId: z.string().max(2048).regex( + new RegExp( + "^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|mrk-[0-9a-f]{32}|alias/[a-zA-Z0-9/_-]+|(arn:aws[-a-z]*:kms:[a-z0-9-]+:\\d{12}:((key/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})|(key/mrk-[0-9a-f]{32})|(alias/[a-zA-Z0-9/_-]+))))$", + ), + ).optional(), + Bucket: z.string().regex(new RegExp("^(arn:aws[a-zA-Z0-9-]*:s3:::.+)$")), + Prefix: z.string().max(1024).regex(new RegExp("^(|.*/)$")).optional(), + ClientToken: z.string().min(1).max(64).regex(new RegExp("^(.+)$")).optional(), + RoleArn: z.string().max(2048).regex( + new RegExp( + "^arn:(aws[a-zA-Z-]*)?:iam::\\d{12}:role/?[a-zA-Z_0-9+=,.@\\-_/]+$", + ), + ), + SynchronizationConfiguration: z.object({ + ImportDataRules: z.array(ImportDataRuleSchema), + ExpirationDataRules: z.array(ExpirationDataRuleSchema), + }).optional(), + AcceptBucketWarning: z.boolean().optional(), +}); + +const StateSchema = z.object({ + CreationTime: z.string().optional(), + FileSystemId: z.string().optional(), + FileSystemArn: z.string(), + Tags: z.array(TagSchema).optional(), + KmsKeyId: z.string().optional(), + Bucket: z.string().optional(), + Prefix: z.string().optional(), + ClientToken: z.string().optional(), + RoleArn: z.string().optional(), + Status: z.string().optional(), + StatusMessage: z.string().optional(), + OwnerId: z.string().optional(), + SynchronizationConfiguration: z.object({ + LatestVersionNumber: z.number(), + ImportDataRules: z.array(ImportDataRuleSchema), + ExpirationDataRules: z.array(ExpirationDataRuleSchema), + }).optional(), + AcceptBucketWarning: z.boolean().optional(), +}).passthrough(); + +type StateData = z.infer; + +const InputsSchema = z.object({ + name: z.string().optional(), + Tags: z.array(TagSchema).optional(), + KmsKeyId: z.string().max(2048).regex( + new RegExp( + "^([0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}|mrk-[0-9a-f]{32}|alias/[a-zA-Z0-9/_-]+|(arn:aws[-a-z]*:kms:[a-z0-9-]+:\\d{12}:((key/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})|(key/mrk-[0-9a-f]{32})|(alias/[a-zA-Z0-9/_-]+))))$", + ), + ).optional(), + Bucket: z.string().regex(new RegExp("^(arn:aws[a-zA-Z0-9-]*:s3:::.+)$")) + .optional(), + Prefix: z.string().max(1024).regex(new RegExp("^(|.*/)$")).optional(), + ClientToken: z.string().min(1).max(64).regex(new RegExp("^(.+)$")).optional(), + RoleArn: z.string().max(2048).regex( + new RegExp( + "^arn:(aws[a-zA-Z-]*)?:iam::\\d{12}:role/?[a-zA-Z_0-9+=,.@\\-_/]+$", + ), + ).optional(), + SynchronizationConfiguration: z.object({ + ImportDataRules: z.array(ImportDataRuleSchema).optional(), + ExpirationDataRules: z.array(ExpirationDataRuleSchema).optional(), + }).optional(), + AcceptBucketWarning: z.boolean().optional(), +}); + +export const model = { + type: "@swamp/aws/s3files/file-system", + version: "2026.04.08.1", + globalArguments: GlobalArgsSchema, + inputsSchema: InputsSchema, + resources: { + state: { + description: "S3Files FileSystem resource state", + schema: StateSchema, + lifetime: "infinite", + garbageCollection: 10, + }, + }, + methods: { + create: { + description: "Create a S3Files FileSystem", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const desiredState: Record = {}; + for (const [key, value] of Object.entries(g)) { + if (key === "name") continue; + if (value !== undefined) desiredState[key] = value; + } + const result = await createResource( + "AWS::S3Files::FileSystem", + desiredState, + ) as StateData; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + get: { + description: "Get a S3Files FileSystem", + arguments: z.object({ + identifier: z.string().describe( + "The primary identifier of the S3Files FileSystem", + ), + }), + execute: async (args: { identifier: string }, context: any) => { + const result = await readResource( + "AWS::S3Files::FileSystem", + args.identifier, + ) as StateData; + const instanceName = + (context.globalArgs.name?.toString() ?? args.identifier).replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + update: { + description: "Update a S3Files FileSystem", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const content = await context.dataRepository.getContent( + context.modelType, + context.modelId, + instanceName, + ); + if (!content) { + throw new Error("No existing state found - run create or get first"); + } + const existing = JSON.parse(new TextDecoder().decode(content)); + const identifier = existing.FileSystemArn?.toString(); + if (!identifier) { + throw new Error("No identifier found in existing state"); + } + const currentState = await readResource( + "AWS::S3Files::FileSystem", + identifier, + ) as StateData; + const desiredState: Record = { ...currentState }; + for (const [key, value] of Object.entries(g)) { + if (key === "name") continue; + if (value !== undefined) desiredState[key] = value; + } + const result = await updateResource( + "AWS::S3Files::FileSystem", + identifier, + currentState, + desiredState, + [ + "Bucket", + "Prefix", + "ClientToken", + "KmsKeyId", + "RoleArn", + "AcceptBucketWarning", + ], + ); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + delete: { + description: "Delete a S3Files FileSystem", + arguments: z.object({ + identifier: z.string().describe( + "The primary identifier of the S3Files FileSystem", + ), + }), + execute: async (args: { identifier: string }, context: any) => { + const { existed } = await deleteResource( + "AWS::S3Files::FileSystem", + args.identifier, + ); + const instanceName = + (context.globalArgs.name?.toString() ?? args.identifier).replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource("state", instanceName, { + identifier: args.identifier, + existed, + status: existed ? "deleted" : "not_found", + deletedAt: new Date().toISOString(), + }); + return { dataHandles: [handle] }; + }, + }, + sync: { + description: "Sync S3Files FileSystem state from AWS", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const content = await context.dataRepository.getContent( + context.modelType, + context.modelId, + instanceName, + ); + if (!content) { + throw new Error("No existing state found - run create or get first"); + } + const existing = JSON.parse(new TextDecoder().decode(content)); + const identifier = existing.FileSystemArn?.toString(); + if (!identifier) { + throw new Error("No identifier found in existing state"); + } + try { + const result = await readResource( + "AWS::S3Files::FileSystem", + identifier, + ) as StateData; + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + } catch (error: unknown) { + if (isResourceNotFoundError(error)) { + const handle = await context.writeResource("state", instanceName, { + identifier, + status: "not_found", + syncedAt: new Date().toISOString(), + }); + return { dataHandles: [handle] }; + } + throw error; + } + }, + }, + }, +}; diff --git a/model/aws/s3files/extensions/models/file_system_policy.ts b/model/aws/s3files/extensions/models/file_system_policy.ts new file mode 100644 index 000000000..26a66aa6d --- /dev/null +++ b/model/aws/s3files/extensions/models/file_system_policy.ts @@ -0,0 +1,220 @@ +// Auto-generated extension model for @swamp/aws/s3files/file-system-policy +// Do not edit manually. Re-generate with: deno task generate:aws + +// deno-lint-ignore-file no-explicit-any + +import { z } from "zod"; +import { + createResource, + deleteResource, + isResourceNotFoundError, + readResource, + updateResource, +} from "./_lib/aws.ts"; + +const GlobalArgsSchema = z.object({ + FileSystemId: z.string().max(128).regex( + new RegExp( + "^(arn:aws[-a-z]*:s3files:[0-9a-z-:]+:file-system/fs-[0-9a-f]{17,40}|fs-[0-9a-f]{17,40})$", + ), + ), + Policy: z.string(), +}); + +const StateSchema = z.object({ + FileSystemId: z.string(), + Policy: z.string().optional(), +}).passthrough(); + +type StateData = z.infer; + +const InputsSchema = z.object({ + FileSystemId: z.string().max(128).regex( + new RegExp( + "^(arn:aws[-a-z]*:s3files:[0-9a-z-:]+:file-system/fs-[0-9a-f]{17,40}|fs-[0-9a-f]{17,40})$", + ), + ).optional(), + Policy: z.string().optional(), +}); + +export const model = { + type: "@swamp/aws/s3files/file-system-policy", + version: "2026.04.08.1", + globalArguments: GlobalArgsSchema, + inputsSchema: InputsSchema, + resources: { + state: { + description: "S3Files FileSystemPolicy resource state", + schema: StateSchema, + lifetime: "infinite", + garbageCollection: 10, + }, + }, + methods: { + create: { + description: "Create a S3Files FileSystemPolicy", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const desiredState: Record = {}; + for (const [key, value] of Object.entries(g)) { + if (value !== undefined) desiredState[key] = value; + } + const result = await createResource( + "AWS::S3Files::FileSystemPolicy", + desiredState, + ) as StateData; + const instanceName = + ((result.FileSystemId ?? g.FileSystemId)?.toString() ?? "current") + .replace(/[\/\\]/g, "_").replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + get: { + description: "Get a S3Files FileSystemPolicy", + arguments: z.object({ + identifier: z.string().describe( + "The primary identifier of the S3Files FileSystemPolicy", + ), + }), + execute: async (args: { identifier: string }, context: any) => { + const result = await readResource( + "AWS::S3Files::FileSystemPolicy", + args.identifier, + ) as StateData; + const instanceName = + ((result.FileSystemId ?? context.globalArgs.FileSystemId) + ?.toString() ?? args.identifier).replace(/[\/\\]/g, "_").replace( + /\.\./g, + "_", + ).replace(/\0/g, ""); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + update: { + description: "Update a S3Files FileSystemPolicy", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const instanceName = (g.FileSystemId?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const content = await context.dataRepository.getContent( + context.modelType, + context.modelId, + instanceName, + ); + if (!content) { + throw new Error("No existing state found - run create or get first"); + } + const existing = JSON.parse(new TextDecoder().decode(content)); + const identifier = existing.FileSystemId?.toString(); + if (!identifier) { + throw new Error("No identifier found in existing state"); + } + const currentState = await readResource( + "AWS::S3Files::FileSystemPolicy", + identifier, + ) as StateData; + const desiredState: Record = { ...currentState }; + for (const [key, value] of Object.entries(g)) { + if (value !== undefined) desiredState[key] = value; + } + const result = await updateResource( + "AWS::S3Files::FileSystemPolicy", + identifier, + currentState, + desiredState, + ["FileSystemId"], + ); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + delete: { + description: "Delete a S3Files FileSystemPolicy", + arguments: z.object({ + identifier: z.string().describe( + "The primary identifier of the S3Files FileSystemPolicy", + ), + }), + execute: async (args: { identifier: string }, context: any) => { + const { existed } = await deleteResource( + "AWS::S3Files::FileSystemPolicy", + args.identifier, + ); + const instanceName = + (context.globalArgs.FileSystemId?.toString() ?? args.identifier) + .replace(/[\/\\]/g, "_").replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource("state", instanceName, { + identifier: args.identifier, + existed, + status: existed ? "deleted" : "not_found", + deletedAt: new Date().toISOString(), + }); + return { dataHandles: [handle] }; + }, + }, + sync: { + description: "Sync S3Files FileSystemPolicy state from AWS", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const instanceName = (g.FileSystemId?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const content = await context.dataRepository.getContent( + context.modelType, + context.modelId, + instanceName, + ); + if (!content) { + throw new Error("No existing state found - run create or get first"); + } + const existing = JSON.parse(new TextDecoder().decode(content)); + const identifier = existing.FileSystemId?.toString(); + if (!identifier) { + throw new Error("No identifier found in existing state"); + } + try { + const result = await readResource( + "AWS::S3Files::FileSystemPolicy", + identifier, + ) as StateData; + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + } catch (error: unknown) { + if (isResourceNotFoundError(error)) { + const handle = await context.writeResource("state", instanceName, { + identifier, + status: "not_found", + syncedAt: new Date().toISOString(), + }); + return { dataHandles: [handle] }; + } + throw error; + } + }, + }, + }, +}; diff --git a/model/aws/s3files/extensions/models/mount_target.ts b/model/aws/s3files/extensions/models/mount_target.ts new file mode 100644 index 000000000..85774c77a --- /dev/null +++ b/model/aws/s3files/extensions/models/mount_target.ts @@ -0,0 +1,265 @@ +// Auto-generated extension model for @swamp/aws/s3files/mount-target +// Do not edit manually. Re-generate with: deno task generate:aws + +// deno-lint-ignore-file no-explicit-any + +import { z } from "zod"; +import { + createResource, + deleteResource, + isResourceNotFoundError, + readResource, + updateResource, +} from "./_lib/aws.ts"; + +const GlobalArgsSchema = z.object({ + name: z.string().describe( + "Instance name for this resource (used as the unique identifier in the factory pattern)", + ), + Ipv4Address: z.string().min(7).max(15).regex( + new RegExp("^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$"), + ).optional(), + Ipv6Address: z.string().min(3).max(39).optional(), + IpAddressType: z.enum(["IPV4_ONLY", "IPV6_ONLY", "DUAL_STACK"]).optional(), + FileSystemId: z.string().max(128).regex( + new RegExp( + "^(arn:aws[-a-z]*:s3files:[0-9a-z-:]+:file-system/fs-[0-9a-f]{17,40}|fs-[0-9a-f]{17,40})$", + ), + ), + SecurityGroups: z.array( + z.string().min(11).max(43).regex(new RegExp("^(sg-[0-9a-f]{8,40})$")), + ).optional(), + SubnetId: z.string().min(15).max(47).regex( + new RegExp("^subnet-[0-9a-f]{8,40}$"), + ), +}); + +const StateSchema = z.object({ + MountTargetId: z.string(), + Ipv4Address: z.string().optional(), + Ipv6Address: z.string().optional(), + IpAddressType: z.string().optional(), + FileSystemId: z.string().optional(), + SecurityGroups: z.array(z.string()).optional(), + SubnetId: z.string().optional(), + AvailabilityZoneId: z.string().optional(), + OwnerId: z.string().optional(), + NetworkInterfaceId: z.string().optional(), + VpcId: z.string().optional(), + Status: z.string().optional(), + StatusMessage: z.string().optional(), +}).passthrough(); + +type StateData = z.infer; + +const InputsSchema = z.object({ + name: z.string().optional(), + Ipv4Address: z.string().min(7).max(15).regex( + new RegExp("^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}$"), + ).optional(), + Ipv6Address: z.string().min(3).max(39).optional(), + IpAddressType: z.enum(["IPV4_ONLY", "IPV6_ONLY", "DUAL_STACK"]).optional(), + FileSystemId: z.string().max(128).regex( + new RegExp( + "^(arn:aws[-a-z]*:s3files:[0-9a-z-:]+:file-system/fs-[0-9a-f]{17,40}|fs-[0-9a-f]{17,40})$", + ), + ).optional(), + SecurityGroups: z.array( + z.string().min(11).max(43).regex(new RegExp("^(sg-[0-9a-f]{8,40})$")), + ).optional(), + SubnetId: z.string().min(15).max(47).regex( + new RegExp("^subnet-[0-9a-f]{8,40}$"), + ).optional(), +}); + +export const model = { + type: "@swamp/aws/s3files/mount-target", + version: "2026.04.08.1", + globalArguments: GlobalArgsSchema, + inputsSchema: InputsSchema, + resources: { + state: { + description: "S3Files MountTarget resource state", + schema: StateSchema, + lifetime: "infinite", + garbageCollection: 10, + }, + }, + methods: { + create: { + description: "Create a S3Files MountTarget", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const desiredState: Record = {}; + for (const [key, value] of Object.entries(g)) { + if (key === "name") continue; + if (value !== undefined) desiredState[key] = value; + } + const result = await createResource( + "AWS::S3Files::MountTarget", + desiredState, + ) as StateData; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + get: { + description: "Get a S3Files MountTarget", + arguments: z.object({ + identifier: z.string().describe( + "The primary identifier of the S3Files MountTarget", + ), + }), + execute: async (args: { identifier: string }, context: any) => { + const result = await readResource( + "AWS::S3Files::MountTarget", + args.identifier, + ) as StateData; + const instanceName = + (context.globalArgs.name?.toString() ?? args.identifier).replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + update: { + description: "Update a S3Files MountTarget", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const content = await context.dataRepository.getContent( + context.modelType, + context.modelId, + instanceName, + ); + if (!content) { + throw new Error("No existing state found - run create or get first"); + } + const existing = JSON.parse(new TextDecoder().decode(content)); + const identifier = existing.MountTargetId?.toString(); + if (!identifier) { + throw new Error("No identifier found in existing state"); + } + const currentState = await readResource( + "AWS::S3Files::MountTarget", + identifier, + ) as StateData; + const desiredState: Record = { ...currentState }; + for (const [key, value] of Object.entries(g)) { + if (key === "name") continue; + if (value !== undefined) desiredState[key] = value; + } + const result = await updateResource( + "AWS::S3Files::MountTarget", + identifier, + currentState, + desiredState, + [ + "Ipv4Address", + "Ipv6Address", + "IpAddressType", + "SubnetId", + "FileSystemId", + ], + ); + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + }, + }, + delete: { + description: "Delete a S3Files MountTarget", + arguments: z.object({ + identifier: z.string().describe( + "The primary identifier of the S3Files MountTarget", + ), + }), + execute: async (args: { identifier: string }, context: any) => { + const { existed } = await deleteResource( + "AWS::S3Files::MountTarget", + args.identifier, + ); + const instanceName = + (context.globalArgs.name?.toString() ?? args.identifier).replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const handle = await context.writeResource("state", instanceName, { + identifier: args.identifier, + existed, + status: existed ? "deleted" : "not_found", + deletedAt: new Date().toISOString(), + }); + return { dataHandles: [handle] }; + }, + }, + sync: { + description: "Sync S3Files MountTarget state from AWS", + arguments: z.object({}), + execute: async (_args: Record, context: any) => { + const g = context.globalArgs; + const instanceName = (g.name?.toString() ?? "current").replace( + /[\/\\]/g, + "_", + ).replace(/\.\./g, "_").replace(/\0/g, ""); + const content = await context.dataRepository.getContent( + context.modelType, + context.modelId, + instanceName, + ); + if (!content) { + throw new Error("No existing state found - run create or get first"); + } + const existing = JSON.parse(new TextDecoder().decode(content)); + const identifier = existing.MountTargetId?.toString(); + if (!identifier) { + throw new Error("No identifier found in existing state"); + } + try { + const result = await readResource( + "AWS::S3Files::MountTarget", + identifier, + ) as StateData; + const handle = await context.writeResource( + "state", + instanceName, + result, + ); + return { dataHandles: [handle] }; + } catch (error: unknown) { + if (isResourceNotFoundError(error)) { + const handle = await context.writeResource("state", instanceName, { + identifier, + status: "not_found", + syncedAt: new Date().toISOString(), + }); + return { dataHandles: [handle] }; + } + throw error; + } + }, + }, + }, +}; diff --git a/model/aws/s3files/manifest.yaml b/model/aws/s3files/manifest.yaml new file mode 100644 index 000000000..578bf2ed3 --- /dev/null +++ b/model/aws/s3files/manifest.yaml @@ -0,0 +1,20 @@ +# Auto-generated manifest. Re-generate with the appropriate deno task. +manifestVersion: 1 +name: "@swamp/aws/s3files" +version: "2026.04.08.1" +description: "AWS S3FILES infrastructure models" +labels: + - aws + - s3files + - cloud + - infrastructure +releaseNotes: | + - Added: access_point, file_system, file_system_policy, mount_target +models: + - access_point.ts + - file_system.ts + - file_system_policy.ts + - mount_target.ts +additionalFiles: + - LICENSE.txt + - README.md diff --git a/model/digitalocean/extensions/models/nfs.ts b/model/digitalocean/extensions/models/nfs.ts index c601aac57..bfc107f2e 100644 --- a/model/digitalocean/extensions/models/nfs.ts +++ b/model/digitalocean/extensions/models/nfs.ts @@ -84,7 +84,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/digitalocean/nfs", - version: "2026.04.03.2", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.03.27.1", @@ -111,6 +111,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, @@ -357,6 +362,67 @@ export const model = { return { dataHandles: handles }; }, }, + reassign: { + description: "reassign the nfs", + arguments: z.object({ + id: z.union([z.string(), z.number()]).describe("The ID of the nfs"), + region: z.string().describe( + "The DigitalOcean region slug (e.g. atl1, nyc2) where the NFS snapshot resides.", + ).optional(), + old_vpc_id: z.string().describe( + "The ID of the VPC from which the NFS share will be reassigned", + ), + new_vpc_id: z.string().describe( + "The ID of the VPC to which the NFS share will be reassigned", + ), + waitForCompletion: z.boolean().describe( + "Wait for the action to complete before returning (default: true)", + ).optional(), + }), + execute: async ( + args: { + id: string | number; + region?: string; + old_vpc_id: string; + new_vpc_id: string; + waitForCompletion?: boolean; + }, + context: any, + ) => { + const params: Record = {}; + if (args.old_vpc_id !== undefined) params.old_vpc_id = args.old_vpc_id; + if (args.new_vpc_id !== undefined) params.new_vpc_id = args.new_vpc_id; + const body: Record = { type: "reassign", params }; + if (args.region !== undefined) body.region = args.region; + const { action: actionResult, resource: updatedResource } = + await createAndPollAction( + "/v2/nfs", + args.id, + body, + args.waitForCompletion ?? true, + ); + const actionInstanceName = `${args.id}-reassign`; + const handles = []; + const actionHandle = await context.writeResource( + "nfs_action", + actionInstanceName, + actionResult, + ); + handles.push(actionHandle); + if (updatedResource) { + const resourceInstanceName = + (updatedResource as Record).name?.toString() ?? + args.id.toString(); + const stateHandle = await context.writeResource( + "state", + resourceInstanceName, + updatedResource, + ); + handles.push(stateHandle); + } + return { dataHandles: handles }; + }, + }, resize: { description: "resize the nfs", arguments: z.object({ diff --git a/model/digitalocean/manifest.yaml b/model/digitalocean/manifest.yaml index e6bb3c38f..89226918b 100644 --- a/model/digitalocean/manifest.yaml +++ b/model/digitalocean/manifest.yaml @@ -1,14 +1,14 @@ # Auto-generated manifest. Re-generate with the appropriate deno task. manifestVersion: 1 name: "@swamp/digitalocean" -version: "2026.04.03.2" +version: "2026.04.08.1" description: "DigitalOcean infrastructure models" labels: - digitalocean - cloud - infrastructure releaseNotes: | - - Updated: app_platform, byoip_prefix, cdn_endpoint, container_registry, custom_image, database_cluster, dedicated_inference, domain, droplet, droplet_autoscale, firewall, floating_ip, function_namespace, kubernetes_cluster, load_balancer, monitoring_alert_policy, monitoring_sink, monitoring_sink_destination, nfs, partner_network_connect_attachment, project, reserved_ip, reserved_ipv6, security_scan, space_key, ssh_key, ssl_certificate, tag, uptime_check, volume, vpc, vpc_nat_gateway, vpc_peering + - Updated: nfs models: - app_platform.ts - byoip_prefix.ts diff --git a/model/gcp/chat/extensions/models/spaces.ts b/model/gcp/chat/extensions/models/spaces.ts index 83de8b3c4..b9e8d4783 100644 --- a/model/gcp/chat/extensions/models/spaces.ts +++ b/model/gcp/chat/extensions/models/spaces.ts @@ -474,7 +474,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/chat/spaces", - version: "2026.04.03.3", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.2", @@ -501,6 +501,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, @@ -791,6 +796,32 @@ export const model = { return { result }; }, }, + find_group_chats: { + description: "find group chats", + arguments: z.object({}), + execute: async (_args: Record, _context: any) => { + const projectId = await getProjectId(); + const params: Record = { project: projectId }; + const result = await createResource( + BASE_URL, + { + "id": "chat.spaces.findGroupChats", + "path": "v1/spaces:findGroupChats", + "httpMethod": "GET", + "parameterOrder": [], + "parameters": { + "pageSize": { "location": "query" }, + "pageToken": { "location": "query" }, + "spaceView": { "location": "query" }, + "users": { "location": "query" }, + }, + }, + params, + {}, + ); + return { result }; + }, + }, search: { description: "search", arguments: z.object({}), diff --git a/model/gcp/chat/manifest.yaml b/model/gcp/chat/manifest.yaml index 34b63f6ee..4341c42d9 100644 --- a/model/gcp/chat/manifest.yaml +++ b/model/gcp/chat/manifest.yaml @@ -1,7 +1,7 @@ # Auto-generated manifest. Re-generate with the appropriate deno task. manifestVersion: 1 name: "@swamp/gcp/chat" -version: "2026.04.04.1" +version: "2026.04.08.1" description: "Google Cloud chat infrastructure models" labels: - gcp @@ -10,7 +10,7 @@ labels: - cloud - infrastructure releaseNotes: | - - Updated: spaces_messages, spaces_spaceevents + - Updated: spaces models: - customemojis.ts - spaces.ts diff --git a/model/gcp/discoveryengine/extensions/models/collections_datastores_servingconfigs.ts b/model/gcp/discoveryengine/extensions/models/collections_datastores_servingconfigs.ts index cfd46127c..3bba38d31 100644 --- a/model/gcp/discoveryengine/extensions/models/collections_datastores_servingconfigs.ts +++ b/model/gcp/discoveryengine/extensions/models/collections_datastores_servingconfigs.ts @@ -578,7 +578,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/discoveryengine/collections-datastores-servingconfigs", - version: "2026.04.03.3", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -605,6 +605,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, @@ -1061,8 +1066,10 @@ export const model = { canonicalFilter: z.any().optional(), contentSearchSpec: z.any().optional(), crowdingSpecs: z.any().optional(), + customRankingParams: z.any().optional(), dataStoreSpecs: z.any().optional(), displaySpec: z.any().optional(), + entity: z.any().optional(), facetSpecs: z.any().optional(), filter: z.any().optional(), imageQuery: z.any().optional(), @@ -1123,12 +1130,16 @@ export const model = { if (args["crowdingSpecs"] !== undefined) { body["crowdingSpecs"] = args["crowdingSpecs"]; } + if (args["customRankingParams"] !== undefined) { + body["customRankingParams"] = args["customRankingParams"]; + } if (args["dataStoreSpecs"] !== undefined) { body["dataStoreSpecs"] = args["dataStoreSpecs"]; } if (args["displaySpec"] !== undefined) { body["displaySpec"] = args["displaySpec"]; } + if (args["entity"] !== undefined) body["entity"] = args["entity"]; if (args["facetSpecs"] !== undefined) { body["facetSpecs"] = args["facetSpecs"]; } @@ -1221,8 +1232,10 @@ export const model = { canonicalFilter: z.any().optional(), contentSearchSpec: z.any().optional(), crowdingSpecs: z.any().optional(), + customRankingParams: z.any().optional(), dataStoreSpecs: z.any().optional(), displaySpec: z.any().optional(), + entity: z.any().optional(), facetSpecs: z.any().optional(), filter: z.any().optional(), imageQuery: z.any().optional(), @@ -1283,12 +1296,16 @@ export const model = { if (args["crowdingSpecs"] !== undefined) { body["crowdingSpecs"] = args["crowdingSpecs"]; } + if (args["customRankingParams"] !== undefined) { + body["customRankingParams"] = args["customRankingParams"]; + } if (args["dataStoreSpecs"] !== undefined) { body["dataStoreSpecs"] = args["dataStoreSpecs"]; } if (args["displaySpec"] !== undefined) { body["displaySpec"] = args["displaySpec"]; } + if (args["entity"] !== undefined) body["entity"] = args["entity"]; if (args["facetSpecs"] !== undefined) { body["facetSpecs"] = args["facetSpecs"]; } diff --git a/model/gcp/discoveryengine/extensions/models/collections_datastores_sessions.ts b/model/gcp/discoveryengine/extensions/models/collections_datastores_sessions.ts index e798b787a..c72d2545a 100644 --- a/model/gcp/discoveryengine/extensions/models/collections_datastores_sessions.ts +++ b/model/gcp/discoveryengine/extensions/models/collections_datastores_sessions.ts @@ -52,6 +52,9 @@ const INSERT_CONFIG = { "location": "path", "required": true, }, + "sessionId": { + "location": "query", + }, }, } as const; @@ -240,6 +243,8 @@ const GlobalArgsSchema = z.object({ "Immutable. Identifier. Resource name of the `AssistAnswer`. Format: `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/sessions/{session}/assistAnswers/{assist_answer}` This field must be a UTF-8 encoded string with a length limit of 1024 characters.", ).optional(), replies: z.array(z.object({ + createTime: z.unknown().describe("The time when the reply was created.") + .optional(), groundedContent: z.unknown().describe( 'A piece of content and possibly its grounding information. Not all content needs grounding. Phrases like "Of course, I will gladly search it for you." do not need grounding.', ).optional(), @@ -264,6 +269,9 @@ const GlobalArgsSchema = z.object({ })).describe("Turns.").optional(), userPseudoId: z.string().describe("A unique identifier for tracking users.") .optional(), + sessionId: z.string().describe( + "Optional. The ID to use for the session, which will become the final component of the session's resource name. This value should be 1-63 characters, and valid characters are /a-z0-9{0,61}[a-z0-9]/. If not specified, a unique ID will be generated.", + ).optional(), location: z.string().describe( "The location for this resource (e.g., 'us', 'us-central1', 'europe-west1')", ).optional(), @@ -331,6 +339,7 @@ const StateSchema = z.object({ }), name: z.string(), replies: z.array(z.object({ + createTime: z.unknown(), groundedContent: z.unknown(), })), state: z.string(), @@ -496,6 +505,8 @@ const InputsSchema = z.object({ "Immutable. Identifier. Resource name of the `AssistAnswer`. Format: `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/sessions/{session}/assistAnswers/{assist_answer}` This field must be a UTF-8 encoded string with a length limit of 1024 characters.", ).optional(), replies: z.array(z.object({ + createTime: z.unknown().describe("The time when the reply was created.") + .optional(), groundedContent: z.unknown().describe( 'A piece of content and possibly its grounding information. Not all content needs grounding. Phrases like "Of course, I will gladly search it for you." do not need grounding.', ).optional(), @@ -520,6 +531,9 @@ const InputsSchema = z.object({ })).describe("Turns.").optional(), userPseudoId: z.string().describe("A unique identifier for tracking users.") .optional(), + sessionId: z.string().describe( + "Optional. The ID to use for the session, which will become the final component of the session's resource name. This value should be 1-63 characters, and valid characters are /a-z0-9{0,61}[a-z0-9]/. If not specified, a unique ID will be generated.", + ).optional(), location: z.string().describe( "The location for this resource (e.g., 'us', 'us-central1', 'europe-west1')", ).optional(), @@ -527,7 +541,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/discoveryengine/collections-datastores-sessions", - version: "2026.04.04.1", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -559,6 +573,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "Added: sessionId", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, @@ -591,6 +610,7 @@ export const model = { if (g["userPseudoId"] !== undefined) { body["userPseudoId"] = g["userPseudoId"]; } + if (g["sessionId"] !== undefined) body["sessionId"] = g["sessionId"]; if (g["parent"] !== undefined && g["name"] !== undefined) { params["name"] = buildResourceName( String(g["parent"]), diff --git a/model/gcp/discoveryengine/extensions/models/collections_datastores_widgetconfigs.ts b/model/gcp/discoveryengine/extensions/models/collections_datastores_widgetconfigs.ts index 5486799a3..86a52ac74 100644 --- a/model/gcp/discoveryengine/extensions/models/collections_datastores_widgetconfigs.ts +++ b/model/gcp/discoveryengine/extensions/models/collections_datastores_widgetconfigs.ts @@ -386,7 +386,7 @@ const GlobalArgsSchema = z.object({ "FEATURE_STATE_OFF", ]), ).describe( - "Output only. Feature config for the engine to opt in or opt out of features. Supported keys: * `agent-gallery` * `no-code-agent-builder` * `prompt-gallery` * `model-selector` * `notebook-lm` * `people-search` * `people-search-org-chart` * `bi-directional-audio` * `feedback` * `session-sharing` * `personalization-memory` * `personalization-suggested-highlights` * `disable-agent-sharing` * `disable-image-generation` * `disable-video-generation` * `disable-onedrive-upload` * `disable-talk-to-content` * `disable-google-drive-upload` * `disable-welcome-emails`", + "Output only. Feature config for the engine to opt in or opt out of features. Supported keys: * `agent-gallery` * `no-code-agent-builder` * `prompt-gallery` * `model-selector` * `notebook-lm` * `people-search` * `people-search-org-chart` * `bi-directional-audio` * `feedback` * `session-sharing` * `personalization-memory` * `personalization-suggested-highlights` * `disable-agent-sharing` * `disable-image-generation` * `disable-video-generation` * `disable-onedrive-upload` * `disable-talk-to-content` * `disable-google-drive-upload` * `disable-welcome-emails` * `disable-canvas` * `disable-canvas-workspace`", ).optional(), generativeAnswerConfig: z.object({ disableRelatedQuestions: z.boolean().describe( @@ -951,7 +951,7 @@ const InputsSchema = z.object({ "FEATURE_STATE_OFF", ]), ).describe( - "Output only. Feature config for the engine to opt in or opt out of features. Supported keys: * `agent-gallery` * `no-code-agent-builder` * `prompt-gallery` * `model-selector` * `notebook-lm` * `people-search` * `people-search-org-chart` * `bi-directional-audio` * `feedback` * `session-sharing` * `personalization-memory` * `personalization-suggested-highlights` * `disable-agent-sharing` * `disable-image-generation` * `disable-video-generation` * `disable-onedrive-upload` * `disable-talk-to-content` * `disable-google-drive-upload` * `disable-welcome-emails`", + "Output only. Feature config for the engine to opt in or opt out of features. Supported keys: * `agent-gallery` * `no-code-agent-builder` * `prompt-gallery` * `model-selector` * `notebook-lm` * `people-search` * `people-search-org-chart` * `bi-directional-audio` * `feedback` * `session-sharing` * `personalization-memory` * `personalization-suggested-highlights` * `disable-agent-sharing` * `disable-image-generation` * `disable-video-generation` * `disable-onedrive-upload` * `disable-talk-to-content` * `disable-google-drive-upload` * `disable-welcome-emails` * `disable-canvas` * `disable-canvas-workspace`", ).optional(), generativeAnswerConfig: z.object({ disableRelatedQuestions: z.boolean().describe( @@ -1018,7 +1018,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/discoveryengine/collections-datastores-widgetconfigs", - version: "2026.04.04.1", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -1050,6 +1050,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, diff --git a/model/gcp/discoveryengine/extensions/models/collections_engines.ts b/model/gcp/discoveryengine/extensions/models/collections_engines.ts index 4e4876581..676e3506b 100644 --- a/model/gcp/discoveryengine/extensions/models/collections_engines.ts +++ b/model/gcp/discoveryengine/extensions/models/collections_engines.ts @@ -199,7 +199,7 @@ const GlobalArgsSchema = z.object({ "FEATURE_STATE_OFF", ]), ).describe( - "Optional. Feature config for the engine to opt in or opt out of features. Supported keys: * `*`: all features, if it's present, all other feature state settings are ignored. * `agent-gallery` * `no-code-agent-builder` * `prompt-gallery` * `model-selector` * `notebook-lm` * `people-search` * `people-search-org-chart` * `bi-directional-audio` * `feedback` * `session-sharing` * `personalization-memory` * `personalization-suggested-highlights` * `disable-agent-sharing` * `disable-image-generation` * `disable-video-generation` * `disable-onedrive-upload` * `disable-talk-to-content` * `disable-google-drive-upload` * `disable-welcome-emails`", + "Optional. Feature config for the engine to opt in or opt out of features. Supported keys: * `*`: all features, if it's present, all other feature state settings are ignored. * `agent-gallery` * `no-code-agent-builder` * `prompt-gallery` * `model-selector` * `notebook-lm` * `people-search` * `people-search-org-chart` * `bi-directional-audio` * `feedback` * `session-sharing` * `personalization-memory` * `personalization-suggested-highlights` * `disable-agent-sharing` * `disable-image-generation` * `disable-video-generation` * `disable-onedrive-upload` * `disable-talk-to-content` * `disable-google-drive-upload` * `disable-welcome-emails` * `disable-canvas` * `disable-canvas-workspace`", ).optional(), industryVertical: z.enum([ "INDUSTRY_VERTICAL_UNSPECIFIED", @@ -554,7 +554,7 @@ const InputsSchema = z.object({ "FEATURE_STATE_OFF", ]), ).describe( - "Optional. Feature config for the engine to opt in or opt out of features. Supported keys: * `*`: all features, if it's present, all other feature state settings are ignored. * `agent-gallery` * `no-code-agent-builder` * `prompt-gallery` * `model-selector` * `notebook-lm` * `people-search` * `people-search-org-chart` * `bi-directional-audio` * `feedback` * `session-sharing` * `personalization-memory` * `personalization-suggested-highlights` * `disable-agent-sharing` * `disable-image-generation` * `disable-video-generation` * `disable-onedrive-upload` * `disable-talk-to-content` * `disable-google-drive-upload` * `disable-welcome-emails`", + "Optional. Feature config for the engine to opt in or opt out of features. Supported keys: * `*`: all features, if it's present, all other feature state settings are ignored. * `agent-gallery` * `no-code-agent-builder` * `prompt-gallery` * `model-selector` * `notebook-lm` * `people-search` * `people-search-org-chart` * `bi-directional-audio` * `feedback` * `session-sharing` * `personalization-memory` * `personalization-suggested-highlights` * `disable-agent-sharing` * `disable-image-generation` * `disable-video-generation` * `disable-onedrive-upload` * `disable-talk-to-content` * `disable-google-drive-upload` * `disable-welcome-emails` * `disable-canvas` * `disable-canvas-workspace`", ).optional(), industryVertical: z.enum([ "INDUSTRY_VERTICAL_UNSPECIFIED", @@ -707,7 +707,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/discoveryengine/collections-engines", - version: "2026.04.03.3", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -734,6 +734,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, diff --git a/model/gcp/discoveryengine/extensions/models/collections_engines_servingconfigs.ts b/model/gcp/discoveryengine/extensions/models/collections_engines_servingconfigs.ts index 885378a10..8c89b5a19 100644 --- a/model/gcp/discoveryengine/extensions/models/collections_engines_servingconfigs.ts +++ b/model/gcp/discoveryengine/extensions/models/collections_engines_servingconfigs.ts @@ -578,7 +578,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/discoveryengine/collections-engines-servingconfigs", - version: "2026.04.03.3", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -605,6 +605,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, @@ -1061,8 +1066,10 @@ export const model = { canonicalFilter: z.any().optional(), contentSearchSpec: z.any().optional(), crowdingSpecs: z.any().optional(), + customRankingParams: z.any().optional(), dataStoreSpecs: z.any().optional(), displaySpec: z.any().optional(), + entity: z.any().optional(), facetSpecs: z.any().optional(), filter: z.any().optional(), imageQuery: z.any().optional(), @@ -1123,12 +1130,16 @@ export const model = { if (args["crowdingSpecs"] !== undefined) { body["crowdingSpecs"] = args["crowdingSpecs"]; } + if (args["customRankingParams"] !== undefined) { + body["customRankingParams"] = args["customRankingParams"]; + } if (args["dataStoreSpecs"] !== undefined) { body["dataStoreSpecs"] = args["dataStoreSpecs"]; } if (args["displaySpec"] !== undefined) { body["displaySpec"] = args["displaySpec"]; } + if (args["entity"] !== undefined) body["entity"] = args["entity"]; if (args["facetSpecs"] !== undefined) { body["facetSpecs"] = args["facetSpecs"]; } @@ -1221,8 +1232,10 @@ export const model = { canonicalFilter: z.any().optional(), contentSearchSpec: z.any().optional(), crowdingSpecs: z.any().optional(), + customRankingParams: z.any().optional(), dataStoreSpecs: z.any().optional(), displaySpec: z.any().optional(), + entity: z.any().optional(), facetSpecs: z.any().optional(), filter: z.any().optional(), imageQuery: z.any().optional(), @@ -1283,12 +1296,16 @@ export const model = { if (args["crowdingSpecs"] !== undefined) { body["crowdingSpecs"] = args["crowdingSpecs"]; } + if (args["customRankingParams"] !== undefined) { + body["customRankingParams"] = args["customRankingParams"]; + } if (args["dataStoreSpecs"] !== undefined) { body["dataStoreSpecs"] = args["dataStoreSpecs"]; } if (args["displaySpec"] !== undefined) { body["displaySpec"] = args["displaySpec"]; } + if (args["entity"] !== undefined) body["entity"] = args["entity"]; if (args["facetSpecs"] !== undefined) { body["facetSpecs"] = args["facetSpecs"]; } diff --git a/model/gcp/discoveryengine/extensions/models/collections_engines_sessions.ts b/model/gcp/discoveryengine/extensions/models/collections_engines_sessions.ts index 4034251fe..0cc1e9980 100644 --- a/model/gcp/discoveryengine/extensions/models/collections_engines_sessions.ts +++ b/model/gcp/discoveryengine/extensions/models/collections_engines_sessions.ts @@ -51,6 +51,9 @@ const INSERT_CONFIG = { "location": "path", "required": true, }, + "sessionId": { + "location": "query", + }, }, } as const; @@ -238,6 +241,8 @@ const GlobalArgsSchema = z.object({ "Immutable. Identifier. Resource name of the `AssistAnswer`. Format: `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/sessions/{session}/assistAnswers/{assist_answer}` This field must be a UTF-8 encoded string with a length limit of 1024 characters.", ).optional(), replies: z.array(z.object({ + createTime: z.unknown().describe("The time when the reply was created.") + .optional(), groundedContent: z.unknown().describe( 'A piece of content and possibly its grounding information. Not all content needs grounding. Phrases like "Of course, I will gladly search it for you." do not need grounding.', ).optional(), @@ -262,6 +267,9 @@ const GlobalArgsSchema = z.object({ })).describe("Turns.").optional(), userPseudoId: z.string().describe("A unique identifier for tracking users.") .optional(), + sessionId: z.string().describe( + "Optional. The ID to use for the session, which will become the final component of the session's resource name. This value should be 1-63 characters, and valid characters are /a-z0-9{0,61}[a-z0-9]/. If not specified, a unique ID will be generated.", + ).optional(), location: z.string().describe( "The location for this resource (e.g., 'us', 'us-central1', 'europe-west1')", ).optional(), @@ -329,6 +337,7 @@ const StateSchema = z.object({ }), name: z.string(), replies: z.array(z.object({ + createTime: z.unknown(), groundedContent: z.unknown(), })), state: z.string(), @@ -494,6 +503,8 @@ const InputsSchema = z.object({ "Immutable. Identifier. Resource name of the `AssistAnswer`. Format: `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/sessions/{session}/assistAnswers/{assist_answer}` This field must be a UTF-8 encoded string with a length limit of 1024 characters.", ).optional(), replies: z.array(z.object({ + createTime: z.unknown().describe("The time when the reply was created.") + .optional(), groundedContent: z.unknown().describe( 'A piece of content and possibly its grounding information. Not all content needs grounding. Phrases like "Of course, I will gladly search it for you." do not need grounding.', ).optional(), @@ -518,6 +529,9 @@ const InputsSchema = z.object({ })).describe("Turns.").optional(), userPseudoId: z.string().describe("A unique identifier for tracking users.") .optional(), + sessionId: z.string().describe( + "Optional. The ID to use for the session, which will become the final component of the session's resource name. This value should be 1-63 characters, and valid characters are /a-z0-9{0,61}[a-z0-9]/. If not specified, a unique ID will be generated.", + ).optional(), location: z.string().describe( "The location for this resource (e.g., 'us', 'us-central1', 'europe-west1')", ).optional(), @@ -525,7 +539,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/discoveryengine/collections-engines-sessions", - version: "2026.04.04.1", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -557,6 +571,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "Added: sessionId", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, @@ -589,6 +608,7 @@ export const model = { if (g["userPseudoId"] !== undefined) { body["userPseudoId"] = g["userPseudoId"]; } + if (g["sessionId"] !== undefined) body["sessionId"] = g["sessionId"]; if (g["parent"] !== undefined && g["name"] !== undefined) { params["name"] = buildResourceName( String(g["parent"]), diff --git a/model/gcp/discoveryengine/extensions/models/collections_engines_widgetconfigs.ts b/model/gcp/discoveryengine/extensions/models/collections_engines_widgetconfigs.ts index 32ef44821..ad9b3f788 100644 --- a/model/gcp/discoveryengine/extensions/models/collections_engines_widgetconfigs.ts +++ b/model/gcp/discoveryengine/extensions/models/collections_engines_widgetconfigs.ts @@ -386,7 +386,7 @@ const GlobalArgsSchema = z.object({ "FEATURE_STATE_OFF", ]), ).describe( - "Output only. Feature config for the engine to opt in or opt out of features. Supported keys: * `agent-gallery` * `no-code-agent-builder` * `prompt-gallery` * `model-selector` * `notebook-lm` * `people-search` * `people-search-org-chart` * `bi-directional-audio` * `feedback` * `session-sharing` * `personalization-memory` * `personalization-suggested-highlights` * `disable-agent-sharing` * `disable-image-generation` * `disable-video-generation` * `disable-onedrive-upload` * `disable-talk-to-content` * `disable-google-drive-upload` * `disable-welcome-emails`", + "Output only. Feature config for the engine to opt in or opt out of features. Supported keys: * `agent-gallery` * `no-code-agent-builder` * `prompt-gallery` * `model-selector` * `notebook-lm` * `people-search` * `people-search-org-chart` * `bi-directional-audio` * `feedback` * `session-sharing` * `personalization-memory` * `personalization-suggested-highlights` * `disable-agent-sharing` * `disable-image-generation` * `disable-video-generation` * `disable-onedrive-upload` * `disable-talk-to-content` * `disable-google-drive-upload` * `disable-welcome-emails` * `disable-canvas` * `disable-canvas-workspace`", ).optional(), generativeAnswerConfig: z.object({ disableRelatedQuestions: z.boolean().describe( @@ -951,7 +951,7 @@ const InputsSchema = z.object({ "FEATURE_STATE_OFF", ]), ).describe( - "Output only. Feature config for the engine to opt in or opt out of features. Supported keys: * `agent-gallery` * `no-code-agent-builder` * `prompt-gallery` * `model-selector` * `notebook-lm` * `people-search` * `people-search-org-chart` * `bi-directional-audio` * `feedback` * `session-sharing` * `personalization-memory` * `personalization-suggested-highlights` * `disable-agent-sharing` * `disable-image-generation` * `disable-video-generation` * `disable-onedrive-upload` * `disable-talk-to-content` * `disable-google-drive-upload` * `disable-welcome-emails`", + "Output only. Feature config for the engine to opt in or opt out of features. Supported keys: * `agent-gallery` * `no-code-agent-builder` * `prompt-gallery` * `model-selector` * `notebook-lm` * `people-search` * `people-search-org-chart` * `bi-directional-audio` * `feedback` * `session-sharing` * `personalization-memory` * `personalization-suggested-highlights` * `disable-agent-sharing` * `disable-image-generation` * `disable-video-generation` * `disable-onedrive-upload` * `disable-talk-to-content` * `disable-google-drive-upload` * `disable-welcome-emails` * `disable-canvas` * `disable-canvas-workspace`", ).optional(), generativeAnswerConfig: z.object({ disableRelatedQuestions: z.boolean().describe( @@ -1018,7 +1018,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/discoveryengine/collections-engines-widgetconfigs", - version: "2026.04.04.1", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -1050,6 +1050,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, diff --git a/model/gcp/discoveryengine/extensions/models/datastores_servingconfigs.ts b/model/gcp/discoveryengine/extensions/models/datastores_servingconfigs.ts index 71e5eca33..d15acf230 100644 --- a/model/gcp/discoveryengine/extensions/models/datastores_servingconfigs.ts +++ b/model/gcp/discoveryengine/extensions/models/datastores_servingconfigs.ts @@ -574,7 +574,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/discoveryengine/datastores-servingconfigs", - version: "2026.04.03.3", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -601,6 +601,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, @@ -1057,8 +1062,10 @@ export const model = { canonicalFilter: z.any().optional(), contentSearchSpec: z.any().optional(), crowdingSpecs: z.any().optional(), + customRankingParams: z.any().optional(), dataStoreSpecs: z.any().optional(), displaySpec: z.any().optional(), + entity: z.any().optional(), facetSpecs: z.any().optional(), filter: z.any().optional(), imageQuery: z.any().optional(), @@ -1119,12 +1126,16 @@ export const model = { if (args["crowdingSpecs"] !== undefined) { body["crowdingSpecs"] = args["crowdingSpecs"]; } + if (args["customRankingParams"] !== undefined) { + body["customRankingParams"] = args["customRankingParams"]; + } if (args["dataStoreSpecs"] !== undefined) { body["dataStoreSpecs"] = args["dataStoreSpecs"]; } if (args["displaySpec"] !== undefined) { body["displaySpec"] = args["displaySpec"]; } + if (args["entity"] !== undefined) body["entity"] = args["entity"]; if (args["facetSpecs"] !== undefined) { body["facetSpecs"] = args["facetSpecs"]; } @@ -1217,8 +1228,10 @@ export const model = { canonicalFilter: z.any().optional(), contentSearchSpec: z.any().optional(), crowdingSpecs: z.any().optional(), + customRankingParams: z.any().optional(), dataStoreSpecs: z.any().optional(), displaySpec: z.any().optional(), + entity: z.any().optional(), facetSpecs: z.any().optional(), filter: z.any().optional(), imageQuery: z.any().optional(), @@ -1279,12 +1292,16 @@ export const model = { if (args["crowdingSpecs"] !== undefined) { body["crowdingSpecs"] = args["crowdingSpecs"]; } + if (args["customRankingParams"] !== undefined) { + body["customRankingParams"] = args["customRankingParams"]; + } if (args["dataStoreSpecs"] !== undefined) { body["dataStoreSpecs"] = args["dataStoreSpecs"]; } if (args["displaySpec"] !== undefined) { body["displaySpec"] = args["displaySpec"]; } + if (args["entity"] !== undefined) body["entity"] = args["entity"]; if (args["facetSpecs"] !== undefined) { body["facetSpecs"] = args["facetSpecs"]; } diff --git a/model/gcp/discoveryengine/extensions/models/datastores_sessions.ts b/model/gcp/discoveryengine/extensions/models/datastores_sessions.ts index 22540085b..30845880c 100644 --- a/model/gcp/discoveryengine/extensions/models/datastores_sessions.ts +++ b/model/gcp/discoveryengine/extensions/models/datastores_sessions.ts @@ -50,6 +50,9 @@ const INSERT_CONFIG = { "location": "path", "required": true, }, + "sessionId": { + "location": "query", + }, }, } as const; @@ -236,6 +239,8 @@ const GlobalArgsSchema = z.object({ "Immutable. Identifier. Resource name of the `AssistAnswer`. Format: `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/sessions/{session}/assistAnswers/{assist_answer}` This field must be a UTF-8 encoded string with a length limit of 1024 characters.", ).optional(), replies: z.array(z.object({ + createTime: z.unknown().describe("The time when the reply was created.") + .optional(), groundedContent: z.unknown().describe( 'A piece of content and possibly its grounding information. Not all content needs grounding. Phrases like "Of course, I will gladly search it for you." do not need grounding.', ).optional(), @@ -260,6 +265,9 @@ const GlobalArgsSchema = z.object({ })).describe("Turns.").optional(), userPseudoId: z.string().describe("A unique identifier for tracking users.") .optional(), + sessionId: z.string().describe( + "Optional. The ID to use for the session, which will become the final component of the session's resource name. This value should be 1-63 characters, and valid characters are /a-z0-9{0,61}[a-z0-9]/. If not specified, a unique ID will be generated.", + ).optional(), location: z.string().describe( "The location for this resource (e.g., 'us', 'us-central1', 'europe-west1')", ).optional(), @@ -327,6 +335,7 @@ const StateSchema = z.object({ }), name: z.string(), replies: z.array(z.object({ + createTime: z.unknown(), groundedContent: z.unknown(), })), state: z.string(), @@ -492,6 +501,8 @@ const InputsSchema = z.object({ "Immutable. Identifier. Resource name of the `AssistAnswer`. Format: `projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/sessions/{session}/assistAnswers/{assist_answer}` This field must be a UTF-8 encoded string with a length limit of 1024 characters.", ).optional(), replies: z.array(z.object({ + createTime: z.unknown().describe("The time when the reply was created.") + .optional(), groundedContent: z.unknown().describe( 'A piece of content and possibly its grounding information. Not all content needs grounding. Phrases like "Of course, I will gladly search it for you." do not need grounding.', ).optional(), @@ -516,6 +527,9 @@ const InputsSchema = z.object({ })).describe("Turns.").optional(), userPseudoId: z.string().describe("A unique identifier for tracking users.") .optional(), + sessionId: z.string().describe( + "Optional. The ID to use for the session, which will become the final component of the session's resource name. This value should be 1-63 characters, and valid characters are /a-z0-9{0,61}[a-z0-9]/. If not specified, a unique ID will be generated.", + ).optional(), location: z.string().describe( "The location for this resource (e.g., 'us', 'us-central1', 'europe-west1')", ).optional(), @@ -523,7 +537,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/discoveryengine/datastores-sessions", - version: "2026.04.04.1", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -555,6 +569,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "Added: sessionId", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, @@ -587,6 +606,7 @@ export const model = { if (g["userPseudoId"] !== undefined) { body["userPseudoId"] = g["userPseudoId"]; } + if (g["sessionId"] !== undefined) body["sessionId"] = g["sessionId"]; if (g["parent"] !== undefined && g["name"] !== undefined) { params["name"] = buildResourceName( String(g["parent"]), diff --git a/model/gcp/discoveryengine/extensions/models/datastores_widgetconfigs.ts b/model/gcp/discoveryengine/extensions/models/datastores_widgetconfigs.ts index 5e768c699..40302a904 100644 --- a/model/gcp/discoveryengine/extensions/models/datastores_widgetconfigs.ts +++ b/model/gcp/discoveryengine/extensions/models/datastores_widgetconfigs.ts @@ -384,7 +384,7 @@ const GlobalArgsSchema = z.object({ "FEATURE_STATE_OFF", ]), ).describe( - "Output only. Feature config for the engine to opt in or opt out of features. Supported keys: * `agent-gallery` * `no-code-agent-builder` * `prompt-gallery` * `model-selector` * `notebook-lm` * `people-search` * `people-search-org-chart` * `bi-directional-audio` * `feedback` * `session-sharing` * `personalization-memory` * `personalization-suggested-highlights` * `disable-agent-sharing` * `disable-image-generation` * `disable-video-generation` * `disable-onedrive-upload` * `disable-talk-to-content` * `disable-google-drive-upload` * `disable-welcome-emails`", + "Output only. Feature config for the engine to opt in or opt out of features. Supported keys: * `agent-gallery` * `no-code-agent-builder` * `prompt-gallery` * `model-selector` * `notebook-lm` * `people-search` * `people-search-org-chart` * `bi-directional-audio` * `feedback` * `session-sharing` * `personalization-memory` * `personalization-suggested-highlights` * `disable-agent-sharing` * `disable-image-generation` * `disable-video-generation` * `disable-onedrive-upload` * `disable-talk-to-content` * `disable-google-drive-upload` * `disable-welcome-emails` * `disable-canvas` * `disable-canvas-workspace`", ).optional(), generativeAnswerConfig: z.object({ disableRelatedQuestions: z.boolean().describe( @@ -949,7 +949,7 @@ const InputsSchema = z.object({ "FEATURE_STATE_OFF", ]), ).describe( - "Output only. Feature config for the engine to opt in or opt out of features. Supported keys: * `agent-gallery` * `no-code-agent-builder` * `prompt-gallery` * `model-selector` * `notebook-lm` * `people-search` * `people-search-org-chart` * `bi-directional-audio` * `feedback` * `session-sharing` * `personalization-memory` * `personalization-suggested-highlights` * `disable-agent-sharing` * `disable-image-generation` * `disable-video-generation` * `disable-onedrive-upload` * `disable-talk-to-content` * `disable-google-drive-upload` * `disable-welcome-emails`", + "Output only. Feature config for the engine to opt in or opt out of features. Supported keys: * `agent-gallery` * `no-code-agent-builder` * `prompt-gallery` * `model-selector` * `notebook-lm` * `people-search` * `people-search-org-chart` * `bi-directional-audio` * `feedback` * `session-sharing` * `personalization-memory` * `personalization-suggested-highlights` * `disable-agent-sharing` * `disable-image-generation` * `disable-video-generation` * `disable-onedrive-upload` * `disable-talk-to-content` * `disable-google-drive-upload` * `disable-welcome-emails` * `disable-canvas` * `disable-canvas-workspace`", ).optional(), generativeAnswerConfig: z.object({ disableRelatedQuestions: z.boolean().describe( @@ -1016,7 +1016,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/discoveryengine/datastores-widgetconfigs", - version: "2026.04.04.1", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -1048,6 +1048,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, diff --git a/model/gcp/discoveryengine/extensions/models/licenseconfigs.ts b/model/gcp/discoveryengine/extensions/models/licenseconfigs.ts index 758ff2838..438954f7a 100644 --- a/model/gcp/discoveryengine/extensions/models/licenseconfigs.ts +++ b/model/gcp/discoveryengine/extensions/models/licenseconfigs.ts @@ -108,6 +108,24 @@ const GlobalArgsSchema = z.object({ name: z.string().describe( "Immutable. Identifier. The fully qualified resource name of the license config. Format: `projects/{project}/locations/{location}/licenseConfigs/{license_config}`", ).optional(), + scheduledUpdate: z.object({ + effectiveDate: z.object({ + day: z.number().int().describe( + "Day of a month. Must be from 1 to 31 and valid for the year and month, or 0 to specify a year by itself or a year and month where the day isn't significant.", + ).optional(), + month: z.number().int().describe( + "Month of a year. Must be from 1 to 12, or 0 to specify a year without a month and day.", + ).optional(), + year: z.number().int().describe( + "Year of the date. Must be from 1 to 9999, or 0 to specify a date without a year.", + ).optional(), + }).describe( + "Represents a whole or partial calendar date, such as a birthday. The time of day and time zone are either specified elsewhere or are insignificant. The date is relative to the Gregorian Calendar. This can represent one of the following: * A full date, with non-zero year, month, and day values. * A month and day, with a zero year (for example, an anniversary). * A year on its own, with a zero month and a zero day. * A year and month, with a zero day (for example, a credit card expiration date). Related types: * google.type.TimeOfDay * google.type.DateTime * google.protobuf.Timestamp", + ).optional(), + seatCount: z.string().describe( + "The seat count scheduled for the next update.", + ).optional(), + }).describe("Message containing data for a scheduled update.").optional(), startDate: z.object({ day: z.number().int().describe( "Day of a month. Must be from 1 to 31 and valid for the year and month, or 0 to specify a year by itself or a year and month where the day isn't significant.", @@ -170,6 +188,14 @@ const StateSchema = z.object({ geminiBundle: z.boolean().optional(), licenseCount: z.string().optional(), name: z.string(), + scheduledUpdate: z.object({ + effectiveDate: z.object({ + day: z.number(), + month: z.number(), + year: z.number(), + }), + seatCount: z.string(), + }).optional(), startDate: z.object({ day: z.number(), month: z.number(), @@ -220,6 +246,24 @@ const InputsSchema = z.object({ name: z.string().describe( "Immutable. Identifier. The fully qualified resource name of the license config. Format: `projects/{project}/locations/{location}/licenseConfigs/{license_config}`", ).optional(), + scheduledUpdate: z.object({ + effectiveDate: z.object({ + day: z.number().int().describe( + "Day of a month. Must be from 1 to 31 and valid for the year and month, or 0 to specify a year by itself or a year and month where the day isn't significant.", + ).optional(), + month: z.number().int().describe( + "Month of a year. Must be from 1 to 12, or 0 to specify a year without a month and day.", + ).optional(), + year: z.number().int().describe( + "Year of the date. Must be from 1 to 9999, or 0 to specify a date without a year.", + ).optional(), + }).describe( + "Represents a whole or partial calendar date, such as a birthday. The time of day and time zone are either specified elsewhere or are insignificant. The date is relative to the Gregorian Calendar. This can represent one of the following: * A full date, with non-zero year, month, and day values. * A month and day, with a zero year (for example, an anniversary). * A year on its own, with a zero month and a zero day. * A year and month, with a zero day (for example, a credit card expiration date). Related types: * google.type.TimeOfDay * google.type.DateTime * google.protobuf.Timestamp", + ).optional(), + seatCount: z.string().describe( + "The seat count scheduled for the next update.", + ).optional(), + }).describe("Message containing data for a scheduled update.").optional(), startDate: z.object({ day: z.number().int().describe( "Day of a month. Must be from 1 to 31 and valid for the year and month, or 0 to specify a year by itself or a year and month where the day isn't significant.", @@ -267,7 +311,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/discoveryengine/licenseconfigs", - version: "2026.04.03.3", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -294,6 +338,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "Added: scheduledUpdate", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, @@ -329,6 +378,9 @@ export const model = { body["licenseCount"] = g["licenseCount"]; } if (g["name"] !== undefined) body["name"] = g["name"]; + if (g["scheduledUpdate"] !== undefined) { + body["scheduledUpdate"] = g["scheduledUpdate"]; + } if (g["startDate"] !== undefined) body["startDate"] = g["startDate"]; if (g["subscriptionTerm"] !== undefined) { body["subscriptionTerm"] = g["subscriptionTerm"]; @@ -438,6 +490,9 @@ export const model = { if (g["licenseCount"] !== undefined) { body["licenseCount"] = g["licenseCount"]; } + if (g["scheduledUpdate"] !== undefined) { + body["scheduledUpdate"] = g["scheduledUpdate"]; + } if (g["startDate"] !== undefined) body["startDate"] = g["startDate"]; if (g["subscriptionTerm"] !== undefined) { body["subscriptionTerm"] = g["subscriptionTerm"]; diff --git a/model/gcp/discoveryengine/extensions/models/userstores_userlicenses.ts b/model/gcp/discoveryengine/extensions/models/userstores_userlicenses.ts index 3e7c921bd..1c33978a0 100644 --- a/model/gcp/discoveryengine/extensions/models/userstores_userlicenses.ts +++ b/model/gcp/discoveryengine/extensions/models/userstores_userlicenses.ts @@ -20,6 +20,9 @@ const LIST_CONFIG = { "parent", ], "parameters": { + "filter": { + "location": "query", + }, "orderBy": { "location": "query", }, @@ -66,7 +69,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/discoveryengine/userstores-userlicenses", - version: "2026.04.03.3", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -93,6 +96,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, diff --git a/model/gcp/discoveryengine/manifest.yaml b/model/gcp/discoveryengine/manifest.yaml index af4419707..c05fe5744 100644 --- a/model/gcp/discoveryengine/manifest.yaml +++ b/model/gcp/discoveryengine/manifest.yaml @@ -1,7 +1,7 @@ # Auto-generated manifest. Re-generate with the appropriate deno task. manifestVersion: 1 name: "@swamp/gcp/discoveryengine" -version: "2026.04.04.1" +version: "2026.04.08.1" description: "Google Cloud discoveryengine infrastructure models" labels: - gcp @@ -10,7 +10,7 @@ labels: - cloud - infrastructure releaseNotes: | - - Updated: collections_datastores, collections_datastores_branches_documents, collections_datastores_conversations, collections_datastores_sessions, collections_datastores_sessions_answers, collections_datastores_widgetconfigs, collections_engines_assistants_agents_a2a_v1_tasks, collections_engines_conversations, collections_engines_sessions, collections_engines_sessions_answers, collections_engines_widgetconfigs, datastores, datastores_branches_documents, datastores_conversations, datastores_sessions, datastores_sessions_answers, datastores_widgetconfigs + - Updated: collections_datastores_servingconfigs, collections_datastores_sessions, collections_datastores_widgetconfigs, collections_engines, collections_engines_servingconfigs, collections_engines_sessions, collections_engines_widgetconfigs, datastores_servingconfigs, datastores_sessions, datastores_widgetconfigs, licenseconfigs, userstores_userlicenses models: - cmekconfigs.ts - collections_datastores.ts diff --git a/model/gcp/displayvideo/extensions/models/advertisers_adgroupads.ts b/model/gcp/displayvideo/extensions/models/advertisers_adgroupads.ts index 821b7f708..ca6d55e01 100644 --- a/model/gcp/displayvideo/extensions/models/advertisers_adgroupads.ts +++ b/model/gcp/displayvideo/extensions/models/advertisers_adgroupads.ts @@ -252,7 +252,7 @@ const GlobalArgsSchema = z.object({ "VIDEO_UNAVAILABLE_REASON_DELETED", ]).describe("The reason why the video data is not available.").optional(), videoAssetId: z.string().describe( - "Required. The YouTube video asset id. This is ad_asset.ad_asset_id.", + "Required. The YouTube video asset id. This is the adAssetId of an AdAsset resource.", ).optional(), }).describe("Details of a YouTube video.").optional(), }).describe("Details for an audio ad.").optional(), @@ -300,7 +300,7 @@ const GlobalArgsSchema = z.object({ ]).describe("The reason why the video data is not available.") .optional(), videoAssetId: z.string().describe( - "Required. The YouTube video asset id. This is ad_asset.ad_asset_id.", + "Required. The YouTube video asset id. This is the adAssetId of an AdAsset resource.", ).optional(), }).describe("Details of a YouTube video.").optional(), }).describe( @@ -321,7 +321,7 @@ const GlobalArgsSchema = z.object({ ).optional(), cards: z.array(z.object({ callToAction: z.string().describe( - "Required. The call-to-action button shown on the card. Must use 10 characters or less.", + "Required. The text on the call-to-action button shown on the card. Must use 10 characters or less.", ).optional(), finalMobileUrl: z.string().describe( "Optional. The URL address of the webpage that people reach after they click the card on a mobile device.", @@ -378,7 +378,7 @@ const GlobalArgsSchema = z.object({ }).describe("Meta data of an image asset.").optional(), })).describe("Required. The list of cards shown on the ad.").optional(), customParameters: z.record(z.string(), z.string()).describe( - "Optional. The custom parameters to pass custom values to tracking URL template.", + "Optional. The custom parameters and accompanying values to add to the tracking URL.", ).optional(), description: z.string().describe("Required. The description of the ad.") .optional(), @@ -421,7 +421,7 @@ const GlobalArgsSchema = z.object({ "Required. The call-to-action button shown on the ad.", ).optional(), customParameters: z.record(z.string(), z.string()).describe( - "Optional. The custom parameters to pass custom values to tracking URL template.", + "Optional. The custom parameters and accompanying values to add to the tracking URL.", ).optional(), descriptions: z.array(z.string()).describe( "Required. The list of descriptions shown on the ad.", @@ -539,7 +539,7 @@ const GlobalArgsSchema = z.object({ "Required. The call-to-action button shown on the ad. The supported values are: * `AUTOMATED` * `APPLY_NOW` * `BOOK_NOW` * `CONTACT_US` * `DOWNLOAD` * `GET_QUOTE` * `LEARN_MORE` * `SHOP_NOW` * `SIGN_UP` * `SUBSCRIBE`", ).optional(), customParameters: z.record(z.string(), z.string()).describe( - "Optional. The custom parameters to pass custom values to tracking URL template.", + "Optional. The custom parameters and accompanying values to add to the tracking URL.", ).optional(), description: z.string().describe("Required. The description of the ad.") .optional(), @@ -624,7 +624,7 @@ const GlobalArgsSchema = z.object({ ).optional(), }).describe("Meta data of an image asset.").optional(), customParameters: z.record(z.string(), z.string()).describe( - "Optional. The custom parameters to pass custom values to tracking URL template.", + "Optional. The custom parameters and accompanying values to add to the tracking URL.", ).optional(), descriptions: z.array(z.string()).describe( "Required. The list of descriptions shown on the ad.", @@ -664,7 +664,7 @@ const GlobalArgsSchema = z.object({ ).optional(), }).describe("Meta data of an image asset.").optional(), longHeadlines: z.array(z.string()).describe( - "Required. The list of lone headlines shown on the ad.", + "Required. The list of long headlines shown on the ad.", ).optional(), trackingUrl: z.string().describe( "Output only. The URL address loaded in the background for tracking purposes.", @@ -682,7 +682,7 @@ const GlobalArgsSchema = z.object({ "VIDEO_UNAVAILABLE_REASON_DELETED", ]).describe("The reason why the video data is not available.").optional(), videoAssetId: z.string().describe( - "Required. The YouTube video asset id. This is ad_asset.ad_asset_id.", + "Required. The YouTube video asset id. This is the adAssetId of an AdAsset resource.", ).optional(), })).describe("Required. The list of YouTube video assets used by this ad.") .optional(), @@ -746,14 +746,14 @@ const GlobalArgsSchema = z.object({ ]).describe("The reason why the video data is not available.") .optional(), videoAssetId: z.string().describe( - "Required. The YouTube video asset id. This is ad_asset.ad_asset_id.", + "Required. The YouTube video asset id. This is the adAssetId of an AdAsset resource.", ).optional(), }).describe("Details of a YouTube video.").optional(), }).describe( "Common attributes for in-stream, non-skippable and bumper ads.", ).optional(), customParameters: z.record(z.string(), z.string()).describe( - "The custom parameters to pass custom values to tracking URL template.", + "The custom parameters and accompanying values to add to the tracking URL.", ).optional(), }).describe("Details for an in-stream ad.").optional(), mastheadAd: z.object({ @@ -782,7 +782,7 @@ const GlobalArgsSchema = z.object({ "VIDEO_UNAVAILABLE_REASON_DELETED", ]).describe("The reason why the video data is not available.").optional(), videoAssetId: z.string().describe( - "Required. The YouTube video asset id. This is ad_asset.ad_asset_id.", + "Required. The YouTube video asset id. This is the adAssetId of an AdAsset resource.", ).optional(), })).describe( "The videos that appear next to the Masthead Ad on desktop. Can be no more than two.", @@ -802,7 +802,7 @@ const GlobalArgsSchema = z.object({ "VIDEO_UNAVAILABLE_REASON_DELETED", ]).describe("The reason why the video data is not available.").optional(), videoAssetId: z.string().describe( - "Required. The YouTube video asset id. This is ad_asset.ad_asset_id.", + "Required. The YouTube video asset id. This is the adAssetId of an AdAsset resource.", ).optional(), }).describe("Details of a YouTube video.").optional(), videoAspectRatio: z.enum([ @@ -857,14 +857,14 @@ const GlobalArgsSchema = z.object({ ]).describe("The reason why the video data is not available.") .optional(), videoAssetId: z.string().describe( - "Required. The YouTube video asset id. This is ad_asset.ad_asset_id.", + "Required. The YouTube video asset id. This is the adAssetId of an AdAsset resource.", ).optional(), }).describe("Details of a YouTube video.").optional(), }).describe( "Common attributes for in-stream, non-skippable and bumper ads.", ).optional(), customParameters: z.record(z.string(), z.string()).describe( - "The custom parameters to pass custom values to tracking URL template.", + "The custom parameters and accompanying values to add to the tracking URL.", ).optional(), }).describe("Details for a non-skippable ad.").optional(), videoDiscoverAd: z.object({ @@ -889,7 +889,7 @@ const GlobalArgsSchema = z.object({ "VIDEO_UNAVAILABLE_REASON_DELETED", ]).describe("The reason why the video data is not available.").optional(), videoAssetId: z.string().describe( - "Required. The YouTube video asset id. This is ad_asset.ad_asset_id.", + "Required. The YouTube video asset id. This is the adAssetId of an AdAsset resource.", ).optional(), }).describe("Details of a YouTube video.").optional(), }).describe("Details for a video discovery ad.").optional(), @@ -914,7 +914,7 @@ const GlobalArgsSchema = z.object({ ).optional(), })).describe("The list of companion banners used by this ad.").optional(), customParameters: z.record(z.string(), z.string()).describe( - "The custom parameters to pass custom values to tracking URL template.", + "The custom parameters and accompanying values to add to the tracking URL.", ).optional(), descriptions: z.array(z.string()).describe( "The list of descriptions shown on the call-to-action banner.", @@ -933,7 +933,7 @@ const GlobalArgsSchema = z.object({ "The list of headlines shown on the call-to-action banner.", ).optional(), longHeadlines: z.array(z.string()).describe( - "The list of lone headlines shown on the call-to-action banner.", + "The list of long headlines shown on the call-to-action banner.", ).optional(), trackingUrl: z.string().describe( "The URL address loaded in the background for tracking purposes.", @@ -948,7 +948,7 @@ const GlobalArgsSchema = z.object({ "VIDEO_UNAVAILABLE_REASON_DELETED", ]).describe("The reason why the video data is not available.").optional(), videoAssetId: z.string().describe( - "Required. The YouTube video asset id. This is ad_asset.ad_asset_id.", + "Required. The YouTube video asset id. This is the adAssetId of an AdAsset resource.", ).optional(), })).describe("The list of YouTube video assets used by this ad.") .optional(), @@ -1473,7 +1473,7 @@ const InputsSchema = z.object({ "VIDEO_UNAVAILABLE_REASON_DELETED", ]).describe("The reason why the video data is not available.").optional(), videoAssetId: z.string().describe( - "Required. The YouTube video asset id. This is ad_asset.ad_asset_id.", + "Required. The YouTube video asset id. This is the adAssetId of an AdAsset resource.", ).optional(), }).describe("Details of a YouTube video.").optional(), }).describe("Details for an audio ad.").optional(), @@ -1521,7 +1521,7 @@ const InputsSchema = z.object({ ]).describe("The reason why the video data is not available.") .optional(), videoAssetId: z.string().describe( - "Required. The YouTube video asset id. This is ad_asset.ad_asset_id.", + "Required. The YouTube video asset id. This is the adAssetId of an AdAsset resource.", ).optional(), }).describe("Details of a YouTube video.").optional(), }).describe( @@ -1542,7 +1542,7 @@ const InputsSchema = z.object({ ).optional(), cards: z.array(z.object({ callToAction: z.string().describe( - "Required. The call-to-action button shown on the card. Must use 10 characters or less.", + "Required. The text on the call-to-action button shown on the card. Must use 10 characters or less.", ).optional(), finalMobileUrl: z.string().describe( "Optional. The URL address of the webpage that people reach after they click the card on a mobile device.", @@ -1599,7 +1599,7 @@ const InputsSchema = z.object({ }).describe("Meta data of an image asset.").optional(), })).describe("Required. The list of cards shown on the ad.").optional(), customParameters: z.record(z.string(), z.string()).describe( - "Optional. The custom parameters to pass custom values to tracking URL template.", + "Optional. The custom parameters and accompanying values to add to the tracking URL.", ).optional(), description: z.string().describe("Required. The description of the ad.") .optional(), @@ -1642,7 +1642,7 @@ const InputsSchema = z.object({ "Required. The call-to-action button shown on the ad.", ).optional(), customParameters: z.record(z.string(), z.string()).describe( - "Optional. The custom parameters to pass custom values to tracking URL template.", + "Optional. The custom parameters and accompanying values to add to the tracking URL.", ).optional(), descriptions: z.array(z.string()).describe( "Required. The list of descriptions shown on the ad.", @@ -1760,7 +1760,7 @@ const InputsSchema = z.object({ "Required. The call-to-action button shown on the ad. The supported values are: * `AUTOMATED` * `APPLY_NOW` * `BOOK_NOW` * `CONTACT_US` * `DOWNLOAD` * `GET_QUOTE` * `LEARN_MORE` * `SHOP_NOW` * `SIGN_UP` * `SUBSCRIBE`", ).optional(), customParameters: z.record(z.string(), z.string()).describe( - "Optional. The custom parameters to pass custom values to tracking URL template.", + "Optional. The custom parameters and accompanying values to add to the tracking URL.", ).optional(), description: z.string().describe("Required. The description of the ad.") .optional(), @@ -1845,7 +1845,7 @@ const InputsSchema = z.object({ ).optional(), }).describe("Meta data of an image asset.").optional(), customParameters: z.record(z.string(), z.string()).describe( - "Optional. The custom parameters to pass custom values to tracking URL template.", + "Optional. The custom parameters and accompanying values to add to the tracking URL.", ).optional(), descriptions: z.array(z.string()).describe( "Required. The list of descriptions shown on the ad.", @@ -1885,7 +1885,7 @@ const InputsSchema = z.object({ ).optional(), }).describe("Meta data of an image asset.").optional(), longHeadlines: z.array(z.string()).describe( - "Required. The list of lone headlines shown on the ad.", + "Required. The list of long headlines shown on the ad.", ).optional(), trackingUrl: z.string().describe( "Output only. The URL address loaded in the background for tracking purposes.", @@ -1903,7 +1903,7 @@ const InputsSchema = z.object({ "VIDEO_UNAVAILABLE_REASON_DELETED", ]).describe("The reason why the video data is not available.").optional(), videoAssetId: z.string().describe( - "Required. The YouTube video asset id. This is ad_asset.ad_asset_id.", + "Required. The YouTube video asset id. This is the adAssetId of an AdAsset resource.", ).optional(), })).describe("Required. The list of YouTube video assets used by this ad.") .optional(), @@ -1967,14 +1967,14 @@ const InputsSchema = z.object({ ]).describe("The reason why the video data is not available.") .optional(), videoAssetId: z.string().describe( - "Required. The YouTube video asset id. This is ad_asset.ad_asset_id.", + "Required. The YouTube video asset id. This is the adAssetId of an AdAsset resource.", ).optional(), }).describe("Details of a YouTube video.").optional(), }).describe( "Common attributes for in-stream, non-skippable and bumper ads.", ).optional(), customParameters: z.record(z.string(), z.string()).describe( - "The custom parameters to pass custom values to tracking URL template.", + "The custom parameters and accompanying values to add to the tracking URL.", ).optional(), }).describe("Details for an in-stream ad.").optional(), mastheadAd: z.object({ @@ -2003,7 +2003,7 @@ const InputsSchema = z.object({ "VIDEO_UNAVAILABLE_REASON_DELETED", ]).describe("The reason why the video data is not available.").optional(), videoAssetId: z.string().describe( - "Required. The YouTube video asset id. This is ad_asset.ad_asset_id.", + "Required. The YouTube video asset id. This is the adAssetId of an AdAsset resource.", ).optional(), })).describe( "The videos that appear next to the Masthead Ad on desktop. Can be no more than two.", @@ -2023,7 +2023,7 @@ const InputsSchema = z.object({ "VIDEO_UNAVAILABLE_REASON_DELETED", ]).describe("The reason why the video data is not available.").optional(), videoAssetId: z.string().describe( - "Required. The YouTube video asset id. This is ad_asset.ad_asset_id.", + "Required. The YouTube video asset id. This is the adAssetId of an AdAsset resource.", ).optional(), }).describe("Details of a YouTube video.").optional(), videoAspectRatio: z.enum([ @@ -2078,14 +2078,14 @@ const InputsSchema = z.object({ ]).describe("The reason why the video data is not available.") .optional(), videoAssetId: z.string().describe( - "Required. The YouTube video asset id. This is ad_asset.ad_asset_id.", + "Required. The YouTube video asset id. This is the adAssetId of an AdAsset resource.", ).optional(), }).describe("Details of a YouTube video.").optional(), }).describe( "Common attributes for in-stream, non-skippable and bumper ads.", ).optional(), customParameters: z.record(z.string(), z.string()).describe( - "The custom parameters to pass custom values to tracking URL template.", + "The custom parameters and accompanying values to add to the tracking URL.", ).optional(), }).describe("Details for a non-skippable ad.").optional(), videoDiscoverAd: z.object({ @@ -2110,7 +2110,7 @@ const InputsSchema = z.object({ "VIDEO_UNAVAILABLE_REASON_DELETED", ]).describe("The reason why the video data is not available.").optional(), videoAssetId: z.string().describe( - "Required. The YouTube video asset id. This is ad_asset.ad_asset_id.", + "Required. The YouTube video asset id. This is the adAssetId of an AdAsset resource.", ).optional(), }).describe("Details of a YouTube video.").optional(), }).describe("Details for a video discovery ad.").optional(), @@ -2135,7 +2135,7 @@ const InputsSchema = z.object({ ).optional(), })).describe("The list of companion banners used by this ad.").optional(), customParameters: z.record(z.string(), z.string()).describe( - "The custom parameters to pass custom values to tracking URL template.", + "The custom parameters and accompanying values to add to the tracking URL.", ).optional(), descriptions: z.array(z.string()).describe( "The list of descriptions shown on the call-to-action banner.", @@ -2154,7 +2154,7 @@ const InputsSchema = z.object({ "The list of headlines shown on the call-to-action banner.", ).optional(), longHeadlines: z.array(z.string()).describe( - "The list of lone headlines shown on the call-to-action banner.", + "The list of long headlines shown on the call-to-action banner.", ).optional(), trackingUrl: z.string().describe( "The URL address loaded in the background for tracking purposes.", @@ -2169,7 +2169,7 @@ const InputsSchema = z.object({ "VIDEO_UNAVAILABLE_REASON_DELETED", ]).describe("The reason why the video data is not available.").optional(), videoAssetId: z.string().describe( - "Required. The YouTube video asset id. This is ad_asset.ad_asset_id.", + "Required. The YouTube video asset id. This is the adAssetId of an AdAsset resource.", ).optional(), })).describe("The list of YouTube video assets used by this ad.") .optional(), @@ -2178,7 +2178,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/displayvideo/advertisers-adgroupads", - version: "2026.04.04.1", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -2215,6 +2215,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, diff --git a/model/gcp/displayvideo/extensions/models/advertisers_adgroups.ts b/model/gcp/displayvideo/extensions/models/advertisers_adgroups.ts index 7bd7ef399..9f9505a29 100644 --- a/model/gcp/displayvideo/extensions/models/advertisers_adgroups.ts +++ b/model/gcp/displayvideo/extensions/models/advertisers_adgroups.ts @@ -133,7 +133,7 @@ const GlobalArgsSchema = z.object({ "Whether the ad group is opted-in to YouTube shorts inventory.", ).optional(), allowYoutubeStream: z.boolean().describe( - "Whether the ad group is opted-in to YouTube in-stream.", + "Whether the ad group is opted-in to YouTube in-stream inventory.", ).optional(), }).describe("The inventory control of the ad group.").optional(), }).describe("The inventory control of the ad group.").optional(), @@ -143,7 +143,7 @@ const GlobalArgsSchema = z.object({ bidStrategy: z.object({ demandGenBid: z.object({ effectiveBiddingValue: z.string().describe( - "Output only. If AG doesn't set value for tCPA or tROAS, line item bidding value will be the effective_bidding_value, if the bidding strategy type is not tCPA or tROAS, effective_bidding_value is always 0. For line item, it will be the same as the value field.", + "Output only. The value effectively used by the bidding strategy. This field will be the same as value if set. If value is not set and the strategy is assigned to an ad group, this field will be inherited from the line item's bidding strategy. If type is not `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPA` or `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_ROAS`, this field will be 0.", ).optional(), effectiveBiddingValueSource: z.enum([ "BIDDING_SOURCE_UNSPECIFIED", @@ -159,10 +159,10 @@ const GlobalArgsSchema = z.object({ "DEMAND_GEN_BIDDING_STRATEGY_TYPE_MAXIMIZE_CONVERSION_VALUE", "DEMAND_GEN_BIDDING_STRATEGY_TYPE_MAXIMIZE_CLICKS", ]).describe( - "Optional. The type of the bidding strategy. This can only be set at the line item level.", + "Optional. The type of the bidding strategy. This can only be set when assigned to a line item. Ad groups will inherit this value from their line item.", ).optional(), value: z.string().describe( - "Optional. The value used by the bidding strategy. This can be set at the line item and ad group level. This field is only applicable for the following strategy types: * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPA` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPC` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_ROAS` Value of this field is in micros of the advertiser's currency or ROAS value. For example, 1000000 represents 1.0 standard units of the currency or 100% ROAS value. If not using an applicable strategy, the value of this field will be 0.", + "Optional. The value used by the bidding strategy. This can be set when assigned to line items or ad groups. This field is only applicable for the following strategy types: * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPA` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPC` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_ROAS` Value of this field is in micros of the advertiser's currency or ROAS value. For example, 1000000 represents 1.0 standard units of the currency or 100% ROAS value. If not using an applicable strategy, the value of this field will be 0.", ).optional(), }).describe( "Settings that control the bid strategy for Demand Gen resources.", @@ -317,7 +317,7 @@ const GlobalArgsSchema = z.object({ "Required. Whether to enable Optimized Targeting for the line item. Optimized targeting is not compatible with all bid strategies. Attempting to set this field to `true` for a line item using the BiddingStrategy field fixed_bid or one of the following combinations of BiddingStrategy fields and BiddingStrategyPerformanceGoalType will result in an error: maximize_auto_spend_bid: * `BIDDING_STRATEGY_PERFORMANCE_GOAL_TYPE_CIVA` * `BIDDING_STRATEGY_PERFORMANCE_GOAL_TYPE_IVO_TEN` * `BIDDING_STRATEGY_PERFORMANCE_GOAL_TYPE_AV_VIEWED` performance_goal_auto_bid: * `BIDDING_STRATEGY_PERFORMANCE_GOAL_TYPE_VIEWABLE_CPM` This also applies if the line item inherits one of the above bid strategies from the parent insertion order. Bid strategies set at the insertion order-level will be inherited by their line items if the `InsertionOrder` budget field automationType is set to `INSERTION_ORDER_AUTOMATION_TYPE_BUDGET` or `INSERTION_ORDER_AUTOMATION_TYPE_BID_BUDGET`.", ).optional(), excludeDemographicExpansion: z.boolean().describe( - "Optional. Whether to exclude demographic expansion for Optimized Targeting. This field only applies to Demand Gen ad groups.", + "Optional. Whether to exclude demographic expansion for Optimized Targeting. This field can only be set for Demand Gen ad groups. Retrieval and management of Demand Gen resources is currently in beta. This field is only available to allowlisted users.", ).optional(), }).describe( "Settings that control the [optimized targeting](//support.google.com/displayvideo/answer/12060859) settings of the line item.", @@ -431,7 +431,7 @@ const InputsSchema = z.object({ "Whether the ad group is opted-in to YouTube shorts inventory.", ).optional(), allowYoutubeStream: z.boolean().describe( - "Whether the ad group is opted-in to YouTube in-stream.", + "Whether the ad group is opted-in to YouTube in-stream inventory.", ).optional(), }).describe("The inventory control of the ad group.").optional(), }).describe("The inventory control of the ad group.").optional(), @@ -441,7 +441,7 @@ const InputsSchema = z.object({ bidStrategy: z.object({ demandGenBid: z.object({ effectiveBiddingValue: z.string().describe( - "Output only. If AG doesn't set value for tCPA or tROAS, line item bidding value will be the effective_bidding_value, if the bidding strategy type is not tCPA or tROAS, effective_bidding_value is always 0. For line item, it will be the same as the value field.", + "Output only. The value effectively used by the bidding strategy. This field will be the same as value if set. If value is not set and the strategy is assigned to an ad group, this field will be inherited from the line item's bidding strategy. If type is not `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPA` or `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_ROAS`, this field will be 0.", ).optional(), effectiveBiddingValueSource: z.enum([ "BIDDING_SOURCE_UNSPECIFIED", @@ -457,10 +457,10 @@ const InputsSchema = z.object({ "DEMAND_GEN_BIDDING_STRATEGY_TYPE_MAXIMIZE_CONVERSION_VALUE", "DEMAND_GEN_BIDDING_STRATEGY_TYPE_MAXIMIZE_CLICKS", ]).describe( - "Optional. The type of the bidding strategy. This can only be set at the line item level.", + "Optional. The type of the bidding strategy. This can only be set when assigned to a line item. Ad groups will inherit this value from their line item.", ).optional(), value: z.string().describe( - "Optional. The value used by the bidding strategy. This can be set at the line item and ad group level. This field is only applicable for the following strategy types: * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPA` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPC` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_ROAS` Value of this field is in micros of the advertiser's currency or ROAS value. For example, 1000000 represents 1.0 standard units of the currency or 100% ROAS value. If not using an applicable strategy, the value of this field will be 0.", + "Optional. The value used by the bidding strategy. This can be set when assigned to line items or ad groups. This field is only applicable for the following strategy types: * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPA` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPC` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_ROAS` Value of this field is in micros of the advertiser's currency or ROAS value. For example, 1000000 represents 1.0 standard units of the currency or 100% ROAS value. If not using an applicable strategy, the value of this field will be 0.", ).optional(), }).describe( "Settings that control the bid strategy for Demand Gen resources.", @@ -615,7 +615,7 @@ const InputsSchema = z.object({ "Required. Whether to enable Optimized Targeting for the line item. Optimized targeting is not compatible with all bid strategies. Attempting to set this field to `true` for a line item using the BiddingStrategy field fixed_bid or one of the following combinations of BiddingStrategy fields and BiddingStrategyPerformanceGoalType will result in an error: maximize_auto_spend_bid: * `BIDDING_STRATEGY_PERFORMANCE_GOAL_TYPE_CIVA` * `BIDDING_STRATEGY_PERFORMANCE_GOAL_TYPE_IVO_TEN` * `BIDDING_STRATEGY_PERFORMANCE_GOAL_TYPE_AV_VIEWED` performance_goal_auto_bid: * `BIDDING_STRATEGY_PERFORMANCE_GOAL_TYPE_VIEWABLE_CPM` This also applies if the line item inherits one of the above bid strategies from the parent insertion order. Bid strategies set at the insertion order-level will be inherited by their line items if the `InsertionOrder` budget field automationType is set to `INSERTION_ORDER_AUTOMATION_TYPE_BUDGET` or `INSERTION_ORDER_AUTOMATION_TYPE_BID_BUDGET`.", ).optional(), excludeDemographicExpansion: z.boolean().describe( - "Optional. Whether to exclude demographic expansion for Optimized Targeting. This field only applies to Demand Gen ad groups.", + "Optional. Whether to exclude demographic expansion for Optimized Targeting. This field can only be set for Demand Gen ad groups. Retrieval and management of Demand Gen resources is currently in beta. This field is only available to allowlisted users.", ).optional(), }).describe( "Settings that control the [optimized targeting](//support.google.com/displayvideo/answer/12060859) settings of the line item.", @@ -624,7 +624,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/displayvideo/advertisers-adgroups", - version: "2026.04.03.3", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -656,6 +656,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, diff --git a/model/gcp/displayvideo/extensions/models/advertisers_adgroups_targetingtypes_assignedtargetingoptions.ts b/model/gcp/displayvideo/extensions/models/advertisers_adgroups_targetingtypes_assignedtargetingoptions.ts index c32bc2d19..0dac26627 100644 --- a/model/gcp/displayvideo/extensions/models/advertisers_adgroups_targetingtypes_assignedtargetingoptions.ts +++ b/model/gcp/displayvideo/extensions/models/advertisers_adgroups_targetingtypes_assignedtargetingoptions.ts @@ -520,7 +520,7 @@ const GlobalArgsSchema = z.object({ "TIME_ZONE_RESOLUTION_END_USER", "TIME_ZONE_RESOLUTION_ADVERTISER", ]).describe( - "Required. The mechanism used to determine which timezone to use for this day and time targeting setting. For demand gen line items, this field is always TIME_ZONE_RESOLUTION_ADVERTISER.", + "Required. The mechanism used to determine which timezone to use for this day and time targeting setting. For Demand Gen line items, this field is always `TIME_ZONE_RESOLUTION_ADVERTISER`.", ).optional(), }).describe( "Representation of a segment of time defined on a specific day of the week and with a start and end time. The time represented by `start_hour` must be before the time represented by `end_hour`.", @@ -768,7 +768,7 @@ const GlobalArgsSchema = z.object({ ).optional(), keywordDetails: z.object({ exemptedPolicyNames: z.array(z.string()).describe( - "Optional. The policy names to exempt the keyword from. This field is only applicable for Demand Gen keywords, which are positively targeted.", + "Optional. The policy names to exempt the keyword from. When attempting to target a keyword that violates a policy, the error returned will include the name of the relevant policy. Use that name in this field to exempt the targeted keyword from the policy. This field is only applicable for positively-targeted keywords assigned to Demand Gen resources. Retrieval and management of Demand Gen resources is currently in beta. This field is only available to allowlisted users.", ).optional(), keyword: z.string().describe( "Required. The keyword, for example `car insurance`. Positive keyword cannot be offensive word. Must be UTF-8 encoded with a maximum size of 255 bytes. Maximum number of characters is 80. Maximum number of words is 10.", @@ -2186,7 +2186,7 @@ const InputsSchema = z.object({ "TIME_ZONE_RESOLUTION_END_USER", "TIME_ZONE_RESOLUTION_ADVERTISER", ]).describe( - "Required. The mechanism used to determine which timezone to use for this day and time targeting setting. For demand gen line items, this field is always TIME_ZONE_RESOLUTION_ADVERTISER.", + "Required. The mechanism used to determine which timezone to use for this day and time targeting setting. For Demand Gen line items, this field is always `TIME_ZONE_RESOLUTION_ADVERTISER`.", ).optional(), }).describe( "Representation of a segment of time defined on a specific day of the week and with a start and end time. The time represented by `start_hour` must be before the time represented by `end_hour`.", @@ -2434,7 +2434,7 @@ const InputsSchema = z.object({ ).optional(), keywordDetails: z.object({ exemptedPolicyNames: z.array(z.string()).describe( - "Optional. The policy names to exempt the keyword from. This field is only applicable for Demand Gen keywords, which are positively targeted.", + "Optional. The policy names to exempt the keyword from. When attempting to target a keyword that violates a policy, the error returned will include the name of the relevant policy. Use that name in this field to exempt the targeted keyword from the policy. This field is only applicable for positively-targeted keywords assigned to Demand Gen resources. Retrieval and management of Demand Gen resources is currently in beta. This field is only available to allowlisted users.", ).optional(), keyword: z.string().describe( "Required. The keyword, for example `car insurance`. Positive keyword cannot be offensive word. Must be UTF-8 encoded with a maximum size of 255 bytes. Maximum number of characters is 80. Maximum number of words is 10.", @@ -3140,7 +3140,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/displayvideo/advertisers-adgroups-targetingtypes-assignedtargetingoptions", - version: "2026.04.04.1", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -3172,6 +3172,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, diff --git a/model/gcp/displayvideo/extensions/models/advertisers_insertionorders.ts b/model/gcp/displayvideo/extensions/models/advertisers_insertionorders.ts index b762d089c..04820189f 100644 --- a/model/gcp/displayvideo/extensions/models/advertisers_insertionorders.ts +++ b/model/gcp/displayvideo/extensions/models/advertisers_insertionorders.ts @@ -103,7 +103,7 @@ const GlobalArgsSchema = z.object({ bidStrategy: z.object({ demandGenBid: z.object({ effectiveBiddingValue: z.string().describe( - "Output only. If AG doesn't set value for tCPA or tROAS, line item bidding value will be the effective_bidding_value, if the bidding strategy type is not tCPA or tROAS, effective_bidding_value is always 0. For line item, it will be the same as the value field.", + "Output only. The value effectively used by the bidding strategy. This field will be the same as value if set. If value is not set and the strategy is assigned to an ad group, this field will be inherited from the line item's bidding strategy. If type is not `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPA` or `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_ROAS`, this field will be 0.", ).optional(), effectiveBiddingValueSource: z.enum([ "BIDDING_SOURCE_UNSPECIFIED", @@ -119,10 +119,10 @@ const GlobalArgsSchema = z.object({ "DEMAND_GEN_BIDDING_STRATEGY_TYPE_MAXIMIZE_CONVERSION_VALUE", "DEMAND_GEN_BIDDING_STRATEGY_TYPE_MAXIMIZE_CLICKS", ]).describe( - "Optional. The type of the bidding strategy. This can only be set at the line item level.", + "Optional. The type of the bidding strategy. This can only be set when assigned to a line item. Ad groups will inherit this value from their line item.", ).optional(), value: z.string().describe( - "Optional. The value used by the bidding strategy. This can be set at the line item and ad group level. This field is only applicable for the following strategy types: * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPA` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPC` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_ROAS` Value of this field is in micros of the advertiser's currency or ROAS value. For example, 1000000 represents 1.0 standard units of the currency or 100% ROAS value. If not using an applicable strategy, the value of this field will be 0.", + "Optional. The value used by the bidding strategy. This can be set when assigned to line items or ad groups. This field is only applicable for the following strategy types: * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPA` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPC` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_ROAS` Value of this field is in micros of the advertiser's currency or ROAS value. For example, 1000000 represents 1.0 standard units of the currency or 100% ROAS value. If not using an applicable strategy, the value of this field will be 0.", ).optional(), }).describe( "Settings that control the bid strategy for Demand Gen resources.", @@ -567,7 +567,7 @@ const InputsSchema = z.object({ bidStrategy: z.object({ demandGenBid: z.object({ effectiveBiddingValue: z.string().describe( - "Output only. If AG doesn't set value for tCPA or tROAS, line item bidding value will be the effective_bidding_value, if the bidding strategy type is not tCPA or tROAS, effective_bidding_value is always 0. For line item, it will be the same as the value field.", + "Output only. The value effectively used by the bidding strategy. This field will be the same as value if set. If value is not set and the strategy is assigned to an ad group, this field will be inherited from the line item's bidding strategy. If type is not `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPA` or `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_ROAS`, this field will be 0.", ).optional(), effectiveBiddingValueSource: z.enum([ "BIDDING_SOURCE_UNSPECIFIED", @@ -583,10 +583,10 @@ const InputsSchema = z.object({ "DEMAND_GEN_BIDDING_STRATEGY_TYPE_MAXIMIZE_CONVERSION_VALUE", "DEMAND_GEN_BIDDING_STRATEGY_TYPE_MAXIMIZE_CLICKS", ]).describe( - "Optional. The type of the bidding strategy. This can only be set at the line item level.", + "Optional. The type of the bidding strategy. This can only be set when assigned to a line item. Ad groups will inherit this value from their line item.", ).optional(), value: z.string().describe( - "Optional. The value used by the bidding strategy. This can be set at the line item and ad group level. This field is only applicable for the following strategy types: * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPA` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPC` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_ROAS` Value of this field is in micros of the advertiser's currency or ROAS value. For example, 1000000 represents 1.0 standard units of the currency or 100% ROAS value. If not using an applicable strategy, the value of this field will be 0.", + "Optional. The value used by the bidding strategy. This can be set when assigned to line items or ad groups. This field is only applicable for the following strategy types: * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPA` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPC` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_ROAS` Value of this field is in micros of the advertiser's currency or ROAS value. For example, 1000000 represents 1.0 standard units of the currency or 100% ROAS value. If not using an applicable strategy, the value of this field will be 0.", ).optional(), }).describe( "Settings that control the bid strategy for Demand Gen resources.", @@ -929,7 +929,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/displayvideo/advertisers-insertionorders", - version: "2026.04.04.1", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -966,6 +966,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, diff --git a/model/gcp/displayvideo/extensions/models/advertisers_lineitems.ts b/model/gcp/displayvideo/extensions/models/advertisers_lineitems.ts index 5f1497e5d..0475e69c5 100644 --- a/model/gcp/displayvideo/extensions/models/advertisers_lineitems.ts +++ b/model/gcp/displayvideo/extensions/models/advertisers_lineitems.ts @@ -103,7 +103,7 @@ const GlobalArgsSchema = z.object({ bidStrategy: z.object({ demandGenBid: z.object({ effectiveBiddingValue: z.string().describe( - "Output only. If AG doesn't set value for tCPA or tROAS, line item bidding value will be the effective_bidding_value, if the bidding strategy type is not tCPA or tROAS, effective_bidding_value is always 0. For line item, it will be the same as the value field.", + "Output only. The value effectively used by the bidding strategy. This field will be the same as value if set. If value is not set and the strategy is assigned to an ad group, this field will be inherited from the line item's bidding strategy. If type is not `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPA` or `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_ROAS`, this field will be 0.", ).optional(), effectiveBiddingValueSource: z.enum([ "BIDDING_SOURCE_UNSPECIFIED", @@ -119,10 +119,10 @@ const GlobalArgsSchema = z.object({ "DEMAND_GEN_BIDDING_STRATEGY_TYPE_MAXIMIZE_CONVERSION_VALUE", "DEMAND_GEN_BIDDING_STRATEGY_TYPE_MAXIMIZE_CLICKS", ]).describe( - "Optional. The type of the bidding strategy. This can only be set at the line item level.", + "Optional. The type of the bidding strategy. This can only be set when assigned to a line item. Ad groups will inherit this value from their line item.", ).optional(), value: z.string().describe( - "Optional. The value used by the bidding strategy. This can be set at the line item and ad group level. This field is only applicable for the following strategy types: * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPA` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPC` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_ROAS` Value of this field is in micros of the advertiser's currency or ROAS value. For example, 1000000 represents 1.0 standard units of the currency or 100% ROAS value. If not using an applicable strategy, the value of this field will be 0.", + "Optional. The value used by the bidding strategy. This can be set when assigned to line items or ad groups. This field is only applicable for the following strategy types: * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPA` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPC` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_ROAS` Value of this field is in micros of the advertiser's currency or ROAS value. For example, 1000000 represents 1.0 standard units of the currency or 100% ROAS value. If not using an applicable strategy, the value of this field will be 0.", ).optional(), }).describe( "Settings that control the bid strategy for Demand Gen resources.", @@ -224,7 +224,7 @@ const GlobalArgsSchema = z.object({ "LINE_ITEM_BUDGET_ALLOCATION_TYPE_FIXED", "LINE_ITEM_BUDGET_ALLOCATION_TYPE_UNLIMITED", ]).describe( - "Required. The type of the budget allocation. `LINE_ITEM_BUDGET_ALLOCATION_TYPE_AUTOMATIC` is only applicable when automatic budget allocation is enabled for the parent insertion order. For demand gen line items, budget allocation type must be `LINE_ITEM_BUDGET_ALLOCATION_TYPE_FIXED`. Demand Gen line items do not support other budget allocation types.", + "Required. The type of the budget allocation. `LINE_ITEM_BUDGET_ALLOCATION_TYPE_AUTOMATIC` is only applicable when automatic budget allocation is enabled for the parent insertion order. This field must be set to `LINE_ITEM_BUDGET_ALLOCATION_TYPE_FIXED` for Demand Gen line items.", ).optional(), budgetUnit: z.enum([ "BUDGET_UNIT_UNSPECIFIED", @@ -262,7 +262,7 @@ const GlobalArgsSchema = z.object({ "The percentage of post-view conversions to count, in millis (1/1000 of a percent). Must be between 0 and 100000 inclusive. For example, to track 50% of the post-click conversions, set a value of 50000.", ).optional(), primaryAttributionModelId: z.string().describe( - "Optional. The attribution model to use for conversion measurement. This attribution model will determine how conversions are counted. The Primary model can be set by you for a floodlight config or group. More details [here](https://support.google.com/displayvideo/answer/7409983). Only applicable to Demand Gen line items.", + "Optional. The attribution model to use for conversion measurement. This attribution model will determine how conversions are counted. The Primary model can be set by you for a floodlight config or group. More details [here](https://support.google.com/displayvideo/answer/7409983). Only applicable to Demand Gen line items. Retrieval and management of Demand Gen resources is currently in beta. This field is only available to allowlisted users.", ).optional(), }).describe( "Settings that control how conversions are counted. All post-click conversions will be counted. A percentage value can be set for post-view conversions counting.", @@ -272,10 +272,10 @@ const GlobalArgsSchema = z.object({ ).optional(), demandGenSettings: z.object({ geoLanguageTargetingEnabled: z.boolean().describe( - "Optional. Immutable. Whether location and language targeting can be set at the line item level. Otherwise, relevant targeting types must be assigned directly to the ad groups.", + "Optional. Immutable. Whether location and language targeting can be set at the line item level. Otherwise, relevant targeting types must be assigned directly to ad groups.", ).optional(), linkedMerchantId: z.string().describe( - "Optional. The ID of the merchant which is linked to the line item for product feed.", + "Optional. The ID of the Merchant Center account used to provide a product feed. This Merchant Center account must already be linked to the advertiser.", ).optional(), thirdPartyMeasurementConfigs: z.object({ brandLiftVendorConfigs: z.array(z.object({ @@ -336,7 +336,7 @@ const GlobalArgsSchema = z.object({ "THIRD_PARTY_VENDOR_VIDEO_RESEARCH", ]).describe("The third-party measurement vendor.").optional(), })).describe( - "Optional. The third-party vendors measuring brand safety. The following third-party vendors are applicable: * `THIRD_PARTY_VENDOR_DOUBLE_VERIFY` * `THIRD_PARTY_VENDOR_INTEGRAL_AD_SCIENCE` * `THIRD_PARTY_VENDOR_ZEFR`", + "Optional. The third-party vendors measuring brand safety. The following third-party vendors are applicable: * `THIRD_PARTY_VENDOR_ZEFR` * `THIRD_PARTY_VENDOR_DOUBLE_VERIFY` * `THIRD_PARTY_VENDOR_INTEGRAL_AD_SCIENCE`", ).optional(), reachVendorConfigs: z.array(z.object({ placementId: z.string().describe( @@ -618,7 +618,7 @@ const GlobalArgsSchema = z.object({ "PARTNER_REVENUE_MODEL_MARKUP_TYPE_MEDIA_COST_MARKUP", "PARTNER_REVENUE_MODEL_MARKUP_TYPE_TOTAL_MEDIA_COST_MARKUP", ]).describe( - "Required. The markup type of the partner revenue model. Demand Gen line items only support `PARTNER_REVENUE_MODEL_MARKUP_TYPE_TOTAL_MEDIA_COST_MARKUP`.", + "Required. The markup type of the partner revenue model. This field must be set to `PARTNER_REVENUE_MODEL_MARKUP_TYPE_TOTAL_MEDIA_COST_MARKUP` for Demand Gen line items.", ).optional(), }).describe("Settings that control how partner revenue is calculated.") .optional(), @@ -639,7 +639,7 @@ const GlobalArgsSchema = z.object({ "Required. Whether to enable Optimized Targeting for the line item. Optimized targeting is not compatible with all bid strategies. Attempting to set this field to `true` for a line item using the BiddingStrategy field fixed_bid or one of the following combinations of BiddingStrategy fields and BiddingStrategyPerformanceGoalType will result in an error: maximize_auto_spend_bid: * `BIDDING_STRATEGY_PERFORMANCE_GOAL_TYPE_CIVA` * `BIDDING_STRATEGY_PERFORMANCE_GOAL_TYPE_IVO_TEN` * `BIDDING_STRATEGY_PERFORMANCE_GOAL_TYPE_AV_VIEWED` performance_goal_auto_bid: * `BIDDING_STRATEGY_PERFORMANCE_GOAL_TYPE_VIEWABLE_CPM` This also applies if the line item inherits one of the above bid strategies from the parent insertion order. Bid strategies set at the insertion order-level will be inherited by their line items if the `InsertionOrder` budget field automationType is set to `INSERTION_ORDER_AUTOMATION_TYPE_BUDGET` or `INSERTION_ORDER_AUTOMATION_TYPE_BID_BUDGET`.", ).optional(), excludeDemographicExpansion: z.boolean().describe( - "Optional. Whether to exclude demographic expansion for Optimized Targeting. This field only applies to Demand Gen ad groups.", + "Optional. Whether to exclude demographic expansion for Optimized Targeting. This field can only be set for Demand Gen ad groups. Retrieval and management of Demand Gen resources is currently in beta. This field is only available to allowlisted users.", ).optional(), }).describe( "Settings that control the [optimized targeting](//support.google.com/displayvideo/answer/12060859) settings of the line item.", @@ -678,7 +678,7 @@ const GlobalArgsSchema = z.object({ "Optional. The ID of the form to generate leads.", ).optional(), linkedMerchantId: z.string().describe( - "Optional. The ID of the merchant which is linked to the line item for product feed.", + "Optional. The ID of the Merchant Center account used to provide a product feed. This Merchant Center account must already be linked to the advertiser.", ).optional(), relatedVideoIds: z.array(z.string()).describe( "Optional. The IDs of the videos appear below the primary video ad when the ad is playing in the YouTube app on mobile devices.", @@ -763,7 +763,7 @@ const GlobalArgsSchema = z.object({ "THIRD_PARTY_VENDOR_VIDEO_RESEARCH", ]).describe("The third-party measurement vendor.").optional(), })).describe( - "Optional. The third-party vendors measuring brand safety. The following third-party vendors are applicable: * `THIRD_PARTY_VENDOR_DOUBLE_VERIFY` * `THIRD_PARTY_VENDOR_INTEGRAL_AD_SCIENCE` * `THIRD_PARTY_VENDOR_ZEFR`", + "Optional. The third-party vendors measuring brand safety. The following third-party vendors are applicable: * `THIRD_PARTY_VENDOR_ZEFR` * `THIRD_PARTY_VENDOR_DOUBLE_VERIFY` * `THIRD_PARTY_VENDOR_INTEGRAL_AD_SCIENCE`", ).optional(), reachVendorConfigs: z.array(z.object({ placementId: z.string().describe( @@ -1101,7 +1101,7 @@ const InputsSchema = z.object({ bidStrategy: z.object({ demandGenBid: z.object({ effectiveBiddingValue: z.string().describe( - "Output only. If AG doesn't set value for tCPA or tROAS, line item bidding value will be the effective_bidding_value, if the bidding strategy type is not tCPA or tROAS, effective_bidding_value is always 0. For line item, it will be the same as the value field.", + "Output only. The value effectively used by the bidding strategy. This field will be the same as value if set. If value is not set and the strategy is assigned to an ad group, this field will be inherited from the line item's bidding strategy. If type is not `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPA` or `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_ROAS`, this field will be 0.", ).optional(), effectiveBiddingValueSource: z.enum([ "BIDDING_SOURCE_UNSPECIFIED", @@ -1117,10 +1117,10 @@ const InputsSchema = z.object({ "DEMAND_GEN_BIDDING_STRATEGY_TYPE_MAXIMIZE_CONVERSION_VALUE", "DEMAND_GEN_BIDDING_STRATEGY_TYPE_MAXIMIZE_CLICKS", ]).describe( - "Optional. The type of the bidding strategy. This can only be set at the line item level.", + "Optional. The type of the bidding strategy. This can only be set when assigned to a line item. Ad groups will inherit this value from their line item.", ).optional(), value: z.string().describe( - "Optional. The value used by the bidding strategy. This can be set at the line item and ad group level. This field is only applicable for the following strategy types: * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPA` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPC` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_ROAS` Value of this field is in micros of the advertiser's currency or ROAS value. For example, 1000000 represents 1.0 standard units of the currency or 100% ROAS value. If not using an applicable strategy, the value of this field will be 0.", + "Optional. The value used by the bidding strategy. This can be set when assigned to line items or ad groups. This field is only applicable for the following strategy types: * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPA` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_CPC` * `DEMAND_GEN_BIDDING_STRATEGY_TYPE_TARGET_ROAS` Value of this field is in micros of the advertiser's currency or ROAS value. For example, 1000000 represents 1.0 standard units of the currency or 100% ROAS value. If not using an applicable strategy, the value of this field will be 0.", ).optional(), }).describe( "Settings that control the bid strategy for Demand Gen resources.", @@ -1222,7 +1222,7 @@ const InputsSchema = z.object({ "LINE_ITEM_BUDGET_ALLOCATION_TYPE_FIXED", "LINE_ITEM_BUDGET_ALLOCATION_TYPE_UNLIMITED", ]).describe( - "Required. The type of the budget allocation. `LINE_ITEM_BUDGET_ALLOCATION_TYPE_AUTOMATIC` is only applicable when automatic budget allocation is enabled for the parent insertion order. For demand gen line items, budget allocation type must be `LINE_ITEM_BUDGET_ALLOCATION_TYPE_FIXED`. Demand Gen line items do not support other budget allocation types.", + "Required. The type of the budget allocation. `LINE_ITEM_BUDGET_ALLOCATION_TYPE_AUTOMATIC` is only applicable when automatic budget allocation is enabled for the parent insertion order. This field must be set to `LINE_ITEM_BUDGET_ALLOCATION_TYPE_FIXED` for Demand Gen line items.", ).optional(), budgetUnit: z.enum([ "BUDGET_UNIT_UNSPECIFIED", @@ -1260,7 +1260,7 @@ const InputsSchema = z.object({ "The percentage of post-view conversions to count, in millis (1/1000 of a percent). Must be between 0 and 100000 inclusive. For example, to track 50% of the post-click conversions, set a value of 50000.", ).optional(), primaryAttributionModelId: z.string().describe( - "Optional. The attribution model to use for conversion measurement. This attribution model will determine how conversions are counted. The Primary model can be set by you for a floodlight config or group. More details [here](https://support.google.com/displayvideo/answer/7409983). Only applicable to Demand Gen line items.", + "Optional. The attribution model to use for conversion measurement. This attribution model will determine how conversions are counted. The Primary model can be set by you for a floodlight config or group. More details [here](https://support.google.com/displayvideo/answer/7409983). Only applicable to Demand Gen line items. Retrieval and management of Demand Gen resources is currently in beta. This field is only available to allowlisted users.", ).optional(), }).describe( "Settings that control how conversions are counted. All post-click conversions will be counted. A percentage value can be set for post-view conversions counting.", @@ -1270,10 +1270,10 @@ const InputsSchema = z.object({ ).optional(), demandGenSettings: z.object({ geoLanguageTargetingEnabled: z.boolean().describe( - "Optional. Immutable. Whether location and language targeting can be set at the line item level. Otherwise, relevant targeting types must be assigned directly to the ad groups.", + "Optional. Immutable. Whether location and language targeting can be set at the line item level. Otherwise, relevant targeting types must be assigned directly to ad groups.", ).optional(), linkedMerchantId: z.string().describe( - "Optional. The ID of the merchant which is linked to the line item for product feed.", + "Optional. The ID of the Merchant Center account used to provide a product feed. This Merchant Center account must already be linked to the advertiser.", ).optional(), thirdPartyMeasurementConfigs: z.object({ brandLiftVendorConfigs: z.array(z.object({ @@ -1334,7 +1334,7 @@ const InputsSchema = z.object({ "THIRD_PARTY_VENDOR_VIDEO_RESEARCH", ]).describe("The third-party measurement vendor.").optional(), })).describe( - "Optional. The third-party vendors measuring brand safety. The following third-party vendors are applicable: * `THIRD_PARTY_VENDOR_DOUBLE_VERIFY` * `THIRD_PARTY_VENDOR_INTEGRAL_AD_SCIENCE` * `THIRD_PARTY_VENDOR_ZEFR`", + "Optional. The third-party vendors measuring brand safety. The following third-party vendors are applicable: * `THIRD_PARTY_VENDOR_ZEFR` * `THIRD_PARTY_VENDOR_DOUBLE_VERIFY` * `THIRD_PARTY_VENDOR_INTEGRAL_AD_SCIENCE`", ).optional(), reachVendorConfigs: z.array(z.object({ placementId: z.string().describe( @@ -1616,7 +1616,7 @@ const InputsSchema = z.object({ "PARTNER_REVENUE_MODEL_MARKUP_TYPE_MEDIA_COST_MARKUP", "PARTNER_REVENUE_MODEL_MARKUP_TYPE_TOTAL_MEDIA_COST_MARKUP", ]).describe( - "Required. The markup type of the partner revenue model. Demand Gen line items only support `PARTNER_REVENUE_MODEL_MARKUP_TYPE_TOTAL_MEDIA_COST_MARKUP`.", + "Required. The markup type of the partner revenue model. This field must be set to `PARTNER_REVENUE_MODEL_MARKUP_TYPE_TOTAL_MEDIA_COST_MARKUP` for Demand Gen line items.", ).optional(), }).describe("Settings that control how partner revenue is calculated.") .optional(), @@ -1637,7 +1637,7 @@ const InputsSchema = z.object({ "Required. Whether to enable Optimized Targeting for the line item. Optimized targeting is not compatible with all bid strategies. Attempting to set this field to `true` for a line item using the BiddingStrategy field fixed_bid or one of the following combinations of BiddingStrategy fields and BiddingStrategyPerformanceGoalType will result in an error: maximize_auto_spend_bid: * `BIDDING_STRATEGY_PERFORMANCE_GOAL_TYPE_CIVA` * `BIDDING_STRATEGY_PERFORMANCE_GOAL_TYPE_IVO_TEN` * `BIDDING_STRATEGY_PERFORMANCE_GOAL_TYPE_AV_VIEWED` performance_goal_auto_bid: * `BIDDING_STRATEGY_PERFORMANCE_GOAL_TYPE_VIEWABLE_CPM` This also applies if the line item inherits one of the above bid strategies from the parent insertion order. Bid strategies set at the insertion order-level will be inherited by their line items if the `InsertionOrder` budget field automationType is set to `INSERTION_ORDER_AUTOMATION_TYPE_BUDGET` or `INSERTION_ORDER_AUTOMATION_TYPE_BID_BUDGET`.", ).optional(), excludeDemographicExpansion: z.boolean().describe( - "Optional. Whether to exclude demographic expansion for Optimized Targeting. This field only applies to Demand Gen ad groups.", + "Optional. Whether to exclude demographic expansion for Optimized Targeting. This field can only be set for Demand Gen ad groups. Retrieval and management of Demand Gen resources is currently in beta. This field is only available to allowlisted users.", ).optional(), }).describe( "Settings that control the [optimized targeting](//support.google.com/displayvideo/answer/12060859) settings of the line item.", @@ -1676,7 +1676,7 @@ const InputsSchema = z.object({ "Optional. The ID of the form to generate leads.", ).optional(), linkedMerchantId: z.string().describe( - "Optional. The ID of the merchant which is linked to the line item for product feed.", + "Optional. The ID of the Merchant Center account used to provide a product feed. This Merchant Center account must already be linked to the advertiser.", ).optional(), relatedVideoIds: z.array(z.string()).describe( "Optional. The IDs of the videos appear below the primary video ad when the ad is playing in the YouTube app on mobile devices.", @@ -1761,7 +1761,7 @@ const InputsSchema = z.object({ "THIRD_PARTY_VENDOR_VIDEO_RESEARCH", ]).describe("The third-party measurement vendor.").optional(), })).describe( - "Optional. The third-party vendors measuring brand safety. The following third-party vendors are applicable: * `THIRD_PARTY_VENDOR_DOUBLE_VERIFY` * `THIRD_PARTY_VENDOR_INTEGRAL_AD_SCIENCE` * `THIRD_PARTY_VENDOR_ZEFR`", + "Optional. The third-party vendors measuring brand safety. The following third-party vendors are applicable: * `THIRD_PARTY_VENDOR_ZEFR` * `THIRD_PARTY_VENDOR_DOUBLE_VERIFY` * `THIRD_PARTY_VENDOR_INTEGRAL_AD_SCIENCE`", ).optional(), reachVendorConfigs: z.array(z.object({ placementId: z.string().describe( @@ -1898,7 +1898,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/displayvideo/advertisers-lineitems", - version: "2026.04.03.3", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -1930,6 +1930,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, diff --git a/model/gcp/displayvideo/extensions/models/advertisers_lineitems_targetingtypes_assignedtargetingoptions.ts b/model/gcp/displayvideo/extensions/models/advertisers_lineitems_targetingtypes_assignedtargetingoptions.ts index 05d3afc57..1ea390b50 100644 --- a/model/gcp/displayvideo/extensions/models/advertisers_lineitems_targetingtypes_assignedtargetingoptions.ts +++ b/model/gcp/displayvideo/extensions/models/advertisers_lineitems_targetingtypes_assignedtargetingoptions.ts @@ -520,7 +520,7 @@ const GlobalArgsSchema = z.object({ "TIME_ZONE_RESOLUTION_END_USER", "TIME_ZONE_RESOLUTION_ADVERTISER", ]).describe( - "Required. The mechanism used to determine which timezone to use for this day and time targeting setting. For demand gen line items, this field is always TIME_ZONE_RESOLUTION_ADVERTISER.", + "Required. The mechanism used to determine which timezone to use for this day and time targeting setting. For Demand Gen line items, this field is always `TIME_ZONE_RESOLUTION_ADVERTISER`.", ).optional(), }).describe( "Representation of a segment of time defined on a specific day of the week and with a start and end time. The time represented by `start_hour` must be before the time represented by `end_hour`.", @@ -768,7 +768,7 @@ const GlobalArgsSchema = z.object({ ).optional(), keywordDetails: z.object({ exemptedPolicyNames: z.array(z.string()).describe( - "Optional. The policy names to exempt the keyword from. This field is only applicable for Demand Gen keywords, which are positively targeted.", + "Optional. The policy names to exempt the keyword from. When attempting to target a keyword that violates a policy, the error returned will include the name of the relevant policy. Use that name in this field to exempt the targeted keyword from the policy. This field is only applicable for positively-targeted keywords assigned to Demand Gen resources. Retrieval and management of Demand Gen resources is currently in beta. This field is only available to allowlisted users.", ).optional(), keyword: z.string().describe( "Required. The keyword, for example `car insurance`. Positive keyword cannot be offensive word. Must be UTF-8 encoded with a maximum size of 255 bytes. Maximum number of characters is 80. Maximum number of words is 10.", @@ -2186,7 +2186,7 @@ const InputsSchema = z.object({ "TIME_ZONE_RESOLUTION_END_USER", "TIME_ZONE_RESOLUTION_ADVERTISER", ]).describe( - "Required. The mechanism used to determine which timezone to use for this day and time targeting setting. For demand gen line items, this field is always TIME_ZONE_RESOLUTION_ADVERTISER.", + "Required. The mechanism used to determine which timezone to use for this day and time targeting setting. For Demand Gen line items, this field is always `TIME_ZONE_RESOLUTION_ADVERTISER`.", ).optional(), }).describe( "Representation of a segment of time defined on a specific day of the week and with a start and end time. The time represented by `start_hour` must be before the time represented by `end_hour`.", @@ -2434,7 +2434,7 @@ const InputsSchema = z.object({ ).optional(), keywordDetails: z.object({ exemptedPolicyNames: z.array(z.string()).describe( - "Optional. The policy names to exempt the keyword from. This field is only applicable for Demand Gen keywords, which are positively targeted.", + "Optional. The policy names to exempt the keyword from. When attempting to target a keyword that violates a policy, the error returned will include the name of the relevant policy. Use that name in this field to exempt the targeted keyword from the policy. This field is only applicable for positively-targeted keywords assigned to Demand Gen resources. Retrieval and management of Demand Gen resources is currently in beta. This field is only available to allowlisted users.", ).optional(), keyword: z.string().describe( "Required. The keyword, for example `car insurance`. Positive keyword cannot be offensive word. Must be UTF-8 encoded with a maximum size of 255 bytes. Maximum number of characters is 80. Maximum number of words is 10.", @@ -3140,7 +3140,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/displayvideo/advertisers-lineitems-targetingtypes-assignedtargetingoptions", - version: "2026.04.04.1", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -3172,6 +3172,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, diff --git a/model/gcp/displayvideo/extensions/models/advertisers_targetingtypes_assignedtargetingoptions.ts b/model/gcp/displayvideo/extensions/models/advertisers_targetingtypes_assignedtargetingoptions.ts index 9b0fe2cd8..da8a550d9 100644 --- a/model/gcp/displayvideo/extensions/models/advertisers_targetingtypes_assignedtargetingoptions.ts +++ b/model/gcp/displayvideo/extensions/models/advertisers_targetingtypes_assignedtargetingoptions.ts @@ -504,7 +504,7 @@ const GlobalArgsSchema = z.object({ "TIME_ZONE_RESOLUTION_END_USER", "TIME_ZONE_RESOLUTION_ADVERTISER", ]).describe( - "Required. The mechanism used to determine which timezone to use for this day and time targeting setting. For demand gen line items, this field is always TIME_ZONE_RESOLUTION_ADVERTISER.", + "Required. The mechanism used to determine which timezone to use for this day and time targeting setting. For Demand Gen line items, this field is always `TIME_ZONE_RESOLUTION_ADVERTISER`.", ).optional(), }).describe( "Representation of a segment of time defined on a specific day of the week and with a start and end time. The time represented by `start_hour` must be before the time represented by `end_hour`.", @@ -752,7 +752,7 @@ const GlobalArgsSchema = z.object({ ).optional(), keywordDetails: z.object({ exemptedPolicyNames: z.array(z.string()).describe( - "Optional. The policy names to exempt the keyword from. This field is only applicable for Demand Gen keywords, which are positively targeted.", + "Optional. The policy names to exempt the keyword from. When attempting to target a keyword that violates a policy, the error returned will include the name of the relevant policy. Use that name in this field to exempt the targeted keyword from the policy. This field is only applicable for positively-targeted keywords assigned to Demand Gen resources. Retrieval and management of Demand Gen resources is currently in beta. This field is only available to allowlisted users.", ).optional(), keyword: z.string().describe( "Required. The keyword, for example `car insurance`. Positive keyword cannot be offensive word. Must be UTF-8 encoded with a maximum size of 255 bytes. Maximum number of characters is 80. Maximum number of words is 10.", @@ -2165,7 +2165,7 @@ const InputsSchema = z.object({ "TIME_ZONE_RESOLUTION_END_USER", "TIME_ZONE_RESOLUTION_ADVERTISER", ]).describe( - "Required. The mechanism used to determine which timezone to use for this day and time targeting setting. For demand gen line items, this field is always TIME_ZONE_RESOLUTION_ADVERTISER.", + "Required. The mechanism used to determine which timezone to use for this day and time targeting setting. For Demand Gen line items, this field is always `TIME_ZONE_RESOLUTION_ADVERTISER`.", ).optional(), }).describe( "Representation of a segment of time defined on a specific day of the week and with a start and end time. The time represented by `start_hour` must be before the time represented by `end_hour`.", @@ -2413,7 +2413,7 @@ const InputsSchema = z.object({ ).optional(), keywordDetails: z.object({ exemptedPolicyNames: z.array(z.string()).describe( - "Optional. The policy names to exempt the keyword from. This field is only applicable for Demand Gen keywords, which are positively targeted.", + "Optional. The policy names to exempt the keyword from. When attempting to target a keyword that violates a policy, the error returned will include the name of the relevant policy. Use that name in this field to exempt the targeted keyword from the policy. This field is only applicable for positively-targeted keywords assigned to Demand Gen resources. Retrieval and management of Demand Gen resources is currently in beta. This field is only available to allowlisted users.", ).optional(), keyword: z.string().describe( "Required. The keyword, for example `car insurance`. Positive keyword cannot be offensive word. Must be UTF-8 encoded with a maximum size of 255 bytes. Maximum number of characters is 80. Maximum number of words is 10.", @@ -3115,7 +3115,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/displayvideo/advertisers-targetingtypes-assignedtargetingoptions", - version: "2026.04.04.1", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -3147,6 +3147,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, diff --git a/model/gcp/displayvideo/extensions/models/inventorysources.ts b/model/gcp/displayvideo/extensions/models/inventorysources.ts index 3ed325acd..aece3eaa4 100644 --- a/model/gcp/displayvideo/extensions/models/inventorysources.ts +++ b/model/gcp/displayvideo/extensions/models/inventorysources.ts @@ -668,7 +668,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/displayvideo/inventorysources", - version: "2026.04.03.3", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -695,12 +695,17 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, resources: { state: { - description: "An inventory source. Next ID: 22", + description: "An inventory source.", schema: StateSchema, lifetime: "infinite", garbageCollection: 10, diff --git a/model/gcp/displayvideo/extensions/models/partners_targetingtypes_assignedtargetingoptions.ts b/model/gcp/displayvideo/extensions/models/partners_targetingtypes_assignedtargetingoptions.ts index 4dd241249..e4875977b 100644 --- a/model/gcp/displayvideo/extensions/models/partners_targetingtypes_assignedtargetingoptions.ts +++ b/model/gcp/displayvideo/extensions/models/partners_targetingtypes_assignedtargetingoptions.ts @@ -502,7 +502,7 @@ const GlobalArgsSchema = z.object({ "TIME_ZONE_RESOLUTION_END_USER", "TIME_ZONE_RESOLUTION_ADVERTISER", ]).describe( - "Required. The mechanism used to determine which timezone to use for this day and time targeting setting. For demand gen line items, this field is always TIME_ZONE_RESOLUTION_ADVERTISER.", + "Required. The mechanism used to determine which timezone to use for this day and time targeting setting. For Demand Gen line items, this field is always `TIME_ZONE_RESOLUTION_ADVERTISER`.", ).optional(), }).describe( "Representation of a segment of time defined on a specific day of the week and with a start and end time. The time represented by `start_hour` must be before the time represented by `end_hour`.", @@ -750,7 +750,7 @@ const GlobalArgsSchema = z.object({ ).optional(), keywordDetails: z.object({ exemptedPolicyNames: z.array(z.string()).describe( - "Optional. The policy names to exempt the keyword from. This field is only applicable for Demand Gen keywords, which are positively targeted.", + "Optional. The policy names to exempt the keyword from. When attempting to target a keyword that violates a policy, the error returned will include the name of the relevant policy. Use that name in this field to exempt the targeted keyword from the policy. This field is only applicable for positively-targeted keywords assigned to Demand Gen resources. Retrieval and management of Demand Gen resources is currently in beta. This field is only available to allowlisted users.", ).optional(), keyword: z.string().describe( "Required. The keyword, for example `car insurance`. Positive keyword cannot be offensive word. Must be UTF-8 encoded with a maximum size of 255 bytes. Maximum number of characters is 80. Maximum number of words is 10.", @@ -2163,7 +2163,7 @@ const InputsSchema = z.object({ "TIME_ZONE_RESOLUTION_END_USER", "TIME_ZONE_RESOLUTION_ADVERTISER", ]).describe( - "Required. The mechanism used to determine which timezone to use for this day and time targeting setting. For demand gen line items, this field is always TIME_ZONE_RESOLUTION_ADVERTISER.", + "Required. The mechanism used to determine which timezone to use for this day and time targeting setting. For Demand Gen line items, this field is always `TIME_ZONE_RESOLUTION_ADVERTISER`.", ).optional(), }).describe( "Representation of a segment of time defined on a specific day of the week and with a start and end time. The time represented by `start_hour` must be before the time represented by `end_hour`.", @@ -2411,7 +2411,7 @@ const InputsSchema = z.object({ ).optional(), keywordDetails: z.object({ exemptedPolicyNames: z.array(z.string()).describe( - "Optional. The policy names to exempt the keyword from. This field is only applicable for Demand Gen keywords, which are positively targeted.", + "Optional. The policy names to exempt the keyword from. When attempting to target a keyword that violates a policy, the error returned will include the name of the relevant policy. Use that name in this field to exempt the targeted keyword from the policy. This field is only applicable for positively-targeted keywords assigned to Demand Gen resources. Retrieval and management of Demand Gen resources is currently in beta. This field is only available to allowlisted users.", ).optional(), keyword: z.string().describe( "Required. The keyword, for example `car insurance`. Positive keyword cannot be offensive word. Must be UTF-8 encoded with a maximum size of 255 bytes. Maximum number of characters is 80. Maximum number of words is 10.", @@ -3112,7 +3112,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/displayvideo/partners-targetingtypes-assignedtargetingoptions", - version: "2026.04.04.1", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.1", @@ -3144,6 +3144,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "No schema changes", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, diff --git a/model/gcp/displayvideo/manifest.yaml b/model/gcp/displayvideo/manifest.yaml index 648417282..c33c53ee4 100644 --- a/model/gcp/displayvideo/manifest.yaml +++ b/model/gcp/displayvideo/manifest.yaml @@ -1,7 +1,7 @@ # Auto-generated manifest. Re-generate with the appropriate deno task. manifestVersion: 1 name: "@swamp/gcp/displayvideo" -version: "2026.04.04.1" +version: "2026.04.08.1" description: "Google Cloud displayvideo infrastructure models" labels: - gcp @@ -10,7 +10,7 @@ labels: - cloud - infrastructure releaseNotes: | - - Updated: advertisers_adgroupads, advertisers_adgroups_targetingtypes_assignedtargetingoptions, advertisers_adgroups_youtubeassettypes_youtubeassetassociations, advertisers_insertionorders, advertisers_lineitems_targetingtypes_assignedtargetingoptions, advertisers_lineitems_youtubeassettypes_youtubeassetassociations, advertisers_targetingtypes_assignedtargetingoptions, partners_targetingtypes_assignedtargetingoptions + - Updated: advertisers_adgroupads, advertisers_adgroups, advertisers_adgroups_targetingtypes_assignedtargetingoptions, advertisers_insertionorders, advertisers_lineitems, advertisers_lineitems_targetingtypes_assignedtargetingoptions, advertisers_targetingtypes_assignedtargetingoptions, inventorysources, partners_targetingtypes_assignedtargetingoptions models: - advertisers.ts - advertisers_adassets.ts diff --git a/model/gcp/workstations/extensions/models/workstationclusters.ts b/model/gcp/workstations/extensions/models/workstationclusters.ts index 01475ca21..e6859f32a 100644 --- a/model/gcp/workstations/extensions/models/workstationclusters.ts +++ b/model/gcp/workstations/extensions/models/workstationclusters.ts @@ -151,6 +151,12 @@ const GlobalArgsSchema = z.object({ tags: z.record(z.string(), z.string()).describe( 'Optional. Input only. Immutable. Tag keys/values directly bound to this resource. For example: "123/environment": "production", "123/costCenter": "marketing"', ).optional(), + workstationAuthorizationUrl: z.string().describe( + "Optional. Specifies the redirect URL for unauthorized requests received by workstation VMs in this cluster. Redirects to this endpoint will send a base64 encoded `state` query param containing the target workstation name and original request hostname. The endpoint is responsible for retrieving a token using `GenerateAccessToken` and redirecting back to the original hostname with the token.", + ).optional(), + workstationLaunchUrl: z.string().describe( + "Optional. Specifies the launch URL for workstations in this cluster. Requests sent to unstarted workstations will be redirected to this URL. Requests redirected to the launch endpoint will be sent with a `workstation` and `project` query parameter containing the full workstation resource name and project ID, respectively. The launch endpoint is responsible for starting the workstation, polling it until it reaches `STATE_RUNNING`, and then issuing a redirect to the workstation's host URL.", + ).optional(), workstationClusterId: z.string().describe( "Required. ID to use for the workstation cluster.", ).optional(), @@ -192,6 +198,8 @@ const StateSchema = z.object({ tags: z.record(z.string(), z.unknown()).optional(), uid: z.string().optional(), updateTime: z.string().optional(), + workstationAuthorizationUrl: z.string().optional(), + workstationLaunchUrl: z.string().optional(), }).passthrough(); type StateData = z.infer; @@ -243,6 +251,12 @@ const InputsSchema = z.object({ tags: z.record(z.string(), z.string()).describe( 'Optional. Input only. Immutable. Tag keys/values directly bound to this resource. For example: "123/environment": "production", "123/costCenter": "marketing"', ).optional(), + workstationAuthorizationUrl: z.string().describe( + "Optional. Specifies the redirect URL for unauthorized requests received by workstation VMs in this cluster. Redirects to this endpoint will send a base64 encoded `state` query param containing the target workstation name and original request hostname. The endpoint is responsible for retrieving a token using `GenerateAccessToken` and redirecting back to the original hostname with the token.", + ).optional(), + workstationLaunchUrl: z.string().describe( + "Optional. Specifies the launch URL for workstations in this cluster. Requests sent to unstarted workstations will be redirected to this URL. Requests redirected to the launch endpoint will be sent with a `workstation` and `project` query parameter containing the full workstation resource name and project ID, respectively. The launch endpoint is responsible for starting the workstation, polling it until it reaches `STATE_RUNNING`, and then issuing a redirect to the workstation's host URL.", + ).optional(), workstationClusterId: z.string().describe( "Required. ID to use for the workstation cluster.", ).optional(), @@ -253,7 +267,7 @@ const InputsSchema = z.object({ export const model = { type: "@swamp/gcp/workstations/workstationclusters", - version: "2026.04.03.3", + version: "2026.04.08.1", upgrades: [ { toVersion: "2026.04.01.2", @@ -280,6 +294,11 @@ export const model = { description: "No schema changes", upgradeAttributes: (old: Record) => old, }, + { + toVersion: "2026.04.08.1", + description: "Added: workstationAuthorizationUrl, workstationLaunchUrl", + upgradeAttributes: (old: Record) => old, + }, ], globalArguments: GlobalArgsSchema, inputsSchema: InputsSchema, @@ -322,6 +341,13 @@ export const model = { } if (g["subnetwork"] !== undefined) body["subnetwork"] = g["subnetwork"]; if (g["tags"] !== undefined) body["tags"] = g["tags"]; + if (g["workstationAuthorizationUrl"] !== undefined) { + body["workstationAuthorizationUrl"] = + g["workstationAuthorizationUrl"]; + } + if (g["workstationLaunchUrl"] !== undefined) { + body["workstationLaunchUrl"] = g["workstationLaunchUrl"]; + } if (g["workstationClusterId"] !== undefined) { body["workstationClusterId"] = g["workstationClusterId"]; } @@ -420,6 +446,13 @@ export const model = { if (g["privateClusterConfig"] !== undefined) { body["privateClusterConfig"] = g["privateClusterConfig"]; } + if (g["workstationAuthorizationUrl"] !== undefined) { + body["workstationAuthorizationUrl"] = + g["workstationAuthorizationUrl"]; + } + if (g["workstationLaunchUrl"] !== undefined) { + body["workstationLaunchUrl"] = g["workstationLaunchUrl"]; + } for (const key of Object.keys(existing)) { if ( key === "fingerprint" || key === "labelFingerprint" || diff --git a/model/gcp/workstations/manifest.yaml b/model/gcp/workstations/manifest.yaml index 0468ff55a..b166a12be 100644 --- a/model/gcp/workstations/manifest.yaml +++ b/model/gcp/workstations/manifest.yaml @@ -1,7 +1,7 @@ # Auto-generated manifest. Re-generate with the appropriate deno task. manifestVersion: 1 name: "@swamp/gcp/workstations" -version: "2026.04.04.1" +version: "2026.04.08.1" description: "Google Cloud workstations infrastructure models" labels: - gcp @@ -10,7 +10,7 @@ labels: - cloud - infrastructure releaseNotes: | - - Updated: workstationclusters_workstationconfigs + - Updated: workstationclusters models: - locations.ts - workstationclusters.ts