From 23b1b564d70b8bfea445b11cc810b2fd16be0572 Mon Sep 17 00:00:00 2001 From: Menghuan1918 Date: Thu, 13 Aug 2026 20:19:56 +0800 Subject: [PATCH] =?UTF-8?q?docs:=20=E6=96=B0=E5=A2=9E=E8=8B=B1=E6=96=87=20?= =?UTF-8?q?README=5FEN.md=EF=BC=8C=E4=BC=98=E5=8C=96=E5=AE=89=E8=A3=85?= =?UTF-8?q?=E6=8C=87=E5=BC=95=EF=BC=88@deepseek-ai/*=20=E5=B7=B2=E5=85=AC?= =?UTF-8?q?=E5=BC=80=E3=80=81plugin-registry=20=E6=8A=98=E5=8F=A0=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 16 +++--- README_EN.md | 135 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+), 7 deletions(-) create mode 100644 README_EN.md diff --git a/README.md b/README.md index 129d2ba..b95a7ad 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # dsh-better-sidebar +[中文](./README.md) · [English](./README_EN.md) + > 一个插件,一套完整工作台: > > 文件管理、编辑预览、内嵌浏览器、真实终端、Git 面板、后台任务页——**右侧栏 + 底部面板双工作台**,一个插件全部搞定。 @@ -40,7 +42,7 @@ https://github.com/user-attachments/assets/23187822-047e-45cc-b480-fe997bd55b86 ## 🚀 安装 -前置:已安装 DSH(`dsh web` 可运行),Node.js ≥ 20、pnpm ≥ 10。把下面提示词**整段**发给 DSH 即可自动完成克隆、构建、注册与安装: +前置:已安装 DSH(`dsh web` 可运行),Node.js ≥ 20、pnpm ≥ 10。`@deepseek-ai/*` 已发布到 npm,`pnpm install` 直接解析、无需令牌。把下面提示词**整段**发给 DSH 即可自动完成克隆、构建、注册与安装: ```text 请帮我把 dsh-better-sidebar 插件安装到我的 web profile(插件 = VSCode 风格右侧侧边栏,仓库 https://github.com/dsh-external/DSH-better-sidebar): @@ -48,7 +50,6 @@ https://github.com/user-attachments/assets/23187822-047e-45cc-b480-fe997bd55b86 1. 克隆并构建: git clone https://github.com/dsh-external/DSH-better-sidebar.git ~/Code/DSH-better-sidebar cd ~/Code/DSH-better-sidebar && pnpm install && pnpm build - (@deepseek-ai/* 从 npm 解析(0.0.1-rc.? 预发布版);若 401/404,用安装者自己的只读令牌配置 ~/.npmrc,或把 devDependencies 改回指向自己 ~/.dsh/source/current 的 link:,不要继续) 2. 注册到 web profile: a. ~/.dsh/profiles/web/package.json 的 dependencies 加 "dsh-better-sidebar": "link:<第 1 步克隆目录的绝对路径>" b. ~/.dsh/profiles/web/cordis.patch.yml 追加: @@ -64,12 +65,13 @@ https://github.com/user-attachments/assets/23187822-047e-45cc-b480-fe997bd55b86 ### 更新 ```text -1. cd ~/Code/DSH-better-sidebar && git pull && pnpm install && pnpm build(401/404 处理同上) +1. cd ~/Code/DSH-better-sidebar && git pull && pnpm install && pnpm build 2. 核对注册仍有效(缺失才补):profile package.json 的 link: 依赖 + cordis.patch.yml 挂载行 3. 仅 client(src/client/*)→ 硬刷新即可;含 host(src/index.ts、src/config.ts 等)→ 重启 DSH + 硬刷新 ``` -### 通过 plugin-registry 安装(可选,与上述二选一) +
+通过 plugin-registry 安装(可选,与上述二选一) 前置:DSH 已集成 [plugin-registry](https://github.com/dsh-external/plugin-registry)(`dsh registry` 可用)。**同时启用两个通道会双挂载**(Node 半挂两次、页面两个侧边栏)。 @@ -83,6 +85,8 @@ dsh registry enable dsh-external/dsh-better-sidebar 更新:`git pull && pnpm install && pnpm build` → `node scripts/package-registry.mjs` → `dsh registry uninstall/install/enable`。切换通道前先移除另一通道的挂载。 +
+ ## 🔌 服务化:注册 tab 与文件预览器 从 v0.4.0 起暴露 `ctx.betterSidebar` 服务,其他插件可注册侧边栏页面与文件预览器(内置 7 tab + 9 viewer 也走同一服务,吃自己的狗粮): @@ -102,9 +106,7 @@ export function apply(ctx: Context) { ## 🛠️ 开发与构建 ```sh -pnpm install # @deepseek-ai/* 从 npm 解析(^0.0.1-rc.1),需安装者自己的只读令牌: - # ~/.npmrc 配 //registry.npmjs.org/:_authToken=<自己的令牌>(勿写进仓库), - # 或改 devDependencies 为 link: 指向自己的 ~/.dsh/source/current +pnpm install # @deepseek-ai/* 已发布到 npm(^0.0.1-rc.1),直接解析、无需令牌 pnpm typecheck # tsc --noEmit pnpm build # → lib/index.js + lib/invariant.js + lib/client.js + lib/client-registry.js + lib/types pnpm test # vitest(含 manifest 一致性守卫,需先 build) diff --git a/README_EN.md b/README_EN.md new file mode 100644 index 0000000..9fea553 --- /dev/null +++ b/README_EN.md @@ -0,0 +1,135 @@ +# dsh-better-sidebar + +[中文](./README.md) · [English](./README_EN.md) + +> One plugin, one complete workbench: +> +> File management, edit & preview, embedded browser, real terminal, Git panel, background tasks — **dual workbench: right sidebar + bottom panel**, all in one plugin. +> +> Tabs are freely draggable; third-party plugins can register new tab pages and file viewers. + +https://github.com/user-attachments/assets/23187822-047e-45cc-b480-fe997bd55b86 + +6c4293e1bec2e935031bf0e986d6ec65 + +## ✨ Features + +- **🗂️ File Explorer**: lazy-loading directory tree (root = session cwd), click to open in the sidebar, `@file` reference at end of line into the input box, right-click to copy path +- **📝 Edit & Preview**: CodeMirror 6 multi-language highlighting + Ctrl/Cmd+S atomic save; inline preview for images / Markdown (preview/edit toggle) / HTML (sandboxed iframe preview, relative resources loadable) / PDF / Word / Excel / PPT; drafts survive tab switches +- **⚡ Client-side Lazy Loading**: heavy dependencies (Office / terminal / code editor) are chunked and loaded on demand — only ~325KB core is fetched at startup; Univer (~20MB) is fetched only when opening .xlsx, the docx viewer only when opening .docx, xterm only when opening a terminal; brief loading on first open, then instant (see `docs/plans/2026-08-12-lazy-chunks-design.md`) +- **🌐 Browser**: embedded web browsing tabs (multiple), back/forward/refresh + "Open in browser"; pages run in a **sandboxed iframe** (opaque origin: cannot access UI data or local files, rejects localhost and other local addresses); the UI shows sandbox status live and can be temporarily unlocked (red warning when off); sites that refuse embedding (X-Frame-Options) show a reason panel; http(s) links in chat/UI open in the sidebar by default (panel auto-expands when collapsed) +- **💻 Terminal**: xterm.js + node-pty real shell (max 3 UI instances per session), tab keep-alive with reconnect/replay; optionally injects 8 `terminal_*` tools for the model +- **🌿 Git Panel**: real diff + VSCode-style diff tabs, lazy-loaded history, right-click to stage/discard/commit/revert/pick +- **🧩 Background Tasks**: full agent topology of the main session, click-through to execution records, live tool-call polling, auto-expand for new subagents; background tasks shown on the same page (all background tasks in the current tree, bash/pwsh type badges + exit codes, click to view live output — auto-follows the bottom, non-consuming peek that doesn't disturb the model's `job_output`; double-click confirm to force-kill) +- **🪟 Bottom Panel**: an independent second workbench (same kind of tabs as the right sidebar) that only squeezes the middle Agent output area without covering the left/right sidebars; auto-opens a new terminal on first expand (can be disabled in the terminal card's secondary settings); one-click collapse via the top-right x +- **📱 Mobile**: at viewport < 768px (true mobile width, not the host's 1024 breakpoint) only the right sidebar shows — when entering narrow screens, bottom-panel tabs merge directly into the right sidebar's tab bar, leaving a single toggle at top-right and a full-width drawer panel; new sessions start collapsed; files/external links in chat auto-expand without squeezing the conversation area +- **🔧 Split-pane Workbench**: drag tabs to split/merge panes (cross-panel dragging supported), divider to adjust ratios; persistent button cluster at top-right (bottom bar + side pull glyph) to collapse/expand both panels; the two panels share a corner double-direction drag to resize, rAF direct-DOM writes keep it smooth +- **🔁 Session Isolation**: layout/panes/tabs/panel states persisted per session (localStorage), stale state auto-purged; chat "produced files" open in the sidebar (auto-expands panels when collapsed) +- **⚙️ Declarative Settings**: the "Side Cards" section of the settings page renders a registry-driven feature list (small card grid, highlighted = enabled), each toggleable independently; secondary settings (auto-expand subagents, terminal tools, auto-open terminal on first bottom-panel expand, sandbox switches, etc.) are edited in a native dialog via the gear button +- **🔌 Service API**: exposes the `ctx.betterSidebar` service — other plugins can register sidebar tabs and file viewers (the 7 built-in tabs + 9 viewers go through the same service, see [AGENTS.md](./AGENTS.md)) +- **🌏 i18n**: UI text follows DSH's language setting (zh/en) with live switching — Host preference takes priority over browser language, dictionaries registered into DSH's i18n namespace; no refresh needed + +## ⌨️ Keyboard Shortcuts + +| Action | Keys | +|---|---| +| Save edits | `Ctrl/Cmd + S` | +| Git commit | `Ctrl + Enter` | +| Close tab | Middle mouse button | +| Split / merge panes | Drag tab to pane edge / middle | +| Reference file to input | Hover the `@file` button at end of line | +| Copy file path | Right-click row → copy relative/absolute path | + +## 🚀 Installation + +Prerequisites: DSH installed (`dsh web` works), Node.js ≥ 20, pnpm ≥ 10. `@deepseek-ai/*` packages are published to npm and resolved directly by `pnpm install` — no token needed. Send the following prompt **in full** to DSH and it will automatically clone, build, register and install: + +```text +Please install the dsh-better-sidebar plugin into my web profile (plugin = VSCode-style right sidebar, repo https://github.com/dsh-external/DSH-better-sidebar): + +1. Clone and build: + git clone https://github.com/dsh-external/DSH-better-sidebar.git ~/Code/DSH-better-sidebar + cd ~/Code/DSH-better-sidebar && pnpm install && pnpm build +2. Register into the web profile: + a. Add "dsh-better-sidebar": "link:" to the dependencies of ~/.dsh/profiles/web/package.json + b. Append to ~/.dsh/profiles/web/cordis.patch.yml: + - insert: + - id: better-sidebar + name: 'dsh-better-sidebar' +3. Run pnpm install in ~/.dsh/profiles/web +4. Restart DSH and hard-refresh (Cmd/Ctrl+Shift+R) to verify +``` + +> Installation = dependency registration (equivalent to `dsh plugin --profile web add link:`) + one mount line. **It also works when DSH is started as an npm package (e.g. `npx -p @deepseek-ai/dsh@0.0.1-rc.1 dsh web`)** (verified since v0.4.3). + +### Updating + +```text +1. cd ~/Code/DSH-better-sidebar && git pull && pnpm install && pnpm build +2. Verify the registration is still valid (only re-add if missing): the link: dependency in the profile's package.json + the cordis.patch.yml mount line +3. Client-only changes (src/client/*) → hard refresh is enough; host changes (src/index.ts, src/config.ts, etc.) → restart DSH + hard refresh +``` + +
+Install via plugin-registry (optional — use either this or the main flow) + +Prerequisite: DSH with [plugin-registry](https://github.com/dsh-external/plugin-registry) integrated (`dsh registry` available). **Enabling both channels double-mounts** (the Node half loads twice, the page gets two sidebars). + +```sh +git clone https://github.com/dsh-external/DSH-better-sidebar.git && cd DSH-better-sidebar +pnpm install && pnpm build +node scripts/package-registry.mjs # assemble the registry/ staging (manifest + artifacts + README, not committed) +dsh registry install ./registry # install (disabled by default) +dsh registry enable dsh-external/dsh-better-sidebar +``` + +Update: `git pull && pnpm install && pnpm build` → `node scripts/package-registry.mjs` → `dsh registry uninstall/install/enable`. Remove the other channel's mount before switching. + +
+ +## 🔌 Service: register tabs & file viewers + +Since v0.4.0 the plugin exposes the `ctx.betterSidebar` service — other plugins can register sidebar pages and file viewers (the 7 built-in tabs + 9 viewers go through the same service, eating our own dog food): + +```ts +import type {} from 'dsh-better-sidebar' // triggers the ctx.betterSidebar type merge +export const inject = ['betterSidebar'] +export function apply(ctx: Context) { + ctx.effect(() => ctx.betterSidebar.registerTab({ + id: 'my-plugin:db', title: 'Database', component: ({ scope }) => , + })) +} +``` + +Full integration docs (`TabDescriptor` / `FileViewerDescriptor` full fields, matching algorithm, HMR pitfalls, declarative settings): see [`AGENTS.md`](./AGENTS.md). + +## 🛠️ Development & Build + +```sh +pnpm install # @deepseek-ai/* resolved from npm (^0.0.1-rc.1, published) — no token needed +pnpm typecheck # tsc --noEmit +pnpm build # → lib/index.js + lib/invariant.js + lib/client.js + lib/client-registry.js + lib/types +pnpm test # vitest (includes manifest consistency guard; build first) +pnpm watch # tsdown --watch +``` + +**Architecture**: a single npm package with host/client halves — host (`src/index.ts`): `/sidebar/api/*` JSON API, `/sidebar/file` media route, `/sidebar/html` preview route, `/sidebar/ws/terminal` WebSocket (fs / git / pty / preview, all session-scoped with a trust fence); client (`src/client/index.tsx`): portal sidebar + views + interception; state persisted per session in localStorage. Organized per DSH official conventions (no default export, dual client bundles); no dependency on npm / checkout at runtime (`@deepseek-ai/*` provided by the web profile). + +## 🔐 Security + +- Routes protected by a Host-header trust fence (same as `/api`); `fs.write` is atomic; media/preview routes only serve files inside the session cwd; git only shells out to the CLI and never sets identity +- HTML preview and browser tab content render in **opaque-origin sandboxed iframes** (no `allow-same-origin`/`allow-top-navigation`, `no-referrer`, all permission policies disabled); the `/sidebar/html` route carries a CSP `sandbox` + size/path bounds; the address bar rejects `javascript:`/`data:`/`file:` and local addresses like localhost +- The UI shows the sandbox status live (red warning when off) and can temporarily unlock the current page; the settings page can disable the sandbox per feature (disabled by default, with a warning) — when off, content shares the origin with the UI; only recommended for fully trusted content + +## ⚠️ Known Limitations + +- Git has no push/pull/fetch; no file watcher (manual refresh); tool inline file-open buttons cannot be intercepted +- Dragging a terminal tab to another pane remounts it (shell restarts) +- `.xlsx` preview does not preserve cell styles (SheetJS community-edition limitation); Office/PPTX preview is inlined into the client bundle (~23MB), slower on first load +- Browser sandbox has no login state / third-party cookies are restricted; some sites need popup login; sites that refuse embedding via `X-Frame-Options`/`frame-ancestors` (e.g. arxiv.org) show a reason panel (with "Open in browser"); in-iframe navigation does not enter the back stack +- HTML preview renders the saved file (not unsaved drafts) +- No bottom panel on mobile (<768px): on narrow screens its tabs merge into the right sidebar once (after migrating back to desktop they stay in the right sidebar); the desktop bottom panel is only available on wide viewports; auto-open terminal on first bottom-panel expand does not trigger on mobile + +## 🖥️ Platform Support + +Windows / Linux / macOS (macOS validated daily; the rest covered by unit tests); `node-pty` prefers prebuilt binaries, otherwise a build toolchain is required (Windows VS Build Tools / Linux make+g+++python3 / macOS Xcode CLT).