mirror of
https://github.com/modelstudioai/cli.git
synced 2026-09-14 19:49:23 +08:00
feat(cli): expose high-risk confirmation guidance in help and skills
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import type {
|
||||
AnyCommand,
|
||||
AuthRequirement,
|
||||
CommandRiskLevel,
|
||||
FlagDef,
|
||||
FlagsDef,
|
||||
LocalizedText,
|
||||
@@ -41,10 +42,16 @@ const AUTH_LABELS = {
|
||||
none: { "en-US": "No Auth", "zh-CN": "无需鉴权" },
|
||||
} satisfies Record<AuthRequirement, LocalizedText>;
|
||||
|
||||
const RISK_LEVEL_LABELS = {
|
||||
high: { "en-US": "high", "zh-CN": "高风险" },
|
||||
} satisfies Record<CommandRiskLevel, LocalizedText>;
|
||||
|
||||
const HELP_TEXT = {
|
||||
usage: { "en-US": "Usage:", "zh-CN": "用法:" },
|
||||
commands: { "en-US": "Commands:", "zh-CN": "命令:" },
|
||||
authentication: { "en-US": "Authentication:", "zh-CN": "鉴权方式:" },
|
||||
risk: { "en-US": "Risk:", "zh-CN": "风险等级:" },
|
||||
riskMessage: { "en-US": "Risk message:", "zh-CN": "风险说明:" },
|
||||
flags: { "en-US": "Flags:", "zh-CN": "选项:" },
|
||||
globalFlags: { "en-US": "Global Flags:", "zh-CN": "全局选项:" },
|
||||
modelAuthFlags: { "en-US": "Model Auth Flags:", "zh-CN": "模型鉴权选项:" },
|
||||
@@ -64,6 +71,10 @@ const HELP_TEXT = {
|
||||
},
|
||||
notes: { "en-US": "Notes:", "zh-CN": "说明:" },
|
||||
examples: { "en-US": "Examples:", "zh-CN": "示例:" },
|
||||
confirmedExample: {
|
||||
"en-US": "# Only after explicit confirmation:",
|
||||
"zh-CN": "# 仅在明确确认后执行:",
|
||||
},
|
||||
minimalWorkflow: { "en-US": "Minimal workflow.yaml:", "zh-CN": "最小 workflow.yaml:" },
|
||||
tryIt: { "en-US": "Try it:", "zh-CN": "试一试:" },
|
||||
} satisfies Record<string, LocalizedText>;
|
||||
@@ -432,6 +443,12 @@ ${authFlagSections ? `${authFlagSections}\n\n` : ""}${b(this.localize(HELP_TEXT.
|
||||
out.write(
|
||||
`${b(this.localize(HELP_TEXT.authentication))} ${a(this.localize(AUTH_LABELS[cmd.auth]))}\n`,
|
||||
);
|
||||
if (cmd.risk !== undefined) {
|
||||
out.write(
|
||||
`${b(this.localize(HELP_TEXT.risk))} ${a(this.localize(RISK_LEVEL_LABELS[cmd.risk.level]))}\n`,
|
||||
);
|
||||
out.write(`${b(this.localize(HELP_TEXT.riskMessage))} ${this.localize(cmd.risk.message)}\n`);
|
||||
}
|
||||
const flagEntries = [
|
||||
...Object.entries(cmd.flags ?? {}),
|
||||
...Object.entries(confirmationFlagDefs(cmd)),
|
||||
@@ -460,6 +477,9 @@ ${authFlagSections ? `${authFlagSections}\n\n` : ""}${b(this.localize(HELP_TEXT.
|
||||
out.write(`\n${b(this.localize(HELP_TEXT.examples))}\n`);
|
||||
for (const example of cmd.exampleArgs) {
|
||||
const localizedExample = this.localize(example);
|
||||
if (cmd.risk !== undefined && /(?:^|\s)--yes(?:\s|$)/.test(localizedExample)) {
|
||||
out.write(` ${d(this.localize(HELP_TEXT.confirmedExample))}\n`);
|
||||
}
|
||||
const line = localizedExample.startsWith("#")
|
||||
? localizedExample
|
||||
: localizedExample
|
||||
|
||||
@@ -47,6 +47,13 @@ test("registry renders runtime help copy with the selected language", async () =
|
||||
},
|
||||
],
|
||||
auth: "none",
|
||||
risk: {
|
||||
level: "high",
|
||||
message: {
|
||||
"en-US": "This operation is permanent.",
|
||||
"zh-CN": "该操作无法撤销。",
|
||||
},
|
||||
},
|
||||
run: async () => {},
|
||||
});
|
||||
const registry = new CommandRegistry({ test: command }, "bl", translator);
|
||||
@@ -69,6 +76,8 @@ test("registry renders runtime help copy with the selected language", async () =
|
||||
|
||||
output = "";
|
||||
registry.printHelp(["test"], stream);
|
||||
expect(output).toContain("风险等级: 高风险");
|
||||
expect(output).toContain("风险说明: 该操作无法撤销。");
|
||||
expect(output).toContain("测试说明");
|
||||
expect(output).toContain('bl test --message "你好"');
|
||||
expect(output).toContain(" # 流式输出响应");
|
||||
|
||||
@@ -53,11 +53,12 @@ test("high risk 命令不能自行声明 runtime 保留的 yes", () => {
|
||||
expect(() => new CommandRegistry({ "x normal": normal }, "bl")).not.toThrow();
|
||||
});
|
||||
|
||||
test("命令 help 只为 high risk 展示 runtime 注入的 --yes", () => {
|
||||
test("命令 help 只为 high risk 展示风险信息和 runtime 注入的 --yes", () => {
|
||||
const high = defineCommand({
|
||||
description: "danger",
|
||||
auth: "none",
|
||||
risk: { level: "high", message: "dangerous operation" },
|
||||
exampleArgs: ["--dry-run", "--yes"],
|
||||
run: noopRun,
|
||||
});
|
||||
const normal = defineCommand({
|
||||
@@ -77,5 +78,10 @@ test("命令 help 只为 high risk 展示 runtime 注入的 --yes", () => {
|
||||
} as unknown as NodeJS.WriteStream);
|
||||
|
||||
expect(highHelp).toContain("--yes");
|
||||
expect(highHelp).toContain("Risk: high");
|
||||
expect(highHelp).toContain("Risk message: dangerous operation");
|
||||
expect(highHelp).toMatch(/# Only after explicit confirmation:\n\s+bl asset delete --yes/);
|
||||
expect(normalHelp).not.toContain("--yes");
|
||||
expect(normalHelp).not.toContain("Risk:");
|
||||
expect(normalHelp).not.toContain("Risk message:");
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user