Harden dependency floors and update the Vitest toolchain to patched releases. - upgrade workspace vitest and @vitest/coverage-v8 dependencies to the 4.1 line across packages and plugins - pin transitive protobufjs via pnpm overrides and lockfile updates to patched versions - adapt Vitest configs, engine test helpers, and security-floor coverage for the new dependency baselines - add the published CLI changeset and related workspace/package metadata updates included in the task branch Files changed: .changeset/fn-6042-security-dependencies.md | 5 + AGENTS.md | 4 + Dockerfile | 3 + docs/PLUGIN_AUTHORING.md | 2 - package.json | 3 +- packages/cli/package.json | 4 +- packages/cli/vitest.config.ts | 2 +- packages/core/package.json | 4 +- packages/core/vitest.config.ts | 2 +- packages/dashboard/app/test/mockApi.ts | 4 +- packages/dashboard/package.json | 4 +- packages/dashboard/vitest.config.ts | 2 +- packages/desktop/package.json | 4 +- packages/desktop/vitest.config.ts | 2 +- packages/droid-cli/package.json | 2 +- packages/droid-cli/vitest.config.ts | 2 +- packages/engine/package.json | 4 +- .../engine/src/__tests__/executor-test-helpers.ts | 29 +- .../engine/src/__tests__/gridlock-detector.test.ts | 5 +- .../src/__tests__/heartbeat-scheduler.test.ts | 3 +- packages/engine/src/__tests__/scheduler.test.ts | 24 +- packages/engine/src/__tests__/self-healing.test.ts | 5 + packages/engine/tsconfig.json | 3 +- packages/engine/vitest.config.ts | 10 +- packages/i18n/package.json | 2 +- packages/i18n/vitest.config.ts | 7 + packages/mobile/package.json | 2 +- packages/mobile/vitest.config.ts | 2 +- packages/pi-claude-cli/package.json | 2 +- packages/pi-claude-cli/vitest.config.ts | 2 +- packages/pi-llama-cpp/package.json | 2 +- packages/pi-llama-cpp/vitest.config.ts | 2 +- packages/plugin-sdk/package.json | 2 +- packages/plugin-sdk/vitest.config.ts | 2 +- .../examples/fusion-plugin-auto-label/package.json | 2 +- .../fusion-plugin-auto-label/vitest.config.ts | 2 +- .../examples/fusion-plugin-ci-status/package.json | 2 +- .../fusion-plugin-ci-status/vitest.config.ts | 2 +- .../fusion-plugin-notification/package.json | 2 +- .../fusion-plugin-notification/vitest.config.ts | 2 +- .../fusion-plugin-settings-demo/package.json | 2 +- .../fusion-plugin-settings-demo/vitest.config.ts | 2 +- plugins/fusion-plugin-acp-runtime/package.json | 2 +- plugins/fusion-plugin-acp-runtime/vitest.config.ts | 2 +- plugins/fusion-plugin-agent-browser/package.json | 2 +- .../fusion-plugin-agent-browser/vitest.config.ts | 2 +- .../fusion-plugin-cli-printing-press/package.json | 2 +- .../vitest.config.ts | 2 +- .../package.json | 2 +- .../src/__tests__/orchestrator-live-output.test.ts | 4 +- .../vitest.config.ts | 2 +- plugins/fusion-plugin-cursor-runtime/package.json | 4 +- .../fusion-plugin-dependency-graph/package.json | 4 +- .../vitest.config.ts | 2 +- plugins/fusion-plugin-droid-runtime/package.json | 2 +- .../fusion-plugin-droid-runtime/vitest.config.ts | 2 +- plugins/fusion-plugin-even-cards/package.json | 2 +- plugins/fusion-plugin-even-cards/vitest.config.ts | 2 +- .../package.json | 2 +- .../vitest.config.ts | 2 +- plugins/fusion-plugin-hermes-runtime/package.json | 2 +- .../fusion-plugin-hermes-runtime/vitest.config.ts | 2 +- .../fusion-plugin-openclaw-runtime/package.json | 2 +- .../vitest.config.ts | 2 +- .../fusion-plugin-paperclip-runtime/package.json | 2 +- .../vitest.config.ts | 2 +- plugins/fusion-plugin-reports/package.json | 2 +- .../src/__tests__/review-panel.test.ts | 6 +- plugins/fusion-plugin-reports/vitest.config.ts | 2 +- plugins/fusion-plugin-roadmap/package.json | 2 +- plugins/fusion-plugin-roadmap/vitest.config.ts | 2 +- plugins/fusion-plugin-whatsapp-chat/package.json | 2 +- .../fusion-plugin-whatsapp-chat/vitest.config.ts | 2 +- pnpm-lock.yaml | 626 ++++++++------------- .../__tests__/dependency-security-floor.test.mjs | 95 ++++ 75 files changed, 475 insertions(+), 491 deletions(-) Fusion-Task-Id: FN-6042 Fusion-Task-Lineage: fff6a1cb-8937-435c-9a91-b7c7a59cc80e
OpenClaw Runtime Plugin
Drives the local openclaw CLI (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):
- Spawns
openclaw --no-color agent --local --json --session-id <uuid> --message <prompt>(plus--agent,--model,--thinking,--timeoutif configured). - 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.usageon the session for token accounting.
- Concatenates
- 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:
- Collect session tools and filter out built-ins:
read,write,edit,bash,grep,find. - Convert remaining tools into MCP-compatible schemas.
- Write a temporary schema file and MCP server config (
node mcp-schema-server.cjs <schema.json>). - Configure a profile-scoped MCP server using
openclaw --profile <id> mcp set fusion-custom-tools <json>. - 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
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 agentinvocation lazy-installs runtime deps and can take 30–60s. 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 |
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.
--jsonemits a single JSON document at process exit.onTextis 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, andfindstay 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
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:
{
"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
pnpm --filter @fusion-plugin-examples/openclaw-runtime test # 44 tests
pnpm --filter @fusion-plugin-examples/openclaw-runtime build