DeepSeek Harness Plugin Hub

发布与管理完整 Harness Profiles,发现适合你的插件。

探索

插件目录环境预设文档中心动态

社区

发布插件联系我们报告问题

相关链接

Plugin Hub GitHubDeepSeek Harness 官方项目系统状态隐私说明
© 2026 DeepSeek Harness Plugin HubPowered byPaxTech

独立、非官方社区项目,与 DeepSeek 官方无隶属、授权或背书关系。

Deepseek Coordination — DeepSeek Harness 插件(DSH Plugin)
DeepSeek Harness Plugin Hub
ProfilesPlugins分类动态文档登录管理 Profiles
ProfilesPlugins分类动态文档登录
← Plugins
D

deepseek-coordination

Deepseek Coordination

一个面向 DeepSeek Harness 的双面 Cordis 插件:主机端负责协调 SQLite 数据库、七个面向模型的工具和 HTTP 接口;Web 端挂载五个编辑器下拉菜单、设置目录以及服务级接管对话框。

插件会安装到这里;不确定时保持 web。

npx -y @deepseek-ai/dsh plugin --profile web add github:eloyhere/deepseek-coordination#0431acadaee866a7a07b39085107225082514719
README兼容性版本

兼容性与来源证明

Deepseek Coordination 以 deepseek-coordination 发布,当前版本为 0.14.10。Plugin Hub 会校验它的 manifest,并保存精确安装来源,便于复现安装结果。

DSH 兼容范围
*
运行环境
web
发布来源
github
Registry 更新时间
2026/10/18

版本

0.14.10stable
2026/10/18
0.14.6stable
2026/10/18
0.13.0stable
2026/10/18
查看其余 10 个版本收起版本
0.11.0stable
2026/10/18
0.10.0stable
2026/10/17
0.9.2stable
2026/10/17
0.6.5stable
2026/10/17
0.2.0stable
2026/10/17
0.1.9stable
2026/10/13
0.1.7stable
2026/10/13
0.1.3stable
2026/10/13
0.1.2stable
2026/10/13
0.1.0stable
2026/10/12

相关插件

正在加载相关插件…

最新版
0.14.10
DSH
*
HMR
重启进程
Tree shaking
未声明可安全裁剪
解包体积
未提供
文件数
未提供
Surface
web
许可证
Apache-2.0
发布源
github
GitHub
★ 1
周下载
0
最近提交
2026/10/18
查看源码 ↗
README Badge

点击下方 Badge 复制 Markdown,粘贴到 README 即可。

这是你的 Plugin?认领权益 · 优先安全扫描

验证 package.json 声明的 GitHub 仓库,即可管理这个公开页面。认领后,Hub 会优先安排当前版本的安全扫描,并在通过后公开展示结果。

认领这个 Plugin →
报告问题

相关插件

继续浏览 ui-customization 分类下经过校验的插件。

Web App@deepseek-ai/dsh-web-appdsh 浏览器界面捆绑包:位于 dsh-base 之上的 Web 补丁层,加上运行时粘合插件(提供前端 dist、Web 界面提示符、bash 运行时变量和 URL 行)Experimental Agent Team Web Profile@deepseek-ai/dsh-experimental-agent-team-web-profile用于 Agent Teams Remote 和 UI 插件的实验性 Web 配置层Whale Widgetdsh-whale-widgetDSH Web 界面右下角的 DeepSeek 余额小鲸鱼挂件:余额/今日已用/峰谷定价、自定义泡泡点击序列(文本/余额/今日/峰谷/图片/随机语句与并列加权选择)、逐行样式与字体、悬浮快捷编辑、音效与每轮消耗、自定义角色/动图/音效、吸附与翻转自定义Ab Chartdsh-ab-chart带有绘制其调用的浏览器卡片的图表渲染工具,封装在一个可发布的插件包中

README

deepseek-coordination

English · 简体中文 · Changelog · 中文更新日志

A dual-face Cordis plugin for DeepSeek Harness: the host half owns a coordination SQLite database, seven model-facing tools and an HTTP surface; the web half mounts five composer dropdowns, a settings catalog and the service-level takeover dialog.

Status: v0.14.10 (2026-10-18). This release adds two read-only docked workspace panels with canvas relationship graphs, a preview matrix (Markdown and math, sanitized HTML, Prism code, docx/xlsx/pptx), an agent roster with estimated progress, and hardens all of it so a panel failure cannot blank the harness. It builds on the v0.12.0 domain layer and the v0.11.0 settings and cache-proxy work. The package version, changelog and release tarball are the same tree; claims below were checked against source, not against the design documents alone.

StatusMeaning in this README
WiredRegistered by src/index.ts or called by the composed service, routes or tools.
Library-onlyImplemented and tested as a module, but not driven by the current turn lifecycle or exposed through a route/tool.
Design/plannedDocumented or declared in config/schema, with no runtime consumer yet.

What it is

PieceLocationRole
Bundlecordis.patch.yml, dsh.bundle in package.jsonInserts one deepseek-coordination row into a DSH profile roster.
Host halflib/index.mjs (ESM, Node)CoordinationService, the coordination SQLite database, 7 tools, 14 route paths and the agent hooks.
Client halflib/client.js (CJS, browser, __ModuleLoader__ wrapper)React 18 + Material UI 9: composer dropdowns, settings page, takeover dialog.
Database%DSH_HOME%\coordination\coordination.db by defaultPlugin-owned SQLite file; 63 tables, 7 triggers, 63 indexes, schema version 24. Never DSH's harness database.

The plugin does not replace DSH's agent loop. It records coordination state, locks one profession per task, exposes the composer selection and file metadata, asks DSH to compact when context pressure crosses a threshold, and relays approvals/questions to a human through its own dialog.

