cnb-npc
v0.1.2
Published
CLI for CNB NPC comments and build watching.
Readme
npc-cli
一个用于 CNB 平台的 Node.js CLI,可通过评论召唤 NPC,并监控一个或多个 NPC 构建状态。
当前仓库已经完成首版 CLI 骨架和核心流程实现。
当前 npm 包名使用 cnb-npc,CLI 可执行名为 npc-cli。
当前状态
以下链路已经在真实 CNB 仓库中验证通过:
.env.npc配置加载comment从stdin或--file读取正文- 若首行未
@NPC,则自动插入CNB_NPC_NAME - PR comment 写入
- PR comments 回读
- 识别 NPC comment
- 从 comments 中提取真实 build SN
watch --build <sn>watch --pr <iid>- 构建状态摘要和最近日志摘要输出
当前已在真实环境验证通过的命令形态:
printf '请帮我测试一下 npc-cli 的评论和构建发现链路。' | node ./dist/src/cli.js comment --pr 27
printf '请帮我测试一下 npc-cli 的评论和构建发现链路。' | node ./dist/src/cli.js comment --pr 27 --wait
node ./dist/src/cli.js builds --pr 27 --debug
node ./dist/src/cli.js watch --pr 27
node ./dist/src/cli.js watch --build cnb-4ko-1jrp7aqji当前限制:
watch --pr当前主要通过 comments 中的 build SN 做关联watch --issue还未完成真实环境验证watch --pr/--issue --all-running的“列出当前目标下所有未完成构建”仍在继续适配 CNB 的真实构建列表接口- 构建列表相关 HTTP endpoint 目前未完全收紧,必要时会回退
cnbCLI
安装与运行
本地开发运行:
npm install
npm run build
node ./dist/src/cli.js --help开发态直接运行:
npm run dev -- --help辅助调试命令:
npm run dev -- resolve-target --pr "https://cnb.cool/foo/bar/-/pulls/23"
npm run dev -- builds --pr 23
npm run dev -- builds --pr 23 --all-running
npm run dev -- builds --pr 23 --debug
node ./dist/src/cli.js builds --pr 27 --debug发布到 npm 后,预期使用方式为:
npx cnb-npc --help如果后续单独发布别名包,再补充 npx npc-cli 入口。
配置文件
项目支持在当前工作目录放置 .env.npc,也支持通过全局参数 --env-file 或环境变量 NPC_CFG_ENV 指定配置文件路径。
可以直接从示例文件开始:
cp .env.npc.example .env.npc当前实现按下面顺序解析配置文件,未声明的字段再回退到进程环境变量和 CNB_* 环境变量:
--env-file <path>NPC_CFG_ENV- 当前工作目录下的
.env.npc
示例:
npm run dev -- --env-file ./.config/npc.dev.env comment --pr 23 --file ./comment.md
NPC_CFG_ENV=./envs/test.npc.env npm run dev -- watch --pr 23示例文件:
CNB_API_ENDPOINT=https://api.cnb.cool
CNB_WEB_ENDPOINT=https://cnb.cool
CNB_REPO_SLUG=beilinmo/CNB-NightStar/qemu-cnb
CNB_TOKEN=your_cnb_token_here
CNB_NPC_NAME=@XMZZUZHI/SuperNPC(张良)
NPC_DEFAULT_POLL_INTERVAL_MS=5000
NPC_DEFAULT_TIMEOUT_MS=1800000字段说明:
CNB_API_ENDPOINT: CNB HTTP API 地址CNB_WEB_ENDPOINT: CNB Web 地址,用于生成构建日志链接CNB_REPO_SLUG: 当前默认仓库路径,使用纯 IID 时必须依赖它解析目标CNB_TOKEN: CNB 访问令牌,用于评论、读取 comments、读取构建状态和日志CNB_NPC_NAME: 默认 NPC mention;当 comment 正文首行没有@NPC 时会自动插入NPC_DEFAULT_POLL_INTERVAL_MS:watch轮询间隔,单位毫秒NPC_DEFAULT_TIMEOUT_MS:watch总超时,单位毫秒
默认 NPC mention 为:
@XMZZUZHI/SuperNPC(张良)目标
项目需要支持两类核心能力:
- 在 Issue / PR 下通过评论与 NPC 交互。
- 通过刷新项目 build logs 监控一个或多个 NPC 的运行状态。
同时满足以下约束:
- 项目以 Node.js CLI 形式交付。
- 用户可直接通过
npx npc-cli运行。 - 项目上下文优先从
.env.npc读取;若不存在,再回退到CNB_*环境变量。 - PR / Issue 输入既支持简单
iid,也支持完整 URL。
设计原则
- 优先使用 CNB HTTP API,不把核心流程绑定到本地
cnbCLI 安装状态。 - 将“资源解析”、“评论发送”、“构建监控”拆为独立模块,便于扩展。
- 默认输出人类可读的状态信息,同时保留后续增加
--json的空间。 - 首个版本优先支持非交互命令模式,避免过早引入 TUI 复杂度。
- 首个版本优先跑通核心流程,再考虑 webhook、daemon、复杂缓存等增强能力。
预期使用方式
1. 评论交互
对 PR 评论:
npm run dev -- comment --pr 23 --file ./comment.md通过文件输入评论内容:
npm run dev -- comment --pr 23 --file ./comment.md通过 stdin 输入评论内容:
printf '请帮我检查最近的变更' | npm run dev -- comment --pr 23评论后等待这次触发的 NPC build 结束:
printf '请帮我检查最近的变更' | npm run dev -- comment --pr 23 --wait真实验证过的 PR 评论命令:
printf '请帮我测试一下 npc-cli 的评论和构建发现链路。' | node ./dist/src/cli.js comment --pr 27对 Issue 评论:
npm run dev -- comment --issue 15 --file ./issue-comment.md通过 URL 指定目标:
npm run dev -- comment --pr "https://cnb.cool/beilinmo/CNB-NightStar/qemu-cnb/-/pulls/23" --file ./comment.md2. 监控 NPC 运行状态
监控某个 PR 相关构建:
npm run dev -- watch --pr 23真实验证过的 PR watch 命令:
node ./dist/src/cli.js watch --pr 27监控某个 Issue 触发的 NPC 构建:
npm run dev -- watch --issue 15按构建号监控:
npm run dev -- watch --build 123456789真实验证过的 build watch 命令:
node ./dist/src/cli.js watch --build cnb-4ko-1jrp7aqji监控多个构建:
npm run dev -- watch --build 123 --build 456 --build 789监控某个 PR / Issue 下所有未完成 NPC 构建:
npm run dev -- watch --pr 23 --all-running配置来源与优先级
配置加载优先级设计如下:
- 当前工作目录下的
.env.npc - 进程环境变量
- CNB 运行时内置
CNB_*环境变量 - 命令行显式参数
注意:命令行参数本身仍然应覆盖配置文件和环境变量。上面优先级表达的是“默认值来源”。
预期支持的配置项
.env.npc 中建议支持以下字段:
CNB_API_ENDPOINT=https://api.cnb.cool
CNB_WEB_ENDPOINT=https://cnb.cool
CNB_REPO_SLUG=beilinmo/CNB-NightStar/qemu-cnb
CNB_TOKEN=xxxx
NPC_DEFAULT_TARGET_TYPE=pr
NPC_DEFAULT_POLL_INTERVAL_MS=5000
NPC_DEFAULT_TIMEOUT_MS=1800000说明:
- 若
.env.npc存在,则先加载其内容。 - 若
.env.npc中缺失某项,则继续读取当前环境。 CNB_*变量继续作为底层上下文来源。
资源识别设计
CLI 需要统一解析以下输入形式:
23https://cnb.cool/<group>/<repo>/-/pulls/23https://cnb.cool/<group>/<repo>/-/issues/15
统一解析结果
内部统一归一化为:
type TargetRef = {
type: 'pull' | 'issue'
iid: number
repoSlug: string
webUrl?: string
}解析规则
- 如果输入是纯数字:
--pr视为当前仓库下的 PR IID--issue视为当前仓库下的 Issue IID
- 如果输入是 URL:
- 自动识别是 PR 还是 Issue
- 自动提取
repoSlug - 允许跨仓库目标
- 若输入既没有显式参数,也没有 URL,则可根据当前
CNB_PULL_REQUEST_IID/CNB_ISSUE_IID自动推断当前上下文。
功能设计
一、评论交互
命令暂定:
npx npc-cli comment [--pr <iid|url> | --issue <iid|url>] --body <text>行为
- 解析目标资源。
- 判定评论目标类型:PR 或 Issue。
- 读取评论正文。
- 拼装并调用 CNB 能力执行评论。
- 输出评论结果摘要。
评论输入来源
comment 子命令支持两种正文输入方式:
- 通过命令行参数指定文件路径,例如
--file ./comment.md - 如果未指定文件,则从
stdin读取正文
首版不把 --body 作为主输入方式,避免复杂转义、多行输入和 shell quoting 问题。
建议命令形态更新为:
npx npc-cli comment [--pr <iid|url> | --issue <iid|url>] [--file <path>]NPC mention 自动补齐
发送评论前,需要检查正文首行是否已经显式 @ 了 NPC。
规则如下:
- 如果首行已经是 NPC mention,则原样发送。
- 如果首行不是 NPC mention,则自动在正文头部插入一行 NPC mention。
- NPC mention 优先读取环境变量
CNB_NPC_NAME。 - 如果
CNB_NPC_NAME未设置,则默认使用:
@XMZZUZHI/SuperNPC(张良)内部可将该值统一解析为一个完整的召唤前缀字符串,而不是只保存纯名称。
示例:
输入正文:
请帮我总结这个 PR 的风险自动发送为:
@XMZZUZHI/SuperNPC(张良)
请帮我总结这个 PR 的风险实现建议
首版优先直接调用 CNB HTTP API:
- 评论发送通过 API 完成。
- 评论列表读取通过 API 完成。
- 构建详情、构建状态、构建日志摘要通过 API 完成。
可保留一个薄的 cnb CLI 适配层作为后备方案,但不作为首版主路径。
当前实现状态
已完成:
.env.npc优先加载CNB_*环境变量回退- PR / Issue 的 IID 与 URL 解析
comment子命令--file/stdin正文输入- 首行 NPC mention 自动补齐
watch --buildwatch --pr/--issue--all-running模式
当前实现说明:
- comments API 使用明确的 HTTP 路径实现。
- build 详情和日志摘要优先走 HTTP API。
- 由于公开文档中 build/log endpoint 细节不完整,当前实现会探测一组候选 endpoint。
- 若 HTTP 失败且本地安装了
cnbCLI`,会尝试用其做构建详情和日志的后备读取。
这意味着:评论流程相对稳定;构建监控流程在不同 CNB 环境里可能仍需根据真实 API 响应做微调。
输出示例
Comment posted
target: pull#23
repo: beil inmo/CNB-NightStar/qemu-cnb
comment-id: 987654上面的 repo 行只是展示格式示意,实际实现时会输出正确 slug。
二、监控 NPC 运行状态
命令暂定:
npx npc-cli watch [--pr <iid|url> | --issue <iid|url> | --build <id> ...]watch 的三种入口
- 资源入口:通过 PR / Issue 识别与其相关的 NPC 构建。
- 构建入口:直接给定一个或多个构建号进行监控。
- 资源全量入口:监控某个 PR / Issue 关联的所有未完成 NPC 构建。
监控流程
- 获取初始构建列表。
- 轮询刷新构建状态。
- 输出每个构建的当前阶段、状态、开始时间、最近日志摘要。
- 当所有构建进入终态后退出。
- 如遇超时则返回非零退出码。
终态定义
- success
- failed
- canceled
- skipped
状态识别维度
每个被监控的 NPC / 构建建议输出:
- build id
- npc 名称或触发人信息
- pipeline / stage / job
- 当前状态
- 最近一次状态变化时间
- build log url
资源入口的发现策略
你已经确认:可以从 Issue / PR 的 comments 确定对应的 build id。
首版按以下顺序尝试:
- 读取目标 PR / Issue 的评论列表。
- 识别其中真正召唤 NPC 的评论。
- 从评论内容、评论回执或约定格式中提取 build id。
- 将提取出的一个或多个 build id 加入监控集合。
- 如启用“所有未完成构建”模式,则额外拉取该目标下所有未终态 NPC 构建并合并去重。
只有在 comments 无法直接提取 build id 时,才退化为基于时间窗口和 NPC 触发信息的候选匹配策略。
日志刷新策略
- 默认轮询间隔:5 秒。
- 默认总超时:30 分钟。
- 当状态发生变化时立即刷新显示。
- 在运行中状态下,可按固定频率拉取最近几行日志摘要。
输出模式
首版建议提供两种输出模式:
- 默认文本模式:适合命令行直接查看。
--json模式:适合其他系统集成。
默认文本模式示意:
[running] build#123456 npc=代码审查员 stage=analyze job=review
tail:
- cloning repository
- parsing diff
- preparing review context
log: https://cnb.cool/.../build/123456
[success] build#123457 npc=代码审查员 stage=finish job=reply
tail:
- generated final comment
- posted comment successfully
log: https://cnb.cool/.../build/123457建议的命令结构
npc-cli
comment
watch
resolve-target
builds子命令说明
comment: 向 PR / Issue 发送评论。watch: 监控一个或多个 NPC 构建状态。resolve-target: 解析 iid / URL 并输出标准结果,便于调试。builds: 根据目标资源列出识别出的候选构建。
说明:
resolve-target和builds属于开发期辅助命令,便于排错,建议保留。
建议的项目结构
.
├── package.json
├── bin/
│ └── npc-cli.js
├── src/
│ ├── cli.ts
│ ├── commands/
│ │ ├── comment.ts
│ │ ├── watch.ts
│ │ ├── resolve-target.ts
│ │ └── builds.ts
│ ├── config/
│ │ ├── load-env.ts
│ │ └── resolve-context.ts
│ ├── domain/
│ │ ├── target.ts
│ │ ├── comment.ts
│ │ └── build.ts
│ ├── services/
│ │ ├── cnb-api.ts
│ │ ├── cnb-cli.ts
│ │ ├── comment-service.ts
│ │ ├── build-discovery-service.ts
│ │ └── build-watch-service.ts
│ ├── parsers/
│ │ ├── target-parser.ts
│ │ ├── summon-parser.ts
│ │ └── comment-input-parser.ts
│ ├── ui/
│ │ ├── printer.ts
│ │ └── json-printer.ts
│ └── utils/
│ ├── time.ts
│ └── exit-code.ts
├── README.md
└── AGENTS.md技术选型建议
首版建议:
- Node.js 20+
- TypeScript
- CLI 框架:
commander - 环境加载:
dotenv - 输出着色:
picocolors - HTTP 客户端:
undici或原生fetch
为什么这样选
commander足够稳定,适合小中型 CLI。- TypeScript 对“目标解析”和“构建状态模型”更安全。
dotenv可直接处理.env.npc的首层配置加载。- 首版不建议引入复杂 TUI 库,避免 watch 场景下界面管理成本过高。
实现策略建议
阶段 1
先跑通最小闭环:
- 解析 PR / Issue IID 或 URL
- 加载
.env.npc - 从
--file或stdin读取评论内容 - 自动补齐首行 NPC mention
- 发送评论
- 通过构建号监控单个 build
- 拉取构建最近几行日志摘要
阶段 2
扩展到资源关联:
- 从 PR / Issue comments 自动发现 build id
- 支持同时监控多个 build
- 支持监控所有未完成 NPC 构建
- 改善输出格式
阶段 3
增强可用性:
--json- 更精准的 NPC 构建关联规则
- 更完整的错误码与重试机制
错误处理原则
- 参数错误返回退出码
2 - 网络或平台调用失败返回退出码
1 - 监控超时返回退出码
3 - 部分构建失败时返回退出码
4
错误输出中应包含:
- 哪个目标失败
- 使用的是哪种解析方式
- 是 HTTP API 失败还是后备
cnbCLI 失败 - 下一步建议,例如是否补充
CNB_TOKEN或CNB_REPO_SLUG
包名建议
已检查的候选包名:
npc-cli: 已被占用npccli: 当前 registry 查询未找到cnb-npc: 当前 registry 查询未找到
建议:
- npm 包名优先考虑
cnb-npc,语义更清晰。 npccli也可作为备选。- 真正发布前再做一次 registry 复核。
已确认方案
你已经确认首版按下面的边界实现:
comment只负责向目标 PR / Issue 发评论。watch --pr/--issue支持两类能力:- 通过 comments 确定对应 build id 并监控
- 监控该资源下所有未完成 NPC 构建
- 支持同一资源下多个 NPC 构建同时监控。
- 支持跨仓库 URL。
- 首版优先使用 HTTP API。
watch输出状态摘要和最近几行日志摘要。- 包名候选后续在
npccli/cnb-npc中二选一,暂不使用已被占用的npc-cli。 comment正文来源支持--file或stdin。- 若正文首行未
@NPC,则自动插入 NPC mention。 - NPC mention 优先读取
CNB_NPC_NAME,默认值为@XMZZUZHI/SuperNPC(张良)。
仍需在实现时核对的技术点
- comments 到 build id 的具体格式或字段来源。
- 构建日志 API 是否支持按偏移量读取末尾若干行。
- “所有未完成 NPC 构建”是否有直接 API 过滤条件可用。
下一步
如果你确认这版设计没有问题,我下一步就开始实际构建项目,优先顺序是:
- 初始化 TypeScript CLI 工程
- 建立
.env.npc与CNB_*上下文加载 - 实现 PR / Issue IID 与 URL 解析
- 实现 HTTP API 客户端与
comment - 实现
watch --build - 实现
watch --pr/--issue
