@jerome-benoit/sap-ai-provider-v2 5.0.3 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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-4JLNWASF.js → chunk-DLGBK3C3.js} +91 -7
  7. package/dist/chunk-DLGBK3C3.js.map +1 -0
  8. package/dist/{chunk-E76ZDPIW.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-UIBQ5AFS.js → chunk-QFMHNGLB.js} +56 -218
  13. package/dist/chunk-QFMHNGLB.js.map +1 -0
  14. package/dist/{chunk-3H5C5U22.js → chunk-QQQYMQPU.js} +19 -10
  15. package/dist/chunk-QQQYMQPU.js.map +1 -0
  16. package/dist/{chunk-NF355OFT.js → chunk-ZOBD7PXJ.js} +116 -21
  17. package/dist/chunk-ZOBD7PXJ.js.map +1 -0
  18. package/dist/{foundation-models-embedding-model-strategy-SAVQFBF4.js → foundation-models-embedding-model-strategy-3WAKJXBY.js} +5 -4
  19. package/dist/{foundation-models-embedding-model-strategy-SAVQFBF4.js.map → foundation-models-embedding-model-strategy-3WAKJXBY.js.map} +1 -1
  20. package/dist/{foundation-models-language-model-strategy-ZDOWVYTA.js → foundation-models-language-model-strategy-PJ26VXEA.js} +21 -8
  21. package/dist/foundation-models-language-model-strategy-PJ26VXEA.js.map +1 -0
  22. package/dist/index.cjs +2008 -497
  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-GT27AFII.js → orchestration-embedding-model-strategy-AZ76XLMD.js} +6 -5
  29. package/dist/{orchestration-embedding-model-strategy-GT27AFII.js.map → orchestration-embedding-model-strategy-AZ76XLMD.js.map} +1 -1
  30. package/dist/{orchestration-language-model-strategy-7QTPQHCC.js → orchestration-language-model-strategy-CT6RHCYO.js} +48 -17
  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-3H5C5U22.js.map +0 -1
  38. package/dist/chunk-4JLNWASF.js.map +0 -1
  39. package/dist/chunk-E76ZDPIW.js.map +0 -1
  40. package/dist/chunk-NF355OFT.js.map +0 -1
  41. package/dist/chunk-UIBQ5AFS.js.map +0 -1
  42. package/dist/chunk-YP3AADWD.js.map +0 -1
  43. package/dist/foundation-models-language-model-strategy-ZDOWVYTA.js.map +0 -1
  44. package/dist/orchestration-language-model-strategy-7QTPQHCC.js.map +0 -1
package/dist/index.cjs CHANGED
@@ -5,8 +5,13 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
6
  var __getProtoOf = Object.getPrototypeOf;
7
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
8
- var __esm = (fn, res) => function __init() {
9
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
8
+ var __esm = (fn, res, err) => function __init() {
9
+ if (err) throw err[0];
10
+ try {
11
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
12
+ } catch (e) {
13
+ throw err = [e], e;
14
+ }
10
15
  };
11
16
  var __export = (target, all) => {
12
17
  for (var name in all)
@@ -30,6 +35,181 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
30
35
  ));
31
36
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
37
 
38
+ // src/sap-ai-provider-options.ts
39
+ function getProviderName(providerIdentifier) {
40
+ const dotIndex = providerIdentifier.indexOf(".");
41
+ return dotIndex === -1 ? providerIdentifier : providerIdentifier.slice(0, dotIndex);
42
+ }
43
+ function validateEmbeddingModelParamsSettings(modelParams) {
44
+ return embeddingModelParamsSchema.parse(modelParams);
45
+ }
46
+ function validateModelParamsSettings(modelParams) {
47
+ return modelParamsSchema.parse(modelParams);
48
+ }
49
+ function validateModelParamsWithWarnings(params, warnings) {
50
+ const result = modelParamsSchema.safeParse(params);
51
+ if (!result.success) {
52
+ for (const issue of result.error.issues) {
53
+ const path = issue.path.join(".");
54
+ const value = path ? params[path] : void 0;
55
+ warnings.push({
56
+ message: `${path}=${String(value)} is invalid: ${issue.message}. The API may reject this value.`,
57
+ type: "other"
58
+ });
59
+ }
60
+ }
61
+ }
62
+ function parseSAPPartProviderOptions(providerOptions, warnings) {
63
+ if (!providerOptions || typeof providerOptions !== "object") {
64
+ return void 0;
65
+ }
66
+ const block = providerOptions[SAP_AI_PROVIDER_NAME];
67
+ if (block === void 0) {
68
+ return void 0;
69
+ }
70
+ const parsed = sapAIPartProviderOptionsSchema.safeParse(block);
71
+ if (parsed.success) {
72
+ return parsed.data;
73
+ }
74
+ if (warnings) {
75
+ for (const issue of parsed.error.issues) {
76
+ const path = issue.path.join(".");
77
+ const message = `providerOptions['sap-ai']${path ? `.${path}` : ""} is invalid: ${issue.message}. The directive was dropped.`;
78
+ if (!warnings.some((w) => w.message === message)) {
79
+ warnings.push({ message, type: "other" });
80
+ }
81
+ }
82
+ }
83
+ return void 0;
84
+ }
85
+ var import_provider_utils, import_zod, SAP_AI_PROVIDER_NAME, modelParamsSchema, embeddingModelParamsSchema, sapAIApiTypeSchema, cacheControlSchema, sapAIPartProviderOptionsSchema, orchestrationReasoningBlockSchema, promptTemplateScopeSchema, promptTemplateRefByIdSchema, promptTemplateRefByScenarioNameVersionSchema, promptTemplateRefSchema, orchestrationConfigRefOverrideSchema, orchestrationConfigRefByIdSchema, orchestrationConfigRefByScenarioNameVersionSchema, orchestrationConfigRefSchema, responsesModelOptionsSchema, dropUnsupportedParamsSchema, sapAILanguageModelProviderOptions, sapAIEmbeddingProviderOptions;
86
+ var init_sap_ai_provider_options = __esm({
87
+ "src/sap-ai-provider-options.ts"() {
88
+ "use strict";
89
+ import_provider_utils = require("@ai-sdk/provider-utils");
90
+ import_zod = require("zod");
91
+ SAP_AI_PROVIDER_NAME = "sap-ai";
92
+ modelParamsSchema = import_zod.z.object({
93
+ frequencyPenalty: import_zod.z.number().min(-2).max(2).optional(),
94
+ maxTokens: import_zod.z.number().int().positive().optional(),
95
+ n: import_zod.z.number().int().positive().optional(),
96
+ parallel_tool_calls: import_zod.z.boolean().optional(),
97
+ presencePenalty: import_zod.z.number().min(-2).max(2).optional(),
98
+ temperature: import_zod.z.number().min(0).max(2).optional(),
99
+ topP: import_zod.z.number().min(0).max(1).optional()
100
+ }).catchall(import_zod.z.unknown());
101
+ embeddingModelParamsSchema = import_zod.z.object({
102
+ dimensions: import_zod.z.number().int().positive().optional(),
103
+ encoding_format: import_zod.z.enum(["base64", "binary", "float"]).optional(),
104
+ normalize: import_zod.z.boolean().optional()
105
+ }).catchall(import_zod.z.unknown());
106
+ sapAIApiTypeSchema = import_zod.z.enum(["orchestration", "foundation-models", "responses"]);
107
+ cacheControlSchema = import_zod.z.object({
108
+ ttl: import_zod.z.enum(["5m", "1h"]).optional(),
109
+ type: import_zod.z.literal("ephemeral")
110
+ });
111
+ sapAIPartProviderOptionsSchema = import_zod.z.object({
112
+ cacheControl: cacheControlSchema.optional()
113
+ });
114
+ orchestrationReasoningBlockSchema = import_zod.z.object({
115
+ content: import_zod.z.string().optional(),
116
+ signature: import_zod.z.string().optional()
117
+ }).strict();
118
+ promptTemplateScopeSchema = import_zod.z.enum(["tenant", "resource_group"]);
119
+ promptTemplateRefByIdSchema = import_zod.z.object({
120
+ id: import_zod.z.string().min(1, "Template ID cannot be empty"),
121
+ scope: promptTemplateScopeSchema.optional()
122
+ });
123
+ promptTemplateRefByScenarioNameVersionSchema = import_zod.z.object({
124
+ name: import_zod.z.string().min(1, "Template name cannot be empty"),
125
+ scenario: import_zod.z.string().min(1, "Scenario cannot be empty"),
126
+ scope: promptTemplateScopeSchema.optional(),
127
+ version: import_zod.z.string().min(1, "Version cannot be empty")
128
+ });
129
+ promptTemplateRefSchema = import_zod.z.union([
130
+ promptTemplateRefByIdSchema,
131
+ promptTemplateRefByScenarioNameVersionSchema
132
+ ]);
133
+ orchestrationConfigRefOverrideSchema = import_zod.z.custom(
134
+ (value) => typeof value === "object" && value !== null && !Array.isArray(value),
135
+ { message: "overrideConfig must be an object" }
136
+ ).refine(
137
+ (value) => {
138
+ let stream;
139
+ try {
140
+ stream = value.stream;
141
+ } catch {
142
+ return false;
143
+ }
144
+ return stream === void 0 || Boolean(stream) && typeof stream === "object" && !Array.isArray(stream);
145
+ },
146
+ { message: "overrideConfig.stream must be an object" }
147
+ ).refine(
148
+ (value) => {
149
+ let stream;
150
+ try {
151
+ stream = value.stream;
152
+ } catch {
153
+ return true;
154
+ }
155
+ if (stream === void 0 || stream === null || typeof stream !== "object") {
156
+ return true;
157
+ }
158
+ try {
159
+ return !("enabled" in stream);
160
+ } catch {
161
+ return false;
162
+ }
163
+ },
164
+ {
165
+ message: "stream.enabled is not allowed in overrideConfig: it is controlled by the call site (stream() or chatCompletion())"
166
+ }
167
+ );
168
+ orchestrationConfigRefByIdSchema = import_zod.z.object({
169
+ id: import_zod.z.string().min(1, "Config ID cannot be empty"),
170
+ overrideConfig: orchestrationConfigRefOverrideSchema.optional()
171
+ });
172
+ orchestrationConfigRefByScenarioNameVersionSchema = import_zod.z.object({
173
+ name: import_zod.z.string().min(1, "Config name cannot be empty"),
174
+ overrideConfig: orchestrationConfigRefOverrideSchema.optional(),
175
+ scenario: import_zod.z.string().min(1, "Scenario cannot be empty"),
176
+ version: import_zod.z.string().min(1, "Version cannot be empty")
177
+ });
178
+ orchestrationConfigRefSchema = import_zod.z.union([
179
+ orchestrationConfigRefByIdSchema,
180
+ orchestrationConfigRefByScenarioNameVersionSchema
181
+ ]);
182
+ responsesModelOptionsSchema = import_zod.z.object({
183
+ metadata: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).nullable().optional()
184
+ }).catchall(import_zod.z.json());
185
+ dropUnsupportedParamsSchema = import_zod.z.boolean();
186
+ sapAILanguageModelProviderOptions = (0, import_provider_utils.lazySchema)(
187
+ () => (0, import_provider_utils.zodSchema)(
188
+ import_zod.z.object({
189
+ api: sapAIApiTypeSchema.optional(),
190
+ dropUnsupportedParams: dropUnsupportedParamsSchema.optional(),
191
+ escapeTemplatePlaceholders: import_zod.z.boolean().optional(),
192
+ includeReasoning: import_zod.z.boolean().optional(),
193
+ modelParams: modelParamsSchema.optional(),
194
+ orchestrationConfigRef: orchestrationConfigRefSchema.optional(),
195
+ placeholderValues: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional(),
196
+ promptTemplateRef: promptTemplateRefSchema.optional(),
197
+ responses: responsesModelOptionsSchema.optional()
198
+ })
199
+ )
200
+ );
201
+ sapAIEmbeddingProviderOptions = (0, import_provider_utils.lazySchema)(
202
+ () => (0, import_provider_utils.zodSchema)(
203
+ import_zod.z.object({
204
+ api: sapAIApiTypeSchema.optional(),
205
+ modelParams: embeddingModelParamsSchema.optional(),
206
+ type: import_zod.z.enum(["document", "query", "text"]).optional()
207
+ })
208
+ )
209
+ );
210
+ }
211
+ });
212
+
33
213
  // src/convert-to-sap-messages.ts
