@jerome-benoit/sap-ai-provider-v2 5.0.2 → 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.
Files changed (44) hide show
  1. package/README.md +44 -24
  2. package/dist/chunk-4ILJD6PI.js +333 -0
  3. package/dist/chunk-4ILJD6PI.js.map +1 -0
  4. package/dist/chunk-BHA5MIN6.js +224 -0
  5. package/dist/chunk-BHA5MIN6.js.map +1 -0
  6. package/dist/{chunk-LEME2MFD.js → chunk-DLGBK3C3.js} +91 -7
  7. package/dist/chunk-DLGBK3C3.js.map +1 -0
  8. package/dist/{chunk-NLMWIVG7.js → chunk-EUBI5ENK.js} +54 -27
  9. package/dist/chunk-EUBI5ENK.js.map +1 -0
  10. package/dist/{chunk-YP3AADWD.js → chunk-FKHOJ3ZC.js} +24 -3
  11. package/dist/chunk-FKHOJ3ZC.js.map +1 -0
  12. package/dist/{chunk-77JSAAPE.js → chunk-QFMHNGLB.js} +56 -218
  13. package/dist/chunk-QFMHNGLB.js.map +1 -0
  14. package/dist/{chunk-U6WJSLR7.js → chunk-QQQYMQPU.js} +19 -10
  15. package/dist/chunk-QQQYMQPU.js.map +1 -0
  16. package/dist/{chunk-QZOZ3PZT.js → chunk-ZOBD7PXJ.js} +118 -22
  17. package/dist/chunk-ZOBD7PXJ.js.map +1 -0
  18. package/dist/{foundation-models-embedding-model-strategy-A3WDDAYK.js → foundation-models-embedding-model-strategy-3WAKJXBY.js} +5 -4
  19. package/dist/{foundation-models-embedding-model-strategy-A3WDDAYK.js.map → foundation-models-embedding-model-strategy-3WAKJXBY.js.map} +1 -1
  20. package/dist/{foundation-models-language-model-strategy-6U6KK6KH.js → foundation-models-language-model-strategy-PJ26VXEA.js} +22 -9
  21. package/dist/foundation-models-language-model-strategy-PJ26VXEA.js.map +1 -0
  22. package/dist/index.cjs +1903 -384
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +798 -185
  25. package/dist/index.d.ts +798 -185
  26. package/dist/index.js +148 -24
  27. package/dist/index.js.map +1 -1
  28. package/dist/{orchestration-embedding-model-strategy-JO3QH5MR.js → orchestration-embedding-model-strategy-AZ76XLMD.js} +6 -5
  29. package/dist/{orchestration-embedding-model-strategy-JO3QH5MR.js.map → orchestration-embedding-model-strategy-AZ76XLMD.js.map} +1 -1
  30. package/dist/{orchestration-language-model-strategy-MBVA7BYX.js → orchestration-language-model-strategy-CT6RHCYO.js} +57 -19
  31. package/dist/orchestration-language-model-strategy-CT6RHCYO.js.map +1 -0
  32. package/dist/responses-language-model-strategy-UYTV6TPM.js +738 -0
  33. package/dist/responses-language-model-strategy-UYTV6TPM.js.map +1 -0
  34. package/dist/sap-ai-error-UPKYWPSS.js +16 -0
  35. package/dist/sap-ai-error-UPKYWPSS.js.map +1 -0
  36. package/package.json +79 -39
  37. package/dist/chunk-77JSAAPE.js.map +0 -1
  38. package/dist/chunk-LEME2MFD.js.map +0 -1
  39. package/dist/chunk-NLMWIVG7.js.map +0 -1
  40. package/dist/chunk-QZOZ3PZT.js.map +0 -1
  41. package/dist/chunk-U6WJSLR7.js.map +0 -1
  42. package/dist/chunk-YP3AADWD.js.map +0 -1
  43. package/dist/foundation-models-language-model-strategy-6U6KK6KH.js.map +0 -1
  44. package/dist/orchestration-language-model-strategy-MBVA7BYX.js.map +0 -1
@@ -1,197 +1,5 @@
1
1
  import {createRequire as __createRequire} from 'module';var require=__createRequire(import.meta.url);
2
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
3
  // src/sap-ai-error.ts
