Skip to content

Commit 4dd0d68

Browse files
authored
Merge pull request #210 from modelstudioai/feat/telemetry-command
Feat/telemetry command
2 parents 0f4ed5a + fab5527 commit 4dd0d68

67 files changed

Lines changed: 9146 additions & 271 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ Once installed, just describe your task to your AI Agent — no need to assemble
117117
| Image & video generation | "Generate an image of a cat in a spacesuit on Mars, then turn it into a video." |
118118
| Speech recognition | "Transcribe this audio; if proper nouns are wrong, add hot words and try again." |
119119
| Usage & quota | "Show my recent model usage, free-tier quota, and rate limits." |
120+
| Monitoring & alerts | "Show my model call stats, failures and logs, and create an alert rule." |
120121
| Model selection | "Recommend a model for image understanding and customer support." |
121122
| About Bailian CLI | "Tell me what Bailian CLI can do for me, and suggest how to use it for my needs." |
122123

README.zh.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ irm https://bailian.aliyun.com/cli/install.ps1 | iex
116116
| 图片和视频生成 | “生成一张穿着太空服的猫站在火星上的图片,再把它制作成一段视频。” |
117117
| 语音识别 | “把这段音频转写成文字,专有名词识别不准的话帮我加上热词再试。” |
118118
| 用量与额度 | “查看最近的模型用量、免费额度和限流情况。” |
119+
| 监控与告警 | “查看我的模型调用统计、失败明细和调用日志,并创建一条告警规则。” |
119120
| 模型选型 | “推荐一个适合图片理解和智能客服的模型。” |
120121
| 了解 Bailian CLI | “介绍一下 Bailian CLI 能帮我完成哪些任务,并根据我的需求推荐使用方式。” |
121122

docs/agents/command-add-remove.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ packages/commands/src/index.ts
7777
- `commands/auth/**` 可用 `ctx.authStore`,`commands/config/**` 可用 `ctx.configStore`;不要把这些持久化能力扩散到普通业务命令
7878
- `commands/plugin/**` 可用 `ctx.commandPacks`;产品 policy 由 runtime 绑定,命令不要自行 import 产品入口
7979
- [ ] 用户可见 Help 文案在命令文件中就近提供 `en-US` / `zh-CN`:命令 `description`、flag `description``notes` 和包含自然语言的 `exampleArgs`;纯命令语法示例可保留为字符串,服务端错误不翻译
80+
- [ ] 如果命令执行不可逆的删除/销毁(远端资源删除、永久移除),必须提供 `yes` switch flag,并在 `run` 中于 `dry-run` 分支之后、任何网络调用之前调用 runtime 的 `confirmDangerousAction(summary, flags.yes ?? false)`(参考 `knowledge/*-delete.ts`);`--yes` 的 flag description 用「Skip the confirmation prompt / 跳过确认提示」,`notes` 里声明不可撤销
8081
- [ ] `packages/commands/src/index.ts`:新增或移除对应 export
8182
- [ ] 如果命令调用 Console Gateway,设置 `auth: "console"`;不要重复声明 console 凭证域 flags
8283
- [ ] 如果命令不需要网络或自己管理配置/登录,设置 `auth: "none"`;不要绕过 runtime auth stage

