## Summary - Add `fusion-plugin-omp-runtime` so Fusion agents can run through operator-installed **Oh My Pi (`omp`)** over the [Agent Client Protocol](https://omp.sh/docs/acp) (`omp acp`). - Wire staged/bundled install, Settings → Authentication card (enable + binary path), model discovery (`omp models` → `omp-cli/*`), and MCP eligibility for runtime id `omp`. - Forward Fusion `systemPrompt` via ACP `session/new` `_meta.systemPromptOverride`. ## How operators use it 1. Install/auth `omp` (credentials under `~/.omp`). 2. Enable **Oh My Pi — via omp ACP** in Settings → Authentication (optional binary path). 3. Set agent **Runtime Source → OMP Runtime** (`runtimeHint: "omp"`), or pick an `omp-cli/*` model when enabled. ## Known v1 gaps - No Grok-style Fusion `fn_*` loopback tool bridge yet (operator MCP is forwarded; in-process custom tools are not). - Model is fixed at spawn (`omp --model … acp`); no mid-session Fusion model switch. ## Test plan - [x] `pnpm --filter @fusion-plugin-examples/omp-runtime test` (unit + live ACP when `omp` is on PATH) - [x] Auth routes: `POST /api/auth/omp-cli`, `GET /api/providers/omp-cli/status` - [x] Engine `runtimeSupportsMcp("omp")` - [ ] Manual: enable card in dashboard, select OMP runtime on an agent, run a short chat turn <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **New Features** * Added Oh My Pi (OMP) CLI support as an ACP-backed runtime and model provider, including model discovery and probing. * Added dashboard auth/status controls to enable OMP, check readiness, and configure the local binary path (with validation). * Exposed OMP custom `fn_*` tools via an MCP loopback bridge, plus optional filesystem capabilities and stricter tool permission gating. * **Documentation** * Added/expanded OMP runtime contract and integration docs (including the ACP session/handshake flow). * **Tests** * Added Vitest coverage for settings wiring, provider status, model discovery, runtime sessions, permissions, MCP bridging, and live connectivity. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
62 lines
1.8 KiB
TypeScript
62 lines
1.8 KiB
TypeScript
import { spawn } from "node:child_process";
|
|
|
|
function formatSpawnError(error: Error & { code?: unknown }): string {
|
|
const code = typeof error.code === "string" ? `${error.code}: ` : "";
|
|
return `spawn error: ${code}${error.message}`.trim();
|
|
}
|
|
|
|
export async function runOmpCommand(
|
|
binary: string,
|
|
args: string[],
|
|
timeoutMs: number,
|
|
): Promise<{ code: number | null; stdout: string; stderr: string }> {
|
|
return new Promise((resolve) => {
|
|
let stdout = "";
|
|
let stderr = "";
|
|
let settled = false;
|
|
let timer: NodeJS.Timeout | undefined;
|
|
|
|
const finish = (result: { code: number | null; stdout: string; stderr: string }) => {
|
|
if (settled) return;
|
|
settled = true;
|
|
if (timer) clearTimeout(timer);
|
|
resolve(result);
|
|
};
|
|
|
|
/*
|
|
FNXC:OmpAcp 2026-07-11-23:35:
|
|
Windows installers/npm-style shims can expose `omp.cmd` or `omp.bat` on PATH;
|
|
Node cannot direct-spawn those batch wrappers without the command shell.
|
|
Keep Unix/macOS on direct spawn.
|
|
*/
|
|
const child = spawn(binary, args, {
|
|
stdio: ["ignore", "pipe", "pipe"],
|
|
shell: process.platform === "win32",
|
|
});
|
|
|
|
timer = setTimeout(() => {
|
|
try {
|
|
child.kill("SIGKILL");
|
|
} catch {
|
|
// best effort
|
|
}
|
|
finish({ code: 124, stdout, stderr });
|
|
}, timeoutMs);
|
|
|
|
child.stdout?.on("data", (c: Buffer) => {
|
|
stdout += c.toString("utf-8");
|
|
});
|
|
child.stderr?.on("data", (c: Buffer) => {
|
|
stderr += c.toString("utf-8");
|
|
});
|
|
child.once("error", (error: Error & { code?: unknown }) => {
|
|
const diagnostic = formatSpawnError(error);
|
|
stderr = stderr ? `${stderr}\n${diagnostic}` : diagnostic;
|
|
finish({ code: 127, stdout, stderr });
|
|
});
|
|
child.once("close", (code) => {
|
|
finish({ code, stdout, stderr });
|
|
});
|
|
});
|
|
}
|