DeepSeek Harness Plugin Hub

Publish and manage complete Harness Profiles. Discover Plugins for your next setup.

Explore

PluginsPresetsDocsNews

Community

Publish a pluginContactReport an issue

Resources

Plugin Hub on GitHubDeepSeek HarnessSystem statusPrivacy notice
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

Independent and unofficial. Not affiliated with, authorized by, or endorsed by DeepSeek.

Hillstone Cli Ops — DSH Plugin for DeepSeek Harness
← Plugins
H

dsh-hillstone-cli-ops

Hillstone Cli Ops

Device operations and maintenance terminal plugin: a “Device Operations and Maintenance” tab in the right sidebar for managing Hillstone devices (create, read, update, delete, and SSH terminal).

The plugin will be installed here. Keep web if you are unsure.

npx -y @deepseek-ai/dsh plugin --profile web add github:jazhu/dsh-hillstone-cli-ops#2048ee2b0719cc9e88439664a4dbdd4a3c679370
READMECompatibilityVersions

Compatibility and provenance

Hillstone Cli Ops is published as dsh-hillstone-cli-ops and currently resolves to version 1.0.0. The Hub verifies its manifest and preserves the exact installation source for reproducible installs.

DSH compatibility
*
Runtime surfaces
web
Release source
github
Registry updated
10/5/2026

Versions

1.0.0
stable
10/5/2026

Related plugins

Loading related plugins…

Latest
1.0.0
DSH
*
HMR
Process restart
Tree shaking
Safe tree shaking not declared
Unpacked size
Unavailable
Files
Unavailable
Surface
web
License
MIT
Source
github
GitHub
★ 0
Weekly downloads
0
Last push
10/11/2026
View source ↗
README badge

Click the badge to copy Markdown for your README.

Do you maintain this Plugin?Claim benefit · Priority security scan

Verify the GitHub repository declared in package.json to manage this listing. After you claim it, Hub will prioritize a security scan of the current version and publish the result when it passes.

Claim this Plugin →
Report an issue
DeepSeek Harness Plugin Hub
ProfilesPluginsCategoriesNewsDocsSign inManage Profiles
ProfilesPluginsCategoriesNewsDocsSign in

Related plugins

More verified plugins in developer-tools.

Ssh@linxin666/dsh-sshRemote SSH operations for the dsh web GUI: host config store (~/.dsh/dsh-ssh.json, import from ~/.ssh/config), a persistent ssh2 connection pool with jump-host support, exec / PTY web terminal / SFTP transfer / local port-forward tunnels / cluster executiUpdate@linxin666/dsh-updateSelf-update plugin for the dsh web GUI: probes npm for newer family releases and runs the owning profile's pnpm update in place, from a sidebar trigger beside the settings seat with a release-notes panelTui@deepseek-harness-tui/dsh-tuiInteractive terminal interface for DeepSeek Harness agents, sessions and tools.Cc Safety Netcc-safety-netA coding agent CLI hook - block destructive commands and secret file access

README

dsh-hillstone-cli-ops

A DeepSeek Harness (DSH) plugin that puts Hillstone / StoneOS network devices into the right sidebar: manage them, open a real SSH terminal, read the per-connection audit trail — and give the assistant seven tools so it can do all of that itself.

The plugin is a two-half DSH plugin: a Node host half (SSH, encryption, session logs, the agent tools) and a browser client half (the sidebar tab and an xterm.js terminal). Both are built from one src/ tree.


What you get

A 「设备运维」 tab in the right sidebar with three sub-tabs:

TabWhat it does
设备管理CRUD devices (name / IP / account / password / SSH port / device type / web port / note). 新增, 复制 and 编辑 all run in one centred dialog.
终端One xterm.js terminal per live connection. Input goes to the host, device output streams back over SSE.
日志The per-connection audit trail: who connected to which device, what was typed, which commands were run, when and why the session ended.

Seven agent tools, so the assistant can operate devices without you:

hillstone_list_devices, hillstone_open_terminal, hillstone_send_input, hillstone_get_output, hillstone_close_terminal, hillstone_list_sessions, hillstone_run_and_analyze.

hillstone_run_and_analyze runs a batch of commands and hands the output to the host LLM with a natural-language task ("检查接口状态和 CPU 负载"). By default it reuses a terminal session an operator already has open, so you can watch the agent work in the tab; with no live session it falls back to a one-shot exec channel.


Install

git clone https://github.com/jazhu/dsh-hillstone-cli-ops
cd dsh-hillstone-cli-ops
pnpm install
pnpm run build          # regenerates dist/ (not committed)

Then point DSH at the directory — either as a local bundle in the plugin manager, or by installing the package into your profile:

pnpm pack && <your-dsh-plugin-install-command> ./dsh-hillstone-cli-ops-1.0.0.tgz

