@jerome-benoit/sap-ai-provider-v2 5.0.2 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +44 -24
- package/dist/chunk-4ILJD6PI.js +333 -0
- package/dist/chunk-4ILJD6PI.js.map +1 -0
- package/dist/chunk-BHA5MIN6.js +224 -0
- package/dist/chunk-BHA5MIN6.js.map +1 -0
- package/dist/{chunk-LEME2MFD.js → chunk-DLGBK3C3.js} +91 -7
- package/dist/chunk-DLGBK3C3.js.map +1 -0
- package/dist/{chunk-NLMWIVG7.js → chunk-EUBI5ENK.js} +54 -27
- package/dist/chunk-EUBI5ENK.js.map +1 -0
- package/dist/{chunk-YP3AADWD.js → chunk-FKHOJ3ZC.js} +24 -3
- package/dist/chunk-FKHOJ3ZC.js.map +1 -0
- package/dist/{chunk-77JSAAPE.js → chunk-QFMHNGLB.js} +56 -218
- package/dist/chunk-QFMHNGLB.js.map +1 -0
- package/dist/{chunk-U6WJSLR7.js → chunk-QQQYMQPU.js} +19 -10
- package/dist/chunk-QQQYMQPU.js.map +1 -0
- package/dist/{chunk-QZOZ3PZT.js → chunk-ZOBD7PXJ.js} +118 -22
- package/dist/chunk-ZOBD7PXJ.js.map +1 -0
- package/dist/{foundation-models-embedding-model-strategy-A3WDDAYK.js → foundation-models-embedding-model-strategy-3WAKJXBY.js} +5 -4
- package/dist/{foundation-models-embedding-model-strategy-A3WDDAYK.js.map → foundation-models-embedding-model-strategy-3WAKJXBY.js.map} +1 -1
- package/dist/{foundation-models-language-model-strategy-6U6KK6KH.js → foundation-models-language-model-strategy-PJ26VXEA.js} +22 -9
- package/dist/foundation-models-language-model-strategy-PJ26VXEA.js.map +1 -0
- package/dist/index.cjs +1903 -384
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +798 -185
- package/dist/index.d.ts +798 -185
- package/dist/index.js +148 -24
- package/dist/index.js.map +1 -1
- package/dist/{orchestration-embedding-model-strategy-JO3QH5MR.js → orchestration-embedding-model-strategy-AZ76XLMD.js} +6 -5
- package/dist/{orchestration-embedding-model-strategy-JO3QH5MR.js.map → orchestration-embedding-model-strategy-AZ76XLMD.js.map} +1 -1
- package/dist/{orchestration-language-model-strategy-MBVA7BYX.js → orchestration-language-model-strategy-CT6RHCYO.js} +57 -19
- package/dist/orchestration-language-model-strategy-CT6RHCYO.js.map +1 -0
- package/dist/responses-language-model-strategy-UYTV6TPM.js +738 -0
- package/dist/responses-language-model-strategy-UYTV6TPM.js.map +1 -0
- package/dist/sap-ai-error-UPKYWPSS.js +16 -0
- package/dist/sap-ai-error-UPKYWPSS.js.map +1 -0
- package/package.json +79 -39
- package/dist/chunk-77JSAAPE.js.map +0 -1
- package/dist/chunk-LEME2MFD.js.map +0 -1
- package/dist/chunk-NLMWIVG7.js.map +0 -1
- package/dist/chunk-QZOZ3PZT.js.map +0 -1
- package/dist/chunk-U6WJSLR7.js.map +0 -1
- package/dist/chunk-YP3AADWD.js.map +0 -1
- package/dist/foundation-models-language-model-strategy-6U6KK6KH.js.map +0 -1
- package/dist/orchestration-language-model-strategy-MBVA7BYX.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
|
-
|
|
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,211 +606,15 @@ 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
|
-
});
|
|
432
|
-
}
|
|
433
|
-
}
|
|
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;
|
|
442
|
-
}
|
|
443
|
-
const parsed = sapAIPartProviderOptionsSchema.safeParse(block);
|
|
444
|
-
if (parsed.success) {
|
|
445
|
-
return parsed.data;
|
|
446
|
-
}
|
|
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
|
-
}
|
|
455
|
-
}
|
|
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
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
|
+
});
|
|
616
618
|
function convertSAPErrorToAPICallError(errorResponse, context) {
|
|
617
619
|
const { code, location, message, requestId } = extractErrorFields(errorResponse);
|
|
618
620
|
const statusCode = getStatusCodeFromSAPError(code, context?.httpStatusCode);
|
|
@@ -631,7 +633,7 @@ function convertSAPErrorToAPICallError(errorResponse, context) {
|
|
|
631
633
|
enhancedMessage += `
|
|
632
634
|
Request ID: ${requestId}`;
|
|
633
635
|
}
|
|
634
|
-
return new
|
|
636
|
+
return new import_provider3.LoadAPIKeyError({
|
|
635
637
|
message: enhancedMessage
|
|
636
638
|
});
|
|
637
639
|
}
|
|
@@ -642,7 +644,7 @@ Request ID: ${requestId}`;
|
|
|
642
644
|
Request ID: ${requestId}`;
|
|
643
645
|
}
|
|
644
646
|
const modelId = context?.modelId ?? extractModelIdentifier(message, location);
|
|
645
|
-
return new
|
|
647
|
+
return new import_provider3.NoSuchModelError({
|
|
646
648
|
message: enhancedMessage,
|
|
647
649
|
modelId: modelId ?? "unknown",
|
|
648
650
|
modelType: context?.modelType ?? "languageModel"
|
|
@@ -661,7 +663,7 @@ Error location: ${location}`;
|
|
|
661
663
|
enhancedMessage += `
|
|
662
664
|
Request ID: ${requestId}`;
|
|
663
665
|
}
|
|
664
|
-
return new
|
|
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 (
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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 (
|
|
730
|
+
if (syntaxError) {
|
|
721
731
|
return createAPICallError(
|
|
722
732
|
error,
|
|
723
733
|
{
|
|
724
734
|
isRetryable: false,
|
|
725
|
-
message: error instanceof Error && error !==
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
1164
|
-
|
|
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,6 +1220,98 @@ The model's response was blocked by content safety filters. Try a different prom
|
|
|
1175
1220
|
}
|
|
1176
1221
|
});
|
|
1177
1222
|
|
|
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;
|
|
1228
|
+
}
|
|
1229
|
+
function throwIfAborted(signal) {
|
|
1230
|
+
if (signal?.aborted) throw createAbortError(signal.reason);
|
|
1231
|
+
}
|
|
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
|
+
|
|
1178
1315
|
// src/strategy-utils.ts
|
|
1179
1316
|
function applyParameterOverrides(modelParams, options, sapModelParams, settingsModelParams, mappings) {
|
|
1180
1317
|
for (const mapping of mappings) {
|
|
@@ -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
|
|
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:
|
|
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
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
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
|
|
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
|
|
1998
|
+
if (api !== "orchestration" && escapeTemplatePlaceholders === true) {
|
|
1829
1999
|
throw new UnsupportedFeatureError(
|
|
1830
2000
|
ESCAPE_TEMPLATE_PLACEHOLDERS_DESCRIPTION,
|
|
1831
|
-
|
|
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
|
-
|
|
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 (
|
|
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 (
|
|
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,27 +2114,44 @@ function validateSettings(options) {
|
|
|
1945
2114
|
);
|
|
1946
2115
|
}
|
|
1947
2116
|
}
|
|
1948
|
-
if (api === "
|
|
1949
|
-
|
|
1950
|
-
|
|
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
|
-
|
|
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"
|
|
1968
|
-
);
|
|
2154
|
+
throw new UnsupportedFeatureError(ORCHESTRATION_ONLY_FEATURES[feature], api, "orchestration");
|
|
1969
2155
|
}
|
|
1970
2156
|
}
|
|
1971
2157
|
}
|
|
@@ -1975,7 +2161,9 @@ var init_sap_ai_validation = __esm({
|
|
|
1975
2161
|
"use strict";
|
|
1976
2162
|
init_deep_merge();
|
|
1977
2163
|
init_sap_ai_error();
|
|
2164
|
+
init_sap_ai_provider_options();
|
|
1978
2165
|
ORCHESTRATION_ONLY_FEATURE_KEYS = [
|
|
2166
|
+
"dropUnsupportedParams",
|
|
1979
2167
|
"fallbackModuleConfigs",
|
|
1980
2168
|
"filtering",
|
|
1981
2169
|
"grounding",
|
|
@@ -1988,6 +2176,7 @@ var init_sap_ai_validation = __esm({
|
|
|
1988
2176
|
"translation"
|
|
1989
2177
|
];
|
|
1990
2178
|
ORCHESTRATION_ONLY_FEATURES = {
|
|
2179
|
+
dropUnsupportedParams: "Unsupported parameter handling (dropUnsupportedParams)",
|
|
1991
2180
|
fallbackModuleConfigs: "Fallback module configurations (fallbackModuleConfigs)",
|
|
1992
2181
|
filtering: "Content filtering",
|
|
1993
2182
|
grounding: "Document grounding",
|
|
@@ -2004,6 +2193,7 @@ var init_sap_ai_validation = __esm({
|
|
|
2004
2193
|
dataSources: "Azure On Your Data (dataSources)"
|
|
2005
2194
|
};
|
|
2006
2195
|
ORCHESTRATION_ONLY_INVOCATION_FEATURE_KEYS = [
|
|
2196
|
+
"dropUnsupportedParams",
|
|
2007
2197
|
"orchestrationConfigRef",
|
|
2008
2198
|
"placeholderValues",
|
|
2009
2199
|
"promptTemplateRef"
|
|
@@ -2012,75 +2202,1146 @@ var init_sap_ai_validation = __esm({
|
|
|
2012
2202
|
ORCHESTRATION_ONLY_EMBEDDING_FEATURES = {
|
|
2013
2203
|
masking: ORCHESTRATION_ONLY_FEATURES.masking
|
|
2014
2204
|
};
|
|
2015
|
-
ESCAPE_TEMPLATE_PLACEHOLDERS_DESCRIPTION = "escapeTemplatePlaceholders (Jinja2 template escaping)";
|
|
2016
|
-
VALID_API_TYPES = [
|
|
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)
|
|
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
|
+
}
|
|
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();
|
|
2567
|
+
}
|
|
2568
|
+
}
|
|
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"() {
|
|
3008
|
+
"use strict";
|
|
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();
|
|
3014
|
+
init_sap_ai_error();
|
|
3015
|
+
init_sap_http_stream();
|
|
3016
|
+
init_strategy_utils();
|
|
2017
3017
|
}
|
|
2018
3018
|
});
|
|
2019
3019
|
|
|
2020
|
-
// src/
|
|
2021
|
-
var
|
|
2022
|
-
__export(
|
|
2023
|
-
|
|
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
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2033
|
-
|
|
2034
|
-
|
|
2035
|
-
|
|
2036
|
-
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
|
|
2044
|
-
|
|
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
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
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
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
|
|
2066
|
-
|
|
2067
|
-
|
|
2068
|
-
|
|
2069
|
-
|
|
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
|
-
|
|
2072
|
-
|
|
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 = { ...
|
|
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:
|
|
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
|
-
|
|
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
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
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
|
-
|
|
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);
|
|
@@ -2536,14 +3872,24 @@ var init_base_language_model_strategy = __esm({
|
|
|
2536
3872
|
request,
|
|
2537
3873
|
options.abortSignal ?? void 0,
|
|
2538
3874
|
settings,
|
|
2539
|
-
mergeRequestConfig(config.requestConfig, void 0, options.headers)
|
|
3875
|
+
mergeRequestConfig(config.requestConfig, void 0, options.headers),
|
|
3876
|
+
commonParts
|
|
2540
3877
|
);
|
|
3878
|
+
if (options.abortSignal?.aborted) {
|
|
3879
|
+
try {
|
|
3880
|
+
streamResponse.cancel();
|
|
3881
|
+
} finally {
|
|
3882
|
+
throwIfAborted(options.abortSignal);
|
|
3883
|
+
}
|
|
3884
|
+
}
|
|
2541
3885
|
const idGenerator = new StreamIdGenerator();
|
|
2542
3886
|
const streamWarnings = this.collectStreamWarnings(settings, commonParts.sapOptions);
|
|
2543
3887
|
const transformedStream = createStreamTransformer({
|
|
2544
3888
|
cancel: streamResponse.cancel,
|
|
2545
3889
|
convertToAISDKError,
|
|
2546
3890
|
extractChunkMetadata: (chunk) => this.extractMetadata(chunk),
|
|
3891
|
+
extractProviderSpecificFields: streamResponse.extractProviderSpecificFields,
|
|
3892
|
+
extractReasoningBlocks: streamResponse.extractReasoningBlocks,
|
|
2547
3893
|
idGenerator,
|
|
2548
3894
|
includeRawChunks: options.includeRawChunks ?? false,
|
|
2549
3895
|
modelId: config.modelId,
|
|
@@ -2603,6 +3949,7 @@ var init_base_language_model_strategy = __esm({
|
|
|
2603
3949
|
const messages = convertToSAPMessages(options.prompt, {
|
|
2604
3950
|
escapeTemplatePlaceholders: this.getEscapeTemplatePlaceholders(sapOptions, settings),
|
|
2605
3951
|
includeReasoning: this.getIncludeReasoning(sapOptions, settings),
|
|
3952
|
+
nativeReasoningProviderName: this.getNativeReasoningProviderName(providerName),
|
|
2606
3953
|
parsePartProviderOptions: this.getPartProviderOptionsParser(),
|
|
2607
3954
|
warnings
|
|
2608
3955
|
});
|
|
@@ -2642,12 +3989,12 @@ var init_base_language_model_strategy = __esm({
|
|
|
2642
3989
|
* @internal
|
|
2643
3990
|
*/
|
|
2644
3991
|
extractMetadata(response) {
|
|
2645
|
-
const
|
|
3992
|
+
const responseMetadata2 = extractCompletionMetadata(
|
|
2646
3993
|
response,
|
|
2647
3994
|
this.getCompletionDataPath()
|
|
2648
3995
|
);
|
|
2649
3996
|
const { headers, requestId } = extractResponseMetadata(response, "rawResponse");
|
|
2650
|
-
return { requestId, responseHeaders: headers, responseMetadata };
|
|
3997
|
+
return { requestId, responseHeaders: headers, responseMetadata: responseMetadata2 };
|
|
2651
3998
|
}
|
|
2652
3999
|
/**
|
|
2653
4000
|
* Returns whether to escape template placeholders for this API.
|
|
@@ -2667,7 +4014,16 @@ var init_base_language_model_strategy = __esm({
|
|
|
2667
4014
|
* @internal
|
|
2668
4015
|
*/
|
|
2669
4016
|
getIncludeReasoning(sapOptions, settings) {
|
|
2670
|
-
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;
|
|
2671
4027
|
}
|
|
2672
4028
|
/**
|
|
2673
4029
|
* Returns a parser for per-message-part `providerOptions['sap-ai']`.
|
|
@@ -2710,6 +4066,7 @@ var init_foundation_models_language_model_strategy = __esm({
|
|
|
2710
4066
|
"src/foundation-models-language-model-strategy.ts"() {
|
|
2711
4067
|
"use strict";
|
|
2712
4068
|
init_base_language_model_strategy();
|
|
4069
|
+
init_sap_http_stream();
|
|
2713
4070
|
init_strategy_utils();
|
|
2714
4071
|
FOUNDATION_MODELS_PARAM_MAPPINGS = [
|
|
2715
4072
|
...BaseLanguageModelStrategy.COMMON_PARAM_MAPPINGS,
|
|
@@ -2755,7 +4112,7 @@ var init_foundation_models_language_model_strategy = __esm({
|
|
|
2755
4112
|
}
|
|
2756
4113
|
async executeApiCall(client, request, requestConfig) {
|
|
2757
4114
|
const response = await client.run(request, requestConfig);
|
|
2758
|
-
const { requestId, responseMetadata } = this.extractMetadata(response);
|
|
4115
|
+
const { requestId, responseMetadata: responseMetadata2 } = this.extractMetadata(response);
|
|
2759
4116
|
return {
|
|
2760
4117
|
getContent: () => response.getContent(),
|
|
2761
4118
|
getFinishReason: () => response.getFinishReason(),
|
|
@@ -2764,21 +4121,28 @@ var init_foundation_models_language_model_strategy = __esm({
|
|
|
2764
4121
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- SAP SDK types headers as any
|
|
2765
4122
|
rawResponse: { headers: response.rawResponse.headers },
|
|
2766
4123
|
requestId,
|
|
2767
|
-
responseMetadata
|
|
4124
|
+
responseMetadata: responseMetadata2
|
|
2768
4125
|
};
|
|
2769
4126
|
}
|
|
2770
|
-
async executeStreamCall(client, request, abortSignal, _settings, requestConfig) {
|
|
2771
|
-
const streamResponse = await
|
|
2772
|
-
|
|
4127
|
+
async executeStreamCall(client, request, abortSignal, _settings, requestConfig, _commonParts) {
|
|
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);
|
|
2773
4134
|
return {
|
|
2774
4135
|
cancel: () => {
|
|
2775
|
-
streamResponse
|
|
4136
|
+
disposeSapStream(streamResponse);
|
|
2776
4137
|
},
|
|
2777
4138
|
getFinishReason: () => streamResponse.getFinishReason(),
|
|
2778
4139
|
requestId,
|
|
2779
4140
|
responseHeaders,
|
|
2780
|
-
responseMetadata,
|
|
2781
|
-
stream:
|
|
4141
|
+
responseMetadata: responseMetadata2,
|
|
4142
|
+
stream: withSapStreamCleanup(
|
|
4143
|
+
streamResponse,
|
|
4144
|
+
streamResponse.stream
|
|
4145
|
+
)
|
|
2782
4146
|
};
|
|
2783
4147
|
}
|
|
2784
4148
|
getCompletionDataPath() {
|
|
@@ -2839,10 +4203,12 @@ var init_orchestration_language_model_strategy = __esm({
|
|
|
2839
4203
|
init_deep_merge();
|
|
2840
4204
|
init_sap_ai_provider_options();
|
|
2841
4205
|
init_sap_ai_validation();
|
|
4206
|
+
init_sap_http_stream();
|
|
2842
4207
|
init_strategy_utils();
|
|
2843
4208
|
ORCHESTRATION_MODULE_KEYS = ["masking", "filtering", "grounding", "translation"];
|
|
2844
4209
|
CONFIG_REF_IGNORED_MODULES = [
|
|
2845
4210
|
...ORCHESTRATION_MODULE_KEYS,
|
|
4211
|
+
"dropUnsupportedParams",
|
|
2846
4212
|
"fallbackModuleConfigs",
|
|
2847
4213
|
"promptTemplateRef",
|
|
2848
4214
|
"responseFormat",
|
|
@@ -2850,7 +4216,11 @@ var init_orchestration_language_model_strategy = __esm({
|
|
|
2850
4216
|
"modelParams",
|
|
2851
4217
|
"modelVersion"
|
|
2852
4218
|
];
|
|
2853
|
-
CONFIG_REF_IGNORED_PROVIDER_OPTIONS = [
|
|
4219
|
+
CONFIG_REF_IGNORED_PROVIDER_OPTIONS = [
|
|
4220
|
+
"dropUnsupportedParams",
|
|
4221
|
+
"promptTemplateRef",
|
|
4222
|
+
"modelParams"
|
|
4223
|
+
];
|
|
2854
4224
|
ORCHESTRATION_PARAM_MAPPINGS = [
|
|
2855
4225
|
...BaseLanguageModelStrategy.COMMON_PARAM_MAPPINGS,
|
|
2856
4226
|
{ camelCaseKey: "topK", optionKey: "topK", outputKey: "top_k" }
|
|
@@ -2880,6 +4250,12 @@ var init_orchestration_language_model_strategy = __esm({
|
|
|
2880
4250
|
const warnings = [];
|
|
2881
4251
|
const configRefCandidate = sapOptions?.orchestrationConfigRef ?? settings.orchestrationConfigRef;
|
|
2882
4252
|
if (configRefCandidate && isOrchestrationConfigRef(configRefCandidate)) {
|
|
4253
|
+
if (settings.streamOptions && hasKeys(settings.streamOptions)) {
|
|
4254
|
+
warnings.push({
|
|
4255
|
+
message: "orchestrationConfigRef is set; local streamOptions are ignored. Configure streaming in the referenced configuration or its overrideConfig.",
|
|
4256
|
+
type: "other"
|
|
4257
|
+
});
|
|
4258
|
+
}
|
|
2883
4259
|
return warnings;
|
|
2884
4260
|
}
|
|
2885
4261
|
if (settings.translation && hasKeys(settings.translation)) {
|
|
@@ -2893,11 +4269,12 @@ var init_orchestration_language_model_strategy = __esm({
|
|
|
2893
4269
|
return warnings;
|
|
2894
4270
|
}
|
|
2895
4271
|
createClient(config, settings, commonParts) {
|
|
2896
|
-
const { configRef, promptTemplateRef, responseFormat, tools } = commonParts.resolvedState;
|
|
4272
|
+
const { configRef, dropUnsupportedParams, promptTemplateRef, responseFormat, tools } = commonParts.resolvedState;
|
|
2897
4273
|
if (configRef) {
|
|
2898
4274
|
return new this.ClientClass(configRef, config.deploymentConfig, config.destination);
|
|
2899
4275
|
}
|
|
2900
4276
|
const clientConfig = this.buildOrchestrationModuleConfig(config, settings, {
|
|
4277
|
+
dropUnsupportedParams,
|
|
2901
4278
|
modelParams: commonParts.modelParams,
|
|
2902
4279
|
promptTemplateRef,
|
|
2903
4280
|
responseFormat,
|
|
@@ -2915,40 +4292,47 @@ var init_orchestration_language_model_strategy = __esm({
|
|
|
2915
4292
|
}
|
|
2916
4293
|
async executeApiCall(client, request, requestConfig) {
|
|
2917
4294
|
const response = await client.chatCompletion(request, requestConfig);
|
|
2918
|
-
const { requestId, responseMetadata } = this.extractMetadata(response);
|
|
4295
|
+
const { requestId, responseMetadata: responseMetadata2 } = this.extractMetadata(response);
|
|
2919
4296
|
return {
|
|
2920
4297
|
getCitations: () => response.getCitations(),
|
|
2921
4298
|
getContent: () => response.getContent(),
|
|
2922
4299
|
getFinishReason: () => response.getFinishReason(),
|
|
2923
4300
|
getIntermediateFailures: () => response.getIntermediateFailures(),
|
|
4301
|
+
getProviderSpecificFields: () => response.findChoiceByIndex(0)?.provider_specific_fields,
|
|
4302
|
+
getReasoningBlocks: () => response.getAssistantMessage()?.reasoning_content,
|
|
2924
4303
|
getTokenUsage: () => response.getTokenUsage(),
|
|
2925
4304
|
getToolCalls: () => response.getToolCalls(),
|
|
2926
4305
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- SAP SDK types headers as any
|
|
2927
4306
|
rawResponse: { headers: response.rawResponse.headers },
|
|
2928
4307
|
requestId,
|
|
2929
|
-
responseMetadata
|
|
4308
|
+
responseMetadata: responseMetadata2
|
|
2930
4309
|
};
|
|
2931
4310
|
}
|
|
2932
|
-
async executeStreamCall(client, request, abortSignal, settings, requestConfig) {
|
|
2933
|
-
const
|
|
2934
|
-
const
|
|
2935
|
-
|
|
4311
|
+
async executeStreamCall(client, request, abortSignal, settings, requestConfig, commonParts) {
|
|
4312
|
+
const { configRef } = commonParts.resolvedState;
|
|
4313
|
+
const sdkStreamOptions = configRef ? void 0 : this.buildSdkStreamOptions(settings.streamOptions);
|
|
4314
|
+
const streamResponse = await executeSapStream(
|
|
4315
|
+
(streamRequestConfig) => client.stream(request, abortSignal, sdkStreamOptions, streamRequestConfig),
|
|
2936
4316
|
abortSignal,
|
|
2937
|
-
sdkStreamOptions,
|
|
2938
4317
|
requestConfig
|
|
2939
4318
|
);
|
|
2940
|
-
const { requestId, responseHeaders, responseMetadata } = this.extractMetadata(streamResponse);
|
|
4319
|
+
const { requestId, responseHeaders, responseMetadata: responseMetadata2 } = this.extractMetadata(streamResponse);
|
|
2941
4320
|
return {
|
|
2942
4321
|
cancel: () => {
|
|
2943
|
-
streamResponse
|
|
4322
|
+
disposeSapStream(streamResponse);
|
|
2944
4323
|
},
|
|
4324
|
+
extractProviderSpecificFields: (chunk) => chunk.findChoiceByIndex(0)?.provider_specific_fields,
|
|
4325
|
+
extractReasoningBlocks: (chunk) => chunk.findChoiceByIndex(0)?.delta.reasoning_content,
|
|
2945
4326
|
getCitations: () => streamResponse.getCitations(),
|
|
2946
4327
|
getFinishReason: () => streamResponse.getFinishReason(),
|
|
2947
4328
|
getIntermediateFailures: () => streamResponse.getIntermediateFailures(),
|
|
2948
4329
|
requestId,
|
|
2949
4330
|
responseHeaders,
|
|
2950
|
-
responseMetadata,
|
|
2951
|
-
stream:
|
|
4331
|
+
responseMetadata: responseMetadata2,
|
|
4332
|
+
stream: withSapStreamCleanup(
|
|
4333
|
+
streamResponse,
|
|
4334
|
+
streamResponse.stream
|
|
4335
|
+
)
|
|
2952
4336
|
};
|
|
2953
4337
|
}
|
|
2954
4338
|
getCompletionDataPath() {
|
|
@@ -2957,6 +4341,9 @@ var init_orchestration_language_model_strategy = __esm({
|
|
|
2957
4341
|
getEscapeTemplatePlaceholders(sapOptions, settings) {
|
|
2958
4342
|
return sapOptions?.escapeTemplatePlaceholders ?? settings.escapeTemplatePlaceholders ?? true;
|
|
2959
4343
|
}
|
|
4344
|
+
getNativeReasoningProviderName(providerName) {
|
|
4345
|
+
return providerName;
|
|
4346
|
+
}
|
|
2960
4347
|
getParamMappings() {
|
|
2961
4348
|
return ORCHESTRATION_PARAM_MAPPINGS;
|
|
2962
4349
|
}
|
|
@@ -2990,7 +4377,8 @@ var init_orchestration_language_model_strategy = __esm({
|
|
|
2990
4377
|
if (converted.warning) warnings.push(converted.warning);
|
|
2991
4378
|
}
|
|
2992
4379
|
const tools = this.resolveTools(settings, options, warnings);
|
|
2993
|
-
|
|
4380
|
+
const dropUnsupportedParams = sapOptions?.dropUnsupportedParams ?? settings.dropUnsupportedParams;
|
|
4381
|
+
return { configRef, dropUnsupportedParams, promptTemplateRef, responseFormat, tools };
|
|
2994
4382
|
}
|
|
2995
4383
|
/**
|
|
2996
4384
|
* Builds request for orchestrationConfigRef mode.
|
|
@@ -3035,6 +4423,7 @@ var init_orchestration_language_model_strategy = __esm({
|
|
|
3035
4423
|
* @param config - Strategy configuration.
|
|
3036
4424
|
* @param settings - Model settings.
|
|
3037
4425
|
* @param params - Build parameters.
|
|
4426
|
+
* @param params.dropUnsupportedParams - Optional unsupported-parameter policy for the primary model.
|
|
3038
4427
|
* @param params.modelParams - LLM model parameters.
|
|
3039
4428
|
* @param params.promptTemplateRef - Optional prompt template reference.
|
|
3040
4429
|
* @param params.responseFormat - Optional response format specification.
|
|
@@ -3044,7 +4433,14 @@ var init_orchestration_language_model_strategy = __esm({
|
|
|
3044
4433
|
* @internal
|
|
3045
4434
|
*/
|
|
3046
4435
|
buildOrchestrationModuleConfig(config, settings, params) {
|
|
3047
|
-
const {
|
|
4436
|
+
const {
|
|
4437
|
+
dropUnsupportedParams,
|
|
4438
|
+
modelParams,
|
|
4439
|
+
promptTemplateRef,
|
|
4440
|
+
responseFormat,
|
|
4441
|
+
toolChoice,
|
|
4442
|
+
tools
|
|
4443
|
+
} = params;
|
|
3048
4444
|
const promptConfig = promptTemplateRef ? this.buildTemplateRefPromptConfig(promptTemplateRef, tools, responseFormat) : this.buildInlineTemplateConfig(tools, responseFormat);
|
|
3049
4445
|
const effectiveModelParams = toolChoice ? { ...modelParams, tool_choice: toolChoice } : modelParams;
|
|
3050
4446
|
const moduleConfig = {
|
|
@@ -3052,7 +4448,8 @@ var init_orchestration_language_model_strategy = __esm({
|
|
|
3052
4448
|
model: {
|
|
3053
4449
|
name: config.modelId,
|
|
3054
4450
|
params: effectiveModelParams,
|
|
3055
|
-
...settings.modelVersion ? { version: settings.modelVersion } : {}
|
|
4451
|
+
...settings.modelVersion ? { version: settings.modelVersion } : {},
|
|
4452
|
+
...dropUnsupportedParams !== void 0 ? { drop_unsupported_params: dropUnsupportedParams } : {}
|
|
3056
4453
|
},
|
|
3057
4454
|
prompt: promptConfig
|
|
3058
4455
|
}
|
|
@@ -3141,7 +4538,7 @@ var init_orchestration_language_model_strategy = __esm({
|
|
|
3141
4538
|
}
|
|
3142
4539
|
}
|
|
3143
4540
|
for (const key of CONFIG_REF_IGNORED_PROVIDER_OPTIONS) {
|
|
3144
|
-
if (sapOptions?.[key] &&
|
|
4541
|
+
if (sapOptions?.[key] !== void 0 && settings[key] === void 0) {
|
|
3145
4542
|
ignoredSettings.push(`providerOptions.${key}`);
|
|
3146
4543
|
}
|
|
3147
4544
|
}
|
|
@@ -3282,6 +4679,52 @@ __export(index_v2_exports, {
|
|
|
3282
4679
|
module.exports = __toCommonJS(index_v2_exports);
|
|
3283
4680
|
init_convert_to_sap_messages();
|
|
3284
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
|
+
|
|
3285
4728
|
// src/sap-ai-adapters-v3-to-v2.ts
|
|
3286
4729
|
function convertStreamPartToV2(internalPart) {
|
|
3287
4730
|
const compatiblePart = internalPart;
|
|
@@ -3299,7 +4742,7 @@ function convertStreamPartToV2(internalPart) {
|
|
|
3299
4742
|
case "stream-start":
|
|
3300
4743
|
return { ...compatiblePart, warnings: convertWarningsToV2(compatiblePart.warnings) };
|
|
3301
4744
|
case "tool-approval-request":
|
|
3302
|
-
|
|
4745
|
+
throw createV2ToolApprovalError();
|
|
3303
4746
|
case "tool-call": {
|
|
3304
4747
|
const { dynamic: _dynamic, ...part } = compatiblePart;
|
|
3305
4748
|
return part;
|
|
@@ -3337,19 +4780,17 @@ function convertWarningToV2(internalWarning) {
|
|
|
3337
4780
|
};
|
|
3338
4781
|
}
|
|
3339
4782
|
function createV2StreamFromInternal(internalStream) {
|
|
3340
|
-
return internalStream
|
|
3341
|
-
|
|
3342
|
-
|
|
3343
|
-
|
|
3344
|
-
|
|
3345
|
-
|
|
3346
|
-
})
|
|
3347
|
-
);
|
|
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
|
+
});
|
|
3348
4789
|
}
|
|
3349
4790
|
|
|
3350
4791
|
// src/sap-ai-embedding-model.ts
|
|
3351
|
-
var
|
|
3352
|
-
var
|
|
4792
|
+
var import_provider_utils3 = require("@ai-sdk/provider-utils");
|
|
4793
|
+
var import_zod4 = require("zod");
|
|
3353
4794
|
init_sap_ai_provider_options();
|
|
3354
4795
|
|
|
3355
4796
|
// src/sap-ai-strategy.ts
|
|
@@ -3380,6 +4821,10 @@ function getOrCreateLanguageModelStrategy(api) {
|
|
|
3380
4821
|
return strategyPromise;
|
|
3381
4822
|
}
|
|
3382
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
|
+
}
|
|
3383
4828
|
if (api === "foundation-models") {
|
|
3384
4829
|
const { AzureOpenAiEmbeddingClient } = await import("@sap-ai-sdk/foundation-models");
|
|
3385
4830
|
const { FoundationModelsEmbeddingModelStrategy: FoundationModelsEmbeddingModelStrategy2 } = await Promise.resolve().then(() => (init_foundation_models_embedding_model_strategy(), foundation_models_embedding_model_strategy_exports));
|
|
@@ -3390,6 +4835,10 @@ async function createEmbeddingModelStrategy(api) {
|
|
|
3390
4835
|
return new OrchestrationEmbeddingModelStrategy2(OrchestrationEmbeddingClient2);
|
|
3391
4836
|
}
|
|
3392
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
|
+
}
|
|
3393
4842
|
if (api === "foundation-models") {
|
|
3394
4843
|
const { AzureOpenAiChatClient } = await import("@sap-ai-sdk/foundation-models");
|
|
3395
4844
|
const { FoundationModelsLanguageModelStrategy: FoundationModelsLanguageModelStrategy2 } = await Promise.resolve().then(() => (init_foundation_models_language_model_strategy(), foundation_models_language_model_strategy_exports));
|
|
@@ -3403,7 +4852,7 @@ async function createLanguageModelStrategy(api) {
|
|
|
3403
4852
|
// src/sap-ai-embedding-model.ts
|
|
3404
4853
|
init_sap_ai_validation();
|
|
3405
4854
|
var DEFAULT_MAX_EMBEDDINGS_PER_CALL = 2048;
|
|
3406
|
-
var maxEmbeddingsPerCallSchema =
|
|
4855
|
+
var maxEmbeddingsPerCallSchema = import_zod4.z.number().int().positive().or(import_zod4.z.literal(Infinity));
|
|
3407
4856
|
var SAPAIEmbeddingModel = class {
|
|
3408
4857
|
maxEmbeddingsPerCall;
|
|
3409
4858
|
modelId;
|
|
@@ -3432,7 +4881,7 @@ var SAPAIEmbeddingModel = class {
|
|
|
3432
4881
|
}
|
|
3433
4882
|
async doEmbed(options) {
|
|
3434
4883
|
const providerName = getProviderName(this.config.provider);
|
|
3435
|
-
const sapOptions = await (0,
|
|
4884
|
+
const sapOptions = await (0, import_provider_utils3.parseProviderOptions)({
|
|
3436
4885
|
provider: providerName,
|
|
3437
4886
|
providerOptions: options.providerOptions,
|
|
3438
4887
|
schema: sapAIEmbeddingProviderOptions
|
|
@@ -3453,7 +4902,12 @@ var SAPAIEmbeddingModel = class {
|
|
|
3453
4902
|
provider: this.config.provider,
|
|
3454
4903
|
requestConfig: this.config.requestConfig
|
|
3455
4904
|
};
|
|
3456
|
-
return strategy.doEmbed(
|
|
4905
|
+
return strategy.doEmbed(
|
|
4906
|
+
strategyConfig,
|
|
4907
|
+
this.settings,
|
|
4908
|
+
options,
|
|
4909
|
+
this.maxEmbeddingsPerCall
|
|
4910
|
+
);
|
|
3457
4911
|
}
|
|
3458
4912
|
};
|
|
3459
4913
|
|
|
@@ -3508,8 +4962,57 @@ var SAPAIEmbeddingModelV2 = class {
|
|
|
3508
4962
|
// src/index-v2.ts
|
|
3509
4963
|
init_sap_ai_error();
|
|
3510
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
|
+
|
|
3511
5014
|
// src/sap-ai-language-model.ts
|
|
3512
|
-
var
|
|
5015
|
+
var import_provider_utils5 = require("@ai-sdk/provider-utils");
|
|
3513
5016
|
init_sap_ai_provider_options();
|
|
3514
5017
|
init_sap_ai_validation();
|
|
3515
5018
|
var SAPAILanguageModel = class {
|
|
@@ -3543,11 +5046,13 @@ var SAPAILanguageModel = class {
|
|
|
3543
5046
|
}
|
|
3544
5047
|
async doGenerate(options) {
|
|
3545
5048
|
const { strategy, strategyConfig } = await this.prepareInvocation(options);
|
|
3546
|
-
|
|
5049
|
+
const result = strategy.doGenerate(strategyConfig, this.settings, options);
|
|
5050
|
+
return result;
|
|
3547
5051
|
}
|
|
3548
5052
|
async doStream(options) {
|
|
3549
5053
|
const { strategy, strategyConfig } = await this.prepareInvocation(options);
|
|
3550
|
-
|
|
5054
|
+
const result = strategy.doStream(strategyConfig, this.settings, options);
|
|
5055
|
+
return result;
|
|
3551
5056
|
}
|
|
3552
5057
|
supportsUrl(url) {
|
|
3553
5058
|
if (url.protocol === "https:") return true;
|
|
@@ -3564,7 +5069,7 @@ var SAPAILanguageModel = class {
|
|
|
3564
5069
|
*/
|
|
3565
5070
|
async prepareInvocation(options) {
|
|
3566
5071
|
const providerName = getProviderName(this.config.provider);
|
|
3567
|
-
const sapOptions = await (0,
|
|
5072
|
+
const sapOptions = await (0, import_provider_utils5.parseProviderOptions)({
|
|
3568
5073
|
provider: providerName,
|
|
3569
5074
|
providerOptions: options.providerOptions,
|
|
3570
5075
|
schema: sapAILanguageModelProviderOptions
|
|
@@ -3574,10 +5079,12 @@ var SAPAILanguageModel = class {
|
|
|
3574
5079
|
api: effectiveApi,
|
|
3575
5080
|
invocationSettings: sapOptions ? {
|
|
3576
5081
|
api: sapOptions.api,
|
|
5082
|
+
dropUnsupportedParams: sapOptions.dropUnsupportedParams,
|
|
3577
5083
|
escapeTemplatePlaceholders: sapOptions.escapeTemplatePlaceholders,
|
|
3578
5084
|
orchestrationConfigRef: sapOptions.orchestrationConfigRef,
|
|
3579
5085
|
placeholderValues: sapOptions.placeholderValues,
|
|
3580
|
-
promptTemplateRef: sapOptions.promptTemplateRef
|
|
5086
|
+
promptTemplateRef: sapOptions.promptTemplateRef,
|
|
5087
|
+
responses: sapOptions.responses
|
|
3581
5088
|
} : void 0,
|
|
3582
5089
|
modelApi: this.settings.api,
|
|
3583
5090
|
modelSettings: this.settings
|
|
@@ -3618,7 +5125,10 @@ var SAPAILanguageModelV2 = class {
|
|
|
3618
5125
|
this.internalModel = new SAPAILanguageModel(modelId, settings, config);
|
|
3619
5126
|
}
|
|
3620
5127
|
async doGenerate(options) {
|
|
3621
|
-
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
|
+
}
|
|
3622
5132
|
return {
|
|
3623
5133
|
content: result.content,
|
|
3624
5134
|
finishReason: result.finishReason.unified,
|
|
@@ -3630,7 +5140,7 @@ var SAPAILanguageModelV2 = class {
|
|
|
3630
5140
|
};
|
|
3631
5141
|
}
|
|
3632
5142
|
async doStream(options) {
|
|
3633
|
-
const result = await this.internalModel.doStream(options);
|
|
5143
|
+
const result = await this.internalModel.doStream(normalizeCallOptions(options));
|
|
3634
5144
|
return {
|
|
3635
5145
|
request: result.request,
|
|
3636
5146
|
response: result.response ? {
|
|
@@ -3640,13 +5150,22 @@ var SAPAILanguageModelV2 = class {
|
|
|
3640
5150
|
};
|
|
3641
5151
|
}
|
|
3642
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
|
+
}
|
|
3643
5162
|
|
|
3644
5163
|
// src/index-v2.ts
|
|
3645
5164
|
init_sap_ai_provider_options();
|
|
3646
5165
|
|
|
3647
5166
|
// src/sap-ai-provider-v2.ts
|
|
3648
|
-
var
|
|
3649
|
-
var
|
|
5167
|
+
var import_provider10 = require("@ai-sdk/provider");
|
|
5168
|
+
var import_util3 = require("@sap-cloud-sdk/util");
|
|
3650
5169
|
init_sap_ai_provider_options();
|
|
3651
5170
|
init_sap_ai_validation();
|
|
3652
5171
|
function createSAPAIProvider(options = {}) {
|
|
@@ -3663,7 +5182,7 @@ function createSAPAIProvider(options = {}) {
|
|
|
3663
5182
|
}
|
|
3664
5183
|
if (typeof process === "undefined" || !process.env.SAP_CLOUD_SDK_LOG_LEVEL) {
|
|
3665
5184
|
const logLevel = options.logLevel ?? "warn";
|
|
3666
|
-
(0,
|
|
5185
|
+
(0, import_util3.setGlobalLogLevel)(logLevel);
|
|
3667
5186
|
}
|
|
3668
5187
|
const deploymentConfig = options.deploymentId ? { deploymentId: options.deploymentId } : { resourceGroup };
|
|
3669
5188
|
const providerApi = options.api ?? "orchestration";
|
|
@@ -3705,7 +5224,7 @@ function createSAPAIProvider(options = {}) {
|
|
|
3705
5224
|
provider.languageModel = createModel;
|
|
3706
5225
|
provider.textEmbeddingModel = createEmbeddingModel;
|
|
3707
5226
|
provider.imageModel = (modelId) => {
|
|
3708
|
-
throw new
|
|
5227
|
+
throw new import_provider10.NoSuchModelError({
|
|
3709
5228
|
message: `SAP AI Core does not support image generation. Model '${modelId}' is not available.`,
|
|
3710
5229
|
modelId,
|
|
3711
5230
|
modelType: "imageModel"
|