Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 10 additions & 9 deletions packages/cli/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,16 @@ irm https://bailian.aliyun.com/cli/install.ps1 | iex

Once installed, just describe your task to your AI Agent — no need to assemble commands by hand.

| Scenario | What to say to your Agent |
| ------------------------ | --------------------------------------------------------------------------------- |
| Managed Agent | "Create a Managed Agent that can generate short-film storyboards and videos." |
| Image & video generation | "Generate an image of a cat in a spacesuit on Mars, then turn it into a video." |
| Speech recognition | "Transcribe this audio; if proper nouns are wrong, add hot words and try again." |
| Usage & quota | "Show my recent model usage, free-tier quota, and rate limits." |
| Monitoring & alerts | "Show my model call stats, failures and logs, and create an alert rule." |
| Model selection | "Recommend a model for image understanding and customer support." |
| About Bailian CLI | "Tell me what Bailian CLI can do for me, and suggest how to use it for my needs." |
| Scenario | What to say to your Agent |
| ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| Managed Agent | "Create a Managed Agent that can generate short-film storyboards and videos." |
| Image & video generation | "Generate an image of a cat in a spacesuit on Mars, then turn it into a video." |
| Speech recognition | "Transcribe this audio; if proper nouns are wrong, add hot words and try again." |
| Usage & quota | "Show my recent model usage, free-tier quota, and rate limits." |
| Monitoring & alerts | "Show my model call stats, failures and logs, and create an alert rule." |
| Throughput reservations | "List my throughput reservations and capacity instances, then scale, renew or release capacity and wait for the operation to finish." |
| Model selection | "Recommend a model for image understanding and customer support." |
| About Bailian CLI | "Tell me what Bailian CLI can do for me, and suggest how to use it for my needs." |

