diff --git a/apps/web/package.json b/apps/web/package.json index 4ad394813..6310be8d5 100644 --- a/apps/web/package.json +++ b/apps/web/package.json @@ -33,8 +33,10 @@ "@ai-sdk/openai": "^3.0.41", "@ai-sdk/openai-compatible": "^2.0.35", "@anthropic-ai/sdk": "^0.90.0", + "@aws-crypto/sha256-js": "^5.2.0", "@aws-sdk/client-s3": "^3.1009.0", "@aws-sdk/s3-request-presigner": "^3.1009.0", + "@aws-sdk/signature-v4": "^3.374.0", "@chat-adapter/github": "4.27.0", "@chat-adapter/slack": "^4.27.0", "@chat-adapter/state-memory": "^4.27.0", diff --git a/apps/web/src/lib/ai-gateway/providers/bedrock-signer.ts b/apps/web/src/lib/ai-gateway/providers/bedrock-signer.ts new file mode 100644 index 000000000..f962bf277 --- /dev/null +++ b/apps/web/src/lib/ai-gateway/providers/bedrock-signer.ts @@ -0,0 +1,54 @@ +import { SignatureV4 } from '@aws-sdk/signature-v4'; +import { Sha256 } from '@aws-crypto/sha256-js'; +import type { CustomLlmAwsBedrock } from '@kilocode/db'; +import type { SignedRequest, SignRequestArgs } from '@/lib/ai-gateway/providers/types'; + +export function makeBedrockSignRequest( + credentials: CustomLlmAwsBedrock, + modelId: string +): (args: SignRequestArgs) => Promise { + const signer = new SignatureV4({ + credentials: { + accessKeyId: credentials.access_key_id, + secretAccessKey: credentials.secret_access_key, + }, + region: credentials.region, + service: 'bedrock', + sha256: Sha256, + }); + + const hostname = `bedrock-runtime.${credentials.region}.amazonaws.com`; + + return async ({ method, body }) => { + const isStreaming = parseStreamFlag(body); + const path = `/model/${encodeURIComponent(modelId)}/${ + isStreaming ? 'invoke-with-response-stream' : 'invoke' + }`; + + const signed = await signer.sign({ + method, + hostname, + path, + protocol: 'https:', + headers: { + 'Content-Type': 'application/json', + host: hostname, + }, + body, + }); + + return { + url: `https://${hostname}${signed.path ?? path}`, + headers: signed.headers, + }; + }; +} + +function parseStreamFlag(body: string): boolean { + try { + const parsed = JSON.parse(body); + return parsed !== null && typeof parsed === 'object' && parsed.stream === true; + } catch { + return false; + } +} diff --git a/apps/web/src/lib/ai-gateway/providers/get-provider.ts b/apps/web/src/lib/ai-gateway/providers/get-provider.ts index f1b47466f..b8c9788a3 100644 --- a/apps/web/src/lib/ai-gateway/providers/get-provider.ts +++ b/apps/web/src/lib/ai-gateway/providers/get-provider.ts @@ -23,6 +23,7 @@ import { addCacheBreakpoints, injectReasoningIntoContent, } from '@/lib/ai-gateway/providers/openrouter/request-helpers'; +import { makeBedrockSignRequest } from '@/lib/ai-gateway/providers/bedrock-signer'; function inferSupportedChatApis( aiSdkProvider: CustomLlmProvider | undefined, @@ -94,6 +95,8 @@ async function checkCustomLlm( if (!customLlm || !customLlm.organization_ids.includes(organizationId)) { return null; } + const bedrock = customLlm.aws_bedrock; + const signRequest = bedrock ? makeBedrockSignRequest(bedrock, customLlm.internal_id) : undefined; return { provider: { id: 'custom', @@ -120,6 +123,7 @@ async function checkCustomLlm( injectReasoningIntoContent(context.request); } }, + signRequest, }, userByok: null, bypassAccessCheck: true, diff --git a/apps/web/src/lib/ai-gateway/providers/types.ts b/apps/web/src/lib/ai-gateway/providers/types.ts index ee7e75c02..03960e8fb 100644 --- a/apps/web/src/lib/ai-gateway/providers/types.ts +++ b/apps/web/src/lib/ai-gateway/providers/types.ts @@ -30,10 +30,23 @@ export type TransformRequestContext = { export type GatewayChatApiKind = GatewayRequest['kind']; +export type SignRequestArgs = { + method: string; + url: string; + body: string; +}; + +export type SignedRequest = { + url?: string; + headers: Record; +}; + export type Provider = { id: ProviderId; apiUrl: string; - apiKey: string; + apiKey: string | undefined; supportedChatApis: ReadonlyArray; transformRequest(context: TransformRequestContext): void; + // When set, replaces the default `Authorization: Bearer ${apiKey}` header. + signRequest?(args: SignRequestArgs): Promise; }; diff --git a/apps/web/src/lib/ai-gateway/providers/upstream-request.ts b/apps/web/src/lib/ai-gateway/providers/upstream-request.ts index ee54d04c8..28909475f 100644 --- a/apps/web/src/lib/ai-gateway/providers/upstream-request.ts +++ b/apps/web/src/lib/ai-gateway/providers/upstream-request.ts @@ -31,14 +31,28 @@ export async function upstreamRequest({ for (const [key, value] of Object.entries(ATTRIBUTION_HEADERS)) { headers.set(key, value); } - headers.set('Authorization', `Bearer ${provider.apiKey}`); headers.set('Content-Type', 'application/json'); Object.entries(extraHeaders).forEach(([key, value]) => { headers.set(key, value); }); - const targetUrl = `${provider.apiUrl}${path}${search}`; + let targetUrl = `${provider.apiUrl}${path}${search}`; + const serializedBody = JSON.stringify(body); + + if (provider.signRequest) { + const signed = await provider.signRequest({ + method, + url: targetUrl, + body: serializedBody, + }); + if (signed.url) targetUrl = signed.url; + for (const [key, value] of Object.entries(signed.headers)) { + headers.set(key, value); + } + } else if (provider.apiKey) { + headers.set('Authorization', `Bearer ${provider.apiKey}`); + } const TEN_MINUTES_MS = 10 * 60 * 1000; const timeoutSignal = AbortSignal.timeout(TEN_MINUTES_MS); @@ -47,7 +61,7 @@ export async function upstreamRequest({ return await fetch(targetUrl, { method, headers, - body: JSON.stringify(body), + body: serializedBody, // @ts-expect-error see https://github.com/node-fetch/node-fetch/issues/1769 duplex: 'half', signal: combinedSignal, diff --git a/packages/db/src/schema-types.ts b/packages/db/src/schema-types.ts index 0c77ddc49..fc386840a 100644 --- a/packages/db/src/schema-types.ts +++ b/packages/db/src/schema-types.ts @@ -951,13 +951,23 @@ export const CustomLlmPricingSchema = z.object({ export type CustomLlmPricing = z.infer; +// When set, upstream requests are SigV4-signed instead of using Bearer auth; +// `internal_id` is used as the Bedrock model id in the request path. +export const CustomLlmAwsBedrockSchema = z.object({ + access_key_id: z.string(), + secret_access_key: z.string(), + region: z.string(), +}); + +export type CustomLlmAwsBedrock = z.infer; + export const CustomLlmDefinitionSchema = z.object({ internal_id: z.string(), display_name: z.string(), context_length: z.number(), max_completion_tokens: z.number(), base_url: z.string(), - api_key: z.string(), + api_key: z.string().optional(), organization_ids: z.array(z.string()), supports_image_input: z.boolean().optional(), add_cache_breakpoints: z.boolean().optional(), @@ -968,6 +978,7 @@ export const CustomLlmDefinitionSchema = z.object({ opencode_settings: OpenCodeSettingsSchema.optional(), openclaw_settings: OpenClawModelSettingsSchema.optional(), pricing: CustomLlmPricingSchema.optional(), + aws_bedrock: CustomLlmAwsBedrockSchema.optional(), }); export type CustomLlmDefinition = z.infer; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5d9c0bf53..affddbdec 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -473,12 +473,18 @@ importers: '@anthropic-ai/sdk': specifier: ^0.90.0 version: 0.90.0(zod@4.3.6) + '@aws-crypto/sha256-js': + specifier: ^5.2.0 + version: 5.2.0 '@aws-sdk/client-s3': specifier: ^3.1009.0 version: 3.1009.0 '@aws-sdk/s3-request-presigner': specifier: ^3.1009.0 version: 3.1009.0 + '@aws-sdk/signature-v4': + specifier: ^3.374.0 + version: 3.374.0 '@chat-adapter/github': specifier: 4.27.0 version: 4.27.0 @@ -2430,6 +2436,9 @@ packages: engines: {node: '>=14.17'} hasBin: true + '@aws-crypto/crc32@3.0.0': + resolution: {integrity: sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==} + '@aws-crypto/crc32@5.2.0': resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} engines: {node: '>=16.0.0'} @@ -2450,6 +2459,9 @@ packages: '@aws-crypto/supports-web-crypto@5.2.0': resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} + '@aws-crypto/util@3.0.0': + resolution: {integrity: sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==} + '@aws-crypto/util@5.2.0': resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} @@ -2553,6 +2565,11 @@ packages: resolution: {integrity: sha512-n1qYFD+tbqZuyskVaxUE+t10AUz9g3qzDw3Tp6QZDKmqsjfDmZBd4GIk2EKJJNtcCBtE5YiUjDYA+3djFAFBBg==} engines: {node: '>=20.0.0'} + '@aws-sdk/signature-v4@3.374.0': + resolution: {integrity: sha512-2xLJvSdzcZZAg0lsDLUAuSQuihzK0dcxIK7WmfuJeF7DGKJFmp9czQmz5f3qiDz6IDQzvgK1M9vtJSVCslJbyQ==} + engines: {node: '>=14.0.0'} + deprecated: This package has moved to @smithy/signature-v4 + '@aws-sdk/token-providers@3.1009.0': resolution: {integrity: sha512-KCPLuTqN9u0Rr38Arln78fRG9KXpzsPWmof+PZzfAHMMQq2QED6YjQrkrfiH7PDefLWEposY1o4/eGwrmKA4JA==} engines: {node: '>=20.0.0'} @@ -2589,6 +2606,9 @@ packages: aws-crt: optional: true + '@aws-sdk/util-utf8-browser@3.259.0': + resolution: {integrity: sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==} + '@aws-sdk/xml-builder@3.972.11': resolution: {integrity: sha512-iitV/gZKQMvY9d7ovmyFnFuTHbBAtrmLnvaSb/3X8vOKyevwtpmEtyc8AdhVWZe0pI/1GsHxlEvQeOePFzy7KQ==} engines: {node: '>=20.0.0'} @@ -7227,6 +7247,9 @@ packages: resolution: {integrity: sha512-cr2lR792vNZcYMriSIj+Um3x9KWrjcu98kn234xA6reOAFMmbRpQMOv8KPgEmLLtx3eldU6c5wALKFqNOhugmg==} engines: {node: '>=18.0.0'} + '@smithy/eventstream-codec@1.1.0': + resolution: {integrity: sha512-3tEbUb8t8an226jKB6V/Q2XU/J53lCwCzULuBPEaF4JjSh+FlCMp7TmogE/Aij5J9DwlsZ4VAD/IRDuQ/0ZtMw==} + '@smithy/eventstream-codec@4.2.12': resolution: {integrity: sha512-FE3bZdEl62ojmy8x4FHqxq2+BuOHlcxiH5vaZ6aqHJr3AIZzwF5jfx8dEiU/X0a8RboyNDjmXjlbr8AdEyLgiA==} engines: {node: '>=18.0.0'} @@ -7267,6 +7290,10 @@ packages: resolution: {integrity: sha512-/4F1zb7Z8LOu1PalTdESFHR0RbPwHd3FcaG1sI3UEIriQTWakysgJr65lc1jj6QY5ye7aFsisajotH6UhWfm/g==} engines: {node: '>=18.0.0'} + '@smithy/is-array-buffer@1.1.0': + resolution: {integrity: sha512-twpQ/n+3OWZJ7Z+xu43MJErmhB/WO/mMTnqR6PwWQShvSJ/emx5d1N59LQZk6ZpTAeuRWrc+eHhkzTp9NFjNRQ==} + engines: {node: '>=14.0.0'} + '@smithy/is-array-buffer@2.2.0': resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} engines: {node: '>=14.0.0'} @@ -7331,6 +7358,10 @@ packages: resolution: {integrity: sha512-HrOKWsUb+otTeo1HxVWeEb99t5ER1XrBi/xka2Wv6NVmTbuCUC1dvlrksdvxFtODLBjsC+PHK+fuy2x/7Ynyiw==} engines: {node: '>=18.0.0'} + '@smithy/signature-v4@1.1.0': + resolution: {integrity: sha512-fDo3m7YqXBs7neciOePPd/X9LPm5QLlDMdIC4m1H6dgNLnXfLMFNIxEfPyohGA8VW9Wn4X8lygnPSGxDZSmp0Q==} + engines: {node: '>=14.0.0'} + '@smithy/signature-v4@5.3.12': resolution: {integrity: sha512-B/FBwO3MVOL00DaRSXfXfa/TRXRheagt/q5A2NM13u7q+sHS59EOVGQNfG7DkmVtdQm5m3vOosoKAXSqn/OEgw==} engines: {node: '>=18.0.0'} @@ -7339,6 +7370,10 @@ packages: resolution: {integrity: sha512-UqwYawyqSr/aog8mnLnfbPurS0gi4G7IYDcD28cUIBhsvWs1+rQcL2IwkUQ+QZ7dibaoRzhNF99fAQ9AUcO00w==} engines: {node: '>=18.0.0'} + '@smithy/types@1.2.0': + resolution: {integrity: sha512-z1r00TvBqF3dh4aHhya7nz1HhvCg4TRmw51fjMrh5do3h+ngSstt/yKlNbHeb9QxJmFbmN8KEVSWgb1bRvfEoA==} + engines: {node: '>=14.0.0'} + '@smithy/types@4.13.1': resolution: {integrity: sha512-787F3yzE2UiJIQ+wYW1CVg2odHjmaWLGksnKQHUrK/lYZSEcy1msuLVvxaR/sI2/aDe9U+TBuLsXnr3vod1g0g==} engines: {node: '>=18.0.0'} @@ -7359,6 +7394,10 @@ packages: resolution: {integrity: sha512-ZkJGvqBzMHVHE7r/hcuCxlTY8pQr1kMtdsVPs7ex4mMU+EAbcXppfo5NmyxMYi2XU49eqaz56j2gsk4dHHPG/g==} engines: {node: '>=18.0.0'} + '@smithy/util-buffer-from@1.1.0': + resolution: {integrity: sha512-9m6NXE0ww+ra5HKHCHig20T+FAwxBAm7DIdwc/767uGWbRcY720ybgPacQNB96JMOI7xVr/CDa3oMzKmW4a+kw==} + engines: {node: '>=14.0.0'} + '@smithy/util-buffer-from@2.2.0': resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} engines: {node: '>=14.0.0'} @@ -7383,10 +7422,18 @@ packages: resolution: {integrity: sha512-VACQVe50j0HZPjpwWcjyT51KUQ4AnsvEaQ2lKHOSL4mNLD0G9BjEniQ+yCt1qqfKfiAHRAts26ud7hBjamrwig==} engines: {node: '>=18.0.0'} + '@smithy/util-hex-encoding@1.1.0': + resolution: {integrity: sha512-7UtIE9eH0u41zpB60Jzr0oNCQ3hMJUabMcKRUVjmyHTXiWDE4vjSqN6qlih7rCNeKGbioS7f/y2Jgym4QZcKFg==} + engines: {node: '>=14.0.0'} + '@smithy/util-hex-encoding@4.2.2': resolution: {integrity: sha512-Qcz3W5vuHK4sLQdyT93k/rfrUwdJ8/HZ+nMUOyGdpeGA1Wxt65zYwi3oEl9kOM+RswvYq90fzkNDahPS8K0OIg==} engines: {node: '>=18.0.0'} + '@smithy/util-middleware@1.1.0': + resolution: {integrity: sha512-6hhckcBqVgjWAqLy2vqlPZ3rfxLDhFWEmM7oLh2POGvsi7j0tHkbN7w4DFhuBExVJAbJ/qqxqZdRY6Fu7/OezQ==} + engines: {node: '>=14.0.0'} + '@smithy/util-middleware@4.2.12': resolution: {integrity: sha512-Er805uFUOvgc0l8nv0e0su0VFISoxhJ/AwOn3gL2NWNY2LUEldP5WtVcRYSQBcjg0y9NfG8JYrCJaYDpupBHJQ==} engines: {node: '>=18.0.0'} @@ -7399,10 +7446,18 @@ packages: resolution: {integrity: sha512-v4sa+3xTweL1CLO2UP0p7tvIMH/Rq1X4KKOxd568mpe6LSLMQCnDHs4uv7m3ukpl3HvcN2JH6jiCS0SNRXKP/w==} engines: {node: '>=18.0.0'} + '@smithy/util-uri-escape@1.1.0': + resolution: {integrity: sha512-/jL/V1xdVRt5XppwiaEU8Etp5WHZj609n0xMTuehmCqdoOFbId1M+aEeDWZsQ+8JbEB/BJ6ynY2SlYmOaKtt8w==} + engines: {node: '>=14.0.0'} + '@smithy/util-uri-escape@4.2.2': resolution: {integrity: sha512-2kAStBlvq+lTXHyAZYfJRb/DfS3rsinLiwb+69SstC9Vb0s9vNWkRwpnj918Pfi85mzi42sOqdV72OLxWAISnw==} engines: {node: '>=18.0.0'} + '@smithy/util-utf8@1.1.0': + resolution: {integrity: sha512-p/MYV+JmqmPyjdgyN2UxAeYDj9cBqCjp0C/NsTWnnjoZUVqoeZ6IrW915L9CAKWVECgv9lVQGc4u/yz26/bI1A==} + engines: {node: '>=14.0.0'} + '@smithy/util-utf8@2.3.0': resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} engines: {node: '>=14.0.0'} @@ -8237,6 +8292,7 @@ packages: '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} + deprecated: Potential CWE-502 - Update to 1.3.1 or higher '@unrs/resolver-binding-android-arm-eabi@1.11.1': resolution: {integrity: sha512-ppLRUgHVaGRWUx0R0Ut06Mjo9gBaBkg3v/8AxusGLhsIotbBLuRk51rAzqLC8gq6NyyAojEXglNjzf6R948DNw==} @@ -14666,6 +14722,9 @@ packages: resolution: {integrity: sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==} engines: {node: '>=6'} + tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -15539,6 +15598,12 @@ snapshots: readable-stream: 3.6.2 simple-get: 4.0.1 + '@aws-crypto/crc32@3.0.0': + dependencies: + '@aws-crypto/util': 3.0.0 + '@aws-sdk/types': 3.973.6 + tslib: 1.14.1 + '@aws-crypto/crc32@5.2.0': dependencies: '@aws-crypto/util': 5.2.0 @@ -15580,6 +15645,12 @@ snapshots: dependencies: tslib: 2.8.1 + '@aws-crypto/util@3.0.0': + dependencies: + '@aws-sdk/types': 3.973.6 + '@aws-sdk/util-utf8-browser': 3.259.0 + tslib: 1.14.1 + '@aws-crypto/util@5.2.0': dependencies: '@aws-sdk/types': 3.973.6 @@ -15937,6 +16008,11 @@ snapshots: '@smithy/types': 4.13.1 tslib: 2.8.1 + '@aws-sdk/signature-v4@3.374.0': + dependencies: + '@smithy/signature-v4': 1.1.0 + tslib: 2.8.1 + '@aws-sdk/token-providers@3.1009.0': dependencies: '@aws-sdk/core': 3.973.20 @@ -15993,6 +16069,10 @@ snapshots: '@smithy/util-config-provider': 4.2.2 tslib: 2.8.1 + '@aws-sdk/util-utf8-browser@3.259.0': + dependencies: + tslib: 2.8.1 + '@aws-sdk/xml-builder@3.972.11': dependencies: '@smithy/types': 4.13.1 @@ -21558,6 +21638,13 @@ snapshots: '@smithy/url-parser': 4.2.12 tslib: 2.8.1 + '@smithy/eventstream-codec@1.1.0': + dependencies: + '@aws-crypto/crc32': 3.0.0 + '@smithy/types': 1.2.0 + '@smithy/util-hex-encoding': 1.1.0 + tslib: 2.8.1 + '@smithy/eventstream-codec@4.2.12': dependencies: '@aws-crypto/crc32': 5.2.0 @@ -21621,6 +21708,10 @@ snapshots: '@smithy/types': 4.13.1 tslib: 2.8.1 + '@smithy/is-array-buffer@1.1.0': + dependencies: + tslib: 2.8.1 + '@smithy/is-array-buffer@2.2.0': dependencies: tslib: 2.8.1 @@ -21721,6 +21812,17 @@ snapshots: '@smithy/types': 4.13.1 tslib: 2.8.1 + '@smithy/signature-v4@1.1.0': + dependencies: + '@smithy/eventstream-codec': 1.1.0 + '@smithy/is-array-buffer': 1.1.0 + '@smithy/types': 1.2.0 + '@smithy/util-hex-encoding': 1.1.0 + '@smithy/util-middleware': 1.1.0 + '@smithy/util-uri-escape': 1.1.0 + '@smithy/util-utf8': 1.1.0 + tslib: 2.8.1 + '@smithy/signature-v4@5.3.12': dependencies: '@smithy/is-array-buffer': 4.2.2 @@ -21742,6 +21844,10 @@ snapshots: '@smithy/util-stream': 4.5.19 tslib: 2.8.1 + '@smithy/types@1.2.0': + dependencies: + tslib: 2.8.1 + '@smithy/types@4.13.1': dependencies: tslib: 2.8.1 @@ -21766,6 +21872,11 @@ snapshots: dependencies: tslib: 2.8.1 + '@smithy/util-buffer-from@1.1.0': + dependencies: + '@smithy/is-array-buffer': 1.1.0 + tslib: 2.8.1 + '@smithy/util-buffer-from@2.2.0': dependencies: '@smithy/is-array-buffer': 2.2.0 @@ -21803,10 +21914,18 @@ snapshots: '@smithy/types': 4.13.1 tslib: 2.8.1 + '@smithy/util-hex-encoding@1.1.0': + dependencies: + tslib: 2.8.1 + '@smithy/util-hex-encoding@4.2.2': dependencies: tslib: 2.8.1 + '@smithy/util-middleware@1.1.0': + dependencies: + tslib: 2.8.1 + '@smithy/util-middleware@4.2.12': dependencies: '@smithy/types': 4.13.1 @@ -21829,10 +21948,19 @@ snapshots: '@smithy/util-utf8': 4.2.2 tslib: 2.8.1 + '@smithy/util-uri-escape@1.1.0': + dependencies: + tslib: 2.8.1 + '@smithy/util-uri-escape@4.2.2': dependencies: tslib: 2.8.1 + '@smithy/util-utf8@1.1.0': + dependencies: + '@smithy/util-buffer-from': 1.1.0 + tslib: 2.8.1 + '@smithy/util-utf8@2.3.0': dependencies: '@smithy/util-buffer-from': 2.2.0 @@ -31076,6 +31204,8 @@ snapshots: minimist: 1.2.8 strip-bom: 3.0.0 + tslib@1.14.1: {} + tslib@2.8.1: {} tsx@4.21.0: