@cerbur/clutch-dsh-worktree 0.1.2 → 0.1.4
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 +247 -92
- package/README.zh.md +297 -0
- package/lib/client/WorktreeContext.d.ts +15 -0
- package/lib/client/WorktreeContext.d.ts.map +1 -0
- package/lib/client/WorktreeContext.js +19 -0
- package/lib/client/WorktreeContext.js.map +1 -0
- package/lib/client/WorktreeHeroContext.d.ts +10 -0
- package/lib/client/WorktreeHeroContext.d.ts.map +1 -0
- package/lib/client/WorktreeHeroContext.js +128 -0
- package/lib/client/WorktreeHeroContext.js.map +1 -0
- package/lib/client/WorktreeOverlay.d.ts +6 -0
- package/lib/client/WorktreeOverlay.d.ts.map +1 -0
- package/lib/client/WorktreeOverlay.js +8 -0
- package/lib/client/WorktreeOverlay.js.map +1 -0
- package/lib/client/WorktreeSurface.d.ts +3 -29
- package/lib/client/WorktreeSurface.d.ts.map +1 -1
- package/lib/client/WorktreeSurface.js +170 -314
- package/lib/client/WorktreeSurface.js.map +1 -1
- package/lib/client/entry.d.ts +1 -1
- package/lib/client/entry.d.ts.map +1 -1
- package/lib/client/entry.js +41 -14
- package/lib/client/entry.js.map +1 -1
- package/lib/client/locales.d.ts +30 -0
- package/lib/client/locales.d.ts.map +1 -1
- package/lib/client/locales.js +32 -2
- package/lib/client/locales.js.map +1 -1
- package/lib/client/session-view.d.ts +21 -0
- package/lib/client/session-view.d.ts.map +1 -0
- package/lib/client/session-view.js +26 -0
- package/lib/client/session-view.js.map +1 -0
- package/lib/client/sidebar-overlay-geometry.d.ts +1 -0
- package/lib/client/sidebar-overlay-geometry.d.ts.map +1 -1
- package/lib/client/sidebar-overlay-geometry.js +28 -17
- package/lib/client/sidebar-overlay-geometry.js.map +1 -1
- package/lib/client/virtual-workspace-membership.d.ts.map +1 -1
- package/lib/client/virtual-workspace-membership.js +17 -6
- package/lib/client/virtual-workspace-membership.js.map +1 -1
- package/lib/client/worktree-connection.d.ts +1 -0
- package/lib/client/worktree-connection.d.ts.map +1 -1
- package/lib/client/worktree-connection.js +4 -0
- package/lib/client/worktree-connection.js.map +1 -1
- package/lib/client/worktree-context-store.d.ts +45 -0
- package/lib/client/worktree-context-store.d.ts.map +1 -0
- package/lib/client/worktree-context-store.js +199 -0
- package/lib/client/worktree-context-store.js.map +1 -0
- package/lib/client/worktree-context.d.ts +32 -0
- package/lib/client/worktree-context.d.ts.map +1 -0
- package/lib/client/worktree-context.js +51 -0
- package/lib/client/worktree-context.js.map +1 -0
- package/lib/client/worktree-error-copy.d.ts.map +1 -1
- package/lib/client/worktree-error-copy.js +14 -0
- package/lib/client/worktree-error-copy.js.map +1 -1
- package/lib/client/worktree-session.d.ts +83 -0
- package/lib/client/worktree-session.d.ts.map +1 -0
- package/lib/client/worktree-session.js +185 -0
- package/lib/client/worktree-session.js.map +1 -0
- package/lib/client/worktree-surface-dialogs.d.ts +7 -0
- package/lib/client/worktree-surface-dialogs.d.ts.map +1 -0
- package/lib/client/worktree-surface-dialogs.js +86 -0
- package/lib/client/worktree-surface-dialogs.js.map +1 -0
- package/lib/client/worktree-surface-rows.d.ts +9 -0
- package/lib/client/worktree-surface-rows.d.ts.map +1 -0
- package/lib/client/worktree-surface-rows.js +223 -0
- package/lib/client/worktree-surface-rows.js.map +1 -0
- package/lib/client/worktree-surface-selectors.d.ts +9 -0
- package/lib/client/worktree-surface-selectors.d.ts.map +1 -0
- package/lib/client/worktree-surface-selectors.js +28 -0
- package/lib/client/worktree-surface-selectors.js.map +1 -0
- package/lib/client/worktree-surface-types.d.ts +233 -0
- package/lib/client/worktree-surface-types.d.ts.map +1 -0
- package/lib/client/worktree-surface-types.js +2 -0
- package/lib/client/worktree-surface-types.js.map +1 -0
- package/lib/client/worktree-view-actions.d.ts +34 -0
- package/lib/client/worktree-view-actions.d.ts.map +1 -0
- package/lib/client/worktree-view-actions.js +69 -0
- package/lib/client/worktree-view-actions.js.map +1 -0
- package/lib/client/worktree-view-errors.d.ts +20 -0
- package/lib/client/worktree-view-errors.d.ts.map +1 -0
- package/lib/client/worktree-view-errors.js +65 -0
- package/lib/client/worktree-view-errors.js.map +1 -0
- package/lib/client/worktree-view-read.d.ts +48 -0
- package/lib/client/worktree-view-read.d.ts.map +1 -0
- package/lib/client/worktree-view-read.js +134 -0
- package/lib/client/worktree-view-read.js.map +1 -0
- package/lib/client/worktree-view.d.ts +4 -63
- package/lib/client/worktree-view.d.ts.map +1 -1
- package/lib/client/worktree-view.js +4 -125
- package/lib/client/worktree-view.js.map +1 -1
- package/lib/client.js +1313 -363
- package/lib/client.js.map +1 -1
- package/lib/contract/index.contract.js +2 -0
- package/lib/contract/index.contract.js.map +1 -1
- package/lib/contract/index.d.ts +17 -2
- package/lib/contract/index.d.ts.map +1 -1
- package/lib/contract/index.js +2 -0
- package/lib/contract/index.js.map +1 -1
- package/lib/host/remote.d.ts.map +1 -1
- package/lib/host/remote.js +1 -0
- package/lib/host/remote.js.map +1 -1
- package/lib/host/service.d.ts +6 -1
- package/lib/host/service.d.ts.map +1 -1
- package/lib/host/service.js +6 -0
- package/lib/host/service.js.map +1 -1
- package/lib/manage/manager-context.d.ts +11 -0
- package/lib/manage/manager-context.d.ts.map +1 -0
- package/lib/manage/manager-context.js +2 -0
- package/lib/manage/manager-context.js.map +1 -0
- package/lib/manage/manager-sessions.d.ts +18 -0
- package/lib/manage/manager-sessions.d.ts.map +1 -0
- package/lib/manage/manager-sessions.js +91 -0
- package/lib/manage/manager-sessions.js.map +1 -0
- package/lib/manage/manager-support.d.ts +18 -0
- package/lib/manage/manager-support.d.ts.map +1 -0
- package/lib/manage/manager-support.js +174 -0
- package/lib/manage/manager-support.js.map +1 -0
- package/lib/manage/manager-worktrees.d.ts +27 -0
- package/lib/manage/manager-worktrees.d.ts.map +1 -0
- package/lib/manage/manager-worktrees.js +259 -0
- package/lib/manage/manager-worktrees.js.map +1 -0
- package/lib/manage/manager.d.ts +25 -62
- package/lib/manage/manager.d.ts.map +1 -1
- package/lib/manage/manager.js +32 -554
- package/lib/manage/manager.js.map +1 -1
- package/lib/provider/sidecar-persistence.d.ts +18 -0
- package/lib/provider/sidecar-persistence.d.ts.map +1 -0
- package/lib/provider/sidecar-persistence.js +162 -0
- package/lib/provider/sidecar-persistence.js.map +1 -0
- package/lib/provider/sidecar-schema.d.ts +6 -0
- package/lib/provider/sidecar-schema.d.ts.map +1 -0
- package/lib/provider/sidecar-schema.js +123 -0
- package/lib/provider/sidecar-schema.js.map +1 -0
- package/lib/provider/sidecar.d.ts +12 -68
- package/lib/provider/sidecar.d.ts.map +1 -1
- package/lib/provider/sidecar.js +61 -346
- package/lib/provider/sidecar.js.map +1 -1
- package/lib/provider/types.d.ts +2 -1
- package/lib/provider/types.d.ts.map +1 -1
- package/lib/provider/types.js.map +1 -1
- package/lib/typert.host.js +60 -18
- package/lib/typert.remote-client.d.ts +3 -1
- package/lib/typert.remote-client.d.ts.map +1 -1
- package/lib/typert.remote-client.js +60 -18
- package/package.json +6 -2
package/README.zh.md
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
# @cerbur/clutch-dsh-worktree
|
|
2
|
+
|
|
3
|
+
`@cerbur/clutch-dsh-worktree` 为 DSH Web UI 增加 Git Worktree 视图,按
|
|
4
|
+
Workspace → Worktree → Session 组织会话,同时继续由 DSH 作为 Project/Workspace 身份、
|
|
5
|
+
Session 元数据、原生列表和会话历史的唯一事实来源。插件只保存 Worktree/Session 的外部
|
|
6
|
+
关系元数据。
|
|
7
|
+
|
|
8
|
+
## 界面截图
|
|
9
|
+
|
|
10
|
+

