refactor(commands): decouple command paths from binary name; drop path presets

Commands no longer hardcode "bl" or their path — the runtime renders the
`<bin> <path>` prefix from each product's registry key, so shared commands
show `bl knowledge retrieve` / `rag retrieve` from one codebase. commands
package now exports only individual commands (no groups/catalog); bl and rag
each spell out their own path map. Also removes the unused export-schema command.
This commit is contained in:
若麒
2026-06-24 14:40:08 +08:00
parent ad236e9b11
commit 24abdbf450
82 changed files with 620 additions and 872 deletions
+101
View File
@@ -0,0 +1,101 @@
import type { Command } from "bailian-cli-core";
import {
authLogin,
authStatus,
authLogout,
textChat,
textOmni,
imageGenerate,
imageEdit,
videoGenerate,
videoEdit,
videoRef,
videoTaskGet,
videoDownload,
visionDescribe,
configShow,
configSet,
update,
appCall,
appList,
memoryAdd,
memorySearch,
memoryList,
memoryUpdate,
memoryDelete,
memoryProfileCreate,
memoryProfileGet,
knowledgeRetrieve,
mcpCall,
mcpList,
mcpTools,
searchWeb,
speechSynthesize,
speechRecognize,
fileUpload,
consoleCall,
usageFree,
usageFreetier,
usageStats,
pipelineRun,
pipelineValidate,
advisorRecommend,
workspaceList,
quotaList,
quotaRequest,
quotaHistory,
quotaCheck,
} from "bailian-cli-commands";
// Full bailian-cli product: every command, exposed under the `bl` binary.
// The command paths below are this product's decision — the command library
// ships no presets, so the map is spelled out here. Kept in its own module
// (no side effects) so tools like generate-reference.ts can import it without
// starting the CLI.
export const commands: Record<string, Command> = {
"auth login": authLogin,
"auth status": authStatus,
"auth logout": authLogout,
"text chat": textChat,
omni: textOmni,
"image generate": imageGenerate,
"image edit": imageEdit,
"video generate": videoGenerate,
"video edit": videoEdit,
"video ref": videoRef,
"video task get": videoTaskGet,
"video download": videoDownload,
"vision describe": visionDescribe,
"config show": configShow,
"config set": configSet,
update,
"app call": appCall,
"app list": appList,
"memory add": memoryAdd,
"memory search": memorySearch,
"memory list": memoryList,
"memory update": memoryUpdate,
"memory delete": memoryDelete,
"memory profile create": memoryProfileCreate,
"memory profile get": memoryProfileGet,
"knowledge retrieve": knowledgeRetrieve,
"mcp call": mcpCall,
"mcp list": mcpList,
"mcp tools": mcpTools,
"search web": searchWeb,
"speech synthesize": speechSynthesize,
"speech recognize": speechRecognize,
"file upload": fileUpload,
"console call": consoleCall,
"usage free": usageFree,
"usage freetier": usageFreetier,
"usage stats": usageStats,
"pipeline run": pipelineRun,
"pipeline validate": pipelineValidate,
"advisor recommend": advisorRecommend,
"workspace list": workspaceList,
"quota list": quotaList,
"quota request": quotaRequest,
"quota history": quotaHistory,
"quota check": quotaCheck,
};
+1 -2
View File
@@ -1,8 +1,7 @@
import { createCli } from "bailian-cli-runtime";
import { commands } from "bailian-cli-commands";
import { commands } from "./commands.ts";
import pkg from "../package.json" with { type: "json" };
// Full bailian-cli product: every command, exposed under the `bl` binary.
createCli(commands, {
binName: "bl",
version: pkg.version,
@@ -19,7 +19,7 @@ import boxen from "boxen";
import chalk, { Chalk, type ChalkInstance } from "chalk";
import { emitBare, emitResult } from "bailian-cli-runtime";
import { createSpinner } from "bailian-cli-runtime";
import { failIfMissing, promptText } from "bailian-cli-runtime";
import { failIfMissing, promptText, cmdUsage } from "bailian-cli-runtime";
function formatContextWindow(tokens: number): string {
if (tokens >= 1_000_000)
@@ -215,10 +215,9 @@ function isEmptyResult(result: RecommendResult): boolean {
}
export default defineCommand({
name: "advisor recommend",
description:
"Recommend the best models for your use case (intent analysis → candidate recall → LLM ranking)",
usage: "bl advisor recommend <prompt> [flags]",
usageArgs: "<prompt> [flags]",
options: [
{
flag: "--message <text>",
@@ -233,13 +232,13 @@ export default defineCommand({
description: "Output format: text (default in TTY), json, yaml",
},
],
examples: [
'bl advisor recommend --message "I need a visual-understanding chatbot"',
'bl advisor recommend --message "Build an Agent that auto-generates animations"',
'bl advisor recommend --message "Legal contract review, high precision required"',
'bl advisor recommend --message "Low-cost high-concurrency online customer service" --output json',
'bl advisor recommend --message "Long document summarization" --dry-run',
"bl advisor recommend # Interactive input",
exampleArgs: [
'--message "I need a visual-understanding chatbot"',
'--message "Build an Agent that auto-generates animations"',
'--message "Legal contract review, high precision required"',
'--message "Low-cost high-concurrency online customer service" --output json',
'--message "Long document summarization" --dry-run',
" # Interactive input",
],
async run(config: Config, flags: GlobalFlags) {
const positional = ((flags as Record<string, unknown>)._positional as string[]) ?? [];
@@ -254,7 +253,7 @@ export default defineCommand({
}
userInput = hint;
} else {
failIfMissing("message", 'bl advisor recommend "your requirement"');
failIfMissing("message", cmdUsage(config, '"your requirement"'));
}
}
+11 -12
View File
@@ -11,13 +11,12 @@ import {
type AppStreamChunk,
type AppCompletionResponse,
} from "bailian-cli-core";
import { failIfMissing } from "bailian-cli-runtime";
import { failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
export default defineCommand({
name: "app call",
description: "Call a Bailian application (agent or workflow)",
usage: "bl app call --app-id <id> --prompt <text> [flags]",
usageArgs: "--app-id <id> --prompt <text> [flags]",
options: [
{ flag: "--app-id <id>", description: "Application ID (required)", required: true },
{ flag: "--prompt <text>", description: "Input prompt text", required: true },
@@ -34,20 +33,20 @@ export default defineCommand({
{ flag: "--biz-params <json>", description: "Business parameters JSON (workflow variables)" },
{ flag: "--has-thoughts", description: "Show agent thinking process" },
],
examples: [
'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"}\'',
exampleArgs: [
'--app-id abc123 --prompt "Hello"',
'--app-id abc123 --prompt "Describe this image" --image https://example.com/photo.jpg',
'--app-id abc123 --prompt "Analyze the image" --image img1.jpg --image img2.jpg',
'--app-id abc123 --prompt "Continue" --session-id sess_xxx --stream',
'--app-id abc123 --prompt "Search for materials" --pipeline-ids pipe1,pipe2',
'--app-id abc123 --prompt "Start" --biz-params \'{"key":"value"}\'',
],
async run(config: Config, flags: GlobalFlags) {
const appId = flags.appId as string;
if (!appId) failIfMissing("app-id", "bl app call --app-id <id> --prompt <text>");
if (!appId) failIfMissing("app-id", cmdUsage(config, "--app-id <id> --prompt <text>"));
const prompt = flags.prompt as string;
if (!prompt) failIfMissing("prompt", "bl app call --app-id <id> --prompt <text>");
if (!prompt) failIfMissing("prompt", cmdUsage(config, "--app-id <id> --prompt <text>"));
const shouldStream =
flags.stream === true || (flags.stream === undefined && process.stdout.isTTY);
+2 -8
View File
@@ -11,10 +11,9 @@ import { emitResult } from "bailian-cli-runtime";
const APP_LIST_API = "zeldaEasy.broadscope-bailian.app-control.list";
export default defineCommand({
name: "app list",
description: "List Bailian applications",
skipDefaultApiKeySetup: true,
usage: "bl app list [flags]",
usageArgs: "[flags]",
options: [
{
flag: "--name <name>",
@@ -41,12 +40,7 @@ export default defineCommand({
type: "number",
},
],
examples: [
"bl app list",
"bl app list --name customer service",
"bl app list --page 2 --page-size 10",
"bl app list --output json",
],
exampleArgs: ["", "--name customer service", "--page 2 --page-size 10", "--output json"],
async run(config: Config, flags: GlobalFlags) {
const name = (flags.name as string) || "";
const pageNo = (flags.page as number) || 1;
+2 -3
View File
@@ -18,10 +18,9 @@ import {
} from "./login-console.ts";
export default defineCommand({
name: "auth login",
description: "Authenticate with API key or console browser login (credentials can coexist)",
skipDefaultApiKeySetup: true,
usage: "bl auth login --api-key <key> | bl auth login --console",
usageArgs: "--api-key <key> | --console",
options: [
{ flag: "--api-key <key>", description: "DashScope API key to store" },
{
@@ -34,7 +33,7 @@ export default defineCommand({
"Sign in via browser; use --console-site to choose domestic (default) or international",
},
],
examples: ["bl auth login --api-key sk-xxxxx", "bl auth login --console"],
exampleArgs: ["--api-key sk-xxxxx", "--console"],
async run(config: Config, flags: GlobalFlags) {
if (flags.console) {
if (config.dryRun) {
@@ -18,10 +18,9 @@ async function clearConsoleToken(): Promise<boolean> {
}
export default defineCommand({
name: "auth logout",
description: "Clear stored credentials",
skipDefaultApiKeySetup: true,
usage: "bl auth logout [--console] [--yes] [--dry-run]",
usageArgs: "[--console] [--yes] [--dry-run]",
options: [
{
flag: "--console",
@@ -30,12 +29,7 @@ export default defineCommand({
},
{ flag: "--yes", description: "Skip confirmation prompt" },
],
examples: [
"bl auth logout",
"bl auth logout --console",
"bl auth logout --dry-run",
"bl auth logout --yes",
],
exampleArgs: ["", "--console", "--dry-run", "--yes"],
async run(config: Config, flags: GlobalFlags) {
const file = readConfigFile();
@@ -108,7 +108,7 @@ function hasAnyAuth(status: AuthStatusPayload): boolean {
);
}
function emitTextStatus(status: AuthStatusPayload): void {
function emitTextStatus(status: AuthStatusPayload, config: Config): void {
emitBare("Authentication Status:");
emitBare(" Stored credentials (can coexist):");
if (status.api_key.configured) {
@@ -134,14 +134,12 @@ function emitTextStatus(status: AuthStatusPayload): void {
` Console gateway: ${status.console_gateway_commands.method} (${status.console_gateway_commands.source}) ${status.console_gateway_commands.masked}`,
);
} else {
emitBare(" Console gateway: unavailable (run bl auth login --console)");
emitBare(` Console gateway: unavailable (run ${config.binName} auth login --console)`);
}
}
export default defineCommand({
name: "auth status",
description: "Show current authentication state",
usage: "bl auth status",
options: [
{ flag: "--console-region <region>", description: "Console region" },
{
@@ -154,7 +152,7 @@ export default defineCommand({
type: "number",
},
],
examples: ["bl auth status", "bl auth status --output json"],
exampleArgs: ["", "--output json"],
async run(config: Config, _flags: GlobalFlags) {
const format = detectOutputFormat(config.output);
const status = await buildStatus(config);
@@ -164,8 +162,8 @@ export default defineCommand({
authenticated: false,
message: "Not authenticated.",
hint: [
"DashScope API: bl auth login --api-key <key> or DASHSCOPE_API_KEY",
"Console gateway: bl auth login --console or DASHSCOPE_ACCESS_TOKEN",
`DashScope API: ${config.binName} auth login --api-key <key> or DASHSCOPE_API_KEY`,
`Console gateway: ${config.binName} auth login --console or DASHSCOPE_ACCESS_TOKEN`,
`Get API Key: ${API_KEY_PAGE}`,
].join("\n"),
...status,
@@ -179,6 +177,6 @@ export default defineCommand({
return;
}
emitTextStatus(status);
emitTextStatus(status, config);
},
});
@@ -1,2 +0,0 @@
/** Full command registry map (all groups merged). Kept for backward compatibility. */
export { commands } from "./groups.ts";
@@ -1,47 +0,0 @@
import { defineCommand, generateToolSchema } from "bailian-cli-core";
import type { Config } from "bailian-cli-core";
import type { GlobalFlags } from "bailian-cli-core";
import { BailianError } from "bailian-cli-core";
import { ExitCode } from "bailian-cli-core";
/**
* Commands that are infrastructure/auth-related and not suitable as Agent tools.
*/
const SKIP_PREFIXES = ["auth ", "config ", "update"];
export default defineCommand({
name: "config export-schema",
description:
"Export all (or one) CLI command(s) as Anthropic/OpenAI-compatible JSON tool schemas",
skipDefaultApiKeySetup: true,
usage: 'bl config export-schema [--command "<name>"]',
options: [
{
flag: "--command <name>",
description: 'Export schema for a specific command only (e.g. "image generate")',
},
],
examples: ["bl config export-schema", 'bl config export-schema --command "video generate"'],
async run(config: Config, flags: GlobalFlags) {
const { commands } = await import("../catalog.ts");
const targetCommand = flags.command as string | undefined;
if (targetCommand) {
const command = commands[targetCommand];
if (!command) {
throw new BailianError(`Command "${targetCommand}" not found.`, ExitCode.USAGE);
}
const schema = generateToolSchema(command);
process.stdout.write(JSON.stringify(schema, null, 2) + "\n");
return;
}
// Export all suitable commands
const allCommands = Object.values(commands);
const schemas = allCommands
.filter((c) => !SKIP_PREFIXES.some((p) => c.name.startsWith(p)))
.map((c) => generateToolSchema(c));
process.stdout.write(JSON.stringify(schemas, null, 2) + "\n");
},
});
+7 -8
View File
@@ -9,7 +9,7 @@ import {
type GlobalFlags,
ExitCode,
} from "bailian-cli-core";
import { emitResult } from "bailian-cli-runtime";
import { emitResult, cmdUsage } from "bailian-cli-runtime";
const VALID_KEYS = [
"base_url",
@@ -50,10 +50,9 @@ const KEY_ALIASES: Record<string, string> = {
};
export default defineCommand({
name: "config set",
description: "Set a config value",
skipDefaultApiKeySetup: true,
usage: "bl config set --key <key> --value <value>",
usageArgs: "--key <key> --value <value>",
options: [
{
flag: "--key <key>",
@@ -62,10 +61,10 @@ export default defineCommand({
},
{ flag: "--value <value>", description: "Value to set" },
],
examples: [
"bl config set --key output --value json",
"bl config set --key timeout --value 600",
"bl config set --key base_url --value https://dashscope.aliyuncs.com",
exampleArgs: [
"--key output --value json",
"--key timeout --value 600",
"--key base_url --value https://dashscope.aliyuncs.com",
],
async run(config: Config, flags: GlobalFlags) {
const key = flags.key as string | undefined;
@@ -75,7 +74,7 @@ export default defineCommand({
throw new BailianError(
"--key and --value are required.",
ExitCode.USAGE,
"bl config set --key <key> --value <value>",
cmdUsage(config, "--key <key> --value <value>"),
);
}
@@ -10,11 +10,9 @@ import {
import { emitResult } from "bailian-cli-runtime";
export default defineCommand({
name: "config show",
description: "Display current configuration",
skipDefaultApiKeySetup: true,
usage: "bl config show",
examples: ["bl config show", "bl config show --output json"],
exampleArgs: ["", "--output json"],
async run(config: Config, _flags: GlobalFlags) {
const file = loadConfigFile();
const format = detectOutputFormat(config.output);
@@ -9,14 +9,13 @@ import {
type Config,
type GlobalFlags,
} from "bailian-cli-core";
import { failIfMissing } from "bailian-cli-runtime";
import { failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult } from "bailian-cli-runtime";
export default defineCommand({
name: "console call",
description: "Call a Bailian console API via the CLI gateway",
skipDefaultApiKeySetup: true,
usage: "bl console call --api <api> --data <json> [flags]",
usageArgs: "--api <api> --data <json> [flags]",
options: [
{
flag: "--api <api>",
@@ -39,16 +38,16 @@ export default defineCommand({
type: "number",
},
],
examples: [
`bl console call --api zeldaEasy.broadscope-bailian.freeTrial.queryFreeTierQuota --data '{"queryFreeTierQuotaRequest":{"models":["qwen3-max"]}}'`,
`bl console call --api some.api.name --data '{"key":"value"}' --console-region cn-beijing`,
exampleArgs: [
`--api zeldaEasy.broadscope-bailian.freeTrial.queryFreeTierQuota --data '{"queryFreeTierQuotaRequest":{"models":["qwen3-max"]}}'`,
`--api some.api.name --data '{"key":"value"}' --console-region cn-beijing`,
],
async run(config: Config, flags: GlobalFlags) {
const api = flags.api as string;
if (!api) failIfMissing("api", "bl console call --api <api> --data <json>");
if (!api) failIfMissing("api", cmdUsage(config, "--api <api> --data <json>"));
const dataRaw = flags.data as string;
if (!dataRaw) failIfMissing("data", "bl console call --api <api> --data <json>");
if (!dataRaw) failIfMissing("data", cmdUsage(config, "--api <api> --data <json>"));
let data: Record<string, unknown>;
try {
+9 -10
View File
@@ -6,13 +6,12 @@ import {
type GlobalFlags,
uploadFile,
} from "bailian-cli-core";
import { failIfMissing } from "bailian-cli-runtime";
import { failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
export default defineCommand({
name: "file upload",
description: "Upload a local file to DashScope temporary storage (48h)",
usage: "bl file upload --file <path> --model <model>",
usageArgs: "--file <path> --model <model>",
options: [
{
flag: "--file <path>",
@@ -25,21 +24,21 @@ export default defineCommand({
required: true,
},
],
examples: [
"bl file upload --file photo.jpg --model qwen3-vl-plus",
"bl file upload --file video.mp4 --model wan2.1-t2v-plus",
"bl file upload --file audio.wav --model qwen3-asr-flash",
"bl file upload --file cat.png --model qwen-image-2.0",
exampleArgs: [
"--file photo.jpg --model qwen3-vl-plus",
"--file video.mp4 --model wan2.1-t2v-plus",
"--file audio.wav --model qwen3-asr-flash",
"--file cat.png --model qwen-image-2.0",
],
async run(config: Config, flags: GlobalFlags) {
const filePath = flags.file as string | undefined;
if (!filePath) {
failIfMissing("file", "bl file upload --file <path> --model <model>");
failIfMissing("file", cmdUsage(config, "--file <path> --model <model>"));
}
const model = flags.model as string | undefined;
if (!model) {
failIfMissing("model", "bl file upload --file <path> --model <model>");
failIfMissing("model", cmdUsage(config, "--file <path> --model <model>"));
}
const format = detectOutputFormat(config.output);
-183
View File
@@ -1,183 +0,0 @@
import type { Command } from "bailian-cli-core";
import authLogin from "./auth/login.ts";
import authStatus from "./auth/status.ts";
import authLogout from "./auth/logout.ts";
import textChat from "./text/chat.ts";
import textOmni from "./omni/chat.ts";
import imageGenerate from "./image/generate.ts";
import imageEdit from "./image/edit.ts";
import videoGenerate from "./video/generate.ts";
import videoEdit from "./video/edit.ts";
import videoRef from "./video/ref.ts";
import videoTaskGet from "./video/task-get.ts";
import videoDownload from "./video/download.ts";
import visionDescribe from "./vision/describe.ts";
import configShow from "./config/show.ts";
import configSet from "./config/set.ts";
import configExportSchema from "./config/export-schema.ts";
import update from "./update.ts";
import appCall from "./app/call.ts";
import appList from "./app/list.ts";
import memoryAdd from "./memory/add.ts";
import memorySearch from "./memory/search.ts";
import memoryList from "./memory/list.ts";
import memoryUpdate from "./memory/update.ts";
import memoryDelete from "./memory/delete.ts";
import memoryProfileCreate from "./memory/profile-create.ts";
import memoryProfileGet from "./memory/profile-get.ts";
import knowledgeRetrieve from "./knowledge/retrieve.ts";
import mcpCall from "./mcp/call.ts";
import mcpList from "./mcp/list.ts";
import mcpTools from "./mcp/tools.ts";
import searchWeb from "./search/web.ts";
import speechSynthesize from "./speech/synthesize.ts";
import speechRecognize from "./speech/recognize.ts";
import fileUpload from "./file/upload.ts";
import consoleCall from "./console/call.ts";
import usageFree from "./usage/free.ts";
import usageFreetier from "./usage/freetier.ts";
import usageStats from "./usage/stats.ts";
import pipelineRun from "./pipeline/run.ts";
import pipelineValidate from "./pipeline/validate.ts";
import advisorRecommend from "./advisor/recommend.ts";
import workspaceList from "./workspace/list.ts";
import quotaList from "./quota/list.ts";
import quotaRequest from "./quota/request.ts";
import quotaHistory from "./quota/history.ts";
import quotaCheck from "./quota/check.ts";
// Re-export individual command implementations so entrypoints can remap their
// paths freely (e.g. rag-cli mapping "knowledge retrieve" → "retrieve").
export {
authLogin,
authStatus,
authLogout,
textChat,
textOmni,
imageGenerate,
imageEdit,
videoGenerate,
videoEdit,
videoRef,
videoTaskGet,
videoDownload,
visionDescribe,
configShow,
configSet,
configExportSchema,
update,
appCall,
appList,
memoryAdd,
memorySearch,
memoryList,
memoryUpdate,
memoryDelete,
memoryProfileCreate,
memoryProfileGet,
knowledgeRetrieve,
mcpCall,
mcpList,
mcpTools,
searchWeb,
speechSynthesize,
speechRecognize,
fileUpload,
consoleCall,
usageFree,
usageFreetier,
usageStats,
pipelineRun,
pipelineValidate,
advisorRecommend,
workspaceList,
quotaList,
quotaRequest,
quotaHistory,
quotaCheck,
};
/**
* Base/infrastructure commands every product needs: auth, config, usage, quota,
* update, and file upload. file-upload lives here (not in knowledge) because it
* is generic infra that knowledge and other capabilities build on.
*/
export const baseCommands: Record<string, Command> = {
"auth login": authLogin,
"auth status": authStatus,
"auth logout": authLogout,
"config show": configShow,
"config set": configSet,
"config export-schema": configExportSchema,
"usage free": usageFree,
"usage freetier": usageFreetier,
"usage stats": usageStats,
"quota list": quotaList,
"quota request": quotaRequest,
"quota history": quotaHistory,
"quota check": quotaCheck,
"file upload": fileUpload,
update: update,
};
/** Knowledge base (RAG) commands. */
export const knowledgeCommands: Record<string, Command> = {
"knowledge retrieve": knowledgeRetrieve,
};
/** Text & multimodal chat commands. */
export const textCommands: Record<string, Command> = {
"text chat": textChat,
omni: textOmni,
};
/** Media generation commands: image / video / vision / speech. */
export const mediaCommands: Record<string, Command> = {
"image generate": imageGenerate,
"image edit": imageEdit,
"video generate": videoGenerate,
"video edit": videoEdit,
"video ref": videoRef,
"video task get": videoTaskGet,
"video download": videoDownload,
"vision describe": visionDescribe,
"speech synthesize": speechSynthesize,
"speech recognize": speechRecognize,
};
/** Memory system commands. */
export const memoryCommands: Record<string, Command> = {
"memory add": memoryAdd,
"memory search": memorySearch,
"memory list": memoryList,
"memory update": memoryUpdate,
"memory delete": memoryDelete,
"memory profile create": memoryProfileCreate,
"memory profile get": memoryProfileGet,
};
/** Remaining capability commands: mcp / search / app / advisor / workspace / console / pipeline. */
export const miscCommands: Record<string, Command> = {
"mcp list": mcpList,
"mcp tools": mcpTools,
"mcp call": mcpCall,
"search web": searchWeb,
"app call": appCall,
"app list": appList,
"advisor recommend": advisorRecommend,
"workspace list": workspaceList,
"console call": consoleCall,
"pipeline run": pipelineRun,
"pipeline validate": pipelineValidate,
};
/** Full command set (all groups merged) — used by the full bailian-cli product. */
export const commands: Record<string, Command> = {
...baseCommands,
...knowledgeCommands,
...textCommands,
...mediaCommands,
...memoryCommands,
...miscCommands,
};
+10 -11
View File
@@ -20,16 +20,15 @@ import {
} from "bailian-cli-core";
import { downloadFile } from "bailian-cli-runtime";
import { runConcurrent, downloadParallel, getConcurrency } from "bailian-cli-runtime";
import { promptText, failIfMissing } from "bailian-cli-runtime";
import { promptText, failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
import { resolveImageSize } from "bailian-cli-runtime";
import { join } from "path";
import { BOOL_FLAG_PROMPT_EXTEND_CLI_TRUE, BOOL_FLAG_WATERMARK } from "bailian-cli-runtime";
export default defineCommand({
name: "image edit",
description: "Edit an existing image with text instructions (Qwen-Image)",
usage: "bl image edit --image <url> --prompt <text> [flags]",
usageArgs: "--image <url> --prompt <text> [flags]",
options: [
{
flag: "--image <url>",
@@ -60,12 +59,12 @@ export default defineCommand({
{ flag: "--out-dir <dir>", description: "Download images to directory" },
{ flag: "--out-prefix <prefix>", description: "Filename prefix (default: edited)" },
],
examples: [
'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 "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 "Replace the background with a beach" --watermark false',
exampleArgs: [
'--image ./photo.png --prompt "Replace the background with a beach"',
'--image https://example.com/logo.png --prompt "Change color to blue" --n 3',
'--image ./a.png --image ./b.png --prompt "Merge two images into one collage"',
'--image https://example.com/photo.png --prompt "Remove the person" --model qwen-image-2.0-pro',
'--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)
@@ -76,7 +75,7 @@ export default defineCommand({
rawImages = [flags.image];
}
if (rawImages.length === 0) {
failIfMissing("image", "bl image edit --image <url> --prompt <text>");
failIfMissing("image", cmdUsage(config, "--image <url> --prompt <text>"));
}
let prompt = flags.prompt as string | undefined;
@@ -91,7 +90,7 @@ export default defineCommand({
}
prompt = hint;
} else {
failIfMissing("prompt", "bl image edit --image <url> --prompt <text>");
failIfMissing("prompt", cmdUsage(config, "--image <url> --prompt <text>"));
}
}
@@ -23,7 +23,7 @@ import {
import { poll } from "bailian-cli-runtime";
import { downloadFile } from "bailian-cli-runtime";
import { runConcurrent, downloadParallel, getConcurrency } from "bailian-cli-runtime";
import { promptText, failIfMissing } from "bailian-cli-runtime";
import { promptText, failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
import { resolveImageSize } from "bailian-cli-runtime";
import { BOOL_FLAG_PROMPT_EXTEND_IMAGE_GENERATE, BOOL_FLAG_WATERMARK } from "bailian-cli-runtime";
@@ -38,9 +38,8 @@ function isSyncModel(model: string): boolean {
}
export default defineCommand({
name: "image generate",
description: "Generate images (Qwen-Image / wan2.x)",
usage: "bl image generate --prompt <text> [flags]",
usageArgs: "--prompt <text> [flags]",
options: [
{ flag: "--prompt <text>", description: "Image description", required: true },
{ flag: "--model <model>", description: "Model ID (default: qwen-image-2.0)" },
@@ -78,16 +77,16 @@ export default defineCommand({
type: "number",
},
],
examples: [
'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',
'bl image generate --prompt "Logo" --watermark false',
'bl image generate --prompt "An alien in the space" --watermark false',
'bl image generate --prompt "sunset" --model wan2.6-t2i --no-wait --quiet',
'bl image generate --prompt "Pro quality" --model qwen-image-2.0-pro',
'bl image generate --prompt "Product shots" --n 2 --concurrent 3 # 6 images in parallel',
exampleArgs: [
'--prompt "A cat in a spacesuit on Mars"',
'--prompt "Logo design" --n 3 --out-dir ./generated/',
'--prompt "Mountain landscape" --size 2688*1536',
'--prompt "A castle" --seed 42 --prompt-extend false',
'--prompt "Logo" --watermark false',
'--prompt "An alien in the space" --watermark false',
'--prompt "sunset" --model wan2.6-t2i --no-wait --quiet',
'--prompt "Pro quality" --model qwen-image-2.0-pro',
'--prompt "Product shots" --n 2 --concurrent 3 # 6 images in parallel',
],
async run(config: Config, flags: GlobalFlags) {
let prompt = (flags.prompt ?? (flags._positional as string[] | undefined)?.[0]) as
@@ -105,7 +104,7 @@ export default defineCommand({
}
prompt = hint;
} else {
failIfMissing("prompt", "bl image generate --prompt <text>");
failIfMissing("prompt", cmdUsage(config, "--prompt <text>"));
}
}
-1
View File
@@ -1 +0,0 @@
export { commands } from "./catalog.ts";
@@ -17,16 +17,15 @@ import {
BailianError,
ExitCode,
} from "bailian-cli-core";
import { failIfMissing } from "bailian-cli-runtime";
import { failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
const BAILIAN_HOST = "bailian.cn-beijing.aliyuncs.com";
export default defineCommand({
name: "knowledge retrieve",
description: "Retrieve from a Bailian knowledge base",
skipDefaultApiKeySetup: true,
usage: "bl knowledge retrieve --index-id <id> --query <text> [flags]",
usageArgs: "--index-id <id> --query <text> [flags]",
options: [
{ flag: "--index-id <id>", description: "Knowledge base index ID (required)", required: true },
{ flag: "--query <text>", description: "Search query (required)", required: true },
@@ -76,16 +75,16 @@ export default defineCommand({
"Authentication: pass `--api-key <key>`. AK/SK auth is deprecated and will be removed in a future version.",
"`--workspace-id` is NOT required when using --api-key.",
],
examples: [
'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',
exampleArgs: [
'--index-id idx_xxx --query "How to use Alibaba Cloud Bailian"',
'--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;
if (!indexId) failIfMissing("index-id", "bl knowledge retrieve --index-id <id> --query <text>");
if (!indexId) failIfMissing("index-id", cmdUsage(config, "--index-id <id> --query <text>"));
const query = flags.query as string;
if (!query) failIfMissing("query", "bl knowledge retrieve --index-id <id> --query <text>");
if (!query) failIfMissing("query", cmdUsage(config, "--index-id <id> --query <text>"));
const format = detectOutputFormat(config.output);
@@ -196,7 +195,7 @@ async function runWithAkSk(
if (!workspaceId) {
throw new BailianError(
"Knowledge retrieve requires a workspace ID.\n" +
"Set via: --workspace-id flag, or env: BAILIAN_WORKSPACE_ID, or config: bl config set workspace_id <id>",
`Set via: --workspace-id flag, or env: BAILIAN_WORKSPACE_ID, or config: ${config.binName} config set workspace_id <id>`,
ExitCode.USAGE,
);
}
+7 -8
View File
@@ -6,7 +6,7 @@ import {
type Config,
type GlobalFlags,
} from "bailian-cli-core";
import { failIfMissing } from "bailian-cli-runtime";
import { failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult } from "bailian-cli-runtime";
import { ensureApiKey } from "bailian-cli-runtime";
@@ -30,10 +30,9 @@ function parseArgFlags(raw: string[]): Record<string, unknown> {
}
export default defineCommand({
name: "mcp call",
description: "Call a tool on an MCP server (tools/call)",
skipDefaultApiKeySetup: true,
usage: "bl mcp call <server-code>.<tool> [--arg k=v ...] [--json '{...}'] [--url <url>]",
usageArgs: "<server-code>.<tool> [--arg k=v ...] [--json '{...}'] [--url <url>]",
options: [
{
flag: "<server-code>.<tool>",
@@ -56,16 +55,16 @@ export default defineCommand({
},
{ flag: "--url <url>", description: "Override the MCP endpoint URL (for non-Bailian servers)" },
],
examples: [
'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",
exampleArgs: [
'market-cmapi00073529.SmartStockSelection --query "Screen consumer stocks with ROE > 15%"',
'market-cmapi00073529.FinQuery --json \'{"q":"Guizhou Maotai","limit":5}\'',
"market-cmapi00073529.SmartFundSelection --arg riskLevel=R3 --arg minScale=10",
],
async run(config: Config, flags: GlobalFlags) {
const positional =
((flags as Record<string, unknown>)._positional as string[] | undefined) ?? [];
const target = positional[0];
if (!target) failIfMissing("<server-code>.<tool>", "bl mcp call <server-code>.<tool>");
if (!target) failIfMissing("<server-code>.<tool>", cmdUsage(config, "<server-code>.<tool>"));
const dot = target!.indexOf(".");
if (dot <= 0 || dot === target!.length - 1) {
+3 -4
View File
@@ -25,10 +25,9 @@ interface ServerSummary {
}
export default defineCommand({
name: "mcp list",
description: "List MCP servers activated under your Bailian account",
skipDefaultApiKeySetup: true,
usage: "bl mcp list [flags]",
usageArgs: "[flags]",
options: [
{ flag: "--name <text>", description: "Filter by server name (substring match)" },
{
@@ -48,7 +47,7 @@ export default defineCommand({
type: "number",
},
],
examples: ["bl mcp list", "bl mcp list --name finance", "bl mcp list --output json"],
exampleArgs: ["", "--name finance", "--output json"],
async run(config: Config, flags: GlobalFlags) {
const serverName = (flags.name as string) || "";
const type = (flags.type as string) || "OFFICIAL";
@@ -85,7 +84,7 @@ export default defineCommand({
const msg = (dataField.errorMsg as string | undefined) ?? code;
const hint =
code === "BailianGateway.Login.NotLogined"
? "Run `bl auth login --console` to refresh your console session."
? `Run \`${config.binName} auth login --console\` to refresh your console session.`
: undefined;
throw new BailianError(`Console gateway: ${msg}`, ExitCode.AUTH, hint);
}
+8 -9
View File
@@ -6,33 +6,32 @@ import {
type Config,
type GlobalFlags,
} from "bailian-cli-core";
import { failIfMissing } from "bailian-cli-runtime";
import { failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult } from "bailian-cli-runtime";
import { ensureApiKey } from "bailian-cli-runtime";
export default defineCommand({
name: "mcp tools",
description: "List tools exposed by an MCP server (tools/list)",
skipDefaultApiKeySetup: true,
usage: "bl mcp tools <server-code> [--url <url>]",
usageArgs: "<server-code> [--url <url>]",
options: [
{
flag: "<server-code>",
description: "Server code from `bl mcp list` (e.g. market-cmapi00073529)",
description: "Server code from `mcp list` (e.g. market-cmapi00073529)",
required: true,
},
{ flag: "--url <url>", description: "Override the MCP endpoint URL (for non-Bailian servers)" },
],
examples: [
"bl mcp tools market-cmapi00073529",
"bl mcp tools market-cmapi00073529 --output json",
"bl mcp tools my-server --url https://example.com/mcp",
exampleArgs: [
"market-cmapi00073529",
"market-cmapi00073529 --output json",
"my-server --url https://example.com/mcp",
],
async run(config: Config, flags: GlobalFlags) {
const positional =
((flags as Record<string, unknown>)._positional as string[] | undefined) ?? [];
const code = positional[0];
if (!code) failIfMissing("server-code", "bl mcp tools <server-code>");
if (!code) failIfMissing("server-code", cmdUsage(config, "<server-code>"));
const url = (flags.url as string) || bailianMcpUrl(config.baseUrl, code!);
const format = detectOutputFormat(config.output);
+7 -8
View File
@@ -8,13 +8,12 @@ import {
type MemoryAddRequest,
type MemoryAddResponse,
} from "bailian-cli-core";
import { failIfMissing } from "bailian-cli-runtime";
import { failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
export default defineCommand({
name: "memory add",
description: "Add memory from messages or custom content",
usage: "bl memory add --user-id <id> [--messages <json>] [--content <text>] [flags]",
usageArgs: "--user-id <id> [--messages <json>] [--content <text>] [flags]",
options: [
{ flag: "--user-id <id>", description: "User ID (required)", required: true },
{
@@ -25,14 +24,14 @@ export default defineCommand({
{ flag: "--profile-schema <id>", description: "Profile schema ID for user profiling" },
{ flag: "--memory-library-id <id>", description: "Memory library ID (isolate memory space)" },
],
examples: [
'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',
exampleArgs: [
'--user-id user1 --content "The user likes Python programming"',
'--user-id user1 --messages \'[{"role":"user","content":"I like traveling"}]\'',
'--user-id user1 --content "Lives in Beijing" --profile-schema schema_xxx',
],
async run(config: Config, flags: GlobalFlags) {
const userId = flags.userId as string;
if (!userId) failIfMissing("user-id", "bl memory add --user-id <id>");
if (!userId) failIfMissing("user-id", cmdUsage(config, "--user-id <id>"));
const body: MemoryAddRequest = { user_id: userId };
@@ -6,25 +6,24 @@ import {
type Config,
type GlobalFlags,
} from "bailian-cli-core";
import { failIfMissing } from "bailian-cli-runtime";
import { failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
export default defineCommand({
name: "memory delete",
description: "Delete a memory node",
usage: "bl memory delete --node-id <id> --user-id <id>",
usageArgs: "--node-id <id> --user-id <id>",
options: [
{ flag: "--node-id <id>", description: "Memory node ID (required)", required: true },
{ flag: "--user-id <id>", description: "User ID (required)", required: true },
{ flag: "--memory-library-id <id>", description: "Memory library ID (non-default library)" },
],
examples: ["bl memory delete --node-id node_xxx --user-id user1"],
exampleArgs: ["--node-id node_xxx --user-id user1"],
async run(config: Config, flags: GlobalFlags) {
const nodeId = flags.nodeId as string;
if (!nodeId) failIfMissing("node-id", "bl memory delete --node-id <id> --user-id <id>");
if (!nodeId) failIfMissing("node-id", cmdUsage(config, "--node-id <id> --user-id <id>"));
const userId = flags.userId as string;
if (!userId) failIfMissing("user-id", "bl memory delete --node-id <id> --user-id <id>");
if (!userId) failIfMissing("user-id", cmdUsage(config, "--node-id <id> --user-id <id>"));
const format = detectOutputFormat(config.output);
const params = new URLSearchParams({ user_id: userId });
@@ -7,26 +7,22 @@ import {
type GlobalFlags,
type MemoryNodeListResponse,
} from "bailian-cli-core";
import { failIfMissing } from "bailian-cli-runtime";
import { failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
export default defineCommand({
name: "memory list",
description: "List memory nodes for a user",
usage: "bl memory list --user-id <id> [flags]",
usageArgs: "--user-id <id> [flags]",
options: [
{ flag: "--user-id <id>", description: "User ID (required)", required: true },
{ flag: "--page-size <n>", description: "Results per page (default: 10)", type: "number" },
{ flag: "--page <n>", description: "Page number (default: 1)", type: "number" },
{ flag: "--memory-library-id <id>", description: "Memory library ID" },
],
examples: [
"bl memory list --user-id user1",
"bl memory list --user-id user1 --page-size 20 --page 2",
],
exampleArgs: ["--user-id user1", "--user-id user1 --page-size 20 --page 2"],
async run(config: Config, flags: GlobalFlags) {
const userId = flags.userId as string;
if (!userId) failIfMissing("user-id", "bl memory list --user-id <id>");
if (!userId) failIfMissing("user-id", cmdUsage(config, "--user-id <id>"));
const format = detectOutputFormat(config.output);
const params = new URLSearchParams();
@@ -8,13 +8,12 @@ import {
type ProfileSchemaCreateRequest,
type ProfileSchemaCreateResponse,
} from "bailian-cli-core";
import { failIfMissing } from "bailian-cli-runtime";
import { failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
export default defineCommand({
name: "memory profile create",
description: "Create a user profile schema for memory profiling",
usage: "bl memory profile create --name <name> --attributes <json> [flags]",
usageArgs: "--name <name> --attributes <json> [flags]",
options: [
{ flag: "--name <name>", description: "Schema name (required)", required: true },
{ flag: "--description <text>", description: "Schema description" },
@@ -24,16 +23,16 @@ export default defineCommand({
required: true,
},
],
examples: [
'bl memory profile create --name "user_basic" --attributes \'[{"name":"age","description":"age"},{"name":"hobby","description":"hobby"}]\'',
exampleArgs: [
'--name "user_basic" --attributes \'[{"name":"age","description":"age"},{"name":"hobby","description":"hobby"}]\'',
],
async run(config: Config, flags: GlobalFlags) {
const name = flags.name as string;
if (!name) failIfMissing("name", "bl memory profile create --name <name> --attributes <json>");
if (!name) failIfMissing("name", cmdUsage(config, "--name <name> --attributes <json>"));
const attrStr = flags.attributes as string;
if (!attrStr)
failIfMissing("attributes", "bl memory profile create --name <name> --attributes <json>");
failIfMissing("attributes", cmdUsage(config, "--name <name> --attributes <json>"));
let attributes;
try {
@@ -7,25 +7,23 @@ import {
type GlobalFlags,
type UserProfileResponse,
} from "bailian-cli-core";
import { failIfMissing } from "bailian-cli-runtime";
import { failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
export default defineCommand({
name: "memory profile get",
description: "Get user profile by schema ID and user ID",
usage: "bl memory profile get --schema-id <id> --user-id <id>",
usageArgs: "--schema-id <id> --user-id <id>",
options: [
{ flag: "--schema-id <id>", description: "Profile schema ID (required)", required: true },
{ flag: "--user-id <id>", description: "User ID (required)", required: true },
],
examples: ["bl memory profile get --schema-id schema_xxx --user-id user1"],
exampleArgs: ["--schema-id schema_xxx --user-id user1"],
async run(config: Config, flags: GlobalFlags) {
const schemaId = flags.schemaId as string;
if (!schemaId)
failIfMissing("schema-id", "bl memory profile get --schema-id <id> --user-id <id>");
if (!schemaId) failIfMissing("schema-id", cmdUsage(config, "--schema-id <id> --user-id <id>"));
const userId = flags.userId as string;
if (!userId) failIfMissing("user-id", "bl memory profile get --schema-id <id> --user-id <id>");
if (!userId) failIfMissing("user-id", cmdUsage(config, "--schema-id <id> --user-id <id>"));
const format = detectOutputFormat(config.output);
const params = new URLSearchParams({ user_id: userId });
@@ -8,13 +8,12 @@ import {
type MemorySearchRequest,
type MemorySearchResponse,
} from "bailian-cli-core";
import { failIfMissing } from "bailian-cli-runtime";
import { failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
export default defineCommand({
name: "memory search",
description: "Search memory nodes by query or messages",
usage: "bl memory search --user-id <id> [--query <text>] [flags]",
usageArgs: "--user-id <id> [--query <text>] [flags]",
options: [
{ flag: "--user-id <id>", description: "User ID (required)", required: true },
{ flag: "--query <text>", description: "Search query text" },
@@ -26,13 +25,13 @@ export default defineCommand({
},
{ flag: "--memory-library-id <id>", description: "Memory library ID" },
],
examples: [
'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',
exampleArgs: [
'--user-id user1 --query "programming preferences"',
'--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;
if (!userId) failIfMissing("user-id", "bl memory search --user-id <id>");
if (!userId) failIfMissing("user-id", cmdUsage(config, "--user-id <id>"));
const body: MemorySearchRequest = { user_id: userId };
@@ -7,13 +7,12 @@ import {
type GlobalFlags,
type MemoryNodeUpdateRequest,
} from "bailian-cli-core";
import { failIfMissing } from "bailian-cli-runtime";
import { failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
export default defineCommand({
name: "memory update",
description: "Update a memory node content",
usage: "bl memory update --node-id <id> --user-id <id> --content <text>",
usageArgs: "--node-id <id> --user-id <id> --content <text>",
options: [
{ flag: "--node-id <id>", description: "Memory node ID (required)", required: true },
{ flag: "--user-id <id>", description: "User ID (required)", required: true },
@@ -24,21 +23,19 @@ 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 "updated memory content"',
],
exampleArgs: ['--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)
failIfMissing("node-id", "bl memory update --node-id <id> --user-id <id> --content <text>");
failIfMissing("node-id", cmdUsage(config, "--node-id <id> --user-id <id> --content <text>"));
const userId = flags.userId as string;
if (!userId)
failIfMissing("user-id", "bl memory update --node-id <id> --user-id <id> --content <text>");
failIfMissing("user-id", cmdUsage(config, "--node-id <id> --user-id <id> --content <text>"));
const content = flags.content as string;
if (!content)
failIfMissing("content", "bl memory update --node-id <id> --user-id <id> --content <text>");
failIfMissing("content", cmdUsage(config, "--node-id <id> --user-id <id> --content <text>"));
const body: MemoryNodeUpdateRequest = {
user_id: userId,
+12 -13
View File
@@ -17,7 +17,7 @@ import {
isInteractive,
resolveFileUrl,
} from "bailian-cli-core";
import { promptText, failIfMissing } from "bailian-cli-runtime";
import { promptText, failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult } from "bailian-cli-runtime";
import { resolveOutputDir, resolveCredential } from "bailian-cli-core";
@@ -85,9 +85,8 @@ function buildWavHeader(dataLength: number): Buffer {
}
export default defineCommand({
name: "omni",
description: "Multimodal chat with text + audio output (Qwen-Omni)",
usage: "bl omni --message <text> [flags]",
usageArgs: "--message <text> [flags]",
options: [
{
flag: "--message <text>",
@@ -118,15 +117,15 @@ export default defineCommand({
{ flag: "--max-tokens <n>", description: "Maximum tokens to generate", type: "number" },
{ flag: "--temperature <n>", description: "Sampling temperature (0.0, 2.0]", type: "number" },
],
examples: [
'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 "Read this passage aloud" --audio-out greeting.wav',
exampleArgs: [
'--message "Hello, who are you?"',
'--message "Describe this image" --image ./photo.jpg',
'--message "What is this audio saying?" --audio https://example.com/audio.wav',
'--message "Summarize this video" --video https://example.com/video.mp4',
'--message "What is this video about?" --video ./local-video.mp4 --text-only',
'--message "Answer in Sichuan dialect: How\'s the weather today?" --voice Sunny',
'--message "Hello" --text-only --output json',
'--message "Read this passage aloud" --audio-out greeting.wav',
],
async run(config: Config, flags: GlobalFlags) {
// --- Parse messages ---
@@ -144,7 +143,7 @@ export default defineCommand({
}
userMessages = [hint];
} else {
failIfMissing("message", "bl text omni --message <text>");
failIfMissing("message", cmdUsage(config, "--message <text>"));
}
}
+11 -10
View File
@@ -1,17 +1,16 @@
import { readFile } from "node:fs/promises";
import { dirname, resolve } from "node:path";
import { defineCommand, type Config, type GlobalFlags } from "bailian-cli-core";
import { emitResult } from "bailian-cli-runtime";
import { emitResult, cmdUsage } from "bailian-cli-runtime";
import { initPipelineSteps } from "bailian-cli-runtime";
import { executePipeline, streamPipelineEvents } from "bailian-cli-runtime";
import type { PipelineLifecycleEvent } from "bailian-cli-runtime";
import { loadPipelineFile } from "./load-file.ts";
export default defineCommand({
name: "pipeline run",
description: "Run a pipeline workflow definition",
skipDefaultApiKeySetup: true,
usage: "bl pipeline run <file> [flags]",
usageArgs: "<file> [flags]",
options: [
{ flag: "--input <json>", description: "Runtime input as inline JSON" },
{ flag: "--input-file <path>", description: "Runtime input from a JSON file" },
@@ -27,17 +26,19 @@ export default defineCommand({
type: "number",
},
],
examples: [
'bl pipeline run workflow.yaml --input \'{"brief":"hello"}\'',
"bl pipeline run workflow.json --input-file inputs.json --concurrency 3",
"bl pipeline run workflow.yaml --dry-run",
"bl pipeline run workflow.json --events jsonl",
"bl pipeline run workflow.yaml --output json",
exampleArgs: [
'workflow.yaml --input \'{"brief":"hello"}\'',
"workflow.json --input-file inputs.json --concurrency 3",
"workflow.yaml --dry-run",
"workflow.json --events jsonl",
"workflow.yaml --output json",
],
async run(config: Config, flags: GlobalFlags) {
const file = ((flags._positional as string[] | undefined) ?? [])[0] as string | undefined;
if (!file) {
process.stderr.write("Error: pipeline file is required\nUsage: bl pipeline run <file>\n");
process.stderr.write(
`Error: pipeline file is required\nUsage: ${cmdUsage(config, "<file>")}\n`,
);
process.exit(2);
}
@@ -1,25 +1,21 @@
import { resolve } from "node:path";
import { defineCommand, type Config, type GlobalFlags } from "bailian-cli-core";
import { emitResult } from "bailian-cli-runtime";
import { emitResult, cmdUsage } from "bailian-cli-runtime";
import { initPipelineSteps } from "bailian-cli-runtime";
import { collectPipelineIssues, collectPipelineHints } from "bailian-cli-runtime";
import { loadPipelineFile } from "./load-file.ts";
export default defineCommand({
name: "pipeline validate",
description: "Validate a pipeline definition without executing",
skipDefaultApiKeySetup: true,
usage: "bl pipeline validate <file>",
usageArgs: "<file>",
options: [],
examples: [
"bl pipeline validate workflow.yaml",
"bl pipeline validate workflow.json --output json",
],
exampleArgs: ["workflow.yaml", "workflow.json --output json"],
async run(config: Config, flags: GlobalFlags) {
const file = ((flags._positional as string[] | undefined) ?? [])[0] as string | undefined;
if (!file) {
process.stderr.write(
"Error: pipeline file is required\nUsage: bl pipeline validate <file>\n",
`Error: pipeline file is required\nUsage: ${cmdUsage(config, "<file>")}\n`,
);
process.exit(2);
}
@@ -235,10 +235,9 @@ function printTable(rows: CheckRow[], noColor: boolean): void {
}
export default defineCommand({
name: "quota check",
description: "Check current usage against rate limits",
skipDefaultApiKeySetup: true,
usage: "bl quota check [--model <model>] [flags]",
usageArgs: "[--model <model>] [flags]",
options: [
{
flag: "--model <model>",
@@ -259,12 +258,12 @@ export default defineCommand({
type: "number",
},
],
examples: [
"bl quota check",
"bl quota check --model qwen3.6-plus",
"bl quota check --period 5",
"bl quota check --model qwen3.6-plus,qwen-turbo",
"bl quota check --output json",
exampleArgs: [
"",
"--model qwen3.6-plus",
"--period 5",
"--model qwen3.6-plus,qwen-turbo",
"--output json",
],
async run(config: Config, flags: GlobalFlags) {
const modelFlag = (flags.model as string) || undefined;
@@ -91,10 +91,9 @@ function printTable(records: LimitApplicationItem[], noColor: boolean, total: nu
}
export default defineCommand({
name: "quota history",
description: "View quota change history",
skipDefaultApiKeySetup: true,
usage: "bl quota history [flags]",
usageArgs: "[flags]",
options: [
{
flag: "--page <n>",
@@ -119,13 +118,7 @@ export default defineCommand({
type: "number",
},
],
examples: [
"bl quota history",
"bl quota history --page 2",
"bl quota history --page-size 20",
"bl quota history --model qwen-turbo",
"bl quota history --output json",
],
exampleArgs: ["", "--page 2", "--page-size 20", "--model qwen-turbo", "--output json"],
async run(config: Config, flags: GlobalFlags) {
const page = Number(flags.page) || 1;
const pageSize = Number(flags.pageSize) || 10;
@@ -152,7 +145,7 @@ export default defineCommand({
} catch (err) {
if (err instanceof BailianError && err.message.includes("NotLogined")) {
process.stderr.write(
"Error: session expired. Run `bl auth login --console` to re-authenticate.\n",
`Error: session expired. Run \`${config.binName} auth login --console\` to re-authenticate.\n`,
);
process.exit(1);
}
+7 -8
View File
@@ -150,10 +150,9 @@ function printTable(models: ModelWithQpm[], noColor: boolean): void {
}
export default defineCommand({
name: "quota list",
description: "View model RPM/TPM rate limits",
skipDefaultApiKeySetup: true,
usage: "bl quota list [--model <model>] [flags]",
usageArgs: "[--model <model>] [flags]",
options: [
{
flag: "--model <model>",
@@ -174,12 +173,12 @@ export default defineCommand({
type: "number",
},
],
examples: [
"bl quota list",
"bl quota list --model qwen3.6-plus",
"bl quota list --model qwen3.6-plus,qwen-turbo",
"bl quota list --all",
"bl quota list --output json",
exampleArgs: [
"",
"--model qwen3.6-plus",
"--model qwen3.6-plus,qwen-turbo",
"--all",
"--output json",
],
async run(config: Config, flags: GlobalFlags) {
const modelFlag = (flags.model as string) || undefined;
@@ -78,10 +78,9 @@ async function fetchModelQpmInfo(
}
export default defineCommand({
name: "quota request",
description: "Request a temporary quota increase",
skipDefaultApiKeySetup: true,
usage: "bl quota request --model <model> --tpm <value> [flags]",
usageArgs: "--model <model> --tpm <value> [flags]",
options: [
{
flag: "--model <model>",
@@ -108,10 +107,10 @@ export default defineCommand({
type: "number",
},
],
examples: [
"bl quota request --model qwen-turbo --tpm 100000",
"bl quota request --model qwen3.6-plus --tpm 8000000 --yes",
"bl quota request --model qwen-turbo --tpm 100000 --output json",
exampleArgs: [
"--model qwen-turbo --tpm 100000",
"--model qwen3.6-plus --tpm 8000000 --yes",
"--model qwen-turbo --tpm 100000 --output json",
],
async run(config: Config, flags: GlobalFlags) {
const modelName = flags.model as string;
@@ -147,7 +146,9 @@ export default defineCommand({
process.stderr.write(
`Error: model "${modelName}" not found or does not support self-service quota increase.\n`,
);
process.stderr.write("Hint: run `bl quota list` to view available models.\n");
process.stderr.write(
`Hint: run \`${config.binName} quota list\` to view available models.\n`,
);
process.exit(1);
}
@@ -186,7 +187,7 @@ export default defineCommand({
} catch (err) {
if (err instanceof BailianError && err.message.includes("NotLogined")) {
process.stderr.write(
"Error: session expired. Run `bl auth login --console` to re-authenticate.\n",
`Error: session expired. Run \`${config.binName} auth login --console\` to re-authenticate.\n`,
);
process.exit(1);
}
+8 -9
View File
@@ -8,23 +8,22 @@ import {
McpClient,
} from "bailian-cli-core";
import { createSpinner } from "bailian-cli-runtime";
import { promptText, failIfMissing } from "bailian-cli-runtime";
import { promptText, failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult } from "bailian-cli-runtime";
export default defineCommand({
name: "search web",
description: "Search the web using DashScope MCP WebSearch service",
usage: "bl search web --query <text> [flags]",
usageArgs: "--query <text> [flags]",
options: [
{ flag: "--query <text>", description: "Search query text", required: true },
{ flag: "--count <n>", description: "Number of search results (default: 10)", type: "number" },
{ flag: "--list-tools", description: "List available MCP tools and exit" },
],
examples: [
'bl search web --query "Alibaba Cloud Bailian latest features"',
'bl search web --query "TypeScript 5.9 new features" --count 5',
'bl search web --query "Today\'s news"',
"bl search web --list-tools",
exampleArgs: [
'--query "Alibaba Cloud Bailian latest features"',
'--query "TypeScript 5.9 new features" --count 5',
'--query "Today\'s news"',
"--list-tools",
],
async run(config: Config, flags: GlobalFlags) {
const mcpUrl = mcpWebSearchEndpoint(config.baseUrl);
@@ -56,7 +55,7 @@ export default defineCommand({
}
query = hint;
} else {
failIfMissing("query", "bl search web --query <text>");
failIfMissing("query", cmdUsage(config, "--query <text>"));
}
}
@@ -19,13 +19,12 @@ import {
speechRecognizeEndpoint,
} from "bailian-cli-core";
import { poll } from "bailian-cli-runtime";
import { failIfMissing } from "bailian-cli-runtime";
import { failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
export default defineCommand({
name: "speech recognize",
description: "Recognize speech from audio files (FunAudio-ASR)",
usage: "bl speech recognize --url <audio-url> [flags]",
usageArgs: "--url <audio-url> [flags]",
options: [
{
flag: "--url <url>",
@@ -51,14 +50,14 @@ export default defineCommand({
type: "number",
},
],
examples: [
"bl speech recognize --url https://example.com/audio.mp3",
"bl speech recognize --url https://example.com/a.mp3 --url https://example.com/b.mp3",
"bl speech recognize --url https://example.com/meeting.wav --diarization --speaker-count 3",
"bl speech recognize --url https://example.com/audio.mp3 --language zh",
"bl speech recognize --url https://example.com/audio.mp3 --vocabulary-id vocab-abc123",
"bl speech recognize --url https://example.com/audio.mp3 --out result.json",
"bl speech recognize --url https://example.com/audio.mp3 --no-wait --quiet",
exampleArgs: [
"--url https://example.com/audio.mp3",
"--url https://example.com/a.mp3 --url https://example.com/b.mp3",
"--url https://example.com/meeting.wav --diarization --speaker-count 3",
"--url https://example.com/audio.mp3 --language zh",
"--url https://example.com/audio.mp3 --vocabulary-id vocab-abc123",
"--url https://example.com/audio.mp3 --out result.json",
"--url https://example.com/audio.mp3 --no-wait --quiet",
],
async run(config: Config, flags: GlobalFlags) {
// Normalize --url to string[] (supports both single and repeated flags)
@@ -69,7 +68,7 @@ export default defineCommand({
rawUrls = [flags.url];
}
if (rawUrls.length === 0) {
failIfMissing("url", "bl speech recognize --url <audio-url>");
failIfMissing("url", cmdUsage(config, "--url <audio-url>"));
}
// Strict validation: --speaker-count requires --diarization
@@ -23,7 +23,7 @@ import {
const COSYVOICE_CLONE_DESIGN_DOC = `${DOCS_HOSTS.cn}/cosyvoice-clone-design-api`;
import { downloadFile } from "bailian-cli-runtime";
import { runConcurrent, downloadParallel, getConcurrency } from "bailian-cli-runtime";
import { promptText, promptSelect, failIfMissing } from "bailian-cli-runtime";
import { promptText, promptSelect, failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
interface VoiceEntry {
@@ -142,9 +142,8 @@ function printVoiceList(model: string): void {
}
export default defineCommand({
name: "speech synthesize",
description: "Synthesize speech from text (CosyVoice TTS)",
usage: "bl speech synthesize --text <text> [flags]",
usageArgs: "--text <text> [flags]",
options: [
{ flag: "--text <text>", description: "Text to synthesize into speech", required: true },
{ flag: "--text-file <path>", description: "Read text from a file instead of --text" },
@@ -181,17 +180,17 @@ export default defineCommand({
},
{ flag: "--stream", description: "Stream raw PCM audio to stdout (pipe to player)" },
],
examples: [
"bl speech synthesize --list-voices --model cosyvoice-v3-flash",
'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 "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',
exampleArgs: [
"--list-voices --model cosyvoice-v3-flash",
'--text "Hello, I am Qwen" --voice <voice_id>',
'--text "Hello world" --voice <voice_id> --language en',
"--text-file script.txt --out speech.wav --voice <voice_id>",
'--text "Today is a good day" --voice <voice_id> --instruction "Use a gentle tone"',
'--text "Hello" --voice <voice_id> --format wav --sample-rate 24000',
"# Stream to audio player (macOS)",
'bl speech synthesize --text "Hello" --voice <voice_id> --stream | afplay -',
'--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 -',
'--text "Hello" --voice <voice_id> --stream | ffplay -nodisp -autoexit -f s16le -ar 24000 -ac 1 -',
],
async run(config: Config, flags: GlobalFlags) {
const model = (flags.model as string) || config.defaultSpeechModel || "cosyvoice-v3-flash";
@@ -223,7 +222,7 @@ export default defineCommand({
}
text = hint;
} else {
failIfMissing("text", "bl speech synthesize --text <text>");
failIfMissing("text", cmdUsage(config, "--text <text>"));
}
}
@@ -264,7 +263,7 @@ export default defineCommand({
const modelVoices = MODEL_VOICES[model];
if (modelVoices && modelVoices.length > 0) {
throw new BailianError(
`--voice is required.\nRun the following to see available voices:\n bl speech synthesize --list-voices --model ${model}`,
`--voice is required.\nRun the following to see available voices:\n ${cmdUsage(config, `--list-voices --model ${model}`)}`,
ExitCode.USAGE,
);
} else {
+10 -11
View File
@@ -13,7 +13,7 @@ import {
type StreamChunk,
isInteractive,
} from "bailian-cli-core";
import { promptText, failIfMissing } from "bailian-cli-runtime";
import { promptText, failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
import { readFileSync } from "fs";
@@ -68,9 +68,8 @@ function parseMessages(flags: GlobalFlags): ParsedMessages {
}
export default defineCommand({
name: "text chat",
description: "Send a chat completion (OpenAI compatible, DashScope)",
usage: "bl text chat --message <text> [flags]",
usageArgs: "--message <text> [flags]",
options: [
{ flag: "--model <model>", description: "Model ID (default: qwen3.7-max)" },
{
@@ -107,13 +106,13 @@ export default defineCommand({
type: "number",
},
],
examples: [
'bl text chat --message "What is Qwen?"',
'bl text chat --model qwen-max --system "You are a coding assistant." --message "Write fizzbuzz in Python"',
'bl text chat --message "Hello" --message "assistant:Hi!" --message "How are you?"',
"cat conversation.json | bl text chat --messages-file - --stream",
'bl text chat --message "Hello" --output json',
'bl text chat --model qwq-plus --message "Solve 1+1" --enable-thinking',
exampleArgs: [
'--message "What is Qwen?"',
'--model qwen-max --system "You are a coding assistant." --message "Write fizzbuzz in Python"',
'--message "Hello" --message "assistant:Hi!" --message "How are you?"',
"--messages-file - --stream",
'--message "Hello" --output json',
'--model qwq-plus --message "Solve 1+1" --enable-thinking',
],
async run(config: Config, flags: GlobalFlags) {
const { system, messages: parsedMessages } = parseMessages(flags);
@@ -130,7 +129,7 @@ export default defineCommand({
}
messages = [{ role: "user", content: hint }];
} else {
failIfMissing("message", "bl text chat --message <text>");
failIfMissing("message", cmdUsage(config, "--message <text>"));
}
}
+1 -3
View File
@@ -28,11 +28,9 @@ function updateAgentSkill(colors: { green: string; yellow: string; reset: string
}
export default defineCommand({
name: "update",
description: "Update the CLI to the latest version",
skipDefaultApiKeySetup: true,
usage: "bl update",
examples: ["bl update"],
exampleArgs: [""],
async run(config) {
const npmPackage = config.npmPackage!;
const binName = config.binName!;
+9 -10
View File
@@ -184,10 +184,9 @@ async function fetchAllModels(config: Config, token: string): Promise<ModelInfo[
}
export default defineCommand({
name: "usage free",
description: "Query free-tier quota for models (all models if --model is omitted)",
skipDefaultApiKeySetup: true,
usage: "bl usage free [--model <model>[,model2,...]] [flags]",
usageArgs: "[--model <model>[,model2,...]] [flags]",
options: [
{
flag: "--model <model>",
@@ -212,14 +211,14 @@ export default defineCommand({
type: "number",
},
],
examples: [
"bl usage free",
"bl usage free --model qwen3-max",
"bl usage free --model qwen3-max,qwen-turbo",
"bl usage free --expiring 30",
"bl usage free --sort remaining",
"bl usage free --model qwen-turbo --output json",
"bl usage free --model qwen3-max --console-region cn-beijing",
exampleArgs: [
"",
"--model qwen3-max",
"--model qwen3-max,qwen-turbo",
"--expiring 30",
"--sort remaining",
"--model qwen-turbo --output json",
"--model qwen3-max --console-region cn-beijing",
],
async run(config: Config, flags: GlobalFlags) {
const modelFlag = (flags.model as string) || undefined;
@@ -100,11 +100,10 @@ async function fetchAllModelNames(config: Config, token: string): Promise<string
}
export default defineCommand({
name: "usage freetier",
description:
"Enable or disable auto-stop for free-tier models. Enables by default; use --off to disable",
skipDefaultApiKeySetup: true,
usage: "bl usage freetier <--model <model>[,model2,...] | --all> [--off] [flags]",
usageArgs: "<--model <model>[,model2,...] | --all> [--off] [flags]",
options: [
{
flag: "--model <model>",
@@ -133,13 +132,13 @@ export default defineCommand({
type: "number",
},
],
examples: [
"bl usage freetier --model qwen3-max",
"bl usage freetier --model qwen3-max,qwen-turbo",
"bl usage freetier --all",
"bl usage freetier --on --model qwen3-max",
"bl usage freetier --off --model qwen3-max",
"bl usage freetier --off --all",
exampleArgs: [
"--model qwen3-max",
"--model qwen3-max,qwen-turbo",
"--all",
"--on --model qwen3-max",
"--off --model qwen3-max",
"--off --all",
],
async run(config: Config, flags: GlobalFlags) {
const modelFlag = (flags.model as string) || undefined;
+13 -12
View File
@@ -101,9 +101,11 @@ function resolveWorkspaceId(config: Config, flagWorkspaceId?: string): string {
if (config.workspaceId) return config.workspaceId;
process.stderr.write(
"Error: workspace-id is required. Set via --workspace-id, BAILIAN_WORKSPACE_ID, or `bl config set workspace_id <id>`.\n",
`Error: workspace-id is required. Set via --workspace-id, BAILIAN_WORKSPACE_ID, or \`${config.binName} config set workspace_id <id>\`.\n`,
);
process.stderr.write(
`Hint: run \`${config.binName} workspace list\` to view available workspaces.\n`,
);
process.stderr.write("Hint: run `bl workspace list` to view available workspaces.\n");
process.exit(1);
}
@@ -283,10 +285,9 @@ function printModelTable(
}
export default defineCommand({
name: "usage stats",
description: "Query model usage statistics",
skipDefaultApiKeySetup: true,
usage: "bl usage stats [--model <model>] [--days <days>] [flags]",
usageArgs: "[--model <model>] [--days <days>] [flags]",
options: [
{
flag: "--model <model>",
@@ -315,14 +316,14 @@ export default defineCommand({
type: "number",
},
],
examples: [
"bl usage stats",
"bl usage stats --days 30",
"bl usage stats --model qwen-turbo",
"bl usage stats --model qwen-turbo --days 7",
"bl usage stats --model qwen3.6-plus,deepseek-v4-pro",
"bl usage stats --type Text --days 14",
"bl usage stats --output json",
exampleArgs: [
"",
"--days 30",
"--model qwen-turbo",
"--model qwen-turbo --days 7",
"--model qwen3.6-plus,deepseek-v4-pro",
"--type Text --days 14",
"--output json",
],
async run(config: Config, flags: GlobalFlags) {
const modelFlag = (flags.model as string) || undefined;
@@ -10,27 +10,26 @@ import {
ExitCode,
} from "bailian-cli-core";
import { downloadFile, formatBytes } from "bailian-cli-runtime";
import { failIfMissing } from "bailian-cli-runtime";
import { failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
export default defineCommand({
name: "video download",
description: "Download a completed video by task ID",
usage: "bl video download --task-id <id> --out <path>",
usageArgs: "--task-id <id> --out <path>",
options: [
{ flag: "--task-id <id>", description: "Task ID to download from" },
{ flag: "--out <path>", description: "Output file path" },
],
examples: [
"bl video download --task-id 3b256896-xxxx --out video.mp4",
"bl video download --task-id 3b256896-xxxx --out video.mp4 --quiet",
exampleArgs: [
"--task-id 3b256896-xxxx --out video.mp4",
"--task-id 3b256896-xxxx --out video.mp4 --quiet",
],
async run(config: Config, flags: GlobalFlags) {
const taskId = flags.taskId as string | undefined;
if (!taskId) failIfMissing("task-id", "bl video download --task-id <id> --out <path>");
if (!taskId) failIfMissing("task-id", cmdUsage(config, "--task-id <id> --out <path>"));
const outPath = flags.out as string | undefined;
if (!outPath) failIfMissing("out", "bl video download --task-id <id> --out video.mp4");
if (!outPath) failIfMissing("out", cmdUsage(config, "--task-id <id> --out video.mp4"));
const format = detectOutputFormat(config.output);
+8 -9
View File
@@ -20,15 +20,14 @@ import {
} from "bailian-cli-core";
import { poll } from "bailian-cli-runtime";
import { downloadFile, formatBytes } from "bailian-cli-runtime";
import { promptText, failIfMissing } from "bailian-cli-runtime";
import { promptText, failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
import { BOOL_FLAG_PROMPT_EXTEND_API_DEFAULT, BOOL_FLAG_WATERMARK } from "bailian-cli-runtime";
export default defineCommand({
name: "video edit",
description:
"Edit a video with happyhorse-1.0-video-edit (style transfer, object replacement, etc.)",
usage: "bl video edit --video <url> --prompt <text> [flags]",
usageArgs: "--video <url> --prompt <text> [flags]",
options: [
{ flag: "--model <model>", description: "Model ID (default: happyhorse-1.0-video-edit)" },
{
@@ -77,11 +76,11 @@ export default defineCommand({
type: "number",
},
],
examples: [
'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 "Put clothes on the kitten in the video" --watermark false',
exampleArgs: [
'--video https://example.com/input.mp4 --prompt "Convert the entire scene to claymation style"',
'--video https://example.com/input.mp4 --prompt "Replace the outfit with the style shown in the image" --ref-image https://example.com/clothes.png',
'--video https://example.com/input.mp4 --prompt "Convert to anime style" --resolution 720P --download output.mp4',
'--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 ---
@@ -95,7 +94,7 @@ export default defineCommand({
}
videoUrl = hint;
} else {
failIfMissing("video", "bl video edit --video <url> --prompt <text>");
failIfMissing("video", cmdUsage(config, "--video <url> --prompt <text>"));
}
}
@@ -21,15 +21,14 @@ import {
import { poll } from "bailian-cli-runtime";
import { downloadFile, formatBytes } from "bailian-cli-runtime";
import { runConcurrent, getConcurrency } from "bailian-cli-runtime";
import { promptText, failIfMissing } from "bailian-cli-runtime";
import { promptText, failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
import { BOOL_FLAG_PROMPT_EXTEND_API_DEFAULT, BOOL_FLAG_WATERMARK } from "bailian-cli-runtime";
export default defineCommand({
name: "video generate",
description:
"Generate a video from text or image (happyhorse-1.0-t2v / happyhorse-1.0-i2v / wan2.6-t2v)",
usage: "bl video generate --prompt <text> [--image <url>] [flags]",
usageArgs: "--prompt <text> [--image <url>] [flags]",
options: [
{
flag: "--model <model>",
@@ -69,12 +68,12 @@ export default defineCommand({
type: "number",
},
],
examples: [
'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 "Make the cat in the scene move"',
'bl video generate --prompt "Mountain landscape" --resolution 720P --duration 5',
'bl video generate --prompt "A cat playing with a ball" --watermark false',
exampleArgs: [
'--prompt "A person reading a book, static shot"',
'--prompt "Ocean waves at sunset." --download sunset.mp4',
'--image https://example.com/cat.png --prompt "Make the cat in the scene move"',
'--prompt "Mountain landscape" --resolution 720P --duration 5',
'--prompt "A cat playing with a ball" --watermark false',
],
async run(config: Config, flags: GlobalFlags) {
let prompt = flags.prompt as string | undefined;
@@ -88,7 +87,7 @@ export default defineCommand({
}
prompt = hint;
} else {
failIfMissing("prompt", "bl video generate --prompt <text>");
failIfMissing("prompt", cmdUsage(config, "--prompt <text>"));
}
}
+10 -11
View File
@@ -20,15 +20,14 @@ import {
} from "bailian-cli-core";
import { poll } from "bailian-cli-runtime";
import { downloadFile, formatBytes } from "bailian-cli-runtime";
import { promptText, failIfMissing } from "bailian-cli-runtime";
import { promptText, failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
import { BOOL_FLAG_PROMPT_EXTEND_API_DEFAULT, BOOL_FLAG_WATERMARK } from "bailian-cli-runtime";
export default defineCommand({
name: "video ref",
description:
"Reference-to-video generation (happyhorse-1.0-r2v / wan2.6-r2v): multi-subject, multi-shot with voice",
usage: "bl video ref --prompt <text> --image <url>... [--ref-video <url>...] [flags]",
usageArgs: "--prompt <text> --image <url>... [--ref-video <url>...] [flags]",
options: [
{ flag: "--model <model>", description: "Model ID (default: happyhorse-1.0-r2v)" },
{
@@ -84,12 +83,12 @@ export default defineCommand({
type: "number",
},
],
examples: [
'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',
exampleArgs: [
'--prompt "Image1 running on the grass" --image person.jpg',
'--prompt "Video 1 plays guitar, Image 1 walks over" --ref-video scene.mp4 --image person.jpg',
'--prompt "Image 1 speaks" --image person.jpg --image-voice voice.mp3 --resolution 1080P',
'--prompt "Image 1 and Image 2 have a conversation" --image a.jpg --image b.jpg --image-voice va.mp3 --image-voice vb.mp3',
'--prompt "Image 1 drinks water" --image person.jpg --watermark false',
],
async run(config: Config, flags: GlobalFlags) {
// --- Validate prompt ---
@@ -105,7 +104,7 @@ export default defineCommand({
}
prompt = hint;
} else {
failIfMissing("prompt", "bl video ref --prompt <text> --image <url>");
failIfMissing("prompt", cmdUsage(config, "--prompt <text> --image <url>"));
}
}
@@ -116,7 +115,7 @@ export default defineCommand({
throw new BailianError(
"At least one --image or --ref-video is required.",
ExitCode.USAGE,
'bl video ref --prompt "description" --image person.jpg',
cmdUsage(config, '--prompt "description" --image person.jpg'),
);
}
@@ -7,21 +7,20 @@ import {
type GlobalFlags,
type DashScopeTaskResponse,
} from "bailian-cli-core";
import { failIfMissing } from "bailian-cli-runtime";
import { failIfMissing, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
export default defineCommand({
name: "video task get",
description: "Query async task status",
usage: "bl video task get --task-id <id>",
usageArgs: "--task-id <id>",
options: [{ flag: "--task-id <id>", description: "Async task ID" }],
examples: [
"bl video task get --task-id 3b256896-3e70-xxxx-xxxx-xxxxxxxxxxxx",
"bl video task get --task-id 3b256896-3e70-xxxx --output json",
exampleArgs: [
"--task-id 3b256896-3e70-xxxx-xxxx-xxxxxxxxxxxx",
"--task-id 3b256896-3e70-xxxx --output json",
],
async run(config: Config, flags: GlobalFlags) {
const taskId = flags.taskId as string | undefined;
if (!taskId) failIfMissing("task-id", "bl video task get --task-id <id>");
if (!taskId) failIfMissing("task-id", cmdUsage(config, "--task-id <id>"));
const format = detectOutputFormat(config.output);
@@ -15,7 +15,7 @@ import {
ExitCode,
isLocalFile,
} from "bailian-cli-core";
import { promptText } from "bailian-cli-runtime";
import { promptText, cmdUsage } from "bailian-cli-runtime";
import { emitResult, emitBare } from "bailian-cli-runtime";
import { readFileSync, existsSync } from "fs";
import { extname } from "path";
@@ -57,9 +57,8 @@ async function toImageUrl(image: string): Promise<string> {
}
export default defineCommand({
name: "vision describe",
description: "Describe an image or video using Qwen-VL",
usage: "bl vision describe --image <path-or-url> [--video <url>] [--prompt <text>]",
usageArgs: "--image <path-or-url> [--video <url>] [--prompt <text>]",
options: [
{ flag: "--image <path-or-url>", description: "Local image path or URL" },
{
@@ -70,12 +69,12 @@ export default defineCommand({
{ flag: "--prompt <text>", description: "Question about the content (default: auto-detected)" },
{ flag: "--model <model>", description: "Vision model (default: qwen3-vl-plus)" },
],
examples: [
"bl vision describe --image photo.jpg",
'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',
exampleArgs: [
"--image photo.jpg",
'--image https://example.com/photo.jpg --prompt "What breed is this dog?"',
'--video https://example.com/video.mp4 --prompt "Summarize the video content"',
"--video ./local-video.mp4",
'--image photo.png --prompt "Extract the text" --model qwen-vl-plus',
],
async run(config: Config, flags: GlobalFlags) {
let image = (flags.image ?? (flags._positional as string[] | undefined)?.[0]) as
@@ -113,7 +112,7 @@ export default defineCommand({
throw new BailianError(
"Missing required argument --image or --video.",
ExitCode.USAGE,
"bl vision describe --image <path-or-url>\nbl vision describe --video <url-or-path>",
`${cmdUsage(config, "--image <path-or-url>")}\n${cmdUsage(config, "--video <url-or-path>")}`,
);
}
}
@@ -76,10 +76,9 @@ function printTable(workspaces: WorkspaceInfo[], noColor: boolean): void {
}
export default defineCommand({
name: "workspace list",
description: "List all workspaces",
skipDefaultApiKeySetup: true,
usage: "bl workspace list [flags]",
usageArgs: "[flags]",
options: [
{
flag: "--list <n>",
@@ -96,7 +95,7 @@ export default defineCommand({
type: "number",
},
],
examples: ["bl workspace list", "bl workspace list --list 5", "bl workspace list --output json"],
exampleArgs: ["", "--list 5", "--output json"],
async run(config: Config, flags: GlobalFlags) {
const limit = Number(flags.list) || 0;
const format = detectOutputFormat(config.output);
+49 -62
View File
@@ -1,63 +1,50 @@
// Command library for bailian-cli products. Exposes the full command set, the
// per-capability groups, and individual command implementations so each
// entrypoint (bl / rag / …) can pick and remap exactly what it needs.
// Command library for bailian-cli products. Exposes individual command
// implementations only — no path presets or capability groups. Each product
// entrypoint (bl / rag / …) builds its own `{ "<path>": command }` map, so the
// command paths a product exposes are a product decision, not baked in here.
export {
commands,
baseCommands,
knowledgeCommands,
textCommands,
mediaCommands,
memoryCommands,
miscCommands,
} from "./commands/groups.ts";
// Individual command implementations (for custom path remapping).
export {
authLogin,
authStatus,
authLogout,
textChat,
textOmni,
imageGenerate,
imageEdit,
videoGenerate,
videoEdit,
videoRef,
videoTaskGet,
videoDownload,
visionDescribe,
configShow,
configSet,
configExportSchema,
update,
appCall,
appList,
memoryAdd,
memorySearch,
memoryList,
memoryUpdate,
memoryDelete,
memoryProfileCreate,
memoryProfileGet,
knowledgeRetrieve,
mcpCall,
mcpList,
mcpTools,
searchWeb,
speechSynthesize,
speechRecognize,
fileUpload,
consoleCall,
usageFree,
usageFreetier,
usageStats,
pipelineRun,
pipelineValidate,
advisorRecommend,
workspaceList,
quotaList,
quotaRequest,
quotaHistory,
quotaCheck,
} from "./commands/groups.ts";
export { default as authLogin } from "./commands/auth/login.ts";
export { default as authStatus } from "./commands/auth/status.ts";
export { default as authLogout } from "./commands/auth/logout.ts";
export { default as textChat } from "./commands/text/chat.ts";
export { default as textOmni } from "./commands/omni/chat.ts";
export { default as imageGenerate } from "./commands/image/generate.ts";
export { default as imageEdit } from "./commands/image/edit.ts";
export { default as videoGenerate } from "./commands/video/generate.ts";
export { default as videoEdit } from "./commands/video/edit.ts";
export { default as videoRef } from "./commands/video/ref.ts";
export { default as videoTaskGet } from "./commands/video/task-get.ts";
export { default as videoDownload } from "./commands/video/download.ts";
export { default as visionDescribe } from "./commands/vision/describe.ts";
export { default as configShow } from "./commands/config/show.ts";
export { default as configSet } from "./commands/config/set.ts";
export { default as update } from "./commands/update.ts";
export { default as appCall } from "./commands/app/call.ts";
export { default as appList } from "./commands/app/list.ts";
export { default as memoryAdd } from "./commands/memory/add.ts";
export { default as memorySearch } from "./commands/memory/search.ts";
export { default as memoryList } from "./commands/memory/list.ts";
export { default as memoryUpdate } from "./commands/memory/update.ts";
export { default as memoryDelete } from "./commands/memory/delete.ts";
export { default as memoryProfileCreate } from "./commands/memory/profile-create.ts";
export { default as memoryProfileGet } from "./commands/memory/profile-get.ts";
export { default as knowledgeRetrieve } from "./commands/knowledge/retrieve.ts";
export { default as mcpCall } from "./commands/mcp/call.ts";
export { default as mcpList } from "./commands/mcp/list.ts";
export { default as mcpTools } from "./commands/mcp/tools.ts";
export { default as searchWeb } from "./commands/search/web.ts";
export { default as speechSynthesize } from "./commands/speech/synthesize.ts";
export { default as speechRecognize } from "./commands/speech/recognize.ts";
export { default as fileUpload } from "./commands/file/upload.ts";
export { default as consoleCall } from "./commands/console/call.ts";
export { default as usageFree } from "./commands/usage/free.ts";
export { default as usageFreetier } from "./commands/usage/freetier.ts";
export { default as usageStats } from "./commands/usage/stats.ts";
export { default as pipelineRun } from "./commands/pipeline/run.ts";
export { default as pipelineValidate } from "./commands/pipeline/validate.ts";
export { default as advisorRecommend } from "./commands/advisor/recommend.ts";
export { default as workspaceList } from "./commands/workspace/list.ts";
export { default as quotaList } from "./commands/quota/list.ts";
export { default as quotaRequest } from "./commands/quota/request.ts";
export { default as quotaHistory } from "./commands/quota/history.ts";
export { default as quotaCheck } from "./commands/quota/check.ts";
+19 -9
View File
@@ -9,22 +9,33 @@ export interface OptionDef {
}
export interface Command {
name: string;
description: string;
usage?: string;
/**
* Argument portion of the usage line, WITHOUT the `<bin> <path>` prefix
* (e.g. "--index-id <id> --query <text> [flags]"). The runtime prepends the
* product binary name and the command's actual path when rendering help, so
* the same command renders correctly under any product (bl / rag / …).
*/
usageArgs?: string;
options?: OptionDef[];
examples?: string[];
/**
* Example argument strings, each WITHOUT the `<bin> <path>` prefix
* (e.g. '--index-id idx_xxx --query "..."'). The runtime prepends
* `<bin> <path>` per product when rendering help.
*/
exampleArgs?: string[];
skipDefaultApiKeySetup?: boolean;
notes?: string[];
execute: (config: Config, flags: GlobalFlags) => Promise<void>;
}
export interface CommandSpec {
name: string;
description: string;
usage?: string;
/** See {@link Command.usageArgs} — argument portion only, no `<bin> <path>` prefix. */
usageArgs?: string;
options?: OptionDef[];
examples?: string[];
/** See {@link Command.exampleArgs} — argument strings only, no `<bin> <path>` prefix. */
exampleArgs?: string[];
skipDefaultApiKeySetup?: boolean;
notes?: string[];
run: (config: Config, flags: GlobalFlags) => Promise<void>;
@@ -32,11 +43,10 @@ export interface CommandSpec {
export function defineCommand(spec: CommandSpec): Command {
return {
name: spec.name,
description: spec.description,
usage: spec.usage,
usageArgs: spec.usageArgs,
options: spec.options,
examples: spec.examples,
exampleArgs: spec.exampleArgs,
skipDefaultApiKeySetup: spec.skipDefaultApiKeySetup,
notes: spec.notes,
execute: (config, flags) => spec.run(config, flags),
-1
View File
@@ -1,6 +1,5 @@
export { generateFilename } from "./filename.ts";
export { resolveOutputDir } from "./output-dir.ts";
export { generateToolSchema } from "./schema.ts";
export { maskToken } from "./token.ts";
export { isInteractive } from "./env.ts";
export { isCI } from "./env.ts";
-82
View File
@@ -1,82 +0,0 @@
import type { Command } from "../types/command.ts";
/**
* Parse a CLI flag string (e.g. "--prompt <text>", "--stream") into
* a parameter name and inferred type.
*/
function parseFlag(flag: string): {
name: string;
kebabName: string;
inferredType: string;
isArray: boolean;
} {
// e.g. "--prompt <text>" -> "prompt"
const match = flag.match(/^--([a-zA-Z0-9-]+)/);
const kebabName = match ? match[1]! : "";
// camelCase to match internal API conventions
const name = kebabName.replace(/-([a-zA-Z0-9])/g, (_, c: string) => c.toUpperCase());
let inferredType = "string";
let isArray = false;
if (!flag.includes("<") && !flag.includes("[")) {
// No parameter value — typically a boolean flag like --stream
inferredType = "boolean";
} else if (
flag.includes("<n>") ||
flag.includes("<hz>") ||
flag.includes("<bps>") ||
flag.includes("<count>")
) {
inferredType = "number";
}
if (flag.toLowerCase().includes("repeatable")) {
isArray = true;
}
return { name, kebabName, inferredType, isArray };
}
export function generateToolSchema(cmd: Command): Record<string, unknown> {
const toolName = `bailian_${cmd.name.replace(/ /g, "_")}`;
const schema: Record<string, unknown> = {
name: toolName,
description: cmd.description,
input_schema: {
type: "object",
properties: {} as Record<string, unknown>,
required: [] as string[],
},
};
if (cmd.options) {
for (const opt of cmd.options) {
const { name, inferredType, isArray } = parseFlag(opt.flag);
if (!name) continue;
// Explicit type from OptionDef takes precedence; fall back to inference
const explicitType = opt.type;
const effectiveType = isArray ? "array" : (explicitType ?? inferredType);
const propSchema: Record<string, unknown> = { description: opt.description };
if (effectiveType === "array") {
propSchema.type = "array";
propSchema.items = { type: "string" };
} else {
propSchema.type = effectiveType;
}
const inputSchema = schema.input_schema as Record<string, unknown>;
(inputSchema.properties as Record<string, unknown>)[name] = propSchema;
if (opt.required) {
(inputSchema.required as string[]).push(name);
}
}
}
return schema;
}
+47 -13
View File
@@ -1,16 +1,50 @@
import { createCli } from "bailian-cli-runtime";
import { baseCommands, knowledgeCommands } from "bailian-cli-commands";
import type { Command } from "bailian-cli-core";
import {
authLogin,
authStatus,
authLogout,
configShow,
configSet,
update,
fileUpload,
usageFree,
usageFreetier,
usageStats,
quotaList,
quotaRequest,
quotaHistory,
quotaCheck,
knowledgeRetrieve,
} from "bailian-cli-commands";
import pkg from "../package.json" with { type: "json" };
// rag-cli: knowledge-base product. Ships only the base infrastructure commands
// (auth, config, usage, quota, update, file upload) plus the knowledge commands —
// no model/app capabilities. Command paths are kept as-is (e.g. `rag knowledge retrieve`).
createCli(
{ ...baseCommands, ...knowledgeCommands },
{
binName: "rag",
version: pkg.version,
clientName: "rag-cli",
npmPackage: "bailian-cli-rag",
},
).run();
// rag-cli: knowledge-base product. Ships the base infrastructure commands
// (auth, config, usage, quota, update, file upload) plus knowledge retrieval,
// remapped to a flat `rag retrieve` path. Routing is driven entirely by these
// keys, and usage/examples/errors render the path from the key — so the same
// shared command shows `rag retrieve` here and `bl knowledge retrieve` in bl.
const commands: Record<string, Command> = {
"auth login": authLogin,
"auth status": authStatus,
"auth logout": authLogout,
"config show": configShow,
"config set": configSet,
update,
"file upload": fileUpload,
"usage free": usageFree,
"usage freetier": usageFreetier,
"usage stats": usageStats,
"quota list": quotaList,
"quota request": quotaRequest,
"quota history": quotaHistory,
"quota check": quotaCheck,
retrieve: knowledgeRetrieve,
};
createCli(commands, {
binName: "rag",
version: pkg.version,
clientName: "rag-cli",
npmPackage: "bailian-cli-rag",
}).run();
+7 -1
View File
@@ -22,7 +22,13 @@ export { BAILIAN_CONSOLE_ROOT, BAILIAN_CONSOLE, API_KEY_PAGE } from "./urls.ts";
// Output facilities consumed by commands
export { emitResult, emitBare } from "./output/output.ts";
export { promptText, promptSelect, promptConfirm, failIfMissing } from "./output/prompt.ts";
export {
promptText,
promptSelect,
promptConfirm,
failIfMissing,
cmdUsage,
} from "./output/prompt.ts";
export { createSpinner, createProgressBar } from "./output/progress.ts";
export { printWelcomeBanner, printQuickStart } from "./output/banner.ts";
export { maybeShowStatusBar } from "./output/status-bar.ts";
+12 -1
View File
@@ -10,9 +10,20 @@
* case explicitly.
*/
import { BailianError, ExitCode, isInteractive } from "bailian-cli-core";
import { BailianError, ExitCode, isInteractive, type Config } from "bailian-cli-core";
import { printCurrentCommandHelp, getExecutingCommandPath } from "../utils/command-help.ts";
/**
* Build a command-usage string for the running command: `<binName> <path> <args>`.
* Both the product binary name and the command path come from the runtime, so
* callers never hardcode "bl" or their own path — the same code renders as
* `bl knowledge retrieve …` under bl and `rag retrieve …` under rag.
*/
export function cmdUsage(config: Config, args = ""): string {
const parts = [config.binName, ...getExecutingCommandPath()].filter(Boolean);
return args ? `${parts.join(" ")} ${args}` : parts.join(" ");
}
// Dynamic import to avoid loading @clack/prompts in non-interactive envs unnecessarily
// (though for CLI tools the startup cost is usually acceptable)
+10 -6
View File
@@ -165,7 +165,7 @@ export class CommandRegistry {
}
if (node.command) {
this.printCommandHelp(node.command, out);
this.printCommandHelp(node.command, commandPath, out);
return;
}
@@ -244,13 +244,17 @@ ${b("Getting Help:")}
`);
}
private printCommandHelp(cmd: Command, out: NodeJS.WriteStream): void {
private printCommandHelp(cmd: Command, commandPath: string[], out: NodeJS.WriteStream): void {
const b = (s: string) => this.bold(s, out);
const a = (s: string) => this.accent(s, out);
const d = (s: string) => this.dim(s, out);
// `<bin> <path>` prefix is rendered here, not stored in the command, so the
// same command shows the right invocation under any product (bl / rag / …).
const prefix = [this.cliName, ...commandPath].join(" ");
out.write(`\n${cmd.description}\n`);
if (cmd.usage) out.write(`${b("Usage:")} ${cmd.usage}\n`);
out.write(`${b("Usage:")} ${prefix}${cmd.usageArgs ? ` ${cmd.usageArgs}` : ""}\n`);
if (cmd.options && cmd.options.length > 0) {
const maxLen = Math.max(...cmd.options.map((o) => o.flag.length));
out.write(`\n${b("Options:")}\n`);
@@ -264,10 +268,10 @@ ${b("Getting Help:")}
out.write(` ${note}\n`);
}
}
if (cmd.examples && cmd.examples.length > 0) {
if (cmd.exampleArgs && cmd.exampleArgs.length > 0) {
out.write(`\n${b("Examples:")}\n`);
for (const ex of cmd.examples) {
out.write(` ${d(ex)}\n`);
for (const ex of cmd.exampleArgs) {
out.write(` ${d(ex ? `${prefix} ${ex}` : prefix)}\n`);
}
}
out.write(
+2 -2
View File
@@ -1,6 +1,6 @@
# `bl advisor` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
@@ -52,5 +52,5 @@ bl advisor recommend --message "Long document summarization" --dry-run
```
```bash
bl advisor recommend # Interactive input
bl advisor recommend # Interactive input
```
+1 -1
View File
@@ -1,6 +1,6 @@
# `bl app` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
+2 -2
View File
@@ -1,6 +1,6 @@
# `bl auth` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
@@ -21,7 +21,7 @@ Index: [index.md](index.md)
| --------------- | ---------------------------------------------------------------------------- |
| **Name** | `auth login` |
| **Description** | Authenticate with API key or console browser login (credentials can coexist) |
| **Usage** | `bl auth login --api-key <key> \| bl auth login --console` |
| **Usage** | `bl auth login --api-key <key> \| --console` |
#### Options
+5 -30
View File
@@ -1,44 +1,19 @@
# `bl config` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
## Commands in this group
| Command | Description |
| ------------------------- | ----------------------------------------------------------------------------------- |
| `bl config export-schema` | Export all (or one) CLI command(s) as Anthropic/OpenAI-compatible JSON tool schemas |
| `bl config set` | Set a config value |
| `bl config show` | Display current configuration |
| Command | Description |
| ---------------- | ----------------------------- |
| `bl config set` | Set a config value |
| `bl config show` | Display current configuration |
## Command details
### `bl config export-schema`
| Field | Value |
| --------------- | ----------------------------------------------------------------------------------- |
| **Name** | `config export-schema` |
| **Description** | Export all (or one) CLI command(s) as Anthropic/OpenAI-compatible JSON tool schemas |
| **Usage** | `bl config export-schema [--command "<name>"]` |
#### Options
| Flag | Type | Required | Description |
| ------------------ | ------ | -------- | ----------------------------------------------------------------- |
| `--command <name>` | string | no | Export schema for a specific command only (e.g. "image generate") |
#### Examples
```bash
bl config export-schema
```
```bash
bl config export-schema --command "video generate"
```
### `bl config set`
| Field | Value |
+1 -1
View File
@@ -1,6 +1,6 @@
# `bl console` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
+1 -1
View File
@@ -1,6 +1,6 @@
# `bl file` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
+1 -1
View File
@@ -1,6 +1,6 @@
# `bl image` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
+2 -3
View File
@@ -1,6 +1,6 @@
# bailian-cli (`bl`) command reference
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Command **details** are in sibling `<group>.md` files in this directory.
@@ -16,7 +16,6 @@ Use this index for the full quick index and global flags.
| `bl auth login` | Authenticate with API key or console browser login (credentials can coexist) | [auth.md](auth.md) |
| `bl auth logout` | Clear stored credentials | [auth.md](auth.md) |
| `bl auth status` | Show current authentication state | [auth.md](auth.md) |
| `bl config export-schema` | Export all (or one) CLI command(s) as Anthropic/OpenAI-compatible JSON tool schemas | [config.md](config.md) |
| `bl config set` | Set a config value | [config.md](config.md) |
| `bl config show` | Display current configuration | [config.md](config.md) |
| `bl console call` | Call a Bailian console API via the CLI gateway | [console.md](console.md) |
@@ -64,7 +63,7 @@ Use this index for the full quick index and global flags.
| `advisor` | `recommend` | [advisor.md](advisor.md) |
| `app` | `call`, `list` | [app.md](app.md) |
| `auth` | `login`, `logout`, `status` | [auth.md](auth.md) |
| `config` | `export-schema`, `set`, `show` | [config.md](config.md) |
| `config` | `set`, `show` | [config.md](config.md) |
| `console` | `call` | [console.md](console.md) |
| `file` | `upload` | [file.md](file.md) |
| `image` | `edit`, `generate` | [image.md](image.md) |
+1 -1
View File
@@ -1,6 +1,6 @@
# `bl knowledge` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
+5 -5
View File
@@ -1,6 +1,6 @@
# `bl mcp` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
@@ -91,10 +91,10 @@ bl mcp list --output json
#### Options
| Flag | Type | Required | Description |
| --------------- | ------ | -------- | ---------------------------------------------------------- |
| `<server-code>` | string | yes | Server code from `bl mcp list` (e.g. market-cmapi00073529) |
| `--url <url>` | string | no | Override the MCP endpoint URL (for non-Bailian servers) |
| Flag | Type | Required | Description |
| --------------- | ------ | -------- | ------------------------------------------------------- |
| `<server-code>` | string | yes | Server code from `mcp list` (e.g. market-cmapi00073529) |
| `--url <url>` | string | no | Override the MCP endpoint URL (for non-Bailian servers) |
#### Examples
+1 -1
View File
@@ -1,6 +1,6 @@
# `bl memory` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
+1 -1
View File
@@ -1,6 +1,6 @@
# `bl omni` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
+1 -1
View File
@@ -1,6 +1,6 @@
# `bl pipeline` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
+1 -1
View File
@@ -1,6 +1,6 @@
# `bl quota` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
+1 -1
View File
@@ -1,6 +1,6 @@
# `bl search` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
+3 -3
View File
@@ -1,6 +1,6 @@
# `bl speech` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
@@ -123,7 +123,7 @@ bl speech synthesize --text "Hello" --voice <voice_id> --format wav --sample-rat
```
```bash
# Stream to audio player (macOS)
bl speech synthesize # Stream to audio player (macOS)
```
```bash
@@ -131,7 +131,7 @@ bl speech synthesize --text "Hello" --voice <voice_id> --stream | afplay -
```
```bash
# Pipe to ffplay
bl speech synthesize # Pipe to ffplay
```
```bash
+2 -2
View File
@@ -1,6 +1,6 @@
# `bl text` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
@@ -52,7 +52,7 @@ bl text chat --message "Hello" --message "assistant:Hi!" --message "How are you?
```
```bash
cat conversation.json | bl text chat --messages-file - --stream
bl text chat --messages-file - --stream
```
```bash
+1 -1
View File
@@ -1,6 +1,6 @@
# `bl update` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
+1 -1
View File
@@ -1,6 +1,6 @@
# `bl usage` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
+1 -1
View File
@@ -1,6 +1,6 @@
# `bl video` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
+1 -1
View File
@@ -1,6 +1,6 @@
# `bl vision` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
+1 -1
View File
@@ -1,6 +1,6 @@
# `bl workspace` commands
> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.
> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.
> Regenerate: `pnpm --filter bailian-cli run generate:reference`.
Index: [index.md](index.md)
+16 -11
View File
@@ -1,5 +1,5 @@
/**
* Generator: reads `packages/commands/src/commands/catalog.ts` and writes:
* Generator: reads the bl product command map (`packages/cli/src/commands.ts`) and writes:
* - `skills/bailian-cli/reference/index.md` — quick index, global flags, notes
* - `skills/bailian-cli/reference/<group>.md` — per top-level command group details
*
@@ -12,14 +12,14 @@ import { mkdirSync, readdirSync, rmSync, writeFileSync } from "node:fs";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { GLOBAL_OPTIONS, type Command, type OptionDef } from "../packages/core/dist/index.mjs";
import { commands } from "../packages/commands/src/commands/catalog.ts";
import { commands } from "../packages/cli/src/commands.ts";
const __dirname = dirname(fileURLToPath(import.meta.url));
const REF_DIR = join(__dirname, "../skills/bailian-cli/reference");
const INDEX_PATH = join(REF_DIR, "index.md");
const GENERATED_BANNER =
"> Auto-generated from `packages/commands/src/commands/catalog.ts`. Do not edit by hand.\n" +
"> Auto-generated from `packages/cli/src/commands.ts`. Do not edit by hand.\n" +
"> Regenerate: `pnpm --filter bailian-cli run generate:reference`.";
function escCell(s: string): string {
@@ -50,9 +50,14 @@ function formatOptionsTable(options: OptionDef[] | undefined): string {
].join("\n");
}
function formatExamples(examples: string[] | undefined): string {
if (!examples?.length) return "_No examples._\n";
return examples.map((ex) => ["```bash", ex, "```"].join("\n")).join("\n\n") + "\n";
function formatExamples(path: string, exampleArgs: string[] | undefined): string {
if (!exampleArgs?.length) return "_No examples._\n";
// Commands store argument-only examples; prepend `bl <path>` for the reference.
return (
exampleArgs
.map((ex) => ["```bash", `bl ${path}${ex ? ` ${ex}` : ""}`, "```"].join("\n"))
.join("\n\n") + "\n"
);
}
function formatNotes(notes: string[] | undefined): string {
@@ -64,11 +69,11 @@ function commandSection(path: string, cmd: Command): string {
const lines: string[] = [];
lines.push(`### \`bl ${path}\``, "");
lines.push(`| Field | Value |`, `| --- | --- |`);
lines.push(`| **Name** | \`${escCell(cmd.name)}\` |`);
lines.push(`| **Name** | \`${escCell(path)}\` |`);
lines.push(`| **Description** | ${escCell(cmd.description)} |`);
if (cmd.usage) {
lines.push(`| **Usage** | \`${escCell(cmd.usage)}\` |`);
}
// Commands store argument-only usage; the `bl <path>` prefix is added here.
const usage = `bl ${path}${cmd.usageArgs ? ` ${cmd.usageArgs}` : ""}`;
lines.push(`| **Usage** | \`${escCell(usage)}\` |`);
lines.push("");
lines.push("#### Options", "");
@@ -80,7 +85,7 @@ function commandSection(path: string, cmd: Command): string {
}
lines.push("#### Examples", "");
lines.push(formatExamples(cmd.examples));
lines.push(formatExamples(path, cmd.exampleArgs));
return lines.join("\n");
}