dsh-git-worktree 0.9.3 → 0.11.0

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 (65) hide show
  1. package/CHANGELOG.md +54 -1
  2. package/README.en.md +7 -4
  3. package/README.md +7 -4
  4. package/lib/adapters/project-skill-provider.js +14 -4
  5. package/lib/adapters/project-skill-provider.js.map +1 -1
  6. package/lib/adapters/registry.js +4 -32
  7. package/lib/adapters/registry.js.map +1 -1
  8. package/lib/client/actions.d.ts +3 -3
  9. package/lib/client/actions.js.map +1 -1
  10. package/lib/client/console-remote/adapter.js +1 -1
  11. package/lib/client/console-remote/adapter.js.map +1 -1
  12. package/lib/client/console-remote/index.d.ts +10 -3
  13. package/lib/client/console-remote/index.js +20 -5
  14. package/lib/client/console-remote/index.js.map +1 -1
  15. package/lib/client/pre-session/controller.js +5 -0
  16. package/lib/client/pre-session/controller.js.map +1 -1
  17. package/lib/client/review-console/PreflightStatus.js +5 -2
  18. package/lib/client/review-console/PreflightStatus.js.map +1 -1
  19. package/lib/client/review-console/ReviewActions.js +47 -46
  20. package/lib/client/review-console/ReviewActions.js.map +1 -1
  21. package/lib/client/review-console/ReviewDetailsModal.js +13 -3
  22. package/lib/client/review-console/ReviewDetailsModal.js.map +1 -1
  23. package/lib/client/review-console/review-console.styles.js +22 -11
  24. package/lib/client/review-console/review-console.styles.js.map +1 -1
  25. package/lib/client/target-console/WorktreeReviewStatus.js +7 -7
  26. package/lib/client/target-console/WorktreeReviewStatus.js.map +1 -1
  27. package/lib/client/workspace-sidebar/index.js +46 -5
  28. package/lib/client/workspace-sidebar/index.js.map +1 -1
  29. package/lib/client.js +5200 -2513
  30. package/lib/commit-message.d.ts +2 -0
  31. package/lib/commit-message.js +5 -0
  32. package/lib/commit-message.js.map +1 -0
  33. package/lib/console-contract.d.ts +1 -1
  34. package/lib/console-host/control-plane.js +6 -5
  35. package/lib/console-host/control-plane.js.map +1 -1
  36. package/lib/console-remote/descriptors.js +5 -3
  37. package/lib/console-remote/descriptors.js.map +1 -1
  38. package/lib/console-remote/schemas.d.ts +1 -1
  39. package/lib/console-remote/schemas.js +3 -2
  40. package/lib/console-remote/schemas.js.map +1 -1
  41. package/lib/host-compat.d.ts +1 -1
  42. package/lib/host-compat.js +3 -0
  43. package/lib/host-compat.js.map +1 -1
  44. package/lib/i18n/client-messages.d.ts +8 -4
  45. package/lib/i18n/client-messages.js +2 -4
  46. package/lib/i18n/client-messages.js.map +1 -1
  47. package/lib/i18n/host-messages.d.ts +3 -7
  48. package/lib/i18n/host-messages.js +3 -7
  49. package/lib/i18n/host-messages.js.map +1 -1
  50. package/lib/index.d.ts +13 -10
  51. package/lib/index.js +9 -2
  52. package/lib/index.js.map +1 -1
  53. package/lib/ports.d.ts +1 -1
  54. package/lib/session-checkout-apply.js +6 -5
  55. package/lib/session-checkout-apply.js.map +1 -1
  56. package/lib/session-checkout-module.js +10 -7
  57. package/lib/session-checkout-module.js.map +1 -1
  58. package/lib/workspace-provider-lifecycle.d.ts +15 -1
  59. package/lib/workspace-provider-lifecycle.js +94 -10
  60. package/lib/workspace-provider-lifecycle.js.map +1 -1
  61. package/package.json +45 -41
  62. package/scripts/check-publish.mjs +4 -1
  63. package/scripts/workspace-sidebar-upstream-alpha.mjs +16 -14
  64. package/scripts/workspace-sidebar-upstream-next.mjs +12 -16
  65. package/scripts/workspace-sidebar-upstream.mjs +64 -30
