@jerome-benoit/sap-ai-provider-v2 5.0.3 → 5.1.0
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.
- package/README.md +44 -24
- package/dist/chunk-4ILJD6PI.js +333 -0
- package/dist/chunk-4ILJD6PI.js.map +1 -0
- package/dist/chunk-BHA5MIN6.js +224 -0
- package/dist/chunk-BHA5MIN6.js.map +1 -0
- package/dist/{chunk-4JLNWASF.js → chunk-DLGBK3C3.js} +91 -7
- package/dist/chunk-DLGBK3C3.js.map +1 -0
- package/dist/{chunk-E76ZDPIW.js → chunk-EUBI5ENK.js} +54 -27
- package/dist/chunk-EUBI5ENK.js.map +1 -0
- package/dist/{chunk-YP3AADWD.js → chunk-FKHOJ3ZC.js} +24 -3
- package/dist/chunk-FKHOJ3ZC.js.map +1 -0
- package/dist/{chunk-UIBQ5AFS.js → chunk-QFMHNGLB.js} +56 -218
- package/dist/chunk-QFMHNGLB.js.map +1 -0
- package/dist/{chunk-3H5C5U22.js → chunk-QQQYMQPU.js} +19 -10
- package/dist/chunk-QQQYMQPU.js.map +1 -0
- package/dist/{chunk-NF355OFT.js → chunk-ZOBD7PXJ.js} +116 -21
- package/dist/chunk-ZOBD7PXJ.js.map +1 -0
- package/dist/{foundation-models-embedding-model-strategy-SAVQFBF4.js → foundation-models-embedding-model-strategy-3WAKJXBY.js} +5 -4
- package/dist/{foundation-models-embedding-model-strategy-SAVQFBF4.js.map → foundation-models-embedding-model-strategy-3WAKJXBY.js.map} +1 -1
- package/dist/{foundation-models-language-model-strategy-ZDOWVYTA.js → foundation-models-language-model-strategy-PJ26VXEA.js} +21 -8
- package/dist/foundation-models-language-model-strategy-PJ26VXEA.js.map +1 -0
- package/dist/index.cjs +2008 -497
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +798 -185
- package/dist/index.d.ts +798 -185
- package/dist/index.js +148 -24
- package/dist/index.js.map +1 -1
- package/dist/{orchestration-embedding-model-strategy-GT27AFII.js → orchestration-embedding-model-strategy-AZ76XLMD.js} +6 -5
- package/dist/{orchestration-embedding-model-strategy-GT27AFII.js.map → orchestration-embedding-model-strategy-AZ76XLMD.js.map} +1 -1
- package/dist/{orchestration-language-model-strategy-7QTPQHCC.js → orchestration-language-model-strategy-CT6RHCYO.js} +48 -17
- package/dist/orchestration-language-model-strategy-CT6RHCYO.js.map +1 -0
- package/dist/responses-language-model-strategy-UYTV6TPM.js +738 -0
- package/dist/responses-language-model-strategy-UYTV6TPM.js.map +1 -0
- package/dist/sap-ai-error-UPKYWPSS.js +16 -0
- package/dist/sap-ai-error-UPKYWPSS.js.map +1 -0
- package/package.json +79 -39
- package/dist/chunk-3H5C5U22.js.map +0 -1
- package/dist/chunk-4JLNWASF.js.map +0 -1
- package/dist/chunk-E76ZDPIW.js.map +0 -1
- package/dist/chunk-NF355OFT.js.map +0 -1
- package/dist/chunk-UIBQ5AFS.js.map +0 -1
- package/dist/chunk-YP3AADWD.js.map +0 -1
- package/dist/foundation-models-language-model-strategy-ZDOWVYTA.js.map +0 -1
- package/dist/orchestration-language-model-strategy-7QTPQHCC.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/responses-language-model-strategy.ts","../src/responses-adapters-v3-to-v4.ts","../src/responses-adapters-v4-to-v3.ts","../src/adapter-metadata.ts","../src/responses-http-transport.ts"],"sourcesContent":["/** OpenAI Responses through SAP AI Core's authenticated HTTP transport. */\nimport type {\n LanguageModelV3CallOptions,\n LanguageModelV3GenerateResult,\n LanguageModelV3Prompt,\n LanguageModelV3StreamPart,\n LanguageModelV3StreamResult,\n LanguageModelV3ToolResultOutput,\n LanguageModelV4,\n LanguageModelV4CallOptions,\n LanguageModelV4Citation,\n SharedV3ProviderMetadata,\n SharedV3ProviderOptions,\n SharedV3Warning,\n} from \"@ai-sdk/provider\";\n\nimport { createOpenAI } from \"@ai-sdk/openai\";\nimport { APICallError } from \"@ai-sdk/provider\";\nimport { z } from \"zod\";\n\nimport type { SAPAIModelSettings, SAPAISettings } from \"./sap-ai-settings.js\";\nimport type { LanguageModelAPIStrategy, LanguageModelStrategyConfig } from \"./sap-ai-strategy.js\";\n\nimport { createAbortError } from \"./abort-utils.js\";\nimport { convertResponsesCallToV4 } from \"./responses-adapters-v3-to-v4.js\";\nimport {\n convertResponsesResultToV3,\n convertResponsesStreamPartToV3,\n} from \"./responses-adapters-v4-to-v3.js\";\nimport { createResponsesTransport } from \"./responses-http-transport.js\";\nimport { convertToAISDKError } from \"./sap-ai-error.js\";\nimport { getProviderName } from \"./sap-ai-provider-options.js\";\nimport { createAISDKRequestBodySummary } from \"./strategy-utils.js\";\nimport { VERSION } from \"./version.js\";\n\nconst MODEL_PARAMETERS = new Set([\n \"frequencyPenalty\",\n \"maxTokens\",\n \"parallel_tool_calls\",\n \"presencePenalty\",\n \"temperature\",\n \"topP\",\n]);\n\nconst OPENAI_STREAM_ERROR_SCHEMA = z.object({\n data: z.object({ type: z.enum([\"error\", \"response.failed\"]) }).loose(),\n isRetryable: z.boolean(),\n message: z.string(),\n statusCode: z.number().int().min(400).max(599),\n});\n\ntype PromptPart = Exclude<LanguageModelV3Prompt[number], { role: \"system\" }>[\"content\"][number];\n\n/**\n * Responses strategy shared by the V2, V3, and V4 public providers.\n * @internal\n */\nexport class ResponsesLanguageModelStrategy implements LanguageModelAPIStrategy {\n async doGenerate(\n config: LanguageModelStrategyConfig,\n settings: SAPAIModelSettings,\n options: LanguageModelV3CallOptions,\n ): Promise<LanguageModelV3GenerateResult> {\n let dispose: ((reason?: unknown) => void) | undefined;\n try {\n const prepared = await prepareModel(config, settings, options);\n dispose = prepared.dispose;\n const { input, model, providerName, warnings } = prepared;\n const result = convertResponsesResultToV3(await model.doGenerate(input));\n return {\n ...result,\n content: result.content.map((part) => fromOpenAIContent(part, providerName)),\n providerMetadata: responseMetadata(result.providerMetadata, providerName),\n warnings: [...warnings, ...result.warnings],\n };\n } catch (error) {\n const failure = convertError(error, config, options, \"doGenerate\");\n dispose?.(failure);\n throw failure;\n }\n }\n\n async doStream(\n config: LanguageModelStrategyConfig,\n settings: SAPAIModelSettings,\n options: LanguageModelV3CallOptions,\n ): Promise<LanguageModelV3StreamResult> {\n let dispose: ((reason?: unknown) => void) | undefined;\n try {\n const prepared = await prepareModel(config, settings, options);\n dispose = prepared.dispose;\n const { input, model, providerName, warnings } = prepared;\n const result = await model.doStream(input);\n const reader = result.stream.getReader();\n let cancelled = false;\n const isCancelled = () => cancelled;\n return {\n ...result,\n stream: new ReadableStream<LanguageModelV3StreamPart>(\n {\n async cancel(reason) {\n cancelled = true;\n dispose?.(reason);\n try {\n await reader.cancel(reason);\n } finally {\n reader.releaseLock();\n }\n },\n async pull(controller) {\n try {\n if (options.abortSignal?.aborted)\n throw createAbortError(options.abortSignal.reason);\n const next = await reader.read();\n if (isCancelled()) return;\n if (options.abortSignal?.aborted)\n throw createAbortError(options.abortSignal.reason);\n if (next.done) {\n reader.releaseLock();\n controller.close();\n return;\n }\n const part = convertResponsesStreamPartToV3(next.value);\n if (part.type === \"stream-start\") {\n controller.enqueue({ ...part, warnings: [...warnings, ...part.warnings] });\n } else if (part.type === \"finish\") {\n controller.enqueue({\n ...part,\n providerMetadata: responseMetadata(part.providerMetadata, providerName),\n });\n } else if (part.type === \"error\") {\n controller.enqueue({\n ...part,\n error: convertError(part.error, config, options, \"doStream\"),\n });\n } else if (\"providerMetadata\" in part || part.type === \"text-end\") {\n controller.enqueue(fromOpenAIContent(part, providerName));\n } else {\n controller.enqueue(part);\n }\n } catch (error) {\n if (isCancelled()) return;\n const failure = convertError(error, config, options, \"doStream\");\n dispose?.(failure);\n // Cleanup failures must not replace the original request or cancellation error.\n await reader.cancel(error).catch(() => undefined);\n if (isCancelled()) return;\n reader.releaseLock();\n controller.enqueue({\n error: failure,\n type: \"error\",\n });\n controller.close();\n }\n },\n },\n { highWaterMark: 0 },\n ),\n };\n } catch (error) {\n const failure = convertError(error, config, options, \"doStream\");\n dispose?.(failure);\n throw failure;\n }\n }\n}\n\n/**\n * Applies the provider's shared error contract without copying transport credentials.\n * @param error - Delegate or SAP transport error.\n * @param config - Model configuration.\n * @param options - Invocation options.\n * @param operation - Generation operation.\n * @returns The corresponding AI SDK error.\n */\nfunction convertError(\n error: unknown,\n config: LanguageModelStrategyConfig,\n options: LanguageModelV3CallOptions,\n operation: \"doGenerate\" | \"doStream\",\n) {\n // The delegate can hide a classified body-read failure under a successful HTTP status.\n if (\n APICallError.isInstance(error) &&\n error.message === \"Failed to process successful response\" &&\n error.statusCode !== undefined &&\n error.statusCode >= 200 &&\n error.statusCode < 300 &&\n APICallError.isInstance(error.cause)\n ) {\n return error.cause;\n }\n if (operation === \"doStream\" && !APICallError.isInstance(error)) {\n const parsed = OPENAI_STREAM_ERROR_SCHEMA.safeParse(error);\n if (parsed.success) {\n return new APICallError({\n cause: error,\n data: parsed.data.data,\n isRetryable: parsed.data.isRetryable,\n message: parsed.data.message,\n requestBodyValues: createAISDKRequestBodySummary(options),\n statusCode: parsed.data.statusCode,\n url: \"sap-ai:responses\",\n });\n }\n }\n return convertToAISDKError(error, {\n modelId: config.modelId,\n modelType: \"languageModel\",\n operation,\n requestBody: createAISDKRequestBodySummary(options),\n url: \"sap-ai:responses\",\n });\n}\n\n/**\n * Exposes native Responses metadata under the configured SAP namespace.\n * @param metadata - Responses metadata.\n * @param providerName - Configured SAP provider namespace.\n * @returns Namespaced metadata.\n */\nfunction fromOpenAI(\n metadata: SharedV3ProviderMetadata | undefined,\n providerName: string,\n): SharedV3ProviderMetadata | undefined {\n if (providerName === \"openai\" || !metadata?.openai) return metadata;\n const { openai, ...rest } = metadata;\n return { ...rest, [providerName]: { ...rest[providerName], ...openai } };\n}\n\n/**\n * Remaps only citation source metadata, retaining untouched sources and positions.\n * @param citations - V4 citations preserved through the shared V3 core.\n * @param providerName - Resolved SAP provider namespace.\n * @returns The original array unless a source namespace changes.\n */\nfunction fromOpenAICitations(\n citations: LanguageModelV4Citation[] | undefined,\n providerName: string,\n): LanguageModelV4Citation[] | undefined {\n if (providerName === \"openai\" || !citations) return citations;\n let mapped: LanguageModelV4Citation[] | undefined;\n let index = 0;\n for (const citation of citations) {\n const providerMetadata = fromOpenAI(citation.source.providerMetadata, providerName);\n if (providerMetadata !== citation.source.providerMetadata) {\n mapped ??= citations.slice();\n mapped[index] = {\n ...citation,\n source: { ...citation.source, providerMetadata },\n };\n }\n index++;\n }\n return mapped ?? citations;\n}\n\n/**\n * Applies the same namespace policy to direct metadata and nested citation sources.\n * @param part - Content or a text-end event, including preserved V4 citation fields.\n * @param providerName - Resolved SAP provider namespace.\n * @returns The original part when no metadata changes, otherwise an immutable copy.\n */\nfunction fromOpenAIContent<\n T extends {\n citations?: LanguageModelV4Citation[];\n providerMetadata?: SharedV3ProviderMetadata;\n },\n>(part: T, providerName: string): T {\n const providerMetadata = fromOpenAI(part.providerMetadata, providerName);\n const citations = fromOpenAICitations(part.citations, providerName);\n if (providerMetadata === part.providerMetadata && citations === part.citations) return part;\n if (providerMetadata === part.providerMetadata) return { ...part, citations };\n return citations === part.citations\n ? { ...part, providerMetadata }\n : { ...part, citations, providerMetadata };\n}\n\n/**\n * Maps configured structured output to the common AI SDK call format.\n * @param settings - Model settings.\n * @returns The corresponding AI SDK response format.\n */\nfunction modelResponseFormat(\n settings: SAPAISettings,\n): LanguageModelV3CallOptions[\"responseFormat\"] {\n const format = settings.responseFormat;\n if (!format || format.type === \"text\") return format;\n if (format.type === \"json_object\") return { type: \"json\" };\n const schema = format.json_schema;\n return {\n description: schema.description,\n name: schema.name,\n schema:\n schema.schema === undefined ? undefined : z.record(z.string(), z.json()).parse(schema.schema),\n type: \"json\",\n };\n}\n\n/**\n * Resolves SAP transport and maps the provider's configuration to Responses options.\n * @param config - SAP deployment and transport configuration.\n * @param settings - Model defaults.\n * @param options - Invocation options.\n * @returns The delegate and its normalized invocation.\n */\nasync function prepareModel(\n config: LanguageModelStrategyConfig,\n settings: SAPAISettings,\n options: LanguageModelV3CallOptions,\n): Promise<{\n dispose: (reason?: unknown) => void;\n input: LanguageModelV4CallOptions;\n model: LanguageModelV4;\n providerName: string;\n warnings: SharedV3Warning[];\n}> {\n if (options.abortSignal?.aborted) {\n throw createAbortError(options.abortSignal.reason);\n }\n const providerName = getProviderName(config.provider);\n const sapOptions = config.parsedProviderOptions;\n const parameters = { ...settings.modelParams, ...sapOptions?.modelParams };\n const warnings: SharedV3Warning[] = Object.keys(parameters)\n .filter((key) => !MODEL_PARAMETERS.has(key))\n .map((key) => ({\n details: \"Use the responses option for Responses-specific parameters.\",\n feature: `modelParams.${key}`,\n type: \"unsupported\",\n }));\n if (sapOptions?.includeReasoning ?? settings.includeReasoning) {\n warnings.push({\n details: \"Responses preserves native reasoning history instead of converting it to text.\",\n feature: \"includeReasoning\",\n type: \"unsupported\",\n });\n }\n const responseOptions = {\n ...(parameters.parallel_tool_calls !== undefined\n ? { parallelToolCalls: parameters.parallel_tool_calls }\n : {}),\n ...(settings.responseFormat?.type === \"json_schema\"\n ? { strictJsonSchema: settings.responseFormat.json_schema.strict }\n : {}),\n store: false,\n ...settings.responses,\n ...sapOptions?.responses,\n };\n const reasoning = \"reasoning\" in options ? options.reasoning : undefined;\n if (typeof reasoning === \"string\" && reasoning !== \"provider-default\") {\n responseOptions.reasoningEffort = reasoning;\n }\n const input: LanguageModelV3CallOptions = {\n ...options,\n frequencyPenalty: options.frequencyPenalty ?? parameters.frequencyPenalty,\n maxOutputTokens: options.maxOutputTokens ?? parameters.maxTokens,\n presencePenalty: options.presencePenalty ?? parameters.presencePenalty,\n prompt: toOpenAIPrompt(options.prompt, providerName),\n providerOptions: {\n ...options.providerOptions,\n openai: responseOptions,\n },\n responseFormat: options.responseFormat ?? modelResponseFormat(settings),\n temperature: options.temperature ?? parameters.temperature,\n tools: options.tools?.map((tool) =>\n tool.type === \"function\"\n ? {\n ...tool,\n providerOptions: toOpenAI(tool.providerOptions, providerName),\n strict: tool.strict ?? false,\n }\n : tool,\n ),\n topP: options.topP ?? parameters.topP,\n };\n const convertedInput = convertResponsesCallToV4(input);\n const transport = await createResponsesTransport(config, settings, options);\n const model = createOpenAI({\n // Authentication is supplied by SAP's transport, not an OpenAI API key.\n apiKey: \"sap-ai-core\",\n baseURL: transport.baseURL,\n fetch: transport.fetch,\n }).responses(config.modelId);\n return { dispose: transport.dispose, input: convertedInput, model, providerName, warnings };\n}\n\n/**\n * Adds provider identity to the final Responses metadata.\n * @param metadata - Delegate metadata.\n * @param providerName - Configured SAP provider namespace.\n * @returns Final provider metadata.\n */\nfunction responseMetadata(\n metadata: SharedV3ProviderMetadata | undefined,\n providerName: string,\n): SharedV3ProviderMetadata {\n const mapped = fromOpenAI(metadata, providerName);\n return {\n ...mapped,\n [providerName]: { ...mapped?.[providerName], api: \"responses\", version: VERSION },\n };\n}\n\n/**\n * Restores the native namespace used by OpenAI's history converter.\n * @param options - Provider options on a message, part, or tool.\n * @param providerName - Configured SAP provider namespace.\n * @returns Options with a native OpenAI slice.\n */\nfunction toOpenAI(\n options: SharedV3ProviderOptions | undefined,\n providerName: string,\n): SharedV3ProviderOptions | undefined {\n if (providerName === \"openai\" || !options?.[providerName]) return options;\n return { ...options, openai: { ...options.openai, ...options[providerName] } };\n}\n\n/**\n * Translates provider-specific file IDs and metadata nested in tool output.\n * @param output - Tool output.\n * @param providerName - Configured SAP provider namespace.\n * @returns Tool output with native Responses identifiers.\n */\nfunction toOpenAIOutput(\n output: LanguageModelV3ToolResultOutput & { providerOptions?: SharedV3ProviderOptions },\n providerName: string,\n): LanguageModelV3ToolResultOutput {\n const mappedOutput = {\n ...output,\n providerOptions: toOpenAI(output.providerOptions, providerName),\n };\n if (mappedOutput.type !== \"content\") return mappedOutput;\n return {\n ...mappedOutput,\n value: mappedOutput.value.map((part) => ({\n ...part,\n ...((part.type === \"file-id\" || part.type === \"image-file-id\") &&\n typeof part.fileId !== \"string\" &&\n part.fileId[providerName]\n ? { fileId: { ...part.fileId, openai: part.fileId[providerName] } }\n : {}),\n ...(\"providerOptions\" in part\n ? { providerOptions: toOpenAI(part.providerOptions, providerName) }\n : {}),\n })),\n };\n}\n\n/**\n * Translates one prompt part while preserving its message-specific type.\n * @param part - Input part.\n * @param providerName - Configured SAP provider namespace.\n * @returns The translated input part.\n */\nfunction toOpenAIPart<T extends PromptPart>(part: T, providerName: string): T {\n return {\n ...part,\n ...(part.type === \"tool-result\" ? { output: toOpenAIOutput(part.output, providerName) } : {}),\n providerOptions: toOpenAI(part.providerOptions, providerName),\n };\n}\n\n/**\n * Preserves reasoning IDs, encrypted content, and tool metadata across requests.\n * @param prompt - The normalized AI SDK prompt.\n * @param providerName - Configured SAP provider namespace.\n * @returns The prompt understood by the Responses delegate.\n */\nfunction toOpenAIPrompt(\n prompt: LanguageModelV3Prompt,\n providerName: string,\n): LanguageModelV3Prompt {\n return prompt.map((message) => {\n const providerOptions = toOpenAI(message.providerOptions, providerName);\n switch (message.role) {\n case \"assistant\":\n return {\n ...message,\n content: message.content.map((part) => toOpenAIPart(part, providerName)),\n providerOptions,\n };\n case \"system\":\n return { ...message, providerOptions };\n case \"tool\":\n return {\n ...message,\n content: message.content.map((part) => toOpenAIPart(part, providerName)),\n providerOptions,\n };\n case \"user\":\n return {\n ...message,\n content: message.content.map((part) => toOpenAIPart(part, providerName)),\n providerOptions,\n };\n }\n });\n}\n","/** Input adapter: convert shared V3 calls to the OpenAI Responses V4 delegate contract. */\nimport type {\n LanguageModelV3CallOptions,\n LanguageModelV3Prompt,\n LanguageModelV3ToolResultOutput,\n LanguageModelV4CallOptions,\n LanguageModelV4Prompt,\n LanguageModelV4ToolResultOutput,\n} from \"@ai-sdk/provider\";\n\nimport { UnsupportedFunctionalityError } from \"@ai-sdk/provider\";\nimport { getTopLevelMediaType } from \"@ai-sdk/provider-utils\";\n\nimport { getURLHref } from \"./convert-to-sap-messages.js\";\n\ntype V3Part = Exclude<LanguageModelV3Prompt[number], { role: \"system\" }>[\"content\"][number];\ntype V3ToolItem = Extract<LanguageModelV3ToolResultOutput, { type: \"content\" }>[\"value\"][number];\ntype V4Part = Exclude<LanguageModelV4Prompt[number], { role: \"system\" }>[\"content\"][number];\ntype V4ToolItem = Extract<LanguageModelV4ToolResultOutput, { type: \"content\" }>[\"value\"][number];\n\n/**\n * Tags V3 prompt files and tool-result media for the V4 delegate.\n * @param options - The normalized V3 invocation, including provider namespaces.\n * @returns V4 options that retain the invocation's data and transport settings.\n */\nexport function convertResponsesCallToV4(\n options: LanguageModelV3CallOptions,\n): LanguageModelV4CallOptions {\n return {\n ...options,\n prompt: options.prompt.map((message) => {\n switch (message.role) {\n case \"assistant\":\n return { ...message, content: message.content.map(convertPromptPart) };\n case \"system\":\n return message;\n case \"tool\":\n return {\n ...message,\n content: message.content.map((part) =>\n part.type === \"tool-result\" ? convertToolResult(part) : part,\n ),\n };\n case \"user\":\n return {\n ...message,\n content: message.content.map((part) =>\n part.type === \"file\" ? convertFile(part) : part,\n ),\n };\n }\n }),\n };\n}\n\n/**\n * Tags inline bytes and canonicalizes URL objects for the delegate's serializer.\n * @param part - A V3 prompt file.\n * @returns The tagged V4 file.\n */\nfunction convertFile(part: Extract<V3Part, { type: \"file\" }>): Extract<V4Part, { type: \"file\" }> {\n const data = part.data;\n const href = getURLHref(data);\n if (href !== undefined) {\n const url =\n data instanceof URL && data.toString === URL.prototype.toString ? data : new URL(href);\n return { ...part, data: { type: \"url\", url } };\n }\n // The V3 union leaves only inline data once URL internal slots have been ruled out.\n return { ...part, data: { data: data as string | Uint8Array, type: \"data\" } };\n}\n\n/**\n * Converts assistant history to the delegate's prompt contract.\n * @param part - A V3 assistant part.\n * @returns Its V4 equivalent.\n */\nfunction convertPromptPart(\n part: Exclude<\n LanguageModelV3Prompt[number],\n { role: \"system\" | \"tool\" | \"user\" }\n >[\"content\"][number],\n): Exclude<LanguageModelV4Prompt[number], { role: \"system\" | \"tool\" | \"user\" }>[\"content\"][number] {\n if (part.type === \"file\") {\n throw new UnsupportedFunctionalityError({\n functionality: \"Responses assistant file history is not supported.\",\n });\n }\n if (part.type === \"tool-result\") return convertToolResult(part);\n return part;\n}\n\n/**\n * Retains file and image categories when tagging tool-result media.\n * @param item - A V3 tool-result content item.\n * @returns The matching V4 content item.\n */\nfunction convertToolItem(item: V3ToolItem): V4ToolItem {\n switch (item.type) {\n case \"custom\":\n case \"text\":\n return item;\n case \"file-data\":\n case \"image-data\": {\n const delegateIsImage = getTopLevelMediaType(item.mediaType) === \"image\";\n if (delegateIsImage !== (item.type === \"image-data\")) {\n throw new UnsupportedFunctionalityError({\n functionality:\n \"Responses tool-result media whose legacy category disagrees with its media type.\",\n });\n }\n return { ...item, data: { data: item.data, type: \"data\" }, type: \"file\" };\n }\n case \"file-id\":\n case \"image-file-id\":\n return {\n data: {\n reference: typeof item.fileId === \"string\" ? { openai: item.fileId } : item.fileId,\n type: \"reference\",\n },\n mediaType: item.type === \"image-file-id\" ? \"image\" : \"application/octet-stream\",\n providerOptions: item.providerOptions,\n type: \"file\",\n };\n case \"file-url\":\n case \"image-url\":\n return {\n data: { type: \"url\", url: new URL(item.url) },\n mediaType: item.type === \"image-url\" ? \"image\" : \"application/octet-stream\",\n providerOptions: item.providerOptions,\n type: \"file\",\n };\n }\n}\n\n/**\n * Converts nested tool-result media without altering non-media outputs.\n * @param part - A V3 tool result.\n * @returns A V4 tool result with the same call identity and options.\n */\nfunction convertToolResult(\n part: Extract<V3Part, { type: \"tool-result\" }>,\n): Extract<V4Part, { type: \"tool-result\" }> {\n return part.output.type === \"content\"\n ? { ...part, output: { ...part.output, value: part.output.value.map(convertToolItem) } }\n : { ...part, output: part.output };\n}\n","/** Output adapter: convert OpenAI Responses V4 results to the shared V3 contract. */\nimport type {\n LanguageModelV3Content,\n LanguageModelV3File,\n LanguageModelV3FinishReason,\n LanguageModelV3GenerateResult,\n LanguageModelV3StreamPart,\n LanguageModelV4Content,\n LanguageModelV4File,\n LanguageModelV4GenerateResult,\n LanguageModelV4StreamPart,\n SharedV3Warning,\n SharedV4Warning,\n} from \"@ai-sdk/provider\";\n\nimport { UnsupportedFunctionalityError } from \"@ai-sdk/provider\";\n\nimport { ORIGINAL_V4_FINISH_REASON } from \"./adapter-metadata.js\";\n\n/** V3-compatible content retaining V4 text citations for the V4 facade. */\ntype ResponsesV3Content =\n | Exclude<LanguageModelV3Content, { type: \"text\" }>\n | (Extract<LanguageModelV3Content, { type: \"text\" }> &\n Pick<Extract<LanguageModelV4Content, { type: \"text\" }>, \"citations\">);\n\n/** Internal result extensions survive V3-shaped spreads without widening public V3 APIs. */\ntype ResponsesV3GenerateResult = Omit<LanguageModelV3GenerateResult, \"content\"> &\n Pick<LanguageModelV4GenerateResult, \"structuredOutputText\"> & {\n content: ResponsesV3Content[];\n };\n\n/** Only existing V3 event kinds carry these preserved V4 fields. */\ntype ResponsesV3StreamPart =\n | Exclude<LanguageModelV3StreamPart, { type: \"text-end\" | \"tool-input-start\" }>\n | (Extract<LanguageModelV3StreamPart, { type: \"text-end\" }> &\n Pick<Extract<LanguageModelV4StreamPart, { type: \"text-end\" }>, \"citations\">)\n | (Extract<LanguageModelV3StreamPart, { type: \"tool-input-start\" }> &\n Pick<Extract<LanguageModelV4StreamPart, { type: \"tool-input-start\" }>, \"inputEncoding\">);\n\n/**\n * Unwraps V4 generated files and maps warnings and finish reasons to V3.\n * @param result - The OpenAI V4 generation result.\n * @returns A result suitable for the shared V3 core.\n */\nexport function convertResponsesResultToV3(\n result: LanguageModelV4GenerateResult,\n): ResponsesV3GenerateResult {\n return {\n ...result,\n content: result.content.map(convertContent),\n finishReason: convertFinishReason(result.finishReason),\n warnings: result.warnings.map(convertWarning),\n };\n}\n\n/**\n * Converts one delegate event inside the existing demand-driven stream wrapper.\n * @param part - The OpenAI V4 event.\n * @returns The corresponding V3 event.\n */\nexport function convertResponsesStreamPartToV3(\n part: LanguageModelV4StreamPart,\n): ResponsesV3StreamPart {\n switch (part.type) {\n case \"custom\":\n case \"reasoning-file\":\n throw new UnsupportedFunctionalityError({\n functionality: `Responses '${part.type}' output has no V3 equivalent.`,\n });\n case \"file\":\n return convertGeneratedFile(part);\n case \"finish\":\n return { ...part, finishReason: convertFinishReason(part.finishReason) };\n case \"stream-start\":\n return { ...part, warnings: part.warnings.map(convertWarning) };\n default:\n return part;\n }\n}\n\n/**\n * Rejects V4-only output instead of leaking invalid content through V2/V3 APIs.\n * @param part - Generated V4 content.\n * @returns Content representable by the shared V3 core.\n */\nfunction convertContent(part: LanguageModelV4Content): ResponsesV3Content {\n if (part.type === \"custom\" || part.type === \"reasoning-file\") {\n throw new UnsupportedFunctionalityError({\n functionality: `Responses '${part.type}' output has no V3 equivalent.`,\n });\n }\n return part.type === \"file\" ? convertGeneratedFile(part) : part;\n}\n\n/**\n * Preserves native finish diagnostics when V3 cannot name the unified reason.\n * @param reason - The V4 finish reason.\n * @returns The corresponding V3 finish reason.\n */\nfunction convertFinishReason(\n reason: LanguageModelV4GenerateResult[\"finishReason\"],\n): LanguageModelV3FinishReason {\n if (reason.unified !== \"interrupted\") return reason as LanguageModelV3FinishReason;\n const converted: LanguageModelV3FinishReason = { ...reason, unified: \"other\" };\n return Object.defineProperty(converted, ORIGINAL_V4_FINISH_REASON, { value: reason });\n}\n\n/**\n * Unwraps generated inline data without fetching URL-backed output.\n * @param part - A generated V4 file.\n * @returns Its inline V3 equivalent.\n */\nfunction convertGeneratedFile(part: LanguageModelV4File): LanguageModelV3File {\n if (part.data.type !== \"data\") {\n throw new UnsupportedFunctionalityError({\n functionality: \"Responses generated file URLs have no V3 equivalent and are not fetched.\",\n });\n }\n return { ...part, data: part.data.data };\n}\n\n/**\n * Retains deprecation diagnostics in the V3 warning union.\n * @param warning - A delegate warning.\n * @returns A V3-compatible warning.\n */\nfunction convertWarning(warning: SharedV4Warning): SharedV3Warning {\n return warning.type === \"deprecated\"\n ? { message: `${warning.setting}: ${warning.message}`, type: \"other\" }\n : warning;\n}\n","/** Private metadata for lossless round trips through the shared V3 contract. */\nimport type { LanguageModelV3FinishReason, LanguageModelV4FinishReason } from \"@ai-sdk/provider\";\n\n// Static CommonJS facades and lazily loaded ESM strategies must share this identity.\nexport const ORIGINAL_V4_FINISH_REASON = Symbol.for(\n \"@jerome-benoit/sap-ai-provider/adapter-metadata.originalV4FinishReason\",\n);\n\nexport type FinishReasonWithV4Metadata = LanguageModelV3FinishReason & {\n [ORIGINAL_V4_FINISH_REASON]?: LanguageModelV4FinishReason;\n};\n","/** Fetch-compatible Responses transport backed by the SAP SDK HTTP client. */\nimport type { LanguageModelV3CallOptions } from \"@ai-sdk/provider\";\nimport type { FetchFunction } from \"@ai-sdk/provider-utils\";\nimport type { CustomRequestConfig } from \"@sap-ai-sdk/core\";\n\nimport { APICallError } from \"@ai-sdk/provider\";\nimport { getFoundationModelDeploymentId, getResourceGroup } from \"@sap-ai-sdk/ai-api/internal.js\";\nimport { executeRequest, getAiCoreDestination } from \"@sap-ai-sdk/core\";\nimport { getTargetUrl } from \"@sap-ai-sdk/core/internal.js\";\n\nimport type { SAPAISettings } from \"./sap-ai-settings.js\";\nimport type { LanguageModelStrategyConfig } from \"./sap-ai-strategy.js\";\n\nimport { createAbortError, throwIfAborted, waitWithAbort } from \"./abort-utils.js\";\nimport { convertToAISDKError, normalizeHeaders } from \"./sap-ai-error.js\";\nimport {\n destroyHttpResponse,\n ERROR_BODY_READ_FAILURE,\n type FailedHttpRequest,\n findFailedHttpRequest,\n isDestroyableRequest,\n preserveResponseBodyTimeout,\n readHttpErrorBody,\n type SAPHttpMiddleware,\n type SAPHttpResponse,\n} from \"./sap-http-stream.js\";\nimport {\n buildModelDeployment,\n createAISDKRequestBodySummary,\n mergeRequestConfig,\n} from \"./strategy-utils.js\";\n\n/**\n * Resolves a SAP deployment and adapts its HTTP transport to the OpenAI provider.\n * @param config - SAP deployment and transport configuration.\n * @param settings - Resolved model settings.\n * @param options - Standard AI SDK call options.\n * @returns The deployment base URL and a fetch-compatible SAP transport.\n * @internal\n */\nexport async function createResponsesTransport(\n config: LanguageModelStrategyConfig,\n settings: SAPAISettings,\n options: LanguageModelV3CallOptions,\n): Promise<{ baseURL: string; dispose: (reason?: unknown) => void; fetch: FetchFunction }> {\n throwIfAborted(options.abortSignal);\n const deployment = buildModelDeployment(config, settings.modelVersion);\n // SAP's discovery helpers expose no signal; cancel the wait and observe late rejections.\n const [deploymentId, destination] = await waitWithAbort(\n Promise.all([\n getFoundationModelDeploymentId(deployment, \"azure-openai\", config.destination),\n getAiCoreDestination(config.destination),\n ]),\n options.abortSignal,\n );\n throwIfAborted(options.abortSignal);\n\n const deploymentPath = `/inference/deployments/${encodeURIComponent(deploymentId)}`;\n const baseURL = getTargetUrl(destination.url, deploymentPath);\n const endpoint = new URL(`${baseURL}/responses`);\n const requestConfig = mergeRequestConfig(\n config.requestConfig,\n options.abortSignal,\n options.headers,\n );\n const activeRequests = new Set<(reason?: unknown) => void>();\n let disposed = false;\n let disposalReason: unknown;\n const dispose = (reason?: unknown) => {\n if (disposed) return;\n disposed = true;\n disposalReason = reason;\n for (const release of activeRequests) {\n try {\n release(reason);\n } catch {\n // Disposal must never replace the invocation's primary failure.\n }\n }\n activeRequests.clear();\n };\n\n const fetch: FetchFunction = async (input, init) => {\n if (disposed) throw createAbortError(disposalReason);\n const url = new URL(typeof input === \"string\" || input instanceof URL ? input : input.url);\n if (url.origin !== endpoint.origin || url.pathname !== endpoint.pathname) {\n throw new TypeError(\"SAP Responses requests must target the configured deployment.\");\n }\n if (init?.method !== \"POST\" || typeof init.body !== \"string\") {\n throw new TypeError(\"SAP Responses requires a POST request with a JSON body.\");\n }\n const body: unknown = JSON.parse(init.body);\n const operation =\n typeof body === \"object\" && body !== null && \"stream\" in body && body.stream === true\n ? \"doStream\"\n : \"doGenerate\";\n const controller = new AbortController();\n const signal = options.abortSignal ?? init.signal;\n const bodyTimeoutCleanups = new Set<() => void>();\n let abortFailedRequest: (() => void) | undefined;\n let activeResponse: SAPHttpResponse | undefined;\n const onAbort = () => {\n controller.abort(signal?.reason);\n };\n const cleanup = () => {\n activeRequests.delete(disposeRequest);\n signal?.removeEventListener(\"abort\", onAbort);\n if (abortFailedRequest) controller.signal.removeEventListener(\"abort\", abortFailedRequest);\n for (const dispose of bodyTimeoutCleanups) dispose();\n activeResponse = undefined;\n };\n const disposeRequest = (reason?: unknown) => {\n try {\n controller.abort(reason);\n } finally {\n try {\n if (activeResponse) destroyHttpResponse(activeResponse);\n } finally {\n cleanup();\n }\n }\n };\n throwIfAborted(signal ?? undefined);\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n activeRequests.add(disposeRequest);\n\n const headers = new Headers(init.headers);\n // Authentication belongs to the SAP destination, not the delegate's placeholder key.\n headers.delete(\"authorization\");\n const configuredHeaders = Object.fromEntries(\n Object.entries(requestConfig?.headers ?? {}).map(([key, value]) => [\n key.toLowerCase(),\n value,\n ]),\n );\n\n let failedRequest: FailedHttpRequest | undefined;\n let failedError: unknown;\n const watchResponse = (response: SAPHttpResponse, request: CustomRequestConfig) => {\n activeResponse = response;\n if (controller.signal.aborted) destroyHttpResponse(response);\n else preserveResponseBodyTimeout(response, request, bodyTimeoutCleanups);\n return response;\n };\n const preserveBodyTimeout: SAPHttpMiddleware =\n ({ fn }) =>\n async (request) => {\n try {\n return watchResponse(await fn(request), request);\n } catch (error) {\n const failed = findFailedHttpRequest(error);\n if (failed) watchResponse(failed.response, request);\n throw error;\n }\n };\n const preserveErrorResponse: SAPHttpMiddleware =\n ({ fn }) =>\n async (request) => {\n try {\n return await fn(request);\n } catch (error) {\n const failed = findFailedHttpRequest(error);\n if (!failed) throw error;\n // SAP's stream error parser assumes JSON. Retain the response before it can\n // discard status and headers when an intermediary returns HTML or an empty body.\n failedRequest = failed;\n failedError = error;\n const request: unknown = failed.response.request;\n if (isDestroyableRequest(request)) {\n // A rejected Axios request no longer observes the request abort signal.\n abortFailedRequest = () => {\n request.destroy();\n };\n if (controller.signal.aborted) abortFailedRequest();\n else controller.signal.addEventListener(\"abort\", abortFailedRequest, { once: true });\n }\n return failed.response;\n }\n };\n\n try {\n const pendingResponse = executeRequest(\n {\n apiVersion: \"2024-10-21\",\n resourceGroup: getResourceGroup(deployment),\n url: `${deploymentPath}/responses`,\n },\n body,\n {\n ...requestConfig,\n headers: { ...Object.fromEntries(headers), ...configuredHeaders },\n middleware: [\n preserveErrorResponse,\n ...(requestConfig?.middleware ?? []),\n preserveBodyTimeout,\n ],\n responseType: \"stream\",\n signal: controller.signal,\n },\n config.destination,\n );\n const response = await waitWithAbort(pendingResponse, controller.signal, destroyHttpResponse);\n activeResponse = response;\n if (controller.signal.aborted) {\n destroyHttpResponse(response);\n throw createAbortError(controller.signal.reason);\n }\n const responseBody: unknown = response.data;\n const responseStream = createByteStream(\n responseBody,\n controller,\n cleanup,\n config,\n options,\n operation,\n );\n if (failedRequest) {\n const readFailure = await readHttpErrorBody(\n failedRequest.response,\n responseStream,\n signal ?? undefined,\n );\n const failure = convertToAISDKError(failedError, {\n modelId: config.modelId,\n modelType: \"languageModel\",\n operation,\n requestBody: createAISDKRequestBodySummary(options),\n url: \"sap-ai:responses\",\n });\n // Secondary body diagnostics must not enter the native cause chain:\n // the delegate scans that chain for network codes and can override HTTP retryability.\n if (readFailure !== undefined && APICallError.isInstance(failure)) {\n Object.defineProperty(failure, ERROR_BODY_READ_FAILURE, { value: readFailure });\n }\n throw failure;\n }\n return new Response(responseStream, {\n headers: normalizeHeaders(response.headers),\n status: response.status,\n });\n } catch (error) {\n dispose(error);\n throw error;\n }\n };\n\n return { baseURL, dispose, fetch };\n}\n\n/**\n * Converts SAP's streaming response without buffering or losing cancellation.\n * @param body - The SAP HTTP client's Node stream.\n * @param requestController - Controls the upstream SAP request.\n * @param cleanup - Removes the caller's abort listener.\n * @param config - Model configuration for safe error conversion.\n * @param options - Standard AI SDK call options.\n * @param operation - Operation derived from the delegate's request body.\n * @returns A native byte stream consumed by the OpenAI provider.\n */\nfunction createByteStream(\n body: unknown,\n requestController: AbortController,\n cleanup: () => void,\n config: LanguageModelStrategyConfig,\n options: LanguageModelV3CallOptions,\n operation: \"doGenerate\" | \"doStream\",\n): ReadableStream<Uint8Array> {\n if (\n typeof body !== \"object\" ||\n body === null ||\n !(Symbol.asyncIterator in body) ||\n typeof body[Symbol.asyncIterator] !== \"function\"\n ) {\n requestController.abort();\n cleanup();\n throw new TypeError(\"SAP Responses did not return a readable response body.\");\n }\n\n const source = body as AsyncIterable<unknown> & { destroy?: () => void };\n const iterator = source[Symbol.asyncIterator]();\n const encoder = new TextEncoder();\n // Axios may already have rejected at the headers of a non-success response.\n const onAbort = () => source.destroy?.();\n const cleanupStream = () => {\n requestController.signal.removeEventListener(\"abort\", onAbort);\n cleanup();\n };\n requestController.signal.addEventListener(\"abort\", onAbort, { once: true });\n if (requestController.signal.aborted) onAbort();\n\n return new ReadableStream<Uint8Array>(\n {\n async cancel(reason) {\n requestController.abort(reason);\n cleanupStream();\n if (source.destroy) {\n source.destroy();\n } else {\n await iterator.return?.();\n }\n },\n async pull(controller) {\n try {\n throwIfAborted(requestController.signal);\n const chunk = await iterator.next();\n throwIfAborted(requestController.signal);\n if (chunk.done) {\n cleanupStream();\n controller.close();\n } else if (typeof chunk.value === \"string\") {\n controller.enqueue(encoder.encode(chunk.value));\n } else if (chunk.value instanceof Uint8Array) {\n controller.enqueue(chunk.value);\n } else {\n throw new TypeError(\"SAP Responses returned a non-byte response chunk.\");\n }\n } catch (error) {\n const failure = requestController.signal.aborted\n ? createAbortError(requestController.signal.reason)\n : error;\n requestController.abort(error);\n cleanupStream();\n source.destroy?.();\n controller.error(\n convertToAISDKError(failure, {\n modelId: config.modelId,\n modelType: \"languageModel\",\n operation,\n requestBody: createAISDKRequestBodySummary(options),\n url: \"sap-ai:responses\",\n }),\n );\n }\n },\n },\n { highWaterMark: 0 },\n );\n}\n"],"mappings":"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","names":["APICallError","UnsupportedFunctionalityError","UnsupportedFunctionalityError","dispose","request","APICallError"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {createRequire as __createRequire} from 'module';var require=__createRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
ApiSwitchError,
|
|
4
|
+
UnsupportedFeatureError,
|
|
5
|
+
convertSAPErrorToAPICallError,
|
|
6
|
+
convertToAISDKError,
|
|
7
|
+
normalizeHeaders
|
|
8
|
+
} from "./chunk-QFMHNGLB.js";
|
|
9
|
+
export {
|
|
10
|
+
ApiSwitchError,
|
|
11
|
+
UnsupportedFeatureError,
|
|
12
|
+
convertSAPErrorToAPICallError,
|
|
13
|
+
convertToAISDKError,
|
|
14
|
+
normalizeHeaders
|
|
15
|
+
};
|
|
16
|
+
//# sourceMappingURL=sap-ai-error-UPKYWPSS.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jerome-benoit/sap-ai-provider-v2",
|
|
3
|
-
"version": "5.0
|
|
3
|
+
"version": "5.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "SAP AI Provider for Vercel AI SDK (LanguageModelV2/EmbeddingModelV2 interfaces)",
|
|
6
6
|
"keywords": [
|
|
@@ -29,8 +29,17 @@
|
|
|
29
29
|
},
|
|
30
30
|
"license": "Apache-2.0",
|
|
31
31
|
"author": "jerome-benoit",
|
|
32
|
-
"
|
|
33
|
-
"
|
|
32
|
+
"devEngines": {
|
|
33
|
+
"runtime": {
|
|
34
|
+
"name": "node",
|
|
35
|
+
"version": "24.22.2",
|
|
36
|
+
"onFail": "ignore"
|
|
37
|
+
},
|
|
38
|
+
"packageManager": {
|
|
39
|
+
"name": "npm",
|
|
40
|
+
"version": ">=11.16.0",
|
|
41
|
+
"onFail": "error"
|
|
42
|
+
}
|
|
34
43
|
},
|
|
35
44
|
"main": "./dist/index.cjs",
|
|
36
45
|
"module": "./dist/index.js",
|
|
@@ -61,65 +70,96 @@
|
|
|
61
70
|
"build:watch": "tsup --watch",
|
|
62
71
|
"build:v2": "tsup --config tsup.config.v2.ts",
|
|
63
72
|
"build:v2:watch": "tsup --config tsup.config.v2.ts --watch",
|
|
64
|
-
"check-build": "
|
|
65
|
-
"check-build:v2": "
|
|
66
|
-
"check-build:v4": "
|
|
73
|
+
"check-build": "tsx scripts/check-build-artifacts.ts main && tsx scripts/check-package-exports.ts",
|
|
74
|
+
"check-build:v2": "tsx scripts/check-build-artifacts.ts v2",
|
|
75
|
+
"check-build:v4": "tsx scripts/check-build-artifacts.ts v4",
|
|
76
|
+
"check-dependency-audit": "tsx scripts/check-dependency-audit.ts",
|
|
77
|
+
"check-lockfile-release-age": "node scripts/check-lockfile-release-age.mjs",
|
|
67
78
|
"clean": "rm -rf dist",
|
|
68
79
|
"lint": "npm run lint:md:all && eslint . --cache",
|
|
69
80
|
"lint-fix": "npm run lint:md:fix && eslint . --fix --cache",
|
|
70
81
|
"lint:md": "markdownlint-cli2 '**/*.md'",
|
|
71
82
|
"lint:md:all": "npm run lint:md && npm run lint:md:toc && npm run lint:md:mermaid",
|
|
72
83
|
"lint:md:fix": "markdownlint-cli2 --fix '**/*.md'",
|
|
73
|
-
"lint:md:links": "
|
|
84
|
+
"lint:md:links": "tsx scripts/check-markdown-links.ts",
|
|
74
85
|
"lint:md:mermaid": "find . -name '*.md' -not -path './node_modules/*' -exec sh -c 'status=0; for file; do mermaid-validate validate-md \"$file\" || status=1; done; exit \"$status\"' sh {} +",
|
|
75
86
|
"lint:md:toc": "tsx scripts/check-toc.ts",
|
|
76
87
|
"prepare:v2": "tsx scripts/prepare-v2-package.ts",
|
|
77
88
|
"prepublishOnly": "if [ \"$AI_SDK_VERSION\" = \"v2\" ]; then npm run build:v2 && npm run check-build:v2 && npm run prepare:v2 && tsx scripts/check-package-exports.ts; else npm run build && npm run check-build; fi",
|
|
78
89
|
"prettier-check": "prettier --cache --check .",
|
|
79
90
|
"prettier-fix": "prettier --cache --write .",
|
|
80
|
-
"test": "
|
|
91
|
+
"test": "npm run test:node",
|
|
81
92
|
"test:coverage": "vitest --config vitest.node.config.ts --run --coverage",
|
|
82
93
|
"test:edge": "vitest --config vitest.edge.config.ts --run",
|
|
83
94
|
"test:node": "vitest --config vitest.node.config.ts --run",
|
|
84
95
|
"test:node:watch": "vitest --config vitest.node.config.ts",
|
|
85
|
-
"test:watch": "
|
|
96
|
+
"test:watch": "npm run test:node:watch",
|
|
86
97
|
"type-check": "tsc --noEmit"
|
|
87
98
|
},
|
|
88
99
|
"dependencies": {
|
|
89
|
-
"@ai-sdk/
|
|
90
|
-
"@ai-sdk/provider
|
|
91
|
-
"@
|
|
92
|
-
"@sap-ai-sdk/
|
|
93
|
-
"@sap-ai-sdk/
|
|
94
|
-
"@sap-ai-sdk/
|
|
100
|
+
"@ai-sdk/openai": "^4.0.105",
|
|
101
|
+
"@ai-sdk/provider": "^4.0.34",
|
|
102
|
+
"@ai-sdk/provider-utils": "^5.0.71",
|
|
103
|
+
"@sap-ai-sdk/ai-api": "^2.17.0",
|
|
104
|
+
"@sap-ai-sdk/core": "^2.17.0",
|
|
105
|
+
"@sap-ai-sdk/foundation-models": "^2.17.0",
|
|
106
|
+
"@sap-ai-sdk/orchestration": "^2.17.0",
|
|
95
107
|
"@sap-cloud-sdk/connectivity": "^4.9.1",
|
|
96
108
|
"@sap-cloud-sdk/util": "^4.9.1",
|
|
97
|
-
"zod": "^4.6.
|
|
109
|
+
"zod": "^4.6.7"
|
|
98
110
|
},
|
|
99
111
|
"devDependencies": {
|
|
100
|
-
"@ai-sdk/provider-v2": "npm:@ai-sdk/provider
|
|
101
|
-
"@
|
|
102
|
-
"@
|
|
103
|
-
"@
|
|
104
|
-
"@
|
|
105
|
-
"
|
|
106
|
-
"
|
|
107
|
-
"
|
|
108
|
-
"eslint
|
|
109
|
-
"eslint-plugin-
|
|
110
|
-
"
|
|
111
|
-
"
|
|
112
|
-
"
|
|
113
|
-
"
|
|
114
|
-
"
|
|
115
|
-
"
|
|
116
|
-
"
|
|
117
|
-
"
|
|
118
|
-
"
|
|
119
|
-
"
|
|
120
|
-
"
|
|
121
|
-
"
|
|
122
|
-
"
|
|
112
|
+
"@ai-sdk/provider-v2": "npm:@ai-sdk/provider@2.0.5",
|
|
113
|
+
"@ai-sdk/provider-v3": "npm:@ai-sdk/provider@3.0.19",
|
|
114
|
+
"@edge-runtime/vm": "5.0.0",
|
|
115
|
+
"@eslint/js": "10.0.1",
|
|
116
|
+
"@types/node": "24.19.2",
|
|
117
|
+
"@vitest/coverage-v8": "5.0.5",
|
|
118
|
+
"ai": "7.0.157",
|
|
119
|
+
"dotenv": "18.0.9",
|
|
120
|
+
"eslint": "10.13.0",
|
|
121
|
+
"eslint-plugin-jsdoc": "65.4.2",
|
|
122
|
+
"eslint-plugin-perfectionist": "5.13.0",
|
|
123
|
+
"github-slugger": "2.0.0",
|
|
124
|
+
"globals": "17.13.0",
|
|
125
|
+
"lefthook": "2.2.2",
|
|
126
|
+
"link-check": "5.6.0",
|
|
127
|
+
"markdown-it": "15.0.3",
|
|
128
|
+
"markdownlint-cli2": "0.24.0",
|
|
129
|
+
"mermaid-validate": "1.3.2",
|
|
130
|
+
"parse5": "8.0.1",
|
|
131
|
+
"prettier": "3.9.10",
|
|
132
|
+
"tsup": "9.0.0",
|
|
133
|
+
"tsx": "4.23.15",
|
|
134
|
+
"typescript": "6.0.3",
|
|
135
|
+
"typescript-eslint": "8.72.1",
|
|
136
|
+
"vitest": "5.0.5"
|
|
137
|
+
},
|
|
138
|
+
"overrides": {
|
|
139
|
+
"@eslint/config-array": {
|
|
140
|
+
"minimatch@>=10.0.0 <11.0.0": ">=11.0.1 <12.0.0"
|
|
141
|
+
},
|
|
142
|
+
"@typescript-eslint/typescript-estree": {
|
|
143
|
+
"minimatch@>=10.0.0 <11.0.0": ">=11.0.1 <12.0.0"
|
|
144
|
+
},
|
|
145
|
+
"basic-ftp": ">=6.2.2 <7.0.0",
|
|
146
|
+
"esbuild": ">=0.28.2 <0.29.0",
|
|
147
|
+
"eslint": {
|
|
148
|
+
"minimatch@>=10.0.0 <11.0.0": ">=11.0.1 <12.0.0"
|
|
149
|
+
},
|
|
150
|
+
"katex": ">=0.18.2 <0.20.0",
|
|
151
|
+
"markdownlint": {
|
|
152
|
+
"re2js": ">=2.8.7 <3.0.0"
|
|
153
|
+
},
|
|
154
|
+
"markdownlint-cli2": {
|
|
155
|
+
"markdown-it": "15.0.3"
|
|
156
|
+
},
|
|
157
|
+
"smol-toml": ">=1.9.0 <2.0.0"
|
|
158
|
+
},
|
|
159
|
+
"allowScripts": {
|
|
160
|
+
"esbuild@0.28.2": true,
|
|
161
|
+
"fsevents@2.3.3": true,
|
|
162
|
+
"lefthook@2.2.2": true
|
|
123
163
|
},
|
|
124
164
|
"peerDependencies": {
|
|
125
165
|
"ai": "^5.0.0 || ^6.0.0"
|
|
@@ -1 +0,0 @@
|
|
|
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\";\nimport type { CustomRequestConfig } from \"@sap-ai-sdk/core\";\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 { getProviderName } from \"./sap-ai-provider-options.js\";\nimport {\n buildEmbeddingResult,\n type EmbeddingProviderOptions,\n type EmbeddingType,\n mergeRequestConfig,\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 if (values.length > maxEmbeddingsPerCall) {\n throw new TooManyEmbeddingValuesForCallError({\n maxEmbeddingsPerCall,\n modelId: config.modelId,\n provider: config.provider,\n values,\n });\n }\n const embeddingOptions = config.parsedProviderOptions;\n const providerName = getProviderName(config.provider);\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(\n client,\n values,\n embeddingType,\n mergeRequestConfig(config.requestConfig, abortSignal, options.headers),\n );\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 modelId: config.modelId,\n modelType: \"embeddingModel\",\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 requestConfig - Request configuration with merged headers and 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 requestConfig: CustomRequestConfig | 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":";;;;;;;;;;;;;AASA,SAAS,0CAA0C;AAuB5C,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,UAAI,OAAO,SAAS,sBAAsB;AACxC,cAAM,IAAI,mCAAmC;AAAA,UAC3C;AAAA,UACA,SAAS,OAAO;AAAA,UAChB,UAAU,OAAO;AAAA,UACjB;AAAA,QACF,CAAC;AAAA,MACH;AACA,YAAM,mBAAmB,OAAO;AAChC,YAAM,eAAe,gBAAgB,OAAO,QAAQ;AAEpD,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;AAAA,QAC1B;AAAA,QACA;AAAA,QACA;AAAA,QACA,mBAAmB,OAAO,eAAe,aAAa,QAAQ,OAAO;AAAA,MACvE;AAEA,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,SAAS,OAAO;AAAA,QAChB,WAAW;AAAA,QACX,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 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/strategy-utils.ts"],"sourcesContent":["/**\n * Shared utilities for SAP AI Core strategy implementations.\n */\nimport type {\n EmbeddingModelV3Embedding,\n EmbeddingModelV3Result,\n JSONArray,\n JSONObject,\n LanguageModelV3CallOptions,\n LanguageModelV3Content,\n LanguageModelV3FinishReason,\n LanguageModelV3FunctionTool,\n LanguageModelV3GenerateResult,\n LanguageModelV3ResponseMetadata,\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 { CustomRequestConfig } from \"@sap-ai-sdk/core\";\nimport type { ZodType } from \"zod\";\n\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 { 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\" } | { type: \"auto\" } | { type: \"none\" } | { type: \"required\" };\n\n/**\n * Anthropic prompt-cache breakdown surfaced via `providerMetadata[providerName].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 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 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 strict?: boolean | null;\n };\n type: \"function\";\n}\n\n/**\n * @internal\n */\nexport type SAPToolChoice =\n \"auto\" | \"none\" | \"required\" | { 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 responseMetadata?: LanguageModelV3ResponseMetadata;\n}\n\n/**\n * @internal\n */\nexport interface SDKStreamChunk {\n _data?: unknown;\n getCitations?(): SDKCitation[] | undefined;\n getDeltaContent(): null | string | undefined;\n getDeltaToolCalls(): null | SDKDeltaToolCall[] | undefined;\n getFinishReason(): null | string | undefined;\n getTokenUsage?(): SDKTokenUsage | 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 { providerName, requestBody, requestId, response, responseHeaders, version, warnings } =\n config;\n\n const content: LanguageModelV3Content[] = [];\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 if (textContent) content.push({ text: textContent, type: \"text\" });\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 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 ...response.responseMetadata,\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 ...(functionTool.strict !== undefined ? { strict: functionTool.strict } : {}),\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 * Reads server completion metadata from the public HTTP payload or a stream chunk.\n * @param response - SAP SDK response or chunk.\n * @param response._data - Parsed payload exposed by stream chunks.\n * @param response.getRequestId - Optional SAP request-ID accessor.\n * @param response.rawResponse - Public HTTP response when available.\n * @param response.rawResponse.data - Parsed HTTP response payload.\n * @param dataPath - Path to the completion object within the payload.\n * @returns Server metadata, with the existing request-ID fallback when no completion ID is sent.\n * @internal\n */\nexport function extractCompletionMetadata(\n response: {\n _data?: unknown;\n getRequestId?: () => string | undefined;\n rawResponse?: { data?: unknown };\n },\n dataPath: readonly string[],\n): LanguageModelV3ResponseMetadata {\n let cursor: unknown;\n try {\n cursor = response.rawResponse?.data;\n } catch {\n // Chunk wrappers and older SDK stream constructors may not expose an HTTP response.\n }\n cursor ??= 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 const metadata: LanguageModelV3ResponseMetadata = {};\n if (cursor !== null && typeof cursor === \"object\") {\n const data = cursor as Record<string, unknown>;\n if (typeof data.id === \"string\" && data.id.length > 0) metadata.id = data.id;\n if (typeof data.model === \"string\" && data.model.length > 0) metadata.modelId = data.model;\n if (typeof data.created === \"number\" && Number.isFinite(data.created)) {\n const timestamp = new Date(data.created * 1000);\n if (Number.isFinite(timestamp.getTime())) metadata.timestamp = timestamp;\n }\n }\n if (metadata.id === undefined && typeof response.getRequestId === \"function\") {\n try {\n const id = response.getRequestId();\n if (typeof id === \"string\" && id.length > 0) metadata.id = id;\n } catch {\n // A request ID is optional and can be unavailable before stream consumption.\n }\n }\n return metadata;\n}\n\n/**\n * Extracts the request id and normalised headers from an SDK response.\n *\n * Resolves `requestId` from `getRequestId()`, then an orchestration chunk's\n * `_data.request_id`, then the `x-request-id` header. Tolerates absent/non-callable\n * accessors and throwing header accessors. `field` selects the underlying wrapper:\n * `response` for orchestration embeddings, `rawResponse` for other SDK responses.\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 if (requestId === undefined) {\n const data = (response as null | { _data?: { request_id?: unknown } })?._data;\n if (typeof data?.request_id === \"string\" && data.request_id.length > 0) {\n requestId = data.request_id;\n }\n }\n\n let rawHeaders: unknown;\n try {\n const wrapper = (response as null | Record<string, unknown>)?.[field] as\n undefined | { 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) {\n return { parameters: buildSAPToolParameters(inputSchema) };\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 tokenUsage?.completion_tokens == null\n ? undefined\n : Math.max(0, tokenUsage.completion_tokens - (reasoningTokens ?? 0)),\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 * Merges provider-level `requestConfig` with per-call cancellation and HTTP headers.\n *\n * The AI SDK `abortSignal` always wins: any `signal` present on `requestConfig` is\n * dropped so callers cannot accidentally bypass the abort contract described in the\n * JSDoc of `SAPAIProviderSettings.requestConfig`. Defined per-call headers override\n * provider headers case-insensitively; undefined values leave defaults intact.\n * @param requestConfig - Provider-level custom request configuration.\n * @param abortSignal - Per-call abort signal from the AI SDK.\n * @param headers - Additional per-call HTTP headers.\n * @returns Merged configuration, or `undefined` when there is nothing to forward.\n * @internal\n */\nexport function mergeRequestConfig(\n requestConfig: CustomRequestConfig | undefined,\n abortSignal: AbortSignal | undefined,\n headers?: Record<string, string | undefined>,\n): CustomRequestConfig | undefined {\n const { signal: _dropped, ...rest } = requestConfig ?? {};\n const callHeaders = normalizeHeaders(headers);\n if (callHeaders) {\n const providerHeaders = Object.fromEntries(\n Object.entries(rest.headers ?? {}).map(([key, value]) => [key.toLowerCase(), value]),\n );\n rest.headers = { ...providerHeaders, ...callHeaders };\n }\n if (abortSignal) return { ...rest, signal: abortSignal };\n return Object.keys(rest).length > 0 ? rest : undefined;\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\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"],"mappings":"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","names":[]}
|
|
@@ -1 +0,0 @@
|
|
|
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 * - `streamOptions` - Post-LLM module streaming configuration\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 - Language model settings to validate for conflicts.\n * @param embeddingSettings - Embedding 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 embeddingSettings: SAPAIEmbeddingSettings | undefined,\n): void {\n if (fromApi === toApi) return;\n if (!modelSettings && !embeddingSettings) return;\n\n if (fromApi === \"orchestration\" && toApi === \"foundation-models\") {\n const orchSettings = modelSettings as OrchestrationModelSettings | undefined;\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 for (const feature of ORCHESTRATION_ONLY_EMBEDDING_FEATURE_KEYS) {\n if (embeddingSettings?.[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 | undefined;\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(\n effectiveModelApi,\n invocationSettings.api,\n modelSettings,\n embeddingSettings,\n );\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":[]}
|