@jerome-benoit/sap-ai-provider 4.2.2 → 4.2.4

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/dist/index.cjs CHANGED
@@ -14141,7 +14141,7 @@ var require_cloud_sdk_logger = __commonJS({
14141
14141
  exports2.createLogger = createLogger;
14142
14142
  exports2.getLogger = getLogger;
14143
14143
  exports2.setLogLevel = setLogLevel;
14144
- exports2.setGlobalLogLevel = setGlobalLogLevel;
14144
+ exports2.setGlobalLogLevel = setGlobalLogLevel2;
14145
14145
  exports2.getGlobalLogLevel = getGlobalLogLevel;
14146
14146
  exports2.setGlobalTransports = setGlobalTransports;
14147
14147
  exports2.setLogFormat = setLogFormat;
@@ -14228,7 +14228,7 @@ var require_cloud_sdk_logger = __commonJS({
14228
14228
  messageContextOrLogger.level = level;
14229
14229
  }
14230
14230
  }
14231
- function setGlobalLogLevel(level) {
14231
+ function setGlobalLogLevel2(level) {
14232
14232
  container.options.level = level;
14233
14233
  container.loggers.forEach((logger) => {
14234
14234
  logger.level = level;
@@ -29743,6 +29743,7 @@ __export(index_exports, {
29743
29743
  OrchestrationStreamChunkResponse: () => import_orchestration4.OrchestrationStreamChunkResponse,
29744
29744
  OrchestrationStreamResponse: () => import_orchestration4.OrchestrationStreamResponse,
29745
29745
  SAPAIEmbeddingModel: () => SAPAIEmbeddingModel,
29746
+ SAPAILanguageModel: () => SAPAILanguageModel,
29746
29747
  SAP_AI_PROVIDER_NAME: () => SAP_AI_PROVIDER_NAME,
29747
29748
  buildAzureContentSafetyFilter: () => import_orchestration3.buildAzureContentSafetyFilter,
29748
29749
  buildDocumentGroundingConfig: () => import_orchestration3.buildDocumentGroundingConfig,
@@ -29751,7 +29752,6 @@ __export(index_exports, {
29751
29752
  buildTranslationConfig: () => import_orchestration3.buildTranslationConfig,
29752
29753
  createSAPAIProvider: () => createSAPAIProvider,
29753
29754
  getProviderName: () => getProviderName,
29754
- isConfigReference: () => import_orchestration3.isConfigReference,
29755
29755
  sapAIEmbeddingProviderOptions: () => sapAIEmbeddingProviderOptions,
29756
29756
  sapAILanguageModelProviderOptions: () => sapAILanguageModelProviderOptions,
29757
29757
  sapai: () => sapai
@@ -29932,46 +29932,45 @@ function convertToAISDKError(error, context) {
29932
29932
  });
29933
29933
  }
29934
29934
  }
29935
- const responseHeaders = context?.responseHeaders ?? getAxiosResponseHeaders(error);
29936
29935
  if (rootError instanceof Error) {
29937
29936
  const errorMsg = rootError.message.toLowerCase();
29938
- const originalMsg = rootError.message;
29937
+ const originalErrorMsg = rootError.message;
29939
29938
  if (errorMsg.includes("authentication") || errorMsg.includes("unauthorized") || errorMsg.includes("aicore_service_key") || errorMsg.includes("invalid credentials") || errorMsg.includes("service credentials") || errorMsg.includes("service binding")) {
29940
29939
  return new import_provider.LoadAPIKeyError({
29941
- message: `SAP AI Core authentication failed: ${originalMsg}
29940
+ message: `SAP AI Core authentication failed: ${originalErrorMsg}
29942
29941
 
29943
29942
  Make sure your AICORE_SERVICE_KEY environment variable is set correctly.
29944
29943
  See: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-service-key`
29945
29944
  });
29946
29945
  }
29947
29946
  if (errorMsg.includes("econnrefused") || errorMsg.includes("enotfound") || errorMsg.includes("network") || errorMsg.includes("timeout")) {
29948
- return new import_provider.APICallError({
29949
- cause: error,
29950
- isRetryable: true,
29951
- message: `Network error connecting to SAP AI Core: ${originalMsg}`,
29952
- requestBodyValues: context?.requestBody,
29953
- responseHeaders,
29954
- statusCode: HTTP_STATUS.SERVICE_UNAVAILABLE,
29955
- url: context?.url ?? ""
29956
- });
29947
+ return createAPICallError(
29948
+ error,
29949
+ {
29950
+ isRetryable: true,
29951
+ message: `Network error connecting to SAP AI Core: ${originalErrorMsg}`,
29952
+ statusCode: HTTP_STATUS.SERVICE_UNAVAILABLE
29953
+ },
29954
+ context
29955
+ );
29957
29956
  }
29958
29957
  if (errorMsg.includes("could not resolve destination")) {
29959
- return new import_provider.APICallError({
29960
- cause: error,
29961
- isRetryable: false,
29962
- message: `SAP AI Core destination error: ${originalMsg}
29958
+ return createAPICallError(
29959
+ error,
29960
+ {
29961
+ isRetryable: false,
29962
+ message: `SAP AI Core destination error: ${originalErrorMsg}
29963
29963
 
29964
29964
  Check your destination configuration or provide a valid destinationName.`,
29965
- requestBodyValues: context?.requestBody,
29966
- responseHeaders,
29967
- statusCode: HTTP_STATUS.BAD_REQUEST,
29968
- url: context?.url ?? ""
29969
- });
29965
+ statusCode: HTTP_STATUS.BAD_REQUEST
29966
+ },
29967
+ context
29968
+ );
29970
29969
  }
29971
29970
  if (errorMsg.includes("failed to resolve deployment") || errorMsg.includes("no deployment matched")) {
29972
- const modelId = extractModelIdentifier(originalMsg);
29971
+ const modelId = extractModelIdentifier(originalErrorMsg);
29973
29972
  return new import_provider.NoSuchModelError({
29974
- message: `SAP AI Core deployment error: ${originalMsg}
29973
+ message: `SAP AI Core deployment error: ${originalErrorMsg}
29975
29974
 
29976
29975
  Make sure you have a running orchestration deployment in your AI Core instance.
29977
29976
  See: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-deployment-for-orchestration`,
@@ -29980,129 +29979,165 @@ See: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-depl
29980
29979
  });
29981
29980
  }
29982
29981
  if (errorMsg.includes("filtered by the output filter")) {
29983
- return new import_provider.APICallError({
29984
- cause: error,
29985
- isRetryable: false,
29986
- message: `Content was filtered: ${originalMsg}
29982
+ return createAPICallError(
29983
+ error,
29984
+ {
29985
+ isRetryable: false,
29986
+ message: `Content was filtered: ${originalErrorMsg}
29987
29987
 
29988
29988
  The model's response was blocked by content safety filters. Try a different prompt.`,
29989
- requestBodyValues: context?.requestBody,
29990
- responseHeaders,
29991
- statusCode: HTTP_STATUS.BAD_REQUEST,
29992
- url: context?.url ?? ""
29993
- });
29989
+ statusCode: HTTP_STATUS.BAD_REQUEST
29990
+ },
29991
+ context
29992
+ );
29994
29993
  }
29995
- const statusMatch = /status code (\d+)/i.exec(originalMsg);
29994
+ const statusMatch = /status code (\d+)/i.exec(originalErrorMsg);
29996
29995
  if (statusMatch) {
29997
29996
  const extractedStatus = Number.parseInt(statusMatch[1], 10);
29998
- return new import_provider.APICallError({
29999
- cause: error,
30000
- isRetryable: isRetryable(extractedStatus),
30001
- message: `SAP AI Core request failed: ${originalMsg}`,
30002
- requestBodyValues: context?.requestBody,
30003
- responseHeaders,
30004
- statusCode: extractedStatus,
30005
- url: context?.url ?? ""
30006
- });
29997
+ return createAPICallError(
29998
+ error,
29999
+ {
30000
+ isRetryable: isRetryable(extractedStatus),
30001
+ message: `SAP AI Core request failed: ${originalErrorMsg}`,
30002
+ statusCode: extractedStatus
30003
+ },
30004
+ context
30005
+ );
30007
30006
  }
30008
30007
  if (errorMsg.includes("consumed stream")) {
30009
- return new import_provider.APICallError({
30010
- cause: error,
30011
- isRetryable: false,
30012
- message: `SAP AI Core stream consumption error: ${originalMsg}`,
30013
- requestBodyValues: context?.requestBody,
30014
- responseHeaders,
30015
- statusCode: HTTP_STATUS.INTERNAL_ERROR,
30016
- url: context?.url ?? ""
30017
- });
30008
+ return createAPICallError(
30009
+ error,
30010
+ {
30011
+ isRetryable: false,
30012
+ message: `SAP AI Core stream consumption error: ${originalErrorMsg}`,
30013
+ statusCode: HTTP_STATUS.INTERNAL_ERROR
30014
+ },
30015
+ context
30016
+ );
30018
30017
  }
30019
30018
  if (errorMsg.includes("iterating over") || errorMsg.includes("parse message into json") || errorMsg.includes("received from") || errorMsg.includes("no body") || errorMsg.includes("invalid sse payload")) {
30020
- return new import_provider.APICallError({
30021
- cause: error,
30022
- isRetryable: true,
30023
- message: `SAP AI Core streaming error: ${originalMsg}`,
30024
- requestBodyValues: context?.requestBody,
30025
- responseHeaders,
30026
- statusCode: HTTP_STATUS.INTERNAL_ERROR,
30027
- url: context?.url ?? ""
30028
- });
30019
+ return createAPICallError(
30020
+ error,
30021
+ {
30022
+ isRetryable: true,
30023
+ message: `SAP AI Core streaming error: ${originalErrorMsg}`,
30024
+ statusCode: HTTP_STATUS.INTERNAL_ERROR
30025
+ },
30026
+ context
30027
+ );
30029
30028
  }
30030
30029
  if (errorMsg.includes("prompt template or messages must be defined") || errorMsg.includes("filtering parameters cannot be empty") || errorMsg.includes("templating yaml string must be non-empty") || errorMsg.includes("could not access response data") || errorMsg.includes("could not parse json") || errorMsg.includes("error parsing yaml") || errorMsg.includes("yaml does not conform") || errorMsg.includes("validation errors")) {
30031
- return new import_provider.APICallError({
30032
- cause: error,
30033
- isRetryable: false,
30034
- message: `SAP AI Core configuration error: ${originalMsg}`,
30035
- requestBodyValues: context?.requestBody,
30036
- responseHeaders,
30037
- statusCode: HTTP_STATUS.BAD_REQUEST,
30038
- url: context?.url ?? ""
30039
- });
30030
+ return createAPICallError(
30031
+ error,
30032
+ {
30033
+ isRetryable: false,
30034
+ message: `SAP AI Core configuration error: ${originalErrorMsg}`,
30035
+ statusCode: HTTP_STATUS.BAD_REQUEST
30036
+ },
30037
+ context
30038
+ );
30040
30039
  }
30041
30040
  if (errorMsg.includes("buffer is not available as globals")) {
30042
- return new import_provider.APICallError({
30043
- cause: error,
30044
- isRetryable: false,
30045
- message: `SAP AI Core environment error: ${originalMsg}`,
30046
- requestBodyValues: context?.requestBody,
30047
- responseHeaders,
30048
- statusCode: HTTP_STATUS.INTERNAL_ERROR,
30049
- url: context?.url ?? ""
30050
- });
30041
+ return createAPICallError(
30042
+ error,
30043
+ {
30044
+ isRetryable: false,
30045
+ message: `SAP AI Core environment error: ${originalErrorMsg}`,
30046
+ statusCode: HTTP_STATUS.INTERNAL_ERROR
30047
+ },
30048
+ context
30049
+ );
30051
30050
  }
30052
30051
  if (errorMsg.includes("response stream is undefined")) {
30053
- return new import_provider.APICallError({
30054
- cause: error,
30055
- isRetryable: false,
30056
- message: `SAP AI Core response stream error: ${originalMsg}`,
30057
- requestBodyValues: context?.requestBody,
30058
- responseHeaders,
30059
- statusCode: HTTP_STATUS.INTERNAL_ERROR,
30060
- url: context?.url ?? ""
30061
- });
30052
+ return createAPICallError(
30053
+ error,
30054
+ {
30055
+ isRetryable: false,
30056
+ message: `SAP AI Core response stream error: ${originalErrorMsg}`,
30057
+ statusCode: HTTP_STATUS.INTERNAL_ERROR
30058
+ },
30059
+ context
30060
+ );
30062
30061
  }
30063
30062
  if (errorMsg.includes("response is required to process") || errorMsg.includes("stream is still open") || errorMsg.includes("data is not available yet")) {
30064
- return new import_provider.APICallError({
30065
- cause: error,
30066
- isRetryable: true,
30067
- message: `SAP AI Core response processing error: ${originalMsg}`,
30068
- requestBodyValues: context?.requestBody,
30069
- responseHeaders,
30070
- statusCode: HTTP_STATUS.INTERNAL_ERROR,
30071
- url: context?.url ?? ""
30072
- });
30063
+ return createAPICallError(
30064
+ error,
30065
+ {
30066
+ isRetryable: true,
30067
+ message: `SAP AI Core response processing error: ${originalErrorMsg}`,
30068
+ statusCode: HTTP_STATUS.INTERNAL_ERROR
30069
+ },
30070
+ context
30071
+ );
30073
30072
  }
30074
30073
  if (errorMsg.includes("failed to fetch the list of deployments")) {
30075
- return new import_provider.APICallError({
30076
- cause: error,
30077
- isRetryable: true,
30078
- message: `SAP AI Core deployment retrieval error: ${originalMsg}`,
30079
- requestBodyValues: context?.requestBody,
30080
- responseHeaders,
30081
- statusCode: HTTP_STATUS.SERVICE_UNAVAILABLE,
30082
- url: context?.url ?? ""
30083
- });
30074
+ return createAPICallError(
30075
+ error,
30076
+ {
30077
+ isRetryable: true,
30078
+ message: `SAP AI Core deployment retrieval error: ${originalErrorMsg}`,
30079
+ statusCode: HTTP_STATUS.SERVICE_UNAVAILABLE
30080
+ },
30081
+ context
30082
+ );
30084
30083
  }
30085
30084
  if (errorMsg.includes("received non-uint8array")) {
30086
- return new import_provider.APICallError({
30087
- cause: error,
30088
- isRetryable: false,
30089
- message: `SAP AI Core stream buffer error: ${originalMsg}`,
30090
- requestBodyValues: context?.requestBody,
30091
- responseHeaders,
30092
- statusCode: HTTP_STATUS.INTERNAL_ERROR,
30093
- url: context?.url ?? ""
30094
- });
30085
+ return createAPICallError(
30086
+ error,
30087
+ {
30088
+ isRetryable: false,
30089
+ message: `SAP AI Core stream buffer error: ${originalErrorMsg}`,
30090
+ statusCode: HTTP_STATUS.INTERNAL_ERROR
30091
+ },
30092
+ context
30093
+ );
30095
30094
  }
30096
30095
  }
30097
30096
  const message = rootError instanceof Error ? rootError.message : typeof rootError === "string" ? rootError : "Unknown error occurred";
30098
30097
  const fullMessage = context?.operation ? `SAP AI Core ${context.operation} failed: ${message}` : `SAP AI Core error: ${message}`;
30098
+ return createAPICallError(
30099
+ error,
30100
+ {
30101
+ isRetryable: false,
30102
+ message: fullMessage,
30103
+ statusCode: HTTP_STATUS.INTERNAL_ERROR
30104
+ },
30105
+ context
30106
+ );
30107
+ }
30108
+ function normalizeHeaders(headers) {
30109
+ if (!headers || typeof headers !== "object") return void 0;
30110
+ const record = headers;
30111
+ const entries = Object.entries(record).flatMap(([key, value]) => {
30112
+ if (typeof value === "string") return [[key, value]];
30113
+ if (Array.isArray(value)) {
30114
+ const strings = value.filter((item) => typeof item === "string").join("; ");
30115
+ return strings.length > 0 ? [[key, strings]] : [];
30116
+ }
30117
+ if (typeof value === "number" || typeof value === "boolean") {
30118
+ return [[key, String(value)]];
30119
+ }
30120
+ return [];
30121
+ });
30122
+ if (entries.length === 0) return void 0;
30123
+ return Object.fromEntries(entries);
30124
+ }
30125
+ function createAPICallError(error, options, context) {
30126
+ const responseBody = getAxiosResponseBody(error);
30127
+ const responseHeaders = context?.responseHeaders ?? getAxiosResponseHeaders(error);
30128
+ const enrichMessage = options.enrichMessage ?? true;
30129
+ const message = enrichMessage && responseBody ? `${options.message}
30130
+
30131
+ SAP AI Core Error Response:
30132
+ ${responseBody}` : options.message;
30099
30133
  return new import_provider.APICallError({
30100
30134
  cause: error,
30101
- isRetryable: false,
30102
- message: fullMessage,
30135
+ isRetryable: options.isRetryable,
30136
+ message,
30103
30137
  requestBodyValues: context?.requestBody,
30138
+ responseBody,
30104
30139
  responseHeaders,
30105
- statusCode: HTTP_STATUS.INTERNAL_ERROR,
30140
+ statusCode: options.statusCode,
30106
30141
  url: context?.url ?? ""
30107
30142
  });
30108
30143
  }
@@ -30126,13 +30161,23 @@ function extractModelIdentifier(message, location) {
30126
30161
  }
30127
30162
  return void 0;
30128
30163
  }
30129
- function getAxiosResponseHeaders(error) {
30164
+ function getAxiosError(error) {
30130
30165
  if (!(error instanceof Error)) return void 0;
30131
30166
  const rootCause = (0, import_util.isErrorWithCause)(error) ? error.rootCause : error;
30132
- if (typeof rootCause !== "object") return void 0;
30167
+ if (typeof rootCause !== "object" || rootCause === null) return void 0;
30133
30168
  const maybeAxios = rootCause;
30134
30169
  if (maybeAxios.isAxiosError !== true) return void 0;
30135
- return normalizeHeaders(maybeAxios.response?.headers);
30170
+ return maybeAxios;
30171
+ }
30172
+ function getAxiosResponseBody(error) {
30173
+ const axiosError = getAxiosError(error);
30174
+ if (!axiosError?.response?.data) return void 0;
30175
+ return serializeAxiosResponseData(axiosError.response.data);
30176
+ }
30177
+ function getAxiosResponseHeaders(error) {
30178
+ const axiosError = getAxiosError(error);
30179
+ if (!axiosError) return void 0;
30180
+ return normalizeHeaders(axiosError.response?.headers);
30136
30181
  }
30137
30182
  function getStatusCodeFromSAPError(code) {
30138
30183
  if (!code) return HTTP_STATUS.INTERNAL_ERROR;
@@ -30178,22 +30223,22 @@ function isOrchestrationErrorResponse(error) {
30178
30223
  function isRetryable(statusCode) {
30179
30224
  return statusCode === HTTP_STATUS.REQUEST_TIMEOUT || statusCode === HTTP_STATUS.CONFLICT || statusCode === HTTP_STATUS.RATE_LIMIT || statusCode >= HTTP_STATUS.INTERNAL_ERROR && statusCode < 600;
30180
30225
  }
30181
- function normalizeHeaders(headers) {
30182
- if (!headers || typeof headers !== "object") return void 0;
30183
- const record = headers;
30184
- const entries = Object.entries(record).flatMap(([key, value]) => {
30185
- if (typeof value === "string") return [[key, value]];
30186
- if (Array.isArray(value)) {
30187
- const strings = value.filter((item) => typeof item === "string").join("; ");
30188
- return strings.length > 0 ? [[key, strings]] : [];
30189
- }
30190
- if (typeof value === "number" || typeof value === "boolean") {
30191
- return [[key, String(value)]];
30226
+ function serializeAxiosResponseData(data, maxLength = 2e3) {
30227
+ if (data === void 0) return void 0;
30228
+ let serialized;
30229
+ try {
30230
+ if (typeof data === "string") {
30231
+ serialized = data;
30232
+ } else {
30233
+ serialized = JSON.stringify(data, null, 2);
30192
30234
  }
30193
- return [];
30194
- });
30195
- if (entries.length === 0) return void 0;
30196
- return Object.fromEntries(entries);
30235
+ } catch {
30236
+ serialized = `[Unable to serialize: ${typeof data}]`;
30237
+ }
30238
+ if (serialized.length > maxLength) {
30239
+ return serialized.slice(0, maxLength) + "...[truncated]";
30240
+ }
30241
+ return serialized;
30197
30242
  }
30198
30243
  function tryExtractSAPErrorFromMessage(message) {
30199
30244
  const jsonMatch = /\{[\s\S]*\}/.exec(message);
@@ -30299,6 +30344,14 @@ var SAPAIEmbeddingModel = class {
30299
30344
  supportsParallelCalls = true;
30300
30345
  config;
30301
30346
  settings;
30347
+ /**
30348
+ * Creates a new SAP AI Embedding Model instance.
30349
+ *
30350
+ * This is the main implementation that handles all SAP AI Core embedding logic.
30351
+ * @param modelId - The model identifier (e.g., 'text-embedding-ada-002', 'text-embedding-3-small').
30352
+ * @param settings - Model configuration settings (embedding type, model parameters, etc.).
30353
+ * @param config - SAP AI Core deployment and destination configuration.
30354
+ */
30302
30355
  constructor(modelId, settings = {}, config) {
30303
30356
  if (settings.modelParams) {
30304
30357
  validateEmbeddingModelParamsSettings(settings.modelParams);
@@ -30311,8 +30364,10 @@ var SAPAIEmbeddingModel = class {
30311
30364
  }
30312
30365
  /**
30313
30366
  * Generates embeddings for the given input values.
30314
- * @param options - The Vercel AI SDK embedding call options.
30315
- * @returns The embedding result with vectors and usage data.
30367
+ *
30368
+ * Validates input count, merges settings, calls SAP AI SDK, and normalizes embeddings.
30369
+ * @param options - The Vercel AI SDK V3 embedding call options.
30370
+ * @returns The embedding result with vectors, usage data, and warnings.
30316
30371
  */
30317
30372
  async doEmbed(options) {
30318
30373
  const { abortSignal, providerOptions, values } = options;
@@ -30403,9 +30458,6 @@ var SAPAIEmbeddingModel = class {
30403
30458
  }
30404
30459
  };
30405
30460
 
30406
- // src/sap-ai-provider.ts
30407
- var import_provider4 = require("@ai-sdk/provider");
30408
-
30409
30461
  // src/sap-ai-language-model.ts
30410
30462
  var import_provider_utils3 = require("@ai-sdk/provider-utils");
30411
30463
  var import_orchestration2 = require("@sap-ai-sdk/orchestration");
@@ -30576,6 +30628,20 @@ function convertToSAPMessages(prompt, options = {}) {
30576
30628
  }
30577
30629
 
30578
30630
  // src/sap-ai-language-model.ts
30631
+ var PARAM_MAPPINGS = [
30632
+ { camelCaseKey: "maxTokens", optionKey: "maxOutputTokens", outputKey: "max_tokens" },
30633
+ { camelCaseKey: "temperature", optionKey: "temperature", outputKey: "temperature" },
30634
+ { camelCaseKey: "topP", optionKey: "topP", outputKey: "top_p" },
30635
+ { camelCaseKey: "topK", optionKey: "topK", outputKey: "top_k" },
30636
+ {
30637
+ camelCaseKey: "frequencyPenalty",
30638
+ optionKey: "frequencyPenalty",
30639
+ outputKey: "frequency_penalty"
30640
+ },
30641
+ { camelCaseKey: "presencePenalty", optionKey: "presencePenalty", outputKey: "presence_penalty" },
30642
+ { camelCaseKey: "seed", optionKey: "seed", outputKey: "seed" },
30643
+ { camelCaseKey: "parallel_tool_calls", outputKey: "parallel_tool_calls" }
30644
+ ];
30579
30645
  var StreamIdGenerator = class {
30580
30646
  generateResponseId() {
30581
30647
  return crypto.randomUUID();
@@ -30623,8 +30689,10 @@ var SAPAILanguageModel = class {
30623
30689
  settings;
30624
30690
  /**
30625
30691
  * Creates a new SAP AI Language Model instance.
30626
- * @param modelId - The model identifier (e.g., 'gpt-4', 'claude-3').
30627
- * @param settings - Model configuration settings.
30692
+ *
30693
+ * This is the main implementation that handles all SAP AI Core orchestration logic.
30694
+ * @param modelId - The model identifier (e.g., 'gpt-4o', 'claude-3-5-sonnet', 'gemini-2.0-flash').
30695
+ * @param settings - Model configuration settings (temperature, max tokens, filtering, etc.).
30628
30696
  * @param config - SAP AI Core deployment and destination configuration.
30629
30697
  * @internal
30630
30698
  */
@@ -30638,83 +30706,23 @@ var SAPAILanguageModel = class {
30638
30706
  }
30639
30707
  /**
30640
30708
  * Generates a single completion (non-streaming).
30641
- * Note: Abort signal uses Promise.race; doesn't cancel underlying HTTP request.
30642
- * @param options - The Vercel AI SDK generation call options.
30643
- * @returns The generation result with content, usage, and provider metadata.
30709
+ *
30710
+ * Builds orchestration configuration, converts messages, validates parameters,
30711
+ * calls SAP AI SDK, and processes the response.
30712
+ * Supports request cancellation via AbortSignal at the HTTP transport layer.
30713
+ * @param options - The Vercel AI SDK V3 generation call options.
30714
+ * @returns The generation result with content, usage, warnings, and provider metadata.
30644
30715
  */
30645
30716
  async doGenerate(options) {
30646
30717
  try {
30647
30718
  const { messages, orchestrationConfig, warnings } = await this.buildOrchestrationConfig(options);
30648
30719
  const client = this.createClient(orchestrationConfig);
30649
- const promptTemplating = orchestrationConfig.promptTemplating;
30650
- const requestBody = {
30651
- messages,
30652
- model: {
30653
- ...orchestrationConfig.promptTemplating.model
30654
- },
30655
- ...promptTemplating.prompt.tools ? { tools: promptTemplating.prompt.tools } : {},
30656
- ...promptTemplating.prompt.response_format ? { response_format: promptTemplating.prompt.response_format } : {},
30657
- ...(() => {
30658
- const masking = orchestrationConfig.masking;
30659
- return masking && Object.keys(masking).length > 0 ? { masking } : {};
30660
- })(),
30661
- ...(() => {
30662
- const filtering = orchestrationConfig.filtering;
30663
- return filtering && Object.keys(filtering).length > 0 ? { filtering } : {};
30664
- })(),
30665
- ...(() => {
30666
- const grounding = orchestrationConfig.grounding;
30667
- return grounding && Object.keys(grounding).length > 0 ? { grounding } : {};
30668
- })(),
30669
- ...(() => {
30670
- const translation = orchestrationConfig.translation;
30671
- return translation && Object.keys(translation).length > 0 ? { translation } : {};
30672
- })()
30673
- };
30674
- const response = await (async () => {
30675
- const completionPromise = client.chatCompletion(requestBody);
30676
- if (options.abortSignal) {
30677
- return Promise.race([
30678
- completionPromise,
30679
- new Promise((_, reject) => {
30680
- if (options.abortSignal?.aborted) {
30681
- reject(
30682
- new Error(
30683
- `Request aborted: ${String(options.abortSignal.reason ?? "unknown reason")}`
30684
- )
30685
- );
30686
- return;
30687
- }
30688
- options.abortSignal?.addEventListener(
30689
- "abort",
30690
- () => {
30691
- reject(
30692
- new Error(
30693
- `Request aborted: ${String(options.abortSignal?.reason ?? "unknown reason")}`
30694
- )
30695
- );
30696
- },
30697
- { once: true }
30698
- );
30699
- })
30700
- ]);
30701
- }
30702
- return completionPromise;
30703
- })();
30704
- const responseHeadersRaw = response.rawResponse.headers;
30705
- const responseHeaders = responseHeadersRaw ? Object.fromEntries(
30706
- Object.entries(responseHeadersRaw).flatMap(([key, value]) => {
30707
- if (typeof value === "string") return [[key, value]];
30708
- if (Array.isArray(value)) {
30709
- const strings = value.filter((item) => typeof item === "string").join("; ");
30710
- return strings.length > 0 ? [[key, strings]] : [];
30711
- }
30712
- if (typeof value === "number" || typeof value === "boolean") {
30713
- return [[key, String(value)]];
30714
- }
30715
- return [];
30716
- })
30717
- ) : void 0;
30720
+ const requestBody = this.buildRequestBody(messages, orchestrationConfig);
30721
+ const response = await client.chatCompletion(
30722
+ requestBody,
30723
+ options.abortSignal ? { signal: options.abortSignal } : void 0
30724
+ );
30725
+ const responseHeaders = normalizeHeaders(response.rawResponse.headers);
30718
30726
  const content = [];
30719
30727
  const textContent = response.getContent();
30720
30728
  if (textContent) {
@@ -30788,31 +30796,18 @@ var SAPAILanguageModel = class {
30788
30796
  }
30789
30797
  /**
30790
30798
  * Generates a streaming completion.
30791
- * Note: Abort signal uses Promise.race; doesn't cancel underlying HTTP request.
30792
- * @param options - The Vercel AI SDK generation call options.
30799
+ *
30800
+ * Builds orchestration configuration, creates streaming client, and transforms
30801
+ * the stream with proper event handling (text blocks, tool calls, finish reason).
30802
+ * Supports request cancellation via AbortSignal at the HTTP transport layer.
30803
+ * @param options - The Vercel AI SDK V3 generation call options.
30793
30804
  * @returns A stream result with async iterable stream parts.
30794
30805
  */
30795
30806
  async doStream(options) {
30796
30807
  try {
30797
30808
  const { messages, orchestrationConfig, warnings } = await this.buildOrchestrationConfig(options);
30798
30809
  const client = this.createClient(orchestrationConfig);
30799
- const promptTemplating = orchestrationConfig.promptTemplating;
30800
- const requestBody = {
30801
- messages,
30802
- model: {
30803
- ...orchestrationConfig.promptTemplating.model
30804
- },
30805
- ...promptTemplating.prompt.tools ? { tools: promptTemplating.prompt.tools } : {},
30806
- ...promptTemplating.prompt.response_format ? { response_format: promptTemplating.prompt.response_format } : {},
30807
- ...(() => {
30808
- const masking = orchestrationConfig.masking;
30809
- return masking && Object.keys(masking).length > 0 ? { masking } : {};
30810
- })(),
30811
- ...(() => {
30812
- const filtering = orchestrationConfig.filtering;
30813
- return filtering && Object.keys(filtering).length > 0 ? { filtering } : {};
30814
- })()
30815
- };
30810
+ const requestBody = this.buildRequestBody(messages, orchestrationConfig);
30816
30811
  const streamResponse = await client.stream(requestBody, options.abortSignal, {
30817
30812
  promptTemplating: { include_usage: true }
30818
30813
  });
@@ -31167,20 +31162,14 @@ var SAPAILanguageModel = class {
31167
31162
  this.settings.modelParams ?? {},
31168
31163
  sapOptions?.modelParams ?? {}
31169
31164
  );
31170
- const maxTokens = options.maxOutputTokens ?? sapOptions?.modelParams?.maxTokens ?? this.settings.modelParams?.maxTokens;
31171
- if (maxTokens !== void 0) modelParams.max_tokens = maxTokens;
31172
- const temperature = options.temperature ?? sapOptions?.modelParams?.temperature ?? this.settings.modelParams?.temperature;
31173
- if (temperature !== void 0) modelParams.temperature = temperature;
31174
- const topP = options.topP ?? sapOptions?.modelParams?.topP ?? this.settings.modelParams?.topP;
31175
- if (topP !== void 0) modelParams.top_p = topP;
31176
- if (options.topK !== void 0) modelParams.top_k = options.topK;
31177
- const frequencyPenalty = options.frequencyPenalty ?? sapOptions?.modelParams?.frequencyPenalty ?? this.settings.modelParams?.frequencyPenalty;
31178
- if (frequencyPenalty !== void 0) {
31179
- modelParams.frequency_penalty = frequencyPenalty;
31180
- }
31181
- const presencePenalty = options.presencePenalty ?? sapOptions?.modelParams?.presencePenalty ?? this.settings.modelParams?.presencePenalty;
31182
- if (presencePenalty !== void 0) {
31183
- modelParams.presence_penalty = presencePenalty;
31165
+ applyParameterOverrides(
31166
+ modelParams,
31167
+ options,
31168
+ sapOptions?.modelParams,
31169
+ this.settings.modelParams
31170
+ );
31171
+ if (options.stopSequences && options.stopSequences.length > 0) {
31172
+ modelParams.stop = options.stopSequences;
31184
31173
  }
31185
31174
  if (supportsN) {
31186
31175
  const nValue = sapOptions?.modelParams?.n ?? this.settings.modelParams?.n;
@@ -31190,16 +31179,6 @@ var SAPAILanguageModel = class {
31190
31179
  } else {
31191
31180
  delete modelParams.n;
31192
31181
  }
31193
- const parallelToolCalls = sapOptions?.modelParams?.parallel_tool_calls ?? this.settings.modelParams?.parallel_tool_calls;
31194
- if (parallelToolCalls !== void 0) {
31195
- modelParams.parallel_tool_calls = parallelToolCalls;
31196
- }
31197
- if (options.stopSequences && options.stopSequences.length > 0) {
31198
- modelParams.stop = options.stopSequences;
31199
- }
31200
- if (options.seed !== void 0) {
31201
- modelParams.seed = options.seed;
31202
- }
31203
31182
  validateModelParamsWithWarnings(
31204
31183
  {
31205
31184
  frequencyPenalty: options.frequencyPenalty,
@@ -31250,25 +31229,35 @@ var SAPAILanguageModel = class {
31250
31229
  ...responseFormat ? { response_format: responseFormat } : {}
31251
31230
  }
31252
31231
  },
31253
- ...(() => {
31254
- const masking = this.settings.masking;
31255
- return masking && Object.keys(masking).length > 0 ? { masking } : {};
31256
- })(),
31257
- ...(() => {
31258
- const filtering = this.settings.filtering;
31259
- return filtering && Object.keys(filtering).length > 0 ? { filtering } : {};
31260
- })(),
31261
- ...(() => {
31262
- const grounding = this.settings.grounding;
31263
- return grounding && Object.keys(grounding).length > 0 ? { grounding } : {};
31264
- })(),
31265
- ...(() => {
31266
- const translation = this.settings.translation;
31267
- return translation && Object.keys(translation).length > 0 ? { translation } : {};
31268
- })()
31232
+ ...this.settings.masking && Object.keys(this.settings.masking).length > 0 ? { masking: this.settings.masking } : {},
31233
+ ...this.settings.filtering && Object.keys(this.settings.filtering).length > 0 ? { filtering: this.settings.filtering } : {},
31234
+ ...this.settings.grounding && Object.keys(this.settings.grounding).length > 0 ? { grounding: this.settings.grounding } : {},
31235
+ ...this.settings.translation && Object.keys(this.settings.translation).length > 0 ? { translation: this.settings.translation } : {}
31269
31236
  };
31270
31237
  return { messages, orchestrationConfig, warnings };
31271
31238
  }
31239
+ /**
31240
+ * Builds the request body for SAP AI SDK chat completion or streaming.
31241
+ * @param messages - The chat messages to send.
31242
+ * @param orchestrationConfig - The orchestration configuration.
31243
+ * @returns The request body object.
31244
+ * @internal
31245
+ */
31246
+ buildRequestBody(messages, orchestrationConfig) {
31247
+ const promptTemplating = orchestrationConfig.promptTemplating;
31248
+ return {
31249
+ messages,
31250
+ model: {
31251
+ ...orchestrationConfig.promptTemplating.model
31252
+ },
31253
+ ...promptTemplating.prompt.tools ? { tools: promptTemplating.prompt.tools } : {},
31254
+ ...promptTemplating.prompt.response_format ? { response_format: promptTemplating.prompt.response_format } : {},
31255
+ ...orchestrationConfig.masking && Object.keys(orchestrationConfig.masking).length > 0 ? { masking: orchestrationConfig.masking } : {},
31256
+ ...orchestrationConfig.filtering && Object.keys(orchestrationConfig.filtering).length > 0 ? { filtering: orchestrationConfig.filtering } : {},
31257
+ ...orchestrationConfig.grounding && Object.keys(orchestrationConfig.grounding).length > 0 ? { grounding: orchestrationConfig.grounding } : {},
31258
+ ...orchestrationConfig.translation && Object.keys(orchestrationConfig.translation).length > 0 ? { translation: orchestrationConfig.translation } : {}
31259
+ };
31260
+ }
31272
31261
  /**
31273
31262
  * Creates an SAP AI SDK OrchestrationClient with the given configuration.
31274
31263
  * @param config - The SAP AI SDK orchestration module configuration.
@@ -31279,6 +31268,18 @@ var SAPAILanguageModel = class {
31279
31268
  return new import_orchestration2.OrchestrationClient(config, this.config.deploymentConfig, this.config.destination);
31280
31269
  }
31281
31270
  };
31271
+ function applyParameterOverrides(modelParams, options, sapModelParams, settingsModelParams) {
31272
+ const params = modelParams;
31273
+ for (const mapping of PARAM_MAPPINGS) {
31274
+ const value = (mapping.optionKey ? options[mapping.optionKey] : void 0) ?? (mapping.camelCaseKey ? sapModelParams?.[mapping.camelCaseKey] : void 0) ?? (mapping.camelCaseKey ? settingsModelParams?.[mapping.camelCaseKey] : void 0);
31275
+ if (value !== void 0) {
31276
+ params[mapping.outputKey] = value;
31277
+ }
31278
+ if (mapping.camelCaseKey && mapping.camelCaseKey !== mapping.outputKey) {
31279
+ Reflect.deleteProperty(params, mapping.camelCaseKey);
31280
+ }
31281
+ }
31282
+ }
31282
31283
  function buildSAPToolParameters(schema) {
31283
31284
  const schemaType = schema.type;
31284
31285
  if (schemaType !== void 0 && schemaType !== "object") {
@@ -31356,6 +31357,8 @@ function mapFinishReason(reason) {
31356
31357
  }
31357
31358
 
31358
31359
  // src/sap-ai-provider.ts
31360
+ var import_provider4 = require("@ai-sdk/provider");
31361
+ var import_util2 = __toESM(require_dist(), 1);
31359
31362
  function createSAPAIProvider(options = {}) {
31360
31363
  if (options.defaultSettings?.modelParams) {
31361
31364
  validateModelParamsSettings(options.defaultSettings.modelParams);
@@ -31368,6 +31371,10 @@ function createSAPAIProvider(options = {}) {
31368
31371
  "createSAPAIProvider: both 'deploymentId' and 'resourceGroup' were provided; using 'deploymentId' and ignoring 'resourceGroup'."
31369
31372
  );
31370
31373
  }
31374
+ if (!process.env.SAP_CLOUD_SDK_LOG_LEVEL) {
31375
+ const logLevel = options.logLevel ?? "warn";
31376
+ (0, import_util2.setGlobalLogLevel)(logLevel);
31377
+ }
31371
31378
  const deploymentConfig = options.deploymentId ? { deploymentId: options.deploymentId } : { resourceGroup };
31372
31379
  const createModel = (modelId, settings = {}) => {
31373
31380
  const mergedSettings = {
@@ -31431,6 +31438,7 @@ var import_orchestration5 = require("@sap-ai-sdk/orchestration");
31431
31438
  OrchestrationStreamChunkResponse,
31432
31439
  OrchestrationStreamResponse,
31433
31440
  SAPAIEmbeddingModel,
31441
+ SAPAILanguageModel,
31434
31442
  SAP_AI_PROVIDER_NAME,
31435
31443
  buildAzureContentSafetyFilter,
31436
31444
  buildDocumentGroundingConfig,
@@ -31439,7 +31447,6 @@ var import_orchestration5 = require("@sap-ai-sdk/orchestration");
31439
31447
  buildTranslationConfig,
31440
31448
  createSAPAIProvider,
31441
31449
  getProviderName,
31442
- isConfigReference,
31443
31450
  sapAIEmbeddingProviderOptions,
31444
31451
  sapAILanguageModelProviderOptions,
31445
31452
  sapai