@nordlys-labs/nordlys-ai-provider 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,1038 @@
1
+ // src/nordlys-provider.ts
2
+ import { NoSuchModelError } from "@ai-sdk/provider";
3
+ import { loadApiKey, withoutTrailingSlash } from "@ai-sdk/provider-utils";
4
+
5
+ // src/nordlys-chat-language-model.ts
6
+ import {
7
+ InvalidResponseDataError
8
+ } from "@ai-sdk/provider";
9
+ import {
10
+ combineHeaders,
11
+ createEventSourceResponseHandler,
12
+ createJsonResponseHandler,
13
+ generateId,
14
+ isParsableJson,
15
+ postJsonToApi
16
+ } from "@ai-sdk/provider-utils";
17
+ import { z as z3 } from "zod";
18
+
19
+ // src/convert-to-nordlys-chat-messages.ts
20
+ import { UnsupportedFunctionalityError } from "@ai-sdk/provider";
21
+ import { convertToBase64 } from "@ai-sdk/provider-utils";
22
+ function convertToolOutput(output) {
23
+ switch (output.type) {
24
+ case "text":
25
+ case "error-text":
26
+ return output.value;
27
+ case "json":
28
+ case "error-json":
29
+ return JSON.stringify(output.value);
30
+ case "content":
31
+ return JSON.stringify(output.value);
32
+ case "execution-denied":
33
+ return "";
34
+ default:
35
+ return "";
36
+ }
37
+ }
38
+ function convertToNordlysChatMessages({
39
+ prompt,
40
+ systemMessageMode = "system"
41
+ }) {
42
+ const messages = [];
43
+ const warnings = [];
44
+ for (const { role, content } of prompt) {
45
+ switch (role) {
46
+ case "system": {
47
+ switch (systemMessageMode) {
48
+ case "system": {
49
+ messages.push({ role: "system", content });
50
+ break;
51
+ }
52
+ case "developer": {
53
+ messages.push({ role: "developer", content });
54
+ break;
55
+ }
56
+ case "remove": {
57
+ warnings.push({
58
+ type: "other",
59
+ message: "system messages are removed for this model"
60
+ });
61
+ break;
62
+ }
63
+ default: {
64
+ const _exhaustiveCheck = systemMessageMode;
65
+ throw new Error(
66
+ `Unsupported system message mode: ${_exhaustiveCheck}`
67
+ );
68
+ }
69
+ }
70
+ break;
71
+ }
72
+ case "user": {
73
+ if (content.length === 1 && content[0].type === "text") {
74
+ messages.push({ role: "user", content: content[0].text });
75
+ break;
76
+ }
77
+ messages.push({
78
+ role: "user",
79
+ content: content.map((part, index) => {
80
+ var _a, _b;
81
+ switch (part.type) {
82
+ case "text": {
83
+ return { type: "text", text: part.text };
84
+ }
85
+ case "file": {
86
+ if ((_a = part.mediaType) == null ? void 0 : _a.startsWith("image/")) {
87
+ const mediaType = part.mediaType === "image/*" ? "image/jpeg" : part.mediaType;
88
+ return {
89
+ type: "image_url",
90
+ image_url: {
91
+ url: part.data instanceof URL ? part.data.toString() : `data:${mediaType};base64,${convertToBase64(part.data)}`
92
+ }
93
+ };
94
+ }
95
+ if (part.mediaType && (part.mediaType === "audio/wav" || part.mediaType === "audio/mp3" || part.mediaType === "audio/mpeg")) {
96
+ if (part.data instanceof URL) {
97
+ throw new UnsupportedFunctionalityError({
98
+ functionality: "audio file parts with URLs"
99
+ });
100
+ }
101
+ return {
102
+ type: "input_audio",
103
+ input_audio: {
104
+ data: convertToBase64(part.data),
105
+ format: part.mediaType === "audio/wav" ? "wav" : "mp3"
106
+ }
107
+ };
108
+ }
109
+ if (part.mediaType && part.mediaType === "application/pdf") {
110
+ if (part.data instanceof URL) {
111
+ throw new UnsupportedFunctionalityError({
112
+ functionality: "PDF file parts with URLs"
113
+ });
114
+ }
115
+ return {
116
+ type: "file",
117
+ file: {
118
+ filename: (_b = part.filename) != null ? _b : `part-${index}.pdf`,
119
+ file_data: `data:application/pdf;base64,${convertToBase64(part.data)}`
120
+ }
121
+ };
122
+ }
123
+ throw new UnsupportedFunctionalityError({
124
+ functionality: `file part media type ${part.mediaType}`
125
+ });
126
+ }
127
+ default: {
128
+ throw new Error(`Unsupported content part type`);
129
+ }
130
+ }
131
+ })
132
+ });
133
+ break;
134
+ }
135
+ case "assistant": {
136
+ const textParts = [];
137
+ const reasoningParts = [];
138
+ const generatedFiles = [];
139
+ const toolCalls = [];
140
+ for (const part of content) {
141
+ switch (part.type) {
142
+ case "text": {
143
+ textParts.push(part.text);
144
+ break;
145
+ }
146
+ case "reasoning": {
147
+ reasoningParts.push(part.text);
148
+ break;
149
+ }
150
+ case "file": {
151
+ const dataString = typeof part.data === "string" ? part.data : part.data instanceof URL ? (() => {
152
+ throw new Error(
153
+ "URL data not supported for generated files"
154
+ );
155
+ })() : Buffer.from(part.data).toString("base64");
156
+ generatedFiles.push({
157
+ media_type: part.mediaType,
158
+ data: dataString
159
+ });
160
+ break;
161
+ }
162
+ case "tool-call": {
163
+ toolCalls.push({
164
+ id: part.toolCallId,
165
+ type: "function",
166
+ function: {
167
+ name: part.toolName,
168
+ arguments: JSON.stringify(part.input)
169
+ }
170
+ });
171
+ break;
172
+ }
173
+ }
174
+ }
175
+ const text = textParts.join("");
176
+ const reasoning = reasoningParts.join("");
177
+ const message = {
178
+ role: "assistant",
179
+ content: text,
180
+ ...toolCalls.length > 0 && { tool_calls: toolCalls },
181
+ ...reasoning && { reasoning_content: reasoning },
182
+ ...generatedFiles.length > 0 && { generated_files: generatedFiles }
183
+ };
184
+ messages.push(message);
185
+ break;
186
+ }
187
+ case "tool": {
188
+ for (const toolResponse of content) {
189
+ if (toolResponse.type === "tool-result") {
190
+ const contentValue = convertToolOutput(toolResponse.output);
191
+ if (contentValue) {
192
+ messages.push({
193
+ role: "tool",
194
+ tool_call_id: toolResponse.toolCallId,
195
+ content: contentValue
196
+ });
197
+ }
198
+ }
199
+ }
200
+ break;
201
+ }
202
+ default: {
203
+ const _exhaustiveCheck = role;
204
+ throw new Error(`Unsupported role: ${_exhaustiveCheck}`);
205
+ }
206
+ }
207
+ }
208
+ return { messages, warnings };
209
+ }
210
+
211
+ // src/get-response-metadata.ts
212
+ function getResponseMetadata({
213
+ id,
214
+ model,
215
+ created
216
+ }) {
217
+ return {
218
+ id: id != null ? id : void 0,
219
+ modelId: model != null ? model : void 0,
220
+ timestamp: created != null ? new Date(created * 1e3) : void 0
221
+ };
222
+ }
223
+
224
+ // src/map-nordlys-finish-reason.ts
225
+ function mapNordlysFinishReason(reason) {
226
+ switch (reason) {
227
+ case "stop":
228
+ return { unified: "stop", raw: reason };
229
+ case "length":
230
+ return { unified: "length", raw: reason };
231
+ case "content_filter":
232
+ return { unified: "content-filter", raw: reason };
233
+ case "tool_calls":
234
+ return { unified: "tool-calls", raw: reason };
235
+ default:
236
+ return { unified: "other", raw: reason };
237
+ }
238
+ }
239
+
240
+ // src/nordlys-chat-options.ts
241
+ import { z } from "zod/v4";
242
+ var nordlysProviderOptions = z.object({
243
+ /**
244
+ * Model name (required for API requests).
245
+ */
246
+ model: z.string().optional(),
247
+ /**
248
+ * Modify the likelihood of specified tokens appearing in the completion.
249
+ */
250
+ logit_bias: z.record(z.string(), z.number()).optional(),
251
+ /**
252
+ * Number of completions to generate for each prompt.
253
+ */
254
+ n: z.number().optional(),
255
+ /**
256
+ * Whether to stream responses.
257
+ */
258
+ stream: z.boolean().optional(),
259
+ /**
260
+ * Unique identifier representing your end-user.
261
+ */
262
+ user: z.string().optional(),
263
+ /**
264
+ * Audio parameter for chat completion.
265
+ */
266
+ audio: z.object({
267
+ format: z.string().optional(),
268
+ voice: z.string().optional()
269
+ }).optional(),
270
+ /**
271
+ * Whether to return log probabilities of the output tokens.
272
+ */
273
+ logprobs: z.boolean().optional(),
274
+ /**
275
+ * Maximum number of completion tokens.
276
+ */
277
+ max_completion_tokens: z.number().optional(),
278
+ /**
279
+ * Metadata for the request.
280
+ */
281
+ metadata: z.record(z.string(), z.string()).optional(),
282
+ /**
283
+ * Modalities for the request.
284
+ */
285
+ modalities: z.array(z.string()).optional(),
286
+ /**
287
+ * Whether to allow parallel tool calls.
288
+ */
289
+ parallel_tool_calls: z.boolean().optional(),
290
+ /**
291
+ * Prediction content parameter.
292
+ */
293
+ prediction: z.object({
294
+ type: z.string().optional(),
295
+ content: z.object({
296
+ OfString: z.string().optional(),
297
+ OfArrayOfContentParts: z.array(z.object({ type: z.literal("text"), text: z.string() })).optional()
298
+ }).optional()
299
+ }).optional(),
300
+ /**
301
+ * Reasoning effort level.
302
+ */
303
+ reasoning_effort: z.string().optional(),
304
+ /**
305
+ * Response format parameter.
306
+ */
307
+ response_format: z.object({
308
+ OfText: z.object({ type: z.string() }).optional(),
309
+ OfJSONObject: z.object({ type: z.string() }).optional(),
310
+ OfJSONSchema: z.object({
311
+ type: z.string(),
312
+ json_schema: z.object({
313
+ name: z.string(),
314
+ schema: z.unknown(),
315
+ description: z.string().optional(),
316
+ strict: z.boolean().optional()
317
+ }).optional()
318
+ }).optional()
319
+ }).optional(),
320
+ /**
321
+ * Seed for deterministic outputs.
322
+ */
323
+ seed: z.number().optional(),
324
+ /**
325
+ * Service tier to use.
326
+ */
327
+ service_tier: z.string().optional(),
328
+ /**
329
+ * Whether to store the conversation.
330
+ */
331
+ store: z.boolean().optional(),
332
+ /**
333
+ * Number of top logprobs to return.
334
+ */
335
+ top_logprobs: z.number().optional(),
336
+ /**
337
+ * Web search options.
338
+ */
339
+ web_search_options: z.object({
340
+ search_context_size: z.string().optional(),
341
+ user_location: z.object({
342
+ type: z.string().optional(),
343
+ approximate: z.object({
344
+ city: z.string().optional(),
345
+ country: z.string().optional(),
346
+ region: z.string().optional(),
347
+ timezone: z.string().optional()
348
+ }).optional()
349
+ }).optional()
350
+ }).optional()
351
+ });
352
+
353
+ // src/nordlys-error.ts
354
+ import { createJsonErrorResponseHandler } from "@ai-sdk/provider-utils";
355
+ import { z as z2 } from "zod";
356
+ var nordlysErrorDataSchema = z2.object({
357
+ error: z2.object({
358
+ message: z2.string(),
359
+ type: z2.string().nullish(),
360
+ param: z2.any().nullish(),
361
+ code: z2.union([z2.string(), z2.number()]).nullish()
362
+ })
363
+ });
364
+ var nordlysFailedResponseHandler = createJsonErrorResponseHandler({
365
+ errorSchema: nordlysErrorDataSchema,
366
+ errorToMessage: (data) => data.error.message
367
+ });
368
+
369
+ // src/nordlys-prepare-tools.ts
370
+ import {
371
+ UnsupportedFunctionalityError as UnsupportedFunctionalityError2
372
+ } from "@ai-sdk/provider";
373
+ function prepareTools({
374
+ tools,
375
+ toolChoice
376
+ }) {
377
+ tools = (tools == null ? void 0 : tools.length) ? tools : void 0;
378
+ const toolWarnings = [];
379
+ if (tools == null) {
380
+ return { tools: void 0, toolChoice: void 0, toolWarnings };
381
+ }
382
+ const openaiCompatTools = [];
383
+ for (const tool of tools) {
384
+ if (tool.type === "provider") {
385
+ toolWarnings.push({ type: "unsupported", feature: `tool: ${tool.name}` });
386
+ } else if (tool.type === "function") {
387
+ openaiCompatTools.push({
388
+ type: "function",
389
+ function: {
390
+ name: tool.name,
391
+ description: tool.description,
392
+ parameters: tool.inputSchema
393
+ }
394
+ });
395
+ }
396
+ }
397
+ if (toolChoice == null) {
398
+ return { tools: openaiCompatTools, toolChoice: void 0, toolWarnings };
399
+ }
400
+ const type = toolChoice.type;
401
+ switch (type) {
402
+ case "auto":
403
+ case "none":
404
+ case "required":
405
+ return { tools: openaiCompatTools, toolChoice: type, toolWarnings };
406
+ case "tool":
407
+ return {
408
+ tools: openaiCompatTools,
409
+ toolChoice: {
410
+ type: "function",
411
+ function: { name: toolChoice.toolName }
412
+ },
413
+ toolWarnings
414
+ };
415
+ default: {
416
+ const _exhaustiveCheck = type;
417
+ throw new UnsupportedFunctionalityError2({
418
+ functionality: `tool choice type: ${_exhaustiveCheck}`
419
+ });
420
+ }
421
+ }
422
+ }
423
+
424
+ // src/nordlys-chat-language-model.ts
425
+ var nordlysChatResponseSchema = z3.object({
426
+ id: z3.string().nullish(),
427
+ created: z3.number().nullish(),
428
+ model: z3.string().nullish(),
429
+ choices: z3.array(
430
+ z3.object({
431
+ message: z3.object({
432
+ role: z3.enum(["assistant", ""]).nullish(),
433
+ content: z3.string().nullish(),
434
+ tool_calls: z3.array(
435
+ z3.object({
436
+ id: z3.string().nullish(),
437
+ type: z3.literal("function"),
438
+ function: z3.object({
439
+ name: z3.string(),
440
+ arguments: z3.string()
441
+ })
442
+ })
443
+ ).nullish(),
444
+ reasoning_content: z3.string().optional(),
445
+ generated_files: z3.array(
446
+ z3.object({
447
+ media_type: z3.string(),
448
+ data: z3.string()
449
+ })
450
+ ).optional()
451
+ }),
452
+ index: z3.number(),
453
+ logprobs: z3.object({
454
+ content: z3.array(
455
+ z3.object({
456
+ token: z3.string(),
457
+ logprob: z3.number(),
458
+ top_logprobs: z3.array(
459
+ z3.object({
460
+ token: z3.string(),
461
+ logprob: z3.number()
462
+ })
463
+ )
464
+ })
465
+ ).nullish()
466
+ }).nullish(),
467
+ finish_reason: z3.string().nullish()
468
+ })
469
+ ).optional(),
470
+ usage: z3.object({
471
+ completion_tokens: z3.number(),
472
+ prompt_tokens: z3.number(),
473
+ total_tokens: z3.number(),
474
+ reasoning_tokens: z3.number().optional(),
475
+ cached_input_tokens: z3.number().optional()
476
+ }).optional(),
477
+ system_fingerprint: z3.string().optional(),
478
+ service_tier: z3.string().optional(),
479
+ provider: z3.string().optional(),
480
+ error: z3.object({
481
+ message: z3.string(),
482
+ type: z3.string(),
483
+ param: z3.any().nullish(),
484
+ code: z3.any().nullish()
485
+ }).optional()
486
+ });
487
+ var nordlysChatChunkSchema = z3.union([
488
+ z3.object({
489
+ id: z3.string().nullish(),
490
+ created: z3.number().nullish(),
491
+ model: z3.string().nullish(),
492
+ choices: z3.array(
493
+ z3.object({
494
+ delta: z3.object({
495
+ role: z3.enum(["assistant", ""]).nullish(),
496
+ content: z3.string().nullish(),
497
+ tool_calls: z3.array(
498
+ z3.object({
499
+ index: z3.number(),
500
+ id: z3.string().nullish(),
501
+ type: z3.union([z3.literal("function"), z3.literal("")]).nullish(),
502
+ function: z3.object({
503
+ name: z3.string().nullish(),
504
+ arguments: z3.string().nullish()
505
+ })
506
+ })
507
+ ).nullish(),
508
+ reasoning_content: z3.string().optional(),
509
+ generated_files: z3.array(
510
+ z3.object({
511
+ media_type: z3.string(),
512
+ data: z3.string()
513
+ })
514
+ ).optional()
515
+ }).nullish(),
516
+ logprobs: z3.object({
517
+ content: z3.array(
518
+ z3.object({
519
+ token: z3.string(),
520
+ logprob: z3.number(),
521
+ top_logprobs: z3.array(
522
+ z3.object({
523
+ token: z3.string(),
524
+ logprob: z3.number()
525
+ })
526
+ )
527
+ })
528
+ ).nullish()
529
+ }).nullish(),
530
+ finish_reason: z3.string().nullish(),
531
+ index: z3.number()
532
+ })
533
+ ),
534
+ usage: z3.object({
535
+ completion_tokens: z3.number(),
536
+ prompt_tokens: z3.number(),
537
+ total_tokens: z3.number(),
538
+ reasoning_tokens: z3.number().optional(),
539
+ cached_input_tokens: z3.number().optional()
540
+ }).optional(),
541
+ provider: z3.string().optional(),
542
+ service_tier: z3.string().optional(),
543
+ system_fingerprint: z3.string().optional()
544
+ }),
545
+ z3.object({
546
+ error: z3.object({
547
+ message: z3.string(),
548
+ type: z3.string(),
549
+ param: z3.any().nullish(),
550
+ code: z3.any().nullish()
551
+ }),
552
+ provider: z3.string().optional()
553
+ })
554
+ ]);
555
+ var NordlysChatLanguageModel = class {
556
+ constructor(modelId, config) {
557
+ this.specificationVersion = "v3";
558
+ this.supportedUrls = {
559
+ "application/pdf": [/^https:\/\/.*$/]
560
+ };
561
+ this.modelId = modelId;
562
+ this.config = config;
563
+ }
564
+ get provider() {
565
+ return this.config.provider;
566
+ }
567
+ async getArgs({
568
+ prompt,
569
+ maxOutputTokens,
570
+ temperature,
571
+ topP,
572
+ topK,
573
+ frequencyPenalty,
574
+ presencePenalty,
575
+ stopSequences,
576
+ responseFormat,
577
+ providerOptions,
578
+ tools,
579
+ toolChoice
580
+ }) {
581
+ const warnings = [];
582
+ if (topK != null) {
583
+ warnings.push({ type: "unsupported", feature: "topK" });
584
+ }
585
+ if (responseFormat != null) {
586
+ warnings.push({ type: "unsupported", feature: "responseFormat" });
587
+ }
588
+ const result = nordlysProviderOptions.safeParse(providerOptions != null ? providerOptions : {});
589
+ const nordlysOptions = result.success ? result.data : {};
590
+ const {
591
+ tools: nordlysTools,
592
+ toolChoice: nordlysToolChoice,
593
+ toolWarnings
594
+ } = prepareTools({
595
+ tools,
596
+ toolChoice
597
+ });
598
+ warnings.push(...toolWarnings);
599
+ const { messages, warnings: messageWarnings } = convertToNordlysChatMessages({ prompt });
600
+ warnings.push(...messageWarnings);
601
+ const standardizedArgs = {
602
+ messages,
603
+ model: this.modelId,
604
+ max_tokens: typeof maxOutputTokens === "number" ? maxOutputTokens : void 0,
605
+ max_completion_tokens: nordlysOptions.max_completion_tokens,
606
+ temperature,
607
+ top_p: topP,
608
+ stop: stopSequences,
609
+ presence_penalty: presencePenalty,
610
+ frequency_penalty: frequencyPenalty,
611
+ user: nordlysOptions.user,
612
+ tools: nordlysTools,
613
+ tool_choice: nordlysToolChoice
614
+ };
615
+ const args = {
616
+ ...standardizedArgs,
617
+ ...nordlysOptions.logit_bias ? { logit_bias: nordlysOptions.logit_bias } : {},
618
+ ...nordlysOptions.audio ? { audio: nordlysOptions.audio } : {},
619
+ ...nordlysOptions.logprobs !== void 0 ? { logprobs: nordlysOptions.logprobs } : {},
620
+ ...nordlysOptions.metadata ? { metadata: nordlysOptions.metadata } : {},
621
+ ...nordlysOptions.modalities ? { modalities: nordlysOptions.modalities } : {},
622
+ ...nordlysOptions.parallel_tool_calls !== void 0 ? { parallel_tool_calls: nordlysOptions.parallel_tool_calls } : {},
623
+ ...nordlysOptions.prediction ? { prediction: nordlysOptions.prediction } : {},
624
+ ...nordlysOptions.reasoning_effort ? { reasoning_effort: nordlysOptions.reasoning_effort } : {},
625
+ ...nordlysOptions.response_format ? { response_format: nordlysOptions.response_format } : {},
626
+ ...nordlysOptions.seed !== void 0 ? { seed: nordlysOptions.seed } : {},
627
+ ...nordlysOptions.service_tier ? { service_tier: nordlysOptions.service_tier } : {},
628
+ ...nordlysOptions.store !== void 0 ? { store: nordlysOptions.store } : {},
629
+ ...nordlysOptions.top_logprobs !== void 0 ? { top_logprobs: nordlysOptions.top_logprobs } : {},
630
+ ...nordlysOptions.web_search_options ? { web_search_options: nordlysOptions.web_search_options } : {}
631
+ };
632
+ return {
633
+ args,
634
+ warnings
635
+ };
636
+ }
637
+ async doGenerate(options) {
638
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
639
+ const { args: body, warnings } = await this.getArgs(options);
640
+ const { responseHeaders, value, rawValue } = await postJsonToApi({
641
+ url: `${this.config.baseURL}/chat/completions`,
642
+ headers: combineHeaders(this.config.headers(), options.headers),
643
+ body,
644
+ failedResponseHandler: nordlysFailedResponseHandler,
645
+ successfulResponseHandler: createJsonResponseHandler(
646
+ nordlysChatResponseSchema
647
+ ),
648
+ abortSignal: options.abortSignal,
649
+ fetch: this.config.fetch
650
+ });
651
+ if (!value) {
652
+ throw new Error("Failed to parse Nordlys API response");
653
+ }
654
+ if (value.error) {
655
+ throw new Error(`Nordlys API Error: ${value.error.message}`);
656
+ }
657
+ if (!value.choices || value.choices.length === 0) {
658
+ throw new Error("No choices returned from Nordlys API");
659
+ }
660
+ const choice = value.choices[0];
661
+ const content = [];
662
+ if ((_a = choice.message) == null ? void 0 : _a.content) {
663
+ content.push({ type: "text", text: choice.message.content });
664
+ }
665
+ if ((_b = choice.message) == null ? void 0 : _b.reasoning_content) {
666
+ content.push({
667
+ type: "reasoning",
668
+ text: choice.message.reasoning_content
669
+ });
670
+ }
671
+ if (((_c = choice.message) == null ? void 0 : _c.generated_files) && choice.message.generated_files.length > 0) {
672
+ for (const file of choice.message.generated_files) {
673
+ content.push({
674
+ type: "file",
675
+ mediaType: file.media_type,
676
+ data: file.data
677
+ });
678
+ }
679
+ }
680
+ if (((_d = choice.message) == null ? void 0 : _d.tool_calls) && choice.message.tool_calls.length > 0) {
681
+ for (const toolCall of choice.message.tool_calls) {
682
+ content.push({
683
+ type: "tool-call",
684
+ toolCallId: toolCall.id || "",
685
+ toolName: ((_e = toolCall.function) == null ? void 0 : _e.name) || "",
686
+ input: ((_f = toolCall.function) == null ? void 0 : _f.arguments) || "{}"
687
+ });
688
+ }
689
+ }
690
+ const {
691
+ prompt_tokens,
692
+ completion_tokens,
693
+ reasoning_tokens,
694
+ cached_input_tokens
695
+ } = (_g = value.usage) != null ? _g : {};
696
+ return {
697
+ content,
698
+ finishReason: choice.finish_reason ? mapNordlysFinishReason(choice.finish_reason) : { unified: "stop", raw: void 0 },
699
+ usage: value.usage && prompt_tokens != null ? {
700
+ inputTokens: {
701
+ total: prompt_tokens,
702
+ noCache: cached_input_tokens != null ? prompt_tokens - cached_input_tokens : void 0,
703
+ cacheRead: cached_input_tokens,
704
+ cacheWrite: void 0
705
+ },
706
+ outputTokens: {
707
+ total: completion_tokens,
708
+ text: completion_tokens != null && reasoning_tokens != null ? completion_tokens - reasoning_tokens : void 0,
709
+ reasoning: reasoning_tokens
710
+ }
711
+ } : {
712
+ inputTokens: {
713
+ total: 0,
714
+ noCache: void 0,
715
+ cacheRead: void 0,
716
+ cacheWrite: void 0
717
+ },
718
+ outputTokens: { total: 0, text: void 0, reasoning: void 0 }
719
+ },
720
+ providerMetadata: value.provider ? {
721
+ nordlys: {
722
+ provider: value.provider,
723
+ service_tier: value.service_tier,
724
+ system_fingerprint: value.system_fingerprint
725
+ }
726
+ } : void 0,
727
+ request: { body },
728
+ response: {
729
+ id: (_h = value.id) != null ? _h : "",
730
+ modelId: (_i = value.model) != null ? _i : "",
731
+ timestamp: new Date(((_j = value.created) != null ? _j : 0) * 1e3),
732
+ headers: responseHeaders,
733
+ body: rawValue
734
+ },
735
+ warnings
736
+ };
737
+ }
738
+ async doStream(options) {
739
+ const { args, warnings } = await this.getArgs(options);
740
+ const body = {
741
+ ...args,
742
+ stream: true,
743
+ stream_options: { include_usage: true }
744
+ };
745
+ const { responseHeaders, value: response } = await postJsonToApi({
746
+ url: `${this.config.baseURL}/chat/completions`,
747
+ headers: combineHeaders(this.config.headers(), options.headers),
748
+ body,
749
+ failedResponseHandler: nordlysFailedResponseHandler,
750
+ successfulResponseHandler: createEventSourceResponseHandler(
751
+ nordlysChatChunkSchema
752
+ ),
753
+ abortSignal: options.abortSignal,
754
+ fetch: this.config.fetch
755
+ });
756
+ const toolCalls = [];
757
+ const state = {
758
+ finishReason: { unified: "other", raw: void 0 },
759
+ usage: {
760
+ inputTokens: {
761
+ total: void 0,
762
+ noCache: void 0,
763
+ cacheRead: void 0,
764
+ cacheWrite: void 0
765
+ },
766
+ outputTokens: {
767
+ total: void 0,
768
+ text: void 0,
769
+ reasoning: void 0
770
+ }
771
+ },
772
+ isFirstChunk: true,
773
+ isActiveText: false,
774
+ provider: void 0,
775
+ serviceTier: void 0,
776
+ systemFingerprint: void 0
777
+ };
778
+ return {
779
+ stream: response.pipeThrough(
780
+ new TransformStream({
781
+ start(controller) {
782
+ controller.enqueue({ type: "stream-start", warnings });
783
+ },
784
+ async transform(chunk, controller) {
785
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s;
786
+ if (!chunk.success) {
787
+ state.finishReason = { unified: "error", raw: void 0 };
788
+ controller.enqueue({ type: "error", error: chunk.error });
789
+ return;
790
+ }
791
+ const value = chunk.value;
792
+ if ("error" in value) {
793
+ state.finishReason = { unified: "error", raw: void 0 };
794
+ controller.enqueue({
795
+ type: "error",
796
+ error: new Error(value.error.message)
797
+ });
798
+ return;
799
+ }
800
+ if (state.isFirstChunk) {
801
+ state.isFirstChunk = false;
802
+ controller.enqueue({
803
+ type: "response-metadata",
804
+ ...getResponseMetadata({
805
+ id: (_a = value.id) != null ? _a : "",
806
+ model: (_b = value.model) != null ? _b : "",
807
+ created: (_c = value.created) != null ? _c : 0
808
+ })
809
+ });
810
+ }
811
+ if (value.usage != null) {
812
+ state.usage.inputTokens.total = (_d = value.usage.prompt_tokens) != null ? _d : void 0;
813
+ state.usage.inputTokens.cacheRead = (_e = value.usage.cached_input_tokens) != null ? _e : void 0;
814
+ state.usage.inputTokens.noCache = value.usage.prompt_tokens != null && value.usage.cached_input_tokens != null ? value.usage.prompt_tokens - value.usage.cached_input_tokens : void 0;
815
+ state.usage.outputTokens.total = (_f = value.usage.completion_tokens) != null ? _f : void 0;
816
+ state.usage.outputTokens.reasoning = (_g = value.usage.reasoning_tokens) != null ? _g : void 0;
817
+ state.usage.outputTokens.text = value.usage.completion_tokens != null && value.usage.reasoning_tokens != null ? value.usage.completion_tokens - value.usage.reasoning_tokens : void 0;
818
+ }
819
+ if (value.provider) {
820
+ state.provider = value.provider;
821
+ }
822
+ if (value.service_tier) {
823
+ state.serviceTier = value.service_tier;
824
+ }
825
+ if (value.system_fingerprint) {
826
+ state.systemFingerprint = value.system_fingerprint;
827
+ }
828
+ const choice = value.choices[0];
829
+ if ((choice == null ? void 0 : choice.finish_reason) != null) {
830
+ state.finishReason = mapNordlysFinishReason(choice.finish_reason);
831
+ }
832
+ if (!(choice == null ? void 0 : choice.delta)) {
833
+ return;
834
+ }
835
+ const delta = choice.delta;
836
+ if (delta.content != null) {
837
+ if (!state.isActiveText) {
838
+ controller.enqueue({ type: "text-start", id: "text-1" });
839
+ state.isActiveText = true;
840
+ }
841
+ controller.enqueue({
842
+ type: "text-delta",
843
+ id: "text-1",
844
+ delta: delta.content
845
+ });
846
+ }
847
+ if (delta.reasoning_content != null) {
848
+ controller.enqueue({
849
+ type: "reasoning-delta",
850
+ id: "reasoning-1",
851
+ delta: delta.reasoning_content
852
+ });
853
+ }
854
+ if (delta.generated_files != null && Array.isArray(delta.generated_files)) {
855
+ for (const file of delta.generated_files) {
856
+ controller.enqueue({
857
+ type: "file",
858
+ mediaType: file.media_type,
859
+ data: file.data
860
+ });
861
+ }
862
+ }
863
+ if (delta.tool_calls != null && Array.isArray(delta.tool_calls)) {
864
+ for (const toolCallDelta of delta.tool_calls) {
865
+ const index = toolCallDelta.index;
866
+ if (toolCalls[index] == null) {
867
+ if (toolCallDelta.type !== "function" && toolCallDelta.type !== "") {
868
+ throw new InvalidResponseDataError({
869
+ data: toolCallDelta,
870
+ message: `Expected 'function' type.`
871
+ });
872
+ }
873
+ if (toolCallDelta.id == null) {
874
+ throw new InvalidResponseDataError({
875
+ data: toolCallDelta,
876
+ message: `Expected 'id' to be a string.`
877
+ });
878
+ }
879
+ if (((_h = toolCallDelta.function) == null ? void 0 : _h.name) == null) {
880
+ throw new InvalidResponseDataError({
881
+ data: toolCallDelta,
882
+ message: `Expected 'function.name' to be a string.`
883
+ });
884
+ }
885
+ controller.enqueue({
886
+ type: "tool-input-start",
887
+ id: toolCallDelta.id,
888
+ toolName: toolCallDelta.function.name
889
+ });
890
+ toolCalls[index] = {
891
+ id: toolCallDelta.id,
892
+ type: "function",
893
+ function: {
894
+ name: toolCallDelta.function.name,
895
+ arguments: (_i = toolCallDelta.function.arguments) != null ? _i : ""
896
+ },
897
+ hasFinished: false
898
+ };
899
+ const toolCall2 = toolCalls[index];
900
+ if (((_j = toolCall2.function) == null ? void 0 : _j.name) != null && ((_k = toolCall2.function) == null ? void 0 : _k.arguments) != null) {
901
+ if (toolCall2.function.arguments.length > 0) {
902
+ controller.enqueue({
903
+ type: "tool-input-delta",
904
+ id: toolCall2.id,
905
+ delta: toolCall2.function.arguments
906
+ });
907
+ }
908
+ if (isParsableJson(toolCall2.function.arguments)) {
909
+ controller.enqueue({
910
+ type: "tool-input-end",
911
+ id: toolCall2.id
912
+ });
913
+ controller.enqueue({
914
+ type: "tool-call",
915
+ toolCallId: (_l = toolCall2.id) != null ? _l : generateId(),
916
+ toolName: toolCall2.function.name,
917
+ input: toolCall2.function.arguments
918
+ });
919
+ toolCall2.hasFinished = true;
920
+ }
921
+ }
922
+ continue;
923
+ }
924
+ const toolCall = toolCalls[index];
925
+ if (toolCall.hasFinished) {
926
+ continue;
927
+ }
928
+ if (((_m = toolCallDelta.function) == null ? void 0 : _m.arguments) != null) {
929
+ toolCall.function.arguments += (_o = (_n = toolCallDelta.function) == null ? void 0 : _n.arguments) != null ? _o : "";
930
+ }
931
+ controller.enqueue({
932
+ type: "tool-input-delta",
933
+ id: toolCall.id,
934
+ delta: (_p = toolCallDelta.function.arguments) != null ? _p : ""
935
+ });
936
+ if (((_q = toolCall.function) == null ? void 0 : _q.name) != null && ((_r = toolCall.function) == null ? void 0 : _r.arguments) != null && isParsableJson(toolCall.function.arguments)) {
937
+ controller.enqueue({
938
+ type: "tool-input-end",
939
+ id: toolCall.id
940
+ });
941
+ controller.enqueue({
942
+ type: "tool-call",
943
+ toolCallId: (_s = toolCall.id) != null ? _s : generateId(),
944
+ toolName: toolCall.function.name,
945
+ input: toolCall.function.arguments
946
+ });
947
+ toolCall.hasFinished = true;
948
+ }
949
+ }
950
+ }
951
+ },
952
+ flush(controller) {
953
+ var _a, _b;
954
+ if (state.isActiveText) {
955
+ controller.enqueue({ type: "text-end", id: "text-1" });
956
+ }
957
+ controller.enqueue({
958
+ type: "finish",
959
+ finishReason: (_a = state.finishReason) != null ? _a : {
960
+ unified: "stop",
961
+ raw: void 0
962
+ },
963
+ usage: (_b = state.usage) != null ? _b : {
964
+ inputTokens: {
965
+ total: 0,
966
+ noCache: void 0,
967
+ cacheRead: void 0,
968
+ cacheWrite: void 0
969
+ },
970
+ outputTokens: {
971
+ total: 0,
972
+ text: void 0,
973
+ reasoning: void 0
974
+ }
975
+ },
976
+ providerMetadata: state.provider || state.serviceTier || state.systemFingerprint ? {
977
+ nordlys: {
978
+ provider: state.provider,
979
+ service_tier: state.serviceTier,
980
+ system_fingerprint: state.systemFingerprint
981
+ }
982
+ } : void 0
983
+ });
984
+ }
985
+ })
986
+ ),
987
+ request: { body },
988
+ response: {
989
+ headers: responseHeaders
990
+ }
991
+ };
992
+ }
993
+ };
994
+
995
+ // src/nordlys-provider.ts
996
+ function createNordlys(options = {}) {
997
+ var _a;
998
+ const baseURL = (_a = withoutTrailingSlash(options.baseURL)) != null ? _a : "https://backend.mangoplant-a7a21605.swedencentral.azurecontainerapps.io/v1";
999
+ const getHeaders = () => ({
1000
+ Authorization: `Bearer ${loadApiKey({
1001
+ apiKey: options.apiKey,
1002
+ environmentVariableName: "NORDLYS_API_KEY",
1003
+ description: "Nordlys"
1004
+ })}`,
1005
+ "Content-Type": "application/json",
1006
+ ...options.headers
1007
+ });
1008
+ const createChatModel = (modelId) => new NordlysChatLanguageModel(modelId, {
1009
+ provider: "nordlys.chat",
1010
+ baseURL,
1011
+ headers: getHeaders,
1012
+ fetch: options.fetch
1013
+ });
1014
+ const provider = function(modelId) {
1015
+ if (new.target) {
1016
+ throw new Error(
1017
+ "The Nordlys model function cannot be called with the new keyword."
1018
+ );
1019
+ }
1020
+ return createChatModel(modelId);
1021
+ };
1022
+ provider.languageModel = createChatModel;
1023
+ provider.chat = createChatModel;
1024
+ provider.embeddingModel = (modelId) => {
1025
+ throw new NoSuchModelError({ modelId, modelType: "embeddingModel" });
1026
+ };
1027
+ provider.imageModel = (modelId) => {
1028
+ throw new NoSuchModelError({ modelId, modelType: "imageModel" });
1029
+ };
1030
+ provider.specificationVersion = "v3";
1031
+ return Object.freeze(provider);
1032
+ }
1033
+ var nordlys = createNordlys();
1034
+ export {
1035
+ createNordlys,
1036
+ nordlys
1037
+ };
1038
+ //# sourceMappingURL=index.js.map