maoda-commander-tt 0.0.18 → 0.0.20
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/main.js +424 -512
- package/dist/main.js.map +1 -1
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2119,9 +2119,26 @@ var ShortcutEmoLynxCommand = class extends ShortcutBaseCommand {
|
|
|
2119
2119
|
}
|
|
2120
2120
|
};
|
|
2121
2121
|
|
|
2122
|
-
// src/commands/shortcut/shortcut-emo-pippit-command.ts
|
|
2122
|
+
// src/commands/shortcut/shortcut-emo-pippit-cn-command.ts
|
|
2123
2123
|
import { homedir as homedir3 } from "os";
|
|
2124
2124
|
import { join as join5 } from "path";
|
|
2125
|
+
var ShortcutEmoPippitCnCommand = class extends ShortcutBaseCommand {
|
|
2126
|
+
_meta() {
|
|
2127
|
+
return {
|
|
2128
|
+
name: "pippit-cn",
|
|
2129
|
+
description: "\u542F\u52A8 pippit-cn \u9879\u76EE",
|
|
2130
|
+
aliases: ["ppc"]
|
|
2131
|
+
};
|
|
2132
|
+
}
|
|
2133
|
+
async _execute(_ctx) {
|
|
2134
|
+
const cwd = join5(homedir3(), "work", "pippit-cn");
|
|
2135
|
+
return this._runCommandLine(`w2 start && emo start platform-xyq`, cwd);
|
|
2136
|
+
}
|
|
2137
|
+
};
|
|
2138
|
+
|
|
2139
|
+
// src/commands/shortcut/shortcut-emo-pippit-command.ts
|
|
2140
|
+
import { homedir as homedir4 } from "os";
|
|
2141
|
+
import { join as join6 } from "path";
|
|
2125
2142
|
var ShortcutEmoPippitCommand = class extends ShortcutBaseCommand {
|
|
2126
2143
|
_meta() {
|
|
2127
2144
|
return {
|
|
@@ -2131,7 +2148,7 @@ var ShortcutEmoPippitCommand = class extends ShortcutBaseCommand {
|
|
|
2131
2148
|
};
|
|
2132
2149
|
}
|
|
2133
2150
|
async _execute(_ctx) {
|
|
2134
|
-
const cwd =
|
|
2151
|
+
const cwd = join6(homedir4(), "work", "pippit");
|
|
2135
2152
|
return this._runCommandLine(`w2 start && emo start platform-business`, cwd);
|
|
2136
2153
|
}
|
|
2137
2154
|
};
|
|
@@ -2148,6 +2165,7 @@ var ShortcutCommand = class extends BaseSubcommandHost {
|
|
|
2148
2165
|
_registerSubcommands() {
|
|
2149
2166
|
this._addSubcommand(new ShortcutEmoLynxCommand());
|
|
2150
2167
|
this._addSubcommand(new ShortcutEmoPippitCommand());
|
|
2168
|
+
this._addSubcommand(new ShortcutEmoPippitCnCommand());
|
|
2151
2169
|
}
|
|
2152
2170
|
};
|
|
2153
2171
|
|
|
@@ -2322,19 +2340,19 @@ var AiCodexCommand = class extends AiBaseCommand {
|
|
|
2322
2340
|
};
|
|
2323
2341
|
|
|
2324
2342
|
// src/commands/ai/ai-run-command.ts
|
|
2325
|
-
import { homedir as
|
|
2326
|
-
import { join as
|
|
2343
|
+
import { homedir as homedir6 } from "os";
|
|
2344
|
+
import { join as join8 } from "path";
|
|
2327
2345
|
|
|
2328
2346
|
// src/commands/ai/ai-context-path.ts
|
|
2329
2347
|
import { existsSync as existsSync2 } from "fs";
|
|
2330
|
-
import { homedir as
|
|
2331
|
-
import { join as
|
|
2348
|
+
import { homedir as homedir5 } from "os";
|
|
2349
|
+
import { join as join7 } from "path";
|
|
2332
2350
|
function getCurrentCloudRootPath() {
|
|
2333
2351
|
if (process.platform !== "darwin") {
|
|
2334
2352
|
return makeError(1, "`--my` \u4EC5\u652F\u6301\u5728 macOS \u4E0A\u4F7F\u7528");
|
|
2335
2353
|
}
|
|
2336
|
-
const cloudRootPath =
|
|
2337
|
-
|
|
2354
|
+
const cloudRootPath = join7(
|
|
2355
|
+
homedir5(),
|
|
2338
2356
|
"Library",
|
|
2339
2357
|
"Mobile Documents",
|
|
2340
2358
|
"com~apple~CloudDocs"
|
|
@@ -2362,7 +2380,7 @@ var AI_RUN_CONTEXT_ALIASES = [
|
|
|
2362
2380
|
return cloudRoot;
|
|
2363
2381
|
}
|
|
2364
2382
|
return ensureDirectoryExists(
|
|
2365
|
-
|
|
2383
|
+
join8(cloudRoot.value, "icloud-hub", "local-knowlege-base")
|
|
2366
2384
|
);
|
|
2367
2385
|
}
|
|
2368
2386
|
},
|
|
@@ -2371,7 +2389,7 @@ var AI_RUN_CONTEXT_ALIASES = [
|
|
|
2371
2389
|
optionDescription: "\u53C2\u8003 ~/work/smart-agent/dymamic-skills \u5B66\u4E60 skill",
|
|
2372
2390
|
resolveReferenceDir: () => {
|
|
2373
2391
|
return ensureDirectoryExists(
|
|
2374
|
-
|
|
2392
|
+
join8(homedir6(), "work", "smart-agent", "dynamic-skills")
|
|
2375
2393
|
);
|
|
2376
2394
|
}
|
|
2377
2395
|
}
|
|
@@ -2437,277 +2455,26 @@ user_prompt:
|
|
|
2437
2455
|
}
|
|
2438
2456
|
};
|
|
2439
2457
|
|
|
2440
|
-
// src/commands/ai/ai-image-command.ts
|
|
2441
|
-
import
|
|
2442
|
-
import * as path7 from "path";
|
|
2443
|
-
import { Option as Option8 } from "commander";
|
|
2444
|
-
|
|
2445
|
-
// src/commands/ai/ai-image-reference.ts
|
|
2458
|
+
// src/commands/ai/ai-image-command-v2.ts
|
|
2459
|
+
import { spawn as spawn3 } from "child_process";
|
|
2446
2460
|
import * as fs5 from "fs/promises";
|
|
2447
|
-
import
|
|
2461
|
+
import { homedir as homedir7 } from "os";
|
|
2448
2462
|
import * as path6 from "path";
|
|
2449
|
-
|
|
2450
|
-
|
|
2451
|
-
var
|
|
2452
|
-
var
|
|
2453
|
-
var MAX_REFERENCE_IMAGE_COUNT = 14;
|
|
2454
|
-
var API_SUPPORTED_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
2455
|
-
"image/jpeg",
|
|
2456
|
-
"image/png",
|
|
2457
|
-
"image/webp",
|
|
2458
|
-
"image/bmp",
|
|
2459
|
-
"image/tiff",
|
|
2460
|
-
"image/gif"
|
|
2461
|
-
]);
|
|
2462
|
-
async function prepareReferenceImages(filePaths) {
|
|
2463
|
-
if (filePaths.length > MAX_REFERENCE_IMAGE_COUNT) {
|
|
2464
|
-
return makeError(
|
|
2465
|
-
1,
|
|
2466
|
-
`\u53C2\u8003\u56FE\u6700\u591A\u652F\u6301 ${MAX_REFERENCE_IMAGE_COUNT} \u5F20\uFF0C\u5F53\u524D\u4F20\u5165 ${filePaths.length} \u5F20\u3002`
|
|
2467
|
-
);
|
|
2468
|
-
}
|
|
2469
|
-
const preparedImages = [];
|
|
2470
|
-
for (const filePath of filePaths) {
|
|
2471
|
-
const prepared = await prepareReferenceImage(filePath);
|
|
2472
|
-
if (!prepared.ok) {
|
|
2473
|
-
return prepared;
|
|
2474
|
-
}
|
|
2475
|
-
preparedImages.push(prepared.value);
|
|
2476
|
-
}
|
|
2477
|
-
return makeOkWith(preparedImages);
|
|
2478
|
-
}
|
|
2479
|
-
async function prepareReferenceImage(filePath) {
|
|
2480
|
-
const resolvedPath = path6.resolve(process.cwd(), filePath);
|
|
2481
|
-
let stats;
|
|
2482
|
-
try {
|
|
2483
|
-
stats = await fs5.stat(resolvedPath);
|
|
2484
|
-
} catch (error) {
|
|
2485
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
2486
|
-
return makeError(1, `\u8BFB\u53D6\u53C2\u8003\u56FE\u5931\u8D25: ${resolvedPath}: ${message}`);
|
|
2487
|
-
}
|
|
2488
|
-
if (!stats.isFile()) {
|
|
2489
|
-
return makeError(1, `\u53C2\u8003\u56FE\u4E0D\u662F\u6587\u4EF6: ${resolvedPath}`);
|
|
2490
|
-
}
|
|
2491
|
-
let fileBytes;
|
|
2492
|
-
try {
|
|
2493
|
-
fileBytes = await fs5.readFile(resolvedPath);
|
|
2494
|
-
} catch (error) {
|
|
2495
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
2496
|
-
return makeError(1, `\u8BFB\u53D6\u53C2\u8003\u56FE\u5185\u5BB9\u5931\u8D25: ${resolvedPath}: ${message}`);
|
|
2497
|
-
}
|
|
2498
|
-
const detectedType = detectMimeType(fileBytes, resolvedPath);
|
|
2499
|
-
if (!detectedType) {
|
|
2500
|
-
return makeError(1, `\u53C2\u8003\u56FE\u4E0D\u662F\u652F\u6301\u7684\u56FE\u7247\u683C\u5F0F: ${resolvedPath}`);
|
|
2501
|
-
}
|
|
2502
|
-
const needsTranscode = !API_SUPPORTED_MIME_TYPES.has(detectedType.mimeType) || fileBytes.byteLength > MAX_REFERENCE_IMAGE_BYTES;
|
|
2503
|
-
if (!needsTranscode) {
|
|
2504
|
-
return makeOkWith({
|
|
2505
|
-
inputPath: filePath,
|
|
2506
|
-
resolvedPath,
|
|
2507
|
-
sourceMimeType: detectedType.mimeType,
|
|
2508
|
-
requestMimeType: detectedType.mimeType,
|
|
2509
|
-
originalBytes: fileBytes.byteLength,
|
|
2510
|
-
finalBytes: fileBytes.byteLength,
|
|
2511
|
-
compressed: false,
|
|
2512
|
-
dataUrl: toDataUrl(detectedType.mimeType, fileBytes)
|
|
2513
|
-
});
|
|
2514
|
-
}
|
|
2515
|
-
const compressed = await compressImageForReference(resolvedPath);
|
|
2516
|
-
if (!compressed.ok) {
|
|
2517
|
-
return compressed;
|
|
2518
|
-
}
|
|
2519
|
-
return makeOkWith({
|
|
2520
|
-
inputPath: filePath,
|
|
2521
|
-
resolvedPath,
|
|
2522
|
-
sourceMimeType: detectedType.mimeType,
|
|
2523
|
-
requestMimeType: compressed.value.mimeType,
|
|
2524
|
-
originalBytes: fileBytes.byteLength,
|
|
2525
|
-
finalBytes: compressed.value.bytes.byteLength,
|
|
2526
|
-
compressed: true,
|
|
2527
|
-
dataUrl: toDataUrl(compressed.value.mimeType, compressed.value.bytes)
|
|
2528
|
-
});
|
|
2529
|
-
}
|
|
2530
|
-
function detectMimeType(fileBytes, filePath) {
|
|
2531
|
-
if (fileBytes.length >= 3 && fileBytes[0] === 255 && fileBytes[1] === 216 && fileBytes[2] === 255) {
|
|
2532
|
-
return { mimeType: "image/jpeg", extension: "jpeg" };
|
|
2533
|
-
}
|
|
2534
|
-
if (fileBytes.length >= 8 && fileBytes[0] === 137 && fileBytes[1] === 80 && fileBytes[2] === 78 && fileBytes[3] === 71 && fileBytes[4] === 13 && fileBytes[5] === 10 && fileBytes[6] === 26 && fileBytes[7] === 10) {
|
|
2535
|
-
return { mimeType: "image/png", extension: "png" };
|
|
2536
|
-
}
|
|
2537
|
-
if (fileBytes.length >= 6) {
|
|
2538
|
-
const gifHeader = fileBytes.subarray(0, 6).toString("ascii");
|
|
2539
|
-
if (gifHeader === "GIF87a" || gifHeader === "GIF89a") {
|
|
2540
|
-
return { mimeType: "image/gif", extension: "gif" };
|
|
2541
|
-
}
|
|
2542
|
-
}
|
|
2543
|
-
if (fileBytes.length >= 12 && fileBytes.subarray(0, 4).toString("ascii") === "RIFF" && fileBytes.subarray(8, 12).toString("ascii") === "WEBP") {
|
|
2544
|
-
return { mimeType: "image/webp", extension: "webp" };
|
|
2545
|
-
}
|
|
2546
|
-
if (fileBytes.length >= 2 && fileBytes.subarray(0, 2).toString("ascii") === "BM") {
|
|
2547
|
-
return { mimeType: "image/bmp", extension: "bmp" };
|
|
2548
|
-
}
|
|
2549
|
-
if (fileBytes.length >= 4 && (fileBytes[0] === 73 && fileBytes[1] === 73 && fileBytes[2] === 42 && fileBytes[3] === 0 || fileBytes[0] === 77 && fileBytes[1] === 77 && fileBytes[2] === 0 && fileBytes[3] === 42)) {
|
|
2550
|
-
return { mimeType: "image/tiff", extension: "tiff" };
|
|
2551
|
-
}
|
|
2552
|
-
if (fileBytes.length >= 12 && fileBytes.subarray(4, 8).toString("ascii") === "ftyp") {
|
|
2553
|
-
const brand = fileBytes.subarray(8, 12).toString("ascii").trim();
|
|
2554
|
-
if (brand.startsWith("avif") || brand === "avis") {
|
|
2555
|
-
return { mimeType: "image/avif", extension: "avif" };
|
|
2556
|
-
}
|
|
2557
|
-
if (brand.startsWith("hei") || brand.startsWith("hev") || brand === "mif1" || brand === "msf1") {
|
|
2558
|
-
return { mimeType: "image/heic", extension: "heic" };
|
|
2559
|
-
}
|
|
2560
|
-
}
|
|
2561
|
-
const ext = path6.extname(filePath).toLowerCase();
|
|
2562
|
-
switch (ext) {
|
|
2563
|
-
case ".jpg":
|
|
2564
|
-
case ".jpeg":
|
|
2565
|
-
return { mimeType: "image/jpeg", extension: "jpeg" };
|
|
2566
|
-
case ".png":
|
|
2567
|
-
return { mimeType: "image/png", extension: "png" };
|
|
2568
|
-
case ".gif":
|
|
2569
|
-
return { mimeType: "image/gif", extension: "gif" };
|
|
2570
|
-
case ".webp":
|
|
2571
|
-
return { mimeType: "image/webp", extension: "webp" };
|
|
2572
|
-
case ".bmp":
|
|
2573
|
-
return { mimeType: "image/bmp", extension: "bmp" };
|
|
2574
|
-
case ".tif":
|
|
2575
|
-
case ".tiff":
|
|
2576
|
-
return { mimeType: "image/tiff", extension: "tiff" };
|
|
2577
|
-
case ".heic":
|
|
2578
|
-
case ".heif":
|
|
2579
|
-
return { mimeType: "image/heic", extension: "heic" };
|
|
2580
|
-
case ".avif":
|
|
2581
|
-
return { mimeType: "image/avif", extension: "avif" };
|
|
2582
|
-
default:
|
|
2583
|
-
return void 0;
|
|
2584
|
-
}
|
|
2585
|
-
}
|
|
2586
|
-
async function compressImageForReference(sourcePath) {
|
|
2587
|
-
if (process.platform !== "darwin") {
|
|
2588
|
-
return makeError(
|
|
2589
|
-
1,
|
|
2590
|
-
`\u53C2\u8003\u56FE\u9700\u8981\u538B\u7F29\u6216\u8F6C\u7801\uFF0C\u4F46\u5F53\u524D\u5E73\u53F0 ${process.platform} \u672A\u5B9E\u73B0\u81EA\u52A8\u5904\u7406\u3002`
|
|
2591
|
-
);
|
|
2592
|
-
}
|
|
2593
|
-
const tempDir = await fs5.mkdtemp(path6.join(os2.tmpdir(), "tt-ai-image-"));
|
|
2594
|
-
try {
|
|
2595
|
-
const dimensions = await readImageDimensions(sourcePath);
|
|
2596
|
-
const maxDimension = Math.max(dimensions.width, dimensions.height);
|
|
2597
|
-
const resizeLimits = uniqueNumbers([
|
|
2598
|
-
maxDimension,
|
|
2599
|
-
Math.floor(maxDimension * 0.85),
|
|
2600
|
-
Math.floor(maxDimension * 0.7),
|
|
2601
|
-
Math.floor(maxDimension * 0.55),
|
|
2602
|
-
Math.floor(maxDimension * 0.4)
|
|
2603
|
-
]).filter((value) => value >= 64);
|
|
2604
|
-
const qualityLevels = [85, 75, 65, 55, 45, 35];
|
|
2605
|
-
let attemptIndex = 0;
|
|
2606
|
-
for (const resizeLimit of resizeLimits) {
|
|
2607
|
-
for (const quality of qualityLevels) {
|
|
2608
|
-
const targetPath = path6.join(tempDir, `compressed-${attemptIndex}.jpeg`);
|
|
2609
|
-
attemptIndex += 1;
|
|
2610
|
-
await runSips([
|
|
2611
|
-
"--setProperty",
|
|
2612
|
-
"format",
|
|
2613
|
-
"jpeg",
|
|
2614
|
-
"--setProperty",
|
|
2615
|
-
"formatOptions",
|
|
2616
|
-
String(quality),
|
|
2617
|
-
sourcePath,
|
|
2618
|
-
"--out",
|
|
2619
|
-
targetPath
|
|
2620
|
-
]);
|
|
2621
|
-
if (resizeLimit < maxDimension) {
|
|
2622
|
-
await runSips(["-Z", String(resizeLimit), targetPath]);
|
|
2623
|
-
}
|
|
2624
|
-
const compressedBytes = await fs5.readFile(targetPath);
|
|
2625
|
-
if (compressedBytes.byteLength <= MAX_REFERENCE_IMAGE_BYTES) {
|
|
2626
|
-
return makeOkWith({
|
|
2627
|
-
mimeType: "image/jpeg",
|
|
2628
|
-
bytes: compressedBytes
|
|
2629
|
-
});
|
|
2630
|
-
}
|
|
2631
|
-
}
|
|
2632
|
-
}
|
|
2633
|
-
return makeError(1, `\u53C2\u8003\u56FE\u538B\u7F29\u5931\u8D25\uFF0C\u65E0\u6CD5\u538B\u7F29\u5230 2MB \u4EE5\u5185: ${sourcePath}`);
|
|
2634
|
-
} catch (error) {
|
|
2635
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
2636
|
-
return makeError(1, `\u5904\u7406\u53C2\u8003\u56FE\u5931\u8D25: ${sourcePath}: ${message}`);
|
|
2637
|
-
} finally {
|
|
2638
|
-
await fs5.rm(tempDir, { recursive: true, force: true });
|
|
2639
|
-
}
|
|
2640
|
-
}
|
|
2641
|
-
async function readImageDimensions(sourcePath) {
|
|
2642
|
-
const { stdout } = await runSips([
|
|
2643
|
-
"-g",
|
|
2644
|
-
"pixelWidth",
|
|
2645
|
-
"-g",
|
|
2646
|
-
"pixelHeight",
|
|
2647
|
-
sourcePath
|
|
2648
|
-
]);
|
|
2649
|
-
const width = readSipsMetric(stdout, "pixelWidth");
|
|
2650
|
-
const height = readSipsMetric(stdout, "pixelHeight");
|
|
2651
|
-
if (!width || !height) {
|
|
2652
|
-
throw new Error("\u65E0\u6CD5\u8BFB\u53D6\u56FE\u7247\u5C3A\u5BF8");
|
|
2653
|
-
}
|
|
2654
|
-
return { width, height };
|
|
2655
|
-
}
|
|
2656
|
-
async function runSips(args) {
|
|
2657
|
-
return execFileAsync("/usr/bin/sips", [...args]);
|
|
2658
|
-
}
|
|
2659
|
-
function readSipsMetric(output, key) {
|
|
2660
|
-
const matcher = new RegExp(`${key}:\\s*(\\d+)`);
|
|
2661
|
-
const matched = output.match(matcher);
|
|
2662
|
-
if (!matched) {
|
|
2663
|
-
return void 0;
|
|
2664
|
-
}
|
|
2665
|
-
const value = Number.parseInt(matched[1], 10);
|
|
2666
|
-
return Number.isFinite(value) ? value : void 0;
|
|
2667
|
-
}
|
|
2668
|
-
function uniqueNumbers(values) {
|
|
2669
|
-
return [...new Set(values)];
|
|
2670
|
-
}
|
|
2671
|
-
function toDataUrl(mimeType, fileBytes) {
|
|
2672
|
-
const suffix = mimeType.replace("image/", "");
|
|
2673
|
-
return `data:image/${suffix};base64,${fileBytes.toString("base64")}`;
|
|
2674
|
-
}
|
|
2675
|
-
|
|
2676
|
-
// src/commands/ai/ai-image-command.ts
|
|
2677
|
-
var IMAGE_GENERATION_URL = "https://ark.cn-beijing.volces.com/api/v3/images/generations";
|
|
2678
|
-
var IMAGE_MODEL = "doubao-seedream-5-0-260128";
|
|
2679
|
-
var AiImageCommand = class extends AiBaseCommand {
|
|
2463
|
+
var GENERATED_IMAGES_DIR = path6.join(homedir7(), ".codex", "generated_images");
|
|
2464
|
+
var CODEX_EMPTY_WORKDIR = path6.join(homedir7(), ".codex-empty");
|
|
2465
|
+
var CREATED_AT_TOLERANCE_MS = 1e3;
|
|
2466
|
+
var AiImageCommandV2 = class extends AiBaseCommand {
|
|
2680
2467
|
_meta() {
|
|
2681
2468
|
return {
|
|
2682
2469
|
name: "image",
|
|
2683
|
-
description: "\
|
|
2470
|
+
description: "\u901A\u8FC7 codex exec \u751F\u6210\u56FE\u7247\uFF0C\u5E76\u8FD4\u56DE\u672C\u5730\u751F\u6210\u56FE\u7247\u8DEF\u5F84"
|
|
2684
2471
|
};
|
|
2685
2472
|
}
|
|
2686
|
-
_configureOptions(cmd) {
|
|
2687
|
-
cmd.addOption(
|
|
2688
|
-
new Option8(
|
|
2689
|
-
"-r, --reference <path>",
|
|
2690
|
-
"\u53C2\u8003\u56FE\u8DEF\u5F84\uFF0C\u53EF\u91CD\u590D\u4F20\u5165\uFF0C\u4E5F\u652F\u6301\u7528\u82F1\u6587\u9017\u53F7\u5206\u9694\u591A\u4E2A\u8DEF\u5F84"
|
|
2691
|
-
).argParser(parseReferencePaths).default([])
|
|
2692
|
-
);
|
|
2693
|
-
cmd.addOption(
|
|
2694
|
-
new Option8(
|
|
2695
|
-
"-s, --size <size>",
|
|
2696
|
-
"\u8F93\u51FA\u5C3A\u5BF8\uFF0C\u4F8B\u5982 1024x1024\u30012048x2048\u30012K"
|
|
2697
|
-
).default("2K")
|
|
2698
|
-
);
|
|
2699
|
-
cmd.addOption(
|
|
2700
|
-
new Option8("--output-format <format>", "\u751F\u6210\u56FE\u7247\u7F16\u7801\u683C\u5F0F").choices(["jpeg", "png", "webp"]).default("jpeg")
|
|
2701
|
-
);
|
|
2702
|
-
cmd.addOption(
|
|
2703
|
-
new Option8(
|
|
2704
|
-
"-o, --output <path>",
|
|
2705
|
-
"\u8F93\u51FA\u8DEF\u5F84\uFF0C\u53EF\u4F20\u6587\u4EF6\u8DEF\u5F84\u6216\u76EE\u5F55\u8DEF\u5F84\uFF1B\u672A\u4F20\u65F6\u9ED8\u8BA4\u5199\u5165\u5F53\u524D\u76EE\u5F55\u5E76\u81EA\u52A8\u547D\u540D"
|
|
2706
|
-
)
|
|
2707
|
-
);
|
|
2708
|
-
}
|
|
2709
2473
|
_configureArguments(cmd) {
|
|
2710
|
-
cmd.argument(
|
|
2474
|
+
cmd.argument(
|
|
2475
|
+
"[prompt...]",
|
|
2476
|
+
"\u751F\u56FE\u63D0\u793A\u8BCD\uFF1B\u5982\u6709\u53C2\u8003\u56FE\uFF0C\u9700\u5728 prompt \u4E2D\u7ED9\u51FA\u53C2\u8003\u56FE\u7684\u7EDD\u5BF9\u5730\u5740"
|
|
2477
|
+
);
|
|
2711
2478
|
}
|
|
2712
2479
|
async _execute(ctx) {
|
|
2713
2480
|
const prompt = this._readPrompt(ctx);
|
|
@@ -2715,250 +2482,162 @@ var AiImageCommand = class extends AiBaseCommand {
|
|
|
2715
2482
|
this._outputJsonError(1, "\u8BF7\u8F93\u5165\u751F\u56FE\u63D0\u793A\u8BCD");
|
|
2716
2483
|
return this._makeOk();
|
|
2717
2484
|
}
|
|
2718
|
-
const
|
|
2719
|
-
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
}
|
|
2723
|
-
const requestBody = {
|
|
2724
|
-
model: IMAGE_MODEL,
|
|
2725
|
-
prompt,
|
|
2726
|
-
size: ctx.options.size ?? "2K",
|
|
2727
|
-
response_format: "url",
|
|
2728
|
-
output_format: ctx.options.outputFormat,
|
|
2729
|
-
watermark: false,
|
|
2730
|
-
...referenceResult.value.length > 0 ? {
|
|
2731
|
-
image: referenceResult.value.map((item) => item.dataUrl)
|
|
2732
|
-
} : {}
|
|
2733
|
-
};
|
|
2734
|
-
const responseResult = await this._requestImage(requestBody);
|
|
2735
|
-
if (!responseResult.ok) {
|
|
2736
|
-
this._outputJsonError(responseResult.code, responseResult.msg);
|
|
2737
|
-
return this._makeOk();
|
|
2738
|
-
}
|
|
2739
|
-
const payload = responseResult.value;
|
|
2740
|
-
const remoteUrl = payload.data?.[0]?.url?.trim();
|
|
2741
|
-
if (!remoteUrl) {
|
|
2742
|
-
this._outputJsonError(1, "\u63A5\u53E3\u8C03\u7528\u6210\u529F\uFF0C\u4F46 data.[0].url \u4E3A\u7A7A");
|
|
2743
|
-
return this._makeOk();
|
|
2744
|
-
}
|
|
2745
|
-
const outputTargetResult = await resolveOutputTarget(
|
|
2746
|
-
ctx.options.output,
|
|
2747
|
-
ctx.options.outputFormat
|
|
2748
|
-
);
|
|
2749
|
-
if (!outputTargetResult.ok) {
|
|
2750
|
-
this._outputJsonError(outputTargetResult.code, outputTargetResult.msg);
|
|
2485
|
+
const startedAt = Date.now();
|
|
2486
|
+
const runResult = await this._runCodexImagePrompt(prompt);
|
|
2487
|
+
if (!runResult.ok) {
|
|
2488
|
+
this._outputJsonError(runResult.code, runResult.msg);
|
|
2751
2489
|
return this._makeOk();
|
|
2752
2490
|
}
|
|
2753
|
-
const
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
);
|
|
2757
|
-
if (!saveResult.ok) {
|
|
2758
|
-
this._outputJsonError(saveResult.code, saveResult.msg);
|
|
2491
|
+
const imagePathResult = await findLatestGeneratedImageFile(startedAt);
|
|
2492
|
+
if (!imagePathResult.ok) {
|
|
2493
|
+
this._outputJsonError(imagePathResult.code, imagePathResult.msg);
|
|
2759
2494
|
return this._makeOk();
|
|
2760
2495
|
}
|
|
2761
2496
|
this._outputJsonOk({
|
|
2762
|
-
image_path:
|
|
2497
|
+
image_path: imagePathResult.value
|
|
2763
2498
|
});
|
|
2764
2499
|
return this._makeOk();
|
|
2765
2500
|
}
|
|
2766
|
-
async
|
|
2767
|
-
const token = process.env.ARK_AK?.trim() || ARK_AK;
|
|
2768
|
-
if (!token) {
|
|
2769
|
-
return makeError(1, "\u7F3A\u5C11 ARK_AK\uFF0C\u8BF7\u5148\u914D\u7F6E\u53EF\u7528\u7684 API Key");
|
|
2770
|
-
}
|
|
2771
|
-
const controller = new AbortController();
|
|
2772
|
-
const timer = setTimeout(() => controller.abort(), 12e4);
|
|
2501
|
+
async _runCodexImagePrompt(prompt) {
|
|
2773
2502
|
try {
|
|
2774
|
-
|
|
2775
|
-
method: "POST",
|
|
2776
|
-
headers: {
|
|
2777
|
-
Authorization: `Bearer ${token}`,
|
|
2778
|
-
"Content-Type": "application/json"
|
|
2779
|
-
},
|
|
2780
|
-
body: JSON.stringify(requestBody),
|
|
2781
|
-
signal: controller.signal
|
|
2782
|
-
});
|
|
2783
|
-
const bodyText = await response.text();
|
|
2784
|
-
const payload = parseJsonSafely(bodyText);
|
|
2785
|
-
if (!response.ok) {
|
|
2786
|
-
const suffix = extractErrorMessage(payload) ?? bodyText.trim();
|
|
2787
|
-
return makeError(
|
|
2788
|
-
response.status,
|
|
2789
|
-
suffix ? `\u751F\u56FE\u63A5\u53E3\u8BF7\u6C42\u5931\u8D25: HTTP ${response.status}: ${suffix}` : `\u751F\u56FE\u63A5\u53E3\u8BF7\u6C42\u5931\u8D25: HTTP ${response.status}`
|
|
2790
|
-
);
|
|
2791
|
-
}
|
|
2792
|
-
if (!payload) {
|
|
2793
|
-
return makeError(1, "\u751F\u56FE\u63A5\u53E3\u8FD4\u56DE\u975E JSON \u54CD\u5E94");
|
|
2794
|
-
}
|
|
2795
|
-
if (hasFailedCode(payload.code)) {
|
|
2796
|
-
return makeError(
|
|
2797
|
-
1,
|
|
2798
|
-
extractErrorMessage(payload) ?? "\u751F\u56FE\u63A5\u53E3\u8FD4\u56DE\u9519\u8BEF"
|
|
2799
|
-
);
|
|
2800
|
-
}
|
|
2801
|
-
return makeOkWith(payload);
|
|
2503
|
+
await fs5.mkdir(CODEX_EMPTY_WORKDIR, { recursive: true });
|
|
2802
2504
|
} catch (error) {
|
|
2803
|
-
const message = error instanceof Error
|
|
2804
|
-
return
|
|
2805
|
-
|
|
2806
|
-
|
|
2505
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2506
|
+
return this._makeError(
|
|
2507
|
+
1,
|
|
2508
|
+
`\u521B\u5EFA codex \u7A7A\u5DE5\u4F5C\u76EE\u5F55\u5931\u8D25: ${CODEX_EMPTY_WORKDIR}: ${message}`
|
|
2509
|
+
);
|
|
2807
2510
|
}
|
|
2808
|
-
|
|
2809
|
-
}
|
|
2810
|
-
|
|
2811
|
-
|
|
2812
|
-
|
|
2813
|
-
|
|
2814
|
-
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2511
|
+
const codexPrompt = `\u751F\u6210\u56FE\u7247
|
|
2512
|
+
${prompt}`;
|
|
2513
|
+
const args = [
|
|
2514
|
+
"exec",
|
|
2515
|
+
"-C",
|
|
2516
|
+
CODEX_EMPTY_WORKDIR,
|
|
2517
|
+
"--skip-git-repo-check",
|
|
2518
|
+
"--ephemeral",
|
|
2519
|
+
"--dangerously-bypass-approvals-and-sandbox",
|
|
2520
|
+
codexPrompt
|
|
2521
|
+
];
|
|
2522
|
+
const child = spawn3("codex", args, {
|
|
2523
|
+
cwd: process.cwd(),
|
|
2524
|
+
stdio: "ignore"
|
|
2818
2525
|
});
|
|
2819
|
-
|
|
2820
|
-
|
|
2821
|
-
|
|
2822
|
-
|
|
2823
|
-
|
|
2824
|
-
|
|
2825
|
-
|
|
2826
|
-
|
|
2827
|
-
autoNamed: true
|
|
2526
|
+
return new Promise((resolve8) => {
|
|
2527
|
+
child.on("error", (error) => {
|
|
2528
|
+
resolve8(
|
|
2529
|
+
this._makeError(
|
|
2530
|
+
1,
|
|
2531
|
+
`\u6267\u884C codex ${args.join(" ")} \u5931\u8D25: ${error.message}`
|
|
2532
|
+
)
|
|
2533
|
+
);
|
|
2828
2534
|
});
|
|
2829
|
-
|
|
2830
|
-
|
|
2831
|
-
|
|
2832
|
-
|
|
2833
|
-
|
|
2834
|
-
|
|
2835
|
-
|
|
2836
|
-
|
|
2837
|
-
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
if (path7.extname(resolvedPath)) {
|
|
2842
|
-
return makeOkWith({
|
|
2843
|
-
directoryPath: path7.dirname(resolvedPath),
|
|
2844
|
-
filePath: resolvedPath,
|
|
2845
|
-
autoNamed: false
|
|
2535
|
+
child.on("close", (code, signal) => {
|
|
2536
|
+
if (code === 0) {
|
|
2537
|
+
resolve8(this._makeOk());
|
|
2538
|
+
return;
|
|
2539
|
+
}
|
|
2540
|
+
const signalText = signal ? `, signal: ${signal}` : "";
|
|
2541
|
+
resolve8(
|
|
2542
|
+
this._makeError(
|
|
2543
|
+
code ?? 1,
|
|
2544
|
+
`\u6267\u884C codex ${args.join(" ")} \u5931\u8D25${signalText}`
|
|
2545
|
+
)
|
|
2546
|
+
);
|
|
2846
2547
|
});
|
|
2847
|
-
}
|
|
2848
|
-
return makeOkWith({
|
|
2849
|
-
directoryPath: resolvedPath,
|
|
2850
|
-
filePath: path7.join(resolvedPath, buildAutoFileName(outputFormat)),
|
|
2851
|
-
autoNamed: true
|
|
2852
2548
|
});
|
|
2853
2549
|
}
|
|
2854
|
-
}
|
|
2855
|
-
async function
|
|
2856
|
-
|
|
2857
|
-
|
|
2858
|
-
|
|
2859
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
2860
|
-
return makeError(
|
|
2861
|
-
1,
|
|
2862
|
-
`\u521B\u5EFA\u8F93\u51FA\u76EE\u5F55\u5931\u8D25: ${target.directoryPath}: ${message}`
|
|
2863
|
-
);
|
|
2864
|
-
}
|
|
2865
|
-
let response;
|
|
2866
|
-
try {
|
|
2867
|
-
response = await fetch(remoteUrl);
|
|
2868
|
-
} catch (error) {
|
|
2869
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
2870
|
-
return makeError(1, `\u4E0B\u8F7D\u56FE\u7247\u5931\u8D25: ${message}`);
|
|
2871
|
-
}
|
|
2872
|
-
if (!response.ok) {
|
|
2873
|
-
return makeError(response.status, `\u4E0B\u8F7D\u56FE\u7247\u5931\u8D25: HTTP ${response.status}`);
|
|
2874
|
-
}
|
|
2875
|
-
const bytes = Buffer.from(await response.arrayBuffer());
|
|
2876
|
-
const targetPath = target.autoNamed ? replaceFileExtension(
|
|
2877
|
-
target.filePath,
|
|
2878
|
-
inferImageExtension(remoteUrl, response)
|
|
2879
|
-
) : target.filePath;
|
|
2880
|
-
try {
|
|
2881
|
-
await fs6.writeFile(targetPath, bytes);
|
|
2882
|
-
} catch (error) {
|
|
2883
|
-
const message = error instanceof Error ? error.message : String(error);
|
|
2884
|
-
return makeError(1, `\u5199\u5165\u56FE\u7247\u5931\u8D25: ${targetPath}: ${message}`);
|
|
2885
|
-
}
|
|
2886
|
-
return makeOkWith(path7.resolve(targetPath));
|
|
2887
|
-
}
|
|
2888
|
-
function parseReferencePaths(value, previous) {
|
|
2889
|
-
return previous.concat(
|
|
2890
|
-
value.split(",").map((item) => item.trim()).filter((item) => item.length > 0)
|
|
2550
|
+
};
|
|
2551
|
+
async function findLatestGeneratedImageFile(minCreatedAt) {
|
|
2552
|
+
const latestDirectoryResult = await findLatestCreatedDirectory(
|
|
2553
|
+
GENERATED_IMAGES_DIR,
|
|
2554
|
+
minCreatedAt
|
|
2891
2555
|
);
|
|
2556
|
+
if (!latestDirectoryResult.ok) {
|
|
2557
|
+
return latestDirectoryResult;
|
|
2558
|
+
}
|
|
2559
|
+
return findLatestCreatedFile(latestDirectoryResult.value);
|
|
2892
2560
|
}
|
|
2893
|
-
function
|
|
2894
|
-
|
|
2895
|
-
|
|
2561
|
+
async function findLatestCreatedDirectory(directoryPath, minCreatedAt) {
|
|
2562
|
+
const entriesResult = await readDirectoryEntries(directoryPath);
|
|
2563
|
+
if (!entriesResult.ok) {
|
|
2564
|
+
return entriesResult;
|
|
2896
2565
|
}
|
|
2897
|
-
|
|
2898
|
-
|
|
2899
|
-
|
|
2900
|
-
|
|
2566
|
+
const directories = await collectCreatedEntries(
|
|
2567
|
+
directoryPath,
|
|
2568
|
+
entriesResult.value.filter((entry) => entry.isDirectory()).map((entry) => entry.name)
|
|
2569
|
+
);
|
|
2570
|
+
if (!directories.ok) {
|
|
2571
|
+
return directories;
|
|
2572
|
+
}
|
|
2573
|
+
const latest = directories.value.filter(
|
|
2574
|
+
(entry) => entry.createdAt >= minCreatedAt - CREATED_AT_TOLERANCE_MS
|
|
2575
|
+
).sort(compareCreatedEntryDesc)[0];
|
|
2576
|
+
if (!latest) {
|
|
2577
|
+
return makeErrorForPath(
|
|
2578
|
+
1,
|
|
2579
|
+
"\u672A\u627E\u5230\u672C\u6B21 codex \u751F\u56FE\u8F93\u51FA\u5B50\u76EE\u5F55",
|
|
2580
|
+
directoryPath
|
|
2581
|
+
);
|
|
2901
2582
|
}
|
|
2583
|
+
return makeOkWith(latest.filePath);
|
|
2902
2584
|
}
|
|
2903
|
-
function
|
|
2904
|
-
|
|
2905
|
-
|
|
2585
|
+
async function findLatestCreatedFile(directoryPath) {
|
|
2586
|
+
const entriesResult = await readDirectoryEntries(directoryPath);
|
|
2587
|
+
if (!entriesResult.ok) {
|
|
2588
|
+
return entriesResult;
|
|
2906
2589
|
}
|
|
2907
|
-
|
|
2908
|
-
|
|
2590
|
+
const files = await collectCreatedEntries(
|
|
2591
|
+
directoryPath,
|
|
2592
|
+
entriesResult.value.filter((entry) => entry.isFile()).map((entry) => entry.name)
|
|
2593
|
+
);
|
|
2594
|
+
if (!files.ok) {
|
|
2595
|
+
return files;
|
|
2909
2596
|
}
|
|
2910
|
-
const
|
|
2911
|
-
|
|
2912
|
-
|
|
2913
|
-
function extractErrorMessage(payload) {
|
|
2914
|
-
if (!payload) {
|
|
2915
|
-
return void 0;
|
|
2597
|
+
const latest = files.value.sort(compareCreatedEntryDesc)[0];
|
|
2598
|
+
if (!latest) {
|
|
2599
|
+
return makeErrorForPath(1, "\u6700\u65B0\u751F\u56FE\u8F93\u51FA\u76EE\u5F55\u4E2D\u672A\u627E\u5230\u6587\u4EF6", directoryPath);
|
|
2916
2600
|
}
|
|
2917
|
-
|
|
2918
|
-
return message || void 0;
|
|
2919
|
-
}
|
|
2920
|
-
function buildAutoFileName(outputFormat) {
|
|
2921
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
2922
|
-
return `ai-image-${timestamp}.${outputFormat}`;
|
|
2601
|
+
return makeOkWith(path6.resolve(latest.filePath));
|
|
2923
2602
|
}
|
|
2924
|
-
function
|
|
2925
|
-
|
|
2926
|
-
|
|
2927
|
-
|
|
2603
|
+
async function readDirectoryEntries(directoryPath) {
|
|
2604
|
+
try {
|
|
2605
|
+
return makeOkWith(await fs5.readdir(directoryPath, { withFileTypes: true }));
|
|
2606
|
+
} catch (error) {
|
|
2607
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2608
|
+
return makeErrorForPath(1, `\u8BFB\u53D6\u76EE\u5F55\u5931\u8D25: ${message}`, directoryPath);
|
|
2928
2609
|
}
|
|
2929
|
-
return `${filePath.slice(0, -ext.length)}.${extension}`;
|
|
2930
2610
|
}
|
|
2931
|
-
function
|
|
2932
|
-
const
|
|
2933
|
-
|
|
2934
|
-
|
|
2935
|
-
|
|
2936
|
-
|
|
2937
|
-
|
|
2938
|
-
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
const ext = path7.extname(url.pathname).toLowerCase();
|
|
2945
|
-
if (ext === ".png") {
|
|
2946
|
-
return "png";
|
|
2947
|
-
}
|
|
2948
|
-
if (ext === ".webp") {
|
|
2949
|
-
return "webp";
|
|
2950
|
-
}
|
|
2951
|
-
if (ext === ".jpg" || ext === ".jpeg") {
|
|
2952
|
-
return "jpeg";
|
|
2611
|
+
async function collectCreatedEntries(parentPath, names) {
|
|
2612
|
+
const entries = [];
|
|
2613
|
+
for (const name of names) {
|
|
2614
|
+
const filePath = path6.join(parentPath, name);
|
|
2615
|
+
try {
|
|
2616
|
+
const stats = await fs5.stat(filePath);
|
|
2617
|
+
entries.push({
|
|
2618
|
+
filePath,
|
|
2619
|
+
createdAt: getCreatedAt(stats)
|
|
2620
|
+
});
|
|
2621
|
+
} catch (error) {
|
|
2622
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2623
|
+
return makeErrorForPath(1, `\u8BFB\u53D6\u8DEF\u5F84\u72B6\u6001\u5931\u8D25: ${message}`, filePath);
|
|
2953
2624
|
}
|
|
2954
|
-
} catch {
|
|
2955
2625
|
}
|
|
2956
|
-
return
|
|
2626
|
+
return makeOkWith(entries);
|
|
2627
|
+
}
|
|
2628
|
+
function getCreatedAt(stats) {
|
|
2629
|
+
return stats.birthtimeMs || stats.ctimeMs || stats.mtimeMs;
|
|
2630
|
+
}
|
|
2631
|
+
function compareCreatedEntryDesc(a, b) {
|
|
2632
|
+
return b.createdAt - a.createdAt || b.filePath.localeCompare(a.filePath);
|
|
2633
|
+
}
|
|
2634
|
+
function makeErrorForPath(code, message, filePath) {
|
|
2635
|
+
return makeError(code, `${message}: ${filePath}`);
|
|
2957
2636
|
}
|
|
2958
2637
|
|
|
2959
2638
|
// src/commands/ai/ai-video-command.ts
|
|
2960
|
-
import * as
|
|
2961
|
-
import { Option as
|
|
2639
|
+
import * as path7 from "path";
|
|
2640
|
+
import { Option as Option8 } from "commander";
|
|
2962
2641
|
|
|
2963
2642
|
// src/bedrock/uuid/uuid.ts
|
|
2964
2643
|
var generateUuid = (() => {
|
|
@@ -3150,10 +2829,10 @@ var AiVideoCommand = class extends AiBaseCommand {
|
|
|
3150
2829
|
}
|
|
3151
2830
|
_configureOptions(cmd) {
|
|
3152
2831
|
cmd.addOption(
|
|
3153
|
-
new
|
|
2832
|
+
new Option8(
|
|
3154
2833
|
"-r, --reference <path>",
|
|
3155
2834
|
"\u53C2\u8003\u56FE\u7247\u6216\u89C6\u9891\u8DEF\u5F84\uFF0C\u53EF\u91CD\u590D\u4F20\u5165\uFF0C\u4E5F\u652F\u6301\u7528\u82F1\u6587\u9017\u53F7\u5206\u9694\u591A\u4E2A\u8DEF\u5F84"
|
|
3156
|
-
).argParser(
|
|
2835
|
+
).argParser(parseReferencePaths).default([])
|
|
3157
2836
|
);
|
|
3158
2837
|
}
|
|
3159
2838
|
_configureArguments(cmd) {
|
|
@@ -3201,7 +2880,7 @@ var AiVideoCommand = class extends AiBaseCommand {
|
|
|
3201
2880
|
return makeOkWith({
|
|
3202
2881
|
asset_id: result.value.assetId,
|
|
3203
2882
|
asset_type: result.value.fileInfo.assetType,
|
|
3204
|
-
file_path:
|
|
2883
|
+
file_path: path7.resolve(process.cwd(), referencePath),
|
|
3205
2884
|
region: result.value.region
|
|
3206
2885
|
});
|
|
3207
2886
|
})
|
|
@@ -3221,7 +2900,7 @@ var AiVideoCommand = class extends AiBaseCommand {
|
|
|
3221
2900
|
});
|
|
3222
2901
|
}
|
|
3223
2902
|
};
|
|
3224
|
-
function
|
|
2903
|
+
function parseReferencePaths(value, previous) {
|
|
3225
2904
|
return previous.concat(
|
|
3226
2905
|
value.split(",").map((item) => item.trim()).filter((item) => item.length > 0)
|
|
3227
2906
|
);
|
|
@@ -3230,7 +2909,240 @@ function parseReferencePaths2(value, previous) {
|
|
|
3230
2909
|
// src/commands/ai/ai-vid-command.ts
|
|
3231
2910
|
import * as fs7 from "fs/promises";
|
|
3232
2911
|
import * as path9 from "path";
|
|
3233
|
-
import { Option as
|
|
2912
|
+
import { Option as Option9 } from "commander";
|
|
2913
|
+
|
|
2914
|
+
// src/commands/ai/ai-image-reference.ts
|
|
2915
|
+
import * as fs6 from "fs/promises";
|
|
2916
|
+
import * as os2 from "os";
|
|
2917
|
+
import * as path8 from "path";
|
|
2918
|
+
import { execFile } from "child_process";
|
|
2919
|
+
import { promisify } from "util";
|
|
2920
|
+
var execFileAsync = promisify(execFile);
|
|
2921
|
+
var MAX_REFERENCE_IMAGE_BYTES = 2 * 1024 * 1024;
|
|
2922
|
+
var MAX_REFERENCE_IMAGE_COUNT = 14;
|
|
2923
|
+
var API_SUPPORTED_MIME_TYPES = /* @__PURE__ */ new Set([
|
|
2924
|
+
"image/jpeg",
|
|
2925
|
+
"image/png",
|
|
2926
|
+
"image/webp",
|
|
2927
|
+
"image/bmp",
|
|
2928
|
+
"image/tiff",
|
|
2929
|
+
"image/gif"
|
|
2930
|
+
]);
|
|
2931
|
+
async function prepareReferenceImages(filePaths) {
|
|
2932
|
+
if (filePaths.length > MAX_REFERENCE_IMAGE_COUNT) {
|
|
2933
|
+
return makeError(
|
|
2934
|
+
1,
|
|
2935
|
+
`\u53C2\u8003\u56FE\u6700\u591A\u652F\u6301 ${MAX_REFERENCE_IMAGE_COUNT} \u5F20\uFF0C\u5F53\u524D\u4F20\u5165 ${filePaths.length} \u5F20\u3002`
|
|
2936
|
+
);
|
|
2937
|
+
}
|
|
2938
|
+
const preparedImages = [];
|
|
2939
|
+
for (const filePath of filePaths) {
|
|
2940
|
+
const prepared = await prepareReferenceImage(filePath);
|
|
2941
|
+
if (!prepared.ok) {
|
|
2942
|
+
return prepared;
|
|
2943
|
+
}
|
|
2944
|
+
preparedImages.push(prepared.value);
|
|
2945
|
+
}
|
|
2946
|
+
return makeOkWith(preparedImages);
|
|
2947
|
+
}
|
|
2948
|
+
async function prepareReferenceImage(filePath) {
|
|
2949
|
+
const resolvedPath = path8.resolve(process.cwd(), filePath);
|
|
2950
|
+
let stats;
|
|
2951
|
+
try {
|
|
2952
|
+
stats = await fs6.stat(resolvedPath);
|
|
2953
|
+
} catch (error) {
|
|
2954
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2955
|
+
return makeError(1, `\u8BFB\u53D6\u53C2\u8003\u56FE\u5931\u8D25: ${resolvedPath}: ${message}`);
|
|
2956
|
+
}
|
|
2957
|
+
if (!stats.isFile()) {
|
|
2958
|
+
return makeError(1, `\u53C2\u8003\u56FE\u4E0D\u662F\u6587\u4EF6: ${resolvedPath}`);
|
|
2959
|
+
}
|
|
2960
|
+
let fileBytes;
|
|
2961
|
+
try {
|
|
2962
|
+
fileBytes = await fs6.readFile(resolvedPath);
|
|
2963
|
+
} catch (error) {
|
|
2964
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
2965
|
+
return makeError(1, `\u8BFB\u53D6\u53C2\u8003\u56FE\u5185\u5BB9\u5931\u8D25: ${resolvedPath}: ${message}`);
|
|
2966
|
+
}
|
|
2967
|
+
const detectedType = detectMimeType(fileBytes, resolvedPath);
|
|
2968
|
+
if (!detectedType) {
|
|
2969
|
+
return makeError(1, `\u53C2\u8003\u56FE\u4E0D\u662F\u652F\u6301\u7684\u56FE\u7247\u683C\u5F0F: ${resolvedPath}`);
|
|
2970
|
+
}
|
|
2971
|
+
const needsTranscode = !API_SUPPORTED_MIME_TYPES.has(detectedType.mimeType) || fileBytes.byteLength > MAX_REFERENCE_IMAGE_BYTES;
|
|
2972
|
+
if (!needsTranscode) {
|
|
2973
|
+
return makeOkWith({
|
|
2974
|
+
inputPath: filePath,
|
|
2975
|
+
resolvedPath,
|
|
2976
|
+
sourceMimeType: detectedType.mimeType,
|
|
2977
|
+
requestMimeType: detectedType.mimeType,
|
|
2978
|
+
originalBytes: fileBytes.byteLength,
|
|
2979
|
+
finalBytes: fileBytes.byteLength,
|
|
2980
|
+
compressed: false,
|
|
2981
|
+
dataUrl: toDataUrl(detectedType.mimeType, fileBytes)
|
|
2982
|
+
});
|
|
2983
|
+
}
|
|
2984
|
+
const compressed = await compressImageForReference(resolvedPath);
|
|
2985
|
+
if (!compressed.ok) {
|
|
2986
|
+
return compressed;
|
|
2987
|
+
}
|
|
2988
|
+
return makeOkWith({
|
|
2989
|
+
inputPath: filePath,
|
|
2990
|
+
resolvedPath,
|
|
2991
|
+
sourceMimeType: detectedType.mimeType,
|
|
2992
|
+
requestMimeType: compressed.value.mimeType,
|
|
2993
|
+
originalBytes: fileBytes.byteLength,
|
|
2994
|
+
finalBytes: compressed.value.bytes.byteLength,
|
|
2995
|
+
compressed: true,
|
|
2996
|
+
dataUrl: toDataUrl(compressed.value.mimeType, compressed.value.bytes)
|
|
2997
|
+
});
|
|
2998
|
+
}
|
|
2999
|
+
function detectMimeType(fileBytes, filePath) {
|
|
3000
|
+
if (fileBytes.length >= 3 && fileBytes[0] === 255 && fileBytes[1] === 216 && fileBytes[2] === 255) {
|
|
3001
|
+
return { mimeType: "image/jpeg", extension: "jpeg" };
|
|
3002
|
+
}
|
|
3003
|
+
if (fileBytes.length >= 8 && fileBytes[0] === 137 && fileBytes[1] === 80 && fileBytes[2] === 78 && fileBytes[3] === 71 && fileBytes[4] === 13 && fileBytes[5] === 10 && fileBytes[6] === 26 && fileBytes[7] === 10) {
|
|
3004
|
+
return { mimeType: "image/png", extension: "png" };
|
|
3005
|
+
}
|
|
3006
|
+
if (fileBytes.length >= 6) {
|
|
3007
|
+
const gifHeader = fileBytes.subarray(0, 6).toString("ascii");
|
|
3008
|
+
if (gifHeader === "GIF87a" || gifHeader === "GIF89a") {
|
|
3009
|
+
return { mimeType: "image/gif", extension: "gif" };
|
|
3010
|
+
}
|
|
3011
|
+
}
|
|
3012
|
+
if (fileBytes.length >= 12 && fileBytes.subarray(0, 4).toString("ascii") === "RIFF" && fileBytes.subarray(8, 12).toString("ascii") === "WEBP") {
|
|
3013
|
+
return { mimeType: "image/webp", extension: "webp" };
|
|
3014
|
+
}
|
|
3015
|
+
if (fileBytes.length >= 2 && fileBytes.subarray(0, 2).toString("ascii") === "BM") {
|
|
3016
|
+
return { mimeType: "image/bmp", extension: "bmp" };
|
|
3017
|
+
}
|
|
3018
|
+
if (fileBytes.length >= 4 && (fileBytes[0] === 73 && fileBytes[1] === 73 && fileBytes[2] === 42 && fileBytes[3] === 0 || fileBytes[0] === 77 && fileBytes[1] === 77 && fileBytes[2] === 0 && fileBytes[3] === 42)) {
|
|
3019
|
+
return { mimeType: "image/tiff", extension: "tiff" };
|
|
3020
|
+
}
|
|
3021
|
+
if (fileBytes.length >= 12 && fileBytes.subarray(4, 8).toString("ascii") === "ftyp") {
|
|
3022
|
+
const brand = fileBytes.subarray(8, 12).toString("ascii").trim();
|
|
3023
|
+
if (brand.startsWith("avif") || brand === "avis") {
|
|
3024
|
+
return { mimeType: "image/avif", extension: "avif" };
|
|
3025
|
+
}
|
|
3026
|
+
if (brand.startsWith("hei") || brand.startsWith("hev") || brand === "mif1" || brand === "msf1") {
|
|
3027
|
+
return { mimeType: "image/heic", extension: "heic" };
|
|
3028
|
+
}
|
|
3029
|
+
}
|
|
3030
|
+
const ext = path8.extname(filePath).toLowerCase();
|
|
3031
|
+
switch (ext) {
|
|
3032
|
+
case ".jpg":
|
|
3033
|
+
case ".jpeg":
|
|
3034
|
+
return { mimeType: "image/jpeg", extension: "jpeg" };
|
|
3035
|
+
case ".png":
|
|
3036
|
+
return { mimeType: "image/png", extension: "png" };
|
|
3037
|
+
case ".gif":
|
|
3038
|
+
return { mimeType: "image/gif", extension: "gif" };
|
|
3039
|
+
case ".webp":
|
|
3040
|
+
return { mimeType: "image/webp", extension: "webp" };
|
|
3041
|
+
case ".bmp":
|
|
3042
|
+
return { mimeType: "image/bmp", extension: "bmp" };
|
|
3043
|
+
case ".tif":
|
|
3044
|
+
case ".tiff":
|
|
3045
|
+
return { mimeType: "image/tiff", extension: "tiff" };
|
|
3046
|
+
case ".heic":
|
|
3047
|
+
case ".heif":
|
|
3048
|
+
return { mimeType: "image/heic", extension: "heic" };
|
|
3049
|
+
case ".avif":
|
|
3050
|
+
return { mimeType: "image/avif", extension: "avif" };
|
|
3051
|
+
default:
|
|
3052
|
+
return void 0;
|
|
3053
|
+
}
|
|
3054
|
+
}
|
|
3055
|
+
async function compressImageForReference(sourcePath) {
|
|
3056
|
+
if (process.platform !== "darwin") {
|
|
3057
|
+
return makeError(
|
|
3058
|
+
1,
|
|
3059
|
+
`\u53C2\u8003\u56FE\u9700\u8981\u538B\u7F29\u6216\u8F6C\u7801\uFF0C\u4F46\u5F53\u524D\u5E73\u53F0 ${process.platform} \u672A\u5B9E\u73B0\u81EA\u52A8\u5904\u7406\u3002`
|
|
3060
|
+
);
|
|
3061
|
+
}
|
|
3062
|
+
const tempDir = await fs6.mkdtemp(path8.join(os2.tmpdir(), "tt-ai-image-"));
|
|
3063
|
+
try {
|
|
3064
|
+
const dimensions = await readImageDimensions(sourcePath);
|
|
3065
|
+
const maxDimension = Math.max(dimensions.width, dimensions.height);
|
|
3066
|
+
const resizeLimits = uniqueNumbers([
|
|
3067
|
+
maxDimension,
|
|
3068
|
+
Math.floor(maxDimension * 0.85),
|
|
3069
|
+
Math.floor(maxDimension * 0.7),
|
|
3070
|
+
Math.floor(maxDimension * 0.55),
|
|
3071
|
+
Math.floor(maxDimension * 0.4)
|
|
3072
|
+
]).filter((value) => value >= 64);
|
|
3073
|
+
const qualityLevels = [85, 75, 65, 55, 45, 35];
|
|
3074
|
+
let attemptIndex = 0;
|
|
3075
|
+
for (const resizeLimit of resizeLimits) {
|
|
3076
|
+
for (const quality of qualityLevels) {
|
|
3077
|
+
const targetPath = path8.join(tempDir, `compressed-${attemptIndex}.jpeg`);
|
|
3078
|
+
attemptIndex += 1;
|
|
3079
|
+
await runSips([
|
|
3080
|
+
"--setProperty",
|
|
3081
|
+
"format",
|
|
3082
|
+
"jpeg",
|
|
3083
|
+
"--setProperty",
|
|
3084
|
+
"formatOptions",
|
|
3085
|
+
String(quality),
|
|
3086
|
+
sourcePath,
|
|
3087
|
+
"--out",
|
|
3088
|
+
targetPath
|
|
3089
|
+
]);
|
|
3090
|
+
if (resizeLimit < maxDimension) {
|
|
3091
|
+
await runSips(["-Z", String(resizeLimit), targetPath]);
|
|
3092
|
+
}
|
|
3093
|
+
const compressedBytes = await fs6.readFile(targetPath);
|
|
3094
|
+
if (compressedBytes.byteLength <= MAX_REFERENCE_IMAGE_BYTES) {
|
|
3095
|
+
return makeOkWith({
|
|
3096
|
+
mimeType: "image/jpeg",
|
|
3097
|
+
bytes: compressedBytes
|
|
3098
|
+
});
|
|
3099
|
+
}
|
|
3100
|
+
}
|
|
3101
|
+
}
|
|
3102
|
+
return makeError(1, `\u53C2\u8003\u56FE\u538B\u7F29\u5931\u8D25\uFF0C\u65E0\u6CD5\u538B\u7F29\u5230 2MB \u4EE5\u5185: ${sourcePath}`);
|
|
3103
|
+
} catch (error) {
|
|
3104
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
3105
|
+
return makeError(1, `\u5904\u7406\u53C2\u8003\u56FE\u5931\u8D25: ${sourcePath}: ${message}`);
|
|
3106
|
+
} finally {
|
|
3107
|
+
await fs6.rm(tempDir, { recursive: true, force: true });
|
|
3108
|
+
}
|
|
3109
|
+
}
|
|
3110
|
+
async function readImageDimensions(sourcePath) {
|
|
3111
|
+
const { stdout } = await runSips([
|
|
3112
|
+
"-g",
|
|
3113
|
+
"pixelWidth",
|
|
3114
|
+
"-g",
|
|
3115
|
+
"pixelHeight",
|
|
3116
|
+
sourcePath
|
|
3117
|
+
]);
|
|
3118
|
+
const width = readSipsMetric(stdout, "pixelWidth");
|
|
3119
|
+
const height = readSipsMetric(stdout, "pixelHeight");
|
|
3120
|
+
if (!width || !height) {
|
|
3121
|
+
throw new Error("\u65E0\u6CD5\u8BFB\u53D6\u56FE\u7247\u5C3A\u5BF8");
|
|
3122
|
+
}
|
|
3123
|
+
return { width, height };
|
|
3124
|
+
}
|
|
3125
|
+
async function runSips(args) {
|
|
3126
|
+
return execFileAsync("/usr/bin/sips", [...args]);
|
|
3127
|
+
}
|
|
3128
|
+
function readSipsMetric(output, key) {
|
|
3129
|
+
const matcher = new RegExp(`${key}:\\s*(\\d+)`);
|
|
3130
|
+
const matched = output.match(matcher);
|
|
3131
|
+
if (!matched) {
|
|
3132
|
+
return void 0;
|
|
3133
|
+
}
|
|
3134
|
+
const value = Number.parseInt(matched[1], 10);
|
|
3135
|
+
return Number.isFinite(value) ? value : void 0;
|
|
3136
|
+
}
|
|
3137
|
+
function uniqueNumbers(values) {
|
|
3138
|
+
return [...new Set(values)];
|
|
3139
|
+
}
|
|
3140
|
+
function toDataUrl(mimeType, fileBytes) {
|
|
3141
|
+
const suffix = mimeType.replace("image/", "");
|
|
3142
|
+
return `data:image/${suffix};base64,${fileBytes.toString("base64")}`;
|
|
3143
|
+
}
|
|
3144
|
+
|
|
3145
|
+
// src/commands/ai/ai-vid-command.ts
|
|
3234
3146
|
var VIDEO_GENERATION_URL = "https://openrouter.ai/api/v1/videos";
|
|
3235
3147
|
var VIDEO_MODEL = "bytedance/seedance-2.0";
|
|
3236
3148
|
var POLLING_LOG_FILE_NAME = "ai-vid-polling.log";
|
|
@@ -3248,34 +3160,34 @@ var AiVidCommand = class extends AiBaseCommand {
|
|
|
3248
3160
|
}
|
|
3249
3161
|
_configureOptions(cmd) {
|
|
3250
3162
|
cmd.addOption(
|
|
3251
|
-
new
|
|
3163
|
+
new Option9(
|
|
3252
3164
|
"-r, --reference <path>",
|
|
3253
3165
|
"\u53C2\u8003\u56FE\u7247\u672C\u5730\u8DEF\u5F84\uFF0C\u53EF\u91CD\u590D\u4F20\u5165\uFF0C\u4E5F\u652F\u6301\u7528\u82F1\u6587\u9017\u53F7\u5206\u9694\u591A\u4E2A\u8DEF\u5F84\uFF1B\u6700\u7EC8\u8F6C\u4E3A base64 data URL"
|
|
3254
|
-
).argParser(
|
|
3166
|
+
).argParser(parseReferencePaths2).default([])
|
|
3255
3167
|
);
|
|
3256
3168
|
cmd.addOption(
|
|
3257
|
-
new
|
|
3169
|
+
new Option9("--resolution <resolution>", "\u89C6\u9891\u5206\u8FA8\u7387").choices(["480p", "720p"]).default("480p")
|
|
3258
3170
|
);
|
|
3259
3171
|
cmd.addOption(
|
|
3260
|
-
new
|
|
3172
|
+
new Option9(
|
|
3261
3173
|
"--aspect-ratio <ratio>",
|
|
3262
3174
|
"\u89C6\u9891\u957F\u5BBD\u6BD4\uFF0C\u4F8B\u5982 16:9\u30019:16\u30011:1\uFF0C\u7F3A\u7701\u4E0D\u6307\u5B9A"
|
|
3263
3175
|
)
|
|
3264
3176
|
);
|
|
3265
3177
|
cmd.addOption(
|
|
3266
|
-
new
|
|
3178
|
+
new Option9(
|
|
3267
3179
|
"--duration <seconds>",
|
|
3268
3180
|
"\u89C6\u9891\u65F6\u957F\uFF08\u79D2\uFF09\uFF0C\u7F3A\u7701\u4E0D\u6307\u5B9A"
|
|
3269
3181
|
).argParser(parseDuration)
|
|
3270
3182
|
);
|
|
3271
3183
|
cmd.addOption(
|
|
3272
|
-
new
|
|
3184
|
+
new Option9(
|
|
3273
3185
|
"--polling-only",
|
|
3274
3186
|
"\u4EC5\u63D0\u4EA4\u5E76\u8FD4\u56DE polling_url\uFF0C\u4E0D\u5728\u672C\u5730\u8F6E\u8BE2\u7ED3\u679C"
|
|
3275
3187
|
).default(false)
|
|
3276
3188
|
);
|
|
3277
3189
|
cmd.addOption(
|
|
3278
|
-
new
|
|
3190
|
+
new Option9(
|
|
3279
3191
|
"-o, --output <path>",
|
|
3280
3192
|
"\u89C6\u9891\u4E0B\u8F7D\u8F93\u51FA\u8DEF\u5F84\uFF0C\u53EF\u4F20\u6587\u4EF6\u8DEF\u5F84\u6216\u76EE\u5F55\u8DEF\u5F84\uFF1B\u672A\u4F20\u65F6\u9ED8\u8BA4\u5199\u5165\u5F53\u524D\u76EE\u5F55\u5E76\u81EA\u52A8\u547D\u540D"
|
|
3281
3193
|
)
|
|
@@ -3351,7 +3263,7 @@ var AiVidCommand = class extends AiBaseCommand {
|
|
|
3351
3263
|
this._outputJsonError(1, "\u89C6\u9891\u751F\u6210\u5B8C\u6210\uFF0C\u4F46\u672A\u62FF\u5230 unsigned_urls[0]");
|
|
3352
3264
|
return this._makeOk();
|
|
3353
3265
|
}
|
|
3354
|
-
const outputTargetResult = await
|
|
3266
|
+
const outputTargetResult = await resolveOutputTarget(ctx.options.output);
|
|
3355
3267
|
if (!outputTargetResult.ok) {
|
|
3356
3268
|
this._outputJsonError(outputTargetResult.code, outputTargetResult.msg);
|
|
3357
3269
|
return this._makeOk();
|
|
@@ -3395,7 +3307,7 @@ var AiVidCommand = class extends AiBaseCommand {
|
|
|
3395
3307
|
clearTimeout(timer);
|
|
3396
3308
|
}
|
|
3397
3309
|
const bodyText = await response.text().catch(() => "");
|
|
3398
|
-
const payload =
|
|
3310
|
+
const payload = parseJsonSafely(bodyText);
|
|
3399
3311
|
if (!response.ok) {
|
|
3400
3312
|
const detail = extractErrorText(payload) ?? bodyText.trim();
|
|
3401
3313
|
const suffix = detail ? `: ${detail}` : "";
|
|
@@ -3441,7 +3353,7 @@ var AiVidCommand = class extends AiBaseCommand {
|
|
|
3441
3353
|
continue;
|
|
3442
3354
|
}
|
|
3443
3355
|
const bodyText = await response.text().catch(() => "");
|
|
3444
|
-
const payload =
|
|
3356
|
+
const payload = parseJsonSafely(bodyText);
|
|
3445
3357
|
if (!response.ok) {
|
|
3446
3358
|
const detail = extractErrorText(payload) ?? bodyText.trim();
|
|
3447
3359
|
return makeError(
|
|
@@ -3476,7 +3388,7 @@ var AiVidCommand = class extends AiBaseCommand {
|
|
|
3476
3388
|
function resolveOpenRouterToken() {
|
|
3477
3389
|
return process.env.OPENROUTER_AK?.trim() || OPENROUTER_AK;
|
|
3478
3390
|
}
|
|
3479
|
-
function
|
|
3391
|
+
function parseReferencePaths2(value, previous) {
|
|
3480
3392
|
return previous.concat(
|
|
3481
3393
|
value.split(",").map((item) => item.trim()).filter((item) => item.length > 0)
|
|
3482
3394
|
);
|
|
@@ -3488,7 +3400,7 @@ function parseDuration(value) {
|
|
|
3488
3400
|
}
|
|
3489
3401
|
return parsed;
|
|
3490
3402
|
}
|
|
3491
|
-
function
|
|
3403
|
+
function parseJsonSafely(text) {
|
|
3492
3404
|
if (!text.trim()) {
|
|
3493
3405
|
return void 0;
|
|
3494
3406
|
}
|
|
@@ -3540,12 +3452,12 @@ async function appendPollingUrl(pollingUrl, generationId) {
|
|
|
3540
3452
|
return makeError(1, `\u5199\u5165 polling \u65E5\u5FD7\u5931\u8D25 ${logFilePath}: ${message}`);
|
|
3541
3453
|
}
|
|
3542
3454
|
}
|
|
3543
|
-
async function
|
|
3455
|
+
async function resolveOutputTarget(outputPath) {
|
|
3544
3456
|
if (!outputPath) {
|
|
3545
3457
|
const directoryPath = process.cwd();
|
|
3546
3458
|
return makeOkWith({
|
|
3547
3459
|
directoryPath,
|
|
3548
|
-
filePath: path9.join(directoryPath,
|
|
3460
|
+
filePath: path9.join(directoryPath, buildAutoFileName()),
|
|
3549
3461
|
autoNamed: true
|
|
3550
3462
|
});
|
|
3551
3463
|
}
|
|
@@ -3555,7 +3467,7 @@ async function resolveOutputTarget2(outputPath) {
|
|
|
3555
3467
|
if (stats.isDirectory()) {
|
|
3556
3468
|
return makeOkWith({
|
|
3557
3469
|
directoryPath: resolvedPath,
|
|
3558
|
-
filePath: path9.join(resolvedPath,
|
|
3470
|
+
filePath: path9.join(resolvedPath, buildAutoFileName()),
|
|
3559
3471
|
autoNamed: true
|
|
3560
3472
|
});
|
|
3561
3473
|
}
|
|
@@ -3579,7 +3491,7 @@ async function resolveOutputTarget2(outputPath) {
|
|
|
3579
3491
|
}
|
|
3580
3492
|
return makeOkWith({
|
|
3581
3493
|
directoryPath: resolvedPath,
|
|
3582
|
-
filePath: path9.join(resolvedPath,
|
|
3494
|
+
filePath: path9.join(resolvedPath, buildAutoFileName()),
|
|
3583
3495
|
autoNamed: true
|
|
3584
3496
|
});
|
|
3585
3497
|
}
|
|
@@ -3617,7 +3529,7 @@ async function downloadVideoToFile(remoteUrl, target, token) {
|
|
|
3617
3529
|
);
|
|
3618
3530
|
}
|
|
3619
3531
|
const bytes = Buffer.from(await response.arrayBuffer());
|
|
3620
|
-
const targetPath = target.autoNamed ?
|
|
3532
|
+
const targetPath = target.autoNamed ? replaceFileExtension(
|
|
3621
3533
|
target.filePath,
|
|
3622
3534
|
inferVideoExtension(remoteUrl, response)
|
|
3623
3535
|
) : target.filePath;
|
|
@@ -3629,11 +3541,11 @@ async function downloadVideoToFile(remoteUrl, target, token) {
|
|
|
3629
3541
|
}
|
|
3630
3542
|
return makeOkWith(path9.resolve(targetPath));
|
|
3631
3543
|
}
|
|
3632
|
-
function
|
|
3544
|
+
function buildAutoFileName() {
|
|
3633
3545
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
3634
3546
|
return `ai-vid-${timestamp}.mp4`;
|
|
3635
3547
|
}
|
|
3636
|
-
function
|
|
3548
|
+
function replaceFileExtension(filePath, extension) {
|
|
3637
3549
|
const ext = path9.extname(filePath);
|
|
3638
3550
|
if (!ext) {
|
|
3639
3551
|
return `${filePath}.${extension}`;
|
|
@@ -3663,7 +3575,7 @@ function inferVideoExtension(remoteUrl, response) {
|
|
|
3663
3575
|
}
|
|
3664
3576
|
|
|
3665
3577
|
// src/commands/ai/ai-querytask-command.ts
|
|
3666
|
-
import { spawn as
|
|
3578
|
+
import { spawn as spawn4 } from "child_process";
|
|
3667
3579
|
var BIN = "xx";
|
|
3668
3580
|
var PPE_ENV = "ppe_new_login_cli";
|
|
3669
3581
|
var POLL_INTERVAL_MS2 = 5e3;
|
|
@@ -3720,7 +3632,7 @@ var AiQueryTaskCommand = class extends AiBaseCommand {
|
|
|
3720
3632
|
"--json"
|
|
3721
3633
|
];
|
|
3722
3634
|
return new Promise((resolve8) => {
|
|
3723
|
-
const child =
|
|
3635
|
+
const child = spawn4(BIN, args, { cwd: process.cwd() });
|
|
3724
3636
|
let stdout = "";
|
|
3725
3637
|
let stderr = "";
|
|
3726
3638
|
child.stdout.on("data", (chunk) => {
|
|
@@ -3801,7 +3713,7 @@ var AiCommand = class extends BaseSubcommandHost {
|
|
|
3801
3713
|
this._addSubcommand(new AiCursorCommand());
|
|
3802
3714
|
this._addSubcommand(new AiCodexCommand());
|
|
3803
3715
|
this._addSubcommand(new AiRunCommand());
|
|
3804
|
-
this._addSubcommand(new
|
|
3716
|
+
this._addSubcommand(new AiImageCommandV2());
|
|
3805
3717
|
this._addSubcommand(new AiVideoCommand());
|
|
3806
3718
|
this._addSubcommand(new AiVidCommand());
|
|
3807
3719
|
this._addSubcommand(new AiQueryTaskCommand());
|