34
214
  function getURLHref(value) {
35
215
  if (typeof value !== "object" || value === null || URL_HREF_DESCRIPTOR?.get === void 0) {
@@ -171,6 +351,7 @@ function convertToSAPMessages(prompt, options = {}) {
171
351
  let text = "";
172
352
  const textParts = parser ? [] : void 0;
173
353
  let anyCacheControl = false;
354
+ let reasoningContent;
174
355
  const toolCalls = [];
175
356
  for (const part of message.content) {
176
357
  switch (part.type) {
@@ -182,6 +363,21 @@ function convertToSAPMessages(prompt, options = {}) {
182
363
  break;
183
364
  }
184
365
  case "reasoning": {
366
+ const nativeNamespace = options.nativeReasoningProviderName;
367
+ const nativeOptions = nativeNamespace === void 0 ? void 0 : part.providerOptions?.[nativeNamespace];
368
+ if (nativeOptions !== null && typeof nativeOptions === "object" && !Array.isArray(nativeOptions) && Object.hasOwn(nativeOptions, "reasoningContent")) {
369
+ const parsed = orchestrationReasoningBlockSchema.safeParse(
370
+ nativeOptions.reasoningContent
371
+ );
372
+ if (!parsed.success) {
373
+ throw new import_provider.InvalidPromptError({
374
+ message: "Invalid native Orchestration reasoning metadata.",
375
+ prompt
376
+ });
377
+ }
378
+ (reasoningContent ??= []).push(parsed.data);
379
+ break;
380
+ }
185
381
  if (includeReasoning && part.text) {
186
382
  const reasoning = `<think>${part.text}</think>`;
187
383
  text += reasoning;
@@ -228,11 +424,12 @@ function convertToSAPMessages(prompt, options = {}) {
228
424
  }
229
425
  }
230
426
  }
231
- if (text || toolCalls.length > 0) {
427
+ if (text || toolCalls.length > 0 || reasoningContent?.length) {
232
428
  const assistantMessage = {
233
429
  content: anyCacheControl && textParts ? textParts.map((p) => wrapAsTextContent(maybeEscape(p.text), p.cacheControl)) : maybeEscape(text),
234
430
  role: "assistant",
235
- tool_calls: toolCalls.length > 0 ? toolCalls : void 0
431
+ tool_calls: toolCalls.length > 0 ? toolCalls : void 0,
432
+ ...reasoningContent && { reasoning_content: reasoningContent }
236
433
  };
237
434
  messages.push(assistantMessage);
238
435
  }
@@ -388,6 +585,7 @@ var init_convert_to_sap_messages = __esm({
388
585
  "src/convert-to-sap-messages.ts"() {
389
586
  "use strict";
390
587
  import_provider = require("@ai-sdk/provider");
588
+ init_sap_ai_provider_options();
391
589
  ZERO_WIDTH_SPACE = "\u200B";
392
590
  ARRAY_BUFFER_BYTE_LENGTH_DESCRIPTOR = Object.getOwnPropertyDescriptor(
393
591
  ArrayBuffer.prototype,
@@ -408,260 +606,64 @@ var init_convert_to_sap_messages = __esm({
408
606
  }
409
607
  });
410
608
 
411
- // src/sap-ai-provider-options.ts
412
- function getProviderName(providerIdentifier) {
413
- const dotIndex = providerIdentifier.indexOf(".");
414
- return dotIndex === -1 ? providerIdentifier : providerIdentifier.slice(0, dotIndex);
415
- }
416
- function validateEmbeddingModelParamsSettings(modelParams) {
417
- return embeddingModelParamsSchema.parse(modelParams);
418
- }
419
- function validateModelParamsSettings(modelParams) {
420
- return modelParamsSchema.parse(modelParams);
421
- }
422
- function validateModelParamsWithWarnings(params, warnings) {
423
- const result = modelParamsSchema.safeParse(params);
424
- if (!result.success) {
425
- for (const issue of result.error.issues) {
426
- const path = issue.path.join(".");
427
- const value = path ? params[path] : void 0;
428
- warnings.push({
429
- message: `${path}=${String(value)} is invalid: ${issue.message}. The API may reject this value.`,
430
- type: "other"
431
- });
609
+ // src/sap-ai-error.ts
610
+ var sap_ai_error_exports = {};
611
+ __export(sap_ai_error_exports, {
612
+ ApiSwitchError: () => ApiSwitchError,
613
+ UnsupportedFeatureError: () => UnsupportedFeatureError,
614
+ convertSAPErrorToAPICallError: () => convertSAPErrorToAPICallError,
615
+ convertToAISDKError: () => convertToAISDKError,
616
+ normalizeHeaders: () => normalizeHeaders
617
+ });
618
+ function convertSAPErrorToAPICallError(errorResponse, context) {
619
+ const { code, location, message, requestId } = extractErrorFields(errorResponse);
620
+ const statusCode = getStatusCodeFromSAPError(code, context?.httpStatusCode);
621
+ const responseBody = JSON.stringify({
622
+ error: {
623
+ code,
624
+ location,
625
+ message,
626
+ request_id: requestId
432
627
  }
628
+ });
629
+ let enhancedMessage = message;
630
+ if (statusCode === HTTP_STATUS.UNAUTHORIZED || statusCode === HTTP_STATUS.FORBIDDEN) {
631
+ 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";
632
+ if (requestId) {
633
+ enhancedMessage += `
634
+ Request ID: ${requestId}`;
635
+ }
636
+ return new import_provider3.LoadAPIKeyError({
637
+ message: enhancedMessage
638
+ });
433
639
  }
434
- }
435
- function parseSAPPartProviderOptions(providerOptions, warnings) {
436
- if (!providerOptions || typeof providerOptions !== "object") {
437
- return void 0;
438
- }
439
- const block = providerOptions[SAP_AI_PROVIDER_NAME];
440
- if (block === void 0) {
441
- return void 0;
640
+ if (statusCode === HTTP_STATUS.NOT_FOUND) {
641
+ 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";
642
+ if (requestId) {
643
+ enhancedMessage += `
644
+ Request ID: ${requestId}`;
645
+ }
646
+ const modelId = context?.modelId ?? extractModelIdentifier(message, location);
647
+ return new import_provider3.NoSuchModelError({
648
+ message: enhancedMessage,
649
+ modelId: modelId ?? "unknown",
650
+ modelType: context?.modelType ?? "languageModel"
651
+ });
442
652
  }
443
- const parsed = sapAIPartProviderOptionsSchema.safeParse(block);
444
- if (parsed.success) {
445
- return parsed.data;
653
+ if (statusCode === HTTP_STATUS.RATE_LIMIT) {
654
+ 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";
655
+ } else if (statusCode >= HTTP_STATUS.INTERNAL_ERROR) {
656
+ 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";
657
+ } else if (location) {
658
+ enhancedMessage += `
659
+
660
+ Error location: ${location}`;
446
661
  }
447
- if (warnings) {
448
- for (const issue of parsed.error.issues) {
449
- const path = issue.path.join(".");
450
- const message = `providerOptions['sap-ai']${path ? `.${path}` : ""} is invalid: ${issue.message}. The directive was dropped.`;
451
- if (!warnings.some((w) => w.message === message)) {
452
- warnings.push({ message, type: "other" });
453
- }
454
- }
662
+ if (requestId) {
663
+ enhancedMessage += `
664
+ Request ID: ${requestId}`;
455
665
  }
456
- return void 0;
457
- }
458
- var import_provider_utils, import_zod, SAP_AI_PROVIDER_NAME, modelParamsSchema, embeddingModelParamsSchema, sapAIApiTypeSchema, cacheControlSchema, sapAIPartProviderOptionsSchema, promptTemplateScopeSchema, promptTemplateRefByIdSchema, promptTemplateRefByScenarioNameVersionSchema, promptTemplateRefSchema, orchestrationConfigRefOverrideSchema, orchestrationConfigRefByIdSchema, orchestrationConfigRefByScenarioNameVersionSchema, orchestrationConfigRefSchema, sapAILanguageModelProviderOptions, sapAIEmbeddingProviderOptions;
459
- var init_sap_ai_provider_options = __esm({
460
- "src/sap-ai-provider-options.ts"() {
461
- "use strict";
462
- import_provider_utils = require("@ai-sdk/provider-utils");
463
- import_zod = require("zod");
464
- SAP_AI_PROVIDER_NAME = "sap-ai";
465
- modelParamsSchema = import_zod.z.object({
466
- frequencyPenalty: import_zod.z.number().min(-2).max(2).optional(),
467
- maxTokens: import_zod.z.number().int().positive().optional(),
468
- n: import_zod.z.number().int().positive().optional(),
469
- parallel_tool_calls: import_zod.z.boolean().optional(),
470
- presencePenalty: import_zod.z.number().min(-2).max(2).optional(),
471
- temperature: import_zod.z.number().min(0).max(2).optional(),
472
- topP: import_zod.z.number().min(0).max(1).optional()
473
- }).catchall(import_zod.z.unknown());
474
- embeddingModelParamsSchema = import_zod.z.object({
475
- dimensions: import_zod.z.number().int().positive().optional(),
476
- encoding_format: import_zod.z.enum(["base64", "binary", "float"]).optional(),
477
- normalize: import_zod.z.boolean().optional()
478
- }).catchall(import_zod.z.unknown());
479
- sapAIApiTypeSchema = import_zod.z.enum(["orchestration", "foundation-models"]);
480
- cacheControlSchema = import_zod.z.object({
481
- ttl: import_zod.z.enum(["5m", "1h"]).optional(),
482
- type: import_zod.z.literal("ephemeral")
483
- });
484
- sapAIPartProviderOptionsSchema = import_zod.z.object({
485
- cacheControl: cacheControlSchema.optional()
486
- });
487
- promptTemplateScopeSchema = import_zod.z.enum(["tenant", "resource_group"]);
488
- promptTemplateRefByIdSchema = import_zod.z.object({
489
- id: import_zod.z.string().min(1, "Template ID cannot be empty"),
490
- scope: promptTemplateScopeSchema.optional()
491
- });
492
- promptTemplateRefByScenarioNameVersionSchema = import_zod.z.object({
493
- name: import_zod.z.string().min(1, "Template name cannot be empty"),
494
- scenario: import_zod.z.string().min(1, "Scenario cannot be empty"),
495
- scope: promptTemplateScopeSchema.optional(),
496
- version: import_zod.z.string().min(1, "Version cannot be empty")
497
- });
498
- promptTemplateRefSchema = import_zod.z.union([
499
- promptTemplateRefByIdSchema,
500
- promptTemplateRefByScenarioNameVersionSchema
501
- ]);
502
- orchestrationConfigRefOverrideSchema = import_zod.z.custom(
503
- (value) => typeof value === "object" && value !== null && !Array.isArray(value),
504
- { message: "overrideConfig must be an object" }
505
- ).refine(
506
- (value) => {
507
- let stream;
508
- try {
509
- stream = value.stream;
510
- } catch {
511
- return false;
512
- }
513
- return stream === void 0 || Boolean(stream) && typeof stream === "object" && !Array.isArray(stream);
514
- },
515
- { message: "overrideConfig.stream must be an object" }
516
- ).refine(
517
- (value) => {
518
- let stream;
519
- try {
520
- stream = value.stream;
521
- } catch {
522
- return true;
523
- }
524
- if (stream === void 0 || stream === null || typeof stream !== "object") {
525
- return true;
526
- }
527
- try {
528
- return !("enabled" in stream);
529
- } catch {
530
- return false;
531
- }
532
- },
533
- {
534
- message: "stream.enabled is not allowed in overrideConfig: it is controlled by the call site (stream() or chatCompletion())"
535
- }
536
- );
537
- orchestrationConfigRefByIdSchema = import_zod.z.object({
538
- id: import_zod.z.string().min(1, "Config ID cannot be empty"),
539
- overrideConfig: orchestrationConfigRefOverrideSchema.optional()
540
- });
541
- orchestrationConfigRefByScenarioNameVersionSchema = import_zod.z.object({
542
- name: import_zod.z.string().min(1, "Config name cannot be empty"),
543
- overrideConfig: orchestrationConfigRefOverrideSchema.optional(),
544
- scenario: import_zod.z.string().min(1, "Scenario cannot be empty"),
545
- version: import_zod.z.string().min(1, "Version cannot be empty")
546
- });
547
- orchestrationConfigRefSchema = import_zod.z.union([
548
- orchestrationConfigRefByIdSchema,
549
- orchestrationConfigRefByScenarioNameVersionSchema
550
- ]);
551
- sapAILanguageModelProviderOptions = (0, import_provider_utils.lazySchema)(
552
- () => (0, import_provider_utils.zodSchema)(
553
- import_zod.z.object({
554
- api: sapAIApiTypeSchema.optional(),
555
- escapeTemplatePlaceholders: import_zod.z.boolean().optional(),
556
- includeReasoning: import_zod.z.boolean().optional(),
557
- modelParams: modelParamsSchema.optional(),
558
- orchestrationConfigRef: orchestrationConfigRefSchema.optional(),
559
- placeholderValues: import_zod.z.record(import_zod.z.string(), import_zod.z.string()).optional(),
560
- promptTemplateRef: promptTemplateRefSchema.optional()
561
- })
562
- )
563
- );
564
- sapAIEmbeddingProviderOptions = (0, import_provider_utils.lazySchema)(
565
- () => (0, import_provider_utils.zodSchema)(
566
- import_zod.z.object({
567
- api: sapAIApiTypeSchema.optional(),
568
- modelParams: embeddingModelParamsSchema.optional(),
569
- type: import_zod.z.enum(["document", "query", "text"]).optional()
570
- })
571
- )
572
- );
573
- }
574
- });
575
-
576
- // src/deep-merge.ts
577
- function deepMerge(...sources) {
578
- const result = {};
579
- for (const source of sources) {
580
- if (source != null) mergeInto(result, source, /* @__PURE__ */ new Set(), 0);
581
- }
582
- return result;
583
- }
584
- function isPlainObject(value) {
585
- if (value === null || typeof value !== "object") return false;
586
- const proto = Object.getPrototypeOf(value);
587
- return proto === Object.prototype || proto === null;
588
- }
589
- function mergeInto(target, source, ancestors, depth) {
590
- if (depth > MAX_DEPTH) throw new Error("Maximum merge depth exceeded");
591
- if (ancestors.has(source)) throw new Error("Circular reference detected during deep merge");
592
- ancestors.add(source);
593
- for (const key of Object.keys(source)) {
594
- const sourceValue = source[key];
595
- const targetValue = Object.hasOwn(target, key) ? target[key] : void 0;
596
- const value = isPlainObject(sourceValue) ? mergeInto(isPlainObject(targetValue) ? targetValue : {}, sourceValue, ancestors, depth + 1) : sourceValue;
597
- Object.defineProperty(target, key, {
598
- configurable: true,
599
- enumerable: true,
600
- value,
601
- writable: true
602
- });
603
- }
604
- ancestors.delete(source);
605
- return target;
606
- }
607
- var MAX_DEPTH;
608
- var init_deep_merge = __esm({
609
- "src/deep-merge.ts"() {
610
- "use strict";
611
- MAX_DEPTH = 100;
612
- }
613
- });
614
-
615
- // src/sap-ai-error.ts
616
- function convertSAPErrorToAPICallError(errorResponse, context) {
617
- const { code, location, message, requestId } = extractErrorFields(errorResponse);
618
- const statusCode = getStatusCodeFromSAPError(code, context?.httpStatusCode);
619
- const responseBody = JSON.stringify({
620
- error: {
621
- code,
622
- location,
623
- message,
624
- request_id: requestId
625
- }
626
- });
627
- let enhancedMessage = message;
628
- if (statusCode === HTTP_STATUS.UNAUTHORIZED || statusCode === HTTP_STATUS.FORBIDDEN) {
629
- 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";
630
- if (requestId) {
631
- enhancedMessage += `
632
- Request ID: ${requestId}`;
633
- }
634
- return new import_provider2.LoadAPIKeyError({
635
- message: enhancedMessage
636
- });
637
- }
638
- if (statusCode === HTTP_STATUS.NOT_FOUND) {
639
- 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";
640
- if (requestId) {
641
- enhancedMessage += `
642
- Request ID: ${requestId}`;
643
- }
644
- const modelId = context?.modelId ?? extractModelIdentifier(message, location);
645
- return new import_provider2.NoSuchModelError({
646
- message: enhancedMessage,
647
- modelId: modelId ?? "unknown",
648
- modelType: context?.modelType ?? "languageModel"
649
- });
650
- }
651
- if (statusCode === HTTP_STATUS.RATE_LIMIT) {
652
- 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";
653
- } else if (statusCode >= HTTP_STATUS.INTERNAL_ERROR) {
654
- 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";
655
- } else if (location) {
656
- enhancedMessage += `
657
-
658
- Error location: ${location}`;
659
- }
660
- if (requestId) {
661
- enhancedMessage += `
662
- Request ID: ${requestId}`;
663
- }
664
- return new import_provider2.APICallError({
666
+ return new import_provider3.APICallError({
665
667
  isRetryable: isRetryable(statusCode),
666
668
  message: enhancedMessage,
667
669
  requestBodyValues: context?.requestBody,
@@ -672,14 +674,21 @@ Request ID: ${requestId}`;
672
674
  });
673
675
  }
674
676
  function convertToAISDKError(error, context) {
675
- if (import_provider2.APICallError.isInstance(error) || import_provider2.LoadAPIKeyError.isInstance(error) || import_provider2.NoSuchModelError.isInstance(error) || import_provider2.InvalidPromptError.isInstance(error) || import_provider2.UnsupportedFunctionalityError.isInstance(error)) {
677
+ if (import_provider3.APICallError.isInstance(error) || import_provider3.LoadAPIKeyError.isInstance(error) || import_provider3.NoSuchModelError.isInstance(error) || import_provider3.InvalidPromptError.isInstance(error) || import_provider3.UnsupportedFunctionalityError.isInstance(error)) {
676
678
  return error;
677
679
  }
678
- const { aborted, response, rootError } = inspectError(error);
680
+ const { aborted, networkCode, noMatchingDeployment, response, rootError, syntaxError } = inspectError(error);
681
+ if (noMatchingDeployment && !aborted) {
682
+ return new import_provider3.NoSuchModelError({
683
+ 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.",
684
+ modelId: context?.modelId ?? "unknown",
685
+ modelType: context?.modelType ?? "languageModel"
686
+ });
687
+ }
679
688
  const responseHeaders = context?.responseHeaders ?? normalizeHeaders(response?.headers);
680
689
  if (!aborted) {
681
690
  const errorResponse = findStructuredErrorResponse(
682
- rootError instanceof SyntaxError ? void 0 : rootError,
691
+ syntaxError ? void 0 : rootError,
683
692
  response?.data
684
693
  );
685
694
  if (errorResponse) {
@@ -697,7 +706,8 @@ function convertToAISDKError(error, context) {
697
706
  };
698
707
  if (aborted) {
699
708
  return createAPICallError(
700
- error,
709
+ // Preserve cancellation priority without retaining credential-bearing criteria.
710
+ noMatchingDeployment ? void 0 : error,
701
711
  {
702
712
  isRetryable: false,
703
713
  message: "Request was aborted by the client",
@@ -706,33 +716,44 @@ function convertToAISDKError(error, context) {
706
716
  resolvedContext
707
717
  );
708
718
  }
709
- if (isHttpStatus(response?.status)) {
719
+ if (isHttpStatus(response?.status) && (networkCode === void 0 || syntaxError !== void 0 || response.status < 200 || response.status >= 300)) {
710
720
  return createAPICallError(
711
721
  error,
712
722
  {
713
723
  isRetryable: isRetryable(response.status),
714
- message: rootError instanceof SyntaxError && error instanceof Error ? error.message : rootError instanceof Error ? rootError.message : "SAP AI Core request failed",
724
+ message: syntaxError && error instanceof Error ? error.message : rootError instanceof Error ? rootError.message : "SAP AI Core request failed",
715
725
  statusCode: response.status
716
726
  },
717
727
  resolvedContext
718
728
  );
719
729
  }
720
- if (rootError instanceof SyntaxError) {
730
+ if (syntaxError) {
721
731
  return createAPICallError(
722
732
  error,
723
733
  {
724
734
  isRetryable: false,
725
- message: error instanceof Error && error !== rootError ? error.message : "Failed to parse SAP AI Core data.",
735
+ message: error instanceof Error && error !== syntaxError ? error.message : "Failed to parse SAP AI Core data.",
726
736
  statusCode: HTTP_STATUS.INTERNAL_ERROR
727
737
  },
728
738
  resolvedContext
729
739
  );
730
740
  }
741
+ if (networkCode) {
742
+ return createAPICallError(
743
+ error,
744
+ {
745
+ isRetryable: true,
746
+ message: `SAP AI Core network error (${networkCode})`,
747
+ statusCode: HTTP_STATUS.SERVICE_UNAVAILABLE
748
+ },
749
+ resolvedContext
750
+ );
751
+ }
731
752
  if (rootError instanceof Error) {
732
753
  const errorMsg = rootError.message.toLowerCase();
733
754
  const originalErrorMsg = rootError.message;
734
755
  if (AUTHENTICATION_ERROR_KEYWORDS.some((keyword) => errorMsg.includes(keyword))) {
735
- return new import_provider2.LoadAPIKeyError({
756
+ return new import_provider3.LoadAPIKeyError({
736
757
  message: `SAP AI Core authentication failed: ${originalErrorMsg}
737
758
 
738
759
  Make sure your AICORE_SERVICE_KEY environment variable is set correctly.
@@ -741,7 +762,7 @@ See: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-serv
741
762
  }
742
763
  if (DEPLOYMENT_ERROR_KEYWORDS.some((keyword) => errorMsg.includes(keyword))) {
743
764
  const modelId = context?.modelId ?? extractModelIdentifier(originalErrorMsg);
744
- return new import_provider2.NoSuchModelError({
765
+ return new import_provider3.NoSuchModelError({
745
766
  message: `SAP AI Core deployment error: ${originalErrorMsg}
746
767
 
747
768
  Make sure you have a running orchestration deployment in your SAP AI Core instance.
@@ -813,7 +834,7 @@ function normalizeHeaders(headers) {
813
834
  return Object.fromEntries(entries);
814
835
  }
815
836
  function createAPICallError(error, options, context) {
816
- return new import_provider2.APICallError({
837
+ return new import_provider3.APICallError({
817
838
  cause: error,
818
839
  isRetryable: options.isRetryable,
819
840
  message: options.message,
@@ -887,10 +908,18 @@ function inspectError(error) {
887
908
  let current = error;
888
909
  let response;
889
910
  let aborted = false;
911
+ let networkCode;
912
+ let noMatchingDeployment = false;
913
+ let syntaxError;
890
914
  while (typeof current === "object" && current !== null && !seen.has(current)) {
891
915
  seen.add(current);
892
916
  rootError = current;
917
+ noMatchingDeployment ||= current instanceof Error && current.message.startsWith("No deployment matched the given criteria:");
893
918
  aborted ||= isAbortError(current);
919
+ if (current instanceof SyntaxError) syntaxError ??= current;
920
+ if (current instanceof Error && "code" in current && typeof current.code === "string") {
921
+ if (RETRYABLE_NETWORK_CODES.has(current.code)) networkCode ??= current.code;
922
+ }
894
923
  const entry = current;
895
924
  if (response === void 0 && entry.isAxiosError === true) response = entry.response;
896
925
  const cause = "cause" in entry ? entry.cause : current instanceof Error && (0, import_util.isErrorWithCause)(current) ? current.rootCause : void 0;
@@ -900,7 +929,7 @@ function inspectError(error) {
900
929
  rootError = cause;
901
930
  current = cause;
902
931
  }
903
- return { aborted, response, rootError };
932
+ return { aborted, networkCode, noMatchingDeployment, response, rootError, syntaxError };
904
933
  }
905
934
  function isAbortError(error) {
906
935
  if (error instanceof DOMException && error.name === "AbortError") {
@@ -1009,11 +1038,11 @@ function tryExtractSAPErrorFromMessage(message) {
1009
1038
  return null;
1010
1039
  }
1011
1040
  }
1012
- var import_provider2, import_util, HTTP_STATUS, ERROR_MATCHERS, AUTHENTICATION_ERROR_KEYWORDS, DEPLOYMENT_ERROR_KEYWORDS, ApiSwitchError, UnsupportedFeatureError;
1041
+ var import_provider3, import_util, HTTP_STATUS, RETRYABLE_NETWORK_CODES, ERROR_MATCHERS, AUTHENTICATION_ERROR_KEYWORDS, DEPLOYMENT_ERROR_KEYWORDS, ApiSwitchError, UnsupportedFeatureError;
1013
1042
  var init_sap_ai_error = __esm({
1014
1043
  "src/sap-ai-error.ts"() {
1015
1044
  "use strict";
1016
- import_provider2 = require("@ai-sdk/provider");
1045
+ import_provider3 = require("@ai-sdk/provider");
1017
1046
  import_util = require("@sap-cloud-sdk/util");
1018
1047
  HTTP_STATUS = {
1019
1048
  BAD_REQUEST: 400,
@@ -1027,6 +1056,17 @@ var init_sap_ai_error = __esm({
1027
1056
  SERVICE_UNAVAILABLE: 503,
1028
1057
  UNAUTHORIZED: 401
1029
1058
  };
1059
+ RETRYABLE_NETWORK_CODES = /* @__PURE__ */ new Set([
1060
+ "EAI_AGAIN",
1061
+ "ECONNABORTED",
1062
+ "ECONNREFUSED",
1063
+ "ECONNRESET",
1064
+ "EHOSTUNREACH",
1065
+ "ENETUNREACH",
1066
+ "ENOTFOUND",
1067
+ "EPIPE",
1068
+ "ETIMEDOUT"
1069
+ ]);
1030
1070
  ERROR_MATCHERS = [
1031
1071
  {
1032
1072
  category: "network",
@@ -1160,8 +1200,13 @@ The model's response was blocked by content safety filters. Try a different prom
1160
1200
  * @param suggestedApi - The API that supports this feature.
1161
1201
  */
1162
1202
  constructor(feature, api, suggestedApi) {
1163
- const apiName = api === "foundation-models" ? "Foundation Models" : "Orchestration";
1164
- const suggestedApiName = suggestedApi === "foundation-models" ? "Foundation Models" : "Orchestration";
1203
+ const names = {
1204
+ "foundation-models": "Foundation Models",
1205
+ orchestration: "Orchestration",
1206
+ responses: "Responses"
1207
+ };
1208
+ const apiName = names[api];
1209
+ const suggestedApiName = names[suggestedApi];
1165
1210
  super(`${feature} is not supported by ${apiName} API. Use ${suggestedApiName} API instead.`);
1166
1211
  this.feature = feature;
1167
1212
  this.api = api;
@@ -1175,43 +1220,135 @@ The model's response was blocked by content safety filters. Try a different prom
1175
1220
  }
1176
1221
  });
1177
1222
 
1178
- // src/strategy-utils.ts
1179
- function applyParameterOverrides(modelParams, options, sapModelParams, settingsModelParams, mappings) {
1180
- for (const mapping of mappings) {
1181
- const value = (mapping.optionKey ? options[mapping.optionKey] : void 0) ?? (mapping.camelCaseKey ? sapModelParams?.[mapping.camelCaseKey] : void 0) ?? (mapping.camelCaseKey ? settingsModelParams?.[mapping.camelCaseKey] : void 0);
1182
- if (value !== void 0) {
1183
- modelParams[mapping.outputKey] = value;
1184
- }
1185
- if (mapping.camelCaseKey && mapping.camelCaseKey !== mapping.outputKey) {
1186
- delete modelParams[mapping.camelCaseKey];
1187
- }
1188
- }
1223
+ // src/abort-utils.ts
1224
+ function createAbortError(reason) {
1225
+ const error = new Error("The operation was aborted.", { cause: reason });
1226
+ error.name = "AbortError";
1227
+ return error;
1189
1228
  }
1190
- function buildAnthropicCacheMetadata(tokenUsage) {
1191
- const details = tokenUsage?.prompt_tokens_details?.cache_creation_token_details;
1192
- if (!details || (details.ephemeral_5m_input_tokens ?? 0) === 0 && (details.ephemeral_1h_input_tokens ?? 0) === 0) {
1193
- return {};
1194
- }
1195
- return { cacheUsage: details };
1229
+ function throwIfAborted(signal) {
1230
+ if (signal?.aborted) throw createAbortError(signal.reason);
1196
1231
  }
1197
- function buildEmbeddingResult(config) {
1198
- const {
1199
- embeddings,
1200
- modelId,
1201
- providerName,
1202
- requestId,
1203
- responseHeaders,
1204
- totalTokens,
1205
- version,
1206
- warnings
1207
- } = config;
1208
- const providerMetadata = {
1209
- [providerName]: {
1210
- model: modelId,
1211
- ...requestId ? { requestId } : {},
1212
- version
1213
- }
1214
- };
1232
+ function waitWithAbort(pending, signal, onAbortedValue) {
1233
+ if (!signal) return pending;
1234
+ return new Promise((resolve, reject) => {
1235
+ let listening = true;
1236
+ const cleanup = () => {
1237
+ if (!listening) return;
1238
+ listening = false;
1239
+ signal.removeEventListener("abort", onAbort);
1240
+ };
1241
+ const onAbort = () => {
1242
+ cleanup();
1243
+ reject(createAbortError(signal.reason));
1244
+ };
1245
+ signal.addEventListener("abort", onAbort, { once: true });
1246
+ void pending.then(
1247
+ (value) => {
1248
+ cleanup();
1249
+ if (signal.aborted) {
1250
+ try {
1251
+ onAbortedValue?.(value);
1252
+ } finally {
1253
+ reject(createAbortError(signal.reason));
1254
+ }
1255
+ } else {
1256
+ resolve(value);
1257
+ }
1258
+ },
1259
+ (error) => {
1260
+ cleanup();
1261
+ reject(error);
1262
+ }
1263
+ ).catch((error) => {
1264
+ cleanup();
1265
+ reject(error);
1266
+ });
1267
+ if (signal.aborted) onAbort();
1268
+ });
1269
+ }
1270
+ var init_abort_utils = __esm({
1271
+ "src/abort-utils.ts"() {
1272
+ "use strict";
1273
+ }
1274
+ });
1275
+
1276
+ // src/deep-merge.ts
1277
+ function deepMerge(...sources) {
1278
+ const result = {};
1279
+ for (const source of sources) {
1280
+ if (source != null) mergeInto(result, source, /* @__PURE__ */ new Set(), 0);
1281
+ }
1282
+ return result;
1283
+ }
1284
+ function isPlainObject(value) {
1285
+ if (value === null || typeof value !== "object") return false;
1286
+ const proto = Object.getPrototypeOf(value);
1287
+ return proto === Object.prototype || proto === null;
1288
+ }
1289
+ function mergeInto(target, source, ancestors, depth) {
1290
+ if (depth > MAX_DEPTH) throw new Error("Maximum merge depth exceeded");
1291
+ if (ancestors.has(source)) throw new Error("Circular reference detected during deep merge");
1292
+ ancestors.add(source);
1293
+ for (const key of Object.keys(source)) {
1294
+ const sourceValue = source[key];
1295
+ const targetValue = Object.hasOwn(target, key) ? target[key] : void 0;
1296
+ const value = isPlainObject(sourceValue) ? mergeInto(isPlainObject(targetValue) ? targetValue : {}, sourceValue, ancestors, depth + 1) : sourceValue;
1297
+ Object.defineProperty(target, key, {
1298
+ configurable: true,
1299
+ enumerable: true,
1300
+ value,
1301
+ writable: true
1302
+ });
1303
+ }
1304
+ ancestors.delete(source);
1305
+ return target;
1306
+ }
1307
+ var MAX_DEPTH;
1308
+ var init_deep_merge = __esm({
1309
+ "src/deep-merge.ts"() {
1310
+ "use strict";
1311
+ MAX_DEPTH = 100;
1312
+ }
1313
+ });
1314
+
1315
+ // src/strategy-utils.ts
1316
+ function applyParameterOverrides(modelParams, options, sapModelParams, settingsModelParams, mappings) {
1317
+ for (const mapping of mappings) {
1318
+ const value = (mapping.optionKey ? options[mapping.optionKey] : void 0) ?? (mapping.camelCaseKey ? sapModelParams?.[mapping.camelCaseKey] : void 0) ?? (mapping.camelCaseKey ? settingsModelParams?.[mapping.camelCaseKey] : void 0);
1319
+ if (value !== void 0) {
1320
+ modelParams[mapping.outputKey] = value;
1321
+ }
1322
+ if (mapping.camelCaseKey && mapping.camelCaseKey !== mapping.outputKey) {
1323
+ delete modelParams[mapping.camelCaseKey];
1324
+ }
1325
+ }
1326
+ }
1327
+ function buildAnthropicCacheMetadata(tokenUsage) {
1328
+ const details = tokenUsage?.prompt_tokens_details?.cache_creation_token_details;
1329
+ if (!details || (details.ephemeral_5m_input_tokens ?? 0) === 0 && (details.ephemeral_1h_input_tokens ?? 0) === 0) {
1330
+ return {};
1331
+ }
1332
+ return { cacheUsage: details };
1333
+ }
1334
+ function buildEmbeddingResult(config) {
1335
+ const {
1336
+ embeddings,
1337
+ modelId,
1338
+ providerName,
1339
+ requestId,
1340
+ responseHeaders,
1341
+ totalTokens,
1342
+ version,
1343
+ warnings
1344
+ } = config;
1345
+ const providerMetadata = {
1346
+ [providerName]: {
1347
+ model: modelId,
1348
+ ...requestId ? { requestId } : {},
1349
+ version
1350
+ }
1351
+ };
1215
1352
  return {
1216
1353
  embeddings,
1217
1354
  providerMetadata,
@@ -1225,9 +1362,23 @@ function buildGenerateResult(config) {
1225
1362
  const content = [];
1226
1363
  const tokenUsage = response.getTokenUsage();
1227
1364
  const finishReasonRaw = response.getFinishReason();
1228
- const finishReason = mapFinishReason(finishReasonRaw);
1365
+ const providerSpecificFields = parseProviderSpecificFields(
1366
+ response.getProviderSpecificFields?.()
1367
+ );
1368
+ const finishReason = mapFinishReason(
1369
+ finishReasonRaw,
1370
+ getProviderFinishReason(providerSpecificFields)
1371
+ );
1229
1372
  const textContent = response.getContent();
1230
1373
  const toolCalls = response.getToolCalls();
1374
+ for (const block of response.getReasoningBlocks?.() ?? []) {
1375
+ const validatedBlock = orchestrationReasoningBlockSchema.parse(block);
1376
+ content.push({
1377
+ providerMetadata: buildOrchestrationReasoningMetadata(validatedBlock, providerName),
1378
+ text: validatedBlock.content ?? "",
1379
+ type: "reasoning"
1380
+ });
1381
+ }
1231
1382
  if (textContent) content.push({ text: textContent, type: "text" });
1232
1383
  for (const toolCall of toolCalls ?? []) {
1233
1384
  content.push({
@@ -1262,9 +1413,10 @@ function buildGenerateResult(config) {
1262
1413
  providerMetadata: {
1263
1414
  [providerName]: {
1264
1415
  ...buildAnthropicCacheMetadata(tokenUsage),
1265
- finishReason: finishReasonRaw ?? "unknown",
1416
+ finishReason: finishReason.raw ?? "unknown",
1266
1417
  finishReasonMapped: finishReason,
1267
1418
  ...intermediateFailures?.length ? { intermediateFailures: sanitizeAsJSONArray(intermediateFailures) } : {},
1419
+ ...providerSpecificFields && { providerSpecificFields },
1268
1420
  ...requestId ? { requestId } : {},
1269
1421
  version
1270
1422
  }
@@ -1535,8 +1687,8 @@ function isZodSchema(obj) {
1535
1687
  const record = obj;
1536
1688
  return "_def" in record && "parse" in record && hasCallableParse(record);
1537
1689
  }
1538
- function mapFinishReason(reason) {
1539
- const raw = reason ?? void 0;
1690
+ function mapFinishReason(reason, originalReason) {
1691
+ const raw = originalReason ?? reason ?? void 0;
1540
1692
  if (!reason) {
1541
1693
  return { raw, unified: "other" };
1542
1694
  }
@@ -1631,6 +1783,18 @@ function normalizeEmbedding(embedding) {
1631
1783
  );
1632
1784
  return Array.from(float32Array);
1633
1785
  }
1786
+ function buildOrchestrationReasoningMetadata(block, providerName) {
1787
+ return { [providerName]: { reasoningContent: block } };
1788
+ }
1789
+ function getProviderFinishReason(fields) {
1790
+ const reason = fields?.finish_reason;
1791
+ return typeof reason === "string" && reason.length > 0 ? reason : void 0;
1792
+ }
1793
+ function parseProviderSpecificFields(value) {
1794
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return void 0;
1795
+ const fields = sanitizeAsJSONObject(value);
1796
+ return fields !== null && typeof fields === "object" && !Array.isArray(fields) ? fields : void 0;
1797
+ }
1634
1798
  function sanitizeAsJSONArray(value) {
1635
1799
  try {
1636
1800
  return JSON.parse(JSON.stringify(value, jsonReplacer));
@@ -1662,16 +1826,17 @@ var VERSION;
1662
1826
  var init_version = __esm({
1663
1827
  "src/version.ts"() {
1664
1828
  "use strict";
1665
- VERSION = true ? "5.0.3" : "0.0.0-test";
1829
+ VERSION = true ? "5.1.0" : "0.0.0-test";
1666
1830
  }
1667
1831
  });
1668
1832
 
1669
1833
  // src/base-embedding-model-strategy.ts
1670
- var import_provider3, BaseEmbeddingModelStrategy;
1834
+ var import_provider4, BaseEmbeddingModelStrategy;
1671
1835
  var init_base_embedding_model_strategy = __esm({
1672
1836
  "src/base-embedding-model-strategy.ts"() {
1673
1837
  "use strict";
1674
- import_provider3 = require("@ai-sdk/provider");
1838
+ import_provider4 = require("@ai-sdk/provider");
1839
+ init_abort_utils();
1675
1840
  init_deep_merge();
1676
1841
  init_sap_ai_error();
1677
1842
  init_sap_ai_provider_options();
@@ -1691,25 +1856,30 @@ var init_base_embedding_model_strategy = __esm({
1691
1856
  const { abortSignal, values } = options;
1692
1857
  try {
1693
1858
  if (values.length > maxEmbeddingsPerCall) {
1694
- throw new import_provider3.TooManyEmbeddingValuesForCallError({
1859
+ throw new import_provider4.TooManyEmbeddingValuesForCallError({
1695
1860
  maxEmbeddingsPerCall,
1696
1861
  modelId: config.modelId,
1697
1862
  provider: config.provider,
1698
1863
  values
1699
1864
  });
1700
1865
  }
1866
+ throwIfAborted(abortSignal);
1701
1867
  const embeddingOptions = config.parsedProviderOptions;
1702
1868
  const providerName = getProviderName(config.provider);
1703
1869
  const embeddingType = embeddingOptions?.type ?? settings.type ?? "text";
1704
1870
  const warnings = [];
1705
1871
  this.resolveWarnings(settings, warnings);
1706
1872
  const client = this.createClient(config, settings, embeddingOptions);
1707
- const response = await this.executeCall(
1708
- client,
1709
- values,
1710
- embeddingType,
1711
- mergeRequestConfig(config.requestConfig, abortSignal, options.headers)
1873
+ const response = await waitWithAbort(
1874
+ this.executeCall(
1875
+ client,
1876
+ values,
1877
+ embeddingType,
1878
+ mergeRequestConfig(config.requestConfig, abortSignal, options.headers)
1879
+ ),
1880
+ abortSignal
1712
1881
  );
1882
+ throwIfAborted(abortSignal);
1713
1883
  const embeddings = this.extractEmbeddings(response);
1714
1884
  const totalTokens = this.extractTokenCount(response);
1715
1885
  const { headers: responseHeaders, requestId } = this.extractResponseMetadata(response);
@@ -1724,7 +1894,7 @@ var init_base_embedding_model_strategy = __esm({
1724
1894
  warnings
1725
1895
  });
1726
1896
  } catch (error) {
1727
- if (error instanceof import_provider3.TooManyEmbeddingValuesForCallError) {
1897
+ if (error instanceof import_provider4.TooManyEmbeddingValuesForCallError) {
1728
1898
  throw error;
1729
1899
  }
1730
1900
  throw convertToAISDKError(error, {
@@ -1825,22 +1995,22 @@ var init_foundation_models_embedding_model_strategy = __esm({
1825
1995
 
1826
1996
  // src/sap-ai-validation.ts
1827
1997
  function validateEscapeTemplatePlaceholders(api, escapeTemplatePlaceholders) {
1828
- if (api === "foundation-models" && escapeTemplatePlaceholders === true) {
1998
+ if (api !== "orchestration" && escapeTemplatePlaceholders === true) {
1829
1999
  throw new UnsupportedFeatureError(
1830
2000
  ESCAPE_TEMPLATE_PLACEHOLDERS_DESCRIPTION,
1831
- "foundation-models",
2001
+ api,
1832
2002
  "orchestration"
1833
2003
  );
1834
2004
  }
1835
2005
  }
1836
- function validateFoundationModelsOnlyOptions(settings) {
2006
+ function validateFoundationModelsOnlyOptions(api, settings) {
1837
2007
  if (!settings) return;
1838
2008
  const fmSettings = settings;
1839
2009
  for (const feature of FOUNDATION_MODELS_ONLY_FEATURE_KEYS) {
1840
2010
  if (fmSettings[feature] !== void 0) {
1841
2011
  throw new UnsupportedFeatureError(
1842
2012
  FOUNDATION_MODELS_ONLY_FEATURES[feature],
1843
- "orchestration",
2013
+ api,
1844
2014
  "foundation-models"
1845
2015
  );
1846
2016
  }
@@ -1858,23 +2028,19 @@ function validateOrchestrationOnlyEmbeddingOptions(settings) {
1858
2028
  }
1859
2029
  }
1860
2030
  }
1861
- function validateOrchestrationOnlyOptions(settings) {
2031
+ function validateOrchestrationOnlyOptions(api, settings) {
1862
2032
  if (!settings) return;
1863
2033
  const orchSettings = settings;
1864
2034
  for (const feature of ORCHESTRATION_ONLY_FEATURE_KEYS) {
1865
2035
  if (orchSettings[feature] !== void 0) {
1866
- throw new UnsupportedFeatureError(
1867
- ORCHESTRATION_ONLY_FEATURES[feature],
1868
- "foundation-models",
1869
- "orchestration"
1870
- );
2036
+ throw new UnsupportedFeatureError(ORCHESTRATION_ONLY_FEATURES[feature], api, "orchestration");
1871
2037
  }
1872
2038
  }
1873
2039
  }
1874
2040
  function validateApiSwitch(fromApi, toApi, modelSettings, embeddingSettings) {
1875
2041
  if (fromApi === toApi) return;
1876
2042
  if (!modelSettings && !embeddingSettings) return;
1877
- if (fromApi === "orchestration" && toApi === "foundation-models") {
2043
+ if (toApi !== "orchestration") {
1878
2044
  const orchSettings = modelSettings;
1879
2045
  for (const feature of ORCHESTRATION_ONLY_FEATURE_KEYS) {
1880
2046
  if (orchSettings?.[feature] !== void 0) {
@@ -1887,7 +2053,7 @@ function validateApiSwitch(fromApi, toApi, modelSettings, embeddingSettings) {
1887
2053
  }
1888
2054
  }
1889
2055
  }
1890
- if (fromApi === "foundation-models" && toApi === "orchestration") {
2056
+ if (toApi !== "foundation-models") {
1891
2057
  const fmSettings = modelSettings;
1892
2058
  for (const feature of FOUNDATION_MODELS_ONLY_FEATURE_KEYS) {
1893
2059
  if (fmSettings?.[feature] !== void 0) {
@@ -1895,6 +2061,9 @@ function validateApiSwitch(fromApi, toApi, modelSettings, embeddingSettings) {
1895
2061
  }
1896
2062
  }
1897
2063
  }
2064
+ if (toApi !== "responses" && modelSettings && "responses" in modelSettings && modelSettings.responses !== void 0) {
2065
+ throw new ApiSwitchError(fromApi, toApi, "responses");
2066
+ }
1898
2067
  }
1899
2068
  function mergeSettingsWithApi(defaultSettings, callSettings, fallbackApi) {
1900
2069
  return {
@@ -1945,142 +2114,1234 @@ function validateSettings(options) {
1945
2114
  );
1946
2115
  }
1947
2116
  }
1948
- if (api === "foundation-models") {
1949
- validateOrchestrationOnlyOptions(modelSettings);
1950
- validateOrchestrationOnlyInvocationOptions(invocationSettings);
2117
+ if (api === "responses" && embeddingSettings !== void 0) {
2118
+ throw new UnsupportedFeatureError("Embeddings", "responses", "foundation-models");
2119
+ }
2120
+ if (api !== "orchestration") {
2121
+ validateOrchestrationOnlyOptions(api, modelSettings);
2122
+ validateOrchestrationOnlyInvocationOptions(api, invocationSettings);
1951
2123
  validateOrchestrationOnlyEmbeddingOptions(embeddingSettings);
2124
+ }
2125
+ if (api !== "foundation-models") {
2126
+ validateFoundationModelsOnlyOptions(api, modelSettings);
2127
+ }
2128
+ const modelResponses = modelSettings && "responses" in modelSettings ? modelSettings.responses : void 0;
2129
+ const invocationResponses = invocationSettings?.responses;
2130
+ if (api !== "responses") {
2131
+ if (modelResponses !== void 0 || invocationResponses !== void 0) {
2132
+ throw new UnsupportedFeatureError("Responses options (responses)", api, "responses");
2133
+ }
1952
2134
  } else {
1953
- validateFoundationModelsOnlyOptions(modelSettings);
2135
+ if (modelResponses !== void 0) responsesModelOptionsSchema.parse(modelResponses);
2136
+ if (invocationResponses !== void 0) responsesModelOptionsSchema.parse(invocationResponses);
2137
+ }
2138
+ const modelDropUnsupportedParams = modelSettings?.dropUnsupportedParams;
2139
+ if (modelDropUnsupportedParams !== void 0) {
2140
+ dropUnsupportedParamsSchema.parse(modelDropUnsupportedParams);
2141
+ }
2142
+ if (invocationSettings?.dropUnsupportedParams !== void 0) {
2143
+ dropUnsupportedParamsSchema.parse(invocationSettings.dropUnsupportedParams);
1954
2144
  }
1955
2145
  const modelEscape = modelSettings?.escapeTemplatePlaceholders;
1956
2146
  const invocationEscape = invocationSettings?.escapeTemplatePlaceholders;
1957
2147
  const effectiveEscape = invocationEscape ?? modelEscape;
1958
2148
  validateEscapeTemplatePlaceholders(api, effectiveEscape);
1959
2149
  }
1960
- function validateOrchestrationOnlyInvocationOptions(invocationSettings) {
2150
+ function validateOrchestrationOnlyInvocationOptions(api, invocationSettings) {
1961
2151
  if (!invocationSettings) return;
1962
2152
  for (const feature of ORCHESTRATION_ONLY_INVOCATION_FEATURE_KEYS) {
1963
2153
  if (invocationSettings[feature] !== void 0) {
1964
- throw new UnsupportedFeatureError(
1965
- ORCHESTRATION_ONLY_FEATURES[feature],
1966
- "foundation-models",
1967
- "orchestration"
2154
+ throw new UnsupportedFeatureError(ORCHESTRATION_ONLY_FEATURES[feature], api, "orchestration");
2155
+ }
2156
+ }
2157
+ }
2158
+ var ORCHESTRATION_ONLY_FEATURE_KEYS, ORCHESTRATION_ONLY_FEATURES, FOUNDATION_MODELS_ONLY_FEATURE_KEYS, FOUNDATION_MODELS_ONLY_FEATURES, ORCHESTRATION_ONLY_INVOCATION_FEATURE_KEYS, ORCHESTRATION_ONLY_EMBEDDING_FEATURE_KEYS, ORCHESTRATION_ONLY_EMBEDDING_FEATURES, ESCAPE_TEMPLATE_PLACEHOLDERS_DESCRIPTION, VALID_API_TYPES;
2159
+ var init_sap_ai_validation = __esm({
2160
+ "src/sap-ai-validation.ts"() {
2161
+ "use strict";
2162
+ init_deep_merge();
2163
+ init_sap_ai_error();
2164
+ init_sap_ai_provider_options();
2165
+ ORCHESTRATION_ONLY_FEATURE_KEYS = [
2166
+ "dropUnsupportedParams",
2167
+ "fallbackModuleConfigs",
2168
+ "filtering",
2169
+ "grounding",
2170
+ "masking",
2171
+ "orchestrationConfigRef",
2172
+ "placeholderValues",
2173
+ "promptTemplateRef",
2174
+ "streamOptions",
2175
+ "tools",
2176
+ "translation"
2177
+ ];
2178
+ ORCHESTRATION_ONLY_FEATURES = {
2179
+ dropUnsupportedParams: "Unsupported parameter handling (dropUnsupportedParams)",
2180
+ fallbackModuleConfigs: "Fallback module configurations (fallbackModuleConfigs)",
2181
+ filtering: "Content filtering",
2182
+ grounding: "Document grounding",
2183
+ masking: "Data masking",
2184
+ orchestrationConfigRef: "Orchestration config reference (orchestrationConfigRef)",
2185
+ placeholderValues: "Placeholder values (placeholderValues)",
2186
+ promptTemplateRef: "Prompt template reference (promptTemplateRef)",
2187
+ streamOptions: "Stream options for post-LLM modules",
2188
+ tools: "SAP-format tool definitions (use AI SDK tools instead)",
2189
+ translation: "Translation"
2190
+ };
2191
+ FOUNDATION_MODELS_ONLY_FEATURE_KEYS = ["dataSources"];
2192
+ FOUNDATION_MODELS_ONLY_FEATURES = {
2193
+ dataSources: "Azure On Your Data (dataSources)"
2194
+ };
2195
+ ORCHESTRATION_ONLY_INVOCATION_FEATURE_KEYS = [
2196
+ "dropUnsupportedParams",
2197
+ "orchestrationConfigRef",
2198
+ "placeholderValues",
2199
+ "promptTemplateRef"
2200
+ ];
2201
+ ORCHESTRATION_ONLY_EMBEDDING_FEATURE_KEYS = ["masking"];
2202
+ ORCHESTRATION_ONLY_EMBEDDING_FEATURES = {
2203
+ masking: ORCHESTRATION_ONLY_FEATURES.masking
2204
+ };
2205
+ ESCAPE_TEMPLATE_PLACEHOLDERS_DESCRIPTION = "escapeTemplatePlaceholders (Jinja2 template escaping)";
2206
+ VALID_API_TYPES = [
2207
+ "orchestration",
2208
+ "foundation-models",
2209
+ "responses"
2210
+ ];
2211
+ }
2212
+ });
2213
+
2214
+ // src/orchestration-embedding-model-strategy.ts
2215
+ var orchestration_embedding_model_strategy_exports = {};
2216
+ __export(orchestration_embedding_model_strategy_exports, {
2217
+ OrchestrationEmbeddingModelStrategy: () => OrchestrationEmbeddingModelStrategy
2218
+ });
2219
+ var OrchestrationEmbeddingModelStrategy;
2220
+ var init_orchestration_embedding_model_strategy = __esm({
2221
+ "src/orchestration-embedding-model-strategy.ts"() {
2222
+ "use strict";
2223
+ init_base_embedding_model_strategy();
2224
+ init_sap_ai_validation();
2225
+ init_strategy_utils();
2226
+ OrchestrationEmbeddingModelStrategy = class extends BaseEmbeddingModelStrategy {
2227
+ ClientClass;
2228
+ constructor(ClientClass) {
2229
+ super();
2230
+ this.ClientClass = ClientClass;
2231
+ }
2232
+ createClient(config, settings, embeddingOptions) {
2233
+ const mergedParams = this.mergeModelParams(settings, embeddingOptions);
2234
+ const embeddingConfig = {
2235
+ model: {
2236
+ name: config.modelId,
2237
+ ...hasKeys(mergedParams) ? { params: mergedParams } : {},
2238
+ ...settings.modelVersion ? { version: settings.modelVersion } : {}
2239
+ }
2240
+ };
2241
+ const moduleConfig = {
2242
+ embeddings: embeddingConfig,
2243
+ ...settings.masking && hasKeys(settings.masking) ? { masking: settings.masking } : {}
2244
+ };
2245
+ return new this.ClientClass(moduleConfig, config.deploymentConfig, config.destination);
2246
+ }
2247
+ async executeCall(client, values, embeddingType, requestConfig) {
2248
+ return client.embed({ input: values, type: embeddingType }, requestConfig);
2249
+ }
2250
+ extractEmbeddings(response) {
2251
+ const embeddingData = response.getEmbeddings();
2252
+ const sortedEmbeddings = [...embeddingData].sort((a, b) => a.index - b.index);
2253
+ return sortedEmbeddings.map((data) => normalizeEmbedding(data.embedding));
2254
+ }
2255
+ extractResponseMetadata(response) {
2256
+ return extractResponseMetadata(response, "response");
2257
+ }
2258
+ extractTokenCount(response) {
2259
+ const tokenUsage = response.getTokenUsage();
2260
+ return tokenUsage.total_tokens;
2261
+ }
2262
+ getUrl() {
2263
+ return "sap-ai:orchestration/embeddings";
2264
+ }
2265
+ resolveWarnings(settings, warnings) {
2266
+ validateMaskingProvidersDeprecation(settings, warnings);
2267
+ }
2268
+ };
2269
+ }
2270
+ });
2271
+
2272
+ // src/responses-adapters-v3-to-v4.ts
2273
+ function convertResponsesCallToV4(options) {
2274
+ return {
2275
+ ...options,
2276
+ prompt: options.prompt.map((message) => {
2277
+ switch (message.role) {
2278
+ case "assistant":
2279
+ return { ...message, content: message.content.map(convertPromptPart) };
2280
+ case "system":
2281
+ return message;
2282
+ case "tool":
2283
+ return {
2284
+ ...message,
2285
+ content: message.content.map(
2286
+ (part) => part.type === "tool-result" ? convertToolResult(part) : part
2287
+ )
2288
+ };
2289
+ case "user":
2290
+ return {
2291
+ ...message,
2292
+ content: message.content.map(
2293
+ (part) => part.type === "file" ? convertFile(part) : part
2294
+ )
2295
+ };
2296
+ }
2297
+ })
2298
+ };
2299
+ }
2300
+ function convertFile(part) {
2301
+ const data = part.data;
2302
+ const href = getURLHref(data);
2303
+ if (href !== void 0) {
2304
+ const url = data instanceof URL && data.toString === URL.prototype.toString ? data : new URL(href);
2305
+ return { ...part, data: { type: "url", url } };
2306
+ }
2307
+ return { ...part, data: { data, type: "data" } };
2308
+ }
2309
+ function convertPromptPart(part) {
2310
+ if (part.type === "file") {
2311
+ throw new import_provider5.UnsupportedFunctionalityError({
2312
+ functionality: "Responses assistant file history is not supported."
2313
+ });
2314
+ }
2315
+ if (part.type === "tool-result") return convertToolResult(part);
2316
+ return part;
2317
+ }
2318
+ function convertToolItem(item) {
2319
+ switch (item.type) {
2320
+ case "custom":
2321
+ case "text":
2322
+ return item;
2323
+ case "file-data":
2324
+ case "image-data": {
2325
+ const delegateIsImage = (0, import_provider_utils2.getTopLevelMediaType)(item.mediaType) === "image";
2326
+ if (delegateIsImage !== (item.type === "image-data")) {
2327
+ throw new import_provider5.UnsupportedFunctionalityError({
2328
+ functionality: "Responses tool-result media whose legacy category disagrees with its media type."
2329
+ });
2330
+ }
2331
+ return { ...item, data: { data: item.data, type: "data" }, type: "file" };
2332
+ }
2333
+ case "file-id":
2334
+ case "image-file-id":
2335
+ return {
2336
+ data: {
2337
+ reference: typeof item.fileId === "string" ? { openai: item.fileId } : item.fileId,
2338
+ type: "reference"
2339
+ },
2340
+ mediaType: item.type === "image-file-id" ? "image" : "application/octet-stream",
2341
+ providerOptions: item.providerOptions,
2342
+ type: "file"
2343
+ };
2344
+ case "file-url":
2345
+ case "image-url":
2346
+ return {
2347
+ data: { type: "url", url: new URL(item.url) },
2348
+ mediaType: item.type === "image-url" ? "image" : "application/octet-stream",
2349
+ providerOptions: item.providerOptions,
2350
+ type: "file"
2351
+ };
2352
+ }
2353
+ }
2354
+ function convertToolResult(part) {
2355
+ return part.output.type === "content" ? { ...part, output: { ...part.output, value: part.output.value.map(convertToolItem) } } : { ...part, output: part.output };
2356
+ }
2357
+ var import_provider5, import_provider_utils2;
2358
+ var init_responses_adapters_v3_to_v4 = __esm({
2359
+ "src/responses-adapters-v3-to-v4.ts"() {
2360
+ "use strict";
2361
+ import_provider5 = require("@ai-sdk/provider");
2362
+ import_provider_utils2 = require("@ai-sdk/provider-utils");
2363
+ init_convert_to_sap_messages();
2364
+ }
2365
+ });
2366
+
2367
+ // src/adapter-metadata.ts
2368
+ var ORIGINAL_V4_FINISH_REASON;
2369
+ var init_adapter_metadata = __esm({
2370
+ "src/adapter-metadata.ts"() {
2371
+ "use strict";
2372
+ ORIGINAL_V4_FINISH_REASON = /* @__PURE__ */ Symbol.for(
2373
+ "@jerome-benoit/sap-ai-provider/adapter-metadata.originalV4FinishReason"
2374
+ );
2375
+ }
2376
+ });
2377
+
2378
+ // src/responses-adapters-v4-to-v3.ts
2379
+ function convertResponsesResultToV3(result) {
2380
+ return {
2381
+ ...result,
2382
+ content: result.content.map(convertContent),
2383
+ finishReason: convertFinishReason(result.finishReason),
2384
+ warnings: result.warnings.map(convertWarning)
2385
+ };
2386
+ }
2387
+ function convertResponsesStreamPartToV3(part) {
2388
+ switch (part.type) {
2389
+ case "custom":
2390
+ case "reasoning-file":
2391
+ throw new import_provider6.UnsupportedFunctionalityError({
2392
+ functionality: `Responses '${part.type}' output has no V3 equivalent.`
2393
+ });
2394
+ case "file":
2395
+ return convertGeneratedFile(part);
2396
+ case "finish":
2397
+ return { ...part, finishReason: convertFinishReason(part.finishReason) };
2398
+ case "stream-start":
2399
+ return { ...part, warnings: part.warnings.map(convertWarning) };
2400
+ default:
2401
+ return part;
2402
+ }
2403
+ }
2404
+ function convertContent(part) {
2405
+ if (part.type === "custom" || part.type === "reasoning-file") {
2406
+ throw new import_provider6.UnsupportedFunctionalityError({
2407
+ functionality: `Responses '${part.type}' output has no V3 equivalent.`
2408
+ });
2409
+ }
2410
+ return part.type === "file" ? convertGeneratedFile(part) : part;
2411
+ }
2412
+ function convertFinishReason(reason) {
2413
+ if (reason.unified !== "interrupted") return reason;
2414
+ const converted = { ...reason, unified: "other" };
2415
+ return Object.defineProperty(converted, ORIGINAL_V4_FINISH_REASON, { value: reason });
2416
+ }
2417
+ function convertGeneratedFile(part) {
2418
+ if (part.data.type !== "data") {
2419
+ throw new import_provider6.UnsupportedFunctionalityError({
2420
+ functionality: "Responses generated file URLs have no V3 equivalent and are not fetched."
2421
+ });
2422
+ }
2423
+ return { ...part, data: part.data.data };
2424
+ }
2425
+ function convertWarning(warning) {
2426
+ return warning.type === "deprecated" ? { message: `${warning.setting}: ${warning.message}`, type: "other" } : warning;
2427
+ }
2428
+ var import_provider6;
2429
+ var init_responses_adapters_v4_to_v3 = __esm({
2430
+ "src/responses-adapters-v4-to-v3.ts"() {
2431
+ "use strict";
2432
+ import_provider6 = require("@ai-sdk/provider");
2433
+ init_adapter_metadata();
2434
+ }
2435
+ });
2436
+
2437
+ // src/sap-http-stream.ts
2438
+ function destroyHttpResponse(response, retainedRequest) {
2439
+ const body = response.data;
2440
+ const request = response.request;
2441
+ try {
2442
+ if (isDestroyableRequest(body)) body.destroy();
2443
+ } finally {
2444
+ if (request !== retainedRequest && isDestroyableRequest(request)) request.destroy();
2445
+ }
2446
+ }
2447
+ function disposeSapStream(response) {
2448
+ if (disposedStreams.has(response)) return;
2449
+ disposedStreams.add(response);
2450
+ try {
2451
+ response.stream.controller.abort();
2452
+ } finally {
2453
+ if (leasedStreams.has(response)) releaseSapStream(response);
2454
+ else destroyHttpResponse(response.rawResponse);
2455
+ }
2456
+ }
2457
+ async function executeSapStream(execute, signal, requestConfig) {
2458
+ const responses = [];
2459
+ const cleanups = /* @__PURE__ */ new Set();
2460
+ let closed = false;
2461
+ let transferred = false;
2462
+ let failedRequest;
2463
+ let failedError;
2464
+ const release = () => {
2465
+ closed = true;
2466
+ signal?.removeEventListener("abort", release);
2467
+ for (const response of responses) {
2468
+ if (response.fromTransport && isConsumedHttpBody(response.data)) continue;
2469
+ const consumedRequest = responses.some(
2470
+ (other) => other.fromTransport && other.request === response.request && isConsumedHttpBody(other.data)
1968
2471
  );
2472
+ try {
2473
+ const dispose = response.disposeTimeout;
2474
+ const retainedRequest = consumedRequest ? response.request : void 0;
2475
+ if (dispose && cleanups.has(dispose)) dispose(retainedRequest);
2476
+ else destroyHttpResponse(response, retainedRequest);
2477
+ } catch {
2478
+ }
1969
2479
  }
2480
+ responses.length = 0;
2481
+ cleanups.clear();
2482
+ };
2483
+ const ownResponse = (response, request, fromTransport, failed) => {
2484
+ const data = response.data;
2485
+ const nativeRequest = response.request;
2486
+ const owned = responses.find((other) => other.data === data && other.request === nativeRequest);
2487
+ if (owned) {
2488
+ if (failed && !owned.disposeTimeout) {
2489
+ owned.disposeTimeout = preserveResponseBodyTimeout(response, request, cleanups);
2490
+ }
2491
+ } else {
2492
+ responses.push({
2493
+ data,
2494
+ disposeTimeout: failed ? preserveResponseBodyTimeout(response, request, cleanups) : void 0,
2495
+ fromTransport,
2496
+ request: nativeRequest
2497
+ });
2498
+ }
2499
+ if (closed || signal?.aborted) release();
2500
+ };
2501
+ const observeResponse = ({ fn }) => async (request) => {
2502
+ try {
2503
+ const response = await fn(request);
2504
+ ownResponse(response, request, true, false);
2505
+ return response;
2506
+ } catch (error) {
2507
+ const failed = findFailedHttpRequest(error);
2508
+ if (failed) ownResponse(failed.response, request, true, true);
2509
+ throw error;
2510
+ }
2511
+ };
2512
+ const captureFinalFailure = ({ fn }) => async (request) => {
2513
+ try {
2514
+ const response = await fn(request);
2515
+ ownResponse(response, request, false, false);
2516
+ return response;
2517
+ } catch (error) {
2518
+ const failed = findFailedHttpRequest(error);
2519
+ if (!failed) throw error;
2520
+ failedRequest = failed;
2521
+ failedError = error;
2522
+ ownResponse(failed.response, request, false, true);
2523
+ return failed.response;
2524
+ }
2525
+ };
2526
+ try {
2527
+ const response = await waitWithAbort(
2528
+ execute({
2529
+ ...requestConfig,
2530
+ middleware: [captureFinalFailure, ...requestConfig?.middleware ?? [], observeResponse]
2531
+ }),
2532
+ signal,
2533
+ disposeSapStream
2534
+ );
2535
+ if (signal?.aborted) {
2536
+ try {
2537
+ disposeSapStream(response);
2538
+ } finally {
2539
+ throwIfAborted(signal);
2540
+ }
2541
+ }
2542
+ if (failedRequest) {
2543
+ try {
2544
+ await readHttpErrorBody(
2545
+ failedRequest.response,
2546
+ createErrorByteStream(failedRequest.response),
2547
+ signal
2548
+ );
2549
+ } catch {
2550
+ throwIfAborted(signal);
2551
+ }
2552
+ throw failedError;
2553
+ }
2554
+ if (responses.length > 0) {
2555
+ streamLeases.set(response, release);
2556
+ leasedStreams.add(response);
2557
+ signal?.addEventListener("abort", release, { once: true });
2558
+ if (signal?.aborted) {
2559
+ releaseSapStream(response);
2560
+ throwIfAborted(signal);
2561
+ }
2562
+ transferred = true;
2563
+ }
2564
+ return response;
2565
+ } finally {
2566
+ if (!transferred) release();
1970
2567
  }
1971
2568
  }
1972
- var ORCHESTRATION_ONLY_FEATURE_KEYS, ORCHESTRATION_ONLY_FEATURES, FOUNDATION_MODELS_ONLY_FEATURE_KEYS, FOUNDATION_MODELS_ONLY_FEATURES, ORCHESTRATION_ONLY_INVOCATION_FEATURE_KEYS, ORCHESTRATION_ONLY_EMBEDDING_FEATURE_KEYS, ORCHESTRATION_ONLY_EMBEDDING_FEATURES, ESCAPE_TEMPLATE_PLACEHOLDERS_DESCRIPTION, VALID_API_TYPES;
1973
- var init_sap_ai_validation = __esm({
1974
- "src/sap-ai-validation.ts"() {
2569
+ function findFailedHttpRequest(error) {
2570
+ const seen = /* @__PURE__ */ new Set();
2571
+ let current = error;
2572
+ for (let depth = 0; depth < 32; depth++) {
2573
+ if (typeof current !== "object" || current === null || seen.has(current)) return void 0;
2574
+ if (import_provider7.AISDKError.isInstance(current)) return void 0;
2575
+ seen.add(current);
2576
+ if (isFailedHttpRequest(current)) return current;
2577
+ current = "cause" in current ? current.cause : current instanceof Error && (0, import_util2.isErrorWithCause)(current) ? current.rootCause : void 0;
2578
+ }
2579
+ return void 0;
2580
+ }
2581
+ function isDestroyableRequest(request) {
2582
+ return typeof request === "object" && request !== null && "destroy" in request && typeof request.destroy === "function";
2583
+ }
2584
+ function preserveResponseBodyTimeout(response, requestConfig, cleanups) {
2585
+ const body = response.data;
2586
+ const request = response.request;
2587
+ if (!isHttpResponseEvents(body) || !isHttpResponseEvents(request)) return;
2588
+ const responseConfig = "config" in response ? response.config : void 0;
2589
+ const timeoutConfig = typeof responseConfig === "object" && responseConfig !== null && !Array.isArray(responseConfig) ? responseConfig : requestConfig;
2590
+ let ownsRequest = true;
2591
+ const release = () => {
2592
+ request.removeListener("timeout", onTimeout);
2593
+ body.removeListener("end", release);
2594
+ body.removeListener("error", onFailure);
2595
+ body.removeListener("close", onFailure);
2596
+ cleanups.delete(dispose);
2597
+ };
2598
+ const onFailure = () => {
2599
+ try {
2600
+ if (ownsRequest) request.destroy();
2601
+ } finally {
2602
+ release();
2603
+ }
2604
+ };
2605
+ const dispose = (retainedRequest) => {
2606
+ ownsRequest = request !== retainedRequest;
2607
+ request.removeListener("timeout", onTimeout);
2608
+ try {
2609
+ body.destroy();
2610
+ } finally {
2611
+ if (ownsRequest) request.destroy();
2612
+ }
2613
+ };
2614
+ const onTimeout = () => {
2615
+ const nativeResponse = "res" in request ? request.res : void 0;
2616
+ if (typeof nativeResponse === "object" && nativeResponse !== null && "complete" in nativeResponse && nativeResponse.complete === true) {
2617
+ release();
2618
+ return;
2619
+ }
2620
+ const timeout = timeoutConfig.timeout;
2621
+ const timeoutErrorMessage = timeoutConfig.timeoutErrorMessage;
2622
+ const transitional = timeoutConfig.transitional;
2623
+ const clarifyTimeoutError = typeof transitional === "object" && transitional !== null && "clarifyTimeoutError" in transitional && transitional.clarifyTimeoutError === true;
2624
+ const message = typeof timeoutErrorMessage === "string" && timeoutErrorMessage ? timeoutErrorMessage : (typeof timeout === "number" || typeof timeout === "string") && timeout ? `timeout of ${String(timeout)}ms exceeded` : "timeout exceeded";
2625
+ body.destroy(
2626
+ Object.assign(new Error(message), {
2627
+ code: clarifyTimeoutError ? "ETIMEDOUT" : "ECONNABORTED"
2628
+ })
2629
+ );
2630
+ request.destroy();
2631
+ };
2632
+ request.once("timeout", onTimeout);
2633
+ body.once("end", release);
2634
+ body.once("error", onFailure);
2635
+ body.once("close", onFailure);
2636
+ cleanups.add(dispose);
2637
+ return dispose;
2638
+ }
2639
+ async function readHttpErrorBody(response, stream, signal) {
2640
+ const decoder = new TextDecoder();
2641
+ const reader = stream.getReader();
2642
+ let retainedBytes = 0;
2643
+ let text = "";
2644
+ let truncated = false;
2645
+ let readFailure;
2646
+ try {
2647
+ for (; ; ) {
2648
+ const chunk = await waitWithAbort(reader.read(), signal);
2649
+ if (chunk.done) {
2650
+ text += decoder.decode();
2651
+ break;
2652
+ }
2653
+ const remaining = MAX_ERROR_BODY_BYTES - retainedBytes;
2654
+ text += decoder.decode(chunk.value.subarray(0, remaining), { stream: true });
2655
+ retainedBytes += Math.min(chunk.value.byteLength, remaining);
2656
+ if (chunk.value.byteLength > remaining) {
2657
+ truncated = true;
2658
+ await reader.cancel("HTTP error diagnostic limit exceeded");
2659
+ break;
2660
+ }
2661
+ }
2662
+ } catch (error) {
2663
+ readFailure = error;
2664
+ if (!truncated) text += decoder.decode();
2665
+ void reader.cancel(error).catch(() => {
2666
+ });
2667
+ } finally {
2668
+ if (signal?.aborted) {
2669
+ destroyHttpResponse(response);
2670
+ void reader.cancel(signal.reason).catch(() => {
2671
+ });
2672
+ }
2673
+ reader.releaseLock();
2674
+ }
2675
+ response.data = truncated ? text + ERROR_BODY_TRUNCATION : text;
2676
+ if (!truncated && readFailure === void 0) {
2677
+ try {
2678
+ response.data = JSON.parse(text);
2679
+ } catch {
2680
+ response.data = text;
2681
+ }
2682
+ }
2683
+ throwIfAborted(signal);
2684
+ return readFailure;
2685
+ }
2686
+ function withSapStreamCleanup(response, stream) {
2687
+ if (!streamLeases.has(response)) return stream;
2688
+ return iterate();
2689
+ async function* iterate() {
2690
+ try {
2691
+ yield* stream;
2692
+ } finally {
2693
+ releaseSapStream(response);
2694
+ }
2695
+ }
2696
+ }
2697
+ function createErrorByteStream(response) {
2698
+ const body = response.data;
2699
+ if (typeof body !== "object" || body === null || !(Symbol.asyncIterator in body) || typeof body[Symbol.asyncIterator] !== "function") {
2700
+ throw new TypeError("SAP did not return a readable HTTP error body.");
2701
+ }
2702
+ const iterator = body[Symbol.asyncIterator]();
2703
+ const encoder = new TextEncoder();
2704
+ return new ReadableStream(
2705
+ {
2706
+ cancel() {
2707
+ destroyHttpResponse(response);
2708
+ },
2709
+ async pull(controller) {
2710
+ try {
2711
+ const chunk = await iterator.next();
2712
+ if (chunk.done) controller.close();
2713
+ else if (typeof chunk.value === "string") controller.enqueue(encoder.encode(chunk.value));
2714
+ else if (chunk.value instanceof Uint8Array) controller.enqueue(chunk.value);
2715
+ else throw new TypeError("SAP returned a non-byte HTTP error chunk.");
2716
+ } catch (error) {
2717
+ try {
2718
+ destroyHttpResponse(response);
2719
+ } catch {
2720
+ } finally {
2721
+ controller.error(error);
2722
+ }
2723
+ }
2724
+ }
2725
+ },
2726
+ { highWaterMark: 0 }
2727
+ );
2728
+ }
2729
+ function isConsumedHttpBody(body) {
2730
+ return typeof body === "object" && body !== null && "readableEnded" in body && body.readableEnded === true;
2731
+ }
2732
+ function isFailedHttpRequest(error) {
2733
+ return error instanceof Error && "isAxiosError" in error && error.isAxiosError === true && "response" in error && typeof error.response === "object" && error.response !== null;
2734
+ }
2735
+ function isHttpResponseEvents(value) {
2736
+ return isDestroyableRequest(value) && "once" in value && typeof value.once === "function" && "removeListener" in value && typeof value.removeListener === "function";
2737
+ }
2738
+ function releaseSapStream(response) {
2739
+ const release = streamLeases.get(response);
2740
+ streamLeases.delete(response);
2741
+ release?.();
2742
+ }
2743
+ var import_provider7, import_util2, ERROR_BODY_TRUNCATION, MAX_ERROR_BODY_BYTES, ERROR_BODY_READ_FAILURE, disposedStreams, leasedStreams, streamLeases;
2744
+ var init_sap_http_stream = __esm({
2745
+ "src/sap-http-stream.ts"() {
2746
+ "use strict";
2747
+ import_provider7 = require("@ai-sdk/provider");
2748
+ import_util2 = require("@sap-cloud-sdk/util");
2749
+ init_abort_utils();
2750
+ ERROR_BODY_TRUNCATION = "...[truncated]";
2751
+ MAX_ERROR_BODY_BYTES = 2e3 - ERROR_BODY_TRUNCATION.length;
2752
+ ERROR_BODY_READ_FAILURE = /* @__PURE__ */ Symbol("sap-ai.httpErrorBodyReadFailure");
2753
+ disposedStreams = /* @__PURE__ */ new WeakSet();
2754
+ leasedStreams = /* @__PURE__ */ new WeakSet();
2755
+ streamLeases = /* @__PURE__ */ new WeakMap();
2756
+ }
2757
+ });
2758
+
2759
+ // src/responses-http-transport.ts
2760
+ async function createResponsesTransport(config, settings, options) {
2761
+ throwIfAborted(options.abortSignal);
2762
+ const deployment = buildModelDeployment(config, settings.modelVersion);
2763
+ const [deploymentId, destination] = await waitWithAbort(
2764
+ Promise.all([
2765
+ (0, import_internal.getFoundationModelDeploymentId)(deployment, "azure-openai", config.destination),
2766
+ (0, import_core.getAiCoreDestination)(config.destination)
2767
+ ]),
2768
+ options.abortSignal
2769
+ );
2770
+ throwIfAborted(options.abortSignal);
2771
+ const deploymentPath = `/inference/deployments/${encodeURIComponent(deploymentId)}`;
2772
+ const baseURL = (0, import_internal2.getTargetUrl)(destination.url, deploymentPath);
2773
+ const endpoint = new URL(`${baseURL}/responses`);
2774
+ const requestConfig = mergeRequestConfig(
2775
+ config.requestConfig,
2776
+ options.abortSignal,
2777
+ options.headers
2778
+ );
2779
+ const activeRequests = /* @__PURE__ */ new Set();
2780
+ let disposed = false;
2781
+ let disposalReason;
2782
+ const dispose = (reason) => {
2783
+ if (disposed) return;
2784
+ disposed = true;
2785
+ disposalReason = reason;
2786
+ for (const release of activeRequests) {
2787
+ try {
2788
+ release(reason);
2789
+ } catch {
2790
+ }
2791
+ }
2792
+ activeRequests.clear();
2793
+ };
2794
+ const fetch = async (input, init) => {
2795
+ if (disposed) throw createAbortError(disposalReason);
2796
+ const url = new URL(typeof input === "string" || input instanceof URL ? input : input.url);
2797
+ if (url.origin !== endpoint.origin || url.pathname !== endpoint.pathname) {
2798
+ throw new TypeError("SAP Responses requests must target the configured deployment.");
2799
+ }
2800
+ if (init?.method !== "POST" || typeof init.body !== "string") {
2801
+ throw new TypeError("SAP Responses requires a POST request with a JSON body.");
2802
+ }
2803
+ const body = JSON.parse(init.body);
2804
+ const operation = typeof body === "object" && body !== null && "stream" in body && body.stream === true ? "doStream" : "doGenerate";
2805
+ const controller = new AbortController();
2806
+ const signal = options.abortSignal ?? init.signal;
2807
+ const bodyTimeoutCleanups = /* @__PURE__ */ new Set();
2808
+ let abortFailedRequest;
2809
+ let activeResponse;
2810
+ const onAbort = () => {
2811
+ controller.abort(signal?.reason);
2812
+ };
2813
+ const cleanup = () => {
2814
+ activeRequests.delete(disposeRequest);
2815
+ signal?.removeEventListener("abort", onAbort);
2816
+ if (abortFailedRequest) controller.signal.removeEventListener("abort", abortFailedRequest);
2817
+ for (const dispose2 of bodyTimeoutCleanups) dispose2();
2818
+ activeResponse = void 0;
2819
+ };
2820
+ const disposeRequest = (reason) => {
2821
+ try {
2822
+ controller.abort(reason);
2823
+ } finally {
2824
+ try {
2825
+ if (activeResponse) destroyHttpResponse(activeResponse);
2826
+ } finally {
2827
+ cleanup();
2828
+ }
2829
+ }
2830
+ };
2831
+ throwIfAborted(signal ?? void 0);
2832
+ signal?.addEventListener("abort", onAbort, { once: true });
2833
+ activeRequests.add(disposeRequest);
2834
+ const headers = new Headers(init.headers);
2835
+ headers.delete("authorization");
2836
+ const configuredHeaders = Object.fromEntries(
2837
+ Object.entries(requestConfig?.headers ?? {}).map(([key, value]) => [
2838
+ key.toLowerCase(),
2839
+ value
2840
+ ])
2841
+ );
2842
+ let failedRequest;
2843
+ let failedError;
2844
+ const watchResponse = (response, request) => {
2845
+ activeResponse = response;
2846
+ if (controller.signal.aborted) destroyHttpResponse(response);
2847
+ else preserveResponseBodyTimeout(response, request, bodyTimeoutCleanups);
2848
+ return response;
2849
+ };
2850
+ const preserveBodyTimeout = ({ fn }) => async (request) => {
2851
+ try {
2852
+ return watchResponse(await fn(request), request);
2853
+ } catch (error) {
2854
+ const failed = findFailedHttpRequest(error);
2855
+ if (failed) watchResponse(failed.response, request);
2856
+ throw error;
2857
+ }
2858
+ };
2859
+ const preserveErrorResponse = ({ fn }) => async (request) => {
2860
+ try {
2861
+ return await fn(request);
2862
+ } catch (error) {
2863
+ const failed = findFailedHttpRequest(error);
2864
+ if (!failed) throw error;
2865
+ failedRequest = failed;
2866
+ failedError = error;
2867
+ const request2 = failed.response.request;
2868
+ if (isDestroyableRequest(request2)) {
2869
+ abortFailedRequest = () => {
2870
+ request2.destroy();
2871
+ };
2872
+ if (controller.signal.aborted) abortFailedRequest();
2873
+ else controller.signal.addEventListener("abort", abortFailedRequest, { once: true });
2874
+ }
2875
+ return failed.response;
2876
+ }
2877
+ };
2878
+ try {
2879
+ const pendingResponse = (0, import_core.executeRequest)(
2880
+ {
2881
+ apiVersion: "2024-10-21",
2882
+ resourceGroup: (0, import_internal.getResourceGroup)(deployment),
2883
+ url: `${deploymentPath}/responses`
2884
+ },
2885
+ body,
2886
+ {
2887
+ ...requestConfig,
2888
+ headers: { ...Object.fromEntries(headers), ...configuredHeaders },
2889
+ middleware: [
2890
+ preserveErrorResponse,
2891
+ ...requestConfig?.middleware ?? [],
2892
+ preserveBodyTimeout
2893
+ ],
2894
+ responseType: "stream",
2895
+ signal: controller.signal
2896
+ },
2897
+ config.destination
2898
+ );
2899
+ const response = await waitWithAbort(pendingResponse, controller.signal, destroyHttpResponse);
2900
+ activeResponse = response;
2901
+ if (controller.signal.aborted) {
2902
+ destroyHttpResponse(response);
2903
+ throw createAbortError(controller.signal.reason);
2904
+ }
2905
+ const responseBody = response.data;
2906
+ const responseStream = createByteStream(
2907
+ responseBody,
2908
+ controller,
2909
+ cleanup,
2910
+ config,
2911
+ options,
2912
+ operation
2913
+ );
2914
+ if (failedRequest) {
2915
+ const readFailure = await readHttpErrorBody(
2916
+ failedRequest.response,
2917
+ responseStream,
2918
+ signal ?? void 0
2919
+ );
2920
+ const failure = convertToAISDKError(failedError, {
2921
+ modelId: config.modelId,
2922
+ modelType: "languageModel",
2923
+ operation,
2924
+ requestBody: createAISDKRequestBodySummary(options),
2925
+ url: "sap-ai:responses"
2926
+ });
2927
+ if (readFailure !== void 0 && import_provider8.APICallError.isInstance(failure)) {
2928
+ Object.defineProperty(failure, ERROR_BODY_READ_FAILURE, { value: readFailure });
2929
+ }
2930
+ throw failure;
2931
+ }
2932
+ return new Response(responseStream, {
2933
+ headers: normalizeHeaders(response.headers),
2934
+ status: response.status
2935
+ });
2936
+ } catch (error) {
2937
+ dispose(error);
2938
+ throw error;
2939
+ }
2940
+ };
2941
+ return { baseURL, dispose, fetch };
2942
+ }
2943
+ function createByteStream(body, requestController, cleanup, config, options, operation) {
2944
+ if (typeof body !== "object" || body === null || !(Symbol.asyncIterator in body) || typeof body[Symbol.asyncIterator] !== "function") {
2945
+ requestController.abort();
2946
+ cleanup();
2947
+ throw new TypeError("SAP Responses did not return a readable response body.");
2948
+ }
2949
+ const source = body;
2950
+ const iterator = source[Symbol.asyncIterator]();
2951
+ const encoder = new TextEncoder();
2952
+ const onAbort = () => source.destroy?.();
2953
+ const cleanupStream = () => {
2954
+ requestController.signal.removeEventListener("abort", onAbort);
2955
+ cleanup();
2956
+ };
2957
+ requestController.signal.addEventListener("abort", onAbort, { once: true });
2958
+ if (requestController.signal.aborted) onAbort();
2959
+ return new ReadableStream(
2960
+ {
2961
+ async cancel(reason) {
2962
+ requestController.abort(reason);
2963
+ cleanupStream();
2964
+ if (source.destroy) {
2965
+ source.destroy();
2966
+ } else {
2967
+ await iterator.return?.();
2968
+ }
2969
+ },
2970
+ async pull(controller) {
2971
+ try {
2972
+ throwIfAborted(requestController.signal);
2973
+ const chunk = await iterator.next();
2974
+ throwIfAborted(requestController.signal);
2975
+ if (chunk.done) {
2976
+ cleanupStream();
2977
+ controller.close();
2978
+ } else if (typeof chunk.value === "string") {
2979
+ controller.enqueue(encoder.encode(chunk.value));
2980
+ } else if (chunk.value instanceof Uint8Array) {
2981
+ controller.enqueue(chunk.value);
2982
+ } else {
2983
+ throw new TypeError("SAP Responses returned a non-byte response chunk.");
2984
+ }
2985
+ } catch (error) {
2986
+ const failure = requestController.signal.aborted ? createAbortError(requestController.signal.reason) : error;
2987
+ requestController.abort(error);
2988
+ cleanupStream();
2989
+ source.destroy?.();
2990
+ controller.error(
2991
+ convertToAISDKError(failure, {
2992
+ modelId: config.modelId,
2993
+ modelType: "languageModel",
2994
+ operation,
2995
+ requestBody: createAISDKRequestBodySummary(options),
2996
+ url: "sap-ai:responses"
2997
+ })
2998
+ );
2999
+ }
3000
+ }
3001
+ },
3002
+ { highWaterMark: 0 }
3003
+ );
3004
+ }
3005
+ var import_provider8, import_internal, import_core, import_internal2;
3006
+ var init_responses_http_transport = __esm({
3007
+ "src/responses-http-transport.ts"() {
1975
3008
  "use strict";
1976
- init_deep_merge();
3009
+ import_provider8 = require("@ai-sdk/provider");
3010
+ import_internal = require("@sap-ai-sdk/ai-api/internal.js");
3011
+ import_core = require("@sap-ai-sdk/core");
3012
+ import_internal2 = require("@sap-ai-sdk/core/internal.js");
3013
+ init_abort_utils();
1977
3014
  init_sap_ai_error();
1978
- ORCHESTRATION_ONLY_FEATURE_KEYS = [
1979
- "fallbackModuleConfigs",
1980
- "filtering",
1981
- "grounding",
1982
- "masking",
1983
- "orchestrationConfigRef",
1984
- "placeholderValues",
1985
- "promptTemplateRef",
1986
- "streamOptions",
1987
- "tools",
1988
- "translation"
1989
- ];
1990
- ORCHESTRATION_ONLY_FEATURES = {
1991
- fallbackModuleConfigs: "Fallback module configurations (fallbackModuleConfigs)",
1992
- filtering: "Content filtering",
1993
- grounding: "Document grounding",
1994
- masking: "Data masking",
1995
- orchestrationConfigRef: "Orchestration config reference (orchestrationConfigRef)",
1996
- placeholderValues: "Placeholder values (placeholderValues)",
1997
- promptTemplateRef: "Prompt template reference (promptTemplateRef)",
1998
- streamOptions: "Stream options for post-LLM modules",
1999
- tools: "SAP-format tool definitions (use AI SDK tools instead)",
2000
- translation: "Translation"
2001
- };
2002
- FOUNDATION_MODELS_ONLY_FEATURE_KEYS = ["dataSources"];
2003
- FOUNDATION_MODELS_ONLY_FEATURES = {
2004
- dataSources: "Azure On Your Data (dataSources)"
2005
- };
2006
- ORCHESTRATION_ONLY_INVOCATION_FEATURE_KEYS = [
2007
- "orchestrationConfigRef",
2008
- "placeholderValues",
2009
- "promptTemplateRef"
2010
- ];
2011
- ORCHESTRATION_ONLY_EMBEDDING_FEATURE_KEYS = ["masking"];
2012
- ORCHESTRATION_ONLY_EMBEDDING_FEATURES = {
2013
- masking: ORCHESTRATION_ONLY_FEATURES.masking
2014
- };
2015
- ESCAPE_TEMPLATE_PLACEHOLDERS_DESCRIPTION = "escapeTemplatePlaceholders (Jinja2 template escaping)";
2016
- VALID_API_TYPES = ["orchestration", "foundation-models"];
3015
+ init_sap_http_stream();
3016
+ init_strategy_utils();
2017
3017
  }
2018
3018
  });
2019
3019
 
2020
- // src/orchestration-embedding-model-strategy.ts
2021
- var orchestration_embedding_model_strategy_exports = {};
2022
- __export(orchestration_embedding_model_strategy_exports, {
2023
- OrchestrationEmbeddingModelStrategy: () => OrchestrationEmbeddingModelStrategy
3020
+ // src/responses-language-model-strategy.ts
3021
+ var responses_language_model_strategy_exports = {};
3022
+ __export(responses_language_model_strategy_exports, {
3023
+ ResponsesLanguageModelStrategy: () => ResponsesLanguageModelStrategy
2024
3024
  });
2025
- var OrchestrationEmbeddingModelStrategy;
2026
- var init_orchestration_embedding_model_strategy = __esm({
2027
- "src/orchestration-embedding-model-strategy.ts"() {
2028
- "use strict";
2029
- init_base_embedding_model_strategy();
2030
- init_sap_ai_validation();
2031
- init_strategy_utils();
2032
- OrchestrationEmbeddingModelStrategy = class extends BaseEmbeddingModelStrategy {
2033
- ClientClass;
2034
- constructor(ClientClass) {
2035
- super();
2036
- this.ClientClass = ClientClass;
2037
- }
2038
- createClient(config, settings, embeddingOptions) {
2039
- const mergedParams = this.mergeModelParams(settings, embeddingOptions);
2040
- const embeddingConfig = {
2041
- model: {
2042
- name: config.modelId,
2043
- ...hasKeys(mergedParams) ? { params: mergedParams } : {},
2044
- ...settings.modelVersion ? { version: settings.modelVersion } : {}
2045
- }
3025
+ function convertError(error, config, options, operation) {
3026
+ if (import_provider9.APICallError.isInstance(error) && error.message === "Failed to process successful response" && error.statusCode !== void 0 && error.statusCode >= 200 && error.statusCode < 300 && import_provider9.APICallError.isInstance(error.cause)) {
3027
+ return error.cause;
3028
+ }
3029
+ if (operation === "doStream" && !import_provider9.APICallError.isInstance(error)) {
3030
+ const parsed = OPENAI_STREAM_ERROR_SCHEMA.safeParse(error);
3031
+ if (parsed.success) {
3032
+ return new import_provider9.APICallError({
3033
+ cause: error,
3034
+ data: parsed.data.data,
3035
+ isRetryable: parsed.data.isRetryable,
3036
+ message: parsed.data.message,
3037
+ requestBodyValues: createAISDKRequestBodySummary(options),
3038
+ statusCode: parsed.data.statusCode,
3039
+ url: "sap-ai:responses"
3040
+ });
3041
+ }
3042
+ }
3043
+ return convertToAISDKError(error, {
3044
+ modelId: config.modelId,
3045
+ modelType: "languageModel",
3046
+ operation,
3047
+ requestBody: createAISDKRequestBodySummary(options),
3048
+ url: "sap-ai:responses"
3049
+ });
3050
+ }
3051
+ function fromOpenAI(metadata, providerName) {
3052
+ if (providerName === "openai" || !metadata?.openai) return metadata;
3053
+ const { openai, ...rest } = metadata;
3054
+ return { ...rest, [providerName]: { ...rest[providerName], ...openai } };
3055
+ }
3056
+ function fromOpenAICitations(citations, providerName) {
3057
+ if (providerName === "openai" || !citations) return citations;
3058
+ let mapped;
3059
+ let index = 0;
3060
+ for (const citation of citations) {
3061
+ const providerMetadata = fromOpenAI(citation.source.providerMetadata, providerName);
3062
+ if (providerMetadata !== citation.source.providerMetadata) {
3063
+ mapped ??= citations.slice();
3064
+ mapped[index] = {
3065
+ ...citation,
3066
+ source: { ...citation.source, providerMetadata }
3067
+ };
3068
+ }
3069
+ index++;
3070
+ }
3071
+ return mapped ?? citations;
3072
+ }
3073
+ function fromOpenAIContent(part, providerName) {
3074
+ const providerMetadata = fromOpenAI(part.providerMetadata, providerName);
3075
+ const citations = fromOpenAICitations(part.citations, providerName);
3076
+ if (providerMetadata === part.providerMetadata && citations === part.citations) return part;
3077
+ if (providerMetadata === part.providerMetadata) return { ...part, citations };
3078
+ return citations === part.citations ? { ...part, providerMetadata } : { ...part, citations, providerMetadata };
3079
+ }
3080
+ function modelResponseFormat(settings) {
3081
+ const format = settings.responseFormat;
3082
+ if (!format || format.type === "text") return format;
3083
+ if (format.type === "json_object") return { type: "json" };
3084
+ const schema = format.json_schema;
3085
+ return {
3086
+ description: schema.description,
3087
+ name: schema.name,
3088
+ schema: schema.schema === void 0 ? void 0 : import_zod3.z.record(import_zod3.z.string(), import_zod3.z.json()).parse(schema.schema),
3089
+ type: "json"
3090
+ };
3091
+ }
3092
+ async function prepareModel(config, settings, options) {
3093
+ if (options.abortSignal?.aborted) {
3094
+ throw createAbortError(options.abortSignal.reason);
3095
+ }
3096
+ const providerName = getProviderName(config.provider);
3097
+ const sapOptions = config.parsedProviderOptions;
3098
+ const parameters = { ...settings.modelParams, ...sapOptions?.modelParams };
3099
+ const warnings = Object.keys(parameters).filter((key) => !MODEL_PARAMETERS.has(key)).map((key) => ({
3100
+ details: "Use the responses option for Responses-specific parameters.",
3101
+ feature: `modelParams.${key}`,
3102
+ type: "unsupported"
3103
+ }));
3104
+ if (sapOptions?.includeReasoning ?? settings.includeReasoning) {
3105
+ warnings.push({
3106
+ details: "Responses preserves native reasoning history instead of converting it to text.",
3107
+ feature: "includeReasoning",
3108
+ type: "unsupported"
3109
+ });
3110
+ }
3111
+ const responseOptions = {
3112
+ ...parameters.parallel_tool_calls !== void 0 ? { parallelToolCalls: parameters.parallel_tool_calls } : {},
3113
+ ...settings.responseFormat?.type === "json_schema" ? { strictJsonSchema: settings.responseFormat.json_schema.strict } : {},
3114
+ store: false,
3115
+ ...settings.responses,
3116
+ ...sapOptions?.responses
3117
+ };
3118
+ const reasoning = "reasoning" in options ? options.reasoning : void 0;
3119
+ if (typeof reasoning === "string" && reasoning !== "provider-default") {
3120
+ responseOptions.reasoningEffort = reasoning;
3121
+ }
3122
+ const input = {
3123
+ ...options,
3124
+ frequencyPenalty: options.frequencyPenalty ?? parameters.frequencyPenalty,
3125
+ maxOutputTokens: options.maxOutputTokens ?? parameters.maxTokens,
3126
+ presencePenalty: options.presencePenalty ?? parameters.presencePenalty,
3127
+ prompt: toOpenAIPrompt(options.prompt, providerName),
3128
+ providerOptions: {
3129
+ ...options.providerOptions,
3130
+ openai: responseOptions
3131
+ },
3132
+ responseFormat: options.responseFormat ?? modelResponseFormat(settings),
3133
+ temperature: options.temperature ?? parameters.temperature,
3134
+ tools: options.tools?.map(
3135
+ (tool) => tool.type === "function" ? {
3136
+ ...tool,
3137
+ providerOptions: toOpenAI(tool.providerOptions, providerName),
3138
+ strict: tool.strict ?? false
3139
+ } : tool
3140
+ ),
3141
+ topP: options.topP ?? parameters.topP
3142
+ };
3143
+ const convertedInput = convertResponsesCallToV4(input);
3144
+ const transport = await createResponsesTransport(config, settings, options);
3145
+ const model = (0, import_openai.createOpenAI)({
3146
+ // Authentication is supplied by SAP's transport, not an OpenAI API key.
3147
+ apiKey: "sap-ai-core",
3148
+ baseURL: transport.baseURL,
3149
+ fetch: transport.fetch
3150
+ }).responses(config.modelId);
3151
+ return { dispose: transport.dispose, input: convertedInput, model, providerName, warnings };
3152
+ }
3153
+ function responseMetadata(metadata, providerName) {
3154
+ const mapped = fromOpenAI(metadata, providerName);
3155
+ return {
3156
+ ...mapped,
3157
+ [providerName]: { ...mapped?.[providerName], api: "responses", version: VERSION }
3158
+ };
3159
+ }
3160
+ function toOpenAI(options, providerName) {
3161
+ if (providerName === "openai" || !options?.[providerName]) return options;
3162
+ return { ...options, openai: { ...options.openai, ...options[providerName] } };
3163
+ }
3164
+ function toOpenAIOutput(output, providerName) {
3165
+ const mappedOutput = {
3166
+ ...output,
3167
+ providerOptions: toOpenAI(output.providerOptions, providerName)
3168
+ };
3169
+ if (mappedOutput.type !== "content") return mappedOutput;
3170
+ return {
3171
+ ...mappedOutput,
3172
+ value: mappedOutput.value.map((part) => ({
3173
+ ...part,
3174
+ ...(part.type === "file-id" || part.type === "image-file-id") && typeof part.fileId !== "string" && part.fileId[providerName] ? { fileId: { ...part.fileId, openai: part.fileId[providerName] } } : {},
3175
+ ..."providerOptions" in part ? { providerOptions: toOpenAI(part.providerOptions, providerName) } : {}
3176
+ }))
3177
+ };
3178
+ }
3179
+ function toOpenAIPart(part, providerName) {
3180
+ return {
3181
+ ...part,
3182
+ ...part.type === "tool-result" ? { output: toOpenAIOutput(part.output, providerName) } : {},
3183
+ providerOptions: toOpenAI(part.providerOptions, providerName)
3184
+ };
3185
+ }
3186
+ function toOpenAIPrompt(prompt, providerName) {
3187
+ return prompt.map((message) => {
3188
+ const providerOptions = toOpenAI(message.providerOptions, providerName);
3189
+ switch (message.role) {
3190
+ case "assistant":
3191
+ return {
3192
+ ...message,
3193
+ content: message.content.map((part) => toOpenAIPart(part, providerName)),
3194
+ providerOptions
2046
3195
  };
2047
- const moduleConfig = {
2048
- embeddings: embeddingConfig,
2049
- ...settings.masking && hasKeys(settings.masking) ? { masking: settings.masking } : {}
3196
+ case "system":
3197
+ return { ...message, providerOptions };
3198
+ case "tool":
3199
+ return {
3200
+ ...message,
3201
+ content: message.content.map((part) => toOpenAIPart(part, providerName)),
3202
+ providerOptions
2050
3203
  };
2051
- return new this.ClientClass(moduleConfig, config.deploymentConfig, config.destination);
2052
- }
2053
- async executeCall(client, values, embeddingType, requestConfig) {
2054
- return client.embed({ input: values, type: embeddingType }, requestConfig);
2055
- }
2056
- extractEmbeddings(response) {
2057
- const embeddingData = response.getEmbeddings();
2058
- const sortedEmbeddings = [...embeddingData].sort((a, b) => a.index - b.index);
2059
- return sortedEmbeddings.map((data) => normalizeEmbedding(data.embedding));
2060
- }
2061
- extractResponseMetadata(response) {
2062
- return extractResponseMetadata(response, "response");
2063
- }
2064
- extractTokenCount(response) {
2065
- const tokenUsage = response.getTokenUsage();
2066
- return tokenUsage.total_tokens;
2067
- }
2068
- getUrl() {
2069
- return "sap-ai:orchestration/embeddings";
3204
+ case "user":
3205
+ return {
3206
+ ...message,
3207
+ content: message.content.map((part) => toOpenAIPart(part, providerName)),
3208
+ providerOptions
3209
+ };
3210
+ }
3211
+ });
3212
+ }
3213
+ var import_openai, import_provider9, import_zod3, MODEL_PARAMETERS, OPENAI_STREAM_ERROR_SCHEMA, ResponsesLanguageModelStrategy;
3214
+ var init_responses_language_model_strategy = __esm({
3215
+ "src/responses-language-model-strategy.ts"() {
3216
+ "use strict";
3217
+ import_openai = require("@ai-sdk/openai");
3218
+ import_provider9 = require("@ai-sdk/provider");
3219
+ import_zod3 = require("zod");
3220
+ init_abort_utils();
3221
+ init_responses_adapters_v3_to_v4();
3222
+ init_responses_adapters_v4_to_v3();
3223
+ init_responses_http_transport();
3224
+ init_sap_ai_error();
3225
+ init_sap_ai_provider_options();
3226
+ init_strategy_utils();
3227
+ init_version();
3228
+ MODEL_PARAMETERS = /* @__PURE__ */ new Set([
3229
+ "frequencyPenalty",
3230
+ "maxTokens",
3231
+ "parallel_tool_calls",
3232
+ "presencePenalty",
3233
+ "temperature",
3234
+ "topP"
3235
+ ]);
3236
+ OPENAI_STREAM_ERROR_SCHEMA = import_zod3.z.object({
3237
+ data: import_zod3.z.object({ type: import_zod3.z.enum(["error", "response.failed"]) }).loose(),
3238
+ isRetryable: import_zod3.z.boolean(),
3239
+ message: import_zod3.z.string(),
3240
+ statusCode: import_zod3.z.number().int().min(400).max(599)
3241
+ });
3242
+ ResponsesLanguageModelStrategy = class {
3243
+ async doGenerate(config, settings, options) {
3244
+ let dispose;
3245
+ try {
3246
+ const prepared = await prepareModel(config, settings, options);
3247
+ dispose = prepared.dispose;
3248
+ const { input, model, providerName, warnings } = prepared;
3249
+ const result = convertResponsesResultToV3(await model.doGenerate(input));
3250
+ return {
3251
+ ...result,
3252
+ content: result.content.map((part) => fromOpenAIContent(part, providerName)),
3253
+ providerMetadata: responseMetadata(result.providerMetadata, providerName),
3254
+ warnings: [...warnings, ...result.warnings]
3255
+ };
3256
+ } catch (error) {
3257
+ const failure = convertError(error, config, options, "doGenerate");
3258
+ dispose?.(failure);
3259
+ throw failure;
3260
+ }
2070
3261
  }
2071
- resolveWarnings(settings, warnings) {
2072
- validateMaskingProvidersDeprecation(settings, warnings);
3262
+ async doStream(config, settings, options) {
3263
+ let dispose;
3264
+ try {
3265
+ const prepared = await prepareModel(config, settings, options);
3266
+ dispose = prepared.dispose;
3267
+ const { input, model, providerName, warnings } = prepared;
3268
+ const result = await model.doStream(input);
3269
+ const reader = result.stream.getReader();
3270
+ let cancelled = false;
3271
+ const isCancelled = () => cancelled;
3272
+ return {
3273
+ ...result,
3274
+ stream: new ReadableStream(
3275
+ {
3276
+ async cancel(reason) {
3277
+ cancelled = true;
3278
+ dispose?.(reason);
3279
+ try {
3280
+ await reader.cancel(reason);
3281
+ } finally {
3282
+ reader.releaseLock();
3283
+ }
3284
+ },
3285
+ async pull(controller) {
3286
+ try {
3287
+ if (options.abortSignal?.aborted)
3288
+ throw createAbortError(options.abortSignal.reason);
3289
+ const next = await reader.read();
3290
+ if (isCancelled()) return;
3291
+ if (options.abortSignal?.aborted)
3292
+ throw createAbortError(options.abortSignal.reason);
3293
+ if (next.done) {
3294
+ reader.releaseLock();
3295
+ controller.close();
3296
+ return;
3297
+ }
3298
+ const part = convertResponsesStreamPartToV3(next.value);
3299
+ if (part.type === "stream-start") {
3300
+ controller.enqueue({ ...part, warnings: [...warnings, ...part.warnings] });
3301
+ } else if (part.type === "finish") {
3302
+ controller.enqueue({
3303
+ ...part,
3304
+ providerMetadata: responseMetadata(part.providerMetadata, providerName)
3305
+ });
3306
+ } else if (part.type === "error") {
3307
+ controller.enqueue({
3308
+ ...part,
3309
+ error: convertError(part.error, config, options, "doStream")
3310
+ });
3311
+ } else if ("providerMetadata" in part || part.type === "text-end") {
3312
+ controller.enqueue(fromOpenAIContent(part, providerName));
3313
+ } else {
3314
+ controller.enqueue(part);
3315
+ }
3316
+ } catch (error) {
3317
+ if (isCancelled()) return;
3318
+ const failure = convertError(error, config, options, "doStream");
3319
+ dispose?.(failure);
3320
+ await reader.cancel(error).catch(() => void 0);
3321
+ if (isCancelled()) return;
3322
+ reader.releaseLock();
3323
+ controller.enqueue({
3324
+ error: failure,
3325
+ type: "error"
3326
+ });
3327
+ controller.close();
3328
+ }
3329
+ }
3330
+ },
3331
+ { highWaterMark: 0 }
3332
+ )
3333
+ };
3334
+ } catch (error) {
3335
+ const failure = convertError(error, config, options, "doStream");
3336
+ dispose?.(failure);
3337
+ throw failure;
3338
+ }
2073
3339
  }
2074
3340
  };
2075
3341
  }
2076
3342
  });
2077
3343
 
2078
3344
  // src/stream-transformer.ts
2079
- function createAbortError(reason) {
2080
- const error = new Error("The operation was aborted.", { cause: reason });
2081
- error.name = "AbortError";
2082
- return error;
2083
- }
2084
3345
  function createInitialStreamState() {
2085
3346
  return {
2086
3347
  activeText: false,
@@ -2109,13 +3370,15 @@ function createStreamTransformer(config) {
2109
3370
  cancel,
2110
3371
  convertToAISDKError: convertToAISDKError2,
2111
3372
  extractChunkMetadata,
3373
+ extractProviderSpecificFields,
3374
+ extractReasoningBlocks,
2112
3375
  idGenerator,
2113
3376
  includeRawChunks,
2114
3377
  modelId,
2115
3378
  options,
2116
3379
  providerName,
2117
3380
  requestId,
2118
- responseMetadata,
3381
+ responseMetadata: responseMetadata2,
2119
3382
  sdkStream,
2120
3383
  streamResponseGetCitations,
2121
3384
  streamResponseGetFinishReason,
@@ -2127,10 +3390,51 @@ function createStreamTransformer(config) {
2127
3390
  let textBlockId = null;
2128
3391
  const streamState = createInitialStreamState();
2129
3392
  const toolCallsInProgress = /* @__PURE__ */ new Map();
2130
- const resolvedResponseMetadata = { ...responseMetadata };
3393
+ const resolvedResponseMetadata = { ...responseMetadata2 };
2131
3394
  let resolvedRequestId = requestId;
2132
3395
  let tokenUsage;
2133
3396
  let citations;
3397
+ let providerSpecificFields;
3398
+ let providerFinishReason;
3399
+ let reasoningBlocks;
3400
+ function collectReasoningBlocks(incoming, controller) {
3401
+ if (incoming === void 0) return true;
3402
+ if (!Array.isArray(incoming)) {
3403
+ handleStreamError(
3404
+ new TypeError("Invalid Orchestration reasoning_content: expected an array."),
3405
+ controller,
3406
+ convertToAISDKError2,
3407
+ options,
3408
+ modelId,
3409
+ url
3410
+ );
3411
+ return false;
3412
+ }
3413
+ const blocks = incoming;
3414
+ if (blocks.length === 0) return true;
3415
+ reasoningBlocks ??= [];
3416
+ for (const [index, value] of blocks.entries()) {
3417
+ const parsed = orchestrationReasoningBlockSchema.safeParse(value);
3418
+ if (!parsed.success) {
3419
+ handleStreamError(parsed.error, controller, convertToAISDKError2, options, modelId, url);
3420
+ return false;
3421
+ }
3422
+ const block = parsed.data;
3423
+ let state = reasoningBlocks[index];
3424
+ if (state) {
3425
+ state.block.content = (state.block.content ?? "") + (block.content ?? "");
3426
+ if (block.signature) state.block.signature = block.signature;
3427
+ } else {
3428
+ state = { block, id: idGenerator.generateReasoningBlockId() };
3429
+ reasoningBlocks.push(state);
3430
+ controller.enqueue({ id: state.id, type: "reasoning-start" });
3431
+ }
3432
+ if (block.content) {
3433
+ controller.enqueue({ delta: block.content, id: state.id, type: "reasoning-delta" });
3434
+ }
3435
+ }
3436
+ return true;
3437
+ }
2134
3438
  function collectCitations(incoming) {
2135
3439
  if (!incoming?.length) return;
2136
3440
  citations ??= /* @__PURE__ */ new Map();
@@ -2207,6 +3511,13 @@ function createStreamTransformer(config) {
2207
3511
  );
2208
3512
  return;
2209
3513
  }
3514
+ for (const state of reasoningBlocks ?? []) {
3515
+ controller.enqueue({
3516
+ id: state.id,
3517
+ providerMetadata: buildOrchestrationReasoningMetadata(state.block, providerName),
3518
+ type: "reasoning-end"
3519
+ });
3520
+ }
2210
3521
  const didEmitAnyToolCalls = finalizeToolCalls(
2211
3522
  controller,
2212
3523
  toolCallsInProgress,
@@ -2218,13 +3529,16 @@ function createStreamTransformer(config) {
2218
3529
  }
2219
3530
  const finalFinishReason = streamResponseGetFinishReason();
2220
3531
  if (finalFinishReason) {
2221
- streamState.finishReason = mapFinishReason(finalFinishReason);
3532
+ streamState.finishReason = mapFinishReason(finalFinishReason, providerFinishReason);
2222
3533
  } else if (didEmitAnyToolCalls) {
2223
3534
  streamState.finishReason = {
2224
- raw: void 0,
3535
+ raw: providerFinishReason,
2225
3536
  unified: "tool-calls"
2226
3537
  };
2227
3538
  }
3539
+ if (providerFinishReason !== void 0) {
3540
+ streamState.finishReason = { ...streamState.finishReason, raw: providerFinishReason };
3541
+ }
2228
3542
  streamState.usage = mapTokenUsage(tokenUsage);
2229
3543
  collectCitations(streamResponseGetCitations?.());
2230
3544
  if (citations) {
@@ -2246,6 +3560,7 @@ function createStreamTransformer(config) {
2246
3560
  ...buildAnthropicCacheMetadata(tokenUsage),
2247
3561
  finishReason: streamState.finishReason.raw ?? "unknown",
2248
3562
  finishReasonMapped: streamState.finishReason,
3563
+ ...providerSpecificFields && { providerSpecificFields },
2249
3564
  ...streamIntermediateFailures?.length ? {
2250
3565
  intermediateFailures: sanitizeAsJSONArray(streamIntermediateFailures)
2251
3566
  } : {},
@@ -2285,6 +3600,14 @@ function createStreamTransformer(config) {
2285
3600
  Object.assign(resolvedResponseMetadata, incomingMetadata);
2286
3601
  collectUsage(chunk.getTokenUsage?.());
2287
3602
  collectCitations(chunk.getCitations?.());
3603
+ const incomingProviderFields = parseProviderSpecificFields(
3604
+ extractProviderSpecificFields?.(chunk)
3605
+ );
3606
+ if (incomingProviderFields) {
3607
+ providerSpecificFields = { ...providerSpecificFields, ...incomingProviderFields };
3608
+ providerFinishReason = getProviderFinishReason(incomingProviderFields) ?? providerFinishReason;
3609
+ }
3610
+ if (!collectReasoningBlocks(extractReasoningBlocks?.(chunk), controller)) return;
2288
3611
  if (streamState.isFirstChunk || metadataChanged) {
2289
3612
  streamState.isFirstChunk = false;
2290
3613
  controller.enqueue({
@@ -2314,7 +3637,7 @@ function createStreamTransformer(config) {
2314
3637
  }
2315
3638
  const chunkFinishReason = chunk.getFinishReason();
2316
3639
  if (chunkFinishReason) {
2317
- streamState.finishReason = mapFinishReason(chunkFinishReason);
3640
+ streamState.finishReason = mapFinishReason(chunkFinishReason, providerFinishReason);
2318
3641
  if (streamState.finishReason.unified === "tool-calls") {
2319
3642
  finalizeToolCalls(controller, toolCallsInProgress, idGenerator, emitToolInputStart);
2320
3643
  if (streamState.activeText && textBlockId) {
@@ -2437,8 +3760,16 @@ var StreamIdGenerator;
2437
3760
  var init_stream_transformer = __esm({
2438
3761
  "src/stream-transformer.ts"() {
2439
3762
  "use strict";
3763
+ init_abort_utils();
3764
+ init_sap_ai_provider_options();
2440
3765
  init_strategy_utils();
2441
3766
  StreamIdGenerator = class {
3767
+ /**
3768
+ * @returns A UUID string for identifying a native reasoning block.
3769
+ */
3770
+ generateReasoningBlockId() {
3771
+ return crypto.randomUUID();
3772
+ }
2442
3773
  /**
2443
3774
  * @returns A UUID string for identifying the response.
2444
3775
  */
@@ -2466,6 +3797,7 @@ var BaseLanguageModelStrategy;
2466
3797
  var init_base_language_model_strategy = __esm({
2467
3798
  "src/base-language-model-strategy.ts"() {
2468
3799
  "use strict";
3800
+ init_abort_utils();
2469
3801
  init_convert_to_sap_messages();
2470
3802
  init_sap_ai_error();
2471
3803
  init_sap_ai_provider_options();
@@ -2497,15 +3829,19 @@ var init_base_language_model_strategy = __esm({
2497
3829
  ];
2498
3830
  async doGenerate(config, settings, options) {
2499
3831
  try {
2500
- if (options.abortSignal?.aborted) throw createAbortError(options.abortSignal.reason);
3832
+ throwIfAborted(options.abortSignal);
2501
3833
  const commonParts = this.buildCommonParts(config, settings, options);
2502
3834
  const { request, warnings } = this.buildRequest(config, settings, options, commonParts);
2503
3835
  const client = this.createClient(config, settings, commonParts);
2504
- const response = await this.executeApiCall(
2505
- client,
2506
- request,
2507
- mergeRequestConfig(config.requestConfig, options.abortSignal, options.headers)
3836
+ const response = await waitWithAbort(
3837
+ this.executeApiCall(
3838
+ client,
3839
+ request,
3840
+ mergeRequestConfig(config.requestConfig, options.abortSignal, options.headers)
3841
+ ),
3842
+ options.abortSignal
2508
3843
  );
3844
+ throwIfAborted(options.abortSignal);
2509
3845
  return buildGenerateResult({
2510
3846
  providerName: commonParts.providerName,
2511
3847
  requestBody: request,
@@ -2527,7 +3863,7 @@ var init_base_language_model_strategy = __esm({
2527
3863
  }
2528
3864
  async doStream(config, settings, options) {
2529
3865
  try {
2530
- if (options.abortSignal?.aborted) throw createAbortError(options.abortSignal.reason);
3866
+ throwIfAborted(options.abortSignal);
2531
3867
  const commonParts = this.buildCommonParts(config, settings, options);
2532
3868
  const { request, warnings } = this.buildRequest(config, settings, options, commonParts);
2533
3869
  const client = this.createClient(config, settings, commonParts);
@@ -2539,12 +3875,21 @@ var init_base_language_model_strategy = __esm({
2539
3875
  mergeRequestConfig(config.requestConfig, void 0, options.headers),
2540
3876
  commonParts
2541
3877
  );
3878
+ if (options.abortSignal?.aborted) {
3879
+ try {
3880
+ streamResponse.cancel();
3881
+ } finally {
3882
+ throwIfAborted(options.abortSignal);
3883
+ }
3884
+ }
2542
3885
  const idGenerator = new StreamIdGenerator();
2543
3886
  const streamWarnings = this.collectStreamWarnings(settings, commonParts.sapOptions);
2544
3887
  const transformedStream = createStreamTransformer({
2545
3888
  cancel: streamResponse.cancel,
2546
3889
  convertToAISDKError,
2547
3890
  extractChunkMetadata: (chunk) => this.extractMetadata(chunk),
3891
+ extractProviderSpecificFields: streamResponse.extractProviderSpecificFields,
3892
+ extractReasoningBlocks: streamResponse.extractReasoningBlocks,
2548
3893
  idGenerator,
2549
3894
  includeRawChunks: options.includeRawChunks ?? false,
2550
3895
  modelId: config.modelId,
@@ -2604,6 +3949,7 @@ var init_base_language_model_strategy = __esm({
2604
3949
  const messages = convertToSAPMessages(options.prompt, {
2605
3950
  escapeTemplatePlaceholders: this.getEscapeTemplatePlaceholders(sapOptions, settings),
2606
3951
  includeReasoning: this.getIncludeReasoning(sapOptions, settings),
3952
+ nativeReasoningProviderName: this.getNativeReasoningProviderName(providerName),
2607
3953
  parsePartProviderOptions: this.getPartProviderOptionsParser(),
2608
3954
  warnings
2609
3955
  });
@@ -2643,12 +3989,12 @@ var init_base_language_model_strategy = __esm({
2643
3989
  * @internal
2644
3990
  */
2645
3991
  extractMetadata(response) {
2646
- const responseMetadata = extractCompletionMetadata(
3992
+ const responseMetadata2 = extractCompletionMetadata(
2647
3993
  response,
2648
3994
  this.getCompletionDataPath()
2649
3995
  );
2650
3996
  const { headers, requestId } = extractResponseMetadata(response, "rawResponse");
2651
- return { requestId, responseHeaders: headers, responseMetadata };
3997
+ return { requestId, responseHeaders: headers, responseMetadata: responseMetadata2 };
2652
3998
  }
2653
3999
  /**
2654
4000
  * Returns whether to escape template placeholders for this API.
@@ -2668,7 +4014,16 @@ var init_base_language_model_strategy = __esm({
2668
4014
  * @internal
2669
4015
  */
2670
4016
  getIncludeReasoning(sapOptions, settings) {
2671
- return sapOptions?.includeReasoning ?? settings.includeReasoning ?? false;
4017
+ return sapOptions?.includeReasoning ?? ("includeReasoning" in settings ? settings.includeReasoning : false) ?? false;
4018
+ }
4019
+ /**
4020
+ * Enables native reasoning history only for strategies supporting the Orchestration wire format.
4021
+ * @param _providerName - Configured provider namespace.
4022
+ * @returns The native reasoning namespace, or undefined for legacy text-only history.
4023
+ * @internal
4024
+ */
4025
+ getNativeReasoningProviderName(_providerName) {
4026
+ return void 0;
2672
4027
  }
2673
4028
  /**
2674
4029
  * Returns a parser for per-message-part `providerOptions['sap-ai']`.
@@ -2711,6 +4066,7 @@ var init_foundation_models_language_model_strategy = __esm({
2711
4066
  "src/foundation-models-language-model-strategy.ts"() {
2712
4067
  "use strict";
2713
4068
  init_base_language_model_strategy();
4069
+ init_sap_http_stream();
2714
4070
  init_strategy_utils();
2715
4071
  FOUNDATION_MODELS_PARAM_MAPPINGS = [
2716
4072
  ...BaseLanguageModelStrategy.COMMON_PARAM_MAPPINGS,
@@ -2756,7 +4112,7 @@ var init_foundation_models_language_model_strategy = __esm({
2756
4112
  }
2757
4113
  async executeApiCall(client, request, requestConfig) {
2758
4114
  const response = await client.run(request, requestConfig);
2759
- const { requestId, responseMetadata } = this.extractMetadata(response);
4115
+ const { requestId, responseMetadata: responseMetadata2 } = this.extractMetadata(response);
2760
4116
  return {
2761
4117
  getContent: () => response.getContent(),
2762
4118
  getFinishReason: () => response.getFinishReason(),
@@ -2765,21 +4121,28 @@ var init_foundation_models_language_model_strategy = __esm({
2765
4121
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- SAP SDK types headers as any
2766
4122
  rawResponse: { headers: response.rawResponse.headers },
2767
4123
  requestId,
2768
- responseMetadata
4124
+ responseMetadata: responseMetadata2
2769
4125
  };
2770
4126
  }
2771
4127
  async executeStreamCall(client, request, abortSignal, _settings, requestConfig, _commonParts) {
2772
- const streamResponse = await client.stream(request, abortSignal, requestConfig);
2773
- const { requestId, responseHeaders, responseMetadata } = this.extractMetadata(streamResponse);
4128
+ const streamResponse = await executeSapStream(
4129
+ (streamRequestConfig) => client.stream(request, abortSignal, streamRequestConfig),
4130
+ abortSignal,
4131
+ requestConfig
4132
+ );
4133
+ const { requestId, responseHeaders, responseMetadata: responseMetadata2 } = this.extractMetadata(streamResponse);
2774
4134
  return {
2775
4135
  cancel: () => {
2776
- streamResponse.stream.controller.abort();
4136
+ disposeSapStream(streamResponse);
2777
4137
  },
2778
4138
  getFinishReason: () => streamResponse.getFinishReason(),
2779
4139
  requestId,
2780
4140
  responseHeaders,
2781
- responseMetadata,
2782
- stream: streamResponse.stream
4141
+ responseMetadata: responseMetadata2,
4142
+ stream: withSapStreamCleanup(
4143
+ streamResponse,
4144
+ streamResponse.stream
4145
+ )
2783
4146
  };
2784
4147
  }
2785
4148
  getCompletionDataPath() {
@@ -2840,10 +4203,12 @@ var init_orchestration_language_model_strategy = __esm({
2840
4203
  init_deep_merge();
2841
4204
  init_sap_ai_provider_options();
2842
4205
  init_sap_ai_validation();
4206
+ init_sap_http_stream();
2843
4207
  init_strategy_utils();
2844
4208
  ORCHESTRATION_MODULE_KEYS = ["masking", "filtering", "grounding", "translation"];
2845
4209
  CONFIG_REF_IGNORED_MODULES = [
2846
4210
  ...ORCHESTRATION_MODULE_KEYS,
4211
+ "dropUnsupportedParams",
2847
4212
  "fallbackModuleConfigs",
2848
4213
  "promptTemplateRef",
2849
4214
  "responseFormat",
@@ -2851,7 +4216,11 @@ var init_orchestration_language_model_strategy = __esm({
2851
4216
  "modelParams",
2852
4217
  "modelVersion"
2853
4218
  ];
2854
- CONFIG_REF_IGNORED_PROVIDER_OPTIONS = ["promptTemplateRef", "modelParams"];
4219
+ CONFIG_REF_IGNORED_PROVIDER_OPTIONS = [
4220
+ "dropUnsupportedParams",
4221
+ "promptTemplateRef",
4222
+ "modelParams"
4223
+ ];
2855
4224
  ORCHESTRATION_PARAM_MAPPINGS = [
2856
4225
  ...BaseLanguageModelStrategy.COMMON_PARAM_MAPPINGS,
2857
4226
  { camelCaseKey: "topK", optionKey: "topK", outputKey: "top_k" }
@@ -2900,11 +4269,12 @@ var init_orchestration_language_model_strategy = __esm({
2900
4269
  return warnings;
2901
4270
  }
2902
4271
  createClient(config, settings, commonParts) {
2903
- const { configRef, promptTemplateRef, responseFormat, tools } = commonParts.resolvedState;
4272
+ const { configRef, dropUnsupportedParams, promptTemplateRef, responseFormat, tools } = commonParts.resolvedState;
2904
4273
  if (configRef) {
2905
4274
  return new this.ClientClass(configRef, config.deploymentConfig, config.destination);
2906
4275
  }
2907
4276
  const clientConfig = this.buildOrchestrationModuleConfig(config, settings, {
4277
+ dropUnsupportedParams,
2908
4278
  modelParams: commonParts.modelParams,
2909
4279
  promptTemplateRef,
2910
4280
  responseFormat,
@@ -2922,41 +4292,47 @@ var init_orchestration_language_model_strategy = __esm({
2922
4292
  }
2923
4293
  async executeApiCall(client, request, requestConfig) {
2924
4294
  const response = await client.chatCompletion(request, requestConfig);
2925
- const { requestId, responseMetadata } = this.extractMetadata(response);
4295
+ const { requestId, responseMetadata: responseMetadata2 } = this.extractMetadata(response);
2926
4296
  return {
2927
4297
  getCitations: () => response.getCitations(),
2928
4298
  getContent: () => response.getContent(),
2929
4299
  getFinishReason: () => response.getFinishReason(),
2930
4300
  getIntermediateFailures: () => response.getIntermediateFailures(),
4301
+ getProviderSpecificFields: () => response.findChoiceByIndex(0)?.provider_specific_fields,
4302
+ getReasoningBlocks: () => response.getAssistantMessage()?.reasoning_content,
2931
4303
  getTokenUsage: () => response.getTokenUsage(),
2932
4304
  getToolCalls: () => response.getToolCalls(),
2933
4305
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- SAP SDK types headers as any
2934
4306
  rawResponse: { headers: response.rawResponse.headers },
2935
4307
  requestId,
2936
- responseMetadata
4308
+ responseMetadata: responseMetadata2
2937
4309
  };
2938
4310
  }
2939
4311
  async executeStreamCall(client, request, abortSignal, settings, requestConfig, commonParts) {
2940
4312
  const { configRef } = commonParts.resolvedState;
2941
4313
  const sdkStreamOptions = configRef ? void 0 : this.buildSdkStreamOptions(settings.streamOptions);
2942
- const streamResponse = await client.stream(
2943
- request,
4314
+ const streamResponse = await executeSapStream(
4315
+ (streamRequestConfig) => client.stream(request, abortSignal, sdkStreamOptions, streamRequestConfig),
2944
4316
  abortSignal,
2945
- sdkStreamOptions,
2946
4317
  requestConfig
2947
4318
  );
2948
- const { requestId, responseHeaders, responseMetadata } = this.extractMetadata(streamResponse);
4319
+ const { requestId, responseHeaders, responseMetadata: responseMetadata2 } = this.extractMetadata(streamResponse);
2949
4320
  return {
2950
4321
  cancel: () => {
2951
- streamResponse.stream.controller.abort();
4322
+ disposeSapStream(streamResponse);
2952
4323
  },
4324
+ extractProviderSpecificFields: (chunk) => chunk.findChoiceByIndex(0)?.provider_specific_fields,
4325
+ extractReasoningBlocks: (chunk) => chunk.findChoiceByIndex(0)?.delta.reasoning_content,
2953
4326
  getCitations: () => streamResponse.getCitations(),
2954
4327
  getFinishReason: () => streamResponse.getFinishReason(),
2955
4328
  getIntermediateFailures: () => streamResponse.getIntermediateFailures(),
2956
4329
  requestId,
2957
4330
  responseHeaders,
2958
- responseMetadata,
2959
- stream: streamResponse.stream
4331
+ responseMetadata: responseMetadata2,
4332
+ stream: withSapStreamCleanup(
4333
+ streamResponse,
4334
+ streamResponse.stream
4335
+ )
2960
4336
  };
2961
4337
  }
2962
4338
  getCompletionDataPath() {
@@ -2965,6 +4341,9 @@ var init_orchestration_language_model_strategy = __esm({
2965
4341
  getEscapeTemplatePlaceholders(sapOptions, settings) {
2966
4342
  return sapOptions?.escapeTemplatePlaceholders ?? settings.escapeTemplatePlaceholders ?? true;
2967
4343
  }
4344
+ getNativeReasoningProviderName(providerName) {
4345
+ return providerName;
4346
+ }
2968
4347
  getParamMappings() {
2969
4348
  return ORCHESTRATION_PARAM_MAPPINGS;
2970
4349
  }
@@ -2998,7 +4377,8 @@ var init_orchestration_language_model_strategy = __esm({
2998
4377
  if (converted.warning) warnings.push(converted.warning);
2999
4378
  }
3000
4379
  const tools = this.resolveTools(settings, options, warnings);
3001
- return { configRef, promptTemplateRef, responseFormat, tools };
4380
+ const dropUnsupportedParams = sapOptions?.dropUnsupportedParams ?? settings.dropUnsupportedParams;
4381
+ return { configRef, dropUnsupportedParams, promptTemplateRef, responseFormat, tools };
3002
4382
  }
3003
4383
  /**
3004
4384
  * Builds request for orchestrationConfigRef mode.
@@ -3043,6 +4423,7 @@ var init_orchestration_language_model_strategy = __esm({
3043
4423
  * @param config - Strategy configuration.
3044
4424
  * @param settings - Model settings.
3045
4425
  * @param params - Build parameters.
4426
+ * @param params.dropUnsupportedParams - Optional unsupported-parameter policy for the primary model.
3046
4427
  * @param params.modelParams - LLM model parameters.
3047
4428
  * @param params.promptTemplateRef - Optional prompt template reference.
3048
4429
  * @param params.responseFormat - Optional response format specification.
@@ -3052,7 +4433,14 @@ var init_orchestration_language_model_strategy = __esm({
3052
4433
  * @internal
3053
4434
  */
3054
4435
  buildOrchestrationModuleConfig(config, settings, params) {
3055
- const { modelParams, promptTemplateRef, responseFormat, toolChoice, tools } = params;
4436
+ const {
4437
+ dropUnsupportedParams,
4438
+ modelParams,
4439
+ promptTemplateRef,
4440
+ responseFormat,
4441
+ toolChoice,
4442
+ tools
4443
+ } = params;
3056
4444
  const promptConfig = promptTemplateRef ? this.buildTemplateRefPromptConfig(promptTemplateRef, tools, responseFormat) : this.buildInlineTemplateConfig(tools, responseFormat);
3057
4445
  const effectiveModelParams = toolChoice ? { ...modelParams, tool_choice: toolChoice } : modelParams;
3058
4446
  const moduleConfig = {
@@ -3060,7 +4448,8 @@ var init_orchestration_language_model_strategy = __esm({
3060
4448
  model: {
3061
4449
  name: config.modelId,
3062
4450
  params: effectiveModelParams,
3063
- ...settings.modelVersion ? { version: settings.modelVersion } : {}
4451
+ ...settings.modelVersion ? { version: settings.modelVersion } : {},
4452
+ ...dropUnsupportedParams !== void 0 ? { drop_unsupported_params: dropUnsupportedParams } : {}
3064
4453
  },
3065
4454
  prompt: promptConfig
3066
4455
  }
@@ -3149,7 +4538,7 @@ var init_orchestration_language_model_strategy = __esm({
3149
4538
  }
3150
4539
  }
3151
4540
  for (const key of CONFIG_REF_IGNORED_PROVIDER_OPTIONS) {
3152
- if (sapOptions?.[key] && !settings[key]) {
4541
+ if (sapOptions?.[key] !== void 0 && settings[key] === void 0) {
3153
4542
  ignoredSettings.push(`providerOptions.${key}`);
3154
4543
  }
3155
4544
  }
@@ -3290,6 +4679,52 @@ __export(index_v2_exports, {
3290
4679
  module.exports = __toCommonJS(index_v2_exports);
3291
4680
  init_convert_to_sap_messages();
3292
4681
 
4682
+ // src/sap-ai-adapters-v3-to-v2.ts
4683
+ var import_provider2 = require("@ai-sdk/provider");
4684
+
4685
+ // src/map-readable-stream.ts
4686
+ function mapReadableStream(source, convert) {
4687
+ const reader = source.getReader();
4688
+ let cancelled = false;
4689
+ return new ReadableStream(
4690
+ {
4691
+ async cancel(reason) {
4692
+ cancelled = true;
4693
+ try {
4694
+ await reader.cancel(reason);
4695
+ } finally {
4696
+ reader.releaseLock();
4697
+ }
4698
+ },
4699
+ async pull(controller) {
4700
+ try {
4701
+ for (; ; ) {
4702
+ const next = await reader.read();
4703
+ if (cancelled) return;
4704
+ if (next.done) {
4705
+ reader.releaseLock();
4706
+ controller.close();
4707
+ return;
4708
+ }
4709
+ const converted = convert(next.value);
4710
+ if (converted !== null) {
4711
+ controller.enqueue(converted);
4712
+ return;
4713
+ }
4714
+ }
4715
+ } catch (error) {
4716
+ if (cancelled) return;
4717
+ await reader.cancel(error).catch(() => void 0);
4718
+ if (cancelled) return;
4719
+ reader.releaseLock();
4720
+ controller.error(error);
4721
+ }
4722
+ }
4723
+ },
4724
+ { highWaterMark: 0 }
4725
+ );
4726
+ }
4727
+
3293
4728
  // src/sap-ai-adapters-v3-to-v2.ts
3294
4729
  function convertStreamPartToV2(internalPart) {
3295
4730
  const compatiblePart = internalPart;
@@ -3307,7 +4742,7 @@ function convertStreamPartToV2(internalPart) {
3307
4742
  case "stream-start":
3308
4743
  return { ...compatiblePart, warnings: convertWarningsToV2(compatiblePart.warnings) };
3309
4744
  case "tool-approval-request":
3310
- return null;
4745
+ throw createV2ToolApprovalError();
3311
4746
  case "tool-call": {
3312
4747
  const { dynamic: _dynamic, ...part } = compatiblePart;
3313
4748
  return part;
@@ -3345,19 +4780,17 @@ function convertWarningToV2(internalWarning) {
3345
4780
  };
3346
4781
  }
3347
4782
  function createV2StreamFromInternal(internalStream) {
3348
- return internalStream.pipeThrough(
3349
- new TransformStream({
3350
- transform(chunk, controller) {
3351
- const converted = convertStreamPartToV2(chunk);
3352
- if (converted !== null) controller.enqueue(converted);
3353
- }
3354
- })
3355
- );
4783
+ return mapReadableStream(internalStream, convertStreamPartToV2);
4784
+ }
4785
+ function createV2ToolApprovalError() {
4786
+ return new import_provider2.UnsupportedFunctionalityError({
4787
+ functionality: "Tool approvals are unavailable through the V2 provider. Use /v3 with AI SDK 6 or /v4 with AI SDK 7."
4788
+ });
3356
4789
  }
3357
4790
 
3358
4791
  // src/sap-ai-embedding-model.ts
3359
- var import_provider_utils2 = require("@ai-sdk/provider-utils");
3360
- var import_zod3 = require("zod");
4792
+ var import_provider_utils3 = require("@ai-sdk/provider-utils");
4793
+ var import_zod4 = require("zod");
3361
4794
  init_sap_ai_provider_options();
3362
4795
 
3363
4796
  // src/sap-ai-strategy.ts
@@ -3388,6 +4821,10 @@ function getOrCreateLanguageModelStrategy(api) {
3388
4821
  return strategyPromise;
3389
4822
  }
3390
4823
  async function createEmbeddingModelStrategy(api) {
4824
+ if (api === "responses") {
4825
+ const { UnsupportedFeatureError: UnsupportedFeatureError2 } = await Promise.resolve().then(() => (init_sap_ai_error(), sap_ai_error_exports));
4826
+ throw new UnsupportedFeatureError2("Embeddings", "responses", "foundation-models");
4827
+ }
3391
4828
  if (api === "foundation-models") {
3392
4829
  const { AzureOpenAiEmbeddingClient } = await import("@sap-ai-sdk/foundation-models");
3393
4830
  const { FoundationModelsEmbeddingModelStrategy: FoundationModelsEmbeddingModelStrategy2 } = await Promise.resolve().then(() => (init_foundation_models_embedding_model_strategy(), foundation_models_embedding_model_strategy_exports));
@@ -3398,6 +4835,10 @@ async function createEmbeddingModelStrategy(api) {
3398
4835
  return new OrchestrationEmbeddingModelStrategy2(OrchestrationEmbeddingClient2);
3399
4836
  }
3400
4837
  async function createLanguageModelStrategy(api) {
4838
+ if (api === "responses") {
4839
+ const { ResponsesLanguageModelStrategy: ResponsesLanguageModelStrategy2 } = await Promise.resolve().then(() => (init_responses_language_model_strategy(), responses_language_model_strategy_exports));
4840
+ return new ResponsesLanguageModelStrategy2();
4841
+ }
3401
4842
  if (api === "foundation-models") {
3402
4843
  const { AzureOpenAiChatClient } = await import("@sap-ai-sdk/foundation-models");
3403
4844
  const { FoundationModelsLanguageModelStrategy: FoundationModelsLanguageModelStrategy2 } = await Promise.resolve().then(() => (init_foundation_models_language_model_strategy(), foundation_models_language_model_strategy_exports));
@@ -3411,7 +4852,7 @@ async function createLanguageModelStrategy(api) {
3411
4852
  // src/sap-ai-embedding-model.ts
3412
4853
  init_sap_ai_validation();
3413
4854
  var DEFAULT_MAX_EMBEDDINGS_PER_CALL = 2048;
3414
- var maxEmbeddingsPerCallSchema = import_zod3.z.number().int().positive().or(import_zod3.z.literal(Infinity));
4855
+ var maxEmbeddingsPerCallSchema = import_zod4.z.number().int().positive().or(import_zod4.z.literal(Infinity));
3415
4856
  var SAPAIEmbeddingModel = class {
3416
4857
  maxEmbeddingsPerCall;
3417
4858
  modelId;
@@ -3440,7 +4881,7 @@ var SAPAIEmbeddingModel = class {
3440
4881
  }
3441
4882
  async doEmbed(options) {
3442
4883
  const providerName = getProviderName(this.config.provider);
3443
- const sapOptions = await (0, import_provider_utils2.parseProviderOptions)({
4884
+ const sapOptions = await (0, import_provider_utils3.parseProviderOptions)({
3444
4885
  provider: providerName,
3445
4886
  providerOptions: options.providerOptions,
3446
4887
  schema: sapAIEmbeddingProviderOptions
@@ -3461,7 +4902,12 @@ var SAPAIEmbeddingModel = class {
3461
4902
  provider: this.config.provider,
3462
4903
  requestConfig: this.config.requestConfig
3463
4904
  };
3464
- return strategy.doEmbed(strategyConfig, this.settings, options, this.maxEmbeddingsPerCall);
4905
+ return strategy.doEmbed(
4906
+ strategyConfig,
4907
+ this.settings,
4908
+ options,
4909
+ this.maxEmbeddingsPerCall
4910
+ );
3465
4911
  }
3466
4912
  };
3467
4913
 
@@ -3516,8 +4962,57 @@ var SAPAIEmbeddingModelV2 = class {
3516
4962
  // src/index-v2.ts
3517
4963
  init_sap_ai_error();
3518
4964
 
4965
+ // src/sap-ai-adapters-v2-to-v3.ts
4966
+ var import_provider_utils4 = require("@ai-sdk/provider-utils");
4967
+ function normalizeV2PromptToV3(prompt) {
4968
+ return prompt.map((message) => {
4969
+ switch (message.role) {
4970
+ case "assistant":
4971
+ return {
4972
+ ...message,
4973
+ content: message.content.map(
4974
+ (part) => part.type === "tool-result" ? normalizeToolResultPart(part) : part
4975
+ )
4976
+ };
4977
+ case "tool":
4978
+ return {
4979
+ ...message,
4980
+ content: message.content.map(
4981
+ (part) => part.type === "tool-result" ? normalizeToolResultPart(part) : part
4982
+ )
4983
+ };
4984
+ default:
4985
+ return message;
4986
+ }
4987
+ });
4988
+ }
4989
+ function normalizeToolOutput(output) {
4990
+ if (output.type !== "content") return output;
4991
+ return {
4992
+ ...output,
4993
+ value: output.value.map((item) => {
4994
+ if (item.type !== "media") return item;
4995
+ const mediaType = (0, import_provider_utils4.resolveFullMediaType)({
4996
+ part: {
4997
+ data: { data: item.data, type: "data" },
4998
+ mediaType: item.mediaType.toLowerCase(),
4999
+ type: "file"
5000
+ }
5001
+ });
5002
+ return {
5003
+ ...item,
5004
+ mediaType,
5005
+ type: mediaType.startsWith("image/") ? "image-data" : "file-data"
5006
+ };
5007
+ })
5008
+ };
5009
+ }
5010
+ function normalizeToolResultPart(part) {
5011
+ return { ...part, output: normalizeToolOutput(part.output) };
5012
+ }
5013
+
3519
5014
  // src/sap-ai-language-model.ts
3520
- var import_provider_utils3 = require("@ai-sdk/provider-utils");
5015
+ var import_provider_utils5 = require("@ai-sdk/provider-utils");
3521
5016
  init_sap_ai_provider_options();
3522
5017
  init_sap_ai_validation();
3523
5018
  var SAPAILanguageModel = class {
@@ -3551,11 +5046,13 @@ var SAPAILanguageModel = class {
3551
5046
  }
3552
5047
  async doGenerate(options) {
3553
5048
  const { strategy, strategyConfig } = await this.prepareInvocation(options);
3554
- return strategy.doGenerate(strategyConfig, this.settings, options);
5049
+ const result = strategy.doGenerate(strategyConfig, this.settings, options);
5050
+ return result;
3555
5051
  }
3556
5052
  async doStream(options) {
3557
5053
  const { strategy, strategyConfig } = await this.prepareInvocation(options);
3558
- return strategy.doStream(strategyConfig, this.settings, options);
5054
+ const result = strategy.doStream(strategyConfig, this.settings, options);
5055
+ return result;
3559
5056
  }
3560
5057
  supportsUrl(url) {
3561
5058
  if (url.protocol === "https:") return true;
@@ -3572,7 +5069,7 @@ var SAPAILanguageModel = class {
3572
5069
  */
3573
5070
  async prepareInvocation(options) {
3574
5071
  const providerName = getProviderName(this.config.provider);
3575
- const sapOptions = await (0, import_provider_utils3.parseProviderOptions)({
5072
+ const sapOptions = await (0, import_provider_utils5.parseProviderOptions)({
3576
5073
  provider: providerName,
3577
5074
  providerOptions: options.providerOptions,
3578
5075
  schema: sapAILanguageModelProviderOptions
@@ -3582,10 +5079,12 @@ var SAPAILanguageModel = class {
3582
5079
  api: effectiveApi,
3583
5080
  invocationSettings: sapOptions ? {
3584
5081
  api: sapOptions.api,
5082
+ dropUnsupportedParams: sapOptions.dropUnsupportedParams,
3585
5083
  escapeTemplatePlaceholders: sapOptions.escapeTemplatePlaceholders,
3586
5084
  orchestrationConfigRef: sapOptions.orchestrationConfigRef,
3587
5085
  placeholderValues: sapOptions.placeholderValues,
3588
- promptTemplateRef: sapOptions.promptTemplateRef
5086
+ promptTemplateRef: sapOptions.promptTemplateRef,
5087
+ responses: sapOptions.responses
3589
5088
  } : void 0,
3590
5089
  modelApi: this.settings.api,
3591
5090
  modelSettings: this.settings
@@ -3626,7 +5125,10 @@ var SAPAILanguageModelV2 = class {
3626
5125
  this.internalModel = new SAPAILanguageModel(modelId, settings, config);
3627
5126
  }
3628
5127
  async doGenerate(options) {
3629
- const result = await this.internalModel.doGenerate(options);
5128
+ const result = await this.internalModel.doGenerate(normalizeCallOptions(options));
5129
+ if (result.content.some((part) => part.type === "tool-approval-request")) {
5130
+ throw createV2ToolApprovalError();
5131
+ }
3630
5132
  return {
3631
5133
  content: result.content,
3632
5134
  finishReason: result.finishReason.unified,
@@ -3638,7 +5140,7 @@ var SAPAILanguageModelV2 = class {
3638
5140
  };
3639
5141
  }
3640
5142
  async doStream(options) {
3641
- const result = await this.internalModel.doStream(options);
5143
+ const result = await this.internalModel.doStream(normalizeCallOptions(options));
3642
5144
  return {
3643
5145
  request: result.request,
3644
5146
  response: result.response ? {
@@ -3648,13 +5150,22 @@ var SAPAILanguageModelV2 = class {
3648
5150
  };
3649
5151
  }
3650
5152
  };
5153
+ function normalizeCallOptions(options) {
5154
+ const normalized = {
5155
+ ...options,
5156
+ prompt: normalizeV2PromptToV3(options.prompt),
5157
+ // Legacy provider-defined tools keep their unsupported warning/skip behavior.
5158
+ tools: options.tools
5159
+ };
5160
+ return normalized;
5161
+ }
3651
5162
 
3652
5163
  // src/index-v2.ts
3653
5164
  init_sap_ai_provider_options();
3654
5165
 
3655
5166
  // src/sap-ai-provider-v2.ts
3656
- var import_provider4 = require("@ai-sdk/provider");
3657
- var import_util2 = require("@sap-cloud-sdk/util");
5167
+ var import_provider10 = require("@ai-sdk/provider");
5168
+ var import_util3 = require("@sap-cloud-sdk/util");
3658
5169
  init_sap_ai_provider_options();
3659
5170
  init_sap_ai_validation();
3660
5171
  function createSAPAIProvider(options = {}) {
@@ -3671,7 +5182,7 @@ function createSAPAIProvider(options = {}) {
3671
5182
  }
3672
5183
  if (typeof process === "undefined" || !process.env.SAP_CLOUD_SDK_LOG_LEVEL) {
3673
5184
  const logLevel = options.logLevel ?? "warn";
3674
- (0, import_util2.setGlobalLogLevel)(logLevel);
5185
+ (0, import_util3.setGlobalLogLevel)(logLevel);
3675
5186
  }
3676
5187
  const deploymentConfig = options.deploymentId ? { deploymentId: options.deploymentId } : { resourceGroup };
3677
5188
  const providerApi = options.api ?? "orchestration";
@@ -3713,7 +5224,7 @@ function createSAPAIProvider(options = {}) {
3713
5224
  provider.languageModel = createModel;
3714
5225
  provider.textEmbeddingModel = createEmbeddingModel;
3715
5226
  provider.imageModel = (modelId) => {
3716
- throw new import_provider4.NoSuchModelError({
5227
+ throw new import_provider10.NoSuchModelError({
3717
5228
  message: `SAP AI Core does not support image generation. Model '${modelId}' is not available.`,
3718
5229
  modelId,
3719
5230
  modelType: "imageModel"