@jingyi0605/codingns4dsh 0.2.0-beta.1 → 0.2.0-rc.2

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 (872) hide show
  1. package/README.en.md +29 -12
  2. package/README.md +22 -13
  3. package/assets/provider-icons/minimax-code.svg +4 -0
  4. package/assets/provider-icons/zcode.svg +14 -0
  5. package/data/build/dist/bootstrap/dsh-connection-adapter.d.ts +1 -1
  6. package/data/build/dist/bootstrap/dsh-connection-adapter.d.ts.map +1 -0
  7. package/data/build/dist/bootstrap/dsh-connection-adapter.js.map +1 -0
  8. package/data/build/dist/bootstrap/dsh-peer-host-preboot-shim.d.ts +50 -0
  9. package/data/build/dist/bootstrap/dsh-peer-host-preboot-shim.d.ts.map +1 -0
  10. package/data/build/dist/bootstrap/dsh-peer-host-preboot-shim.js +239 -0
  11. package/data/build/dist/bootstrap/dsh-peer-host-preboot-shim.js.map +1 -0
  12. package/data/build/dist/bootstrap/index.d.ts +3 -1
  13. package/data/build/dist/bootstrap/index.d.ts.map +1 -0
  14. package/data/build/dist/bootstrap/index.js +1 -0
  15. package/data/build/dist/bootstrap/index.js.map +1 -0
  16. package/data/build/dist/client/account-bar.d.ts +8 -1
  17. package/data/build/dist/client/account-bar.d.ts.map +1 -0
  18. package/data/build/dist/client/account-bar.js +166 -79
  19. package/data/build/dist/client/account-bar.js.map +1 -0
  20. package/data/build/dist/client/bundle.js +16641 -8889
  21. package/data/build/dist/client/bundle.js.map +1 -0
  22. package/data/build/dist/client/cli-catalog.d.ts.map +1 -0
  23. package/data/build/dist/client/cli-catalog.js.map +1 -0
  24. package/data/build/dist/client/cli-slots.d.ts.map +1 -0
  25. package/data/build/dist/client/cli-slots.js +32 -13
  26. package/data/build/dist/client/cli-slots.js.map +1 -0
  27. package/data/build/dist/client/context-breakdown-dom.d.ts.map +1 -0
  28. package/data/build/dist/client/context-breakdown-dom.js.map +1 -0
  29. package/data/build/dist/client/debug/ui.d.ts +2 -1
  30. package/data/build/dist/client/debug/ui.d.ts.map +1 -0
  31. package/data/build/dist/client/debug/ui.js +40 -33
  32. package/data/build/dist/client/debug/ui.js.map +1 -0
  33. package/data/build/dist/client/delegate-command.d.ts +16 -0
  34. package/data/build/dist/client/delegate-command.d.ts.map +1 -0
  35. package/data/build/dist/client/delegate-command.js +138 -0
  36. package/data/build/dist/client/delegate-command.js.map +1 -0
  37. package/data/build/dist/client/delegate-plan.d.ts +31 -0
  38. package/data/build/dist/client/delegate-plan.d.ts.map +1 -0
  39. package/data/build/dist/client/delegate-plan.js +59 -0
  40. package/data/build/dist/client/delegate-plan.js.map +1 -0
  41. package/data/build/dist/client/delegate-ui-dom.d.ts +40 -0
  42. package/data/build/dist/client/delegate-ui-dom.d.ts.map +1 -0
  43. package/data/build/dist/client/delegate-ui-dom.js +363 -0
  44. package/data/build/dist/client/delegate-ui-dom.js.map +1 -0
  45. package/data/build/dist/client/dsh-h5-bootstrap.d.ts.map +1 -0
  46. package/data/build/dist/client/dsh-h5-bootstrap.js +12 -5
  47. package/data/build/dist/client/dsh-h5-bootstrap.js.map +1 -0
  48. package/data/build/dist/client/dsh-runtime-version.d.ts +3 -2
  49. package/data/build/dist/client/dsh-runtime-version.d.ts.map +1 -0
  50. package/data/build/dist/client/dsh-runtime-version.js +7 -6
  51. package/data/build/dist/client/dsh-runtime-version.js.map +1 -0
  52. package/data/build/dist/client/external-tool-stream.d.ts.map +1 -0
  53. package/data/build/dist/client/external-tool-stream.js +44 -36
  54. package/data/build/dist/client/external-tool-stream.js.map +1 -0
  55. package/data/build/dist/client/features/cli-adapters.d.ts +7 -2
  56. package/data/build/dist/client/features/cli-adapters.d.ts.map +1 -0
  57. package/data/build/dist/client/features/cli-adapters.js +59 -105
  58. package/data/build/dist/client/features/cli-adapters.js.map +1 -0
  59. package/data/build/dist/client/features/debug.d.ts.map +1 -0
  60. package/data/build/dist/client/features/debug.js +6 -4
  61. package/data/build/dist/client/features/debug.js.map +1 -0
  62. package/data/build/dist/client/features/file-management-panel.d.ts.map +1 -0
  63. package/data/build/dist/client/features/file-management-panel.js.map +1 -0
  64. package/data/build/dist/client/features/file-management.d.ts.map +1 -0
  65. package/data/build/dist/client/features/file-management.js +8 -5
  66. package/data/build/dist/client/features/file-management.js.map +1 -0
  67. package/data/build/dist/client/features/index.d.ts +4 -2
  68. package/data/build/dist/client/features/index.d.ts.map +1 -0
  69. package/data/build/dist/client/features/index.js +5 -2
  70. package/data/build/dist/client/features/index.js.map +1 -0
  71. package/data/build/dist/client/features/lan-access-panel.d.ts.map +1 -0
  72. package/data/build/dist/client/features/lan-access-panel.js +89 -11
  73. package/data/build/dist/client/features/lan-access-panel.js.map +1 -0
  74. package/data/build/dist/client/features/lan-access-status.d.ts +40 -0
  75. package/data/build/dist/client/features/lan-access-status.d.ts.map +1 -0
  76. package/data/build/dist/client/features/lan-access-status.js +118 -0
  77. package/data/build/dist/client/features/lan-access-status.js.map +1 -0
  78. package/data/build/dist/client/features/lan-access.d.ts +4 -1
  79. package/data/build/dist/client/features/lan-access.d.ts.map +1 -0
  80. package/data/build/dist/client/features/lan-access.js +35 -5
  81. package/data/build/dist/client/features/lan-access.js.map +1 -0
  82. package/data/build/dist/client/features/login-protection-panel.d.ts.map +1 -0
  83. package/data/build/dist/client/features/login-protection-panel.js +9 -7
  84. package/data/build/dist/client/features/login-protection-panel.js.map +1 -0
  85. package/data/build/dist/client/features/login-protection-session.d.ts.map +1 -0
  86. package/data/build/dist/client/features/login-protection-session.js.map +1 -0
  87. package/data/build/dist/client/features/login-protection.d.ts.map +1 -0
  88. package/data/build/dist/client/features/login-protection.js +3 -3
  89. package/data/build/dist/client/features/login-protection.js.map +1 -0
  90. package/data/build/dist/client/features/mobile-access-panel.d.ts +12 -0
  91. package/data/build/dist/client/features/mobile-access-panel.d.ts.map +1 -0
  92. package/data/build/dist/client/features/mobile-access-panel.js +259 -0
  93. package/data/build/dist/client/features/mobile-access-panel.js.map +1 -0
  94. package/data/build/dist/client/features/mobile-access.d.ts +13 -0
  95. package/data/build/dist/client/features/mobile-access.d.ts.map +1 -0
  96. package/data/build/dist/client/features/mobile-access.js +79 -0
  97. package/data/build/dist/client/features/mobile-access.js.map +1 -0
  98. package/data/build/dist/client/features/peer-host.d.ts +35 -1
  99. package/data/build/dist/client/features/peer-host.d.ts.map +1 -0
  100. package/data/build/dist/client/features/peer-host.js +599 -56
  101. package/data/build/dist/client/features/peer-host.js.map +1 -0
  102. package/data/build/dist/client/features/reverse-proxy-panel.d.ts.map +1 -0
  103. package/data/build/dist/client/features/reverse-proxy-panel.js +2 -1
  104. package/data/build/dist/client/features/reverse-proxy-panel.js.map +1 -0
  105. package/data/build/dist/client/features/reverse-proxy.d.ts.map +1 -0
  106. package/data/build/dist/client/features/reverse-proxy.js +3 -3
  107. package/data/build/dist/client/features/reverse-proxy.js.map +1 -0
  108. package/data/build/dist/client/features/subscription-usage-panel.d.ts.map +1 -0
  109. package/data/build/dist/client/features/subscription-usage-panel.js.map +1 -0
  110. package/data/build/dist/client/features/terminal-enhancement-panel.d.ts.map +1 -0
  111. package/data/build/dist/client/features/terminal-enhancement-panel.js.map +1 -0
  112. package/data/build/dist/client/features/terminal-enhancement.d.ts.map +1 -0
  113. package/data/build/dist/client/features/terminal-enhancement.js +3 -3
  114. package/data/build/dist/client/features/terminal-enhancement.js.map +1 -0
  115. package/data/build/dist/client/features/types.d.ts +12 -0
  116. package/data/build/dist/client/features/types.d.ts.map +1 -0
  117. package/data/build/dist/client/features/types.js.map +1 -0
  118. package/data/build/dist/client/features/workspace-session-enhancement-panel.d.ts.map +1 -0
  119. package/data/build/dist/client/features/workspace-session-enhancement-panel.js +5 -2
  120. package/data/build/dist/client/features/workspace-session-enhancement-panel.js.map +1 -0
  121. package/data/build/dist/client/features/workspace-session-enhancement.d.ts.map +1 -0
  122. package/data/build/dist/client/features/workspace-session-enhancement.js +24 -6
  123. package/data/build/dist/client/features/workspace-session-enhancement.js.map +1 -0
  124. package/data/build/dist/client/file-management-dom.d.ts +5 -0
  125. package/data/build/dist/client/file-management-dom.d.ts.map +1 -0
  126. package/data/build/dist/client/file-management-dom.js +78 -38
  127. package/data/build/dist/client/file-management-dom.js.map +1 -0
  128. package/data/build/dist/client/git-history-graph.d.ts +81 -0
  129. package/data/build/dist/client/git-history-graph.d.ts.map +1 -0
  130. package/data/build/dist/client/git-history-graph.js +195 -0
  131. package/data/build/dist/client/git-history-graph.js.map +1 -0
  132. package/data/build/dist/client/git-management.d.ts +2 -0
  133. package/data/build/dist/client/git-management.d.ts.map +1 -0
  134. package/data/build/dist/client/git-management.js +284 -108
  135. package/data/build/dist/client/git-management.js.map +1 -0
  136. package/data/build/dist/client/git-panel-styles.d.ts +28 -0
  137. package/data/build/dist/client/git-panel-styles.d.ts.map +1 -0
  138. package/data/build/dist/client/git-panel-styles.js +95 -0
  139. package/data/build/dist/client/git-panel-styles.js.map +1 -0
  140. package/data/build/dist/client/git-workspace-events.d.ts +7 -0
  141. package/data/build/dist/client/git-workspace-events.d.ts.map +1 -0
  142. package/data/build/dist/client/git-workspace-events.js +32 -0
  143. package/data/build/dist/client/git-workspace-events.js.map +1 -0
  144. package/data/build/dist/client/h5-bootstrap-entry.d.ts.map +1 -0
  145. package/data/build/dist/client/h5-bootstrap-entry.js.map +1 -0
  146. package/data/build/dist/client/host-router.d.ts.map +1 -0
  147. package/data/build/dist/client/host-router.js.map +1 -0
  148. package/data/build/dist/client/index.d.ts +7 -4
  149. package/data/build/dist/client/index.d.ts.map +1 -0
  150. package/data/build/dist/client/index.js +16 -9
  151. package/data/build/dist/client/index.js.map +1 -0
  152. package/data/build/dist/client/lan-access.d.ts.map +1 -0
  153. package/data/build/dist/client/lan-access.js.map +1 -0
  154. package/data/build/dist/client/locale.d.ts +7 -0
  155. package/data/build/dist/client/locale.d.ts.map +1 -0
  156. package/data/build/dist/client/locale.js +231 -47
  157. package/data/build/dist/client/locale.js.map +1 -0
  158. package/data/build/dist/client/locales/debug.d.ts +9 -0
  159. package/data/build/dist/client/locales/debug.d.ts.map +1 -0
  160. package/data/build/dist/client/locales/debug.js +163 -0
  161. package/data/build/dist/client/locales/debug.js.map +1 -0
  162. package/data/build/dist/client/locales/fileWorkspace.d.ts +9 -0
  163. package/data/build/dist/client/locales/fileWorkspace.d.ts.map +1 -0
  164. package/data/build/dist/client/locales/fileWorkspace.js +139 -0
  165. package/data/build/dist/client/locales/fileWorkspace.js.map +1 -0
  166. package/data/build/dist/client/locales/git.d.ts +9 -0
  167. package/data/build/dist/client/locales/git.d.ts.map +1 -0
  168. package/data/build/dist/client/locales/git.js +223 -0
  169. package/data/build/dist/client/locales/git.js.map +1 -0
  170. package/data/build/dist/client/locales/panels.d.ts +9 -0
  171. package/data/build/dist/client/locales/panels.d.ts.map +1 -0
  172. package/data/build/dist/client/locales/panels.js +33 -0
  173. package/data/build/dist/client/locales/panels.js.map +1 -0
  174. package/data/build/dist/client/locales/peerHost.d.ts +9 -0
  175. package/data/build/dist/client/locales/peerHost.d.ts.map +1 -0
  176. package/data/build/dist/client/locales/peerHost.js +153 -0
  177. package/data/build/dist/client/locales/peerHost.js.map +1 -0
  178. package/data/build/dist/client/locales/peerHostWorkspace.d.ts +9 -0
  179. package/data/build/dist/client/locales/peerHostWorkspace.d.ts.map +1 -0
  180. package/data/build/dist/client/locales/peerHostWorkspace.js +69 -0
  181. package/data/build/dist/client/locales/peerHostWorkspace.js.map +1 -0
  182. package/data/build/dist/client/locales/terminalAuth.d.ts +9 -0
  183. package/data/build/dist/client/locales/terminalAuth.d.ts.map +1 -0
  184. package/data/build/dist/client/locales/terminalAuth.js +67 -0
  185. package/data/build/dist/client/locales/terminalAuth.js.map +1 -0
  186. package/data/build/dist/client/locales/usage.d.ts +9 -0
  187. package/data/build/dist/client/locales/usage.d.ts.map +1 -0
  188. package/data/build/dist/client/locales/usage.js +195 -0
  189. package/data/build/dist/client/locales/usage.js.map +1 -0
  190. package/data/build/dist/client/mobile-session-interaction.d.ts +44 -0
  191. package/data/build/dist/client/mobile-session-interaction.d.ts.map +1 -0
  192. package/data/build/dist/client/mobile-session-interaction.js +291 -0
  193. package/data/build/dist/client/mobile-session-interaction.js.map +1 -0
  194. package/data/build/dist/client/mobile-settings-modal-dom.d.ts +49 -0
  195. package/data/build/dist/client/mobile-settings-modal-dom.d.ts.map +1 -0
  196. package/data/build/dist/client/mobile-settings-modal-dom.js +152 -0
  197. package/data/build/dist/client/mobile-settings-modal-dom.js.map +1 -0
  198. package/data/build/dist/client/mobile-sidebar-gestures.d.ts +97 -0
  199. package/data/build/dist/client/mobile-sidebar-gestures.d.ts.map +1 -0
  200. package/data/build/dist/client/mobile-sidebar-gestures.js +316 -0
  201. package/data/build/dist/client/mobile-sidebar-gestures.js.map +1 -0
  202. package/data/build/dist/client/mobile-sidebar-logo.d.ts +18 -0
  203. package/data/build/dist/client/mobile-sidebar-logo.d.ts.map +1 -0
  204. package/data/build/dist/client/mobile-sidebar-logo.js +15 -0
  205. package/data/build/dist/client/mobile-sidebar-logo.js.map +1 -0
  206. package/data/build/dist/client/mobile-sidebar-rail-dom.d.ts +114 -0
  207. package/data/build/dist/client/mobile-sidebar-rail-dom.d.ts.map +1 -0
  208. package/data/build/dist/client/mobile-sidebar-rail-dom.js +452 -0
  209. package/data/build/dist/client/mobile-sidebar-rail-dom.js.map +1 -0
  210. package/data/build/dist/client/mobile-vibration.d.ts +16 -0
  211. package/data/build/dist/client/mobile-vibration.d.ts.map +1 -0
  212. package/data/build/dist/client/mobile-vibration.js +20 -0
  213. package/data/build/dist/client/mobile-vibration.js.map +1 -0
  214. package/data/build/dist/client/native-workspace-store.d.ts +29 -0
  215. package/data/build/dist/client/native-workspace-store.d.ts.map +1 -0
  216. package/data/build/dist/client/native-workspace-store.js +64 -0
  217. package/data/build/dist/client/native-workspace-store.js.map +1 -0
  218. package/data/build/dist/client/peer-host-aggregate-refresh.d.ts +13 -0
  219. package/data/build/dist/client/peer-host-aggregate-refresh.d.ts.map +1 -0
  220. package/data/build/dist/client/peer-host-aggregate-refresh.js +14 -0
  221. package/data/build/dist/client/peer-host-aggregate-refresh.js.map +1 -0
  222. package/data/build/dist/client/peer-host-color.d.ts +13 -0
  223. package/data/build/dist/client/peer-host-color.d.ts.map +1 -0
  224. package/data/build/dist/client/peer-host-color.js +57 -0
  225. package/data/build/dist/client/peer-host-color.js.map +1 -0
  226. package/data/build/dist/client/peer-host-connection-button.d.ts +14 -1
  227. package/data/build/dist/client/peer-host-connection-button.d.ts.map +1 -0
  228. package/data/build/dist/client/peer-host-connection-button.js +18 -7
  229. package/data/build/dist/client/peer-host-connection-button.js.map +1 -0
  230. package/data/build/dist/client/peer-host-management-api.d.ts +34 -0
  231. package/data/build/dist/client/peer-host-management-api.d.ts.map +1 -0
  232. package/data/build/dist/client/peer-host-management-api.js +12 -0
  233. package/data/build/dist/client/peer-host-management-api.js.map +1 -0
  234. package/data/build/dist/client/peer-host-management-panel.d.ts +4 -1
  235. package/data/build/dist/client/peer-host-management-panel.d.ts.map +1 -0
  236. package/data/build/dist/client/peer-host-management-panel.js +533 -94
  237. package/data/build/dist/client/peer-host-management-panel.js.map +1 -0
  238. package/data/build/dist/client/peer-host-native-projection.d.ts +47 -0
  239. package/data/build/dist/client/peer-host-native-projection.d.ts.map +1 -0
  240. package/data/build/dist/client/peer-host-native-projection.js +142 -0
  241. package/data/build/dist/client/peer-host-native-projection.js.map +1 -0
  242. package/data/build/dist/client/peer-host-native-store-projection.d.ts +21 -0
  243. package/data/build/dist/client/peer-host-native-store-projection.d.ts.map +1 -0
  244. package/data/build/dist/client/peer-host-native-store-projection.js +114 -0
  245. package/data/build/dist/client/peer-host-native-store-projection.js.map +1 -0
  246. package/data/build/dist/client/peer-host-scoped-client.d.ts.map +1 -0
  247. package/data/build/dist/client/peer-host-scoped-client.js +5 -5
  248. package/data/build/dist/client/peer-host-scoped-client.js.map +1 -0
  249. package/data/build/dist/client/peer-host-session-controller.d.ts.map +1 -0
  250. package/data/build/dist/client/peer-host-session-controller.js.map +1 -0
  251. package/data/build/dist/client/peer-host-workspace-tab.d.ts +52 -0
  252. package/data/build/dist/client/peer-host-workspace-tab.d.ts.map +1 -0
  253. package/data/build/dist/client/peer-host-workspace-tab.js +492 -0
  254. package/data/build/dist/client/peer-host-workspace-tab.js.map +1 -0
  255. package/data/build/dist/client/peer-host-workspace-tag.d.ts +47 -0
  256. package/data/build/dist/client/peer-host-workspace-tag.d.ts.map +1 -0
  257. package/data/build/dist/client/peer-host-workspace-tag.js +207 -0
  258. package/data/build/dist/client/peer-host-workspace-tag.js.map +1 -0
  259. package/data/build/dist/client/popup-dismiss.d.ts +48 -0
  260. package/data/build/dist/client/popup-dismiss.d.ts.map +1 -0
  261. package/data/build/dist/client/popup-dismiss.js +93 -0
  262. package/data/build/dist/client/popup-dismiss.js.map +1 -0
  263. package/data/build/dist/client/provider-icon-assets.d.ts.map +1 -0
  264. package/data/build/dist/client/provider-icon-assets.js +4 -0
  265. package/data/build/dist/client/provider-icon-assets.js.map +1 -0
  266. package/data/build/dist/client/provider-icons.d.ts +18 -3
  267. package/data/build/dist/client/provider-icons.d.ts.map +1 -0
  268. package/data/build/dist/client/provider-icons.js +30 -14
  269. package/data/build/dist/client/provider-icons.js.map +1 -0
  270. package/data/build/dist/client/pwa-install-prompt.d.ts +76 -0
  271. package/data/build/dist/client/pwa-install-prompt.d.ts.map +1 -0
  272. package/data/build/dist/client/pwa-install-prompt.js +179 -0
  273. package/data/build/dist/client/pwa-install-prompt.js.map +1 -0
  274. package/data/build/dist/client/pwa-notifications.d.ts +105 -0
  275. package/data/build/dist/client/pwa-notifications.d.ts.map +1 -0
  276. package/data/build/dist/client/pwa-notifications.js +192 -0
  277. package/data/build/dist/client/pwa-notifications.js.map +1 -0
  278. package/data/build/dist/client/quick-phrase-layout.d.ts +11 -0
  279. package/data/build/dist/client/quick-phrase-layout.d.ts.map +1 -0
  280. package/data/build/dist/client/quick-phrase-layout.js +20 -0
  281. package/data/build/dist/client/quick-phrase-layout.js.map +1 -0
  282. package/data/build/dist/client/quick-phrase-slot.d.ts.map +1 -0
  283. package/data/build/dist/client/quick-phrase-slot.js +20 -8
  284. package/data/build/dist/client/quick-phrase-slot.js.map +1 -0
  285. package/data/build/dist/client/remote-web-context.d.ts.map +1 -0
  286. package/data/build/dist/client/remote-web-context.js.map +1 -0
  287. package/data/build/dist/client/session-adapter-cache.d.ts.map +1 -0
  288. package/data/build/dist/client/session-adapter-cache.js.map +1 -0
  289. package/data/build/dist/client/session-changed-files-view.d.ts +8 -1
  290. package/data/build/dist/client/session-changed-files-view.d.ts.map +1 -0
  291. package/data/build/dist/client/session-changed-files-view.js +71 -28
  292. package/data/build/dist/client/session-changed-files-view.js.map +1 -0
  293. package/data/build/dist/client/settings-anchor.d.ts +73 -0
  294. package/data/build/dist/client/settings-anchor.d.ts.map +1 -0
  295. package/data/build/dist/client/settings-anchor.js +70 -0
  296. package/data/build/dist/client/settings-anchor.js.map +1 -0
  297. package/data/build/dist/client/settings-bridge.d.ts.map +1 -0
  298. package/data/build/dist/client/settings-bridge.js.map +1 -0
  299. package/data/build/dist/client/settings-section.d.ts.map +1 -0
  300. package/data/build/dist/client/settings-section.js +19 -5
  301. package/data/build/dist/client/settings-section.js.map +1 -0
  302. package/data/build/dist/client/subscription-slot.d.ts +4 -1
  303. package/data/build/dist/client/subscription-slot.d.ts.map +1 -0
  304. package/data/build/dist/client/subscription-slot.js +328 -69
  305. package/data/build/dist/client/subscription-slot.js.map +1 -0
  306. package/data/build/dist/client/terminal/index.d.ts.map +1 -0
  307. package/data/build/dist/client/terminal/index.js.map +1 -0
  308. package/data/build/dist/client/terminal/model.d.ts +13 -2
  309. package/data/build/dist/client/terminal/model.d.ts.map +1 -0
  310. package/data/build/dist/client/terminal/model.js +27 -7
  311. package/data/build/dist/client/terminal/model.js.map +1 -0
  312. package/data/build/dist/client/terminal/recovery.d.ts.map +1 -0
  313. package/data/build/dist/client/terminal/recovery.js.map +1 -0
  314. package/data/build/dist/client/terminal/styles.d.ts.map +1 -0
  315. package/data/build/dist/client/terminal/styles.js.map +1 -0
  316. package/data/build/dist/client/terminal/ui.d.ts.map +1 -0
  317. package/data/build/dist/client/terminal/ui.js +3 -1
  318. package/data/build/dist/client/terminal/ui.js.map +1 -0
  319. package/data/build/dist/client/terminal/xterm-view.d.ts +4 -1
  320. package/data/build/dist/client/terminal/xterm-view.d.ts.map +1 -0
  321. package/data/build/dist/client/terminal/xterm-view.js +19 -17
  322. package/data/build/dist/client/terminal/xterm-view.js.map +1 -0
  323. package/data/build/dist/client/theme.d.ts +17 -5
  324. package/data/build/dist/client/theme.d.ts.map +1 -0
  325. package/data/build/dist/client/theme.js +35 -13
  326. package/data/build/dist/client/theme.js.map +1 -0
  327. package/data/build/dist/client/workspace-session-archive-dom.d.ts +17 -0
  328. package/data/build/dist/client/workspace-session-archive-dom.d.ts.map +1 -0
  329. package/data/build/dist/client/workspace-session-archive-dom.js +192 -47
  330. package/data/build/dist/client/workspace-session-archive-dom.js.map +1 -0
  331. package/data/build/dist/client/workspace-session-fiber.d.ts.map +1 -0
  332. package/data/build/dist/client/workspace-session-fiber.js.map +1 -0
  333. package/data/build/dist/client/workspace-session-logo-dom.d.ts +3 -0
  334. package/data/build/dist/client/workspace-session-logo-dom.d.ts.map +1 -0
  335. package/data/build/dist/client/workspace-session-logo-dom.js +3 -1
  336. package/data/build/dist/client/workspace-session-logo-dom.js.map +1 -0
  337. package/data/build/dist/client/workspace-session-rightbar-dom.d.ts.map +1 -0
  338. package/data/build/dist/client/workspace-session-rightbar-dom.js.map +1 -0
  339. package/data/build/dist/client/workspace-session-visibility-dom.d.ts +3 -0
  340. package/data/build/dist/client/workspace-session-visibility-dom.d.ts.map +1 -0
  341. package/data/build/dist/client/workspace-session-visibility-dom.js +46 -17
  342. package/data/build/dist/client/workspace-session-visibility-dom.js.map +1 -0
  343. package/data/build/dist/dsh-capabilities/client/config-forms-adapter.d.ts.map +1 -0
  344. package/data/build/dist/dsh-capabilities/client/config-forms-adapter.js.map +1 -0
  345. package/data/build/dist/dsh-capabilities/client/conversation-adapter.d.ts.map +1 -0
  346. package/data/build/dist/dsh-capabilities/client/conversation-adapter.js.map +1 -0
  347. package/data/build/dist/dsh-capabilities/client/locale-adapter.d.ts.map +1 -0
  348. package/data/build/dist/dsh-capabilities/client/locale-adapter.js.map +1 -0
  349. package/data/build/dist/dsh-capabilities/client/primitives-adapter.d.ts +10 -0
  350. package/data/build/dist/dsh-capabilities/client/primitives-adapter.d.ts.map +1 -0
  351. package/data/build/dist/dsh-capabilities/client/primitives-adapter.js +20 -0
  352. package/data/build/dist/dsh-capabilities/client/primitives-adapter.js.map +1 -0
  353. package/data/build/dist/dsh-capabilities/client/settings-scope-adapter.d.ts.map +1 -0
  354. package/data/build/dist/dsh-capabilities/client/settings-scope-adapter.js.map +1 -0
  355. package/data/build/dist/dsh-capabilities/client/sidebar-adapter.d.ts.map +1 -0
  356. package/data/build/dist/dsh-capabilities/client/sidebar-adapter.js.map +1 -0
  357. package/data/build/dist/dsh-capabilities/client/theme-adapter.d.ts.map +1 -0
  358. package/data/build/dist/dsh-capabilities/client/theme-adapter.js.map +1 -0
  359. package/data/build/dist/dsh-capabilities/client/typert-adapter.d.ts.map +1 -0
  360. package/data/build/dist/dsh-capabilities/client/typert-adapter.js.map +1 -0
  361. package/data/build/dist/dsh-capabilities/host/config-forms-adapter.d.ts.map +1 -0
  362. package/data/build/dist/dsh-capabilities/host/config-forms-adapter.js.map +1 -0
  363. package/data/build/dist/dsh-capabilities/host/connection-rpc-adapter.d.ts.map +1 -0
  364. package/data/build/dist/dsh-capabilities/host/connection-rpc-adapter.js.map +1 -0
  365. package/data/build/dist/dsh-capabilities/host/settings-scope-adapter.d.ts.map +1 -0
  366. package/data/build/dist/dsh-capabilities/host/settings-scope-adapter.js.map +1 -0
  367. package/data/build/dist/dsh-capabilities/host/typert-adapter.d.ts.map +1 -0
  368. package/data/build/dist/dsh-capabilities/host/typert-adapter.js.map +1 -0
  369. package/data/build/dist/dsh-capabilities/index.d.ts.map +1 -0
  370. package/data/build/dist/dsh-capabilities/index.js.map +1 -0
  371. package/data/build/dist/dsh-capabilities/matrix.d.ts.map +1 -0
  372. package/data/build/dist/dsh-capabilities/matrix.js +44 -31
  373. package/data/build/dist/dsh-capabilities/matrix.js.map +1 -0
  374. package/data/build/dist/dsh-capabilities/registry.d.ts.map +1 -0
  375. package/data/build/dist/dsh-capabilities/registry.js +6 -2
  376. package/data/build/dist/dsh-capabilities/registry.js.map +1 -0
  377. package/data/build/dist/dsh-capabilities/routes.d.ts.map +1 -0
  378. package/data/build/dist/dsh-capabilities/routes.js +96 -11
  379. package/data/build/dist/dsh-capabilities/routes.js.map +1 -0
  380. package/data/build/dist/dsh-capabilities/settings-store.d.ts.map +1 -0
  381. package/data/build/dist/dsh-capabilities/settings-store.js.map +1 -0
  382. package/data/build/dist/dsh-capabilities/types.d.ts +1 -1
  383. package/data/build/dist/dsh-capabilities/types.d.ts.map +1 -0
  384. package/data/build/dist/dsh-capabilities/types.js.map +1 -0
  385. package/data/build/dist/features/host-router.d.ts.map +1 -0
  386. package/data/build/dist/features/host-router.js.map +1 -0
  387. package/data/build/dist/features/index.d.ts.map +1 -0
  388. package/data/build/dist/features/index.js.map +1 -0
  389. package/data/build/dist/features/registry.d.ts.map +1 -0
  390. package/data/build/dist/features/registry.js.map +1 -0
  391. package/data/build/dist/features/resource-scope/index.d.ts.map +1 -0
  392. package/data/build/dist/features/resource-scope/index.js.map +1 -0
  393. package/data/build/dist/host/auth-session.d.ts.map +1 -0
  394. package/data/build/dist/host/auth-session.js.map +1 -0
  395. package/data/build/dist/host/browser-text.d.ts +30 -0
  396. package/data/build/dist/host/browser-text.d.ts.map +1 -0
  397. package/data/build/dist/host/browser-text.js +105 -0
  398. package/data/build/dist/host/browser-text.js.map +1 -0
  399. package/data/build/dist/host/cli-adapters/attachment-utils.d.ts +14 -0
  400. package/data/build/dist/host/cli-adapters/attachment-utils.d.ts.map +1 -0
  401. package/data/build/dist/host/cli-adapters/attachment-utils.js +78 -0
  402. package/data/build/dist/host/cli-adapters/attachment-utils.js.map +1 -0
  403. package/data/build/dist/host/cli-adapters/claude-driver.d.ts +28 -2
  404. package/data/build/dist/host/cli-adapters/claude-driver.d.ts.map +1 -0
  405. package/data/build/dist/host/cli-adapters/claude-driver.js +78 -5
  406. package/data/build/dist/host/cli-adapters/claude-driver.js.map +1 -0
  407. package/data/build/dist/host/cli-adapters/claude-model-options.d.ts.map +1 -0
  408. package/data/build/dist/host/cli-adapters/claude-model-options.js +22 -9
  409. package/data/build/dist/host/cli-adapters/claude-model-options.js.map +1 -0
  410. package/data/build/dist/host/cli-adapters/codex-driver.d.ts +10 -0
  411. package/data/build/dist/host/cli-adapters/codex-driver.d.ts.map +1 -0
  412. package/data/build/dist/host/cli-adapters/codex-driver.js +352 -49
  413. package/data/build/dist/host/cli-adapters/codex-driver.js.map +1 -0
  414. package/data/build/dist/host/cli-adapters/command-code-driver.d.ts +24 -2
  415. package/data/build/dist/host/cli-adapters/command-code-driver.d.ts.map +1 -0
  416. package/data/build/dist/host/cli-adapters/command-code-driver.js +296 -34
  417. package/data/build/dist/host/cli-adapters/command-code-driver.js.map +1 -0
  418. package/data/build/dist/host/cli-adapters/command-code-subscription.d.ts.map +1 -0
  419. package/data/build/dist/host/cli-adapters/command-code-subscription.js.map +1 -0
  420. package/data/build/dist/host/cli-adapters/delegate-dispatch.d.ts +47 -0
  421. package/data/build/dist/host/cli-adapters/delegate-dispatch.d.ts.map +1 -0
  422. package/data/build/dist/host/cli-adapters/delegate-dispatch.js +158 -0
  423. package/data/build/dist/host/cli-adapters/delegate-dispatch.js.map +1 -0
  424. package/data/build/dist/host/cli-adapters/desktop-app-runtime.d.ts +32 -0
  425. package/data/build/dist/host/cli-adapters/desktop-app-runtime.d.ts.map +1 -0
  426. package/data/build/dist/host/cli-adapters/desktop-app-runtime.js +121 -0
  427. package/data/build/dist/host/cli-adapters/desktop-app-runtime.js.map +1 -0
  428. package/data/build/dist/host/cli-adapters/driver.d.ts.map +1 -0
  429. package/data/build/dist/host/cli-adapters/driver.js.map +1 -0
  430. package/data/build/dist/host/cli-adapters/dsh-message-projector.d.ts.map +1 -0
  431. package/data/build/dist/host/cli-adapters/dsh-message-projector.js +5 -4
  432. package/data/build/dist/host/cli-adapters/dsh-message-projector.js.map +1 -0
  433. package/data/build/dist/host/cli-adapters/dsh-tool-history.d.ts.map +1 -0
  434. package/data/build/dist/host/cli-adapters/dsh-tool-history.js +49 -1
  435. package/data/build/dist/host/cli-adapters/dsh-tool-history.js.map +1 -0
  436. package/data/build/dist/host/cli-adapters/dsh-virtual-providers.d.ts +16 -0
  437. package/data/build/dist/host/cli-adapters/dsh-virtual-providers.d.ts.map +1 -0
  438. package/data/build/dist/host/cli-adapters/dsh-virtual-providers.js +73 -0
  439. package/data/build/dist/host/cli-adapters/dsh-virtual-providers.js.map +1 -0
  440. package/data/build/dist/host/cli-adapters/feature.d.ts.map +1 -0
  441. package/data/build/dist/host/cli-adapters/feature.js +348 -19
  442. package/data/build/dist/host/cli-adapters/feature.js.map +1 -0
  443. package/data/build/dist/host/cli-adapters/gemini-driver.d.ts.map +1 -0
  444. package/data/build/dist/host/cli-adapters/gemini-driver.js +27 -8
  445. package/data/build/dist/host/cli-adapters/gemini-driver.js.map +1 -0
  446. package/data/build/dist/host/cli-adapters/grok-driver.d.ts.map +1 -0
  447. package/data/build/dist/host/cli-adapters/grok-driver.js +27 -9
  448. package/data/build/dist/host/cli-adapters/grok-driver.js.map +1 -0
  449. package/data/build/dist/host/cli-adapters/http-sse-client.d.ts.map +1 -0
  450. package/data/build/dist/host/cli-adapters/http-sse-client.js.map +1 -0
  451. package/data/build/dist/host/cli-adapters/interaction-events.d.ts.map +1 -0
  452. package/data/build/dist/host/cli-adapters/interaction-events.js.map +1 -0
  453. package/data/build/dist/host/cli-adapters/json-rpc-process.d.ts +22 -6
  454. package/data/build/dist/host/cli-adapters/json-rpc-process.d.ts.map +1 -0
  455. package/data/build/dist/host/cli-adapters/json-rpc-process.js +118 -21
  456. package/data/build/dist/host/cli-adapters/json-rpc-process.js.map +1 -0
  457. package/data/build/dist/host/cli-adapters/kimi-driver.d.ts.map +1 -0
  458. package/data/build/dist/host/cli-adapters/kimi-driver.js +33 -7
  459. package/data/build/dist/host/cli-adapters/kimi-driver.js.map +1 -0
  460. package/data/build/dist/host/cli-adapters/legacy-session-adapter.d.ts +11 -2
  461. package/data/build/dist/host/cli-adapters/legacy-session-adapter.d.ts.map +1 -0
  462. package/data/build/dist/host/cli-adapters/legacy-session-adapter.js +15 -6
  463. package/data/build/dist/host/cli-adapters/legacy-session-adapter.js.map +1 -0
  464. package/data/build/dist/host/cli-adapters/legacy-session-settings.d.ts.map +1 -0
  465. package/data/build/dist/host/cli-adapters/legacy-session-settings.js.map +1 -0
  466. package/data/build/dist/host/cli-adapters/mcode-catalog.d.ts +23 -0
  467. package/data/build/dist/host/cli-adapters/mcode-catalog.d.ts.map +1 -0
  468. package/data/build/dist/host/cli-adapters/mcode-catalog.js +120 -0
  469. package/data/build/dist/host/cli-adapters/mcode-catalog.js.map +1 -0
  470. package/data/build/dist/host/cli-adapters/mcode-driver.d.ts +56 -0
  471. package/data/build/dist/host/cli-adapters/mcode-driver.d.ts.map +1 -0
  472. package/data/build/dist/host/cli-adapters/mcode-driver.js +544 -0
  473. package/data/build/dist/host/cli-adapters/mcode-driver.js.map +1 -0
  474. package/data/build/dist/host/cli-adapters/model-catalog.d.ts +30 -5
  475. package/data/build/dist/host/cli-adapters/model-catalog.d.ts.map +1 -0
  476. package/data/build/dist/host/cli-adapters/model-catalog.js +83 -8
  477. package/data/build/dist/host/cli-adapters/model-catalog.js.map +1 -0
  478. package/data/build/dist/host/cli-adapters/native-subagent-dispatch.d.ts +51 -0
  479. package/data/build/dist/host/cli-adapters/native-subagent-dispatch.d.ts.map +1 -0
  480. package/data/build/dist/host/cli-adapters/native-subagent-dispatch.js +193 -0
  481. package/data/build/dist/host/cli-adapters/native-subagent-dispatch.js.map +1 -0
  482. package/data/build/dist/host/cli-adapters/native-subagent-holder.d.ts +4 -0
  483. package/data/build/dist/host/cli-adapters/native-subagent-holder.d.ts.map +1 -0
  484. package/data/build/dist/host/cli-adapters/native-subagent-holder.js +4 -0
  485. package/data/build/dist/host/cli-adapters/native-subagent-holder.js.map +1 -0
  486. package/data/build/dist/host/cli-adapters/native-team-proxy.d.ts.map +1 -0
  487. package/data/build/dist/host/cli-adapters/native-team-proxy.js +18 -15
  488. package/data/build/dist/host/cli-adapters/native-team-proxy.js.map +1 -0
  489. package/data/build/dist/host/cli-adapters/native-team-subagent.d.ts +45 -0
  490. package/data/build/dist/host/cli-adapters/native-team-subagent.d.ts.map +1 -0
  491. package/data/build/dist/host/cli-adapters/native-team-subagent.js +107 -0
  492. package/data/build/dist/host/cli-adapters/native-team-subagent.js.map +1 -0
  493. package/data/build/dist/host/cli-adapters/official-provider-subscription.d.ts.map +1 -0
  494. package/data/build/dist/host/cli-adapters/official-provider-subscription.js.map +1 -0
  495. package/data/build/dist/host/cli-adapters/opencode-driver.d.ts.map +1 -0
  496. package/data/build/dist/host/cli-adapters/opencode-driver.js +20 -4
  497. package/data/build/dist/host/cli-adapters/opencode-driver.js.map +1 -0
  498. package/data/build/dist/host/cli-adapters/pi-driver.d.ts.map +1 -0
  499. package/data/build/dist/host/cli-adapters/pi-driver.js +30 -8
  500. package/data/build/dist/host/cli-adapters/pi-driver.js.map +1 -0
  501. package/data/build/dist/host/cli-adapters/process-utils.d.ts.map +1 -0
  502. package/data/build/dist/host/cli-adapters/process-utils.js.map +1 -0
  503. package/data/build/dist/host/cli-adapters/provider-registry.d.ts.map +1 -0
  504. package/data/build/dist/host/cli-adapters/provider-registry.js.map +1 -0
  505. package/data/build/dist/host/cli-adapters/provider-subscription.d.ts +8 -1
  506. package/data/build/dist/host/cli-adapters/provider-subscription.d.ts.map +1 -0
  507. package/data/build/dist/host/cli-adapters/provider-subscription.js +98 -2
  508. package/data/build/dist/host/cli-adapters/provider-subscription.js.map +1 -0
  509. package/data/build/dist/host/cli-adapters/registry-holder.d.ts +4 -0
  510. package/data/build/dist/host/cli-adapters/registry-holder.d.ts.map +1 -0
  511. package/data/build/dist/host/cli-adapters/registry-holder.js +9 -0
  512. package/data/build/dist/host/cli-adapters/registry-holder.js.map +1 -0
  513. package/data/build/dist/host/cli-adapters/registry.d.ts +13 -0
  514. package/data/build/dist/host/cli-adapters/registry.d.ts.map +1 -0
  515. package/data/build/dist/host/cli-adapters/registry.js +37 -0
  516. package/data/build/dist/host/cli-adapters/registry.js.map +1 -0
  517. package/data/build/dist/host/cli-adapters/rpc-driver-utils.d.ts.map +1 -0
  518. package/data/build/dist/host/cli-adapters/rpc-driver-utils.js.map +1 -0
  519. package/data/build/dist/host/cli-adapters/session-probe.d.ts.map +1 -0
  520. package/data/build/dist/host/cli-adapters/session-probe.js.map +1 -0
  521. package/data/build/dist/host/cli-adapters/session-store.d.ts +6 -1
  522. package/data/build/dist/host/cli-adapters/session-store.d.ts.map +1 -0
  523. package/data/build/dist/host/cli-adapters/session-store.js +42 -4
  524. package/data/build/dist/host/cli-adapters/session-store.js.map +1 -0
  525. package/data/build/dist/host/cli-adapters/standard-stream-driver.d.ts +2 -0
  526. package/data/build/dist/host/cli-adapters/standard-stream-driver.d.ts.map +1 -0
  527. package/data/build/dist/host/cli-adapters/standard-stream-driver.js +30 -4
  528. package/data/build/dist/host/cli-adapters/standard-stream-driver.js.map +1 -0
  529. package/data/build/dist/host/cli-adapters/stream-normalizer.d.ts.map +1 -0
  530. package/data/build/dist/host/cli-adapters/stream-normalizer.js.map +1 -0
  531. package/data/build/dist/host/cli-adapters/subagent-tool.d.ts +5 -0
  532. package/data/build/dist/host/cli-adapters/subagent-tool.d.ts.map +1 -0
  533. package/data/build/dist/host/cli-adapters/subagent-tool.js +66 -0
  534. package/data/build/dist/host/cli-adapters/subagent-tool.js.map +1 -0
  535. package/data/build/dist/host/cli-adapters/tool-observation.d.ts.map +1 -0
  536. package/data/build/dist/host/cli-adapters/tool-observation.js.map +1 -0
  537. package/data/build/dist/host/cli-adapters/zcode-driver.d.ts +57 -0
  538. package/data/build/dist/host/cli-adapters/zcode-driver.d.ts.map +1 -0
  539. package/data/build/dist/host/cli-adapters/zcode-driver.js +843 -0
  540. package/data/build/dist/host/cli-adapters/zcode-driver.js.map +1 -0
  541. package/data/build/dist/host/cli-adapters/zcode-subscription.d.ts +28 -0
  542. package/data/build/dist/host/cli-adapters/zcode-subscription.d.ts.map +1 -0
  543. package/data/build/dist/host/cli-adapters/zcode-subscription.js +212 -0
  544. package/data/build/dist/host/cli-adapters/zcode-subscription.js.map +1 -0
  545. package/data/build/dist/host/cli-bridge/bridge-holder.d.ts +27 -0
  546. package/data/build/dist/host/cli-bridge/bridge-holder.d.ts.map +1 -0
  547. package/data/build/dist/host/cli-bridge/bridge-holder.js +51 -0
  548. package/data/build/dist/host/cli-bridge/bridge-holder.js.map +1 -0
  549. package/data/build/dist/host/cli-bridge/bridge-server.d.ts +34 -0
  550. package/data/build/dist/host/cli-bridge/bridge-server.d.ts.map +1 -0
  551. package/data/build/dist/host/cli-bridge/bridge-server.js +135 -0
  552. package/data/build/dist/host/cli-bridge/bridge-server.js.map +1 -0
  553. package/data/build/dist/host/cli-bridge/command-code-mod.d.ts +25 -0
  554. package/data/build/dist/host/cli-bridge/command-code-mod.d.ts.map +1 -0
  555. package/data/build/dist/host/cli-bridge/command-code-mod.js +60 -0
  556. package/data/build/dist/host/cli-bridge/command-code-mod.js.map +1 -0
  557. package/data/build/dist/host/cli-bridge/dispatch.d.ts +19 -0
  558. package/data/build/dist/host/cli-bridge/dispatch.d.ts.map +1 -0
  559. package/data/build/dist/host/cli-bridge/dispatch.js +90 -0
  560. package/data/build/dist/host/cli-bridge/dispatch.js.map +1 -0
  561. package/data/build/dist/host/cli-bridge/injections.d.ts +28 -0
  562. package/data/build/dist/host/cli-bridge/injections.d.ts.map +1 -0
  563. package/data/build/dist/host/cli-bridge/injections.js +131 -0
  564. package/data/build/dist/host/cli-bridge/injections.js.map +1 -0
  565. package/data/build/dist/host/cli-bridge/mcp-stdio-entry.d.ts +8 -0
  566. package/data/build/dist/host/cli-bridge/mcp-stdio-entry.d.ts.map +1 -0
  567. package/data/build/dist/host/cli-bridge/mcp-stdio-entry.js +151 -0
  568. package/data/build/dist/host/cli-bridge/mcp-stdio-entry.js.map +1 -0
  569. package/data/build/dist/host/control-api-client.d.ts.map +1 -0
  570. package/data/build/dist/host/control-api-client.js.map +1 -0
  571. package/data/build/dist/host/credential-store.d.ts.map +1 -0
  572. package/data/build/dist/host/credential-store.js.map +1 -0
  573. package/data/build/dist/host/debug.d.ts.map +1 -0
  574. package/data/build/dist/host/debug.js.map +1 -0
  575. package/data/build/dist/host/dsh-device-runtime.d.ts.map +1 -0
  576. package/data/build/dist/host/dsh-device-runtime.js.map +1 -0
  577. package/data/build/dist/host/dsh-gateway-feature.d.ts.map +1 -0
  578. package/data/build/dist/host/dsh-gateway-feature.js.map +1 -0
  579. package/data/build/dist/host/dsh-runtime-version.d.ts.map +1 -0
  580. package/data/build/dist/host/dsh-runtime-version.js.map +1 -0
  581. package/data/build/dist/host/features/auth.d.ts.map +1 -0
  582. package/data/build/dist/host/features/auth.js.map +1 -0
  583. package/data/build/dist/host/features/debug.d.ts.map +1 -0
  584. package/data/build/dist/host/features/debug.js.map +1 -0
  585. package/data/build/dist/host/features/file-management.d.ts.map +1 -0
  586. package/data/build/dist/host/features/file-management.js.map +1 -0
  587. package/data/build/dist/host/features/git-management.d.ts.map +1 -0
  588. package/data/build/dist/host/features/git-management.js +97 -10
  589. package/data/build/dist/host/features/git-management.js.map +1 -0
  590. package/data/build/dist/host/features/host-status.d.ts.map +1 -0
  591. package/data/build/dist/host/features/host-status.js.map +1 -0
  592. package/data/build/dist/host/features/index.d.ts.map +1 -0
  593. package/data/build/dist/host/features/index.js.map +1 -0
  594. package/data/build/dist/host/features/lan-access-dsh.d.ts.map +1 -0
  595. package/data/build/dist/host/features/lan-access-dsh.js +34 -1
  596. package/data/build/dist/host/features/lan-access-dsh.js.map +1 -0
  597. package/data/build/dist/host/features/peer-host.d.ts.map +1 -0
  598. package/data/build/dist/host/features/peer-host.js +341 -20
  599. package/data/build/dist/host/features/peer-host.js.map +1 -0
  600. package/data/build/dist/host/features/terminal-process.d.ts.map +1 -0
  601. package/data/build/dist/host/features/terminal-process.js.map +1 -0
  602. package/data/build/dist/host/features/terminal-status.d.ts.map +1 -0
  603. package/data/build/dist/host/features/terminal-status.js.map +1 -0
  604. package/data/build/dist/host/features/types.d.ts +3 -0
  605. package/data/build/dist/host/features/types.d.ts.map +1 -0
  606. package/data/build/dist/host/features/types.js.map +1 -0
  607. package/data/build/dist/host/host-router.d.ts.map +1 -0
  608. package/data/build/dist/host/host-router.js.map +1 -0
  609. package/data/build/dist/host/index-injection.d.ts +15 -0
  610. package/data/build/dist/host/index-injection.d.ts.map +1 -0
  611. package/data/build/dist/host/index-injection.js +45 -0
  612. package/data/build/dist/host/index-injection.js.map +1 -0
  613. package/data/build/dist/host/index.d.ts +12 -2
  614. package/data/build/dist/host/index.d.ts.map +1 -0
  615. package/data/build/dist/host/index.js +75 -3
  616. package/data/build/dist/host/index.js.map +1 -0
  617. package/data/build/dist/host/lan-access-dsh.d.ts +93 -2
  618. package/data/build/dist/host/lan-access-dsh.d.ts.map +1 -0
  619. package/data/build/dist/host/lan-access-dsh.js +438 -27
  620. package/data/build/dist/host/lan-access-dsh.js.map +1 -0
  621. package/data/build/dist/host/login-attempt-guard.d.ts +55 -0
  622. package/data/build/dist/host/login-attempt-guard.d.ts.map +1 -0
  623. package/data/build/dist/host/login-attempt-guard.js +201 -0
  624. package/data/build/dist/host/login-attempt-guard.js.map +1 -0
  625. package/data/build/dist/host/modules/peer-host/aggregated-host-transport.d.ts +146 -0
  626. package/data/build/dist/host/modules/peer-host/aggregated-host-transport.d.ts.map +1 -0
  627. package/data/build/dist/host/modules/peer-host/aggregated-host-transport.js +322 -0
  628. package/data/build/dist/host/modules/peer-host/aggregated-host-transport.js.map +1 -0
  629. package/data/build/dist/host/modules/peer-host/dsh-native-summary-source.d.ts +8 -0
  630. package/data/build/dist/host/modules/peer-host/dsh-native-summary-source.d.ts.map +1 -0
  631. package/data/build/dist/host/modules/peer-host/dsh-native-summary-source.js +120 -0
  632. package/data/build/dist/host/modules/peer-host/dsh-native-summary-source.js.map +1 -0
  633. package/data/build/dist/host/modules/peer-host/host-api-proxy-service.d.ts +25 -0
  634. package/data/build/dist/host/modules/peer-host/host-api-proxy-service.d.ts.map +1 -0
  635. package/data/build/dist/host/modules/peer-host/host-api-proxy-service.js +26 -3
  636. package/data/build/dist/host/modules/peer-host/host-api-proxy-service.js.map +1 -0
  637. package/data/build/dist/host/modules/peer-host/host-ws-connector.d.ts.map +1 -0
  638. package/data/build/dist/host/modules/peer-host/host-ws-connector.js.map +1 -0
  639. package/data/build/dist/host/modules/peer-host/host-ws-proxy-service.d.ts.map +1 -0
  640. package/data/build/dist/host/modules/peer-host/host-ws-proxy-service.js.map +1 -0
  641. package/data/build/dist/host/modules/peer-host/peer-host-aggregate-service.d.ts +10 -0
  642. package/data/build/dist/host/modules/peer-host/peer-host-aggregate-service.d.ts.map +1 -0
  643. package/data/build/dist/host/modules/peer-host/peer-host-aggregate-service.js +27 -12
  644. package/data/build/dist/host/modules/peer-host/peer-host-aggregate-service.js.map +1 -0
  645. package/data/build/dist/host/modules/peer-host/peer-host-diagnostics.d.ts.map +1 -0
  646. package/data/build/dist/host/modules/peer-host/peer-host-diagnostics.js +3 -0
  647. package/data/build/dist/host/modules/peer-host/peer-host-diagnostics.js.map +1 -0
  648. package/data/build/dist/host/modules/peer-host/peer-host-handshake.d.ts +2 -0
  649. package/data/build/dist/host/modules/peer-host/peer-host-handshake.d.ts.map +1 -0
  650. package/data/build/dist/host/modules/peer-host/peer-host-handshake.js +6 -0
  651. package/data/build/dist/host/modules/peer-host/peer-host-handshake.js.map +1 -0
  652. package/data/build/dist/host/modules/peer-host/peer-host-native-dispatch.d.ts +17 -0
  653. package/data/build/dist/host/modules/peer-host/peer-host-native-dispatch.d.ts.map +1 -0
  654. package/data/build/dist/host/modules/peer-host/peer-host-native-dispatch.js +52 -0
  655. package/data/build/dist/host/modules/peer-host/peer-host-native-dispatch.js.map +1 -0
  656. package/data/build/dist/host/modules/peer-host/peer-host-native-protocol.d.ts +25 -0
  657. package/data/build/dist/host/modules/peer-host/peer-host-native-protocol.d.ts.map +1 -0
  658. package/data/build/dist/host/modules/peer-host/peer-host-native-protocol.js +187 -0
  659. package/data/build/dist/host/modules/peer-host/peer-host-native-protocol.js.map +1 -0
  660. package/data/build/dist/host/modules/peer-host/peer-host-native-transport.d.ts +30 -0
  661. package/data/build/dist/host/modules/peer-host/peer-host-native-transport.d.ts.map +1 -0
  662. package/data/build/dist/host/modules/peer-host/peer-host-native-transport.js +120 -0
  663. package/data/build/dist/host/modules/peer-host/peer-host-native-transport.js.map +1 -0
  664. package/data/build/dist/host/modules/peer-host/peer-host-relay.d.ts.map +1 -0
  665. package/data/build/dist/host/modules/peer-host/peer-host-relay.js.map +1 -0
  666. package/data/build/dist/host/modules/peer-host/peer-host-remote-summary-source.d.ts +60 -0
  667. package/data/build/dist/host/modules/peer-host/peer-host-remote-summary-source.d.ts.map +1 -0
  668. package/data/build/dist/host/modules/peer-host/peer-host-remote-summary-source.js +181 -0
  669. package/data/build/dist/host/modules/peer-host/peer-host-remote-summary-source.js.map +1 -0
  670. package/data/build/dist/host/modules/peer-host/peer-host-session.d.ts +20 -1
  671. package/data/build/dist/host/modules/peer-host/peer-host-session.d.ts.map +1 -0
  672. package/data/build/dist/host/modules/peer-host/peer-host-session.js +118 -37
  673. package/data/build/dist/host/modules/peer-host/peer-host-session.js.map +1 -0
  674. package/data/build/dist/host/modules/peer-host/peer-host-store.d.ts +21 -0
  675. package/data/build/dist/host/modules/peer-host/peer-host-store.d.ts.map +1 -0
  676. package/data/build/dist/host/modules/peer-host/peer-host-store.js +65 -3
  677. package/data/build/dist/host/modules/peer-host/peer-host-store.js.map +1 -0
  678. package/data/build/dist/host/modules/peer-host/peer-host-virtual-registry.d.ts +49 -0
  679. package/data/build/dist/host/modules/peer-host/peer-host-virtual-registry.d.ts.map +1 -0
  680. package/data/build/dist/host/modules/peer-host/peer-host-virtual-registry.js +174 -0
  681. package/data/build/dist/host/modules/peer-host/peer-host-virtual-registry.js.map +1 -0
  682. package/data/build/dist/host/modules/peer-host/peer-host-ws-gateway.d.ts.map +1 -0
  683. package/data/build/dist/host/modules/peer-host/peer-host-ws-gateway.js.map +1 -0
  684. package/data/build/dist/host/modules/pwa/index.d.ts +7 -0
  685. package/data/build/dist/host/modules/pwa/index.d.ts.map +1 -0
  686. package/data/build/dist/host/modules/pwa/index.js +7 -0
  687. package/data/build/dist/host/modules/pwa/index.js.map +1 -0
  688. package/data/build/dist/host/modules/pwa/pwa-assets.d.ts +50 -0
  689. package/data/build/dist/host/modules/pwa/pwa-assets.d.ts.map +1 -0
  690. package/data/build/dist/host/modules/pwa/pwa-assets.js +182 -0
  691. package/data/build/dist/host/modules/pwa/pwa-assets.js.map +1 -0
  692. package/data/build/dist/host/modules/pwa/pwa-client-script.d.ts +10 -0
  693. package/data/build/dist/host/modules/pwa/pwa-client-script.d.ts.map +1 -0
  694. package/data/build/dist/host/modules/pwa/pwa-client-script.js +38 -0
  695. package/data/build/dist/host/modules/pwa/pwa-client-script.js.map +1 -0
  696. package/data/build/dist/host/modules/pwa/pwa-icons.d.ts +10 -0
  697. package/data/build/dist/host/modules/pwa/pwa-icons.d.ts.map +1 -0
  698. package/data/build/dist/host/modules/pwa/pwa-icons.js +185 -0
  699. package/data/build/dist/host/modules/pwa/pwa-icons.js.map +1 -0
  700. package/data/build/dist/host/modules/pwa/pwa-push.d.ts +74 -0
  701. package/data/build/dist/host/modules/pwa/pwa-push.d.ts.map +1 -0
  702. package/data/build/dist/host/modules/pwa/pwa-push.js +288 -0
  703. package/data/build/dist/host/modules/pwa/pwa-push.js.map +1 -0
  704. package/data/build/dist/host/modules/pwa/pwa-session-notifications.d.ts +17 -0
  705. package/data/build/dist/host/modules/pwa/pwa-session-notifications.d.ts.map +1 -0
  706. package/data/build/dist/host/modules/pwa/pwa-session-notifications.js +82 -0
  707. package/data/build/dist/host/modules/pwa/pwa-session-notifications.js.map +1 -0
  708. package/data/build/dist/host/modules/pwa/pwa-viewport.d.ts +12 -0
  709. package/data/build/dist/host/modules/pwa/pwa-viewport.d.ts.map +1 -0
  710. package/data/build/dist/host/modules/pwa/pwa-viewport.js +47 -0
  711. package/data/build/dist/host/modules/pwa/pwa-viewport.js.map +1 -0
  712. package/data/build/dist/host/native-session-bridge.d.ts.map +1 -0
  713. package/data/build/dist/host/native-session-bridge.js +86 -55
  714. package/data/build/dist/host/native-session-bridge.js.map +1 -0
  715. package/data/build/dist/host/relay-tunnel-runtime.d.ts +33 -0
  716. package/data/build/dist/host/relay-tunnel-runtime.d.ts.map +1 -0
  717. package/data/build/dist/host/relay-tunnel-runtime.js +71 -19
  718. package/data/build/dist/host/relay-tunnel-runtime.js.map +1 -0
  719. package/data/build/dist/host/remote-web-runtime.d.ts.map +1 -0
  720. package/data/build/dist/host/remote-web-runtime.js.map +1 -0
  721. package/data/build/dist/host/rpc-table.d.ts.map +1 -0
  722. package/data/build/dist/host/rpc-table.js.map +1 -0
  723. package/data/build/dist/host/rpc.d.ts.map +1 -0
  724. package/data/build/dist/host/rpc.js +21 -6
  725. package/data/build/dist/host/rpc.js.map +1 -0
  726. package/data/build/dist/host/session-changes.d.ts.map +1 -0
  727. package/data/build/dist/host/session-changes.js.map +1 -0
  728. package/data/build/dist/host/session-migration-repair.d.ts.map +1 -0
  729. package/data/build/dist/host/session-migration-repair.js.map +1 -0
  730. package/data/build/dist/host/settings.d.ts.map +1 -0
  731. package/data/build/dist/host/settings.js +33 -1
  732. package/data/build/dist/host/settings.js.map +1 -0
  733. package/data/build/dist/host/terminal/attachment-registry.d.ts.map +1 -0
  734. package/data/build/dist/host/terminal/attachment-registry.js.map +1 -0
  735. package/data/build/dist/host/terminal/backends/conpty-backend.d.ts.map +1 -0
  736. package/data/build/dist/host/terminal/backends/conpty-backend.js.map +1 -0
  737. package/data/build/dist/host/terminal/backends/local-pty-backend.d.ts.map +1 -0
  738. package/data/build/dist/host/terminal/backends/local-pty-backend.js.map +1 -0
  739. package/data/build/dist/host/terminal/backends/tmux-backend.d.ts.map +1 -0
  740. package/data/build/dist/host/terminal/backends/tmux-backend.js.map +1 -0
  741. package/data/build/dist/host/terminal/broker/conpty-broker-client.d.ts.map +1 -0
  742. package/data/build/dist/host/terminal/broker/conpty-broker-client.js.map +1 -0
  743. package/data/build/dist/host/terminal/broker/conpty-broker-process.d.ts.map +1 -0
  744. package/data/build/dist/host/terminal/broker/conpty-broker-process.js.map +1 -0
  745. package/data/build/dist/host/terminal/broker/conpty-broker-protocol.d.ts.map +1 -0
  746. package/data/build/dist/host/terminal/broker/conpty-broker-protocol.js.map +1 -0
  747. package/data/build/dist/host/terminal/controller-factory.d.ts.map +1 -0
  748. package/data/build/dist/host/terminal/controller-factory.js.map +1 -0
  749. package/data/build/dist/host/terminal/index.d.ts.map +1 -0
  750. package/data/build/dist/host/terminal/index.js.map +1 -0
  751. package/data/build/dist/host/terminal/runtime-adapter.d.ts.map +1 -0
  752. package/data/build/dist/host/terminal/runtime-adapter.js.map +1 -0
  753. package/data/build/dist/host/terminal/runtime-manager.d.ts.map +1 -0
  754. package/data/build/dist/host/terminal/runtime-manager.js.map +1 -0
  755. package/data/build/dist/host/terminal/shell-detection.d.ts.map +1 -0
  756. package/data/build/dist/host/terminal/shell-detection.js.map +1 -0
  757. package/data/build/dist/host/terminal/startup.d.ts.map +1 -0
  758. package/data/build/dist/host/terminal/startup.js.map +1 -0
  759. package/data/build/dist/host/terminal/terminal-controller.d.ts.map +1 -0
  760. package/data/build/dist/host/terminal/terminal-controller.js.map +1 -0
  761. package/data/build/dist/host/terminal/terminal-process-service.d.ts.map +1 -0
  762. package/data/build/dist/host/terminal/terminal-process-service.js.map +1 -0
  763. package/data/build/dist/host/terminal/terminal-process-store.d.ts.map +1 -0
  764. package/data/build/dist/host/terminal/terminal-process-store.js.map +1 -0
  765. package/data/build/dist/host/terminal/terminal-service.d.ts.map +1 -0
  766. package/data/build/dist/host/terminal/terminal-service.js.map +1 -0
  767. package/data/build/dist/host/terminal/terminal-store.d.ts.map +1 -0
  768. package/data/build/dist/host/terminal/terminal-store.js.map +1 -0
  769. package/data/build/dist/index.d.ts +2 -2
  770. package/data/build/dist/index.d.ts.map +1 -0
  771. package/data/build/dist/index.js +2 -2
  772. package/data/build/dist/index.js.map +1 -0
  773. package/data/build/dist/shared/contracts/auth.d.ts.map +1 -0
  774. package/data/build/dist/shared/contracts/auth.js.map +1 -0
  775. package/data/build/dist/shared/contracts/cli-adapter.d.ts +35 -0
  776. package/data/build/dist/shared/contracts/cli-adapter.d.ts.map +1 -0
  777. package/data/build/dist/shared/contracts/cli-adapter.js.map +1 -0
  778. package/data/build/dist/shared/contracts/command-code.d.ts.map +1 -0
  779. package/data/build/dist/shared/contracts/command-code.js.map +1 -0
  780. package/data/build/dist/shared/contracts/config.d.ts +89 -0
  781. package/data/build/dist/shared/contracts/config.d.ts.map +1 -0
  782. package/data/build/dist/shared/contracts/config.js +92 -0
  783. package/data/build/dist/shared/contracts/config.js.map +1 -0
  784. package/data/build/dist/shared/contracts/debug-config.d.ts.map +1 -0
  785. package/data/build/dist/shared/contracts/debug-config.js.map +1 -0
  786. package/data/build/dist/shared/contracts/debug.d.ts.map +1 -0
  787. package/data/build/dist/shared/contracts/debug.js.map +1 -0
  788. package/data/build/dist/shared/contracts/dsh-device.d.ts.map +1 -0
  789. package/data/build/dist/shared/contracts/dsh-device.js.map +1 -0
  790. package/data/build/dist/shared/contracts/errors.d.ts +2 -2
  791. package/data/build/dist/shared/contracts/errors.d.ts.map +1 -0
  792. package/data/build/dist/shared/contracts/errors.js.map +1 -0
  793. package/data/build/dist/shared/contracts/feature.d.ts.map +1 -0
  794. package/data/build/dist/shared/contracts/feature.js.map +1 -0
  795. package/data/build/dist/shared/contracts/file-management.d.ts.map +1 -0
  796. package/data/build/dist/shared/contracts/file-management.js.map +1 -0
  797. package/data/build/dist/shared/contracts/git.d.ts +15 -1
  798. package/data/build/dist/shared/contracts/git.d.ts.map +1 -0
  799. package/data/build/dist/shared/contracts/git.js.map +1 -0
  800. package/data/build/dist/shared/contracts/host-status.d.ts.map +1 -0
  801. package/data/build/dist/shared/contracts/host-status.js.map +1 -0
  802. package/data/build/dist/shared/contracts/lan-access-dsh.d.ts +23 -0
  803. package/data/build/dist/shared/contracts/lan-access-dsh.d.ts.map +1 -0
  804. package/data/build/dist/shared/contracts/lan-access-dsh.js.map +1 -0
  805. package/data/build/dist/shared/contracts/peer-host.d.ts +160 -1
  806. package/data/build/dist/shared/contracts/peer-host.d.ts.map +1 -0
  807. package/data/build/dist/shared/contracts/peer-host.js +73 -0
  808. package/data/build/dist/shared/contracts/peer-host.js.map +1 -0
  809. package/data/build/dist/shared/contracts/signaling.d.ts.map +1 -0
  810. package/data/build/dist/shared/contracts/signaling.js.map +1 -0
  811. package/data/build/dist/shared/contracts/subscription.d.ts +15 -0
  812. package/data/build/dist/shared/contracts/subscription.d.ts.map +1 -0
  813. package/data/build/dist/shared/contracts/subscription.js.map +1 -0
  814. package/data/build/dist/shared/contracts/terminal-process.d.ts.map +1 -0
  815. package/data/build/dist/shared/contracts/terminal-process.js.map +1 -0
  816. package/data/build/dist/shared/contracts/terminal.d.ts.map +1 -0
  817. package/data/build/dist/shared/contracts/terminal.js.map +1 -0
  818. package/data/build/dist/shared/contracts/transport.d.ts.map +1 -0
  819. package/data/build/dist/shared/contracts/transport.js.map +1 -0
  820. package/data/build/dist/shared/contracts/version.d.ts +14 -6
  821. package/data/build/dist/shared/contracts/version.d.ts.map +1 -0
  822. package/data/build/dist/shared/contracts/version.js +23 -8
  823. package/data/build/dist/shared/contracts/version.js.map +1 -0
  824. package/data/build/dist/shared/debug.d.ts.map +1 -0
  825. package/data/build/dist/shared/debug.js.map +1 -0
  826. package/data/build/dist/shared/index.d.ts +6 -6
  827. package/data/build/dist/shared/index.d.ts.map +1 -0
  828. package/data/build/dist/shared/index.js +3 -3
  829. package/data/build/dist/shared/index.js.map +1 -0
  830. package/data/build/dist/transport/carrier.d.ts.map +1 -0
  831. package/data/build/dist/transport/carrier.js.map +1 -0
  832. package/data/build/dist/transport/debug.d.ts.map +1 -0
  833. package/data/build/dist/transport/debug.js +2 -0
  834. package/data/build/dist/transport/debug.js.map +1 -0
  835. package/data/build/dist/transport/dsh-envelope.d.ts.map +1 -0
  836. package/data/build/dist/transport/dsh-envelope.js.map +1 -0
  837. package/data/build/dist/transport/dsh-gateway.d.ts.map +1 -0
  838. package/data/build/dist/transport/dsh-gateway.js.map +1 -0
  839. package/data/build/dist/transport/dsh-session.d.ts.map +1 -0
  840. package/data/build/dist/transport/dsh-session.js.map +1 -0
  841. package/data/build/dist/transport/dsh-transport.d.ts.map +1 -0
  842. package/data/build/dist/transport/dsh-transport.js.map +1 -0
  843. package/data/build/dist/transport/frame.d.ts.map +1 -0
  844. package/data/build/dist/transport/frame.js.map +1 -0
  845. package/data/build/dist/transport/index.d.ts +1 -1
  846. package/data/build/dist/transport/index.d.ts.map +1 -0
  847. package/data/build/dist/transport/index.js +1 -1
  848. package/data/build/dist/transport/index.js.map +1 -0
  849. package/data/build/dist/transport/multiplexer.d.ts.map +1 -0
  850. package/data/build/dist/transport/multiplexer.js.map +1 -0
  851. package/data/build/dist/transport/webrtc-client.d.ts +8 -0
  852. package/data/build/dist/transport/webrtc-client.d.ts.map +1 -0
  853. package/data/build/dist/transport/webrtc-client.js +135 -9
  854. package/data/build/dist/transport/webrtc-client.js.map +1 -0
  855. package/data/build/dist/transport/webrtc-host.d.ts.map +1 -0
  856. package/data/build/dist/transport/webrtc-host.js +5 -1
  857. package/data/build/dist/transport/webrtc-host.js.map +1 -0
  858. package/data/build/dist/typert.host.d.ts.map +1 -0
  859. package/data/build/dist/typert.host.js.map +1 -0
  860. package/data/build/dist/typert.remote-client.d.ts.map +1 -0
  861. package/data/build/dist/typert.remote-client.js.map +1 -0
  862. package/package.json +36 -19
  863. package/profile/README.md +18 -5
  864. package/profile/package.json +3 -3
  865. package/profile/scripts/check-dsh-install.mjs +100 -9
  866. package/profile/version.json +3 -3
  867. package/scripts/check-dsh-install.mjs +98 -17
  868. package/version.json +3 -3
  869. package/data/build/dist/client/host-navigation.d.ts +0 -29
  870. package/data/build/dist/client/host-navigation.js +0 -29
  871. package/data/build/dist/client/peer-host-native-session-ui.d.ts +0 -60
  872. package/data/build/dist/client/peer-host-native-session-ui.js +0 -372
