@kontextmind/kxm
Version:
KXM local-first multi-agent orchestration and operator dashboard
61 lines (57 loc) • 3.18 kB
JavaScript
import { spawn } from "node:child_process";
import { mkdirSync, writeFileSync } from "node:fs";
import { join, resolve } from "node:path";
import { pathToFileURL } from "node:url";
import { HubClient } from "../plugins/kxm/dist/client.js";
import { buildArgv } from "./harness-run.mjs";
// Launch intent only: these labels are not observed model identity or admission.
export function nativeCriticLaunch(harness) {
if (!["fable", "astra"].includes(harness)) {
throw new Error("usage: native-critic.mjs <fable|astra> <prompt>");
}
const model = harness === "fable" ? "fable" : "gpt-6-astra";
const command = harness === "fable" ? "claude" : "codex";
const args = harness === "fable"
? ["-p", "--model", model, "--effort", "medium", "--output-format", "json", "--no-session-persistence", "--tools", "Read,Glob,Grep", "--setting-sources", "user"]
: buildArgv({ harness: "codex", model, effort: "low", permission: "read-only", prompt_file: "-" });
return { model, command, args };
}
async function main() {
const [harness, ...promptParts] = process.argv.slice(2);
let launch;
try {
launch = nativeCriticLaunch(harness);
} catch (error) {
console.error(error.message);
process.exitCode = 2;
return;
}
const { model, command, args } = launch;
const env = process.env;
const serverUrl = env.KXM_SERVER_URL || "http://127.0.0.1:7331";
const outDir = env.KXM_CRITIC_DIR || join(process.cwd(), ".kxm", "assets", "critic-reviews");
mkdirSync(outDir, { recursive: true });
const client = new HubClient({ serverUrl, authToken: env.KXM_AUTH_TOKEN, name: `${harness}-critic`, purpose: "independent CLI critic", project: env.KXM_PROJECT || ".kxm", model });
const prompt = promptParts.join(" ");
const agent = await client.start(() => { });
const result = await new Promise((resolve) => {
const child = spawn(command, args, { env, stdio: ["pipe", "pipe", "pipe"], shell: false });
let stdout = "", stderr = "";
child.stdout.on("data", (chunk) => { stdout += chunk; });
child.stderr.on("data", (chunk) => { stderr += chunk; });
child.on("error", (error) => resolve({ code: null, stdout, stderr: String(error) }));
child.on("close", (code, signal) => resolve({ code, signal, stdout, stderr }));
child.stdin.end(prompt);
});
const stamp = new Date().toISOString().replace(/[:.]/g, "-");
const path = join(outDir, `${harness}-${stamp}.json`);
writeFileSync(path, JSON.stringify({ schema: "kxm.native-critic-review.v1", harness, model, agentId: agent.id, completedAt: new Date().toISOString(), ...result }, null, 2) + "\n", { mode: 0o600 });
try { await client.send({ target: env.KXM_REVIEW_TARGET || agent.id, content: `${harness} review completed; artifact=${path}; exit=${String(result.code)}`, delivery: "followUp", idempotencyKey: `critic:${harness}:${stamp}` }); } catch { /* Transport artifact remains, not approval or hub peer-reply evidence. */ }
await client.stop();
if (result.code !== 0) process.exit(result.code ?? 1);
console.log(path);
}
if (process.argv[1] && import.meta.url === pathToFileURL(resolve(process.argv[1])).href) {
await main();
}