@jerome-benoit/sap-ai-provider 3.0.0-rc.2 → 3.0.0-rc.4
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/package.json +3 -3
- package/dist/index.d.mts +0 -651
- package/dist/index.mjs +0 -687
- package/dist/index.mjs.map +0 -1
package/dist/index.mjs
DELETED
|
@@ -1,687 +0,0 @@
|
|
|
1
|
-
// src/sap-ai-chat-language-model.ts
|
|
2
|
-
import {
|
|
3
|
-
OrchestrationClient
|
|
4
|
-
} from "@sap-ai-sdk/orchestration";
|
|
5
|
-
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
6
|
-
|
|
7
|
-
// src/convert-to-sap-messages.ts
|
|
8
|
-
import {
|
|
9
|
-
UnsupportedFunctionalityError
|
|
10
|
-
} from "@ai-sdk/provider";
|
|
11
|
-
function convertToSAPMessages(prompt) {
|
|
12
|
-
const messages = [];
|
|
13
|
-
for (const message of prompt) {
|
|
14
|
-
switch (message.role) {
|
|
15
|
-
case "system": {
|
|
16
|
-
const systemMessage = {
|
|
17
|
-
role: "system",
|
|
18
|
-
content: message.content
|
|
19
|
-
};
|
|
20
|
-
messages.push(systemMessage);
|
|
21
|
-
break;
|
|
22
|
-
}
|
|
23
|
-
case "user": {
|
|
24
|
-
const contentParts = [];
|
|
25
|
-
for (const part of message.content) {
|
|
26
|
-
switch (part.type) {
|
|
27
|
-
case "text": {
|
|
28
|
-
contentParts.push({
|
|
29
|
-
type: "text",
|
|
30
|
-
text: part.text
|
|
31
|
-
});
|
|
32
|
-
break;
|
|
33
|
-
}
|
|
34
|
-
case "file": {
|
|
35
|
-
if (!part.mediaType.startsWith("image/")) {
|
|
36
|
-
throw new UnsupportedFunctionalityError({
|
|
37
|
-
functionality: "Only image files are supported"
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
const imageUrl = part.data instanceof URL ? part.data.toString() : `data:${part.mediaType};base64,${String(part.data)}`;
|
|
41
|
-
contentParts.push({
|
|
42
|
-
type: "image_url",
|
|
43
|
-
image_url: {
|
|
44
|
-
url: imageUrl
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
break;
|
|
48
|
-
}
|
|
49
|
-
default: {
|
|
50
|
-
throw new UnsupportedFunctionalityError({
|
|
51
|
-
functionality: `Content type ${part.type}`
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
const userMessage = contentParts.length === 1 && contentParts[0].type === "text" ? {
|
|
57
|
-
role: "user",
|
|
58
|
-
content: contentParts[0].text ?? ""
|
|
59
|
-
} : {
|
|
60
|
-
role: "user",
|
|
61
|
-
content: contentParts
|
|
62
|
-
};
|
|
63
|
-
messages.push(userMessage);
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
66
|
-
case "assistant": {
|
|
67
|
-
let text = "";
|
|
68
|
-
const toolCalls = [];
|
|
69
|
-
for (const part of message.content) {
|
|
70
|
-
switch (part.type) {
|
|
71
|
-
case "text": {
|
|
72
|
-
text += part.text;
|
|
73
|
-
break;
|
|
74
|
-
}
|
|
75
|
-
case "tool-call": {
|
|
76
|
-
toolCalls.push({
|
|
77
|
-
id: part.toolCallId,
|
|
78
|
-
type: "function",
|
|
79
|
-
function: {
|
|
80
|
-
name: part.toolName,
|
|
81
|
-
arguments: JSON.stringify(part.input)
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
const assistantMessage = {
|
|
89
|
-
role: "assistant",
|
|
90
|
-
content: text || "",
|
|
91
|
-
tool_calls: toolCalls.length > 0 ? toolCalls : void 0
|
|
92
|
-
};
|
|
93
|
-
messages.push(assistantMessage);
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
case "tool": {
|
|
97
|
-
for (const part of message.content) {
|
|
98
|
-
const toolMessage = {
|
|
99
|
-
role: "tool",
|
|
100
|
-
tool_call_id: part.toolCallId,
|
|
101
|
-
content: JSON.stringify(part.output)
|
|
102
|
-
};
|
|
103
|
-
messages.push(toolMessage);
|
|
104
|
-
}
|
|
105
|
-
break;
|
|
106
|
-
}
|
|
107
|
-
default: {
|
|
108
|
-
const _exhaustiveCheck = message;
|
|
109
|
-
throw new Error(
|
|
110
|
-
`Unsupported role: ${_exhaustiveCheck.role}`
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
return messages;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// src/sap-ai-chat-language-model.ts
|
|
119
|
-
function isZodSchema(obj) {
|
|
120
|
-
return obj !== null && typeof obj === "object" && "_def" in obj && "parse" in obj && typeof obj.parse === "function";
|
|
121
|
-
}
|
|
122
|
-
var SAPAIChatLanguageModel = class {
|
|
123
|
-
/**
|
|
124
|
-
* Creates a new SAP AI Chat Language Model instance.
|
|
125
|
-
*
|
|
126
|
-
* @param modelId - The model identifier
|
|
127
|
-
* @param settings - Model-specific configuration settings
|
|
128
|
-
* @param config - Internal configuration (deployment config, destination, etc.)
|
|
129
|
-
*
|
|
130
|
-
* @internal This constructor is not meant to be called directly.
|
|
131
|
-
* Use the provider function instead.
|
|
132
|
-
*/
|
|
133
|
-
constructor(modelId, settings, config) {
|
|
134
|
-
/** AI SDK specification version */
|
|
135
|
-
this.specificationVersion = "v2";
|
|
136
|
-
/** Default object generation mode */
|
|
137
|
-
this.defaultObjectGenerationMode = "json";
|
|
138
|
-
/** Whether the model supports image URLs */
|
|
139
|
-
this.supportsImageUrls = true;
|
|
140
|
-
/** Whether the model supports structured outputs */
|
|
141
|
-
this.supportsStructuredOutputs = true;
|
|
142
|
-
this.settings = settings;
|
|
143
|
-
this.config = config;
|
|
144
|
-
this.modelId = modelId;
|
|
145
|
-
}
|
|
146
|
-
/**
|
|
147
|
-
* Checks if a URL is supported for file/image uploads.
|
|
148
|
-
*
|
|
149
|
-
* @param url - The URL to check
|
|
150
|
-
* @returns True if the URL protocol is HTTPS
|
|
151
|
-
*/
|
|
152
|
-
supportsUrl(url) {
|
|
153
|
-
return url.protocol === "https:";
|
|
154
|
-
}
|
|
155
|
-
/**
|
|
156
|
-
* Returns supported URL patterns for different content types.
|
|
157
|
-
*
|
|
158
|
-
* @returns Record of content types to regex patterns
|
|
159
|
-
*/
|
|
160
|
-
get supportedUrls() {
|
|
161
|
-
return {
|
|
162
|
-
"image/*": [
|
|
163
|
-
/^https:\/\/.*\.(?:png|jpg|jpeg|gif|webp)$/i,
|
|
164
|
-
/^data:image\/.*$/
|
|
165
|
-
]
|
|
166
|
-
};
|
|
167
|
-
}
|
|
168
|
-
/**
|
|
169
|
-
* Gets the provider identifier.
|
|
170
|
-
*
|
|
171
|
-
* @returns The provider name ('sap-ai')
|
|
172
|
-
*/
|
|
173
|
-
get provider() {
|
|
174
|
-
return this.config.provider;
|
|
175
|
-
}
|
|
176
|
-
/**
|
|
177
|
-
* Builds orchestration module config for SAP AI SDK.
|
|
178
|
-
*
|
|
179
|
-
* @param options - Call options from the AI SDK
|
|
180
|
-
* @returns Object containing orchestration config and warnings
|
|
181
|
-
*
|
|
182
|
-
* @internal
|
|
183
|
-
*/
|
|
184
|
-
buildOrchestrationConfig(options) {
|
|
185
|
-
const warnings = [];
|
|
186
|
-
const messages = convertToSAPMessages(options.prompt);
|
|
187
|
-
let tools;
|
|
188
|
-
if (this.settings.tools && this.settings.tools.length > 0) {
|
|
189
|
-
tools = this.settings.tools;
|
|
190
|
-
} else {
|
|
191
|
-
const availableTools = options.tools;
|
|
192
|
-
tools = availableTools?.map((tool) => {
|
|
193
|
-
if (tool.type === "function") {
|
|
194
|
-
const inputSchema = tool.inputSchema;
|
|
195
|
-
const toolWithParams = tool;
|
|
196
|
-
let parameters;
|
|
197
|
-
if (toolWithParams.parameters && isZodSchema(toolWithParams.parameters)) {
|
|
198
|
-
const jsonSchema = zodToJsonSchema(toolWithParams.parameters, {
|
|
199
|
-
$refStrategy: "none"
|
|
200
|
-
});
|
|
201
|
-
delete jsonSchema.$schema;
|
|
202
|
-
parameters = {
|
|
203
|
-
type: "object",
|
|
204
|
-
...jsonSchema
|
|
205
|
-
};
|
|
206
|
-
} else if (inputSchema && Object.keys(inputSchema).length > 0) {
|
|
207
|
-
const hasProperties = inputSchema.properties && typeof inputSchema.properties === "object" && Object.keys(inputSchema.properties).length > 0;
|
|
208
|
-
if (hasProperties) {
|
|
209
|
-
parameters = {
|
|
210
|
-
type: "object",
|
|
211
|
-
...inputSchema
|
|
212
|
-
};
|
|
213
|
-
} else {
|
|
214
|
-
parameters = {
|
|
215
|
-
type: "object",
|
|
216
|
-
properties: {},
|
|
217
|
-
required: []
|
|
218
|
-
};
|
|
219
|
-
}
|
|
220
|
-
} else {
|
|
221
|
-
parameters = {
|
|
222
|
-
type: "object",
|
|
223
|
-
properties: {},
|
|
224
|
-
required: []
|
|
225
|
-
};
|
|
226
|
-
}
|
|
227
|
-
return {
|
|
228
|
-
type: "function",
|
|
229
|
-
function: {
|
|
230
|
-
name: tool.name,
|
|
231
|
-
description: tool.description,
|
|
232
|
-
parameters
|
|
233
|
-
}
|
|
234
|
-
};
|
|
235
|
-
} else {
|
|
236
|
-
warnings.push({
|
|
237
|
-
type: "unsupported-tool",
|
|
238
|
-
tool
|
|
239
|
-
});
|
|
240
|
-
return null;
|
|
241
|
-
}
|
|
242
|
-
}).filter((t) => t !== null);
|
|
243
|
-
}
|
|
244
|
-
const supportsN = !this.modelId.startsWith("amazon--") && !this.modelId.startsWith("anthropic--");
|
|
245
|
-
const orchestrationConfig = {
|
|
246
|
-
promptTemplating: {
|
|
247
|
-
model: {
|
|
248
|
-
name: this.modelId,
|
|
249
|
-
version: this.settings.modelVersion ?? "latest",
|
|
250
|
-
params: {
|
|
251
|
-
max_tokens: this.settings.modelParams?.maxTokens,
|
|
252
|
-
temperature: this.settings.modelParams?.temperature,
|
|
253
|
-
top_p: this.settings.modelParams?.topP,
|
|
254
|
-
frequency_penalty: this.settings.modelParams?.frequencyPenalty,
|
|
255
|
-
presence_penalty: this.settings.modelParams?.presencePenalty,
|
|
256
|
-
n: supportsN ? this.settings.modelParams?.n ?? 1 : void 0
|
|
257
|
-
}
|
|
258
|
-
},
|
|
259
|
-
prompt: {
|
|
260
|
-
template: [],
|
|
261
|
-
tools: tools && tools.length > 0 ? tools : void 0
|
|
262
|
-
}
|
|
263
|
-
},
|
|
264
|
-
// Include masking module if provided
|
|
265
|
-
...this.settings.masking ? { masking: this.settings.masking } : {},
|
|
266
|
-
// Include filtering module if provided
|
|
267
|
-
...this.settings.filtering ? { filtering: this.settings.filtering } : {}
|
|
268
|
-
};
|
|
269
|
-
return { orchestrationConfig, messages, warnings };
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Creates an OrchestrationClient instance.
|
|
273
|
-
*
|
|
274
|
-
* @param config - Orchestration module configuration
|
|
275
|
-
* @returns OrchestrationClient instance
|
|
276
|
-
*
|
|
277
|
-
* @internal
|
|
278
|
-
*/
|
|
279
|
-
createClient(config) {
|
|
280
|
-
return new OrchestrationClient(
|
|
281
|
-
config,
|
|
282
|
-
this.config.deploymentConfig,
|
|
283
|
-
this.config.destination
|
|
284
|
-
);
|
|
285
|
-
}
|
|
286
|
-
/**
|
|
287
|
-
* Generates a single completion (non-streaming).
|
|
288
|
-
*
|
|
289
|
-
* This method implements the `LanguageModelV2.doGenerate` interface,
|
|
290
|
-
* sending a request to SAP AI Core and returning the complete response.
|
|
291
|
-
*
|
|
292
|
-
* **Features:**
|
|
293
|
-
* - Tool calling support
|
|
294
|
-
* - Multi-modal input (text + images)
|
|
295
|
-
* - Data masking (if configured)
|
|
296
|
-
* - Content filtering (if configured)
|
|
297
|
-
*
|
|
298
|
-
* @param options - Generation options including prompt, tools, and settings
|
|
299
|
-
* @returns Promise resolving to the generation result with content, usage, and metadata
|
|
300
|
-
*
|
|
301
|
-
* @example
|
|
302
|
-
* ```typescript
|
|
303
|
-
* const result = await model.doGenerate({
|
|
304
|
-
* prompt: [
|
|
305
|
-
* { role: 'user', content: [{ type: 'text', text: 'Hello!' }] }
|
|
306
|
-
* ]
|
|
307
|
-
* });
|
|
308
|
-
*
|
|
309
|
-
* console.log(result.content); // Generated content
|
|
310
|
-
* console.log(result.usage); // Token usage
|
|
311
|
-
* ```
|
|
312
|
-
*/
|
|
313
|
-
async doGenerate(options) {
|
|
314
|
-
const { orchestrationConfig, messages, warnings } = this.buildOrchestrationConfig(options);
|
|
315
|
-
const client = this.createClient(orchestrationConfig);
|
|
316
|
-
const response = await client.chatCompletion({
|
|
317
|
-
messages
|
|
318
|
-
});
|
|
319
|
-
const content = [];
|
|
320
|
-
const textContent = response.getContent();
|
|
321
|
-
if (textContent) {
|
|
322
|
-
content.push({
|
|
323
|
-
type: "text",
|
|
324
|
-
text: textContent
|
|
325
|
-
});
|
|
326
|
-
}
|
|
327
|
-
const toolCalls = response.getToolCalls();
|
|
328
|
-
if (toolCalls) {
|
|
329
|
-
for (const toolCall of toolCalls) {
|
|
330
|
-
content.push({
|
|
331
|
-
type: "tool-call",
|
|
332
|
-
toolCallId: toolCall.id,
|
|
333
|
-
toolName: toolCall.function.name,
|
|
334
|
-
// AI SDK expects input as a JSON string, which it parses internally
|
|
335
|
-
input: toolCall.function.arguments
|
|
336
|
-
});
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
const tokenUsage = response.getTokenUsage();
|
|
340
|
-
const finishReasonRaw = response.getFinishReason();
|
|
341
|
-
const finishReason = mapFinishReason(finishReasonRaw);
|
|
342
|
-
return {
|
|
343
|
-
content,
|
|
344
|
-
finishReason,
|
|
345
|
-
usage: {
|
|
346
|
-
inputTokens: tokenUsage.prompt_tokens,
|
|
347
|
-
outputTokens: tokenUsage.completion_tokens,
|
|
348
|
-
totalTokens: tokenUsage.total_tokens
|
|
349
|
-
},
|
|
350
|
-
rawCall: {
|
|
351
|
-
rawPrompt: { config: orchestrationConfig, messages },
|
|
352
|
-
rawSettings: {}
|
|
353
|
-
},
|
|
354
|
-
warnings
|
|
355
|
-
};
|
|
356
|
-
}
|
|
357
|
-
/**
|
|
358
|
-
* Generates a streaming completion.
|
|
359
|
-
*
|
|
360
|
-
* This method implements the `LanguageModelV2.doStream` interface,
|
|
361
|
-
* sending a streaming request to SAP AI Core and returning a stream of response parts.
|
|
362
|
-
*
|
|
363
|
-
* **Stream Events:**
|
|
364
|
-
* - `stream-start` - Stream initialization
|
|
365
|
-
* - `response-metadata` - Response metadata (model, timestamp)
|
|
366
|
-
* - `text-start` - Text generation starts
|
|
367
|
-
* - `text-delta` - Incremental text chunks
|
|
368
|
-
* - `text-end` - Text generation completes
|
|
369
|
-
* - `tool-call` - Tool call detected
|
|
370
|
-
* - `finish` - Stream completes with usage and finish reason
|
|
371
|
-
* - `error` - Error occurred
|
|
372
|
-
*
|
|
373
|
-
* @param options - Streaming options including prompt, tools, and settings
|
|
374
|
-
* @returns Promise resolving to stream and raw call metadata
|
|
375
|
-
*
|
|
376
|
-
* @example
|
|
377
|
-
* ```typescript
|
|
378
|
-
* const { stream } = await model.doStream({
|
|
379
|
-
* prompt: [
|
|
380
|
-
* { role: 'user', content: [{ type: 'text', text: 'Write a story' }] }
|
|
381
|
-
* ]
|
|
382
|
-
* });
|
|
383
|
-
*
|
|
384
|
-
* for await (const part of stream) {
|
|
385
|
-
* if (part.type === 'text-delta') {
|
|
386
|
-
* process.stdout.write(part.delta);
|
|
387
|
-
* }
|
|
388
|
-
* }
|
|
389
|
-
* ```
|
|
390
|
-
*/
|
|
391
|
-
async doStream(options) {
|
|
392
|
-
const { orchestrationConfig, messages, warnings } = this.buildOrchestrationConfig(options);
|
|
393
|
-
const client = this.createClient(orchestrationConfig);
|
|
394
|
-
const streamResponse = await client.stream(
|
|
395
|
-
{ messages },
|
|
396
|
-
options.abortSignal,
|
|
397
|
-
{ promptTemplating: { include_usage: true } }
|
|
398
|
-
);
|
|
399
|
-
let finishReason = "unknown";
|
|
400
|
-
const usage = {
|
|
401
|
-
inputTokens: void 0,
|
|
402
|
-
outputTokens: void 0,
|
|
403
|
-
totalTokens: void 0
|
|
404
|
-
};
|
|
405
|
-
let isFirstChunk = true;
|
|
406
|
-
let activeText = false;
|
|
407
|
-
const toolCallsInProgress = /* @__PURE__ */ new Map();
|
|
408
|
-
const sdkStream = streamResponse.stream;
|
|
409
|
-
const transformedStream = new ReadableStream({
|
|
410
|
-
async start(controller) {
|
|
411
|
-
controller.enqueue({ type: "stream-start", warnings });
|
|
412
|
-
try {
|
|
413
|
-
for await (const chunk of sdkStream) {
|
|
414
|
-
if (isFirstChunk) {
|
|
415
|
-
isFirstChunk = false;
|
|
416
|
-
controller.enqueue({
|
|
417
|
-
type: "response-metadata",
|
|
418
|
-
id: void 0,
|
|
419
|
-
modelId: void 0,
|
|
420
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
421
|
-
});
|
|
422
|
-
}
|
|
423
|
-
const deltaContent = chunk.getDeltaContent();
|
|
424
|
-
if (deltaContent) {
|
|
425
|
-
if (!activeText) {
|
|
426
|
-
controller.enqueue({ type: "text-start", id: "0" });
|
|
427
|
-
activeText = true;
|
|
428
|
-
}
|
|
429
|
-
controller.enqueue({
|
|
430
|
-
type: "text-delta",
|
|
431
|
-
id: "0",
|
|
432
|
-
delta: deltaContent
|
|
433
|
-
});
|
|
434
|
-
}
|
|
435
|
-
const deltaToolCalls = chunk.getDeltaToolCalls();
|
|
436
|
-
if (deltaToolCalls) {
|
|
437
|
-
for (const toolCallChunk of deltaToolCalls) {
|
|
438
|
-
const index = toolCallChunk.index;
|
|
439
|
-
if (!toolCallsInProgress.has(index)) {
|
|
440
|
-
toolCallsInProgress.set(index, {
|
|
441
|
-
id: toolCallChunk.id ?? `tool_${String(index)}`,
|
|
442
|
-
name: toolCallChunk.function?.name ?? "",
|
|
443
|
-
arguments: ""
|
|
444
|
-
});
|
|
445
|
-
const tc2 = toolCallsInProgress.get(index);
|
|
446
|
-
if (!tc2) continue;
|
|
447
|
-
if (toolCallChunk.function?.name) {
|
|
448
|
-
controller.enqueue({
|
|
449
|
-
type: "tool-input-start",
|
|
450
|
-
id: tc2.id,
|
|
451
|
-
toolName: tc2.name
|
|
452
|
-
});
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
const tc = toolCallsInProgress.get(index);
|
|
456
|
-
if (!tc) continue;
|
|
457
|
-
if (toolCallChunk.id) {
|
|
458
|
-
tc.id = toolCallChunk.id;
|
|
459
|
-
}
|
|
460
|
-
if (toolCallChunk.function?.name) {
|
|
461
|
-
tc.name = toolCallChunk.function.name;
|
|
462
|
-
}
|
|
463
|
-
if (toolCallChunk.function?.arguments) {
|
|
464
|
-
tc.arguments += toolCallChunk.function.arguments;
|
|
465
|
-
controller.enqueue({
|
|
466
|
-
type: "tool-input-delta",
|
|
467
|
-
id: tc.id,
|
|
468
|
-
delta: toolCallChunk.function.arguments
|
|
469
|
-
});
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
}
|
|
473
|
-
const chunkFinishReason = chunk.getFinishReason();
|
|
474
|
-
if (chunkFinishReason) {
|
|
475
|
-
finishReason = mapFinishReason(chunkFinishReason);
|
|
476
|
-
}
|
|
477
|
-
const chunkUsage = chunk.getTokenUsage();
|
|
478
|
-
if (chunkUsage) {
|
|
479
|
-
usage.inputTokens = chunkUsage.prompt_tokens;
|
|
480
|
-
usage.outputTokens = chunkUsage.completion_tokens;
|
|
481
|
-
usage.totalTokens = chunkUsage.total_tokens;
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
const toolCalls = Array.from(toolCallsInProgress.values());
|
|
485
|
-
for (const tc of toolCalls) {
|
|
486
|
-
controller.enqueue({
|
|
487
|
-
type: "tool-input-end",
|
|
488
|
-
id: tc.id
|
|
489
|
-
});
|
|
490
|
-
controller.enqueue({
|
|
491
|
-
type: "tool-call",
|
|
492
|
-
toolCallId: tc.id,
|
|
493
|
-
toolName: tc.name,
|
|
494
|
-
input: tc.arguments
|
|
495
|
-
});
|
|
496
|
-
}
|
|
497
|
-
if (activeText) {
|
|
498
|
-
controller.enqueue({ type: "text-end", id: "0" });
|
|
499
|
-
}
|
|
500
|
-
const finalUsage = streamResponse.getTokenUsage();
|
|
501
|
-
if (finalUsage) {
|
|
502
|
-
usage.inputTokens = finalUsage.prompt_tokens;
|
|
503
|
-
usage.outputTokens = finalUsage.completion_tokens;
|
|
504
|
-
usage.totalTokens = finalUsage.total_tokens;
|
|
505
|
-
}
|
|
506
|
-
const finalFinishReason = streamResponse.getFinishReason();
|
|
507
|
-
if (finalFinishReason) {
|
|
508
|
-
finishReason = mapFinishReason(finalFinishReason);
|
|
509
|
-
}
|
|
510
|
-
controller.enqueue({
|
|
511
|
-
type: "finish",
|
|
512
|
-
finishReason,
|
|
513
|
-
usage
|
|
514
|
-
});
|
|
515
|
-
controller.close();
|
|
516
|
-
} catch (error) {
|
|
517
|
-
controller.enqueue({
|
|
518
|
-
type: "error",
|
|
519
|
-
error: error instanceof Error ? error : new Error(String(error))
|
|
520
|
-
});
|
|
521
|
-
controller.close();
|
|
522
|
-
}
|
|
523
|
-
}
|
|
524
|
-
});
|
|
525
|
-
return {
|
|
526
|
-
stream: transformedStream,
|
|
527
|
-
rawCall: {
|
|
528
|
-
rawPrompt: { config: orchestrationConfig, messages },
|
|
529
|
-
rawSettings: {}
|
|
530
|
-
}
|
|
531
|
-
};
|
|
532
|
-
}
|
|
533
|
-
};
|
|
534
|
-
function mapFinishReason(reason) {
|
|
535
|
-
if (!reason) return "unknown";
|
|
536
|
-
switch (reason.toLowerCase()) {
|
|
537
|
-
case "stop":
|
|
538
|
-
return "stop";
|
|
539
|
-
case "length":
|
|
540
|
-
return "length";
|
|
541
|
-
case "tool_calls":
|
|
542
|
-
case "function_call":
|
|
543
|
-
return "tool-calls";
|
|
544
|
-
case "content_filter":
|
|
545
|
-
return "content-filter";
|
|
546
|
-
default:
|
|
547
|
-
return "unknown";
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
|
|
551
|
-
// src/sap-ai-provider.ts
|
|
552
|
-
function createSAPAIProvider(options = {}) {
|
|
553
|
-
const resourceGroup = options.resourceGroup ?? "default";
|
|
554
|
-
const deploymentConfig = options.deploymentId ? { deploymentId: options.deploymentId } : { resourceGroup };
|
|
555
|
-
const createModel = (modelId, settings = {}) => {
|
|
556
|
-
const mergedSettings = {
|
|
557
|
-
...options.defaultSettings,
|
|
558
|
-
...settings,
|
|
559
|
-
modelParams: {
|
|
560
|
-
...options.defaultSettings?.modelParams ?? {},
|
|
561
|
-
...settings.modelParams ?? {}
|
|
562
|
-
}
|
|
563
|
-
};
|
|
564
|
-
return new SAPAIChatLanguageModel(modelId, mergedSettings, {
|
|
565
|
-
provider: "sap-ai",
|
|
566
|
-
deploymentConfig,
|
|
567
|
-
destination: options.destination
|
|
568
|
-
});
|
|
569
|
-
};
|
|
570
|
-
const provider = function(modelId, settings) {
|
|
571
|
-
if (new.target) {
|
|
572
|
-
throw new Error(
|
|
573
|
-
"The SAP AI provider function cannot be called with the new keyword."
|
|
574
|
-
);
|
|
575
|
-
}
|
|
576
|
-
return createModel(modelId, settings);
|
|
577
|
-
};
|
|
578
|
-
provider.chat = createModel;
|
|
579
|
-
return provider;
|
|
580
|
-
}
|
|
581
|
-
var sapai = createSAPAIProvider();
|
|
582
|
-
|
|
583
|
-
// src/sap-ai-chat-settings.ts
|
|
584
|
-
import {
|
|
585
|
-
buildDpiMaskingProvider,
|
|
586
|
-
buildAzureContentSafetyFilter,
|
|
587
|
-
buildLlamaGuard38BFilter,
|
|
588
|
-
buildDocumentGroundingConfig,
|
|
589
|
-
buildTranslationConfig
|
|
590
|
-
} from "@sap-ai-sdk/orchestration";
|
|
591
|
-
|
|
592
|
-
// src/sap-ai-error.ts
|
|
593
|
-
var SAPAIError = class _SAPAIError extends Error {
|
|
594
|
-
constructor(message, options) {
|
|
595
|
-
super(message);
|
|
596
|
-
this.name = "SAPAIError";
|
|
597
|
-
this.code = options?.code;
|
|
598
|
-
this.location = options?.location;
|
|
599
|
-
this.requestId = options?.requestId;
|
|
600
|
-
this.details = options?.details;
|
|
601
|
-
this.cause = options?.cause;
|
|
602
|
-
}
|
|
603
|
-
/**
|
|
604
|
-
* Creates a SAPAIError from an OrchestrationErrorResponse.
|
|
605
|
-
*
|
|
606
|
-
* @param errorResponse - The error response from SAP AI SDK
|
|
607
|
-
* @returns A new SAPAIError instance
|
|
608
|
-
*/
|
|
609
|
-
static fromOrchestrationError(errorResponse) {
|
|
610
|
-
const error = errorResponse.error;
|
|
611
|
-
if (Array.isArray(error)) {
|
|
612
|
-
const firstError = error[0];
|
|
613
|
-
return new _SAPAIError(
|
|
614
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
615
|
-
firstError?.message ?? "Unknown orchestration error",
|
|
616
|
-
{
|
|
617
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
618
|
-
code: firstError?.code,
|
|
619
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
620
|
-
location: firstError?.location,
|
|
621
|
-
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
|
622
|
-
requestId: firstError?.request_id
|
|
623
|
-
}
|
|
624
|
-
);
|
|
625
|
-
} else {
|
|
626
|
-
return new _SAPAIError(error.message ?? "Unknown orchestration error", {
|
|
627
|
-
code: error.code,
|
|
628
|
-
location: error.location,
|
|
629
|
-
requestId: error.request_id
|
|
630
|
-
});
|
|
631
|
-
}
|
|
632
|
-
}
|
|
633
|
-
/**
|
|
634
|
-
* Creates a SAPAIError from a generic error.
|
|
635
|
-
*
|
|
636
|
-
* @param error - The original error
|
|
637
|
-
* @param context - Optional context about where the error occurred
|
|
638
|
-
* @returns A new SAPAIError instance
|
|
639
|
-
*/
|
|
640
|
-
static fromError(error, context) {
|
|
641
|
-
if (error instanceof _SAPAIError) {
|
|
642
|
-
return error;
|
|
643
|
-
}
|
|
644
|
-
let message;
|
|
645
|
-
if (error instanceof Error) {
|
|
646
|
-
message = error.message;
|
|
647
|
-
} else if (error == null) {
|
|
648
|
-
message = "Unknown error";
|
|
649
|
-
} else if (typeof error === "string" || typeof error === "number" || typeof error === "boolean" || typeof error === "bigint") {
|
|
650
|
-
message = String(error);
|
|
651
|
-
} else {
|
|
652
|
-
try {
|
|
653
|
-
message = JSON.stringify(error);
|
|
654
|
-
} catch {
|
|
655
|
-
message = "[Unstringifiable Value]";
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
return new _SAPAIError(context ? `${context}: ${message}` : message, {
|
|
659
|
-
cause: error
|
|
660
|
-
});
|
|
661
|
-
}
|
|
662
|
-
};
|
|
663
|
-
|
|
664
|
-
// src/types/completion-response.ts
|
|
665
|
-
import {
|
|
666
|
-
OrchestrationResponse,
|
|
667
|
-
OrchestrationStreamResponse,
|
|
668
|
-
OrchestrationStreamChunkResponse
|
|
669
|
-
} from "@sap-ai-sdk/orchestration";
|
|
670
|
-
|
|
671
|
-
// src/index.ts
|
|
672
|
-
import { OrchestrationClient as OrchestrationClient2 } from "@sap-ai-sdk/orchestration";
|
|
673
|
-
export {
|
|
674
|
-
OrchestrationClient2 as OrchestrationClient,
|
|
675
|
-
OrchestrationResponse,
|
|
676
|
-
OrchestrationStreamChunkResponse,
|
|
677
|
-
OrchestrationStreamResponse,
|
|
678
|
-
SAPAIError,
|
|
679
|
-
buildAzureContentSafetyFilter,
|
|
680
|
-
buildDocumentGroundingConfig,
|
|
681
|
-
buildDpiMaskingProvider,
|
|
682
|
-
buildLlamaGuard38BFilter,
|
|
683
|
-
buildTranslationConfig,
|
|
684
|
-
createSAPAIProvider,
|
|
685
|
-
sapai
|
|
686
|
-
};
|
|
687
|
-
//# sourceMappingURL=index.mjs.map
|