@jingyi0605/codingns 0.3.6 → 0.5.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 (369) hide show
  1. package/README.md +3 -0
  2. package/bin/codingns.mjs +913 -1
  3. package/dist/public/assets/AdaptiveButlerPage-B153lk5H.css +1 -0
  4. package/dist/public/assets/AdaptiveButlerPage-R-XZw7pd.js +3 -0
  5. package/dist/public/assets/App-DUAg5urj.css +1 -0
  6. package/dist/public/assets/App-DkvE5EyM.js +30 -0
  7. package/dist/public/assets/BootstrapPage-Vu5oEJ8z.js +1 -0
  8. package/dist/public/assets/ConversationPage-Cjpg6g0J.js +2 -0
  9. package/dist/public/assets/DesktopDetachPreviewPage-BgeEqbc5.js +1 -0
  10. package/dist/public/assets/DesktopWindowPage-1WelvxdH.js +2 -0
  11. package/dist/public/assets/FileContextPanel-D_ghXJuW.js +1 -0
  12. package/dist/public/assets/GitSidebar-D9f9Jxwr.js +6 -0
  13. package/dist/public/assets/MobileCreateSessionSheet-DLq5qPkx.js +1 -0
  14. package/dist/public/assets/MobileSheet-DLg-gX1t.js +1 -0
  15. package/dist/public/assets/MobileTopHeaderFrame-DArgZI7L.js +1 -0
  16. package/dist/public/assets/MobileWorkspaceSwitcherHeader-0ywJKfBQ.js +1 -0
  17. package/dist/public/assets/ServerSettingsModal-izoYMx9U.js +1 -0
  18. package/dist/public/assets/SessionIndexPage-C5aG8FIv.js +1 -0
  19. package/dist/public/assets/SettingsPage-HJIC-P-4.js +1 -0
  20. package/dist/public/assets/TerminalManagerPanel-DpyUTo9k.js +1 -0
  21. package/dist/public/assets/{TerminalPage-D00S4KM6.js → TerminalPage-CtKXIU0h.js} +19 -19
  22. package/dist/public/assets/TerminalRuntimeFallbackModal-CRhOQOsT.js +1 -0
  23. package/dist/public/assets/ToolFilesPage-DcYPsS-e.js +1 -0
  24. package/dist/public/assets/ToolGitPage-CsPl89ty.js +1 -0
  25. package/dist/public/assets/ToolProcessesPage-D0dvR8xK.js +1 -0
  26. package/dist/public/assets/ToolsHomePage-4fP-KRiv.js +1 -0
  27. package/dist/public/assets/WorkbenchLandingPage-kvlfyxRo.js +1 -0
  28. package/dist/public/assets/WorkbenchLayout-ByFw4eeu.js +3 -0
  29. package/dist/public/assets/WorkbenchModal-Ctob14VR.js +1 -0
  30. package/dist/public/assets/WorkbenchShellRoute-BUITtdAg.css +1 -0
  31. package/dist/public/assets/WorkbenchShellRoute-Kw7JEZI3.js +1 -0
  32. package/dist/public/assets/WorkspaceDebugDetailPage-Com5kEXJ.js +1 -0
  33. package/dist/public/assets/WorkspaceDetailPage-D0Lrx4Uz.js +1 -0
  34. package/dist/public/assets/WorkspaceHomePage-wR8d3aP9.js +1 -0
  35. package/dist/public/assets/butler-records-events-DgWCG364.js +1 -0
  36. package/dist/public/assets/default-session-permission-mode-CcGwR4Kk.js +1 -0
  37. package/dist/public/assets/event-DvH9tcej.js +1 -0
  38. package/dist/public/assets/file-tree-icon-UFVoVzhM.js +31 -0
  39. package/dist/public/assets/index-Byp9hJ0c.js +42 -0
  40. package/dist/public/assets/index-_52jxu4a.css +1 -0
  41. package/dist/public/assets/preferences-service-KIYeE2gk.js +1 -0
  42. package/dist/public/assets/session-runtime-machine-0KNSSPp5.js +17 -0
  43. package/dist/public/assets/styles-BWPBZvze.css +1 -0
  44. package/dist/public/assets/styles-CSUx5LGe.js +1 -0
  45. package/dist/public/assets/terminal-runtime-meta-AWXJpN4r.js +1 -0
  46. package/dist/public/assets/useRegisteredDebugTemplates-DBDRdptr.js +1 -0
  47. package/dist/public/assets/window-BWqRixxq.js +1 -0
  48. package/dist/public/index.html +2 -2
  49. package/dist/server/middlewares/auth-guard.d.ts +4 -0
  50. package/dist/server/middlewares/auth-guard.js +42 -4
  51. package/dist/server/middlewares/auth-guard.js.map +1 -1
  52. package/dist/server/modules/assistant-capability/assistant-capability-controller.d.ts +234 -0
  53. package/dist/server/modules/assistant-capability/assistant-capability-controller.js +365 -0
  54. package/dist/server/modules/assistant-capability/assistant-capability-controller.js.map +1 -1
  55. package/dist/server/modules/assistant-capability/assistant-capability-service.d.ts +262 -2
  56. package/dist/server/modules/assistant-capability/assistant-capability-service.js +737 -3
  57. package/dist/server/modules/assistant-capability/assistant-capability-service.js.map +1 -1
  58. package/dist/server/modules/auth/auth-controller.d.ts +11 -1
  59. package/dist/server/modules/auth/auth-controller.js +61 -2
  60. package/dist/server/modules/auth/auth-controller.js.map +1 -1
  61. package/dist/server/modules/auth/auth-device-display-name.d.ts +10 -0
  62. package/dist/server/modules/auth/auth-device-display-name.js +190 -0
  63. package/dist/server/modules/auth/auth-device-display-name.js.map +1 -0
  64. package/dist/server/modules/auth/auth-service.d.ts +80 -5
  65. package/dist/server/modules/auth/auth-service.js +333 -23
  66. package/dist/server/modules/auth/auth-service.js.map +1 -1
  67. package/dist/server/modules/butler/assistant-automation-service.d.ts +112 -0
  68. package/dist/server/modules/butler/assistant-automation-service.js +832 -0
  69. package/dist/server/modules/butler/assistant-automation-service.js.map +1 -0
  70. package/dist/server/modules/butler/assistant-automation-trigger.d.ts +94 -0
  71. package/dist/server/modules/butler/assistant-automation-trigger.js +400 -0
  72. package/dist/server/modules/butler/assistant-automation-trigger.js.map +1 -0
  73. package/dist/server/modules/butler/assistant-sandbox-cleanup-scheduler.d.ts +32 -0
  74. package/dist/server/modules/butler/assistant-sandbox-cleanup-scheduler.js +93 -0
  75. package/dist/server/modules/butler/assistant-sandbox-cleanup-scheduler.js.map +1 -0
  76. package/dist/server/modules/butler/assistant-sandbox-service.d.ts +69 -0
  77. package/dist/server/modules/butler/assistant-sandbox-service.js +399 -0
  78. package/dist/server/modules/butler/assistant-sandbox-service.js.map +1 -0
  79. package/dist/server/modules/butler/butler-action-context-service.d.ts +4 -1
  80. package/dist/server/modules/butler/butler-action-context-service.js +8 -2
  81. package/dist/server/modules/butler/butler-action-context-service.js.map +1 -1
  82. package/dist/server/modules/butler/butler-auth-service.js +7 -2
  83. package/dist/server/modules/butler/butler-auth-service.js.map +1 -1
  84. package/dist/server/modules/butler/butler-control-session-service.d.ts +11 -1
  85. package/dist/server/modules/butler/butler-control-session-service.js +173 -40
  86. package/dist/server/modules/butler/butler-control-session-service.js.map +1 -1
  87. package/dist/server/modules/butler/butler-control-timer-scheduler.d.ts +32 -0
  88. package/dist/server/modules/butler/butler-control-timer-scheduler.js +93 -0
  89. package/dist/server/modules/butler/butler-control-timer-scheduler.js.map +1 -0
  90. package/dist/server/modules/butler/butler-control-timer-service.d.ts +42 -0
  91. package/dist/server/modules/butler/butler-control-timer-service.js +132 -0
  92. package/dist/server/modules/butler/butler-control-timer-service.js.map +1 -0
  93. package/dist/server/modules/butler/butler-controller.d.ts +42 -2
  94. package/dist/server/modules/butler/butler-controller.js +79 -12
  95. package/dist/server/modules/butler/butler-controller.js.map +1 -1
  96. package/dist/server/modules/butler/butler-follow-up-evaluation-instruction-adapter.d.ts +2 -1
  97. package/dist/server/modules/butler/butler-follow-up-evaluation-instruction-adapter.js +27 -25
  98. package/dist/server/modules/butler/butler-follow-up-evaluation-instruction-adapter.js.map +1 -1
  99. package/dist/server/modules/butler/butler-follow-up-service.d.ts +41 -5
  100. package/dist/server/modules/butler/butler-follow-up-service.js +568 -371
  101. package/dist/server/modules/butler/butler-follow-up-service.js.map +1 -1
  102. package/dist/server/modules/butler/butler-inbox-analysis-service.d.ts +4 -1
  103. package/dist/server/modules/butler/butler-inbox-analysis-service.js +18 -4
  104. package/dist/server/modules/butler/butler-inbox-analysis-service.js.map +1 -1
  105. package/dist/server/modules/butler/butler-inbox-service.js +1 -0
  106. package/dist/server/modules/butler/butler-inbox-service.js.map +1 -1
  107. package/dist/server/modules/butler/butler-profile-service.js +2 -5
  108. package/dist/server/modules/butler/butler-profile-service.js.map +1 -1
  109. package/dist/server/modules/butler/butler-project-service.d.ts +3 -1
  110. package/dist/server/modules/butler/butler-project-service.js +7 -1
  111. package/dist/server/modules/butler/butler-project-service.js.map +1 -1
  112. package/dist/server/modules/butler/butler-session-service.d.ts +5 -1
  113. package/dist/server/modules/butler/butler-session-service.js +26 -1
  114. package/dist/server/modules/butler/butler-session-service.js.map +1 -1
  115. package/dist/server/modules/butler/butler-session-summary-service.js +2 -1
  116. package/dist/server/modules/butler/butler-session-summary-service.js.map +1 -1
  117. package/dist/server/modules/butler/butler-workspace-context.d.ts +4 -1
  118. package/dist/server/modules/butler/butler-workspace-context.js +204 -58
  119. package/dist/server/modules/butler/butler-workspace-context.js.map +1 -1
  120. package/dist/server/modules/butler/patrol-execution-service.js +2 -1
  121. package/dist/server/modules/butler/patrol-execution-service.js.map +1 -1
  122. package/dist/server/modules/butler/provider-adapter-registry.d.ts +3 -0
  123. package/dist/server/modules/butler/provider-adapter-registry.js +18 -1
  124. package/dist/server/modules/butler/provider-adapter-registry.js.map +1 -1
  125. package/dist/server/modules/butler/verification-run-service.d.ts +9 -2
  126. package/dist/server/modules/butler/verification-run-service.js +188 -34
  127. package/dist/server/modules/butler/verification-run-service.js.map +1 -1
  128. package/dist/server/modules/debug-target/debug-target-controller.js +1 -1
  129. package/dist/server/modules/debug-target/debug-target-controller.js.map +1 -1
  130. package/dist/server/modules/debug-target/debug-target-service.d.ts +7 -2
  131. package/dist/server/modules/debug-target/debug-target-service.js +563 -100
  132. package/dist/server/modules/debug-target/debug-target-service.js.map +1 -1
  133. package/dist/server/modules/git/git-command-helper-client.d.ts +1 -0
  134. package/dist/server/modules/git/git-command-helper-client.js +19 -26
  135. package/dist/server/modules/git/git-command-helper-client.js.map +1 -1
  136. package/dist/server/modules/git/git-command-runner.js +19 -1
  137. package/dist/server/modules/git/git-command-runner.js.map +1 -1
  138. package/dist/server/modules/preferences/profile-service.d.ts +3 -1
  139. package/dist/server/modules/preferences/profile-service.js +74 -3
  140. package/dist/server/modules/preferences/profile-service.js.map +1 -1
  141. package/dist/server/modules/provider/provider-controller.d.ts +1 -1
  142. package/dist/server/modules/provider/provider-controller.js.map +1 -1
  143. package/dist/server/modules/provider/provider-discovery-helper-client.d.ts +5 -3
  144. package/dist/server/modules/provider/provider-discovery-helper-client.js +129 -43
  145. package/dist/server/modules/provider/provider-discovery-helper-client.js.map +1 -1
  146. package/dist/server/modules/provider/provider-discovery-helper-process.js +44 -0
  147. package/dist/server/modules/provider/provider-discovery-helper-process.js.map +1 -1
  148. package/dist/server/modules/provider/provider-discovery-runtime.js +83 -3
  149. package/dist/server/modules/provider/provider-discovery-runtime.js.map +1 -1
  150. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-identity-service.d.ts +10 -0
  151. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-identity-service.js +48 -0
  152. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-identity-service.js.map +1 -0
  153. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-packets.d.ts +48 -0
  154. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-packets.js +11 -0
  155. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-packets.js.map +1 -0
  156. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-protocol.d.ts +74 -0
  157. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-protocol.js +302 -0
  158. package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-protocol.js.map +1 -0
  159. package/dist/server/modules/relay-tunnel/relay-tunnel-controller.d.ts +33 -0
  160. package/dist/server/modules/relay-tunnel/relay-tunnel-controller.js +57 -0
  161. package/dist/server/modules/relay-tunnel/relay-tunnel-controller.js.map +1 -0
  162. package/dist/server/modules/relay-tunnel/relay-tunnel-edge-proof.d.ts +9 -0
  163. package/dist/server/modules/relay-tunnel/relay-tunnel-edge-proof.js +25 -0
  164. package/dist/server/modules/relay-tunnel/relay-tunnel-edge-proof.js.map +1 -0
  165. package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.d.ts +18 -0
  166. package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.js +230 -0
  167. package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.js.map +1 -0
  168. package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.d.ts +41 -0
  169. package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.js +443 -0
  170. package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.js.map +1 -0
  171. package/dist/server/modules/relay-tunnel/relay-tunnel-service.d.ts +111 -0
  172. package/dist/server/modules/relay-tunnel/relay-tunnel-service.js +771 -0
  173. package/dist/server/modules/relay-tunnel/relay-tunnel-service.js.map +1 -0
  174. package/dist/server/modules/sessions/claude-runtime-helper-client.js +23 -1
  175. package/dist/server/modules/sessions/claude-runtime-helper-client.js.map +1 -1
  176. package/dist/server/modules/sessions/codex-app-server-helper-client.d.ts +2 -1
  177. package/dist/server/modules/sessions/codex-app-server-helper-client.js +78 -0
  178. package/dist/server/modules/sessions/codex-app-server-helper-client.js.map +1 -1
  179. package/dist/server/modules/sessions/codex-app-server-helper-process.js +84 -2
  180. package/dist/server/modules/sessions/codex-app-server-helper-process.js.map +1 -1
  181. package/dist/server/modules/sessions/provider-session-delete-cli.d.ts +15 -0
  182. package/dist/server/modules/sessions/provider-session-delete-cli.js +148 -0
  183. package/dist/server/modules/sessions/provider-session-delete-cli.js.map +1 -0
  184. package/dist/server/modules/sessions/session-controller.d.ts +4 -1
  185. package/dist/server/modules/sessions/session-controller.js +4 -0
  186. package/dist/server/modules/sessions/session-controller.js.map +1 -1
  187. package/dist/server/modules/sessions/session-history-service.d.ts +24 -1
  188. package/dist/server/modules/sessions/session-history-service.js +401 -42
  189. package/dist/server/modules/sessions/session-history-service.js.map +1 -1
  190. package/dist/server/modules/sessions/session-live-runtime-router-service.d.ts +25 -0
  191. package/dist/server/modules/sessions/session-live-runtime-router-service.js +42 -0
  192. package/dist/server/modules/sessions/session-live-runtime-router-service.js.map +1 -0
  193. package/dist/server/modules/sessions/session-live-runtime-service.d.ts +6 -0
  194. package/dist/server/modules/sessions/session-live-runtime-service.js +130 -28
  195. package/dist/server/modules/sessions/session-live-runtime-service.js.map +1 -1
  196. package/dist/server/modules/sessions/session-message-attachment-service.d.ts +1 -0
  197. package/dist/server/modules/sessions/session-message-attachment-service.js +22 -0
  198. package/dist/server/modules/sessions/session-message-attachment-service.js.map +1 -1
  199. package/dist/server/modules/sessions/session-message-origin-utils.d.ts +12 -0
  200. package/dist/server/modules/sessions/session-message-origin-utils.js +45 -0
  201. package/dist/server/modules/sessions/session-message-origin-utils.js.map +1 -0
  202. package/dist/server/modules/sessions/session-permission-request-service.d.ts +1 -0
  203. package/dist/server/modules/sessions/session-permission-request-service.js +367 -5
  204. package/dist/server/modules/sessions/session-permission-request-service.js.map +1 -1
  205. package/dist/server/modules/sessions/session-provider-error-mapper.js +32 -0
  206. package/dist/server/modules/sessions/session-provider-error-mapper.js.map +1 -1
  207. package/dist/server/modules/sessions/session-provider-usage-guard-service.d.ts +37 -0
  208. package/dist/server/modules/sessions/session-provider-usage-guard-service.js +179 -0
  209. package/dist/server/modules/sessions/session-provider-usage-guard-service.js.map +1 -0
  210. package/dist/server/modules/sessions/session-provider-usage-limit.d.ts +17 -0
  211. package/dist/server/modules/sessions/session-provider-usage-limit.js +465 -0
  212. package/dist/server/modules/sessions/session-provider-usage-limit.js.map +1 -0
  213. package/dist/server/modules/skills/assistant-runtime-skill-catalog.d.ts +8 -0
  214. package/dist/server/modules/skills/assistant-runtime-skill-catalog.js +26 -0
  215. package/dist/server/modules/skills/assistant-runtime-skill-catalog.js.map +1 -0
  216. package/dist/server/modules/skills/assistant-runtime-skill-cleanup.d.ts +9 -0
  217. package/dist/server/modules/skills/assistant-runtime-skill-cleanup.js +55 -0
  218. package/dist/server/modules/skills/assistant-runtime-skill-cleanup.js.map +1 -0
  219. package/dist/server/modules/skills/builtin-skill-service.js +1 -6
  220. package/dist/server/modules/skills/builtin-skill-service.js.map +1 -1
  221. package/dist/server/modules/skills/builtin-skills/codingns-assistant/SKILL.md +19 -12
  222. package/dist/server/modules/skills/builtin-skills/codingns-assistant/references/cli-workflow.md +9 -3
  223. package/dist/server/modules/skills/skill-controller.d.ts +2 -2
  224. package/dist/server/modules/skills/skill-controller.js +9 -1
  225. package/dist/server/modules/skills/skill-controller.js.map +1 -1
  226. package/dist/server/modules/skills/skill-manager-service.d.ts +26 -1
  227. package/dist/server/modules/skills/skill-manager-service.js +346 -90
  228. package/dist/server/modules/skills/skill-manager-service.js.map +1 -1
  229. package/dist/server/modules/skills/skill-name-policy.d.ts +2 -0
  230. package/dist/server/modules/skills/skill-name-policy.js +10 -0
  231. package/dist/server/modules/skills/skill-name-policy.js.map +1 -0
  232. package/dist/server/modules/tailscale/tailscale-service.d.ts +2 -0
  233. package/dist/server/modules/tailscale/tailscale-service.js +21 -8
  234. package/dist/server/modules/tailscale/tailscale-service.js.map +1 -1
  235. package/dist/server/modules/tasks/task-helper-client.d.ts +5 -2
  236. package/dist/server/modules/tasks/task-helper-client.js +118 -38
  237. package/dist/server/modules/tasks/task-helper-client.js.map +1 -1
  238. package/dist/server/modules/tasks/task-helper-process.js +94 -3
  239. package/dist/server/modules/tasks/task-helper-process.js.map +1 -1
  240. package/dist/server/modules/tasks/task-types.d.ts +6 -0
  241. package/dist/server/modules/tasks/task-types.js +7 -1
  242. package/dist/server/modules/tasks/task-types.js.map +1 -1
  243. package/dist/server/modules/terminal/command-template-service.d.ts +9 -0
  244. package/dist/server/modules/terminal/command-template-service.js +87 -5
  245. package/dist/server/modules/terminal/command-template-service.js.map +1 -1
  246. package/dist/server/modules/terminal/template-reverse-proxy-service.js +71 -3
  247. package/dist/server/modules/terminal/template-reverse-proxy-service.js.map +1 -1
  248. package/dist/server/modules/terminal/terminal-controller.d.ts +3 -0
  249. package/dist/server/modules/terminal/terminal-controller.js +41 -0
  250. package/dist/server/modules/terminal/terminal-controller.js.map +1 -1
  251. package/dist/server/modules/workbench/workbench-service.d.ts +3 -0
  252. package/dist/server/modules/workbench/workbench-service.js +4 -3
  253. package/dist/server/modules/workbench/workbench-service.js.map +1 -1
  254. package/dist/server/modules/workbench/workspace-file-watcher.d.ts +14 -6
  255. package/dist/server/modules/workbench/workspace-file-watcher.js +267 -57
  256. package/dist/server/modules/workbench/workspace-file-watcher.js.map +1 -1
  257. package/dist/server/modules/workbench/workspace-panel-snapshot-service.d.ts +2 -0
  258. package/dist/server/modules/workbench/workspace-panel-snapshot-service.js +32 -3
  259. package/dist/server/modules/workbench/workspace-panel-snapshot-service.js.map +1 -1
  260. package/dist/server/modules/worktree/worktree-manager.d.ts +9 -1
  261. package/dist/server/modules/worktree/worktree-manager.js +9 -1
  262. package/dist/server/modules/worktree/worktree-manager.js.map +1 -1
  263. package/dist/server/routes/assistant.js +49 -0
  264. package/dist/server/routes/assistant.js.map +1 -1
  265. package/dist/server/routes/auth.js +4 -0
  266. package/dist/server/routes/auth.js.map +1 -1
  267. package/dist/server/routes/butler.js +5 -0
  268. package/dist/server/routes/butler.js.map +1 -1
  269. package/dist/server/routes/sessions.js +1 -0
  270. package/dist/server/routes/sessions.js.map +1 -1
  271. package/dist/server/routes/system.d.ts +2 -1
  272. package/dist/server/routes/system.js +13 -1
  273. package/dist/server/routes/system.js.map +1 -1
  274. package/dist/server/server/create-server.d.ts +18 -0
  275. package/dist/server/server/create-server.js +113 -20
  276. package/dist/server/server/create-server.js.map +1 -1
  277. package/dist/server/shared/utils/tokens.d.ts +3 -1
  278. package/dist/server/shared/utils/tokens.js +9 -2
  279. package/dist/server/shared/utils/tokens.js.map +1 -1
  280. package/dist/server/storage/repositories/assistant-automation-run-repository.d.ts +12 -0
  281. package/dist/server/storage/repositories/assistant-automation-run-repository.js +139 -0
  282. package/dist/server/storage/repositories/assistant-automation-run-repository.js.map +1 -0
  283. package/dist/server/storage/repositories/assistant-automation-task-repository.d.ts +17 -0
  284. package/dist/server/storage/repositories/assistant-automation-task-repository.js +179 -0
  285. package/dist/server/storage/repositories/assistant-automation-task-repository.js.map +1 -0
  286. package/dist/server/storage/repositories/assistant-sandbox-workspace-repository.d.ts +18 -0
  287. package/dist/server/storage/repositories/assistant-sandbox-workspace-repository.js +191 -0
  288. package/dist/server/storage/repositories/assistant-sandbox-workspace-repository.js.map +1 -0
  289. package/dist/server/storage/repositories/auth-device-repository.d.ts +22 -0
  290. package/dist/server/storage/repositories/auth-device-repository.js +97 -0
  291. package/dist/server/storage/repositories/auth-device-repository.js.map +1 -0
  292. package/dist/server/storage/repositories/auth-device-session-repository.d.ts +17 -0
  293. package/dist/server/storage/repositories/auth-device-session-repository.js +82 -0
  294. package/dist/server/storage/repositories/auth-device-session-repository.js.map +1 -0
  295. package/dist/server/storage/repositories/auth-login-event-repository.d.ts +9 -0
  296. package/dist/server/storage/repositories/auth-login-event-repository.js +53 -0
  297. package/dist/server/storage/repositories/auth-login-event-repository.js.map +1 -0
  298. package/dist/server/storage/repositories/auth-token-repository.d.ts +4 -0
  299. package/dist/server/storage/repositories/auth-token-repository.js +58 -5
  300. package/dist/server/storage/repositories/auth-token-repository.js.map +1 -1
  301. package/dist/server/storage/repositories/butler-control-session-repository.js +27 -3
  302. package/dist/server/storage/repositories/butler-control-session-repository.js.map +1 -1
  303. package/dist/server/storage/repositories/butler-control-timer-repository.d.ts +15 -0
  304. package/dist/server/storage/repositories/butler-control-timer-repository.js +157 -0
  305. package/dist/server/storage/repositories/butler-control-timer-repository.js.map +1 -0
  306. package/dist/server/storage/repositories/butler-follow-up-task-repository.js +21 -3
  307. package/dist/server/storage/repositories/butler-follow-up-task-repository.js.map +1 -1
  308. package/dist/server/storage/repositories/instance-relay-tunnel-identity-repository.d.ts +8 -0
  309. package/dist/server/storage/repositories/instance-relay-tunnel-identity-repository.js +52 -0
  310. package/dist/server/storage/repositories/instance-relay-tunnel-identity-repository.js.map +1 -0
  311. package/dist/server/storage/repositories/instance-relay-tunnel-repository.d.ts +10 -0
  312. package/dist/server/storage/repositories/instance-relay-tunnel-repository.js +153 -0
  313. package/dist/server/storage/repositories/instance-relay-tunnel-repository.js.map +1 -0
  314. package/dist/server/storage/repositories/instance-tailscale-repository.js +6 -3
  315. package/dist/server/storage/repositories/instance-tailscale-repository.js.map +1 -1
  316. package/dist/server/storage/repositories/managed-skill-repository.d.ts +2 -1
  317. package/dist/server/storage/repositories/managed-skill-repository.js +14 -4
  318. package/dist/server/storage/repositories/managed-skill-repository.js.map +1 -1
  319. package/dist/server/storage/repositories/session-message-attachment-repository.d.ts +2 -0
  320. package/dist/server/storage/repositories/session-message-attachment-repository.js +24 -0
  321. package/dist/server/storage/repositories/session-message-attachment-repository.js.map +1 -1
  322. package/dist/server/storage/repositories/user-preference-profile-repository.js +6 -3
  323. package/dist/server/storage/repositories/user-preference-profile-repository.js.map +1 -1
  324. package/dist/server/storage/sqlite/client.js +534 -2
  325. package/dist/server/storage/sqlite/client.js.map +1 -1
  326. package/dist/server/storage/sqlite/schema.sql +228 -4
  327. package/dist/server/types/domain.d.ts +170 -2
  328. package/dist/server/ws/workbench-ws-hub.d.ts +14 -8
  329. package/dist/server/ws/workbench-ws-hub.js +369 -209
  330. package/dist/server/ws/workbench-ws-hub.js.map +1 -1
  331. package/dist/server/ws/ws-auth-guard.js +1 -4
  332. package/dist/server/ws/ws-auth-guard.js.map +1 -1
  333. package/dist/server/ws/ws-server.d.ts +1 -1
  334. package/dist/server/ws/ws-server.js.map +1 -1
  335. package/node_modules/@codingns/session-sync-core/dist/codex-resume-history.d.ts +1 -0
  336. package/node_modules/@codingns/session-sync-core/dist/codex-resume-history.js +80 -0
  337. package/node_modules/@codingns/session-sync-core/dist/codex-resume-history.js.map +1 -0
  338. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.d.ts +5 -1
  339. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js +122 -4
  340. package/node_modules/@codingns/session-sync-core/dist/providers/claude-code.js.map +1 -1
  341. package/node_modules/@codingns/session-sync-core/dist/providers/codex.d.ts +17 -1
  342. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js +437 -51
  343. package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +1 -1
  344. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.d.ts +7 -1
  345. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js +240 -27
  346. package/node_modules/@codingns/session-sync-core/dist/providers/gemini.js.map +1 -1
  347. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.d.ts +5 -1
  348. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js +108 -2
  349. package/node_modules/@codingns/session-sync-core/dist/providers/kimi.js.map +1 -1
  350. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.d.ts +3 -0
  351. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js +101 -8
  352. package/node_modules/@codingns/session-sync-core/dist/providers/opencode.js.map +1 -1
  353. package/node_modules/@codingns/session-sync-core/dist/providers/utils.d.ts +1 -0
  354. package/node_modules/@codingns/session-sync-core/dist/providers/utils.js +4 -1
  355. package/node_modules/@codingns/session-sync-core/dist/providers/utils.js.map +1 -1
  356. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js +44 -0
  357. package/node_modules/@codingns/session-sync-core/dist/runtime/claude-runtime.js.map +1 -1
  358. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.d.ts +5 -1
  359. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +153 -60
  360. package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -1
  361. package/node_modules/@codingns/session-sync-core/dist/runtime/types.d.ts +1 -0
  362. package/node_modules/@codingns/session-sync-core/dist/services.d.ts +1 -0
  363. package/node_modules/@codingns/session-sync-core/dist/services.js +24 -8
  364. package/node_modules/@codingns/session-sync-core/dist/services.js.map +1 -1
  365. package/node_modules/@codingns/session-sync-core/dist/types.d.ts +6 -0
  366. package/package.json +1 -1
  367. package/scripts/postinstall.mjs +0 -33
  368. package/dist/public/assets/index-BlOinYqR.js +0 -122
  369. package/dist/public/assets/index-Dg_7g6lA.css +0 -1
