DSH Plugins Marketplace

DSH Plugins

Plugins

/

dsh-prompt-reforge

d

dsh-prompt-reforge

Manifest valid

A DSH composer control that reforges a rough draft into a precise prompt, with one-click revert.

UI (client)hasBundlePatch

dsh-prompt-reforge

A composer control for DeepSeek Harness (DSH) that rewrites the draft you are typing into a sharper, more specific prompt — then lets you put the original back with one click.

It sits in the composer toolbar next to the model selector. No panel, no modal: the rewritten prompt lands in the editor you are already looking at.

[ + ]  [ permission ]            [ ✨ ]  [ ▾ model ]
                                   │
                                   └─ press to reforge, press again to revert

What it does

StepWhat you see
Empty draftThe button stays inert and says "Write something first, then reforge it."
No model selectedInert, with "Pick a model first, then reforge."
Model list failed to loadStill clickable — the click retries the load. "The model list failed to load. Click to retry."
Draft with reference chipsInert — rewriting would drop the chips. "Remove reference chips before reforging."
ReadyThe button arms. Press it.
RewritingSpinner, "Reforging…". Press again to cancel.
RewrittenThe draft is replaced. The same button now reads "Restore the original draft".
You keep typingThe backup is dropped, so a revert can never silently swallow your edit.
You type while it rewritesThe result is discarded rather than overwriting you, and the tooltip says so.
FailureThe draft is left untouched and the tooltip carries the reason.

The rewrite runs against the model and provider already selected for that session, so the result matches the assistant you are about to talk to. Your draft is never sent anywhere else.

Install

From the DSH plugin manager, by package name:

plugin_manager action=install_bundle target=dsh-prompt-reforge

Or point it at the release tarball:

plugin_manager action=install_bundle target=https://github.com/Cloud017/dsh-prompt-reforge/releases/download/v0.2.2/dsh-prompt-reforge-0.2.2.tgz

Or at a local checkout:

plugin_manager action=install_bundle target=<absolute path to this directory>

Or from the GUI: Plugins → Add plugin → Install third-party plugin, paste the package name, the release URL, the repository URL, or a local directory, then restart DSH. The tarball aliases dsh-prompt-reforge.tgz on the same release track the newest version, so a pinned URL can be replaced with .../latest/download/dsh-prompt-reforge.tgz.

Once installed, dsh.profile.bundles gains one entry. The plugin adds exactly one host row; it does not change your model routing, providers, or default model.

How it works

Two halves, both shipped in this package:

  • Host half (lib/index.js) registers one POST /plugins/dsh-prompt-reforge/enhance route on the harness web server. It validates the request, calls ctx.llm.stream() on the session's routed model, and returns the normalized text. It refuses non-loopback requests, caps the body at 256 KiB and the draft at 20 000 characters, and aborts the model call if the browser disconnects or the 60 s budget runs out.
  • Browser half (lib/client.js) registers a control into the conversation.input.right slot. It owns the button state machine, talks to the route with fetch, and writes the result back through the composer's inputActions.insertText, falling back to inputActions.setDraft when the editor API is unavailable or refuses the edit.

The browser bundle declares no dependency beyond React from the module loader; the host half imports nothing from @deepseek-ai/* and reaches the LLM runtime through ctx.get('llm').

Why the state lives outside React

Button state is keyed by session and kept in a module-level map rather than component state. Composer seats are unmounted and remounted freely (switching sessions, resizing, layout changes), and a rewrite in flight must survive that. Aborts are tracked by AbortController identity rather than by a sequence counter, so a late response from a cancelled call can never overwrite the draft.

A rewrite writes the whole draft as a single insertText span, so it lands as one undo step instead of destroying the editor's history. The live draft is read from a ref at the moment the model answers: if it no longer matches what was sent, the result is dropped and the tooltip says why, because silently overwriting someone's typing is worse than losing a rewrite.

Request contract

POST /plugins/dsh-prompt-reforge/enhance

{ "draft": "rough text", "provider": "workbuddy", "model": "deepseek-v4.1-flash", "sessionId": "session-…" }

Success: 200 { "ok": true, "text": "…" }

Failure: { "ok": false, "error": { "code": "…", "message": "…" } }

StatusCodeMeaning
400invalid_bodyBody was not a JSON object
400empty_draftNothing to rewrite
400missing_routeprovider or model missing
403request_not_trustedNon-loopback Host or foreign Origin
405method_not_allowedNot a POST
413body_too_large / draft_too_longOver the size caps
499abortedThe browser went away
502empty_result / upstream codeThe model produced nothing usable
503llm_unavailableNo LLM runtime in this composition
504timeoutExceeded the 60 s budget

Configuration

Nothing to configure. Caps live at the top of lib/index.js and lib/client.js if you want to fork them:

ConstantDefaultWhere
MAX_DRAFT_CHARS20 000both halves must agree
MAX_BODY_BYTES256 KiBhost
MAX_TOKENS2 048host
TIMEOUT_MS60 000host
LENGTH_BUDGET800 charactersprompt (lib/prompts.js)

Development

node --test          # 71 tests, no dependencies beyond Node

The suite covers the prompt pipeline, the route (including loopback rejection driven straight over a socket, since fetch cannot forge a Host header), and the button state machine against a minimal React stand-in — no DOM, no browser.

Layout:

lib/index.js     host half: route, validation, LLM call, error mapping
lib/http.js      loopback guard, JSON responses, bounded body reader
lib/llm.js       stream consumption and failure classification
lib/prompts.js   system prompt, user template, output normalization
lib/client.js    browser half: the composer control
locale/          plugin-list metadata
test/            node:test suites

Compatibility

DSH 0.2.1-rc.1 and newer within 0.3.0, written as >=0.2.1-rc.1 <0.3.0-0 || >=0.2.2-0 <0.3.0-0 — the two branches exist because a plain range does not match its own prereleases, so 0.2.2-rc.1 would otherwise be rejected.

The @deepseek-ai/* peer dependencies are declared optional: they are provided by the harness composition, never installed by this package, and a composition missing one degrades the feature instead of failing the client.

License

MIT © Cloud017

Comments

Loading…