kaiju-coder-7-opencode / scripts /opencode-kaiju-no-autocontinue.mjs
restokes92's picture
Upload Kaiju Coder 7 OpenCode helper package
89ef4db verified
import { spawn } from "node:child_process";
import { existsSync } from "node:fs";
import { mkdir, writeFile } from "node:fs/promises";
import { homedir, platform } from "node:os";
import path from "node:path";
import { tool } from "@opencode-ai/plugin";
const TASK_KINDS = ["auto", "website", "business_document", "business_suite", "app", "code_project", "repo_patch", "coding"];
const defaultRuntimeScript = () =>
path.join(homedir(), ".config", "opencode", "kaiju-coder-7-runtime", "scripts", "run_kaiju_router.py");
const resolveSafeFile = (directory, filePath) => {
const base = path.resolve(directory || process.cwd());
const resolved = path.resolve(base, filePath);
if (resolved !== base && !resolved.startsWith(`${base}${path.sep}`)) {
throw new Error(`Refusing to write outside the OpenCode directory: ${filePath}`);
}
return resolved;
};
const runProcess = (command, args, options = {}) =>
new Promise((resolve, reject) => {
const child = spawn(command, args, {
...options,
env: {
...process.env,
...(options.env || {}),
},
});
let stdout = "";
let stderr = "";
child.stdout?.on("data", (chunk) => {
stdout += chunk.toString();
});
child.stderr?.on("data", (chunk) => {
stderr += chunk.toString();
});
child.on("error", reject);
child.on("close", (code) => {
if (code === 0) {
resolve({ stdout, stderr });
return;
}
reject(new Error([`Command failed with exit ${code}: ${command}`, stdout, stderr].filter(Boolean).join("\n")));
});
});
const shouldOpenArtifact = (text) =>
/\b(open it|open the (?:html|file|site|website|page)|launch it|show it)\b/i.test(text || "");
const extractArtifactPath = (stdout) => {
const artifact = stdout.match(/^Artifact:\s*(.+)$/m);
if (artifact) {
return artifact[1].trim();
}
const project = stdout.match(/^Project\/repo:\s*(.+)$/m);
return project ? project[1].trim() : "";
};
const openArtifact = async (artifactPath) => {
if (!artifactPath || !existsSync(artifactPath)) {
return "";
}
const system = platform();
if (system === "darwin") {
await runProcess("open", [artifactPath]);
} else if (system === "win32") {
await runProcess("cmd", ["/c", "start", "", artifactPath]);
} else {
await runProcess("xdg-open", [artifactPath]);
}
return `Opened artifact: ${artifactPath}`;
};
export const KaijuCoder7NoAutocontinuePlugin = async () => {
const isKaijuCoder7 = (input) => {
const payload = JSON.stringify({
agent: input?.agent,
model: input?.model,
provider: input?.provider,
session: input?.session,
});
return (
payload.includes("kaiju-coder-7") ||
payload.includes("Kaiju Coder 7") ||
payload.includes("kaiju/kaiju-coder-7")
);
};
return {
tool: {
kaiju_write_file: tool({
description:
"Write one exact small file in the current OpenCode directory. Use for exact one-file creation requests, not large generated websites or projects.",
args: {
file_path: tool.schema.string().describe("Relative path to write inside the current OpenCode directory."),
content: tool.schema.string().describe("Exact file content to write."),
},
async execute(args, context) {
const target = resolveSafeFile(context.directory, args.file_path);
await mkdir(path.dirname(target), { recursive: true });
await writeFile(target, args.content, "utf8");
return {
output: `Wrote file: ${target}`,
metadata: { file_path: target, bytes: Buffer.byteLength(args.content, "utf8") },
};
},
}),
kaiju_artifact: tool({
description:
"Create fast Kaiju Coder 7 websites, owner packs, apps, business documents, or code artifacts with the packaged local router. Use this instead of bash/write for large generated artifact tasks.",
args: {
prompt: tool.schema.string().describe("The full user request to build."),
out_dir: tool.schema
.string()
.optional()
.describe("Absolute output directory. For Desktop requests, use /Users/<user>/Desktop/<clear-folder-name>."),
kind: tool.schema
.enum(TASK_KINDS)
.optional()
.describe("Artifact type. Use website for sites and business_suite for owner operating packs."),
no_planner: tool.schema
.boolean()
.optional()
.describe("Use deterministic rendering without a second model-planning call. Defaults to true."),
},
async execute(args, context) {
const runtimeScript = process.env.KAIJU_ROUTER_SCRIPT || defaultRuntimeScript();
if (!existsSync(runtimeScript)) {
throw new Error(`Kaiju router runtime is missing: ${runtimeScript}`);
}
const outDir =
args.out_dir ||
path.join(homedir(), "Desktop", "Kaiju-Coder-7-Artifacts");
const kind = args.kind || "auto";
const noPlanner = args.no_planner !== false;
const procArgs = [runtimeScript, "--kind", kind, "--out-dir", outDir, "--prompt", args.prompt];
if (noPlanner) {
procArgs.splice(1, 0, "--no-planner");
}
context.metadata({
title: `Kaiju artifact: ${kind}`,
metadata: { out_dir: outDir, kind, no_planner: noPlanner },
});
const result = await runProcess(process.env.KAIJU_PYTHON || "python3", procArgs, {
cwd: context.directory || process.cwd(),
});
let output = result.stdout.trim() || "Kaiju artifact command completed.";
if (shouldOpenArtifact(args.prompt)) {
const artifactPath = extractArtifactPath(output);
try {
const opened = await openArtifact(artifactPath);
output += opened
? `\n${opened}`
: "\nOpen requested, but no generated artifact path was available to open.";
} catch (error) {
output += `\nOpen requested, but could not open artifact: ${error.message}`;
}
}
return {
output,
metadata: { stderr: result.stderr.trim(), out_dir: outDir, kind, no_planner: noPlanner },
};
},
}),
},
async "chat.params"(input, output) {
if (!isKaijuCoder7(input)) {
return;
}
output.temperature = 0;
output.maxOutputTokens = Math.min(output.maxOutputTokens || 768, 768);
},
async "experimental.compaction.autocontinue"(input, output) {
if (isKaijuCoder7(input)) {
output.enabled = false;
}
},
async "experimental.session.compacting"(input, output) {
if (!isKaijuCoder7(input)) {
return;
}
output.context.push(
[
"For Kaiju Coder 7 sessions, summarize only facts proven by tool output.",
"Do not say a file was created unless a write/edit/bash/read result confirms it exists.",
"If work is incomplete or unverified, mark it incomplete instead of complete.",
"Never convert a maximum-step, compaction, or length-limit stop into a successful completion claim.",
].join("\n"),
);
},
};
};
export default KaijuCoder7NoAutocontinuePlugin;