dsh-multi-folder 0.1.7 → 0.2.1

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.md CHANGED
@@ -34,6 +34,15 @@ dsh plugin --profile web add dsh-multi-folder
34
34
 
35
35
  Then **restart the DSH backend** (host composition loads at process start) and **refresh the browser page** (the client bundle is served `no-cache`).
36
36
 
37
+ ## Compatibility
38
+
39
+ Choose the plugin version that matches your DeepSeek Harness release:
40
+
41
+ | DeepSeek Harness | Install |
42
+ | --- | --- |
43
+ | 0.1.1 or earlier | `dsh-multi-folder@0.1.7` |
44
+ | 0.1.2-alpha or later | the latest `dsh-multi-folder` |
45
+
37
46
  ## Usage
38
47
 
39
48
  A Multi-folder button appears in the session header, and a second entry appears on the **session-creation page**: a chip row directly above the composer card (the same band the git-branch chip uses), aligned with the workspace/preset chips of the new-session screen. Clicking it opens the panel as a popover anchored to the chip. Exactly one session-creation entry is ever shown — the plugin registers three candidate seats and elects the best available one (upstream `conversation.hero.workspaceExtras` chip > `conversation.input.dock` row > fixed bottom-right launcher for shells declaring neither). The panel lets you:
package/README.zh.md CHANGED
@@ -34,6 +34,15 @@ dsh plugin --profile web add dsh-multi-folder
34
34
 
35
35
  然后**重启 DSH 后端**(宿主组合在进程启动时装载)并**刷新浏览器页面**(客户端 bundle 以 `no-cache` 提供)。
36
36
 
37
+ ## 兼容性
38
+
39
+ 请选择与你的 DeepSeek Harness 版本匹配的插件版本:
40
+
41
+ | DeepSeek Harness | 安装 |
42
+ | --- | --- |
43
+ | 0.1.1 及更早 | `dsh-multi-folder@0.1.7` |
44
+ | 0.1.2-alpha 及更新 | 最新版 `dsh-multi-folder` |
45
+
37
46
  ## 使用
38
47
 
39
48
  会话头部出现「多工作目录」按钮(英文界面显示 "Multi-folder");**会话创建页**的入口位于**输入框上方**——与 git 分支胶囊同一条 dock 带,左边缘对齐新会话界面的工作区/预设胶囊,点击后面板以锚定在该胶囊上的浮层展开。会话创建页始终只显示**一个**入口:插件注册三个候选座位并选用当前可用的最佳者(上游 `conversation.hero.workspaceExtras` chip > `conversation.input.dock` 行 > 两者皆未声明时的右下角浮动按钮)。打开面板即可:
