fix(plugins): re-export probe symbols + declare plugin deps in dashboard
- Hermes / OpenClaw plugin index.ts now re-export `probeHermesBinary` / `probeOpenClawBinary` and their status types so the dashboard's `runtime-provider-probes.ts` façade can import them via the public package entry instead of deep paths. - Dashboard `package.json` adds `@fusion-plugin-examples/hermes-runtime`, `…/openclaw-runtime`, `…/paperclip-runtime` as workspace deps so pnpm symlinks them into `packages/dashboard/node_modules/`. Without these, the new probe imports failed with "Cannot find module" during `pnpm typecheck`. This clears 6 of the 9 outstanding typecheck errors. The remaining 3 are in the in-flight Hermes plugin rewrite (runtime-adapter still imports from a deleted `./pi-module.js`; the new `index.ts` calls a factory with the wrong arg type) and should be resolved by the same change set that landed the rewrite. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,80 +1,83 @@
|
||||
# Hermes Runtime Plugin
|
||||
|
||||
Hermes is a **raw-model runtime** plugin for Fusion. It creates and manages LLM sessions directly through [`@mariozechner/pi-ai`](https://www.npmjs.com/package/@mariozechner/pi-ai), without using Fusion's internal Pi coding-agent pipeline.
|
||||
Drives the local **`hermes` CLI** ([NousResearch/hermes-agent](https://github.com/NousResearch/hermes-agent)) as a subprocess, so a Fusion agent backed by this runtime delegates each prompt to a real Hermes Agent process running on the same machine.
|
||||
|
||||
## What it does
|
||||
|
||||
- Resolves provider/model settings from plugin settings, environment variables, and defaults
|
||||
- Creates in-memory streaming sessions with `streamSimple(...)`
|
||||
- Maintains conversation history (`messages`) inside the plugin session
|
||||
- Streams text/thinking/tool-call deltas through runtime callbacks
|
||||
- Exposes model description as `<provider>/<modelId>`
|
||||
For each `promptWithFallback(session, prompt)` call:
|
||||
|
||||
## How it differs from the default Pi runtime
|
||||
1. Spawns `hermes chat -q <prompt> -Q --source tool` (with `--resume <id>` on subsequent calls in the same session).
|
||||
2. Captures the trailing `session_id: YYYYMMDD_HHMMSS_xxxxxx` line from stdout.
|
||||
3. Strips ANSI + TUI chrome (`╭─ Hermes ─╮`, `↻ Resumed session …`, etc.) and forwards the cleaned response body to `session.callbacks.onText(...)`.
|
||||
4. Persists the captured session id on the session object so the next call resumes the same Hermes session.
|
||||
|
||||
| Runtime | Behavior |
|
||||
| --- | --- |
|
||||
| Default Pi runtime (`pi`) | Full coding-agent flow (`createFnAgent`, tool execution, skill/session manager integration) |
|
||||
| Hermes runtime (`hermes`) | Direct pi-ai model streaming (no coding-agent tool execution pipeline) |
|
||||
This is fundamentally different from the older "raw-model" approach that bypassed `hermes` entirely by calling `@mariozechner/pi-ai` directly. The CLI subprocess is now the source of truth — provider/model selection, auth, skills, and memory are all the responsibility of the user's local `hermes` install.
|
||||
|
||||
Hermes is intentionally lightweight: it does not execute tools or perform filesystem workflows like the coding agent.
|
||||
## Prerequisites
|
||||
|
||||
## Configuration
|
||||
You need the `hermes` Python CLI on `PATH` (or set `binaryPath` / `HERMES_BIN`). Install instructions:
|
||||
|
||||
Hermes resolves settings in this order:
|
||||
```bash
|
||||
# Recommended: use the upstream installer
|
||||
curl -LsSf https://hermes-agent.nousresearch.com/install.sh | sh
|
||||
|
||||
1. Plugin settings (`ctx.settings`)
|
||||
2. Environment variables
|
||||
3. Built-in defaults
|
||||
|
||||
### Plugin settings
|
||||
|
||||
```json
|
||||
{
|
||||
"provider": "anthropic",
|
||||
"modelId": "claude-sonnet-4-5",
|
||||
"apiKey": "...optional...",
|
||||
"thinkingLevel": "medium"
|
||||
}
|
||||
# Or via pipx (cross-platform)
|
||||
pipx install hermes-agent
|
||||
```
|
||||
|
||||
### Environment variable fallbacks
|
||||
After install, run `hermes login` (or `hermes auth`) to configure a provider. The Fusion plugin does **not** manage Hermes auth — it inherits whatever the local install has.
|
||||
|
||||
- `HERMES_PROVIDER`
|
||||
- `HERMES_MODEL_ID`
|
||||
- `HERMES_API_KEY`
|
||||
- `HERMES_THINKING_LEVEL`
|
||||
Verify with `hermes --version`.
|
||||
|
||||
### Defaults
|
||||
## Limitations
|
||||
|
||||
- `provider`: `anthropic`
|
||||
- `modelId`: `claude-sonnet-4-5`
|
||||
- `apiKey`: `undefined`
|
||||
- `thinkingLevel`: `undefined`
|
||||
Because we drive the CLI's `chat -q` mode:
|
||||
|
||||
## Runtime contract notes
|
||||
- **No per-token streaming.** Hermes buffers output through prompt_toolkit; the full response arrives once the process exits. `onText` is called exactly once per turn.
|
||||
- **No reasoning/thinking deltas.** `-Q` mode suppresses them. If you need streaming + reasoning, switch to Hermes's ACP mode (not yet implemented in this plugin).
|
||||
- **No tool-call hooks.** Hermes runs tools internally; Fusion only sees the final assistant text. Use `yolo: true` to skip Hermes's interactive approval prompts in non-interactive sessions.
|
||||
- **`AgentRuntimeOptions.cwd`, `tools`, `skills`, `sessionManager`, etc. are ignored** — Hermes's own session/tools/skills systems handle these.
|
||||
|
||||
Hermes accepts the standard `AgentRuntimeOptions` shape for compatibility, but these Pi-specific fields are **silently ignored**:
|
||||
## Settings
|
||||
|
||||
- `cwd`
|
||||
- `tools`
|
||||
- `skills`
|
||||
- `customTools`
|
||||
- `sessionManager`
|
||||
- `skillSelection`
|
||||
| Key | Env var | Default | Notes |
|
||||
|---|---|---|---|
|
||||
| `binaryPath` | `HERMES_BIN` | `hermes` | Path to the `hermes` binary. Falls back to PATH lookup. |
|
||||
| `model` | `HERMES_MODEL_ID` | (Hermes default) | `-m <model>` (e.g. `claude-sonnet-4-5`, `MiniMax-M2.7`). |
|
||||
| `provider` | `HERMES_PROVIDER` | (Hermes default) | `--provider <provider>` — one of `auto`, `anthropic`, `openrouter`, `gemini`, `openai-codex`, `copilot`, `copilot-acp`, `huggingface`, `zai`, `kimi-coding`, `minimax`, `minimax-cn`, `kilocode`, `xiaomi`, `nous`. |
|
||||
| `maxTurns` | `HERMES_MAX_TURNS` | `12` | `--max-turns N`. Hermes's own default is 90; we cap lower. |
|
||||
| `yolo` | `HERMES_YOLO` | `false` | `--yolo` — skip interactive approval. Required for non-interactive sessions that use shell-style tools. |
|
||||
| `cliTimeoutMs` | `HERMES_CLI_TIMEOUT_MS` | `300000` (5 min) | Hard kill on the Fusion side. |
|
||||
|
||||
The runtime returns `sessionFile: undefined` because Hermes sessions are in-memory.
|
||||
Settings precedence: plugin settings → env var → default.
|
||||
|
||||
## Public API
|
||||
|
||||
```ts
|
||||
import {
|
||||
HermesRuntimeAdapter,
|
||||
resolveCliSettings,
|
||||
invokeHermesCli,
|
||||
buildHermesArgs,
|
||||
parseHermesOutput,
|
||||
probeHermesBinary,
|
||||
type HermesCliSettings,
|
||||
type HermesCliResult,
|
||||
type HermesBinaryStatus,
|
||||
} from "@fusion-plugin-examples/hermes-runtime";
|
||||
```
|
||||
|
||||
`probeHermesBinary({ binaryPath?, timeoutMs? })` runs `hermes --version` and returns `{ available, version, binaryPath, reason, probeDurationMs }`. Used by the dashboard's "Runtimes → Hermes" settings card to power the install-status badge.
|
||||
|
||||
## Metadata
|
||||
|
||||
- **Plugin ID:** `fusion-plugin-hermes-runtime`
|
||||
- **Runtime ID:** `hermes`
|
||||
- **Runtime name:** `Hermes Runtime`
|
||||
- **Package:** `@fusion-plugin-examples/hermes-runtime`
|
||||
|
||||
## Development
|
||||
|
||||
```bash
|
||||
pnpm --filter @fusion-plugin-examples/hermes-runtime test
|
||||
pnpm --filter @fusion-plugin-examples/hermes-runtime test # 41 tests
|
||||
pnpm --filter @fusion-plugin-examples/hermes-runtime build
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user