# DSH Workbench — VS Code-style Three-Column Layout Plugin [中文](README.md) | English Inspired by [microsoft/vscode](https://github.com/microsoft/vscode), this plugin adds a workbench experience to the DeepSeek Harness (DSH) Web GUI: - **Docked Explorer file tree on the right** (official VS Code seti file-type icons, expand/collapse, new file/folder, refresh, collapse all, draggable width, collapsible panel) - **Click a file to switch the center column to a code editor** (monaco-editor 0.52.2 — the VS Code editor core; multi-tab, syntax highlighting, minimap, Ctrl+S, dirty markers, save-conflict "Reload / Overwrite") - **Markdown render preview**: opening a `.md` file shows a "Preview" toggle in the tab bar — one click switches to a rendered view (headings/lists/tables/code blocks/quotes/task lists/links/images) that refreshes live as you edit; built-in self-contained renderer with no extra dependencies - **Editor fills the whole column** (the input box / dock strip auto-hides while editing; switch back via "Back to chat" or the top "Chat" tab) - **Safety boundary**: every file operation goes through DSH's `ctx.fs` service with a double fence inside the workspace sandbox — out-of-bounds paths are rejected; writes use version-number CAS to prevent overwrites ``` ┌─────────┬──────────────────────────┬────────────┐ │ Sidebar │ Center: chat ⇄ files │ Right: │ │ (stock) │ click file → Monaco │ Explorer │ └─────────┴──────────────────────────┴────────────┘ ``` ## Architecture | File | Role | |---|---| | `index.js` | Host half (Cordis plugin): registers the `/wb/*` static-asset route + `/wb/api/` file operations (describe/listDir/readFile/writeFile/createFile/createDir/assetText) with the workspace fence | | `client.js` | Client half (browser plugin bundle): bootstraps loading `/wb/workbench-client.js` | | `assets/workbench-client.js` | UI bundle: ExplorerRoot (right column, `explorer` slot) + EditorView (center column, `workbench.editor` view in `conversation.view`) | | `assets/vs/` | monaco-editor distribution (generated by `npm run setup:assets`, not committed) | | `assets/seti.*` | seti icon font and generated assets (`npm run generate:seti`) | | `patches/*.patch` | Three in-place patches to the DSH checkout packages (the three-column layout depends on them) | | `scripts/*.mjs` | Asset download / icon generation / patch application / profile install | | `dynamic/` | In-session dynamic plugin form (for cordis_define), optional | The three patches (`patches/`, generated against DSH `0.1.0-rc.6`): 1. `ui-layout.patch` — adds a 4th grid track `explorer` (240–420px, default 300) to AppFrame + the `explorer` slot + a drag handle + the `toggleExplorer` service method 2. `ui-conversation.patch` — exposes `window.__DSH_CONV_BRIDGE__[sessionId].setView`, so clicking a file switches the center view automatically 3. `ui-sidebar.patch` — mounts the UI bundle on page load (self-healing on refresh) ## Installation Prerequisites: Node.js ≥ 18, git, network access to an npm registry. ```bash git clone dsh-workbench cd dsh-workbench # 1. Download monaco assets and generate seti icons (~13MB) npm run setup:assets # 2. Install into a DSH profile (the /wb route and client bootstrap load on # the next `dsh web` restart) node scripts/install-profile.mjs --profile web # 3. Apply the three-column layout patches to the current DSH checkout # (without them you only get floating windows / no right column — see # "Patches" below) node scripts/apply-patches.mjs --checkout # Without --checkout it auto-detects the checkout under ~/.npm-cache/_npx ``` Then **restart `dsh web`** and **hard-refresh (Ctrl+F5)** the page. > Checkout root: the directory that contains `node_modules/@deepseek-ai/` (npx > installs usually live at `~/.npm-cache/_npx//`; on this machine, > `C:\Users\\.npm-cache\_npx\1e7f6d9597241db0`). ## Patches (why they exist) DSH's client shell exposes no public extension point for a "persistent right column + click-file-to-switch-the-center-view" layout: - The right column needs a new grid track in the layout shell (the `explorer` slot) — done by `ui-layout.patch` - The active-view switch in the center view ring (`conversation.view`) is private state — exposed by `ui-conversation.patch` The patches modify the checkout's client bundles in place (DSH reads them per request with `cache-control: no-cache`, so a hard refresh picks them up — no rebuild required). They were generated against `0.1.0-rc.6`; if they stop applying after a DSH upgrade, regenerate them against the new bundles (`git diff --no-index `). ## Usage 1. Hard-refresh the page → the file tree appears on the right 2. Click a directory to expand, click a file → the center switches to the Monaco editor and the input box hides 3. Ctrl+S saves; switch views via the "Chat / Code" tabs or the "Back to chat" button 4. Explorer header: new file/folder, refresh, collapse all, `«` to collapse the panel; drag its left edge to resize; **when collapsed a 28px rail stays on the right — click it to reopen** ## Workspace Following The file-tree root = **the active session's workspace** (that session's `header.cwd`, its own sandbox boundary): - Switch to whichever workspace/session you're working in, and the right column shows that workspace's files; editor tabs and the tree rebuild automatically on switch - The client injects the active session id into every `/wb/api/*` call; the server resolves the fence root via `sandboxPolicy.resolve({ session })` - With no active session it falls back to the deployment root (the `sandboxPolicy` fallback root, which you can pin via the profile's `cordis.patch.yml`) > Note: session-scoped resolution requires the host half to inject the `sessions` service. After changing `index.js` / `client.js`, **restart `dsh web`** and hard-refresh. ## Uninstall 1. Remove the `workbench` row under `- insert:` in `/profiles/web/cordis.patch.yml`, then restart `dsh web` 2. Delete `/profiles/web/node_modules/@dsh-local/dsh-workbench/` 3. Revert the patches: reinstall the packages (`npm i @deepseek-ai/dsh-client-ui-{layout,conversation,sidebar}@0.1.0-rc.6` and overwrite the checkout's `lib/client.js`), or `git apply -R patches/*.patch` ## Known Limitations - `ctx.fs` has no rename/delete contract → renaming/deleting files is not supported yet - Binary files are read-only rejected; single-file read cap is 5MB - With no session open the right column is visible but clicking a file won't switch the center view (the view ring is session-scoped); the tree then shows the deployment root - File-tree root = the active session's workspace (falls back to the `sandboxPolicy` fallback root when no session, pinnable via profile patch) - The Markdown preview is a self-contained GFM subset: headings, bold/italic, inline + fenced code, lists and task lists, blockquotes, tables, links, images, hr; nested lists, footnotes, and raw HTML passthrough are not supported (HTML is always escaped to prevent injection) ## Credits & License - [microsoft/vscode](https://github.com/microsoft/vscode) (Explorer design reference; seti icons and theme data, MIT) - [microsoft/monaco-editor](https://github.com/microsoft/monaco-editor) (MIT) - [jesseweed/seti-ui](https://github.com/jesseweed/seti-ui) (seti font upstream, MIT) - This plugin is MIT Licensed