dsh-file-ref
其他 活跃维护

dsh-file-ref

cucen066/dsh-file-ref

为web编辑器提供类Codex风格的工作区文件引用功能,输入@即可快速浏览并关联本地工作区文件,无需手动填写路径,简化开发场景下的文件关联操作。

0
Stars 标星
0
Forks 分支
0
Watchers 关注
0
Open Issues
JavaScript
主要语言
MIT
开源协议
25 KB
仓库大小
1 个月前
最后推送
一键安装扩展 / 插件指令
dsh plugin --profile web add github:cucen066/dsh-file-ref
git clone https://github.com/cucen066/dsh-file-ref.git
git clone git@github.com:cucen066/dsh-file-ref.git
README.md main

dsh-file-ref

Codex-style workspace file references for the DeepSeek Harness web GUI: type @ in the composer to browse the current workspace's files and insert the file's workspace-relative path as plain text, prefixed with a workspace anchor (工作区文件:).

@ → file.md → send

The agent receives a relative path anchored to the workspace (工作区文件:file.md), so it resolves the file inside the session workspace instead of searching the whole disk by name — no absolute paths, no truncated chips.

Why plain text instead of a chip?

DSH's composer reference chips occupy a single character cell, so any label longer than 1–2 characters is visually truncated (the full label only appears on hover). For file names that defeats the purpose. Inserting the path as plain text means:

  • the composer shows the complete file name before you send;
  • the sent message is exactly what you picked (WYSIWYG);
  • the agent gets a short, unambiguous relative path prefixed with a workspace anchor (工作区文件:sub/file.md for nested files), which steers it to the workspace instead of a disk-wide search.

Features

  • @ opens a file group at the top of the existing trigger menu (before subagents/plugins).
  • Candidates come from a small host endpoint, so the browser never touches the filesystem directly.
  • Files only (directories are skipped), recursive walk up to depth 4, capped at 300 files; node_modules, .git, and dotfiles are excluded.
  • Anchored workspace-relative insertion (工作区文件:relative/path); falls back to the bare file name when the file is outside the workspace root.

Requirements

  • A running DSH web profile (dsh web).
  • Loopback bind (127.0.0.1 — the default). See Security.

Installation

Add the package to the profile and enable it, then restart dsh web.

# from your workspace (the path is anchored to the invoking directory)
dsh plugin --profile web add github:<your-account>/dsh-file-ref
# or from a local checkout
dsh plugin --profile web add /path/to/dsh-file-ref

Append a row to $DSH_HOME/profiles/web/cordis.patch.yml:

- insert:
    - id: file-ref
      name: 'dsh-file-ref'
      inject: [webServer]

Restart the server:

dsh web

While developing the bundle itself, the client half hot-reloads: the
client-hmr chain polls served bundles every 500 ms and reloads the plugin
in the browser without a server restart. New rows (the cordis patch above)
still need a restart because the boot graph is composed at startup.

How it works

Two halves, one package (a dsh.client dual-face plugin):

  • Host half (lib/index.js) registers one exact HTTP route on the web
    server: GET /dsh-file-ref/list?path=<absolute-directory>{ cwd, files: [{ name, path }] }. The walk uses node:fs/promises with a bounded
    recursive scan.
  • Browser half (lib/client.js) registers an @ input-trigger source
    (file-ref, order -1 so it lists first). Candidates call the route with
    the session's cwd (from the sessions store). Picking a file inserts the
    workspace-relative path prefixed with a workspace anchor plus a trailing
    space — the anchor makes the model resolve the file inside the workspace
    rather than searching the whole disk by name.

The browser never needs a filesystem API; the host never exposes one beyond
the single listing route.

Development

The client bundle is a plain classic script that registers itself via
window.__ModuleLoader__.load({ id, factory }) (the format the DSH module
loader serves under /plugins/<id>/client.js). No build step is required.

Run the host smoke test (no cordis needed):

node smoke-test.mjs                # lists this package's own directory
node smoke-test.mjs /path/to/dir   # or any absolute directory

Security

  • The listing route is unauthenticated and accepts any absolute path —
    acceptable for the default loopback bind, not for --host 0.0.0.0.
  • Relative paths are rejected (400); unreadable directories are skipped
    silently.
  • No file contents ever leave the host — only names and paths.

Limitations

  • Web surface only (the composer lives in the web GUI).
  • Files only; no directory entries, no nested-picker navigation.
  • The @ menu group title renders the raw source name (file-ref) because
    the trigger menu's locale namespace is owned by ui-input-trigger.

License

MIT