The five composer controls are 权限 (permission), 职能 (profession), 交互 (interaction), 情景 (scene), 验证 (validation). The command face (/goal, /plan, /feedback, /compact, /permission) is defined as a message prefix, not a sixth dropdown.

Install and build

RequirementDetail
Node.jspackage.json declares >=18, but the host imports node:sqlite; use a Node build that ships it. Verified on Node 24.21.0.
npmnpm 11 (bundled with Node 24) installs from package-lock.json and drives the scripts and the release workflow.
DSHA DSH installation with the dsh CLI and a web-capable profile (@deepseek-ai/dsh-base + @deepseek-ai/dsh-web-app).
Peer packagesSee the table below; they come from the DSH installation, not from this package.
cd deepseek-coordination
npm ci                  # or `npm install` in a fresh checkout
npm run typecheck       # tsc -p tsconfig.json --noEmit
npm test                # tsdown test build + node --test
npm run build           # lib/index.mjs, lib/index.d.mts, lib/client.js
npm pack                # prepack builds first; produces the installable tarball

npm run test:tsc type-checks the test tree. npm run pack:check validates the packed runtime files and syntax-checks the host entry. package-lock.json is committed; npm ci reproduces it exactly.

Peer packageRangeSide
@deepseek-ai/cordis^4.0.1Host runtime
@deepseek-ai/dsh-host-webserver^0.1.0-rc.7 || >=0.2.1-rc.2Host route registration
@deepseek-ai/dsh-client-runtime, -locale, -ui-slots, -ui-settings^0.1.0-rc.7 || >=0.2.1-rc.2Browser module table
react^18.2.0Browser module table; never bundled

The client half is compiled against the 0.2.1-rc.2 client packages the desktop runtime ships (-locale, -ui-settings, -ui-slots, -ui-conversation). @deepseek-ai/dsh-client-runtime and @deepseek-ai/dsh-host-webserver publish no 0.2.x release, so their devDependencies stay on 0.1.0-rc.8 while their peer ranges accept the 0.2.1+ runtime the host provides. The open-ended >=0.2.1-rc.2 accepts every later stable release; ^0.1.0-rc.7 keeps the 0.1 line installable.

Install into a profile

Install the packed tarball, not the GitHub source:

npm pack
dsh plugin --profile <name> add .\deepseek-coordination-0.14.10.tgz
dsh --profile <name> --dump-config   # expect a deepseek-coordination layer

Raw github:eloyhere/deepseek-coordination installs are unsupported. lib/ is gitignored, and the bundle is only built by prepack (or an explicit npm run build), which npm does not run for a git dependency; the installed package then fails at activation with ERR_MODULE_NOT_FOUND for lib/index.mjs. The tag-triggered GitHub Actions workflow (.github/workflows/release.yml) builds and attaches the verified tarball to the release; install that artifact.

npm latest is still the old 0.1.9 dsh-os line. Do not install by package name yet. A local checkout can be linked with dsh plugin --profile <name> add . after npm run build.

dsh plugin add writes the dependency and the bundle row. If the profile still records a different package spec, replace it rather than assuming the new code loaded; check dsh --profile <name> --dump-config and the installed package.json version.

Uninstall or disable

If a release makes the harness unreachable, remove it in this order and restart afterwards:

  1. Remove the deepseek-coordination bundle entry from the profile roster (dsh plugin --profile <name> remove deepseek-coordination, or delete the row by hand).
  2. pnpm remove deepseek-coordination in the profile.
  3. Delete node_modules/deepseek-coordination if it still exists; some uninstall paths leave the directory behind.
  4. pnpm install to rewrite the lockfile and dependency tree.
  5. Restart the harness. The client bundle is served at boot, so reloading the page alone does not unload the old plugin.

For a no-restart recovery path limited to the panel UI, set localStorage['coordination.panel.disabled'] = '1' (or 'true') in the Web GUI and reload: the coordination panel column mounts nothing, while the rest of the plugin stays available. Set the key back to '0' (or delete it) and reload to restore the panels. The flag is read once at mount, so both directions need a reload.

ArtifactFormatSize in this build
lib/index.mjsHost ESM, platform: node2,380,317 B
lib/index.d.mtsHost declarations9,095 B
lib/client.jsBrowser CJS wrapped in __ModuleLoader__.load()3,332,193 B

Material UI, emotion and react-dom are bundled into lib/client.js; React itself comes from the host module table. The inlined react-dom is the 18.3.1 line that matches the host's React 18 — npm refuses to auto-install a React 19 react-dom against a React 18 react. The client bundle is large because MUI and react-dom are inlined, not because it ships a second React.

Architecture

Host half (src/index.ts):

  • exports name, inject = ['webServer', 'tools'] and Config; apply() resolves config, creates the service, recovers interrupted turns and installs every effect through ctx.effect.
  • CoordinationService (src/host/coordination.ts) is the Cordis coordination service. It owns the database, module host and the composed modules: session, selection, turn, profession, plan, goal, compact, directive, permission, takeover/gate, provider, cache and command.
  • SQLite is opened with node:sqlite (DatabaseSync), foreign keys, a 5 s busy timeout and WAL outside :memory:. Triggers refuse changing a locked profession and make orchestration_trace append-only.
  • The /deepseek-coordination prefix route answers JSON { ok, value | error }; request bodies are capped at 1 MiB and unknown paths return 404 with the route envelope.
  • Seven tools are registered through ctx.tools; the three composer tools are re-registered after POST /locale, because their descriptions are part of the model-facing prompt.
  • Hooks: agent/pre-step opens the coordination turn and runs the compaction governor; agent/turn-stopping closes it as done; agent/error closes it as failed; approval/request and user-questions/request feed the takeover gate. A 60 s timer deletes expired lock rows.

