mirror of
https://github.com/modelstudioai/cli.git
synced 2026-09-14 19:49:23 +08:00
Merge pull request #63 from modelstudioai/feat/i18n-english-only
feat(cli): standardize user-facing CLI text to English
This commit is contained in:
@@ -35,12 +35,12 @@ export default defineCommand({
|
||||
{ flag: "--has-thoughts", description: "Show agent thinking process" },
|
||||
],
|
||||
examples: [
|
||||
'bl app call --app-id abc123 --prompt "你好"',
|
||||
'bl app call --app-id abc123 --prompt "描述这张图片" --image https://example.com/photo.jpg',
|
||||
'bl app call --app-id abc123 --prompt "分析图片" --image img1.jpg --image img2.jpg',
|
||||
'bl app call --app-id abc123 --prompt "继续" --session-id sess_xxx --stream',
|
||||
'bl app call --app-id abc123 --prompt "搜索资料" --pipeline-ids pipe1,pipe2',
|
||||
'bl app call --app-id abc123 --prompt "开始" --biz-params \'{"key":"value"}\'',
|
||||
'bl app call --app-id abc123 --prompt "Hello"',
|
||||
'bl app call --app-id abc123 --prompt "Describe this image" --image https://example.com/photo.jpg',
|
||||
'bl app call --app-id abc123 --prompt "Analyze the image" --image img1.jpg --image img2.jpg',
|
||||
'bl app call --app-id abc123 --prompt "Continue" --session-id sess_xxx --stream',
|
||||
'bl app call --app-id abc123 --prompt "Search for materials" --pipeline-ids pipe1,pipe2',
|
||||
'bl app call --app-id abc123 --prompt "Start" --biz-params \'{"key":"value"}\'',
|
||||
],
|
||||
async run(config: Config, flags: GlobalFlags) {
|
||||
const appId = flags.appId as string;
|
||||
|
||||
@@ -37,7 +37,7 @@ export default defineCommand({
|
||||
],
|
||||
examples: [
|
||||
"bl app list",
|
||||
"bl app list --name 客服",
|
||||
"bl app list --name customer service",
|
||||
"bl app list --page 2 --page-size 10",
|
||||
"bl app list --output json",
|
||||
],
|
||||
|
||||
@@ -64,11 +64,11 @@ export default defineCommand({
|
||||
{ flag: "--out-prefix <prefix>", description: "Filename prefix (default: edited)" },
|
||||
],
|
||||
examples: [
|
||||
'bl image edit --image ./photo.png --prompt "把背景换成海滩"',
|
||||
'bl image edit --image ./photo.png --prompt "Replace the background with a beach"',
|
||||
'bl image edit --image https://example.com/logo.png --prompt "Change color to blue" --n 3',
|
||||
'bl image edit --image ./a.png --image ./b.png --prompt "把两张图合并成一张拼图"',
|
||||
'bl image edit --image ./a.png --image ./b.png --prompt "Merge two images into one collage"',
|
||||
'bl image edit --image https://example.com/photo.png --prompt "Remove the person" --model qwen-image-2.0-pro',
|
||||
'bl image edit --image ./photo.png --prompt "把背景换成海滩" --watermark false',
|
||||
'bl image edit --image ./photo.png --prompt "Replace the background with a beach" --watermark false',
|
||||
],
|
||||
async run(config: Config, flags: GlobalFlags) {
|
||||
// Normalize --image to string array (supports both single and repeated flags)
|
||||
|
||||
@@ -82,7 +82,7 @@ export default defineCommand({
|
||||
},
|
||||
],
|
||||
examples: [
|
||||
'bl image generate --prompt "一只穿太空服的猫在火星上"',
|
||||
'bl image generate --prompt "A cat in a spacesuit on Mars"',
|
||||
'bl image generate --prompt "Logo design" --n 3 --out-dir ./generated/',
|
||||
'bl image generate --prompt "Mountain landscape" --size 2688*1536',
|
||||
'bl image generate --prompt "A castle" --seed 42 --prompt-extend false',
|
||||
|
||||
@@ -77,8 +77,8 @@ export default defineCommand({
|
||||
"`--workspace-id` is NOT required when using --api-key.",
|
||||
],
|
||||
examples: [
|
||||
'bl knowledge retrieve --index-id idx_xxx --query "如何使用阿里云百炼"',
|
||||
'bl knowledge retrieve --api-key $DASHSCOPE_API_KEY --index-id idx_xxx --query "RAG检索" --rerank --rerank-model qwen3-rerank-hybrid',
|
||||
'bl knowledge retrieve --index-id idx_xxx --query "How to use Alibaba Cloud Bailian"',
|
||||
'bl knowledge retrieve --api-key $DASHSCOPE_API_KEY --index-id idx_xxx --query "RAG retrieval" --rerank --rerank-model qwen3-rerank-hybrid',
|
||||
],
|
||||
async run(config: Config, flags: GlobalFlags) {
|
||||
const indexId = flags.indexId as string;
|
||||
|
||||
@@ -57,8 +57,8 @@ export default defineCommand({
|
||||
{ flag: "--url <url>", description: "Override the MCP endpoint URL (for non-Bailian servers)" },
|
||||
],
|
||||
examples: [
|
||||
'bl mcp call market-cmapi00073529.SmartStockSelection --query "筛选ROE>15%的消费股"',
|
||||
'bl mcp call market-cmapi00073529.FinQuery --json \'{"q":"贵州茅台","limit":5}\'',
|
||||
'bl mcp call market-cmapi00073529.SmartStockSelection --query "Screen consumer stocks with ROE > 15%"',
|
||||
'bl mcp call market-cmapi00073529.FinQuery --json \'{"q":"Guizhou Maotai","limit":5}\'',
|
||||
"bl mcp call market-cmapi00073529.SmartFundSelection --arg riskLevel=R3 --arg minScale=10",
|
||||
],
|
||||
async run(config: Config, flags: GlobalFlags) {
|
||||
|
||||
@@ -38,7 +38,7 @@ export default defineCommand({
|
||||
{ flag: "--page-size <n>", description: "Results per page (default: 30)", type: "number" },
|
||||
{ flag: "--region <region>", description: "API region (default: cn-beijing)" },
|
||||
],
|
||||
examples: ["bl mcp list", "bl mcp list --name 金融", "bl mcp list --output json"],
|
||||
examples: ["bl mcp list", "bl mcp list --name finance", "bl mcp list --output json"],
|
||||
async run(config: Config, flags: GlobalFlags) {
|
||||
const serverName = (flags.name as string) || "";
|
||||
const type = (flags.type as string) || "OFFICIAL";
|
||||
|
||||
@@ -26,9 +26,9 @@ export default defineCommand({
|
||||
{ flag: "--memory-library-id <id>", description: "Memory library ID (isolate memory space)" },
|
||||
],
|
||||
examples: [
|
||||
'bl memory add --user-id user1 --content "用户喜欢Python编程"',
|
||||
'bl memory add --user-id user1 --messages \'[{"role":"user","content":"我喜欢旅行"}]\'',
|
||||
'bl memory add --user-id user1 --content "住在北京" --profile-schema schema_xxx',
|
||||
'bl memory add --user-id user1 --content "The user likes Python programming"',
|
||||
'bl memory add --user-id user1 --messages \'[{"role":"user","content":"I like traveling"}]\'',
|
||||
'bl memory add --user-id user1 --content "Lives in Beijing" --profile-schema schema_xxx',
|
||||
],
|
||||
async run(config: Config, flags: GlobalFlags) {
|
||||
const userId = flags.userId as string;
|
||||
|
||||
@@ -20,12 +20,12 @@ export default defineCommand({
|
||||
{ flag: "--description <text>", description: "Schema description" },
|
||||
{
|
||||
flag: "--attributes <json>",
|
||||
description: 'Attributes JSON array: [{"name":"age","description":"年龄"}]',
|
||||
description: 'Attributes JSON array: [{"name":"age","description":"age"}]',
|
||||
required: true,
|
||||
},
|
||||
],
|
||||
examples: [
|
||||
'bl memory profile create --name "user_basic" --attributes \'[{"name":"age","description":"年龄"},{"name":"hobby","description":"爱好"}]\'',
|
||||
'bl memory profile create --name "user_basic" --attributes \'[{"name":"age","description":"age"},{"name":"hobby","description":"hobby"}]\'',
|
||||
],
|
||||
async run(config: Config, flags: GlobalFlags) {
|
||||
const name = flags.name as string;
|
||||
|
||||
@@ -27,8 +27,8 @@ export default defineCommand({
|
||||
{ flag: "--memory-library-id <id>", description: "Memory library ID" },
|
||||
],
|
||||
examples: [
|
||||
'bl memory search --user-id user1 --query "编程偏好"',
|
||||
'bl memory search --user-id user1 --messages \'[{"role":"user","content":"推荐一本书"}]\' --top-k 5',
|
||||
'bl memory search --user-id user1 --query "programming preferences"',
|
||||
'bl memory search --user-id user1 --messages \'[{"role":"user","content":"recommend a book"}]\' --top-k 5',
|
||||
],
|
||||
async run(config: Config, flags: GlobalFlags) {
|
||||
const userId = flags.userId as string;
|
||||
|
||||
@@ -24,7 +24,9 @@ export default defineCommand({
|
||||
},
|
||||
{ flag: "--memory-library-id <id>", description: "Memory library ID (non-default library)" },
|
||||
],
|
||||
examples: ['bl memory update --node-id node_xxx --user-id user1 --content "更新后的记忆内容"'],
|
||||
examples: [
|
||||
'bl memory update --node-id node_xxx --user-id user1 --content "updated memory content"',
|
||||
],
|
||||
async run(config: Config, flags: GlobalFlags) {
|
||||
const nodeId = flags.nodeId as string;
|
||||
if (!nodeId)
|
||||
|
||||
@@ -21,7 +21,7 @@ import { promptText, failIfMissing } from "../../output/prompt.ts";
|
||||
import { emitResult } from "../../output/output.ts";
|
||||
import { resolveOutputDir, resolveCredential } from "bailian-cli-core";
|
||||
|
||||
const OMNI_VOICES = ["Chelsie", "Cherry", "Ethan", "Serena", "Tina"];
|
||||
const OMNI_VOICES = ["Chelsie", "Cherry", "Ethan", "Serena", "Sunny", "Tina"];
|
||||
|
||||
/**
|
||||
* Extension to input audio format.
|
||||
@@ -119,14 +119,14 @@ export default defineCommand({
|
||||
{ flag: "--temperature <n>", description: "Sampling temperature (0.0, 2.0]", type: "number" },
|
||||
],
|
||||
examples: [
|
||||
'bl omni --message "你好,你是谁?"',
|
||||
'bl omni --message "描述这张图片" --image ./photo.jpg',
|
||||
'bl omni --message "这段音频在说什么?" --audio https://example.com/audio.wav',
|
||||
'bl omni --message "总结这个视频" --video https://example.com/video.mp4',
|
||||
'bl omni --message "这个视频讲了什么" --video ./local-video.mp4 --text-only',
|
||||
'bl omni --message "用四川话回答:今天天气怎么样" --voice Serena',
|
||||
'bl omni --message "Hello, who are you?"',
|
||||
'bl omni --message "Describe this image" --image ./photo.jpg',
|
||||
'bl omni --message "What is this audio saying?" --audio https://example.com/audio.wav',
|
||||
'bl omni --message "Summarize this video" --video https://example.com/video.mp4',
|
||||
'bl omni --message "What is this video about?" --video ./local-video.mp4 --text-only',
|
||||
'bl omni --message "Answer in Sichuan dialect: How\'s the weather today?" --voice Sunny',
|
||||
'bl omni --message "Hello" --text-only --output json',
|
||||
'bl omni --message "朗读这段话" --audio-out greeting.wav',
|
||||
'bl omni --message "Read this passage aloud" --audio-out greeting.wav',
|
||||
],
|
||||
async run(config: Config, flags: GlobalFlags) {
|
||||
// --- Parse messages ---
|
||||
|
||||
@@ -64,9 +64,9 @@ function formatRatio(usage: number, limit: number): string {
|
||||
function getStatus(usage: number, limit: number): string {
|
||||
if (limit <= 0) return "-";
|
||||
const pct = (usage / limit) * 100;
|
||||
if (pct >= 100) return "已限流";
|
||||
if (pct >= 80) return "接近限流";
|
||||
return "正常";
|
||||
if (pct >= 100) return "Rate Limited";
|
||||
if (pct >= 80) return "Near limit";
|
||||
return "Normal";
|
||||
}
|
||||
|
||||
function getNestedRecord(
|
||||
@@ -193,8 +193,7 @@ function printTable(rows: CheckRow[], noColor: boolean): void {
|
||||
const yellow = noColor ? (t: string) => t : (t: string) => `\x1b[33m${t}\x1b[0m`;
|
||||
const red = noColor ? (t: string) => t : (t: string) => `\x1b[31m${t}\x1b[0m`;
|
||||
|
||||
const headersCn = ["模型", "RPM 用量/限额", "TPM 用量/限额", "状态"];
|
||||
const headersEn = ["Model", "RPM Usage/Limit", "TPM Usage/Limit", "Status"];
|
||||
const headers = ["Model", "RPM Usage/Limit", "TPM Usage/Limit", "Status"];
|
||||
|
||||
const tableRows = rows.map((r) => {
|
||||
const rpmStr = r.rpmUsage < 0 ? "-" : formatRatio(r.rpmUsage, r.rpmLimit);
|
||||
@@ -215,36 +214,30 @@ function printTable(rows: CheckRow[], noColor: boolean): void {
|
||||
return;
|
||||
}
|
||||
|
||||
const widths = headersCn.map((label, col) =>
|
||||
Math.max(
|
||||
displayWidth(label),
|
||||
displayWidth(headersEn[col]),
|
||||
...tableRows.map((r) => displayWidth(r.cells[col])),
|
||||
),
|
||||
const widths = headers.map((label, col) =>
|
||||
Math.max(displayWidth(label), ...tableRows.map((r) => displayWidth(r.cells[col]))),
|
||||
);
|
||||
|
||||
const cnLine = headersCn.map((label, col) => bold(padEnd(label, widths[col]))).join(" ");
|
||||
const enLine = headersEn.map((label, col) => dim(padEnd(label, widths[col]))).join(" ");
|
||||
const headerLine = headers.map((label, col) => bold(padEnd(label, widths[col]))).join(" ");
|
||||
const separator = widths.map((w) => dim("─".repeat(w))).join("──");
|
||||
|
||||
process.stdout.write(cnLine + "\n");
|
||||
process.stdout.write(enLine + "\n");
|
||||
process.stdout.write(headerLine + "\n");
|
||||
process.stdout.write(separator + "\n");
|
||||
|
||||
const statusCol = 3;
|
||||
for (const r of tableRows) {
|
||||
const cells = r.cells.map((cell, col) => {
|
||||
if (col === statusCol) {
|
||||
if (cell === "已限流") return red(padEnd(cell, widths[col]));
|
||||
if (cell === "接近限流") return yellow(padEnd(cell, widths[col]));
|
||||
if (cell === "正常") return green(padEnd(cell, widths[col]));
|
||||
if (cell === "Rate Limited") return red(padEnd(cell, widths[col]));
|
||||
if (cell === "Near limit") return yellow(padEnd(cell, widths[col]));
|
||||
if (cell === "Normal") return green(padEnd(cell, widths[col]));
|
||||
}
|
||||
return padEnd(cell, widths[col]);
|
||||
});
|
||||
process.stdout.write(cells.join(" ") + "\n");
|
||||
}
|
||||
|
||||
process.stdout.write(dim(`\n共 ${rows.length} 个模型 (Total: ${rows.length})`) + "\n");
|
||||
process.stdout.write(dim(`\nTotal: ${rows.length} models`) + "\n");
|
||||
}
|
||||
|
||||
export default defineCommand({
|
||||
|
||||
@@ -65,8 +65,7 @@ function printTable(records: LimitApplicationItem[], noColor: boolean, total: nu
|
||||
const bold = noColor ? (t: string) => t : (t: string) => `\x1b[1m${t}\x1b[0m`;
|
||||
const dim = noColor ? (t: string) => t : (t: string) => `\x1b[2m${t}\x1b[0m`;
|
||||
|
||||
const headersCn = ["模型", "Token 账号限流", "申请时间"];
|
||||
const headersEn = ["Model", "Token Limit", "Applied At"];
|
||||
const headers = ["Model", "Token Limit", "Applied At"];
|
||||
|
||||
const rows = records.map((r) => [
|
||||
r.deployedModel,
|
||||
@@ -74,27 +73,21 @@ function printTable(records: LimitApplicationItem[], noColor: boolean, total: nu
|
||||
formatDateTime(r.gmtCreate),
|
||||
]);
|
||||
|
||||
const widths = headersCn.map((label, col) =>
|
||||
Math.max(
|
||||
displayWidth(label),
|
||||
displayWidth(headersEn[col]),
|
||||
...rows.map((row) => displayWidth(row[col])),
|
||||
),
|
||||
const widths = headers.map((label, col) =>
|
||||
Math.max(displayWidth(label), ...rows.map((row) => displayWidth(row[col]))),
|
||||
);
|
||||
|
||||
const cnLine = headersCn.map((label, col) => bold(padEnd(label, widths[col]))).join(" ");
|
||||
const enLine = headersEn.map((label, col) => dim(padEnd(label, widths[col]))).join(" ");
|
||||
const headerLine = headers.map((label, col) => bold(padEnd(label, widths[col]))).join(" ");
|
||||
const separator = widths.map((w) => dim("─".repeat(w))).join("──");
|
||||
|
||||
process.stdout.write(cnLine + "\n");
|
||||
process.stdout.write(enLine + "\n");
|
||||
process.stdout.write(headerLine + "\n");
|
||||
process.stdout.write(separator + "\n");
|
||||
|
||||
for (const row of rows) {
|
||||
process.stdout.write(row.map((cell, col) => padEnd(cell, widths[col])).join(" ") + "\n");
|
||||
}
|
||||
|
||||
process.stdout.write(dim(`\n共 ${total} 条记录 (Total: ${total})`) + "\n");
|
||||
process.stdout.write(dim(`\nTotal: ${total} records`) + "\n");
|
||||
}
|
||||
|
||||
export default defineCommand({
|
||||
|
||||
@@ -108,8 +108,7 @@ function printTable(models: ModelWithQpm[], noColor: boolean): void {
|
||||
const bold = noColor ? (t: string) => t : (t: string) => `\x1b[1m${t}\x1b[0m`;
|
||||
const dim = noColor ? (t: string) => t : (t: string) => `\x1b[2m${t}\x1b[0m`;
|
||||
|
||||
const headersCn = ["模型", "RPM", "TPM", "可设上限 TPM"];
|
||||
const headersEn = ["Model", "Req/min", "Token/min", "Max TPM"];
|
||||
const headers = ["Model", "Req/min", "Token/min", "Max TPM"];
|
||||
|
||||
const rows = models.map((m) => {
|
||||
const qpm = m.qpmInfo;
|
||||
@@ -135,27 +134,21 @@ function printTable(models: ModelWithQpm[], noColor: boolean): void {
|
||||
return;
|
||||
}
|
||||
|
||||
const widths = headersCn.map((label, col) =>
|
||||
Math.max(
|
||||
displayWidth(label),
|
||||
displayWidth(headersEn[col]),
|
||||
...rows.map((row) => displayWidth(row[col])),
|
||||
),
|
||||
const widths = headers.map((label, col) =>
|
||||
Math.max(displayWidth(label), ...rows.map((row) => displayWidth(row[col]))),
|
||||
);
|
||||
|
||||
const cnLine = headersCn.map((label, col) => bold(padEnd(label, widths[col]))).join(" ");
|
||||
const enLine = headersEn.map((label, col) => dim(padEnd(label, widths[col]))).join(" ");
|
||||
const headerLine = headers.map((label, col) => bold(padEnd(label, widths[col]))).join(" ");
|
||||
const separator = widths.map((w) => dim("─".repeat(w))).join("──");
|
||||
|
||||
process.stdout.write(cnLine + "\n");
|
||||
process.stdout.write(enLine + "\n");
|
||||
process.stdout.write(headerLine + "\n");
|
||||
process.stdout.write(separator + "\n");
|
||||
|
||||
for (const row of rows) {
|
||||
process.stdout.write(row.map((cell, col) => padEnd(cell, widths[col])).join(" ") + "\n");
|
||||
}
|
||||
|
||||
process.stdout.write(dim(`\n共 ${models.length} 个模型 (Total: ${models.length})`) + "\n");
|
||||
process.stdout.write(dim(`\nTotal: ${models.length} models`) + "\n");
|
||||
}
|
||||
|
||||
export default defineCommand({
|
||||
|
||||
@@ -21,9 +21,9 @@ export default defineCommand({
|
||||
{ flag: "--list-tools", description: "List available MCP tools and exit" },
|
||||
],
|
||||
examples: [
|
||||
'bl search web --query "阿里云百炼最新功能"',
|
||||
'bl search web --query "Alibaba Cloud Bailian latest features"',
|
||||
'bl search web --query "TypeScript 5.9 new features" --count 5',
|
||||
'bl search web --query "今日新闻"',
|
||||
'bl search web --query "Today\'s news"',
|
||||
"bl search web --list-tools",
|
||||
],
|
||||
async run(config: Config, flags: GlobalFlags) {
|
||||
|
||||
@@ -171,7 +171,8 @@ export default defineCommand({
|
||||
{ flag: "--language <lang>", description: "Language hint (e.g. zh, en, ja, ko, fr, de)" },
|
||||
{
|
||||
flag: "--instruction <text>",
|
||||
description: 'Natural language instruction to control speech style (e.g. "请用温柔的语调")',
|
||||
description:
|
||||
'Natural language instruction to control speech style (e.g. "Use a gentle tone")',
|
||||
},
|
||||
{ flag: "--enable-ssml", description: "Enable SSML markup parsing in input text" },
|
||||
{
|
||||
@@ -182,13 +183,13 @@ export default defineCommand({
|
||||
],
|
||||
examples: [
|
||||
"bl speech synthesize --list-voices --model cosyvoice-v3-flash",
|
||||
'bl speech synthesize --text "你好,我是千问" --voice <voice_id>',
|
||||
'bl speech synthesize --text "Hello, I am Qwen" --voice <voice_id>',
|
||||
'bl speech synthesize --text "Hello world" --voice <voice_id> --language en',
|
||||
"bl speech synthesize --text-file script.txt --out speech.wav --voice <voice_id>",
|
||||
'bl speech synthesize --text "今天天气真好" --voice <voice_id> --instruction "请用温柔的语调说话"',
|
||||
'bl speech synthesize --text "Today is a good day" --voice <voice_id> --instruction "Use a gentle tone"',
|
||||
'bl speech synthesize --text "Hello" --voice <voice_id> --format wav --sample-rate 24000',
|
||||
"# Stream to audio player (macOS)",
|
||||
'bl speech synthesize --text "你好" --voice <voice_id> --stream | afplay -',
|
||||
'bl speech synthesize --text "Hello" --voice <voice_id> --stream | afplay -',
|
||||
"# Pipe to ffplay",
|
||||
'bl speech synthesize --text "Hello" --voice <voice_id> --stream | ffplay -nodisp -autoexit -f s16le -ar 24000 -ac 1 -',
|
||||
],
|
||||
|
||||
@@ -78,8 +78,7 @@ function printTable(
|
||||
typeMap: Map<string, string>,
|
||||
noColor: boolean,
|
||||
): void {
|
||||
const headersCn = ["模型", "类型", "剩余/总量", "使用率", "过期时间", "用完即停"];
|
||||
const headersEn = ["Model", "Type", "Remaining/Total", "Usage", "Expires", "Auto-Stop"];
|
||||
const headers = ["Model", "Type", "Remaining/Total", "Usage", "Expires", "Auto-Stop"];
|
||||
|
||||
const rows = quotas.map((quota) => {
|
||||
const hasQuota = quota.quotaInitTotal != null && quota.quotaTotal != null;
|
||||
@@ -102,12 +101,8 @@ function printTable(
|
||||
];
|
||||
});
|
||||
|
||||
const widths = headersCn.map((label, col) =>
|
||||
Math.max(
|
||||
displayWidth(label),
|
||||
displayWidth(headersEn[col]),
|
||||
...rows.map((row) => displayWidth(row[col])),
|
||||
),
|
||||
const widths = headers.map((label, col) =>
|
||||
Math.max(displayWidth(label), ...rows.map((row) => displayWidth(row[col]))),
|
||||
);
|
||||
|
||||
const dim = noColor ? (text: string) => text : (text: string) => `\x1b[2m${text}\x1b[0m`;
|
||||
@@ -115,13 +110,11 @@ function printTable(
|
||||
const green = noColor ? (text: string) => text : (text: string) => `\x1b[32m${text}\x1b[0m`;
|
||||
const yellow = noColor ? (text: string) => text : (text: string) => `\x1b[33m${text}\x1b[0m`;
|
||||
|
||||
const autoStopCol = headersCn.length - 1;
|
||||
const cnLine = headersCn.map((label, col) => bold(padEnd(label, widths[col]))).join(" ");
|
||||
const enLine = headersEn.map((label, col) => dim(padEnd(label, widths[col]))).join(" ");
|
||||
const autoStopCol = headers.length - 1;
|
||||
const headerLine = headers.map((label, col) => bold(padEnd(label, widths[col]))).join(" ");
|
||||
const separator = widths.map((width) => dim("─".repeat(width))).join("──");
|
||||
|
||||
process.stdout.write(cnLine + "\n");
|
||||
process.stdout.write(enLine + "\n");
|
||||
process.stdout.write(headerLine + "\n");
|
||||
process.stdout.write(separator + "\n");
|
||||
|
||||
for (const row of rows) {
|
||||
|
||||
@@ -155,33 +155,32 @@ function resolveUsageMap(item: ModelStatisticItem): Record<string, number> {
|
||||
}
|
||||
|
||||
interface UsageLabel {
|
||||
cn: string;
|
||||
en: string;
|
||||
unit?: string;
|
||||
}
|
||||
|
||||
const USAGE_KEY_LABELS: Record<string, UsageLabel> = {
|
||||
total_token: { cn: "总 Token", en: "Total Tokens", unit: "tokens" },
|
||||
input_token: { cn: "输入 Token", en: "Input Tokens", unit: "tokens" },
|
||||
output_token: { cn: "输出 Token", en: "Output Tokens", unit: "tokens" },
|
||||
input_token_cache: { cn: "缓存 Token", en: "Cached Tokens", unit: "tokens" },
|
||||
input_token_cache_read: { cn: "缓存读取", en: "Cache Read", unit: "tokens" },
|
||||
input_token_cache_creation: { cn: "缓存创建", en: "Cache Creation", unit: "tokens" },
|
||||
thinking_input_token: { cn: "思考输入", en: "Thinking Input", unit: "tokens" },
|
||||
thinking_output_token: { cn: "思考输出", en: "Thinking Output", unit: "tokens" },
|
||||
text_input_token: { cn: "文本输入", en: "Text Input", unit: "tokens" },
|
||||
purein_text_output_token: { cn: "文本输出", en: "Text Output", unit: "tokens" },
|
||||
embedding_token: { cn: "向量", en: "Embedding", unit: "tokens" },
|
||||
image_number: { cn: "图片数", en: "Images", unit: "张" },
|
||||
video_duration: { cn: "视频时长", en: "Video Duration", unit: "秒" },
|
||||
content_duration: { cn: "音频时长", en: "Audio Duration", unit: "秒" },
|
||||
tts_text_number: { cn: "语音合成", en: "TTS Chars", unit: "字符" },
|
||||
total_token_avg: { cn: "平均 Token/次", en: "Avg Tokens/Req" },
|
||||
total_token: { en: "Total Tokens", unit: "tokens" },
|
||||
input_token: { en: "Input Tokens", unit: "tokens" },
|
||||
output_token: { en: "Output Tokens", unit: "tokens" },
|
||||
input_token_cache: { en: "Cached Tokens", unit: "tokens" },
|
||||
input_token_cache_read: { en: "Cache Read", unit: "tokens" },
|
||||
input_token_cache_creation: { en: "Cache Creation", unit: "tokens" },
|
||||
thinking_input_token: { en: "Thinking Input", unit: "tokens" },
|
||||
thinking_output_token: { en: "Thinking Output", unit: "tokens" },
|
||||
text_input_token: { en: "Text Input", unit: "tokens" },
|
||||
purein_text_output_token: { en: "Text Output", unit: "tokens" },
|
||||
embedding_token: { en: "Embedding", unit: "tokens" },
|
||||
image_number: { en: "Images", unit: "images" },
|
||||
video_duration: { en: "Video Duration", unit: "sec" },
|
||||
content_duration: { en: "Audio Duration", unit: "sec" },
|
||||
tts_text_number: { en: "TTS Chars", unit: "chars" },
|
||||
total_token_avg: { en: "Avg Tokens/Req" },
|
||||
};
|
||||
|
||||
function formatLabel(label: UsageLabel): string {
|
||||
const unitSuffix = label.unit ? ` [${label.unit}]` : "";
|
||||
return `${label.cn} (${label.en})${unitSuffix}`;
|
||||
return `${label.en}${unitSuffix}`;
|
||||
}
|
||||
|
||||
function printOverview(
|
||||
@@ -195,12 +194,12 @@ function printOverview(
|
||||
const dim = noColor ? (text: string) => text : (text: string) => `\x1b[2m${text}\x1b[0m`;
|
||||
|
||||
process.stdout.write(
|
||||
`${dim("时间范围 Period:")} ${formatDate(startTime)} ~ ${formatDate(endTime)} ${dim(`(${days} 天)`)}\n\n`,
|
||||
`${dim("Time Range Period:")} ${formatDate(startTime)} ~ ${formatDate(endTime)} ${dim(`(${days} days)`)}\n\n`,
|
||||
);
|
||||
|
||||
const rows: [string, string][] = [
|
||||
["调用模型数 (Models Called)", formatNumber(stat.modelCount ?? 0)],
|
||||
["调用成功次数 (Successful Calls)", formatNumber(stat.callSuccessCount ?? 0)],
|
||||
["Models Called", formatNumber(stat.modelCount ?? 0)],
|
||||
["Successful Calls", formatNumber(stat.callSuccessCount ?? 0)],
|
||||
];
|
||||
|
||||
for (const usage of stat.usages ?? []) {
|
||||
@@ -226,7 +225,7 @@ function printModelTable(
|
||||
const dim = noColor ? (text: string) => text : (text: string) => `\x1b[2m${text}\x1b[0m`;
|
||||
|
||||
process.stdout.write(
|
||||
`${dim("时间范围 Period:")} ${formatDate(startTime)} ~ ${formatDate(endTime)} ${dim(`(${days} 天)`)}\n\n`,
|
||||
`${dim("Time Range Period:")} ${formatDate(startTime)} ~ ${formatDate(endTime)} ${dim(`(${days} days)`)}\n\n`,
|
||||
);
|
||||
|
||||
if (items.length === 0) {
|
||||
@@ -257,20 +256,7 @@ function printModelTable(
|
||||
return (idxA === -1 ? 999 : idxA) - (idxB === -1 ? 999 : idxB);
|
||||
});
|
||||
|
||||
const headersCn = [
|
||||
"模型",
|
||||
"调用次数",
|
||||
...orderedKeys.map((key) => {
|
||||
const label = USAGE_KEY_LABELS[key];
|
||||
if (!label) return key;
|
||||
return label.unit ? `${label.cn} [${label.unit}]` : label.cn;
|
||||
}),
|
||||
];
|
||||
const headersEn = [
|
||||
"Model",
|
||||
"Calls",
|
||||
...orderedKeys.map((key) => USAGE_KEY_LABELS[key]?.en ?? key),
|
||||
];
|
||||
const headers = ["Model", "Calls", ...orderedKeys.map((key) => USAGE_KEY_LABELS[key]?.en ?? key)];
|
||||
const rows = items.map((item, idx) => [
|
||||
item.model,
|
||||
formatNumber(item.callSuccessCount ?? 0),
|
||||
@@ -280,20 +266,14 @@ function printModelTable(
|
||||
}),
|
||||
]);
|
||||
|
||||
const widths = headersCn.map((label, col) =>
|
||||
Math.max(
|
||||
displayWidth(label),
|
||||
displayWidth(headersEn[col]),
|
||||
...rows.map((row) => displayWidth(row[col])),
|
||||
),
|
||||
const widths = headers.map((label, col) =>
|
||||
Math.max(displayWidth(label), ...rows.map((row) => displayWidth(row[col]))),
|
||||
);
|
||||
|
||||
const cnLine = headersCn.map((label, col) => bold(padEnd(label, widths[col]))).join(" ");
|
||||
const enLine = headersEn.map((label, col) => dim(padEnd(label, widths[col]))).join(" ");
|
||||
const headerLine = headers.map((label, col) => bold(padEnd(label, widths[col]))).join(" ");
|
||||
const separator = widths.map((width) => dim("─".repeat(width))).join("──");
|
||||
|
||||
process.stdout.write(cnLine + "\n");
|
||||
process.stdout.write(enLine + "\n");
|
||||
process.stdout.write(headerLine + "\n");
|
||||
process.stdout.write(separator + "\n");
|
||||
|
||||
for (const row of rows) {
|
||||
@@ -301,7 +281,7 @@ function printModelTable(
|
||||
process.stdout.write(cells.join(" ") + "\n");
|
||||
}
|
||||
|
||||
process.stdout.write(dim(`\n共 ${items.length} 个模型 (Total: ${items.length})`) + "\n");
|
||||
process.stdout.write(dim(`\nTotal: ${items.length} models`) + "\n");
|
||||
}
|
||||
|
||||
export default defineCommand({
|
||||
|
||||
@@ -39,7 +39,10 @@ export default defineCommand({
|
||||
description: "Input video URL or local file (mp4/mov, 2-10s)",
|
||||
required: true,
|
||||
},
|
||||
{ flag: "--prompt <text>", description: 'Edit instruction (e.g. "将画面转换为黏土风格")' },
|
||||
{
|
||||
flag: "--prompt <text>",
|
||||
description: 'Edit instruction (e.g. "Convert the scene to a claymation style")',
|
||||
},
|
||||
{ flag: "--ref-image <url>", description: "Reference image URL (up to 4, comma-separated)" },
|
||||
{
|
||||
flag: "--negative-prompt <text>",
|
||||
@@ -78,10 +81,10 @@ export default defineCommand({
|
||||
},
|
||||
],
|
||||
examples: [
|
||||
'bl video edit --video https://example.com/input.mp4 --prompt "将整个画面转换为黏土风格"',
|
||||
'bl video edit --video https://example.com/input.mp4 --prompt "替换衣服为图片中的款式" --ref-image https://example.com/clothes.png',
|
||||
'bl video edit --video https://example.com/input.mp4 --prompt "Convert the entire scene to claymation style"',
|
||||
'bl video edit --video https://example.com/input.mp4 --prompt "Replace the outfit with the style shown in the image" --ref-image https://example.com/clothes.png',
|
||||
'bl video edit --video https://example.com/input.mp4 --prompt "Convert to anime style" --resolution 720P --download output.mp4',
|
||||
'bl video edit --video https://example.com/input.mp4 --prompt "给视频里的小猫穿上衣服" --watermark false',
|
||||
'bl video edit --video https://example.com/input.mp4 --prompt "Put clothes on the kitten in the video" --watermark false',
|
||||
],
|
||||
async run(config: Config, flags: GlobalFlags) {
|
||||
// --- Validate video URL ---
|
||||
|
||||
@@ -85,9 +85,9 @@ export default defineCommand({
|
||||
},
|
||||
],
|
||||
examples: [
|
||||
'bl video generate --prompt "一个人在读书,静态镜头"',
|
||||
'bl video generate --prompt "A person reading a book, static shot"',
|
||||
'bl video generate --prompt "Ocean waves at sunset." --download sunset.mp4',
|
||||
'bl video generate --image https://example.com/cat.png --prompt "让画面中的猫动起来"',
|
||||
'bl video generate --image https://example.com/cat.png --prompt "Make the cat in the scene move"',
|
||||
'bl video generate --prompt "Mountain landscape" --resolution 1280*720 --duration 5',
|
||||
'bl video generate --prompt "A cat playing with a ball" --watermark false',
|
||||
],
|
||||
|
||||
@@ -36,7 +36,7 @@ export default defineCommand({
|
||||
{ flag: "--model <model>", description: "Model ID (default: happyhorse-1.0-r2v)" },
|
||||
{
|
||||
flag: "--prompt <text>",
|
||||
description: "Video description with reference markers (图1, 视频1, etc.)",
|
||||
description: "Video description with reference markers (image1, video1, etc.)",
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
@@ -88,11 +88,11 @@ export default defineCommand({
|
||||
},
|
||||
],
|
||||
examples: [
|
||||
'bl video ref --prompt "图1在草地上奔跑" --image person.jpg',
|
||||
'bl video ref --prompt "视频1在弹吉他,图1走过来" --ref-video scene.mp4 --image person.jpg',
|
||||
'bl video ref --prompt "图1说话" --image person.jpg --image-voice voice.mp3 --resolution 1080P',
|
||||
'bl video ref --prompt "图1和图2在对话" --image a.jpg --image b.jpg --image-voice va.mp3 --image-voice vb.mp3',
|
||||
'bl video ref --prompt "图1在喝水" --image person.jpg --watermark false',
|
||||
'bl video ref --prompt "Image1 running on the grass" --image person.jpg',
|
||||
'bl video ref --prompt "Video 1 plays guitar, Image 1 walks over" --ref-video scene.mp4 --image person.jpg',
|
||||
'bl video ref --prompt "Image 1 speaks" --image person.jpg --image-voice voice.mp3 --resolution 1080P',
|
||||
'bl video ref --prompt "Image 1 and Image 2 have a conversation" --image a.jpg --image b.jpg --image-voice va.mp3 --image-voice vb.mp3',
|
||||
'bl video ref --prompt "Image 1 drinks water" --image person.jpg --watermark false',
|
||||
],
|
||||
async run(config: Config, flags: GlobalFlags) {
|
||||
// --- Validate prompt ---
|
||||
@@ -100,7 +100,7 @@ export default defineCommand({
|
||||
if (!prompt) {
|
||||
if (isInteractive({ nonInteractive: config.nonInteractive })) {
|
||||
const hint = await promptText({
|
||||
message: "Enter your video prompt (use 图1, 视频1 to reference inputs):",
|
||||
message: "Enter your video prompt (use Image1, Video1 to reference inputs):",
|
||||
});
|
||||
if (!hint) {
|
||||
process.stderr.write("Video generation cancelled.\n");
|
||||
@@ -119,7 +119,7 @@ export default defineCommand({
|
||||
throw new BailianError(
|
||||
"At least one --image or --ref-video is required.",
|
||||
ExitCode.USAGE,
|
||||
'bl video ref --prompt "描述" --image person.jpg',
|
||||
'bl video ref --prompt "description" --image person.jpg',
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -72,8 +72,8 @@ export default defineCommand({
|
||||
],
|
||||
examples: [
|
||||
"bl vision describe --image photo.jpg",
|
||||
'bl vision describe --image https://example.com/photo.jpg --prompt "这只狗是什么品种?"',
|
||||
'bl vision describe --video https://example.com/video.mp4 --prompt "总结视频内容"',
|
||||
'bl vision describe --image https://example.com/photo.jpg --prompt "What breed is this dog?"',
|
||||
'bl vision describe --video https://example.com/video.mp4 --prompt "Summarize the video content"',
|
||||
"bl vision describe --video ./local-video.mp4",
|
||||
'bl vision describe --image photo.png --prompt "Extract the text" --model qwen-vl-plus',
|
||||
],
|
||||
|
||||
@@ -46,8 +46,7 @@ function printTable(workspaces: WorkspaceInfo[], noColor: boolean): void {
|
||||
const dim = noColor ? (text: string) => text : (text: string) => `\x1b[2m${text}\x1b[0m`;
|
||||
const green = noColor ? (text: string) => text : (text: string) => `\x1b[32m${text}\x1b[0m`;
|
||||
|
||||
const headersCn = ["空间名称", "Workspace ID", "默认空间"];
|
||||
const headersEn = ["Name", "", "Default"];
|
||||
const headers = ["Name", "Workspace ID", "Default"];
|
||||
|
||||
const rows = workspaces.map((ws) => [
|
||||
ws.agentName,
|
||||
@@ -55,20 +54,14 @@ function printTable(workspaces: WorkspaceInfo[], noColor: boolean): void {
|
||||
ws.defaultAgent ? "Yes" : "-",
|
||||
]);
|
||||
|
||||
const widths = headersCn.map((label, col) =>
|
||||
Math.max(
|
||||
displayWidth(label),
|
||||
displayWidth(headersEn[col]),
|
||||
...rows.map((row) => displayWidth(row[col])),
|
||||
),
|
||||
const widths = headers.map((label, col) =>
|
||||
Math.max(displayWidth(label), ...rows.map((row) => displayWidth(row[col]))),
|
||||
);
|
||||
|
||||
const cnLine = headersCn.map((label, col) => bold(padEnd(label, widths[col]))).join(" ");
|
||||
const enLine = headersEn.map((label, col) => dim(padEnd(label, widths[col]))).join(" ");
|
||||
const headerLine = headers.map((label, col) => bold(padEnd(label, widths[col]))).join(" ");
|
||||
const separator = widths.map((width) => dim("─".repeat(width))).join("──");
|
||||
|
||||
process.stdout.write(cnLine + "\n");
|
||||
process.stdout.write(enLine + "\n");
|
||||
process.stdout.write(headerLine + "\n");
|
||||
process.stdout.write(separator + "\n");
|
||||
|
||||
for (const row of rows) {
|
||||
@@ -79,9 +72,7 @@ function printTable(workspaces: WorkspaceInfo[], noColor: boolean): void {
|
||||
process.stdout.write(cells.join(" ") + "\n");
|
||||
}
|
||||
|
||||
process.stdout.write(
|
||||
dim(`\n共 ${workspaces.length} 个空间 (Total: ${workspaces.length})`) + "\n",
|
||||
);
|
||||
process.stdout.write(dim(`\nTotal: ${workspaces.length}`) + "\n");
|
||||
}
|
||||
|
||||
export default defineCommand({
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { API_KEY_PAGE } from "../urls.ts";
|
||||
|
||||
const QUICK_START_TASKS = [
|
||||
"帮我生成一套鸭舌帽的亚马逊电商主图(白底 + 场景图 + 模特上身图)",
|
||||
"帮我生成一段 3 分钟的幽默相声音频",
|
||||
"帮我生成一套小红帽故事绘本 PDF(含插图)",
|
||||
"帮我分析这个视频的内容并写一篇小红书文案",
|
||||
"Help me generate a set of Amazon e-commerce main images for baseball caps (white background + lifestyle shots + model wear shots)",
|
||||
"Help me generate a 3-minute humorous crosstalk audio clip",
|
||||
"Help me generate a Little Red Riding Hood picture-book PDF (with illustrations)",
|
||||
"Help me analyze this video and write a Xiaohongshu-style post",
|
||||
];
|
||||
|
||||
function colors() {
|
||||
|
||||
@@ -96,7 +96,7 @@ describe.skipIf(!isConsoleE2EReady())("e2e: quota(Console)", () => {
|
||||
expect(data.data?.input?.supports).toBeUndefined();
|
||||
});
|
||||
|
||||
test("quota list 文本输出包含双行表头", async () => {
|
||||
test("quota list 文本输出包含英文表头", async () => {
|
||||
const { stdout, stderr, exitCode } = await runCli([
|
||||
"quota",
|
||||
"list",
|
||||
@@ -105,11 +105,9 @@ describe.skipIf(!isConsoleE2EReady())("e2e: quota(Console)", () => {
|
||||
"--no-color",
|
||||
]);
|
||||
expect(exitCode, stderr).toBe(0);
|
||||
expect(stdout).toContain("模型");
|
||||
expect(stdout).toContain("Model");
|
||||
expect(stdout).toContain("RPM");
|
||||
expect(stdout).toContain("TPM");
|
||||
expect(stdout).toContain("可设上限 TPM");
|
||||
expect(stdout).toContain("Req/min");
|
||||
expect(stdout).toContain("Token/min");
|
||||
expect(stdout).toContain("Max TPM");
|
||||
});
|
||||
|
||||
@@ -125,7 +123,7 @@ describe.skipIf(!isConsoleE2EReady())("e2e: quota(Console)", () => {
|
||||
]);
|
||||
expect(exitCode, stderr).toBe(0);
|
||||
expect(stdout).toContain("qwen3.6-plus");
|
||||
expect(stdout).toMatch(/共 1 个模型/);
|
||||
expect(stdout).toMatch(/Total: 1 models/);
|
||||
});
|
||||
|
||||
test("quota list --model 不存在的模型报错", async () => {
|
||||
@@ -235,7 +233,7 @@ describe.skipIf(!isConsoleE2EReady())("e2e: quota(Console)", () => {
|
||||
expect(data.apis).toContain("zeldaEasy.bailian-telemetry.monitor.getMonitorData");
|
||||
});
|
||||
|
||||
test("quota check 文本输出包含双行表头", async () => {
|
||||
test("quota check 文本输出包含英文表头", async () => {
|
||||
const { stdout, stderr, exitCode } = await runCli([
|
||||
"quota",
|
||||
"check",
|
||||
@@ -244,12 +242,10 @@ describe.skipIf(!isConsoleE2EReady())("e2e: quota(Console)", () => {
|
||||
"--no-color",
|
||||
]);
|
||||
expect(exitCode, stderr).toBe(0);
|
||||
expect(stdout).toContain("模型");
|
||||
expect(stdout).toContain("Model");
|
||||
expect(stdout).toContain("RPM 用量/限额");
|
||||
expect(stdout).toContain("RPM Usage/Limit");
|
||||
expect(stdout).toContain("TPM 用量/限额");
|
||||
expect(stdout).toContain("状态");
|
||||
expect(stdout).toContain("TPM Usage/Limit");
|
||||
expect(stdout).toContain("Status");
|
||||
});
|
||||
|
||||
test("quota check --model 指定单模型", async () => {
|
||||
@@ -264,7 +260,7 @@ describe.skipIf(!isConsoleE2EReady())("e2e: quota(Console)", () => {
|
||||
]);
|
||||
expect(exitCode, stderr).toBe(0);
|
||||
expect(stdout).toContain("qwen3.6-plus");
|
||||
expect(stdout).toMatch(/共 1 个模型/);
|
||||
expect(stdout).toMatch(/Total: 1 models/);
|
||||
});
|
||||
|
||||
test("quota check --model 逗号分隔多模型", async () => {
|
||||
@@ -280,7 +276,7 @@ describe.skipIf(!isConsoleE2EReady())("e2e: quota(Console)", () => {
|
||||
expect(exitCode, stderr).toBe(0);
|
||||
expect(stdout).toContain("qwen3.6-plus");
|
||||
expect(stdout).toContain("qwen-plus");
|
||||
expect(stdout).toMatch(/共 2 个模型/);
|
||||
expect(stdout).toMatch(/Total: 2 models/);
|
||||
});
|
||||
|
||||
test("quota check JSON 输出包含用量和限额字段", async () => {
|
||||
@@ -311,7 +307,7 @@ describe.skipIf(!isConsoleE2EReady())("e2e: quota(Console)", () => {
|
||||
expect(data[0].tpmLimit).toBeTypeOf("number");
|
||||
});
|
||||
|
||||
test("quota check 状态列显示正常/接近限流/已限流之一", async () => {
|
||||
test("quota check 状态列显示 Normal/Near limit/Rate Limited 之一", async () => {
|
||||
const { stdout, stderr, exitCode } = await runCli([
|
||||
"quota",
|
||||
"check",
|
||||
@@ -323,7 +319,7 @@ describe.skipIf(!isConsoleE2EReady())("e2e: quota(Console)", () => {
|
||||
]);
|
||||
expect(exitCode, stderr).toBe(0);
|
||||
const hasStatus =
|
||||
stdout.includes("正常") || stdout.includes("接近限流") || stdout.includes("已限流");
|
||||
stdout.includes("Normal") || stdout.includes("Near limit") || stdout.includes("Rate Limited");
|
||||
expect(hasStatus).toBe(true);
|
||||
});
|
||||
|
||||
|
||||
@@ -176,8 +176,8 @@ describe.skipIf(!isConsoleE2EReady())("e2e: usage stats(Console)", () => {
|
||||
expect(data.successResponse).toBe(true);
|
||||
});
|
||||
|
||||
test("usage stats 概览文本输出包含中英文表头", async () => {
|
||||
const { stderr, exitCode } = await runCli([
|
||||
test("usage stats 概览文本输出包含英文标签", async () => {
|
||||
const { stdout, stderr, exitCode } = await runCli([
|
||||
"usage",
|
||||
"stats",
|
||||
"--workspace-id",
|
||||
@@ -187,10 +187,13 @@ describe.skipIf(!isConsoleE2EReady())("e2e: usage stats(Console)", () => {
|
||||
"--no-color",
|
||||
]);
|
||||
expect(exitCode, stderr).toBe(0);
|
||||
expect(stdout).toContain("Time Range Period:");
|
||||
expect(stdout).toContain("Models Called");
|
||||
expect(stdout).toContain("Successful Calls");
|
||||
});
|
||||
|
||||
test("usage stats 概览文本输出包含 Token 用量", async () => {
|
||||
const { stderr, exitCode } = await runCli([
|
||||
const { stdout, stderr, exitCode } = await runCli([
|
||||
"usage",
|
||||
"stats",
|
||||
"--workspace-id",
|
||||
@@ -200,10 +203,11 @@ describe.skipIf(!isConsoleE2EReady())("e2e: usage stats(Console)", () => {
|
||||
"--no-color",
|
||||
]);
|
||||
expect(exitCode, stderr).toBe(0);
|
||||
expect(stdout).toMatch(/Total Tokens|Input Tokens|Output Tokens/);
|
||||
});
|
||||
|
||||
test("usage stats --model 单模型文本输出包含双行表头", async () => {
|
||||
const { stderr, exitCode } = await runCli([
|
||||
test("usage stats --model 单模型文本输出包含英文表头", async () => {
|
||||
const { stdout, stderr, exitCode } = await runCli([
|
||||
"usage",
|
||||
"stats",
|
||||
"--workspace-id",
|
||||
@@ -215,10 +219,14 @@ describe.skipIf(!isConsoleE2EReady())("e2e: usage stats(Console)", () => {
|
||||
"--no-color",
|
||||
]);
|
||||
expect(exitCode, stderr).toBe(0);
|
||||
expect(stdout).toContain("Time Range Period:");
|
||||
expect(stdout).toContain("Model");
|
||||
expect(stdout).toContain("Calls");
|
||||
expect(stdout).toMatch(/Total: \d+ models/);
|
||||
});
|
||||
|
||||
test("usage stats --model 逗号分隔多模型返回多行", async () => {
|
||||
const { stderr, exitCode } = await runCli([
|
||||
const { stdout, stderr, exitCode } = await runCli([
|
||||
"usage",
|
||||
"stats",
|
||||
"--workspace-id",
|
||||
@@ -230,6 +238,9 @@ describe.skipIf(!isConsoleE2EReady())("e2e: usage stats(Console)", () => {
|
||||
"--no-color",
|
||||
]);
|
||||
expect(exitCode, stderr).toBe(0);
|
||||
expect(stdout).toContain("qwen3.6-plus");
|
||||
expect(stdout).toContain("deepseek-v4-pro");
|
||||
expect(stdout).toMatch(/Total: 2 models/);
|
||||
});
|
||||
|
||||
test("usage stats --model 不存在的模型返回空表格", async () => {
|
||||
@@ -249,7 +260,7 @@ describe.skipIf(!isConsoleE2EReady())("e2e: usage stats(Console)", () => {
|
||||
});
|
||||
|
||||
test("usage stats --days 1 短时间范围正常返回", async () => {
|
||||
const { stderr, exitCode } = await runCli([
|
||||
const { stdout, stderr, exitCode } = await runCli([
|
||||
"usage",
|
||||
"stats",
|
||||
"--workspace-id",
|
||||
@@ -261,10 +272,11 @@ describe.skipIf(!isConsoleE2EReady())("e2e: usage stats(Console)", () => {
|
||||
"--no-color",
|
||||
]);
|
||||
expect(exitCode, stderr).toBe(0);
|
||||
expect(stdout).toContain("(1 days)");
|
||||
});
|
||||
|
||||
test("usage stats --type Vision 按类型过滤", async () => {
|
||||
const { stderr, exitCode } = await runCli([
|
||||
const { stdout, stderr, exitCode } = await runCli([
|
||||
"usage",
|
||||
"stats",
|
||||
"--workspace-id",
|
||||
@@ -276,5 +288,6 @@ describe.skipIf(!isConsoleE2EReady())("e2e: usage stats(Console)", () => {
|
||||
"--no-color",
|
||||
]);
|
||||
expect(exitCode, stderr).toBe(0);
|
||||
expect(stdout).toContain("Time Range Period:");
|
||||
});
|
||||
});
|
||||
|
||||
@@ -140,7 +140,7 @@ Commonly used:
|
||||
|
||||
```bash
|
||||
# Chat
|
||||
bl text chat --message "用中文写一首关于春天的诗"
|
||||
bl text chat --message "Write a poem about spring in Chinese"
|
||||
|
||||
# Image
|
||||
bl image generate --prompt "A cat in space" --out-dir ./out/
|
||||
@@ -149,11 +149,11 @@ bl image generate --prompt "A cat in space" --out-dir ./out/
|
||||
bl video generate --prompt "Sunset on the beach" --download sunset.mp4
|
||||
|
||||
# Omni (local files OK)
|
||||
bl omni --message "描述视频内容" --video ./demo.mp4 --text-only
|
||||
bl omni --message "Describe the video content" --video ./demo.mp4 --text-only
|
||||
|
||||
# App
|
||||
bl app list --output json
|
||||
bl app call --app-id <code> --prompt "你好"
|
||||
bl app call --app-id <code> --prompt "Hello"
|
||||
```
|
||||
|
||||
More examples per command: see `reference/<group>.md` (e.g. [`reference/text.md`](reference/text.md)).
|
||||
|
||||
@@ -137,9 +137,9 @@ If it still fails with INCLUDE signals → offer reporting.
|
||||
|
||||
When INCLUDE matches, ask in **Chinese** (adjust if the user prefers English):
|
||||
|
||||
> `bl` 命令出现了疑似 CLI 自身的问题。
|
||||
> 是否需要帮你整理信息,向百炼 CLI 团队提交 GitHub Issue?
|
||||
> 提交前会自动脱敏 API Key;你也可以只复制模版自行提交。
|
||||
> The `bl` command hit what looks like a CLI bug.
|
||||
> Would you like help gathering details to file a GitHub Issue with the Bailian CLI team?
|
||||
> API Keys will be redacted automatically before submission; you can also copy the template and submit yourself.
|
||||
|
||||
If the user agrees → [Collect information](#collect-information) → [Submit](#submit).
|
||||
|
||||
@@ -290,7 +290,7 @@ If a matching open issue exists:
|
||||
|
||||
Before submitting, **always show the redacted issue body to the user** and ask for confirmation:
|
||||
|
||||
> 以下是即将提交的 Issue 内容(已脱敏),请确认是否提交:
|
||||
> Below is the redacted Issue content to be submitted—confirm submission?
|
||||
> show body
|
||||
|
||||
Only proceed after the user confirms.
|
||||
@@ -329,7 +329,7 @@ If `gh` is not installed or not authenticated:
|
||||
1. Write the complete redacted issue body to a local file (e.g. `./cli-bug-report.md`)
|
||||
2. Print the file content to the user
|
||||
3. Provide the direct URL: [https://github.com/modelstudioai/cli/issues/new?template=bug_report.yml](https://github.com/modelstudioai/cli/issues/new?template=bug_report.yml)
|
||||
4. Instruct: "请在浏览器中打开上面的链接,将内容粘贴到 issue body 中提交。"
|
||||
4. Instruct: "Open the link above in your browser and paste the content into the issue body to submit."
|
||||
|
||||
Do **not** block on `gh` — always provide a manual path.
|
||||
|
||||
|
||||
@@ -40,27 +40,27 @@ Index: [index.md](index.md)
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
bl app call --app-id abc123 --prompt "你好"
|
||||
bl app call --app-id abc123 --prompt "Hello"
|
||||
```
|
||||
|
||||
```bash
|
||||
bl app call --app-id abc123 --prompt "描述这张图片" --image https://example.com/photo.jpg
|
||||
bl app call --app-id abc123 --prompt "Describe this image" --image https://example.com/photo.jpg
|
||||
```
|
||||
|
||||
```bash
|
||||
bl app call --app-id abc123 --prompt "分析图片" --image img1.jpg --image img2.jpg
|
||||
bl app call --app-id abc123 --prompt "Analyze the image" --image img1.jpg --image img2.jpg
|
||||
```
|
||||
|
||||
```bash
|
||||
bl app call --app-id abc123 --prompt "继续" --session-id sess_xxx --stream
|
||||
bl app call --app-id abc123 --prompt "Continue" --session-id sess_xxx --stream
|
||||
```
|
||||
|
||||
```bash
|
||||
bl app call --app-id abc123 --prompt "搜索资料" --pipeline-ids pipe1,pipe2
|
||||
bl app call --app-id abc123 --prompt "Search for materials" --pipeline-ids pipe1,pipe2
|
||||
```
|
||||
|
||||
```bash
|
||||
bl app call --app-id abc123 --prompt "开始" --biz-params '{"key":"value"}'
|
||||
bl app call --app-id abc123 --prompt "Start" --biz-params '{"key":"value"}'
|
||||
```
|
||||
|
||||
### `bl app list`
|
||||
@@ -87,7 +87,7 @@ bl app list
|
||||
```
|
||||
|
||||
```bash
|
||||
bl app list --name 客服
|
||||
bl app list --name customer service
|
||||
```
|
||||
|
||||
```bash
|
||||
|
||||
@@ -41,7 +41,7 @@ Index: [index.md](index.md)
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
bl image edit --image ./photo.png --prompt "把背景换成海滩"
|
||||
bl image edit --image ./photo.png --prompt "Replace the background with a beach"
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -49,7 +49,7 @@ bl image edit --image https://example.com/logo.png --prompt "Change color to blu
|
||||
```
|
||||
|
||||
```bash
|
||||
bl image edit --image ./a.png --image ./b.png --prompt "把两张图合并成一张拼图"
|
||||
bl image edit --image ./a.png --image ./b.png --prompt "Merge two images into one collage"
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -57,7 +57,7 @@ bl image edit --image https://example.com/photo.png --prompt "Remove the person"
|
||||
```
|
||||
|
||||
```bash
|
||||
bl image edit --image ./photo.png --prompt "把背景换成海滩" --watermark false
|
||||
bl image edit --image ./photo.png --prompt "Replace the background with a beach" --watermark false
|
||||
```
|
||||
|
||||
### `bl image generate`
|
||||
@@ -88,7 +88,7 @@ bl image edit --image ./photo.png --prompt "把背景换成海滩" --watermark f
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
bl image generate --prompt "一只穿太空服的猫在火星上"
|
||||
bl image generate --prompt "A cat in a spacesuit on Mars"
|
||||
```
|
||||
|
||||
```bash
|
||||
|
||||
@@ -47,9 +47,9 @@ Index: [index.md](index.md)
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
bl knowledge retrieve --index-id idx_xxx --query "如何使用阿里云百炼"
|
||||
bl knowledge retrieve --index-id idx_xxx --query "How to use Alibaba Cloud Bailian"
|
||||
```
|
||||
|
||||
```bash
|
||||
bl knowledge retrieve --api-key $DASHSCOPE_API_KEY --index-id idx_xxx --query "RAG检索" --rerank --rerank-model qwen3-rerank-hybrid
|
||||
bl knowledge retrieve --api-key $DASHSCOPE_API_KEY --index-id idx_xxx --query "RAG retrieval" --rerank --rerank-model qwen3-rerank-hybrid
|
||||
```
|
||||
|
||||
@@ -36,11 +36,11 @@ Index: [index.md](index.md)
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
bl mcp call market-cmapi00073529.SmartStockSelection --query "筛选ROE>15%的消费股"
|
||||
bl mcp call market-cmapi00073529.SmartStockSelection --query "Screen consumer stocks with ROE > 15%"
|
||||
```
|
||||
|
||||
```bash
|
||||
bl mcp call market-cmapi00073529.FinQuery --json '{"q":"贵州茅台","limit":5}'
|
||||
bl mcp call market-cmapi00073529.FinQuery --json '{"q":"Guizhou Maotai","limit":5}'
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -72,7 +72,7 @@ bl mcp list
|
||||
```
|
||||
|
||||
```bash
|
||||
bl mcp list --name 金融
|
||||
bl mcp list --name finance
|
||||
```
|
||||
|
||||
```bash
|
||||
|
||||
@@ -40,15 +40,15 @@ Index: [index.md](index.md)
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
bl memory add --user-id user1 --content "用户喜欢Python编程"
|
||||
bl memory add --user-id user1 --content "The user likes Python programming"
|
||||
```
|
||||
|
||||
```bash
|
||||
bl memory add --user-id user1 --messages '[{"role":"user","content":"我喜欢旅行"}]'
|
||||
bl memory add --user-id user1 --messages '[{"role":"user","content":"I like traveling"}]'
|
||||
```
|
||||
|
||||
```bash
|
||||
bl memory add --user-id user1 --content "住在北京" --profile-schema schema_xxx
|
||||
bl memory add --user-id user1 --content "Lives in Beijing" --profile-schema schema_xxx
|
||||
```
|
||||
|
||||
### `bl memory delete`
|
||||
@@ -110,16 +110,16 @@ bl memory list --user-id user1 --page-size 20 --page 2
|
||||
|
||||
#### Options
|
||||
|
||||
| Flag | Type | Required | Description |
|
||||
| ---------------------- | ------ | -------- | ------------------------------------------------------------ |
|
||||
| `--name <name>` | string | yes | Schema name (required) |
|
||||
| `--description <text>` | string | no | Schema description |
|
||||
| `--attributes <json>` | string | yes | Attributes JSON array: [{"name":"age","description":"年龄"}] |
|
||||
| Flag | Type | Required | Description |
|
||||
| ---------------------- | ------ | -------- | ----------------------------------------------------------- |
|
||||
| `--name <name>` | string | yes | Schema name (required) |
|
||||
| `--description <text>` | string | no | Schema description |
|
||||
| `--attributes <json>` | string | yes | Attributes JSON array: [{"name":"age","description":"age"}] |
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
bl memory profile create --name "user_basic" --attributes '[{"name":"age","description":"年龄"},{"name":"hobby","description":"爱好"}]'
|
||||
bl memory profile create --name "user_basic" --attributes '[{"name":"age","description":"age"},{"name":"hobby","description":"hobby"}]'
|
||||
```
|
||||
|
||||
### `bl memory profile get`
|
||||
@@ -164,11 +164,11 @@ bl memory profile get --schema-id schema_xxx --user-id user1
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
bl memory search --user-id user1 --query "编程偏好"
|
||||
bl memory search --user-id user1 --query "programming preferences"
|
||||
```
|
||||
|
||||
```bash
|
||||
bl memory search --user-id user1 --messages '[{"role":"user","content":"推荐一本书"}]' --top-k 5
|
||||
bl memory search --user-id user1 --messages '[{"role":"user","content":"recommend a book"}]' --top-k 5
|
||||
```
|
||||
|
||||
### `bl memory update`
|
||||
@@ -191,5 +191,5 @@ bl memory search --user-id user1 --messages '[{"role":"user","content":"推荐
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
bl memory update --node-id node_xxx --user-id user1 --content "更新后的记忆内容"
|
||||
bl memory update --node-id node_xxx --user-id user1 --content "updated memory content"
|
||||
```
|
||||
|
||||
@@ -23,45 +23,45 @@ Index: [index.md](index.md)
|
||||
|
||||
#### Options
|
||||
|
||||
| Flag | Type | Required | Description |
|
||||
| ---------------------- | ------- | -------- | ----------------------------------------------------------------------------- |
|
||||
| `--message <text>` | array | yes | Message text (repeatable, prefix role: to set role) |
|
||||
| `--model <model>` | string | no | Model ID (default: qwen3.5-omni-plus) |
|
||||
| `--system <text>` | string | no | System prompt |
|
||||
| `--image <url>` | array | no | Image URL or local file (repeatable) |
|
||||
| `--audio <url>` | array | no | Audio URL or local file (.wav/.mp3/.amr/.aac/.m4a/.ogg/.3gp/.3gpp) |
|
||||
| `--video <url>` | array | no | Video file URL / local path, or comma-separated frame URLs |
|
||||
| `--voice <voice>` | string | no | Output voice (default: Cherry). Options: Chelsie, Cherry, Ethan, Serena, Tina |
|
||||
| `--audio-format <fmt>` | string | no | Audio output format (default: wav) |
|
||||
| `--audio-out <path>` | string | no | Save audio to file (default: auto-generate) |
|
||||
| `--text-only` | boolean | no | Output text only, no audio generation |
|
||||
| `--max-tokens <n>` | number | no | Maximum tokens to generate |
|
||||
| `--temperature <n>` | number | no | Sampling temperature (0.0, 2.0] |
|
||||
| Flag | Type | Required | Description |
|
||||
| ---------------------- | ------- | -------- | ------------------------------------------------------------------------------------ |
|
||||
| `--message <text>` | array | yes | Message text (repeatable, prefix role: to set role) |
|
||||
| `--model <model>` | string | no | Model ID (default: qwen3.5-omni-plus) |
|
||||
| `--system <text>` | string | no | System prompt |
|
||||
| `--image <url>` | array | no | Image URL or local file (repeatable) |
|
||||
| `--audio <url>` | array | no | Audio URL or local file (.wav/.mp3/.amr/.aac/.m4a/.ogg/.3gp/.3gpp) |
|
||||
| `--video <url>` | array | no | Video file URL / local path, or comma-separated frame URLs |
|
||||
| `--voice <voice>` | string | no | Output voice (default: Cherry). Options: Chelsie, Cherry, Ethan, Serena, Sunny, Tina |
|
||||
| `--audio-format <fmt>` | string | no | Audio output format (default: wav) |
|
||||
| `--audio-out <path>` | string | no | Save audio to file (default: auto-generate) |
|
||||
| `--text-only` | boolean | no | Output text only, no audio generation |
|
||||
| `--max-tokens <n>` | number | no | Maximum tokens to generate |
|
||||
| `--temperature <n>` | number | no | Sampling temperature (0.0, 2.0] |
|
||||
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
bl omni --message "你好,你是谁?"
|
||||
bl omni --message "Hello, who are you?"
|
||||
```
|
||||
|
||||
```bash
|
||||
bl omni --message "描述这张图片" --image ./photo.jpg
|
||||
bl omni --message "Describe this image" --image ./photo.jpg
|
||||
```
|
||||
|
||||
```bash
|
||||
bl omni --message "这段音频在说什么?" --audio https://example.com/audio.wav
|
||||
bl omni --message "What is this audio saying?" --audio https://example.com/audio.wav
|
||||
```
|
||||
|
||||
```bash
|
||||
bl omni --message "总结这个视频" --video https://example.com/video.mp4
|
||||
bl omni --message "Summarize this video" --video https://example.com/video.mp4
|
||||
```
|
||||
|
||||
```bash
|
||||
bl omni --message "这个视频讲了什么" --video ./local-video.mp4 --text-only
|
||||
bl omni --message "What is this video about?" --video ./local-video.mp4 --text-only
|
||||
```
|
||||
|
||||
```bash
|
||||
bl omni --message "用四川话回答:今天天气怎么样" --voice Serena
|
||||
bl omni --message "Answer in Sichuan dialect: How's the weather today?" --voice Sunny
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -69,5 +69,5 @@ bl omni --message "Hello" --text-only --output json
|
||||
```
|
||||
|
||||
```bash
|
||||
bl omni --message "朗读这段话" --audio-out greeting.wav
|
||||
bl omni --message "Read this passage aloud" --audio-out greeting.wav
|
||||
```
|
||||
|
||||
@@ -32,7 +32,7 @@ Index: [index.md](index.md)
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
bl search web --query "阿里云百炼最新功能"
|
||||
bl search web --query "Alibaba Cloud Bailian latest features"
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -40,7 +40,7 @@ bl search web --query "TypeScript 5.9 new features" --count 5
|
||||
```
|
||||
|
||||
```bash
|
||||
bl search web --query "今日新闻"
|
||||
bl search web --query "Today's news"
|
||||
```
|
||||
|
||||
```bash
|
||||
|
||||
@@ -91,7 +91,7 @@ bl speech recognize --url https://example.com/audio.mp3 --no-wait --quiet
|
||||
| `--pitch <pitch>` | string | no | Pitch multiplier 0.5-2.0 (default: 1.0) |
|
||||
| `--seed <seed>` | string | no | Random seed 0-65535 for reproducible synthesis |
|
||||
| `--language <lang>` | string | no | Language hint (e.g. zh, en, ja, ko, fr, de) |
|
||||
| `--instruction <text>` | string | no | Natural language instruction to control speech style (e.g. "请用温柔的语调") |
|
||||
| `--instruction <text>` | string | no | Natural language instruction to control speech style (e.g. "Use a gentle tone") |
|
||||
| `--enable-ssml` | boolean | no | Enable SSML markup parsing in input text |
|
||||
| `--out <path>` | string | no | Save audio to file (default: auto-generate in temp dir) |
|
||||
| `--stream` | boolean | no | Stream raw PCM audio to stdout (pipe to player) |
|
||||
@@ -103,7 +103,7 @@ bl speech synthesize --list-voices --model cosyvoice-v3-flash
|
||||
```
|
||||
|
||||
```bash
|
||||
bl speech synthesize --text "你好,我是千问" --voice <voice_id>
|
||||
bl speech synthesize --text "Hello, I am Qwen" --voice <voice_id>
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -115,7 +115,7 @@ bl speech synthesize --text-file script.txt --out speech.wav --voice <voice_id>
|
||||
```
|
||||
|
||||
```bash
|
||||
bl speech synthesize --text "今天天气真好" --voice <voice_id> --instruction "请用温柔的语调说话"
|
||||
bl speech synthesize --text "Today is a good day" --voice <voice_id> --instruction "Use a gentle tone"
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -127,7 +127,7 @@ bl speech synthesize --text "Hello" --voice <voice_id> --format wav --sample-rat
|
||||
```
|
||||
|
||||
```bash
|
||||
bl speech synthesize --text "你好" --voice <voice_id> --stream | afplay -
|
||||
bl speech synthesize --text "Hello" --voice <voice_id> --stream | afplay -
|
||||
```
|
||||
|
||||
```bash
|
||||
|
||||
@@ -56,7 +56,7 @@ bl video download --task-id 3b256896-xxxx --out video.mp4 --quiet
|
||||
| --------------------------- | ------- | -------- | --------------------------------------------------------------------------------------- |
|
||||
| `--model <model>` | string | no | Model ID (default: happyhorse-1.0-video-edit) |
|
||||
| `--video <url>` | string | yes | Input video URL or local file (mp4/mov, 2-10s) |
|
||||
| `--prompt <text>` | string | no | Edit instruction (e.g. "将画面转换为黏土风格") |
|
||||
| `--prompt <text>` | string | no | Edit instruction (e.g. "Convert the scene to a claymation style") |
|
||||
| `--ref-image <url>` | string | no | Reference image URL (up to 4, comma-separated) |
|
||||
| `--negative-prompt <text>` | string | no | Negative prompt to exclude unwanted content |
|
||||
| `--resolution <res>` | string | no | Resolution: 720P or 1080P (default: 1080P) |
|
||||
@@ -74,11 +74,11 @@ bl video download --task-id 3b256896-xxxx --out video.mp4 --quiet
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
bl video edit --video https://example.com/input.mp4 --prompt "将整个画面转换为黏土风格"
|
||||
bl video edit --video https://example.com/input.mp4 --prompt "Convert the entire scene to claymation style"
|
||||
```
|
||||
|
||||
```bash
|
||||
bl video edit --video https://example.com/input.mp4 --prompt "替换衣服为图片中的款式" --ref-image https://example.com/clothes.png
|
||||
bl video edit --video https://example.com/input.mp4 --prompt "Replace the outfit with the style shown in the image" --ref-image https://example.com/clothes.png
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -86,7 +86,7 @@ bl video edit --video https://example.com/input.mp4 --prompt "Convert to anime s
|
||||
```
|
||||
|
||||
```bash
|
||||
bl video edit --video https://example.com/input.mp4 --prompt "给视频里的小猫穿上衣服" --watermark false
|
||||
bl video edit --video https://example.com/input.mp4 --prompt "Put clothes on the kitten in the video" --watermark false
|
||||
```
|
||||
|
||||
### `bl video generate`
|
||||
@@ -119,7 +119,7 @@ bl video edit --video https://example.com/input.mp4 --prompt "给视频里的小
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
bl video generate --prompt "一个人在读书,静态镜头"
|
||||
bl video generate --prompt "A person reading a book, static shot"
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -127,7 +127,7 @@ bl video generate --prompt "Ocean waves at sunset." --download sunset.mp4
|
||||
```
|
||||
|
||||
```bash
|
||||
bl video generate --image https://example.com/cat.png --prompt "让画面中的猫动起来"
|
||||
bl video generate --image https://example.com/cat.png --prompt "Make the cat in the scene move"
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -151,7 +151,7 @@ bl video generate --prompt "A cat playing with a ball" --watermark false
|
||||
| Flag | Type | Required | Description |
|
||||
| --------------------------- | ------- | -------- | --------------------------------------------------------------------------------------- |
|
||||
| `--model <model>` | string | no | Model ID (default: happyhorse-1.0-r2v) |
|
||||
| `--prompt <text>` | string | yes | Video description with reference markers (图1, 视频1, etc.) |
|
||||
| `--prompt <text>` | string | yes | Video description with reference markers (image1, video1, etc.) |
|
||||
| `--image <url>` | array | no | Reference image URL or local file (repeatable for multiple subjects) |
|
||||
| `--ref-video <url>` | array | no | Reference video URL or local file (repeatable) |
|
||||
| `--image-voice <url>` | array | no | Voice URL for corresponding image (pairs by position) |
|
||||
@@ -170,23 +170,23 @@ bl video generate --prompt "A cat playing with a ball" --watermark false
|
||||
#### Examples
|
||||
|
||||
```bash
|
||||
bl video ref --prompt "图1在草地上奔跑" --image person.jpg
|
||||
bl video ref --prompt "Image1 running on the grass" --image person.jpg
|
||||
```
|
||||
|
||||
```bash
|
||||
bl video ref --prompt "视频1在弹吉他,图1走过来" --ref-video scene.mp4 --image person.jpg
|
||||
bl video ref --prompt "Video 1 plays guitar, Image 1 walks over" --ref-video scene.mp4 --image person.jpg
|
||||
```
|
||||
|
||||
```bash
|
||||
bl video ref --prompt "图1说话" --image person.jpg --image-voice voice.mp3 --resolution 1080P
|
||||
bl video ref --prompt "Image 1 speaks" --image person.jpg --image-voice voice.mp3 --resolution 1080P
|
||||
```
|
||||
|
||||
```bash
|
||||
bl video ref --prompt "图1和图2在对话" --image a.jpg --image b.jpg --image-voice va.mp3 --image-voice vb.mp3
|
||||
bl video ref --prompt "Image 1 and Image 2 have a conversation" --image a.jpg --image b.jpg --image-voice va.mp3 --image-voice vb.mp3
|
||||
```
|
||||
|
||||
```bash
|
||||
bl video ref --prompt "图1在喝水" --image person.jpg --watermark false
|
||||
bl video ref --prompt "Image 1 drinks water" --image person.jpg --watermark false
|
||||
```
|
||||
|
||||
### `bl video task get`
|
||||
|
||||
@@ -37,11 +37,11 @@ bl vision describe --image photo.jpg
|
||||
```
|
||||
|
||||
```bash
|
||||
bl vision describe --image https://example.com/photo.jpg --prompt "这只狗是什么品种?"
|
||||
bl vision describe --image https://example.com/photo.jpg --prompt "What breed is this dog?"
|
||||
```
|
||||
|
||||
```bash
|
||||
bl vision describe --video https://example.com/video.mp4 --prompt "总结视频内容"
|
||||
bl vision describe --video https://example.com/video.mp4 --prompt "Summarize the video content"
|
||||
```
|
||||
|
||||
```bash
|
||||
|
||||
Reference in New Issue
Block a user