@illuma-ai/agents 1.1.20 → 1.1.21

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.
@@ -92,6 +92,20 @@ class IllumaBedrockConverse extends aws.ChatBedrockConverse {
92
92
  invocationParams(options) {
93
93
  const params = super.invocationParams(options);
94
94
  // Add cachePoint to tools array if promptCache is enabled and tools exist
95
+ /**
96
+ * Bedrock requires all toolSpec.description fields to be non-empty strings.
97
+ * Some tools (e.g., MCP-sourced or dynamically created) may have empty or
98
+ * missing descriptions. Patch them here to avoid Bedrock validation errors.
99
+ */
100
+ if (params.toolConfig?.tools &&
101
+ Array.isArray(params.toolConfig.tools)) {
102
+ for (const t of params.toolConfig.tools) {
103
+ const spec = t.toolSpec;
104
+ if (spec && (!spec.description || spec.description === '')) {
105
+ spec.description = spec.description || `Tool: ${spec.name ?? 'unknown'}`;
106
+ }
107
+ }
108
+ }
95
109
  // Only Claude models support cachePoint - check model name
96
110
  const modelId = this.model.toLowerCase();
97
111
  const isClaudeModel = modelId.includes('claude') || modelId.includes('anthropic');
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs","sources":["../../../../src/llm/bedrock/index.ts"],"sourcesContent":["/**\n * Optimized ChatBedrockConverse wrapper that fixes content block merging for\n * streaming responses and adds support for latest @langchain/aws features:\n *\n * - Prompt caching support for Bedrock Converse API (Illuma feature)\n * - Application Inference Profiles (PR #9129)\n * - Service Tiers (Priority/Standard/Flex) (PR #9785) - requires AWS SDK 3.966.0+\n *\n * Bedrock's `@langchain/aws` library does not include an `index` property on content\n * blocks (unlike Anthropic/OpenAI), which causes LangChain's `_mergeLists` to append\n * each streaming chunk as a separate array entry instead of merging by index.\n *\n * This wrapper takes full ownership of the stream by directly interfacing with the\n * AWS SDK client (`this.client`) and using custom handlers from `./utils/` that\n * include `contentBlockIndex` in response_metadata for every delta type. It then\n * promotes `contentBlockIndex` to an `index` property on each content block\n * (mirroring Anthropic's pattern) and strips it from metadata to avoid\n * `_mergeDicts` conflicts.\n *\n * When multiple content block types are present (e.g. reasoning + text), text deltas\n * are promoted from strings to array form with `index` so they merge correctly once\n * the accumulated content is already an array.\n *\n * PROMPT CACHING:\n * When promptCache: true is set, this wrapper adds cachePoint markers to the tools array\n * to enable Bedrock prompt caching for tool definitions. This allows tool schemas to be\n * cached and reused across requests, reducing latency and costs.\n *\n * CACHE TOKEN EXTRACTION:\n * Cache token extraction is handled in `./utils/message_outputs.ts` and added\n * to usage_metadata with input_token_details (cacheReadInputTokens/cacheWriteInputTokens).\n */\n\nimport { ChatBedrockConverse } from '@langchain/aws';\nimport { ConverseStreamCommand } from '@aws-sdk/client-bedrock-runtime';\nimport { AIMessageChunk } from '@langchain/core/messages';\nimport type { BaseMessage } from '@langchain/core/messages';\nimport { ChatGenerationChunk, ChatResult } from '@langchain/core/outputs';\nimport type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';\nimport type { ChatBedrockConverseInput } from '@langchain/aws';\nimport {\n convertToConverseMessages,\n handleConverseStreamContentBlockStart,\n handleConverseStreamContentBlockDelta,\n handleConverseStreamMetadata,\n} from './utils';\n\n/**\n * Service tier type for Bedrock invocations.\n * Requires AWS SDK >= 3.966.0 to actually work.\n * @see https://docs.aws.amazon.com/bedrock/latest/userguide/service-tiers-inference.html\n */\nexport type ServiceTierType = 'priority' | 'default' | 'flex' | 'reserved';\n\n/**\n * Extended input interface with additional features:\n * - promptCache: Enable Bedrock prompt caching for tool definitions\n * - applicationInferenceProfile: Use an inference profile ARN instead of model ID\n * - serviceTier: Specify service tier (Priority, Standard, Flex, Reserved)\n */\nexport interface IllumaBedrockConverseInput extends ChatBedrockConverseInput {\n /**\n * Enable Bedrock prompt caching for tool definitions.\n * When true, adds cachePoint markers to tools array.\n */\n promptCache?: boolean;\n\n /**\n * Application Inference Profile ARN to use for the model.\n * For example, \"arn:aws:bedrock:eu-west-1:123456789102:application-inference-profile/fm16bt65tzgx\"\n * When provided, this ARN will be used for the actual inference calls instead of the model ID.\n * Must still provide `model` as normal modelId to benefit from all the metadata.\n * @see https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-create.html\n */\n applicationInferenceProfile?: string;\n\n /**\n * Service tier for model invocation.\n * Specifies the processing tier type used for serving the request.\n * Supported values are 'priority', 'default', 'flex', and 'reserved'.\n *\n * - 'priority': Prioritized processing for lower latency\n * - 'default': Standard processing tier\n * - 'flex': Flexible processing tier with lower cost\n * - 'reserved': Reserved capacity for consistent performance\n *\n * If not provided, AWS uses the default tier.\n * Note: Requires AWS SDK >= 3.966.0 to work.\n * @see https://docs.aws.amazon.com/bedrock/latest/userguide/service-tiers-inference.html\n */\n serviceTier?: ServiceTierType;\n}\n\n/**\n * Extended call options with serviceTier override support.\n */\nexport interface IllumaBedrockConverseCallOptions {\n serviceTier?: ServiceTierType;\n}\n\nexport class IllumaBedrockConverse extends ChatBedrockConverse {\n /** Enable Bedrock prompt caching for tool definitions */\n promptCache: boolean;\n\n /** Application Inference Profile ARN to use instead of model ID */\n applicationInferenceProfile?: string;\n\n /** Service tier for model invocation */\n serviceTier?: ServiceTierType;\n\n constructor(fields?: IllumaBedrockConverseInput) {\n super(fields);\n this.promptCache = fields?.promptCache ?? false;\n this.applicationInferenceProfile = fields?.applicationInferenceProfile;\n this.serviceTier = fields?.serviceTier;\n\n // Fix: Force supportsToolChoiceValues for Claude models\n // The parent constructor checks `model.includes('claude-3')` but this fails when:\n // 1. Using applicationInferenceProfile ARNs (arn:aws:bedrock:...)\n // 2. Using different naming conventions (claude-4, claude-opus-4, etc.)\n // We need to ensure tool_choice is properly set for withStructuredOutput to work\n const modelName = (fields?.model ?? '').toLowerCase();\n const profileName = (\n fields?.applicationInferenceProfile ?? ''\n ).toLowerCase();\n const isClaudeModel =\n modelName.includes('claude') ||\n modelName.includes('anthropic') ||\n profileName.includes('claude') ||\n profileName.includes('anthropic');\n\n if (isClaudeModel && !this.supportsToolChoiceValues?.length) {\n // Claude models support all tool choice values\n this.supportsToolChoiceValues = ['auto', 'any', 'tool'];\n }\n }\n\n static lc_name(): string {\n return 'IllumaBedrockConverse';\n }\n\n /**\n * Get the model ID to use for API calls.\n * Returns applicationInferenceProfile if set, otherwise returns this.model.\n */\n protected getModelId(): string {\n return this.applicationInferenceProfile ?? this.model;\n }\n\n /**\n * Override invocationParams to:\n * 1. Add cachePoint to tools when promptCache is enabled\n * 2. Add serviceTier support\n *\n * CACHING STRATEGY: Separate cachePoints for core tools and MCP tools\n * - Core tools (web_search, execute_code, etc.) are stable → cache first\n * - MCP tools (have '_mcp_' in name) are dynamic → cache separately after\n * - This allows core tools to stay cached when MCP selection changes\n *\n * NOTE: Only Claude models support cachePoint - Nova and other models will reject it.\n */\n override invocationParams(\n options?: this['ParsedCallOptions'] & IllumaBedrockConverseCallOptions\n ): ReturnType<ChatBedrockConverse['invocationParams']> & {\n serviceTier?: { type: ServiceTierType };\n } {\n const params = super.invocationParams(options);\n\n // Add cachePoint to tools array if promptCache is enabled and tools exist\n // Only Claude models support cachePoint - check model name\n const modelId = this.model.toLowerCase();\n const isClaudeModel =\n modelId.includes('claude') || modelId.includes('anthropic');\n\n if (\n this.promptCache &&\n isClaudeModel &&\n params.toolConfig?.tools &&\n Array.isArray(params.toolConfig.tools) &&\n params.toolConfig.tools.length > 0\n ) {\n // Separate core tools from MCP tools\n // MCP tools have '_mcp_' in their name (e.g., 'search_emails_mcp_Google-Workspace')\n const coreTools: typeof params.toolConfig.tools = [];\n const mcpTools: typeof params.toolConfig.tools = [];\n\n for (const tool of params.toolConfig.tools) {\n // Check if tool has a name property with '_mcp_' pattern\n const toolName =\n (tool as { toolSpec?: { name?: string } }).toolSpec?.name ?? '';\n if (toolName.includes('_mcp_')) {\n mcpTools.push(tool);\n } else {\n coreTools.push(tool);\n }\n }\n\n // Build tools array with strategic cachePoints:\n // [CoreTool1, CoreTool2, cachePoint] + [MCPTool1, MCPTool2, cachePoint]\n const toolsWithCache: typeof params.toolConfig.tools = [];\n\n // Add core tools with cachePoint (if any)\n if (coreTools.length > 0) {\n toolsWithCache.push(...coreTools);\n toolsWithCache.push({ cachePoint: { type: 'default' } });\n }\n\n // Add MCP tools with their own cachePoint (if any)\n if (mcpTools.length > 0) {\n toolsWithCache.push(...mcpTools);\n toolsWithCache.push({ cachePoint: { type: 'default' } });\n }\n\n // If no tools at all (shouldn't happen but safety check)\n if (toolsWithCache.length === 0) {\n toolsWithCache.push({ cachePoint: { type: 'default' } });\n }\n\n params.toolConfig.tools = toolsWithCache;\n }\n\n // Add serviceTier support\n const serviceTierType = options?.serviceTier ?? this.serviceTier;\n\n return {\n ...params,\n serviceTier: serviceTierType ? { type: serviceTierType } : undefined,\n };\n }\n\n /**\n * Override _generateNonStreaming to use applicationInferenceProfile as modelId.\n * Uses the same model-swapping pattern as streaming for consistency.\n */\n override async _generateNonStreaming(\n messages: BaseMessage[],\n options: this['ParsedCallOptions'] & IllumaBedrockConverseCallOptions,\n runManager?: CallbackManagerForLLMRun\n ): Promise<ChatResult> {\n const originalModel = this.model;\n if (\n this.applicationInferenceProfile != null &&\n this.applicationInferenceProfile !== ''\n ) {\n this.model = this.applicationInferenceProfile;\n }\n\n try {\n return await super._generateNonStreaming(messages, options, runManager);\n } finally {\n this.model = originalModel;\n }\n }\n\n /**\n * Own the stream end-to-end so we have direct access to every\n * `contentBlockDelta.contentBlockIndex` from the AWS SDK.\n *\n * This replaces the parent's implementation which strips contentBlockIndex\n * from text and reasoning deltas, making it impossible to merge correctly.\n */\n override async *_streamResponseChunks(\n messages: BaseMessage[],\n options: this['ParsedCallOptions'] & IllumaBedrockConverseCallOptions,\n runManager?: CallbackManagerForLLMRun\n ): AsyncGenerator<ChatGenerationChunk> {\n const { converseMessages, converseSystem } =\n convertToConverseMessages(messages);\n const params = this.invocationParams(options);\n\n let { streamUsage } = this;\n if ((options as Record<string, unknown>).streamUsage !== undefined) {\n streamUsage = (options as Record<string, unknown>).streamUsage as boolean;\n }\n\n const modelId = this.getModelId();\n\n const command = new ConverseStreamCommand({\n modelId,\n messages: converseMessages,\n system: converseSystem,\n ...(params as Record<string, unknown>),\n });\n\n const response = await this.client.send(command, {\n abortSignal: options.signal,\n });\n\n if (!response.stream) {\n return;\n }\n\n const seenBlockIndices = new Set<number>();\n\n for await (const event of response.stream) {\n if (event.contentBlockStart != null) {\n const startChunk = handleConverseStreamContentBlockStart(\n event.contentBlockStart\n );\n if (startChunk != null) {\n const idx = event.contentBlockStart.contentBlockIndex;\n if (idx != null) {\n seenBlockIndices.add(idx);\n }\n yield this.enrichChunk(startChunk, seenBlockIndices);\n }\n } else if (event.contentBlockDelta != null) {\n const deltaChunk = handleConverseStreamContentBlockDelta(\n event.contentBlockDelta\n );\n\n const idx = event.contentBlockDelta.contentBlockIndex;\n if (idx != null) {\n seenBlockIndices.add(idx);\n }\n\n yield this.enrichChunk(deltaChunk, seenBlockIndices);\n\n await runManager?.handleLLMNewToken(\n deltaChunk.text,\n undefined,\n undefined,\n undefined,\n undefined,\n { chunk: deltaChunk }\n );\n } else if (event.metadata != null) {\n yield handleConverseStreamMetadata(event.metadata, { streamUsage });\n } else if (event.contentBlockStop != null) {\n const stopIdx = event.contentBlockStop.contentBlockIndex;\n if (stopIdx != null) {\n seenBlockIndices.add(stopIdx);\n }\n } else {\n yield new ChatGenerationChunk({\n text: '',\n message: new AIMessageChunk({\n content: '',\n response_metadata: event,\n }),\n });\n }\n }\n }\n\n /**\n * Inject `index` on content blocks for proper merge behaviour, then strip\n * `contentBlockIndex` from response_metadata to prevent `_mergeDicts` conflicts.\n *\n * Text string content is promoted to array form only when the stream contains\n * multiple content block indices (e.g. reasoning at index 0, text at index 1),\n * ensuring text merges correctly with the already-array accumulated content.\n */\n enrichChunk(\n chunk: ChatGenerationChunk,\n seenBlockIndices: Set<number>\n ): ChatGenerationChunk {\n const message = chunk.message;\n if (!(message instanceof AIMessageChunk)) {\n return chunk;\n }\n\n const metadata = message.response_metadata as Record<string, unknown>;\n const blockIndex = this.extractContentBlockIndex(metadata);\n const hasMetadataIndex = blockIndex != null;\n\n let content: AIMessageChunk['content'] = message.content;\n let contentModified = false;\n\n if (Array.isArray(content) && blockIndex != null) {\n content = content.map((block) =>\n typeof block === 'object' && !('index' in block)\n ? { ...block, index: blockIndex }\n : block\n );\n contentModified = true;\n } else if (\n typeof content === 'string' &&\n content !== '' &&\n blockIndex != null &&\n seenBlockIndices.size > 1\n ) {\n content = [{ type: 'text', text: content, index: blockIndex }];\n contentModified = true;\n }\n\n if (!contentModified && !hasMetadataIndex) {\n return chunk;\n }\n\n const cleanedMetadata = hasMetadataIndex\n ? (this.removeContentBlockIndex(metadata) as Record<string, unknown>)\n : metadata;\n\n return new ChatGenerationChunk({\n text: chunk.text,\n message: new AIMessageChunk({\n ...message,\n content,\n response_metadata: cleanedMetadata,\n }),\n generationInfo: chunk.generationInfo,\n });\n }\n\n /**\n * Extract `contentBlockIndex` from the top level of response_metadata.\n * Our custom handlers always place it at the top level.\n */\n private extractContentBlockIndex(\n metadata: Record<string, unknown>\n ): number | undefined {\n if (\n 'contentBlockIndex' in metadata &&\n typeof metadata.contentBlockIndex === 'number'\n ) {\n return metadata.contentBlockIndex;\n }\n return undefined;\n }\n\n private removeContentBlockIndex(obj: unknown): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => this.removeContentBlockIndex(item));\n }\n\n if (typeof obj === 'object') {\n const cleaned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (key !== 'contentBlockIndex') {\n cleaned[key] = this.removeContentBlockIndex(value);\n }\n }\n return cleaned;\n }\n\n return obj;\n }\n}\n\n/** @deprecated Use IllumaBedrockConverse. Alias kept for backward compatibility with existing imports. */\nexport const CustomChatBedrockConverse = IllumaBedrockConverse;\n\nexport type { ChatBedrockConverseInput };\n"],"names":["ChatBedrockConverse","messages","convertToConverseMessages","ConverseStreamCommand","handleConverseStreamContentBlockStart","handleConverseStreamContentBlockDelta","handleConverseStreamMetadata","ChatGenerationChunk","AIMessageChunk"],"mappings":"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"}
1
+ {"version":3,"file":"index.cjs","sources":["../../../../src/llm/bedrock/index.ts"],"sourcesContent":["/**\n * Optimized ChatBedrockConverse wrapper that fixes content block merging for\n * streaming responses and adds support for latest @langchain/aws features:\n *\n * - Prompt caching support for Bedrock Converse API (Illuma feature)\n * - Application Inference Profiles (PR #9129)\n * - Service Tiers (Priority/Standard/Flex) (PR #9785) - requires AWS SDK 3.966.0+\n *\n * Bedrock's `@langchain/aws` library does not include an `index` property on content\n * blocks (unlike Anthropic/OpenAI), which causes LangChain's `_mergeLists` to append\n * each streaming chunk as a separate array entry instead of merging by index.\n *\n * This wrapper takes full ownership of the stream by directly interfacing with the\n * AWS SDK client (`this.client`) and using custom handlers from `./utils/` that\n * include `contentBlockIndex` in response_metadata for every delta type. It then\n * promotes `contentBlockIndex` to an `index` property on each content block\n * (mirroring Anthropic's pattern) and strips it from metadata to avoid\n * `_mergeDicts` conflicts.\n *\n * When multiple content block types are present (e.g. reasoning + text), text deltas\n * are promoted from strings to array form with `index` so they merge correctly once\n * the accumulated content is already an array.\n *\n * PROMPT CACHING:\n * When promptCache: true is set, this wrapper adds cachePoint markers to the tools array\n * to enable Bedrock prompt caching for tool definitions. This allows tool schemas to be\n * cached and reused across requests, reducing latency and costs.\n *\n * CACHE TOKEN EXTRACTION:\n * Cache token extraction is handled in `./utils/message_outputs.ts` and added\n * to usage_metadata with input_token_details (cacheReadInputTokens/cacheWriteInputTokens).\n */\n\nimport { ChatBedrockConverse } from '@langchain/aws';\nimport { ConverseStreamCommand } from '@aws-sdk/client-bedrock-runtime';\nimport { AIMessageChunk } from '@langchain/core/messages';\nimport type { BaseMessage } from '@langchain/core/messages';\nimport { ChatGenerationChunk, ChatResult } from '@langchain/core/outputs';\nimport type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';\nimport type { ChatBedrockConverseInput } from '@langchain/aws';\nimport {\n convertToConverseMessages,\n handleConverseStreamContentBlockStart,\n handleConverseStreamContentBlockDelta,\n handleConverseStreamMetadata,\n} from './utils';\n\n/**\n * Service tier type for Bedrock invocations.\n * Requires AWS SDK >= 3.966.0 to actually work.\n * @see https://docs.aws.amazon.com/bedrock/latest/userguide/service-tiers-inference.html\n */\nexport type ServiceTierType = 'priority' | 'default' | 'flex' | 'reserved';\n\n/**\n * Extended input interface with additional features:\n * - promptCache: Enable Bedrock prompt caching for tool definitions\n * - applicationInferenceProfile: Use an inference profile ARN instead of model ID\n * - serviceTier: Specify service tier (Priority, Standard, Flex, Reserved)\n */\nexport interface IllumaBedrockConverseInput extends ChatBedrockConverseInput {\n /**\n * Enable Bedrock prompt caching for tool definitions.\n * When true, adds cachePoint markers to tools array.\n */\n promptCache?: boolean;\n\n /**\n * Application Inference Profile ARN to use for the model.\n * For example, \"arn:aws:bedrock:eu-west-1:123456789102:application-inference-profile/fm16bt65tzgx\"\n * When provided, this ARN will be used for the actual inference calls instead of the model ID.\n * Must still provide `model` as normal modelId to benefit from all the metadata.\n * @see https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-create.html\n */\n applicationInferenceProfile?: string;\n\n /**\n * Service tier for model invocation.\n * Specifies the processing tier type used for serving the request.\n * Supported values are 'priority', 'default', 'flex', and 'reserved'.\n *\n * - 'priority': Prioritized processing for lower latency\n * - 'default': Standard processing tier\n * - 'flex': Flexible processing tier with lower cost\n * - 'reserved': Reserved capacity for consistent performance\n *\n * If not provided, AWS uses the default tier.\n * Note: Requires AWS SDK >= 3.966.0 to work.\n * @see https://docs.aws.amazon.com/bedrock/latest/userguide/service-tiers-inference.html\n */\n serviceTier?: ServiceTierType;\n}\n\n/**\n * Extended call options with serviceTier override support.\n */\nexport interface IllumaBedrockConverseCallOptions {\n serviceTier?: ServiceTierType;\n}\n\nexport class IllumaBedrockConverse extends ChatBedrockConverse {\n /** Enable Bedrock prompt caching for tool definitions */\n promptCache: boolean;\n\n /** Application Inference Profile ARN to use instead of model ID */\n applicationInferenceProfile?: string;\n\n /** Service tier for model invocation */\n serviceTier?: ServiceTierType;\n\n constructor(fields?: IllumaBedrockConverseInput) {\n super(fields);\n this.promptCache = fields?.promptCache ?? false;\n this.applicationInferenceProfile = fields?.applicationInferenceProfile;\n this.serviceTier = fields?.serviceTier;\n\n // Fix: Force supportsToolChoiceValues for Claude models\n // The parent constructor checks `model.includes('claude-3')` but this fails when:\n // 1. Using applicationInferenceProfile ARNs (arn:aws:bedrock:...)\n // 2. Using different naming conventions (claude-4, claude-opus-4, etc.)\n // We need to ensure tool_choice is properly set for withStructuredOutput to work\n const modelName = (fields?.model ?? '').toLowerCase();\n const profileName = (\n fields?.applicationInferenceProfile ?? ''\n ).toLowerCase();\n const isClaudeModel =\n modelName.includes('claude') ||\n modelName.includes('anthropic') ||\n profileName.includes('claude') ||\n profileName.includes('anthropic');\n\n if (isClaudeModel && !this.supportsToolChoiceValues?.length) {\n // Claude models support all tool choice values\n this.supportsToolChoiceValues = ['auto', 'any', 'tool'];\n }\n }\n\n static lc_name(): string {\n return 'IllumaBedrockConverse';\n }\n\n /**\n * Get the model ID to use for API calls.\n * Returns applicationInferenceProfile if set, otherwise returns this.model.\n */\n protected getModelId(): string {\n return this.applicationInferenceProfile ?? this.model;\n }\n\n /**\n * Override invocationParams to:\n * 1. Add cachePoint to tools when promptCache is enabled\n * 2. Add serviceTier support\n *\n * CACHING STRATEGY: Separate cachePoints for core tools and MCP tools\n * - Core tools (web_search, execute_code, etc.) are stable → cache first\n * - MCP tools (have '_mcp_' in name) are dynamic → cache separately after\n * - This allows core tools to stay cached when MCP selection changes\n *\n * NOTE: Only Claude models support cachePoint - Nova and other models will reject it.\n */\n override invocationParams(\n options?: this['ParsedCallOptions'] & IllumaBedrockConverseCallOptions\n ): ReturnType<ChatBedrockConverse['invocationParams']> & {\n serviceTier?: { type: ServiceTierType };\n } {\n const params = super.invocationParams(options);\n\n // Add cachePoint to tools array if promptCache is enabled and tools exist\n /**\n * Bedrock requires all toolSpec.description fields to be non-empty strings.\n * Some tools (e.g., MCP-sourced or dynamically created) may have empty or\n * missing descriptions. Patch them here to avoid Bedrock validation errors.\n */\n if (\n params.toolConfig?.tools &&\n Array.isArray(params.toolConfig.tools)\n ) {\n for (const t of params.toolConfig.tools) {\n const spec = (t as { toolSpec?: { description?: string } }).toolSpec;\n if (spec && (!spec.description || spec.description === '')) {\n spec.description = spec.description || `Tool: ${(spec as { name?: string }).name ?? 'unknown'}`;\n }\n }\n }\n\n // Only Claude models support cachePoint - check model name\n const modelId = this.model.toLowerCase();\n const isClaudeModel =\n modelId.includes('claude') || modelId.includes('anthropic');\n\n if (\n this.promptCache &&\n isClaudeModel &&\n params.toolConfig?.tools &&\n Array.isArray(params.toolConfig.tools) &&\n params.toolConfig.tools.length > 0\n ) {\n // Separate core tools from MCP tools\n // MCP tools have '_mcp_' in their name (e.g., 'search_emails_mcp_Google-Workspace')\n const coreTools: typeof params.toolConfig.tools = [];\n const mcpTools: typeof params.toolConfig.tools = [];\n\n for (const tool of params.toolConfig.tools) {\n // Check if tool has a name property with '_mcp_' pattern\n const toolName =\n (tool as { toolSpec?: { name?: string } }).toolSpec?.name ?? '';\n if (toolName.includes('_mcp_')) {\n mcpTools.push(tool);\n } else {\n coreTools.push(tool);\n }\n }\n\n // Build tools array with strategic cachePoints:\n // [CoreTool1, CoreTool2, cachePoint] + [MCPTool1, MCPTool2, cachePoint]\n const toolsWithCache: typeof params.toolConfig.tools = [];\n\n // Add core tools with cachePoint (if any)\n if (coreTools.length > 0) {\n toolsWithCache.push(...coreTools);\n toolsWithCache.push({ cachePoint: { type: 'default' } });\n }\n\n // Add MCP tools with their own cachePoint (if any)\n if (mcpTools.length > 0) {\n toolsWithCache.push(...mcpTools);\n toolsWithCache.push({ cachePoint: { type: 'default' } });\n }\n\n // If no tools at all (shouldn't happen but safety check)\n if (toolsWithCache.length === 0) {\n toolsWithCache.push({ cachePoint: { type: 'default' } });\n }\n\n params.toolConfig.tools = toolsWithCache;\n }\n\n // Add serviceTier support\n const serviceTierType = options?.serviceTier ?? this.serviceTier;\n\n return {\n ...params,\n serviceTier: serviceTierType ? { type: serviceTierType } : undefined,\n };\n }\n\n /**\n * Override _generateNonStreaming to use applicationInferenceProfile as modelId.\n * Uses the same model-swapping pattern as streaming for consistency.\n */\n override async _generateNonStreaming(\n messages: BaseMessage[],\n options: this['ParsedCallOptions'] & IllumaBedrockConverseCallOptions,\n runManager?: CallbackManagerForLLMRun\n ): Promise<ChatResult> {\n const originalModel = this.model;\n if (\n this.applicationInferenceProfile != null &&\n this.applicationInferenceProfile !== ''\n ) {\n this.model = this.applicationInferenceProfile;\n }\n\n try {\n return await super._generateNonStreaming(messages, options, runManager);\n } finally {\n this.model = originalModel;\n }\n }\n\n /**\n * Own the stream end-to-end so we have direct access to every\n * `contentBlockDelta.contentBlockIndex` from the AWS SDK.\n *\n * This replaces the parent's implementation which strips contentBlockIndex\n * from text and reasoning deltas, making it impossible to merge correctly.\n */\n override async *_streamResponseChunks(\n messages: BaseMessage[],\n options: this['ParsedCallOptions'] & IllumaBedrockConverseCallOptions,\n runManager?: CallbackManagerForLLMRun\n ): AsyncGenerator<ChatGenerationChunk> {\n const { converseMessages, converseSystem } =\n convertToConverseMessages(messages);\n const params = this.invocationParams(options);\n\n let { streamUsage } = this;\n if ((options as Record<string, unknown>).streamUsage !== undefined) {\n streamUsage = (options as Record<string, unknown>).streamUsage as boolean;\n }\n\n const modelId = this.getModelId();\n\n const command = new ConverseStreamCommand({\n modelId,\n messages: converseMessages,\n system: converseSystem,\n ...(params as Record<string, unknown>),\n });\n\n const response = await this.client.send(command, {\n abortSignal: options.signal,\n });\n\n if (!response.stream) {\n return;\n }\n\n const seenBlockIndices = new Set<number>();\n\n for await (const event of response.stream) {\n if (event.contentBlockStart != null) {\n const startChunk = handleConverseStreamContentBlockStart(\n event.contentBlockStart\n );\n if (startChunk != null) {\n const idx = event.contentBlockStart.contentBlockIndex;\n if (idx != null) {\n seenBlockIndices.add(idx);\n }\n yield this.enrichChunk(startChunk, seenBlockIndices);\n }\n } else if (event.contentBlockDelta != null) {\n const deltaChunk = handleConverseStreamContentBlockDelta(\n event.contentBlockDelta\n );\n\n const idx = event.contentBlockDelta.contentBlockIndex;\n if (idx != null) {\n seenBlockIndices.add(idx);\n }\n\n yield this.enrichChunk(deltaChunk, seenBlockIndices);\n\n await runManager?.handleLLMNewToken(\n deltaChunk.text,\n undefined,\n undefined,\n undefined,\n undefined,\n { chunk: deltaChunk }\n );\n } else if (event.metadata != null) {\n yield handleConverseStreamMetadata(event.metadata, { streamUsage });\n } else if (event.contentBlockStop != null) {\n const stopIdx = event.contentBlockStop.contentBlockIndex;\n if (stopIdx != null) {\n seenBlockIndices.add(stopIdx);\n }\n } else {\n yield new ChatGenerationChunk({\n text: '',\n message: new AIMessageChunk({\n content: '',\n response_metadata: event,\n }),\n });\n }\n }\n }\n\n /**\n * Inject `index` on content blocks for proper merge behaviour, then strip\n * `contentBlockIndex` from response_metadata to prevent `_mergeDicts` conflicts.\n *\n * Text string content is promoted to array form only when the stream contains\n * multiple content block indices (e.g. reasoning at index 0, text at index 1),\n * ensuring text merges correctly with the already-array accumulated content.\n */\n enrichChunk(\n chunk: ChatGenerationChunk,\n seenBlockIndices: Set<number>\n ): ChatGenerationChunk {\n const message = chunk.message;\n if (!(message instanceof AIMessageChunk)) {\n return chunk;\n }\n\n const metadata = message.response_metadata as Record<string, unknown>;\n const blockIndex = this.extractContentBlockIndex(metadata);\n const hasMetadataIndex = blockIndex != null;\n\n let content: AIMessageChunk['content'] = message.content;\n let contentModified = false;\n\n if (Array.isArray(content) && blockIndex != null) {\n content = content.map((block) =>\n typeof block === 'object' && !('index' in block)\n ? { ...block, index: blockIndex }\n : block\n );\n contentModified = true;\n } else if (\n typeof content === 'string' &&\n content !== '' &&\n blockIndex != null &&\n seenBlockIndices.size > 1\n ) {\n content = [{ type: 'text', text: content, index: blockIndex }];\n contentModified = true;\n }\n\n if (!contentModified && !hasMetadataIndex) {\n return chunk;\n }\n\n const cleanedMetadata = hasMetadataIndex\n ? (this.removeContentBlockIndex(metadata) as Record<string, unknown>)\n : metadata;\n\n return new ChatGenerationChunk({\n text: chunk.text,\n message: new AIMessageChunk({\n ...message,\n content,\n response_metadata: cleanedMetadata,\n }),\n generationInfo: chunk.generationInfo,\n });\n }\n\n /**\n * Extract `contentBlockIndex` from the top level of response_metadata.\n * Our custom handlers always place it at the top level.\n */\n private extractContentBlockIndex(\n metadata: Record<string, unknown>\n ): number | undefined {\n if (\n 'contentBlockIndex' in metadata &&\n typeof metadata.contentBlockIndex === 'number'\n ) {\n return metadata.contentBlockIndex;\n }\n return undefined;\n }\n\n private removeContentBlockIndex(obj: unknown): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => this.removeContentBlockIndex(item));\n }\n\n if (typeof obj === 'object') {\n const cleaned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (key !== 'contentBlockIndex') {\n cleaned[key] = this.removeContentBlockIndex(value);\n }\n }\n return cleaned;\n }\n\n return obj;\n }\n}\n\n/** @deprecated Use IllumaBedrockConverse. Alias kept for backward compatibility with existing imports. */\nexport const CustomChatBedrockConverse = IllumaBedrockConverse;\n\nexport type { ChatBedrockConverseInput };\n"],"names":["ChatBedrockConverse","messages","convertToConverseMessages","ConverseStreamCommand","handleConverseStreamContentBlockStart","handleConverseStreamContentBlockDelta","handleConverseStreamMetadata","ChatGenerationChunk","AIMessageChunk"],"mappings":"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"}
@@ -90,6 +90,20 @@ class IllumaBedrockConverse extends ChatBedrockConverse {
90
90
  invocationParams(options) {
91
91
  const params = super.invocationParams(options);
92
92
  // Add cachePoint to tools array if promptCache is enabled and tools exist
93
+ /**
94
+ * Bedrock requires all toolSpec.description fields to be non-empty strings.
95
+ * Some tools (e.g., MCP-sourced or dynamically created) may have empty or
96
+ * missing descriptions. Patch them here to avoid Bedrock validation errors.
97
+ */
98
+ if (params.toolConfig?.tools &&
99
+ Array.isArray(params.toolConfig.tools)) {
100
+ for (const t of params.toolConfig.tools) {
101
+ const spec = t.toolSpec;
102
+ if (spec && (!spec.description || spec.description === '')) {
103
+ spec.description = spec.description || `Tool: ${spec.name ?? 'unknown'}`;
104
+ }
105
+ }
106
+ }
93
107
  // Only Claude models support cachePoint - check model name
94
108
  const modelId = this.model.toLowerCase();
95
109
  const isClaudeModel = modelId.includes('claude') || modelId.includes('anthropic');
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","sources":["../../../../src/llm/bedrock/index.ts"],"sourcesContent":["/**\n * Optimized ChatBedrockConverse wrapper that fixes content block merging for\n * streaming responses and adds support for latest @langchain/aws features:\n *\n * - Prompt caching support for Bedrock Converse API (Illuma feature)\n * - Application Inference Profiles (PR #9129)\n * - Service Tiers (Priority/Standard/Flex) (PR #9785) - requires AWS SDK 3.966.0+\n *\n * Bedrock's `@langchain/aws` library does not include an `index` property on content\n * blocks (unlike Anthropic/OpenAI), which causes LangChain's `_mergeLists` to append\n * each streaming chunk as a separate array entry instead of merging by index.\n *\n * This wrapper takes full ownership of the stream by directly interfacing with the\n * AWS SDK client (`this.client`) and using custom handlers from `./utils/` that\n * include `contentBlockIndex` in response_metadata for every delta type. It then\n * promotes `contentBlockIndex` to an `index` property on each content block\n * (mirroring Anthropic's pattern) and strips it from metadata to avoid\n * `_mergeDicts` conflicts.\n *\n * When multiple content block types are present (e.g. reasoning + text), text deltas\n * are promoted from strings to array form with `index` so they merge correctly once\n * the accumulated content is already an array.\n *\n * PROMPT CACHING:\n * When promptCache: true is set, this wrapper adds cachePoint markers to the tools array\n * to enable Bedrock prompt caching for tool definitions. This allows tool schemas to be\n * cached and reused across requests, reducing latency and costs.\n *\n * CACHE TOKEN EXTRACTION:\n * Cache token extraction is handled in `./utils/message_outputs.ts` and added\n * to usage_metadata with input_token_details (cacheReadInputTokens/cacheWriteInputTokens).\n */\n\nimport { ChatBedrockConverse } from '@langchain/aws';\nimport { ConverseStreamCommand } from '@aws-sdk/client-bedrock-runtime';\nimport { AIMessageChunk } from '@langchain/core/messages';\nimport type { BaseMessage } from '@langchain/core/messages';\nimport { ChatGenerationChunk, ChatResult } from '@langchain/core/outputs';\nimport type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';\nimport type { ChatBedrockConverseInput } from '@langchain/aws';\nimport {\n convertToConverseMessages,\n handleConverseStreamContentBlockStart,\n handleConverseStreamContentBlockDelta,\n handleConverseStreamMetadata,\n} from './utils';\n\n/**\n * Service tier type for Bedrock invocations.\n * Requires AWS SDK >= 3.966.0 to actually work.\n * @see https://docs.aws.amazon.com/bedrock/latest/userguide/service-tiers-inference.html\n */\nexport type ServiceTierType = 'priority' | 'default' | 'flex' | 'reserved';\n\n/**\n * Extended input interface with additional features:\n * - promptCache: Enable Bedrock prompt caching for tool definitions\n * - applicationInferenceProfile: Use an inference profile ARN instead of model ID\n * - serviceTier: Specify service tier (Priority, Standard, Flex, Reserved)\n */\nexport interface IllumaBedrockConverseInput extends ChatBedrockConverseInput {\n /**\n * Enable Bedrock prompt caching for tool definitions.\n * When true, adds cachePoint markers to tools array.\n */\n promptCache?: boolean;\n\n /**\n * Application Inference Profile ARN to use for the model.\n * For example, \"arn:aws:bedrock:eu-west-1:123456789102:application-inference-profile/fm16bt65tzgx\"\n * When provided, this ARN will be used for the actual inference calls instead of the model ID.\n * Must still provide `model` as normal modelId to benefit from all the metadata.\n * @see https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-create.html\n */\n applicationInferenceProfile?: string;\n\n /**\n * Service tier for model invocation.\n * Specifies the processing tier type used for serving the request.\n * Supported values are 'priority', 'default', 'flex', and 'reserved'.\n *\n * - 'priority': Prioritized processing for lower latency\n * - 'default': Standard processing tier\n * - 'flex': Flexible processing tier with lower cost\n * - 'reserved': Reserved capacity for consistent performance\n *\n * If not provided, AWS uses the default tier.\n * Note: Requires AWS SDK >= 3.966.0 to work.\n * @see https://docs.aws.amazon.com/bedrock/latest/userguide/service-tiers-inference.html\n */\n serviceTier?: ServiceTierType;\n}\n\n/**\n * Extended call options with serviceTier override support.\n */\nexport interface IllumaBedrockConverseCallOptions {\n serviceTier?: ServiceTierType;\n}\n\nexport class IllumaBedrockConverse extends ChatBedrockConverse {\n /** Enable Bedrock prompt caching for tool definitions */\n promptCache: boolean;\n\n /** Application Inference Profile ARN to use instead of model ID */\n applicationInferenceProfile?: string;\n\n /** Service tier for model invocation */\n serviceTier?: ServiceTierType;\n\n constructor(fields?: IllumaBedrockConverseInput) {\n super(fields);\n this.promptCache = fields?.promptCache ?? false;\n this.applicationInferenceProfile = fields?.applicationInferenceProfile;\n this.serviceTier = fields?.serviceTier;\n\n // Fix: Force supportsToolChoiceValues for Claude models\n // The parent constructor checks `model.includes('claude-3')` but this fails when:\n // 1. Using applicationInferenceProfile ARNs (arn:aws:bedrock:...)\n // 2. Using different naming conventions (claude-4, claude-opus-4, etc.)\n // We need to ensure tool_choice is properly set for withStructuredOutput to work\n const modelName = (fields?.model ?? '').toLowerCase();\n const profileName = (\n fields?.applicationInferenceProfile ?? ''\n ).toLowerCase();\n const isClaudeModel =\n modelName.includes('claude') ||\n modelName.includes('anthropic') ||\n profileName.includes('claude') ||\n profileName.includes('anthropic');\n\n if (isClaudeModel && !this.supportsToolChoiceValues?.length) {\n // Claude models support all tool choice values\n this.supportsToolChoiceValues = ['auto', 'any', 'tool'];\n }\n }\n\n static lc_name(): string {\n return 'IllumaBedrockConverse';\n }\n\n /**\n * Get the model ID to use for API calls.\n * Returns applicationInferenceProfile if set, otherwise returns this.model.\n */\n protected getModelId(): string {\n return this.applicationInferenceProfile ?? this.model;\n }\n\n /**\n * Override invocationParams to:\n * 1. Add cachePoint to tools when promptCache is enabled\n * 2. Add serviceTier support\n *\n * CACHING STRATEGY: Separate cachePoints for core tools and MCP tools\n * - Core tools (web_search, execute_code, etc.) are stable → cache first\n * - MCP tools (have '_mcp_' in name) are dynamic → cache separately after\n * - This allows core tools to stay cached when MCP selection changes\n *\n * NOTE: Only Claude models support cachePoint - Nova and other models will reject it.\n */\n override invocationParams(\n options?: this['ParsedCallOptions'] & IllumaBedrockConverseCallOptions\n ): ReturnType<ChatBedrockConverse['invocationParams']> & {\n serviceTier?: { type: ServiceTierType };\n } {\n const params = super.invocationParams(options);\n\n // Add cachePoint to tools array if promptCache is enabled and tools exist\n // Only Claude models support cachePoint - check model name\n const modelId = this.model.toLowerCase();\n const isClaudeModel =\n modelId.includes('claude') || modelId.includes('anthropic');\n\n if (\n this.promptCache &&\n isClaudeModel &&\n params.toolConfig?.tools &&\n Array.isArray(params.toolConfig.tools) &&\n params.toolConfig.tools.length > 0\n ) {\n // Separate core tools from MCP tools\n // MCP tools have '_mcp_' in their name (e.g., 'search_emails_mcp_Google-Workspace')\n const coreTools: typeof params.toolConfig.tools = [];\n const mcpTools: typeof params.toolConfig.tools = [];\n\n for (const tool of params.toolConfig.tools) {\n // Check if tool has a name property with '_mcp_' pattern\n const toolName =\n (tool as { toolSpec?: { name?: string } }).toolSpec?.name ?? '';\n if (toolName.includes('_mcp_')) {\n mcpTools.push(tool);\n } else {\n coreTools.push(tool);\n }\n }\n\n // Build tools array with strategic cachePoints:\n // [CoreTool1, CoreTool2, cachePoint] + [MCPTool1, MCPTool2, cachePoint]\n const toolsWithCache: typeof params.toolConfig.tools = [];\n\n // Add core tools with cachePoint (if any)\n if (coreTools.length > 0) {\n toolsWithCache.push(...coreTools);\n toolsWithCache.push({ cachePoint: { type: 'default' } });\n }\n\n // Add MCP tools with their own cachePoint (if any)\n if (mcpTools.length > 0) {\n toolsWithCache.push(...mcpTools);\n toolsWithCache.push({ cachePoint: { type: 'default' } });\n }\n\n // If no tools at all (shouldn't happen but safety check)\n if (toolsWithCache.length === 0) {\n toolsWithCache.push({ cachePoint: { type: 'default' } });\n }\n\n params.toolConfig.tools = toolsWithCache;\n }\n\n // Add serviceTier support\n const serviceTierType = options?.serviceTier ?? this.serviceTier;\n\n return {\n ...params,\n serviceTier: serviceTierType ? { type: serviceTierType } : undefined,\n };\n }\n\n /**\n * Override _generateNonStreaming to use applicationInferenceProfile as modelId.\n * Uses the same model-swapping pattern as streaming for consistency.\n */\n override async _generateNonStreaming(\n messages: BaseMessage[],\n options: this['ParsedCallOptions'] & IllumaBedrockConverseCallOptions,\n runManager?: CallbackManagerForLLMRun\n ): Promise<ChatResult> {\n const originalModel = this.model;\n if (\n this.applicationInferenceProfile != null &&\n this.applicationInferenceProfile !== ''\n ) {\n this.model = this.applicationInferenceProfile;\n }\n\n try {\n return await super._generateNonStreaming(messages, options, runManager);\n } finally {\n this.model = originalModel;\n }\n }\n\n /**\n * Own the stream end-to-end so we have direct access to every\n * `contentBlockDelta.contentBlockIndex` from the AWS SDK.\n *\n * This replaces the parent's implementation which strips contentBlockIndex\n * from text and reasoning deltas, making it impossible to merge correctly.\n */\n override async *_streamResponseChunks(\n messages: BaseMessage[],\n options: this['ParsedCallOptions'] & IllumaBedrockConverseCallOptions,\n runManager?: CallbackManagerForLLMRun\n ): AsyncGenerator<ChatGenerationChunk> {\n const { converseMessages, converseSystem } =\n convertToConverseMessages(messages);\n const params = this.invocationParams(options);\n\n let { streamUsage } = this;\n if ((options as Record<string, unknown>).streamUsage !== undefined) {\n streamUsage = (options as Record<string, unknown>).streamUsage as boolean;\n }\n\n const modelId = this.getModelId();\n\n const command = new ConverseStreamCommand({\n modelId,\n messages: converseMessages,\n system: converseSystem,\n ...(params as Record<string, unknown>),\n });\n\n const response = await this.client.send(command, {\n abortSignal: options.signal,\n });\n\n if (!response.stream) {\n return;\n }\n\n const seenBlockIndices = new Set<number>();\n\n for await (const event of response.stream) {\n if (event.contentBlockStart != null) {\n const startChunk = handleConverseStreamContentBlockStart(\n event.contentBlockStart\n );\n if (startChunk != null) {\n const idx = event.contentBlockStart.contentBlockIndex;\n if (idx != null) {\n seenBlockIndices.add(idx);\n }\n yield this.enrichChunk(startChunk, seenBlockIndices);\n }\n } else if (event.contentBlockDelta != null) {\n const deltaChunk = handleConverseStreamContentBlockDelta(\n event.contentBlockDelta\n );\n\n const idx = event.contentBlockDelta.contentBlockIndex;\n if (idx != null) {\n seenBlockIndices.add(idx);\n }\n\n yield this.enrichChunk(deltaChunk, seenBlockIndices);\n\n await runManager?.handleLLMNewToken(\n deltaChunk.text,\n undefined,\n undefined,\n undefined,\n undefined,\n { chunk: deltaChunk }\n );\n } else if (event.metadata != null) {\n yield handleConverseStreamMetadata(event.metadata, { streamUsage });\n } else if (event.contentBlockStop != null) {\n const stopIdx = event.contentBlockStop.contentBlockIndex;\n if (stopIdx != null) {\n seenBlockIndices.add(stopIdx);\n }\n } else {\n yield new ChatGenerationChunk({\n text: '',\n message: new AIMessageChunk({\n content: '',\n response_metadata: event,\n }),\n });\n }\n }\n }\n\n /**\n * Inject `index` on content blocks for proper merge behaviour, then strip\n * `contentBlockIndex` from response_metadata to prevent `_mergeDicts` conflicts.\n *\n * Text string content is promoted to array form only when the stream contains\n * multiple content block indices (e.g. reasoning at index 0, text at index 1),\n * ensuring text merges correctly with the already-array accumulated content.\n */\n enrichChunk(\n chunk: ChatGenerationChunk,\n seenBlockIndices: Set<number>\n ): ChatGenerationChunk {\n const message = chunk.message;\n if (!(message instanceof AIMessageChunk)) {\n return chunk;\n }\n\n const metadata = message.response_metadata as Record<string, unknown>;\n const blockIndex = this.extractContentBlockIndex(metadata);\n const hasMetadataIndex = blockIndex != null;\n\n let content: AIMessageChunk['content'] = message.content;\n let contentModified = false;\n\n if (Array.isArray(content) && blockIndex != null) {\n content = content.map((block) =>\n typeof block === 'object' && !('index' in block)\n ? { ...block, index: blockIndex }\n : block\n );\n contentModified = true;\n } else if (\n typeof content === 'string' &&\n content !== '' &&\n blockIndex != null &&\n seenBlockIndices.size > 1\n ) {\n content = [{ type: 'text', text: content, index: blockIndex }];\n contentModified = true;\n }\n\n if (!contentModified && !hasMetadataIndex) {\n return chunk;\n }\n\n const cleanedMetadata = hasMetadataIndex\n ? (this.removeContentBlockIndex(metadata) as Record<string, unknown>)\n : metadata;\n\n return new ChatGenerationChunk({\n text: chunk.text,\n message: new AIMessageChunk({\n ...message,\n content,\n response_metadata: cleanedMetadata,\n }),\n generationInfo: chunk.generationInfo,\n });\n }\n\n /**\n * Extract `contentBlockIndex` from the top level of response_metadata.\n * Our custom handlers always place it at the top level.\n */\n private extractContentBlockIndex(\n metadata: Record<string, unknown>\n ): number | undefined {\n if (\n 'contentBlockIndex' in metadata &&\n typeof metadata.contentBlockIndex === 'number'\n ) {\n return metadata.contentBlockIndex;\n }\n return undefined;\n }\n\n private removeContentBlockIndex(obj: unknown): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => this.removeContentBlockIndex(item));\n }\n\n if (typeof obj === 'object') {\n const cleaned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (key !== 'contentBlockIndex') {\n cleaned[key] = this.removeContentBlockIndex(value);\n }\n }\n return cleaned;\n }\n\n return obj;\n }\n}\n\n/** @deprecated Use IllumaBedrockConverse. Alias kept for backward compatibility with existing imports. */\nexport const CustomChatBedrockConverse = IllumaBedrockConverse;\n\nexport type { ChatBedrockConverseInput };\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","sources":["../../../../src/llm/bedrock/index.ts"],"sourcesContent":["/**\n * Optimized ChatBedrockConverse wrapper that fixes content block merging for\n * streaming responses and adds support for latest @langchain/aws features:\n *\n * - Prompt caching support for Bedrock Converse API (Illuma feature)\n * - Application Inference Profiles (PR #9129)\n * - Service Tiers (Priority/Standard/Flex) (PR #9785) - requires AWS SDK 3.966.0+\n *\n * Bedrock's `@langchain/aws` library does not include an `index` property on content\n * blocks (unlike Anthropic/OpenAI), which causes LangChain's `_mergeLists` to append\n * each streaming chunk as a separate array entry instead of merging by index.\n *\n * This wrapper takes full ownership of the stream by directly interfacing with the\n * AWS SDK client (`this.client`) and using custom handlers from `./utils/` that\n * include `contentBlockIndex` in response_metadata for every delta type. It then\n * promotes `contentBlockIndex` to an `index` property on each content block\n * (mirroring Anthropic's pattern) and strips it from metadata to avoid\n * `_mergeDicts` conflicts.\n *\n * When multiple content block types are present (e.g. reasoning + text), text deltas\n * are promoted from strings to array form with `index` so they merge correctly once\n * the accumulated content is already an array.\n *\n * PROMPT CACHING:\n * When promptCache: true is set, this wrapper adds cachePoint markers to the tools array\n * to enable Bedrock prompt caching for tool definitions. This allows tool schemas to be\n * cached and reused across requests, reducing latency and costs.\n *\n * CACHE TOKEN EXTRACTION:\n * Cache token extraction is handled in `./utils/message_outputs.ts` and added\n * to usage_metadata with input_token_details (cacheReadInputTokens/cacheWriteInputTokens).\n */\n\nimport { ChatBedrockConverse } from '@langchain/aws';\nimport { ConverseStreamCommand } from '@aws-sdk/client-bedrock-runtime';\nimport { AIMessageChunk } from '@langchain/core/messages';\nimport type { BaseMessage } from '@langchain/core/messages';\nimport { ChatGenerationChunk, ChatResult } from '@langchain/core/outputs';\nimport type { CallbackManagerForLLMRun } from '@langchain/core/callbacks/manager';\nimport type { ChatBedrockConverseInput } from '@langchain/aws';\nimport {\n convertToConverseMessages,\n handleConverseStreamContentBlockStart,\n handleConverseStreamContentBlockDelta,\n handleConverseStreamMetadata,\n} from './utils';\n\n/**\n * Service tier type for Bedrock invocations.\n * Requires AWS SDK >= 3.966.0 to actually work.\n * @see https://docs.aws.amazon.com/bedrock/latest/userguide/service-tiers-inference.html\n */\nexport type ServiceTierType = 'priority' | 'default' | 'flex' | 'reserved';\n\n/**\n * Extended input interface with additional features:\n * - promptCache: Enable Bedrock prompt caching for tool definitions\n * - applicationInferenceProfile: Use an inference profile ARN instead of model ID\n * - serviceTier: Specify service tier (Priority, Standard, Flex, Reserved)\n */\nexport interface IllumaBedrockConverseInput extends ChatBedrockConverseInput {\n /**\n * Enable Bedrock prompt caching for tool definitions.\n * When true, adds cachePoint markers to tools array.\n */\n promptCache?: boolean;\n\n /**\n * Application Inference Profile ARN to use for the model.\n * For example, \"arn:aws:bedrock:eu-west-1:123456789102:application-inference-profile/fm16bt65tzgx\"\n * When provided, this ARN will be used for the actual inference calls instead of the model ID.\n * Must still provide `model` as normal modelId to benefit from all the metadata.\n * @see https://docs.aws.amazon.com/bedrock/latest/userguide/inference-profiles-create.html\n */\n applicationInferenceProfile?: string;\n\n /**\n * Service tier for model invocation.\n * Specifies the processing tier type used for serving the request.\n * Supported values are 'priority', 'default', 'flex', and 'reserved'.\n *\n * - 'priority': Prioritized processing for lower latency\n * - 'default': Standard processing tier\n * - 'flex': Flexible processing tier with lower cost\n * - 'reserved': Reserved capacity for consistent performance\n *\n * If not provided, AWS uses the default tier.\n * Note: Requires AWS SDK >= 3.966.0 to work.\n * @see https://docs.aws.amazon.com/bedrock/latest/userguide/service-tiers-inference.html\n */\n serviceTier?: ServiceTierType;\n}\n\n/**\n * Extended call options with serviceTier override support.\n */\nexport interface IllumaBedrockConverseCallOptions {\n serviceTier?: ServiceTierType;\n}\n\nexport class IllumaBedrockConverse extends ChatBedrockConverse {\n /** Enable Bedrock prompt caching for tool definitions */\n promptCache: boolean;\n\n /** Application Inference Profile ARN to use instead of model ID */\n applicationInferenceProfile?: string;\n\n /** Service tier for model invocation */\n serviceTier?: ServiceTierType;\n\n constructor(fields?: IllumaBedrockConverseInput) {\n super(fields);\n this.promptCache = fields?.promptCache ?? false;\n this.applicationInferenceProfile = fields?.applicationInferenceProfile;\n this.serviceTier = fields?.serviceTier;\n\n // Fix: Force supportsToolChoiceValues for Claude models\n // The parent constructor checks `model.includes('claude-3')` but this fails when:\n // 1. Using applicationInferenceProfile ARNs (arn:aws:bedrock:...)\n // 2. Using different naming conventions (claude-4, claude-opus-4, etc.)\n // We need to ensure tool_choice is properly set for withStructuredOutput to work\n const modelName = (fields?.model ?? '').toLowerCase();\n const profileName = (\n fields?.applicationInferenceProfile ?? ''\n ).toLowerCase();\n const isClaudeModel =\n modelName.includes('claude') ||\n modelName.includes('anthropic') ||\n profileName.includes('claude') ||\n profileName.includes('anthropic');\n\n if (isClaudeModel && !this.supportsToolChoiceValues?.length) {\n // Claude models support all tool choice values\n this.supportsToolChoiceValues = ['auto', 'any', 'tool'];\n }\n }\n\n static lc_name(): string {\n return 'IllumaBedrockConverse';\n }\n\n /**\n * Get the model ID to use for API calls.\n * Returns applicationInferenceProfile if set, otherwise returns this.model.\n */\n protected getModelId(): string {\n return this.applicationInferenceProfile ?? this.model;\n }\n\n /**\n * Override invocationParams to:\n * 1. Add cachePoint to tools when promptCache is enabled\n * 2. Add serviceTier support\n *\n * CACHING STRATEGY: Separate cachePoints for core tools and MCP tools\n * - Core tools (web_search, execute_code, etc.) are stable → cache first\n * - MCP tools (have '_mcp_' in name) are dynamic → cache separately after\n * - This allows core tools to stay cached when MCP selection changes\n *\n * NOTE: Only Claude models support cachePoint - Nova and other models will reject it.\n */\n override invocationParams(\n options?: this['ParsedCallOptions'] & IllumaBedrockConverseCallOptions\n ): ReturnType<ChatBedrockConverse['invocationParams']> & {\n serviceTier?: { type: ServiceTierType };\n } {\n const params = super.invocationParams(options);\n\n // Add cachePoint to tools array if promptCache is enabled and tools exist\n /**\n * Bedrock requires all toolSpec.description fields to be non-empty strings.\n * Some tools (e.g., MCP-sourced or dynamically created) may have empty or\n * missing descriptions. Patch them here to avoid Bedrock validation errors.\n */\n if (\n params.toolConfig?.tools &&\n Array.isArray(params.toolConfig.tools)\n ) {\n for (const t of params.toolConfig.tools) {\n const spec = (t as { toolSpec?: { description?: string } }).toolSpec;\n if (spec && (!spec.description || spec.description === '')) {\n spec.description = spec.description || `Tool: ${(spec as { name?: string }).name ?? 'unknown'}`;\n }\n }\n }\n\n // Only Claude models support cachePoint - check model name\n const modelId = this.model.toLowerCase();\n const isClaudeModel =\n modelId.includes('claude') || modelId.includes('anthropic');\n\n if (\n this.promptCache &&\n isClaudeModel &&\n params.toolConfig?.tools &&\n Array.isArray(params.toolConfig.tools) &&\n params.toolConfig.tools.length > 0\n ) {\n // Separate core tools from MCP tools\n // MCP tools have '_mcp_' in their name (e.g., 'search_emails_mcp_Google-Workspace')\n const coreTools: typeof params.toolConfig.tools = [];\n const mcpTools: typeof params.toolConfig.tools = [];\n\n for (const tool of params.toolConfig.tools) {\n // Check if tool has a name property with '_mcp_' pattern\n const toolName =\n (tool as { toolSpec?: { name?: string } }).toolSpec?.name ?? '';\n if (toolName.includes('_mcp_')) {\n mcpTools.push(tool);\n } else {\n coreTools.push(tool);\n }\n }\n\n // Build tools array with strategic cachePoints:\n // [CoreTool1, CoreTool2, cachePoint] + [MCPTool1, MCPTool2, cachePoint]\n const toolsWithCache: typeof params.toolConfig.tools = [];\n\n // Add core tools with cachePoint (if any)\n if (coreTools.length > 0) {\n toolsWithCache.push(...coreTools);\n toolsWithCache.push({ cachePoint: { type: 'default' } });\n }\n\n // Add MCP tools with their own cachePoint (if any)\n if (mcpTools.length > 0) {\n toolsWithCache.push(...mcpTools);\n toolsWithCache.push({ cachePoint: { type: 'default' } });\n }\n\n // If no tools at all (shouldn't happen but safety check)\n if (toolsWithCache.length === 0) {\n toolsWithCache.push({ cachePoint: { type: 'default' } });\n }\n\n params.toolConfig.tools = toolsWithCache;\n }\n\n // Add serviceTier support\n const serviceTierType = options?.serviceTier ?? this.serviceTier;\n\n return {\n ...params,\n serviceTier: serviceTierType ? { type: serviceTierType } : undefined,\n };\n }\n\n /**\n * Override _generateNonStreaming to use applicationInferenceProfile as modelId.\n * Uses the same model-swapping pattern as streaming for consistency.\n */\n override async _generateNonStreaming(\n messages: BaseMessage[],\n options: this['ParsedCallOptions'] & IllumaBedrockConverseCallOptions,\n runManager?: CallbackManagerForLLMRun\n ): Promise<ChatResult> {\n const originalModel = this.model;\n if (\n this.applicationInferenceProfile != null &&\n this.applicationInferenceProfile !== ''\n ) {\n this.model = this.applicationInferenceProfile;\n }\n\n try {\n return await super._generateNonStreaming(messages, options, runManager);\n } finally {\n this.model = originalModel;\n }\n }\n\n /**\n * Own the stream end-to-end so we have direct access to every\n * `contentBlockDelta.contentBlockIndex` from the AWS SDK.\n *\n * This replaces the parent's implementation which strips contentBlockIndex\n * from text and reasoning deltas, making it impossible to merge correctly.\n */\n override async *_streamResponseChunks(\n messages: BaseMessage[],\n options: this['ParsedCallOptions'] & IllumaBedrockConverseCallOptions,\n runManager?: CallbackManagerForLLMRun\n ): AsyncGenerator<ChatGenerationChunk> {\n const { converseMessages, converseSystem } =\n convertToConverseMessages(messages);\n const params = this.invocationParams(options);\n\n let { streamUsage } = this;\n if ((options as Record<string, unknown>).streamUsage !== undefined) {\n streamUsage = (options as Record<string, unknown>).streamUsage as boolean;\n }\n\n const modelId = this.getModelId();\n\n const command = new ConverseStreamCommand({\n modelId,\n messages: converseMessages,\n system: converseSystem,\n ...(params as Record<string, unknown>),\n });\n\n const response = await this.client.send(command, {\n abortSignal: options.signal,\n });\n\n if (!response.stream) {\n return;\n }\n\n const seenBlockIndices = new Set<number>();\n\n for await (const event of response.stream) {\n if (event.contentBlockStart != null) {\n const startChunk = handleConverseStreamContentBlockStart(\n event.contentBlockStart\n );\n if (startChunk != null) {\n const idx = event.contentBlockStart.contentBlockIndex;\n if (idx != null) {\n seenBlockIndices.add(idx);\n }\n yield this.enrichChunk(startChunk, seenBlockIndices);\n }\n } else if (event.contentBlockDelta != null) {\n const deltaChunk = handleConverseStreamContentBlockDelta(\n event.contentBlockDelta\n );\n\n const idx = event.contentBlockDelta.contentBlockIndex;\n if (idx != null) {\n seenBlockIndices.add(idx);\n }\n\n yield this.enrichChunk(deltaChunk, seenBlockIndices);\n\n await runManager?.handleLLMNewToken(\n deltaChunk.text,\n undefined,\n undefined,\n undefined,\n undefined,\n { chunk: deltaChunk }\n );\n } else if (event.metadata != null) {\n yield handleConverseStreamMetadata(event.metadata, { streamUsage });\n } else if (event.contentBlockStop != null) {\n const stopIdx = event.contentBlockStop.contentBlockIndex;\n if (stopIdx != null) {\n seenBlockIndices.add(stopIdx);\n }\n } else {\n yield new ChatGenerationChunk({\n text: '',\n message: new AIMessageChunk({\n content: '',\n response_metadata: event,\n }),\n });\n }\n }\n }\n\n /**\n * Inject `index` on content blocks for proper merge behaviour, then strip\n * `contentBlockIndex` from response_metadata to prevent `_mergeDicts` conflicts.\n *\n * Text string content is promoted to array form only when the stream contains\n * multiple content block indices (e.g. reasoning at index 0, text at index 1),\n * ensuring text merges correctly with the already-array accumulated content.\n */\n enrichChunk(\n chunk: ChatGenerationChunk,\n seenBlockIndices: Set<number>\n ): ChatGenerationChunk {\n const message = chunk.message;\n if (!(message instanceof AIMessageChunk)) {\n return chunk;\n }\n\n const metadata = message.response_metadata as Record<string, unknown>;\n const blockIndex = this.extractContentBlockIndex(metadata);\n const hasMetadataIndex = blockIndex != null;\n\n let content: AIMessageChunk['content'] = message.content;\n let contentModified = false;\n\n if (Array.isArray(content) && blockIndex != null) {\n content = content.map((block) =>\n typeof block === 'object' && !('index' in block)\n ? { ...block, index: blockIndex }\n : block\n );\n contentModified = true;\n } else if (\n typeof content === 'string' &&\n content !== '' &&\n blockIndex != null &&\n seenBlockIndices.size > 1\n ) {\n content = [{ type: 'text', text: content, index: blockIndex }];\n contentModified = true;\n }\n\n if (!contentModified && !hasMetadataIndex) {\n return chunk;\n }\n\n const cleanedMetadata = hasMetadataIndex\n ? (this.removeContentBlockIndex(metadata) as Record<string, unknown>)\n : metadata;\n\n return new ChatGenerationChunk({\n text: chunk.text,\n message: new AIMessageChunk({\n ...message,\n content,\n response_metadata: cleanedMetadata,\n }),\n generationInfo: chunk.generationInfo,\n });\n }\n\n /**\n * Extract `contentBlockIndex` from the top level of response_metadata.\n * Our custom handlers always place it at the top level.\n */\n private extractContentBlockIndex(\n metadata: Record<string, unknown>\n ): number | undefined {\n if (\n 'contentBlockIndex' in metadata &&\n typeof metadata.contentBlockIndex === 'number'\n ) {\n return metadata.contentBlockIndex;\n }\n return undefined;\n }\n\n private removeContentBlockIndex(obj: unknown): unknown {\n if (obj === null || obj === undefined) {\n return obj;\n }\n\n if (Array.isArray(obj)) {\n return obj.map((item) => this.removeContentBlockIndex(item));\n }\n\n if (typeof obj === 'object') {\n const cleaned: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n if (key !== 'contentBlockIndex') {\n cleaned[key] = this.removeContentBlockIndex(value);\n }\n }\n return cleaned;\n }\n\n return obj;\n }\n}\n\n/** @deprecated Use IllumaBedrockConverse. Alias kept for backward compatibility with existing imports. */\nexport const CustomChatBedrockConverse = IllumaBedrockConverse;\n\nexport type { ChatBedrockConverseInput };\n"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@illuma-ai/agents",
3
- "version": "1.1.20",
3
+ "version": "1.1.21",
4
4
  "main": "./dist/cjs/main.cjs",
