jimeng-cli 0.2.1 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunk-2IIK4X7C.js +10228 -0
- package/dist/chunk-2IIK4X7C.js.map +1 -0
- package/dist/cli/index.cjs +6317 -415
- package/dist/cli/index.cjs.map +1 -1
- package/dist/cli/index.js +409 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/mcp/index.cjs +5981 -376
- package/dist/mcp/index.cjs.map +1 -1
- package/dist/mcp/index.js +111 -1
- package/dist/mcp/index.js.map +1 -1
- package/package.json +11 -16
- package/dist/chunk-3SUCLOAC.js +0 -4702
- package/dist/chunk-3SUCLOAC.js.map +0 -1
package/dist/cli/index.js
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
generateImageComposition,
|
|
6
6
|
generateImages,
|
|
7
7
|
generateVideo,
|
|
8
|
+
getAssetList,
|
|
8
9
|
getCredit,
|
|
9
10
|
getLiveModels,
|
|
10
11
|
getTaskResponse,
|
|
@@ -12,9 +13,11 @@ import {
|
|
|
12
13
|
logger_default,
|
|
13
14
|
parseRegionCode,
|
|
14
15
|
receiveCredit,
|
|
16
|
+
refreshAllTokenModels,
|
|
15
17
|
session_pool_default,
|
|
18
|
+
upscaleImage,
|
|
16
19
|
waitForTaskResponse
|
|
17
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-2IIK4X7C.js";
|
|
18
21
|
|
|
19
22
|
// src/cli/app.ts
|
|
20
23
|
import process2 from "process";
|
|
@@ -495,6 +498,34 @@ function printTaskInfo(task, deps) {
|
|
|
495
498
|
}
|
|
496
499
|
}
|
|
497
500
|
function createQueryCommandHandlers(deps) {
|
|
501
|
+
const handleModelsRefresh = async (argv) => {
|
|
502
|
+
const args = minimist2(argv, {
|
|
503
|
+
boolean: ["help", "json"]
|
|
504
|
+
});
|
|
505
|
+
if (args.help) {
|
|
506
|
+
console.log(deps.usageModelsRefresh());
|
|
507
|
+
return;
|
|
508
|
+
}
|
|
509
|
+
await deps.ensureTokenPoolReady();
|
|
510
|
+
const results = await refreshAllTokenModels();
|
|
511
|
+
const isJson = Boolean(args.json);
|
|
512
|
+
if (isJson) {
|
|
513
|
+
deps.printCommandJson("models.refresh", results);
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
if (results.length === 0) {
|
|
517
|
+
console.log("No enabled+live tokens found in pool. Nothing to refresh.");
|
|
518
|
+
return;
|
|
519
|
+
}
|
|
520
|
+
console.log(`Refreshed ${results.length} token(s).`);
|
|
521
|
+
console.log("");
|
|
522
|
+
console.log("token region imageModels videoModels capabilityTags error");
|
|
523
|
+
for (const r of results) {
|
|
524
|
+
const tags = r.capabilityTags.length > 0 ? r.capabilityTags.join(",") : "-";
|
|
525
|
+
const err = r.error ? r.error.slice(0, 60) : "-";
|
|
526
|
+
console.log(`${r.token} ${r.region} ${r.imageModels} ${r.videoModels} ${tags} ${err}`);
|
|
527
|
+
}
|
|
528
|
+
};
|
|
498
529
|
const handleModelsList = async (argv) => {
|
|
499
530
|
const args = minimist2(argv, {
|
|
500
531
|
string: ["region", "token"],
|
|
@@ -638,10 +669,62 @@ ${deps.usageTaskWait()}`);
|
|
|
638
669
|
if (isJson) deps.printCommandJson("task.wait", taskInfo);
|
|
639
670
|
else printTaskInfo(taskInfo, deps);
|
|
640
671
|
};
|
|
672
|
+
const handleTaskList = async (argv) => {
|
|
673
|
+
const args = minimist2(argv, {
|
|
674
|
+
string: ["token", "region", "type", "count"],
|
|
675
|
+
boolean: ["help", "json"]
|
|
676
|
+
});
|
|
677
|
+
if (args.help) {
|
|
678
|
+
console.log(deps.usageTaskList());
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
681
|
+
const token = deps.getSingleString(args, "token");
|
|
682
|
+
const region = deps.getRegionWithDefault(args);
|
|
683
|
+
const type = deps.getSingleString(args, "type");
|
|
684
|
+
const countRaw = deps.getSingleString(args, "count");
|
|
685
|
+
const count = countRaw ? Number(countRaw) : 20;
|
|
686
|
+
const isJson = Boolean(args.json);
|
|
687
|
+
if (type && type !== "image" && type !== "video" && type !== "all") {
|
|
688
|
+
deps.fail(`Invalid --type: ${type}. Use image, video, or all.`);
|
|
689
|
+
}
|
|
690
|
+
const pick = await deps.pickDirectTokenForTask(token, region);
|
|
691
|
+
const result = await getAssetList(
|
|
692
|
+
pick.token,
|
|
693
|
+
buildRegionInfo(pick.region),
|
|
694
|
+
{
|
|
695
|
+
count: Number.isFinite(count) && count > 0 ? count : 20,
|
|
696
|
+
type
|
|
697
|
+
}
|
|
698
|
+
);
|
|
699
|
+
if (isJson) {
|
|
700
|
+
deps.printCommandJson("task.list", {
|
|
701
|
+
has_more: result.hasMore,
|
|
702
|
+
next_offset: result.nextOffset,
|
|
703
|
+
total: result.items.length,
|
|
704
|
+
items: result.items
|
|
705
|
+
});
|
|
706
|
+
return;
|
|
707
|
+
}
|
|
708
|
+
console.log(`Total: ${result.items.length} items${result.hasMore ? " (more available)" : ""}
|
|
709
|
+
`);
|
|
710
|
+
for (const item of result.items) {
|
|
711
|
+
const typeLabel = item.type === 1 ? "IMG" : "VID";
|
|
712
|
+
const statusLabel = item.status === 144 || item.status === 10 ? "DONE" : item.status === 30 ? "FAIL" : "PROC";
|
|
713
|
+
const time = item.createdTime > 0 ? new Date(item.createdTime * 1e3).toLocaleString() : "-";
|
|
714
|
+
const modelShort = item.modelName || item.modelReqKey || "-";
|
|
715
|
+
const promptShort = item.prompt.length > 50 ? item.prompt.slice(0, 50) + "..." : item.prompt;
|
|
716
|
+
console.log(`${item.id} ${typeLabel} ${statusLabel.padEnd(4)} ${time} ${modelShort.padEnd(20)} ${promptShort}`);
|
|
717
|
+
if (item.imageUrl) {
|
|
718
|
+
console.log(` ${item.imageUrl}`);
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
};
|
|
641
722
|
return {
|
|
642
723
|
handleModelsList,
|
|
724
|
+
handleModelsRefresh,
|
|
643
725
|
handleTaskGet,
|
|
644
726
|
handleTaskWait,
|
|
727
|
+
handleTaskList,
|
|
645
728
|
printTaskInfo: (task) => {
|
|
646
729
|
const normalized = collectTaskInfo(task, deps);
|
|
647
730
|
if (!normalized) {
|
|
@@ -1187,13 +1270,260 @@ function createMediaCommandHandlers(deps) {
|
|
|
1187
1270
|
deps.printDownloadSummary("video", [filePath]);
|
|
1188
1271
|
}
|
|
1189
1272
|
};
|
|
1273
|
+
const handleImageUpscale = async (argv) => {
|
|
1274
|
+
const args = minimist3(argv, {
|
|
1275
|
+
string: [
|
|
1276
|
+
"token",
|
|
1277
|
+
"region",
|
|
1278
|
+
"image",
|
|
1279
|
+
"model",
|
|
1280
|
+
"resolution",
|
|
1281
|
+
"output-dir",
|
|
1282
|
+
"wait-timeout-seconds",
|
|
1283
|
+
"poll-interval-ms"
|
|
1284
|
+
],
|
|
1285
|
+
boolean: ["help", "wait", "json"],
|
|
1286
|
+
default: { wait: true }
|
|
1287
|
+
});
|
|
1288
|
+
if (args.help) {
|
|
1289
|
+
console.log(deps.usageImageUpscale());
|
|
1290
|
+
return;
|
|
1291
|
+
}
|
|
1292
|
+
const token = deps.getSingleString(args, "token");
|
|
1293
|
+
const region = deps.getRegionWithDefault(args);
|
|
1294
|
+
const imageSource = deps.getSingleString(args, "image");
|
|
1295
|
+
if (!imageSource) deps.failWithUsage("Missing required --image.", deps.usageImageUpscale());
|
|
1296
|
+
const outputDir = deps.getSingleString(args, "output-dir") || "./pic/cli-image-upscale";
|
|
1297
|
+
const model = deps.getSingleString(args, "model") || "jimeng-5.0";
|
|
1298
|
+
const resolution = deps.getSingleString(args, "resolution") || "4k";
|
|
1299
|
+
const wait = Boolean(args.wait);
|
|
1300
|
+
const isJson = Boolean(args.json);
|
|
1301
|
+
const pick = await deps.pickDirectTokenForGeneration(token, region, model, "image");
|
|
1302
|
+
let image;
|
|
1303
|
+
if (isHttpUrl(imageSource)) {
|
|
1304
|
+
image = imageSource;
|
|
1305
|
+
} else {
|
|
1306
|
+
const imagePath = path3.resolve(imageSource);
|
|
1307
|
+
if (!await pathExists2(imagePath)) deps.fail(`Image file not found: ${imagePath}`);
|
|
1308
|
+
image = await readFile2(imagePath);
|
|
1309
|
+
}
|
|
1310
|
+
const result = await upscaleImage(
|
|
1311
|
+
model,
|
|
1312
|
+
image,
|
|
1313
|
+
{
|
|
1314
|
+
resolution,
|
|
1315
|
+
wait,
|
|
1316
|
+
waitTimeoutSeconds: parsePositiveNumberOption2(args, "wait-timeout-seconds", deps),
|
|
1317
|
+
pollIntervalMs: parsePositiveNumberOption2(args, "poll-interval-ms", deps)
|
|
1318
|
+
},
|
|
1319
|
+
pick.token,
|
|
1320
|
+
buildRegionInfo(pick.region)
|
|
1321
|
+
);
|
|
1322
|
+
if (!Array.isArray(result)) {
|
|
1323
|
+
if (isJson) deps.printCommandJson("image.upscale", result, { wait });
|
|
1324
|
+
else deps.printTaskInfo(result);
|
|
1325
|
+
return;
|
|
1326
|
+
}
|
|
1327
|
+
const urls = result;
|
|
1328
|
+
if (urls.length === 0) deps.fail("No image URL found in response.");
|
|
1329
|
+
const savedFiles = await downloadImages(urls, outputDir, "jimeng-image-upscale", deps);
|
|
1330
|
+
if (isJson) {
|
|
1331
|
+
deps.printCommandJson(
|
|
1332
|
+
"image.upscale",
|
|
1333
|
+
{ data: urls.map((url) => ({ url })), files: savedFiles },
|
|
1334
|
+
{ wait, resolution }
|
|
1335
|
+
);
|
|
1336
|
+
} else {
|
|
1337
|
+
deps.printDownloadSummary("image", savedFiles);
|
|
1338
|
+
}
|
|
1339
|
+
};
|
|
1190
1340
|
return {
|
|
1191
1341
|
handleImageGenerate,
|
|
1192
1342
|
handleImageEdit,
|
|
1343
|
+
handleImageUpscale,
|
|
1193
1344
|
handleVideoGenerate
|
|
1194
1345
|
};
|
|
1195
1346
|
}
|
|
1196
1347
|
|
|
1348
|
+
// src/cli/login.ts
|
|
1349
|
+
import { execSync, spawn } from "child_process";
|
|
1350
|
+
import { existsSync } from "fs";
|
|
1351
|
+
import path4 from "path";
|
|
1352
|
+
import os from "os";
|
|
1353
|
+
import { fileURLToPath } from "url";
|
|
1354
|
+
import minimist4 from "minimist";
|
|
1355
|
+
var __filename = fileURLToPath(import.meta.url);
|
|
1356
|
+
var __dirname = path4.dirname(__filename);
|
|
1357
|
+
var LOGIN_SCRIPT = path4.join(__dirname, "..", "..", "scripts", "jimeng_login_helper.py");
|
|
1358
|
+
function createLoginCommandHandler(deps) {
|
|
1359
|
+
return async (argv) => {
|
|
1360
|
+
const args = minimist4(argv, {
|
|
1361
|
+
string: ["region", "sessionid", "debug-port"],
|
|
1362
|
+
boolean: ["help", "headless", "json"]
|
|
1363
|
+
});
|
|
1364
|
+
if (args.help) {
|
|
1365
|
+
console.log(usageLogin());
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1368
|
+
const region = deps.getRegionWithDefault(args);
|
|
1369
|
+
const parsedRegion = deps.parseRegionOrFail(region);
|
|
1370
|
+
const isJson = Boolean(args.json);
|
|
1371
|
+
const sessionid = deps.getSingleString(args, "sessionid");
|
|
1372
|
+
const debugPort = deps.getSingleString(args, "debug-port") || "9333";
|
|
1373
|
+
const headless = Boolean(args.headless);
|
|
1374
|
+
if (sessionid) {
|
|
1375
|
+
await addSessionToPool(sessionid, parsedRegion || "cn", deps, isJson);
|
|
1376
|
+
return;
|
|
1377
|
+
}
|
|
1378
|
+
const pythonLoginResult = await tryPythonLogin(debugPort, headless);
|
|
1379
|
+
if (pythonLoginResult) {
|
|
1380
|
+
await addSessionToPool(pythonLoginResult, parsedRegion || "cn", deps, isJson);
|
|
1381
|
+
return;
|
|
1382
|
+
}
|
|
1383
|
+
console.log("");
|
|
1384
|
+
console.log("Auto login not available. Please provide your sessionid manually.");
|
|
1385
|
+
console.log("You can get it from:");
|
|
1386
|
+
console.log(" 1. Login at https://jimeng.jianying.com/ai-tool/home/");
|
|
1387
|
+
console.log(" 2. Open DevTools > Application > Cookies > sessionid");
|
|
1388
|
+
console.log("");
|
|
1389
|
+
console.log("Then run: jimeng login --sessionid <your_sessionid> --region cn");
|
|
1390
|
+
console.log("");
|
|
1391
|
+
console.log("Or install Python 3 to use the automatic browser login.");
|
|
1392
|
+
};
|
|
1393
|
+
}
|
|
1394
|
+
async function tryPythonLogin(debugPort, headless) {
|
|
1395
|
+
const loginScript = findLoginScript();
|
|
1396
|
+
if (!loginScript) {
|
|
1397
|
+
return null;
|
|
1398
|
+
}
|
|
1399
|
+
console.log(`Launching browser login (debug port: ${debugPort})...`);
|
|
1400
|
+
console.log("Please complete login in the Chrome window.\n");
|
|
1401
|
+
try {
|
|
1402
|
+
const cmdArgs = [loginScript, "--debug-port", debugPort];
|
|
1403
|
+
if (headless) cmdArgs.push("--headless");
|
|
1404
|
+
const result = await runPythonScript(cmdArgs);
|
|
1405
|
+
const output = result.stdout.trim();
|
|
1406
|
+
const match = output.match(/sessionid:\s*(\S+)/);
|
|
1407
|
+
if (match) {
|
|
1408
|
+
return match[1];
|
|
1409
|
+
}
|
|
1410
|
+
console.log("Login script completed but sessionid not found in output.");
|
|
1411
|
+
return null;
|
|
1412
|
+
} catch (error) {
|
|
1413
|
+
console.log(`Auto login failed: ${error.message}`);
|
|
1414
|
+
return null;
|
|
1415
|
+
}
|
|
1416
|
+
}
|
|
1417
|
+
function findLoginScript() {
|
|
1418
|
+
if (existsSync(LOGIN_SCRIPT)) {
|
|
1419
|
+
return LOGIN_SCRIPT;
|
|
1420
|
+
}
|
|
1421
|
+
const candidates = [
|
|
1422
|
+
path4.join(process.cwd(), "jimeng_login.py"),
|
|
1423
|
+
path4.join(os.homedir(), ".jimeng_login.py")
|
|
1424
|
+
];
|
|
1425
|
+
try {
|
|
1426
|
+
const whichResult = execSync("which jimeng_login.py 2>/dev/null || echo ''", { encoding: "utf-8" }).trim();
|
|
1427
|
+
if (whichResult) return whichResult;
|
|
1428
|
+
} catch {
|
|
1429
|
+
}
|
|
1430
|
+
for (const candidate of candidates) {
|
|
1431
|
+
if (existsSync(candidate)) return candidate;
|
|
1432
|
+
}
|
|
1433
|
+
return null;
|
|
1434
|
+
}
|
|
1435
|
+
function runPythonScript(args) {
|
|
1436
|
+
return new Promise((resolve, reject) => {
|
|
1437
|
+
var _a, _b;
|
|
1438
|
+
const pythonCmd = process.platform === "win32" ? "python" : "python3";
|
|
1439
|
+
const proc = spawn(pythonCmd, args, {
|
|
1440
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
1441
|
+
env: { ...process.env }
|
|
1442
|
+
});
|
|
1443
|
+
let stdout = "";
|
|
1444
|
+
let stderr = "";
|
|
1445
|
+
(_a = proc.stdout) == null ? void 0 : _a.on("data", (data) => {
|
|
1446
|
+
stdout += data.toString();
|
|
1447
|
+
const lines = data.toString().split("\n").filter(Boolean);
|
|
1448
|
+
for (const line of lines) {
|
|
1449
|
+
console.log(line);
|
|
1450
|
+
}
|
|
1451
|
+
});
|
|
1452
|
+
(_b = proc.stderr) == null ? void 0 : _b.on("data", (data) => {
|
|
1453
|
+
stderr += data.toString();
|
|
1454
|
+
});
|
|
1455
|
+
proc.on("close", (code) => {
|
|
1456
|
+
if (code === 0) {
|
|
1457
|
+
resolve({ stdout, stderr });
|
|
1458
|
+
} else {
|
|
1459
|
+
reject(new Error(`Login script exited with code ${code}: ${stderr.slice(-200)}`));
|
|
1460
|
+
}
|
|
1461
|
+
});
|
|
1462
|
+
proc.on("error", (error) => {
|
|
1463
|
+
reject(new Error(`Failed to run login script: ${error.message}`));
|
|
1464
|
+
});
|
|
1465
|
+
});
|
|
1466
|
+
}
|
|
1467
|
+
async function addSessionToPool(sessionid, region, deps, isJson) {
|
|
1468
|
+
await deps.ensureTokenPoolReady();
|
|
1469
|
+
const { added, total } = await session_pool_default.addTokens([sessionid], { defaultRegion: region });
|
|
1470
|
+
if (added > 0) {
|
|
1471
|
+
const masked = sessionid.length > 10 ? `${sessionid.slice(0, 4)}...${sessionid.slice(-4)}` : "***";
|
|
1472
|
+
let creditInfo = "";
|
|
1473
|
+
try {
|
|
1474
|
+
const { totalCredit } = await getCredit(sessionid, buildRegionInfo(region));
|
|
1475
|
+
creditInfo = ` (credits: ${totalCredit})`;
|
|
1476
|
+
} catch {
|
|
1477
|
+
creditInfo = " (credit check failed)";
|
|
1478
|
+
}
|
|
1479
|
+
if (isJson) {
|
|
1480
|
+
deps.printCommandJson("login", {
|
|
1481
|
+
token: masked,
|
|
1482
|
+
region,
|
|
1483
|
+
added: true,
|
|
1484
|
+
total,
|
|
1485
|
+
creditCheck: creditInfo.trim()
|
|
1486
|
+
});
|
|
1487
|
+
} else {
|
|
1488
|
+
console.log(`
|
|
1489
|
+
Login successful!`);
|
|
1490
|
+
console.log(` Token: ${masked}`);
|
|
1491
|
+
console.log(` Region: ${region}${creditInfo}`);
|
|
1492
|
+
console.log(` Pool size: ${total} token(s)`);
|
|
1493
|
+
}
|
|
1494
|
+
} else {
|
|
1495
|
+
if (isJson) {
|
|
1496
|
+
deps.printCommandJson("login", {
|
|
1497
|
+
added: false,
|
|
1498
|
+
total,
|
|
1499
|
+
reason: "token already exists in pool"
|
|
1500
|
+
});
|
|
1501
|
+
} else {
|
|
1502
|
+
console.log(`Token already exists in pool. Pool size: ${total} token(s)`);
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
function usageLogin() {
|
|
1507
|
+
return [
|
|
1508
|
+
"Usage:",
|
|
1509
|
+
" jimeng login [options]",
|
|
1510
|
+
"",
|
|
1511
|
+
"Options:",
|
|
1512
|
+
" --region <region> Region for the token (default cn)",
|
|
1513
|
+
" --sessionid <token> Add sessionid directly (skip browser login)",
|
|
1514
|
+
" --debug-port <port> Chrome debug port (default 9333)",
|
|
1515
|
+
" --headless Run Chrome in headless mode",
|
|
1516
|
+
" --json Output structured JSON",
|
|
1517
|
+
" --help Show help",
|
|
1518
|
+
"",
|
|
1519
|
+
"Notes:",
|
|
1520
|
+
" - Without --sessionid, launches Chrome for browser login (requires Python 3).",
|
|
1521
|
+
" - With --sessionid, directly adds the token to the pool.",
|
|
1522
|
+
" - After login, the token is automatically added to the token pool.",
|
|
1523
|
+
" - Token is validated by checking credit balance."
|
|
1524
|
+
].join("\n");
|
|
1525
|
+
}
|
|
1526
|
+
|
|
1197
1527
|
// src/cli/app.ts
|
|
1198
1528
|
var JSON_OPTION = " --json Output structured JSON";
|
|
1199
1529
|
var HELP_OPTION = " --help Show help";
|
|
@@ -1234,6 +1564,21 @@ function usageModelsList() {
|
|
|
1234
1564
|
HELP_OPTION
|
|
1235
1565
|
]);
|
|
1236
1566
|
}
|
|
1567
|
+
function usageModelsRefresh() {
|
|
1568
|
+
return buildUsageText(" jimeng models refresh [options]", [
|
|
1569
|
+
" --json Output structured JSON",
|
|
1570
|
+
HELP_OPTION
|
|
1571
|
+
], [
|
|
1572
|
+
{
|
|
1573
|
+
title: "Notes:",
|
|
1574
|
+
lines: [
|
|
1575
|
+
" - Refreshes dynamicCapabilities (imageModels, videoModels, capabilityTags) for",
|
|
1576
|
+
" all enabled+live tokens in the token pool.",
|
|
1577
|
+
" - Results are persisted to token-pool.json automatically."
|
|
1578
|
+
]
|
|
1579
|
+
}
|
|
1580
|
+
]);
|
|
1581
|
+
}
|
|
1237
1582
|
function usageTokenSubcommand(name) {
|
|
1238
1583
|
const subcommand = TOKEN_SUBCOMMANDS_BY_NAME[name];
|
|
1239
1584
|
return buildUsageText(subcommand.usageLine, subcommand.options, subcommand.sections);
|
|
@@ -1300,6 +1645,34 @@ function usageImageEdit() {
|
|
|
1300
1645
|
]
|
|
1301
1646
|
);
|
|
1302
1647
|
}
|
|
1648
|
+
function usageImageUpscale() {
|
|
1649
|
+
return buildUsageText(
|
|
1650
|
+
" jimeng image upscale --image <path_or_url> [options]",
|
|
1651
|
+
[
|
|
1652
|
+
" --token <token> Optional, override token-pool selection",
|
|
1653
|
+
" --region <region> X-Region header, default cn (cn/us/hk/jp/sg)",
|
|
1654
|
+
" --image <path_or_url> Required, local file or URL",
|
|
1655
|
+
" --model <model> Default jimeng-5.0",
|
|
1656
|
+
" --resolution <res> Default 4k (target resolution)",
|
|
1657
|
+
" --wait / --no-wait Default wait; --no-wait returns task only",
|
|
1658
|
+
" --wait-timeout-seconds Optional wait timeout override",
|
|
1659
|
+
" --poll-interval-ms Optional poll interval override",
|
|
1660
|
+
JSON_OPTION,
|
|
1661
|
+
" --output-dir <dir> Default ./pic/cli-image-upscale",
|
|
1662
|
+
HELP_OPTION
|
|
1663
|
+
],
|
|
1664
|
+
[
|
|
1665
|
+
{
|
|
1666
|
+
title: "Notes:",
|
|
1667
|
+
lines: [
|
|
1668
|
+
" - Upscales an existing image to higher resolution using super_resolution.",
|
|
1669
|
+
" - Supports 2k and 4k target resolutions.",
|
|
1670
|
+
" - Image source can be a local file path or HTTP URL."
|
|
1671
|
+
]
|
|
1672
|
+
}
|
|
1673
|
+
]
|
|
1674
|
+
);
|
|
1675
|
+
}
|
|
1303
1676
|
function usageVideoGenerate() {
|
|
1304
1677
|
return buildUsageText(" jimeng video generate --prompt <text> [options]", [
|
|
1305
1678
|
" --token <token> Optional, override token-pool selection",
|
|
@@ -1369,6 +1742,16 @@ function usageTaskWait() {
|
|
|
1369
1742
|
HELP_OPTION
|
|
1370
1743
|
]);
|
|
1371
1744
|
}
|
|
1745
|
+
function usageTaskList() {
|
|
1746
|
+
return buildUsageText(" jimeng task list [options]", [
|
|
1747
|
+
" --token <token> Optional, override token-pool selection",
|
|
1748
|
+
" --region <region> X-Region header, default cn (cn/us/hk/jp/sg)",
|
|
1749
|
+
" --type <type> Filter by type: image, video, or all (default all)",
|
|
1750
|
+
" --count <num> Number of items per page (default 20)",
|
|
1751
|
+
JSON_OPTION,
|
|
1752
|
+
HELP_OPTION
|
|
1753
|
+
]);
|
|
1754
|
+
}
|
|
1372
1755
|
function configureCliLogging(command) {
|
|
1373
1756
|
if (process2.env.JIMENG_CLI_VERBOSE_LOGS === "true") {
|
|
1374
1757
|
process2.env.JIMENG_CLI_SILENT_LOGS = "false";
|
|
@@ -1502,8 +1885,10 @@ var TOKEN_SUBCOMMANDS = createTokenSubcommands({
|
|
|
1502
1885
|
});
|
|
1503
1886
|
var queryHandlers = createQueryCommandHandlers({
|
|
1504
1887
|
usageModelsList,
|
|
1888
|
+
usageModelsRefresh,
|
|
1505
1889
|
usageTaskGet,
|
|
1506
1890
|
usageTaskWait,
|
|
1891
|
+
usageTaskList,
|
|
1507
1892
|
getSingleString,
|
|
1508
1893
|
getRegionWithDefault,
|
|
1509
1894
|
parseRegionOrFail,
|
|
@@ -1517,6 +1902,7 @@ var queryHandlers = createQueryCommandHandlers({
|
|
|
1517
1902
|
var mediaHandlers = createMediaCommandHandlers({
|
|
1518
1903
|
usageImageGenerate,
|
|
1519
1904
|
usageImageEdit,
|
|
1905
|
+
usageImageUpscale,
|
|
1520
1906
|
usageVideoGenerate,
|
|
1521
1907
|
getSingleString,
|
|
1522
1908
|
getRegionWithDefault,
|
|
@@ -1535,10 +1921,26 @@ function buildHandlersMap(subcommands) {
|
|
|
1535
1921
|
return Object.fromEntries(subcommands.map((item) => [item.name, item.handler]));
|
|
1536
1922
|
}
|
|
1537
1923
|
var COMMAND_SPECS = [
|
|
1924
|
+
{
|
|
1925
|
+
name: "login",
|
|
1926
|
+
description: "Login and add session to token pool",
|
|
1927
|
+
handler: createLoginCommandHandler({
|
|
1928
|
+
getSingleString,
|
|
1929
|
+
getRegionWithDefault,
|
|
1930
|
+
parseRegionOrFail,
|
|
1931
|
+
ensureTokenPoolReady,
|
|
1932
|
+
fail,
|
|
1933
|
+
printJson,
|
|
1934
|
+
printCommandJson
|
|
1935
|
+
})
|
|
1936
|
+
},
|
|
1538
1937
|
{
|
|
1539
1938
|
name: "models",
|
|
1540
1939
|
description: "Model commands",
|
|
1541
|
-
subcommands: [
|
|
1940
|
+
subcommands: [
|
|
1941
|
+
{ name: "list", description: "List available models", handler: queryHandlers.handleModelsList },
|
|
1942
|
+
{ name: "refresh", description: "Refresh token dynamic capabilities (model list)", handler: queryHandlers.handleModelsRefresh }
|
|
1943
|
+
],
|
|
1542
1944
|
usage: usageRoot
|
|
1543
1945
|
},
|
|
1544
1946
|
{
|
|
@@ -1546,7 +1948,8 @@ var COMMAND_SPECS = [
|
|
|
1546
1948
|
description: "Image commands",
|
|
1547
1949
|
subcommands: [
|
|
1548
1950
|
{ name: "generate", description: "Generate image from text", handler: mediaHandlers.handleImageGenerate },
|
|
1549
|
-
{ name: "edit", description: "Edit image(s) with prompt", handler: mediaHandlers.handleImageEdit }
|
|
1951
|
+
{ name: "edit", description: "Edit image(s) with prompt", handler: mediaHandlers.handleImageEdit },
|
|
1952
|
+
{ name: "upscale", description: "Upscale image to higher resolution", handler: mediaHandlers.handleImageUpscale }
|
|
1550
1953
|
],
|
|
1551
1954
|
usage: usageRoot
|
|
1552
1955
|
},
|
|
@@ -1567,7 +1970,8 @@ var COMMAND_SPECS = [
|
|
|
1567
1970
|
description: "Task commands",
|
|
1568
1971
|
subcommands: [
|
|
1569
1972
|
{ name: "get", description: "Get task status", handler: queryHandlers.handleTaskGet },
|
|
1570
|
-
{ name: "wait", description: "Wait until task completion", handler: queryHandlers.handleTaskWait }
|
|
1973
|
+
{ name: "wait", description: "Wait until task completion", handler: queryHandlers.handleTaskWait },
|
|
1974
|
+
{ name: "list", description: "List task history", handler: queryHandlers.handleTaskList }
|
|
1571
1975
|
],
|
|
1572
1976
|
usage: usageRoot
|
|
1573
1977
|
},
|
|
@@ -1629,7 +2033,7 @@ async function run() {
|
|
|
1629
2033
|
failWithUsage(`Unknown command: ${[command, subcommand].filter(Boolean).join(" ")}`, usageRoot());
|
|
1630
2034
|
}
|
|
1631
2035
|
if (spec.handler) {
|
|
1632
|
-
await spec.handler(rest);
|
|
2036
|
+
await spec.handler(subcommand ? [subcommand, ...rest] : rest);
|
|
1633
2037
|
return;
|
|
1634
2038
|
}
|
|
1635
2039
|
if (spec.subcommands) {
|