@jerome-benoit/sap-ai-provider 4.0.0-rc.1 → 4.0.0-rc.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -90
- package/dist/index.cjs +622 -609
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +256 -188
- package/dist/index.d.ts +256 -188
- package/dist/index.js +613 -599
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -29739,7 +29739,7 @@ var require_dist = __commonJS({
|
|
|
29739
29739
|
}
|
|
29740
29740
|
});
|
|
29741
29741
|
|
|
29742
|
-
// src/sap-ai-
|
|
29742
|
+
// src/sap-ai-language-model.ts
|
|
29743
29743
|
import {
|
|
29744
29744
|
OrchestrationClient
|
|
29745
29745
|
} from "@sap-ai-sdk/orchestration";
|
|
@@ -29755,25 +29755,78 @@ function convertToSAPMessages(prompt, options = {}) {
|
|
|
29755
29755
|
const includeReasoning = options.includeReasoning ?? false;
|
|
29756
29756
|
for (const message of prompt) {
|
|
29757
29757
|
switch (message.role) {
|
|
29758
|
+
case "assistant": {
|
|
29759
|
+
let text = "";
|
|
29760
|
+
const toolCalls = [];
|
|
29761
|
+
for (const part of message.content) {
|
|
29762
|
+
switch (part.type) {
|
|
29763
|
+
case "reasoning": {
|
|
29764
|
+
if (includeReasoning && part.text) {
|
|
29765
|
+
text += `<reasoning>${part.text}</reasoning>`;
|
|
29766
|
+
}
|
|
29767
|
+
break;
|
|
29768
|
+
}
|
|
29769
|
+
case "text": {
|
|
29770
|
+
text += part.text;
|
|
29771
|
+
break;
|
|
29772
|
+
}
|
|
29773
|
+
case "tool-call": {
|
|
29774
|
+
let argumentsJson;
|
|
29775
|
+
if (typeof part.input === "string") {
|
|
29776
|
+
try {
|
|
29777
|
+
JSON.parse(part.input);
|
|
29778
|
+
argumentsJson = part.input;
|
|
29779
|
+
} catch {
|
|
29780
|
+
argumentsJson = JSON.stringify(part.input);
|
|
29781
|
+
}
|
|
29782
|
+
} else {
|
|
29783
|
+
argumentsJson = JSON.stringify(part.input);
|
|
29784
|
+
}
|
|
29785
|
+
toolCalls.push({
|
|
29786
|
+
function: {
|
|
29787
|
+
arguments: argumentsJson,
|
|
29788
|
+
name: part.toolName
|
|
29789
|
+
},
|
|
29790
|
+
id: part.toolCallId,
|
|
29791
|
+
type: "function"
|
|
29792
|
+
});
|
|
29793
|
+
break;
|
|
29794
|
+
}
|
|
29795
|
+
}
|
|
29796
|
+
}
|
|
29797
|
+
const assistantMessage = {
|
|
29798
|
+
content: text || "",
|
|
29799
|
+
role: "assistant",
|
|
29800
|
+
tool_calls: toolCalls.length > 0 ? toolCalls : void 0
|
|
29801
|
+
};
|
|
29802
|
+
messages.push(assistantMessage);
|
|
29803
|
+
break;
|
|
29804
|
+
}
|
|
29758
29805
|
case "system": {
|
|
29759
29806
|
const systemMessage = {
|
|
29760
|
-
|
|
29761
|
-
|
|
29807
|
+
content: message.content,
|
|
29808
|
+
role: "system"
|
|
29762
29809
|
};
|
|
29763
29810
|
messages.push(systemMessage);
|
|
29764
29811
|
break;
|
|
29765
29812
|
}
|
|
29813
|
+
case "tool": {
|
|
29814
|
+
for (const part of message.content) {
|
|
29815
|
+
if (part.type === "tool-result") {
|
|
29816
|
+
const toolMessage = {
|
|
29817
|
+
content: JSON.stringify(part.output),
|
|
29818
|
+
role: "tool",
|
|
29819
|
+
tool_call_id: part.toolCallId
|
|
29820
|
+
};
|
|
29821
|
+
messages.push(toolMessage);
|
|
29822
|
+
}
|
|
29823
|
+
}
|
|
29824
|
+
break;
|
|
29825
|
+
}
|
|
29766
29826
|
case "user": {
|
|
29767
29827
|
const contentParts = [];
|
|
29768
29828
|
for (const part of message.content) {
|
|
29769
29829
|
switch (part.type) {
|
|
29770
|
-
case "text": {
|
|
29771
|
-
contentParts.push({
|
|
29772
|
-
type: "text",
|
|
29773
|
-
text: part.text
|
|
29774
|
-
});
|
|
29775
|
-
break;
|
|
29776
|
-
}
|
|
29777
29830
|
case "file": {
|
|
29778
29831
|
if (!part.mediaType.startsWith("image/")) {
|
|
29779
29832
|
throw new UnsupportedFunctionalityError({
|
|
@@ -29815,10 +29868,17 @@ function convertToSAPMessages(prompt, options = {}) {
|
|
|
29815
29868
|
}
|
|
29816
29869
|
}
|
|
29817
29870
|
contentParts.push({
|
|
29818
|
-
type: "image_url",
|
|
29819
29871
|
image_url: {
|
|
29820
29872
|
url: imageUrl
|
|
29821
|
-
}
|
|
29873
|
+
},
|
|
29874
|
+
type: "image_url"
|
|
29875
|
+
});
|
|
29876
|
+
break;
|
|
29877
|
+
}
|
|
29878
|
+
case "text": {
|
|
29879
|
+
contentParts.push({
|
|
29880
|
+
text: part.text,
|
|
29881
|
+
type: "text"
|
|
29822
29882
|
});
|
|
29823
29883
|
break;
|
|
29824
29884
|
}
|
|
@@ -29830,75 +29890,15 @@ function convertToSAPMessages(prompt, options = {}) {
|
|
|
29830
29890
|
}
|
|
29831
29891
|
}
|
|
29832
29892
|
const userMessage = contentParts.length === 1 && contentParts[0].type === "text" ? {
|
|
29833
|
-
|
|
29834
|
-
|
|
29893
|
+
content: contentParts[0].text ?? "",
|
|
29894
|
+
role: "user"
|
|
29835
29895
|
} : {
|
|
29836
|
-
|
|
29837
|
-
|
|
29896
|
+
content: contentParts,
|
|
29897
|
+
role: "user"
|
|
29838
29898
|
};
|
|
29839
29899
|
messages.push(userMessage);
|
|
29840
29900
|
break;
|
|
29841
29901
|
}
|
|
29842
|
-
case "assistant": {
|
|
29843
|
-
let text = "";
|
|
29844
|
-
const toolCalls = [];
|
|
29845
|
-
for (const part of message.content) {
|
|
29846
|
-
switch (part.type) {
|
|
29847
|
-
case "text": {
|
|
29848
|
-
text += part.text;
|
|
29849
|
-
break;
|
|
29850
|
-
}
|
|
29851
|
-
case "reasoning": {
|
|
29852
|
-
if (includeReasoning && part.text) {
|
|
29853
|
-
text += `<reasoning>${part.text}</reasoning>`;
|
|
29854
|
-
}
|
|
29855
|
-
break;
|
|
29856
|
-
}
|
|
29857
|
-
case "tool-call": {
|
|
29858
|
-
let argumentsJson;
|
|
29859
|
-
if (typeof part.input === "string") {
|
|
29860
|
-
try {
|
|
29861
|
-
JSON.parse(part.input);
|
|
29862
|
-
argumentsJson = part.input;
|
|
29863
|
-
} catch {
|
|
29864
|
-
argumentsJson = JSON.stringify(part.input);
|
|
29865
|
-
}
|
|
29866
|
-
} else {
|
|
29867
|
-
argumentsJson = JSON.stringify(part.input);
|
|
29868
|
-
}
|
|
29869
|
-
toolCalls.push({
|
|
29870
|
-
id: part.toolCallId,
|
|
29871
|
-
type: "function",
|
|
29872
|
-
function: {
|
|
29873
|
-
name: part.toolName,
|
|
29874
|
-
arguments: argumentsJson
|
|
29875
|
-
}
|
|
29876
|
-
});
|
|
29877
|
-
break;
|
|
29878
|
-
}
|
|
29879
|
-
}
|
|
29880
|
-
}
|
|
29881
|
-
const assistantMessage = {
|
|
29882
|
-
role: "assistant",
|
|
29883
|
-
content: text || "",
|
|
29884
|
-
tool_calls: toolCalls.length > 0 ? toolCalls : void 0
|
|
29885
|
-
};
|
|
29886
|
-
messages.push(assistantMessage);
|
|
29887
|
-
break;
|
|
29888
|
-
}
|
|
29889
|
-
case "tool": {
|
|
29890
|
-
for (const part of message.content) {
|
|
29891
|
-
if (part.type === "tool-result") {
|
|
29892
|
-
const toolMessage = {
|
|
29893
|
-
role: "tool",
|
|
29894
|
-
tool_call_id: part.toolCallId,
|
|
29895
|
-
content: JSON.stringify(part.output)
|
|
29896
|
-
};
|
|
29897
|
-
messages.push(toolMessage);
|
|
29898
|
-
}
|
|
29899
|
-
}
|
|
29900
|
-
break;
|
|
29901
|
-
}
|
|
29902
29902
|
default: {
|
|
29903
29903
|
const _exhaustiveCheck = message;
|
|
29904
29904
|
throw new Error(
|
|
@@ -29913,16 +29913,6 @@ function convertToSAPMessages(prompt, options = {}) {
|
|
|
29913
29913
|
// src/sap-ai-error.ts
|
|
29914
29914
|
var import_util = __toESM(require_dist(), 1);
|
|
29915
29915
|
import { APICallError, LoadAPIKeyError } from "@ai-sdk/provider";
|
|
29916
|
-
function getStatusCodeFromSAPError(code) {
|
|
29917
|
-
if (!code) return 500;
|
|
29918
|
-
if (code >= 100 && code < 600) {
|
|
29919
|
-
return code;
|
|
29920
|
-
}
|
|
29921
|
-
return 500;
|
|
29922
|
-
}
|
|
29923
|
-
function isRetryable(statusCode) {
|
|
29924
|
-
return statusCode === 429 || statusCode >= 500 && statusCode < 600;
|
|
29925
|
-
}
|
|
29926
29916
|
function convertSAPErrorToAPICallError(errorResponse, context) {
|
|
29927
29917
|
const error = errorResponse.error;
|
|
29928
29918
|
let message;
|
|
@@ -29944,9 +29934,9 @@ function convertSAPErrorToAPICallError(errorResponse, context) {
|
|
|
29944
29934
|
const statusCode = getStatusCodeFromSAPError(code);
|
|
29945
29935
|
const responseBody = JSON.stringify({
|
|
29946
29936
|
error: {
|
|
29947
|
-
message,
|
|
29948
29937
|
code,
|
|
29949
29938
|
location,
|
|
29939
|
+
message,
|
|
29950
29940
|
request_id: requestId
|
|
29951
29941
|
}
|
|
29952
29942
|
});
|
|
@@ -29969,53 +29959,14 @@ Error location: ${location}`;
|
|
|
29969
29959
|
Request ID: ${requestId}`;
|
|
29970
29960
|
}
|
|
29971
29961
|
return new APICallError({
|
|
29962
|
+
isRetryable: isRetryable(statusCode),
|
|
29972
29963
|
message: enhancedMessage,
|
|
29973
|
-
url: context?.url ?? "",
|
|
29974
29964
|
requestBodyValues: context?.requestBody,
|
|
29975
|
-
statusCode,
|
|
29976
|
-
responseHeaders: context?.responseHeaders,
|
|
29977
29965
|
responseBody,
|
|
29978
|
-
|
|
29979
|
-
|
|
29980
|
-
|
|
29981
|
-
function isOrchestrationErrorResponse(error) {
|
|
29982
|
-
if (error === null || typeof error !== "object" || !("error" in error)) {
|
|
29983
|
-
return false;
|
|
29984
|
-
}
|
|
29985
|
-
const errorEnvelope = error;
|
|
29986
|
-
const innerError = errorEnvelope.error;
|
|
29987
|
-
if (innerError === void 0) return false;
|
|
29988
|
-
if (Array.isArray(innerError)) {
|
|
29989
|
-
return innerError.every(
|
|
29990
|
-
(entry) => entry !== null && typeof entry === "object" && "message" in entry && typeof entry.message === "string"
|
|
29991
|
-
);
|
|
29992
|
-
}
|
|
29993
|
-
return typeof innerError === "object" && innerError !== null && "message" in innerError && typeof innerError.message === "string";
|
|
29994
|
-
}
|
|
29995
|
-
function normalizeHeaders(headers) {
|
|
29996
|
-
if (!headers || typeof headers !== "object") return void 0;
|
|
29997
|
-
const record = headers;
|
|
29998
|
-
const entries = Object.entries(record).flatMap(([key, value]) => {
|
|
29999
|
-
if (typeof value === "string") return [[key, value]];
|
|
30000
|
-
if (Array.isArray(value)) {
|
|
30001
|
-
const strings = value.filter((item) => typeof item === "string").join("; ");
|
|
30002
|
-
return strings.length > 0 ? [[key, strings]] : [];
|
|
30003
|
-
}
|
|
30004
|
-
if (typeof value === "number" || typeof value === "boolean") {
|
|
30005
|
-
return [[key, String(value)]];
|
|
30006
|
-
}
|
|
30007
|
-
return [];
|
|
29966
|
+
responseHeaders: context?.responseHeaders,
|
|
29967
|
+
statusCode,
|
|
29968
|
+
url: context?.url ?? ""
|
|
30008
29969
|
});
|
|
30009
|
-
if (entries.length === 0) return void 0;
|
|
30010
|
-
return Object.fromEntries(entries);
|
|
30011
|
-
}
|
|
30012
|
-
function getAxiosResponseHeaders(error) {
|
|
30013
|
-
if (!(error instanceof Error)) return void 0;
|
|
30014
|
-
const rootCause = (0, import_util.isErrorWithCause)(error) ? error.rootCause : error;
|
|
30015
|
-
if (typeof rootCause !== "object") return void 0;
|
|
30016
|
-
const maybeAxios = rootCause;
|
|
30017
|
-
if (maybeAxios.isAxiosError !== true) return void 0;
|
|
30018
|
-
return normalizeHeaders(maybeAxios.response?.headers);
|
|
30019
29970
|
}
|
|
30020
29971
|
function convertToAISDKError(error, context) {
|
|
30021
29972
|
if (error instanceof APICallError || error instanceof LoadAPIKeyError) {
|
|
@@ -30040,30 +29991,79 @@ See: https://help.sap.com/docs/sap-ai-core/sap-ai-core-service-guide/create-serv
|
|
|
30040
29991
|
}
|
|
30041
29992
|
if (errorMsg.includes("econnrefused") || errorMsg.includes("enotfound") || errorMsg.includes("network") || errorMsg.includes("timeout")) {
|
|
30042
29993
|
return new APICallError({
|
|
29994
|
+
cause: error,
|
|
29995
|
+
isRetryable: true,
|
|
30043
29996
|
message: `Network error connecting to SAP AI Core: ${error.message}`,
|
|
30044
|
-
url: context?.url ?? "",
|
|
30045
29997
|
requestBodyValues: context?.requestBody,
|
|
30046
|
-
statusCode: 503,
|
|
30047
|
-
isRetryable: true,
|
|
30048
29998
|
responseHeaders,
|
|
30049
|
-
|
|
29999
|
+
statusCode: 503,
|
|
30000
|
+
url: context?.url ?? ""
|
|
30050
30001
|
});
|
|
30051
30002
|
}
|
|
30052
30003
|
}
|
|
30053
30004
|
const message = error instanceof Error ? error.message : typeof error === "string" ? error : "Unknown error occurred";
|
|
30054
30005
|
const fullMessage = context?.operation ? `SAP AI Core ${context.operation} failed: ${message}` : `SAP AI Core error: ${message}`;
|
|
30055
30006
|
return new APICallError({
|
|
30007
|
+
cause: error,
|
|
30008
|
+
isRetryable: false,
|
|
30056
30009
|
message: fullMessage,
|
|
30057
|
-
url: context?.url ?? "",
|
|
30058
30010
|
requestBodyValues: context?.requestBody,
|
|
30059
|
-
statusCode: 500,
|
|
30060
|
-
isRetryable: false,
|
|
30061
30011
|
responseHeaders,
|
|
30062
|
-
|
|
30012
|
+
statusCode: 500,
|
|
30013
|
+
url: context?.url ?? ""
|
|
30014
|
+
});
|
|
30015
|
+
}
|
|
30016
|
+
function getAxiosResponseHeaders(error) {
|
|
30017
|
+
if (!(error instanceof Error)) return void 0;
|
|
30018
|
+
const rootCause = (0, import_util.isErrorWithCause)(error) ? error.rootCause : error;
|
|
30019
|
+
if (typeof rootCause !== "object") return void 0;
|
|
30020
|
+
const maybeAxios = rootCause;
|
|
30021
|
+
if (maybeAxios.isAxiosError !== true) return void 0;
|
|
30022
|
+
return normalizeHeaders(maybeAxios.response?.headers);
|
|
30023
|
+
}
|
|
30024
|
+
function getStatusCodeFromSAPError(code) {
|
|
30025
|
+
if (!code) return 500;
|
|
30026
|
+
if (code >= 100 && code < 600) {
|
|
30027
|
+
return code;
|
|
30028
|
+
}
|
|
30029
|
+
return 500;
|
|
30030
|
+
}
|
|
30031
|
+
function isOrchestrationErrorResponse(error) {
|
|
30032
|
+
if (error === null || typeof error !== "object" || !("error" in error)) {
|
|
30033
|
+
return false;
|
|
30034
|
+
}
|
|
30035
|
+
const errorEnvelope = error;
|
|
30036
|
+
const innerError = errorEnvelope.error;
|
|
30037
|
+
if (innerError === void 0) return false;
|
|
30038
|
+
if (Array.isArray(innerError)) {
|
|
30039
|
+
return innerError.every(
|
|
30040
|
+
(entry) => entry !== null && typeof entry === "object" && "message" in entry && typeof entry.message === "string"
|
|
30041
|
+
);
|
|
30042
|
+
}
|
|
30043
|
+
return typeof innerError === "object" && innerError !== null && "message" in innerError && typeof innerError.message === "string";
|
|
30044
|
+
}
|
|
30045
|
+
function isRetryable(statusCode) {
|
|
30046
|
+
return statusCode === 429 || statusCode >= 500 && statusCode < 600;
|
|
30047
|
+
}
|
|
30048
|
+
function normalizeHeaders(headers) {
|
|
30049
|
+
if (!headers || typeof headers !== "object") return void 0;
|
|
30050
|
+
const record = headers;
|
|
30051
|
+
const entries = Object.entries(record).flatMap(([key, value]) => {
|
|
30052
|
+
if (typeof value === "string") return [[key, value]];
|
|
30053
|
+
if (Array.isArray(value)) {
|
|
30054
|
+
const strings = value.filter((item) => typeof item === "string").join("; ");
|
|
30055
|
+
return strings.length > 0 ? [[key, strings]] : [];
|
|
30056
|
+
}
|
|
30057
|
+
if (typeof value === "number" || typeof value === "boolean") {
|
|
30058
|
+
return [[key, String(value)]];
|
|
30059
|
+
}
|
|
30060
|
+
return [];
|
|
30063
30061
|
});
|
|
30062
|
+
if (entries.length === 0) return void 0;
|
|
30063
|
+
return Object.fromEntries(entries);
|
|
30064
30064
|
}
|
|
30065
30065
|
|
|
30066
|
-
// src/sap-ai-
|
|
30066
|
+
// src/sap-ai-language-model.ts
|
|
30067
30067
|
var StreamIdGenerator = class {
|
|
30068
30068
|
/**
|
|
30069
30069
|
* Generates a unique ID for a text block.
|
|
@@ -30074,139 +30074,27 @@ var StreamIdGenerator = class {
|
|
|
30074
30074
|
return crypto.randomUUID();
|
|
30075
30075
|
}
|
|
30076
30076
|
};
|
|
30077
|
-
|
|
30078
|
-
if (params.temperature !== void 0 && (params.temperature < 0 || params.temperature > 2)) {
|
|
30079
|
-
warnings.push({
|
|
30080
|
-
type: "other",
|
|
30081
|
-
message: `temperature=${String(params.temperature)} is outside typical range [0, 2]. The API may reject this value.`
|
|
30082
|
-
});
|
|
30083
|
-
}
|
|
30084
|
-
if (params.topP !== void 0 && (params.topP < 0 || params.topP > 1)) {
|
|
30085
|
-
warnings.push({
|
|
30086
|
-
type: "other",
|
|
30087
|
-
message: `topP=${String(params.topP)} is outside valid range [0, 1]. The API may reject this value.`
|
|
30088
|
-
});
|
|
30089
|
-
}
|
|
30090
|
-
if (params.frequencyPenalty !== void 0 && (params.frequencyPenalty < -2 || params.frequencyPenalty > 2)) {
|
|
30091
|
-
warnings.push({
|
|
30092
|
-
type: "other",
|
|
30093
|
-
message: `frequencyPenalty=${String(params.frequencyPenalty)} is outside typical range [-2, 2]. The API may reject this value.`
|
|
30094
|
-
});
|
|
30095
|
-
}
|
|
30096
|
-
if (params.presencePenalty !== void 0 && (params.presencePenalty < -2 || params.presencePenalty > 2)) {
|
|
30097
|
-
warnings.push({
|
|
30098
|
-
type: "other",
|
|
30099
|
-
message: `presencePenalty=${String(params.presencePenalty)} is outside typical range [-2, 2]. The API may reject this value.`
|
|
30100
|
-
});
|
|
30101
|
-
}
|
|
30102
|
-
if (params.maxTokens !== void 0 && params.maxTokens <= 0) {
|
|
30103
|
-
warnings.push({
|
|
30104
|
-
type: "other",
|
|
30105
|
-
message: `maxTokens=${String(params.maxTokens)} must be positive. The API will likely reject this value.`
|
|
30106
|
-
});
|
|
30107
|
-
}
|
|
30108
|
-
if (params.n !== void 0 && params.n <= 0) {
|
|
30109
|
-
warnings.push({
|
|
30110
|
-
type: "other",
|
|
30111
|
-
message: `n=${String(params.n)} must be positive. The API will likely reject this value.`
|
|
30112
|
-
});
|
|
30113
|
-
}
|
|
30114
|
-
}
|
|
30115
|
-
function createAISDKRequestBodySummary(options) {
|
|
30116
|
-
return {
|
|
30117
|
-
promptMessages: options.prompt.length,
|
|
30118
|
-
hasImageParts: options.prompt.some(
|
|
30119
|
-
(message) => message.role === "user" && message.content.some(
|
|
30120
|
-
(part) => part.type === "file" && part.mediaType.startsWith("image/")
|
|
30121
|
-
)
|
|
30122
|
-
),
|
|
30123
|
-
tools: options.tools?.length ?? 0,
|
|
30124
|
-
temperature: options.temperature,
|
|
30125
|
-
topP: options.topP,
|
|
30126
|
-
topK: options.topK,
|
|
30127
|
-
maxOutputTokens: options.maxOutputTokens,
|
|
30128
|
-
stopSequences: options.stopSequences?.length,
|
|
30129
|
-
seed: options.seed,
|
|
30130
|
-
toolChoiceType: options.toolChoice?.type,
|
|
30131
|
-
responseFormatType: options.responseFormat?.type
|
|
30132
|
-
};
|
|
30133
|
-
}
|
|
30134
|
-
function hasCallableParse(obj) {
|
|
30135
|
-
return typeof obj.parse === "function";
|
|
30136
|
-
}
|
|
30137
|
-
function isZodSchema(obj) {
|
|
30138
|
-
if (obj === null || typeof obj !== "object") {
|
|
30139
|
-
return false;
|
|
30140
|
-
}
|
|
30141
|
-
const record = obj;
|
|
30142
|
-
return "_def" in record && "parse" in record && hasCallableParse(record);
|
|
30143
|
-
}
|
|
30144
|
-
function buildSAPToolParameters(schema) {
|
|
30145
|
-
const schemaType = schema.type;
|
|
30146
|
-
if (schemaType !== void 0 && schemaType !== "object") {
|
|
30147
|
-
return {
|
|
30148
|
-
type: "object",
|
|
30149
|
-
properties: {},
|
|
30150
|
-
required: []
|
|
30151
|
-
};
|
|
30152
|
-
}
|
|
30153
|
-
const properties = schema.properties && typeof schema.properties === "object" ? schema.properties : {};
|
|
30154
|
-
const required = Array.isArray(schema.required) && schema.required.every((item) => typeof item === "string") ? schema.required : [];
|
|
30155
|
-
const additionalFields = Object.fromEntries(
|
|
30156
|
-
Object.entries(schema).filter(
|
|
30157
|
-
([key]) => key !== "type" && key !== "properties" && key !== "required"
|
|
30158
|
-
)
|
|
30159
|
-
);
|
|
30160
|
-
return {
|
|
30161
|
-
type: "object",
|
|
30162
|
-
properties,
|
|
30163
|
-
required,
|
|
30164
|
-
...additionalFields
|
|
30165
|
-
};
|
|
30166
|
-
}
|
|
30167
|
-
var SAPAIChatLanguageModel = class {
|
|
30168
|
-
specificationVersion = "v3";
|
|
30077
|
+
var SAPAILanguageModel = class {
|
|
30169
30078
|
modelId;
|
|
30170
|
-
|
|
30171
|
-
settings;
|
|
30172
|
-
/**
|
|
30173
|
-
* Creates a new SAP AI Chat Language Model instance.
|
|
30174
|
-
*
|
|
30175
|
-
* @param modelId - The model identifier
|
|
30176
|
-
* @param settings - Model-specific configuration settings
|
|
30177
|
-
* @param config - Internal configuration (deployment config, destination, etc.)
|
|
30178
|
-
*
|
|
30179
|
-
* @internal This constructor is not meant to be called directly.
|
|
30180
|
-
* Use the provider function instead.
|
|
30181
|
-
*/
|
|
30182
|
-
constructor(modelId, settings, config) {
|
|
30183
|
-
this.settings = settings;
|
|
30184
|
-
this.config = config;
|
|
30185
|
-
this.modelId = modelId;
|
|
30186
|
-
}
|
|
30187
|
-
/**
|
|
30188
|
-
* Checks if a URL is supported for file/image uploads.
|
|
30189
|
-
*
|
|
30190
|
-
* @param url - The URL to check
|
|
30191
|
-
* @returns True if the URL protocol is HTTPS or data with valid image format
|
|
30192
|
-
*/
|
|
30193
|
-
supportsUrl(url) {
|
|
30194
|
-
if (url.protocol === "https:") return true;
|
|
30195
|
-
if (url.protocol === "data:") {
|
|
30196
|
-
return /^data:image\//i.test(url.href);
|
|
30197
|
-
}
|
|
30198
|
-
return false;
|
|
30199
|
-
}
|
|
30079
|
+
specificationVersion = "v3";
|
|
30200
30080
|
/**
|
|
30201
|
-
*
|
|
30081
|
+
* Model capabilities.
|
|
30202
30082
|
*
|
|
30203
|
-
*
|
|
30083
|
+
* These defaults assume “modern” model behavior to avoid maintaining a
|
|
30084
|
+
* per-model capability matrix. If a deployment doesn't support a feature,
|
|
30085
|
+
* SAP AI Core will fail the request at runtime.
|
|
30204
30086
|
*/
|
|
30205
|
-
|
|
30206
|
-
|
|
30207
|
-
|
|
30208
|
-
|
|
30209
|
-
|
|
30087
|
+
supportsImageUrls = true;
|
|
30088
|
+
/** Multiple completions via the `n` parameter (provider-specific support). */
|
|
30089
|
+
supportsMultipleCompletions = true;
|
|
30090
|
+
/** Parallel tool calls. */
|
|
30091
|
+
supportsParallelToolCalls = true;
|
|
30092
|
+
/** Streaming responses. */
|
|
30093
|
+
supportsStreaming = true;
|
|
30094
|
+
/** Structured JSON outputs (json_schema response format). */
|
|
30095
|
+
supportsStructuredOutputs = true;
|
|
30096
|
+
/** Tool/function calling. */
|
|
30097
|
+
supportsToolCalls = true;
|
|
30210
30098
|
/**
|
|
30211
30099
|
* Generates text completion using SAP AI Core's Orchestration API.
|
|
30212
30100
|
*
|
|
@@ -30252,206 +30140,31 @@ var SAPAIChatLanguageModel = class {
|
|
|
30252
30140
|
return this.config.provider;
|
|
30253
30141
|
}
|
|
30254
30142
|
/**
|
|
30255
|
-
*
|
|
30256
|
-
*
|
|
30257
|
-
* These defaults assume “modern” model behavior to avoid maintaining a
|
|
30258
|
-
* per-model capability matrix. If a deployment doesn't support a feature,
|
|
30259
|
-
* SAP AI Core will fail the request at runtime.
|
|
30260
|
-
*/
|
|
30261
|
-
supportsImageUrls = true;
|
|
30262
|
-
/** Structured JSON outputs (json_schema response format). */
|
|
30263
|
-
supportsStructuredOutputs = true;
|
|
30264
|
-
/** Tool/function calling. */
|
|
30265
|
-
supportsToolCalls = true;
|
|
30266
|
-
/** Streaming responses. */
|
|
30267
|
-
supportsStreaming = true;
|
|
30268
|
-
/** Multiple completions via the `n` parameter (provider-specific support). */
|
|
30269
|
-
supportsMultipleCompletions = true;
|
|
30270
|
-
/** Parallel tool calls. */
|
|
30271
|
-
supportsParallelToolCalls = true;
|
|
30272
|
-
/**
|
|
30273
|
-
* Builds orchestration module config for SAP AI SDK.
|
|
30143
|
+
* Returns supported URL patterns for different content types.
|
|
30274
30144
|
*
|
|
30275
|
-
* @
|
|
30276
|
-
* @returns Object containing orchestration config, messages, and warnings
|
|
30277
|
-
* @internal
|
|
30145
|
+
* @returns Record of content types to regex patterns
|
|
30278
30146
|
*/
|
|
30279
|
-
|
|
30280
|
-
|
|
30281
|
-
|
|
30282
|
-
const messages = convertToSAPMessages(options.prompt, {
|
|
30283
|
-
includeReasoning: providerOptions.includeReasoning ?? this.settings.includeReasoning ?? false
|
|
30284
|
-
});
|
|
30285
|
-
let tools;
|
|
30286
|
-
const settingsTools = providerOptions.tools ?? this.settings.tools;
|
|
30287
|
-
const optionsTools = options.tools;
|
|
30288
|
-
const shouldUseSettingsTools = settingsTools && settingsTools.length > 0 && (!optionsTools || optionsTools.length === 0);
|
|
30289
|
-
const shouldUseOptionsTools = !!(optionsTools && optionsTools.length > 0);
|
|
30290
|
-
if (settingsTools && settingsTools.length > 0 && optionsTools && optionsTools.length > 0) {
|
|
30291
|
-
warnings.push({
|
|
30292
|
-
type: "other",
|
|
30293
|
-
message: "Both settings.tools and call options.tools were provided; preferring call options.tools."
|
|
30294
|
-
});
|
|
30295
|
-
}
|
|
30296
|
-
if (shouldUseSettingsTools) {
|
|
30297
|
-
tools = settingsTools;
|
|
30298
|
-
} else {
|
|
30299
|
-
const availableTools = shouldUseOptionsTools ? optionsTools : void 0;
|
|
30300
|
-
tools = availableTools?.map((tool) => {
|
|
30301
|
-
if (tool.type === "function") {
|
|
30302
|
-
const inputSchema = tool.inputSchema;
|
|
30303
|
-
const toolWithParams = tool;
|
|
30304
|
-
let parameters;
|
|
30305
|
-
if (toolWithParams.parameters && isZodSchema(toolWithParams.parameters)) {
|
|
30306
|
-
try {
|
|
30307
|
-
const jsonSchema = zodToJsonSchema(
|
|
30308
|
-
toolWithParams.parameters,
|
|
30309
|
-
{
|
|
30310
|
-
$refStrategy: "none"
|
|
30311
|
-
}
|
|
30312
|
-
);
|
|
30313
|
-
const schemaRecord = jsonSchema;
|
|
30314
|
-
delete schemaRecord.$schema;
|
|
30315
|
-
parameters = buildSAPToolParameters(schemaRecord);
|
|
30316
|
-
} catch (error) {
|
|
30317
|
-
warnings.push({
|
|
30318
|
-
type: "unsupported",
|
|
30319
|
-
feature: `tool schema conversion for ${tool.name}`,
|
|
30320
|
-
details: `Failed to convert tool Zod schema: ${error instanceof Error ? error.message : String(error)}. Falling back to empty object schema.`
|
|
30321
|
-
});
|
|
30322
|
-
parameters = buildSAPToolParameters({});
|
|
30323
|
-
}
|
|
30324
|
-
} else if (inputSchema && Object.keys(inputSchema).length > 0) {
|
|
30325
|
-
const hasProperties = inputSchema.properties && typeof inputSchema.properties === "object" && Object.keys(inputSchema.properties).length > 0;
|
|
30326
|
-
if (hasProperties) {
|
|
30327
|
-
parameters = buildSAPToolParameters(inputSchema);
|
|
30328
|
-
} else {
|
|
30329
|
-
parameters = buildSAPToolParameters({});
|
|
30330
|
-
}
|
|
30331
|
-
} else {
|
|
30332
|
-
parameters = buildSAPToolParameters({});
|
|
30333
|
-
}
|
|
30334
|
-
return {
|
|
30335
|
-
type: "function",
|
|
30336
|
-
function: {
|
|
30337
|
-
name: tool.name,
|
|
30338
|
-
description: tool.description,
|
|
30339
|
-
parameters
|
|
30340
|
-
}
|
|
30341
|
-
};
|
|
30342
|
-
} else {
|
|
30343
|
-
warnings.push({
|
|
30344
|
-
type: "unsupported",
|
|
30345
|
-
feature: `tool type for ${tool.name}`,
|
|
30346
|
-
details: "Only 'function' tool type is supported."
|
|
30347
|
-
});
|
|
30348
|
-
return null;
|
|
30349
|
-
}
|
|
30350
|
-
}).filter((t) => t !== null);
|
|
30351
|
-
}
|
|
30352
|
-
const supportsN = !this.modelId.startsWith("amazon--") && !this.modelId.startsWith("anthropic--");
|
|
30353
|
-
const modelParams = {};
|
|
30354
|
-
const maxTokens = options.maxOutputTokens ?? providerOptions.modelParams?.maxTokens ?? this.settings.modelParams?.maxTokens;
|
|
30355
|
-
if (maxTokens !== void 0) modelParams.max_tokens = maxTokens;
|
|
30356
|
-
const temperature = options.temperature ?? providerOptions.modelParams?.temperature ?? this.settings.modelParams?.temperature;
|
|
30357
|
-
if (temperature !== void 0) modelParams.temperature = temperature;
|
|
30358
|
-
const topP = options.topP ?? providerOptions.modelParams?.topP ?? this.settings.modelParams?.topP;
|
|
30359
|
-
if (topP !== void 0) modelParams.top_p = topP;
|
|
30360
|
-
if (options.topK !== void 0) modelParams.top_k = options.topK;
|
|
30361
|
-
const frequencyPenalty = options.frequencyPenalty ?? providerOptions.modelParams?.frequencyPenalty ?? this.settings.modelParams?.frequencyPenalty;
|
|
30362
|
-
if (frequencyPenalty !== void 0) {
|
|
30363
|
-
modelParams.frequency_penalty = frequencyPenalty;
|
|
30364
|
-
}
|
|
30365
|
-
const presencePenalty = options.presencePenalty ?? providerOptions.modelParams?.presencePenalty ?? this.settings.modelParams?.presencePenalty;
|
|
30366
|
-
if (presencePenalty !== void 0) {
|
|
30367
|
-
modelParams.presence_penalty = presencePenalty;
|
|
30368
|
-
}
|
|
30369
|
-
if (supportsN) {
|
|
30370
|
-
const nValue = providerOptions.modelParams?.n ?? this.settings.modelParams?.n;
|
|
30371
|
-
if (nValue !== void 0) {
|
|
30372
|
-
modelParams.n = nValue;
|
|
30373
|
-
}
|
|
30374
|
-
}
|
|
30375
|
-
const parallelToolCalls = providerOptions.modelParams?.parallel_tool_calls ?? this.settings.modelParams?.parallel_tool_calls;
|
|
30376
|
-
if (parallelToolCalls !== void 0) {
|
|
30377
|
-
modelParams.parallel_tool_calls = parallelToolCalls;
|
|
30378
|
-
}
|
|
30379
|
-
if (options.stopSequences && options.stopSequences.length > 0) {
|
|
30380
|
-
modelParams.stop = options.stopSequences;
|
|
30381
|
-
}
|
|
30382
|
-
if (options.seed !== void 0) {
|
|
30383
|
-
modelParams.seed = options.seed;
|
|
30384
|
-
}
|
|
30385
|
-
validateModelParameters(
|
|
30386
|
-
{
|
|
30387
|
-
temperature,
|
|
30388
|
-
topP,
|
|
30389
|
-
frequencyPenalty,
|
|
30390
|
-
presencePenalty,
|
|
30391
|
-
maxTokens,
|
|
30392
|
-
n: modelParams.n
|
|
30393
|
-
},
|
|
30394
|
-
warnings
|
|
30395
|
-
);
|
|
30396
|
-
if (options.toolChoice && options.toolChoice.type !== "auto") {
|
|
30397
|
-
warnings.push({
|
|
30398
|
-
type: "unsupported",
|
|
30399
|
-
feature: "toolChoice",
|
|
30400
|
-
details: `SAP AI SDK does not support toolChoice '${options.toolChoice.type}'. Using default 'auto' behavior.`
|
|
30401
|
-
});
|
|
30402
|
-
}
|
|
30403
|
-
if (options.responseFormat?.type === "json") {
|
|
30404
|
-
warnings.push({
|
|
30405
|
-
type: "other",
|
|
30406
|
-
message: "responseFormat JSON mode is forwarded to the underlying model; support and schema adherence depend on the model/deployment."
|
|
30407
|
-
});
|
|
30408
|
-
}
|
|
30409
|
-
const responseFormat = options.responseFormat?.type === "json" ? options.responseFormat.schema ? {
|
|
30410
|
-
type: "json_schema",
|
|
30411
|
-
json_schema: {
|
|
30412
|
-
name: options.responseFormat.name ?? "response",
|
|
30413
|
-
description: options.responseFormat.description,
|
|
30414
|
-
schema: options.responseFormat.schema,
|
|
30415
|
-
strict: null
|
|
30416
|
-
}
|
|
30417
|
-
} : { type: "json_object" } : void 0;
|
|
30418
|
-
const orchestrationConfig = {
|
|
30419
|
-
promptTemplating: {
|
|
30420
|
-
model: {
|
|
30421
|
-
name: this.modelId,
|
|
30422
|
-
version: providerOptions.modelVersion ?? this.settings.modelVersion ?? "latest",
|
|
30423
|
-
params: modelParams
|
|
30424
|
-
},
|
|
30425
|
-
prompt: {
|
|
30426
|
-
template: [],
|
|
30427
|
-
tools: tools && tools.length > 0 ? tools : void 0,
|
|
30428
|
-
...responseFormat ? { response_format: responseFormat } : {}
|
|
30429
|
-
}
|
|
30430
|
-
},
|
|
30431
|
-
...(() => {
|
|
30432
|
-
const masking = providerOptions.masking ?? this.settings.masking;
|
|
30433
|
-
return masking && Object.keys(masking).length > 0 ? { masking } : {};
|
|
30434
|
-
})(),
|
|
30435
|
-
...(() => {
|
|
30436
|
-
const filtering = providerOptions.filtering ?? this.settings.filtering;
|
|
30437
|
-
return filtering && Object.keys(filtering).length > 0 ? { filtering } : {};
|
|
30438
|
-
})()
|
|
30147
|
+
get supportedUrls() {
|
|
30148
|
+
return {
|
|
30149
|
+
"image/*": [/^https:\/\/.+$/i, /^data:image\/.*$/]
|
|
30439
30150
|
};
|
|
30440
|
-
return { orchestrationConfig, messages, warnings };
|
|
30441
30151
|
}
|
|
30152
|
+
config;
|
|
30153
|
+
settings;
|
|
30442
30154
|
/**
|
|
30443
|
-
* Creates
|
|
30155
|
+
* Creates a new SAP AI Chat Language Model instance.
|
|
30444
30156
|
*
|
|
30445
|
-
* @param
|
|
30446
|
-
* @
|
|
30447
|
-
* @
|
|
30157
|
+
* @param modelId - The model identifier
|
|
30158
|
+
* @param settings - Model-specific configuration settings
|
|
30159
|
+
* @param config - Internal configuration (deployment config, destination, etc.)
|
|
30160
|
+
*
|
|
30161
|
+
* @internal This constructor is not meant to be called directly.
|
|
30162
|
+
* Use the provider function instead.
|
|
30448
30163
|
*/
|
|
30449
|
-
|
|
30450
|
-
|
|
30451
|
-
|
|
30452
|
-
|
|
30453
|
-
this.config.destination
|
|
30454
|
-
);
|
|
30164
|
+
constructor(modelId, settings, config) {
|
|
30165
|
+
this.settings = settings;
|
|
30166
|
+
this.config = config;
|
|
30167
|
+
this.modelId = modelId;
|
|
30455
30168
|
}
|
|
30456
30169
|
/**
|
|
30457
30170
|
* Generates a single completion (non-streaming).
|
|
@@ -30489,7 +30202,7 @@ var SAPAIChatLanguageModel = class {
|
|
|
30489
30202
|
*/
|
|
30490
30203
|
async doGenerate(options) {
|
|
30491
30204
|
try {
|
|
30492
|
-
const {
|
|
30205
|
+
const { messages, orchestrationConfig, warnings } = this.buildOrchestrationConfig(options);
|
|
30493
30206
|
const client = this.createClient(orchestrationConfig);
|
|
30494
30207
|
const promptTemplating = orchestrationConfig.promptTemplating;
|
|
30495
30208
|
const requestBody = {
|
|
@@ -30506,6 +30219,14 @@ var SAPAIChatLanguageModel = class {
|
|
|
30506
30219
|
...(() => {
|
|
30507
30220
|
const filtering = orchestrationConfig.filtering;
|
|
30508
30221
|
return filtering && Object.keys(filtering).length > 0 ? { filtering } : {};
|
|
30222
|
+
})(),
|
|
30223
|
+
...(() => {
|
|
30224
|
+
const grounding = orchestrationConfig.grounding;
|
|
30225
|
+
return grounding && Object.keys(grounding).length > 0 ? { grounding } : {};
|
|
30226
|
+
})(),
|
|
30227
|
+
...(() => {
|
|
30228
|
+
const translation = orchestrationConfig.translation;
|
|
30229
|
+
return translation && Object.keys(translation).length > 0 ? { translation } : {};
|
|
30509
30230
|
})()
|
|
30510
30231
|
};
|
|
30511
30232
|
const response = await (async () => {
|
|
@@ -30556,18 +30277,18 @@ var SAPAIChatLanguageModel = class {
|
|
|
30556
30277
|
const textContent = response.getContent();
|
|
30557
30278
|
if (textContent) {
|
|
30558
30279
|
content.push({
|
|
30559
|
-
|
|
30560
|
-
|
|
30280
|
+
text: textContent,
|
|
30281
|
+
type: "text"
|
|
30561
30282
|
});
|
|
30562
30283
|
}
|
|
30563
30284
|
const toolCalls = response.getToolCalls();
|
|
30564
30285
|
if (toolCalls) {
|
|
30565
30286
|
for (const toolCall of toolCalls) {
|
|
30566
30287
|
content.push({
|
|
30567
|
-
|
|
30288
|
+
input: toolCall.function.arguments,
|
|
30568
30289
|
toolCallId: toolCall.id,
|
|
30569
30290
|
toolName: toolCall.function.name,
|
|
30570
|
-
|
|
30291
|
+
type: "tool-call"
|
|
30571
30292
|
});
|
|
30572
30293
|
}
|
|
30573
30294
|
}
|
|
@@ -30576,26 +30297,13 @@ var SAPAIChatLanguageModel = class {
|
|
|
30576
30297
|
const finishReason = mapFinishReason(finishReasonRaw);
|
|
30577
30298
|
const rawResponseBody = {
|
|
30578
30299
|
content: textContent,
|
|
30579
|
-
|
|
30300
|
+
finishReason: finishReasonRaw,
|
|
30580
30301
|
tokenUsage,
|
|
30581
|
-
|
|
30302
|
+
toolCalls
|
|
30582
30303
|
};
|
|
30583
30304
|
return {
|
|
30584
30305
|
content,
|
|
30585
30306
|
finishReason,
|
|
30586
|
-
usage: {
|
|
30587
|
-
inputTokens: {
|
|
30588
|
-
total: tokenUsage.prompt_tokens,
|
|
30589
|
-
noCache: tokenUsage.prompt_tokens,
|
|
30590
|
-
cacheRead: void 0,
|
|
30591
|
-
cacheWrite: void 0
|
|
30592
|
-
},
|
|
30593
|
-
outputTokens: {
|
|
30594
|
-
total: tokenUsage.completion_tokens,
|
|
30595
|
-
text: tokenUsage.completion_tokens,
|
|
30596
|
-
reasoning: void 0
|
|
30597
|
-
}
|
|
30598
|
-
},
|
|
30599
30307
|
providerMetadata: {
|
|
30600
30308
|
"sap-ai": {
|
|
30601
30309
|
finishReason: finishReasonRaw ?? "unknown",
|
|
@@ -30607,18 +30315,31 @@ var SAPAIChatLanguageModel = class {
|
|
|
30607
30315
|
body: requestBody
|
|
30608
30316
|
},
|
|
30609
30317
|
response: {
|
|
30610
|
-
|
|
30611
|
-
modelId: this.modelId,
|
|
30318
|
+
body: rawResponseBody,
|
|
30612
30319
|
headers: responseHeaders,
|
|
30613
|
-
|
|
30320
|
+
modelId: this.modelId,
|
|
30321
|
+
timestamp: /* @__PURE__ */ new Date()
|
|
30322
|
+
},
|
|
30323
|
+
usage: {
|
|
30324
|
+
inputTokens: {
|
|
30325
|
+
cacheRead: void 0,
|
|
30326
|
+
cacheWrite: void 0,
|
|
30327
|
+
noCache: tokenUsage.prompt_tokens,
|
|
30328
|
+
total: tokenUsage.prompt_tokens
|
|
30329
|
+
},
|
|
30330
|
+
outputTokens: {
|
|
30331
|
+
reasoning: void 0,
|
|
30332
|
+
text: tokenUsage.completion_tokens,
|
|
30333
|
+
total: tokenUsage.completion_tokens
|
|
30334
|
+
}
|
|
30614
30335
|
},
|
|
30615
30336
|
warnings
|
|
30616
30337
|
};
|
|
30617
30338
|
} catch (error) {
|
|
30618
30339
|
throw convertToAISDKError(error, {
|
|
30619
30340
|
operation: "doGenerate",
|
|
30620
|
-
|
|
30621
|
-
|
|
30341
|
+
requestBody: createAISDKRequestBodySummary(options),
|
|
30342
|
+
url: "sap-ai:orchestration"
|
|
30622
30343
|
});
|
|
30623
30344
|
}
|
|
30624
30345
|
}
|
|
@@ -30647,6 +30368,8 @@ var SAPAIChatLanguageModel = class {
|
|
|
30647
30368
|
* - Usage format: `{ inputTokens: { total, ... }, outputTokens: { total, ... } }`
|
|
30648
30369
|
* - Warnings only in `stream-start` event
|
|
30649
30370
|
*
|
|
30371
|
+
* @see {@link https://sdk.vercel.ai/docs/ai-sdk-core/streaming Vercel AI SDK Streaming}
|
|
30372
|
+
*
|
|
30650
30373
|
* @param options - Streaming options including prompt, tools, and settings
|
|
30651
30374
|
* @returns Promise resolving to stream and request metadata
|
|
30652
30375
|
*
|
|
@@ -30672,7 +30395,7 @@ var SAPAIChatLanguageModel = class {
|
|
|
30672
30395
|
*/
|
|
30673
30396
|
async doStream(options) {
|
|
30674
30397
|
try {
|
|
30675
|
-
const {
|
|
30398
|
+
const { messages, orchestrationConfig, warnings } = this.buildOrchestrationConfig(options);
|
|
30676
30399
|
const client = this.createClient(orchestrationConfig);
|
|
30677
30400
|
const promptTemplating = orchestrationConfig.promptTemplating;
|
|
30678
30401
|
const requestBody = {
|
|
@@ -30699,25 +30422,25 @@ var SAPAIChatLanguageModel = class {
|
|
|
30699
30422
|
const idGenerator = new StreamIdGenerator();
|
|
30700
30423
|
let textBlockId = null;
|
|
30701
30424
|
const streamState = {
|
|
30425
|
+
activeText: false,
|
|
30702
30426
|
finishReason: {
|
|
30703
|
-
|
|
30704
|
-
|
|
30427
|
+
raw: void 0,
|
|
30428
|
+
unified: "other"
|
|
30705
30429
|
},
|
|
30430
|
+
isFirstChunk: true,
|
|
30706
30431
|
usage: {
|
|
30707
30432
|
inputTokens: {
|
|
30708
|
-
total: void 0,
|
|
30709
|
-
noCache: void 0,
|
|
30710
30433
|
cacheRead: void 0,
|
|
30711
|
-
cacheWrite: void 0
|
|
30434
|
+
cacheWrite: void 0,
|
|
30435
|
+
noCache: void 0,
|
|
30436
|
+
total: void 0
|
|
30712
30437
|
},
|
|
30713
30438
|
outputTokens: {
|
|
30714
|
-
|
|
30439
|
+
reasoning: void 0,
|
|
30715
30440
|
text: void 0,
|
|
30716
|
-
|
|
30441
|
+
total: void 0
|
|
30717
30442
|
}
|
|
30718
|
-
}
|
|
30719
|
-
isFirstChunk: true,
|
|
30720
|
-
activeText: false
|
|
30443
|
+
}
|
|
30721
30444
|
};
|
|
30722
30445
|
const toolCallsInProgress = /* @__PURE__ */ new Map();
|
|
30723
30446
|
const sdkStream = streamResponse.stream;
|
|
@@ -30725,6 +30448,11 @@ var SAPAIChatLanguageModel = class {
|
|
|
30725
30448
|
const warningsSnapshot = [...warnings];
|
|
30726
30449
|
const warningsOut = [...warningsSnapshot];
|
|
30727
30450
|
const transformedStream = new ReadableStream({
|
|
30451
|
+
cancel(reason) {
|
|
30452
|
+
if (reason) {
|
|
30453
|
+
console.debug("SAP AI stream cancelled:", reason);
|
|
30454
|
+
}
|
|
30455
|
+
},
|
|
30728
30456
|
async start(controller) {
|
|
30729
30457
|
controller.enqueue({
|
|
30730
30458
|
type: "stream-start",
|
|
@@ -30735,30 +30463,30 @@ var SAPAIChatLanguageModel = class {
|
|
|
30735
30463
|
if (streamState.isFirstChunk) {
|
|
30736
30464
|
streamState.isFirstChunk = false;
|
|
30737
30465
|
controller.enqueue({
|
|
30738
|
-
type: "response-metadata",
|
|
30739
30466
|
modelId,
|
|
30740
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
30467
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
30468
|
+
type: "response-metadata"
|
|
30741
30469
|
});
|
|
30742
30470
|
}
|
|
30743
30471
|
const deltaToolCalls = chunk.getDeltaToolCalls();
|
|
30744
30472
|
if (Array.isArray(deltaToolCalls) && deltaToolCalls.length > 0) {
|
|
30745
30473
|
streamState.finishReason = {
|
|
30746
|
-
|
|
30747
|
-
|
|
30474
|
+
raw: void 0,
|
|
30475
|
+
unified: "tool-calls"
|
|
30748
30476
|
};
|
|
30749
30477
|
}
|
|
30750
30478
|
const deltaContent = chunk.getDeltaContent();
|
|
30751
30479
|
if (typeof deltaContent === "string" && deltaContent.length > 0 && streamState.finishReason.unified !== "tool-calls") {
|
|
30752
30480
|
if (!streamState.activeText) {
|
|
30753
30481
|
textBlockId = idGenerator.generateTextBlockId();
|
|
30754
|
-
controller.enqueue({ type: "text-start"
|
|
30482
|
+
controller.enqueue({ id: textBlockId, type: "text-start" });
|
|
30755
30483
|
streamState.activeText = true;
|
|
30756
30484
|
}
|
|
30757
30485
|
if (textBlockId) {
|
|
30758
30486
|
controller.enqueue({
|
|
30759
|
-
|
|
30487
|
+
delta: deltaContent,
|
|
30760
30488
|
id: textBlockId,
|
|
30761
|
-
|
|
30489
|
+
type: "text-delta"
|
|
30762
30490
|
});
|
|
30763
30491
|
}
|
|
30764
30492
|
}
|
|
@@ -30770,11 +30498,11 @@ var SAPAIChatLanguageModel = class {
|
|
|
30770
30498
|
}
|
|
30771
30499
|
if (!toolCallsInProgress.has(index)) {
|
|
30772
30500
|
toolCallsInProgress.set(index, {
|
|
30773
|
-
id: toolCallChunk.id ?? `tool_${String(index)}`,
|
|
30774
|
-
toolName: toolCallChunk.function?.name,
|
|
30775
30501
|
arguments: "",
|
|
30502
|
+
didEmitCall: false,
|
|
30776
30503
|
didEmitInputStart: false,
|
|
30777
|
-
|
|
30504
|
+
id: toolCallChunk.id ?? `tool_${String(index)}`,
|
|
30505
|
+
toolName: toolCallChunk.function?.name
|
|
30778
30506
|
});
|
|
30779
30507
|
}
|
|
30780
30508
|
const tc = toolCallsInProgress.get(index);
|
|
@@ -30789,9 +30517,9 @@ var SAPAIChatLanguageModel = class {
|
|
|
30789
30517
|
if (!tc.didEmitInputStart && tc.toolName) {
|
|
30790
30518
|
tc.didEmitInputStart = true;
|
|
30791
30519
|
controller.enqueue({
|
|
30792
|
-
type: "tool-input-start",
|
|
30793
30520
|
id: tc.id,
|
|
30794
|
-
toolName: tc.toolName
|
|
30521
|
+
toolName: tc.toolName,
|
|
30522
|
+
type: "tool-input-start"
|
|
30795
30523
|
});
|
|
30796
30524
|
}
|
|
30797
30525
|
const argumentsDelta = toolCallChunk.function?.arguments;
|
|
@@ -30799,9 +30527,9 @@ var SAPAIChatLanguageModel = class {
|
|
|
30799
30527
|
tc.arguments += argumentsDelta;
|
|
30800
30528
|
if (tc.didEmitInputStart) {
|
|
30801
30529
|
controller.enqueue({
|
|
30802
|
-
|
|
30530
|
+
delta: argumentsDelta,
|
|
30803
30531
|
id: tc.id,
|
|
30804
|
-
|
|
30532
|
+
type: "tool-input-delta"
|
|
30805
30533
|
});
|
|
30806
30534
|
}
|
|
30807
30535
|
}
|
|
@@ -30819,28 +30547,28 @@ var SAPAIChatLanguageModel = class {
|
|
|
30819
30547
|
if (!tc.didEmitInputStart) {
|
|
30820
30548
|
tc.didEmitInputStart = true;
|
|
30821
30549
|
controller.enqueue({
|
|
30822
|
-
type: "tool-input-start",
|
|
30823
30550
|
id: tc.id,
|
|
30824
|
-
toolName: tc.toolName ?? ""
|
|
30551
|
+
toolName: tc.toolName ?? "",
|
|
30552
|
+
type: "tool-input-start"
|
|
30825
30553
|
});
|
|
30826
30554
|
}
|
|
30827
30555
|
if (!tc.toolName) {
|
|
30828
30556
|
warningsOut.push({
|
|
30829
|
-
|
|
30830
|
-
|
|
30557
|
+
message: "Received tool-call delta without a tool name. Emitting tool-call with an empty tool name.",
|
|
30558
|
+
type: "other"
|
|
30831
30559
|
});
|
|
30832
30560
|
}
|
|
30833
30561
|
tc.didEmitCall = true;
|
|
30834
|
-
controller.enqueue({ type: "tool-input-end"
|
|
30562
|
+
controller.enqueue({ id: tc.id, type: "tool-input-end" });
|
|
30835
30563
|
controller.enqueue({
|
|
30836
|
-
|
|
30564
|
+
input: tc.arguments,
|
|
30837
30565
|
toolCallId: tc.id,
|
|
30838
30566
|
toolName: tc.toolName ?? "",
|
|
30839
|
-
|
|
30567
|
+
type: "tool-call"
|
|
30840
30568
|
});
|
|
30841
30569
|
}
|
|
30842
30570
|
if (streamState.activeText && textBlockId) {
|
|
30843
|
-
controller.enqueue({ type: "text-end"
|
|
30571
|
+
controller.enqueue({ id: textBlockId, type: "text-end" });
|
|
30844
30572
|
streamState.activeText = false;
|
|
30845
30573
|
}
|
|
30846
30574
|
}
|
|
@@ -30855,109 +30583,399 @@ var SAPAIChatLanguageModel = class {
|
|
|
30855
30583
|
if (!tc.didEmitInputStart) {
|
|
30856
30584
|
tc.didEmitInputStart = true;
|
|
30857
30585
|
controller.enqueue({
|
|
30858
|
-
type: "tool-input-start",
|
|
30859
30586
|
id: tc.id,
|
|
30860
|
-
toolName: tc.toolName ?? ""
|
|
30587
|
+
toolName: tc.toolName ?? "",
|
|
30588
|
+
type: "tool-input-start"
|
|
30861
30589
|
});
|
|
30862
30590
|
}
|
|
30863
30591
|
if (!tc.toolName) {
|
|
30864
30592
|
warningsOut.push({
|
|
30865
|
-
|
|
30866
|
-
|
|
30593
|
+
message: "Received tool-call delta without a tool name. Emitting tool-call with an empty tool name.",
|
|
30594
|
+
type: "other"
|
|
30867
30595
|
});
|
|
30868
30596
|
}
|
|
30869
30597
|
didEmitAnyToolCalls = true;
|
|
30870
30598
|
tc.didEmitCall = true;
|
|
30871
|
-
controller.enqueue({ type: "tool-input-end"
|
|
30599
|
+
controller.enqueue({ id: tc.id, type: "tool-input-end" });
|
|
30872
30600
|
controller.enqueue({
|
|
30873
|
-
|
|
30601
|
+
input: tc.arguments,
|
|
30874
30602
|
toolCallId: tc.id,
|
|
30875
30603
|
toolName: tc.toolName ?? "",
|
|
30876
|
-
|
|
30604
|
+
type: "tool-call"
|
|
30877
30605
|
});
|
|
30878
30606
|
}
|
|
30879
30607
|
if (streamState.activeText && textBlockId) {
|
|
30880
|
-
controller.enqueue({ type: "text-end"
|
|
30608
|
+
controller.enqueue({ id: textBlockId, type: "text-end" });
|
|
30881
30609
|
}
|
|
30882
30610
|
const finalFinishReason = streamResponse.getFinishReason();
|
|
30883
30611
|
if (finalFinishReason) {
|
|
30884
30612
|
streamState.finishReason = mapFinishReason(finalFinishReason);
|
|
30885
30613
|
} else if (didEmitAnyToolCalls) {
|
|
30886
30614
|
streamState.finishReason = {
|
|
30887
|
-
|
|
30888
|
-
|
|
30615
|
+
raw: void 0,
|
|
30616
|
+
unified: "tool-calls"
|
|
30889
30617
|
};
|
|
30890
30618
|
}
|
|
30891
|
-
const finalUsage = streamResponse.getTokenUsage();
|
|
30892
|
-
if (finalUsage) {
|
|
30893
|
-
streamState.usage.inputTokens.total = finalUsage.prompt_tokens;
|
|
30894
|
-
streamState.usage.inputTokens.noCache = finalUsage.prompt_tokens;
|
|
30895
|
-
streamState.usage.outputTokens.total = finalUsage.completion_tokens;
|
|
30896
|
-
streamState.usage.outputTokens.text = finalUsage.completion_tokens;
|
|
30619
|
+
const finalUsage = streamResponse.getTokenUsage();
|
|
30620
|
+
if (finalUsage) {
|
|
30621
|
+
streamState.usage.inputTokens.total = finalUsage.prompt_tokens;
|
|
30622
|
+
streamState.usage.inputTokens.noCache = finalUsage.prompt_tokens;
|
|
30623
|
+
streamState.usage.outputTokens.total = finalUsage.completion_tokens;
|
|
30624
|
+
streamState.usage.outputTokens.text = finalUsage.completion_tokens;
|
|
30625
|
+
}
|
|
30626
|
+
controller.enqueue({
|
|
30627
|
+
finishReason: streamState.finishReason,
|
|
30628
|
+
type: "finish",
|
|
30629
|
+
usage: streamState.usage
|
|
30630
|
+
});
|
|
30631
|
+
controller.close();
|
|
30632
|
+
} catch (error) {
|
|
30633
|
+
const aiError = convertToAISDKError(error, {
|
|
30634
|
+
operation: "doStream",
|
|
30635
|
+
requestBody: createAISDKRequestBodySummary(options),
|
|
30636
|
+
url: "sap-ai:orchestration"
|
|
30637
|
+
});
|
|
30638
|
+
controller.enqueue({
|
|
30639
|
+
error: aiError instanceof Error ? aiError : new Error(String(aiError)),
|
|
30640
|
+
type: "error"
|
|
30641
|
+
});
|
|
30642
|
+
controller.close();
|
|
30643
|
+
}
|
|
30644
|
+
}
|
|
30645
|
+
});
|
|
30646
|
+
return {
|
|
30647
|
+
request: {
|
|
30648
|
+
body: requestBody
|
|
30649
|
+
},
|
|
30650
|
+
stream: transformedStream
|
|
30651
|
+
};
|
|
30652
|
+
} catch (error) {
|
|
30653
|
+
throw convertToAISDKError(error, {
|
|
30654
|
+
operation: "doStream",
|
|
30655
|
+
requestBody: createAISDKRequestBodySummary(options),
|
|
30656
|
+
url: "sap-ai:orchestration"
|
|
30657
|
+
});
|
|
30658
|
+
}
|
|
30659
|
+
}
|
|
30660
|
+
/**
|
|
30661
|
+
* Checks if a URL is supported for file/image uploads.
|
|
30662
|
+
*
|
|
30663
|
+
* @param url - The URL to check
|
|
30664
|
+
* @returns True if the URL protocol is HTTPS or data with valid image format
|
|
30665
|
+
*/
|
|
30666
|
+
supportsUrl(url) {
|
|
30667
|
+
if (url.protocol === "https:") return true;
|
|
30668
|
+
if (url.protocol === "data:") {
|
|
30669
|
+
return /^data:image\//i.test(url.href);
|
|
30670
|
+
}
|
|
30671
|
+
return false;
|
|
30672
|
+
}
|
|
30673
|
+
/**
|
|
30674
|
+
* Builds orchestration module config for SAP AI SDK.
|
|
30675
|
+
*
|
|
30676
|
+
* @param options - Call options from the AI SDK
|
|
30677
|
+
* @returns Object containing orchestration config, messages, and warnings
|
|
30678
|
+
* @internal
|
|
30679
|
+
*/
|
|
30680
|
+
buildOrchestrationConfig(options) {
|
|
30681
|
+
const providerOptions = options.providerOptions?.sap ?? {};
|
|
30682
|
+
const warnings = [];
|
|
30683
|
+
const messages = convertToSAPMessages(options.prompt, {
|
|
30684
|
+
includeReasoning: providerOptions.includeReasoning ?? this.settings.includeReasoning ?? false
|
|
30685
|
+
});
|
|
30686
|
+
let tools;
|
|
30687
|
+
const settingsTools = providerOptions.tools ?? this.settings.tools;
|
|
30688
|
+
const optionsTools = options.tools;
|
|
30689
|
+
const shouldUseSettingsTools = settingsTools && settingsTools.length > 0 && (!optionsTools || optionsTools.length === 0);
|
|
30690
|
+
const shouldUseOptionsTools = !!(optionsTools && optionsTools.length > 0);
|
|
30691
|
+
if (settingsTools && settingsTools.length > 0 && optionsTools && optionsTools.length > 0) {
|
|
30692
|
+
warnings.push({
|
|
30693
|
+
message: "Both settings.tools and call options.tools were provided; preferring call options.tools.",
|
|
30694
|
+
type: "other"
|
|
30695
|
+
});
|
|
30696
|
+
}
|
|
30697
|
+
if (shouldUseSettingsTools) {
|
|
30698
|
+
tools = settingsTools;
|
|
30699
|
+
} else {
|
|
30700
|
+
const availableTools = shouldUseOptionsTools ? optionsTools : void 0;
|
|
30701
|
+
tools = availableTools?.map((tool) => {
|
|
30702
|
+
if (tool.type === "function") {
|
|
30703
|
+
const inputSchema = tool.inputSchema;
|
|
30704
|
+
const toolWithParams = tool;
|
|
30705
|
+
let parameters;
|
|
30706
|
+
if (toolWithParams.parameters && isZodSchema(toolWithParams.parameters)) {
|
|
30707
|
+
try {
|
|
30708
|
+
const jsonSchema = zodToJsonSchema(
|
|
30709
|
+
toolWithParams.parameters,
|
|
30710
|
+
{
|
|
30711
|
+
$refStrategy: "none"
|
|
30712
|
+
}
|
|
30713
|
+
);
|
|
30714
|
+
const schemaRecord = jsonSchema;
|
|
30715
|
+
delete schemaRecord.$schema;
|
|
30716
|
+
parameters = buildSAPToolParameters(schemaRecord);
|
|
30717
|
+
} catch (error) {
|
|
30718
|
+
warnings.push({
|
|
30719
|
+
details: `Failed to convert tool Zod schema: ${error instanceof Error ? error.message : String(error)}. Falling back to empty object schema.`,
|
|
30720
|
+
feature: `tool schema conversion for ${tool.name}`,
|
|
30721
|
+
type: "unsupported"
|
|
30722
|
+
});
|
|
30723
|
+
parameters = buildSAPToolParameters({});
|
|
30724
|
+
}
|
|
30725
|
+
} else if (inputSchema && Object.keys(inputSchema).length > 0) {
|
|
30726
|
+
const hasProperties = inputSchema.properties && typeof inputSchema.properties === "object" && Object.keys(inputSchema.properties).length > 0;
|
|
30727
|
+
if (hasProperties) {
|
|
30728
|
+
parameters = buildSAPToolParameters(inputSchema);
|
|
30729
|
+
} else {
|
|
30730
|
+
parameters = buildSAPToolParameters({});
|
|
30897
30731
|
}
|
|
30898
|
-
|
|
30899
|
-
|
|
30900
|
-
finishReason: streamState.finishReason,
|
|
30901
|
-
usage: streamState.usage
|
|
30902
|
-
});
|
|
30903
|
-
controller.close();
|
|
30904
|
-
} catch (error) {
|
|
30905
|
-
const aiError = convertToAISDKError(error, {
|
|
30906
|
-
operation: "doStream",
|
|
30907
|
-
url: "sap-ai:orchestration",
|
|
30908
|
-
requestBody: createAISDKRequestBodySummary(options)
|
|
30909
|
-
});
|
|
30910
|
-
controller.enqueue({
|
|
30911
|
-
type: "error",
|
|
30912
|
-
error: aiError instanceof Error ? aiError : new Error(String(aiError))
|
|
30913
|
-
});
|
|
30914
|
-
controller.close();
|
|
30915
|
-
}
|
|
30916
|
-
},
|
|
30917
|
-
cancel(reason) {
|
|
30918
|
-
if (reason) {
|
|
30919
|
-
console.debug("SAP AI stream cancelled:", reason);
|
|
30732
|
+
} else {
|
|
30733
|
+
parameters = buildSAPToolParameters({});
|
|
30920
30734
|
}
|
|
30735
|
+
return {
|
|
30736
|
+
function: {
|
|
30737
|
+
description: tool.description,
|
|
30738
|
+
name: tool.name,
|
|
30739
|
+
parameters
|
|
30740
|
+
},
|
|
30741
|
+
type: "function"
|
|
30742
|
+
};
|
|
30743
|
+
} else {
|
|
30744
|
+
warnings.push({
|
|
30745
|
+
details: "Only 'function' tool type is supported.",
|
|
30746
|
+
feature: `tool type for ${tool.name}`,
|
|
30747
|
+
type: "unsupported"
|
|
30748
|
+
});
|
|
30749
|
+
return null;
|
|
30921
30750
|
}
|
|
30751
|
+
}).filter((t) => t !== null);
|
|
30752
|
+
}
|
|
30753
|
+
const supportsN = !this.modelId.startsWith("amazon--") && !this.modelId.startsWith("anthropic--");
|
|
30754
|
+
const modelParams = {};
|
|
30755
|
+
const maxTokens = options.maxOutputTokens ?? providerOptions.modelParams?.maxTokens ?? this.settings.modelParams?.maxTokens;
|
|
30756
|
+
if (maxTokens !== void 0) modelParams.max_tokens = maxTokens;
|
|
30757
|
+
const temperature = options.temperature ?? providerOptions.modelParams?.temperature ?? this.settings.modelParams?.temperature;
|
|
30758
|
+
if (temperature !== void 0) modelParams.temperature = temperature;
|
|
30759
|
+
const topP = options.topP ?? providerOptions.modelParams?.topP ?? this.settings.modelParams?.topP;
|
|
30760
|
+
if (topP !== void 0) modelParams.top_p = topP;
|
|
30761
|
+
if (options.topK !== void 0) modelParams.top_k = options.topK;
|
|
30762
|
+
const frequencyPenalty = options.frequencyPenalty ?? providerOptions.modelParams?.frequencyPenalty ?? this.settings.modelParams?.frequencyPenalty;
|
|
30763
|
+
if (frequencyPenalty !== void 0) {
|
|
30764
|
+
modelParams.frequency_penalty = frequencyPenalty;
|
|
30765
|
+
}
|
|
30766
|
+
const presencePenalty = options.presencePenalty ?? providerOptions.modelParams?.presencePenalty ?? this.settings.modelParams?.presencePenalty;
|
|
30767
|
+
if (presencePenalty !== void 0) {
|
|
30768
|
+
modelParams.presence_penalty = presencePenalty;
|
|
30769
|
+
}
|
|
30770
|
+
if (supportsN) {
|
|
30771
|
+
const nValue = providerOptions.modelParams?.n ?? this.settings.modelParams?.n;
|
|
30772
|
+
if (nValue !== void 0) {
|
|
30773
|
+
modelParams.n = nValue;
|
|
30774
|
+
}
|
|
30775
|
+
}
|
|
30776
|
+
const parallelToolCalls = providerOptions.modelParams?.parallel_tool_calls ?? this.settings.modelParams?.parallel_tool_calls;
|
|
30777
|
+
if (parallelToolCalls !== void 0) {
|
|
30778
|
+
modelParams.parallel_tool_calls = parallelToolCalls;
|
|
30779
|
+
}
|
|
30780
|
+
if (options.stopSequences && options.stopSequences.length > 0) {
|
|
30781
|
+
modelParams.stop = options.stopSequences;
|
|
30782
|
+
}
|
|
30783
|
+
if (options.seed !== void 0) {
|
|
30784
|
+
modelParams.seed = options.seed;
|
|
30785
|
+
}
|
|
30786
|
+
validateModelParameters(
|
|
30787
|
+
{
|
|
30788
|
+
frequencyPenalty,
|
|
30789
|
+
maxTokens,
|
|
30790
|
+
n: modelParams.n,
|
|
30791
|
+
presencePenalty,
|
|
30792
|
+
temperature,
|
|
30793
|
+
topP
|
|
30794
|
+
},
|
|
30795
|
+
warnings
|
|
30796
|
+
);
|
|
30797
|
+
if (options.toolChoice && options.toolChoice.type !== "auto") {
|
|
30798
|
+
warnings.push({
|
|
30799
|
+
details: `SAP AI SDK does not support toolChoice '${options.toolChoice.type}'. Using default 'auto' behavior.`,
|
|
30800
|
+
feature: "toolChoice",
|
|
30801
|
+
type: "unsupported"
|
|
30922
30802
|
});
|
|
30923
|
-
|
|
30924
|
-
|
|
30925
|
-
|
|
30926
|
-
|
|
30927
|
-
|
|
30928
|
-
};
|
|
30929
|
-
} catch (error) {
|
|
30930
|
-
throw convertToAISDKError(error, {
|
|
30931
|
-
operation: "doStream",
|
|
30932
|
-
url: "sap-ai:orchestration",
|
|
30933
|
-
requestBody: createAISDKRequestBodySummary(options)
|
|
30803
|
+
}
|
|
30804
|
+
if (options.responseFormat?.type === "json") {
|
|
30805
|
+
warnings.push({
|
|
30806
|
+
message: "responseFormat JSON mode is forwarded to the underlying model; support and schema adherence depend on the model/deployment.",
|
|
30807
|
+
type: "other"
|
|
30934
30808
|
});
|
|
30935
30809
|
}
|
|
30810
|
+
const responseFormat = options.responseFormat?.type === "json" ? options.responseFormat.schema ? {
|
|
30811
|
+
json_schema: {
|
|
30812
|
+
description: options.responseFormat.description,
|
|
30813
|
+
name: options.responseFormat.name ?? "response",
|
|
30814
|
+
schema: options.responseFormat.schema,
|
|
30815
|
+
strict: null
|
|
30816
|
+
},
|
|
30817
|
+
type: "json_schema"
|
|
30818
|
+
} : { type: "json_object" } : void 0;
|
|
30819
|
+
const orchestrationConfig = {
|
|
30820
|
+
promptTemplating: {
|
|
30821
|
+
model: {
|
|
30822
|
+
name: this.modelId,
|
|
30823
|
+
params: modelParams,
|
|
30824
|
+
version: providerOptions.modelVersion ?? this.settings.modelVersion ?? "latest"
|
|
30825
|
+
},
|
|
30826
|
+
prompt: {
|
|
30827
|
+
template: [],
|
|
30828
|
+
tools: tools && tools.length > 0 ? tools : void 0,
|
|
30829
|
+
...responseFormat ? { response_format: responseFormat } : {}
|
|
30830
|
+
}
|
|
30831
|
+
},
|
|
30832
|
+
...(() => {
|
|
30833
|
+
const masking = providerOptions.masking ?? this.settings.masking;
|
|
30834
|
+
return masking && Object.keys(masking).length > 0 ? { masking } : {};
|
|
30835
|
+
})(),
|
|
30836
|
+
...(() => {
|
|
30837
|
+
const filtering = providerOptions.filtering ?? this.settings.filtering;
|
|
30838
|
+
return filtering && Object.keys(filtering).length > 0 ? { filtering } : {};
|
|
30839
|
+
})(),
|
|
30840
|
+
...(() => {
|
|
30841
|
+
const grounding = providerOptions.grounding ?? this.settings.grounding;
|
|
30842
|
+
return grounding && Object.keys(grounding).length > 0 ? { grounding } : {};
|
|
30843
|
+
})(),
|
|
30844
|
+
...(() => {
|
|
30845
|
+
const translation = providerOptions.translation ?? this.settings.translation;
|
|
30846
|
+
return translation && Object.keys(translation).length > 0 ? { translation } : {};
|
|
30847
|
+
})()
|
|
30848
|
+
};
|
|
30849
|
+
return { messages, orchestrationConfig, warnings };
|
|
30850
|
+
}
|
|
30851
|
+
/**
|
|
30852
|
+
* Creates an OrchestrationClient instance.
|
|
30853
|
+
*
|
|
30854
|
+
* @param config - Orchestration module configuration
|
|
30855
|
+
* @returns OrchestrationClient instance
|
|
30856
|
+
* @internal
|
|
30857
|
+
*/
|
|
30858
|
+
createClient(config) {
|
|
30859
|
+
return new OrchestrationClient(
|
|
30860
|
+
config,
|
|
30861
|
+
this.config.deploymentConfig,
|
|
30862
|
+
this.config.destination
|
|
30863
|
+
);
|
|
30936
30864
|
}
|
|
30937
30865
|
};
|
|
30866
|
+
function buildSAPToolParameters(schema) {
|
|
30867
|
+
const schemaType = schema.type;
|
|
30868
|
+
if (schemaType !== void 0 && schemaType !== "object") {
|
|
30869
|
+
return {
|
|
30870
|
+
properties: {},
|
|
30871
|
+
required: [],
|
|
30872
|
+
type: "object"
|
|
30873
|
+
};
|
|
30874
|
+
}
|
|
30875
|
+
const properties = schema.properties && typeof schema.properties === "object" ? schema.properties : {};
|
|
30876
|
+
const required = Array.isArray(schema.required) && schema.required.every((item) => typeof item === "string") ? schema.required : [];
|
|
30877
|
+
const additionalFields = Object.fromEntries(
|
|
30878
|
+
Object.entries(schema).filter(
|
|
30879
|
+
([key]) => key !== "type" && key !== "properties" && key !== "required"
|
|
30880
|
+
)
|
|
30881
|
+
);
|
|
30882
|
+
return {
|
|
30883
|
+
properties,
|
|
30884
|
+
required,
|
|
30885
|
+
type: "object",
|
|
30886
|
+
...additionalFields
|
|
30887
|
+
};
|
|
30888
|
+
}
|
|
30889
|
+
function createAISDKRequestBodySummary(options) {
|
|
30890
|
+
return {
|
|
30891
|
+
hasImageParts: options.prompt.some(
|
|
30892
|
+
(message) => message.role === "user" && message.content.some(
|
|
30893
|
+
(part) => part.type === "file" && part.mediaType.startsWith("image/")
|
|
30894
|
+
)
|
|
30895
|
+
),
|
|
30896
|
+
maxOutputTokens: options.maxOutputTokens,
|
|
30897
|
+
promptMessages: options.prompt.length,
|
|
30898
|
+
responseFormatType: options.responseFormat?.type,
|
|
30899
|
+
seed: options.seed,
|
|
30900
|
+
stopSequences: options.stopSequences?.length,
|
|
30901
|
+
temperature: options.temperature,
|
|
30902
|
+
toolChoiceType: options.toolChoice?.type,
|
|
30903
|
+
tools: options.tools?.length ?? 0,
|
|
30904
|
+
topK: options.topK,
|
|
30905
|
+
topP: options.topP
|
|
30906
|
+
};
|
|
30907
|
+
}
|
|
30908
|
+
function hasCallableParse(obj) {
|
|
30909
|
+
return typeof obj.parse === "function";
|
|
30910
|
+
}
|
|
30911
|
+
function isZodSchema(obj) {
|
|
30912
|
+
if (obj === null || typeof obj !== "object") {
|
|
30913
|
+
return false;
|
|
30914
|
+
}
|
|
30915
|
+
const record = obj;
|
|
30916
|
+
return "_def" in record && "parse" in record && hasCallableParse(record);
|
|
30917
|
+
}
|
|
30938
30918
|
function mapFinishReason(reason) {
|
|
30939
30919
|
const raw = reason;
|
|
30940
|
-
if (!reason) return { unified: "other"
|
|
30920
|
+
if (!reason) return { raw, unified: "other" };
|
|
30941
30921
|
switch (reason.toLowerCase()) {
|
|
30942
|
-
case "
|
|
30922
|
+
case "content_filter":
|
|
30923
|
+
return { raw, unified: "content-filter" };
|
|
30943
30924
|
case "end_turn":
|
|
30944
|
-
case "stop_sequence":
|
|
30945
30925
|
case "eos":
|
|
30946
|
-
|
|
30926
|
+
case "stop":
|
|
30927
|
+
case "stop_sequence":
|
|
30928
|
+
return { raw, unified: "stop" };
|
|
30929
|
+
case "error":
|
|
30930
|
+
return { raw, unified: "error" };
|
|
30931
|
+
case "function_call":
|
|
30932
|
+
case "tool_call":
|
|
30933
|
+
case "tool_calls":
|
|
30934
|
+
return { raw, unified: "tool-calls" };
|
|
30947
30935
|
case "length":
|
|
30948
30936
|
case "max_tokens":
|
|
30949
30937
|
case "max_tokens_reached":
|
|
30950
|
-
return { unified: "length"
|
|
30951
|
-
case "tool_calls":
|
|
30952
|
-
case "tool_call":
|
|
30953
|
-
case "function_call":
|
|
30954
|
-
return { unified: "tool-calls", raw };
|
|
30955
|
-
case "content_filter":
|
|
30956
|
-
return { unified: "content-filter", raw };
|
|
30957
|
-
case "error":
|
|
30958
|
-
return { unified: "error", raw };
|
|
30938
|
+
return { raw, unified: "length" };
|
|
30959
30939
|
default:
|
|
30960
|
-
return { unified: "other"
|
|
30940
|
+
return { raw, unified: "other" };
|
|
30941
|
+
}
|
|
30942
|
+
}
|
|
30943
|
+
function validateModelParameters(params, warnings) {
|
|
30944
|
+
if (params.temperature !== void 0 && (params.temperature < 0 || params.temperature > 2)) {
|
|
30945
|
+
warnings.push({
|
|
30946
|
+
message: `temperature=${String(params.temperature)} is outside typical range [0, 2]. The API may reject this value.`,
|
|
30947
|
+
type: "other"
|
|
30948
|
+
});
|
|
30949
|
+
}
|
|
30950
|
+
if (params.topP !== void 0 && (params.topP < 0 || params.topP > 1)) {
|
|
30951
|
+
warnings.push({
|
|
30952
|
+
message: `topP=${String(params.topP)} is outside valid range [0, 1]. The API may reject this value.`,
|
|
30953
|
+
type: "other"
|
|
30954
|
+
});
|
|
30955
|
+
}
|
|
30956
|
+
if (params.frequencyPenalty !== void 0 && (params.frequencyPenalty < -2 || params.frequencyPenalty > 2)) {
|
|
30957
|
+
warnings.push({
|
|
30958
|
+
message: `frequencyPenalty=${String(params.frequencyPenalty)} is outside typical range [-2, 2]. The API may reject this value.`,
|
|
30959
|
+
type: "other"
|
|
30960
|
+
});
|
|
30961
|
+
}
|
|
30962
|
+
if (params.presencePenalty !== void 0 && (params.presencePenalty < -2 || params.presencePenalty > 2)) {
|
|
30963
|
+
warnings.push({
|
|
30964
|
+
message: `presencePenalty=${String(params.presencePenalty)} is outside typical range [-2, 2]. The API may reject this value.`,
|
|
30965
|
+
type: "other"
|
|
30966
|
+
});
|
|
30967
|
+
}
|
|
30968
|
+
if (params.maxTokens !== void 0 && params.maxTokens <= 0) {
|
|
30969
|
+
warnings.push({
|
|
30970
|
+
message: `maxTokens=${String(params.maxTokens)} must be positive. The API will likely reject this value.`,
|
|
30971
|
+
type: "other"
|
|
30972
|
+
});
|
|
30973
|
+
}
|
|
30974
|
+
if (params.n !== void 0 && params.n <= 0) {
|
|
30975
|
+
warnings.push({
|
|
30976
|
+
message: `n=${String(params.n)} must be positive. The API will likely reject this value.`,
|
|
30977
|
+
type: "other"
|
|
30978
|
+
});
|
|
30961
30979
|
}
|
|
30962
30980
|
}
|
|
30963
30981
|
|
|
@@ -30975,19 +30993,19 @@ function createSAPAIProvider(options = {}) {
|
|
|
30975
30993
|
const mergedSettings = {
|
|
30976
30994
|
...options.defaultSettings,
|
|
30977
30995
|
...settings,
|
|
30996
|
+
filtering: settings.filtering ?? options.defaultSettings?.filtering,
|
|
30997
|
+
// Complex objects: override, do not merge
|
|
30998
|
+
masking: settings.masking ?? options.defaultSettings?.masking,
|
|
30978
30999
|
modelParams: {
|
|
30979
31000
|
...options.defaultSettings?.modelParams ?? {},
|
|
30980
31001
|
...settings.modelParams ?? {}
|
|
30981
31002
|
},
|
|
30982
|
-
// Complex objects: override, do not merge
|
|
30983
|
-
masking: settings.masking ?? options.defaultSettings?.masking,
|
|
30984
|
-
filtering: settings.filtering ?? options.defaultSettings?.filtering,
|
|
30985
31003
|
tools: settings.tools ?? options.defaultSettings?.tools
|
|
30986
31004
|
};
|
|
30987
|
-
return new
|
|
30988
|
-
provider: "sap-ai",
|
|
31005
|
+
return new SAPAILanguageModel(modelId, mergedSettings, {
|
|
30989
31006
|
deploymentConfig,
|
|
30990
|
-
destination: options.destination
|
|
31007
|
+
destination: options.destination,
|
|
31008
|
+
provider: "sap-ai"
|
|
30991
31009
|
});
|
|
30992
31010
|
};
|
|
30993
31011
|
const provider = function(modelId, settings) {
|
|
@@ -31003,23 +31021,19 @@ function createSAPAIProvider(options = {}) {
|
|
|
31003
31021
|
}
|
|
31004
31022
|
var sapai = createSAPAIProvider();
|
|
31005
31023
|
|
|
31006
|
-
// src/sap-ai-
|
|
31024
|
+
// src/sap-ai-settings.ts
|
|
31007
31025
|
import {
|
|
31008
|
-
buildDpiMaskingProvider,
|
|
31009
31026
|
buildAzureContentSafetyFilter,
|
|
31010
|
-
buildLlamaGuard38BFilter,
|
|
31011
31027
|
buildDocumentGroundingConfig,
|
|
31012
|
-
|
|
31028
|
+
buildDpiMaskingProvider,
|
|
31029
|
+
buildLlamaGuard38BFilter,
|
|
31030
|
+
buildTranslationConfig,
|
|
31031
|
+
isConfigReference
|
|
31013
31032
|
} from "@sap-ai-sdk/orchestration";
|
|
31014
|
-
|
|
31015
|
-
// src/types/completion-request.ts
|
|
31016
|
-
import { isConfigReference } from "@sap-ai-sdk/orchestration";
|
|
31017
|
-
|
|
31018
|
-
// src/types/completion-response.ts
|
|
31019
31033
|
import {
|
|
31020
31034
|
OrchestrationResponse,
|
|
31021
|
-
|
|
31022
|
-
|
|
31035
|
+
OrchestrationStreamChunkResponse,
|
|
31036
|
+
OrchestrationStreamResponse
|
|
31023
31037
|
} from "@sap-ai-sdk/orchestration";
|
|
31024
31038
|
|
|
31025
31039
|
// src/index.ts
|