@jerome-benoit/sap-ai-provider 4.6.9 → 4.7.1

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.
Files changed (40) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +22 -32
  3. package/dist/{chunk-EXOXZ5OU.js → chunk-4JIMBRMV.js} +44 -7
  4. package/dist/chunk-4JIMBRMV.js.map +1 -0
  5. package/dist/{chunk-4RRRJBEL.js → chunk-BZWUUBX2.js} +407 -275
  6. package/dist/chunk-BZWUUBX2.js.map +1 -0
  7. package/dist/chunk-HDOSHLV6.js +190 -0
  8. package/dist/chunk-HDOSHLV6.js.map +1 -0
  9. package/dist/chunk-OA6TJHD2.js +93 -0
  10. package/dist/chunk-OA6TJHD2.js.map +1 -0
  11. package/dist/{chunk-DYFBCE2W.js → chunk-RUCURXS7.js} +60 -6
  12. package/dist/chunk-RUCURXS7.js.map +1 -0
  13. package/dist/{chunk-F4MUYVQJ.js → chunk-XIWHF23D.js} +1919 -955
  14. package/dist/chunk-XIWHF23D.js.map +1 -0
  15. package/dist/{foundation-models-embedding-model-strategy-3MMM3QDC.js → foundation-models-embedding-model-strategy-TACUPFS2.js} +8 -4
  16. package/dist/foundation-models-embedding-model-strategy-TACUPFS2.js.map +1 -0
  17. package/dist/{foundation-models-language-model-strategy-OPGTN6DA.js → foundation-models-language-model-strategy-LLWYUGA3.js} +15 -10
  18. package/dist/foundation-models-language-model-strategy-LLWYUGA3.js.map +1 -0
  19. package/dist/index.cjs +2546 -1311
  20. package/dist/index.cjs.map +1 -1
  21. package/dist/index.d.cts +68 -66
  22. package/dist/index.d.ts +68 -66
  23. package/dist/index.js +11 -172
  24. package/dist/index.js.map +1 -1
  25. package/dist/{orchestration-embedding-model-strategy-R6G6VVU6.js → orchestration-embedding-model-strategy-RYI3HWRZ.js} +14 -4
  26. package/dist/orchestration-embedding-model-strategy-RYI3HWRZ.js.map +1 -0
  27. package/dist/{orchestration-language-model-strategy-KFW3CFRY.js → orchestration-language-model-strategy-NIUPRYDW.js} +53 -77
  28. package/dist/orchestration-language-model-strategy-NIUPRYDW.js.map +1 -0
  29. package/package.json +18 -14
  30. package/LICENSE.md +0 -187
  31. package/dist/chunk-4RRRJBEL.js.map +0 -1
  32. package/dist/chunk-DYFBCE2W.js.map +0 -1
  33. package/dist/chunk-EXOXZ5OU.js.map +0 -1
  34. package/dist/chunk-F4MUYVQJ.js.map +0 -1
  35. package/dist/chunk-NQJIUL3F.js +0 -61
  36. package/dist/chunk-NQJIUL3F.js.map +0 -1
  37. package/dist/foundation-models-embedding-model-strategy-3MMM3QDC.js.map +0 -1
  38. package/dist/foundation-models-language-model-strategy-OPGTN6DA.js.map +0 -1
  39. package/dist/orchestration-embedding-model-strategy-R6G6VVU6.js.map +0 -1
  40. package/dist/orchestration-language-model-strategy-KFW3CFRY.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/strategy-utils.ts","../src/stream-transformer.ts"],"sourcesContent":["/**\n * Shared utilities for SAP AI Core strategy implementations.\n */\nimport type {\n EmbeddingModelV3CallOptions,\n EmbeddingModelV3Embedding,\n EmbeddingModelV3Result,\n JSONArray,\n JSONObject,\n LanguageModelV3CallOptions,\n LanguageModelV3Content,\n LanguageModelV3FinishReason,\n LanguageModelV3FunctionTool,\n LanguageModelV3GenerateResult,\n LanguageModelV3Usage,\n SharedV3ProviderMetadata,\n SharedV3Warning,\n} from \"@ai-sdk/provider\";\nimport type { DeploymentIdConfig, ResourceGroupConfig } from \"@sap-ai-sdk/ai-api/internal.js\";\nimport type { ZodType } from \"zod\";\n\nimport { TooManyEmbeddingValuesForCallError } from \"@ai-sdk/provider\";\nimport { parseProviderOptions } from \"@ai-sdk/provider-utils\";\nimport { z } from \"zod\";\n\nimport type { ParsePartProviderOptions } from \"./sap-ai-provider-options.js\";\n\nimport { deepMerge } from \"./deep-merge.js\";\nimport { normalizeHeaders } from \"./sap-ai-error.js\";\nimport { getProviderName, sapAIEmbeddingProviderOptions } from \"./sap-ai-provider-options.js\";\nimport { validateModelParamsWithWarnings } from \"./sap-ai-provider-options.js\";\n\n/**\n * @internal\n */\nexport interface AISDKTool {\n description?: string;\n inputSchema?: unknown;\n name: string;\n type: string;\n}\n\n/**\n * @internal\n */\nexport type AISDKToolChoice =\n | { toolName: string; type: \"tool\" }\n | { type: \"auto\" }\n | { type: \"none\" }\n | { type: \"required\" };\n\n/**\n * Anthropic prompt-cache breakdown surfaced via `providerMetadata['sap-ai'].cacheUsage`.\n *\n * Mirrors the per-TTL ephemeral bucket shape returned by the SAP AI SDK token usage\n * payload (`prompt_tokens_details.cache_creation_token_details`).\n * @internal\n */\nexport type AnthropicCacheUsage = NonNullable<\n NonNullable<SDKTokenUsage[\"prompt_tokens_details\"]>[\"cache_creation_token_details\"]\n>;\n\n/**\n * @internal\n */\nexport interface BaseEmbeddingConfig {\n readonly maxEmbeddingsPerCall: number;\n readonly modelId: string;\n readonly provider: string;\n}\n\n/**\n * @internal\n */\nexport interface BaseModelDeploymentConfig {\n readonly deploymentConfig: DeploymentIdConfig | ResourceGroupConfig;\n readonly modelId: string;\n}\n\n/**\n * @internal\n */\nexport interface BuildModelParamsConfig {\n readonly options: LanguageModelV3CallOptions;\n readonly paramMappings: readonly ParamMapping[];\n readonly providerModelParams?: Record<string, unknown>;\n readonly settingsModelParams?: Record<string, unknown>;\n}\n\n/**\n * @internal\n */\nexport interface BuildModelParamsResult {\n readonly modelParams: Record<string, unknown>;\n readonly warnings: SharedV3Warning[];\n}\n\n/**\n * @internal\n */\nexport interface ConvertedResponseFormatResult {\n readonly responseFormat: SAPResponseFormat | undefined;\n readonly warning: SharedV3Warning | undefined;\n}\n\n/**\n * @internal\n */\nexport interface ConvertedToolsResult<T> {\n readonly tools: T[] | undefined;\n readonly warnings: SharedV3Warning[];\n}\n\n/**\n * Optional plumbing accepted by `convertToolsToSAPFormat`.\n *\n * Strategies that honour per-tool `providerOptions['sap-ai']` (e.g. orchestration\n * Anthropic `cacheControl`) supply a `parser`; Foundation Models omits it.\n * @internal\n */\nexport interface ConvertToolsOptions {\n readonly parser?: ParsePartProviderOptions;\n readonly warnings?: SharedV3Warning[];\n}\n\n/**\n * Parsed embedding provider options from AI SDK call.\n * @internal\n */\nexport interface EmbeddingProviderOptions {\n readonly modelParams?: Record<string, unknown>;\n readonly type?: EmbeddingType;\n}\n\n/**\n * @internal\n */\nexport interface EmbeddingResultConfig {\n readonly embeddings: EmbeddingModelV3Embedding[];\n readonly modelId: string;\n readonly providerName: string;\n readonly requestId?: string;\n readonly responseHeaders?: Record<string, string>;\n readonly totalTokens: number;\n readonly version: string;\n readonly warnings?: readonly SharedV3Warning[];\n}\n\n/**\n * Valid embedding types for orchestration API.\n * @internal\n */\nexport type EmbeddingType = \"document\" | \"query\" | \"text\";\n\n/**\n * @internal\n */\nexport interface ExtractedToolParameters {\n readonly parameters: SAPToolParameters;\n readonly warning?: SharedV3Warning;\n}\n\n/**\n * @internal\n */\nexport interface FunctionToolWithParameters extends LanguageModelV3FunctionTool {\n readonly parameters?: unknown;\n}\n\n/**\n * @internal\n */\nexport interface GenerateResultConfig {\n readonly modelId: string;\n readonly providerName: string;\n readonly requestBody: unknown;\n /** SAP-pipeline request id resolved by `extractResponseMetadata`. */\n readonly requestId?: string;\n readonly response: SDKResponse;\n readonly responseHeaders: Record<string, string> | undefined;\n readonly version: string;\n readonly warnings: SharedV3Warning[];\n}\n\n/**\n * Parameter mapping for AI SDK options → SAP model params.\n * @internal\n */\nexport interface ParamMapping {\n readonly camelCaseKey?: string;\n readonly optionKey?: string;\n readonly outputKey: string;\n}\n\n/**\n * Response metadata extracted from an SDK response: server-provided request id\n * and normalised HTTP headers.\n * @internal\n */\nexport interface ResponseMetadata {\n readonly headers: Record<string, string> | undefined;\n readonly requestId: string | undefined;\n}\n\n/**\n * @internal\n */\nexport type SAPResponseFormat =\n | {\n json_schema: {\n description?: string;\n name: string;\n schema: Record<string, unknown>;\n strict: boolean | null;\n };\n type: \"json_schema\";\n }\n | { type: \"json_object\" }\n | { type: \"text\" };\n\n/**\n * @internal\n */\nexport interface SAPTool<P = SAPToolParameters> {\n cache_control?: { ttl?: \"1h\" | \"5m\"; type: \"ephemeral\" };\n function: {\n description?: string;\n name: string;\n parameters?: P;\n };\n type: \"function\";\n}\n\n/**\n * @internal\n */\nexport type SAPToolChoice =\n | \"auto\"\n | \"none\"\n | \"required\"\n | { function: { name: string }; type: \"function\" };\n\n/**\n * @internal\n */\nexport type SAPToolParameters = Record<string, unknown> & {\n properties: Record<string, unknown>;\n required: string[];\n type: \"object\";\n};\n\n/**\n * @internal\n */\nexport interface SDKCitation {\n end_index?: number;\n ref_id?: number;\n start_index?: number;\n title: string;\n url: string;\n}\n\n/**\n * @internal\n */\nexport interface SDKDeltaToolCall {\n function?: { arguments?: string; name?: string };\n id?: string;\n index?: number;\n}\n\n/**\n * @internal\n */\nexport interface SDKResponse {\n getCitations?(): SDKCitation[] | undefined;\n getContent(): null | string | undefined;\n getFinishReason(): null | string | undefined;\n getIntermediateFailures?(): undefined | unknown[];\n getTokenUsage(): SDKTokenUsage | undefined;\n getToolCalls(): null | SDKToolCall[] | undefined;\n rawResponse: { headers: Headers | Record<string, string> };\n /** SAP-pipeline request id resolved by `extractResponseMetadata`. */\n requestId?: string;\n responseId?: string;\n}\n\nexport {\n createInitialStreamState,\n createStreamTransformer,\n StreamIdGenerator,\n type StreamState,\n type StreamTransformerConfig,\n type ToolCallInProgress,\n} from \"./stream-transformer.js\";\n\n/**\n * @internal\n */\nexport interface SDKStreamChunk {\n _data?: unknown;\n getDeltaContent(): null | string | undefined;\n getDeltaToolCalls(): null | SDKDeltaToolCall[] | undefined;\n getFinishReason(): null | string | undefined;\n}\n\n/**\n * Token usage shape returned by SAP AI SDK responses.\n *\n * Shared by both doGenerate and doStream paths, this type captures the\n * superset of fields exposed by the Orchestration (`TokenUsage`) and\n * Foundation Models (`AzureOpenAiCompletionUsage`) SDKs.\n * @internal\n */\nexport interface SDKTokenUsage {\n completion_tokens?: number;\n completion_tokens_details?: {\n accepted_prediction_tokens?: number;\n audio_tokens?: number;\n reasoning_tokens?: number;\n rejected_prediction_tokens?: number;\n };\n prompt_tokens?: number;\n prompt_tokens_details?: {\n audio_tokens?: number;\n cache_creation_token_details?: {\n ephemeral_1h_input_tokens?: number;\n ephemeral_5m_input_tokens?: number;\n };\n cache_creation_tokens?: number;\n cached_tokens?: number;\n };\n}\n\n/**\n * @internal\n */\nexport interface SDKToolCall {\n function: { arguments: string; name: string };\n id: string;\n}\n\n/**\n * Applies parameter overrides from AI SDK options and modelParams.\n * @param modelParams - The model parameters object to modify.\n * @param options - AI SDK call options.\n * @param sapModelParams - Provider options model params.\n * @param settingsModelParams - Settings model params.\n * @param mappings - Parameter mappings for this strategy.\n * @internal\n */\nexport function applyParameterOverrides(\n modelParams: Record<string, unknown>,\n options: Record<string, unknown>,\n sapModelParams: Record<string, unknown> | undefined,\n settingsModelParams: Record<string, unknown> | undefined,\n mappings: readonly ParamMapping[],\n): void {\n for (const mapping of mappings) {\n const value =\n (mapping.optionKey ? options[mapping.optionKey] : undefined) ??\n (mapping.camelCaseKey ? sapModelParams?.[mapping.camelCaseKey] : undefined) ??\n (mapping.camelCaseKey ? settingsModelParams?.[mapping.camelCaseKey] : undefined);\n\n if (value !== undefined) {\n modelParams[mapping.outputKey] = value;\n }\n\n if (mapping.camelCaseKey && mapping.camelCaseKey !== mapping.outputKey) {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete modelParams[mapping.camelCaseKey];\n }\n }\n}\n\n/**\n * Returns the Anthropic prompt-caching slice of `providerMetadata[provider]` as a\n * spread-ready fragment.\n *\n * Returns `{ cacheUsage }` when at least one ephemeral TTL bucket is populated;\n * otherwise `{}` so callers can `...` it unconditionally.\n * @param tokenUsage - Raw token usage from the SAP SDK response.\n * @returns Spread-ready provider-metadata fragment.\n * @internal\n */\nexport function buildAnthropicCacheMetadata(tokenUsage: null | SDKTokenUsage | undefined): {\n cacheUsage?: AnthropicCacheUsage;\n} {\n const details = tokenUsage?.prompt_tokens_details?.cache_creation_token_details;\n if (\n !details ||\n ((details.ephemeral_5m_input_tokens ?? 0) === 0 &&\n (details.ephemeral_1h_input_tokens ?? 0) === 0)\n ) {\n return {};\n }\n return { cacheUsage: details };\n}\n\n/**\n * Builds an EmbeddingModelV3Result from embedding data.\n * @param config - Configuration with embeddings and metadata.\n * @returns Complete embedding result for AI SDK.\n * @internal\n */\nexport function buildEmbeddingResult(config: EmbeddingResultConfig): EmbeddingModelV3Result {\n const {\n embeddings,\n modelId,\n providerName,\n requestId,\n responseHeaders,\n totalTokens,\n version,\n warnings,\n } = config;\n\n const providerMetadata: SharedV3ProviderMetadata = {\n [providerName]: {\n model: modelId,\n ...(requestId ? { requestId } : {}),\n version,\n },\n };\n\n return {\n embeddings,\n providerMetadata,\n ...(responseHeaders ? { response: { headers: responseHeaders } } : {}),\n usage: { tokens: totalTokens },\n warnings: warnings ? [...warnings] : [],\n };\n}\n\n/**\n * Builds a LanguageModelV3GenerateResult from SDK response.\n * @param config - Configuration with response and metadata.\n * @returns Complete generate result for AI SDK.\n * @internal\n */\nexport function buildGenerateResult(config: GenerateResultConfig): LanguageModelV3GenerateResult {\n const {\n modelId,\n providerName,\n requestBody,\n requestId,\n response,\n responseHeaders,\n version,\n warnings,\n } = config;\n\n const content = extractResponseContent(response);\n\n const tokenUsage = response.getTokenUsage();\n const finishReasonRaw = response.getFinishReason();\n const finishReason = mapFinishReason(finishReasonRaw);\n\n const textContent = response.getContent();\n const toolCalls = response.getToolCalls();\n\n const rawResponseBody = {\n content: textContent,\n finishReason: finishReasonRaw,\n tokenUsage,\n toolCalls,\n };\n\n const citations = response.getCitations?.();\n if (citations?.length) {\n for (const citation of citations) {\n content.push({\n id: String(citation.ref_id ?? citation.url),\n sourceType: \"url\" as const,\n title: citation.title,\n type: \"source\" as const,\n url: citation.url,\n });\n }\n }\n\n const intermediateFailures = response.getIntermediateFailures?.();\n\n return {\n content,\n finishReason,\n providerMetadata: {\n [providerName]: {\n ...buildAnthropicCacheMetadata(tokenUsage),\n finishReason: finishReasonRaw ?? \"unknown\",\n finishReasonMapped: finishReason,\n ...(intermediateFailures?.length\n ? { intermediateFailures: sanitizeAsJSONArray(intermediateFailures) }\n : {}),\n ...(requestId ? { requestId } : {}),\n version,\n },\n },\n request: {\n body: requestBody,\n },\n response: {\n body: rawResponseBody,\n headers: responseHeaders,\n id: response.responseId,\n modelId,\n timestamp: new Date(),\n },\n usage: mapTokenUsage(tokenUsage),\n warnings,\n };\n}\n\n/**\n * Builds a ModelDeployment object for the Foundation Models API SDK.\n * @param config - The strategy configuration containing deployment info and model ID.\n * @param modelVersion - Optional model version for model-based resolution.\n * @returns A ModelDeployment object for the Foundation Models API SDK.\n * @internal\n */\nexport function buildModelDeployment(\n config: BaseModelDeploymentConfig,\n modelVersion?: string,\n): { deploymentId: string } | { modelName: string; modelVersion?: string; resourceGroup?: string } {\n const deploymentConfig = config.deploymentConfig;\n\n if (\"deploymentId\" in deploymentConfig) {\n return { deploymentId: deploymentConfig.deploymentId };\n }\n\n const resourceGroup =\n \"resourceGroup\" in deploymentConfig ? deploymentConfig.resourceGroup : undefined;\n\n return {\n modelName: config.modelId,\n ...(modelVersion && { modelVersion }),\n ...(resourceGroup && { resourceGroup }),\n };\n}\n\n/**\n * Builds and validates model parameters from multiple sources.\n * @param config - Configuration with options, mappings, and source parameters.\n * @returns The merged model parameters and validation warnings.\n * @internal\n */\nexport function buildModelParams(config: BuildModelParamsConfig): BuildModelParamsResult {\n const { options, paramMappings, providerModelParams, settingsModelParams } = config;\n const warnings: SharedV3Warning[] = [];\n\n const modelParams: Record<string, unknown> = deepMerge(\n settingsModelParams ?? {},\n providerModelParams ?? {},\n );\n\n applyParameterOverrides(\n modelParams,\n options,\n providerModelParams,\n settingsModelParams,\n paramMappings,\n );\n\n if (options.stopSequences && options.stopSequences.length > 0) {\n modelParams.stop = options.stopSequences;\n }\n\n validateModelParamsWithWarnings(\n {\n frequencyPenalty: options.frequencyPenalty,\n maxTokens: options.maxOutputTokens,\n presencePenalty: options.presencePenalty,\n temperature: options.temperature,\n topP: options.topP,\n },\n warnings,\n );\n\n return { modelParams, warnings };\n}\n\n/**\n * Builds SAP AI SDK-compatible tool parameters from a JSON schema.\n * @param schema - The JSON schema to convert.\n * @returns The SAP-compatible tool parameters object.\n * @internal\n */\nexport function buildSAPToolParameters(schema: Record<string, unknown>): SAPToolParameters {\n const schemaType = schema.type;\n\n if (schemaType !== undefined && schemaType !== \"object\") {\n return {\n properties: {},\n required: [],\n type: \"object\",\n };\n }\n\n const properties =\n schema.properties && typeof schema.properties === \"object\"\n ? (schema.properties as Record<string, unknown>)\n : {};\n\n const required =\n Array.isArray(schema.required) && schema.required.every((item) => typeof item === \"string\")\n ? schema.required\n : [];\n\n const additionalFields = Object.fromEntries(\n Object.entries(schema).filter(\n ([key]) => key !== \"type\" && key !== \"properties\" && key !== \"required\",\n ),\n );\n\n return {\n properties,\n required,\n type: \"object\",\n ...additionalFields,\n };\n}\n\n/**\n * Computes the non-cached prompt tokens from a prompt-token total and its cache slices.\n *\n * Returns `undefined` when the total is unknown. Returns the total unchanged when no\n * cache breakdown is reported. Otherwise subtracts both cache buckets and clamps the\n * result at zero to defend against inconsistent SDK token counts where\n * `cached + cacheWrite > prompt`.\n * @param promptTokens - Total prompt tokens reported by the SDK.\n * @param cachedTokens - Tokens served from the prompt cache.\n * @param cacheWriteTokens - Tokens written to the prompt cache.\n * @returns The non-cached prompt token count, or `undefined` when unknown.\n * @internal\n */\nexport function computeNoCache(\n promptTokens: number | undefined,\n cachedTokens: number | undefined,\n cacheWriteTokens: number | undefined,\n): number | undefined {\n if (promptTokens == null) {\n return undefined;\n }\n if (cachedTokens == null && cacheWriteTokens == null) {\n return promptTokens;\n }\n return Math.max(0, promptTokens - (cachedTokens ?? 0) - (cacheWriteTokens ?? 0));\n}\n\n/**\n * Converts AI SDK response format to SAP-compatible format.\n * @param optionsResponseFormat - The AI SDK response format from call options.\n * @param settingsResponseFormat - The fallback response format from settings.\n * @returns The converted response format and any warning.\n * @internal\n */\nexport function convertResponseFormat(\n optionsResponseFormat: LanguageModelV3CallOptions[\"responseFormat\"],\n settingsResponseFormat?: unknown,\n): ConvertedResponseFormatResult {\n let responseFormat: SAPResponseFormat | undefined;\n let warning: SharedV3Warning | undefined;\n\n if (optionsResponseFormat?.type === \"json\") {\n responseFormat = optionsResponseFormat.schema\n ? {\n json_schema: {\n description: optionsResponseFormat.description,\n name: optionsResponseFormat.name ?? \"response\",\n schema: optionsResponseFormat.schema as Record<string, unknown>,\n strict: null,\n },\n type: \"json_schema\" as const,\n }\n : { type: \"json_object\" as const };\n } else if (settingsResponseFormat) {\n responseFormat = settingsResponseFormat as SAPResponseFormat;\n }\n\n if (responseFormat && responseFormat.type !== \"text\") {\n warning = {\n message:\n \"responseFormat JSON mode is forwarded to the underlying model; support and schema adherence depend on the model/deployment.\",\n type: \"other\",\n };\n }\n\n return { responseFormat, warning };\n}\n\n/**\n * Converts AI SDK tools to SAP-compatible tool format.\n * @param tools - The AI SDK tools to convert.\n * @param options - Optional per-tool parsing config.\n * @param options.parser - Reads per-tool `providerOptions['sap-ai']` and returns parsed directives, or `undefined` when none apply.\n * @param options.warnings - Sink for Zod validation issues raised while parsing.\n * @returns The converted tools and any warnings.\n * @internal\n */\nexport function convertToolsToSAPFormat<T extends SAPTool<unknown>>(\n tools: AISDKTool[] | undefined,\n options: ConvertToolsOptions = {},\n): ConvertedToolsResult<T> {\n const { parser, warnings: parserWarnings } = options;\n const warnings: SharedV3Warning[] = [];\n\n if (!tools || tools.length === 0) {\n return { tools: undefined, warnings };\n }\n\n const convertedTools = tools\n .map((tool): null | T => {\n if (tool.type === \"function\") {\n const functionTool = tool as LanguageModelV3FunctionTool;\n const { parameters, warning } = extractToolParameters(functionTool);\n if (warning) {\n warnings.push(warning);\n }\n\n const cacheControl = parser?.(functionTool.providerOptions, parserWarnings)?.cacheControl;\n\n return {\n ...(cacheControl ? { cache_control: cacheControl } : {}),\n function: {\n name: tool.name,\n parameters,\n ...(tool.description ? { description: tool.description } : {}),\n },\n type: \"function\",\n } as T;\n } else {\n warnings.push({\n details: \"Only 'function' tool type is supported.\",\n feature: `tool type for ${tool.name}`,\n type: \"unsupported\",\n });\n return null;\n }\n })\n .filter((t): t is T => t !== null);\n\n return {\n tools: convertedTools.length > 0 ? convertedTools : undefined,\n warnings,\n };\n}\n\n/**\n * Creates a summary of Vercel AI SDK request options for error context.\n * @param options - The language model call options to summarize.\n * @returns An object summarizing the request for debugging.\n * @internal\n */\nexport function createAISDKRequestBodySummary(options: LanguageModelV3CallOptions): {\n hasImageParts: boolean;\n maxOutputTokens?: number;\n promptMessages: number;\n responseFormatType?: string;\n seed?: number;\n stopSequences?: number;\n temperature?: number;\n toolChoiceType?: string;\n tools: number;\n topK?: number;\n topP?: number;\n} {\n return {\n hasImageParts: options.prompt.some(\n (message) =>\n message.role === \"user\" &&\n message.content.some((part) => part.type === \"file\" && part.mediaType.startsWith(\"image/\")),\n ),\n maxOutputTokens: options.maxOutputTokens,\n promptMessages: options.prompt.length,\n responseFormatType: options.responseFormat?.type,\n seed: options.seed,\n stopSequences: options.stopSequences?.length,\n temperature: options.temperature,\n toolChoiceType: options.toolChoice?.type,\n tools: options.tools?.length ?? 0,\n topK: options.topK,\n topP: options.topP,\n };\n}\n\n/**\n * Resolves the SDK completion identifier from an internal `_data` payload, falling back to\n * the pipeline request id reported by `getRequestId()` when the path is not present.\n *\n * Tolerates SDKs that omit `_data` entirely or expose `getRequestId()` as a non-function.\n * @param response - SDK response object exposing `_data` and optionally `getRequestId()`.\n * @param response._data - Internal SDK payload that holds the completion id under `dataPath`.\n * @param response.getRequestId - Function returning the SAP AI Core pipeline request id.\n * @param dataPath - Dotted property path traversed under `_data` (e.g. `[\"final_result\",\"id\"]`).\n * @returns The first non-empty completion id found along the path, or `undefined`.\n * @internal\n */\nexport function extractCompletionId(\n response: { _data?: unknown; getRequestId?: () => string | undefined },\n dataPath: readonly string[],\n): string | undefined {\n let cursor: unknown = response._data;\n for (const key of dataPath) {\n if (cursor !== null && typeof cursor === \"object\" && key in cursor) {\n cursor = (cursor as Record<string, unknown>)[key];\n } else {\n cursor = undefined;\n break;\n }\n }\n if (typeof cursor === \"string\" && cursor.length > 0) {\n return cursor;\n }\n const fn = response.getRequestId;\n if (typeof fn !== \"function\") {\n return undefined;\n }\n try {\n const rid = fn.call(response);\n return typeof rid === \"string\" && rid.length > 0 ? rid : undefined;\n } catch {\n return undefined;\n }\n}\n\n/**\n * Extracts content (text and tool calls) from SDK response.\n * @param response - SDK response object.\n * @returns Content array for LanguageModelV3GenerateResult.\n * @internal\n */\nexport function extractResponseContent(response: SDKResponse): LanguageModelV3Content[] {\n const content: LanguageModelV3Content[] = [];\n\n const textContent = response.getContent();\n if (textContent) {\n content.push({\n text: textContent,\n type: \"text\",\n });\n }\n\n const toolCalls = response.getToolCalls();\n if (toolCalls) {\n for (const toolCall of toolCalls) {\n content.push({\n input: toolCall.function.arguments,\n toolCallId: toolCall.id,\n toolName: toolCall.function.name,\n type: \"tool-call\",\n });\n }\n }\n\n return content;\n}\n\n/**\n * Extracts the request id and normalised headers from an SDK response.\n *\n * Resolves `requestId` from `getRequestId()` first; when absent, falls back to the\n * `x-request-id` header. Tolerates SDKs that omit `getRequestId`, expose it as a\n * non-function, or raise from the `headers` accessor. `field` selects the underlying\n * HttpResponse wrapper (`rawResponse` for foundation-models, `response` for orchestration).\n * @param response - SDK response object.\n * @param field - Property containing the underlying HttpResponse wrapper.\n * @returns Combined `{ requestId, headers }` with both fields defensively gathered.\n * @internal\n */\nexport function extractResponseMetadata(\n response: unknown,\n field: \"rawResponse\" | \"response\",\n): ResponseMetadata {\n let requestId: string | undefined;\n const fn = (response as null | { getRequestId?: unknown })?.getRequestId;\n if (typeof fn === \"function\") {\n try {\n const value = (fn as () => string | undefined).call(response);\n requestId = typeof value === \"string\" && value.length > 0 ? value : undefined;\n } catch {\n requestId = undefined;\n }\n }\n\n let rawHeaders: unknown;\n try {\n const wrapper = (response as null | Record<string, unknown>)?.[field] as\n | undefined\n | { headers?: unknown };\n rawHeaders = wrapper?.headers;\n } catch {\n rawHeaders = undefined;\n }\n const headers = rawHeaders === undefined ? undefined : normalizeHeaders(rawHeaders);\n\n if (requestId === undefined && typeof headers?.[\"x-request-id\"] === \"string\") {\n requestId = headers[\"x-request-id\"];\n }\n\n return { headers, requestId };\n}\n\n/**\n * Extracts SAP-compatible tool parameters from an AI SDK function tool.\n * @param tool - The AI SDK function tool to extract parameters from.\n * @returns The extracted parameters and optional warning.\n * @internal\n */\nexport function extractToolParameters(tool: LanguageModelV3FunctionTool): ExtractedToolParameters {\n const inputSchema = tool.inputSchema as Record<string, unknown> | undefined;\n const toolWithParams = tool as FunctionToolWithParameters;\n\n if (toolWithParams.parameters && isZodSchema(toolWithParams.parameters)) {\n try {\n const jsonSchema = z.toJSONSchema(toolWithParams.parameters);\n const schemaRecord = jsonSchema as Record<string, unknown>;\n delete schemaRecord.$schema;\n return { parameters: buildSAPToolParameters(schemaRecord) };\n } catch (error) {\n return {\n parameters: buildSAPToolParameters({}),\n warning: {\n details: `Failed to convert tool Zod schema: ${error instanceof Error ? error.message : String(error)}. Falling back to empty object schema.`,\n feature: `tool schema conversion for ${tool.name}`,\n type: \"unsupported\",\n },\n };\n }\n }\n\n if (inputSchema && hasKeys(inputSchema)) {\n const hasProperties =\n inputSchema.properties &&\n typeof inputSchema.properties === \"object\" &&\n hasKeys(inputSchema.properties);\n\n if (hasProperties) {\n return { parameters: buildSAPToolParameters(inputSchema) };\n }\n }\n\n return { parameters: buildSAPToolParameters({}) };\n}\n\n/**\n * Checks if an object has a callable parse method.\n * @param obj - The object to check for a parse method.\n * @returns True if the object has a callable parse method.\n * @internal\n */\nexport function hasCallableParse(\n obj: Record<string, unknown>,\n): obj is Record<string, unknown> & { parse: (...args: unknown[]) => unknown } {\n return typeof obj.parse === \"function\";\n}\n\n/**\n * Checks if an object has at least one own enumerable property.\n * @param obj - The object to check.\n * @returns True if the object has one or more keys.\n * @internal\n */\nexport function hasKeys(obj: object): boolean {\n return Object.keys(obj).length > 0;\n}\n\n/**\n * Type guard for Zod schema objects.\n * @param obj - The object to check.\n * @returns True if the object is a Zod schema.\n * @internal\n */\nexport function isZodSchema(obj: unknown): obj is ZodType {\n if (obj === null || typeof obj !== \"object\") {\n return false;\n }\n const record = obj as Record<string, unknown>;\n return \"_def\" in record && \"parse\" in record && hasCallableParse(record);\n}\n\n/**\n * Maps provider finish reasons to Vercel AI SDK LanguageModelV3FinishReason.\n * @param reason - The raw finish reason string from the provider.\n * @returns The unified finish reason with both raw and unified representations.\n * @internal\n */\nexport function mapFinishReason(reason: null | string | undefined): LanguageModelV3FinishReason {\n const raw = reason ?? undefined;\n\n if (!reason) {\n return { raw, unified: \"other\" };\n }\n\n switch (reason.toLowerCase()) {\n case \"content_filter\":\n case \"guardrail_intervened\":\n return { raw, unified: \"content-filter\" };\n case \"end_turn\":\n case \"eos\":\n case \"stop\":\n case \"stop_sequence\":\n return { raw, unified: \"stop\" };\n case \"error\":\n return { raw, unified: \"error\" };\n case \"function_call\":\n case \"tool_call\":\n case \"tool_calls\":\n case \"tool_use\":\n return { raw, unified: \"tool-calls\" };\n case \"length\":\n case \"max_tokens\":\n case \"max_tokens_reached\":\n return { raw, unified: \"length\" };\n default:\n return { raw, unified: \"other\" };\n }\n}\n\n/**\n * Maps SAP AI SDK token usage to Vercel AI SDK LanguageModelV3Usage.\n *\n * `usage.raw` is populated only when the SDK reports fields not represented in\n * `inputTokens` / `outputTokens` (audio or prediction-token buckets); otherwise omitted.\n * @param tokenUsage - Raw token usage from the SAP SDK response.\n * @returns Mapped usage with input/output token breakdowns.\n * @internal\n */\nexport function mapTokenUsage(tokenUsage: null | SDKTokenUsage | undefined): LanguageModelV3Usage {\n const cachedTokens = tokenUsage?.prompt_tokens_details?.cached_tokens;\n const cacheWriteTokens = tokenUsage?.prompt_tokens_details?.cache_creation_tokens;\n const reasoningTokens = tokenUsage?.completion_tokens_details?.reasoning_tokens;\n const promptTokens = tokenUsage?.prompt_tokens;\n\n const promptDetails = tokenUsage?.prompt_tokens_details;\n const completionDetails = tokenUsage?.completion_tokens_details;\n const hasUnmappedFields =\n promptDetails?.audio_tokens != null ||\n completionDetails?.audio_tokens != null ||\n completionDetails?.accepted_prediction_tokens != null ||\n completionDetails?.rejected_prediction_tokens != null;\n\n return {\n inputTokens: {\n cacheRead: cachedTokens,\n cacheWrite: cacheWriteTokens,\n noCache: computeNoCache(promptTokens, cachedTokens, cacheWriteTokens),\n total: promptTokens,\n },\n outputTokens: {\n reasoning: reasoningTokens,\n text:\n reasoningTokens != null\n ? (tokenUsage?.completion_tokens ?? 0) - reasoningTokens\n : tokenUsage?.completion_tokens,\n total: tokenUsage?.completion_tokens,\n },\n ...(hasUnmappedFields && tokenUsage ? { raw: sanitizeAsJSONObject(tokenUsage) } : {}),\n };\n}\n\n/**\n * Maps Vercel AI SDK toolChoice to SAP Foundation Models SDK tool_choice format.\n * @param toolChoice - The Vercel AI SDK tool choice.\n * @returns The SAP SDK tool_choice format, or undefined if no mapping needed.\n * @internal\n */\nexport function mapToolChoice(toolChoice: AISDKToolChoice | undefined): SAPToolChoice | undefined {\n if (!toolChoice) {\n return undefined;\n }\n\n switch (toolChoice.type) {\n case \"auto\":\n return \"auto\";\n case \"none\":\n return \"none\";\n case \"required\":\n return \"required\";\n case \"tool\":\n return {\n function: { name: toolChoice.toolName },\n type: \"function\",\n };\n default:\n return undefined;\n }\n}\n\n/**\n * Converts SAP AI SDK embedding to Vercel AI SDK format.\n * @param embedding - The embedding as number array or base64 string.\n * @returns The normalized embedding as a number array.\n * @internal\n */\nexport function normalizeEmbedding(embedding: number[] | string): EmbeddingModelV3Embedding {\n if (Array.isArray(embedding)) {\n return embedding;\n }\n const buffer = Buffer.from(embedding, \"base64\");\n const float32Array = new Float32Array(\n buffer.buffer,\n buffer.byteOffset,\n buffer.length / Float32Array.BYTES_PER_ELEMENT,\n );\n return Array.from(float32Array);\n}\n\n/**\n * Prepares embedding call by parsing provider options and validating input count.\n * @param config - Base embedding configuration.\n * @param options - Embedding model call options.\n * @returns Parsed SAP options and provider name.\n * @throws {TooManyEmbeddingValuesForCallError} When input count exceeds maximum.\n * @internal\n */\nexport async function prepareEmbeddingCall(\n config: BaseEmbeddingConfig,\n options: EmbeddingModelV3CallOptions,\n): Promise<{ embeddingOptions: EmbeddingProviderOptions | undefined; providerName: string }> {\n const { maxEmbeddingsPerCall, modelId, provider } = config;\n const { providerOptions, values } = options;\n\n const providerName = getProviderName(provider);\n const sapOptions = await parseProviderOptions({\n provider: providerName,\n providerOptions,\n schema: sapAIEmbeddingProviderOptions,\n });\n\n if (values.length > maxEmbeddingsPerCall) {\n throw new TooManyEmbeddingValuesForCallError({\n maxEmbeddingsPerCall,\n modelId,\n provider,\n values,\n });\n }\n\n return { embeddingOptions: sapOptions, providerName };\n}\n\nconst jsonReplacer = (_key: string, value: unknown): unknown =>\n typeof value === \"bigint\" ? value.toString() : value;\n\n/**\n * Coerces an array into a JSON-conformant payload suitable for `providerMetadata` values.\n *\n * Non-serialisable entries (functions, symbols, `undefined`) are dropped or replaced\n * by `null` per `JSON.stringify` defaults. Bigint values become decimal strings.\n * Returns an empty array when the entire payload cannot be serialised (e.g. circular\n * references).\n * @param value - Candidate array.\n * @returns JSON-safe array.\n * @internal\n */\nexport function sanitizeAsJSONArray(value: readonly unknown[]): JSONArray {\n try {\n return JSON.parse(JSON.stringify(value, jsonReplacer)) as JSONArray;\n } catch {\n return [];\n }\n}\n\n/**\n * Coerces an object into a JSON-conformant payload suitable for `providerMetadata` or\n * `LanguageModelV3Usage.raw`.\n *\n * Non-serialisable values are dropped per `JSON.stringify` defaults. Bigint values\n * become decimal strings. Returns an empty object when the entire payload cannot be\n * serialised.\n * @param value - Candidate object.\n * @returns JSON-safe object.\n * @internal\n */\nexport function sanitizeAsJSONObject(value: object): JSONObject {\n try {\n return JSON.parse(JSON.stringify(value, jsonReplacer)) as JSONObject;\n } catch {\n return {};\n }\n}\n","/**\n * Stream transformer for converting SAP AI SDK streaming responses\n * into Vercel AI SDK LanguageModelV3StreamPart events.\n */\nimport type {\n LanguageModelV3CallOptions,\n LanguageModelV3FinishReason,\n LanguageModelV3StreamPart,\n LanguageModelV3Usage,\n SharedV3Warning,\n} from \"@ai-sdk/provider\";\n\nimport { convertAsyncIteratorToReadableStream } from \"@ai-sdk/provider-utils\";\n\nimport type {\n SDKCitation,\n SDKDeltaToolCall,\n SDKStreamChunk,\n SDKTokenUsage,\n} from \"./strategy-utils.js\";\n\nimport {\n buildAnthropicCacheMetadata,\n createAISDKRequestBodySummary,\n mapFinishReason,\n mapTokenUsage,\n sanitizeAsJSONArray,\n} from \"./strategy-utils.js\";\n\n/**\n * @internal\n */\nexport interface StreamState {\n activeText: boolean;\n finishReason: LanguageModelV3FinishReason;\n isFirstChunk: boolean;\n usage: LanguageModelV3Usage;\n}\n\n/**\n * @internal\n */\nexport interface StreamTransformerConfig {\n readonly convertToAISDKError: (\n error: unknown,\n context: { operation: string; requestBody: unknown; url: string },\n ) => unknown;\n readonly idGenerator: StreamIdGenerator;\n readonly includeRawChunks: boolean;\n readonly modelId: string;\n readonly options: LanguageModelV3CallOptions;\n readonly providerName: string;\n /** SAP-pipeline request id resolved by `extractResponseMetadata`. */\n readonly requestId?: string;\n readonly responseId: string;\n readonly sdkStream: AsyncIterable<SDKStreamChunk>;\n readonly streamResponseGetCitations?: () => SDKCitation[] | undefined;\n readonly streamResponseGetFinishReason: () => null | string | undefined;\n readonly streamResponseGetIntermediateFailures?: () => undefined | unknown[];\n readonly streamResponseGetTokenUsage: () => null | SDKTokenUsage | undefined;\n readonly url: string;\n readonly version: string;\n readonly warnings: readonly SharedV3Warning[];\n}\n\n/**\n * @internal\n */\nexport interface ToolCallInProgress {\n arguments: string;\n didEmitCall: boolean;\n didEmitInputStart: boolean;\n id: string | undefined;\n toolName?: string;\n}\n\n/**\n * @internal\n */\nexport class StreamIdGenerator {\n /**\n * @returns A UUID string for identifying the response.\n */\n generateResponseId(): string {\n return crypto.randomUUID();\n }\n\n /**\n * @returns A UUID string for identifying a text block.\n */\n generateTextBlockId(): string {\n return crypto.randomUUID();\n }\n\n /**\n * @returns A UUID string for identifying a tool call when the API does not provide one.\n */\n generateToolCallId(): string {\n return crypto.randomUUID();\n }\n}\n\n/**\n * Creates the initial stream state for processing streaming responses.\n * @returns The initial stream state object.\n * @internal\n */\nexport function createInitialStreamState(): StreamState {\n return {\n activeText: false,\n finishReason: {\n raw: undefined,\n unified: \"other\" as const,\n },\n isFirstChunk: true,\n usage: {\n inputTokens: {\n cacheRead: undefined,\n cacheWrite: undefined,\n noCache: undefined,\n total: undefined,\n },\n outputTokens: {\n reasoning: undefined,\n text: undefined,\n total: undefined,\n },\n },\n };\n}\n\n/**\n * Creates a ReadableStream that transforms SAP AI SDK streaming responses\n * into Vercel AI SDK LanguageModelV3StreamPart events.\n * @param config - The stream transformer configuration containing all dependencies.\n * @returns A ReadableStream of LanguageModelV3StreamPart events.\n * @internal\n */\nexport function createStreamTransformer(\n config: StreamTransformerConfig,\n): ReadableStream<LanguageModelV3StreamPart> {\n const {\n convertToAISDKError,\n idGenerator,\n includeRawChunks,\n modelId,\n options,\n providerName,\n requestId,\n responseId,\n sdkStream,\n streamResponseGetCitations,\n streamResponseGetFinishReason,\n streamResponseGetIntermediateFailures,\n streamResponseGetTokenUsage,\n url,\n version,\n warnings,\n } = config;\n\n let textBlockId: null | string = null;\n const streamState = createInitialStreamState();\n const toolCallsInProgress = new Map<number, ToolCallInProgress>();\n\n /**\n * Emits tool-input-start and replays any buffered arguments as a delta.\n * @param tc - The in-progress tool call state.\n * @param controller - The transform stream controller to enqueue events into.\n */\n function emitToolInputStart(\n tc: ToolCallInProgress,\n controller: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n ): void {\n if (tc.didEmitInputStart || tc.id == null) return;\n tc.didEmitInputStart = true;\n controller.enqueue({\n id: tc.id,\n toolName: tc.toolName ?? \"\",\n type: \"tool-input-start\",\n });\n if (tc.arguments.length > 0) {\n controller.enqueue({\n delta: tc.arguments,\n id: tc.id,\n type: \"tool-input-delta\",\n });\n }\n }\n\n return convertAsyncIteratorToReadableStream(\n safeIterate(sdkStream)[Symbol.asyncIterator](),\n ).pipeThrough(\n new TransformStream<Error | SDKStreamChunk, LanguageModelV3StreamPart>({\n flush(controller) {\n const didEmitAnyToolCalls = finalizeToolCalls(\n controller,\n toolCallsInProgress,\n idGenerator,\n emitToolInputStart,\n );\n\n if (streamState.activeText && textBlockId) {\n controller.enqueue({ id: textBlockId, type: \"text-end\" });\n }\n\n const finalFinishReason = streamResponseGetFinishReason();\n if (finalFinishReason) {\n streamState.finishReason = mapFinishReason(finalFinishReason);\n } else if (didEmitAnyToolCalls) {\n streamState.finishReason = {\n raw: undefined,\n unified: \"tool-calls\",\n };\n }\n\n const finalUsage = streamResponseGetTokenUsage();\n if (finalUsage) {\n streamState.usage = mapTokenUsage(finalUsage);\n }\n\n const streamCitations = streamResponseGetCitations?.();\n if (streamCitations?.length) {\n for (const citation of streamCitations) {\n controller.enqueue({\n id: String(citation.ref_id ?? citation.url),\n sourceType: \"url\" as const,\n title: citation.title,\n type: \"source\",\n url: citation.url,\n });\n }\n }\n\n const streamIntermediateFailures = streamResponseGetIntermediateFailures?.();\n\n controller.enqueue({\n finishReason: streamState.finishReason,\n providerMetadata: {\n [providerName]: {\n ...buildAnthropicCacheMetadata(finalUsage),\n finishReason: streamState.finishReason.raw ?? \"unknown\",\n finishReasonMapped: streamState.finishReason,\n ...(streamIntermediateFailures?.length\n ? {\n intermediateFailures: sanitizeAsJSONArray(streamIntermediateFailures),\n }\n : {}),\n ...(requestId ? { requestId } : {}),\n responseId,\n version,\n },\n },\n type: \"finish\",\n usage: streamState.usage,\n });\n },\n\n start(controller) {\n controller.enqueue({\n type: \"stream-start\",\n warnings: [...warnings],\n });\n },\n\n transform(chunk, controller) {\n if (chunk instanceof Error) {\n handleStreamError(chunk, controller, convertToAISDKError, options, url);\n return;\n }\n\n if (includeRawChunks) {\n controller.enqueue({\n rawValue: (chunk as { _data?: unknown })._data ?? chunk,\n type: \"raw\",\n });\n }\n\n if (streamState.isFirstChunk) {\n streamState.isFirstChunk = false;\n controller.enqueue({\n id: responseId,\n modelId,\n timestamp: new Date(),\n type: \"response-metadata\",\n });\n }\n\n const deltaToolCalls = chunk.getDeltaToolCalls();\n if (Array.isArray(deltaToolCalls) && deltaToolCalls.length > 0) {\n streamState.finishReason = {\n raw: undefined,\n unified: \"tool-calls\",\n };\n }\n\n const deltaContent = chunk.getDeltaContent();\n if (\n typeof deltaContent === \"string\" &&\n deltaContent.length > 0 &&\n streamState.finishReason.unified !== \"tool-calls\"\n ) {\n textBlockId = handleTextDelta(\n deltaContent,\n controller,\n streamState,\n textBlockId,\n idGenerator,\n );\n }\n\n if (Array.isArray(deltaToolCalls) && deltaToolCalls.length > 0) {\n handleToolCallDeltas(deltaToolCalls, controller, toolCallsInProgress, emitToolInputStart);\n }\n\n const chunkFinishReason = chunk.getFinishReason();\n if (chunkFinishReason) {\n streamState.finishReason = mapFinishReason(chunkFinishReason);\n\n if (streamState.finishReason.unified === \"tool-calls\") {\n finalizeToolCalls(controller, toolCallsInProgress, idGenerator, emitToolInputStart);\n\n if (streamState.activeText && textBlockId) {\n controller.enqueue({ id: textBlockId, type: \"text-end\" });\n streamState.activeText = false;\n }\n }\n }\n },\n }),\n );\n}\n\n/**\n * Finalizes pending tool calls by emitting tool-input-end and tool-call events.\n * @param controller - The transform stream controller.\n * @param toolCallsInProgress - Map of in-progress tool calls.\n * @param idGenerator - ID generator for tool calls without IDs.\n * @param emitToolInputStart - Function to emit tool-input-start events.\n * @returns Whether any tool calls were finalized.\n * @internal\n */\nfunction finalizeToolCalls(\n controller: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n toolCallsInProgress: Map<number, ToolCallInProgress>,\n idGenerator: StreamIdGenerator,\n emitToolInputStart: (\n tc: ToolCallInProgress,\n ctrl: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n ) => void,\n): boolean {\n const toolCalls = Array.from(toolCallsInProgress.values());\n let didEmitAnyToolCalls = false;\n\n for (const tc of toolCalls) {\n if (tc.didEmitCall) {\n continue;\n }\n\n tc.id ??= idGenerator.generateToolCallId();\n emitToolInputStart(tc, controller);\n\n didEmitAnyToolCalls = true;\n tc.didEmitCall = true;\n controller.enqueue({ id: tc.id, type: \"tool-input-end\" });\n controller.enqueue({\n input: tc.arguments,\n toolCallId: tc.id,\n toolName: tc.toolName ?? \"\",\n type: \"tool-call\",\n });\n }\n\n return didEmitAnyToolCalls;\n}\n\n/**\n * Handles a stream error by converting it and enqueuing an error event.\n * @param error - The error from the stream iteration.\n * @param controller - The transform stream controller.\n * @param convertToAISDKError - Error conversion function.\n * @param options - Language model call options for context.\n * @param url - The request URL for error context.\n * @internal\n */\nfunction handleStreamError(\n error: Error,\n controller: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n convertToAISDKError: StreamTransformerConfig[\"convertToAISDKError\"],\n options: LanguageModelV3CallOptions,\n url: string,\n): void {\n const aiError = convertToAISDKError(error, {\n operation: \"doStream\",\n requestBody: createAISDKRequestBodySummary(options),\n url,\n });\n controller.enqueue({\n error: aiError instanceof Error ? aiError : new Error(String(aiError)),\n type: \"error\",\n });\n controller.terminate();\n}\n\n/**\n * Handles a text delta by managing text block lifecycle.\n * @param deltaContent - The text delta content.\n * @param controller - The transform stream controller.\n * @param streamState - The current stream state.\n * @param currentTextBlockId - The current text block ID (or null).\n * @param idGenerator - ID generator for new text blocks.\n * @returns The current text block ID (may be newly created).\n * @internal\n */\nfunction handleTextDelta(\n deltaContent: string,\n controller: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n streamState: StreamState,\n currentTextBlockId: null | string,\n idGenerator: StreamIdGenerator,\n): string {\n let textBlockId = currentTextBlockId;\n if (!streamState.activeText) {\n textBlockId = idGenerator.generateTextBlockId();\n controller.enqueue({ id: textBlockId, type: \"text-start\" });\n streamState.activeText = true;\n }\n if (textBlockId) {\n controller.enqueue({\n delta: deltaContent,\n id: textBlockId,\n type: \"text-delta\",\n });\n return textBlockId;\n }\n return currentTextBlockId ?? idGenerator.generateTextBlockId();\n}\n\n/**\n * Handles tool call delta chunks by assembling tool calls progressively.\n * @param deltaToolCalls - The tool call delta chunks from the stream.\n * @param controller - The transform stream controller.\n * @param toolCallsInProgress - Map of in-progress tool calls by index.\n * @param emitToolInputStart - Function to emit tool-input-start events.\n * @internal\n */\nfunction handleToolCallDeltas(\n deltaToolCalls: SDKDeltaToolCall[],\n controller: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n toolCallsInProgress: Map<number, ToolCallInProgress>,\n emitToolInputStart: (\n tc: ToolCallInProgress,\n ctrl: TransformStreamDefaultController<LanguageModelV3StreamPart>,\n ) => void,\n): void {\n for (const toolCallChunk of deltaToolCalls) {\n const index = toolCallChunk.index;\n if (typeof index !== \"number\" || !Number.isFinite(index)) {\n continue;\n }\n\n if (!toolCallsInProgress.has(index)) {\n toolCallsInProgress.set(index, {\n arguments: \"\",\n didEmitCall: false,\n didEmitInputStart: false,\n id:\n typeof toolCallChunk.id === \"string\" && toolCallChunk.id.length > 0\n ? toolCallChunk.id\n : undefined,\n toolName: toolCallChunk.function?.name,\n });\n }\n\n const tc = toolCallsInProgress.get(index);\n if (!tc) continue;\n\n if (\n typeof toolCallChunk.id === \"string\" &&\n toolCallChunk.id.length > 0 &&\n tc.id === undefined\n ) {\n tc.id = toolCallChunk.id;\n }\n\n const nextToolName = toolCallChunk.function?.name;\n if (typeof nextToolName === \"string\" && nextToolName.length > 0) {\n tc.toolName = nextToolName;\n }\n\n if (!tc.didEmitInputStart && tc.toolName != null && tc.id != null) {\n emitToolInputStart(tc, controller);\n }\n\n const argumentsDelta = toolCallChunk.function?.arguments;\n if (typeof argumentsDelta === \"string\" && argumentsDelta.length > 0) {\n tc.arguments += argumentsDelta;\n\n if (tc.didEmitInputStart && tc.id != null) {\n controller.enqueue({\n delta: argumentsDelta,\n id: tc.id,\n type: \"tool-input-delta\",\n });\n }\n }\n }\n}\n\n/**\n * Wraps an async iterable to catch iteration errors and yield them as values.\n *\n * Intentionally single-error: after yielding the first Error, this generator completes.\n * The downstream TransformStream terminates via `controller.error()` on receiving an Error,\n * so no further values would be consumed. This is a cooperative contract — the stream\n * pipeline guarantees no reads after the first error event.\n * @param iterable - The async iterable to wrap.\n * @yields {Error | T} Original values or Error instances for caught exceptions.\n * @internal\n */\nasync function* safeIterate<T>(iterable: AsyncIterable<T>): AsyncGenerator<Error | T> {\n try {\n yield* iterable;\n } catch (error) {\n yield error instanceof Error ? error : new Error(String(error));\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,190 @@
