@deepseek-ai/dsh-client-ui-directory-picker-native 0.1.1-rc.2 → 0.1.2-alpha.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.i18n.yaml CHANGED
@@ -2,5 +2,5 @@
2
2
  # side as of the last confirmed-consistent state. Both languages carry equal authority;
3
3
  # after editing either side, bring the other along and re-record with:
4
4
  # pnpm run verify-translation-pairing --write packages/client/ui-directory-picker-native/README.md
5
- README.md: feb944b38a17086e0fcc6e4da52e1f16a4055166
6
- README.zh.md: c102d867e1828f95bddd51704a1c1af8bad71397
5
+ README.md: 56df434a1ddf386c44bb0818d3ca7c267b7e2695
6
+ README.zh.md: 9b19ec76538df10fbfa6ede04b8c00d2e5f1ed0c
package/README.md CHANGED
@@ -1,13 +1,63 @@
1
+ ---
2
+ description: "Native directory-picker surface: the browser half that drives the host OS chooser for workspace-directory flows; for users and maintainers choosing a picking interaction."
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @deepseek-ai/dsh-client-ui-directory-picker-native
2
7
 
3
8
  English | [中文](README.zh.md)
4
9
 
5
- Native directory-picker surface: the browser half of the native picking interaction. It fills ui-workspace's two directory-flow holes (`conversation.hero.workspace.directoryFlow` and `sidebar.workspaces.directoryFlow`) with a renderless occupant that answers each `open` request by driving the local Host's OS chooser through `ctx.workspaces.pickDirectory()`, then reports exactly one outcome — a picked path, a cancellation, or a failure — back through the owner conversation. The OS dialog itself belongs to [`dsh-host-directory-picker-native`](../../host/directory-picker-native/README.md); mounting this package composes the surface with that backend from one cordis.yml row, so no client code branches on a capability kind.
10
+ ## Summary
11
+
12
+ This package provides the native directory-picking surface for the Web GUI: when a workspace flow asks for a directory, a renderless browser occupant opens the operating system's own chooser on the machine running the Host and reports the single outcome — a picked path, a cancellation, or a failure. It fills the two directory-flow slots declared by `ui-workspace`, composing the client side of the native picking interaction in one cordis.yml row. Choose it when the browser runs on the same machine as the Host; in-process and remote-browser deployments need the [`-browse`](../ui-directory-picker-browse/README.md) surface instead.
13
+
14
+ ## Table of Contents
15
+
16
+ - [Use this package](#use-this-package)
17
+ - [Understand the implementation](#understand-the-implementation)
18
+ - [Further Exploration](#further-exploration)
19
+ - [Model Experience](#model-experience)
20
+ - [Known Limitations and Deferred Work](#known-limitations-and-deferred-work)
21
+ - [Dev Note](#dev-note)
22
+
23
+ -----
24
+
25
+ <a id="use-this-package"></a>
26
+ ## Use this package
27
+
28
+ Mount this plugin alongside `ui-workspace` and the host backend [`dsh-host-directory-picker-native`](../../host/directory-picker-native/README.md); one cordis.yml row then composes the whole native picking interaction. When a workspace add or picker flow opens a directory request, the user sees the operating system's folder dialog; the picked path is adopted by the workspace flow, and cancelling closes the dialog.
29
+
30
+ ### When to choose it
31
+
32
+ Choose this surface when the browser runs on the same machine as the Host, so an OS dialog can open there. Choose the [`-browse`](../ui-directory-picker-browse/README.md) surface when the browser is remote or in-process and no local chooser exists. The two surfaces fill the same slots, so switching is a composition change, not a code change.
33
+
34
+ -----
35
+
36
+ <a id="understand-the-implementation"></a>
37
+ ## Understand the implementation
38
+
39
+ <details>
40
+ <summary>Implementation internals — click to expand</summary>
6
41
 
7
- Both registrations install as one transactional effect through nested `slots.inject()` calls, because either declaring entry may activate later or replace its declaration. The occupant arms once per rising `open` edge, so re-renders — including an adoption that keeps `open` true while `busy` — never launch a second chooser, and the owner withdrawing `open` re-arms the next request. Settlements ride a ref so the answer reaches the owner's latest handlers rather than the ones captured when the chooser opened. An unmount (HMR replacing the occupant) discards the settlement wholesale: the wire carries no per-request abort, so the host-side chooser survives until answered, its answer lands nowhere, and the replacement instance re-arms under the owner's still-open request.
42
+ Both slot registrations install as one transactional effect through nested `ctx.slots.inject()` calls, because either declaring entry may activate later or replace its declaration. The occupant arms once per rising `open` edge, so re-renders never launch a second chooser; settlements ride a ref so the answer reaches the owner's latest handlers. An unmount (HMR replacing the occupant) discards the settlement wholesale: the wire carries no per-request abort, so the host-side chooser survives until answered and its answer lands nowhere. The node half is an empty `apply` that keeps the plugin on the host roster.
8
43
 
9
- The node half is an empty `apply`: it exists so the plugin appears in the host cordis.yml and Loader, while the browser half ships through `exports["./client"]` and is discovered through the `dsh.client` manifest declaration.
44
+ </details>
10
45
 
46
+ -----
47
+
48
+ <a id="further-exploration"></a>
49
+ ## Further Exploration
50
+
51
+ Read these pages when the picking surface is not enough. They move from the browser half to the host backend and the slots it fills.
52
+
53
+ - [dsh-host-directory-picker-native](../../host/directory-picker-native/README.md) — the OS chooser backend this surface drives.
54
+ - [ui-workspace](../ui-workspace/README.md) — declares the directory-flow slots and owns the picking conversation.
55
+ - [ui-directory-picker-browse](../ui-directory-picker-browse/README.md) — the in-app browsing alternative for remote and in-process deployments.
56
+ - [Web client architecture](../../../.agents/notes/implemented/architecture/2026-07-19-gui-web-client-architecture.md) — how browser plugin rows load and register slots.
57
+
58
+ -----
59
+
60
+ <a id="model-experience"></a>
11
61
  ## Model Experience
12
62
 
13
63
  None, as the directory chooser is browser chrome; nothing here reaches a model request.
@@ -18,5 +68,20 @@ None; this package neither assembles nor sends a provider request.
18
68
 
19
69
  ## Known Limitations and Deferred Work
20
70
 
21
- - **No cancellation of an open chooser** — the wire has no per-request abort, so a chooser already on the host display cannot be closed from the browser; a discarded settlement is simply ignored.
71
+ <a id="known-limitations-and-deferred-work"></a>
72
+
73
+
74
+ These limits define when the native chooser fits. They are current package constraints, not a general picker comparison or a task backlog.
75
+
76
+ - **No cancellation of an open chooser** — the wire has no per-request abort, so a chooser already on the host display cannot be closed from the browser; a discarded settlement is ignored.
22
77
  - **Local Host carriers only** — an OS dialog opens on the machine running the Host, so in-process and remote-browser deployments need the `-browse` composition instead. Platform failures surface through the owner's retryable folder dialog.
78
+
79
+ <a id="dev-note"></a>
80
+ ### Dev Note
81
+
82
+ <details>
83
+ <summary>Working context for maintainers — click to expand</summary>
84
+
85
+ None.
86
+
87
+ </details>
package/README.zh.md CHANGED
@@ -1,13 +1,63 @@
1
+ ---
2
+ description: "原生目录选择表面:驱动宿主操作系统选择器的浏览器半部,用于工作区目录流程;供选择拾取交互的用户与维护者阅读。"
3
+ kind: "package-reference"
4
+ ---
5
+
1
6
  # @deepseek-ai/dsh-client-ui-directory-picker-native
2
7
 
3
8
  [English](README.md) | 中文
4
9
 
5
- 原生目录选择界面:原生选取交互的浏览器半边。它通过 ui-workspace 的两个 directory-flow 洞(`conversation.hero.workspace.directoryFlow` 与 `sidebar.workspaces.directoryFlow`)装入一个无渲染占位者,每次收到 `open` 请求就用 `ctx.workspaces.pickDirectory()` 驱动本地 Host 的操作系统选择框,然后通过 owner 会话回报恰好一个结果——选中的路径、取消、或失败。系统对话框本身属于 [`dsh-host-directory-picker-native`](../../host/directory-picker-native/README.zh.md);挂载本包即用一行 cordis.yml 把界面与该后端组合起来,因此没有任何客户端代码按能力种类分支。
10
+ ## 概述
11
+
12
+ 本包提供 Web GUI 的原生目录拾取表面:当工作区流程请求一个目录时,一个无渲染的浏览器填充会在运行宿主的机器上打开操作系统自带的选择器,并回报唯一结果——拾取的路径、取消或失败。它填充 `ui-workspace` 声明的两个目录流程槽位,用一行 cordis.yml 组合出原生拾取交互的客户端一侧。当浏览器与宿主运行在同一台机器上时选择它;进程内与远程浏览器部署则需要 [`-browse`](../ui-directory-picker-browse/README.zh.md) 表面。
13
+
14
+ ## 目录
15
+
16
+ - [使用本包](#use-this-package)
17
+ - [理解实现](#understand-the-implementation)
18
+ - [进一步探索](#further-exploration)
19
+ - [模型体验](#model-experience)
20
+ - [已知限制与延期工作](#known-limitations-and-deferred-work)
21
+ - [开发备注](#dev-note)
22
+
23
+ -----
24
+
25
+ <a id="use-this-package"></a>
26
+ ## 使用本包
27
+
28
+ 与 `ui-workspace` 及宿主后端 [`dsh-host-directory-picker-native`](../../host/directory-picker-native/README.zh.md) 一起挂载本插件;一行 cordis.yml 随即组合出完整的原生拾取交互。当工作区添加或选择器流程发起目录请求时,用户看到操作系统的文件夹对话框;拾取的路径被工作区流程采纳,取消则关闭对话框。
29
+
30
+ ### 何时选择
31
+
32
+ 当浏览器与宿主运行在同一台机器上、操作系统对话框可以在那里打开时,选择此表面。当浏览器为远程或进程内、没有本地选择器时,选择 [`-browse`](../ui-directory-picker-browse/README.zh.md) 表面。两个表面填充相同的槽位,因此切换只是组合改动,而非代码改动。
33
+
34
+ -----
35
+
36
+ <a id="understand-the-implementation"></a>
37
+ ## 理解实现
38
+
39
+ <details>
40
+ <summary>实现细节——点击展开</summary>
6
41
 
7
- 两处注册通过嵌套的 `slots.inject()` 作为一个事务性 effect 安装,因为任一声明方条目都可能稍后激活或替换其声明。占位者在每个 `open` 上升沿只武装一次,所以重渲染(包括采纳期间 `busy` 而 `open` 仍为真)都不会再开第二个选择框;owner 撤回 `open` 会为下一次请求重新武装。结果经由 ref 回报,因此答案落到 owner 最新的处理器上,而不是打开选择框时捕获的那一套。卸载(HMR 替换占位者)会整体丢弃该结果:wire 上没有按请求的中止通道,所以 Host 侧的选择框会一直存在到被回答,它的答案无处可落,替换后的实例则在 owner 仍然打开的请求下重新武装。
42
+ 两个槽位注册经嵌套的 `ctx.slots.inject()` 调用作为一次事务性效果安装,因为任一声明条目都可能晚些激活或替换其声明。填充在每个上升沿 `open` 时只武装一次,因此重渲染永远不会再拉起一个选择器;结算结果挂在 ref 上,让答复到达持有方最新的处理器。卸载(HMR 替换填充)会整体丢弃结算:线上没有按请求中止的机制,因此宿主侧选择器会一直存活到被答复,而它的答复无处落地。node 半部是一个空 `apply`,让插件留在宿主名单上。
8
43
 
9
- node 半边是一个空 `apply`:它的存在只为让插件出现在 host 的 cordis.yml 与 Loader 中,浏览器半边经 `exports["./client"]` 出货,并通过 `dsh.client` 清单声明被发现。
44
+ </details>
10
45
 
46
+ -----
47
+
48
+ <a id="further-exploration"></a>
49
+ ## 进一步探索
50
+
51
+ 当拾取面不够用时阅读以下页面。它们从浏览器半部进入宿主后端与它所填充的槽位。
52
+
53
+ - [dsh-host-directory-picker-native](../../host/directory-picker-native/README.zh.md)——本表面驱动的操作系统选择器后端。
54
+ - [ui-workspace](../ui-workspace/README.zh.md)——声明目录流程槽位并拥有拾取对话。
55
+ - [ui-directory-picker-browse](../ui-directory-picker-browse/README.zh.md)——面向远程与进程内部署的应用内浏览替代方案。
56
+ - [Web 客户端架构](../../../.agents/notes/implemented/architecture/2026-07-19-gui-web-client-architecture.zh.md)——浏览器插件行如何加载并注册槽位。
57
+
58
+ -----
59
+
60
+ <a id="model-experience"></a>
11
61
  ## 模型体验
12
62
 
13
63
  无,因为目录选择器属于浏览器界面;本包中的任何内容都不会进入模型请求。
@@ -16,7 +66,22 @@ node 半边是一个空 `apply`:它的存在只为让插件出现在 host 的
16
66
 
17
67
  无;本包既不组装也不发送 provider 请求。
18
68
 
19
- ## 已知限制与暂缓事项
69
+ ## 已知限制与延期工作
70
+
71
+ <a id="known-limitations-and-deferred-work"></a>
72
+
73
+
74
+ 这些限制界定了原生选择器的适用时机。它们是当前包约束,不是通用选择器对比或任务积压。
75
+
76
+ - **无法取消已打开的选择器**——线上没有按请求中止的机制,因此已显示在宿主上的选择器无法从浏览器关闭;被丢弃的结算会被忽略。
77
+ - **仅限本地宿主承载**——操作系统对话框在运行宿主的机器上打开,因此进程内与远程浏览器部署需要 `-browse` 组合。平台失败经由持有方的可重试文件夹对话框呈现。
78
+
79
+ <a id="dev-note"></a>
80
+ ### 开发备注
81
+
82
+ <details>
83
+ <summary>维护者的工作上下文——点击展开</summary>
84
+
85
+ 无。
20
86
 
21
- - **无法取消已打开的选择框** —— wire 上没有按请求的中止通道,因此已经出现在 Host 显示器上的选择框无法从浏览器关闭;被丢弃的结果只是被忽略。
22
- - **仅限本地 Host 载体** —— 系统对话框开在运行 Host 的机器上,所以进程内与远程浏览器部署需要改用 `-browse` 组合。平台失败通过 owner 的可重试文件夹对话框呈现。
87
+ </details>
package/lib/client.js CHANGED
@@ -51,8 +51,8 @@ window.__ModuleLoader__.load({
51
51
  }
52
52
  //#endregion
53
53
  //#region lib/types/client/index.js
54
- /** Required services (cordis fiber inject): the slot registry and the wire-facing workspace service. */
55
- const inject = ["slots", "workspaces"];
54
+ /** Required services (cordis fiber inject): the slot registry and workspace UI service. */
55
+ const inject = ["slots", "uiWorkspace"];
56
56
  /**
57
57
  * Client plugin body: register the renderless native flow into both
58
58
  * directory-flow holes through `slots.inject()` because the ui-workspace
@@ -60,7 +60,7 @@ window.__ModuleLoader__.load({
60
60
  * @param ctx - client root context.
61
61
  */
62
62
  function apply(ctx) {
63
- const injected = () => ({ pick: () => ctx.workspaces.pickDirectory() });
63
+ const injected = () => ({ pick: () => ctx.uiWorkspace.pickDirectory() });
64
64
  ctx.slots.inject("conversation.hero.workspace.directoryFlow", () => ctx.slots.inject("sidebar.workspaces.directoryFlow", function* () {
65
65
  yield ctx.slots.register({
66
66
  name: "conversation.hero.workspace.directoryFlow",
@@ -1,14 +1,14 @@
1
1
  /**
2
2
  * Browser half of the native directory-picker backend: fills ui-workspace's
3
3
  * two directory-flow holes with a renderless occupant that answers each
4
- * `open` by driving `host.pickDirectory` (the node half's OS chooser) and
4
+ * `open` by driving `directoryPicker/pick` (the node half's OS chooser) and
5
5
  * reporting the one outcome — picked path, cancellation, or failure — back
6
6
  * through the owner conversation. Mounting this package therefore composes
7
7
  * both sides of the native interaction with one cordis.yml row; no client
8
8
  * code branches on a capability kind.
9
9
  */
10
- import type { ClientContext } from '@deepseek-ai/dsh-client-runtime/client';
11
- /** Required services (cordis fiber inject): the slot registry and the wire-facing workspace service. */
10
+ import type { Context as ClientContext } from '@deepseek-ai/cordis';
11
+ /** Required services (cordis fiber inject): the slot registry and workspace UI service. */
12
12
  export declare const inject: string[];
13
13
  /**
14
14
  * Client plugin body: register the renderless native flow into both
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@deepseek-ai/dsh-client-ui-directory-picker-native",
3
3
  "description": "Native directory-picker surface: the renderless workspace directory-flow occupant driving the host's OS chooser",
4
- "version": "0.1.1-rc.2",
4
+ "version": "0.1.2-alpha.2",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -32,7 +32,7 @@
32
32
  "dsh": {
33
33
  "client": {
34
34
  "inject": [
35
- "@deepseek-ai/dsh-client-runtime",
35
+ "@deepseek-ai/dsh-client-ui-renderer",
36
36
  "@deepseek-ai/dsh-client-ui-workspace"
37
37
  ],
38
38
  "platform": "web"
@@ -40,20 +40,17 @@
40
40
  },
41
41
  "license": "MIT",
42
42
  "peerDependencies": {
43
- "@deepseek-ai/dsh-client-ui-workspace": "^0.1.1-rc.2",
44
- "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
45
- "@deepseek-ai/cordis": "^4.0.1",
46
- "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2"
43
+ "@deepseek-ai/cordis": "^4.0.2"
47
44
  },
48
45
  "devDependencies": {
49
46
  "@testing-library/react": "^16.1.0",
50
47
  "@types/react": "~18.3.1",
51
48
  "react": "^18.2.0",
52
49
  "react-dom": "^18.2.0",
53
- "@deepseek-ai/dsh-client-ui-workspace": "^0.1.1-rc.2",
54
- "@deepseek-ai/dsh-invariants": "^0.1.1-rc.2",
55
- "@deepseek-ai/dsh-client-runtime": "^0.1.1-rc.2",
56
- "@deepseek-ai/cordis": "^4.0.1"
50
+ "@deepseek-ai/dsh-client-ui-workspace": "^0.1.2-alpha.2",
51
+ "@deepseek-ai/dsh-invariants": "^0.1.2-alpha.2",
52
+ "@deepseek-ai/cordis": "^4.0.2",
53
+ "@deepseek-ai/dsh-client-ui-renderer": "^0.1.2-alpha.2"
57
54
  },
58
55
  "files": [
59
56
  "lib/index.js",