voyager
Nagi-ovo
Enhancement suite for Gemini, AI Studio, Claude & ChatGPT — plus a prompt manager for any websites, DeepSeek Harness included. / 面向 Gemini、AI Studio、Claude 与 ChatGPT 的增强套件;其中的提示词管理器可用于任意网站,如 DeepSeek Harness。
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:dsh-pulse/dsh-hermes-bridge
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
DSH ↔ WeChat bridge plugin: inbound dispatch (WeChat → DSH agent) + outbound push (DSH → WeChat), powered by the Hermes gateway as the WeChat transport. Zero-LLM outbound push via hermes send, and a persistent per-cwd session pool that reuses DSH agent sessions (15–20× cheaper than one-shot headless invocations).
Scope: this plugin is a task-queue execution endpoint for DSH — it does not implement the WeChat protocol itself. The WeChat side (both the inbound trigger and the transport) comes from a self-deployed Hermes Agent gateway plus your own inbound script; without those, the WeChat half of the chain will not work.
微信 ↔ DSH 双向桥插件:入站调度(微信消息 → DSH agent 执行)+ 出站推送(任务进度/结果 → 微信)。出站走 hermes send 零 LLM 消耗;按工作目录复用常驻会话,比一次性 headless 调用省 15–20× token。
⚠️ Read this first — environment assumptions. This plugin was developed against one specific environment (see Environment assumptions). DSH and Hermes deployments vary wildly between users; this plugin cannot work out-of-the-box everywhere. Please review the assumptions and adapt the configuration to your setup before expecting it to run.
⚠️ 先读环境假设。 本插件基于特定开发环境编写(见「环境假设」章节)。DSH 与 Hermes 的部署方式千奇百怪,本插件无法开箱即用于所有环境,请先核对假设并适配你的配置。
The one-way manual chain "WeChat → Hermes skill → dsh --profile headless" works but burns tokens on cold starts, loses session context between messages, and cannot notify you when a long task finishes. This plugin productizes the chain as a first-class DSH plugin:
ctx.agents.create/resume + followup), so follow-up messages continue the same conversation.接单 → 开跑 → 完成/失败 to WeChat with structured changes / verification / leftovers.hermes send (iLink REST), no model call, no gateway dependency for bot-token platforms.ctx.jobs (falls back gracefully when the job controller is absent).WeChat ──▶ Hermes gateway ──▶ dsh-run.sh (bridge-first) ──▶ POST 127.0.0.1:8643/v1/tasks
│
▼
persistent session pool (per cwd)
│
DSH agent (full toolset, followup + whenIdle)
│
WeChat ◀── hermes send ──◀── structured result pushback ──◀──┘
Inbound: Hermes (or any HTTP client) POSTs a task to the plugin's loopback endpoint. The plugin dispatches to the per-cwd resident agent session and pushes progress back via hermes send. If the bridge is down, the shell script falls back to one-shot dsh --profile headless.
The task queue is persisted to disk (~/.dsh/hermes-bridge/tasks.jsonl, JSONL append per state change). On startup the plugin reloads it and:
queued tasks are resumed and run;running tasks (interrupted by a restart) are re-queued with their original sessionId, so the agent session is resumed and work continues where it left off — no cold restart, no lost work;maxRuns times (default 2) is marked failed instead of looping forever;Because the dsh server itself runs under systemd with Restart=always, this closes the loop: submit tasks in the evening (e.g. via WeChat), the server can restart overnight for any reason, and the queue picks right back up — results are pushed to WeChat as each task finishes.
Developed and verified on one specific machine (see the deployment notes in DEVELOPMENT.md). Your environment will differ; check each item:
| Assumption | Value used here | What to adapt on your side |
|---|---|---|
| DSH version | 0.1.0-rc.7 (Node ≥ 22) |
ctx.agents / ctx.agentPresets / session APIs are rc-stage snapshots — a DSH upgrade may break them. Pin the rc range you run, or adjust code. |
| DSH profile | web profile (persistent host; dsh web keeps the plugin resident) |
A headless-only deployment must host the plugin some other way (its HTTP loopback must stay alive). |
| DSH model config | provider: tokenrhythm / model: deepseek-v4-flash-0731 (from your ~/.dsh/settings.yaml agent-default-model) |
Point provider/model at your default model. {{model}} is resolved from agentOptions.model — if the persona template says {{model}} has no value, you are missing model. |
| Hermes install | venv at ~/.hermes/hermes-agent/venv/bin/hermes, gateway service hermes-gateway.service (user systemd) |
hermesBin config must point at your hermes CLI; the gateway service name/port may differ. |
| WeChat channel | iLink personal-bot channel (ilinkai.weixin.qq.com) reached by Hermes |
Your channel may be Telegram/Discord/Slack/etc. The outbound path only needs hermes send --to <platform>:<target> — switch pushTarget accordingly. The inbound trigger (Hermes skill / hook) is channel-specific. |
hermes send targets |
verified with hermes send --list |
Run hermes send --list yourself; chat IDs are environment-specific. |
| HTTP loopback | 127.0.0.1:8643 |
Change port if it collides; the host is hardcoded to loopback (security). |
| Session persistence | ~/.dsh/sessions (per-user) |
If your DSH_HOME differs, session resume paths change accordingly. |
Known limits (not bugs):
sendmessage (ret=-2 → 30s cooldown, handled by Hermes). Bursts of pushes can be dropped/serialized. Keep push volume low (the plugin pushes once per task state, which is fine).dsh web has no authentication by design. Run it loopback-only; do not expose it.DEVELOPMENT.md for what to re-verify).From npm (published as @dsh-pulse/dsh-hermes-bridge):
dsh plugin --profile web add @dsh-pulse/dsh-hermes-bridge
Or from GitHub:
git clone https://github.com/dsh-pulse/dsh-hermes-bridge.git
cd dsh-hermes-bridge && npm install # installs peer deps if missing
# register in your web profile patch
cat >> ~/.dsh/profiles/web/cordis.patch.yml <<'EOF'
- insert:
- id: hermes-bridge
name: 'file:/absolute/path/to/dsh-hermes-bridge/lib/index.js'
config:
port: 8643
authToken: '${env.DSH_BRIDGE_TOKEN}' # REQUIRED — plugin refuses to start without it
pushTarget: 'weixin:<chat_id>' # REQUIRED
hermesBin: '/path/to/hermes' # optional, default 'hermes'
workspaceRoots: ['/path/to/workspace'] # optional cwd whitelist
EOF
Requires @deepseek-ai/cordis (peer dependency) — ships inside DSH. The plugin is designed for the web profile (persistent host); do not install into headless.
| key | type | default | description |
|---|---|---|---|
port |
number | 8643 |
loopback listen port (host is hardcoded 127.0.0.1) |
authToken |
string | — | required; Bearer token checked on every request (constant-time compare) |
pushTarget |
string | — | required; e.g. weixin:<chat_id> — resolved by hermes send |
hermesBin |
string | hermes |
path to the hermes CLI |
retries |
number | 1 |
outbound push retries |
maxTextLen |
number | 1500 |
push text truncation |
preset |
string | standard |
agent preset mounted in session setup |
provider / model |
string | dsh defaults | agent model (align with your agent-default-model) |
workspaceRoots |
string[] | [] |
cwd whitelist (realpath prefix check; empty = unrestricted) |
maxAgents |
number | 3 |
resident session cap (LRU eviction) |
maxQueue |
number | 8 |
task queue cap (429 when full) |
taskTtlMs |
number | 86400000 |
finished task retention (24h) |
queueFile |
string | ~/.dsh/hermes-bridge/tasks.jsonl |
JSONL queue persistence path (~ expands) |
maxRuns |
number | 2 |
max interrupted-and-resumed attempts per task before it's marked failed (guards restart loops) |
recoverOnStart |
boolean | true |
reload and resume unfinished tasks on startup (set false to disable auto-recovery) |
taskTtlMs |
number | 86400000 |
finished task retention (24h) |
Authorization: Bearer <token>)| Endpoint | Description |
|---|---|
POST /v1/tasks |
Inbound task {task, context?, cwd?, sessionId?, title?} → 202 {taskId} |
GET /v1/tasks/:id |
Task status + structured result (changes/verification/leftovers) |
POST /v1/tasks/:id/cancel |
Cancel (queued → failed immediately; running → intent flagged) |
POST /v1/notify |
Pure push {text} (no agent involved) |
GET /v1/health |
Liveness |
Pushback messages (one per state, no spam):
📥 已接单 br-xxxxxxxx
🔧 开跑 br-xxxxxxxx
✅ br-xxxxxxxx(6m12s)
改动:…
验证:…
遗留:…
server.listen(port, '127.0.0.1') — the host is hardcoded, exposing it requires source changes.authToken is mandatory; the plugin refuses to activate without it. Token lives in your profile patch (600 perms) or env, never in code.workspaceRoots is set, paths outside it are rejected (403) both at ingress and inside executeTask.spawn(args[]) — task text never passes through a shell.sk-/sk_tr_/ghp_ token patterns and credentials paths before sending.⚠️ This plugin executes arbitrary DSH agent work with full tool access. Only feed it trusted instructions (keep the WeChat-side discipline in your Hermes skill layer), and never expose the HTTP port beyond loopback.
| Symptom | Cause / fix |
|---|---|
prompt variable "{{model}}" has no value |
agentOptions.model missing — set model (align with your agent-default-model). |
Task reports done but result is empty |
Check the session log for turn/end with reason.kind == "error" — the plugin now flags those as failed; verify model/provider. |
hermes send fails Could not resolve target |
Run hermes send --list, put the exact target in pushTarget. |
EADDRINUSE on the port |
Another instance holds it — change port, or restart the host once after code edits (ESM module cache). |
| WeChat pushes missing/serialized | iLink rate limit (ret=-2, 30s cooldown) — keep push volume low. |
| Hermes still runs headless instead of bridge | The plugin is invoked via dsh-run.sh which internally tries the bridge first (then falls back). If your skill calls something else, point it at dsh-run.sh. See DEVELOPMENT.md §Troubleshooting-Hermes. |
See DEVELOPMENT.md (EN) / DEVELOPMENT.zh-CN.md (中文) — architecture decisions, the problems we hit and how they were solved, test strategy, and what to re-verify after a DSH upgrade.
MIT
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: wechat。