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>.draft and replaces the original
only when you press Finish (the original is copied to the backup folder first); Cancel
discards the draft. A file opened with edit_open is 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.js holds 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.js keeps the document
list. Both are pure Node.js and covered by tests/.
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 from web-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 ; registers a French dictionary and language entry with DSH's locale service |
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.