Files
fusion/plugins/fusion-plugin-openclaw-runtime/README.md
Fusion 4c204c9485 feat(FN-3717): add OpenClaw MCP bridge (+5 more)
Commits merged:
- docs(FN-3717): update openclaw runtime and settings docs
- test(FN-3717): fix openclaw engine test typing
- test(FN-3717): strengthen openclaw bridge coverage
- feat(FN-3717): complete Step 2 — wire engine and bundle delivery
- fix(FN-3717): address openclaw bridge review feedback
- feat(FN-3717): complete Step 1 — add OpenClaw MCP bridge

Files changed:
.changeset/fn-3717-openclaw-tool-bridge.md         |  5 ++
 docs/settings-reference.md                         | 28 +++++---
 packages/cli/src/__tests__/bundle-output.test.ts   |  9 +++
 packages/cli/tsup.config.ts                        |  7 ++
 .../src/__tests__/openclaw-runtime-e2e.test.ts     | 28 ++++++++
 .../__tests__/openclaw-runtime-integration.test.ts | 10 +++
 plugins/fusion-plugin-openclaw-runtime/README.md   | 13 ++++
 .../src/__tests__/cli-spawn.test.ts                | 82 +++++++++++++++++++---
 .../src/__tests__/mcp-config.test.ts               | 45 ++++++++++++
 .../src/__tests__/runtime-adapter.test.ts          | 46 ++++++++++++
 .../fusion-plugin-openclaw-runtime/src/index.ts    |  5 ++
 .../src/mcp-config.ts                              | 60 ++++++++++++++++
 .../src/mcp-schema-server.cjs                      | 59 ++++++++++++++++
 .../src/pi-module.ts                               | 52 ++++++++++++--
 .../src/runtime-adapter.ts                         | 26 +++++++
 .../fusion-plugin-openclaw-runtime/src/types.ts    |  4 ++
 16 files changed, 457 insertions(+), 22 deletions(-)

Fusion-Task-Id: FN-3717
2026-05-07 18:00:18 -07:00

113 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# OpenClaw Runtime Plugin
Drives the local **`openclaw` CLI** ([openclaw/openclaw](https://github.com/openclaw/openclaw)) as a subprocess. By default it runs `openclaw agent --local` (embedded mode, no daemon required); you can opt into the WebSocket gateway with `useGateway: true`.
## What it does
For each `promptWithFallback(session, prompt)`:
1. Spawns `openclaw --no-color agent --local --json --session-id <uuid> --message <prompt>` (plus `--agent`, `--model`, `--thinking`, `--timeout` if configured).
2. Reads the single JSON document on stdout (matching `OpenClawAgentJson`):
- Concatenates `payloads[]` where `!isError && !isReasoning``session.callbacks.onText(...)`.
- Joins `payloads[].isReasoning === true``session.callbacks.onThinking(...)`.
- Surfaces tool-level errors (`payloads[].isError === true`) as a logger warning.
- Stores `meta.agentMeta.usage` on the session for token accounting.
3. Reuses the same UUID across every prompt for the session so OpenClaw resumes the same agent conversation server-side.
The previous HTTP `/v1/chat/completions` integration has been removed — that endpoint required a separate gateway daemon and was an OpenAI-compat shim. The CLI surface is the canonical OpenClaw API.
## Fusion tool-control (MCP bridge)
When a Fusion OpenClaw session includes custom tools, the runtime plugin now enables tool-control through OpenClaw's supported MCP configuration flow:
1. Collect session tools and filter out built-ins: `read`, `write`, `edit`, `bash`, `grep`, `find`.
2. Convert remaining tools into MCP-compatible schemas.
3. Write a temporary schema file and MCP server config (`node mcp-schema-server.cjs <schema.json>`).
4. Configure a profile-scoped MCP server using `openclaw --profile <id> mcp set fusion-custom-tools <json>`.
5. Spawn the agent turn with `openclaw --profile <id> agent ...` so OpenClaw can see the configured MCP server.
No private protocol is used — this is the verified OpenClaw CLI contract (`mcp set` + `--profile`).
## Prerequisites
```bash
npm install -g openclaw
```
Verify with `openclaw --version` (expect `OpenClaw 2026.x.y`).
If you want gateway mode (`useGateway: true`), also start `openclaw gateway run` separately.
> **First-run note:** the very first `openclaw agent` invocation lazy-installs runtime deps and can take 3060s. Subsequent calls are fast.
## Settings
| Key | Env var | Default | Notes |
|---|---|---|---|
| `binaryPath` | `OPENCLAW_BIN` | `openclaw` | Path to the `openclaw` binary. |
| `agentId` | `OPENCLAW_AGENT_ID` | `main` | Maps to `--agent <id>`. List with `openclaw agents list`. |
| `model` | `OPENCLAW_MODEL` | (OpenClaw default) | Maps to `--model <provider/model>`, e.g. `anthropic/claude-haiku-4-5`. |
| `thinking` | `OPENCLAW_THINKING` | `off` | One of `off | minimal | low | medium | high | xhigh | adaptive | max`. |
| `cliTimeoutSec` | `OPENCLAW_TIMEOUT_SEC` | `0` | OpenClaw-side timeout (0 = no limit). |
| `cliTimeoutMs` | `OPENCLAW_CLI_TIMEOUT_MS` | `300000` | Hard kill on the Fusion side. |
| `useGateway` | `OPENCLAW_USE_GATEWAY` | `false` | When `true`, omit `--local`; the CLI tries the WS gateway and falls back to embedded after ~2 s. |
Settings precedence: plugin settings → env var → default.
## Limitations
- **No per-token streaming.** `--json` emits a single JSON document at process exit. `onText` is called exactly once.
- **Default ignores the gateway.** With `useGateway: false` (default) we always pass `--local`, skipping the WebSocket connect attempt entirely. Most users want this.
- **Built-in tools are intentionally excluded from MCP bridge.** `read`, `write`, `edit`, `bash`, `grep`, and `find` stay native to Fusion and are not duplicated through OpenClaw MCP.
- **AbortSignal sends SIGTERM.** If the CLI ignores it (e.g. during a long model download), the hard-kill timer (`cliTimeoutMs`) eventually fires.
## Public API
```ts
import {
OpenClawRuntimeAdapter,
resolveCliConfig,
buildOpenClawArgs,
createCliSession,
promptCli,
describeCliModel,
extractStderrError,
probeOpenClawBinary,
type CliConfig,
type GatewaySession,
type OpenClawAgentJson,
type OpenClawBinaryStatus,
} from "@fusion-plugin-examples/openclaw-runtime";
```
`probeOpenClawBinary({ binaryPath?, timeoutMs? })` runs `openclaw --version` and returns `{ available, version, binaryPath, reason, probeDurationMs }` — used by the dashboard's "Runtimes → OpenClaw" settings card.
## Agent configuration
To create a Fusion agent backed by OpenClaw, set `runtimeConfig.runtimeHint`:
```json
{
"name": "OpenClaw Executor",
"role": "executor",
"runtimeConfig": {
"runtimeHint": "openclaw"
}
}
```
Runtime selection happens in the dashboard's **New Agent → Plugin Runtime → OpenClaw**.
## Metadata
- **Plugin ID:** `fusion-plugin-openclaw-runtime`
- **Runtime ID:** `openclaw`
- **Package:** `@fusion-plugin-examples/openclaw-runtime`
## Development
```bash
pnpm --filter @fusion-plugin-examples/openclaw-runtime test # 44 tests
pnpm --filter @fusion-plugin-examples/openclaw-runtime build
```