@openrouter/ai-sdk-provider 2.6.0 → 2.8.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.mjs CHANGED
@@ -36,7 +36,7 @@ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot
36
36
  var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
37
37
  var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
38
38
 
39
- // node_modules/.pnpm/@ai-sdk+provider@3.0.0/node_modules/@ai-sdk/provider/dist/index.mjs
39
+ // node_modules/.pnpm/@ai-sdk+provider@3.0.8/node_modules/@ai-sdk/provider/dist/index.mjs
40
40
  var marker = "vercel.ai.error";
41
41
  var symbol = Symbol.for(marker);
42
42
  var _a;
@@ -306,34 +306,61 @@ var symbol13 = Symbol.for(marker13);
306
306
  var _a13;
307
307
  var _b13;
308
308
  var TypeValidationError = class _TypeValidationError extends (_b13 = AISDKError, _a13 = symbol13, _b13) {
309
- constructor({ value, cause }) {
309
+ constructor({
310
+ value,
311
+ cause,
312
+ context
313
+ }) {
314
+ let contextPrefix = "Type validation failed";
315
+ if (context == null ? void 0 : context.field) {
316
+ contextPrefix += ` for ${context.field}`;
317
+ }
318
+ if ((context == null ? void 0 : context.entityName) || (context == null ? void 0 : context.entityId)) {
319
+ contextPrefix += " (";
320
+ const parts = [];
321
+ if (context.entityName) {
322
+ parts.push(context.entityName);
323
+ }
324
+ if (context.entityId) {
325
+ parts.push(`id: "${context.entityId}"`);
326
+ }
327
+ contextPrefix += parts.join(", ");
328
+ contextPrefix += ")";
329
+ }
310
330
  super({
311
331
  name: name12,
312
- message: `Type validation failed: Value: ${JSON.stringify(value)}.
332
+ message: `${contextPrefix}: Value: ${JSON.stringify(value)}.
313
333
  Error message: ${getErrorMessage(cause)}`,
314
334
  cause
315
335
  });
316
336
  this[_a13] = true;
317
337
  this.value = value;
338
+ this.context = context;
318
339
  }
319
340
  static isInstance(error) {
320
341
  return AISDKError.hasMarker(error, marker13);
321
342
  }
322
343
  /**
323
344
  * Wraps an error into a TypeValidationError.
324
- * If the cause is already a TypeValidationError with the same value, it returns the cause.
345
+ * If the cause is already a TypeValidationError with the same value and context, it returns the cause.
325
346
  * Otherwise, it creates a new TypeValidationError.
326
347
  *
327
348
  * @param {Object} params - The parameters for wrapping the error.
328
349
  * @param {unknown} params.value - The value that failed validation.
329
350
  * @param {unknown} params.cause - The original error or cause of the validation failure.
351
+ * @param {TypeValidationContext} params.context - Optional context about what is being validated.
330
352
  * @returns {TypeValidationError} A TypeValidationError instance.
331
353
  */
332
354
  static wrap({
333
355
  value,
334
- cause
356
+ cause,
357
+ context
335
358
  }) {
336
- return _TypeValidationError.isInstance(cause) && cause.value === value ? cause : new _TypeValidationError({ value, cause });
359
+ var _a152, _b152, _c;
360
+ 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)) {
361
+ return cause;
362
+ }
363
+ return new _TypeValidationError({ value, cause, context });
337
364
  }
338
365
  };
339
366
  var name13 = "AI_UnsupportedFunctionalityError";
@@ -355,7 +382,7 @@ var UnsupportedFunctionalityError = class extends (_b14 = AISDKError, _a14 = sym
355
382
  }
356
383
  };
357
384
 
358
- // node_modules/.pnpm/@ai-sdk+provider-utils@4.0.1_zod@4.3.5/node_modules/@ai-sdk/provider-utils/dist/index.mjs
385
+ // node_modules/.pnpm/@ai-sdk+provider-utils@4.0.23_zod@4.3.5/node_modules/@ai-sdk/provider-utils/dist/index.mjs
359
386
  import * as z4 from "zod/v4";
360
387
  import { ZodFirstPartyTypeKind as ZodFirstPartyTypeKind3 } from "zod/v3";
361
388
  import { ZodFirstPartyTypeKind } from "zod/v3";
@@ -490,13 +517,41 @@ var EventSourceParserStream = class extends TransformStream {
490
517
  }
491
518
  };
492
519
 
493
- // node_modules/.pnpm/@ai-sdk+provider-utils@4.0.1_zod@4.3.5/node_modules/@ai-sdk/provider-utils/dist/index.mjs
520
+ // node_modules/.pnpm/@ai-sdk+provider-utils@4.0.23_zod@4.3.5/node_modules/@ai-sdk/provider-utils/dist/index.mjs
494
521
  function combineHeaders(...headers) {
495
522
  return headers.reduce(
496
523
  (combinedHeaders, currentHeaders) => __spreadValues(__spreadValues({}, combinedHeaders), currentHeaders != null ? currentHeaders : {}),
497
524
  {}
498
525
  );
499
526
  }
527
+ async function delay(delayInMs, options) {
528
+ if (delayInMs == null) {
529
+ return Promise.resolve();
530
+ }
531
+ const signal = options == null ? void 0 : options.abortSignal;
532
+ return new Promise((resolve2, reject) => {
533
+ if (signal == null ? void 0 : signal.aborted) {
534
+ reject(createAbortError());
535
+ return;
536
+ }
537
+ const timeoutId = setTimeout(() => {
538
+ cleanup();
539
+ resolve2();
540
+ }, delayInMs);
541
+ const cleanup = () => {
542
+ clearTimeout(timeoutId);
543
+ signal == null ? void 0 : signal.removeEventListener("abort", onAbort);
544
+ };
545
+ const onAbort = () => {
546
+ cleanup();
547
+ reject(createAbortError());
548
+ };
549
+ signal == null ? void 0 : signal.addEventListener("abort", onAbort);
550
+ });
551
+ }
552
+ function createAbortError() {
553
+ return new DOMException("Delay was aborted", "AbortError");
554
+ }
500
555
  function extractResponseHeaders(response) {
501
556
  return Object.fromEntries([...response.headers]);
502
557
  }
@@ -531,6 +586,7 @@ var DownloadError = class extends (_b15 = AISDKError, _a15 = symbol15, _b15) {
531
586
  return AISDKError.hasMarker(error, marker15);
532
587
  }
533
588
  };
589
+ var DEFAULT_MAX_DOWNLOAD_SIZE = 2 * 1024 * 1024 * 1024;
534
590
  var createIdGenerator = ({
535
591
  prefix,
536
592
  size = 16,
@@ -562,6 +618,25 @@ function isAbortError(error) {
562
618
  error.name === "TimeoutError");
563
619
  }
564
620
  var FETCH_FAILED_ERROR_MESSAGES = ["fetch failed", "failed to fetch"];
621
+ var BUN_ERROR_CODES = [
622
+ "ConnectionRefused",
623
+ "ConnectionClosed",
624
+ "FailedToOpenSocket",
625
+ "ECONNRESET",
626
+ "ECONNREFUSED",
627
+ "ETIMEDOUT",
628
+ "EPIPE"
629
+ ];
630
+ function isBunNetworkError(error) {
631
+ if (!(error instanceof Error)) {
632
+ return false;
633
+ }
634
+ const code = error.code;
635
+ if (typeof code === "string" && BUN_ERROR_CODES.includes(code)) {
636
+ return true;
637
+ }
638
+ return false;
639
+ }
565
640
  function handleFetchError({
566
641
  error,
567
642
  url,
@@ -583,6 +658,15 @@ function handleFetchError({
583
658
  });
584
659
  }
585
660
  }
661
+ if (isBunNetworkError(error)) {
662
+ return new APICallError({
663
+ message: `Cannot connect to API: ${error.message}`,
664
+ cause: error,
665
+ url,
666
+ requestBodyValues,
667
+ isRetryable: true
668
+ });
669
+ }
586
670
  return error;
587
671
  }
588
672
  function getRuntimeEnvironmentUserAgent(globalThisAny = globalThis) {
@@ -631,7 +715,75 @@ function withUserAgentSuffix(headers, ...userAgentSuffixParts) {
631
715
  );
632
716
  return Object.fromEntries(normalizedHeaders.entries());
633
717
  }
634
- var VERSION = true ? "4.0.1" : "0.0.0-test";
718
+ var VERSION = true ? "4.0.23" : "0.0.0-test";
719
+ var getOriginalFetch = () => globalThis.fetch;
720
+ var getFromApi = async ({
721
+ url,
722
+ headers = {},
723
+ successfulResponseHandler,
724
+ failedResponseHandler,
725
+ abortSignal,
726
+ fetch: fetch2 = getOriginalFetch()
727
+ }) => {
728
+ try {
729
+ const response = await fetch2(url, {
730
+ method: "GET",
731
+ headers: withUserAgentSuffix(
732
+ headers,
733
+ `ai-sdk/provider-utils/${VERSION}`,
734
+ getRuntimeEnvironmentUserAgent()
735
+ ),
736
+ signal: abortSignal
737
+ });
738
+ const responseHeaders = extractResponseHeaders(response);
739
+ if (!response.ok) {
740
+ let errorInformation;
741
+ try {
742
+ errorInformation = await failedResponseHandler({
743
+ response,
744
+ url,
745
+ requestBodyValues: {}
746
+ });
747
+ } catch (error) {
748
+ if (isAbortError(error) || APICallError.isInstance(error)) {
749
+ throw error;
750
+ }
751
+ throw new APICallError({
752
+ message: "Failed to process error response",
753
+ cause: error,
754
+ statusCode: response.status,
755
+ url,
756
+ responseHeaders,
757
+ requestBodyValues: {}
758
+ });
759
+ }
760
+ throw errorInformation.value;
761
+ }
762
+ try {
763
+ return await successfulResponseHandler({
764
+ response,
765
+ url,
766
+ requestBodyValues: {}
767
+ });
768
+ } catch (error) {
769
+ if (error instanceof Error) {
770
+ if (isAbortError(error) || APICallError.isInstance(error)) {
771
+ throw error;
772
+ }
773
+ }
774
+ throw new APICallError({
775
+ message: "Failed to process successful response",
776
+ cause: error,
777
+ statusCode: response.status,
778
+ url,
779
+ responseHeaders,
780
+ requestBodyValues: {}
781
+ });
782
+ }
783
+ } catch (error) {
784
+ throw handleFetchError({ error, url, requestBodyValues: {} });
785
+ }
786
+ };
635
787
  function loadApiKey({
636
788
  apiKey,
637
789
  environmentVariableName,
@@ -648,7 +800,7 @@ function loadApiKey({
648
800
  }
649
801
  if (typeof process === "undefined") {
650
802
  throw new LoadAPIKeyError({
651
- message: `${description} API key is missing. Pass it using the '${apiKeyParameterName}' parameter. Environment variables is not supported in this environment.`
803
+ message: `${description} API key is missing. Pass it using the '${apiKeyParameterName}' parameter. Environment variables are not supported in this environment.`
652
804
  });
653
805
  }
654
806
  apiKey = process.env[environmentVariableName];
@@ -664,8 +816,8 @@ function loadApiKey({
664
816
  }
665
817
  return apiKey;
666
818
  }
667
- var suspectProtoRx = /"__proto__"\s*:/;
668
- var suspectConstructorRx = /"constructor"\s*:/;
819
+ var suspectProtoRx = /"(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])"\s*:/;
820
+ 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*:/;
669
821
  function _parse(text) {
670
822
  const obj = JSON.parse(text);
671
823
  if (obj === null || typeof obj !== "object") {
@@ -685,7 +837,7 @@ function filter(obj) {
685
837
  if (Object.prototype.hasOwnProperty.call(node, "__proto__")) {
686
838
  throw new SyntaxError("Object contains forbidden prototype property");
687
839
  }
688
- if (Object.prototype.hasOwnProperty.call(node, "constructor") && Object.prototype.hasOwnProperty.call(node.constructor, "prototype")) {
840
+ if (Object.prototype.hasOwnProperty.call(node, "constructor") && node.constructor !== null && typeof node.constructor === "object" && Object.prototype.hasOwnProperty.call(node.constructor, "prototype")) {
689
841
  throw new SyntaxError("Object contains forbidden prototype property");
690
842
  }
691
843
  for (const key in node) {
@@ -712,31 +864,40 @@ function secureJsonParse(text) {
712
864
  }
713
865
  }
714
866
  function addAdditionalPropertiesToJsonSchema(jsonSchema2) {
715
- if (jsonSchema2.type === "object") {
867
+ if (jsonSchema2.type === "object" || Array.isArray(jsonSchema2.type) && jsonSchema2.type.includes("object")) {
716
868
  jsonSchema2.additionalProperties = false;
717
- const properties = jsonSchema2.properties;
869
+ const { properties } = jsonSchema2;
718
870
  if (properties != null) {
719
- for (const property in properties) {
720
- properties[property] = addAdditionalPropertiesToJsonSchema(
721
- properties[property]
722
- );
871
+ for (const key of Object.keys(properties)) {
872
+ properties[key] = visit(properties[key]);
723
873
  }
724
874
  }
725
875
  }
726
- if (jsonSchema2.type === "array" && jsonSchema2.items != null) {
727
- if (Array.isArray(jsonSchema2.items)) {
728
- jsonSchema2.items = jsonSchema2.items.map(
729
- (item) => addAdditionalPropertiesToJsonSchema(item)
730
- );
731
- } else {
732
- jsonSchema2.items = addAdditionalPropertiesToJsonSchema(
733
- jsonSchema2.items
734
- );
876
+ if (jsonSchema2.items != null) {
877
+ jsonSchema2.items = Array.isArray(jsonSchema2.items) ? jsonSchema2.items.map(visit) : visit(jsonSchema2.items);
878
+ }
879
+ if (jsonSchema2.anyOf != null) {
880
+ jsonSchema2.anyOf = jsonSchema2.anyOf.map(visit);
881
+ }
882
+ if (jsonSchema2.allOf != null) {
883
+ jsonSchema2.allOf = jsonSchema2.allOf.map(visit);
884
+ }
885
+ if (jsonSchema2.oneOf != null) {
886
+ jsonSchema2.oneOf = jsonSchema2.oneOf.map(visit);
887
+ }
888
+ const { definitions } = jsonSchema2;
889
+ if (definitions != null) {
890
+ for (const key of Object.keys(definitions)) {
891
+ definitions[key] = visit(definitions[key]);
735
892
  }
736
893
  }
737
894
  return jsonSchema2;
738
895
  }
739
- var ignoreOverride = Symbol(
896
+ function visit(def) {
897
+ if (typeof def === "boolean") return def;
898
+ return addAdditionalPropertiesToJsonSchema(def);
899
+ }
900
+ var ignoreOverride = /* @__PURE__ */ Symbol(
740
901
  "Let zodToJsonSchema decide on which parser to use"
741
902
  );
742
903
  var defaultOptions = {
@@ -1802,7 +1963,7 @@ var zod3ToJsonSchema = (schema, options) => {
1802
1963
  combined.$schema = "http://json-schema.org/draft-07/schema#";
1803
1964
  return combined;
1804
1965
  };
1805
- var schemaSymbol = Symbol.for("vercel.ai.schema");
1966
+ var schemaSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.schema");
1806
1967
  function jsonSchema(jsonSchema2, {
1807
1968
  validate
1808
1969
  } = {}) {
@@ -1827,9 +1988,11 @@ function asSchema(schema) {
1827
1988
  }
1828
1989
  function standardSchema(standardSchema2) {
1829
1990
  return jsonSchema(
1830
- () => standardSchema2["~standard"].jsonSchema.input({
1831
- target: "draft-07"
1832
- }),
1991
+ () => addAdditionalPropertiesToJsonSchema(
1992
+ standardSchema2["~standard"].jsonSchema.input({
1993
+ target: "draft-07"
1994
+ })
1995
+ ),
1833
1996
  {
1834
1997
  validate: async (value) => {
1835
1998
  const result = await standardSchema2["~standard"].validate(value);
@@ -1892,17 +2055,19 @@ function zodSchema(zodSchema2, options) {
1892
2055
  }
1893
2056
  async function validateTypes({
1894
2057
  value,
1895
- schema
2058
+ schema,
2059
+ context
1896
2060
  }) {
1897
- const result = await safeValidateTypes({ value, schema });
2061
+ const result = await safeValidateTypes({ value, schema, context });
1898
2062
  if (!result.success) {
1899
- throw TypeValidationError.wrap({ value, cause: result.error });
2063
+ throw TypeValidationError.wrap({ value, cause: result.error, context });
1900
2064
  }
1901
2065
  return result.value;
1902
2066
  }
1903
2067
  async function safeValidateTypes({
1904
2068
  value,
1905
- schema
2069
+ schema,
2070
+ context
1906
2071
  }) {
1907
2072
  const actualSchema = asSchema(schema);
1908
2073
  try {
@@ -1915,13 +2080,13 @@ async function safeValidateTypes({
1915
2080
  }
1916
2081
  return {
1917
2082
  success: false,
1918
- error: TypeValidationError.wrap({ value, cause: result.error }),
2083
+ error: TypeValidationError.wrap({ value, cause: result.error, context }),
1919
2084
  rawValue: value
1920
2085
  };
1921
2086
  } catch (error) {
1922
2087
  return {
1923
2088
  success: false,
1924
- error: TypeValidationError.wrap({ value, cause: error }),
2089
+ error: TypeValidationError.wrap({ value, cause: error, context }),
1925
2090
  rawValue: value
1926
2091
  };
1927
2092
  }
@@ -3352,7 +3517,7 @@ var OpenRouterChatLanguageModel = class {
3352
3517
  tools,
3353
3518
  toolChoice
3354
3519
  }) {
3355
- var _a16;
3520
+ var _a16, _b16;
3356
3521
  const baseArgs = __spreadValues(__spreadValues({
3357
3522
  // model id:
3358
3523
  model: this.modelId,
@@ -3363,12 +3528,12 @@ var OpenRouterChatLanguageModel = class {
3363
3528
  top_logprobs: typeof this.settings.logprobs === "number" ? this.settings.logprobs : typeof this.settings.logprobs === "boolean" ? this.settings.logprobs ? 0 : void 0 : void 0,
3364
3529
  user: this.settings.user,
3365
3530
  parallel_tool_calls: this.settings.parallelToolCalls,
3366
- // standardized settings:
3367
- max_tokens: maxOutputTokens,
3368
- temperature,
3369
- top_p: topP,
3370
- frequency_penalty: frequencyPenalty,
3371
- presence_penalty: presencePenalty,
3531
+ // standardized settings (call-level options override model-level settings):
3532
+ max_tokens: maxOutputTokens != null ? maxOutputTokens : this.settings.maxTokens,
3533
+ temperature: temperature != null ? temperature : this.settings.temperature,
3534
+ top_p: topP != null ? topP : this.settings.topP,
3535
+ frequency_penalty: frequencyPenalty != null ? frequencyPenalty : this.settings.frequencyPenalty,
3536
+ presence_penalty: presencePenalty != null ? presencePenalty : this.settings.presencePenalty,
3372
3537
  seed,
3373
3538
  stop: stopSequences,
3374
3539
  response_format: (responseFormat == null ? void 0 : responseFormat.type) === "json" ? responseFormat.schema != null ? {
@@ -3381,7 +3546,7 @@ var OpenRouterChatLanguageModel = class {
3381
3546
  description: responseFormat.description
3382
3547
  })
3383
3548
  } : { type: "json_object" } : void 0,
3384
- top_k: topK,
3549
+ top_k: topK != null ? topK : this.settings.topK,
3385
3550
  // messages:
3386
3551
  messages: convertToOpenRouterChatMessages(prompt),
3387
3552
  // OpenRouter specific settings:
@@ -3402,14 +3567,18 @@ var OpenRouterChatLanguageModel = class {
3402
3567
  const mappedTools = [];
3403
3568
  for (const tool2 of tools) {
3404
3569
  if (tool2.type === "function") {
3405
- mappedTools.push({
3570
+ const openrouterOptions = (_b16 = tool2.providerOptions) == null ? void 0 : _b16.openrouter;
3571
+ const eagerInputStreaming = openrouterOptions == null ? void 0 : openrouterOptions.eager_input_streaming;
3572
+ mappedTools.push(__spreadValues({
3406
3573
  type: "function",
3407
3574
  function: {
3408
3575
  name: tool2.name,
3409
3576
  description: tool2.description,
3410
3577
  parameters: tool2.inputSchema
3411
3578
  }
3412
- });
3579
+ }, eagerInputStreaming != null && {
3580
+ eager_input_streaming: eagerInputStreaming
3581
+ }));
3413
3582
  } else if (tool2.type === "provider") {
3414
3583
  mappedTools.push(mapProviderTool(tool2));
3415
3584
  }
@@ -3747,18 +3916,16 @@ var OpenRouterChatLanguageModel = class {
3747
3916
  return;
3748
3917
  }
3749
3918
  const delta = choice.delta;
3750
- const emitReasoningChunk = (chunkText, providerMetadata) => {
3919
+ const emitReasoningChunk = (chunkText) => {
3751
3920
  if (!reasoningStarted) {
3752
3921
  reasoningId = generateId();
3753
3922
  controller.enqueue({
3754
- providerMetadata,
3755
3923
  type: "reasoning-start",
3756
3924
  id: reasoningId
3757
3925
  });
3758
3926
  reasoningStarted = true;
3759
3927
  }
3760
3928
  controller.enqueue({
3761
- providerMetadata,
3762
3929
  type: "reasoning-delta",
3763
3930
  delta: chunkText,
3764
3931
  id: reasoningId || generateId()
@@ -3780,15 +3947,10 @@ var OpenRouterChatLanguageModel = class {
3780
3947
  }
3781
3948
  }
3782
3949
  if (!textStarted) {
3783
- const reasoningMetadata = {
3784
- openrouter: {
3785
- reasoning_details: accumulatedReasoningDetails.map((d) => __spreadValues({}, d))
3786
- }
3787
- };
3788
3950
  for (const detail of delta.reasoning_details) {
3789
3951
  switch (detail.type) {
3790
3952
  case "reasoning.text" /* Text */: {
3791
- emitReasoningChunk(detail.text || "", reasoningMetadata);
3953
+ emitReasoningChunk(detail.text || "");
3792
3954
  break;
3793
3955
  }
3794
3956
  case "reasoning.encrypted" /* Encrypted */: {
@@ -3796,7 +3958,7 @@ var OpenRouterChatLanguageModel = class {
3796
3958
  }
3797
3959
  case "reasoning.summary" /* Summary */: {
3798
3960
  if (detail.summary) {
3799
- emitReasoningChunk(detail.summary, reasoningMetadata);
3961
+ emitReasoningChunk(detail.summary);
3800
3962
  }
3801
3963
  break;
3802
3964
  }
@@ -4085,6 +4247,12 @@ var OpenRouterChatLanguageModel = class {
4085
4247
  if (accumulatedFileAnnotations.length > 0) {
4086
4248
  openrouterMetadata.annotations = accumulatedFileAnnotations;
4087
4249
  }
4250
+ if (usage.inputTokens.total === void 0 && openrouterUsage.promptTokens !== void 0) {
4251
+ usage.inputTokens.total = openrouterUsage.promptTokens;
4252
+ }
4253
+ if (usage.outputTokens.total === void 0 && openrouterUsage.completionTokens !== void 0) {
4254
+ usage.outputTokens.total = openrouterUsage.completionTokens;
4255
+ }
4088
4256
  usage.raw = rawUsage;
4089
4257
  controller.enqueue({
4090
4258
  type: "finish",
@@ -4320,16 +4488,16 @@ var OpenRouterCompletionLanguageModel = class {
4320
4488
  logprobs: typeof this.settings.logprobs === "number" ? this.settings.logprobs : typeof this.settings.logprobs === "boolean" ? this.settings.logprobs ? 0 : void 0 : void 0,
4321
4489
  suffix: this.settings.suffix,
4322
4490
  user: this.settings.user,
4323
- // standardized settings:
4324
- max_tokens: maxOutputTokens,
4325
- temperature,
4326
- top_p: topP,
4327
- frequency_penalty: frequencyPenalty,
4328
- presence_penalty: presencePenalty,
4491
+ // standardized settings (call-level options override model-level settings):
4492
+ max_tokens: maxOutputTokens != null ? maxOutputTokens : this.settings.maxTokens,
4493
+ temperature: temperature != null ? temperature : this.settings.temperature,
4494
+ top_p: topP != null ? topP : this.settings.topP,
4495
+ frequency_penalty: frequencyPenalty != null ? frequencyPenalty : this.settings.frequencyPenalty,
4496
+ presence_penalty: presencePenalty != null ? presencePenalty : this.settings.presencePenalty,
4329
4497
  seed,
4330
4498
  stop: stopSequences,
4331
4499
  response_format: responseFormat,
4332
- top_k: topK,
4500
+ top_k: topK != null ? topK : this.settings.topK,
4333
4501
  // prompt:
4334
4502
  prompt: completionPrompt,
4335
4503
  // OpenRouter specific settings:
@@ -4899,7 +5067,199 @@ function withUserAgentSuffix2(headers, ...userAgentSuffixParts) {
4899
5067
  }
4900
5068
 
4901
5069
  // src/version.ts
4902
- var VERSION2 = false ? "0.0.0-test" : "2.6.0";
5070
+ var VERSION2 = false ? "0.0.0-test" : "2.8.0";
5071
+
5072
+ // src/video/schemas.ts
5073
+ import { z as z12 } from "zod/v4";
5074
+ var VideoGenerationSubmitResponseSchema = z12.object({
5075
+ id: z12.string(),
5076
+ generation_id: z12.string().optional(),
5077
+ polling_url: z12.string(),
5078
+ status: z12.string()
5079
+ }).passthrough();
5080
+ var VideoGenerationPollResponseSchema = z12.object({
5081
+ id: z12.string(),
5082
+ generation_id: z12.string().optional(),
5083
+ polling_url: z12.string(),
5084
+ status: z12.string(),
5085
+ unsigned_urls: z12.array(z12.string()).optional(),
5086
+ usage: z12.object({
5087
+ cost: z12.number().optional(),
5088
+ is_byok: z12.boolean().optional()
5089
+ }).passthrough().optional(),
5090
+ error: z12.string().optional()
5091
+ }).passthrough();
5092
+
5093
+ // src/video/index.ts
5094
+ var DEFAULT_POLL_INTERVAL_MS = 2e3;
5095
+ var DEFAULT_MAX_POLL_TIME_MS = 6e5;
5096
+ var OpenRouterVideoModel = class {
5097
+ constructor(modelId, settings, config) {
5098
+ this.specificationVersion = "v3";
5099
+ this.provider = "openrouter";
5100
+ this.maxVideosPerCall = 1;
5101
+ this.modelId = modelId;
5102
+ this.settings = settings;
5103
+ this.config = config;
5104
+ }
5105
+ async doGenerate(options) {
5106
+ var _a16, _b16, _c, _d, _e;
5107
+ const {
5108
+ prompt,
5109
+ n,
5110
+ aspectRatio,
5111
+ resolution,
5112
+ duration,
5113
+ seed,
5114
+ image,
5115
+ abortSignal,
5116
+ headers,
5117
+ providerOptions
5118
+ } = options;
5119
+ const warnings = [];
5120
+ if (n > 1) {
5121
+ warnings.push({
5122
+ type: "unsupported",
5123
+ feature: "n > 1",
5124
+ details: `OpenRouter video generation returns 1 video per call. Requested ${n} videos.`
5125
+ });
5126
+ }
5127
+ const body = __spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues({
5128
+ model: this.modelId,
5129
+ prompt: prompt != null ? prompt : ""
5130
+ }, aspectRatio !== void 0 && { aspect_ratio: aspectRatio }), resolution !== void 0 && { size: resolution }), duration !== void 0 && { duration }), seed !== void 0 && { seed }), this.settings.generateAudio !== void 0 && {
5131
+ generate_audio: this.settings.generateAudio
5132
+ }), image !== void 0 && {
5133
+ frame_images: [convertImageToFrameImage(image)]
5134
+ }), this.config.extraBody), this.settings.extraBody), providerOptions.openrouter);
5135
+ const mergedHeaders = combineHeaders(this.config.headers(), headers);
5136
+ const { value: submitResponse, responseHeaders } = await postJsonToApi({
5137
+ url: this.config.url({
5138
+ path: "/videos",
5139
+ modelId: this.modelId
5140
+ }),
5141
+ headers: mergedHeaders,
5142
+ body,
5143
+ failedResponseHandler: openrouterFailedResponseHandler,
5144
+ successfulResponseHandler: createJsonResponseHandler(
5145
+ VideoGenerationSubmitResponseSchema
5146
+ ),
5147
+ abortSignal,
5148
+ fetch: this.config.fetch
5149
+ });
5150
+ const pollIntervalMs = (_a16 = this.settings.pollIntervalMs) != null ? _a16 : DEFAULT_POLL_INTERVAL_MS;
5151
+ const maxPollTimeMs = (_b16 = this.settings.maxPollTimeMs) != null ? _b16 : DEFAULT_MAX_POLL_TIME_MS;
5152
+ const pollResult = await this.pollUntilComplete({
5153
+ jobId: submitResponse.id,
5154
+ headers: mergedHeaders,
5155
+ abortSignal,
5156
+ pollIntervalMs,
5157
+ maxPollTimeMs
5158
+ });
5159
+ const videos = [];
5160
+ if (pollResult.unsigned_urls) {
5161
+ for (const url of pollResult.unsigned_urls) {
5162
+ videos.push({
5163
+ type: "url",
5164
+ url,
5165
+ mediaType: "video/mp4"
5166
+ });
5167
+ }
5168
+ }
5169
+ const providerMetadata = {
5170
+ openrouter: {
5171
+ generationId: (_c = pollResult.generation_id) != null ? _c : null,
5172
+ cost: (_e = (_d = pollResult.usage) == null ? void 0 : _d.cost) != null ? _e : null
5173
+ }
5174
+ };
5175
+ return {
5176
+ videos,
5177
+ warnings,
5178
+ providerMetadata,
5179
+ response: {
5180
+ timestamp: /* @__PURE__ */ new Date(),
5181
+ modelId: this.modelId,
5182
+ headers: responseHeaders
5183
+ }
5184
+ };
5185
+ }
5186
+ async pollUntilComplete({
5187
+ jobId,
5188
+ headers,
5189
+ abortSignal,
5190
+ pollIntervalMs,
5191
+ maxPollTimeMs
5192
+ }) {
5193
+ var _a16;
5194
+ const startTime = Date.now();
5195
+ while (Date.now() - startTime < maxPollTimeMs) {
5196
+ abortSignal == null ? void 0 : abortSignal.throwIfAborted();
5197
+ await delay(pollIntervalMs);
5198
+ abortSignal == null ? void 0 : abortSignal.throwIfAborted();
5199
+ const { value: pollResponse } = await getFromApi({
5200
+ url: this.config.url({
5201
+ path: `/videos/${jobId}`,
5202
+ modelId: this.modelId
5203
+ }),
5204
+ headers,
5205
+ failedResponseHandler: openrouterFailedResponseHandler,
5206
+ successfulResponseHandler: createJsonResponseHandler(
5207
+ VideoGenerationPollResponseSchema
5208
+ ),
5209
+ abortSignal,
5210
+ fetch: this.config.fetch
5211
+ });
5212
+ if (pollResponse.status === "completed") {
5213
+ return {
5214
+ generation_id: pollResponse.generation_id,
5215
+ unsigned_urls: pollResponse.unsigned_urls,
5216
+ usage: pollResponse.usage
5217
+ };
5218
+ }
5219
+ if (pollResponse.status === "failed" || pollResponse.status === "dead" || pollResponse.status === "cancelled" || pollResponse.status === "expired") {
5220
+ throw new APICallError({
5221
+ message: (_a16 = pollResponse.error) != null ? _a16 : `Video generation failed with status: ${pollResponse.status}`,
5222
+ url: this.config.url({
5223
+ path: `/videos/${jobId}`,
5224
+ modelId: this.modelId
5225
+ }),
5226
+ requestBodyValues: {},
5227
+ statusCode: 500,
5228
+ isRetryable: false
5229
+ });
5230
+ }
5231
+ }
5232
+ throw new APICallError({
5233
+ message: `Video generation timed out after ${maxPollTimeMs}ms`,
5234
+ url: this.config.url({
5235
+ path: `/videos/${jobId}`,
5236
+ modelId: this.modelId
5237
+ }),
5238
+ requestBodyValues: {},
5239
+ statusCode: 408,
5240
+ isRetryable: true
5241
+ });
5242
+ }
5243
+ };
5244
+ function convertImageToFrameImage(file) {
5245
+ if (file.type === "url") {
5246
+ return {
5247
+ type: "image_url",
5248
+ image_url: { url: file.url },
5249
+ frame_type: "first_frame"
5250
+ };
5251
+ }
5252
+ const url = buildFileDataUrl({
5253
+ data: file.data,
5254
+ mediaType: file.mediaType,
5255
+ defaultMediaType: "image/png"
5256
+ });
5257
+ return {
5258
+ type: "image_url",
5259
+ image_url: { url },
5260
+ frame_type: "first_frame"
5261
+ };
5262
+ }
4903
5263
 
4904
5264
  // src/provider.ts
4905
5265
  function createOpenRouter(options = {}) {
@@ -4948,6 +5308,13 @@ function createOpenRouter(options = {}) {
4948
5308
  fetch: options.fetch,
4949
5309
  extraBody: options.extraBody
4950
5310
  });
5311
+ const createVideoModel = (modelId, settings = {}) => new OpenRouterVideoModel(modelId, settings, {
5312
+ provider: "openrouter.video",
5313
+ url: ({ path }) => `${baseURL}${path}`,
5314
+ headers: getHeaders,
5315
+ fetch: options.fetch,
5316
+ extraBody: options.extraBody
5317
+ });
4951
5318
  const createLanguageModel = (modelId, settings) => {
4952
5319
  if (new.target) {
4953
5320
  throw new Error(
@@ -4969,6 +5336,7 @@ function createOpenRouter(options = {}) {
4969
5336
  provider.textEmbeddingModel = createEmbeddingModel;
4970
5337
  provider.embedding = createEmbeddingModel;
4971
5338
  provider.imageModel = createImageModel;
5339
+ provider.videoModel = createVideoModel;
4972
5340
  provider.tools = {
4973
5341
  webSearch
4974
5342
  };