Skip to content

Commit fab5527

Browse files
committed
fix: migrate delete commands to runtime risk confirmation
- Remove self-declared yes flags from dataset/finetune/deploy delete: the runtime injects --yes for commands declaring risk, and the duplicate declaration broke registry startup (redeclares reserved flag) - Migrate alert delete / template delete to the risk mechanism so the confirmation gate is runtime-owned again - e2e: drop stale USAGE(2) confirmation tests superseded by exit-7 coverage; align dataset assertions with current behavior (2GB media upload cap, video schema supported)
1 parent 427f9b5 commit fab5527

10 files changed

Lines changed: 56 additions & 70 deletions

File tree

packages/commands/src/commands/alert/delete.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,13 @@ export default defineCommand({
1111
"zh-CN": "删除模型告警规则",
1212
},
1313
auth: "console",
14+
risk: {
15+
level: "high",
16+
message: {
17+
"en-US": "This permanently deletes the specified alert rules and cannot be undone.",
18+
"zh-CN": "该操作会永久删除指定的告警规则,且无法撤销。",
19+
},
20+
},
1421
usageArgs: "--rule-id <id>[,<id>...] [--yes]",
1522
flags: {
1623
ruleId: {
@@ -22,10 +29,6 @@ export default defineCommand({
2229
"zh-CN": "要删除的规则 ID,多个以逗号分隔",
2330
},
2431
},
25-
yes: {
26-
type: "switch",
27-
description: { "en-US": "Skip the confirmation prompt", "zh-CN": "跳过确认提示" },
28-
},
2932
},
3033
exampleArgs: ["--rule-id 789", "--rule-id 789,790 --dry-run", "--rule-id 789 --yes"],
3134
notes: [

packages/commands/src/commands/alert/template-delete.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,13 @@ export default defineCommand({
1616
"zh-CN": "删除自定义告警模板(官方模板不可删除)",
1717
},
1818
auth: "console",
19+
risk: {
20+
level: "high",
21+
message: {
22+
"en-US": "This permanently deletes the specified alert templates and cannot be undone.",
23+
"zh-CN": "该操作会永久删除指定的告警模板,且无法撤销。",
24+
},
25+
},
1926
usageArgs: "--template-id <id>[,<id>...] [--yes]",
2027
flags: {
2128
templateId: {
@@ -27,10 +34,6 @@ export default defineCommand({
2734
"zh-CN": "要删除的模板 ID,多个以逗号分隔",
2835
},
2936
},
30-
yes: {
31-
type: "switch",
32-
description: { "en-US": "Skip the confirmation prompt", "zh-CN": "跳过确认提示" },
33-
},
3437
},
3538
exampleArgs: ["--template-id 123", "--template-id 123,124 --dry-run", "--template-id 123 --yes"],
3639
notes: [

packages/commands/src/commands/dataset/delete.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ const DELETE_FLAGS = {
88
description: { "en-US": "Dataset file ID (required)", "zh-CN": "数据集文件 ID(必填)" },
99
required: true,
1010
},
11-
yes: {
12-
type: "switch",
13-
description: { "en-US": "Skip the confirmation prompt", "zh-CN": "跳过确认提示" },
14-
},
1511
} satisfies FlagsDef;
1612

1713
export default defineCommand({

packages/commands/src/commands/deploy/delete.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,6 @@ const DELETE_FLAGS = {
2525
"zh-CN": "跳过本地 STOPPED/FAILED 状态预检查",
2626
},
2727
},
28-
yes: {
29-
type: "switch",
30-
description: { "en-US": "Skip the confirmation prompt", "zh-CN": "跳过确认提示" },
31-
},
3228
} satisfies FlagsDef;
3329

3430
/**

packages/commands/src/commands/finetune/delete.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,6 @@ const DELETE_FLAGS = {
88
description: { "en-US": "Fine-tune job ID (required)", "zh-CN": "微调任务 ID(必填)" },
99
required: true,
1010
},
11-
yes: {
12-
type: "switch",
13-
description: { "en-US": "Skip the confirmation prompt", "zh-CN": "跳过确认提示" },
14-
},
1511
} satisfies FlagsDef;
1612

1713
export default defineCommand({

packages/commands/tests/e2e/alert.e2e.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,15 +170,15 @@ describe("e2e: alert", () => {
170170
expect(stderr).toMatch(/--yes/i);
171171
});
172172

173-
test("alert delete 非 TTY 无 --yes 报 USAGE (2)", async () => {
173+
test("alert delete 非 TTY 无 --yes 返回确认请求 (7)", async () => {
174174
// 确认门先于 console 凭证解析与任何网络请求触发
175175
const { stderr, exitCode } = await runCommandE2e(ALERT_ROUTES, [
176176
"alert",
177177
"delete",
178178
"--rule-id",
179179
"789",
180180
]);
181-
expect(exitCode).toBe(2);
181+
expect(exitCode).toBe(7);
182182
expect(stderr).toMatch(/--yes/);
183183
});
184184

@@ -349,15 +349,15 @@ describe("e2e: alert", () => {
349349
expect(stderr).toMatch(/--yes/i);
350350
});
351351

352-
test("alert template delete 非 TTY 无 --yes 报 USAGE (2)", async () => {
352+
test("alert template delete 非 TTY 无 --yes 返回确认请求 (7)", async () => {
353353
const { stderr, exitCode } = await runCommandE2e(ALERT_ROUTES, [
354354
"alert",
355355
"template",
356356
"delete",
357357
"--template-id",
358358
"123",
359359
]);
360-
expect(exitCode).toBe(2);
360+
expect(exitCode).toBe(7);
361361
expect(stderr).toMatch(/--yes/);
362362
});
363363

packages/commands/tests/e2e/dataset.e2e.test.ts

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,8 @@ describe.skipIf(!isDashScopeE2EReady())("e2e: dataset (offline)", () => {
216216
expect(data.schema).toBe("dpo");
217217
});
218218

219-
test("dataset upload --schema image --no-validate --dry-run 采用 1GB 媒体上限", async () => {
220-
// image schema raises the upload cap to 1 GiB (vs 300 MB for text).
219+
test("dataset upload --schema image --no-validate --dry-run 采用 2GB 媒体上限", async () => {
220+
// image schema raises the upload cap to 2 GiB (vs 300 MB for text).
221221
// --no-validate keeps this offline (the jsonl fixture is not a real zip).
222222
const file = join(e2eFixturesDir, ".dataset-valid.jsonl");
223223
const { stdout, stderr, exitCode } = await runCommandE2e(DATASET_ROUTES, [
@@ -236,7 +236,7 @@ describe.skipIf(!isDashScopeE2EReady())("e2e: dataset (offline)", () => {
236236
const data = parseStdoutJson<{ action: string; schema: string; max_bytes: number }>(stdout);
237237
expect(data.action).toBe("dataset.upload");
238238
expect(data.schema).toBe("image");
239-
expect(data.max_bytes).toBe(1024 * 1024 * 1024);
239+
expect(data.max_bytes).toBe(2 * 1024 * 1024 * 1024);
240240
});
241241

242242
test.each(["tts", "image"])("dataset upload --dry-run 接受媒体 schema %s", async (schema) => {
@@ -259,7 +259,9 @@ describe.skipIf(!isDashScopeE2EReady())("e2e: dataset (offline)", () => {
259259
expect(data.schema).toBe(schema);
260260
});
261261

262-
test("dataset validate --schema video 拒绝(视频生成入口已隐藏)", async () => {
262+
test("dataset validate --schema video 接受视频 schema(按记录结构校验)", async () => {
263+
// video schema is supported; the chatml fixture fails on record shape
264+
// (missing first_frame_path), not on schema acceptance.
263265
const file = join(e2eFixturesDir, ".dataset-valid.jsonl");
264266
const { stdout, stderr, exitCode } = await runCommandE2e(DATASET_ROUTES, [
265267
"dataset",
@@ -272,10 +274,11 @@ describe.skipIf(!isDashScopeE2EReady())("e2e: dataset (offline)", () => {
272274
"json",
273275
]);
274276
expect(exitCode, stdout + stderr).not.toBe(0);
275-
expect(`${stdout}\n${stderr}`).toMatch(/--schema video is not supported/);
277+
expect(`${stdout}\n${stderr}`).not.toMatch(/is not supported/);
278+
expect(`${stdout}\n${stderr}`).toMatch(/first_frame_path/);
276279
});
277280

278-
test("dataset upload --schema video 拒绝(视频生成入口已隐藏)", async () => {
281+
test("dataset upload --schema video --no-validate --dry-run 采用 2GB 媒体上限", async () => {
279282
const file = join(e2eFixturesDir, ".dataset-valid.jsonl");
280283
const { stdout, stderr, exitCode } = await runCommandE2e(DATASET_ROUTES, [
281284
"dataset",
@@ -289,8 +292,11 @@ describe.skipIf(!isDashScopeE2EReady())("e2e: dataset (offline)", () => {
289292
"--output",
290293
"json",
291294
]);
292-
expect(exitCode, stdout + stderr).not.toBe(0);
293-
expect(`${stdout}\n${stderr}`).toMatch(/--schema video is not supported/);
295+
expect(exitCode, stdout + stderr).toBe(0);
296+
const data = parseStdoutJson<{ action: string; schema: string; max_bytes: number }>(stdout);
297+
expect(data.action).toBe("dataset.upload");
298+
expect(data.schema).toBe("video");
299+
expect(data.max_bytes).toBe(2 * 1024 * 1024 * 1024);
294300
});
295301

296302
test("dataset delete --dry-run 发出结构化动作", async () => {

packages/commands/tests/e2e/deploy.e2e.test.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -207,19 +207,6 @@ describe.skipIf(!isDashScopeE2EReady())("e2e: deploy (offline)", () => {
207207
expect(exitCode, stderr).toBe(0);
208208
expect(stderr).toMatch(/--yes/i);
209209
});
210-
211-
test("deploy delete 非 TTY 无 --yes 报 USAGE (2)", async () => {
212-
// --skip-precheck 保证确认门在发任何网络请求前触发
213-
const { stderr, exitCode } = await runCommandE2e(DEPLOY_ROUTES, [
214-
"deploy",
215-
"delete",
216-
"--deployed-model",
217-
"dep-xxx",
218-
"--skip-precheck",
219-
]);
220-
expect(exitCode).toBe(2);
221-
expect(stderr).toMatch(/--yes/);
222-
});
223210
});
224211

225212
describe("e2e: deploy high-risk confirmation", () => {

packages/commands/tests/e2e/finetune.e2e.test.ts

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -304,17 +304,6 @@ describe.skipIf(!isDashScopeE2EReady())("e2e: finetune (offline)", () => {
304304
expect(stderr).toMatch(/--yes/i);
305305
});
306306

307-
test("finetune delete 非 TTY 无 --yes 报 USAGE (2)", async () => {
308-
const { stderr, exitCode } = await runCommandE2e(FINETUNE_ROUTES, [
309-
"finetune",
310-
"delete",
311-
"--job-id",
312-
"ft-xxx",
313-
]);
314-
expect(exitCode).toBe(2);
315-
expect(stderr).toMatch(/--yes/);
316-
});
317-
318307
test("finetune create --dry-run 解析多 datasets 中的空白", async () => {
319308
const { stdout, stderr, exitCode } = await runCommandE2e(FINETUNE_ROUTES, [
320309
"finetune",

skills/bailian-cli/reference/alert.md

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -79,19 +79,23 @@ bl alert create --name test --template-id 123 --model qwen3.6-plus --dry-run
7979

8080
### `bl alert delete`
8181

82-
| Field | Value |
83-
| ------------------ | -------------------------------------------------- |
84-
| **Name** | `alert delete` |
85-
| **Description** | Delete model alert rules |
86-
| **Authentication** | Console |
87-
| **Usage** | `bl alert delete --rule-id <id>[,<id>...] [--yes]` |
82+
| Field | Value |
83+
| ------------------ | ------------------------------------------------------------------------ |
84+
| **Name** | `alert delete` |
85+
| **Description** | Delete model alert rules |
86+
| **Authentication** | Console |
87+
| **Usage** | `bl alert delete --rule-id <id>[,<id>...] [--yes]` |
88+
| **Risk** | `high` |
89+
| **Risk message** | This permanently deletes the specified alert rules and cannot be undone. |
90+
91+
> **Agent safety:** Never add `--yes` automatically. On `type="requires_confirmation"`, stop and ask for explicit user confirmation of the same action and scope.
8892
8993
#### Flags
9094

9195
| Flag | Type | Required | Description |
9296
| ------------------------------ | ------ | -------- | -------------------------------------------------------- |
9397
| `--rule-id <id>[,<id>...]` | string | yes | Rule ID(s) to delete, comma-separated |
94-
| `--yes` | switch | no | Skip the confirmation prompt |
98+
| `--yes` | switch | no | Confirm this high-risk operation |
9599
| `--console-region <region>` | string | no | Console gateway region (e.g. cn-beijing, ap-southeast-1) |
96100
| `--console-site <site>` | string | no | Console site: domestic, international |
97101
| `--console-switch-agent <uid>` | number | no | Switch agent UID for delegated access |
@@ -112,6 +116,7 @@ bl alert delete --rule-id 789,790 --dry-run
112116
```
113117

114118
```bash
119+
# Only after explicit user confirmation:
115120
bl alert delete --rule-id 789 --yes
116121
```
117122

@@ -331,19 +336,23 @@ bl alert template create --name test --condition 'model_call_count:sum:>:100:60'
331336

332337
### `bl alert template delete`
333338

334-
| Field | Value |
335-
| ------------------ | -------------------------------------------------------------------- |
336-
| **Name** | `alert template delete` |
337-
| **Description** | Delete custom alert templates (official templates cannot be deleted) |
338-
| **Authentication** | Console |
339-
| **Usage** | `bl alert template delete --template-id <id>[,<id>...] [--yes]` |
339+
| Field | Value |
340+
| ------------------ | ---------------------------------------------------------------------------- |
341+
| **Name** | `alert template delete` |
342+
| **Description** | Delete custom alert templates (official templates cannot be deleted) |
343+
| **Authentication** | Console |
344+
| **Usage** | `bl alert template delete --template-id <id>[,<id>...] [--yes]` |
345+
| **Risk** | `high` |
346+
| **Risk message** | This permanently deletes the specified alert templates and cannot be undone. |
347+
348+
> **Agent safety:** Never add `--yes` automatically. On `type="requires_confirmation"`, stop and ask for explicit user confirmation of the same action and scope.
340349
341350
#### Flags
342351

343352
| Flag | Type | Required | Description |
344353
| ------------------------------ | ------ | -------- | -------------------------------------------------------- |
345354
| `--template-id <id>[,<id>...]` | string | yes | Template ID(s) to delete, comma-separated |
346-
| `--yes` | switch | no | Skip the confirmation prompt |
355+
| `--yes` | switch | no | Confirm this high-risk operation |
347356
| `--console-region <region>` | string | no | Console gateway region (e.g. cn-beijing, ap-southeast-1) |
348357
| `--console-site <site>` | string | no | Console site: domestic, international |
349358
| `--console-switch-agent <uid>` | number | no | Switch agent UID for delegated access |
@@ -364,6 +373,7 @@ bl alert template delete --template-id 123,124 --dry-run
364373
```
365374

366375
```bash
376+
# Only after explicit user confirmation:
367377
bl alert template delete --template-id 123 --yes
368378
```
369379

0 commit comments

Comments
 (0)