@tanstack/ai-bedrock 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"converse-text.js","sources":["../../../src/adapters/converse-text.ts"],"sourcesContent":["import { EventType, convertSchemaToJsonSchema } from '@tanstack/ai'\nimport { BaseTextAdapter } from '@tanstack/ai/adapters'\nimport { toRunErrorPayload } from '@tanstack/ai/adapter-internals'\nimport { resolveBedrockAuth } from '../utils/auth'\nimport { toConverseMessages } from '../converse/message-converter'\nimport { toToolConfig } from '../converse/tool-converter'\nimport {\n processConverseStream,\n throwIfConverseStreamError,\n} from '../converse/stream-processor'\nimport {\n STRUCTURED_TOOL_NAME,\n buildStructuredToolConfig,\n} from '../converse/structured-output'\nimport type { ResolvedBedrockAuth } from '../utils/auth'\nimport type { ConverseToolInput } from '../converse/tool-converter'\nimport type * as BedrockRuntime from '@aws-sdk/client-bedrock-runtime'\nimport type {\n BedrockRuntimeClient,\n BedrockRuntimeClientConfig,\n ContentBlock,\n ConverseCommandInput,\n ConverseCommandOutput,\n ConverseStreamCommandInput,\n ConverseStreamOutput,\n} from '@aws-sdk/client-bedrock-runtime'\nimport type {\n JSONSchema,\n Modality,\n StreamChunk,\n TextOptions,\n Tool,\n} from '@tanstack/ai'\nimport type {\n StructuredOutputOptions,\n StructuredOutputResult,\n} from '@tanstack/ai/adapters'\nimport type { BedrockClientConfig } from '../utils/client'\nimport type { BedrockMessageMetadataByModality } from '../message-types'\nimport type {\n BedrockConverseModels,\n ResolveConverseProviderOptions,\n ResolveInputModalities,\n} from '../model-meta'\n\n/** Config for the Converse adapter — same client config as the chat adapter. */\nexport interface BedrockConverseConfig extends BedrockClientConfig {}\n\n/**\n * Bedrock Converse text adapter. Wires the Converse translation modules (message\n * converter, tool converter, stream processor, structured-output forced-tool\n * builder) onto `@tanstack/ai`'s `BaseTextAdapter` and the\n * `@aws-sdk/client-bedrock-runtime` `BedrockRuntimeClient`.\n *\n * The success-path AG-UI lifecycle (`RUN_STARTED`..`RUN_FINISHED`) is owned by\n * `processConverseStream`; this adapter only owns the catch/`RUN_ERROR` path,\n * mirroring openai-base's `chatStream`.\n *\n * The actual SDK calls live behind two protected seams (`sendStream` / `send`)\n * so tests can subclass and inject canned Converse SDK shapes without a real\n * AWS request.\n */\nexport class BedrockConverseTextAdapter<\n TModel extends BedrockConverseModels,\n // Constraint mirrors the chat adapter (text.ts): the base parameterises\n // `TProviderOptions extends Record<string, any>`, and our default\n // `ResolveConverseProviderOptions<TModel>` resolves to an interface lacking an\n // implicit index signature — which `Record<string, unknown>` would reject but\n // `Record<string, any>` accepts. Confined to the generic constraint (the\n // established adapter pattern) — no value `as` cast is introduced.\n TProviderOptions extends Record<string, any> =\n ResolveConverseProviderOptions<TModel>,\n TInputModalities extends ReadonlyArray<Modality> =\n ResolveInputModalities<TModel>,\n> extends BaseTextAdapter<\n TModel,\n TProviderOptions,\n TInputModalities,\n BedrockMessageMetadataByModality\n> {\n override readonly kind = 'text' as const\n override readonly name = 'bedrock-converse' as const\n private clientPromise?: Promise<BedrockRuntimeClient>\n private readonly clientConfig: BedrockConverseConfig\n\n constructor(config: BedrockConverseConfig, model: TModel) {\n super({}, model)\n // Defer client construction and auth resolution: the AWS SDK is Node/\n // server-only, so we must not pull it into the static graph here. The\n // client (and its dynamic import) is built lazily on first SDK call.\n this.clientConfig = config\n }\n\n /**\n * Dynamically import `@aws-sdk/client-bedrock-runtime`. The specifier is held\n * in a variable (not a string literal) so bundler dep scanners (e.g. Vite/\n * esbuild optimizeDeps) cannot statically discover the AWS SDK and try to\n * pre-bundle it for the browser — it would fail on the SDK's Node-only\n * `fromTokenFile` export chain. The SDK is Node/server-only and is only\n * reached on a real request. `typeof import(...)` is a type-only reference\n * (erased at emit) so the imported members keep full typing.\n */\n protected importBedrockRuntime(): Promise<typeof BedrockRuntime> {\n const mod = '@aws-sdk/client-bedrock-runtime'\n return import(/* @vite-ignore */ mod) as Promise<typeof BedrockRuntime>\n }\n\n /**\n * Lazily construct the `BedrockRuntimeClient`. The dynamic import keeps\n * `@aws-sdk/client-bedrock-runtime` out of the static/browser graph and\n * defers `resolveBedrockAuth` until a real request is made.\n */\n protected async getClient(): Promise<BedrockRuntimeClient> {\n if (!this.clientPromise) {\n this.clientPromise = (async () => {\n const { BedrockRuntimeClient } = await this.importBedrockRuntime()\n const region = this.clientConfig.region ?? 'us-east-1'\n const resolved = resolveBedrockAuth(\n {\n apiKey: this.clientConfig.apiKey,\n region,\n auth: this.clientConfig.auth,\n },\n 'runtime',\n )\n return new BedrockRuntimeClient(\n this.buildClientConfig(resolved, region, this.clientConfig.baseURL),\n )\n })().catch((error: unknown) => {\n // Don't cache a rejected promise — clear it so a later call can retry\n // (e.g. after a transient import failure or fixed auth config).\n this.clientPromise = undefined\n throw error\n })\n }\n return this.clientPromise\n }\n\n /**\n * Map resolved auth + endpoint to a `BedrockRuntimeClientConfig`.\n *\n * Recent `@aws-sdk/client-bedrock-runtime` exposes a first-class `token`\n * config field for Bedrock API-key bearer auth. But the client's default\n * auth-scheme order is SigV4 first, then bearer — so passing `token` alone is\n * not enough: the SDK still resolves SigV4 and throws \"Could not load\n * credentials from any providers\". Pinning `authSchemePreference` to the\n * bearer scheme makes the API key actually get used. SigV4 uses the AWS\n * credential provider chain and the default scheme order.\n */\n protected buildClientConfig(\n resolved: ResolvedBedrockAuth,\n region: string,\n endpoint: string | undefined,\n ): BedrockRuntimeClientConfig {\n if (resolved.kind === 'bearer') {\n return {\n region,\n token: { token: resolved.token },\n authSchemePreference: ['httpBearerAuth'],\n ...(endpoint ? { endpoint } : {}),\n }\n }\n return {\n region: resolved.region,\n credentials: resolved.credentials,\n ...(endpoint ? { endpoint } : {}),\n }\n }\n\n // ---------------------------------------------------------------------------\n // SDK seams (overridden in tests so no real AWS call happens)\n // ---------------------------------------------------------------------------\n\n protected async sendStream(\n input: ConverseStreamCommandInput,\n ): Promise<AsyncIterable<ConverseStreamOutput>> {\n const { ConverseStreamCommand } = await this.importBedrockRuntime()\n const client = await this.getClient()\n const res = await client.send(new ConverseStreamCommand(input))\n if (!res.stream) {\n throw new Error('Bedrock Converse: empty stream response')\n }\n return res.stream\n }\n\n protected async send(\n input: ConverseCommandInput,\n ): Promise<ConverseCommandOutput> {\n const { ConverseCommand } = await this.importBedrockRuntime()\n const client = await this.getClient()\n return client.send(new ConverseCommand(input))\n }\n\n // ---------------------------------------------------------------------------\n // Public adapter surface\n // ---------------------------------------------------------------------------\n\n async *chatStream(\n options: TextOptions<TProviderOptions>,\n ): AsyncIterable<StreamChunk> {\n try {\n options.logger.request(\n `activity=chat provider=${this.name} model=${this.model} messages=${options.messages.length} tools=${options.tools?.length ?? 0} stream=true`,\n { provider: this.name, model: this.model },\n )\n const input = this.buildInput(options)\n const stream = await this.sendStream(input)\n yield* processConverseStream(stream, () => this.generateId(), {\n threadId: options.threadId,\n parentRunId: options.parentRunId,\n model: options.model,\n })\n } catch (error: unknown) {\n const errorPayload = toRunErrorPayload(\n error,\n `${this.name}.chatStream failed`,\n )\n options.logger.errors(`${this.name}.chatStream fatal`, {\n error: errorPayload,\n source: `${this.name}.chatStream`,\n })\n // Conditional `code` spread keeps the wire shape spec-compliant under\n // `exactOptionalPropertyTypes` (AG-UI's `RunErrorEvent.code` is optional).\n yield {\n type: EventType.RUN_ERROR,\n model: options.model,\n timestamp: Date.now(),\n message: errorPayload.message,\n ...(errorPayload.code !== undefined && { code: errorPayload.code }),\n error: {\n message: errorPayload.message,\n ...(errorPayload.code !== undefined && { code: errorPayload.code }),\n },\n }\n }\n }\n\n /**\n * Structured output via the forced-tool strategy. Converse has no native\n * json_schema response_format, so we force a single tool whose input schema\n * is the requested output schema and read the model's `toolUse.input` back as\n * the structured result.\n */\n async structuredOutput(\n options: StructuredOutputOptions<TProviderOptions>,\n ): Promise<StructuredOutputResult<unknown>> {\n const { chatOptions, outputSchema } = options\n try {\n chatOptions.logger.request(\n `activity=structuredOutput provider=${this.name} model=${this.model} messages=${chatOptions.messages.length}`,\n { provider: this.name, model: this.model },\n )\n const input: ConverseCommandInput = {\n ...this.buildInput(chatOptions),\n toolConfig: buildStructuredToolConfig(outputSchema),\n }\n const res = await this.send(input)\n const structured = extractStructuredToolInput(res)\n if (structured === undefined) {\n throw new Error(\n `${this.name}.structuredOutput: response contained no forced-tool output`,\n )\n }\n return {\n data: structured,\n rawText: JSON.stringify(structured),\n }\n } catch (error: unknown) {\n chatOptions.logger.errors(`${this.name}.structuredOutput fatal`, {\n error: toRunErrorPayload(error, `${this.name}.structuredOutput failed`),\n source: `${this.name}.structuredOutput`,\n })\n throw error\n }\n }\n\n /**\n * Streaming structured output. Same forced-tool strategy as\n * `structuredOutput`, but streamed: the forced tool's `toolUse.input` JSON\n * fragments are accumulated from the Converse stream and a terminal\n * `CUSTOM 'structured-output.complete'` event carries `{ object, raw }`,\n * mirroring openai-base's `structuredOutputStream` contract exactly.\n */\n async *structuredOutputStream(\n options: StructuredOutputOptions<TProviderOptions>,\n ): AsyncIterable<StreamChunk> {\n const { chatOptions, outputSchema } = options\n const timestamp = Date.now()\n const runId = this.generateId()\n const threadId = chatOptions.threadId ?? this.generateId()\n const messageId = this.generateId()\n\n let hasEmittedRunStarted = false\n let hasEmittedTextMessageStart = false\n let accumulatedRaw = ''\n let finishReason: 'stop' | 'length' | 'content_filter' = 'stop'\n\n try {\n chatOptions.logger.request(\n `activity=structuredOutputStream provider=${this.name} model=${this.model} messages=${chatOptions.messages.length}`,\n { provider: this.name, model: this.model },\n )\n const input: ConverseStreamCommandInput = {\n ...this.buildInput(chatOptions),\n toolConfig: buildStructuredToolConfig(outputSchema),\n }\n const stream = await this.sendStream(input)\n\n // The forced tool streams its `input` as partial-JSON fragments inside\n // `contentBlockDelta.delta.toolUse.input`. We surface them as\n // TEXT_MESSAGE_CONTENT deltas (raw JSON text), matching openai-base which\n // carries the structured JSON as text deltas.\n for await (const ev of stream) {\n if (!hasEmittedRunStarted) {\n hasEmittedRunStarted = true\n yield {\n type: EventType.RUN_STARTED,\n runId,\n threadId,\n model: chatOptions.model,\n timestamp,\n parentRunId: chatOptions.parentRunId,\n }\n }\n\n // Surface in-band server/throttle/validation errors instead of\n // letting them fall through and masquerade as an empty response.\n throwIfConverseStreamError(ev)\n\n if ('contentBlockDelta' in ev) {\n const delta = ev.contentBlockDelta?.delta\n const fragment =\n delta && 'toolUse' in delta ? delta.toolUse?.input : undefined\n if (fragment !== undefined) {\n if (!hasEmittedTextMessageStart) {\n hasEmittedTextMessageStart = true\n yield {\n type: EventType.TEXT_MESSAGE_START,\n messageId,\n role: 'assistant',\n model: chatOptions.model,\n timestamp,\n }\n }\n accumulatedRaw += fragment\n yield {\n type: EventType.TEXT_MESSAGE_CONTENT,\n messageId,\n delta: fragment,\n content: accumulatedRaw,\n model: chatOptions.model,\n timestamp,\n }\n }\n continue\n }\n\n if ('messageStop' in ev) {\n const stopReason = ev.messageStop?.stopReason\n // The forced structured-output tool produces stopReason 'tool_use' on\n // success, but that's an implementation detail — a cleanly-completed\n // structured run reports 'stop', matching openai-base's contract.\n finishReason =\n stopReason === 'max_tokens'\n ? 'length'\n : stopReason === 'content_filtered'\n ? 'content_filter'\n : 'stop'\n continue\n }\n }\n\n if (!hasEmittedRunStarted) {\n hasEmittedRunStarted = true\n yield {\n type: EventType.RUN_STARTED,\n runId,\n threadId,\n model: chatOptions.model,\n timestamp,\n parentRunId: chatOptions.parentRunId,\n }\n }\n\n if (hasEmittedTextMessageStart) {\n yield {\n type: EventType.TEXT_MESSAGE_END,\n messageId,\n model: chatOptions.model,\n timestamp,\n }\n }\n\n if (accumulatedRaw.length === 0) {\n yield {\n type: EventType.RUN_ERROR,\n runId,\n model: chatOptions.model,\n timestamp,\n message: `${this.name}.structuredOutputStream: response contained no content`,\n code: 'empty-response',\n error: {\n message: `${this.name}.structuredOutputStream: response contained no content`,\n code: 'empty-response',\n },\n }\n return\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(accumulatedRaw)\n } catch {\n yield {\n type: EventType.RUN_ERROR,\n runId,\n model: chatOptions.model,\n timestamp,\n message: `Failed to parse structured output as JSON. Content: ${accumulatedRaw.slice(0, 200)}${accumulatedRaw.length > 200 ? '...' : ''}`,\n code: 'parse-error',\n error: {\n message: 'Failed to parse structured output as JSON',\n code: 'parse-error',\n },\n }\n return\n }\n\n yield {\n type: EventType.CUSTOM,\n name: 'structured-output.complete',\n value: {\n object: parsed,\n raw: accumulatedRaw,\n },\n model: chatOptions.model,\n timestamp,\n }\n\n yield {\n type: EventType.RUN_FINISHED,\n runId,\n threadId,\n model: chatOptions.model,\n timestamp,\n finishReason,\n }\n } catch (error: unknown) {\n if (!hasEmittedRunStarted) {\n hasEmittedRunStarted = true\n yield {\n type: EventType.RUN_STARTED,\n runId,\n threadId,\n model: chatOptions.model,\n timestamp,\n parentRunId: chatOptions.parentRunId,\n }\n }\n const errorPayload = toRunErrorPayload(\n error,\n `${this.name}.structuredOutputStream failed`,\n )\n chatOptions.logger.errors(`${this.name}.structuredOutputStream fatal`, {\n error: errorPayload,\n source: `${this.name}.structuredOutputStream`,\n })\n yield {\n type: EventType.RUN_ERROR,\n runId,\n model: chatOptions.model,\n timestamp,\n message: errorPayload.message,\n ...(errorPayload.code !== undefined && { code: errorPayload.code }),\n error: {\n message: errorPayload.message,\n ...(errorPayload.code !== undefined && { code: errorPayload.code }),\n },\n }\n }\n }\n\n /**\n * Converse sends `tools` and a forced structured-output tool via two separate\n * mechanisms, never together. Declaring `false` makes the engine run the\n * agent loop without `outputSchema` and finalize via `structuredOutput` /\n * `structuredOutputStream`.\n */\n supportsCombinedToolsAndSchema(): boolean {\n return false\n }\n\n // ---------------------------------------------------------------------------\n // Request construction\n // ---------------------------------------------------------------------------\n\n /**\n * Translate `TextOptions` into a `ConverseCommandInput`. Shared by chatStream,\n * structuredOutput, and structuredOutputStream (the latter two override\n * `toolConfig` with the forced structured tool afterwards).\n */\n protected buildInput(\n options: TextOptions<TProviderOptions>,\n ): ConverseCommandInput {\n const { system, messages } = toConverseMessages(\n options.messages,\n options.systemPrompts,\n )\n\n const toolConfig = options.tools\n ? toToolConfig(convertTools(options.tools), 'auto')\n : undefined\n\n // Sampling options live on `modelOptions` (typed as the narrowed\n // `BedrockConverseProviderOptions`, which surfaces the OpenAI Chat\n // Completions field names); translate them into Converse's `inferenceConfig`,\n // which uses AWS-native camelCase keys.\n const modelOptions = options.modelOptions\n const temperature = modelOptions?.temperature\n const topP = modelOptions?.top_p\n const maxTokens = modelOptions?.max_completion_tokens\n const stop = modelOptions?.stop\n const stopSequences =\n stop == null ? undefined : Array.isArray(stop) ? stop : [stop]\n\n const inferenceConfig =\n temperature != null ||\n topP != null ||\n maxTokens != null ||\n stopSequences != null\n ? {\n ...(temperature != null && { temperature }),\n ...(topP != null && { topP }),\n ...(maxTokens != null && { maxTokens }),\n ...(stopSequences != null && { stopSequences }),\n }\n : undefined\n\n return {\n modelId: this.model,\n messages,\n ...(system.length > 0 && { system }),\n ...(toolConfig && { toolConfig }),\n ...(inferenceConfig && { inferenceConfig }),\n }\n }\n}\n\n/**\n * Convert TanStack `Tool[]` to the Converse tool-converter input shape. Reuses\n * the SAME `convertSchemaToJsonSchema` the other adapters use so the Converse\n * tool input schemas match what every other provider sends.\n */\nfunction convertTools(tools: Array<Tool>): Array<ConverseToolInput> {\n return tools.map((tool) => {\n const inputSchema: JSONSchema = convertSchemaToJsonSchema(\n tool.inputSchema,\n ) ?? { type: 'object', properties: {}, required: [] }\n return {\n name: tool.name,\n description: tool.description,\n inputSchema,\n }\n })\n}\n\n/**\n * Find the forced structured-output tool's `input` in a non-streaming Converse\n * response. SDK-boundary narrowing only — `ConverseOutput` is a tagged union\n * (`{ message }`) and a tool-use block is `{ toolUse: { input } }`.\n */\nfunction extractStructuredToolInput(\n res: ConverseCommandOutput,\n): unknown | undefined {\n const message =\n res.output && 'message' in res.output ? res.output.message : undefined\n const content: Array<ContentBlock> = message?.content ?? []\n for (const block of content) {\n if ('toolUse' in block && block.toolUse) {\n // Only accept the forced structured tool (an unnamed block is allowed,\n // since the forced tool is the only one configured). A differently-named\n // tool-use block is a hallucinated/leftover call whose arbitrary input\n // must not be returned as the validated result — leave it to the caller's\n // `throw` so the failure is accurate instead of silently wrong.\n if (\n block.toolUse.name === STRUCTURED_TOOL_NAME ||\n block.toolUse.name === undefined\n ) {\n return block.toolUse.input\n }\n }\n }\n return undefined\n}\n\n/** Converse adapter with an explicit API key (low-level; mirrors createBedrockChat). */\nexport function createBedrockConverse<TModel extends BedrockConverseModels>(\n model: TModel,\n apiKey: string,\n config?: Omit<BedrockConverseConfig, 'apiKey'>,\n): BedrockConverseTextAdapter<TModel> {\n return new BedrockConverseTextAdapter({ ...config, apiKey }, model)\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"converse-text.js","names":[],"sources":["../../../src/adapters/converse-text.ts"],"sourcesContent":["import { EventType, convertSchemaToJsonSchema } from '@tanstack/ai'\nimport { BaseTextAdapter } from '@tanstack/ai/adapters'\nimport { toRunErrorPayload } from '@tanstack/ai/adapter-internals'\nimport { resolveBedrockAuth } from '../utils/auth'\nimport { toConverseMessages } from '../converse/message-converter'\nimport { toToolConfig } from '../converse/tool-converter'\nimport {\n processConverseStream,\n throwIfConverseStreamError,\n} from '../converse/stream-processor'\nimport {\n STRUCTURED_TOOL_NAME,\n buildStructuredToolConfig,\n} from '../converse/structured-output'\nimport type { ResolvedBedrockAuth } from '../utils/auth'\nimport type { ConverseToolInput } from '../converse/tool-converter'\nimport type * as BedrockRuntime from '@aws-sdk/client-bedrock-runtime'\nimport type {\n BedrockRuntimeClient,\n BedrockRuntimeClientConfig,\n ContentBlock,\n ConverseCommandInput,\n ConverseCommandOutput,\n ConverseStreamCommandInput,\n ConverseStreamOutput,\n} from '@aws-sdk/client-bedrock-runtime'\nimport type {\n JSONSchema,\n Modality,\n StreamChunk,\n TextOptions,\n Tool,\n} from '@tanstack/ai'\nimport type {\n StructuredOutputOptions,\n StructuredOutputResult,\n} from '@tanstack/ai/adapters'\nimport type { BedrockClientConfig } from '../utils/client'\nimport type { BedrockMessageMetadataByModality } from '../message-types'\nimport type {\n BedrockConverseModels,\n ResolveConverseProviderOptions,\n ResolveInputModalities,\n} from '../model-meta'\n\n/** Config for the Converse adapter — same client config as the chat adapter. */\nexport interface BedrockConverseConfig extends BedrockClientConfig {}\n\n/**\n * Bedrock Converse text adapter. Wires the Converse translation modules (message\n * converter, tool converter, stream processor, structured-output forced-tool\n * builder) onto `@tanstack/ai`'s `BaseTextAdapter` and the\n * `@aws-sdk/client-bedrock-runtime` `BedrockRuntimeClient`.\n *\n * The success-path AG-UI lifecycle (`RUN_STARTED`..`RUN_FINISHED`) is owned by\n * `processConverseStream`; this adapter only owns the catch/`RUN_ERROR` path,\n * mirroring openai-base's `chatStream`.\n *\n * The actual SDK calls live behind two protected seams (`sendStream` / `send`)\n * so tests can subclass and inject canned Converse SDK shapes without a real\n * AWS request.\n */\nexport class BedrockConverseTextAdapter<\n TModel extends BedrockConverseModels,\n // Constraint mirrors the chat adapter (text.ts): the base parameterises\n // `TProviderOptions extends Record<string, any>`, and our default\n // `ResolveConverseProviderOptions<TModel>` resolves to an interface lacking an\n // implicit index signature — which `Record<string, unknown>` would reject but\n // `Record<string, any>` accepts. Confined to the generic constraint (the\n // established adapter pattern) — no value `as` cast is introduced.\n TProviderOptions extends Record<string, any> =\n ResolveConverseProviderOptions<TModel>,\n TInputModalities extends ReadonlyArray<Modality> =\n ResolveInputModalities<TModel>,\n> extends BaseTextAdapter<\n TModel,\n TProviderOptions,\n TInputModalities,\n BedrockMessageMetadataByModality\n> {\n override readonly kind = 'text' as const\n override readonly name = 'bedrock-converse' as const\n private clientPromise?: Promise<BedrockRuntimeClient>\n private readonly clientConfig: BedrockConverseConfig\n\n constructor(config: BedrockConverseConfig, model: TModel) {\n super({}, model)\n // Defer client construction and auth resolution: the AWS SDK is Node/\n // server-only, so we must not pull it into the static graph here. The\n // client (and its dynamic import) is built lazily on first SDK call.\n this.clientConfig = config\n }\n\n /**\n * Dynamically import `@aws-sdk/client-bedrock-runtime`. The specifier is held\n * in a variable (not a string literal) so bundler dep scanners (e.g. Vite/\n * esbuild optimizeDeps) cannot statically discover the AWS SDK and try to\n * pre-bundle it for the browser — it would fail on the SDK's Node-only\n * `fromTokenFile` export chain. The SDK is Node/server-only and is only\n * reached on a real request. `typeof import(...)` is a type-only reference\n * (erased at emit) so the imported members keep full typing.\n */\n protected importBedrockRuntime(): Promise<typeof BedrockRuntime> {\n const mod = '@aws-sdk/client-bedrock-runtime'\n return import(/* @vite-ignore */ mod) as Promise<typeof BedrockRuntime>\n }\n\n /**\n * Lazily construct the `BedrockRuntimeClient`. The dynamic import keeps\n * `@aws-sdk/client-bedrock-runtime` out of the static/browser graph and\n * defers `resolveBedrockAuth` until a real request is made.\n */\n protected async getClient(): Promise<BedrockRuntimeClient> {\n if (!this.clientPromise) {\n this.clientPromise = (async () => {\n const { BedrockRuntimeClient } = await this.importBedrockRuntime()\n const region = this.clientConfig.region ?? 'us-east-1'\n const resolved = resolveBedrockAuth(\n {\n apiKey: this.clientConfig.apiKey,\n region,\n auth: this.clientConfig.auth,\n },\n 'runtime',\n )\n return new BedrockRuntimeClient(\n this.buildClientConfig(resolved, region, this.clientConfig.baseURL),\n )\n })().catch((error: unknown) => {\n // Don't cache a rejected promise — clear it so a later call can retry\n // (e.g. after a transient import failure or fixed auth config).\n this.clientPromise = undefined\n throw error\n })\n }\n return this.clientPromise\n }\n\n /**\n * Map resolved auth + endpoint to a `BedrockRuntimeClientConfig`.\n *\n * Recent `@aws-sdk/client-bedrock-runtime` exposes a first-class `token`\n * config field for Bedrock API-key bearer auth. But the client's default\n * auth-scheme order is SigV4 first, then bearer — so passing `token` alone is\n * not enough: the SDK still resolves SigV4 and throws \"Could not load\n * credentials from any providers\". Pinning `authSchemePreference` to the\n * bearer scheme makes the API key actually get used. SigV4 uses the AWS\n * credential provider chain and the default scheme order.\n */\n protected buildClientConfig(\n resolved: ResolvedBedrockAuth,\n region: string,\n endpoint: string | undefined,\n ): BedrockRuntimeClientConfig {\n if (resolved.kind === 'bearer') {\n return {\n region,\n token: { token: resolved.token },\n authSchemePreference: ['httpBearerAuth'],\n ...(endpoint ? { endpoint } : {}),\n }\n }\n return {\n region: resolved.region,\n credentials: resolved.credentials,\n ...(endpoint ? { endpoint } : {}),\n }\n }\n\n // ---------------------------------------------------------------------------\n // SDK seams (overridden in tests so no real AWS call happens)\n // ---------------------------------------------------------------------------\n\n protected async sendStream(\n input: ConverseStreamCommandInput,\n ): Promise<AsyncIterable<ConverseStreamOutput>> {\n const { ConverseStreamCommand } = await this.importBedrockRuntime()\n const client = await this.getClient()\n const res = await client.send(new ConverseStreamCommand(input))\n if (!res.stream) {\n throw new Error('Bedrock Converse: empty stream response')\n }\n return res.stream\n }\n\n protected async send(\n input: ConverseCommandInput,\n ): Promise<ConverseCommandOutput> {\n const { ConverseCommand } = await this.importBedrockRuntime()\n const client = await this.getClient()\n return client.send(new ConverseCommand(input))\n }\n\n // ---------------------------------------------------------------------------\n // Public adapter surface\n // ---------------------------------------------------------------------------\n\n async *chatStream(\n options: TextOptions<TProviderOptions>,\n ): AsyncIterable<StreamChunk> {\n try {\n options.logger.request(\n `activity=chat provider=${this.name} model=${this.model} messages=${options.messages.length} tools=${options.tools?.length ?? 0} stream=true`,\n { provider: this.name, model: this.model },\n )\n const input = this.buildInput(options)\n const stream = await this.sendStream(input)\n yield* processConverseStream(stream, () => this.generateId(), {\n threadId: options.threadId,\n parentRunId: options.parentRunId,\n model: options.model,\n })\n } catch (error: unknown) {\n const errorPayload = toRunErrorPayload(\n error,\n `${this.name}.chatStream failed`,\n )\n options.logger.errors(`${this.name}.chatStream fatal`, {\n error: errorPayload,\n source: `${this.name}.chatStream`,\n })\n // Conditional `code` spread keeps the wire shape spec-compliant under\n // `exactOptionalPropertyTypes` (AG-UI's `RunErrorEvent.code` is optional).\n yield {\n type: EventType.RUN_ERROR,\n model: options.model,\n timestamp: Date.now(),\n message: errorPayload.message,\n ...(errorPayload.code !== undefined && { code: errorPayload.code }),\n error: {\n message: errorPayload.message,\n ...(errorPayload.code !== undefined && { code: errorPayload.code }),\n },\n }\n }\n }\n\n /**\n * Structured output via the forced-tool strategy. Converse has no native\n * json_schema response_format, so we force a single tool whose input schema\n * is the requested output schema and read the model's `toolUse.input` back as\n * the structured result.\n */\n async structuredOutput(\n options: StructuredOutputOptions<TProviderOptions>,\n ): Promise<StructuredOutputResult<unknown>> {\n const { chatOptions, outputSchema } = options\n try {\n chatOptions.logger.request(\n `activity=structuredOutput provider=${this.name} model=${this.model} messages=${chatOptions.messages.length}`,\n { provider: this.name, model: this.model },\n )\n const input: ConverseCommandInput = {\n ...this.buildInput(chatOptions),\n toolConfig: buildStructuredToolConfig(outputSchema),\n }\n const res = await this.send(input)\n const structured = extractStructuredToolInput(res)\n if (structured === undefined) {\n throw new Error(\n `${this.name}.structuredOutput: response contained no forced-tool output`,\n )\n }\n return {\n data: structured,\n rawText: JSON.stringify(structured),\n }\n } catch (error: unknown) {\n chatOptions.logger.errors(`${this.name}.structuredOutput fatal`, {\n error: toRunErrorPayload(error, `${this.name}.structuredOutput failed`),\n source: `${this.name}.structuredOutput`,\n })\n throw error\n }\n }\n\n /**\n * Streaming structured output. Same forced-tool strategy as\n * `structuredOutput`, but streamed: the forced tool's `toolUse.input` JSON\n * fragments are accumulated from the Converse stream and a terminal\n * `CUSTOM 'structured-output.complete'` event carries `{ object, raw }`,\n * mirroring openai-base's `structuredOutputStream` contract exactly.\n */\n async *structuredOutputStream(\n options: StructuredOutputOptions<TProviderOptions>,\n ): AsyncIterable<StreamChunk> {\n const { chatOptions, outputSchema } = options\n const timestamp = Date.now()\n const runId = this.generateId()\n const threadId = chatOptions.threadId ?? this.generateId()\n const messageId = this.generateId()\n\n let hasEmittedRunStarted = false\n let hasEmittedTextMessageStart = false\n let accumulatedRaw = ''\n let finishReason: 'stop' | 'length' | 'content_filter' = 'stop'\n\n try {\n chatOptions.logger.request(\n `activity=structuredOutputStream provider=${this.name} model=${this.model} messages=${chatOptions.messages.length}`,\n { provider: this.name, model: this.model },\n )\n const input: ConverseStreamCommandInput = {\n ...this.buildInput(chatOptions),\n toolConfig: buildStructuredToolConfig(outputSchema),\n }\n const stream = await this.sendStream(input)\n\n // The forced tool streams its `input` as partial-JSON fragments inside\n // `contentBlockDelta.delta.toolUse.input`. We surface them as\n // TEXT_MESSAGE_CONTENT deltas (raw JSON text), matching openai-base which\n // carries the structured JSON as text deltas.\n for await (const ev of stream) {\n if (!hasEmittedRunStarted) {\n hasEmittedRunStarted = true\n yield {\n type: EventType.RUN_STARTED,\n runId,\n threadId,\n model: chatOptions.model,\n timestamp,\n parentRunId: chatOptions.parentRunId,\n }\n }\n\n // Surface in-band server/throttle/validation errors instead of\n // letting them fall through and masquerade as an empty response.\n throwIfConverseStreamError(ev)\n\n if ('contentBlockDelta' in ev) {\n const delta = ev.contentBlockDelta?.delta\n const fragment =\n delta && 'toolUse' in delta ? delta.toolUse?.input : undefined\n if (fragment !== undefined) {\n if (!hasEmittedTextMessageStart) {\n hasEmittedTextMessageStart = true\n yield {\n type: EventType.TEXT_MESSAGE_START,\n messageId,\n role: 'assistant',\n model: chatOptions.model,\n timestamp,\n }\n }\n accumulatedRaw += fragment\n yield {\n type: EventType.TEXT_MESSAGE_CONTENT,\n messageId,\n delta: fragment,\n content: accumulatedRaw,\n model: chatOptions.model,\n timestamp,\n }\n }\n continue\n }\n\n if ('messageStop' in ev) {\n const stopReason = ev.messageStop?.stopReason\n // The forced structured-output tool produces stopReason 'tool_use' on\n // success, but that's an implementation detail — a cleanly-completed\n // structured run reports 'stop', matching openai-base's contract.\n finishReason =\n stopReason === 'max_tokens'\n ? 'length'\n : stopReason === 'content_filtered'\n ? 'content_filter'\n : 'stop'\n continue\n }\n }\n\n if (!hasEmittedRunStarted) {\n hasEmittedRunStarted = true\n yield {\n type: EventType.RUN_STARTED,\n runId,\n threadId,\n model: chatOptions.model,\n timestamp,\n parentRunId: chatOptions.parentRunId,\n }\n }\n\n if (hasEmittedTextMessageStart) {\n yield {\n type: EventType.TEXT_MESSAGE_END,\n messageId,\n model: chatOptions.model,\n timestamp,\n }\n }\n\n if (accumulatedRaw.length === 0) {\n yield {\n type: EventType.RUN_ERROR,\n runId,\n model: chatOptions.model,\n timestamp,\n message: `${this.name}.structuredOutputStream: response contained no content`,\n code: 'empty-response',\n error: {\n message: `${this.name}.structuredOutputStream: response contained no content`,\n code: 'empty-response',\n },\n }\n return\n }\n\n let parsed: unknown\n try {\n parsed = JSON.parse(accumulatedRaw)\n } catch {\n yield {\n type: EventType.RUN_ERROR,\n runId,\n model: chatOptions.model,\n timestamp,\n message: `Failed to parse structured output as JSON. Content: ${accumulatedRaw.slice(0, 200)}${accumulatedRaw.length > 200 ? '...' : ''}`,\n code: 'parse-error',\n error: {\n message: 'Failed to parse structured output as JSON',\n code: 'parse-error',\n },\n }\n return\n }\n\n yield {\n type: EventType.CUSTOM,\n name: 'structured-output.complete',\n value: {\n object: parsed,\n raw: accumulatedRaw,\n },\n model: chatOptions.model,\n timestamp,\n }\n\n yield {\n type: EventType.RUN_FINISHED,\n runId,\n threadId,\n model: chatOptions.model,\n timestamp,\n finishReason,\n }\n } catch (error: unknown) {\n if (!hasEmittedRunStarted) {\n hasEmittedRunStarted = true\n yield {\n type: EventType.RUN_STARTED,\n runId,\n threadId,\n model: chatOptions.model,\n timestamp,\n parentRunId: chatOptions.parentRunId,\n }\n }\n const errorPayload = toRunErrorPayload(\n error,\n `${this.name}.structuredOutputStream failed`,\n )\n chatOptions.logger.errors(`${this.name}.structuredOutputStream fatal`, {\n error: errorPayload,\n source: `${this.name}.structuredOutputStream`,\n })\n yield {\n type: EventType.RUN_ERROR,\n runId,\n model: chatOptions.model,\n timestamp,\n message: errorPayload.message,\n ...(errorPayload.code !== undefined && { code: errorPayload.code }),\n error: {\n message: errorPayload.message,\n ...(errorPayload.code !== undefined && { code: errorPayload.code }),\n },\n }\n }\n }\n\n /**\n * Converse sends `tools` and a forced structured-output tool via two separate\n * mechanisms, never together. Declaring `false` makes the engine run the\n * agent loop without `outputSchema` and finalize via `structuredOutput` /\n * `structuredOutputStream`.\n */\n supportsCombinedToolsAndSchema(): boolean {\n return false\n }\n\n // ---------------------------------------------------------------------------\n // Request construction\n // ---------------------------------------------------------------------------\n\n /**\n * Translate `TextOptions` into a `ConverseCommandInput`. Shared by chatStream,\n * structuredOutput, and structuredOutputStream (the latter two override\n * `toolConfig` with the forced structured tool afterwards).\n */\n protected buildInput(\n options: TextOptions<TProviderOptions>,\n ): ConverseCommandInput {\n const { system, messages } = toConverseMessages(\n options.messages,\n options.systemPrompts,\n )\n\n const toolConfig = options.tools\n ? toToolConfig(convertTools(options.tools), 'auto')\n : undefined\n\n // Sampling options live on `modelOptions` (typed as the narrowed\n // `BedrockConverseProviderOptions`, which surfaces the OpenAI Chat\n // Completions field names); translate them into Converse's `inferenceConfig`,\n // which uses AWS-native camelCase keys.\n const modelOptions = options.modelOptions\n const temperature = modelOptions?.temperature\n const topP = modelOptions?.top_p\n const maxTokens = modelOptions?.max_completion_tokens\n const stop = modelOptions?.stop\n const stopSequences =\n stop == null ? undefined : Array.isArray(stop) ? stop : [stop]\n\n const inferenceConfig =\n temperature != null ||\n topP != null ||\n maxTokens != null ||\n stopSequences != null\n ? {\n ...(temperature != null && { temperature }),\n ...(topP != null && { topP }),\n ...(maxTokens != null && { maxTokens }),\n ...(stopSequences != null && { stopSequences }),\n }\n : undefined\n\n return {\n modelId: this.model,\n messages,\n ...(system.length > 0 && { system }),\n ...(toolConfig && { toolConfig }),\n ...(inferenceConfig && { inferenceConfig }),\n }\n }\n}\n\n/**\n * Convert TanStack `Tool[]` to the Converse tool-converter input shape. Reuses\n * the SAME `convertSchemaToJsonSchema` the other adapters use so the Converse\n * tool input schemas match what every other provider sends.\n */\nfunction convertTools(tools: Array<Tool>): Array<ConverseToolInput> {\n return tools.map((tool) => {\n const inputSchema: JSONSchema = convertSchemaToJsonSchema(\n tool.inputSchema,\n ) ?? { type: 'object', properties: {}, required: [] }\n return {\n name: tool.name,\n description: tool.description,\n inputSchema,\n }\n })\n}\n\n/**\n * Find the forced structured-output tool's `input` in a non-streaming Converse\n * response. SDK-boundary narrowing only — `ConverseOutput` is a tagged union\n * (`{ message }`) and a tool-use block is `{ toolUse: { input } }`.\n */\nfunction extractStructuredToolInput(\n res: ConverseCommandOutput,\n): unknown | undefined {\n const message =\n res.output && 'message' in res.output ? res.output.message : undefined\n const content: Array<ContentBlock> = message?.content ?? []\n for (const block of content) {\n if ('toolUse' in block && block.toolUse) {\n // Only accept the forced structured tool (an unnamed block is allowed,\n // since the forced tool is the only one configured). A differently-named\n // tool-use block is a hallucinated/leftover call whose arbitrary input\n // must not be returned as the validated result — leave it to the caller's\n // `throw` so the failure is accurate instead of silently wrong.\n if (\n block.toolUse.name === STRUCTURED_TOOL_NAME ||\n block.toolUse.name === undefined\n ) {\n return block.toolUse.input\n }\n }\n }\n return undefined\n}\n\n/** Converse adapter with an explicit API key (low-level; mirrors createBedrockChat). */\nexport function createBedrockConverse<TModel extends BedrockConverseModels>(\n model: TModel,\n apiKey: string,\n config?: Omit<BedrockConverseConfig, 'apiKey'>,\n): BedrockConverseTextAdapter<TModel> {\n return new BedrockConverseTextAdapter({ ...config, apiKey }, model)\n}\n"],"mappings":"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"}
@@ -1,22 +1,28 @@
1
+ import { withBedrockDefaults } from "../utils/client.js";
1
2
  import OpenAI from "openai";
2
3
  import { OpenAIBaseResponsesTextAdapter } from "@tanstack/openai-base";
3
- import { withBedrockDefaults } from "../utils/client.js";
4
- class BedrockResponsesTextAdapter extends OpenAIBaseResponsesTextAdapter {
5
- kind = "text";
6
- name = "bedrock-responses";
7
- constructor(config, model) {
8
- super(
9
- model,
10
- "bedrock-responses",
11
- new OpenAI(withBedrockDefaults(config, "mantle"))
12
- );
13
- }
14
- }
4
+ //#region src/adapters/responses-text.ts
5
+ /**
6
+ * Bedrock Responses adapter. Drives mantle's OpenAI-compatible `/responses`
7
+ * endpoint via the OpenAI SDK (`client.responses.create`) — the same base
8
+ * class ai-openai's `openaiText` uses. Responses is mantle-only, so the
9
+ * constructor forces the mantle baseURL.
10
+ */
11
+ var BedrockResponsesTextAdapter = class extends OpenAIBaseResponsesTextAdapter {
12
+ kind = "text";
13
+ name = "bedrock-responses";
14
+ constructor(config, model) {
15
+ super(model, "bedrock-responses", new OpenAI(withBedrockDefaults(config, "mantle")));
16
+ }
17
+ };
18
+ /** Responses adapter with an explicit API key (low-level; the public branching factory delegates here). */
15
19
  function createBedrockResponsesText(model, apiKey, config) {
16
- return new BedrockResponsesTextAdapter({ ...config, apiKey }, model);
20
+ return new BedrockResponsesTextAdapter({
21
+ ...config,
22
+ apiKey
23
+ }, model);
17
24
  }
18
- export {
19
- BedrockResponsesTextAdapter,
20
- createBedrockResponsesText
21
- };
22
- //# sourceMappingURL=responses-text.js.map
25
+ //#endregion
26
+ export { BedrockResponsesTextAdapter, createBedrockResponsesText };
27
+
28
+ //# sourceMappingURL=responses-text.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"responses-text.js","sources":["../../../src/adapters/responses-text.ts"],"sourcesContent":["import OpenAI from 'openai'\nimport { OpenAIBaseResponsesTextAdapter } from '@tanstack/openai-base'\nimport { withBedrockDefaults } from '../utils/client'\nimport type { Modality } from '@tanstack/ai'\nimport type { BedrockClientConfig } from '../utils/client'\nimport type { BedrockMessageMetadataByModality } from '../message-types'\nimport type {\n BedrockChatModelToolCapabilitiesByName,\n BedrockResponsesModels,\n ResolveInputModalities,\n} from '../model-meta'\nimport type { ExternalResponsesProviderOptions } from '../text/responses-provider-options'\n\nexport interface BedrockResponsesConfig extends BedrockClientConfig {}\n\nexport type { ExternalResponsesProviderOptions as BedrockResponsesProviderOptions } from '../text/responses-provider-options'\n\ntype ResolveToolCapabilities<TModel extends string> =\n TModel extends keyof BedrockChatModelToolCapabilitiesByName\n ? NonNullable<BedrockChatModelToolCapabilitiesByName[TModel]>\n : readonly []\n\n/**\n * Bedrock Responses adapter. Drives mantle's OpenAI-compatible `/responses`\n * endpoint via the OpenAI SDK (`client.responses.create`) — the same base\n * class ai-openai's `openaiText` uses. Responses is mantle-only, so the\n * constructor forces the mantle baseURL.\n */\nexport class BedrockResponsesTextAdapter<\n TModel extends BedrockResponsesModels,\n // Constraint mirrors the chat adapter (and ai-groq / ai-openai) and the base,\n // which parameterises `TProviderOptions extends Record<string, any>`. Our\n // default `ExternalResponsesProviderOptions` is an interface that (lacking an\n // implicit index signature) `Record<string, unknown>` would reject but\n // `Record<string, any>` accepts. This `any` is confined to the generic\n // constraint — no value/shape `as` cast is introduced.\n TProviderOptions extends Record<string, any> =\n ExternalResponsesProviderOptions,\n TInputModalities extends ReadonlyArray<Modality> =\n ResolveInputModalities<TModel>,\n TToolCapabilities extends ReadonlyArray<string> =\n ResolveToolCapabilities<TModel>,\n> extends OpenAIBaseResponsesTextAdapter<\n TModel,\n TProviderOptions,\n TInputModalities,\n BedrockMessageMetadataByModality,\n TToolCapabilities\n> {\n override readonly kind = 'text' as const\n override readonly name = 'bedrock-responses' as const\n\n constructor(config: BedrockResponsesConfig, model: TModel) {\n // Responses is mantle-only — force the mantle base URL (an explicit\n // config.baseURL still wins, e.g. E2E pointing at aimock).\n super(\n model,\n 'bedrock-responses',\n new OpenAI(withBedrockDefaults(config, 'mantle')),\n )\n }\n}\n\n/** Responses adapter with an explicit API key (low-level; the public branching factory delegates here). */\nexport function createBedrockResponsesText<\n TModel extends BedrockResponsesModels,\n>(\n model: TModel,\n apiKey: string,\n config?: Omit<BedrockResponsesConfig, 'apiKey'>,\n): BedrockResponsesTextAdapter<TModel> {\n return new BedrockResponsesTextAdapter({ ...config, apiKey }, model)\n}\n"],"names":[],"mappings":";;;AA4BO,MAAM,oCAcH,+BAMR;AAAA,EACkB,OAAO;AAAA,EACP,OAAO;AAAA,EAEzB,YAAY,QAAgC,OAAe;AAGzD;AAAA,MACE;AAAA,MACA;AAAA,MACA,IAAI,OAAO,oBAAoB,QAAQ,QAAQ,CAAC;AAAA,IAAA;AAAA,EAEpD;AACF;AAGO,SAAS,2BAGd,OACA,QACA,QACqC;AACrC,SAAO,IAAI,4BAA4B,EAAE,GAAG,QAAQ,OAAA,GAAU,KAAK;AACrE;"}
1
+ {"version":3,"file":"responses-text.js","names":[],"sources":["../../../src/adapters/responses-text.ts"],"sourcesContent":["import OpenAI from 'openai'\nimport { OpenAIBaseResponsesTextAdapter } from '@tanstack/openai-base'\nimport { withBedrockDefaults } from '../utils/client'\nimport type { Modality } from '@tanstack/ai'\nimport type { BedrockClientConfig } from '../utils/client'\nimport type { BedrockMessageMetadataByModality } from '../message-types'\nimport type {\n BedrockChatModelToolCapabilitiesByName,\n BedrockResponsesModels,\n ResolveInputModalities,\n} from '../model-meta'\nimport type { ExternalResponsesProviderOptions } from '../text/responses-provider-options'\n\nexport interface BedrockResponsesConfig extends BedrockClientConfig {}\n\nexport type { ExternalResponsesProviderOptions as BedrockResponsesProviderOptions } from '../text/responses-provider-options'\n\ntype ResolveToolCapabilities<TModel extends string> =\n TModel extends keyof BedrockChatModelToolCapabilitiesByName\n ? NonNullable<BedrockChatModelToolCapabilitiesByName[TModel]>\n : readonly []\n\n/**\n * Bedrock Responses adapter. Drives mantle's OpenAI-compatible `/responses`\n * endpoint via the OpenAI SDK (`client.responses.create`) — the same base\n * class ai-openai's `openaiText` uses. Responses is mantle-only, so the\n * constructor forces the mantle baseURL.\n */\nexport class BedrockResponsesTextAdapter<\n TModel extends BedrockResponsesModels,\n // Constraint mirrors the chat adapter (and ai-groq / ai-openai) and the base,\n // which parameterises `TProviderOptions extends Record<string, any>`. Our\n // default `ExternalResponsesProviderOptions` is an interface that (lacking an\n // implicit index signature) `Record<string, unknown>` would reject but\n // `Record<string, any>` accepts. This `any` is confined to the generic\n // constraint — no value/shape `as` cast is introduced.\n TProviderOptions extends Record<string, any> =\n ExternalResponsesProviderOptions,\n TInputModalities extends ReadonlyArray<Modality> =\n ResolveInputModalities<TModel>,\n TToolCapabilities extends ReadonlyArray<string> =\n ResolveToolCapabilities<TModel>,\n> extends OpenAIBaseResponsesTextAdapter<\n TModel,\n TProviderOptions,\n TInputModalities,\n BedrockMessageMetadataByModality,\n TToolCapabilities\n> {\n override readonly kind = 'text' as const\n override readonly name = 'bedrock-responses' as const\n\n constructor(config: BedrockResponsesConfig, model: TModel) {\n // Responses is mantle-only — force the mantle base URL (an explicit\n // config.baseURL still wins, e.g. E2E pointing at aimock).\n super(\n model,\n 'bedrock-responses',\n new OpenAI(withBedrockDefaults(config, 'mantle')),\n )\n }\n}\n\n/** Responses adapter with an explicit API key (low-level; the public branching factory delegates here). */\nexport function createBedrockResponsesText<\n TModel extends BedrockResponsesModels,\n>(\n model: TModel,\n apiKey: string,\n config?: Omit<BedrockResponsesConfig, 'apiKey'>,\n): BedrockResponsesTextAdapter<TModel> {\n return new BedrockResponsesTextAdapter({ ...config, apiKey }, model)\n}\n"],"mappings":";;;;;;;;;;AA4BA,IAAa,8BAAb,cAcU,+BAMR;CACA,OAAyB;CACzB,OAAyB;CAEzB,YAAY,QAAgC,OAAe;EAGzD,MACE,OACA,qBACA,IAAI,OAAO,oBAAoB,QAAQ,QAAQ,CAAC,CAClD;CACF;AACF;;AAGA,SAAgB,2BAGd,OACA,QACA,QACqC;CACrC,OAAO,IAAI,4BAA4B;EAAE,GAAG;EAAQ;CAAO,GAAG,KAAK;AACrE"}
@@ -1,38 +1,47 @@
1
+ import { withBedrockDefaults } from "../utils/client.js";
1
2
  import OpenAI from "openai";
2
3
  import { OpenAIBaseChatCompletionsTextAdapter } from "@tanstack/openai-base";
3
- import { withBedrockDefaults } from "../utils/client.js";
4
- class BedrockTextAdapter extends OpenAIBaseChatCompletionsTextAdapter {
5
- kind = "text";
6
- name = "bedrock";
7
- constructor(config, model) {
8
- super(model, "bedrock", new OpenAI(withBedrockDefaults(config)));
9
- }
10
- /**
11
- * Surface reasoning deltas (gpt-oss / Claude reasoning) the OpenAI-compatible
12
- * way. Base types the chunk as `unknown`; narrow with runtime guards — no
13
- * `as` casts, no `any`.
14
- */
15
- extractReasoning(chunk) {
16
- return readDeltaReasoning(chunk);
17
- }
18
- }
4
+ //#region src/adapters/text.ts
5
+ /**
6
+ * Bedrock Chat Completions adapter. Drives Bedrock's OpenAI-compatible
7
+ * `/chat/completions` endpoint via the OpenAI SDK with a baseURL override
8
+ * (same pattern as ai-groq). Tool conversion, streaming, structured output,
9
+ * and the agent loop come from the base.
10
+ */
11
+ var BedrockTextAdapter = class extends OpenAIBaseChatCompletionsTextAdapter {
12
+ kind = "text";
13
+ name = "bedrock";
14
+ constructor(config, model) {
15
+ super(model, "bedrock", new OpenAI(withBedrockDefaults(config)));
16
+ }
17
+ /**
18
+ * Surface reasoning deltas (gpt-oss / Claude reasoning) the OpenAI-compatible
19
+ * way. Base types the chunk as `unknown`; narrow with runtime guards — no
20
+ * `as` casts, no `any`.
21
+ */
22
+ extractReasoning(chunk) {
23
+ return readDeltaReasoning(chunk);
24
+ }
25
+ };
26
+ /** Cast-free narrowing of a Chat Completions chunk's reasoning delta. */
19
27
  function readDeltaReasoning(chunk) {
20
- if (typeof chunk !== "object" || chunk === null || !("choices" in chunk))
21
- return void 0;
22
- if (!Array.isArray(chunk.choices)) return void 0;
23
- const choice = chunk.choices[0];
24
- if (typeof choice !== "object" || choice === null || !("delta" in choice))
25
- return void 0;
26
- const delta = choice.delta;
27
- if (typeof delta !== "object" || delta === null) return void 0;
28
- const raw = "reasoning" in delta && typeof delta.reasoning === "string" ? delta.reasoning : "reasoning_content" in delta && typeof delta.reasoning_content === "string" ? delta.reasoning_content : void 0;
29
- return raw && raw.length > 0 ? { text: raw } : void 0;
28
+ if (typeof chunk !== "object" || chunk === null || !("choices" in chunk)) return void 0;
29
+ if (!Array.isArray(chunk.choices)) return void 0;
30
+ const choice = chunk.choices[0];
31
+ if (typeof choice !== "object" || choice === null || !("delta" in choice)) return void 0;
32
+ const delta = choice.delta;
33
+ if (typeof delta !== "object" || delta === null) return void 0;
34
+ const raw = "reasoning" in delta && typeof delta.reasoning === "string" ? delta.reasoning : "reasoning_content" in delta && typeof delta.reasoning_content === "string" ? delta.reasoning_content : void 0;
35
+ return raw && raw.length > 0 ? { text: raw } : void 0;
30
36
  }
37
+ /** Chat adapter with an explicit API key (low-level; the public branching factory delegates here). */
31
38
  function createBedrockChat(model, apiKey, config) {
32
- return new BedrockTextAdapter({ ...config, apiKey }, model);
39
+ return new BedrockTextAdapter({
40
+ ...config,
41
+ apiKey
42
+ }, model);
33
43
  }
34
- export {
35
- BedrockTextAdapter,
36
- createBedrockChat
37
- };
38
- //# sourceMappingURL=text.js.map
44
+ //#endregion
45
+ export { BedrockTextAdapter, createBedrockChat };
46
+
47
+ //# sourceMappingURL=text.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"text.js","sources":["../../../src/adapters/text.ts"],"sourcesContent":["import OpenAI from 'openai'\nimport { OpenAIBaseChatCompletionsTextAdapter } from '@tanstack/openai-base'\nimport { withBedrockDefaults } from '../utils/client'\nimport type { Modality } from '@tanstack/ai'\nimport type { BedrockClientConfig } from '../utils/client'\nimport type { BedrockMessageMetadataByModality } from '../message-types'\nimport type {\n BedrockChatModelToolCapabilitiesByName,\n BedrockChatModels,\n ResolveInputModalities,\n ResolveProviderOptions,\n} from '../model-meta'\n\nexport interface BedrockTextConfig extends BedrockClientConfig {}\n\nexport type { ExternalTextProviderOptions as BedrockTextProviderOptions } from '../text/text-provider-options'\n\ntype ResolveToolCapabilities<TModel extends string> =\n TModel extends keyof BedrockChatModelToolCapabilitiesByName\n ? NonNullable<BedrockChatModelToolCapabilitiesByName[TModel]>\n : readonly []\n\n/**\n * Bedrock Chat Completions adapter. Drives Bedrock's OpenAI-compatible\n * `/chat/completions` endpoint via the OpenAI SDK with a baseURL override\n * (same pattern as ai-groq). Tool conversion, streaming, structured output,\n * and the agent loop come from the base.\n */\nexport class BedrockTextAdapter<\n TModel extends BedrockChatModels,\n // Constraint mirrors ai-groq and the base, which parameterises\n // `TProviderOptions extends Record<string, any>`. Our default\n // `ResolveProviderOptions<TModel>` resolves to the `BedrockTextProviderOptions`\n // interface, which (lacking an implicit index signature) `Record<string,\n // unknown>` would reject but `Record<string, any>` accepts. This `any` is\n // confined to the generic constraint (the established ai-groq pattern) — no\n // value/shape `as` cast is introduced.\n TProviderOptions extends Record<string, any> = ResolveProviderOptions<TModel>,\n TInputModalities extends ReadonlyArray<Modality> =\n ResolveInputModalities<TModel>,\n TToolCapabilities extends ReadonlyArray<string> =\n ResolveToolCapabilities<TModel>,\n> extends OpenAIBaseChatCompletionsTextAdapter<\n TModel,\n TProviderOptions,\n TInputModalities,\n BedrockMessageMetadataByModality,\n TToolCapabilities\n> {\n override readonly kind = 'text' as const\n override readonly name = 'bedrock' as const\n\n constructor(config: BedrockTextConfig, model: TModel) {\n // No `forced` -> honors config.endpoint ('runtime' default, 'mantle' allowed).\n super(model, 'bedrock', new OpenAI(withBedrockDefaults(config)))\n }\n\n /**\n * Surface reasoning deltas (gpt-oss / Claude reasoning) the OpenAI-compatible\n * way. Base types the chunk as `unknown`; narrow with runtime guards — no\n * `as` casts, no `any`.\n */\n protected override extractReasoning(\n chunk: unknown,\n ): { text: string } | undefined {\n return readDeltaReasoning(chunk)\n }\n}\n\n/** Cast-free narrowing of a Chat Completions chunk's reasoning delta. */\nfunction readDeltaReasoning(chunk: unknown): { text: string } | undefined {\n if (typeof chunk !== 'object' || chunk === null || !('choices' in chunk))\n return undefined\n if (!Array.isArray(chunk.choices)) return undefined\n const choice: unknown = chunk.choices[0]\n if (typeof choice !== 'object' || choice === null || !('delta' in choice))\n return undefined\n const delta = choice.delta\n if (typeof delta !== 'object' || delta === null) return undefined\n const raw =\n 'reasoning' in delta && typeof delta.reasoning === 'string'\n ? delta.reasoning\n : 'reasoning_content' in delta &&\n typeof delta.reasoning_content === 'string'\n ? delta.reasoning_content\n : undefined\n return raw && raw.length > 0 ? { text: raw } : undefined\n}\n\n/** Chat adapter with an explicit API key (low-level; the public branching factory delegates here). */\nexport function createBedrockChat<TModel extends BedrockChatModels>(\n model: TModel,\n apiKey: string,\n config?: Omit<BedrockTextConfig, 'apiKey'>,\n): BedrockTextAdapter<TModel> {\n return new BedrockTextAdapter({ ...config, apiKey }, model)\n}\n"],"names":[],"mappings":";;;AA4BO,MAAM,2BAcH,qCAMR;AAAA,EACkB,OAAO;AAAA,EACP,OAAO;AAAA,EAEzB,YAAY,QAA2B,OAAe;AAEpD,UAAM,OAAO,WAAW,IAAI,OAAO,oBAAoB,MAAM,CAAC,CAAC;AAAA,EACjE;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOmB,iBACjB,OAC8B;AAC9B,WAAO,mBAAmB,KAAK;AAAA,EACjC;AACF;AAGA,SAAS,mBAAmB,OAA8C;AACxE,MAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,EAAE,aAAa;AAChE,WAAO;AACT,MAAI,CAAC,MAAM,QAAQ,MAAM,OAAO,EAAG,QAAO;AAC1C,QAAM,SAAkB,MAAM,QAAQ,CAAC;AACvC,MAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,EAAE,WAAW;AAChE,WAAO;AACT,QAAM,QAAQ,OAAO;AACrB,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,QAAM,MACJ,eAAe,SAAS,OAAO,MAAM,cAAc,WAC/C,MAAM,YACN,uBAAuB,SACrB,OAAO,MAAM,sBAAsB,WACnC,MAAM,oBACN;AACR,SAAO,OAAO,IAAI,SAAS,IAAI,EAAE,MAAM,QAAQ;AACjD;AAGO,SAAS,kBACd,OACA,QACA,QAC4B;AAC5B,SAAO,IAAI,mBAAmB,EAAE,GAAG,QAAQ,OAAA,GAAU,KAAK;AAC5D;"}
1
+ {"version":3,"file":"text.js","names":[],"sources":["../../../src/adapters/text.ts"],"sourcesContent":["import OpenAI from 'openai'\nimport { OpenAIBaseChatCompletionsTextAdapter } from '@tanstack/openai-base'\nimport { withBedrockDefaults } from '../utils/client'\nimport type { Modality } from '@tanstack/ai'\nimport type { BedrockClientConfig } from '../utils/client'\nimport type { BedrockMessageMetadataByModality } from '../message-types'\nimport type {\n BedrockChatModelToolCapabilitiesByName,\n BedrockChatModels,\n ResolveInputModalities,\n ResolveProviderOptions,\n} from '../model-meta'\n\nexport interface BedrockTextConfig extends BedrockClientConfig {}\n\nexport type { ExternalTextProviderOptions as BedrockTextProviderOptions } from '../text/text-provider-options'\n\ntype ResolveToolCapabilities<TModel extends string> =\n TModel extends keyof BedrockChatModelToolCapabilitiesByName\n ? NonNullable<BedrockChatModelToolCapabilitiesByName[TModel]>\n : readonly []\n\n/**\n * Bedrock Chat Completions adapter. Drives Bedrock's OpenAI-compatible\n * `/chat/completions` endpoint via the OpenAI SDK with a baseURL override\n * (same pattern as ai-groq). Tool conversion, streaming, structured output,\n * and the agent loop come from the base.\n */\nexport class BedrockTextAdapter<\n TModel extends BedrockChatModels,\n // Constraint mirrors ai-groq and the base, which parameterises\n // `TProviderOptions extends Record<string, any>`. Our default\n // `ResolveProviderOptions<TModel>` resolves to the `BedrockTextProviderOptions`\n // interface, which (lacking an implicit index signature) `Record<string,\n // unknown>` would reject but `Record<string, any>` accepts. This `any` is\n // confined to the generic constraint (the established ai-groq pattern) — no\n // value/shape `as` cast is introduced.\n TProviderOptions extends Record<string, any> = ResolveProviderOptions<TModel>,\n TInputModalities extends ReadonlyArray<Modality> =\n ResolveInputModalities<TModel>,\n TToolCapabilities extends ReadonlyArray<string> =\n ResolveToolCapabilities<TModel>,\n> extends OpenAIBaseChatCompletionsTextAdapter<\n TModel,\n TProviderOptions,\n TInputModalities,\n BedrockMessageMetadataByModality,\n TToolCapabilities\n> {\n override readonly kind = 'text' as const\n override readonly name = 'bedrock' as const\n\n constructor(config: BedrockTextConfig, model: TModel) {\n // No `forced` -> honors config.endpoint ('runtime' default, 'mantle' allowed).\n super(model, 'bedrock', new OpenAI(withBedrockDefaults(config)))\n }\n\n /**\n * Surface reasoning deltas (gpt-oss / Claude reasoning) the OpenAI-compatible\n * way. Base types the chunk as `unknown`; narrow with runtime guards — no\n * `as` casts, no `any`.\n */\n protected override extractReasoning(\n chunk: unknown,\n ): { text: string } | undefined {\n return readDeltaReasoning(chunk)\n }\n}\n\n/** Cast-free narrowing of a Chat Completions chunk's reasoning delta. */\nfunction readDeltaReasoning(chunk: unknown): { text: string } | undefined {\n if (typeof chunk !== 'object' || chunk === null || !('choices' in chunk))\n return undefined\n if (!Array.isArray(chunk.choices)) return undefined\n const choice: unknown = chunk.choices[0]\n if (typeof choice !== 'object' || choice === null || !('delta' in choice))\n return undefined\n const delta = choice.delta\n if (typeof delta !== 'object' || delta === null) return undefined\n const raw =\n 'reasoning' in delta && typeof delta.reasoning === 'string'\n ? delta.reasoning\n : 'reasoning_content' in delta &&\n typeof delta.reasoning_content === 'string'\n ? delta.reasoning_content\n : undefined\n return raw && raw.length > 0 ? { text: raw } : undefined\n}\n\n/** Chat adapter with an explicit API key (low-level; the public branching factory delegates here). */\nexport function createBedrockChat<TModel extends BedrockChatModels>(\n model: TModel,\n apiKey: string,\n config?: Omit<BedrockTextConfig, 'apiKey'>,\n): BedrockTextAdapter<TModel> {\n return new BedrockTextAdapter({ ...config, apiKey }, model)\n}\n"],"mappings":";;;;;;;;;;AA4BA,IAAa,qBAAb,cAcU,qCAMR;CACA,OAAyB;CACzB,OAAyB;CAEzB,YAAY,QAA2B,OAAe;EAEpD,MAAM,OAAO,WAAW,IAAI,OAAO,oBAAoB,MAAM,CAAC,CAAC;CACjE;;;;;;CAOA,iBACE,OAC8B;EAC9B,OAAO,mBAAmB,KAAK;CACjC;AACF;;AAGA,SAAS,mBAAmB,OAA8C;CACxE,IAAI,OAAO,UAAU,YAAY,UAAU,QAAQ,EAAE,aAAa,QAChE,OAAO,KAAA;CACT,IAAI,CAAC,MAAM,QAAQ,MAAM,OAAO,GAAG,OAAO,KAAA;CAC1C,MAAM,SAAkB,MAAM,QAAQ;CACtC,IAAI,OAAO,WAAW,YAAY,WAAW,QAAQ,EAAE,WAAW,SAChE,OAAO,KAAA;CACT,MAAM,QAAQ,OAAO;CACrB,IAAI,OAAO,UAAU,YAAY,UAAU,MAAM,OAAO,KAAA;CACxD,MAAM,MACJ,eAAe,SAAS,OAAO,MAAM,cAAc,WAC/C,MAAM,YACN,uBAAuB,SACrB,OAAO,MAAM,sBAAsB,WACnC,MAAM,oBACN,KAAA;CACR,OAAO,OAAO,IAAI,SAAS,IAAI,EAAE,MAAM,IAAI,IAAI,KAAA;AACjD;;AAGA,SAAgB,kBACd,OACA,QACA,QAC4B;CAC5B,OAAO,IAAI,mBAAmB;EAAE,GAAG;EAAQ;CAAO,GAAG,KAAK;AAC5D"}
@@ -1,181 +1,135 @@
1
1
  import { normalizeSystemPrompts } from "@tanstack/ai";
2
+ //#region src/converse/message-converter.ts
2
3
  function base64ToBytes(b64) {
3
- return new Uint8Array(Buffer.from(b64, "base64"));
4
+ return new Uint8Array(Buffer.from(b64, "base64"));
4
5
  }
5
6
  function imageFormat(mime) {
6
- switch (mime) {
7
- case "image/png":
8
- return "png";
9
- case "image/jpeg":
10
- case "image/jpg":
11
- return "jpeg";
12
- case "image/gif":
13
- return "gif";
14
- case "image/webp":
15
- return "webp";
16
- default:
17
- throw new Error(
18
- `Bedrock Converse: unsupported image MIME type "${mime}". Supported types: image/png, image/jpeg, image/gif, image/webp.`
19
- );
20
- }
7
+ switch (mime) {
8
+ case "image/png": return "png";
9
+ case "image/jpeg":
10
+ case "image/jpg": return "jpeg";
11
+ case "image/gif": return "gif";
12
+ case "image/webp": return "webp";
13
+ default: throw new Error(`Bedrock Converse: unsupported image MIME type "${mime}". Supported types: image/png, image/jpeg, image/gif, image/webp.`);
14
+ }
21
15
  }
22
16
  function documentFormat(mime) {
23
- switch (mime) {
24
- case "application/pdf":
25
- return "pdf";
26
- case "text/csv":
27
- return "csv";
28
- case "application/msword":
29
- return "doc";
30
- case "application/vnd.openxmlformats-officedocument.wordprocessingml.document":
31
- return "docx";
32
- case "application/vnd.ms-excel":
33
- return "xls";
34
- case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet":
35
- return "xlsx";
36
- case "text/html":
37
- return "html";
38
- case "text/plain":
39
- return "txt";
40
- case "text/markdown":
41
- case "text/x-markdown":
42
- return "md";
43
- default:
44
- throw new Error(
45
- `Bedrock Converse: unsupported document MIME type "${mime}". Supported types: pdf, csv, doc, docx, xls, xlsx, html, txt, md.`
46
- );
47
- }
17
+ switch (mime) {
18
+ case "application/pdf": return "pdf";
19
+ case "text/csv": return "csv";
20
+ case "application/msword": return "doc";
21
+ case "application/vnd.openxmlformats-officedocument.wordprocessingml.document": return "docx";
22
+ case "application/vnd.ms-excel": return "xls";
23
+ case "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": return "xlsx";
24
+ case "text/html": return "html";
25
+ case "text/plain": return "txt";
26
+ case "text/markdown":
27
+ case "text/x-markdown": return "md";
28
+ default: throw new Error(`Bedrock Converse: unsupported document MIME type "${mime}". Supported types: pdf, csv, doc, docx, xls, xlsx, html, txt, md.`);
29
+ }
48
30
  }
49
31
  function stringContent(content) {
50
- if (content === null) return "";
51
- if (typeof content === "string") return content;
52
- return content.filter((p) => p.type === "text").map((p) => p.content).join("");
32
+ if (content === null) return "";
33
+ if (typeof content === "string") return content;
34
+ return content.filter((p) => p.type === "text").map((p) => p.content).join("");
53
35
  }
54
36
  function isTextPart(p) {
55
- return p.type === "text";
37
+ return p.type === "text";
56
38
  }
57
39
  function isImagePart(p) {
58
- return p.type === "image";
40
+ return p.type === "image";
59
41
  }
60
42
  function isDocumentPart(p) {
61
- return p.type === "document";
43
+ return p.type === "document";
62
44
  }
63
45
  function isDataSource(source) {
64
- return source.type === "data";
46
+ return source.type === "data";
65
47
  }
66
48
  function contentPartToBlock(part, docIndex) {
67
- if (isTextPart(part)) {
68
- return { text: part.content };
69
- }
70
- if (isImagePart(part)) {
71
- const { source } = part;
72
- if (!isDataSource(source)) {
73
- throw new Error(
74
- "Bedrock Converse requires inline image bytes; URL image sources are not supported."
75
- );
76
- }
77
- return {
78
- image: {
79
- format: imageFormat(source.mimeType),
80
- source: { bytes: base64ToBytes(source.value) }
81
- }
82
- };
83
- }
84
- if (isDocumentPart(part)) {
85
- const { source } = part;
86
- if (!isDataSource(source)) {
87
- throw new Error(
88
- "Bedrock Converse requires inline document bytes; URL document sources are not supported."
89
- );
90
- }
91
- return {
92
- document: {
93
- format: documentFormat(source.mimeType),
94
- name: `document-${docIndex}`,
95
- source: { bytes: base64ToBytes(source.value) }
96
- }
97
- };
98
- }
99
- throw new Error(
100
- `Bedrock Converse does not support content part type "${String(part.type)}".`
101
- );
49
+ if (isTextPart(part)) return { text: part.content };
50
+ if (isImagePart(part)) {
51
+ const { source } = part;
52
+ if (!isDataSource(source)) throw new Error("Bedrock Converse requires inline image bytes; URL image sources are not supported.");
53
+ return { image: {
54
+ format: imageFormat(source.mimeType),
55
+ source: { bytes: base64ToBytes(source.value) }
56
+ } };
57
+ }
58
+ if (isDocumentPart(part)) {
59
+ const { source } = part;
60
+ if (!isDataSource(source)) throw new Error("Bedrock Converse requires inline document bytes; URL document sources are not supported.");
61
+ return { document: {
62
+ format: documentFormat(source.mimeType),
63
+ name: `document-${docIndex}`,
64
+ source: { bytes: base64ToBytes(source.value) }
65
+ } };
66
+ }
67
+ throw new Error(`Bedrock Converse does not support content part type "${String(part.type)}".`);
102
68
  }
103
69
  function messageToBlocks(msg, docCounter) {
104
- const blocks = [];
105
- if (msg.role === "tool") {
106
- if (!msg.toolCallId) {
107
- throw new Error(
108
- "Bedrock Converse: tool message is missing toolCallId. Every tool result must reference the tool use ID it is responding to."
109
- );
110
- }
111
- const textContent = stringContent(msg.content);
112
- const toolResult = { text: textContent };
113
- blocks.push({
114
- toolResult: {
115
- toolUseId: msg.toolCallId,
116
- content: [toolResult],
117
- status: "success"
118
- }
119
- });
120
- return blocks;
121
- }
122
- if (typeof msg.content === "string") {
123
- if (msg.content !== "") {
124
- blocks.push({ text: msg.content });
125
- }
126
- } else if (Array.isArray(msg.content)) {
127
- for (const part of msg.content) {
128
- const docIndex = isDocumentPart(part) ? ++docCounter.value : 0;
129
- blocks.push(contentPartToBlock(part, docIndex));
130
- }
131
- }
132
- if (msg.role === "assistant" && msg.toolCalls) {
133
- for (const call of msg.toolCalls) {
134
- const rawArguments = call.function.arguments || "{}";
135
- let parsed;
136
- try {
137
- parsed = JSON.parse(rawArguments);
138
- } catch (error) {
139
- throw new Error(
140
- `Bedrock Converse: tool call "${call.function.name}" has malformed JSON arguments (${String(error)}). Raw: ${rawArguments}`
141
- );
142
- }
143
- if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
144
- throw new Error(
145
- `Bedrock Converse: tool call "${call.function.name}" arguments must be a JSON object, got ${Array.isArray(parsed) ? "array" : typeof parsed}.`
146
- );
147
- }
148
- blocks.push({
149
- toolUse: {
150
- toolUseId: call.id,
151
- name: call.function.name,
152
- input: parsed
153
- }
154
- });
155
- }
156
- }
157
- return blocks;
70
+ const blocks = [];
71
+ if (msg.role === "tool") {
72
+ if (!msg.toolCallId) throw new Error("Bedrock Converse: tool message is missing toolCallId. Every tool result must reference the tool use ID it is responding to.");
73
+ const toolResult = { text: stringContent(msg.content) };
74
+ blocks.push({ toolResult: {
75
+ toolUseId: msg.toolCallId,
76
+ content: [toolResult],
77
+ status: "success"
78
+ } });
79
+ return blocks;
80
+ }
81
+ if (typeof msg.content === "string") {
82
+ if (msg.content !== "") blocks.push({ text: msg.content });
83
+ } else if (Array.isArray(msg.content)) for (const part of msg.content) {
84
+ const docIndex = isDocumentPart(part) ? ++docCounter.value : 0;
85
+ blocks.push(contentPartToBlock(part, docIndex));
86
+ }
87
+ if (msg.role === "assistant" && msg.toolCalls) for (const call of msg.toolCalls) {
88
+ const rawArguments = call.function.arguments || "{}";
89
+ let parsed;
90
+ try {
91
+ parsed = JSON.parse(rawArguments);
92
+ } catch (error) {
93
+ throw new Error(`Bedrock Converse: tool call "${call.function.name}" has malformed JSON arguments (${String(error)}). Raw: ${rawArguments}`);
94
+ }
95
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error(`Bedrock Converse: tool call "${call.function.name}" arguments must be a JSON object, got ${Array.isArray(parsed) ? "array" : typeof parsed}.`);
96
+ blocks.push({ toolUse: {
97
+ toolUseId: call.id,
98
+ name: call.function.name,
99
+ input: parsed
100
+ } });
101
+ }
102
+ return blocks;
158
103
  }
