@jerome-benoit/sap-ai-provider 4.1.0 → 4.1.2
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 +174 -52
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +174 -52
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -29765,6 +29765,17 @@ var import_orchestration = require("@sap-ai-sdk/orchestration");
|
|
|
29765
29765
|
// src/sap-ai-error.ts
|
|
29766
29766
|
var import_provider = require("@ai-sdk/provider");
|
|
29767
29767
|
var import_util = __toESM(require_dist(), 1);
|
|
29768
|
+
var HTTP_STATUS = {
|
|
29769
|
+
BAD_REQUEST: 400,
|
|
29770
|
+
CONFLICT: 409,
|
|
29771
|
+
FORBIDDEN: 403,
|
|
29772
|
+
INTERNAL_ERROR: 500,
|
|
29773
|
+
NOT_FOUND: 404,
|
|
29774
|
+
RATE_LIMIT: 429,
|
|
29775
|
+
REQUEST_TIMEOUT: 408,
|
|
29776
|
+
SERVICE_UNAVAILABLE: 503,
|
|
29777
|
+
UNAUTHORIZED: 401
|
|
29778
|
+
};
|
|
29768
29779
|
function convertSAPErrorToAPICallError(errorResponse, context) {
|
|
29769
29780
|
const error = errorResponse.error;
|
|
29770
29781
|
let message;
|
|
@@ -29793,7 +29804,7 @@ function convertSAPErrorToAPICallError(errorResponse, context) {
|
|
|
29793
29804
|
}
|
|
29794
29805
|
});
|
|
29795
29806
|
let enhancedMessage = message;
|
|
29796
|
-
if (statusCode ===
|
|
29807
|
+
if (statusCode === HTTP_STATUS.UNAUTHORIZED || statusCode === HTTP_STATUS.FORBIDDEN) {
|
|
29797
29808
|
enhancedMessage += "\n\nAuthentication failed. Verify your AICORE_SERVICE_KEY environment variable is set correctly.\nSee: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-service-key";
|
|
29798
29809
|
if (requestId) {
|
|
29799
29810
|
enhancedMessage += `
|
|
@@ -29803,7 +29814,7 @@ Request ID: ${requestId}`;
|
|
|
29803
29814
|
message: enhancedMessage
|
|
29804
29815
|
});
|
|
29805
29816
|
}
|
|
29806
|
-
if (statusCode ===
|
|
29817
|
+
if (statusCode === HTTP_STATUS.NOT_FOUND) {
|
|
29807
29818
|
enhancedMessage += "\n\nResource not found. The model or deployment may not exist in your SAP AI Core instance.\nSee: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-deployment-for-orchestration";
|
|
29808
29819
|
if (requestId) {
|
|
29809
29820
|
enhancedMessage += `
|
|
@@ -29816,9 +29827,9 @@ Request ID: ${requestId}`;
|
|
|
29816
29827
|
modelType: "languageModel"
|
|
29817
29828
|
});
|
|
29818
29829
|
}
|
|
29819
|
-
if (statusCode ===
|
|
29830
|
+
if (statusCode === HTTP_STATUS.RATE_LIMIT) {
|
|
29820
29831
|
enhancedMessage += "\n\nRate limit exceeded. Please try again later or contact your SAP administrator.\nSee: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/rate-limits";
|
|
29821
|
-
} else if (statusCode >=
|
|
29832
|
+
} else if (statusCode >= HTTP_STATUS.INTERNAL_ERROR) {
|
|
29822
29833
|
enhancedMessage += "\n\nSAP AI Core service error. This is typically a temporary issue. The request will be retried automatically.\nSee: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/troubleshooting";
|
|
29823
29834
|
} else if (location) {
|
|
29824
29835
|
enhancedMessage += `
|
|
@@ -29878,7 +29889,7 @@ See: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-serv
|
|
|
29878
29889
|
message: `Network error connecting to SAP AI Core: ${originalMsg}`,
|
|
29879
29890
|
requestBodyValues: context?.requestBody,
|
|
29880
29891
|
responseHeaders,
|
|
29881
|
-
statusCode:
|
|
29892
|
+
statusCode: HTTP_STATUS.SERVICE_UNAVAILABLE,
|
|
29882
29893
|
url: context?.url ?? ""
|
|
29883
29894
|
});
|
|
29884
29895
|
}
|
|
@@ -29891,7 +29902,7 @@ See: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-serv
|
|
|
29891
29902
|
Check your destination configuration or provide a valid destinationName.`,
|
|
29892
29903
|
requestBodyValues: context?.requestBody,
|
|
29893
29904
|
responseHeaders,
|
|
29894
|
-
statusCode:
|
|
29905
|
+
statusCode: HTTP_STATUS.BAD_REQUEST,
|
|
29895
29906
|
url: context?.url ?? ""
|
|
29896
29907
|
});
|
|
29897
29908
|
}
|
|
@@ -29915,7 +29926,7 @@ See: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-depl
|
|
|
29915
29926
|
The model's response was blocked by content safety filters. Try a different prompt.`,
|
|
29916
29927
|
requestBodyValues: context?.requestBody,
|
|
29917
29928
|
responseHeaders,
|
|
29918
|
-
statusCode:
|
|
29929
|
+
statusCode: HTTP_STATUS.BAD_REQUEST,
|
|
29919
29930
|
url: context?.url ?? ""
|
|
29920
29931
|
});
|
|
29921
29932
|
}
|
|
@@ -29932,14 +29943,91 @@ The model's response was blocked by content safety filters. Try a different prom
|
|
|
29932
29943
|
url: context?.url ?? ""
|
|
29933
29944
|
});
|
|
29934
29945
|
}
|
|
29935
|
-
if (errorMsg.includes("
|
|
29946
|
+
if (errorMsg.includes("consumed stream")) {
|
|
29947
|
+
return new import_provider.APICallError({
|
|
29948
|
+
cause: error,
|
|
29949
|
+
isRetryable: false,
|
|
29950
|
+
message: `SAP AI Core stream consumption error: ${originalMsg}`,
|
|
29951
|
+
requestBodyValues: context?.requestBody,
|
|
29952
|
+
responseHeaders,
|
|
29953
|
+
statusCode: HTTP_STATUS.INTERNAL_ERROR,
|
|
29954
|
+
url: context?.url ?? ""
|
|
29955
|
+
});
|
|
29956
|
+
}
|
|
29957
|
+
if (errorMsg.includes("iterating over") || errorMsg.includes("parse message into json") || errorMsg.includes("received from") || errorMsg.includes("no body") || errorMsg.includes("invalid sse payload")) {
|
|
29936
29958
|
return new import_provider.APICallError({
|
|
29937
29959
|
cause: error,
|
|
29938
29960
|
isRetryable: true,
|
|
29939
29961
|
message: `SAP AI Core streaming error: ${originalMsg}`,
|
|
29940
29962
|
requestBodyValues: context?.requestBody,
|
|
29941
29963
|
responseHeaders,
|
|
29942
|
-
statusCode:
|
|
29964
|
+
statusCode: HTTP_STATUS.INTERNAL_ERROR,
|
|
29965
|
+
url: context?.url ?? ""
|
|
29966
|
+
});
|
|
29967
|
+
}
|
|
29968
|
+
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")) {
|
|
29969
|
+
return new import_provider.APICallError({
|
|
29970
|
+
cause: error,
|
|
29971
|
+
isRetryable: false,
|
|
29972
|
+
message: `SAP AI Core configuration error: ${originalMsg}`,
|
|
29973
|
+
requestBodyValues: context?.requestBody,
|
|
29974
|
+
responseHeaders,
|
|
29975
|
+
statusCode: HTTP_STATUS.BAD_REQUEST,
|
|
29976
|
+
url: context?.url ?? ""
|
|
29977
|
+
});
|
|
29978
|
+
}
|
|
29979
|
+
if (errorMsg.includes("buffer is not available as globals")) {
|
|
29980
|
+
return new import_provider.APICallError({
|
|
29981
|
+
cause: error,
|
|
29982
|
+
isRetryable: false,
|
|
29983
|
+
message: `SAP AI Core environment error: ${originalMsg}`,
|
|
29984
|
+
requestBodyValues: context?.requestBody,
|
|
29985
|
+
responseHeaders,
|
|
29986
|
+
statusCode: HTTP_STATUS.INTERNAL_ERROR,
|
|
29987
|
+
url: context?.url ?? ""
|
|
29988
|
+
});
|
|
29989
|
+
}
|
|
29990
|
+
if (errorMsg.includes("response stream is undefined")) {
|
|
29991
|
+
return new import_provider.APICallError({
|
|
29992
|
+
cause: error,
|
|
29993
|
+
isRetryable: false,
|
|
29994
|
+
message: `SAP AI Core response stream error: ${originalMsg}`,
|
|
29995
|
+
requestBodyValues: context?.requestBody,
|
|
29996
|
+
responseHeaders,
|
|
29997
|
+
statusCode: HTTP_STATUS.INTERNAL_ERROR,
|
|
29998
|
+
url: context?.url ?? ""
|
|
29999
|
+
});
|
|
30000
|
+
}
|
|
30001
|
+
if (errorMsg.includes("response is required to process") || errorMsg.includes("stream is still open") || errorMsg.includes("data is not available yet")) {
|
|
30002
|
+
return new import_provider.APICallError({
|
|
30003
|
+
cause: error,
|
|
30004
|
+
isRetryable: true,
|
|
30005
|
+
message: `SAP AI Core response processing error: ${originalMsg}`,
|
|
30006
|
+
requestBodyValues: context?.requestBody,
|
|
30007
|
+
responseHeaders,
|
|
30008
|
+
statusCode: HTTP_STATUS.INTERNAL_ERROR,
|
|
30009
|
+
url: context?.url ?? ""
|
|
30010
|
+
});
|
|
30011
|
+
}
|
|
30012
|
+
if (errorMsg.includes("failed to fetch the list of deployments")) {
|
|
30013
|
+
return new import_provider.APICallError({
|
|
30014
|
+
cause: error,
|
|
30015
|
+
isRetryable: true,
|
|
30016
|
+
message: `SAP AI Core deployment retrieval error: ${originalMsg}`,
|
|
30017
|
+
requestBodyValues: context?.requestBody,
|
|
30018
|
+
responseHeaders,
|
|
30019
|
+
statusCode: HTTP_STATUS.SERVICE_UNAVAILABLE,
|
|
30020
|
+
url: context?.url ?? ""
|
|
30021
|
+
});
|
|
30022
|
+
}
|
|
30023
|
+
if (errorMsg.includes("received non-uint8array")) {
|
|
30024
|
+
return new import_provider.APICallError({
|
|
30025
|
+
cause: error,
|
|
30026
|
+
isRetryable: false,
|
|
30027
|
+
message: `SAP AI Core stream buffer error: ${originalMsg}`,
|
|
30028
|
+
requestBodyValues: context?.requestBody,
|
|
30029
|
+
responseHeaders,
|
|
30030
|
+
statusCode: HTTP_STATUS.INTERNAL_ERROR,
|
|
29943
30031
|
url: context?.url ?? ""
|
|
29944
30032
|
});
|
|
29945
30033
|
}
|
|
@@ -29952,7 +30040,7 @@ The model's response was blocked by content safety filters. Try a different prom
|
|
|
29952
30040
|
message: fullMessage,
|
|
29953
30041
|
requestBodyValues: context?.requestBody,
|
|
29954
30042
|
responseHeaders,
|
|
29955
|
-
statusCode:
|
|
30043
|
+
statusCode: HTTP_STATUS.INTERNAL_ERROR,
|
|
29956
30044
|
url: context?.url ?? ""
|
|
29957
30045
|
});
|
|
29958
30046
|
}
|
|
@@ -29985,11 +30073,11 @@ function getAxiosResponseHeaders(error) {
|
|
|
29985
30073
|
return normalizeHeaders(maybeAxios.response?.headers);
|
|
29986
30074
|
}
|
|
29987
30075
|
function getStatusCodeFromSAPError(code) {
|
|
29988
|
-
if (!code) return
|
|
30076
|
+
if (!code) return HTTP_STATUS.INTERNAL_ERROR;
|
|
29989
30077
|
if (code >= 100 && code < 600) {
|
|
29990
30078
|
return code;
|
|
29991
30079
|
}
|
|
29992
|
-
return
|
|
30080
|
+
return HTTP_STATUS.INTERNAL_ERROR;
|
|
29993
30081
|
}
|
|
29994
30082
|
function isOrchestrationErrorResponse(error) {
|
|
29995
30083
|
if (error === null || typeof error !== "object" || !("error" in error)) {
|
|
@@ -29999,14 +30087,34 @@ function isOrchestrationErrorResponse(error) {
|
|
|
29999
30087
|
const innerError = errorEnvelope.error;
|
|
30000
30088
|
if (innerError === void 0) return false;
|
|
30001
30089
|
if (Array.isArray(innerError)) {
|
|
30002
|
-
return innerError.every(
|
|
30003
|
-
(entry
|
|
30004
|
-
|
|
30090
|
+
return innerError.every((entry) => {
|
|
30091
|
+
if (entry === null || typeof entry !== "object" || !("message" in entry)) {
|
|
30092
|
+
return false;
|
|
30093
|
+
}
|
|
30094
|
+
const errorEntry = entry;
|
|
30095
|
+
if (typeof errorEntry.message !== "string") {
|
|
30096
|
+
return false;
|
|
30097
|
+
}
|
|
30098
|
+
if ("code" in entry && typeof errorEntry.code !== "number") {
|
|
30099
|
+
return false;
|
|
30100
|
+
}
|
|
30101
|
+
return true;
|
|
30102
|
+
});
|
|
30103
|
+
}
|
|
30104
|
+
if (typeof innerError !== "object" || innerError === null || !("message" in innerError)) {
|
|
30105
|
+
return false;
|
|
30106
|
+
}
|
|
30107
|
+
const errorObj = innerError;
|
|
30108
|
+
if (typeof errorObj.message !== "string") {
|
|
30109
|
+
return false;
|
|
30110
|
+
}
|
|
30111
|
+
if ("code" in innerError && typeof errorObj.code !== "number") {
|
|
30112
|
+
return false;
|
|
30005
30113
|
}
|
|
30006
|
-
return
|
|
30114
|
+
return true;
|
|
30007
30115
|
}
|
|
30008
30116
|
function isRetryable(statusCode) {
|
|
30009
|
-
return statusCode ===
|
|
30117
|
+
return statusCode === HTTP_STATUS.REQUEST_TIMEOUT || statusCode === HTTP_STATUS.CONFLICT || statusCode === HTTP_STATUS.RATE_LIMIT || statusCode >= HTTP_STATUS.INTERNAL_ERROR && statusCode < 600;
|
|
30010
30118
|
}
|
|
30011
30119
|
function normalizeHeaders(headers) {
|
|
30012
30120
|
if (!headers || typeof headers !== "object") return void 0;
|
|
@@ -30084,9 +30192,46 @@ var modelParamsSchema = import_zod.z.object({
|
|
|
30084
30192
|
*/
|
|
30085
30193
|
topP: import_zod.z.number().min(0).max(1).optional()
|
|
30086
30194
|
}).catchall(import_zod.z.unknown());
|
|
30195
|
+
var embeddingModelParamsSchema = import_zod.z.object({
|
|
30196
|
+
/**
|
|
30197
|
+
* The number of dimensions for output embeddings.
|
|
30198
|
+
* Must be a positive integer. Support varies by model.
|
|
30199
|
+
* - text-embedding-3-small: supports 512, 1536
|
|
30200
|
+
* - text-embedding-3-large: supports 256, 1024, 3072
|
|
30201
|
+
*/
|
|
30202
|
+
dimensions: import_zod.z.number().int().positive().optional(),
|
|
30203
|
+
/**
|
|
30204
|
+
* Encoding format for embeddings.
|
|
30205
|
+
* - 'float': Array of floats (default)
|
|
30206
|
+
* - 'base64': Base64-encoded binary
|
|
30207
|
+
* - 'binary': Raw binary format
|
|
30208
|
+
*/
|
|
30209
|
+
encoding_format: import_zod.z.enum(["base64", "binary", "float"]).optional(),
|
|
30210
|
+
/**
|
|
30211
|
+
* Whether to normalize the embedding vectors.
|
|
30212
|
+
* When true, vectors are normalized to unit length.
|
|
30213
|
+
*/
|
|
30214
|
+
normalize: import_zod.z.boolean().optional()
|
|
30215
|
+
}).catchall(import_zod.z.unknown());
|
|
30216
|
+
function validateEmbeddingModelParamsSettings(modelParams) {
|
|
30217
|
+
return embeddingModelParamsSchema.parse(modelParams);
|
|
30218
|
+
}
|
|
30087
30219
|
function validateModelParamsSettings(modelParams) {
|
|
30088
30220
|
return modelParamsSchema.parse(modelParams);
|
|
30089
30221
|
}
|
|
30222
|
+
function validateModelParamsWithWarnings(params, warnings) {
|
|
30223
|
+
const result = modelParamsSchema.safeParse(params);
|
|
30224
|
+
if (!result.success) {
|
|
30225
|
+
for (const issue of result.error.issues) {
|
|
30226
|
+
const path = issue.path.join(".");
|
|
30227
|
+
const value = path ? params[path] : void 0;
|
|
30228
|
+
warnings.push({
|
|
30229
|
+
message: `${path}=${String(value)} is invalid: ${issue.message}. The API may reject this value.`,
|
|
30230
|
+
type: "other"
|
|
30231
|
+
});
|
|
30232
|
+
}
|
|
30233
|
+
}
|
|
30234
|
+
}
|
|
30090
30235
|
var sapAILanguageModelProviderOptions = (0, import_provider_utils.lazySchema)(
|
|
30091
30236
|
() => (0, import_provider_utils.zodSchema)(
|
|
30092
30237
|
import_zod.z.object({
|
|
@@ -30112,8 +30257,14 @@ var sapAIEmbeddingProviderOptions = (0, import_provider_utils.lazySchema)(
|
|
|
30112
30257
|
/**
|
|
30113
30258
|
* Additional model parameters for this call.
|
|
30114
30259
|
* Passed directly to the embedding API.
|
|
30260
|
+
*
|
|
30261
|
+
* Known parameters:
|
|
30262
|
+
* - `dimensions`: Output embedding dimensions (model-dependent)
|
|
30263
|
+
* - `encoding_format`: 'float' | 'base64' | 'binary'
|
|
30264
|
+
* - `normalize`: Whether to normalize vectors
|
|
30265
|
+
* @see {@link embeddingModelParamsSchema} for validation rules
|
|
30115
30266
|
*/
|
|
30116
|
-
modelParams:
|
|
30267
|
+
modelParams: embeddingModelParamsSchema.optional(),
|
|
30117
30268
|
/**
|
|
30118
30269
|
* Embedding task type for this specific call.
|
|
30119
30270
|
* Overrides the constructor `type` setting.
|
|
@@ -30161,6 +30312,9 @@ var SAPAIEmbeddingModel = class {
|
|
|
30161
30312
|
* @param config - Internal configuration from the provider
|
|
30162
30313
|
*/
|
|
30163
30314
|
constructor(modelId, settings = {}, config) {
|
|
30315
|
+
if (settings.modelParams) {
|
|
30316
|
+
validateEmbeddingModelParamsSettings(settings.modelParams);
|
|
30317
|
+
}
|
|
30164
30318
|
this.modelId = modelId;
|
|
30165
30319
|
this.settings = settings;
|
|
30166
30320
|
this.config = config;
|
|
@@ -30298,7 +30452,7 @@ function convertToSAPMessages(prompt, options = {}) {
|
|
|
30298
30452
|
switch (part.type) {
|
|
30299
30453
|
case "reasoning": {
|
|
30300
30454
|
if (includeReasoning && part.text) {
|
|
30301
|
-
text += `<
|
|
30455
|
+
text += `<think>${part.text}</think>`;
|
|
30302
30456
|
}
|
|
30303
30457
|
break;
|
|
30304
30458
|
}
|
|
@@ -31142,7 +31296,7 @@ var SAPAILanguageModel = class {
|
|
|
31142
31296
|
if (options.seed !== void 0) {
|
|
31143
31297
|
modelParams.seed = options.seed;
|
|
31144
31298
|
}
|
|
31145
|
-
|
|
31299
|
+
validateModelParamsWithWarnings(
|
|
31146
31300
|
{
|
|
31147
31301
|
frequencyPenalty: options.frequencyPenalty,
|
|
31148
31302
|
maxTokens: options.maxOutputTokens,
|
|
@@ -31291,38 +31445,6 @@ function mapFinishReason(reason) {
|
|
|
31291
31445
|
return { raw, unified: "other" };
|
|
31292
31446
|
}
|
|
31293
31447
|
}
|
|
31294
|
-
function validateAISDKParameters(params, warnings) {
|
|
31295
|
-
if (params.temperature !== void 0 && (params.temperature < 0 || params.temperature > 2)) {
|
|
31296
|
-
warnings.push({
|
|
31297
|
-
message: `temperature=${String(params.temperature)} is outside typical range [0, 2]. The API may reject this value.`,
|
|
31298
|
-
type: "other"
|
|
31299
|
-
});
|
|
31300
|
-
}
|
|
31301
|
-
if (params.topP !== void 0 && (params.topP < 0 || params.topP > 1)) {
|
|
31302
|
-
warnings.push({
|
|
31303
|
-
message: `topP=${String(params.topP)} is outside valid range [0, 1]. The API may reject this value.`,
|
|
31304
|
-
type: "other"
|
|
31305
|
-
});
|
|
31306
|
-
}
|
|
31307
|
-
if (params.frequencyPenalty !== void 0 && (params.frequencyPenalty < -2 || params.frequencyPenalty > 2)) {
|
|
31308
|
-
warnings.push({
|
|
31309
|
-
message: `frequencyPenalty=${String(params.frequencyPenalty)} is outside typical range [-2, 2]. The API may reject this value.`,
|
|
31310
|
-
type: "other"
|
|
31311
|
-
});
|
|
31312
|
-
}
|
|
31313
|
-
if (params.presencePenalty !== void 0 && (params.presencePenalty < -2 || params.presencePenalty > 2)) {
|
|
31314
|
-
warnings.push({
|
|
31315
|
-
message: `presencePenalty=${String(params.presencePenalty)} is outside typical range [-2, 2]. The API may reject this value.`,
|
|
31316
|
-
type: "other"
|
|
31317
|
-
});
|
|
31318
|
-
}
|
|
31319
|
-
if (params.maxTokens !== void 0 && params.maxTokens <= 0) {
|
|
31320
|
-
warnings.push({
|
|
31321
|
-
message: `maxTokens=${String(params.maxTokens)} must be positive. The API will likely reject this value.`,
|
|
31322
|
-
type: "other"
|
|
31323
|
-
});
|
|
31324
|
-
}
|
|
31325
|
-
}
|
|
31326
31448
|
|
|
31327
31449
|
// src/sap-ai-provider.ts
|
|
31328
31450
|
function createSAPAIProvider(options = {}) {
|