@openrouter/ai-sdk-provider 2.7.0 → 2.8.1

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
  }
@@ -2855,9 +3020,9 @@ function convertToOpenRouterChatMessages(prompt) {
2855
3020
  const parsedProviderOptions = OpenRouterProviderOptionsSchema.safeParse(providerOptions);
2856
3021
  const messageReasoningDetails = parsedProviderOptions.success ? (_e = (_d = parsedProviderOptions.data) == null ? void 0 : _d.openrouter) == null ? void 0 : _e.reasoning_details : void 0;
2857
3022
  const messageAnnotations = parsedProviderOptions.success ? (_g = (_f = parsedProviderOptions.data) == null ? void 0 : _f.openrouter) == null ? void 0 : _g.annotations : void 0;
2858
- const candidateReasoningDetails = messageReasoningDetails && Array.isArray(messageReasoningDetails) && messageReasoningDetails.length > 0 ? messageReasoningDetails : findFirstReasoningDetails(content);
3023
+ const candidateReasoningDetails = messageReasoningDetails && Array.isArray(messageReasoningDetails) ? messageReasoningDetails : findFirstReasoningDetails(content);
2859
3024
  let finalReasoningDetails;
2860
- if (candidateReasoningDetails && candidateReasoningDetails.length > 0) {
3025
+ if (candidateReasoningDetails) {
2861
3026
  const validDetails = candidateReasoningDetails.filter((detail) => {
2862
3027
  var _a17;
2863
3028
  if (detail.type !== "reasoning.text" /* Text */) {
@@ -2883,9 +3048,9 @@ function convertToOpenRouterChatMessages(prompt) {
2883
3048
  uniqueDetails.push(detail);
2884
3049
  }
2885
3050
  }
2886
- finalReasoningDetails = uniqueDetails.length > 0 ? uniqueDetails : void 0;
3051
+ finalReasoningDetails = uniqueDetails;
2887
3052
  }
2888
- const effectiveReasoning = reasoning && finalReasoningDetails ? reasoning : void 0;
3053
+ const effectiveReasoning = reasoning && finalReasoningDetails && finalReasoningDetails.length > 0 ? reasoning : void 0;
2889
3054
  messages.push({
2890
3055
  role: "assistant",
2891
3056
  content: text,
@@ -3812,15 +3977,17 @@ var OpenRouterChatLanguageModel = class {
3812
3977
  controller.enqueue({
3813
3978
  type: "reasoning-end",
3814
3979
  id: reasoningId || generateId(),
3815
- // Include accumulated reasoning_details so the AI SDK can update
3816
- // the reasoning part's providerMetadata with the correct signature.
3817
- // The signature typically arrives in the last reasoning delta,
3980
+ // Always include accumulated reasoning_details so the AI SDK can
3981
+ // update the reasoning part's providerMetadata with the correct
3982
+ // signature. The signature typically arrives in the last delta,
3818
3983
  // but reasoning-start only carries the first delta's metadata.
3819
- providerMetadata: accumulatedReasoningDetails.length > 0 ? {
3984
+ // An empty array is intentional — it signals the provider produced
3985
+ // no reasoning tokens this turn (e.g. DeepSeek V4).
3986
+ providerMetadata: {
3820
3987
  openrouter: {
3821
3988
  reasoning_details: accumulatedReasoningDetails
3822
3989
  }
3823
- } : void 0
3990
+ }
3824
3991
  });
3825
3992
  reasoningStarted = false;
3826
3993
  }
@@ -4055,13 +4222,14 @@ var OpenRouterChatLanguageModel = class {
4055
4222
  controller.enqueue({
4056
4223
  type: "reasoning-end",
4057
4224
  id: reasoningId || generateId(),
4058
- // Include accumulated reasoning_details so the AI SDK can update
4059
- // the reasoning part's providerMetadata with the correct signature.
4060
- providerMetadata: accumulatedReasoningDetails.length > 0 ? {
4225
+ // Always include accumulated reasoning_details so the AI SDK can
4226
+ // update the reasoning part's providerMetadata. An empty array is
4227
+ // intentional it signals the provider produced no reasoning tokens.
4228
+ providerMetadata: {
4061
4229
  openrouter: {
4062
4230
  reasoning_details: accumulatedReasoningDetails
4063
4231
  }
4064
- } : void 0
4232
+ }
4065
4233
  });
4066
4234
  }
4067
4235
  if (textStarted) {
@@ -4076,9 +4244,7 @@ var OpenRouterChatLanguageModel = class {
4076
4244
  if (provider !== void 0) {
4077
4245
  openrouterMetadata.provider = provider;
4078
4246
  }
4079
- if (accumulatedReasoningDetails.length > 0) {
4080
- openrouterMetadata.reasoning_details = accumulatedReasoningDetails;
4081
- }
4247
+ openrouterMetadata.reasoning_details = accumulatedReasoningDetails;
4082
4248
  if (accumulatedFileAnnotations.length > 0) {
4083
4249
  openrouterMetadata.annotations = accumulatedFileAnnotations;
4084
4250
  }
@@ -4902,7 +5068,199 @@ function withUserAgentSuffix2(headers, ...userAgentSuffixParts) {
4902
5068
  }
4903
5069
 
4904
5070
  // src/version.ts
4905
- var VERSION2 = false ? "0.0.0-test" : "2.7.0";
5071
+ var VERSION2 = false ? "0.0.0-test" : "2.8.1";
5072
+
5073
+ // src/video/schemas.ts
5074
+ import { z as z12 } from "zod/v4";
5075
+ var VideoGenerationSubmitResponseSchema = z12.object({
5076
+ id: z12.string(),
5077
+ generation_id: z12.string().optional(),
5078
+ polling_url: z12.string(),
5079
+ status: z12.string()
5080
+ }).passthrough();
5081
+ var VideoGenerationPollResponseSchema = z12.object({
5082
+ id: z12.string(),
5083
+ generation_id: z12.string().optional(),
5084
+ polling_url: z12.string(),
5085
+ status: z12.string(),
5086
+ unsigned_urls: z12.array(z12.string()).optional(),
5087
+ usage: z12.object({
5088
+ cost: z12.number().optional(),
5089
+ is_byok: z12.boolean().optional()
5090
+ }).passthrough().optional(),
5091
+ error: z12.string().optional()
5092
+ }).passthrough();
5093
+
5094
+ // src/video/index.ts
5095
+ var DEFAULT_POLL_INTERVAL_MS = 2e3;
5096
+ var DEFAULT_MAX_POLL_TIME_MS = 6e5;
5097
+ var OpenRouterVideoModel = class {
5098
+ constructor(modelId, settings, config) {
5099
+ this.specificationVersion = "v3";
5100
+ this.provider = "openrouter";
5101
+ this.maxVideosPerCall = 1;
5102
+ this.modelId = modelId;
5103
+ this.settings = settings;
5104
+ this.config = config;
5105
+ }
5106
+ async doGenerate(options) {
5107
+ var _a16, _b16, _c, _d, _e;
5108
+ const {
5109
+ prompt,
5110
+ n,
5111
+ aspectRatio,
5112
+ resolution,
5113
+ duration,
5114
+ seed,
5115
+ image,
5116
+ abortSignal,
5117
+ headers,
5118
+ providerOptions
5119
+ } = options;
5120
+ const warnings = [];
5121
+ if (n > 1) {
5122
+ warnings.push({
5123
+ type: "unsupported",
5124
+ feature: "n > 1",
5125
+ details: `OpenRouter video generation returns 1 video per call. Requested ${n} videos.`
5126
+ });
5127
+ }
5128
+ const body = __spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues(__spreadValues({
5129
+ model: this.modelId,
5130
+ prompt: prompt != null ? prompt : ""
5131
+ }, aspectRatio !== void 0 && { aspect_ratio: aspectRatio }), resolution !== void 0 && { size: resolution }), duration !== void 0 && { duration }), seed !== void 0 && { seed }), this.settings.generateAudio !== void 0 && {
5132
+ generate_audio: this.settings.generateAudio
5133
+ }), image !== void 0 && {
5134
+ frame_images: [convertImageToFrameImage(image)]
5135
+ }), this.config.extraBody), this.settings.extraBody), providerOptions.openrouter);
5136
+ const mergedHeaders = combineHeaders(this.config.headers(), headers);
5137
+ const { value: submitResponse, responseHeaders } = await postJsonToApi({
5138
+ url: this.config.url({
5139
+ path: "/videos",
5140
+ modelId: this.modelId
5141
+ }),
5142
+ headers: mergedHeaders,
5143
+ body,
5144
+ failedResponseHandler: openrouterFailedResponseHandler,
5145
+ successfulResponseHandler: createJsonResponseHandler(
5146
+ VideoGenerationSubmitResponseSchema
5147
+ ),
5148
+ abortSignal,
5149
+ fetch: this.config.fetch
5150
+ });
5151
+ const pollIntervalMs = (_a16 = this.settings.pollIntervalMs) != null ? _a16 : DEFAULT_POLL_INTERVAL_MS;
5152
+ const maxPollTimeMs = (_b16 = this.settings.maxPollTimeMs) != null ? _b16 : DEFAULT_MAX_POLL_TIME_MS;
5153
+ const pollResult = await this.pollUntilComplete({
5154
+ jobId: submitResponse.id,
5155
+ headers: mergedHeaders,
5156
+ abortSignal,
5157
+ pollIntervalMs,
5158
+ maxPollTimeMs
5159
+ });
5160
+ const videos = [];
5161
+ if (pollResult.unsigned_urls) {
5162
+ for (const url of pollResult.unsigned_urls) {
5163
+ videos.push({
5164
+ type: "url",
5165
+ url,
5166
+ mediaType: "video/mp4"
5167
+ });
5168
+ }
5169
+ }
5170
+ const providerMetadata = {
5171
+ openrouter: {
5172
+ generationId: (_c = pollResult.generation_id) != null ? _c : null,
5173
+ cost: (_e = (_d = pollResult.usage) == null ? void 0 : _d.cost) != null ? _e : null
5174
+ }
5175
+ };
5176
+ return {
5177
+ videos,
5178
+ warnings,
5179
+ providerMetadata,
5180
+ response: {
5181
+ timestamp: /* @__PURE__ */ new Date(),
5182
+ modelId: this.modelId,
5183
+ headers: responseHeaders
5184
+ }
5185
+ };
5186
+ }
5187
+ async pollUntilComplete({
5188
+ jobId,
5189
+ headers,
5190
+ abortSignal,
5191
+ pollIntervalMs,
5192
+ maxPollTimeMs
5193
+ }) {
5194
+ var _a16;
5195
+ const startTime = Date.now();
5196
+ while (Date.now() - startTime < maxPollTimeMs) {
5197
+ abortSignal == null ? void 0 : abortSignal.throwIfAborted();
5198
+ await delay(pollIntervalMs);
5199
+ abortSignal == null ? void 0 : abortSignal.throwIfAborted();
5200
+ const { value: pollResponse } = await getFromApi({
5201
+ url: this.config.url({
5202
+ path: `/videos/${jobId}`,
5203
+ modelId: this.modelId
5204
+ }),
5205
+ headers,
5206
+ failedResponseHandler: openrouterFailedResponseHandler,
5207
+ successfulResponseHandler: createJsonResponseHandler(
5208
+ VideoGenerationPollResponseSchema
5209
+ ),
5210
+ abortSignal,
5211
+ fetch: this.config.fetch
5212
+ });
5213
+ if (pollResponse.status === "completed") {
5214
+ return {
5215
+ generation_id: pollResponse.generation_id,
5216
+ unsigned_urls: pollResponse.unsigned_urls,
5217
+ usage: pollResponse.usage
5218
+ };
5219
+ }
5220
+ if (pollResponse.status === "failed" || pollResponse.status === "dead" || pollResponse.status === "cancelled" || pollResponse.status === "expired") {
5221
+ throw new APICallError({
5222
+ message: (_a16 = pollResponse.error) != null ? _a16 : `Video generation failed with status: ${pollResponse.status}`,
5223
+ url: this.config.url({
5224
+ path: `/videos/${jobId}`,
5225
+ modelId: this.modelId
5226
+ }),
5227
+ requestBodyValues: {},
5228
+ statusCode: 500,
5229
+ isRetryable: false
5230
+ });
5231
+ }
5232
+ }
5233
+ throw new APICallError({
5234
+ message: `Video generation timed out after ${maxPollTimeMs}ms`,
5235
+ url: this.config.url({
5236
+ path: `/videos/${jobId}`,
5237
+ modelId: this.modelId
5238
+ }),
5239
+ requestBodyValues: {},
5240
+ statusCode: 408,
5241
+ isRetryable: true
5242
+ });
5243
+ }
5244
+ };
5245
+ function convertImageToFrameImage(file) {
5246
+ if (file.type === "url") {
5247
+ return {
5248
+ type: "image_url",
5249
+ image_url: { url: file.url },
5250
+ frame_type: "first_frame"
5251
+ };
5252
+ }
5253
+ const url = buildFileDataUrl({
5254
+ data: file.data,
5255
+ mediaType: file.mediaType,
5256
+ defaultMediaType: "image/png"
5257
+ });
5258
+ return {
5259
+ type: "image_url",
5260
+ image_url: { url },
5261
+ frame_type: "first_frame"
5262
+ };
5263
+ }
4906
5264
 
4907
5265
  // src/provider.ts
4908
5266
  function createOpenRouter(options = {}) {
@@ -4951,6 +5309,13 @@ function createOpenRouter(options = {}) {
4951
5309
  fetch: options.fetch,
4952
5310
  extraBody: options.extraBody
4953
5311
  });
5312
+ const createVideoModel = (modelId, settings = {}) => new OpenRouterVideoModel(modelId, settings, {
5313
+ provider: "openrouter.video",
5314
+ url: ({ path }) => `${baseURL}${path}`,
5315
+ headers: getHeaders,
5316
+ fetch: options.fetch,
5317
+ extraBody: options.extraBody
5318
+ });
4954
5319
  const createLanguageModel = (modelId, settings) => {
4955
5320
  if (new.target) {
4956
5321
  throw new Error(
@@ -4972,6 +5337,7 @@ function createOpenRouter(options = {}) {
4972
5337
  provider.textEmbeddingModel = createEmbeddingModel;
4973
5338
  provider.embedding = createEmbeddingModel;
4974
5339
  provider.imageModel = createImageModel;
5340
+ provider.videoModel = createVideoModel;
4975
5341
  provider.tools = {
4976
5342
  webSearch
4977
5343
  };