Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/agents/skill-change.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
2. **`bailian-protocol` 是共享协议 skill**,业务 skill 执行前应 Read 它
3. **不要**在 frontmatter 写 `companions`,也不要对外说「companions = 安装器硬依赖」
4. 子集安装:`bl skill add --name bailian-protocol,<skill>`;漏装 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)。

## 概念图

Expand All @@ -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 范围
Expand Down
6 changes: 3 additions & 3 deletions packages/commands/src/commands/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`,
);
}
}
Expand Down
40 changes: 32 additions & 8 deletions packages/commands/tests/update-binary-skill-sync.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
4 changes: 2 additions & 2 deletions packages/runtime/src/utils/update-checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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`);
}
}

Expand Down
24 changes: 22 additions & 2 deletions packages/runtime/tests/update-checker.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
});
2 changes: 1 addition & 1 deletion skills/bailian-protocol/assets/issue-reporting.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
7 changes: 4 additions & 3 deletions skills/bailian-protocol/assets/versioning.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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.
Expand Down
Loading