在 DeepSeek Harness 中嵌入可编辑对话画布,通过连线选择画布请求的上下文,支持分支、合并与本地 Agent 会话导入。
安装
# npm 包(预构建)
dsh plugin --profile web add dsh-thoughtdag
# GitHub 源码(首次需按提示配置 allowBuilds 构建授权后重试)
dsh plugin --profile web add github:chenxiachan/thoughtdag#path:/dsh
装任何插件都等于在你的机器上跑第三方代码,权限和你本人一样大——能读你的文件、用你的凭据、访问网络,工具审批管不到它。GitHub 来源的插件还会在安装时执行构建脚本——pnpm 默认拦截,所以安装可能停在 ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED 或 ERR_PNPM_IGNORED_BUILDS;dsh 会打印出需要添加的确切键名,把它加进该 profile 的 pnpm-workspace.yaml 的 allowBuilds 下,重跑一次即可装上。放行构建本身就是一次信任判断:请只安装可信来源,并尽量锁定 commit(github:owner/repo#sha)。
README
该插件的 README 只有英文版本。
This directory is the DeepSeek Harness plugin of ThoughtDAG, 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.
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
"对话 | 思维图" switch to the session header that shows the canvas in a
same-origin full-screen iframe.
The switch lives in the session header: open a session first — there is no switcher on the empty state. (入口在会话标题栏,需要先打开一个会话; 空态下没有切换器。)
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 GUI gains a "对话 | 思维图" switch in the session header; "思维图" 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/disksessionslist durable sessions on disk (id, title, cwd from the session header; newest first) GET /thoughtdag/api/disksessions/<id>/logone disk session as JSONL — the exact dialect ThoughtDAG's dsh-sessionadapter parses, so a past harness session imports like a local fileGET /thoughtdag/api/sessionslist live sessions in this process GET /thoughtdag/api/sessions/<id>/logone live session's events as JSONL GET /thoughtdag/api/sessions/<id>/turnsturn 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 fromdsh-thoughtdag)POST /thoughtdag/api/sessions/<id>/followup`{ text GET /thoughtdag/api/roots·GET /thoughtdag/api/roots/<key>/list|head|read|rangethe 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;relnever escapes its rootGET /thoughtdag/api/modelsthe harness's model catalog in the SPA's list shape ( <provider>/<model>ids, the harness default)POST /thoughtdag/api/stream·POST /thoughtdag/api/claudethe SPA's own proxy protocol, answered on the harness's providers and credentials ( ctx.llm.stream); the embedded SPA is built withVITE_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/followupharness/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, sourcedsh-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 eyesPOST /thoughtdag/api/fetch-urlthe 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)
- installed into the local
webprofile viadsh plugin --profile web add <dir> - a fresh web-profile boot serves
/thoughtdag/(SPA) and the bridge API; the index injection table listsdsh-thoughtdag/client.js - headless-browser walk: the "对话 | 思维图" switch appears in the session header, the full-screen same-origin iframe opens, and ThoughtDAG boots inside it
- fetching the bridge from INSIDE the thoughtdag origin works with no extra
auth:
GET /thoughtdag/api/disksessionslists every on-disk session (new sessions created by the running instance appear automatically) andGET .../logreturns the full event stream - real session logs decode correctly (multi-frame zstd → 15k+ JSONL lines,
identical to the
zstdCLI) - the live bridge (
/api/sessions) reflects the running instance's active session as soon as the GUI opens one (verified: opening the UI surfaces the auto-created session with its live seq), complementing the disk archive
Canvas-side import
When a turn launched from the canvas needs the person's approval (the
harness's sandbox asking to escalate, a policy hook answering ask), the
plugin answers first: it registers ahead of the harness's own panel on the
approval/request waterfall for the sessions it is running, streams the
question to the canvas as an approval frame, and the node shows it —
tool, command, the harness's reason, allow once or reject. The decision
returns through POST /thoughtdag/api/approvals/:id and stays on the node
as part of the turn's record. If the canvas stream is gone, the request
is handed down the chain to the harness's panel unchanged.
Inside the iframe the canvas runs with this bridge as its session source
(the SPA is built with VITE_DSH_BRIDGE=/thoughtdag/api): Session Atlas
lists the harness's sessions beside Claude Code's, Codex's and Pi's (served by
this host from their directories), opens one as a graph, and follows it
live by polling the session's seq. The client half tells the canvas which
session the chat shows (td:current-session) and switches the chat when the
canvas names one (td:select-session).
The why layer inside the harness
The plugin bundles the thoughtdag CLI's library (lib/why.mjs, built at pack time) and answers the same four questions over the same ~/.thoughtdag index — no CLI or MCP install needed:
| Surface | What |
|---|---|
| Native tools | why_check(path), why_file(path, include_read?, limit?), why_find(phrase, in?, limit?), why_recall(session, turn) — the agent calls them like any harness tool; relative paths resolve against the session's working directory |
/why <path | url | arxiv:id> |
a person asks from the chat; the answer is the CLI's why output, no model message |
| System-prompt section | four lines telling the model to why_check before editing a file with history and how to read the other three |
Both are on by default; whyTools: false / whyPrompt: false in the plugin config turn them off.
Not yet (roadmap)
- Canvas why panel (a node's file → its history through
/thoughtdag/api) - Canvas UI for the write bridge: name a fork point on a node, hand a compiled context to
inject, continue withfollowup; the client already switches the chat to a session the canvas names (td:select-session) replace: shadow a surface range from the canvas (DSH's compaction primitive); needs a live check of how the chat renders a replaced range- Theme and language sync with the harness UI
- Open the chat's current session on the canvas automatically when the view switches
Development
# 1. build the embedded ThoughtDAG SPA with a /thoughtdag/ subpath base (from the repo root)
npm run dsh:build # writes dsh/dist-app, which git ignores
# 2. install into a profile from this directory (pnpm link)
dsh plugin --profile web add /abs/path/to/thoughtdag/dsh
# 3. restart the profile's web app; open a session and use the switch in its header
The script drives tsc, vite and esbuild through Node directly, so the
same code path builds on Windows, macOS and Linux. Always run it as
npm run dsh:build instead of passing the flags through Git Bash by hand:
MSYS path conversion rewrites --base=/thoughtdag/ into a Git-install path,
which bakes a broken base into dist-app — every asset request then falls
through to the SPA fallback HTML and the canvas mounts as a blank white page.
While developing, the profile keeps a pnpm link to this directory, so edits
to lib/ apply on the next restart without reinstalling.
License: MIT
链接
同类插件
zhu1090093659/dsh-web#packages/dsh-task-board★ 7488
侧边栏多列任务看板:卡片交给真实 DSH 智能体会话执行,支持 cron 定时(Host 侧到点执行,关浏览器也生效)。
zhu1090093659/dsh-web#packages/dsh-web-all★ 7488
DSH Web UI 插件与皮肤合集:任务看板、git 图、右侧面板、远程移动端 UI、桌宠、实时 token 统计与皮肤中心。
omdsh-dev/DSH-better-sidebar★ 3555
侧边栏完整工作台:内置文件渲染编辑、终端、Git 与子代理,支持三方插件注册新 Tab。
ccch1mneyyy/dsh-TUI★ 2994
Claude Code 风格全屏终端 UI:像素鲸鱼顶栏、实时工作状态行、思考流式展开。
MeteorNOX/DeepSeek-Balance-Whale-Widget★ 2274
右下角常驻的小鲸鱼余额挂件:显示余额、今日已用、每轮对话消耗与随机台词,带音效与设置菜单。
Devin-AXIS/deepseek-design#deepseek-idesign★ 1072
可视化设计工作室,支持网站、App 原型、海报、信息卡、报告和杂志的模板创建、元素编辑、选区级 AI 草稿衔接与导出。
社区评论
评论公开保存在 GitHub Discussions。加载评论会连接 GitHub 和 Giscus;发表内容需要 GitHub 账号。