From 4b788080c2c7f4a0caff6b4a70a8b73c4e83fd2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=95=85=E7=92=83?= Date: Tue, 22 Sep 2026 16:19:16 +0800 Subject: [PATCH 1/2] feat(inference): add Prime mode for text and video --- .../commands/src/commands/shared/prime.ts | 63 +++++++++ packages/commands/src/commands/text/chat.ts | 41 +++++- .../commands/src/commands/video/generate.ts | 53 ++++++-- .../commands/tests/e2e/text-chat.e2e.test.ts | 128 +++++++++++++++++- .../tests/e2e/video-generate-t2v.e2e.test.ts | 101 +++++++++++++- packages/commands/tests/prime.test.ts | 50 +++++++ packages/core/src/client/endpoints.ts | 6 + packages/core/src/client/index.ts | 1 + skills/bailian-cli/reference/text.md | 11 ++ skills/bailian-gen/reference/video.md | 11 ++ 10 files changed, 446 insertions(+), 19 deletions(-) create mode 100644 packages/commands/src/commands/shared/prime.ts create mode 100644 packages/commands/tests/prime.test.ts diff --git a/packages/commands/src/commands/shared/prime.ts b/packages/commands/src/commands/shared/prime.ts new file mode 100644 index 00000000..a5d5c5f7 --- /dev/null +++ b/packages/commands/src/commands/shared/prime.ts @@ -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: "", + 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; + settings: { workspaceId?: string }; + identity: { binName: string }; + client: Pick; + }, + 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 . You can also override the endpoint with --base-url.`, + ); + } + return workspaceMaaSBaseUrl(workspaceId); + }); +} diff --git a/packages/commands/src/commands/text/chat.ts b/packages/commands/src/commands/text/chat.ts index 4a5f5f02..22f139bb 100644 --- a/packages/commands/src/commands/text/chat.ts +++ b/packages/commands/src/commands/text/chat.ts @@ -22,6 +22,7 @@ import { inspectResponsesStreamEvent, extractResponsesText, } from "./responses.ts"; +import { PRIME_FLAGS, resolvePrimeEndpoint, validatePrimeFlags } from "../shared/prime.ts"; const CHAT_FLAGS = { api: { @@ -107,6 +108,7 @@ const CHAT_FLAGS = { "zh-CN": "思考过程最大 Token 数(默认:4096)", }, }, + ...PRIME_FLAGS, } satisfies FlagsDef; type ChatFlags = ParsedFlags; @@ -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 --model glm-5.3-prime --message "Explain this code"', + "zh-CN": '--prime --workspace-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."; } @@ -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 { @@ -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, @@ -336,7 +369,7 @@ export default defineCommand({ } } else if (api === "responses") { const response = await ctx.client.requestJson({ - path: responsesPath(), + path: requestPath, method: "POST", body, }); @@ -350,7 +383,7 @@ export default defineCommand({ } } else { const response = await ctx.client.requestJson({ - path: chatPath(), + path: requestPath, method: "POST", body, }); diff --git a/packages/commands/src/commands/video/generate.ts b/packages/commands/src/commands/video/generate.ts index f3121dbb..1108ca98 100644 --- a/packages/commands/src/commands/video/generate.ts +++ b/packages/commands/src/commands/video/generate.ts @@ -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: { @@ -128,6 +129,7 @@ export default defineCommand({ "参考文件 URL 或本地路径,用于文件生视频(仅 wan3.0-video;与 --image/--last-frame 互斥)", }, }, + ...PRIME_FLAGS, ...ASYNC_FLAG, ...CONCURRENT_FLAG, pollInterval: { @@ -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 --model wan3.0-video-prime --prompt "Ocean waves at sunset"', + "zh-CN": '--prime --workspace-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; @@ -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: { @@ -286,7 +309,10 @@ export default defineCommand({ }, }; } - emitResult({ request: previewBody }, format); + emitResult( + flags.prime ? { endpoint: submitPath, request: previewBody } : { request: previewBody }, + format, + ); return; } @@ -298,7 +324,7 @@ export default defineCommand({ settings, () => ctx.client.requestJson({ - path: isKf2v && !isWan30 ? image2videoPath() : videoGeneratePath(), + path: submitPath, method: "POST", body, async: true, @@ -306,7 +332,7 @@ export default defineCommand({ "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`); @@ -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(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; }, }); }); @@ -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 }); } } diff --git a/packages/commands/tests/e2e/text-chat.e2e.test.ts b/packages/commands/tests/e2e/text-chat.e2e.test.ts index eb46da5d..1fbf95dc 100644 --- a/packages/commands/tests/e2e/text-chat.e2e.test.ts +++ b/packages/commands/tests/e2e/text-chat.e2e.test.ts @@ -1,7 +1,36 @@ -import { describe, expect, test } from "vite-plus/test"; +import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; +import { join } from "node:path"; +import { afterEach, beforeEach, describe, expect, test } from "vite-plus/test"; import { isDashScopeE2EReady, parseStdoutJson, runCommandHelp, runCommandE2e } from "./helpers.ts"; import { TEXT_CHAT_ROUTES } from "./topic-routes.ts"; +let isolatedDirectory: string; + +beforeEach(() => { + isolatedDirectory = mkdtempSync(join(tmpdir(), "bl-text-prime-e2e-")); + writeFileSync(join(isolatedDirectory, "config.json"), "{}"); +}); + +afterEach(() => { + rmSync(isolatedDirectory, { recursive: true, force: true }); +}); + +function runIsolatedTextChat(args: string[], envOverrides: NodeJS.ProcessEnv = {}) { + return runCommandE2e(TEXT_CHAT_ROUTES, args, { + BAILIAN_CONFIG_DIR: isolatedDirectory, + HOME: isolatedDirectory, + USERPROFILE: isolatedDirectory, + ...envOverrides, + }); +} + +const EMPTY_MODEL_ENV = { + DASHSCOPE_API_KEY: "", + DASHSCOPE_BASE_URL: "", + BAILIAN_WORKSPACE_ID: "", +}; + /** * Text chat:help / 分组不依赖密钥;对话需 DashScope。 */ @@ -11,6 +40,8 @@ describe("e2e: text chat", () => { const { stderr, exitCode } = await runCommandHelp(TEXT_CHAT_ROUTES, ["text", "chat", "--help"]); expect(exitCode, stderr).toBe(0); expect(stderr).toMatch(/--api\s+/i); + expect(stderr).toMatch(/--prime/i); + expect(stderr).toMatch(/--workspace-id/i); expect(stderr).toMatch(/chat|--message|model|stream/i); }); @@ -41,6 +72,101 @@ describe("e2e: text chat", () => { expect(exitCode).toBe(2); expect(stderr).toMatch(/thinking-budget.*Responses/i); }); + + test("Prime 模式要求显式 --model", async () => { + const { stderr, exitCode } = await runIsolatedTextChat( + ["text", "chat", "--prime", "--message", "hello"], + EMPTY_MODEL_ENV, + ); + expect(exitCode).toBe(2); + expect(stderr).toMatch(/--prime.*--model/i); + }); + + test("Prime 模式在默认 Base URL 下要求 workspace", async () => { + const { stderr, exitCode } = await runIsolatedTextChat( + ["text", "chat", "--prime", "--model", "glm-5.3-prime", "--message", "hello", "--dry-run"], + EMPTY_MODEL_ENV, + ); + expect(exitCode).toBe(2); + expect(stderr).toMatch(/Workspace ID is required/i); + }); + + test("Prime 模式拒绝 Responses API", async () => { + const { stderr, exitCode } = await runIsolatedTextChat( + [ + "text", + "chat", + "--prime", + "--api", + "responses", + "--model", + "glm-5.3-prime", + "--message", + "hello", + ], + EMPTY_MODEL_ENV, + ); + expect(exitCode).toBe(2); + expect(stderr).toMatch(/--prime.*--api chat/i); + }); + + test("未启用 Prime 时拒绝 --workspace-id", async () => { + const { stderr, exitCode } = await runIsolatedTextChat( + ["text", "chat", "--workspace-id", "ws_test", "--message", "hello"], + EMPTY_MODEL_ENV, + ); + expect(exitCode).toBe(2); + expect(stderr).toMatch(/--workspace-id.*--prime/i); + }); + + test("Prime dry-run 输出 workspace Endpoint 和请求体", async () => { + const { stdout, stderr, exitCode } = await runIsolatedTextChat( + [ + "text", + "chat", + "--prime", + "--workspace-id", + "ws_test", + "--model", + "glm-5.3-prime", + "--message", + "hello", + "--dry-run", + "--output", + "json", + ], + EMPTY_MODEL_ENV, + ); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson<{ endpoint?: string; request?: { model?: string } }>(stdout); + expect(data.endpoint).toBe( + "https://ws_test.cn-beijing.maas.aliyuncs.com/compatible-mode/v1/chat/completions", + ); + expect(data.request?.model).toBe("glm-5.3-prime"); + }); + + test("Prime dry-run 允许自定义 Base URL 覆盖 workspace Endpoint", async () => { + const { stdout, stderr, exitCode } = await runIsolatedTextChat( + [ + "text", + "chat", + "--prime", + "--model", + "glm-5.3-prime", + "--message", + "hello", + "--base-url", + "https://example.test", + "--dry-run", + "--output", + "json", + ], + EMPTY_MODEL_ENV, + ); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson<{ endpoint?: string }>(stdout); + expect(data.endpoint).toBe("https://example.test/compatible-mode/v1/chat/completions"); + }); }); describe.skipIf(!isDashScopeE2EReady())("e2e: text chat(DashScope)", () => { diff --git a/packages/commands/tests/e2e/video-generate-t2v.e2e.test.ts b/packages/commands/tests/e2e/video-generate-t2v.e2e.test.ts index c77a27d1..92aad127 100644 --- a/packages/commands/tests/e2e/video-generate-t2v.e2e.test.ts +++ b/packages/commands/tests/e2e/video-generate-t2v.e2e.test.ts @@ -1,5 +1,7 @@ +import { mkdtempSync, rmSync, writeFileSync } from "node:fs"; +import { tmpdir } from "node:os"; import { join } from "node:path"; -import { describe, expect, test } from "vite-plus/test"; +import { afterEach, beforeEach, describe, expect, test } from "vite-plus/test"; import { cliTimeoutPrefix, e2eLabelFromMetaUrl, @@ -12,6 +14,32 @@ import { } from "./helpers.ts"; import { VIDEO_ROUTES } from "./topic-routes.ts"; +let isolatedDirectory: string; + +beforeEach(() => { + isolatedDirectory = mkdtempSync(join(tmpdir(), "bl-video-prime-e2e-")); + writeFileSync(join(isolatedDirectory, "config.json"), "{}"); +}); + +afterEach(() => { + rmSync(isolatedDirectory, { recursive: true, force: true }); +}); + +function runIsolatedVideoGenerate(args: string[], envOverrides: NodeJS.ProcessEnv = {}) { + return runCommandE2e(VIDEO_ROUTES, args, { + BAILIAN_CONFIG_DIR: isolatedDirectory, + HOME: isolatedDirectory, + USERPROFILE: isolatedDirectory, + ...envOverrides, + }); +} + +const EMPTY_MODEL_ENV = { + DASHSCOPE_API_KEY: "", + DASHSCOPE_BASE_URL: "", + BAILIAN_WORKSPACE_ID: "", +}; + /** * Video generate (t2v):help / 分组不依赖密钥;长任务需视频 E2E + DashScope。 */ @@ -24,8 +52,79 @@ describe("e2e: video generate (t2v)", () => { "--help", ]); expect(exitCode, stderr).toBe(0); + expect(stderr).toMatch(/--prime/i); + expect(stderr).toMatch(/--workspace-id/i); expect(stderr).toMatch(/generate|--prompt|--model|download|image/i); }); + + test("Prime 模式要求显式 --model", async () => { + const { stderr, exitCode } = await runIsolatedVideoGenerate( + ["video", "generate", "--prime", "--prompt", "hello"], + EMPTY_MODEL_ENV, + ); + expect(exitCode).toBe(2); + expect(stderr).toMatch(/--prime.*--model/i); + }); + + test("未启用 Prime 时拒绝 --workspace-id", async () => { + const { stderr, exitCode } = await runIsolatedVideoGenerate( + ["video", "generate", "--workspace-id", "ws_test", "--prompt", "hello"], + EMPTY_MODEL_ENV, + ); + expect(exitCode).toBe(2); + expect(stderr).toMatch(/--workspace-id.*--prime/i); + }); + + test("Prime dry-run 输出 workspace Endpoint 和请求体", async () => { + const { stdout, stderr, exitCode } = await runIsolatedVideoGenerate( + [ + "video", + "generate", + "--prime", + "--workspace-id", + "ws_test", + "--model", + "wan3.0-video-prime", + "--prompt", + "hello", + "--dry-run", + "--output", + "json", + ], + EMPTY_MODEL_ENV, + ); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson<{ endpoint?: string; request?: { model?: string } }>(stdout); + expect(data.endpoint).toBe( + "https://ws_test.cn-beijing.maas.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis", + ); + expect(data.request?.model).toBe("wan3.0-video-prime"); + }); + + test("Prime dry-run 允许自定义 Base URL 覆盖 workspace Endpoint", async () => { + const { stdout, stderr, exitCode } = await runIsolatedVideoGenerate( + [ + "video", + "generate", + "--prime", + "--model", + "wan3.0-video-prime", + "--prompt", + "hello", + "--base-url", + "https://example.test", + "--dry-run", + "--output", + "json", + ], + EMPTY_MODEL_ENV, + ); + expect(exitCode, stderr).toBe(0); + const data = parseStdoutJson<{ endpoint?: string }>(stdout); + expect(data.endpoint).toBe( + "https://example.test/api/v1/services/aigc/video-generation/video-synthesis", + ); + }); }); describe.skipIf(!isBailianE2EVideoEnabled() || !isDashScopeE2EReady())( diff --git a/packages/commands/tests/prime.test.ts b/packages/commands/tests/prime.test.ts new file mode 100644 index 00000000..e17725b2 --- /dev/null +++ b/packages/commands/tests/prime.test.ts @@ -0,0 +1,50 @@ +import { describe, expect, test } from "vite-plus/test"; +import { resolvePrimeEndpoint, validatePrimeFlags } from "../src/commands/shared/prime.ts"; + +function createUrlResolver(baseUrl: string, usesDefaultBaseUrl: boolean) { + return { + url(path: string, defaultBaseUrl?: () => string): string { + const resolvedBaseUrl = usesDefaultBaseUrl && defaultBaseUrl ? defaultBaseUrl() : baseUrl; + return resolvedBaseUrl + path; + }, + }; +} + +describe("Prime command helpers", () => { + test("要求显式 model,且 workspace flag 只能与 Prime 一起使用", () => { + expect(validatePrimeFlags({ prime: true })).toMatch(/--model/); + expect(validatePrimeFlags({ prime: false, workspaceId: "ws_test" })).toMatch(/--prime/); + expect(validatePrimeFlags({ prime: true, model: "prime-model" })).toBeUndefined(); + }); + + test("默认 Base URL 下让提交与轮询共用 workspace host", () => { + const ctx = { + flags: { workspaceId: "ws_test" }, + settings: {}, + identity: { binName: "bl" }, + client: createUrlResolver("https://dashscope.aliyuncs.com", true), + }; + + expect( + resolvePrimeEndpoint(ctx, "/api/v1/services/aigc/video-generation/video-synthesis"), + ).toBe( + "https://ws_test.cn-beijing.maas.aliyuncs.com/api/v1/services/aigc/video-generation/video-synthesis", + ); + expect(resolvePrimeEndpoint(ctx, "/api/v1/tasks/task_test")).toBe( + "https://ws_test.cn-beijing.maas.aliyuncs.com/api/v1/tasks/task_test", + ); + }); + + test("显式 Base URL 优先,且不要求 workspace", () => { + const ctx = { + flags: {}, + settings: {}, + identity: { binName: "bl" }, + client: createUrlResolver("https://example.test", false), + }; + + expect(resolvePrimeEndpoint(ctx, "/compatible-mode/v1/chat/completions")).toBe( + "https://example.test/compatible-mode/v1/chat/completions", + ); + }); +}); diff --git a/packages/core/src/client/endpoints.ts b/packages/core/src/client/endpoints.ts index d7f98cc8..ce8c1bb4 100644 --- a/packages/core/src/client/endpoints.ts +++ b/packages/core/src/client/endpoints.ts @@ -108,6 +108,12 @@ export function knowledgeRetrievePath(): string { return "/api/v1/indices/rag/index/retrieve"; } +// ---- Workspace-scoped MaaS endpoints (cn-beijing only) ---- + +export function workspaceMaaSBaseUrl(workspaceId: string): string { + return `https://${workspaceId}.cn-beijing.maas.aliyuncs.com`; +} + // ---- Knowledge Search (新版 RAG 检索, workspace-based host) ---- export function knowledgeSearchEndpoint(workspaceId: string): string { diff --git a/packages/core/src/client/index.ts b/packages/core/src/client/index.ts index ebb9ab77..c1063462 100644 --- a/packages/core/src/client/index.ts +++ b/packages/core/src/client/index.ts @@ -38,6 +38,7 @@ export { userProfilePath, videoGeneratePath, image2videoPath, + workspaceMaaSBaseUrl, } from "./endpoints.ts"; export { isLegacyImage2ImageModel, diff --git a/skills/bailian-cli/reference/text.md b/skills/bailian-cli/reference/text.md index 6b5f949a..12cdbb7f 100644 --- a/skills/bailian-cli/reference/text.md +++ b/skills/bailian-cli/reference/text.md @@ -38,9 +38,16 @@ Index: [index.md](index.md) | `--tool ` | array | no | Tool definition as JSON or file path (repeatable) | | `--enable-thinking` | switch | no | Enable thinking/reasoning mode (for qwen3/qwq models) | | `--thinking-budget ` | number | no | Max tokens for thinking (default: 4096) | +| `--prime` | switch | no | Use Prime mode with a workspace-scoped endpoint | +| `--workspace-id ` | string | no | Workspace ID for the default Prime endpoint (or set BAILIAN_WORKSPACE_ID) | | `--api-key ` | string | no | API key | | `--base-url ` | string | no | API base URL | +#### Notes + +- Prime mode requires an explicit model and currently supports only the Chat Completions API. +- 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. + #### Examples ```bash @@ -70,3 +77,7 @@ bl text chat --message "Hello" --output json ```bash bl text chat --model qwq-plus --message "Solve 1+1" --enable-thinking ``` + +```bash +bl text chat --prime --workspace-id --model glm-5.3-prime --message "Explain this code" +``` diff --git a/skills/bailian-gen/reference/video.md b/skills/bailian-gen/reference/video.md index 2f5d90ef..f665c23d 100644 --- a/skills/bailian-gen/reference/video.md +++ b/skills/bailian-gen/reference/video.md @@ -121,12 +121,19 @@ bl video edit --video https://example.com/input.mp4 --prompt "Put clothes on the | `--seed ` | number | no | Random seed for reproducible generation | | `--download ` | string | no | Save video to file on completion | | `--file ` | string | no | Reference file URL or local path for file-to-video (wan3.0-video only; mutually exclusive with --image/--last-frame) | +| `--prime` | switch | no | Use Prime mode with a workspace-scoped endpoint | +| `--workspace-id ` | string | no | Workspace ID for the default Prime endpoint (or set BAILIAN_WORKSPACE_ID) | | `--async` | switch | no | Return async task id without waiting | | `--concurrent ` | number | no | Run N parallel requests (default: 1) | | `--poll-interval ` | number | no | Polling interval when waiting (default: 5) | | `--api-key ` | string | no | API key | | `--base-url ` | string | no | API base URL | +#### Notes + +- Prime mode requires an explicit model. +- 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. + #### Examples ```bash @@ -149,6 +156,10 @@ bl video generate --prompt "Mountain landscape" --resolution 720P --duration 5 bl video generate --prompt "A cat playing with a ball" --watermark false ``` +```bash +bl video generate --prime --workspace-id --model wan3.0-video-prime --prompt "Ocean waves at sunset" +``` + ### `bl video ref` | Field | Value | From 960906f6400a09a1a32e1cb2b0021139c16e38c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=95=85=E7=92=83?= Date: Tue, 22 Sep 2026 16:39:28 +0800 Subject: [PATCH 2/2] fix(release): sync package READMEs --- packages/cli/README.md | 19 ++++++++++--------- packages/cli/README.zh.md | 19 ++++++++++--------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/packages/cli/README.md b/packages/cli/README.md index b951ab9b..492cafd6 100644 --- a/packages/cli/README.md +++ b/packages/cli/README.md @@ -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&) diff --git a/packages/cli/README.zh.md b/packages/cli/README.zh.md index 93605443..27cb0cfe 100644 --- a/packages/cli/README.zh.md +++ b/packages/cli/README.zh.md @@ -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&)