dsh-web
zhu1090093659
DeepSeek Harness (DSH) Web 插件聚合生态 · 万物皆插件,通过创意工坊分发||DeepSeek Harness (DSH) Web Plugin Aggregation Ecosystem · Everything is a plugin, distributed via the Creative Workshop
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:chendefine/dsh-sidebar-superdoc-docx
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
English | 中文
Open and edit .docx files directly in the DSH web GUI's better-sidebar editor, powered by SuperDoc — a browser-native DOCX editor that reads and writes the real OOXML (no server-side document service needed).
Dependency: this plugin registers its file viewer with dsh-better-sidebar (
>= 0.13.0) — a mandatory peer dependency. Without it, the viewer never appears. Install it first (or together with this plugin).⚠️ License notice: this plugin's own code is MIT, but it integrates AGPL-3.0
superdocand the proprietary-licensed@superdoc/docx-engineat runtime — installing it means accepting those terms. See License below and THIRD-PARTY-NOTICES.md.
.docx in the sidebar with comments and tracked changes; three
open modes selectable in the settings page: editing / suggesting / viewing.Save button exports the edited document and atomically overwrites the opened
file through a dedicated route (tmp + rename, never a half-written state); unsaved edits show a ● dot.replaceFile); a dirty editor only shows a banner with a manual Reload — your edits are never silently
dropped.node_modules: no CDN traffic, no third-party document service,
telemetry off by default. Fully offline after pnpm install..docx in the session; you see the new
version in the sidebar within seconds, polish it by hand, save — and the agent's next turn works from the
latest version. A two-way loop without interruptions.suggesting mode; comments and suggestions land as tracked changes..docx in the file tree and see the
paginated document, with a download link one click away.>= 20;web profile;dsh-better-sidebar >= 0.13.0 installed in the same profile (see the dependency note above).The package is published on npmjs as dsh-sidebar-superdoc-docx:
dsh plugin --profile web add dsh-better-sidebar dsh-sidebar-superdoc-docx
Or by hand: edit the profile's package.json (e.g. ~/.dsh/profiles/web/package.json), add the two
npm dependencies and the bundle entries, then run pnpm install in the profile directory:
{
"dependencies": {
"dsh-better-sidebar": ">=0.13.0",
"dsh-sidebar-superdoc-docx": "^0.1.0"
},
"dsh": { "profile": { "bundles": ["…", "dsh-better-sidebar", "dsh-sidebar-superdoc-docx"] } }
}
Finally restart dsh web (the host half must reload) and hard-refresh the browser (Ctrl/Cmd+Shift+R).
dsh plugin --profile web add github:chendefine/dsh-sidebar-superdoc-docx
For local development, clone, build, and link:
git clone https://github.com/chendefine/dsh-sidebar-superdoc-docx
cd dsh-sidebar-superdoc-docx
pnpm install
pnpm build # → lib/index.js + lib/client.js + lib/types
then, in the profile's package.json, point the dependency at the clone and run pnpm install
in the profile directory:
{
"dependencies": {
"dsh-sidebar-superdoc-docx": "link:/absolute/path/to/dsh-sidebar-superdoc-docx"
}
}
cordis.patch.yml of the profile)- id: dsh-sidebar-superdoc-docx
config:
fileLimitMb: 100 # save-route size cap in MB, default 100
allowOutsideWorkspace: false # allow saving files resolved outside the session cwd, default false
Click any .docx in the sidebar file tree — it opens in the DOCX (SuperDoc) viewer instead of the built-in
code/download viewers.
Under Settings → Side cards → File preview → DOCX (SuperDoc), the gear exposes the "open mode" select:
editing / suggesting / viewing. The choice persists in pluginSettings['superdoc:docx'].mode and takes effect
immediately (the editor remounts in the new mode); viewing also hides the save button.
● Unsaved changes; click Save to export and atomically write back to the
opened path;replaceFile,
re-fitting the zoom;Reload (reloading
discards the current unsaved edits).| Viewer | id | priority |
|---|---|---|
| built-in code viewer | code |
-100 |
| built-in download viewer | binary-download |
-50 |
| office preview plugin | docx |
0 |
| OnlyOffice plugin | onlyoffice:docx |
10 |
| this plugin | superdoc:docx |
10 |
Ties (e.g. with OnlyOffice) break by registration order. Every viewer can be toggled individually under Settings → Side cards → File preview without affecting the others.
browser (client half, tiny CJS bundle via window.__ModuleLoader__)
└─ ctx.betterSidebar.registerFileViewer('superdoc:docx', exts:['docx'], priority:10, fetchStrategy:'mediaUrl')
└─ SuperDocView: <script src="/sidebar/superdoc/assets/superdoc.min.js"> (global `SuperDoc`)
reads: fetch(/sidebar/file?sessionId=&path=) → Blob → new SuperDoc({ document: blob, contained: true })
saves: superdoc.export({triggerDownload:false}) → Blob → PUT /sidebar/superdoc/save?sessionId=&path=
node (host half, 4 fenced routes)
├─ GET /sidebar/superdoc/info versions / health / cache-bust seed
├─ GET /sidebar/superdoc/assets/<file> superdoc/dist-cdn (closed whitelist)
├─ GET /sidebar/superdoc/engine/dist-cdn/<path> @superdoc/docx-engine/dist-cdn mirror (engine + workers)
└─ PUT /sidebar/superdoc/save raw DOCX bytes → atomic write inside the session cwd
superdoc@2.10.0 + @superdoc/docx-engine@0.9.0 (per package.json; the info route
reports the installed versions and doubles as the cache-bust seed).Before the script loads, the client sets globalThis.SUPERDOC_ENGINE_CDN_BASE_URL = '/sidebar/superdoc/engine',
pointing SuperDoc's engine resolver at this plugin's route. The engine then dynamic-imports
…/dist-cdn/docx-engine.es.js and resolves its web workers relative to that same-origin URL — browsers
refuse cross-origin worker creation, and otherwise jsdelivr would become a runtime dependency. That is the entire
reason the host half mirrors the dist-cdn tree.
src/trust-fence.ts, behaviorally identical to better-sidebar's): the Host header must be
loopback or a trusted authority from webRuntime.trustedHosts; sec-fetch-site: cross-site and mismatched
Origins are refused — a DNS-rebinding / cross-site defense, not authentication.src/paths.ts + the save route): absolute paths only; isWithin compares path segments
(/a/bc is not within /a/b); the parent directory is realpath-checked to close symlink escapes; .docx
only; bodies above fileLimitMb get a 413; writes go through tmp + rename atomic replacement.src/assets.ts): the superdoc build exposes a closed whitelist of 3 files; engine
subpaths pass a shape check, reject ./.. segments, and must realpath inside dist-cdn as regular files.telemetry: { enabled: false }); the plugin keeps no state on disk.src/
index.ts host half: build & register the 4 routes (buildRoutes is pure, test-friendly)
assets.ts node_modules asset discovery / whitelists / realpath containment / content types
config.ts config resolution (fileLimitMb, allowOutsideWorkspace; plain TS, zero deps)
paths.ts absolute-path requirement + segment-aware containment + symlink-safe parent realpath
trust-fence.ts browser trust fence (copied, not imported — plugins must not depend on upstream internals)
wire.ts {ok,...} / {ok:false,error:{code,message}} JSON shape + size-capped raw-body reader
client/
index.ts client half: register the superdoc:docx viewer + attach dictionaries
SuperDocView.tsx the editor component (mount / save state machine / disk poll / fit-to-pane zoom)
loader.ts runtime loader (script/stylesheet singletons, engine base URL, contained layout CSS)
settings.ts open-mode read (validated, falls back to editing)
urls.ts URL builders for /sidebar/file and the save route (better-sidebar request contract)
i18n.ts / locales.ts / icons.tsx zh/en dictionaries, registration, icons
tests/ vitest: routes / save-flow / viewers / trust-fence / locales
lib/index.js, ESM (es2023), zero runtime dependencies;lib/client.js — a CJS bundle registered via window.__ModuleLoader__.load({ id, factory }), the
official external client-plugin delivery format (same shape as dsh-sidebar-onlyoffice and
dsh-web-search-aggregation);<script>
(structurally identical to how onlyoffice loads its api.js).tsdown.config.ts ships a rolldown plugin that fails the build when the client bundle imports any Node builtin
or value-imports @deepseek-ai/*; React / react-dom / cordis stay external and come from the host's module
table. The browser half must be self-contained.
RouteContext,
ClientContextFace) — external plugins must not reach into the monorepo's Context augmentation graph;{ok:...} / {ok:false,error:{code,message}} (aligned with better-sidebar's wire
format); error codes: forbidden / method-error / bad-request / not-found / fs-error / internal;superdoc:docx) to avoid clashes with the builtins and onlyoffice:docx;
priority 10 beats the builtins; fetchStrategy: 'mediaUrl';dshSidebarSuperdoc namespace;fs.write is UTF-8-text-only, so binary
exports must go through it.pnpm test (vitest run) covers:
| File | Coverage |
|---|---|
routes.test.ts |
the 4 routes: whitelist hits / traversal & symlink refusals / workspace fence on & off / 413 / 405 / 403 |
save-flow.test.ts |
save state machine: hint clears after a successful save, in-flight edits stay unsaved, header buttons position-stable |
viewers.test.ts |
viewer contract: id / exts / priority / fetchStrategy / settings row; no id clash with existing viewers |
trust-fence.test.ts |
loopback & trusted authorities pass; unknown hosts / cross-site markers / mismatched origins refused |
locales.test.ts |
zh/en key parity, non-empty values, unique namespace |
pnpm typecheck # tsc --noEmit
pnpm test # vitest run
pnpm build # host ESM + client ModuleLoader bundle (purity gate enforced)
.docx (SuperDoc does not open legacy .doc).● unsaved dot.workspaceFence is disabled, files outside the workspace can be opened through the media
route, but saving them still requires allowOutsideWorkspace: true here.@superdoc-dev/fonts (not wired up here).This plugin's code is MIT. It integrates (unmodified, installed by pnpm install and served verbatim by its
routes) two SuperDoc components:
| Package | License | Note |
|---|---|---|
superdoc |
AGPL-3.0 | unmodified npm artifact; network-service use triggers AGPL source-offer duties |
@superdoc/docx-engine |
Proprietary (DOCX Engine Proprietary License) | without a commercial agreement, use is limited to SuperDoc-dependent, AGPL-permitted purposes (evaluation/development/testing); commercial use needs a SuperDoc license |
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: dsh-better-sidebar。