Client half (src/client/index.ts):

  • inject = ['slots', 'locale']; package.json's dsh.client.inject separately lists the four module-table packages.
  • settings.section (order 50) mounts CoordinationSettings; conversation.input.left (order 40) mounts the composer controls and the takeover dialog as siblings.
  • Language follows ctx.locale.getLocale().active, normalises zh*/en* onto zh-CN/en-US, and reports changes to POST /locale. The host rebuilds localized tool descriptions from that report.
  • The client bridge uses same-origin fetch with a 3 s selection timeout and 2 s takeover/locale timeouts. Unreachable hosts fall back to a per-session localStorage copy for the five choices; a permission preset is never written offline.
  • The composer components are memoised on sessionId only, because the slot also passes the composer input on every keystroke; re-rendering this row would make emotion touch <head> and close DSH's popover.
deepseek-coordination/
├─ src/
│  ├─ index.ts                 # host composition root: service, routes, tools, hooks
│  ├─ host/
│  │  ├─ coordination.ts      # CoordinationService (Cordis service "coordination")
│  │  ├─ config.ts             # Schemastery schema + resolveConfig()
│  │  ├─ database.ts           # SQLite schema (24), 63 tables, triggers
│  │  ├─ dsh.ts                # narrow DSH ports + turn lifecycle
│  │  ├─ tools.ts              # 7 model-facing tools
│  │  ├─ chain.ts              # bounded Chain projection engine
│  │  ├─ node-registry.ts      # NodeCard registry and describe()
│  │  ├─ parse-service.ts      # workspace-bound parse + read service
│  │  ├─ token.ts              # TokenGovernor and pure policy
│  │  ├─ takeover-gate.ts      # approval/question waterfall gate
│  │  ├─ selection.ts turn.ts profession.ts …   # selection, lock, lifecycle
│  │  ├─ bayesian.ts comprehension.ts organization.ts … # library engines
│  │  └─ text/                 # P0 parsers: JS/TS, CSS/HTML/MD, TeX, formulas, graph
│  ├─ client/
│  │  ├─ index.ts              # slots, locale store, nav icon, takeover CSS
│  │  ├─ controls.ts           # five composer dropdowns, tooltips, offline replay
│  │  ├─ settings.ts           # 13-group, 151-control settings catalog
│  │  ├─ takeover.ts           # approval/question dialog
│  │  ├─ bridge.ts store.ts i18n.ts theme.ts selection-cache.ts
│  └─ shared/                  # entity/enum/selection/i18n/error + data structures
├─ test/                       # 24 *.test.ts + helpers.ts
├─ lib/                        # build output; gitignored, never edited by hand
├─ cordis.patch.yml            # bundle row inserted into a profile
├─ scripts/check-pack.mjs      # tarball runtime-file verification
└─ .github/workflows/release.yml

Composer controls

ControlOptionsWhat it does
权限 PermissionDSH preset catalog, or a neutral “follow DSH” stateWrites the chosen preset to DSH immediately through ctx.permissionPresets; never persists it in the coordination DB. Only shown while the local 权限接管 switch is on.
职能 Professiondecision / outcome / resource / personnel / qualification / executionLocked for the active turn. Selecting another value is refused with PROFESSION_LOCKED and opens the rebuild/abandon dialog.
交互 Interactionemotion / think / heuristic / converge / orchestrateStored for the next turn; frozen while the active turn has a non-cleared goal.
情景 Scenedialogue / writing / office / research / engineering / iterateStored for the next turn. writing sits between dialogue and office; the scene policy is read by the turn pipeline.
验证 Validationlow / medium / highStored for the next turn; frozen while the active turn has a draft/scored/active plan. All three levels search.
  • Every control and every option has a tooltip. A single-owner tooltipVisibility store ensures only one composer tooltip is visible; placement is left/right, exit is a 160 ms fade, and the fade popper is pointer-transparent.
  • Clicking a dropdown opens its menu on the first click; there is no state change on pointerdown/mousedown that would swallow the Select click.
  • A locked profession trigger is disabled and carries an accessible name with the lock explanation; option MenuItems carry the label plus hint for keyboard and screen-reader users.
  • Phase freezes are re-derived from the host on every poll: turn → profession, plan → validation, goal → interaction. The select is disabled but stays focusable, its aria-label and tooltip name when the freeze lifts, and the server refuses a changed value with INVALID_STATE (replaying the stored value is allowed).
  • Tooltips obey the host's ui.showTooltip gate; the local “show hints” preference can only narrow them, never resurrect a host-disabled tooltip.
  • Saves are optimistic and debounced by 120 ms. A rejected save reverts to the last host-confirmed state; offline edits are replayed when the host returns. A full-access preset needs an explicit second confirmation.
  • While the host state is loading, selects stay disabled and show a loading line. A missing preset catalog is shown as a missing catalog, not invented.

Validation budgets are policy, not a claim that the whole pipeline runs today:

LevelQueries × resultsEvidence scopeInteraction scope
low1 × 3Current turn onlySelected interaction
medium2 × 5Current sessionSelected interaction
high4 × 8All local contentAll interactions

The budgets live in src/host/comprehension.ts and the shared ValidationBudgetByLevel table. ComprehensionModule is library-only and is not driven by the current CoordinationService turn lifecycle, so the composer persists the level without executing these searches yet.

Scenes and the writing profile

ScenePlanOutlineRevisionScoreBashWebMax iterations
dialogue––––noyes1
writingyesyesyesyesnoyes3
officeyes–––noyes1
researchyes–––noyes3
engineeringyes–––yesyes3
iterate–––yesnoyes3