packages/cli/src/commands.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,47 @@ import {
8787
pipelineValidate,
8888
advisorRecommend,
8989
modelList,
90+
modelSearch,
91+
modelCode,
9092
workspaceList,
9193
quotaList,
9294
quotaUpdate,
9395
quotaDelete,
9496
quotaHistory,
9597
quotaCheck,
98+
monitorOverview,
99+
monitorModels,
100+
monitorMetrics,
101+
monitorErrors,
102+
monitorDeliveryStatus,
103+
monitorDeliveryEnable,
104+
monitorDeliveryDisable,
105+
logStatus,
106+
logAuditList,
107+
logAuditGet,
108+
logAuditCount,
109+
logAuditEnable,
110+
logAuditDisable,
111+
logInferenceList,
112+
logInferenceGet,
113+
logInferenceCount,
114+
logInferenceEnable,
115+
logInferenceDisable,
116+
logTraceList,
117+
logTraceGet,
118+
logTraceStats,
119+
alertMetrics,
120+
alertTemplateList,
121+
alertTemplateCreate,
122+
alertTemplateUpdate,
123+
alertTemplateDelete,
124+
alertList,
125+
alertCreate,
126+
alertUpdate,
127+
alertDelete,
128+
alertEnable,
129+
alertDisable,
130+
alertHistory,
96131
permissionList,
97132
permissionGrant,
98133
permissionRevoke,
@@ -324,12 +359,47 @@ export const commands: Record<string, AnyCommand> = {
324359
"pipeline validate": pipelineValidate,
325360
"advisor recommend": advisorRecommend,
326361
"model list": modelList,
362+
"model search": modelSearch,
363+
"model code": modelCode,
327364
"workspace list": workspaceList,
328365
"quota list": quotaList,
329366
"quota update": quotaUpdate,
330367
"quota delete": quotaDelete,
331368
"quota history": quotaHistory,
332369
"quota check": quotaCheck,
370+
"monitor overview": monitorOverview,
371+
"monitor models": monitorModels,
372+
"monitor metrics": monitorMetrics,
373+
"monitor errors": monitorErrors,
374+
"monitor delivery status": monitorDeliveryStatus,
375+
"monitor delivery enable": monitorDeliveryEnable,
376+
"monitor delivery disable": monitorDeliveryDisable,
377+
"log status": logStatus,
378+
"log audit list": logAuditList,
379+
"log audit get": logAuditGet,
380+
"log audit count": logAuditCount,
381+
"log audit enable": logAuditEnable,
382+
"log audit disable": logAuditDisable,
383+
"log inference list": logInferenceList,
384+
"log inference get": logInferenceGet,
385+
"log inference count": logInferenceCount,
386+
"log inference enable": logInferenceEnable,
387+
"log inference disable": logInferenceDisable,
388+
"log trace list": logTraceList,
389+
"log trace get": logTraceGet,
390+
"log trace stats": logTraceStats,
391+
"alert metrics": alertMetrics,
392+
"alert template list": alertTemplateList,
393+
"alert template create": alertTemplateCreate,
394+
"alert template update": alertTemplateUpdate,
395+
"alert template delete": alertTemplateDelete,
396+
"alert list": alertList,
397+
"alert create": alertCreate,
398+
"alert update": alertUpdate,
399+
"alert delete": alertDelete,
400+
"alert enable": alertEnable,
401+
"alert disable": alertDisable,
402+
"alert history": alertHistory,
333403
"permission list": permissionList,
334404
"permission grant": permissionGrant,
335405
"permission revoke": permissionRevoke,
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
import {
2+
defineCommand,
3+
detectOutputFormat,
4+
effectiveConsoleGatewayConfig,
5+
unwrapResponse,
6+
} from "bailian-cli-core";
7+
import { emitResult } from "bailian-cli-runtime";
8+
import {
9+
ALERT_RULE_WRITE_FLAGS,
10+
buildAlertRuleReqDTO,
11+
ensureAlertReady,
12+
validateAlertRuleFlags,
13+
} from "./shared.ts";
14+
15+
const CREATE_RULE_API = "zeldaEasy.bailian-telemetry.alertRule.createAlertRule";
16+
17+
export default defineCommand({
18+
description: {
19+
"en-US": "Create a model alert rule from an alert template",
20+
"zh-CN": "基于告警模板创建模型告警规则",
21+
},
22+
auth: "console",
23+
usageArgs: "--name <name> --template-id <id> --model <model> [flags]",
24+
flags: ALERT_RULE_WRITE_FLAGS,
25+
notes: [
26+
{
27+
"en-US":
28+
"Alert conditions come from the template; browse `alert template list` first. Notification contacts/contact groups are created in the CloudMonitor console — pass their IDs via --contact/--contact-group.",
29+
"zh-CN":
30+
"告警条件来自模板,请先用 `alert template list` 挑选。通知联系人/联系组需在云监控控制台创建,本命令通过 --contact/--contact-group 接收其 ID。",
31+
},
32+
],
33+
exampleArgs: [
34+
"--name high-failure-rate --template-id 123 --model qwen3.6-plus",
35+
"--name latency --template-id 456 --model qwen3.6-plus,qwen-turbo --level ERROR --contact-group 4004200",
36+
"--name nightly --template-id 123 --model qwen3.6-plus --notify-window 09:00-18:00 --notify-days 1,2,3,4,5 --silence 3600",
37+
"--name test --template-id 123 --model qwen3.6-plus --dry-run",
38+
],
39+
validate: (flags) => validateAlertRuleFlags(flags),
40+
async run(ctx) {
41+
const { settings, flags } = ctx;
42+
const format = settings.outputExplicit ? detectOutputFormat(settings.output) : "json";
43+
44+
const reqDTO = {
45+
...(settings.workspaceId ? { workspaceId: settings.workspaceId } : {}),
46+
...buildAlertRuleReqDTO(flags),
47+
};
48+
49+
if (settings.dryRun) {
50+
emitResult(
51+
{
52+
api: CREATE_RULE_API,
53+
data: { reqDTO },
54+
...effectiveConsoleGatewayConfig(settings),
55+
},
56+
format,
57+
);
58+
return;
59+
}
60+
61+
await ensureAlertReady(ctx.client, settings.workspaceId, ctx.identity.binName, settings);
62+
63+
const raw = await ctx.client.console(CREATE_RULE_API, { reqDTO });
64+
const resp = unwrapResponse(raw as Record<string, unknown>);
65+
const ruleId = (resp.data ?? resp.ruleId ?? resp) as string | undefined;
66+
67+
if (format === "json") {
68+
emitResult({ created: true, ruleId }, format);
69+
return;
70+
}
71+
72+
process.stdout.write(`Alert rule created${ruleId ? `: ${ruleId}` : "."}\n`);
73+
},
74+
});
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
import { defineCommand, detectOutputFormat, effectiveConsoleGatewayConfig } from "bailian-cli-core";
2+
import { emitResult } from "bailian-cli-runtime";
3+
import { parseCommaList } from "../shared/params.ts";
4+
import { ensureAlertReady } from "./shared.ts";
5+
6+
const DELETE_RULES_API = "zeldaEasy.bailian-telemetry.alertRule.deleteAlertRules";
7+
8+
export default defineCommand({
9+
description: {
10+
"en-US": "Delete model alert rules",
11+
"zh-CN": "删除模型告警规则",
12+
},
13+
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+
},
21+
usageArgs: "--rule-id <id>[,<id>...] [--yes]",
22+
flags: {
23+
ruleId: {
24+
type: "string",
25+
valueHint: "<id>[,<id>...]",
26+
required: true,
27+
description: {
28+
"en-US": "Rule ID(s) to delete, comma-separated",
29+
"zh-CN": "要删除的规则 ID,多个以逗号分隔",
30+
},
31+
},
32+
},
33+
exampleArgs: ["--rule-id 789", "--rule-id 789,790 --dry-run", "--rule-id 789 --yes"],
34+
notes: [
35+
{
36+
"en-US": "Irreversible — the alert rules are permanently removed.",
37+
"zh-CN": "该操作不可撤销——告警规则将被永久删除。",
38+
},
39+
],
40+
async run(ctx) {
41+
const { settings, flags } = ctx;
42+
const format = settings.outputExplicit ? detectOutputFormat(settings.output) : "json";
43+
44+
const reqDTO = { ruleIds: parseCommaList(flags.ruleId) };
45+
46+
if (settings.dryRun) {
47+
emitResult(
48+
{
49+
api: DELETE_RULES_API,
50+
data: { reqDTO },
51+
...effectiveConsoleGatewayConfig(settings),
52+
},
53+
format,
54+
);
55+
return;
56+
}
57+
58+
await ensureAlertReady(ctx.client, settings.workspaceId, ctx.identity.binName, settings);
59+
60+
await ctx.client.console(DELETE_RULES_API, { reqDTO });
61+
62+
if (format === "json") {
63+
emitResult({ deleted: reqDTO.ruleIds }, format);
64+
return;
65+
}
66+
67+
process.stdout.write(`Deleted ${reqDTO.ruleIds.length} alert rule(s).\n`);
68+
},
69+
});
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import { defineCommand, detectOutputFormat, effectiveConsoleGatewayConfig } from "bailian-cli-core";
2+
import { emitResult } from "bailian-cli-runtime";
3+
import { ensureAlertReady } from "./shared.ts";
4+
5+
const DISABLE_RULE_API = "zeldaEasy.bailian-telemetry.alertRule.disableAlertRule";
6+
7+
export default defineCommand({
8+
description: {
9+
"en-US": "Disable a model alert rule (keeps the rule, stops notifications)",
10+
"zh-CN": "停用模型告警规则(保留规则,停止通知)",
11+
},
12+
auth: "console",
13+
usageArgs: "--rule-id <id> [flags]",
14+
flags: {
15+
ruleId: {
16+
type: "string",
17+
valueHint: "<id>",
18+
required: true,
19+
description: {
20+
"en-US": "Alert rule ID",
21+
"zh-CN": "告警规则 ID",
22+
},
23+
},
24+
},
25+
exampleArgs: ["--rule-id 789", "--rule-id 789 --dry-run"],
26+
async run(ctx) {
27+
const { settings, flags } = ctx;
28+
const format = settings.outputExplicit ? detectOutputFormat(settings.output) : "json";
29+
30+
const reqDTO = {
31+
workspaceId: settings.workspaceId,
32+
bizSource: "bailian",
33+
ruleId: flags.ruleId,
34+
};
35+
36+
if (settings.dryRun) {
37+
emitResult(
38+
{
39+
api: DISABLE_RULE_API,
40+
data: { reqDTO },
41+
...effectiveConsoleGatewayConfig(settings),
42+
},
43+
format,
44+
);
45+
return;
46+
}
47+
48+
await ensureAlertReady(ctx.client, settings.workspaceId, ctx.identity.binName, settings);
49+
50+
await ctx.client.console(DISABLE_RULE_API, { reqDTO });
51+
52+
if (format === "json") {
53+
emitResult({ enabled: false, ruleId: flags.ruleId }, format);
54+
return;
55+
}
56+
57+
process.stdout.write(`Alert rule disabled: ${flags.ruleId}\n`);
58+
},
59+
});
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { defineCommand, detectOutputFormat, effectiveConsoleGatewayConfig } from "bailian-cli-core";
2+
import { emitResult } from "bailian-cli-runtime";
3+
import { ensureAlertReady } from "./shared.ts";
4+
5+
export default defineCommand({
6+
description: {
7+
"en-US": "Enable a model alert rule",
8+
"zh-CN": "启用模型告警规则",
9+
},
10+
auth: "console",
11+
usageArgs: "--rule-id <id> [flags]",
12+
flags: {
13+
ruleId: {
14+
type: "string",
15+
valueHint: "<id>",
16+
required: true,
17+
description: {
18+
"en-US": "Alert rule ID",
19+
"zh-CN": "告警规则 ID",
20+
},
21+
},
22+
},
23+
exampleArgs: ["--rule-id 789", "--rule-id 789 --dry-run"],
24+
async run(ctx) {
25+
const { settings, flags } = ctx;
26+
const format = settings.outputExplicit ? detectOutputFormat(settings.output) : "json";
27+
28+
const reqDTO = {
29+
workspaceId: settings.workspaceId,
30+
bizSource: "bailian",
31+
ruleId: flags.ruleId,
32+
};
33+
34+
if (settings.dryRun) {
35+
emitResult(
36+
{
37+
api: "zeldaEasy.bailian-telemetry.alertRule.enableAlertRule",
38+
data: { reqDTO },
39+
...effectiveConsoleGatewayConfig(settings),
40+
},
41+
format,
42+
);
43+
return;
44+
}
45+
46+
await ensureAlertReady(ctx.client, settings.workspaceId, ctx.identity.binName, settings);
47+
48+
await ctx.client.console("zeldaEasy.bailian-telemetry.alertRule.enableAlertRule", { reqDTO });
49+
50+
if (format === "json") {
51+
emitResult({ enabled: true, ruleId: flags.ruleId }, format);
52+
return;
53+
}
54+
55+
process.stdout.write(`Alert rule enabled: ${flags.ruleId}\n`);
56+
},
57+
});

0 commit comments

Comments
 (0)