🐛 Remove OpenCode V1 plugin support

Remove the legacy @opencode-ai/plugin import and V1 server export so
the local plugin loads under OpenCode V2 without project dependencies.

Add a focused smoke test for the V2 export and tool registration, and
update the related script memories.

AI-assisted-by: space-bunny-free
This commit is contained in:
Andrey Antukh 2026-09-23 16:28:11 +00:00
parent 58b1acbb66
commit 992170a9a4
4 changed files with 45 additions and 89 deletions

View File

@ -1,22 +1,9 @@
// Penpot opencode plugin: custom tools for Penpot development.
// Penpot OpenCode V2 plugin: custom tools for Penpot development.
//
// Dual V1 + V2 implementation from a single file:
// - OpenCode V1 (>= 1.18.29) calls the default export's `server()` and uses
// the returned `tool` map (built with the `tool()` helper from
// `@opencode-ai/plugin`).
// - OpenCode V2 reads the default export's `id` and `setup()` and ignores
// `server()`. Tools are registered via `ctx.tool.transform()` with JSON
// Schema inputs, and `execute` returns `{ content }`.
// See https://opencode.ai/v2/docs/build/plugins/migrate-v1
//
// NOTE: the V2 side intentionally does NOT
// `import { Plugin } from "@opencode/plugin"`. At runtime `Plugin.define` is
// the identity function, so a plain `{ id, setup }` object is equivalent, and
// skipping the import keeps this plugin dependency-free
// (`.opencode/package.json` is gitignored, so a new dependency declared there
// would not travel with this file).
// Tools are registered with `ctx.tool.transform()` and JSON Schema inputs.
// Keep this plugin dependency-free so the auto-discovered local plugin loads
// without project npm dependencies.
import { tool } from "@opencode-ai/plugin"
import path from "path"
import { spawn } from "child_process"
@ -106,64 +93,6 @@ function executeParenRepair({ files, code }, directory) {
})
}
// --- V1 tool definitions (OpenCode V1 calls `server()` below) ---
const penpotPsqlTool = tool({
description:
"Execute a SQL command against the Penpot database. Uses the defaults from scripts/psql.",
args: {
sql: tool.schema
.string()
.describe("SQL command to execute"),
test: tool.schema
.boolean()
.describe("Use the penpot_test database")
.optional(),
},
async execute(args, context) {
return executePsql(args.sql, args.test === true, context.worktree)
},
})
const parenRepairTool = tool({
description:
"Fix mismatched parentheses/braces in Clojure files (.clj, .cljs, .cljc) then reformat with cljfmt.",
args: {
// A string is used instead of an array so OpenCode displays it
// in the generic tool invocation.
files: tool.schema
.string()
.describe(
"Comma-separated file paths to fix, for example: frontend/src/app/config.cljs, backend/src/core.clj",
)
.optional(),
code: tool.schema
.string()
.describe("Code string to fix via stdin")
.optional(),
},
async execute(args, context) {
return executeParenRepair(args, context.worktree)
},
})
async function server() {
return {
tool: {
"paren-repair": parenRepairTool,
"penpot-psql": penpotPsqlTool,
},
}
}
// --- V2 setup (OpenCode V2 calls `setup()` and ignores `server()`) ---
const penpotPsqlInputSchema = {
type: "object",
properties: {
@ -199,10 +128,7 @@ const parenRepairInputSchema = {
}
async function setup(ctx) {
// Plugin instance location. This is not the location of every session the
// tools may run for, but it is the closest V2 equivalent of the V1
// per-execution `context.worktree` (the repo checkout the plugin loaded
// from), which is what both tools need as cwd / script base.
// Use the plugin instance location as the working directory for both tools.
const directory =
ctx.location.directory ?? ctx.location.project?.canonical
@ -240,5 +166,4 @@ async function setup(ctx) {
export default {
id: "penpot",
setup,
server,
}

View File

@ -0,0 +1,32 @@
import assert from "node:assert/strict"
import test from "node:test"
import plugin from "../plugins/penpot.js"
test("exports only the OpenCode V2 plugin contract", () => {
assert.equal(plugin.id, "penpot")
assert.equal("server" in plugin, false)
})
test("registers the Penpot tools during setup", async () => {
const tools = []
const context = {
location: { directory: "/tmp/opencode/penpot-plugin-test" },
tool: {
async transform(apply) {
apply({
add(tool) {
tools.push(tool)
},
})
},
},
}
await plugin.setup(context)
assert.deepEqual(
tools.map((tool) => tool.name).sort(),
["paren-repair", "penpot-psql"],
)
})

View File

@ -27,11 +27,11 @@ bb scripts/paren-repair --help
```
`bb` must be invoked from the repo root so the path `scripts/paren-repair` resolves.
## Native Tool Available (opencode)
## Native Tool Available (OpenCode V2)
A native opencode tool `paren-repair` is available (defined in
`.opencode/plugins/penpot.js`, which registers it for both opencode V1 via
`server()` and opencode V2 via `setup()`). The LLM can call it directly with:
A native OpenCode V2 tool `paren-repair` is available. It is defined in
`.opencode/plugins/penpot.js` and registered through `setup()`. The LLM can
call it directly with:
- `files`: comma-separated file paths to fix (a string, not an array)
- `code`: Code string to fix via stdin

View File

@ -25,12 +25,11 @@ scripts/psql --host myhost --user myuser --db mydb
`scripts/psql` must be invoked from the repo root so the path resolves.
## Native Tool Available (opencode)
## Native Tool Available (OpenCode V2)
A native opencode tool `penpot-psql` is available (defined in
`.opencode/plugins/penpot.js`, which registers it for both opencode V1 via
`server()` and opencode V2 via `setup()`). The LLM can call it directly
with:
A native OpenCode V2 tool `penpot-psql` is available. It is defined in
`.opencode/plugins/penpot.js` and registered through `setup()`. The LLM can
call it directly with:
- `sql`: SQL command string to execute
- `test`: Boolean flag to use the `penpot_test` database