@jingyi0605/codingns4dsh 0.2.1-beta.1 → 0.2.1-beta.3

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 (217) hide show
  1. package/README.en.md +25 -14
  2. package/README.md +21 -17
  3. package/data/build/dist/client/bundle.js +366 -81
  4. package/data/build/dist/client/bundle.js.map +1 -1
  5. package/data/build/dist/client/locales/fileWorkspace.d.ts.map +1 -1
  6. package/data/build/dist/client/locales/fileWorkspace.js +4 -0
  7. package/data/build/dist/client/locales/fileWorkspace.js.map +1 -1
  8. package/data/build/dist/client/locales/peerHostWorkspace.d.ts.map +1 -1
  9. package/data/build/dist/client/locales/peerHostWorkspace.js +16 -2
  10. package/data/build/dist/client/locales/peerHostWorkspace.js.map +1 -1
  11. package/data/build/dist/client/peer-host-native-projection.d.ts +4 -3
  12. package/data/build/dist/client/peer-host-native-projection.d.ts.map +1 -1
  13. package/data/build/dist/client/peer-host-native-projection.js +7 -6
  14. package/data/build/dist/client/peer-host-native-projection.js.map +1 -1
  15. package/data/build/dist/client/peer-host-native-store-projection.js +9 -21
  16. package/data/build/dist/client/peer-host-native-store-projection.js.map +1 -1
  17. package/data/build/dist/client/peer-host-workspace-tab.d.ts.map +1 -1
  18. package/data/build/dist/client/peer-host-workspace-tab.js +139 -10
  19. package/data/build/dist/client/peer-host-workspace-tab.js.map +1 -1
  20. package/data/build/dist/client/session-changed-files-view.d.ts.map +1 -1
  21. package/data/build/dist/client/session-changed-files-view.js +162 -58
  22. package/data/build/dist/client/session-changed-files-view.js.map +1 -1
  23. package/data/build/dist/client/skill-command.d.ts +1 -1
  24. package/data/build/dist/client/skill-command.d.ts.map +1 -1
  25. package/data/build/dist/client/skill-command.js +25 -2
  26. package/data/build/dist/client/skill-command.js.map +1 -1
  27. package/data/build/dist/client/skill-reference-dom.js +1 -1
  28. package/data/build/dist/client/skill-reference-dom.js.map +1 -1
  29. package/data/build/dist/client/terminal/styles.js +2 -2
  30. package/data/build/dist/dsh-capabilities/host/sidebar-session-compat.d.ts +28 -0
  31. package/data/build/dist/dsh-capabilities/host/sidebar-session-compat.d.ts.map +1 -0
  32. package/data/build/dist/dsh-capabilities/host/sidebar-session-compat.js +109 -0
  33. package/data/build/dist/dsh-capabilities/host/sidebar-session-compat.js.map +1 -0
  34. package/data/build/dist/host/cli-adapters/acp-cli-driver.d.ts +25 -3
  35. package/data/build/dist/host/cli-adapters/acp-cli-driver.d.ts.map +1 -1
  36. package/data/build/dist/host/cli-adapters/acp-cli-driver.js +120 -9
  37. package/data/build/dist/host/cli-adapters/acp-cli-driver.js.map +1 -1
  38. package/data/build/dist/host/cli-adapters/acp-elicitation.d.ts +31 -0
  39. package/data/build/dist/host/cli-adapters/acp-elicitation.d.ts.map +1 -0
  40. package/data/build/dist/host/cli-adapters/acp-elicitation.js +144 -0
  41. package/data/build/dist/host/cli-adapters/acp-elicitation.js.map +1 -0
  42. package/data/build/dist/host/cli-adapters/antigravity-driver.d.ts +2 -1
  43. package/data/build/dist/host/cli-adapters/antigravity-driver.d.ts.map +1 -1
  44. package/data/build/dist/host/cli-adapters/antigravity-driver.js +15 -2
  45. package/data/build/dist/host/cli-adapters/antigravity-driver.js.map +1 -1
  46. package/data/build/dist/host/cli-adapters/attachment-utils.d.ts +16 -5
  47. package/data/build/dist/host/cli-adapters/attachment-utils.d.ts.map +1 -1
  48. package/data/build/dist/host/cli-adapters/attachment-utils.js +152 -42
  49. package/data/build/dist/host/cli-adapters/attachment-utils.js.map +1 -1
  50. package/data/build/dist/host/cli-adapters/claude-driver.d.ts +23 -8
  51. package/data/build/dist/host/cli-adapters/claude-driver.d.ts.map +1 -1
  52. package/data/build/dist/host/cli-adapters/claude-driver.js +227 -70
  53. package/data/build/dist/host/cli-adapters/claude-driver.js.map +1 -1
  54. package/data/build/dist/host/cli-adapters/codebuddy-driver.d.ts +7 -1
  55. package/data/build/dist/host/cli-adapters/codebuddy-driver.d.ts.map +1 -1
  56. package/data/build/dist/host/cli-adapters/codebuddy-driver.js +143 -6
  57. package/data/build/dist/host/cli-adapters/codebuddy-driver.js.map +1 -1
  58. package/data/build/dist/host/cli-adapters/codex-driver.d.ts.map +1 -1
  59. package/data/build/dist/host/cli-adapters/codex-driver.js +74 -6
  60. package/data/build/dist/host/cli-adapters/codex-driver.js.map +1 -1
  61. package/data/build/dist/host/cli-adapters/command-code-acp-loader.d.ts +23 -0
  62. package/data/build/dist/host/cli-adapters/command-code-acp-loader.d.ts.map +1 -0
  63. package/data/build/dist/host/cli-adapters/command-code-acp-loader.js +39 -0
  64. package/data/build/dist/host/cli-adapters/command-code-acp-loader.js.map +1 -0
  65. package/data/build/dist/host/cli-adapters/command-code-driver.d.ts +17 -6
  66. package/data/build/dist/host/cli-adapters/command-code-driver.d.ts.map +1 -1
  67. package/data/build/dist/host/cli-adapters/command-code-driver.js +448 -26
  68. package/data/build/dist/host/cli-adapters/command-code-driver.js.map +1 -1
  69. package/data/build/dist/host/cli-adapters/command-code-subscription.d.ts +1 -1
  70. package/data/build/dist/host/cli-adapters/command-code-subscription.d.ts.map +1 -1
  71. package/data/build/dist/host/cli-adapters/command-code-subscription.js +7 -4
  72. package/data/build/dist/host/cli-adapters/command-code-subscription.js.map +1 -1
  73. package/data/build/dist/host/cli-adapters/cursor-driver.d.ts +1 -1
  74. package/data/build/dist/host/cli-adapters/cursor-driver.js +2 -2
  75. package/data/build/dist/host/cli-adapters/cursor-driver.js.map +1 -1
  76. package/data/build/dist/host/cli-adapters/delegation-mention-rewrite.js +1 -1
  77. package/data/build/dist/host/cli-adapters/delegation-mention-rewrite.js.map +1 -1
  78. package/data/build/dist/host/cli-adapters/dsh-message-projector.d.ts.map +1 -1
  79. package/data/build/dist/host/cli-adapters/dsh-message-projector.js +28 -0
  80. package/data/build/dist/host/cli-adapters/dsh-message-projector.js.map +1 -1
  81. package/data/build/dist/host/cli-adapters/dsh-tool-history.d.ts.map +1 -1
  82. package/data/build/dist/host/cli-adapters/dsh-tool-history.js +23 -1
  83. package/data/build/dist/host/cli-adapters/dsh-tool-history.js.map +1 -1
  84. package/data/build/dist/host/cli-adapters/feature.d.ts.map +1 -1
  85. package/data/build/dist/host/cli-adapters/feature.js +5 -3
  86. package/data/build/dist/host/cli-adapters/feature.js.map +1 -1
  87. package/data/build/dist/host/cli-adapters/gemini-driver.d.ts +2 -1
  88. package/data/build/dist/host/cli-adapters/gemini-driver.d.ts.map +1 -1
  89. package/data/build/dist/host/cli-adapters/gemini-driver.js +66 -11
  90. package/data/build/dist/host/cli-adapters/gemini-driver.js.map +1 -1
  91. package/data/build/dist/host/cli-adapters/grok-driver.d.ts +5 -2
  92. package/data/build/dist/host/cli-adapters/grok-driver.d.ts.map +1 -1
  93. package/data/build/dist/host/cli-adapters/grok-driver.js +268 -18
  94. package/data/build/dist/host/cli-adapters/grok-driver.js.map +1 -1
  95. package/data/build/dist/host/cli-adapters/json-rpc-process.d.ts +2 -0
  96. package/data/build/dist/host/cli-adapters/json-rpc-process.d.ts.map +1 -1
  97. package/data/build/dist/host/cli-adapters/json-rpc-process.js +8 -3
  98. package/data/build/dist/host/cli-adapters/json-rpc-process.js.map +1 -1
  99. package/data/build/dist/host/cli-adapters/kimi-driver.d.ts +4 -0
  100. package/data/build/dist/host/cli-adapters/kimi-driver.d.ts.map +1 -1
  101. package/data/build/dist/host/cli-adapters/kimi-driver.js +11 -4
  102. package/data/build/dist/host/cli-adapters/kimi-driver.js.map +1 -1
  103. package/data/build/dist/host/cli-adapters/kiro-driver.js +1 -1
  104. package/data/build/dist/host/cli-adapters/kiro-driver.js.map +1 -1
  105. package/data/build/dist/host/cli-adapters/mcode-driver.d.ts +6 -2
  106. package/data/build/dist/host/cli-adapters/mcode-driver.d.ts.map +1 -1
  107. package/data/build/dist/host/cli-adapters/mcode-driver.js +95 -26
  108. package/data/build/dist/host/cli-adapters/mcode-driver.js.map +1 -1
  109. package/data/build/dist/host/cli-adapters/native-subagent-dispatch.d.ts +55 -1
  110. package/data/build/dist/host/cli-adapters/native-subagent-dispatch.d.ts.map +1 -1
  111. package/data/build/dist/host/cli-adapters/native-subagent-dispatch.js +148 -6
  112. package/data/build/dist/host/cli-adapters/native-subagent-dispatch.js.map +1 -1
  113. package/data/build/dist/host/cli-adapters/native-team-subagent.d.ts +7 -0
  114. package/data/build/dist/host/cli-adapters/native-team-subagent.d.ts.map +1 -1
  115. package/data/build/dist/host/cli-adapters/native-team-subagent.js.map +1 -1
  116. package/data/build/dist/host/cli-adapters/new-api-subscription.d.ts.map +1 -1
  117. package/data/build/dist/host/cli-adapters/new-api-subscription.js +11 -58
  118. package/data/build/dist/host/cli-adapters/new-api-subscription.js.map +1 -1
  119. package/data/build/dist/host/cli-adapters/opencode-driver.d.ts +5 -2
  120. package/data/build/dist/host/cli-adapters/opencode-driver.d.ts.map +1 -1
  121. package/data/build/dist/host/cli-adapters/opencode-driver.js +136 -18
  122. package/data/build/dist/host/cli-adapters/opencode-driver.js.map +1 -1
  123. package/data/build/dist/host/cli-adapters/pi-driver.d.ts.map +1 -1
  124. package/data/build/dist/host/cli-adapters/pi-driver.js +2 -1
  125. package/data/build/dist/host/cli-adapters/pi-driver.js.map +1 -1
  126. package/data/build/dist/host/cli-adapters/process-utils.d.ts +10 -0
  127. package/data/build/dist/host/cli-adapters/process-utils.d.ts.map +1 -1
  128. package/data/build/dist/host/cli-adapters/process-utils.js +20 -0
  129. package/data/build/dist/host/cli-adapters/process-utils.js.map +1 -1
  130. package/data/build/dist/host/cli-adapters/provider-subscription.d.ts +3 -0
  131. package/data/build/dist/host/cli-adapters/provider-subscription.d.ts.map +1 -1
  132. package/data/build/dist/host/cli-adapters/provider-subscription.js +42 -8
  133. package/data/build/dist/host/cli-adapters/provider-subscription.js.map +1 -1
  134. package/data/build/dist/host/cli-adapters/qoder-driver.d.ts +4 -4
  135. package/data/build/dist/host/cli-adapters/qoder-driver.d.ts.map +1 -1
  136. package/data/build/dist/host/cli-adapters/qoder-driver.js +31 -8
  137. package/data/build/dist/host/cli-adapters/qoder-driver.js.map +1 -1
  138. package/data/build/dist/host/cli-adapters/registry.d.ts.map +1 -1
  139. package/data/build/dist/host/cli-adapters/registry.js +5 -3
  140. package/data/build/dist/host/cli-adapters/registry.js.map +1 -1
  141. package/data/build/dist/host/cli-adapters/rpc-driver-utils.d.ts.map +1 -1
  142. package/data/build/dist/host/cli-adapters/rpc-driver-utils.js +2 -9
  143. package/data/build/dist/host/cli-adapters/rpc-driver-utils.js.map +1 -1
  144. package/data/build/dist/host/cli-adapters/skill-filesystem.d.ts +25 -0
  145. package/data/build/dist/host/cli-adapters/skill-filesystem.d.ts.map +1 -0
  146. package/data/build/dist/host/cli-adapters/skill-filesystem.js +161 -0
  147. package/data/build/dist/host/cli-adapters/skill-filesystem.js.map +1 -0
  148. package/data/build/dist/host/cli-adapters/standard-stream-driver.d.ts +1 -0
  149. package/data/build/dist/host/cli-adapters/standard-stream-driver.d.ts.map +1 -1
  150. package/data/build/dist/host/cli-adapters/standard-stream-driver.js +7 -1
  151. package/data/build/dist/host/cli-adapters/standard-stream-driver.js.map +1 -1
  152. package/data/build/dist/host/cli-adapters/subagent-tool.d.ts.map +1 -1
  153. package/data/build/dist/host/cli-adapters/subagent-tool.js +40 -10
  154. package/data/build/dist/host/cli-adapters/subagent-tool.js.map +1 -1
  155. package/data/build/dist/host/cli-adapters/zcode-driver.d.ts +8 -2
  156. package/data/build/dist/host/cli-adapters/zcode-driver.d.ts.map +1 -1
  157. package/data/build/dist/host/cli-adapters/zcode-driver.js +166 -55
  158. package/data/build/dist/host/cli-adapters/zcode-driver.js.map +1 -1
  159. package/data/build/dist/host/cli-adapters/zcode-interactions.d.ts +18 -0
  160. package/data/build/dist/host/cli-adapters/zcode-interactions.d.ts.map +1 -0
  161. package/data/build/dist/host/cli-adapters/zcode-interactions.js +90 -0
  162. package/data/build/dist/host/cli-adapters/zcode-interactions.js.map +1 -0
  163. package/data/build/dist/host/cli-adapters/zcode-provider-config.d.ts +26 -0
  164. package/data/build/dist/host/cli-adapters/zcode-provider-config.d.ts.map +1 -0
  165. package/data/build/dist/host/cli-adapters/zcode-provider-config.js +102 -0
  166. package/data/build/dist/host/cli-adapters/zcode-provider-config.js.map +1 -0
  167. package/data/build/dist/host/cli-adapters/zcode-subscription.d.ts +2 -7
  168. package/data/build/dist/host/cli-adapters/zcode-subscription.d.ts.map +1 -1
  169. package/data/build/dist/host/cli-adapters/zcode-subscription.js.map +1 -1
  170. package/data/build/dist/host/cli-adapters/zcode-telemetry.d.ts +17 -0
  171. package/data/build/dist/host/cli-adapters/zcode-telemetry.d.ts.map +1 -0
  172. package/data/build/dist/host/cli-adapters/zcode-telemetry.js +124 -0
  173. package/data/build/dist/host/cli-adapters/zcode-telemetry.js.map +1 -0
  174. package/data/build/dist/host/cli-bridge/bridge-holder.d.ts +4 -1
  175. package/data/build/dist/host/cli-bridge/bridge-holder.d.ts.map +1 -1
  176. package/data/build/dist/host/cli-bridge/bridge-holder.js.map +1 -1
  177. package/data/build/dist/host/cli-bridge/bridge-server.d.ts +11 -3
  178. package/data/build/dist/host/cli-bridge/bridge-server.d.ts.map +1 -1
  179. package/data/build/dist/host/cli-bridge/bridge-server.js +8 -4
  180. package/data/build/dist/host/cli-bridge/bridge-server.js.map +1 -1
  181. package/data/build/dist/host/cli-bridge/command-code-mod.js +18 -2
  182. package/data/build/dist/host/cli-bridge/command-code-mod.js.map +1 -1
  183. package/data/build/dist/host/cli-bridge/dispatch.d.ts.map +1 -1
  184. package/data/build/dist/host/cli-bridge/dispatch.js +30 -5
  185. package/data/build/dist/host/cli-bridge/dispatch.js.map +1 -1
  186. package/data/build/dist/host/cli-bridge/injections.d.ts +2 -9
  187. package/data/build/dist/host/cli-bridge/injections.d.ts.map +1 -1
  188. package/data/build/dist/host/cli-bridge/injections.js +9 -19
  189. package/data/build/dist/host/cli-bridge/injections.js.map +1 -1
  190. package/data/build/dist/host/cli-bridge/mcp-stdio-entry.js +49 -7
  191. package/data/build/dist/host/cli-bridge/mcp-stdio-entry.js.map +1 -1
  192. package/data/build/dist/host/features/peer-host.d.ts.map +1 -1
  193. package/data/build/dist/host/features/peer-host.js +23 -0
  194. package/data/build/dist/host/features/peer-host.js.map +1 -1
  195. package/data/build/dist/host/index.d.ts +1 -1
  196. package/data/build/dist/host/index.d.ts.map +1 -1
  197. package/data/build/dist/host/index.js +4 -1
  198. package/data/build/dist/host/index.js.map +1 -1
  199. package/data/build/dist/host/modules/peer-host/peer-host-native-protocol.d.ts +2 -0
  200. package/data/build/dist/host/modules/peer-host/peer-host-native-protocol.d.ts.map +1 -1
  201. package/data/build/dist/host/modules/peer-host/peer-host-native-protocol.js +5 -0
  202. package/data/build/dist/host/modules/peer-host/peer-host-native-protocol.js.map +1 -1
  203. package/data/build/dist/host/modules/peer-host/peer-host-remote-summary-source.d.ts.map +1 -1
  204. package/data/build/dist/host/modules/peer-host/peer-host-remote-summary-source.js +3 -1
  205. package/data/build/dist/host/modules/peer-host/peer-host-remote-summary-source.js.map +1 -1
  206. package/data/build/dist/host/rpc.d.ts.map +1 -1
  207. package/data/build/dist/host/rpc.js +5 -0
  208. package/data/build/dist/host/rpc.js.map +1 -1
  209. package/data/build/dist/shared/contracts/cli-adapter.d.ts +4 -0
  210. package/data/build/dist/shared/contracts/cli-adapter.d.ts.map +1 -1
  211. package/data/build/dist/shared/contracts/version.d.ts +1 -1
  212. package/data/build/dist/shared/contracts/version.js +1 -1
  213. package/package.json +3 -1
  214. package/profile/README.md +2 -2
  215. package/profile/package.json +2 -2
  216. package/profile/version.json +1 -1
  217. package/version.json +1 -1
