@apertis/ai-sdk-provider 0.1.1 → 1.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 CHANGED
@@ -93,17 +93,18 @@ var openAIChatChunkSchema = z2.object({
93
93
 
94
94
  // src/utils/map-finish-reason.ts
95
95
  function mapApertisFinishReason(finishReason) {
96
+ const raw = finishReason ?? void 0;
96
97
  switch (finishReason) {
97
98
  case "stop":
98
- return "stop";
99
+ return { unified: "stop", raw };
99
100
  case "length":
100
- return "length";
101
+ return { unified: "length", raw };
101
102
  case "tool_calls":
102
- return "tool-calls";
103
+ return { unified: "tool-calls", raw };
103
104
  case "content_filter":
104
- return "content-filter";
105
+ return { unified: "content-filter", raw };
105
106
  default:
106
- return "unknown";
107
+ return { unified: "other", raw };
107
108
  }
108
109
  }
109
110
 
@@ -122,13 +123,29 @@ function convertToOpenAIMessages(prompt) {
122
123
  switch (part.type) {
123
124
  case "text":
124
125
  return { type: "text", text: part.text };
125
- case "image":
126
- return {
127
- type: "image_url",
128
- image_url: {
129
- url: part.image instanceof URL ? part.image.toString() : `data:${part.mimeType ?? "image/png"};base64,${Buffer.from(part.image).toString("base64")}`
126
+ case "file": {
127
+ if (part.mediaType?.startsWith("image/")) {
128
+ let url;
129
+ if (part.data instanceof URL) {
130
+ url = part.data.toString();
131
+ } else if (typeof part.data === "string") {
132
+ if (part.data.startsWith("http://") || part.data.startsWith("https://")) {
133
+ url = part.data;
134
+ } else {
135
+ url = `data:${part.mediaType};base64,${part.data}`;
136
+ }
137
+ } else {
138
+ url = `data:${part.mediaType};base64,${Buffer.from(part.data).toString("base64")}`;
130
139
  }
131
- };
140
+ return {
141
+ type: "image_url",
142
+ image_url: { url }
143
+ };
144
+ }
145
+ throw new Error(
146
+ `Unsupported file type: ${part.mediaType}. Only image/* is supported.`
147
+ );
148
+ }
132
149
  default:
133
150
  throw new Error(
134
151
  `Unsupported user content part type: ${part.type}`
@@ -139,12 +156,10 @@ function convertToOpenAIMessages(prompt) {
139
156
  break;
140
157
  case "assistant": {
141
158
  const textContent = message.content.filter((p) => p.type === "text").map((p) => p.text).join("");
142
- const toolCalls = message.content.filter(
143
- (p) => p.type === "tool-call"
144
- ).map((tc) => {
159
+ const toolCalls = message.content.filter((p) => p.type === "tool-call").map((tc) => {
145
160
  let arguments_str = "{}";
146
161
  try {
147
- arguments_str = JSON.stringify(tc.args);
162
+ arguments_str = typeof tc.input === "string" ? tc.input : JSON.stringify(tc.input);
148
163
  } catch {
149
164
  arguments_str = "{}";
150
165
  }
@@ -163,12 +178,17 @@ function convertToOpenAIMessages(prompt) {
163
178
  }
164
179
  case "tool":
165
180
  for (const result of message.content) {
181
+ if (result.type !== "tool-result") continue;
166
182
  let content = "{}";
167
- if (typeof result.result === "string") {
168
- content = result.result;
183
+ const output = result.output;
184
+ if (typeof output === "string") {
185
+ content = output;
186
+ } else if (Array.isArray(output)) {
187
+ const textParts = output.filter((p) => p.type === "text").map((p) => p.text);
188
+ content = textParts.join("");
169
189
  } else {
170
190
  try {
171
- content = JSON.stringify(result.result);
191
+ content = JSON.stringify(output);
172
192
  } catch {
173
193
  content = "{}";
174
194
  }
@@ -193,7 +213,7 @@ function convertToOpenAITools(tools) {
193
213
  function: {
194
214
  name: tool.name,
195
215
  description: tool.description,
196
- parameters: tool.parameters
216
+ parameters: tool.inputSchema
197
217
  }
198
218
  }));
199
219
  }
@@ -207,7 +227,11 @@ function convertToOpenAIToolChoice(toolChoice) {
207
227
  case "required":
208
228
  return "required";
209
229
  case "tool":
210
- return { type: "function", function: { name: toolChoice.toolName } };
230
+ if (!toolChoice.toolName) return void 0;
231
+ return {
232
+ type: "function",
233
+ function: { name: toolChoice.toolName }
234
+ };
211
235
  default:
212
236
  return void 0;
213
237
  }
@@ -220,15 +244,17 @@ var ApertisChatLanguageModel = class {
220
244
  this.settings = settings;
221
245
  this.config = config;
222
246
  }
223
- specificationVersion = "v1";
224
- defaultObjectGenerationMode = "json";
225
- supportsImageUrls = true;
247
+ specificationVersion = "v3";
248
+ /**
249
+ * Supported URL patterns for different media types.
250
+ * Supports HTTP(S) image URLs for direct URL passing.
251
+ */
252
+ supportedUrls = {
253
+ "image/*": [/^https?:\/\/.+$/]
254
+ };
226
255
  get provider() {
227
256
  return this.config.provider;
228
257
  }
229
- get supportsStructuredOutputs() {
230
- return true;
231
- }
232
258
  async doGenerate(options) {
233
259
  const body = this.buildRequestBody(options, false);
234
260
  const { value: response } = await postJsonToApi({
@@ -243,20 +269,41 @@ var ApertisChatLanguageModel = class {
243
269
  abortSignal: options.abortSignal
244
270
  });
245
271
  const choice = response.choices[0];
272
+ const content = [];
273
+ if (choice.message.content) {
274
+ content.push({
275
+ type: "text",
276
+ text: choice.message.content
277
+ });
278
+ }
279
+ if (choice.message.tool_calls) {
280
+ for (const tc of choice.message.tool_calls) {
281
+ content.push({
282
+ type: "tool-call",
283
+ toolCallId: tc.id,
284
+ toolName: tc.function.name,
285
+ input: tc.function.arguments
286
+ });
287
+ }
288
+ }
246
289
  return {
247
- text: choice.message.content ?? void 0,
248
- toolCalls: choice.message.tool_calls?.map((tc) => ({
249
- toolCallType: "function",
250
- toolCallId: tc.id,
251
- toolName: tc.function.name,
252
- args: tc.function.arguments
253
- })),
290
+ content,
254
291
  finishReason: mapApertisFinishReason(choice.finish_reason),
255
292
  usage: {
256
- promptTokens: response.usage?.prompt_tokens ?? 0,
257
- completionTokens: response.usage?.completion_tokens ?? 0
293
+ inputTokens: {
294
+ total: response.usage?.prompt_tokens ?? 0,
295
+ noCache: void 0,
296
+ cacheRead: void 0,
297
+ cacheWrite: void 0
298
+ },
299
+ outputTokens: {
300
+ total: response.usage?.completion_tokens ?? 0,
301
+ text: void 0,
302
+ reasoning: void 0
303
+ }
258
304
  },
259
- rawCall: { rawPrompt: options.prompt, rawSettings: body }
305
+ warnings: [],
306
+ request: { body }
260
307
  };
261
308
  }
262
309
  async doStream(options) {
@@ -273,6 +320,7 @@ var ApertisChatLanguageModel = class {
273
320
  abortSignal: options.abortSignal
274
321
  });
275
322
  const toolCallBuffers = /* @__PURE__ */ new Map();
323
+ let textId = null;
276
324
  const transformStream = new TransformStream({
277
325
  transform(parseResult, controller) {
278
326
  if (!parseResult.success) {
@@ -282,9 +330,17 @@ var ApertisChatLanguageModel = class {
282
330
  const choice = chunk.choices[0];
283
331
  if (!choice) return;
284
332
  if (choice.delta.content) {
333
+ if (!textId) {
334
+ textId = generateId();
335
+ controller.enqueue({
336
+ type: "text-start",
337
+ id: textId
338
+ });
339
+ }
285
340
  controller.enqueue({
286
341
  type: "text-delta",
287
- textDelta: choice.delta.content
342
+ id: textId,
343
+ delta: choice.delta.content
288
344
  });
289
345
  }
290
346
  if (choice.delta.tool_calls) {
@@ -301,14 +357,19 @@ var ApertisChatLanguageModel = class {
301
357
  }
302
358
  }
303
359
  if (choice.finish_reason) {
360
+ if (textId) {
361
+ controller.enqueue({
362
+ type: "text-end",
363
+ id: textId
364
+ });
365
+ }
304
366
  for (const [, buffer] of toolCallBuffers) {
305
367
  if (buffer.name) {
306
368
  controller.enqueue({
307
369
  type: "tool-call",
308
- toolCallType: "function",
309
370
  toolCallId: buffer.id,
310
371
  toolName: buffer.name,
311
- args: buffer.arguments
372
+ input: buffer.arguments
312
373
  });
313
374
  }
314
375
  }
@@ -317,21 +378,35 @@ var ApertisChatLanguageModel = class {
317
378
  type: "finish",
318
379
  finishReason: mapApertisFinishReason(choice.finish_reason),
319
380
  usage: {
320
- promptTokens: chunk.usage?.prompt_tokens ?? 0,
321
- completionTokens: chunk.usage?.completion_tokens ?? 0
381
+ inputTokens: {
382
+ total: chunk.usage?.prompt_tokens ?? 0,
383
+ noCache: void 0,
384
+ cacheRead: void 0,
385
+ cacheWrite: void 0
386
+ },
387
+ outputTokens: {
388
+ total: chunk.usage?.completion_tokens ?? 0,
389
+ text: void 0,
390
+ reasoning: void 0
391
+ }
322
392
  }
323
393
  });
324
394
  }
325
395
  },
326
396
  flush(controller) {
397
+ if (textId) {
398
+ controller.enqueue({
399
+ type: "text-end",
400
+ id: textId
401
+ });
402
+ }
327
403
  for (const [, buffer] of toolCallBuffers) {
328
404
  if (buffer.name) {
329
405
  controller.enqueue({
330
406
  type: "tool-call",
331
- toolCallType: "function",
332
407
  toolCallId: buffer.id,
333
408
  toolName: buffer.name,
334
- args: buffer.arguments
409
+ input: buffer.arguments
335
410
  });
336
411
  }
337
412
  }
@@ -339,13 +414,12 @@ var ApertisChatLanguageModel = class {
339
414
  });
340
415
  return {
341
416
  stream: response.pipeThrough(transformStream),
342
- rawCall: { rawPrompt: options.prompt, rawSettings: body }
417
+ request: { body }
343
418
  };
344
419
  }
345
420
  buildRequestBody(options, stream) {
346
- const tools = options.mode.type === "regular" ? this.filterFunctionTools(options.mode.tools) : void 0;
347
- const toolChoice = options.mode.type === "regular" ? options.mode.toolChoice : void 0;
348
- const responseFormat = options.mode.type === "object-json" ? { type: "json_object" } : void 0;
421
+ const tools = this.filterFunctionTools(options.tools);
422
+ const responseFormat = options.responseFormat?.type === "json" ? { type: "json_object" } : void 0;
349
423
  const body = {
350
424
  model: this.modelId,
351
425
  messages: convertToOpenAIMessages(options.prompt),
@@ -354,7 +428,8 @@ var ApertisChatLanguageModel = class {
354
428
  if (stream) body.stream_options = { include_usage: true };
355
429
  if (options.temperature !== void 0)
356
430
  body.temperature = options.temperature;
357
- if (options.maxTokens !== void 0) body.max_tokens = options.maxTokens;
431
+ if (options.maxOutputTokens !== void 0)
432
+ body.max_tokens = options.maxOutputTokens;
358
433
  if (options.topP !== void 0) body.top_p = options.topP;
359
434
  if (options.frequencyPenalty !== void 0)
360
435
  body.frequency_penalty = options.frequencyPenalty;
@@ -364,7 +439,7 @@ var ApertisChatLanguageModel = class {
364
439
  if (options.seed !== void 0) body.seed = options.seed;
365
440
  const convertedTools = convertToOpenAITools(tools);
366
441
  if (convertedTools !== void 0) body.tools = convertedTools;
367
- const convertedToolChoice = convertToOpenAIToolChoice(toolChoice);
442
+ const convertedToolChoice = convertToOpenAIToolChoice(options.toolChoice);
368
443
  if (convertedToolChoice !== void 0)
369
444
  body.tool_choice = convertedToolChoice;
370
445
  if (responseFormat !== void 0) body.response_format = responseFormat;
@@ -383,6 +458,327 @@ var ApertisChatLanguageModel = class {
383
458
  }
384
459
  };
385
460
 
461
+ // src/apertis-completion-language-model.ts
462
+ import {
463
+ createEventSourceResponseHandler as createEventSourceResponseHandler2,
464
+ createJsonResponseHandler as createJsonResponseHandler2,
465
+ generateId as generateId2,
466
+ postJsonToApi as postJsonToApi2
467
+ } from "@ai-sdk/provider-utils";
468
+
469
+ // src/schemas/completion-response.ts
470
+ import { z as z3 } from "zod";
471
+ var openAICompletionResponseSchema = z3.object({
472
+ id: z3.string(),
473
+ object: z3.literal("text_completion"),
474
+ created: z3.number(),
475
+ model: z3.string(),
476
+ choices: z3.array(
477
+ z3.object({
478
+ text: z3.string(),
479
+ index: z3.number(),
480
+ logprobs: z3.object({
481
+ tokens: z3.array(z3.string()).optional(),
482
+ token_logprobs: z3.array(z3.number()).optional(),
483
+ top_logprobs: z3.array(z3.record(z3.number())).optional(),
484
+ text_offset: z3.array(z3.number()).optional()
485
+ }).nullable().optional(),
486
+ finish_reason: z3.string().nullable().optional()
487
+ })
488
+ ),
489
+ usage: z3.object({
490
+ prompt_tokens: z3.number(),
491
+ completion_tokens: z3.number(),
492
+ total_tokens: z3.number()
493
+ }).optional()
494
+ });
495
+ var openAICompletionChunkSchema = z3.object({
496
+ id: z3.string(),
497
+ object: z3.literal("text_completion"),
498
+ created: z3.number(),
499
+ model: z3.string(),
500
+ choices: z3.array(
501
+ z3.object({
502
+ text: z3.string(),
503
+ index: z3.number(),
504
+ logprobs: z3.object({
505
+ tokens: z3.array(z3.string()).optional(),
506
+ token_logprobs: z3.array(z3.number()).optional(),
507
+ top_logprobs: z3.array(z3.record(z3.number())).optional(),
508
+ text_offset: z3.array(z3.number()).optional()
509
+ }).nullable().optional(),
510
+ finish_reason: z3.string().nullable().optional()
511
+ })
512
+ ),
513
+ usage: z3.object({
514
+ prompt_tokens: z3.number(),
515
+ completion_tokens: z3.number(),
516
+ total_tokens: z3.number()
517
+ }).optional().nullable()
518
+ });
519
+
520
+ // src/apertis-completion-language-model.ts
521
+ var ApertisCompletionLanguageModel = class {
522
+ constructor(modelId, settings, config) {
523
+ this.modelId = modelId;
524
+ this.settings = settings;
525
+ this.config = config;
526
+ }
527
+ specificationVersion = "v3";
528
+ supportedUrls = {};
529
+ get provider() {
530
+ return this.config.provider;
531
+ }
532
+ async doGenerate(options) {
533
+ const body = this.buildRequestBody(options, false);
534
+ const { value: response } = await postJsonToApi2({
535
+ url: `${this.config.baseURL}/completions`,
536
+ headers: this.config.headers(),
537
+ body,
538
+ failedResponseHandler: apertisFailedResponseHandler,
539
+ successfulResponseHandler: createJsonResponseHandler2(
540
+ openAICompletionResponseSchema
541
+ ),
542
+ fetch: this.config.fetch,
543
+ abortSignal: options.abortSignal
544
+ });
545
+ const choice = response.choices[0];
546
+ const content = [];
547
+ if (choice.text) {
548
+ content.push({
549
+ type: "text",
550
+ text: choice.text
551
+ });
552
+ }
553
+ return {
554
+ content,
555
+ finishReason: this.mapFinishReason(choice.finish_reason),
556
+ usage: {
557
+ inputTokens: {
558
+ total: response.usage?.prompt_tokens ?? 0,
559
+ noCache: void 0,
560
+ cacheRead: void 0,
561
+ cacheWrite: void 0
562
+ },
563
+ outputTokens: {
564
+ total: response.usage?.completion_tokens ?? 0,
565
+ text: void 0,
566
+ reasoning: void 0
567
+ }
568
+ },
569
+ warnings: [],
570
+ request: { body }
571
+ };
572
+ }
573
+ async doStream(options) {
574
+ const body = this.buildRequestBody(options, true);
575
+ const { value: response } = await postJsonToApi2({
576
+ url: `${this.config.baseURL}/completions`,
577
+ headers: this.config.headers(),
578
+ body,
579
+ failedResponseHandler: apertisFailedResponseHandler,
580
+ successfulResponseHandler: createEventSourceResponseHandler2(
581
+ openAICompletionChunkSchema
582
+ ),
583
+ fetch: this.config.fetch,
584
+ abortSignal: options.abortSignal
585
+ });
586
+ let textId = null;
587
+ const transformStream = new TransformStream({
588
+ transform(parseResult, controller) {
589
+ if (!parseResult.success) {
590
+ return;
591
+ }
592
+ const chunk = parseResult.value;
593
+ const choice = chunk.choices[0];
594
+ if (!choice) return;
595
+ if (choice.text) {
596
+ if (!textId) {
597
+ textId = generateId2();
598
+ controller.enqueue({
599
+ type: "text-start",
600
+ id: textId
601
+ });
602
+ }
603
+ controller.enqueue({
604
+ type: "text-delta",
605
+ id: textId,
606
+ delta: choice.text
607
+ });
608
+ }
609
+ if (choice.finish_reason) {
610
+ if (textId) {
611
+ controller.enqueue({
612
+ type: "text-end",
613
+ id: textId
614
+ });
615
+ }
616
+ controller.enqueue({
617
+ type: "finish",
618
+ finishReason: {
619
+ unified: choice.finish_reason === "stop" ? "stop" : choice.finish_reason === "length" ? "length" : "other",
620
+ raw: choice.finish_reason ?? void 0
621
+ },
622
+ usage: {
623
+ inputTokens: {
624
+ total: chunk.usage?.prompt_tokens ?? 0,
625
+ noCache: void 0,
626
+ cacheRead: void 0,
627
+ cacheWrite: void 0
628
+ },
629
+ outputTokens: {
630
+ total: chunk.usage?.completion_tokens ?? 0,
631
+ text: void 0,
632
+ reasoning: void 0
633
+ }
634
+ }
635
+ });
636
+ }
637
+ },
638
+ flush(controller) {
639
+ if (textId) {
640
+ controller.enqueue({
641
+ type: "text-end",
642
+ id: textId
643
+ });
644
+ }
645
+ }
646
+ });
647
+ return {
648
+ stream: response.pipeThrough(transformStream),
649
+ request: { body }
650
+ };
651
+ }
652
+ buildRequestBody(options, stream) {
653
+ const prompt = this.convertPromptToText(options.prompt);
654
+ const body = {
655
+ model: this.modelId,
656
+ prompt,
657
+ stream
658
+ };
659
+ if (stream) body.stream_options = { include_usage: true };
660
+ if (options.maxOutputTokens !== void 0)
661
+ body.max_tokens = options.maxOutputTokens;
662
+ if (options.temperature !== void 0)
663
+ body.temperature = options.temperature;
664
+ if (options.topP !== void 0) body.top_p = options.topP;
665
+ if (options.frequencyPenalty !== void 0)
666
+ body.frequency_penalty = options.frequencyPenalty;
667
+ if (options.presencePenalty !== void 0)
668
+ body.presence_penalty = options.presencePenalty;
669
+ if (options.stopSequences !== void 0) body.stop = options.stopSequences;
670
+ if (options.seed !== void 0) body.seed = options.seed;
671
+ if (this.settings.echo !== void 0) body.echo = this.settings.echo;
672
+ if (this.settings.logprobs !== void 0)
673
+ body.logprobs = this.settings.logprobs;
674
+ if (this.settings.suffix !== void 0) body.suffix = this.settings.suffix;
675
+ if (this.settings.user !== void 0) body.user = this.settings.user;
676
+ return body;
677
+ }
678
+ convertPromptToText(prompt) {
679
+ const parts = [];
680
+ for (const message of prompt) {
681
+ if (message.role === "system") {
682
+ parts.push(message.content);
683
+ } else if (message.role === "user") {
684
+ for (const part of message.content) {
685
+ if (part.type === "text") {
686
+ parts.push(part.text);
687
+ }
688
+ }
689
+ } else if (message.role === "assistant") {
690
+ for (const part of message.content) {
691
+ if (part.type === "text") {
692
+ parts.push(part.text);
693
+ }
694
+ }
695
+ }
696
+ }
697
+ return parts.join("\n\n");
698
+ }
699
+ mapFinishReason(finishReason) {
700
+ const raw = finishReason ?? void 0;
701
+ switch (finishReason) {
702
+ case "stop":
703
+ return { unified: "stop", raw };
704
+ case "length":
705
+ return { unified: "length", raw };
706
+ default:
707
+ return { unified: "other", raw };
708
+ }
709
+ }
710
+ };
711
+
712
+ // src/apertis-embedding-model.ts
713
+ import {
714
+ createJsonResponseHandler as createJsonResponseHandler3,
715
+ postJsonToApi as postJsonToApi3
716
+ } from "@ai-sdk/provider-utils";
717
+
718
+ // src/schemas/embedding-response.ts
719
+ import { z as z4 } from "zod";
720
+ var openAIEmbeddingResponseSchema = z4.object({
721
+ object: z4.literal("list"),
722
+ data: z4.array(
723
+ z4.object({
724
+ object: z4.literal("embedding"),
725
+ embedding: z4.array(z4.number()),
726
+ index: z4.number()
727
+ })
728
+ ),
729
+ model: z4.string(),
730
+ usage: z4.object({
731
+ prompt_tokens: z4.number(),
732
+ total_tokens: z4.number()
733
+ }).optional()
734
+ });
735
+
736
+ // src/apertis-embedding-model.ts
737
+ var ApertisEmbeddingModel = class {
738
+ constructor(modelId, settings, config) {
739
+ this.modelId = modelId;
740
+ this.settings = settings;
741
+ this.config = config;
742
+ this.maxEmbeddingsPerCall = settings.maxEmbeddingsPerCall ?? 2048;
743
+ this.supportsParallelCalls = settings.supportsParallelCalls ?? true;
744
+ }
745
+ specificationVersion = "v3";
746
+ maxEmbeddingsPerCall;
747
+ supportsParallelCalls;
748
+ get provider() {
749
+ return this.config.provider;
750
+ }
751
+ async doEmbed(options) {
752
+ const body = {
753
+ model: this.modelId,
754
+ input: options.values,
755
+ encoding_format: "float"
756
+ };
757
+ if (this.settings.dimensions !== void 0) {
758
+ body.dimensions = this.settings.dimensions;
759
+ }
760
+ if (this.settings.user !== void 0) {
761
+ body.user = this.settings.user;
762
+ }
763
+ const { value: response } = await postJsonToApi3({
764
+ url: `${this.config.baseURL}/embeddings`,
765
+ headers: this.config.headers(),
766
+ body,
767
+ failedResponseHandler: apertisFailedResponseHandler,
768
+ successfulResponseHandler: createJsonResponseHandler3(
769
+ openAIEmbeddingResponseSchema
770
+ ),
771
+ fetch: this.config.fetch,
772
+ abortSignal: options.abortSignal
773
+ });
774
+ return {
775
+ embeddings: response.data.map((item) => item.embedding),
776
+ usage: response.usage ? { tokens: response.usage.prompt_tokens } : void 0,
777
+ warnings: []
778
+ };
779
+ }
780
+ };
781
+
386
782
  // src/apertis-provider.ts
387
783
  function createApertis(options = {}) {
388
784
  const baseURL = withoutTrailingSlash(options.baseURL) ?? "https://api.apertis.ai/v1";
@@ -401,11 +797,30 @@ function createApertis(options = {}) {
401
797
  headers: getHeaders,
402
798
  fetch: options.fetch
403
799
  });
800
+ const createCompletionModel = (modelId, settings = {}) => new ApertisCompletionLanguageModel(modelId, settings, {
801
+ provider: "apertis.completion",
802
+ baseURL,
803
+ headers: getHeaders,
804
+ fetch: options.fetch
805
+ });
806
+ const createEmbeddingModel = (modelId, settings = {}) => new ApertisEmbeddingModel(modelId, settings, {
807
+ provider: "apertis.embedding",
808
+ baseURL,
809
+ headers: getHeaders,
810
+ fetch: options.fetch
811
+ });
404
812
  const provider = Object.assign(
405
813
  (modelId, settings) => createChatModel(modelId, settings),
406
814
  {
815
+ specificationVersion: "v3",
407
816
  chat: createChatModel,
408
- languageModel: createChatModel
817
+ languageModel: (modelId) => createChatModel(modelId),
818
+ completion: createCompletionModel,
819
+ embeddingModel: (modelId) => createEmbeddingModel(modelId),
820
+ textEmbeddingModel: createEmbeddingModel,
821
+ imageModel: () => {
822
+ throw new Error("Image models are not supported by Apertis");
823
+ }
409
824
  }
410
825
  );
411
826
  return provider;