- Escape (and the mask) now reaches only the topmost dialog: while the nested New-folder dialog is up the browser ignores its own Modal close, and the nested dialog's in-flight fence keeps both open during creation. - New folder disables while any listing loads, so a slow post-create relist/select sequence cannot host a second create against a target the pending listing is about to change. - Deep ancestry scrolls inside a dedicated crumb trail whose tail is pinned into view; the path-edit zone keeps its reserved width instead of being clipped by the card, preserving cross-drive path entry. - The workspace-management e2e records a directory-browser aria golden at a staged tree (host HOME pointed at the scaffold cwd collapses ancestry into the Home crumb, keeping the artifact machine-independent), and the keyless snapshot's row targeting goes through visible label text — listitem accessible-name computation differs across dom-accessibility-api environments (the CI-only miss).
@deepseek-ai/dsh-host-directory-picker-browse
English | 中文
The in-app browsing backend of the directory-picker seam: BrowseDirectoryPicker registers ctx.directoryPicker with the browse capability — one-level directory listing and child-directory creation over Node's stdlib, which already carries the per-OS adaptation. Nothing renders on the host display, so this backend serves remote clients the native backend cannot.
Behavior facts: listings return directories only, name-sorted, with symlinks-to-directories followed (broken/cyclic links skipped — the probe stat failing means "not enterable") and a host-owned hidden flag (POSIX dot convention) left for the client to act on; crumbs is the root-to-target ancestor chain, the root crumb labeled by its full path (/, C:\); an absent list path means the host account's home directory. createDirectory is non-recursive (a missing parent is a real failure, not a level to invent) and validates the name as a single non-blank segment even when called directly, mirroring the wire schema's fence. Both primitives reject an explicit path that is not fully qualified — relative forms, and on Windows the rooted drive-less forms (\foo, /foo) and incomplete UNC prefixes (\\, \\server) that isAbsolute accepts — with directory-unreadable/directory-create-failed, instead of letting resolve rebase it under the host process cwd or current drive. Failures throw the seam's typed DirectoryPickerError. Policy rationale: the directory-picker capability seam Agent Note.
Dual-face package: the browser half (./client) fills ui-workspace's two directory-flow holes with the in-app Select Workspace Directory dialog (figma Harness 813-23126 family — Miller two-column view, breadcrumb with a click-to-edit path zone, nested New-folder dialog), driving host.listDirectory/host.createDirectory and registering its own locale namespace (directory-browser, zh default / en). One cordis.yml row therefore composes both sides of the browse interaction; the client carries no capability-kind branching, and mounting a second flow package fails at load (the holes are single kind).
Model Experience
None, as the backend serves the GUI host's directory selection; nothing here reaches a model request.
KV Cache effect
None; this package neither assembles nor sends a provider request.
Known Limitations and Deferred Work
- Windows hidden attribute is not read — Node dirents do not expose
FILE_ATTRIBUTE_HIDDEN, sohiddenmeans dot-prefixed on every platform until a native probe is worth its cost. - No drive-root enumeration — on Windows the ancestry stops at the drive root; crossing drives waits for the browser UI's path-entry affordance rather than an enumeration primitive here.
- Whole-filesystem scope — no per-deployment browse-root restriction;
workspace.createaccepts arbitrary paths today, so a root here would be UX scoping, not a boundary — deferred until a deployment needs it.