# dsh-remote-dirpicker

> Make the "Add Workspace" directory picker work from **remote browsers** (nginx / reverse proxy / any non-loopback access) in DeepSeek Harness Web.

[![npm version](https://img.shields.io/npm/v/dsh-remote-dirpicker)](https://www.npmjs.com/package/dsh-remote-dirpicker)
[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)

让 DSH Web 的"新增工作区"目录选择，在**远程浏览器**（nginx 反代 / 公网域名 / 局域网 IP）访问时也能正常使用——不再出现"远程点击新增工作区没反应，而宿主机屏幕上却弹出访达对话框"的问题。

## 目录

- [功能](#功能)
- [解决的问题](#解决的问题)
- [工作原理](#工作原理)
- [使用效果](#使用效果)
- [安装](#安装)
- [验证](#验证)
- [卸载](#卸载)
- [兼容性与注意事项](#兼容性与注意事项)
- [许可](#许可)

---

## 功能

本插件**固定使用浏览器内目录浏览器（browse）这一种交互**——本地与远程完全一致，不再依赖宿主显示器的原生对话框（详见[工作原理](#工作原理)）。

- ✅ 远程（公网 / 反代 / 局域网）访问时，点"新增工作区"弹出**浏览器内目录浏览器**，可直接：
  - 浏览宿主文件系统（面包屑导航、逐级进入）
  - 输入绝对路径跳转
  - 编辑路径
  - 显示 / 隐藏隐藏文件
  - 新建文件夹后立即进入
- ✅ 本机（`127.0.0.1` / `localhost`）访问时同样使用浏览器内目录浏览器，功能一致、体验统一（**不会**再弹出访达等原生对话框）
- ✅ 一行安装、一行卸载，与 dsh 官方插件同样的安装/卸载方式
- ✅ 不修改 dsh 核心代码，纯组合层 patch + 官方目录选择能力

## 解决的问题

DeepSeek Harness Web 默认挂载 `directory-picker-auto` 来决定目录选择交互，它在**启动时按宿主绑定地址**只采样一次：

> 下表描述的是 **DSH 默认（未安装本插件时）** 的选择逻辑——它正是问题所在，**不是**本插件的功能。本插件只有一种交互（browse，见[工作原理](#工作原理)），本地与远程表现一致。

| 绑定地址 | auto 解析结果 | 交互方式 |
|---|---|---|
| `127.0.0.1` / `localhost` | `native` | 在**宿主显示器上**弹出操作系统选择器（macOS 为访达 Finder） |
| 非回环地址 | `browse` | 浏览器内目录浏览器 |

当通过 nginx 把 `127.0.0.1:3080` 反代到公网域名（如 `dsh.example.com`）时：

- dsh 的绑定地址**依然是** `127.0.0.1` → auto 解析为 `native`
- 访达对话框在**宿主机（macmini）屏幕**上弹出
- 远程浏览器什么都看不到，点"新增工作区"看起来**毫无反应**

这正是 DSH 官方 README 建议的 "Mount `-browse` directly in an overlay to pin the interaction" 场景。

## 工作原理

本插件是一个标准的 DSH 插件包（bundle patch + 宿主半边），通过 `cordis.patch.yml` 调整组合：

1. **停用 `directory-picker-auto`**（`disabled: true`）——它的一次性采样无法同时服务本地和远程；
2. **挂载 browse 宿主能力** `@deepseek-ai/dsh-host-directory-picker-browse`——注册 `directoryPicker` 服务的 `browse` 能力，通过 `host.listDirectory` / `host.createDirectory` RPC 提供目录列表与新建文件夹；
3. **挂载 browse 浏览器界面** `@deepseek-ai/dsh-client-ui-directory-picker-browse`——在浏览器内渲染目录浏览器对话框。

`browse` 交互完全运行在浏览器内，数据只通过 HTTP RPC 访问宿主文件系统，**不需要宿主显示器**，因此本地、局域网、公网反代访问表现完全一致。

插件宿主半边（`lib/index.js`）仅做启动健康检查：确认 `directoryPicker` 能力为 `browse`，并在启动日志打印一行确认信息。

## 使用效果

**远程浏览器**（如 `https://dsh.example.com`）：

1. 打开 DSH Web，进入工作区选择（侧边栏或对话头部）
2. 点击"新增工作区"
3. 弹出**浏览器内目录浏览器**窗口：
   - 默认列出宿主 home 目录（带 `/` → `Users` → `xxx` 面包屑）
   - 点击目录行进入子目录；双击亦可
   - 可点"编辑路径"粘贴完整绝对路径回车直达
   - "新建文件夹"可在当前目录创建新文件夹
   - 底部"打开"确认选中当前目录并创建工作区，"取消"关闭
4. 选中目录后正常创建并打开工作区，与本地无差别

**本机浏览器**（`http://127.0.0.1:3080`）：同样的浏览器内目录浏览器，行为一致。

## 安装

### 前置要求

- 已安装 DeepSeek Harness CLI（`dsh` 命令可用）
- 目标 profile 名（默认 `web`）

### 从 npm 安装（推荐）

```bash
dsh plugin --profile web add dsh-remote-dirpicker
```

如需锁定精确版本（不随 `latest` 漂移）：

```bash
dsh plugin --profile web add dsh-remote-dirpicker@0.1.0
```

### 从源码安装（开发）

```bash
dsh plugin --profile web add /绝对/路径/dsh-remote-dirpicker
```

安装后 `dsh.profile.bundles` 会追加 `dsh-remote-dirpicker` 一行。

> ⚠️ **必须重启 dsh web 生效**：bundle 组合变更在启动时读取，安装/卸载后请重启 dsh web 服务。

## 验证

安装并重启后，可用以下命令确认生效：

```bash
# 1) 组合树：auto 行已禁用、browse 三行已插入
dsh --profile web --dump-config | grep -A1 "remote-dir-picker\|directory-picker"
# 期望：directory-picker（auto）disabled: true，
#       remote-dir-picker / remote-dir-picker-browse-host / remote-dir-picker-browse-ui 三行存在

# 2) 浏览器 boot manifest 应包含 browse 界面（而非 -native）
curl -s http://127.0.0.1:3080/ | grep -o '"id":"[^"]*"' | grep directory-picker
# 期望输出：
# "id":"@deepseek-ai/dsh-client-ui-directory-picker-browse"

# 3) browse 客户端 bundle 可访问
curl -s -o /dev/null -w "%{http_code}" \
  http://127.0.0.1:3080/plugins/@deepseek-ai/dsh-client-ui-directory-picker-browse/client.js
# 期望输出：200
```

然后在浏览器（含远程）打开 dsh web，点击工作区选择 → "新增工作区"，应弹出浏览器内目录浏览器。

## 卸载

```bash
dsh plugin --profile web remove dsh-remote-dirpicker
```

或手动从 `~/.dsh/profiles/web/package.json` 的 `dsh.profile.bundles` 数组中删除 `dsh-remote-dirpicker` 行。

卸载后**重启 dsh web**，即恢复 dsh 默认的 `directory-picker-auto` 行为。

## 兼容性与注意事项

- **目标平台**：DSH Web 宿主（macOS / Linux / Windows），目录浏览完全跨平台；
- **交互变化**：固定 `browse` 后，本机访问也不再弹出访达等原生对话框，统一使用浏览器内目录浏览器（功能等价，且支持路径输入、新建文件夹——对远程场景是必需能力）；
- **安全**：`browse` 能力仅通过 dsh 自身的 RPC 通道暴露，遵循 dsh 现有的访问控制，不引入额外的开放端口；
- **版本记录**：`0.2.0` 曾作为实验性自适应构建发布，存在缺陷，已废弃（deprecated）并回退至 `0.1.0`，请始终使用 `0.1.0` 或更高稳定版本。

## 许可

[MIT](LICENSE)