diff --git a/docs/agents/skill-change.md b/docs/agents/skill-change.md index ca4a31f4..4136f17e 100644 --- a/docs/agents/skill-change.md +++ b/docs/agents/skill-change.md @@ -15,7 +15,7 @@ 2. **`bailian-protocol` 是共享协议 skill**,业务 skill 执行前应 Read 它 3. **不要**在 frontmatter 写 `companions`,也不要对外说「companions = 安装器硬依赖」 4. 子集安装:`bl skill add --name bailian-protocol,`;漏装 protocol 会导致相对路径 Read 失败 -5. **`bl skill add --all`:** 安装 registry 全量(含 `spark-video` 等非 bailian 技能);一键安装 / `bl update` 用 `skill init`,不要用 `--all` +5. **`bl skill add --all`:** 安装 registry 全量(含 `spark-video` 等非 bailian 技能);不要用 `--all` 做升级同步。首次 / 整包用 `bl skill init`。升级后自动同步以及 `bl update` 成功后用 `bl skill update`(只更新已安装,不装新 skill)。 ## 概念图 @@ -38,7 +38,7 @@ bailian-gen bailian-finetune bailian-managed-agent bailian-web-search ### A. 分层边界 -- [ ] **整包装齐**:安装/升级文案主推 `bl skill init`;业务 skill **不**声明 `companions` +- [ ] **整包装齐**:安装 / 缺 skill 文案主推 `bl skill init`;升级同步用 `bl skill update`(只更新已安装,不装新 skill);业务 skill **不**声明 `companions` - [ ] **协议读取**:CRITICAL / references 可链 `../bailian-protocol/…`;若读不到 → 停止执行 `bl`,提示 `bl skill init` - [ ] **高风险确认**:统一由 `bailian-protocol` 定义;reference / leaf help 以 `risk: high` 明示风险,业务 skill 不得引导 Agent 自动补 `--yes`。遇到 exit code 7 / `requires_confirmation` 时停止执行并请求确认;目标或范围变化后重新确认 - [ ] **正常控制流**:`requires_confirmation` 不是 CLI bug,`assets/issue-reporting.md` 必须将 exit code 7 保持在 EXCLUDE 范围 diff --git a/packages/commands/src/commands/update.ts b/packages/commands/src/commands/update.ts index cfbceb48..f7753e0c 100644 --- a/packages/commands/src/commands/update.ts +++ b/packages/commands/src/commands/update.ts @@ -20,16 +20,16 @@ import { type AnsiStyles, } from "bailian-cli-runtime"; -const SKILL_INSTALL_CMD = "bl skill init"; +const SKILL_UPDATE_CMD = "bl skill update"; function updateAgentSkill(color: AnsiStyles): void { process.stderr.write("\nUpdating agent skill...\n"); try { - execSync(SKILL_INSTALL_CMD, { stdio: "inherit" }); + execSync(SKILL_UPDATE_CMD, { stdio: "inherit" }); process.stderr.write(`${color.green("\u2713 Agent skill updated.")}\n`); } catch { process.stderr.write( - `${color.yellow(`Agent skill update skipped. Run manually: ${SKILL_INSTALL_CMD}`)}\n`, + `${color.yellow(`Agent skill update skipped. Run manually: ${SKILL_UPDATE_CMD}`)}\n`, ); } } diff --git a/packages/commands/tests/update-binary-skill-sync.test.ts b/packages/commands/tests/update-binary-skill-sync.test.ts index 6a55a8ba..547faa08 100644 --- a/packages/commands/tests/update-binary-skill-sync.test.ts +++ b/packages/commands/tests/update-binary-skill-sync.test.ts @@ -45,18 +45,42 @@ afterEach(() => { vi.clearAllMocks(); }); -test("binary bl update syncs bailian skills after the CLI update succeeds", async () => { +const identity = { + binName: "bl", + clientName: "bailian-cli", + npmPackage: "bailian-cli", + version: "1.14.3", +}; + +function expectSkillUpdateNotInit(): void { + expect(childProcessMocks.execSync).toHaveBeenCalledWith("bl skill update", { stdio: "inherit" }); + expect( + childProcessMocks.execSync.mock.calls.some((call) => String(call[0]).includes("skill init")), + ).toBe(false); +} + +test("binary bl update refreshes installed skills and does not run skill init", async () => { await updateCommand.run({ - identity: { - binName: "bl", - clientName: "bailian-cli", - npmPackage: "bailian-cli", - version: "1.14.3", - }, + identity, flags: { to: "1.15.0" }, settings: {}, } as never); expect(runtimeMocks.performBinaryUpdate).toHaveBeenCalledWith("1.15.0"); - expect(childProcessMocks.execSync).toHaveBeenCalledWith("bl skill init", { stdio: "inherit" }); + expectSkillUpdateNotInit(); +}); + +test("npm bl update refreshes installed skills and does not run skill init", async () => { + process.env.BAILIAN_INSTALL_METHOD = "npm"; + + await updateCommand.run({ + identity, + flags: { to: "1.15.0" }, + settings: {}, + } as never); + + expect(childProcessMocks.execSync).toHaveBeenCalledWith("npm install -g bailian-cli@1.15.0", { + stdio: "inherit", + }); + expectSkillUpdateNotInit(); }); diff --git a/packages/runtime/src/utils/update-checker.ts b/packages/runtime/src/utils/update-checker.ts index 65999c0b..ed492a64 100644 --- a/packages/runtime/src/utils/update-checker.ts +++ b/packages/runtime/src/utils/update-checker.ts @@ -218,13 +218,13 @@ async function syncAgentSkillsAfterUpdate( try { process.stderr.write(` ${dim}Syncing agent skill...${reset}\n`); const { execSync } = await import("child_process"); - execSync("bl skill init", { stdio: "inherit" }); + execSync("bl skill update", { stdio: "inherit" }); process.stderr.write(` ${green}\u2713 Agent skill updated.${reset}\n\n`); } catch (error) { process.stderr.write( ` ${yellow}\u26a0 Agent skill sync failed: ${errorMessage(error)}${reset}\n`, ); - process.stderr.write(` ${yellow} Run manually: bl skill init${reset}\n\n`); + process.stderr.write(` ${yellow} Run manually: bl skill update${reset}\n\n`); } } diff --git a/packages/runtime/tests/update-checker.test.ts b/packages/runtime/tests/update-checker.test.ts index 7c1dc0b8..1f290c1f 100644 --- a/packages/runtime/tests/update-checker.test.ts +++ b/packages/runtime/tests/update-checker.test.ts @@ -170,10 +170,30 @@ test("shouldAutoUpdate only targets stable releases with a significant gap", () expect(shouldAutoUpdate("1.4.2", "1.4.2-beta.1")).toBe(false); }); -test("binary auto-update syncs bailian skills after the CLI update succeeds", async () => { +function expectSkillUpdateNotInit(): void { + expect(childProcessMocks.execSync).toHaveBeenCalledWith("bl skill update", { stdio: "inherit" }); + expect( + childProcessMocks.execSync.mock.calls.some((call) => String(call[0]).includes("skill init")), + ).toBe(false); +} + +test("binary auto-update refreshes installed skills and does not run skill init", async () => { const updated = await performAutoUpdate("1.14.3", "2.0.0"); expect(updated).toBe(true); expect(binaryUpdateMocks.performBinaryUpdate).toHaveBeenCalledWith("2.0.0"); - expect(childProcessMocks.execSync).toHaveBeenCalledWith("bl skill init", { stdio: "inherit" }); + expectSkillUpdateNotInit(); +}); + +test("npm auto-update refreshes installed skills and does not run skill init", async () => { + process.env.BAILIAN_INSTALL_METHOD = "npm"; + childProcessMocks.execSync.mockReturnValue(""); + + const updated = await performAutoUpdate("1.14.3", "2.0.0"); + + expect(updated).toBe(true); + expect(childProcessMocks.execSync).toHaveBeenCalledWith("npm install -g bailian-cli@latest", { + stdio: "inherit", + }); + expectSkillUpdateNotInit(); }); diff --git a/skills/bailian-protocol/assets/issue-reporting.md b/skills/bailian-protocol/assets/issue-reporting.md index 28e9faca..0a88893a 100644 --- a/skills/bailian-protocol/assets/issue-reporting.md +++ b/skills/bailian-protocol/assets/issue-reporting.md @@ -115,7 +115,7 @@ Offer reporting when **none** of EXCLUDE applies **and** any of the following ho ### Before offering to report -1. Align versions: [SKILL.md → Version & updates](../SKILL.md#version--updates-after-provider-selection-before-the-first-bl-command) — run `bl update` and `bl skill init` if mismatched. +1. Align versions: [SKILL.md → Version & updates](../SKILL.md#version--updates-after-provider-selection-before-the-first-bl-command) — run `bl update` and `bl skill update` if mismatched. If needed skills are missing, run `bl skill init`. 2. Confirm `bl auth status` is healthy (for commands that need auth). 3. Retry once with `--verbose` if stderr was thin. diff --git a/skills/bailian-protocol/assets/versioning.md b/skills/bailian-protocol/assets/versioning.md index 7b368289..6de95f88 100644 --- a/skills/bailian-protocol/assets/versioning.md +++ b/skills/bailian-protocol/assets/versioning.md @@ -14,10 +14,11 @@ ``` If this fails, see [Missing `bl`](#missing-bl) below. 3. Compare the two versions (ignore the `bl` prefix; compare only `X.Y.Z`): - - If `metadata.version` ≠ `bl --version`, refresh skills before doing anything else: + - If `metadata.version` ≠ `bl --version`, refresh already-installed skills before doing anything else: ```bash - bl skill init + bl skill update ``` + - If `bailian-protocol` or another needed skill is missing, stop and run `bl skill init`. Do not use `bl skill init` only to refresh versions — it installs every `bailian-*` skill. - Do not trust a stale `reference/` when versions mismatch — flags may be wrong. 4. Check the latest published CLI version: ```bash @@ -26,7 +27,7 @@ 5. If the installed `bl` is **older** than the latest npm version, **STOP** the current task and **ask the user** (report skill version, installed CLI version, and npm latest): > A newer version of bl is available (current: X.Y.Z, latest: A.B.C). Upgrade before continuing? - **Do NOT auto-upgrade silently** — the user decides. - - If the user agrees: run `bl update`, then continue. (`bl update` uses the detected install channel and, on success, also runs `bl skill init` to keep skills in lockstep across all agent apps.) + - If the user agrees: run `bl update`, then continue. (`bl update` uses the detected install channel and, on success, also runs `bl skill update` to refresh already-installed skills; it does not install new skills. First-time install still uses `bl skill init`.) - If the user declines: continue with the current version and note it in the summary. - If `npm view` / `bl update` fails (offline, registry blocked, permission): continue with the current `bl` and tell the user it could not be updated. 6. Only proceed with the user's actual task after the above is resolved.