@jerome-benoit/sap-ai-provider-v2 5.0.1 → 5.0.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.
Files changed (40) hide show
  1. package/README.md +39 -32
  2. package/dist/chunk-77JSAAPE.js +778 -0
  3. package/dist/chunk-77JSAAPE.js.map +1 -0
  4. package/dist/{chunk-AFZC2DH2.js → chunk-LEME2MFD.js} +59 -387
  5. package/dist/chunk-LEME2MFD.js.map +1 -0
  6. package/dist/{chunk-U23M3VYO.js → chunk-NLMWIVG7.js} +17 -7
  7. package/dist/chunk-NLMWIVG7.js.map +1 -0
  8. package/dist/chunk-QZOZ3PZT.js +634 -0
  9. package/dist/chunk-QZOZ3PZT.js.map +1 -0
  10. package/dist/{chunk-JRUSQTKB.js → chunk-U6WJSLR7.js} +19 -11
  11. package/dist/chunk-U6WJSLR7.js.map +1 -0
  12. package/dist/{chunk-MF3VO3ER.js → chunk-YP3AADWD.js} +47 -40
  13. package/dist/chunk-YP3AADWD.js.map +1 -0
  14. package/dist/{foundation-models-embedding-model-strategy-2GUADNXT.js → foundation-models-embedding-model-strategy-A3WDDAYK.js} +8 -9
  15. package/dist/foundation-models-embedding-model-strategy-A3WDDAYK.js.map +1 -0
  16. package/dist/{foundation-models-language-model-strategy-5AYZ5KHA.js → foundation-models-language-model-strategy-6U6KK6KH.js} +18 -21
  17. package/dist/foundation-models-language-model-strategy-6U6KK6KH.js.map +1 -0
  18. package/dist/index.cjs +1323 -31666
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.cts +17 -32
  21. package/dist/index.d.ts +17 -32
  22. package/dist/index.js +48 -194
  23. package/dist/index.js.map +1 -1
  24. package/dist/{orchestration-embedding-model-strategy-F7WHDLX7.js → orchestration-embedding-model-strategy-JO3QH5MR.js} +7 -11
  25. package/dist/orchestration-embedding-model-strategy-JO3QH5MR.js.map +1 -0
  26. package/dist/{orchestration-language-model-strategy-Z72AFW62.js → orchestration-language-model-strategy-MBVA7BYX.js} +23 -25
  27. package/dist/orchestration-language-model-strategy-MBVA7BYX.js.map +1 -0
  28. package/package.json +15 -12
  29. package/dist/chunk-2KOXKYVT.js +0 -31083
  30. package/dist/chunk-2KOXKYVT.js.map +0 -1
  31. package/dist/chunk-643USI3B.js +0 -251
  32. package/dist/chunk-643USI3B.js.map +0 -1
  33. package/dist/chunk-AFZC2DH2.js.map +0 -1
  34. package/dist/chunk-JRUSQTKB.js.map +0 -1
  35. package/dist/chunk-MF3VO3ER.js.map +0 -1
  36. package/dist/chunk-U23M3VYO.js.map +0 -1
  37. package/dist/foundation-models-embedding-model-strategy-2GUADNXT.js.map +0 -1
  38. package/dist/foundation-models-language-model-strategy-5AYZ5KHA.js.map +0 -1
  39. package/dist/orchestration-embedding-model-strategy-F7WHDLX7.js.map +0 -1
  40. package/dist/orchestration-language-model-strategy-Z72AFW62.js.map +0 -1
