test: add opencode plugin compatibility checks

This commit is contained in:
Ralph Chang
2026-04-27 18:54:14 +08:00
parent 909fec9abb
commit c2ee245620
3 changed files with 112 additions and 2 deletions
+34
View File
@@ -0,0 +1,34 @@
name: compatibility
on:
pull_request:
push:
branches: [main]
schedule:
- cron: "0 9 * * 1"
jobs:
locked:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm run typecheck
- run: npm test
opencode-latest:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: npm
- run: npm ci
- run: npm install --no-save @opencode-ai/plugin@latest
- run: npm run typecheck
- run: npm test
+3 -2
View File
@@ -16,7 +16,8 @@
"scripts": {
"build": "node -e \"console.log('No build step required: OpenCode loads index.ts directly')\"",
"typecheck": "tsc --noEmit",
"test": "node --test --experimental-strip-types tests/*.test.ts"
"test": "node --test --experimental-strip-types tests/*.test.ts",
"check:compat": "npm install --no-save @opencode-ai/plugin@latest && npm run typecheck && npm test"
},
"keywords": [
"opencode",
@@ -37,7 +38,7 @@
},
"homepage": "https://github.com/sdwolf4103/opencode-working-memory#readme",
"peerDependencies": {
"@opencode-ai/plugin": "^1.2.0"
"@opencode-ai/plugin": ">=1.2.0 <2.0.0"
},
"devDependencies": {
"@types/node": "^24.3.0",
+75
View File
@@ -0,0 +1,75 @@
/**
* Plugin capability test.
*
* This is the loud alarm for OpenCode plugin API compatibility.
* It fails tests, not user runtime.
*
* If any required hook key disappears from MemoryV2Plugin output,
* this test will catch it before release.
*/
import { describe, it } from "node:test";
import assert from "node:assert";
import { MemoryV2Plugin } from "../src/plugin.ts";
const REQUIRED_PLUGIN_HOOKS = [
"experimental.chat.system.transform",
"tool.execute.after",
"experimental.session.compacting",
"event",
] as const;
describe("plugin capability", () => {
it("MemoryV2Plugin has all required hooks", async () => {
// Create minimal mock client
const mockClient = {
session: {
get: async () => ({ data: { parentID: null } }),
},
};
// Create minimal mock input
const mockInput = {
directory: "/tmp/test-workspace",
client: mockClient,
};
// Instantiate plugin
const plugin = await MemoryV2Plugin(mockInput);
// Assert all required hooks exist and are functions
for (const hook of REQUIRED_PLUGIN_HOOKS) {
assert(
hook in plugin,
`Missing required hook: ${hook}`
);
assert(
typeof plugin[hook] === "function",
`Hook ${hook} is not a function`
);
}
});
it("MemoryV2Plugin returns exactly the expected hook keys", async () => {
const mockClient = {
session: {
get: async () => ({ data: { parentID: null } }),
},
};
const mockInput = {
directory: "/tmp/test-workspace",
client: mockClient,
};
const plugin = await MemoryV2Plugin(mockInput);
const keys = Object.keys(plugin).sort();
const expected = [...REQUIRED_PLUGIN_HOOKS].sort();
assert.deepStrictEqual(
keys,
expected,
`Plugin returned unexpected keys: ${keys.join(", ")}`
);
});
});