@bluefocus-ai/blueai-cli
v0.6.1
Published
BlueAI atomic capabilities CLI
Readme
blueai-cli
BlueAI 原子能力 CLI —— Agent 优先,OpenAPI 驱动,动态命令树。
blueai-cli 在启动时从 OpenAPI YAML 规范动态构建命令树,没有任何静态命令注册。23 个 service、206 个原子能力按 x-cli.path 挂载成可变深度的命令树,外加 api / config / doctor / spec / task 五个内置基础设施命令。
设计原则:Agent 优先。 当"人类可读 vs 机器可解析""简洁 vs 显式""交互提示 vs 纯 flag"出现取舍时,一律选择让 Agent 更高效的一方。人类友好只是附带收益。
目录
安装
npm install -g @bluefocus-ai/blueai-cli要求 Node.js ≥ 18。
从旧包迁移
如果之前安装过 blueai-cli 或 @bmc/blueai-cli,这些包与新包都提供同名的 blueai-cli 命令,直接安装可能报 EEXIST。先卸载旧包,再重新安装:
npm uninstall -g blueai-cli @bmc/blueai-cli
npm install -g @bluefocus-ai/blueai-cli@latest
blueai-cli --version迁移完成后,后续升级同一个包只需执行:
npm install -g @bluefocus-ai/blueai-cli@latest不要在迁移时使用 --force 覆盖命令文件;这可能留下不一致的全局包记录。
$ blueai-cli --version
blueai-cli/0.0.13
$ blueai-cli --help
BlueAI 原子能力 CLI
...首次使用前,配置一个统一的 Bearer API key:
blueai-cli config init快速上手
所有 YAML 驱动命令的调用形式都是:
blueai-cli <path...> --params '<JSON>' [--flags]<path...> 是点分命令树路径(空格分隔),例如 aigc video text2video kling。
# 文生视频(Kling),同步轮询到出结果
blueai-cli aigc video text2video kling \
--params '{"prompt":"一只在月球上弹吉他的猫","duration":"5"}'
# 文生图(即梦 Seedream 4.6)
blueai-cli aigc image text2image jimeng v4-6 \
--params '{"prompt":"赛博朋克东京街景","aspect_ratio":"16:9"}'
# OpenAI 兼容聊天
blueai-cli llm chat \
--params '{"model":"gpt-4o","messages":[{"role":"user","content":"hi"}]}'不知道某个命令接受哪些参数?查帮助:
blueai-cli aigc video text2video kling --help命令树
命令树由每个 operation 的 x-cli.path 声明,深度从 2 到 5 段不等。顶层分五大类:
| 顶层 | 含义 | 命令数 |
|---|---|---|
| aigc | 音频 / 图像 / 视频生成与编辑 | 126 |
| data | 社媒数据抓取与分析 | 43 |
| llm | LLM 对话 / 补全 / 嵌入 / 重排 | 10 |
| media-storage | 媒体文件存储与打包 | 10 |
| tools | 搜索 / 抓取 / 视频工具 | 17 |
实时查询当前生效的命令(Agent 推荐):
# 所有命令 + 完整 OpenAPI 元数据(JSON)
blueai-cli spec list
# 按 glob 过滤
blueai-cli spec list --path 'aigc.video.**'
# 按 service 过滤
blueai-cli spec list --service kling
# 人类可读的命令树视图
blueai-cli spec tree完整的静态命令清单见 COMMANDS.md(自动生成,请勿手改)。
路径命名规则
- aigc 路径以 provider 段结尾(即便 sole-provider 也保留,便于对比模型/质量/成本);非 aigc 路径在 sole-provider 时省略 provider 段。
- 段名不重复父级语义(无
tools.search.search.metaso)。 - 有共同前缀的 ≥2 个 operation 会引入语义子命名空间(如
aigc.audio.hotword-library.*)。 - 同一 provider 多个不兼容版本各占一个叶子段(如
aigc.image.text2image.jimeng.{v3-0,v4,v4-5,v4-6,v5})。 - 同一 operation 可挂载到多个路径(aliases)。
通用 flag 与参数
所有 YAML 驱动命令都接受:
| Flag | 说明 |
|---|---|
| --params '<JSON>' | 请求参数,JSON 对象(批量模式时为 JSON 数组) |
| --async | 异步:跳过轮询,提交后立即返回 task_id |
| --dry-run | 只打印将发出的 HTTP 请求,不真正调用 |
| --format | 输出格式:json(默认)/ ndjson / table / csv |
| --verbose | 输出请求 / 轮询细节到 stderr |
| --api-key | 显式指定 API key,覆盖凭据解析链 |
multipart 能力额外接受 --file <path>。
异步任务与任务注册表
async 能力(sync: false)默认行为:
- 发起请求,从响应里提取
task_id - 按配置的
statusPath/statusField/pollInterval轮询 - 通过
x-cli.async.statusEnum把原始状态归一为pending | processing | succeeded | failed(未知值视为pending继续轮询) - 返回终态轮询响应原文;轮询无总超时上限(
pollTimeout已废弃,可用SIGINT/SIGTERM中断等待)
任务注册表:每次 --async 提交都会在 ~/.blueai/tasks.json 写一条记录,包含重新轮询所需的全部配置(statusPath / statusField / statusEnum / pollInterval / serviceId / path),且每条记录带自己的 enum 快照——spec 之后变更不会影响在途任务的解读。
# 查看待处理任务
blueai-cli task list [--status pending|succeeded|failed] [--service kling]
# 监听单个任务到完成(自动从注册表查配置)
blueai-cli task status <task_id> --watch
# 并发等待指定 ID
blueai-cli task wait --ids '["abc","def"]' [--concurrency 3] [--format ndjson]
# 等待所有 pending 任务(Agent 友好,无需传 ID)
blueai-cli task wait --all [--concurrency 3] [--format ndjson]Agent 单会话异步模式:--async 批量提交 → 做别的事 → task wait --all --format ndjson 收集结果。注册表跨会话持久化,后续会话自动看到之前提交的 pending 任务。终态记录 7 天后自动清理。
长轮询可被 SIGINT / SIGTERM 中断,返回 Interrupted 错误(exit 130),detail 含 task_id 和 last_status。
批量模式
任何能力都支持把 --params 传成 JSON 数组,一次调用跑 N 个请求:
blueai-cli aigc video text2video kling \
--params '[{"prompt":"a","_label":"variant-1"},{"prompt":"b","_label":"variant-2"}]' \
--concurrency 3 \
--format ndjsonPer-item 内置键(调用前剥离):
_label— 回显到结果,便于关联_file— 该项的文件上传路径(仅 multipart,不能与全局--file同用)
Flag:
--concurrency N— 并行在途数(默认service.defaultConcurrency ?? 3)--fail-fast— 首次失败后停止调度新项,exit 1
NDJSON 输出(Agent 推荐):每行一条结果 {"index":0,"label":"...","ok":true,"data":{...},"serviceId":"kling"},最后一行是 {"batch_summary":{"total":N,"succeeded":S,"failed":F}}。进度按条打到 stderr。
异步批量(fire-and-forget):--async 跳过轮询,每项立即返回 task_id,配合 task wait --all 稍后集中收结果。
文件上传
multipart 能力把 --file 的内容直接从磁盘流式发出,CLI 不会把整文件读进内存。Content-Length 预先计算好(非 chunked),兼容拒绝 chunked 上传的网关。重试时从磁盘重新读取,每次都发完整 body。
已知限制:multipart 上传遇到 301/302/307/308 重定向会被拒绝而非跟随(源流已被消费)。生产网关不会对 multipart 重定向,这是安全兜底。
配置与凭据
单一统一 Bearer API key。所有 service 都发 Authorization: Bearer <apiKey>。
凭据解析顺序(前者优先):
--api-keyflag- 工作区
.blueai/credentials.json(从 CWD 向上查找) BLUEAI_API_KEY环境变量- 用户级
~/.blueai/credentials.json
设置了
BLUEAI_CONFIG_DIR时,工作区查找会被跳过(测试隔离用)。
网关解析顺序:BLUEAI_<SERVICE_ID_UPPER>_GATEWAY 环境变量 → spec 的 servers[0].url(- 替换为 _ 再全大写,如 BLUEAI_LLM_RELAY_GATEWAY)。
凭据文件格式:
{ "default": { "apiKey": "sk-..." } }旧版 providers.*.api_key / services.*.api_key 桶可被 blueai-cli config migrate 就地升级为扁平 apiKey;仅含 appid/secret 的旧文件无法自动迁移,需获取统一 apiKey 后 config init。
- 配置:
~/.blueai/config.json—— profile、轮询设置、格式默认值 - 凭据:
~/.blueai/credentials.json—— 每个 profile 一个apiKey - 工作区凭据:
<project>/.blueai/credentials.json—— 同格式,优先级高于用户级
内置命令
这五个不经过动态树,直接挂在根命令下:
| 命令 | 用途 |
|---|---|
| blueai-cli api | 原始 HTTP 调用(需 --gateway 或 BLUEAI_GATEWAY) |
| blueai-cli config | init / profiles / show / migrate |
| blueai-cli doctor | 环境与配置诊断 |
| blueai-cli spec | list(扁平能力清单)/ tree(命令树视图) |
| blueai-cli task | list / status <id> --watch / wait --ids / wait --all |
输出格式与错误码
输出统一为 JSON 信封:
{ "ok": true, "data": { ... }, "meta": { ... } }
// 或
{ "ok": false, "error": { "type": "auth_error", "message": "...", "hint": "..." } }错误通过 BlueAIError 归类为带类型的 exit code:
| Exit | 含义 |
|---|---|
| 0 | 成功 |
| 1 | API 错误 |
| 2 | 校验错误 |
| 3 | 鉴权错误(无 apiKey 时提示 --api-key / BLUEAI_API_KEY / config init) |
| 4 | 网络错误 |
| 5 | 内部错误 |
请求可靠性:单请求超时默认不设限(无超时,适用于视频理解等可长达数分钟的慢同步接口);需要限制时通过 --timeout flag 或 per-capability 的 x-cli.requestTimeout 设置(profile.requestTimeout 已废弃不再读取)。挂起 TCP 连接会被销毁并上报为 network 错误;429 遵守 Retry-After(上限 60s),否则指数退避;2xx 但 JSON 解析失败不重试,作为 api_error 返回前 500 字节 body。
开发
npm run build # 干净编译:rm -rf dist && tsc -b
npm test # 全量测试
npm test -- --grep "pattern" # 按名过滤
./bin/dev.js <cmd> # ts-node 直接跑,无需 build
./bin/run.js <cmd> # 跑编译后的 dist/,需先 build
npm run lint # ESLint
npm run gen-commands # 从 spec 重新生成 COMMANDS.md
npm run fill-x-cli # 给 raw spec 自动注入 x-cli stub架构
openapi/raw/*.yaml + openapi/x-cli/*.yaml → spec-fetcher(merge) → openapi-loader → ServiceDef[] → command-builder → citty CommandDef 树src/cli.ts— 入口,读SERVICES、拉 spec、构建命令树src/lib/spec-fetcher.ts— 三级回退加载 spec(merged → raw+x-cli → legacy)src/lib/spec-overlay.ts— 合并 Apifox raw 与人工维护的x-clioverlaysrc/lib/openapi-loader.ts— 解析合并后的 OpenAPI,产出ServiceDefsrc/lib/command-builder.ts— 按x-cli.path把能力挂到命令树(可多挂载)src/lib/executor.ts— 执行能力:解析参数、构建 HTTP、multipart、异步轮询src/lib/client.ts— 原生node:http/node:https裸客户端,带重试,无外部 HTTP 库
新增 service
- 用
node scripts/fetch-apifox-spec.mjs --output <id>拉 OpenAPI 到openapi/raw/<id>.yaml(先设APIFOX_PROJECT_ID/APIFOX_ACCESS_TOKEN),或手工编写(须含servers[0].url)。 - 创建
openapi/x-cli/<id>.yaml,为每个 operation 写x-clioverlay(path/sync/async等)。可先npm run fill-x-cli生成 stub 再手改。 - 在
src/providers/config.ts的SERVICES里加{id, specFile}(需要每日 Apifox 同步的再加apifoxProjectId)。 - 如有异步轮询,在 overlay 的
x-cli.async.statusEnum里声明 raw→canonical 映射,无需改 TS。构建期 zod 会校验 canonical 值拼写。 npm run gen-commands更新COMMANDS.md,npm run build验证。
了解更多
- COMMANDS.md — 全量命令清单(自动生成)
- CLAUDE.md — 给 AI Coding Agent 的开发约定与架构细节
- 实时命令元数据:
blueai-cli spec list
License: MIT
