بنقرة واحدة
create-cli-command
将前端 API 能力封装成 agentbay-cli 命令的标准化流程
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
将前端 API 能力封装成 agentbay-cli 命令的标准化流程
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
AgentBay CLI 双语 CHANGELOG 与 GitHub Release 发版 SOP。Use when preparing a release, updating bilingual CHANGELOG, translating release notes, creating tags, refreshing GitHub Release notes, or running make release-prep/backfill-release-notes.
AgentBay CLI 命令文档同步流程(docs/、README、CHANGELOG readiness)
AgentBay CLI 需求开发全流程规范(分支管理、推送、提交、PR),不含具体需求内容
将当前本地分支推送到 aliyun 远程的同名分支(禁止推送到 master/main)
将当前本地分支推送到 origin 远程的同名分支(禁止推送到 master/main)
| name | create-cli-command |
| description | 将前端 API 能力封装成 agentbay-cli 命令的标准化流程 |
本 skill 必须与 feature-development-workflow 配套使用,两者分工如下:
| Skill | 负责 | 触发时机 |
|---|---|---|
| feature-development-workflow | 分支管理(从 aliyun/master 拉 feat 分支)、双远程推送(origin → aliyun)、PR 流程、变更档案 | 开发前、提交后 |
| create-cli-command(本文件) | SDK 模型 → Client 接口 → Cobra 命令 → mock 同步 → 单测 → 对客文档 readiness | 开发中 |
执行铁律:
feature-development-workflow 的 Phase 0(变更档案初始化)和分支创建,确认当前在 feat-<name> 分支且基于 aliyun/master,否则不得进入本 skill 的 Phase 1。⚠️ 切分支前必须先询问用户:用户可能已在当前分支开发,不要自动切换 feat 分支。feature-development-workflow 的 Phase 4-6 完成 commit、双远程 push(origin 先、aliyun 后)、PR、trace.md 更新。若用户未提前走
feature-development-workflow,本 skill 执行第一步必须主动提醒并引导用户先建档、拉分支。
将 agent-bay 前端控制台中的 API 能力封装成 agentbay-cli 命令行工具,包括:
当用户提出以下需求时触发:
查找前端 API 实现
agent-bay/src/http/api/ 目录下搜索接口确认 API 信息
xiaoying(CLI 使用,不是前端的 xiaoying-double-centre)2025-05-01与用户确认
--name 而非位置参数)internal/client/
├── {action}_request_model.go # 请求模型
└── {action}_response_model.go # 响应模型
要求:
Validate() 方法GetXxx() 辅助方法在 internal/client/client.go 中添加:
{Action}WithOptions() - 完整调用方法{Action}() - 简化调用方法{Action}WithContext() - 支持 context 的方法parse{Action}Response() - 响应解析函数⚠️ parser 必须放入 internal/client/dual_format_responses.go(而非 client.go),且必须遵守下述容错规范:
*int32 / *int64 字段用 json.RawMessage + int32FromFlexibleJSON 解析,兼容数字与字符串两种序列化形式(服务端常会以字符串返回 HttpStatusCode 等数字字段)。< 开头走 XML 分支、否则走 JSON 分支,两条路径都要调用 applyMapHeadersAndStatus 归一 headers / statusCode。&ErrWithRequestID{Err: ..., RequestID: extractRequestIDFromResponse(res)} 包装。internal/client/ 下配套一个 xxx_parse_test.go,至少覆盖「JSON 数字字段为字符串 / 数字 / XML」三种场景。反面案例:BatchCreateHideResourceGroupsWithMaxSession 早期直接用 json.Unmarshal 打到 *int32,遇到 "HttpStatusCode":"200" 直接报 cannot unmarshal string into Go struct field ... of type int32。详见 references/api-format.md 与规则 development.md 响应解析必须使用容错模板。
API 配置模板:
params := &openapiutil.Params{
Action: dara.String("ActionName"),
Version: dara.String("2025-05-01"),
Protocol: dara.String("HTTPS"),
Pathname: dara.String("/"),
Method: dara.String("POST"),
AuthType: dara.String("AK"),
Style: dara.String("RPC"),
ReqBodyType: dara.String("formData"),
BodyType: dara.String("string"),
}
在 internal/agentbay/client.go 中:
Client interface 中添加方法定义clientWrapper 中实现方法⚠️ 重要:更新接口后必须同步更新所有 Mock 类!
# 1. 查找所有实现该接口的 mock 类
grep -r "type mock.*Client struct" cmd/ test/
# 2. 为每个 mock 类添加新方法
# 示例:在 cmd/image_status_helper_test.go 和 cmd/image_list_helper_test.go 中添加
// 为每个 mock 类添加(返回 "not implemented")
func (m *mockClient) NewMethod(ctx context.Context, request *client.NewRequest) (*client.NewResponse, error) {
return nil, fmt.Errorf("not implemented")
}
检查清单:
go test ./cmd/... 确保编译通过在 cmd/ 目录下创建命令文件:
--name, --api-key-id)MarkFlagRequired()规则: 每个 CLI 命令调用的每一个对外接口请求,无论成功还是失败、无论是否带 -v / --verbose,都必须在终端打印对应的 RequestId,便于客户在出现问题时直接复制日志给运维定位。
❌ 禁止做法(之前的旧规范):
// ❌ 不要再用 verbose 守卫保护 RequestId 打印
verbose, _ := cmd.Flags().GetBool("verbose")
if verbose && resp.Body.RequestId != nil && *resp.Body.RequestId != "" {
printRequestIDIfVerbose(cmd, *resp.Body.RequestId)
}
✅ 正确做法:
// 1. 成功路径:直接打印(不依赖 verbose)
if resp != nil && resp.Body != nil {
if reqId := resp.Body.GetRequestId(); reqId != nil && *reqId != "" {
fmt.Printf("[INFO] {Action} Request ID: %s\n", *reqId)
}
}
// 2. 错误路径:err 中携带的 RequestId 也必须打印
resp, err := apiClient.{Action}(ctx, req)
if err != nil {
// 不再使用 printRequestIDFromErrIfVerbose(带 verbose 守卫的版本)
if reqId := extractRequestIDFromErr(err); reqId != "" {
fmt.Printf("[INFO] {Action} Request ID: %s\n", reqId)
}
return fmt.Errorf("[ERROR] Failed to {action}: %w", err)
}
多接口命令: 命令体内若调用多个接口(如先 GetMcpImageInfo 再 BatchCreateXxx),每一个接口的 RequestId 都要分别打印,并在前缀里标注接口名以便区分:
[INFO] GetMcpImageInfo Request ID: 1A2B3C4D-...
[INFO] BatchCreateHideResourceGroupsWithMaxSession Request ID: 5E6F7G8H-...
参考实现: cmd/image_set_max_session.go
verbose / -v 的真正用途: 仅控制额外的调试信息(请求体、响应体 JSON、堆栈等),不再控制 RequestId 是否打印。
规则:命令涉及不可逆操作(删除、永久停用等)时,必须同时实现二次确认提示和 --yes / -y 跳过参数。
哪些情况触发:
| 操作类型 | 示例 | 是否需要 |
|---|---|---|
| 永久删除资源 | apikey delete, image delete | ✅ 必须 |
| 多步骤前置依赖(如先禁用才能删除) | 每步都提示 | ✅ 每步 |
| 可逆状态变更 | enable, disable | ❌ 不需要 |
| 查询/只读操作 | list, status | ❌ 不需要 |
标准实现(复用 cmd/confirm.go 中已有的 ConfirmPrompt):
// init() 中注册 flag
apikeyDeleteCmd.Flags().BoolP("yes", "y", false, "Skip all confirmation prompts (for non-interactive use)")
// RunE 中使用
autoYes, _ := cmd.Flags().GetBool("yes")
// 每个确认点调用 ConfirmPrompt,autoYes 透传
confirmed, err := ConfirmPrompt("Are you sure you want to delete? [y/N]: ", autoYes)
if err != nil {
return fmt.Errorf("[ERROR] %w", err)
}
if !confirmed {
fmt.Printf("[INFO] Operation cancelled.\n")
return nil
}
ConfirmPrompt 三种行为:
--yes 传入 → 直接 true,无任何输出--yes → 返回错误,提示用户加 --yes多步骤命令:每步单独调用 ConfirmPrompt(prompt, autoYes),一个 --yes 跳过全部步骤。
参考实现:
cmd/apikey_delete.go —— 多步骤(禁用确认 + 删除确认)cmd/image.go runImageDelete —— 单步骤确认命令层级:
agentbay
└── apikey # 命令组
├── create --name <名称> # 子命令
└── concurrency # 子命令组
└── set --api-key-id <ID> --concurrency <数值>
在 main.go 的 init() 中注册命令:
rootCmd.AddCommand(cmd.XxxCmd)
在 test/unit/cmd/ 目录创建测试文件:
测试覆盖要求:
测试命名规范:
Test<命令组>Cmd // 测试命令组
Test<子命令>Cmd // 测试子命令
编译测试
go build -o agentbay .
帮助信息测试
./agentbay <command> --help
./agentbay <command> <subcommand> --help
参数校验测试
运行新命令的单元测试
go test -v ./test/unit/cmd/ -run TestXxx -count=1
🔁 全量回归测试(强制)
新增 / 修改 CLI 命令后,必须运行全量测试,确保没有任何已有命令的单测因接口变更、mock 缺失或公共代码改动而被破坏:
# 全量测试(包括 cmd / internal / test/unit/...)
go test ./... -count=1
# 或更严格:跑 race 检测
go test ./... -count=1 -race
通过标准:
go build -o agentbay . 无错误且产出的二进制保留在项目根目录供用户直接使用go test ./... -count=1 全部 PASS重要:每次新增或修改命令后,必须执行
go build -o agentbay .重新构建二进制到项目根目录。不要仅用go build ./...(只验证编译不输出文件),否则用户运行./agentbay时仍是旧版本。
⚠️ 隔离原则:新增命令不得修改其它命令的公共行为。如果必须改公共代码(如 internal/agentbay/client.go、config、auth),必须在 PR/变更档案里明确列出影响范围,并跑完所有相关命令的回归用例。
本阶段委托 update-cli-command-docs skill 执行,不在本 skill 内展开。
加载并执行 .qoder/skills/update-cli-command-docs/SKILL.md,该 skill 将完成:
docs/en/<group>.md 和 docs/zh/<group>.mdREADME.md 和 README.zh-CN.md Command Overview 表格README.md 或 docs/en/**,执行 bash scripts/build-llms-full.sh 并同步 llms-full.txt;文档结构变化时检查 llms.txtCHANGELOG.md readiness(校验 commit/PR title 可被 release-prep 采集;不在日常命令开发中全量生成 CHANGELOG)⚠️ 不得在本 Phase 中内联执行文档操作,必须遵循
update-cli-command-docs的 Phase 0-3 完整流程。
对客文档(cli-analysis/ 目录、钉钉文档)不在此 skill 范围内,需手动同步。
⚠️ 重要: 必须询问用户是否提交,不要自动提交!
提交前展示:
git status
git diff --stat
询问用户:"需要我帮你提交代码吗?"
用户确认后,使用规范的 commit message:
git add -A
git commit -m "feat: add <功能描述> CLI command
- 具体改动点 1
- 具体改动点 2
- 具体改动点 3"
✅ 必须包含:
✅ 代码质量:
✅ docs/ 命令文档(必须):
docs/en/<command-group>.md 已更新(语法、参数、示例、输出)docs/zh/<command-group>.md 已更新(与英文版结构一致)README.md Command Overview 表格已更新README.zh-CN.md Command Overview 表格已更新README.md 或 docs/en/**,已执行 bash scripts/build-llms-full.sh 并同步 llms-full.txtllms.txt 导航链接✅ 对客文档(cli-analysis/):
✅ 提交与 CHANGELOG readiness:
feat(apikey): ...)! 或 BREAKING CHANGE:make release-prep VERSION=X.Y.Z 生成到 CHANGELOGupdate-cli-command-docs 完成 llms readiness(llms-full.txt / llms.txt 已同步或明确无需更新)xiaoying,不是前端的 xiaoying-double-centre"HttpStatusCode":"200"),parser 必须用 dual_format_responses.go 中的 int32FromFlexibleJSON 容错,绝不直接 json.Unmarshal 打到 *int32。详见 references/api-format.md 响应解析容错模板。--name),不使用位置参数README.md 或 docs/en/** 变化时,必须通过 update-cli-command-docs 执行 bash scripts/build-llms-full.sh 并同步 llms-full.txt;文档结构变化时检查 llms.txtagentbay.Client 接口添加新方法后,必须立即更新所有 mock 类!
grep -r "type mock.*Client struct" cmd/ test/fmt.Errorf("not implemented"))mockGetMcpImageInfoClient, mockImageListClient*mockClient does not implement agentbay.Client (missing method Xxx)