> More examples and scenarios: [Aliyun Model Studio CLI Site](https://bailian.console.aliyun.com/cli?source_channel=cli_github&)

Expand Down
19 changes: 10 additions & 9 deletions packages/cli/README.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,15 +111,16 @@ irm https://bailian.aliyun.com/cli/install.ps1 | iex

安装完成后,直接在 AI Agent 中描述你的任务,无需手动拼接命令。

| 场景 | 可以这样对 Agent 说 |
| ---------------- | ----------------------------------------------------------------------- |
| Managed Agent | “帮我创建一个能够生成短片分镜和视频的 Managed Agent。” |
| 图片和视频生成 | “生成一张穿着太空服的猫站在火星上的图片,再把它制作成一段视频。” |
| 语音识别 | “把这段音频转写成文字,专有名词识别不准的话帮我加上热词再试。” |
| 用量与额度 | “查看最近的模型用量、免费额度和限流情况。” |
| 监控与告警 | “查看我的模型调用统计、失败明细和调用日志,并创建一条告警规则。” |
| 模型选型 | “推荐一个适合图片理解和智能客服的模型。” |
| 了解 Bailian CLI | “介绍一下 Bailian CLI 能帮我完成哪些任务,并根据我的需求推荐使用方式。” |
| 场景 | 可以这样对 Agent 说 |
| ---------------- | ---------------------------------------------------------------------------- |
| Managed Agent | “帮我创建一个能够生成短片分镜和视频的 Managed Agent。” |
| 图片和视频生成 | “生成一张穿着太空服的猫站在火星上的图片,再把它制作成一段视频。” |
| 语音识别 | “把这段音频转写成文字,专有名词识别不准的话帮我加上热词再试。” |
| 用量与额度 | “查看最近的模型用量、免费额度和限流情况。” |
| 监控与告警 | “查看我的模型调用统计、失败明细和调用日志,并创建一条告警规则。” |
| 吞吐预留 | “查看我的吞吐预留及容量实例,并对容量进行扩缩、续订或释放,再等待操作完成。” |
| 模型选型 | “推荐一个适合图片理解和智能客服的模型。” |
| 了解 Bailian CLI | “介绍一下 Bailian CLI 能帮我完成哪些任务,并根据我的需求推荐使用方式。” |

> 更多案例与使用场景:[阿里云百炼 CLI 官方主页](https://bailian.console.aliyun.com/cli?source_channel=cli_github&)

Expand Down
63 changes: 63 additions & 0 deletions packages/commands/src/commands/shared/prime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import {
BailianError,
ExitCode,
workspaceMaaSBaseUrl,
type Client,
type FlagsDef,
} from "bailian-cli-core";

export const PRIME_FLAGS = {
prime: {
type: "switch",
description: {
"en-US": "Use Prime mode with a workspace-scoped endpoint",
"zh-CN": "使用工作空间专属 Endpoint 的 Prime 模式",
},
},
workspaceId: {
type: "string",
valueHint: "<id>",
description: {
"en-US": "Workspace ID for the default Prime endpoint (or set BAILIAN_WORKSPACE_ID)",
"zh-CN": "默认 Prime Endpoint 使用的 Workspace ID(也可设置 BAILIAN_WORKSPACE_ID)",
},
},
} satisfies FlagsDef;

interface PrimeFlags {
prime: boolean;
workspaceId?: string;
model?: string;
}

export function validatePrimeFlags(flags: PrimeFlags): string | undefined {
if (flags.workspaceId && !flags.prime) {
return "--workspace-id requires --prime.";
}
if (flags.prime && !flags.model) {
return "--prime requires an explicit --model.";
}
return undefined;
}

export function resolvePrimeEndpoint(
ctx: {
flags: Pick<PrimeFlags, "workspaceId">;
settings: { workspaceId?: string };
identity: { binName: string };
client: Pick<Client, "url">;
},
path: string,
): string {
return ctx.client.url(path, () => {
const workspaceId = ctx.flags.workspaceId || ctx.settings.workspaceId;
if (!workspaceId) {
throw new BailianError(
"Workspace ID is required for the default Prime endpoint.",
ExitCode.USAGE,
`Pass --workspace-id, set BAILIAN_WORKSPACE_ID env, or configure: ${ctx.identity.binName} config set workspace_id <id>. You can also override the endpoint with --base-url.`,
);
}
return workspaceMaaSBaseUrl(workspaceId);
});
}
41 changes: 37 additions & 4 deletions packages/commands/src/commands/text/chat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import {
inspectResponsesStreamEvent,
extractResponsesText,
} from "./responses.ts";
import { PRIME_FLAGS, resolvePrimeEndpoint, validatePrimeFlags } from "../shared/prime.ts";

const CHAT_FLAGS = {
api: {
Expand Down Expand Up @@ -107,6 +108,7 @@ const CHAT_FLAGS = {
"zh-CN": "思考过程最大 Token 数(默认:4096)",
},
},
...PRIME_FLAGS,
} satisfies FlagsDef;
type ChatFlags = ParsedFlags<typeof CHAT_FLAGS>;

Expand Down Expand Up @@ -187,11 +189,33 @@ export default defineCommand({
"en-US": '--model qwq-plus --message "Solve 1+1" --enable-thinking',
"zh-CN": '--model qwq-plus --message "计算 1+1" --enable-thinking',
},
{
"en-US": '--prime --workspace-id <id> --model glm-5.3-prime --message "Explain this code"',
"zh-CN": '--prime --workspace-id <id> --model glm-5.3-prime --message "解释这段代码"',
},
],
notes: [
{
"en-US":
"Prime mode requires an explicit model and currently supports only the Chat Completions API.",
"zh-CN": "Prime 模式必须显式指定模型,且当前仅支持 Chat Completions API。",
},
{
"en-US":
"Prime endpoint: configured --base-url, DASHSCOPE_BASE_URL, or profile base_url takes precedence; otherwise workspace is resolved from --workspace-id, BAILIAN_WORKSPACE_ID, then config workspace_id.",
"zh-CN":
"Prime Endpoint:已配置的 --base-url、DASHSCOPE_BASE_URL 或 Profile base_url 优先;否则按 --workspace-id、BAILIAN_WORKSPACE_ID、配置项 workspace_id 解析工作空间。",
},
],
validate: (flags) => {
if (!flags.message && !flags.messagesFile) {
return "Provide --message or --messages-file.";
}
const primeValidation = validatePrimeFlags(flags);
if (primeValidation) return primeValidation;
if (flags.prime && flags.api === "responses") {
return "--prime currently supports only --api chat.";
}
if (flags.api === "responses" && flags.thinkingBudget !== undefined) {
return "--thinking-budget is not supported by the Responses API.";
}
Expand Down Expand Up @@ -240,6 +264,12 @@ export default defineCommand({
}
}

const requestPath = flags.prime
? resolvePrimeEndpoint(ctx, chatPath())
: api === "responses"
? responsesPath()
: chatPath();

if (flags.tool) {
const tools = flags.tool.map((toolValue) => {
try {
Expand All @@ -253,13 +283,16 @@ export default defineCommand({
}

if (settings.dryRun) {
emitResult({ request: body }, format);
emitResult(
flags.prime ? { endpoint: requestPath, request: body } : { request: body },
format,
);
return;
}

if (shouldStream) {
const responseStream = await ctx.client.request({
path: api === "responses" ? responsesPath() : chatPath(),
path: requestPath,
method: "POST",
body,
stream: true,
Expand Down Expand Up @@ -336,7 +369,7 @@ export default defineCommand({
}
} else if (api === "responses") {
const response = await ctx.client.requestJson<ResponsesResponse>({
path: responsesPath(),
path: requestPath,
method: "POST",
body,
});
Expand All @@ -350,7 +383,7 @@ export default defineCommand({
}
} else {
const response = await ctx.client.requestJson<ChatResponse>({
path: chatPath(),
path: requestPath,
method: "POST",
body,
});
Expand Down
53 changes: 40 additions & 13 deletions packages/commands/src/commands/video/generate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { downloadFile, formatBytes } from "bailian-cli-runtime";
import { runConcurrent, getConcurrency } 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";
import { PRIME_FLAGS, resolvePrimeEndpoint, validatePrimeFlags } from "../shared/prime.ts";

export default defineCommand({
description: {
Expand Down Expand Up @@ -128,6 +129,7 @@ export default defineCommand({
"参考文件 URL 或本地路径,用于文件生视频(仅 wan3.0-video;与 --image/--last-frame 互斥)",
},
},
...PRIME_FLAGS,
...ASYNC_FLAG,
...CONCURRENT_FLAG,
pollInterval: {
Expand Down Expand Up @@ -160,7 +162,25 @@ export default defineCommand({
"en-US": '--prompt "A cat playing with a ball" --watermark false',
"zh-CN": '--prompt "一只正在玩球的猫" --watermark false',
},
{
"en-US":
'--prime --workspace-id <id> --model wan3.0-video-prime --prompt "Ocean waves at sunset"',
"zh-CN": '--prime --workspace-id <id> --model wan3.0-video-prime --prompt "日落时的海浪"',
},
],
notes: [
{
"en-US": "Prime mode requires an explicit model.",
"zh-CN": "Prime 模式必须显式指定模型。",
},
{
"en-US":
"Prime endpoint: configured --base-url, DASHSCOPE_BASE_URL, or profile base_url takes precedence; otherwise workspace is resolved from --workspace-id, BAILIAN_WORKSPACE_ID, then config workspace_id.",
"zh-CN":
"Prime Endpoint:已配置的 --base-url、DASHSCOPE_BASE_URL 或 Profile base_url 优先;否则按 --workspace-id、BAILIAN_WORKSPACE_ID、配置项 workspace_id 解析工作空间。",
},
],
validate: validatePrimeFlags,
async run(ctx) {
const { settings, flags } = ctx;
const prompt = flags.prompt;
Expand Down Expand Up @@ -211,6 +231,9 @@ export default defineCommand({
const watermark = resolveWatermark(flags.watermark, settings.watermark);
const promptExtend = resolveBooleanFlag(flags.promptExtend, undefined, "prompt-extend");

const requestPath = isKf2v && !isWan30 ? image2videoPath() : videoGeneratePath();
const submitPath = flags.prime ? resolvePrimeEndpoint(ctx, requestPath) : requestPath;

const body: DashScopeVideoRequest = {
model,
input: {
Expand Down Expand Up @@ -286,7 +309,10 @@ export default defineCommand({
},
};
}
emitResult({ request: previewBody }, format);
emitResult(
flags.prime ? { endpoint: submitPath, request: previewBody } : { request: previewBody },
format,
);
return;
}

Expand All @@ -298,15 +324,15 @@ export default defineCommand({
settings,
() =>
ctx.client.requestJson<DashScopeAsyncResponse>({
path: isKf2v && !isWan30 ? image2videoPath() : videoGeneratePath(),
path: submitPath,
method: "POST",
body,
async: true,
}),
"tasks",
);

const taskIds = responses.map((r) => r.output.task_id);
const taskIds = responses.map((response) => response.output.task_id);

if (!settings.quiet) {
process.stderr.write(`[Model: ${model}]\n`);
Expand All @@ -322,17 +348,19 @@ export default defineCommand({
const pollInterval = flags.pollInterval ?? 5;

const pollPromises = taskIds.map((taskId) => {
const pollUrl = ctx.client.url(taskPath(taskId));
const pollUrl = flags.prime
? resolvePrimeEndpoint(ctx, taskPath(taskId))
: ctx.client.url(taskPath(taskId));
return poll<DashScopeTaskResponse>(ctx.client, settings, {
url: pollUrl,
intervalSec: pollInterval,
timeoutSec: settings.timeout,
isComplete: (d) => (d as DashScopeTaskResponse).output.task_status === "SUCCEEDED",
isFailed: (d) => (d as DashScopeTaskResponse).output.task_status === "FAILED",
getStatus: (d) => (d as DashScopeTaskResponse).output.task_status,
getErrorMessage: (d) => {
const o = (d as DashScopeTaskResponse).output;
return o.message || o.code || undefined;
isComplete: (data) => (data as DashScopeTaskResponse).output.task_status === "SUCCEEDED",
isFailed: (data) => (data as DashScopeTaskResponse).output.task_status === "FAILED",
getStatus: (data) => (data as DashScopeTaskResponse).output.task_status,
getErrorMessage: (data) => {
const output = (data as DashScopeTaskResponse).output;
return output.message || output.code || undefined;
},
});
});
Expand All @@ -341,12 +369,11 @@ export default defineCommand({

// Collect video URLs from all results
const videos: Array<{ taskId: string; videoUrl: string }> = [];
for (let i = 0; i < results.length; i++) {
const result = results[i]!;
for (const [resultIndex, result] of results.entries()) {
const videoUrl =
result.output.video_url || (result.output.results && result.output.results[0]?.url);
if (videoUrl) {
videos.push({ taskId: taskIds[i]!, videoUrl });
videos.push({ taskId: taskIds[resultIndex]!, videoUrl });
}
}

Expand Down
Loading
Loading