diff --git a/README.en.md b/README.en.md index f7ba2c1..f5d4e74 100644 --- a/README.en.md +++ b/README.en.md @@ -87,6 +87,28 @@ credentials included. Since a device holding the tokenized link already has full the shipped loopback isolation. Set it to `false` to restore that posture and change settings locally through `127.0.0.1:3080` (or an `ssh -L 3080:127.0.0.1:3080 ` tunnel). +## The directory picker behind "Add workspace" + +`directory-picker-auto` picks ONE backend at boot from **host-side** facts: `native` requires "a +loopback-only bind (an all-interfaces bind admits remote browsers no OS chooser can reach)" plus a +servable display. This bundle deliberately keeps the official webserver on loopback (the LAN is a +separate listener on 3082), so a LAN deployment still resolves to `native` — and the dialog opens on +the **server machine**, where the remote operator can neither see nor reach it. + +This bundle's patch therefore pins the `browse` pair, the documented way to force an interaction +("pinning an interaction remains composing that pair directly instead of this row"): + +- `@deepseek-ai/dsh-host-directory-picker-browse` (backend) +- `@deepseek-ai/dsh-client-ui-directory-picker-browse` (surface) + +That backend lists the server's directory tree inside the page; upstream describes it as serving +"remote clients the dialog backend cannot". + +**Tradeoff**: the seam mounts exactly one backend per process, so a **local page switches to the +in-page browser too** — there is no "native locally, in-page remotely" combination. To restore the +adaptive choice, remove the last three entries of `cordis.patch.yml` (the +`- id: directory-picker / disabled: true` entry and the `insert` block after it). + ## Troubleshooting | Symptom | Cause and fix | diff --git a/README.md b/README.md index 15320e5..ee5686b 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,25 @@ DSH 官方把「持久化设置」限制在回环页面:客户端由 `location 回环隔离 —— 设为 `false` 即回到官方姿态,设置请在本机通过 `127.0.0.1:3080`(或 `ssh -L 3080:127.0.0.1:3080 <主机>` 隧道)修改。 +## 添加工作区的目录选择器 + +`directory-picker-auto` 在启动时按**服务器侧**事实选一个后端:`native` 要求「仅绑回环 + 非 SSH + +有可用显示器」,理由是「全网卡绑定意味着存在操作系统对话框够不到的远程浏览器」。本插件刻意让官方 +服务器保持回环(LAN 由 3082 独立转发),于是局域网部署仍被判为 `native` —— 对话框会在**服务器 +本机**弹出,远程操作者既看不到也点不到。 + +因此本插件的 patch 按官方文档的方式锁定 `browse` 这一对(`directory-picker-auto` 的文档写明 +「pinning an interaction remains composing that pair directly instead of this row」): + +- `@deepseek-ai/dsh-host-directory-picker-browse`(后端) +- `@deepseek-ai/dsh-client-ui-directory-picker-browse`(界面) + +该后端在页面内列出服务器目录树,官方描述为「serves remote clients the dialog backend cannot」。 + +**取舍**:这个 seam 每个进程只能挂一个后端,所以**本地页面也会改用页面内浏览**,不再弹操作系统 +对话框(也就是说"本地原生、远程网页"无法并存)。想恢复自适应选择,删掉 `cordis.patch.yml` 里 +最后那三行即可(`- id: directory-picker / disabled: true` 与其后的 `insert` 块)。 + ## 排障 | 现象 | 原因与处理 | diff --git a/cordis.patch.yml b/cordis.patch.yml index 991e626..750bce4 100644 --- a/cordis.patch.yml +++ b/cordis.patch.yml @@ -1,12 +1,15 @@ # @sutong/dsh-lan-access — bundle patch. # -# This patch only INSERTS one row and overrides no shipped row. That is a -# deliberate design property: the LAN listener is a separate socket that -# forwards to the loopback web server, so nothing in the official composition -# (webserver bind, connection trust fence, launch token) has to change, and a -# failure or a manual disable of this row cannot break the loopback Web UI. +# The LAN listener itself overrides no shipped row: it is a separate socket that +# forwards to the loopback web server, so the official webserver bind, the +# connection trust fence, and the launch token stay untouched, and disabling +# this bundle cannot break the loopback Web UI. # -# The row is an ordinary Cordis plugin activated by package name. +# The overrides below are UI-facing and deliberate. Each is explained where it +# appears and can be removed on its own. + +# ── the LAN listener ───────────────────────────────────────────────────────── +# An ordinary Cordis plugin activated by package name. - insert: - id: dsh-lan-access name: '@sutong/dsh-lan-access' @@ -23,3 +26,27 @@ # authorization — but that settings UI reads and writes server settings, # credentials included. Set this to false to keep the shipped posture. ownsHostCompat: true + +# ── pin the in-browser directory picker ────────────────────────────────────── +# +# "Add workspace" asks the directory-picker seam for a folder. Its chooser row +# resolves ONE backend at boot from host facts, and `native` requires "a +# loopback-only bind (an all-interfaces bind admits remote browsers no OS +# chooser can reach)" plus a servable display. This bundle keeps the official +# webserver on loopback by design, so a LAN deployment still resolves to +# `native` — and the OS dialog opens on the server, where the remote operator +# cannot see or reach it. +# +# Pinning the `browse` pair is the documented way to force an interaction +# ("pinning an interaction remains composing that pair directly instead of this +# row"), and that backend "serves remote clients the dialog backend cannot". +# The seam mounts exactly one backend per process, so this also applies to a +# local page: it trades the OS dialog for the in-page browser everywhere. +# Remove these three entries to get the adaptive choice back. +- id: directory-picker + disabled: true +- insert: + - id: directory-picker-browse + name: '@deepseek-ai/dsh-host-directory-picker-browse' + - id: ui-directory-picker-browse + name: '@deepseek-ai/dsh-client-ui-directory-picker-browse'