# 左侧文件浏览器 (fexp) [English](README.en.md) · [中文](README.md) ![GitHub Release](https://img.shields.io/github/v/release/ShanHaiFish/fexp-file-explorer) ![License](https://img.shields.io/github/license/ShanHaiFish/fexp-file-explorer) ![GitHub Stars](https://img.shields.io/github/stars/ShanHaiFish/fexp-file-explorer) [![Docs](https://img.shields.io/badge/docs-GitHub%20Pages-2ea44f)](https://shanhaifish.github.io/fexp-file-explorer/) DSH(DeepSeek Harness)动态 Cordis 插件:在左侧工作区浏览目录与文件。双入口(侧栏顶部「文件浏览」胶囊 + 会话标题栏「打开目录」按钮)→ 320px 滑出面板,自动定位当前工作区目录,点击目录进入、点击文件预览文本内容;工具栏可一键在系统资源管理器中打开当前目录,预览时可把文件引用添加到聊天输入框。 **v1.5.0 起为静态 bundle 插件,随 profile 层栈自动加载**——安装一次,每次启动 DSH 即自动生效,不再需要手动 define/run。**v1.6.0 已发布到 npm**,`dsh plugin --profile web add fexp-file-explorer` 直接安装。 ## 功能特性 - **双入口**(SVG 矢量图标, 颜色全部使用主题 CSS 变量, 深浅色及任意主题下文字与背景都保持对比): - 侧栏顶部「工作区」标题行右侧的「文件浏览」胶囊按钮(宽栏时显示; 工作区「搜索会话」搜索框展开时自动隐藏, 避免遮挡搜索框, v1.5.1) - 会话标题栏「打开目录」按钮 - **浏览面板**(点击任意入口滑出, 320px, 覆盖左侧区域): - 自动定位到**当前工作区目录**(当前会话 cwd); 切换工作区后面板自动重新定位, 同一工作区重开保留上次浏览位置 - 目录在前、文件在后, 文件显示大小; 点击目录进入、点击文件预览 - 面包屑任意层级跳转; 工具栏: 当前工作区 / 回到根目录 / 上一级 / 刷新 / **在系统资源管理器中打开** - 文件预览: 文本内容(默认 256KB 上限, 最大 1MB), 二进制/超限有明确提示 - 预览头部: 文件名 / 大小 / **[添加到聊天]** / 关闭预览 - **在系统资源管理器中打开**: 一键用系统资源管理器打开当前浏览的目录 (DSH 原生 `host.openPath`, Windows 走 `Invoke-Item`; 直连原生 API `POST /api/host.openPath`, 避免被拦截型第三方插件把调用改道到文件编辑器) — **v1.6.1**: 适配新版 DSH 的 `session/openWorkspacePath` Typert Remote 端点 (先试新端点, 不可达时回退旧 `host.openPath` 与 `workspaces.openPath`) - **添加到聊天(v1.6.0)**: 预览文件时把 DSH **@ 文件命令引用**追加到聊天输入框草稿 (不覆盖已有内容), 可连续添加多个文件(空格分隔): 工作区 cwd 内的文件用 相对路径(`@client/client.js` 形式), 工作区外保留绝对路径, 含空格路径按官方 语法加引号(`@"path with spaces"`); 输入框只显示短引用, DSH 原生 @ 语义 让模型明白这是你显式引用的文件, 需要内容时它会用 read 工具读取 - **图标(v1.4.0)**: Google Material Icons 官方库(fonts.google.com/icons, Apache 2.0 许可), 实心填充风格小尺寸下依然清晰, 与 Chrome/Android 大厂视觉一致 ## 界面预览 | | | | | --- | --- | --- | | ![fexp 界面截图 1](assets/screenshot-1.png) | ![fexp 界面截图 2](assets/screenshot-2.png) | ![fexp 界面截图 3](assets/screenshot-3.png) | ## 快速开始 ```sh # 安装(静态 bundle, 推荐; 已发布到 npm) dsh plugin --profile web add fexp-file-explorer ``` 直接从源码安装(本地开发或未发布时, 注意路径不能含空格): ```sh dsh plugin --profile web add file:/path/to/fexp-file-explorer ``` 重启 `dsh web` 后插件即自动生效:侧栏顶部出现「文件浏览」胶囊按钮,会话标题栏出现「打开目录」按钮,无需手动 define/run。 ## 使用说明 1. **打开面板**: 点击侧栏「文件浏览」或会话标题栏「打开目录」, 320px 面板从左侧滑出, 自动定位到当前工作区目录; 2. **浏览**: 点击目录进入下一级, 用工具栏「上一级 / 回到根目录 / 刷新」导航, 或点面包屑任意层级跳转; 3. **预览文件**: 点击文件在面板底部预览文本内容(默认 256KB 上限); 4. **添加到聊天**: 预览时点击「添加到聊天」, DSH @ 文件引用(`@相对路径` / `@"带空格路径"`)追加到输入框草稿, 编辑后发送; 5. **在系统资源管理器中打开**: 工具栏最右侧按钮, 一键打开当前浏览的目录(Windows 走 `Invoke-Item`)。 ## 仓库内容 | 路径 | 说明 | | --- | --- | | `package.json` + `cordis.patch.yml` + `lib/` + `client/` | **静态 bundle**(推荐):`dsh plugin add` 安装后随 DSH 启动自动加载 | | `host-source.js` + `client-source.js` | 动态插件回退形态:无 bundle 能力的 profile 按下方流程加载 | | `manifest.json` | 插件元数据 + 恢复定义参数(plugin/name/purpose/version) | | `LICENSE` | MIT 许可证 | | `assets/` | 界面预览截图(screenshot-1~3.png) | | `AGENTS.md` | 代理协作约定(重建流程/修改工作流/编码约定/版本管理) | | `README.md` / `README.en.md` | 中文 / English 文档 | ## 双形态说明 | | 静态 bundle(v1.5.0, 推荐) | 动态插件(回退) | | --- | --- | --- | | 加载方式 | `dsh plugin add` 装进 profile 层栈, 随 DSH 启动自动加载 | 每次 DSH 重启后需 `cordis_define` + `cordis_run` 手动注册 | | 代码位置 | `lib/index.js`(Host) + `client/client.js`(Client) | `host-source.js` + `client-source.js` | | 适用场景 | 正常 profile(web 等) | 无 bundle 能力的 profile | 动态回退形态步骤: 1. 让 agent 读取 `host-source.js` 与 `client-source.js`; 2. `cordis_define`:`plugin: { kind:"new", idPrefix:"fexp" }`,name/purpose 取 `manifest.json`(purpose 含 `CAPABILITIES: fs, rpc` 声明),`code.host` / `code.client` 取两个源码文件的完整内容; 3. `cordis_run` 激活;面板出现即成功。 > 动态形态不跨 DSH 进程存续,重启后需重新加载;静态 bundle 形态无此限制。 ## 技术要点 - **Host 半区**: 静态 bundle 形态在 `lib/index.js`,经 `webServer` 挂三个 JSON 路由(`/fexp/default-root` / `/fexp/list-dir` / `/fexp/read-file`), 底层使用 DSH 的 `fs` 服务(resolve/listDir/stat/readText) 与 `sandboxPolicy.workspaceRoot`; 动态回退形态在 `host-source.js`,通过 `harness.handle` 暴露同名三个 RPC。 - **Client 半区**: 全部使用增量插槽(`shell.overlay`、 `conversation.session.header.actions`、`conversation.input.dock`、 `sidebar.footer.action`), 不替换任何内置 UI; 纯 JS + `React.createElement`, 无 JSX/TS; 静态形态经 `window.__ModuleLoader__.load` 注册, `host.call` → fetch 同源路由, `styles.insert` → 自建 `