@@ -2,9 +2,9 @@ import { createHash } from 'node:crypto'
2
2
  import { readFileSync } from 'node:fs'
3
3
  import { createRequire } from 'node:module'
4
4
 
5
- export const WORKSPACE_UI_VERSION = '0.1.2-rc.1'
6
- export const WORKSPACE_LOCALE_VERSION = '0.1.2-rc.1'
7
- export const WORKSPACE_CLIENT_SHA256 = '53c40660195c42cde709b802e239f473dd721f45bc329684af31c01fdb73282a'
5
+ export const WORKSPACE_UI_VERSION = '0.2.1-rc.2'
6
+ export const WORKSPACE_LOCALE_VERSION = '0.2.1-rc.2'
7
+ export const WORKSPACE_CLIENT_SHA256 = '52765aacb6c7f96327da5d8709d8cbb30dd2957d4744a42da04c18e07fe264e5'
8
8
  export const OFFICIAL_WORKSPACE_VIRTUAL_ID = 'virtual:dsh-official-workspace-client'
9
9
  export const RESOLVED_OFFICIAL_WORKSPACE_VIRTUAL_ID = `\0${OFFICIAL_WORKSPACE_VIRTUAL_ID}`
10
10
 
@@ -33,6 +33,14 @@ function replaceExactlyOnce(source, needle, replacement, label) {
33
33
  return source.slice(0, first) + replacement + source.slice(first + needle.length)
34
34
  }
35
35
 
36
+ // DSH 0.2 removed the legacy search/menu seams; those optional decorations are
37
+ // handled by the modern Workspace row/slot path below when the seam exists.
38
+ function replaceIfPresent(source, needle, replacement, label) {
39
+ const hit = source.includes(needle)
40
+ if (process.env.WT_DEBUG_SEAMS) console.log(`[seam] ${hit ? 'HIT ' : 'SKIP '} (optional) ${label}`)
41
+ return hit ? replaceExactlyOnce(source, needle, replacement, label) : source
42
+ }
43
+
36
44
  /**
37
45
  * Add one package-owned row decoration to the already version/hash-gated
38
46
  * official Browser. Every replacement is exact and therefore fails closed if
@@ -40,6 +48,20 @@ function replaceExactlyOnce(source, needle, replacement, label) {
40
48
  */