5
5
  "module": "./dist/esm/main.mjs",
6
6
  "types": "./dist/types/index.d.ts",
@@ -167,6 +167,23 @@ export class IllumaBedrockConverse extends ChatBedrockConverse {
167
167
  const params = super.invocationParams(options);
168
168
 
169
169
  // Add cachePoint to tools array if promptCache is enabled and tools exist
170
+ /**
171
+ * Bedrock requires all toolSpec.description fields to be non-empty strings.
172
+ * Some tools (e.g., MCP-sourced or dynamically created) may have empty or
173
+ * missing descriptions. Patch them here to avoid Bedrock validation errors.
174
+ */
175
+ if (
176
+ params.toolConfig?.tools &&
177
+ Array.isArray(params.toolConfig.tools)
178
+ ) {
179
+ for (const t of params.toolConfig.tools) {
180
+ const spec = (t as { toolSpec?: { description?: string } }).toolSpec;
181
+ if (spec && (!spec.description || spec.description === '')) {
182
+ spec.description = spec.description || `Tool: ${(spec as { name?: string }).name ?? 'unknown'}`;
183
+ }
184
+ }
185
+ }
186
+
170
187
  // Only Claude models support cachePoint - check model name
171
188
  const modelId = this.model.toLowerCase();
172
189
  const isClaudeModel =