package/docs/design.md CHANGED
@@ -154,8 +154,7 @@ window.__ModuleLoader__.load({
154
154
  - `inject: ['remote', 'remote.commands', 'slots', 'workspaces', 'connection', 'sessions', 'locale']`; the package's
155
155
  `dsh.client.inject` lists the packages providing them
156
156
  (`@deepseek-ai/dsh-api-gateway`, `@deepseek-ai/dsh-api-remotes`,
157
- `@deepseek-ai/dsh-client-connection`, `@deepseek-ai/dsh-client-locale`,
158
- `@deepseek-ai/dsh-client-runtime`).
157
+ `@deepseek-ai/dsh-client-connection`, `@deepseek-ai/dsh-client-locale`).
159
158
  - UI registrations: `conversation.session.header.actions` (session-scoped button),
160
159
  `shell.overlay` panel, `conversation.input.dock` chip row (session-scoped
161
160
  list entry above the composer card — the session-creation page's shipped
@@ -201,9 +200,13 @@ window.__ModuleLoader__.load({
201
200
  renders directly ABOVE the composer card, in the same band as the
202
201
  git-branch chip. The entry receives the dock owner share (`{ session,
203
202
  input }`) plus the standard `useSessions` / `useWorkspaces` selector hooks,
204
- so the hero phase (`composerPhase === 'blank' && (openState === 'open' ||
205
- blank)`) and the target workspace come from framework props instead of DOM
206
- probing. The row stays **in flow** — `display:flex` with the official hero
203
+ so the hero phase and the target workspace come from framework props instead
204
+ of DOM probing. Detection is DSH-version-adaptive: a shell whose
205
+ `SessionSnapshot` carries `composerPhase` uses
206
+ `composerPhase === 'blank' && (openState === 'open' || blank)`, while DSH
207
+ 0.1.2 (no `composerPhase`) uses the settled-blank fallback
208
+ `blank && !running && !promptAttempted && (openState === 'open' || blank)`.
209
+ The row stays **in flow** — `display:flex` with the official hero
207
210
  row's 20px indent, no absolute positioning — so the framework's list-slot
208
211
  arrangement keeps it clear of every other plugin's dock row. It renders
209
212
  only on the session-creation page; an active session keeps its entry in the
package/lib/client.js CHANGED
@@ -214,12 +214,13 @@ window.__ModuleLoader__.load({
214
214
 
215
215
  // ------------------------------------------------------------- plugin
216
216
  var name = 'dsh-multi-folder';
217
- var inject = ['remote', 'remote.commands', 'slots', 'workspaces', 'connection', 'sessions', 'locale'];
217
+ var inject = ['remote', 'remote.commands', 'slots', 'workspaces', 'uiWorkspace', 'connection', 'sessions', 'locale'];
218
218
 
219
219
  function apply(ctx) {
220
220
  var slots = ctx.slots;
221
221
  var remote = ctx.remote;
222
222
  var workspaces = ctx.workspaces;
223
+ var uiWorkspace = ctx.uiWorkspace;
223
224
  var connection = ctx.connection;
224
225
  var sessions = ctx.sessions;
225
226
  var locale = ctx.locale;
@@ -398,7 +399,18 @@ window.__ModuleLoader__.load({
398
399
  }
399
400
 
400
401
  function addDirectory() {
401
- workspaces.pickDirectory().then(function (path) {
402
+ // DSH 0.1.2 moved the directory picker onto `uiWorkspace`; earlier
403
+ // shells kept it on `workspaces`. Pick whichever service actually
404
+ // exposes it (and call it with the right receiver), surfacing a clear
405
+ // error when neither does instead of throwing synchronously.
406
+ var picker = (uiWorkspace && typeof uiWorkspace.pickDirectory === 'function')
407
+ ? uiWorkspace
408
+ : (workspaces && typeof workspaces.pickDirectory === 'function') ? workspaces : null;
409
+ if (picker === null) {
410
+ patch({ error: 'multi-folder: the directory picker service is unavailable' });
411
+ return;
412
+ }
413
+ picker.pickDirectory().then(function (path) {
402
414
  if (path === null || path === undefined) return;
403
415
  var snapshot = getSnapshot();
404
416
  if (snapshot.sessionId) {
@@ -763,10 +775,22 @@ window.__ModuleLoader__.load({
763
775
  /** The shell's own hero predicate, read from the dock's owner share: a
764
776
  * blank conversation with an open session. A still-loading blank
765
777
  * session already lists as blank, so it may enter the hero phase
766
- * before the composer snapshot settles to `open`. */
778
+ * before the composer snapshot settles to `open`.
779
+ *
780
+ * DSH 0.1.2 exposes no `composerPhase` on SessionSnapshot; the hero
781
+ * phase there is a settled blank session (mirroring ConversationRoot's
782
+ * `hero = sessionId === undefined || (shellPhase === 'blank' && ...)`),
783
+ * so the blank/lifecycle fields are used as the fallback. Newer DSH
784
+ * shells that do carry `composerPhase` keep their original check. */
767
785
  function isHeroPhase(session, blank) {
768
786
  if (!session) return false;
769
- return session.composerPhase === 'blank' && (session.openState === 'open' || blank === true);
787
+ if (session.composerPhase !== undefined) {
788
+ return session.composerPhase === 'blank' && (session.openState === 'open' || blank === true);
789
+ }
790
+ return session.blank === true
791
+ && !session.running
792
+ && !session.promptAttempted
793
+ && (blank === true || session.openState === 'open');
770
794
  }
771
795
 
772
796
  /** The workspace path a session belongs to, from the workspaces list. */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-multi-folder",
3
- "version": "0.1.7",
3
+ "version": "0.2.1",
4
4
  "description": "DeepSeek Harness plugin: secondary working directories for a project. The agent keeps the primary workspace as cwd, gains equal write/exec permissions on configured secondary directories under workspace-write mode, and is notified of configuration changes at the next message boundary. Configurable from the session header AND from the session-creation page (before the first message) through a sessionless multiFolder remote API.",
5
5
  "keywords": [
6
6
  "dsh-plugin",
@@ -42,7 +42,8 @@
42
42
  "compatibility": {
43
43
  "node": ">=20",
44
44
  "dshReleases": {
45
- "0.1.1-rc.2": "compatible"
45
+ "0.1.1-rc.2": "incompatible",
46
+ "0.1.2-alpha.1": "compatible"
46
47
  }
47
48
  },
48
49
  "bundle": {
@@ -54,8 +55,7 @@
54
55
  "@deepseek-ai/dsh-api-gateway",
55
56
  "@deepseek-ai/dsh-api-remotes",
56
57
  "@deepseek-ai/dsh-client-connection",
57
- "@deepseek-ai/dsh-client-locale",
58
- "@deepseek-ai/dsh-client-runtime"
58
+ "@deepseek-ai/dsh-client-locale"
59
59
  ]
60
60
  }
61
61
  },