41
49
  export function decorateOfficialWorkspaceClient(source) {
42
50
  let derived = source
51
+ // Service derives its own Cordis Context, so retain the proxy's per-instance
52
+ // guard at construction. Menus and shortcuts share these service boundaries.
53
+ derived = replaceExactlyOnce(derived,
54
+ '\t\t\t\tsuper(ctx, "uiWorkspace");\n\t\t\t\tthis.directoryPicker = directoryPicker;',
55
+ '\t\t\t\tsuper(ctx, "uiWorkspace");\n\t\t\t\tthis.managedWorktreeGuard = ctx.get("__dshGitWorktreeManagedGuard");\n\t\t\t\tthis.directoryPicker = directoryPicker;',
56
+ 'instance-local managed guard')
57
+ derived = replaceExactlyOnce(derived,
58
+ '\t\t\tasync forkSession(sessionId, onCreated, options) {\n\t\t\t\treturn this.sessions.fork({',
59
+ '\t\t\tasync forkSession(sessionId, onCreated, options) {\n\t\t\t\tif (this.managedWorktreeGuard.blockSession(sessionId)) throw new Error("managed Session must be changed through its Worktree owner");\n\t\t\t\treturn this.sessions.fork({',
60
+ 'Managed Session fork from menus and shortcuts')
61
+ derived = replaceExactlyOnce(derived,
62
+ '\t\t\t\tconst target = workspaceId ?? currentWorkspaceId ?? recent;\n\t\t\t\tif (target === void 0) {',
63
+ '\t\t\t\tconst target = workspaceId ?? currentWorkspaceId ?? recent;\n\t\t\t\tif (target !== void 0 && this.managedWorktreeGuard.blockWorkspace(target)) return;\n\t\t\t\tif (target === void 0) {',
64
+ 'Managed Workspace new Session shortcut')
43
65
  derived = replaceExactlyOnce(derived,
44
66
  '\t\tconst zh = {',
45
67
  `\t\tconst zh = {\n\t\t\t"dshGitWorktree.managed": "托管 Worktree",\n\t\t\t"dshGitWorktree.state.working": "进行中",\n\t\t\t"dshGitWorktree.state.ready_for_review": "待验收",\n\t\t\t"dshGitWorktree.state.preview_active": "预览中",\n\t\t\t"dshGitWorktree.state.preview_detached": "待恢复",\n\t\t\t"dshGitWorktree.state.recovery_required": "需要恢复",\n\t\t\t"dshGitWorktree.state.finalized": "已完成",\n\t\t\t"dshGitWorktree.state.discarded": "已放弃",`,
@@ -49,78 +71,90 @@ export function decorateOfficialWorkspaceClient(source) {
49
71
  `\t\tconst en = {\n\t\t\t"dshGitWorktree.managed": "Managed Worktree",\n\t\t\t"dshGitWorktree.state.working": "In progress",\n\t\t\t"dshGitWorktree.state.ready_for_review": "Ready for review",\n\t\t\t"dshGitWorktree.state.preview_active": "Preview",\n\t\t\t"dshGitWorktree.state.preview_detached": "Resume preview",\n\t\t\t"dshGitWorktree.state.recovery_required": "Recovery required",\n\t\t\t"dshGitWorktree.state.finalized": "Done",\n\t\t\t"dshGitWorktree.state.discarded": "Discarded",`,
50
72
  'English Worktree locale')
51
73
  derived = replaceExactlyOnce(derived,
52
- '\t\t\t\tgroups.push(buildGroup(workspace.workspaceId, workspace.workspaceId, workspace.path, Date.parse(workspace.createdAt), workspace.title, members, "account"));',
53
- '\t\t\t\tconst group = buildGroup(workspace.workspaceId, workspace.workspaceId, workspace.path, Date.parse(workspace.createdAt), workspace.title, members, "account");\n\t\t\t\tif (workspace.__dshGitWorktreeProtected === true) group.__dshGitWorktreeProtected = true;\n\t\t\t\tgroups.push(group);',
74
+ '\t\t\t\tgroups.push(buildGroup(workspace.workspaceId, workspace.workspaceId, workspace.path, Date.parse(workspace.createdAt), workspace.title, members));',
75
+ '\t\t\t\tconst group = buildGroup(workspace.workspaceId, workspace.workspaceId, workspace.path, Date.parse(workspace.createdAt), workspace.title, members);\n\t\t\t\tif (workspace.__dshGitWorktreeProtected === true) group.__dshGitWorktreeProtected = true;\n\t\t\t\tgroups.push(group);',
54
76
  'Managed workspace metadata')
55
77
  derived = replaceExactlyOnce(derived,
56
78
  '\t\t\t\tupdatedAt: s.updatedAt,\n\t\t\t\t...pendingInteraction === void 0 ? {} : { pendingInteraction }',
57
79
  '\t\t\t\tupdatedAt: s.updatedAt,\n\t\t\t\t...s.__dshGitWorktree === void 0 ? {} : { __dshGitWorktree: s.__dshGitWorktree },\n\t\t\t\t...pendingInteraction === void 0 ? {} : { pendingInteraction }',
58
80
  'session node metadata')
59
81
  derived = replaceExactlyOnce(derived,
60
- '\t\t\t\t\t\trunningSubagentCount: descendants.get(summary.id)?.runningCount ?? 0,\n\t\t\t\t\t\t...pendingInteraction === void 0 ? {} : { pendingInteraction },',
61
- '\t\t\t\t\t\trunningSubagentCount: descendants.get(summary.id)?.runningCount ?? 0,\n\t\t\t\t\t\t...summary.__dshGitWorktree === void 0 ? {} : { __dshGitWorktree: summary.__dshGitWorktree },\n\t\t\t\t\t\t...pendingInteraction === void 0 ? {} : { pendingInteraction },',
82
+ '\t\t\t\t\t\tworkspace: labelOf(summary),\n\t\t\t\t\t\trunning: status?.running ?? summary.running,',
83
+ '\t\t\t\t\t\tworkspace: labelOf(summary),\n\t\t\t\t\t\t...summary.__dshGitWorktree === void 0 ? {} : { __dshGitWorktree: summary.__dshGitWorktree },\n\t\t\t\t\t\trunning: status?.running ?? summary.running,',
62
84
  'search result metadata')
63
85
  derived = replaceExactlyOnce(derived,
64
86
  '\t\t\t\t\tlabel: g.label,\n\t\t\t\t\tsessionCount: g.sessions.length,',
65
87
  '\t\t\t\t\tlabel: g.label,\n\t\t\t\t\t...g.__dshGitWorktreeProtected === true ? { __dshGitWorktreeProtected: true } : {},\n\t\t\t\t\tsessionCount: g.sessions.length,',
66
88
  'Managed workspace group metadata')
67
- derived = replaceExactlyOnce(derived,
68
- '\t\t/** Hover-card body: full title, relative time, and every relevant live status. */\n\t\tfunction SessionHoverContent',
69
- `\t\tfunction managedWorktreeDecoration(node, t) {\n\t\t\tconst value = node.__dshGitWorktree;\n\t\t\tif (value?.kind !== "managed-worktree" || typeof value.state !== "string") return void 0;\n\t\t\tconst label = t(\`dshGitWorktree.state.\${value.state}\`);\n\t\t\treturn {\n\t\t\t\tstate: value.state,\n\t\t\t\tlabel,\n\t\t\t\tariaLabel: \`\${t("dshGitWorktree.managed")}, \${label}, \${displayTitle(node, t)}\`\n\t\t\t};\n\t\t}\n\t\tfunction ManagedWorktreeIdentity({ decoration }) {\n\t\t\treturn (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("span", {\n\t\t\t\tclassName: "dsh-git-worktree-sidebar-icon",\n\t\t\t\t"data-worktree-state": decoration.state,\n\t\t\t\t"aria-hidden": "true",\n\t\t\t\tchildren: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutline16, {})\n\t\t\t}), (0, react_jsx_runtime.jsx)("span", {\n\t\t\t\tclassName: "dsh-git-worktree-sidebar-badge",\n\t\t\t\t"data-worktree-state": decoration.state,\n\t\t\t\t"aria-hidden": "true",\n\t\t\t\tchildren: decoration.label\n\t\t\t})] });\n\t\t}\n\t\t/** Hover-card body: full title, relative time, and every relevant live status. */\n\t\tfunction SessionHoverContent`,
89
+ derived = replaceIfPresent(derived,
90
+ '\t\t\tconst draggable = drag !== void 0 && !row.blank && !row.archived;\n\t\t\tconst [menuOpen, setMenuOpen]',
91
+ '\t\t\tconst draggable = drag !== void 0 && !row.blank && !row.archived;\n\t\t\tconst worktreeDecoration = managedWorktreeDecoration(node, t);\n\t\t\tconst [menuOpen, setMenuOpen]',
92
+ 'modern session decoration setup')
93
+ derived = replaceIfPresent(derived,
94
+ '\t\t\t\t\tclassName: clsx(Rows_module_css_default.sessionRow, selected && Rows_module_css_default.selected, menuOpen && Rows_module_css_default.menuOpen, row.archived && Rows_module_css_default.archived, drag?.marker === "before" && Rows_module_css_default.dropBefore, drag?.marker === "after" && Rows_module_css_default.dropAfter),\n\t\t\t\t\trole: "treeitem",',
95
+ '\t\t\t\t\tclassName: clsx(Rows_module_css_default.sessionRow, selected && Rows_module_css_default.selected, menuOpen && Rows_module_css_default.menuOpen, row.archived && Rows_module_css_default.archived, drag?.marker === "before" && Rows_module_css_default.dropBefore, drag?.marker === "after" && Rows_module_css_default.dropAfter),\n\t\t\t\t\t...worktreeDecoration === void 0 ? {} : { "aria-label": worktreeDecoration.ariaLabel, "data-managed-worktree": "true" },\n\t\t\t\t\trole: "treeitem",',
96
+ 'modern session row identity')
97
+ derived = replaceIfPresent(derived,
98
+ '\t\t\t\t\t\t\tchildren: !row.archived && !row.blank && (showStatus ? (0, react_jsx_runtime.jsx)(SessionStatusDots, { statuses }) : renderSlot("sidebar.session.row.leading", { sessionId: node.id }))\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t(0, react_jsx_runtime.jsx)("span", {',
99
+ '\t\t\t\t\t\t\tchildren: !row.archived && !row.blank && (showStatus ? (0, react_jsx_runtime.jsx)(SessionStatusDots, { statuses }) : renderSlot("sidebar.session.row.leading", { sessionId: node.id }))\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tworktreeDecoration !== void 0 && (0, react_jsx_runtime.jsx)(ManagedWorktreeIdentity, { decoration: worktreeDecoration }),\n\t\t\t\t\t\t(0, react_jsx_runtime.jsx)("span", {',
100
+ 'modern session row decoration')
101
+ derived = replaceIfPresent(derived,
102
+ '\t\tfunction SessionHoverContent',
103
+ `\t\tfunction managedWorktreeDecoration(node, t) {\n\t\t\tconst value = node.__dshGitWorktree;\n\t\t\tif (value?.kind !== "managed-worktree" || typeof value.state !== "string") return void 0;\n\t\t\tconst label = t(\`dshGitWorktree.state.\${value.state}\`);\n\t\t\treturn {\n\t\t\t\tstate: value.state,\n\t\t\t\tlabel,\n\t\t\t\tariaLabel: \`\${t("dshGitWorktree.managed")}, \${label}, \${displayTitle(node, t)}\`\n\t\t\t};\n\t\t}\n\t\tfunction ManagedWorktreeIdentity({ decoration }) {\n\t\t\treturn (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [(0, react_jsx_runtime.jsx)("span", {\n\t\t\t\tclassName: "dsh-git-worktree-sidebar-icon",\n\t\t\t\t"data-worktree-state": decoration.state,\n\t\t\t\t"aria-hidden": "true",\n\t\t\t\tchildren: (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutlineRegular, {})\n\t\t\t}), decoration.state !== "working" && (0, react_jsx_runtime.jsx)("span", {\n\t\t\t\tclassName: "dsh-git-worktree-sidebar-badge",\n\t\t\t\t"data-worktree-state": decoration.state,\n\t\t\t\t"aria-hidden": "true",\n\t\t\t\tchildren: decoration.label\n\t\t\t})] });\n\t\t}\n\t\t/** Hover-card body: full title, relative time, and every relevant live status. */\n\t\tfunction SessionHoverContent`,
70
104
  'Managed row helper')
71
105
  derived = replaceExactlyOnce(derived,
72
- '\t\t\tconst statuses = sessionStatuses(node, t);\n\t\t\treturn (0, react_jsx_runtime.jsxs)("div", {\n\t\t\t\tclassName: Rows_module_css_default.hoverContent,',
106
+ '\t\t\tconst statuses = sessionStatuses(node, t).filter((status) => !(node.archived && (status.state === "done" || status.state === "idle")));\n\t\t\treturn (0, react_jsx_runtime.jsxs)("div", {\n\t\t\t\tclassName: Rows_module_css_default.hoverContent,',
73
107
  '\t\t\tconst statuses = sessionStatuses(node, t);\n\t\t\tconst worktreeDecoration = managedWorktreeDecoration(node, t);\n\t\t\treturn (0, react_jsx_runtime.jsxs)("div", {\n\t\t\t\tclassName: Rows_module_css_default.hoverContent,',
74
108
  'hover metadata')
75
109
  derived = replaceExactlyOnce(derived,
76
110
  '\t\t\t\t\t\tchildren: displayTitle(node, t)\n\t\t\t\t\t}),\n\t\t\t\t\t!node.blank',
77
- '\t\t\t\t\t\tchildren: displayTitle(node, t)\n\t\t\t\t\t}),\n\t\t\t\t\tworktreeDecoration !== void 0 && (0, react_jsx_runtime.jsxs)("div", {\n\t\t\t\t\t\tclassName: Rows_module_css_default.hoverStatus,\n\t\t\t\t\t\tchildren: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutline16, {}), (0, react_jsx_runtime.jsx)("span", { children: worktreeDecoration.ariaLabel })]\n\t\t\t\t\t}),\n\t\t\t\t\t!node.blank',
111
+ '\t\t\t\t\t\tchildren: displayTitle(node, t)\n\t\t\t\t\t}),\n\t\t\t\t\tworktreeDecoration !== void 0 && (0, react_jsx_runtime.jsxs)("div", {\n\t\t\t\t\t\tclassName: Rows_module_css_default.hoverStatus,\n\t\t\t\t\t\tchildren: [(0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconBranchOutlineRegular, {}), (0, react_jsx_runtime.jsx)("span", { children: worktreeDecoration.ariaLabel })]\n\t\t\t\t\t}),\n\t\t\t\t\t!node.blank',
78
112
  'hover Worktree identity')
79
- derived = replaceExactlyOnce(derived,
113
+ derived = replaceIfPresent(derived,
80
114
  '\t\t\tconst primaryStatus = statuses[0];\n\t\t\treturn (0, react_jsx_runtime.jsxs)("button", {\n\t\t\t\ttype: "button",\n\t\t\t\tclassName: clsx(Rows_module_css_default.searchResultRow, selected && Rows_module_css_default.selected),',
81
115
  '\t\t\tconst primaryStatus = statuses[0];\n\t\t\tconst worktreeDecoration = managedWorktreeDecoration(result, t);\n\t\t\treturn (0, react_jsx_runtime.jsxs)("button", {\n\t\t\t\ttype: "button",\n\t\t\t\tclassName: clsx(Rows_module_css_default.searchResultRow, selected && Rows_module_css_default.selected),\n\t\t\t\t...worktreeDecoration === void 0 ? {} : { "aria-label": worktreeDecoration.ariaLabel, "data-managed-worktree": "true" },',
82
116
  'search Worktree identity')
83
- derived = replaceExactlyOnce(derived,
117
+ derived = replaceIfPresent(derived,
84
118
  '\t\t\t\t\t\t\tchildren: (primaryStatus.state !== "done" || result.completed) && (0, react_jsx_runtime.jsx)(SessionStatusDots, { statuses })\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t(0, react_jsx_runtime.jsx)("span", {\n\t\t\t\t\t\t\tclassName: Rows_module_css_default.searchResultTitle,',
85
119
  '\t\t\t\t\t\t\tchildren: (primaryStatus.state !== "done" || result.completed) && (0, react_jsx_runtime.jsx)(SessionStatusDots, { statuses })\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tworktreeDecoration !== void 0 && (0, react_jsx_runtime.jsx)(ManagedWorktreeIdentity, { decoration: worktreeDecoration }),\n\t\t\t\t\t\t(0, react_jsx_runtime.jsx)("span", {\n\t\t\t\t\t\t\tclassName: Rows_module_css_default.searchResultTitle,',
86
120
  'search Worktree decoration')
87
- derived = replaceExactlyOnce(derived,
88
- '\t\t\tconst label = row.workspaceId === void 0 ? t("group.ungrouped") : row.label;\n\t\t\tconst active = group.expanded && group.containsCurrent;',
89
- '\t\t\tconst label = row.workspaceId === void 0 ? t("group.ungrouped") : row.label;\n\t\t\tconst protectedManagedWorkspace = row.__dshGitWorktreeProtected === true;\n\t\t\tconst active = group.expanded && group.containsCurrent;',
121
+ derived = replaceIfPresent(derived,
122
+ '\t\t\tconst label = row.workspaceId === void 0 ? t("group.ungrouped") : row.label;\n\t\t\tconst active = containsCurrentDescendant || group.expanded && group.containsCurrent;',
123
+ '\t\t\tconst label = row.workspaceId === void 0 ? t("group.ungrouped") : row.label;\n\t\t\tconst protectedManagedWorkspace = row.__dshGitWorktreeProtected === true;\n\t\t\tconst active = containsCurrentDescendant || group.expanded && group.containsCurrent;',
90
124
  'Managed workspace row metadata')
91
- derived = replaceExactlyOnce(derived,
92
- '\t\t\t\tclassName: clsx(Rows_module_css_default.projectRow, menuOpen && Rows_module_css_default.menuOpen),\n\t\t\t\trole: "treeitem",\n\t\t\t\t"aria-expanded": row.expanded,\n\t\t\t\tonClick: onToggle,\n\t\t\t\tdraggable: drag !== void 0,',
93
- '\t\t\t\tclassName: clsx(Rows_module_css_default.projectRow, menuOpen && Rows_module_css_default.menuOpen),\n\t\t\t\trole: "treeitem",\n\t\t\t\t"aria-expanded": row.expanded,\n\t\t\t\tonClick: onToggle,\n\t\t\t\tdraggable: !protectedManagedWorkspace && drag !== void 0,',
125
+ derived = replaceIfPresent(derived,
126
+ '\t\t\t\tclassName: clsx(Rows_module_css_default.projectRow, menuOpen && Rows_module_css_default.menuOpen),\n\t\t\t\t"data-row-key": `workspace:${group.key}`,\n\t\t\t\trole: "treeitem",\n\t\t\t\t"aria-expanded": row.expanded,\n\t\t\t\tonClick: onToggle,\n\t\t\t\tdraggable: drag !== void 0,',
127
+ '\t\t\t\tclassName: clsx(Rows_module_css_default.projectRow, menuOpen && Rows_module_css_default.menuOpen),\n\t\t\t\t"data-row-key": `workspace:${group.key}`,\n\t\t\t\trole: "treeitem",\n\t\t\t\t"aria-expanded": row.expanded,\n\t\t\t\tonClick: onToggle,\n\t\t\t\tdraggable: !protectedManagedWorkspace && drag !== void 0,',
94
128
  'Managed workspace drag')
95
- derived = replaceExactlyOnce(derived,
129
+ derived = replaceIfPresent(derived,
96
130
  '\t\t\t\t\t\tchildren: [actions !== void 0 && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {',
97
131
  '\t\t\t\t\t\tchildren: [!protectedManagedWorkspace && actions !== void 0 && (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.Menu, {',
98
132
  'Managed workspace menu')
99
- derived = replaceExactlyOnce(derived,
100
- '\t\t\t\t\t\t}), (0, react_jsx_runtime.jsx)("button", {\n\t\t\t\t\t\t\ttype: "button",\n\t\t\t\t\t\t\tclassName: Rows_module_css_default.iconButton,\n\t\t\t\t\t\t\t"aria-label": t("actions.newSession.aria", { name: label }),',
101
- '\t\t\t\t\t\t}), !protectedManagedWorkspace && (0, react_jsx_runtime.jsx)("button", {\n\t\t\t\t\t\t\ttype: "button",\n\t\t\t\t\t\t\tclassName: Rows_module_css_default.iconButton,\n\t\t\t\t\t\t\t"aria-label": t("actions.newSession.aria", { name: label }),',
133
+ derived = replaceIfPresent(derived,
134
+ '\t\t\t\t\t\t\tchildren: (0, react_jsx_runtime.jsx)("button", {\n\t\t\t\t\t\t\t\ttype: "button",\n\t\t\t\t\t\t\t\tclassName: Rows_module_css_default.iconButton,\n\t\t\t\t\t\t\t\t"aria-keyshortcuts": newShortcut?.aria,\n\t\t\t\t\t\t\t\t"aria-label": t("actions.newSession.aria", { name: label }),',
135
+ '\t\t\t\t\t\t\tchildren: !protectedManagedWorkspace && (0, react_jsx_runtime.jsx)("button", {\n\t\t\t\t\t\t\t\ttype: "button",\n\t\t\t\t\t\t\t\tclassName: Rows_module_css_default.iconButton,\n\t\t\t\t\t\t\t\t"aria-keyshortcuts": newShortcut?.aria,\n\t\t\t\t\t\t\t\t"aria-label": t("actions.newSession.aria", { name: label }),',
102
136
  'Managed workspace new Session')
103
- derived = replaceExactlyOnce(derived,
137
+ derived = replaceIfPresent(derived,
104
138
  '\t\t\tconst showStatus = statuses[0].state !== "done" || row.completed;\n\t\t\tconst [menuOpen, setMenuOpen]',
105
139
  '\t\t\tconst showStatus = statuses[0].state !== "done" || row.completed;\n\t\t\tconst worktreeDecoration = managedWorktreeDecoration(row, t);\n\t\t\tconst [menuOpen, setMenuOpen]',
106
140
  'session Worktree metadata')
107
- derived = replaceExactlyOnce(derived,
141
+ derived = replaceIfPresent(derived,
108
142
  '\t\t\t];\n\t\t\treturn (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.HoverCard, {',
109
143
  '\t\t\t];\n\t\t\tconst visibleSessionMenuItems = worktreeDecoration === void 0 ? sessionMenuItems : sessionMenuItems.filter((item) => item.id !== "fork");\n\t\t\treturn (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.HoverCard, {',
110
144
  'Managed session menu')
111
- derived = replaceExactlyOnce(derived,
145
+ derived = replaceIfPresent(derived,
112
146
  '\t\t\t\t\tclassName: clsx(Rows_module_css_default.sessionRow, selected && Rows_module_css_default.selected, menuOpen && Rows_module_css_default.menuOpen, flat && !showStatus && Rows_module_css_default.flatSessionRowWithoutStatus, drag?.marker === "before" && Rows_module_css_default.dropBefore, drag?.marker === "after" && Rows_module_css_default.dropAfter),\n\t\t\t\t\trole: "treeitem",',
113
147
  '\t\t\t\t\tclassName: clsx(Rows_module_css_default.sessionRow, selected && Rows_module_css_default.selected, menuOpen && Rows_module_css_default.menuOpen, flat && !showStatus && Rows_module_css_default.flatSessionRowWithoutStatus, drag?.marker === "before" && Rows_module_css_default.dropBefore, drag?.marker === "after" && Rows_module_css_default.dropAfter),\n\t\t\t\t\trole: "treeitem",\n\t\t\t\t\t...worktreeDecoration === void 0 ? {} : { "aria-label": worktreeDecoration.ariaLabel, "data-managed-worktree": "true" },',
114
148
  'session Worktree aria')
115
- derived = replaceExactlyOnce(derived,
149
+ derived = replaceIfPresent(derived,
116
150
  '\t\t\t\t\t"aria-selected": selected,\n\t\t\t\t\tonClick: () => {\n\t\t\t\t\t\tonOpen(node.id);\n\t\t\t\t\t},\n\t\t\t\t\tdraggable: drag !== void 0,',
117
151
  '\t\t\t\t\t"aria-selected": selected,\n\t\t\t\t\tonClick: () => {\n\t\t\t\t\t\tonOpen(node.id);\n\t\t\t\t\t},\n\t\t\t\t\tdraggable: worktreeDecoration === void 0 && drag !== void 0,',
118
152
  'Managed session drag')
119
- derived = replaceExactlyOnce(derived,
153
+ derived = replaceIfPresent(derived,
120
154
  '\t\t\t\t\t\t(!flat || showStatus) && (0, react_jsx_runtime.jsx)("span", {\n\t\t\t\t\t\t\tclassName: Rows_module_css_default.slot,\n\t\t\t\t\t\t\tchildren: showStatus && (0, react_jsx_runtime.jsx)(SessionStatusDots, { statuses })\n\t\t\t\t\t\t}),\n\t\t\t\t\t\t(0, react_jsx_runtime.jsx)("span", {',
121
155
  '\t\t\t\t\t\tworktreeDecoration === void 0 && (!flat || showStatus) && (0, react_jsx_runtime.jsx)("span", {\n\t\t\t\t\t\t\tclassName: Rows_module_css_default.slot,\n\t\t\t\t\t\t\tchildren: showStatus && (0, react_jsx_runtime.jsx)(SessionStatusDots, { statuses })\n\t\t\t\t\t\t}),\n\t\t\t\t\t\tworktreeDecoration !== void 0 && (0, react_jsx_runtime.jsx)(ManagedWorktreeIdentity, { decoration: worktreeDecoration }),\n\t\t\t\t\t\t(0, react_jsx_runtime.jsx)("span", {',
122
156
  'session Worktree decoration')
123
- derived = replaceExactlyOnce(derived,
157
+ derived = replaceIfPresent(derived,
124
158
  '\t\t\t\t\t\t\t\titems: sessionMenuItems,',
125
159
  '\t\t\t\t\t\t\t\titems: visibleSessionMenuItems,',
126
160
  'Managed session visible menu')