dsh-mixxed
dsh-client-ui-filesystem-manager
A customized DeepSeek Harness filetree manager UI plugin.
- Stars
- 0
- Language
- TypeScript
- Created
- Aug 16, 2026
- Updated
- Aug 16, 2026
Introduction
dsh-client-ui-filesystem-manager
English · 中文
A dsh plugin that adds a Files (文件) tab to the conversation window. Pick the tab and the session area becomes a VSCode-style explorer: a file tree of the current workspace on the left, and a file viewer on the right.
Built as a fully out-of-tree plugin — the deepseek-harness source stays untouched. It registers into the same conversation.view ring as the shipped Trajectory tab, serves the tree and file contents over its own HTTP routes (ctx.webServer), and is styled entirely with the dsh design tokens (--dsw-*) and ui-primitives components.
Install
-
Install the plugin from npm (published as
@dsh-mixxed/dsh-client-ui-filesystem-manager):dsh plugin --profile web add @dsh-mixxed/dsh-client-ui-filesystem-managerThe package declares
dsh.bundle(its bundledcordis.patch.yml), sodsh plugin addautomatically appends it to the profile'sdsh.profile.bundleslayer stack and the plugin mounts on the next boot — no manualcordis.patch.ymlediting. -
Restart the profile (new plugins are discovered at boot), open a session, and click the 文件 / Files tab.
Building from source (development / offline)
pnpm install
pnpm run typecheck
pnpm test
pnpm run build
npm pack # produces dsh-mixxed-dsh-client-ui-filesystem-manager-<version>.tgz
dsh plugin --profile <name> add ./dsh-mixxed-dsh-client-ui-filesystem-manager-<version>.tgz
Features
- Third conversation tab: 对话 / 轨迹 / 文件, registered into the
conversation.viewring (order 20, after Trajectory) - VSCode-style split view: draggable divider, left = file tree, right = file viewer
- Lazy file tree: directories expand on demand (one listing request per directory), directories-first stable ordering, indent guides, VSCode-style language glyphs (JS/TS, HTML, CSS, JSON, Shell, scripting, compiled languages, config, and Markdown each use a distinct dsh built-in icon), hidden files shown, empty/loading/error states, refresh button
- Type-aware viewer:
- Markdown (
.md) rendered through the house MarkdownText (no line numbers) - Every other text file (code/JSON included) through the house ReadBlock: VSCode-style line-number gutter + per-extension shiki highlighting (unknown extensions fall back to plain monospace), with a copy button
- Images inlined as base64 (png/jpg/jpeg/gif/webp/svg/bmp/ico/avif)
- Binary files and oversized files get a clear state (with size) and an "open in system app" shortcut
- Markdown (
- Viewer toolbar: refresh, open in system default app, copy relative path, download
- Full-height independent scrolling: the input dialog hides while Files is active; the two panes stretch to the column bottom (level with the app sidebar) and the tree and the file content scroll independently, the content card itself filling the pane with the scrollbar inside it
- Chat links open in the Files tab: read / edit / write tool rows, produced-file chips, and prose file mentions switch to the Files tab and open the file there — workspace-contained paths only; paths outside the workspace keep the system default open
- Per-session caching: listings and file contents are fetched once per session (single-flight);
connection/resetclears the caches; tab re-entry is instant - Workspace-contained access: every request resolves against the session's workspace root through
ctx.fsand enforces canonical containment — no raw path from the browser is ever trusted - i18n: 中文 / English, theme tokens follow the active light/dark theme
Usage notes (harness behavior, accepted as-is)
- The tree always shows the current session's workspace; switching workspace/session rebuilds the tree.
- Listings and contents are cached for the session — file changes on disk appear after a manual refresh (tree header or viewer toolbar).
- Files larger than the text cap (512 KiB by default) are not streamed into the viewer; use "open in system app" instead.
- Viewing is read-only: no edit/write/rename/delete, no code indexing or search.
Verify
dsh --profile <name> --dump-config | Select-String ui-filesystem-manager
The composed config shows the ui-filesystem-manager row, and $DSH_HOME/profiles/<name>/package.json lists @dsh-mixxed/dsh-client-ui-filesystem-manager under dsh.profile.bundles (auto-appended by dsh plugin add).
End-to-end (boot the profile on a spare port, then):
dsh --profile <name> --port 3800 # in one shell
node scripts/e2e.mjs # drives Chrome: tabs → tree → expand → viewer
Config (optional)
Tune the read caps from your profile's own cordis.patch.yml — the user layer is applied after the bundle layer, so an id-targeted patch overrides the bundled mount row:
- id: ui-filesystem-manager
name: "@dsh-mixxed/dsh-client-ui-filesystem-manager"
config:
maxTextBytes: 524288 # text file cap before "file too large" (default 512 KiB)
maxImageBytes: 8388608 # image byte cap for the inline viewer (default 8 MiB)