Bundle
dsh-plugin-chat-menu
在 DSH 会话输入框输入 @ 呼出工作目录文件浏览菜单:搜索、递归查找、逐级深入、多格式 snippet 引用
- Source
- ChocoLZS
- stars
- 1 stars
- License
- MIT
- Updated
- Updated 2 days ago
Readme
# dsh-plugin-chat-menu
<div align="center">
<b style="font-size: 1.15em;">在 DSH 会话输入框输入 <code>@</code>,呼出工作目录文件浏览菜单</b><br /><br />
<code>名称搜索</code> <code>递归查找</code> <code>逐级深入</code> <code>多格式引用</code> <code>ESC 取消</code><br /><br />
搜索、点选、把文件/目录路径以任意格式引用进输入框,全程无需离开键盘。
</div>
<div align="center">








</div>
## ✨ 功能一览
- **`@` 原生整合**:注册进 DSH 内置的 `@` 触发菜单,与「子智能体」「插件」分组并列在同一个原生菜单里(`文件` 分组排最前)
- **🔍 名称搜索**:输入即按文件/目录名过滤当前层;当前层命中不足时自动在**整个工作目录内递归搜索**(深度/目录数/扫描条目数三重预算,大仓库不卡顿)
- **🗂️ 逐级深入**:点击目录项写入 `@目录/` 继续深入,继续输入字符即列出该层内容
- **⌨️ 原生键盘**:`↑/↓` 移动高亮、`Enter` 或点击选中、`ESC` 取消——全部由内置管线仲裁,稳定可靠
- **🛡️ 防误发**:整行是 `@目录路径/` 时按 Enter 不会发送;目录名后按空格自动补成 `@目录/` 并展开
- **🪝 会话感知**:工作目录跟随当前会话 `header.cwd`,菜单内容与所在目录保持一致
## 🚀 安装
**前置**:已装好 DSH(`dsh web` 能正常运行),Node.js ≥ 20。
### 一键脚本
**macOS / Linux**(Windows 装了 Git Bash 或 WSL 也可):
```sh
curl -fsSL https://raw.githubusercontent.com/ChocoLZS/dsh-plugin-chat-menu/main/scripts/install.sh | bash
```
**Windows(PowerShell 5.1+ / pwsh)**:
```powershell
irm https://raw.githubusercontent.com/ChocoLZS/dsh-plugin-chat-menu/main/scripts/install.ps1 | iex
```
装完**重启 DSH 并硬刷新浏览器**(Cmd/Ctrl+Shift+R)即可看到 `@` 文件菜单。
### 手动安装(dsh 官方 CLI)
```sh
dsh plugin --profile web add dsh-plugin-chat-menu
```
等价写法(无需全局安装 dsh):
```sh
npx -y --package @deepseek-ai/dsh dsh plugin --profile web add dsh-plugin-chat-menu
```
> `dsh plugin` 会登记依赖、识别包内 `dsh.bundle.patch`(`cordis.patch.yml`)并自动写入 `dsh.profile.bundles` 完成挂载——不修改 DSH 源码,插件作为独立包被 profile 引用。
### 本地开发
```sh
npm run build # 生成 lib/(host 半 + 浏览器 bundle)
dsh plugin --profile web add "file:$(pwd)"
```
更新:修改 `src/` 后重新 `npm run build`,再执行一次上面的 `dsh plugin add`。
> 卸载:`dsh plugin --profile web remove dsh-plugin-chat-menu`。
### 动态插件(未发布 npm 时,快速使用 / 调试)
chat-menu 同时提供**动态 Cordis 插件**形态(`dynamic/` 目录,由构建生成):
```sh
npm run build # 生成 lib/ 与 dynamic/
```
1. `cordis_define`:`idPrefix: atfile`;`code.host` / `code.client` 分别取 `dynamic/host.js` / `dynamic/client.js` 的函数体;
2. `cordis_run`:首次 `run` 激活(浏览器半首次需批准),改版 `update` 同一 pluginId。
> ⚠️ 动态插件随 DSH 进程重启而清空,重启后需重新装载。**同一时间只装一种形态**:动态版与 bundle 版都会注册 `@` 文件菜单,同时运行会出现两个菜单——装 bundle 版就不要加载动态版(反之亦然)。
## 🧬 单一源码保证
两种形态(bundle 版与动态版)**由同一份 TypeScript 源码构建生成**,不存在两份手工维护的副本:
```
src/
├── core/ # 共享核心(唯一逻辑来源,零环境依赖)
│ ├── host-core.ts # 目录列举逻辑(服务注入;bundle 路由与动态桥共用)
│ └── source-core.ts # @ 文件源(candidates/onPick/match*;内置菜单渲染)
└── host/
├── bundle.ts # bundle Host 装配(webServer 路由 + 信任栅栏)
└── dynamic.ts # 动态 Host 装配(harness.handle 桥)
```
`npm run build`(`scripts/build.mjs`,esbuild)从这些源文件产出两种安装形态:
- `lib/` → **bundle 版**(`dsh plugin add`):`index.js`(ESM Host)+ `client.js` / `client-registry.js`(module-loader factory)
- `dynamic/` → **动态版**(`cordis_define`):`host.js` / `client.js`(函数体,核心内联)
两者只差「安装方式 + 注册周期 + 传输通道」(HTTP 路由 ↔ `harness.handle`/`host.call`),**业务逻辑全部来自同一份 `src/core/`**(菜单渲染由 DSH 内置管线提供)。改逻辑只需改 `src/`,再 `npm run build` 两种形态同步更新。
## ⌨️ 使用速查
| 按键 | 行为 |
| --- | --- |
| `@` | 呼出原生触发菜单(`文件` / 子智能体 / 插件分组并列) |
| 输入字符 | 按名称过滤当前层;无匹配时递归搜索 |
| `↑` / `↓` | 移动高亮 |
| `Enter` | 选中条目(目录 → `@目录/` 深入;文件 → 相对路径) |
| `空格` | 目录名后按空格 → 自动补成 `@目录/` 并展开该层 |
| `ESC` | 取消菜单 |
> 点击目录项写入 `@目录/` 后继续输入字符,即可逐级进入下一层。
## 📂 结构
```
dsh-plugin-chat-menu/
├── README.md # 本文件
├── AGENTS.md # dsh-plugin-* 仓库族约定(agent 开发必读)
├── LICENSE # MIT
├── package.json # npm 包清单(devDeps: typescript/esbuild;dsh.bundle.patch / dsh.client)
├── tsconfig.json # TypeScript 配置(npm run typecheck)
├── dsh.plugin.json # 插件注册表清单(id / client.main)
├── cordis.patch.yml # bundle 挂载补丁(dsh plugin add 自动注册)
├── src/ # ★ 单一 TypeScript 源码
│ ├── core/ # 共享核心(host-core.ts 列举逻辑 / source-core.ts @ 源)
│ └── host/ # 装配(bundle.ts 路由 / dynamic.ts 动态桥)
├── dynamic/ # 构建产物(npm run build 生成,不入库):动态函数体
├── scripts/
│ ├── build.mjs # esbuild 单一源码 → lib/ + dynamic/(两种形态)
│ ├── install.sh # 一键安装(macOS / Linux / Git Bash)
│ └── install.ps1 # 一键安装(Windows PowerShell)
└── lib/ # 构建产物(npm run build 生成,不入库):bundle 版
├── index.js
├── client.js
└── client-registry.js
```
- `src/core/host-core.ts` — 入参 `{ sessionId, path, filter }`:`path` 逐段解析真实目录(先精确、后忽略大小写),`filter` 名称过滤;工作目录取会话 `header.cwd`,缺失回退 `sandboxPolicy.workspaceRoot`。
- `src/core/source-core.ts` — 注册 `@` 文件源:`candidates(query)` 名称搜索 + 递归、`onPick` 写入路径/`@目录/`、`matchSpace`/`matchEnter` 防误发;菜单渲染与键盘仲裁由 DSH 内置 `inputTriggers` 管线提供。
## 📝 License
[MIT](./LICENSE)
Install
dsh plugin --profile web add github:ChocoLZS/dsh-plugin-chat-menu
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-plugin-chat-menu 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.
- This source has no pinned commit, so a later push upstream changes what installs. Prefer pinning a commit.