@apertis/ai-sdk-provider 2.0.1 → 3.0.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.cjs CHANGED
@@ -31,12 +31,11 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  apertis: () => apertis,
34
- createApertis: () => createApertis,
35
- createApertisV3: () => createApertisV3
34
+ createApertis: () => createApertis
36
35
  });
37
36
  module.exports = __toCommonJS(index_exports);
38
37
 
39
- // node_modules/.pnpm/@ai-sdk+provider@3.0.4/node_modules/@ai-sdk/provider/dist/index.mjs
38
+ // node_modules/.pnpm/@ai-sdk+provider@3.0.8/node_modules/@ai-sdk/provider/dist/index.mjs
40
39
  var marker = "vercel.ai.error";
41
40
  var symbol = Symbol.for(marker);
42
41
  var _a;
@@ -306,34 +305,61 @@ var symbol13 = Symbol.for(marker13);
306
305
  var _a13;
307
306
  var _b13;
308
307
  var TypeValidationError = class _TypeValidationError extends (_b13 = AISDKError, _a13 = symbol13, _b13) {
309
- constructor({ value, cause }) {
308
+ constructor({
309
+ value,
310
+ cause,
311
+ context
312
+ }) {
313
+ let contextPrefix = "Type validation failed";
314
+ if (context == null ? void 0 : context.field) {
315
+ contextPrefix += ` for ${context.field}`;
316
+ }
317
+ if ((context == null ? void 0 : context.entityName) || (context == null ? void 0 : context.entityId)) {
318
+ contextPrefix += " (";
319
+ const parts = [];
320
+ if (context.entityName) {
321
+ parts.push(context.entityName);
322
+ }
323
+ if (context.entityId) {
324
+ parts.push(`id: "${context.entityId}"`);
325
+ }
326
+ contextPrefix += parts.join(", ");
327
+ contextPrefix += ")";
328
+ }
310
329
  super({
311
330
  name: name12,
312
- message: `Type validation failed: Value: ${JSON.stringify(value)}.
331
+ message: `${contextPrefix}: Value: ${JSON.stringify(value)}.
313
332
  Error message: ${getErrorMessage(cause)}`,
314
333
  cause
315
334
  });
316
335
  this[_a13] = true;
317
336
  this.value = value;
337
+ this.context = context;
318
338
  }
319
339
  static isInstance(error) {
320
340
  return AISDKError.hasMarker(error, marker13);
321
341
  }
322
342
  /**
323
343
  * Wraps an error into a TypeValidationError.
324
- * If the cause is already a TypeValidationError with the same value, it returns the cause.
344
+ * If the cause is already a TypeValidationError with the same value and context, it returns the cause.
325
345
  * Otherwise, it creates a new TypeValidationError.
326
346
  *
327
347
  * @param {Object} params - The parameters for wrapping the error.
328
348
  * @param {unknown} params.value - The value that failed validation.
329
349
  * @param {unknown} params.cause - The original error or cause of the validation failure.
350
+ * @param {TypeValidationContext} params.context - Optional context about what is being validated.
330
351
  * @returns {TypeValidationError} A TypeValidationError instance.
331
352
  */
332
353
  static wrap({
333
354
  value,
334
- cause
355
+ cause,
356
+ context
335
357
  }) {
336
- return _TypeValidationError.isInstance(cause) && cause.value === value ? cause : new _TypeValidationError({ value, cause });
358
+ var _a152, _b152, _c;
359
+ if (_TypeValidationError.isInstance(cause) && cause.value === value && ((_a152 = cause.context) == null ? void 0 : _a152.field) === (context == null ? void 0 : context.field) && ((_b152 = cause.context) == null ? void 0 : _b152.entityName) === (context == null ? void 0 : context.entityName) && ((_c = cause.context) == null ? void 0 : _c.entityId) === (context == null ? void 0 : context.entityId)) {
360
+ return cause;
361
+ }
362
+ return new _TypeValidationError({ value, cause, context });
337
363
  }
338
364
  };
339
365
  var name13 = "AI_UnsupportedFunctionalityError";
@@ -355,7 +381,7 @@ var UnsupportedFunctionalityError = class extends (_b14 = AISDKError, _a14 = sym
355
381
  }
356
382
  };
357
383
 
358
- // node_modules/.pnpm/@ai-sdk+provider-utils@4.0.8_zod@3.25.76/node_modules/@ai-sdk/provider-utils/dist/index.mjs
384
+ // node_modules/.pnpm/@ai-sdk+provider-utils@4.0.23_zod@3.25.76/node_modules/@ai-sdk/provider-utils/dist/index.mjs
359
385
  var z4 = __toESM(require("zod/v4"), 1);
360
386
  var import_v3 = require("zod/v3");
361
387
  var import_v32 = require("zod/v3");
@@ -488,11 +514,57 @@ var EventSourceParserStream = class extends TransformStream {
488
514
  }
489
515
  };
490
516
 
491
- // node_modules/.pnpm/@ai-sdk+provider-utils@4.0.8_zod@3.25.76/node_modules/@ai-sdk/provider-utils/dist/index.mjs
517
+ // node_modules/.pnpm/@ai-sdk+provider-utils@4.0.23_zod@3.25.76/node_modules/@ai-sdk/provider-utils/dist/index.mjs
518
+ function combineHeaders(...headers) {
519
+ return headers.reduce(
520
+ (combinedHeaders, currentHeaders) => ({
521
+ ...combinedHeaders,
522
+ ...currentHeaders != null ? currentHeaders : {}
523
+ }),
524
+ {}
525
+ );
526
+ }
492
527
  function extractResponseHeaders(response) {
493
528
  return Object.fromEntries([...response.headers]);
494
529
  }
495
530
  var { btoa, atob } = globalThis;
531
+ function convertBase64ToUint8Array(base64String) {
532
+ const base64Url = base64String.replace(/-/g, "+").replace(/_/g, "/");
533
+ const latin1string = atob(base64Url);
534
+ return Uint8Array.from(latin1string, (byte) => byte.codePointAt(0));
535
+ }
536
+ function convertUint8ArrayToBase64(array) {
537
+ let latin1string = "";
538
+ for (let i = 0; i < array.length; i++) {
539
+ latin1string += String.fromCodePoint(array[i]);
540
+ }
541
+ return btoa(latin1string);
542
+ }
543
+ function convertToBase64(value) {
544
+ return value instanceof Uint8Array ? convertUint8ArrayToBase64(value) : value;
545
+ }
546
+ function convertToFormData(input, options = {}) {
547
+ const { useArrayBrackets = true } = options;
548
+ const formData = new FormData();
549
+ for (const [key, value] of Object.entries(input)) {
550
+ if (value == null) {
551
+ continue;
552
+ }
553
+ if (Array.isArray(value)) {
554
+ if (value.length === 1) {
555
+ formData.append(key, value[0]);
556
+ continue;
557
+ }
558
+ const arrayKey = useArrayBrackets ? `${key}[]` : key;
559
+ for (const item of value) {
560
+ formData.append(arrayKey, item);
561
+ }
562
+ continue;
563
+ }
564
+ formData.append(key, value);
565
+ }
566
+ return formData;
567
+ }
496
568
  var name14 = "AI_DownloadError";
497
569
  var marker15 = `vercel.ai.error.${name14}`;
498
570
  var symbol15 = Symbol.for(marker15);
@@ -516,6 +588,187 @@ var DownloadError = class extends (_b15 = AISDKError, _a15 = symbol15, _b15) {
516
588
  return AISDKError.hasMarker(error, marker15);
517
589
  }
518
590
  };
591
+ var DEFAULT_MAX_DOWNLOAD_SIZE = 2 * 1024 * 1024 * 1024;
592
+ async function readResponseWithSizeLimit({
593
+ response,
594
+ url,
595
+ maxBytes = DEFAULT_MAX_DOWNLOAD_SIZE
596
+ }) {
597
+ const contentLength = response.headers.get("content-length");
598
+ if (contentLength != null) {
599
+ const length = parseInt(contentLength, 10);
600
+ if (!isNaN(length) && length > maxBytes) {
601
+ throw new DownloadError({
602
+ url,
603
+ message: `Download of ${url} exceeded maximum size of ${maxBytes} bytes (Content-Length: ${length}).`
604
+ });
605
+ }
606
+ }
607
+ const body = response.body;
608
+ if (body == null) {
609
+ return new Uint8Array(0);
610
+ }
611
+ const reader = body.getReader();
612
+ const chunks = [];
613
+ let totalBytes = 0;
614
+ try {
615
+ while (true) {
616
+ const { done, value } = await reader.read();
617
+ if (done) {
618
+ break;
619
+ }
620
+ totalBytes += value.length;
621
+ if (totalBytes > maxBytes) {
622
+ throw new DownloadError({
623
+ url,
624
+ message: `Download of ${url} exceeded maximum size of ${maxBytes} bytes.`
625
+ });
626
+ }
627
+ chunks.push(value);
628
+ }
629
+ } finally {
630
+ try {
631
+ await reader.cancel();
632
+ } finally {
633
+ reader.releaseLock();
634
+ }
635
+ }
636
+ const result = new Uint8Array(totalBytes);
637
+ let offset = 0;
638
+ for (const chunk of chunks) {
639
+ result.set(chunk, offset);
640
+ offset += chunk.length;
641
+ }
642
+ return result;
643
+ }
644
+ function validateDownloadUrl(url) {
645
+ let parsed;
646
+ try {
647
+ parsed = new URL(url);
648
+ } catch (e) {
649
+ throw new DownloadError({
650
+ url,
651
+ message: `Invalid URL: ${url}`
652
+ });
653
+ }
654
+ if (parsed.protocol === "data:") {
655
+ return;
656
+ }
657
+ if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
658
+ throw new DownloadError({
659
+ url,
660
+ message: `URL scheme must be http, https, or data, got ${parsed.protocol}`
661
+ });
662
+ }
663
+ const hostname = parsed.hostname;
664
+ if (!hostname) {
665
+ throw new DownloadError({
666
+ url,
667
+ message: `URL must have a hostname`
668
+ });
669
+ }
670
+ if (hostname === "localhost" || hostname.endsWith(".local") || hostname.endsWith(".localhost")) {
671
+ throw new DownloadError({
672
+ url,
673
+ message: `URL with hostname ${hostname} is not allowed`
674
+ });
675
+ }
676
+ if (hostname.startsWith("[") && hostname.endsWith("]")) {
677
+ const ipv6 = hostname.slice(1, -1);
678
+ if (isPrivateIPv6(ipv6)) {
679
+ throw new DownloadError({
680
+ url,
681
+ message: `URL with IPv6 address ${hostname} is not allowed`
682
+ });
683
+ }
684
+ return;
685
+ }
686
+ if (isIPv4(hostname)) {
687
+ if (isPrivateIPv4(hostname)) {
688
+ throw new DownloadError({
689
+ url,
690
+ message: `URL with IP address ${hostname} is not allowed`
691
+ });
692
+ }
693
+ return;
694
+ }
695
+ }
696
+ function isIPv4(hostname) {
697
+ const parts = hostname.split(".");
698
+ if (parts.length !== 4) return false;
699
+ return parts.every((part) => {
700
+ const num = Number(part);
701
+ return Number.isInteger(num) && num >= 0 && num <= 255 && String(num) === part;
702
+ });
703
+ }
704
+ function isPrivateIPv4(ip) {
705
+ const parts = ip.split(".").map(Number);
706
+ const [a, b] = parts;
707
+ if (a === 0) return true;
708
+ if (a === 10) return true;
709
+ if (a === 127) return true;
710
+ if (a === 169 && b === 254) return true;
711
+ if (a === 172 && b >= 16 && b <= 31) return true;
712
+ if (a === 192 && b === 168) return true;
713
+ return false;
714
+ }
715
+ function isPrivateIPv6(ip) {
716
+ const normalized = ip.toLowerCase();
717
+ if (normalized === "::1") return true;
718
+ if (normalized === "::") return true;
719
+ if (normalized.startsWith("::ffff:")) {
720
+ const mappedPart = normalized.slice(7);
721
+ if (isIPv4(mappedPart)) {
722
+ return isPrivateIPv4(mappedPart);
723
+ }
724
+ const hexParts = mappedPart.split(":");
725
+ if (hexParts.length === 2) {
726
+ const high = parseInt(hexParts[0], 16);
727
+ const low = parseInt(hexParts[1], 16);
728
+ if (!isNaN(high) && !isNaN(low)) {
729
+ const a = high >> 8 & 255;
730
+ const b = high & 255;
731
+ const c = low >> 8 & 255;
732
+ const d = low & 255;
733
+ return isPrivateIPv4(`${a}.${b}.${c}.${d}`);
734
+ }
735
+ }
736
+ }
737
+ if (normalized.startsWith("fc") || normalized.startsWith("fd")) return true;
738
+ if (normalized.startsWith("fe80")) return true;
739
+ return false;
740
+ }
741
+ async function downloadBlob(url, options) {
742
+ var _a22, _b22;
743
+ validateDownloadUrl(url);
744
+ try {
745
+ const response = await fetch(url, {
746
+ signal: options == null ? void 0 : options.abortSignal
747
+ });
748
+ if (response.redirected) {
749
+ validateDownloadUrl(response.url);
750
+ }
751
+ if (!response.ok) {
752
+ throw new DownloadError({
753
+ url,
754
+ statusCode: response.status,
755
+ statusText: response.statusText
756
+ });
757
+ }
758
+ const data = await readResponseWithSizeLimit({
759
+ response,
760
+ url,
761
+ maxBytes: (_a22 = options == null ? void 0 : options.maxBytes) != null ? _a22 : DEFAULT_MAX_DOWNLOAD_SIZE
762
+ });
763
+ const contentType = (_b22 = response.headers.get("content-type")) != null ? _b22 : void 0;
764
+ return new Blob([data], contentType ? { type: contentType } : void 0);
765
+ } catch (error) {
766
+ if (DownloadError.isInstance(error)) {
767
+ throw error;
768
+ }
769
+ throw new DownloadError({ url, cause: error });
770
+ }
771
+ }
519
772
  var createIdGenerator = ({
520
773
  prefix,
521
774
  size = 16,
@@ -547,6 +800,25 @@ function isAbortError(error) {
547
800
  error.name === "TimeoutError");
548
801
  }
549
802
  var FETCH_FAILED_ERROR_MESSAGES = ["fetch failed", "failed to fetch"];
803
+ var BUN_ERROR_CODES = [
804
+ "ConnectionRefused",
805
+ "ConnectionClosed",
806
+ "FailedToOpenSocket",
807
+ "ECONNRESET",
808
+ "ECONNREFUSED",
809
+ "ETIMEDOUT",
810
+ "EPIPE"
811
+ ];
812
+ function isBunNetworkError(error) {
813
+ if (!(error instanceof Error)) {
814
+ return false;
815
+ }
816
+ const code = error.code;
817
+ if (typeof code === "string" && BUN_ERROR_CODES.includes(code)) {
818
+ return true;
819
+ }
820
+ return false;
821
+ }
550
822
  function handleFetchError({
551
823
  error,
552
824
  url,
@@ -568,6 +840,15 @@ function handleFetchError({
568
840
  });
569
841
  }
570
842
  }
843
+ if (isBunNetworkError(error)) {
844
+ return new APICallError({
845
+ message: `Cannot connect to API: ${error.message}`,
846
+ cause: error,
847
+ url,
848
+ requestBodyValues,
849
+ isRetryable: true
850
+ });
851
+ }
571
852
  return error;
572
853
  }
573
854
  function getRuntimeEnvironmentUserAgent(globalThisAny = globalThis) {
@@ -616,41 +897,9 @@ function withUserAgentSuffix(headers, ...userAgentSuffixParts) {
616
897
  );
617
898
  return Object.fromEntries(normalizedHeaders.entries());
618
899
  }
619
- var VERSION = true ? "4.0.8" : "0.0.0-test";
620
- function loadApiKey({
621
- apiKey,
622
- environmentVariableName,
623
- apiKeyParameterName = "apiKey",
624
- description
625
- }) {
626
- if (typeof apiKey === "string") {
627
- return apiKey;
628
- }
629
- if (apiKey != null) {
630
- throw new LoadAPIKeyError({
631
- message: `${description} API key must be a string.`
632
- });
633
- }
634
- if (typeof process === "undefined") {
635
- throw new LoadAPIKeyError({
636
- message: `${description} API key is missing. Pass it using the '${apiKeyParameterName}' parameter. Environment variables is not supported in this environment.`
637
- });
638
- }
639
- apiKey = process.env[environmentVariableName];
640
- if (apiKey == null) {
641
- throw new LoadAPIKeyError({
642
- message: `${description} API key is missing. Pass it using the '${apiKeyParameterName}' parameter or the ${environmentVariableName} environment variable.`
643
- });
644
- }
645
- if (typeof apiKey !== "string") {
646
- throw new LoadAPIKeyError({
647
- message: `${description} API key must be a string. The value of the ${environmentVariableName} environment variable is not a string.`
648
- });
649
- }
650
- return apiKey;
651
- }
652
- var suspectProtoRx = /"__proto__"\s*:/;
653
- var suspectConstructorRx = /"constructor"\s*:/;
900
+ var VERSION = true ? "4.0.23" : "0.0.0-test";
901
+ var suspectProtoRx = /"(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])"\s*:/;
902
+ var suspectConstructorRx = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/;
654
903
  function _parse(text) {
655
904
  const obj = JSON.parse(text);
656
905
  if (obj === null || typeof obj !== "object") {
@@ -670,7 +919,7 @@ function filter(obj) {
670
919
  if (Object.prototype.hasOwnProperty.call(node, "__proto__")) {
671
920
  throw new SyntaxError("Object contains forbidden prototype property");
672
921
  }
673
- if (Object.prototype.hasOwnProperty.call(node, "constructor") && Object.prototype.hasOwnProperty.call(node.constructor, "prototype")) {
922
+ if (Object.prototype.hasOwnProperty.call(node, "constructor") && node.constructor !== null && typeof node.constructor === "object" && Object.prototype.hasOwnProperty.call(node.constructor, "prototype")) {
674
923
  throw new SyntaxError("Object contains forbidden prototype property");
675
924
  }
676
925
  for (const key in node) {
@@ -1921,17 +2170,19 @@ function zodSchema(zodSchema2, options) {
1921
2170
  }
1922
2171
  async function validateTypes({
1923
2172
  value,
1924
- schema
2173
+ schema,
2174
+ context
1925
2175
  }) {
1926
- const result = await safeValidateTypes({ value, schema });
2176
+ const result = await safeValidateTypes({ value, schema, context });
1927
2177
  if (!result.success) {
1928
- throw TypeValidationError.wrap({ value, cause: result.error });
2178
+ throw TypeValidationError.wrap({ value, cause: result.error, context });
1929
2179
  }
1930
2180
  return result.value;
1931
2181
  }
1932
2182
  async function safeValidateTypes({
1933
2183
  value,
1934
- schema
2184
+ schema,
2185
+ context
1935
2186
  }) {
1936
2187
  const actualSchema = asSchema(schema);
1937
2188
  try {
@@ -1944,13 +2195,13 @@ async function safeValidateTypes({
1944
2195
  }
1945
2196
  return {
1946
2197
  success: false,
1947
- error: TypeValidationError.wrap({ value, cause: result.error }),
2198
+ error: TypeValidationError.wrap({ value, cause: result.error, context }),
1948
2199
  rawValue: value
1949
2200
  };
1950
2201
  } catch (error) {
1951
2202
  return {
1952
2203
  success: false,
1953
- error: TypeValidationError.wrap({ value, cause: error }),
2204
+ error: TypeValidationError.wrap({ value, cause: error, context }),
1954
2205
  rawValue: value
1955
2206
  };
1956
2207
  }
@@ -1990,6 +2241,14 @@ async function safeParseJSON({
1990
2241
  };
1991
2242
  }
1992
2243
  }
2244
+ function isParsableJson(input) {
2245
+ try {
2246
+ secureJsonParse(input);
2247
+ return true;
2248
+ } catch (e) {
2249
+ return false;
2250
+ }
2251
+ }
1993
2252
  function parseJsonEventStream({
1994
2253
  stream,
1995
2254
  schema
@@ -2005,6 +2264,27 @@ function parseJsonEventStream({
2005
2264
  })
2006
2265
  );
2007
2266
  }
2267
+ async function parseProviderOptions({
2268
+ provider,
2269
+ providerOptions,
2270
+ schema
2271
+ }) {
2272
+ if ((providerOptions == null ? void 0 : providerOptions[provider]) == null) {
2273
+ return void 0;
2274
+ }
2275
+ const parsedProviderOptions = await safeValidateTypes({
2276
+ value: providerOptions[provider],
2277
+ schema
2278
+ });
2279
+ if (!parsedProviderOptions.success) {
2280
+ throw new InvalidArgumentError({
2281
+ argument: "providerOptions",
2282
+ message: `invalid ${provider} provider options`,
2283
+ cause: parsedProviderOptions.error
2284
+ });
2285
+ }
2286
+ return parsedProviderOptions.value;
2287
+ }
2008
2288
  var getOriginalFetch2 = () => globalThis.fetch;
2009
2289
  var postJsonToApi = async ({
2010
2290
  url,
@@ -2029,6 +2309,26 @@ var postJsonToApi = async ({
2029
2309
  abortSignal,
2030
2310
  fetch: fetch2
2031
2311
  });
2312
+ var postFormDataToApi = async ({
2313
+ url,
2314
+ headers,
2315
+ formData,
2316
+ failedResponseHandler,
2317
+ successfulResponseHandler,
2318
+ abortSignal,
2319
+ fetch: fetch2
2320
+ }) => postToApi({
2321
+ url,
2322
+ headers,
2323
+ body: {
2324
+ content: formData,
2325
+ values: Object.fromEntries(formData.entries())
2326
+ },
2327
+ failedResponseHandler,
2328
+ successfulResponseHandler,
2329
+ abortSignal,
2330
+ fetch: fetch2
2331
+ });
2032
2332
  var postToApi = async ({
2033
2333
  url,
2034
2334
  headers = {},
@@ -2193,854 +2493,1677 @@ function withoutTrailingSlash(url) {
2193
2493
  return url == null ? void 0 : url.replace(/\/$/, "");
2194
2494
  }
2195
2495
 
2196
- // src/apertis-error.ts
2197
- var import_zod = require("zod");
2198
- var apertisErrorSchema = import_zod.z.object({
2199
- error: import_zod.z.object({
2200
- message: import_zod.z.string(),
2201
- type: import_zod.z.string().optional(),
2202
- code: import_zod.z.string().nullable().optional(),
2203
- param: import_zod.z.string().nullable().optional()
2496
+ // node_modules/.pnpm/@ai-sdk+openai-compatible@2.0.41_zod@3.25.76/node_modules/@ai-sdk/openai-compatible/dist/index.mjs
2497
+ var import_v4 = require("zod/v4");
2498
+ var import_v42 = require("zod/v4");
2499
+ var import_v43 = require("zod/v4");
2500
+ var import_v44 = require("zod/v4");
2501
+ var import_v45 = require("zod/v4");
2502
+ var import_v46 = require("zod/v4");
2503
+ var import_v47 = require("zod/v4");
2504
+ var import_v48 = require("zod/v4");
2505
+ function toCamelCase(str) {
2506
+ return str.replace(/[_-]([a-z])/g, (g) => g[1].toUpperCase());
2507
+ }
2508
+ function resolveProviderOptionsKey(rawName, providerOptions) {
2509
+ const camelName = toCamelCase(rawName);
2510
+ if (camelName !== rawName && (providerOptions == null ? void 0 : providerOptions[camelName]) != null) {
2511
+ return camelName;
2512
+ }
2513
+ return rawName;
2514
+ }
2515
+ var openaiCompatibleErrorDataSchema = import_v42.z.object({
2516
+ error: import_v42.z.object({
2517
+ message: import_v42.z.string(),
2518
+ // The additional information below is handled loosely to support
2519
+ // OpenAI-compatible providers that have slightly different error
2520
+ // responses:
2521
+ type: import_v42.z.string().nullish(),
2522
+ param: import_v42.z.any().nullish(),
2523
+ code: import_v42.z.union([import_v42.z.string(), import_v42.z.number()]).nullish()
2204
2524
  })
2205
2525
  });
2206
- var apertisFailedResponseHandler = createJsonErrorResponseHandler({
2207
- errorSchema: apertisErrorSchema,
2208
- errorToMessage: (error) => error.error.message
2209
- });
2210
-
2211
- // src/schemas/chat-response.ts
2212
- var import_zod2 = require("zod");
2213
- var openAIChatResponseSchema = import_zod2.z.object({
2214
- id: import_zod2.z.string().optional(),
2215
- object: import_zod2.z.literal("chat.completion").optional(),
2216
- created: import_zod2.z.number().optional(),
2217
- model: import_zod2.z.string().optional(),
2218
- choices: import_zod2.z.array(
2219
- import_zod2.z.object({
2220
- index: import_zod2.z.number(),
2221
- message: import_zod2.z.object({
2222
- role: import_zod2.z.literal("assistant"),
2223
- content: import_zod2.z.string().nullable(),
2224
- tool_calls: import_zod2.z.array(
2225
- import_zod2.z.object({
2226
- id: import_zod2.z.string(),
2227
- type: import_zod2.z.literal("function"),
2228
- function: import_zod2.z.object({
2229
- name: import_zod2.z.string(),
2230
- arguments: import_zod2.z.string()
2231
- })
2232
- })
2233
- ).optional()
2234
- }),
2235
- finish_reason: import_zod2.z.string().nullable(),
2236
- logprobs: import_zod2.z.any().nullable().optional()
2237
- })
2238
- ),
2239
- usage: import_zod2.z.object({
2240
- prompt_tokens: import_zod2.z.number(),
2241
- completion_tokens: import_zod2.z.number(),
2242
- total_tokens: import_zod2.z.number().optional()
2243
- }).optional()
2244
- });
2245
- var openAIChatChunkSchema = import_zod2.z.object({
2246
- id: import_zod2.z.string().optional(),
2247
- object: import_zod2.z.literal("chat.completion.chunk").optional(),
2248
- created: import_zod2.z.number().optional(),
2249
- model: import_zod2.z.string().optional(),
2250
- choices: import_zod2.z.array(
2251
- import_zod2.z.object({
2252
- index: import_zod2.z.number(),
2253
- delta: import_zod2.z.object({
2254
- role: import_zod2.z.literal("assistant").optional(),
2255
- content: import_zod2.z.string().nullable().optional(),
2256
- tool_calls: import_zod2.z.array(
2257
- import_zod2.z.object({
2258
- index: import_zod2.z.number(),
2259
- id: import_zod2.z.string().optional(),
2260
- type: import_zod2.z.literal("function").optional(),
2261
- function: import_zod2.z.object({
2262
- name: import_zod2.z.string().optional(),
2263
- arguments: import_zod2.z.string().optional()
2264
- }).optional()
2265
- })
2266
- ).optional()
2267
- }),
2268
- finish_reason: import_zod2.z.string().nullable().optional()
2269
- })
2270
- ),
2271
- usage: import_zod2.z.object({
2272
- prompt_tokens: import_zod2.z.number(),
2273
- completion_tokens: import_zod2.z.number()
2274
- }).nullish()
2275
- });
2276
-
2277
- // src/utils/map-finish-reason.ts
2278
- function normalizeFinishReason(finishReason) {
2279
- switch (finishReason) {
2280
- case "stop":
2281
- return "stop";
2282
- case "length":
2283
- return "length";
2284
- case "tool_calls":
2285
- return "tool-calls";
2286
- case "content_filter":
2287
- return "content-filter";
2288
- default:
2289
- return "other";
2526
+ var defaultOpenAICompatibleErrorStructure = {
2527
+ errorSchema: openaiCompatibleErrorDataSchema,
2528
+ errorToMessage: (data) => data.error.message
2529
+ };
2530
+ function convertOpenAICompatibleChatUsage(usage) {
2531
+ var _a16, _b16, _c, _d, _e, _f;
2532
+ if (usage == null) {
2533
+ return {
2534
+ inputTokens: {
2535
+ total: void 0,
2536
+ noCache: void 0,
2537
+ cacheRead: void 0,
2538
+ cacheWrite: void 0
2539
+ },
2540
+ outputTokens: {
2541
+ total: void 0,
2542
+ text: void 0,
2543
+ reasoning: void 0
2544
+ },
2545
+ raw: void 0
2546
+ };
2290
2547
  }
2291
- }
2292
- function mapApertisFinishReason(finishReason) {
2548
+ const promptTokens = (_a16 = usage.prompt_tokens) != null ? _a16 : 0;
2549
+ const completionTokens = (_b16 = usage.completion_tokens) != null ? _b16 : 0;
2550
+ const cacheReadTokens = (_d = (_c = usage.prompt_tokens_details) == null ? void 0 : _c.cached_tokens) != null ? _d : 0;
2551
+ const reasoningTokens = (_f = (_e = usage.completion_tokens_details) == null ? void 0 : _e.reasoning_tokens) != null ? _f : 0;
2293
2552
  return {
2294
- unified: normalizeFinishReason(finishReason),
2295
- raw: finishReason ?? void 0
2553
+ inputTokens: {
2554
+ total: promptTokens,
2555
+ noCache: promptTokens - cacheReadTokens,
2556
+ cacheRead: cacheReadTokens,
2557
+ cacheWrite: void 0
2558
+ },
2559
+ outputTokens: {
2560
+ total: completionTokens,
2561
+ text: completionTokens - reasoningTokens,
2562
+ reasoning: reasoningTokens
2563
+ },
2564
+ raw: usage
2296
2565
  };
2297
2566
  }
2298
- function mapApertisFinishReasonV2(finishReason) {
2299
- return normalizeFinishReason(finishReason);
2567
+ function getOpenAIMetadata(message) {
2568
+ var _a16, _b16;
2569
+ return (_b16 = (_a16 = message == null ? void 0 : message.providerOptions) == null ? void 0 : _a16.openaiCompatible) != null ? _b16 : {};
2300
2570
  }
2301
-
2302
- // src/utils/convert-to-openai-messages.ts
2303
- function convertToOpenAIMessages(prompt) {
2571
+ function getAudioFormat(mediaType) {
2572
+ switch (mediaType) {
2573
+ case "audio/wav":
2574
+ return "wav";
2575
+ case "audio/mp3":
2576
+ case "audio/mpeg":
2577
+ return "mp3";
2578
+ default:
2579
+ return null;
2580
+ }
2581
+ }
2582
+ function convertToOpenAICompatibleChatMessages(prompt) {
2583
+ var _a16, _b16, _c;
2304
2584
  const messages = [];
2305
- for (const message of prompt) {
2306
- switch (message.role) {
2307
- case "system":
2308
- messages.push({ role: "system", content: message.content });
2585
+ for (const { role, content, ...message } of prompt) {
2586
+ const metadata = getOpenAIMetadata({ ...message });
2587
+ switch (role) {
2588
+ case "system": {
2589
+ messages.push({ role: "system", content, ...metadata });
2309
2590
  break;
2310
- case "user":
2591
+ }
2592
+ case "user": {
2593
+ if (content.length === 1 && content[0].type === "text") {
2594
+ messages.push({
2595
+ role: "user",
2596
+ content: content[0].text,
2597
+ ...getOpenAIMetadata(content[0])
2598
+ });
2599
+ break;
2600
+ }
2311
2601
  messages.push({
2312
2602
  role: "user",
2313
- content: message.content.map((part) => {
2603
+ content: content.map((part) => {
2604
+ var _a22;
2605
+ const partMetadata = getOpenAIMetadata(part);
2314
2606
  switch (part.type) {
2315
- case "text":
2316
- return { type: "text", text: part.text };
2607
+ case "text": {
2608
+ return { type: "text", text: part.text, ...partMetadata };
2609
+ }
2317
2610
  case "file": {
2318
- if (part.mediaType?.startsWith("image/")) {
2319
- let url;
2611
+ if (part.mediaType.startsWith("image/")) {
2612
+ const mediaType = part.mediaType === "image/*" ? "image/jpeg" : part.mediaType;
2613
+ return {
2614
+ type: "image_url",
2615
+ image_url: {
2616
+ url: part.data instanceof URL ? part.data.toString() : `data:${mediaType};base64,${convertToBase64(part.data)}`
2617
+ },
2618
+ ...partMetadata
2619
+ };
2620
+ }
2621
+ if (part.mediaType.startsWith("audio/")) {
2320
2622
  if (part.data instanceof URL) {
2321
- url = part.data.toString();
2322
- } else if (typeof part.data === "string") {
2323
- if (part.data.startsWith("http://") || part.data.startsWith("https://")) {
2324
- url = part.data;
2325
- } else {
2326
- url = `data:${part.mediaType};base64,${part.data}`;
2327
- }
2328
- } else {
2329
- url = `data:${part.mediaType};base64,${Buffer.from(part.data).toString("base64")}`;
2623
+ throw new UnsupportedFunctionalityError({
2624
+ functionality: "audio file parts with URLs"
2625
+ });
2626
+ }
2627
+ const format = getAudioFormat(part.mediaType);
2628
+ if (format === null) {
2629
+ throw new UnsupportedFunctionalityError({
2630
+ functionality: `audio media type ${part.mediaType}`
2631
+ });
2330
2632
  }
2331
2633
  return {
2332
- type: "image_url",
2333
- image_url: { url }
2634
+ type: "input_audio",
2635
+ input_audio: {
2636
+ data: convertToBase64(part.data),
2637
+ format
2638
+ },
2639
+ ...partMetadata
2640
+ };
2641
+ }
2642
+ if (part.mediaType === "application/pdf") {
2643
+ if (part.data instanceof URL) {
2644
+ throw new UnsupportedFunctionalityError({
2645
+ functionality: "PDF file parts with URLs"
2646
+ });
2647
+ }
2648
+ return {
2649
+ type: "file",
2650
+ file: {
2651
+ filename: (_a22 = part.filename) != null ? _a22 : "document.pdf",
2652
+ file_data: `data:application/pdf;base64,${convertToBase64(part.data)}`
2653
+ },
2654
+ ...partMetadata
2655
+ };
2656
+ }
2657
+ if (part.mediaType.startsWith("text/")) {
2658
+ const textContent = part.data instanceof URL ? part.data.toString() : typeof part.data === "string" ? new TextDecoder().decode(
2659
+ convertBase64ToUint8Array(part.data)
2660
+ ) : new TextDecoder().decode(part.data);
2661
+ return {
2662
+ type: "text",
2663
+ text: textContent,
2664
+ ...partMetadata
2334
2665
  };
2335
2666
  }
2336
- throw new Error(
2337
- `Unsupported file type: ${part.mediaType}. Only image/* is supported.`
2338
- );
2667
+ throw new UnsupportedFunctionalityError({
2668
+ functionality: `file part media type ${part.mediaType}`
2669
+ });
2339
2670
  }
2340
- default:
2341
- throw new Error(
2342
- `Unsupported user content part type: ${part.type}`
2343
- );
2344
2671
  }
2345
- })
2672
+ }),
2673
+ ...metadata
2346
2674
  });
2347
2675
  break;
2676
+ }
2348
2677
  case "assistant": {
2349
- const textContent = message.content.filter((p) => p.type === "text").map((p) => p.text).join("");
2350
- const toolCalls = message.content.filter((p) => p.type === "tool-call").map((tc) => {
2351
- let arguments_str = "{}";
2352
- try {
2353
- arguments_str = typeof tc.input === "string" ? tc.input : JSON.stringify(tc.input);
2354
- } catch {
2355
- arguments_str = "{}";
2678
+ let text = "";
2679
+ let reasoning = "";
2680
+ const toolCalls = [];
2681
+ for (const part of content) {
2682
+ const partMetadata = getOpenAIMetadata(part);
2683
+ switch (part.type) {
2684
+ case "text": {
2685
+ text += part.text;
2686
+ break;
2687
+ }
2688
+ case "reasoning": {
2689
+ reasoning += part.text;
2690
+ break;
2691
+ }
2692
+ case "tool-call": {
2693
+ const thoughtSignature = (_b16 = (_a16 = part.providerOptions) == null ? void 0 : _a16.google) == null ? void 0 : _b16.thoughtSignature;
2694
+ toolCalls.push({
2695
+ id: part.toolCallId,
2696
+ type: "function",
2697
+ function: {
2698
+ name: part.toolName,
2699
+ arguments: JSON.stringify(part.input)
2700
+ },
2701
+ ...partMetadata,
2702
+ // Include extra_content for Google Gemini thought signatures
2703
+ ...thoughtSignature ? {
2704
+ extra_content: {
2705
+ google: {
2706
+ thought_signature: String(thoughtSignature)
2707
+ }
2708
+ }
2709
+ } : {}
2710
+ });
2711
+ break;
2712
+ }
2356
2713
  }
2357
- return {
2358
- id: tc.toolCallId,
2359
- type: "function",
2360
- function: { name: tc.toolName, arguments: arguments_str }
2361
- };
2362
- });
2714
+ }
2363
2715
  messages.push({
2364
2716
  role: "assistant",
2365
- content: textContent || null,
2366
- ...toolCalls.length > 0 ? { tool_calls: toolCalls } : {}
2717
+ content: text,
2718
+ ...reasoning.length > 0 ? { reasoning_content: reasoning } : {},
2719
+ tool_calls: toolCalls.length > 0 ? toolCalls : void 0,
2720
+ ...metadata
2367
2721
  });
2368
2722
  break;
2369
2723
  }
2370
- case "tool":
2371
- for (const result of message.content) {
2372
- if (result.type !== "tool-result") continue;
2373
- let content = "{}";
2374
- const output = result.output;
2375
- if (typeof output === "string") {
2376
- content = output;
2377
- } else if (Array.isArray(output)) {
2378
- const textParts = output.filter((p) => p.type === "text").map((p) => p.text);
2379
- content = textParts.join("");
2380
- } else {
2381
- try {
2382
- content = JSON.stringify(output);
2383
- } catch {
2384
- content = "{}";
2385
- }
2724
+ case "tool": {
2725
+ for (const toolResponse of content) {
2726
+ if (toolResponse.type === "tool-approval-response") {
2727
+ continue;
2728
+ }
2729
+ const output = toolResponse.output;
2730
+ let contentValue;
2731
+ switch (output.type) {
2732
+ case "text":
2733
+ case "error-text":
2734
+ contentValue = output.value;
2735
+ break;
2736
+ case "execution-denied":
2737
+ contentValue = (_c = output.reason) != null ? _c : "Tool execution denied.";
2738
+ break;
2739
+ case "content":
2740
+ case "json":
2741
+ case "error-json":
2742
+ contentValue = JSON.stringify(output.value);
2743
+ break;
2386
2744
  }
2745
+ const toolResponseMetadata = getOpenAIMetadata(toolResponse);
2387
2746
  messages.push({
2388
2747
  role: "tool",
2389
- tool_call_id: result.toolCallId,
2390
- content
2748
+ tool_call_id: toolResponse.toolCallId,
2749
+ content: contentValue,
2750
+ ...toolResponseMetadata
2391
2751
  });
2392
2752
  }
2393
2753
  break;
2754
+ }
2755
+ default: {
2756
+ const _exhaustiveCheck = role;
2757
+ throw new Error(`Unsupported role: ${_exhaustiveCheck}`);
2758
+ }
2394
2759
  }
2395
2760
  }
2396
2761
  return messages;
2397
2762
  }
2398
-
2399
- // src/utils/convert-to-openai-tools.ts
2400
- function convertToOpenAITools(tools) {
2401
- if (!tools || tools.length === 0) return void 0;
2402
- return tools.map((tool) => ({
2403
- type: "function",
2404
- function: {
2405
- name: tool.name,
2406
- description: tool.description,
2407
- parameters: tool.inputSchema
2408
- }
2409
- }));
2410
- }
2411
- function convertToOpenAIToolChoice(toolChoice) {
2412
- if (!toolChoice) return void 0;
2413
- switch (toolChoice.type) {
2414
- case "none":
2415
- return "none";
2416
- case "auto":
2417
- return "auto";
2418
- case "required":
2419
- return "required";
2420
- case "tool":
2421
- if (!toolChoice.toolName) return void 0;
2422
- return {
2423
- type: "function",
2424
- function: { name: toolChoice.toolName }
2425
- };
2763
+ function getResponseMetadata({
2764
+ id,
2765
+ model,
2766
+ created
2767
+ }) {
2768
+ return {
2769
+ id: id != null ? id : void 0,
2770
+ modelId: model != null ? model : void 0,
2771
+ timestamp: created != null ? new Date(created * 1e3) : void 0
2772
+ };
2773
+ }
2774
+ function mapOpenAICompatibleFinishReason(finishReason) {
2775
+ switch (finishReason) {
2776
+ case "stop":
2777
+ return "stop";
2778
+ case "length":
2779
+ return "length";
2780
+ case "content_filter":
2781
+ return "content-filter";
2782
+ case "function_call":
2783
+ case "tool_calls":
2784
+ return "tool-calls";
2426
2785
  default:
2427
- return void 0;
2786
+ return "other";
2428
2787
  }
2429
2788
  }
2430
-
2431
- // src/apertis-chat-language-model.ts
2432
- var ApertisChatLanguageModel = class {
2433
- constructor(modelId, settings, config) {
2434
- this.modelId = modelId;
2435
- this.settings = settings;
2436
- this.config = config;
2437
- }
2438
- specificationVersion = "v3";
2789
+ var openaiCompatibleLanguageModelChatOptions = import_v43.z.object({
2439
2790
  /**
2440
- * Supported URL patterns for different media types.
2441
- * Supports HTTP(S) image URLs for direct URL passing.
2791
+ * A unique identifier representing your end-user, which can help the provider to
2792
+ * monitor and detect abuse.
2442
2793
  */
2443
- supportedUrls = {
2444
- "image/*": [/^https?:\/\/.+$/]
2445
- };
2446
- get provider() {
2447
- return this.config.provider;
2794
+ user: import_v43.z.string().optional(),
2795
+ /**
2796
+ * Reasoning effort for reasoning models. Defaults to `medium`.
2797
+ */
2798
+ reasoningEffort: import_v43.z.string().optional(),
2799
+ /**
2800
+ * Controls the verbosity of the generated text. Defaults to `medium`.
2801
+ */
2802
+ textVerbosity: import_v43.z.string().optional(),
2803
+ /**
2804
+ * Whether to use strict JSON schema validation.
2805
+ * When true, the model uses constrained decoding to guarantee schema compliance.
2806
+ * Only used when the provider supports structured outputs and a schema is provided.
2807
+ *
2808
+ * @default true
2809
+ */
2810
+ strictJsonSchema: import_v43.z.boolean().optional()
2811
+ });
2812
+ function prepareTools({
2813
+ tools,
2814
+ toolChoice
2815
+ }) {
2816
+ tools = (tools == null ? void 0 : tools.length) ? tools : void 0;
2817
+ const toolWarnings = [];
2818
+ if (tools == null) {
2819
+ return { tools: void 0, toolChoice: void 0, toolWarnings };
2820
+ }
2821
+ const openaiCompatTools = [];
2822
+ for (const tool of tools) {
2823
+ if (tool.type === "provider") {
2824
+ toolWarnings.push({
2825
+ type: "unsupported",
2826
+ feature: `provider-defined tool ${tool.id}`
2827
+ });
2828
+ } else {
2829
+ openaiCompatTools.push({
2830
+ type: "function",
2831
+ function: {
2832
+ name: tool.name,
2833
+ description: tool.description,
2834
+ parameters: tool.inputSchema,
2835
+ ...tool.strict != null ? { strict: tool.strict } : {}
2836
+ }
2837
+ });
2838
+ }
2839
+ }
2840
+ if (toolChoice == null) {
2841
+ return { tools: openaiCompatTools, toolChoice: void 0, toolWarnings };
2842
+ }
2843
+ const type = toolChoice.type;
2844
+ switch (type) {
2845
+ case "auto":
2846
+ case "none":
2847
+ case "required":
2848
+ return { tools: openaiCompatTools, toolChoice: type, toolWarnings };
2849
+ case "tool":
2850
+ return {
2851
+ tools: openaiCompatTools,
2852
+ toolChoice: {
2853
+ type: "function",
2854
+ function: { name: toolChoice.toolName }
2855
+ },
2856
+ toolWarnings
2857
+ };
2858
+ default: {
2859
+ const _exhaustiveCheck = type;
2860
+ throw new UnsupportedFunctionalityError({
2861
+ functionality: `tool choice type: ${_exhaustiveCheck}`
2862
+ });
2863
+ }
2864
+ }
2865
+ }
2866
+ var OpenAICompatibleChatLanguageModel = class {
2867
+ // type inferred via constructor
2868
+ constructor(modelId, config) {
2869
+ this.specificationVersion = "v3";
2870
+ var _a16, _b16;
2871
+ this.modelId = modelId;
2872
+ this.config = config;
2873
+ const errorStructure = (_a16 = config.errorStructure) != null ? _a16 : defaultOpenAICompatibleErrorStructure;
2874
+ this.chunkSchema = createOpenAICompatibleChatChunkSchema(
2875
+ errorStructure.errorSchema
2876
+ );
2877
+ this.failedResponseHandler = createJsonErrorResponseHandler(errorStructure);
2878
+ this.supportsStructuredOutputs = (_b16 = config.supportsStructuredOutputs) != null ? _b16 : false;
2879
+ }
2880
+ get provider() {
2881
+ return this.config.provider;
2882
+ }
2883
+ get providerOptionsName() {
2884
+ return this.config.provider.split(".")[0].trim();
2885
+ }
2886
+ get supportedUrls() {
2887
+ var _a16, _b16, _c;
2888
+ return (_c = (_b16 = (_a16 = this.config).supportedUrls) == null ? void 0 : _b16.call(_a16)) != null ? _c : {};
2889
+ }
2890
+ transformRequestBody(args) {
2891
+ var _a16, _b16, _c;
2892
+ return (_c = (_b16 = (_a16 = this.config).transformRequestBody) == null ? void 0 : _b16.call(_a16, args)) != null ? _c : args;
2893
+ }
2894
+ async getArgs({
2895
+ prompt,
2896
+ maxOutputTokens,
2897
+ temperature,
2898
+ topP,
2899
+ topK,
2900
+ frequencyPenalty,
2901
+ presencePenalty,
2902
+ providerOptions,
2903
+ stopSequences,
2904
+ responseFormat,
2905
+ seed,
2906
+ toolChoice,
2907
+ tools
2908
+ }) {
2909
+ var _a16, _b16, _c, _d, _e;
2910
+ const warnings = [];
2911
+ const deprecatedOptions = await parseProviderOptions({
2912
+ provider: "openai-compatible",
2913
+ providerOptions,
2914
+ schema: openaiCompatibleLanguageModelChatOptions
2915
+ });
2916
+ if (deprecatedOptions != null) {
2917
+ warnings.push({
2918
+ type: "other",
2919
+ message: `The 'openai-compatible' key in providerOptions is deprecated. Use 'openaiCompatible' instead.`
2920
+ });
2921
+ }
2922
+ const compatibleOptions = Object.assign(
2923
+ deprecatedOptions != null ? deprecatedOptions : {},
2924
+ (_a16 = await parseProviderOptions({
2925
+ provider: "openaiCompatible",
2926
+ providerOptions,
2927
+ schema: openaiCompatibleLanguageModelChatOptions
2928
+ })) != null ? _a16 : {},
2929
+ (_b16 = await parseProviderOptions({
2930
+ provider: this.providerOptionsName,
2931
+ providerOptions,
2932
+ schema: openaiCompatibleLanguageModelChatOptions
2933
+ })) != null ? _b16 : {},
2934
+ (_c = await parseProviderOptions({
2935
+ provider: toCamelCase(this.providerOptionsName),
2936
+ providerOptions,
2937
+ schema: openaiCompatibleLanguageModelChatOptions
2938
+ })) != null ? _c : {}
2939
+ );
2940
+ const strictJsonSchema = (_d = compatibleOptions == null ? void 0 : compatibleOptions.strictJsonSchema) != null ? _d : true;
2941
+ if (topK != null) {
2942
+ warnings.push({ type: "unsupported", feature: "topK" });
2943
+ }
2944
+ if ((responseFormat == null ? void 0 : responseFormat.type) === "json" && responseFormat.schema != null && !this.supportsStructuredOutputs) {
2945
+ warnings.push({
2946
+ type: "unsupported",
2947
+ feature: "responseFormat",
2948
+ details: "JSON response format schema is only supported with structuredOutputs"
2949
+ });
2950
+ }
2951
+ const {
2952
+ tools: openaiTools,
2953
+ toolChoice: openaiToolChoice,
2954
+ toolWarnings
2955
+ } = prepareTools({
2956
+ tools,
2957
+ toolChoice
2958
+ });
2959
+ const metadataKey = resolveProviderOptionsKey(
2960
+ this.providerOptionsName,
2961
+ providerOptions
2962
+ );
2963
+ return {
2964
+ metadataKey,
2965
+ args: {
2966
+ // model id:
2967
+ model: this.modelId,
2968
+ // model specific settings:
2969
+ user: compatibleOptions.user,
2970
+ // standardized settings:
2971
+ max_tokens: maxOutputTokens,
2972
+ temperature,
2973
+ top_p: topP,
2974
+ frequency_penalty: frequencyPenalty,
2975
+ presence_penalty: presencePenalty,
2976
+ response_format: (responseFormat == null ? void 0 : responseFormat.type) === "json" ? this.supportsStructuredOutputs === true && responseFormat.schema != null ? {
2977
+ type: "json_schema",
2978
+ json_schema: {
2979
+ schema: responseFormat.schema,
2980
+ strict: strictJsonSchema,
2981
+ name: (_e = responseFormat.name) != null ? _e : "response",
2982
+ description: responseFormat.description
2983
+ }
2984
+ } : { type: "json_object" } : void 0,
2985
+ stop: stopSequences,
2986
+ seed,
2987
+ ...Object.fromEntries(
2988
+ Object.entries({
2989
+ ...providerOptions == null ? void 0 : providerOptions[this.providerOptionsName],
2990
+ ...providerOptions == null ? void 0 : providerOptions[toCamelCase(this.providerOptionsName)]
2991
+ }).filter(
2992
+ ([key]) => !Object.keys(
2993
+ openaiCompatibleLanguageModelChatOptions.shape
2994
+ ).includes(key)
2995
+ )
2996
+ ),
2997
+ reasoning_effort: compatibleOptions.reasoningEffort,
2998
+ verbosity: compatibleOptions.textVerbosity,
2999
+ // messages:
3000
+ messages: convertToOpenAICompatibleChatMessages(prompt),
3001
+ // tools:
3002
+ tools: openaiTools,
3003
+ tool_choice: openaiToolChoice
3004
+ },
3005
+ warnings: [...warnings, ...toolWarnings]
3006
+ };
2448
3007
  }
2449
3008
  async doGenerate(options) {
2450
- const body = this.buildRequestBody(options, false);
2451
- const { value: response } = await postJsonToApi({
2452
- url: `${this.config.baseURL}/chat/completions`,
2453
- headers: this.config.headers(),
2454
- body,
2455
- failedResponseHandler: apertisFailedResponseHandler,
3009
+ var _a16, _b16, _c, _d, _e, _f, _g, _h;
3010
+ const { args, warnings, metadataKey } = await this.getArgs({ ...options });
3011
+ const transformedBody = this.transformRequestBody(args);
3012
+ const body = JSON.stringify(transformedBody);
3013
+ const {
3014
+ responseHeaders,
3015
+ value: responseBody,
3016
+ rawValue: rawResponse
3017
+ } = await postJsonToApi({
3018
+ url: this.config.url({
3019
+ path: "/chat/completions",
3020
+ modelId: this.modelId
3021
+ }),
3022
+ headers: combineHeaders(this.config.headers(), options.headers),
3023
+ body: transformedBody,
3024
+ failedResponseHandler: this.failedResponseHandler,
2456
3025
  successfulResponseHandler: createJsonResponseHandler(
2457
- openAIChatResponseSchema
3026
+ OpenAICompatibleChatResponseSchema
2458
3027
  ),
2459
- fetch: this.config.fetch,
2460
- abortSignal: options.abortSignal
3028
+ abortSignal: options.abortSignal,
3029
+ fetch: this.config.fetch
2461
3030
  });
2462
- const choice = response.choices[0];
3031
+ const choice = responseBody.choices[0];
2463
3032
  const content = [];
2464
- if (choice.message.content) {
3033
+ const text = choice.message.content;
3034
+ if (text != null && text.length > 0) {
3035
+ content.push({ type: "text", text });
3036
+ }
3037
+ const reasoning = (_a16 = choice.message.reasoning_content) != null ? _a16 : choice.message.reasoning;
3038
+ if (reasoning != null && reasoning.length > 0) {
2465
3039
  content.push({
2466
- type: "text",
2467
- text: choice.message.content
3040
+ type: "reasoning",
3041
+ text: reasoning
2468
3042
  });
2469
3043
  }
2470
- if (choice.message.tool_calls) {
2471
- for (const tc of choice.message.tool_calls) {
3044
+ if (choice.message.tool_calls != null) {
3045
+ for (const toolCall of choice.message.tool_calls) {
3046
+ const thoughtSignature = (_c = (_b16 = toolCall.extra_content) == null ? void 0 : _b16.google) == null ? void 0 : _c.thought_signature;
2472
3047
  content.push({
2473
3048
  type: "tool-call",
2474
- toolCallId: tc.id,
2475
- toolName: tc.function.name,
2476
- input: tc.function.arguments
3049
+ toolCallId: (_d = toolCall.id) != null ? _d : generateId(),
3050
+ toolName: toolCall.function.name,
3051
+ input: toolCall.function.arguments,
3052
+ ...thoughtSignature ? {
3053
+ providerMetadata: {
3054
+ [metadataKey]: { thoughtSignature }
3055
+ }
3056
+ } : {}
2477
3057
  });
2478
3058
  }
2479
3059
  }
3060
+ const providerMetadata = {
3061
+ [metadataKey]: {},
3062
+ ...await ((_f = (_e = this.config.metadataExtractor) == null ? void 0 : _e.extractMetadata) == null ? void 0 : _f.call(_e, {
3063
+ parsedBody: rawResponse
3064
+ }))
3065
+ };
3066
+ const completionTokenDetails = (_g = responseBody.usage) == null ? void 0 : _g.completion_tokens_details;
3067
+ if ((completionTokenDetails == null ? void 0 : completionTokenDetails.accepted_prediction_tokens) != null) {
3068
+ providerMetadata[metadataKey].acceptedPredictionTokens = completionTokenDetails == null ? void 0 : completionTokenDetails.accepted_prediction_tokens;
3069
+ }
3070
+ if ((completionTokenDetails == null ? void 0 : completionTokenDetails.rejected_prediction_tokens) != null) {
3071
+ providerMetadata[metadataKey].rejectedPredictionTokens = completionTokenDetails == null ? void 0 : completionTokenDetails.rejected_prediction_tokens;
3072
+ }
2480
3073
  return {
2481
3074
  content,
2482
- finishReason: mapApertisFinishReason(choice.finish_reason),
2483
- usage: {
2484
- inputTokens: {
2485
- total: response.usage?.prompt_tokens ?? 0,
2486
- noCache: void 0,
2487
- cacheRead: void 0,
2488
- cacheWrite: void 0
2489
- },
2490
- outputTokens: {
2491
- total: response.usage?.completion_tokens ?? 0,
2492
- text: void 0,
2493
- reasoning: void 0
2494
- }
3075
+ finishReason: {
3076
+ unified: mapOpenAICompatibleFinishReason(choice.finish_reason),
3077
+ raw: (_h = choice.finish_reason) != null ? _h : void 0
3078
+ },
3079
+ usage: convertOpenAICompatibleChatUsage(responseBody.usage),
3080
+ providerMetadata,
3081
+ request: { body },
3082
+ response: {
3083
+ ...getResponseMetadata(responseBody),
3084
+ headers: responseHeaders,
3085
+ body: rawResponse
2495
3086
  },
2496
- warnings: [],
2497
- request: { body }
3087
+ warnings
2498
3088
  };
2499
3089
  }
2500
3090
  async doStream(options) {
2501
- const body = this.buildRequestBody(options, true);
2502
- const { value: response } = await postJsonToApi({
2503
- url: `${this.config.baseURL}/chat/completions`,
2504
- headers: this.config.headers(),
3091
+ var _a16;
3092
+ const { args, warnings, metadataKey } = await this.getArgs({ ...options });
3093
+ const body = this.transformRequestBody({
3094
+ ...args,
3095
+ stream: true,
3096
+ // only include stream_options when in strict compatibility mode:
3097
+ stream_options: this.config.includeUsage ? { include_usage: true } : void 0
3098
+ });
3099
+ const metadataExtractor = (_a16 = this.config.metadataExtractor) == null ? void 0 : _a16.createStreamExtractor();
3100
+ const { responseHeaders, value: response } = await postJsonToApi({
3101
+ url: this.config.url({
3102
+ path: "/chat/completions",
3103
+ modelId: this.modelId
3104
+ }),
3105
+ headers: combineHeaders(this.config.headers(), options.headers),
2505
3106
  body,
2506
- failedResponseHandler: apertisFailedResponseHandler,
3107
+ failedResponseHandler: this.failedResponseHandler,
2507
3108
  successfulResponseHandler: createEventSourceResponseHandler(
2508
- openAIChatChunkSchema
3109
+ this.chunkSchema
2509
3110
  ),
2510
- fetch: this.config.fetch,
2511
- abortSignal: options.abortSignal
3111
+ abortSignal: options.abortSignal,
3112
+ fetch: this.config.fetch
2512
3113
  });
2513
- const toolCallBuffers = /* @__PURE__ */ new Map();
2514
- let textId = null;
2515
- const transformStream = new TransformStream({
2516
- transform(parseResult, controller) {
2517
- if (!parseResult.success) {
2518
- return;
2519
- }
2520
- const chunk = parseResult.value;
2521
- const choice = chunk.choices[0];
2522
- if (!choice) return;
2523
- if (choice.delta.content) {
2524
- if (!textId) {
2525
- textId = generateId();
2526
- controller.enqueue({
2527
- type: "text-start",
2528
- id: textId
2529
- });
2530
- }
2531
- controller.enqueue({
2532
- type: "text-delta",
2533
- id: textId,
2534
- delta: choice.delta.content
2535
- });
2536
- }
2537
- if (choice.delta.tool_calls) {
2538
- for (const tc of choice.delta.tool_calls) {
2539
- let buffer = toolCallBuffers.get(tc.index);
2540
- if (!buffer) {
2541
- buffer = { id: tc.id ?? generateId(), name: "", arguments: "" };
2542
- toolCallBuffers.set(tc.index, buffer);
3114
+ const toolCalls = [];
3115
+ let finishReason = {
3116
+ unified: "other",
3117
+ raw: void 0
3118
+ };
3119
+ let usage = void 0;
3120
+ let isFirstChunk = true;
3121
+ const providerOptionsName = metadataKey;
3122
+ let isActiveReasoning = false;
3123
+ let isActiveText = false;
3124
+ return {
3125
+ stream: response.pipeThrough(
3126
+ new TransformStream({
3127
+ start(controller) {
3128
+ controller.enqueue({ type: "stream-start", warnings });
3129
+ },
3130
+ transform(chunk, controller) {
3131
+ var _a22, _b16, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r;
3132
+ if (options.includeRawChunks) {
3133
+ controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
2543
3134
  }
2544
- if (tc.id) buffer.id = tc.id;
2545
- if (tc.function?.name) buffer.name += tc.function.name;
2546
- if (tc.function?.arguments)
2547
- buffer.arguments += tc.function.arguments;
2548
- }
2549
- }
2550
- if (choice.finish_reason) {
2551
- if (textId) {
2552
- controller.enqueue({
2553
- type: "text-end",
2554
- id: textId
2555
- });
2556
- textId = null;
2557
- }
2558
- for (const [, buffer] of toolCallBuffers) {
2559
- if (buffer.name) {
3135
+ if (!chunk.success) {
3136
+ finishReason = { unified: "error", raw: void 0 };
3137
+ controller.enqueue({ type: "error", error: chunk.error });
3138
+ return;
3139
+ }
3140
+ metadataExtractor == null ? void 0 : metadataExtractor.processChunk(chunk.rawValue);
3141
+ if ("error" in chunk.value) {
3142
+ finishReason = { unified: "error", raw: void 0 };
2560
3143
  controller.enqueue({
2561
- type: "tool-call",
2562
- toolCallId: buffer.id,
2563
- toolName: buffer.name,
2564
- input: buffer.arguments
3144
+ type: "error",
3145
+ error: chunk.value.error.message
2565
3146
  });
3147
+ return;
2566
3148
  }
2567
- }
2568
- toolCallBuffers.clear();
2569
- controller.enqueue({
2570
- type: "finish",
2571
- finishReason: mapApertisFinishReason(choice.finish_reason),
2572
- usage: {
2573
- inputTokens: {
2574
- total: chunk.usage?.prompt_tokens ?? 0,
2575
- noCache: void 0,
2576
- cacheRead: void 0,
2577
- cacheWrite: void 0
2578
- },
2579
- outputTokens: {
2580
- total: chunk.usage?.completion_tokens ?? 0,
2581
- text: void 0,
2582
- reasoning: void 0
3149
+ const value = chunk.value;
3150
+ if (isFirstChunk) {
3151
+ isFirstChunk = false;
3152
+ controller.enqueue({
3153
+ type: "response-metadata",
3154
+ ...getResponseMetadata(value)
3155
+ });
3156
+ }
3157
+ if (value.usage != null) {
3158
+ usage = value.usage;
3159
+ }
3160
+ const choice = value.choices[0];
3161
+ if ((choice == null ? void 0 : choice.finish_reason) != null) {
3162
+ finishReason = {
3163
+ unified: mapOpenAICompatibleFinishReason(choice.finish_reason),
3164
+ raw: (_a22 = choice.finish_reason) != null ? _a22 : void 0
3165
+ };
3166
+ }
3167
+ if ((choice == null ? void 0 : choice.delta) == null) {
3168
+ return;
3169
+ }
3170
+ const delta = choice.delta;
3171
+ const reasoningContent = (_b16 = delta.reasoning_content) != null ? _b16 : delta.reasoning;
3172
+ if (reasoningContent) {
3173
+ if (!isActiveReasoning) {
3174
+ controller.enqueue({
3175
+ type: "reasoning-start",
3176
+ id: "reasoning-0"
3177
+ });
3178
+ isActiveReasoning = true;
2583
3179
  }
3180
+ controller.enqueue({
3181
+ type: "reasoning-delta",
3182
+ id: "reasoning-0",
3183
+ delta: reasoningContent
3184
+ });
3185
+ }
3186
+ if (delta.content) {
3187
+ if (isActiveReasoning) {
3188
+ controller.enqueue({
3189
+ type: "reasoning-end",
3190
+ id: "reasoning-0"
3191
+ });
3192
+ isActiveReasoning = false;
3193
+ }
3194
+ if (!isActiveText) {
3195
+ controller.enqueue({ type: "text-start", id: "txt-0" });
3196
+ isActiveText = true;
3197
+ }
3198
+ controller.enqueue({
3199
+ type: "text-delta",
3200
+ id: "txt-0",
3201
+ delta: delta.content
3202
+ });
3203
+ }
3204
+ if (delta.tool_calls != null) {
3205
+ if (isActiveReasoning) {
3206
+ controller.enqueue({
3207
+ type: "reasoning-end",
3208
+ id: "reasoning-0"
3209
+ });
3210
+ isActiveReasoning = false;
3211
+ }
3212
+ for (const toolCallDelta of delta.tool_calls) {
3213
+ const index = (_c = toolCallDelta.index) != null ? _c : toolCalls.length;
3214
+ if (toolCalls[index] == null) {
3215
+ if (toolCallDelta.id == null) {
3216
+ throw new InvalidResponseDataError({
3217
+ data: toolCallDelta,
3218
+ message: `Expected 'id' to be a string.`
3219
+ });
3220
+ }
3221
+ if (((_d = toolCallDelta.function) == null ? void 0 : _d.name) == null) {
3222
+ throw new InvalidResponseDataError({
3223
+ data: toolCallDelta,
3224
+ message: `Expected 'function.name' to be a string.`
3225
+ });
3226
+ }
3227
+ controller.enqueue({
3228
+ type: "tool-input-start",
3229
+ id: toolCallDelta.id,
3230
+ toolName: toolCallDelta.function.name
3231
+ });
3232
+ toolCalls[index] = {
3233
+ id: toolCallDelta.id,
3234
+ type: "function",
3235
+ function: {
3236
+ name: toolCallDelta.function.name,
3237
+ arguments: (_e = toolCallDelta.function.arguments) != null ? _e : ""
3238
+ },
3239
+ hasFinished: false,
3240
+ thoughtSignature: (_h = (_g = (_f = toolCallDelta.extra_content) == null ? void 0 : _f.google) == null ? void 0 : _g.thought_signature) != null ? _h : void 0
3241
+ };
3242
+ const toolCall2 = toolCalls[index];
3243
+ if (((_i = toolCall2.function) == null ? void 0 : _i.name) != null && ((_j = toolCall2.function) == null ? void 0 : _j.arguments) != null) {
3244
+ if (toolCall2.function.arguments.length > 0) {
3245
+ controller.enqueue({
3246
+ type: "tool-input-delta",
3247
+ id: toolCall2.id,
3248
+ delta: toolCall2.function.arguments
3249
+ });
3250
+ }
3251
+ if (isParsableJson(toolCall2.function.arguments)) {
3252
+ controller.enqueue({
3253
+ type: "tool-input-end",
3254
+ id: toolCall2.id
3255
+ });
3256
+ controller.enqueue({
3257
+ type: "tool-call",
3258
+ toolCallId: (_k = toolCall2.id) != null ? _k : generateId(),
3259
+ toolName: toolCall2.function.name,
3260
+ input: toolCall2.function.arguments,
3261
+ ...toolCall2.thoughtSignature ? {
3262
+ providerMetadata: {
3263
+ [providerOptionsName]: {
3264
+ thoughtSignature: toolCall2.thoughtSignature
3265
+ }
3266
+ }
3267
+ } : {}
3268
+ });
3269
+ toolCall2.hasFinished = true;
3270
+ }
3271
+ }
3272
+ continue;
3273
+ }
3274
+ const toolCall = toolCalls[index];
3275
+ if (toolCall.hasFinished) {
3276
+ continue;
3277
+ }
3278
+ if (((_l = toolCallDelta.function) == null ? void 0 : _l.arguments) != null) {
3279
+ toolCall.function.arguments += (_n = (_m = toolCallDelta.function) == null ? void 0 : _m.arguments) != null ? _n : "";
3280
+ }
3281
+ controller.enqueue({
3282
+ type: "tool-input-delta",
3283
+ id: toolCall.id,
3284
+ delta: (_o = toolCallDelta.function.arguments) != null ? _o : ""
3285
+ });
3286
+ if (((_p = toolCall.function) == null ? void 0 : _p.name) != null && ((_q = toolCall.function) == null ? void 0 : _q.arguments) != null && isParsableJson(toolCall.function.arguments)) {
3287
+ controller.enqueue({
3288
+ type: "tool-input-end",
3289
+ id: toolCall.id
3290
+ });
3291
+ controller.enqueue({
3292
+ type: "tool-call",
3293
+ toolCallId: (_r = toolCall.id) != null ? _r : generateId(),
3294
+ toolName: toolCall.function.name,
3295
+ input: toolCall.function.arguments,
3296
+ ...toolCall.thoughtSignature ? {
3297
+ providerMetadata: {
3298
+ [providerOptionsName]: {
3299
+ thoughtSignature: toolCall.thoughtSignature
3300
+ }
3301
+ }
3302
+ } : {}
3303
+ });
3304
+ toolCall.hasFinished = true;
3305
+ }
3306
+ }
3307
+ }
3308
+ },
3309
+ flush(controller) {
3310
+ var _a22, _b16, _c, _d, _e;
3311
+ if (isActiveReasoning) {
3312
+ controller.enqueue({ type: "reasoning-end", id: "reasoning-0" });
3313
+ }
3314
+ if (isActiveText) {
3315
+ controller.enqueue({ type: "text-end", id: "txt-0" });
3316
+ }
3317
+ for (const toolCall of toolCalls.filter(
3318
+ (toolCall2) => !toolCall2.hasFinished
3319
+ )) {
3320
+ controller.enqueue({
3321
+ type: "tool-input-end",
3322
+ id: toolCall.id
3323
+ });
3324
+ controller.enqueue({
3325
+ type: "tool-call",
3326
+ toolCallId: (_a22 = toolCall.id) != null ? _a22 : generateId(),
3327
+ toolName: toolCall.function.name,
3328
+ input: toolCall.function.arguments,
3329
+ ...toolCall.thoughtSignature ? {
3330
+ providerMetadata: {
3331
+ [providerOptionsName]: {
3332
+ thoughtSignature: toolCall.thoughtSignature
3333
+ }
3334
+ }
3335
+ } : {}
3336
+ });
3337
+ }
3338
+ const providerMetadata = {
3339
+ [providerOptionsName]: {},
3340
+ ...metadataExtractor == null ? void 0 : metadataExtractor.buildMetadata()
3341
+ };
3342
+ if (((_b16 = usage == null ? void 0 : usage.completion_tokens_details) == null ? void 0 : _b16.accepted_prediction_tokens) != null) {
3343
+ providerMetadata[providerOptionsName].acceptedPredictionTokens = (_c = usage == null ? void 0 : usage.completion_tokens_details) == null ? void 0 : _c.accepted_prediction_tokens;
3344
+ }
3345
+ if (((_d = usage == null ? void 0 : usage.completion_tokens_details) == null ? void 0 : _d.rejected_prediction_tokens) != null) {
3346
+ providerMetadata[providerOptionsName].rejectedPredictionTokens = (_e = usage == null ? void 0 : usage.completion_tokens_details) == null ? void 0 : _e.rejected_prediction_tokens;
2584
3347
  }
2585
- });
2586
- }
2587
- },
2588
- flush(controller) {
2589
- if (textId) {
2590
- controller.enqueue({
2591
- type: "text-end",
2592
- id: textId
2593
- });
2594
- }
2595
- for (const [, buffer] of toolCallBuffers) {
2596
- if (buffer.name) {
2597
3348
  controller.enqueue({
2598
- type: "tool-call",
2599
- toolCallId: buffer.id,
2600
- toolName: buffer.name,
2601
- input: buffer.arguments
3349
+ type: "finish",
3350
+ finishReason,
3351
+ usage: convertOpenAICompatibleChatUsage(usage),
3352
+ providerMetadata
2602
3353
  });
2603
3354
  }
2604
- }
2605
- }
2606
- });
2607
- return {
2608
- stream: response.pipeThrough(transformStream),
2609
- request: { body }
3355
+ })
3356
+ ),
3357
+ request: { body },
3358
+ response: { headers: responseHeaders }
2610
3359
  };
2611
3360
  }
2612
- buildRequestBody(options, stream) {
2613
- const tools = this.filterFunctionTools(options.tools);
2614
- const responseFormat = options.responseFormat?.type === "json" ? { type: "json_object" } : void 0;
2615
- const body = {
2616
- model: this.modelId,
2617
- messages: convertToOpenAIMessages(options.prompt),
2618
- stream
3361
+ };
3362
+ var openaiCompatibleTokenUsageSchema = import_v4.z.looseObject({
3363
+ prompt_tokens: import_v4.z.number().nullish(),
3364
+ completion_tokens: import_v4.z.number().nullish(),
3365
+ total_tokens: import_v4.z.number().nullish(),
3366
+ prompt_tokens_details: import_v4.z.object({
3367
+ cached_tokens: import_v4.z.number().nullish()
3368
+ }).nullish(),
3369
+ completion_tokens_details: import_v4.z.object({
3370
+ reasoning_tokens: import_v4.z.number().nullish(),
3371
+ accepted_prediction_tokens: import_v4.z.number().nullish(),
3372
+ rejected_prediction_tokens: import_v4.z.number().nullish()
3373
+ }).nullish()
3374
+ }).nullish();
3375
+ var OpenAICompatibleChatResponseSchema = import_v4.z.looseObject({
3376
+ id: import_v4.z.string().nullish(),
3377
+ created: import_v4.z.number().nullish(),
3378
+ model: import_v4.z.string().nullish(),
3379
+ choices: import_v4.z.array(
3380
+ import_v4.z.object({
3381
+ message: import_v4.z.object({
3382
+ role: import_v4.z.literal("assistant").nullish(),
3383
+ content: import_v4.z.string().nullish(),
3384
+ reasoning_content: import_v4.z.string().nullish(),
3385
+ reasoning: import_v4.z.string().nullish(),
3386
+ tool_calls: import_v4.z.array(
3387
+ import_v4.z.object({
3388
+ id: import_v4.z.string().nullish(),
3389
+ function: import_v4.z.object({
3390
+ name: import_v4.z.string(),
3391
+ arguments: import_v4.z.string()
3392
+ }),
3393
+ // Support for Google Gemini thought signatures via OpenAI compatibility
3394
+ extra_content: import_v4.z.object({
3395
+ google: import_v4.z.object({
3396
+ thought_signature: import_v4.z.string().nullish()
3397
+ }).nullish()
3398
+ }).nullish()
3399
+ })
3400
+ ).nullish()
3401
+ }),
3402
+ finish_reason: import_v4.z.string().nullish()
3403
+ })
3404
+ ),
3405
+ usage: openaiCompatibleTokenUsageSchema
3406
+ });
3407
+ var chunkBaseSchema = import_v4.z.looseObject({
3408
+ id: import_v4.z.string().nullish(),
3409
+ created: import_v4.z.number().nullish(),
3410
+ model: import_v4.z.string().nullish(),
3411
+ choices: import_v4.z.array(
3412
+ import_v4.z.object({
3413
+ delta: import_v4.z.object({
3414
+ role: import_v4.z.enum(["assistant"]).nullish(),
3415
+ content: import_v4.z.string().nullish(),
3416
+ // Most openai-compatible models set `reasoning_content`, but some
3417
+ // providers serving `gpt-oss` set `reasoning`. See #7866
3418
+ reasoning_content: import_v4.z.string().nullish(),
3419
+ reasoning: import_v4.z.string().nullish(),
3420
+ tool_calls: import_v4.z.array(
3421
+ import_v4.z.object({
3422
+ index: import_v4.z.number().nullish(),
3423
+ //google does not send index
3424
+ id: import_v4.z.string().nullish(),
3425
+ function: import_v4.z.object({
3426
+ name: import_v4.z.string().nullish(),
3427
+ arguments: import_v4.z.string().nullish()
3428
+ }),
3429
+ // Support for Google Gemini thought signatures via OpenAI compatibility
3430
+ extra_content: import_v4.z.object({
3431
+ google: import_v4.z.object({
3432
+ thought_signature: import_v4.z.string().nullish()
3433
+ }).nullish()
3434
+ }).nullish()
3435
+ })
3436
+ ).nullish()
3437
+ }).nullish(),
3438
+ finish_reason: import_v4.z.string().nullish()
3439
+ })
3440
+ ),
3441
+ usage: openaiCompatibleTokenUsageSchema
3442
+ });
3443
+ var createOpenAICompatibleChatChunkSchema = (errorSchema) => import_v4.z.union([chunkBaseSchema, errorSchema]);
3444
+ function convertOpenAICompatibleCompletionUsage(usage) {
3445
+ var _a16, _b16;
3446
+ if (usage == null) {
3447
+ return {
3448
+ inputTokens: {
3449
+ total: void 0,
3450
+ noCache: void 0,
3451
+ cacheRead: void 0,
3452
+ cacheWrite: void 0
3453
+ },
3454
+ outputTokens: {
3455
+ total: void 0,
3456
+ text: void 0,
3457
+ reasoning: void 0
3458
+ },
3459
+ raw: void 0
2619
3460
  };
2620
- if (stream) body.stream_options = { include_usage: true };
2621
- if (options.temperature !== void 0)
2622
- body.temperature = options.temperature;
2623
- if (options.maxOutputTokens !== void 0)
2624
- body.max_tokens = options.maxOutputTokens;
2625
- if (options.topP !== void 0) body.top_p = options.topP;
2626
- if (options.frequencyPenalty !== void 0)
2627
- body.frequency_penalty = options.frequencyPenalty;
2628
- if (options.presencePenalty !== void 0)
2629
- body.presence_penalty = options.presencePenalty;
2630
- if (options.stopSequences !== void 0) body.stop = options.stopSequences;
2631
- if (options.seed !== void 0) body.seed = options.seed;
2632
- const convertedTools = convertToOpenAITools(tools);
2633
- if (convertedTools !== void 0) body.tools = convertedTools;
2634
- const convertedToolChoice = convertToOpenAIToolChoice(options.toolChoice);
2635
- if (convertedToolChoice !== void 0)
2636
- body.tool_choice = convertedToolChoice;
2637
- if (responseFormat !== void 0) body.response_format = responseFormat;
2638
- if (this.settings.user !== void 0) body.user = this.settings.user;
2639
- if (this.settings.logprobs !== void 0)
2640
- body.logprobs = this.settings.logprobs;
2641
- if (this.settings.topLogprobs !== void 0)
2642
- body.top_logprobs = this.settings.topLogprobs;
2643
- return body;
2644
- }
2645
- filterFunctionTools(tools) {
2646
- if (!tools) return void 0;
2647
- return tools.filter(
2648
- (tool) => tool.type === "function"
2649
- );
2650
3461
  }
2651
- };
3462
+ const promptTokens = (_a16 = usage.prompt_tokens) != null ? _a16 : 0;
3463
+ const completionTokens = (_b16 = usage.completion_tokens) != null ? _b16 : 0;
3464
+ return {
3465
+ inputTokens: {
3466
+ total: promptTokens,
3467
+ noCache: promptTokens,
3468
+ cacheRead: void 0,
3469
+ cacheWrite: void 0
3470
+ },
3471
+ outputTokens: {
3472
+ total: completionTokens,
3473
+ text: completionTokens,
3474
+ reasoning: void 0
3475
+ },
3476
+ raw: usage
3477
+ };
3478
+ }
3479
+ function convertToOpenAICompatibleCompletionPrompt({
3480
+ prompt,
3481
+ user = "user",
3482
+ assistant = "assistant"
3483
+ }) {
3484
+ let text = "";
3485
+ if (prompt[0].role === "system") {
3486
+ text += `${prompt[0].content}
3487
+
3488
+ `;
3489
+ prompt = prompt.slice(1);
3490
+ }
3491
+ for (const { role, content } of prompt) {
3492
+ switch (role) {
3493
+ case "system": {
3494
+ throw new InvalidPromptError({
3495
+ message: "Unexpected system message in prompt: ${content}",
3496
+ prompt
3497
+ });
3498
+ }
3499
+ case "user": {
3500
+ const userMessage = content.map((part) => {
3501
+ switch (part.type) {
3502
+ case "text": {
3503
+ return part.text;
3504
+ }
3505
+ }
3506
+ }).filter(Boolean).join("");
3507
+ text += `${user}:
3508
+ ${userMessage}
3509
+
3510
+ `;
3511
+ break;
3512
+ }
3513
+ case "assistant": {
3514
+ const assistantMessage = content.map((part) => {
3515
+ switch (part.type) {
3516
+ case "text": {
3517
+ return part.text;
3518
+ }
3519
+ case "tool-call": {
3520
+ throw new UnsupportedFunctionalityError({
3521
+ functionality: "tool-call messages"
3522
+ });
3523
+ }
3524
+ }
3525
+ }).join("");
3526
+ text += `${assistant}:
3527
+ ${assistantMessage}
2652
3528
 
2653
- // src/apertis-chat-language-model-v2.ts
2654
- var ApertisChatLanguageModelV2 = class {
2655
- constructor(modelId, settings, config) {
3529
+ `;
3530
+ break;
3531
+ }
3532
+ case "tool": {
3533
+ throw new UnsupportedFunctionalityError({
3534
+ functionality: "tool messages"
3535
+ });
3536
+ }
3537
+ default: {
3538
+ const _exhaustiveCheck = role;
3539
+ throw new Error(`Unsupported role: ${_exhaustiveCheck}`);
3540
+ }
3541
+ }
3542
+ }
3543
+ text += `${assistant}:
3544
+ `;
3545
+ return {
3546
+ prompt: text,
3547
+ stopSequences: [`
3548
+ ${user}:`]
3549
+ };
3550
+ }
3551
+ function getResponseMetadata2({
3552
+ id,
3553
+ model,
3554
+ created
3555
+ }) {
3556
+ return {
3557
+ id: id != null ? id : void 0,
3558
+ modelId: model != null ? model : void 0,
3559
+ timestamp: created != null ? new Date(created * 1e3) : void 0
3560
+ };
3561
+ }
3562
+ function mapOpenAICompatibleFinishReason2(finishReason) {
3563
+ switch (finishReason) {
3564
+ case "stop":
3565
+ return "stop";
3566
+ case "length":
3567
+ return "length";
3568
+ case "content_filter":
3569
+ return "content-filter";
3570
+ case "function_call":
3571
+ case "tool_calls":
3572
+ return "tool-calls";
3573
+ default:
3574
+ return "other";
3575
+ }
3576
+ }
3577
+ var openaiCompatibleLanguageModelCompletionOptions = import_v45.z.object({
3578
+ /**
3579
+ * Echo back the prompt in addition to the completion.
3580
+ */
3581
+ echo: import_v45.z.boolean().optional(),
3582
+ /**
3583
+ * Modify the likelihood of specified tokens appearing in the completion.
3584
+ *
3585
+ * Accepts a JSON object that maps tokens (specified by their token ID in
3586
+ * the GPT tokenizer) to an associated bias value from -100 to 100.
3587
+ */
3588
+ logitBias: import_v45.z.record(import_v45.z.string(), import_v45.z.number()).optional(),
3589
+ /**
3590
+ * The suffix that comes after a completion of inserted text.
3591
+ */
3592
+ suffix: import_v45.z.string().optional(),
3593
+ /**
3594
+ * A unique identifier representing your end-user, which can help providers to
3595
+ * monitor and detect abuse.
3596
+ */
3597
+ user: import_v45.z.string().optional()
3598
+ });
3599
+ var OpenAICompatibleCompletionLanguageModel = class {
3600
+ // type inferred via constructor
3601
+ constructor(modelId, config) {
3602
+ this.specificationVersion = "v3";
3603
+ var _a16;
2656
3604
  this.modelId = modelId;
2657
- this.settings = settings;
2658
3605
  this.config = config;
3606
+ const errorStructure = (_a16 = config.errorStructure) != null ? _a16 : defaultOpenAICompatibleErrorStructure;
3607
+ this.chunkSchema = createOpenAICompatibleCompletionChunkSchema(
3608
+ errorStructure.errorSchema
3609
+ );
3610
+ this.failedResponseHandler = createJsonErrorResponseHandler(errorStructure);
2659
3611
  }
2660
- specificationVersion = "v2";
2661
- supportedUrls = {
2662
- "image/*": [/^https?:\/\/.+$/]
2663
- };
2664
3612
  get provider() {
2665
3613
  return this.config.provider;
2666
3614
  }
3615
+ get providerOptionsName() {
3616
+ return this.config.provider.split(".")[0].trim();
3617
+ }
3618
+ get supportedUrls() {
3619
+ var _a16, _b16, _c;
3620
+ return (_c = (_b16 = (_a16 = this.config).supportedUrls) == null ? void 0 : _b16.call(_a16)) != null ? _c : {};
3621
+ }
3622
+ async getArgs({
3623
+ prompt,
3624
+ maxOutputTokens,
3625
+ temperature,
3626
+ topP,
3627
+ topK,
3628
+ frequencyPenalty,
3629
+ presencePenalty,
3630
+ stopSequences: userStopSequences,
3631
+ responseFormat,
3632
+ seed,
3633
+ providerOptions,
3634
+ tools,
3635
+ toolChoice
3636
+ }) {
3637
+ var _a16, _b16;
3638
+ const warnings = [];
3639
+ const completionOptions = Object.assign(
3640
+ (_a16 = await parseProviderOptions({
3641
+ provider: this.providerOptionsName,
3642
+ providerOptions,
3643
+ schema: openaiCompatibleLanguageModelCompletionOptions
3644
+ })) != null ? _a16 : {},
3645
+ (_b16 = await parseProviderOptions({
3646
+ provider: toCamelCase(this.providerOptionsName),
3647
+ providerOptions,
3648
+ schema: openaiCompatibleLanguageModelCompletionOptions
3649
+ })) != null ? _b16 : {}
3650
+ );
3651
+ if (topK != null) {
3652
+ warnings.push({ type: "unsupported", feature: "topK" });
3653
+ }
3654
+ if (tools == null ? void 0 : tools.length) {
3655
+ warnings.push({ type: "unsupported", feature: "tools" });
3656
+ }
3657
+ if (toolChoice != null) {
3658
+ warnings.push({ type: "unsupported", feature: "toolChoice" });
3659
+ }
3660
+ if (responseFormat != null && responseFormat.type !== "text") {
3661
+ warnings.push({
3662
+ type: "unsupported",
3663
+ feature: "responseFormat",
3664
+ details: "JSON response format is not supported."
3665
+ });
3666
+ }
3667
+ const { prompt: completionPrompt, stopSequences } = convertToOpenAICompatibleCompletionPrompt({ prompt });
3668
+ const stop = [...stopSequences != null ? stopSequences : [], ...userStopSequences != null ? userStopSequences : []];
3669
+ return {
3670
+ args: {
3671
+ // model id:
3672
+ model: this.modelId,
3673
+ // model specific settings:
3674
+ echo: completionOptions.echo,
3675
+ logit_bias: completionOptions.logitBias,
3676
+ suffix: completionOptions.suffix,
3677
+ user: completionOptions.user,
3678
+ // standardized settings:
3679
+ max_tokens: maxOutputTokens,
3680
+ temperature,
3681
+ top_p: topP,
3682
+ frequency_penalty: frequencyPenalty,
3683
+ presence_penalty: presencePenalty,
3684
+ seed,
3685
+ ...providerOptions == null ? void 0 : providerOptions[this.providerOptionsName],
3686
+ ...providerOptions == null ? void 0 : providerOptions[toCamelCase(this.providerOptionsName)],
3687
+ // prompt:
3688
+ prompt: completionPrompt,
3689
+ // stop sequences:
3690
+ stop: stop.length > 0 ? stop : void 0
3691
+ },
3692
+ warnings
3693
+ };
3694
+ }
2667
3695
  async doGenerate(options) {
2668
- const body = this.buildRequestBody(options, false);
2669
- const { value: response } = await postJsonToApi({
2670
- url: `${this.config.baseURL}/chat/completions`,
2671
- headers: this.config.headers(),
2672
- body,
2673
- failedResponseHandler: apertisFailedResponseHandler,
3696
+ const { args, warnings } = await this.getArgs(options);
3697
+ const {
3698
+ responseHeaders,
3699
+ value: response,
3700
+ rawValue: rawResponse
3701
+ } = await postJsonToApi({
3702
+ url: this.config.url({
3703
+ path: "/completions",
3704
+ modelId: this.modelId
3705
+ }),
3706
+ headers: combineHeaders(this.config.headers(), options.headers),
3707
+ body: args,
3708
+ failedResponseHandler: this.failedResponseHandler,
2674
3709
  successfulResponseHandler: createJsonResponseHandler(
2675
- openAIChatResponseSchema
3710
+ openaiCompatibleCompletionResponseSchema
2676
3711
  ),
2677
- fetch: this.config.fetch,
2678
- abortSignal: options.abortSignal
3712
+ abortSignal: options.abortSignal,
3713
+ fetch: this.config.fetch
2679
3714
  });
2680
3715
  const choice = response.choices[0];
2681
3716
  const content = [];
2682
- if (choice.message.content) {
2683
- content.push({
2684
- type: "text",
2685
- text: choice.message.content
2686
- });
2687
- }
2688
- if (choice.message.tool_calls) {
2689
- for (const tc of choice.message.tool_calls) {
2690
- content.push({
2691
- type: "tool-call",
2692
- toolCallId: tc.id,
2693
- toolName: tc.function.name,
2694
- input: tc.function.arguments
2695
- });
2696
- }
3717
+ if (choice.text != null && choice.text.length > 0) {
3718
+ content.push({ type: "text", text: choice.text });
2697
3719
  }
2698
3720
  return {
2699
3721
  content,
2700
- finishReason: mapApertisFinishReasonV2(choice.finish_reason),
2701
- usage: {
2702
- inputTokens: response.usage?.prompt_tokens ?? 0,
2703
- outputTokens: response.usage?.completion_tokens ?? 0,
2704
- totalTokens: response.usage?.total_tokens ?? void 0
3722
+ usage: convertOpenAICompatibleCompletionUsage(response.usage),
3723
+ finishReason: {
3724
+ unified: mapOpenAICompatibleFinishReason2(choice.finish_reason),
3725
+ raw: choice.finish_reason
2705
3726
  },
2706
- warnings: [],
2707
- request: { body }
3727
+ request: { body: args },
3728
+ response: {
3729
+ ...getResponseMetadata2(response),
3730
+ headers: responseHeaders,
3731
+ body: rawResponse
3732
+ },
3733
+ warnings
2708
3734
  };
2709
3735
  }
2710
3736
  async doStream(options) {
2711
- const body = this.buildRequestBody(options, true);
2712
- const { value: response } = await postJsonToApi({
2713
- url: `${this.config.baseURL}/chat/completions`,
2714
- headers: this.config.headers(),
3737
+ const { args, warnings } = await this.getArgs(options);
3738
+ const body = {
3739
+ ...args,
3740
+ stream: true,
3741
+ // only include stream_options when in strict compatibility mode:
3742
+ stream_options: this.config.includeUsage ? { include_usage: true } : void 0
3743
+ };
3744
+ const { responseHeaders, value: response } = await postJsonToApi({
3745
+ url: this.config.url({
3746
+ path: "/completions",
3747
+ modelId: this.modelId
3748
+ }),
3749
+ headers: combineHeaders(this.config.headers(), options.headers),
2715
3750
  body,
2716
- failedResponseHandler: apertisFailedResponseHandler,
3751
+ failedResponseHandler: this.failedResponseHandler,
2717
3752
  successfulResponseHandler: createEventSourceResponseHandler(
2718
- openAIChatChunkSchema
3753
+ this.chunkSchema
2719
3754
  ),
2720
- fetch: this.config.fetch,
2721
- abortSignal: options.abortSignal
3755
+ abortSignal: options.abortSignal,
3756
+ fetch: this.config.fetch
2722
3757
  });
2723
- const toolCallBuffers = /* @__PURE__ */ new Map();
2724
- let textId = null;
2725
- const transformStream = new TransformStream({
2726
- transform(parseResult, controller) {
2727
- if (!parseResult.success) {
2728
- return;
2729
- }
2730
- const chunk = parseResult.value;
2731
- const choice = chunk.choices[0];
2732
- if (!choice) return;
2733
- if (choice.delta.content) {
2734
- if (!textId) {
2735
- textId = generateId();
2736
- controller.enqueue({
2737
- type: "text-start",
2738
- id: textId
2739
- });
2740
- }
2741
- controller.enqueue({
2742
- type: "text-delta",
2743
- id: textId,
2744
- delta: choice.delta.content
2745
- });
2746
- }
2747
- if (choice.delta.tool_calls) {
2748
- for (const tc of choice.delta.tool_calls) {
2749
- let buffer = toolCallBuffers.get(tc.index);
2750
- if (!buffer) {
2751
- buffer = {
2752
- id: tc.id ?? generateId(),
2753
- name: "",
2754
- arguments: ""
3758
+ let finishReason = {
3759
+ unified: "other",
3760
+ raw: void 0
3761
+ };
3762
+ let usage = void 0;
3763
+ let isFirstChunk = true;
3764
+ return {
3765
+ stream: response.pipeThrough(
3766
+ new TransformStream({
3767
+ start(controller) {
3768
+ controller.enqueue({ type: "stream-start", warnings });
3769
+ },
3770
+ transform(chunk, controller) {
3771
+ var _a16;
3772
+ if (options.includeRawChunks) {
3773
+ controller.enqueue({ type: "raw", rawValue: chunk.rawValue });
3774
+ }
3775
+ if (!chunk.success) {
3776
+ finishReason = { unified: "error", raw: void 0 };
3777
+ controller.enqueue({ type: "error", error: chunk.error });
3778
+ return;
3779
+ }
3780
+ const value = chunk.value;
3781
+ if ("error" in value) {
3782
+ finishReason = { unified: "error", raw: void 0 };
3783
+ controller.enqueue({ type: "error", error: value.error });
3784
+ return;
3785
+ }
3786
+ if (isFirstChunk) {
3787
+ isFirstChunk = false;
3788
+ controller.enqueue({
3789
+ type: "response-metadata",
3790
+ ...getResponseMetadata2(value)
3791
+ });
3792
+ controller.enqueue({
3793
+ type: "text-start",
3794
+ id: "0"
3795
+ });
3796
+ }
3797
+ if (value.usage != null) {
3798
+ usage = value.usage;
3799
+ }
3800
+ const choice = value.choices[0];
3801
+ if ((choice == null ? void 0 : choice.finish_reason) != null) {
3802
+ finishReason = {
3803
+ unified: mapOpenAICompatibleFinishReason2(choice.finish_reason),
3804
+ raw: (_a16 = choice.finish_reason) != null ? _a16 : void 0
2755
3805
  };
2756
- toolCallBuffers.set(tc.index, buffer);
2757
3806
  }
2758
- if (tc.id) buffer.id = tc.id;
2759
- if (tc.function?.name) buffer.name += tc.function.name;
2760
- if (tc.function?.arguments)
2761
- buffer.arguments += tc.function.arguments;
2762
- }
2763
- }
2764
- if (choice.finish_reason) {
2765
- if (textId) {
2766
- controller.enqueue({
2767
- type: "text-end",
2768
- id: textId
2769
- });
2770
- textId = null;
2771
- }
2772
- for (const [, buffer] of toolCallBuffers) {
2773
- if (buffer.name) {
3807
+ if ((choice == null ? void 0 : choice.text) != null) {
2774
3808
  controller.enqueue({
2775
- type: "tool-call",
2776
- toolCallId: buffer.id,
2777
- toolName: buffer.name,
2778
- input: buffer.arguments
3809
+ type: "text-delta",
3810
+ id: "0",
3811
+ delta: choice.text
2779
3812
  });
2780
3813
  }
2781
- }
2782
- toolCallBuffers.clear();
2783
- controller.enqueue({
2784
- type: "finish",
2785
- finishReason: mapApertisFinishReasonV2(choice.finish_reason),
2786
- usage: {
2787
- inputTokens: chunk.usage?.prompt_tokens ?? 0,
2788
- outputTokens: chunk.usage?.completion_tokens ?? 0,
2789
- totalTokens: void 0
3814
+ },
3815
+ flush(controller) {
3816
+ if (!isFirstChunk) {
3817
+ controller.enqueue({ type: "text-end", id: "0" });
2790
3818
  }
2791
- });
2792
- }
2793
- },
2794
- flush(controller) {
2795
- if (textId) {
2796
- controller.enqueue({
2797
- type: "text-end",
2798
- id: textId
2799
- });
2800
- }
2801
- for (const [, buffer] of toolCallBuffers) {
2802
- if (buffer.name) {
2803
3819
  controller.enqueue({
2804
- type: "tool-call",
2805
- toolCallId: buffer.id,
2806
- toolName: buffer.name,
2807
- input: buffer.arguments
3820
+ type: "finish",
3821
+ finishReason,
3822
+ usage: convertOpenAICompatibleCompletionUsage(usage)
2808
3823
  });
2809
3824
  }
2810
- }
2811
- }
2812
- });
2813
- return {
2814
- stream: response.pipeThrough(transformStream),
2815
- request: { body }
2816
- };
2817
- }
2818
- buildRequestBody(options, stream) {
2819
- const tools = this.filterFunctionTools(options.tools);
2820
- const responseFormat = options.responseFormat?.type === "json" ? { type: "json_object" } : void 0;
2821
- const body = {
2822
- model: this.modelId,
2823
- messages: convertToOpenAIMessages(options.prompt),
2824
- stream
3825
+ })
3826
+ ),
3827
+ request: { body },
3828
+ response: { headers: responseHeaders }
2825
3829
  };
2826
- if (stream) body.stream_options = { include_usage: true };
2827
- if (options.temperature !== void 0)
2828
- body.temperature = options.temperature;
2829
- if (options.maxOutputTokens !== void 0)
2830
- body.max_tokens = options.maxOutputTokens;
2831
- if (options.topP !== void 0) body.top_p = options.topP;
2832
- if (options.frequencyPenalty !== void 0)
2833
- body.frequency_penalty = options.frequencyPenalty;
2834
- if (options.presencePenalty !== void 0)
2835
- body.presence_penalty = options.presencePenalty;
2836
- if (options.stopSequences !== void 0) body.stop = options.stopSequences;
2837
- if (options.seed !== void 0) body.seed = options.seed;
2838
- const convertedTools = convertToOpenAITools(tools);
2839
- if (convertedTools !== void 0) body.tools = convertedTools;
2840
- const convertedToolChoice = convertToOpenAIToolChoice(options.toolChoice);
2841
- if (convertedToolChoice !== void 0)
2842
- body.tool_choice = convertedToolChoice;
2843
- if (responseFormat !== void 0) body.response_format = responseFormat;
2844
- if (this.settings.user !== void 0) body.user = this.settings.user;
2845
- if (this.settings.logprobs !== void 0)
2846
- body.logprobs = this.settings.logprobs;
2847
- if (this.settings.topLogprobs !== void 0)
2848
- body.top_logprobs = this.settings.topLogprobs;
2849
- return body;
2850
- }
2851
- filterFunctionTools(tools) {
2852
- if (!tools) return void 0;
2853
- return tools.filter(
2854
- (tool) => tool.type === "function"
2855
- );
2856
3830
  }
2857
3831
  };
2858
-
2859
- // src/schemas/embedding-response.ts
2860
- var import_zod3 = require("zod");
2861
- var openAIEmbeddingResponseSchema = import_zod3.z.object({
2862
- object: import_zod3.z.literal("list").optional(),
2863
- data: import_zod3.z.array(
2864
- import_zod3.z.object({
2865
- object: import_zod3.z.literal("embedding").optional(),
2866
- embedding: import_zod3.z.array(import_zod3.z.number()),
2867
- index: import_zod3.z.number()
3832
+ var usageSchema = import_v44.z.object({
3833
+ prompt_tokens: import_v44.z.number(),
3834
+ completion_tokens: import_v44.z.number(),
3835
+ total_tokens: import_v44.z.number()
3836
+ });
3837
+ var openaiCompatibleCompletionResponseSchema = import_v44.z.object({
3838
+ id: import_v44.z.string().nullish(),
3839
+ created: import_v44.z.number().nullish(),
3840
+ model: import_v44.z.string().nullish(),
3841
+ choices: import_v44.z.array(
3842
+ import_v44.z.object({
3843
+ text: import_v44.z.string(),
3844
+ finish_reason: import_v44.z.string()
2868
3845
  })
2869
3846
  ),
2870
- model: import_zod3.z.string().optional(),
2871
- usage: import_zod3.z.object({
2872
- prompt_tokens: import_zod3.z.number(),
2873
- total_tokens: import_zod3.z.number()
2874
- }).optional()
3847
+ usage: usageSchema.nullish()
2875
3848
  });
2876
-
2877
- // src/apertis-embedding-model.ts
2878
- var ApertisEmbeddingModel = class {
2879
- constructor(modelId, settings, config) {
3849
+ var createOpenAICompatibleCompletionChunkSchema = (errorSchema) => import_v44.z.union([
3850
+ import_v44.z.object({
3851
+ id: import_v44.z.string().nullish(),
3852
+ created: import_v44.z.number().nullish(),
3853
+ model: import_v44.z.string().nullish(),
3854
+ choices: import_v44.z.array(
3855
+ import_v44.z.object({
3856
+ text: import_v44.z.string(),
3857
+ finish_reason: import_v44.z.string().nullish(),
3858
+ index: import_v44.z.number()
3859
+ })
3860
+ ),
3861
+ usage: usageSchema.nullish()
3862
+ }),
3863
+ errorSchema
3864
+ ]);
3865
+ var openaiCompatibleEmbeddingModelOptions = import_v47.z.object({
3866
+ /**
3867
+ * The number of dimensions the resulting output embeddings should have.
3868
+ * Only supported in text-embedding-3 and later models.
3869
+ */
3870
+ dimensions: import_v47.z.number().optional(),
3871
+ /**
3872
+ * A unique identifier representing your end-user, which can help providers to
3873
+ * monitor and detect abuse.
3874
+ */
3875
+ user: import_v47.z.string().optional()
3876
+ });
3877
+ var OpenAICompatibleEmbeddingModel = class {
3878
+ constructor(modelId, config) {
3879
+ this.specificationVersion = "v3";
2880
3880
  this.modelId = modelId;
2881
- this.settings = settings;
2882
3881
  this.config = config;
2883
- this.maxEmbeddingsPerCall = settings.maxEmbeddingsPerCall ?? 2048;
2884
- this.supportsParallelCalls = settings.supportsParallelCalls ?? true;
2885
3882
  }
2886
- specificationVersion = "v3";
2887
- maxEmbeddingsPerCall;
2888
- supportsParallelCalls;
2889
3883
  get provider() {
2890
3884
  return this.config.provider;
2891
3885
  }
2892
- async doEmbed(options) {
2893
- const body = {
2894
- model: this.modelId,
2895
- input: options.values,
2896
- encoding_format: "float"
2897
- };
2898
- if (this.settings.dimensions !== void 0) {
2899
- body.dimensions = this.settings.dimensions;
3886
+ get maxEmbeddingsPerCall() {
3887
+ var _a16;
3888
+ return (_a16 = this.config.maxEmbeddingsPerCall) != null ? _a16 : 2048;
3889
+ }
3890
+ get supportsParallelCalls() {
3891
+ var _a16;
3892
+ return (_a16 = this.config.supportsParallelCalls) != null ? _a16 : true;
3893
+ }
3894
+ get providerOptionsName() {
3895
+ return this.config.provider.split(".")[0].trim();
3896
+ }
3897
+ async doEmbed({
3898
+ values,
3899
+ headers,
3900
+ abortSignal,
3901
+ providerOptions
3902
+ }) {
3903
+ var _a16, _b16, _c;
3904
+ const warnings = [];
3905
+ const deprecatedOptions = await parseProviderOptions({
3906
+ provider: "openai-compatible",
3907
+ providerOptions,
3908
+ schema: openaiCompatibleEmbeddingModelOptions
3909
+ });
3910
+ if (deprecatedOptions != null) {
3911
+ warnings.push({
3912
+ type: "other",
3913
+ message: `The 'openai-compatible' key in providerOptions is deprecated. Use 'openaiCompatible' instead.`
3914
+ });
2900
3915
  }
2901
- if (this.settings.user !== void 0) {
2902
- body.user = this.settings.user;
3916
+ const compatibleOptions = Object.assign(
3917
+ deprecatedOptions != null ? deprecatedOptions : {},
3918
+ (_a16 = await parseProviderOptions({
3919
+ provider: "openaiCompatible",
3920
+ providerOptions,
3921
+ schema: openaiCompatibleEmbeddingModelOptions
3922
+ })) != null ? _a16 : {},
3923
+ (_b16 = await parseProviderOptions({
3924
+ provider: this.providerOptionsName,
3925
+ providerOptions,
3926
+ schema: openaiCompatibleEmbeddingModelOptions
3927
+ })) != null ? _b16 : {}
3928
+ );
3929
+ if (values.length > this.maxEmbeddingsPerCall) {
3930
+ throw new TooManyEmbeddingValuesForCallError({
3931
+ provider: this.provider,
3932
+ modelId: this.modelId,
3933
+ maxEmbeddingsPerCall: this.maxEmbeddingsPerCall,
3934
+ values
3935
+ });
2903
3936
  }
2904
- const { value: response } = await postJsonToApi({
2905
- url: `${this.config.baseURL}/embeddings`,
2906
- headers: this.config.headers(),
2907
- body,
2908
- failedResponseHandler: apertisFailedResponseHandler,
3937
+ const {
3938
+ responseHeaders,
3939
+ value: response,
3940
+ rawValue
3941
+ } = await postJsonToApi({
3942
+ url: this.config.url({
3943
+ path: "/embeddings",
3944
+ modelId: this.modelId
3945
+ }),
3946
+ headers: combineHeaders(this.config.headers(), headers),
3947
+ body: {
3948
+ model: this.modelId,
3949
+ input: values,
3950
+ encoding_format: "float",
3951
+ dimensions: compatibleOptions.dimensions,
3952
+ user: compatibleOptions.user
3953
+ },
3954
+ failedResponseHandler: createJsonErrorResponseHandler(
3955
+ (_c = this.config.errorStructure) != null ? _c : defaultOpenAICompatibleErrorStructure
3956
+ ),
2909
3957
  successfulResponseHandler: createJsonResponseHandler(
2910
- openAIEmbeddingResponseSchema
3958
+ openaiTextEmbeddingResponseSchema
2911
3959
  ),
2912
- fetch: this.config.fetch,
2913
- abortSignal: options.abortSignal
3960
+ abortSignal,
3961
+ fetch: this.config.fetch
2914
3962
  });
2915
3963
  return {
3964
+ warnings,
2916
3965
  embeddings: response.data.map((item) => item.embedding),
2917
3966
  usage: response.usage ? { tokens: response.usage.prompt_tokens } : void 0,
2918
- warnings: []
3967
+ providerMetadata: response.providerMetadata,
3968
+ response: { headers: responseHeaders, body: rawValue }
2919
3969
  };
2920
3970
  }
2921
3971
  };
2922
-
2923
- // src/apertis-embedding-model-v2.ts
2924
- var ApertisEmbeddingModelV2 = class {
2925
- constructor(modelId, settings, config) {
3972
+ var openaiTextEmbeddingResponseSchema = import_v46.z.object({
3973
+ data: import_v46.z.array(import_v46.z.object({ embedding: import_v46.z.array(import_v46.z.number()) })),
3974
+ usage: import_v46.z.object({ prompt_tokens: import_v46.z.number() }).nullish(),
3975
+ providerMetadata: import_v46.z.record(import_v46.z.string(), import_v46.z.record(import_v46.z.string(), import_v46.z.any())).optional()
3976
+ });
3977
+ var OpenAICompatibleImageModel = class {
3978
+ constructor(modelId, config) {
2926
3979
  this.modelId = modelId;
2927
- this.settings = settings;
2928
3980
  this.config = config;
2929
- this.maxEmbeddingsPerCall = settings.maxEmbeddingsPerCall ?? 2048;
2930
- this.supportsParallelCalls = settings.supportsParallelCalls ?? true;
3981
+ this.specificationVersion = "v3";
3982
+ this.maxImagesPerCall = 10;
2931
3983
  }
2932
- specificationVersion = "v2";
2933
- maxEmbeddingsPerCall;
2934
- supportsParallelCalls;
2935
3984
  get provider() {
2936
3985
  return this.config.provider;
2937
3986
  }
2938
- async doEmbed(options) {
2939
- const body = {
2940
- model: this.modelId,
2941
- input: options.values,
2942
- encoding_format: "float"
3987
+ /**
3988
+ * The provider options key used to extract provider-specific options.
3989
+ */
3990
+ get providerOptionsKey() {
3991
+ return this.config.provider.split(".")[0].trim();
3992
+ }
3993
+ // TODO: deprecate non-camelCase keys and remove in future major version
3994
+ getArgs(providerOptions) {
3995
+ return {
3996
+ ...providerOptions[this.providerOptionsKey],
3997
+ ...providerOptions[toCamelCase(this.providerOptionsKey)]
2943
3998
  };
2944
- if (this.settings.dimensions !== void 0) {
2945
- body.dimensions = this.settings.dimensions;
3999
+ }
4000
+ async doGenerate({
4001
+ prompt,
4002
+ n,
4003
+ size,
4004
+ aspectRatio,
4005
+ seed,
4006
+ providerOptions,
4007
+ headers,
4008
+ abortSignal,
4009
+ files,
4010
+ mask
4011
+ }) {
4012
+ var _a16, _b16, _c, _d, _e;
4013
+ const warnings = [];
4014
+ if (aspectRatio != null) {
4015
+ warnings.push({
4016
+ type: "unsupported",
4017
+ feature: "aspectRatio",
4018
+ details: "This model does not support aspect ratio. Use `size` instead."
4019
+ });
2946
4020
  }
2947
- if (this.settings.user !== void 0) {
2948
- body.user = this.settings.user;
4021
+ if (seed != null) {
4022
+ warnings.push({ type: "unsupported", feature: "seed" });
2949
4023
  }
2950
- const { value: response } = await postJsonToApi({
2951
- url: `${this.config.baseURL}/embeddings`,
2952
- headers: this.config.headers(),
2953
- body,
2954
- failedResponseHandler: apertisFailedResponseHandler,
4024
+ const currentDate = (_c = (_b16 = (_a16 = this.config._internal) == null ? void 0 : _a16.currentDate) == null ? void 0 : _b16.call(_a16)) != null ? _c : /* @__PURE__ */ new Date();
4025
+ const args = this.getArgs(providerOptions);
4026
+ if (files != null && files.length > 0) {
4027
+ const { value: response2, responseHeaders: responseHeaders2 } = await postFormDataToApi({
4028
+ url: this.config.url({
4029
+ path: "/images/edits",
4030
+ modelId: this.modelId
4031
+ }),
4032
+ headers: combineHeaders(this.config.headers(), headers),
4033
+ formData: convertToFormData({
4034
+ model: this.modelId,
4035
+ prompt,
4036
+ image: await Promise.all(files.map((file) => fileToBlob(file))),
4037
+ mask: mask != null ? await fileToBlob(mask) : void 0,
4038
+ n,
4039
+ size,
4040
+ ...args
4041
+ }),
4042
+ failedResponseHandler: createJsonErrorResponseHandler(
4043
+ (_d = this.config.errorStructure) != null ? _d : defaultOpenAICompatibleErrorStructure
4044
+ ),
4045
+ successfulResponseHandler: createJsonResponseHandler(
4046
+ openaiCompatibleImageResponseSchema
4047
+ ),
4048
+ abortSignal,
4049
+ fetch: this.config.fetch
4050
+ });
4051
+ return {
4052
+ images: response2.data.map((item) => item.b64_json),
4053
+ warnings,
4054
+ response: {
4055
+ timestamp: currentDate,
4056
+ modelId: this.modelId,
4057
+ headers: responseHeaders2
4058
+ }
4059
+ };
4060
+ }
4061
+ const { value: response, responseHeaders } = await postJsonToApi({
4062
+ url: this.config.url({
4063
+ path: "/images/generations",
4064
+ modelId: this.modelId
4065
+ }),
4066
+ headers: combineHeaders(this.config.headers(), headers),
4067
+ body: {
4068
+ model: this.modelId,
4069
+ prompt,
4070
+ n,
4071
+ size,
4072
+ ...args,
4073
+ response_format: "b64_json"
4074
+ },
4075
+ failedResponseHandler: createJsonErrorResponseHandler(
4076
+ (_e = this.config.errorStructure) != null ? _e : defaultOpenAICompatibleErrorStructure
4077
+ ),
2955
4078
  successfulResponseHandler: createJsonResponseHandler(
2956
- openAIEmbeddingResponseSchema
4079
+ openaiCompatibleImageResponseSchema
2957
4080
  ),
2958
- fetch: this.config.fetch,
2959
- abortSignal: options.abortSignal
4081
+ abortSignal,
4082
+ fetch: this.config.fetch
2960
4083
  });
2961
4084
  return {
2962
- embeddings: response.data.map((item) => item.embedding),
2963
- usage: response.usage ? { tokens: response.usage.prompt_tokens } : void 0
4085
+ images: response.data.map((item) => item.b64_json),
4086
+ warnings,
4087
+ response: {
4088
+ timestamp: currentDate,
4089
+ modelId: this.modelId,
4090
+ headers: responseHeaders
4091
+ }
2964
4092
  };
2965
4093
  }
2966
4094
  };
2967
-
2968
- // src/apertis-provider.ts
2969
- function initializeProvider(options = {}) {
2970
- const baseURL = withoutTrailingSlash(options.baseURL) ?? "https://api.apertis.ai/v1";
2971
- const getHeaders = () => ({
2972
- ...options.headers,
2973
- Authorization: `Bearer ${loadApiKey({
2974
- apiKey: options.apiKey,
2975
- environmentVariableName: "APERTIS_API_KEY",
2976
- description: "Apertis API key"
2977
- })}`,
2978
- "Content-Type": "application/json"
2979
- });
2980
- return { baseURL, getHeaders, fetch: options.fetch };
4095
+ var openaiCompatibleImageResponseSchema = import_v48.z.object({
4096
+ data: import_v48.z.array(import_v48.z.object({ b64_json: import_v48.z.string() }))
4097
+ });
4098
+ async function fileToBlob(file) {
4099
+ if (file.type === "url") {
4100
+ return downloadBlob(file.url);
4101
+ }
4102
+ const data = file.data instanceof Uint8Array ? file.data : convertBase64ToUint8Array(file.data);
4103
+ return new Blob([data], { type: file.mediaType });
2981
4104
  }
2982
- function createApertis(options = {}) {
2983
- const { baseURL, getHeaders, fetch: fetchImpl } = initializeProvider(options);
2984
- const createChatModel = (modelId, settings = {}) => new ApertisChatLanguageModelV2(modelId, settings, {
2985
- provider: "apertis.chat",
2986
- baseURL,
4105
+ var VERSION2 = true ? "2.0.41" : "0.0.0-test";
4106
+ function createOpenAICompatible(options) {
4107
+ const baseURL = withoutTrailingSlash(options.baseURL);
4108
+ const providerName = options.name;
4109
+ const headers = {
4110
+ ...options.apiKey && { Authorization: `Bearer ${options.apiKey}` },
4111
+ ...options.headers
4112
+ };
4113
+ const getHeaders = () => withUserAgentSuffix(headers, `ai-sdk/openai-compatible/${VERSION2}`);
4114
+ const getCommonModelConfig = (modelType) => ({
4115
+ provider: `${providerName}.${modelType}`,
4116
+ url: ({ path }) => {
4117
+ const url = new URL(`${baseURL}${path}`);
4118
+ if (options.queryParams) {
4119
+ url.search = new URLSearchParams(options.queryParams).toString();
4120
+ }
4121
+ return url.toString();
4122
+ },
2987
4123
  headers: getHeaders,
2988
- fetch: fetchImpl
4124
+ fetch: options.fetch
2989
4125
  });
2990
- const createEmbeddingModel = (modelId, settings = {}) => new ApertisEmbeddingModelV2(modelId, settings, {
2991
- provider: "apertis.embedding",
2992
- baseURL,
2993
- headers: getHeaders,
2994
- fetch: fetchImpl
4126
+ const createLanguageModel = (modelId) => createChatModel(modelId);
4127
+ const createChatModel = (modelId) => new OpenAICompatibleChatLanguageModel(modelId, {
4128
+ ...getCommonModelConfig("chat"),
4129
+ includeUsage: options.includeUsage,
4130
+ supportsStructuredOutputs: options.supportsStructuredOutputs,
4131
+ transformRequestBody: options.transformRequestBody,
4132
+ metadataExtractor: options.metadataExtractor
2995
4133
  });
2996
- const provider = Object.assign(
2997
- (modelId, settings) => createChatModel(modelId, settings),
2998
- {
2999
- specificationVersion: "v2",
3000
- chat: createChatModel,
3001
- languageModel: (modelId) => createChatModel(modelId),
3002
- textEmbeddingModel: createEmbeddingModel,
3003
- imageModel: () => {
3004
- throw new Error("Image models are not supported by Apertis");
3005
- }
3006
- }
3007
- );
3008
- return provider;
3009
- }
3010
- function createApertisV3(options = {}) {
3011
- const { baseURL, getHeaders, fetch: fetchImpl } = initializeProvider(options);
3012
- const createChatModel = (modelId, settings = {}) => new ApertisChatLanguageModel(modelId, settings, {
3013
- provider: "apertis.chat",
3014
- baseURL,
3015
- headers: getHeaders,
3016
- fetch: fetchImpl
4134
+ const createCompletionModel = (modelId) => new OpenAICompatibleCompletionLanguageModel(modelId, {
4135
+ ...getCommonModelConfig("completion"),
4136
+ includeUsage: options.includeUsage
3017
4137
  });
3018
- const createEmbeddingModel = (modelId, settings = {}) => new ApertisEmbeddingModel(modelId, settings, {
3019
- provider: "apertis.embedding",
3020
- baseURL,
3021
- headers: getHeaders,
3022
- fetch: fetchImpl
4138
+ const createEmbeddingModel = (modelId) => new OpenAICompatibleEmbeddingModel(modelId, {
4139
+ ...getCommonModelConfig("embedding")
3023
4140
  });
3024
- const provider = Object.assign(
3025
- (modelId, settings) => createChatModel(modelId, settings),
3026
- {
3027
- specificationVersion: "v3",
3028
- chat: createChatModel,
3029
- languageModel: (modelId) => createChatModel(modelId),
3030
- embeddingModel: (modelId) => createEmbeddingModel(modelId),
3031
- textEmbeddingModel: createEmbeddingModel,
3032
- imageModel: () => {
3033
- throw new Error("Image models are not supported by Apertis");
3034
- }
3035
- }
3036
- );
4141
+ const createImageModel = (modelId) => new OpenAICompatibleImageModel(modelId, getCommonModelConfig("image"));
4142
+ const provider = (modelId) => createLanguageModel(modelId);
4143
+ provider.specificationVersion = "v3";
4144
+ provider.languageModel = createLanguageModel;
4145
+ provider.chatModel = createChatModel;
4146
+ provider.completionModel = createCompletionModel;
4147
+ provider.embeddingModel = createEmbeddingModel;
4148
+ provider.textEmbeddingModel = createEmbeddingModel;
4149
+ provider.imageModel = createImageModel;
3037
4150
  return provider;
3038
4151
  }
4152
+
4153
+ // src/apertis-provider.ts
4154
+ function createApertis(options = {}) {
4155
+ return createOpenAICompatible({
4156
+ name: "apertis",
4157
+ baseURL: options.baseURL ?? "https://api.apertis.ai/v1",
4158
+ apiKey: options.apiKey ?? process.env.APERTIS_API_KEY,
4159
+ headers: options.headers,
4160
+ fetch: options.fetch
4161
+ });
4162
+ }
3039
4163
  var apertis = createApertis();
3040
4164
  // Annotate the CommonJS export names for ESM import in node:
3041
4165
  0 && (module.exports = {
3042
4166
  apertis,
3043
- createApertis,
3044
- createApertisV3
4167
+ createApertis
3045
4168
  });
3046
4169
  //# sourceMappingURL=index.cjs.map