1
+ import {createRequire as __createRequire} from 'module';var require=__createRequire(import.meta.url);
2
+ import {
3
+ ApiSwitchError,
4
+ UnsupportedFeatureError,
5
+ deepMerge
6
+ } from "./chunk-XIWHF23D.js";
7
+
8
+ // src/sap-ai-validation.ts
9
+ function validateEscapeTemplatePlaceholders(api, escapeTemplatePlaceholders) {
10
+ if (api === "foundation-models" && escapeTemplatePlaceholders === true) {
11
+ throw new UnsupportedFeatureError(
12
+ ESCAPE_TEMPLATE_PLACEHOLDERS_DESCRIPTION,
13
+ "foundation-models",
14
+ "orchestration"
15
+ );
16
+ }
17
+ }
18
+ function validateFoundationModelsOnlyOptions(settings) {
19
+ if (!settings) return;
20
+ const fmSettings = settings;
21
+ for (const feature of FOUNDATION_MODELS_ONLY_FEATURE_KEYS) {
22
+ if (fmSettings[feature] !== void 0) {
23
+ throw new UnsupportedFeatureError(
24
+ FOUNDATION_MODELS_ONLY_FEATURES[feature],
25
+ "orchestration",
26
+ "foundation-models"
27
+ );
28
+ }
29
+ }
30
+ }
31
+ function validateOrchestrationOnlyEmbeddingOptions(settings) {
32
+ if (!settings) return;
33
+ for (const feature of ORCHESTRATION_ONLY_EMBEDDING_FEATURE_KEYS) {
34
+ if (settings[feature] !== void 0) {
35
+ throw new UnsupportedFeatureError(
36
+ ORCHESTRATION_ONLY_EMBEDDING_FEATURES[feature],
37
+ "foundation-models",
38
+ "orchestration"
39
+ );
40
+ }
41
+ }
42
+ }
43
+ function validateOrchestrationOnlyOptions(settings) {
44
+ if (!settings) return;
45
+ const orchSettings = settings;
46
+ for (const feature of ORCHESTRATION_ONLY_FEATURE_KEYS) {
47
+ if (orchSettings[feature] !== void 0) {
48
+ throw new UnsupportedFeatureError(
49
+ ORCHESTRATION_ONLY_FEATURES[feature],
50
+ "foundation-models",
51
+ "orchestration"
52
+ );
53
+ }
54
+ }
55
+ }
56
+ var ORCHESTRATION_ONLY_FEATURE_KEYS = [
57
+ "fallbackModuleConfigs",
58
+ "filtering",
59
+ "grounding",
60
+ "masking",
61
+ "orchestrationConfigRef",
62
+ "placeholderValues",
63
+ "promptTemplateRef",
64
+ "streamOptions",
65
+ "tools",
66
+ "translation"
67
+ ];
68
+ var ORCHESTRATION_ONLY_FEATURES = {
69
+ fallbackModuleConfigs: "Fallback module configurations (fallbackModuleConfigs)",
70
+ filtering: "Content filtering",
71
+ grounding: "Document grounding",
72
+ masking: "Data masking",
73
+ orchestrationConfigRef: "Orchestration config reference (orchestrationConfigRef)",
74
+ placeholderValues: "Placeholder values (placeholderValues)",
75
+ promptTemplateRef: "Prompt template reference (promptTemplateRef)",
76
+ streamOptions: "Stream options for post-LLM modules",
77
+ tools: "SAP-format tool definitions (use AI SDK tools instead)",
78
+ translation: "Translation"
79
+ };
80
+ var FOUNDATION_MODELS_ONLY_FEATURE_KEYS = ["dataSources"];
81
+ var FOUNDATION_MODELS_ONLY_FEATURES = {
82
+ dataSources: "Azure On Your Data (dataSources)"
83
+ };
84
+ var ORCHESTRATION_ONLY_INVOCATION_FEATURE_KEYS = [
85
+ "orchestrationConfigRef",
86
+ "placeholderValues",
87
+ "promptTemplateRef"
88
+ ];
89
+ var ORCHESTRATION_ONLY_EMBEDDING_FEATURE_KEYS = ["masking"];
90
+ var ORCHESTRATION_ONLY_EMBEDDING_FEATURES = {
91
+ masking: ORCHESTRATION_ONLY_FEATURES.masking
92
+ };
93
+ var ESCAPE_TEMPLATE_PLACEHOLDERS_DESCRIPTION = "escapeTemplatePlaceholders (Jinja2 template escaping)";
94
+ function validateApiSwitch(fromApi, toApi, modelSettings) {
95
+ if (fromApi === toApi) return;
96
+ if (!modelSettings) return;
97
+ if (fromApi === "orchestration" && toApi === "foundation-models") {
98
+ const orchSettings = modelSettings;
99
+ for (const feature of ORCHESTRATION_ONLY_FEATURE_KEYS) {
100
+ if (orchSettings[feature] !== void 0) {
101
+ throw new ApiSwitchError(fromApi, toApi, feature);
102
+ }
103
+ }
104
+ }
105
+ if (fromApi === "foundation-models" && toApi === "orchestration") {
106
+ const fmSettings = modelSettings;
107
+ for (const feature of FOUNDATION_MODELS_ONLY_FEATURE_KEYS) {
108
+ if (fmSettings[feature] !== void 0) {
109
+ throw new ApiSwitchError(fromApi, toApi, feature);
110
+ }
111
+ }
112
+ }
113
+ }
114
+ var VALID_API_TYPES = ["orchestration", "foundation-models"];
115
+ function mergeSettingsWithApi(defaultSettings, callSettings, fallbackApi) {
116
+ return {
117
+ ...deepMerge(defaultSettings, callSettings),
118
+ api: callSettings.api ?? defaultSettings?.api ?? fallbackApi
119
+ };
120
+ }
121
+ function resolveApi(providerApi, modelApi, invocationApi) {
122
+ return invocationApi ?? modelApi ?? providerApi ?? "orchestration";
123
+ }
124
+ function validateApiInput(api) {
125
+ if (api === void 0) return;
126
+ if (typeof api !== "string" || !VALID_API_TYPES.includes(api)) {
127
+ throw new Error(
128
+ `Invalid API type: ${JSON.stringify(api)}. Valid values are: ${VALID_API_TYPES.map((t) => `"${t}"`).join(", ")}`
129
+ );
130
+ }
131
+ }
132
+ function validateMaskingProvidersDeprecation(modelSettings, warnings) {
133
+ const masking = modelSettings?.masking;
134
+ if (!masking || typeof masking !== "object") {
135
+ return;
136
+ }
137
+ const maskingRecord = masking;
138
+ const hasDeprecated = maskingRecord.masking_providers !== void 0;
139
+ const hasPreferred = maskingRecord.providers !== void 0;
140
+ if (hasDeprecated && !hasPreferred) {
141
+ warnings.push({
142
+ message: "settings.masking.masking_providers is deprecated and will be removed by SAP on 2027-03-20. Migrate to settings.masking.providers.",
143
+ type: "other"
144
+ });
145
+ }
146
+ }
147
+ function validateSettings(options) {
148
+ const { api, embeddingSettings, invocationSettings, modelApi, modelSettings } = options;
149
+ validateApiInput(api);
150
+ if (invocationSettings?.api !== void 0) {
151
+ validateApiInput(invocationSettings.api);
152
+ }
153
+ if (invocationSettings?.api !== void 0) {
154
+ const effectiveModelApi = modelApi ?? "orchestration";
155
+ if (effectiveModelApi !== invocationSettings.api) {
156
+ validateApiSwitch(effectiveModelApi, invocationSettings.api, modelSettings);
157
+ }
158
+ }
159
+ if (api === "foundation-models") {
160
+ validateOrchestrationOnlyOptions(modelSettings);
161
+ validateOrchestrationOnlyInvocationOptions(invocationSettings);
162
+ validateOrchestrationOnlyEmbeddingOptions(embeddingSettings);
163
+ } else {
164
+ validateFoundationModelsOnlyOptions(modelSettings);
165
+ }
166
+ const modelEscape = modelSettings?.escapeTemplatePlaceholders;
167
+ const invocationEscape = invocationSettings?.escapeTemplatePlaceholders;
168
+ const effectiveEscape = invocationEscape ?? modelEscape;
169
+ validateEscapeTemplatePlaceholders(api, effectiveEscape);
170
+ }
171
+ function validateOrchestrationOnlyInvocationOptions(invocationSettings) {
172
+ if (!invocationSettings) return;
173
+ for (const feature of ORCHESTRATION_ONLY_INVOCATION_FEATURE_KEYS) {
174
+ if (invocationSettings[feature] !== void 0) {
175
+ throw new UnsupportedFeatureError(
176
+ ORCHESTRATION_ONLY_FEATURES[feature],
177
+ "foundation-models",
178
+ "orchestration"
179
+ );
180
+ }
181
+ }
182
+ }
183
+
184
+ export {
185
+ mergeSettingsWithApi,
186
+ resolveApi,
187
+ validateMaskingProvidersDeprecation,
188
+ validateSettings
189
+ };
190
+ //# sourceMappingURL=chunk-HDOSHLV6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sap-ai-validation.ts"],"sourcesContent":["/** Validation and resolution functions for SAP AI API-specific features. */\nimport type { SharedV3Warning } from \"@ai-sdk/provider\";\n\nimport type {\n FoundationModelsModelSettings,\n OrchestrationModelSettings,\n SAPAIApiType,\n SAPAIEmbeddingSettings,\n SAPAIModelSettings,\n SAPAISettings,\n} from \"./sap-ai-settings.js\";\n\nimport { deepMerge } from \"./deep-merge.js\";\nimport { ApiSwitchError, UnsupportedFeatureError } from \"./sap-ai-error.js\";\n\n/**\n * Type guard for Foundation Models API settings.\n * @param settings - Settings to check.\n * @returns True if settings are for Foundation Models API.\n */\nexport function isFoundationModelsSettings(\n settings: SAPAIModelSettings | SAPAISettings,\n): settings is FoundationModelsModelSettings {\n return settings.api === \"foundation-models\";\n}\n\n/**\n * Type guard for Orchestration API settings.\n * @param settings - Settings to check.\n * @returns True if settings are for Orchestration API.\n */\nexport function isOrchestrationSettings(\n settings: SAPAIModelSettings | SAPAISettings,\n): settings is OrchestrationModelSettings {\n return settings.api === undefined || settings.api === \"orchestration\";\n}\n\n/**\n * Validates escapeTemplatePlaceholders option based on API type.\n *\n * Jinja2 template escaping is only supported by the Orchestration API.\n * @param api - SAP AI API type.\n * @param escapeTemplatePlaceholders - Whether to escape template placeholders.\n * @throws {UnsupportedFeatureError} When escapeTemplatePlaceholders is true with Foundation Models API.\n * @internal\n */\nfunction validateEscapeTemplatePlaceholders(\n api: SAPAIApiType,\n escapeTemplatePlaceholders: boolean | undefined,\n): void {\n if (api === \"foundation-models\" && escapeTemplatePlaceholders === true) {\n throw new UnsupportedFeatureError(\n ESCAPE_TEMPLATE_PLACEHOLDERS_DESCRIPTION,\n \"foundation-models\",\n \"orchestration\",\n );\n }\n}\n\n/**\n * Validates that Foundation Models-only options are not used with Orchestration API.\n *\n * Foundation Models-only features:\n * - `dataSources` - Azure On Your Data configuration\n * @param settings - Settings to validate.\n * @throws {UnsupportedFeatureError} When dataSources is set with Orchestration API.\n * @internal\n */\nfunction validateFoundationModelsOnlyOptions(\n settings: SAPAIModelSettings | SAPAISettings | undefined,\n): void {\n if (!settings) return;\n\n const fmSettings = settings as FoundationModelsModelSettings;\n\n for (const feature of FOUNDATION_MODELS_ONLY_FEATURE_KEYS) {\n if (fmSettings[feature] !== undefined) {\n throw new UnsupportedFeatureError(\n FOUNDATION_MODELS_ONLY_FEATURES[feature],\n \"orchestration\",\n \"foundation-models\",\n );\n }\n }\n}\n\n/**\n * Validates that Orchestration-only embedding options are not used with Foundation Models API.\n *\n * Orchestration-only embedding features:\n * - `masking` - Data masking module\n * @param settings - Embedding settings to validate.\n * @throws {UnsupportedFeatureError} When masking is set with Foundation Models API.\n * @internal\n */\nfunction validateOrchestrationOnlyEmbeddingOptions(\n settings: SAPAIEmbeddingSettings | undefined,\n): void {\n if (!settings) return;\n\n for (const feature of ORCHESTRATION_ONLY_EMBEDDING_FEATURE_KEYS) {\n if (settings[feature] !== undefined) {\n throw new UnsupportedFeatureError(\n ORCHESTRATION_ONLY_EMBEDDING_FEATURES[feature],\n \"foundation-models\",\n \"orchestration\",\n );\n }\n }\n}\n\n/**\n * Validates that Orchestration-only options are not used with Foundation Models API.\n *\n * Orchestration-only features:\n * - `fallbackModuleConfigs` - Prompt module fallback configuration list\n * - `filtering` - Content filtering module\n * - `grounding` - Document grounding module\n * - `masking` - Data masking module\n * - `orchestrationConfigRef` - Prompt Registry configuration reference\n * - `placeholderValues` - Jinja2 template placeholder values\n * - `promptTemplateRef` - Prompt Registry template reference\n * - `tools` - SAP-format tool definitions (use AI SDK tools instead)\n * - `translation` - Translation module\n * @param settings - Settings to validate.\n * @throws {UnsupportedFeatureError} When any Orchestration-only feature is set with Foundation Models API.\n * @internal\n */\nfunction validateOrchestrationOnlyOptions(\n settings: SAPAIModelSettings | SAPAISettings | undefined,\n): void {\n if (!settings) return;\n\n const orchSettings = settings as OrchestrationModelSettings;\n\n for (const feature of ORCHESTRATION_ONLY_FEATURE_KEYS) {\n if (orchSettings[feature] !== undefined) {\n throw new UnsupportedFeatureError(\n ORCHESTRATION_ONLY_FEATURES[feature],\n \"foundation-models\",\n \"orchestration\",\n );\n }\n }\n}\n\n/**\n * Keys for Orchestration-only features.\n * @internal\n */\nconst ORCHESTRATION_ONLY_FEATURE_KEYS = [\n \"fallbackModuleConfigs\",\n \"filtering\",\n \"grounding\",\n \"masking\",\n \"orchestrationConfigRef\",\n \"placeholderValues\",\n \"promptTemplateRef\",\n \"streamOptions\",\n \"tools\",\n \"translation\",\n] as const;\n\n/**\n * Mapping of Orchestration-only feature keys to human-readable descriptions.\n * Used for generating consistent error messages.\n * @internal\n */\nconst ORCHESTRATION_ONLY_FEATURES: Readonly<\n Record<(typeof ORCHESTRATION_ONLY_FEATURE_KEYS)[number], string>\n> = {\n fallbackModuleConfigs: \"Fallback module configurations (fallbackModuleConfigs)\",\n filtering: \"Content filtering\",\n grounding: \"Document grounding\",\n masking: \"Data masking\",\n orchestrationConfigRef: \"Orchestration config reference (orchestrationConfigRef)\",\n placeholderValues: \"Placeholder values (placeholderValues)\",\n promptTemplateRef: \"Prompt template reference (promptTemplateRef)\",\n streamOptions: \"Stream options for post-LLM modules\",\n tools: \"SAP-format tool definitions (use AI SDK tools instead)\",\n translation: \"Translation\",\n} as const;\n\n/**\n * Keys for Foundation Models-only features.\n * @internal\n */\nconst FOUNDATION_MODELS_ONLY_FEATURE_KEYS = [\"dataSources\"] as const;\n\n/**\n * Mapping of Foundation Models-only feature keys to human-readable descriptions.\n * Used for generating consistent error messages.\n * @internal\n */\nconst FOUNDATION_MODELS_ONLY_FEATURES: Readonly<\n Record<(typeof FOUNDATION_MODELS_ONLY_FEATURE_KEYS)[number], string>\n> = {\n dataSources: \"Azure On Your Data (dataSources)\",\n} as const;\n\n/**\n * Subset of Orchestration-only features that can be set at invocation level.\n * @internal\n */\nconst ORCHESTRATION_ONLY_INVOCATION_FEATURE_KEYS = [\n \"orchestrationConfigRef\",\n \"placeholderValues\",\n \"promptTemplateRef\",\n] as const;\n\n/**\n * Keys for Orchestration-only embedding features.\n * @internal\n */\nconst ORCHESTRATION_ONLY_EMBEDDING_FEATURE_KEYS = [\"masking\"] as const;\n\n/**\n * Mapping of Orchestration-only embedding feature keys to human-readable descriptions.\n * Uses the same descriptions as the main ORCHESTRATION_ONLY_FEATURES for consistency.\n * @internal\n */\nconst ORCHESTRATION_ONLY_EMBEDDING_FEATURES: Readonly<\n Record<(typeof ORCHESTRATION_ONLY_EMBEDDING_FEATURE_KEYS)[number], string>\n> = {\n masking: ORCHESTRATION_ONLY_FEATURES.masking,\n} as const;\n\n/**\n * Human-readable description for escapeTemplatePlaceholders feature.\n * Used for generating consistent error messages.\n * @internal\n */\nconst ESCAPE_TEMPLATE_PLACEHOLDERS_DESCRIPTION =\n \"escapeTemplatePlaceholders (Jinja2 template escaping)\";\n\n/**\n * Validates that switching APIs at invocation time is allowed.\n *\n * API switching is blocked when the model was configured with features\n * that are specific to one API and incompatible with the target API.\n * @param fromApi - Source API type (configured at model creation).\n * @param toApi - Target API type (requested at invocation time).\n * @param modelSettings - Model settings to validate for conflicts.\n * @throws {ApiSwitchError} When the model has features incompatible with the target API.\n * @internal\n */\nfunction validateApiSwitch(\n fromApi: SAPAIApiType,\n toApi: SAPAIApiType,\n modelSettings: SAPAIModelSettings | SAPAISettings | undefined,\n): void {\n if (fromApi === toApi) return;\n if (!modelSettings) return;\n\n if (fromApi === \"orchestration\" && toApi === \"foundation-models\") {\n const orchSettings = modelSettings as OrchestrationModelSettings;\n\n for (const feature of ORCHESTRATION_ONLY_FEATURE_KEYS) {\n if (orchSettings[feature] !== undefined) {\n throw new ApiSwitchError(fromApi, toApi, feature);\n }\n }\n }\n\n if (fromApi === \"foundation-models\" && toApi === \"orchestration\") {\n const fmSettings = modelSettings as FoundationModelsModelSettings;\n\n for (const feature of FOUNDATION_MODELS_ONLY_FEATURE_KEYS) {\n if (fmSettings[feature] !== undefined) {\n throw new ApiSwitchError(fromApi, toApi, feature);\n }\n }\n }\n}\n\n/**\n * @internal\n */\nconst VALID_API_TYPES: readonly SAPAIApiType[] = [\"orchestration\", \"foundation-models\"];\n\n/** Options for the main validation function. */\nexport interface ValidateSettingsOptions {\n readonly api: SAPAIApiType;\n readonly embeddingSettings?: SAPAIEmbeddingSettings;\n readonly invocationSettings?: {\n readonly api?: SAPAIApiType;\n readonly escapeTemplatePlaceholders?: boolean;\n readonly orchestrationConfigRef?: unknown;\n readonly placeholderValues?: unknown;\n readonly promptTemplateRef?: unknown;\n };\n readonly modelApi?: SAPAIApiType;\n readonly modelSettings?: SAPAIModelSettings | SAPAISettings;\n}\n\n/**\n * Gets the effective escapeTemplatePlaceholders value based on API and settings.\n * @param api - SAP AI API type.\n * @param modelSettings - Model settings.\n * @param invocationEscape - Invocation-level escape setting.\n * @returns Effective escapeTemplatePlaceholders value.\n */\nexport function getEffectiveEscapeTemplatePlaceholders(\n api: SAPAIApiType,\n modelSettings: SAPAIModelSettings | SAPAISettings | undefined,\n invocationEscape: boolean | undefined,\n): boolean {\n if (api === \"foundation-models\") {\n return false;\n }\n\n if (invocationEscape !== undefined) {\n return invocationEscape;\n }\n\n const modelValue = (modelSettings as OrchestrationModelSettings | undefined)\n ?.escapeTemplatePlaceholders;\n if (modelValue !== undefined) {\n return modelValue;\n }\n\n return true;\n}\n\n/**\n * Merges settings with proper API precedence (callSettings > defaultSettings > fallbackApi).\n * @param defaultSettings - Provider-level default settings.\n * @param callSettings - Per-call settings that override defaults.\n * @param fallbackApi - Fallback API type when neither settings specify one.\n * @returns Merged settings with correct API precedence.\n * @internal\n */\nexport function mergeSettingsWithApi<T extends { api?: string }>(\n defaultSettings: Record<string, unknown> | undefined,\n callSettings: Partial<T>,\n fallbackApi: string,\n): T {\n return {\n ...deepMerge(defaultSettings, callSettings as Record<string, unknown>),\n api: callSettings.api ?? (defaultSettings?.api as string | undefined) ?? fallbackApi,\n } as T;\n}\n\n/**\n * Resolves the effective API type using the full precedence chain.\n * @param providerApi - Provider-level API type.\n * @param modelApi - Model-level API type.\n * @param invocationApi - Invocation-level API type.\n * @returns Resolved API type.\n */\nexport function resolveApi(\n providerApi: SAPAIApiType | undefined,\n modelApi: SAPAIApiType | undefined,\n invocationApi: SAPAIApiType | undefined,\n): SAPAIApiType {\n return invocationApi ?? modelApi ?? providerApi ?? \"orchestration\";\n}\n\n/**\n * Validates that the API value is a valid SAPAIApiType.\n * @param api - API value to validate.\n */\nexport function validateApiInput(api: unknown): void {\n if (api === undefined) return;\n\n if (typeof api !== \"string\" || !VALID_API_TYPES.includes(api as SAPAIApiType)) {\n throw new Error(\n `Invalid API type: ${JSON.stringify(api)}. ` +\n `Valid values are: ${VALID_API_TYPES.map((t) => `\"${t}\"`).join(\", \")}`,\n );\n }\n}\n\n/**\n * Pushes a deprecation warning when `settings.masking` carries `masking_providers`\n * without a `providers` block.\n * @param modelSettings - Resolved model settings (LM or embedding) that may carry a `masking` module.\n * @param warnings - Sink that collects the deprecation warning when it applies.\n * @internal\n */\nexport function validateMaskingProvidersDeprecation(\n modelSettings: undefined | { masking?: unknown },\n warnings: SharedV3Warning[],\n): void {\n const masking = modelSettings?.masking;\n if (!masking || typeof masking !== \"object\") {\n return;\n }\n const maskingRecord = masking as Record<string, unknown>;\n const hasDeprecated = maskingRecord.masking_providers !== undefined;\n const hasPreferred = maskingRecord.providers !== undefined;\n if (hasDeprecated && !hasPreferred) {\n warnings.push({\n message:\n \"settings.masking.masking_providers is deprecated and will be removed by SAP on 2027-03-20. \" +\n \"Migrate to settings.masking.providers.\",\n type: \"other\",\n });\n }\n}\n\n/**\n * Main validation function that performs all API-specific validations.\n *\n * This function orchestrates all validation checks:\n * 1. Validates API type inputs\n * 2. Checks for API switching conflicts\n * 3. Validates API-specific feature usage\n * 4. Validates template placeholder escaping\n * @param options - Validation options.\n * @throws {Error} When an invalid API type is provided.\n * @throws {ApiSwitchError} When attempting to switch APIs with incompatible settings.\n * @throws {UnsupportedFeatureError} When using features not supported by the current API.\n * @see {@link ApiSwitchError}\n * @see {@link UnsupportedFeatureError}\n */\nexport function validateSettings(options: ValidateSettingsOptions): void {\n const { api, embeddingSettings, invocationSettings, modelApi, modelSettings } = options;\n\n validateApiInput(api);\n if (invocationSettings?.api !== undefined) {\n validateApiInput(invocationSettings.api);\n }\n\n if (invocationSettings?.api !== undefined) {\n const effectiveModelApi = modelApi ?? \"orchestration\";\n if (effectiveModelApi !== invocationSettings.api) {\n validateApiSwitch(effectiveModelApi, invocationSettings.api, modelSettings);\n }\n }\n\n if (api === \"foundation-models\") {\n validateOrchestrationOnlyOptions(modelSettings);\n validateOrchestrationOnlyInvocationOptions(invocationSettings);\n validateOrchestrationOnlyEmbeddingOptions(embeddingSettings);\n } else {\n validateFoundationModelsOnlyOptions(modelSettings);\n }\n\n const modelEscape = (modelSettings as OrchestrationModelSettings | undefined)\n ?.escapeTemplatePlaceholders;\n const invocationEscape = invocationSettings?.escapeTemplatePlaceholders;\n const effectiveEscape = invocationEscape ?? modelEscape;\n validateEscapeTemplatePlaceholders(api, effectiveEscape);\n}\n\n/**\n * Validates that Orchestration-only options are not passed at invocation level with Foundation Models API.\n * @param invocationSettings - Invocation-level settings to validate.\n * @throws {UnsupportedFeatureError} When any Orchestration-only feature is set at invocation level.\n * @internal\n */\nfunction validateOrchestrationOnlyInvocationOptions(\n invocationSettings: ValidateSettingsOptions[\"invocationSettings\"],\n): void {\n if (!invocationSettings) return;\n\n for (const feature of ORCHESTRATION_ONLY_INVOCATION_FEATURE_KEYS) {\n if (invocationSettings[feature] !== undefined) {\n throw new UnsupportedFeatureError(\n ORCHESTRATION_ONLY_FEATURES[feature],\n \"foundation-models\",\n \"orchestration\",\n );\n }\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,93 @@
1
+ import {createRequire as __createRequire} from 'module';var require=__createRequire(import.meta.url);
2
+ import {
3
+ buildEmbeddingResult,
4
+ prepareEmbeddingCall
5
+ } from "./chunk-BZWUUBX2.js";
6
+ import {
7
+ VERSION,
8
+ convertToAISDKError,
9
+ deepMerge
10
+ } from "./chunk-XIWHF23D.js";
11
+
12
+ // src/base-embedding-model-strategy.ts
13
+ import { TooManyEmbeddingValuesForCallError } from "@ai-sdk/provider";
14
+ var BaseEmbeddingModelStrategy = class {
15
+ /**
16
+ * Template method implementing the shared embedding algorithm.
17
+ * @param config - Strategy configuration.
18
+ * @param settings - Embedding model settings.
19
+ * @param options - AI SDK call options.
20
+ * @param maxEmbeddingsPerCall - Maximum embeddings per call.
21
+ * @returns Complete embedding result for AI SDK.
22
+ * @internal
23
+ */
24
+ async doEmbed(config, settings, options, maxEmbeddingsPerCall) {
25
+ const { abortSignal, values } = options;
26
+ try {
27
+ const { embeddingOptions, providerName } = await prepareEmbeddingCall(
28
+ { maxEmbeddingsPerCall, modelId: config.modelId, provider: config.provider },
29
+ options
30
+ );
31
+ const embeddingType = embeddingOptions?.type ?? settings.type ?? "text";
32
+ const warnings = [];
33
+ this.resolveWarnings(settings, warnings);
34
+ const client = this.createClient(config, settings, embeddingOptions);
35
+ const response = await this.executeCall(client, values, embeddingType, abortSignal);
36
+ const embeddings = this.extractEmbeddings(response);
37
+ const totalTokens = this.extractTokenCount(response);
38
+ const { headers: responseHeaders, requestId } = this.extractResponseMetadata(response);
39
+ return buildEmbeddingResult({
40
+ embeddings,
41
+ modelId: config.modelId,
42
+ providerName,
43
+ requestId,
44
+ responseHeaders,
45
+ totalTokens,
46
+ version: VERSION,
47
+ warnings
48
+ });
49
+ } catch (error) {
50
+ if (error instanceof TooManyEmbeddingValuesForCallError) {
51
+ throw error;
52
+ }
53
+ throw convertToAISDKError(error, {
54
+ operation: "doEmbed",
55
+ requestBody: { values: values.length },
56
+ url: this.getUrl()
57
+ });
58
+ }
59
+ }
60
+ /**
61
+ * Extracts response metadata (request id and HTTP headers) from the SDK response.
62
+ *
63
+ * Default returns both fields as `undefined`; subclasses override to extract from the SDK response.
64
+ * @param _response - SDK response.
65
+ * @returns Combined `{ headers, requestId }` metadata.
66
+ * @internal
67
+ */
68
+ extractResponseMetadata(_response) {
69
+ return { headers: void 0, requestId: void 0 };
70
+ }
71
+ mergeModelParams(settings, embeddingOptions) {
72
+ return deepMerge(
73
+ settings.modelParams ?? {},
74
+ embeddingOptions?.modelParams ?? {}
75
+ );
76
+ }
77
+ /**
78
+ * Pushes API-specific deprecation or migration warnings into the shared
79
+ * sink. Default no-op; subclasses override to surface settings-level
80
+ * warnings (e.g. orchestration's masking_providers deprecation).
81
+ * @param _settings - Embedding model settings.
82
+ * @param _warnings - Shared warnings sink for the current call.
83
+ * @internal
84
+ */
85
+ resolveWarnings(_settings, _warnings) {
86
+ return;
87
+ }
88
+ };
89
+
90
+ export {
91
+ BaseEmbeddingModelStrategy
92
+ };
93
+ //# sourceMappingURL=chunk-OA6TJHD2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/base-embedding-model-strategy.ts"],"sourcesContent":["/** Base class for embedding model strategies using the Template Method pattern. */\nimport type {\n EmbeddingModelV3CallOptions,\n EmbeddingModelV3Embedding,\n EmbeddingModelV3Result,\n SharedV3Warning,\n} from \"@ai-sdk/provider\";\n\nimport { TooManyEmbeddingValuesForCallError } from \"@ai-sdk/provider\";\n\nimport type { SAPAIEmbeddingSettings } from \"./sap-ai-settings.js\";\nimport type { EmbeddingModelAPIStrategy, EmbeddingModelStrategyConfig } from \"./sap-ai-strategy.js\";\n\nimport { deepMerge } from \"./deep-merge.js\";\nimport { convertToAISDKError } from \"./sap-ai-error.js\";\nimport {\n buildEmbeddingResult,\n type EmbeddingProviderOptions,\n type EmbeddingType,\n prepareEmbeddingCall,\n type ResponseMetadata,\n} from \"./strategy-utils.js\";\nimport { VERSION } from \"./version.js\";\n\n/**\n * Abstract base class for embedding model strategies using the Template Method pattern.\n * @template TClient - The SDK client type (e.g., AzureOpenAiEmbeddingClient, OrchestrationEmbeddingClient).\n * @template TResponse - The API response type from the SDK client.\n * @internal\n */\nexport abstract class BaseEmbeddingModelStrategy<\n TClient,\n TResponse,\n> implements EmbeddingModelAPIStrategy {\n /**\n * Template method implementing the shared embedding algorithm.\n * @param config - Strategy configuration.\n * @param settings - Embedding model settings.\n * @param options - AI SDK call options.\n * @param maxEmbeddingsPerCall - Maximum embeddings per call.\n * @returns Complete embedding result for AI SDK.\n * @internal\n */\n async doEmbed(\n config: EmbeddingModelStrategyConfig,\n settings: SAPAIEmbeddingSettings,\n options: EmbeddingModelV3CallOptions,\n maxEmbeddingsPerCall: number,\n ): Promise<EmbeddingModelV3Result> {\n const { abortSignal, values } = options;\n\n try {\n const { embeddingOptions, providerName } = await prepareEmbeddingCall(\n { maxEmbeddingsPerCall, modelId: config.modelId, provider: config.provider },\n options,\n );\n\n const embeddingType = embeddingOptions?.type ?? settings.type ?? \"text\";\n\n const warnings: SharedV3Warning[] = [];\n this.resolveWarnings(settings, warnings);\n\n const client = this.createClient(config, settings, embeddingOptions);\n\n const response = await this.executeCall(client, values, embeddingType, abortSignal);\n\n const embeddings = this.extractEmbeddings(response);\n const totalTokens = this.extractTokenCount(response);\n const { headers: responseHeaders, requestId } = this.extractResponseMetadata(response);\n\n return buildEmbeddingResult({\n embeddings,\n modelId: config.modelId,\n providerName,\n requestId,\n responseHeaders,\n totalTokens,\n version: VERSION,\n warnings,\n });\n } catch (error) {\n if (error instanceof TooManyEmbeddingValuesForCallError) {\n throw error;\n }\n throw convertToAISDKError(error, {\n operation: \"doEmbed\",\n requestBody: { values: values.length },\n url: this.getUrl(),\n });\n }\n }\n\n /**\n * Creates the appropriate SDK client for this API.\n * @param config - Strategy configuration.\n * @param settings - Embedding model settings.\n * @param embeddingOptions - Parsed provider options from the call.\n * @returns SDK client instance.\n * @internal\n */\n protected abstract createClient(\n config: EmbeddingModelStrategyConfig,\n settings: SAPAIEmbeddingSettings,\n embeddingOptions: EmbeddingProviderOptions | undefined,\n ): TClient;\n\n /**\n * Executes the embedding API call.\n * @param client - SDK client instance.\n * @param values - Input strings to embed.\n * @param embeddingType - Type of embedding (text, query, document).\n * @param abortSignal - Optional abort signal.\n * @returns SDK response containing embeddings.\n * @internal\n */\n protected abstract executeCall(\n client: TClient,\n values: string[],\n embeddingType: EmbeddingType,\n abortSignal: AbortSignal | undefined,\n ): Promise<TResponse>;\n\n /**\n * Extracts embeddings from the SDK response.\n * @param response - SDK response containing embedding data.\n * @returns Array of normalized embedding vectors.\n * @internal\n */\n protected abstract extractEmbeddings(response: TResponse): EmbeddingModelV3Embedding[];\n\n /**\n * Extracts response metadata (request id and HTTP headers) from the SDK response.\n *\n * Default returns both fields as `undefined`; subclasses override to extract from the SDK response.\n * @param _response - SDK response.\n * @returns Combined `{ headers, requestId }` metadata.\n * @internal\n */\n protected extractResponseMetadata(_response: TResponse): ResponseMetadata {\n return { headers: undefined, requestId: undefined };\n }\n\n /**\n * Extracts total token count from the SDK response.\n * @param response - SDK response containing usage data.\n * @returns Total token count used for the embedding request.\n * @internal\n */\n protected abstract extractTokenCount(response: TResponse): number;\n\n /**\n * Returns the URL identifier for this API (used in error messages).\n * @returns URL string identifier.\n * @internal\n */\n protected abstract getUrl(): string;\n\n protected mergeModelParams(\n settings: SAPAIEmbeddingSettings,\n embeddingOptions: EmbeddingProviderOptions | undefined,\n ): Record<string, unknown> {\n return deepMerge(\n (settings.modelParams as Record<string, unknown> | undefined) ?? {},\n embeddingOptions?.modelParams ?? {},\n );\n }\n\n /**\n * Pushes API-specific deprecation or migration warnings into the shared\n * sink. Default no-op; subclasses override to surface settings-level\n * warnings (e.g. orchestration's masking_providers deprecation).\n * @param _settings - Embedding model settings.\n * @param _warnings - Shared warnings sink for the current call.\n * @internal\n */\n protected resolveWarnings(_settings: SAPAIEmbeddingSettings, _warnings: SharedV3Warning[]): void {\n return;\n }\n}\n"],"mappings":";;;;;;;;;;;;AAQA,SAAS,0CAA0C;AAsB5C,IAAe,6BAAf,MAGgC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUrC,MAAM,QACJ,QACA,UACA,SACA,sBACiC;AACjC,UAAM,EAAE,aAAa,OAAO,IAAI;AAEhC,QAAI;AACF,YAAM,EAAE,kBAAkB,aAAa,IAAI,MAAM;AAAA,QAC/C,EAAE,sBAAsB,SAAS,OAAO,SAAS,UAAU,OAAO,SAAS;AAAA,QAC3E;AAAA,MACF;AAEA,YAAM,gBAAgB,kBAAkB,QAAQ,SAAS,QAAQ;AAEjE,YAAM,WAA8B,CAAC;AACrC,WAAK,gBAAgB,UAAU,QAAQ;AAEvC,YAAM,SAAS,KAAK,aAAa,QAAQ,UAAU,gBAAgB;AAEnE,YAAM,WAAW,MAAM,KAAK,YAAY,QAAQ,QAAQ,eAAe,WAAW;AAElF,YAAM,aAAa,KAAK,kBAAkB,QAAQ;AAClD,YAAM,cAAc,KAAK,kBAAkB,QAAQ;AACnD,YAAM,EAAE,SAAS,iBAAiB,UAAU,IAAI,KAAK,wBAAwB,QAAQ;AAErF,aAAO,qBAAqB;AAAA,QAC1B;AAAA,QACA,SAAS,OAAO;AAAA,QAChB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA,SAAS;AAAA,QACT;AAAA,MACF,CAAC;AAAA,IACH,SAAS,OAAO;AACd,UAAI,iBAAiB,oCAAoC;AACvD,cAAM;AAAA,MACR;AACA,YAAM,oBAAoB,OAAO;AAAA,QAC/B,WAAW;AAAA,QACX,aAAa,EAAE,QAAQ,OAAO,OAAO;AAAA,QACrC,KAAK,KAAK,OAAO;AAAA,MACnB,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgDU,wBAAwB,WAAwC;AACxE,WAAO,EAAE,SAAS,QAAW,WAAW,OAAU;AAAA,EACpD;AAAA,EAiBU,iBACR,UACA,kBACyB;AACzB,WAAO;AAAA,MACJ,SAAS,eAAuD,CAAC;AAAA,MAClE,kBAAkB,eAAe,CAAC;AAAA,IACpC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUU,gBAAgB,WAAmC,WAAoC;AAC/F;AAAA,EACF;AACF;","names":[]}
@@ -1,22 +1,24 @@
1
1
  import {createRequire as __createRequire} from 'module';var require=__createRequire(import.meta.url);
