dsh-edit-panel
Live writing of text files for DeepSeek Harness (DSH): the AI writes a text or Markdown file section by section into an editor in the right sidebar, and you can type in the same file at the same time.
Maintenance: best-effort. Issues may go unanswered; forks are welcome.
What it adds
- Five tools for the model, in every conversation:
edit_begin(path, outline, title?)creates the file with its headings and opens the panel;edit_write_section(section, content)writes one section, saved to disk at once;edit_status()says what is written, what you changed, and what to do next;edit_finish()ends the draft;edit_open(path)shows an existing file in the panel without changing it.
- The panel (a right-sidebar tab, Live writing): each section in a small word-processor editor (bold, italic, headings, lists, quotes, links, undo; read and written as Markdown). What you type is saved after a short pause, and the AI cannot overwrite a section while you are typing in it.
- Proposals instead of overwrites: when the AI rewrites a section that already has text, the file does not change; the panel shows its proposal word by word (added in green, removed struck in red), and you keep or refuse each change, or all of them.
- Existing files are safe: an existing file is drafted in
<file>.draftand replaces the original only when you press Finish (the original is copied to the backup folder first); Cancel discards the draft. A file opened withedit_openis edited in place, after a backup copy. - Ask the AI about a passage: select text, then the ✦ Ask the AI pill (or Ctrl+K) puts the passage, with its section, in the message box, with quick actions (shorten, rephrase, fix, translate).
- Documents of the conversation: a drawer above the message box lists the files opened in this
conversation; a click reopens one. A click on a text file link
[name](/path/file.md)in the conversation opens it in the panel. - Your instructions per section and your decisions are given back to the model as runtime context, so they survive compaction.
Files: .md, .markdown, .txt, .text, .tex, .org, .rst, .qmd, .rmd, inside your home
folder and not in a hidden folder. In Markdown files, sections are the ## headings.
The interface is in English, and in French when DSH's language is French (tables en and fr at
the top of client.js).
Install
dsh plugin --profile web add github:MathieuPortmann/dsh-edit-panel
Restart the profile afterwards. Requires Node ^22.19.0 || >=24 and DSH >=0.2.0-rc.2 <0.3.0 (see
Compatibility). Once the package is on npm, dsh plugin --profile web add dsh-edit-panel works too.
Configuration
Options of the edit-panel row:
| Option | Default | Meaning |
|---|---|---|
dataDir |
<DSH_HOME>/edit-panel |
state of the drafts (one JSON per conversation) and the document list |
backupDir |
<DSH_HOME>/backups/edit-panel |
copies of files before they are replaced or opened |
announce |
true |
one line in every conversation telling the model that text files are written through the panel; set false to use the tools only when asked |
How it works
lib/draft.jsholds the drafts: it renders the file from its sections, reads it back to see what you changed (a fingerprint per section), keeps proposals waiting, locks a section for 30 s while you type, and replaces or restores files with backups.lib/docs.jskeeps the document list. Both are pure Node.js and covered bytests/.index.js(host side) registers the tools, sends the draft state as runtime context, and serves the panel through an RPC channel at/edit-api/<method>, behind DSH's own connection check.client.js(page side) draws the tab, the drawer and the editors. The editor itself (web/editor.js) is a bundle of ProseMirror and markdown-it built fromweb-src/editor.js; the page receives it from the host and loads it once.
Compatibility
| Component | Supported |
|---|---|
| Node.js | ^22.19.0 || >=24.0.0 (engines.node) |
| DSH | >=0.2.0-rc.2 <0.3.0; declared as optional peerDependencies on @deepseek-ai/dsh-tools and @deepseek-ai/schemastery, the only DSH packages the host side imports |
| Platform | Linux (tested); pure JavaScript, no native addon |
| Page | DSH's web UI with the right sidebar; the drawer finds the message box by its editable area and may need an update when the page changes |
Tested with DSH 0.2.0-rc.2 on Node 22.23 (see Verification).
Permissions and external services
Everything the plugin can touch, and what happens when it fails:
| Capability | Where | Used for | If it fails |
|---|---|---|---|
| Files | lib/draft.js, lib/docs.js |
writes the text files the model drafts and the files you open in the panel, only inside your home folder, never in hidden folders, only the text extensions above; <file>.draft working copies; backup copies in backupDir; state in dataDir |
the tool or the panel shows the error; nothing is written |
| Network | none | nothing leaves the computer | n/a |
| Commands | none | no child process, no shell | n/a |
| Tools for the model | index.js |
edit_open, edit_begin, edit_write_section, edit_status, edit_finish (see above) |
an error text is returned to the model |
| HTTP route | index.js (ctx.webServer.register) |
POST /edit-api/<method> for the panel, behind ctx.connection.admit() (DSH's Host/Origin fence and token); JSON bodies only, limited to 1 MiB |
non-admitted requests get 401/403; other errors are returned in the RPC envelope |
| Dynamic module loading | index.js (importFromDsh) |
loads @deepseek-ai/dsh-tools and @deepseek-ai/schemastery from the DSH installation that runs the plugin. Nothing is downloaded |
the plugin fails to load |
| Code evaluation in the page | client.js (loadLib) |
the editor bundle, read by the host from this package's web/editor.js, is turned into code with new Function once (or, under a strict content policy, loaded as a blob script). No other text is ever evaluated, and nothing comes from the network |
the panel shows "Editor unavailable" and the sections as plain text |
| Interface | client.js |
a right-sidebar tab, a drawer above the message box, a click handler on text file links of the conversation, the font choice saved in the browser's localStorage; registers a French dictionary and language entry with DSH's locale service |
no panel |
Verification
Checked on a disposable profile (DSH_HOME pointing at a temporary folder, so the real profile is
never touched):
npm pack
dsh plugin --profile t add file:$PWD/dsh-edit-panel-0.1.0.tgz # install
dsh t --port 3095 --no-open # start: plugin loads, no error
dsh plugin --profile t remove dsh-edit-panel # uninstall
npm test runs 9 standalone tests (drafts: new and existing files, the user's edits, locks,
proposals kept, merged or refused, open in place, cancel, duplicate headings, path rules; the
document list) with no DSH installation needed.
web/editor.js is reproducible: cd web-src && npm ci && npm run build rebuilds it byte for byte
with the versions pinned in web-src/package-lock.json (esbuild 0.28.2). The bundled libraries and
their licenses are listed in THIRD_PARTY_NOTICES.md.
Develop
npm test
cd web-src && npm ci && npm run build # after changing web-src/editor.js
License
MIT for this plugin. The bundled libraries keep their own licenses (MIT, and BSD-2-Clause for
entities), see THIRD_PARTY_NOTICES.md.
No comments yet. Be the first to write one.