Bundle
dsh-office-tool
dsh plugin: complete Office document tools for the agent (create/read/edit .docx/.xlsx/.pptx through the OfficeCLI binary) plus a document preview in the dsh web sidebar via dsh-better-sidebar.
- Source
- rong-coder
- stars
- 3 stars
- License
- MIT
- Updated
- Updated 7 hours ago
Readme
# dsh-office-tool
[](LICENSE)
[](https://www.typescriptlang.org/)
[](package.json)
A [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (`dsh`) plugin that gives the agent **complete Office document capabilities** — create, read, query, and edit `.docx` / `.xlsx` / `.pptx` — by driving the [OfficeCLI](https://github.com/iOfficeAI/OfficeCLI) binary, plus **in-document preview in the dsh web sidebar** through [dsh-better-sidebar](https://github.com/omdsh-dev/DSH-better-sidebar).
Everything renders with OfficeCLI's built-in high-fidelity HTML engine, so the agent and the user can *see* the document (via the sidebar preview) instead of guessing from the DOM — no Microsoft Office required.
---
## Features
- **9 model-facing tools** (`office_create` / `get` / `query` / `set` / `add` / `remove` / `view` / `batch` + `office_cli` passthrough), covering the full OfficeCLI command surface (move/swap/merge/dump/import/validate/raw/… via `office_cli`).
- **Structured `--json` envelopes** everywhere — success `{success, data}` / failure `{success:false, error:{code, suggestion}}`, with OfficeCLI's self-healing error codes surfaced to the model.
- **Sidebar preview**: opening a `.docx` / `.xlsx` / `.pptx` in better-sidebar renders it with OfficeCLI's HTML engine in an iframe (auto-reloads when the file changes). A dedicated **「Office 预览」tab** runs `officecli watch` for live SSE-refreshing preview while the agent edits.
- **Works headless too**: the tools activate in any profile (no web UI needed); only the preview routes wait for a web server.
---
## Prerequisites
- `dsh` installed and a working profile (the `web` profile for preview).
- [OfficeCLI](https://github.com/iOfficeAI/OfficeCLI) binary available (`officecli install`, or any PATH install). The plugin fails loud at load if it cannot resolve the binary.
- For the sidebar preview: [dsh-better-sidebar](https://github.com/omdsh-dev/DSH-better-sidebar) installed in the same profile.
## Install
```sh
# into your web profile (requires dsh-better-sidebar for the preview)
dsh plugin --profile web add dsh-better-sidebar
dsh plugin --profile web add dsh-office-tool
# restart `dsh web`, then hard-refresh the browser (Cmd/Ctrl+Shift+R)
```
Install from a local checkout with `dsh plugin --profile web add ./dsh-office-tool`, or build/attach it from a clone of this repository (the `prepare` script builds `lib/` on install):
```sh
git clone https://github.com/rong-coder/dsh-office-tool.git
cd dsh-office-tool && pnpm install
dsh plugin --profile web add ./dsh-office-tool
```
## Configuration
Override rows in your profile `cordis.patch.yml` (a patch replaces a row's **whole** config):
```yaml
- id: office-tool
config:
command: 'C:\path\to\officecli.exe' # binary name or absolute path (env DSH_OFFICECLI wins)
timeoutMs: 60000
maxOutputBytes: 16777216
- id: office-tool-preview
config:
preview:
allowOutsideWorkspace: false # allow rendering absolute paths outside the host cwd
watch:
enabled: true
idleSeconds: 300
```
`command` accepts a bare name resolved on PATH, or an absolute path (Windows `.exe`). `$DSH_OFFICECLI` overrides the default `'officecli'`.
## Tools
| Tool | What it does |
|---|---|
| `office_create(file, type?, force?)` | Create a blank `.docx` / `.xlsx` / `.pptx` |
| `office_get(file, path?, depth?)` | Read one element + children as JSON (`/slide[1]/shape[2]`, `/body/p[3]`, `/Sheet1/A1`, `/`) |
| `office_query(file, selector, limit?)` | CSS-like query (`run:contains(TODO)`, `row[Salary>5000 and Region=EMEA]`) |
| `office_set(file, path, props, find?, replace?)` | Modify element properties (text/fonts/colors/layout/formulas) |
| `office_add(file, parent, type, props?, after?/before?/index?/from?)` | Add an element (slide/shape/paragraph/row/sheet/chart…) or clone (`--from`) |
| `office_remove(file, path, shift?)` | Remove an element |
| `office_view(file, mode, page?, cols?, maxLines?)` | `text`/`outline`/`annotated`/`stats`/`issues` as text; `html`/`screenshot` return a preview URL |
| `office_batch(file, commands[], bestEffort?)` | Atomic multi-op batch (`op`/`path`/`props`) |
| `office_cli(argv)` | Raw passthrough for everything else: `merge`, `dump`, `import`, `validate`, `raw`, `raw-set`, `move`, `swap`, `refresh`, `help`, `load_skill` |
OfficeCLI's path/selector syntax and error codes apply throughout — see `officecli --help` or `officecli help <fmt> <verb>` for details.
## Sidebar preview
The client half registers, through `ctx.betterSidebar`:
- **File viewer** (`office:officecli`, exts `docx/xlsx/pptx`, `priority: 100`): opens the file in an iframe served by the host `/office/preview` route, which renders it with `officecli view <file> html`. A refresh button and a lightweight mtime probe keep it current as the agent edits. Conflicts with the bundled docx/xlsx/pptx viewer are resolved by priority (100 wins).
- **「Office 预览」tab**: enter a document path and it starts `officecli watch` (host-managed, ephemeral port) and iframes the live preview; the watch process stops when the tab closes or the plugin unloads.
Host routes (registered only when `ctx.webServer` exists — never in headless):
- `GET /office/preview?path=…&cwd=…&page=…` — rendered HTML (`probe=1` → `{mtime}`).
- `GET /office/watch?path=…&action=open|close|status` — JSON `{url, port}` for the live tab.
## Repository layout
```
├── src/
│ ├── index.ts # host plugin entry: OfficeService + tool registration
│ ├── service.ts # argv construction, spawn, --json envelope parsing
│ ├── errors.ts # OfficeError + officecli error-code mapping
│ ├── config.ts # Config type + defaults + load-time validation
│ ├── paths.ts # preview path resolution + workspace checks
│ ├── tools/ # office_create/get/query/set/add/remove/view/batch/cli
│ ├── preview/ # /office/preview route + watch process manager
│ └── client/ # client bundle: better-sidebar file viewer + live tab
├── tests/ # unit, route-HTTP, and real-officecli integration tests
├── cordis.patch.yml # dsh bundle manifest (plugin rows to insert)
├── tsdown.config.ts # single build producing host + client bundles
└── package.json # dsh.bundle + dsh.client manifests
```
## Development
```sh
pnpm install
pnpm run typecheck
pnpm test # unit + route tests; integration tests self-skip without officecli
pnpm run build # lib/index.js (tools) + lib/preview.js (preview host) + lib/client.js (client bundle)
```
The integration tests run against a real officecli when the `@officecli/officecli` devDependency has downloaded its binary (create → add → get → view html).
## Known Limitations and Deferred Work
- **Live preview updates only on OfficeCLI mutations**: `officecli watch` refreshes when *officecli* edits the document; files changed by other tools do not auto-push (the snapshot viewer's probe still reloads them).
- **`view screenshot` needs a headless browser** (Chrome/Edge/Chromium/Firefox or Playwright) installed on the host, like OfficeCLI itself.
- **KaTeX CDN**: rendered HTML with math formulas loads KaTeX from `d.officecli.ai` (jsdelivr fallback); without network, formulas degrade to monospace text. Documents without formulas are fully offline.
- **Electron/desktop shell**: the preview routes are served same-origin by the host; the Web UI (browser) is supported. If the app's CSP ever blocks the live-tab iframe (`http://127.0.0.1:<port>`), add `frame-src` via a host index tap or switch the tab to the host-proxied route.
- **Tool file paths resolve against the host cwd** (where `dsh` was launched). Relative paths in `office_*` tools are resolved there; the sidebar preview additionally honors better-sidebar's session `cwd`.
Install
dsh plugin --profile web add github:rong-coder/dsh-office-tool#9c789750646ab5ef8bcaa212319118e99b5ae1ee
Profile: web
With the hub plugin installed, ask your agent to install it by name — it resolves the same plan shown here.
dsh plugin --profile web add github:stvlynn/dsh.fish#path:packages/dsh-plugin-hub
install dsh-office-tool from the hub
- This package builds from source on install. pnpm will ask you to allow its build script — that is permission to run the package’s code on your machine, outside the agent sandbox. Only allow sources you trust.