dsh-thoughtdag
Adds an editable conversation canvas to DeepSeek Harness, where graph connections select context for canvas requests, with branching, merging, and local agent session imports.
Install
dsh plugin --profile web add dsh-thoughtdag
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✓ |
| 2 list | ✓ |
| 3 mount | ✓ |
| 4 boot | — |
Four stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
dsh-thoughtdag
This directory is the DeepSeek Harness plugin of [ThoughtDAG](../README.md), published to npm as dsh-thoughtdag; its version follows the app's, and the ThoughtDAG build it embeds is the one in this tree.
ThoughtDAG for DeepSeek Harness: open DSH sessions (live or on disk) as
editable thought graphs on ThoughtDAG's infinite canvas — from inside the
harness UI.
Source, releases and issues live at github.com/chenxiachan/thoughtdag. If the plugin helps you, a star there helps others find it.
This is a DeepSeek Harness
plugin (a Cordis plugin distributed as an npm package), built on the same shell
pattern as dsh-synapse: the host
half mounts the ThoughtDAG SPA under /thoughtdag/ on the EXISTING harness
web server (no second process, no second port), and the client half adds a
ThoughtDAG entry to the harness sidebar (beside Plugins) that shows the
canvas in the main column, in a same-origin iframe.
The entry is the host's own panel mechanism (sidebar.panellist plus the
root main panel slot), so it is there before any session is open and
follows the host's language and theme. The iframe stays in the plugin's own
layer, laid over the panel while it is selected, so switching never reloads
the canvas. (0.4.19 to 0.5.18 floated a 对话 | 思维图 switch over the top
strip instead; every placement collided with host chrome somewhere, see
#55, #61, #63, #73. Hosts without the panel slot still get that switch.)
What works
dsh plugin --profile web add dsh-thoughtdaginstalls the plugin from npm; every GitHub release also carriesdsh-thoughtdag-<version>.tgz, and the same command takes that file's URL (dsh pluginforwards to pnpm)- The harness sidebar gains a ThoughtDAG entry; selecting it opens ThoughtDAG at
/thoughtdag/ (same origin — no CORS, no second server)
- The host serves the SPA plus a read-only session bridge:
Endpoint · Purpose
GET /thoughtdag/api/disksessions · list durable sessions on disk (id, title, cwd from the session header; newest first)
GET /thoughtdag/api/disksessions/<id>/log · one disk session as JSONL — the exact dialect ThoughtDAG's dsh-session adapter parses, so a past harness session imports like a local file
GET /thoughtdag/api/sessions · list live sessions in this process
GET /thoughtdag/api/sessions/<id>/log · one live session's events as JSONL
GET /thoughtdag/api/sessions/<id>/turns · turn boundaries (start/end seq, the person's message id) of a live or on-disk session — the fork points a canvas can name
POST /thoughtdag/api/sessions/<id>/fork · { afterTurn } or { atSeq } → a child session inheriting the prefix through that completed turn (sessionController.fork, so the chat UI lists it)
POST /thoughtdag/api/sessions/<id>/inject · { text } or { blocks: [{type:'text',text}] } → model-facing context for the next step (agent.inject; no wake; shown in the transcript as injected context from dsh-thoughtdag)
POST /thoughtdag/api/sessions/<id>/followup · { text · blocks, mode?: 'queue' · 'steer' } → a user prompt through sessionController.prompt, exactly as the composer sends one
GET /thoughtdag/api/roots · GET /thoughtdag/api/roots/<key>/list\ · head\ · read\ · range · the other agents' session directories on this machine (claude-projects = ~/.claude/projects, codex-sessions = ~/.codex/sessions) with the desktop bridge's file primitives, so Session Atlas inside the harness lists all three sources and mirrors a Claude Code or Codex session as the desktop does; rel never escapes its root
GET /thoughtdag/api/models · the harness's model catalog in the SPA's list shape (<provider>/<model> ids, the harness default)
POST /thoughtdag/api/stream · POST /thoughtdag/api/claude · the SPA's own proxy protocol, answered on the harness's providers and credentials (ctx.llm.stream); the embedded SPA is built with VITE_API_BASE=/thoughtdag, so its model picker and every canvas-native generation (summaries, condensing, a canvas that is not a mirrored session) run on the harness's models. These calls do not enter a session log; a mirrored session's turns go through /followup
harness/agent (a catalog entry) · pick it in the picker and the question goes INTO the harness: a fresh session per call, the canvas's wired context injected first (agent.inject, source dsh-thoughtdag), the question as a user follow-up, the harness's own agent loop with tools; text, reasoning and tool calls stream back as the SPA's frames, the first frame names the session ({ harnessSession }) and, once the question enters the surface, the turn it created ({ harnessTurn: { turn, userMessageId, seq } }), so the canvas can mark its node as that turn's mirror instead of receiving it twice. The session stays in the Chat and the atlas. harness: { cwd } sets the session's working directory (the canvas passes the project it mirrors, else the current chat session's); harness: { session } continues a mirrored session instead of forking a fresh one (a tail follow-up); images (base64) are admitted through the controller's prompt and a vision model is selected for that turn, so a picture the canvas holds is read by the harness's own eyes
POST /thoughtdag/api/fetch-url · the SPA's link snapshot ({ url } → { title, text, fetchedAt, html? }) through the harness's bounded, credential-free fetcher (ctx.web.fetch)
Disk logs are zstd concatenated-frame files; the bridge locates frame
boundaries structurally and decodes each with node:zlib (the same walk the
DSH persistence backend performs), so no external zstd binary or native
module is needed.
- The bridge is Host-header fenced (localhost/127.0.0.1 +
trustedHosts)
Verified (2026-09)
- installe
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::43,最后更新 2026-11-01