@@ -296,6 +296,8 @@ window.__ModuleLoader__.load({
296
296
  "sessionFiles.title": "Changed files",
297
297
  "sessionFiles.count": "{count} files",
298
298
  "sessionFiles.refresh": "Refresh",
299
+ "sessionFiles.close": "Close diff",
300
+ "sessionFiles.loadingDiff": "Reading diff…",
299
301
  "sessionFiles.stageAll": "Stage all",
300
302
  "sessionFiles.loading": "Reading session changes…",
301
303
  "sessionFiles.empty": "No changed files were detected in this session",
@@ -362,6 +364,8 @@ window.__ModuleLoader__.load({
362
364
  "sessionFiles.title": "修改文件",
363
365
  "sessionFiles.count": "{count} 个文件",
364
366
  "sessionFiles.refresh": "刷新",
367
+ "sessionFiles.close": "关闭 Diff",
368
+ "sessionFiles.loadingDiff": "正在读取 Diff…",
365
369
  "sessionFiles.stageAll": "全部暂存",
366
370
  "sessionFiles.loading": "正在读取会话修改…",
367
371
  "sessionFiles.empty": "本次会话没有已识别的修改文件",
@@ -810,11 +814,18 @@ window.__ModuleLoader__.load({
810
814
  "peerHostWorkspace.tabRemote": "Remote HOST",
811
815
  "peerHostWorkspace.sourceLabel": "Workspace source",
812
816
  "peerHostWorkspace.heading": "Remote HOST workspaces",
813
- "peerHostWorkspace.hint": "Choose a Host, then one of its registered workspaces; added workspaces appear only in the local sidebar.",
817
+ "peerHostWorkspace.hint": "Choose a Host to view its added workspaces; use the candidates below to add another one.",
814
818
  "peerHostWorkspace.loadingHosts": "Reading registered Hosts…",
815
819
  "peerHostWorkspace.noHosts": "No other Host is registered yet. Add one under “Manage other DSH Hosts” first.",
816
820
  "peerHostWorkspace.loadingWorkspaces": "Reading the workspaces registered on this Host…",
817
821
  "peerHostWorkspace.noWorkspaces": "This Host has no registered workspaces.",
822
+ "peerHostWorkspace.addedHeading": "Added workspaces",
823
+ "peerHostWorkspace.availableHeading": "Add a workspace",
824
+ "peerHostWorkspace.noAddedWorkspaces": "No remote workspace has been added to this Host yet.",
825
+ "peerHostWorkspace.columnWorkspace": "Workspace",
826
+ "peerHostWorkspace.columnSessions": "Sessions",
827
+ "peerHostWorkspace.columnHost": "Remote HOST",
828
+ "peerHostWorkspace.columnPath": "Path",
818
829
  "peerHostWorkspace.noSessions": "No sessions",
819
830
  "peerHostWorkspace.sessionCount": "{count} sessions",
820
831
  "peerHostWorkspace.added": "Added; the workspace appears in the sidebar after you close this dialog.",
@@ -841,11 +852,18 @@ window.__ModuleLoader__.load({
841
852
  "peerHostWorkspace.tabRemote": "远程 HOST",
842
853
  "peerHostWorkspace.sourceLabel": "工作区来源",
843
854
  "peerHostWorkspace.heading": "远程 HOST 工作区",
844
- "peerHostWorkspace.hint": "选择一台 Host,再选择它上面已登记的工作区;添加后只在本机侧栏显示这些工作区。",
855
+ "peerHostWorkspace.hint": "选择一台 Host 查看已添加的工作区;可在下方候选列表继续添加工作区。",
845
856
  "peerHostWorkspace.loadingHosts": "正在读取已登记的 Host…",
846
857
  "peerHostWorkspace.noHosts": "尚未登记其他 Host。请先在“管理其他 DSH Host”中添加。",
847
858
  "peerHostWorkspace.loadingWorkspaces": "正在读取该 Host 已登记的工作区…",
848
859
  "peerHostWorkspace.noWorkspaces": "该 Host 上没有已登记的工作区。",
860
+ "peerHostWorkspace.addedHeading": "已添加的远程工作区",
861
+ "peerHostWorkspace.availableHeading": "添加远程工作区",
862
+ "peerHostWorkspace.noAddedWorkspaces": "该 Host 尚未添加远程工作区。",
863
+ "peerHostWorkspace.columnWorkspace": "工作区名称",
864
+ "peerHostWorkspace.columnSessions": "会话数",
865
+ "peerHostWorkspace.columnHost": "所属远程 HOST",
866
+ "peerHostWorkspace.columnPath": "路径",
849
867
  "peerHostWorkspace.noSessions": "无会话",
850
868
  "peerHostWorkspace.sessionCount": "{count} 个会话",
851
869
  "peerHostWorkspace.added": "已添加;关闭对话框后该工作区会出现在侧栏。",
@@ -2788,7 +2806,7 @@ window.__ModuleLoader__.load({
2788
2806
  return /^0\.1\.5(?:-|$)/u.test(version);
2789
2807
  }
2790
2808
  /** Codingns4DSH 插件自身的 npm 版本。 */
2791
- const CODINGNS_VERSION = "0.2.1-beta.1";
2809
+ const CODINGNS_VERSION = "0.2.1-beta.3";
2792
2810
  /** 判断宿主版本是否落在当前插件声明的 DSH 兼容范围内;范围省略上界时不校验上限。 */
2793
2811
  function isDshVersionCompatible(version) {
2794
2812
  const match = /^>=([^ ]+)(?: <=([^ ]+))?$/u.exec(DSH_COMPATIBILITY);
@@ -17110,7 +17128,7 @@ window.__ModuleLoader__.load({
17110
17128
  function findSkillReferenceMentions(value, names) {
17111
17129
  const byLowerName = new Map([...names].map((name) => [name.toLocaleLowerCase(), name]));
17112
17130
  const matches = [];
17113
- for (const match of value.matchAll(/\/[A-Za-z0-9][A-Za-z0-9._-]*(?=\s|$)/gu)) {
17131
+ for (const match of value.matchAll(/\/[A-Za-z0-9][A-Za-z0-9._:/-]*(?=\s|$)/gu)) {
17114
17132
  const token = match[0] ?? "";
17115
17133
  const start = match.index ?? -1;
17116
17134
  const before = start > 0 ? value[start - 1] : void 0;
@@ -17251,7 +17269,8 @@ window.__ModuleLoader__.load({
17251
17269
  const SKILL_INPUT_SOURCE = "codingns-skills";
17252
17270
  const SKILL_CATALOG_CACHE_TTL_MS = 3e4;
17253
17271
  const skillCatalogCache = /* @__PURE__ */ new Map();
17254
- /** 把 Codex 原生 Skill 目录接入 DSH `/` 菜单。 */
17272
+ const skillCapabilityCache = /* @__PURE__ */ new Map();
17273
+ /** 把声明了 Skill 能力的外部 Agent 目录接入 DSH `/` 菜单。 */
17255
17274
  function registerSkillCommand(ctx, options) {
17256
17275
  const state = {
17257
17276
  catalogReady: false,
@@ -17419,11 +17438,20 @@ window.__ModuleLoader__.load({
17419
17438
  return false;
17420
17439
  }
17421
17440
  }
17422
- /** 按会话与 Agent 选择版本缓存目录,避免输入每个字符都请求 Codex。 */
17441
+ /** 按会话与 Agent 选择版本缓存目录,避免输入每个字符都请求外部 CLI。 */
17423
17442
  async function loadSkillCatalog(rpc, sessionId, signal, forceReload) {
17424
17443
  const selectionRevision = cliSessionSelectionRevision(sessionId);
17425
17444
  const cached = skillCatalogCache.get(sessionId);
17426
17445
  if (!forceReload && cached !== void 0 && cached.selectionRevision === selectionRevision && Date.now() - cached.loadedAt < SKILL_CATALOG_CACHE_TTL_MS) return cached.catalog;
17446
+ if (!await supportsSelectedAgentSkills(rpc, sessionId, selectionRevision)) {
17447
+ skillCatalogCache.set(sessionId, {
17448
+ selectionRevision,
17449
+ loadedAt: Date.now(),
17450
+ catalog: []
17451
+ });
17452
+ publishSkillCatalog(sessionId, []);
17453
+ return [];
17454
+ }
17427
17455
  const catalog = await callCliRpc(rpc, "skills", {
17428
17456
  sessionId,
17429
17457
  forceReload: true
@@ -17436,6 +17464,25 @@ window.__ModuleLoader__.load({
17436
17464
  publishSkillCatalog(sessionId, catalog);
17437
17465
  return catalog;
17438
17466
  }
17467
+ /** 让原生 DSH Skill UI 处理 dsh 会话,插件只为声明了 skills 的外部适配器请求目录。 */
17468
+ async function supportsSelectedAgentSkills(rpc, sessionId, selectionRevision) {
17469
+ const cached = skillCapabilityCache.get(sessionId);
17470
+ if (cached?.selectionRevision === selectionRevision) return cached.supported;
17471
+ const session = await callCliRpc(rpc, "session/get", { sessionId });
17472
+ if (session.adapterId === "dsh") {
17473
+ skillCapabilityCache.set(sessionId, {
17474
+ selectionRevision,
17475
+ supported: false
17476
+ });
17477
+ return false;
17478
+ }
17479
+ const supported = (await callCliRpc(rpc, "catalog", {})).find((item) => item.id === session.adapterId)?.capabilities?.includes("skills") === true;
17480
+ skillCapabilityCache.set(sessionId, {
17481
+ selectionRevision,
17482
+ supported
17483
+ });
17484
+ return supported;
17485
+ }
17439
17486
  function skillCommandSpan(draft, draftRev, selection) {
17440
17487
  const caret = selection?.end ?? draft.length;
17441
17488
  const token = /\/(?:skills|技能)(?=\s|$)/gu;
@@ -56021,8 +56068,11 @@ window.__ModuleLoader__.load({
56021
56068
  }
56022
56069
  //#endregion
56023
56070
  //#region src/client/session-changed-files-view.ts
56071
+ init_popup_dismiss();
56024
56072
  init_locale();
56025
56073
  const SESSION_CHANGED_FILES_VIEW_ID = "codingns4dsh/session-changed-files";
56074
+ /** 后台轮询只负责兜底发现外部文件变化,不能和页面交互争夺刷新节奏。 */
56075
+ const SESSION_CHANGED_FILES_BACKGROUND_REFRESH_MS = 3e4;
56026
56076
  /** 会话“修改文件”视图;数据只通过插件 RPC 和现有 Git RPC 读取。 */
56027
56077
  function SessionChangedFilesView(props) {
56028
56078
  const t = props.t;
@@ -56031,50 +56081,68 @@ window.__ModuleLoader__.load({
56031
56081
  const [changes, setChanges] = (0, react.useState)([]);
56032
56082
  const [selectedPath, setSelectedPath] = (0, react.useState)();
56033
56083
  const [diff, setDiff] = (0, react.useState)();
56084
+ const [diffLoading, setDiffLoading] = (0, react.useState)(false);
56085
+ const [mobileDiffOpen, setMobileDiffOpen] = (0, react.useState)(false);
56034
56086
  const [collapsed, setCollapsed] = (0, react.useState)(/* @__PURE__ */ new Set());
56035
56087
  const [hoveredPath, setHoveredPath] = (0, react.useState)();
56036
56088
  const [loading, setLoading] = (0, react.useState)(true);
56037
56089
  const [busy, setBusy] = (0, react.useState)(false);
56038
56090
  const [error, setError] = (0, react.useState)();
56039
56091
  const requestGeneration = (0, react.useRef)(0);
56040
- const load = async () => {
56092
+ const inFlightLoad = (0, react.useRef)();
56093
+ const load = (foreground = false) => {
56094
+ if (inFlightLoad.current !== void 0) return inFlightLoad.current;
56041
56095
  const generation = requestGeneration.current + 1;
56042
56096
  requestGeneration.current = generation;
56043
- setLoading(true);
56044
- setError(void 0);
56045
- try {
56046
- const resolved = await resolveGitWorkspaceId(props.remote, props.sessionId);
56047
- if (resolved === void 0) throw new Error("当前会话没有可用的工作区");
56048
- const [sessionFiles, status] = await Promise.all([call(props.rpc, "fileManagement/session-changes", {
56049
- sessionId: props.sessionId,
56050
- workspaceId: resolved
56051
- }), call(props.rpc, "git/status", { workspaceId: resolved })]);
56052
- if (generation !== requestGeneration.current) return;
56053
- const next = selectSessionChangedFiles(sessionFiles, status);
56054
- setWorkspaceId(resolved);
56055
- setChanges(next);
56056
- props.reportCount?.(props.sessionId, next.length);
56057
- setSelectedPath((current) => current !== void 0 && next.some((item) => item.path === current) ? current : next[0]?.path);
56058
- } catch (cause) {
56059
- if (generation !== requestGeneration.current) return;
56060
- setError(cause instanceof Error ? cause.message : String(cause));
56061
- setChanges([]);
56062
- setWorkspaceId(void 0);
56063
- props.reportCount?.(props.sessionId, 0);
56064
- } finally {
56065
- if (generation === requestGeneration.current) setLoading(false);
56097
+ if (foreground) {
56098
+ setLoading(true);
56099
+ setError(void 0);
56066
56100
  }
56101
+ const tracked = (async () => {
56102
+ try {
56103
+ const resolved = await resolveGitWorkspaceId(props.remote, props.sessionId);
56104
+ if (resolved === void 0) throw new Error("当前会话没有可用的工作区");
56105
+ const [sessionFiles, status] = await Promise.all([call(props.rpc, "fileManagement/session-changes", {
56106
+ sessionId: props.sessionId,
56107
+ workspaceId: resolved
56108
+ }), call(props.rpc, "git/status", { workspaceId: resolved })]);
56109
+ if (generation !== requestGeneration.current) return;
56110
+ const next = selectSessionChangedFiles(sessionFiles, status);
56111
+ setWorkspaceId((current) => current === resolved ? current : resolved);
56112
+ setChanges((current) => mergeChangedFiles(current, next));
56113
+ props.reportCount?.(props.sessionId, next.length);
56114
+ setSelectedPath((current) => current !== void 0 && next.some((item) => item.path === current) ? current : next[0]?.path);
56115
+ setError(void 0);
56116
+ } catch (cause) {
56117
+ if (generation !== requestGeneration.current) return;
56118
+ if (foreground) {
56119
+ setError(cause instanceof Error ? cause.message : String(cause));
56120
+ setChanges([]);
56121
+ setWorkspaceId(void 0);
56122
+ props.reportCount?.(props.sessionId, 0);
56123
+ } else setError(cause instanceof Error ? cause.message : String(cause));
56124
+ } finally {
56125
+ if (generation === requestGeneration.current && foreground) setLoading(false);
56126
+ }
56127
+ })().finally(() => {
56128
+ if (inFlightLoad.current === tracked) inFlightLoad.current = void 0;
56129
+ });
56130
+ inFlightLoad.current = tracked;
56131
+ return tracked;
56067
56132
  };
56068
56133
  (0, react.useEffect)(() => {
56069
56134
  setDiff(void 0);
56135
+ setDiffLoading(false);
56136
+ setMobileDiffOpen(false);
56070
56137
  setCollapsed(/* @__PURE__ */ new Set());
56071
56138
  setWorkspaceId(void 0);
56072
- load();
56139
+ load(true);
56073
56140
  const timer = globalThis.setInterval(() => {
56074
56141
  load();
56075
- }, 5e3);
56142
+ }, SESSION_CHANGED_FILES_BACKGROUND_REFRESH_MS);
56076
56143
  return () => {
56077
56144
  requestGeneration.current += 1;
56145
+ inFlightLoad.current = void 0;
56078
56146
  globalThis.clearInterval(timer);
56079
56147
  };
56080
56148
  }, [
@@ -56096,11 +56164,18 @@ window.__ModuleLoader__.load({
56096
56164
  (0, react.useEffect)(() => {
56097
56165
  if (workspaceId === void 0 || selectedPath === void 0) {
56098
56166
  setDiff(void 0);
56167
+ setDiffLoading(false);
56099
56168
  return;
56100
56169
  }
56101
56170
  const selected = changes.find((item) => item.path === selectedPath);
56102
- if (selected === void 0) return;
56171
+ if (selected === void 0) {
56172
+ setDiff(void 0);
56173
+ setDiffLoading(false);
56174
+ return;
56175
+ }
56103
56176
  let cancelled = false;
56177
+ setDiff(void 0);
56178
+ setDiffLoading(true);
56104
56179
  call(props.rpc, "git/diff", {
56105
56180
  workspaceId,
56106
56181
  path: selected.path,
@@ -56109,6 +56184,8 @@ window.__ModuleLoader__.load({
56109
56184
  if (!cancelled) setDiff(value);
56110
56185
  }).catch((cause) => {
56111
56186
  if (!cancelled) setError(cause instanceof Error ? cause.message : String(cause));
56187
+ }).finally(() => {
56188
+ if (!cancelled) setDiffLoading(false);
56112
56189
  });
56113
56190
  return () => {
56114
56191
  cancelled = true;
@@ -56119,6 +56196,14 @@ window.__ModuleLoader__.load({
56119
56196
  selectedPath,
56120
56197
  workspaceId
56121
56198
  ]);
56199
+ (0, react.useEffect)(() => {
56200
+ if (!compactLayout) setMobileDiffOpen(false);
56201
+ if (selectedPath === void 0 || !changes.some((item) => item.path === selectedPath)) setMobileDiffOpen(false);
56202
+ }, [
56203
+ changes,
56204
+ compactLayout,
56205
+ selectedPath
56206
+ ]);
56122
56207
  const tree = (0, react.useMemo)(() => buildTree(changes), [changes]);
56123
56208
  const unstaged = changes.filter((item) => !item.staged);
56124
56209
  const stageTargets = async (targets, action) => {
@@ -56130,7 +56215,7 @@ window.__ModuleLoader__.load({
56130
56215
  targets
56131
56216
  });
56132
56217
  notifyGitWorkspaceChanged(workspaceId);
56133
- await load();
56218
+ await load(true);
56134
56219
  } catch (cause) {
56135
56220
  setError(cause instanceof Error ? cause.message : String(cause));
56136
56221
  } finally {
@@ -56146,6 +56231,11 @@ window.__ModuleLoader__.load({
56146
56231
  });
56147
56232
  };
56148
56233
  const hasChanges = changes.length > 0;
56234
+ const selectedChange = selectedPath === void 0 ? void 0 : changes.find((item) => item.path === selectedPath);
56235
+ const selectPath = (path) => {
56236
+ setSelectedPath(path);
56237
+ if (compactLayout) setMobileDiffOpen(true);
56238
+ };
56149
56239
  const viewRootStyle = {
56150
56240
  ...rootStyle,
56151
56241
  padding: compactLayout ? "0 16px" : rootStyle.padding
@@ -56167,7 +56257,7 @@ window.__ModuleLoader__.load({
56167
56257
  return (0, react.createElement)("div", { style: viewRootStyle }, (0, react.createElement)("div", { style: viewToolbarStyle }, (0, react.createElement)("strong", { style: { fontSize: 15 } }, t("sessionFiles.title")), (0, react.createElement)("span", { style: countStyle }, t("sessionFiles.count", { count: changes.length })), (0, react.createElement)("span", { style: { flex: 1 } }), (0, react.createElement)("button", {
56168
56258
  type: "button",
56169
56259
  disabled: loading || busy,
56170
- onClick: () => void load(),
56260
+ onClick: () => void load(true),
56171
56261
  style: toolbarRefreshButtonStyle,
56172
56262
  title: t("sessionFiles.refresh"),
56173
56263
  "aria-label": t("sessionFiles.refresh")
@@ -56181,7 +56271,24 @@ window.__ModuleLoader__.load({
56181
56271
  }, (0, react.createElement)(StageIcon))), error === void 0 ? null : (0, react.createElement)("div", {
56182
56272
  role: "alert",
56183
56273
  style: errorStyle
56184
- }, error), (0, react.createElement)("div", { style: viewContentStyle }, (0, react.createElement)("div", { style: viewTreePaneStyle }, loading ? (0, react.createElement)("div", { style: emptyStyle }, t("sessionFiles.loading")) : changes.length === 0 ? (0, react.createElement)("div", { style: emptyStyle }, t("sessionFiles.empty")) : tree.map((node) => renderNode(node, 0, collapsed, hoveredPath, selectedPath, toggle, setSelectedPath, setHoveredPath, stageTargets, t))), hasChanges ? (0, react.createElement)("div", { style: diffPaneStyle }, selectedPath === void 0 ? (0, react.createElement)("div", { style: emptyStyle }, t("sessionFiles.selectFile")) : diff?.content ? (0, react.createElement)("pre", { style: diffStyle }, renderDiff(diff.content)) : (0, react.createElement)("div", { style: emptyStyle }, t("sessionFiles.noDiff"))) : null));
56274
+ }, error), (0, react.createElement)("div", { style: viewContentStyle }, (0, react.createElement)("div", { style: viewTreePaneStyle }, loading ? (0, react.createElement)("div", { style: emptyStyle }, t("sessionFiles.loading")) : changes.length === 0 ? (0, react.createElement)("div", { style: emptyStyle }, t("sessionFiles.empty")) : tree.map((node) => renderNode(node, 0, collapsed, hoveredPath, selectedPath, toggle, selectPath, setHoveredPath, stageTargets, t))), !compactLayout && hasChanges ? (0, react.createElement)("div", { style: diffPaneStyle }, selectedPath === void 0 ? (0, react.createElement)("div", { style: emptyStyle }, t("sessionFiles.selectFile")) : diffLoading ? (0, react.createElement)("div", { style: emptyStyle }, t("sessionFiles.loadingDiff")) : diff?.content ? (0, react.createElement)("pre", { style: diffStyle }, renderDiff(diff.content)) : (0, react.createElement)("div", { style: emptyStyle }, t("sessionFiles.noDiff"))) : null), compactLayout && mobileDiffOpen && selectedPath !== void 0 ? (0, react.createElement)("div", {
56275
+ style: mobileDiffOverlayStyle,
56276
+ onPointerDown: backdropPointerDownHandler(() => setMobileDiffOpen(false))
56277
+ }, (0, react.createElement)("section", {
56278
+ role: "dialog",
56279
+ "aria-modal": true,
56280
+ "aria-label": selectedChange?.path ?? t("sessionFiles.title"),
56281
+ style: mobileDiffModalStyle
56282
+ }, (0, react.createElement)("header", { style: mobileDiffHeaderStyle }, (0, react.createElement)("strong", {
56283
+ style: mobileDiffTitleStyle,
56284
+ title: selectedChange?.path
56285
+ }, selectedChange?.path ?? t("sessionFiles.title")), (0, react.createElement)("button", {
56286
+ type: "button",
56287
+ onClick: () => setMobileDiffOpen(false),
56288
+ style: mobileDiffCloseStyle,
56289
+ title: t("sessionFiles.close"),
56290
+ "aria-label": t("sessionFiles.close")
56291
+ }, "×")), (0, react.createElement)("div", { style: mobileDiffBodyStyle }, diffLoading ? (0, react.createElement)("div", { style: emptyStyle }, t("sessionFiles.loadingDiff")) : diff?.content ? (0, react.createElement)("pre", { style: diffStyle }, renderDiff(diff.content)) : (0, react.createElement)("div", { style: emptyStyle }, t("sessionFiles.noDiff"))))) : null);
56185
56292
  }
56186
56293
  /** 注册 DSH 原生 conversation.view Slot;标签由 DSH 根据 Slot 的 id/label 自动投影。 */
56187
56294
  function registerSessionChangedFilesView(ctx, rpc, remote, locale) {
@@ -56264,37 +56371,51 @@ window.__ModuleLoader__.load({
56264
56371
  (0, react.useEffect)(() => {
56265
56372
  let disposed = false;
56266
56373
  let generation = 0;
56374
+ let hasSuccessfulLoad = false;
56375
+ let subscribedWorkspaceId;
56376
+ let inFlight;
56267
56377
  let disposeWorkspaceSubscription;
56268
56378
  const updateWorkspaceSubscription = (workspaceId) => {
56379
+ if (subscribedWorkspaceId === workspaceId) return;
56269
56380
  disposeWorkspaceSubscription?.();
56381
+ subscribedWorkspaceId = workspaceId;
56270
56382
  disposeWorkspaceSubscription = workspaceId === void 0 ? void 0 : subscribeGitWorkspaceChanged(workspaceId, () => {
56271
56383
  load();
56272
56384
  });
56273
56385
  };
56274
- const load = async () => {
56386
+ const load = () => {
56387
+ if (inFlight !== void 0) return inFlight;
56275
56388
  const currentGeneration = ++generation;
56276
- try {
56277
- const workspaceId = await resolveGitWorkspaceId(props.remote, props.sessionId);
56278
- if (workspaceId === void 0) throw new Error("当前会话没有可用的工作区");
56279
- const [sessionFiles, status] = await Promise.all([call(props.rpc, "fileManagement/session-changes", {
56280
- sessionId: props.sessionId,
56281
- workspaceId
56282
- }), call(props.rpc, "git/status", { workspaceId })]);
56283
- if (disposed || currentGeneration !== generation) return;
56284
- updateWorkspaceSubscription(workspaceId);
56285
- const count = selectSessionChangedFiles(sessionFiles, status).length;
56286
- props.reportCount(props.sessionId, count);
56287
- } catch {
56288
- if (!disposed && currentGeneration === generation) props.reportCount(props.sessionId, 0);
56289
- }
56389
+ const tracked = (async () => {
56390
+ try {
56391
+ const workspaceId = await resolveGitWorkspaceId(props.remote, props.sessionId);
56392
+ if (workspaceId === void 0) throw new Error("当前会话没有可用的工作区");
56393
+ const [sessionFiles, status] = await Promise.all([call(props.rpc, "fileManagement/session-changes", {
56394
+ sessionId: props.sessionId,
56395
+ workspaceId
56396
+ }), call(props.rpc, "git/status", { workspaceId })]);
56397
+ if (disposed || currentGeneration !== generation) return;
56398
+ updateWorkspaceSubscription(workspaceId);
56399
+ const count = selectSessionChangedFiles(sessionFiles, status).length;
56400
+ hasSuccessfulLoad = true;
56401
+ props.reportCount(props.sessionId, count);
56402
+ } catch {
56403
+ if (!disposed && currentGeneration === generation && !hasSuccessfulLoad) props.reportCount(props.sessionId, 0);
56404
+ }
56405
+ })().finally(() => {
56406
+ if (inFlight === tracked) inFlight = void 0;
56407
+ });
56408
+ inFlight = tracked;
56409
+ return tracked;
56290
56410
  };
56291
56411
  load();
56292
56412
  const timer = globalThis.setInterval(() => {
56293
56413
  load();
56294
- }, 5e3);
56414
+ }, SESSION_CHANGED_FILES_BACKGROUND_REFRESH_MS);
56295
56415
  return () => {
56296
56416
  disposed = true;
56297
56417
  generation += 1;
56418
+ inFlight = void 0;
56298
56419
  globalThis.clearInterval(timer);
56299
56420
  disposeWorkspaceSubscription?.();
56300
56421
  };
@@ -56313,6 +56434,19 @@ window.__ModuleLoader__.load({
56313
56434
  style: diffLineStyle(line)
56314
56435
  }, `${line}${index < lines.length - 1 ? "\n" : ""}`));
56315
56436
  }
56437
+ /** 只替换真正变化的行对象,后台刷新时保持未变化文件的引用和交互状态。 */
56438
+ function mergeChangedFiles(current, next) {
56439
+ if (current.length === next.length && current.every((item, index) => sameChange(item, next[index]))) return current;
56440
+ const previous = new Map(current.map((item) => [item.path, item]));
56441
+ return next.map((item) => {
56442
+ const old = previous.get(item.path);
56443
+ return old !== void 0 && sameChange(old, item) ? old : item;
56444
+ });
56445
+ }
56446
+ function sameChange(left, right) {
56447
+ if (left === void 0 || right === void 0) return left === right;
56448
+ return left.path === right.path && left.status === right.status && left.staged === right.staged && left.oldPath === right.oldPath && left.binary === right.binary && left.stagedStatus === right.stagedStatus && left.worktreeStatus === right.worktreeStatus;
56449
+ }
56316
56450
  /** 只显示当前 Git 状态中仍属于本会话触及范围的文件。 */
56317
56451
  function selectSessionChangedFiles(sessionFiles, status) {
56318
56452
  const touched = new Set(sessionFiles.paths.map(normalizePath));
@@ -56663,6 +56797,66 @@ window.__ModuleLoader__.load({
56663
56797
  wordBreak: "break-word",
56664
56798
  font: "12px/1.55 var(--dsw-font-mono,ui-monospace,monospace)"
56665
56799
  };
56800
+ const mobileDiffOverlayStyle = {
56801
+ position: "fixed",
56802
+ inset: 0,
56803
+ zIndex: 1e3,
56804
+ display: "flex",
56805
+ alignItems: "stretch",
56806
+ justifyContent: "center",
56807
+ padding: 10,
56808
+ boxSizing: "border-box",
56809
+ background: "rgba(0,0,0,.48)"
56810
+ };
56811
+ const mobileDiffModalStyle = {
56812
+ display: "flex",
56813
+ flexDirection: "column",
56814
+ width: "100%",
56815
+ maxWidth: 720,
56816
+ maxHeight: "100%",
56817
+ minHeight: 0,
56818
+ overflow: "hidden",
56819
+ borderRadius: 10,
56820
+ background: "var(--dsw-alias-bg-layer-1,#fff)",
56821
+ boxShadow: "0 12px 40px rgba(0,0,0,.3)"
56822
+ };
56823
+ const mobileDiffHeaderStyle = {
56824
+ display: "flex",
56825
+ alignItems: "center",
56826
+ gap: 8,
56827
+ minHeight: 46,
56828
+ padding: "0 12px",
56829
+ borderBottom: "1px solid var(--dsw-alias-border-l3,#ddd)",
56830
+ flex: "0 0 auto"
56831
+ };
56832
+ const mobileDiffTitleStyle = {
56833
+ minWidth: 0,
56834
+ flex: 1,
56835
+ overflow: "hidden",
56836
+ textOverflow: "ellipsis",
56837
+ whiteSpace: "nowrap",
56838
+ fontSize: 13
56839
+ };
56840
+ const mobileDiffCloseStyle = {
56841
+ display: "inline-flex",
56842
+ alignItems: "center",
56843
+ justifyContent: "center",
56844
+ width: 32,
56845
+ height: 32,
56846
+ border: 0,
56847
+ borderRadius: 6,
56848
+ padding: 0,
56849
+ background: "transparent",
56850
+ color: "var(--dsw-alias-label-secondary,#777)",
56851
+ cursor: "pointer",
56852
+ fontSize: 22,
56853
+ lineHeight: 1
56854
+ };
56855
+ const mobileDiffBodyStyle = {
56856
+ minHeight: 0,
56857
+ overflow: "auto",
56858
+ background: "var(--dsw-alias-bg-layer-1,transparent)"
56859
+ };
56666
56860
  const diffHeaderLineStyle = {
56667
56861
  display: "block",
56668
56862
  color: "var(--dsw-alias-label-tertiary,#777)"
@@ -58511,12 +58705,13 @@ window.__ModuleLoader__.load({
58511
58705
  //#region src/client/peer-host-native-projection.ts
58512
58706
  init_session_adapter_cache();
58513
58707
  /**
58514
- * 为混合工作区生成只用于原生侧栏树归属的稳定路径。
58708
+ * 为需要稳定显示标识的调用方生成虚拟 URI。
58515
58709
  *
58516
58710
  * DSH 会把 `workspace.path` 的目录前缀关系解释成父子工作区。不同 Host 的真实
58517
58711
  * 路径以及本地工作区之间都可能发生前缀重叠,因此列表层不能继续暴露真实目录。
58518
- * 这里使用不对应本机文件系统的 URI,并把完整虚拟 ID 编码成单一段,保证所有
58519
- * 工作区都是同一层的兄弟节点。文件和会话请求仍使用所属 Host 的真实路径。
58712
+ * 这里使用不对应本机文件系统的 URI,并把完整虚拟 ID 编码成单一段。Workspace
58713
+ * Store 使用这个值保证不同 Host 的同路径工作区仍是并列条目;真正的文件请求会在
58714
+ * Host 转发边界按虚拟 Workspace ID还原为目标 Host 的真实路径。
58520
58715
  */
58521
58716
  function createPeerHostWorkspaceDisplayPath(virtualWorkspaceId) {
58522
58717
  return `codingns-peer-host://${encodeURIComponent(virtualWorkspaceId)}`;
@@ -58590,8 +58785,8 @@ window.__ModuleLoader__.load({
58590
58785
  }
58591
58786
  function projectWorkspace(virtualHostId, workspace) {
58592
58787
  const virtualWorkspaceId = createVirtualWorkspaceId(virtualHostId, workspace.workspaceId);
58593
- const displayPath = createPeerHostWorkspaceDisplayPath(virtualWorkspaceId);
58594
58788
  const realPath = workspace.path;
58789
+ const displayPath = createPeerHostWorkspaceDisplayPath(virtualWorkspaceId);
58595
58790
  const sessionIds = [];
58596
58791
  const archivedSessionIds = [];
58597
58792
  const sessions = [];
@@ -58747,7 +58942,7 @@ window.__ModuleLoader__.load({
58747
58942
  }));
58748
58943
  const injected = virtual.filter((workspace) => !known.has(workspace.workspaceId));
58749
58944
  const archivedSessionIds = mergeArchivedSessionIds(record.archivedSessionIds, virtual);
58750
- const mergedItems = normalizeWorkspaceDisplayPaths(orderWorkspaceItems([...items, ...injected], orderedWorkspaceIds, localHostId), localHostId);
58945
+ const mergedItems = normalizeRemoteWorkspaceDisplayPaths(orderWorkspaceItems([...items, ...injected], orderedWorkspaceIds, localHostId));
58751
58946
  if (!(mergedItems.length !== items.length || mergedItems.some((item, index) => item !== items[index])) && archivedSessionIds === void 0) return snapshot;
58752
58947
  return {
58753
58948
  ...record,
@@ -58755,20 +58950,14 @@ window.__ModuleLoader__.load({
58755
58950
  ...archivedSessionIds === void 0 ? {} : { archivedSessionIds }
58756
58951
  };
58757
58952
  }
58758
- /**
58759
- * 原生 Remote 返回的远端工作区可能已经存在于底层 Store,此时不会走 injected
58760
- * 分支;本地条目也可能因真实目录前缀形成树层级。按虚拟 ID统一规范化 path,
58761
- * 保证所有工作区在 DSH 列表中都是同层兄弟节点。
58762
- */
58763
- function normalizeWorkspaceDisplayPaths(items, localHostId) {
58953
+ /** 原生 Remote 可能先把远端条目写入底层 Store,仍需强制保持扁平虚拟显示路径。 */
58954
+ function normalizeRemoteWorkspaceDisplayPaths(items) {
58764
58955
  let changed = false;
58765
58956
  const normalized = items.map((item) => {
58766
58957
  const record = asRecord$1(item);
58767
58958
  const workspaceId = record?.workspaceId;
58768
- if (record === null || typeof workspaceId !== "string") return item;
58769
- const virtualWorkspaceId = parseVirtualWorkspaceId(workspaceId) !== null ? workspaceId : localHostId === void 0 ? void 0 : createVirtualWorkspaceId(localHostId, workspaceId);
58770
- if (virtualWorkspaceId === void 0) return item;
58771
- const displayPath = createPeerHostWorkspaceDisplayPath(virtualWorkspaceId);
58959
+ if (record === null || typeof workspaceId !== "string" || parseVirtualWorkspaceId(workspaceId) === null) return item;
58960
+ const displayPath = createPeerHostWorkspaceDisplayPath(workspaceId);
58772
58961
  if (record.path === displayPath) return item;
58773
58962
  changed = true;
58774
58963
  return {
@@ -58779,9 +58968,8 @@ window.__ModuleLoader__.load({
58779
58968
  return changed ? normalized : items;
58780
58969
  }
58781
58970
  /**
58782
- * 原生会话列表只把空白会话的 cwd 用于判断是否能复用。工作区树扁平化后,
58783
- * 让空白行看到同一个显示路径即可保留该判断;正式会话继续保留真实 cwd,
58784
- * 避免 Git、文件面板或远端工具拿到虚拟 URI。
58971
+ * 原生会话列表只把空白会话的 cwd 用于判断是否能复用;同步工作区真实路径即可
58972
+ * 保留该判断,正式会话也继续保留真实 cwd,避免 Git、文件面板或远端工具拿到虚拟 URI。
58785
58973
  */
58786
58974
  function installSessionDisplayPathProjection(workspaceStore, sessionStore) {
58787
58975
  if (sessionStore === void 0) return () => void 0;
@@ -59237,6 +59425,18 @@ window.__ModuleLoader__.load({
59237
59425
  .${TAB_CLASS}-rowName{overflow:hidden;font-size:13px;font-weight:500;line-height:20px;text-overflow:ellipsis;white-space:nowrap}
59238
59426
  .${TAB_CLASS}-rowMeta{overflow:hidden;font-size:11px;line-height:17px;color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap}
59239
59427
  .${TAB_CLASS}-rowCount{flex:none;font-size:11px;line-height:17px;color:var(--dsw-alias-label-tertiary);font-variant-numeric:tabular-nums}
59428
+ .${TAB_CLASS}-sectionTitle{margin:4px 0 0;font-size:13px;font-weight:510;line-height:20px;color:var(--dsw-alias-label-primary)}
59429
+ .${TAB_CLASS}-tableWrap{flex:none;overflow-x:auto;margin:0 -8px;border:.5px solid var(--dsw-alias-border-l4);border-radius:var(--dsw-radius-sm)}
59430
+ .${TAB_CLASS}-table{width:100%;min-width:520px;border-collapse:collapse;table-layout:fixed;font-size:12px;line-height:18px}
59431
+ .${TAB_CLASS}-table th{padding:8px;text-align:left;font-size:11px;font-weight:500;color:var(--dsw-alias-label-tertiary);background:var(--dsw-alias-interactive-bg-hover);white-space:nowrap}
59432
+ .${TAB_CLASS}-table td{padding:9px 8px;border-top:.5px solid var(--dsw-alias-border-l4);color:var(--dsw-alias-label-primary);vertical-align:top}
59433
+ .${TAB_CLASS}-table th:nth-child(1),.${TAB_CLASS}-table td:nth-child(1){width:25%}
59434
+ .${TAB_CLASS}-table th:nth-child(2),.${TAB_CLASS}-table td:nth-child(2){width:13%;white-space:nowrap}
59435
+ .${TAB_CLASS}-table th:nth-child(3),.${TAB_CLASS}-table td:nth-child(3){width:20%;white-space:nowrap}
59436
+ .${TAB_CLASS}-table th:nth-child(4),.${TAB_CLASS}-table td:nth-child(4){width:42%}
59437
+ .${TAB_CLASS}-tableName{display:block;overflow:hidden;font-weight:500;text-overflow:ellipsis;white-space:nowrap}
59438
+ .${TAB_CLASS}-tablePath{display:block;overflow:hidden;color:var(--dsw-alias-label-tertiary);text-overflow:ellipsis;white-space:nowrap}
59439
+ .${TAB_CLASS}-tableEmpty{padding:10px 0;margin:0;font-size:12px;line-height:18px;color:var(--dsw-alias-label-tertiary)}
59240
59440
  [${PEER_HOST_WORKSPACE_TAB_STATE_ATTRIBUTE}='remote'] ${CRUMB_BAR_SELECTOR},
59241
59441
  [${PEER_HOST_WORKSPACE_TAB_STATE_ATTRIBUTE}='remote'] ${CONTENT_SELECTOR},
59242
59442
  [${PEER_HOST_WORKSPACE_TAB_STATE_ATTRIBUTE}='remote'] ${FOOTER_BAR_SELECTOR}{display:none !important}
@@ -59304,12 +59504,12 @@ window.__ModuleLoader__.load({
59304
59504
  }
59305
59505
  /** 注入样式表;用插件自有标记,停用时按标记精确移除。 */
59306
59506
  function installStyle(dom) {
59307
- if (dom.querySelector(`style[data-plugin-css="${TAB_STYLE_ID}"]`) !== null) return;
59308
- const style = dom.createElement("style");
59507
+ const existing = dom.querySelector(`style[data-plugin-css="${TAB_STYLE_ID}"]`);
59508
+ const style = existing ?? dom.createElement("style");
59309
59509
  style.dataset.plugin = "codingns4dsh";
59310
59510
  style.dataset.pluginCss = TAB_STYLE_ID;
59311
59511
  style.textContent = TAB_STYLE_TEXT;
59312
- dom.head?.appendChild(style);
59512
+ if (existing === null) dom.head?.appendChild(style);
59313
59513
  }
59314
59514
  /** 在原生对话框里建立标签栏与远端面板。 */
59315
59515
  function inject$1(dialog, editorScope, options, previous = null) {
@@ -59345,6 +59545,7 @@ window.__ModuleLoader__.load({
59345
59545
  records: previous?.records ?? null,
59346
59546
  selectedHostId: previous?.selectedHostId ?? null,
59347
59547
  candidates: previous?.candidates ?? null,
59548
+ addedWorkspaces: previous?.addedWorkspaces ?? null,
59348
59549
  loading: false,
59349
59550
  message: previous?.message ?? null,
59350
59551
  messageKind: previous?.messageKind ?? "info",
@@ -59420,6 +59621,7 @@ window.__ModuleLoader__.load({
59420
59621
  if (options === null || state.selectedHostId === record.id) return;
59421
59622
  state.selectedHostId = record.id;
59422
59623
  state.candidates = null;
59624
+ state.addedWorkspaces = null;
59423
59625
  state.message = null;
59424
59626
  render(state, options);
59425
59627
  if (record.status === "ready") loadCandidates(state, options);
@@ -59437,15 +59639,35 @@ window.__ModuleLoader__.load({
59437
59639
  state.panel.append(note(dom, t("peerHostWorkspace.loadingWorkspaces"), "info"));
59438
59640
  return;
59439
59641
  }
59440
- if (state.candidates.length === 0) {
59642
+ if (state.candidates.length === 0 && (state.addedWorkspaces === null || state.addedWorkspaces.length === 0)) {
59441
59643
  if (state.message !== null) state.panel.append(note(dom, state.message, state.messageKind));
59442
59644
  else state.panel.append(note(dom, t("peerHostWorkspace.noWorkspaces"), "info"));
59443
59645
  return;
59444
59646
  }
59647
+ const addedIds = new Set(selected?.visibleWorkspaceIds ?? []);
59648
+ const addedCandidates = state.addedWorkspaces === null ? state.candidates.filter((candidate) => addedIds.has(candidate.workspaceId)) : state.addedWorkspaces;
59649
+ const addedWorkspaceIds = new Set(addedCandidates.map((candidate) => candidate.workspaceId));
59650
+ const availableCandidates = state.candidates.filter((candidate) => !addedWorkspaceIds.has(candidate.workspaceId) && !addedIds.has(candidate.workspaceId));
59651
+ const addedHeading = dom.createElement("strong");
59652
+ addedHeading.className = `${TAB_CLASS}-sectionTitle`;
59653
+ addedHeading.textContent = t("peerHostWorkspace.addedHeading");
59654
+ state.panel.append(addedHeading);
59655
+ if (addedCandidates.length === 0) {
59656
+ const empty = dom.createElement("p");
59657
+ empty.className = `${TAB_CLASS}-tableEmpty`;
59658
+ empty.textContent = t("peerHostWorkspace.noAddedWorkspaces");
59659
+ state.panel.append(empty);
59660
+ } else state.panel.append(createWorkspaceTable(dom, t, selected?.displayName ?? "", addedCandidates));
59661
+ if (availableCandidates.length > 0) {
59662
+ const availableHeading = dom.createElement("strong");
59663
+ availableHeading.className = `${TAB_CLASS}-sectionTitle`;
59664
+ availableHeading.textContent = t("peerHostWorkspace.availableHeading");
59665
+ state.panel.append(availableHeading);
59666
+ }
59445
59667
  const list = dom.createElement("div");
59446
59668
  list.className = `${TAB_CLASS}-list`;
59447
59669
  list.setAttribute("role", "list");
59448
- for (const candidate of state.candidates) {
59670
+ for (const candidate of availableCandidates) {
59449
59671
  const row = dom.createElement("button");
59450
59672
  row.type = "button";
59451
59673
  row.className = `${TAB_CLASS}-row`;
@@ -59473,9 +59695,56 @@ window.__ModuleLoader__.load({
59473
59695
  });
59474
59696
  list.append(row);
59475
59697
  }
59476
- state.panel.append(list);
59698
+ if (availableCandidates.length > 0) state.panel.append(list);
59477
59699
  if (state.message !== null) state.panel.append(note(dom, state.message, state.messageKind));
59478
59700
  }
59701
+ /** 渲染已添加工作区的只读信息表;添加动作仍由下方候选列表负责。 */
59702
+ function createWorkspaceTable(dom, t, hostName, candidates) {
59703
+ const wrapper = dom.createElement("div");
59704
+ wrapper.className = `${TAB_CLASS}-tableWrap`;
59705
+ const table = dom.createElement("table");
59706
+ table.className = `${TAB_CLASS}-table`;
59707
+ table.setAttribute("aria-label", t("peerHostWorkspace.addedHeading"));
59708
+ const head = dom.createElement("thead");
59709
+ const headerRow = dom.createElement("tr");
59710
+ for (const label of [
59711
+ t("peerHostWorkspace.columnWorkspace"),
59712
+ t("peerHostWorkspace.columnSessions"),
59713
+ t("peerHostWorkspace.columnHost"),
59714
+ t("peerHostWorkspace.columnPath")
59715
+ ]) {
59716
+ const cell = dom.createElement("th");
59717
+ cell.setAttribute("scope", "col");
59718
+ cell.textContent = label;
59719
+ headerRow.append(cell);
59720
+ }
59721
+ head.append(headerRow);
59722
+ const body = dom.createElement("tbody");
59723
+ for (const candidate of candidates) {
59724
+ const row = dom.createElement("tr");
59725
+ row.setAttribute("data-codingns-peer-host-tab-added-workspace", candidate.workspaceId);
59726
+ const name = dom.createElement("td");
59727
+ const nameText = dom.createElement("span");
59728
+ nameText.className = `${TAB_CLASS}-tableName`;
59729
+ nameText.textContent = candidate.displayName;
59730
+ name.append(nameText);
59731
+ const sessions = dom.createElement("td");
59732
+ sessions.textContent = candidate.sessionCount === 0 ? t("peerHostWorkspace.noSessions") : t("peerHostWorkspace.sessionCount", { count: candidate.sessionCount });
59733
+ const host = dom.createElement("td");
59734
+ host.textContent = hostName;
59735
+ const path = dom.createElement("td");
59736
+ path.title = candidate.path;
59737
+ const pathText = dom.createElement("span");
59738
+ pathText.className = `${TAB_CLASS}-tablePath`;
59739
+ pathText.textContent = candidate.path;
59740
+ path.append(pathText);
59741
+ row.append(name, sessions, host, path);
59742
+ body.append(row);
59743
+ }
59744
+ table.append(head, body);
59745
+ wrapper.append(table);
59746
+ return wrapper;
59747
+ }
59479
59748
  async function loadRecords(state, options) {
59480
59749
  const generation = ++state.generation;
59481
59750
  try {
@@ -59495,12 +59764,21 @@ window.__ModuleLoader__.load({
59495
59764
  if (hostId === null) return;
59496
59765
  const generation = ++state.generation;
59497
59766
  try {
59498
- const candidates = await options.api.workspaceCandidates(hostId);
59767
+ const [candidateResult, aggregateResult] = await Promise.allSettled([options.api.workspaceCandidates(hostId), options.api.aggregate()]);
59499
59768
  if (state.generation !== generation || state.selectedHostId !== hostId) return;
59500
- state.candidates = candidates;
59769
+ if (candidateResult.status === "rejected") throw candidateResult.reason;
59770
+ state.candidates = candidateResult.value;
59771
+ const aggregateHost = aggregateResult.status === "fulfilled" ? aggregateResult.value.find((result) => result.targetHostId === hostId) : void 0;
59772
+ state.addedWorkspaces = aggregateHost?.availability === "ready" ? aggregateHost.workspaces.map((workspace) => ({
59773
+ workspaceId: workspace.workspaceId,
59774
+ displayName: workspace.displayName,
59775
+ path: workspace.path,
59776
+ sessionCount: workspace.sessions.length + (workspace.archivedSessions?.length ?? 0)
59777
+ })) : null;
59501
59778
  } catch (error) {
59502
59779
  if (state.generation !== generation || state.selectedHostId !== hostId) return;
59503
59780
  state.candidates = [];
59781
+ state.addedWorkspaces = [];
59504
59782
  state.message = message(error);
59505
59783
  state.messageKind = "error";
59506
59784
  }
@@ -59513,7 +59791,14 @@ window.__ModuleLoader__.load({
59513
59791
  state.message = null;
59514
59792
  render(state, options);
59515
59793
  try {
59516
- await options.api.setWorkspaceVisibility(hostId, workspaceId, true);
59794
+ const updated = await options.api.setWorkspaceVisibility(hostId, workspaceId, true);
59795
+ if (updated !== void 0) state.records = state.records?.map((record) => record.id === hostId ? updated : record) ?? state.records;
59796
+ const added = state.candidates?.find((candidate) => candidate.workspaceId === workspaceId);
59797
+ if (added !== void 0) {
59798
+ const visibleIds = new Set(state.records?.find((record) => record.id === hostId)?.visibleWorkspaceIds ?? []);
59799
+ const current = state.addedWorkspaces ?? state.candidates?.filter((candidate) => visibleIds.has(candidate.workspaceId)) ?? [];
59800
+ if (!current.some((workspace) => workspace.workspaceId === added.workspaceId)) state.addedWorkspaces = [...current, added];
59801
+ }
59517
59802
  state.message = state.t("peerHostWorkspace.added");
59518
59803
  state.messageKind = "success";
59519
59804
  await options.onWorkspaceAdded?.(hostId, workspaceId);
@@ -66424,10 +66709,10 @@ window.__ModuleLoader__.load({
66424
66709
  .${terminalClass.toolAction}[aria-pressed="true"],.${terminalClass.toolModifierActive}{background:var(--dsw-alias-button-ghost-active-fill,var(--dsw-alias-interactive-bg-active));box-shadow:inset 0 0 0 .5px var(--dsw-alias-button-ghost-active-border,var(--dsw-alias-border-l3))}
66425
66710
  .${terminalClass.listRow}{box-sizing:border-box;display:flex;align-items:center;height:28px;min-width:110px;max-width:220px;border-radius:var(--dsw-radius-sm,6px);background:transparent;flex:none}
66426
66711
  .${terminalClass.listRowSelected}{background:var(--dsw-alias-interactive-bg-hover);box-shadow:var(--dsw-elevation-soft,0 1px 2px rgba(0,0,0,.08))}
66427
- .${terminalClass.listSelect}{box-sizing:border-box;min-width:0;height:28px;min-height:28px;flex:1;text-align:left;color:inherit;border:0;background:transparent;cursor:pointer;padding:0 8px;display:flex;align-items:center;gap:5px;font:inherit;line-height:20px}
66712
+ .${terminalClass.listSelect}{box-sizing:border-box;min-width:0;height:28px;min-height:28px;flex:1;text-align:left;color:inherit;border:0;background:transparent;cursor:pointer;padding:0 8px;display:flex;align-items:center;gap:5px;font:inherit;font-size:12px;line-height:20px}
66428
66713
  .${terminalClass.listSelect} span{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}
66429
66714
  .${terminalClass.listSelect} small{color:var(--dsw-alias-label-caption);font-size:11px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
66430
- .${terminalClass.listInput}{box-sizing:border-box;min-width:0;height:24px;min-height:24px;flex:1;margin:0 4px;color:inherit;background:var(--dsw-alias-bg-base);border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-sm,6px);padding:0 6px;font:inherit;line-height:20px}
66715
+ .${terminalClass.listInput}{box-sizing:border-box;min-width:0;height:24px;min-height:24px;flex:1;margin:0 4px;color:inherit;background:var(--dsw-alias-bg-base);border:.5px solid var(--dsw-alias-border-l3);border-radius:var(--dsw-radius-sm,6px);padding:0 6px;font:inherit;font-size:12px;line-height:20px}
66431
66716
  .${terminalClass.listClose}{box-sizing:border-box;width:28px;height:28px;min-height:28px;padding:0;border:0;color:var(--dsw-alias-label-secondary);background:transparent;cursor:pointer;font:inherit;font-size:16px;line-height:20px;flex:none}
66432
66717
  .${terminalClass.listClose}:hover{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-interactive-bg-hover)}
66433
66718
  .${terminalClass.content}{box-sizing:border-box;width:100%;min-width:0;min-height:0;display:flex;flex:1 1 auto;overflow:hidden}