writing requires an outline and at least one revision round, requires a quality score, disallows bash, allows web search and caps the loop at three iterations. The pass threshold is 0.6; plan.ts uses that writing threshold. The turn pipeline reads the require-* flags, citation/evidence, allowWeb and sandboxOnly; reasoning (thinking, reasoningEffort) belongs to DSH — the page has no row for it, and the turn records what the session's own request header carries rather than a scene literal. allowBash, maxIteration and non-writing thresholds remain deferred diagnostics because no DSH port or consumer exists yet.

Profession lock and turn lifecycle

  • One task has exactly one profession. turn.create writes profession NOT NULL, locked = 1 and one profession record plus one lock trace event.
  • While a non-terminal turn exists, SelectionModule.set refuses a different profession with ProfessionLockedError; the HTTP layer answers 409 PROFESSION_LOCKED. The selection is not mutated.
  • POST /profession/rebuild ends the active task as abandoned, creates a replacement turn with a new ordinal and profession, copies the prompt/command, and emits rebuild + lock trace events. It requires an active turn.
  • POST /profession/abandon closes the active task without a replacement; the next task may choose again. Both reselect flags are forced true by resolveConfig.
  • SQLite repeats the rule: trg_turn_profession_lock, trg_profession_record_lock, trg_subtask_profession_lock abort a profession change while locked; trg_turn_profession_unlock and trg_subtask_profession_unlock refuse clearing the flag.
HookEffect
agent/pre-stepEnsure the coordination session, open (or reuse) one Turn for the DSH turn; also runs the token governor before next().
agent/turn-stoppingClose the Turn as done; the profession unlocks for the next turn.
agent/errorClose the Turn as failed.
Host startrecoverInterrupted() marks every non-terminal Turn failed with reason turn was interrupted by a host restart.
Every 60 sDelete ended locks older than defaultLease.

Terminal turn states (done, failed, cancelled, abandoned) are irreversible. The turn hook records turn metadata and an empty prompt row; it does not mirror the DSH conversation into the coordination database.

Domain ecosystems and parsers

The file layer is not one parser with a bag of node kinds. Each system owns a module under src/host/text/, and the node kinds it may emit are bounded by that system's semantics. All output is body-free NodeMetadata: kind, explicit name/label, span and fragment coordinates — never a body, a cell value or a paragraph.

EcosystemModuleNode kinds it may emit
textex.tsdefinition, lemma, theorem, proof, property, axiom, corollary, claim, example, remark, calculation, condition (+ requires/meets edges)
bookbook.tsbook, part, chapter, article, section, person, venue — the only producer of article
markdownmarkup.tsdocument, chapter, heading, paragraph, div, link, code, section, sheet, cell, range, condition
htmlmarkup.tsdocument, section (<article> maps here), chapter (<h1>), link, code
js/tsjavascript.tsclass, function, method, variable, interface, type, enumeration, namespace, importation, exportation, condition
javajava.tsmodule, class, interface, enumeration, method, variable, importation
pythonpython.tsclass, function, method, variable, importation
c/c++

Rules that hold across every ecosystem:

  • Language nuance lives in label, not in new kinds. Rust impl is kind: 'class' with label: 'implementation'; C++ struct/enum and PHP trait work the same way. NodeKind stays a small closed union.
  • Descriptive only. No parser writes files, builds, installs, executes macros or reaches the network. A real "create project" is a shell command behind DSH's permission model, never a plugin tool.
  • Explicit evidence only. A heading level is never inferred from text, a package version is never invented, and a missing relationship is reported rather than paired positionally. Malformed input returns a diagnostic and never throws.
  • Bounded. ZIP entries ≤ 2000, uncompressed ≤ 64 MiB per entry / 256 MiB total, XML nesting ≤ 128, nodes ≤ MAX_METADATA_NODES (20 000), and the parser honors the token/time budgets.
  • SUMMARY.md resolves to book through the registry's filename-first rule; README.md and other Markdown stay with the Markdown parser.

The graph answers "what is in this workspace" through coordination_parse, coordination_describe and coordination_chain. The chain query takes an optional kind (trimmed, case-insensitive) on every node-returning action, so "all lemmas" or "all chapters" is one call instead of a scan. Directory nodes are derived from unambiguous workspace paths and connected with contains/part_of; the invariant is part_of (child→parent) exact, contains (parent→child) best-effort.

Workspace panels

