**English** · [简体中文](README.md) # dsh-file-beam **Drag files onto the DSH Web composer — resolve their real absolute paths, register them as chips, and let the agent analyze the source files directly. No copy, no path text in your input.** [![dsh-plugin](https://img.shields.io/badge/DSH-Plugin-111827)](https://github.com/topics/dsh-plugin) [![License](https://img.shields.io/badge/license-MIT-22c55e)](LICENSE)
--- ## Install ```sh dsh plugin --profile web add github:bleamayaka/dsh-file-beam ``` Restart `dsh web` and refresh the browser to take effect. --- ## Features - **Dock chip interaction** — drop a file **or folder** anywhere on the page; a chip appears above the composer - **Instant path when exposed** — when the browser hands over the real path (`text/uri-list`), it is used directly with zero search; otherwise the host searches the session workspace + `~/Downloads`, `~/Desktop`, `~/Documents` by name and returns candidate absolute paths like `C:\Users\...\Desktop\report.docx`; you pick the right one - **mtime-proximity ranking** — with multiple same-name candidates, the one whose disk mtime is closest to the dropped file's modification time surfaces first - **No copy, no transfer** — only the path string is registered; file contents are never read or uploaded; the agent reads the source file directly with its own fs tools - **Hidden path injection** — the chosen path is NOT written into the composer text (your input stays clean); on submit the host injects the file list into the agent request as a hidden plugin-notice message — the model sees the full absolute paths, the UI shows only a one-line "📎 N files" summary - **Send without typing** — once every chip is registered a Send button appears in the chip bar; one click hands the files to the agent (an invisible U+2063 draft marker enables file-only submit; the host strips it before the model sees it) - **History attachment cards** — sent files stay as mini chips in the conversation history (metadata lives in the message's durable `source` field — UI-side data, never part of the model context) - **Works from any workspace** — search is based on the session workspace + configured dirs, so the agent can always locate the files - **Unique match auto-registers** — no click needed when there's exactly one candidate; candidate buttons only appear for same-name files in multiple directories - **Auto-clear after send** — chips disappear once your message is actually sent (the host has consumed the registrations), and on session switch; nothing lingers - **Images keep the native flow** — pure image drops use DSH's built-in multimodal upload; anything containing a non-image file becomes a path reference - **Robustness** — duplicate-drop dedup, same-name dedup, connection-reset cleanup, cancellable directory search --- ## Usage 1. Drop a file (e.g. `report.docx`, `data.csv`) anywhere on the DSH Web page 2. A chip appears above the composer: "resolving…" then candidate path buttons (a directly exposed path registers instantly, no waiting) 3. Pick the right path → the chip becomes "registered " (dismissible with ×) 4. Type your instruction and send, or just click the **Send** button in the chip bar — no path text appears in the composer, but the agent receives the hidden file list and reads the source files directly; the chips clear after send and mini attachment cards stay in the history --- ## Configuration (optional) ```yaml # Override in the profile's cordis.patch.yml: - id: dsh-file-beam config: searchDirs: ["~/Downloads", "~/Desktop", "~/Documents"] # extra search dirs workspaceDepth: 10 # workspace search depth searchDirsDepth: 3 # extra-dir search depth maxResults: 20 # candidate cap ``` --- ## Structure - `lib/index.js` — Host half: path search, session registration (attach/detach/pending), `agent/pre-step` hidden injection - `lib/client.js` — Browser half: drag capture, dock chip (`conversation.input.dock` slot), candidate picking - `cordis.patch.yml` — bundle layer declaration (inserts itself) --- ## Official community This plugin is part of the DeepSeek Harness ecosystem. Join the official community to discuss, report issues, or share your experience: - [DeepSeek Harness GitHub Discussions](https://github.com/deepseek-ai/deepseek-harness/discussions) — official forum: feedback, questions, plugin sharing - [DeepSeek Harness Discord](https://discord.gg/Ycq5dCaS4) — official Discord community - This repo carries the [`dsh-plugin`](https://github.com/topics/dsh-plugin) topic for GitHub discoverability --- ## Credits This plugin references the following open-source projects and official materials: **Interaction & path resolution** - **Interaction design** (dock chip, name-based real-path search, candidate picking, unique-match auto-register): inspired by [gezg/dsh-drag-file](https://github.com/gezg/dsh-drag-file) (MIT) — this plugin changes its model to "no path text in the composer; the host injects paths hidden." - **Chip-bar Send button & path optimizations** ([AKIRACOD/dsh-drag-and-drop](https://github.com/akiracod/dsh-drag-and-drop), BSD-3-Clause, fork of [omdsh-dev/dsh-drag-and-drop](https://github.com/omdsh-dev/dsh-drag-and-drop)): - **Send without typing**: a Send button in the chip bar that submits via `conversation.input.for(scope).submit()` — no typing required - **Instant path extraction**: real paths are parsed straight from the drop's `text/uri-list` / `text/plain` `file://` URLs (including UNC network paths), skipping the host search entirely - **mtime-proximity ranking**: with multiple same-name candidates, the one whose disk mtime is closest to the dropped file's `lastModified` surfaces first **Hidden injection & persistence** - **Hidden injection mechanism** (`agent/pre-step` inserting a plugin-notice message — model sees the full list, UI shows a one-line summary): inspired by the attachment-bridge design of [re-ITRT/dsh-file-fix](https://github.com/re-itrt/dsh-file-fix). - **File-only-submit trick & history cards** ([WJZ-P/dsh-attachments](https://github.com/WJZ-P/dsh-attachments), MIT): - **U+2063 invisible draft marker**: when files are ready and the draft is empty, an invisible non-whitespace character enables the native submit; the host strips it before the model sees it — no synthetic copy is ever shown - **Durable attachment metadata**: file metadata is written into the message's `source` field (UI-side, never model context) and lifted into chat history via a `conversationEvents` definition + the keyed `conversation.chat.node` slot rendering attachment cards **Spec & docs** - **DSH plugin contract** (`dsh.bundle` / `dsh.client` / cordis entry / client bundle wrapper): per the official [cordis-tutorial](https://github.com/deepseek-ai/deepseek-harness/blob/master/docs/cordis-tutorial/01-first-plugin.md) and the community [make-dsh-plugin](https://github.com/vlln/plugin-registry/blob/main/skills/make-dsh-plugin/SKILL.md) spec. --- ## License MIT