@@ -1,8 +1,10 @@
1
1
  import { AppError } from "../shared/errors/app-error.js";
2
2
  import { logTerminalDebug, terminalDebugNowMs } from "../shared/utils/terminal-debug-log.js";
3
3
  const WORKBENCH_REFRESH_INTERVAL_MS = 60_000;
4
- const SIDEBAR_REFRESH_INTERVAL_MS = 5_000;
5
4
  const GIT_SUBSCRIPTION_MIN_REFRESH_INTERVAL_MS = 15_000;
5
+ const GIT_REFRESH_QUIET_WINDOW_MS = 800;
6
+ const TERMINAL_MANAGER_REFRESH_QUIET_WINDOW_MS = 300;
7
+ const WORKSPACE_MANAGEMENT_REFRESH_INTERVAL_MS = 5_000;
6
8
  const WORKBENCH_REALTIME_BROADCAST_DEBOUNCE_MS = 120;
7
9
  const WORKSPACE_MANAGEMENT_TIMER_REFRESH_ENABLED = readBooleanEnv(process.env.CODINGNS_WORKSPACE_MANAGEMENT_AUTO_REFRESH, false);
8
10
  export class WorkbenchWsHub {
@@ -15,12 +17,18 @@ export class WorkbenchWsHub {
15
17
  clientGitSubscriptions = new WeakMap();
16
18
  clientTerminalManagerSubscriptions = new WeakMap();
17
19
  clientWorkspaceManagementSubscriptions = new WeakMap();
18
- constructor(workbenchService, workspacePanelSnapshotService, fileWatcher) {
20
+ constructor(workbenchService, workspacePanelSnapshotService, fileWatcher, terminalService) {
19
21
  this.workbenchService = workbenchService;
20
22
  this.workspacePanelSnapshotService = workspacePanelSnapshotService;
21
23
  this.fileWatcher = fileWatcher;
22
- this.fileWatcher.setOnChange((workspaceId) => {
23
- this.handleWorkspaceFileChange(workspaceId);
24
+ this.fileWatcher.setOnChange((event) => {
25
+ this.handleWorkspaceWatcherChange(event);
26
+ });
27
+ terminalService?.on("status", (terminal) => {
28
+ this.handleTerminalManagerChange(terminal.workspaceId);
29
+ });
30
+ terminalService?.on("exit", ({ terminal }) => {
31
+ this.handleTerminalManagerChange(terminal.workspaceId);
24
32
  });
25
33
  }
26
34
  handleMessage(client, payload, authContext) {
@@ -31,85 +39,78 @@ export class WorkbenchWsHub {
31
39
  const userId = authContext.user.userId;
32
40
  const channel = this.getOrCreateChannel(userId);
33
41
  this.attachClient(client, userId, channel);
34
- switch (message.type) {
35
- case "workbench.subscribe":
36
- void this.sendWorkbenchSnapshotToClient(client, userId, channel);
37
- return true;
38
- case "workbench.refresh":
39
- void this.syncTitlesAndBroadcast(userId);
40
- void this.refreshAndBroadcast(userId, true);
41
- return true;
42
- case "fileTree.subscribe":
43
- this.clientFileTreeSubscriptions.set(client, {
44
- workspaceId: message.workspaceId.trim(),
45
- paths: normalizePanelPaths(message.paths),
46
- lastPayloadByPath: new Map()
47
- });
48
- this.fileWatcher.subscribe(message.workspaceId.trim());
49
- void this.refreshFileTreeSubscriptions(client);
50
- return true;
51
- case "fileTree.refresh":
52
- for (const path of normalizePanelPaths(message.paths)) {
53
- this.workspacePanelSnapshotService.invalidateFileTree(message.workspaceId.trim(), path);
54
- }
55
- this.ensureFileTreeSubscription(client, message.workspaceId, message.paths);
56
- void this.refreshFileTreeSubscriptions(client, true);
57
- return true;
58
- case "git.subscribe":
59
- this.clientGitSubscriptions.set(client, {
60
- workspaceId: message.workspaceId.trim(),
61
- lastPayload: null,
62
- lastRequestedAt: 0,
63
- refreshTask: null,
64
- refreshController: null
65
- });
66
- this.fileWatcher.subscribe(message.workspaceId.trim());
67
- void this.refreshGitSubscription(client);
68
- return true;
69
- case "git.refresh":
70
- this.workspacePanelSnapshotService.invalidateGit(message.workspaceId.trim());
71
- this.abortGitRefresh(client, "git subscription replaced");
72
- this.clientGitSubscriptions.set(client, {
73
- workspaceId: message.workspaceId.trim(),
74
- lastPayload: null,
75
- lastRequestedAt: 0,
76
- refreshTask: null,
77
- refreshController: null
78
- });
79
- void this.refreshGitSubscription(client, true);
80
- return true;
81
- case "terminalManager.subscribe":
82
- this.clientTerminalManagerSubscriptions.set(client, {
83
- workspaceId: message.workspaceId.trim(),
84
- lastPayload: null
85
- });
86
- void this.refreshTerminalManagerSubscription(client);
87
- return true;
88
- case "terminalManager.refresh":
89
- this.workspacePanelSnapshotService.invalidateTerminalManager(message.workspaceId.trim());
90
- this.clientTerminalManagerSubscriptions.set(client, {
91
- workspaceId: message.workspaceId.trim(),
92
- lastPayload: null
93
- });
94
- void this.refreshTerminalManagerSubscription(client, true);
95
- return true;
96
- case "workspaceManagement.subscribe":
97
- this.clientWorkspaceManagementSubscriptions.set(client, {
98
- workspaceId: message.workspaceId.trim(),
99
- lastPayload: null
100
- });
101
- void this.refreshWorkspaceManagementSubscription(client);
102
- return true;
103
- case "workspaceManagement.refresh":
104
- this.workspacePanelSnapshotService.invalidateWorkspaceManagement(message.workspaceId.trim());
105
- this.clientWorkspaceManagementSubscriptions.set(client, {
106
- workspaceId: message.workspaceId.trim(),
107
- lastPayload: null
108
- });
109
- void this.refreshWorkspaceManagementSubscription(client, true);
110
- return true;
111
- default:
112
- return false;
42
+ try {
43
+ switch (message.type) {
44
+ case "workbench.subscribe":
45
+ void this.sendWorkbenchSnapshotToClient(client, userId, channel);
46
+ if (this.workbenchService.shouldRefreshSnapshot()) {
47
+ this.workbenchService.scheduleSnapshotRefresh(userId);
48
+ }
49
+ return true;
50
+ case "workbench.refresh":
51
+ void this.refreshAndBroadcast(userId, true);
52
+ return true;
53
+ case "fileTree.subscribe":
54
+ this.replaceFileTreeSubscription(client, message.workspaceId, message.paths);
55
+ void this.refreshFileTreeSubscriptions(client);
56
+ return true;
57
+ case "fileTree.refresh":
58
+ for (const path of normalizePanelPaths(message.paths)) {
59
+ this.workspacePanelSnapshotService.invalidateFileTree(message.workspaceId.trim(), path);
60
+ }
61
+ this.ensureFileTreeSubscription(client, message.workspaceId, message.paths);
62
+ void this.refreshFileTreeSubscriptions(client, true);
63
+ return true;
64
+ case "git.subscribe":
65
+ this.ensureGitSubscription(client, message.workspaceId);
66
+ void this.refreshGitSubscription(client, false, {
67
+ deliverIfUnchanged: true,
68
+ ignoreMinInterval: true
69
+ });
70
+ return true;
71
+ case "git.refresh":
72
+ this.workspacePanelSnapshotService.invalidateGit(message.workspaceId.trim());
73
+ this.ensureGitSubscription(client, message.workspaceId);
74
+ this.scheduleGitRefresh(client, {
75
+ force: true
76
+ });
77
+ return true;
78
+ case "terminalManager.subscribe":
79
+ this.ensureTerminalManagerSubscription(client, message.workspaceId);
80
+ this.scheduleTerminalManagerRefresh(client);
81
+ return true;
82
+ case "terminalManager.refresh":
83
+ this.workspacePanelSnapshotService.invalidateTerminalManager(message.workspaceId.trim());
84
+ this.ensureTerminalManagerSubscription(client, message.workspaceId);
85
+ this.scheduleTerminalManagerRefresh(client, {
86
+ force: true
87
+ });
88
+ return true;
89
+ case "workspaceManagement.subscribe":
90
+ this.clientWorkspaceManagementSubscriptions.set(client, {
91
+ workspaceId: message.workspaceId.trim(),
92
+ lastPayload: null
93
+ });
94
+ void this.refreshWorkspaceManagementSubscription(client);
95
+ return true;
96
+ case "workspaceManagement.refresh":
97
+ this.workspacePanelSnapshotService.invalidateWorkspaceManagement(message.workspaceId.trim());
98
+ this.clientWorkspaceManagementSubscriptions.set(client, {
99
+ workspaceId: message.workspaceId.trim(),
100
+ lastPayload: null
101
+ });
102
+ void this.refreshWorkspaceManagementSubscription(client, true);
103
+ return true;
104
+ default:
105
+ return false;
106
+ }
107
+ }
108
+ catch (error) {
109
+ this.reportAsyncError("handleMessage", error, {
110
+ userId,
111
+ workspaceId: extractWorkspaceIdFromWorkbenchMessage(message)
112
+ });
113
+ return true;
113
114
  }
114
115
  }
115
116
  cleanupClient(client) {
@@ -127,12 +128,19 @@ export class WorkbenchWsHub {
127
128
  // 文件监听器引用计数递减
128
129
  const fileTreeSub = this.clientFileTreeSubscriptions.get(client);
129
130
  if (fileTreeSub) {
130
- this.fileWatcher.unsubscribe(fileTreeSub.workspaceId);
131
+ this.fileWatcher.unsubscribeFileTree(fileTreeSub.workspaceId, fileTreeSub.paths);
131
132
  }
132
133
  const gitSub = this.clientGitSubscriptions.get(client);
133
134
  if (gitSub) {
134
135
  gitSub.refreshController?.abort(new Error("git subscription closed"));
135
- this.fileWatcher.unsubscribe(gitSub.workspaceId);
136
+ if (gitSub.refreshTimer) {
137
+ clearTimeout(gitSub.refreshTimer);
138
+ }
139
+ this.fileWatcher.unsubscribeGit(gitSub.workspaceId);
140
+ }
141
+ const terminalManagerSub = this.clientTerminalManagerSubscriptions.get(client);
142
+ if (terminalManagerSub?.refreshTimer) {
143
+ clearTimeout(terminalManagerSub.refreshTimer);
136
144
  }
137
145
  this.clientFileTreeSubscriptions.delete(client);
138
146
  this.clientGitSubscriptions.delete(client);
@@ -144,8 +152,8 @@ export class WorkbenchWsHub {
144
152
  if (channel.workbenchTimer) {
145
153
  clearInterval(channel.workbenchTimer);
146
154
  }
147
- if (channel.sidebarTimer) {
148
- clearInterval(channel.sidebarTimer);
155
+ if (channel.workspaceManagementTimer) {
156
+ clearInterval(channel.workspaceManagementTimer);
149
157
  }
150
158
  if (channel.realtimeBroadcastTimer) {
151
159
  clearTimeout(channel.realtimeBroadcastTimer);
@@ -208,22 +216,42 @@ export class WorkbenchWsHub {
208
216
  channel.clients.add(client);
209
217
  this.clientUsers.set(client, userId);
210
218
  }
211
- /**
212
- * 文件变化回调:chokidar 检测到工作区文件变化后,失效缓存并推送更新给订阅了该工作区的客户端。
213
- */
214
- handleWorkspaceFileChange(workspaceId) {
215
- this.workspacePanelSnapshotService.invalidateFileTree(workspaceId);
216
- this.workspacePanelSnapshotService.invalidateGit(workspaceId);
219
+ handleWorkspaceWatcherChange(event) {
220
+ if (event.scope === "fileTree") {
221
+ this.workspacePanelSnapshotService.invalidateFileTree(event.workspaceId);
222
+ this.workspacePanelSnapshotService.invalidateGit(event.workspaceId);
223
+ }
224
+ else {
225
+ this.workspacePanelSnapshotService.invalidateGit(event.workspaceId);
226
+ }
217
227
  for (const [, channel] of this.userChannels) {
218
228
  for (const client of channel.clients) {
219
229
  const fileTreeSub = this.clientFileTreeSubscriptions.get(client);
220
- if (fileTreeSub && fileTreeSub.workspaceId === workspaceId) {
230
+ if (event.scope === "fileTree" &&
231
+ fileTreeSub &&
232
+ fileTreeSub.workspaceId === event.workspaceId) {
221
233
  void this.refreshFileTreeSubscriptions(client, true);
222
234
  }
223
235
  const gitSub = this.clientGitSubscriptions.get(client);
224
- if (gitSub && gitSub.workspaceId === workspaceId) {
225
- void this.refreshGitSubscription(client, true);
236
+ if (gitSub && gitSub.workspaceId === event.workspaceId) {
237
+ this.scheduleGitRefresh(client, {
238
+ quietWindowMs: GIT_REFRESH_QUIET_WINDOW_MS
239
+ });
240
+ }
241
+ }
242
+ }
243
+ }
244
+ handleTerminalManagerChange(workspaceId) {
245
+ this.workspacePanelSnapshotService.invalidateTerminalManager(workspaceId);
246
+ for (const [, channel] of this.userChannels) {
247
+ for (const client of channel.clients) {
248
+ const subscription = this.clientTerminalManagerSubscriptions.get(client);
249
+ if (!subscription || subscription.workspaceId !== workspaceId) {
250
+ continue;
226
251
  }
252
+ this.scheduleTerminalManagerRefresh(client, {
253
+ quietWindowMs: TERMINAL_MANAGER_REFRESH_QUIET_WINDOW_MS
254
+ });
227
255
  }
228
256
  }
229
257
  }
@@ -236,12 +264,11 @@ export class WorkbenchWsHub {
236
264
  clients: new Set(),
237
265
  lastWorkbenchPayload: null,
238
266
  workbenchTimer: null,
239
- sidebarTimer: null,
267
+ workspaceManagementTimer: null,
240
268
  realtimeBroadcastTimer: null,
241
269
  realtimeBroadcastQueued: false,
242
270
  realtimeBroadcastTask: null,
243
- refreshTask: null,
244
- titleSyncTask: null
271
+ refreshTask: null
245
272
  };
246
273
  channel.workbenchTimer = setInterval(() => {
247
274
  if (!this.workbenchService.shouldRefreshSnapshot()) {
@@ -251,47 +278,16 @@ export class WorkbenchWsHub {
251
278
  this.reportAsyncError("workbenchTimer", error, { userId });
252
279
  });
253
280
  }, WORKBENCH_REFRESH_INTERVAL_MS);
254
- channel.sidebarTimer = setInterval(() => {
255
- void this.refreshSidebarSubscriptions(userId).catch((error) => {
256
- this.reportAsyncError("sidebarTimer", error, { userId });
257
- });
258
- }, SIDEBAR_REFRESH_INTERVAL_MS);
281
+ if (WORKSPACE_MANAGEMENT_TIMER_REFRESH_ENABLED) {
282
+ channel.workspaceManagementTimer = setInterval(() => {
283
+ void this.refreshWorkspaceManagementSubscriptions(userId).catch((error) => {
284
+ this.reportAsyncError("workspaceManagementTimer", error, { userId });
285
+ });
286
+ }, WORKSPACE_MANAGEMENT_REFRESH_INTERVAL_MS);
287
+ }
259
288
  this.userChannels.set(userId, channel);
260
289
  return channel;
261
290
  }
262
- async syncTitlesAndBroadcast(userId) {
263
- const channel = this.getOrCreateChannel(userId);
264
- if (channel.titleSyncTask) {
265
- return channel.titleSyncTask;
266
- }
267
- channel.titleSyncTask = (async () => {
268
- const startedAtMs = terminalDebugNowMs();
269
- try {
270
- const snapshot = await this.workbenchService
271
- .scheduleSessionTitleSync(userId, "workbench_ws.sync_titles")
272
- .promise;
273
- const payload = buildWorkbenchPayload(snapshot);
274
- if (payload === channel.lastWorkbenchPayload) {
275
- return;
276
- }
277
- channel.lastWorkbenchPayload = payload;
278
- for (const client of channel.clients) {
279
- client.send(payload);
280
- }
281
- logTerminalDebug("workbench.sync_titles.completed", {
282
- userId,
283
- clientCount: channel.clients.size,
284
- durationMs: terminalDebugNowMs() - startedAtMs
285
- });
286
- }
287
- catch (error) {
288
- this.reportAsyncError("syncTitlesAndBroadcast", error, { userId });
289
- }
290
- })().finally(() => {
291
- channel.titleSyncTask = null;
292
- });
293
- return channel.titleSyncTask;
294
- }
295
291
  async sendWorkbenchSnapshotToClient(client, userId, channel) {
296
292
  try {
297
293
  const payload = buildWorkbenchPayload(this.workbenchService.getSnapshot(userId));
@@ -338,48 +334,30 @@ export class WorkbenchWsHub {
338
334
  });
339
335
  return channel.refreshTask;
340
336
  }
341
- async refreshSidebarSubscriptions(userId) {
342
- const channel = this.userChannels.get(userId);
343
- if (!channel) {
344
- return;
345
- }
346
- const startedAtMs = terminalDebugNowMs();
347
- await Promise.all([...channel.clients].map(async (client) => {
348
- const refreshTasks = [
349
- this.refreshGitSubscription(client),
350
- this.refreshTerminalManagerSubscription(client)
351
- ];
352
- if (WORKSPACE_MANAGEMENT_TIMER_REFRESH_ENABLED) {
353
- refreshTasks.push(this.refreshWorkspaceManagementSubscription(client));
354
- }
355
- await Promise.allSettled(refreshTasks);
356
- }));
357
- logTerminalDebug("workbench.sidebar_refresh.completed", {
358
- userId,
359
- clientCount: channel.clients.size,
360
- durationMs: terminalDebugNowMs() - startedAtMs
361
- });
362
- }
363
337
  ensureFileTreeSubscription(client, workspaceId, paths) {
364
338
  const current = this.clientFileTreeSubscriptions.get(client);
365
339
  const normalizedWorkspaceId = workspaceId.trim();
366
340
  const normalizedPaths = normalizePanelPaths(paths);
367
- if (!current || current.workspaceId !== normalizedWorkspaceId) {
368
- const next = {
369
- workspaceId: normalizedWorkspaceId,
370
- paths: normalizedPaths,
371
- lastPayloadByPath: new Map()
372
- };
373
- this.clientFileTreeSubscriptions.set(client, next);
374
- return next;
375
- }
376
- if (normalizedPaths.length > 0) {
377
- current.paths = normalizedPaths;
378
- }
379
- if (current.paths.length === 0) {
380
- current.paths = [""];
341
+ const nextPaths = normalizedPaths.length > 0 ? normalizedPaths : [""];
342
+ if (current &&
343
+ current.workspaceId === normalizedWorkspaceId &&
344
+ areStringArraysEqual(current.paths, nextPaths)) {
345
+ return current;
346
+ }
347
+ const next = {
348
+ workspaceId: normalizedWorkspaceId,
349
+ paths: nextPaths,
350
+ lastPayloadByPath: new Map()
351
+ };
352
+ this.fileWatcher.subscribeFileTree(normalizedWorkspaceId, nextPaths);
353
+ this.clientFileTreeSubscriptions.set(client, next);
354
+ if (current) {
355
+ this.fileWatcher.unsubscribeFileTree(current.workspaceId, current.paths);
381
356
  }
382
- return current;
357
+ return next;
358
+ }
359
+ replaceFileTreeSubscription(client, workspaceId, paths) {
360
+ return this.ensureFileTreeSubscription(client, workspaceId, paths);
383
361
  }
384
362
  async refreshFileTreeSubscriptions(client, force = false) {
385
363
  const subscription = this.clientFileTreeSubscriptions.get(client);
@@ -405,21 +383,30 @@ export class WorkbenchWsHub {
405
383
  });
406
384
  }
407
385
  }
408
- async refreshGitSubscription(client, force = false) {
386
+ async refreshGitSubscription(client, force = false, options) {
409
387
  const subscription = this.clientGitSubscriptions.get(client);
410
388
  if (!subscription) {
411
389
  return;
412
390
  }
413
391
  if (subscription.refreshTask) {
414
- if (!force) {
392
+ subscription.queuedRefresh = true;
393
+ subscription.queuedForce = subscription.queuedForce || force;
394
+ if (!options?.deliverIfUnchanged) {
415
395
  return subscription.refreshTask;
416
396
  }
417
- subscription.refreshController?.abort(new Error("git subscription superseded"));
418
- await subscription.refreshTask;
397
+ return await subscription.refreshTask.finally(() => {
398
+ if (subscription.lastPayload) {
399
+ client.send(subscription.lastPayload);
400
+ }
401
+ });
419
402
  }
420
403
  const now = Date.now();
421
- if (!force
404
+ if (!options?.ignoreMinInterval &&
405
+ !force
422
406
  && now - subscription.lastRequestedAt < GIT_SUBSCRIPTION_MIN_REFRESH_INTERVAL_MS) {
407
+ subscription.queuedRefresh = true;
408
+ subscription.queuedForce = subscription.queuedForce || force;
409
+ this.deferQueuedGitRefresh(client, GIT_SUBSCRIPTION_MIN_REFRESH_INTERVAL_MS - (now - subscription.lastRequestedAt));
423
410
  return;
424
411
  }
425
412
  subscription.lastRequestedAt = now;
@@ -436,7 +423,7 @@ export class WorkbenchWsHub {
436
423
  return;
437
424
  }
438
425
  const payload = buildGitPayload(snapshot);
439
- if (payload === subscription.lastPayload) {
426
+ if (payload === subscription.lastPayload && !options?.deliverIfUnchanged) {
440
427
  return;
441
428
  }
442
429
  subscription.lastPayload = payload;
@@ -462,45 +449,190 @@ export class WorkbenchWsHub {
462
449
  if (subscription.refreshController === controller) {
463
450
  subscription.refreshController = null;
464
451
  }
452
+ if (subscription.queuedRefresh && !subscription.refreshTimer) {
453
+ this.flushQueuedGitRefresh(client);
454
+ }
465
455
  });
466
456
  return subscription.refreshTask;
467
457
  }
468
- abortGitRefresh(client, reason) {
469
- this.clientGitSubscriptions.get(client)?.refreshController?.abort(new Error(reason));
458
+ ensureGitSubscription(client, workspaceId) {
459
+ const normalizedWorkspaceId = workspaceId.trim();
460
+ const current = this.clientGitSubscriptions.get(client);
461
+ if (current && current.workspaceId === normalizedWorkspaceId) {
462
+ return current;
463
+ }
464
+ const next = {
465
+ workspaceId: normalizedWorkspaceId,
466
+ lastPayload: null,
467
+ lastRequestedAt: 0,
468
+ refreshTask: null,
469
+ refreshController: null,
470
+ refreshTimer: null,
471
+ queuedRefresh: false,
472
+ queuedForce: false
473
+ };
474
+ this.fileWatcher.subscribeGit(normalizedWorkspaceId);
475
+ this.clientGitSubscriptions.set(client, next);
476
+ if (current) {
477
+ current.refreshController?.abort(new Error("git subscription replaced"));
478
+ if (current.refreshTimer) {
479
+ clearTimeout(current.refreshTimer);
480
+ }
481
+ this.fileWatcher.unsubscribeGit(current.workspaceId);
482
+ }
483
+ return next;
470
484
  }
471
- async refreshTerminalManagerSubscription(client, force = false) {
485
+ scheduleGitRefresh(client, options) {
486
+ const subscription = this.clientGitSubscriptions.get(client);
487
+ if (!subscription) {
488
+ return;
489
+ }
490
+ subscription.queuedRefresh = true;
491
+ subscription.queuedForce = subscription.queuedForce || (options?.force ?? false);
492
+ if (subscription.refreshTimer) {
493
+ clearTimeout(subscription.refreshTimer);
494
+ subscription.refreshTimer = null;
495
+ }
496
+ const quietWindowMs = options?.quietWindowMs ?? 0;
497
+ if (quietWindowMs > 0) {
498
+ this.deferQueuedGitRefresh(client, quietWindowMs);
499
+ return;
500
+ }
501
+ this.flushQueuedGitRefresh(client);
502
+ }
503
+ flushQueuedGitRefresh(client) {
504
+ const subscription = this.clientGitSubscriptions.get(client);
505
+ if (!subscription || subscription.refreshTimer || subscription.refreshTask || !subscription.queuedRefresh) {
506
+ return;
507
+ }
508
+ const force = subscription.queuedForce;
509
+ subscription.queuedRefresh = false;
510
+ subscription.queuedForce = false;
511
+ void this.refreshGitSubscription(client, force);
512
+ }
513
+ deferQueuedGitRefresh(client, delayMs) {
514
+ const subscription = this.clientGitSubscriptions.get(client);
515
+ if (!subscription) {
516
+ return;
517
+ }
518
+ if (subscription.refreshTimer) {
519
+ clearTimeout(subscription.refreshTimer);
520
+ }
521
+ subscription.refreshTimer = setTimeout(() => {
522
+ subscription.refreshTimer = null;
523
+ this.flushQueuedGitRefresh(client);
524
+ }, Math.max(0, delayMs));
525
+ }
526
+ ensureTerminalManagerSubscription(client, workspaceId) {
527
+ const normalizedWorkspaceId = workspaceId.trim();
528
+ const current = this.clientTerminalManagerSubscriptions.get(client);
529
+ if (current && current.workspaceId === normalizedWorkspaceId) {
530
+ return current;
531
+ }
532
+ if (current?.refreshTimer) {
533
+ clearTimeout(current.refreshTimer);
534
+ }
535
+ const next = {
536
+ workspaceId: normalizedWorkspaceId,
537
+ lastPayload: null,
538
+ refreshTask: null,
539
+ refreshTimer: null,
540
+ queuedRefresh: false,
541
+ queuedForce: false
542
+ };
543
+ this.clientTerminalManagerSubscriptions.set(client, next);
544
+ return next;
545
+ }
546
+ scheduleTerminalManagerRefresh(client, options) {
472
547
  const subscription = this.clientTerminalManagerSubscriptions.get(client);
473
548
  if (!subscription) {
474
549
  return;
475
550
  }
476
- try {
477
- const startedAtMs = terminalDebugNowMs();
478
- const snapshot = await this.workspacePanelSnapshotService.getTerminalManagerSnapshot(subscription.workspaceId, { force });
479
- const payloadStartedAtMs = terminalDebugNowMs();
480
- const payload = buildTerminalManagerPayload(snapshot);
481
- const payloadBuildMs = terminalDebugNowMs() - payloadStartedAtMs;
482
- if (payload === subscription.lastPayload) {
483
- return;
484
- }
485
- subscription.lastPayload = payload;
486
- const sendStartedAtMs = terminalDebugNowMs();
487
- client.send(payload);
488
- logTerminalDebug("workbench.terminal_manager_refresh.completed", {
489
- workspaceId: subscription.workspaceId,
490
- force,
491
- terminalCount: snapshot.terminals.length,
492
- templateCount: snapshot.templates.length,
493
- templateStatusCount: snapshot.templateStatuses.length,
494
- payloadBuildMs,
495
- sendMs: terminalDebugNowMs() - sendStartedAtMs,
496
- durationMs: terminalDebugNowMs() - startedAtMs
497
- });
551
+ subscription.queuedRefresh = true;
552
+ subscription.queuedForce = subscription.queuedForce || (options?.force ?? false);
553
+ if (subscription.refreshTimer) {
554
+ clearTimeout(subscription.refreshTimer);
555
+ subscription.refreshTimer = null;
498
556
  }
499
- catch (error) {
500
- this.reportAsyncError("refreshTerminalManagerSubscription", error, {
501
- workspaceId: subscription.workspaceId
502
- });
557
+ const quietWindowMs = options?.quietWindowMs ?? 0;
558
+ if (quietWindowMs > 0) {
559
+ this.deferQueuedTerminalManagerRefresh(client, quietWindowMs);
560
+ return;
561
+ }
562
+ this.flushQueuedTerminalManagerRefresh(client);
563
+ }
564
+ flushQueuedTerminalManagerRefresh(client) {
565
+ const subscription = this.clientTerminalManagerSubscriptions.get(client);
566
+ if (!subscription || subscription.refreshTimer || !subscription.queuedRefresh) {
567
+ return;
568
+ }
569
+ if (subscription.refreshTask) {
570
+ return;
503
571
  }
572
+ const force = subscription.queuedForce;
573
+ subscription.queuedRefresh = false;
574
+ subscription.queuedForce = false;
575
+ void this.refreshTerminalManagerSubscription(client, force);
576
+ }
577
+ deferQueuedTerminalManagerRefresh(client, delayMs) {
578
+ const subscription = this.clientTerminalManagerSubscriptions.get(client);
579
+ if (!subscription) {
580
+ return;
581
+ }
582
+ if (subscription.refreshTimer) {
583
+ clearTimeout(subscription.refreshTimer);
584
+ }
585
+ subscription.refreshTimer = setTimeout(() => {
586
+ subscription.refreshTimer = null;
587
+ this.flushQueuedTerminalManagerRefresh(client);
588
+ }, Math.max(0, delayMs));
589
+ }
590
+ async refreshTerminalManagerSubscription(client, force = false) {
591
+ const subscription = this.clientTerminalManagerSubscriptions.get(client);
592
+ if (!subscription) {
593
+ return;
594
+ }
595
+ if (subscription.refreshTask) {
596
+ subscription.queuedRefresh = true;
597
+ subscription.queuedForce = subscription.queuedForce || force;
598
+ return subscription.refreshTask;
599
+ }
600
+ subscription.refreshTask = (async () => {
601
+ try {
602
+ const startedAtMs = terminalDebugNowMs();
603
+ const snapshot = await this.workspacePanelSnapshotService.getTerminalManagerSnapshot(subscription.workspaceId, { force });
604
+ const payloadStartedAtMs = terminalDebugNowMs();
605
+ const payload = buildTerminalManagerPayload(snapshot);
606
+ const payloadBuildMs = terminalDebugNowMs() - payloadStartedAtMs;
607
+ if (payload === subscription.lastPayload) {
608
+ return;
609
+ }
610
+ subscription.lastPayload = payload;
611
+ const sendStartedAtMs = terminalDebugNowMs();
612
+ client.send(payload);
613
+ logTerminalDebug("workbench.terminal_manager_refresh.completed", {
614
+ workspaceId: subscription.workspaceId,
615
+ force,
616
+ terminalCount: snapshot.terminals.length,
617
+ templateCount: snapshot.templates.length,
618
+ templateStatusCount: snapshot.templateStatuses.length,
619
+ payloadBuildMs,
620
+ sendMs: terminalDebugNowMs() - sendStartedAtMs,
621
+ durationMs: terminalDebugNowMs() - startedAtMs
622
+ });
623
+ }
624
+ catch (error) {
625
+ this.reportAsyncError("refreshTerminalManagerSubscription", error, {
626
+ workspaceId: subscription.workspaceId
627
+ });
628
+ }
629
+ })().finally(() => {
630
+ subscription.refreshTask = null;
631
+ if (subscription.queuedRefresh && !subscription.refreshTimer) {
632
+ this.flushQueuedTerminalManagerRefresh(client);
633
+ }
634
+ });
635
+ return subscription.refreshTask;
504
636
  }
505
637
  async refreshWorkspaceManagementSubscription(client, force = false) {
506
638
  const subscription = this.clientWorkspaceManagementSubscriptions.get(client);
@@ -522,6 +654,13 @@ export class WorkbenchWsHub {
522
654
  });
523
655
  }
524
656
  }
657
+ async refreshWorkspaceManagementSubscriptions(userId) {
658
+ const channel = this.userChannels.get(userId);
659
+ if (!channel) {
660
+ return;
661
+ }
662
+ await Promise.allSettled([...channel.clients].map((client) => this.refreshWorkspaceManagementSubscription(client)));
663
+ }
525
664
  reportAsyncError(scope, error, context = {}) {
526
665
  const appError = error instanceof AppError
527
666
  ? error
@@ -596,6 +735,21 @@ function parseWorkbenchMessage(payload) {
596
735
  return null;
597
736
  }
598
737
  }
738
+ function extractWorkspaceIdFromWorkbenchMessage(message) {
739
+ switch (message.type) {
740
+ case "fileTree.subscribe":
741
+ case "fileTree.refresh":
742
+ case "git.subscribe":
743
+ case "git.refresh":
744
+ case "terminalManager.subscribe":
745
+ case "terminalManager.refresh":
746
+ case "workspaceManagement.subscribe":
747
+ case "workspaceManagement.refresh":
748
+ return message.workspaceId.trim();
749
+ default:
750
+ return undefined;
751
+ }
752
+ }
599
753
  function normalizePanelPaths(paths) {
600
754
  const uniquePaths = new Set();
601
755
  for (const value of paths ?? [""]) {
@@ -604,6 +758,12 @@ function normalizePanelPaths(paths) {
604
758
  }
605
759
  return [...uniquePaths];
606
760
  }
761
+ function areStringArraysEqual(left, right) {
762
+ if (left.length !== right.length) {
763
+ return false;
764
+ }
765
+ return left.every((value, index) => value === right[index]);
766
+ }
607
767
  function buildWorkbenchPayload(snapshot) {
608
768
  return JSON.stringify({
609
769
  type: "workbench.snapshot",