|
|
11
|
+
|
|
12
|
+
中文截图展示了侧边栏中的 Worktree 模式、包含 Main 和 Worktree 行的 Workspace 树,以及
|
|
13
|
+
新会话空白 Hero 中的只读上下文。
|
|
14
|
+
|
|
15
|
+
## 能力
|
|
16
|
+
|
|
17
|
+
- 从 DSH Sidebar footer 进入 Worktree 模式,按 Workspace → Worktree → Session 浏览会话。
|
|
18
|
+
- 搜索 Workspace,并从已有 local branch 创建 Git Worktree 和 branch。
|
|
19
|
+
- 在 Main 或 active Worktree 下创建普通 Session 或 Worktree Session,并直接打开新会话。
|
|
20
|
+
- 查看 ready、repair、active 和 detached Worktree 状态,包括可重试的操作错误。
|
|
21
|
+
- 通过 active Worktree 的选项菜单和确认弹窗移除 Worktree;Main 和 detached 行不显示该菜单。
|
|
22
|
+
- 继续使用 DSH 原生的 Workspace rename/delete/reorder 和 Session 菜单。Worktree 可以在所属
|
|
23
|
+
Workspace 内排序;顺序保存在插件 sidecar 中,Main 固定在第一位。
|
|
24
|
+
- 在已有 Conversation 的标题行以及新会话空白 Hero 中,以只读方式显示当前 local branch 或
|
|
25
|
+
Worktree branch 上下文。
|
|
26
|
+
- Worktree Session 仍出现在原始 DSH Project/Workspace 视角中;插件不复制 Session 内容,
|
|
27
|
+
也不修改消息、prompt、transcript 或历史记录。
|
|
28
|
+
|
|
29
|
+
### 兼容性与前置条件
|
|
30
|
+
|
|
31
|
+
- DSH CLI 和目标 Web profile 必须使用 `dsh-v0.1.0-rc.8`。
|
|
32
|
+
- 目标 profile(例如 `web` 或 `demo`)必须已经可以正常启动,且 plugin 必须安装到实际
|
|
33
|
+
启动 Web UI 的同一个 profile。
|
|
34
|
+
- DSH Client 必须提供原生 `@deepseek-ai/dsh-client-ui-conversation` package 及其
|
|
35
|
+
`conversation.session.header.actions` seat。
|
|
36
|
+
- Workspace 必须位于 Git repository 中,且至少有一个初始 commit 和本地 branch。如果缺少
|
|
37
|
+
前置条件,创建弹窗会显示可复制的 setup 命令;插件不会执行这些命令,也不会修改
|
|
38
|
+
Workspace 文件。
|
|
39
|
+
- package 声明了可安装的 `dsh.bundle` 并提供 `cordis.patch.yml`;浏览器 UI 通过
|
|
40
|
+
`dsh.client` metadata 声明。
|
|
41
|
+
|
|
42
|
+
## 安装
|
|
43
|
+
|
|
44
|
+
普通用户安装请使用 npm package。开发或验证本地源码时使用仓库 checkout;从市场条目安装
|
|
45
|
+
源码 package 时使用 GitHub source path。
|
|
46
|
+
|
|
47
|
+
### 从 npm 安装(推荐)
|
|
48
|
+
|
|
49
|
+
在已经安装 DSH CLI 的环境中执行:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
dsh plugin --profile web add @cerbur/clutch-dsh-worktree
|
|
53
|
+
dsh web
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
如果使用 `deepseek-harness` 源码 checkout、系统没有独立的 `dsh` 命令,使用等价的转发
|
|
57
|
+
形式:
|
|
58
|
+
|
|
59
|
+
```bash
|
|
60
|
+
cd /path/to/deepseek-harness
|
|
61
|
+
pnpm dsh plugin --profile web add @cerbur/clutch-dsh-worktree
|
|
62
|
+
pnpm dsh web
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
可以通过官方 registry 查看当前发布版本:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
npm view @cerbur/clutch-dsh-worktree version --registry=https://registry.npmjs.org/
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### 从仓库 checkout 安装
|
|
72
|
+
|
|
73
|
+
先从 `clutch-dsh` checkout 构建 package,再把绝对路径安装到 DSH profile:
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
cd /path/to/clutch-dsh
|
|
77
|
+
pnpm install
|
|
78
|
+
pnpm --filter @cerbur/clutch-dsh-worktree build
|
|
79
|
+
|
|
80
|
+
cd /path/to/deepseek-harness
|
|
81
|
+
pnpm install
|
|
82
|
+
pnpm run build
|
|
83
|
+
pnpm dsh plugin --profile web add /path/to/clutch-dsh/packages/clutch-dsh-worktree
|
|
84
|
+
pnpm dsh web --dump-config
|
|
85
|
+
pnpm dsh web
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
`--dump-config` 输出中应包含该 plugin 的 bundle layer。如果 profile 中仍有旧的 unscoped
|
|
89
|
+
安装,先移除:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
pnpm dsh plugin --profile web remove clutch-dsh-worktree
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
更新本地 checkout 时,重新构建 package 并重启 DSH:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
cd /path/to/clutch-dsh
|
|
99
|
+
pnpm --filter @cerbur/clutch-dsh-worktree build
|
|
100
|
+
cd /path/to/deepseek-harness
|
|
101
|
+
pnpm dsh web
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
修改 `package.json`、`cordis.patch.yml` 或 profile bundle 成员后,需要再次执行 plugin add
|
|
105
|
+
命令。
|
|
106
|
+
|
|
107
|
+
### 从 GitHub 源码安装
|
|
108
|
+
|
|
109
|
+
`awesome-dsh-plugin` 生成的源码路径为:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
dsh plugin --profile web add "github:Cerbur/clutch-dsh#path:/packages/clutch-dsh-worktree"
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
这是源码 Git 依赖,不是预构建的 npm package。它的 `prepare` 生命周期会生成 `lib/`。当前
|
|
116
|
+
DSH profile 使用 pnpm 11 的 `allowBuilds`:首次执行 Git 安装时,pnpm 会故意拒绝构建,并
|
|
117
|
+
在错误信息中打印包含包名、Git URL、解析后的 commit 和子目录 path 的完整 key。将完整
|
|
118
|
+
key 复制到 profile 的 `pnpm-workspace.yaml`,例如:
|
|
119
|
+
|
|
120
|
+
```yaml
|
|
121
|
+
allowBuilds:
|
|
122
|
+
'@cerbur/clutch-dsh-worktree@git+https://github.com/Cerbur/clutch-dsh#<resolved-commit>&path:/packages/clutch-dsh-worktree': true
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
必须使用 pnpm 错误提示中打印的完整包 key:`<resolved-commit>`、Git URL 和 path 都必须与
|
|
126
|
+
错误输出一致。对于直接 Git 依赖,只写包名不够;当前 pnpm 11 的 Git prepare 流程也不使用
|
|
127
|
+
`onlyBuiltDependencies` 这一配置。保存授权后重新执行原安装命令;commit 变化后需要为新
|
|
128
|
+
commit 增加对应的 key。该 allowlist 属于信任此 Git commit 的 profile 维护者,不要写入
|
|
129
|
+
plugin package。
|
|
130
|
+
|
|
131
|
+
授权后,Git prepare 会在 checkout 的 monorepo 中执行 `pnpm install`,再执行
|
|
132
|
+
`pnpm run build`,因此 profile 必须能访问其配置的 registry。授权之后出现 registry DNS、
|
|
133
|
+
镜像或 lockfile 错误,属于安装环境问题,不是 `allowBuilds` 拒绝。若要避免源码构建授权,
|
|
134
|
+
请使用上面的 npm 安装方式。
|
|
135
|
+
|
|
136
|
+
### 卸载
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
cd /path/to/deepseek-harness
|
|
140
|
+
pnpm dsh plugin --profile web remove @cerbur/clutch-dsh-worktree
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## 使用说明
|
|
144
|
+
|
|
145
|
+
### 打开 Worktree 模式
|
|
146
|
+
|
|
147
|
+
1. 启动 DSH Web UI,在 Sidebar footer 选择 Worktree。Worktree 模式是附加界面,不会添加
|
|
148
|
+
独立的 Workspace/Worktree Tab。
|
|
149
|
+
2. 使用 Workspace 树搜索、展开并选择 Main 或 Worktree 视角。每组默认显示五行,更多内容
|
|
150
|
+
使用 Expand more/Collapse。
|
|
151
|
+
|
|
152
|
+

