@cerbur/clutch-dsh-worktree 0.1.5 → 0.1.6

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.
Files changed (108) hide show
  1. package/README.md +66 -15
  2. package/README.zh.md +59 -13
  3. package/lib/client/WorktreeHeroContext.d.ts +1 -1
  4. package/lib/client/WorktreeHeroContext.js +1 -1
  5. package/lib/client/WorktreeSurface.d.ts +1 -1
  6. package/lib/client/WorktreeSurface.d.ts.map +1 -1
  7. package/lib/client/WorktreeSurface.js +348 -85
  8. package/lib/client/WorktreeSurface.js.map +1 -1
  9. package/lib/client/entry.d.ts.map +1 -1
  10. package/lib/client/entry.js +3 -0
  11. package/lib/client/entry.js.map +1 -1
  12. package/lib/client/locales.d.ts +24 -0
  13. package/lib/client/locales.d.ts.map +1 -1
  14. package/lib/client/locales.js +26 -2
  15. package/lib/client/locales.js.map +1 -1
  16. package/lib/client/virtual-workspace-membership.js +1 -1
  17. package/lib/client/virtual-workspace-membership.js.map +1 -1
  18. package/lib/client/worktree-connection.d.ts +2 -0
  19. package/lib/client/worktree-connection.d.ts.map +1 -1
  20. package/lib/client/worktree-connection.js +4 -0
  21. package/lib/client/worktree-connection.js.map +1 -1
  22. package/lib/client/worktree-error-copy.d.ts.map +1 -1
  23. package/lib/client/worktree-error-copy.js +6 -0
  24. package/lib/client/worktree-error-copy.js.map +1 -1
  25. package/lib/client/worktree-expand-state.d.ts +33 -0
  26. package/lib/client/worktree-expand-state.d.ts.map +1 -0
  27. package/lib/client/worktree-expand-state.js +83 -0
  28. package/lib/client/worktree-expand-state.js.map +1 -0
  29. package/lib/client/worktree-session-position.d.ts +2 -0
  30. package/lib/client/worktree-session-position.d.ts.map +1 -0
  31. package/lib/client/worktree-session-position.js +11 -0
  32. package/lib/client/worktree-session-position.js.map +1 -0
  33. package/lib/client/worktree-surface-dialogs.d.ts +1 -1
  34. package/lib/client/worktree-surface-dialogs.d.ts.map +1 -1
  35. package/lib/client/worktree-surface-dialogs.js +30 -13
  36. package/lib/client/worktree-surface-dialogs.js.map +1 -1
  37. package/lib/client/worktree-surface-rows.d.ts +2 -2
  38. package/lib/client/worktree-surface-rows.d.ts.map +1 -1
  39. package/lib/client/worktree-surface-rows.js +5 -5
  40. package/lib/client/worktree-surface-rows.js.map +1 -1
  41. package/lib/client/worktree-surface-selectors.d.ts +16 -0
  42. package/lib/client/worktree-surface-selectors.d.ts.map +1 -1
  43. package/lib/client/worktree-surface-selectors.js +54 -0
  44. package/lib/client/worktree-surface-selectors.js.map +1 -1
  45. package/lib/client/worktree-surface-types.d.ts +28 -1
  46. package/lib/client/worktree-surface-types.d.ts.map +1 -1
  47. package/lib/client/worktree-view-actions.d.ts +3 -0
  48. package/lib/client/worktree-view-actions.d.ts.map +1 -1
  49. package/lib/client/worktree-view-actions.js +3 -0
  50. package/lib/client/worktree-view-actions.js.map +1 -1
  51. package/lib/client/worktree-view-read.d.ts +8 -0
  52. package/lib/client/worktree-view-read.d.ts.map +1 -1
  53. package/lib/client/worktree-view-read.js +19 -0
  54. package/lib/client/worktree-view-read.js.map +1 -1
  55. package/lib/client.js +612 -101
  56. package/lib/client.js.map +1 -1
  57. package/lib/contract/index.contract.js +14 -0
  58. package/lib/contract/index.contract.js.map +1 -1
  59. package/lib/contract/index.d.ts +22 -2
  60. package/lib/contract/index.d.ts.map +1 -1
  61. package/lib/contract/index.js +4 -0
  62. package/lib/contract/index.js.map +1 -1
  63. package/lib/host/remote.d.ts.map +1 -1
  64. package/lib/host/remote.js +2 -0
  65. package/lib/host/remote.js.map +1 -1
  66. package/lib/host/service.d.ts +8 -1
  67. package/lib/host/service.d.ts.map +1 -1
  68. package/lib/host/service.js +12 -0
  69. package/lib/host/service.js.map +1 -1
  70. package/lib/index.d.ts +1 -1
  71. package/lib/index.d.ts.map +1 -1
  72. package/lib/index.js.map +1 -1
  73. package/lib/manage/manager-support.d.ts +2 -0
  74. package/lib/manage/manager-support.d.ts.map +1 -1
  75. package/lib/manage/manager-support.js +9 -0
  76. package/lib/manage/manager-support.js.map +1 -1
  77. package/lib/manage/manager-worktrees.d.ts +10 -1
  78. package/lib/manage/manager-worktrees.d.ts.map +1 -1
  79. package/lib/manage/manager-worktrees.js +121 -5
  80. package/lib/manage/manager-worktrees.js.map +1 -1
  81. package/lib/manage/manager.d.ts +8 -1
  82. package/lib/manage/manager.d.ts.map +1 -1
  83. package/lib/manage/manager.js +7 -1
  84. package/lib/manage/manager.js.map +1 -1
  85. package/lib/provider/git.d.ts +2 -0
  86. package/lib/provider/git.d.ts.map +1 -1
  87. package/lib/provider/git.js +23 -1
  88. package/lib/provider/git.js.map +1 -1
  89. package/lib/provider/index.d.ts +1 -1
  90. package/lib/provider/index.d.ts.map +1 -1
  91. package/lib/provider/index.js +1 -1
  92. package/lib/provider/index.js.map +1 -1
  93. package/lib/provider/sidecar-schema.d.ts +1 -1
  94. package/lib/provider/sidecar-schema.d.ts.map +1 -1
  95. package/lib/provider/sidecar-schema.js +33 -37
  96. package/lib/provider/sidecar-schema.js.map +1 -1
  97. package/lib/provider/sidecar.d.ts.map +1 -1
  98. package/lib/provider/sidecar.js +3 -1
  99. package/lib/provider/sidecar.js.map +1 -1
  100. package/lib/provider/types.d.ts +9 -1
  101. package/lib/provider/types.d.ts.map +1 -1
  102. package/lib/provider/types.js +2 -1
  103. package/lib/provider/types.js.map +1 -1
  104. package/lib/typert.host.js +115 -21
  105. package/lib/typert.remote-client.d.ts +5 -1
  106. package/lib/typert.remote-client.d.ts.map +1 -1
  107. package/lib/typert.remote-client.js +115 -21
  108. package/package.json +30 -30