Two read-only panels dock to the right edge and stack vertically: the relationship panel (files / agents / dependencies / imports / exports) and the workspace panel (files / outline / dependencies / imports / preview). Each keeps a 48px title bar with menu, search and minimize/restore; expanding one pushes the other. A relationship tab draws a native canvas graph with directional flow, cycle pulsing, hover tooltips and click selection; the agents tab lists the main agent and its subagents with an estimated progress ring and opens a read-only transcript. The preview tab renders Markdown/math, sanitized HTML, docx HTML, Prism-highlighted code, xlsx sheets and pptx slides — all read-only, bounded and no-store. State is { openLeft, openRight, width } in localStorage; views are hash routes (#coordination/panel/right/<view>?path=…). Bundle cost is about +2 MB (KaTeX, react-markdown, Prism, MUI icons), 700 KB gzipped.

Settings and configuration

The settings page is driven by SETTINGS_CONTROLS in src/shared/selection.ts: 139 controls in 13 groups, 122 writable host rows, covering 155 config leaves. Twelve scene leaves (scenes.*.thinking, scenes.*.reasoningEffort) stay in the schema but have no row: DSH's model page owns reasoning, and duplicating it here would create two sources of truth. The 18 top-level config keys include database and databasePath, which are deliberately not projected or writable.

GroupDefaults / scopeWrite path
sessionmaxTurnPerSession=1000, defaultLease=30000 ms, clarifyTimeout=30000 msHost rows through /config
professionenabled/lock/rebuild/abandon forced true; default mirrors defaults.profession; audit/errorHint trueForced flags read-only; audit/errorHint host rows (audit has no consumer)
planthreshold 0.5, maxRebuild 3, 8 weights summing to 1, 8 dimension thresholdsHost rows; weights re-normalise on save
orchestrationmaxReject 2, maxSubTask 32, groundTruth true, timeout 5000 ms, shell ground truth false, modelRouting trueHost rows; groundTruthTimeout has no consumer
cacheenabled true, ttl 60000 ms, fingerprintWindow 50, effortWarning trueHost rows; enabled/effortWarning gate the cache proxy decorator, ttl caches the model catalog, fingerprintWindow has no consumer
bayesianprior 0.5, stopEntropy 0.05, infoGain 0.01, maxRoutes 12, calibrationFloor 0.1Host rows; calibrationFloor has no consumer
comprehensionstageTimeout 30000 ms, searchEnabled true, maxEvidence 8, highHistoryWindow 50Host rows
compactionauto true, soft 0.70, hard 0.88, reserve 2048, recentTurns 6, cooldown 30000 ms, maxPerSession 20auto/soft/hard host rows; structural fields read-only
uitoolbar (deprecated alias), showTooltip , takeover , refreshInterval , compact , locale

GET /deepseek-coordination/config returns { values, defaults }; defaults is resolveConfig(undefined), so the page never duplicates a default literal. POST /config accepts a flat dotted patch such as { "plan.threshold": 0.7 }, validates it against the catalog and the real Schemastery schema, applies it to the live config, re-resolves invariants (weight normalisation, alias mirror, forced flags, compaction clamps), rebuilds TokenGovernor when compaction changes, and persists the applied paths.

Persistence is the host's own override document at <database dir>/config.overrides.json: a flat { "plan.threshold": 0.7 } map written atomically beside the coordination database and merged over the profile config on the next start. It is not DSH's ctx.settings.update, which only accepts .volatile() schemas — and a volatile node turns every parsed value into a reference wrapper this host cannot adopt without rewriting every config reader. persisted: true therefore means "stored in the coordination host's own document"; a write that only touched ignored rows reports false. Unknown keys, databasePath and database are rejected with INVALID_ARGUMENT. Known but non-editable keys are reported in ignored and never written. POST /config/compaction remains as a small compatibility route for the old auto/soft/hard patch.

The page is Material UI end to end: one default-expanded Accordion per group, a List of rows, six scene tables (no scene dropdown), Checkbox for booleans, RadioGroup for enums, TextField type="number" for every number (weights and ratios included, rounded to the row's step for display only), and Chip only for the 主机 / 本机 / 强制 / 只读 / 计划中 status plus connection state. The full-access confirmation is a modal MUI Dialog above the tooltip layer, never an inline banner. There is no save button; controls apply on change/blur. A forced row draws a disabled control, a read-only row shows a value, and a planned row says the runtime does not read it yet. The settings nav icon is a host-shell workaround: the shell accepts only { id, order, label } for a section, so the plugin decorates its nav button with a CSS mask of the Material sync glyph.

Service-level takeover

  • With ui.takeover on, TakeoverGate listens to DSH's approval/request and user-questions/request waterfalls. It records a durable pending row, emits takeover/pending, and waits for a human answer delivered through the client routes.
  • The listener registers with { prepend: true }. DSH's own approval and question UI listens to the same waterfalls, and a listener registered later never runs once the GUI claims the request. Note that a deployment approval policy of never makes DSH reject before the waterfall, so no dialog can appear regardless of this switch.
  • A timeout, an aborted request signal, an explicit cancel, or plugin unload calls next(); the gate never turns “nobody answered” into allowed-once or a fabricated answer. unavailable is the host's fail-closed outcome and is rejected as a user decision.
  • The dialog polls /takeover/pending every 1 s only while the local 权限接管 switch is on, the session id is real and the document is visible. The first pending request is rendered; a 1 / N badge appears for a queue.
  • Approval offers 仅本次允许 / 拒绝 / 取消; only allowed-once and rejected are submitted, while cancel/Esc/backdrop use the cancel route. Questions render radios for single-select, checkboxes for multi-select and optional free text; submit stays disabled until every question is answered.
  • Both switches are needed: host ui.takeover (default false) opens the gate; the local 权限接管 switch makes the dialog poll. With the host switch off, the gate delegates immediately and there is nothing to show.

Cache proxy (experimental, off by default)

DSH freezes a model request before any adapter sees it: buildRequest() deep-freezes the messages and Object.freezes the request, and the llm/stream waterfall's fallback closes over that object. The one supported place where outgoing content can still be rebuilt is the adapter boundary, so the plugin registers an extra provider route (coordination-proxy) and forwards each request to the real provider after rebuilding it.

Wiring (src/index.ts, src/host/proxy-service.ts, src/host/proxy-adapter.ts, src/host/model-brand.ts):

  • agent/request rewrites the route to coordination-proxy and remembers the real one. Only allowlisted providers (deepseek, deepseek-account, deepseek-official) are intercepted; anything else keeps the route the harness chose.
  • The adapter forwards through ctx.llm.stream with the real provider, so transport, retries, attribution headers and usage reporting stay with the real adapter.
  • ctx.llm.resolveModelInfo(provider, model) supplies the host's model identity; it is classified onto a built-in cache brand (DeepSeek, OpenAI, Anthropic, Google, xAI, Moonshot, Qwen, Zhipu, Mistral, Meta, unknown) with automaticPrefixCache, explicitCacheBreakpoints, minPrefixTokens, effortBreaksCache and stripVolatileHelps.
  • In normalize mode, outgoing content is decorated only when the family has an automatic prefix cache and cache.enabled is on: CacheModule.decorate moves fixed content first and replaces volatile fragments (ISO timestamps, UUIDs, long hex, current-time phrases) with stable placeholders. Explicit-breakpoint families (Anthropic) are never rewritten, because markers — not bytes — decide reuse there. The advisory cacheWarning field is stripped before forwarding.

Security model — the proxy sees every prompt, so it is built to be unable to leak:

  1. no credential access (no ctx.credentials, no token, no Authorization, no API key);
  2. no egress (the adapter module has no imports and no fetch/http/net; forwarding is an in-process call);
  3. no content persistence — proxy.log receives structural events only ({event, provider, model, brand, messages, chars, tools, reason, upstreamProvider, prefix, stable, from, to}), never prompt or answer text;
  4. provider allowlist enforced in both the routing listener and the adapter;
  5. refusal and failure messages name the route only;
  6. opt-in and reversible.

Enable it by creating %DSH_HOME%\coordination\proxy.enable (or DSH_COORDINATION_PROXY=1) and restarting. The proxy then defaults to measure mode: it records baseline metrics and prefix hashes without rewriting content. GET /deepseek-coordination/proxy/status reports counts, ids and hashes only: available, enabled, mode, decorate, upstream, upstreamProvider, model (brand and policy), forwards, refusals, metrics and prefix. Delete the flag file and restart to return to the normal path.

Measure vs normalize

Attaching the proxy and rewriting the request are independent switches. With the proxy enabled, the default measure mode forwards each request with only the real provider route restored; it never calls the cache decorator. To let the decorator run, create a proxy.mode file containing normalize, create a proxy.rewrite marker file, or set DSH_COORDINATION_PROXY_REWRITE=1, then restart. In both modes proxy.log gains a prefix line per forward ({ prefix: '<16 hex>', stable }) and a prefix-churn line ({ from, to }) when the fingerprint changes; metrics aggregates the last 100 requests (requests, samples, inputTokens, cachedInputTokens, hitRate, with DSH's cacheReadTokens surfaced as cachedInputTokens). Read a real session's baseline with curl http://127.0.0.1:<port>/deepseek-coordination/proxy/status, using the port that serves the Web GUI.

Interaction with exact-provider host modules

The rewrite is visible to every agent/request consumer: while the proxy is attached, the route recorded in the request is coordination-proxy, not the real provider. /proxy/status therefore exposes upstreamProvider (the real provider captured before the rewrite) beside upstream. Host modules that resolve credentials or account state by exact provider id can misbehave under that rewrite; the known case is the host's web-search account fallback, which needed a host-side fix (shipped in the 0.2.1-rc.2 patch). ProxyService.compatibility() carries the same list as static data, and the proxy does not probe the host.

Auto-compaction and the token governor

TokenGovernor estimates context (CJK-aware O(n) estimator with a bounded 256-entry memo), plans a budget against contextWindow - reserve, and asks DSH's compactIfNeeded at agent/pre-step when utilisation crosses a threshold. Defaults: soft 0.70, hard 0.88, reserve max(2048, 8% of window) capped at 25%, recentTurns 6, cooldown 30 s, maxPerSession 20.

The soft threshold is editable as a 0.30–0.90 ratio; the hard threshold as 0.30–0.98 and strictly above soft. The old 60/70/80/88% values remain valid choices (0.60, 0.70, 0.80, 0.88) even though the catalog now edits it as a number field with 0.01 precision. Auto compaction is disabled by compaction.auto=false, but an explicit compact command is not governed by that switch.

Fail-safe rules are deliberate: the hook never blocks the step; a missing compaction port, null/undefined result, timeout, throw, spent per-session allowance or unelapsed cooldown all become a no-op, and the agent proceeds to next(). The governor snaps the policy at construction, so a live settings change also rebuilds it. DSH owns the actual safe range and replacement; this plugin only decides when it is worth asking.

File tools, parser and Chain

The file layer is wired as four model-facing tools, alongside the three composer tools:

ToolPurpose
coordination_parseParse a workspace file or supplied text. Exactly one of path/text; returns references, diagnostics, charset, truncation and node cards, never the file body.
coordination_describeRead one NodeCard and optionally summary/description/usage/purpose by handle; never the body.
coordination_chainQuery one bounded relation chain: dependencies, dependents, satisfies, satisfied_by, baseline, prerequisites, unmet, path or cycle. Depth ≤ 8, links ≤ 50, ~1,500 tokens; never an AST or graph object.
coordination_readThe only tool that returns file content. Reads a byte range (end exclusive) or a line range (1-based inclusive), capped at 256 KiB / 2,000 lines / 16k tokens per call.

P0 parsers are lexical and deterministic: JS/TS/JSX (imports, exports, require, dynamic import, symbols, comments), CSS/HTML/Markdown (@import/url(), script/link/img, links/images/headings/front matter/fenced divs/formulas), TeX (theorem-like environments, proofs, labels/refs, math, \input/\include), generic formulas (Markdown/TeX/spreadsheet/MathML/OMML/unknown; no evaluation), and a lexical dependency graph (external filtering, topological order, cycles, levels, isolated vertices). Malformed input produces diagnostics and truncated, not a crash.

Every parsed node is blueprint-only: path, UTF-8 byteStart/byteEnd, 1-based lineStart/lineEnd, sha256:<hex> fingerprint and charset; no text, body, content or AST. The same holds for NodeCard and ChainLink. coordination_read is the single content path; it rejects absolute paths, UNC paths, traversal and symlink escapes, refuses NUL/binary/undecodable content, and hashes what it returns.

LimitValue
Source text per parse1 MiB; prefix parsed and marked truncated
Tokens per parse200,000
AST depth256
Parse wall clock2,000 ms
Diagnostics retained100
Node metadata per parse20,000
Dependency graph20,000 vertices / 100,000 edges, fail-closed
Formulas5,000 per scan / 512 references
Parse cache256 files, LRU keyed path+mtime+size+parserId
Read range256 KiB / 2,000 lines / 16,000 estimated tokens
Chain projectiondepth ≤ 8 / links ≤ 50 / ~1,500 tokens; 50k nodes / 200k edges fail-closed

parser.enabled is read when the file tools are registered; parser limits and chain.depth/links/tokenBudget are captured when the lazy tool runtime creates its ParseService/ChainEngine. A live change through /config therefore does not retune an already-created runtime; it takes effect on the next registration (today a locale change or restart). The workspace root falls back to process.cwd() because the plugin entry does not receive DSH's workspace root; a host whose cwd is not the workspace must pass a root through tool options.

No write or refresh tool exists. The v24 write contract needs expectedFingerprint conflict detection, transactional reparse and range recomputation, explicit charset/BOM changes and a watcher/rename policy; none is implemented, so a writer would risk overwriting concurrent edits or returning stale ranges. coordination_write and coordination_refresh are design/planned.

Data structures

The shared library in src/shared/ is pure ES2022: hash/LRU, nodes, binary/B+ and red-black trees, heaps, stack/deque/queue, ordered maps/sets/skip lists, AST/token stream, directed graph, trie and sparse grid. The current runtime uses:

  • LruList for the token-estimator memo, parse cache, node registry and chain projection cache.
  • BinaryHeap for selectContext, preserving the old total order (value desc → created asc → id byte-asc → input index).
  • RedBlackTree predecessor/successor for numeric agreement; the exact argmax proof is in the adoption document.
  • OrderedSet for first-seen dedupe in comprehension/emotion/permission; Queue for the permission-command token stream.
  • DirectedGraph for the dependency graph and one graph per chain relation.

The second adoption pass is measured and randomized-tested. Its honest caveat: on the 20k-chunk wide synthetic case the heap is not faster than V8 sort (17.7 ms vs 15.9 ms); it wins when the budget fills early and is never worse in result. SparseGrid and BPlusTree are regression-tested in the shared library but not wired into a runtime path; do not infer they are used.

Tools and routes

ToolWhat it returns
coordination_selectionRead or patch the five selections for a session (including command and DSH preset); returns SelectionState with lock, presets and config projection.
coordination_professionRead the current profession record; set a profession only before/without an active task. A locked task returns PROFESSION_LOCKED and leaves the selection unchanged.
coordination_professionlockRead the lock state/profession of the active turn, or of a given turn ordinal.
coordination_parseBody-free parse projection (references, diagnostics, charset, truncation, cards).
coordination_describeBody-free NodeCard and requested metadata fields.
coordination_chainBounded ChainProjection only.
coordination_readThe only content-returning tool; capped byte/line range.

All routes live under /deepseek-coordination; there are 14 paths / 16 method handlers:

MethodPathPurpose
GET/pingLiveness; returns plugin name, pong, current locale.
POST/echoEcho a JSON body (diagnostic).
GET, POST/selectionRead SelectionState; patch the five choices.
GET/presetsDSH permission-preset catalog projected for the dropdown.
POST/permissionApply one DSH preset immediately.
GET, POST/configRead { values, defaults }; apply a flat config patch.
POST/config/compactionCompatibility patch for auto/soft/hard.
GET/takeover/pendingPending approval/question windows for a session.
POST/takeover/answerDeliver a validated human answer; invalid answers keep the window open.
POST/takeover/cancelCancel a window and delegate to the host default.
POST/profession/rebuildEnd the active task and create a replacement with a new profession.
POST/profession/abandonEnd the active task without a replacement.
POST/localeReport the client language; re-registers localized tool descriptions.
GET/stateSelection plus coordination metrics (session, turn, plan, subtask, trace, takeover, schema).

There is no coordination_write, coordination_refresh, outline, findSymbol, searchSummary or commentsOf tool. The four file tools carry inline EN/zh-CN copy because the shared ToolName table has no keys for them yet; the three composer tools use the shared copy table.

Data, privacy and safety

  • The plugin owns an independent SQLite database. It never opens DSH's harness database. The default path is %DSH_HOME%\coordination\coordination.db; database/databasePath are deployment-only and are neither projected nor writable from /config.
  • Parser nodes, NodeCards, ChainLinks and their tool results never carry file bodies, attachments or ASTs. Only coordination_read returns text, and only for the requested range.
  • Preview is the only body-bearing route: workspace-relative only, 64 KiB text cap, user-initiated, never cached or logged; every other graph route stays body-free. Office previews are converted server-side and size-capped; no file is written.
  • The workspace panel is read-only: no edit/rename/delete/create/build; the only non-GET graph route is POST /graph/rebuild, which re-parses known paths.
  • File paths are workspace-relative; absolute paths, drive-rooted paths, UNC paths, .. escapes and symlink escapes are rejected before a read. Binary/NUL/undecodable content is refused rather than guessed.
  • The turn hook records turn metadata and an empty prompt row; it does not mirror the DSH transcript. No file content is copied into the coordination database.
  • Permission presets are written to DSH immediately (full access needs a second confirmation) and are never stored in the offline localStorage copy. Offline replay covers only the five stored selection fields.
  • The optional cache proxy adds no transport and no credential surface: it forwards through DSH's own ctx.llm.stream, traces structural counts only, and refuses providers outside its allowlist.
  • Takeover never auto-approves. Timeout, abort, cancel and unload delegate with next(); only a human decision delivered through the answer route settles a window.
  • Fail-closed behaviour is explicit: invalid takeover answers leave the window open; PROFESSION_LOCKED leaves the selection intact; parser uncertainty is unverifiable; graph/parse overflow is truncated; compaction failure is a no-op; chain unknown never auto-passes.
  • The coordination DB stores task/audit rows (including prompt and trace rows), not credentials or provider secrets. The config projection contains no DSH credential, token or provider key.

Testing, quality and limitations

CheckResult
npm test615 tests, 614 pass, 1 skipped (GC-only), 0 fail, ~3 s on Node 24.21.0
npm run typecheck / npm run test:tscClean
npm run buildHost + client bundles green; MUI "use client" directive warnings are non-fatal
npm run pack:checkOK: the runtime tarball carries the four shipped files
Release CI.github/workflows/release.yml runs typecheck, test:tsc, tests, pack:check and attaches the tarball to a v* GitHub Release

Parser and structure numbers are guards, not promises: a 100k-character parse test stays under 3 s; the data-structure report records B+ tree 10k inserts at 8.3/9.8 ms, skip-list 10k inserts at 6.4 ms, red-black 10k random set/delete at 13.5 ms, sparse grid 10k cells at 5.1 ms, and hashString 100k calls at 4.3 ms on the audit machine. The complexity audit records the ordinal COUNT(*) → MAX(ordinal) change (≈65–69 ms → ≈12–14 ms for 2,000 statements) and route ranking (2,400 → 200 posterior statements for 200 × 12 routes).

Known limitations, stated rather than hidden:

  1. Durable graph is bounded. node/edge/snapshot are now schema 24 and survive a new runtime; rehydration is bounded to the newest 10k nodes / 50k edges, removed symbols are not pruned, and a handle older than the rehydration window is NOT_FOUND.
  2. Domain extraction is parser-level; some projections are still partial. Book/Article/Part/Chapter/Section/Paragraph, Person/Venue, Condition, Sheet/Cell/Range and TeX proof status are emitted and projected onto node cards; docx/xlsx/pptx now parse through a bounded ZIP+OOXML reader, while Publisher/Access stay explicitly unsupported. partOf/condition edges are queryable through coordination_chain; cross-file Book composition and Sign promotion remain deferred.
  3. The core turn pipeline is wired, the wider engines are not. Comprehension → Organization → Plan/score and required Predict rows now run for command=none turns, with the scene policy applied where ports exist. Standalone Emotion/Bayesian/Cognition/Orchestration/Learning/Resource/Score, plan rebuild loops and decompose/dispatch/verify/synthesize remain library-only. Reasoning is DSH-owned and no longer reported as a plugin gap; allowBash, maxIteration and non-writing score thresholds are still recorded as deferred diagnostics, not faked.
  4. Configured caps are live. parser.maxAstDepth, both dependency-graph caps and tools.maxResultBytes are consumed; parser/chain limits retune an existing runtime, and a config change no longer leaves a stale tool runtime.
  5. Workspace root is resolved, not hard-coded. Tool option → service root → host root → sandbox-policy root → process.cwd() only as the last fallback.
  6. parser.enabled still needs registration. The other file-layer limits retune live; turning the parser off fails closed immediately, but adding/removing the four tools requires the next registration (restart).
  7. No browser E2E test. The UI is covered by types, build, the settings-catalog tests and the takeover/bridge/integration tests; visual verification remains manual/screenshot-based.
  8. Node engine is >=22.13.0. node:sqlite is unflagged from 22.13.0/23.4.0; CI and this verification use 24.21.0.
  9. A profile can still record an older package spec. Verify the installed version (dsh --profile <name> --dump-config or the profile's package.json); install the 0.11.0 tarball or link the built checkout rather than assuming a previous install was upgraded.

Repository history and license

0.1.x is dsh-os, a different OS-interaction project, no longer on the branch tip; 0.2.0 became the DSH plugin bundle; 0.3–0.6 moved the UI from Angular to MDUI to plain React to Material UI; 0.7–0.9 added the five dropdowns, i18n, profession lock, takeover, compaction, the P0 parser, the domain model and the shared data structures; 0.10.0 added the settings catalog, the four file tools, the second data-structure pass and the verified tarball; 0.11.0 added durable settings, DSH-owned reasoning and the experimental cache proxy with brand profiles; 0.12.0 added the per-ecosystem domain layer, the chain kind filter, the directory layer and NodeRecord. Earlier states remain in git history and tags.

Apache-2.0 © 2026 Eloy Kim. See LICENSE. Source: github.com/eloyhere/deepseek-coordination.

c-family.ts
module, class, function, method, variable, importation
rustrust.tsmodule, class, enumeration, function, method, variable, importation
phpphp.tsmodule, class, interface, enumeration, function, method, variable, importation
mavenmaven.tsproject, module, dependency (parent is a dependency with label: 'parent')
npmnpm.tsproject, dependency, script (the command body is never stored)
officeoffice.tsdocx: document, chapter, section, paragraph, link; xlsx: workbook, sheet, range, formula; pptx: document, slide; pub/accdb: no nodes, one unsupported-format diagnostic
textsentence.tssentence segmentation and line ranges (coordinates, not nodes)
true
true
false
5000 ms
true
auto
Host rows plus the two local switches; toolbar/locale read-only
scenessix scene profiles, 9 exposed rows each (thinking/effort remain schema-only) and a writing threshold of 0.6Host rows; only the writing score threshold is read by plan.ts
parserenabled true, 1 MiB, 200k tokens, depth 256, 2 s, cache 256, graph 20k/100kenabled + four limits host rows; depth and graph caps planned
chaindepth 8, links 50, tokenBudget 1500Host rows
toolsmaxResultBytes 0Planned/read-only; not consumed
defaultsprofession execution, interaction think, scene dialogue, validation medium, command noneHost rows
  • The cache proxy is experimental and off by default. Its brand profiles are policy defaults, not measurements, and it only rewrites content for families with an automatic prefix cache; the observable gain on a stable session may be near zero, which is why it ships behind a flag and a status endpoint rather than enabled.