@cerbur/clutch-dsh-worktree 0.1.5 → 0.1.7
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 +167 -24
- package/README.zh.md +141 -19
- package/cordis.patch.yml +21 -0
- package/lib/client/WorktreeContext.d.ts.map +1 -1
- package/lib/client/WorktreeContext.js +2 -2
- package/lib/client/WorktreeContext.js.map +1 -1
- package/lib/client/WorktreeHeroContext.d.ts +1 -1
- package/lib/client/WorktreeHeroContext.js +1 -1
- package/lib/client/WorktreeSurface.d.ts +2 -2
- package/lib/client/WorktreeSurface.d.ts.map +1 -1
- package/lib/client/WorktreeSurface.js +592 -124
- package/lib/client/WorktreeSurface.js.map +1 -1
- package/lib/client/entry.d.ts.map +1 -1
- package/lib/client/entry.js +87 -2
- package/lib/client/entry.js.map +1 -1
- package/lib/client/index.d.ts +3 -0
- package/lib/client/index.d.ts.map +1 -1
- package/lib/client/index.js +2 -0
- package/lib/client/index.js.map +1 -1
- package/lib/client/locales.d.ts +82 -0
- package/lib/client/locales.d.ts.map +1 -1
- package/lib/client/locales.js +84 -2
- package/lib/client/locales.js.map +1 -1
- package/lib/client/session-view.d.ts +34 -0
- package/lib/client/session-view.d.ts.map +1 -1
- package/lib/client/session-view.js +119 -1
- package/lib/client/session-view.js.map +1 -1
- package/lib/client/virtual-workspace-membership.js +1 -1
- package/lib/client/virtual-workspace-membership.js.map +1 -1
- package/lib/client/worktree-connection.d.ts +6 -2
- package/lib/client/worktree-connection.d.ts.map +1 -1
- package/lib/client/worktree-connection.js +8 -0
- package/lib/client/worktree-connection.js.map +1 -1
- package/lib/client/worktree-error-copy.d.ts +2 -0
- package/lib/client/worktree-error-copy.d.ts.map +1 -1
- package/lib/client/worktree-error-copy.js +22 -0
- package/lib/client/worktree-error-copy.js.map +1 -1
- package/lib/client/worktree-expand-state.d.ts +33 -0
- package/lib/client/worktree-expand-state.d.ts.map +1 -0
- package/lib/client/worktree-expand-state.js +83 -0
- package/lib/client/worktree-expand-state.js.map +1 -0
- package/lib/client/worktree-permission-icon.d.ts +7 -0
- package/lib/client/worktree-permission-icon.d.ts.map +1 -0
- package/lib/client/worktree-permission-icon.js +119 -0
- package/lib/client/worktree-permission-icon.js.map +1 -0
- package/lib/client/worktree-permission.d.ts +21 -0
- package/lib/client/worktree-permission.d.ts.map +1 -0
- package/lib/client/worktree-permission.js +70 -0
- package/lib/client/worktree-permission.js.map +1 -0
- package/lib/client/worktree-session-fork.d.ts +65 -0
- package/lib/client/worktree-session-fork.d.ts.map +1 -0
- package/lib/client/worktree-session-fork.js +174 -0
- package/lib/client/worktree-session-fork.js.map +1 -0
- package/lib/client/worktree-session-order.d.ts +36 -0
- package/lib/client/worktree-session-order.d.ts.map +1 -0
- package/lib/client/worktree-session-order.js +215 -0
- package/lib/client/worktree-session-order.js.map +1 -0
- package/lib/client/worktree-session-position.d.ts +2 -0
- package/lib/client/worktree-session-position.d.ts.map +1 -0
- package/lib/client/worktree-session-position.js +11 -0
- package/lib/client/worktree-session-position.js.map +1 -0
- package/lib/client/worktree-session.d.ts +34 -1
- package/lib/client/worktree-session.d.ts.map +1 -1
- package/lib/client/worktree-session.js +98 -2
- package/lib/client/worktree-session.js.map +1 -1
- package/lib/client/worktree-surface-dialogs.d.ts +1 -1
- package/lib/client/worktree-surface-dialogs.d.ts.map +1 -1
- package/lib/client/worktree-surface-dialogs.js +30 -13
- package/lib/client/worktree-surface-dialogs.js.map +1 -1
- package/lib/client/worktree-surface-rows.d.ts +4 -4
- package/lib/client/worktree-surface-rows.d.ts.map +1 -1
- package/lib/client/worktree-surface-rows.js +132 -47
- package/lib/client/worktree-surface-rows.js.map +1 -1
- package/lib/client/worktree-surface-selectors.d.ts +18 -0
- package/lib/client/worktree-surface-selectors.d.ts.map +1 -1
- package/lib/client/worktree-surface-selectors.js +62 -0
- package/lib/client/worktree-surface-selectors.js.map +1 -1
- package/lib/client/worktree-surface-types.d.ts +73 -3
- package/lib/client/worktree-surface-types.d.ts.map +1 -1
- package/lib/client/worktree-view-actions.d.ts +11 -3
- package/lib/client/worktree-view-actions.d.ts.map +1 -1
- package/lib/client/worktree-view-actions.js +31 -2
- package/lib/client/worktree-view-actions.js.map +1 -1
- package/lib/client/worktree-view-errors.d.ts +10 -0
- package/lib/client/worktree-view-errors.d.ts.map +1 -1
- package/lib/client/worktree-view-errors.js +22 -1
- package/lib/client/worktree-view-errors.js.map +1 -1
- package/lib/client/worktree-view-read.d.ts +8 -0
- package/lib/client/worktree-view-read.d.ts.map +1 -1
- package/lib/client/worktree-view-read.js +19 -0
- package/lib/client/worktree-view-read.js.map +1 -1
- package/lib/client.js +2047 -264
- package/lib/client.js.map +1 -1
- package/lib/contract/index.contract.js +16 -0
- package/lib/contract/index.contract.js.map +1 -1
- package/lib/contract/index.d.ts +26 -2
- package/lib/contract/index.d.ts.map +1 -1
- package/lib/contract/index.js +8 -0
- package/lib/contract/index.js.map +1 -1
- package/lib/contract/worktree-permission.d.ts +73 -0
- package/lib/contract/worktree-permission.d.ts.map +1 -0
- package/lib/contract/worktree-permission.js +32 -0
- package/lib/contract/worktree-permission.js.map +1 -0
- package/lib/host/index.d.ts +4 -0
- package/lib/host/index.d.ts.map +1 -1
- package/lib/host/index.js +2 -0
- package/lib/host/index.js.map +1 -1
- package/lib/host/remote.d.ts +2 -2
- package/lib/host/remote.d.ts.map +1 -1
- package/lib/host/remote.js +9 -1
- package/lib/host/remote.js.map +1 -1
- package/lib/host/service.d.ts +10 -1
- package/lib/host/service.d.ts.map +1 -1
- package/lib/host/service.js +48 -2
- package/lib/host/service.js.map +1 -1
- package/lib/host/worktree-permission-manager.d.ts +14 -0
- package/lib/host/worktree-permission-manager.d.ts.map +1 -0
- package/lib/host/worktree-permission-manager.js +111 -0
- package/lib/host/worktree-permission-manager.js.map +1 -0
- package/lib/host/worktree-permission.d.ts +38 -0
- package/lib/host/worktree-permission.d.ts.map +1 -0
- package/lib/host/worktree-permission.js +156 -0
- package/lib/host/worktree-permission.js.map +1 -0
- package/lib/index.d.ts +4 -3
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +2 -1
- package/lib/index.js.map +1 -1
- package/lib/manage/manager-support.d.ts +2 -0
- package/lib/manage/manager-support.d.ts.map +1 -1
- package/lib/manage/manager-support.js +9 -0
- package/lib/manage/manager-support.js.map +1 -1
- package/lib/manage/manager-worktrees.d.ts +10 -1
- package/lib/manage/manager-worktrees.d.ts.map +1 -1
- package/lib/manage/manager-worktrees.js +121 -5
- package/lib/manage/manager-worktrees.js.map +1 -1
- package/lib/manage/manager.d.ts +8 -1
- package/lib/manage/manager.d.ts.map +1 -1
- package/lib/manage/manager.js +7 -1
- package/lib/manage/manager.js.map +1 -1
- package/lib/manage/worktree-permission.d.ts +3 -0
- package/lib/manage/worktree-permission.d.ts.map +1 -0
- package/lib/manage/worktree-permission.js +3 -0
- package/lib/manage/worktree-permission.js.map +1 -0
- package/lib/provider/git.d.ts +2 -0
- package/lib/provider/git.d.ts.map +1 -1
- package/lib/provider/git.js +23 -1
- package/lib/provider/git.js.map +1 -1
- package/lib/provider/index.d.ts +1 -1
- package/lib/provider/index.d.ts.map +1 -1
- package/lib/provider/index.js +1 -1
- package/lib/provider/index.js.map +1 -1
- package/lib/provider/sidecar-schema.d.ts +1 -1
- package/lib/provider/sidecar-schema.d.ts.map +1 -1
- package/lib/provider/sidecar-schema.js +33 -37
- package/lib/provider/sidecar-schema.js.map +1 -1
- package/lib/provider/sidecar.d.ts.map +1 -1
- package/lib/provider/sidecar.js +3 -1
- package/lib/provider/sidecar.js.map +1 -1
- package/lib/provider/types.d.ts +9 -1
- package/lib/provider/types.d.ts.map +1 -1
- package/lib/provider/types.js +2 -1
- package/lib/provider/types.js.map +1 -1
- package/lib/typert.host.js +214 -21
- package/lib/typert.remote-client.d.ts +9 -1
- package/lib/typert.remote-client.d.ts.map +1 -1
- package/lib/typert.remote-client.js +214 -21
- package/package.json +30 -30
package/README.md
CHANGED
|
@@ -12,18 +12,57 @@ The plugin stores only external Worktree/Session relationship metadata.
|
|
|
12
12
|
The English screenshot shows Worktree mode in the Sidebar, a Workspace tree with Main and
|
|
13
13
|
Worktree rows, and the read-only blank-session Hero context.
|
|
14
14
|
|
|
15
|
+

