@2515097216/jimeng-free-api 0.8.10 → 0.8.12

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.
@@ -1196,7 +1196,7 @@ process.setMaxListeners(Infinity);
1196
1196
  process.on("uncaughtException", (err, origin) => {
1197
1197
  logger_default.error(`An unhandled error occurred: ${origin}`, err);
1198
1198
  });
1199
- process.on("unhandledRejection", (_17, promise) => {
1199
+ process.on("unhandledRejection", (_18, promise) => {
1200
1200
  promise.catch((err) => logger_default.error("An unhandled rejection occurred:", err));
1201
1201
  });
1202
1202
  process.on("warning", (warning) => logger_default.warn("System warning: ", warning));
@@ -1599,13 +1599,16 @@ var Server = class {
1599
1599
  var server_default = new Server();
1600
1600
 
1601
1601
  // src/api/routes/index.ts
1602
- import fs8 from "fs-extra";
1602
+ import fs9 from "fs-extra";
1603
+ import path7 from "path";
1604
+ import mime4 from "mime";
1603
1605
 
1604
1606
  // src/api/routes/images.ts
1605
- import fs6 from "fs";
1606
- import _13 from "lodash";
1607
+ import fs7 from "fs";
1608
+ import _14 from "lodash";
1607
1609
 
1608
1610
  // src/api/controllers/images.ts
1611
+ import _13 from "lodash";
1609
1612
  import crypto2 from "crypto";
1610
1613
 
1611
1614
  // src/lib/configs/model-config.ts
@@ -2475,7 +2478,7 @@ async function generateImageComposition(_model, prompt, imageUrls, {
2475
2478
  }],
2476
2479
  strength: 0.5
2477
2480
  })),
