deepseek-harness
deepseek-ai
DeepSeek Harness: Everything is a Plugin.
PROJECT TOPICS
PROJECT README
AI-managed SSH connections with a live multi-tab terminal panel for DeepSeek Harness.
SSH terminal panel + AI connection manager for DeepSeek Harness (DSH).
The AI agent can autonomously create, address, and tear down SSH connections
right from the conversation (ssh_connect / ssh_exec / ssh_list /
ssh_status / ssh_disconnect / ssh_exec_read / ssh_exec_kill /
ssh_delete), while a XShell/Uniterm-style multi-tab terminal panel in the
Web GUI shows every command — model and human — in real time on the same
screen.
ssh_exec on a saved
name automatically re-establishes the connection from its saved settings.ssh_connect) or from the Settings
page, is managed by the AI agent. It appears in ssh_list and is
immediately addressable by ssh_exec / ssh_status / ssh_disconnect /
ssh_delete — no transfer step exists or is needed.ssh_disconnect, Settings "Disconnect" button). A
"reconnected — the shell state was reset" notice is shown after an
automatic reconnect.ssh_exec against a connection whose shared
terminal shell is still active waits until the shell falls quiet (no
output/input for shellQuietWaitMs, default 2 s) or returns a readable
"busy" result instead of interleaving output.ssh_disconnect keeps the tab open showing "disconnected" (one
click to reconnect); a model connect that has no tab re-opens one
automatically. Connecting a saved connection (tab bar "+", the
Settings-page Connect button) never rejects an already-open connection:
when a tab for that connection is already open, the call opens a FRESH
independent session in a new tab — even when the same connection is already
connected in another tab — and only connects the primary session (the one
the model tools address) when no tab is open yet.dsh-ssh:terminal — visible in its + menu, with a live
connection-count badge), and the AI-connect auto-open lands there (opening
and expanding the sidebar). Both surfaces share the one host-managed state
stream, so switching never forks the terminals. panelSurface (see
settings below) chooses the surface: auto (default — sidebar when
installed), sidebar (prefer sidebar), native (always the built-in
column). Without dsh-better-sidebar everything falls back to the native
column automatically. Each connection owns one real interactive shell
(PTY): the
login banner (motd / Last login), the remote prompt user@host:path$,
input echo and cd updates all come from the remote shell, exactly like a
native SSH client. There is no input box and no copy control — click
the terminal and type; keystrokes go straight into the remote shell
(arrows, Tab, Ctrl-C, paste, IME supported). A blinking block cursor shows
while the terminal is focused. AI-run commands appear in the same
scrollback with source tags. Multi-tab, ANSI colors, scrollback. The view
stays pinned to the newest output as it arrives — even large output bursts
follow to the bottom; scrolling up to read history is respected (no forced
jump), but whenever the AI starts operating the connection the terminal
slides back to the bottom so the AI's live output is visible.dsh-ssh settings namespace (heartbeat, reconnect
policy, timeouts, output caps, records path) can be overridden through the
DSH settings system / profile patch.pnpm-lock.yaml)web profilescripts/test-acceptance.mjs)# from npm (recommended)
dsh plugin --profile web add @jmcc-guo/dsh-ssh
# or directly from GitHub
dsh plugin --profile web add "github:jmcc-guo/dsh-ssh#v0.5.0"
# or from a local checkout
dsh plugin --profile web add <path-to-this-repo>
The bundle patch (cordis.patch.yml) mounts the dsh-ssh row. Override
config in the profile patch with the same row id:
- id: dsh-ssh
config:
heartbeatIntervalMs: 20000
reconnectMaxAttempts: 8
outputLimitBytes: 2097152
Restart the profile process afterwards (plugin-set changes and the client bundle graph are composed at boot).
ssh2 and its full dependency closure are shipped bundled inside the
package (bundleDependencies), so installing @jmcc-guo/dsh-ssh never runs
dependency build scripts: no allowBuilds edits, no
ERR_PNPM_IGNORED_BUILDS. ssh2 runs on its pure-JS implementation, which is
fully functional (verified against a real SSH server); the optional native
crypto binding is intentionally not compiled.
pnpm peers check may report "missing peer" for the @deepseek-ai/* packages
even though DSH provides them: with the hoisted profile layout, external
plugins resolve host packages at runtime from the shared profiles/node_modules
tree, which pnpm's static peer check does not cross. The warnings are benign —
the plugin loads fine (verified at runtime).
dsh-ssh)| Key | Default | Meaning |
|---|---|---|
heartbeatIntervalMs |
30000 | ssh2 keep-alive interval |
keepaliveCountMax |
3 | keep-alive failures before the connection is considered dead |
connectTimeoutMs |
15000 | SSH handshake / TCP connect timeout |
reconnectBaseDelayMs |
2000 | first auto-reconnect delay (doubles per attempt) |
reconnectMaxDelayMs |
60000 | backoff cap |
reconnectMaxAttempts |
5 | max automatic reconnect attempts |
execTimeoutMs |
120000 | default ssh_exec completion wait |
busyWaitTimeoutMs |
20000 | default mutex wait when the connection is busy |
reconnectWaitTimeoutMs |
30000 | default wait while reconnecting |
shellQuietWaitMs |
2000 | shared-shell silence required before AI may run |
outputLimitBytes |
1048576 | per-connection terminal buffer cap |
execOutputMaxBytes |
200000 | cap on output returned to the model per command |
recordsPath |
$DSH_HOME/storages/dsh-ssh/connections.json |
records file override |
panelSurface |
auto |
where the Web panel lives: auto = dsh-better-sidebar when installed, else the native column; sidebar = prefer dsh-better-sidebar (falls back to native when absent); native = always the built-in details column. Applied live to open panels |
ssh_connect — create a new connection (host/port/user + auth by
credential reference or key file path) or re-establish an existing one.ssh_exec — run a command on a saved connection by name; auto-reconnects
when offline, waits through reconnect/busy states (with timeouts), returns
output + exit code; long commands return an execId for
ssh_exec_read / ssh_exec_kill.ssh_exec_read — incremental output of a running (or finished) command.ssh_exec_kill — terminate a running command (SIGINT through the pty).ssh_list — all saved connections with live status (every connection is
AI-managed).ssh_status — detailed status of one saved connection.ssh_disconnect — explicit disconnect (no auto-reconnect; optional
delete); the panel tab stays open showing "disconnected".ssh_delete — delete a saved connection record (disconnects first).Secret rule for the model: never pass passwords or private keys inline in
tool arguments (they are recorded verbatim in the session log and rejected).
Use auth.passwordRef / auth.privateKeyRef (a stored credential or
environment variable) or auth.privateKeyPath (a key file on the host).
New secrets can be stored through the panel's connection form, which routes
them into the DSH credential store.
/ssh/ws) applies the harness browser-trust fence:
loopback/trusted-host Host, same-origin Origin, cross-site fetch-metadata
rejection.lib/index.js plugin entry: config schema, manager + tools + panel channel wiring
lib/manager.js SshManager — connection lifecycle, keep-alive/reconnect, mutex, PTY shells
lib/tools.js model tools (ssh_connect / ssh_exec / ssh_exec_read / ssh_exec_kill / ...)
lib/ws.js panel WebSocket channel (/ssh/ws) with the browser-trust fence
lib/store.js persisted connection records
lib/client.js Web GUI client: multi-tab terminal panel + settings UI
cordis.patch.yml bundle patch that mounts the dsh-ssh row
scripts/ test suites (see below)
scripts/ contains the acceptance suite and helpers (requires a reachable
SSH server; the included tests target a WSL OpenSSH instance):
node scripts/test-acceptance.mjs # 64-check manager-level acceptance suite
node scripts/smoke.mjs # quick smoke test
node scripts/test-panel-ws.mjs # panel WebSocket channel drive (test web instance on :3081)
node scripts/test-rename.mjs # focused rename test (no SSH server needed)
node scripts/test-connect-tabs.mjs # focused connect/tab-semantics test (no SSH server needed)
node scripts/test-panel-channel.mjs # focused panel WS channel test (no SSH server, no DSH instance needed)
node scripts/test-client-surface.mjs # dual-surface (native column / dsh-better-sidebar) logic — no server needed
Issues and pull requests are welcome. Keep the model-facing surface (tool names, parameter semantics, result shapes) backward compatible, and make sure secrets never end up in logs, records or tool results.
MIT
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: 无有效分类标签。