From 61441cff90c7a9fd53d61c5734f5f78226c6c946 Mon Sep 17 00:00:00 2001 From: Hunter Blackwell <31895576+chunterb@users.noreply.github.com> Date: Sun, 7 Dec 2025 11:10:05 -0600 Subject: [PATCH 1/7] feat(ai-bedrock): add AWS Bedrock adapter --- packages/typescript/ai-bedrock/CHANGELOG.md | 1 + packages/typescript/ai-bedrock/README.md | 131 ++ packages/typescript/ai-bedrock/package.json | 55 + .../ai-bedrock/src/bedrock-adapter.ts | 1157 +++++++++++ packages/typescript/ai-bedrock/src/index.ts | 44 + .../ai-bedrock/src/message-types.ts | 155 ++ .../typescript/ai-bedrock/src/model-meta.ts | 1830 +++++++++++++++++ .../src/text/text-provider-options.ts | 180 ++ packages/typescript/ai-bedrock/tsconfig.json | 9 + packages/typescript/ai-bedrock/vite.config.ts | 36 + 10 files changed, 3598 insertions(+) create mode 100644 packages/typescript/ai-bedrock/CHANGELOG.md create mode 100644 packages/typescript/ai-bedrock/README.md create mode 100644 packages/typescript/ai-bedrock/package.json create mode 100644 packages/typescript/ai-bedrock/src/bedrock-adapter.ts create mode 100644 packages/typescript/ai-bedrock/src/index.ts create mode 100644 packages/typescript/ai-bedrock/src/message-types.ts create mode 100644 packages/typescript/ai-bedrock/src/model-meta.ts create mode 100644 packages/typescript/ai-bedrock/src/text/text-provider-options.ts create mode 100644 packages/typescript/ai-bedrock/tsconfig.json create mode 100644 packages/typescript/ai-bedrock/vite.config.ts diff --git a/packages/typescript/ai-bedrock/CHANGELOG.md b/packages/typescript/ai-bedrock/CHANGELOG.md new file mode 100644 index 00000000..e7de9d85 --- /dev/null +++ b/packages/typescript/ai-bedrock/CHANGELOG.md @@ -0,0 +1 @@ +# @tanstack/ai-bedrock diff --git a/packages/typescript/ai-bedrock/README.md b/packages/typescript/ai-bedrock/README.md new file mode 100644 index 00000000..77acf865 --- /dev/null +++ b/packages/typescript/ai-bedrock/README.md @@ -0,0 +1,131 @@ +
+ +
+ +
+ +
+ + + + + + + + + +
+ +
+ + semantic-release + + + Release + + + Follow @TanStack + +
+ +
+ +### [Become a Sponsor!](https://github.com/sponsors/tannerlinsley/) +
+ +# TanStack AI + +A powerful, type-safe AI SDK for building AI-powered applications. + +- Provider-agnostic adapters (OpenAI, Anthropic, Gemini, Ollama, etc.) +- **Multimodal content support** - Send images, audio, video, and documents +- Chat completion, streaming, and agent loop strategies +- Headless chat state management with adapters (SSE, HTTP stream, custom) +- Isomorphic type-safe tools with server/client execution +- **Enhanced integration with TanStack Start** - Share implementations between AI tools and server functions + +### Read the docs → + +## Bonus: TanStack Start Integration + +TanStack AI works with **any** framework (Next.js, Express, Remix, etc.). + +**With TanStack Start**, you get a bonus: share implementations between AI tools and server functions with `createServerFnTool`: + +```typescript +import { createServerFnTool } from '@tanstack/ai-react' + +// Define once, get AI tool AND server function (TanStack Start only) +const getProducts = createServerFnTool({ + name: 'getProducts', + inputSchema: z.object({ query: z.string() }), + execute: async ({ query }) => db.products.search(query), +}) + +// Use in AI chat +chat({ tools: [getProducts.server] }) + +// Call directly from components (no API endpoint needed!) +const products = await getProducts.serverFn({ query: 'laptop' }) +``` + +No duplicate logic, full type safety, automatic validation. The `serverFn` feature requires TanStack Start. See [docs](https://tanstack.com/ai) for details. + +## Get Involved + +- We welcome issues and pull requests! +- Participate in [GitHub discussions](https://github.com/TanStack/ai/discussions) +- Chat with the community on [Discord](https://discord.com/invite/WrRKjPJ) +- See [CONTRIBUTING.md](./CONTRIBUTING.md) for setup instructions + +## Partners + + + + + + +
+ + + + + CodeRabbit + + + + + + + + Cloudflare + + +
+ +
+AI & you? +

+We're looking for TanStack AI Partners to join our mission! Partner with us to push the boundaries of TanStack AI and build amazing things together. +

+LET'S CHAT +
+ +## Explore the TanStack Ecosystem + +- TanStack Config – Tooling for JS/TS packages +- TanStack DB – Reactive sync client store +- TanStack Devtools – Unified devtools panel +- TanStack Form – Type‑safe form state +- TanStack Pacer – Debouncing, throttling, batching +- TanStack Query – Async state & caching +- TanStack Ranger – Range & slider primitives +- TanStack Router – Type‑safe routing, caching & URL state +- TanStack Start – Full‑stack SSR & streaming +- TanStack Store – Reactive data store +- TanStack Table – Headless datagrids +- TanStack Virtual – Virtualized rendering + +… and more at TanStack.com » + + diff --git a/packages/typescript/ai-bedrock/package.json b/packages/typescript/ai-bedrock/package.json new file mode 100644 index 00000000..c68416ab --- /dev/null +++ b/packages/typescript/ai-bedrock/package.json @@ -0,0 +1,55 @@ +{ + "name": "@tanstack/ai-bedrock", + "version": "0.0.1", + "description": "AWS Bedrock adapter for TanStack AI", + "author": "", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/TanStack/ai.git", + "directory": "packages/typescript/ai-bedrock" + }, + "type": "module", + "module": "./dist/esm/index.js", + "types": "./dist/esm/index.d.ts", + "exports": { + ".": { + "types": "./dist/esm/index.d.ts", + "import": "./dist/esm/index.js" + } + }, + "files": [ + "dist", + "src" + ], + "scripts": { + "build": "vite build", + "clean": "premove ./build ./dist", + "lint:fix": "eslint ./src --fix", + "test:build": "publint --strict", + "test:eslint": "eslint ./src", + "test:lib": "vitest --passWithNoTests", + "test:lib:dev": "pnpm test:lib --watch", + "test:types": "tsc" + }, + "keywords": [ + "ai", + "aws", + "bedrock", + "tanstack", + "adapter" + ], + "dependencies": { + "@smithy/eventstream-codec": "^4.2.5", + "@smithy/util-utf8": "^4.2.0", + "@tanstack/ai": "workspace:*", + "aws4fetch": "^1.0.20" + }, + "devDependencies": { + "@vitest/coverage-v8": "4.0.14", + "vite": "^7.2.4" + }, + "peerDependencies": { + "@tanstack/ai": "workspace:*" + } +} diff --git a/packages/typescript/ai-bedrock/src/bedrock-adapter.ts b/packages/typescript/ai-bedrock/src/bedrock-adapter.ts new file mode 100644 index 00000000..dd416f99 --- /dev/null +++ b/packages/typescript/ai-bedrock/src/bedrock-adapter.ts @@ -0,0 +1,1157 @@ +import { AwsV4Signer } from 'aws4fetch' +import { EventStreamCodec } from '@smithy/eventstream-codec' +import { fromUtf8, toUtf8 } from '@smithy/util-utf8' +import { BaseAdapter } from '@tanstack/ai' +import { + BEDROCK_EMBEDDING_MODELS, + BEDROCK_MODELS, +} from './model-meta' +import { convertToolsToProviderFormat } from './tools/tool-converter' +import type { + ChatOptions, + ContentPart, + EmbeddingOptions, + EmbeddingResult, + ModelMessage, + StreamChunk, + SummarizationOptions, + SummarizationResult, +} from '@tanstack/ai' +import type { + BedrockChatModelProviderOptionsByName, + BedrockModelInputModalitiesByName, +} from './model-meta' +import type { BedrockProviderOptions } from './text/text-provider-options' +import type { + BedrockDocumentFormat, + BedrockDocumentMetadata, + BedrockImageFormat, + BedrockImageMetadata, + BedrockMessageMetadataByModality, + BedrockVideoFormat, + BedrockVideoMetadata, +} from './message-types' + +/** + * AWS credentials returned by a credential provider + */ +export interface BedrockCredentials { + accessKeyId: string + secretAccessKey: string + sessionToken?: string +} + +interface BedrockTextBlock { + text: string +} + +interface BedrockImageBlock { + image: { + format: BedrockImageFormat + source: { bytes: string } | { s3Location: { uri: string; bucketOwner?: string } } + } +} + +interface BedrockVideoBlock { + video: { + format: BedrockVideoFormat + source: { bytes: string } | { s3Location: { uri: string; bucketOwner?: string } } + } +} + +interface BedrockDocumentBlock { + document: { + format: BedrockDocumentFormat + name: string + source: + | { bytes: string } + | { s3Location: { uri: string; bucketOwner?: string } } + | { text: string } + } +} + +interface BedrockToolUseBlock { + toolUse: { + toolUseId: string + name: string + input: Record + } +} + +interface BedrockToolResultBlock { + toolResult: { + toolUseId: string + content: Array + } +} + +type BedrockContentBlock = + | BedrockTextBlock + | BedrockImageBlock + | BedrockVideoBlock + | BedrockDocumentBlock + | BedrockToolUseBlock + | BedrockToolResultBlock + +interface BedrockMessage { + role: 'user' | 'assistant' + content: Array +} + +interface BedrockConverseInput { + messages: Array + system?: Array<{ text: string }> + inferenceConfig?: { + maxTokens?: number + temperature?: number + topP?: number + topK?: number + stopSequences?: Array + } + toolConfig?: { + tools?: Array<{ + toolSpec: { + name: string + description?: string + inputSchema: { json: Record } + } + }> + toolChoice?: { auto: object } | { any: object } | { tool: { name: string } } + } + additionalModelRequestFields?: Record + performanceConfig?: { + latency: 'standard' | 'optimized' + } + serviceTier?: { + type: 'priority' | 'default' | 'flex' | 'reserved' + } + requestMetadata?: Record +} + +interface BedrockStreamEvent { + messageStart?: { role: string } + contentBlockStart?: { + contentBlockIndex?: number + start?: { + toolUse?: { + toolUseId?: string + name?: string + } + } + } + contentBlockDelta?: { + contentBlockIndex?: number + delta?: { + text?: string + reasoningContent?: { text?: string } + toolUse?: { input?: string } + } + } + contentBlockStop?: { contentBlockIndex?: number } + messageStop?: { stopReason?: string } + metadata?: { + usage?: { + inputTokens?: number + outputTokens?: number + totalTokens?: number + cacheReadInputTokens?: number + cacheWriteInputTokens?: number + } + } + internalServerException?: { message?: string } + modelStreamErrorException?: { message?: string } + throttlingException?: { message?: string } + validationException?: { message?: string } +} + +/** + * Configuration options for the Bedrock adapter. + * + * Supports two authentication methods: + * 1. **API Key (Bearer Token)** - Recommended for simplicity + * 2. **AWS SigV4** - Traditional AWS authentication with access keys + * + * Authentication priority: + * 1. `apiKey` (or `AWS_BEARER_TOKEN_BEDROCK` env var) + * 2. `credentialProvider` function + * 3. `accessKeyId`/`secretAccessKey` (or env vars) + * + * @example API Key Authentication + * ```typescript + * const bedrock = createBedrock({ + * apiKey: 'your-bedrock-api-key', + * region: 'us-east-1' + * }); + * ``` + * + * @example SigV4 Authentication + * ```typescript + * const bedrock = createBedrock({ + * accessKeyId: 'AKIAIOSFODNN7EXAMPLE', + * secretAccessKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY', + * region: 'us-east-1' + * }); + * ``` + * + * @example Credential Provider (for IAM roles, STS) + * ```typescript + * const bedrock = createBedrock({ + * credentialProvider: async () => ({ + * accessKeyId: 'temp-access-key', + * secretAccessKey: 'temp-secret-key', + * sessionToken: 'session-token' + * }), + * region: 'us-east-1' + * }); + * ``` + */ +export interface BedrockConfig { + /** + * AWS region for Bedrock service. + * Used to construct the endpoint URL. + * + * If not provided, defaults to: + * 1. `AWS_REGION` environment variable + * 2. `AWS_DEFAULT_REGION` environment variable + * 3. `'us-east-1'` as final fallback + */ + region?: string + + /** + * Amazon Bedrock API key for Bearer token authentication. + * This is the recommended authentication method for simplicity. + * + * If not provided, checks `AWS_BEARER_TOKEN_BEDROCK` environment variable. + * + * Note: API keys cannot be used with: + * - Agents for Amazon Bedrock APIs + * - Data Automation APIs + * - Bidirectional streaming (Nova Sonic) + * + * @see https://docs.aws.amazon.com/bedrock/latest/userguide/api-keys.html + */ + apiKey?: string + + /** + * AWS Access Key ID for SigV4 authentication. + * Must be provided together with `secretAccessKey`. + * + * If not provided, checks `AWS_ACCESS_KEY_ID` environment variable. + */ + accessKeyId?: string + + /** + * AWS Secret Access Key for SigV4 authentication. + * Must be provided together with `accessKeyId`. + * + * If not provided, checks `AWS_SECRET_ACCESS_KEY` environment variable. + */ + secretAccessKey?: string + + /** + * AWS Session Token for temporary credentials (SigV4). + * Optional, used with temporary credentials from STS. + * + * If not provided, checks `AWS_SESSION_TOKEN` environment variable. + */ + sessionToken?: string + + /** + * Async function that returns AWS credentials dynamically. + * Useful for IAM roles, EC2 instance profiles, or STS assume role. + * + * Takes precedence over static `accessKeyId`/`secretAccessKey` if provided. + * + * @example + * ```typescript + * credentialProvider: async () => { + * const sts = new STSClient({}); + * const { Credentials } = await sts.send(new AssumeRoleCommand({...})); + * return { + * accessKeyId: Credentials.AccessKeyId, + * secretAccessKey: Credentials.SecretAccessKey, + * sessionToken: Credentials.SessionToken + * }; + * } + * ``` + */ + credentialProvider?: () => Promise + + /** + * Custom base URL for Bedrock API. + * If not provided, constructed from region: `https://bedrock-runtime.{region}.amazonaws.com` + * + * Useful for: + * - Custom endpoints + * - VPC endpoints + * - Local development/testing + */ + baseURL?: string +} + +export class Bedrock extends BaseAdapter< + typeof BEDROCK_MODELS, + typeof BEDROCK_EMBEDDING_MODELS, + BedrockProviderOptions, + Record, + BedrockChatModelProviderOptionsByName, + BedrockModelInputModalitiesByName, + BedrockMessageMetadataByModality +> { + name = 'bedrock' as const + models = BEDROCK_MODELS + embeddingModels = BEDROCK_EMBEDDING_MODELS + + declare _modelProviderOptionsByName: BedrockChatModelProviderOptionsByName + declare _modelInputModalitiesByName: BedrockModelInputModalitiesByName + declare _messageMetadataByModality: BedrockMessageMetadataByModality + + private bedrockConfig: BedrockConfig + private _resolvedRegion: string + private _resolvedBaseURL: string + + constructor(config: BedrockConfig = {}) { + super({}) + this.bedrockConfig = config + this._resolvedRegion = this.resolveRegion() + this._resolvedBaseURL = this.resolveBaseURL() + this.validateAuthConfig() + } + + async *chatStream( + options: ChatOptions, + ): AsyncIterable { + const converseInput = this.mapCommonOptionsToBedrock(options) + const modelId = encodeURIComponent(options.model) + const url = `${this._resolvedBaseURL}/model/${modelId}/converse-stream` + + try { + const response = await this.fetchWithAuth(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + ...options.request?.headers, + }, + body: JSON.stringify(converseInput), + signal: options.request?.signal, + }) + + if (!response.ok) { + const errorText = await response.text() + console.error('[Bedrock Adapter] API error:', { + status: response.status, + statusText: response.statusText, + error: errorText, + }) + yield { + type: 'error', + id: this.generateId(), + model: options.model, + timestamp: Date.now(), + error: { + message: `Bedrock API error (${response.status}): ${errorText}`, + code: String(response.status), + }, + } + return + } + + yield* this.processBedrockStream(response, options.model) + } catch (error) { + console.error('[Bedrock Adapter] Error in chatStream:', { + message: error instanceof Error ? error.message : String(error), + error, + }) + yield { + type: 'error', + id: this.generateId(), + model: options.model, + timestamp: Date.now(), + error: { + message: + error instanceof Error + ? error.message + : 'An unknown error occurred during chat stream', + }, + } + } + } + + async summarize(options: SummarizationOptions): Promise { + const prompt = this.buildSummarizationPrompt(options) + const modelId = encodeURIComponent(options.model) + const url = `${this._resolvedBaseURL}/model/${modelId}/converse` + + const converseInput: BedrockConverseInput = { + messages: [ + { + role: 'user', + content: [{ text: options.text }], + }, + ], + system: [{ text: prompt }], + inferenceConfig: { + maxTokens: options.maxLength || 500, + temperature: 0.7, + }, + } + + const response = await this.fetchWithAuth(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(converseInput), + }) + + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Bedrock API error (${response.status}): ${errorText}`) + } + + const result = (await response.json()) as { + output: { message: { content: Array<{ text?: string }> } } + usage: { inputTokens: number; outputTokens: number; totalTokens: number } + } + + const summary = result.output.message.content + .map((block) => block.text || '') + .join('') + + return { + id: this.generateId(), + model: options.model, + summary, + usage: { + promptTokens: result.usage.inputTokens, + completionTokens: result.usage.outputTokens, + totalTokens: result.usage.totalTokens, + }, + } + } + + async createEmbeddings(options: EmbeddingOptions): Promise { + const inputs = Array.isArray(options.input) + ? options.input + : [options.input] + const embeddings: Array> = [] + let totalInputTokens = 0 + + for (const inputText of inputs) { + const modelId = encodeURIComponent(options.model) + const url = `${this._resolvedBaseURL}/model/${modelId}/invoke` + + const body = { + inputText, + dimensions: options.dimensions, + normalize: true, + } + + const response = await this.fetchWithAuth(url, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(body), + }) + + if (!response.ok) { + const errorText = await response.text() + throw new Error(`Bedrock embedding error (${response.status}): ${errorText}`) + } + + const result = (await response.json()) as { + embedding: Array + inputTextTokenCount: number + } + + embeddings.push(result.embedding) + totalInputTokens += result.inputTextTokenCount + } + + return { + id: this.generateId(), + model: options.model, + embeddings, + usage: { + promptTokens: totalInputTokens, + totalTokens: totalInputTokens, + }, + } + } + + private getEnv(): Record | undefined { + if (typeof globalThis !== 'undefined') { + const win = (globalThis as Record).window as + | { env?: Record } + | undefined + if (win?.env) { + return win.env + } + } + if (typeof process !== 'undefined') { + return process.env + } + return undefined + } + + private resolveRegion(): string { + if (this.bedrockConfig.region) { + return this.bedrockConfig.region + } + const env = this.getEnv() + return env?.AWS_REGION || env?.AWS_DEFAULT_REGION || 'us-east-1' + } + + private resolveBaseURL(): string { + if (this.bedrockConfig.baseURL) { + return this.bedrockConfig.baseURL + } + return `https://bedrock-runtime.${this._resolvedRegion}.amazonaws.com` + } + + private validateAuthConfig(): void { + const env = this.getEnv() + + const hasApiKey = + this.bedrockConfig.apiKey || env?.AWS_BEARER_TOKEN_BEDROCK + const hasCredentialProvider = !!this.bedrockConfig.credentialProvider + const hasAccessKey = + this.bedrockConfig.accessKeyId ?? env?.AWS_ACCESS_KEY_ID + const hasSecretKey = + this.bedrockConfig.secretAccessKey ?? env?.AWS_SECRET_ACCESS_KEY + const hasSigV4Credentials = hasAccessKey && hasSecretKey + + if (hasApiKey) { + const apiKey = this.bedrockConfig.apiKey ?? env?.AWS_BEARER_TOKEN_BEDROCK + if (apiKey && apiKey.trim() === '') { + throw new Error( + 'Bedrock: Invalid API key. API key cannot be empty or whitespace.\n' + + 'Provide a valid API key via:\n' + + ' - config.apiKey\n' + + ' - AWS_BEARER_TOKEN_BEDROCK environment variable' + ) + } + return + } + + if (!hasCredentialProvider && !hasSigV4Credentials) { + throw new Error( + 'Bedrock: No authentication credentials provided.\n' + + 'Provide authentication via one of:\n' + + ' 1. config.apiKey or AWS_BEARER_TOKEN_BEDROCK (API key)\n' + + ' 2. config.credentialProvider (dynamic credentials)\n' + + ' 3. config.accessKeyId + config.secretAccessKey (static credentials)\n' + + ' 4. AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY (environment variables)\n' + + ' 5. Mix of config and environment variables (e.g., config.accessKeyId + AWS_SECRET_ACCESS_KEY)' + ) + } + } + + private async fetchWithAuth( + url: string, + init: RequestInit, + ): Promise { + const env = this.getEnv() + const apiKey = this.bedrockConfig.apiKey ?? env?.AWS_BEARER_TOKEN_BEDROCK + + if (apiKey) { + const headers = new Headers(init.headers) + headers.set('Authorization', `Bearer ${apiKey}`) + return fetch(url, { ...init, headers }) + } + + const credentials = this.bedrockConfig.credentialProvider + ? await this.bedrockConfig.credentialProvider() + : { + accessKeyId: + this.bedrockConfig.accessKeyId ?? env?.AWS_ACCESS_KEY_ID ?? '', + secretAccessKey: + this.bedrockConfig.secretAccessKey ?? + env?.AWS_SECRET_ACCESS_KEY ?? + '', + sessionToken: + this.bedrockConfig.sessionToken ?? env?.AWS_SESSION_TOKEN, + } + + const signedRequest = await this.signRequest(url, init, credentials) + return fetch(url, signedRequest) + } + + private async signRequest( + url: string, + init: RequestInit, + credentials: BedrockCredentials, + ): Promise { + const headers = new Headers(init.headers) + headers.set('host', new URL(url).host) + + const body = + typeof init.body === 'string' ? init.body : JSON.stringify(init.body) + + const signer = new AwsV4Signer({ + url, + method: 'POST', + headers: Object.entries(Object.fromEntries(headers.entries())), + body, + region: this._resolvedRegion, + accessKeyId: credentials.accessKeyId, + secretAccessKey: credentials.secretAccessKey, + sessionToken: credentials.sessionToken, + service: 'bedrock', + }) + + const signed = await signer.sign() + return { ...init, headers: signed.headers, body } + } + + private mapCommonOptionsToBedrock( + options: ChatOptions, + ): BedrockConverseInput { + const { messages } = this.formatMessages(options.messages) + const providerOptions = options.providerOptions + + const inferenceConfig: BedrockConverseInput['inferenceConfig'] = {} + if (options.options?.maxTokens != null) { + inferenceConfig.maxTokens = options.options.maxTokens + } + if (options.options?.temperature != null) { + inferenceConfig.temperature = Math.min( + 1, + Math.max(0, options.options.temperature), + ) + } + if (options.options?.topP != null) { + inferenceConfig.topP = options.options.topP + } + if (providerOptions?.topK != null) { + inferenceConfig.topK = providerOptions.topK + } + if (providerOptions?.stopSequences != null) { + inferenceConfig.stopSequences = providerOptions.stopSequences + } + + const systemMessages: Array<{ text: string }> = [] + if (options.systemPrompts?.length) { + systemMessages.push({ text: options.systemPrompts.join('\n') }) + } + + const converseInput: BedrockConverseInput = { + messages, + ...(systemMessages.length > 0 && { system: systemMessages }), + ...(Object.keys(inferenceConfig).length > 0 && { inferenceConfig }), + } + + if (options.tools?.length) { + const bedrockTools = convertToolsToProviderFormat( + options.tools, + options.model, + ) + converseInput.toolConfig = { + tools: bedrockTools, + } + + if (providerOptions?.toolChoice) { + converseInput.toolConfig.toolChoice = providerOptions.toolChoice + } + } + + if (providerOptions?.additionalModelRequestFields) { + converseInput.additionalModelRequestFields = + providerOptions.additionalModelRequestFields + } + + if (providerOptions?.reasoningConfig) { + const reasoningConfig = providerOptions.reasoningConfig + converseInput.additionalModelRequestFields = { + ...converseInput.additionalModelRequestFields, + thinking: { + type: reasoningConfig.type, + ...(reasoningConfig.budgetTokens != null && { + budget_tokens: reasoningConfig.budgetTokens, + }), + }, + } + } + + if (providerOptions?.performanceConfig) { + converseInput.performanceConfig = providerOptions.performanceConfig + } + + if (providerOptions?.serviceTier) { + converseInput.serviceTier = providerOptions.serviceTier + } + + if (providerOptions?.requestMetadata) { + converseInput.requestMetadata = providerOptions.requestMetadata + } + + return converseInput + } + + private formatMessages(messages: Array): { + messages: Array + } { + const bedrockMessages: Array = [] + + for (const message of messages) { + if (message.role === 'tool' && message.toolCallId) { + const lastMessage = bedrockMessages[bedrockMessages.length - 1] + const toolResultBlock: BedrockToolResultBlock = { + toolResult: { + toolUseId: message.toolCallId, + content: [ + { + text: + typeof message.content === 'string' + ? message.content + : JSON.stringify(message.content), + }, + ], + }, + } + + if (lastMessage?.role === 'user') { + lastMessage.content.push(toolResultBlock) + } else { + bedrockMessages.push({ + role: 'user', + content: [toolResultBlock], + }) + } + continue + } + + const bedrockContent: Array = [] + + if (Array.isArray(message.content)) { + for (const part of message.content) { + bedrockContent.push(this.convertContentPartToBedrock(part)) + } + } else if (message.content) { + bedrockContent.push({ text: message.content }) + } + + if (message.role === 'assistant' && message.toolCalls?.length) { + for (const toolCall of message.toolCalls) { + let parsedInput: Record = {} + try { + parsedInput = toolCall.function.arguments + ? JSON.parse(toolCall.function.arguments) + : {} + } catch { + parsedInput = {} + } + bedrockContent.push({ + toolUse: { + toolUseId: toolCall.id, + name: toolCall.function.name, + input: parsedInput, + }, + }) + } + } + + if (bedrockContent.length > 0) { + bedrockMessages.push({ + role: message.role === 'assistant' ? 'assistant' : 'user', + content: bedrockContent, + }) + } + } + + return { messages: bedrockMessages } + } + + private convertContentPartToBedrock(part: ContentPart): BedrockContentBlock { + switch (part.type) { + case 'text': + return { text: part.content } + case 'image': { + const metadata = part.metadata as BedrockImageMetadata | undefined + const source = metadata?.s3Location + ? { s3Location: metadata.s3Location } + : { bytes: part.source.value } + return { + image: { + format: metadata?.format ?? 'jpeg', + source, + }, + } + } + case 'video': { + const metadata = part.metadata as BedrockVideoMetadata | undefined + const source = metadata?.s3Location + ? { s3Location: metadata.s3Location } + : { bytes: part.source.value } + return { + video: { + format: metadata?.format ?? 'mp4', + source, + }, + } + } + case 'document': { + const metadata = part.metadata as BedrockDocumentMetadata | undefined + const source = metadata?.s3Location + ? { s3Location: metadata.s3Location } + : { bytes: part.source.value } + return { + document: { + format: metadata?.format ?? 'pdf', + name: metadata?.name ?? `document-${Date.now()}`, + source, + }, + } + } + case 'audio': + throw new Error( + 'Bedrock Converse API does not support audio input. Use Bedrock Data Automation for audio processing.', + ) + default: { + const _exhaustiveCheck: never = part + throw new Error( + `Unsupported content part type: ${(_exhaustiveCheck as ContentPart).type}`, + ) + } + } + } + + private async *processBedrockStream( + response: Response, + model: string, + ): AsyncIterable { + const timestamp = Date.now() + let accumulatedContent = '' + let accumulatedThinking = '' + const toolCallMap = new Map< + number, + { id: string; name: string; input: string } + >() + let currentBlockIndex = -1 + let pendingFinishReason: + | 'stop' + | 'tool_calls' + | 'length' + | 'content_filter' + | null = null + + const reader = response.body?.getReader() + if (!reader) { + yield { + type: 'error', + id: this.generateId(), + model, + timestamp, + error: { message: 'No response body' }, + } + return + } + + const codec = new EventStreamCodec(toUtf8, fromUtf8) + let buffer = new Uint8Array(0) + const textDecoder = new TextDecoder() + + try { + for (;;) { + const { done, value } = await reader.read() + if (done) break + + const newBuffer = new Uint8Array(buffer.length + value.length) + newBuffer.set(buffer) + newBuffer.set(value, buffer.length) + buffer = newBuffer + + while (buffer.length >= 4) { + const totalLength = new DataView( + buffer.buffer, + buffer.byteOffset, + buffer.byteLength, + ).getUint32(0, false) + + if (buffer.length < totalLength) break + + try { + const subView = buffer.subarray(0, totalLength) + const decoded = codec.decode(subView) + buffer = buffer.slice(totalLength) + + if (decoded.headers[':message-type']?.value === 'event') { + const eventType = decoded.headers[':event-type']?.value as string + const data = JSON.parse(textDecoder.decode(decoded.body)) + delete data.p + + const event = { [eventType]: data } as BedrockStreamEvent + + if (event.messageStart) { + continue + } + + if (event.contentBlockStart) { + currentBlockIndex = + event.contentBlockStart.contentBlockIndex ?? 0 + if (event.contentBlockStart.start?.toolUse) { + const toolUse = event.contentBlockStart.start.toolUse + toolCallMap.set(currentBlockIndex, { + id: toolUse.toolUseId || this.generateId(), + name: toolUse.name || '', + input: '', + }) + } + } + + if (event.contentBlockDelta?.delta) { + const delta = event.contentBlockDelta.delta + + if (delta.text) { + accumulatedContent += delta.text + yield { + type: 'content', + id: this.generateId(), + model, + timestamp, + delta: delta.text, + content: accumulatedContent, + role: 'assistant', + } + } + + if (delta.reasoningContent?.text) { + accumulatedThinking += delta.reasoningContent.text + yield { + type: 'thinking', + id: this.generateId(), + model, + timestamp, + delta: delta.reasoningContent.text, + content: accumulatedThinking, + } + } + + if (delta.toolUse?.input) { + const existing = toolCallMap.get(currentBlockIndex) + if (existing) { + existing.input += delta.toolUse.input + } + } + } + + if (event.contentBlockStop) { + const blockIndex = + event.contentBlockStop.contentBlockIndex ?? currentBlockIndex + const toolData = toolCallMap.get(blockIndex) + if (toolData) { + yield { + type: 'tool_call', + id: this.generateId(), + model, + timestamp, + toolCall: { + id: toolData.id, + type: 'function', + function: { + name: toolData.name, + arguments: toolData.input || '{}', + }, + }, + index: blockIndex, + } + } + } + + if (event.messageStop) { + const stopReason = event.messageStop.stopReason + let finishReason: 'stop' | 'tool_calls' | 'length' | 'content_filter' = + 'stop' + + if (stopReason === 'tool_use' || toolCallMap.size > 0) { + finishReason = 'tool_calls' + } else if ( + stopReason === 'max_tokens' || + stopReason === 'model_context_window_exceeded' + ) { + finishReason = 'length' + } else if ( + stopReason === 'content_filtered' || + stopReason === 'guardrail_intervened' + ) { + finishReason = 'content_filter' + } + + pendingFinishReason = finishReason + } + + if (event.metadata) { + const finishReason = pendingFinishReason ?? 'stop' + yield { + type: 'done', + id: this.generateId(), + model, + timestamp, + finishReason, + usage: event.metadata.usage + ? { + promptTokens: event.metadata.usage.inputTokens ?? 0, + completionTokens: event.metadata.usage.outputTokens ?? 0, + totalTokens: event.metadata.usage.totalTokens ?? 0, + } + : undefined, + } + pendingFinishReason = null + } + + if ( + event.internalServerException || + event.modelStreamErrorException || + event.throttlingException || + event.validationException + ) { + const errorObj = + event.internalServerException || + event.modelStreamErrorException || + event.throttlingException || + event.validationException + yield { + type: 'error', + id: this.generateId(), + model, + timestamp, + error: { + message: errorObj?.message || 'Bedrock stream error', + }, + } + } + } + } catch { + break + } + } + } + + if (pendingFinishReason !== null) { + yield { + type: 'done', + id: this.generateId(), + model, + timestamp, + finishReason: pendingFinishReason, + } + } + } finally { + reader.releaseLock() + } + } + + private buildSummarizationPrompt(options: SummarizationOptions): string { + let prompt = 'You are a professional summarizer. ' + + switch (options.style) { + case 'bullet-points': + prompt += 'Provide a summary in bullet point format. ' + break + case 'paragraph': + prompt += 'Provide a summary in paragraph format. ' + break + case 'concise': + prompt += 'Provide a very concise summary in 1-2 sentences. ' + break + default: + prompt += 'Provide a clear and concise summary. ' + } + + if (options.focus && options.focus.length > 0) { + prompt += `Focus on the following aspects: ${options.focus.join(', ')}. ` + } + + if (options.maxLength) { + prompt += `Keep the summary under ${options.maxLength} tokens. ` + } + + return prompt + } +} + +/** + * Creates a Bedrock adapter with the provided configuration. + * + * @param config - Bedrock configuration options + * @returns A configured Bedrock adapter instance + * + * @example API Key Authentication + * ```typescript + * const bedrockAdapter = createBedrock({ + * apiKey: 'your-bedrock-api-key', + * region: 'us-east-1' + * }); + * + * const ai = new AI({ + * adapters: { bedrock: bedrockAdapter } + * }); + * ``` + * + * @example SigV4 with Static Credentials + * ```typescript + * const bedrockAdapter = createBedrock({ + * accessKeyId: 'AKIAIOSFODNN7EXAMPLE', + * secretAccessKey: 'wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY', + * region: 'us-west-2' + * }); + * ``` + * + * @example SigV4 with Credential Provider + * ```typescript + * const bedrockAdapter = createBedrock({ + * credentialProvider: async () => ({ + * accessKeyId: await getAccessKey(), + * secretAccessKey: await getSecretKey(), + * sessionToken: await getSessionToken() + * }), + * region: 'eu-west-1' + * }); + * ``` + */ +export function createBedrock(config?: BedrockConfig): Bedrock { + return new Bedrock(config ?? {}) +} + +/** + * Creates a Bedrock adapter with automatic environment variable detection. + * + * This is an alias for `createBedrock()` that provides a cleaner API. + * Authentication is automatically detected from environment variables: + * + * **Authentication (checked in order):** + * 1. `AWS_BEARER_TOKEN_BEDROCK` - API key for Bearer token auth + * 2. `AWS_ACCESS_KEY_ID` + `AWS_SECRET_ACCESS_KEY` - SigV4 auth + * 3. `AWS_SESSION_TOKEN` - Optional session token for temporary credentials + * + * **Region:** + * - `AWS_REGION` or `AWS_DEFAULT_REGION` + * - Falls back to `'us-east-1'` if not set + * + * Environment variables are checked in: + * - `process.env` (Node.js) + * - `window.env` (Browser with injected env) + * + * @param config - Optional configuration to override environment defaults + * @returns Configured Bedrock adapter instance + * + * @example Basic Usage (relies on environment variables) + * ```typescript + * // Set AWS_BEARER_TOKEN_BEDROCK or AWS credentials in environment + * const ai = new AI({ + * adapters: { bedrock: bedrock() } + * }); + * ``` + * + * @example With Config Overrides + * ```typescript + * const ai = new AI({ + * adapters: { + * bedrock: bedrock({ + * region: 'eu-central-1', + * baseURL: 'https://custom-endpoint.example.com' + * }) + * } + * }); + * ``` + */ +export function bedrock(config?: BedrockConfig): Bedrock { + return createBedrock(config) +} diff --git a/packages/typescript/ai-bedrock/src/index.ts b/packages/typescript/ai-bedrock/src/index.ts new file mode 100644 index 00000000..35ce733e --- /dev/null +++ b/packages/typescript/ai-bedrock/src/index.ts @@ -0,0 +1,44 @@ +export { + bedrock, + Bedrock, + createBedrock, + type BedrockConfig, + type BedrockCredentials, +} from './bedrock-adapter' +export { + isAnthropicModel, + isInferenceProfileId, + toInferenceProfileId, + type InferenceProfileRegion, +} from './model-meta' +export type { + BedrockChatModelProviderOptionsByName, + BedrockModelInputModalitiesByName, +} from './model-meta' +export type { + BedrockAdditionalFieldsOptions, + BedrockAnthropicOptions, + BedrockAnthropicReasoningOptions, + BedrockBaseOptions, + BedrockPerformanceOptions, + BedrockProviderOptions, + BedrockReasoningEffortOptions, + BedrockRequestMetadataOptions, + BedrockServiceTierOptions, + BedrockToolChoiceOptions, +} from './text/text-provider-options' +export type { + BedrockAudioMetadata, + BedrockDocumentFormat, + BedrockDocumentMetadata, + BedrockImageFormat, + BedrockImageMetadata, + BedrockMessageMetadataByModality, + BedrockS3Location, + BedrockTextMetadata, + BedrockVideoFormat, + BedrockVideoMetadata, +} from './message-types' + +export { convertToolsToProviderFormat } from './tools/tool-converter' +export type { BedrockToolSpec } from './tools/custom-tool' diff --git a/packages/typescript/ai-bedrock/src/message-types.ts b/packages/typescript/ai-bedrock/src/message-types.ts new file mode 100644 index 00000000..078f75ba --- /dev/null +++ b/packages/typescript/ai-bedrock/src/message-types.ts @@ -0,0 +1,155 @@ +/** + * Bedrock-specific metadata types for multimodal content parts. + * These types extend the base ContentPart metadata with Bedrock-specific options. + * + * Bedrock supports various foundation models with different multimodal capabilities + * through the Converse API. + * + * @see https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html + * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Converse.html + */ + +/** + * Supported image formats for Bedrock. + * + * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ImageBlock.html + */ +export type BedrockImageFormat = 'jpeg' | 'png' | 'gif' | 'webp' + +/** + * Supported audio formats for Bedrock. + * Note: The Bedrock Converse API does not currently support audio input in ContentBlock. + */ +export type BedrockAudioFormat = never + +/** + * Supported video formats for Bedrock. + * + * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_VideoBlock.html + */ +export type BedrockVideoFormat = + | 'mkv' + | 'mov' + | 'mp4' + | 'webm' + | 'flv' + | 'mpeg' + | 'mpg' + | 'wmv' + | 'three_gp' + +/** + * Supported document formats for Bedrock. + * + * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_DocumentBlock.html + */ +export type BedrockDocumentFormat = + | 'pdf' + | 'csv' + | 'doc' + | 'docx' + | 'xls' + | 'xlsx' + | 'html' + | 'txt' + | 'md' + +/** + * S3 location for media content. + * Use this to reference files stored in Amazon S3 instead of inline base64 data. + * + * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_S3Location.html + */ +export interface BedrockS3Location { + /** + * S3 URI of the file (e.g., "s3://bucket-name/path/to/file.jpg") + */ + uri: string + /** + * AWS account ID of the bucket owner (required for cross-account access) + */ + bucketOwner?: string +} + +/** + * Metadata for Bedrock image content parts. + * + * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ImageBlock.html + */ +export interface BedrockImageMetadata { + /** + * The format of the image. + * Required for proper content processing. + */ + format?: BedrockImageFormat + /** + * S3 location for the image. When provided, the image will be loaded from S3 + * instead of using inline base64 data. This is more efficient for large files. + */ + s3Location?: BedrockS3Location +} + +/** + * Metadata for Bedrock audio content parts. + * Note: The Bedrock Converse API does not currently support audio input in ContentBlock. + */ +export interface BedrockAudioMetadata {} + +/** + * Metadata for Bedrock video content parts. + * + * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_VideoBlock.html + */ +export interface BedrockVideoMetadata { + /** + * The format of the video. + * Required for proper content processing. + */ + format?: BedrockVideoFormat + /** + * S3 location for the video. When provided, the video will be loaded from S3 + * instead of using inline base64 data. Recommended for video files. + */ + s3Location?: BedrockS3Location +} + +/** + * Metadata for Bedrock document content parts. + * + * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_DocumentBlock.html + */ +export interface BedrockDocumentMetadata { + /** + * The format of the document. + * Required for proper content processing. + */ + format?: BedrockDocumentFormat + /** + * S3 location for the document. When provided, the document will be loaded from S3 + * instead of using inline base64 data. + */ + s3Location?: BedrockS3Location + /** + * Optional name for the document (used for identification in responses). + * If not provided, a default name will be generated. + */ + name?: string +} + +/** + * Metadata for Bedrock text content parts. + * Currently no specific metadata options for text in Bedrock. + */ +export interface BedrockTextMetadata {} + +/** + * Map of modality types to their Bedrock-specific metadata types. + * Used for type inference when constructing multimodal messages. + */ +export interface BedrockMessageMetadataByModality { + text: BedrockTextMetadata + image: BedrockImageMetadata + audio: BedrockAudioMetadata + video: BedrockVideoMetadata + document: BedrockDocumentMetadata +} diff --git a/packages/typescript/ai-bedrock/src/model-meta.ts b/packages/typescript/ai-bedrock/src/model-meta.ts new file mode 100644 index 00000000..430969b4 --- /dev/null +++ b/packages/typescript/ai-bedrock/src/model-meta.ts @@ -0,0 +1,1830 @@ +/** + * Bedrock model metadata and provider options + * + * ## Inference Profiles (Cross-Region Inference) + * + * AWS Bedrock uses "inference profiles" to enable cross-region model invocation. + * For newer Claude models (Claude 3.5 Sonnet v2, Claude 3.7 Sonnet, Claude 4 series), + * **inference profiles are required** - direct model IDs will return an error: + * + * ``` + * "Invocation of model ID anthropic.claude-3-5-sonnet-20241022-v2:0 with on-demand + * throughput isn't supported. Retry your request with the ID or ARN of an inference + * profile that contains this model." + * ``` + * + * ### Model ID Formats + * + * | Format | Example | Use Case | + * |--------|---------|----------| + * | Direct | `anthropic.claude-3-haiku-20240307-v1:0` | Legacy models in single region | + * | US Profile | `us.anthropic.claude-3-5-sonnet-20241022-v2:0` | **Recommended** - US cross-region | + * | EU Profile | `eu.anthropic.claude-3-5-sonnet-20241022-v2:0` | EU cross-region (GDPR compliance) | + * + * ### Utilities + * + * Use the exported helper functions: + * - `toInferenceProfileId(modelId, region?)` - Convert to inference profile + * - `isInferenceProfileId(modelId)` - Check if already an inference profile + * - `isAnthropicModel(modelId)` - Check if Anthropic model (any format) + * + * @see https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html + * @see https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles.html + */ + +import type { + BedrockAnthropicOptions, + BedrockAnthropicReasoningOptions, + BedrockProviderOptions, + BedrockReasoningEffortOptions, +} from './text/text-provider-options' + +interface ModelMeta { + name: string + id: string + supports: { + input: Array<'text' | 'image' | 'audio' | 'video' | 'document'> + output: Array<'text' | 'image' | 'audio' | 'video' | 'embedding'> + reasoning?: boolean + tools?: boolean + streaming?: boolean + } + context_window?: number + max_output_tokens?: number + providerOptions?: TProviderOptions +} + +const NOVA_LITE = { + name: 'Nova Lite', + id: 'amazon.nova-lite-v1:0', + context_window: 300_000, + max_output_tokens: 5_000, + supports: { + input: ['text', 'image', 'video'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const NOVA_MICRO = { + name: 'Nova Micro', + id: 'amazon.nova-micro-v1:0', + context_window: 128_000, + max_output_tokens: 5_000, + supports: { + input: ['text'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const NOVA_PRO = { + name: 'Nova Pro', + id: 'amazon.nova-pro-v1:0', + context_window: 300_000, + max_output_tokens: 5_000, + supports: { + input: ['text', 'image', 'video', 'document'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_NOVA_PREMIER = { + name: 'Nova Premier', + id: 'us.amazon.nova-premier-v1:0', + context_window: 1_000_000, + max_output_tokens: 32_000, + supports: { + input: ['text', 'image', 'video', 'document'], + output: ['text'], + reasoning: true, + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_NOVA_PRO = { + name: 'Nova Pro (US)', + id: 'us.amazon.nova-pro-v1:0', + context_window: 300_000, + max_output_tokens: 5_000, + supports: { + input: ['text', 'image', 'video', 'document'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_NOVA_MICRO = { + name: 'Nova Micro (US)', + id: 'us.amazon.nova-micro-v1:0', + context_window: 128_000, + max_output_tokens: 5_000, + supports: { + input: ['text'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_NOVA_LITE = { + name: 'Nova Lite (US)', + id: 'us.amazon.nova-lite-v1:0', + context_window: 300_000, + max_output_tokens: 5_000, + supports: { + input: ['text', 'image', 'video'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_NOVA_2_LITE = { + name: 'Nova 2 Lite', + id: 'us.amazon.nova-2-lite-v1:0', + context_window: 1_000_000, + max_output_tokens: 32_000, + supports: { + input: ['text', 'image'], + output: ['text'], + reasoning: true, + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_NOVA_2_SONIC = { + name: 'Nova 2 Sonic', + id: 'us.amazon.nova-2-sonic-v1:0', + context_window: 1_000_000, + supports: { + input: ['audio', 'text'], + output: ['audio', 'text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const CLAUDE_3_HAIKU = { + name: 'Claude 3 Haiku', + id: 'anthropic.claude-3-haiku-20240307-v1:0', + context_window: 200_000, + max_output_tokens: 4_096, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const CLAUDE_3_SONNET = { + name: 'Claude 3 Sonnet', + id: 'anthropic.claude-3-sonnet-20240229-v1:0', + context_window: 200_000, + max_output_tokens: 4_096, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const CLAUDE_3_OPUS = { + name: 'Claude 3 Opus', + id: 'anthropic.claude-3-opus-20240229-v1:0', + context_window: 200_000, + max_output_tokens: 4_096, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const CLAUDE_3_5_HAIKU = { + name: 'Claude 3.5 Haiku', + id: 'anthropic.claude-3-5-haiku-20241022-v1:0', + context_window: 200_000, + max_output_tokens: 8_192, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const CLAUDE_3_5_SONNET = { + name: 'Claude 3.5 Sonnet', + id: 'anthropic.claude-3-5-sonnet-20240620-v1:0', + context_window: 200_000, + max_output_tokens: 8_192, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const CLAUDE_3_5_SONNET_V2 = { + name: 'Claude 3.5 Sonnet v2', + id: 'anthropic.claude-3-5-sonnet-20241022-v2:0', + context_window: 200_000, + max_output_tokens: 8_192, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const CLAUDE_3_7_SONNET = { + name: 'Claude 3.7 Sonnet', + id: 'anthropic.claude-3-7-sonnet-20250219-v1:0', + context_window: 200_000, + max_output_tokens: 64_000, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + reasoning: true, + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta< + BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions +> + +const CLAUDE_HAIKU_4_5 = { + name: 'Claude Haiku 4.5', + id: 'anthropic.claude-haiku-4-5-20251001-v1:0', + context_window: 200_000, + max_output_tokens: 64_000, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + reasoning: true, + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta< + BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions +> + +const CLAUDE_SONNET_4 = { + name: 'Claude Sonnet 4', + id: 'anthropic.claude-sonnet-4-20250514-v1:0', + context_window: 200_000, + max_output_tokens: 64_000, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + reasoning: true, + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta< + BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions +> + +const CLAUDE_SONNET_4_5 = { + name: 'Claude Sonnet 4.5', + id: 'anthropic.claude-sonnet-4-5-20250929-v1:0', + context_window: 200_000, + max_output_tokens: 64_000, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + reasoning: true, + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta< + BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions +> + +const CLAUDE_OPUS_4 = { + name: 'Claude Opus 4', + id: 'anthropic.claude-opus-4-20250514-v1:0', + context_window: 200_000, + max_output_tokens: 32_000, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + reasoning: true, + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta< + BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions +> + +const CLAUDE_OPUS_4_1 = { + name: 'Claude Opus 4.1', + id: 'anthropic.claude-opus-4-1-20250805-v1:0', + context_window: 200_000, + max_output_tokens: 64_000, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + reasoning: true, + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta< + BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions +> + +const US_CLAUDE_3_HAIKU = { + name: 'Claude 3 Haiku (US)', + id: 'us.anthropic.claude-3-haiku-20240307-v1:0', + context_window: 200_000, + max_output_tokens: 4_096, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_CLAUDE_3_SONNET = { + name: 'Claude 3 Sonnet (US)', + id: 'us.anthropic.claude-3-sonnet-20240229-v1:0', + context_window: 200_000, + max_output_tokens: 4_096, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_CLAUDE_3_OPUS = { + name: 'Claude 3 Opus (US)', + id: 'us.anthropic.claude-3-opus-20240229-v1:0', + context_window: 200_000, + max_output_tokens: 4_096, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_CLAUDE_3_5_HAIKU = { + name: 'Claude 3.5 Haiku (US)', + id: 'us.anthropic.claude-3-5-haiku-20241022-v1:0', + context_window: 200_000, + max_output_tokens: 8_192, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_CLAUDE_3_5_SONNET = { + name: 'Claude 3.5 Sonnet (US)', + id: 'us.anthropic.claude-3-5-sonnet-20240620-v1:0', + context_window: 200_000, + max_output_tokens: 8_192, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_CLAUDE_3_5_SONNET_V2 = { + name: 'Claude 3.5 Sonnet v2 (US)', + id: 'us.anthropic.claude-3-5-sonnet-20241022-v2:0', + context_window: 200_000, + max_output_tokens: 8_192, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_CLAUDE_3_7_SONNET = { + name: 'Claude 3.7 Sonnet (US)', + id: 'us.anthropic.claude-3-7-sonnet-20250219-v1:0', + context_window: 200_000, + max_output_tokens: 64_000, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + reasoning: true, + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta< + BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions +> + +const US_CLAUDE_SONNET_4 = { + name: 'Claude Sonnet 4 (US)', + id: 'us.anthropic.claude-sonnet-4-20250514-v1:0', + context_window: 200_000, + max_output_tokens: 64_000, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + reasoning: true, + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta< + BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions +> + +const US_CLAUDE_SONNET_4_5 = { + name: 'Claude Sonnet 4.5 (US)', + id: 'us.anthropic.claude-sonnet-4-5-20250929-v1:0', + context_window: 200_000, + max_output_tokens: 64_000, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + reasoning: true, + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta< + BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions +> + +const US_CLAUDE_OPUS_4 = { + name: 'Claude Opus 4 (US)', + id: 'us.anthropic.claude-opus-4-20250514-v1:0', + context_window: 200_000, + max_output_tokens: 32_000, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + reasoning: true, + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta< + BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions +> + +const US_CLAUDE_OPUS_4_1 = { + name: 'Claude Opus 4.1 (US)', + id: 'us.anthropic.claude-opus-4-1-20250805-v1:0', + context_window: 200_000, + max_output_tokens: 64_000, + supports: { + input: ['text', 'image', 'document'], + output: ['text'], + reasoning: true, + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta< + BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions +> + +const LLAMA_3_8B = { + name: 'Llama 3 8B Instruct', + id: 'meta.llama3-8b-instruct-v1:0', + context_window: 8_192, + max_output_tokens: 2_048, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const LLAMA_3_70B = { + name: 'Llama 3 70B Instruct', + id: 'meta.llama3-70b-instruct-v1:0', + context_window: 8_192, + max_output_tokens: 2_048, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const LLAMA_3_1_8B = { + name: 'Llama 3.1 8B Instruct', + id: 'meta.llama3-1-8b-instruct-v1:0', + context_window: 128_000, + max_output_tokens: 2_048, + supports: { + input: ['text'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const LLAMA_3_1_70B = { + name: 'Llama 3.1 70B Instruct', + id: 'meta.llama3-1-70b-instruct-v1:0', + context_window: 128_000, + max_output_tokens: 2_048, + supports: { + input: ['text'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const LLAMA_3_1_405B = { + name: 'Llama 3.1 405B Instruct', + id: 'meta.llama3-1-405b-instruct-v1:0', + context_window: 128_000, + max_output_tokens: 2_048, + supports: { + input: ['text'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const LLAMA_3_2_1B = { + name: 'Llama 3.2 1B Instruct', + id: 'meta.llama3-2-1b-instruct-v1:0', + context_window: 128_000, + max_output_tokens: 2_048, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const LLAMA_3_2_3B = { + name: 'Llama 3.2 3B Instruct', + id: 'meta.llama3-2-3b-instruct-v1:0', + context_window: 128_000, + max_output_tokens: 2_048, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const LLAMA_3_2_11B = { + name: 'Llama 3.2 11B Vision Instruct', + id: 'meta.llama3-2-11b-instruct-v1:0', + context_window: 128_000, + max_output_tokens: 2_048, + supports: { + input: ['text', 'image'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const LLAMA_3_2_90B = { + name: 'Llama 3.2 90B Vision Instruct', + id: 'meta.llama3-2-90b-instruct-v1:0', + context_window: 128_000, + max_output_tokens: 2_048, + supports: { + input: ['text', 'image'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const LLAMA_3_3_70B = { + name: 'Llama 3.3 70B Instruct', + id: 'meta.llama3-3-70b-instruct-v1:0', + context_window: 128_000, + max_output_tokens: 2_048, + supports: { + input: ['text'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const LLAMA_4_SCOUT = { + name: 'Llama 4 Scout 17B Instruct', + id: 'meta.llama4-scout-17b-instruct-v1:0', + context_window: 3_500_000, + max_output_tokens: 16_384, + supports: { + input: ['text', 'image'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const LLAMA_4_MAVERICK = { + name: 'Llama 4 Maverick 17B Instruct', + id: 'meta.llama4-maverick-17b-instruct-v1:0', + context_window: 1_000_000, + max_output_tokens: 16_384, + supports: { + input: ['text', 'image'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_LLAMA_3_1_8B = { + name: 'Llama 3.1 8B Instruct (US)', + id: 'us.meta.llama3-1-8b-instruct-v1:0', + context_window: 128_000, + max_output_tokens: 2_048, + supports: { + input: ['text'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_LLAMA_3_1_70B = { + name: 'Llama 3.1 70B Instruct (US)', + id: 'us.meta.llama3-1-70b-instruct-v1:0', + context_window: 128_000, + max_output_tokens: 2_048, + supports: { + input: ['text'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_LLAMA_3_2_1B = { + name: 'Llama 3.2 1B Instruct (US)', + id: 'us.meta.llama3-2-1b-instruct-v1:0', + context_window: 128_000, + max_output_tokens: 2_048, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const US_LLAMA_3_2_3B = { + name: 'Llama 3.2 3B Instruct (US)', + id: 'us.meta.llama3-2-3b-instruct-v1:0', + context_window: 128_000, + max_output_tokens: 2_048, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const US_LLAMA_3_2_11B = { + name: 'Llama 3.2 11B Vision Instruct (US)', + id: 'us.meta.llama3-2-11b-instruct-v1:0', + context_window: 128_000, + max_output_tokens: 2_048, + supports: { + input: ['text', 'image'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const US_LLAMA_3_2_90B = { + name: 'Llama 3.2 90B Vision Instruct (US)', + id: 'us.meta.llama3-2-90b-instruct-v1:0', + context_window: 128_000, + max_output_tokens: 2_048, + supports: { + input: ['text', 'image'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const US_LLAMA_3_3_70B = { + name: 'Llama 3.3 70B Instruct (US)', + id: 'us.meta.llama3-3-70b-instruct-v1:0', + context_window: 128_000, + max_output_tokens: 2_048, + supports: { + input: ['text'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_LLAMA_4_SCOUT = { + name: 'Llama 4 Scout 17B Instruct (US)', + id: 'us.meta.llama4-scout-17b-instruct-v1:0', + context_window: 3_500_000, + max_output_tokens: 16_384, + supports: { + input: ['text', 'image'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_LLAMA_4_MAVERICK = { + name: 'Llama 4 Maverick 17B Instruct (US)', + id: 'us.meta.llama4-maverick-17b-instruct-v1:0', + context_window: 1_000_000, + max_output_tokens: 16_384, + supports: { + input: ['text', 'image'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const MISTRAL_7B = { + name: 'Mistral 7B Instruct', + id: 'mistral.mistral-7b-instruct-v0:2', + context_window: 32_768, + max_output_tokens: 8_192, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const MIXTRAL_8X7B = { + name: 'Mixtral 8x7B Instruct', + id: 'mistral.mixtral-8x7b-instruct-v0:1', + context_window: 32_768, + max_output_tokens: 4_096, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const MISTRAL_LARGE_2402 = { + name: 'Mistral Large (24.02)', + id: 'mistral.mistral-large-2402-v1:0', + context_window: 32_768, + max_output_tokens: 8_192, + supports: { + input: ['text'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const MISTRAL_LARGE_2407 = { + name: 'Mistral Large (24.07)', + id: 'mistral.mistral-large-2407-v1:0', + context_window: 128_000, + max_output_tokens: 8_192, + supports: { + input: ['text'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const MISTRAL_SMALL_2402 = { + name: 'Mistral Small (24.02)', + id: 'mistral.mistral-small-2402-v1:0', + context_window: 32_768, + max_output_tokens: 8_192, + supports: { + input: ['text'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_PIXTRAL_LARGE = { + name: 'Pixtral Large (25.02)', + id: 'us.mistral.pixtral-large-2502-v1:0', + context_window: 128_000, + max_output_tokens: 8_192, + supports: { + input: ['text', 'image'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const MISTRAL_LARGE_3 = { + name: 'Mistral Large 3', + id: 'mistral.mistral-large-3-675b-instruct', + context_window: 128_000, + max_output_tokens: 8_192, + supports: { + input: ['text', 'image'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const MINISTRAL_3_3B = { + name: 'Ministral 3 3B', + id: 'mistral.ministral-3-3b-instruct', + context_window: 128_000, + max_output_tokens: 8_192, + supports: { + input: ['text', 'image'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const MINISTRAL_3_8B = { + name: 'Ministral 3 8B', + id: 'mistral.ministral-3-8b-instruct', + context_window: 128_000, + max_output_tokens: 8_192, + supports: { + input: ['text', 'image'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const MINISTRAL_3_14B = { + name: 'Ministral 3 14B', + id: 'mistral.ministral-3-14b-instruct', + context_window: 128_000, + max_output_tokens: 8_192, + supports: { + input: ['text', 'image'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const MAGISTRAL_SMALL = { + name: 'Magistral Small', + id: 'mistral.magistral-small-2509', + context_window: 128_000, + max_output_tokens: 8_192, + supports: { + input: ['text', 'image'], + output: ['text'], + reasoning: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const VOXTRAL_MINI = { + name: 'Voxtral Mini 3B', + id: 'mistral.voxtral-mini-3b-2507', + context_window: 32_768, + supports: { + input: ['audio', 'text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const VOXTRAL_SMALL = { + name: 'Voxtral Small 24B', + id: 'mistral.voxtral-small-24b-2507', + context_window: 32_768, + supports: { + input: ['audio', 'text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const TITAN_TEXT_LARGE = { + name: 'Titan Text Large', + id: 'amazon.titan-tg1-large', + context_window: 8_000, + max_output_tokens: 8_000, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const TITAN_TEXT_EXPRESS = { + name: 'Titan Text Express', + id: 'amazon.titan-text-express-v1', + context_window: 8_000, + max_output_tokens: 8_000, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const TITAN_TEXT_LITE = { + name: 'Titan Text Lite', + id: 'amazon.titan-text-lite-v1', + context_window: 4_000, + max_output_tokens: 4_000, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const COHERE_COMMAND_TEXT = { + name: 'Command Text', + id: 'cohere.command-text-v14', + context_window: 4_096, + max_output_tokens: 4_096, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const COHERE_COMMAND_LIGHT = { + name: 'Command Light', + id: 'cohere.command-light-text-v14', + context_window: 4_096, + max_output_tokens: 4_096, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const COHERE_COMMAND_R = { + name: 'Command R', + id: 'cohere.command-r-v1:0', + context_window: 128_000, + max_output_tokens: 4_096, + supports: { + input: ['text'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const COHERE_COMMAND_R_PLUS = { + name: 'Command R+', + id: 'cohere.command-r-plus-v1:0', + context_window: 128_000, + max_output_tokens: 4_096, + supports: { + input: ['text'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const DEEPSEEK_R1 = { + name: 'DeepSeek R1', + id: 'deepseek.r1-v1:0', + context_window: 64_000, + max_output_tokens: 8_192, + supports: { + input: ['text'], + output: ['text'], + reasoning: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const US_DEEPSEEK_R1 = { + name: 'DeepSeek R1 (US)', + id: 'us.deepseek.r1-v1:0', + context_window: 64_000, + max_output_tokens: 8_192, + supports: { + input: ['text'], + output: ['text'], + reasoning: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const DEEPSEEK_V3 = { + name: 'DeepSeek V3', + id: 'deepseek.v3-v1:0', + context_window: 64_000, + max_output_tokens: 8_192, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const AI21_JAMBA_LARGE = { + name: 'Jamba 1.5 Large', + id: 'ai21.jamba-1-5-large-v1:0', + context_window: 256_000, + max_output_tokens: 4_096, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const AI21_JAMBA_MINI = { + name: 'Jamba 1.5 Mini', + id: 'ai21.jamba-1-5-mini-v1:0', + context_window: 256_000, + max_output_tokens: 4_096, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const WRITER_PALMYRA_X4 = { + name: 'Palmyra X4', + id: 'writer.palmyra-x4-v1:0', + context_window: 128_000, + max_output_tokens: 8_192, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const WRITER_PALMYRA_X5 = { + name: 'Palmyra X5', + id: 'writer.palmyra-x5-v1:0', + context_window: 128_000, + max_output_tokens: 8_192, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const GEMMA_3_4B = { + name: 'Gemma 3 4B IT', + id: 'google.gemma-3-4b-it', + context_window: 32_768, + max_output_tokens: 8_192, + supports: { + input: ['text', 'image'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const GEMMA_3_12B = { + name: 'Gemma 3 12B IT', + id: 'google.gemma-3-12b-it', + context_window: 32_768, + max_output_tokens: 8_192, + supports: { + input: ['text', 'image'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const GEMMA_3_27B = { + name: 'Gemma 3 27B IT', + id: 'google.gemma-3-27b-it', + context_window: 32_768, + max_output_tokens: 8_192, + supports: { + input: ['text', 'image'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const NVIDIA_NEMOTRON_9B = { + name: 'NVIDIA Nemotron Nano 9B v2', + id: 'nvidia.nemotron-nano-9b-v2', + context_window: 32_768, + max_output_tokens: 8_192, + supports: { + input: ['text'], + output: ['text'], + reasoning: true, + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const NVIDIA_NEMOTRON_12B_VL = { + name: 'NVIDIA Nemotron Nano 12B v2 VL', + id: 'nvidia.nemotron-nano-12b-v2', + context_window: 32_768, + max_output_tokens: 8_192, + supports: { + input: ['text', 'image', 'video'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const MINIMAX_M2 = { + name: 'MiniMax M2', + id: 'minimax.minimax-m2', + context_window: 128_000, + max_output_tokens: 8_192, + supports: { + input: ['text'], + output: ['text'], + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const MOONSHOT_KIMI_K2 = { + name: 'Kimi K2 Thinking', + id: 'moonshot.kimi-k2-thinking', + context_window: 128_000, + max_output_tokens: 8_192, + supports: { + input: ['text'], + output: ['text'], + reasoning: true, + tools: true, + streaming: true, + }, +} as const satisfies ModelMeta + +const OPENAI_SAFEGUARD_20B = { + name: 'GPT OSS Safeguard 20B', + id: 'openai.gpt-oss-safeguard-20b', + context_window: 128_000, + max_output_tokens: 8_192, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const OPENAI_SAFEGUARD_120B = { + name: 'GPT OSS Safeguard 120B', + id: 'openai.gpt-oss-safeguard-120b', + context_window: 128_000, + max_output_tokens: 8_192, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const QWEN_3_NEXT_80B = { + name: 'Qwen3 Next 80B A3B Instruct', + id: 'qwen.qwen3-next-80b-a3b', + context_window: 128_000, + max_output_tokens: 8_192, + supports: { + input: ['text'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const QWEN_3_VL_235B = { + name: 'Qwen3 VL 235B A22B', + id: 'qwen.qwen3-vl-235b-a22b', + context_window: 128_000, + max_output_tokens: 8_192, + supports: { + input: ['text', 'image'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const TWELVELABS_PEGASUS = { + name: 'Pegasus v1.2', + id: 'twelvelabs.pegasus-v1.2:0', + context_window: 128_000, + supports: { + input: ['text', 'video'], + output: ['text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const LUMA_RAY_V2 = { + name: 'Ray v2', + id: 'luma.ray-v2:0', + supports: { + input: ['text'], + output: ['video'], + streaming: false, + }, +} as const satisfies ModelMeta + +const TITAN_EMBED_TEXT_V1 = { + name: 'Titan Embeddings G1 - Text', + id: 'amazon.titan-embed-text-v1', + context_window: 8_192, + supports: { + input: ['text'], + output: ['embedding'], + streaming: false, + }, +} as const satisfies ModelMeta + +const TITAN_EMBED_TEXT_V2 = { + name: 'Titan Text Embeddings V2', + id: 'amazon.titan-embed-text-v2:0', + context_window: 8_192, + supports: { + input: ['text'], + output: ['embedding'], + streaming: false, + }, +} as const satisfies ModelMeta + +const TITAN_EMBED_IMAGE = { + name: 'Titan Multimodal Embeddings G1', + id: 'amazon.titan-embed-image-v1', + context_window: 256, + supports: { + input: ['text', 'image'], + output: ['embedding'], + streaming: false, + }, +} as const satisfies ModelMeta + +const NOVA_MULTIMODAL_EMBED = { + name: 'Nova 2 Multimodal Embeddings', + id: 'amazon.nova-2-multimodal-embeddings-v1:0', + supports: { + input: ['text', 'image', 'audio', 'video'], + output: ['embedding'], + streaming: false, + }, +} as const satisfies ModelMeta + +const COHERE_EMBED_ENGLISH = { + name: 'Cohere Embed English v3', + id: 'cohere.embed-english-v3', + context_window: 512, + supports: { + input: ['text'], + output: ['embedding'], + streaming: false, + }, +} as const satisfies ModelMeta + +const COHERE_EMBED_MULTILINGUAL = { + name: 'Cohere Embed Multilingual v3', + id: 'cohere.embed-multilingual-v3', + context_window: 512, + supports: { + input: ['text'], + output: ['embedding'], + streaming: false, + }, +} as const satisfies ModelMeta + +const COHERE_EMBED_V4 = { + name: 'Cohere Embed v4', + id: 'cohere.embed-v4:0', + context_window: 128_000, + supports: { + input: ['text', 'image'], + output: ['embedding'], + streaming: false, + }, +} as const satisfies ModelMeta + +const TWELVELABS_MARENGO_EMBED = { + name: 'Marengo Embed v2.7', + id: 'twelvelabs.marengo-embed-2-7-v1:0', + supports: { + input: ['video'], + output: ['embedding'], + streaming: false, + }, +} as const satisfies ModelMeta + +/* const NOVA_CANVAS = { + name: 'Nova Canvas', + id: 'amazon.nova-canvas-v1:0', + supports: { + input: ['text', 'image'], + output: ['image'], + streaming: false, + }, +} as const satisfies ModelMeta + +const NOVA_REEL_V1_0 = { + name: 'Nova Reel', + id: 'amazon.nova-reel-v1:0', + supports: { + input: ['text', 'image'], + output: ['video'], + streaming: false, + }, +} as const satisfies ModelMeta + +const NOVA_REEL_V1_1 = { + name: 'Nova Reel', + id: 'amazon.nova-reel-v1:1', + supports: { + input: ['text', 'image'], + output: ['video'], + streaming: false, + }, +} as const satisfies ModelMeta + +const NOVA_SONIC = { + name: 'Nova Sonic', + id: 'amazon.nova-sonic-v1:0', + context_window: 300_000, + supports: { + input: ['audio'], + output: ['audio', 'text'], + streaming: true, + }, +} as const satisfies ModelMeta + +const RERANK_1_0 = { + name: 'Rerank 1.0', + id: 'amazon.rerank-v1:0', + supports: { + input: ['text'], + output: ['text'], + streaming: false, + }, +} as const satisfies ModelMeta */ + +export const BEDROCK_MODELS = [ + NOVA_LITE.id, + NOVA_MICRO.id, + NOVA_PRO.id, + US_NOVA_PREMIER.id, + US_NOVA_PRO.id, + US_NOVA_MICRO.id, + US_NOVA_LITE.id, + US_NOVA_2_LITE.id, + US_NOVA_2_SONIC.id, + CLAUDE_3_HAIKU.id, + CLAUDE_3_SONNET.id, + CLAUDE_3_OPUS.id, + CLAUDE_3_5_HAIKU.id, + CLAUDE_3_5_SONNET.id, + CLAUDE_3_5_SONNET_V2.id, + CLAUDE_3_7_SONNET.id, + CLAUDE_HAIKU_4_5.id, + CLAUDE_SONNET_4.id, + CLAUDE_SONNET_4_5.id, + CLAUDE_OPUS_4.id, + CLAUDE_OPUS_4_1.id, + US_CLAUDE_3_HAIKU.id, + US_CLAUDE_3_SONNET.id, + US_CLAUDE_3_OPUS.id, + US_CLAUDE_3_5_HAIKU.id, + US_CLAUDE_3_5_SONNET.id, + US_CLAUDE_3_5_SONNET_V2.id, + US_CLAUDE_3_7_SONNET.id, + US_CLAUDE_SONNET_4.id, + US_CLAUDE_SONNET_4_5.id, + US_CLAUDE_OPUS_4.id, + US_CLAUDE_OPUS_4_1.id, + LLAMA_3_8B.id, + LLAMA_3_70B.id, + LLAMA_3_1_8B.id, + LLAMA_3_1_70B.id, + LLAMA_3_1_405B.id, + LLAMA_3_2_1B.id, + LLAMA_3_2_3B.id, + LLAMA_3_2_11B.id, + LLAMA_3_2_90B.id, + LLAMA_3_3_70B.id, + LLAMA_4_SCOUT.id, + LLAMA_4_MAVERICK.id, + US_LLAMA_3_1_8B.id, + US_LLAMA_3_1_70B.id, + US_LLAMA_3_2_1B.id, + US_LLAMA_3_2_3B.id, + US_LLAMA_3_2_11B.id, + US_LLAMA_3_2_90B.id, + US_LLAMA_3_3_70B.id, + US_LLAMA_4_SCOUT.id, + US_LLAMA_4_MAVERICK.id, + MISTRAL_7B.id, + MIXTRAL_8X7B.id, + MISTRAL_LARGE_2402.id, + MISTRAL_LARGE_2407.id, + MISTRAL_SMALL_2402.id, + US_PIXTRAL_LARGE.id, + TITAN_TEXT_LARGE.id, + TITAN_TEXT_EXPRESS.id, + TITAN_TEXT_LITE.id, + COHERE_COMMAND_TEXT.id, + COHERE_COMMAND_LIGHT.id, + COHERE_COMMAND_R.id, + COHERE_COMMAND_R_PLUS.id, + DEEPSEEK_R1.id, + US_DEEPSEEK_R1.id, + DEEPSEEK_V3.id, + AI21_JAMBA_LARGE.id, + AI21_JAMBA_MINI.id, + WRITER_PALMYRA_X4.id, + WRITER_PALMYRA_X5.id, + TWELVELABS_PEGASUS.id, + LUMA_RAY_V2.id, + MISTRAL_LARGE_3.id, + MINISTRAL_3_3B.id, + MINISTRAL_3_8B.id, + MINISTRAL_3_14B.id, + MAGISTRAL_SMALL.id, + VOXTRAL_MINI.id, + VOXTRAL_SMALL.id, + GEMMA_3_4B.id, + GEMMA_3_12B.id, + GEMMA_3_27B.id, + NVIDIA_NEMOTRON_9B.id, + NVIDIA_NEMOTRON_12B_VL.id, + MINIMAX_M2.id, + MOONSHOT_KIMI_K2.id, + OPENAI_SAFEGUARD_20B.id, + OPENAI_SAFEGUARD_120B.id, + QWEN_3_NEXT_80B.id, + QWEN_3_VL_235B.id, +] as const + +export const BEDROCK_EMBEDDING_MODELS = [ + TITAN_EMBED_TEXT_V1.id, + TITAN_EMBED_TEXT_V2.id, + TITAN_EMBED_IMAGE.id, + NOVA_MULTIMODAL_EMBED.id, + COHERE_EMBED_ENGLISH.id, + COHERE_EMBED_MULTILINGUAL.id, + COHERE_EMBED_V4.id, + TWELVELABS_MARENGO_EMBED.id, +] as const + +/* const BEDROCK_IMAGE_MODELS = [ + NOVA_CANVAS.id, +] as const */ + +/* const BEDROCK_VIDEO_MODELS = [ + NOVA_REEL_V1_0.id, + NOVA_REEL_V1_1.id, +] as const */ + +/* const BEDROCK_RERANK_MODELS = [ + RERANK_1_0.id, +] as const */ + +/* const BEDROCK_SPEECH_MODELS = [ + NOVA_SONIC.id, +] as const */ + +/** + * Type-only map from Bedrock model name to its provider-specific options. + * Options vary by model capabilities (reasoning, Anthropic-specific features). + */ +export type BedrockChatModelProviderOptionsByName = { + [NOVA_LITE.id]: BedrockProviderOptions + [NOVA_MICRO.id]: BedrockProviderOptions + [NOVA_PRO.id]: BedrockProviderOptions + [US_NOVA_PREMIER.id]: BedrockProviderOptions & BedrockReasoningEffortOptions + [US_NOVA_PRO.id]: BedrockProviderOptions + [US_NOVA_MICRO.id]: BedrockProviderOptions + [US_NOVA_LITE.id]: BedrockProviderOptions + [US_NOVA_2_LITE.id]: BedrockProviderOptions & BedrockReasoningEffortOptions + [US_NOVA_2_SONIC.id]: BedrockProviderOptions + [CLAUDE_3_HAIKU.id]: BedrockProviderOptions & BedrockAnthropicOptions + [CLAUDE_3_SONNET.id]: BedrockProviderOptions & BedrockAnthropicOptions + [CLAUDE_3_OPUS.id]: BedrockProviderOptions & BedrockAnthropicOptions + [CLAUDE_3_5_HAIKU.id]: BedrockProviderOptions & BedrockAnthropicOptions + [CLAUDE_3_5_SONNET.id]: BedrockProviderOptions & BedrockAnthropicOptions + [CLAUDE_3_5_SONNET_V2.id]: BedrockProviderOptions & BedrockAnthropicOptions + [CLAUDE_3_7_SONNET.id]: BedrockProviderOptions & + BedrockAnthropicOptions & + BedrockAnthropicReasoningOptions + [CLAUDE_HAIKU_4_5.id]: BedrockProviderOptions & + BedrockAnthropicOptions & + BedrockAnthropicReasoningOptions + [CLAUDE_SONNET_4.id]: BedrockProviderOptions & + BedrockAnthropicOptions & + BedrockAnthropicReasoningOptions + [CLAUDE_SONNET_4_5.id]: BedrockProviderOptions & + BedrockAnthropicOptions & + BedrockAnthropicReasoningOptions + [CLAUDE_OPUS_4.id]: BedrockProviderOptions & + BedrockAnthropicOptions & + BedrockAnthropicReasoningOptions + [CLAUDE_OPUS_4_1.id]: BedrockProviderOptions & + BedrockAnthropicOptions & + BedrockAnthropicReasoningOptions + [US_CLAUDE_3_HAIKU.id]: BedrockProviderOptions & BedrockAnthropicOptions + [US_CLAUDE_3_SONNET.id]: BedrockProviderOptions & BedrockAnthropicOptions + [US_CLAUDE_3_OPUS.id]: BedrockProviderOptions & BedrockAnthropicOptions + [US_CLAUDE_3_5_HAIKU.id]: BedrockProviderOptions & BedrockAnthropicOptions + [US_CLAUDE_3_5_SONNET.id]: BedrockProviderOptions & BedrockAnthropicOptions + [US_CLAUDE_3_5_SONNET_V2.id]: BedrockProviderOptions & BedrockAnthropicOptions + [US_CLAUDE_3_7_SONNET.id]: BedrockProviderOptions & + BedrockAnthropicOptions & + BedrockAnthropicReasoningOptions + [US_CLAUDE_SONNET_4.id]: BedrockProviderOptions & + BedrockAnthropicOptions & + BedrockAnthropicReasoningOptions + [US_CLAUDE_SONNET_4_5.id]: BedrockProviderOptions & + BedrockAnthropicOptions & + BedrockAnthropicReasoningOptions + [US_CLAUDE_OPUS_4.id]: BedrockProviderOptions & + BedrockAnthropicOptions & + BedrockAnthropicReasoningOptions + [US_CLAUDE_OPUS_4_1.id]: BedrockProviderOptions & + BedrockAnthropicOptions & + BedrockAnthropicReasoningOptions + [LLAMA_3_8B.id]: BedrockProviderOptions + [LLAMA_3_70B.id]: BedrockProviderOptions + [LLAMA_3_1_8B.id]: BedrockProviderOptions + [LLAMA_3_1_70B.id]: BedrockProviderOptions + [LLAMA_3_1_405B.id]: BedrockProviderOptions + [LLAMA_3_2_1B.id]: BedrockProviderOptions + [LLAMA_3_2_3B.id]: BedrockProviderOptions + [LLAMA_3_2_11B.id]: BedrockProviderOptions + [LLAMA_3_2_90B.id]: BedrockProviderOptions + [LLAMA_3_3_70B.id]: BedrockProviderOptions + [LLAMA_4_SCOUT.id]: BedrockProviderOptions + [LLAMA_4_MAVERICK.id]: BedrockProviderOptions + [US_LLAMA_3_1_8B.id]: BedrockProviderOptions + [US_LLAMA_3_1_70B.id]: BedrockProviderOptions + [US_LLAMA_3_2_1B.id]: BedrockProviderOptions + [US_LLAMA_3_2_3B.id]: BedrockProviderOptions + [US_LLAMA_3_2_11B.id]: BedrockProviderOptions + [US_LLAMA_3_2_90B.id]: BedrockProviderOptions + [US_LLAMA_3_3_70B.id]: BedrockProviderOptions + [US_LLAMA_4_SCOUT.id]: BedrockProviderOptions + [US_LLAMA_4_MAVERICK.id]: BedrockProviderOptions + [MISTRAL_7B.id]: BedrockProviderOptions + [MIXTRAL_8X7B.id]: BedrockProviderOptions + [MISTRAL_LARGE_2402.id]: BedrockProviderOptions + [MISTRAL_LARGE_2407.id]: BedrockProviderOptions + [MISTRAL_SMALL_2402.id]: BedrockProviderOptions + [US_PIXTRAL_LARGE.id]: BedrockProviderOptions + [TITAN_TEXT_LARGE.id]: BedrockProviderOptions + [TITAN_TEXT_EXPRESS.id]: BedrockProviderOptions + [TITAN_TEXT_LITE.id]: BedrockProviderOptions + [COHERE_COMMAND_TEXT.id]: BedrockProviderOptions + [COHERE_COMMAND_LIGHT.id]: BedrockProviderOptions + [COHERE_COMMAND_R.id]: BedrockProviderOptions + [COHERE_COMMAND_R_PLUS.id]: BedrockProviderOptions + [DEEPSEEK_R1.id]: BedrockProviderOptions & BedrockReasoningEffortOptions + [US_DEEPSEEK_R1.id]: BedrockProviderOptions & BedrockReasoningEffortOptions + [DEEPSEEK_V3.id]: BedrockProviderOptions + [AI21_JAMBA_LARGE.id]: BedrockProviderOptions + [AI21_JAMBA_MINI.id]: BedrockProviderOptions + [WRITER_PALMYRA_X4.id]: BedrockProviderOptions + [WRITER_PALMYRA_X5.id]: BedrockProviderOptions + [TWELVELABS_PEGASUS.id]: BedrockProviderOptions + [LUMA_RAY_V2.id]: BedrockProviderOptions + [MISTRAL_LARGE_3.id]: BedrockProviderOptions + [MINISTRAL_3_3B.id]: BedrockProviderOptions + [MINISTRAL_3_8B.id]: BedrockProviderOptions + [MINISTRAL_3_14B.id]: BedrockProviderOptions + [MAGISTRAL_SMALL.id]: BedrockProviderOptions & BedrockReasoningEffortOptions + [VOXTRAL_MINI.id]: BedrockProviderOptions + [VOXTRAL_SMALL.id]: BedrockProviderOptions + [GEMMA_3_4B.id]: BedrockProviderOptions + [GEMMA_3_12B.id]: BedrockProviderOptions + [GEMMA_3_27B.id]: BedrockProviderOptions + [NVIDIA_NEMOTRON_9B.id]: BedrockProviderOptions & BedrockReasoningEffortOptions + [NVIDIA_NEMOTRON_12B_VL.id]: BedrockProviderOptions + [MINIMAX_M2.id]: BedrockProviderOptions + [MOONSHOT_KIMI_K2.id]: BedrockProviderOptions & BedrockReasoningEffortOptions + [OPENAI_SAFEGUARD_20B.id]: BedrockProviderOptions + [OPENAI_SAFEGUARD_120B.id]: BedrockProviderOptions + [QWEN_3_NEXT_80B.id]: BedrockProviderOptions + [QWEN_3_VL_235B.id]: BedrockProviderOptions +} + +/** + * Type-only map from Bedrock model name to its supported input modalities. + * Used by the core AI types to constrain ContentPart types based on the selected model. + * + * @see https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html + */ +export type BedrockModelInputModalitiesByName = { + [NOVA_LITE.id]: typeof NOVA_LITE.supports.input + [NOVA_MICRO.id]: typeof NOVA_MICRO.supports.input + [NOVA_PRO.id]: typeof NOVA_PRO.supports.input + [US_NOVA_PREMIER.id]: typeof US_NOVA_PREMIER.supports.input + [US_NOVA_PRO.id]: typeof US_NOVA_PRO.supports.input + [US_NOVA_MICRO.id]: typeof US_NOVA_MICRO.supports.input + [US_NOVA_LITE.id]: typeof US_NOVA_LITE.supports.input + [US_NOVA_2_LITE.id]: typeof US_NOVA_2_LITE.supports.input + [US_NOVA_2_SONIC.id]: typeof US_NOVA_2_SONIC.supports.input + [CLAUDE_3_HAIKU.id]: typeof CLAUDE_3_HAIKU.supports.input + [CLAUDE_3_SONNET.id]: typeof CLAUDE_3_SONNET.supports.input + [CLAUDE_3_OPUS.id]: typeof CLAUDE_3_OPUS.supports.input + [CLAUDE_3_5_HAIKU.id]: typeof CLAUDE_3_5_HAIKU.supports.input + [CLAUDE_3_5_SONNET.id]: typeof CLAUDE_3_5_SONNET.supports.input + [CLAUDE_3_5_SONNET_V2.id]: typeof CLAUDE_3_5_SONNET_V2.supports.input + [CLAUDE_3_7_SONNET.id]: typeof CLAUDE_3_7_SONNET.supports.input + [CLAUDE_HAIKU_4_5.id]: typeof CLAUDE_HAIKU_4_5.supports.input + [CLAUDE_SONNET_4.id]: typeof CLAUDE_SONNET_4.supports.input + [CLAUDE_SONNET_4_5.id]: typeof CLAUDE_SONNET_4_5.supports.input + [CLAUDE_OPUS_4.id]: typeof CLAUDE_OPUS_4.supports.input + [CLAUDE_OPUS_4_1.id]: typeof CLAUDE_OPUS_4_1.supports.input + [US_CLAUDE_3_HAIKU.id]: typeof US_CLAUDE_3_HAIKU.supports.input + [US_CLAUDE_3_SONNET.id]: typeof US_CLAUDE_3_SONNET.supports.input + [US_CLAUDE_3_OPUS.id]: typeof US_CLAUDE_3_OPUS.supports.input + [US_CLAUDE_3_5_HAIKU.id]: typeof US_CLAUDE_3_5_HAIKU.supports.input + [US_CLAUDE_3_5_SONNET.id]: typeof US_CLAUDE_3_5_SONNET.supports.input + [US_CLAUDE_3_5_SONNET_V2.id]: typeof US_CLAUDE_3_5_SONNET_V2.supports.input + [US_CLAUDE_3_7_SONNET.id]: typeof US_CLAUDE_3_7_SONNET.supports.input + [US_CLAUDE_SONNET_4.id]: typeof US_CLAUDE_SONNET_4.supports.input + [US_CLAUDE_SONNET_4_5.id]: typeof US_CLAUDE_SONNET_4_5.supports.input + [US_CLAUDE_OPUS_4.id]: typeof US_CLAUDE_OPUS_4.supports.input + [US_CLAUDE_OPUS_4_1.id]: typeof US_CLAUDE_OPUS_4_1.supports.input + [LLAMA_3_8B.id]: typeof LLAMA_3_8B.supports.input + [LLAMA_3_70B.id]: typeof LLAMA_3_70B.supports.input + [LLAMA_3_1_8B.id]: typeof LLAMA_3_1_8B.supports.input + [LLAMA_3_1_70B.id]: typeof LLAMA_3_1_70B.supports.input + [LLAMA_3_1_405B.id]: typeof LLAMA_3_1_405B.supports.input + [LLAMA_3_2_1B.id]: typeof LLAMA_3_2_1B.supports.input + [LLAMA_3_2_3B.id]: typeof LLAMA_3_2_3B.supports.input + [LLAMA_3_2_11B.id]: typeof LLAMA_3_2_11B.supports.input + [LLAMA_3_2_90B.id]: typeof LLAMA_3_2_90B.supports.input + [LLAMA_3_3_70B.id]: typeof LLAMA_3_3_70B.supports.input + [LLAMA_4_SCOUT.id]: typeof LLAMA_4_SCOUT.supports.input + [LLAMA_4_MAVERICK.id]: typeof LLAMA_4_MAVERICK.supports.input + [US_LLAMA_3_1_8B.id]: typeof US_LLAMA_3_1_8B.supports.input + [US_LLAMA_3_1_70B.id]: typeof US_LLAMA_3_1_70B.supports.input + [US_LLAMA_3_2_1B.id]: typeof US_LLAMA_3_2_1B.supports.input + [US_LLAMA_3_2_3B.id]: typeof US_LLAMA_3_2_3B.supports.input + [US_LLAMA_3_2_11B.id]: typeof US_LLAMA_3_2_11B.supports.input + [US_LLAMA_3_2_90B.id]: typeof US_LLAMA_3_2_90B.supports.input + [US_LLAMA_3_3_70B.id]: typeof US_LLAMA_3_3_70B.supports.input + [US_LLAMA_4_SCOUT.id]: typeof US_LLAMA_4_SCOUT.supports.input + [US_LLAMA_4_MAVERICK.id]: typeof US_LLAMA_4_MAVERICK.supports.input + [MISTRAL_7B.id]: typeof MISTRAL_7B.supports.input + [MIXTRAL_8X7B.id]: typeof MIXTRAL_8X7B.supports.input + [MISTRAL_LARGE_2402.id]: typeof MISTRAL_LARGE_2402.supports.input + [MISTRAL_LARGE_2407.id]: typeof MISTRAL_LARGE_2407.supports.input + [MISTRAL_SMALL_2402.id]: typeof MISTRAL_SMALL_2402.supports.input + [US_PIXTRAL_LARGE.id]: typeof US_PIXTRAL_LARGE.supports.input + [TITAN_TEXT_LARGE.id]: typeof TITAN_TEXT_LARGE.supports.input + [TITAN_TEXT_EXPRESS.id]: typeof TITAN_TEXT_EXPRESS.supports.input + [TITAN_TEXT_LITE.id]: typeof TITAN_TEXT_LITE.supports.input + [COHERE_COMMAND_TEXT.id]: typeof COHERE_COMMAND_TEXT.supports.input + [COHERE_COMMAND_LIGHT.id]: typeof COHERE_COMMAND_LIGHT.supports.input + [COHERE_COMMAND_R.id]: typeof COHERE_COMMAND_R.supports.input + [COHERE_COMMAND_R_PLUS.id]: typeof COHERE_COMMAND_R_PLUS.supports.input + [DEEPSEEK_R1.id]: typeof DEEPSEEK_R1.supports.input + [US_DEEPSEEK_R1.id]: typeof US_DEEPSEEK_R1.supports.input + [DEEPSEEK_V3.id]: typeof DEEPSEEK_V3.supports.input + [AI21_JAMBA_LARGE.id]: typeof AI21_JAMBA_LARGE.supports.input + [AI21_JAMBA_MINI.id]: typeof AI21_JAMBA_MINI.supports.input + [WRITER_PALMYRA_X4.id]: typeof WRITER_PALMYRA_X4.supports.input + [WRITER_PALMYRA_X5.id]: typeof WRITER_PALMYRA_X5.supports.input + [TWELVELABS_PEGASUS.id]: typeof TWELVELABS_PEGASUS.supports.input + [LUMA_RAY_V2.id]: typeof LUMA_RAY_V2.supports.input + [MISTRAL_LARGE_3.id]: typeof MISTRAL_LARGE_3.supports.input + [MINISTRAL_3_3B.id]: typeof MINISTRAL_3_3B.supports.input + [MINISTRAL_3_8B.id]: typeof MINISTRAL_3_8B.supports.input + [MINISTRAL_3_14B.id]: typeof MINISTRAL_3_14B.supports.input + [MAGISTRAL_SMALL.id]: typeof MAGISTRAL_SMALL.supports.input + [VOXTRAL_MINI.id]: typeof VOXTRAL_MINI.supports.input + [VOXTRAL_SMALL.id]: typeof VOXTRAL_SMALL.supports.input + [GEMMA_3_4B.id]: typeof GEMMA_3_4B.supports.input + [GEMMA_3_12B.id]: typeof GEMMA_3_12B.supports.input + [GEMMA_3_27B.id]: typeof GEMMA_3_27B.supports.input + [NVIDIA_NEMOTRON_9B.id]: typeof NVIDIA_NEMOTRON_9B.supports.input + [NVIDIA_NEMOTRON_12B_VL.id]: typeof NVIDIA_NEMOTRON_12B_VL.supports.input + [MINIMAX_M2.id]: typeof MINIMAX_M2.supports.input + [MOONSHOT_KIMI_K2.id]: typeof MOONSHOT_KIMI_K2.supports.input + [OPENAI_SAFEGUARD_20B.id]: typeof OPENAI_SAFEGUARD_20B.supports.input + [OPENAI_SAFEGUARD_120B.id]: typeof OPENAI_SAFEGUARD_120B.supports.input + [QWEN_3_NEXT_80B.id]: typeof QWEN_3_NEXT_80B.supports.input + [QWEN_3_VL_235B.id]: typeof QWEN_3_VL_235B.supports.input +} + +/** + * Inference Profile Region type for cross-region inference + * @see https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles.html + */ +export type InferenceProfileRegion = 'us' | 'eu' + +/** + * Converts a direct Anthropic model ID to an inference profile ID. + * + * AWS Bedrock requires inference profiles for newer Claude models (Claude 3.5 Sonnet v2 and later). + * Direct model IDs like `anthropic.claude-3-5-sonnet-20241022-v2:0` will not work for on-demand + * invocation with these models. Use this helper to convert to the appropriate inference profile. + * + * @param modelId - The model ID (can be direct or already an inference profile) + * @param region - The inference profile region ('us' or 'eu'). Defaults to 'us'. + * @returns The inference profile model ID + * + * @example + * ```typescript + * // Convert direct model ID to US inference profile + * toInferenceProfileId('anthropic.claude-3-5-sonnet-20241022-v2:0') + * // Returns: 'us.anthropic.claude-3-5-sonnet-20241022-v2:0' + * + * // Convert to EU inference profile + * toInferenceProfileId('anthropic.claude-3-5-sonnet-20241022-v2:0', 'eu') + * // Returns: 'eu.anthropic.claude-3-5-sonnet-20241022-v2:0' + * + * // Already an inference profile - returns unchanged + * toInferenceProfileId('us.anthropic.claude-3-5-sonnet-20241022-v2:0') + * // Returns: 'us.anthropic.claude-3-5-sonnet-20241022-v2:0' + * ``` + * + * @see https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html + */ +export function toInferenceProfileId( + modelId: string, + region: InferenceProfileRegion = 'us', +): string { + if ( + modelId.startsWith('us.') || + modelId.startsWith('eu.') || + !modelId.startsWith('anthropic.') + ) { + return modelId + } + return `${region}.${modelId}` +} + +/** + * Checks if a model ID is an Anthropic model (direct or inference profile) + * + * @param modelId - The model ID to check + * @returns true if the model ID is for an Anthropic model + * + * @example + * ```typescript + * isAnthropicModel('anthropic.claude-3-5-sonnet-20241022-v2:0') // true + * isAnthropicModel('us.anthropic.claude-3-5-sonnet-20241022-v2:0') // true + * isAnthropicModel('eu.anthropic.claude-3-haiku-20240307-v1:0') // true + * isAnthropicModel('amazon.nova-lite-v1:0') // false + * ``` + */ +export function isAnthropicModel(modelId: string): boolean { + return ( + modelId.startsWith('anthropic.') || + modelId.startsWith('us.anthropic.') || + modelId.startsWith('eu.anthropic.') + ) +} + +/** + * Checks if a model ID uses an inference profile format + * + * @param modelId - The model ID to check + * @returns true if the model ID uses an inference profile (has us. or eu. prefix) + * + * @example + * ```typescript + * isInferenceProfileId('us.anthropic.claude-3-5-sonnet-20241022-v2:0') // true + * isInferenceProfileId('eu.anthropic.claude-3-haiku-20240307-v1:0') // true + * isInferenceProfileId('anthropic.claude-3-5-sonnet-20241022-v2:0') // false + * isInferenceProfileId('us.amazon.nova-premier-v1:0') // true + * ``` + */ +export function isInferenceProfileId(modelId: string): boolean { + return modelId.startsWith('us.') || modelId.startsWith('eu.') +} diff --git a/packages/typescript/ai-bedrock/src/text/text-provider-options.ts b/packages/typescript/ai-bedrock/src/text/text-provider-options.ts new file mode 100644 index 00000000..5259c517 --- /dev/null +++ b/packages/typescript/ai-bedrock/src/text/text-provider-options.ts @@ -0,0 +1,180 @@ +/** + * Bedrock provider options interfaces + * Split by feature for per-model type-safety + * + * @see https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html + */ + +export interface BedrockBaseOptions { + /** + * The maximum number of tokens to generate in the response. + */ + maxTokens?: number + /** + * Controls randomness in the output. Higher values produce more random results. + * Range: 0.0 to 1.0 + */ + temperature?: number + /** + * Nucleus sampling parameter. Only consider tokens with cumulative probability up to this value. + * Range: 0.0 to 1.0 + */ + topP?: number + /** + * Only sample from the top K options for each subsequent token. + * Not all models support this parameter. + */ + topK?: number + /** + * Sequences that will cause the model to stop generating further tokens. + */ + stopSequences?: Array +} + +export interface BedrockAdditionalFieldsOptions { + /** + * Escape hatch for provider-specific fields not exposed by the Converse API. + * Use this to pass model-specific parameters directly. + */ + additionalModelRequestFields?: Record +} + +export interface BedrockPerformanceOptions { + /** + * Performance configuration for latency optimization. + * When set to 'optimized', uses latency-optimized inference for supported models. + * + * Supported models (as of 2025): + * - Amazon Nova Pro + * - Anthropic Claude 3.5 Haiku + * - Meta Llama 3.1 70B/405B Instruct + * + * Benefits: Up to 42% faster time-to-first-token (TTFT) and 77% more output tokens/second. + * + * @see https://docs.aws.amazon.com/bedrock/latest/userguide/latency-optimized-inference.html + */ + performanceConfig?: { + latency: 'standard' | 'optimized' + } +} + +export interface BedrockServiceTierOptions { + /** + * Service tier configuration for request prioritization. + * + * - `priority`: For mission-critical apps needing rapid response (25% better latency, premium pricing) + * - `default`: Standard tier for everyday AI tasks + * - `flex`: Cost-effective for non-time-critical workloads (discounted pricing) + * - `reserved`: Predictable performance with guaranteed tokens-per-minute capacity + * + * @see https://docs.aws.amazon.com/bedrock/latest/userguide/service-tiers.html + */ + serviceTier?: { + type: 'priority' | 'default' | 'flex' | 'reserved' + } +} + +export interface BedrockRequestMetadataOptions { + /** + * Metadata as key-value pairs for request tracking and log filtering. + * Useful for analytics, debugging, and cost allocation. + * + * @example + * ```typescript + * requestMetadata: { + * userId: '12345', + * sessionId: 'abc-def', + * feature: 'chat-assistant' + * } + * ``` + * + * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Converse.html + */ + requestMetadata?: Record +} + +export interface BedrockToolChoiceOptions { + /** + * Controls how the model selects and invokes tools. + * + * - `auto`: Model autonomously decides whether to call a tool or generate text (default) + * - `any`: Model must invoke at least one tool from the provided list + * - `tool`: Model must use a specific named tool + * + * Supported by: Anthropic Claude 3+, Amazon Nova models + * + * @example + * ```typescript + * // Let model decide + * toolChoice: { auto: {} } + * + * // Force tool use + * toolChoice: { any: {} } + * + * // Use specific tool + * toolChoice: { tool: { name: 'get_weather' } } + * ``` + * + * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ToolChoice.html + */ + toolChoice?: { auto: object } | { any: object } | { tool: { name: string } } +} + +export interface BedrockAnthropicReasoningOptions { + /** + * Configuration for Claude's extended thinking capabilities. + * Only applicable to Claude reasoning models on Bedrock. + * + * Note: When thinking is enabled, `temperature`, `topP`, and `topK` cannot be modified. + * Streaming is required when `maxTokens` > 21,333. + * + * @see https://docs.aws.amazon.com/bedrock/latest/userguide/claude-messages-extended-thinking.html + * @see https://docs.anthropic.com/en/docs/build-with-claude/extended-thinking + */ + reasoningConfig?: { + /** + * Whether reasoning is enabled or disabled. + */ + type: 'enabled' | 'disabled' + /** + * Token budget for reasoning/thinking. + * Minimum: 1024, Maximum: 64000 + */ + budgetTokens?: number + } +} + +export interface BedrockReasoningEffortOptions { + /** + * Configuration for reasoning effort on non-Anthropic models. + * Applicable to Amazon Nova, DeepSeek R1, Mistral Magistral, NVIDIA Nemotron, Moonshot Kimi. + */ + reasoningConfig?: { + /** + * Whether reasoning is enabled or disabled. + */ + type: 'enabled' | 'disabled' + /** + * Maximum reasoning effort level. + */ + maxReasoningEffort?: 'low' | 'medium' | 'high' + } +} + +export interface BedrockAnthropicOptions { + /** + * Anthropic-specific beta features. + * Only applicable to Claude models on Bedrock. + * @see https://docs.anthropic.com/en/api/versioning#beta-features + */ + anthropicBeta?: Array +} + +export type BedrockProviderOptions = BedrockBaseOptions & + BedrockAdditionalFieldsOptions & + BedrockAnthropicReasoningOptions & + BedrockPerformanceOptions & + BedrockServiceTierOptions & + BedrockRequestMetadataOptions & + BedrockToolChoiceOptions + diff --git a/packages/typescript/ai-bedrock/tsconfig.json b/packages/typescript/ai-bedrock/tsconfig.json new file mode 100644 index 00000000..ea11c109 --- /dev/null +++ b/packages/typescript/ai-bedrock/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*.ts", "src/**/*.tsx"], + "exclude": ["node_modules", "dist", "**/*.config.ts"] +} diff --git a/packages/typescript/ai-bedrock/vite.config.ts b/packages/typescript/ai-bedrock/vite.config.ts new file mode 100644 index 00000000..77bcc2e6 --- /dev/null +++ b/packages/typescript/ai-bedrock/vite.config.ts @@ -0,0 +1,36 @@ +import { defineConfig, mergeConfig } from 'vitest/config' +import { tanstackViteConfig } from '@tanstack/vite-config' +import packageJson from './package.json' + +const config = defineConfig({ + test: { + name: packageJson.name, + dir: './', + watch: false, + globals: true, + environment: 'node', + include: ['tests/**/*.test.ts'], + coverage: { + provider: 'v8', + reporter: ['text', 'json', 'html', 'lcov'], + exclude: [ + 'node_modules/', + 'dist/', + 'tests/', + '**/*.test.ts', + '**/*.config.ts', + '**/types.ts', + ], + include: ['src/**/*.ts'], + }, + }, +}) + +export default mergeConfig( + config, + tanstackViteConfig({ + entry: ['./src/index.ts'], + srcDir: './src', + cjs: false, + }), +) From b714dc25fc413145fe87f56fb486656d148e3387 Mon Sep 17 00:00:00 2001 From: Hunter Blackwell <31895576+chunterb@users.noreply.github.com> Date: Sun, 7 Dec 2025 11:10:10 -0600 Subject: [PATCH 2/7] feat(ai-bedrock): add tool support --- .../src/tools/anthropic-bash-tool.ts | 22 ++++++ .../tools/anthropic-code-execution-tool.ts | 56 +++++++++++++ .../src/tools/anthropic-computer-use-tool.ts | 58 ++++++++++++++ .../src/tools/anthropic-memory-tool.ts | 78 +++++++++++++++++++ .../src/tools/anthropic-text-editor-tool.ts | 35 +++++++++ .../src/tools/anthropic-web-fetch-tool.ts | 23 ++++++ .../src/tools/anthropic-web-search-tool.ts | 11 +++ .../ai-bedrock/src/tools/custom-tool.ts | 24 ++++++ .../typescript/ai-bedrock/src/tools/index.ts | 2 + .../ai-bedrock/src/tools/tool-converter.ts | 69 ++++++++++++++++ 10 files changed, 378 insertions(+) create mode 100644 packages/typescript/ai-bedrock/src/tools/anthropic-bash-tool.ts create mode 100644 packages/typescript/ai-bedrock/src/tools/anthropic-code-execution-tool.ts create mode 100644 packages/typescript/ai-bedrock/src/tools/anthropic-computer-use-tool.ts create mode 100644 packages/typescript/ai-bedrock/src/tools/anthropic-memory-tool.ts create mode 100644 packages/typescript/ai-bedrock/src/tools/anthropic-text-editor-tool.ts create mode 100644 packages/typescript/ai-bedrock/src/tools/anthropic-web-fetch-tool.ts create mode 100644 packages/typescript/ai-bedrock/src/tools/anthropic-web-search-tool.ts create mode 100644 packages/typescript/ai-bedrock/src/tools/custom-tool.ts create mode 100644 packages/typescript/ai-bedrock/src/tools/index.ts create mode 100644 packages/typescript/ai-bedrock/src/tools/tool-converter.ts diff --git a/packages/typescript/ai-bedrock/src/tools/anthropic-bash-tool.ts b/packages/typescript/ai-bedrock/src/tools/anthropic-bash-tool.ts new file mode 100644 index 00000000..087c9ee8 --- /dev/null +++ b/packages/typescript/ai-bedrock/src/tools/anthropic-bash-tool.ts @@ -0,0 +1,22 @@ +import type { Tool } from '@tanstack/ai' +import type { BedrockToolSpec } from './custom-tool' + +const BASH_INPUT_SCHEMA = { + type: 'object', + properties: { + command: { type: 'string' }, + restart: { type: 'boolean' }, + }, + required: ['command'], +} as const + +export function convertBashToolToAdapterFormat(tool: Tool): BedrockToolSpec { + return { + toolSpec: { + name: tool.name, + inputSchema: { + json: BASH_INPUT_SCHEMA as unknown as Record, + }, + }, + } +} diff --git a/packages/typescript/ai-bedrock/src/tools/anthropic-code-execution-tool.ts b/packages/typescript/ai-bedrock/src/tools/anthropic-code-execution-tool.ts new file mode 100644 index 00000000..f3e56057 --- /dev/null +++ b/packages/typescript/ai-bedrock/src/tools/anthropic-code-execution-tool.ts @@ -0,0 +1,56 @@ +import type { Tool } from '@tanstack/ai' +import type { BedrockToolSpec } from './custom-tool' + +const CODE_EXECUTION_INPUT_SCHEMA_20250522 = { + type: 'object', + properties: { + code: { type: 'string' }, + }, + required: ['code'], +} as const + +const CODE_EXECUTION_INPUT_SCHEMA_20250825 = { + oneOf: [ + { + type: 'object', + properties: { + type: { type: 'string', const: 'bash_code_execution' }, + command: { type: 'string' }, + }, + required: ['type', 'command'], + }, + { + type: 'object', + properties: { + type: { type: 'string', const: 'text_editor_code_execution' }, + command: { type: 'string', enum: ['view', 'create', 'str_replace'] }, + path: { type: 'string' }, + file_text: { type: 'string' }, + old_str: { type: 'string' }, + new_str: { type: 'string' }, + }, + required: ['type', 'command', 'path'], + }, + ], +} as const + +export function convertCodeExecutionToolToAdapterFormat( + tool: Tool, +): BedrockToolSpec { + const metadata = tool.metadata as { type?: string } | undefined + const toolType = metadata?.type + + const schema = + toolType === 'code_execution_20250825' + ? CODE_EXECUTION_INPUT_SCHEMA_20250825 + : CODE_EXECUTION_INPUT_SCHEMA_20250522 + + return { + toolSpec: { + name: tool.name, + inputSchema: { + json: schema as unknown as Record, + }, + }, + } +} diff --git a/packages/typescript/ai-bedrock/src/tools/anthropic-computer-use-tool.ts b/packages/typescript/ai-bedrock/src/tools/anthropic-computer-use-tool.ts new file mode 100644 index 00000000..edbc15c5 --- /dev/null +++ b/packages/typescript/ai-bedrock/src/tools/anthropic-computer-use-tool.ts @@ -0,0 +1,58 @@ +import type { Tool } from '@tanstack/ai' +import type { BedrockToolSpec } from './custom-tool' + +const COMPUTER_USE_INPUT_SCHEMA = { + type: 'object', + properties: { + action: { + type: 'string', + enum: [ + 'key', + 'hold_key', + 'type', + 'cursor_position', + 'mouse_move', + 'left_mouse_down', + 'left_mouse_up', + 'left_click', + 'left_click_drag', + 'right_click', + 'middle_click', + 'double_click', + 'triple_click', + 'scroll', + 'wait', + 'screenshot', + ], + }, + coordinate: { + type: 'array', + items: { type: 'integer' }, + }, + duration: { type: 'number' }, + scroll_amount: { type: 'number' }, + scroll_direction: { + type: 'string', + enum: ['up', 'down', 'left', 'right'], + }, + start_coordinate: { + type: 'array', + items: { type: 'integer' }, + }, + text: { type: 'string' }, + }, + required: ['action'], +} as const + +export function convertComputerUseToolToAdapterFormat( + tool: Tool, +): BedrockToolSpec { + return { + toolSpec: { + name: tool.name, + inputSchema: { + json: COMPUTER_USE_INPUT_SCHEMA as unknown as Record, + }, + }, + } +} diff --git a/packages/typescript/ai-bedrock/src/tools/anthropic-memory-tool.ts b/packages/typescript/ai-bedrock/src/tools/anthropic-memory-tool.ts new file mode 100644 index 00000000..185cc056 --- /dev/null +++ b/packages/typescript/ai-bedrock/src/tools/anthropic-memory-tool.ts @@ -0,0 +1,78 @@ +import type { Tool } from '@tanstack/ai' +import type { BedrockToolSpec } from './custom-tool' + +const MEMORY_INPUT_SCHEMA = { + oneOf: [ + { + type: 'object', + properties: { + command: { type: 'string', const: 'view' }, + path: { type: 'string' }, + view_range: { + type: 'array', + items: { type: 'number' }, + minItems: 2, + maxItems: 2, + }, + }, + required: ['command', 'path'], + }, + { + type: 'object', + properties: { + command: { type: 'string', const: 'create' }, + path: { type: 'string' }, + file_text: { type: 'string' }, + }, + required: ['command', 'path', 'file_text'], + }, + { + type: 'object', + properties: { + command: { type: 'string', const: 'str_replace' }, + path: { type: 'string' }, + old_str: { type: 'string' }, + new_str: { type: 'string' }, + }, + required: ['command', 'path', 'old_str', 'new_str'], + }, + { + type: 'object', + properties: { + command: { type: 'string', const: 'insert' }, + path: { type: 'string' }, + insert_line: { type: 'number' }, + insert_text: { type: 'string' }, + }, + required: ['command', 'path', 'insert_line', 'insert_text'], + }, + { + type: 'object', + properties: { + command: { type: 'string', const: 'delete' }, + path: { type: 'string' }, + }, + required: ['command', 'path'], + }, + { + type: 'object', + properties: { + command: { type: 'string', const: 'rename' }, + old_path: { type: 'string' }, + new_path: { type: 'string' }, + }, + required: ['command', 'old_path', 'new_path'], + }, + ], +} as const + +export function convertMemoryToolToAdapterFormat(tool: Tool): BedrockToolSpec { + return { + toolSpec: { + name: tool.name, + inputSchema: { + json: MEMORY_INPUT_SCHEMA as unknown as Record, + }, + }, + } +} diff --git a/packages/typescript/ai-bedrock/src/tools/anthropic-text-editor-tool.ts b/packages/typescript/ai-bedrock/src/tools/anthropic-text-editor-tool.ts new file mode 100644 index 00000000..6e838d08 --- /dev/null +++ b/packages/typescript/ai-bedrock/src/tools/anthropic-text-editor-tool.ts @@ -0,0 +1,35 @@ +import type { Tool } from '@tanstack/ai' +import type { BedrockToolSpec } from './custom-tool' + +const TEXT_EDITOR_INPUT_SCHEMA = { + type: 'object', + properties: { + command: { + type: 'string', + enum: ['view', 'create', 'str_replace', 'insert', 'undo_edit'], + }, + path: { type: 'string' }, + file_text: { type: 'string' }, + insert_line: { type: 'integer' }, + new_str: { type: 'string' }, + old_str: { type: 'string' }, + view_range: { + type: 'array', + items: { type: 'integer' }, + }, + }, + required: ['command', 'path'], +} as const + +export function convertTextEditorToolToAdapterFormat( + tool: Tool, +): BedrockToolSpec { + return { + toolSpec: { + name: tool.name, + inputSchema: { + json: TEXT_EDITOR_INPUT_SCHEMA as unknown as Record, + }, + }, + } +} diff --git a/packages/typescript/ai-bedrock/src/tools/anthropic-web-fetch-tool.ts b/packages/typescript/ai-bedrock/src/tools/anthropic-web-fetch-tool.ts new file mode 100644 index 00000000..e60fabd3 --- /dev/null +++ b/packages/typescript/ai-bedrock/src/tools/anthropic-web-fetch-tool.ts @@ -0,0 +1,23 @@ +import type { Tool } from '@tanstack/ai' +import type { BedrockToolSpec } from './custom-tool' + +const WEB_FETCH_INPUT_SCHEMA = { + type: 'object', + properties: { + url: { type: 'string' }, + }, + required: ['url'], +} as const + +export function convertWebFetchToolToAdapterFormat( + tool: Tool, +): BedrockToolSpec { + return { + toolSpec: { + name: tool.name, + inputSchema: { + json: WEB_FETCH_INPUT_SCHEMA as unknown as Record, + }, + }, + } +} diff --git a/packages/typescript/ai-bedrock/src/tools/anthropic-web-search-tool.ts b/packages/typescript/ai-bedrock/src/tools/anthropic-web-search-tool.ts new file mode 100644 index 00000000..b87c7e33 --- /dev/null +++ b/packages/typescript/ai-bedrock/src/tools/anthropic-web-search-tool.ts @@ -0,0 +1,11 @@ +import type { Tool } from '@tanstack/ai' +import type { BedrockToolSpec } from './custom-tool' + +export function convertWebSearchToolToAdapterFormat( + _tool: Tool, +): BedrockToolSpec { + throw new Error( + 'The web_search tool is not supported on Amazon Bedrock. ' + + 'Please remove this tool from your configuration.', + ) +} diff --git a/packages/typescript/ai-bedrock/src/tools/custom-tool.ts b/packages/typescript/ai-bedrock/src/tools/custom-tool.ts new file mode 100644 index 00000000..72f30d41 --- /dev/null +++ b/packages/typescript/ai-bedrock/src/tools/custom-tool.ts @@ -0,0 +1,24 @@ +import { convertZodToJsonSchema } from '@tanstack/ai' +import type { Tool } from '@tanstack/ai' + +export interface BedrockToolSpec { + toolSpec: { + name: string + description?: string + inputSchema: { json: Record } + } +} + +export function convertCustomToolToAdapterFormat(tool: Tool): BedrockToolSpec { + const jsonSchema = convertZodToJsonSchema(tool.inputSchema) + + return { + toolSpec: { + name: tool.name, + ...(tool.description && { description: tool.description }), + inputSchema: { + json: jsonSchema || { type: 'object', properties: {} }, + }, + }, + } +} diff --git a/packages/typescript/ai-bedrock/src/tools/index.ts b/packages/typescript/ai-bedrock/src/tools/index.ts new file mode 100644 index 00000000..c83a7383 --- /dev/null +++ b/packages/typescript/ai-bedrock/src/tools/index.ts @@ -0,0 +1,2 @@ +export type { BedrockToolSpec } from './custom-tool' +export { convertToolsToProviderFormat } from './tool-converter' diff --git a/packages/typescript/ai-bedrock/src/tools/tool-converter.ts b/packages/typescript/ai-bedrock/src/tools/tool-converter.ts new file mode 100644 index 00000000..bf1d3098 --- /dev/null +++ b/packages/typescript/ai-bedrock/src/tools/tool-converter.ts @@ -0,0 +1,69 @@ +import { convertBashToolToAdapterFormat } from './anthropic-bash-tool' +import { convertCodeExecutionToolToAdapterFormat } from './anthropic-code-execution-tool' +import { convertComputerUseToolToAdapterFormat } from './anthropic-computer-use-tool' +import { convertMemoryToolToAdapterFormat } from './anthropic-memory-tool' +import { convertTextEditorToolToAdapterFormat } from './anthropic-text-editor-tool' +import { convertWebFetchToolToAdapterFormat } from './anthropic-web-fetch-tool' +import { convertWebSearchToolToAdapterFormat } from './anthropic-web-search-tool' +import { convertCustomToolToAdapterFormat } from './custom-tool' +import { isAnthropicModel } from '../model-meta' +import type { Tool } from '@tanstack/ai' +import type { BedrockToolSpec } from './custom-tool' + +/** + * Converts standard Tool format to Bedrock-specific tool format + * + * @param tools - Array of standard Tool objects + * @param modelId - Model ID to determine if Anthropic provider tools are supported. + * Supports all Anthropic model ID formats: + * - Direct: `anthropic.claude-3-5-sonnet-20241022-v2:0` + * - US inference profile: `us.anthropic.claude-3-5-sonnet-20241022-v2:0` + * - EU inference profile: `eu.anthropic.claude-3-5-sonnet-20241022-v2:0` + * @returns Array of Bedrock tool specifications + * + * @example + * ```typescript + * const tools: Tool[] = [{ + * name: "get_weather", + * description: "Get weather for a location", + * inputSchema: z.object({ + * location: z.string() + * }) + * }]; + * + * const bedrockTools = convertToolsToProviderFormat(tools, 'us.anthropic.claude-3-5-sonnet-20241022-v2:0'); + * ``` + */ +export function convertToolsToProviderFormat( + tools: Array, + modelId: string, +): Array { + const isAnthropic = isAnthropicModel(modelId) + + return tools.map((tool) => { + const name = tool.name + + if (isAnthropic) { + switch (name) { + case 'bash': + return convertBashToolToAdapterFormat(tool) + case 'code_execution': + return convertCodeExecutionToolToAdapterFormat(tool) + case 'computer': + return convertComputerUseToolToAdapterFormat(tool) + case 'memory': + return convertMemoryToolToAdapterFormat(tool) + case 'str_replace_editor': + return convertTextEditorToolToAdapterFormat(tool) + case 'web_fetch': + return convertWebFetchToolToAdapterFormat(tool) + case 'web_search': + return convertWebSearchToolToAdapterFormat(tool) + default: + return convertCustomToolToAdapterFormat(tool) + } + } + + return convertCustomToolToAdapterFormat(tool) + }) +} From a904c429a8c3b6e29eeaf8b9012e5a7f1d242dbb Mon Sep 17 00:00:00 2001 From: Hunter Blackwell <31895576+chunterb@users.noreply.github.com> Date: Mon, 8 Dec 2025 16:39:58 -0600 Subject: [PATCH 3/7] refactor: leverage aws bedrock sdk types --- packages/typescript/ai-bedrock/package.json | 2 + .../ai-bedrock/src/bedrock-adapter.ts | 494 +++---- packages/typescript/ai-bedrock/src/index.ts | 8 +- .../ai-bedrock/src/message-types.ts | 89 +- .../typescript/ai-bedrock/src/model-meta.ts | 582 +------- .../src/text/text-provider-options.ts | 32 +- .../src/tools/anthropic-bash-tool.ts | 9 +- .../tools/anthropic-code-execution-tool.ts | 11 +- .../src/tools/anthropic-computer-use-tool.ts | 11 +- .../src/tools/anthropic-memory-tool.ts | 9 +- .../src/tools/anthropic-text-editor-tool.ts | 11 +- .../src/tools/anthropic-web-fetch-tool.ts | 11 +- .../src/tools/anthropic-web-search-tool.ts | 8 +- .../ai-bedrock/src/tools/custom-tool.ts | 16 +- .../typescript/ai-bedrock/src/tools/index.ts | 1 - .../ai-bedrock/src/tools/tool-converter.ts | 11 +- pnpm-lock.yaml | 1168 ++++++++++++++++- 17 files changed, 1502 insertions(+), 971 deletions(-) diff --git a/packages/typescript/ai-bedrock/package.json b/packages/typescript/ai-bedrock/package.json index c68416ab..55805368 100644 --- a/packages/typescript/ai-bedrock/package.json +++ b/packages/typescript/ai-bedrock/package.json @@ -46,6 +46,8 @@ "aws4fetch": "^1.0.20" }, "devDependencies": { + "@aws-sdk/client-bedrock": "^3.947.0", + "@aws-sdk/client-bedrock-runtime": "^3.947.0", "@vitest/coverage-v8": "4.0.14", "vite": "^7.2.4" }, diff --git a/packages/typescript/ai-bedrock/src/bedrock-adapter.ts b/packages/typescript/ai-bedrock/src/bedrock-adapter.ts index dd416f99..6da1ab67 100644 --- a/packages/typescript/ai-bedrock/src/bedrock-adapter.ts +++ b/packages/typescript/ai-bedrock/src/bedrock-adapter.ts @@ -2,11 +2,29 @@ import { AwsV4Signer } from 'aws4fetch' import { EventStreamCodec } from '@smithy/eventstream-codec' import { fromUtf8, toUtf8 } from '@smithy/util-utf8' import { BaseAdapter } from '@tanstack/ai' -import { - BEDROCK_EMBEDDING_MODELS, - BEDROCK_MODELS, -} from './model-meta' +import { BEDROCK_EMBEDDING_MODELS, BEDROCK_MODELS } from './model-meta' import { convertToolsToProviderFormat } from './tools/tool-converter' +import type { + ContentBlock, + ConverseRequest, + ConverseResponse, + ConverseStreamOutput, + ConverseStreamRequest, + DocumentFormat, + ImageFormat, + InferenceConfiguration, + Message, + StopReason, + SystemContentBlock, + TokenUsage, + ToolConfiguration, + VideoFormat, +} from '@aws-sdk/client-bedrock-runtime' +import type { + AwsCredentialIdentity, + AwsCredentialIdentityProvider, + DocumentType, +} from '@smithy/types' import type { ChatOptions, ContentPart, @@ -23,146 +41,95 @@ import type { } from './model-meta' import type { BedrockProviderOptions } from './text/text-provider-options' import type { - BedrockDocumentFormat, BedrockDocumentMetadata, - BedrockImageFormat, BedrockImageMetadata, BedrockMessageMetadataByModality, - BedrockVideoFormat, BedrockVideoMetadata, } from './message-types' +type BedrockMessage = Message +type BedrockContentBlock = ContentBlock +type BedrockConversePayload = Omit +type BedrockConverseStreamPayload = Omit +type BedrockStreamEvent = ConverseStreamOutput + /** - * AWS credentials returned by a credential provider + * TanStack AI finish reason type */ -export interface BedrockCredentials { - accessKeyId: string - secretAccessKey: string - sessionToken?: string -} +type FinishReason = 'stop' | 'tool_calls' | 'length' | 'content_filter' -interface BedrockTextBlock { - text: string -} - -interface BedrockImageBlock { - image: { - format: BedrockImageFormat - source: { bytes: string } | { s3Location: { uri: string; bucketOwner?: string } } +/** + * Maps Bedrock StopReason to TanStack AI finish reason. + * Uses the SDK's StopReason type for exhaustive handling. + * + * @param stopReason - The Bedrock stop reason from the stream event + * @param hasToolCalls - Whether tool calls were made in this response + * @returns The normalized TanStack AI finish reason + */ +function mapBedrockStopReason( + stopReason: StopReason | undefined, + hasToolCalls: boolean, +): FinishReason { + if (hasToolCalls || stopReason === 'tool_use') { + return 'tool_calls' } -} -interface BedrockVideoBlock { - video: { - format: BedrockVideoFormat - source: { bytes: string } | { s3Location: { uri: string; bucketOwner?: string } } + switch (stopReason) { + case 'max_tokens': + case 'model_context_window_exceeded': + return 'length' + case 'content_filtered': + case 'guardrail_intervened': + return 'content_filter' + case 'end_turn': + case 'stop_sequence': + case undefined: + default: + return 'stop' } } -interface BedrockDocumentBlock { - document: { - format: BedrockDocumentFormat - name: string - source: - | { bytes: string } - | { s3Location: { uri: string; bucketOwner?: string } } - | { text: string } +/** + * Maps Bedrock TokenUsage to TanStack AI usage format. + * + * @param usage - The Bedrock token usage from the metadata event + * @returns The normalized TanStack AI usage object + */ +function mapBedrockTokenUsage(usage: TokenUsage | undefined): { + promptTokens: number + completionTokens: number + totalTokens: number +} | undefined { + if (!usage) return undefined + + return { + promptTokens: usage.inputTokens ?? 0, + completionTokens: usage.outputTokens ?? 0, + totalTokens: usage.totalTokens ?? 0, } } -interface BedrockToolUseBlock { - toolUse: { - toolUseId: string - name: string - input: Record +function toUint8Array(base64: string): Uint8Array { + if (typeof Buffer !== 'undefined') { + return Uint8Array.from(Buffer.from(base64, 'base64')) } -} -interface BedrockToolResultBlock { - toolResult: { - toolUseId: string - content: Array + if (typeof atob !== 'undefined') { + const binary = atob(base64) + const bytes = new Uint8Array(binary.length) + for (let i = 0; i < binary.length; i++) { + bytes[i] = binary.charCodeAt(i) + } + return bytes } -} -type BedrockContentBlock = - | BedrockTextBlock - | BedrockImageBlock - | BedrockVideoBlock - | BedrockDocumentBlock - | BedrockToolUseBlock - | BedrockToolResultBlock - -interface BedrockMessage { - role: 'user' | 'assistant' - content: Array + throw new Error('Inline data sources require base64 decoding, which is not available in this environment') } -interface BedrockConverseInput { - messages: Array - system?: Array<{ text: string }> - inferenceConfig?: { - maxTokens?: number - temperature?: number - topP?: number - topK?: number - stopSequences?: Array - } - toolConfig?: { - tools?: Array<{ - toolSpec: { - name: string - description?: string - inputSchema: { json: Record } - } - }> - toolChoice?: { auto: object } | { any: object } | { tool: { name: string } } - } - additionalModelRequestFields?: Record - performanceConfig?: { - latency: 'standard' | 'optimized' - } - serviceTier?: { - type: 'priority' | 'default' | 'flex' | 'reserved' - } - requestMetadata?: Record -} - -interface BedrockStreamEvent { - messageStart?: { role: string } - contentBlockStart?: { - contentBlockIndex?: number - start?: { - toolUse?: { - toolUseId?: string - name?: string - } - } - } - contentBlockDelta?: { - contentBlockIndex?: number - delta?: { - text?: string - reasoningContent?: { text?: string } - toolUse?: { input?: string } - } - } - contentBlockStop?: { contentBlockIndex?: number } - messageStop?: { stopReason?: string } - metadata?: { - usage?: { - inputTokens?: number - outputTokens?: number - totalTokens?: number - cacheReadInputTokens?: number - cacheWriteInputTokens?: number - } - } - internalServerException?: { message?: string } - modelStreamErrorException?: { message?: string } - throttlingException?: { message?: string } - validationException?: { message?: string } -} +/** + * AWS credentials returned by a credential provider + */ +export type BedrockCredentials = AwsCredentialIdentity /** * Configuration options for the Bedrock adapter. @@ -275,7 +242,7 @@ export interface BedrockConfig { * } * ``` */ - credentialProvider?: () => Promise + credentialProvider?: AwsCredentialIdentityProvider /** * Custom base URL for Bedrock API. @@ -382,7 +349,7 @@ export class Bedrock extends BaseAdapter< const modelId = encodeURIComponent(options.model) const url = `${this._resolvedBaseURL}/model/${modelId}/converse` - const converseInput: BedrockConverseInput = { + const converseInput: BedrockConversePayload = { messages: [ { role: 'user', @@ -392,7 +359,6 @@ export class Bedrock extends BaseAdapter< system: [{ text: prompt }], inferenceConfig: { maxTokens: options.maxLength || 500, - temperature: 0.7, }, } @@ -407,23 +373,19 @@ export class Bedrock extends BaseAdapter< throw new Error(`Bedrock API error (${response.status}): ${errorText}`) } - const result = (await response.json()) as { - output: { message: { content: Array<{ text?: string }> } } - usage: { inputTokens: number; outputTokens: number; totalTokens: number } - } - - const summary = result.output.message.content - .map((block) => block.text || '') - .join('') + const result = (await response.json()) as ConverseResponse + const outputMessage = result.output?.message + const summary = outputMessage?.content?.map((block) => block.text || '').join('') ?? '' + const usage = mapBedrockTokenUsage(result.usage) return { id: this.generateId(), model: options.model, summary, - usage: { - promptTokens: result.usage.inputTokens, - completionTokens: result.usage.outputTokens, - totalTokens: result.usage.totalTokens, + usage: usage ?? { + promptTokens: 0, + completionTokens: 0, + totalTokens: 0, }, } } @@ -603,11 +565,14 @@ export class Bedrock extends BaseAdapter< private mapCommonOptionsToBedrock( options: ChatOptions, - ): BedrockConverseInput { + ): BedrockConverseStreamPayload { const { messages } = this.formatMessages(options.messages) const providerOptions = options.providerOptions - const inferenceConfig: BedrockConverseInput['inferenceConfig'] = {} + const inferenceConfig: Partial = {} + const additionalModelRequestFields: Record = { + ...(providerOptions?.additionalModelRequestFields ?? {}), + } if (options.options?.maxTokens != null) { inferenceConfig.maxTokens = options.options.maxTokens } @@ -621,18 +586,18 @@ export class Bedrock extends BaseAdapter< inferenceConfig.topP = options.options.topP } if (providerOptions?.topK != null) { - inferenceConfig.topK = providerOptions.topK + additionalModelRequestFields.topK = providerOptions.topK } if (providerOptions?.stopSequences != null) { inferenceConfig.stopSequences = providerOptions.stopSequences } - const systemMessages: Array<{ text: string }> = [] + const systemMessages: Array = [] if (options.systemPrompts?.length) { systemMessages.push({ text: options.systemPrompts.join('\n') }) } - const converseInput: BedrockConverseInput = { + const converseInput: BedrockConverseStreamPayload = { messages, ...(systemMessages.length > 0 && { system: systemMessages }), ...(Object.keys(inferenceConfig).length > 0 && { inferenceConfig }), @@ -643,33 +608,32 @@ export class Bedrock extends BaseAdapter< options.tools, options.model, ) - converseInput.toolConfig = { + + const toolConfig: ToolConfiguration = { tools: bedrockTools, } if (providerOptions?.toolChoice) { - converseInput.toolConfig.toolChoice = providerOptions.toolChoice + toolConfig.toolChoice = providerOptions.toolChoice } - } - if (providerOptions?.additionalModelRequestFields) { - converseInput.additionalModelRequestFields = - providerOptions.additionalModelRequestFields + converseInput.toolConfig = toolConfig } if (providerOptions?.reasoningConfig) { const reasoningConfig = providerOptions.reasoningConfig - converseInput.additionalModelRequestFields = { - ...converseInput.additionalModelRequestFields, - thinking: { - type: reasoningConfig.type, - ...(reasoningConfig.budgetTokens != null && { - budget_tokens: reasoningConfig.budgetTokens, - }), - }, + additionalModelRequestFields.thinking = { + type: reasoningConfig.type, + ...(reasoningConfig.budgetTokens != null && { + budget_tokens: reasoningConfig.budgetTokens, + }), } } + if (Object.keys(additionalModelRequestFields).length > 0) { + converseInput.additionalModelRequestFields = additionalModelRequestFields + } + if (providerOptions?.performanceConfig) { converseInput.performanceConfig = providerOptions.performanceConfig } @@ -693,7 +657,7 @@ export class Bedrock extends BaseAdapter< for (const message of messages) { if (message.role === 'tool' && message.toolCallId) { const lastMessage = bedrockMessages[bedrockMessages.length - 1] - const toolResultBlock: BedrockToolResultBlock = { + const toolResultBlock: BedrockContentBlock = { toolResult: { toolUseId: message.toolCallId, content: [ @@ -707,7 +671,7 @@ export class Bedrock extends BaseAdapter< }, } - if (lastMessage?.role === 'user') { + if (lastMessage?.role === 'user' && lastMessage.content) { lastMessage.content.push(toolResultBlock) } else { bedrockMessages.push({ @@ -730,14 +694,9 @@ export class Bedrock extends BaseAdapter< if (message.role === 'assistant' && message.toolCalls?.length) { for (const toolCall of message.toolCalls) { - let parsedInput: Record = {} - try { - parsedInput = toolCall.function.arguments - ? JSON.parse(toolCall.function.arguments) - : {} - } catch { - parsedInput = {} - } + const parsedInput = this.parseToolArguments( + toolCall.function.arguments, + ) bedrockContent.push({ toolUse: { toolUseId: toolCall.id, @@ -760,43 +719,91 @@ export class Bedrock extends BaseAdapter< } private convertContentPartToBedrock(part: ContentPart): BedrockContentBlock { + const DEFAULT_IMAGE_FORMAT: ImageFormat = 'jpeg' + const DEFAULT_VIDEO_FORMAT: VideoFormat = 'mp4' + const DEFAULT_DOCUMENT_FORMAT: DocumentFormat = 'pdf' + switch (part.type) { case 'text': return { text: part.content } case 'image': { const metadata = part.metadata as BedrockImageMetadata | undefined - const source = metadata?.s3Location - ? { s3Location: metadata.s3Location } - : { bytes: part.source.value } - return { - image: { - format: metadata?.format ?? 'jpeg', - source, - }, + const format = metadata?.format ?? DEFAULT_IMAGE_FORMAT + + if (metadata?.s3Location) { + return { + image: { + format, + source: { s3Location: metadata.s3Location }, + }, + } } + + if (part.source.type === 'data') { + return { + image: { + format, + source: { bytes: toUint8Array(part.source.value) }, + }, + } + } + + throw new Error('Bedrock only supports image sources as inline base64 data or S3 locations') } case 'video': { const metadata = part.metadata as BedrockVideoMetadata | undefined - const source = metadata?.s3Location - ? { s3Location: metadata.s3Location } - : { bytes: part.source.value } - return { - video: { - format: metadata?.format ?? 'mp4', - source, - }, + const format = metadata?.format ?? DEFAULT_VIDEO_FORMAT + + if (metadata?.s3Location) { + return { + video: { + format, + source: { s3Location: metadata.s3Location }, + }, + } + } + + if (part.source.type === 'data') { + return { + video: { + format, + source: { bytes: toUint8Array(part.source.value) }, + }, + } } + + throw new Error('Bedrock only supports video sources as inline base64 data or S3 locations') } case 'document': { const metadata = part.metadata as BedrockDocumentMetadata | undefined - const source = metadata?.s3Location - ? { s3Location: metadata.s3Location } - : { bytes: part.source.value } + const format = metadata?.format ?? DEFAULT_DOCUMENT_FORMAT + const name = metadata?.name ?? `document-${Date.now()}` + + if (metadata?.s3Location) { + return { + document: { + format, + name, + source: { s3Location: metadata.s3Location }, + }, + } + } + + if (part.source.type === 'data') { + return { + document: { + format, + name, + source: { bytes: toUint8Array(part.source.value) }, + }, + } + } + return { document: { - format: metadata?.format ?? 'pdf', - name: metadata?.name ?? `document-${Date.now()}`, - source, + format, + name, + source: { text: part.source.value }, }, } } @@ -813,6 +820,16 @@ export class Bedrock extends BaseAdapter< } } + private parseToolArguments(args?: string): DocumentType { + if (!args) return {} as DocumentType + + try { + return JSON.parse(args) as DocumentType + } catch { + return {} as DocumentType + } + } + private async *processBedrockStream( response: Response, model: string, @@ -825,12 +842,7 @@ export class Bedrock extends BaseAdapter< { id: string; name: string; input: string } >() let currentBlockIndex = -1 - let pendingFinishReason: - | 'stop' - | 'tool_calls' - | 'length' - | 'content_filter' - | null = null + let pendingFinishReason: FinishReason | null = null const reader = response.body?.getReader() if (!reader) { @@ -884,13 +896,13 @@ export class Bedrock extends BaseAdapter< } if (event.contentBlockStart) { - currentBlockIndex = - event.contentBlockStart.contentBlockIndex ?? 0 - if (event.contentBlockStart.start?.toolUse) { - const toolUse = event.contentBlockStart.start.toolUse + currentBlockIndex = event.contentBlockStart.contentBlockIndex ?? 0 + + const toolUseStart = event.contentBlockStart.start?.toolUse + if (toolUseStart) { toolCallMap.set(currentBlockIndex, { - id: toolUse.toolUseId || this.generateId(), - name: toolUse.name || '', + id: toolUseStart.toolUseId || this.generateId(), + name: toolUseStart.name || '', input: '', }) } @@ -933,8 +945,7 @@ export class Bedrock extends BaseAdapter< } if (event.contentBlockStop) { - const blockIndex = - event.contentBlockStop.contentBlockIndex ?? currentBlockIndex + const blockIndex = event.contentBlockStop.contentBlockIndex ?? currentBlockIndex const toolData = toolCallMap.get(blockIndex) if (toolData) { yield { @@ -956,42 +967,23 @@ export class Bedrock extends BaseAdapter< } if (event.messageStop) { - const stopReason = event.messageStop.stopReason - let finishReason: 'stop' | 'tool_calls' | 'length' | 'content_filter' = - 'stop' - - if (stopReason === 'tool_use' || toolCallMap.size > 0) { - finishReason = 'tool_calls' - } else if ( - stopReason === 'max_tokens' || - stopReason === 'model_context_window_exceeded' - ) { - finishReason = 'length' - } else if ( - stopReason === 'content_filtered' || - stopReason === 'guardrail_intervened' - ) { - finishReason = 'content_filter' - } - - pendingFinishReason = finishReason + pendingFinishReason = mapBedrockStopReason( + event.messageStop.stopReason, + toolCallMap.size > 0, + ) } if (event.metadata) { const finishReason = pendingFinishReason ?? 'stop' + const usage = mapBedrockTokenUsage(event.metadata.usage) + yield { type: 'done', id: this.generateId(), model, timestamp, finishReason, - usage: event.metadata.usage - ? { - promptTokens: event.metadata.usage.inputTokens ?? 0, - completionTokens: event.metadata.usage.outputTokens ?? 0, - totalTokens: event.metadata.usage.totalTokens ?? 0, - } - : undefined, + usage, } pendingFinishReason = null } @@ -1013,7 +1005,7 @@ export class Bedrock extends BaseAdapter< model, timestamp, error: { - message: errorObj?.message || 'Bedrock stream error', + message: errorObj.message || 'Bedrock stream error', }, } } @@ -1070,18 +1062,23 @@ export class Bedrock extends BaseAdapter< /** * Creates a Bedrock adapter with the provided configuration. * - * @param config - Bedrock configuration options + * Supports two calling patterns for flexibility: + * 1. `createBedrock(apiKey)` or `createBedrock(apiKey, config)` - Simple API key auth + * 2. `createBedrock(config)` - Full config object for SigV4 or advanced options + * + * @param apiKeyOrConfig - API key string or full configuration object + * @param config - Optional additional configuration when first arg is API key * @returns A configured Bedrock adapter instance * - * @example API Key Authentication + * @example Simple API Key (like OpenAI/Anthropic) * ```typescript - * const bedrockAdapter = createBedrock({ - * apiKey: 'your-bedrock-api-key', - * region: 'us-east-1' - * }); + * const bedrock = createBedrock('your-bedrock-api-key'); + * ``` * - * const ai = new AI({ - * adapters: { bedrock: bedrockAdapter } + * @example API Key with Region + * ```typescript + * const bedrock = createBedrock('your-bedrock-api-key', { + * region: 'us-east-1' * }); * ``` * @@ -1106,15 +1103,26 @@ export class Bedrock extends BaseAdapter< * }); * ``` */ -export function createBedrock(config?: BedrockConfig): Bedrock { - return new Bedrock(config ?? {}) +export function createBedrock( + apiKey: string, + config?: Omit, +): Bedrock +export function createBedrock(config?: BedrockConfig): Bedrock +export function createBedrock( + apiKeyOrConfig?: string | BedrockConfig, + maybeConfig?: Omit, +): Bedrock { + if (typeof apiKeyOrConfig === 'string') { + return new Bedrock({ apiKey: apiKeyOrConfig, ...(maybeConfig ?? {}) }) + } + return new Bedrock(apiKeyOrConfig ?? {}) } /** - * Creates a Bedrock adapter with automatic environment variable detection. + * Create a Bedrock adapter with automatic environment variable detection. * - * This is an alias for `createBedrock()` that provides a cleaner API. - * Authentication is automatically detected from environment variables: + * Authentication is automatically detected from environment variables. + * Throws an error if no valid authentication is configured. * * **Authentication (checked in order):** * 1. `AWS_BEARER_TOKEN_BEDROCK` - API key for Bearer token auth @@ -1131,6 +1139,7 @@ export function createBedrock(config?: BedrockConfig): Bedrock { * * @param config - Optional configuration to override environment defaults * @returns Configured Bedrock adapter instance + * @throws Error if no authentication credentials are found * * @example Basic Usage (relies on environment variables) * ```typescript @@ -1145,8 +1154,7 @@ export function createBedrock(config?: BedrockConfig): Bedrock { * const ai = new AI({ * adapters: { * bedrock: bedrock({ - * region: 'eu-central-1', - * baseURL: 'https://custom-endpoint.example.com' + * region: 'eu-central-1' * }) * } * }); diff --git a/packages/typescript/ai-bedrock/src/index.ts b/packages/typescript/ai-bedrock/src/index.ts index 35ce733e..9838e067 100644 --- a/packages/typescript/ai-bedrock/src/index.ts +++ b/packages/typescript/ai-bedrock/src/index.ts @@ -5,12 +5,7 @@ export { type BedrockConfig, type BedrockCredentials, } from './bedrock-adapter' -export { - isAnthropicModel, - isInferenceProfileId, - toInferenceProfileId, - type InferenceProfileRegion, -} from './model-meta' +export { BEDROCK_EMBEDDING_MODELS, BEDROCK_MODELS } from './model-meta' export type { BedrockChatModelProviderOptionsByName, BedrockModelInputModalitiesByName, @@ -41,4 +36,3 @@ export type { } from './message-types' export { convertToolsToProviderFormat } from './tools/tool-converter' -export type { BedrockToolSpec } from './tools/custom-tool' diff --git a/packages/typescript/ai-bedrock/src/message-types.ts b/packages/typescript/ai-bedrock/src/message-types.ts index 078f75ba..04a8d06a 100644 --- a/packages/typescript/ai-bedrock/src/message-types.ts +++ b/packages/typescript/ai-bedrock/src/message-types.ts @@ -1,128 +1,74 @@ /** * Bedrock-specific metadata types for multimodal content parts. - * These types extend the base ContentPart metadata with Bedrock-specific options. - * - * Bedrock supports various foundation models with different multimodal capabilities - * through the Converse API. * * @see https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html - * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_Converse.html */ +import type { + DocumentFormat, + ImageFormat, + S3Location, + VideoFormat, +} from '@aws-sdk/client-bedrock-runtime' + /** - * Supported image formats for Bedrock. - * * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ImageBlock.html */ -export type BedrockImageFormat = 'jpeg' | 'png' | 'gif' | 'webp' +export type BedrockImageFormat = ImageFormat /** - * Supported audio formats for Bedrock. - * Note: The Bedrock Converse API does not currently support audio input in ContentBlock. + * The Bedrock Converse API does not currently support audio input. */ export type BedrockAudioFormat = never /** - * Supported video formats for Bedrock. - * * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_VideoBlock.html */ -export type BedrockVideoFormat = - | 'mkv' - | 'mov' - | 'mp4' - | 'webm' - | 'flv' - | 'mpeg' - | 'mpg' - | 'wmv' - | 'three_gp' +export type BedrockVideoFormat = VideoFormat /** - * Supported document formats for Bedrock. - * * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_DocumentBlock.html */ -export type BedrockDocumentFormat = - | 'pdf' - | 'csv' - | 'doc' - | 'docx' - | 'xls' - | 'xlsx' - | 'html' - | 'txt' - | 'md' +export type BedrockDocumentFormat = DocumentFormat /** - * S3 location for media content. - * Use this to reference files stored in Amazon S3 instead of inline base64 data. - * * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_S3Location.html */ -export interface BedrockS3Location { - /** - * S3 URI of the file (e.g., "s3://bucket-name/path/to/file.jpg") - */ - uri: string - /** - * AWS account ID of the bucket owner (required for cross-account access) - */ - bucketOwner?: string -} +export type BedrockS3Location = S3Location /** - * Metadata for Bedrock image content parts. - * * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ImageBlock.html */ export interface BedrockImageMetadata { - /** - * The format of the image. - * Required for proper content processing. - */ format?: BedrockImageFormat /** * S3 location for the image. When provided, the image will be loaded from S3 - * instead of using inline base64 data. This is more efficient for large files. + * instead of using inline base64 data. */ s3Location?: BedrockS3Location } /** - * Metadata for Bedrock audio content parts. - * Note: The Bedrock Converse API does not currently support audio input in ContentBlock. + * The Bedrock Converse API does not currently support audio input. */ export interface BedrockAudioMetadata {} /** - * Metadata for Bedrock video content parts. - * * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_VideoBlock.html */ export interface BedrockVideoMetadata { - /** - * The format of the video. - * Required for proper content processing. - */ format?: BedrockVideoFormat /** * S3 location for the video. When provided, the video will be loaded from S3 - * instead of using inline base64 data. Recommended for video files. + * instead of using inline base64 data. */ s3Location?: BedrockS3Location } /** - * Metadata for Bedrock document content parts. - * * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_DocumentBlock.html */ export interface BedrockDocumentMetadata { - /** - * The format of the document. - * Required for proper content processing. - */ format?: BedrockDocumentFormat /** * S3 location for the document. When provided, the document will be loaded from S3 @@ -130,21 +76,18 @@ export interface BedrockDocumentMetadata { */ s3Location?: BedrockS3Location /** - * Optional name for the document (used for identification in responses). - * If not provided, a default name will be generated. + * Name for the document. If not provided, a default name will be generated. */ name?: string } /** * Metadata for Bedrock text content parts. - * Currently no specific metadata options for text in Bedrock. */ export interface BedrockTextMetadata {} /** * Map of modality types to their Bedrock-specific metadata types. - * Used for type inference when constructing multimodal messages. */ export interface BedrockMessageMetadataByModality { text: BedrockTextMetadata diff --git a/packages/typescript/ai-bedrock/src/model-meta.ts b/packages/typescript/ai-bedrock/src/model-meta.ts index 430969b4..01cad6fd 100644 --- a/packages/typescript/ai-bedrock/src/model-meta.ts +++ b/packages/typescript/ai-bedrock/src/model-meta.ts @@ -5,12 +5,15 @@ * * AWS Bedrock uses "inference profiles" to enable cross-region model invocation. * For newer Claude models (Claude 3.5 Sonnet v2, Claude 3.7 Sonnet, Claude 4 series), - * **inference profiles are required** - direct model IDs will return an error: + * **inference profiles are required** - direct model IDs will return an error. * - * ``` - * "Invocation of model ID anthropic.claude-3-5-sonnet-20241022-v2:0 with on-demand - * throughput isn't supported. Retry your request with the ID or ARN of an inference - * profile that contains this model." + * To use inference profiles, pass the full inference profile ID as the model: + * + * ```typescript + * await bedrock.chat({ + * model: 'us.anthropic.claude-sonnet-4-20250514-v1:0', + * messages: [...] + * }); * ``` * * ### Model ID Formats @@ -18,15 +21,9 @@ * | Format | Example | Use Case | * |--------|---------|----------| * | Direct | `anthropic.claude-3-haiku-20240307-v1:0` | Legacy models in single region | - * | US Profile | `us.anthropic.claude-3-5-sonnet-20241022-v2:0` | **Recommended** - US cross-region | + * | US Profile | `us.anthropic.claude-3-5-sonnet-20241022-v2:0` | US cross-region | * | EU Profile | `eu.anthropic.claude-3-5-sonnet-20241022-v2:0` | EU cross-region (GDPR compliance) | - * - * ### Utilities - * - * Use the exported helper functions: - * - `toInferenceProfileId(modelId, region?)` - Convert to inference profile - * - `isInferenceProfileId(modelId)` - Check if already an inference profile - * - `isAnthropicModel(modelId)` - Check if Anthropic model (any format) + * | APAC Profile | `apac.anthropic.claude-sonnet-4-20250514-v1:0` | Asia Pacific cross-region | * * @see https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html * @see https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles.html @@ -107,45 +104,6 @@ const US_NOVA_PREMIER = { }, } as const satisfies ModelMeta -const US_NOVA_PRO = { - name: 'Nova Pro (US)', - id: 'us.amazon.nova-pro-v1:0', - context_window: 300_000, - max_output_tokens: 5_000, - supports: { - input: ['text', 'image', 'video', 'document'], - output: ['text'], - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta - -const US_NOVA_MICRO = { - name: 'Nova Micro (US)', - id: 'us.amazon.nova-micro-v1:0', - context_window: 128_000, - max_output_tokens: 5_000, - supports: { - input: ['text'], - output: ['text'], - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta - -const US_NOVA_LITE = { - name: 'Nova Lite (US)', - id: 'us.amazon.nova-lite-v1:0', - context_window: 300_000, - max_output_tokens: 5_000, - supports: { - input: ['text', 'image', 'video'], - output: ['text'], - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta - const US_NOVA_2_LITE = { name: 'Nova 2 Lite', id: 'us.amazon.nova-2-lite-v1:0', @@ -345,164 +303,6 @@ const CLAUDE_OPUS_4_1 = { BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions > -const US_CLAUDE_3_HAIKU = { - name: 'Claude 3 Haiku (US)', - id: 'us.anthropic.claude-3-haiku-20240307-v1:0', - context_window: 200_000, - max_output_tokens: 4_096, - supports: { - input: ['text', 'image', 'document'], - output: ['text'], - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta - -const US_CLAUDE_3_SONNET = { - name: 'Claude 3 Sonnet (US)', - id: 'us.anthropic.claude-3-sonnet-20240229-v1:0', - context_window: 200_000, - max_output_tokens: 4_096, - supports: { - input: ['text', 'image', 'document'], - output: ['text'], - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta - -const US_CLAUDE_3_OPUS = { - name: 'Claude 3 Opus (US)', - id: 'us.anthropic.claude-3-opus-20240229-v1:0', - context_window: 200_000, - max_output_tokens: 4_096, - supports: { - input: ['text', 'image', 'document'], - output: ['text'], - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta - -const US_CLAUDE_3_5_HAIKU = { - name: 'Claude 3.5 Haiku (US)', - id: 'us.anthropic.claude-3-5-haiku-20241022-v1:0', - context_window: 200_000, - max_output_tokens: 8_192, - supports: { - input: ['text', 'image', 'document'], - output: ['text'], - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta - -const US_CLAUDE_3_5_SONNET = { - name: 'Claude 3.5 Sonnet (US)', - id: 'us.anthropic.claude-3-5-sonnet-20240620-v1:0', - context_window: 200_000, - max_output_tokens: 8_192, - supports: { - input: ['text', 'image', 'document'], - output: ['text'], - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta - -const US_CLAUDE_3_5_SONNET_V2 = { - name: 'Claude 3.5 Sonnet v2 (US)', - id: 'us.anthropic.claude-3-5-sonnet-20241022-v2:0', - context_window: 200_000, - max_output_tokens: 8_192, - supports: { - input: ['text', 'image', 'document'], - output: ['text'], - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta - -const US_CLAUDE_3_7_SONNET = { - name: 'Claude 3.7 Sonnet (US)', - id: 'us.anthropic.claude-3-7-sonnet-20250219-v1:0', - context_window: 200_000, - max_output_tokens: 64_000, - supports: { - input: ['text', 'image', 'document'], - output: ['text'], - reasoning: true, - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta< - BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions -> - -const US_CLAUDE_SONNET_4 = { - name: 'Claude Sonnet 4 (US)', - id: 'us.anthropic.claude-sonnet-4-20250514-v1:0', - context_window: 200_000, - max_output_tokens: 64_000, - supports: { - input: ['text', 'image', 'document'], - output: ['text'], - reasoning: true, - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta< - BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions -> - -const US_CLAUDE_SONNET_4_5 = { - name: 'Claude Sonnet 4.5 (US)', - id: 'us.anthropic.claude-sonnet-4-5-20250929-v1:0', - context_window: 200_000, - max_output_tokens: 64_000, - supports: { - input: ['text', 'image', 'document'], - output: ['text'], - reasoning: true, - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta< - BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions -> - -const US_CLAUDE_OPUS_4 = { - name: 'Claude Opus 4 (US)', - id: 'us.anthropic.claude-opus-4-20250514-v1:0', - context_window: 200_000, - max_output_tokens: 32_000, - supports: { - input: ['text', 'image', 'document'], - output: ['text'], - reasoning: true, - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta< - BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions -> - -const US_CLAUDE_OPUS_4_1 = { - name: 'Claude Opus 4.1 (US)', - id: 'us.anthropic.claude-opus-4-1-20250805-v1:0', - context_window: 200_000, - max_output_tokens: 64_000, - supports: { - input: ['text', 'image', 'document'], - output: ['text'], - reasoning: true, - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta< - BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions -> - const LLAMA_3_8B = { name: 'Llama 3 8B Instruct', id: 'meta.llama3-8b-instruct-v1:0', @@ -653,119 +453,6 @@ const LLAMA_4_MAVERICK = { }, } as const satisfies ModelMeta -const US_LLAMA_3_1_8B = { - name: 'Llama 3.1 8B Instruct (US)', - id: 'us.meta.llama3-1-8b-instruct-v1:0', - context_window: 128_000, - max_output_tokens: 2_048, - supports: { - input: ['text'], - output: ['text'], - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta - -const US_LLAMA_3_1_70B = { - name: 'Llama 3.1 70B Instruct (US)', - id: 'us.meta.llama3-1-70b-instruct-v1:0', - context_window: 128_000, - max_output_tokens: 2_048, - supports: { - input: ['text'], - output: ['text'], - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta - -const US_LLAMA_3_2_1B = { - name: 'Llama 3.2 1B Instruct (US)', - id: 'us.meta.llama3-2-1b-instruct-v1:0', - context_window: 128_000, - max_output_tokens: 2_048, - supports: { - input: ['text'], - output: ['text'], - streaming: true, - }, -} as const satisfies ModelMeta - -const US_LLAMA_3_2_3B = { - name: 'Llama 3.2 3B Instruct (US)', - id: 'us.meta.llama3-2-3b-instruct-v1:0', - context_window: 128_000, - max_output_tokens: 2_048, - supports: { - input: ['text'], - output: ['text'], - streaming: true, - }, -} as const satisfies ModelMeta - -const US_LLAMA_3_2_11B = { - name: 'Llama 3.2 11B Vision Instruct (US)', - id: 'us.meta.llama3-2-11b-instruct-v1:0', - context_window: 128_000, - max_output_tokens: 2_048, - supports: { - input: ['text', 'image'], - output: ['text'], - streaming: true, - }, -} as const satisfies ModelMeta - -const US_LLAMA_3_2_90B = { - name: 'Llama 3.2 90B Vision Instruct (US)', - id: 'us.meta.llama3-2-90b-instruct-v1:0', - context_window: 128_000, - max_output_tokens: 2_048, - supports: { - input: ['text', 'image'], - output: ['text'], - streaming: true, - }, -} as const satisfies ModelMeta - -const US_LLAMA_3_3_70B = { - name: 'Llama 3.3 70B Instruct (US)', - id: 'us.meta.llama3-3-70b-instruct-v1:0', - context_window: 128_000, - max_output_tokens: 2_048, - supports: { - input: ['text'], - output: ['text'], - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta - -const US_LLAMA_4_SCOUT = { - name: 'Llama 4 Scout 17B Instruct (US)', - id: 'us.meta.llama4-scout-17b-instruct-v1:0', - context_window: 3_500_000, - max_output_tokens: 16_384, - supports: { - input: ['text', 'image'], - output: ['text'], - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta - -const US_LLAMA_4_MAVERICK = { - name: 'Llama 4 Maverick 17B Instruct (US)', - id: 'us.meta.llama4-maverick-17b-instruct-v1:0', - context_window: 1_000_000, - max_output_tokens: 16_384, - supports: { - input: ['text', 'image'], - output: ['text'], - tools: true, - streaming: true, - }, -} as const satisfies ModelMeta - const MISTRAL_7B = { name: 'Mistral 7B Instruct', id: 'mistral.mistral-7b-instruct-v0:2', @@ -1025,19 +712,6 @@ const DEEPSEEK_R1 = { }, } as const satisfies ModelMeta -const US_DEEPSEEK_R1 = { - name: 'DeepSeek R1 (US)', - id: 'us.deepseek.r1-v1:0', - context_window: 64_000, - max_output_tokens: 8_192, - supports: { - input: ['text'], - output: ['text'], - reasoning: true, - streaming: true, - }, -} as const satisfies ModelMeta - const DEEPSEEK_V3 = { name: 'DeepSeek V3', id: 'deepseek.v3-v1:0', @@ -1342,65 +1016,11 @@ const TWELVELABS_MARENGO_EMBED = { }, } as const satisfies ModelMeta -/* const NOVA_CANVAS = { - name: 'Nova Canvas', - id: 'amazon.nova-canvas-v1:0', - supports: { - input: ['text', 'image'], - output: ['image'], - streaming: false, - }, -} as const satisfies ModelMeta - -const NOVA_REEL_V1_0 = { - name: 'Nova Reel', - id: 'amazon.nova-reel-v1:0', - supports: { - input: ['text', 'image'], - output: ['video'], - streaming: false, - }, -} as const satisfies ModelMeta - -const NOVA_REEL_V1_1 = { - name: 'Nova Reel', - id: 'amazon.nova-reel-v1:1', - supports: { - input: ['text', 'image'], - output: ['video'], - streaming: false, - }, -} as const satisfies ModelMeta - -const NOVA_SONIC = { - name: 'Nova Sonic', - id: 'amazon.nova-sonic-v1:0', - context_window: 300_000, - supports: { - input: ['audio'], - output: ['audio', 'text'], - streaming: true, - }, -} as const satisfies ModelMeta - -const RERANK_1_0 = { - name: 'Rerank 1.0', - id: 'amazon.rerank-v1:0', - supports: { - input: ['text'], - output: ['text'], - streaming: false, - }, -} as const satisfies ModelMeta */ - export const BEDROCK_MODELS = [ NOVA_LITE.id, NOVA_MICRO.id, NOVA_PRO.id, US_NOVA_PREMIER.id, - US_NOVA_PRO.id, - US_NOVA_MICRO.id, - US_NOVA_LITE.id, US_NOVA_2_LITE.id, US_NOVA_2_SONIC.id, CLAUDE_3_HAIKU.id, @@ -1415,17 +1035,6 @@ export const BEDROCK_MODELS = [ CLAUDE_SONNET_4_5.id, CLAUDE_OPUS_4.id, CLAUDE_OPUS_4_1.id, - US_CLAUDE_3_HAIKU.id, - US_CLAUDE_3_SONNET.id, - US_CLAUDE_3_OPUS.id, - US_CLAUDE_3_5_HAIKU.id, - US_CLAUDE_3_5_SONNET.id, - US_CLAUDE_3_5_SONNET_V2.id, - US_CLAUDE_3_7_SONNET.id, - US_CLAUDE_SONNET_4.id, - US_CLAUDE_SONNET_4_5.id, - US_CLAUDE_OPUS_4.id, - US_CLAUDE_OPUS_4_1.id, LLAMA_3_8B.id, LLAMA_3_70B.id, LLAMA_3_1_8B.id, @@ -1438,15 +1047,6 @@ export const BEDROCK_MODELS = [ LLAMA_3_3_70B.id, LLAMA_4_SCOUT.id, LLAMA_4_MAVERICK.id, - US_LLAMA_3_1_8B.id, - US_LLAMA_3_1_70B.id, - US_LLAMA_3_2_1B.id, - US_LLAMA_3_2_3B.id, - US_LLAMA_3_2_11B.id, - US_LLAMA_3_2_90B.id, - US_LLAMA_3_3_70B.id, - US_LLAMA_4_SCOUT.id, - US_LLAMA_4_MAVERICK.id, MISTRAL_7B.id, MIXTRAL_8X7B.id, MISTRAL_LARGE_2402.id, @@ -1461,7 +1061,6 @@ export const BEDROCK_MODELS = [ COHERE_COMMAND_R.id, COHERE_COMMAND_R_PLUS.id, DEEPSEEK_R1.id, - US_DEEPSEEK_R1.id, DEEPSEEK_V3.id, AI21_JAMBA_LARGE.id, AI21_JAMBA_MINI.id, @@ -1500,23 +1099,6 @@ export const BEDROCK_EMBEDDING_MODELS = [ TWELVELABS_MARENGO_EMBED.id, ] as const -/* const BEDROCK_IMAGE_MODELS = [ - NOVA_CANVAS.id, -] as const */ - -/* const BEDROCK_VIDEO_MODELS = [ - NOVA_REEL_V1_0.id, - NOVA_REEL_V1_1.id, -] as const */ - -/* const BEDROCK_RERANK_MODELS = [ - RERANK_1_0.id, -] as const */ - -/* const BEDROCK_SPEECH_MODELS = [ - NOVA_SONIC.id, -] as const */ - /** * Type-only map from Bedrock model name to its provider-specific options. * Options vary by model capabilities (reasoning, Anthropic-specific features). @@ -1526,9 +1108,6 @@ export type BedrockChatModelProviderOptionsByName = { [NOVA_MICRO.id]: BedrockProviderOptions [NOVA_PRO.id]: BedrockProviderOptions [US_NOVA_PREMIER.id]: BedrockProviderOptions & BedrockReasoningEffortOptions - [US_NOVA_PRO.id]: BedrockProviderOptions - [US_NOVA_MICRO.id]: BedrockProviderOptions - [US_NOVA_LITE.id]: BedrockProviderOptions [US_NOVA_2_LITE.id]: BedrockProviderOptions & BedrockReasoningEffortOptions [US_NOVA_2_SONIC.id]: BedrockProviderOptions [CLAUDE_3_HAIKU.id]: BedrockProviderOptions & BedrockAnthropicOptions @@ -1555,27 +1134,6 @@ export type BedrockChatModelProviderOptionsByName = { [CLAUDE_OPUS_4_1.id]: BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions - [US_CLAUDE_3_HAIKU.id]: BedrockProviderOptions & BedrockAnthropicOptions - [US_CLAUDE_3_SONNET.id]: BedrockProviderOptions & BedrockAnthropicOptions - [US_CLAUDE_3_OPUS.id]: BedrockProviderOptions & BedrockAnthropicOptions - [US_CLAUDE_3_5_HAIKU.id]: BedrockProviderOptions & BedrockAnthropicOptions - [US_CLAUDE_3_5_SONNET.id]: BedrockProviderOptions & BedrockAnthropicOptions - [US_CLAUDE_3_5_SONNET_V2.id]: BedrockProviderOptions & BedrockAnthropicOptions - [US_CLAUDE_3_7_SONNET.id]: BedrockProviderOptions & - BedrockAnthropicOptions & - BedrockAnthropicReasoningOptions - [US_CLAUDE_SONNET_4.id]: BedrockProviderOptions & - BedrockAnthropicOptions & - BedrockAnthropicReasoningOptions - [US_CLAUDE_SONNET_4_5.id]: BedrockProviderOptions & - BedrockAnthropicOptions & - BedrockAnthropicReasoningOptions - [US_CLAUDE_OPUS_4.id]: BedrockProviderOptions & - BedrockAnthropicOptions & - BedrockAnthropicReasoningOptions - [US_CLAUDE_OPUS_4_1.id]: BedrockProviderOptions & - BedrockAnthropicOptions & - BedrockAnthropicReasoningOptions [LLAMA_3_8B.id]: BedrockProviderOptions [LLAMA_3_70B.id]: BedrockProviderOptions [LLAMA_3_1_8B.id]: BedrockProviderOptions @@ -1588,15 +1146,6 @@ export type BedrockChatModelProviderOptionsByName = { [LLAMA_3_3_70B.id]: BedrockProviderOptions [LLAMA_4_SCOUT.id]: BedrockProviderOptions [LLAMA_4_MAVERICK.id]: BedrockProviderOptions - [US_LLAMA_3_1_8B.id]: BedrockProviderOptions - [US_LLAMA_3_1_70B.id]: BedrockProviderOptions - [US_LLAMA_3_2_1B.id]: BedrockProviderOptions - [US_LLAMA_3_2_3B.id]: BedrockProviderOptions - [US_LLAMA_3_2_11B.id]: BedrockProviderOptions - [US_LLAMA_3_2_90B.id]: BedrockProviderOptions - [US_LLAMA_3_3_70B.id]: BedrockProviderOptions - [US_LLAMA_4_SCOUT.id]: BedrockProviderOptions - [US_LLAMA_4_MAVERICK.id]: BedrockProviderOptions [MISTRAL_7B.id]: BedrockProviderOptions [MIXTRAL_8X7B.id]: BedrockProviderOptions [MISTRAL_LARGE_2402.id]: BedrockProviderOptions @@ -1611,7 +1160,6 @@ export type BedrockChatModelProviderOptionsByName = { [COHERE_COMMAND_R.id]: BedrockProviderOptions [COHERE_COMMAND_R_PLUS.id]: BedrockProviderOptions [DEEPSEEK_R1.id]: BedrockProviderOptions & BedrockReasoningEffortOptions - [US_DEEPSEEK_R1.id]: BedrockProviderOptions & BedrockReasoningEffortOptions [DEEPSEEK_V3.id]: BedrockProviderOptions [AI21_JAMBA_LARGE.id]: BedrockProviderOptions [AI21_JAMBA_MINI.id]: BedrockProviderOptions @@ -1650,9 +1198,6 @@ export type BedrockModelInputModalitiesByName = { [NOVA_MICRO.id]: typeof NOVA_MICRO.supports.input [NOVA_PRO.id]: typeof NOVA_PRO.supports.input [US_NOVA_PREMIER.id]: typeof US_NOVA_PREMIER.supports.input - [US_NOVA_PRO.id]: typeof US_NOVA_PRO.supports.input - [US_NOVA_MICRO.id]: typeof US_NOVA_MICRO.supports.input - [US_NOVA_LITE.id]: typeof US_NOVA_LITE.supports.input [US_NOVA_2_LITE.id]: typeof US_NOVA_2_LITE.supports.input [US_NOVA_2_SONIC.id]: typeof US_NOVA_2_SONIC.supports.input [CLAUDE_3_HAIKU.id]: typeof CLAUDE_3_HAIKU.supports.input @@ -1667,17 +1212,6 @@ export type BedrockModelInputModalitiesByName = { [CLAUDE_SONNET_4_5.id]: typeof CLAUDE_SONNET_4_5.supports.input [CLAUDE_OPUS_4.id]: typeof CLAUDE_OPUS_4.supports.input [CLAUDE_OPUS_4_1.id]: typeof CLAUDE_OPUS_4_1.supports.input - [US_CLAUDE_3_HAIKU.id]: typeof US_CLAUDE_3_HAIKU.supports.input - [US_CLAUDE_3_SONNET.id]: typeof US_CLAUDE_3_SONNET.supports.input - [US_CLAUDE_3_OPUS.id]: typeof US_CLAUDE_3_OPUS.supports.input - [US_CLAUDE_3_5_HAIKU.id]: typeof US_CLAUDE_3_5_HAIKU.supports.input - [US_CLAUDE_3_5_SONNET.id]: typeof US_CLAUDE_3_5_SONNET.supports.input - [US_CLAUDE_3_5_SONNET_V2.id]: typeof US_CLAUDE_3_5_SONNET_V2.supports.input - [US_CLAUDE_3_7_SONNET.id]: typeof US_CLAUDE_3_7_SONNET.supports.input - [US_CLAUDE_SONNET_4.id]: typeof US_CLAUDE_SONNET_4.supports.input - [US_CLAUDE_SONNET_4_5.id]: typeof US_CLAUDE_SONNET_4_5.supports.input - [US_CLAUDE_OPUS_4.id]: typeof US_CLAUDE_OPUS_4.supports.input - [US_CLAUDE_OPUS_4_1.id]: typeof US_CLAUDE_OPUS_4_1.supports.input [LLAMA_3_8B.id]: typeof LLAMA_3_8B.supports.input [LLAMA_3_70B.id]: typeof LLAMA_3_70B.supports.input [LLAMA_3_1_8B.id]: typeof LLAMA_3_1_8B.supports.input @@ -1690,15 +1224,6 @@ export type BedrockModelInputModalitiesByName = { [LLAMA_3_3_70B.id]: typeof LLAMA_3_3_70B.supports.input [LLAMA_4_SCOUT.id]: typeof LLAMA_4_SCOUT.supports.input [LLAMA_4_MAVERICK.id]: typeof LLAMA_4_MAVERICK.supports.input - [US_LLAMA_3_1_8B.id]: typeof US_LLAMA_3_1_8B.supports.input - [US_LLAMA_3_1_70B.id]: typeof US_LLAMA_3_1_70B.supports.input - [US_LLAMA_3_2_1B.id]: typeof US_LLAMA_3_2_1B.supports.input - [US_LLAMA_3_2_3B.id]: typeof US_LLAMA_3_2_3B.supports.input - [US_LLAMA_3_2_11B.id]: typeof US_LLAMA_3_2_11B.supports.input - [US_LLAMA_3_2_90B.id]: typeof US_LLAMA_3_2_90B.supports.input - [US_LLAMA_3_3_70B.id]: typeof US_LLAMA_3_3_70B.supports.input - [US_LLAMA_4_SCOUT.id]: typeof US_LLAMA_4_SCOUT.supports.input - [US_LLAMA_4_MAVERICK.id]: typeof US_LLAMA_4_MAVERICK.supports.input [MISTRAL_7B.id]: typeof MISTRAL_7B.supports.input [MIXTRAL_8X7B.id]: typeof MIXTRAL_8X7B.supports.input [MISTRAL_LARGE_2402.id]: typeof MISTRAL_LARGE_2402.supports.input @@ -1713,7 +1238,6 @@ export type BedrockModelInputModalitiesByName = { [COHERE_COMMAND_R.id]: typeof COHERE_COMMAND_R.supports.input [COHERE_COMMAND_R_PLUS.id]: typeof COHERE_COMMAND_R_PLUS.supports.input [DEEPSEEK_R1.id]: typeof DEEPSEEK_R1.supports.input - [US_DEEPSEEK_R1.id]: typeof US_DEEPSEEK_R1.supports.input [DEEPSEEK_V3.id]: typeof DEEPSEEK_V3.supports.input [AI21_JAMBA_LARGE.id]: typeof AI21_JAMBA_LARGE.supports.input [AI21_JAMBA_MINI.id]: typeof AI21_JAMBA_MINI.supports.input @@ -1741,90 +1265,4 @@ export type BedrockModelInputModalitiesByName = { [QWEN_3_VL_235B.id]: typeof QWEN_3_VL_235B.supports.input } -/** - * Inference Profile Region type for cross-region inference - * @see https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles.html - */ -export type InferenceProfileRegion = 'us' | 'eu' -/** - * Converts a direct Anthropic model ID to an inference profile ID. - * - * AWS Bedrock requires inference profiles for newer Claude models (Claude 3.5 Sonnet v2 and later). - * Direct model IDs like `anthropic.claude-3-5-sonnet-20241022-v2:0` will not work for on-demand - * invocation with these models. Use this helper to convert to the appropriate inference profile. - * - * @param modelId - The model ID (can be direct or already an inference profile) - * @param region - The inference profile region ('us' or 'eu'). Defaults to 'us'. - * @returns The inference profile model ID - * - * @example - * ```typescript - * // Convert direct model ID to US inference profile - * toInferenceProfileId('anthropic.claude-3-5-sonnet-20241022-v2:0') - * // Returns: 'us.anthropic.claude-3-5-sonnet-20241022-v2:0' - * - * // Convert to EU inference profile - * toInferenceProfileId('anthropic.claude-3-5-sonnet-20241022-v2:0', 'eu') - * // Returns: 'eu.anthropic.claude-3-5-sonnet-20241022-v2:0' - * - * // Already an inference profile - returns unchanged - * toInferenceProfileId('us.anthropic.claude-3-5-sonnet-20241022-v2:0') - * // Returns: 'us.anthropic.claude-3-5-sonnet-20241022-v2:0' - * ``` - * - * @see https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-support.html - */ -export function toInferenceProfileId( - modelId: string, - region: InferenceProfileRegion = 'us', -): string { - if ( - modelId.startsWith('us.') || - modelId.startsWith('eu.') || - !modelId.startsWith('anthropic.') - ) { - return modelId - } - return `${region}.${modelId}` -} - -/** - * Checks if a model ID is an Anthropic model (direct or inference profile) - * - * @param modelId - The model ID to check - * @returns true if the model ID is for an Anthropic model - * - * @example - * ```typescript - * isAnthropicModel('anthropic.claude-3-5-sonnet-20241022-v2:0') // true - * isAnthropicModel('us.anthropic.claude-3-5-sonnet-20241022-v2:0') // true - * isAnthropicModel('eu.anthropic.claude-3-haiku-20240307-v1:0') // true - * isAnthropicModel('amazon.nova-lite-v1:0') // false - * ``` - */ -export function isAnthropicModel(modelId: string): boolean { - return ( - modelId.startsWith('anthropic.') || - modelId.startsWith('us.anthropic.') || - modelId.startsWith('eu.anthropic.') - ) -} - -/** - * Checks if a model ID uses an inference profile format - * - * @param modelId - The model ID to check - * @returns true if the model ID uses an inference profile (has us. or eu. prefix) - * - * @example - * ```typescript - * isInferenceProfileId('us.anthropic.claude-3-5-sonnet-20241022-v2:0') // true - * isInferenceProfileId('eu.anthropic.claude-3-haiku-20240307-v1:0') // true - * isInferenceProfileId('anthropic.claude-3-5-sonnet-20241022-v2:0') // false - * isInferenceProfileId('us.amazon.nova-premier-v1:0') // true - * ``` - */ -export function isInferenceProfileId(modelId: string): boolean { - return modelId.startsWith('us.') || modelId.startsWith('eu.') -} diff --git a/packages/typescript/ai-bedrock/src/text/text-provider-options.ts b/packages/typescript/ai-bedrock/src/text/text-provider-options.ts index 5259c517..db113d1f 100644 --- a/packages/typescript/ai-bedrock/src/text/text-provider-options.ts +++ b/packages/typescript/ai-bedrock/src/text/text-provider-options.ts @@ -1,25 +1,21 @@ +import type { + PerformanceConfigLatency, + ServiceTierType, + ToolChoice, +} from '@aws-sdk/client-bedrock-runtime' +import type { DocumentType } from '@smithy/types' + /** * Bedrock provider options interfaces * Split by feature for per-model type-safety * + * Note: Common options (maxTokens, temperature, topP) are passed via ChatOptions.options, + * not via providerOptions. These interfaces only contain Bedrock-specific options. + * * @see https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference.html */ export interface BedrockBaseOptions { - /** - * The maximum number of tokens to generate in the response. - */ - maxTokens?: number - /** - * Controls randomness in the output. Higher values produce more random results. - * Range: 0.0 to 1.0 - */ - temperature?: number - /** - * Nucleus sampling parameter. Only consider tokens with cumulative probability up to this value. - * Range: 0.0 to 1.0 - */ - topP?: number /** * Only sample from the top K options for each subsequent token. * Not all models support this parameter. @@ -36,7 +32,7 @@ export interface BedrockAdditionalFieldsOptions { * Escape hatch for provider-specific fields not exposed by the Converse API. * Use this to pass model-specific parameters directly. */ - additionalModelRequestFields?: Record + additionalModelRequestFields?: Record } export interface BedrockPerformanceOptions { @@ -54,7 +50,7 @@ export interface BedrockPerformanceOptions { * @see https://docs.aws.amazon.com/bedrock/latest/userguide/latency-optimized-inference.html */ performanceConfig?: { - latency: 'standard' | 'optimized' + latency: PerformanceConfigLatency } } @@ -70,7 +66,7 @@ export interface BedrockServiceTierOptions { * @see https://docs.aws.amazon.com/bedrock/latest/userguide/service-tiers.html */ serviceTier?: { - type: 'priority' | 'default' | 'flex' | 'reserved' + type: ServiceTierType } } @@ -117,7 +113,7 @@ export interface BedrockToolChoiceOptions { * * @see https://docs.aws.amazon.com/bedrock/latest/APIReference/API_runtime_ToolChoice.html */ - toolChoice?: { auto: object } | { any: object } | { tool: { name: string } } + toolChoice?: ToolChoice } export interface BedrockAnthropicReasoningOptions { diff --git a/packages/typescript/ai-bedrock/src/tools/anthropic-bash-tool.ts b/packages/typescript/ai-bedrock/src/tools/anthropic-bash-tool.ts index 087c9ee8..7508cbc4 100644 --- a/packages/typescript/ai-bedrock/src/tools/anthropic-bash-tool.ts +++ b/packages/typescript/ai-bedrock/src/tools/anthropic-bash-tool.ts @@ -1,5 +1,6 @@ -import type { Tool } from '@tanstack/ai' -import type { BedrockToolSpec } from './custom-tool' +import type { Tool as AiTool } from '@tanstack/ai' +import type { Tool } from '@aws-sdk/client-bedrock-runtime' +import type { DocumentType } from '@smithy/types' const BASH_INPUT_SCHEMA = { type: 'object', @@ -10,12 +11,12 @@ const BASH_INPUT_SCHEMA = { required: ['command'], } as const -export function convertBashToolToAdapterFormat(tool: Tool): BedrockToolSpec { +export function convertBashToolToAdapterFormat(tool: AiTool): Tool { return { toolSpec: { name: tool.name, inputSchema: { - json: BASH_INPUT_SCHEMA as unknown as Record, + json: BASH_INPUT_SCHEMA as unknown as DocumentType, }, }, } diff --git a/packages/typescript/ai-bedrock/src/tools/anthropic-code-execution-tool.ts b/packages/typescript/ai-bedrock/src/tools/anthropic-code-execution-tool.ts index f3e56057..27fe9a2b 100644 --- a/packages/typescript/ai-bedrock/src/tools/anthropic-code-execution-tool.ts +++ b/packages/typescript/ai-bedrock/src/tools/anthropic-code-execution-tool.ts @@ -1,5 +1,6 @@ -import type { Tool } from '@tanstack/ai' -import type { BedrockToolSpec } from './custom-tool' +import type { Tool as AiTool } from '@tanstack/ai' +import type { Tool } from '@aws-sdk/client-bedrock-runtime' +import type { DocumentType } from '@smithy/types' const CODE_EXECUTION_INPUT_SCHEMA_20250522 = { type: 'object', @@ -35,8 +36,8 @@ const CODE_EXECUTION_INPUT_SCHEMA_20250825 = { } as const export function convertCodeExecutionToolToAdapterFormat( - tool: Tool, -): BedrockToolSpec { + tool: AiTool, +): Tool { const metadata = tool.metadata as { type?: string } | undefined const toolType = metadata?.type @@ -49,7 +50,7 @@ export function convertCodeExecutionToolToAdapterFormat( toolSpec: { name: tool.name, inputSchema: { - json: schema as unknown as Record, + json: schema as unknown as DocumentType, }, }, } diff --git a/packages/typescript/ai-bedrock/src/tools/anthropic-computer-use-tool.ts b/packages/typescript/ai-bedrock/src/tools/anthropic-computer-use-tool.ts index edbc15c5..e5f870c6 100644 --- a/packages/typescript/ai-bedrock/src/tools/anthropic-computer-use-tool.ts +++ b/packages/typescript/ai-bedrock/src/tools/anthropic-computer-use-tool.ts @@ -1,5 +1,6 @@ -import type { Tool } from '@tanstack/ai' -import type { BedrockToolSpec } from './custom-tool' +import type { Tool as AiTool } from '@tanstack/ai' +import type { Tool } from '@aws-sdk/client-bedrock-runtime' +import type { DocumentType } from '@smithy/types' const COMPUTER_USE_INPUT_SCHEMA = { type: 'object', @@ -45,13 +46,13 @@ const COMPUTER_USE_INPUT_SCHEMA = { } as const export function convertComputerUseToolToAdapterFormat( - tool: Tool, -): BedrockToolSpec { + tool: AiTool, +): Tool { return { toolSpec: { name: tool.name, inputSchema: { - json: COMPUTER_USE_INPUT_SCHEMA as unknown as Record, + json: COMPUTER_USE_INPUT_SCHEMA as unknown as DocumentType, }, }, } diff --git a/packages/typescript/ai-bedrock/src/tools/anthropic-memory-tool.ts b/packages/typescript/ai-bedrock/src/tools/anthropic-memory-tool.ts index 185cc056..40bfdb64 100644 --- a/packages/typescript/ai-bedrock/src/tools/anthropic-memory-tool.ts +++ b/packages/typescript/ai-bedrock/src/tools/anthropic-memory-tool.ts @@ -1,5 +1,6 @@ -import type { Tool } from '@tanstack/ai' -import type { BedrockToolSpec } from './custom-tool' +import type { Tool as AiTool } from '@tanstack/ai' +import type { Tool } from '@aws-sdk/client-bedrock-runtime' +import type { DocumentType } from '@smithy/types' const MEMORY_INPUT_SCHEMA = { oneOf: [ @@ -66,12 +67,12 @@ const MEMORY_INPUT_SCHEMA = { ], } as const -export function convertMemoryToolToAdapterFormat(tool: Tool): BedrockToolSpec { +export function convertMemoryToolToAdapterFormat(tool: AiTool): Tool { return { toolSpec: { name: tool.name, inputSchema: { - json: MEMORY_INPUT_SCHEMA as unknown as Record, + json: MEMORY_INPUT_SCHEMA as unknown as DocumentType, }, }, } diff --git a/packages/typescript/ai-bedrock/src/tools/anthropic-text-editor-tool.ts b/packages/typescript/ai-bedrock/src/tools/anthropic-text-editor-tool.ts index 6e838d08..73ef1d16 100644 --- a/packages/typescript/ai-bedrock/src/tools/anthropic-text-editor-tool.ts +++ b/packages/typescript/ai-bedrock/src/tools/anthropic-text-editor-tool.ts @@ -1,5 +1,6 @@ -import type { Tool } from '@tanstack/ai' -import type { BedrockToolSpec } from './custom-tool' +import type { Tool as AiTool } from '@tanstack/ai' +import type { Tool } from '@aws-sdk/client-bedrock-runtime' +import type { DocumentType } from '@smithy/types' const TEXT_EDITOR_INPUT_SCHEMA = { type: 'object', @@ -22,13 +23,13 @@ const TEXT_EDITOR_INPUT_SCHEMA = { } as const export function convertTextEditorToolToAdapterFormat( - tool: Tool, -): BedrockToolSpec { + tool: AiTool, +): Tool { return { toolSpec: { name: tool.name, inputSchema: { - json: TEXT_EDITOR_INPUT_SCHEMA as unknown as Record, + json: TEXT_EDITOR_INPUT_SCHEMA as unknown as DocumentType, }, }, } diff --git a/packages/typescript/ai-bedrock/src/tools/anthropic-web-fetch-tool.ts b/packages/typescript/ai-bedrock/src/tools/anthropic-web-fetch-tool.ts index e60fabd3..5dc2ab5e 100644 --- a/packages/typescript/ai-bedrock/src/tools/anthropic-web-fetch-tool.ts +++ b/packages/typescript/ai-bedrock/src/tools/anthropic-web-fetch-tool.ts @@ -1,5 +1,6 @@ -import type { Tool } from '@tanstack/ai' -import type { BedrockToolSpec } from './custom-tool' +import type { Tool as AiTool } from '@tanstack/ai' +import type { Tool } from '@aws-sdk/client-bedrock-runtime' +import type { DocumentType } from '@smithy/types' const WEB_FETCH_INPUT_SCHEMA = { type: 'object', @@ -10,13 +11,13 @@ const WEB_FETCH_INPUT_SCHEMA = { } as const export function convertWebFetchToolToAdapterFormat( - tool: Tool, -): BedrockToolSpec { + tool: AiTool, +): Tool { return { toolSpec: { name: tool.name, inputSchema: { - json: WEB_FETCH_INPUT_SCHEMA as unknown as Record, + json: WEB_FETCH_INPUT_SCHEMA as unknown as DocumentType, }, }, } diff --git a/packages/typescript/ai-bedrock/src/tools/anthropic-web-search-tool.ts b/packages/typescript/ai-bedrock/src/tools/anthropic-web-search-tool.ts index b87c7e33..e13d76c9 100644 --- a/packages/typescript/ai-bedrock/src/tools/anthropic-web-search-tool.ts +++ b/packages/typescript/ai-bedrock/src/tools/anthropic-web-search-tool.ts @@ -1,9 +1,9 @@ -import type { Tool } from '@tanstack/ai' -import type { BedrockToolSpec } from './custom-tool' +import type { Tool as AiTool } from '@tanstack/ai' +import type { Tool } from '@aws-sdk/client-bedrock-runtime' export function convertWebSearchToolToAdapterFormat( - _tool: Tool, -): BedrockToolSpec { + _tool: AiTool, +): Tool { throw new Error( 'The web_search tool is not supported on Amazon Bedrock. ' + 'Please remove this tool from your configuration.', diff --git a/packages/typescript/ai-bedrock/src/tools/custom-tool.ts b/packages/typescript/ai-bedrock/src/tools/custom-tool.ts index 72f30d41..88c15eb5 100644 --- a/packages/typescript/ai-bedrock/src/tools/custom-tool.ts +++ b/packages/typescript/ai-bedrock/src/tools/custom-tool.ts @@ -1,15 +1,9 @@ import { convertZodToJsonSchema } from '@tanstack/ai' -import type { Tool } from '@tanstack/ai' +import type { Tool as AiTool } from '@tanstack/ai' +import type { Tool } from '@aws-sdk/client-bedrock-runtime' +import type { DocumentType } from '@smithy/types' -export interface BedrockToolSpec { - toolSpec: { - name: string - description?: string - inputSchema: { json: Record } - } -} - -export function convertCustomToolToAdapterFormat(tool: Tool): BedrockToolSpec { +export function convertCustomToolToAdapterFormat(tool: AiTool): Tool { const jsonSchema = convertZodToJsonSchema(tool.inputSchema) return { @@ -17,7 +11,7 @@ export function convertCustomToolToAdapterFormat(tool: Tool): BedrockToolSpec { name: tool.name, ...(tool.description && { description: tool.description }), inputSchema: { - json: jsonSchema || { type: 'object', properties: {} }, + json: (jsonSchema || { type: 'object', properties: {} }) as DocumentType, }, }, } diff --git a/packages/typescript/ai-bedrock/src/tools/index.ts b/packages/typescript/ai-bedrock/src/tools/index.ts index c83a7383..41f83e85 100644 --- a/packages/typescript/ai-bedrock/src/tools/index.ts +++ b/packages/typescript/ai-bedrock/src/tools/index.ts @@ -1,2 +1 @@ -export type { BedrockToolSpec } from './custom-tool' export { convertToolsToProviderFormat } from './tool-converter' diff --git a/packages/typescript/ai-bedrock/src/tools/tool-converter.ts b/packages/typescript/ai-bedrock/src/tools/tool-converter.ts index bf1d3098..1135f322 100644 --- a/packages/typescript/ai-bedrock/src/tools/tool-converter.ts +++ b/packages/typescript/ai-bedrock/src/tools/tool-converter.ts @@ -6,9 +6,8 @@ import { convertTextEditorToolToAdapterFormat } from './anthropic-text-editor-to import { convertWebFetchToolToAdapterFormat } from './anthropic-web-fetch-tool' import { convertWebSearchToolToAdapterFormat } from './anthropic-web-search-tool' import { convertCustomToolToAdapterFormat } from './custom-tool' -import { isAnthropicModel } from '../model-meta' -import type { Tool } from '@tanstack/ai' -import type { BedrockToolSpec } from './custom-tool' +import type { Tool } from '@aws-sdk/client-bedrock-runtime' +import type { Tool as AiTool } from '@tanstack/ai' /** * Converts standard Tool format to Bedrock-specific tool format @@ -35,10 +34,10 @@ import type { BedrockToolSpec } from './custom-tool' * ``` */ export function convertToolsToProviderFormat( - tools: Array, + tools: Array, modelId: string, -): Array { - const isAnthropic = isAnthropicModel(modelId) +): Array { + const isAnthropic = modelId.includes('anthropic.') return tools.map((tool) => { const name = tool.name diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c0c4a417..bcf476d5 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -195,6 +195,9 @@ importers: '@tanstack/ai-anthropic': specifier: workspace:* version: link:../../packages/typescript/ai-anthropic + '@tanstack/ai-bedrock': + specifier: workspace:* + version: link:../../packages/typescript/ai-bedrock '@tanstack/ai-client': specifier: workspace:* version: link:../../packages/typescript/ai-client @@ -215,7 +218,7 @@ importers: version: link:../../packages/typescript/ai-react-ui '@tanstack/nitro-v2-vite-plugin': specifier: ^1.139.0 - version: 1.139.0(rolldown@1.0.0-beta.53)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + version: 1.139.0(aws4fetch@1.0.20)(rolldown@1.0.0-beta.53)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) '@tanstack/react-devtools': specifier: ^0.8.2 version: 0.8.2(@types/react-dom@19.2.3(@types/react@19.2.7))(@types/react@19.2.7)(csstype@3.2.3)(react-dom@19.2.0(react@19.2.0))(react@19.2.0)(solid-js@1.9.10) @@ -351,7 +354,7 @@ importers: version: link:../../packages/typescript/ai-solid-ui '@tanstack/nitro-v2-vite-plugin': specifier: ^1.139.0 - version: 1.139.0(rolldown@1.0.0-beta.53)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + version: 1.139.0(aws4fetch@1.0.20)(rolldown@1.0.0-beta.53)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) '@tanstack/router-plugin': specifier: ^1.139.7 version: 1.139.10(@tanstack/react-router@1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0))(vite-plugin-solid@2.11.10(@testing-library/jest-dom@6.9.1)(solid-js@1.9.10)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)))(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) @@ -556,6 +559,34 @@ importers: specifier: ^4.1.13 version: 4.1.13 + packages/typescript/ai-bedrock: + dependencies: + '@smithy/eventstream-codec': + specifier: ^4.2.5 + version: 4.2.5 + '@smithy/util-utf8': + specifier: ^4.2.0 + version: 4.2.0 + '@tanstack/ai': + specifier: workspace:* + version: link:../ai + aws4fetch: + specifier: ^1.0.20 + version: 1.0.20 + devDependencies: + '@aws-sdk/client-bedrock': + specifier: ^3.947.0 + version: 3.947.0 + '@aws-sdk/client-bedrock-runtime': + specifier: ^3.947.0 + version: 3.947.0 + '@vitest/coverage-v8': + specifier: 4.0.14 + version: 4.0.14(vitest@4.0.14(@types/node@24.10.1)(happy-dom@20.0.10)(jiti@2.6.1)(jsdom@27.2.0(postcss@8.5.6))(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + vite: + specifier: ^7.2.4 + version: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) + packages/typescript/ai-client: dependencies: '@tanstack/ai': @@ -953,7 +984,7 @@ importers: version: link:../../ai-react '@tanstack/nitro-v2-vite-plugin': specifier: ^1.139.0 - version: 1.139.0(rolldown@1.0.0-beta.53)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) + version: 1.139.0(aws4fetch@1.0.20)(rolldown@1.0.0-beta.53)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1)) '@tanstack/react-router': specifier: ^1.139.7 version: 1.139.7(react-dom@19.2.0(react@19.2.0))(react@19.2.0) @@ -1051,6 +1082,147 @@ packages: '@asamuzakjp/nwsapi@2.3.9': resolution: {integrity: sha512-n8GuYSrI9bF7FFZ/SjhwevlHc8xaVlb/7HmHelnc/PZXBD2ZR49NnN9sMMuDdEGPeeRQ5d0hqlSlEpgCX3Wl0Q==} + '@aws-crypto/crc32@5.2.0': + resolution: {integrity: sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/sha256-browser@5.2.0': + resolution: {integrity: sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==} + + '@aws-crypto/sha256-js@5.2.0': + resolution: {integrity: sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==} + engines: {node: '>=16.0.0'} + + '@aws-crypto/supports-web-crypto@5.2.0': + resolution: {integrity: sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==} + + '@aws-crypto/util@5.2.0': + resolution: {integrity: sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==} + + '@aws-sdk/client-bedrock-runtime@3.947.0': + resolution: {integrity: sha512-gYHkLDyHZN8eWDOvbMZOoBYUznq0N1yMzhZGLKqiekyWqDWA+PI08JjbPHX/ajpddkYM807SvRfD6unS59eVFg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/client-bedrock@3.947.0': + resolution: {integrity: sha512-BJ9K3v16zUh/0EcqBFWSbzd4Sf3To+eFx0hvaQQhd/U/2fixlDU84ORkVUJ9rV7MLdstBxVwsZm9V9Z2qls4pA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/client-sso@3.947.0': + resolution: {integrity: sha512-sDwcO8SP290WSErY1S8pz8hTafeghKmmWjNVks86jDK30wx62CfazOTeU70IpWgrUBEygyXk/zPogHsUMbW2Rg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/core@3.947.0': + resolution: {integrity: sha512-Khq4zHhuAkvCFuFbgcy3GrZTzfSX7ZIjIcW1zRDxXRLZKRtuhnZdonqTUfaWi5K42/4OmxkYNpsO7X7trQOeHw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-env@3.947.0': + resolution: {integrity: sha512-VR2V6dRELmzwAsCpK4GqxUi6UW5WNhAXS9F9AzWi5jvijwJo3nH92YNJUP4quMpgFZxJHEWyXLWgPjh9u0zYOA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-http@3.947.0': + resolution: {integrity: sha512-inF09lh9SlHj63Vmr5d+LmwPXZc2IbK8lAruhOr3KLsZAIHEgHgGPXWDC2ukTEMzg0pkexQ6FOhXXad6klK4RA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-ini@3.947.0': + resolution: {integrity: sha512-A2ZUgJUJZERjSzvCi2NR/hBVbVkTXPD0SdKcR/aITb30XwF+n3T963b+pJl90qhOspoy7h0IVYNR7u5Nr9tJdQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-login@3.947.0': + resolution: {integrity: sha512-u7M3hazcB7aJiVwosNdJRbIJDzbwQ861NTtl6S0HmvWpixaVb7iyhJZWg8/plyUznboZGBm7JVEdxtxv3u0bTA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-node@3.947.0': + resolution: {integrity: sha512-S0Zqebr71KyrT6J4uYPhwV65g4V5uDPHnd7dt2W34FcyPu+hVC7Hx4MFmsPyVLeT5cMCkkZvmY3kAoEzgUPJJg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-process@3.947.0': + resolution: {integrity: sha512-WpanFbHe08SP1hAJNeDdBDVz9SGgMu/gc0XJ9u3uNpW99nKZjDpvPRAdW7WLA4K6essMjxWkguIGNOpij6Do2Q==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-sso@3.947.0': + resolution: {integrity: sha512-NktnVHTGaUMaozxycYrepvb3yfFquHTQ53lt6hBEVjYBzK3C4tVz0siUpr+5RMGLSiZ5bLBp2UjJPgwx4i4waQ==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/credential-provider-web-identity@3.947.0': + resolution: {integrity: sha512-gokm/e/YHiHLrZgLq4j8tNAn8RJDPbIcglFRKgy08q8DmAqHQ8MXAKW3eS0QjAuRXU9mcMmUo1NrX6FRNBCCPw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/eventstream-handler-node@3.936.0': + resolution: {integrity: sha512-4zIbhdRmol2KosIHmU31ATvNP0tkJhDlRj9GuawVJoEnMvJA1pd2U3SRdiOImJU3j8pT46VeS4YMmYxfjGHByg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-eventstream@3.936.0': + resolution: {integrity: sha512-XQSH8gzLkk8CDUDxyt4Rdm9owTpRIPdtg2yw9Y2Wl5iSI55YQSiC3x8nM3c4Y4WqReJprunFPK225ZUDoYCfZA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-host-header@3.936.0': + resolution: {integrity: sha512-tAaObaAnsP1XnLGndfkGWFuzrJYuk9W0b/nLvol66t8FZExIAf/WdkT2NNAWOYxljVs++oHnyHBCxIlaHrzSiw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-logger@3.936.0': + resolution: {integrity: sha512-aPSJ12d3a3Ea5nyEnLbijCaaYJT2QjQ9iW+zGh5QcZYXmOGWbKVyPSxmVOboZQG+c1M8t6d2O7tqrwzIq8L8qw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-recursion-detection@3.936.0': + resolution: {integrity: sha512-l4aGbHpXM45YNgXggIux1HgsCVAvvBoqHPkqLnqMl9QVapfuSTjJHfDYDsx1Xxct6/m7qSMUzanBALhiaGO2fA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-user-agent@3.947.0': + resolution: {integrity: sha512-7rpKV8YNgCP2R4F9RjWZFcD2R+SO/0R4VHIbY9iZJdH2MzzJ8ZG7h8dZ2m8QkQd1fjx4wrFJGGPJUTYXPV3baA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/middleware-websocket@3.936.0': + resolution: {integrity: sha512-bPe3rqeugyj/MmjP0yBSZox2v1Wa8Dv39KN+RxVbQroLO8VUitBo6xyZ0oZebhZ5sASwSg58aDcMlX0uFLQnTA==} + engines: {node: '>= 14.0.0'} + + '@aws-sdk/nested-clients@3.947.0': + resolution: {integrity: sha512-DjRJEYNnHUTu9kGPPQDTSXquwSEd6myKR4ssI4FaYLFhdT3ldWpj73yYt807H3tdmhS7vPmdVqchSJnjurUQAw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/region-config-resolver@3.936.0': + resolution: {integrity: sha512-wOKhzzWsshXGduxO4pqSiNyL9oUtk4BEvjWm9aaq6Hmfdoydq6v6t0rAGHWPjFwy9z2haovGRi3C8IxdMB4muw==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/token-providers@3.947.0': + resolution: {integrity: sha512-X/DyB8GuK44rsE89Tn5+s542B3PhGbXQSgV8lvqHDzvicwCt0tWny6790st6CPETrVVV2K3oJMfG5U3/jAmaZA==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/types@3.936.0': + resolution: {integrity: sha512-uz0/VlMd2pP5MepdrHizd+T+OKfyK4r3OA9JI+L/lPKg0YFQosdJNCKisr6o70E3dh8iMpFYxF1UN/4uZsyARg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-endpoints@3.936.0': + resolution: {integrity: sha512-0Zx3Ntdpu+z9Wlm7JKUBOzS9EunwKAb4KdGUQQxDqh5Lc3ta5uBoub+FgmVuzwnmBu9U1Os8UuwVTH0Lgu+P5w==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-format-url@3.936.0': + resolution: {integrity: sha512-MS5eSEtDUFIAMHrJaMERiHAvDPdfxc/T869ZjDNFAIiZhyc037REw0aoTNeimNXDNy2txRNZJaAUn/kE4RwN+g==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-locate-window@3.893.0': + resolution: {integrity: sha512-T89pFfgat6c8nMmpI8eKjBcDcgJq36+m9oiXbcUzeU55MP9ZuGgBomGjGnHaEyF36jenW9gmg3NfZDm0AO2XPg==} + engines: {node: '>=18.0.0'} + + '@aws-sdk/util-user-agent-browser@3.936.0': + resolution: {integrity: sha512-eZ/XF6NxMtu+iCma58GRNRxSq4lHo6zHQLOZRIeL/ghqYJirqHdenMOwrzPettj60KWlv827RVebP9oNVrwZbw==} + + '@aws-sdk/util-user-agent-node@3.947.0': + resolution: {integrity: sha512-+vhHoDrdbb+zerV4noQk1DHaUMNzWFWPpPYjVTwW2186k5BEJIecAMChYkghRrBVJ3KPWP1+JnZwOd72F3d4rQ==} + engines: {node: '>=18.0.0'} + peerDependencies: + aws-crt: '>=1.0.0' + peerDependenciesMeta: + aws-crt: + optional: true + + '@aws-sdk/xml-builder@3.930.0': + resolution: {integrity: sha512-YIfkD17GocxdmlUVc3ia52QhcWuRIUJonbF8A2CYfcWNV3HzvAqpcPeC0bYUhkK+8e8YO1ARnLKZQE0TlwzorA==} + engines: {node: '>=18.0.0'} + + '@aws/lambda-invoke-store@0.2.2': + resolution: {integrity: sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg==} + engines: {node: '>=18.0.0'} + '@babel/code-frame@7.26.2': resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} engines: {node: '>=6.9.0'} @@ -2247,6 +2419,198 @@ packages: resolution: {integrity: sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==} engines: {node: '>=18'} + '@smithy/abort-controller@4.2.5': + resolution: {integrity: sha512-j7HwVkBw68YW8UmFRcjZOmssE77Rvk0GWAIN1oFBhsaovQmZWYCIcGa9/pwRB0ExI8Sk9MWNALTjftjHZea7VA==} + engines: {node: '>=18.0.0'} + + '@smithy/config-resolver@4.4.3': + resolution: {integrity: sha512-ezHLe1tKLUxDJo2LHtDuEDyWXolw8WGOR92qb4bQdWq/zKenO5BvctZGrVJBK08zjezSk7bmbKFOXIVyChvDLw==} + engines: {node: '>=18.0.0'} + + '@smithy/core@3.18.7': + resolution: {integrity: sha512-axG9MvKhMWOhFbvf5y2DuyTxQueO0dkedY9QC3mAfndLosRI/9LJv8WaL0mw7ubNhsO4IuXX9/9dYGPFvHrqlw==} + engines: {node: '>=18.0.0'} + + '@smithy/credential-provider-imds@4.2.5': + resolution: {integrity: sha512-BZwotjoZWn9+36nimwm/OLIcVe+KYRwzMjfhd4QT7QxPm9WY0HiOV8t/Wlh+HVUif0SBVV7ksq8//hPaBC/okQ==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-codec@4.2.5': + resolution: {integrity: sha512-Ogt4Zi9hEbIP17oQMd68qYOHUzmH47UkK7q7Gl55iIm9oKt27MUGrC5JfpMroeHjdkOliOA4Qt3NQ1xMq/nrlA==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-browser@4.2.5': + resolution: {integrity: sha512-HohfmCQZjppVnKX2PnXlf47CW3j92Ki6T/vkAT2DhBR47e89pen3s4fIa7otGTtrVxmj7q+IhH0RnC5kpR8wtw==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-config-resolver@4.3.5': + resolution: {integrity: sha512-ibjQjM7wEXtECiT6my1xfiMH9IcEczMOS6xiCQXoUIYSj5b1CpBbJ3VYbdwDy8Vcg5JHN7eFpOCGk8nyZAltNQ==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-node@4.2.5': + resolution: {integrity: sha512-+elOuaYx6F2H6x1/5BQP5ugv12nfJl66GhxON8+dWVUEDJ9jah/A0tayVdkLRP0AeSac0inYkDz5qBFKfVp2Gg==} + engines: {node: '>=18.0.0'} + + '@smithy/eventstream-serde-universal@4.2.5': + resolution: {integrity: sha512-G9WSqbST45bmIFaeNuP/EnC19Rhp54CcVdX9PDL1zyEB514WsDVXhlyihKlGXnRycmHNmVv88Bvvt4EYxWef/Q==} + engines: {node: '>=18.0.0'} + + '@smithy/fetch-http-handler@5.3.6': + resolution: {integrity: sha512-3+RG3EA6BBJ/ofZUeTFJA7mHfSYrZtQIrDP9dI8Lf7X6Jbos2jptuLrAAteDiFVrmbEmLSuRG/bUKzfAXk7dhg==} + engines: {node: '>=18.0.0'} + + '@smithy/hash-node@4.2.5': + resolution: {integrity: sha512-DpYX914YOfA3UDT9CN1BM787PcHfWRBB43fFGCYrZFUH0Jv+5t8yYl+Pd5PW4+QzoGEDvn5d5QIO4j2HyYZQSA==} + engines: {node: '>=18.0.0'} + + '@smithy/invalid-dependency@4.2.5': + resolution: {integrity: sha512-2L2erASEro1WC5nV+plwIMxrTXpvpfzl4e+Nre6vBVRR2HKeGGcvpJyyL3/PpiSg+cJG2KpTmZmq934Olb6e5A==} + engines: {node: '>=18.0.0'} + + '@smithy/is-array-buffer@2.2.0': + resolution: {integrity: sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==} + engines: {node: '>=14.0.0'} + + '@smithy/is-array-buffer@4.2.0': + resolution: {integrity: sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-content-length@4.2.5': + resolution: {integrity: sha512-Y/RabVa5vbl5FuHYV2vUCwvh/dqzrEY/K2yWPSqvhFUwIY0atLqO4TienjBXakoy4zrKAMCZwg+YEqmH7jaN7A==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-endpoint@4.3.14': + resolution: {integrity: sha512-v0q4uTKgBM8dsqGjqsabZQyH85nFaTnFcgpWU1uydKFsdyyMzfvOkNum9G7VK+dOP01vUnoZxIeRiJ6uD0kjIg==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-retry@4.4.14': + resolution: {integrity: sha512-Z2DG8Ej7FyWG1UA+7HceINtSLzswUgs2np3sZX0YBBxCt+CXG4QUxv88ZDS3+2/1ldW7LqtSY1UO/6VQ1pND8Q==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-serde@4.2.6': + resolution: {integrity: sha512-VkLoE/z7e2g8pirwisLz8XJWedUSY8my/qrp81VmAdyrhi94T+riBfwP+AOEEFR9rFTSonC/5D2eWNmFabHyGQ==} + engines: {node: '>=18.0.0'} + + '@smithy/middleware-stack@4.2.5': + resolution: {integrity: sha512-bYrutc+neOyWxtZdbB2USbQttZN0mXaOyYLIsaTbJhFsfpXyGWUxJpEuO1rJ8IIJm2qH4+xJT0mxUSsEDTYwdQ==} + engines: {node: '>=18.0.0'} + + '@smithy/node-config-provider@4.3.5': + resolution: {integrity: sha512-UTurh1C4qkVCtqggI36DGbLB2Kv8UlcFdMXDcWMbqVY2uRg0XmT9Pb4Vj6oSQ34eizO1fvR0RnFV4Axw4IrrAg==} + engines: {node: '>=18.0.0'} + + '@smithy/node-http-handler@4.4.5': + resolution: {integrity: sha512-CMnzM9R2WqlqXQGtIlsHMEZfXKJVTIrqCNoSd/QpAyp+Dw0a1Vps13l6ma1fH8g7zSPNsA59B/kWgeylFuA/lw==} + engines: {node: '>=18.0.0'} + + '@smithy/property-provider@4.2.5': + resolution: {integrity: sha512-8iLN1XSE1rl4MuxvQ+5OSk/Zb5El7NJZ1td6Tn+8dQQHIjp59Lwl6bd0+nzw6SKm2wSSriH2v/I9LPzUic7EOg==} + engines: {node: '>=18.0.0'} + + '@smithy/protocol-http@5.3.5': + resolution: {integrity: sha512-RlaL+sA0LNMp03bf7XPbFmT5gN+w3besXSWMkA8rcmxLSVfiEXElQi4O2IWwPfxzcHkxqrwBFMbngB8yx/RvaQ==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-builder@4.2.5': + resolution: {integrity: sha512-y98otMI1saoajeik2kLfGyRp11e5U/iJYH/wLCh3aTV/XutbGT9nziKGkgCaMD1ghK7p6htHMm6b6scl9JRUWg==} + engines: {node: '>=18.0.0'} + + '@smithy/querystring-parser@4.2.5': + resolution: {integrity: sha512-031WCTdPYgiQRYNPXznHXof2YM0GwL6SeaSyTH/P72M1Vz73TvCNH2Nq8Iu2IEPq9QP2yx0/nrw5YmSeAi/AjQ==} + engines: {node: '>=18.0.0'} + + '@smithy/service-error-classification@4.2.5': + resolution: {integrity: sha512-8fEvK+WPE3wUAcDvqDQG1Vk3ANLR8Px979te96m84CbKAjBVf25rPYSzb4xU4hlTyho7VhOGnh5i62D/JVF0JQ==} + engines: {node: '>=18.0.0'} + + '@smithy/shared-ini-file-loader@4.4.0': + resolution: {integrity: sha512-5WmZ5+kJgJDjwXXIzr1vDTG+RhF9wzSODQBfkrQ2VVkYALKGvZX1lgVSxEkgicSAFnFhPj5rudJV0zoinqS0bA==} + engines: {node: '>=18.0.0'} + + '@smithy/signature-v4@5.3.5': + resolution: {integrity: sha512-xSUfMu1FT7ccfSXkoLl/QRQBi2rOvi3tiBZU2Tdy3I6cgvZ6SEi9QNey+lqps/sJRnogIS+lq+B1gxxbra2a/w==} + engines: {node: '>=18.0.0'} + + '@smithy/smithy-client@4.9.10': + resolution: {integrity: sha512-Jaoz4Jw1QYHc1EFww/E6gVtNjhoDU+gwRKqXP6C3LKYqqH2UQhP8tMP3+t/ePrhaze7fhLE8vS2q6vVxBANFTQ==} + engines: {node: '>=18.0.0'} + + '@smithy/types@4.9.0': + resolution: {integrity: sha512-MvUbdnXDTwykR8cB1WZvNNwqoWVaTRA0RLlLmf/cIFNMM2cKWz01X4Ly6SMC4Kks30r8tT3Cty0jmeWfiuyHTA==} + engines: {node: '>=18.0.0'} + + '@smithy/url-parser@4.2.5': + resolution: {integrity: sha512-VaxMGsilqFnK1CeBX+LXnSuaMx4sTL/6znSZh2829txWieazdVxr54HmiyTsIbpOTLcf5nYpq9lpzmwRdxj6rQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-base64@4.3.0': + resolution: {integrity: sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-browser@4.2.0': + resolution: {integrity: sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-body-length-node@4.2.1': + resolution: {integrity: sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-buffer-from@2.2.0': + resolution: {integrity: sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==} + engines: {node: '>=14.0.0'} + + '@smithy/util-buffer-from@4.2.0': + resolution: {integrity: sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==} + engines: {node: '>=18.0.0'} + + '@smithy/util-config-provider@4.2.0': + resolution: {integrity: sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-browser@4.3.13': + resolution: {integrity: sha512-hlVLdAGrVfyNei+pKIgqDTxfu/ZI2NSyqj4IDxKd5bIsIqwR/dSlkxlPaYxFiIaDVrBy0he8orsFy+Cz119XvA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-defaults-mode-node@4.2.16': + resolution: {integrity: sha512-F1t22IUiJLHrxW9W1CQ6B9PN+skZ9cqSuzB18Eh06HrJPbjsyZ7ZHecAKw80DQtyGTRcVfeukKaCRYebFwclbg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-endpoints@3.2.5': + resolution: {integrity: sha512-3O63AAWu2cSNQZp+ayl9I3NapW1p1rR5mlVHcF6hAB1dPZUQFfRPYtplWX/3xrzWthPGj5FqB12taJJCfH6s8A==} + engines: {node: '>=18.0.0'} + + '@smithy/util-hex-encoding@4.2.0': + resolution: {integrity: sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==} + engines: {node: '>=18.0.0'} + + '@smithy/util-middleware@4.2.5': + resolution: {integrity: sha512-6Y3+rvBF7+PZOc40ybeZMcGln6xJGVeY60E7jy9Mv5iKpMJpHgRE6dKy9ScsVxvfAYuEX4Q9a65DQX90KaQ3bA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-retry@4.2.5': + resolution: {integrity: sha512-GBj3+EZBbN4NAqJ/7pAhsXdfzdlznOh8PydUijy6FpNIMnHPSMO2/rP4HKu+UFeikJxShERk528oy7GT79YiJg==} + engines: {node: '>=18.0.0'} + + '@smithy/util-stream@4.5.6': + resolution: {integrity: sha512-qWw/UM59TiaFrPevefOZ8CNBKbYEP6wBAIlLqxn3VAIo9rgnTNc4ASbVrqDmhuwI87usnjhdQrxodzAGFFzbRQ==} + engines: {node: '>=18.0.0'} + + '@smithy/util-uri-escape@4.2.0': + resolution: {integrity: sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==} + engines: {node: '>=18.0.0'} + + '@smithy/util-utf8@2.3.0': + resolution: {integrity: sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==} + engines: {node: '>=14.0.0'} + + '@smithy/util-utf8@4.2.0': + resolution: {integrity: sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==} + engines: {node: '>=18.0.0'} + + '@smithy/uuid@1.1.0': + resolution: {integrity: sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==} + engines: {node: '>=18.0.0'} + '@solid-devtools/debugger@0.28.1': resolution: {integrity: sha512-6qIUI6VYkXoRnL8oF5bvh2KgH71qlJ18hNw/mwSyY6v48eb80ZR48/5PDXufUa3q+MBSuYa1uqTMwLewpay9eg==} peerDependencies: @@ -3404,6 +3768,9 @@ packages: peerDependencies: postcss: ^8.1.0 + aws4fetch@1.0.20: + resolution: {integrity: sha512-/djoAN709iY65ETD6LKCtyyEI04XIBP5xVvfmNxsEP0uJB5tyaGBztSryRr4HqMStr9R06PisQE7m9zDTXKu6g==} + axios@1.13.2: resolution: {integrity: sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==} @@ -3487,6 +3854,9 @@ packages: boolbase@1.0.0: resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} + bowser@2.13.1: + resolution: {integrity: sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==} + brace-expansion@1.1.12: resolution: {integrity: sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==} @@ -4214,6 +4584,10 @@ packages: fast-levenshtein@2.0.6: resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + fast-xml-parser@5.2.5: + resolution: {integrity: sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==} + hasBin: true + fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} @@ -6231,6 +6605,9 @@ packages: strip-literal@3.1.0: resolution: {integrity: sha512-8r3mkIM/2+PpjHoOtiAW8Rg3jJLHaV7xPwG+YRGrv6FP0wwk/toTpATxWYOW0BKdWwl82VT2tFYi5DlROa0Mxg==} + strnum@2.1.1: + resolution: {integrity: sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==} + style-to-js@1.1.18: resolution: {integrity: sha512-JFPn62D4kJaPTnhFUI244MThx+FEGbi+9dw1b9yBBQ+1CZpV7QAT8kUtJ7b7EUNdHajjF/0x8fT+16oLJoojLg==} @@ -7012,6 +7389,466 @@ snapshots: '@asamuzakjp/nwsapi@2.3.9': {} + '@aws-crypto/crc32@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.936.0 + tslib: 2.8.1 + + '@aws-crypto/sha256-browser@5.2.0': + dependencies: + '@aws-crypto/sha256-js': 5.2.0 + '@aws-crypto/supports-web-crypto': 5.2.0 + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.936.0 + '@aws-sdk/util-locate-window': 3.893.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-crypto/sha256-js@5.2.0': + dependencies: + '@aws-crypto/util': 5.2.0 + '@aws-sdk/types': 3.936.0 + tslib: 2.8.1 + + '@aws-crypto/supports-web-crypto@5.2.0': + dependencies: + tslib: 2.8.1 + + '@aws-crypto/util@5.2.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@smithy/util-utf8': 2.3.0 + tslib: 2.8.1 + + '@aws-sdk/client-bedrock-runtime@3.947.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.947.0 + '@aws-sdk/credential-provider-node': 3.947.0 + '@aws-sdk/eventstream-handler-node': 3.936.0 + '@aws-sdk/middleware-eventstream': 3.936.0 + '@aws-sdk/middleware-host-header': 3.936.0 + '@aws-sdk/middleware-logger': 3.936.0 + '@aws-sdk/middleware-recursion-detection': 3.936.0 + '@aws-sdk/middleware-user-agent': 3.947.0 + '@aws-sdk/middleware-websocket': 3.936.0 + '@aws-sdk/region-config-resolver': 3.936.0 + '@aws-sdk/token-providers': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@aws-sdk/util-endpoints': 3.936.0 + '@aws-sdk/util-user-agent-browser': 3.936.0 + '@aws-sdk/util-user-agent-node': 3.947.0 + '@smithy/config-resolver': 4.4.3 + '@smithy/core': 3.18.7 + '@smithy/eventstream-serde-browser': 4.2.5 + '@smithy/eventstream-serde-config-resolver': 4.3.5 + '@smithy/eventstream-serde-node': 4.2.5 + '@smithy/fetch-http-handler': 5.3.6 + '@smithy/hash-node': 4.2.5 + '@smithy/invalid-dependency': 4.2.5 + '@smithy/middleware-content-length': 4.2.5 + '@smithy/middleware-endpoint': 4.3.14 + '@smithy/middleware-retry': 4.4.14 + '@smithy/middleware-serde': 4.2.6 + '@smithy/middleware-stack': 4.2.5 + '@smithy/node-config-provider': 4.3.5 + '@smithy/node-http-handler': 4.4.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + '@smithy/url-parser': 4.2.5 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-body-length-node': 4.2.1 + '@smithy/util-defaults-mode-browser': 4.3.13 + '@smithy/util-defaults-mode-node': 4.2.16 + '@smithy/util-endpoints': 3.2.5 + '@smithy/util-middleware': 4.2.5 + '@smithy/util-retry': 4.2.5 + '@smithy/util-stream': 4.5.6 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-bedrock@3.947.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.947.0 + '@aws-sdk/credential-provider-node': 3.947.0 + '@aws-sdk/middleware-host-header': 3.936.0 + '@aws-sdk/middleware-logger': 3.936.0 + '@aws-sdk/middleware-recursion-detection': 3.936.0 + '@aws-sdk/middleware-user-agent': 3.947.0 + '@aws-sdk/region-config-resolver': 3.936.0 + '@aws-sdk/token-providers': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@aws-sdk/util-endpoints': 3.936.0 + '@aws-sdk/util-user-agent-browser': 3.936.0 + '@aws-sdk/util-user-agent-node': 3.947.0 + '@smithy/config-resolver': 4.4.3 + '@smithy/core': 3.18.7 + '@smithy/fetch-http-handler': 5.3.6 + '@smithy/hash-node': 4.2.5 + '@smithy/invalid-dependency': 4.2.5 + '@smithy/middleware-content-length': 4.2.5 + '@smithy/middleware-endpoint': 4.3.14 + '@smithy/middleware-retry': 4.4.14 + '@smithy/middleware-serde': 4.2.6 + '@smithy/middleware-stack': 4.2.5 + '@smithy/node-config-provider': 4.3.5 + '@smithy/node-http-handler': 4.4.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + '@smithy/url-parser': 4.2.5 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-body-length-node': 4.2.1 + '@smithy/util-defaults-mode-browser': 4.3.13 + '@smithy/util-defaults-mode-node': 4.2.16 + '@smithy/util-endpoints': 3.2.5 + '@smithy/util-middleware': 4.2.5 + '@smithy/util-retry': 4.2.5 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/client-sso@3.947.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.947.0 + '@aws-sdk/middleware-host-header': 3.936.0 + '@aws-sdk/middleware-logger': 3.936.0 + '@aws-sdk/middleware-recursion-detection': 3.936.0 + '@aws-sdk/middleware-user-agent': 3.947.0 + '@aws-sdk/region-config-resolver': 3.936.0 + '@aws-sdk/types': 3.936.0 + '@aws-sdk/util-endpoints': 3.936.0 + '@aws-sdk/util-user-agent-browser': 3.936.0 + '@aws-sdk/util-user-agent-node': 3.947.0 + '@smithy/config-resolver': 4.4.3 + '@smithy/core': 3.18.7 + '@smithy/fetch-http-handler': 5.3.6 + '@smithy/hash-node': 4.2.5 + '@smithy/invalid-dependency': 4.2.5 + '@smithy/middleware-content-length': 4.2.5 + '@smithy/middleware-endpoint': 4.3.14 + '@smithy/middleware-retry': 4.4.14 + '@smithy/middleware-serde': 4.2.6 + '@smithy/middleware-stack': 4.2.5 + '@smithy/node-config-provider': 4.3.5 + '@smithy/node-http-handler': 4.4.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + '@smithy/url-parser': 4.2.5 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-body-length-node': 4.2.1 + '@smithy/util-defaults-mode-browser': 4.3.13 + '@smithy/util-defaults-mode-node': 4.2.16 + '@smithy/util-endpoints': 3.2.5 + '@smithy/util-middleware': 4.2.5 + '@smithy/util-retry': 4.2.5 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/core@3.947.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@aws-sdk/xml-builder': 3.930.0 + '@smithy/core': 3.18.7 + '@smithy/node-config-provider': 4.3.5 + '@smithy/property-provider': 4.2.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/signature-v4': 5.3.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-middleware': 4.2.5 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-env@3.947.0': + dependencies: + '@aws-sdk/core': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@smithy/property-provider': 4.2.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-http@3.947.0': + dependencies: + '@aws-sdk/core': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@smithy/fetch-http-handler': 5.3.6 + '@smithy/node-http-handler': 4.4.5 + '@smithy/property-provider': 4.2.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + '@smithy/util-stream': 4.5.6 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-ini@3.947.0': + dependencies: + '@aws-sdk/core': 3.947.0 + '@aws-sdk/credential-provider-env': 3.947.0 + '@aws-sdk/credential-provider-http': 3.947.0 + '@aws-sdk/credential-provider-login': 3.947.0 + '@aws-sdk/credential-provider-process': 3.947.0 + '@aws-sdk/credential-provider-sso': 3.947.0 + '@aws-sdk/credential-provider-web-identity': 3.947.0 + '@aws-sdk/nested-clients': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@smithy/credential-provider-imds': 4.2.5 + '@smithy/property-provider': 4.2.5 + '@smithy/shared-ini-file-loader': 4.4.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-login@3.947.0': + dependencies: + '@aws-sdk/core': 3.947.0 + '@aws-sdk/nested-clients': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@smithy/property-provider': 4.2.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/shared-ini-file-loader': 4.4.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-node@3.947.0': + dependencies: + '@aws-sdk/credential-provider-env': 3.947.0 + '@aws-sdk/credential-provider-http': 3.947.0 + '@aws-sdk/credential-provider-ini': 3.947.0 + '@aws-sdk/credential-provider-process': 3.947.0 + '@aws-sdk/credential-provider-sso': 3.947.0 + '@aws-sdk/credential-provider-web-identity': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@smithy/credential-provider-imds': 4.2.5 + '@smithy/property-provider': 4.2.5 + '@smithy/shared-ini-file-loader': 4.4.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-process@3.947.0': + dependencies: + '@aws-sdk/core': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@smithy/property-provider': 4.2.5 + '@smithy/shared-ini-file-loader': 4.4.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/credential-provider-sso@3.947.0': + dependencies: + '@aws-sdk/client-sso': 3.947.0 + '@aws-sdk/core': 3.947.0 + '@aws-sdk/token-providers': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@smithy/property-provider': 4.2.5 + '@smithy/shared-ini-file-loader': 4.4.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/credential-provider-web-identity@3.947.0': + dependencies: + '@aws-sdk/core': 3.947.0 + '@aws-sdk/nested-clients': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@smithy/property-provider': 4.2.5 + '@smithy/shared-ini-file-loader': 4.4.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/eventstream-handler-node@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@smithy/eventstream-codec': 4.2.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-eventstream@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-host-header@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-logger@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-recursion-detection@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@aws/lambda-invoke-store': 0.2.2 + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-user-agent@3.947.0': + dependencies: + '@aws-sdk/core': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@aws-sdk/util-endpoints': 3.936.0 + '@smithy/core': 3.18.7 + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/middleware-websocket@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@aws-sdk/util-format-url': 3.936.0 + '@smithy/eventstream-codec': 4.2.5 + '@smithy/eventstream-serde-browser': 4.2.5 + '@smithy/fetch-http-handler': 5.3.6 + '@smithy/protocol-http': 5.3.5 + '@smithy/signature-v4': 5.3.5 + '@smithy/types': 4.9.0 + '@smithy/util-hex-encoding': 4.2.0 + tslib: 2.8.1 + + '@aws-sdk/nested-clients@3.947.0': + dependencies: + '@aws-crypto/sha256-browser': 5.2.0 + '@aws-crypto/sha256-js': 5.2.0 + '@aws-sdk/core': 3.947.0 + '@aws-sdk/middleware-host-header': 3.936.0 + '@aws-sdk/middleware-logger': 3.936.0 + '@aws-sdk/middleware-recursion-detection': 3.936.0 + '@aws-sdk/middleware-user-agent': 3.947.0 + '@aws-sdk/region-config-resolver': 3.936.0 + '@aws-sdk/types': 3.936.0 + '@aws-sdk/util-endpoints': 3.936.0 + '@aws-sdk/util-user-agent-browser': 3.936.0 + '@aws-sdk/util-user-agent-node': 3.947.0 + '@smithy/config-resolver': 4.4.3 + '@smithy/core': 3.18.7 + '@smithy/fetch-http-handler': 5.3.6 + '@smithy/hash-node': 4.2.5 + '@smithy/invalid-dependency': 4.2.5 + '@smithy/middleware-content-length': 4.2.5 + '@smithy/middleware-endpoint': 4.3.14 + '@smithy/middleware-retry': 4.4.14 + '@smithy/middleware-serde': 4.2.6 + '@smithy/middleware-stack': 4.2.5 + '@smithy/node-config-provider': 4.3.5 + '@smithy/node-http-handler': 4.4.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + '@smithy/url-parser': 4.2.5 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-body-length-node': 4.2.1 + '@smithy/util-defaults-mode-browser': 4.3.13 + '@smithy/util-defaults-mode-node': 4.2.16 + '@smithy/util-endpoints': 3.2.5 + '@smithy/util-middleware': 4.2.5 + '@smithy/util-retry': 4.2.5 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/region-config-resolver@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@smithy/config-resolver': 4.4.3 + '@smithy/node-config-provider': 4.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/token-providers@3.947.0': + dependencies: + '@aws-sdk/core': 3.947.0 + '@aws-sdk/nested-clients': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@smithy/property-provider': 4.2.5 + '@smithy/shared-ini-file-loader': 4.4.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + transitivePeerDependencies: + - aws-crt + + '@aws-sdk/types@3.936.0': + dependencies: + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/util-endpoints@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@smithy/types': 4.9.0 + '@smithy/url-parser': 4.2.5 + '@smithy/util-endpoints': 3.2.5 + tslib: 2.8.1 + + '@aws-sdk/util-format-url@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@smithy/querystring-builder': 4.2.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/util-locate-window@3.893.0': + dependencies: + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-browser@3.936.0': + dependencies: + '@aws-sdk/types': 3.936.0 + '@smithy/types': 4.9.0 + bowser: 2.13.1 + tslib: 2.8.1 + + '@aws-sdk/util-user-agent-node@3.947.0': + dependencies: + '@aws-sdk/middleware-user-agent': 3.947.0 + '@aws-sdk/types': 3.936.0 + '@smithy/node-config-provider': 4.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@aws-sdk/xml-builder@3.930.0': + dependencies: + '@smithy/types': 4.9.0 + fast-xml-parser: 5.2.5 + tslib: 2.8.1 + + '@aws/lambda-invoke-store@0.2.2': {} + '@babel/code-frame@7.26.2': dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -8172,6 +9009,310 @@ snapshots: '@sindresorhus/merge-streams@4.0.0': {} + '@smithy/abort-controller@4.2.5': + dependencies: + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/config-resolver@4.4.3': + dependencies: + '@smithy/node-config-provider': 4.3.5 + '@smithy/types': 4.9.0 + '@smithy/util-config-provider': 4.2.0 + '@smithy/util-endpoints': 3.2.5 + '@smithy/util-middleware': 4.2.5 + tslib: 2.8.1 + + '@smithy/core@3.18.7': + dependencies: + '@smithy/middleware-serde': 4.2.6 + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-body-length-browser': 4.2.0 + '@smithy/util-middleware': 4.2.5 + '@smithy/util-stream': 4.5.6 + '@smithy/util-utf8': 4.2.0 + '@smithy/uuid': 1.1.0 + tslib: 2.8.1 + + '@smithy/credential-provider-imds@4.2.5': + dependencies: + '@smithy/node-config-provider': 4.3.5 + '@smithy/property-provider': 4.2.5 + '@smithy/types': 4.9.0 + '@smithy/url-parser': 4.2.5 + tslib: 2.8.1 + + '@smithy/eventstream-codec@4.2.5': + dependencies: + '@aws-crypto/crc32': 5.2.0 + '@smithy/types': 4.9.0 + '@smithy/util-hex-encoding': 4.2.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-browser@4.2.5': + dependencies: + '@smithy/eventstream-serde-universal': 4.2.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-config-resolver@4.3.5': + dependencies: + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-node@4.2.5': + dependencies: + '@smithy/eventstream-serde-universal': 4.2.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/eventstream-serde-universal@4.2.5': + dependencies: + '@smithy/eventstream-codec': 4.2.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/fetch-http-handler@5.3.6': + dependencies: + '@smithy/protocol-http': 5.3.5 + '@smithy/querystring-builder': 4.2.5 + '@smithy/types': 4.9.0 + '@smithy/util-base64': 4.3.0 + tslib: 2.8.1 + + '@smithy/hash-node@4.2.5': + dependencies: + '@smithy/types': 4.9.0 + '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/invalid-dependency@4.2.5': + dependencies: + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/is-array-buffer@2.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/is-array-buffer@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/middleware-content-length@4.2.5': + dependencies: + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/middleware-endpoint@4.3.14': + dependencies: + '@smithy/core': 3.18.7 + '@smithy/middleware-serde': 4.2.6 + '@smithy/node-config-provider': 4.3.5 + '@smithy/shared-ini-file-loader': 4.4.0 + '@smithy/types': 4.9.0 + '@smithy/url-parser': 4.2.5 + '@smithy/util-middleware': 4.2.5 + tslib: 2.8.1 + + '@smithy/middleware-retry@4.4.14': + dependencies: + '@smithy/node-config-provider': 4.3.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/service-error-classification': 4.2.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + '@smithy/util-middleware': 4.2.5 + '@smithy/util-retry': 4.2.5 + '@smithy/uuid': 1.1.0 + tslib: 2.8.1 + + '@smithy/middleware-serde@4.2.6': + dependencies: + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/middleware-stack@4.2.5': + dependencies: + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/node-config-provider@4.3.5': + dependencies: + '@smithy/property-provider': 4.2.5 + '@smithy/shared-ini-file-loader': 4.4.0 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/node-http-handler@4.4.5': + dependencies: + '@smithy/abort-controller': 4.2.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/querystring-builder': 4.2.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/property-provider@4.2.5': + dependencies: + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/protocol-http@5.3.5': + dependencies: + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/querystring-builder@4.2.5': + dependencies: + '@smithy/types': 4.9.0 + '@smithy/util-uri-escape': 4.2.0 + tslib: 2.8.1 + + '@smithy/querystring-parser@4.2.5': + dependencies: + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/service-error-classification@4.2.5': + dependencies: + '@smithy/types': 4.9.0 + + '@smithy/shared-ini-file-loader@4.4.0': + dependencies: + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/signature-v4@5.3.5': + dependencies: + '@smithy/is-array-buffer': 4.2.0 + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + '@smithy/util-hex-encoding': 4.2.0 + '@smithy/util-middleware': 4.2.5 + '@smithy/util-uri-escape': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/smithy-client@4.9.10': + dependencies: + '@smithy/core': 3.18.7 + '@smithy/middleware-endpoint': 4.3.14 + '@smithy/middleware-stack': 4.2.5 + '@smithy/protocol-http': 5.3.5 + '@smithy/types': 4.9.0 + '@smithy/util-stream': 4.5.6 + tslib: 2.8.1 + + '@smithy/types@4.9.0': + dependencies: + tslib: 2.8.1 + + '@smithy/url-parser@4.2.5': + dependencies: + '@smithy/querystring-parser': 4.2.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/util-base64@4.3.0': + dependencies: + '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/util-body-length-browser@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-body-length-node@4.2.1': + dependencies: + tslib: 2.8.1 + + '@smithy/util-buffer-from@2.2.0': + dependencies: + '@smithy/is-array-buffer': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-buffer-from@4.2.0': + dependencies: + '@smithy/is-array-buffer': 4.2.0 + tslib: 2.8.1 + + '@smithy/util-config-provider@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-defaults-mode-browser@4.3.13': + dependencies: + '@smithy/property-provider': 4.2.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/util-defaults-mode-node@4.2.16': + dependencies: + '@smithy/config-resolver': 4.4.3 + '@smithy/credential-provider-imds': 4.2.5 + '@smithy/node-config-provider': 4.3.5 + '@smithy/property-provider': 4.2.5 + '@smithy/smithy-client': 4.9.10 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/util-endpoints@3.2.5': + dependencies: + '@smithy/node-config-provider': 4.3.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/util-hex-encoding@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-middleware@4.2.5': + dependencies: + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/util-retry@4.2.5': + dependencies: + '@smithy/service-error-classification': 4.2.5 + '@smithy/types': 4.9.0 + tslib: 2.8.1 + + '@smithy/util-stream@4.5.6': + dependencies: + '@smithy/fetch-http-handler': 5.3.6 + '@smithy/node-http-handler': 4.4.5 + '@smithy/types': 4.9.0 + '@smithy/util-base64': 4.3.0 + '@smithy/util-buffer-from': 4.2.0 + '@smithy/util-hex-encoding': 4.2.0 + '@smithy/util-utf8': 4.2.0 + tslib: 2.8.1 + + '@smithy/util-uri-escape@4.2.0': + dependencies: + tslib: 2.8.1 + + '@smithy/util-utf8@2.3.0': + dependencies: + '@smithy/util-buffer-from': 2.2.0 + tslib: 2.8.1 + + '@smithy/util-utf8@4.2.0': + dependencies: + '@smithy/util-buffer-from': 4.2.0 + tslib: 2.8.1 + + '@smithy/uuid@1.1.0': + dependencies: + tslib: 2.8.1 + '@solid-devtools/debugger@0.28.1(solid-js@1.9.10)': dependencies: '@nothing-but/utils': 0.17.0 @@ -8471,9 +9612,9 @@ snapshots: '@tanstack/history@1.139.0': {} - '@tanstack/nitro-v2-vite-plugin@1.139.0(rolldown@1.0.0-beta.53)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))': + '@tanstack/nitro-v2-vite-plugin@1.139.0(aws4fetch@1.0.20)(rolldown@1.0.0-beta.53)(vite@7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1))': dependencies: - nitropack: 2.12.9(rolldown@1.0.0-beta.53) + nitropack: 2.12.9(aws4fetch@1.0.20)(rolldown@1.0.0-beta.53) pathe: 2.0.3 vite: 7.2.4(@types/node@24.10.1)(jiti@2.6.1)(lightningcss@1.30.2)(terser@5.44.0)(tsx@4.20.6)(yaml@2.8.1) transitivePeerDependencies: @@ -9760,6 +10901,8 @@ snapshots: postcss: 8.5.6 postcss-value-parser: 4.2.0 + aws4fetch@1.0.20: {} + axios@1.13.2: dependencies: follow-redirects: 1.15.11 @@ -9847,6 +10990,8 @@ snapshots: boolbase@1.0.0: {} + bowser@2.13.1: {} + brace-expansion@1.1.12: dependencies: balanced-match: 1.0.2 @@ -10591,6 +11736,10 @@ snapshots: fast-levenshtein@2.0.6: {} + fast-xml-parser@5.2.5: + dependencies: + strnum: 2.1.1 + fastq@1.19.1: dependencies: reusify: 1.1.0 @@ -11979,7 +13128,7 @@ snapshots: negotiator@1.0.0: {} - nitropack@2.12.9(rolldown@1.0.0-beta.53): + nitropack@2.12.9(aws4fetch@1.0.20)(rolldown@1.0.0-beta.53): dependencies: '@cloudflare/kv-asset-handler': 0.4.0 '@rollup/plugin-alias': 5.1.1(rollup@4.53.3) @@ -12046,7 +13195,7 @@ snapshots: unenv: 2.0.0-rc.24 unimport: 5.5.0 unplugin-utils: 0.3.1 - unstorage: 1.17.2(db0@0.3.4)(ioredis@5.8.2) + unstorage: 1.17.2(aws4fetch@1.0.20)(db0@0.3.4)(ioredis@5.8.2) untyped: 2.0.0 unwasm: 0.3.11 youch: 4.1.0-beta.11 @@ -13047,6 +14196,8 @@ snapshots: dependencies: js-tokens: 9.0.1 + strnum@2.1.1: {} + style-to-js@1.1.18: dependencies: style-to-object: 1.0.11 @@ -13436,7 +14587,7 @@ snapshots: '@oxc-project/runtime': 0.101.0 rolldown: 1.0.0-beta.53 - unstorage@1.17.2(db0@0.3.4)(ioredis@5.8.2): + unstorage@1.17.2(aws4fetch@1.0.20)(db0@0.3.4)(ioredis@5.8.2): dependencies: anymatch: 3.1.3 chokidar: 4.0.3 @@ -13447,6 +14598,7 @@ snapshots: ofetch: 1.5.0 ufo: 1.6.1 optionalDependencies: + aws4fetch: 1.0.20 db0: 0.3.4 ioredis: 5.8.2 From 3e0475f6d626fd4fca875697c8010919928fe4f2 Mon Sep 17 00:00:00 2001 From: Hunter Blackwell <31895576+chunterb@users.noreply.github.com> Date: Mon, 8 Dec 2025 16:46:37 -0600 Subject: [PATCH 4/7] fix: over abstraction --- .../ai-bedrock/src/bedrock-adapter.ts | 70 ++++--------------- 1 file changed, 15 insertions(+), 55 deletions(-) diff --git a/packages/typescript/ai-bedrock/src/bedrock-adapter.ts b/packages/typescript/ai-bedrock/src/bedrock-adapter.ts index 6da1ab67..0cb30798 100644 --- a/packages/typescript/ai-bedrock/src/bedrock-adapter.ts +++ b/packages/typescript/ai-bedrock/src/bedrock-adapter.ts @@ -53,55 +53,8 @@ type BedrockConversePayload = Omit type BedrockConverseStreamPayload = Omit type BedrockStreamEvent = ConverseStreamOutput -/** - * TanStack AI finish reason type - */ -type FinishReason = 'stop' | 'tool_calls' | 'length' | 'content_filter' - -/** - * Maps Bedrock StopReason to TanStack AI finish reason. - * Uses the SDK's StopReason type for exhaustive handling. - * - * @param stopReason - The Bedrock stop reason from the stream event - * @param hasToolCalls - Whether tool calls were made in this response - * @returns The normalized TanStack AI finish reason - */ -function mapBedrockStopReason( - stopReason: StopReason | undefined, - hasToolCalls: boolean, -): FinishReason { - if (hasToolCalls || stopReason === 'tool_use') { - return 'tool_calls' - } - - switch (stopReason) { - case 'max_tokens': - case 'model_context_window_exceeded': - return 'length' - case 'content_filtered': - case 'guardrail_intervened': - return 'content_filter' - case 'end_turn': - case 'stop_sequence': - case undefined: - default: - return 'stop' - } -} - -/** - * Maps Bedrock TokenUsage to TanStack AI usage format. - * - * @param usage - The Bedrock token usage from the metadata event - * @returns The normalized TanStack AI usage object - */ -function mapBedrockTokenUsage(usage: TokenUsage | undefined): { - promptTokens: number - completionTokens: number - totalTokens: number -} | undefined { +function mapTokenUsage(usage: TokenUsage | undefined) { if (!usage) return undefined - return { promptTokens: usage.inputTokens ?? 0, completionTokens: usage.outputTokens ?? 0, @@ -376,7 +329,7 @@ export class Bedrock extends BaseAdapter< const result = (await response.json()) as ConverseResponse const outputMessage = result.output?.message const summary = outputMessage?.content?.map((block) => block.text || '').join('') ?? '' - const usage = mapBedrockTokenUsage(result.usage) + const usage = mapTokenUsage(result.usage) return { id: this.generateId(), @@ -842,7 +795,7 @@ export class Bedrock extends BaseAdapter< { id: string; name: string; input: string } >() let currentBlockIndex = -1 - let pendingFinishReason: FinishReason | null = null + let pendingFinishReason: 'stop' | 'tool_calls' | 'length' | 'content_filter' | null = null const reader = response.body?.getReader() if (!reader) { @@ -967,15 +920,22 @@ export class Bedrock extends BaseAdapter< } if (event.messageStop) { - pendingFinishReason = mapBedrockStopReason( - event.messageStop.stopReason, - toolCallMap.size > 0, - ) + const stopReason: StopReason | undefined = event.messageStop.stopReason + const hasToolCalls = toolCallMap.size > 0 + if (hasToolCalls || stopReason === 'tool_use') { + pendingFinishReason = 'tool_calls' + } else if (stopReason === 'max_tokens' || stopReason === 'model_context_window_exceeded') { + pendingFinishReason = 'length' + } else if (stopReason === 'content_filtered' || stopReason === 'guardrail_intervened') { + pendingFinishReason = 'content_filter' + } else { + pendingFinishReason = 'stop' + } } if (event.metadata) { const finishReason = pendingFinishReason ?? 'stop' - const usage = mapBedrockTokenUsage(event.metadata.usage) + const usage = mapTokenUsage(event.metadata.usage) yield { type: 'done', From 2ebfc20df27747610cea201e53274dd3674f143e Mon Sep 17 00:00:00 2001 From: Hunter Blackwell <31895576+chunterb@users.noreply.github.com> Date: Mon, 8 Dec 2025 16:49:02 -0600 Subject: [PATCH 5/7] fix: code cleanup and over abs --- .../ai-bedrock/src/bedrock-adapter.ts | 31 +++++++------------ 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/packages/typescript/ai-bedrock/src/bedrock-adapter.ts b/packages/typescript/ai-bedrock/src/bedrock-adapter.ts index 0cb30798..740a4c74 100644 --- a/packages/typescript/ai-bedrock/src/bedrock-adapter.ts +++ b/packages/typescript/ai-bedrock/src/bedrock-adapter.ts @@ -62,23 +62,6 @@ function mapTokenUsage(usage: TokenUsage | undefined) { } } -function toUint8Array(base64: string): Uint8Array { - if (typeof Buffer !== 'undefined') { - return Uint8Array.from(Buffer.from(base64, 'base64')) - } - - if (typeof atob !== 'undefined') { - const binary = atob(base64) - const bytes = new Uint8Array(binary.length) - for (let i = 0; i < binary.length; i++) { - bytes[i] = binary.charCodeAt(i) - } - return bytes - } - - throw new Error('Inline data sources require base64 decoding, which is not available in this environment') -} - /** * AWS credentials returned by a credential provider */ @@ -696,7 +679,7 @@ export class Bedrock extends BaseAdapter< return { image: { format, - source: { bytes: toUint8Array(part.source.value) }, + source: { bytes: base64ToBytes(part.source.value) }, }, } } @@ -720,7 +703,7 @@ export class Bedrock extends BaseAdapter< return { video: { format, - source: { bytes: toUint8Array(part.source.value) }, + source: { bytes: base64ToBytes(part.source.value) }, }, } } @@ -747,7 +730,7 @@ export class Bedrock extends BaseAdapter< document: { format, name, - source: { bytes: toUint8Array(part.source.value) }, + source: { bytes: base64ToBytes(part.source.value) }, }, } } @@ -1123,3 +1106,11 @@ export function createBedrock( export function bedrock(config?: BedrockConfig): Bedrock { return createBedrock(config) } + +function base64ToBytes(base64: string): Uint8Array { + if (typeof Buffer !== 'undefined') { + return Uint8Array.from(Buffer.from(base64, 'base64')) + } + const binary = atob(base64) + return Uint8Array.from(binary, (c) => c.charCodeAt(0)) +} From 44e85cf145c43d3529b8130290812ff51d1a1485 Mon Sep 17 00:00:00 2001 From: Hunter Blackwell <31895576+chunterb@users.noreply.github.com> Date: Mon, 8 Dec 2025 17:03:41 -0600 Subject: [PATCH 6/7] feat: supports options from aws --- .../typescript/ai-bedrock/src/model-meta.ts | 1298 +++++++++++------ 1 file changed, 870 insertions(+), 428 deletions(-) diff --git a/packages/typescript/ai-bedrock/src/model-meta.ts b/packages/typescript/ai-bedrock/src/model-meta.ts index 01cad6fd..533145e6 100644 --- a/packages/typescript/ai-bedrock/src/model-meta.ts +++ b/packages/typescript/ai-bedrock/src/model-meta.ts @@ -36,188 +36,263 @@ import type { BedrockReasoningEffortOptions, } from './text/text-provider-options' +/** + * Model metadata structure aligned with AWS Bedrock Converse API supported features. + * @see https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference-supported-models-features.html + */ interface ModelMeta { name: string id: string supports: { - input: Array<'text' | 'image' | 'audio' | 'video' | 'document'> - output: Array<'text' | 'image' | 'audio' | 'video' | 'embedding'> + converse: boolean + streaming: boolean + systemPrompts: boolean + documentChat: boolean + vision: boolean + toolUse: boolean + streamingToolUse: boolean + guardrails: boolean + s3Links: boolean reasoning?: boolean - tools?: boolean - streaming?: boolean } - context_window?: number - max_output_tokens?: number + contextWindow?: number + maxOutputTokens?: number providerOptions?: TProviderOptions } const NOVA_LITE = { name: 'Nova Lite', id: 'amazon.nova-lite-v1:0', - context_window: 300_000, - max_output_tokens: 5_000, + contextWindow: 300_000, + maxOutputTokens: 5_000, supports: { - input: ['text', 'image', 'video'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: true, + guardrails: true, + s3Links: true, }, } as const satisfies ModelMeta const NOVA_MICRO = { name: 'Nova Micro', id: 'amazon.nova-micro-v1:0', - context_window: 128_000, - max_output_tokens: 5_000, + contextWindow: 128_000, + maxOutputTokens: 5_000, supports: { - input: ['text'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: false, + vision: false, + toolUse: true, + streamingToolUse: true, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const NOVA_PRO = { name: 'Nova Pro', id: 'amazon.nova-pro-v1:0', - context_window: 300_000, - max_output_tokens: 5_000, + contextWindow: 300_000, + maxOutputTokens: 5_000, supports: { - input: ['text', 'image', 'video', 'document'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: true, + guardrails: true, + s3Links: true, }, } as const satisfies ModelMeta const US_NOVA_PREMIER = { name: 'Nova Premier', id: 'us.amazon.nova-premier-v1:0', - context_window: 1_000_000, - max_output_tokens: 32_000, - supports: { - input: ['text', 'image', 'video', 'document'], - output: ['text'], + contextWindow: 1_000_000, + maxOutputTokens: 32_000, + supports: { + converse: true, + streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: true, + guardrails: true, + s3Links: true, reasoning: true, - tools: true, - streaming: true, }, } as const satisfies ModelMeta const US_NOVA_2_LITE = { name: 'Nova 2 Lite', id: 'us.amazon.nova-2-lite-v1:0', - context_window: 1_000_000, - max_output_tokens: 32_000, - supports: { - input: ['text', 'image'], - output: ['text'], + contextWindow: 1_000_000, + maxOutputTokens: 32_000, + supports: { + converse: true, + streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: true, + guardrails: true, + s3Links: true, reasoning: true, - tools: true, - streaming: true, }, } as const satisfies ModelMeta const US_NOVA_2_SONIC = { name: 'Nova 2 Sonic', id: 'us.amazon.nova-2-sonic-v1:0', - context_window: 1_000_000, + contextWindow: 1_000_000, supports: { - input: ['audio', 'text'], - output: ['audio', 'text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: false, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: false, + s3Links: false, }, } as const satisfies ModelMeta const CLAUDE_3_HAIKU = { name: 'Claude 3 Haiku', id: 'anthropic.claude-3-haiku-20240307-v1:0', - context_window: 200_000, - max_output_tokens: 4_096, + contextWindow: 200_000, + maxOutputTokens: 4_096, supports: { - input: ['text', 'image', 'document'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: true, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const CLAUDE_3_SONNET = { name: 'Claude 3 Sonnet', id: 'anthropic.claude-3-sonnet-20240229-v1:0', - context_window: 200_000, - max_output_tokens: 4_096, + contextWindow: 200_000, + maxOutputTokens: 4_096, supports: { - input: ['text', 'image', 'document'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: true, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const CLAUDE_3_OPUS = { name: 'Claude 3 Opus', id: 'anthropic.claude-3-opus-20240229-v1:0', - context_window: 200_000, - max_output_tokens: 4_096, + contextWindow: 200_000, + maxOutputTokens: 4_096, supports: { - input: ['text', 'image', 'document'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: true, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const CLAUDE_3_5_HAIKU = { name: 'Claude 3.5 Haiku', id: 'anthropic.claude-3-5-haiku-20241022-v1:0', - context_window: 200_000, - max_output_tokens: 8_192, + contextWindow: 200_000, + maxOutputTokens: 8_192, supports: { - input: ['text', 'image', 'document'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: true, + streamingToolUse: true, + guardrails: false, + s3Links: false, }, } as const satisfies ModelMeta const CLAUDE_3_5_SONNET = { name: 'Claude 3.5 Sonnet', id: 'anthropic.claude-3-5-sonnet-20240620-v1:0', - context_window: 200_000, - max_output_tokens: 8_192, + contextWindow: 200_000, + maxOutputTokens: 8_192, supports: { - input: ['text', 'image', 'document'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: true, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const CLAUDE_3_5_SONNET_V2 = { name: 'Claude 3.5 Sonnet v2', id: 'anthropic.claude-3-5-sonnet-20241022-v2:0', - context_window: 200_000, - max_output_tokens: 8_192, + contextWindow: 200_000, + maxOutputTokens: 8_192, supports: { - input: ['text', 'image', 'document'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: true, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const CLAUDE_3_7_SONNET = { name: 'Claude 3.7 Sonnet', id: 'anthropic.claude-3-7-sonnet-20250219-v1:0', - context_window: 200_000, - max_output_tokens: 64_000, - supports: { - input: ['text', 'image', 'document'], - output: ['text'], + contextWindow: 200_000, + maxOutputTokens: 64_000, + supports: { + converse: true, + streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: true, + guardrails: true, + s3Links: false, reasoning: true, - tools: true, - streaming: true, }, } as const satisfies ModelMeta< BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions @@ -226,14 +301,19 @@ const CLAUDE_3_7_SONNET = { const CLAUDE_HAIKU_4_5 = { name: 'Claude Haiku 4.5', id: 'anthropic.claude-haiku-4-5-20251001-v1:0', - context_window: 200_000, - max_output_tokens: 64_000, - supports: { - input: ['text', 'image', 'document'], - output: ['text'], + contextWindow: 200_000, + maxOutputTokens: 64_000, + supports: { + converse: true, + streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: true, + guardrails: false, + s3Links: false, reasoning: true, - tools: true, - streaming: true, }, } as const satisfies ModelMeta< BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions @@ -242,14 +322,19 @@ const CLAUDE_HAIKU_4_5 = { const CLAUDE_SONNET_4 = { name: 'Claude Sonnet 4', id: 'anthropic.claude-sonnet-4-20250514-v1:0', - context_window: 200_000, - max_output_tokens: 64_000, - supports: { - input: ['text', 'image', 'document'], - output: ['text'], + contextWindow: 200_000, + maxOutputTokens: 64_000, + supports: { + converse: true, + streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: true, + guardrails: false, + s3Links: false, reasoning: true, - tools: true, - streaming: true, }, } as const satisfies ModelMeta< BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions @@ -258,14 +343,19 @@ const CLAUDE_SONNET_4 = { const CLAUDE_SONNET_4_5 = { name: 'Claude Sonnet 4.5', id: 'anthropic.claude-sonnet-4-5-20250929-v1:0', - context_window: 200_000, - max_output_tokens: 64_000, - supports: { - input: ['text', 'image', 'document'], - output: ['text'], + contextWindow: 200_000, + maxOutputTokens: 64_000, + supports: { + converse: true, + streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: true, + guardrails: false, + s3Links: false, reasoning: true, - tools: true, - streaming: true, }, } as const satisfies ModelMeta< BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions @@ -274,14 +364,19 @@ const CLAUDE_SONNET_4_5 = { const CLAUDE_OPUS_4 = { name: 'Claude Opus 4', id: 'anthropic.claude-opus-4-20250514-v1:0', - context_window: 200_000, - max_output_tokens: 32_000, - supports: { - input: ['text', 'image', 'document'], - output: ['text'], + contextWindow: 200_000, + maxOutputTokens: 32_000, + supports: { + converse: true, + streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: true, + guardrails: false, + s3Links: false, reasoning: true, - tools: true, - streaming: true, }, } as const satisfies ModelMeta< BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions @@ -290,14 +385,19 @@ const CLAUDE_OPUS_4 = { const CLAUDE_OPUS_4_1 = { name: 'Claude Opus 4.1', id: 'anthropic.claude-opus-4-1-20250805-v1:0', - context_window: 200_000, - max_output_tokens: 64_000, - supports: { - input: ['text', 'image', 'document'], - output: ['text'], + contextWindow: 200_000, + maxOutputTokens: 64_000, + supports: { + converse: true, + streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: true, + guardrails: false, + s3Links: false, reasoning: true, - tools: true, - streaming: true, }, } as const satisfies ModelMeta< BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions @@ -306,617 +406,901 @@ const CLAUDE_OPUS_4_1 = { const LLAMA_3_8B = { name: 'Llama 3 8B Instruct', id: 'meta.llama3-8b-instruct-v1:0', - context_window: 8_192, - max_output_tokens: 2_048, + contextWindow: 8_192, + maxOutputTokens: 2_048, supports: { - input: ['text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const LLAMA_3_70B = { name: 'Llama 3 70B Instruct', id: 'meta.llama3-70b-instruct-v1:0', - context_window: 8_192, - max_output_tokens: 2_048, + contextWindow: 8_192, + maxOutputTokens: 2_048, supports: { - input: ['text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const LLAMA_3_1_8B = { name: 'Llama 3.1 8B Instruct', id: 'meta.llama3-1-8b-instruct-v1:0', - context_window: 128_000, - max_output_tokens: 2_048, + contextWindow: 128_000, + maxOutputTokens: 2_048, supports: { - input: ['text'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: true, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const LLAMA_3_1_70B = { name: 'Llama 3.1 70B Instruct', id: 'meta.llama3-1-70b-instruct-v1:0', - context_window: 128_000, - max_output_tokens: 2_048, + contextWindow: 128_000, + maxOutputTokens: 2_048, supports: { - input: ['text'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: true, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const LLAMA_3_1_405B = { name: 'Llama 3.1 405B Instruct', id: 'meta.llama3-1-405b-instruct-v1:0', - context_window: 128_000, - max_output_tokens: 2_048, + contextWindow: 128_000, + maxOutputTokens: 2_048, supports: { - input: ['text'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: true, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const LLAMA_3_2_1B = { name: 'Llama 3.2 1B Instruct', id: 'meta.llama3-2-1b-instruct-v1:0', - context_window: 128_000, - max_output_tokens: 2_048, + contextWindow: 128_000, + maxOutputTokens: 2_048, supports: { - input: ['text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const LLAMA_3_2_3B = { name: 'Llama 3.2 3B Instruct', id: 'meta.llama3-2-3b-instruct-v1:0', - context_window: 128_000, - max_output_tokens: 2_048, + contextWindow: 128_000, + maxOutputTokens: 2_048, supports: { - input: ['text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const LLAMA_3_2_11B = { name: 'Llama 3.2 11B Vision Instruct', id: 'meta.llama3-2-11b-instruct-v1:0', - context_window: 128_000, - max_output_tokens: 2_048, + contextWindow: 128_000, + maxOutputTokens: 2_048, supports: { - input: ['text', 'image'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const LLAMA_3_2_90B = { name: 'Llama 3.2 90B Vision Instruct', id: 'meta.llama3-2-90b-instruct-v1:0', - context_window: 128_000, - max_output_tokens: 2_048, + contextWindow: 128_000, + maxOutputTokens: 2_048, supports: { - input: ['text', 'image'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const LLAMA_3_3_70B = { name: 'Llama 3.3 70B Instruct', id: 'meta.llama3-3-70b-instruct-v1:0', - context_window: 128_000, - max_output_tokens: 2_048, + contextWindow: 128_000, + maxOutputTokens: 2_048, supports: { - input: ['text'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: true, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const LLAMA_4_SCOUT = { name: 'Llama 4 Scout 17B Instruct', id: 'meta.llama4-scout-17b-instruct-v1:0', - context_window: 3_500_000, - max_output_tokens: 16_384, + contextWindow: 3_500_000, + maxOutputTokens: 16_384, supports: { - input: ['text', 'image'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const LLAMA_4_MAVERICK = { name: 'Llama 4 Maverick 17B Instruct', id: 'meta.llama4-maverick-17b-instruct-v1:0', - context_window: 1_000_000, - max_output_tokens: 16_384, + contextWindow: 1_000_000, + maxOutputTokens: 16_384, supports: { - input: ['text', 'image'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const MISTRAL_7B = { name: 'Mistral 7B Instruct', id: 'mistral.mistral-7b-instruct-v0:2', - context_window: 32_768, - max_output_tokens: 8_192, + contextWindow: 32_768, + maxOutputTokens: 8_192, supports: { - input: ['text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: false, + documentChat: true, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const MIXTRAL_8X7B = { name: 'Mixtral 8x7B Instruct', id: 'mistral.mixtral-8x7b-instruct-v0:1', - context_window: 32_768, - max_output_tokens: 4_096, + contextWindow: 32_768, + maxOutputTokens: 4_096, supports: { - input: ['text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: false, + documentChat: true, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const MISTRAL_LARGE_2402 = { name: 'Mistral Large (24.02)', id: 'mistral.mistral-large-2402-v1:0', - context_window: 32_768, - max_output_tokens: 8_192, + contextWindow: 32_768, + maxOutputTokens: 8_192, supports: { - input: ['text'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: true, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const MISTRAL_LARGE_2407 = { name: 'Mistral Large (24.07)', id: 'mistral.mistral-large-2407-v1:0', - context_window: 128_000, - max_output_tokens: 8_192, + contextWindow: 128_000, + maxOutputTokens: 8_192, supports: { - input: ['text'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: true, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const MISTRAL_SMALL_2402 = { name: 'Mistral Small (24.02)', id: 'mistral.mistral-small-2402-v1:0', - context_window: 32_768, - max_output_tokens: 8_192, + contextWindow: 32_768, + maxOutputTokens: 8_192, supports: { - input: ['text'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: false, + vision: false, + toolUse: true, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const US_PIXTRAL_LARGE = { name: 'Pixtral Large (25.02)', id: 'us.mistral.pixtral-large-2502-v1:0', - context_window: 128_000, - max_output_tokens: 8_192, + contextWindow: 128_000, + maxOutputTokens: 8_192, supports: { - input: ['text', 'image'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const MISTRAL_LARGE_3 = { name: 'Mistral Large 3', id: 'mistral.mistral-large-3-675b-instruct', - context_window: 128_000, - max_output_tokens: 8_192, + contextWindow: 128_000, + maxOutputTokens: 8_192, supports: { - input: ['text', 'image'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const MINISTRAL_3_3B = { name: 'Ministral 3 3B', id: 'mistral.ministral-3-3b-instruct', - context_window: 128_000, - max_output_tokens: 8_192, + contextWindow: 128_000, + maxOutputTokens: 8_192, supports: { - input: ['text', 'image'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const MINISTRAL_3_8B = { name: 'Ministral 3 8B', id: 'mistral.ministral-3-8b-instruct', - context_window: 128_000, - max_output_tokens: 8_192, + contextWindow: 128_000, + maxOutputTokens: 8_192, supports: { - input: ['text', 'image'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const MINISTRAL_3_14B = { name: 'Ministral 3 14B', id: 'mistral.ministral-3-14b-instruct', - context_window: 128_000, - max_output_tokens: 8_192, + contextWindow: 128_000, + maxOutputTokens: 8_192, supports: { - input: ['text', 'image'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const MAGISTRAL_SMALL = { name: 'Magistral Small', id: 'mistral.magistral-small-2509', - context_window: 128_000, - max_output_tokens: 8_192, - supports: { - input: ['text', 'image'], - output: ['text'], + contextWindow: 128_000, + maxOutputTokens: 8_192, + supports: { + converse: true, + streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, reasoning: true, - streaming: true, }, } as const satisfies ModelMeta const VOXTRAL_MINI = { name: 'Voxtral Mini 3B', id: 'mistral.voxtral-mini-3b-2507', - context_window: 32_768, + contextWindow: 32_768, supports: { - input: ['audio', 'text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: false, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const VOXTRAL_SMALL = { name: 'Voxtral Small 24B', id: 'mistral.voxtral-small-24b-2507', - context_window: 32_768, + contextWindow: 32_768, supports: { - input: ['audio', 'text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: false, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const TITAN_TEXT_LARGE = { name: 'Titan Text Large', id: 'amazon.titan-tg1-large', - context_window: 8_000, - max_output_tokens: 8_000, + contextWindow: 8_000, + maxOutputTokens: 8_000, supports: { - input: ['text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: false, + documentChat: true, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const TITAN_TEXT_EXPRESS = { name: 'Titan Text Express', id: 'amazon.titan-text-express-v1', - context_window: 8_000, - max_output_tokens: 8_000, + contextWindow: 8_000, + maxOutputTokens: 8_000, supports: { - input: ['text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: false, + documentChat: true, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const TITAN_TEXT_LITE = { name: 'Titan Text Lite', id: 'amazon.titan-text-lite-v1', - context_window: 4_000, - max_output_tokens: 4_000, + contextWindow: 4_000, + maxOutputTokens: 4_000, supports: { - input: ['text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: false, + documentChat: true, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const COHERE_COMMAND_TEXT = { name: 'Command Text', id: 'cohere.command-text-v14', - context_window: 4_096, - max_output_tokens: 4_096, + contextWindow: 4_096, + maxOutputTokens: 4_096, supports: { - input: ['text'], - output: ['text'], - streaming: true, + converse: false, + streaming: false, + systemPrompts: false, + documentChat: true, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const COHERE_COMMAND_LIGHT = { name: 'Command Light', id: 'cohere.command-light-text-v14', - context_window: 4_096, - max_output_tokens: 4_096, + contextWindow: 4_096, + maxOutputTokens: 4_096, supports: { - input: ['text'], - output: ['text'], - streaming: true, + converse: false, + streaming: false, + systemPrompts: false, + documentChat: false, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const COHERE_COMMAND_R = { name: 'Command R', id: 'cohere.command-r-v1:0', - context_window: 128_000, - max_output_tokens: 4_096, + contextWindow: 128_000, + maxOutputTokens: 4_096, supports: { - input: ['text'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: true, + streamingToolUse: true, + guardrails: false, + s3Links: false, }, } as const satisfies ModelMeta const COHERE_COMMAND_R_PLUS = { name: 'Command R+', id: 'cohere.command-r-plus-v1:0', - context_window: 128_000, - max_output_tokens: 4_096, + contextWindow: 128_000, + maxOutputTokens: 4_096, supports: { - input: ['text'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: true, + streamingToolUse: true, + guardrails: false, + s3Links: false, }, } as const satisfies ModelMeta const DEEPSEEK_R1 = { name: 'DeepSeek R1', id: 'deepseek.r1-v1:0', - context_window: 64_000, - max_output_tokens: 8_192, - supports: { - input: ['text'], - output: ['text'], + contextWindow: 64_000, + maxOutputTokens: 8_192, + supports: { + converse: true, + streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, reasoning: true, - streaming: true, }, } as const satisfies ModelMeta const DEEPSEEK_V3 = { name: 'DeepSeek V3', id: 'deepseek.v3-v1:0', - context_window: 64_000, - max_output_tokens: 8_192, + contextWindow: 64_000, + maxOutputTokens: 8_192, supports: { - input: ['text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const AI21_JAMBA_LARGE = { name: 'Jamba 1.5 Large', id: 'ai21.jamba-1-5-large-v1:0', - context_window: 256_000, - max_output_tokens: 4_096, + contextWindow: 256_000, + maxOutputTokens: 4_096, supports: { - input: ['text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: true, + streamingToolUse: true, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const AI21_JAMBA_MINI = { name: 'Jamba 1.5 Mini', id: 'ai21.jamba-1-5-mini-v1:0', - context_window: 256_000, - max_output_tokens: 4_096, + contextWindow: 256_000, + maxOutputTokens: 4_096, supports: { - input: ['text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: true, + streamingToolUse: true, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const WRITER_PALMYRA_X4 = { name: 'Palmyra X4', id: 'writer.palmyra-x4-v1:0', - context_window: 128_000, - max_output_tokens: 8_192, + contextWindow: 128_000, + maxOutputTokens: 8_192, supports: { - input: ['text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: true, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const WRITER_PALMYRA_X5 = { name: 'Palmyra X5', id: 'writer.palmyra-x5-v1:0', - context_window: 128_000, - max_output_tokens: 8_192, + contextWindow: 128_000, + maxOutputTokens: 8_192, supports: { - input: ['text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: true, + vision: false, + toolUse: true, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const GEMMA_3_4B = { name: 'Gemma 3 4B IT', id: 'google.gemma-3-4b-it', - context_window: 32_768, - max_output_tokens: 8_192, + contextWindow: 32_768, + maxOutputTokens: 8_192, supports: { - input: ['text', 'image'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: false, + vision: true, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const GEMMA_3_12B = { name: 'Gemma 3 12B IT', id: 'google.gemma-3-12b-it', - context_window: 32_768, - max_output_tokens: 8_192, + contextWindow: 32_768, + maxOutputTokens: 8_192, supports: { - input: ['text', 'image'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: false, + vision: true, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const GEMMA_3_27B = { name: 'Gemma 3 27B IT', id: 'google.gemma-3-27b-it', - context_window: 32_768, - max_output_tokens: 8_192, + contextWindow: 32_768, + maxOutputTokens: 8_192, supports: { - input: ['text', 'image'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: false, + vision: true, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const NVIDIA_NEMOTRON_9B = { name: 'NVIDIA Nemotron Nano 9B v2', id: 'nvidia.nemotron-nano-9b-v2', - context_window: 32_768, - max_output_tokens: 8_192, - supports: { - input: ['text'], - output: ['text'], + contextWindow: 32_768, + maxOutputTokens: 8_192, + supports: { + converse: true, + streaming: true, + systemPrompts: true, + documentChat: false, + vision: false, + toolUse: true, + streamingToolUse: false, + guardrails: true, + s3Links: false, reasoning: true, - tools: true, - streaming: true, }, } as const satisfies ModelMeta const NVIDIA_NEMOTRON_12B_VL = { name: 'NVIDIA Nemotron Nano 12B v2 VL', id: 'nvidia.nemotron-nano-12b-v2', - context_window: 32_768, - max_output_tokens: 8_192, + contextWindow: 32_768, + maxOutputTokens: 8_192, supports: { - input: ['text', 'image', 'video'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: false, + vision: true, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const MINIMAX_M2 = { name: 'MiniMax M2', id: 'minimax.minimax-m2', - context_window: 128_000, - max_output_tokens: 8_192, + contextWindow: 128_000, + maxOutputTokens: 8_192, supports: { - input: ['text'], - output: ['text'], - tools: true, + converse: true, streaming: true, + systemPrompts: true, + documentChat: false, + vision: false, + toolUse: true, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const MOONSHOT_KIMI_K2 = { name: 'Kimi K2 Thinking', id: 'moonshot.kimi-k2-thinking', - context_window: 128_000, - max_output_tokens: 8_192, - supports: { - input: ['text'], - output: ['text'], + contextWindow: 128_000, + maxOutputTokens: 8_192, + supports: { + converse: true, + streaming: true, + systemPrompts: true, + documentChat: false, + vision: false, + toolUse: true, + streamingToolUse: false, + guardrails: true, + s3Links: false, reasoning: true, - tools: true, - streaming: true, }, } as const satisfies ModelMeta const OPENAI_SAFEGUARD_20B = { name: 'GPT OSS Safeguard 20B', id: 'openai.gpt-oss-safeguard-20b', - context_window: 128_000, - max_output_tokens: 8_192, + contextWindow: 128_000, + maxOutputTokens: 8_192, supports: { - input: ['text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: false, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const OPENAI_SAFEGUARD_120B = { name: 'GPT OSS Safeguard 120B', id: 'openai.gpt-oss-safeguard-120b', - context_window: 128_000, - max_output_tokens: 8_192, + contextWindow: 128_000, + maxOutputTokens: 8_192, supports: { - input: ['text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: false, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const QWEN_3_NEXT_80B = { name: 'Qwen3 Next 80B A3B Instruct', id: 'qwen.qwen3-next-80b-a3b', - context_window: 128_000, - max_output_tokens: 8_192, + contextWindow: 128_000, + maxOutputTokens: 8_192, supports: { - input: ['text'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: false, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const QWEN_3_VL_235B = { name: 'Qwen3 VL 235B A22B', id: 'qwen.qwen3-vl-235b-a22b', - context_window: 128_000, - max_output_tokens: 8_192, + contextWindow: 128_000, + maxOutputTokens: 8_192, supports: { - input: ['text', 'image'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: false, + vision: true, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta const TWELVELABS_PEGASUS = { name: 'Pegasus v1.2', id: 'twelvelabs.pegasus-v1.2:0', - context_window: 128_000, + contextWindow: 128_000, supports: { - input: ['text', 'video'], - output: ['text'], + converse: true, streaming: true, + systemPrompts: true, + documentChat: false, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: true, + s3Links: false, }, } as const satisfies ModelMeta @@ -924,42 +1308,66 @@ const LUMA_RAY_V2 = { name: 'Ray v2', id: 'luma.ray-v2:0', supports: { - input: ['text'], - output: ['video'], + converse: false, streaming: false, + systemPrompts: false, + documentChat: false, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: false, + s3Links: false, }, } as const satisfies ModelMeta const TITAN_EMBED_TEXT_V1 = { name: 'Titan Embeddings G1 - Text', id: 'amazon.titan-embed-text-v1', - context_window: 8_192, + contextWindow: 8_192, supports: { - input: ['text'], - output: ['embedding'], + converse: false, streaming: false, + systemPrompts: false, + documentChat: false, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: false, + s3Links: false, }, } as const satisfies ModelMeta const TITAN_EMBED_TEXT_V2 = { name: 'Titan Text Embeddings V2', id: 'amazon.titan-embed-text-v2:0', - context_window: 8_192, + contextWindow: 8_192, supports: { - input: ['text'], - output: ['embedding'], + converse: false, streaming: false, + systemPrompts: false, + documentChat: false, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: false, + s3Links: false, }, } as const satisfies ModelMeta const TITAN_EMBED_IMAGE = { name: 'Titan Multimodal Embeddings G1', id: 'amazon.titan-embed-image-v1', - context_window: 256, + contextWindow: 256, supports: { - input: ['text', 'image'], - output: ['embedding'], + converse: false, streaming: false, + systemPrompts: false, + documentChat: false, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: false, + s3Links: false, }, } as const satisfies ModelMeta @@ -967,42 +1375,66 @@ const NOVA_MULTIMODAL_EMBED = { name: 'Nova 2 Multimodal Embeddings', id: 'amazon.nova-2-multimodal-embeddings-v1:0', supports: { - input: ['text', 'image', 'audio', 'video'], - output: ['embedding'], + converse: false, streaming: false, + systemPrompts: false, + documentChat: false, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: false, + s3Links: false, }, } as const satisfies ModelMeta const COHERE_EMBED_ENGLISH = { name: 'Cohere Embed English v3', id: 'cohere.embed-english-v3', - context_window: 512, + contextWindow: 512, supports: { - input: ['text'], - output: ['embedding'], + converse: false, streaming: false, + systemPrompts: false, + documentChat: false, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: false, + s3Links: false, }, } as const satisfies ModelMeta const COHERE_EMBED_MULTILINGUAL = { name: 'Cohere Embed Multilingual v3', id: 'cohere.embed-multilingual-v3', - context_window: 512, + contextWindow: 512, supports: { - input: ['text'], - output: ['embedding'], + converse: false, streaming: false, + systemPrompts: false, + documentChat: false, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: false, + s3Links: false, }, } as const satisfies ModelMeta const COHERE_EMBED_V4 = { name: 'Cohere Embed v4', id: 'cohere.embed-v4:0', - context_window: 128_000, + contextWindow: 128_000, supports: { - input: ['text', 'image'], - output: ['embedding'], + converse: false, streaming: false, + systemPrompts: false, + documentChat: false, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: false, + s3Links: false, }, } as const satisfies ModelMeta @@ -1010,9 +1442,15 @@ const TWELVELABS_MARENGO_EMBED = { name: 'Marengo Embed v2.7', id: 'twelvelabs.marengo-embed-2-7-v1:0', supports: { - input: ['video'], - output: ['embedding'], + converse: false, streaming: false, + systemPrompts: false, + documentChat: false, + vision: false, + toolUse: false, + streamingToolUse: false, + guardrails: false, + s3Links: false, }, } as const satisfies ModelMeta @@ -1187,82 +1625,86 @@ export type BedrockChatModelProviderOptionsByName = { [QWEN_3_VL_235B.id]: BedrockProviderOptions } +type TextOnly = readonly ['text'] +type TextImage = readonly ['text', 'image'] +type TextImageDocument = readonly ['text', 'image', 'document'] +type TextDocument = readonly ['text', 'document'] + /** * Type-only map from Bedrock model name to its supported input modalities. - * Used by the core AI types to constrain ContentPart types based on the selected model. + * Derived from the supports.vision and supports.documentChat flags. * * @see https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html */ export type BedrockModelInputModalitiesByName = { - [NOVA_LITE.id]: typeof NOVA_LITE.supports.input - [NOVA_MICRO.id]: typeof NOVA_MICRO.supports.input - [NOVA_PRO.id]: typeof NOVA_PRO.supports.input - [US_NOVA_PREMIER.id]: typeof US_NOVA_PREMIER.supports.input - [US_NOVA_2_LITE.id]: typeof US_NOVA_2_LITE.supports.input - [US_NOVA_2_SONIC.id]: typeof US_NOVA_2_SONIC.supports.input - [CLAUDE_3_HAIKU.id]: typeof CLAUDE_3_HAIKU.supports.input - [CLAUDE_3_SONNET.id]: typeof CLAUDE_3_SONNET.supports.input - [CLAUDE_3_OPUS.id]: typeof CLAUDE_3_OPUS.supports.input - [CLAUDE_3_5_HAIKU.id]: typeof CLAUDE_3_5_HAIKU.supports.input - [CLAUDE_3_5_SONNET.id]: typeof CLAUDE_3_5_SONNET.supports.input - [CLAUDE_3_5_SONNET_V2.id]: typeof CLAUDE_3_5_SONNET_V2.supports.input - [CLAUDE_3_7_SONNET.id]: typeof CLAUDE_3_7_SONNET.supports.input - [CLAUDE_HAIKU_4_5.id]: typeof CLAUDE_HAIKU_4_5.supports.input - [CLAUDE_SONNET_4.id]: typeof CLAUDE_SONNET_4.supports.input - [CLAUDE_SONNET_4_5.id]: typeof CLAUDE_SONNET_4_5.supports.input - [CLAUDE_OPUS_4.id]: typeof CLAUDE_OPUS_4.supports.input - [CLAUDE_OPUS_4_1.id]: typeof CLAUDE_OPUS_4_1.supports.input - [LLAMA_3_8B.id]: typeof LLAMA_3_8B.supports.input - [LLAMA_3_70B.id]: typeof LLAMA_3_70B.supports.input - [LLAMA_3_1_8B.id]: typeof LLAMA_3_1_8B.supports.input - [LLAMA_3_1_70B.id]: typeof LLAMA_3_1_70B.supports.input - [LLAMA_3_1_405B.id]: typeof LLAMA_3_1_405B.supports.input - [LLAMA_3_2_1B.id]: typeof LLAMA_3_2_1B.supports.input - [LLAMA_3_2_3B.id]: typeof LLAMA_3_2_3B.supports.input - [LLAMA_3_2_11B.id]: typeof LLAMA_3_2_11B.supports.input - [LLAMA_3_2_90B.id]: typeof LLAMA_3_2_90B.supports.input - [LLAMA_3_3_70B.id]: typeof LLAMA_3_3_70B.supports.input - [LLAMA_4_SCOUT.id]: typeof LLAMA_4_SCOUT.supports.input - [LLAMA_4_MAVERICK.id]: typeof LLAMA_4_MAVERICK.supports.input - [MISTRAL_7B.id]: typeof MISTRAL_7B.supports.input - [MIXTRAL_8X7B.id]: typeof MIXTRAL_8X7B.supports.input - [MISTRAL_LARGE_2402.id]: typeof MISTRAL_LARGE_2402.supports.input - [MISTRAL_LARGE_2407.id]: typeof MISTRAL_LARGE_2407.supports.input - [MISTRAL_SMALL_2402.id]: typeof MISTRAL_SMALL_2402.supports.input - [US_PIXTRAL_LARGE.id]: typeof US_PIXTRAL_LARGE.supports.input - [TITAN_TEXT_LARGE.id]: typeof TITAN_TEXT_LARGE.supports.input - [TITAN_TEXT_EXPRESS.id]: typeof TITAN_TEXT_EXPRESS.supports.input - [TITAN_TEXT_LITE.id]: typeof TITAN_TEXT_LITE.supports.input - [COHERE_COMMAND_TEXT.id]: typeof COHERE_COMMAND_TEXT.supports.input - [COHERE_COMMAND_LIGHT.id]: typeof COHERE_COMMAND_LIGHT.supports.input - [COHERE_COMMAND_R.id]: typeof COHERE_COMMAND_R.supports.input - [COHERE_COMMAND_R_PLUS.id]: typeof COHERE_COMMAND_R_PLUS.supports.input - [DEEPSEEK_R1.id]: typeof DEEPSEEK_R1.supports.input - [DEEPSEEK_V3.id]: typeof DEEPSEEK_V3.supports.input - [AI21_JAMBA_LARGE.id]: typeof AI21_JAMBA_LARGE.supports.input - [AI21_JAMBA_MINI.id]: typeof AI21_JAMBA_MINI.supports.input - [WRITER_PALMYRA_X4.id]: typeof WRITER_PALMYRA_X4.supports.input - [WRITER_PALMYRA_X5.id]: typeof WRITER_PALMYRA_X5.supports.input - [TWELVELABS_PEGASUS.id]: typeof TWELVELABS_PEGASUS.supports.input - [LUMA_RAY_V2.id]: typeof LUMA_RAY_V2.supports.input - [MISTRAL_LARGE_3.id]: typeof MISTRAL_LARGE_3.supports.input - [MINISTRAL_3_3B.id]: typeof MINISTRAL_3_3B.supports.input - [MINISTRAL_3_8B.id]: typeof MINISTRAL_3_8B.supports.input - [MINISTRAL_3_14B.id]: typeof MINISTRAL_3_14B.supports.input - [MAGISTRAL_SMALL.id]: typeof MAGISTRAL_SMALL.supports.input - [VOXTRAL_MINI.id]: typeof VOXTRAL_MINI.supports.input - [VOXTRAL_SMALL.id]: typeof VOXTRAL_SMALL.supports.input - [GEMMA_3_4B.id]: typeof GEMMA_3_4B.supports.input - [GEMMA_3_12B.id]: typeof GEMMA_3_12B.supports.input - [GEMMA_3_27B.id]: typeof GEMMA_3_27B.supports.input - [NVIDIA_NEMOTRON_9B.id]: typeof NVIDIA_NEMOTRON_9B.supports.input - [NVIDIA_NEMOTRON_12B_VL.id]: typeof NVIDIA_NEMOTRON_12B_VL.supports.input - [MINIMAX_M2.id]: typeof MINIMAX_M2.supports.input - [MOONSHOT_KIMI_K2.id]: typeof MOONSHOT_KIMI_K2.supports.input - [OPENAI_SAFEGUARD_20B.id]: typeof OPENAI_SAFEGUARD_20B.supports.input - [OPENAI_SAFEGUARD_120B.id]: typeof OPENAI_SAFEGUARD_120B.supports.input - [QWEN_3_NEXT_80B.id]: typeof QWEN_3_NEXT_80B.supports.input - [QWEN_3_VL_235B.id]: typeof QWEN_3_VL_235B.supports.input + [NOVA_LITE.id]: TextImageDocument + [NOVA_MICRO.id]: TextOnly + [NOVA_PRO.id]: TextImageDocument + [US_NOVA_PREMIER.id]: TextImageDocument + [US_NOVA_2_LITE.id]: TextImageDocument + [US_NOVA_2_SONIC.id]: TextOnly + [CLAUDE_3_HAIKU.id]: TextImageDocument + [CLAUDE_3_SONNET.id]: TextImageDocument + [CLAUDE_3_OPUS.id]: TextImageDocument + [CLAUDE_3_5_HAIKU.id]: TextDocument + [CLAUDE_3_5_SONNET.id]: TextImageDocument + [CLAUDE_3_5_SONNET_V2.id]: TextImageDocument + [CLAUDE_3_7_SONNET.id]: TextImageDocument + [CLAUDE_HAIKU_4_5.id]: TextImageDocument + [CLAUDE_SONNET_4.id]: TextImageDocument + [CLAUDE_SONNET_4_5.id]: TextImageDocument + [CLAUDE_OPUS_4.id]: TextImageDocument + [CLAUDE_OPUS_4_1.id]: TextImageDocument + [LLAMA_3_8B.id]: TextDocument + [LLAMA_3_70B.id]: TextDocument + [LLAMA_3_1_8B.id]: TextDocument + [LLAMA_3_1_70B.id]: TextDocument + [LLAMA_3_1_405B.id]: TextDocument + [LLAMA_3_2_1B.id]: TextDocument + [LLAMA_3_2_3B.id]: TextDocument + [LLAMA_3_2_11B.id]: TextImageDocument + [LLAMA_3_2_90B.id]: TextImageDocument + [LLAMA_3_3_70B.id]: TextDocument + [LLAMA_4_SCOUT.id]: TextImageDocument + [LLAMA_4_MAVERICK.id]: TextImageDocument + [MISTRAL_7B.id]: TextDocument + [MIXTRAL_8X7B.id]: TextDocument + [MISTRAL_LARGE_2402.id]: TextDocument + [MISTRAL_LARGE_2407.id]: TextDocument + [MISTRAL_SMALL_2402.id]: TextOnly + [US_PIXTRAL_LARGE.id]: TextImageDocument + [TITAN_TEXT_LARGE.id]: TextDocument + [TITAN_TEXT_EXPRESS.id]: TextDocument + [TITAN_TEXT_LITE.id]: TextDocument + [COHERE_COMMAND_TEXT.id]: TextDocument + [COHERE_COMMAND_LIGHT.id]: TextOnly + [COHERE_COMMAND_R.id]: TextDocument + [COHERE_COMMAND_R_PLUS.id]: TextDocument + [DEEPSEEK_R1.id]: TextDocument + [DEEPSEEK_V3.id]: TextDocument + [AI21_JAMBA_LARGE.id]: TextDocument + [AI21_JAMBA_MINI.id]: TextDocument + [WRITER_PALMYRA_X4.id]: TextDocument + [WRITER_PALMYRA_X5.id]: TextDocument + [TWELVELABS_PEGASUS.id]: TextOnly + [LUMA_RAY_V2.id]: TextOnly + [MISTRAL_LARGE_3.id]: TextImageDocument + [MINISTRAL_3_3B.id]: TextImageDocument + [MINISTRAL_3_8B.id]: TextImageDocument + [MINISTRAL_3_14B.id]: TextImageDocument + [MAGISTRAL_SMALL.id]: TextImageDocument + [VOXTRAL_MINI.id]: TextOnly + [VOXTRAL_SMALL.id]: TextOnly + [GEMMA_3_4B.id]: TextImage + [GEMMA_3_12B.id]: TextImage + [GEMMA_3_27B.id]: TextImage + [NVIDIA_NEMOTRON_9B.id]: TextOnly + [NVIDIA_NEMOTRON_12B_VL.id]: TextImage + [MINIMAX_M2.id]: TextOnly + [MOONSHOT_KIMI_K2.id]: TextOnly + [OPENAI_SAFEGUARD_20B.id]: TextOnly + [OPENAI_SAFEGUARD_120B.id]: TextOnly + [QWEN_3_NEXT_80B.id]: TextOnly + [QWEN_3_VL_235B.id]: TextImage } - From d6d66fbd93dac97000a83346fd072750ed933a76 Mon Sep 17 00:00:00 2001 From: Hunter Blackwell <31895576+chunterb@users.noreply.github.com> Date: Tue, 9 Dec 2025 17:25:26 -0600 Subject: [PATCH 7/7] feat: aws bedrock inference profiles --- .../ai-bedrock/src/bedrock-adapter.ts | 92 +++++- .../ai-bedrock/src/bedrock-regions.ts | 49 +++ packages/typescript/ai-bedrock/src/index.ts | 11 +- .../typescript/ai-bedrock/src/model-meta.ts | 292 ++++++++++++------ 4 files changed, 353 insertions(+), 91 deletions(-) create mode 100644 packages/typescript/ai-bedrock/src/bedrock-regions.ts diff --git a/packages/typescript/ai-bedrock/src/bedrock-adapter.ts b/packages/typescript/ai-bedrock/src/bedrock-adapter.ts index 740a4c74..991a3192 100644 --- a/packages/typescript/ai-bedrock/src/bedrock-adapter.ts +++ b/packages/typescript/ai-bedrock/src/bedrock-adapter.ts @@ -2,8 +2,14 @@ import { AwsV4Signer } from 'aws4fetch' import { EventStreamCodec } from '@smithy/eventstream-codec' import { fromUtf8, toUtf8 } from '@smithy/util-utf8' import { BaseAdapter } from '@tanstack/ai' -import { BEDROCK_EMBEDDING_MODELS, BEDROCK_MODELS } from './model-meta' +import { + BEDROCK_EMBEDDING_MODELS, + BEDROCK_MODELS, + BEDROCK_MODEL_META, +} from './model-meta' import { convertToolsToProviderFormat } from './tools/tool-converter' +import { getProfileGeography } from './bedrock-regions' +import type { InferenceProfileGeography } from './bedrock-regions' import type { ContentBlock, ConverseRequest, @@ -190,6 +196,21 @@ export interface BedrockConfig { * - Local development/testing */ baseURL?: string + + /** + * Explicit geography for cross-region inference profiles. + * Overrides automatic detection from AWS region. + * + * Use this for: + * - Data residency requirements (e.g., force 'eu' for GDPR) + * - Using 'global' profiles for maximum throughput + * + * If not set, geography is inferred from `region`: + * - us-* → 'us' + * - eu-*, me-*, af-*, il-* → 'eu' + * - ap-* → 'apac' + */ + inferenceProfileRegion?: InferenceProfileGeography } export class Bedrock extends BaseAdapter< @@ -225,7 +246,8 @@ export class Bedrock extends BaseAdapter< options: ChatOptions, ): AsyncIterable { const converseInput = this.mapCommonOptionsToBedrock(options) - const modelId = encodeURIComponent(options.model) + const resolvedModelId = this.resolveModelId(options.model) + const modelId = encodeURIComponent(resolvedModelId) const url = `${this._resolvedBaseURL}/model/${modelId}/converse-stream` try { @@ -282,7 +304,8 @@ export class Bedrock extends BaseAdapter< async summarize(options: SummarizationOptions): Promise { const prompt = this.buildSummarizationPrompt(options) - const modelId = encodeURIComponent(options.model) + const resolvedModelId = this.resolveModelId(options.model) + const modelId = encodeURIComponent(resolvedModelId) const url = `${this._resolvedBaseURL}/model/${modelId}/converse` const converseInput: BedrockConversePayload = { @@ -333,8 +356,10 @@ export class Bedrock extends BaseAdapter< const embeddings: Array> = [] let totalInputTokens = 0 + const resolvedModelId = this.resolveModelId(options.model) + const modelId = encodeURIComponent(resolvedModelId) + for (const inputText of inputs) { - const modelId = encodeURIComponent(options.model) const url = `${this._resolvedBaseURL}/model/${modelId}/invoke` const body = { @@ -404,6 +429,65 @@ export class Bedrock extends BaseAdapter< return `https://bedrock-runtime.${this._resolvedRegion}.amazonaws.com` } + private resolveModelId(modelId: string): string { + const isAlreadyPrefixed = + /^(us|eu|apac|global)\./.test(modelId) || modelId.startsWith('arn:') + if (isAlreadyPrefixed) { + return modelId + } + + const profile = BEDROCK_MODEL_META[modelId]?.inferenceProfile + if (!profile) { + return modelId + } + + const geography = this.resolveProfileGeography(profile.regions) + if (geography) { + return `${geography}.${modelId}` + } + + if (!profile.required) { + return modelId + } + + if (profile.regions.includes('global')) { + return `global.${modelId}` + } + + const configured = this.bedrockConfig.inferenceProfileRegion + const inferred = getProfileGeography(this._resolvedRegion) + const context = configured + ? ` (configured: '${configured}', not supported)` + : inferred + ? ` (inferred: '${inferred}', not supported)` + : '' + + throw new Error( + `Model "${modelId}" requires a cross-region inference profile.\n\n` + + `Your region: ${this._resolvedRegion}${context}\n` + + `Supported: ${profile.regions.join(', ')}\n\n` + + `Fix options:\n` + + ` • Set inferenceProfileRegion: '${profile.regions[0]}' in config\n` + + ` • Use full profile ID: "${profile.regions[0]}.${modelId}"`, + ) + } + + private resolveProfileGeography( + supportedRegions: Array, + ): InferenceProfileGeography | null { + const preferred = this.bedrockConfig.inferenceProfileRegion + if (preferred && supportedRegions.includes(preferred)) { + return preferred + } + + const inferred = getProfileGeography(this._resolvedRegion) + if (inferred && supportedRegions.includes(inferred)) { + return inferred + } + + return null + } + private validateAuthConfig(): void { const env = this.getEnv() diff --git a/packages/typescript/ai-bedrock/src/bedrock-regions.ts b/packages/typescript/ai-bedrock/src/bedrock-regions.ts new file mode 100644 index 00000000..230a7b51 --- /dev/null +++ b/packages/typescript/ai-bedrock/src/bedrock-regions.ts @@ -0,0 +1,49 @@ +/** + * AWS Bedrock inference profile geography resolution. + * + * Cross-region inference profiles use geographic prefixes (us., eu., apac., global.) + * to route requests across AWS regions within a geography. + * + * @see https://docs.aws.amazon.com/bedrock/latest/userguide/cross-region-inference.html + */ + +/** Geographic regions for cross-region inference profiles */ +export type InferenceProfileGeography = 'us' | 'eu' | 'apac' | 'global' + +/** Inference profile configuration for a model */ +export interface InferenceProfileConfig { + /** Which geographies have inference profiles for this model */ + regions: Array + /** If true, model must be invoked via inference profile (no direct invocation) */ + required?: boolean +} + +/** + * Maps an AWS region code to its inference profile geography. + * Returns null for regions that don't map to a specific geography. + */ +export function getProfileGeography( + awsRegion: string, +): Exclude | null { + if (!awsRegion) return null + + // US regions + if (awsRegion.startsWith('us-')) return 'us' + + // EU regions (includes Middle East and Africa which AWS groups with EU) + if ( + awsRegion.startsWith('eu-') || + awsRegion.startsWith('me-') || + awsRegion.startsWith('af-') || + awsRegion.startsWith('il-') + ) { + return 'eu' + } + + // APAC regions + if (awsRegion.startsWith('ap-')) return 'apac' + + // Regions that don't map to a specific geography (ca-, sa-, mx-, etc.) + // These need explicit config or global profiles + return null +} diff --git a/packages/typescript/ai-bedrock/src/index.ts b/packages/typescript/ai-bedrock/src/index.ts index 9838e067..8f774701 100644 --- a/packages/typescript/ai-bedrock/src/index.ts +++ b/packages/typescript/ai-bedrock/src/index.ts @@ -5,11 +5,20 @@ export { type BedrockConfig, type BedrockCredentials, } from './bedrock-adapter' -export { BEDROCK_EMBEDDING_MODELS, BEDROCK_MODELS } from './model-meta' +export { + BEDROCK_EMBEDDING_MODELS, + BEDROCK_MODEL_META, + BEDROCK_MODELS, +} from './model-meta' export type { BedrockChatModelProviderOptionsByName, BedrockModelInputModalitiesByName, } from './model-meta' +export { + getProfileGeography, + type InferenceProfileConfig, + type InferenceProfileGeography, +} from './bedrock-regions' export type { BedrockAdditionalFieldsOptions, BedrockAnthropicOptions, diff --git a/packages/typescript/ai-bedrock/src/model-meta.ts b/packages/typescript/ai-bedrock/src/model-meta.ts index 533145e6..7b2d1cc2 100644 --- a/packages/typescript/ai-bedrock/src/model-meta.ts +++ b/packages/typescript/ai-bedrock/src/model-meta.ts @@ -1,32 +1,21 @@ /** - * Bedrock model metadata and provider options + * Bedrock model metadata and provider options. * - * ## Inference Profiles (Cross-Region Inference) - * - * AWS Bedrock uses "inference profiles" to enable cross-region model invocation. - * For newer Claude models (Claude 3.5 Sonnet v2, Claude 3.7 Sonnet, Claude 4 series), - * **inference profiles are required** - direct model IDs will return an error. - * - * To use inference profiles, pass the full inference profile ID as the model: + * Cross-region inference profiles are automatically resolved based on your AWS region. + * Just pass the base model ID and the adapter handles the rest. * + * @example * ```typescript + * // The adapter automatically resolves to 'us.anthropic.claude-sonnet-4-20250514-v1:0' + * // when your region is us-east-1 * await bedrock.chat({ - * model: 'us.anthropic.claude-sonnet-4-20250514-v1:0', + * model: 'anthropic.claude-sonnet-4-20250514-v1:0', * messages: [...] * }); * ``` * - * ### Model ID Formats - * - * | Format | Example | Use Case | - * |--------|---------|----------| - * | Direct | `anthropic.claude-3-haiku-20240307-v1:0` | Legacy models in single region | - * | US Profile | `us.anthropic.claude-3-5-sonnet-20241022-v2:0` | US cross-region | - * | EU Profile | `eu.anthropic.claude-3-5-sonnet-20241022-v2:0` | EU cross-region (GDPR compliance) | - * | APAC Profile | `apac.anthropic.claude-sonnet-4-20250514-v1:0` | Asia Pacific cross-region | - * - * @see https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html - * @see https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles.html +* @see https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html +* @see https://docs.aws.amazon.com/bedrock/latest/userguide/cross-region-inference.html */ import type { @@ -35,11 +24,8 @@ import type { BedrockProviderOptions, BedrockReasoningEffortOptions, } from './text/text-provider-options' +import type { InferenceProfileConfig } from './bedrock-regions' -/** - * Model metadata structure aligned with AWS Bedrock Converse API supported features. - * @see https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference-supported-models-features.html - */ interface ModelMeta { name: string id: string @@ -58,6 +44,7 @@ interface ModelMeta { contextWindow?: number maxOutputTokens?: number providerOptions?: TProviderOptions + inferenceProfile?: InferenceProfileConfig } const NOVA_LITE = { @@ -65,6 +52,7 @@ const NOVA_LITE = { id: 'amazon.nova-lite-v1:0', contextWindow: 300_000, maxOutputTokens: 5_000, + inferenceProfile: { regions: ['us', 'eu', 'apac'] }, supports: { converse: true, streaming: true, @@ -83,6 +71,7 @@ const NOVA_MICRO = { id: 'amazon.nova-micro-v1:0', contextWindow: 128_000, maxOutputTokens: 5_000, + inferenceProfile: { regions: ['us', 'eu', 'apac'] }, supports: { converse: true, streaming: true, @@ -101,6 +90,7 @@ const NOVA_PRO = { id: 'amazon.nova-pro-v1:0', contextWindow: 300_000, maxOutputTokens: 5_000, + inferenceProfile: { regions: ['us', 'eu', 'apac'] }, supports: { converse: true, streaming: true, @@ -114,11 +104,12 @@ const NOVA_PRO = { }, } as const satisfies ModelMeta -const US_NOVA_PREMIER = { +const NOVA_PREMIER = { name: 'Nova Premier', - id: 'us.amazon.nova-premier-v1:0', + id: 'amazon.nova-premier-v1:0', contextWindow: 1_000_000, maxOutputTokens: 32_000, + inferenceProfile: { regions: ['us'], required: true }, supports: { converse: true, streaming: true, @@ -133,11 +124,12 @@ const US_NOVA_PREMIER = { }, } as const satisfies ModelMeta -const US_NOVA_2_LITE = { +const NOVA_2_LITE = { name: 'Nova 2 Lite', - id: 'us.amazon.nova-2-lite-v1:0', + id: 'amazon.nova-2-lite-v1:0', contextWindow: 1_000_000, maxOutputTokens: 32_000, + inferenceProfile: { regions: ['us', 'global'], required: true }, supports: { converse: true, streaming: true, @@ -152,10 +144,11 @@ const US_NOVA_2_LITE = { }, } as const satisfies ModelMeta -const US_NOVA_2_SONIC = { +const NOVA_2_SONIC = { name: 'Nova 2 Sonic', - id: 'us.amazon.nova-2-sonic-v1:0', + id: 'amazon.nova-2-sonic-v1:0', contextWindow: 1_000_000, + inferenceProfile: { regions: ['us'], required: true }, supports: { converse: true, streaming: true, @@ -174,6 +167,7 @@ const CLAUDE_3_HAIKU = { id: 'anthropic.claude-3-haiku-20240307-v1:0', contextWindow: 200_000, maxOutputTokens: 4_096, + inferenceProfile: { regions: ['us', 'eu', 'apac'] }, supports: { converse: true, streaming: true, @@ -192,6 +186,7 @@ const CLAUDE_3_SONNET = { id: 'anthropic.claude-3-sonnet-20240229-v1:0', contextWindow: 200_000, maxOutputTokens: 4_096, + inferenceProfile: { regions: ['us', 'eu', 'apac'] }, supports: { converse: true, streaming: true, @@ -210,6 +205,7 @@ const CLAUDE_3_OPUS = { id: 'anthropic.claude-3-opus-20240229-v1:0', contextWindow: 200_000, maxOutputTokens: 4_096, + inferenceProfile: { regions: ['us'] }, supports: { converse: true, streaming: true, @@ -228,6 +224,7 @@ const CLAUDE_3_5_HAIKU = { id: 'anthropic.claude-3-5-haiku-20241022-v1:0', contextWindow: 200_000, maxOutputTokens: 8_192, + inferenceProfile: { regions: ['us', 'eu', 'apac'] }, supports: { converse: true, streaming: true, @@ -246,6 +243,7 @@ const CLAUDE_3_5_SONNET = { id: 'anthropic.claude-3-5-sonnet-20240620-v1:0', contextWindow: 200_000, maxOutputTokens: 8_192, + inferenceProfile: { regions: ['us', 'eu', 'apac'] }, supports: { converse: true, streaming: true, @@ -264,6 +262,7 @@ const CLAUDE_3_5_SONNET_V2 = { id: 'anthropic.claude-3-5-sonnet-20241022-v2:0', contextWindow: 200_000, maxOutputTokens: 8_192, + inferenceProfile: { regions: ['us', 'eu', 'apac'], required: true }, supports: { converse: true, streaming: true, @@ -282,6 +281,7 @@ const CLAUDE_3_7_SONNET = { id: 'anthropic.claude-3-7-sonnet-20250219-v1:0', contextWindow: 200_000, maxOutputTokens: 64_000, + inferenceProfile: { regions: ['us', 'eu', 'apac'], required: true }, supports: { converse: true, streaming: true, @@ -303,6 +303,7 @@ const CLAUDE_HAIKU_4_5 = { id: 'anthropic.claude-haiku-4-5-20251001-v1:0', contextWindow: 200_000, maxOutputTokens: 64_000, + inferenceProfile: { regions: ['us', 'eu', 'apac', 'global'], required: true }, supports: { converse: true, streaming: true, @@ -324,6 +325,7 @@ const CLAUDE_SONNET_4 = { id: 'anthropic.claude-sonnet-4-20250514-v1:0', contextWindow: 200_000, maxOutputTokens: 64_000, + inferenceProfile: { regions: ['us', 'eu', 'apac', 'global'], required: true }, supports: { converse: true, streaming: true, @@ -345,6 +347,7 @@ const CLAUDE_SONNET_4_5 = { id: 'anthropic.claude-sonnet-4-5-20250929-v1:0', contextWindow: 200_000, maxOutputTokens: 64_000, + inferenceProfile: { regions: ['us', 'eu', 'apac', 'global'], required: true }, supports: { converse: true, streaming: true, @@ -366,6 +369,7 @@ const CLAUDE_OPUS_4 = { id: 'anthropic.claude-opus-4-20250514-v1:0', contextWindow: 200_000, maxOutputTokens: 32_000, + inferenceProfile: { regions: ['us', 'eu', 'apac'], required: true }, supports: { converse: true, streaming: true, @@ -387,6 +391,29 @@ const CLAUDE_OPUS_4_1 = { id: 'anthropic.claude-opus-4-1-20250805-v1:0', contextWindow: 200_000, maxOutputTokens: 64_000, + inferenceProfile: { regions: ['us', 'eu', 'apac'], required: true }, + supports: { + converse: true, + streaming: true, + systemPrompts: true, + documentChat: true, + vision: true, + toolUse: true, + streamingToolUse: true, + guardrails: false, + s3Links: false, + reasoning: true, + }, +} as const satisfies ModelMeta< + BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions +> + +const CLAUDE_OPUS_4_5 = { + name: 'Claude Opus 4.5', + id: 'anthropic.claude-opus-4-5-20251101-v1:0', + contextWindow: 200_000, + maxOutputTokens: 64_000, + inferenceProfile: { regions: ['us', 'eu', 'global'], required: true }, supports: { converse: true, streaming: true, @@ -444,6 +471,7 @@ const LLAMA_3_1_8B = { id: 'meta.llama3-1-8b-instruct-v1:0', contextWindow: 128_000, maxOutputTokens: 2_048, + inferenceProfile: { regions: ['us', 'eu'] }, supports: { converse: true, streaming: true, @@ -462,6 +490,7 @@ const LLAMA_3_1_70B = { id: 'meta.llama3-1-70b-instruct-v1:0', contextWindow: 128_000, maxOutputTokens: 2_048, + inferenceProfile: { regions: ['us', 'eu'] }, supports: { converse: true, streaming: true, @@ -480,6 +509,7 @@ const LLAMA_3_1_405B = { id: 'meta.llama3-1-405b-instruct-v1:0', contextWindow: 128_000, maxOutputTokens: 2_048, + inferenceProfile: { regions: ['us'] }, supports: { converse: true, streaming: true, @@ -498,6 +528,7 @@ const LLAMA_3_2_1B = { id: 'meta.llama3-2-1b-instruct-v1:0', contextWindow: 128_000, maxOutputTokens: 2_048, + inferenceProfile: { regions: ['us'] }, supports: { converse: true, streaming: true, @@ -516,6 +547,7 @@ const LLAMA_3_2_3B = { id: 'meta.llama3-2-3b-instruct-v1:0', contextWindow: 128_000, maxOutputTokens: 2_048, + inferenceProfile: { regions: ['us'] }, supports: { converse: true, streaming: true, @@ -534,6 +566,7 @@ const LLAMA_3_2_11B = { id: 'meta.llama3-2-11b-instruct-v1:0', contextWindow: 128_000, maxOutputTokens: 2_048, + inferenceProfile: { regions: ['us'] }, supports: { converse: true, streaming: true, @@ -552,6 +585,7 @@ const LLAMA_3_2_90B = { id: 'meta.llama3-2-90b-instruct-v1:0', contextWindow: 128_000, maxOutputTokens: 2_048, + inferenceProfile: { regions: ['us'] }, supports: { converse: true, streaming: true, @@ -570,6 +604,7 @@ const LLAMA_3_3_70B = { id: 'meta.llama3-3-70b-instruct-v1:0', contextWindow: 128_000, maxOutputTokens: 2_048, + inferenceProfile: { regions: ['us'] }, supports: { converse: true, streaming: true, @@ -586,8 +621,9 @@ const LLAMA_3_3_70B = { const LLAMA_4_SCOUT = { name: 'Llama 4 Scout 17B Instruct', id: 'meta.llama4-scout-17b-instruct-v1:0', - contextWindow: 3_500_000, + contextWindow: 10_000_000, maxOutputTokens: 16_384, + inferenceProfile: { regions: ['us'] }, supports: { converse: true, streaming: true, @@ -606,6 +642,7 @@ const LLAMA_4_MAVERICK = { id: 'meta.llama4-maverick-17b-instruct-v1:0', contextWindow: 1_000_000, maxOutputTokens: 16_384, + inferenceProfile: { regions: ['us'] }, supports: { converse: true, streaming: true, @@ -709,11 +746,12 @@ const MISTRAL_SMALL_2402 = { }, } as const satisfies ModelMeta -const US_PIXTRAL_LARGE = { +const PIXTRAL_LARGE = { name: 'Pixtral Large (25.02)', - id: 'us.mistral.pixtral-large-2502-v1:0', + id: 'mistral.pixtral-large-2502-v1:0', contextWindow: 128_000, maxOutputTokens: 8_192, + inferenceProfile: { regions: ['us', 'eu'], required: true }, supports: { converse: true, streaming: true, @@ -754,8 +792,8 @@ const MINISTRAL_3_3B = { converse: true, streaming: true, systemPrompts: true, - documentChat: true, - vision: true, + documentChat: false, + vision: false, toolUse: false, streamingToolUse: false, guardrails: true, @@ -772,8 +810,8 @@ const MINISTRAL_3_8B = { converse: true, streaming: true, systemPrompts: true, - documentChat: true, - vision: true, + documentChat: false, + vision: false, toolUse: false, streamingToolUse: false, guardrails: true, @@ -790,8 +828,8 @@ const MINISTRAL_3_14B = { converse: true, streaming: true, systemPrompts: true, - documentChat: true, - vision: true, + documentChat: false, + vision: false, toolUse: false, streamingToolUse: false, guardrails: true, @@ -983,6 +1021,7 @@ const DEEPSEEK_R1 = { id: 'deepseek.r1-v1:0', contextWindow: 64_000, maxOutputTokens: 8_192, + inferenceProfile: { regions: ['us'], required: true }, supports: { converse: true, streaming: true, @@ -1028,7 +1067,7 @@ const AI21_JAMBA_LARGE = { vision: false, toolUse: true, streamingToolUse: true, - guardrails: true, + guardrails: false, s3Links: false, }, } as const satisfies ModelMeta @@ -1046,7 +1085,7 @@ const AI21_JAMBA_MINI = { vision: false, toolUse: true, streamingToolUse: true, - guardrails: true, + guardrails: false, s3Links: false, }, } as const satisfies ModelMeta @@ -1087,10 +1126,14 @@ const WRITER_PALMYRA_X5 = { }, } as const satisfies ModelMeta +// ============================================================================= +// Other Models +// ============================================================================= + const GEMMA_3_4B = { - name: 'Gemma 3 4B IT', + name: 'Gemma 3 4B', id: 'google.gemma-3-4b-it', - contextWindow: 32_768, + contextWindow: 128_000, maxOutputTokens: 8_192, supports: { converse: true, @@ -1106,9 +1149,9 @@ const GEMMA_3_4B = { } as const satisfies ModelMeta const GEMMA_3_12B = { - name: 'Gemma 3 12B IT', + name: 'Gemma 3 12B', id: 'google.gemma-3-12b-it', - contextWindow: 32_768, + contextWindow: 128_000, maxOutputTokens: 8_192, supports: { converse: true, @@ -1124,9 +1167,9 @@ const GEMMA_3_12B = { } as const satisfies ModelMeta const GEMMA_3_27B = { - name: 'Gemma 3 27B IT', + name: 'Gemma 3 27B', id: 'google.gemma-3-27b-it', - contextWindow: 32_768, + contextWindow: 128_000, maxOutputTokens: 8_192, supports: { converse: true, @@ -1144,7 +1187,7 @@ const GEMMA_3_27B = { const NVIDIA_NEMOTRON_9B = { name: 'NVIDIA Nemotron Nano 9B v2', id: 'nvidia.nemotron-nano-9b-v2', - contextWindow: 32_768, + contextWindow: 128_000, maxOutputTokens: 8_192, supports: { converse: true, @@ -1152,7 +1195,7 @@ const NVIDIA_NEMOTRON_9B = { systemPrompts: true, documentChat: false, vision: false, - toolUse: true, + toolUse: false, streamingToolUse: false, guardrails: true, s3Links: false, @@ -1163,7 +1206,7 @@ const NVIDIA_NEMOTRON_9B = { const NVIDIA_NEMOTRON_12B_VL = { name: 'NVIDIA Nemotron Nano 12B v2 VL', id: 'nvidia.nemotron-nano-12b-v2', - contextWindow: 32_768, + contextWindow: 128_000, maxOutputTokens: 8_192, supports: { converse: true, @@ -1189,7 +1232,7 @@ const MINIMAX_M2 = { systemPrompts: true, documentChat: false, vision: false, - toolUse: true, + toolUse: false, streamingToolUse: false, guardrails: true, s3Links: false, @@ -1197,7 +1240,7 @@ const MINIMAX_M2 = { } as const satisfies ModelMeta const MOONSHOT_KIMI_K2 = { - name: 'Kimi K2 Thinking', + name: 'Moonshot Kimi K2 Thinking', id: 'moonshot.kimi-k2-thinking', contextWindow: 128_000, maxOutputTokens: 8_192, @@ -1205,9 +1248,9 @@ const MOONSHOT_KIMI_K2 = { converse: true, streaming: true, systemPrompts: true, - documentChat: false, + documentChat: true, vision: false, - toolUse: true, + toolUse: false, streamingToolUse: false, guardrails: true, s3Links: false, @@ -1289,8 +1332,9 @@ const QWEN_3_VL_235B = { const TWELVELABS_PEGASUS = { name: 'Pegasus v1.2', - id: 'twelvelabs.pegasus-v1.2:0', + id: 'twelvelabs.pegasus-1-2-v1:0', contextWindow: 128_000, + inferenceProfile: { regions: ['us', 'eu', 'apac', 'global'] }, supports: { converse: true, streaming: true, @@ -1425,6 +1469,7 @@ const COHERE_EMBED_V4 = { name: 'Cohere Embed v4', id: 'cohere.embed-v4:0', contextWindow: 128_000, + inferenceProfile: { regions: ['us', 'eu', 'global'] }, supports: { converse: false, streaming: false, @@ -1458,9 +1503,9 @@ export const BEDROCK_MODELS = [ NOVA_LITE.id, NOVA_MICRO.id, NOVA_PRO.id, - US_NOVA_PREMIER.id, - US_NOVA_2_LITE.id, - US_NOVA_2_SONIC.id, + NOVA_PREMIER.id, + NOVA_2_LITE.id, + NOVA_2_SONIC.id, CLAUDE_3_HAIKU.id, CLAUDE_3_SONNET.id, CLAUDE_3_OPUS.id, @@ -1473,6 +1518,7 @@ export const BEDROCK_MODELS = [ CLAUDE_SONNET_4_5.id, CLAUDE_OPUS_4.id, CLAUDE_OPUS_4_1.id, + CLAUDE_OPUS_4_5.id, LLAMA_3_8B.id, LLAMA_3_70B.id, LLAMA_3_1_8B.id, @@ -1490,7 +1536,7 @@ export const BEDROCK_MODELS = [ MISTRAL_LARGE_2402.id, MISTRAL_LARGE_2407.id, MISTRAL_SMALL_2402.id, - US_PIXTRAL_LARGE.id, + PIXTRAL_LARGE.id, TITAN_TEXT_LARGE.id, TITAN_TEXT_EXPRESS.id, TITAN_TEXT_LITE.id, @@ -1537,17 +1583,99 @@ export const BEDROCK_EMBEDDING_MODELS = [ TWELVELABS_MARENGO_EMBED.id, ] as const -/** - * Type-only map from Bedrock model name to its provider-specific options. - * Options vary by model capabilities (reasoning, Anthropic-specific features). - */ +export const BEDROCK_MODEL_META: Record> = { + [NOVA_LITE.id]: NOVA_LITE, + [NOVA_MICRO.id]: NOVA_MICRO, + [NOVA_PRO.id]: NOVA_PRO, + [NOVA_PREMIER.id]: NOVA_PREMIER, + [NOVA_2_LITE.id]: NOVA_2_LITE, + [NOVA_2_SONIC.id]: NOVA_2_SONIC, + [CLAUDE_3_HAIKU.id]: CLAUDE_3_HAIKU, + [CLAUDE_3_SONNET.id]: CLAUDE_3_SONNET, + [CLAUDE_3_OPUS.id]: CLAUDE_3_OPUS, + [CLAUDE_3_5_HAIKU.id]: CLAUDE_3_5_HAIKU, + [CLAUDE_3_5_SONNET.id]: CLAUDE_3_5_SONNET, + [CLAUDE_3_5_SONNET_V2.id]: CLAUDE_3_5_SONNET_V2, + [CLAUDE_3_7_SONNET.id]: CLAUDE_3_7_SONNET, + [CLAUDE_HAIKU_4_5.id]: CLAUDE_HAIKU_4_5, + [CLAUDE_SONNET_4.id]: CLAUDE_SONNET_4, + [CLAUDE_SONNET_4_5.id]: CLAUDE_SONNET_4_5, + [CLAUDE_OPUS_4.id]: CLAUDE_OPUS_4, + [CLAUDE_OPUS_4_1.id]: CLAUDE_OPUS_4_1, + [CLAUDE_OPUS_4_5.id]: CLAUDE_OPUS_4_5, + [LLAMA_3_8B.id]: LLAMA_3_8B, + [LLAMA_3_70B.id]: LLAMA_3_70B, + [LLAMA_3_1_8B.id]: LLAMA_3_1_8B, + [LLAMA_3_1_70B.id]: LLAMA_3_1_70B, + [LLAMA_3_1_405B.id]: LLAMA_3_1_405B, + [LLAMA_3_2_1B.id]: LLAMA_3_2_1B, + [LLAMA_3_2_3B.id]: LLAMA_3_2_3B, + [LLAMA_3_2_11B.id]: LLAMA_3_2_11B, + [LLAMA_3_2_90B.id]: LLAMA_3_2_90B, + [LLAMA_3_3_70B.id]: LLAMA_3_3_70B, + [LLAMA_4_SCOUT.id]: LLAMA_4_SCOUT, + [LLAMA_4_MAVERICK.id]: LLAMA_4_MAVERICK, + [MISTRAL_7B.id]: MISTRAL_7B, + [MIXTRAL_8X7B.id]: MIXTRAL_8X7B, + [MISTRAL_LARGE_2402.id]: MISTRAL_LARGE_2402, + [MISTRAL_LARGE_2407.id]: MISTRAL_LARGE_2407, + [MISTRAL_SMALL_2402.id]: MISTRAL_SMALL_2402, + [PIXTRAL_LARGE.id]: PIXTRAL_LARGE, + [TITAN_TEXT_LARGE.id]: TITAN_TEXT_LARGE, + [TITAN_TEXT_EXPRESS.id]: TITAN_TEXT_EXPRESS, + [TITAN_TEXT_LITE.id]: TITAN_TEXT_LITE, + [COHERE_COMMAND_TEXT.id]: COHERE_COMMAND_TEXT, + [COHERE_COMMAND_LIGHT.id]: COHERE_COMMAND_LIGHT, + [COHERE_COMMAND_R.id]: COHERE_COMMAND_R, + [COHERE_COMMAND_R_PLUS.id]: COHERE_COMMAND_R_PLUS, + [DEEPSEEK_R1.id]: DEEPSEEK_R1, + [DEEPSEEK_V3.id]: DEEPSEEK_V3, + [AI21_JAMBA_LARGE.id]: AI21_JAMBA_LARGE, + [AI21_JAMBA_MINI.id]: AI21_JAMBA_MINI, + [WRITER_PALMYRA_X4.id]: WRITER_PALMYRA_X4, + [WRITER_PALMYRA_X5.id]: WRITER_PALMYRA_X5, + [TWELVELABS_PEGASUS.id]: TWELVELABS_PEGASUS, + [LUMA_RAY_V2.id]: LUMA_RAY_V2, + [MISTRAL_LARGE_3.id]: MISTRAL_LARGE_3, + [MINISTRAL_3_3B.id]: MINISTRAL_3_3B, + [MINISTRAL_3_8B.id]: MINISTRAL_3_8B, + [MINISTRAL_3_14B.id]: MINISTRAL_3_14B, + [MAGISTRAL_SMALL.id]: MAGISTRAL_SMALL, + [VOXTRAL_MINI.id]: VOXTRAL_MINI, + [VOXTRAL_SMALL.id]: VOXTRAL_SMALL, + [GEMMA_3_4B.id]: GEMMA_3_4B, + [GEMMA_3_12B.id]: GEMMA_3_12B, + [GEMMA_3_27B.id]: GEMMA_3_27B, + [NVIDIA_NEMOTRON_9B.id]: NVIDIA_NEMOTRON_9B, + [NVIDIA_NEMOTRON_12B_VL.id]: NVIDIA_NEMOTRON_12B_VL, + [MINIMAX_M2.id]: MINIMAX_M2, + [MOONSHOT_KIMI_K2.id]: MOONSHOT_KIMI_K2, + [OPENAI_SAFEGUARD_20B.id]: OPENAI_SAFEGUARD_20B, + [OPENAI_SAFEGUARD_120B.id]: OPENAI_SAFEGUARD_120B, + [QWEN_3_NEXT_80B.id]: QWEN_3_NEXT_80B, + [QWEN_3_VL_235B.id]: QWEN_3_VL_235B, + [TITAN_EMBED_TEXT_V1.id]: TITAN_EMBED_TEXT_V1, + [TITAN_EMBED_TEXT_V2.id]: TITAN_EMBED_TEXT_V2, + [TITAN_EMBED_IMAGE.id]: TITAN_EMBED_IMAGE, + [NOVA_MULTIMODAL_EMBED.id]: NOVA_MULTIMODAL_EMBED, + [COHERE_EMBED_ENGLISH.id]: COHERE_EMBED_ENGLISH, + [COHERE_EMBED_MULTILINGUAL.id]: COHERE_EMBED_MULTILINGUAL, + [COHERE_EMBED_V4.id]: COHERE_EMBED_V4, + [TWELVELABS_MARENGO_EMBED.id]: TWELVELABS_MARENGO_EMBED, +} + +type TextOnly = readonly ['text'] +type TextImage = readonly ['text', 'image'] +type TextImageDocument = readonly ['text', 'image', 'document'] +type TextDocument = readonly ['text', 'document'] + export type BedrockChatModelProviderOptionsByName = { [NOVA_LITE.id]: BedrockProviderOptions [NOVA_MICRO.id]: BedrockProviderOptions [NOVA_PRO.id]: BedrockProviderOptions - [US_NOVA_PREMIER.id]: BedrockProviderOptions & BedrockReasoningEffortOptions - [US_NOVA_2_LITE.id]: BedrockProviderOptions & BedrockReasoningEffortOptions - [US_NOVA_2_SONIC.id]: BedrockProviderOptions + [NOVA_PREMIER.id]: BedrockProviderOptions & BedrockReasoningEffortOptions + [NOVA_2_LITE.id]: BedrockProviderOptions & BedrockReasoningEffortOptions + [NOVA_2_SONIC.id]: BedrockProviderOptions [CLAUDE_3_HAIKU.id]: BedrockProviderOptions & BedrockAnthropicOptions [CLAUDE_3_SONNET.id]: BedrockProviderOptions & BedrockAnthropicOptions [CLAUDE_3_OPUS.id]: BedrockProviderOptions & BedrockAnthropicOptions @@ -1572,6 +1700,9 @@ export type BedrockChatModelProviderOptionsByName = { [CLAUDE_OPUS_4_1.id]: BedrockProviderOptions & BedrockAnthropicOptions & BedrockAnthropicReasoningOptions + [CLAUDE_OPUS_4_5.id]: BedrockProviderOptions & + BedrockAnthropicOptions & + BedrockAnthropicReasoningOptions [LLAMA_3_8B.id]: BedrockProviderOptions [LLAMA_3_70B.id]: BedrockProviderOptions [LLAMA_3_1_8B.id]: BedrockProviderOptions @@ -1589,7 +1720,7 @@ export type BedrockChatModelProviderOptionsByName = { [MISTRAL_LARGE_2402.id]: BedrockProviderOptions [MISTRAL_LARGE_2407.id]: BedrockProviderOptions [MISTRAL_SMALL_2402.id]: BedrockProviderOptions - [US_PIXTRAL_LARGE.id]: BedrockProviderOptions + [PIXTRAL_LARGE.id]: BedrockProviderOptions [TITAN_TEXT_LARGE.id]: BedrockProviderOptions [TITAN_TEXT_EXPRESS.id]: BedrockProviderOptions [TITAN_TEXT_LITE.id]: BedrockProviderOptions @@ -1625,24 +1756,13 @@ export type BedrockChatModelProviderOptionsByName = { [QWEN_3_VL_235B.id]: BedrockProviderOptions } -type TextOnly = readonly ['text'] -type TextImage = readonly ['text', 'image'] -type TextImageDocument = readonly ['text', 'image', 'document'] -type TextDocument = readonly ['text', 'document'] - -/** - * Type-only map from Bedrock model name to its supported input modalities. - * Derived from the supports.vision and supports.documentChat flags. - * - * @see https://docs.aws.amazon.com/bedrock/latest/userguide/models-supported.html - */ export type BedrockModelInputModalitiesByName = { [NOVA_LITE.id]: TextImageDocument [NOVA_MICRO.id]: TextOnly [NOVA_PRO.id]: TextImageDocument - [US_NOVA_PREMIER.id]: TextImageDocument - [US_NOVA_2_LITE.id]: TextImageDocument - [US_NOVA_2_SONIC.id]: TextOnly + [NOVA_PREMIER.id]: TextImageDocument + [NOVA_2_LITE.id]: TextImageDocument + [NOVA_2_SONIC.id]: TextOnly [CLAUDE_3_HAIKU.id]: TextImageDocument [CLAUDE_3_SONNET.id]: TextImageDocument [CLAUDE_3_OPUS.id]: TextImageDocument @@ -1655,6 +1775,7 @@ export type BedrockModelInputModalitiesByName = { [CLAUDE_SONNET_4_5.id]: TextImageDocument [CLAUDE_OPUS_4.id]: TextImageDocument [CLAUDE_OPUS_4_1.id]: TextImageDocument + [CLAUDE_OPUS_4_5.id]: TextImageDocument [LLAMA_3_8B.id]: TextDocument [LLAMA_3_70B.id]: TextDocument [LLAMA_3_1_8B.id]: TextDocument @@ -1672,7 +1793,7 @@ export type BedrockModelInputModalitiesByName = { [MISTRAL_LARGE_2402.id]: TextDocument [MISTRAL_LARGE_2407.id]: TextDocument [MISTRAL_SMALL_2402.id]: TextOnly - [US_PIXTRAL_LARGE.id]: TextImageDocument + [PIXTRAL_LARGE.id]: TextImageDocument [TITAN_TEXT_LARGE.id]: TextDocument [TITAN_TEXT_EXPRESS.id]: TextDocument [TITAN_TEXT_LITE.id]: TextDocument @@ -1689,9 +1810,9 @@ export type BedrockModelInputModalitiesByName = { [TWELVELABS_PEGASUS.id]: TextOnly [LUMA_RAY_V2.id]: TextOnly [MISTRAL_LARGE_3.id]: TextImageDocument - [MINISTRAL_3_3B.id]: TextImageDocument - [MINISTRAL_3_8B.id]: TextImageDocument - [MINISTRAL_3_14B.id]: TextImageDocument + [MINISTRAL_3_3B.id]: TextOnly + [MINISTRAL_3_8B.id]: TextOnly + [MINISTRAL_3_14B.id]: TextOnly [MAGISTRAL_SMALL.id]: TextImageDocument [VOXTRAL_MINI.id]: TextOnly [VOXTRAL_SMALL.id]: TextOnly @@ -1707,4 +1828,3 @@ export type BedrockModelInputModalitiesByName = { [QWEN_3_NEXT_80B.id]: TextOnly [QWEN_3_VL_235B.id]: TextImage } -