feat: OpenCode 和 Claude Code 适配器及测试

This commit is contained in:
2026-06-08 17:24:24 +08:00
parent 6c2a229536
commit 7530a5a743
3 changed files with 216 additions and 0 deletions

View File

@@ -0,0 +1,85 @@
import { describe, it, expect, beforeEach, afterEach } from "bun:test";
import { existsSync } from "node:fs";
import { mkdir, rm, readFile, readdir } from "node:fs/promises";
import { join } from "node:path";
import { injectOpenCode } from "../../src/adapters/opencode.ts";
const TMP_DIR = join(import.meta.dir, "__tmp_opencode_test__");
beforeEach(async () => {
await mkdir(TMP_DIR, { recursive: true });
});
afterEach(async () => {
await rm(TMP_DIR, { recursive: true, force: true });
});
describe("injectOpenCode", () => {
it("生成 discuss、plan、build、archive 的 command 和 skill 文件", async () => {
await injectOpenCode(TMP_DIR);
const commands = await readdir(join(TMP_DIR, ".opencode", "commands"));
const skills = await readdir(join(TMP_DIR, ".opencode", "skills"));
for (const stage of ["discuss", "plan", "build", "archive"]) {
expect(commands).toContain(`${stage}.md`);
expect(skills).toContain(`rune-${stage}.md`);
}
});
it("生成 rune-status command 和 skill", async () => {
await injectOpenCode(TMP_DIR);
const commands = await readdir(join(TMP_DIR, ".opencode", "commands"));
const skills = await readdir(join(TMP_DIR, ".opencode", "skills"));
expect(commands).toContain("rune-status.md");
expect(skills).toContain("rune-status.md");
});
it("command 文件包含 skill 调用指令", async () => {
await injectOpenCode(TMP_DIR);
const content = await readFile(
join(TMP_DIR, ".opencode", "commands", "discuss.md"),
"utf-8",
);
expect(content).toContain("rune-discuss");
});
it("skill 文件包含 bash 命令", async () => {
await injectOpenCode(TMP_DIR);
const content = await readFile(
join(TMP_DIR, ".opencode", "skills", "rune-discuss.md"),
"utf-8",
);
expect(content).toContain("rune discuss");
expect(content).toContain("description");
});
it("plan/build/archive skill 包含变更名称参数提示", async () => {
await injectOpenCode(TMP_DIR);
for (const stage of ["plan", "build", "archive"]) {
const content = await readFile(
join(TMP_DIR, ".opencode", "skills", `rune-${stage}.md`),
"utf-8",
);
expect(content).toContain("变更名");
}
});
it("重复注入时不覆盖已存在的文件", async () => {
await injectOpenCode(TMP_DIR);
const originalContent = await readFile(
join(TMP_DIR, ".opencode", "commands", "discuss.md"),
"utf-8",
);
await injectOpenCode(TMP_DIR);
const content = await readFile(
join(TMP_DIR, ".opencode", "commands", "discuss.md"),
"utf-8",
);
expect(content).toBe(originalContent);
});
});