## 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 -->
51 lines
1.7 KiB
TypeScript
51 lines
1.7 KiB
TypeScript
/* Vendored ACP client from fusion-plugin-acp-runtime — see ./VENDORED.md (FNXC:GrokAcp 2026-07-11-16:00). */
|
|
// Builds ACP `ContentBlock[]` from a Fusion prompt.
|
|
//
|
|
// U3 core path: a plain string prompt becomes a single `{ type: "text", text }`
|
|
// block. The runtime may later pass structured content (e.g. an attached image);
|
|
// when present we emit the matching block. Keep this small and pure.
|
|
|
|
import type { ContentBlock } from "@agentclientprotocol/sdk";
|
|
|
|
/** Optional structured content the runtime may attach alongside the text prompt. */
|
|
export interface PromptImage {
|
|
/** Base64-encoded image data (no data: prefix). */
|
|
data: string;
|
|
/** MIME type, e.g. "image/png". */
|
|
mimeType: string;
|
|
/** Optional source URI for the image. */
|
|
uri?: string;
|
|
}
|
|
|
|
export interface BuildPromptOptions {
|
|
/** Image content to append as image block(s) after the text. */
|
|
images?: PromptImage[];
|
|
}
|
|
|
|
/**
|
|
* Build the ACP prompt content blocks for a turn.
|
|
*
|
|
* A non-empty string yields one text block. An empty/whitespace-only string
|
|
* yields no text block (but any attached images are still included), so we never
|
|
* send a meaningless empty text block. Images, when supplied, are appended as
|
|
* `image` blocks (passthrough — KTD ContentBlock image variant).
|
|
*/
|
|
export function buildPromptBlocks(prompt: string, opts?: BuildPromptOptions): ContentBlock[] {
|
|
const blocks: ContentBlock[] = [];
|
|
|
|
if (typeof prompt === "string" && prompt.trim().length > 0) {
|
|
blocks.push({ type: "text", text: prompt });
|
|
}
|
|
|
|
for (const image of opts?.images ?? []) {
|
|
blocks.push({
|
|
type: "image",
|
|
data: image.data,
|
|
mimeType: image.mimeType,
|
|
...(image.uri ? { uri: image.uri } : {}),
|
|
});
|
|
}
|
|
|
|
return blocks;
|
|
}
|