package/lib/client.js CHANGED
@@ -42,10 +42,18 @@ window.__ModuleLoader__.load({
42
42
  "worktree.options": "Worktree 选项:{name}",
43
43
  "worktree.remove": "移除 Worktree",
44
44
  "worktree.removeDescription": "移除“{name}”?Session 会保留在 DSH 中,并作为已分离关系继续可用。",
45
+ "worktree.removeExternalDescription": "移除“{name}”?这会删除关联的外部 Worktree 目录。Session 会保留在 DSH 中,并作为已分离关系继续可用。",
45
46
  "worktree.addSession": "向 {name} 添加会话",
46
47
  "worktree.noWorktrees": "暂无 Worktree",
47
48
  "worktree.createTitle": "新建 Worktree",
48
49
  "worktree.createDescription": "“{name}” · Worktree 路径由 DSH 管理。",
50
+ "worktree.tabCreate": "创建",
51
+ "worktree.tabImport": "导入",
52
+ "worktree.importDescription": "向“{name}”注册已有的 Worktree。注册不会移动目录;之后移除会删除关联的 Worktree 目录。",
53
+ "worktree.importLoading": "正在查找可导入的 Worktree…",
54
+ "worktree.importEmpty": "没有可导入的 Worktree。",
55
+ "worktree.importPlaceholder": "请选择要导入的 Worktree",
56
+ "worktree.importSelected": "已选择",
49
57
  "worktree.baseBranch": "Worktree 基线分支",
50
58
  "worktree.noLocalBranch": "没有本地分支",
51
59
  "worktree.noBranches": "此工作区中没有找到本地分支。",
@@ -56,6 +64,7 @@ window.__ModuleLoader__.load({
56
64
  "worktree.setup.commands": "可复制的命令",
57
65
  "worktree.name": "Worktree 名称",
58
66
  "worktree.create": "创建 Worktree",
67
+ "worktree.import": "导入 Worktree",
59
68
  "session.options": "会话选项:{name}",
60
69
  "session.new": "新会话",
61
70
  "session.rename": "重命名会话",
@@ -86,7 +95,10 @@ window.__ModuleLoader__.load({
86
95
  "error.worktreeOrderingUnavailable": "Worktree 排序不可用,请重新连接后重试。",
87
96
  "error.worktreeCreatedSessionUnavailable": "Worktree 已创建,但 Session 创建不可用,请重新连接后重试。",
88
97
  "error.sessionCreationUnavailable": "Session 创建不可用,请重新连接后重试。",
89
- "error.worktreeRecordMissing": "Worktree 创建未返回 Worktree 记录,请重试请求。",
98
+ "error.worktreeRecordMissing": "Worktree 注册未返回 Worktree 记录,请重试请求。",
99
+ "error.worktreeImportInvalid": "这个 Worktree 无法导入,请选择同一 Workspace 中有效的绝对路径。",
100
+ "error.worktreeAlreadyManaged": "这个 Worktree 已由插件管理。",
101
+ "error.worktreeRegistrationSessionUnavailable": "Worktree 已注册,但 Session 创建不可用,请重新连接后重试。",
90
102
  "error.workspaceRenameUnavailable": "工作区重命名不可用,请重新连接后重试。",
91
103
  "error.workspaceDeleteUnavailable": "工作区删除不可用,请重新连接后重试。",
92
104
  "error.sessionRenameUnavailable": "会话重命名不可用,请重新连接后重试。",
@@ -132,10 +144,18 @@ window.__ModuleLoader__.load({
132
144
  "worktree.options": "Worktree options for {name}",
133
145
  "worktree.remove": "Remove Worktree",
134
146
  "worktree.removeDescription": "Remove {name}? Sessions stay in DSH and remain available as detached bindings.",
147
+ "worktree.removeExternalDescription": "Remove {name}? This deletes the linked external Worktree directory. Sessions stay in DSH and remain available as detached bindings.",
135
148
  "worktree.addSession": "Add Session to {name}",
136
149
  "worktree.noWorktrees": "No Worktrees",
137
150
  "worktree.createTitle": "New Worktree",
138
151
  "worktree.createDescription": "{name} · the Worktree path is managed by DSH.",
152
+ "worktree.tabCreate": "Create",
153
+ "worktree.tabImport": "Import",
154
+ "worktree.importDescription": "Register an existing Worktree for {name}. Registration leaves the directory in place; removing it later deletes the linked Worktree directory.",
155
+ "worktree.importLoading": "Finding importable Worktrees…",
156
+ "worktree.importEmpty": "No importable Worktrees found.",
157
+ "worktree.importPlaceholder": "Select a Worktree to import",
158
+ "worktree.importSelected": "Selected",
139
159
  "worktree.baseBranch": "Worktree base branch",
140
160
  "worktree.noLocalBranch": "No local branch",
141
161
  "worktree.noBranches": "No local branches found in this Workspace.",
@@ -146,6 +166,7 @@ window.__ModuleLoader__.load({
146
166
  "worktree.setup.commands": "Copyable commands",
147
167
  "worktree.name": "Worktree name",
148
168
  "worktree.create": "Create Worktree",
169
+ "worktree.import": "Import Worktree",
149
170
  "session.options": "Session options for {name}",
150
171
  "session.new": "New Session",
151
172
  "session.rename": "Rename session",
@@ -176,7 +197,10 @@ window.__ModuleLoader__.load({
176
197
  "error.worktreeOrderingUnavailable": "Worktree ordering is unavailable; retry after reconnecting.",
177
198
  "error.worktreeCreatedSessionUnavailable": "Worktree created, but Session creation is unavailable; retry after reconnecting.",
178
199
  "error.sessionCreationUnavailable": "Session creation is unavailable; retry after reconnecting.",
179
- "error.worktreeRecordMissing": "Worktree creation returned no Worktree record; retry the request.",
200
+ "error.worktreeRecordMissing": "Worktree registration returned no Worktree record; retry the request.",
201
+ "error.worktreeImportInvalid": "This Worktree cannot be imported. Choose a valid absolute path in this Workspace.",
202
+ "error.worktreeAlreadyManaged": "This Worktree is already managed by the plugin.",
203
+ "error.worktreeRegistrationSessionUnavailable": "The Worktree was registered, but Session creation is unavailable; retry after reconnecting.",
180
204
  "error.workspaceRenameUnavailable": "Workspace rename is unavailable; retry after reconnecting.",
181
205
  "error.workspaceDeleteUnavailable": "Workspace delete is unavailable; retry after reconnecting.",
182
206
  "error.sessionRenameUnavailable": "Session rename is unavailable; retry after reconnecting.",
@@ -200,8 +224,10 @@ window.__ModuleLoader__.load({
200
224
  */
201
225
  const WORKTREE_CONNECTION_ENDPOINTS = Object.freeze({
202
226
  listWorktrees: "worktreeManager/listWorktrees",
227
+ listImportCandidates: "worktreeManager/listImportCandidates",
203
228
  listBranches: "worktreeManager/listBranches",
204
229
  createWorktree: "worktreeManager/createWorktree",
230
+ importWorktree: "worktreeManager/importWorktree",
205
231
  removeWorktree: "worktreeManager/removeWorktree",
206
232
  insertWorktreeBefore: "worktreeManager/insertWorktreeBefore",
207
233
  listBindings: "worktreeManager/listBindings",
@@ -220,14 +246,14 @@ window.__ModuleLoader__.load({
220
246
  this.retryable = options.retryable;
221
247
  }
222
248
  };
223
- function isRecord(value) {
249
+ function isRecord$1(value) {
224
250
  return typeof value === "object" && value !== null && !Array.isArray(value);
225
251
  }
226
252
  function isWorktreeError(value) {
227
- return isRecord(value) && typeof value.code === "string" && typeof value.message === "string" && isRecord(value.details);
253
+ return isRecord$1(value) && typeof value.code === "string" && typeof value.message === "string" && isRecord$1(value.details);
228
254
  }
229
255
  function isWorktreeRemoteResult(value) {
230
- if (!isRecord(value) || typeof value.ok !== "boolean") return false;
256
+ if (!isRecord$1(value) || typeof value.ok !== "boolean") return false;
231
257
  return value.ok || isWorktreeError(value.error) && value.error.details !== void 0;
232
258
  }
233
259
  function disposedError() {
@@ -248,7 +274,7 @@ window.__ModuleLoader__.load({
248
274
  });
249
275
  }
250
276
  function gatewayFailure(endpoint, result) {
251
- const rawDetails = isRecord(result.error.details) ? result.error.details : {};
277
+ const rawDetails = isRecord$1(result.error.details) ? result.error.details : {};
252
278
  throw new WorktreeConnectionError({
253
279
  code: result.error.code,
254
280
  message: result.error.message,
@@ -305,8 +331,10 @@ window.__ModuleLoader__.load({
305
331
  }
306
332
  return {
307
333
  listWorktrees: (input) => invoke("listWorktrees", input),
334
+ listImportCandidates: (input) => invoke("listImportCandidates", input),
308
335
  listBranches: (input) => invoke("listBranches", input),
309
336
  createWorktree: (input) => invoke("createWorktree", input),
337
+ importWorktree: (input) => invoke("importWorktree", input),
310
338
  async removeWorktree(input) {
311
339
  await invoke("removeWorktree", input);
312
340
  },
@@ -324,7 +352,7 @@ window.__ModuleLoader__.load({
324
352
  };
325
353
  }
326
354
  //#endregion
327
- //#region \0clutch-dsh-worktree-css:/private/tmp/clutch-dsh-wt-worktree-0.1.5-release/packages/clutch-dsh-worktree/src/client/worktree-context.css.mjs
355
+ //#region \0clutch-dsh-worktree-css:/Users/yuancheng/.dsh/clutch-dsh-worktree/worktree/wt_0c53e50f-f169-4c5e-9664-1c2d58ae1212/packages/clutch-dsh-worktree/src/client/worktree-context.css.mjs
328
356
  const css$1 = ".-cerbur-clutch-dsh-worktree-headerContext {\n display: inline-flex;\n min-width: 0;\n height: 22px;\n align-items: center;\n gap: 4px;\n max-width: 180px;\n overflow: hidden;\n border-radius: 6px;\n padding: 0 2px 0 0;\n background: var(--dsw-alias-fill-tsp-secondary);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 22px;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-contextIcon {\n flex: none;\n opacity: 0.7;\n}\n\n.-cerbur-clutch-dsh-worktree-contextLabel {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-contextHoverTitle {\n max-width: 360px;\n color: var(--dsw-static-neutral-bluish-00);\n font-size: 14px;\n line-height: 20px;\n overflow-wrap: anywhere;\n white-space: normal;\n}\n\n.-cerbur-clutch-dsh-worktree-heroContextHost {\n position: absolute;\n z-index: 1;\n display: block;\n width: max-content;\n max-width: 260px;\n min-height: 22px;\n}\n\n.-cerbur-clutch-dsh-worktree-heroContext {\n display: inline-flex;\n box-sizing: border-box;\n max-width: 260px;\n min-height: 22px;\n align-items: center;\n overflow: hidden;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 999px;\n padding: 0 8px;\n background: var(--dsw-alias-bg-layer-1);\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n line-height: 20px;\n pointer-events: auto;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n";
329
357
  const styleId$1 = "@cerbur/clutch-dsh-worktree/worktree-context.css";
330
358
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"@cerbur/clutch-dsh-worktree/worktree-context.css\"]") === null) {
@@ -371,8 +399,8 @@ window.__ModuleLoader__.load({
371
399
  });
372
400
  }
373
401
  //#endregion
374
- //#region \0clutch-dsh-worktree-css:/private/tmp/clutch-dsh-wt-worktree-0.1.5-release/packages/clutch-dsh-worktree/src/client/worktree.css.mjs
375
- const css = ".-cerbur-clutch-dsh-worktree-action {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 8px;\n width: calc(100% + 4px);\n height: 42px;\n margin: 4px -2px;\n box-sizing: border-box;\n border: 0;\n border-radius: 12px;\n padding: 0 10px 0 8px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n text-align: left;\n overflow: hidden;\n}\n\n.-cerbur-clutch-dsh-worktree-action:hover,\n.-cerbur-clutch-dsh-worktree-action[data-active='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-action[data-collapsed='true'] {\n width: 36px;\n height: 36px;\n margin: 8px 0 10px;\n justify-content: center;\n gap: 0;\n padding: 0;\n border-radius: 50%;\n}\n\n.-cerbur-clutch-dsh-worktree-actionLabel {\n display: inline-flex;\n min-width: 0;\n align-items: center;\n height: 22px;\n overflow: hidden;\n font-weight: 400;\n line-height: 22px;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-surface {\n position: absolute;\n top: 0;\n left: 0;\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n min-width: 56px;\n overflow: hidden;\n border-right: 1px solid var(--dsw-alias-border-l1);\n background: var(--dsw-specific-sidebar-fill);\n color: var(--dsw-alias-label-primary);\n pointer-events: auto;\n transition: width var(--ds-transition-duration-slow) var(--ds-ease-in-out);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .-cerbur-clutch-dsh-worktree-surface {\n transition: none;\n }\n}\n\n.-cerbur-clutch-dsh-worktree-wideContent {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n}\n\n.-cerbur-clutch-dsh-worktree-surface[data-collapsed='true'] .-cerbur-clutch-dsh-worktree-wideContent {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-closeButton {\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: inherit;\n cursor: pointer;\n font: inherit;\n}\n\n.-cerbur-clutch-dsh-worktree-closeButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-header {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: none;\n min-height: 44px;\n padding: 6px 10px;\n box-sizing: border-box;\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n}\n\n.-cerbur-clutch-dsh-worktree-title {\n min-width: 0;\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 14px;\n font-weight: 600;\n}\n\n.-cerbur-clutch-dsh-worktree-closeButton {\n flex: none;\n width: 28px;\n height: 28px;\n font-size: 18px;\n line-height: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-modeButton[data-active='true'] {\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-workspacePicker {\n display: block;\n width: calc(100% - 20px);\n margin: 6px 10px 8px;\n padding: 6px 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 7px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceLabel {\n display: block;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-content {\n min-height: 0;\n flex: 1;\n overflow: auto;\n padding: 0 10px 12px;\n}\n\n.-cerbur-clutch-dsh-worktree-content:focus-visible {\n outline: 2px solid var(--dsw-alias-border-l3);\n outline-offset: -2px;\n}\n\n.-cerbur-clutch-dsh-worktree-error {\n margin: 12px 0 0;\n padding: 8px;\n border: 1px solid var(--dsw-alias-state-error-primary);\n border-radius: 7px;\n}\n\n.-cerbur-clutch-dsh-worktree-retryButton,\n.-cerbur-clutch-dsh-worktree-actionButton {\n border: 0;\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: inherit;\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-retryButton,\n.-cerbur-clutch-dsh-worktree-actionButton {\n width: 100%;\n padding: 6px 8px;\n}\n\n.-cerbur-clutch-dsh-worktree-recoveryActions {\n display: grid;\n gap: 6px;\n margin-top: 6px;\n}\n\n.-cerbur-clutch-dsh-worktree-retryButton:disabled,\n.-cerbur-clutch-dsh-worktree-actionButton:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.-cerbur-clutch-dsh-worktree-actions {\n display: grid;\n gap: 6px;\n margin-top: 10px;\n padding: 8px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 7px;\n}\n\n.-cerbur-clutch-dsh-worktree-actionSelect {\n min-width: 0;\n padding: 5px 6px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-section {\n margin: 12px 0 0;\n}\n\n.-cerbur-clutch-dsh-worktree-sectionTitle {\n margin: 0 2px 4px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n}\n\n.-cerbur-clutch-dsh-worktree-empty,\n.-cerbur-clutch-dsh-worktree-message {\n margin: 0;\n padding: 8px 4px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n}\n\n.-cerbur-clutch-dsh-worktree-gitReadiness {\n display: grid;\n gap: 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-commandBlock {\n margin: 6px 0 0;\n padding: 8px;\n overflow-x: auto;\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-secondary);\n font: 11px/16px ui-monospace, SFMono-Regular, Menlo, monospace;\n white-space: pre-wrap;\n}\n\n.-cerbur-clutch-dsh-worktree-message[data-error='true'] {\n color: var(--dsw-alias-state-error-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-worktree,\n.-cerbur-clutch-dsh-worktree-session {\n display: flex;\n align-items: center;\n width: 100%;\n min-width: 0;\n box-sizing: border-box;\n border: 0;\n border-radius: 7px;\n padding: 6px 8px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n text-align: left;\n}\n\n.-cerbur-clutch-dsh-worktree-worktree {\n cursor: default;\n}\n\n.-cerbur-clutch-dsh-worktree-session {\n cursor: pointer;\n}\n\n.-cerbur-clutch-dsh-worktree-worktree:hover,\n.-cerbur-clutch-dsh-worktree-session:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeLabel,\n.-cerbur-clutch-dsh-worktree-sessionLabel {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-status {\n flex: none;\n margin-left: auto;\n padding-left: 8px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-searchRow {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 10px 6px;\n}\n\n.-cerbur-clutch-dsh-worktree-searchIcon {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n color: var(--dsw-alias-label-secondary);\n}\n\n.-cerbur-clutch-dsh-worktree-searchInput {\n min-width: 0;\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 7px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n outline: none;\n}\n\n.-cerbur-clutch-dsh-worktree-searchInput {\n width: 100%;\n padding: 6px 8px;\n font-size: 13px;\n line-height: 18px;\n}\n\n.-cerbur-clutch-dsh-worktree-searchInput:focus,\n.-cerbur-clutch-dsh-worktree-actionSelect:focus {\n border-color: #3b82f6;\n}\n\n.-cerbur-clutch-dsh-worktree-iconButton {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: 0;\n border-radius: 7px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 20px;\n line-height: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-iconButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceList {\n min-width: 0;\n min-height: 0;\n display: grid;\n gap: 4px;\n overflow-x: hidden;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceGroup {\n min-width: 0;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow,\n.-cerbur-clutch-dsh-worktree-worktreeRow {\n position: relative;\n display: flex;\n align-items: center;\n min-width: 0;\n min-height: 36px;\n box-sizing: border-box;\n border-radius: 8px;\n padding: 3px 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover,\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow .-cerbur-clutch-dsh-worktree-workspaceDisclosure {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover .-cerbur-clutch-dsh-worktree-workspaceDisclosure,\n.-cerbur-clutch-dsh-worktree-workspaceRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-workspaceDisclosure {\n display: inline-flex;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover .-cerbur-clutch-dsh-worktree-workspaceIcon,\n.-cerbur-clutch-dsh-worktree-workspaceRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-workspaceIcon {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow .-cerbur-clutch-dsh-worktree-worktreeDisclosure {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover .-cerbur-clutch-dsh-worktree-worktreeDisclosure,\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-worktreeDisclosure {\n display: inline-flex;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover .-cerbur-clutch-dsh-worktree-worktreeIcon,\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-worktreeIcon {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-disclosureButton {\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 28px;\n border: 0;\n border-radius: 6px;\n padding: 0;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 17px;\n line-height: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-disclosureButton > svg {\n display: block;\n}\n\n.-cerbur-clutch-dsh-worktree-disclosureButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceIcon,\n.-cerbur-clutch-dsh-worktree-worktreeIcon {\n flex: none;\n width: 24px;\n color: var(--dsw-alias-label-secondary);\n font-size: 20px;\n line-height: 1;\n text-align: center;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeState {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 12px;\n margin-right: 0;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceIcon {\n color: var(--dsw-alias-brand-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceTitle,\n.-cerbur-clutch-dsh-worktree-worktreeLabel {\n min-width: 0;\n overflow: hidden;\n flex: 1;\n padding: 0 6px;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 14px;\n font-weight: 400;\n line-height: 20px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-main-group='true'] .-cerbur-clutch-dsh-worktree-worktreeLabel {\n font-weight: 600;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeHoverTitle {\n color: var(--dsw-static-neutral-bluish-00);\n font-size: 14px;\n line-height: 20px;\n overflow-wrap: anywhere;\n}\n\n.-cerbur-clutch-dsh-worktree-treeActionSlot,\n.-cerbur-clutch-dsh-worktree-workspaceActions {\n position: relative;\n display: inline-flex;\n flex: 0 0 64px;\n align-items: center;\n justify-content: flex-end;\n width: 64px;\n height: 28px;\n margin-left: auto;\n}\n\n.-cerbur-clutch-dsh-worktree-treeActionSlot > .-cerbur-clutch-dsh-worktree-menuAction {\n position: absolute;\n top: 0;\n right: 32px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeActionSlot > .-cerbur-clutch-dsh-worktree-iconButton:last-child {\n position: absolute;\n top: 0;\n right: 0;\n}\n\n.-cerbur-clutch-dsh-worktree-menuAction {\n display: inline-flex;\n width: 28px;\n height: 28px;\n visibility: hidden;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover .-cerbur-clutch-dsh-worktree-menuAction,\n.-cerbur-clutch-dsh-worktree-workspaceRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-menuAction,\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover .-cerbur-clutch-dsh-worktree-menuAction,\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-menuAction {\n visibility: visible;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropBefore::before,\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n position: absolute;\n right: 4px;\n left: 4px;\n height: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-brand-primary);\n content: '';\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropBefore::before {\n top: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n bottom: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropBefore::before,\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n position: absolute;\n right: 4px;\n left: 4px;\n height: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-brand-primary);\n content: '';\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropBefore::before {\n top: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n bottom: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeChildren {\n margin-left: 24px;\n padding: 2px 0 5px 12px;\n border-left: 1px solid var(--dsw-alias-border-l1);\n}\n\n.-cerbur-clutch-dsh-worktree-groupLabel {\n padding: 6px 8px 3px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n font-weight: 600;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n}\n\n.-cerbur-clutch-dsh-worktree-groupHeader {\n display: flex;\n align-items: center;\n min-height: 34px;\n padding-right: 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-groupHeader .-cerbur-clutch-dsh-worktree-groupLabel {\n flex: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeGroup {\n margin-top: 2px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow {\n min-height: 34px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow .-cerbur-clutch-dsh-worktree-worktreeIcon,\n.-cerbur-clutch-dsh-worktree-worktreeRow .-cerbur-clutch-dsh-worktree-disclosureButton {\n width: 22px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow {\n position: relative;\n display: flex;\n align-items: center;\n width: 100%;\n min-width: 0;\n min-height: 31px;\n box-sizing: border-box;\n border-radius: 7px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow:hover,\n.-cerbur-clutch-dsh-worktree-treeSessionRow[data-menu-open='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropBefore::before,\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n position: absolute;\n right: 4px;\n left: 4px;\n height: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-brand-primary);\n content: '';\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropBefore::before {\n top: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n bottom: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionContent {\n display: flex;\n align-items: center;\n flex: 1;\n width: 0;\n min-width: 0;\n min-height: 31px;\n box-sizing: border-box;\n border: 0;\n border-radius: 7px;\n padding: 4px 4px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: inherit;\n font-size: 14px;\n font-weight: 400;\n line-height: 20px;\n text-align: left;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionContent:hover {\n background: transparent;\n}\n\n.-cerbur-clutch-dsh-worktree-rowActions {\n display: none;\n flex: none;\n align-items: center;\n gap: 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-sessionOverflowButton {\n display: block;\n width: calc(100% - 24px);\n margin: 2px 0 4px 24px;\n padding: 4px 8px;\n border: 0;\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 12px;\n font-weight: 400;\n line-height: 20px;\n text-align: left;\n}\n\n.-cerbur-clutch-dsh-worktree-sessionOverflowButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow:hover .-cerbur-clutch-dsh-worktree-rowActions,\n.-cerbur-clutch-dsh-worktree-treeSessionRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-rowActions {\n display: inline-flex;\n}\n\n.-cerbur-clutch-dsh-worktree-renameInput {\n width: 100%;\n}\n\n.-cerbur-clutch-dsh-worktree-renameError {\n margin: 8px 0 0;\n color: var(--dsw-alias-state-error-primary);\n font-size: 13px;\n line-height: 20px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeGuide {\n flex: none;\n width: 20px;\n color: var(--dsw-alias-label-tertiary);\n text-align: center;\n}\n\n.-cerbur-clutch-dsh-worktree-emptyNested {\n margin: 0;\n padding: 4px 8px 5px 28px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-modalField {\n display: grid;\n gap: 5px;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n}\n";
402
+ //#region \0clutch-dsh-worktree-css:/Users/yuancheng/.dsh/clutch-dsh-worktree/worktree/wt_0c53e50f-f169-4c5e-9664-1c2d58ae1212/packages/clutch-dsh-worktree/src/client/worktree.css.mjs
403
+ const css = ".-cerbur-clutch-dsh-worktree-action {\n display: flex;\n align-items: center;\n justify-content: flex-start;\n gap: 8px;\n width: calc(100% + 4px);\n height: 42px;\n margin: 4px -2px;\n box-sizing: border-box;\n border: 0;\n border-radius: 12px;\n padding: 0 10px 0 8px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: inherit;\n font-size: 14px;\n line-height: 22px;\n text-align: left;\n overflow: hidden;\n}\n\n.-cerbur-clutch-dsh-worktree-action:hover,\n.-cerbur-clutch-dsh-worktree-action[data-active='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-action[data-collapsed='true'] {\n width: 36px;\n height: 36px;\n margin: 8px 0 10px;\n justify-content: center;\n gap: 0;\n padding: 0;\n border-radius: 50%;\n}\n\n.-cerbur-clutch-dsh-worktree-actionLabel {\n display: inline-flex;\n min-width: 0;\n align-items: center;\n height: 22px;\n overflow: hidden;\n font-weight: 400;\n line-height: 22px;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-surface {\n position: absolute;\n top: 0;\n left: 0;\n display: flex;\n flex-direction: column;\n box-sizing: border-box;\n min-width: 56px;\n overflow: hidden;\n border-right: 1px solid var(--dsw-alias-border-l1);\n background: var(--dsw-specific-sidebar-fill);\n color: var(--dsw-alias-label-primary);\n pointer-events: auto;\n transition: width var(--ds-transition-duration-slow) var(--ds-ease-in-out);\n}\n\n@media (prefers-reduced-motion: reduce) {\n .-cerbur-clutch-dsh-worktree-surface {\n transition: none;\n }\n}\n\n.-cerbur-clutch-dsh-worktree-wideContent {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n}\n\n.-cerbur-clutch-dsh-worktree-surface[data-collapsed='true'] .-cerbur-clutch-dsh-worktree-wideContent {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeModalTabs {\n display: flex;\n gap: 8px;\n margin-bottom: 12px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeModalTab {\n border: 0;\n border-bottom: 2px solid transparent;\n padding: 4px 0;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeModalTab[aria-selected='true'] {\n border-bottom-color: var(--dsw-alias-label-primary);\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeImportCandidates {\n display: grid;\n gap: 8px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeImportSelect {\n width: 100%;\n min-width: 0;\n padding: 7px 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 13px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeImportError {\n display: grid;\n gap: 8px;\n}\n\n.-cerbur-clutch-dsh-worktree-closeButton {\n border: 0;\n border-radius: 8px;\n background: transparent;\n color: inherit;\n cursor: pointer;\n font: inherit;\n}\n\n.-cerbur-clutch-dsh-worktree-closeButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-header {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: none;\n min-height: 44px;\n padding: 6px 10px;\n box-sizing: border-box;\n border-bottom: 1px solid var(--dsw-alias-border-l1);\n}\n\n.-cerbur-clutch-dsh-worktree-title {\n min-width: 0;\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 14px;\n font-weight: 600;\n}\n\n.-cerbur-clutch-dsh-worktree-closeButton {\n flex: none;\n width: 28px;\n height: 28px;\n font-size: 18px;\n line-height: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-modeButton[data-active='true'] {\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-workspacePicker {\n display: block;\n width: calc(100% - 20px);\n margin: 6px 10px 8px;\n padding: 6px 8px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 7px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceLabel {\n display: block;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-content {\n min-height: 0;\n flex: 1;\n overflow: auto;\n padding: 0 10px 12px;\n}\n\n.-cerbur-clutch-dsh-worktree-content:focus-visible {\n outline: 2px solid var(--dsw-alias-border-l3);\n outline-offset: -2px;\n}\n\n.-cerbur-clutch-dsh-worktree-error {\n margin: 12px 0 0;\n padding: 8px;\n border: 1px solid var(--dsw-alias-state-error-primary);\n border-radius: 7px;\n}\n\n.-cerbur-clutch-dsh-worktree-retryButton,\n.-cerbur-clutch-dsh-worktree-actionButton {\n border: 0;\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: inherit;\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-retryButton,\n.-cerbur-clutch-dsh-worktree-actionButton {\n width: 100%;\n padding: 6px 8px;\n}\n\n.-cerbur-clutch-dsh-worktree-recoveryActions {\n display: grid;\n gap: 6px;\n margin-top: 6px;\n}\n\n.-cerbur-clutch-dsh-worktree-retryButton:disabled,\n.-cerbur-clutch-dsh-worktree-actionButton:disabled {\n cursor: not-allowed;\n opacity: 0.5;\n}\n\n.-cerbur-clutch-dsh-worktree-actions {\n display: grid;\n gap: 6px;\n margin-top: 10px;\n padding: 8px;\n border: 1px solid var(--dsw-alias-border-l1);\n border-radius: 7px;\n}\n\n.-cerbur-clutch-dsh-worktree-actionSelect {\n min-width: 0;\n padding: 5px 6px;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-section {\n margin: 12px 0 0;\n}\n\n.-cerbur-clutch-dsh-worktree-sectionTitle {\n margin: 0 2px 4px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n font-weight: 600;\n letter-spacing: 0.02em;\n text-transform: uppercase;\n}\n\n.-cerbur-clutch-dsh-worktree-empty,\n.-cerbur-clutch-dsh-worktree-message {\n margin: 0;\n padding: 8px 4px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 12px;\n line-height: 18px;\n}\n\n.-cerbur-clutch-dsh-worktree-gitReadiness {\n display: grid;\n gap: 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-commandBlock {\n margin: 6px 0 0;\n padding: 8px;\n overflow-x: auto;\n border-radius: 6px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-secondary);\n font: 11px/16px ui-monospace, SFMono-Regular, Menlo, monospace;\n white-space: pre-wrap;\n}\n\n.-cerbur-clutch-dsh-worktree-message[data-error='true'] {\n color: var(--dsw-alias-state-error-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-worktree,\n.-cerbur-clutch-dsh-worktree-session {\n display: flex;\n align-items: center;\n width: 100%;\n min-width: 0;\n box-sizing: border-box;\n border: 0;\n border-radius: 7px;\n padding: 6px 8px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n font: inherit;\n font-size: 12px;\n text-align: left;\n}\n\n.-cerbur-clutch-dsh-worktree-worktree {\n cursor: default;\n}\n\n.-cerbur-clutch-dsh-worktree-session {\n cursor: pointer;\n}\n\n.-cerbur-clutch-dsh-worktree-worktree:hover,\n.-cerbur-clutch-dsh-worktree-session:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeLabel,\n.-cerbur-clutch-dsh-worktree-sessionLabel {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.-cerbur-clutch-dsh-worktree-status {\n flex: none;\n margin-left: auto;\n padding-left: 8px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-searchRow {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 8px 10px 6px;\n}\n\n.-cerbur-clutch-dsh-worktree-searchIcon {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n color: var(--dsw-alias-label-secondary);\n}\n\n.-cerbur-clutch-dsh-worktree-searchInput {\n min-width: 0;\n box-sizing: border-box;\n border: 1px solid var(--dsw-alias-border-l2);\n border-radius: 7px;\n background: var(--dsw-alias-button-elevated-fill);\n color: var(--dsw-alias-label-primary);\n font: inherit;\n outline: none;\n}\n\n.-cerbur-clutch-dsh-worktree-searchInput {\n width: 100%;\n padding: 6px 8px;\n font-size: 13px;\n line-height: 18px;\n}\n\n.-cerbur-clutch-dsh-worktree-searchInput:focus,\n.-cerbur-clutch-dsh-worktree-actionSelect:focus,\n.-cerbur-clutch-dsh-worktree-worktreeImportSelect:focus {\n border-color: #3b82f6;\n}\n\n.-cerbur-clutch-dsh-worktree-iconButton {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n border: 0;\n border-radius: 7px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 20px;\n line-height: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-iconButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceList {\n min-width: 0;\n min-height: 0;\n display: grid;\n gap: 4px;\n overflow-x: hidden;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceGroup {\n min-width: 0;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow,\n.-cerbur-clutch-dsh-worktree-worktreeRow {\n position: relative;\n display: flex;\n align-items: center;\n min-width: 0;\n min-height: 36px;\n box-sizing: border-box;\n border-radius: 8px;\n padding: 3px 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover,\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow .-cerbur-clutch-dsh-worktree-workspaceDisclosure {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover .-cerbur-clutch-dsh-worktree-workspaceDisclosure,\n.-cerbur-clutch-dsh-worktree-workspaceRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-workspaceDisclosure {\n display: inline-flex;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover .-cerbur-clutch-dsh-worktree-workspaceIcon,\n.-cerbur-clutch-dsh-worktree-workspaceRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-workspaceIcon {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow .-cerbur-clutch-dsh-worktree-worktreeDisclosure {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover .-cerbur-clutch-dsh-worktree-worktreeDisclosure,\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-worktreeDisclosure {\n display: inline-flex;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover .-cerbur-clutch-dsh-worktree-worktreeIcon,\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-worktreeIcon {\n display: none;\n}\n\n.-cerbur-clutch-dsh-worktree-disclosureButton {\n flex: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 28px;\n border: 0;\n border-radius: 6px;\n padding: 0;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 17px;\n line-height: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-disclosureButton > svg {\n display: block;\n}\n\n.-cerbur-clutch-dsh-worktree-disclosureButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceIcon,\n.-cerbur-clutch-dsh-worktree-worktreeIcon {\n flex: none;\n width: 24px;\n color: var(--dsw-alias-label-secondary);\n font-size: 20px;\n line-height: 1;\n text-align: center;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeState {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 12px;\n margin-right: 0;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceIcon {\n color: var(--dsw-alias-brand-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceTitle,\n.-cerbur-clutch-dsh-worktree-worktreeLabel {\n min-width: 0;\n overflow: hidden;\n flex: 1;\n padding: 0 6px;\n text-overflow: ellipsis;\n white-space: nowrap;\n font-size: 14px;\n font-weight: 400;\n line-height: 20px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-main-group='true'] .-cerbur-clutch-dsh-worktree-worktreeLabel {\n font-weight: 600;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeHoverTitle {\n color: var(--dsw-static-neutral-bluish-00);\n font-size: 14px;\n line-height: 20px;\n overflow-wrap: anywhere;\n}\n\n.-cerbur-clutch-dsh-worktree-treeActionSlot,\n.-cerbur-clutch-dsh-worktree-workspaceActions {\n position: relative;\n display: inline-flex;\n flex: 0 0 64px;\n align-items: center;\n justify-content: flex-end;\n width: 64px;\n height: 28px;\n margin-left: auto;\n}\n\n.-cerbur-clutch-dsh-worktree-treeActionSlot > .-cerbur-clutch-dsh-worktree-menuAction {\n position: absolute;\n top: 0;\n right: 32px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeActionSlot > .-cerbur-clutch-dsh-worktree-iconButton:last-child {\n position: absolute;\n top: 0;\n right: 0;\n}\n\n.-cerbur-clutch-dsh-worktree-menuAction {\n display: inline-flex;\n width: 28px;\n height: 28px;\n visibility: hidden;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow:hover .-cerbur-clutch-dsh-worktree-menuAction,\n.-cerbur-clutch-dsh-worktree-workspaceRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-menuAction,\n.-cerbur-clutch-dsh-worktree-worktreeRow:hover .-cerbur-clutch-dsh-worktree-menuAction,\n.-cerbur-clutch-dsh-worktree-worktreeRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-menuAction {\n visibility: visible;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropBefore::before,\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n position: absolute;\n right: 4px;\n left: 4px;\n height: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-brand-primary);\n content: '';\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropBefore::before {\n top: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-workspaceRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n bottom: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropBefore::before,\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n position: absolute;\n right: 4px;\n left: 4px;\n height: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-brand-primary);\n content: '';\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropBefore::before {\n top: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n bottom: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeChildren {\n margin-left: 16px;\n padding: 2px 0 5px 12px;\n border-left: 1px solid var(--dsw-alias-border-l1);\n}\n\n.-cerbur-clutch-dsh-worktree-groupLabel {\n padding: 6px 8px 3px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 10px;\n font-weight: 600;\n letter-spacing: 0.05em;\n text-transform: uppercase;\n}\n\n.-cerbur-clutch-dsh-worktree-groupHeader {\n display: flex;\n align-items: center;\n min-height: 34px;\n padding-right: 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-groupHeader .-cerbur-clutch-dsh-worktree-groupLabel {\n flex: 1;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeGroup {\n margin-top: 2px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow {\n min-height: 34px;\n}\n\n.-cerbur-clutch-dsh-worktree-worktreeRow .-cerbur-clutch-dsh-worktree-worktreeIcon,\n.-cerbur-clutch-dsh-worktree-worktreeRow .-cerbur-clutch-dsh-worktree-disclosureButton {\n width: 22px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow {\n position: relative;\n display: flex;\n align-items: center;\n width: calc(100% - 22px);\n margin-left: 22px;\n min-width: 0;\n min-height: 31px;\n box-sizing: border-box;\n border-radius: 7px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow:hover,\n.-cerbur-clutch-dsh-worktree-treeSessionRow[data-menu-open='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow[data-session-current='true'] {\n background: var(--dsw-alias-interactive-bg-hover);\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow[data-session-current='true'] .-cerbur-clutch-dsh-worktree-treeSessionContent {\n font-weight: 600;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropBefore::before,\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n position: absolute;\n right: 4px;\n left: 4px;\n height: 2px;\n border-radius: 2px;\n background: var(--dsw-alias-brand-primary);\n content: '';\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropBefore::before {\n top: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow.-cerbur-clutch-dsh-worktree-dropAfter::after {\n bottom: -1px;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionContent {\n display: flex;\n align-items: center;\n flex: 1;\n width: 0;\n min-width: 0;\n min-height: 31px;\n box-sizing: border-box;\n border: 0;\n border-radius: 7px;\n padding: 4px 4px;\n background: transparent;\n color: var(--dsw-alias-label-primary);\n cursor: pointer;\n font: inherit;\n font-size: 14px;\n font-weight: 400;\n line-height: 20px;\n text-align: left;\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionContent:hover {\n background: transparent;\n}\n\n.-cerbur-clutch-dsh-worktree-rowActions {\n display: none;\n flex: none;\n align-items: center;\n gap: 4px;\n}\n\n.-cerbur-clutch-dsh-worktree-sessionOverflowButton {\n display: block;\n width: calc(100% - 24px);\n margin: 2px 0 4px 24px;\n padding: 4px 8px;\n border: 0;\n border-radius: 6px;\n background: transparent;\n color: var(--dsw-alias-label-secondary);\n cursor: pointer;\n font: inherit;\n font-size: 12px;\n font-weight: 400;\n line-height: 20px;\n text-align: left;\n}\n\n.-cerbur-clutch-dsh-worktree-sessionOverflowButton:hover {\n background: var(--dsw-alias-interactive-bg-hover);\n color: var(--dsw-alias-label-primary);\n}\n\n.-cerbur-clutch-dsh-worktree-treeSessionRow:hover .-cerbur-clutch-dsh-worktree-rowActions,\n.-cerbur-clutch-dsh-worktree-treeSessionRow[data-menu-open='true'] .-cerbur-clutch-dsh-worktree-rowActions {\n display: inline-flex;\n}\n\n.-cerbur-clutch-dsh-worktree-renameInput {\n width: 100%;\n}\n\n.-cerbur-clutch-dsh-worktree-renameError {\n margin: 8px 0 0;\n color: var(--dsw-alias-state-error-primary);\n font-size: 13px;\n line-height: 20px;\n}\n\n.-cerbur-clutch-dsh-worktree-emptyNested {\n margin: 0;\n padding: 4px 8px 5px 28px;\n color: var(--dsw-alias-label-tertiary);\n font-size: 11px;\n}\n\n.-cerbur-clutch-dsh-worktree-modalField {\n display: grid;\n gap: 5px;\n color: var(--dsw-alias-label-secondary);\n font-size: 12px;\n}\n";
376
404
  const styleId = "@cerbur/clutch-dsh-worktree/worktree.css";
377
405
  if (typeof document !== "undefined" && document.querySelector("style[data-plugin-css=\"@cerbur/clutch-dsh-worktree/worktree.css\"]") === null) {
378
406
  const tag = document.createElement("style");
@@ -386,6 +414,11 @@ window.__ModuleLoader__.load({
386
414
  "actionLabel": "-cerbur-clutch-dsh-worktree-actionLabel",
387
415
  "surface": "-cerbur-clutch-dsh-worktree-surface",
388
416
  "wideContent": "-cerbur-clutch-dsh-worktree-wideContent",
417
+ "worktreeModalTabs": "-cerbur-clutch-dsh-worktree-worktreeModalTabs",
418
+ "worktreeModalTab": "-cerbur-clutch-dsh-worktree-worktreeModalTab",
419
+ "worktreeImportCandidates": "-cerbur-clutch-dsh-worktree-worktreeImportCandidates",
420
+ "worktreeImportSelect": "-cerbur-clutch-dsh-worktree-worktreeImportSelect",
421
+ "worktreeImportError": "-cerbur-clutch-dsh-worktree-worktreeImportError",
389
422
  "closeButton": "-cerbur-clutch-dsh-worktree-closeButton",
390
423
  "header": "-cerbur-clutch-dsh-worktree-header",
391
424
  "title": "-cerbur-clutch-dsh-worktree-title",
@@ -441,7 +474,6 @@ window.__ModuleLoader__.load({
441
474
  "sessionOverflowButton": "-cerbur-clutch-dsh-worktree-sessionOverflowButton",
442
475
  "renameInput": "-cerbur-clutch-dsh-worktree-renameInput",
443
476
  "renameError": "-cerbur-clutch-dsh-worktree-renameError",
444
- "treeGuide": "-cerbur-clutch-dsh-worktree-treeGuide",
445
477
  "emptyNested": "-cerbur-clutch-dsh-worktree-emptyNested",
446
478
  "modalField": "-cerbur-clutch-dsh-worktree-modalField"
447
479
  };
@@ -512,7 +544,7 @@ window.__ModuleLoader__.load({
512
544
  }
513
545
  /**
514
546
  * Browser-local Hero suffix. It intentionally uses the frame overlay because
515
- * rc.8 exposes no additive slot beside the native Hero headline.
547
+ * The current upstream DSH exposes no additive slot beside the native Hero headline.
516
548
  */
517
549
  function WorktreeHeroContext({ useWorktreeContext, t }) {
518
550
  const state = useWorktreeContext((snapshot) => snapshot);
@@ -711,6 +743,84 @@ window.__ModuleLoader__.load({
711
743
  };
712
744
  }
713
745
  //#endregion
746
+ //#region lib/client/worktree-expand-state.js
747
+ /** Browser-local storage identity; never sent to DSH or the plugin sidecar. */
748
+ const WORKTREE_EXPAND_STATE_STORAGE_KEY = "clutch-dsh-worktree.expand-state";
749
+ function emptyState() {
750
+ return {
751
+ collapsedWorkspaceIds: {},
752
+ collapsedMainWorkspaceIds: {},
753
+ collapsedWorktreeIds: {}
754
+ };
755
+ }
756
+ function isRecord(value) {
757
+ return typeof value === "object" && value !== null && !Array.isArray(value);
758
+ }
759
+ function normalizeIds(value) {
760
+ if (!isRecord(value)) return {};
761
+ return Object.fromEntries(Object.entries(value).filter(([id, collapsed]) => id.length > 0 && collapsed === true));
762
+ }
763
+ /** Turn any persisted JSON value into the current state shape. */
764
+ function normalizeWorktreeExpandState(value) {
765
+ const source = isRecord(value) ? value : {};
766
+ return {
767
+ collapsedWorkspaceIds: normalizeIds(source.collapsedWorkspaceIds),
768
+ collapsedMainWorkspaceIds: normalizeIds(source.collapsedMainWorkspaceIds),
769
+ collapsedWorktreeIds: normalizeIds(source.collapsedWorktreeIds)
770
+ };
771
+ }
772
+ function isWorkspaceExpanded(state, workspaceId) {
773
+ return state.collapsedWorkspaceIds[workspaceId] !== true;
774
+ }
775
+ function isMainExpanded(state, workspaceId) {
776
+ return state.collapsedMainWorkspaceIds[workspaceId] !== true;
777
+ }
778
+ function isWorktreeExpanded(state, worktreeId) {
779
+ return state.collapsedWorktreeIds[worktreeId] !== true;
780
+ }
781
+ function toggle(record, id) {
782
+ if (record[id] === true) delete record[id];
783
+ else record[id] = true;
784
+ }
785
+ function retain(record, ids) {
786
+ const allowed = new Set(ids);
787
+ for (const id of Object.keys(record)) if (!allowed.has(id)) delete record[id];
788
+ }
789
+ /** Create one apply-scoped store; component remounts share this instance. */
790
+ function createWorktreeExpandStateStore(snapshotStoreFactory) {
791
+ let store;
792
+ try {
793
+ store = snapshotStoreFactory(emptyState(), { persist: { name: WORKTREE_EXPAND_STATE_STORAGE_KEY } });
794
+ } catch {
795
+ store = snapshotStoreFactory(emptyState());
796
+ }
797
+ store.set(normalizeWorktreeExpandState(store.getSnapshot()));
798
+ return Object.assign(store, { actions: {
799
+ toggleWorkspace: (workspaceId) => {
800
+ store.update((draft) => {
801
+ toggle(draft.collapsedWorkspaceIds, workspaceId);
802
+ });
803
+ },
804
+ toggleMain: (workspaceId) => {
805
+ store.update((draft) => {
806
+ toggle(draft.collapsedMainWorkspaceIds, workspaceId);
807
+ });
808
+ },
809
+ toggleWorktree: (worktreeId) => {
810
+ store.update((draft) => {
811
+ toggle(draft.collapsedWorktreeIds, worktreeId);
812
+ });
813
+ },
814
+ retain: (workspaceIds, worktreeIds) => {
815
+ store.update((draft) => {
816
+ retain(draft.collapsedWorkspaceIds, workspaceIds);
817
+ retain(draft.collapsedMainWorkspaceIds, workspaceIds);
818
+ retain(draft.collapsedWorktreeIds, worktreeIds);
819
+ });
820
+ }
821
+ } });
822
+ }
823
+ //#endregion
714
824
  //#region lib/client/view-mode.js
715
825
  /** Browser-local storage key; it is never sent to DSH or the sidecar. */
716
826
  const WORKTREE_VIEW_MODE_STORAGE_KEY = "clutch-dsh-worktree.view-mode";
@@ -787,6 +897,9 @@ window.__ModuleLoader__.load({
787
897
  case "SESSION_CREATE_UNAVAILABLE": return t("error.sessionCreationUnavailable");
788
898
  case "WORKTREE_CREATED_SESSION_UNAVAILABLE": return t("error.worktreeCreatedSessionUnavailable");
789
899
  case "WORKTREE_RECORD_MISSING": return t("error.worktreeRecordMissing");
900
+ case "WORKTREE_IMPORT_INVALID": return t("error.worktreeImportInvalid");
901
+ case "WORKTREE_ALREADY_MANAGED": return t("error.worktreeAlreadyManaged");
902
+ case "WORKTREE_REGISTRATION_SESSION_UNAVAILABLE": return t("error.worktreeRegistrationSessionUnavailable");
790
903
  case "WORKSPACE_RENAME_UNAVAILABLE": return t("error.workspaceRenameUnavailable");
791
904
  case "WORKSPACE_DELETE_UNAVAILABLE": return t("error.workspaceDeleteUnavailable");
792
905
  case "SESSION_RENAME_UNAVAILABLE": return t("error.sessionRenameUnavailable");
@@ -917,6 +1030,7 @@ window.__ModuleLoader__.load({
917
1030
  /** Keep mutation routing in the browser Consumer while leaving wire details to the adapter. */
918
1031
  async function executeWorktreeAction(manager, action) {
919
1032
  if (action.type === "createWorktree") return manager.createWorktree(action.input);
1033
+ if (action.type === "importWorktree") return manager.importWorktree(action.input);
920
1034
  if (action.type === "removeWorktree") {
921
1035
  await manager.removeWorktree(action.input);
922
1036
  return;
@@ -943,6 +1057,14 @@ window.__ModuleLoader__.load({
943
1057
  }
944
1058
  //#endregion
945
1059
  //#region lib/client/worktree-view-read.js
1060
+ /** Merge one freshly read Workspace projection without clearing other ready views. */
1061
+ function mergeWorktreeView(views, nextView) {
1062
+ const index = views.findIndex((view) => view.workspaceId === nextView.workspaceId);
1063
+ if (index === -1) return [...views, nextView];
1064
+ const merged = [...views];
1065
+ merged[index] = nextView;
1066
+ return merged;
1067
+ }
946
1068
  /** Reuse the previous ID snapshot when DSH republishes equivalent Workspace items. */
947
1069
  function stableWorkspaceIds(previous, next) {
948
1070
  if (previous.length !== next.length) return next;
@@ -1048,6 +1170,19 @@ window.__ModuleLoader__.load({
1048
1170
  readiness: branchesResult.value.length > 0 ? { status: "ready" } : { status: "noLocalBranch" }
1049
1171
  };
1050
1172
  }
1173
+ /** Isolate modal-target reads from full-surface refresh generations. */
1174
+ function createWorktreeModalViewLoader() {
1175
+ const guard = createWorktreeRefreshGuard();
1176
+ return {
1177
+ invalidate: guard.invalidate,
1178
+ load(manager, workspaceId, onSuccess, onError) {
1179
+ return guard.run(() => loadWorktreeView(manager, workspaceId), (data) => onSuccess({
1180
+ workspaceId,
1181
+ ...data
1182
+ }), (error) => onError(toWorktreeViewError(error)));
1183
+ }
1184
+ };
1185
+ }
1051
1186
  /** Load one independent projection per DSH Workspace for the flat sidebar hierarchy. */
1052
1187
  async function loadWorktreeViews(manager, workspaceIds, options = {}) {
1053
1188
  const views = await Promise.all(workspaceIds.map(async (workspaceId) => ({
@@ -1348,10 +1483,12 @@ window.__ModuleLoader__.load({
1348
1483
  })
1349
1484
  });
1350
1485
  }
1351
- function WorktreeCreateDialog({ t, workspace, view, setupStatus, canCreate, selectedBranch, newBranch, actionPending, onClose, onSelectedBranchChange, onNewBranchChange, onSubmit }) {
1486
+ function WorktreeCreateDialog({ t, workspace, view, readError, setupStatus, canCreate, mode, importCandidates, selectedImportPath, selectedBranch, newBranch, actionPending, onClose, onRetry, onModeChange, onRetryImportCandidates, onSelectedImportPathChange, onSelectedBranchChange, onNewBranchChange, onSubmit }) {
1352
1487
  if (workspace === void 0) return null;
1353
1488
  const setupCommands = setupStatus === void 0 ? [] : worktreeSetupCommands(setupStatus);
1354
- return (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
1489
+ const importing = mode === "import";
1490
+ const importBlocked = actionPending || importCandidates.status === "loading" || selectedImportPath === void 0;
1491
+ return (0, react_jsx_runtime.jsxs)(_deepseek_ai_dsh_client_ui_primitives.Modal, {
1355
1492
  open: true,
1356
1493
  onClose: () => {
1357
1494
  if (actionPending) return;
@@ -1359,7 +1496,7 @@ window.__ModuleLoader__.load({
1359
1496
  },
1360
1497
  closeLabel: t("dialog.closeWorktreeCreate"),
1361
1498
  title: t("worktree.createTitle"),
1362
- description: t("worktree.createDescription", { name: workspace.title }),
1499
+ description: importing ? t("worktree.importDescription", { name: workspace.title }) : t("worktree.createDescription", { name: workspace.title }),
1363
1500
  footer: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1364
1501
  variant: "outline",
1365
1502
  disabled: actionPending,
@@ -1367,13 +1504,104 @@ window.__ModuleLoader__.load({
1367
1504
  children: t("dialog.cancel")
1368
1505
  }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1369
1506
  variant: "primary",
1370
- disabled: actionPending || selectedBranch.length === 0 || newBranch.trim().length === 0,
1507
+ disabled: importing ? importBlocked : actionPending || !canCreate || selectedBranch.length === 0 || newBranch.trim().length === 0,
1371
1508
  onClick: () => {
1372
1509
  onSubmit();
1373
1510
  },
1374
- children: t("worktree.create")
1511
+ children: importing ? t("worktree.import") : t("worktree.create")
1375
1512
  })] }),
1376
- children: canCreate ? (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("label", {
1513
+ children: [(0, react_jsx_runtime.jsxs)("div", {
1514
+ className: worktree_css_default.worktreeModalTabs,
1515
+ role: "tablist",
1516
+ "aria-label": t("worktree.title"),
1517
+ children: [(0, react_jsx_runtime.jsx)("button", {
1518
+ className: worktree_css_default.worktreeModalTab,
1519
+ type: "button",
1520
+ role: "tab",
1521
+ "aria-selected": mode === "create",
1522
+ disabled: actionPending,
1523
+ onClick: () => {
1524
+ onModeChange("create");
1525
+ },
1526
+ children: t("worktree.tabCreate")
1527
+ }), (0, react_jsx_runtime.jsx)("button", {
1528
+ className: worktree_css_default.worktreeModalTab,
1529
+ type: "button",
1530
+ role: "tab",
1531
+ "aria-selected": mode === "import",
1532
+ disabled: actionPending,
1533
+ onClick: () => {
1534
+ onModeChange("import");
1535
+ },
1536
+ children: t("worktree.tabImport")
1537
+ })]
1538
+ }), importing ? (0, react_jsx_runtime.jsxs)("div", {
1539
+ className: worktree_css_default.worktreeImportCandidates,
1540
+ role: "tabpanel",
1541
+ children: [
1542
+ importCandidates.status === "loading" && importCandidates.candidates.length === 0 && (0, react_jsx_runtime.jsx)("p", {
1543
+ className: worktree_css_default.message,
1544
+ children: t("worktree.importLoading")
1545
+ }),
1546
+ importCandidates.status === "error" && (0, react_jsx_runtime.jsxs)("div", {
1547
+ className: worktree_css_default.worktreeImportError,
1548
+ role: "alert",
1549
+ children: [(0, react_jsx_runtime.jsx)("p", {
1550
+ className: worktree_css_default.message,
1551
+ children: formatWorktreeViewError(importCandidates.error, t)
1552
+ }), (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1553
+ variant: "outline",
1554
+ disabled: actionPending,
1555
+ onClick: onRetryImportCandidates,
1556
+ children: t("action.retry")
1557
+ })]
1558
+ }),
1559
+ importCandidates.candidates.length === 0 && importCandidates.status === "ready" && (0, react_jsx_runtime.jsx)("p", {
1560
+ className: worktree_css_default.message,
1561
+ children: t("worktree.importEmpty")
1562
+ }),
1563
+ importCandidates.candidates.length > 0 && (0, react_jsx_runtime.jsxs)("label", {
1564
+ className: worktree_css_default.modalField,
1565
+ children: [t("worktree.tabImport"), (0, react_jsx_runtime.jsxs)("select", {
1566
+ className: worktree_css_default.worktreeImportSelect,
1567
+ "data-worktree-import-select": true,
1568
+ "aria-label": t("worktree.tabImport"),
1569
+ value: selectedImportPath ?? "",
1570
+ disabled: actionPending,
1571
+ onChange: (event) => {
1572
+ onSelectedImportPathChange(event.currentTarget.value);
1573
+ },
1574
+ children: [(0, react_jsx_runtime.jsx)("option", {
1575
+ value: "",
1576
+ disabled: true,
1577
+ children: t("worktree.importPlaceholder")
1578
+ }), importCandidates.candidates.map((candidate) => (0, react_jsx_runtime.jsxs)("option", {
1579
+ value: candidate.absolutePath,
1580
+ children: [
1581
+ candidate.branch,
1582
+ " — ",
1583
+ candidate.absolutePath
1584
+ ]
1585
+ }, candidate.absolutePath))]
1586
+ })]
1587
+ })
1588
+ ]
1589
+ }) : readError !== void 0 ? (0, react_jsx_runtime.jsxs)("div", {
1590
+ className: worktree_css_default.gitReadiness,
1591
+ "data-worktree-readiness": "error",
1592
+ role: "alert",
1593
+ children: [(0, react_jsx_runtime.jsx)("p", {
1594
+ className: worktree_css_default.message,
1595
+ "data-error": "true",
1596
+ children: formatWorktreeViewError(readError, t)
1597
+ }), readError.retryable && onRetry !== void 0 && (0, react_jsx_runtime.jsx)("button", {
1598
+ type: "button",
1599
+ className: worktree_css_default.retryButton,
1600
+ disabled: actionPending,
1601
+ onClick: onRetry,
1602
+ children: t("action.retry")
1603
+ })]
1604
+ }) : canCreate ? (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsxs)("label", {
1377
1605
  className: worktree_css_default.modalField,
1378
1606
  children: [t("worktree.baseBranch"), (0, react_jsx_runtime.jsx)("select", {
1379
1607
  className: worktree_css_default.actionSelect,
@@ -1416,7 +1644,7 @@ window.__ModuleLoader__.load({
1416
1644
  "aria-label": t("worktree.setup.commands"),
1417
1645
  children: setupCommands.join("\n")
1418
1646
  })]
1419
- })
1647
+ })]
1420
1648
  });
1421
1649
  }
1422
1650
  function WorktreeRemovalDialog({ t, worktree, actionPending, onClose, onSubmit }) {
@@ -1429,7 +1657,7 @@ window.__ModuleLoader__.load({
1429
1657
  },
1430
1658
  closeLabel: t("dialog.closeWorktreeRemove"),
1431
1659
  title: t("worktree.remove"),
1432
- description: t("worktree.removeDescription", { name: worktree.branch }),
1660
+ description: worktree.source === "external" ? t("worktree.removeExternalDescription", { name: worktree.branch }) : t("worktree.removeDescription", { name: worktree.branch }),
1433
1661
  footer: (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Button, {
1434
1662
  variant: "outline",
1435
1663
  disabled: actionPending,
@@ -1453,6 +1681,17 @@ window.__ModuleLoader__.load({
1453
1681
  function bindingIdsFor(bindings, worktreeId) {
1454
1682
  return bindings.filter((binding) => binding.worktreeId === worktreeId).map((binding) => binding.sessionId);
1455
1683
  }
1684
+ function clearSessionGroupExpansion(current, groupKeys) {
1685
+ const next = { ...current };
1686
+ for (const key of groupKeys) delete next[key];
1687
+ return next;
1688
+ }
1689
+ function isCompleteWorktreeWorkspaceSnapshot(workspaceIds, views) {
1690
+ if (views.length !== workspaceIds.length) return false;
1691
+ const expected = new Set(workspaceIds);
1692
+ const actual = new Set(views.map((view) => view.workspaceId));
1693
+ return actual.size === expected.size && [...expected].every((id) => actual.has(id));
1694
+ }
1456
1695
  function includesText(value, query) {
1457
1696
  return value.toLocaleLowerCase().includes(query);
1458
1697
  }
@@ -1464,6 +1703,46 @@ window.__ModuleLoader__.load({
1464
1703
  if (view.worktrees.some((record) => includesText(record.branch, query) || includesText(record.absolutePath, query))) return true;
1465
1704
  return view.bindings.some((binding) => sessionMatchesQuery(binding.sessionId, sessions, query));
1466
1705
  }
1706
+ function resolveCurrentSessionLocation(currentSessionId, workspaces, views) {
1707
+ if (currentSessionId === void 0) return void 0;
1708
+ const workspace = workspaces.find((candidate) => candidate.sessionIds.includes(currentSessionId));
1709
+ if (workspace === void 0) return void 0;
1710
+ const view = views.find((candidate) => candidate.workspaceId === workspace.workspaceId);
1711
+ if (view === void 0) return void 0;
1712
+ const binding = view.bindings.find((candidate) => candidate.sessionId === currentSessionId);
1713
+ if (binding === void 0) return {
1714
+ sessionId: currentSessionId,
1715
+ workspaceId: workspace.workspaceId,
1716
+ groupKey: "main:" + workspace.workspaceId,
1717
+ kind: "main"
1718
+ };
1719
+ const worktree = view.worktrees.find((candidate) => candidate.worktreeId === binding.worktreeId && candidate.workspaceId === workspace.workspaceId);
1720
+ if (worktree === void 0) return void 0;
1721
+ return {
1722
+ sessionId: currentSessionId,
1723
+ workspaceId: workspace.workspaceId,
1724
+ groupKey: "worktree:" + worktree.worktreeId,
1725
+ kind: "worktree",
1726
+ worktreeId: worktree.worktreeId
1727
+ };
1728
+ }
1729
+ function currentSessionRevealKeys(location) {
1730
+ if (location === void 0) return [];
1731
+ return [
1732
+ "workspace:" + location.workspaceId,
1733
+ location.kind === "main" ? "main:" + location.workspaceId : "worktree:" + location.worktreeId,
1734
+ "session-group:" + location.groupKey
1735
+ ];
1736
+ }
1737
+ //#endregion
1738
+ //#region lib/client/worktree-session-position.js
1739
+ function scrollCurrentSessionIntoView(root, sessionId) {
1740
+ if (root === null) return false;
1741
+ const row = Array.from(root.querySelectorAll("[data-session-id]")).find((candidate) => candidate.dataset.sessionId === sessionId);
1742
+ if (row === void 0) return false;
1743
+ row.scrollIntoView({ block: "nearest" });
1744
+ return true;
1745
+ }
1467
1746
  //#endregion
1468
1747
  //#region lib/client/worktree-surface-rows.js
1469
1748
  function rowHalf(event) {
@@ -1696,7 +1975,7 @@ window.__ModuleLoader__.load({
1696
1975
  });
1697
1976
  }
1698
1977
  /** Worktree-mode Session row with the same trailing options menu as native DSH rows. */
1699
- function WorktreeSessionRow({ t, sessionId, blank, label, drag, actionPending, onOpen, onRename, onFork, onArchive }) {
1978
+ function WorktreeSessionRow({ t, sessionId, blank, current, label, drag, actionPending, onOpen, onRename, onFork, onArchive }) {
1700
1979
  const [menuOpen, setMenuOpen] = (0, react.useState)(false);
1701
1980
  const markerClass = drag.marker === "before" ? worktree_css_default.dropBefore : drag.marker === "after" ? worktree_css_default.dropAfter : "";
1702
1981
  const sessionMenuItems = [
@@ -1723,9 +2002,11 @@ window.__ModuleLoader__.load({
1723
2002
  className: `${worktree_css_default.treeSessionRow} ${markerClass}`,
1724
2003
  "data-session-id": sessionId,
1725
2004
  "data-session-blank": blank ? "true" : void 0,
2005
+ "data-session-current": current ? "true" : void 0,
1726
2006
  "data-session-drag": drag.active ? "active" : void 0,
1727
2007
  "data-menu-open": menuOpen || void 0,
1728
2008
  role: "treeitem",
2009
+ "aria-current": current ? "true" : void 0,
1729
2010
  draggable: true,
1730
2011
  onDragStart: (event) => {
1731
2012
  event.dataTransfer.effectAllowed = "move";
@@ -1744,18 +2025,14 @@ window.__ModuleLoader__.load({
1744
2025
  event.preventDefault();
1745
2026
  drag.drop(rowHalf(event));
1746
2027
  },
1747
- children: [(0, react_jsx_runtime.jsxs)("button", {
2028
+ children: [(0, react_jsx_runtime.jsx)("button", {
1748
2029
  type: "button",
1749
2030
  className: worktree_css_default.treeSessionContent,
1750
2031
  onClick: onOpen,
1751
- children: [(0, react_jsx_runtime.jsx)("span", {
1752
- className: worktree_css_default.treeGuide,
1753
- "aria-hidden": "true",
1754
- children: "└"
1755
- }), (0, react_jsx_runtime.jsx)("span", {
2032
+ children: (0, react_jsx_runtime.jsx)("span", {
1756
2033
  className: worktree_css_default.sessionLabel,
1757
2034
  children: label
1758
- })]
2035
+ })
1759
2036
  }), !blank && (0, react_jsx_runtime.jsx)("span", {
1760
2037
  className: worktree_css_default.rowActions,
1761
2038
  children: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {
@@ -1787,13 +2064,14 @@ window.__ModuleLoader__.load({
1787
2064
  })]
1788
2065
  });
1789
2066
  }
1790
- function WorktreeSessionGroup({ t, groupKey, sessionIds, workspaceId, expanded, actionPending, sessions, dragState, onToggleExpanded, onStartDrag, onHoverDrag, onClearDrag, onFinishDrag, onCommitDrag, onOpen, onRename, onFork, onArchive }) {
2067
+ function WorktreeSessionGroup({ t, groupKey, sessionIds, workspaceId, currentSessionId, expanded, actionPending, sessions, dragState, onToggleExpanded, onStartDrag, onHoverDrag, onClearDrag, onFinishDrag, onCommitDrag, onOpen, onRename, onFork, onArchive }) {
1791
2068
  const visibleSessionIds = expanded ? sessionIds : sessionIds.slice(0, 5);
1792
2069
  const sameGroupDrag = dragState?.groupKey === groupKey;
1793
2070
  return (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [visibleSessionIds.map((sessionId) => (0, react_jsx_runtime.jsx)(WorktreeSessionRow, {
1794
2071
  t,
1795
2072
  sessionId,
1796
2073
  blank: isBlankSession(sessionId, sessions),
2074
+ current: sessionId === currentSessionId,
1797
2075
  label: sessionLabel(sessionId, sessions, t),
1798
2076
  drag: {
1799
2077
  active: sameGroupDrag,
@@ -1857,19 +2135,31 @@ window.__ModuleLoader__.load({
1857
2135
  * Peer Worktree navigation surface. It keeps the original DSH Workspace mode
1858
2136
  * intact and renders a browser-local Workspace → Worktree → Session projection.
1859
2137
  */
1860
- 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 }) {
2138
+ function WorktreeSurface({ useStore, actions, useSessions, useWorkspaces, t, available, expandState, manager, invalidateWorktreeContext, createWorkspace, createSessionForWorktree: createSessionCallback, createMainSession, renameWorkspace, deleteWorkspace, insertWorkspaceBefore, insertSessionBefore, insertWorktreeBefore, renameSession, forkSession, archiveSession, ensureSessionWorkspace, syncSessionWorkspaces, openSession }) {
1861
2139
  const mode = effectiveViewMode(useStore((state) => state.viewMode), available && manager !== void 0);
1862
2140
  const sessions = useSessions((state) => state);
1863
2141
  const workspaces = useWorkspaces((state) => state);
2142
+ const currentSessionId = sessions.current;
1864
2143
  const workspaceIds = useStableWorkspaceIds(workspaces.items);
1865
2144
  const [readState, setReadState] = (0, react.useState)(EMPTY_READ_STATE);
2145
+ const expandSnapshot = (0, react.useSyncExternalStore)(expandState.subscribe, expandState.getSnapshot, expandState.getSnapshot);
1866
2146
  const readStateRef = (0, react.useRef)(readState);
1867
2147
  readStateRef.current = readState;
1868
2148
  const [searchQuery, setSearchQuery] = (0, react.useState)("");
1869
- const [expandedWorkspaces, setExpandedWorkspaces] = (0, react.useState)({});
1870
- const [expandedMains, setExpandedMains] = (0, react.useState)({});
1871
- const [expandedWorktrees, setExpandedWorktrees] = (0, react.useState)({});
2149
+ const [currentSessionReveal, setCurrentSessionReveal] = (0, react.useState)();
2150
+ const searchQueryRef = (0, react.useRef)(searchQuery);
2151
+ searchQueryRef.current = searchQuery;
2152
+ const locateGenerationRef = (0, react.useRef)(0);
2153
+ const positionedLocateGenerationRef = (0, react.useRef)();
1872
2154
  const [worktreeModalWorkspaceId, setWorktreeModalWorkspaceId] = (0, react.useState)();
2155
+ const [modalReadError, setModalReadError] = (0, react.useState)();
2156
+ const [modalReadLoading, setModalReadLoading] = (0, react.useState)(false);
2157
+ const [worktreeModalMode, setWorktreeModalMode] = (0, react.useState)("create");
2158
+ const [importCandidates, setImportCandidates] = (0, react.useState)({
2159
+ status: "idle",
2160
+ candidates: []
2161
+ });
2162
+ const [selectedImportPath, setSelectedImportPath] = (0, react.useState)();
1873
2163
  const [openWorkspaceMenuId, setOpenWorkspaceMenuId] = (0, react.useState)();
1874
2164
  const [openWorktreeMenuId, setOpenWorktreeMenuId] = (0, react.useState)();
1875
2165
  const [worktreeRemoval, setWorktreeRemoval] = (0, react.useState)();
@@ -1897,6 +2187,11 @@ window.__ModuleLoader__.load({
1897
2187
  const [worktreeDrag, setWorktreeDrag] = (0, react.useState)();
1898
2188
  const worktreeDropCommitted = (0, react.useRef)(false);
1899
2189
  const refreshGuard = (0, react.useRef)(createWorktreeRefreshGuard());
2190
+ const modalReadLoader = (0, react.useRef)(createWorktreeModalViewLoader());
2191
+ const modalReadViewRef = (0, react.useRef)();
2192
+ const importCandidatesGuard = (0, react.useRef)(createWorktreeRefreshGuard());
2193
+ const modalWorkspaceIdRef = (0, react.useRef)(worktreeModalWorkspaceId);
2194
+ modalWorkspaceIdRef.current = worktreeModalWorkspaceId;
1900
2195
  const { ref, width, bounds } = useSidebarOverlayGeometry(mode === "worktree");
1901
2196
  const collapsed = width <= 64;
1902
2197
  const query = searchQuery.trim().toLocaleLowerCase();
@@ -1919,13 +2214,13 @@ window.__ModuleLoader__.load({
1919
2214
  }), (views) => {
1920
2215
  setReadState({
1921
2216
  status: "ready",
1922
- views
2217
+ views: modalReadViewRef.current === void 0 ? views : mergeWorktreeView(views, modalReadViewRef.current)
1923
2218
  });
1924
2219
  }, (error) => {
1925
2220
  if (preserveCurrent) throw error;
1926
2221
  setReadState({
1927
2222
  status: "error",
1928
- views: [],
2223
+ views: modalReadViewRef.current === void 0 ? [] : [modalReadViewRef.current],
1929
2224
  error: toWorktreeViewError(error)
1930
2225
  });
1931
2226
  });
@@ -1934,10 +2229,39 @@ window.__ModuleLoader__.load({
1934
2229
  manager,
1935
2230
  workspaceIds
1936
2231
  ]);
2232
+ const loadModalWorktreeView = (0, react.useCallback)((workspaceId) => {
2233
+ setModalReadError(void 0);
2234
+ setModalReadLoading(true);
2235
+ if (manager === void 0) {
2236
+ setModalReadLoading(false);
2237
+ setModalReadError({
2238
+ code: "WORKTREE_VIEW_UNAVAILABLE",
2239
+ message: "",
2240
+ retryable: true
2241
+ });
2242
+ return;
2243
+ }
2244
+ modalReadLoader.current.load(manager, workspaceId, (view) => {
2245
+ modalReadViewRef.current = view;
2246
+ setModalReadLoading(false);
2247
+ setReadState((current) => ({
2248
+ ...current,
2249
+ views: mergeWorktreeView(current.views, view)
2250
+ }));
2251
+ }, (error) => {
2252
+ setModalReadLoading(false);
2253
+ setModalReadError(toWorktreeViewError(error));
2254
+ });
2255
+ }, [manager]);
1937
2256
  (0, react.useEffect)(() => {
1938
2257
  if (mode === "worktree") refresh({ preserveCurrent: readStateRef.current.status === "ready" });
1939
2258
  else {
1940
2259
  refreshGuard.current.invalidate();
2260
+ modalReadLoader.current.invalidate();
2261
+ modalReadViewRef.current = void 0;
2262
+ setWorktreeModalWorkspaceId(void 0);
2263
+ setModalReadError(void 0);
2264
+ setModalReadLoading(false);
1941
2265
  setReadState(EMPTY_READ_STATE);
1942
2266
  }
1943
2267
  }, [mode, refresh]);
@@ -1953,18 +2277,76 @@ window.__ModuleLoader__.load({
1953
2277
  syncSessionWorkspaces
1954
2278
  ]);
1955
2279
  const viewByWorkspace = (0, react.useMemo)(() => new Map(readState.views.map((view) => [view.workspaceId, view])), [readState.views]);
2280
+ const currentSessionLocation = (0, react.useMemo)(() => readState.status === "ready" ? resolveCurrentSessionLocation(currentSessionId, workspaces.items, readState.views) : void 0, [
2281
+ currentSessionId,
2282
+ readState.status,
2283
+ readState.views,
2284
+ workspaces.items
2285
+ ]);
2286
+ const currentRevealKeys = (0, react.useMemo)(() => new Set(currentSessionRevealKeys(currentSessionLocation)), [currentSessionLocation]);
2287
+ const isCurrentSessionReveal = (key) => currentSessionReveal !== void 0 && currentSessionReveal.sessionId === currentSessionId && currentRevealKeys.has(key) && currentSessionReveal.suppressedKeys[key] !== true;
2288
+ (0, react.useLayoutEffect)(() => {
2289
+ locateGenerationRef.current += 1;
2290
+ positionedLocateGenerationRef.current = void 0;
2291
+ if (mode !== "worktree") {
2292
+ setCurrentSessionReveal(void 0);
2293
+ return;
2294
+ }
2295
+ if (searchQueryRef.current.trim().length > 0) setSearchQuery("");
2296
+ setCurrentSessionReveal(currentSessionId === void 0 ? void 0 : {
2297
+ sessionId: currentSessionId,
2298
+ suppressedKeys: {}
2299
+ });
2300
+ }, [currentSessionId, mode]);
2301
+ (0, react.useLayoutEffect)(() => {
2302
+ if (mode !== "worktree" || currentSessionId === void 0 || currentSessionLocation === void 0) return;
2303
+ const generation = locateGenerationRef.current;
2304
+ if (positionedLocateGenerationRef.current === generation) return;
2305
+ let cancelled = false;
2306
+ const frame = requestAnimationFrame(() => {
2307
+ if (cancelled || generation !== locateGenerationRef.current) return;
2308
+ if (!scrollCurrentSessionIntoView(ref.current, currentSessionId)) return;
2309
+ positionedLocateGenerationRef.current = generation;
2310
+ });
2311
+ return () => {
2312
+ cancelled = true;
2313
+ cancelAnimationFrame(frame);
2314
+ };
2315
+ }, [
2316
+ currentSessionId,
2317
+ currentSessionLocation,
2318
+ currentSessionReveal,
2319
+ expandSnapshot,
2320
+ mode,
2321
+ query,
2322
+ readState.status
2323
+ ]);
2324
+ (0, react.useEffect)(() => {
2325
+ if (readState.status !== "ready" || !isCompleteWorktreeWorkspaceSnapshot(workspaceIds, readState.views)) return;
2326
+ expandState.actions.retain(workspaceIds, readState.views.flatMap((view) => view.worktrees.map((record) => record.worktreeId)));
2327
+ }, [
2328
+ expandState,
2329
+ readState.status,
2330
+ readState.views,
2331
+ workspaceIds
2332
+ ]);
1956
2333
  const modalWorkspace = workspaces.items.find((workspace) => workspace.workspaceId === worktreeModalWorkspaceId);
1957
2334
  const modalView = worktreeModalWorkspaceId === void 0 ? void 0 : viewByWorkspace.get(worktreeModalWorkspaceId);
1958
2335
  const modalReadiness = modalView?.readiness;
1959
2336
  const modalSetupStatus = modalView === void 0 ? void 0 : modalReadiness?.status === "ready" ? modalView.branches.length === 0 ? "noLocalBranch" : void 0 : modalReadiness?.status;
1960
- const modalCanCreate = modalSetupStatus === void 0 && modalReadiness?.status === "ready";
2337
+ const modalCanCreate = !modalReadLoading && modalSetupStatus === void 0 && modalReadiness?.status === "ready";
1961
2338
  (0, react.useEffect)(() => {
1962
2339
  if (worktreeModalWorkspaceId === void 0 || modalView === void 0) return;
1963
2340
  if (modalView.readiness.status !== "ready") {
1964
2341
  setSelectedBranch("");
2342
+ setNewBranch("");
1965
2343
  return;
1966
2344
  }
1967
2345
  setSelectedBranch((current) => reconcileBaseBranchSelection(current, modalView.branches));
2346
+ setNewBranch((current) => {
2347
+ if (current.length > 0) return current;
2348
+ return createDefaultWorktreeName([...modalView.branches.map((branch) => branch.name), ...modalView.worktrees.map((worktree) => worktree.branch)]);
2349
+ });
1968
2350
  }, [modalView, worktreeModalWorkspaceId]);
1969
2351
  const runMutation = async (operation) => {
1970
2352
  setActionPending(true);
@@ -1978,6 +2360,27 @@ window.__ModuleLoader__.load({
1978
2360
  setActionPending(false);
1979
2361
  }
1980
2362
  };
2363
+ const loadImportCandidates = (0, react.useCallback)(async (workspaceId) => {
2364
+ if (manager === void 0) return;
2365
+ setImportCandidates((current) => ({
2366
+ status: "loading",
2367
+ candidates: current.candidates
2368
+ }));
2369
+ await importCandidatesGuard.current.run(() => manager.listImportCandidates({ workspaceId }), (candidates) => {
2370
+ if (modalWorkspaceIdRef.current !== workspaceId) return;
2371
+ setImportCandidates({
2372
+ status: "ready",
2373
+ candidates
2374
+ });
2375
+ }, (error) => {
2376
+ if (modalWorkspaceIdRef.current !== workspaceId) return;
2377
+ setImportCandidates((current) => ({
2378
+ status: "error",
2379
+ candidates: current.candidates,
2380
+ error: toWorktreeViewError(error)
2381
+ }));
2382
+ });
2383
+ }, [manager]);
1981
2384
  const workspaceRenameTrimmed = workspaceRenameDraft.trim();
1982
2385
  const workspaceRenameDuplicate = workspaceRenameTarget !== void 0 && workspaceRenameTrimmed.length > 0 && workspaces.items.some((workspace) => workspace.workspaceId !== workspaceRenameTarget.workspaceId && workspace.title === workspaceRenameTrimmed);
1983
2386
  const workspaceRenameBlocked = workspaceRenamePending || workspaceRenameTarget === void 0 || workspaceRenameTrimmed.length === 0 || workspaceRenameTrimmed === workspaceRenameTarget?.currentTitle || workspaceRenameDuplicate;
@@ -2160,80 +2563,172 @@ window.__ModuleLoader__.load({
2160
2563
  if (archiveSession === void 0) return;
2161
2564
  await runMutation(() => archiveSession(sessionId));
2162
2565
  };
2566
+ const clearSessionGroups = (groupKeys) => {
2567
+ if (groupKeys.length === 0) return;
2568
+ setExpandedSessionGroups((current) => clearSessionGroupExpansion(current, groupKeys));
2569
+ };
2570
+ const suppressCurrentSessionReveal = (key) => {
2571
+ if (!isCurrentSessionReveal(key)) return false;
2572
+ setCurrentSessionReveal((current) => {
2573
+ if (current === void 0 || current.sessionId !== currentSessionId) return current;
2574
+ return {
2575
+ ...current,
2576
+ suppressedKeys: {
2577
+ ...current.suppressedKeys,
2578
+ [key]: true
2579
+ }
2580
+ };
2581
+ });
2582
+ return true;
2583
+ };
2163
2584
  const toggleWorkspace = (workspaceId) => {
2164
- setExpandedWorkspaces((current) => ({
2165
- ...current,
2166
- [workspaceId]: current[workspaceId] === false
2167
- }));
2585
+ const persistedExpanded = isWorkspaceExpanded(expandSnapshot, workspaceId);
2586
+ const autoExpanded = isCurrentSessionReveal("workspace:" + workspaceId);
2587
+ const visuallyExpanded = persistedExpanded || autoExpanded;
2588
+ if (visuallyExpanded && autoExpanded) suppressCurrentSessionReveal("workspace:" + workspaceId);
2589
+ if (visuallyExpanded && !persistedExpanded) {
2590
+ clearSessionGroups(["main:" + workspaceId, ...(viewByWorkspace.get(workspaceId)?.worktrees.map((record) => record.worktreeId) ?? []).map((worktreeId) => "worktree:" + worktreeId)]);
2591
+ return;
2592
+ }
2593
+ expandState.actions.toggleWorkspace(workspaceId);
2594
+ if (visuallyExpanded) clearSessionGroups(["main:" + workspaceId, ...(viewByWorkspace.get(workspaceId)?.worktrees.map((record) => record.worktreeId) ?? []).map((worktreeId) => "worktree:" + worktreeId)]);
2168
2595
  };
2169
2596
  const toggleMain = (workspaceId) => {
2170
- setExpandedMains((current) => ({
2171
- ...current,
2172
- [workspaceId]: current[workspaceId] === false
2173
- }));
2597
+ const persistedExpanded = isMainExpanded(expandSnapshot, workspaceId);
2598
+ const autoExpanded = isCurrentSessionReveal("main:" + workspaceId);
2599
+ const visuallyExpanded = persistedExpanded || autoExpanded;
2600
+ if (visuallyExpanded && autoExpanded) suppressCurrentSessionReveal("main:" + workspaceId);
2601
+ if (visuallyExpanded && !persistedExpanded) {
2602
+ clearSessionGroups(["main:" + workspaceId]);
2603
+ return;
2604
+ }
2605
+ expandState.actions.toggleMain(workspaceId);
2606
+ if (visuallyExpanded) clearSessionGroups(["main:" + workspaceId]);
2174
2607
  };
2175
2608
  const toggleWorktree = (worktreeId) => {
2176
- setExpandedWorktrees((current) => ({
2609
+ const persistedExpanded = isWorktreeExpanded(expandSnapshot, worktreeId);
2610
+ const autoExpanded = isCurrentSessionReveal("worktree:" + worktreeId);
2611
+ const visuallyExpanded = persistedExpanded || autoExpanded;
2612
+ if (visuallyExpanded && autoExpanded) suppressCurrentSessionReveal("worktree:" + worktreeId);
2613
+ if (visuallyExpanded && !persistedExpanded) {
2614
+ clearSessionGroups(["worktree:" + worktreeId]);
2615
+ return;
2616
+ }
2617
+ expandState.actions.toggleWorktree(worktreeId);
2618
+ if (visuallyExpanded) clearSessionGroups(["worktree:" + worktreeId]);
2619
+ };
2620
+ const toggleSessionGroup = (groupKey) => {
2621
+ const autoExpanded = isCurrentSessionReveal("session-group:" + groupKey);
2622
+ const transientExpanded = expandedSessionGroups[groupKey] === true;
2623
+ if (autoExpanded) {
2624
+ suppressCurrentSessionReveal("session-group:" + groupKey);
2625
+ setExpandedSessionGroups((current) => {
2626
+ const next = { ...current };
2627
+ delete next[groupKey];
2628
+ return next;
2629
+ });
2630
+ return;
2631
+ }
2632
+ setExpandedSessionGroups((current) => ({
2177
2633
  ...current,
2178
- [worktreeId]: current[worktreeId] === false
2634
+ [groupKey]: !transientExpanded
2179
2635
  }));
2180
2636
  };
2637
+ const closeWorktreeCreator = (force = false) => {
2638
+ if (actionPending && !force) return;
2639
+ modalReadLoader.current.invalidate();
2640
+ modalReadViewRef.current = void 0;
2641
+ importCandidatesGuard.current.invalidate();
2642
+ setWorktreeModalWorkspaceId(void 0);
2643
+ setModalReadError(void 0);
2644
+ setModalReadLoading(false);
2645
+ };
2181
2646
  const openWorktreeCreator = (workspace) => {
2182
2647
  const view = viewByWorkspace.get(workspace.workspaceId);
2183
- const baseBranch = selectDefaultBaseBranch(view?.branches ?? []);
2184
- const existingNames = [...(view?.branches ?? []).map((branch) => branch.name), ...(view?.worktrees ?? []).map((worktree) => worktree.branch)];
2648
+ modalReadLoader.current.invalidate();
2649
+ modalReadViewRef.current = void 0;
2650
+ importCandidatesGuard.current.invalidate();
2185
2651
  setWorktreeModalWorkspaceId(workspace.workspaceId);
2186
- setSelectedBranch(baseBranch);
2187
- setNewBranch(createDefaultWorktreeName(existingNames));
2652
+ setWorktreeModalMode("create");
2653
+ setImportCandidates({
2654
+ status: "idle",
2655
+ candidates: []
2656
+ });
2657
+ setSelectedImportPath(void 0);
2188
2658
  setActionError(void 0);
2659
+ setModalReadError(void 0);
2660
+ setModalReadLoading(false);
2661
+ if (view === void 0) {
2662
+ setSelectedBranch("");
2663
+ setNewBranch("");
2664
+ loadModalWorktreeView(workspace.workspaceId);
2665
+ return;
2666
+ }
2667
+ setSelectedBranch(selectDefaultBaseBranch(view.branches));
2668
+ setNewBranch(createDefaultWorktreeName([...view.branches.map((branch) => branch.name), ...view.worktrees.map((worktree) => worktree.branch)]));
2669
+ };
2670
+ const changeWorktreeModalMode = (mode) => {
2671
+ setWorktreeModalMode(mode);
2672
+ if (mode === "import" && worktreeModalWorkspaceId !== void 0 && importCandidates.status === "idle") loadImportCandidates(worktreeModalWorkspaceId);
2673
+ };
2674
+ const continueWorktreeRegistration = async (registeredWorktree) => {
2675
+ closeWorktreeCreator(true);
2676
+ if (createSessionCallback === void 0) {
2677
+ await refresh({ preserveCurrent: true });
2678
+ setActionError({
2679
+ code: "WORKTREE_REGISTRATION_SESSION_UNAVAILABLE",
2680
+ message: "",
2681
+ retryable: true
2682
+ });
2683
+ return;
2684
+ }
2685
+ const sessionInput = {
2686
+ workspaceId: registeredWorktree.workspaceId,
2687
+ worktreeId: registeredWorktree.worktreeId,
2688
+ cwd: registeredWorktree.absolutePath
2689
+ };
2690
+ try {
2691
+ await createSessionCallback(sessionInput);
2692
+ await invalidateWorktreeContext?.(registeredWorktree.workspaceId);
2693
+ } catch (error) {
2694
+ if (error instanceof WorktreeSessionBindingError && error.retryable) setPendingSessionBinding({
2695
+ ...sessionInput,
2696
+ sessionId: error.sessionId
2697
+ });
2698
+ throw error;
2699
+ }
2700
+ await refresh({ preserveCurrent: true });
2189
2701
  };
2190
2702
  const submitWorktree = async () => {
2191
2703
  const worktreeName = newBranch.trim();
2192
- if (manager === void 0 || modalWorkspace === void 0 || !modalCanCreate || selectedBranch.length === 0 || worktreeName.length === 0) return;
2193
- const input = {
2194
- workspaceId: modalWorkspace.workspaceId,
2195
- branch: selectedBranch,
2196
- newBranch: worktreeName
2197
- };
2704
+ const selectedImportCandidate = importCandidates.candidates.find((candidate) => candidate.absolutePath === selectedImportPath);
2705
+ if (manager === void 0 || modalWorkspace === void 0) return;
2706
+ if (worktreeModalMode === "create" && (!modalCanCreate || selectedBranch.length === 0 || worktreeName.length === 0)) return;
2707
+ if (worktreeModalMode === "import" && selectedImportCandidate === void 0) return;
2198
2708
  setActionPending(true);
2199
2709
  setActionError(void 0);
2200
2710
  setPendingSessionBinding(void 0);
2201
2711
  try {
2202
- const createdWorktree = await executeWorktreeAction(manager, {
2712
+ const registeredWorktree = worktreeModalMode === "create" ? await executeWorktreeAction(manager, {
2203
2713
  type: "createWorktree",
2204
- input
2714
+ input: {
2715
+ workspaceId: modalWorkspace.workspaceId,
2716
+ branch: selectedBranch,
2717
+ newBranch: worktreeName
2718
+ }
2719
+ }) : await executeWorktreeAction(manager, {
2720
+ type: "importWorktree",
2721
+ input: {
2722
+ workspaceId: modalWorkspace.workspaceId,
2723
+ absolutePath: selectedImportCandidate.absolutePath
2724
+ }
2205
2725
  });
2206
- if (createdWorktree === void 0) throw {
2726
+ if (registeredWorktree === void 0) throw {
2207
2727
  code: "WORKTREE_RECORD_MISSING",
2208
2728
  message: "",
2209
2729
  retryable: true
2210
2730
  };
2211
- setWorktreeModalWorkspaceId(void 0);
2212
- if (createSessionCallback === void 0) {
2213
- await refresh({ preserveCurrent: true });
2214
- setActionError({
2215
- code: "WORKTREE_CREATED_SESSION_UNAVAILABLE",
2216
- message: "",
2217
- retryable: true
2218
- });
2219
- return;
2220
- }
2221
- const sessionInput = {
2222
- workspaceId: createdWorktree.workspaceId,
2223
- worktreeId: createdWorktree.worktreeId,
2224
- cwd: createdWorktree.absolutePath
2225
- };
2226
- try {
2227
- await createSessionCallback(sessionInput);
2228
- await invalidateWorktreeContext?.(createdWorktree.workspaceId);
2229
- } catch (error) {
2230
- if (error instanceof WorktreeSessionBindingError && error.retryable) setPendingSessionBinding({
2231
- ...sessionInput,
2232
- sessionId: error.sessionId
2233
- });
2234
- throw error;
2235
- }
2236
- await refresh({ preserveCurrent: true });
2731
+ await continueWorktreeRegistration(registeredWorktree);
2237
2732
  } catch (error) {
2238
2733
  setActionError(toWorktreeViewError(error));
2239
2734
  } finally {
@@ -2437,13 +2932,15 @@ window.__ModuleLoader__.load({
2437
2932
  const view = viewByWorkspace.get(workspace.workspaceId);
2438
2933
  const currentBranch = view?.branches.find((branch) => branch.isCurrent)?.name;
2439
2934
  const mainLabel = currentBranch === void 0 ? t("worktree.main") : t("worktree.mainWithBranch", { branch: currentBranch });
2440
- const expanded = expandedWorkspaces[workspace.workspaceId] !== false;
2935
+ const expanded = isWorkspaceExpanded(expandSnapshot, workspace.workspaceId) || isCurrentSessionReveal("workspace:" + workspace.workspaceId);
2441
2936
  const workspaceMatchesQuery = includesText(workspace.title, query);
2442
2937
  const allWorkspaceSessionIds = filterArchivedSessionIds(workspaceSessionIds(workspaces, workspace.workspaceId, sessions.ids), archivedSessionIds);
2443
2938
  const bindings = view?.bindings ?? [];
2444
2939
  const visibleMainSessionIds = filterVisibleSessionIds(unboundSessionIds(allWorkspaceSessionIds, [...new Set(bindings.map((binding) => binding.sessionId))]), sessions).filter((sessionId) => workspaceMatchesQuery || sessionMatchesQuery(sessionId, sessions, query));
2445
- const mainExpanded = expandedMains[workspace.workspaceId] !== false;
2940
+ const mainExpanded = isMainExpanded(expandSnapshot, workspace.workspaceId) || isCurrentSessionReveal("main:" + workspace.workspaceId);
2446
2941
  const mainGroupKey = `main:${workspace.workspaceId}`;
2942
+ const sessionIds = visibleMainSessionIds;
2943
+ const mainSessionGroupExpanded = expandedSessionGroups[mainGroupKey] === true || sessionIds.length > 5 && isCurrentSessionReveal("session-group:" + mainGroupKey);
2447
2944
  const worktrees = view?.worktrees ?? [];
2448
2945
  const sameWorkspaceWorktreeDrag = worktreeDrag?.workspaceId === workspace.workspaceId;
2449
2946
  return (0, react_jsx_runtime.jsxs)("section", {
@@ -2522,17 +3019,15 @@ window.__ModuleLoader__.load({
2522
3019
  mainExpanded && (0, react_jsx_runtime.jsx)(WorktreeSessionGroup, {
2523
3020
  t,
2524
3021
  groupKey: mainGroupKey,
2525
- sessionIds: visibleMainSessionIds,
3022
+ sessionIds,
2526
3023
  workspaceId: workspace.workspaceId,
2527
- expanded: expandedSessionGroups[mainGroupKey] === true,
3024
+ currentSessionId,
3025
+ expanded: mainSessionGroupExpanded,
2528
3026
  actionPending,
2529
3027
  sessions,
2530
3028
  dragState: sessionDrag,
2531
3029
  onToggleExpanded: () => {
2532
- setExpandedSessionGroups((current) => ({
2533
- ...current,
2534
- [mainGroupKey]: current[mainGroupKey] !== true
2535
- }));
3030
+ toggleSessionGroup(mainGroupKey);
2536
3031
  },
2537
3032
  onStartDrag: (groupKey, sessionId) => {
2538
3033
  sessionDropCommitted.current = false;
@@ -2575,9 +3070,11 @@ window.__ModuleLoader__.load({
2575
3070
  if (query.length > 0 && !worktreeMatchesQuery && !worktreeSessionIds.some((sessionId) => sessionMatchesQuery(sessionId, sessions, query))) return null;
2576
3071
  const visibleWorktreeSessionIds = worktreeSessionIds.filter((sessionId) => worktreeMatchesQuery || sessionMatchesQuery(sessionId, sessions, query));
2577
3072
  const worktreeGroupKey = `worktree:${record.worktreeId}`;
3073
+ const sessionIds = visibleWorktreeSessionIds;
3074
+ const sessionGroupExpanded = expandedSessionGroups[worktreeGroupKey] === true || sessionIds.length > 5 && isCurrentSessionReveal("session-group:" + worktreeGroupKey);
2578
3075
  const state = record.status === "removed" ? "warning" : record.health === "repair" ? "error" : "done";
2579
3076
  const stateLabel = record.status === "removed" ? t("worktree.detached") : record.health === "repair" ? t("worktree.repair") : t("worktree.ready");
2580
- const worktreeExpanded = expandedWorktrees[record.worktreeId] !== false;
3077
+ const worktreeExpanded = isWorktreeExpanded(expandSnapshot, record.worktreeId) || isCurrentSessionReveal("worktree:" + record.worktreeId);
2581
3078
  return (0, react_jsx_runtime.jsxs)("div", {
2582
3079
  className: worktree_css_default.worktreeGroup,
2583
3080
  "data-worktree-id": record.worktreeId,
@@ -2648,17 +3145,15 @@ window.__ModuleLoader__.load({
2648
3145
  }), worktreeExpanded && (0, react_jsx_runtime.jsx)(WorktreeSessionGroup, {
2649
3146
  t,
2650
3147
  groupKey: worktreeGroupKey,
2651
- sessionIds: visibleWorktreeSessionIds,
3148
+ sessionIds,
2652
3149
  workspaceId: workspace.workspaceId,
2653
- expanded: expandedSessionGroups[worktreeGroupKey] === true,
3150
+ currentSessionId,
3151
+ expanded: sessionGroupExpanded,
2654
3152
  actionPending,
2655
3153
  sessions,
2656
3154
  dragState: sessionDrag,
2657
3155
  onToggleExpanded: () => {
2658
- setExpandedSessionGroups((current) => ({
2659
- ...current,
2660
- [worktreeGroupKey]: current[worktreeGroupKey] !== true
2661
- }));
3156
+ toggleSessionGroup(worktreeGroupKey);
2662
3157
  },
2663
3158
  onStartDrag: (groupKey, sessionId) => {
2664
3159
  sessionDropCommitted.current = false;
@@ -2741,14 +3236,28 @@ window.__ModuleLoader__.load({
2741
3236
  t,
2742
3237
  workspace: modalWorkspace,
2743
3238
  view: modalView,
3239
+ readError: modalReadError,
2744
3240
  setupStatus: modalSetupStatus,
2745
3241
  canCreate: modalCanCreate,
3242
+ mode: worktreeModalMode,
3243
+ importCandidates,
3244
+ selectedImportPath,
2746
3245
  selectedBranch,
2747
3246
  newBranch,
2748
3247
  actionPending,
2749
- onClose: () => {
2750
- setWorktreeModalWorkspaceId(void 0);
3248
+ onClose: closeWorktreeCreator,
3249
+ onRetry: () => {
3250
+ if (worktreeModalWorkspaceId === void 0) return;
3251
+ modalReadViewRef.current = void 0;
3252
+ setSelectedBranch("");
3253
+ setNewBranch("");
3254
+ loadModalWorktreeView(worktreeModalWorkspaceId);
3255
+ },
3256
+ onModeChange: changeWorktreeModalMode,
3257
+ onRetryImportCandidates: () => {
3258
+ if (worktreeModalWorkspaceId !== void 0) loadImportCandidates(worktreeModalWorkspaceId);
2751
3259
  },
3260
+ onSelectedImportPathChange: setSelectedImportPath,
2752
3261
  onSelectedBranchChange: setSelectedBranch,
2753
3262
  onNewBranchChange: setNewBranch,
2754
3263
  onSubmit: submitWorktree
@@ -3172,6 +3681,7 @@ window.__ModuleLoader__.load({
3172
3681
  ctx.effect(() => () => contextProjection.dispose(), "clutch-dsh-worktree: Session context cleanup");
3173
3682
  contextProjection.refresh();
3174
3683
  const viewStore = createWorktreeViewStore();
3684
+ const expandState = createWorktreeExpandStateStore(_deepseek_ai_dsh_client_runtime_client.createSnapshotStore);
3175
3685
  const ensureSessionWorkspace = (workspaceId, sessionId) => {
3176
3686
  virtualWorkspaceMembership.ensure({
3177
3687
  workspaceId,
@@ -3213,6 +3723,7 @@ window.__ModuleLoader__.load({
3213
3723
  locale: WORKTREE_NS,
3214
3724
  inject: () => ({
3215
3725
  available: true,
3726
+ expandState,
3216
3727
  hooks: { worktreeContext: contextProjection.store },
3217
3728
  manager,
3218
3729
  createWorkspace: async () => {