OpenViking
volcengine
Self-evolving Context Database for AI Agents. Unify Agent Memory, Knowledge RAG and Skills.
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:TaxolYang0000/dsh-kanban-watcher
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
⚠️ AI-GENERATED CODE NOTICE: This plugin was generated by DeepSeek AI and has NOT been human-reviewed. Use at your own risk; review security-critical paths (permission presets, output whitelist, file writes) before deployment. 中文版 README 见 README.zh-CN.md
The board-execution-side plugin of the DSH ↔ Hermes dual-agent collaboration pipeline: watches the Hermes kanban task queue, hands tasks to a DSH Agent in a Web GUI session, and writes results back to the board plus a done file.
This plugin solves how tasks cross systems when two independent agents (DSH + Hermes) run on the same machine:
| Scenario | Description |
|---|---|
| Dual-agent collaboration | You dispatch from the Hermes terminal (/dsh-send); DSH auto-opens a session in the Web GUI, fully visible and replayable |
| Kanban task queue | The queue uses Hermes' built-in kanban (~/.hermes/kanban.db, board dsh) with metadata, atomic claim, state machine, comments, crash recovery |
| Unattended execution | Watcher sessions use a dedicated permission preset (danger-full-access + never); whitelisted outputs write without approval |
| Results visible on both sides | DSH: the session stays in the GUI session list; Hermes: board comments carry the result summary, and the done file triggers external-event injection into the running session |
Not for: single-agent setups (no board needed); parallel multi-task execution (v1 is serial); cross-machine deployments (assumes DSH and Hermes share one machine and user).
Hermes terminal DSH web host Hermes side
───────────── ────────────── ─────────
/dsh-send "task" ──create──▶ board (kanban.db, board=dsh)
(skill) ──trigger──▶ ~/.dsh/kanban-trigger/<id>.trigger
│ fs.watch event-driven wake-up
▼
claim <id> (atomic)
show <id> --json (read metadata)
agents.create (open GUI session)
followup(task) → agent executes
│ withTimeout hard cap (600s)
▼
comment + complete --result ──▶ board write-back (/inbox visible)
writeDoneFile(<id>.done) ──▶ ~/.dsh/kanban-done/<id>.done
→ Hermes idle loop notices, injects into the session
Key design points:
~/.dsh/kanban-trigger/<id>.trigger); the plugin's fs.watch responds in milliseconds,
with a 30s low-frequency fallback poll in case events are lost.status === "ready" tasks are claimed;
kanban guarantees a single claim; a running set prevents same-tick duplicates.running tasks and reclaims them back to
ready (previous execution interrupted); it also holds a singleton lock (PID + liveness check).model_override/provider_override) is mapped to
a DSH provider/model via modelMap; unmapped specs fall back to __fallback__; the actual
model used is written back into the result.session-hermes-<id>-<uuid> session attached
to the workspace, so it appears in the GUI sidebar in real time and survives refresh.This plugin is a Cordis plugin package, not a dsh.bundle patch layer: once added as a
dependency in the web profile, the loader imports it directly.
cd ~/.dsh/profiles/web
pnpm add file:<your-clone-path>/dsh-side/plugins/dsh-kanban-watcher
Expected output
dsh: warning: dsh-kanban-watcher declares no dsh.bundle— this is NORMAL. The plugin only needs to be imported by the loader, not become a patch layer.
~/.dsh/profiles/web/cordis.patch.yml)- insert:
- id: kanban-watcher
name: 'dsh-kanban-watcher'
config:
board: 'dsh'
assignee: 'dsh'
triggerDir: '~/.dsh/kanban-trigger'
pollIntervalMs: 30000
allowedOutputDirs:
- '<your-DSH-workspace>'
modelMap:
'deepseek-v4-flash': { provider: 'deepseek-official', model: 'deepseek-v4-flash' }
'__fallback__': { provider: 'deepseek-official', model: 'deepseek-v4-flash' }
pkill -f "dsh web --port 3080" # kill cleanly first (rule), then start
nohup <dsh-bin> web --port 3080 > /tmp/dsh-web.log 2>&1 &
Verify: tail -f /tmp/dsh-web.log shows kanban-watcher started.
All config lives in the plugin line's config in cordis.patch.yml; every key has a default:
| Key | Default | Description |
|---|---|---|
hermesBin |
~/.local/bin/hermes |
Path to the hermes CLI (kanban subcommand entry) |
board |
dsh |
Board name; must match the board used by Hermes /dsh-send |
assignee |
dsh |
Claim owner; only tasks assigned to dsh are processed |
triggerDir |
~/.dsh/kanban-trigger |
Trigger file dir: Hermes writes <id>.trigger here; fs.watch wakes on events |
doneDir |
~/.dsh/kanban-done |
Done file dir: written on completion; Hermes' external-event injection watches here by default (HERMES_DONE_WATCH_DIR can override) |
pollIntervalMs |
30000 |
Fallback poll interval (fs.watch events may coalesce/lost) |
taskTimeoutMs |
600000 |
Per-task hard timeout (10 min); releases the agent session and reports the error, so an unanswered approval can't stall the pipeline |
permissionPreset |
hermes-trusted |
Watcher-session permission preset (danger-full-access + never): whitelisted outputs write without approval, upgrade requests fail fast |
cwd |
$DSH_WORKSPACE |
Default working dir when a task doesn't specify one |
allowedOutputDirs |
[$DSH_WORKSPACE, $DESKTOP] |
Output whitelist (mirrors the Hermes dispatch-side whitelist; enforcement stays on the Hermes side) |
modelMap |
flash→flash / __fallback__ |
Hermes model spec → DSH provider/model translation table; __fallback__ is the catch-all |
resumeTokenWarning |
500000 |
Token guard threshold: warns to create a new session when a resumed session is estimated above this |
⚠️ Security trade-off (must read):
hermes-trusted= danger-full-access + never, so a watcher session has full-disk write permission. The security boundary relies on the Hermes dispatch-side whitelist (source filtering), not a sandbox. Protect against untrusted task sources separately.
Hermes uses the /dsh-send skill (see hermes-side/dsh-send-skill/SKILL.md):
/dsh-send --model deepseek-v4-flash write this week's progress report
/dsh-send does: create a kanban task (hermes kanban --board dsh create ... --assignee dsh --created-by hermes --json) → write a trigger file ~/.dsh/kanban-trigger/<id>.trigger → return the task id.
fs.watch receives a trigger-file event (or the 30s fallback poll), drainOnce starts;list --json --assignee dsh finds ready tasks → claim <id> (atomic) → show <id> --json reads metadata;model_override/provider_override are translated through modelMap, agents.create opens a GUI
session (standard preset + hermes-trusted permission preset), followup injects the task, withTimeout caps it;comment + complete --result write back to the board, then writeDoneFile writes <id>.done.When the task body carries [会话继承:<keyword>] (or an explicit [会话继承:<session-id>]), the
watcher matches a historical session in the same workspace and continues its context instead of
starting a fresh conversation:
agents.get + followup, scheme A)agents.resume restores the event stream, then continue/dsh-send --resume keep-discussing-X analyze the conclusion from before
# The task body will carry [会话继承:keep-discussing-X]; the watcher matches a historical
# session whose title contains the keyword
继承会话: <session-id>resumeTokenWarning (default 500k) it warns to create a new session--workspace are only loggedhermes kanban --board dsh show <id> # board detail + comments
/inbox # task queue (read-only)
DSH side: a "📥 from Hermes: ..." session appears in the Web GUI session list; open it to replay the full execution. The done file also makes the Hermes session auto-pop an "External Notification".
dsh-kanban-watcher/
├── lib/
│ └── index.js # plugin body (single file, ~590 lines)
├── package.json # package manifest (Cordis plugin, not a bundle patch)
└── README.md # this file (EN) / README.zh-CN.md (中文)
pnpm add file: into
~/.dsh/profiles/web/node_modules/. After editing source, restart dsh web for changes to
take effect (a running node process does not hot-reload plugin code).list --json returns a plain array, show returns .task,
claim has no --assignee, comment takes positional args, terminal state is done, etc.)
are verified and documented in the header comment of lib/index.js.MIT
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: multi-agent。