@@ -0,0 +1,778 @@
1
+ import {createRequire as __createRequire} from 'module';var require=__createRequire(import.meta.url);
2
+
3
+ // src/sap-ai-provider-options.ts
4
+ import { lazySchema, zodSchema } from "@ai-sdk/provider-utils";
5
+ import { z } from "zod";
6
+ var SAP_AI_PROVIDER_NAME = "sap-ai";
7
+ function getProviderName(providerIdentifier) {
8
+ const dotIndex = providerIdentifier.indexOf(".");
9
+ return dotIndex === -1 ? providerIdentifier : providerIdentifier.slice(0, dotIndex);
10
+ }
11
+ var modelParamsSchema = z.object({
12
+ frequencyPenalty: z.number().min(-2).max(2).optional(),
13
+ maxTokens: z.number().int().positive().optional(),
14
+ n: z.number().int().positive().optional(),
15
+ parallel_tool_calls: z.boolean().optional(),
16
+ presencePenalty: z.number().min(-2).max(2).optional(),
17
+ temperature: z.number().min(0).max(2).optional(),
18
+ topP: z.number().min(0).max(1).optional()
19
+ }).catchall(z.unknown());
20
+ var embeddingModelParamsSchema = z.object({
21
+ dimensions: z.number().int().positive().optional(),
22
+ encoding_format: z.enum(["base64", "binary", "float"]).optional(),
23
+ normalize: z.boolean().optional()
24
+ }).catchall(z.unknown());
25
+ function validateEmbeddingModelParamsSettings(modelParams) {
26
+ return embeddingModelParamsSchema.parse(modelParams);
27
+ }
28
+ function validateModelParamsSettings(modelParams) {
29
+ return modelParamsSchema.parse(modelParams);
30
+ }
31
+ function validateModelParamsWithWarnings(params, warnings) {
32
+ const result = modelParamsSchema.safeParse(params);
33
+ if (!result.success) {
34
+ for (const issue of result.error.issues) {
35
+ const path = issue.path.join(".");
36
+ const value = path ? params[path] : void 0;
37
+ warnings.push({
38
+ message: `${path}=${String(value)} is invalid: ${issue.message}. The API may reject this value.`,
39
+ type: "other"
40
+ });
41
+ }
42
+ }
43
+ }
44
+ var sapAIApiTypeSchema = z.enum(["orchestration", "foundation-models"]);
45
+ var cacheControlSchema = z.object({
46
+ ttl: z.enum(["5m", "1h"]).optional(),
47
+ type: z.literal("ephemeral")
48
+ });
49
+ var sapAIPartProviderOptionsSchema = z.object({
50
+ cacheControl: cacheControlSchema.optional()
51
+ });
52
+ function parseSAPPartProviderOptions(providerOptions, warnings) {
53
+ if (!providerOptions || typeof providerOptions !== "object") {
54
+ return void 0;
55
+ }
56
+ const block = providerOptions[SAP_AI_PROVIDER_NAME];
57
+ if (block === void 0) {
58
+ return void 0;
59
+ }
60
+ const parsed = sapAIPartProviderOptionsSchema.safeParse(block);
61
+ if (parsed.success) {
62
+ return parsed.data;
63
+ }
64
+ if (warnings) {
65
+ for (const issue of parsed.error.issues) {
66
+ const path = issue.path.join(".");
67
+ const message = `providerOptions['sap-ai']${path ? `.${path}` : ""} is invalid: ${issue.message}. The directive was dropped.`;
68
+ if (!warnings.some((w) => w.message === message)) {
69
+ warnings.push({ message, type: "other" });
70
+ }
71
+ }
72
+ }
73
+ return void 0;
74
+ }
75
+ var promptTemplateScopeSchema = z.enum(["tenant", "resource_group"]);
76
+ var promptTemplateRefByIdSchema = z.object({
77
+ id: z.string().min(1, "Template ID cannot be empty"),
78
+ scope: promptTemplateScopeSchema.optional()
79
+ });
80
+ var promptTemplateRefByScenarioNameVersionSchema = z.object({
81
+ name: z.string().min(1, "Template name cannot be empty"),
82
+ scenario: z.string().min(1, "Scenario cannot be empty"),
83
+ scope: promptTemplateScopeSchema.optional(),
84
+ version: z.string().min(1, "Version cannot be empty")
85
+ });
86
+ var promptTemplateRefSchema = z.union([
87
+ promptTemplateRefByIdSchema,
88
+ promptTemplateRefByScenarioNameVersionSchema
89
+ ]);
90
+ var orchestrationConfigRefOverrideSchema = z.custom(
91
+ (value) => typeof value === "object" && value !== null && !Array.isArray(value),
92
+ { message: "overrideConfig must be an object" }
93
+ ).refine(
94
+ (value) => {
95
+ let stream;
96
+ try {
97
+ stream = value.stream;
98
+ } catch {
99
+ return false;
100
+ }
101
+ return stream === void 0 || Boolean(stream) && typeof stream === "object" && !Array.isArray(stream);
102
+ },
103
+ { message: "overrideConfig.stream must be an object" }
104
+ ).refine(
105
+ (value) => {
106
+ let stream;
107
+ try {
108
+ stream = value.stream;
109
+ } catch {
110
+ return true;
111
+ }
112
+ if (stream === void 0 || stream === null || typeof stream !== "object") {
113
+ return true;
114
+ }
115
+ try {
116
+ return !("enabled" in stream);
117
+ } catch {
118
+ return false;
119
+ }
120
+ },
121
+ {
122
+ message: "stream.enabled is not allowed in overrideConfig: it is controlled by the call site (stream() or chatCompletion())"
123
+ }
124
+ );
125
+ var orchestrationConfigRefByIdSchema = z.object({
126
+ id: z.string().min(1, "Config ID cannot be empty"),
127
+ overrideConfig: orchestrationConfigRefOverrideSchema.optional()
128
+ });
129
+ var orchestrationConfigRefByScenarioNameVersionSchema = z.object({
130
+ name: z.string().min(1, "Config name cannot be empty"),
131
+ overrideConfig: orchestrationConfigRefOverrideSchema.optional(),
132
+ scenario: z.string().min(1, "Scenario cannot be empty"),
133
+ version: z.string().min(1, "Version cannot be empty")
134
+ });
135
+ var orchestrationConfigRefSchema = z.union([
136
+ orchestrationConfigRefByIdSchema,
137
+ orchestrationConfigRefByScenarioNameVersionSchema
138
+ ]);
139
+ var sapAILanguageModelProviderOptions = lazySchema(
140
+ () => zodSchema(
141
+ z.object({
142
+ api: sapAIApiTypeSchema.optional(),
143
+ escapeTemplatePlaceholders: z.boolean().optional(),
144
+ includeReasoning: z.boolean().optional(),
145
+ modelParams: modelParamsSchema.optional(),
146
+ orchestrationConfigRef: orchestrationConfigRefSchema.optional(),
147
+ placeholderValues: z.record(z.string(), z.string()).optional(),
148
+ promptTemplateRef: promptTemplateRefSchema.optional()
149
+ })
150
+ )
151
+ );
152
+ var sapAIEmbeddingProviderOptions = lazySchema(
153
+ () => zodSchema(
154
+ z.object({
155
+ api: sapAIApiTypeSchema.optional(),
156
+ modelParams: embeddingModelParamsSchema.optional(),
157
+ type: z.enum(["document", "query", "text"]).optional()
158
+ })
159
+ )
160
+ );
161
+
162
+ // src/deep-merge.ts
163
+ var MAX_DEPTH = 100;
164
+ function deepMerge(...sources) {
165
+ const result = {};
166
+ for (const source of sources) {
167
+ if (source != null) mergeInto(result, source, /* @__PURE__ */ new Set(), 0);
168
+ }
169
+ return result;
170
+ }
171
+ function isPlainObject(value) {
172
+ if (value === null || typeof value !== "object") return false;
173
+ const proto = Object.getPrototypeOf(value);
174
+ return proto === Object.prototype || proto === null;
175
+ }
176
+ function mergeInto(target, source, ancestors, depth) {
177
+ if (depth > MAX_DEPTH) throw new Error("Maximum merge depth exceeded");
178
+ if (ancestors.has(source)) throw new Error("Circular reference detected during deep merge");
179
+ ancestors.add(source);
180
+ for (const key of Object.keys(source)) {
181
+ const sourceValue = source[key];
182
+ const targetValue = Object.hasOwn(target, key) ? target[key] : void 0;
183
+ const value = isPlainObject(sourceValue) ? mergeInto(isPlainObject(targetValue) ? targetValue : {}, sourceValue, ancestors, depth + 1) : sourceValue;
184
+ Object.defineProperty(target, key, {
185
+ configurable: true,
186
+ enumerable: true,
187
+ value,
188
+ writable: true
189
+ });
190
+ }
191
+ ancestors.delete(source);
192
+ return target;
193
+ }
194
+
195
+ // src/sap-ai-error.ts
196
+ import {
197
+ APICallError,
198
+ InvalidPromptError,
199
+ LoadAPIKeyError,
200
+ NoSuchModelError,
201
+ UnsupportedFunctionalityError
202
+ } from "@ai-sdk/provider";
203
+ import { isErrorWithCause } from "@sap-cloud-sdk/util";
204
+ var HTTP_STATUS = {
205
+ BAD_REQUEST: 400,
206
+ CLIENT_CLOSED_REQUEST: 499,
207
+ CONFLICT: 409,
208
+ FORBIDDEN: 403,
209
+ INTERNAL_ERROR: 500,
210
+ NOT_FOUND: 404,
211
+ RATE_LIMIT: 429,
212
+ REQUEST_TIMEOUT: 408,
213
+ SERVICE_UNAVAILABLE: 503,
214
+ UNAUTHORIZED: 401
215
+ };
216
+ var ERROR_MATCHERS = [
217
+ {
218
+ category: "network",
219
+ isRetryable: true,
220
+ keywords: ["econnrefused", "enotfound", "network", "timeout"],
221
+ statusCode: HTTP_STATUS.SERVICE_UNAVAILABLE
222
+ },
223
+ {
224
+ category: "destination",
225
+ isRetryable: false,
226
+ keywords: ["could not resolve destination"],
227
+ message: (original) => `SAP AI Core destination error: ${original}
228
+
229
+ Check your destination configuration or provide a valid destinationName.`,
230
+ statusCode: HTTP_STATUS.BAD_REQUEST
231
+ },
232
+ {
233
+ category: "content filtered",
234
+ isRetryable: false,
235
+ keywords: ["filtered by the output filter"],
236
+ message: (original) => `Content was filtered: ${original}
237
+
238
+ The model's response was blocked by content safety filters. Try a different prompt.`,
239
+ statusCode: HTTP_STATUS.BAD_REQUEST
240
+ },
241
+ {
242
+ category: "stream consumption",
243
+ isRetryable: false,
244
+ keywords: ["consumed stream"],
245
+ statusCode: HTTP_STATUS.INTERNAL_ERROR
246
+ },
247
+ {
248
+ category: "streaming",
249
+ isRetryable: true,
250
+ keywords: [
251
+ "iterating over",
252
+ "parse message into json",
253
+ "received from",
254
+ "no body",
255
+ "invalid sse payload"
256
+ ],
257
+ statusCode: HTTP_STATUS.INTERNAL_ERROR
258
+ },
259
+ {
260
+ category: "configuration",
261
+ isRetryable: false,
262
+ keywords: [
263
+ "prompt template or messages must be defined",
264
+ "filtering parameters cannot be empty",
265
+ "templating yaml string must be non-empty",
266
+ "could not access response data",
267
+ "could not parse json",
268
+ "error parsing yaml",
269
+ "yaml does not conform",
270
+ "validation errors"
271
+ ],
272
+ statusCode: HTTP_STATUS.BAD_REQUEST
273
+ },
274
+ {
275
+ category: "environment",
276
+ isRetryable: false,
277
+ keywords: ["buffer is not available as globals"],
278
+ statusCode: HTTP_STATUS.INTERNAL_ERROR
279
+ },
280
+ {
281
+ category: "response stream",
282
+ isRetryable: false,
283
+ keywords: ["response stream is undefined"],
284
+ statusCode: HTTP_STATUS.INTERNAL_ERROR
285
+ },
286
+ {
287
+ category: "response processing",
288
+ isRetryable: true,
289
+ keywords: [
290
+ "response is required to process",
291
+ "stream is still open",
292
+ "data is not available yet"
293
+ ],
294
+ statusCode: HTTP_STATUS.INTERNAL_ERROR
295
+ },
296
+ {
297
+ category: "deployment retrieval",
298
+ isRetryable: true,
299
+ keywords: ["failed to fetch the list of deployments"],
300
+ statusCode: HTTP_STATUS.SERVICE_UNAVAILABLE
301
+ },
302
+ {
303
+ category: "stream buffer",
304
+ isRetryable: false,
305
+ keywords: ["received non-uint8array"],
306
+ statusCode: HTTP_STATUS.INTERNAL_ERROR
307
+ }
308
+ ];
309
+ var AUTHENTICATION_ERROR_KEYWORDS = [
310
+ "authentication",
311
+ "unauthorized",
312
+ "aicore_service_key",
313
+ "invalid credentials",
314
+ "service credentials",
315
+ "service binding"
316
+ ];
317
+ var DEPLOYMENT_ERROR_KEYWORDS = [
318
+ "failed to resolve deployment",
319
+ "no deployment matched"
320
+ ];
321
+ var ApiSwitchError = class extends Error {
322
+ /**
323
+ * Creates a new ApiSwitchError.
324
+ * @param fromApi - The API the model was configured with.
325
+ * @param toApi - The API being switched to at invocation time.
326
+ * @param conflictingFeature - The feature that prevents the API switch.
327
+ */
328
+ constructor(fromApi, toApi, conflictingFeature) {
329
+ super(
330
+ `Cannot switch from ${fromApi} to ${toApi} API at invocation time because ${conflictingFeature} would be ignored. Create a new model instance without ${fromApi}-specific features, or keep using the ${fromApi} API.`
331
+ );
332
+ this.fromApi = fromApi;
333
+ this.toApi = toApi;
334
+ this.conflictingFeature = conflictingFeature;
335
+ this.name = "ApiSwitchError";
336
+ }
337
+ fromApi;
338
+ toApi;
339
+ conflictingFeature;
340
+ };
341
+ var UnsupportedFeatureError = class extends Error {
342
+ /**
343
+ * Creates a new UnsupportedFeatureError.
344
+ * @param feature - The name of the unsupported feature (e.g., "Content filtering").
345
+ * @param api - The API being used that does not support the feature.
346
+ * @param suggestedApi - The API that supports this feature.
347
+ */
348
+ constructor(feature, api, suggestedApi) {
349
+ const apiName = api === "foundation-models" ? "Foundation Models" : "Orchestration";
350
+ const suggestedApiName = suggestedApi === "foundation-models" ? "Foundation Models" : "Orchestration";
351
+ super(`${feature} is not supported by ${apiName} API. Use ${suggestedApiName} API instead.`);
352
+ this.feature = feature;
353
+ this.api = api;
354
+ this.suggestedApi = suggestedApi;
355
+ this.name = "UnsupportedFeatureError";
356
+ }
357
+ feature;
358
+ api;
359
+ suggestedApi;
360
+ };
361
+ function convertSAPErrorToAPICallError(errorResponse, context) {
362
+ const { code, location, message, requestId } = extractErrorFields(errorResponse);
363
+ const statusCode = getStatusCodeFromSAPError(code, context?.httpStatusCode);
364
+ const responseBody = JSON.stringify({
365
+ error: {
366
+ code,
367
+ location,
368
+ message,
369
+ request_id: requestId
370
+ }
371
+ });
372
+ let enhancedMessage = message;
373
+ if (statusCode === HTTP_STATUS.UNAUTHORIZED || statusCode === HTTP_STATUS.FORBIDDEN) {
374
+ 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";
375
+ if (requestId) {
376
+ enhancedMessage += `
377
+ Request ID: ${requestId}`;
378
+ }
379
+ return new LoadAPIKeyError({
380
+ message: enhancedMessage
381
+ });
382
+ }
383
+ if (statusCode === HTTP_STATUS.NOT_FOUND) {
384
+ 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";
385
+ if (requestId) {
386
+ enhancedMessage += `
387
+ Request ID: ${requestId}`;
388
+ }
389
+ const modelId = context?.modelId ?? extractModelIdentifier(message, location);
390
+ return new NoSuchModelError({
391
+ message: enhancedMessage,
392
+ modelId: modelId ?? "unknown",
393
+ modelType: context?.modelType ?? "languageModel"
394
+ });
395
+ }
396
+ if (statusCode === HTTP_STATUS.RATE_LIMIT) {
397
+ 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";
398
+ } else if (statusCode >= HTTP_STATUS.INTERNAL_ERROR) {
399
+ enhancedMessage += "\n\nSAP AI Core service error. This is typically a temporary issue. Retries depend on the caller's retry configuration.\nSee: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/troubleshooting";
400
+ } else if (location) {
401
+ enhancedMessage += `
402
+
403
+ Error location: ${location}`;
404
+ }
405
+ if (requestId) {
406
+ enhancedMessage += `
407
+ Request ID: ${requestId}`;
408
+ }
409
+ return new APICallError({
410
+ isRetryable: isRetryable(statusCode),
411
+ message: enhancedMessage,
412
+ requestBodyValues: context?.requestBody,
413
+ responseBody,
414
+ responseHeaders: context?.responseHeaders,
415
+ statusCode,
416
+ url: context?.url ?? ""
417
+ });
418
+ }
419
+ function convertToAISDKError(error, context) {
420
+ if (APICallError.isInstance(error) || LoadAPIKeyError.isInstance(error) || NoSuchModelError.isInstance(error) || InvalidPromptError.isInstance(error) || UnsupportedFunctionalityError.isInstance(error)) {
421
+ return error;
422
+ }
423
+ const { aborted, response, rootError } = inspectError(error);
424
+ const responseHeaders = context?.responseHeaders ?? normalizeHeaders(response?.headers);
425
+ if (!aborted) {
426
+ const errorResponse = findStructuredErrorResponse(
427
+ rootError instanceof SyntaxError ? void 0 : rootError,
428
+ response?.data
429
+ );
430
+ if (errorResponse) {
431
+ return convertSAPErrorToAPICallError(errorResponse, {
432
+ ...context,
433
+ httpStatusCode: response?.status ?? context?.httpStatusCode,
434
+ responseHeaders
435
+ });
436
+ }
437
+ }
438
+ const resolvedContext = {
439
+ ...context,
440
+ responseBody: serializeAxiosResponseData(response?.data),
441
+ responseHeaders
442
+ };
443
+ if (aborted) {
444
+ return createAPICallError(
445
+ error,
446
+ {
447
+ isRetryable: false,
448
+ message: "Request was aborted by the client",
449
+ statusCode: HTTP_STATUS.CLIENT_CLOSED_REQUEST
450
+ },
451
+ resolvedContext
452
+ );
453
+ }
454
+ if (isHttpStatus(response?.status)) {
455
+ return createAPICallError(
456
+ error,
457
+ {
458
+ isRetryable: isRetryable(response.status),
459
+ message: rootError instanceof SyntaxError && error instanceof Error ? error.message : rootError instanceof Error ? rootError.message : "SAP AI Core request failed",
460
+ statusCode: response.status
461
+ },
462
+ resolvedContext
463
+ );
464
+ }
465
+ if (rootError instanceof SyntaxError) {
466
+ return createAPICallError(
467
+ error,
468
+ {
469
+ isRetryable: false,
470
+ message: error instanceof Error && error !== rootError ? error.message : "Failed to parse SAP AI Core data.",
471
+ statusCode: HTTP_STATUS.INTERNAL_ERROR
472
+ },
473
+ resolvedContext
474
+ );
475
+ }
476
+ if (rootError instanceof Error) {
477
+ const errorMsg = rootError.message.toLowerCase();
478
+ const originalErrorMsg = rootError.message;
479
+ if (AUTHENTICATION_ERROR_KEYWORDS.some((keyword) => errorMsg.includes(keyword))) {
480
+ return new LoadAPIKeyError({
481
+ message: `SAP AI Core authentication failed: ${originalErrorMsg}
482
+
483
+ Make sure your AICORE_SERVICE_KEY environment variable is set correctly.
484
+ See: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-service-key`
485
+ });
486
+ }
487
+ if (DEPLOYMENT_ERROR_KEYWORDS.some((keyword) => errorMsg.includes(keyword))) {
488
+ const modelId = context?.modelId ?? extractModelIdentifier(originalErrorMsg);
489
+ return new NoSuchModelError({
490
+ message: `SAP AI Core deployment error: ${originalErrorMsg}
491
+
492
+ Make sure you have a running orchestration deployment in your SAP AI Core instance.
493
+ See: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-deployment-for-orchestration`,
494
+ modelId: modelId ?? "unknown",
495
+ modelType: context?.modelType ?? "languageModel"
496
+ });
497
+ }
498
+ const statusMatch = /status code (\d+)/i.exec(originalErrorMsg);
499
+ const extractedStatus = statusMatch?.[1] ? Number.parseInt(statusMatch[1], 10) : void 0;
500
+ if (isHttpStatus(extractedStatus)) {
501
+ return createAPICallError(
502
+ error,
503
+ {
504
+ isRetryable: isRetryable(extractedStatus),
505
+ message: `SAP AI Core request failed: ${originalErrorMsg}`,
506
+ statusCode: extractedStatus
507
+ },
508
+ resolvedContext
509
+ );
510
+ }
511
+ for (const matcher of ERROR_MATCHERS) {
512
+ if (matcher.keywords.some((keyword) => errorMsg.includes(keyword))) {
513
+ const message2 = "message" in matcher ? matcher.message(originalErrorMsg) : `SAP AI Core ${matcher.category} error: ${originalErrorMsg}`;
514
+ return createAPICallError(
515
+ error,
516
+ {
517
+ isRetryable: matcher.isRetryable,
518
+ message: message2,
519
+ statusCode: matcher.statusCode
520
+ },
521
+ resolvedContext
522
+ );
523
+ }
524
+ }
525
+ }
526
+ const message = rootError instanceof Error ? rootError.message : typeof rootError === "string" ? rootError : "Unknown error occurred";
527
+ const fullMessage = context?.operation ? `SAP AI Core ${context.operation} failed: ${message}` : `SAP AI Core error: ${message}`;
528
+ return createAPICallError(
529
+ error,
530
+ {
531
+ isRetryable: false,
532
+ message: fullMessage,
533
+ statusCode: HTTP_STATUS.INTERNAL_ERROR
534
+ },
535
+ resolvedContext
536
+ );
537
+ }
538
+ function normalizeHeaders(headers) {
539
+ if (!headers || typeof headers !== "object") return void 0;
540
+ if (typeof Headers !== "undefined" && headers instanceof Headers) {
541
+ const out = Object.fromEntries(headers.entries());
542
+ return Object.keys(out).length === 0 ? void 0 : out;
543
+ }
544
+ const record = headers;
545
+ const entries = Object.entries(record).flatMap(([key, value]) => {
546
+ const k = key.toLowerCase();
547
+ if (typeof value === "string") return [[k, value]];
548
+ if (Array.isArray(value)) {
549
+ const strings = value.filter((item) => typeof item === "string").join("; ");
550
+ return strings.length > 0 ? [[k, strings]] : [];
551
+ }
552
+ if (typeof value === "number" || typeof value === "boolean") {
553
+ return [[k, String(value)]];
554
+ }
555
+ return [];
556
+ });
557
+ if (entries.length === 0) return void 0;
558
+ return Object.fromEntries(entries);
559
+ }
560
+ function createAPICallError(error, options, context) {
561
+ return new APICallError({
562
+ cause: error,
563
+ isRetryable: options.isRetryable,
564
+ message: options.message,
565
+ requestBodyValues: context?.requestBody,
566
+ responseBody: context?.responseBody,
567
+ responseHeaders: context?.responseHeaders,
568
+ statusCode: options.statusCode,
569
+ url: context?.url ?? ""
570
+ });
571
+ }
572
+ function extractErrorFields(response) {
573
+ const innerError = response.error;
574
+ if (Array.isArray(innerError)) {
575
+ const first = innerError[0];
576
+ return {
577
+ code: first?.code,
578
+ location: first?.location,
579
+ message: first?.message ?? "Unknown SAP AI error",
580
+ requestId: first?.request_id
581
+ };
582
+ }
583
+ const entry = innerError;
584
+ return {
585
+ code: entry.code,
586
+ location: entry.location,
587
+ message: entry.message,
588
+ requestId: entry.request_id
589
+ };
590
+ }
591
+ function extractModelIdentifier(message, location) {
592
+ const patterns = [
593
+ /deployment[:\s]+([a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*)/i,
594
+ /model[:\s]+([a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*)/i,
595
+ /resource[:\s]+([a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*)/i
596
+ ];
597
+ for (const pattern of patterns) {
598
+ const match = pattern.exec(message);
599
+ if (match?.[1]) {
600
+ return match[1];
601
+ }
602
+ }
603
+ if (location) {
604
+ const locationMatch = /([a-zA-Z0-9_-]+(?:\.[a-zA-Z0-9_-]+)*)/.exec(location);
605
+ if (locationMatch?.[1]) {
606
+ return locationMatch[1];
607
+ }
608
+ }
609
+ return void 0;
610
+ }
611
+ function findStructuredErrorResponse(rootError, axiosData) {
612
+ if (isStructuredErrorResponse(rootError)) return rootError;
613
+ if (isStructuredErrorResponse(axiosData)) return axiosData;
614
+ if (rootError instanceof Error) {
615
+ const parsed = tryExtractSAPErrorFromMessage(rootError.message);
616
+ if (isStructuredErrorResponse(parsed)) return parsed;
617
+ }
618
+ return void 0;
619
+ }
620
+ function getStatusCodeFromSAPError(code, httpStatusCode) {
621
+ if (isHttpStatus(code)) {
622
+ return code;
623
+ }
624
+ if (isHttpStatus(httpStatusCode)) {
625
+ return httpStatusCode;
626
+ }
627
+ return HTTP_STATUS.INTERNAL_ERROR;
628
+ }
629
+ function inspectError(error) {
630
+ const seen = /* @__PURE__ */ new Set();
631
+ let rootError = error;
632
+ let current = error;
633
+ let response;
634
+ let aborted = false;
635
+ while (typeof current === "object" && current !== null && !seen.has(current)) {
636
+ seen.add(current);
637
+ rootError = current;
638
+ aborted ||= isAbortError(current);
639
+ const entry = current;
640
+ if (response === void 0 && entry.isAxiosError === true) response = entry.response;
641
+ const cause = "cause" in entry ? entry.cause : current instanceof Error && isErrorWithCause(current) ? current.rootCause : void 0;
642
+ if (cause === void 0 || typeof cause === "object" && cause !== null && seen.has(cause)) {
643
+ break;
644
+ }
645
+ rootError = cause;
646
+ current = cause;
647
+ }
648
+ return { aborted, response, rootError };
649
+ }
650
+ function isAbortError(error) {
651
+ if (error instanceof DOMException && error.name === "AbortError") {
652
+ return true;
653
+ }
654
+ if (error instanceof Error && error.name === "AbortError") {
655
+ return true;
656
+ }
657
+ const transportError = error;
658
+ return transportError.isAxiosError === true && transportError.code === "ERR_CANCELED";
659
+ }
660
+ function isHttpStatus(status) {
661
+ return typeof status === "number" && Number.isInteger(status) && status >= 100 && status < 600;
662
+ }
663
+ function isRetryable(statusCode) {
664
+ return statusCode === HTTP_STATUS.REQUEST_TIMEOUT || statusCode === HTTP_STATUS.CONFLICT || statusCode === HTTP_STATUS.RATE_LIMIT || statusCode >= HTTP_STATUS.INTERNAL_ERROR && statusCode < 600;
665
+ }
666
+ function isStructuredErrorResponse(error) {
667
+ if (error === null || typeof error !== "object" || !("error" in error)) {
668
+ return false;
669
+ }
670
+ const errorEnvelope = error;
671
+ const innerError = errorEnvelope.error;
672
+ if (innerError === void 0) return false;
673
+ if (Array.isArray(innerError)) {
674
+ return innerError.every((entry) => {
675
+ if (entry === null || typeof entry !== "object" || !("message" in entry)) {
676
+ return false;
677
+ }
678
+ const errorEntry = entry;
679
+ if (typeof errorEntry.message !== "string") {
680
+ return false;
681
+ }
682
+ if ("code" in entry && errorEntry.code != null && typeof errorEntry.code !== "number") {
683
+ return false;
684
+ }
685
+ return true;
686
+ });
687
+ }
688
+ if (typeof innerError !== "object" || innerError === null || !("message" in innerError)) {
689
+ return false;
690
+ }
691
+ const errorObj = innerError;
692
+ if (typeof errorObj.message !== "string") {
693
+ return false;
694
+ }
695
+ if ("code" in innerError && errorObj.code != null && typeof errorObj.code !== "number") {
696
+ return false;
697
+ }
698
+ return true;
699
+ }
700
+ function serializeAxiosResponseData(data, maxLength = 2e3) {
701
+ if (data === void 0) return void 0;
702
+ let serialized;
703
+ try {
704
+ if (typeof data === "string") {
705
+ serialized = data;
706
+ } else {
707
+ const json = JSON.stringify(data, null, 2);
708
+ serialized = typeof json === "string" ? json : `[Unable to serialize: ${typeof data}]`;
709
+ }
710
+ } catch {
711
+ serialized = `[Unable to serialize: ${typeof data}]`;
712
+ }
713
+ if (serialized.length > maxLength) {
714
+ return serialized.slice(0, maxLength) + "...[truncated]";
715
+ }
716
+ return serialized;
717
+ }
718
+ function tryExtractSAPErrorFromMessage(message) {
719
+ const startIdx = message.indexOf("{");
720
+ if (startIdx === -1) return null;
721
+ let depth = 0;
722
+ let endIdx = -1;
723
+ let inString = false;
724
+ let escaped = false;
725
+ for (let i = startIdx; i < message.length; i++) {
726
+ const character = message.charCodeAt(i);
727
+ if (inString) {
728
+ if (escaped) escaped = false;
729
+ else if (character === 92) escaped = true;
730
+ else if (character === 34) inString = false;
731
+ continue;
732
+ }
733
+ if (character === 34) inString = true;
734
+ else if (character === 123) depth++;
735
+ else if (character === 125) {
736
+ depth--;
737
+ if (depth === 0) {
738
+ endIdx = i;
739
+ break;
740
+ }
741
+ }
742
+ }
743
+ if (endIdx === -1) return null;
744
+ try {
745
+ const parsed = JSON.parse(message.slice(startIdx, endIdx + 1));
746
+ if (parsed && typeof parsed === "object" && "error" in parsed) {
747
+ return parsed;
748
+ }
749
+ if (parsed && typeof parsed === "object" && "message" in parsed) {
750
+ return { error: parsed };
751
+ }
752
+ return null;
753
+ } catch {
754
+ return null;
755
+ }
756
+ }
757
+
758
+ // src/version.ts
759
+ var VERSION = true ? "5.0.2" : "0.0.0-test";
760
+
761
+ export {
762
+ SAP_AI_PROVIDER_NAME,
763
+ getProviderName,
764
+ validateEmbeddingModelParamsSettings,
765
+ validateModelParamsSettings,
766
+ validateModelParamsWithWarnings,
767
+ parseSAPPartProviderOptions,
768
+ orchestrationConfigRefSchema,
769
+ sapAILanguageModelProviderOptions,
770
+ sapAIEmbeddingProviderOptions,
771
+ deepMerge,
772
+ ApiSwitchError,
773
+ UnsupportedFeatureError,
774
+ convertToAISDKError,
775
+ normalizeHeaders,
776
+ VERSION
777
+ };
778
+ //# sourceMappingURL=chunk-77JSAAPE.js.map