2
2
  import {
3
3
  convertToSAPMessages
4
- } from "./chunk-EXOXZ5OU.js";
4
+ } from "./chunk-4JIMBRMV.js";
5
5
  import {
6
6
  StreamIdGenerator,
7
7
  buildGenerateResult,
8
8
  buildModelParams,
9
9
  createAISDKRequestBodySummary,
10
10
  createStreamTransformer,
11
+ extractCompletionId,
12
+ extractResponseMetadata,
11
13
  mapToolChoice
12
- } from "./chunk-4RRRJBEL.js";
14
+ } from "./chunk-BZWUUBX2.js";
13
15
  import {
14
16
  VERSION,
15
17
  convertToAISDKError,
16
18
  getProviderName,
17
19
  normalizeHeaders,
18
20
  sapAILanguageModelProviderOptions
19
- } from "./chunk-F4MUYVQJ.js";
21
+ } from "./chunk-XIWHF23D.js";
20
22
 
21
23
  // src/base-language-model-strategy.ts
22
24
  import { parseProviderOptions } from "@ai-sdk/provider-utils";
@@ -52,6 +54,7 @@ var BaseLanguageModelStrategy = class {
52
54
  modelId: config.modelId,
53
55
  providerName: commonParts.providerName,
54
56
  requestBody: request,
57
+ requestId: response.requestId,
55
58
  response,
56
59
  responseHeaders: normalizeHeaders(response.rawResponse.headers),
57
60
  version: VERSION,
@@ -86,7 +89,7 @@ var BaseLanguageModelStrategy = class {
86
89
  modelId: config.modelId,
87
90
  options,
88
91
  providerName: commonParts.providerName,
89
- responseHeaders: streamResponse.responseHeaders,
92
+ requestId: streamResponse.requestId,
90
93
  responseId,
91
94
  sdkStream: streamResponse.stream,
92
95
  streamResponseGetCitations: streamResponse.getCitations,
@@ -130,9 +133,18 @@ var BaseLanguageModelStrategy = class {
130
133
  schema: sapAILanguageModelProviderOptions
131
134
  });
132
135
  const warnings = [];
136
+ const resolvedState = this.resolveAdditionalState(
137
+ config,
138
+ settings,
139
+ sapOptions,
140
+ options,
141
+ warnings
142
+ );
133
143
  const messages = convertToSAPMessages(options.prompt, {
134
144
  escapeTemplatePlaceholders: this.getEscapeTemplatePlaceholders(sapOptions, settings),
135
- includeReasoning: this.getIncludeReasoning(sapOptions, settings)
145
+ includeReasoning: this.getIncludeReasoning(sapOptions, settings),
146
+ parsePartProviderOptions: this.getPartProviderOptionsParser(),
147
+ warnings
136
148
  });
137
149
  const { modelParams, warnings: paramWarnings } = buildModelParams({
138
150
  options,
@@ -146,6 +158,7 @@ var BaseLanguageModelStrategy = class {
146
158
  messages,
147
159
  modelParams,
148
160
  providerName,
161
+ resolvedState,
149
162
  sapOptions,
150
163
  toolChoice,
151
164
  warnings
@@ -162,6 +175,20 @@ var BaseLanguageModelStrategy = class {
162
175
  collectStreamWarnings(_settings, _sapOptions) {
163
176
  return [];
164
177
  }
178
+ /**
179
+ * Resolves request id, completion id, and normalised headers from an SDK response.
180
+ * @param response - Raw SDK response or stream response.
181
+ * @returns Combined metadata fragment.
182
+ * @internal
183
+ */
184
+ extractMetadata(response) {
185
+ const responseId = extractCompletionId(
186
+ response,
187
+ this.getCompletionIdPath()
188
+ );
189
+ const { headers, requestId } = extractResponseMetadata(response, "rawResponse");
190
+ return { requestId, responseHeaders: headers, responseId };
191
+ }
165
192
  /**
166
193
  * Returns whether to escape template placeholders for this API.
167
194
  * @param _sapOptions - Parsed provider options (unused in base implementation).
@@ -182,9 +209,36 @@ var BaseLanguageModelStrategy = class {
182
209
  getIncludeReasoning(sapOptions, settings) {
183
210
  return sapOptions?.includeReasoning ?? settings.includeReasoning ?? false;
184
211
  }
212
+ /**
213
+ * Returns a parser for per-message-part `providerOptions['sap-ai']`.
214
+ *
215
+ * Default returns `undefined`; strategies honouring part-level directives
216
+ * (e.g. Anthropic `cacheControl` on orchestration) override to return a parser.
217
+ * @returns Parser callback, or undefined to disable per-part plumbing.
218
+ * @internal
219
+ */
220
+ getPartProviderOptionsParser() {
221
+ return void 0;
222
+ }
223
+ /**
224
+ * Resolves API-specific extra state shared between doGenerate and doStream
225
+ * (e.g. orchestration `configRef` / `promptTemplateRef` / `tools`). Override
226
+ * to add API-specific deprecation checks or pre-resolve auxiliary inputs.
227
+ * Pushed warnings flow into the shared sink.
228
+ * @param _config - Strategy configuration.
229
+ * @param _settings - Model settings.
230
+ * @param _sapOptions - Parsed provider options, or `undefined`.
231
+ * @param _options - AI SDK call options.
232
+ * @param _warnings - Shared warnings sink for the current call.
233
+ * @returns Strategy-specific resolved state, or `undefined` (default).
234
+ * @internal
235
+ */
236
+ resolveAdditionalState(_config, _settings, _sapOptions, _options, _warnings) {
237
+ return void 0;
238
+ }
185
239
  };
186
240
 
187
241
  export {
188
242
  BaseLanguageModelStrategy
189
243
  };
190
- //# sourceMappingURL=chunk-DYFBCE2W.js.map
244
+ //# sourceMappingURL=chunk-RUCURXS7.js.map