Skip to content
dsh.fish
Bundle

dsh-paperclip

Zero-intrusion DeepSeek Harness bundle: πŸ“Ž upload button with pending popover, read_document multi-format tool (txt/pdf/docx/xlsx/json/md/ini/conf), Settings β†’ General toggle. Standard Cordis bundle, no DSH source changes.

Source
runfali
License
MIT
Updated
Updated 2 days ago

Readme

# dsh-paperclip

> A zero-intrusion bundle for DeepSeek Harness: πŸ“Ž upload button with popover Β· `read_document` multi-format reader Β· Settings β†’ General toggle. Adapts to light / dark themes.

[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
[![Node.js >= 22](https://img.shields.io/badge/node-%3E%3D22-brightgreen)](package.json)
[![Version](https://img.shields.io/badge/version-0.1.0-orange)](package.json)

**English** | [δΈ­ζ–‡](README.zh-CN.md)

## Features

- **πŸ“Ž Upload button + popover** β€” Borderless πŸ“Ž button in the composer. A small β–΄ next to it shows the count; click to expand upward and see pending files (filename only). Click Γ— to remove. Files are uploaded immediately and the server path is appended to the message on send.
- **`read_document` tool** β€” Read `txt / json / conf / md / ini / pdf / docx / xlsx` with `offset` / `limit` paging. Text formats work zero-dependency; `pdf / docx / xlsx` show a hint when optional deps are missing.
- **One toggle** β€” **Settings β†’ General** has an β€œEnable file uploads” switch. Off hides the button and blocks uploads. No extra tabs.
- **Theme-aware** β€” Uses DSH design tokens, looks correct in light and dark mode.
- **Zero-intrusion** β€” Standard Cordis `bundle` plugin, no DSH source changes.

## Requirements

- DeepSeek Harness `dsh >= 0.1.0-rc.8` (`web` profile)
- Node.js `>= 22`

## Install

```bash
git clone https://github.com/runfali/dsh-paperclip.git
cd dsh-paperclip
pnpm install
pnpm build        # builds lib/client.js (browser bundle)
dsh plugin --profile web add .
# restart manually: dsh web
```

Uninstall:

```bash
dsh plugin --profile web remove dsh-paperclip
```

Restart `dsh web` to apply.

## Configuration

Edit in **Settings β†’ Plugin Config β†’ paperclip** or override in `~/.dsh/profiles/web/cordis.patch.yml` (full replacement):

| Field | Default | Description |
|---|---|---|
| `enabled` | `true` | Show button and enable uploads |
| `maxBytes` | `67108864` | Per-upload byte cap |
| `uploadDir` | `""` | Persist directory; empty β†’ `~/.dsh/uploads/paperclip` (content-addressed, deduped) |
| `allowedExtensions` | `[]` | Whitelist (empty = allow all) |
| `readLimit` | `2000` | `read_document` line window |
| `maxFileBytes` | `67108864` | `read_document` per-file byte cap |
| `sheetRowLimit` | `200` | `xlsx` rows kept per sheet |

Example:

```yaml
- id: paperclip
  config:
    enabled: true
    maxBytes: 67108864
    uploadDir: ""
    allowedExtensions: []
    readLimit: 2000
    maxFileBytes: 67108864
    sheetRowLimit: 200
```

## Usage

**Upload**: Click πŸ“Ž to pick files. If needed, click β–΄ to expand the list above the input; Γ— removes a file. Type a message and Send β€” the list clears and paths are sent with the message.

**Read**: The model calls `read_document({ file_path, format: "auto", offset: 1, limit: 2000 })`.

## Security

- Only loopback `Host`, same-origin `Origin`, `Sec-Fetch-Site` check; only `POST` / `DELETE`.
- Byte cap checked twice, filename sanitized, `DELETE` confined to `uploadDir`.
- Default dir `~/.dsh/uploads/paperclip`, content-addressed and deduped.

## Known Limitations

- Pending list is in-memory; reload clears it (files remain).
- No GC β€” only Γ— deletes.
- `pdf / docx / xlsx` need optional deps (`pnpm add pdf-parse mammoth xlsx` inside the plugin directory); text formats work without them.

## License

[MIT](LICENSE)

Install

dsh plugin --profile web add github:runfali/dsh-paperclip

Profile: web

  • 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.
  • This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.
Source