@@ -5,7 +5,11 @@ import { createHmac, randomBytes, scryptSync, timingSafeEqual } from 'node:crypt
5
5
  import { homedir } from 'node:os';
6
6
  import { mkdir, readFile, rename, writeFile } from 'node:fs/promises';
7
7
  import { dirname, join } from 'node:path';
8
+ import { normalizeLanAccessDshPwaSettings, DEFAULT_LAN_ACCESS_DSH_PWA_SETTINGS } from '../shared/contracts/config.js';
9
+ import { PWA_ASSET_PREFIX, PWA_MANIFEST_PATH, PWA_SERVICE_WORKER_PATH } from './modules/pwa/index.js';
8
10
  import { CodingNsRpcError } from './rpc-table.js';
11
+ import { createLoginAttemptContext, LoginAttemptGuard } from './login-attempt-guard.js';
12
+ import { hostBrowserText, resolveAcceptLanguageLocale, resolveHostPushLocale } from './browser-text.js';
9
13
  /**
10
14
  * Cookie 不包含端口信息;多个 DSH 实例若共用名称,浏览器会在实例之间覆盖会话。
11
15
  * 正式环境保留旧名称,开发环境由启动包装命令显式指定独立名称。
@@ -139,7 +143,9 @@ export class LanAccessDshProxy {
139
143
  loginConfig = null;
140
144
  /** 当前进程内主动退出的会话;正常会话由签名令牌承载,可跨代理重建复用。 */