Restart the DSH main process afterwards. Disabling and re-enabling a plugin does not rebuild the host fiber in a running process, so new host code (SSH handling, the tools, the log writer) only takes effect on a real restart.

Requirements: Node 22+, a DSH build that exposes the tools and sidebarRightTabs services, and ssh2 / xterm (installed by pnpm install).


Design notes

A few things here were decided from measurement, not from the obvious guess.

The pager is not optional on StoneOS

Measured on a real SG-6000: show cpu detail produces 9172 characters and stops 13 times at --More-- \0, and the device emits zero SGR sequences.

The part that bites is the second one: the pager eats anything typed into it. A command sent while the pager is waiting is silently swallowed — the pager just flushes the rest of the page and returns to the prompt. So a tool that writes a command and then waits for a prompt hangs until it times out, having never run the command.

hillstone_run_and_analyze therefore watches for --More-- and answers it with a space, on the same write chain as any other input, and reports the number of pages it had to advance. hillstone_send_input submits a bare command automatically (see below) so the model does not have to remember the trailing carriage return.

We do not send terminal length 0 on connect. The SG-6000 rejects it with ^-----unrecognized keyword and paginates anyway, so it achieved nothing except putting a bogus device error at the top of every session.

send_input submits, but knows when not to

A model that passes a bare command and waits for output is the overwhelmingly common case, and without the \r the text just sits in the device's line buffer. So hillstone_send_input appends a carriage return — except when the input is obviously not a command line:

databehaviour
multi-character, no control characters, not blankappends \r
a single key (" " to page, "q") or anything containing control characterssent verbatim
anything, with an explicit submit: true / falsethe explicit value wins

submit also accepts "true" / "false", because a JSON-ish caller can hand over a string and submit: "false" must not be read as truthy.

The output cursor counts bytes

hillstone_get_output is the read half of hillstone_send_input: the agent polls with a since cursor instead of re-reading everything or sleeping blindly. That cursor is a byte offset, not a character offset. The transcript is capped and re-sliced when it overflows, so a string index would shift underneath a polling agent; a cursor landing inside a multi-byte character is walked back to the lead byte rather than producing a replacement glyph. The since < dropped test is what decides a cursor is too old — comparing against a moving total instead makes every cursor look stale the moment any new output arrives.

A ToolDefinition that breaks the contract does not throw

DSH's ToolDefinition requires output.schema and output.render(args, value) and expects parameters to be a flat property table (field → { type, description, required? }), not a JSON Schema object. Violating this does not raise at registration time — the tool simply never appears in Tool.listTools. The plugin looks healthy, the agent reports that it cannot operate devices, and nothing in a log says why.

So both the regression suite and the bundle gate assert the contract itself, not just the tool names: every tool must have a description, a flat parameter table, an execute, and an output.render that turns a real result into readable text blocks and renders a failure as readable text instead of throwing.

Passwords never reach the browser

A device password is encrypted at rest with a per-profile key and decrypted only inside the host process. The copy button is server-side: the host copies the ciphertext, so duplicating a device never moves a plaintext password into the page, and editing a copy with an empty password field keeps the inherited one.

A local API on a fixed port

The browser half cannot call the host's services directly, so the host opens a loopback HTTP server (127.0.0.1:18783, prefix /ops-api). It is guarded by a per-session bearer token that the page fetches from GET /ops-api/_session, which only answers a loopback request with no or a local Origin — otherwise any web page the user visits while the harness runs could reach the API. The page carries the token in X-Ops-Token.

One log file per connection, per day

Every connection writes <dataDir>/oplog/<YYYY-MM-DD>/<connId>.jsonl: a header line, one line per input / command / event entry, and a final line recording the end reason. No end line means the session is still active — a log that only records successes is not an audit trail, so the log is opened before the SSH handshake and a refused port or a bad password is recorded too. Device output is deliberately not logged: a show tech-support dump would inflate the log by three orders of magnitude, and the device keeps its own logs. Days are keyed in local time, and 30 days are kept.


Development

node node_modules/typescript/bin/tsc --noEmit   # typecheck (build.mjs does NOT gate on this)
node build.mjs                                  # esbuild dual bundle
node test/terminal-regression.mjs               # offline end-to-end
node test/bundle-gate.mjs                       # greps the built product

Run them in that order. bundle-gate asserts against dist/, so a failed build would otherwise leave it passing on the previous artefacts — it compares the mtimes of dist/* against src/** + build.mjs and reports MISS … (STALE).

test/terminal-regression.mjs boots the real dist/index.mjs against a self-hosted fake StoneOS over real ssh2, including a fake pager that stops at --More-- and eats whatever is typed there — the same failure mode as the real box. It also boots a second host instance with a recording tool registry, because the tool surface is what an agent actually uses, and the browser's HTTP API is not.

License

MIT — see LICENSE.