dsh-file-workbench-lib
master1sun/dsh-file-workbench-lib
File workbench library plugin for DSH, provide file processing capability.
インストール
dsh plugin --profile web add github:master1sun/dsh-file-workbench-libREADME
DSH File Workbench Plugin (Vue 3 + Vite)
🌐 English | 简体中文
Provides three capabilities inside the right-side panel of a DSH session view, all sharing the same workspace root:
- 🗂 File Workbench (tab kind
workbench): a Windows 11 Explorer-style file manager - 📝 File Editor (tab kind
vscode): a CodeMirror multi-tab code editor + project tree - ▶ Terminal: persistent shells via node-pty (ConPTY), a global singleton that survives panel close/reopen
On top of that: Git / SVN management panels, sending files into the session input box as official @path reference chips, a background-task panel, and handling selected files with a sub-agent.
File viewing is delegated to the DSH native right-side viewer (Markdown / syntax-highlighted code / images / PDF / HTML / plain text); use the file editor for in-place editing, or right-click "Edit" in the file list to open the built-in notepad.
Panels & Entry Points
| Panel | Tab kind | Guide entry | Notes |
|---|---|---|---|
| File Workbench | workbench | order 100 | Open from the right-sidebar guide area; auto-navigates to the current session's workspace directory on first open |
| File Editor | vscode | order 101 | Same as above, listed below the File Workbench |
| Terminal | — | — | Toolbar terminal button, or right-click a directory → "Open in Terminal" |
The only entries are the right-sidebar guide cards and tabs; there are no input-box buttons or top drawer anymore.
Feature Overview
🗂 File Workbench (Explorer)
- Single-window Win11 tree: Home / Gallery / This PC drives / Recycle Bin / Favorites / Session files; draggable splitter (default 3:7), command bar + status bar, directory-first case-insensitive sorting.
- Real drive volume labels: reads system volume labels shown as
Label (C:), falling back to a localized "Local Disk (C:)". - View modes: 8 modes — extra-large / large / medium / small icons, list, details, content, tiles; details-view column widths are draggable; toggle extension visibility.
- Search: recursive search of file names and content within the current directory, with case sensitivity / regex support and virtual scrolling; supports cross-file batch replace on content hits.
- CRUD: create file / directory, rename, delete (with confirmation), copy / cut / paste, rubber-band multi-select, batch operations, external drag-and-drop upload, compress / extract.
- Recycle Bin: shares the same UI as the file list (same 8 view modes / sorting / multi-select / rubber band), with operations switched to Restore / Delete permanently / Empty recycle bin.
- Git badges: file status (
?/A/M/D) badges + right-click Git operations. - Notepad: right-click "Edit" opens the built-in text editor (save-as / clipboard / unsaved-changes confirmation).
- Background tasks: long-running jobs like uploads and compression show progress and results in the background-task panel, with a history archive.
- Sub-agent: right-click "Handle with sub-agent" to start an official sub-agent session on the selected files / directories.
- Navigation: back / forward / up / back to session directory, breadcrumb address bar, favorites, session-touched files (real-time via SSE).
📝 File Editor
- Project tree: expansion state and scroll position persisted; single click selects, double click opens; right-click for new file / folder, rename, delete, refresh, add to session.
- Multi-tab editing: CodeMirror 6, languages loaded on demand by extension (TS/JS/JSON/HTML/CSS/Markdown/YAML/XML/Python/SQL/Java/C++/Rust/Go/PHP, plus legacy modes like C#/shell/Ruby; falls back to plain text when nothing matches).
- Tab-bar context menu: close / save & close / close others / close tabs to the right / close all.
- Editor context menu: format content, save;
Ctrl+Ssaves; unsaved tabs confirm before closing; read-only files are clearly marked. - Open folder: two-pane picker (left pane "My Computer + shortcuts", right pane the corresponding folder), supports double-click to drill down, single click to select, plus new-folder creation or direct path input.
- Shares the same global terminal as the file workbench.
▶ Terminal
- Persistent ConPTY shells (node-pty): real console semantics — per-character backspace, immediate enter execution, full-screen TTY programs and CJK output all work; switchable between
cmd/powershell. - Multi-tab (up to 9), one independent backend session per tab; sessions survive panel closes, and reconnecting resumes output.
- Floating windows: draggable, resizable from the bottom-right corner, double-click to reset; minimized windows collapse into the bottom-right dock (persistent across panels, restorable).
- Cleanup on close: on Windows the whole process tree is killed with
taskkill /T, avoiding orphaned npm / python / node processes. - Search & display: Ctrl+F to search output (case-sensitive), font size up/down, clear screen.
- Key bindings:
Ctrl+Ccopies when there's a selection (otherwise passes SIGINT through),Ctrl+Vpaste,Ctrl+Fsearch,Ctrl±/Ctrl+0font size. - Privilege badge: shows whether the current terminal is "Administrator" or "Standard", see Permission model.
- Official terminal backend: for local shells, the process layer (PTY creation / reconnect / cleanup) is delegated to the host's official
ctx.webTerminalsservice when available, with automatic fallback to the plugin's own backend; SSH terminals always use the plugin's own SSH channel.
🌿 Git / SVN Management Panels
Both panels open from the file workbench and the file editor (right-click → open management panel), each organized into sections in a narrow left column:
Git (7 sections)
| Section | Capabilities |
|---|---|
| Changes | staged / unstaged / untracked groups; inline stage, unstage, ignore, discard; stage all; commit (with quick commit) |
| History | commit graph (all / current branch) + commit details (hash / author / time / parents / refs / file list / patch); reset (soft / mixed / hard), revert, cherry-pick |
| Branches | create & switch, rename, local & remote branch list, switch, merge into current, push, delete, checkout remote branch |
| Tags | create, fetch all, publish Release, view, fetch remote tags, push, delete |
| Remotes | add, edit URL, delete |
| Stashes | create, view, apply / delete |
| Command line | built-in git CLI: run any git subcommand and see the output |
Plus per-file diff view / file history / blame, and upstream/downstream ↑ahead ↓behind display.
SVN (3 sections: Changes / Log / Output)
- Update, cleanup, checkout (URL + target directory), add to version control, revert, resolve conflicts, commit (selected or all).
- Per-file diff / blame; working-copy URL and repository root display.
- Ignore uses
svn:ignore(a directory property applied on the parent directory; read-then-idempotently-append). - Clear guidance is shown when the svn CLI is missing or the current directory is not a working copy.
Context menus are generated uniformly by composables/domain/repoMenu.ts (single source of truth); Git offers stage / commit / diff / discard / ignore (writing the repo-root .gitignore), SVN offers open management panel / update / add to version control / ignore.
🧩 External View Injection (Activity Bar)
Both the file editor and the file workbench let external plugins/scripts register their own views via a framework-agnostic Activity Bar registry — no Vue/React required; plain JS works too. Full author guide: docs/activity-bar-plugin.md.
- Two independent registries, exposed as window globals:
- File editor:
window.__dshFileWorkbenchVSCode__.activityBar.register(view) - File workbench:
window.__dshFileWorkbenchWorkbench__.activityBar.register(view)
- File editor:
- Contract: each view is
{ id, title, icon?, order?, mount(el, ctx), when? };mount(el, ctx)renders intoeland may return a cleanup function invoked when the view is switched away or unmounted.ctxexposesprojectDir/theme/activeFilegetters,onProjectChange/onThemeChange/onDidChangeActiveFilesubscriptions, andopenFile/listOpenFiles/openDiff/toast. - Command contribution points (editor, apiVersion ≥ 2): plugins can also register callable actions via
window.__dshFileWorkbenchVSCode__.commands(register/execute/unregister/list/has) — the analogue of VS Code'scommands.registerCommand. Registered commands are inert until something invokes them by id, so they don't mutate editor behavior unprompted. - Status bar items (editor, apiVersion ≥ 2): expose a command as a clickable button in the editor's bottom status bar via
window.__dshFileWorkbenchVSCode__.statusbar.register({ id, text, commandId, tooltip?, order?, when? }); clicking it auto-executescommandIdwith a{ path, projectDir }context. This is the built-in trigger surface for commands — no need to host your own button. - Background tasks (workbench, apiVersion ≥ 3): reuse the workbench's task panel as a generic progress registry via
window.__dshFileWorkbenchWorkbench__.backgroundTasks(start(label, opts?) → { step, updateLabel, done, fail },clearFinished,clearAll). Registered plugin tasks show up in the same bottom-bar task button with history/archives. When an injected view is active, only the local-nav areas of the status bar are dimmed/disabled — the background-task button stays clickable and viewable. - Multi-language titles:
titleaccepts a string or a per-locale object ({ zh, en }), resolved against the page language. - Placement & visibility: in the workbench, registered views appear in an "External injections" nav group under the Recycle Bin; the whole group hides when nothing is registered. While an injected view is active, the top toolbar (WinMenuBar) and the explorer's command bar are disabled (inert + dimmed); the bottom status bar keeps its background-task button usable and only dims the local-nav areas (file info / view switch).
- Idempotent: re-registering the same
idoverwrites (supports hot-update);unregister(id)removes it cleanly. The registry lives at module scope, so panel unmount/remount keeps registrations.
🔗 Session Integration
- Session files: files touched by the current session are pushed in real time via SSE and shown in the nav tree's "Session files" group.
- Add to session: writes a file / directory into the current session input draft as an official DSH structured reference chip (
@path,source: "reference") — not plain text. - Open redirect: clicking files in the session (tool-line paths, artifact lines, body mentions) is redirected to this plugin; falls back to host-native behavior when the workbench isn't mounted.
- Follows the session: switching sessions or a session's working directory change moves the workspace root automatically.
🎨 Settings
Allow operations outside the workspace root (root switch), show hidden files, accent color, UI font size, font family, theme (follow host / dark / light), default view.
Keyboard Shortcuts
Global:
| Key | Action |
|---|---|
? | Open shortcut help (global) |
File list (while focused):
| Key | Action |
|---|---|
Ctrl/Cmd+A | Select all |
Ctrl/Cmd+C / X / V | Copy / cut / paste |
Ctrl/Cmd+F | Focus the filter box |
Ctrl+Shift+N | New folder |
Delete / F2 / F5 | Delete (confirm) / rename / refresh |
Enter | Open file / enter directory |
↑ ↓ Home End | Move selection |
Backspace / Alt+↑ | Go to parent directory |
Alt+← / → | Navigate history back / forward |
File editor & terminal:
| Key | Where | Action |
|---|---|---|
Ctrl/Cmd+S | Editor | Save current tab |
| Tab-bar right click | Editor | Close / save & close / close others / close to the right / close all |
Ctrl+C | Terminal | Copy when there's a selection; otherwise passes SIGINT through |
Ctrl+V | Terminal | Paste |
Ctrl+F | Terminal | Search terminal output |
Ctrl± / Ctrl+0 | Terminal | Increase / decrease / reset font size |
Project Structure
src/
shared/
types.ts shared types (host ↔ client ↔ Vue)
locales.ts zh/en copy dictionary (both must be updated together)
session-files.ts session transcript file parsing
host/ server side (Cordis plugin)
index.ts apply: registers /api/dsh-file-workbench routes + static assets + self-update
updater.ts self-update after startup
fs/
fs-tree.ts list / sort / symlinks / containment guard
fs-search.ts recursive search + cross-file replace
fs-read.ts open / save
fs-zip.ts compress / extract
fs-drives.ts drives & volume labels (Win32_LogicalDisk, 5-min TTL cache)
recycle.ts system recycle bin
routes/
routes.ts route dispatch table
routes-fs.ts file system (list / search / read-write / compress / My Computer)
routes-git.ts Git (status / diff / add / discard / log / branch / tag / remote / stash / ignore)
routes-svn.ts SVN (info / status / run / log / blame)
routes-terminal.ts terminal: persistent ConPTY shells (SSE stream) + host privilege probe /term-env
routes-recycle.ts recycle bin
routes-session-stream.ts session-touched-files SSE
routes-subagent.ts sub-agent
routes-task-archives.ts background task archives
routes-persist.ts preference persistence
routes-util.ts JSON envelope / body parsing / static assets / path validation
store/
root-store.ts workspace root
workbench-store.ts prefs / favorites / layout persistence
subagent/subagent.ts official sub-agent sessions
client/ DSH client bridge (TSX, registered into the right sidebar; injects Vue assets + mounts)
index.tsx apply: registers the two right-sidebar tabs, redirects file opens, injects Vue assets, reference channel
RightPaneBridge.tsx mounts the Vue workbench / editor body into the right-panel container
ComposerBridge.tsx session input reference seat (official `@path` chip writing)
TabMenuBridge.tsx right-sidebar tab menu additions (new editor / float window)
OfficialTerminalBridge.ts official terminal bridge: local terminals via host ctx.webTerminals
api.ts "open tab" bridge
vue/ Vue 3 + Vite frontend
main.ts entry: right-panel mounting + global terminal mounted persistently (on body)
App.vue file workbench single-window shell
styles.css global theme variables & base styles
components/
common/ WinMenuBar / NavPathBar / Icon / ContextMenu / ConfirmDialog / ShortcutHelpDialog
business/explorer/ ExplorerPane (two panes + splitter), CommandBar, NavPane, FileListPane (list / recycle bin),
ThisPcPane, SearchPane, StatusBar, BgTaskPanel, TxtEditor
business/vscode/ VSCodePane, ProjectTree, TabBar, CodeEditor, FolderPickerDialog, langResolver
business/git/ GitPanel, GitDiffView, GitGraphList, SvnPanel, QuickCommit
business/terminal/ TerminalHost (global singleton host), TerminalDialog (floating / docked)
settings/ SettingsDialog
composables/
core/ useApi, settings, theme, i18n, dialog, fileTaskMeta
domain/ git, gitGraph, svn, repoMenu (single source for context menus), terminalStore,
officialTerm (official terminal bridge accessor), driveName
session/ sessionSse, tasks, listStatus
ui/ icons, clipboard, dnd, virtual
stores/ workbench, explorer, fileCommands, vscode, activityBar (external view-injection registry)
types/ auto-imports.d.ts, components.d.ts
Development
Prerequisites: Node ≥ 20, npm (or pnpm).
| Command | Purpose |
|---|---|
npm run dev:vue | Run the Vue app standalone for development (mounts #app itself; pair with a running host) |
npm run build:vue | Build only the Vue bundle (dist/) |
npm run typecheck | vue-tsc --noEmit |
npm run build | Full build: Vite (Vue) + esbuild (host/client) → lib/ |
npm run build:dev | Same, with --dev |
npm run sync | Sync lib/ into the web profile |
npm run deploy | build:dev + sync |
The API base defaults to /api/dsh-file-workbench and can be overridden with the VITE_API_BASE
environment variable (e.g. during development, point it at http://localhost:xxxx/api/dsh-file-workbench).
What a change affects (affects how you debug):
- Only
src/vue/**orsrc/shared/locales.ts→ build + sync, then hard-refresh the browser. - Changes in
src/host/**orsrc/client/**(e.g. new routes) → must restartdsh web.
Installing into DSH (web profile)
npm run build && npm run sync # build and sync the bundle into the web profile
After installing, run npm install inside the profile (so cordis.patch.yml takes effect),
restart dsh web, and hard-refresh the browser (Cmd/Ctrl+Shift+R).
If
dsh webdoesn't already include the mount entry for this plugin, append the following to~/.dsh/profiles/web/cordis.patch.yml:- insert: - id: dsh-file-workbench name: 'dsh-file-workbench'
Usage
- Click "File Workbench" or "File Editor" in the DSH right-sidebar guide area (the first open auto-navigates to the current session's workspace directory).
- Workbench: pick a location in the left nav tree; double-click folders on the right to enter, double-click files to open them in the DSH right-side viewer.
- Editor: pick a project directory via the toolbar "Open folder" → double-click files in the
project tree → edit across tabs,
Ctrl+Sto save. - Terminal: open via the toolbar terminal button; minimized windows collapse into the bottom-right dock; click to restore.
?shows the shortcut help.
Permission Model (Terminal Administrator Mode)
Terminal shells are spawned by the host via ConPTY, and child processes inherit the token of
the dsh web process — so "do commands in the terminal have administrator rights" equals
"was dsh web started as administrator".
- Getting an administrator terminal: run
dsh webas administrator (right-click the terminal/shortcut → "Run as administrator"); then all terminals in the panel have administrator rights. - Badge: the terminal tab bar shows "Administrator / Standard"; hover for details, click for
guidance. The probe is provided by the host's
GET /term-env(on Windows, determined by the integrity-level SID fromwhoami /groups; on POSIX,uid === 0). - Why the plugin can't spawn a single elevated terminal: on Windows elevation must go through
UAC, and a process elevated via ShellExecute /
runascannot attach to a ConPTY pseudo-console, so the plugin cannot elevate a single terminal; the only viable path is elevating the host itself. - Alternatives (not implemented): per-command elevation via
sudo.exe(requires Windows sudo enabled in inline mode), or a host-registered high-privilege helper bridged over a named pipe (introduces a self-built elevation channel with a large security surface).
Security
- All read/write paths first pass a root containment guard (re-checked after symlink resolution), rejecting privilege escalation and path traversal.
- Outside the workspace root everything is read-only by default; the root switch in settings must be enabled to allow writes.
- Search does not descend into symlinked directories (loop-safe) and has budgets on visited and matched file counts.
- Terminal working directories go through the same protected-path validation; terminating a session cleans up the whole process tree.
- Persistence only writes whitelisted keys (prefs / favorites / layout) under
{DSH_HOME|~/.dsh}/fileworkbench/.
Dependencies
- Vue 3 + Vite (frontend); React (DSH right-sidebar bridge, provided by the host); esbuild (host/client build).
element-plus(UI components);@xterm/xterm+ fit / search / web-links addons (terminal rendering).- CodeMirror 6 (editor:
@codemirror/*language packages loaded on demand). node-pty(ConPTY interactive terminal, a native module; the terminal is unavailable if missing).fflate(compress / extract);fzstd(decompress zstd session transcripts).- Reuses peers
@deepseek-ai/cordisand@deepseek-ai/dsh-host-webserver.
License
MIT