141
145
  revokedSessions = new Set();
146
+ loginAttempts = new LoginAttemptGuard();
142
147
  upstreamCookie = null;
148
+ pwaProvider = null;
143
149
  constructor(runtime = createNodeLanAccessDshRuntime(), authenticatedUrl, sessionCookieName = resolveLoginProtectionCookieName()) {
144
150
  this.runtime = runtime;
145
151
  this.authenticatedUrl = authenticatedUrl;
@@ -207,6 +213,7 @@ export class LanAccessDshProxy {
207
213
  socket.destroy();
208
214
  active.sockets.clear();
209
215
  this.revokedSessions.clear();
216
+ this.loginAttempts.reset();
210
217
  await active.close();
211
218
  }
212
219
  async close() {
@@ -217,9 +224,26 @@ export class LanAccessDshProxy {
217
224
  }
218
225
  setLoginConfig(config) {
219
226
  this.loginConfig = config === null ? null : normalizeLoginConfig(config);
227
+ this.loginAttempts.reset();
220
228
  if (config === null || !config.enabled)
221
229
  this.revokedSessions.clear();
222
230
  }
231
+ /** 注入 PWA 资产来源;传 null 表示回到“不提供 PWA 资产”的原始行为。 */
232
+ setPwaProvider(provider) {
233
+ this.pwaProvider = provider;
234
+ }
235
+ /** PWA 资产就绪状态;只描述代理侧能力,不含浏览器状态与凭据。 */
236
+ pwaStatus() {
237
+ const bundle = this.pwaProvider?.snapshot() ?? null;
238
+ return {
239
+ listening: this.active?.state === 'listening',
240
+ manifest: bundle !== null,
241
+ serviceWorker: bundle?.serviceWorker !== null && bundle?.serviceWorker !== undefined,
242
+ marker: bundle?.marker ?? null,
243
+ assetPaths: bundle === null ? [] : [...bundle.assets.keys()],
244
+ paths: { manifest: PWA_MANIFEST_PATH, serviceWorker: PWA_SERVICE_WORKER_PATH },
245
+ };
246
+ }
223
247
  loginSettings() {
224
248
  const config = this.loginConfig;
225
249
  return {
@@ -264,7 +288,7 @@ export class LanAccessDshProxy {
264
288
  // pipe 以便验证连接关系。
265
289
  if (typeof dshSocket.on === 'function') {
266
290
  const localAddress = isLoopbackSocket(localSocket);
267
- const authTransform = new LanAccessDshAuthTransform(localSocket, (request) => this.authorize(request, localAddress));
291
+ const authTransform = new LanAccessDshAuthTransform(localSocket, (request) => this.authorize(request, localAddress, localSocket));
268
292
  const requestTransform = new LanAccessDshRequestTransform(`127.0.0.1:${active.config.dshPort}`, this.upstreamCookie);
269
293
  localSocket.pipe(authTransform);
270
294
  authTransform.pipe(requestTransform);
@@ -286,8 +310,43 @@ export class LanAccessDshProxy {
286
310
  loginEnabled: this.loginConfig?.enabled === true,
287
311
  };
288
312
  }
289
- authorize(request, localAddress) {
313
+ authorize(request, localAddress, localSocket) {
290
314
  const config = this.loginConfig;
315
+ // 登录页与登录错误按浏览器自己的语言渲染;DSH 只支持 zh/en,其它语言回退中文。
316
+ const locale = resolveAcceptLanguageLocale(request.headers['accept-language']);
317
+ const loginContext = createLoginAttemptContext(readRemoteAddress(localSocket), request.headers);
318
+ // PeerHost 的握手和目标 Host 认证端点必须在建立登录保护会话前可达:
319
+ // 握手只返回公开能力摘要,auth/login 负责交换目标 Host 自己签发的短期票据。
320
+ // 其他 API 仍然经过登录保护,不把业务数据面暴露给未登录客户端。
321
+ if (request.method === 'GET' && request.path === '/api/public/host-handshake')
322
+ return 'pass';
323
+ const authResponse = resolvePeerHostAuthResponse(request, config, this.revokedSessions, this.loginAttempts, loginContext);
324
+ if (authResponse !== undefined)
325
+ return authResponse;
326
+ // Host-to-Host 请求不持有浏览器 Cookie,而是由 PeerHost Host 侧注入目标 Host
327
+ // 签发的 Bearer 票据;只放行固定资源白名单,票据本身必须通过签名校验。
328
+ if (isPeerHostRouteRequest(request)) {
329
+ const token = readBearerToken(request.headers.authorization);
330
+ if (token !== undefined) {
331
+ return verifyPeerHostAccessToken(config, token, this.revokedSessions)
332
+ ? 'pass'
333
+ : loginResponse(401, '需要登录');
334
+ }
335
+ }
336
+ // PWA 静态资产先于登录判定:它们只包含公开元数据,未登录时也可取;命中时
337
+ // 直接合成响应,不进入上游转发路径。
338
+ const pwaResponse = this.authorizePwa(request);
339
+ if (pwaResponse !== undefined)
340
+ return pwaResponse;
341
+ if (request.path === '/__codingns/captcha' && request.method === 'GET') {
342
+ const captchaId = readQueryParameter(request.query, 'id');
343
+ const svg = !localAddress && config !== null && config.enabled && config.scopes.lan && captchaId !== undefined
344
+ ? this.loginAttempts.renderCaptcha(captchaId, loginContext)
345
+ : undefined;
346
+ return svg === undefined
347
+ ? synthLanResponse({ status: 404, contentType: 'text/plain; charset=utf-8', body: 'Not Found' })
348
+ : synthLanResponse({ status: 200, contentType: 'image/svg+xml; charset=utf-8', body: svg });
349
+ }
291
350
  if (request.path === '/__codingns/session' && request.method === 'GET') {
292
351
  const token = readCookie(request.headers.cookie, this.sessionCookieName);
293
352
  const authenticated = !localAddress && config !== null && config.enabled && config.scopes.lan
@@ -313,9 +372,26 @@ export class LanAccessDshProxy {
313
372
  return 'pass';
314
373
  if (request.path === '/__codingns/login' && request.method === 'POST') {
315
374
  const form = new URLSearchParams(new TextDecoder().decode(request.body));
316
- if (form.get('username') !== config.username || !verifyPassword(form.get('password') ?? '', config)) {
317
- return loginResponse(401, loginPageWithError('用户名或密码错误', form.get('username') ?? ''));
375
+ const username = form.get('username') ?? '';
376
+ const captchaId = form.get('captchaId') ?? undefined;
377
+ const captchaCode = form.get('captchaCode') ?? undefined;
378
+ const attempt = this.loginAttempts.beforeLogin(loginContext, {
379
+ ...(captchaId === undefined ? {} : { captchaId }),
380
+ ...(captchaCode === undefined ? {} : { captchaCode }),
381
+ });
382
+ if (!attempt.allowed) {
383
+ const challenge = this.loginAttempts.requiresCaptcha(loginContext) ? this.loginAttempts.issueCaptcha(loginContext) : undefined;
384
+ const message = attempt.reason === 'rate_limited'
385
+ ? hostBrowserText(locale, 'login.rateLimited', { seconds: attempt.retryAfterSeconds })
386
+ : hostBrowserText(locale, 'login.badCaptcha');
387
+ return loginResponse(429, loginPageWithError(message, username, challenge, locale), { 'Retry-After': String(attempt.retryAfterSeconds) });
318
388
  }
389
+ if (username !== config.username || !verifyPassword(form.get('password') ?? '', config)) {
390
+ this.loginAttempts.recordFailure(loginContext);
391
+ const challenge = this.loginAttempts.requiresCaptcha(loginContext) ? this.loginAttempts.issueCaptcha(loginContext) : undefined;
392
+ return loginResponse(401, loginPageWithError(hostBrowserText(locale, 'login.badCredentials'), username, challenge, locale));
393
+ }
394
+ this.loginAttempts.recordSuccess(loginContext);
319
395
  const expiresAt = Date.now() + config.timeoutSeconds * 1000;
320
396
  const payload = encodeSessionPayload({ username: config.username, scope: 'lan', expiresAt, nonce: randomBytes(16).toString('base64url') });
321
397
  const token = `${payload}.${signSessionPayload(payload, config)}`;
@@ -336,9 +412,25 @@ export class LanAccessDshProxy {
336
412
  if (token !== undefined && !this.revokedSessions.has(token) && verifySignedSessionToken(token, config, 'lan')) {
337
413
  return 'pass';
338
414
  }
339
- return request.path === '/' || request.path.endsWith('.html')
340
- ? loginResponse(200, loginPage())
341
- : loginResponse(401, '需要登录');
415
+ // 只有真正渲染登录页的 HTML 请求才签发验证码。浏览器会为 favicon、图标等
416
+ // 静态资源发出额外的未登录请求,如果它们也签发验证码,就会不断翻转页面上
417
+ // 已经渲染的 captchaId,用户永远提交不到与图片一致的答案。
418
+ if (request.path !== '/' && !request.path.endsWith('.html'))
419
+ return loginResponse(401, hostBrowserText(locale, 'login.required'));
420
+ const challenge = this.loginAttempts.requiresCaptcha(loginContext) ? this.loginAttempts.issueCaptcha(loginContext) : undefined;
421
+ return loginResponse(200, loginPage(challenge, locale));
422
+ }
423
+ /**
424
+ * PWA 白名单:`/manifest.webmanifest`、`/sw.js` 与 `/__codingns/pwa/*`。
425
+ *
426
+ * 返回 undefined 表示“不属于 PWA 白名单,或当前未启用”,交回原有登录与转发
427
+ * 语义;这样关闭增强时行为与改造前完全一致。合成内容只有公开元数据与图标,
428
+ * 不允许出现任何 Cookie、令牌或宿主路径。
429
+ */
430
+ authorizePwa(request) {
431
+ // manifest 的 description 属于浏览器可见文案,按请求语言选择。
432
+ const locale = resolveAcceptLanguageLocale(request.headers['accept-language']);
433
+ return resolveLanAccessDshPwaResponse(request, this.pwaProvider?.snapshot(locale) ?? null);
342
434
  }
343
435
  /** DSH 启动时的认证 URL 只在 Host 内交换一次 Cookie,绝不下发到浏览器。 */
344
436
  async takeOverDshWebToken() {
@@ -351,10 +443,195 @@ export class LanAccessDshProxy {
351
443
  this.upstreamCookie = cookie;
352
444
  }
353
445
  }
446
+ /**
447
+ * PeerHost 出站请求允许访问的固定路由白名单。
448
+ *
449
+ * 票据校验在调用方完成:这里只回答“这条路由是否属于 Host-to-Host 数据面”,
450
+ * 避免把路径判定和签名校验混在一起,也避免把整个 LAN API 变成公开入口。
451
+ */
452
+ export function isPeerHostRouteRequest(request) {
453
+ const routes = [
454
+ { prefix: '/ws', methods: ['GET'] },
455
+ { prefix: '/api/codingns/host/status', methods: ['POST'] },
456
+ { prefix: '/api/codingns/peerHost/nativeLocal', methods: ['POST'] },
457
+ { prefix: '/api/codingns/peerHost/native', methods: ['POST'] },
458
+ { prefix: '/api/codingns/peerHost/nativeStream', methods: ['POST'] },
459
+ { prefix: '/api/codingns/peerHost/nativeStreamOpen', methods: ['POST'] },
460
+ { prefix: '/api/codingns/peerHost/nativeStreamNext', methods: ['POST'] },
461
+ { prefix: '/api/codingns/peerHost/nativeStreamClose', methods: ['POST'] },
462
+ // 远端对话框的适配器、模型、会话绑定和命令目录都通过 CodingNS CLI RPC
463
+ // 读取;这是 Host-to-Host 数据面,必须与 Host API 代理的白名单保持一致。
464
+ { prefix: '/api/codingns/cli', methods: ['POST'] },
465
+ { prefix: '/api/workspaces', methods: ['GET'] },
466
+ { prefix: '/api/sessions', methods: ['GET', 'POST'] },
467
+ { prefix: '/api/file-tree', methods: ['GET'] },
468
+ { prefix: '/api/files', methods: ['GET', 'PUT', 'POST'] },
469
+ { prefix: '/api/git', methods: ['GET', 'POST'] },
470
+ { prefix: '/api/terminal', methods: ['GET', 'POST'] },
471
+ { prefix: '/api/right-tools', methods: ['GET', 'POST'] },
472
+ ];
473
+ const route = routes.find((candidate) => request.path === candidate.prefix || request.path.startsWith(`${candidate.prefix}/`));
474
+ return route !== undefined && route.methods.includes(request.method.toUpperCase());
475
+ }
476
+ /** PeerHost 目标侧认证端点;路径固定,客户端不能自定义目标或凭据格式。 */
477
+ export const PEER_HOST_AUTH_PATHS = {
478
+ login: '/api/auth/login',
479
+ refresh: '/api/auth/refresh',
480
+ logout: '/api/auth/logout',
481
+ };
482
+ /**
483
+ * PeerHost 目标侧认证裁决。
484
+ *
485
+ * 目标 Host 自己签发短期票据,当前 Host 才能在不保存目标密码的前提下代理请求。
486
+ * 票据复用登录保护的签名材料;登录保护未覆盖局域网范围时返回占位票据,与
487
+ * “未启用保护即放行”的既有语义保持一致。返回 undefined 表示不是认证端点。
488
+ */
489
+ export function resolvePeerHostAuthResponse(request, config, revoked, loginAttempts, loginContext) {
490
+ if (request.method.toUpperCase() !== 'POST')
491
+ return undefined;
492
+ if (request.path === PEER_HOST_AUTH_PATHS.login) {
493
+ const credentials = readJsonBody(request.body);
494
+ const username = typeof credentials?.username === 'string' ? credentials.username : '';
495
+ const password = typeof credentials?.password === 'string' ? credentials.password : '';
496
+ if (!peerHostLoginProtected(config))
497
+ return loginJsonResponse(200, issueOpenPeerHostCredential());
498
+ const attempt = loginAttempts?.beforeLogin(loginContext ?? { ipAddress: 'unknown', deviceFingerprint: 'unknown-device' }, { allowCaptcha: false });
499
+ if (attempt !== undefined && !attempt.allowed) {
500
+ return loginJsonResponse(429, { error: { code: 'PEER_HOST_LOGIN_RATE_LIMITED', message: '目标 Host 登录尝试过于频繁' } }, { 'Retry-After': String(attempt.retryAfterSeconds) });
501
+ }
502
+ if (username === '' || password === '' || username !== config.username || !verifyPassword(password, config)) {
503
+ if (loginAttempts !== undefined)
504
+ loginAttempts.recordFailure(loginContext ?? { ipAddress: 'unknown', deviceFingerprint: 'unknown-device' });
505
+ return loginJsonResponse(401, { error: { code: 'PEER_HOST_SESSION_REQUIRED', message: '目标 Host 用户名或密码错误' } });
506
+ }
507
+ if (loginAttempts !== undefined)
508
+ loginAttempts.recordSuccess(loginContext ?? { ipAddress: 'unknown', deviceFingerprint: 'unknown-device' });
509
+ return loginJsonResponse(200, issuePeerHostCredential(config));
510
+ }
511
+ if (request.path === PEER_HOST_AUTH_PATHS.refresh) {
512
+ const body = readJsonBody(request.body);
513
+ const refreshToken = typeof body?.refreshToken === 'string' ? body.refreshToken : '';
514
+ if (!peerHostLoginProtected(config))
515
+ return loginJsonResponse(200, issueOpenPeerHostCredential());
516
+ if (refreshToken === '' || revoked.has(refreshToken) || !verifySignedSessionToken(refreshToken, config, 'lan')) {
517
+ return loginJsonResponse(401, { error: { code: 'PEER_HOST_SESSION_REQUIRED', message: '目标 Host 登录态已失效' } });
518
+ }
519
+ return loginJsonResponse(200, issuePeerHostCredential(config));
520
+ }
521
+ if (request.path === PEER_HOST_AUTH_PATHS.logout) {
522
+ const token = readBearerToken(request.headers.authorization);
523
+ if (token !== undefined && peerHostLoginProtected(config))
524
+ revoked.add(token);
525
+ return loginJsonResponse(200, { ok: true });
526
+ }
527
+ return undefined;
528
+ }
529
+ /** 校验 PeerHost 出站票据;登录保护未覆盖局域网范围时保持向后兼容。 */
530
+ export function verifyPeerHostAccessToken(config, token, revoked = new Set()) {
531
+ if (!peerHostLoginProtected(config))
532
+ return true;
533
+ return !revoked.has(token) && verifySignedSessionToken(token, config, 'lan');
534
+ }
535
+ export function readBearerToken(value) {
536
+ const match = /^Bearer\s+(\S+)$/u.exec(value?.trim() ?? '');
537
+ return match?.[1];
538
+ }
539
+ function peerHostLoginProtected(config) {
540
+ return config !== null && config.enabled && config.scopes.lan;
541
+ }
542
+ function issuePeerHostCredential(config) {
543
+ return {
544
+ accessToken: issueLoginProtectionSession(config, 'lan').token,
545
+ refreshToken: issueLoginProtectionSession(config, 'lan').token,
546
+ expiresIn: config.timeoutSeconds,
547
+ };
548
+ }
549
+ /** 未启用登录保护时目标不校验票据,这里只保证 Host 侧凭据格式一致。 */
550
+ function issueOpenPeerHostCredential() {
551
+ return {
552
+ accessToken: `open.${randomBytes(16).toString('base64url')}`,
553
+ refreshToken: `open.${randomBytes(16).toString('base64url')}`,
554
+ expiresIn: 3600,
555
+ };
556
+ }
557
+ function readJsonBody(body) {
558
+ try {
559
+ const value = JSON.parse(new TextDecoder().decode(body));
560
+ return isRecord(value) ? value : null;
561
+ }
562
+ catch {
563
+ return null;
564
+ }
565
+ }
566
+ /**
567
+ * PWA 静态资产白名单:`/manifest.webmanifest`、`/sw.js` 与 `/__codingns/pwa/*`。
568
+ *
569
+ * 返回 undefined 表示“不属于白名单,或当前未启用”,交回原有登录与转发语义;
570
+ * 这样关闭增强时行为与改造前完全一致。合成内容只有公开元数据与图标,不允许
571
+ * 出现任何 Cookie、令牌或宿主路径。
572
+ */
573
+ export function resolveLanAccessDshPwaResponse(request, bundle) {
574
+ const path = request.path;
575
+ const inWhitelist = path === PWA_MANIFEST_PATH || path === PWA_SERVICE_WORKER_PATH || path.startsWith(PWA_ASSET_PREFIX);
576
+ if (!inWhitelist)
577
+ return undefined;
578
+ const headOnly = request.method === 'HEAD';
579
+ if (request.method !== 'GET' && !headOnly) {
580
+ return synthLanResponse({
581
+ status: 405,
582
+ contentType: 'text/plain; charset=utf-8',
583
+ body: 'Method Not Allowed',
584
+ headers: { Allow: 'GET, HEAD' },
585
+ });
586
+ }
587
+ if (bundle === null) {
588
+ // 未启用:manifest 与 SW 保持原有语义(manifest 透传上游、/sw.js 走登录/上游),
589
+ // 图标路径没有上游对应物,直接 404 以免落到 SPA 兜底。
590
+ return path.startsWith(PWA_ASSET_PREFIX)
591
+ ? synthLanResponse({ status: 404, contentType: 'text/plain; charset=utf-8', body: 'Not Found' })
592
+ : undefined;
593
+ }
594
+ if (path === PWA_MANIFEST_PATH) {
595
+ return synthLanResponse({
596
+ status: 200,
597
+ contentType: 'application/manifest+json; charset=utf-8',
598
+ body: bundle.manifest,
599
+ cacheControl: 'public, max-age=300',
600
+ headOnly,
601
+ });
602
+ }
603
+ if (path === PWA_SERVICE_WORKER_PATH) {
604
+ if (bundle.serviceWorker === null)
605
+ return undefined;
606
+ return synthLanResponse({
607
+ status: 200,
608
+ contentType: 'text/javascript; charset=utf-8',
609
+ body: bundle.serviceWorker,
610
+ // SW 脚本必须每次回源校验:插件升级后要能立刻安装新版本。
611
+ cacheControl: 'no-cache',
612
+ headOnly,
613
+ });
614
+ }
615
+ const asset = bundle.assets.get(path);
616
+ if (asset === undefined) {
617
+ return synthLanResponse({ status: 404, contentType: 'text/plain; charset=utf-8', body: 'Not Found' });
618
+ }
619
+ return synthLanResponse({
620
+ status: 200,
621
+ contentType: asset.contentType,
622
+ body: asset.body,
623
+ cacheControl: asset.cacheControl,
624
+ headOnly,
625
+ });
626
+ }
354
627
  function isLoopbackSocket(socket) {
355
628
  const remoteAddress = socket.remoteAddress;
356
629
  return remoteAddress === '127.0.0.1' || remoteAddress === '::1' || remoteAddress === '::ffff:127.0.0.1';
357
630
  }
631
+ function readRemoteAddress(socket) {
632
+ const remoteAddress = socket.remoteAddress;
633
+ return typeof remoteAddress === 'string' ? remoteAddress : undefined;
634
+ }
358
635
  /** 在 TCP 转发前完成登录校验;未通过时直接向局域网客户端返回页面/错误。 */
359
636
  class LanAccessDshAuthTransform extends Transform {
360
637
  client;
@@ -388,9 +665,12 @@ class LanAccessDshAuthTransform extends Transform {
388
665
  }
389
666
  const requestLine = decodeLatin1(head).split('\r\n', 1)[0] ?? '';
390
667
  const parts = requestLine.split(' ');
668
+ const target = parts[1] ?? '/';
669
+ const querySeparator = target.indexOf('?');
391
670
  const request = {
392
671
  method: parts[0] ?? 'GET',
393
- path: (parts[1] ?? '/').split('?', 1)[0] ?? '/',
672
+ path: querySeparator < 0 ? target : target.slice(0, querySeparator),
673
+ ...(querySeparator < 0 ? {} : { query: target.slice(querySeparator + 1) }),
394
674
  headers,
395
675
  body: this.pending.subarray(end + 4, end + 4 + bodyLength),
396
676
  };
@@ -431,6 +711,17 @@ function readCookie(value, name) {
431
711
  }
432
712
  return undefined;
433
713
  }
714
+ function readQueryParameter(query, name) {
715
+ if (query === undefined)
716
+ return undefined;
717
+ try {
718
+ const value = new URLSearchParams(query).get(name)?.trim();
719
+ return value === undefined || value === '' ? undefined : value;
720
+ }
721
+ catch {
722
+ return undefined;
723
+ }
724
+ }
434
725
  function sessionCookie(name, token, timeoutSeconds) {
435
726
  return `${name}=${token}; Path=/; HttpOnly; SameSite=Strict; Max-Age=${timeoutSeconds}`;
436
727
  }
@@ -447,6 +738,21 @@ function getSetCookie(headers) {
447
738
  const values = extended.getSetCookie?.() ?? (headers.get('set-cookie') === null ? [] : [headers.get('set-cookie')]);
448
739
  return values.map((value) => value.split(';', 1)[0]).find((value) => value !== '');
449
740
  }
741
+ export function synthLanResponse(input) {
742
+ const body = typeof input.body === 'string'
743
+ ? new TextEncoder().encode(input.body)
744
+ : input.body ?? new Uint8Array(0);
745
+ const headers = {
746
+ 'Content-Type': input.contentType,
747
+ 'Content-Length': String(body.length),
748
+ 'Cache-Control': input.cacheControl ?? 'no-store',
749
+ 'X-Content-Type-Options': 'nosniff',
750
+ Connection: 'close',
751
+ ...input.headers,
752
+ };
753
+ const head = encodeLatin1(`HTTP/1.1 ${input.status} ${statusText(input.status)}\r\n${Object.entries(headers).map(([key, value]) => `${key}: ${value}`).join('\r\n')}\r\n\r\n`);
754
+ return input.headOnly === true ? head : concatBytes(head, body);
755
+ }
450
756
  function loginResponse(status, body, extra = {}) {
451
757
  const isHtml = body.startsWith('<!doctype html>');
452
758
  const isJson = extra['Content-Type']?.startsWith('application/json') === true;
@@ -457,7 +763,7 @@ function loginResponse(status, body, extra = {}) {
457
763
  'Cache-Control': 'no-store',
458
764
  'X-Content-Type-Options': 'nosniff',
459
765
  'X-Frame-Options': 'DENY',
460
- 'Content-Security-Policy': "default-src 'none'; style-src 'unsafe-inline'; form-action 'self'; base-uri 'none'",
766
+ 'Content-Security-Policy': "default-src 'none'; img-src 'self'; style-src 'unsafe-inline'; form-action 'self'; base-uri 'none'",
461
767
  'Referrer-Policy': 'no-referrer',
462
768
  Connection: 'close',
463
769
  ...extra,
@@ -468,22 +774,39 @@ function loginResponse(status, body, extra = {}) {
468
774
  function loginJsonResponse(status, value, extra = {}) {
469
775
  return loginResponse(status, JSON.stringify(value), { 'Content-Type': 'application/json; charset=utf-8', ...extra });
470
776
  }
471
- function loginPage() {
777
+ function loginPage(captcha, locale) {
778
+ const captchaFields = captcha === undefined ? '' : `<input type="hidden" name="captchaId" value="${escapeHtml(captcha.id)}"><div class="cyber-captcha" style="display:flex;flex-direction:row;align-items:center;gap:12px;width:100%;"><img src="/__codingns/captcha?id=${encodeURIComponent(captcha.id)}" width="140" height="52" alt="${escapeHtml(hostBrowserText(locale, 'login.captchaAlt'))}" style="display:block;flex:0 0 140px;width:140px;height:52px;border:1px solid rgba(59,130,246,.5);border-radius:7px;background:rgba(15,23,42,.68);"><input class="cyber-input" name="captchaCode" autocomplete="off" inputmode="text" maxlength="5" placeholder="${escapeHtml(hostBrowserText(locale, 'login.captchaPlaceholder'))}" required style="flex:1 1 auto;min-width:0;width:auto;height:52px;padding:12px 14px;border:1px solid rgba(59,130,246,.5);border-radius:8px;background:rgba(15,23,42,.68);box-shadow:inset 0 0 8px rgba(59,130,246,.12);color:#f1f5f9;font:14px var(--font-mono);outline:0;"></div>`;
472
779
  // 视觉规则直接复用 codingns4dsh-h5/styles.css 的 Cyber 登录区,只把 Connect
473
780
  // 账号字段替换成本地用户名/密码;不能依赖外部 CSS,避免局域网入口离线时失效。
474
- return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>DSH Web | 本地登录</title><style>
475
- :root{font-family:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,monospace;color:#f1f5f9;background:#0a0f1d}*{box-sizing:border-box}html,body{width:100%;height:100%;margin:0}body{overflow:hidden}.cyber-login-page{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;overflow:hidden;background:radial-gradient(ellipse at center,#0f172a 0%,#0a0f1d 100%);color:#f1f5f9}.cyber-login-page:before{content:"";position:absolute;inset:0;background-image:linear-gradient(rgba(59,130,246,.08) 1px,transparent 1px),linear-gradient(90deg,rgba(59,130,246,.08) 1px,transparent 1px);background-size:50px 50px;transform:perspective(500px) rotateX(60deg);transform-origin:center top}.cyber-login-page:after{content:"";position:absolute;inset:0;pointer-events:none;background:repeating-linear-gradient(0deg,transparent,transparent 2px,rgba(0,0,0,.15) 2px,rgba(0,0,0,.15) 4px)}.cyber-login-container{position:relative;z-index:2;display:flex;flex-direction:column;align-items:center;gap:30px;width:min(440px,calc(100% - 32px));padding:24px}.cyber-login-content{display:flex;flex-direction:column;align-items:center;gap:28px;width:100%}.cyber-brand{display:flex;flex-direction:column;align-items:center;gap:13px;text-align:center}.cyber-logo{display:grid;place-items:center;width:80px;height:80px;border:1px solid rgba(59,130,246,.48);border-radius:22px;color:#60a5fa;font-size:19px;font-weight:700;letter-spacing:2px;box-shadow:0 0 25px rgba(0,212,255,.35),inset 0 0 22px rgba(59,130,246,.18);transform:rotate(30deg)}.cyber-logo span{transform:rotate(-30deg)}.cyber-brand-title{margin:0;color:#f1f5f9;font-size:28px;font-weight:700;letter-spacing:4px}.cyber-brand-subtitle{margin:0;color:#94a3b8;font-size:12px;letter-spacing:1.5px}.cyber-card{width:100%;padding:30px;border:1px solid rgba(59,130,246,.28);border-radius:12px;background:rgba(30,41,59,.78);backdrop-filter:blur(10px);box-shadow:0 8px 32px rgba(0,0,0,.4),0 0 0 1px rgba(59,130,246,.28)}.cyber-card-header{display:flex;align-items:center;gap:12px;margin-bottom:22px}.cyber-line{flex:1;height:1px;background:linear-gradient(90deg,transparent,rgba(59,130,246,.48),transparent)}.cyber-card-label{color:#94a3b8;font-size:11px;font-weight:600;letter-spacing:3px;white-space:nowrap}.cyber-form{display:flex;flex-direction:column;gap:18px}.cyber-connect-hint{margin:0;color:#94a3b8;font-size:12px;line-height:1.7}.cyber-field{position:relative;padding:12px 16px;border:1px solid rgba(59,130,246,.28);border-radius:8px;background:rgba(15,23,42,.68)}.cyber-field-label{display:flex;align-items:center;gap:8px;margin-bottom:8px;color:#94a3b8;font-size:11px;letter-spacing:1px}.cyber-field-icon{color:#60a5fa}.cyber-input{width:100%;padding:0;border:0;outline:0;background:transparent;color:#f1f5f9;font:14px var(--font-mono)}.cyber-input::placeholder{color:#94a3b8;opacity:.55}.cyber-submit{position:relative;width:100%;min-height:48px;margin-top:4px;padding:14px 24px;overflow:hidden;border:0;border-radius:8px;background:linear-gradient(135deg,#3b82f6,#06b6d4);color:white;font:600 13px var(--font-mono);letter-spacing:2px;cursor:pointer;box-shadow:0 0 18px rgba(59,130,246,.32)}.cyber-submit:hover{filter:brightness(1.12)}.cyber-submit:active{transform:translateY(1px)}.cyber-submit:disabled{cursor:wait;opacity:.6}.cyber-submit-text{position:relative;display:flex;align-items:center;justify-content:center;gap:8px}.cyber-status{display:flex;align-items:center;gap:8px;margin:0;padding:10px 12px;border:1px solid rgba(239,68,68,.25);border-radius:6px;background:rgba(239,68,68,.1);color:#fca5a5;font-size:12px;line-height:1.5}.cyber-footer{margin-top:2px}.cyber-divider{display:flex;align-items:center;gap:12px;margin-bottom:14px}.cyber-divider-line{flex:1;height:1px;background:linear-gradient(90deg,transparent,rgba(59,130,246,.48),transparent)}.cyber-divider-text{color:#64748b;font-size:10px;letter-spacing:2px}.cyber-version{display:flex;align-items:center;gap:12px;color:#64748b;font-size:10px;letter-spacing:2px;opacity:.65}@media(prefers-color-scheme:light){.cyber-login-page{color:#0f172a;background:radial-gradient(ellipse at center,#f8fafc 0%,#eef4fb 100%)}.cyber-card{background:rgba(255,255,255,.86);box-shadow:0 8px 28px rgba(15,23,42,.12),0 0 0 1px rgba(37,99,235,.13)}.cyber-brand-title{color:#0f172a}.cyber-input{color:#0f172a}.cyber-connect-hint,.cyber-field-label,.cyber-card-label{color:#64748b}.cyber-field{background:rgba(241,245,249,.86)}}@media(max-width:520px){.cyber-login-container{width:100%;padding:20px 16px}.cyber-card{padding:24px 20px}.cyber-brand-subtitle{font-size:10px;letter-spacing:1px}}
476
- </style></head><body><main class="cyber-login-page"><div class="cyber-login-container"><div class="cyber-login-content"><div class="cyber-brand"><div class="cyber-logo"><span>DSH</span></div><h1 class="cyber-brand-title">DSH Web</h1><p class="cyber-brand-subtitle">LOCAL SECURE DSH ENVIRONMENT</p></div><div class="cyber-card"><form class="cyber-form" method="post" action="/__codingns/login"><div class="cyber-card-header"><div class="cyber-line"></div><span class="cyber-card-label">LOCAL ACCESS</span><div class="cyber-line"></div></div><p class="cyber-connect-hint">使用本机设置的本地账号进入 DSH Web。</p><div class="cyber-field"><label class="cyber-field-label" for="login-username"><span class="cyber-field-icon" aria-hidden="true">⌁</span>用户名</label><input class="cyber-input" id="login-username" name="username" autocomplete="username" placeholder="输入本地用户名" required></div><div class="cyber-field"><label class="cyber-field-label" for="login-password"><span class="cyber-field-icon" aria-hidden="true">⚷</span>密码</label><input class="cyber-input" id="login-password" name="password" type="password" autocomplete="current-password" placeholder="输入本地密码" required></div><button class="cyber-submit" type="submit"><span class="cyber-submit-text"><span aria-hidden="true">➤</span>登录 DSH Web</span></button><div class="cyber-footer"><div class="cyber-divider"><span class="cyber-divider-line"></span><span class="cyber-divider-text">CODINGNS</span><span class="cyber-divider-line"></span></div></div></form></div></div><div class="cyber-version"><span>CODINGNS4DSH</span><span>|</span><span>LOCAL AUTH READY</span></div></div></main></body></html>`;
781
+ return `<!doctype html><html lang="${locale === 'zh' ? 'zh-CN' : 'en'}"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><meta name="theme-color" content="#0a0f1d"><meta name="mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"><link rel="apple-touch-icon" sizes="180x180" href="/__codingns/pwa/apple-touch-icon.png"><title>${escapeHtml(hostBrowserText(locale, 'login.documentTitle'))}</title><style>
782
+ :root{font-family:"SFMono-Regular",Consolas,"Liberation Mono",Menlo,monospace;color:#f1f5f9;background:#0a0f1d}*{box-sizing:border-box}html,body{width:100%;height:100%;margin:0}body{overflow:hidden}.cyber-login-page{position:fixed;inset:0;display:flex;align-items:center;justify-content:center;overflow:hidden;background:radial-gradient(ellipse at center,#0f172a 0%,#0a0f1d 100%);color:#f1f5f9}.cyber-login-page:before{content:"";position:absolute;inset:0;background-image:linear-gradient(rgba(59,130,246,.08) 1px,transparent 1px),linear-gradient(90deg,rgba(59,130,246,.08) 1px,transparent 1px);background-size:50px 50px;transform:perspective(500px) rotateX(60deg);transform-origin:center top}.cyber-login-page:after{content:"";position:absolute;inset:0;pointer-events:none;background:repeating-linear-gradient(0deg,transparent,transparent 2px,rgba(0,0,0,.15) 2px,rgba(0,0,0,.15) 4px)}.cyber-login-container{position:relative;z-index:2;display:flex;flex-direction:column;align-items:center;gap:30px;width:min(440px,calc(100% - 32px));padding:calc(24px + env(safe-area-inset-top,0px)) calc(24px + env(safe-area-inset-right,0px)) calc(24px + env(safe-area-inset-bottom,0px)) calc(24px + env(safe-area-inset-left,0px))}.cyber-login-content{display:flex;flex-direction:column;align-items:center;gap:28px;width:100%}.cyber-brand{display:flex;flex-direction:column;align-items:center;gap:13px;text-align:center}.cyber-logo{display:grid;place-items:center;width:80px;height:80px;border:1px solid rgba(59,130,246,.48);border-radius:22px;color:#60a5fa;font-size:19px;font-weight:700;letter-spacing:2px;box-shadow:0 0 25px rgba(0,212,255,.35),inset 0 0 22px rgba(59,130,246,.18);transform:rotate(30deg)}.cyber-logo span{transform:rotate(-30deg)}.cyber-brand-title{margin:0;color:#f1f5f9;font-size:28px;font-weight:700;letter-spacing:4px}.cyber-brand-subtitle{margin:0;color:#94a3b8;font-size:12px;letter-spacing:1.5px}.cyber-card{width:100%;padding:30px;border:1px solid rgba(59,130,246,.28);border-radius:12px;background:rgba(30,41,59,.78);backdrop-filter:blur(10px);box-shadow:0 8px 32px rgba(0,0,0,.4),0 0 0 1px rgba(59,130,246,.28)}.cyber-card-header{display:flex;align-items:center;gap:12px;margin-bottom:22px}.cyber-line{flex:1;height:1px;background:linear-gradient(90deg,transparent,rgba(59,130,246,.48),transparent)}.cyber-card-label{color:#94a3b8;font-size:11px;font-weight:600;letter-spacing:3px;white-space:nowrap}.cyber-form{display:flex;flex-direction:column;gap:18px}.cyber-connect-hint{margin:0;color:#94a3b8;font-size:12px;line-height:1.7}.cyber-field{position:relative;padding:12px 16px;border:1px solid rgba(59,130,246,.28);border-radius:8px;background:rgba(15,23,42,.68)}.cyber-field-label{display:flex;align-items:center;gap:8px;margin-bottom:8px;color:#94a3b8;font-size:11px;letter-spacing:1px}.cyber-field-icon{color:#60a5fa}.cyber-input{width:100%;padding:0;border:0;outline:0;background:transparent;color:#f1f5f9;font:14px var(--font-mono)}.cyber-input::placeholder{color:#94a3b8;opacity:.55}.cyber-captcha{display:flex;align-items:center;gap:12px}.cyber-captcha img{display:block;flex:0 0 140px;width:140px;height:52px;border:1px solid rgba(59,130,246,.28);border-radius:7px}.cyber-captcha .cyber-input{flex:1;min-width:0;width:auto;padding:12px;border:1px solid rgba(59,130,246,.28);border-radius:8px;background:rgba(15,23,42,.68)}.cyber-submit{position:relative;width:100%;min-height:48px;margin-top:4px;padding:14px 24px;overflow:hidden;border:0;border-radius:8px;background:linear-gradient(135deg,#3b82f6,#06b6d4);color:white;font:600 13px var(--font-mono);letter-spacing:2px;cursor:pointer;box-shadow:0 0 18px rgba(59,130,246,.32)}.cyber-submit:hover{filter:brightness(1.12)}.cyber-submit:active{transform:translateY(1px)}.cyber-submit:disabled{cursor:wait;opacity:.6}.cyber-submit-text{position:relative;display:flex;align-items:center;justify-content:center;gap:8px}.cyber-status{display:flex;align-items:center;gap:8px;margin:0;padding:10px 12px;border:1px solid rgba(239,68,68,.25);border-radius:6px;background:rgba(239,68,68,.1);color:#fca5a5;font-size:12px;line-height:1.5}.cyber-footer{margin-top:2px}.cyber-divider{display:flex;align-items:center;gap:12px;margin-bottom:14px}.cyber-divider-line{flex:1;height:1px;background:linear-gradient(90deg,transparent,rgba(59,130,246,.48),transparent)}.cyber-divider-text{color:#64748b;font-size:10px;letter-spacing:2px}.cyber-version{display:flex;align-items:center;gap:12px;color:#64748b;font-size:10px;letter-spacing:2px;opacity:.65}@media(prefers-color-scheme:light){.cyber-login-page{color:#0f172a;background:radial-gradient(ellipse at center,#f8fafc 0%,#eef4fb 100%)}.cyber-card{background:rgba(255,255,255,.86);box-shadow:0 8px 28px rgba(15,23,42,.12),0 0 0 1px rgba(37,99,235,.13)}.cyber-brand-title{color:#0f172a}.cyber-input{color:#0f172a}.cyber-connect-hint,.cyber-field-label,.cyber-card-label{color:#64748b}.cyber-field{background:rgba(241,245,249,.86)}}@media(max-width:520px){.cyber-login-container{width:100%;padding:calc(20px + env(safe-area-inset-top,0px)) calc(16px + env(safe-area-inset-right,0px)) calc(20px + env(safe-area-inset-bottom,0px)) calc(16px + env(safe-area-inset-left,0px))}.cyber-card{padding:24px 20px}.cyber-brand-subtitle{font-size:10px;letter-spacing:1px}}
783
+ </style></head><body><main class="cyber-login-page"><div class="cyber-login-container"><div class="cyber-login-content"><div class="cyber-brand"><div class="cyber-logo"><span>DSH</span></div><h1 class="cyber-brand-title">DSH Web</h1><p class="cyber-brand-subtitle">LOCAL SECURE DSH ENVIRONMENT</p></div><div class="cyber-card"><form class="cyber-form" method="post" action="/__codingns/login"><div class="cyber-card-header"><div class="cyber-line"></div><span class="cyber-card-label">LOCAL ACCESS</span><div class="cyber-line"></div></div><p class="cyber-connect-hint">${escapeHtml(hostBrowserText(locale, 'login.description'))}</p><div class="cyber-field"><label class="cyber-field-label" for="login-username"><span class="cyber-field-icon" aria-hidden="true">⌁</span>${escapeHtml(hostBrowserText(locale, 'login.username'))}</label><input class="cyber-input" id="login-username" name="username" autocomplete="username" placeholder="${escapeHtml(hostBrowserText(locale, 'login.usernamePlaceholder'))}" required></div><div class="cyber-field"><label class="cyber-field-label" for="login-password"><span class="cyber-field-icon" aria-hidden="true">⚷</span>${escapeHtml(hostBrowserText(locale, 'login.password'))}</label><input class="cyber-input" id="login-password" name="password" type="password" autocomplete="current-password" placeholder="${escapeHtml(hostBrowserText(locale, 'login.passwordPlaceholder'))}" required></div>${captchaFields}<button class="cyber-submit" type="submit"><span class="cyber-submit-text"><span aria-hidden="true">➤</span>${escapeHtml(hostBrowserText(locale, 'login.submit'))}</span></button><div class="cyber-footer"><div class="cyber-divider"><span class="cyber-divider-line"></span><span class="cyber-divider-text">CODINGNS</span><span class="cyber-divider-line"></span></div></div></form></div></div><div class="cyber-version"><span>CODINGNS4DSH</span><span>|</span><span>LOCAL AUTH READY</span></div></div></main></body></html>`;
477
784
  }
478
785
  /** 登录失败时继续渲染完整登录页,避免浏览器落到无样式的纯文本错误页。 */
479
- function loginPageWithError(message, username) {
480
- const page = loginPage();
786
+ function loginPageWithError(message, username, captcha, locale) {
787
+ const page = loginPage(captcha, locale);
481
788
  const status = `<p class="cyber-status" role="alert" aria-live="polite"><span aria-hidden="true">!</span>${escapeHtml(message)}</p>`;
482
789
  return page
483
790
  .replace('<p class="cyber-connect-hint">', `${status}<p class="cyber-connect-hint">`)
484
791
  .replace('name="username" autocomplete="username"', `name="username" autocomplete="username" value="${escapeHtml(username)}"`);
485
792
  }
486
- function statusText(status) { return status === 200 ? 'OK' : status === 303 ? 'See Other' : status === 401 ? 'Unauthorized' : 'Request Error'; }
793
+ function statusText(status) {
794
+ switch (status) {
795
+ case 200: return 'OK';
796
+ case 204: return 'No Content';
797
+ case 301: return 'Moved Permanently';
798
+ case 302: return 'Found';
799
+ case 303: return 'See Other';
800
+ case 400: return 'Bad Request';
801
+ case 401: return 'Unauthorized';
802
+ case 404: return 'Not Found';
803
+ case 405: return 'Method Not Allowed';
804
+ case 429: return 'Too Many Requests';
805
+ case 431: return 'Request Header Fields Too Large';
806
+ case 500: return 'Internal Server Error';
807
+ default: return 'Request Error';
808
+ }
809
+ }
487
810
  function escapeHtml(value) { return value.replace(/[&<>"']/g, (char) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;' })[char] ?? char); }
488
811
  /**
489
812
  * 将局域网入口发往上游 DSH 的 HTTP 请求头改成上游自身的 authority。
@@ -712,7 +1035,12 @@ export function normalizeLanAccessDshConfig(value, allowedListenHosts) {
712
1035
  ...(value.login === undefined ? {} : { login: normalizeLoginConfig(value.login) }),
713
1036
  };
714
1037
  }
715
- export function createLanAccessDshRpcHandler(proxy, settings, loginStore = new FileLanAccessDshLoginStore()) {
1038
+ export function createLanAccessDshRpcHandler(proxy, settings, loginStore = new FileLanAccessDshLoginStore(), options = {}) {
1039
+ const requirePush = () => {
1040
+ if (options.push === undefined)
1041
+ throw new CodingNsRpcError('CODINGNS_PWA_PUSH_UNAVAILABLE', '推送服务未启用');
1042
+ return options.push;
1043
+ };
716
1044
  return async (action, payload) => {
717
1045
  switch (action) {
718
1046
  case 'addresses':
@@ -726,12 +1054,45 @@ export function createLanAccessDshRpcHandler(proxy, settings, loginStore = new F
726
1054
  case 'settings/set': {
727
1055
  if (settings === undefined)
728
1056
  throw new CodingNsRpcError('CODINGNS_SETTINGS_UNAVAILABLE', 'Codingns4DSH 设置服务不可用');
729
- const next = parseLanAccessDshSettings(payload, proxy.listenHosts());
1057
+ const next = parseLanAccessDshSettings(payload, proxy.listenHosts(), settings.get().lanAccessDsh.pwa);
730
1058
  await settings.update({ lanAccessDsh: next });
731
1059
  return settings.get().lanAccessDsh;
732
1060
  }
733
1061
  case 'login/get':
734
1062
  return proxy.loginSettings();
1063
+ case 'pwa/status':
1064
+ return proxy.pwaStatus();
1065
+ case 'pwa/vapid': {
1066
+ const push = requirePush();
1067
+ return { available: true, publicKey: (await push.vapidKeys()).publicKey };
1068
+ }
1069
+ case 'pwa/push/status': {
1070
+ if (options.push === undefined)
1071
+ return { available: false, subscriptions: 0 };
1072
+ const subscriptions = await options.push.listSubscriptions();
1073
+ return { available: true, subscriptions: subscriptions.length };
1074
+ }
1075
+ case 'pwa/push/subscribe': {
1076
+ const push = requirePush();
1077
+ const input = parsePushSubscribePayload(payload);
1078
+ const record = await push.subscribe(input, readPushLabel(payload));
1079
+ return { endpoint: record.endpoint, createdAt: record.createdAt, subscriptions: (await push.listSubscriptions()).length };
1080
+ }
1081
+ case 'pwa/push/unsubscribe': {
1082
+ const push = requirePush();
1083
+ const endpoint = readPushEndpoint(payload);
1084
+ return { removed: await push.unsubscribe(endpoint) };
1085
+ }
1086
+ case 'pwa/push/test': {
1087
+ const push = requirePush();
1088
+ const locale = options.resolveLocale?.() ?? 'zh';
1089
+ const summary = await push.sendToAll({
1090
+ title: hostBrowserText(locale, 'push.testTitle'),
1091
+ body: hostBrowserText(locale, 'push.testBody'),
1092
+ tag: 'codingns4dsh-test',
1093
+ });
1094
+ return summary;
1095
+ }
735
1096
  case 'login/set': {
736
1097
  const current = await loginStore.read();
737
1098
  const next = parseLoginSettings(payload, current);
@@ -791,7 +1152,7 @@ function parseLoginSessionRefreshPayload(value) {
791
1152
  return { token, scope };
792
1153
  }
793
1154
  function defaultLanAccessDshSettings() {
794
- return { autoStart: false, listenHost: '0.0.0.0', listenPort: 13080, dshPort: 0 };
1155
+ return { autoStart: false, listenHost: '0.0.0.0', listenPort: 13080, dshPort: 0, pwa: { ...DEFAULT_LAN_ACCESS_DSH_PWA_SETTINGS } };
795
1156
  }
796
1157
  function parseLoginSettings(value, current) {
797
1158
  if (!value || typeof value !== 'object')
@@ -805,13 +1166,28 @@ function parseLoginSettings(value, current) {
805
1166
  const timeoutSeconds = requireInteger(input.timeoutSeconds, '超时时间', 60, 604800);
806
1167
  const scopes = parseLoginScopes(input.scopes ?? current?.scopes);
807
1168
  const password = typeof input.password === 'string' ? input.password : '';
808
- if (password === '' && current === null)
809
- throw new LanAccessDshError('LAN_ACCESS_DSH_INVALID', '启用登录保护时必须设置密码');
810
- if (password !== '' && (password.length < 8 || password.length > 256))
1169
+ if (password === '') {
1170
+ if (current === null)
1171
+ throw new LanAccessDshError('LAN_ACCESS_DSH_INVALID', '启用登录保护时必须设置密码');
1172
+ return { enabled: true, username, passwordHash: current.passwordHash, passwordSalt: current.passwordSalt, timeoutSeconds, scopes };
1173
+ }
1174
+ return createLoginProtectionConfig({ username, password, timeoutSeconds, scopes });
1175
+ }
1176
+ /** 由明文密码生成登录保护配置;只在设置写入与测试夹具中使用,不回显密码。 */
1177
+ export function createLoginProtectionConfig(input) {
1178
+ const username = requireLoginText(input.username, '用户名', 1, 128);
1179
+ const timeoutSeconds = requireInteger(input.timeoutSeconds, '超时时间', 60, 604800);
1180
+ if (input.password.length < 8 || input.password.length > 256)
811
1181
  throw new LanAccessDshError('LAN_ACCESS_DSH_INVALID', '密码长度必须是 8 到 256 个字符');
812
- const passwordSalt = password === '' ? current.passwordSalt : randomBytes(16).toString('hex');
813
- const passwordHash = password === '' ? current.passwordHash : hashPassword(password, passwordSalt);
814
- return { enabled: true, username, passwordHash, passwordSalt, timeoutSeconds, scopes };
1182
+ const passwordSalt = randomBytes(16).toString('hex');
1183
+ return {
1184
+ enabled: true,
1185
+ username,
1186
+ passwordHash: hashPassword(input.password, passwordSalt),
1187
+ passwordSalt,
1188
+ timeoutSeconds,
1189
+ scopes: parseLoginScopes(input.scopes),
1190
+ };
815
1191
  }
816
1192
  function normalizeLoginConfig(value) {
817
1193
  if (typeof value !== 'object' || value === null)
@@ -900,8 +1276,36 @@ function parseLoginScopes(value) {
900
1276
  return { lan: input.lan, relay: input.relay };
901
1277
  }
902
1278
  function isNodeError(error, code) { return typeof error === 'object' && error !== null && 'code' in error && error.code === code; }
1279
+ /** 推送订阅只接受 endpoint + 两个密钥,其余字段忽略;非法输入给出稳定错误码。 */
1280
+ function parsePushSubscribePayload(value) {
1281
+ if (!isRecord(value))
1282
+ throw new CodingNsRpcError('CODINGNS_PWA_PUSH_INVALID', '推送订阅参数无效');
1283
+ const keys = value.keys;
1284
+ if (typeof value.endpoint !== 'string' || !isRecord(keys) || typeof keys.p256dh !== 'string' || typeof keys.auth !== 'string') {
1285
+ throw new CodingNsRpcError('CODINGNS_PWA_PUSH_INVALID', '推送订阅参数无效');
1286
+ }
1287
+ return { endpoint: value.endpoint, keys: { p256dh: keys.p256dh, auth: keys.auth } };
1288
+ }
1289
+ function readPushLabel(value) {
1290
+ if (!isRecord(value))
1291
+ return '';
1292
+ return typeof value.label === 'string' ? value.label : '';
1293
+ }
1294
+ function readPushEndpoint(value) {
1295
+ if (!isRecord(value) || typeof value.endpoint !== 'string' || value.endpoint === '') {
1296
+ throw new CodingNsRpcError('CODINGNS_PWA_PUSH_INVALID', '推送订阅 endpoint 无效');
1297
+ }
1298
+ return value.endpoint;
1299
+ }
903
1300
  function isRecord(value) { return typeof value === 'object' && value !== null && !Array.isArray(value); }
904
- function parseLanAccessDshSettings(value, allowedListenHosts) {
1301
+ /**
1302
+ * 解析监听映射设置。
1303
+ *
1304
+ * PWA 设置已经移到「移动端访问增强」卡片,它的写入走设置 RPC 的 `lanAccessDsh.pwa` 路径;
1305
+ * 这里在请求未携带 `pwa` 时沿用当前值,避免用户在局域网卡片里只改监听端口就把手机端
1306
+ * 资产配置重置成默认档位。显式传入 `pwa` 时仍然走归一化。
1307
+ */
1308
+ function parseLanAccessDshSettings(value, allowedListenHosts, currentPwa = null) {
905
1309
  if (!value || typeof value !== 'object')
906
1310
  throw new LanAccessDshError('LAN_ACCESS_DSH_INVALID', '局域网访问 DSH 设置必须是对象');
907
1311
  const input = value;
@@ -912,7 +1316,14 @@ function parseLanAccessDshSettings(value, allowedListenHosts) {
912
1316
  const dshPort = requirePort(input.dshPort, 'dshPort', true);
913
1317
  if (!new Set(allowedListenHosts).has(listenHost))
914
1318
  throw new LanAccessDshError('LAN_ACCESS_DSH_INVALID', '监听地址必须来自本机网卡或 0.0.0.0');
915
- return { autoStart: input.autoStart, listenHost, listenPort, dshPort };
1319
+ const pwa = input.pwa === undefined && currentPwa !== null
1320
+ ? currentPwa
1321
+ : parseLanAccessDshPwaSettings(input.pwa);
1322
+ return { autoStart: input.autoStart, listenHost, listenPort, dshPort, pwa };
1323
+ }
1324
+ /** PWA 档位走归一化而非严格校验:非法值收敛到保守默认,避免设置页写不进去。 */
1325
+ function parseLanAccessDshPwaSettings(value) {
1326
+ return normalizeLanAccessDshPwaSettings(value);
916
1327
  }
917
1328
  function parseStartPayload(value) {
918
1329
  if (!value || typeof value !== 'object')