|
|
153
|
+
|
|
154
|
+
上图展示了侧边栏入口以及新会话空白 Hero 中显示的视觉上下文。界面语言跟随 DSH 当前的
|
|
155
|
+
语言设置。
|
|
156
|
+
|
|
157
|
+
### 创建 Worktree
|
|
158
|
+
|
|
159
|
+
1. 选择 Workspace,点击它旁边的 `+`,选择基线 local branch,并填写 Worktree name。默认
|
|
160
|
+
branch 名称为 `dsh/<8-character-random-string>`。
|
|
161
|
+
2. 目标 Worktree 路径必须是绝对路径,属于同一个 Project,且不能是 Project 根目录。相对
|
|
162
|
+
路径、其他 Project 的路径或 Project 根目录都会被拒绝。
|
|
163
|
+
3. 如果缺少 Git、初始 commit 或本地 branch,按照弹窗中的可复制命令修复后重试。插件只
|
|
164
|
+
展示这些命令,不会执行命令或编辑业务文件。
|
|
165
|
+
|
|
166
|
+
### 创建 Main 和 Worktree Session
|
|
167
|
+
|
|
168
|
+
- 使用 Main 的 `+`,在 Project 根目录视角中创建普通 DSH Session。
|
|
169
|
+
- 使用 Worktree 的 `+`,创建或复用 runtime cwd 指向该 Worktree 的 Session。在 rc.8 中,
|
|
170
|
+
原生调用为 `session.create({ cwd: worktreePath })`;插件随后保存外部 binding,在当前
|
|
171
|
+
浏览器内应用 `{ workspaceId, sessionId }` membership projection,并打开该 Session。
|
|
172
|
+
- 如果存在目标 cwd 完全匹配的未归档 blank Session,连接器会优先复用它。已绑定的 Session
|
|
173
|
+
会直接打开;未绑定的候选会先 binding,再 projection 和打开。否则执行
|
|
174
|
+
`create → bind → project → open`,同一个 Worktree 的并发点击会合并。
|
|
175
|
+
- 如果 DSH 创建 Session 后 binding 失败,Session ID 仍会保留,可用于 Retry 或 Open 恢复。
|
|
176
|
+
插件不会删除或修改该 DSH Session。
|
|
177
|
+
- provisional blank Session 遵循 DSH 原生显示规则:只在当前选中的视角中显示,使用本地化
|
|
178
|
+
的 `New Session` 文案,不显示生成的 ID,也没有 Rename、Fork 或 Archive 菜单。接受第一条
|
|
179
|
+
prompt 后,它会变为普通 Session 行;隐藏 blank 行不会删除 Session 或 Worktree binding。
|
|
180
|
+
|
|
181
|
+
### 排序与管理 Worktree
|
|
182
|
+
|
|
183
|
+
- 在所属 Workspace 内拖动 Worktree。排序持久化在 plugin sidecar 的有序 `worktrees` 数组中;
|
|
184
|
+
Main 是固定的第一行,Worktree 不能跨 Workspace 移动。
|
|
185
|
+
- 使用 active Worktree 的选项菜单和确认弹窗移除 Worktree。Main 和 detached Worktree 不显示
|
|
186
|
+
该菜单。
|
|
187
|
+
- 移除 Worktree 不会删除其 Session。关系会保留为 detached,直到显式解绑。删除 Workspace
|
|
188
|
+
只会删除 DSH 的 Workspace registration;其目录、Session、Git Worktree 和 plugin
|
|
189
|
+
sidecar 会保留。
|
|
190
|
+
- DSH 原生的 Workspace rename/delete/reorder 和 Session 菜单继续可用。Session 拖动排序
|
|
191
|
+
限定在当前视觉 Main 或 Worktree 分组中。
|
|
192
|
+
- Main 分组显示当前 local branch:有分支时为 `本地(branch)`,DSH 没有返回当前分支时
|
|
193
|
+
回退为 `本地`。branch 名称、路径、Workspace 名称、Session 标题以及原始 DSH/Git 错误
|
|
194
|
+
信息保持原值。
|
|
195
|
+
- 已有 Session 会在标题行显示只读上下文,格式为 `Session title` → `Agent mode` →
|
|
196
|
+
`current branch / Worktree branch`。原生标题存在且有锚点时,新会话空白 Hero 会在标题后
|
|
197
|
+
显示 `Workspace (branch)`。
|
|
198
|
+
|
|
199
|
+
### 理解状态与恢复提示
|
|
200
|
+
|
|
201
|
+
- `ready` 表示 Worktree 可用。`repair` 表示 Worktree、Session、binding 或 cwd 缺失/无效。
|
|
202
|
+
`detached` 表示 Git Worktree 已被移除,但关系仍然保留。active binding 指向缺失
|
|
203
|
+
Worktree 时会显示明确的 repair 警告或错误,不会静默切换到其他 Worktree。
|
|
204
|
+
- Worktree health 是 Git 的运行时 projection,不写入 sidecar。Git 前置条件失败按
|
|
205
|
+
Workspace 显示 setup 提示;Connection、Gateway 和未预期的 Worktree domain 错误会保留
|
|
206
|
+
为可重试错误,不会伪装为空列表。
|
|
207
|
+
- 已经 ready 的视角刷新时会保留当前 projection,直到替换数据可用。首次进入和显式 Retry
|
|
208
|
+
可以显示 loading 状态。
|
|
209
|
+
|
|
210
|
+
## 界面语言
|
|
211
|
+
|
|
212
|
+
Worktree 模式跟随 DSH 当前界面语言。语言偏好由 DSH 管理;插件不增加独立的语言设置。
|
|
213
|
+
Worktree 入口、Workspace → Worktree → Session 树、菜单、弹窗、状态和重试提示均提供中文
|
|
214
|
+
和 English 文案。
|
|
215
|
+
|
|
216
|
+
Workspace 名称、Session 标题、branch 名称、路径以及 DSH/Host 返回的原始错误信息保持不变,
|
|
217
|
+
便于诊断和继续使用 DSH 原生数据。Main 分组在 English 中本地化为 `Local (branch)`,中文
|
|
218
|
+
为 `本地(branch)`;没有返回当前 branch 时分别回退为 `Local`/`本地`。
|
|
219
|
+
|
|
220
|
+
## 数据边界与当前限制
|
|
221
|
+
|
|
222
|
+
DSH 管理原始 Project/Workspace 身份和根目录、Session 身份和元数据、原生 Project/Session
|
|
223
|
+
列表、消息、prompt、transcript 和历史记录。插件不会复制或重写这些内容。插件的外部索引
|
|
224
|
+
位于 DSH host 的 plugin data directory 或独立 sidecar 存储中,只能包含以下关系事实:
|
|
225
|
+
|
|
226
|
+
- `projectId`、`worktreeId` 和 `sessionId`;
|
|
227
|
+
- 绝对 Worktree 路径、branch 和生命周期状态;
|
|
228
|
+
- binding 状态和 schema version。
|
|
229
|
+
|
|
230
|
+
索引不会写入 Project 工作树或 DSH 原始数据目录,也不会保存 `projectRoot` 副本或任何
|
|
231
|
+
Session 内容。如果 sidecar 不可用或损坏,原生 Project/Session 视角仍然可读,插件进入
|
|
232
|
+
degraded/read-only 状态;不能用空索引覆盖 DSH 原生列表。
|
|
233
|
+
|
|
234
|
+
一个 Session 最多绑定一个 active Worktree,一个 Worktree 可以绑定多个 Session。Session
|
|
235
|
+
重复绑定同一个 Worktree 是幂等的,绑定两个 active Worktree 会产生 conflict。没有 binding、
|
|
236
|
+
使用 Main binding 或处于 detached binding 的 Session 使用 Project 根目录作为 cwd;active
|
|
237
|
+
Worktree binding 使用对应的 Worktree 路径。cwd 在每次执行时派生,不会写回 DSH Session 元数据。
|
|
238
|
+
|
|
239
|
+
创建 Worktree 时先创建 Git Worktree,再记录外部关系。sidecar 写入失败时会尽可能清理刚
|
|
240
|
+
创建的 Git Worktree。删除 Worktree 失败时不会改变 sidecar 状态,因此关系仍可重试。创建
|
|
241
|
+
Session 时先调用 DSH 原生 API,再写入 binding;binding 失败不会删除或修改已创建的 Session。
|
|
242
|
+
|
|
243
|
+
rc.8 的 `session.create` API 不能同时接收 `workspaceId` 和独立 cwd。因此 Worktree 流程
|
|
244
|
+
使用浏览器本地 membership projection,而不是持久化的 DSH attach,并且不会修改 DSH 源码、
|
|
245
|
+
Session metadata 或原生 Workspace 存储。native list 刷新后会重放 projection;binding 消失
|
|
246
|
+
或 Client dispose 时会移除 projection。
|
|
247
|
+
|
|
248
|
+
空白 Hero 上下文只用于展示。由于 rc.8 没有 additive Hero headline slot,它的位置依赖原生
|
|
249
|
+
`[data-phase="hero"]` 和标题锚点;锚点不可用时浮层会消失,未来有正式 DSH slot 时应迁移到
|
|
250
|
+
该 slot。
|
|
251
|
+
|
|
252
|
+
## 开发与验证
|
|
253
|
+
|
|
254
|
+
从 workspace 根目录执行:
|
|
255
|
+
|
|
256
|
+
```bash
|
|
257
|
+
cd /path/to/clutch-dsh
|
|
258
|
+
pnpm install
|
|
259
|
+
pnpm run check:workspace
|
|
260
|
+
pnpm run check:patches
|
|
261
|
+
pnpm --filter @cerbur/clutch-dsh-worktree typecheck
|
|
262
|
+
pnpm --filter @cerbur/clutch-dsh-worktree build
|
|
263
|
+
pnpm --filter @cerbur/clutch-dsh-worktree test
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
验证双语 README contract 和格式:
|
|
267
|
+
|
|
268
|
+
```bash
|
|
269
|
+
cd /path/to/clutch-dsh/packages/clutch-dsh-worktree
|
|
270
|
+
node --test test/readme-parity.test.mjs
|
|
271
|
+
pnpm exec prettier --check README.md README.zh.md test/readme-parity.test.mjs
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
完整 workspace 检查为:
|
|
275
|
+
|
|
276
|
+
```bash
|
|
277
|
+
cd /path/to/clutch-dsh
|
|
278
|
+
pnpm run check
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
不要提交生成的 `lib/`、coverage、sidecar 数据或本地凭据。数据边界和生命周期规则见
|
|
282
|
+
[AGENTS.md](AGENTS.md),版本与安装来源见 [docs/RELEASING.md](docs/RELEASING.md),浏览器
|
|
283
|
+
Consumer 边界见 [src/client/README.md](src/client/README.md)。
|
|
284
|
+
|
|
285
|
+
## 插件市场描述
|
|
286
|
+
|
|
287
|
+
向 `awesome-dsh-plugin` 投稿时使用 `git` 分类,并保持描述与 package 一致:
|
|
288
|
+
|
|
289
|
+
```yaml
|
|
290
|
+
category: git
|
|
291
|
+
description:
|
|
292
|
+
en: Adds a Worktree view to DSH Web UI that groups Sessions by Git worktree while keeping DSH as the source of truth.
|
|
293
|
+
zh: 为 DSH Web UI 增加按 Git Worktree 组织 Session 的视角,同时继续由 DSH 管理原始 Project/Workspace 和 Session 数据。
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
市场投稿还需要在外部确认 `dsh-plugin` topic、仓库年龄和提交数等信息;这些外部属性无法
|
|
297
|
+
由 package README 设置。
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { SnapshotStore } from '@deepseek-ai/dsh-client-runtime/client';
|
|
2
|
+
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
3
|
+
import type { WorktreeContextState } from './worktree-context-store.js';
|
|
4
|
+
import { WORKTREE_NS } from './locales.js';
|
|
5
|
+
/** Browser-local context snapshot supplied by the Client entry. */
|
|
6
|
+
export interface WorktreeContextInjected {
|
|
7
|
+
readonly hooks: {
|
|
8
|
+
readonly worktreeContext: SnapshotStore<WorktreeContextState>;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
/** Props for the active Session-header context action. */
|
|
12
|
+
export type WorktreeHeaderContextProps = PropsRuntime<'conversation.session.header.actions'> & PropsLocale<typeof WORKTREE_NS> & InjectFace<WorktreeContextInjected>;
|
|
13
|
+
/** Render the current branch or active Worktree branch beside the Session title. */
|
|
14
|
+
export declare function WorktreeHeaderContext({ sessionId, useWorktreeContext, t, }: WorktreeHeaderContextProps): import("react").JSX.Element | null;
|
|
15
|
+
//# sourceMappingURL=WorktreeContext.d.ts.map
|
|
@@ -0,0 +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;AAyBtC,oFAAoF;AACpF,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,kBAAkB,EAClB,CAAC,GACF,EAAE,0BAA0B,sCAI5B"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { IconBranchOutline16 } from '@deepseek-ai/dsh-client-ui-primitives';
|
|
3
|
+
import styles from './worktree-context.css';
|
|
4
|
+
function WorktreeContextLabel({ value, t, }) {
|
|
5
|
+
if (value.kind === 'none')
|
|
6
|
+
return null;
|
|
7
|
+
const ariaLabel = value.kind === 'main'
|
|
8
|
+
? t('context.main', { name: value.label })
|
|
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 })] }));
|
|
11
|
+
}
|
|
12
|
+
/** Render the current branch or active Worktree branch beside the Session title. */
|
|
13
|
+
export function WorktreeHeaderContext({ sessionId, useWorktreeContext, t, }) {
|
|
14
|
+
const state = useWorktreeContext((snapshot) => snapshot);
|
|
15
|
+
if (state.sessionId !== sessionId)
|
|
16
|
+
return null;
|
|
17
|
+
return _jsx(WorktreeContextLabel, { value: state.value, t: t });
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=WorktreeContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorktreeContext.js","sourceRoot":"","sources":["../../src/client/WorktreeContext.tsx"],"names":[],"mappings":";AAOA,OAAO,EAAE,mBAAmB,EAAE,MAAM,uCAAuC,CAAC;AAK5E,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,gBACE,SAAS,EAAE,MAAM,CAAC,aAAa,EAC/B,KAAK,EAAE,KAAK,CAAC,KAAK,gBACN,SAAS,aAErB,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,CACR,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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { InjectFace, PropsLocale, PropsRuntime } from '@deepseek-ai/dsh-client-ui-slots';
|
|
2
|
+
import type { WorktreeContextInjected } from './WorktreeContext.js';
|
|
3
|
+
import { WORKTREE_NS } from './locales.js';
|
|
4
|
+
export type WorktreeHeroContextProps = PropsRuntime<'shell.overlay'> & PropsLocale<typeof WORKTREE_NS> & InjectFace<WorktreeContextInjected>;
|
|
5
|
+
/**
|
|
6
|
+
* Browser-local Hero suffix. It intentionally uses the frame overlay because
|
|
7
|
+
* rc.8 exposes no additive slot beside the native Hero headline.
|
|
8
|
+
*/
|
|
9
|
+
export declare function WorktreeHeroContext({ useWorktreeContext, t, }: WorktreeHeroContextProps): import("react").JSX.Element | null;
|
|
10
|
+
//# sourceMappingURL=WorktreeHeroContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorktreeHeroContext.d.ts","sourceRoot":"","sources":["../../src/client/WorktreeHeroContext.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,UAAU,EACV,WAAW,EACX,YAAY,EAEb,MAAM,kCAAkC,CAAC;AAE1C,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAC;AAEpE,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAK3C,MAAM,MAAM,wBAAwB,GAClC,YAAY,CAAC,eAAe,CAAC,GAC7B,WAAW,CAAC,OAAO,WAAW,CAAC,GAC/B,UAAU,CAAC,uBAAuB,CAAC,CAAC;AA2EtC;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,kBAAkB,EAClB,CAAC,GACF,EAAE,wBAAwB,sCAqE1B"}
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useCallback, useLayoutEffect, useState } from 'react';
|
|
3
|
+
import styles from './worktree-context.css';
|
|
4
|
+
function labelFor(state) {
|
|
5
|
+
if (state.status !== 'ready' ||
|
|
6
|
+
state.workspaceTitle === undefined ||
|
|
7
|
+
state.value.kind === 'none') {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
return `${state.workspaceTitle} (${state.value.label})`;
|
|
11
|
+
}
|
|
12
|
+
function elementWithClassSuffix(root, suffix) {
|
|
13
|
+
const candidates = root.querySelectorAll('[class]');
|
|
14
|
+
for (const candidate of candidates) {
|
|
15
|
+
if ([...candidate.classList].some((token) => token === suffix || token.endsWith(`_${suffix}`))) {
|
|
16
|
+
return candidate;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
function headlineElement(root) {
|
|
22
|
+
// Anchor to the visible end of the native title line. The headline wrapper
|
|
23
|
+
// spans the whole content column, so using it would place the suffix at the
|
|
24
|
+
// far edge instead of immediately after the title and preview badge.
|
|
25
|
+
return elementWithClassSuffix(root, 'previewBadge')
|
|
26
|
+
?? elementWithClassSuffix(root, 'headlineText')
|
|
27
|
+
?? elementWithClassSuffix(root, 'headline');
|
|
28
|
+
}
|
|
29
|
+
function positionedAncestor(element) {
|
|
30
|
+
if (element.offsetParent instanceof HTMLElement)
|
|
31
|
+
return element.offsetParent;
|
|
32
|
+
for (let ancestor = element.parentElement; ancestor !== null; ancestor = ancestor.parentElement) {
|
|
33
|
+
if (getComputedStyle(ancestor).position !== 'static')
|
|
34
|
+
return ancestor;
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
function measurePlacement(element) {
|
|
39
|
+
const hero = document.querySelector('[data-phase="hero"]');
|
|
40
|
+
// The Slot renderer inserts a display: contents wrapper before the actual
|
|
41
|
+
// shell overlay layer, so the direct parent is not the containing block.
|
|
42
|
+
const overlay = positionedAncestor(element);
|
|
43
|
+
const headline = hero === null ? null : headlineElement(hero);
|
|
44
|
+
if (hero === null || headline === null || overlay === null)
|
|
45
|
+
return null;
|
|
46
|
+
const anchor = headline.getBoundingClientRect();
|
|
47
|
+
const frame = overlay.getBoundingClientRect();
|
|
48
|
+
const width = element.getBoundingClientRect().width;
|
|
49
|
+
const afterHeadlineLeft = anchor.right - frame.left + 8;
|
|
50
|
+
const fitsAfterHeadline = afterHeadlineLeft + width <= frame.width - 8;
|
|
51
|
+
return {
|
|
52
|
+
left: fitsAfterHeadline
|
|
53
|
+
? afterHeadlineLeft
|
|
54
|
+
: Math.max(8, frame.width - width - 8),
|
|
55
|
+
top: fitsAfterHeadline
|
|
56
|
+
? Math.max(8, anchor.top - frame.top + (anchor.height - 22) / 2)
|
|
57
|
+
: Math.max(8, anchor.bottom - frame.top + 8),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function contextAriaLabel(state, t) {
|
|
61
|
+
if (state.value.kind === 'main')
|
|
62
|
+
return t('context.main', { name: state.value.label });
|
|
63
|
+
if (state.value.kind === 'worktree')
|
|
64
|
+
return t('context.worktree', { name: state.value.label });
|
|
65
|
+
return undefined;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Browser-local Hero suffix. It intentionally uses the frame overlay because
|
|
69
|
+
* rc.8 exposes no additive slot beside the native Hero headline.
|
|
70
|
+
*/
|
|
71
|
+
export function WorktreeHeroContext({ useWorktreeContext, t, }) {
|
|
72
|
+
const state = useWorktreeContext((snapshot) => snapshot);
|
|
73
|
+
const label = labelFor(state);
|
|
74
|
+
const [placement, setPlacement] = useState(null);
|
|
75
|
+
const measure = useCallback((element) => {
|
|
76
|
+
if (element === null) {
|
|
77
|
+
setPlacement(null);
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
setPlacement(measurePlacement(element));
|
|
81
|
+
}, []);
|
|
82
|
+
useLayoutEffect(() => {
|
|
83
|
+
if (typeof document === 'undefined' || typeof window === 'undefined')
|
|
84
|
+
return undefined;
|
|
85
|
+
const element = document.querySelector('[data-worktree-hero-context]');
|
|
86
|
+
if (element === null)
|
|
87
|
+
return undefined;
|
|
88
|
+
let frameRequest;
|
|
89
|
+
const schedule = () => {
|
|
90
|
+
if (frameRequest !== undefined)
|
|
91
|
+
window.cancelAnimationFrame(frameRequest);
|
|
92
|
+
frameRequest = window.requestAnimationFrame(() => {
|
|
93
|
+
frameRequest = undefined;
|
|
94
|
+
measure(element);
|
|
95
|
+
});
|
|
96
|
+
};
|
|
97
|
+
const mutationObserver = typeof MutationObserver === 'undefined'
|
|
98
|
+
? undefined
|
|
99
|
+
: new MutationObserver(schedule);
|
|
100
|
+
mutationObserver?.observe(document.body, {
|
|
101
|
+
subtree: true,
|
|
102
|
+
childList: true,
|
|
103
|
+
attributes: true,
|
|
104
|
+
attributeFilter: ['class', 'data-phase'],
|
|
105
|
+
});
|
|
106
|
+
const resizeObserver = typeof ResizeObserver === 'undefined'
|
|
107
|
+
? undefined
|
|
108
|
+
: new ResizeObserver(schedule);
|
|
109
|
+
resizeObserver?.observe(positionedAncestor(element) ?? element);
|
|
110
|
+
window.addEventListener('resize', schedule);
|
|
111
|
+
schedule();
|
|
112
|
+
return () => {
|
|
113
|
+
if (frameRequest !== undefined)
|
|
114
|
+
window.cancelAnimationFrame(frameRequest);
|
|
115
|
+
mutationObserver?.disconnect();
|
|
116
|
+
resizeObserver?.disconnect();
|
|
117
|
+
window.removeEventListener('resize', schedule);
|
|
118
|
+
};
|
|
119
|
+
}, [label, measure]);
|
|
120
|
+
const ariaLabel = contextAriaLabel(state, t);
|
|
121
|
+
if (label === undefined)
|
|
122
|
+
return null;
|
|
123
|
+
return (_jsx("span", { ref: measure, className: styles.heroContext, "data-worktree-hero-context": true, "aria-label": ariaLabel, title: label, style: placement === null ? { visibility: 'hidden' } : {
|
|
124
|
+
left: `${placement.left}px`,
|
|
125
|
+
top: `${placement.top}px`,
|
|
126
|
+
}, children: label }));
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=WorktreeHeroContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorktreeHeroContext.js","sourceRoot":"","sources":["../../src/client/WorktreeHeroContext.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { WorktreeHeroContextProps } from './WorktreeHeroContext.js';
|
|
2
|
+
import { type WorktreeSurfaceProps } from './WorktreeSurface.js';
|
|
3
|
+
export type WorktreeOverlayProps = WorktreeSurfaceProps & Pick<WorktreeHeroContextProps, 'useWorktreeContext'>;
|
|
4
|
+
/** Compose the independent Hero context and Worktree navigation overlays. */
|
|
5
|
+
export declare function WorktreeOverlay(props: WorktreeOverlayProps): import("react").JSX.Element;
|
|
6
|
+
//# sourceMappingURL=WorktreeOverlay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorktreeOverlay.d.ts","sourceRoot":"","sources":["../../src/client/WorktreeOverlay.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,0BAA0B,CAAC;AAEzE,OAAO,EAAmB,KAAK,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAElF,MAAM,MAAM,oBAAoB,GAAG,oBAAoB,GACrD,IAAI,CAAC,wBAAwB,EAAE,oBAAoB,CAAC,CAAC;AAEvD,6EAA6E;AAC7E,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,+BAO1D"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { WorktreeHeroContext } from './WorktreeHeroContext.js';
|
|
3
|
+
import { WorktreeSurface } from './WorktreeSurface.js';
|
|
4
|
+
/** Compose the independent Hero context and Worktree navigation overlays. */
|
|
5
|
+
export function WorktreeOverlay(props) {
|
|
6
|
+
return (_jsxs(_Fragment, { children: [_jsx(WorktreeHeroContext, { ...props }), _jsx(WorktreeSurface, { ...props })] }));
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=WorktreeOverlay.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WorktreeOverlay.js","sourceRoot":"","sources":["../../src/client/WorktreeOverlay.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAA6B,MAAM,sBAAsB,CAAC;AAKlF,6EAA6E;AAC7E,MAAM,UAAU,eAAe,CAAC,KAA2B;IACzD,OAAO,CACL,8BACE,KAAC,mBAAmB,OAAK,KAAK,GAAI,EAClC,KAAC,eAAe,OAAK,KAAK,GAAI,IAC7B,CACJ,CAAC;AACJ,CAAC"}
|
|
@@ -1,34 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
import { WORKTREE_NS } from './locales.js';
|
|
4
|
-
import type { createWorktreeViewStore } from './view-mode-store.js';
|
|
5
|
-
import { type CreateSessionForWorktreeInput } from './worktree-view.js';
|
|
6
|
-
/** Apply-time facts and DSH navigation callbacks used by the surface. */
|
|
7
|
-
export interface WorktreeSurfaceInjected {
|
|
8
|
-
readonly available: boolean;
|
|
9
|
-
readonly manager?: WorktreeManager;
|
|
10
|
-
readonly createWorkspace?: () => Promise<void>;
|
|
11
|
-
readonly createSessionForWorktree?: (input: CreateSessionForWorktreeInput) => Promise<string>;
|
|
12
|
-
readonly createMainSession?: (workspaceId: string) => void;
|
|
13
|
-
readonly renameWorkspace?: (workspaceId: string, title: string) => Promise<void>;
|
|
14
|
-
readonly deleteWorkspace?: (workspaceId: string) => Promise<void>;
|
|
15
|
-
readonly insertWorkspaceBefore?: (workspaceId: string, beforeWorkspaceId?: string) => Promise<void>;
|
|
16
|
-
readonly insertSessionBefore?: (workspaceId: string, sessionId: string, beforeSessionId?: string) => Promise<void>;
|
|
17
|
-
readonly renameSession?: (sessionId: string, title: string) => Promise<void>;
|
|
18
|
-
readonly forkSession?: (sessionId: string) => void;
|
|
19
|
-
readonly archiveSession?: (sessionId: string) => Promise<void>;
|
|
20
|
-
readonly ensureSessionWorkspace?: (workspaceId: string, sessionId: string) => void;
|
|
21
|
-
readonly syncSessionWorkspaces?: (bindings: readonly {
|
|
22
|
-
workspaceId: string;
|
|
23
|
-
sessionId: string;
|
|
24
|
-
}[]) => void;
|
|
25
|
-
readonly openSession: (sessionId: string) => void;
|
|
26
|
-
}
|
|
27
|
-
/** Props derived from the frame overlay slot, shared state, and injected face. */
|
|
28
|
-
export type WorktreeSurfaceProps = PropsRuntime<'shell.overlay'> & PropsStore<ReturnType<typeof createWorktreeViewStore>> & PropsLocale<typeof WORKTREE_NS> & WorktreeSurfaceInjected;
|
|
1
|
+
import type { WorktreeSurfaceProps } from './worktree-surface-types.js';
|
|
2
|
+
export type { WorktreeSurfaceInjected, WorktreeSurfaceProps, } from './worktree-surface-types.js';
|
|
29
3
|
/**
|
|
30
4
|
* Peer Worktree navigation surface. It keeps the original DSH Workspace mode
|
|
31
5
|
* intact and renders a browser-local Workspace → Worktree → Session projection.
|
|
32
6
|
*/
|
|
33
|
-
export declare function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces, t, available, manager, createWorkspace, createSessionForWorktree: createSessionCallback, createMainSession, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, insertSessionBefore, renameSession, forkSession, archiveSession, ensureSessionWorkspace, syncSessionWorkspaces, openSession, }: WorktreeSurfaceProps): import("react").JSX.Element | null;
|
|
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;
|
|
34
8
|
//# sourceMappingURL=WorktreeSurface.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WorktreeSurface.d.ts","sourceRoot":"","sources":["../../src/client/WorktreeSurface.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"WorktreeSurface.d.ts","sourceRoot":"","sources":["../../src/client/WorktreeSurface.tsx"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAOV,oBAAoB,EAOrB,MAAM,6BAA6B,CAAC;AAmBrC,YAAY,EACV,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,6BAA6B,CAAC;AAkBrC;;;GAGG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,OAAO,EACP,WAAW,EACX,aAAa,EACb,CAAC,EACD,SAAS,EACT,OAAO,EACP,yBAAyB,EACzB,eAAe,EACf,wBAAwB,EAAE,qBAAqB,EAC/C,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,oBAAoB,EACpB,aAAa,EACb,WAAW,EACX,cAAc,EACd,sBAAsB,EACtB,qBAAqB,EACrB,WAAW,GACZ,EAAE,oBAAoB,sCA6mCtB"}
|