Files
deepseek-harness/packages/host/directory-picker-native/README.zh.md
Huanqi Cao 089f4dfad8 feat(picker): open the Win32 folder dialog in-process over koffi
The modern IFileOpenDialog becomes the primary win32 tier: a koffi-driven
COM conversation on a worker_threads worker (the modal Show never blocks
the host event loop), per-monitor-v2 DPI via SetThreadDpiAwarenessContext,
and abort service by re-posting WM_CLOSE to the dialog thread's windows,
with terminate+unref as the last resort (Node cannot interrupt a thread
blocked in native code, and such a worker must never hold the process open).

The PowerShell chain stays as the fallback tier with its trigger widened
from ENOENT to any pwsh failure, closing the review-flagged PowerShell 6
regression (no WinForms: exit 1, not ENOENT, so 5.1 never ran).

Layering keeps per-file coverage honest on every host: pure sequencing and
the driver test against fakes anywhere; the bindings run against a mocked
koffi COM world (the session-persistence-jsonl technique); POSIX hosts
drive the real spawn plumbing to its koffi-load rejection; win32 hosts run
a real open-and-abort-close smoke. The smoke joins processBoundTests: a
worker blocked in a native modal wedges the threads pool's teardown, while
a fork contains it. The worker bundles as its own CJS tsdown entry
(workflow-workerthread's pattern; no TLA), and the host module is imported
statically so the node-half bundle stays chunk-free.

Built-plane and real-COM behavior verified on native Windows: standalone
probes for the source worker, the built CJS worker, and the driver's abort
path all open and close the real dialog.

Agent Notes: new implemented/feature/2026-08-02-win32-in-process-folder-dialog
(bilingual) owns the decision; the DPI note is re-scoped to the fallback tier
it now describes and its AutoUpgradeEnabled attribution corrected (.NET Core
3.0 rewrote FolderBrowserDialog; the opt-out arrived in .NET 6).
2026-08-05 00:31:43 +08:00

2.7 KiB
Raw Blame History

@deepseek-ai/dsh-host-directory-picker-native

English | 中文

目录选择 seam 的原生 OS 选择器后端:NativeDirectoryPicker 以 native 能力注册 ctx.directoryPicker,其 pick(signal) 每次调用打开一个原生选择器并解析出所选绝对路径(取消时为 null)。平台工具不经 shell 调用:macOS 使用 osascript,Linux 使用 Zenity 并以 KDialog 回退;调用方的中止信号会终止原生进程。Windows 在进程内打开现代 IFileOpenDialog——由 koffi 在 worker 线程上驱动的 COM 会话,带 per-monitor-v2 DPI 感知,中止时向对话框线程投递 WM_CLOSE——当该原生面不可用时回退到 PowerShell 承载的对话框(先 pwsh,再回退到每台 Windows 都自带的 Windows PowerShell 5.1);可解析但无法呈现对话框的 pwsh(PowerShell 6 没有 WinForms)同样落入该回退。只有操作者坐在宿主屏幕前时才可用——远程部署应组合 -browse。命令边界(DirectoryPickerRunner)与平台事实可注入,便于确定性测试。共享的免 shell 子进程运行器位于 dsh-native-command。

双面包:browser half(./client)向 ui-workspace 的两个目录流洞注册一个无渲染的流程占用者——每次 open 请求驱动 host.pickDirectory,并经洞的 owner 会话上报唯一结果(所选路径/取消/失败)。因此一行 cordis.yml 同时组合原生交互的两侧;client 侧不含任何能力 kind 分支,挂载第二个流程包会在加载期失败(洞为 single kind)。

模型体验

无。该后端服务于 GUI 宿主的目录选择;这里没有任何内容进入模型请求。

KV 缓存影响

无;该包既不组装也不发送提供方请求。

已知限制与延期工作

  • Linux 依赖桌面工具——Zenity 与 KDialog 均未安装时,pick 以包含解决建议的错误拒绝;它不会回退为手输路径提示(组合层面的回退是 browse 后端)。
  • Windows 回退链会降级对话框——进程内选择器就是现代资源管理器风格对话框;koffi 无法驱动 COM 时由 PowerShell 层级接手,最终只到达 Windows PowerShell 5.1 的机器得到旧版文件夹树,DPI 已修正,但界面不是现代的。
  • 卡死的中止可能泄漏一个对话框线程——当 WM_CLOSE 始终投递不到(对话框窗口从未创建)时,driver 会 terminate 并 unref 该 worker;Node 无法打断阻塞在原生模态调用里的线程,因此该线程会存活到进程退出。