dsh-files-tab
A DeepSeek Harness (DSH) plugin that adds a Files tab to the conversation view — open, read and edit workspace files without leaving the chat.
中文文档见 README.zh.md。
Features
- Files tab in the conversation view, with multi-document chips (open / switch / close, dirty marker). State is per session.
- Two open modes, chosen by file type:
- Read — Markdown rendered with a collapsible table of contents (default for
.md/.markdown). - Edit — Monaco with syntax highlighting; the default (and only mode) for code / other files. Markdown can switch between Read and Edit.
- Read — Markdown rendered with a collapsible table of contents (default for
- Toolbar: mode switch (segmented control), Save (
Ctrl/Cmd+S) with a dirty indicator. - Open file dialog: browse the workspace as a lazy-loaded directory tree, or type to search by filename; type a path to open it directly.
- Sandbox-aware: read / write / list / search resolve against the calling session's workspace cwd and honor its sandbox policy.
- Theme-adaptive (light / dark, via DSH design tokens) and i18n (English / 简体中文, follows the DSH language setting).
Packages
| Package | Half | Description |
|---|---|---|
@dzwalker/dsh-host-files |
Host | files service: readFile / saveFile / listDir / searchFiles Remote. |
@dzwalker/dsh-client-ui-files |
Client | The browser Files tab UI. |
Requirements
- DeepSeek Harness
^0.1.0-rc.5(the plugin builds against the DSH client/host packages of that line). - A DSH web profile (the tab registers into
conversation.view).
Install
Install both packages into your DSH profile, then add them to the composition.
# from your DSH profile directory
pnpm add @dzwalker/dsh-host-files @dzwalker/dsh-client-ui-files
Add to your profile's cordis.patch.yml (or run dsh web --patch examples/cordis.yml):
- insert:
- id: files-host
name: '@dzwalker/dsh-host-files'
- id: files
name: '@dzwalker/dsh-client-ui-files'
Restart the web server. A Files tab appears next to Chat / Trajectory.
Usage
- Open the Files tab → click Open file (or the + Open… chip) to browse or search the workspace.
- Markdown opens in Read mode; use the toolbar to switch to Edit.
- Edit, then Save (
Ctrl/Cmd+S). The chip shows a dirty dot until saved.
Known limitations
- Monaco runs without language workers: you get editing + syntax highlighting, but no IntelliSense / diagnostics. This keeps the single-file bundle self-contained.
- The client bundle is large (~5 MB, Monaco inlined); it is served once and cached.
- Saving uses the session sandbox policy; writing outside the allowed workspace is denied by DSH.
- Opening a file by clicking a path in the conversation is not included in this release. It requires an extension point in the DSH conversation view that is not yet upstream. See Roadmap.
Roadmap
- Click a file path / artifact name in the conversation to open it in the Files tab (pending an upstream
openFileextension point in@deepseek-ai/dsh-client-ui-conversation). - Optional Monaco language workers for IntelliSense / diagnostics (see Known limitations for the trade-off and why they are off by default).
Building from source
The published npm packages already ship prebuilt
lib/artifacts (including the generated Typert Remote contracts and the bundled Monacoclient.js). Consumers do not need to build anything — justpnpm addthe two packages (see Install).
Building from source has one caveat. The Host half generates its Typert Remote contracts
(typert.host.js / typert.remote-client.js) with @deepseek-ai/dsh-typert-generator,
which currently only resolves the @deepseek-ai/dsh-typert-protocol markers when it runs
inside the DSH monorepo workspace (where that package is a source project). Out of tree
the generator silently produces no Remote artifacts, so a standalone pnpm run build here
cannot yet emit a complete, self-consistent Host bundle.
Until DSH ships a dedicated out-of-tree plugin SDK, the release artifacts are produced by
adding these two packages to a DSH monorepo checkout as workspace packages and running the
monorepo's build:lib:host / build:lib:client, then publishing the resulting lib/ from
here. This repository is the source and release home; the monorepo is only the build host.
The build scripts here run tsdown per package (build:host / build:client), which is the
correct structure; the only missing piece out of tree is the generated Host Typert contracts.
Standalone type-checking works once the Host Typert contracts exist, because the Client
half imports @dzwalker/dsh-host-files/remote (lib/typert.remote-client.d.ts). So either:
pnpm install
pnpm run build:host # emits lib/index.js (Typert contracts only emit inside the monorepo)
pnpm run typecheck # passes once lib/typert.remote-client.d.ts is present
or drop the prebuilt Host lib/ (e.g. copied from a release) in place first, then
pnpm run typecheck.
License
MIT © dzwalker
No comments yet. Be the first to write one.