2478
- prompt_placeholder_info_list: uploadedImageIds.map((_17, index) => ({
2481
+ prompt_placeholder_info_list: uploadedImageIds.map((_18, index) => ({
2479
2482
  type: "",
2480
2483
  id: util_default.uuid(),
2481
2484
  ability_index: index
@@ -2502,6 +2505,7 @@ async function generateImageComposition(_model, prompt, imageUrls, {
2502
2505
  logger_default.info(`\u56FE\u751F\u56FE\u4EFB\u52A1\u5DF2\u63D0\u4EA4\uFF0Chistory_id: ${historyId}\uFF0C\u7B49\u5F85\u751F\u6210\u5B8C\u6210...`);
2503
2506
  let status = 20, failCode, item_list = [];
2504
2507
  let pollCount = 0;
2508
+ let missingRecordCount = 0;
2505
2509
  const maxPollCount = 600;
2506
2510
  while (pollCount < maxPollCount) {
2507
2511
  await new Promise((resolve) => setTimeout(resolve, 1e3));
@@ -2587,8 +2591,15 @@ async function generateImageComposition(_model, prompt, imageUrls, {
2587
2591
  }
2588
2592
  }
2589
2593
  });
2590
- if (!result[historyId])
2591
- throw new APIException(exceptions_default.API_IMAGE_GENERATION_FAILED, "\u8BB0\u5F55\u4E0D\u5B58\u5728");
2594
+ if (!result[historyId]) {
2595
+ missingRecordCount++;
2596
+ logger_default.warn(`history_id ${historyId} not found in poll result, retry ${missingRecordCount}/10`);
2597
+ if (missingRecordCount >= 10) {
2598
+ throw new APIException(exceptions_default.API_IMAGE_GENERATION_FAILED, "\u8BB0\u5F55\u4E0D\u5B58\u5728");
2599
+ }
2600
+ continue;
2601
+ }
2602
+ missingRecordCount = 0;
2592
2603
  status = result[historyId].status;
2593
2604
  failCode = result[historyId].fail_code;
2594
2605
  item_list = result[historyId].item_list || [];
@@ -2626,13 +2637,18 @@ async function generateMultiImages(_model, prompt, {
2626
2637
  resolution = "2k",
2627
2638
  sampleStrength = 0.5,
2628
2639
  negativePrompt = "",
2629
- intelligentRatio = false
2640
+ intelligentRatio = false,
2641
+ targetImageCount
2630
2642
  }, refreshToken) {
2631
2643
  const model = getModel(_model);
2632
2644
  const resolutionResult = resolveResolution(resolution, ratio);
2633
2645
  const { width, height, imageRatio, resolutionType } = resolutionResult;
2634
- const targetImageCount = prompt.match(/(\d+)张/) ? parseInt(prompt.match(/(\d+)张/)[1]) : 4;
2635
- logger_default.info(`\u4F7F\u7528 ${_model} \u591A\u56FE\u751F\u6210: ${targetImageCount}\u5F20\u56FE\u7247 ${width}x${height} (${ratio}@${resolution}) \u7CBE\u7EC6\u5EA6: ${sampleStrength}`);
2646
+ const finalTargetImageCount = _13.clamp(
2647
+ targetImageCount ?? (prompt.match(/(\d+)张/) ? parseInt(prompt.match(/(\d+)张/)[1]) : 4),
2648
+ 1,
2649
+ 10
2650
+ );
2651
+ logger_default.info(`\u4F7F\u7528 ${_model} \u591A\u56FE\u751F\u6210: ${finalTargetImageCount}\u5F20\u56FE\u7247 ${width}x${height} (${ratio}@${resolution}) \u7CBE\u7EC6\u5EA6: ${sampleStrength}`);
2636
2652
  const componentId = util_default.uuid();
2637
2653
  const submitId = util_default.uuid();
2638
2654
  const sceneOption = {
@@ -2721,7 +2737,7 @@ async function generateMultiImages(_model, prompt, {
2721
2737
  gen_option: {
2722
2738
  type: "",
2723
2739
  id: util_default.uuid(),
2724
- generate_all: false
2740
+ generate_all: finalTargetImageCount > 1
2725
2741
  }
2726
2742
  }
2727
2743
  }
@@ -2737,15 +2753,16 @@ async function generateMultiImages(_model, prompt, {
2737
2753
  const historyId = aigc_data == null ? void 0 : aigc_data.history_record_id;
2738
2754
  if (!historyId)
2739
2755
  throw new APIException(exceptions_default.API_IMAGE_GENERATION_FAILED, "\u8BB0\u5F55ID\u4E0D\u5B58\u5728");
2740
- logger_default.info(`\u591A\u56FE\u751F\u6210\u4EFB\u52A1\u5DF2\u63D0\u4EA4\uFF0Csubmit_id: ${submitId}, history_id: ${historyId}\uFF0C\u7B49\u5F85\u751F\u6210 ${targetImageCount} \u5F20\u56FE\u7247...`);
2756
+ logger_default.info(`\u591A\u56FE\u751F\u6210\u4EFB\u52A1\u5DF2\u63D0\u4EA4\uFF0Csubmit_id: ${submitId}, history_id: ${historyId}\uFF0C\u7B49\u5F85\u751F\u6210 ${finalTargetImageCount} \u5F20\u56FE\u7247...`);
2741
2757
  let status = 20, failCode, item_list = [];
2742
2758
  let pollCount = 0;
2759
+ let missingRecordCount = 0;
2743
2760
  const maxPollCount = 600;
2744
2761
  while (pollCount < maxPollCount) {
2745
2762
  await new Promise((resolve) => setTimeout(resolve, 1e3));
2746
2763
  pollCount++;
2747
2764
  if (pollCount % 30 === 0) {
2748
- logger_default.info(`\u591A\u56FE\u751F\u6210\u8FDB\u5EA6: \u7B2C ${pollCount} \u6B21\u8F6E\u8BE2 (history_id: ${historyId})\uFF0C\u5F53\u524D\u72B6\u6001: ${status}\uFF0C\u5DF2\u751F\u6210: ${item_list.length}/${targetImageCount} \u5F20\u56FE\u7247...`);
2765
+ logger_default.info(`\u591A\u56FE\u751F\u6210\u8FDB\u5EA6: \u7B2C ${pollCount} \u6B21\u8F6E\u8BE2 (history_id: ${historyId})\uFF0C\u5F53\u524D\u72B6\u6001: ${status}\uFF0C\u5DF2\u751F\u6210: ${item_list.length}/${finalTargetImageCount} \u5F20\u56FE\u7247...`);
2749
2766
  }
2750
2767
  const result = await request("post", "/mweb/v1/get_history_by_ids", refreshToken, {
2751
2768
  data: {
@@ -2825,20 +2842,27 @@ async function generateMultiImages(_model, prompt, {
2825
2842
  }
2826
2843
  }
2827
2844
  });
2828
- if (!result[historyId])
2829
- throw new APIException(exceptions_default.API_IMAGE_GENERATION_FAILED, "\u8BB0\u5F55\u4E0D\u5B58\u5728");
2845
+ if (!result[historyId]) {
2846
+ missingRecordCount++;
2847
+ logger_default.warn(`history_id ${historyId} not found in poll result, retry ${missingRecordCount}/10`);
2848
+ if (missingRecordCount >= 10) {
2849
+ throw new APIException(exceptions_default.API_IMAGE_GENERATION_FAILED, "\u8BB0\u5F55\u4E0D\u5B58\u5728");
2850
+ }
2851
+ continue;
2852
+ }
2853
+ missingRecordCount = 0;
2830
2854
  status = result[historyId].status;
2831
2855
  failCode = result[historyId].fail_code;
2832
2856
  item_list = result[historyId].item_list || [];
2833
- if (item_list.length >= targetImageCount) {
2857
+ if (item_list.length >= finalTargetImageCount) {
2834
2858
  logger_default.info(`\u591A\u56FE\u751F\u6210\u5B8C\u6210: \u72B6\u6001=${status}, \u5DF2\u751F\u6210 ${item_list.length} \u5F20\u56FE\u7247`);
2835
2859
  break;
2836
2860
  }
2837
2861
  if (pollCount % 60 === 0) {
2838
2862
  logger_default.info(`jimeng-4.0 \u8BE6\u7EC6\u72B6\u6001: status=${status}, item_list.length=${item_list.length}, failCode=${failCode || "none"}`);
2839
2863
  }
2840
- if (status === 10 && item_list.length < targetImageCount && pollCount % 30 === 0) {
2841
- logger_default.info(`jimeng-4.0 \u72B6\u6001\u5DF2\u5B8C\u6210\u4F46\u56FE\u7247\u6570\u91CF\u4E0D\u8DB3: \u72B6\u6001=${status}, \u5DF2\u751F\u6210 ${item_list.length}/${targetImageCount} \u5F20\u56FE\u7247\uFF0C\u7EE7\u7EED\u7B49\u5F85...`);
2864
+ if (status === 10 && item_list.length < finalTargetImageCount && pollCount % 30 === 0) {
2865
+ logger_default.info(`jimeng-4.0 \u72B6\u6001\u5DF2\u5B8C\u6210\u4F46\u56FE\u7247\u6570\u91CF\u4E0D\u8DB3: \u72B6\u6001=${status}, \u5DF2\u751F\u6210 ${item_list.length}/${finalTargetImageCount} \u5F20\u56FE\u7247\uFF0C\u7EE7\u7EED\u7B49\u5F85...`);
2842
2866
  }
2843
2867
  }
2844
2868
  if (pollCount >= maxPollCount) {
@@ -2855,7 +2879,7 @@ async function generateMultiImages(_model, prompt, {
2855
2879
  if (!((_c = (_b = (_a = item == null ? void 0 : item.image) == null ? void 0 : _a.large_images) == null ? void 0 : _b[0]) == null ? void 0 : _c.image_url))
2856
2880
  return ((_d = item == null ? void 0 : item.common_attr) == null ? void 0 : _d.cover_url) || null;
2857
2881
  return item.image.large_images[0].image_url;
2858
- }).filter((url) => url !== null);
2882
+ }).filter((url) => url !== null).slice(0, finalTargetImageCount);
2859
2883
  logger_default.info(`\u591A\u56FE\u751F\u6210\u7ED3\u679C: \u6210\u529F\u751F\u6210 ${imageUrls.length} \u5F20\u56FE\u7247`);
2860
2884
  return imageUrls;
2861
2885
  }
@@ -2864,7 +2888,8 @@ async function generateImages(_model, prompt, {
2864
2888
  resolution = "2k",
2865
2889
  sampleStrength = 0.5,
2866
2890
  negativePrompt = "",
2867
- intelligentRatio = false
2891
+ intelligentRatio = false,
2892
+ n = 1
2868
2893
  }, refreshToken) {
2869
2894
  const model = getModel(_model);
2870
2895
  const resolutionResult = resolveResolution(resolution, ratio);
@@ -2873,9 +2898,15 @@ async function generateImages(_model, prompt, {
2873
2898
  const { totalCredit } = await getCredit(refreshToken);
2874
2899
  if (totalCredit <= 0)
2875
2900
  await receiveCredit(refreshToken);
2876
- const isMultiImageRequest = /jimeng-[45]\.[0-9]/.test(_model) && (prompt.includes("\u8FDE\u7EED") || prompt.includes("\u7ED8\u672C") || prompt.includes("\u6545\u4E8B") || /\d+张/.test(prompt));
2901
+ const finalN = _13.clamp(Number(n) || 1, 1, 10);
2902
+ const isMultiImageRequest = /jimeng-[45]\.[0-9]/.test(_model) && (finalN > 1 || prompt.includes("\u8FDE\u7EED") || prompt.includes("\u7ED8\u672C") || prompt.includes("\u6545\u4E8B") || /\d+张/.test(prompt));
2877
2903
  if (isMultiImageRequest) {
2878
- return await generateMultiImages(_model, prompt, { ratio, resolution, sampleStrength, negativePrompt, intelligentRatio }, refreshToken);
2904
+ return await generateMultiImages(
2905
+ _model,
2906
+ prompt,
2907
+ { ratio, resolution, sampleStrength, negativePrompt, intelligentRatio, targetImageCount: finalN > 1 ? finalN : void 0 },
2908
+ refreshToken
2909
+ );
2879
2910
  }
2880
2911
  const componentId = util_default.uuid();
2881
2912
  const submitId = util_default.uuid();
@@ -2980,6 +3011,7 @@ async function generateImages(_model, prompt, {
2980
3011
  logger_default.info(`\u6587\u751F\u56FE\u4EFB\u52A1\u5DF2\u63D0\u4EA4\uFF0Csubmit_id: ${submitId}, history_id: ${historyId}\uFF0C\u7B49\u5F85\u751F\u6210\u5B8C\u6210...`);
2981
3012
  let status = 20, failCode, item_list = [];
2982
3013
  let pollCount = 0;
3014
+ let missingRecordCount = 0;
2983
3015
  const maxPollCount = 600;
2984
3016
  while (pollCount < maxPollCount) {
2985
3017
  await new Promise((resolve) => setTimeout(resolve, 1e3));
@@ -3086,8 +3118,15 @@ async function generateImages(_model, prompt, {
3086
3118
  }
3087
3119
  }
3088
3120
  });
3089
- if (!result[historyId])
3090
- throw new APIException(exceptions_default.API_IMAGE_GENERATION_FAILED, "\u8BB0\u5F55\u4E0D\u5B58\u5728");
3121
+ if (!result[historyId]) {
3122
+ missingRecordCount++;
3123
+ logger_default.warn(`history_id ${historyId} not found in poll result, retry ${missingRecordCount}/10`);
3124
+ if (missingRecordCount >= 10) {
3125
+ throw new APIException(exceptions_default.API_IMAGE_GENERATION_FAILED, "\u8BB0\u5F55\u4E0D\u5B58\u5728");
3126
+ }
3127
+ continue;
3128
+ }
3129
+ missingRecordCount = 0;
3091
3130
  status = result[historyId].status;
3092
3131
  failCode = result[historyId].fail_code;
3093
3132
  item_list = result[historyId].item_list || [];
@@ -3121,6 +3160,62 @@ async function generateImages(_model, prompt, {
3121
3160
  return imageUrls;
3122
3161
  }
3123
3162
 
3163
+ // src/lib/local-assets.ts
3164
+ import path6 from "path";
3165
+ import axios3 from "axios";
3166
+ import fs6 from "fs-extra";
3167
+ function resolveExtension(sourceUrl, contentType, fallback = "bin") {
3168
+ if (contentType) {
3169
+ const ext = util_default.mimeToExtension(contentType.split(";")[0].trim());
3170
+ if (ext) return ext;
3171
+ }
3172
+ const urlExt = util_default.extractURLExtension(sourceUrl);
3173
+ if (urlExt) return urlExt;
3174
+ return fallback;
3175
+ }
3176
+ function normalizePrefix(prefix = "") {
3177
+ if (!prefix) return "";
3178
+ return prefix.startsWith("/") ? prefix : `/${prefix}`;
3179
+ }
3180
+ function buildPublicBaseUrl(headers = {}) {
3181
+ const forwardedProto = headers["x-forwarded-proto"];
3182
+ const forwardedHost = headers["x-forwarded-host"];
3183
+ const host = forwardedHost || headers.host;
3184
+ if (!host) return null;
3185
+ const protocol = forwardedProto || "http";
3186
+ return `${protocol}://${host}${normalizePrefix(config_default.service.urlPrefix)}`;
3187
+ }
3188
+ async function saveRemoteAssetToLocalUrl(remoteUrl, assetType = "images", publicBaseUrl) {
3189
+ const { relativePath } = await saveRemoteAssetToLocalPath(remoteUrl, assetType);
3190
+ const baseUrl = publicBaseUrl || `${config_default.service.publicDirUrl.replace(/\/public$/, "")}${normalizePrefix(config_default.service.urlPrefix)}`;
3191
+ const localUrl = `${baseUrl}/public/${relativePath}`;
3192
+ logger_default.info(`asset localized: ${remoteUrl} -> ${localUrl}`);
3193
+ return localUrl;
3194
+ }
3195
+ async function saveRemoteAssetToLocalPath(remoteUrl, assetType = "images") {
3196
+ const response = await axios3.get(remoteUrl, {
3197
+ responseType: "arraybuffer",
3198
+ timeout: 12e4
3199
+ });
3200
+ const ext = resolveExtension(
3201
+ remoteUrl,
3202
+ response.headers["content-type"],
3203
+ assetType === "videos" ? "mp4" : "png"
3204
+ );
3205
+ const dateDir = util_default.getDateString("yyyyMMdd");
3206
+ const relativePath = path6.posix.join("generated", assetType, dateDir, `${util_default.uuid(false)}.${ext}`);
3207
+ const outputPath = path6.join(config_default.system.publicDirPath, ...relativePath.split("/"));
3208
+ await fs6.ensureDir(path6.dirname(outputPath));
3209
+ await fs6.writeFile(outputPath, response.data);
3210
+ return { outputPath, relativePath };
3211
+ }
3212
+ async function saveRemoteAssetsToLocalUrls(remoteUrls, assetType = "images", publicBaseUrl) {
3213
+ return Promise.all(remoteUrls.map((url) => saveRemoteAssetToLocalUrl(url, assetType, publicBaseUrl)));
3214
+ }
3215
+ async function saveRemoteAssetsToLocalPaths(remoteUrls, assetType = "images") {
3216
+ return Promise.all(remoteUrls.map((url) => saveRemoteAssetToLocalPath(url, assetType)));
3217
+ }
3218
+
3124
3219
  // src/api/routes/images.ts
3125
3220
  var images_default = {
3126
3221
  prefix: "/v1/images",
@@ -3136,9 +3231,9 @@ var images_default = {
3136
3231
  const contentType = request2.headers["content-type"] || "";
3137
3232
  const isMultiPart = contentType.startsWith("multipart/form-data");
3138
3233
  if (isMultiPart) {
3139
- request2.validate("body.model", (v) => _13.isUndefined(v) || _13.isString(v)).validate("body.prompt", _13.isString).validate("body.negative_prompt", (v) => _13.isUndefined(v) || _13.isString(v)).validate("body.ratio", (v) => _13.isUndefined(v) || _13.isString(v)).validate("body.resolution", (v) => _13.isUndefined(v) || _13.isString(v)).validate("body.intelligent_ratio", (v) => _13.isUndefined(v) || typeof v === "string" && (v === "true" || v === "false") || _13.isBoolean(v)).validate("body.sample_strength", (v) => _13.isUndefined(v) || typeof v === "string" && !isNaN(parseFloat(v)) || _13.isFinite(v)).validate("body.response_format", (v) => _13.isUndefined(v) || _13.isString(v)).validate("headers.authorization", _13.isString);
3234
+ request2.validate("body.model", (v) => _14.isUndefined(v) || _14.isString(v)).validate("body.prompt", _14.isString).validate("body.negative_prompt", (v) => _14.isUndefined(v) || _14.isString(v)).validate("body.ratio", (v) => _14.isUndefined(v) || _14.isString(v)).validate("body.resolution", (v) => _14.isUndefined(v) || _14.isString(v)).validate("body.intelligent_ratio", (v) => _14.isUndefined(v) || typeof v === "string" && (v === "true" || v === "false") || _14.isBoolean(v)).validate("body.sample_strength", (v) => _14.isUndefined(v) || typeof v === "string" && !isNaN(parseFloat(v)) || _14.isFinite(v)).validate("body.n", (v) => _14.isUndefined(v) || typeof v === "string" && /^\d+$/.test(v) || _14.isFinite(v) && v >= 1 && v <= 10).validate("body.response_format", (v) => _14.isUndefined(v) || _14.isString(v)).validate("headers.authorization", _14.isString);
3140
3235
  } else {
3141
- request2.validate("body.model", (v) => _13.isUndefined(v) || _13.isString(v)).validate("body.prompt", _13.isString).validate("body.images", (v) => _13.isUndefined(v) || _13.isArray(v)).validate("body.negative_prompt", (v) => _13.isUndefined(v) || _13.isString(v)).validate("body.ratio", (v) => _13.isUndefined(v) || _13.isString(v)).validate("body.resolution", (v) => _13.isUndefined(v) || _13.isString(v)).validate("body.intelligent_ratio", (v) => _13.isUndefined(v) || _13.isBoolean(v)).validate("body.sample_strength", (v) => _13.isUndefined(v) || _13.isFinite(v)).validate("body.response_format", (v) => _13.isUndefined(v) || _13.isString(v)).validate("headers.authorization", _13.isString);
3236
+ request2.validate("body.model", (v) => _14.isUndefined(v) || _14.isString(v)).validate("body.prompt", _14.isString).validate("body.images", (v) => _14.isUndefined(v) || _14.isArray(v)).validate("body.negative_prompt", (v) => _14.isUndefined(v) || _14.isString(v)).validate("body.ratio", (v) => _14.isUndefined(v) || _14.isString(v)).validate("body.resolution", (v) => _14.isUndefined(v) || _14.isString(v)).validate("body.intelligent_ratio", (v) => _14.isUndefined(v) || _14.isBoolean(v)).validate("body.sample_strength", (v) => _14.isUndefined(v) || _14.isFinite(v)).validate("body.n", (v) => _14.isUndefined(v) || _14.isFinite(v) && v >= 1 && v <= 10).validate("body.response_format", (v) => _14.isUndefined(v) || _14.isString(v)).validate("headers.authorization", _14.isString);
3142
3237
  }
3143
3238
  let images = null;
3144
3239
  if (isMultiPart) {
@@ -3149,7 +3244,7 @@ var images_default = {
3149
3244
  if (imageFiles.length > 10) {
3150
3245
  throw new Error("\u6700\u591A\u652F\u630110\u5F20\u8F93\u5165\u56FE\u7247");
3151
3246
  }
3152
- images = imageFiles.map((file) => fs6.readFileSync(file.filepath));
3247
+ images = imageFiles.map((file) => fs7.readFileSync(file.filepath));
3153
3248
  }
3154
3249
  }
3155
3250
  } else {
@@ -3159,18 +3254,18 @@ var images_default = {
3159
3254
  throw new Error("\u6700\u591A\u652F\u630110\u5F20\u8F93\u5165\u56FE\u7247");
3160
3255
  }
3161
3256
  bodyImages.forEach((image, index) => {
3162
- if (!_13.isString(image) && !_13.isObject(image)) {
3257
+ if (!_14.isString(image) && !_14.isObject(image)) {
3163
3258
  throw new Error(`\u56FE\u7247 ${index + 1} \u683C\u5F0F\u4E0D\u6B63\u786E\uFF1A\u5E94\u4E3AURL\u5B57\u7B26\u4E32\u6216\u5305\u542Burl\u5B57\u6BB5\u7684\u5BF9\u8C61`);
3164
3259
  }
3165
- if (_13.isObject(image) && !image.url) {
3260
+ if (_14.isObject(image) && !image.url) {
3166
3261
  throw new Error(`\u56FE\u7247 ${index + 1} \u7F3A\u5C11url\u5B57\u6BB5`);
3167
3262
  }
3168
3263
  });
3169
- images = bodyImages.map((image) => _13.isString(image) ? image : image.url);
3264
+ images = bodyImages.map((image) => _14.isString(image) ? image : image.url);
3170
3265
  }
3171
3266
  }
3172
3267
  const tokens = tokenSplit(request2.headers.authorization);
3173
- const token = _13.sample(tokens);
3268
+ const token = _14.sample(tokens);
3174
3269
  const {
3175
3270
  model,
3176
3271
  prompt,
@@ -3179,11 +3274,14 @@ var images_default = {
3179
3274
  resolution,
3180
3275
  intelligent_ratio: intelligentRatio,
3181
3276
  sample_strength: sampleStrength,
3277
+ n,
3182
3278
  response_format
3183
3279
  } = request2.body;
3184
3280
  const finalSampleStrength = isMultiPart && typeof sampleStrength === "string" ? parseFloat(sampleStrength) : sampleStrength;
3185
3281
  const finalIntelligentRatio = isMultiPart && typeof intelligentRatio === "string" ? intelligentRatio === "true" : intelligentRatio;
3186
- const responseFormat = _13.defaultTo(response_format, "url");
3282
+ const finalN = isMultiPart && typeof n === "string" ? parseInt(n) : n;
3283
+ const responseFormat = _14.defaultTo(response_format, "url");
3284
+ const publicBaseUrl = buildPublicBaseUrl(request2.headers);
3187
3285
  let imageUrls;
3188
3286
  let resultData = {
3189
3287
  created: util_default.unixTimestamp()
@@ -3204,14 +3302,16 @@ var images_default = {
3204
3302
  resolution,
3205
3303
  sampleStrength: finalSampleStrength,
3206
3304
  negativePrompt,
3207
- intelligentRatio: finalIntelligentRatio
3305
+ intelligentRatio: finalIntelligentRatio,
3306
+ n: finalN
3208
3307
  }, token);
3209
3308
  }
3210
3309
  let data = [];
3211
3310
  if (responseFormat == "b64_json") {
3212
3311
  data = (await Promise.all(imageUrls.map((url) => util_default.fetchFileBASE64(url)))).map((b64) => ({ b64_json: b64 }));
3213
3312
  } else {
3214
- data = imageUrls.map((url) => ({
3313
+ const localUrls = await saveRemoteAssetsToLocalUrls(imageUrls, "images", publicBaseUrl);
3314
+ data = localUrls.map((url) => ({
3215
3315
  url
3216
3316
  }));
3217
3317
  }
@@ -3230,9 +3330,9 @@ var images_default = {
3230
3330
  const contentType = request2.headers["content-type"] || "";
3231
3331
  const isMultiPart = contentType.startsWith("multipart/form-data");
3232
3332
  if (isMultiPart) {
3233
- request2.validate("body.model", (v) => _13.isUndefined(v) || _13.isString(v)).validate("body.prompt", _13.isString).validate("body.negative_prompt", (v) => _13.isUndefined(v) || _13.isString(v)).validate("body.ratio", (v) => _13.isUndefined(v) || _13.isString(v)).validate("body.resolution", (v) => _13.isUndefined(v) || _13.isString(v)).validate("body.intelligent_ratio", (v) => _13.isUndefined(v) || typeof v === "string" && (v === "true" || v === "false") || _13.isBoolean(v)).validate("body.sample_strength", (v) => _13.isUndefined(v) || typeof v === "string" && !isNaN(parseFloat(v)) || _13.isFinite(v)).validate("body.response_format", (v) => _13.isUndefined(v) || _13.isString(v)).validate("headers.authorization", _13.isString);
3333
+ request2.validate("body.model", (v) => _14.isUndefined(v) || _14.isString(v)).validate("body.prompt", _14.isString).validate("body.negative_prompt", (v) => _14.isUndefined(v) || _14.isString(v)).validate("body.ratio", (v) => _14.isUndefined(v) || _14.isString(v)).validate("body.resolution", (v) => _14.isUndefined(v) || _14.isString(v)).validate("body.intelligent_ratio", (v) => _14.isUndefined(v) || typeof v === "string" && (v === "true" || v === "false") || _14.isBoolean(v)).validate("body.sample_strength", (v) => _14.isUndefined(v) || typeof v === "string" && !isNaN(parseFloat(v)) || _14.isFinite(v)).validate("body.response_format", (v) => _14.isUndefined(v) || _14.isString(v)).validate("headers.authorization", _14.isString);
3234
3334
  } else {
3235
- request2.validate("body.model", (v) => _13.isUndefined(v) || _13.isString(v)).validate("body.prompt", _13.isString).validate("body.images", _13.isArray).validate("body.negative_prompt", (v) => _13.isUndefined(v) || _13.isString(v)).validate("body.ratio", (v) => _13.isUndefined(v) || _13.isString(v)).validate("body.resolution", (v) => _13.isUndefined(v) || _13.isString(v)).validate("body.intelligent_ratio", (v) => _13.isUndefined(v) || _13.isBoolean(v)).validate("body.sample_strength", (v) => _13.isUndefined(v) || _13.isFinite(v)).validate("body.response_format", (v) => _13.isUndefined(v) || _13.isString(v)).validate("headers.authorization", _13.isString);
3335
+ request2.validate("body.model", (v) => _14.isUndefined(v) || _14.isString(v)).validate("body.prompt", _14.isString).validate("body.images", _14.isArray).validate("body.negative_prompt", (v) => _14.isUndefined(v) || _14.isString(v)).validate("body.ratio", (v) => _14.isUndefined(v) || _14.isString(v)).validate("body.resolution", (v) => _14.isUndefined(v) || _14.isString(v)).validate("body.intelligent_ratio", (v) => _14.isUndefined(v) || _14.isBoolean(v)).validate("body.sample_strength", (v) => _14.isUndefined(v) || _14.isFinite(v)).validate("body.response_format", (v) => _14.isUndefined(v) || _14.isString(v)).validate("headers.authorization", _14.isString);
3236
3336
  }
3237
3337
  let images = [];
3238
3338
  if (isMultiPart) {
@@ -3247,7 +3347,7 @@ var images_default = {
3247
3347
  if (imageFiles.length > 10) {
3248
3348
  throw new Error("\u6700\u591A\u652F\u630110\u5F20\u8F93\u5165\u56FE\u7247");
3249
3349
  }
3250
- images = imageFiles.map((file) => fs6.readFileSync(file.filepath));
3350
+ images = imageFiles.map((file) => fs7.readFileSync(file.filepath));
3251
3351
  } else {
3252
3352
  const bodyImages = request2.body.images;
3253
3353
  if (!bodyImages || bodyImages.length === 0) {
@@ -3257,17 +3357,17 @@ var images_default = {
3257
3357
  throw new Error("\u6700\u591A\u652F\u630110\u5F20\u8F93\u5165\u56FE\u7247");
3258
3358
  }
3259
3359
  bodyImages.forEach((image, index) => {
3260
- if (!_13.isString(image) && !_13.isObject(image)) {
3360
+ if (!_14.isString(image) && !_14.isObject(image)) {
3261
3361
  throw new Error(`\u56FE\u7247 ${index + 1} \u683C\u5F0F\u4E0D\u6B63\u786E\uFF1A\u5E94\u4E3AURL\u5B57\u7B26\u4E32\u6216\u5305\u542Burl\u5B57\u6BB5\u7684\u5BF9\u8C61`);
3262
3362
  }
3263
- if (_13.isObject(image) && !image.url) {
3363
+ if (_14.isObject(image) && !image.url) {
3264
3364
  throw new Error(`\u56FE\u7247 ${index + 1} \u7F3A\u5C11url\u5B57\u6BB5`);
3265
3365
  }
3266
3366
  });
3267
- images = bodyImages.map((image) => _13.isString(image) ? image : image.url);
3367
+ images = bodyImages.map((image) => _14.isString(image) ? image : image.url);
3268
3368
  }
3269
3369
  const tokens = tokenSplit(request2.headers.authorization);
3270
- const token = _13.sample(tokens);
3370
+ const token = _14.sample(tokens);
3271
3371
  const {
3272
3372
  model,
3273
3373
  prompt,
@@ -3280,7 +3380,8 @@ var images_default = {
3280
3380
  } = request2.body;
3281
3381
  const finalSampleStrength = isMultiPart && typeof sampleStrength === "string" ? parseFloat(sampleStrength) : sampleStrength;
3282
3382
  const finalIntelligentRatio = isMultiPart && typeof intelligentRatio === "string" ? intelligentRatio === "true" : intelligentRatio;
3283
- const responseFormat = _13.defaultTo(response_format, "url");
3383
+ const responseFormat = _14.defaultTo(response_format, "url");
3384
+ const publicBaseUrl = buildPublicBaseUrl(request2.headers);
3284
3385
  const resultUrls = await generateImageComposition(model, prompt, images, {
3285
3386
  ratio,
3286
3387
  resolution,
@@ -3292,7 +3393,8 @@ var images_default = {
3292
3393
  if (responseFormat == "b64_json") {
3293
3394
  data = (await Promise.all(resultUrls.map((url) => util_default.fetchFileBASE64(url)))).map((b64) => ({ b64_json: b64 }));
3294
3395
  } else {
3295
- data = resultUrls.map((url) => ({
3396
+ const localUrls = await saveRemoteAssetsToLocalUrls(resultUrls, "images", publicBaseUrl);
3397
+ data = localUrls.map((url) => ({
3296
3398
  url
3297
3399
  }));
3298
3400
  }
@@ -3307,14 +3409,14 @@ var images_default = {
3307
3409
  };
3308
3410
 
3309
3411
  // src/api/routes/chat.ts
3310
- import _14 from "lodash";
3412
+ import _15 from "lodash";
3311
3413
 
3312
3414
  // src/api/controllers/chat.ts
3313
3415
  import { PassThrough } from "stream";
3314
3416
 
3315
3417
  // src/api/controllers/videos.ts
3316
3418
  import crypto3 from "crypto";
3317
- import fs7 from "fs";
3419
+ import fs8 from "fs";
3318
3420
  var DEFAULT_ASSISTANT_ID3 = 513695;
3319
3421
  var DEFAULT_MODEL2 = "jimeng-video-3.0";
3320
3422
  var DEFAULT_DRAFT_VERSION = "3.2.8";
@@ -3390,8 +3492,8 @@ var MATERIAL_TYPE_CODE = {
3390
3492
  audio: 3
3391
3493
  };
3392
3494
  function detectMaterialType(file) {
3393
- const mime4 = (file.mimetype || file.mimeType || "").toLowerCase();
3394
- if (mime4 && MIME_TO_MATERIAL_TYPE[mime4]) return MIME_TO_MATERIAL_TYPE[mime4];
3495
+ const mime5 = (file.mimetype || file.mimeType || "").toLowerCase();
3496
+ if (mime5 && MIME_TO_MATERIAL_TYPE[mime5]) return MIME_TO_MATERIAL_TYPE[mime5];
3395
3497
  const filename = (file.originalFilename || file.newFilename || "").toLowerCase();
3396
3498
  const dotIdx = filename.lastIndexOf(".");
3397
3499
  if (dotIdx >= 0) {
@@ -4077,7 +4179,7 @@ async function generateVideo(_model, prompt, {
4077
4179
  }
4078
4180
  try {
4079
4181
  logger_default.info(`\u5F00\u59CB\u4E0A\u4F20\u7B2C ${i + 1} \u4E2A\u6587\u4EF6: ${file.originalFilename || file.filepath}`);
4080
- const buffer = fs7.readFileSync(file.filepath);
4182
+ const buffer = fs8.readFileSync(file.filepath);
4081
4183
  const imageUri = await uploadImageBufferForVideo(buffer, refreshToken);
4082
4184
  if (imageUri) {
4083
4185
  uploadIDs.push(imageUri);
@@ -4447,7 +4549,7 @@ async function generateSeedanceVideo(_model, prompt, {
4447
4549
  const materialType = detectMaterialType(file);
4448
4550
  try {
4449
4551
  logger_default.info(`Seedance: \u5F00\u59CB\u4E0A\u4F20\u7B2C ${i + 1} \u4E2A\u6587\u4EF6 (${materialType}): ${file.originalFilename || file.filepath}`);
4450
- const buffer = fs7.readFileSync(file.filepath);
4552
+ const buffer = fs8.readFileSync(file.filepath);
4451
4553
  if (materialType === "image") {
4452
4554
  const imageUri = await uploadImageBufferForVideo(buffer, refreshToken);
4453
4555
  if (imageUri) {
@@ -4836,7 +4938,7 @@ var MAX_RETRY_COUNT = 3;
4836
4938
  var RETRY_DELAY = 5e3;
4837
4939
  function parseModel(model) {
4838
4940
  const [_model, size] = model.split(":");
4839
- const [_17, width, height] = /(\d+)[\W\w](\d+)/.exec(size) ?? [];
4941
+ const [_18, width, height] = /(\d+)[\W\w](\d+)/.exec(size) ?? [];
4840
4942
  return {
4841
4943
  model: _model,
4842
4944
  width: size ? Math.ceil(parseInt(width) / 2) * 2 : 1024,
@@ -4846,7 +4948,7 @@ function parseModel(model) {
4846
4948
  function isVideoModel(model) {
4847
4949
  return model.startsWith("jimeng-video") || model.startsWith("seedance-");
4848
4950
  }
4849
- async function createCompletion(messages, refreshToken, _model = DEFAULT_MODEL, retryCount = 0) {
4951
+ async function createCompletion(messages, refreshToken, _model = DEFAULT_MODEL, retryCount = 0, publicBaseUrl) {
4850
4952
  return (async () => {
4851
4953
  if (messages.length === 0)
4852
4954
  throw new APIException(exceptions_default.API_REQUEST_PARAMS_INVALID, "\u6D88\u606F\u4E0D\u80FD\u4E3A\u7A7A");
@@ -4905,7 +5007,8 @@ curl -X POST http://localhost:3000/v1/videos/generations \\
4905
5007
  },
4906
5008
  refreshToken
4907
5009
  );
4908
- logger_default.info(`\u89C6\u9891\u751F\u6210\u6210\u529F\uFF0CURL: ${videoUrl}`);
5010
+ const localVideoUrl = await saveRemoteAssetToLocalUrl(videoUrl, "videos", publicBaseUrl);
5011
+ logger_default.info(`\u89C6\u9891\u751F\u6210\u6210\u529F\uFF0CURL: ${localVideoUrl}`);
4909
5012
  return {
4910
5013
  id: util_default.uuid(),
4911
5014
  model: _model,
@@ -4915,7 +5018,7 @@ curl -X POST http://localhost:3000/v1/videos/generations \\
4915
5018
  index: 0,
4916
5019
  message: {
4917
5020
  role: "assistant",
4918
- content: `![video](${videoUrl})
5021
+ content: `![video](${localVideoUrl})
4919
5022
  `
4920
5023
  },
4921
5024
  finish_reason: "stop"
@@ -4959,6 +5062,7 @@ curl -X POST http://localhost:3000/v1/videos/generations \\
4959
5062
  },
4960
5063
  refreshToken
4961
5064
  );
5065
+ const localImageUrls = await saveRemoteAssetsToLocalUrls(imageUrls, "images", publicBaseUrl);
4962
5066
  return {
4963
5067
  id: util_default.uuid(),
4964
5068
  model: _model || model,
@@ -4968,7 +5072,7 @@ curl -X POST http://localhost:3000/v1/videos/generations \\
4968
5072
  index: 0,
4969
5073
  message: {
4970
5074
  role: "assistant",
4971
- content: imageUrls.reduce(
5075
+ content: localImageUrls.reduce(
4972
5076
  (acc, url, i) => acc + `![image_${i}](${url})
4973
5077
  `,
4974
5078
  ""
@@ -4987,13 +5091,13 @@ curl -X POST http://localhost:3000/v1/videos/generations \\
4987
5091
  logger_default.warn(`Try again after ${RETRY_DELAY / 1e3}s...`);
4988
5092
  return (async () => {
4989
5093
  await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY));
4990
- return createCompletion(messages, refreshToken, _model, retryCount + 1);
5094
+ return createCompletion(messages, refreshToken, _model, retryCount + 1, publicBaseUrl);
4991
5095
  })();
4992
5096
  }
4993
5097
  throw err;
4994
5098
  });
4995
5099
  }
4996
- async function createCompletionStream(messages, refreshToken, _model = DEFAULT_MODEL, retryCount = 0) {
5100
+ async function createCompletionStream(messages, refreshToken, _model = DEFAULT_MODEL, retryCount = 0, publicBaseUrl) {
4997
5101
  return (async () => {
4998
5102
  const { model, width, height } = parseModel(_model);
4999
5103
  logger_default.info(messages);
@@ -5079,10 +5183,11 @@ async function createCompletionStream(messages, refreshToken, _model = DEFAULT_M
5079
5183
  messages[messages.length - 1].content,
5080
5184
  { ratio: "16:9", resolution: "720p" },
5081
5185
  refreshToken
5082
- ).then((videoUrl) => {
5186
+ ).then(async (videoUrl) => {
5083
5187
  clearInterval(progressInterval);
5084
5188
  clearTimeout(timeoutId);
5085
- logger_default.info(`\u89C6\u9891\u751F\u6210\u6210\u529F\uFF0CURL: ${videoUrl}`);
5189
+ const localVideoUrl = await saveRemoteAssetToLocalUrl(videoUrl, "videos", publicBaseUrl);
5190
+ logger_default.info(`\u89C6\u9891\u751F\u6210\u6210\u529F\uFF0CURL: ${localVideoUrl}`);
5086
5191
  stream.write(
5087
5192
  "data: " + JSON.stringify({
5088
5193
  id: util_default.uuid(),
@@ -5097,11 +5202,11 @@ async function createCompletionStream(messages, refreshToken, _model = DEFAULT_M
5097
5202
 
5098
5203
  \u2705 \u89C6\u9891\u751F\u6210\u5B8C\u6210\uFF01
5099
5204
 
5100
- ![video](${videoUrl})
5205
+ ![video](${localVideoUrl})
5101
5206
 
5102
5207
  \u60A8\u53EF\u4EE5\uFF1A
5103
5208
  1. \u76F4\u63A5\u67E5\u770B\u4E0A\u65B9\u89C6\u9891
5104
- 2. \u4F7F\u7528\u4EE5\u4E0B\u94FE\u63A5\u4E0B\u8F7D\u6216\u5206\u4EAB\uFF1A${videoUrl}`
5209
+ 2. \u4F7F\u7528\u4EE5\u4E0B\u94FE\u63A5\u4E0B\u8F7D\u6216\u5206\u4EAB\uFF1A${localVideoUrl}`
5105
5210
  },
5106
5211
  finish_reason: null
5107
5212
  }
@@ -5187,9 +5292,10 @@ ${errorMessage}`
5187
5292
  messages[messages.length - 1].content,
5188
5293
  { width, height },
5189
5294
  refreshToken
5190
- ).then((imageUrls) => {
5191
- for (let i = 0; i < imageUrls.length; i++) {
5192
- const url = imageUrls[i];
5295
+ ).then(async (imageUrls) => {
5296
+ const localImageUrls = await saveRemoteAssetsToLocalUrls(imageUrls, "images", publicBaseUrl);
5297
+ for (let i = 0; i < localImageUrls.length; i++) {
5298
+ const url = localImageUrls[i];
5193
5299
  stream.write(
5194
5300
  "data: " + JSON.stringify({
5195
5301
  id: util_default.uuid(),
@@ -5203,7 +5309,7 @@ ${errorMessage}`
5203
5309
  content: `![image_${i}](${url})
5204
5310
  `
5205
5311
  },
5206
- finish_reason: i < imageUrls.length - 1 ? null : "stop"
5312
+ finish_reason: i < localImageUrls.length - 1 ? null : "stop"
5207
5313
  }
5208
5314
  ]
5209
5315
  }) + "\n\n"
@@ -5216,7 +5322,7 @@ ${errorMessage}`
5216
5322
  object: "chat.completion.chunk",
5217
5323
  choices: [
5218
5324
  {
5219
- index: imageUrls.length + 1,
5325
+ index: localImageUrls.length + 1,
5220
5326
  delta: {
5221
5327
  role: "assistant",
5222
5328
  content: "\u56FE\u50CF\u751F\u6210\u5B8C\u6210\uFF01"
@@ -5259,7 +5365,8 @@ ${errorMessage}`
5259
5365
  messages,
5260
5366
  refreshToken,
5261
5367
  _model,
5262
- retryCount + 1
5368
+ retryCount + 1,
5369
+ publicBaseUrl
5263
5370
  );
5264
5371
  })();
5265
5372
  }
@@ -5272,17 +5379,18 @@ var chat_default = {
5272
5379
  prefix: "/v1/chat",
5273
5380
  post: {
5274
5381
  "/completions": async (request2) => {
5275
- request2.validate("body.model", (v) => _14.isUndefined(v) || _14.isString(v)).validate("body.messages", _14.isArray).validate("headers.authorization", _14.isString);
5382
+ request2.validate("body.model", (v) => _15.isUndefined(v) || _15.isString(v)).validate("body.messages", _15.isArray).validate("headers.authorization", _15.isString);
5276
5383
  const tokens = tokenSplit(request2.headers.authorization);
5277
- const token = _14.sample(tokens);
5384
+ const token = _15.sample(tokens);
5278
5385
  const { model, messages, stream } = request2.body;
5386
+ const publicBaseUrl = buildPublicBaseUrl(request2.headers);
5279
5387
  if (stream) {
5280
- const stream2 = await createCompletionStream(messages, token, model);
5388
+ const stream2 = await createCompletionStream(messages, token, model, 0, publicBaseUrl);
5281
5389
  return new Response(stream2, {
5282
5390
  type: "text/event-stream"
5283
5391
  });
5284
5392
  } else
5285
- return await createCompletion(messages, token, model);
5393
+ return await createCompletion(messages, token, model, 0, publicBaseUrl);
5286
5394
  }
5287
5395
  }
5288
5396
  };
@@ -5296,19 +5404,19 @@ var ping_default = {
5296
5404
  };
5297
5405
 
5298
5406
  // src/api/routes/token.ts
5299
- import _15 from "lodash";
5407
+ import _16 from "lodash";
5300
5408
  var token_default = {
5301
5409
  prefix: "/token",
5302
5410
  post: {
5303
5411
  "/check": async (request2) => {
5304
- request2.validate("body.token", _15.isString);
5412
+ request2.validate("body.token", _16.isString);
5305
5413
  const live = await getTokenLiveStatus(request2.body.token);
5306
5414
  return {
5307
5415
  live
5308
5416
  };
5309
5417
  },
5310
5418
  "/points": async (request2) => {
5311
- request2.validate("headers.authorization", _15.isString);
5419
+ request2.validate("headers.authorization", _16.isString);
5312
5420
  const tokens = tokenSplit(request2.headers.authorization);
5313
5421
  const points = await Promise.all(tokens.map(async (token) => {
5314
5422
  return {
@@ -5472,7 +5580,7 @@ var models_default = {
5472
5580
  };
5473
5581
 
5474
5582
  // src/api/routes/videos.ts
5475
- import _16 from "lodash";
5583
+ import _17 from "lodash";
5476
5584
  var videos_default = {
5477
5585
  prefix: "/v1/videos",
5478
5586
  post: {
@@ -5485,16 +5593,16 @@ var videos_default = {
5485
5593
  }
5486
5594
  const contentType = request2.headers["content-type"] || "";
5487
5595
  const isMultiPart = contentType.startsWith("multipart/form-data");
5488
- request2.validate("body.model", (v) => _16.isUndefined(v) || _16.isString(v)).validate("body.prompt", (v) => _16.isUndefined(v) || _16.isString(v)).validate("body.ratio", (v) => _16.isUndefined(v) || _16.isString(v)).validate("body.resolution", (v) => _16.isUndefined(v) || _16.isString(v)).validate("body.duration", (v) => {
5489
- if (_16.isUndefined(v)) return true;
5596
+ request2.validate("body.model", (v) => _17.isUndefined(v) || _17.isString(v)).validate("body.prompt", (v) => _17.isUndefined(v) || _17.isString(v)).validate("body.ratio", (v) => _17.isUndefined(v) || _17.isString(v)).validate("body.resolution", (v) => _17.isUndefined(v) || _17.isString(v)).validate("body.duration", (v) => {
5597
+ if (_17.isUndefined(v)) return true;
5490
5598
  if (isMultiPart && typeof v === "string") {
5491
5599
  const num = parseInt(v);
5492
5600
  return num >= 4 && num <= 15 || num === 5 || num === 10;
5493
5601
  }
5494
- return _16.isFinite(v) && (v >= 4 && v <= 15 || v === 5 || v === 10);
5495
- }).validate("body.file_paths", (v) => _16.isUndefined(v) || _16.isArray(v)).validate("body.filePaths", (v) => _16.isUndefined(v) || _16.isArray(v)).validate("body.response_format", (v) => _16.isUndefined(v) || _16.isString(v)).validate("headers.authorization", _16.isString);
5602
+ return _17.isFinite(v) && (v >= 4 && v <= 15 || v === 5 || v === 10);
5603
+ }).validate("body.file_paths", (v) => _17.isUndefined(v) || _17.isArray(v)).validate("body.filePaths", (v) => _17.isUndefined(v) || _17.isArray(v)).validate("body.response_format", (v) => _17.isUndefined(v) || _17.isString(v)).validate("headers.authorization", _17.isString);
5496
5604
  const tokens = tokenSplit(request2.headers.authorization);
5497
- const token = _16.sample(tokens);
5605
+ const token = _17.sample(tokens);
5498
5606
  const {
5499
5607
  model = DEFAULT_MODEL2,
5500
5608
  prompt,
@@ -5547,10 +5655,12 @@ var videos_default = {
5547
5655
  }]
5548
5656
  };
5549
5657
  } else {
5658
+ const publicBaseUrl = buildPublicBaseUrl(request2.headers);
5659
+ const localVideoUrl = await saveRemoteAssetToLocalUrl(videoUrl, "videos", publicBaseUrl);
5550
5660
  return {
5551
5661
  created: util_default.unixTimestamp(),
5552
5662
  data: [{
5553
- url: videoUrl,
5663
+ url: localVideoUrl,
5554
5664
  revised_prompt: prompt
5555
5665
  }]
5556
5666
  };
@@ -5570,13 +5680,32 @@ var routes_default = [
5570
5680
  {
5571
5681
  get: {
5572
5682
  "/": async () => {
5573
- const content = await fs8.readFile("public/welcome.html");
5683
+ const content = await fs9.readFile("public/welcome.html");
5574
5684
  return new Response(content, {
5575
5685
  type: "html",
5576
5686
  headers: {
5577
5687
  Expires: "-1"
5578
5688
  }
5579
5689
  });
5690
+ },
5691
+ "/public/(.*)": async (request2) => {
5692
+ const rawPath = decodeURIComponent(request2.params[0] || "").replace(/^[/\\]+/, "");
5693
+ if (!rawPath) throw new Error("\u6587\u4EF6\u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A");
5694
+ const root = path7.resolve(config_default.system.publicDirPath);
5695
+ const filePath = path7.resolve(root, rawPath);
5696
+ const relative = path7.relative(root, filePath);
5697
+ if (relative.startsWith("..") || path7.isAbsolute(relative)) {
5698
+ throw new Error("\u975E\u6CD5\u6587\u4EF6\u8DEF\u5F84");
5699
+ }
5700
+ if (!await fs9.pathExists(filePath)) {
5701
+ throw new Error("\u6587\u4EF6\u4E0D\u5B58\u5728");
5702
+ }
5703
+ return new Response(fs9.createReadStream(filePath), {
5704
+ type: mime4.getType(filePath) || "application/octet-stream",
5705
+ headers: {
5706
+ "Cache-Control": "public, max-age=31536000, immutable"
5707
+ }
5708
+ });
5580
5709
  }
5581
5710
  }
5582
5711
  },
@@ -5599,9 +5728,11 @@ export {
5599
5728
  DEFAULT_MODEL,
5600
5729
  generateImageComposition,
5601
5730
  generateImages,
5731
+ saveRemoteAssetToLocalPath,
5732
+ saveRemoteAssetsToLocalPaths,
5602
5733
  DEFAULT_MODEL2,
5603
5734
  generateVideo,
5604
5735
  generateSeedanceVideo,
5605
5736
  routes_default
5606
5737
  };
5607
- //# sourceMappingURL=chunk-Z45BIJT6.js.map
5738
+ //# sourceMappingURL=chunk-FKUVCAUE.js.map