196
4
  import {
197
5
  APICallError,
@@ -213,6 +21,17 @@ var HTTP_STATUS = {
213
21
  SERVICE_UNAVAILABLE: 503,
214
22
  UNAUTHORIZED: 401
215
23
  };
24
+ var RETRYABLE_NETWORK_CODES = /* @__PURE__ */ new Set([
25
+ "EAI_AGAIN",
26
+ "ECONNABORTED",
27
+ "ECONNREFUSED",
28
+ "ECONNRESET",
29
+ "EHOSTUNREACH",
30
+ "ENETUNREACH",
31
+ "ENOTFOUND",
32
+ "EPIPE",
33
+ "ETIMEDOUT"
34
+ ]);
216
35
  var ERROR_MATCHERS = [
217
36
  {
218
37
  category: "network",
@@ -346,8 +165,13 @@ var UnsupportedFeatureError = class extends Error {
346
165
  * @param suggestedApi - The API that supports this feature.
347
166
  */
348
167
  constructor(feature, api, suggestedApi) {
349
- const apiName = api === "foundation-models" ? "Foundation Models" : "Orchestration";
350
- const suggestedApiName = suggestedApi === "foundation-models" ? "Foundation Models" : "Orchestration";
168
+ const names = {
169
+ "foundation-models": "Foundation Models",
170
+ orchestration: "Orchestration",
171
+ responses: "Responses"
172
+ };
173
+ const apiName = names[api];
174
+ const suggestedApiName = names[suggestedApi];
351
175
  super(`${feature} is not supported by ${apiName} API. Use ${suggestedApiName} API instead.`);
352
176
  this.feature = feature;
353
177
  this.api = api;
@@ -420,11 +244,18 @@ function convertToAISDKError(error, context) {
420
244
  if (APICallError.isInstance(error) || LoadAPIKeyError.isInstance(error) || NoSuchModelError.isInstance(error) || InvalidPromptError.isInstance(error) || UnsupportedFunctionalityError.isInstance(error)) {
421
245
  return error;
422
246
  }
423
- const { aborted, response, rootError } = inspectError(error);
247
+ const { aborted, networkCode, noMatchingDeployment, response, rootError, syntaxError } = inspectError(error);
248
+ if (noMatchingDeployment && !aborted) {
249
+ return new NoSuchModelError({
250
+ message: "SAP AI Core has no running deployment matching the requested model. Check the model ID, model version, resource group, and deployment status in your SAP AI Core instance.",
251
+ modelId: context?.modelId ?? "unknown",
252
+ modelType: context?.modelType ?? "languageModel"
253
+ });
254
+ }
424
255
  const responseHeaders = context?.responseHeaders ?? normalizeHeaders(response?.headers);
425
256
  if (!aborted) {
426
257
  const errorResponse = findStructuredErrorResponse(
427
- rootError instanceof SyntaxError ? void 0 : rootError,
258
+ syntaxError ? void 0 : rootError,
428
259
  response?.data
429
260
  );
430
261
  if (errorResponse) {
@@ -442,7 +273,8 @@ function convertToAISDKError(error, context) {
442
273
  };
443
274
  if (aborted) {
444
275
  return createAPICallError(
445
- error,
276
+ // Preserve cancellation priority without retaining credential-bearing criteria.
277
+ noMatchingDeployment ? void 0 : error,
446
278
  {
447
279
  isRetryable: false,
448
280
  message: "Request was aborted by the client",
@@ -451,28 +283,39 @@ function convertToAISDKError(error, context) {
451
283
  resolvedContext
452
284
  );
453
285
  }
454
- if (isHttpStatus(response?.status)) {
286
+ if (isHttpStatus(response?.status) && (networkCode === void 0 || syntaxError !== void 0 || response.status < 200 || response.status >= 300)) {
455
287
  return createAPICallError(
456
288
  error,
457
289
  {
458
290
  isRetryable: isRetryable(response.status),
459
- message: rootError instanceof SyntaxError && error instanceof Error ? error.message : rootError instanceof Error ? rootError.message : "SAP AI Core request failed",
291
+ message: syntaxError && error instanceof Error ? error.message : rootError instanceof Error ? rootError.message : "SAP AI Core request failed",
460
292
  statusCode: response.status
461
293
  },
462
294
  resolvedContext
463
295
  );
464
296
  }
465
- if (rootError instanceof SyntaxError) {
297
+ if (syntaxError) {
466
298
  return createAPICallError(
467
299
  error,
468
300
  {
469
301
  isRetryable: false,
470
- message: error instanceof Error && error !== rootError ? error.message : "Failed to parse SAP AI Core data.",
302
+ message: error instanceof Error && error !== syntaxError ? error.message : "Failed to parse SAP AI Core data.",
471
303
  statusCode: HTTP_STATUS.INTERNAL_ERROR
472
304
  },
473
305
  resolvedContext
474
306
  );
475
307
  }
308
+ if (networkCode) {
309
+ return createAPICallError(
310
+ error,
311
+ {
312
+ isRetryable: true,
313
+ message: `SAP AI Core network error (${networkCode})`,
314
+ statusCode: HTTP_STATUS.SERVICE_UNAVAILABLE
315
+ },
316
+ resolvedContext
317
+ );
318
+ }
476
319
  if (rootError instanceof Error) {
477
320
  const errorMsg = rootError.message.toLowerCase();
478
321
  const originalErrorMsg = rootError.message;
@@ -632,10 +475,18 @@ function inspectError(error) {
632
475
  let current = error;
633
476
  let response;
634
477
  let aborted = false;
478
+ let networkCode;
479
+ let noMatchingDeployment = false;
480
+ let syntaxError;
635
481
  while (typeof current === "object" && current !== null && !seen.has(current)) {
636
482
  seen.add(current);
637
483
  rootError = current;
484
+ noMatchingDeployment ||= current instanceof Error && current.message.startsWith("No deployment matched the given criteria:");
638
485
  aborted ||= isAbortError(current);
486
+ if (current instanceof SyntaxError) syntaxError ??= current;
487
+ if (current instanceof Error && "code" in current && typeof current.code === "string") {
488
+ if (RETRYABLE_NETWORK_CODES.has(current.code)) networkCode ??= current.code;
489
+ }
639
490
  const entry = current;
640
491
  if (response === void 0 && entry.isAxiosError === true) response = entry.response;
641
492
  const cause = "cause" in entry ? entry.cause : current instanceof Error && isErrorWithCause(current) ? current.rootCause : void 0;
@@ -645,7 +496,7 @@ function inspectError(error) {
645
496
  rootError = cause;
646
497
  current = cause;
647
498
  }
648
- return { aborted, response, rootError };
499
+ return { aborted, networkCode, noMatchingDeployment, response, rootError, syntaxError };
649
500
  }
650
501
  function isAbortError(error) {
651
502
  if (error instanceof DOMException && error.name === "AbortError") {
@@ -755,24 +606,11 @@ function tryExtractSAPErrorFromMessage(message) {
755
606
  }
756
607
  }
757
608
 
758
- // src/version.ts
759
- var VERSION = true ? "5.0.2" : "0.0.0-test";
760
-
761
609
  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
610
  ApiSwitchError,
773
611
  UnsupportedFeatureError,
612
+ convertSAPErrorToAPICallError,
774
613
  convertToAISDKError,
775
- normalizeHeaders,
776
- VERSION
614
+ normalizeHeaders
777
615
  };
778
- //# sourceMappingURL=chunk-77JSAAPE.js.map
616
+ //# sourceMappingURL=chunk-QFMHNGLB.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/sap-ai-error.ts"],"sourcesContent":["/** Error conversion utilities for SAP AI Core to Vercel AI SDK error types. */\nimport type { OrchestrationErrorResponse } from \"@sap-ai-sdk/orchestration\";\n\nimport {\n APICallError,\n InvalidPromptError,\n LoadAPIKeyError,\n NoSuchModelError,\n UnsupportedFunctionalityError,\n} from \"@ai-sdk/provider\";\nimport { isErrorWithCause } from \"@sap-cloud-sdk/util\";\n\nimport type { SAPAIApiType } from \"./sap-ai-settings.js\";\n\ninterface AxiosResponse {\n data?: unknown;\n headers?: unknown;\n status?: number;\n}\n\n/** Request metadata used when translating SAP failures. */\ninterface ErrorContext {\n httpStatusCode?: number;\n modelId?: string;\n modelType?: \"embeddingModel\" | \"languageModel\";\n operation?: string;\n requestBody?: unknown;\n responseHeaders?: Record<string, string>;\n url?: string;\n}\n\n/** Diagnostic response body is retained explicitly, never appended to the message. */\ninterface ResolvedErrorContext extends ErrorContext {\n responseBody?: string;\n}\n\n/**\n * @internal\n */\nconst HTTP_STATUS = {\n BAD_REQUEST: 400,\n CLIENT_CLOSED_REQUEST: 499,\n CONFLICT: 409,\n FORBIDDEN: 403,\n INTERNAL_ERROR: 500,\n NOT_FOUND: 404,\n RATE_LIMIT: 429,\n REQUEST_TIMEOUT: 408,\n SERVICE_UNAVAILABLE: 503,\n UNAUTHORIZED: 401,\n} as const;\n\nconst RETRYABLE_NETWORK_CODES = new Set([\n \"EAI_AGAIN\",\n \"ECONNABORTED\",\n \"ECONNREFUSED\",\n \"ECONNRESET\",\n \"EHOSTUNREACH\",\n \"ENETUNREACH\",\n \"ENOTFOUND\",\n \"EPIPE\",\n \"ETIMEDOUT\",\n]);\n\n/**\n * Error message matchers for categorization and retryability.\n * @internal\n */\nconst ERROR_MATCHERS = [\n {\n category: \"network\",\n isRetryable: true,\n keywords: [\"econnrefused\", \"enotfound\", \"network\", \"timeout\"],\n statusCode: HTTP_STATUS.SERVICE_UNAVAILABLE,\n },\n {\n category: \"destination\",\n isRetryable: false,\n keywords: [\"could not resolve destination\"],\n message: (original: string) =>\n `SAP AI Core destination error: ${original}\\n\\n` +\n `Check your destination configuration or provide a valid destinationName.`,\n statusCode: HTTP_STATUS.BAD_REQUEST,\n },\n {\n category: \"content filtered\",\n isRetryable: false,\n keywords: [\"filtered by the output filter\"],\n message: (original: string) =>\n `Content was filtered: ${original}\\n\\n` +\n `The model's response was blocked by content safety filters. Try a different prompt.`,\n statusCode: HTTP_STATUS.BAD_REQUEST,\n },\n {\n category: \"stream consumption\",\n isRetryable: false,\n keywords: [\"consumed stream\"],\n statusCode: HTTP_STATUS.INTERNAL_ERROR,\n },\n {\n category: \"streaming\",\n isRetryable: true,\n keywords: [\n \"iterating over\",\n \"parse message into json\",\n \"received from\",\n \"no body\",\n \"invalid sse payload\",\n ],\n statusCode: HTTP_STATUS.INTERNAL_ERROR,\n },\n {\n category: \"configuration\",\n isRetryable: false,\n keywords: [\n \"prompt template or messages must be defined\",\n \"filtering parameters cannot be empty\",\n \"templating yaml string must be non-empty\",\n \"could not access response data\",\n \"could not parse json\",\n \"error parsing yaml\",\n \"yaml does not conform\",\n \"validation errors\",\n ],\n statusCode: HTTP_STATUS.BAD_REQUEST,\n },\n {\n category: \"environment\",\n isRetryable: false,\n keywords: [\"buffer is not available as globals\"],\n statusCode: HTTP_STATUS.INTERNAL_ERROR,\n },\n {\n category: \"response stream\",\n isRetryable: false,\n keywords: [\"response stream is undefined\"],\n statusCode: HTTP_STATUS.INTERNAL_ERROR,\n },\n {\n category: \"response processing\",\n isRetryable: true,\n keywords: [\n \"response is required to process\",\n \"stream is still open\",\n \"data is not available yet\",\n ],\n statusCode: HTTP_STATUS.INTERNAL_ERROR,\n },\n {\n category: \"deployment retrieval\",\n isRetryable: true,\n keywords: [\"failed to fetch the list of deployments\"],\n statusCode: HTTP_STATUS.SERVICE_UNAVAILABLE,\n },\n {\n category: \"stream buffer\",\n isRetryable: false,\n keywords: [\"received non-uint8array\"],\n statusCode: HTTP_STATUS.INTERNAL_ERROR,\n },\n] as const;\n\n/**\n * Keywords that indicate an authentication error.\n * @internal\n */\nconst AUTHENTICATION_ERROR_KEYWORDS = [\n \"authentication\",\n \"unauthorized\",\n \"aicore_service_key\",\n \"invalid credentials\",\n \"service credentials\",\n \"service binding\",\n] as const;\n\n/**\n * Keywords that indicate a deployment/model resolution error.\n * @internal\n */\nconst DEPLOYMENT_ERROR_KEYWORDS = [\n \"failed to resolve deployment\",\n \"no deployment matched\",\n] as const;\n\n/**\n * Error thrown when attempting to switch APIs at invocation time with conflicting model settings.\n * @example\n * ```typescript\n * const model = provider(\"gpt-4.1\", { filtering: { ... } });\n *\n * await generateText({\n * model,\n * providerOptions: { [SAP_AI_PROVIDER_NAME]: { api: \"foundation-models\" } },\n * prompt: \"Hello\",\n * });\n * // Throws: ApiSwitchError(\"orchestration\", \"foundation-models\", \"filtering\")\n * ```\n * @see {@link validateSettings} - Main validation function that throws this error\n * @see {@link UnsupportedFeatureError} - Related error for features unsupported by an API\n */\nexport class ApiSwitchError extends Error {\n /**\n * Creates a new ApiSwitchError.\n * @param fromApi - The API the model was configured with.\n * @param toApi - The API being switched to at invocation time.\n * @param conflictingFeature - The feature that prevents the API switch.\n */\n constructor(\n public readonly fromApi: SAPAIApiType,\n public readonly toApi: SAPAIApiType,\n public readonly conflictingFeature: string,\n ) {\n super(\n `Cannot switch from ${fromApi} to ${toApi} API at invocation time because ` +\n `${conflictingFeature} would be ignored. Create a new model instance without ` +\n `${fromApi}-specific features, or keep using the ${fromApi} API.`,\n );\n this.name = \"ApiSwitchError\";\n }\n}\n\n/**\n * Error thrown when a feature is used with an incompatible API.\n * @example\n * ```typescript\n * throw new UnsupportedFeatureError(\"Content filtering\", \"foundation-models\", \"orchestration\");\n * // Rejects the request: content filtering requires the Orchestration API.\n * ```\n * @see {@link validateSettings} - Main validation function that throws this error\n * @see {@link ApiSwitchError} - Related error for API switching conflicts\n */\nexport class UnsupportedFeatureError extends Error {\n /**\n * Creates a new UnsupportedFeatureError.\n * @param feature - The name of the unsupported feature (e.g., \"Content filtering\").\n * @param api - The API being used that does not support the feature.\n * @param suggestedApi - The API that supports this feature.\n */\n constructor(\n public readonly feature: string,\n public readonly api: SAPAIApiType,\n public readonly suggestedApi: SAPAIApiType,\n ) {\n const names: Record<SAPAIApiType, string> = {\n \"foundation-models\": \"Foundation Models\",\n orchestration: \"Orchestration\",\n responses: \"Responses\",\n };\n const apiName = names[api];\n const suggestedApiName = names[suggestedApi];\n super(`${feature} is not supported by ${apiName} API. Use ${suggestedApiName} API instead.`);\n this.name = \"UnsupportedFeatureError\";\n }\n}\n\n/**\n * Converts a structured SAP error response to the appropriate Vercel AI SDK error.\n * @param errorResponse - SAP orchestration error response.\n * @param context - Request context.\n * @param context.modelId - Known requested model ID, preferred over message-based extraction.\n * @param context.modelType - Requested model kind (defaults to languageModel).\n * @param context.httpStatusCode - Fallback HTTP status when the body code is missing or outside the HTTP status range.\n * @param context.requestBody - Original request body.\n * @param context.responseHeaders - Response headers.\n * @param context.url - Request URL.\n * @returns LoadAPIKeyError for 401/403, NoSuchModelError for 404, or APICallError otherwise.\n */\nexport function convertSAPErrorToAPICallError(\n errorResponse: OrchestrationErrorResponse,\n context?: ErrorContext,\n): APICallError | LoadAPIKeyError | NoSuchModelError {\n const { code, location, message, requestId } = extractErrorFields(errorResponse);\n\n const statusCode = getStatusCodeFromSAPError(code, context?.httpStatusCode);\n\n const responseBody = JSON.stringify({\n error: {\n code,\n location,\n message,\n request_id: requestId,\n },\n });\n\n let enhancedMessage = message;\n\n if (statusCode === HTTP_STATUS.UNAUTHORIZED || statusCode === HTTP_STATUS.FORBIDDEN) {\n enhancedMessage +=\n \"\\n\\nAuthentication failed. Verify your AICORE_SERVICE_KEY environment variable is set correctly.\" +\n \"\\nSee: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-service-key\";\n if (requestId) {\n enhancedMessage += `\\nRequest ID: ${requestId}`;\n }\n return new LoadAPIKeyError({\n message: enhancedMessage,\n });\n }\n\n if (statusCode === HTTP_STATUS.NOT_FOUND) {\n enhancedMessage +=\n \"\\n\\nResource not found. The model or deployment may not exist in your SAP AI Core instance.\" +\n \"\\nSee: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-deployment-for-orchestration\";\n if (requestId) {\n enhancedMessage += `\\nRequest ID: ${requestId}`;\n }\n const modelId = context?.modelId ?? extractModelIdentifier(message, location);\n return new NoSuchModelError({\n message: enhancedMessage,\n modelId: modelId ?? \"unknown\",\n modelType: context?.modelType ?? \"languageModel\",\n });\n }\n\n if (statusCode === HTTP_STATUS.RATE_LIMIT) {\n enhancedMessage +=\n \"\\n\\nRate limit exceeded. Please try again later or contact your SAP administrator.\" +\n \"\\nSee: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/rate-limits\";\n } else if (statusCode >= HTTP_STATUS.INTERNAL_ERROR) {\n enhancedMessage +=\n \"\\n\\nSAP AI Core service error. This is typically a temporary issue. Retries depend on the caller's retry configuration.\" +\n \"\\nSee: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/troubleshooting\";\n } else if (location) {\n enhancedMessage += `\\n\\nError location: ${location}`;\n }\n\n if (requestId) {\n enhancedMessage += `\\nRequest ID: ${requestId}`;\n }\n\n return new APICallError({\n isRetryable: isRetryable(statusCode),\n message: enhancedMessage,\n requestBodyValues: context?.requestBody,\n responseBody,\n responseHeaders: context?.responseHeaders,\n statusCode,\n url: context?.url ?? \"\",\n });\n}\n\n/**\n * Converts SAP failures while preserving standard request and API errors across SDK versions.\n * @param error - Error to convert.\n * @param context - Request context.\n * @param context.modelId - Known requested model ID, preferred over message-based extraction.\n * @param context.modelType - Requested model kind (defaults to languageModel).\n * @param context.operation - Operation name.\n * @param context.requestBody - Original request body.\n * @param context.responseHeaders - Response headers.\n * @param context.url - Request URL.\n * @returns Vercel AI SDK error.\n */\nexport function convertToAISDKError(\n error: unknown,\n context?: ErrorContext,\n):\n | APICallError\n | InvalidPromptError\n | LoadAPIKeyError\n | NoSuchModelError\n | UnsupportedFunctionalityError {\n if (\n APICallError.isInstance(error) ||\n LoadAPIKeyError.isInstance(error) ||\n NoSuchModelError.isInstance(error) ||\n InvalidPromptError.isInstance(error) ||\n UnsupportedFunctionalityError.isInstance(error)\n ) {\n return error;\n }\n\n const { aborted, networkCode, noMatchingDeployment, response, rootError, syntaxError } =\n inspectError(error);\n if (noMatchingDeployment && !aborted) {\n // SAP serializes discovery criteria, including custom destination credentials.\n // Neither the criteria nor the original cause may escape this boundary.\n return new NoSuchModelError({\n message:\n \"SAP AI Core has no running deployment matching the requested model. \" +\n \"Check the model ID, model version, resource group, and deployment status in your SAP AI Core instance.\",\n modelId: context?.modelId ?? \"unknown\",\n modelType: context?.modelType ?? \"languageModel\",\n });\n }\n const responseHeaders = context?.responseHeaders ?? normalizeHeaders(response?.headers);\n if (!aborted) {\n const errorResponse = findStructuredErrorResponse(\n syntaxError ? undefined : rootError,\n response?.data,\n );\n if (errorResponse) {\n return convertSAPErrorToAPICallError(errorResponse, {\n ...context,\n httpStatusCode: response?.status ?? context?.httpStatusCode,\n responseHeaders,\n });\n }\n }\n\n const resolvedContext: ResolvedErrorContext = {\n ...context,\n responseBody: serializeAxiosResponseData(response?.data),\n responseHeaders,\n };\n if (aborted) {\n return createAPICallError(\n // Preserve cancellation priority without retaining credential-bearing criteria.\n noMatchingDeployment ? undefined : error,\n {\n isRetryable: false,\n message: \"Request was aborted by the client\",\n statusCode: HTTP_STATUS.CLIENT_CLOSED_REQUEST,\n },\n resolvedContext,\n );\n }\n\n // Successful headers do not establish a successful response-body read.\n if (\n isHttpStatus(response?.status) &&\n (networkCode === undefined ||\n syntaxError !== undefined ||\n response.status < 200 ||\n response.status >= 300)\n ) {\n return createAPICallError(\n error,\n {\n isRetryable: isRetryable(response.status),\n message:\n syntaxError && error instanceof Error\n ? error.message\n : rootError instanceof Error\n ? rootError.message\n : \"SAP AI Core request failed\",\n statusCode: response.status,\n },\n resolvedContext,\n );\n }\n\n // Native parser messages can contain credential or response fragments. Keep the\n // enclosing SDK message instead, with the original chain available only as cause.\n if (syntaxError) {\n return createAPICallError(\n error,\n {\n isRetryable: false,\n message:\n error instanceof Error && error !== syntaxError\n ? error.message\n : \"Failed to parse SAP AI Core data.\",\n statusCode: HTTP_STATUS.INTERNAL_ERROR,\n },\n resolvedContext,\n );\n }\n\n if (networkCode) {\n return createAPICallError(\n error,\n {\n isRetryable: true,\n message: `SAP AI Core network error (${networkCode})`,\n statusCode: HTTP_STATUS.SERVICE_UNAVAILABLE,\n },\n resolvedContext,\n );\n }\n\n if (rootError instanceof Error) {\n const errorMsg = rootError.message.toLowerCase();\n const originalErrorMsg = rootError.message;\n\n if (AUTHENTICATION_ERROR_KEYWORDS.some((keyword) => errorMsg.includes(keyword))) {\n return new LoadAPIKeyError({\n message:\n `SAP AI Core authentication failed: ${originalErrorMsg}\\n\\n` +\n `Make sure your AICORE_SERVICE_KEY environment variable is set correctly.\\n` +\n `See: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-service-key`,\n });\n }\n\n if (DEPLOYMENT_ERROR_KEYWORDS.some((keyword) => errorMsg.includes(keyword))) {\n const modelId = context?.modelId ?? extractModelIdentifier(originalErrorMsg);\n return new NoSuchModelError({\n message:\n `SAP AI Core deployment error: ${originalErrorMsg}\\n\\n` +\n `Make sure you have a running orchestration deployment in your SAP AI Core instance.\\n` +\n `See: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-deployment-for-orchestration`,\n modelId: modelId ?? \"unknown\",\n modelType: context?.modelType ?? \"languageModel\",\n });\n }\n\n const statusMatch = /status code (\\d+)/i.exec(originalErrorMsg);\n const extractedStatus = statusMatch?.[1] ? Number.parseInt(statusMatch[1], 10) : undefined;\n if (isHttpStatus(extractedStatus)) {\n return createAPICallError(\n error,\n {\n isRetryable: isRetryable(extractedStatus),\n message: `SAP AI Core request failed: ${originalErrorMsg}`,\n statusCode: extractedStatus,\n },\n resolvedContext,\n );\n }\n\n for (const matcher of ERROR_MATCHERS) {\n if (matcher.keywords.some((keyword) => errorMsg.includes(keyword))) {\n const message =\n \"message\" in matcher\n ? matcher.message(originalErrorMsg)\n : `SAP AI Core ${matcher.category} error: ${originalErrorMsg}`;\n return createAPICallError(\n error,\n {\n isRetryable: matcher.isRetryable,\n message,\n statusCode: matcher.statusCode,\n },\n resolvedContext,\n );\n }\n }\n }\n\n const message =\n rootError instanceof Error\n ? rootError.message\n : typeof rootError === \"string\"\n ? rootError\n : \"Unknown error occurred\";\n\n const fullMessage = context?.operation\n ? `SAP AI Core ${context.operation} failed: ${message}`\n : `SAP AI Core error: ${message}`;\n\n return createAPICallError(\n error,\n {\n isRetryable: false,\n message: fullMessage,\n statusCode: HTTP_STATUS.INTERNAL_ERROR,\n },\n resolvedContext,\n );\n}\n\n/**\n * Normalizes various header formats to a string record.\n * @param headers - Headers to normalize.\n * @returns Normalized headers record.\n */\nexport function normalizeHeaders(headers: unknown): Record<string, string> | undefined {\n if (!headers || typeof headers !== \"object\") return undefined;\n\n if (typeof Headers !== \"undefined\" && headers instanceof Headers) {\n const out = Object.fromEntries(headers.entries());\n return Object.keys(out).length === 0 ? undefined : out;\n }\n\n const record = headers as Record<string, unknown>;\n const entries = Object.entries(record).flatMap(([key, value]) => {\n const k = key.toLowerCase();\n if (typeof value === \"string\") return [[k, value]];\n if (Array.isArray(value)) {\n const strings = value.filter((item): item is string => typeof item === \"string\").join(\"; \");\n return strings.length > 0 ? [[k, strings]] : [];\n }\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return [[k, String(value)]];\n }\n return [];\n });\n\n if (entries.length === 0) return undefined;\n return Object.fromEntries(entries) as Record<string, string>;\n}\n\n/**\n * Builds an API error with diagnostics kept separate from the message.\n * @param error - Original error.\n * @param options - Error options.\n * @param options.isRetryable - Whether error is retryable.\n * @param options.message - Error message.\n * @param options.statusCode - HTTP status code.\n * @param context - Request context.\n * @param context.operation - Operation name.\n * @param context.requestBody - Original request body.\n * @param context.responseHeaders - Response headers.\n * @param context.url - Request URL.\n * @returns API call error.\n * @internal\n */\nfunction createAPICallError(\n error: unknown,\n options: {\n isRetryable: boolean;\n message: string;\n statusCode: number;\n },\n context?: ResolvedErrorContext,\n): APICallError {\n return new APICallError({\n cause: error,\n isRetryable: options.isRetryable,\n message: options.message,\n requestBodyValues: context?.requestBody,\n responseBody: context?.responseBody,\n responseHeaders: context?.responseHeaders,\n statusCode: options.statusCode,\n url: context?.url ?? \"\",\n });\n}\n\n/**\n * @param response - SAP orchestration error response.\n * @returns Destructured error fields (message, code, location, requestId).\n * @internal\n */\nfunction extractErrorFields(response: OrchestrationErrorResponse): {\n code?: number;\n location?: string;\n message: string;\n requestId?: string;\n} {\n const innerError = response.error;\n if (Array.isArray(innerError)) {\n const first = innerError[0] as\n undefined | { code?: number; location?: string; message: string; request_id?: string };\n return {\n code: first?.code,\n location: first?.location,\n message: first?.message ?? \"Unknown SAP AI error\",\n requestId: first?.request_id,\n };\n }\n const entry = innerError as {\n code?: number;\n location?: string;\n message: string;\n request_id?: string;\n };\n return {\n code: entry.code,\n location: entry.location,\n message: entry.message,\n requestId: entry.request_id,\n };\n}\n\n/**\n * @param message - Error message.\n * @param location - Error location.\n * @returns Extracted model identifier.\n * @internal\n */\nfunction extractModelIdentifier(message: string, location?: string): string | undefined {\n const patterns = [\n /deployment[:\\s]+([a-zA-Z0-9_-]+(?:\\.[a-zA-Z0-9_-]+)*)/i,\n /model[:\\s]+([a-zA-Z0-9_-]+(?:\\.[a-zA-Z0-9_-]+)*)/i,\n /resource[:\\s]+([a-zA-Z0-9_-]+(?:\\.[a-zA-Z0-9_-]+)*)/i,\n ];\n\n for (const pattern of patterns) {\n const match = pattern.exec(message);\n if (match?.[1]) {\n return match[1];\n }\n }\n\n if (location) {\n const locationMatch = /([a-zA-Z0-9_-]+(?:\\.[a-zA-Z0-9_-]+)*)/.exec(location);\n if (locationMatch?.[1]) {\n return locationMatch[1];\n }\n }\n\n return undefined;\n}\n\n/**\n * @param rootError - Root cause after inspecting the chain.\n * @param axiosData - Response data retained from an Axios wrapper.\n * @returns A structured SAP response when available.\n */\nfunction findStructuredErrorResponse(\n rootError: unknown,\n axiosData: unknown,\n): OrchestrationErrorResponse | undefined {\n if (isStructuredErrorResponse(rootError)) return rootError;\n if (isStructuredErrorResponse(axiosData)) return axiosData;\n if (rootError instanceof Error) {\n const parsed = tryExtractSAPErrorFromMessage(rootError.message);\n if (isStructuredErrorResponse(parsed)) return parsed;\n }\n return undefined;\n}\n\n/**\n * @param code - SAP error code.\n * @param httpStatusCode - HTTP status code from the response, used as fallback.\n * @returns HTTP status code.\n * @internal\n */\nfunction getStatusCodeFromSAPError(code?: number, httpStatusCode?: number): number {\n if (isHttpStatus(code)) {\n return code;\n }\n\n if (isHttpStatus(httpStatusCode)) {\n return httpStatusCode;\n }\n\n return HTTP_STATUS.INTERNAL_ERROR;\n}\n\n/**\n * Inspects native and SAP cause chains once, keeping transport metadata from wrappers.\n * @param error - Raw SDK error.\n * @returns The terminal cause, transport metadata, and classified native failures.\n */\nfunction inspectError(error: unknown): {\n aborted: boolean;\n networkCode?: string;\n noMatchingDeployment: boolean;\n response?: AxiosResponse;\n rootError: unknown;\n syntaxError?: SyntaxError;\n} {\n const seen = new Set<object>();\n let rootError = error;\n let current = error;\n let response: AxiosResponse | undefined;\n let aborted = false;\n let networkCode: string | undefined;\n let noMatchingDeployment = false;\n let syntaxError: SyntaxError | undefined;\n while (typeof current === \"object\" && current !== null && !seen.has(current)) {\n seen.add(current);\n rootError = current;\n noMatchingDeployment ||=\n current instanceof Error &&\n current.message.startsWith(\"No deployment matched the given criteria:\");\n aborted ||= isAbortError(current);\n if (current instanceof SyntaxError) syntaxError ??= current;\n if (current instanceof Error && \"code\" in current && typeof current.code === \"string\") {\n if (RETRYABLE_NETWORK_CODES.has(current.code)) networkCode ??= current.code;\n }\n const entry = current as { cause?: unknown; isAxiosError?: boolean; response?: AxiosResponse };\n if (response === undefined && entry.isAxiosError === true) response = entry.response;\n // SAP ErrorWithCause exposes a native cause too. Avoid its recursive rootCause\n // getter when that cause is present so cyclic chains cannot overflow the stack.\n const cause =\n \"cause\" in entry\n ? entry.cause\n : current instanceof Error && isErrorWithCause(current)\n ? current.rootCause\n : undefined;\n if (cause === undefined || (typeof cause === \"object\" && cause !== null && seen.has(cause))) {\n break;\n }\n rootError = cause;\n current = cause;\n }\n return { aborted, networkCode, noMatchingDeployment, response, rootError, syntaxError };\n}\n\n/**\n * Identifies native aborts and Axios cancellations retained in SAP error causes.\n * @param error - Error to check.\n * @returns Whether the error represents request cancellation.\n * @internal\n */\nfunction isAbortError(error: object): boolean {\n if (error instanceof DOMException && error.name === \"AbortError\") {\n return true;\n }\n if (error instanceof Error && error.name === \"AbortError\") {\n return true;\n }\n const transportError = error as { code?: unknown; isAxiosError?: unknown };\n return transportError.isAxiosError === true && transportError.code === \"ERR_CANCELED\";\n}\n\n/**\n * @param status - Candidate HTTP status.\n * @returns Whether the value is an integer HTTP status.\n */\nfunction isHttpStatus(status: unknown): status is number {\n return typeof status === \"number\" && Number.isInteger(status) && status >= 100 && status < 600;\n}\n\n/**\n * @param statusCode - HTTP status code.\n * @returns True if error is retryable.\n * @internal\n */\nfunction isRetryable(statusCode: number): boolean {\n return (\n statusCode === HTTP_STATUS.REQUEST_TIMEOUT ||\n statusCode === HTTP_STATUS.CONFLICT ||\n statusCode === HTTP_STATUS.RATE_LIMIT ||\n (statusCode >= HTTP_STATUS.INTERNAL_ERROR && statusCode < 600)\n );\n}\n\n/**\n * @param error - Error to check.\n * @returns True if error is an orchestration error response.\n * @internal\n */\nfunction isStructuredErrorResponse(error: unknown): error is OrchestrationErrorResponse {\n if (error === null || typeof error !== \"object\" || !(\"error\" in error)) {\n return false;\n }\n\n const errorEnvelope = error as { error?: unknown };\n const innerError = errorEnvelope.error;\n\n if (innerError === undefined) return false;\n\n if (Array.isArray(innerError)) {\n return innerError.every((entry) => {\n if (entry === null || typeof entry !== \"object\" || !(\"message\" in entry)) {\n return false;\n }\n const errorEntry = entry as { code?: unknown; message?: unknown };\n if (typeof errorEntry.message !== \"string\") {\n return false;\n }\n if (\"code\" in entry && errorEntry.code != null && typeof errorEntry.code !== \"number\") {\n return false;\n }\n return true;\n });\n }\n\n if (typeof innerError !== \"object\" || innerError === null || !(\"message\" in innerError)) {\n return false;\n }\n\n const errorObj = innerError as { code?: unknown; message?: unknown };\n if (typeof errorObj.message !== \"string\") {\n return false;\n }\n if (\"code\" in innerError && errorObj.code != null && typeof errorObj.code !== \"number\") {\n return false;\n }\n\n return true;\n}\n\n/**\n * @param data - Data to serialize.\n * @param maxLength - Maximum output length.\n * @returns Serialized data.\n * @internal\n */\nfunction serializeAxiosResponseData(data: unknown, maxLength = 2000): string | undefined {\n if (data === undefined) return undefined;\n\n let serialized: string;\n try {\n if (typeof data === \"string\") {\n serialized = data;\n } else {\n const json: unknown = JSON.stringify(data, null, 2);\n serialized = typeof json === \"string\" ? json : `[Unable to serialize: ${typeof data}]`;\n }\n } catch {\n serialized = `[Unable to serialize: ${typeof data}]`;\n }\n\n if (serialized.length > maxLength) {\n return serialized.slice(0, maxLength) + \"...[truncated]\";\n }\n return serialized;\n}\n\n/**\n * @param message - Error message to parse.\n * @returns Extracted SAP error or null.\n * @internal\n */\nfunction tryExtractSAPErrorFromMessage(message: string): unknown {\n const startIdx = message.indexOf(\"{\");\n if (startIdx === -1) return null;\n\n let depth = 0;\n let endIdx = -1;\n let inString = false;\n let escaped = false;\n for (let i = startIdx; i < message.length; i++) {\n const character = message.charCodeAt(i);\n if (inString) {\n if (escaped) escaped = false;\n else if (character === 0x5c) escaped = true;\n else if (character === 0x22) inString = false;\n continue;\n }\n if (character === 0x22) inString = true;\n else if (character === 0x7b) depth++;\n else if (character === 0x7d) {\n depth--;\n if (depth === 0) {\n endIdx = i;\n break;\n }\n }\n }\n if (endIdx === -1) return null;\n\n try {\n const parsed: unknown = JSON.parse(message.slice(startIdx, endIdx + 1));\n\n if (parsed && typeof parsed === \"object\" && \"error\" in parsed) {\n return parsed;\n }\n\n if (parsed && typeof parsed === \"object\" && \"message\" in parsed) {\n return { error: parsed as Record<string, unknown> };\n }\n\n return null;\n } catch {\n return null;\n }\n}\n"],"mappings":"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","names":["message"]}
@@ -1,14 +1,18 @@
1
1
  import {createRequire as __createRequire} from 'module';var require=__createRequire(import.meta.url);
2
2
  import {
3
3
  buildEmbeddingResult,
4
- mergeRequestConfig
5
- } from "./chunk-LEME2MFD.js";
4
+ mergeRequestConfig,
5
+ throwIfAborted,
6
+ waitWithAbort
7
+ } from "./chunk-DLGBK3C3.js";
6
8
  import {
7
9
  VERSION,
8
- convertToAISDKError,
9
10
  deepMerge,
10
11
  getProviderName
11
- } from "./chunk-77JSAAPE.js";
12
+ } from "./chunk-BHA5MIN6.js";
13
+ import {
14
+ convertToAISDKError
15
+ } from "./chunk-QFMHNGLB.js";
12
16
 
13
17
  // src/base-embedding-model-strategy.ts
14
18
  import { TooManyEmbeddingValuesForCallError } from "@ai-sdk/provider";
@@ -33,18 +37,23 @@ var BaseEmbeddingModelStrategy = class {
33
37
  values
34
38
  });
35
39
  }
40
+ throwIfAborted(abortSignal);
36
41
  const embeddingOptions = config.parsedProviderOptions;
37
42
  const providerName = getProviderName(config.provider);
38
43
  const embeddingType = embeddingOptions?.type ?? settings.type ?? "text";
39
44
  const warnings = [];
40
45
  this.resolveWarnings(settings, warnings);
41
46
  const client = this.createClient(config, settings, embeddingOptions);
42
- const response = await this.executeCall(
43
- client,
44
- values,
45
- embeddingType,
46
- mergeRequestConfig(config.requestConfig, abortSignal, options.headers)
47
+ const response = await waitWithAbort(
48
+ this.executeCall(
49
+ client,
50
+ values,
51
+ embeddingType,
52
+ mergeRequestConfig(config.requestConfig, abortSignal, options.headers)
53
+ ),
54
+ abortSignal
47
55
  );
56
+ throwIfAborted(abortSignal);
48
57
  const embeddings = this.extractEmbeddings(response);
49
58
  const totalTokens = this.extractTokenCount(response);
50
59
  const { headers: responseHeaders, requestId } = this.extractResponseMetadata(response);
@@ -104,4 +113,4 @@ var BaseEmbeddingModelStrategy = class {
104
113
  export {
105
114
  BaseEmbeddingModelStrategy
106
115
  };
107
- //# sourceMappingURL=chunk-U6WJSLR7.js.map
116
+ //# sourceMappingURL=chunk-QQQYMQPU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/base-embedding-model-strategy.ts"],"sourcesContent":["/** Base class for embedding model strategies using the Template Method pattern. */\nimport type {\n EmbeddingModelV3CallOptions,\n EmbeddingModelV3Embedding,\n EmbeddingModelV3Result,\n SharedV3Warning,\n} from \"@ai-sdk/provider\";\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 { throwIfAborted, waitWithAbort } from \"./abort-utils.js\";\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 throwIfAborted(abortSignal);\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 waitWithAbort(\n this.executeCall(\n client,\n values,\n embeddingType,\n mergeRequestConfig(config.requestConfig, abortSignal, options.headers),\n ),\n abortSignal,\n );\n throwIfAborted(abortSignal);\n\n const embeddings = this.extractEmbeddings(response);\n const totalTokens = this.extractTokenCount(response);\n const { headers: responseHeaders, requestId } = this.extractResponseMetadata(response);\n\n return buildEmbeddingResult({\n embeddings,\n modelId: config.modelId,\n providerName,\n requestId,\n responseHeaders,\n totalTokens,\n version: VERSION,\n warnings,\n });\n } catch (error) {\n if (error instanceof TooManyEmbeddingValuesForCallError) {\n throw error;\n }\n throw convertToAISDKError(error, {\n 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;AAwB5C,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,qBAAe,WAAW;AAC1B,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;AAAA,QACrB,KAAK;AAAA,UACH;AAAA,UACA;AAAA,UACA;AAAA,UACA,mBAAmB,OAAO,eAAe,aAAa,QAAQ,OAAO;AAAA,QACvE;AAAA,QACA;AAAA,MACF;AACA,qBAAe,WAAW;AAE1B,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":[]}