|
|
16
|
+
|
|
17
|
+
The Import screenshot shows the existing Workspace `+` dialog with Create selected by default,
|
|
18
|
+
the adjacent Import tab, and a standard dropdown containing safe example branch/path values.
|
|
19
|
+
|
|
15
20
|
## Capabilities
|
|
16
21
|
|
|
17
22
|
- Enter Worktree mode from the DSH Sidebar footer and browse Workspace → Worktree → Session.
|
|
18
23
|
- Search Workspaces and create a Git Worktree and branch from an existing local branch.
|
|
24
|
+
- Choose Import in the same dialog to discover unmanaged, branch-attached Git Worktrees linked to the Workspace repository. The first version omits the repository root and detached HEAD entries.
|
|
25
|
+
- Register an existing Worktree in place without moving, copying, or editing its directory; the imported record uses `source: external` and then follows the same Session, binding, health, ordering, cwd, projection, refresh, and recovery flow as a plugin-created record.
|
|
26
|
+
- Remove plugin-created and imported Worktrees through real `git worktree remove`; removing an imported Worktree can delete its linked directory and is called out in the confirmation dialog.
|
|
19
27
|
- Create a normal Session from Main or a Session whose runtime cwd is an active Worktree, then
|
|
20
28
|
open it directly.
|
|
29
|
+
- For active Worktree Sessions, request the named `worktree-full-access` preset after an
|
|
30
|
+
explicit confirmation. It combines DSH `danger-full-access` with `ask`: it removes filesystem
|
|
31
|
+
confinement for linked Git metadata while keeping approval prompts enabled; network and
|
|
32
|
+
process policy are unchanged. The native Access menu marks `Worktree Full Access` with a
|
|
33
|
+
Worktree branch icon.
|
|
34
|
+
- Preserve an explicit restriction selected in DSH's native Access UI. If the custom preset is
|
|
35
|
+
unavailable, fall back to `workspace-write + ask` when possible; if the permission capability
|
|
36
|
+
cannot be verified, show a retryable degraded state instead of claiming Full Access.
|
|
37
|
+
- Reuse the native `StateDot` for Session status indicators. Running, running-subagent, warning,
|
|
38
|
+
and completed states occupy the trailing slot; idle Sessions show native relative time for the
|
|
39
|
+
last human-authored message there. Hover or an open menu gives the trailing slot back to the
|
|
40
|
+
existing actions menu.
|
|
41
|
+
- Show the native DSH Session hover detail card with the complete title, relative time, and current
|
|
42
|
+
status; the card yields to the Session actions menu and row dragging.
|
|
43
|
+
- Cover native waiting-for-approval, plan-review, question, completed, idle, and running-subagent
|
|
44
|
+
states without copying the animation implementation into the plugin.
|
|
45
|
+
- Show one native running indicator on a collapsed Workspace, Main, or Worktree when any of its
|
|
46
|
+
non-archived Sessions is active; expanded groups keep their normal action rail instead.
|
|
47
|
+
- Promote a Session to the head of its Main or Worktree visual group after a newer user message.
|
|
48
|
+
This ordering is browser-local and does not mutate DSH Workspace order or the Worktree sidecar.
|
|
49
|
+
- Fork a Session from the native DSH Workspace tab, the Worktree view, or the Conversation fork
|
|
50
|
+
action. When the parent has an active Worktree binding, the child is bound to the same Worktree,
|
|
51
|
+
then added to the browser-local Workspace membership projection after the binding refresh; the
|
|
52
|
+
child remains a normal DSH Session. The refresh ordering keeps it from briefly appearing in
|
|
53
|
+
Main/Local. A sidecar failure keeps the child available and exposes retryable binding recovery.
|
|
21
54
|
- See ready, repair, active, and detached Worktree states, including retryable operation errors.
|
|
22
|
-
-
|
|
23
|
-
|
|
55
|
+
- Use the shared Main and Worktree row options menu to copy the selected row's absolute path.
|
|
56
|
+
Main and detached rows show only `Copy path`; active Worktree rows also show `Remove Worktree`
|
|
57
|
+
with confirmation.
|
|
58
|
+
- Create a new Worktree from the Local or an active Worktree's options menu. The Create dialog
|
|
59
|
+
uses the selected row's current branch as its base and suggests the next available numbered
|
|
60
|
+
name, such as `feature-2` or `feature-3`; detached Worktrees do not expose this action.
|
|
24
61
|
- Continue using DSH-native Workspace rename/delete/reorder and Session menus. Worktree rows can
|
|
25
62
|
be reordered within their owning Workspace; order is stored in the plugin sidecar and Main is
|
|
26
63
|
fixed first.
|
|
64
|
+
- Persist Workspace, Main, and Worktree expansion choices in browser-local storage; the five-row Session overflow state remains transient and resets after refresh or parent collapse.
|
|
65
|
+
- Highlight the DSH current Session in Worktree view; entering Worktree mode or switching the current Session temporarily reveals its Workspace/Main/Worktree path, expands Session overflow only when the row is outside the first five, clears a hiding search, and scrolls the row into view; this browser-local behavior does not change persisted expansion choices.
|
|
27
66
|
- Keep the current local branch or Worktree branch visible as read-only context in the existing
|
|
28
67
|
Conversation title row and in the blank-session Hero.
|
|
29
68
|
- Keep Conversation and Hero context stable across same-Session snapshot updates and Session
|
|
@@ -33,10 +72,18 @@ Worktree rows, and the read-only blank-session Hero context.
|
|
|
33
72
|
`WT` button when the Sidebar is collapsed.
|
|
34
73
|
- Keep Worktree Sessions in the original DSH Project/Workspace view; the plugin does not copy
|
|
35
74
|
Session content or modify messages, prompts, transcripts, or history.
|
|
75
|
+
- Worktree fork membership is not written to DSH's durable `Workspace.sessionIds`. While this
|
|
76
|
+
plugin is loaded, the browser can show the child through its local projection; without the
|
|
77
|
+
plugin, the child remains in DSH's global Session management but is not durably attached to the
|
|
78
|
+
native Workspace root membership.
|
|
36
79
|
|
|
37
80
|
### Compatibility and prerequisites
|
|
38
81
|
|
|
39
|
-
-
|
|
82
|
+
- For development and source validation, use a clean checkout of the official [DeepSeek Harness
|
|
83
|
+
repository](https://github.com/deepseek-ai/deepseek-harness) on its current default branch. The
|
|
84
|
+
repository currently uses `master` rather than `main`; it is developer-preview software, so its
|
|
85
|
+
package and API contracts may change. Run the upstream install/build steps before installing
|
|
86
|
+
this plugin into that profile.
|
|
40
87
|
- The target profile, such as `web` or `demo`, must already start successfully, and the plugin
|
|
41
88
|
must be installed into the same profile that launches the Web UI.
|
|
42
89
|
- DSH Client must provide the native `@deepseek-ai/dsh-client-ui-conversation` package and its
|
|
@@ -79,6 +126,20 @@ To inspect the currently published version on the official registry:
|
|
|
79
126
|
npm view @cerbur/clutch-dsh-worktree version --registry=https://registry.npmjs.org/
|
|
80
127
|
```
|
|
81
128
|
|
|
129
|
+
### Prepare the current upstream DSH checkout
|
|
130
|
+
|
|
131
|
+
For source-based development or validation, prepare the upstream checkout first. The current
|
|
132
|
+
upstream default branch is `master`; follow the repository's default branch if it changes later.
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
git clone https://github.com/deepseek-ai/deepseek-harness.git
|
|
136
|
+
cd deepseek-harness
|
|
137
|
+
git fetch origin
|
|
138
|
+
git pull --ff-only origin master
|
|
139
|
+
pnpm install
|
|
140
|
+
pnpm run build
|
|
141
|
+
```
|
|
142
|
+
|
|
82
143
|
### Install from a repository checkout
|
|
83
144
|
|
|
84
145
|
Build the package from the `clutch-dsh` checkout, then install its absolute path into the DSH
|
|
@@ -172,45 +233,117 @@ blank-session Hero. The displayed language follows DSH's current language settin
|
|
|
172
233
|
|
|
173
234
|
1. Select a Workspace, press its `+`, choose a baseline local branch, and enter a Worktree name.
|
|
174
235
|
The default branch name is `dsh/<8-character-random-string>`.
|
|
175
|
-
2.
|
|
236
|
+
2. To create a sibling from an existing Worktree, open that active Worktree's options menu and
|
|
237
|
+
choose `Create new Worktree`. The dialog preselects the Worktree branch as the base and
|
|
238
|
+
chooses the next available numeric suffix for the name; existing names are skipped.
|
|
239
|
+
3. The target Worktree path must be absolute, belong to the same Project, and differ from the
|
|
176
240
|
Project root. Relative paths, a different Project, or the Project root are rejected.
|
|
177
|
-
|
|
241
|
+
4. Git must be installed and available on `PATH`. A missing Git executable shows install guidance
|
|
178
242
|
and no command block; install Git, restart DSH, and retry. If the repository, initial commit,
|
|
179
243
|
or local branch is missing, follow the copyable setup commands in the dialog. The plugin only
|
|
180
244
|
renders this guidance; it does not run setup or installation commands or edit business files.
|
|
181
245
|
|
|
246
|
+
### Import an existing Worktree
|
|
247
|
+
|
|
248
|
+
1. Select a Workspace, press its `+`, and choose the `Import` tab. The dialog loads Git-linked
|
|
249
|
+
Worktrees for that repository through the existing DSH `/api` Connection.
|
|
250
|
+
2. The first version lists only branch-attached, non-root Worktrees that are not already present
|
|
251
|
+
in the plugin sidecar. Detached HEAD entries are intentionally omitted. Candidates are presented
|
|
252
|
+
in a standard dropdown; each option shows its branch first and absolute path as secondary
|
|
253
|
+
diagnostic text.
|
|
254
|
+
3. Choose an option and select `Import Worktree`. Registration writes only the plugin sidecar;
|
|
255
|
+
the existing Worktree directory and Git working state remain in place. Import then creates or
|
|
256
|
+
reuses a Session at that Worktree cwd and runs the same bind → open → binding refresh flow as
|
|
257
|
+
Create. Newly created Sessions are not projected into native Workspace membership before the
|
|
258
|
+
binding refresh.
|
|
259
|
+
4. An active external import for the same Workspace and physical path is idempotent. A path already
|
|
260
|
+
managed by the plugin returns `WORKTREE_ALREADY_MANAGED`; invalid or stale candidates return
|
|
261
|
+
`WORKTREE_IMPORT_INVALID` and can be retried after the repository state is fixed.
|
|
262
|
+
|
|
182
263
|
### Create Main and Worktree Sessions
|
|
183
264
|
|
|
184
265
|
- Use Main's `+` to create a normal DSH Session in the Project-root view.
|
|
185
|
-
- Use a Worktree's `+` to create or reuse a Session with that Worktree as its runtime cwd.
|
|
186
|
-
|
|
187
|
-
external binding
|
|
188
|
-
|
|
266
|
+
- Use a Worktree's `+` to create or reuse a Session with that Worktree as its runtime cwd. The
|
|
267
|
+
plugin calls the upstream runtime with `session.create({ cwd: worktreePath })`, then saves the
|
|
268
|
+
external binding and opens the Session. The browser-local `{ workspaceId, sessionId }` membership
|
|
269
|
+
projection is refreshed afterward, so the newly created Session does not briefly appear in Main.
|
|
189
270
|
- The connector reuses an unarchived blank Session with the exact target cwd when possible. An
|
|
190
271
|
already-bound Session opens directly; an unbound candidate is bound before projection and
|
|
191
|
-
opening. Otherwise the flow is `create → bind →
|
|
192
|
-
same Worktree are coalesced.
|
|
272
|
+
opening. Otherwise the new-Session flow is `create → bind → open → refresh`, and concurrent
|
|
273
|
+
clicks for the same Worktree are coalesced.
|
|
193
274
|
- If binding fails after DSH has created the Session, the Session ID remains available for Retry
|
|
194
275
|
or Open recovery. The plugin does not delete or mutate that DSH Session.
|
|
276
|
+
- Before opening an active Worktree Session, the plugin explains in a DSH-styled in-page dialog why
|
|
277
|
+
linked Git metadata may need access outside the Session directory. The dialog requires an explicit
|
|
278
|
+
risk acknowledgement; cancelling keeps the Session and binding, does not change permissions, and
|
|
279
|
+
leaves a retryable pending state. The native DSH Access selector remains the way to switch to
|
|
280
|
+
another permission mode.
|
|
195
281
|
- A provisional blank Session follows DSH's native display rules: it is shown only in the
|
|
196
282
|
selected view, uses the localized `New Session` label, hides its generated ID, and has no
|
|
197
283
|
Rename, Fork, or Archive menu. After the first prompt is accepted, it becomes an ordinary
|
|
198
284
|
Session row; hiding the blank row does not delete the Session or its Worktree binding.
|
|
199
285
|
|
|
286
|
+
### Session activity and ordering
|
|
287
|
+
|
|
288
|
+
- Session rows reuse DSH's native `StateDot`: running Sessions, Sessions with running subagents,
|
|
289
|
+
waiting approval, plan review, question, and completed states show their status dot in the
|
|
290
|
+
trailing slot instead of relative time. Idle Sessions use that slot for the native compact
|
|
291
|
+
relative-time label.
|
|
292
|
+
- The trailing metadata uses the native compact buckets (`now`, minutes, hours, days, months, and
|
|
293
|
+
years). It is based on DSH's `updatedAt`, which advances with the latest human-authored message;
|
|
294
|
+
blank New Session rows have no time label. The display follows snapshot renders and does not add
|
|
295
|
+
an independent minute ticker.
|
|
296
|
+
- Hovering a Worktree Session row opens the native detail card after 500 ms with its full title,
|
|
297
|
+
relative time, and status; the card is suppressed while the Session menu is open or a row is
|
|
298
|
+
being dragged.
|
|
299
|
+
- A collapsed Workspace, Main group, or Worktree group shows the same running dot when any
|
|
300
|
+
non-archived member is ongoing, including activity hidden by search. Expanding the group hides
|
|
301
|
+
the aggregate dot; hover, focus, or an open menu reveals the existing action controls.
|
|
302
|
+
- A newer user message promotes its Session to the head of the current Main or Worktree visual
|
|
303
|
+
group. The promotion, observed timestamps, and per-group order live only in browser-local state;
|
|
304
|
+
successful manual drag still uses the native DSH ordering API before updating that local order.
|
|
305
|
+
|
|
306
|
+
### Fork Worktree Sessions
|
|
307
|
+
|
|
308
|
+
- Use any native DSH fork entry point: a Session-list tab, a Worktree Session menu, or the
|
|
309
|
+
Conversation fork action. The plugin wraps the shared DSH `sessions.fork` service, so the
|
|
310
|
+
original fork cut, title increment, and child lineage stay native.
|
|
311
|
+
- After DSH creates the child, the plugin looks up the parent's active sidecar binding, writes the
|
|
312
|
+
child binding through the existing `/api` Manager. The Worktree view refreshes the binding before
|
|
313
|
+
replaying the browser-local Workspace membership projection, so the child does not briefly appear
|
|
314
|
+
in Main/Local; ready content is retained during that refresh.
|
|
315
|
+
- If the child is created but sidecar lookup or binding fails, DSH keeps the child and the plugin
|
|
316
|
+
shows Retry Binding/Open Created Session recovery. A later plugin initialization also retries
|
|
317
|
+
recoverable fork children from native Session lineage summaries; it never binds unrelated
|
|
318
|
+
subagents automatically.
|
|
319
|
+
- This flow does not persist the child into DSH `Workspace.sessionIds`. The native DSH Workspace
|
|
320
|
+
view can only see the temporary browser projection while the plugin is loaded; the durable native
|
|
321
|
+
Workspace data is unchanged.
|
|
322
|
+
|
|
200
323
|
### Reorder and manage Worktrees
|
|
201
324
|
|
|
202
325
|
- Drag Worktrees within their owning Workspace. The ordered `worktrees` array is persisted in
|
|
203
326
|
the plugin sidecar; Main is a fixed first row and Worktrees cannot move across Workspaces.
|
|
204
|
-
-
|
|
205
|
-
detached Worktrees
|
|
327
|
+
- Open the shared Main and Worktree options menu to copy the selected row's absolute path. Main
|
|
328
|
+
and detached/removed Worktrees show only `Copy path`; active Worktrees also show `Remove
|
|
329
|
+
Worktree` with a confirmation dialog.
|
|
330
|
+
- Imported Worktrees expose the same active options menu as plugin-created Worktrees. Removing
|
|
331
|
+
either source runs real `git worktree remove`; for an imported Worktree, the confirmation warns
|
|
332
|
+
that the linked Worktree directory may be deleted. Sessions are retained as detached bindings.
|
|
206
333
|
- Removing a Worktree does not delete its Sessions. The relationship remains detached until it
|
|
207
334
|
is explicitly unbound. Deleting a Workspace removes only DSH's Workspace registration; its
|
|
208
335
|
directory, Sessions, Git Worktrees, and plugin sidecar remain.
|
|
336
|
+
- After a successful removal, detached Sessions that still have Full Access are normalized to
|
|
337
|
+
`workspace-write + ask` when the public DSH permission service is available. An unavailable
|
|
338
|
+
service is reported as an unverified, retryable warning; it never grants Full Access to a
|
|
339
|
+
detached Session.
|
|
209
340
|
- DSH-native Workspace rename/delete/reorder and Session menus remain available. Session drag
|
|
210
341
|
ordering is limited to the current visual Main or Worktree group.
|
|
211
342
|
- The Main group shows the current local branch as `Local (branch)` and falls back to `Local` if
|
|
212
|
-
DSH reports no current branch.
|
|
213
|
-
|
|
343
|
+
DSH reports no current branch. When a Workspace is imported from a Git subdirectory, the Git
|
|
344
|
+
root is resolved first and the same branch/worktree information is used as for the root.
|
|
345
|
+
Branch names, paths, Workspace names, Session titles, and raw DSH/Git errors keep their
|
|
346
|
+
original values.
|
|
214
347
|
- Existing Sessions show read-only context in the form `Session title` → `Agent mode` →
|
|
215
348
|
`current branch / Worktree branch`. Long values remain ellipsized in the compact chip and show
|
|
216
349
|
their complete value in a hover card. The blank Hero shows `Workspace (branch)` after the native
|
|
@@ -229,6 +362,9 @@ blank-session Hero. The displayed language follows DSH's current language settin
|
|
|
229
362
|
commands, while repository, initial commit, or local branch failures show copyable setup
|
|
230
363
|
commands. Connection, Gateway, and unexpected Worktree-domain failures remain visible as
|
|
231
364
|
retryable errors rather than empty lists.
|
|
365
|
+
- Permission status is also explicit: Full Access, fallback `workspace-write`, preserved user
|
|
366
|
+
restriction, unverified capability, confirmation pending, and retryable setup failure are not
|
|
367
|
+
silently collapsed into an empty or falsely successful Worktree state.
|
|
232
368
|
- Refreshing an already-ready view preserves its current projection until replacement data is
|
|
233
369
|
available. Same-Session snapshot updates do not blank the context or trigger redundant reads;
|
|
234
370
|
initial entry and explicit Retry may show a loading state when no cached view is available.
|
|
@@ -254,6 +390,7 @@ an independent sidecar store and may contain only relationship facts such as:
|
|
|
254
390
|
|
|
255
391
|
- `projectId`, `worktreeId`, and `sessionId`;
|
|
256
392
|
- an absolute Worktree path, branch, and lifecycle state;
|
|
393
|
+
- the Worktree source (`plugin` or `external`);
|
|
257
394
|
- binding status and schema version.
|
|
258
395
|
|
|
259
396
|
The index is not written into a Project working tree or DSH's raw data directory. It does not
|
|
@@ -273,15 +410,21 @@ does not change the sidecar state, so the relationship remains retryable. Sessio
|
|
|
273
410
|
the native DSH API before binding; a binding failure never deletes or modifies the already-created
|
|
274
411
|
Session.
|
|
275
412
|
|
|
276
|
-
The
|
|
277
|
-
|
|
278
|
-
attach
|
|
279
|
-
projection is replayed after native list refreshes and removed when the binding
|
|
280
|
-
Client is disposed.
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
413
|
+
The Worktree session flow sends the independent Worktree cwd through the upstream DSH runtime and
|
|
414
|
+
keeps `{ workspaceId, sessionId }` as a browser-local membership projection rather than a
|
|
415
|
+
persistent DSH attach. It does not modify DSH source, Session metadata, or native Workspace
|
|
416
|
+
storage. The projection is replayed after native list refreshes and removed when the binding
|
|
417
|
+
disappears or the Client is disposed.
|
|
418
|
+
|
|
419
|
+
Permission changes use only the public DSH per-Session permission service and its
|
|
420
|
+
`permission/preset`, `sandbox/mode`, and `approval/policy` records. The plugin does not write
|
|
421
|
+
messages, prompts, transcripts, Workspace data, or Session metadata, and cannot enlarge a
|
|
422
|
+
filesystem sandbox imposed by the host running DSH.
|
|
423
|
+
|
|
424
|
+
The blank Hero context is visual only. Because the current upstream DSH source checkout has no
|
|
425
|
+
additive Hero headline slot, its placement depends on the native `[data-phase="hero"]` and title
|
|
426
|
+
anchors; it disappears when those anchors are unavailable and should move to a formal DSH slot
|
|
427
|
+
when one exists.
|
|
285
428
|
|
|
286
429
|
## Development and verification
|
|
287
430
|
|
package/README.zh.md
CHANGED
|
@@ -12,15 +12,50 @@ Session 元数据、原生列表和会话历史的唯一事实来源。插件只
|
|
|
12
12
|
中文截图展示了侧边栏中的 Worktree 模式、包含 Main 和 Worktree 行的 Workspace 树,以及
|
|
13
13
|
新会话空白 Hero 中的只读上下文。
|
|
14
14
|
|
|
15
|
+

|
|
16
|
+
|
|
17
|
+
导入截图展示了现有 Workspace `+` 弹窗:默认选中创建,旁边是导入 Tab,并在普通下拉框中
|
|
18
|
+
使用安全的示例 branch 和路径值。
|
|
19
|
+
|
|
15
20
|
## 能力
|
|
16
21
|
|
|
17
22
|
- 从 DSH Sidebar footer 进入 Worktree 模式,按 Workspace → Worktree → Session 浏览会话。
|
|
18
23
|
- 搜索 Workspace,并从已有 local branch 创建 Git Worktree 和 branch。
|
|
24
|
+
- 在同一个弹窗中选择导入,发现与当前 Workspace repository 关联、尚未由 sidecar 管理且绑定 branch 的 Git Worktree。第一版不展示 repository root 和 detached HEAD 条目。
|
|
25
|
+
- 导入只登记已有 Worktree,不移动、复制或编辑其目录;记录使用 `source: external`,之后与 plugin 创建的记录共享 Session、binding、health、排序、cwd、projection、刷新和恢复流程。
|
|
26
|
+
- plugin 创建和导入的 Worktree 都通过真实的 `git worktree remove` 移除;移除导入的 Worktree 可能删除其关联目录,确认弹窗会明确提示。
|
|
19
27
|
- 在 Main 或 active Worktree 下创建普通 Session 或 Worktree Session,并直接打开新会话。
|
|
28
|
+
- 对 active Worktree Session,先经明确确认,再请求命名的 `worktree-full-access` 预设。它将
|
|
29
|
+
DSH 的 `danger-full-access` 与 `ask` 组合:关闭关联 Git 元数据的文件系统限制,但保留
|
|
30
|
+
审批提示;网络和进程策略不变。原生 Access 菜单中的 `Worktree Full Access` 会显示
|
|
31
|
+
Worktree branch 图标。
|
|
32
|
+
- 保留用户在 DSH 原生 Access 界面中选择的限制。如果自定义预设不可用,在可能时回退到
|
|
33
|
+
`workspace-write + ask`;如果无法验证权限能力,则显示可重试的降级状态,不伪称已获得完全访问。
|
|
34
|
+
- 复用原生动画 `StateDot` 展示运行中的 Session,并为最近一条用户发送的 Session 消息显示
|
|
35
|
+
原生相对时间;hover 或打开菜单时,右侧位置让位给已有的操作菜单。
|
|
36
|
+
- 使用 DSH 原生 Session hover 详情卡片展示完整标题、相对时间和当前状态;打开 Session 操作
|
|
37
|
+
菜单或拖拽行时,详情卡片让位。
|
|
38
|
+
- 补齐原生的等待审批、计划待审、等待回答、已完成、空闲和运行中子代理状态;插件不会复制
|
|
39
|
+
原生动画实现。
|
|
40
|
+
- 当折叠的 Workspace、Main 或 Worktree 中存在任一未归档的活动 Session 时,在其右侧显示
|
|
41
|
+
一个原生运行指示器;展开后恢复普通操作栏。
|
|
42
|
+
- 用户在 Session 中发送新消息后,该 Session 会移动到当前 Main 或 Worktree 视觉分组的队首。
|
|
43
|
+
该排序只保存在浏览器本地,不修改 DSH Workspace 顺序或 Worktree sidecar。
|
|
44
|
+
- 从 DSH 原生 Workspace session list tab、Worktree view 或 Conversation fork 操作 fork
|
|
45
|
+
Session。parent 有 active Worktree binding 时,child 会先绑定到同一个 Worktree,再在 binding
|
|
46
|
+
refresh 完成后加入浏览器本地 Workspace membership projection;child 仍然是普通 DSH Session。
|
|
47
|
+
这一时序避免 child 短暂出现在 Main/Local。sidecar 失败时 child 会保留,并显示可重试的
|
|
48
|
+
binding 恢复操作。
|
|
20
49
|
- 查看 ready、repair、active 和 detached Worktree 状态,包括可重试的操作错误。
|
|
21
|
-
- 通过
|
|
50
|
+
- 通过 Main 和 Worktree 共用的选项菜单复制所选行的绝对路径;Main 和 detached 行只显示“复制路径”,
|
|
51
|
+
active Worktree 额外显示“移除 Worktree”并要求确认。
|
|
52
|
+
- 通过 Local 或 active Worktree 的选项菜单创建新的 Worktree。创建弹窗会以所选行的当前 branch
|
|
53
|
+
为基线,并预填下一个可用的递增名称,例如 `feature-2` 或 `feature-3`;detached Worktree
|
|
54
|
+
不显示该动作。
|
|
22
55
|
- 继续使用 DSH 原生的 Workspace rename/delete/reorder 和 Session 菜单。Worktree 可以在所属
|
|
23
56
|
Workspace 内排序;顺序保存在插件 sidecar 中,Main 固定在第一位。
|
|
57
|
+
- 将 Workspace、Main 和 Worktree 的展开选择保存到浏览器本地存储;Session 五行溢出展开保持临时状态,并在刷新或父级折叠后重置。
|
|
58
|
+
- 在 Worktree view 高亮 DSH 当前 Session;进入 Worktree 模式或切换当前会话时,临时展开其 Workspace/Main/Worktree 路径;只有当前行不在前五行时才展开 Session 五行溢出,随后清空隐藏它的搜索并滚动定位;这一浏览器本地行为不改变已保存的展开选择。
|
|
24
59
|
- 在已有 Conversation 的标题行以及新会话空白 Hero 中,以只读方式显示当前 local branch 或
|
|
25
60
|
Worktree branch 上下文。
|
|
26
61
|
- 在同一个 Session 的 snapshot 更新以及 Session 切换期间保持 Conversation 和 Hero 上下文
|
|
@@ -29,10 +64,16 @@ Session 元数据、原生列表和会话历史的唯一事实来源。插件只
|
|
|
29
64
|
对齐原生字体和排版,Sidebar 折叠后不再额外显示 `WT` 按钮。
|
|
30
65
|
- Worktree Session 仍出现在原始 DSH Project/Workspace 视角中;插件不复制 Session 内容,
|
|
31
66
|
也不修改消息、prompt、transcript 或历史记录。
|
|
67
|
+
- Worktree fork 的 membership 不会写入 DSH 持久化的 `Workspace.sessionIds`。plugin 加载期间,
|
|
68
|
+
浏览器可以通过本地 projection 显示 child;不加载 plugin 时,child 仍在 DSH 全局 Session 管理中,
|
|
69
|
+
但不会被持久化挂到 native Workspace root membership 下。
|
|
32
70
|
|
|
33
71
|
### 兼容性与前置条件
|
|
34
72
|
|
|
35
|
-
-
|
|
73
|
+
- 开发和源码验证应使用官方 [DeepSeek Harness 仓库](https://github.com/deepseek-ai/deepseek-harness)
|
|
74
|
+
的干净 checkout,并跟随仓库当前默认分支。该仓库当前使用 `master` 而不是 `main`,且仍是
|
|
75
|
+
developer preview,package 和 API contract 可能变化;在向 profile 安装本 plugin 前,先完成
|
|
76
|
+
upstream 的安装和构建步骤。
|
|
36
77
|
- 目标 profile(例如 `web` 或 `demo`)必须已经可以正常启动,且 plugin 必须安装到实际
|
|
37
78
|
启动 Web UI 的同一个 profile。
|
|
38
79
|
- DSH Client 必须提供原生 `@deepseek-ai/dsh-client-ui-conversation` package 及其
|
|
@@ -73,6 +114,20 @@ pnpm dsh web
|
|
|
73
114
|
npm view @cerbur/clutch-dsh-worktree version --registry=https://registry.npmjs.org/
|
|
74
115
|
```
|
|
75
116
|
|
|
117
|
+
### 准备当前 upstream DSH checkout
|
|
118
|
+
|
|
119
|
+
进行源码开发或验证时,先准备 upstream checkout。当前 upstream 默认分支是 `master`;如果仓库
|
|
120
|
+
未来切换默认分支,应跟随仓库的当前默认分支。
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
git clone https://github.com/deepseek-ai/deepseek-harness.git
|
|
124
|
+
cd deepseek-harness
|
|
125
|
+
git fetch origin
|
|
126
|
+
git pull --ff-only origin master
|
|
127
|
+
pnpm install
|
|
128
|
+
pnpm run build
|
|
129
|
+
```
|
|
130
|
+
|
|
76
131
|
### 从仓库 checkout 安装
|
|
77
132
|
|
|
78
133
|
先从 `clutch-dsh` checkout 构建 package,再把绝对路径安装到 DSH profile:
|
|
@@ -163,42 +218,102 @@ pnpm dsh plugin --profile web remove @cerbur/clutch-dsh-worktree
|
|
|
163
218
|
|
|
164
219
|
1. 选择 Workspace,点击它旁边的 `+`,选择基线 local branch,并填写 Worktree name。默认
|
|
165
220
|
branch 名称为 `dsh/<8-character-random-string>`。
|
|
166
|
-
2.
|
|
221
|
+
2. 如果要从已有 Worktree 创建同级 Worktree,打开该 active Worktree 的选项菜单并选择
|
|
222
|
+
`创建新的 Worktree`。弹窗会以当前 Worktree branch 作为基线,并为名称选择下一个可用的
|
|
223
|
+
递增序号;已有名称会被跳过。
|
|
224
|
+
3. 目标 Worktree 路径必须是绝对路径,属于同一个 Project,且不能是 Project 根目录。相对
|
|
167
225
|
路径、其他 Project 的路径或 Project 根目录都会被拒绝。
|
|
168
|
-
|
|
226
|
+
4. Git 必须已安装且可在 PATH 中使用。Git 可执行文件缺失时显示安装提示且不显示命令块;请
|
|
169
227
|
安装 Git、重启 DSH 后重试。如果缺少 repository、初始 commit 或本地 branch,按照弹窗中
|
|
170
228
|
的可复制 setup 命令修复后重试。插件只展示这些提示,不会执行 setup 或安装命令或编辑
|
|
171
229
|
业务文件。
|
|
172
230
|
|
|
231
|
+
### 导入已有 Worktree
|
|
232
|
+
|
|
233
|
+
1. 选择 Workspace,点击旁边的 `+`,再选择 `导入` Tab。弹窗通过现有 DSH `/api` Connection
|
|
234
|
+
加载该 repository 的 Git Worktree 候选项。
|
|
235
|
+
2. 第一版只列出绑定 branch、不是 repository root、且未出现在 plugin sidecar 中的 Worktree。
|
|
236
|
+
detached HEAD 会被省略;候选项通过普通下拉框选择,每个选项先显示 branch,再显示绝对路径
|
|
237
|
+
作为诊断信息。
|
|
238
|
+
3. 在下拉框中选择一个选项并点击 `导入 Worktree`。登记只写入 plugin sidecar,已有 Worktree 目录和 Git
|
|
239
|
+
工作状态保持不变。随后会在该 Worktree cwd 创建或复用 Session,并执行与创建相同的
|
|
240
|
+
`bind → open → binding refresh` 流程;新建 Session 不会在 binding 刷新前投影到原生
|
|
241
|
+
Workspace membership。
|
|
242
|
+
4. 同一 Workspace、同一物理路径的 active external 导入是幂等的。已经由 plugin 管理的路径
|
|
243
|
+
返回 `WORKTREE_ALREADY_MANAGED`;无效或过期候选项返回 `WORKTREE_IMPORT_INVALID`,修复
|
|
244
|
+
repository 状态后可以重试。
|
|
245
|
+
|
|
173
246
|
### 创建 Main 和 Worktree Session
|
|
174
247
|
|
|
175
248
|
- 使用 Main 的 `+`,在 Project 根目录视角中创建普通 DSH Session。
|
|
176
|
-
- 使用 Worktree 的 `+`,创建或复用 runtime cwd 指向该 Worktree 的 Session
|
|
177
|
-
|
|
178
|
-
|
|
249
|
+
- 使用 Worktree 的 `+`,创建或复用 runtime cwd 指向该 Worktree 的 Session。插件通过 upstream
|
|
250
|
+
runtime 调用 `session.create({ cwd: worktreePath })`,随后保存外部 binding 并打开该 Session。
|
|
251
|
+
当前浏览器内的 `{ workspaceId, sessionId }` membership projection 会在之后刷新,因此新建
|
|
252
|
+
Session 不会短暂出现在 Main 中。
|
|
179
253
|
- 如果存在目标 cwd 完全匹配的未归档 blank Session,连接器会优先复用它。已绑定的 Session
|
|
180
254
|
会直接打开;未绑定的候选会先 binding,再 projection 和打开。否则执行
|
|
181
|
-
`create → bind →
|
|
255
|
+
新建路径执行 `create → bind → open → refresh`,同一个 Worktree 的并发点击会合并。
|
|
182
256
|
- 如果 DSH 创建 Session 后 binding 失败,Session ID 仍会保留,可用于 Retry 或 Open 恢复。
|
|
183
257
|
插件不会删除或修改该 DSH Session。
|
|
258
|
+
- 打开 active Worktree Session 前,插件会在 DSH 风格的页面内弹窗中说明关联 Git 元数据为什么
|
|
259
|
+
可能需要访问 Session 目录之外的内容。弹窗要求明确勾选风险确认;取消会保留 Session 和
|
|
260
|
+
binding,不改变权限,并留下可重试的待处理状态。需要切换到其他权限模式时,继续使用 DSH
|
|
261
|
+
原生 Access 选择器。
|
|
184
262
|
- provisional blank Session 遵循 DSH 原生显示规则:只在当前选中的视角中显示,使用本地化
|
|
185
263
|
的 `New Session` 文案,不显示生成的 ID,也没有 Rename、Fork 或 Archive 菜单。接受第一条
|
|
186
264
|
prompt 后,它会变为普通 Session 行;隐藏 blank 行不会删除 Session 或 Worktree binding。
|
|
187
265
|
|
|
266
|
+
### Session 活动与排序
|
|
267
|
+
|
|
268
|
+
- Session 行复用 DSH 原生 `StateDot`:运行中的 Session 以及存在运行中子代理的 Session,使用
|
|
269
|
+
右侧动画点替代相对时间。等待审批、计划待审和等待回答使用原生 warning 点;已完成 Session
|
|
270
|
+
保留原生 completed 点。
|
|
271
|
+
- 右侧元数据使用原生紧凑时间单位(刚刚、分钟、小时、天、月、年),来源是 DSH 的
|
|
272
|
+
`updatedAt`,该字段随最近一条用户消息推进;空白 New Session 不显示时间。时间只在 snapshot
|
|
273
|
+
render 时按原生规则重新计算,不额外增加每分钟 ticker。
|
|
274
|
+
- 将鼠标悬停在 Worktree Session 行上 500 毫秒后,会打开原生详情卡片,展示完整标题、相对时间
|
|
275
|
+
和状态;Session 菜单打开或行正在拖拽时不显示卡片。
|
|
276
|
+
- 折叠的 Workspace、Main 或 Worktree 分组,只要任一未归档成员正在运行就显示相同的原生运行点,
|
|
277
|
+
即使该 Session 被搜索隐藏也会计入。展开后隐藏聚合点;hover、focus 或打开菜单时显示原有
|
|
278
|
+
操作控件。
|
|
279
|
+
- 用户发送新消息后,Session 会移动到当前 Main 或 Worktree 视觉分组队首。promotion、已观察
|
|
280
|
+
时间戳和每组顺序只存在浏览器本地;手动拖动仍先调用 DSH 原生排序 API,成功后再更新本地顺序。
|
|
281
|
+
|
|
282
|
+
### Fork Worktree Session
|
|
283
|
+
|
|
284
|
+
- 可以使用任意 DSH 原生 fork 入口:Session list 中的 tab、Worktree Session 菜单或
|
|
285
|
+
Conversation fork 操作。插件包装共享的 DSH `sessions.fork` service,因此原生的 fork cut、
|
|
286
|
+
标题递增和 child lineage 语义保持不变。
|
|
287
|
+
- DSH 创建 child 后,插件读取 parent 的 active sidecar binding,通过现有 `/api` Manager 写入
|
|
288
|
+
child binding。随后 Worktree view 先刷新 binding,再重放浏览器本地 Workspace membership
|
|
289
|
+
projection,因此 child 不会短暂出现在 Main/Local;刷新期间保留 ready 内容。
|
|
290
|
+
- 如果 child 已创建但 sidecar 查询或 binding 失败,DSH 仍保留 child,plugin 显示 Retry Binding/
|
|
291
|
+
Open Created Session 恢复操作。后续 plugin 初始化也会根据原生 Session lineage summary 重试可恢复
|
|
292
|
+
的 fork child;不会自动绑定无关的 subagent。
|
|
293
|
+
- 这一流程不会把 child 持久化写入 DSH `Workspace.sessionIds`。native DSH Workspace view 只有在
|
|
294
|
+
plugin 加载期间才能看到临时浏览器 projection;native Workspace 持久化数据保持不变。
|
|
295
|
+
|
|
188
296
|
### 排序与管理 Worktree
|
|
189
297
|
|
|
190
298
|
- 在所属 Workspace 内拖动 Worktree。排序持久化在 plugin sidecar 的有序 `worktrees` 数组中;
|
|
191
299
|
Main 是固定的第一行,Worktree 不能跨 Workspace 移动。
|
|
192
|
-
-
|
|
193
|
-
|
|
300
|
+
- 打开 Main 和 Worktree 共用的选项菜单复制所选行的绝对路径。Main 和 detached/removed Worktree
|
|
301
|
+
只显示“复制路径”;active Worktree 还显示“移除 Worktree”并要求确认。
|
|
302
|
+
- 导入的 Worktree 与 plugin 创建的 Worktree 显示相同的 active 选项菜单。两种来源都执行真实
|
|
303
|
+
`git worktree remove`;导入项的确认文案会警告关联 Worktree 目录可能被删除。Session 会
|
|
304
|
+
保留为 detached binding。
|
|
194
305
|
- 移除 Worktree 不会删除其 Session。关系会保留为 detached,直到显式解绑。删除 Workspace
|
|
195
306
|
只会删除 DSH 的 Workspace registration;其目录、Session、Git Worktree 和 plugin
|
|
196
307
|
sidecar 会保留。
|
|
308
|
+
- Worktree 成功移除后,如果公共 DSH 权限服务可用,仍处于完全访问的 detached Session 会
|
|
309
|
+
归一化为 `workspace-write + ask`。权限服务不可用时显示未验证且可重试的警告;不会向
|
|
310
|
+
detached Session 自动授予完全访问。
|
|
197
311
|
- DSH 原生的 Workspace rename/delete/reorder 和 Session 菜单继续可用。Session 拖动排序
|
|
198
312
|
限定在当前视觉 Main 或 Worktree 分组中。
|
|
199
313
|
- Main 分组显示当前 local branch:有分支时为 `本地(branch)`,DSH 没有返回当前分支时
|
|
200
|
-
回退为
|
|
201
|
-
|
|
314
|
+
回退为 `本地`。如果导入的 Workspace 是 Git 仓库中的子目录,会先解析 Git 根目录,再
|
|
315
|
+
复用与 Git 根目录相同的 branch/worktree 信息。branch 名称、路径、Workspace 名称、Session
|
|
316
|
+
标题以及原始 DSH/Git 错误信息保持原值。
|
|
202
317
|
- 已有 Session 会在标题行显示只读上下文,格式为 `Session title` → `Agent mode` →
|
|
203
318
|
`current branch / Worktree branch`。过长值在紧凑 chip 中折叠,并通过 hover card 显示完整
|
|
204
319
|
内容。原生标题存在且有锚点时,新会话空白 Hero 会在标题后显示 `Workspace (branch)`,并
|
|
@@ -218,6 +333,8 @@ pnpm dsh plugin --profile web remove @cerbur/clutch-dsh-worktree
|
|
|
218
333
|
- 已经 ready 的视角刷新时会保留当前 projection,直到替换数据可用。同一个 Session 的
|
|
219
334
|
snapshot 更新不会清空上下文,也不会触发重复读取;没有缓存视角时,首次进入和显式 Retry
|
|
220
335
|
可以显示 loading 状态。
|
|
336
|
+
- 权限状态会明确显示为完全访问、回退到 `workspace-write`、保留用户限制、能力未验证、
|
|
337
|
+
等待确认或可重试的设置失败,不会静默折叠为空列表或伪造成功。
|
|
221
338
|
|
|
222
339
|
## 界面语言
|
|
223
340
|
|
|
@@ -237,6 +354,7 @@ DSH 管理原始 Project/Workspace 身份和根目录、Session 身份和元数
|
|
|
237
354
|
|
|
238
355
|
- `projectId`、`worktreeId` 和 `sessionId`;
|
|
239
356
|
- 绝对 Worktree 路径、branch 和生命周期状态;
|
|
357
|
+
- Worktree 来源(`plugin` 或 `external`);
|
|
240
358
|
- binding 状态和 schema version。
|
|
241
359
|
|
|
242
360
|
索引不会写入 Project 工作树或 DSH 原始数据目录,也不会保存 `projectRoot` 副本或任何
|
|
@@ -252,14 +370,18 @@ Worktree binding 使用对应的 Worktree 路径。cwd 在每次执行时派生
|
|
|
252
370
|
创建的 Git Worktree。删除 Worktree 失败时不会改变 sidecar 状态,因此关系仍可重试。创建
|
|
253
371
|
Session 时先调用 DSH 原生 API,再写入 binding;binding 失败不会删除或修改已创建的 Session。
|
|
254
372
|
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
Session metadata 或原生 Workspace 存储。native list
|
|
258
|
-
|
|
373
|
+
Worktree Session 流程将独立的 Worktree cwd 交给 upstream DSH runtime,并将
|
|
374
|
+
`{ workspaceId, sessionId }` 保持为浏览器本地 membership projection,而不是持久化的 DSH
|
|
375
|
+
attach。它不会修改 DSH 源码、Session metadata 或原生 Workspace 存储。native list 刷新后会
|
|
376
|
+
重放 projection;binding 消失或 Client dispose 时会移除 projection。
|
|
377
|
+
|
|
378
|
+
权限变更只使用 DSH 公共的 per-Session 权限服务及其 `permission/preset`、`sandbox/mode`、
|
|
379
|
+
`approval/policy` 记录。插件不会写入消息、prompt、transcript、Workspace 数据或 Session
|
|
380
|
+
metadata,也不能扩大运行 DSH 的宿主沙箱边界。
|
|
259
381
|
|
|
260
|
-
空白 Hero
|
|
261
|
-
`[data-phase="hero"]`
|
|
262
|
-
|
|
382
|
+
空白 Hero 上下文只用于展示。由于当前 upstream DSH source checkout 没有 additive Hero
|
|
383
|
+
headline slot,它的位置依赖原生 `[data-phase="hero"]` 和标题锚点;锚点不可用时浮层会消失,
|
|
384
|
+
未来有正式 DSH slot 时应迁移到该 slot。
|
|
263
385
|
|
|
264
386
|
## 开发与验证
|
|
265
387
|
|
package/cordis.patch.yml
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
- id: permission
|
|
2
|
+
# DSH patch rows replace the whole config. Keep the upstream presets and add
|
|
3
|
+
# one named bundle; the plugin applies it only after an active Worktree
|
|
4
|
+
# binding is confirmed by the Host.
|
|
5
|
+
config:
|
|
6
|
+
presets:
|
|
7
|
+
read-only:
|
|
8
|
+
sandbox: read-only
|
|
9
|
+
approval: ask
|
|
10
|
+
workspace-write:
|
|
11
|
+
sandbox: workspace-write
|
|
12
|
+
approval: ask
|
|
13
|
+
danger-full-access:
|
|
14
|
+
sandbox: danger-full-access
|
|
15
|
+
approval: never
|
|
16
|
+
worktree-full-access:
|
|
17
|
+
sandbox: danger-full-access
|
|
18
|
+
approval: ask
|
|
19
|
+
name: Worktree Full Access
|
|
20
|
+
description: Full file access for Worktree metadata while keeping approval prompts enabled.
|
|
21
|
+
|
|
1
22
|
- insert:
|
|
2
23
|
- id: clutch-dsh-worktree-host
|
|
3
24
|
name: '@cerbur/clutch-dsh-worktree'
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorktreeContext.d.ts","sourceRoot":"","sources":["../../src/client/WorktreeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,YAAY,EAEb,MAAM,kCAAkC,CAAC;AAI1C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,mEAAmE;AACnE,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,eAAe,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;KAC/D,CAAC;CACH;AAID,0DAA0D;AAC1D,MAAM,MAAM,0BAA0B,GACpC,YAAY,CAAC,qCAAqC,CAAC,GACnD,WAAW,CAAC,OAAO,WAAW,CAAC,GAC/B,UAAU,CAAC,uBAAuB,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"WorktreeContext.d.ts","sourceRoot":"","sources":["../../src/client/WorktreeContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wCAAwC,CAAC;AAC5E,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,YAAY,EAEb,MAAM,kCAAkC,CAAC;AAI1C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACxE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,mEAAmE;AACnE,MAAM,WAAW,uBAAuB;IACtC,QAAQ,CAAC,KAAK,EAAE;QACd,QAAQ,CAAC,eAAe,EAAE,aAAa,CAAC,oBAAoB,CAAC,CAAC;KAC/D,CAAC;CACH;AAID,0DAA0D;AAC1D,MAAM,MAAM,0BAA0B,GACpC,YAAY,CAAC,qCAAqC,CAAC,GACnD,WAAW,CAAC,OAAO,WAAW,CAAC,GAC/B,UAAU,CAAC,uBAAuB,CAAC,CAAC;AA2BtC,oFAAoF;AACpF,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,kBAAkB,EAClB,CAAC,GACF,EAAE,0BAA0B,sCAI5B"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { IconBranchOutline16 } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
2
|
+
import { HoverCard, IconBranchOutline16 } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
3
3
|
import styles from './worktree-context.css';
|
|
4
4
|
function WorktreeContextLabel({ value, t, }) {
|
|
5
5
|
if (value.kind === 'none')
|
|
@@ -7,7 +7,7 @@ function WorktreeContextLabel({ value, t, }) {
|
|
|
7
7
|
const ariaLabel = value.kind === 'main'
|
|
8
8
|
? t('context.main', { name: value.label })
|
|
9
9
|
: t('context.worktree', { name: value.label });
|
|
10
|
-
return (_jsxs("span", { className: styles.headerContext, title: value.label, "aria-label": ariaLabel, children: [_jsx(IconBranchOutline16, { size: 14, className: styles.contextIcon, "aria-hidden": "true" }), _jsx("span", { className: styles.contextLabel, children: value.label })] }));
|
|
10
|
+
return (_jsx(HoverCard, { anchor: _jsxs("span", { className: styles.headerContext, title: value.label, "aria-label": ariaLabel, children: [_jsx(IconBranchOutline16, { size: 14, className: styles.contextIcon, "aria-hidden": "true" }), _jsx("span", { className: styles.contextLabel, children: value.label })] }), content: _jsx("div", { className: styles.contextHoverTitle, children: value.label }), openDelayMs: 500 }));
|
|
11
11
|
}
|
|
12
12
|
/** Render the current branch or active Worktree branch beside the Session title. */
|
|
13
13
|
export function WorktreeHeaderContext({ sessionId, useWorktreeContext, t, }) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorktreeContext.js","sourceRoot":"","sources":["../../src/client/WorktreeContext.tsx"],"names":[],"mappings":";AAOA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"WorktreeContext.js","sourceRoot":"","sources":["../../src/client/WorktreeContext.tsx"],"names":[],"mappings":";AAOA,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAKvF,OAAO,MAAM,MAAM,wBAAwB,CAAC;AAiB5C,SAAS,oBAAoB,CAAC,EAC5B,KAAK,EACL,CAAC,GAIF;IACC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACvC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,KAAK,MAAM;QACrC,CAAC,CAAC,CAAC,CAAC,cAAc,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC;QAC1C,CAAC,CAAC,CAAC,CAAC,kBAAkB,EAAE,EAAE,IAAI,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;IACjD,OAAO,CACL,KAAC,SAAS,IACR,MAAM,EACJ,gBAAM,SAAS,EAAE,MAAM,CAAC,aAAa,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,gBAAc,SAAS,aAC9E,KAAC,mBAAmB,IAAC,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,CAAC,WAAW,iBAAc,MAAM,GAAG,EACnF,eAAM,SAAS,EAAE,MAAM,CAAC,YAAY,YAAG,KAAK,CAAC,KAAK,GAAQ,IACrD,EAET,OAAO,EAAE,cAAK,SAAS,EAAE,MAAM,CAAC,iBAAiB,YAAG,KAAK,CAAC,KAAK,GAAO,EACtE,WAAW,EAAE,GAAG,GAChB,CACH,CAAC;AACJ,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,qBAAqB,CAAC,EACpC,SAAS,EACT,kBAAkB,EAClB,CAAC,GAC0B;IAC3B,MAAM,KAAK,GAAG,kBAAkB,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,CAAC;IACzD,IAAI,KAAK,CAAC,SAAS,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IAC/C,OAAO,KAAC,oBAAoB,IAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,GAAI,CAAC;AAC5D,CAAC"}
|
|
@@ -4,7 +4,7 @@ import { WORKTREE_NS } from './locales.js';
|
|
|
4
4
|
export type WorktreeHeroContextProps = PropsRuntime<'shell.overlay'> & PropsLocale<typeof WORKTREE_NS> & InjectFace<WorktreeContextInjected>;
|
|
5
5
|
/**
|
|
6
6
|
* Browser-local Hero suffix. It intentionally uses the frame overlay because
|
|
7
|
-
*
|
|
7
|
+
* The current upstream DSH exposes no additive slot beside the native Hero headline.
|
|
8
8
|
*/
|
|
9
9
|
export declare function WorktreeHeroContext({ useWorktreeContext, t, }: WorktreeHeroContextProps): import("react").JSX.Element | null;
|
|
10
10
|
//# sourceMappingURL=WorktreeHeroContext.d.ts.map
|
|
@@ -71,7 +71,7 @@ function contextAriaLabel(state, t) {
|
|
|
71
71
|
}
|
|
72
72
|
/**
|
|
73
73
|
* Browser-local Hero suffix. It intentionally uses the frame overlay because
|
|
74
|
-
*
|
|
74
|
+
* The current upstream DSH exposes no additive slot beside the native Hero headline.
|
|
75
75
|
*/
|
|
76
76
|
export function WorktreeHeroContext({ useWorktreeContext, t, }) {
|
|
77
77
|
const state = useWorktreeContext((snapshot) => snapshot);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { WorktreeSurfaceProps } from './worktree-surface-types.js';
|
|
2
|
-
export type { WorktreeSurfaceInjected, WorktreeSurfaceProps
|
|
2
|
+
export type { WorktreeSurfaceInjected, WorktreeSurfaceProps } from './worktree-surface-types.js';
|
|
3
3
|
/**
|
|
4
4
|
* Peer Worktree navigation surface. It keeps the original DSH Workspace mode
|
|
5
5
|
* intact and renders a browser-local Workspace → Worktree → Session projection.
|
|
6
6
|
*/
|
|
7
|
-
export declare function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces, t, available, manager, invalidateWorktreeContext, createWorkspace, createSessionForWorktree: createSessionCallback, createMainSession, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, insertSessionBefore, insertWorktreeBefore, renameSession, forkSession, archiveSession, ensureSessionWorkspace, syncSessionWorkspaces, openSession, }: WorktreeSurfaceProps): import("react").JSX.Element | null;
|
|
7
|
+
export declare function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces, t, available, expandState, sessionOrder, manager, permission, confirmFullAccess, fullAccessConfirmation, onPermissionResult, onPermissionNotice, permissionNotice, invalidateWorktreeContext, createWorkspace, createSessionForWorktree: createSessionCallback, createMainSession, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, insertSessionBefore, insertWorktreeBefore, renameSession, forkSession, archiveSession, forkRecovery, retryForkSession, ensureSessionWorkspace, syncSessionWorkspaces, openSession, }: WorktreeSurfaceProps): import("react").JSX.Element | null;
|
|
8
8
|
//# sourceMappingURL=WorktreeSurface.d.ts.map
|