[00:00:00 ] $ docker run -d --rm -e TZ='Asia/Shanghai' -e HTTP_PROXY -e HTTPS_PROXY -e NO_PROXY -e http_proxy -e https_proxy -e no_proxy --ulimit nofile=65535:65535 --sysctl net.ipv4.ping_group_range="0 2147483647" --cap-drop CAP_NET_RAW --cgroup-parent=cnb.klo.1joojgph9.001.slice --cpus 8 --cpu-shares 10 -m 16g --memory-swap 16g --runtime=sysbox-runc --name cnb-klo-1joojgph9-001-network-bus --entrypoint= orangeci/network-bus:latest sleep 79200 [00:00:00 +36ms] 8db70d949e831d95a098753e7a3cf32a539a33e0eed379b5b58d873a28676623 [00:00:00 +297ms] exit code: 0, signal: 0, duration: 332ms [00:00:01 +23ms] $ docker pull orangeci/network-bus:latest [00:00:01 +1ms] $ docker run --rm --network host --pid=host --cap-add NET_ADMIN --cap-add SYS_ADMIN -v /var/run/docker.sock:/var/run/docker.sock --name cnb-klo-1joojgph9-001-orange-tc orangeci/orange-tc:latest -c cnb-klo-1joojgph9-001-network-bus -d default:56Mbps -d 10.200.254.0/24:3Gbps -d 169.254.0.0/16:8Gbps -u default:56Mbps -u 10.200.254.0/24:1Gbps -u 169.254.0.0/16:8Gbps -a nsenter -b [00:00:01 +134ms] container: cnb-klo-1joojgph9-001-network-bus [00:00:01 +0ms] mode: [00:00:01 +0ms] action: nsenter [00:00:01 +0ms] batch: true [00:00:01 +0ms] input downloads: [default:56Mbps 10.200.254.0/24:3Gbps 169.254.0.0/16:8Gbps] [00:00:01 +0ms] input uploads: [default:56Mbps 10.200.254.0/24:1Gbps 169.254.0.0/16:8Gbps] [00:00:01 +10ms] done [00:00:01 +41ms] exit code: 0, signal: 0, duration: 186ms [00:00:01 +6ms] $ docker pull orangeci/orange-tc:latest [00:00:01 +13ms] $ mkdir -p $CNB_RUNNER_PIPELINE_CACHE && mkdir -p $CNB_RUNNER_WORKSPACE_PARENT [00:00:01 +2ms] exit code: 0, signal: 0, duration: 2ms [00:00:01 +4ms] $ docker run --rm -e TZ='Asia/Shanghai' -u root --network=host --privileged=true --ulimit nofile=65535:65535 --storage-opt size=256G --shm-size 8g -v /data/orange-ci/git/cnb.cool/1828241703790710784/cache/:/data/orange-ci/git/cnb.cool/1828241703790710784/cache/ -v /data/orange-ci/runner/1828241703790710784/:/yyds:rshared -v /data/orange-ci/runner/:/data/orange-ci/runner/:rshared $ORANGE_ENVS --init --name cnb-klo-1joojgph9-001-git-clone-yyds cnbcool/git-clone-yyds:latest [00:00:01 +250ms] use git username/password [00:00:01 +3ms] git version 2.39.5 [00:00:01 +1ms] file:/etc/gitconfig filter.lfs.clean=git-lfs clean -- %f [00:00:01 +1ms] file:/etc/gitconfig filter.lfs.smudge=git-lfs smudge -- %f [00:00:01 +0ms] file:/etc/gitconfig filter.lfs.process=git-lfs filter-process [00:00:01 +0ms] file:/etc/gitconfig filter.lfs.required=true [00:00:01 +0ms] file:/root/.gitconfig user.name=cnb [00:00:01 +0ms] file:/root/.gitconfig user.email=cnb@noreply.cnb.cool [00:00:01 +0ms] file:/root/.gitconfig credential.helper=/bin/git-credential [00:00:01 +0ms] file:/root/.gitconfig credential.usehttppath=true [00:00:01 +0ms] file:/root/.gitconfig url.https://cnb.cool/.insteadof=git@cnb.cool: [00:00:01 +0ms] file:/root/.gitconfig url.https://cnb.cool/.insteadof=cnb.cool: [00:00:01 +0ms] file:/root/.gitconfig url.https://cnb.cool/.insteadof=http://cnb.cool/ [00:00:01 +0ms] file:/root/.gitconfig core.quotepath=false [00:00:01 +0ms] file:/root/.gitconfig core.autocrlf=false [00:00:01 +0ms] file:/root/.gitconfig core.longpaths=true [00:00:01 +0ms] file:/root/.gitconfig i18n.commitencoding=utf-8 [00:00:01 +0ms] file:/root/.gitconfig merge.directoryrenames=false [00:00:01 +0ms] file:/root/.gitconfig gc.auto=0 [00:00:01 +0ms] file:/root/.gitconfig gc.pruneexpire=never [00:00:01 +0ms] file:/root/.gitconfig lfs.concurrenttransfers=8 [00:00:01 +5ms] 2026-05-16 22:37.21 $ lfs-progress-for-git [00:00:01 +1ms] 2026-05-16 22:37.21 $ flock -xn ${PLUGIN_GIT_CACHE} ${CUR_DIR}/git-clone [00:00:01 +1ms] [.git] show progress... [00:00:01 +1ms] 2026-05-16 22:37.21 $ flock -x ${PLUGIN_GIT_CACHE} echo done [00:00:01 +31ms] done [00:00:01 +1ms] 2026-05-16 22:37.21 $ copy-on-write for /yyds/cnb-klo-1joojgph9-001~rg8/workspace [00:00:01 +222ms] latest: Pulling from orangeci/network-bus [00:00:01 +10ms] Digest: sha256:88737276d46f4115fbce2c748dae79c83944e92254f9e64d1247d71f0cacbf08 [00:00:01 +0ms] Status: Image is up to date for orangeci/network-bus:latest [00:00:01 +1ms] docker.io/orangeci/network-bus:latest [00:00:01 +1ms] exit code: 0, signal: 0, duration: 741ms [00:00:01 +132ms] latest: Pulling from orangeci/orange-tc [00:00:01 +7ms] Digest: sha256:eeddbbb98defbd7db5175879b1fb72ab865c5f7de41ccd0bd1140933e6761132 [00:00:01 +0ms] Status: Image is up to date for orangeci/orange-tc:latest [00:00:01 +2ms] docker.io/orangeci/orange-tc:latest [00:00:01 +1ms] exit code: 0, signal: 0, duration: 690ms [00:00:02 +811ms] Create a snapshot of '/data/orange-ci/git/cnb.cool/1828241703790710784/cache/' in '/yyds/cnb-klo-1joojgph9-001~rg8/workspace' [00:00:02 +3ms] 2026-05-16 22:37.23 $ cd /yyds/cnb-klo-1joojgph9-001~rg8/workspace && /bin/git-checkout [00:00:02 +5ms] 2026-05-16 22:37.23 $ git remote set-url origin "https://cnb.cool/cnb/feedback.git" [00:00:02 +2ms] 2026-05-16 22:37.23 $ git remote -v [00:00:02 +2ms] origin https://cnb.cool/cnb/feedback.git (fetch) [00:00:02 +0ms] origin https://cnb.cool/cnb/feedback.git (push) [00:00:02 +2ms] 2026-05-16 22:37.23 $ git rev-parse HEAD [00:00:02 +1ms] 58b7334bdd90043a4b20615e3819d7ca01ffc16d [00:00:02 +2ms] 2026-05-16 22:37.23 $ skip fetch due to fetched in cow [00:00:02 +1ms] 2026-05-16 22:37.23 $ skip checkout due to checkouted in cow [00:00:02 +6ms] 2026-05-16 22:37.23 $ done [00:00:02 +41ms] exit code: 0, signal: 0, duration: 1.5s [00:00:02 +14ms] $ docker pull cnbcool/git-clone-yyds:latest [00:00:02 +13ms] $ docker pull cnbcool/default-npc:latest [00:00:03 +680ms] latest: Pulling from cnbcool/git-clone-yyds [00:00:03 +13ms] Digest: sha256:b7e9dd6ad3e970479dd6f1fda744933fae3915ff7fc4dd0e071e5c73fa18747c [00:00:03 +0ms] Status: Image is up to date for cnbcool/git-clone-yyds:latest [00:00:03 +2ms] docker.io/cnbcool/git-clone-yyds:latest [00:00:03 +1ms] exit code: 0, signal: 0, duration: 709ms [00:00:03 +43ms] latest: Pulling from cnbcool/default-npc [00:00:03 +95ms] 9b02e9fcb401: Already exists [00:00:03 +6ms] 2d6acbc8e716: Pulling fs layer [00:00:03 +0ms] 17245302a67c: Pulling fs layer [00:00:03 +0ms] 3b703c5d9722: Pulling fs layer [00:00:03 +0ms] 2f26afb99d23: Pulling fs layer [00:00:03 +0ms] 112e43985503: Pulling fs layer [00:00:03 +0ms] 112e43985503: Waiting [00:00:03 +0ms] 2f26afb99d23: Waiting [00:00:03 +176ms] 2d6acbc8e716: Download complete [00:00:03 +17ms] 2d6acbc8e716: Pull complete [00:00:03 +19ms] 3b703c5d9722: Download complete [00:00:03 +115ms] 2f26afb99d23: Verifying Checksum [00:00:03 +0ms] 2f26afb99d23: Download complete [00:00:04 +328ms] 17245302a67c: Verifying Checksum [00:00:04 +0ms] 17245302a67c: Download complete [00:00:05 +1.5s] 17245302a67c: Pull complete [00:00:05 +74ms] 3b703c5d9722: Pull complete [00:00:05 +26ms] 2f26afb99d23: Pull complete [00:00:08 +2.7s] 112e43985503: Verifying Checksum [00:00:08 +0ms] 112e43985503: Download complete [00:00:15 +6.6s] 112e43985503: Pull complete [00:00:15 +11ms] Digest: sha256:1378d8e8e2b25b850ae5d0727a412f596195c3089157287063fd5e3ce3c4d499 [00:00:15 +4ms] Status: Downloaded newer image for cnbcool/default-npc:latest [00:00:15 +1ms] docker.io/cnbcool/default-npc:latest [00:00:15 +2ms] exit code: 0, signal: 0, duration: 12.5s [00:00:15 +683ms] $ command -v helm > /dev/null && helm registry login -u ${CNB_TOKEN_USER_NAME} --password-stdin ${CNB_HELM_REGISTRY} || true [00:00:16 +74ms] exit code: 0, signal: 0, duration: 73ms [00:00:16 +227ms] $ echo ~ [00:00:16 +59ms] /root [00:00:16 +2ms] exit code: 0, signal: 0, duration: 60ms [00:00:16 +5ms] $ pwd [00:00:16 +65ms] /workspace [00:00:16 +2ms] exit code: 0, signal: 0, duration: 67ms [00:00:16 +5ms] $ cat 'AGENTS.md' 2>/dev/null [00:00:16 +71ms] exit code: 1, signal: -1, duration: 70ms [00:00:16 +4ms] $ cat 'CODEBUDDY.md' 2>/dev/null [00:00:16 +70ms] exit code: 1, signal: -1, duration: 69ms [00:00:16 +4ms] $ test -d ~/'.agents/skills' && echo 1 || echo 0 [00:00:16 +67ms] 1 [00:00:16 +3ms] exit code: 0, signal: 0, duration: 69ms [00:00:16 +5ms] $ cat ~/'.agents/skills/SKILL.md' 2>/dev/null [00:00:16 +62ms] exit code: 1, signal: -1, duration: 63ms [00:00:16 +5ms] $ ls -1A ~/'.agents/skills' 2>/dev/null [00:00:16 +67ms] cnb-api [00:00:16 +0ms] cnb-knowledge-base [00:00:16 +0ms] cnb-pipeline [00:00:16 +1ms] code-commit [00:00:16 +0ms] code-review [00:00:16 +0ms] knowledge-base [00:00:16 +0ms] markitdown [00:00:16 +0ms] npc-delegate [00:00:16 +0ms] npc-search [00:00:16 +0ms] pr-diff [00:00:16 +0ms] pr-summary [00:00:16 +0ms] tapd-resource-fetcher [00:00:16 +0ms] text-path-converter [00:00:16 +0ms] upload-attachment [00:00:16 +1ms] exit code: 0, signal: 0, duration: 69ms [00:00:16 +6ms] $ test -d ~/'.agents/skills/cnb-api' && echo dir || (test -f ~/'.agents/skills/cnb-api' && echo file || echo other) [00:00:16 +63ms] dir [00:00:16 +2ms] exit code: 0, signal: 0, duration: 65ms [00:00:16 +6ms] $ cat ~/'.agents/skills/cnb-api/SKILL.md' 2>/dev/null [00:00:16 +59ms] --- [00:00:16 +0ms] name: cnb-api [00:00:16 +0ms] description: CNB 平台交互命令,支持仓库、Issue、PR、流水线、制品库等操作。 [00:00:16 +0ms] --- [00:00:16 +0ms] [00:00:16 +0ms] # cnb-api [00:00:16 +0ms] [00:00:16 +0ms] 操作 CNB 平台资源的 CLI 工具。 [00:00:16 +0ms] [00:00:16 +0ms] ## 快捷命令 [00:00:16 +0ms] [00:00:16 +0ms] issues: [00:00:16 +0ms] - `cnb issues get` — 获取当前 Issue 详情 [00:00:16 +0ms] - `cnb issues list-comments` — 列出当前 Issue 评论 [00:00:16 +0ms] - `cnb issues comment --body '内容'` — 发表评论到当前 Issue [00:00:16 +0ms] - `cnb issues close` — 关闭当前 Issue [00:00:16 +0ms] - `cnb issues open` — 打开当前 Issue [00:00:16 +0ms] - `cnb issues list-labels` — 列出当前 Issue 标签 [00:00:16 +0ms] - `cnb issues add-labels --labels bug --labels feature` — 添加标签到当前 Issue [00:00:16 +0ms] - `cnb issues list-assignees` — 查看当前 Issue 处理人 [00:00:16 +0ms] - `cnb issues add-assignees --assignees username` — 添加处理人到当前 Issue [00:00:16 +0ms] - `cnb issues upload-file --file 文件路径` — 上传文件到当前 Issue [00:00:16 +0ms] - `cnb issues upload-image --file 图片路径` — 上传图片到当前 Issue [00:00:16 +0ms] [00:00:16 +0ms] pulls: [00:00:16 +0ms] - `cnb pulls get` — 获取当前 PR 详情 [00:00:16 +0ms] - `cnb pulls list-files` — 列出当前 PR 变更文件 [00:00:16 +0ms] - `cnb pulls list-commits` — 列出当前 PR 提交记录 [00:00:16 +0ms] - `cnb pulls list-comments` — 列出当前 PR 评论 [00:00:16 +0ms] - `cnb pulls comment --body '内容'` — 发表 PR 评论 [00:00:16 +0ms] - `cnb pulls list-labels` — 列出当前 PR 标签 [00:00:16 +0ms] - `cnb pulls add-labels --labels ready --labels approved` — 添加标签到当前 PR [00:00:16 +0ms] - `cnb pulls check-status` — 获取当前 PR 的 CI 状态 [00:00:16 +0ms] - `cnb pulls get-ci-logs` — 获取当前 PR 的 CI 构建日志 [00:00:16 +0ms] - `cnb pulls list-reviews` — 查看当前当前的评审列表 [00:00:16 +0ms] - `cnb pulls list-assignees` — 查看当前 PR 处理人 [00:00:16 +0ms] - `cnb pulls upload-file --file 文件路径` — 上传文件到当前 PR [00:00:16 +0ms] - `cnb pulls upload-image --file 图片路径` — 上传图片到当前 PR [00:00:16 +0ms] [00:00:16 +0ms] 注意事项: [00:00:16 +0ms] - **链接结构**:Issue 链接格式为 `//-/issues/`,PR 链接格式为 `//-/pulls/`。在生成或引用链接时请遵循此结构。 [00:00:16 +0ms] - **参数自动识别**:快捷命令中的 Issue/PR 编号会自动从环境变量识别,无需额外传递。 [00:00:16 +0ms] - **默认仅需摘要**:默认会精简响应输出结果,只返回核心字段。添加 `--verbose` 输出完整数据。 [00:00:16 +1ms] - **单引号传参**:传递多行文本参数时,使用单引号可防止命令注入攻击,并减少不必要的转义。 [00:00:16 +0ms] - **快捷命令适用范围**: 快捷命令只能操作当前仓库的当前 Issue/PR,跨仓库或跨编号操作请参考 `更多 API`。 [00:00:16 +0ms] - **npc提及和召唤的区别**: 评论中直接 @npc 会召唤 npc 干活,如果只提及不召唤,应该去掉 `@` 符号,或使用反引号包裹 `@npc`。 [00:00:16 +0ms] [00:00:16 +0ms] ## 更多 API [00:00:16 +0ms] [00:00:16 +0ms] 1. `cnb --help` 查看所有模块 [00:00:16 +0ms] 2. `cnb --help` 查看模块下的工具列表 [00:00:16 +0ms] 3. `cnb --help` 查看工具参数 [00:00:16 +1ms] exit code: 0, signal: 0, duration: 61ms [00:00:16 +7ms] $ test -d ~/'.agents/skills/cnb-knowledge-base' && echo dir || (test -f ~/'.agents/skills/cnb-knowledge-base' && echo file || echo other) [00:00:16 +58ms] dir [00:00:16 +2ms] exit code: 0, signal: 0, duration: 60ms [00:00:16 +5ms] $ cat ~/'.agents/skills/cnb-knowledge-base/SKILL.md' 2>/dev/null [00:00:17 +63ms] --- [00:00:17 +0ms] name: cnb-knowledge-base [00:00:17 +0ms] description: 查询 CNB 平台官方文档,包括代码托管、制品库、AI 助手、云原生构建(CI/CD)、开发者工具等。 [00:00:17 +0ms] --- [00:00:17 +0ms] [00:00:17 +0ms] # CNB 知识库 [00:00:17 +0ms] [00:00:17 +0ms] 自动查询 CNB 云原生构建平台官方文档,为用户提供准确的使用指引和操作说明。 [00:00:17 +0ms] [00:00:17 +0ms] ## 文档来源 [00:00:17 +0ms] [00:00:17 +0ms] > 下方 URL 中的 `${CNB_WEB_PROTOCOL}` 和 `${CNB_WEB_HOST}` 为环境变量,使用前先 `echo` 获取实际值再拼接。 [00:00:17 +0ms] [00:00:17 +0ms] CNB 官方文档站点:`${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}` [00:00:17 +0ms] [00:00:17 +0ms] 提供两种文档索引: [00:00:17 +0ms] [00:00:17 +0ms] | 索引 | URL | 说明 | [00:00:17 +0ms] |------|-----|------| [00:00:17 +0ms] | 增量索引 | `${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}/zh/llms.txt` | 文档目录索引,包含所有文档的标题和路径链接 | [00:00:17 +0ms] | 全量文档 | `${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}/zh/llms-full.txt` | 包含所有文档的完整内容(体积较大) | [00:00:17 +0ms] [00:00:17 +0ms] ## 文档覆盖范围 [00:00:17 +0ms] [00:00:17 +0ms] CNB 文档涵盖以下主要领域: [00:00:17 +0ms] [00:00:17 +0ms] - **指南**:创建仓库、Git 认证、迁移工具、角色权限、访问令牌、部署令牌 [00:00:17 +0ms] - **代码托管**:密钥仓库、元数据、ISSUE 模板、分类标签、UI 定制 [00:00:17 +0ms] - **制品库**:Docker、Helm、Maven、npm、PyPI、Cargo、Nuget、Composer、ohpm 等 12 种制品库 [00:00:17 +0ms] - **AI 助手**:AI 助手简介、知识库、MCP Server、Code Wiki [00:00:17 +0ms] - **云原生开发**:开发环境、端口预览、IDE 客户端(VSCode/Cursor/JetBrains)、容器模式 [00:00:17 +0ms] - **云原生构建**:流水线配置、触发规则、语法手册、构建环境、环境变量、插件、缓存、定时任务、部署流程 [00:00:17 +0ms] - **开发者**:徽章、Open API [00:00:17 +0ms] - **OAuth 授权**:用户授权、OAuth 应用创建 [00:00:17 +0ms] - **其他**:FAQ、定价、SLA、任务集等 [00:00:17 +0ms] [00:00:17 +0ms] ## 使用流程 [00:00:17 +0ms] [00:00:17 +0ms] ### 第一步:分析用户问题 [00:00:17 +0ms] [00:00:17 +0ms] 仔细分析用户提出的问题,提取关键词,判断用户想了解哪个领域的文档。 [00:00:17 +0ms] [00:00:17 +0ms] ### 第二步:获取文档索引 [00:00:17 +0ms] [00:00:17 +0ms] 使用 WebFetch 获取文档目录索引: [00:00:17 +0ms] [00:00:17 +0ms] ``` [00:00:17 +0ms] WebFetch url: ${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}/zh/llms.txt [00:00:17 +0ms] prompt: 列出所有文档的标题和路径链接,帮我找到与「{用户问题的关键词}」相关的文档路径 [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] ### 第三步:获取具体文档内容 [00:00:17 +0ms] [00:00:17 +0ms] 根据索引中匹配到的文档路径,拼接完整 URL 并获取文档内容: [00:00:17 +0ms] [00:00:17 +0ms] ``` [00:00:17 +0ms] WebFetch url: ${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}{文档路径} [00:00:17 +0ms] prompt: 提取这篇文档的完整内容,保留代码示例和配置说明 [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] **注意**:索引中的路径格式为 `/zh/category/topic.md`,拼接后完整 URL 为 `${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}/zh/category/topic.md`。 [00:00:17 +0ms] [00:00:17 +0ms] ### 第四步:整理并回答 [00:00:17 +0ms] [00:00:17 +0ms] 将获取到的文档内容整理后,根据用户问题: [00:00:17 +0ms] 1. 提取与用户问题最相关的内容 [00:00:17 +0ms] 2. 保留重要的代码示例和配置片段 [00:00:17 +0ms] 3. 简明呈现给用户 [00:00:17 +0ms] 4. 内容较长时适当精简,并附原文档链接 [00:00:17 +0ms] [00:00:17 +0ms] ## 注意事项 [00:00:17 +0ms] [00:00:17 +0ms] - 如果增量索引未找到相关文档,可尝试全量文档 `${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}/zh/llms-full.txt` [00:00:17 +0ms] - 单个文档无法完全回答时,可获取多个文档综合回答 [00:00:17 +0ms] - 始终基于官方文档回答,不臆造信息 [00:00:17 +2ms] - 附带文档来源链接 [00:00:17 +0ms] exit code: 0, signal: 0, duration: 65ms [00:00:17 +13ms] $ test -d ~/'.agents/skills/cnb-pipeline' && echo dir || (test -f ~/'.agents/skills/cnb-pipeline' && echo file || echo other) [00:00:17 +64ms] dir [00:00:17 +2ms] exit code: 0, signal: 0, duration: 66ms [00:00:17 +4ms] $ cat ~/'.agents/skills/cnb-pipeline/SKILL.md' 2>/dev/null [00:00:17 +58ms] --- [00:00:17 +0ms] name: cnb-pipeline [00:00:17 +0ms] description: 编写/修改 .cnb.yml 配置,诊断流水线失败原因,优化构建性能。 [00:00:17 +0ms] supports: cnb [00:00:17 +0ms] --- [00:00:17 +0ms] [00:00:17 +0ms] # CNB 流水线配置与诊断 [00:00:17 +0ms] [00:00:17 +0ms] 生成/修改 `.cnb.yml` 配置文件,诊断流水线失败,优化构建性能。 [00:00:17 +0ms] [00:00:17 +0ms] > 本文档 URL 中的 `${CNB_WEB_PROTOCOL:-https}` 和 `${CNB_WEB_HOST:-cnb.cool}` 为环境变量,使用前先 `echo` 获取实际值再拼接。 [00:00:17 +0ms] [00:00:17 +0ms] ## 模式判定 [00:00:17 +0ms] [00:00:17 +0ms] 根据用户意图自动选择工作模式: [00:00:17 +0ms] [00:00:17 +0ms] - **配置模式**(写/改流水线)→ 走下方「配置工作流程」 [00:00:17 +0ms] - **诊断模式**(失败/报错/慢/优化)→ 走下方「诊断工作流程」 [00:00:17 +0ms] [00:00:17 +0ms] ## 配置工作流程 [00:00:17 +0ms] [00:00:17 +0ms] 1. **了解需求** -- 明确触发分支、事件、构建语言/环境、构建步骤、特殊需求。信息充足可直接生成。 [00:00:17 +0ms] 2. **查看现有配置** -- 修改场景下先读取 `.cnb.yml` 和 `.ci/` 目录。 [00:00:17 +0ms] 3. **按需加载文档** -- 遇到不确定的语法细节时,先 `echo` 获取环境变量拼接文档 URL,再用 WebFetch 加载对应的深入文档链接;也可读取本 skill 的 `references/` 子目录下的参考文件。 [00:00:17 +0ms] 4. **生成配置** -- 按下方语法速查生成完整可运行的配置。 [00:00:17 +0ms] 5. **校验(必须)** -- 每次生成/修改后必须校验通过才能展示给用户。 [00:00:17 +1ms] 6. **解释配置** -- 简要说明关键部分。 [00:00:17 +0ms] [00:00:17 +0ms] ### 校验命令 [00:00:17 +0ms] [00:00:17 +0ms] ```bash [00:00:17 +0ms] [ -d validator/node_modules ] || npm install --prefix validator [00:00:17 +0ms] node validator/validate.js .cnb.yml [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] 两项均通过(`YAML 语法` + `Schema`)才算有效。`--refresh` 可强制更新 Schema 缓存。 [00:00:17 +0ms] [00:00:17 +0ms] ## 诊断工作流程 [00:00:17 +0ms] [00:00:17 +0ms] > 详细流程见 `references/diagnose-guide.md`,依赖 [cnb-api] skill。 [00:00:17 +0ms] [00:00:17 +0ms] 1. **确定构建 sn**(可选)-- 默认不传,CLI 自动解析;需指定时从 `cnb pulls check-status` 对应检查项的 `target_url` 末段取(勿用 `context` 字段)。 [00:00:17 +0ms] 2. **获取数据**: [00:00:17 +0ms] - 失败诊断:`cnb pulls get-ci-logs`(自动定位失败构建;也可加 `--sn` 指定) [00:00:17 +0ms] - 性能优化:通过 `cnb build --help` / `cnb pulls --help` 探索可用命令,获取 Stage 耗时与慢 Stage 日志 [00:00:17 +0ms] 3. **分析并输出报告** -- 判定失败类型或耗时瓶颈,给出修复/优化建议。配置相关问题结合语法速查分析。 [00:00:17 +0ms] [00:00:17 +0ms] --- [00:00:17 +0ms] [00:00:17 +0ms] ## 语法速查 [00:00:17 +0ms] [00:00:17 +0ms] ### 层级结构 [00:00:17 +0ms] [00:00:17 +0ms] ``` [00:00:17 +0ms] 分支 (main / "feature/*" / "$") [00:00:17 +0ms] └── 事件 (push / pull_request / tag_push ...) [00:00:17 +0ms] └── Pipeline(多条并发) [00:00:17 +0ms] └── Stage(顺序执行) [00:00:17 +0ms] └── Job(数组串行 / 对象并行) [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] ### 触发分支 [00:00:17 +0ms] [00:00:17 +0ms] ```yaml [00:00:17 +0ms] main: # 精确匹配 [00:00:17 +0ms] "feature/*": # 通配符 [00:00:17 +0ms] "(main|develop)": # 或匹配 [00:00:17 +0ms] "**/!(main|develop)": # 排除 [00:00:17 +0ms] "**": # 所有分支 [00:00:17 +0ms] "$": # 兜底(未被 glob 匹配的分支 + tag_push/issue 等) [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] ### 常用触发事件 [00:00:17 +0ms] [00:00:17 +0ms] | 事件 | 时机 | [00:00:17 +0ms] |------|------| [00:00:17 +0ms] | `push` | 推送代码 | [00:00:17 +0ms] | `pull_request` | PR 创建/重新打开/源分支 push | [00:00:17 +0ms] | `tag_push` | 推送 Tag | [00:00:17 +0ms] | `"crontab: 30 5 * * *"` | 定时任务 | [00:00:17 +0ms] | `web_trigger` / `api_trigger` | 手动/API 触发 | [00:00:17 +0ms] [00:00:17 +0ms] > 完整事件列表及代码版本说明见 `references/syntax-reference.md` 或在线文档:${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}/zh/build/trigger-rule.md [00:00:17 +0ms] [00:00:17 +0ms] ### Pipeline 骨架 [00:00:17 +0ms] [00:00:17 +0ms] ```yaml [00:00:17 +0ms] main: [00:00:17 +0ms] push: [00:00:17 +0ms] - name: ci [00:00:17 +0ms] runner: { cpus: 2 } [00:00:17 +0ms] docker: [00:00:17 +0ms] image: node:20 # 或 build (Dockerfile) 或 devcontainer [00:00:17 +0ms] services: [docker] # Docker-in-Docker [00:00:17 +0ms] env: { NODE_ENV: production } [00:00:17 +0ms] imports: [./secrets.yml] [00:00:17 +0ms] stages: [...] [00:00:17 +0ms] failStages: [...] # 仅失败时执行 [00:00:17 +0ms] endStages: [...] # 始终执行 [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] ### Stage [00:00:17 +0ms] [00:00:17 +0ms] ```yaml [00:00:17 +0ms] stages: [00:00:17 +0ms] - name: install [00:00:17 +0ms] script: npm ci [00:00:17 +0ms] timeout: 10m [00:00:17 +0ms] retry: 2 [00:00:17 +0ms] allowFailure: true [00:00:17 +0ms] ifModify: ["**/*.ts"] [00:00:17 +0ms] image: node:18 # 覆盖 Pipeline 镜像 [00:00:17 +0ms] env: { KEY: value } [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] ### Job(三种类型) [00:00:17 +0ms] [00:00:17 +0ms] ```yaml [00:00:17 +0ms] # 脚本任务 [00:00:17 +0ms] - name: build [00:00:17 +0ms] script: npm run build [00:00:17 +0ms] [00:00:17 +0ms] # 插件任务 [00:00:17 +0ms] - name: docker-push [00:00:17 +0ms] image: plugins/docker [00:00:17 +0ms] settings: { repo: myrepo/app, tags: [$CNB_BRANCH] } [00:00:17 +0ms] [00:00:17 +0ms] # 内置任务 [00:00:17 +0ms] - name: trigger [00:00:17 +0ms] type: cnb:trigger [00:00:17 +0ms] options: { slug: org/other-repo, branch: main, event: api_trigger } [00:00:17 +0ms] exports: { sn: BUILD_SN } [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] **并发模式**:`jobs` 为数组时串行,为对象时并行。 [00:00:17 +0ms] [00:00:17 +0ms] ### 环境变量(速查) [00:00:17 +0ms] [00:00:17 +0ms] ```yaml [00:00:17 +0ms] env: { MY_VAR: value } # 声明 [00:00:17 +0ms] imports: [./secrets.yml] # 导入密钥仓库 [00:00:17 +0ms] exports: { VERSION: MY_VERSION } # 跨 Stage 传递 [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] 脚本中输出 `##[set-output key=value]` 可导出变量。 [00:00:17 +0ms] [00:00:17 +0ms] > 详细用法见 `references/env-variables.md` 或在线文档:${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}/zh/build/env.md [00:00:17 +0ms] [00:00:17 +0ms] ### 常用内置变量 [00:00:17 +0ms] [00:00:17 +0ms] | 变量 | 说明 | [00:00:17 +0ms] |------|------| [00:00:17 +0ms] | `CNB_BRANCH` | 分支/Tag 名 | [00:00:17 +0ms] | `CNB_COMMIT` / `CNB_COMMIT_SHORT` | Commit SHA | [00:00:17 +0ms] | `CNB_REPO_SLUG` | 仓库路径 | [00:00:17 +0ms] | `CNB_BUILD_ID` | 构建 ID | [00:00:17 +0ms] | `CNB_TOKEN` | 构建凭证 | [00:00:17 +0ms] | `CNB_EVENT` | 事件名 | [00:00:17 +0ms] | `CNB_PULL_REQUEST_IID` | PR 编号 | [00:00:17 +0ms] [00:00:17 +0ms] > 完整列表:${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}/zh/build/build-in-env.md [00:00:17 +0ms] [00:00:17 +0ms] ### Include 和 !reference [00:00:17 +0ms] [00:00:17 +0ms] ```yaml [00:00:17 +0ms] include: [00:00:17 +0ms] - .ci/build.yml # 本地 [00:00:17 +0ms] - "${CNB_WEB_ENDPOINT:-https://cnb.cool}/org/tpl/-/blob/main/ci.yml" # 远程 [00:00:17 +0ms] [00:00:17 +0ms] docker: !reference [.docker-config] # 引用对象 [00:00:17 +0ms] stages: !reference [.common-pipeline, stages] # 多级路径引用 [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] ### 数据卷缓存 [00:00:17 +0ms] [00:00:17 +0ms] ```yaml [00:00:17 +0ms] docker: [00:00:17 +0ms] volumes: [00:00:17 +0ms] - node_modules # cow(默认,写时复制) [00:00:17 +0ms] - cache:/root/.npm:rw # 读写 [00:00:17 +0ms] - shared:/data:data # 临时数据卷(Pipeline 内共享) [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] --- [00:00:17 +0ms] [00:00:17 +0ms] ## 详细参考文档 [00:00:17 +0ms] [00:00:17 +0ms] 需要深入了解某个主题时,读取以下文件: [00:00:17 +0ms] [00:00:17 +0ms] | 文件 | 内容 | [00:00:17 +0ms] |------|------| [00:00:17 +0ms] | `references/syntax-reference.md` | 完整触发事件列表、Pipeline/Stage/Job 全部字段、变量替换规则、include 合并规则 | [00:00:17 +0ms] | `references/builtin-tasks.md` | 所有内置任务类型(cnb:trigger、git:release 等)及参数说明 | [00:00:17 +0ms] | `references/env-variables.md` | 环境变量声明/导入/导出/传递的完整用法 | [00:00:17 +0ms] | `references/best-practices.md` | YAML 锚点复用、按功能拆分 .ci/ 目录、Pipeline 编排等最佳实践 | [00:00:17 +0ms] | `references/diagnose-guide.md` | CI 失败诊断流程、性能优化分析流程、失败类型判定表、常见优化点 | [00:00:17 +0ms] [00:00:17 +0ms] --- [00:00:17 +0ms] [00:00:17 +0ms] ## 注意事项 [00:00:17 +0ms] [00:00:17 +0ms] 1. **YAML 缩进**用空格,不用 Tab [00:00:17 +0ms] 2. **分支名含特殊字符**需引号包裹:`"feature/*"` [00:00:17 +0ms] 3. **并发模型**:同事件多 Pipeline 并发;Pipeline 内 Stage 顺序;Stage 内 jobs 数组串行、对象并行 [00:00:17 +1ms] 4. **PR 安全限制**:PR 类事件 `CNB_TOKEN` 权限受限,敏感操作放 `push` / `pull_request.target` / `tag_push` [00:00:17 +0ms] 5. **YAML 锚点仅限单文件**:跨文件用 `!reference`(只能引用值,不能合并展开) [00:00:17 +0ms] 6. **`!reference` 引用键名必须全局唯一**:跨文件共享时加文件/模块前缀避免冲突 [00:00:17 +0ms] 7. **变量值上限 100KiB**,变量名只能含字母/数字/下划线且不能数字开头 [00:00:17 +0ms] exit code: 0, signal: 0, duration: 60ms [00:00:17 +5ms] $ test -d ~/'.agents/skills/code-commit' && echo dir || (test -f ~/'.agents/skills/code-commit' && echo file || echo other) [00:00:17 +58ms] dir [00:00:17 +2ms] exit code: 0, signal: 0, duration: 59ms [00:00:17 +6ms] $ cat ~/'.agents/skills/code-commit/SKILL.md' 2>/dev/null [00:00:17 +67ms] --- [00:00:17 +0ms] name: code-commit [00:00:17 +0ms] description: 编写代码、提交推送并创建 PR,适用于功能开发、Bug 修复、重构优化等场景。 [00:00:17 +0ms] --- [00:00:17 +0ms] [00:00:17 +0ms] # 自动编码并提交推送 [00:00:17 +0ms] [00:00:17 +0ms] 根据用户需求选择: [00:00:17 +0ms] 1. 新建分支 -> 编写代码 -> 推送代码 -> 并创建 PR [00:00:17 +0ms] 2. 切换到 PR 源分支 -> 编写代码 -> 推送代码更新 PR [00:00:17 +0ms] [00:00:17 +0ms] ## 步骤 [00:00:17 +0ms] [00:00:17 +0ms] ### 1. 理解需求 [00:00:17 +0ms] [00:00:17 +0ms] 分析用户输入,明确要修改的文件、功能/Bug 描述、目标分支(PR 的 base)。 [00:00:17 +0ms] 如需了解项目结构,直接在当前工作区读取代码。如需了解 PR 变更,可使用 pr-diff Skill。 [00:00:17 +0ms] [00:00:17 +0ms] ### 2. 判断场景并准备分支 [00:00:17 +0ms] [00:00:17 +0ms] 根据触发场景切换到正确的工作分支: [00:00:17 +0ms] [00:00:17 +0ms] - **PR 评论触发**(`CNB_PULL_REQUEST_IID` 存在):在此分支上继续修改 [00:00:17 +0ms] ```bash [00:00:17 +0ms] git checkout "$CNB_PULL_REQUEST_BRANCH" [00:00:17 +0ms] git pull origin "$CNB_PULL_REQUEST_BRANCH" [00:00:17 +0ms] ``` [00:00:17 +0ms] - **ISSUE 评论触发** PR 已存在,则切换到 PR 源分支继续开发 [00:00:17 +0ms] ```bash [00:00:17 +0ms] git checkout && git pull [00:00:17 +0ms] ``` [00:00:17 +0ms] - **ISSUE 评论触发** PR 不存在,则基于目标分支创建新分支 `auto/{关键词1}-{关键词2}-{4位随机后缀}` [00:00:17 +0ms] ```bash [00:00:17 +0ms] git checkout -b auto/{关键词1}-{关键词2}-$(openssl rand -hex 2) [00:00:17 +0ms] ``` [00:00:17 +0ms] > ⚠️ **分支命名精简规则**: [00:00:17 +0ms] > - `{关键词}`:从 ISSUE 标题/描述中提取 **2 个核心关键词**(名词或动词),用短横线连接,每个关键词不超过 2 个英文单词 [00:00:17 +0ms] > - `{随机后缀}`:固定 4 位十六进制,用 `$(openssl rand -hex 2)` 生成 [00:00:17 +0ms] > - **总长度控制**:分支名 `auto/` 之后的部分不超过 20 个字符 [00:00:17 +0ms] > - **示例**:`auto/optimize-skill-3a7f`、`auto/login-error-b2c1` [00:00:17 +0ms] [00:00:17 +0ms] ### 3. 编写代码 [00:00:17 +0ms] [00:00:17 +0ms] 直接在工作区中读取和修改文件,实现代码变更。遵循项目已有的代码风格,确保 import/依赖完整。 [00:00:17 +0ms] [00:00:17 +0ms] ### 4. 验证与提交 [00:00:17 +0ms] [00:00:17 +0ms] ```bash [00:00:17 +0ms] # 查看变更概览 [00:00:17 +0ms] git diff --stat [00:00:17 +0ms] # 如有构建/lint 命令则执行验证 [00:00:17 +0ms] # 暂存并提交 [00:00:17 +0ms] git add -A [00:00:17 +0ms] git commit -m "{类型}: {简短描述}" [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] 类型:`feat`(新功能) / `fix`(修复) / `refactor`(重构) / `docs`(文档) / `chore`(其他) [00:00:17 +0ms] [00:00:17 +0ms] ### 5. 推送变更并判断是否需要创建 PR [00:00:17 +0ms] [00:00:17 +0ms] ```bash [00:00:17 +0ms] # 推送当前分支 [00:00:17 +0ms] git push origin HEAD [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] 根据推送输出判断是否已有 PR: [00:00:17 +0ms] [00:00:17 +0ms] - **已有 PR**(输出包含 `There is already has pull request`):跳过创建 PR,直接在评论中告知用户 [00:00:17 +0ms] - **无 PR**(输出包含 `Create a pull request` 或 `new branch`):走第 6 步创建 PR [00:00:17 +0ms] [00:00:17 +0ms] > ⚠️ 只有新建分支且推送后确认无 PR 时,才执行第 6 步。 [00:00:17 +0ms] [00:00:17 +0ms] **示例 1 — 已有 PR,跳过创建:** [00:00:17 +0ms] ``` [00:00:17 +0ms] $ git push origin HEAD [00:00:17 +0ms] remote: [00:00:17 +0ms] remote: There is already has pull request for 'fix/optimize-code-commit-skill' by visiting: [00:00:17 +0ms] remote: [00:00:17 +0ms] remote: https://cnb.cool/cnb/skills/cnb-skill/-/pulls/140 [00:00:17 +0ms] remote: [00:00:17 +0ms] To https://cnb.cool/cnb/skills/cnb-skill.git [00:00:17 +0ms] e3d8f95..639bd55 HEAD -> fix/optimize-code-commit-skill [00:00:17 +1ms] [00:00:17 +0ms] # 输出包含 "There is already has pull request" → 已有 PR,不再创建 [00:00:17 +0ms] # 在评论中告知用户:PR 已存在,代码已推送到 PR #140 [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] **示例 2 — 无 PR,需要创建:** [00:00:17 +0ms] ``` [00:00:17 +0ms] $ git push origin HEAD [00:00:17 +0ms] remote: [00:00:17 +0ms] remote: Create a pull request for 'fix/optimize-code-commit-skill' to 'main' by visiting: [00:00:17 +0ms] remote: [00:00:17 +0ms] remote: https://cnb.cool/cnb/skills/cnb-skill/-/compare/main...fix/optimize-code-commit-skill [00:00:17 +0ms] remote: [00:00:17 +0ms] To https://cnb.cool/cnb/skills/cnb-skill.git [00:00:17 +0ms] * [new branch] fix/optimize-code-commit-skill -> fix/optimize-code-commit-skill [00:00:17 +0ms] [00:00:17 +0ms] # 输出包含 "Create a pull request" → 无 PR,需要走第 6 步创建 [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] ### 6. 创建 PR(仅推送后确认无 PR 时执行) [00:00:17 +0ms] [00:00:17 +0ms] ```bash [00:00:17 +0ms] # 创建 PR [00:00:17 +0ms] cnb pulls post-pull --repo "$CNB_REPO_SLUG" \ [00:00:17 +0ms] --base "$CNB_DEFAULT_BRANCH" \ [00:00:17 +0ms] --head "$(git branch --show-current)" \ [00:00:17 +0ms] --title "{类型}: {简短描述}" \ [00:00:17 +0ms] --body "{变更目的与主要改动点}\n\nRef #{ISSUE编号}" [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] > ⚠️ **必须引用 Issue**:由 ISSUE 评论触发创建 PR 时,PR body 末尾必须包含 `Ref #{ISSUE编号}`(如 `Ref #149`),这样 Issue 侧边栏才会自动显示关联的 PR。ISSUE 编号从环境变量 `$CNB_ISSUE_IID` 获取。 [00:00:17 +0ms] [00:00:17 +0ms] ## 注意事项 [00:00:17 +0ms] [00:00:17 +0ms] - 编码前先理解项目结构和代码风格 [00:00:17 +0ms] - 需求不明确或范围过大时,先在评论中确认再执行 [00:00:17 +0ms] - 不修改无关文件,推送前确认变更正确 [00:00:17 +0ms] - 生成/修改 `.cnb.yml` 文件时需使用 cnb-pipeline skill 技能 [00:00:17 +0ms] [00:00:17 +0ms] ## 禁止的操作 [00:00:17 +0ms] [00:00:17 +0ms] - ❌ PR 不存在时,禁止在默认分支上修改代码,需新建分支并创建 PR [00:00:17 +1ms] - ❌ `git push --force`(不要强制推送,除非用户明确要求;如需覆盖可用 `--force-with-lease`) [00:00:17 +0ms] exit code: 0, signal: 0, duration: 69ms [00:00:17 +5ms] $ test -d ~/'.agents/skills/code-review' && echo dir || (test -f ~/'.agents/skills/code-review' && echo file || echo other) [00:00:17 +67ms] dir [00:00:17 +1ms] exit code: 0, signal: 0, duration: 69ms [00:00:17 +5ms] $ cat ~/'.agents/skills/code-review/SKILL.md' 2>/dev/null [00:00:17 +61ms] --- [00:00:17 +0ms] name: code-review [00:00:17 +0ms] description: PR 代码评审,检查安全漏洞、Bug 和代码质量,输出结构化结果并通过 API 发送行级评论。 [00:00:17 +0ms] --- [00:00:17 +0ms] [00:00:17 +0ms] # PR 代码评审 [00:00:17 +0ms] [00:00:17 +0ms] 对 PR 的代码变更进行专业评审,发现安全漏洞、Bug、代码质量和性能问题,并通过 PR Review API 发送行级评论。 [00:00:17 +0ms] [00:00:17 +0ms] ## 评审步骤 [00:00:17 +0ms] [00:00:17 +0ms] ### 1. 获取 PR 变更 [00:00:17 +0ms] [00:00:17 +0ms] 使用 pr-diff Skill 获取 PR 的代码变更。 [00:00:17 +0ms] [00:00:17 +0ms] **需过滤的非代码文件**(不评审): [00:00:17 +0ms] - 依赖锁文件:`package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `go.sum`, `Cargo.lock` 等 [00:00:17 +0ms] - 图片文件:`*.png`, `*.jpg`, `*.gif`, `*.svg`, `*.ico` 等 [00:00:17 +0ms] - 字体文件:`*.woff`, `*.ttf`, `*.eot` 等 [00:00:17 +0ms] - 二进制文件:`*.exe`, `*.dll`, `*.so`, `*.jar`, `*.pyc` 等 [00:00:17 +0ms] - 压缩文件:`*.zip`, `*.tar.gz`, `*.rar` 等 [00:00:17 +0ms] - 压缩的代码:`*.min.js`, `*.min.css`, `*.map` [00:00:17 +0ms] - 构建产物目录:`dist/`, `build/`, `out/`, `target/`, `.next/` [00:00:17 +0ms] - 依赖目录:`node_modules/`, `vendor/`, `.venv/` [00:00:17 +0ms] [00:00:17 +0ms] **文件限制**: [00:00:17 +0ms] - 最多评审 30 个文件 [00:00:17 +0ms] - diff 最大 100000 字符(超出则截断) [00:00:17 +0ms] [00:00:17 +0ms] ### 2. 分析代码 [00:00:17 +0ms] [00:00:17 +0ms] **评审重点**(按优先级): [00:00:17 +0ms] [00:00:17 +0ms] 1. **安全漏洞**:SQL 注入、XSS、CSRF、硬编码凭证、敏感信息泄露、不安全加密 [00:00:17 +0ms] 2. **潜在 Bug**:空指针、数组越界、并发问题、资源泄漏、异常处理不当 [00:00:17 +0ms] 3. **代码质量**:可读性、命名规范、代码重复 [00:00:17 +0ms] 4. **性能问题**:N+1 查询、低效算法、不必要的 I/O [00:00:17 +0ms] [00:00:17 +0ms] **评审原则**: [00:00:17 +0ms] - 只评审新增代码(diff 中 `+` 开头的行,不含 `+++` 文件头) [00:00:17 +0ms] - **禁止评审**:删除的代码(`-` 开头)、上下文代码、未修改的代码 [00:00:17 +0ms] - **忽略**:EOF 换行符、行尾空格、缩进风格(应由 linter 处理) [00:00:17 +0ms] [00:00:17 +0ms] **理解上下文**: [00:00:17 +0ms] 当 diff 上下文不足以理解代码时(如需要看函数定义、类型、依赖关系),使用 Read 工具读取相关源文件理解上下文,并确认准确行号。 [00:00:17 +0ms] [00:00:17 +0ms] ### 3. 输出评审结果 [00:00:17 +0ms] [00:00:17 +0ms] **必须严格输出以下 JSON 格式**: [00:00:17 +0ms] [00:00:17 +0ms] ```json [00:00:17 +0ms] { [00:00:17 +0ms] "status": "passed | needs_modification | critical", [00:00:17 +0ms] "issues": [ [00:00:17 +0ms] { [00:00:17 +0ms] "severity": "critical | warning | info", [00:00:17 +0ms] "file": "文件路径", [00:00:17 +0ms] "start_line": 起始行号, [00:00:17 +0ms] "end_line": 结束行号, [00:00:17 +0ms] "problem": "问题:描述问题", [00:00:17 +0ms] "suggestion": "建议:修复建议" [00:00:17 +0ms] } [00:00:17 +0ms] ] [00:00:17 +0ms] } [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] **字段说明**: [00:00:17 +0ms] - `status`: 评审状态 [00:00:17 +0ms] - `passed`: 通过,无问题 [00:00:17 +0ms] - `needs_modification`: 需要修改 [00:00:17 +0ms] - `critical`: 存在严重问题 [00:00:17 +0ms] - `severity`: 问题严重程度 [00:00:17 +0ms] - `critical`: 严重(安全漏洞、崩溃 Bug) [00:00:17 +0ms] - `warning`: 警告(潜在问题) [00:00:17 +0ms] - `info`: 建议(代码质量改进) [00:00:17 +0ms] - `start_line` / `end_line`: 问题代码的行号范围(对应新文件行号) [00:00:17 +0ms] - `problem` / `suggestion`: 使用 Markdown 格式,提高可读性 [00:00:17 +0ms] - 使用 \`代码\` 标记变量名、函数名 [00:00:17 +0ms] - 使用代码块展示修复示例 [00:00:17 +0ms] [00:00:17 +0ms] **无问题时**:`issues` 为空数组 `[]` [00:00:17 +0ms] [00:00:17 +0ms] ### 4. 发送评审评论 [00:00:17 +0ms] [00:00:17 +0ms] **重要**:API 基础地址从环境变量 `CNB_API_ENDPOINT` 获取(默认 `https://api.cnb.cool`),仓库名从环境变量 `CNB_REPO_SLUG` 获取,PR 编号从环境变量 `CNB_PULL_REQUEST_IID` 获取。 [00:00:17 +0ms] [00:00:17 +0ms] **有问题时**:调用 PostPullReview 接口发送行级评审评论: [00:00:17 +1ms] [00:00:17 +0ms] ```bash [00:00:17 +0ms] curl -X POST \ [00:00:17 +0ms] "${CNB_API_ENDPOINT:-https://api.cnb.cool}/${CNB_REPO_SLUG}/-/pulls/${CNB_PULL_REQUEST_IID}/reviews" \ [00:00:17 +0ms] -H "Accept: application/vnd.cnb.api+json" \ [00:00:17 +0ms] -H "Authorization: Bearer $CNB_TOKEN" \ [00:00:17 +0ms] -H "Content-Type: application/json" \ [00:00:17 +0ms] -d '{ [00:00:17 +0ms] "body": "**评审结果**: 需要修改", [00:00:17 +0ms] "event": "comment", [00:00:17 +0ms] "comments": [ [00:00:17 +0ms] { [00:00:17 +0ms] "body": "问题: ...\n建议: ...", [00:00:17 +0ms] "path": "文件路径", [00:00:17 +0ms] "start_line": 起始行号, [00:00:17 +0ms] "start_side": "right", [00:00:17 +0ms] "end_line": 结束行号, [00:00:17 +0ms] "end_side": "right", [00:00:17 +0ms] "subject_type": "line" [00:00:17 +0ms] } [00:00:17 +0ms] ] [00:00:17 +0ms] }' [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] **无问题时**:调用 PostPullComment 接口发送总结评论: [00:00:17 +0ms] [00:00:17 +0ms] ```bash [00:00:17 +0ms] curl -X POST \ [00:00:17 +0ms] "${CNB_API_ENDPOINT:-https://api.cnb.cool}/${CNB_REPO_SLUG}/-/pulls/${CNB_PULL_REQUEST_IID}/comments" \ [00:00:17 +0ms] -H "Accept: application/vnd.cnb.api+json" \ [00:00:17 +0ms] -H "Authorization: Bearer $CNB_TOKEN" \ [00:00:17 +0ms] -H "Content-Type: application/json" \ [00:00:17 +0ms] -d '{ [00:00:17 +0ms] "body": "**评审结果**: 通过\n\n代码质量良好,未发现明显问题。" [00:00:17 +0ms] }' [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] ## 注意事项 [00:00:17 +0ms] [00:00:17 +0ms] 1. **最多发送 10 条评论**,优先发送严重程度高的问题(critical > warning > info) [00:00:17 +0ms] 2. 行号必须对应 diff 中的**新文件行号**(右侧行号),务必通过读取源文件确认 [00:00:17 +0ms] 3. 每条评论需说明问题原因和修复建议 [00:00:17 +1ms] 4. 评审结果必须是有效 JSON [00:00:17 +0ms] exit code: 0, signal: 0, duration: 63ms [00:00:17 +5ms] $ test -d ~/'.agents/skills/knowledge-base' && echo dir || (test -f ~/'.agents/skills/knowledge-base' && echo file || echo other) [00:00:17 +54ms] dir [00:00:17 +2ms] exit code: 0, signal: 0, duration: 56ms [00:00:17 +6ms] $ cat ~/'.agents/skills/knowledge-base/SKILL.md' 2>/dev/null [00:00:17 +62ms] --- [00:00:17 +0ms] name: knowledge-base [00:00:17 +0ms] description: 检索指定仓库的知识库,返回相关的文本片段及其来源。 [00:00:17 +0ms] --- [00:00:17 +0ms] [00:00:17 +0ms] ## 使用场景 [00:00:17 +0ms] [00:00:17 +0ms] - 检索指定仓库的知识库,返回与问题最相关的文本片段及其来源,用于回答用户问题 [00:00:17 +0ms] [00:00:17 +0ms] ## 执行命令 [00:00:17 +0ms] [00:00:17 +0ms] ```bash [00:00:17 +0ms] cnb knowledge-base query-knowledge-base-get --repo / --query "<自然语言问题或关键词>" --top-k 5 [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] - `--repo`:仓库路径,如 `cnb/feedback`,**必填** [00:00:17 +0ms] - `--query`:查询语句,**必填** [00:00:17 +2ms] - `--top-k`:返回的片段数量,默认为 5, 非必填 [00:00:17 +0ms] exit code: 0, signal: 0, duration: 65ms [00:00:17 +5ms] $ test -d ~/'.agents/skills/markitdown' && echo dir || (test -f ~/'.agents/skills/markitdown' && echo file || echo other) [00:00:17 +69ms] dir [00:00:17 +2ms] exit code: 0, signal: 0, duration: 71ms [00:00:17 +5ms] $ cat ~/'.agents/skills/markitdown/SKILL.md' 2>/dev/null [00:00:17 +64ms] --- [00:00:17 +0ms] name: markitdown [00:00:17 +0ms] description: 将多种文件格式(PDF、Office 文档、图片、网页内容、结构化数据)转换为针对大语言模型优化的 Markdown。适用场景包括:文档转 Markdown、从 PDF / Office 文件中提取文本、图片 OCR 等。 [00:00:17 +1ms] --- [00:00:17 +0ms] [00:00:17 +0ms] # MarkItDown [00:00:17 +0ms] [00:00:17 +0ms] ## 概述 [00:00:17 +0ms] [00:00:17 +0ms] MarkItDown 是一个 Python 工具,可以把各种文件格式转换为 Markdown,专为大语言模型和文本分析场景优化。它在输出干净、Token 高效的 Markdown 的同时,会保留文档结构(标题、列表、表格、超链接)。 [00:00:17 +0ms] [00:00:17 +0ms] ## 何时使用本 Skill [00:00:17 +0ms] [00:00:17 +0ms] 当用户有以下需求时,使用本 Skill: [00:00:17 +0ms] - 把文档转换成 Markdown 格式 [00:00:17 +0ms] - 从 PDF、Word、PowerPoint、Excel 文件中提取文本 [00:00:17 +0ms] - 对图片做 OCR 提取文字 [00:00:17 +0ms] - 把 HTML、EPUB 或网页内容转成 Markdown [00:00:17 +0ms] [00:00:17 +0ms] ## 核心能力 [00:00:17 +0ms] [00:00:17 +0ms] ### 1. 文档转换 [00:00:17 +0ms] [00:00:17 +0ms] 把 Office 文档和 PDF 转换为 Markdown,同时保留结构。 [00:00:17 +0ms] [00:00:17 +0ms] **支持的格式:** [00:00:17 +0ms] - PDF 文件 [00:00:17 +0ms] - Word 文档(DOCX) [00:00:17 +0ms] - PowerPoint 演示文稿(PPTX) [00:00:17 +0ms] - Excel 表格(XLSX、XLS) [00:00:17 +0ms] [00:00:17 +0ms] **基础用法:** [00:00:17 +0ms] ```python [00:00:17 +0ms] from markitdown import MarkItDown [00:00:17 +0ms] [00:00:17 +0ms] md = MarkItDown() [00:00:17 +0ms] result = md.convert("document.pdf") [00:00:17 +0ms] print(result.text_content) [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] **命令行:** [00:00:17 +0ms] ```bash [00:00:17 +0ms] markitdown document.pdf -o output.md [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] ### 2. 图片处理 [00:00:17 +0ms] [00:00:17 +0ms] 若前模型不支持读取图片内容时,使用此方法从图片中提取元数据与文字。 [00:00:17 +0ms] [00:00:17 +0ms] markitdown 进行图片 OCR 需要配置 LLM, 当前环境没有配置,所以 markitdown 无法进行图片 OCR。 [00:00:17 +0ms] [00:00:17 +0ms] 容器里已经装好 `tesseract-ocr`,并带了简体和繁体中文语言包: [00:00:17 +0ms] [00:00:17 +0ms] ```bash [00:00:17 +0ms] # 仅英文 [00:00:17 +0ms] tesseract image.png stdout [00:00:17 +0ms] [00:00:17 +0ms] # 中文 + 英文(截图/密集排版建议加 --psm 6) [00:00:17 +0ms] tesseract image.png stdout -l chi_sim+eng --psm 6 [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] 在 Python 中: [00:00:17 +0ms] ```python [00:00:17 +0ms] import pytesseract [00:00:17 +0ms] from PIL import Image [00:00:17 +0ms] [00:00:17 +0ms] text = pytesseract.image_to_string(Image.open("image.png"), lang="chi_sim+eng") [00:00:17 +0ms] print(text) [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] **关于 PDF:** MarkItDown 通过 `pdfminer` 处理文本型 PDF(无需 OCR)。对扫描件 / 纯图片 PDF,他无法识别内容,需要回落到 `tesseract`(可以先用 `poppler-utils` 里的 `pdftoppm` 把页面转成图片再识别)。 [00:00:17 +0ms] [00:00:17 +0ms] ### 3. 网页内容提取 [00:00:17 +0ms] [00:00:17 +0ms] 把基于网页的内容和电子书转成 Markdown。 [00:00:17 +0ms] [00:00:17 +0ms] **支持的格式:** [00:00:17 +0ms] - HTML 文件和网页 [00:00:17 +0ms] - EPUB 电子书 [00:00:17 +0ms] - RSS 订阅 [00:00:17 +0ms] [00:00:17 +0ms] ## 安装 [00:00:17 +0ms] [00:00:17 +0ms] [00:00:17 +0ms] **按需安装(指定功能):** [00:00:17 +0ms] ```bash [00:00:17 +0ms] pip install 'markitdown[pdf]' # PDF 支持 [00:00:17 +0ms] pip install 'markitdown[docx]' # Word 支持 [00:00:17 +0ms] pip install 'markitdown[pptx]' # PowerPoint 支持 [00:00:17 +0ms] pip install 'markitdown[xlsx]' # Excel 支持 [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] **完整安装(所有功能):** [00:00:17 +0ms] ```bash [00:00:17 +0ms] pip install 'markitdown[all]' [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] **要求:** [00:00:17 +0ms] - Python 3.10 或更高版本 [00:00:17 +1ms] exit code: 0, signal: 0, duration: 67ms [00:00:17 +5ms] $ test -d ~/'.agents/skills/npc-delegate' && echo dir || (test -f ~/'.agents/skills/npc-delegate' && echo file || echo other) [00:00:17 +68ms] dir [00:00:17 +2ms] exit code: 0, signal: 0, duration: 70ms [00:00:17 +4ms] $ cat ~/'.agents/skills/npc-delegate/SKILL.md' 2>/dev/null [00:00:17 +58ms] --- [00:00:17 +0ms] name: npc-delegate [00:00:17 +0ms] description: 当任务复杂或需要特定专长时,主动召唤其他 NPC 协同工作。 [00:00:17 +0ms] --- [00:00:17 +0ms] [00:00:17 +0ms] # 召唤 NPC 协同工作 [00:00:17 +0ms] [00:00:17 +0ms] 当遇到以下情况时,应主动召唤其他 NPC: [00:00:17 +0ms] [00:00:17 +0ms] 1. **任务超出能力范围**:需要特定领域专家(如前端、测试、安全等) [00:00:17 +0ms] 2. **任务可并行处理**:多个子任务可同时进行 [00:00:17 +0ms] 3. **需要跨仓库协作**:涉及其他仓库的代码或功能 [00:00:17 +0ms] 4. **其他 NPC 更擅长**:效率更高 [00:00:17 +0ms] [00:00:17 +0ms] ## 召唤流程 [00:00:17 +0ms] [00:00:17 +0ms] ### 1. 评估任务,决定是否召唤 [00:00:17 +0ms] [00:00:17 +0ms] 问自己: [00:00:17 +0ms] - 这个任务是否需要特定领域的专业知识? [00:00:17 +0ms] - 是否有其他 NPC 更擅长处理这个任务? [00:00:17 +0ms] - 任务是否可以拆解并并行处理? [00:00:17 +0ms] [00:00:17 +0ms] ### 2. 搜索合适的 NPC [00:00:17 +0ms] [00:00:17 +0ms] 使用 `npc-search` skill 搜索: [00:00:17 +0ms] [00:00:17 +0ms] ```bash [00:00:17 +0ms] cnb knowledge-base search-npc --key "关键词" --top-n 3 [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] 示例场景对应搜索词: [00:00:17 +0ms] | 场景 | 搜索关键词 | [00:00:17 +0ms] |------|-----------| [00:00:17 +0ms] | 需要代码审查 | `代码审查`、`CR` | [00:00:17 +0ms] | 需要写前端 | `前端开发`、`React` | [00:00:17 +1ms] | 需要写测试 | `单元测试`、`测试用例` | [00:00:17 +0ms] | 需要性能优化 | `性能优化`、`调优` | [00:00:17 +0ms] | 需要安全审计 | `安全`、`审计` | [00:00:17 +0ms] [00:00:17 +0ms] ### 3. 正确发起召唤 [00:00:17 +0ms] [00:00:17 +0ms] 找到合适的 NPC 后,使用正确的 @ 格式召唤: [00:00:17 +0ms] [00:00:17 +0ms] ``` [00:00:17 +0ms] @{slug}({name}) [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] 示例: [00:00:17 +0ms] - `@npc/hok(π)` - 仓库 `npc/hok` 下名为 `π` 的 NPC [00:00:17 +0ms] - `@npc/code-reviewer(代码审查员)` - 仓库 `npc/code-reviewer` [00:00:17 +0ms] [00:00:17 +0ms] ### 4. 传递完整的上下文 [00:00:17 +0ms] [00:00:17 +0ms] 召唤时提供充分信息: [00:00:17 +0ms] - **任务背景**:要解决的问题 [00:00:17 +0ms] - **相关文件**:涉及的代码或路径 [00:00:17 +0ms] - **约束条件**:技术栈、代码规范等 [00:00:17 +0ms] - **期望结果**:交付物形式 [00:00:17 +0ms] [00:00:17 +0ms] 示例召唤方式: [00:00:17 +0ms] [00:00:17 +0ms] ``` [00:00:17 +0ms] @npc/xxx 帮我审查 /workspace/src/auth 目录下的登录逻辑,重点关注: [00:00:17 +0ms] 1. 密码存储是否安全 [00:00:17 +0ms] 2. Session 管理是否有漏洞 [00:00:17 +0ms] 参考标准:OWASP Top 10 [00:00:17 +0ms] ``` [00:00:17 +0ms] [00:00:17 +0ms] ## 协同工作模式 [00:00:17 +0ms] [00:00:17 +0ms] 召唤成功后,可: [00:00:17 +0ms] [00:00:17 +0ms] 1. **分工协作**:拆分任务,各 NPC 处理一部分 [00:00:17 +0ms] 2. **串联审核**:一个 NPC 完成后,另一个继续优化 [00:00:17 +0ms] 3. **并行处理**:多个 NPC 同时处理独立任务 [00:00:17 +0ms] [00:00:17 +0ms] ## 何时主动建议召唤 [00:00:17 +0ms] [00:00:17 +0ms] 作为 AI,以下情况应主动建议用户召唤其他 NPC: [00:00:17 +0ms] [00:00:17 +0ms] - 需求明显超出当前 NPC 能力 [00:00:17 +0ms] - 任务涉及多个专业领域 [00:00:17 +0ms] - 任务耗时长,可拆解并行 [00:00:17 +0ms] [00:00:17 +0ms] ## 注意事项 [00:00:17 +0ms] [00:00:17 +0ms] - 召唤前先了解目标 NPC 的能力范围(通过 slogan 判断) [00:00:17 +0ms] - 尽量一次召唤到位,避免反复补充上下文 [00:00:17 +0ms] - 模糊需求先自行分析,再决定是否召唤 [00:00:17 +0ms] - 始终把控整体任务,即使分配了子任务 [00:00:17 +1ms] - 评论中如果只提及 npc 不召唤,应该去掉 `@` 符号,或使用反引号包裹 `@npc` [00:00:17 +0ms] exit code: 0, signal: 0, duration: 60ms [00:00:17 +6ms] $ test -d ~/'.agents/skills/npc-search' && echo dir || (test -f ~/'.agents/skills/npc-search' && echo file || echo other) [00:00:17 +59ms] dir [00:00:17 +2ms] exit code: 0, signal: 0, duration: 62ms [00:00:17 +5ms] $ cat ~/'.agents/skills/npc-search/SKILL.md' 2>/dev/null [00:00:18 +58ms] --- [00:00:18 +0ms] name: npc-search [00:00:18 +0ms] description: 通过关键词语义搜索 CNB 平台上的公开 NPC 角色,帮助用户找到最适合当前需求的 NPC。 [00:00:18 +0ms] --- [00:00:18 +0ms] [00:00:18 +0ms] # 搜索 NPC 角色 [00:00:18 +0ms] [00:00:18 +0ms] 根据用户需求,通过关键词语义搜索 CNB 平台上的公开 NPC 角色,帮助用户找到最合适的 NPC。 [00:00:18 +0ms] [00:00:18 +0ms] ## 搜索步骤 [00:00:18 +0ms] [00:00:18 +0ms] ### 1. 提取搜索关键词 [00:00:18 +0ms] [00:00:18 +0ms] 分析用户的需求,提取最能描述目标 NPC 功能的关键词。例如: [00:00:18 +0ms] [00:00:18 +0ms] - 用户说"帮我找一个能做代码审查的 NPC" → 关键词:`代码审查` [00:00:18 +0ms] - 用户说"有没有写前端的 NPC" → 关键词:`前端开发` [00:00:18 +0ms] - 用户说"我需要一个 NPC 帮我写单元测试" → 关键词:`单元测试` [00:00:18 +0ms] [00:00:18 +0ms] ### 2. 执行搜索 [00:00:18 +0ms] [00:00:18 +0ms] ```bash [00:00:18 +0ms] cnb knowledge-base search-npc --key "关键词" [00:00:18 +0ms] ``` [00:00:18 +0ms] [00:00:18 +0ms] 可选参数: [00:00:18 +0ms] - `--top-n `:返回结果数量,最大 20(默认 10) [00:00:18 +0ms] [00:00:18 +0ms] ### 3. 解读搜索结果 [00:00:18 +0ms] [00:00:18 +0ms] 搜索结果包含以下字段: [00:00:18 +0ms] [00:00:18 +0ms] | 字段 | 说明 | [00:00:18 +0ms] |------|------| [00:00:18 +0ms] | `name` | NPC 角色名称 | [00:00:18 +0ms] | `slug` | NPC 所在仓库路径 | [00:00:18 +0ms] | `slogan` | NPC 简介/标语,描述其能力和特点 | [00:00:18 +0ms] | `score` | 语义匹配分数(越高越相关) | [00:00:18 +0ms] | `avatar` | NPC 头像路径 | [00:00:18 +0ms] [00:00:18 +0ms] ### 4. 选出最合适的 NPC [00:00:18 +0ms] [00:00:18 +0ms] 根据搜索结果,结合以下因素选出最合适的 NPC: [00:00:18 +0ms] [00:00:18 +0ms] 1. **匹配分数**(score):分数越高,语义匹配度越高 [00:00:18 +0ms] 2. **slogan 描述**:了解 NPC 能力定位,判断是否符合需求 [00:00:18 +0ms] 3. **角色名称**(name):通常反映专长领域 [00:00:18 +0ms] [00:00:18 +0ms] 选定后,NPC 的使用形式为 `@{slug}({name})`,其中 `slug` 是仓库路径,`name` 是角色名。 [00:00:18 +0ms] [00:00:18 +0ms] 例如:`@npc/hok(π)` 表示仓库 `npc/hok` 下名为 `π` 的 NPC 角色。 [00:00:18 +0ms] [00:00:18 +0ms] ## 注意事项 [00:00:18 +1ms] [00:00:18 +0ms] - 关键词应精准,避免过于宽泛 [00:00:18 +0ms] - 搜索结果不理想时,可换关键词重试 [00:00:18 +0ms] - slogan 为空的 NPC 可能缺少描述,优先推荐有明确 slogan 的 [00:00:18 +0ms] - 直接执行命令搜索,无需用户确认 [00:00:18 +1ms] - **npc提及**: 评论中直接 @npc 会召唤 npc 干活,如果只提及不召唤,应该去掉 `@` 符号,或使用反引号包裹 `@npc`。 [00:00:18 +0ms] exit code: 0, signal: 0, duration: 60ms [00:00:18 +5ms] $ test -d ~/'.agents/skills/pr-diff' && echo dir || (test -f ~/'.agents/skills/pr-diff' && echo file || echo other) [00:00:18 +61ms] dir [00:00:18 +2ms] exit code: 0, signal: 0, duration: 63ms [00:00:18 +4ms] $ cat ~/'.agents/skills/pr-diff/SKILL.md' 2>/dev/null [00:00:18 +61ms] --- [00:00:18 +0ms] name: pr-diff [00:00:18 +0ms] description: 获取 PR 的 diff 变更信息。当需要查看 PR 代码变更、获取文件差异时使用此技能。 [00:00:18 +0ms] --- [00:00:18 +0ms] [00:00:18 +0ms] # 获取 PR Diff [00:00:18 +0ms] [00:00:18 +0ms] 获取 PR 的代码变更差异信息,用于代码评审、变更总结等场景。 [00:00:18 +0ms] [00:00:18 +0ms] ## 1. 判断场景并获取 SHA [00:00:18 +0ms] [00:00:18 +0ms] ### 场景 A:PR 评论触发(`CNB_PULL_REQUEST_IID` 存在) [00:00:18 +0ms] [00:00:18 +0ms] 直接从环境变量获取: [00:00:18 +0ms] - head SHA:`CNB_PULL_REQUEST_SHA` [00:00:18 +0ms] - target SHA:`CNB_PULL_REQUEST_TARGET_SHA` [00:00:18 +0ms] [00:00:18 +0ms] 若环境变量不存在,通过 API 查询当前 PR 详情。 [00:00:18 +0ms] [00:00:18 +0ms] ### 场景 B:Issue 或其他场景引用 PR [00:00:18 +0ms] [00:00:18 +0ms] 用户输入中提及了 PR 编号(如 `!45`),需要: [00:00:18 +0ms] 1. 从用户输入中解析 PR 编号 [00:00:18 +0ms] 2. 通过 API 查询该 PR 详情获取 SHA [00:00:18 +0ms] 3. fetch 对应的 commit(本地可能没有) [00:00:18 +0ms] [00:00:18 +0ms] ### API 查询 PR 详情 [00:00:18 +0ms] [00:00:18 +0ms] ```bash [00:00:18 +0ms] # 将 ${pr_iid} 替换为实际 PR 编号 [00:00:18 +0ms] pr_info=$(curl -s \ [00:00:18 +0ms] "${CNB_API_ENDPOINT:-https://api.cnb.cool}/${CNB_REPO_SLUG}/-/pulls/${pr_iid}" \ [00:00:18 +0ms] -H "Accept: application/vnd.cnb.api+json" \ [00:00:18 +0ms] -H "Authorization: Bearer $CNB_TOKEN") [00:00:18 +0ms] [00:00:18 +0ms] head_sha=$(echo "$pr_info" | jq -r '.head.sha') [00:00:18 +0ms] target_sha=$(echo "$pr_info" | jq -r '.base.sha') [00:00:18 +0ms] [00:00:18 +0ms] # 场景 B 需要确保本地有这些 commit [00:00:18 +0ms] git fetch origin "$head_sha" "$target_sha" 2>/dev/null || git fetch origin [00:00:18 +0ms] ``` [00:00:18 +0ms] [00:00:18 +0ms] ## 2. 获取 Diff [00:00:18 +0ms] [00:00:18 +0ms] ### 获取变更文件列表 [00:00:18 +0ms] [00:00:18 +0ms] ```bash [00:00:18 +0ms] git diff --name-only "${target_sha}...${head_sha}" [00:00:18 +1ms] ``` [00:00:18 +0ms] [00:00:18 +0ms] ### 获取变更统计 [00:00:18 +0ms] [00:00:18 +0ms] ```bash [00:00:18 +0ms] git diff --stat "${target_sha}...${head_sha}" [00:00:18 +0ms] ``` [00:00:18 +0ms] [00:00:18 +0ms] ### 获取完整 Diff [00:00:18 +0ms] [00:00:18 +0ms] ```bash [00:00:18 +0ms] git diff -U5 "${target_sha}...${head_sha}" [00:00:18 +0ms] ``` [00:00:18 +0ms] [00:00:18 +0ms] ### 获取特定文件的 Diff [00:00:18 +0ms] [00:00:18 +0ms] ```bash [00:00:18 +0ms] git diff -U5 "${target_sha}...${head_sha}" -- path/to/file.ts [00:00:18 +0ms] ``` [00:00:18 +0ms] [00:00:18 +0ms] ## 3. 过滤文件 [00:00:18 +0ms] [00:00:18 +0ms] 根据使用场景,可排除无需关注的文件: [00:00:18 +0ms] [00:00:18 +0ms] ```bash [00:00:18 +0ms] # 常见排除模式 [00:00:18 +0ms] git diff -U5 "${target_sha}...${head_sha}" -- . \ [00:00:18 +0ms] ':!package-lock.json' ':!yarn.lock' ':!pnpm-lock.yaml' ':!go.sum' ':!*.lock' \ [00:00:18 +0ms] ':!*.png' ':!*.jpg' ':!*.gif' ':!*.svg' ':!*.ico' \ [00:00:18 +0ms] ':!*.min.js' ':!*.min.css' ':!*.map' \ [00:00:18 +0ms] ':!dist/*' ':!build/*' ':!node_modules/*' [00:00:18 +0ms] ``` [00:00:18 +0ms] [00:00:18 +0ms] **可排除的文件类型**: [00:00:18 +0ms] - 锁文件:`package-lock.json`、`yarn.lock`、`pnpm-lock.yaml`、`go.sum`、`Cargo.lock` [00:00:18 +0ms] - 图片/字体:`*.png`、`*.jpg`、`*.gif`、`*.svg`、`*.woff`、`*.ttf` [00:00:18 +0ms] - 二进制:`*.exe`、`*.dll`、`*.so`、`*.jar`、`*.pyc` [00:00:18 +0ms] - 压缩包:`*.zip`、`*.tar.gz`、`*.rar` [00:00:18 +0ms] - 构建产物:`dist/`、`build/`、`out/`、`target/`、`.next/` [00:00:18 +0ms] - 依赖目录:`node_modules/`、`vendor/`、`.venv/` [00:00:18 +0ms] - 压缩文件:`*.min.js`、`*.min.css`、`*.map` [00:00:18 +0ms] [00:00:18 +0ms] ## 4. 使用建议 [00:00:18 +0ms] [00:00:18 +0ms] 1. **diff 过大时**:先用 `--name-only` 查看文件列表,再按需获取具体文件 [00:00:18 +0ms] 2. **代码评审**:建议排除锁文件、图片、构建产物 [00:00:18 +0ms] 3. **变更总结**:可保留更多文件,但排除二进制和依赖目录 [00:00:18 +0ms] 4. **上下文行数**:`-U5` 提供 5 行上下文,可按需调整 [00:00:18 +1ms] exit code: 0, signal: 0, duration: 63ms [00:00:18 +5ms] $ test -d ~/'.agents/skills/pr-summary' && echo dir || (test -f ~/'.agents/skills/pr-summary' && echo file || echo other) [00:00:18 +71ms] dir [00:00:18 +2ms] exit code: 0, signal: 0, duration: 73ms [00:00:18 +7ms] $ cat ~/'.agents/skills/pr-summary/SKILL.md' 2>/dev/null [00:00:18 +55ms] --- [00:00:18 +0ms] name: pr-summary [00:00:18 +0ms] description: 总结 PR 变更内容,概述主要改动点并生成变更说明。 [00:00:18 +0ms] --- [00:00:18 +0ms] [00:00:18 +0ms] # PR 变更总结 [00:00:18 +0ms] [00:00:18 +0ms] 对 PR 的代码变更进行分析,生成结构化的变更总结。 [00:00:18 +0ms] [00:00:18 +0ms] ## 执行步骤 [00:00:18 +0ms] [00:00:18 +0ms] ### 1. 获取变更信息 [00:00:18 +0ms] [00:00:18 +0ms] 使用 **pr-diff** Skill 获取 PR 变更: [00:00:18 +0ms] - 先获取变更统计(`--stat`)和文件列表(`--name-only`) [00:00:18 +0ms] - 再按需获取关键文件的具体 diff [00:00:18 +0ms] [00:00:18 +1ms] ### 2. 过滤文件 [00:00:18 +0ms] [00:00:18 +0ms] **优先分析**(核心代码): [00:00:18 +0ms] - 业务逻辑:`src/`、`lib/`、`app/`、`packages/` [00:00:18 +0ms] - API/接口:`api/`、`routes/`、`controllers/` [00:00:18 +0ms] - 配置文件:`*.config.*`、`*.yml`、`*.yaml` [00:00:18 +0ms] - 数据库/模型:`models/`、`schema/`、`migrations/` [00:00:18 +0ms] [00:00:18 +0ms] **跳过**(非核心文件): [00:00:18 +0ms] - 依赖锁文件:`package-lock.json`、`yarn.lock`、`go.sum` [00:00:18 +0ms] - 构建产物:`dist/`、`build/`、`.next/` [00:00:18 +0ms] - 生成文件:`*.min.js`、`*.map` [00:00:18 +0ms] - 纯测试文件(除非测试是本次变更重点) [00:00:18 +0ms] [00:00:18 +0ms] ### 3. 分析变更 [00:00:18 +0ms] [00:00:18 +0ms] 按以下维度分析: [00:00:18 +0ms] [00:00:18 +0ms] | 维度 | 关注点 | [00:00:18 +0ms] |------|--------| [00:00:18 +0ms] | **变更类型** | feat(新功能)、fix(修复)、refactor(重构)、perf(性能)、docs(文档)、chore(配置/依赖) | [00:00:18 +0ms] | **影响范围** | 涉及哪些模块、影响哪些功能点 | [00:00:18 +0ms] | **关键改动** | 核心逻辑变更、API 变化、数据结构变更 | [00:00:18 +0ms] | **破坏性变更** | 不兼容改动、需要迁移的内容 | [00:00:18 +0ms] [00:00:18 +0ms] 若上下文不足以理解代码意图,使用 Read 工具读取完整源文件。 [00:00:18 +0ms] [00:00:18 +0ms] ## 输出格式 [00:00:18 +0ms] [00:00:18 +0ms] ```markdown [00:00:18 +0ms] **{type}**: {一句话描述} [00:00:18 +0ms] [00:00:18 +0ms] **主要改动** [00:00:18 +0ms] - {模块}: {变更说明} [00:00:18 +0ms] - {模块}: {变更说明} [00:00:18 +0ms] [00:00:18 +0ms] **注意**: {破坏性变更或风险点;如无则省略} [00:00:18 +0ms] ``` [00:00:18 +0ms] [00:00:18 +0ms] ## 总结原则 [00:00:18 +0ms] [00:00:18 +0ms] 1. **简洁明了**:突出重点,避免逐行复述 diff [00:00:18 +0ms] 2. **按功能分组**:按模块/功能组织,而非逐文件罗列 [00:00:18 +0ms] 3. **突出意图**:说明"为什么改"而非仅描述"改了什么" [00:00:18 +0ms] 4. **识别风险**:主动指出破坏性变更和需要关注的点 [00:00:18 +0ms] [00:00:18 +0ms] ## 大型 PR 处理 [00:00:18 +0ms] [00:00:18 +0ms] 当文件数超过 20 个时: [00:00:18 +0ms] 1. 先用 `--stat` 分析变更分布,按模块归类 [00:00:18 +0ms] 2. 重点分析核心模块变更(变更量大或涉及关键逻辑) [00:00:18 +0ms] 3. 在末尾概括未详细分析的文件/模块 [00:00:18 +1ms] exit code: 0, signal: 0, duration: 58ms [00:00:18 +5ms] $ test -d ~/'.agents/skills/tapd-resource-fetcher' && echo dir || (test -f ~/'.agents/skills/tapd-resource-fetcher' && echo file || echo other) [00:00:18 +65ms] dir [00:00:18 +2ms] exit code: 0, signal: 0, duration: 66ms [00:00:18 +4ms] $ cat ~/'.agents/skills/tapd-resource-fetcher/SKILL.md' 2>/dev/null [00:00:18 +69ms] --- [00:00:18 +0ms] name: tapd-resource-fetcher [00:00:18 +0ms] description: 获取 TAPD 资源(需求/缺陷/任务/迭代),支持从 TAPD 链接自动解析。 [00:00:18 +0ms] --- [00:00:18 +0ms] [00:00:18 +0ms] # 获取 TAPD 资源 [00:00:18 +0ms] [00:00:18 +0ms] 从用户提供的 TAPD 链接中提取参数,调用 API 获取资源数据。 [00:00:18 +0ms] [00:00:18 +0ms] ## 1. 解析链接 [00:00:18 +0ms] [00:00:18 +0ms] 格式:`https://www.tapd.cn/tapd_fe/{workspace_id}/{type}/detail/{id}` [00:00:18 +0ms] [00:00:18 +0ms] - `type`: story / bug / task / iteration [00:00:18 +0ms] [00:00:18 +0ms] ## 2. 请求 [00:00:18 +0ms] [00:00:18 +0ms] ```bash [00:00:18 +0ms] curl -s "$CNB_API_ENDPOINT/tapd/reference/{workspace_id}/{type}/{id}" \ [00:00:18 +0ms] -H "Accept: application/vnd.cnb.api+json" \ [00:00:18 +0ms] -H "Authorization: Bearer $CNB_TOKEN" [00:00:18 +0ms] ``` [00:00:18 +0ms] [00:00:18 +0ms] 多个链接时逐个请求,汇总后统一展示。 [00:00:18 +0ms] [00:00:18 +0ms] ## 3. 响应处理 [00:00:18 +0ms] [00:00:18 +0ms] - HTTP 2xx 且 `data` 非空 → 返回 `data` 内容 [00:00:18 +0ms] - HTTP 2xx 但 `data` 为 `[]` → 提示"未找到该资源,请检查资源 ID" [00:00:18 +0ms] - HTTP >= 300 → 按 `errcode` 提示用户(返回 `status` 和 `trace`): [00:00:18 +0ms] [00:00:18 +0ms] | errcode | 提示 | [00:00:18 +0ms] |---------|------| [00:00:18 +0ms] | `2000076` | 项目未启用 TAPD 集成,请联系管理员开启 | [00:00:18 +1ms] | `2000073` | 未绑定 TAPD 账号,请前往个人设置绑定 | [00:00:18 +0ms] | `2000074` | TAPD 授权已过期,请重新绑定 | [00:00:18 +0ms] | `2000075` | 无权限或资源 ID 错误,请检查链接 | [00:00:18 +0ms] | `401` | 请先登录 CNB 平台 | [00:00:18 +0ms] | `403` / `404` | 无权限或资源不存在 | [00:00:18 +0ms] | 其他 | 请求失败,请重试或联系管理员并提供 trace | [00:00:18 +0ms] [00:00:18 +0ms] 注意:不要向用户暴露错误堆栈等内部细节。 [00:00:18 +1ms] exit code: 0, signal: 0, duration: 70ms [00:00:18 +4ms] $ test -d ~/'.agents/skills/text-path-converter' && echo dir || (test -f ~/'.agents/skills/text-path-converter' && echo file || echo other) [00:00:18 +61ms] dir [00:00:18 +2ms] exit code: 0, signal: 0, duration: 63ms [00:00:18 +5ms] $ cat ~/'.agents/skills/text-path-converter/SKILL.md' 2>/dev/null [00:00:18 +67ms] --- [00:00:18 +0ms] name: text-path-converter [00:00:18 +0ms] description: 将 ISSUE/PR 描述、评论、Review 中的相对路径转换为绝对路径,避免路径歧义,支持纯文本与 Markdown。 [00:00:18 +0ms] requires: [00:00:18 +0ms] bins: [node] [00:00:18 +0ms] files: [scripts/convertLink.js] [00:00:18 +0ms] --- [00:00:18 +0ms] [00:00:18 +0ms] # CNB 文本相对路径转换器 [00:00:18 +1ms] [00:00:18 +0ms] ## 使用方式 [00:00:18 +0ms] [00:00:18 +0ms] 获取到 ISSUE 或合并请求的描述、评论、Review 的原始内容后,执行以下脚本进行转换。脚本会将所有相对路径替换为绝对路径,并将转换结果输出到标准输出。 [00:00:18 +0ms] [00:00:18 +0ms] ```bash [00:00:18 +0ms] # 执行转换,结果输出到标准输出 [00:00:18 +0ms] node scripts/convertLink.js <在此粘贴原始内容> [00:00:18 +0ms] ``` [00:00:18 +0ms] [00:00:18 +0ms] ## 示例 [00:00:18 +0ms] [00:00:18 +0ms] **转换前:** [00:00:18 +0ms] ``` [00:00:18 +0ms] 请参考 ./src/utils/helper.ts 中的实现,以及 ../docs/api.md 的说明。 [00:00:18 +0ms] ``` [00:00:18 +0ms] [00:00:18 +0ms] **转换后:** [00:00:18 +0ms] ``` [00:00:18 +0ms] 请参考 https://cnb.cool/cnb/cool/default-npc-agent/-/git/raw/main/src/utils/helper.ts 中的实现,以及 https://cnb.cool/cnb/cool/default-npc-agent/-/git/raw/main/docs/api.md 的说明。 [00:00:18 +0ms] ``` [00:00:18 +1ms] exit code: 0, signal: 0, duration: 69ms [00:00:18 +5ms] $ test -d ~/'.agents/skills/upload-attachment' && echo dir || (test -f ~/'.agents/skills/upload-attachment' && echo file || echo other) [00:00:18 +60ms] dir [00:00:18 +2ms] exit code: 0, signal: 0, duration: 61ms [00:00:18 +5ms] $ cat ~/'.agents/skills/upload-attachment/SKILL.md' 2>/dev/null [00:00:18 +66ms] --- [00:00:18 +0ms] name: upload-attachment [00:00:18 +0ms] description: 上传附件(图片、文档、压缩包等)到 Issue 或 PR 评论,返回 Markdown 附件链接。 [00:00:18 +0ms] --- [00:00:18 +0ms] [00:00:18 +0ms] # 上传附件到 Issue / PR [00:00:18 +0ms] [00:00:18 +0ms] 将本地文件上传到 CNB 平台的 Issue 或 PR,返回可嵌入评论的 Markdown 附件链接。 [00:00:18 +0ms] [00:00:18 +0ms] ## 使用场景 [00:00:18 +0ms] [00:00:18 +0ms] - 在 Issue 或 PR 评论中附加截图、日志文件、构建产物等 [00:00:18 +0ms] - 上传图片(png/jpg/gif/svg/webp)或普通文件(zip/pdf/log 等) [00:00:18 +0ms] [00:00:18 +0ms] ## 执行步骤 [00:00:18 +0ms] [00:00:18 +0ms] ### 1. 判断文件类别 [00:00:18 +0ms] [00:00:18 +0ms] 根据文件扩展名判断使用哪个命令: [00:00:18 +0ms] [00:00:18 +0ms] - **图片**(`.png`, `.jpg`, `.jpeg`, `.gif`, `.svg`, `.webp`, `.ico` 等图片类型)→ 使用 `upload-image` [00:00:18 +0ms] - **其他文件** → 使用 `upload-file` [00:00:18 +0ms] [00:00:18 +0ms] ### 2. 执行上传 [00:00:18 +0ms] [00:00:18 +0ms] 上传图片: [00:00:18 +0ms] [00:00:18 +0ms] ```bash [00:00:18 +0ms] cnb issues upload-image --file 本地文件路径 [00:00:18 +0ms] cnb pulls upload-image --file 本地文件路径 [00:00:18 +0ms] ``` [00:00:18 +0ms] [00:00:18 +0ms] 上传普通文件: [00:00:18 +0ms] [00:00:18 +0ms] ```bash [00:00:18 +0ms] cnb issues upload-file --file 本地文件路径 [00:00:18 +0ms] cnb pulls upload-file --file 本地文件路径 [00:00:18 +0ms] ``` [00:00:18 +0ms] [00:00:18 +0ms] ### 3. 使用上传结果 [00:00:18 +0ms] [00:00:18 +0ms] 命令返回 JSON,其中包含 `asset_link`(Issue)或 `path`(PR)字段,即附件的访问链接。 [00:00:18 +0ms] [00:00:18 +0ms] 附件在评论中的 Markdown 格式: [00:00:18 +0ms] [00:00:18 +0ms] - 图片:`![文件名](附件URL)` — 渲染为内联图片 [00:00:18 +2ms] - 普通文件:`[文件名](附件URL)` — 渲染为下载链接 [00:00:18 +0ms] exit code: 0, signal: 0, duration: 68ms [00:00:18 +5ms] $ test -d ~/'.codebuddy/skills' && echo 1 || echo 0 [00:00:18 +59ms] 1 [00:00:18 +2ms] exit code: 0, signal: 0, duration: 61ms [00:00:18 +5ms] $ cat ~/'.codebuddy/skills/SKILL.md' 2>/dev/null [00:00:18 +64ms] exit code: 1, signal: -1, duration: 64ms [00:00:18 +4ms] $ ls -1A ~/'.codebuddy/skills' 2>/dev/null [00:00:18 +57ms] cnb-api [00:00:18 +0ms] cnb-knowledge-base [00:00:18 +0ms] cnb-pipeline [00:00:18 +0ms] code-commit [00:00:18 +0ms] code-review [00:00:18 +0ms] knowledge-base [00:00:18 +0ms] markitdown [00:00:18 +0ms] npc-delegate [00:00:18 +0ms] npc-search [00:00:18 +0ms] pr-diff [00:00:18 +0ms] pr-summary [00:00:18 +0ms] tapd-resource-fetcher [00:00:18 +0ms] text-path-converter [00:00:18 +0ms] upload-attachment [00:00:18 +3ms] exit code: 0, signal: 0, duration: 60ms [00:00:18 +5ms] $ test -d ~/'.codebuddy/skills/cnb-api' && echo dir || (test -f ~/'.codebuddy/skills/cnb-api' && echo file || echo other) [00:00:19 +68ms] dir [00:00:19 +2ms] exit code: 0, signal: 0, duration: 70ms [00:00:19 +5ms] $ cat ~/'.codebuddy/skills/cnb-api/SKILL.md' 2>/dev/null [00:00:19 +61ms] --- [00:00:19 +1ms] name: cnb-api [00:00:19 +0ms] description: CNB 平台交互命令,支持仓库、Issue、PR、流水线、制品库等操作。 [00:00:19 +0ms] --- [00:00:19 +0ms] [00:00:19 +0ms] # cnb-api [00:00:19 +0ms] [00:00:19 +0ms] 操作 CNB 平台资源的 CLI 工具。 [00:00:19 +0ms] [00:00:19 +0ms] ## 快捷命令 [00:00:19 +0ms] [00:00:19 +0ms] issues: [00:00:19 +0ms] - `cnb issues get` — 获取当前 Issue 详情 [00:00:19 +0ms] - `cnb issues list-comments` — 列出当前 Issue 评论 [00:00:19 +0ms] - `cnb issues comment --body '内容'` — 发表评论到当前 Issue [00:00:19 +0ms] - `cnb issues close` — 关闭当前 Issue [00:00:19 +0ms] - `cnb issues open` — 打开当前 Issue [00:00:19 +0ms] - `cnb issues list-labels` — 列出当前 Issue 标签 [00:00:19 +0ms] - `cnb issues add-labels --labels bug --labels feature` — 添加标签到当前 Issue [00:00:19 +0ms] - `cnb issues list-assignees` — 查看当前 Issue 处理人 [00:00:19 +0ms] - `cnb issues add-assignees --assignees username` — 添加处理人到当前 Issue [00:00:19 +0ms] - `cnb issues upload-file --file 文件路径` — 上传文件到当前 Issue [00:00:19 +0ms] - `cnb issues upload-image --file 图片路径` — 上传图片到当前 Issue [00:00:19 +0ms] [00:00:19 +0ms] pulls: [00:00:19 +0ms] - `cnb pulls get` — 获取当前 PR 详情 [00:00:19 +0ms] - `cnb pulls list-files` — 列出当前 PR 变更文件 [00:00:19 +0ms] - `cnb pulls list-commits` — 列出当前 PR 提交记录 [00:00:19 +0ms] - `cnb pulls list-comments` — 列出当前 PR 评论 [00:00:19 +0ms] - `cnb pulls comment --body '内容'` — 发表 PR 评论 [00:00:19 +0ms] - `cnb pulls list-labels` — 列出当前 PR 标签 [00:00:19 +0ms] - `cnb pulls add-labels --labels ready --labels approved` — 添加标签到当前 PR [00:00:19 +0ms] - `cnb pulls check-status` — 获取当前 PR 的 CI 状态 [00:00:19 +0ms] - `cnb pulls get-ci-logs` — 获取当前 PR 的 CI 构建日志 [00:00:19 +0ms] - `cnb pulls list-reviews` — 查看当前当前的评审列表 [00:00:19 +0ms] - `cnb pulls list-assignees` — 查看当前 PR 处理人 [00:00:19 +0ms] - `cnb pulls upload-file --file 文件路径` — 上传文件到当前 PR [00:00:19 +0ms] - `cnb pulls upload-image --file 图片路径` — 上传图片到当前 PR [00:00:19 +0ms] [00:00:19 +0ms] 注意事项: [00:00:19 +0ms] - **链接结构**:Issue 链接格式为 `//-/issues/`,PR 链接格式为 `//-/pulls/`。在生成或引用链接时请遵循此结构。 [00:00:19 +0ms] - **参数自动识别**:快捷命令中的 Issue/PR 编号会自动从环境变量识别,无需额外传递。 [00:00:19 +0ms] - **默认仅需摘要**:默认会精简响应输出结果,只返回核心字段。添加 `--verbose` 输出完整数据。 [00:00:19 +0ms] - **单引号传参**:传递多行文本参数时,使用单引号可防止命令注入攻击,并减少不必要的转义。 [00:00:19 +0ms] - **快捷命令适用范围**: 快捷命令只能操作当前仓库的当前 Issue/PR,跨仓库或跨编号操作请参考 `更多 API`。 [00:00:19 +0ms] - **npc提及和召唤的区别**: 评论中直接 @npc 会召唤 npc 干活,如果只提及不召唤,应该去掉 `@` 符号,或使用反引号包裹 `@npc`。 [00:00:19 +0ms] [00:00:19 +0ms] ## 更多 API [00:00:19 +0ms] [00:00:19 +0ms] 1. `cnb --help` 查看所有模块 [00:00:19 +0ms] 2. `cnb --help` 查看模块下的工具列表 [00:00:19 +0ms] 3. `cnb --help` 查看工具参数 [00:00:19 +2ms] exit code: 0, signal: 0, duration: 63ms [00:00:19 +4ms] $ test -d ~/'.codebuddy/skills/cnb-knowledge-base' && echo dir || (test -f ~/'.codebuddy/skills/cnb-knowledge-base' && echo file || echo other) [00:00:19 +60ms] dir [00:00:19 +2ms] exit code: 0, signal: 0, duration: 62ms [00:00:19 +4ms] $ cat ~/'.codebuddy/skills/cnb-knowledge-base/SKILL.md' 2>/dev/null [00:00:19 +58ms] --- [00:00:19 +0ms] name: cnb-knowledge-base [00:00:19 +0ms] description: 查询 CNB 平台官方文档,包括代码托管、制品库、AI 助手、云原生构建(CI/CD)、开发者工具等。 [00:00:19 +0ms] --- [00:00:19 +0ms] [00:00:19 +0ms] # CNB 知识库 [00:00:19 +0ms] [00:00:19 +0ms] 自动查询 CNB 云原生构建平台官方文档,为用户提供准确的使用指引和操作说明。 [00:00:19 +0ms] [00:00:19 +0ms] ## 文档来源 [00:00:19 +0ms] [00:00:19 +0ms] > 下方 URL 中的 `${CNB_WEB_PROTOCOL}` 和 `${CNB_WEB_HOST}` 为环境变量,使用前先 `echo` 获取实际值再拼接。 [00:00:19 +0ms] [00:00:19 +0ms] CNB 官方文档站点:`${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}` [00:00:19 +0ms] [00:00:19 +0ms] 提供两种文档索引: [00:00:19 +0ms] [00:00:19 +0ms] | 索引 | URL | 说明 | [00:00:19 +0ms] |------|-----|------| [00:00:19 +0ms] | 增量索引 | `${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}/zh/llms.txt` | 文档目录索引,包含所有文档的标题和路径链接 | [00:00:19 +0ms] | 全量文档 | `${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}/zh/llms-full.txt` | 包含所有文档的完整内容(体积较大) | [00:00:19 +0ms] [00:00:19 +0ms] ## 文档覆盖范围 [00:00:19 +0ms] [00:00:19 +0ms] CNB 文档涵盖以下主要领域: [00:00:19 +0ms] [00:00:19 +0ms] - **指南**:创建仓库、Git 认证、迁移工具、角色权限、访问令牌、部署令牌 [00:00:19 +0ms] - **代码托管**:密钥仓库、元数据、ISSUE 模板、分类标签、UI 定制 [00:00:19 +0ms] - **制品库**:Docker、Helm、Maven、npm、PyPI、Cargo、Nuget、Composer、ohpm 等 12 种制品库 [00:00:19 +0ms] - **AI 助手**:AI 助手简介、知识库、MCP Server、Code Wiki [00:00:19 +0ms] - **云原生开发**:开发环境、端口预览、IDE 客户端(VSCode/Cursor/JetBrains)、容器模式 [00:00:19 +0ms] - **云原生构建**:流水线配置、触发规则、语法手册、构建环境、环境变量、插件、缓存、定时任务、部署流程 [00:00:19 +0ms] - **开发者**:徽章、Open API [00:00:19 +0ms] - **OAuth 授权**:用户授权、OAuth 应用创建 [00:00:19 +0ms] - **其他**:FAQ、定价、SLA、任务集等 [00:00:19 +0ms] [00:00:19 +0ms] ## 使用流程 [00:00:19 +0ms] [00:00:19 +0ms] ### 第一步:分析用户问题 [00:00:19 +0ms] [00:00:19 +0ms] 仔细分析用户提出的问题,提取关键词,判断用户想了解哪个领域的文档。 [00:00:19 +0ms] [00:00:19 +0ms] ### 第二步:获取文档索引 [00:00:19 +0ms] [00:00:19 +0ms] 使用 WebFetch 获取文档目录索引: [00:00:19 +0ms] [00:00:19 +0ms] ``` [00:00:19 +0ms] WebFetch url: ${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}/zh/llms.txt [00:00:19 +0ms] prompt: 列出所有文档的标题和路径链接,帮我找到与「{用户问题的关键词}」相关的文档路径 [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] ### 第三步:获取具体文档内容 [00:00:19 +0ms] [00:00:19 +0ms] 根据索引中匹配到的文档路径,拼接完整 URL 并获取文档内容: [00:00:19 +0ms] [00:00:19 +0ms] ``` [00:00:19 +0ms] WebFetch url: ${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}{文档路径} [00:00:19 +1ms] prompt: 提取这篇文档的完整内容,保留代码示例和配置说明 [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] **注意**:索引中的路径格式为 `/zh/category/topic.md`,拼接后完整 URL 为 `${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}/zh/category/topic.md`。 [00:00:19 +0ms] [00:00:19 +0ms] ### 第四步:整理并回答 [00:00:19 +0ms] [00:00:19 +0ms] 将获取到的文档内容整理后,根据用户问题: [00:00:19 +0ms] 1. 提取与用户问题最相关的内容 [00:00:19 +0ms] 2. 保留重要的代码示例和配置片段 [00:00:19 +0ms] 3. 简明呈现给用户 [00:00:19 +0ms] 4. 内容较长时适当精简,并附原文档链接 [00:00:19 +0ms] [00:00:19 +0ms] ## 注意事项 [00:00:19 +0ms] [00:00:19 +0ms] - 如果增量索引未找到相关文档,可尝试全量文档 `${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}/zh/llms-full.txt` [00:00:19 +0ms] - 单个文档无法完全回答时,可获取多个文档综合回答 [00:00:19 +0ms] - 始终基于官方文档回答,不臆造信息 [00:00:19 +1ms] - 附带文档来源链接 [00:00:19 +0ms] exit code: 0, signal: 0, duration: 59ms [00:00:19 +4ms] $ test -d ~/'.codebuddy/skills/cnb-pipeline' && echo dir || (test -f ~/'.codebuddy/skills/cnb-pipeline' && echo file || echo other) [00:00:19 +68ms] dir [00:00:19 +2ms] exit code: 0, signal: 0, duration: 69ms [00:00:19 +4ms] $ cat ~/'.codebuddy/skills/cnb-pipeline/SKILL.md' 2>/dev/null [00:00:19 +66ms] --- [00:00:19 +1ms] name: cnb-pipeline [00:00:19 +0ms] description: 编写/修改 .cnb.yml 配置,诊断流水线失败原因,优化构建性能。 [00:00:19 +0ms] supports: cnb [00:00:19 +0ms] --- [00:00:19 +0ms] [00:00:19 +0ms] # CNB 流水线配置与诊断 [00:00:19 +0ms] [00:00:19 +0ms] 生成/修改 `.cnb.yml` 配置文件,诊断流水线失败,优化构建性能。 [00:00:19 +0ms] [00:00:19 +0ms] > 本文档 URL 中的 `${CNB_WEB_PROTOCOL:-https}` 和 `${CNB_WEB_HOST:-cnb.cool}` 为环境变量,使用前先 `echo` 获取实际值再拼接。 [00:00:19 +0ms] [00:00:19 +0ms] ## 模式判定 [00:00:19 +0ms] [00:00:19 +0ms] 根据用户意图自动选择工作模式: [00:00:19 +0ms] [00:00:19 +0ms] - **配置模式**(写/改流水线)→ 走下方「配置工作流程」 [00:00:19 +0ms] - **诊断模式**(失败/报错/慢/优化)→ 走下方「诊断工作流程」 [00:00:19 +0ms] [00:00:19 +0ms] ## 配置工作流程 [00:00:19 +0ms] [00:00:19 +0ms] 1. **了解需求** -- 明确触发分支、事件、构建语言/环境、构建步骤、特殊需求。信息充足可直接生成。 [00:00:19 +0ms] 2. **查看现有配置** -- 修改场景下先读取 `.cnb.yml` 和 `.ci/` 目录。 [00:00:19 +0ms] 3. **按需加载文档** -- 遇到不确定的语法细节时,先 `echo` 获取环境变量拼接文档 URL,再用 WebFetch 加载对应的深入文档链接;也可读取本 skill 的 `references/` 子目录下的参考文件。 [00:00:19 +0ms] 4. **生成配置** -- 按下方语法速查生成完整可运行的配置。 [00:00:19 +0ms] 5. **校验(必须)** -- 每次生成/修改后必须校验通过才能展示给用户。 [00:00:19 +0ms] 6. **解释配置** -- 简要说明关键部分。 [00:00:19 +0ms] [00:00:19 +0ms] ### 校验命令 [00:00:19 +0ms] [00:00:19 +0ms] ```bash [00:00:19 +0ms] [ -d validator/node_modules ] || npm install --prefix validator [00:00:19 +0ms] node validator/validate.js .cnb.yml [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] 两项均通过(`YAML 语法` + `Schema`)才算有效。`--refresh` 可强制更新 Schema 缓存。 [00:00:19 +0ms] [00:00:19 +0ms] ## 诊断工作流程 [00:00:19 +0ms] [00:00:19 +0ms] > 详细流程见 `references/diagnose-guide.md`,依赖 [cnb-api] skill。 [00:00:19 +0ms] [00:00:19 +0ms] 1. **确定构建 sn**(可选)-- 默认不传,CLI 自动解析;需指定时从 `cnb pulls check-status` 对应检查项的 `target_url` 末段取(勿用 `context` 字段)。 [00:00:19 +0ms] 2. **获取数据**: [00:00:19 +0ms] - 失败诊断:`cnb pulls get-ci-logs`(自动定位失败构建;也可加 `--sn` 指定) [00:00:19 +0ms] - 性能优化:通过 `cnb build --help` / `cnb pulls --help` 探索可用命令,获取 Stage 耗时与慢 Stage 日志 [00:00:19 +0ms] 3. **分析并输出报告** -- 判定失败类型或耗时瓶颈,给出修复/优化建议。配置相关问题结合语法速查分析。 [00:00:19 +0ms] [00:00:19 +0ms] --- [00:00:19 +0ms] [00:00:19 +0ms] ## 语法速查 [00:00:19 +0ms] [00:00:19 +0ms] ### 层级结构 [00:00:19 +0ms] [00:00:19 +0ms] ``` [00:00:19 +0ms] 分支 (main / "feature/*" / "$") [00:00:19 +0ms] └── 事件 (push / pull_request / tag_push ...) [00:00:19 +0ms] └── Pipeline(多条并发) [00:00:19 +0ms] └── Stage(顺序执行) [00:00:19 +0ms] └── Job(数组串行 / 对象并行) [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] ### 触发分支 [00:00:19 +0ms] [00:00:19 +0ms] ```yaml [00:00:19 +0ms] main: # 精确匹配 [00:00:19 +0ms] "feature/*": # 通配符 [00:00:19 +0ms] "(main|develop)": # 或匹配 [00:00:19 +0ms] "**/!(main|develop)": # 排除 [00:00:19 +0ms] "**": # 所有分支 [00:00:19 +0ms] "$": # 兜底(未被 glob 匹配的分支 + tag_push/issue 等) [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] ### 常用触发事件 [00:00:19 +0ms] [00:00:19 +0ms] | 事件 | 时机 | [00:00:19 +0ms] |------|------| [00:00:19 +0ms] | `push` | 推送代码 | [00:00:19 +0ms] | `pull_request` | PR 创建/重新打开/源分支 push | [00:00:19 +0ms] | `tag_push` | 推送 Tag | [00:00:19 +0ms] | `"crontab: 30 5 * * *"` | 定时任务 | [00:00:19 +0ms] | `web_trigger` / `api_trigger` | 手动/API 触发 | [00:00:19 +0ms] [00:00:19 +0ms] > 完整事件列表及代码版本说明见 `references/syntax-reference.md` 或在线文档:${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}/zh/build/trigger-rule.md [00:00:19 +0ms] [00:00:19 +0ms] ### Pipeline 骨架 [00:00:19 +0ms] [00:00:19 +0ms] ```yaml [00:00:19 +0ms] main: [00:00:19 +0ms] push: [00:00:19 +0ms] - name: ci [00:00:19 +0ms] runner: { cpus: 2 } [00:00:19 +0ms] docker: [00:00:19 +0ms] image: node:20 # 或 build (Dockerfile) 或 devcontainer [00:00:19 +0ms] services: [docker] # Docker-in-Docker [00:00:19 +0ms] env: { NODE_ENV: production } [00:00:19 +0ms] imports: [./secrets.yml] [00:00:19 +0ms] stages: [...] [00:00:19 +0ms] failStages: [...] # 仅失败时执行 [00:00:19 +0ms] endStages: [...] # 始终执行 [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] ### Stage [00:00:19 +0ms] [00:00:19 +0ms] ```yaml [00:00:19 +0ms] stages: [00:00:19 +0ms] - name: install [00:00:19 +0ms] script: npm ci [00:00:19 +0ms] timeout: 10m [00:00:19 +0ms] retry: 2 [00:00:19 +0ms] allowFailure: true [00:00:19 +0ms] ifModify: ["**/*.ts"] [00:00:19 +0ms] image: node:18 # 覆盖 Pipeline 镜像 [00:00:19 +0ms] env: { KEY: value } [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] ### Job(三种类型) [00:00:19 +0ms] [00:00:19 +0ms] ```yaml [00:00:19 +0ms] # 脚本任务 [00:00:19 +0ms] - name: build [00:00:19 +0ms] script: npm run build [00:00:19 +0ms] [00:00:19 +0ms] # 插件任务 [00:00:19 +0ms] - name: docker-push [00:00:19 +0ms] image: plugins/docker [00:00:19 +0ms] settings: { repo: myrepo/app, tags: [$CNB_BRANCH] } [00:00:19 +0ms] [00:00:19 +0ms] # 内置任务 [00:00:19 +0ms] - name: trigger [00:00:19 +0ms] type: cnb:trigger [00:00:19 +0ms] options: { slug: org/other-repo, branch: main, event: api_trigger } [00:00:19 +0ms] exports: { sn: BUILD_SN } [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] **并发模式**:`jobs` 为数组时串行,为对象时并行。 [00:00:19 +0ms] [00:00:19 +0ms] ### 环境变量(速查) [00:00:19 +0ms] [00:00:19 +0ms] ```yaml [00:00:19 +0ms] env: { MY_VAR: value } # 声明 [00:00:19 +0ms] imports: [./secrets.yml] # 导入密钥仓库 [00:00:19 +0ms] exports: { VERSION: MY_VERSION } # 跨 Stage 传递 [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] 脚本中输出 `##[set-output key=value]` 可导出变量。 [00:00:19 +0ms] [00:00:19 +0ms] > 详细用法见 `references/env-variables.md` 或在线文档:${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}/zh/build/env.md [00:00:19 +0ms] [00:00:19 +0ms] ### 常用内置变量 [00:00:19 +0ms] [00:00:19 +0ms] | 变量 | 说明 | [00:00:19 +0ms] |------|------| [00:00:19 +0ms] | `CNB_BRANCH` | 分支/Tag 名 | [00:00:19 +0ms] | `CNB_COMMIT` / `CNB_COMMIT_SHORT` | Commit SHA | [00:00:19 +0ms] | `CNB_REPO_SLUG` | 仓库路径 | [00:00:19 +0ms] | `CNB_BUILD_ID` | 构建 ID | [00:00:19 +1ms] | `CNB_TOKEN` | 构建凭证 | [00:00:19 +0ms] | `CNB_EVENT` | 事件名 | [00:00:19 +0ms] | `CNB_PULL_REQUEST_IID` | PR 编号 | [00:00:19 +0ms] [00:00:19 +0ms] > 完整列表:${CNB_WEB_PROTOCOL:-https}://docs.${CNB_WEB_HOST:-cnb.cool}/zh/build/build-in-env.md [00:00:19 +0ms] [00:00:19 +0ms] ### Include 和 !reference [00:00:19 +0ms] [00:00:19 +0ms] ```yaml [00:00:19 +0ms] include: [00:00:19 +0ms] - .ci/build.yml # 本地 [00:00:19 +0ms] - "${CNB_WEB_ENDPOINT:-https://cnb.cool}/org/tpl/-/blob/main/ci.yml" # 远程 [00:00:19 +0ms] [00:00:19 +0ms] docker: !reference [.docker-config] # 引用对象 [00:00:19 +0ms] stages: !reference [.common-pipeline, stages] # 多级路径引用 [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] ### 数据卷缓存 [00:00:19 +0ms] [00:00:19 +0ms] ```yaml [00:00:19 +0ms] docker: [00:00:19 +0ms] volumes: [00:00:19 +0ms] - node_modules # cow(默认,写时复制) [00:00:19 +0ms] - cache:/root/.npm:rw # 读写 [00:00:19 +0ms] - shared:/data:data # 临时数据卷(Pipeline 内共享) [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] --- [00:00:19 +0ms] [00:00:19 +0ms] ## 详细参考文档 [00:00:19 +0ms] [00:00:19 +0ms] 需要深入了解某个主题时,读取以下文件: [00:00:19 +0ms] [00:00:19 +0ms] | 文件 | 内容 | [00:00:19 +0ms] |------|------| [00:00:19 +0ms] | `references/syntax-reference.md` | 完整触发事件列表、Pipeline/Stage/Job 全部字段、变量替换规则、include 合并规则 | [00:00:19 +0ms] | `references/builtin-tasks.md` | 所有内置任务类型(cnb:trigger、git:release 等)及参数说明 | [00:00:19 +0ms] | `references/env-variables.md` | 环境变量声明/导入/导出/传递的完整用法 | [00:00:19 +0ms] | `references/best-practices.md` | YAML 锚点复用、按功能拆分 .ci/ 目录、Pipeline 编排等最佳实践 | [00:00:19 +0ms] | `references/diagnose-guide.md` | CI 失败诊断流程、性能优化分析流程、失败类型判定表、常见优化点 | [00:00:19 +0ms] [00:00:19 +0ms] --- [00:00:19 +0ms] [00:00:19 +0ms] ## 注意事项 [00:00:19 +0ms] [00:00:19 +0ms] 1. **YAML 缩进**用空格,不用 Tab [00:00:19 +0ms] 2. **分支名含特殊字符**需引号包裹:`"feature/*"` [00:00:19 +0ms] 3. **并发模型**:同事件多 Pipeline 并发;Pipeline 内 Stage 顺序;Stage 内 jobs 数组串行、对象并行 [00:00:19 +0ms] 4. **PR 安全限制**:PR 类事件 `CNB_TOKEN` 权限受限,敏感操作放 `push` / `pull_request.target` / `tag_push` [00:00:19 +0ms] 5. **YAML 锚点仅限单文件**:跨文件用 `!reference`(只能引用值,不能合并展开) [00:00:19 +0ms] 6. **`!reference` 引用键名必须全局唯一**:跨文件共享时加文件/模块前缀避免冲突 [00:00:19 +0ms] 7. **变量值上限 100KiB**,变量名只能含字母/数字/下划线且不能数字开头 [00:00:19 +0ms] exit code: 0, signal: 0, duration: 68ms [00:00:19 +8ms] $ test -d ~/'.codebuddy/skills/code-commit' && echo dir || (test -f ~/'.codebuddy/skills/code-commit' && echo file || echo other) [00:00:19 +68ms] dir [00:00:19 +2ms] exit code: 0, signal: 0, duration: 69ms [00:00:19 +4ms] $ cat ~/'.codebuddy/skills/code-commit/SKILL.md' 2>/dev/null [00:00:19 +56ms] --- [00:00:19 +0ms] name: code-commit [00:00:19 +0ms] description: 编写代码、提交推送并创建 PR,适用于功能开发、Bug 修复、重构优化等场景。 [00:00:19 +0ms] --- [00:00:19 +0ms] [00:00:19 +0ms] # 自动编码并提交推送 [00:00:19 +0ms] [00:00:19 +0ms] 根据用户需求选择: [00:00:19 +0ms] 1. 新建分支 -> 编写代码 -> 推送代码 -> 并创建 PR [00:00:19 +0ms] 2. 切换到 PR 源分支 -> 编写代码 -> 推送代码更新 PR [00:00:19 +1ms] [00:00:19 +0ms] ## 步骤 [00:00:19 +0ms] [00:00:19 +0ms] ### 1. 理解需求 [00:00:19 +0ms] [00:00:19 +0ms] 分析用户输入,明确要修改的文件、功能/Bug 描述、目标分支(PR 的 base)。 [00:00:19 +0ms] 如需了解项目结构,直接在当前工作区读取代码。如需了解 PR 变更,可使用 pr-diff Skill。 [00:00:19 +0ms] [00:00:19 +0ms] ### 2. 判断场景并准备分支 [00:00:19 +0ms] [00:00:19 +0ms] 根据触发场景切换到正确的工作分支: [00:00:19 +0ms] [00:00:19 +0ms] - **PR 评论触发**(`CNB_PULL_REQUEST_IID` 存在):在此分支上继续修改 [00:00:19 +0ms] ```bash [00:00:19 +0ms] git checkout "$CNB_PULL_REQUEST_BRANCH" [00:00:19 +0ms] git pull origin "$CNB_PULL_REQUEST_BRANCH" [00:00:19 +0ms] ``` [00:00:19 +0ms] - **ISSUE 评论触发** PR 已存在,则切换到 PR 源分支继续开发 [00:00:19 +0ms] ```bash [00:00:19 +0ms] git checkout && git pull [00:00:19 +0ms] ``` [00:00:19 +0ms] - **ISSUE 评论触发** PR 不存在,则基于目标分支创建新分支 `auto/{关键词1}-{关键词2}-{4位随机后缀}` [00:00:19 +0ms] ```bash [00:00:19 +0ms] git checkout -b auto/{关键词1}-{关键词2}-$(openssl rand -hex 2) [00:00:19 +0ms] ``` [00:00:19 +0ms] > ⚠️ **分支命名精简规则**: [00:00:19 +0ms] > - `{关键词}`:从 ISSUE 标题/描述中提取 **2 个核心关键词**(名词或动词),用短横线连接,每个关键词不超过 2 个英文单词 [00:00:19 +0ms] > - `{随机后缀}`:固定 4 位十六进制,用 `$(openssl rand -hex 2)` 生成 [00:00:19 +0ms] > - **总长度控制**:分支名 `auto/` 之后的部分不超过 20 个字符 [00:00:19 +0ms] > - **示例**:`auto/optimize-skill-3a7f`、`auto/login-error-b2c1` [00:00:19 +0ms] [00:00:19 +0ms] ### 3. 编写代码 [00:00:19 +0ms] [00:00:19 +0ms] 直接在工作区中读取和修改文件,实现代码变更。遵循项目已有的代码风格,确保 import/依赖完整。 [00:00:19 +0ms] [00:00:19 +0ms] ### 4. 验证与提交 [00:00:19 +0ms] [00:00:19 +0ms] ```bash [00:00:19 +0ms] # 查看变更概览 [00:00:19 +0ms] git diff --stat [00:00:19 +0ms] # 如有构建/lint 命令则执行验证 [00:00:19 +0ms] # 暂存并提交 [00:00:19 +0ms] git add -A [00:00:19 +0ms] git commit -m "{类型}: {简短描述}" [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] 类型:`feat`(新功能) / `fix`(修复) / `refactor`(重构) / `docs`(文档) / `chore`(其他) [00:00:19 +0ms] [00:00:19 +0ms] ### 5. 推送变更并判断是否需要创建 PR [00:00:19 +0ms] [00:00:19 +0ms] ```bash [00:00:19 +0ms] # 推送当前分支 [00:00:19 +0ms] git push origin HEAD [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] 根据推送输出判断是否已有 PR: [00:00:19 +0ms] [00:00:19 +0ms] - **已有 PR**(输出包含 `There is already has pull request`):跳过创建 PR,直接在评论中告知用户 [00:00:19 +0ms] - **无 PR**(输出包含 `Create a pull request` 或 `new branch`):走第 6 步创建 PR [00:00:19 +0ms] [00:00:19 +0ms] > ⚠️ 只有新建分支且推送后确认无 PR 时,才执行第 6 步。 [00:00:19 +0ms] [00:00:19 +0ms] **示例 1 — 已有 PR,跳过创建:** [00:00:19 +0ms] ``` [00:00:19 +0ms] $ git push origin HEAD [00:00:19 +0ms] remote: [00:00:19 +0ms] remote: There is already has pull request for 'fix/optimize-code-commit-skill' by visiting: [00:00:19 +0ms] remote: [00:00:19 +0ms] remote: https://cnb.cool/cnb/skills/cnb-skill/-/pulls/140 [00:00:19 +0ms] remote: [00:00:19 +0ms] To https://cnb.cool/cnb/skills/cnb-skill.git [00:00:19 +0ms] e3d8f95..639bd55 HEAD -> fix/optimize-code-commit-skill [00:00:19 +0ms] [00:00:19 +0ms] # 输出包含 "There is already has pull request" → 已有 PR,不再创建 [00:00:19 +0ms] # 在评论中告知用户:PR 已存在,代码已推送到 PR #140 [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] **示例 2 — 无 PR,需要创建:** [00:00:19 +0ms] ``` [00:00:19 +0ms] $ git push origin HEAD [00:00:19 +0ms] remote: [00:00:19 +0ms] remote: Create a pull request for 'fix/optimize-code-commit-skill' to 'main' by visiting: [00:00:19 +0ms] remote: [00:00:19 +0ms] remote: https://cnb.cool/cnb/skills/cnb-skill/-/compare/main...fix/optimize-code-commit-skill [00:00:19 +0ms] remote: [00:00:19 +0ms] To https://cnb.cool/cnb/skills/cnb-skill.git [00:00:19 +0ms] * [new branch] fix/optimize-code-commit-skill -> fix/optimize-code-commit-skill [00:00:19 +0ms] [00:00:19 +0ms] # 输出包含 "Create a pull request" → 无 PR,需要走第 6 步创建 [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] ### 6. 创建 PR(仅推送后确认无 PR 时执行) [00:00:19 +0ms] [00:00:19 +0ms] ```bash [00:00:19 +0ms] # 创建 PR [00:00:19 +0ms] cnb pulls post-pull --repo "$CNB_REPO_SLUG" \ [00:00:19 +0ms] --base "$CNB_DEFAULT_BRANCH" \ [00:00:19 +0ms] --head "$(git branch --show-current)" \ [00:00:19 +0ms] --title "{类型}: {简短描述}" \ [00:00:19 +0ms] --body "{变更目的与主要改动点}\n\nRef #{ISSUE编号}" [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] > ⚠️ **必须引用 Issue**:由 ISSUE 评论触发创建 PR 时,PR body 末尾必须包含 `Ref #{ISSUE编号}`(如 `Ref #149`),这样 Issue 侧边栏才会自动显示关联的 PR。ISSUE 编号从环境变量 `$CNB_ISSUE_IID` 获取。 [00:00:19 +0ms] [00:00:19 +0ms] ## 注意事项 [00:00:19 +0ms] [00:00:19 +0ms] - 编码前先理解项目结构和代码风格 [00:00:19 +0ms] - 需求不明确或范围过大时,先在评论中确认再执行 [00:00:19 +0ms] - 不修改无关文件,推送前确认变更正确 [00:00:19 +0ms] - 生成/修改 `.cnb.yml` 文件时需使用 cnb-pipeline skill 技能 [00:00:19 +0ms] [00:00:19 +0ms] ## 禁止的操作 [00:00:19 +0ms] [00:00:19 +0ms] - ❌ PR 不存在时,禁止在默认分支上修改代码,需新建分支并创建 PR [00:00:19 +1ms] - ❌ `git push --force`(不要强制推送,除非用户明确要求;如需覆盖可用 `--force-with-lease`) [00:00:19 +0ms] exit code: 0, signal: 0, duration: 58ms [00:00:19 +5ms] $ test -d ~/'.codebuddy/skills/code-review' && echo dir || (test -f ~/'.codebuddy/skills/code-review' && echo file || echo other) [00:00:19 +59ms] dir [00:00:19 +2ms] exit code: 0, signal: 0, duration: 60ms [00:00:19 +4ms] $ cat ~/'.codebuddy/skills/code-review/SKILL.md' 2>/dev/null [00:00:19 +64ms] --- [00:00:19 +1ms] name: code-review [00:00:19 +0ms] description: PR 代码评审,检查安全漏洞、Bug 和代码质量,输出结构化结果并通过 API 发送行级评论。 [00:00:19 +0ms] --- [00:00:19 +0ms] [00:00:19 +0ms] # PR 代码评审 [00:00:19 +0ms] [00:00:19 +0ms] 对 PR 的代码变更进行专业评审,发现安全漏洞、Bug、代码质量和性能问题,并通过 PR Review API 发送行级评论。 [00:00:19 +0ms] [00:00:19 +0ms] ## 评审步骤 [00:00:19 +0ms] [00:00:19 +0ms] ### 1. 获取 PR 变更 [00:00:19 +0ms] [00:00:19 +0ms] 使用 pr-diff Skill 获取 PR 的代码变更。 [00:00:19 +0ms] [00:00:19 +0ms] **需过滤的非代码文件**(不评审): [00:00:19 +0ms] - 依赖锁文件:`package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`, `go.sum`, `Cargo.lock` 等 [00:00:19 +0ms] - 图片文件:`*.png`, `*.jpg`, `*.gif`, `*.svg`, `*.ico` 等 [00:00:19 +0ms] - 字体文件:`*.woff`, `*.ttf`, `*.eot` 等 [00:00:19 +0ms] - 二进制文件:`*.exe`, `*.dll`, `*.so`, `*.jar`, `*.pyc` 等 [00:00:19 +0ms] - 压缩文件:`*.zip`, `*.tar.gz`, `*.rar` 等 [00:00:19 +0ms] - 压缩的代码:`*.min.js`, `*.min.css`, `*.map` [00:00:19 +0ms] - 构建产物目录:`dist/`, `build/`, `out/`, `target/`, `.next/` [00:00:19 +0ms] - 依赖目录:`node_modules/`, `vendor/`, `.venv/` [00:00:19 +0ms] [00:00:19 +0ms] **文件限制**: [00:00:19 +0ms] - 最多评审 30 个文件 [00:00:19 +0ms] - diff 最大 100000 字符(超出则截断) [00:00:19 +0ms] [00:00:19 +0ms] ### 2. 分析代码 [00:00:19 +0ms] [00:00:19 +0ms] **评审重点**(按优先级): [00:00:19 +0ms] [00:00:19 +0ms] 1. **安全漏洞**:SQL 注入、XSS、CSRF、硬编码凭证、敏感信息泄露、不安全加密 [00:00:19 +0ms] 2. **潜在 Bug**:空指针、数组越界、并发问题、资源泄漏、异常处理不当 [00:00:19 +0ms] 3. **代码质量**:可读性、命名规范、代码重复 [00:00:19 +0ms] 4. **性能问题**:N+1 查询、低效算法、不必要的 I/O [00:00:19 +0ms] [00:00:19 +0ms] **评审原则**: [00:00:19 +0ms] - 只评审新增代码(diff 中 `+` 开头的行,不含 `+++` 文件头) [00:00:19 +0ms] - **禁止评审**:删除的代码(`-` 开头)、上下文代码、未修改的代码 [00:00:19 +0ms] - **忽略**:EOF 换行符、行尾空格、缩进风格(应由 linter 处理) [00:00:19 +0ms] [00:00:19 +0ms] **理解上下文**: [00:00:19 +0ms] 当 diff 上下文不足以理解代码时(如需要看函数定义、类型、依赖关系),使用 Read 工具读取相关源文件理解上下文,并确认准确行号。 [00:00:19 +0ms] [00:00:19 +0ms] ### 3. 输出评审结果 [00:00:19 +0ms] [00:00:19 +0ms] **必须严格输出以下 JSON 格式**: [00:00:19 +0ms] [00:00:19 +0ms] ```json [00:00:19 +0ms] { [00:00:19 +0ms] "status": "passed | needs_modification | critical", [00:00:19 +0ms] "issues": [ [00:00:19 +0ms] { [00:00:19 +0ms] "severity": "critical | warning | info", [00:00:19 +0ms] "file": "文件路径", [00:00:19 +0ms] "start_line": 起始行号, [00:00:19 +0ms] "end_line": 结束行号, [00:00:19 +0ms] "problem": "问题:描述问题", [00:00:19 +0ms] "suggestion": "建议:修复建议" [00:00:19 +0ms] } [00:00:19 +0ms] ] [00:00:19 +0ms] } [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] **字段说明**: [00:00:19 +0ms] - `status`: 评审状态 [00:00:19 +0ms] - `passed`: 通过,无问题 [00:00:19 +0ms] - `needs_modification`: 需要修改 [00:00:19 +0ms] - `critical`: 存在严重问题 [00:00:19 +0ms] - `severity`: 问题严重程度 [00:00:19 +0ms] - `critical`: 严重(安全漏洞、崩溃 Bug) [00:00:19 +0ms] - `warning`: 警告(潜在问题) [00:00:19 +0ms] - `info`: 建议(代码质量改进) [00:00:19 +0ms] - `start_line` / `end_line`: 问题代码的行号范围(对应新文件行号) [00:00:19 +0ms] - `problem` / `suggestion`: 使用 Markdown 格式,提高可读性 [00:00:19 +0ms] - 使用 \`代码\` 标记变量名、函数名 [00:00:19 +0ms] - 使用代码块展示修复示例 [00:00:19 +0ms] [00:00:19 +0ms] **无问题时**:`issues` 为空数组 `[]` [00:00:19 +0ms] [00:00:19 +0ms] ### 4. 发送评审评论 [00:00:19 +0ms] [00:00:19 +0ms] **重要**:API 基础地址从环境变量 `CNB_API_ENDPOINT` 获取(默认 `https://api.cnb.cool`),仓库名从环境变量 `CNB_REPO_SLUG` 获取,PR 编号从环境变量 `CNB_PULL_REQUEST_IID` 获取。 [00:00:19 +0ms] [00:00:19 +0ms] **有问题时**:调用 PostPullReview 接口发送行级评审评论: [00:00:19 +0ms] [00:00:19 +0ms] ```bash [00:00:19 +0ms] curl -X POST \ [00:00:19 +0ms] "${CNB_API_ENDPOINT:-https://api.cnb.cool}/${CNB_REPO_SLUG}/-/pulls/${CNB_PULL_REQUEST_IID}/reviews" \ [00:00:19 +0ms] -H "Accept: application/vnd.cnb.api+json" \ [00:00:19 +0ms] -H "Authorization: Bearer $CNB_TOKEN" \ [00:00:19 +0ms] -H "Content-Type: application/json" \ [00:00:19 +0ms] -d '{ [00:00:19 +0ms] "body": "**评审结果**: 需要修改", [00:00:19 +0ms] "event": "comment", [00:00:19 +0ms] "comments": [ [00:00:19 +0ms] { [00:00:19 +0ms] "body": "问题: ...\n建议: ...", [00:00:19 +0ms] "path": "文件路径", [00:00:19 +0ms] "start_line": 起始行号, [00:00:19 +0ms] "start_side": "right", [00:00:19 +0ms] "end_line": 结束行号, [00:00:19 +0ms] "end_side": "right", [00:00:19 +0ms] "subject_type": "line" [00:00:19 +0ms] } [00:00:19 +0ms] ] [00:00:19 +0ms] }' [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] **无问题时**:调用 PostPullComment 接口发送总结评论: [00:00:19 +0ms] [00:00:19 +0ms] ```bash [00:00:19 +0ms] curl -X POST \ [00:00:19 +0ms] "${CNB_API_ENDPOINT:-https://api.cnb.cool}/${CNB_REPO_SLUG}/-/pulls/${CNB_PULL_REQUEST_IID}/comments" \ [00:00:19 +0ms] -H "Accept: application/vnd.cnb.api+json" \ [00:00:19 +0ms] -H "Authorization: Bearer $CNB_TOKEN" \ [00:00:19 +0ms] -H "Content-Type: application/json" \ [00:00:19 +0ms] -d '{ [00:00:19 +0ms] "body": "**评审结果**: 通过\n\n代码质量良好,未发现明显问题。" [00:00:19 +0ms] }' [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] ## 注意事项 [00:00:19 +0ms] [00:00:19 +0ms] 1. **最多发送 10 条评论**,优先发送严重程度高的问题(critical > warning > info) [00:00:19 +0ms] 2. 行号必须对应 diff 中的**新文件行号**(右侧行号),务必通过读取源文件确认 [00:00:19 +0ms] 3. 每条评论需说明问题原因和修复建议 [00:00:19 +1ms] 4. 评审结果必须是有效 JSON [00:00:19 +0ms] exit code: 0, signal: 0, duration: 66ms [00:00:19 +5ms] $ test -d ~/'.codebuddy/skills/knowledge-base' && echo dir || (test -f ~/'.codebuddy/skills/knowledge-base' && echo file || echo other) [00:00:19 +58ms] dir [00:00:19 +2ms] exit code: 0, signal: 0, duration: 59ms [00:00:19 +4ms] $ cat ~/'.codebuddy/skills/knowledge-base/SKILL.md' 2>/dev/null [00:00:19 +68ms] --- [00:00:19 +1ms] name: knowledge-base [00:00:19 +0ms] description: 检索指定仓库的知识库,返回相关的文本片段及其来源。 [00:00:19 +0ms] --- [00:00:19 +0ms] [00:00:19 +0ms] ## 使用场景 [00:00:19 +0ms] [00:00:19 +0ms] - 检索指定仓库的知识库,返回与问题最相关的文本片段及其来源,用于回答用户问题 [00:00:19 +0ms] [00:00:19 +0ms] ## 执行命令 [00:00:19 +0ms] [00:00:19 +0ms] ```bash [00:00:19 +0ms] cnb knowledge-base query-knowledge-base-get --repo / --query "<自然语言问题或关键词>" --top-k 5 [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] - `--repo`:仓库路径,如 `cnb/feedback`,**必填** [00:00:19 +0ms] - `--query`:查询语句,**必填** [00:00:19 +1ms] - `--top-k`:返回的片段数量,默认为 5, 非必填 [00:00:19 +0ms] exit code: 0, signal: 0, duration: 70ms [00:00:19 +5ms] $ test -d ~/'.codebuddy/skills/markitdown' && echo dir || (test -f ~/'.codebuddy/skills/markitdown' && echo file || echo other) [00:00:19 +62ms] dir [00:00:19 +2ms] exit code: 0, signal: 0, duration: 63ms [00:00:19 +7ms] $ cat ~/'.codebuddy/skills/markitdown/SKILL.md' 2>/dev/null [00:00:19 +59ms] --- [00:00:19 +0ms] name: markitdown [00:00:19 +0ms] description: 将多种文件格式(PDF、Office 文档、图片、网页内容、结构化数据)转换为针对大语言模型优化的 Markdown。适用场景包括:文档转 Markdown、从 PDF / Office 文件中提取文本、图片 OCR 等。 [00:00:19 +0ms] --- [00:00:19 +0ms] [00:00:19 +0ms] # MarkItDown [00:00:19 +0ms] [00:00:19 +0ms] ## 概述 [00:00:19 +0ms] [00:00:19 +0ms] MarkItDown 是一个 Python 工具,可以把各种文件格式转换为 Markdown,专为大语言模型和文本分析场景优化。它在输出干净、Token 高效的 Markdown 的同时,会保留文档结构(标题、列表、表格、超链接)。 [00:00:19 +0ms] [00:00:19 +0ms] ## 何时使用本 Skill [00:00:19 +0ms] [00:00:19 +0ms] 当用户有以下需求时,使用本 Skill: [00:00:19 +0ms] - 把文档转换成 Markdown 格式 [00:00:19 +0ms] - 从 PDF、Word、PowerPoint、Excel 文件中提取文本 [00:00:19 +0ms] - 对图片做 OCR 提取文字 [00:00:19 +0ms] - 把 HTML、EPUB 或网页内容转成 Markdown [00:00:19 +0ms] [00:00:19 +0ms] ## 核心能力 [00:00:19 +0ms] [00:00:19 +0ms] ### 1. 文档转换 [00:00:19 +0ms] [00:00:19 +0ms] 把 Office 文档和 PDF 转换为 Markdown,同时保留结构。 [00:00:19 +0ms] [00:00:19 +0ms] **支持的格式:** [00:00:19 +0ms] - PDF 文件 [00:00:19 +0ms] - Word 文档(DOCX) [00:00:19 +0ms] - PowerPoint 演示文稿(PPTX) [00:00:19 +0ms] - Excel 表格(XLSX、XLS) [00:00:19 +0ms] [00:00:19 +0ms] **基础用法:** [00:00:19 +1ms] ```python [00:00:19 +0ms] from markitdown import MarkItDown [00:00:19 +0ms] [00:00:19 +0ms] md = MarkItDown() [00:00:19 +0ms] result = md.convert("document.pdf") [00:00:19 +0ms] print(result.text_content) [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] **命令行:** [00:00:19 +0ms] ```bash [00:00:19 +0ms] markitdown document.pdf -o output.md [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] ### 2. 图片处理 [00:00:19 +0ms] [00:00:19 +0ms] 若前模型不支持读取图片内容时,使用此方法从图片中提取元数据与文字。 [00:00:19 +0ms] [00:00:19 +0ms] markitdown 进行图片 OCR 需要配置 LLM, 当前环境没有配置,所以 markitdown 无法进行图片 OCR。 [00:00:19 +0ms] [00:00:19 +0ms] 容器里已经装好 `tesseract-ocr`,并带了简体和繁体中文语言包: [00:00:19 +0ms] [00:00:19 +0ms] ```bash [00:00:19 +0ms] # 仅英文 [00:00:19 +0ms] tesseract image.png stdout [00:00:19 +0ms] [00:00:19 +0ms] # 中文 + 英文(截图/密集排版建议加 --psm 6) [00:00:19 +0ms] tesseract image.png stdout -l chi_sim+eng --psm 6 [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] 在 Python 中: [00:00:19 +0ms] ```python [00:00:19 +0ms] import pytesseract [00:00:19 +0ms] from PIL import Image [00:00:19 +0ms] [00:00:19 +0ms] text = pytesseract.image_to_string(Image.open("image.png"), lang="chi_sim+eng") [00:00:19 +0ms] print(text) [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] **关于 PDF:** MarkItDown 通过 `pdfminer` 处理文本型 PDF(无需 OCR)。对扫描件 / 纯图片 PDF,他无法识别内容,需要回落到 `tesseract`(可以先用 `poppler-utils` 里的 `pdftoppm` 把页面转成图片再识别)。 [00:00:19 +0ms] [00:00:19 +0ms] ### 3. 网页内容提取 [00:00:19 +0ms] [00:00:19 +0ms] 把基于网页的内容和电子书转成 Markdown。 [00:00:19 +0ms] [00:00:19 +0ms] **支持的格式:** [00:00:19 +0ms] - HTML 文件和网页 [00:00:19 +0ms] - EPUB 电子书 [00:00:19 +0ms] - RSS 订阅 [00:00:19 +0ms] [00:00:19 +0ms] ## 安装 [00:00:19 +0ms] [00:00:19 +0ms] [00:00:19 +0ms] **按需安装(指定功能):** [00:00:19 +0ms] ```bash [00:00:19 +0ms] pip install 'markitdown[pdf]' # PDF 支持 [00:00:19 +0ms] pip install 'markitdown[docx]' # Word 支持 [00:00:19 +0ms] pip install 'markitdown[pptx]' # PowerPoint 支持 [00:00:19 +0ms] pip install 'markitdown[xlsx]' # Excel 支持 [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] **完整安装(所有功能):** [00:00:19 +0ms] ```bash [00:00:19 +0ms] pip install 'markitdown[all]' [00:00:19 +0ms] ``` [00:00:19 +0ms] [00:00:19 +0ms] **要求:** [00:00:19 +0ms] - Python 3.10 或更高版本 [00:00:19 +1ms] exit code: 0, signal: 0, duration: 60ms [00:00:19 +4ms] $ test -d ~/'.codebuddy/skills/npc-delegate' && echo dir || (test -f ~/'.codebuddy/skills/npc-delegate' && echo file || echo other) [00:00:19 +55ms] dir [00:00:19 +2ms] exit code: 0, signal: 0, duration: 56ms [00:00:19 +4ms] $ cat ~/'.codebuddy/skills/npc-delegate/SKILL.md' 2>/dev/null [00:00:20 +70ms] --- [00:00:20 +0ms] name: npc-delegate [00:00:20 +0ms] description: 当任务复杂或需要特定专长时,主动召唤其他 NPC 协同工作。 [00:00:20 +0ms] --- [00:00:20 +0ms] [00:00:20 +0ms] # 召唤 NPC 协同工作 [00:00:20 +0ms] [00:00:20 +0ms] 当遇到以下情况时,应主动召唤其他 NPC: [00:00:20 +0ms] [00:00:20 +0ms] 1. **任务超出能力范围**:需要特定领域专家(如前端、测试、安全等) [00:00:20 +0ms] 2. **任务可并行处理**:多个子任务可同时进行 [00:00:20 +0ms] 3. **需要跨仓库协作**:涉及其他仓库的代码或功能 [00:00:20 +0ms] 4. **其他 NPC 更擅长**:效率更高 [00:00:20 +0ms] [00:00:20 +0ms] ## 召唤流程 [00:00:20 +0ms] [00:00:20 +0ms] ### 1. 评估任务,决定是否召唤 [00:00:20 +0ms] [00:00:20 +0ms] 问自己: [00:00:20 +0ms] - 这个任务是否需要特定领域的专业知识? [00:00:20 +0ms] - 是否有其他 NPC 更擅长处理这个任务? [00:00:20 +0ms] - 任务是否可以拆解并并行处理? [00:00:20 +0ms] [00:00:20 +0ms] ### 2. 搜索合适的 NPC [00:00:20 +0ms] [00:00:20 +0ms] 使用 `npc-search` skill 搜索: [00:00:20 +0ms] [00:00:20 +0ms] ```bash [00:00:20 +0ms] cnb knowledge-base search-npc --key "关键词" --top-n 3 [00:00:20 +0ms] ``` [00:00:20 +0ms] [00:00:20 +0ms] 示例场景对应搜索词: [00:00:20 +0ms] | 场景 | 搜索关键词 | [00:00:20 +0ms] |------|-----------| [00:00:20 +0ms] | 需要代码审查 | `代码审查`、`CR` | [00:00:20 +0ms] | 需要写前端 | `前端开发`、`React` | [00:00:20 +0ms] | 需要写测试 | `单元测试`、`测试用例` | [00:00:20 +0ms] | 需要性能优化 | `性能优化`、`调优` | [00:00:20 +0ms] | 需要安全审计 | `安全`、`审计` | [00:00:20 +0ms] [00:00:20 +0ms] ### 3. 正确发起召唤 [00:00:20 +0ms] [00:00:20 +0ms] 找到合适的 NPC 后,使用正确的 @ 格式召唤: [00:00:20 +0ms] [00:00:20 +0ms] ``` [00:00:20 +0ms] @{slug}({name}) [00:00:20 +0ms] ``` [00:00:20 +0ms] [00:00:20 +0ms] 示例: [00:00:20 +0ms] - `@npc/hok(π)` - 仓库 `npc/hok` 下名为 `π` 的 NPC [00:00:20 +0ms] - `@npc/code-reviewer(代码审查员)` - 仓库 `npc/code-reviewer` [00:00:20 +0ms] [00:00:20 +0ms] ### 4. 传递完整的上下文 [00:00:20 +0ms] [00:00:20 +0ms] 召唤时提供充分信息: [00:00:20 +0ms] - **任务背景**:要解决的问题 [00:00:20 +0ms] - **相关文件**:涉及的代码或路径 [00:00:20 +0ms] - **约束条件**:技术栈、代码规范等 [00:00:20 +0ms] - **期望结果**:交付物形式 [00:00:20 +0ms] [00:00:20 +0ms] 示例召唤方式: [00:00:20 +0ms] [00:00:20 +0ms] ``` [00:00:20 +0ms] @npc/xxx 帮我审查 /workspace/src/auth 目录下的登录逻辑,重点关注: [00:00:20 +0ms] 1. 密码存储是否安全 [00:00:20 +0ms] 2. Session 管理是否有漏洞 [00:00:20 +0ms] 参考标准:OWASP Top 10 [00:00:20 +0ms] ``` [00:00:20 +0ms] [00:00:20 +0ms] ## 协同工作模式 [00:00:20 +0ms] [00:00:20 +0ms] 召唤成功后,可: [00:00:20 +0ms] [00:00:20 +0ms] 1. **分工协作**:拆分任务,各 NPC 处理一部分 [00:00:20 +0ms] 2. **串联审核**:一个 NPC 完成后,另一个继续优化 [00:00:20 +0ms] 3. **并行处理**:多个 NPC 同时处理独立任务 [00:00:20 +0ms] [00:00:20 +0ms] ## 何时主动建议召唤 [00:00:20 +0ms] [00:00:20 +0ms] 作为 AI,以下情况应主动建议用户召唤其他 NPC: [00:00:20 +0ms] [00:00:20 +0ms] - 需求明显超出当前 NPC 能力 [00:00:20 +0ms] - 任务涉及多个专业领域 [00:00:20 +0ms] - 任务耗时长,可拆解并行 [00:00:20 +0ms] [00:00:20 +0ms] ## 注意事项 [00:00:20 +0ms] [00:00:20 +0ms] - 召唤前先了解目标 NPC 的能力范围(通过 slogan 判断) [00:00:20 +0ms] - 尽量一次召唤到位,避免反复补充上下文 [00:00:20 +0ms] - 模糊需求先自行分析,再决定是否召唤 [00:00:20 +0ms] - 始终把控整体任务,即使分配了子任务 [00:00:20 +1ms] - 评论中如果只提及 npc 不召唤,应该去掉 `@` 符号,或使用反引号包裹 `@npc` [00:00:20 +0ms] exit code: 0, signal: 0, duration: 71ms [00:00:20 +5ms] $ test -d ~/'.codebuddy/skills/npc-search' && echo dir || (test -f ~/'.codebuddy/skills/npc-search' && echo file || echo other) [00:00:20 +61ms] dir [00:00:20 +2ms] exit code: 0, signal: 0, duration: 62ms [00:00:20 +5ms] $ cat ~/'.codebuddy/skills/npc-search/SKILL.md' 2>/dev/null [00:00:20 +62ms] --- [00:00:20 +0ms] name: npc-search [00:00:20 +0ms] description: 通过关键词语义搜索 CNB 平台上的公开 NPC 角色,帮助用户找到最适合当前需求的 NPC。 [00:00:20 +0ms] --- [00:00:20 +0ms] [00:00:20 +0ms] # 搜索 NPC 角色 [00:00:20 +0ms] [00:00:20 +0ms] 根据用户需求,通过关键词语义搜索 CNB 平台上的公开 NPC 角色,帮助用户找到最合适的 NPC。 [00:00:20 +0ms] [00:00:20 +0ms] ## 搜索步骤 [00:00:20 +0ms] [00:00:20 +0ms] ### 1. 提取搜索关键词 [00:00:20 +0ms] [00:00:20 +0ms] 分析用户的需求,提取最能描述目标 NPC 功能的关键词。例如: [00:00:20 +0ms] [00:00:20 +0ms] - 用户说"帮我找一个能做代码审查的 NPC" → 关键词:`代码审查` [00:00:20 +0ms] - 用户说"有没有写前端的 NPC" → 关键词:`前端开发` [00:00:20 +0ms] - 用户说"我需要一个 NPC 帮我写单元测试" → 关键词:`单元测试` [00:00:20 +0ms] [00:00:20 +0ms] ### 2. 执行搜索 [00:00:20 +0ms] [00:00:20 +0ms] ```bash [00:00:20 +0ms] cnb knowledge-base search-npc --key "关键词" [00:00:20 +0ms] ``` [00:00:20 +0ms] [00:00:20 +0ms] 可选参数: [00:00:20 +0ms] - `--top-n `:返回结果数量,最大 20(默认 10) [00:00:20 +0ms] [00:00:20 +0ms] ### 3. 解读搜索结果 [00:00:20 +0ms] [00:00:20 +0ms] 搜索结果包含以下字段: [00:00:20 +0ms] [00:00:20 +0ms] | 字段 | 说明 | [00:00:20 +0ms] |------|------| [00:00:20 +0ms] | `name` | NPC 角色名称 | [00:00:20 +0ms] | `slug` | NPC 所在仓库路径 | [00:00:20 +0ms] | `slogan` | NPC 简介/标语,描述其能力和特点 | [00:00:20 +0ms] | `score` | 语义匹配分数(越高越相关) | [00:00:20 +0ms] | `avatar` | NPC 头像路径 | [00:00:20 +0ms] [00:00:20 +0ms] ### 4. 选出最合适的 NPC [00:00:20 +0ms] [00:00:20 +0ms] 根据搜索结果,结合以下因素选出最合适的 NPC: [00:00:20 +0ms] [00:00:20 +0ms] 1. **匹配分数**(score):分数越高,语义匹配度越高 [00:00:20 +0ms] 2. **slogan 描述**:了解 NPC 能力定位,判断是否符合需求 [00:00:20 +0ms] 3. **角色名称**(name):通常反映专长领域 [00:00:20 +0ms] [00:00:20 +0ms] 选定后,NPC 的使用形式为 `@{slug}({name})`,其中 `slug` 是仓库路径,`name` 是角色名。 [00:00:20 +0ms] [00:00:20 +0ms] 例如:`@npc/hok(π)` 表示仓库 `npc/hok` 下名为 `π` 的 NPC 角色。 [00:00:20 +0ms] [00:00:20 +0ms] ## 注意事项 [00:00:20 +0ms] [00:00:20 +0ms] - 关键词应精准,避免过于宽泛 [00:00:20 +0ms] - 搜索结果不理想时,可换关键词重试 [00:00:20 +0ms] - slogan 为空的 NPC 可能缺少描述,优先推荐有明确 slogan 的 [00:00:20 +0ms] - 直接执行命令搜索,无需用户确认 [00:00:20 +1ms] - **npc提及**: 评论中直接 @npc 会召唤 npc 干活,如果只提及不召唤,应该去掉 `@` 符号,或使用反引号包裹 `@npc`。 [00:00:20 +0ms] exit code: 0, signal: 0, duration: 64ms [00:00:20 +5ms] $ test -d ~/'.codebuddy/skills/pr-diff' && echo dir || (test -f ~/'.codebuddy/skills/pr-diff' && echo file || echo other) [00:00:20 +57ms] dir [00:00:20 +1ms] exit code: 0, signal: 0, duration: 58ms [00:00:20 +5ms] $ cat ~/'.codebuddy/skills/pr-diff/SKILL.md' 2>/dev/null [00:00:20 +61ms] --- [00:00:20 +0ms] name: pr-diff [00:00:20 +0ms] description: 获取 PR 的 diff 变更信息。当需要查看 PR 代码变更、获取文件差异时使用此技能。 [00:00:20 +0ms] --- [00:00:20 +0ms] [00:00:20 +1ms] # 获取 PR Diff [00:00:20 +0ms] [00:00:20 +0ms] 获取 PR 的代码变更差异信息,用于代码评审、变更总结等场景。 [00:00:20 +0ms] [00:00:20 +0ms] ## 1. 判断场景并获取 SHA [00:00:20 +0ms] [00:00:20 +0ms] ### 场景 A:PR 评论触发(`CNB_PULL_REQUEST_IID` 存在) [00:00:20 +0ms] [00:00:20 +0ms] 直接从环境变量获取: [00:00:20 +0ms] - head SHA:`CNB_PULL_REQUEST_SHA` [00:00:20 +0ms] - target SHA:`CNB_PULL_REQUEST_TARGET_SHA` [00:00:20 +0ms] [00:00:20 +0ms] 若环境变量不存在,通过 API 查询当前 PR 详情。 [00:00:20 +0ms] [00:00:20 +0ms] ### 场景 B:Issue 或其他场景引用 PR [00:00:20 +0ms] [00:00:20 +0ms] 用户输入中提及了 PR 编号(如 `!45`),需要: [00:00:20 +0ms] 1. 从用户输入中解析 PR 编号 [00:00:20 +0ms] 2. 通过 API 查询该 PR 详情获取 SHA [00:00:20 +0ms] 3. fetch 对应的 commit(本地可能没有) [00:00:20 +0ms] [00:00:20 +0ms] ### API 查询 PR 详情 [00:00:20 +0ms] [00:00:20 +0ms] ```bash [00:00:20 +0ms] # 将 ${pr_iid} 替换为实际 PR 编号 [00:00:20 +0ms] pr_info=$(curl -s \ [00:00:20 +0ms] "${CNB_API_ENDPOINT:-https://api.cnb.cool}/${CNB_REPO_SLUG}/-/pulls/${pr_iid}" \ [00:00:20 +0ms] -H "Accept: application/vnd.cnb.api+json" \ [00:00:20 +0ms] -H "Authorization: Bearer $CNB_TOKEN") [00:00:20 +0ms] [00:00:20 +0ms] head_sha=$(echo "$pr_info" | jq -r '.head.sha') [00:00:20 +0ms] target_sha=$(echo "$pr_info" | jq -r '.base.sha') [00:00:20 +0ms] [00:00:20 +0ms] # 场景 B 需要确保本地有这些 commit [00:00:20 +0ms] git fetch origin "$head_sha" "$target_sha" 2>/dev/null || git fetch origin [00:00:20 +0ms] ``` [00:00:20 +0ms] [00:00:20 +0ms] ## 2. 获取 Diff [00:00:20 +0ms] [00:00:20 +0ms] ### 获取变更文件列表 [00:00:20 +0ms] [00:00:20 +0ms] ```bash [00:00:20 +0ms] git diff --name-only "${target_sha}...${head_sha}" [00:00:20 +0ms] ``` [00:00:20 +0ms] [00:00:20 +0ms] ### 获取变更统计 [00:00:20 +0ms] [00:00:20 +0ms] ```bash [00:00:20 +0ms] git diff --stat "${target_sha}...${head_sha}" [00:00:20 +0ms] ``` [00:00:20 +0ms] [00:00:20 +0ms] ### 获取完整 Diff [00:00:20 +0ms] [00:00:20 +0ms] ```bash [00:00:20 +0ms] git diff -U5 "${target_sha}...${head_sha}" [00:00:20 +0ms] ``` [00:00:20 +0ms] [00:00:20 +0ms] ### 获取特定文件的 Diff [00:00:20 +0ms] [00:00:20 +0ms] ```bash [00:00:20 +0ms] git diff -U5 "${target_sha}...${head_sha}" -- path/to/file.ts [00:00:20 +0ms] ``` [00:00:20 +0ms] [00:00:20 +0ms] ## 3. 过滤文件 [00:00:20 +0ms] [00:00:20 +0ms] 根据使用场景,可排除无需关注的文件: [00:00:20 +0ms] [00:00:20 +0ms] ```bash [00:00:20 +0ms] # 常见排除模式 [00:00:20 +0ms] git diff -U5 "${target_sha}...${head_sha}" -- . \ [00:00:20 +0ms] ':!package-lock.json' ':!yarn.lock' ':!pnpm-lock.yaml' ':!go.sum' ':!*.lock' \ [00:00:20 +0ms] ':!*.png' ':!*.jpg' ':!*.gif' ':!*.svg' ':!*.ico' \ [00:00:20 +0ms] ':!*.min.js' ':!*.min.css' ':!*.map' \ [00:00:20 +0ms] ':!dist/*' ':!build/*' ':!node_modules/*' [00:00:20 +0ms] ``` [00:00:20 +0ms] [00:00:20 +0ms] **可排除的文件类型**: [00:00:20 +0ms] - 锁文件:`package-lock.json`、`yarn.lock`、`pnpm-lock.yaml`、`go.sum`、`Cargo.lock` [00:00:20 +0ms] - 图片/字体:`*.png`、`*.jpg`、`*.gif`、`*.svg`、`*.woff`、`*.ttf` [00:00:20 +0ms] - 二进制:`*.exe`、`*.dll`、`*.so`、`*.jar`、`*.pyc` [00:00:20 +0ms] - 压缩包:`*.zip`、`*.tar.gz`、`*.rar` [00:00:20 +0ms] - 构建产物:`dist/`、`build/`、`out/`、`target/`、`.next/` [00:00:20 +0ms] - 依赖目录:`node_modules/`、`vendor/`、`.venv/` [00:00:20 +0ms] - 压缩文件:`*.min.js`、`*.min.css`、`*.map` [00:00:20 +0ms] [00:00:20 +0ms] ## 4. 使用建议 [00:00:20 +0ms] [00:00:20 +0ms] 1. **diff 过大时**:先用 `--name-only` 查看文件列表,再按需获取具体文件 [00:00:20 +0ms] 2. **代码评审**:建议排除锁文件、图片、构建产物 [00:00:20 +0ms] 3. **变更总结**:可保留更多文件,但排除二进制和依赖目录 [00:00:20 +0ms] 4. **上下文行数**:`-U5` 提供 5 行上下文,可按需调整 [00:00:20 +2ms] exit code: 0, signal: 0, duration: 64ms [00:00:20 +7ms] $ test -d ~/'.codebuddy/skills/pr-summary' && echo dir || (test -f ~/'.codebuddy/skills/pr-summary' && echo file || echo other) [00:00:20 +57ms] dir [00:00:20 +2ms] exit code: 0, signal: 0, duration: 59ms [00:00:20 +4ms] $ cat ~/'.codebuddy/skills/pr-summary/SKILL.md' 2>/dev/null [00:00:20 +66ms] --- [00:00:20 +0ms] name: pr-summary [00:00:20 +0ms] description: 总结 PR 变更内容,概述主要改动点并生成变更说明。 [00:00:20 +0ms] --- [00:00:20 +0ms] [00:00:20 +0ms] # PR 变更总结 [00:00:20 +0ms] [00:00:20 +0ms] 对 PR 的代码变更进行分析,生成结构化的变更总结。 [00:00:20 +0ms] [00:00:20 +0ms] ## 执行步骤 [00:00:20 +0ms] [00:00:20 +0ms] ### 1. 获取变更信息 [00:00:20 +0ms] [00:00:20 +0ms] 使用 **pr-diff** Skill 获取 PR 变更: [00:00:20 +0ms] - 先获取变更统计(`--stat`)和文件列表(`--name-only`) [00:00:20 +0ms] - 再按需获取关键文件的具体 diff [00:00:20 +0ms] [00:00:20 +0ms] ### 2. 过滤文件 [00:00:20 +0ms] [00:00:20 +0ms] **优先分析**(核心代码): [00:00:20 +0ms] - 业务逻辑:`src/`、`lib/`、`app/`、`packages/` [00:00:20 +0ms] - API/接口:`api/`、`routes/`、`controllers/` [00:00:20 +0ms] - 配置文件:`*.config.*`、`*.yml`、`*.yaml` [00:00:20 +0ms] - 数据库/模型:`models/`、`schema/`、`migrations/` [00:00:20 +0ms] [00:00:20 +0ms] **跳过**(非核心文件): [00:00:20 +0ms] - 依赖锁文件:`package-lock.json`、`yarn.lock`、`go.sum` [00:00:20 +0ms] - 构建产物:`dist/`、`build/`、`.next/` [00:00:20 +0ms] - 生成文件:`*.min.js`、`*.map` [00:00:20 +0ms] - 纯测试文件(除非测试是本次变更重点) [00:00:20 +0ms] [00:00:20 +0ms] ### 3. 分析变更 [00:00:20 +0ms] [00:00:20 +0ms] 按以下维度分析: [00:00:20 +0ms] [00:00:20 +0ms] | 维度 | 关注点 | [00:00:20 +0ms] |------|--------| [00:00:20 +0ms] | **变更类型** | feat(新功能)、fix(修复)、refactor(重构)、perf(性能)、docs(文档)、chore(配置/依赖) | [00:00:20 +0ms] | **影响范围** | 涉及哪些模块、影响哪些功能点 | [00:00:20 +0ms] | **关键改动** | 核心逻辑变更、API 变化、数据结构变更 | [00:00:20 +0ms] | **破坏性变更** | 不兼容改动、需要迁移的内容 | [00:00:20 +0ms] [00:00:20 +0ms] 若上下文不足以理解代码意图,使用 Read 工具读取完整源文件。 [00:00:20 +0ms] [00:00:20 +0ms] ## 输出格式 [00:00:20 +0ms] [00:00:20 +0ms] ```markdown [00:00:20 +0ms] **{type}**: {一句话描述} [00:00:20 +0ms] [00:00:20 +0ms] **主要改动** [00:00:20 +0ms] - {模块}: {变更说明} [00:00:20 +0ms] - {模块}: {变更说明} [00:00:20 +0ms] [00:00:20 +0ms] **注意**: {破坏性变更或风险点;如无则省略} [00:00:20 +0ms] ``` [00:00:20 +0ms] [00:00:20 +0ms] ## 总结原则 [00:00:20 +0ms] [00:00:20 +0ms] 1. **简洁明了**:突出重点,避免逐行复述 diff [00:00:20 +0ms] 2. **按功能分组**:按模块/功能组织,而非逐文件罗列 [00:00:20 +0ms] 3. **突出意图**:说明"为什么改"而非仅描述"改了什么" [00:00:20 +0ms] 4. **识别风险**:主动指出破坏性变更和需要关注的点 [00:00:20 +0ms] [00:00:20 +0ms] ## 大型 PR 处理 [00:00:20 +0ms] [00:00:20 +0ms] 当文件数超过 20 个时: [00:00:20 +0ms] 1. 先用 `--stat` 分析变更分布,按模块归类 [00:00:20 +0ms] 2. 重点分析核心模块变更(变更量大或涉及关键逻辑) [00:00:20 +0ms] 3. 在末尾概括未详细分析的文件/模块 [00:00:20 +2ms] exit code: 0, signal: 0, duration: 67ms [00:00:20 +4ms] $ test -d ~/'.codebuddy/skills/tapd-resource-fetcher' && echo dir || (test -f ~/'.codebuddy/skills/tapd-resource-fetcher' && echo file || echo other) [00:00:20 +68ms] dir [00:00:20 +2ms] exit code: 0, signal: 0, duration: 70ms [00:00:20 +5ms] $ cat ~/'.codebuddy/skills/tapd-resource-fetcher/SKILL.md' 2>/dev/null [00:00:20 +58ms] --- [00:00:20 +0ms] name: tapd-resource-fetcher [00:00:20 +0ms] description: 获取 TAPD 资源(需求/缺陷/任务/迭代),支持从 TAPD 链接自动解析。 [00:00:20 +0ms] --- [00:00:20 +0ms] [00:00:20 +0ms] # 获取 TAPD 资源 [00:00:20 +0ms] [00:00:20 +0ms] 从用户提供的 TAPD 链接中提取参数,调用 API 获取资源数据。 [00:00:20 +0ms] [00:00:20 +0ms] ## 1. 解析链接 [00:00:20 +0ms] [00:00:20 +0ms] 格式:`https://www.tapd.cn/tapd_fe/{workspace_id}/{type}/detail/{id}` [00:00:20 +0ms] [00:00:20 +0ms] - `type`: story / bug / task / iteration [00:00:20 +0ms] [00:00:20 +0ms] ## 2. 请求 [00:00:20 +0ms] [00:00:20 +0ms] ```bash [00:00:20 +0ms] curl -s "$CNB_API_ENDPOINT/tapd/reference/{workspace_id}/{type}/{id}" \ [00:00:20 +0ms] -H "Accept: application/vnd.cnb.api+json" \ [00:00:20 +0ms] -H "Authorization: Bearer $CNB_TOKEN" [00:00:20 +0ms] ``` [00:00:20 +0ms] [00:00:20 +0ms] 多个链接时逐个请求,汇总后统一展示。 [00:00:20 +0ms] [00:00:20 +0ms] ## 3. 响应处理 [00:00:20 +0ms] [00:00:20 +0ms] - HTTP 2xx 且 `data` 非空 → 返回 `data` 内容 [00:00:20 +0ms] - HTTP 2xx 但 `data` 为 `[]` → 提示"未找到该资源,请检查资源 ID" [00:00:20 +0ms] - HTTP >= 300 → 按 `errcode` 提示用户(返回 `status` 和 `trace`): [00:00:20 +0ms] [00:00:20 +0ms] | errcode | 提示 | [00:00:20 +0ms] |---------|------| [00:00:20 +0ms] | `2000076` | 项目未启用 TAPD 集成,请联系管理员开启 | [00:00:20 +0ms] | `2000073` | 未绑定 TAPD 账号,请前往个人设置绑定 | [00:00:20 +0ms] | `2000074` | TAPD 授权已过期,请重新绑定 | [00:00:20 +0ms] | `2000075` | 无权限或资源 ID 错误,请检查链接 | [00:00:20 +0ms] | `401` | 请先登录 CNB 平台 | [00:00:20 +0ms] | `403` / `404` | 无权限或资源不存在 | [00:00:20 +0ms] | 其他 | 请求失败,请重试或联系管理员并提供 trace | [00:00:20 +0ms] [00:00:20 +0ms] 注意:不要向用户暴露错误堆栈等内部细节。 [00:00:20 +2ms] exit code: 0, signal: 0, duration: 60ms [00:00:20 +6ms] $ test -d ~/'.codebuddy/skills/text-path-converter' && echo dir || (test -f ~/'.codebuddy/skills/text-path-converter' && echo file || echo other) [00:00:20 +50ms] dir [00:00:20 +2ms] exit code: 0, signal: 0, duration: 52ms [00:00:20 +5ms] $ cat ~/'.codebuddy/skills/text-path-converter/SKILL.md' 2>/dev/null [00:00:20 +64ms] --- [00:00:20 +0ms] name: text-path-converter [00:00:20 +0ms] description: 将 ISSUE/PR 描述、评论、Review 中的相对路径转换为绝对路径,避免路径歧义,支持纯文本与 Markdown。 [00:00:20 +0ms] requires: [00:00:20 +0ms] bins: [node] [00:00:20 +0ms] files: [scripts/convertLink.js] [00:00:20 +0ms] --- [00:00:20 +0ms] [00:00:20 +0ms] # CNB 文本相对路径转换器 [00:00:20 +0ms] [00:00:20 +0ms] ## 使用方式 [00:00:20 +0ms] [00:00:20 +0ms] 获取到 ISSUE 或合并请求的描述、评论、Review 的原始内容后,执行以下脚本进行转换。脚本会将所有相对路径替换为绝对路径,并将转换结果输出到标准输出。 [00:00:20 +0ms] [00:00:20 +0ms] ```bash [00:00:20 +0ms] # 执行转换,结果输出到标准输出 [00:00:20 +0ms] node scripts/convertLink.js <在此粘贴原始内容> [00:00:20 +0ms] ``` [00:00:20 +1ms] [00:00:20 +0ms] ## 示例 [00:00:20 +0ms] [00:00:20 +0ms] **转换前:** [00:00:20 +0ms] ``` [00:00:20 +0ms] 请参考 ./src/utils/helper.ts 中的实现,以及 ../docs/api.md 的说明。 [00:00:20 +0ms] ``` [00:00:20 +0ms] [00:00:20 +0ms] **转换后:** [00:00:20 +0ms] ``` [00:00:20 +0ms] 请参考 https://cnb.cool/cnb/cool/default-npc-agent/-/git/raw/main/src/utils/helper.ts 中的实现,以及 https://cnb.cool/cnb/cool/default-npc-agent/-/git/raw/main/docs/api.md 的说明。 [00:00:20 +0ms] ``` [00:00:20 +1ms] exit code: 0, signal: 0, duration: 66ms [00:00:20 +5ms] $ test -d ~/'.codebuddy/skills/upload-attachment' && echo dir || (test -f ~/'.codebuddy/skills/upload-attachment' && echo file || echo other) [00:00:20 +57ms] dir [00:00:20 +2ms] exit code: 0, signal: 0, duration: 59ms [00:00:20 +5ms] $ cat ~/'.codebuddy/skills/upload-attachment/SKILL.md' 2>/dev/null [00:00:20 +64ms] --- [00:00:20 +0ms] name: upload-attachment [00:00:20 +0ms] description: 上传附件(图片、文档、压缩包等)到 Issue 或 PR 评论,返回 Markdown 附件链接。 [00:00:20 +0ms] --- [00:00:20 +0ms] [00:00:20 +0ms] # 上传附件到 Issue / PR [00:00:20 +0ms] [00:00:20 +0ms] 将本地文件上传到 CNB 平台的 Issue 或 PR,返回可嵌入评论的 Markdown 附件链接。 [00:00:20 +0ms] [00:00:20 +0ms] ## 使用场景 [00:00:20 +0ms] [00:00:20 +0ms] - 在 Issue 或 PR 评论中附加截图、日志文件、构建产物等 [00:00:20 +0ms] - 上传图片(png/jpg/gif/svg/webp)或普通文件(zip/pdf/log 等) [00:00:20 +0ms] [00:00:20 +0ms] ## 执行步骤 [00:00:20 +0ms] [00:00:20 +0ms] ### 1. 判断文件类别 [00:00:20 +0ms] [00:00:20 +0ms] 根据文件扩展名判断使用哪个命令: [00:00:20 +0ms] [00:00:20 +0ms] - **图片**(`.png`, `.jpg`, `.jpeg`, `.gif`, `.svg`, `.webp`, `.ico` 等图片类型)→ 使用 `upload-image` [00:00:20 +0ms] - **其他文件** → 使用 `upload-file` [00:00:20 +0ms] [00:00:20 +0ms] ### 2. 执行上传 [00:00:20 +0ms] [00:00:20 +0ms] 上传图片: [00:00:20 +0ms] [00:00:20 +0ms] ```bash [00:00:20 +0ms] cnb issues upload-image --file 本地文件路径 [00:00:20 +0ms] cnb pulls upload-image --file 本地文件路径 [00:00:20 +0ms] ``` [00:00:20 +0ms] [00:00:20 +0ms] 上传普通文件: [00:00:20 +0ms] [00:00:20 +0ms] ```bash [00:00:20 +0ms] cnb issues upload-file --file 本地文件路径 [00:00:20 +0ms] cnb pulls upload-file --file 本地文件路径 [00:00:20 +0ms] ``` [00:00:20 +0ms] [00:00:20 +0ms] ### 3. 使用上传结果 [00:00:20 +0ms] [00:00:20 +0ms] 命令返回 JSON,其中包含 `asset_link`(Issue)或 `path`(PR)字段,即附件的访问链接。 [00:00:20 +0ms] [00:00:20 +0ms] 附件在评论中的 Markdown 格式: [00:00:20 +0ms] [00:00:20 +1ms] - 图片:`![文件名](附件URL)` — 渲染为内联图片 [00:00:20 +1ms] - 普通文件:`[文件名](附件URL)` — 渲染为下载链接 [00:00:20 +0ms] exit code: 0, signal: 0, duration: 67ms [00:00:20 +5ms] $ test -d '.agents/skills' && echo 1 || echo 0 [00:00:20 +65ms] 0 [00:00:20 +2ms] exit code: 0, signal: 0, duration: 67ms [00:00:20 +5ms] $ test -d '.codebuddy/skills' && echo 1 || echo 0 [00:00:20 +59ms] 1 [00:00:20 +2ms] exit code: 0, signal: 0, duration: 61ms [00:00:20 +6ms] $ cat '.codebuddy/skills/SKILL.md' 2>/dev/null [00:00:21 +78ms] exit code: 1, signal: -1, duration: 77ms [00:00:21 +4ms] $ ls -1A '.codebuddy/skills' 2>/dev/null [00:00:21 +60ms] close-issue [00:00:21 +1ms] exit code: 0, signal: 0, duration: 61ms [00:00:21 +5ms] $ test -d '.codebuddy/skills/close-issue' && echo dir || (test -f '.codebuddy/skills/close-issue' && echo file || echo other) [00:00:21 +68ms] dir [00:00:21 +3ms] exit code: 0, signal: 0, duration: 71ms [00:00:21 +5ms] $ cat '.codebuddy/skills/close-issue/SKILL.md' 2>/dev/null [00:00:21 +65ms] --- [00:00:21 +0ms] name: close-issue [00:00:21 +0ms] description: 当前仓库关闭 Issue 的流程和规范。 [00:00:21 +1ms] --- [00:00:21 +0ms] [00:00:21 +0ms] ## 规范 [00:00:21 +0ms] [00:00:21 +0ms] ### 更新标签 [00:00:21 +0ms] [00:00:21 +0ms] 1. 获取当前 Issue 的标签列表 [00:00:21 +0ms] 2. 如果包含 `已解决:待发布`,则需要添加 `已解决:已生效` [00:00:21 +0ms] 3. 如果包含 `已解决:待验证`,则需要添加 `已解决:已生效` [00:00:21 +0ms] [00:00:21 +0ms] ### 关闭 [00:00:21 +0ms] [00:00:21 +0ms] 执行关闭操作 [00:00:21 +1ms] exit code: 0, signal: 0, duration: 67ms [00:00:23 +2.5s] $ test -r '/root/.codebuddy/skills/markitdown/SKILL.md' [00:00:23 +67ms] exit code: 0, signal: 0, duration: 67ms [00:00:23 +5ms] $ stat -c %s '/root/.codebuddy/skills/markitdown/SKILL.md' 2>/dev/null || stat -f %z '/root/.codebuddy/skills/markitdown/SKILL.md' [00:00:23 +65ms] 2754 [00:00:23 +2ms] exit code: 0, signal: 0, duration: 67ms [00:00:23 +5ms] $ cat '/root/.codebuddy/skills/markitdown/SKILL.md' [00:00:23 +54ms] --- [00:00:23 +0ms] name: markitdown [00:00:23 +0ms] description: 将多种文件格式(PDF、Office 文档、图片、网页内容、结构化数据)转换为针对大语言模型优化的 Markdown。适用场景包括:文档转 Markdown、从 PDF / Office 文件中提取文本、图片 OCR 等。 [00:00:23 +0ms] --- [00:00:23 +0ms] [00:00:23 +0ms] # MarkItDown [00:00:23 +0ms] [00:00:23 +0ms] ## 概述 [00:00:23 +0ms] [00:00:23 +0ms] MarkItDown 是一个 Python 工具,可以把各种文件格式转换为 Markdown,专为大语言模型和文本分析场景优化。它在输出干净、Token 高效的 Markdown 的同时,会保留文档结构(标题、列表、表格、超链接)。 [00:00:23 +0ms] [00:00:23 +0ms] ## 何时使用本 Skill [00:00:23 +0ms] [00:00:23 +0ms] 当用户有以下需求时,使用本 Skill: [00:00:23 +0ms] - 把文档转换成 Markdown 格式 [00:00:23 +0ms] - 从 PDF、Word、PowerPoint、Excel 文件中提取文本 [00:00:23 +0ms] - 对图片做 OCR 提取文字 [00:00:23 +0ms] - 把 HTML、EPUB 或网页内容转成 Markdown [00:00:23 +0ms] [00:00:23 +0ms] ## 核心能力 [00:00:23 +0ms] [00:00:23 +0ms] ### 1. 文档转换 [00:00:23 +0ms] [00:00:23 +0ms] 把 Office 文档和 PDF 转换为 Markdown,同时保留结构。 [00:00:23 +0ms] [00:00:23 +0ms] **支持的格式:** [00:00:23 +0ms] - PDF 文件 [00:00:23 +0ms] - Word 文档(DOCX) [00:00:23 +0ms] - PowerPoint 演示文稿(PPTX) [00:00:23 +0ms] - Excel 表格(XLSX、XLS) [00:00:23 +0ms] [00:00:23 +0ms] **基础用法:** [00:00:23 +0ms] ```python [00:00:23 +0ms] from markitdown import MarkItDown [00:00:23 +0ms] [00:00:23 +0ms] md = MarkItDown() [00:00:23 +0ms] result = md.convert("document.pdf") [00:00:23 +0ms] print(result.text_content) [00:00:23 +0ms] ``` [00:00:23 +0ms] [00:00:23 +0ms] **命令行:** [00:00:23 +0ms] ```bash [00:00:23 +0ms] markitdown document.pdf -o output.md [00:00:23 +0ms] ``` [00:00:23 +0ms] [00:00:23 +0ms] ### 2. 图片处理 [00:00:23 +0ms] [00:00:23 +0ms] 若前模型不支持读取图片内容时,使用此方法从图片中提取元数据与文字。 [00:00:23 +0ms] [00:00:23 +0ms] markitdown 进行图片 OCR 需要配置 LLM, 当前环境没有配置,所以 markitdown 无法进行图片 OCR。 [00:00:23 +0ms] [00:00:23 +0ms] 容器里已经装好 `tesseract-ocr`,并带了简体和繁体中文语言包: [00:00:23 +0ms] [00:00:23 +0ms] ```bash [00:00:23 +0ms] # 仅英文 [00:00:23 +0ms] tesseract image.png stdout [00:00:23 +1ms] [00:00:23 +0ms] # 中文 + 英文(截图/密集排版建议加 --psm 6) [00:00:23 +0ms] tesseract image.png stdout -l chi_sim+eng --psm 6 [00:00:23 +0ms] ``` [00:00:23 +0ms] [00:00:23 +0ms] 在 Python 中: [00:00:23 +0ms] ```python [00:00:23 +0ms] import pytesseract [00:00:23 +0ms] from PIL import Image [00:00:23 +0ms] [00:00:23 +0ms] text = pytesseract.image_to_string(Image.open("image.png"), lang="chi_sim+eng") [00:00:23 +0ms] print(text) [00:00:23 +0ms] ``` [00:00:23 +0ms] [00:00:23 +0ms] **关于 PDF:** MarkItDown 通过 `pdfminer` 处理文本型 PDF(无需 OCR)。对扫描件 / 纯图片 PDF,他无法识别内容,需要回落到 `tesseract`(可以先用 `poppler-utils` 里的 `pdftoppm` 把页面转成图片再识别)。 [00:00:23 +0ms] [00:00:23 +0ms] ### 3. 网页内容提取 [00:00:23 +0ms] [00:00:23 +0ms] 把基于网页的内容和电子书转成 Markdown。 [00:00:23 +0ms] [00:00:23 +0ms] **支持的格式:** [00:00:23 +0ms] - HTML 文件和网页 [00:00:23 +0ms] - EPUB 电子书 [00:00:23 +0ms] - RSS 订阅 [00:00:23 +0ms] [00:00:23 +0ms] ## 安装 [00:00:23 +0ms] [00:00:23 +0ms] [00:00:23 +0ms] **按需安装(指定功能):** [00:00:23 +0ms] ```bash [00:00:23 +0ms] pip install 'markitdown[pdf]' # PDF 支持 [00:00:23 +0ms] pip install 'markitdown[docx]' # Word 支持 [00:00:23 +0ms] pip install 'markitdown[pptx]' # PowerPoint 支持 [00:00:23 +0ms] pip install 'markitdown[xlsx]' # Excel 支持 [00:00:23 +0ms] ``` [00:00:23 +0ms] [00:00:23 +0ms] **完整安装(所有功能):** [00:00:23 +0ms] ```bash [00:00:23 +0ms] pip install 'markitdown[all]' [00:00:23 +0ms] ``` [00:00:23 +0ms] [00:00:23 +0ms] **要求:** [00:00:23 +0ms] - Python 3.10 或更高版本 [00:00:23 +1ms] exit code: 0, signal: 0, duration: 56ms [00:00:23 +6ms] $ test -r '/root/.codebuddy/skills/cnb-api/SKILL.md' [00:00:24 +71ms] exit code: 0, signal: 0, duration: 72ms [00:00:24 +5ms] $ stat -c %s '/root/.codebuddy/skills/cnb-api/SKILL.md' 2>/dev/null || stat -f %z '/root/.codebuddy/skills/cnb-api/SKILL.md' [00:00:24 +63ms] 2787 [00:00:24 +2ms] exit code: 0, signal: 0, duration: 65ms [00:00:24 +5ms] $ cat '/root/.codebuddy/skills/cnb-api/SKILL.md' [00:00:24 +63ms] --- [00:00:24 +0ms] name: cnb-api [00:00:24 +0ms] description: CNB 平台交互命令,支持仓库、Issue、PR、流水线、制品库等操作。 [00:00:24 +0ms] --- [00:00:24 +0ms] [00:00:24 +0ms] # cnb-api [00:00:24 +0ms] [00:00:24 +1ms] 操作 CNB 平台资源的 CLI 工具。 [00:00:24 +0ms] [00:00:24 +0ms] ## 快捷命令 [00:00:24 +0ms] [00:00:24 +0ms] issues: [00:00:24 +0ms] - `cnb issues get` — 获取当前 Issue 详情 [00:00:24 +0ms] - `cnb issues list-comments` — 列出当前 Issue 评论 [00:00:24 +0ms] - `cnb issues comment --body '内容'` — 发表评论到当前 Issue [00:00:24 +0ms] - `cnb issues close` — 关闭当前 Issue [00:00:24 +0ms] - `cnb issues open` — 打开当前 Issue [00:00:24 +0ms] - `cnb issues list-labels` — 列出当前 Issue 标签 [00:00:24 +0ms] - `cnb issues add-labels --labels bug --labels feature` — 添加标签到当前 Issue [00:00:24 +0ms] - `cnb issues list-assignees` — 查看当前 Issue 处理人 [00:00:24 +0ms] - `cnb issues add-assignees --assignees username` — 添加处理人到当前 Issue [00:00:24 +0ms] - `cnb issues upload-file --file 文件路径` — 上传文件到当前 Issue [00:00:24 +0ms] - `cnb issues upload-image --file 图片路径` — 上传图片到当前 Issue [00:00:24 +0ms] [00:00:24 +0ms] pulls: [00:00:24 +0ms] - `cnb pulls get` — 获取当前 PR 详情 [00:00:24 +0ms] - `cnb pulls list-files` — 列出当前 PR 变更文件 [00:00:24 +0ms] - `cnb pulls list-commits` — 列出当前 PR 提交记录 [00:00:24 +0ms] - `cnb pulls list-comments` — 列出当前 PR 评论 [00:00:24 +0ms] - `cnb pulls comment --body '内容'` — 发表 PR 评论 [00:00:24 +0ms] - `cnb pulls list-labels` — 列出当前 PR 标签 [00:00:24 +0ms] - `cnb pulls add-labels --labels ready --labels approved` — 添加标签到当前 PR [00:00:24 +0ms] - `cnb pulls check-status` — 获取当前 PR 的 CI 状态 [00:00:24 +0ms] - `cnb pulls get-ci-logs` — 获取当前 PR 的 CI 构建日志 [00:00:24 +0ms] - `cnb pulls list-reviews` — 查看当前当前的评审列表 [00:00:24 +0ms] - `cnb pulls list-assignees` — 查看当前 PR 处理人 [00:00:24 +0ms] - `cnb pulls upload-file --file 文件路径` — 上传文件到当前 PR [00:00:24 +0ms] - `cnb pulls upload-image --file 图片路径` — 上传图片到当前 PR [00:00:24 +0ms] [00:00:24 +0ms] 注意事项: [00:00:24 +0ms] - **链接结构**:Issue 链接格式为 `//-/issues/`,PR 链接格式为 `//-/pulls/`。在生成或引用链接时请遵循此结构。 [00:00:24 +0ms] - **参数自动识别**:快捷命令中的 Issue/PR 编号会自动从环境变量识别,无需额外传递。 [00:00:24 +0ms] - **默认仅需摘要**:默认会精简响应输出结果,只返回核心字段。添加 `--verbose` 输出完整数据。 [00:00:24 +0ms] - **单引号传参**:传递多行文本参数时,使用单引号可防止命令注入攻击,并减少不必要的转义。 [00:00:24 +0ms] - **快捷命令适用范围**: 快捷命令只能操作当前仓库的当前 Issue/PR,跨仓库或跨编号操作请参考 `更多 API`。 [00:00:24 +0ms] - **npc提及和召唤的区别**: 评论中直接 @npc 会召唤 npc 干活,如果只提及不召唤,应该去掉 `@` 符号,或使用反引号包裹 `@npc`。 [00:00:24 +0ms] [00:00:24 +0ms] ## 更多 API [00:00:24 +0ms] [00:00:24 +0ms] 1. `cnb --help` 查看所有模块 [00:00:24 +0ms] 2. `cnb --help` 查看模块下的工具列表 [00:00:24 +0ms] 3. `cnb --help` 查看工具参数 [00:00:24 +1ms] exit code: 0, signal: 0, duration: 65ms [00:00:30 +6.7s] $ curl -sL "https://cnb.cool/cnb/feedback/-/imgs/issues/2055658219926962176/IrkN7VD4DcPuFzTmOfZ4OE/08ff7b16-fa1b-4318-a7a2-c6a5bd75ff47.jpg" -o /tmp/ocr_test.jpg && file /tmp/ocr_test.jpg [00:00:31 +529ms] /tmp/ocr_test.jpg: JPEG image data, Exif standard: [TIFF image data, big-endian, direntries=6, height=2656, software=Android BP2A.250605.031.A3, orientation=upper-left, datetime=2026:05:16 22:06:06, width=1220], baseline, precision 8, 1220x2656, components 3 [00:00:31 +2ms] exit code: 0, signal: 0, duration: 531ms [00:00:32 +1.1s] $ test -r '/tmp/ocr_test.jpg' [00:00:32 +63ms] exit code: 0, signal: 0, duration: 63ms [00:00:32 +5ms] $ stat -c %s '/tmp/ocr_test.jpg' 2>/dev/null || stat -f %z '/tmp/ocr_test.jpg' [00:00:32 +69ms] 379076 [00:00:32 +2ms] exit code: 0, signal: 0, duration: 71ms [00:00:35 +2.5s] $ tesseract /tmp/ocr_test.jpg stdout -l chi_sim+eng --psm 6 2>/dev/null [00:00:36 +1.1s] 22:06 >- Tl Tall SS [00:00:36 +0ms] {a} & docs.cnb.cool/zh/artifact/d: : [00:00:36 +0ms] = Menu 此页内容 > [00:00:36 +0ms] 、\ cl [00:00:36 +0ms] 推进制品 [00:00:36 +0ms] 本地命令行推送 [00:00:36 +0ms] 同名制品 [00:00:36 +0ms] 1/${CNB_REPO_SLUG_LOWERCASE}:latest . [00:00:36 +0ms] CNB_REPO_SLUG_LOWERCASE}: latest [00:00:36 +0ms] 非同名制品 [00:00:36 +0ms] docker build -t docker.cnb.cool/${CNB [00:00:36 +0ms] docker push docker.cnb.cool/${CNB_REP [00:00:36 +0ms] 云原生构建中推送 [00:00:36 +0ms] ym .cnb.yml [00:00:36 +0ms] ~ [00:00:36 +0ms] 22% [00:00:36 +0ms] main [00:00:36 +0ms] push [00:00:36 +0ms] services [00:00:36 +0ms] De [00:00:36 +21ms] exit code: 0, signal: 0, duration: 1.1s [00:00:37 +1.4s] $ tesseract /tmp/ocr_test.jpg stdout -l chi_sim+eng --psm 3 2>/dev/null [00:00:38 +1.0s] sl eal 仿 [00:00:38 +0ms] [00:00:38 +0ms] 22:06 >- [00:00:38 +0ms] [00:00:38 +0ms] (oy G docs.cnb.cool/zh/artifact/d [00:00:38 +0ms] [00:00:38 +0ms] 、 co [00:00:38 +0ms] 推送制品 [00:00:38 +0ms] 本地命令行推送 [00:00:38 +0ms] 同名制品 [00:00:38 +0ms] 1/$4CNB_REPO_SLUG_LOWERCASE}:latest . [00:00:38 +0ms] :latest [00:00:38 +0ms] [00:00:38 +0ms] CNB_REPO_SLUG_LOWERCASE [00:00:38 +0ms] [00:00:38 +0ms] 非同名制品 [00:00:38 +0ms] docker build -t docker.cnb.cool/$4CNB [00:00:38 +0ms] docker push docker.cnb.cool/${CNB_REP [00:00:38 +0ms] 云原生构建中推送 [00:00:38 +0ms] ym .cnb.yml [00:00:38 +0ms] za [00:00:38 +0ms] 22% [00:00:38 +0ms] main [00:00:38 +0ms] push [00:00:38 +0ms] services [00:00:38 +0ms] [00:00:38 +0ms] = O < [00:00:38 +0ms] [00:00:38 +21ms] exit code: 0, signal: 0, duration: 1.0s [00:00:48 +10.1s] $ cnb issues comment --body '@samsong(AcidBunny) 你好!关于 NPC 的 OCR 能力,我来详细介绍一下: ## OCR 能力说明 NPC(如我 CodeBuddy)的 OCR 能力是通过以下方式提供的: ### 1. 多模态模型直接识别(推荐) 如果 NPC 底层的 AI 模型支持图片输入(多模态能力),可以直接"看懂"图片内容,识别效果最好,适合截图、照片等场景。不过当前我运行的基础模型暂不支持直接读取图片像素内容。 ### 2. Tesseract OCR 引擎(备选) 当底层模型不支持图片时,会通过 **Tesseract** 开源 OCR 引擎来提取图片中的文字。容器中已预装 Tesseract 并附带中文简繁体语言包,支持命令行和 Python 调用。 ### 3. MarkItDown 工具链 通过 `markitdown` Python 库也能对图片进行 OCR 文字提取(需配置 LLM)。 --- ## 你这张图片我看到了什么? 我用 Tesseract OCR 识别了你上传的截图,内容大致如下: > 这是一张 **CNB 制品库(docs.cnb.cool/zh/artifact/docker)** 的文档页面截图,展示的是 **Docker 推送制品** 的相关配置说明,包括: > - **本地命令行推送** > - 同名制品:`docker build -t docker.cnb.cool/\${CNB_REPO_SLUG_LOWERCASE}:latest .` → `docker push ...` > - 非同名制品:类似命令 > - **云原生构建中推送**:通过 `.cnb.yml` 配置 > - 底部状态栏显示 `22%` 电量、`main` 分支、`push`、`services` 等信息 > - 看起来是用手机 Firefox 浏览器打开的页面 --- **总结:** OCR 能力是 NPC 的一项实用功能,主要通过多模态模型或 Tesseract 引擎实现。对于截图中的中文文字识别,Tesseract 的效果还不错但不如多模态模型精准。如果你需要更高精度的图片识别,可以召唤支持多模态的 NPC 来处理。' [00:00:49 +522ms] status: 201 [00:00:49 +0ms] data: [00:00:49 +0ms] id: "2055659070481485824" [00:00:49 +0ms] created_at: "2026-05-16T14:38:09Z" [00:00:49 +9ms] exit code: 0, signal: 0, duration: 531ms [00:00:51 +2.4s] $ docker pull orangeci/check-is-remote-debugging:latest [00:00:52 +319ms] $ docker run --rm --network host --pid=host --cap-add NET_ADMIN --cap-add SYS_ADMIN -v /var/run/docker.sock:/var/run/docker.sock --name cnb-klo-1joojgph9-001-orange-tc-clean orangeci/orange-tc:latest -c cnb-klo-1joojgph9-001-network-bus -m clean -d default:56Mbps -d 10.200.254.0/24:3Gbps -d 169.254.0.0/16:8Gbps -u default:56Mbps -u 10.200.254.0/24:1Gbps -u 169.254.0.0/16:8Gbps -a nsenter -b [00:00:52 +49ms] latest: Pulling from orangeci/check-is-remote-debugging [00:00:52 +11ms] Digest: sha256:519a2e95ed0a11547c9d3e183028cb044d7bac3cb8317c6c14181a45c482e444 [00:00:52 +0ms] Status: Image is up to date for orangeci/check-is-remote-debugging:latest [00:00:52 +2ms] docker.io/orangeci/check-is-remote-debugging:latest [00:00:52 +1ms] exit code: 0, signal: 0, duration: 381ms [00:00:52 +74ms] container: cnb-klo-1joojgph9-001-network-bus [00:00:52 +1ms] mode: clean [00:00:52 +0ms] action: nsenter [00:00:52 +0ms] batch: true [00:00:52 +29ms] clean done [00:00:52 +45ms] exit code: 0, signal: 0, duration: 211ms [00:00:52 +5ms] $ docker kill cnb-klo-1joojgph9-001-network-bus [00:00:52 +157ms] cnb-klo-1joojgph9-001-network-bus [00:00:52 +1ms] exit code: 0, signal: 0, duration: 157ms [00:00:52 +129ms] $ docker pull cnbcool/clear-containers [00:00:52 +10ms] Using default tag: latest [00:00:53 +898ms] latest: Pulling from cnbcool/clear-containers [00:00:53 +11ms] Digest: sha256:812510bd6314d37a8a8e3281caf12fbc0c6bd064fb2fe9218d5eced545cf22a1 [00:00:53 +0ms] Status: Image is up to date for cnbcool/clear-containers:latest [00:00:53 +1ms] docker.io/cnbcool/clear-containers:latest [00:00:53 +1ms] exit code: 0, signal: 0, duration: 921ms