[中文](README.md) · **English** # hermeslike-MoA **Hermes-style Mixture-of-Agents (MoA) request aggregator — runs every routed LLM call through a router → parallel reference advisors → aggregator streaming pipeline, with dual-provider failover and a V4P triple-gate cost guard.**
--- `hermeslike-moa` is a DSH plugin (`dsh.bundle`). It registers a dsh-llm `LlmAdapter` (provider route `deepseek-moa`, plus `go-moa` when an OpenCode Go key is configured); every model request routed to those providers runs the MoA pipeline: ``` user request → V4F router (one call, JSON verdict: does the task warrant V4P?) → reference advisors ×N in parallel (V4F; Hermes-style advisor system prompt; tool calls/results folded into plain text; tool results head+tail preview; reference outputs redacted; synthetic user judgement instruction appended) → aggregator (model: explicit user choice first → router → V4P triple gate) → streaming passthrough (standard dsh-llm StreamChunk) ``` ## The three model entries The model picker offers three models: | Model | Meaning | |---|---| | **`deepseek-v4-mix`** (MoA Mix) | **Full MoA pipeline**: router → reference advisors ×N (flash, parallel) → aggregator (pro or flash) → stream. Costs N+2 calls (1 router + N refs + 1 aggregator); aggregator pro is V4P-gated | | **`deepseek-v4-pro`** | **Direct single V4 Pro** (no MoA overhead); **still V4P-gated** (anti-footgun: demotes to flash on empty budget or errors per settings) | | **`deepseek-v4-flash`** | **Direct single V4 Flash** (no MoA, cheapest/fastest; **not gated**) | > Any **unknown model id** (outside the three above) is treated as **flash direct** — it never silently triggers the expensive MoA path. ## Highlights - **`mix` model category**: the model picker now lists **`MoA Mix · 模型混合`** (`deepseek-v4-mix`) — selecting it pins the full MoA pipeline (a "simulate selection" entry); the aggregator model still follows settings/router; `flash`/`pro` remain explicit aggregator choices. - **Hermes-faithful advisory view** (`lib/reference.js`, modeled on Hermes `moa_loop.py`): drops the acting agent's system prompt, renders `tool_calls` as `[called tool: name(args)]`, folds each tool result (head+tail preview, 4000-char budget) into the preceding assistant turn, emits **zero tool-role messages** (strict-provider safe), appends a synthetic user judgement instruction so the view ends on user. - **Redaction**: centralized secret shapes (sk-/Bearer/JWT/private keys/DB URLs) + safe email/phone regexes (delimited, never mangling SHAs/IDs/dates). - **Context trim**: rough token estimate, drop oldest frames, keep user-first invariant, keep trailing synthetic instruction. - **Dual channel**: official (DeepSeek pay-as-you-go) + go (OpenCode Go subscription); **go-preferred whole pipeline, auto-switch to official after 3 consecutive failures**. - **V4P triple gate**: budget multiple (look-ahead pool = F spend×ratio − P spend) + per-window cap + min interval. - **New-contract accounting**: dsh-llm disjoint `TokenUsage` (`inputTokens` = uncached input; cache read/write separate), rolling-window cost. ## Install ```bash # bundle: enters the profile layer stack (restart web) dsh plugin --profile web add github:beimianism/Hermeslike-Mixagent-MoA # or local dev path (use your own) dsh plugin --profile web add /path/to/hermeslike-moa ``` > Public `@deepseek-ai/*` and `cordis` deps are intentionally undeclared (injected by the profile pnpm closure). ## System settings (recommended) The plugin ships its own **web settings page** (Settings → Hermeslike MoA, rendered by its client half — the official Models page disables third-party provider editors). Every field has a ⓘ hover tooltip, and each API-key field shows a live health diagnostic (`keyHealth`): - **Enable / disable** the MoA aggregator. - **API keys (type them right here, robustness-first)**: the form has two write-only password fields — `DeepSeek API key` and `OpenCode Go API key`. Type a key directly in the settings UI and it takes effect (stored locally in `settings.yaml`, never echoed back, stripped on the wire); leave blank to fall back to the env refs (`apiKeyEnv`/`goApiKeyEnv`, resolved via credentials/environment). If both are empty: missing official key → requests fail 401; missing Go key → Go channel just disabled. Health shows "✓ valid / ✗ malformed reason" live. - **Model mix**: - `reference advisor count` (1–8, default 3) - `reference temperatures` (in order) - `aggregator model`: auto (router decides) / flash / pro (V4P-gated) — the Hermes aggregator-slot equivalent - `prefer Go channel`: OpenCode Go subscription first; auto-switch to official after 3 consecutive failures - **V4P triple gate**: budget multiple / per-window cap / min interval / degrade-to-flash on gate block - **Privacy**: advisor-output redaction level - API keys are configured in the credentials seam (referencing env var names like `DEEPSEEK_API_KEY`, never literal secrets) The settings document holds the `hermeslike-moa:` section; the plugin row `config:` in `cordis.patch.yml` acts as the composition base (user overrides win). ## Configuration (composition base) These fields default from the plugin row `config:` in `cordis.patch.yml`; user settings override them: | Key | Default | Meaning | |---|---|---| | `apiKeyEnv` / `DEEPSEEK_API_KEY` | `DEEPSEEK_API_KEY` | DeepSeek official key env ref | | `goApiKeyEnv` / `OPENCODE_API_KEY` | `OPENCODE_API_KEY` | OpenCode Go key env ref (empty disables Go) | | `endpoint` | `https://api.deepseek.com/chat/completions` | official endpoint | | `goEndpoint` | `https://opencode.ai/api/v1/chat/completions` | Go endpoint | | `enabled` | `true` | master switch | | `ratio` | `0.5` | V4P look-ahead pool ratio (F×ratio−P) | | `windowMs` | `3600000` | ledger rolling window | | `refCount` | `3` | reference advisor count | | `refTemps` | `[0.5,0.8,1.1]` | per-reference temperature | | `aggregatorModel` | `auto` | aggregator model (auto/flash/pro) | | `preferGo` | `true` | prefer Go channel | | `fallbackToFlash` | `true` | degrade V4F when gate blocks V4P | | `minBudgetMultiple` | `3` | gate: budget multiple | | `maxProPerWindow` | `3` | gate: V4P per-window cap | | `minProIntervalMs` | `900000` | gate: min interval | Example: ```yaml - insert: - id: hermeslike-moa name: 'hermeslike-moa' config: apiKeyEnv: DEEPSEEK_API_KEY goApiKeyEnv: OPENCODE_API_KEY ratio: 0.5 refCount: 3 ``` ## Layout ``` hermeslike-moa/ ├── package.json ├── cordis.patch.yml ├── index.js # apply(): config parse + registerAdapter ├── lib/ │ ├── adapter.js # MoaAdapter extends LlmAdapter (dual + failover) │ ├── pipeline.js # MoaPipeline: route → refs×N → aggregate → stream │ ├── router.js # V4F router + keyword fallback │ ├── reference.js # Hermes advisory view: render/truncate/redact/trim │ ├── wire.js # HTTP one-shot/stream + TokenUsage normalization │ ├── ledger.js # spend ledger + V4P triple gate │ ├── prices.js # price table │ ├── prompts.js # three system prompts │ └── settings.js # settings schema (web settings form) + resolution └── README / README.en ``` ## License [MIT](./LICENSE)