104
+ /**
105
+ * Convert TanStack AI messages + system prompts into the Converse API format.
106
+ *
107
+ * - System prompts are lifted into `SystemContentBlock[]`.
108
+ * - `tool` role messages are remapped to `user` role `toolResult` blocks.
109
+ * - Consecutive messages with the same Converse role are merged (Converse
110
+ * requires strict user/assistant alternation).
111
+ */
159
112
  function toConverseMessages(messages, systemPrompts) {
160
- const system = normalizeSystemPrompts(
161
- systemPrompts
162
- ).map((p) => ({ text: p.content }));
163
- const converseMessages = [];
164
- const docCounter = { value: 0 };
165
- for (const msg of messages) {
166
- const converseRole = msg.role === "assistant" ? "assistant" : "user";
167
- const blocks = messageToBlocks(msg, docCounter);
168
- if (blocks.length === 0) continue;
169
- const last = converseMessages[converseMessages.length - 1];
170
- if (last && last.role === converseRole) {
171
- last.content = [...last.content ?? [], ...blocks];
172
- } else {
173
- converseMessages.push({ role: converseRole, content: blocks });
174
- }
175
- }
176
- return { system, messages: converseMessages };
113
+ const system = normalizeSystemPrompts(systemPrompts).map((p) => ({ text: p.content }));
114
+ const converseMessages = [];
115
+ const docCounter = { value: 0 };
116
+ for (const msg of messages) {
117
+ const converseRole = msg.role === "assistant" ? "assistant" : "user";
118
+ const blocks = messageToBlocks(msg, docCounter);
119
+ if (blocks.length === 0) continue;
120
+ const last = converseMessages[converseMessages.length - 1];
121
+ if (last && last.role === converseRole) last.content = [...last.content ?? [], ...blocks];
122
+ else converseMessages.push({
123
+ role: converseRole,
124
+ content: blocks
125
+ });
126
+ }
127
+ return {
128
+ system,
129
+ messages: converseMessages
130
+ };
177
131
  }
178
- export {
179
- toConverseMessages
180
- };
181
- //# sourceMappingURL=message-converter.js.map
132
+ //#endregion
133
+ export { toConverseMessages };
134
+
135
+ //# sourceMappingURL=message-converter.js.map