feat: add OpenCode adapter
Thin OpenCode plugin injecting the ponytail ruleset via experimental.chat.system.transform, reusing the shared instruction builder. Verified end-to-end on OpenCode 1.17.4. Supersedes #15.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
description: Review changes for over-engineering — what can be deleted
|
||||
---
|
||||
|
||||
Review the current code changes for over-engineering only — not correctness. One line per finding: L<line>: <tag> <what to cut>. <replacement>. Tags: delete (dead code/speculative feature), stdlib (reinvented standard library), native (dependency doing what the platform does), yagni (abstraction with one implementation), shrink (same logic, fewer lines). End with the net lines removable. If nothing to cut: 'Lean already. Ship.'
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
description: Switch ponytail intensity level (lite/full/ultra/off)
|
||||
---
|
||||
|
||||
Switch to ponytail $ARGUMENTS mode. If no level specified, use full. Lazy senior dev mode — before any code: does it need to exist at all (YAGNI)? Does the standard library do it? A native platform feature? Can it be one line? Build the minimum that works. No unrequested abstractions, no avoidable dependencies, no boilerplate. Mark intentional simplifications with a ponytail: comment.
|
||||
@@ -0,0 +1,65 @@
|
||||
// ponytail — OpenCode plugin.
|
||||
//
|
||||
// Injects the ponytail ruleset into every chat's system prompt at the active
|
||||
// intensity, and persists /ponytail mode switches. Reuses the shared instruction
|
||||
// builder so Claude Code, Codex, pi, and OpenCode all read one source of truth.
|
||||
//
|
||||
// OpenCode loads this as a server plugin — add it to your opencode.json:
|
||||
// { "plugin": ["./.opencode/plugins/ponytail.mjs"] }
|
||||
|
||||
import { createRequire } from 'module';
|
||||
import fs from 'fs';
|
||||
import os from 'os';
|
||||
import path from 'path';
|
||||
|
||||
// The shared instruction builder is CommonJS; bridge to it from this ES module.
|
||||
const require = createRequire(import.meta.url);
|
||||
const { getPonytailInstructions } = require('../../hooks/ponytail-instructions');
|
||||
const { getDefaultMode, normalizePersistedMode } = require('../../hooks/ponytail-config');
|
||||
|
||||
// OpenCode has no flag-file convention of its own; keep mode beside its config.
|
||||
const statePath = path.join(
|
||||
process.env.XDG_CONFIG_HOME || path.join(os.homedir(), '.config'),
|
||||
'opencode',
|
||||
'.ponytail-active',
|
||||
);
|
||||
|
||||
function readMode() {
|
||||
try {
|
||||
return normalizePersistedMode(fs.readFileSync(statePath, 'utf8').trim()) || getDefaultMode();
|
||||
} catch (e) {
|
||||
return getDefaultMode();
|
||||
}
|
||||
}
|
||||
|
||||
function writeMode(mode) {
|
||||
fs.mkdirSync(path.dirname(statePath), { recursive: true });
|
||||
fs.writeFileSync(statePath, mode);
|
||||
}
|
||||
|
||||
export default async ({ client } = {}) => {
|
||||
const log = (level, message) => {
|
||||
try { client && client.app && client.app.log({ body: { service: 'ponytail', level, message } }); } catch (e) {}
|
||||
};
|
||||
|
||||
return {
|
||||
// Append the ruleset to the system prompt every turn.
|
||||
'experimental.chat.system.transform': async (_input, output) => {
|
||||
const mode = readMode();
|
||||
if (mode === 'off') return;
|
||||
output.system.push(getPonytailInstructions(mode));
|
||||
},
|
||||
|
||||
// Persist `/ponytail <level>` so the next turn's injection follows it.
|
||||
// ponytail: mode applies from the next message, not the current one — the
|
||||
// transform reads the flag the command writes. Good enough; switch to a
|
||||
// synchronous store if same-turn switching ever matters.
|
||||
'command.execute.before': async (input) => {
|
||||
if (!input || input.command !== 'ponytail') return;
|
||||
// `off` is persisted like any mode; the transform reads it and stays silent.
|
||||
const mode = normalizePersistedMode((input.arguments || '').trim()) || getDefaultMode();
|
||||
writeMode(mode);
|
||||
log('info', 'ponytail ' + mode);
|
||||
},
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user