@walkhi/code-relax 0.1.0-beta.9 → 0.1.0-beta.91

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 (850) hide show
  1. package/README.md +67 -44
  2. package/dist/bin/cleanup-accounts.mjs +63 -0
  3. package/dist/bin/codex-remote.mjs +382 -261
  4. package/dist/bin/manage-relay-admin.mjs +20 -0
  5. package/dist/bin/migrate-relay-db.mjs +109 -0
  6. package/dist/bin/publish-android-release.mjs +63 -0
  7. package/dist/bin/publish-harmony-release.mjs +46 -0
  8. package/dist/bin/release-upload-server.mjs +190 -0
  9. package/dist/bin/self-relay-admin.mjs +8 -0
  10. package/dist/bin/self-relay-demo.mjs +1 -1
  11. package/dist/bin/self-relay-server.mjs +43 -30
  12. package/dist/bin/set-relay-admin-password.mjs +11 -0
  13. package/dist/build-platform.json +1 -0
  14. package/dist/get-shared-service-url.ps1 +12 -4
  15. package/dist/shared/app-server-events.cjs +452 -235
  16. package/dist/shared/code-browser.cjs +159 -0
  17. package/dist/shared/file-changes.cjs +31 -0
  18. package/dist/shared/file-citations.cjs +117 -0
  19. package/dist/shared/file-mentions.cjs +92 -0
  20. package/dist/shared/message-delivery.cjs +115 -0
  21. package/dist/shared/p2p-data-channel.cjs +22 -0
  22. package/dist/shared/p2p-diagnostics.cjs +1 -1
  23. package/dist/shared/p2p-file-channel.cjs +87 -0
  24. package/dist/shared/p2p-ice-policy.cjs +22 -0
  25. package/dist/shared/plan-pricing.cjs +32 -0
  26. package/dist/shared/question-attention.cjs +100 -0
  27. package/dist/shared/release-version.cjs +31 -0
  28. package/dist/shared/server-requests.cjs +347 -67
  29. package/dist/shared/service-endpoints.cjs +21 -0
  30. package/dist/shared/timeline-sync.cjs +173 -67
  31. package/dist/skills/code-relax/SKILL.md +22 -17
  32. package/dist/src/archived-threads.mjs +22 -0
  33. package/dist/src/bounded-process-log.mjs +63 -0
  34. package/dist/src/browser-auth-operations.mjs +46 -0
  35. package/dist/src/celsius-client.mjs +107 -0
  36. package/dist/src/code-browser.mjs +99 -0
  37. package/dist/src/desktop-launcher.mjs +57 -32
  38. package/dist/src/desktop-operation.mjs +46 -0
  39. package/dist/src/dots-approval-timeline.mjs +99 -0
  40. package/dist/src/dots-avatar.mjs +42 -0
  41. package/dist/src/dots-chat-projection.mjs +50 -0
  42. package/dist/src/dots-chat-server.mjs +623 -0
  43. package/dist/src/dots-message-images.mjs +318 -0
  44. package/dist/src/dots-profile.mjs +77 -0
  45. package/dist/src/dots-room-activity.mjs +199 -0
  46. package/dist/src/dots-room-client.mjs +163 -0
  47. package/dist/src/dots-room-projection.mjs +94 -0
  48. package/dist/src/dots-schedules.mjs +66 -0
  49. package/dist/src/dots-summary-tasks.mjs +32 -0
  50. package/dist/src/dots-task-catalog.mjs +433 -0
  51. package/dist/src/dots-task-files.mjs +52 -0
  52. package/dist/src/file-transfer-range.mjs +22 -0
  53. package/dist/src/file-upload-session.mjs +151 -0
  54. package/dist/src/hosted-history-app-server.mjs +103 -0
  55. package/dist/src/hosted-history-cache.mjs +113 -0
  56. package/dist/src/lan-socket-server.mjs +266 -37
  57. package/dist/src/managed-app-server.mjs +398 -216
  58. package/dist/src/managed-endpoint.mjs +25 -0
  59. package/dist/src/message-upload-files.mjs +111 -0
  60. package/dist/src/onboarding.mjs +9 -27
  61. package/dist/src/plan-pricing.mjs +47 -0
  62. package/dist/src/platform/README.md +7 -12
  63. package/dist/src/platform/codex-protocol.mjs +51 -0
  64. package/dist/src/platform/codex-runtime.mjs +4 -0
  65. package/dist/src/platform/credential-store.mjs +19 -0
  66. package/dist/src/platform/desktop-host.mjs +3 -0
  67. package/dist/src/platform/desktop-permission-mode.mjs +17 -0
  68. package/dist/src/platform/desktop-project-registration.mjs +3 -0
  69. package/dist/src/platform/desktop-project-store.mjs +219 -0
  70. package/dist/src/platform/file-opener.mjs +9 -0
  71. package/dist/src/platform/linux/codex-runtime.mjs +56 -0
  72. package/dist/src/platform/linux/desktop-host.mjs +87 -0
  73. package/dist/src/platform/linux/desktop-installation.mjs +36 -0
  74. package/dist/src/platform/linux/desktop-project-registration.mjs +11 -0
  75. package/dist/src/platform/linux/network-info.mjs +11 -0
  76. package/dist/src/platform/linux/process.mjs +53 -0
  77. package/dist/src/platform/linux/project-locations.mjs +17 -0
  78. package/dist/src/platform/linux/resident-startup.mjs +52 -0
  79. package/dist/src/platform/linux/retained-runtime.mjs +76 -0
  80. package/dist/src/platform/linux/service-host.mjs +18 -0
  81. package/dist/src/platform/linux/system.mjs +50 -0
  82. package/dist/src/platform/linux/user-environment.mjs +31 -0
  83. package/dist/src/platform/macos/codex-runtime.mjs +121 -0
  84. package/dist/src/platform/macos/desktop-host.mjs +114 -0
  85. package/dist/src/platform/macos/desktop-project-registration.mjs +11 -0
  86. package/dist/src/platform/macos/network-info.mjs +8 -0
  87. package/dist/src/platform/macos/project-locations.mjs +8 -0
  88. package/dist/src/platform/macos/resident-startup.mjs +84 -0
  89. package/dist/src/platform/macos/retained-runtime.mjs +127 -0
  90. package/dist/src/platform/macos/service-host.mjs +18 -0
  91. package/dist/src/platform/macos/system.mjs +29 -0
  92. package/dist/src/platform/macos/user-environment.mjs +31 -0
  93. package/dist/src/platform/managed-user-environment.mjs +78 -0
  94. package/dist/src/platform/native-package.mjs +61 -0
  95. package/dist/src/platform/network-info.mjs +3 -0
  96. package/dist/src/platform/path-identity.mjs +5 -0
  97. package/dist/src/platform/posix/network-candidates.mjs +23 -0
  98. package/dist/src/platform/posix/runtime-paths.mjs +25 -0
  99. package/dist/src/platform/power-inhibitor.mjs +22 -0
  100. package/dist/src/platform/project-locations.mjs +3 -0
  101. package/dist/src/platform/runtime-paths.mjs +8 -0
  102. package/dist/src/platform/select.mjs +5 -0
  103. package/dist/src/platform/service-host.mjs +3 -0
  104. package/dist/src/platform/user-environment.mjs +3 -0
  105. package/dist/src/platform/windows/activate-desktop.ps1 +49 -0
  106. package/dist/src/platform/windows/codex-runtime.mjs +225 -0
  107. package/dist/src/platform/windows/desktop-helper.mjs +179 -0
  108. package/dist/src/platform/windows/desktop-host.mjs +45 -18
  109. package/dist/src/platform/windows/desktop-info.ps1 +27 -5
  110. package/dist/src/platform/windows/desktop-project-registration.mjs +4 -0
  111. package/dist/src/platform/windows/desktop-runtime.ps1 +10 -0
  112. package/dist/src/platform/windows/desktop-shortcuts.ps1 +6 -13
  113. package/dist/src/platform/windows/dots-profile.mjs +49 -0
  114. package/dist/src/platform/windows/keep-awake.ps1 +20 -0
  115. package/dist/src/platform/windows/launch-worker.mjs +41 -42
  116. package/dist/src/platform/windows/project-locations.mjs +16 -0
  117. package/dist/src/platform/windows/resident-start.js +20 -0
  118. package/dist/src/platform/windows/resident-startup.ps1 +27 -11
  119. package/dist/src/platform/windows/rustdesk-video-probe.mjs +168 -0
  120. package/dist/src/platform/windows/service-host.mjs +17 -22
  121. package/dist/src/platform/windows/start-hidden-console.ps1 +11 -2
  122. package/dist/src/platform/windows/user-environment.mjs +52 -50
  123. package/dist/src/project-create.mjs +121 -0
  124. package/dist/src/project-management.mjs +59 -0
  125. package/dist/src/project-remove.mjs +55 -0
  126. package/dist/src/project-update.mjs +59 -0
  127. package/dist/src/relay-config-import.mjs +45 -0
  128. package/dist/src/runtime-discovery.mjs +67 -0
  129. package/dist/src/self-relay/account-cleanup.mjs +30 -0
  130. package/dist/src/self-relay/account-connections.mjs +63 -0
  131. package/dist/src/self-relay/admin-auth.mjs +59 -0
  132. package/dist/src/self-relay/admin-cloud.mjs +101 -0
  133. package/dist/src/self-relay/admin-login-page.mjs +7 -0
  134. package/dist/src/self-relay/admin-page.mjs +87 -54
  135. package/dist/src/self-relay/admin-server.mjs +105 -0
  136. package/dist/src/self-relay/admin-state.mjs +69 -16
  137. package/dist/src/self-relay/admin-style.mjs +58 -0
  138. package/dist/src/self-relay/admin-workstations-page.mjs +95 -0
  139. package/dist/src/self-relay/admin-workstations.mjs +143 -0
  140. package/dist/src/self-relay/android-releases.mjs +61 -0
  141. package/dist/src/self-relay/client.mjs +45 -45
  142. package/dist/src/self-relay/connection-reporting.mjs +38 -0
  143. package/dist/src/self-relay/connector.mjs +456 -145
  144. package/dist/src/self-relay/demo.mjs +1 -1
  145. package/dist/src/self-relay/device-info.mjs +27 -0
  146. package/dist/src/self-relay/device-store.mjs +10 -2
  147. package/dist/src/self-relay/diagnostics.mjs +54 -0
  148. package/dist/src/self-relay/email-accounts.mjs +195 -0
  149. package/dist/src/self-relay/file-wire.mjs +76 -0
  150. package/dist/src/self-relay/lan-authorizations.mjs +44 -2
  151. package/dist/src/self-relay/lifecycle.mjs +252 -259
  152. package/dist/src/self-relay/long-pairing.mjs +40 -0
  153. package/dist/src/self-relay/mysql-state.mjs +118 -0
  154. package/dist/src/self-relay/p2p-probe.mjs +168 -123
  155. package/dist/src/self-relay/phone-connections.mjs +55 -0
  156. package/dist/src/self-relay/privacy-page.mjs +26 -0
  157. package/dist/src/self-relay/public-releases.mjs +67 -0
  158. package/dist/src/self-relay/rtc-file-bridge.mjs +46 -0
  159. package/dist/src/self-relay/server.mjs +1065 -424
  160. package/dist/src/self-relay/usage-daily.mjs +55 -0
  161. package/dist/src/self-relay/usage-meter.mjs +141 -0
  162. package/dist/src/server.mjs +1434 -723
  163. package/dist/src/service-control.mjs +17 -7
  164. package/dist/src/service-doctor.mjs +150 -70
  165. package/dist/src/service-health.mjs +2 -2
  166. package/dist/src/service-install.mjs +16 -10
  167. package/dist/src/service-lifecycle.mjs +52 -42
  168. package/dist/src/service-power.mjs +58 -0
  169. package/dist/src/service-restart.mjs +45 -12
  170. package/dist/src/service-update-worker.mjs +42 -0
  171. package/dist/src/service-update.mjs +80 -0
  172. package/dist/src/shared-app-server.mjs +511 -307
  173. package/dist/src/shared-catalog.mjs +132 -50
  174. package/dist/src/shared-recovery.mjs +22 -12
  175. package/dist/src/shared-thread-stream.mjs +143 -51
  176. package/dist/src/skill-install.mjs +0 -13
  177. package/dist/src/thread-goals.mjs +40 -0
  178. package/dist/src/turn-model-history.mjs +47 -0
  179. package/dist/src/usage-reset.mjs +17 -0
  180. package/dist/src/workstation-downloads.mjs +120 -0
  181. package/package.json +48 -48
  182. package/tools/postinstall.mjs +186 -146
  183. package/dist/src/debug-ui.mjs +0 -131
  184. package/dist/src/platform/windows/credential-store.mjs +0 -27
  185. package/dist/src/platform/windows/credential-store.ps1 +0 -49
  186. package/dist/src/platform/windows/desktop-shortcut-run.ps1 +0 -5
  187. package/dist/web/activity-view.js +0 -283
  188. package/dist/web/approval-ui.js +0 -188
  189. package/dist/web/capabilities.js +0 -50
  190. package/dist/web/chat-transport.js +0 -196
  191. package/dist/web/chat.css +0 -781
  192. package/dist/web/chat.js +0 -3812
  193. package/dist/web/client-platform.js +0 -11
  194. package/dist/web/community.css +0 -82
  195. package/dist/web/community.html +0 -36
  196. package/dist/web/composer-controller.js +0 -97
  197. package/dist/web/conversation-controller.js +0 -99
  198. package/dist/web/disclosure-state-controller.js +0 -95
  199. package/dist/web/draft-controller.js +0 -103
  200. package/dist/web/harmony-platform.js +0 -52
  201. package/dist/web/highlight-powershell.min.js +0 -39
  202. package/dist/web/highlight.min.js +0 -1262
  203. package/dist/web/history-cache.js +0 -240
  204. package/dist/web/history-controller.js +0 -167
  205. package/dist/web/index.html +0 -293
  206. package/dist/web/lan-session.js +0 -122
  207. package/dist/web/link-action-controller.js +0 -212
  208. package/dist/web/message-send-controller.js +0 -177
  209. package/dist/web/message-view.js +0 -98
  210. package/dist/web/p2p-data-channel.js +0 -50
  211. package/dist/web/p2p-diagnostics.js +0 -28
  212. package/dist/web/p2p-probe.js +0 -123
  213. package/dist/web/page-resume.js +0 -28
  214. package/dist/web/pending-message-store.js +0 -108
  215. package/dist/web/queue-controller.js +0 -82
  216. package/dist/web/resources.json +0 -1
  217. package/dist/web/self-relay-session.js +0 -129
  218. package/dist/web/server-requests.js +0 -67
  219. package/dist/web/station-connection-controller.js +0 -75
  220. package/dist/web/task-list-view.js +0 -289
  221. package/dist/web/thread-attention-controller.js +0 -124
  222. package/dist/web/thread-context-controller.js +0 -30
  223. package/dist/web/thread-list-controller.js +0 -61
  224. package/dist/web/thread-list-sync.js +0 -86
  225. package/dist/web/thread-title-controller.js +0 -57
  226. package/dist/web/timeline-formatters.js +0 -249
  227. package/dist/web/timeline-reducer.js +0 -77
  228. package/dist/web/timeline-renderer.js +0 -161
  229. package/dist/web/timeline-scroll-controller.js +0 -50
  230. package/dist/web/timeline-sync.js +0 -67
  231. package/dist/web/usage-controller.js +0 -258
  232. package/dist/web/vendor/README.md +0 -14
  233. package/dist/web/vendor/highlight-powershell.min.js +0 -39
  234. package/dist/web/vendor/highlight.LICENSE.txt +0 -29
  235. package/dist/web/vendor/highlight.min.js +0 -1262
  236. package/dist/web/vendor/lucide.LICENSE.txt +0 -17
  237. package/node_modules/@img/colour/LICENSE.md +0 -82
  238. package/node_modules/@img/colour/README.md +0 -15
  239. package/node_modules/@img/colour/color.cjs +0 -1596
  240. package/node_modules/@img/colour/index.cjs +0 -1
  241. package/node_modules/@img/colour/index.d.ts +0 -929
  242. package/node_modules/@img/colour/package.json +0 -58
  243. package/node_modules/@img/sharp-win32-x64/LICENSE +0 -191
  244. package/node_modules/@img/sharp-win32-x64/README.md +0 -59
  245. package/node_modules/@img/sharp-win32-x64/index.cjs +0 -1
  246. package/node_modules/@img/sharp-win32-x64/lib/libvips-42.dll +0 -0
  247. package/node_modules/@img/sharp-win32-x64/lib/libvips-cpp-8.18.6.dll +0 -0
  248. package/node_modules/@img/sharp-win32-x64/lib/sharp-win32-x64-0.35.4.node +0 -0
  249. package/node_modules/@img/sharp-win32-x64/package.json +0 -40
  250. package/node_modules/@img/sharp-win32-x64/versions.json +0 -30
  251. package/node_modules/@node-datachannel/win32-x64-msvc/node_datachannel.node +0 -0
  252. package/node_modules/@node-datachannel/win32-x64-msvc/package.json +0 -20
  253. package/node_modules/ansi-regex/index.d.ts +0 -37
  254. package/node_modules/ansi-regex/index.js +0 -10
  255. package/node_modules/ansi-regex/license +0 -9
  256. package/node_modules/ansi-regex/package.json +0 -55
  257. package/node_modules/ansi-regex/readme.md +0 -78
  258. package/node_modules/ansi-styles/index.d.ts +0 -345
  259. package/node_modules/ansi-styles/index.js +0 -163
  260. package/node_modules/ansi-styles/license +0 -9
  261. package/node_modules/ansi-styles/package.json +0 -56
  262. package/node_modules/ansi-styles/readme.md +0 -152
  263. package/node_modules/camelcase/index.d.ts +0 -63
  264. package/node_modules/camelcase/index.js +0 -76
  265. package/node_modules/camelcase/license +0 -9
  266. package/node_modules/camelcase/package.json +0 -43
  267. package/node_modules/camelcase/readme.md +0 -99
  268. package/node_modules/cliui/CHANGELOG.md +0 -76
  269. package/node_modules/cliui/LICENSE.txt +0 -14
  270. package/node_modules/cliui/README.md +0 -115
  271. package/node_modules/cliui/index.js +0 -354
  272. package/node_modules/cliui/package.json +0 -65
  273. package/node_modules/color-convert/CHANGELOG.md +0 -54
  274. package/node_modules/color-convert/LICENSE +0 -21
  275. package/node_modules/color-convert/README.md +0 -68
  276. package/node_modules/color-convert/conversions.js +0 -839
  277. package/node_modules/color-convert/index.js +0 -81
  278. package/node_modules/color-convert/package.json +0 -48
  279. package/node_modules/color-convert/route.js +0 -97
  280. package/node_modules/color-name/LICENSE +0 -8
  281. package/node_modules/color-name/README.md +0 -11
  282. package/node_modules/color-name/index.js +0 -152
  283. package/node_modules/color-name/package.json +0 -28
  284. package/node_modules/decamelize/index.js +0 -13
  285. package/node_modules/decamelize/license +0 -21
  286. package/node_modules/decamelize/package.json +0 -38
  287. package/node_modules/decamelize/readme.md +0 -48
  288. package/node_modules/detect-libc/LICENSE +0 -201
  289. package/node_modules/detect-libc/README.md +0 -163
  290. package/node_modules/detect-libc/index.d.ts +0 -14
  291. package/node_modules/detect-libc/lib/detect-libc.js +0 -313
  292. package/node_modules/detect-libc/lib/elf.js +0 -39
  293. package/node_modules/detect-libc/lib/filesystem.js +0 -51
  294. package/node_modules/detect-libc/lib/process.js +0 -24
  295. package/node_modules/detect-libc/package.json +0 -44
  296. package/node_modules/dijkstrajs/.travis.yml +0 -4
  297. package/node_modules/dijkstrajs/CONTRIBUTING.md +0 -8
  298. package/node_modules/dijkstrajs/LICENSE.md +0 -19
  299. package/node_modules/dijkstrajs/README.md +0 -18
  300. package/node_modules/dijkstrajs/dijkstra.js +0 -165
  301. package/node_modules/dijkstrajs/package.json +0 -60
  302. package/node_modules/dijkstrajs/test/dijkstra.test.js +0 -96
  303. package/node_modules/emoji-regex/LICENSE-MIT.txt +0 -20
  304. package/node_modules/emoji-regex/README.md +0 -73
  305. package/node_modules/emoji-regex/es2015/index.js +0 -6
  306. package/node_modules/emoji-regex/es2015/text.js +0 -6
  307. package/node_modules/emoji-regex/index.d.ts +0 -23
  308. package/node_modules/emoji-regex/index.js +0 -6
  309. package/node_modules/emoji-regex/package.json +0 -50
  310. package/node_modules/emoji-regex/text.js +0 -6
  311. package/node_modules/find-up/index.d.ts +0 -137
  312. package/node_modules/find-up/index.js +0 -89
  313. package/node_modules/find-up/license +0 -9
  314. package/node_modules/find-up/package.json +0 -53
  315. package/node_modules/find-up/readme.md +0 -156
  316. package/node_modules/get-caller-file/LICENSE.md +0 -6
  317. package/node_modules/get-caller-file/README.md +0 -41
  318. package/node_modules/get-caller-file/index.d.ts +0 -2
  319. package/node_modules/get-caller-file/index.js +0 -22
  320. package/node_modules/get-caller-file/index.js.map +0 -1
  321. package/node_modules/get-caller-file/package.json +0 -42
  322. package/node_modules/is-fullwidth-code-point/index.d.ts +0 -17
  323. package/node_modules/is-fullwidth-code-point/index.js +0 -50
  324. package/node_modules/is-fullwidth-code-point/license +0 -9
  325. package/node_modules/is-fullwidth-code-point/package.json +0 -42
  326. package/node_modules/is-fullwidth-code-point/readme.md +0 -39
  327. package/node_modules/locate-path/index.d.ts +0 -83
  328. package/node_modules/locate-path/index.js +0 -65
  329. package/node_modules/locate-path/license +0 -9
  330. package/node_modules/locate-path/package.json +0 -45
  331. package/node_modules/locate-path/readme.md +0 -122
  332. package/node_modules/node-datachannel/.clang-format +0 -17
  333. package/node_modules/node-datachannel/.editorconfig +0 -12
  334. package/node_modules/node-datachannel/.eslintignore +0 -8
  335. package/node_modules/node-datachannel/.eslintrc.json +0 -27
  336. package/node_modules/node-datachannel/.gitmodules +0 -3
  337. package/node_modules/node-datachannel/.prettierignore +0 -7
  338. package/node_modules/node-datachannel/.prettierrc +0 -13
  339. package/node_modules/node-datachannel/API.md +0 -247
  340. package/node_modules/node-datachannel/BULDING.md +0 -26
  341. package/node_modules/node-datachannel/CMakeLists.txt +0 -153
  342. package/node_modules/node-datachannel/LICENSE +0 -373
  343. package/node_modules/node-datachannel/README.md +0 -129
  344. package/node_modules/node-datachannel/dist/cjs/index.cjs +0 -11
  345. package/node_modules/node-datachannel/dist/cjs/index.cjs.map +0 -1
  346. package/node_modules/node-datachannel/dist/cjs/lib/datachannel-stream.cjs +0 -101
  347. package/node_modules/node-datachannel/dist/cjs/lib/datachannel-stream.cjs.map +0 -1
  348. package/node_modules/node-datachannel/dist/cjs/lib/index.cjs +0 -91
  349. package/node_modules/node-datachannel/dist/cjs/lib/index.cjs.map +0 -1
  350. package/node_modules/node-datachannel/dist/cjs/lib/node-datachannel.cjs +0 -94
  351. package/node_modules/node-datachannel/dist/cjs/lib/node-datachannel.cjs.map +0 -1
  352. package/node_modules/node-datachannel/dist/cjs/lib/websocket-server.cjs +0 -45
  353. package/node_modules/node-datachannel/dist/cjs/lib/websocket-server.cjs.map +0 -1
  354. package/node_modules/node-datachannel/dist/cjs/lib/websocket.cjs +0 -8
  355. package/node_modules/node-datachannel/dist/cjs/lib/websocket.cjs.map +0 -1
  356. package/node_modules/node-datachannel/dist/cjs/polyfill/Events.cjs +0 -86
  357. package/node_modules/node-datachannel/dist/cjs/polyfill/Events.cjs.map +0 -1
  358. package/node_modules/node-datachannel/dist/cjs/polyfill/Exception.cjs +0 -34
  359. package/node_modules/node-datachannel/dist/cjs/polyfill/Exception.cjs.map +0 -1
  360. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCCertificate.cjs +0 -34
  361. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCCertificate.cjs.map +0 -1
  362. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCDataChannel.cjs +0 -214
  363. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCDataChannel.cjs.map +0 -1
  364. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCDtlsTransport.cjs +0 -53
  365. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCDtlsTransport.cjs.map +0 -1
  366. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCError.cjs +0 -83
  367. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCError.cjs.map +0 -1
  368. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCIceCandidate.cjs +0 -132
  369. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCIceCandidate.cjs.map +0 -1
  370. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCIceTransport.cjs +0 -94
  371. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCIceTransport.cjs.map +0 -1
  372. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCPeerConnection.cjs +0 -434
  373. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCPeerConnection.cjs.map +0 -1
  374. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCSctpTransport.cjs +0 -59
  375. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCSctpTransport.cjs.map +0 -1
  376. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCSessionDescription.cjs +0 -45
  377. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCSessionDescription.cjs.map +0 -1
  378. package/node_modules/node-datachannel/dist/cjs/polyfill/index.cjs +0 -42
  379. package/node_modules/node-datachannel/dist/cjs/polyfill/index.cjs.map +0 -1
  380. package/node_modules/node-datachannel/dist/esm/index.mjs +0 -8
  381. package/node_modules/node-datachannel/dist/esm/index.mjs.map +0 -1
  382. package/node_modules/node-datachannel/dist/esm/lib/datachannel-stream.mjs +0 -78
  383. package/node_modules/node-datachannel/dist/esm/lib/datachannel-stream.mjs.map +0 -1
  384. package/node_modules/node-datachannel/dist/esm/lib/index.mjs +0 -64
  385. package/node_modules/node-datachannel/dist/esm/lib/index.mjs.map +0 -1
  386. package/node_modules/node-datachannel/dist/esm/lib/node-datachannel.mjs +0 -78
  387. package/node_modules/node-datachannel/dist/esm/lib/node-datachannel.mjs.map +0 -1
  388. package/node_modules/node-datachannel/dist/esm/lib/websocket-server.mjs +0 -43
  389. package/node_modules/node-datachannel/dist/esm/lib/websocket-server.mjs.map +0 -1
  390. package/node_modules/node-datachannel/dist/esm/lib/websocket.mjs +0 -6
  391. package/node_modules/node-datachannel/dist/esm/lib/websocket.mjs.map +0 -1
  392. package/node_modules/node-datachannel/dist/esm/polyfill/Events.mjs +0 -82
  393. package/node_modules/node-datachannel/dist/esm/polyfill/Events.mjs.map +0 -1
  394. package/node_modules/node-datachannel/dist/esm/polyfill/Exception.mjs +0 -28
  395. package/node_modules/node-datachannel/dist/esm/polyfill/Exception.mjs.map +0 -1
  396. package/node_modules/node-datachannel/dist/esm/polyfill/RTCCertificate.mjs +0 -30
  397. package/node_modules/node-datachannel/dist/esm/polyfill/RTCCertificate.mjs.map +0 -1
  398. package/node_modules/node-datachannel/dist/esm/polyfill/RTCDataChannel.mjs +0 -210
  399. package/node_modules/node-datachannel/dist/esm/polyfill/RTCDataChannel.mjs.map +0 -1
  400. package/node_modules/node-datachannel/dist/esm/polyfill/RTCDtlsTransport.mjs +0 -49
  401. package/node_modules/node-datachannel/dist/esm/polyfill/RTCDtlsTransport.mjs.map +0 -1
  402. package/node_modules/node-datachannel/dist/esm/polyfill/RTCError.mjs +0 -79
  403. package/node_modules/node-datachannel/dist/esm/polyfill/RTCError.mjs.map +0 -1
  404. package/node_modules/node-datachannel/dist/esm/polyfill/RTCIceCandidate.mjs +0 -128
  405. package/node_modules/node-datachannel/dist/esm/polyfill/RTCIceCandidate.mjs.map +0 -1
  406. package/node_modules/node-datachannel/dist/esm/polyfill/RTCIceTransport.mjs +0 -89
  407. package/node_modules/node-datachannel/dist/esm/polyfill/RTCIceTransport.mjs.map +0 -1
  408. package/node_modules/node-datachannel/dist/esm/polyfill/RTCPeerConnection.mjs +0 -430
  409. package/node_modules/node-datachannel/dist/esm/polyfill/RTCPeerConnection.mjs.map +0 -1
  410. package/node_modules/node-datachannel/dist/esm/polyfill/RTCSctpTransport.mjs +0 -55
  411. package/node_modules/node-datachannel/dist/esm/polyfill/RTCSctpTransport.mjs.map +0 -1
  412. package/node_modules/node-datachannel/dist/esm/polyfill/RTCSessionDescription.mjs +0 -41
  413. package/node_modules/node-datachannel/dist/esm/polyfill/RTCSessionDescription.mjs.map +0 -1
  414. package/node_modules/node-datachannel/dist/esm/polyfill/index.mjs +0 -27
  415. package/node_modules/node-datachannel/dist/esm/polyfill/index.mjs.map +0 -1
  416. package/node_modules/node-datachannel/dist/types/lib/datachannel-stream.d.ts +0 -24
  417. package/node_modules/node-datachannel/dist/types/lib/index.d.ts +0 -241
  418. package/node_modules/node-datachannel/dist/types/lib/types.d.ts +0 -119
  419. package/node_modules/node-datachannel/dist/types/lib/websocket-server.d.ts +0 -13
  420. package/node_modules/node-datachannel/dist/types/lib/websocket.d.ts +0 -25
  421. package/node_modules/node-datachannel/dist/types/polyfill/Events.d.ts +0 -15
  422. package/node_modules/node-datachannel/dist/types/polyfill/RTCCertificate.d.ts +0 -9
  423. package/node_modules/node-datachannel/dist/types/polyfill/RTCDataChannel.d.ts +0 -29
  424. package/node_modules/node-datachannel/dist/types/polyfill/RTCDtlsTransport.d.ts +0 -15
  425. package/node_modules/node-datachannel/dist/types/polyfill/RTCError.d.ts +0 -17
  426. package/node_modules/node-datachannel/dist/types/polyfill/RTCIceCandidate.d.ts +0 -21
  427. package/node_modules/node-datachannel/dist/types/polyfill/RTCIceTransport.d.ts +0 -30
  428. package/node_modules/node-datachannel/dist/types/polyfill/RTCPeerConnection.d.ts +0 -64
  429. package/node_modules/node-datachannel/dist/types/polyfill/RTCSctpTransport.d.ts +0 -15
  430. package/node_modules/node-datachannel/dist/types/polyfill/RTCSessionDescription.d.ts +0 -10
  431. package/node_modules/node-datachannel/dist/types/polyfill/index.d.ts +0 -26
  432. package/node_modules/node-datachannel/jest.config.ts +0 -14
  433. package/node_modules/node-datachannel/package.json +0 -133
  434. package/node_modules/node-datachannel/rollup.config.mjs +0 -67
  435. package/node_modules/node-datachannel/src/cpp/data-channel-wrapper.cpp +0 -530
  436. package/node_modules/node-datachannel/src/cpp/data-channel-wrapper.h +0 -63
  437. package/node_modules/node-datachannel/src/cpp/ice-udp-mux-listener-wrapper.cpp +0 -172
  438. package/node_modules/node-datachannel/src/cpp/ice-udp-mux-listener-wrapper.h +0 -43
  439. package/node_modules/node-datachannel/src/cpp/main.cpp +0 -58
  440. package/node_modules/node-datachannel/src/cpp/media-audio-wrapper.cpp +0 -457
  441. package/node_modules/node-datachannel/src/cpp/media-audio-wrapper.h +0 -52
  442. package/node_modules/node-datachannel/src/cpp/media-av1packetization.cpp +0 -24
  443. package/node_modules/node-datachannel/src/cpp/media-av1packetization.h +0 -11
  444. package/node_modules/node-datachannel/src/cpp/media-av1rtppacketizer-wrapper.cpp +0 -126
  445. package/node_modules/node-datachannel/src/cpp/media-av1rtppacketizer-wrapper.h +0 -29
  446. package/node_modules/node-datachannel/src/cpp/media-direction.cpp +0 -43
  447. package/node_modules/node-datachannel/src/cpp/media-direction.h +0 -10
  448. package/node_modules/node-datachannel/src/cpp/media-h264rtppacketizer-wrapper.cpp +0 -126
  449. package/node_modules/node-datachannel/src/cpp/media-h264rtppacketizer-wrapper.h +0 -30
  450. package/node_modules/node-datachannel/src/cpp/media-h265rtppacketizer-wrapper.cpp +0 -126
  451. package/node_modules/node-datachannel/src/cpp/media-h265rtppacketizer-wrapper.h +0 -30
  452. package/node_modules/node-datachannel/src/cpp/media-h26xseparator.cpp +0 -32
  453. package/node_modules/node-datachannel/src/cpp/media-h26xseparator.h +0 -11
  454. package/node_modules/node-datachannel/src/cpp/media-mediahandler-helper.cpp +0 -31
  455. package/node_modules/node-datachannel/src/cpp/media-mediahandler-helper.h +0 -11
  456. package/node_modules/node-datachannel/src/cpp/media-pacinghandler-wrapper.cpp +0 -79
  457. package/node_modules/node-datachannel/src/cpp/media-pacinghandler-wrapper.h +0 -28
  458. package/node_modules/node-datachannel/src/cpp/media-rtcpnackresponder-wrapper.cpp +0 -68
  459. package/node_modules/node-datachannel/src/cpp/media-rtcpnackresponder-wrapper.h +0 -28
  460. package/node_modules/node-datachannel/src/cpp/media-rtcpreceivingsession-wrapper.cpp +0 -57
  461. package/node_modules/node-datachannel/src/cpp/media-rtcpreceivingsession-wrapper.h +0 -28
  462. package/node_modules/node-datachannel/src/cpp/media-rtcpsrreporter-wrapper.cpp +0 -93
  463. package/node_modules/node-datachannel/src/cpp/media-rtcpsrreporter-wrapper.h +0 -30
  464. package/node_modules/node-datachannel/src/cpp/media-rtppacketizationconfig-wrapper.cpp +0 -167
  465. package/node_modules/node-datachannel/src/cpp/media-rtppacketizationconfig-wrapper.h +0 -35
  466. package/node_modules/node-datachannel/src/cpp/media-rtppacketizer-wrapper.cpp +0 -95
  467. package/node_modules/node-datachannel/src/cpp/media-rtppacketizer-wrapper.h +0 -30
  468. package/node_modules/node-datachannel/src/cpp/media-track-wrapper.cpp +0 -458
  469. package/node_modules/node-datachannel/src/cpp/media-track-wrapper.h +0 -61
  470. package/node_modules/node-datachannel/src/cpp/media-video-wrapper.cpp +0 -526
  471. package/node_modules/node-datachannel/src/cpp/media-video-wrapper.h +0 -56
  472. package/node_modules/node-datachannel/src/cpp/peer-connection-wrapper.cpp +0 -1298
  473. package/node_modules/node-datachannel/src/cpp/peer-connection-wrapper.h +0 -89
  474. package/node_modules/node-datachannel/src/cpp/rtc-wrapper.cpp +0 -205
  475. package/node_modules/node-datachannel/src/cpp/rtc-wrapper.h +0 -24
  476. package/node_modules/node-datachannel/src/cpp/thread-safe-callback.cpp +0 -57
  477. package/node_modules/node-datachannel/src/cpp/thread-safe-callback.h +0 -47
  478. package/node_modules/node-datachannel/src/cpp/web-socket-server-wrapper.cpp +0 -275
  479. package/node_modules/node-datachannel/src/cpp/web-socket-server-wrapper.h +0 -41
  480. package/node_modules/node-datachannel/src/cpp/web-socket-wrapper.cpp +0 -796
  481. package/node_modules/node-datachannel/src/cpp/web-socket-wrapper.h +0 -63
  482. package/node_modules/node-datachannel/src/index.ts +0 -9
  483. package/node_modules/node-datachannel/src/lib/datachannel-stream.ts +0 -100
  484. package/node_modules/node-datachannel/src/lib/index.ts +0 -290
  485. package/node_modules/node-datachannel/src/lib/node-datachannel.ts +0 -84
  486. package/node_modules/node-datachannel/src/lib/types.ts +0 -169
  487. package/node_modules/node-datachannel/src/lib/websocket-server.ts +0 -37
  488. package/node_modules/node-datachannel/src/lib/websocket.ts +0 -26
  489. package/node_modules/node-datachannel/src/polyfill/Events.ts +0 -82
  490. package/node_modules/node-datachannel/src/polyfill/Exception.ts +0 -37
  491. package/node_modules/node-datachannel/src/polyfill/README.md +0 -41
  492. package/node_modules/node-datachannel/src/polyfill/RTCCertificate.ts +0 -21
  493. package/node_modules/node-datachannel/src/polyfill/RTCDataChannel.ts +0 -225
  494. package/node_modules/node-datachannel/src/polyfill/RTCDtlsTransport.ts +0 -46
  495. package/node_modules/node-datachannel/src/polyfill/RTCError.ts +0 -78
  496. package/node_modules/node-datachannel/src/polyfill/RTCIceCandidate.ts +0 -128
  497. package/node_modules/node-datachannel/src/polyfill/RTCIceTransport.ts +0 -90
  498. package/node_modules/node-datachannel/src/polyfill/RTCPeerConnection.ts +0 -527
  499. package/node_modules/node-datachannel/src/polyfill/RTCSctpTransport.ts +0 -51
  500. package/node_modules/node-datachannel/src/polyfill/RTCSessionDescription.ts +0 -41
  501. package/node_modules/node-datachannel/src/polyfill/index.ts +0 -38
  502. package/node_modules/node-datachannel/tsconfig.json +0 -21
  503. package/node_modules/p-limit/index.d.ts +0 -38
  504. package/node_modules/p-limit/index.js +0 -57
  505. package/node_modules/p-limit/license +0 -9
  506. package/node_modules/p-limit/package.json +0 -52
  507. package/node_modules/p-limit/readme.md +0 -101
  508. package/node_modules/p-locate/index.d.ts +0 -64
  509. package/node_modules/p-locate/index.js +0 -52
  510. package/node_modules/p-locate/license +0 -9
  511. package/node_modules/p-locate/package.json +0 -53
  512. package/node_modules/p-locate/readme.md +0 -90
  513. package/node_modules/p-try/index.d.ts +0 -39
  514. package/node_modules/p-try/index.js +0 -9
  515. package/node_modules/p-try/license +0 -9
  516. package/node_modules/p-try/package.json +0 -42
  517. package/node_modules/p-try/readme.md +0 -58
  518. package/node_modules/path-exists/index.d.ts +0 -28
  519. package/node_modules/path-exists/index.js +0 -23
  520. package/node_modules/path-exists/license +0 -9
  521. package/node_modules/path-exists/package.json +0 -39
  522. package/node_modules/path-exists/readme.md +0 -52
  523. package/node_modules/pngjs/.eslintignore +0 -2
  524. package/node_modules/pngjs/.eslintrc.json +0 -19
  525. package/node_modules/pngjs/.prettierignore +0 -3
  526. package/node_modules/pngjs/LICENSE +0 -20
  527. package/node_modules/pngjs/README.md +0 -429
  528. package/node_modules/pngjs/browser.js +0 -16096
  529. package/node_modules/pngjs/coverage/lcov-report/base.css +0 -354
  530. package/node_modules/pngjs/coverage/lcov-report/bitmapper.js.html +0 -881
  531. package/node_modules/pngjs/coverage/lcov-report/bitpacker.js.html +0 -554
  532. package/node_modules/pngjs/coverage/lcov-report/block-navigation.js +0 -77
  533. package/node_modules/pngjs/coverage/lcov-report/chunkstream.js.html +0 -647
  534. package/node_modules/pngjs/coverage/lcov-report/constants.js.html +0 -176
  535. package/node_modules/pngjs/coverage/lcov-report/crc.js.html +0 -200
  536. package/node_modules/pngjs/coverage/lcov-report/favicon.png +0 -0
  537. package/node_modules/pngjs/coverage/lcov-report/filter-pack.js.html +0 -593
  538. package/node_modules/pngjs/coverage/lcov-report/filter-parse-async.js.html +0 -152
  539. package/node_modules/pngjs/coverage/lcov-report/filter-parse-sync.js.html +0 -143
  540. package/node_modules/pngjs/coverage/lcov-report/filter-parse.js.html +0 -611
  541. package/node_modules/pngjs/coverage/lcov-report/format-normaliser.js.html +0 -359
  542. package/node_modules/pngjs/coverage/lcov-report/index.html +0 -426
  543. package/node_modules/pngjs/coverage/lcov-report/interlace.js.html +0 -365
  544. package/node_modules/pngjs/coverage/lcov-report/packer-async.js.html +0 -230
  545. package/node_modules/pngjs/coverage/lcov-report/packer-sync.js.html +0 -248
  546. package/node_modules/pngjs/coverage/lcov-report/packer.js.html +0 -467
  547. package/node_modules/pngjs/coverage/lcov-report/paeth-predictor.js.html +0 -128
  548. package/node_modules/pngjs/coverage/lcov-report/parser-async.js.html +0 -575
  549. package/node_modules/pngjs/coverage/lcov-report/parser-sync.js.html +0 -404
  550. package/node_modules/pngjs/coverage/lcov-report/parser.js.html +0 -950
  551. package/node_modules/pngjs/coverage/lcov-report/png-sync.js.html +0 -116
  552. package/node_modules/pngjs/coverage/lcov-report/png.js.html +0 -662
  553. package/node_modules/pngjs/coverage/lcov-report/prettify.css +0 -101
  554. package/node_modules/pngjs/coverage/lcov-report/prettify.js +0 -1007
  555. package/node_modules/pngjs/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  556. package/node_modules/pngjs/coverage/lcov-report/sorter.js +0 -169
  557. package/node_modules/pngjs/coverage/lcov-report/sync-inflate.js.html +0 -584
  558. package/node_modules/pngjs/coverage/lcov-report/sync-reader.js.html +0 -215
  559. package/node_modules/pngjs/coverage/lcov.info +0 -2177
  560. package/node_modules/pngjs/lib/bitmapper.js +0 -267
  561. package/node_modules/pngjs/lib/bitpacker.js +0 -158
  562. package/node_modules/pngjs/lib/chunkstream.js +0 -189
  563. package/node_modules/pngjs/lib/constants.js +0 -32
  564. package/node_modules/pngjs/lib/crc.js +0 -40
  565. package/node_modules/pngjs/lib/filter-pack.js +0 -171
  566. package/node_modules/pngjs/lib/filter-parse-async.js +0 -24
  567. package/node_modules/pngjs/lib/filter-parse-sync.js +0 -21
  568. package/node_modules/pngjs/lib/filter-parse.js +0 -177
  569. package/node_modules/pngjs/lib/format-normaliser.js +0 -93
  570. package/node_modules/pngjs/lib/interlace.js +0 -95
  571. package/node_modules/pngjs/lib/packer-async.js +0 -50
  572. package/node_modules/pngjs/lib/packer-sync.js +0 -56
  573. package/node_modules/pngjs/lib/packer.js +0 -129
  574. package/node_modules/pngjs/lib/paeth-predictor.js +0 -16
  575. package/node_modules/pngjs/lib/parser-async.js +0 -165
  576. package/node_modules/pngjs/lib/parser-sync.js +0 -108
  577. package/node_modules/pngjs/lib/parser.js +0 -290
  578. package/node_modules/pngjs/lib/png-sync.js +0 -12
  579. package/node_modules/pngjs/lib/png.js +0 -194
  580. package/node_modules/pngjs/lib/sync-inflate.js +0 -168
  581. package/node_modules/pngjs/lib/sync-reader.js +0 -45
  582. package/node_modules/pngjs/package.json +0 -73
  583. package/node_modules/qrcode/README.md +0 -770
  584. package/node_modules/qrcode/bin/qrcode +0 -159
  585. package/node_modules/qrcode/helper/to-sjis-browser.js +0 -2
  586. package/node_modules/qrcode/helper/to-sjis.js +0 -105
  587. package/node_modules/qrcode/lib/browser.js +0 -76
  588. package/node_modules/qrcode/lib/can-promise.js +0 -7
  589. package/node_modules/qrcode/lib/core/alignment-pattern.js +0 -83
  590. package/node_modules/qrcode/lib/core/alphanumeric-data.js +0 -59
  591. package/node_modules/qrcode/lib/core/bit-buffer.js +0 -37
  592. package/node_modules/qrcode/lib/core/bit-matrix.js +0 -65
  593. package/node_modules/qrcode/lib/core/byte-data.js +0 -30
  594. package/node_modules/qrcode/lib/core/error-correction-code.js +0 -135
  595. package/node_modules/qrcode/lib/core/error-correction-level.js +0 -50
  596. package/node_modules/qrcode/lib/core/finder-pattern.js +0 -22
  597. package/node_modules/qrcode/lib/core/format-info.js +0 -29
  598. package/node_modules/qrcode/lib/core/galois-field.js +0 -69
  599. package/node_modules/qrcode/lib/core/kanji-data.js +0 -54
  600. package/node_modules/qrcode/lib/core/mask-pattern.js +0 -234
  601. package/node_modules/qrcode/lib/core/mode.js +0 -167
  602. package/node_modules/qrcode/lib/core/numeric-data.js +0 -43
  603. package/node_modules/qrcode/lib/core/polynomial.js +0 -62
  604. package/node_modules/qrcode/lib/core/qrcode.js +0 -495
  605. package/node_modules/qrcode/lib/core/reed-solomon-encoder.js +0 -56
  606. package/node_modules/qrcode/lib/core/regex.js +0 -31
  607. package/node_modules/qrcode/lib/core/segments.js +0 -330
  608. package/node_modules/qrcode/lib/core/utils.js +0 -63
  609. package/node_modules/qrcode/lib/core/version-check.js +0 -9
  610. package/node_modules/qrcode/lib/core/version.js +0 -163
  611. package/node_modules/qrcode/lib/index.js +0 -12
  612. package/node_modules/qrcode/lib/renderer/canvas.js +0 -63
  613. package/node_modules/qrcode/lib/renderer/png.js +0 -78
  614. package/node_modules/qrcode/lib/renderer/svg-tag.js +0 -81
  615. package/node_modules/qrcode/lib/renderer/svg.js +0 -19
  616. package/node_modules/qrcode/lib/renderer/terminal/terminal-small.js +0 -85
  617. package/node_modules/qrcode/lib/renderer/terminal/terminal.js +0 -49
  618. package/node_modules/qrcode/lib/renderer/terminal.js +0 -9
  619. package/node_modules/qrcode/lib/renderer/utf8.js +0 -71
  620. package/node_modules/qrcode/lib/renderer/utils.js +0 -99
  621. package/node_modules/qrcode/lib/server.js +0 -138
  622. package/node_modules/qrcode/license +0 -10
  623. package/node_modules/qrcode/package.json +0 -77
  624. package/node_modules/require-directory/.jshintrc +0 -67
  625. package/node_modules/require-directory/.npmignore +0 -1
  626. package/node_modules/require-directory/.travis.yml +0 -3
  627. package/node_modules/require-directory/LICENSE +0 -22
  628. package/node_modules/require-directory/README.markdown +0 -184
  629. package/node_modules/require-directory/index.js +0 -86
  630. package/node_modules/require-directory/package.json +0 -40
  631. package/node_modules/require-main-filename/CHANGELOG.md +0 -26
  632. package/node_modules/require-main-filename/LICENSE.txt +0 -14
  633. package/node_modules/require-main-filename/README.md +0 -26
  634. package/node_modules/require-main-filename/index.js +0 -18
  635. package/node_modules/require-main-filename/package.json +0 -35
  636. package/node_modules/semver/LICENSE +0 -15
  637. package/node_modules/semver/README.md +0 -680
  638. package/node_modules/semver/bin/semver.js +0 -195
  639. package/node_modules/semver/classes/comparator.js +0 -143
  640. package/node_modules/semver/classes/index.js +0 -7
  641. package/node_modules/semver/classes/range.js +0 -577
  642. package/node_modules/semver/classes/semver.js +0 -350
  643. package/node_modules/semver/functions/clean.js +0 -8
  644. package/node_modules/semver/functions/cmp.js +0 -54
  645. package/node_modules/semver/functions/coerce.js +0 -62
  646. package/node_modules/semver/functions/compare-build.js +0 -9
  647. package/node_modules/semver/functions/compare-loose.js +0 -5
  648. package/node_modules/semver/functions/compare.js +0 -7
  649. package/node_modules/semver/functions/diff.js +0 -60
  650. package/node_modules/semver/functions/eq.js +0 -5
  651. package/node_modules/semver/functions/gt.js +0 -5
  652. package/node_modules/semver/functions/gte.js +0 -5
  653. package/node_modules/semver/functions/inc.js +0 -21
  654. package/node_modules/semver/functions/lt.js +0 -5
  655. package/node_modules/semver/functions/lte.js +0 -5
  656. package/node_modules/semver/functions/major.js +0 -5
  657. package/node_modules/semver/functions/minor.js +0 -5
  658. package/node_modules/semver/functions/neq.js +0 -5
  659. package/node_modules/semver/functions/parse.js +0 -18
  660. package/node_modules/semver/functions/patch.js +0 -5
  661. package/node_modules/semver/functions/prerelease.js +0 -8
  662. package/node_modules/semver/functions/rcompare.js +0 -5
  663. package/node_modules/semver/functions/rsort.js +0 -5
  664. package/node_modules/semver/functions/satisfies.js +0 -12
  665. package/node_modules/semver/functions/sort.js +0 -5
  666. package/node_modules/semver/functions/truncate.js +0 -48
  667. package/node_modules/semver/functions/valid.js +0 -8
  668. package/node_modules/semver/index.js +0 -93
  669. package/node_modules/semver/internal/constants.js +0 -37
  670. package/node_modules/semver/internal/debug.js +0 -11
  671. package/node_modules/semver/internal/identifiers.js +0 -29
  672. package/node_modules/semver/internal/lrucache.js +0 -42
  673. package/node_modules/semver/internal/parse-options.js +0 -17
  674. package/node_modules/semver/internal/re.js +0 -223
  675. package/node_modules/semver/package.json +0 -78
  676. package/node_modules/semver/preload.js +0 -4
  677. package/node_modules/semver/range.bnf +0 -17
  678. package/node_modules/semver/ranges/gtr.js +0 -6
  679. package/node_modules/semver/ranges/intersects.js +0 -9
  680. package/node_modules/semver/ranges/ltr.js +0 -6
  681. package/node_modules/semver/ranges/max-satisfying.js +0 -27
  682. package/node_modules/semver/ranges/min-satisfying.js +0 -26
  683. package/node_modules/semver/ranges/min-version.js +0 -63
  684. package/node_modules/semver/ranges/outside.js +0 -82
  685. package/node_modules/semver/ranges/simplify.js +0 -49
  686. package/node_modules/semver/ranges/subset.js +0 -249
  687. package/node_modules/semver/ranges/to-comparators.js +0 -10
  688. package/node_modules/semver/ranges/valid.js +0 -13
  689. package/node_modules/set-blocking/CHANGELOG.md +0 -26
  690. package/node_modules/set-blocking/LICENSE.txt +0 -14
  691. package/node_modules/set-blocking/README.md +0 -31
  692. package/node_modules/set-blocking/index.js +0 -7
  693. package/node_modules/set-blocking/package.json +0 -42
  694. package/node_modules/sharp/LICENSE +0 -191
  695. package/node_modules/sharp/README.md +0 -112
  696. package/node_modules/sharp/dist/channel.cjs +0 -177
  697. package/node_modules/sharp/dist/channel.mjs +0 -177
  698. package/node_modules/sharp/dist/colour.cjs +0 -199
  699. package/node_modules/sharp/dist/colour.mjs +0 -199
  700. package/node_modules/sharp/dist/composite.cjs +0 -213
  701. package/node_modules/sharp/dist/composite.mjs +0 -213
  702. package/node_modules/sharp/dist/constructor.cjs +0 -511
  703. package/node_modules/sharp/dist/constructor.mjs +0 -511
  704. package/node_modules/sharp/dist/index.cjs +0 -25
  705. package/node_modules/sharp/dist/index.d.cts +0 -1999
  706. package/node_modules/sharp/dist/index.d.mts +0 -2046
  707. package/node_modules/sharp/dist/index.mjs +0 -25
  708. package/node_modules/sharp/dist/input.cjs +0 -819
  709. package/node_modules/sharp/dist/input.mjs +0 -819
  710. package/node_modules/sharp/dist/is.cjs +0 -143
  711. package/node_modules/sharp/dist/is.mjs +0 -143
  712. package/node_modules/sharp/dist/libvips.cjs +0 -212
  713. package/node_modules/sharp/dist/libvips.mjs +0 -212
  714. package/node_modules/sharp/dist/operation.cjs +0 -1002
  715. package/node_modules/sharp/dist/operation.mjs +0 -1002
  716. package/node_modules/sharp/dist/output.cjs +0 -1785
  717. package/node_modules/sharp/dist/output.mjs +0 -1785
  718. package/node_modules/sharp/dist/resize.cjs +0 -617
  719. package/node_modules/sharp/dist/resize.mjs +0 -617
  720. package/node_modules/sharp/dist/sharp.cjs +0 -174
  721. package/node_modules/sharp/dist/sharp.mjs +0 -174
  722. package/node_modules/sharp/dist/utility.cjs +0 -301
  723. package/node_modules/sharp/dist/utility.mjs +0 -301
  724. package/node_modules/sharp/install/build.js +0 -38
  725. package/node_modules/sharp/lib/index.d.ts +0 -1999
  726. package/node_modules/sharp/package.json +0 -227
  727. package/node_modules/sharp/src/binding.gyp +0 -303
  728. package/node_modules/sharp/src/common.cc +0 -1186
  729. package/node_modules/sharp/src/common.h +0 -421
  730. package/node_modules/sharp/src/metadata.cc +0 -404
  731. package/node_modules/sharp/src/metadata.h +0 -95
  732. package/node_modules/sharp/src/operations.cc +0 -516
  733. package/node_modules/sharp/src/operations.h +0 -137
  734. package/node_modules/sharp/src/pipeline.cc +0 -1948
  735. package/node_modules/sharp/src/pipeline.h +0 -422
  736. package/node_modules/sharp/src/sharp.cc +0 -43
  737. package/node_modules/sharp/src/stats.cc +0 -186
  738. package/node_modules/sharp/src/stats.h +0 -62
  739. package/node_modules/sharp/src/utilities.cc +0 -289
  740. package/node_modules/sharp/src/utilities.h +0 -22
  741. package/node_modules/string-width/index.d.ts +0 -29
  742. package/node_modules/string-width/index.js +0 -47
  743. package/node_modules/string-width/license +0 -9
  744. package/node_modules/string-width/package.json +0 -56
  745. package/node_modules/string-width/readme.md +0 -50
  746. package/node_modules/strip-ansi/index.d.ts +0 -17
  747. package/node_modules/strip-ansi/index.js +0 -4
  748. package/node_modules/strip-ansi/license +0 -9
  749. package/node_modules/strip-ansi/package.json +0 -54
  750. package/node_modules/strip-ansi/readme.md +0 -46
  751. package/node_modules/which-module/LICENSE +0 -13
  752. package/node_modules/which-module/README.md +0 -58
  753. package/node_modules/which-module/index.js +0 -9
  754. package/node_modules/which-module/package.json +0 -41
  755. package/node_modules/wrap-ansi/index.js +0 -186
  756. package/node_modules/wrap-ansi/license +0 -9
  757. package/node_modules/wrap-ansi/package.json +0 -61
  758. package/node_modules/wrap-ansi/readme.md +0 -97
  759. package/node_modules/ws/LICENSE +0 -20
  760. package/node_modules/ws/README.md +0 -548
  761. package/node_modules/ws/browser.js +0 -8
  762. package/node_modules/ws/index.js +0 -22
  763. package/node_modules/ws/lib/buffer-util.js +0 -131
  764. package/node_modules/ws/lib/constants.js +0 -19
  765. package/node_modules/ws/lib/event-target.js +0 -292
  766. package/node_modules/ws/lib/extension.js +0 -203
  767. package/node_modules/ws/lib/limiter.js +0 -55
  768. package/node_modules/ws/lib/permessage-deflate.js +0 -530
  769. package/node_modules/ws/lib/receiver.js +0 -743
  770. package/node_modules/ws/lib/sender.js +0 -607
  771. package/node_modules/ws/lib/stream.js +0 -161
  772. package/node_modules/ws/lib/subprotocol.js +0 -62
  773. package/node_modules/ws/lib/validation.js +0 -152
  774. package/node_modules/ws/lib/websocket-server.js +0 -562
  775. package/node_modules/ws/lib/websocket.js +0 -1407
  776. package/node_modules/ws/package.json +0 -74
  777. package/node_modules/ws/wrapper.mjs +0 -21
  778. package/node_modules/y18n/CHANGELOG.md +0 -35
  779. package/node_modules/y18n/LICENSE +0 -13
  780. package/node_modules/y18n/README.md +0 -109
  781. package/node_modules/y18n/index.js +0 -188
  782. package/node_modules/y18n/package.json +0 -39
  783. package/node_modules/yargs/CHANGELOG.md +0 -420
  784. package/node_modules/yargs/LICENSE +0 -21
  785. package/node_modules/yargs/README.md +0 -140
  786. package/node_modules/yargs/build/lib/apply-extends.d.ts +0 -2
  787. package/node_modules/yargs/build/lib/apply-extends.js +0 -65
  788. package/node_modules/yargs/build/lib/argsert.d.ts +0 -2
  789. package/node_modules/yargs/build/lib/argsert.js +0 -65
  790. package/node_modules/yargs/build/lib/command.d.ts +0 -64
  791. package/node_modules/yargs/build/lib/command.js +0 -416
  792. package/node_modules/yargs/build/lib/common-types.d.ts +0 -36
  793. package/node_modules/yargs/build/lib/common-types.js +0 -25
  794. package/node_modules/yargs/build/lib/completion-templates.d.ts +0 -2
  795. package/node_modules/yargs/build/lib/completion-templates.js +0 -50
  796. package/node_modules/yargs/build/lib/completion.d.ts +0 -21
  797. package/node_modules/yargs/build/lib/completion.js +0 -135
  798. package/node_modules/yargs/build/lib/is-promise.d.ts +0 -1
  799. package/node_modules/yargs/build/lib/is-promise.js +0 -9
  800. package/node_modules/yargs/build/lib/levenshtein.d.ts +0 -1
  801. package/node_modules/yargs/build/lib/levenshtein.js +0 -58
  802. package/node_modules/yargs/build/lib/middleware.d.ts +0 -10
  803. package/node_modules/yargs/build/lib/middleware.js +0 -57
  804. package/node_modules/yargs/build/lib/obj-filter.d.ts +0 -1
  805. package/node_modules/yargs/build/lib/obj-filter.js +0 -14
  806. package/node_modules/yargs/build/lib/parse-command.d.ts +0 -11
  807. package/node_modules/yargs/build/lib/parse-command.js +0 -36
  808. package/node_modules/yargs/build/lib/process-argv.d.ts +0 -2
  809. package/node_modules/yargs/build/lib/process-argv.js +0 -31
  810. package/node_modules/yargs/build/lib/usage.d.ts +0 -49
  811. package/node_modules/yargs/build/lib/usage.js +0 -540
  812. package/node_modules/yargs/build/lib/validation.d.ts +0 -34
  813. package/node_modules/yargs/build/lib/validation.js +0 -330
  814. package/node_modules/yargs/build/lib/yargs.d.ts +0 -274
  815. package/node_modules/yargs/build/lib/yargs.js +0 -1190
  816. package/node_modules/yargs/build/lib/yerror.d.ts +0 -4
  817. package/node_modules/yargs/build/lib/yerror.js +0 -11
  818. package/node_modules/yargs/index.js +0 -40
  819. package/node_modules/yargs/locales/be.json +0 -46
  820. package/node_modules/yargs/locales/de.json +0 -46
  821. package/node_modules/yargs/locales/en.json +0 -51
  822. package/node_modules/yargs/locales/es.json +0 -46
  823. package/node_modules/yargs/locales/fi.json +0 -49
  824. package/node_modules/yargs/locales/fr.json +0 -53
  825. package/node_modules/yargs/locales/hi.json +0 -49
  826. package/node_modules/yargs/locales/hu.json +0 -46
  827. package/node_modules/yargs/locales/id.json +0 -50
  828. package/node_modules/yargs/locales/it.json +0 -46
  829. package/node_modules/yargs/locales/ja.json +0 -51
  830. package/node_modules/yargs/locales/ko.json +0 -49
  831. package/node_modules/yargs/locales/nb.json +0 -44
  832. package/node_modules/yargs/locales/nl.json +0 -49
  833. package/node_modules/yargs/locales/nn.json +0 -44
  834. package/node_modules/yargs/locales/pirate.json +0 -13
  835. package/node_modules/yargs/locales/pl.json +0 -49
  836. package/node_modules/yargs/locales/pt.json +0 -45
  837. package/node_modules/yargs/locales/pt_BR.json +0 -48
  838. package/node_modules/yargs/locales/ru.json +0 -46
  839. package/node_modules/yargs/locales/th.json +0 -46
  840. package/node_modules/yargs/locales/tr.json +0 -48
  841. package/node_modules/yargs/locales/zh_CN.json +0 -48
  842. package/node_modules/yargs/locales/zh_TW.json +0 -47
  843. package/node_modules/yargs/package.json +0 -92
  844. package/node_modules/yargs/yargs.js +0 -14
  845. package/node_modules/yargs-parser/CHANGELOG.md +0 -601
  846. package/node_modules/yargs-parser/LICENSE.txt +0 -14
  847. package/node_modules/yargs-parser/README.md +0 -449
  848. package/node_modules/yargs-parser/index.js +0 -1032
  849. package/node_modules/yargs-parser/lib/tokenize-arg-string.js +0 -40
  850. package/node_modules/yargs-parser/package.json +0 -46
@@ -2,19 +2,23 @@ import fs from 'node:fs';
2
2
  import path from 'node:path';
3
3
  import { randomUUID } from 'node:crypto';
4
4
 
5
- export function relayAdminState(file, initialMaxRelaySessions) {
6
- let value = { version: 2, maxRelaySessions: initialMaxRelaySessions, announcement: null, announcements: [] };
5
+ // 80 title + 2000 body UTF-16 units fit even when every unit uses a six-byte JSON escape.
6
+ export const MAX_ADMIN_REQUEST_BYTES = 16 * 1024;
7
+
8
+ export function relayAdminState(file, initialMaxRelaySessions, { initial, persist } = {}) {
9
+ let value = initial ? validate(initial) : { version: 3, maxRelaySessions: initialMaxRelaySessions, announcement: null, announcements: [] };
7
10
  if (file && fs.existsSync(file)) value = validate(JSON.parse(fs.readFileSync(file, 'utf8')));
8
11
 
9
- function save(next) {
10
- value = validate(next);
11
- if (!file) return value;
12
+ async function save(next) {
13
+ const validated = validate(next);
14
+ if (persist) await persist(validated);
15
+ if (!file) { value = validated; return value; }
12
16
  fs.mkdirSync(path.dirname(file), { recursive: true, mode: 0o700 });
13
17
  const temporary = `${file}.${randomUUID()}.tmp`;
14
18
  let descriptor;
15
19
  try {
16
20
  descriptor = fs.openSync(temporary, 'wx', 0o600);
17
- fs.writeFileSync(descriptor, JSON.stringify(value));
21
+ fs.writeFileSync(descriptor, JSON.stringify(validated));
18
22
  fs.fsyncSync(descriptor); fs.closeSync(descriptor); descriptor = undefined;
19
23
  fs.renameSync(temporary, file);
20
24
  if (process.platform !== 'win32') {
@@ -25,18 +29,45 @@ export function relayAdminState(file, initialMaxRelaySessions) {
25
29
  if (descriptor !== undefined) fs.closeSync(descriptor);
26
30
  fs.rmSync(temporary, { force: true });
27
31
  }
32
+ value = validated;
28
33
  return value;
29
34
  }
30
35
 
31
36
  return {
32
37
  read: () => structuredClone(value),
33
38
  setMaxRelaySessions(maxRelaySessions) { return save({ ...value, maxRelaySessions }); },
34
- publish(title, message) {
35
- const announcement = { id: randomUUID(), title: clean(title, 80), message: clean(message, 2000),
36
- publishedAt: new Date().toISOString() };
37
- return save({ ...value, announcement, announcements: [announcement, ...value.announcements] });
39
+ createAnnouncement(title, message, publish = false) {
40
+ const now = new Date().toISOString();
41
+ const record = { id: randomUUID(), title: clean(title, 80), message: clean(message, 2000),
42
+ createdAt: now, updatedAt: now, publishedAt: publish ? now : null, status: publish ? 'active' : 'draft' };
43
+ const announcements = value.announcements.map(item => publish && item.status === 'active'
44
+ ? { ...item, status: 'withdrawn', updatedAt: now } : item);
45
+ return save({ ...value, announcement: publish ? publicAnnouncement(record) : value.announcement,
46
+ announcements: [record, ...announcements] });
47
+ },
48
+ updateDraft(id, title, message) {
49
+ const existing = value.announcements.find(item => item.id === id);
50
+ if (!existing || existing.status !== 'draft') throw new Error('Only drafts can be edited');
51
+ return save({ ...value, announcements: value.announcements.map(item => item.id === id
52
+ ? { ...item, title: clean(title, 80), message: clean(message, 2000), updatedAt: new Date().toISOString() } : item) });
53
+ },
54
+ publishDraft(id, title, message) {
55
+ const existing = value.announcements.find(item => item.id === id);
56
+ if (!existing || existing.status !== 'draft') throw new Error('Only drafts can be published');
57
+ const now = new Date().toISOString();
58
+ const published = { ...existing, title: title === undefined ? existing.title : clean(title, 80),
59
+ message: message === undefined ? existing.message : clean(message, 2000),
60
+ publishedAt: now, updatedAt: now, status: 'active' };
61
+ return save({ ...value, announcement: publicAnnouncement(published),
62
+ announcements: value.announcements.map(item => item.id === id ? published : item.status === 'active'
63
+ ? { ...item, status: 'withdrawn', updatedAt: now } : item) });
64
+ },
65
+ withdraw(id) {
66
+ if (!value.announcement || value.announcement.id !== id) throw new Error('Announcement is no longer active');
67
+ const now = new Date().toISOString();
68
+ return save({ ...value, announcement: null, announcements: value.announcements.map(item => item.status === 'active'
69
+ ? { ...item, status: 'withdrawn', updatedAt: now } : item) });
38
70
  },
39
- withdraw() { return save({ ...value, announcement: null }); },
40
71
  deleteAnnouncement(id) {
41
72
  if (typeof id !== 'string' || !value.announcements.some(item => item.id === id)) throw new Error('Announcement not found');
42
73
  if (value.announcement?.id === id) throw new Error('Withdraw the current announcement before deleting it');
@@ -46,18 +77,24 @@ export function relayAdminState(file, initialMaxRelaySessions) {
46
77
  }
47
78
 
48
79
  function validate(source) {
49
- if (!source || ![1, 2].includes(source.version) || !Number.isSafeInteger(source.maxRelaySessions) ||
80
+ if (!source || ![1, 2, 3].includes(source.version) || !Number.isSafeInteger(source.maxRelaySessions) ||
50
81
  source.maxRelaySessions < 1 || source.maxRelaySessions > 256) throw new Error('Invalid relay admin state');
51
82
  const announcement = source.announcement == null ? null : validateAnnouncement(source.announcement);
52
83
  const announcements = source.version === 1 ? (announcement ? [announcement] : []) : source.announcements;
53
84
  if (!Array.isArray(announcements)) throw new Error('Invalid relay announcement history');
54
- const validated = announcements.map(validateAnnouncement);
55
- if (new Set(validated.map(item => item.id)).size !== validated.length ||
56
- (announcement && !validated.some(item => item.id === announcement.id &&
85
+ const validated = source.version === 3 ? announcements.map(validateRecord) : announcements.map(item => {
86
+ const old = validateAnnouncement(item);
87
+ return { ...old, createdAt: old.publishedAt, updatedAt: old.publishedAt,
88
+ status: old.id === announcement?.id ? 'active' : 'withdrawn' };
89
+ });
90
+ const active = validated.filter(item => item.status === 'active');
91
+ if (new Set(validated.map(item => item.id)).size !== validated.length || active.length > 1 ||
92
+ (active.length === 0) !== (announcement === null) ||
93
+ (announcement && !active.some(item => item.id === announcement.id &&
57
94
  item.title === announcement.title && item.message === announcement.message && item.publishedAt === announcement.publishedAt))) {
58
95
  throw new Error('Invalid relay announcement history');
59
96
  }
60
- return { version: 2, maxRelaySessions: source.maxRelaySessions, announcement, announcements: validated };
97
+ return { version: 3, maxRelaySessions: source.maxRelaySessions, announcement, announcements: validated };
61
98
  }
62
99
 
63
100
  function validateAnnouncement(item) {
@@ -66,6 +103,22 @@ function validateAnnouncement(item) {
66
103
  return { id: item.id, title: clean(item.title, 80), message: clean(item.message, 2000), publishedAt: item.publishedAt };
67
104
  }
68
105
 
106
+ function validateRecord(item) {
107
+ if (!item || !/^[\w-]{16,128}$/.test(item.id) || !['draft', 'active', 'withdrawn'].includes(item.status) ||
108
+ typeof item.createdAt !== 'string' || !Number.isFinite(Date.parse(item.createdAt)) ||
109
+ typeof item.updatedAt !== 'string' || !Number.isFinite(Date.parse(item.updatedAt)) ||
110
+ (item.status === 'draft' ? item.publishedAt !== null :
111
+ typeof item.publishedAt !== 'string' || !Number.isFinite(Date.parse(item.publishedAt)))) {
112
+ throw new Error('Invalid relay announcement record');
113
+ }
114
+ return { id: item.id, title: clean(item.title, 80), message: clean(item.message, 2000),
115
+ createdAt: item.createdAt, updatedAt: item.updatedAt, publishedAt: item.publishedAt, status: item.status };
116
+ }
117
+
118
+ function publicAnnouncement(record) {
119
+ return { id: record.id, title: record.title, message: record.message, publishedAt: record.publishedAt };
120
+ }
121
+
69
122
  function clean(value, limit) {
70
123
  if (typeof value !== 'string' || !value.trim() || value.trim().length > limit || /[\u0000-\u0008\u000b\u000c\u000e-\u001f\u007f]/.test(value)) {
71
124
  throw new Error('Invalid announcement text');
@@ -0,0 +1,58 @@
1
+ // Shared semantic resources for the standalone relay management pages.
2
+ export const adminUiTokens = `:root{
3
+ --admin-page:#f5f7fa;--admin-text:#26332b;--admin-muted:#607168;
4
+ --admin-surface:#ffffffee;--admin-row:#f8faf8;
5
+ --admin-border:#d5ddd8;--admin-row-border:#dce5df;
6
+ --admin-accent:#286e43;--admin-accent-surface:#e0f0e5;
7
+ --admin-error:#a5443b;--admin-card-radius:16px;--admin-control-radius:9px;
8
+ --admin-card-padding:22px;
9
+ --admin-font:14px;--admin-heading:24px;--admin-title:18px;--admin-value:16px;--admin-label:12px;
10
+ --admin-space-sm:6px;--admin-space:12px;--admin-space-lg:18px;--admin-control-height:44px;
11
+ --admin-login-width:400px;--admin-status-height:42px;
12
+ --admin-footer-caption:12px;--admin-footer-opacity:0.75;--admin-footer-space:24px;
13
+ }`;
14
+
15
+ export const adminFooterStyles = `body{display:flex;flex-direction:column}
16
+ body>main{width:100%;flex:1;margin:0 auto}
17
+ .admin-footer{flex-shrink:0;padding:0 var(--admin-footer-space) var(--admin-footer-space);text-align:center;color:var(--admin-muted);font-size:var(--admin-footer-caption);opacity:var(--admin-footer-opacity)}`;
18
+
19
+ export const adminAuthStyles = `
20
+ *{box-sizing:border-box}.admin-login{margin:0;min-height:100vh;background:var(--admin-page);color:var(--admin-text);font:var(--admin-font)/1.5 system-ui,"Microsoft YaHei",sans-serif}
21
+ .admin-login main{display:grid;place-items:center;padding:var(--admin-card-padding)}
22
+ .login-card{width:100%;max-width:var(--admin-login-width);padding:var(--admin-card-padding);background:var(--admin-surface);border:1px solid var(--admin-border);border-radius:var(--admin-card-radius);display:grid;gap:var(--admin-space)}
23
+ .login-card h1{font-size:var(--admin-heading);margin:0}.login-card p{margin:0;color:var(--admin-muted)}
24
+ .login-card input,.login-card button{font:inherit;min-height:var(--admin-control-height);padding:var(--admin-space);border:1px solid var(--admin-border);border-radius:var(--admin-control-radius)}
25
+ .login-card input{width:100%;background:var(--admin-surface);color:var(--admin-text)}
26
+ .login-card button{background:var(--admin-accent-surface);color:var(--admin-accent);cursor:pointer;font-weight:600}
27
+ .login-card button:disabled{opacity:.6;cursor:wait}.login-card :focus-visible{outline:2px solid var(--admin-accent);outline-offset:2px}
28
+ .login-card #result{min-height:var(--admin-status-height);color:var(--admin-error)}
29
+ .page-head .admin-logout{margin-left:auto;flex:none;white-space:nowrap}
30
+ @media(max-width:600px){.page-head{flex-wrap:wrap}.page-head .nav{order:3;flex-basis:100%}}`;
31
+
32
+ export const adminWorkstationStyles = `
33
+ .workstation-content{display:grid;gap:var(--admin-space-lg)}
34
+ .workstation-row{display:grid;gap:var(--admin-space-lg);width:100%;text-align:left;text-decoration:none;min-height:var(--admin-control-height);padding:var(--admin-card-padding);border:1px solid var(--admin-row-border);border-radius:var(--admin-card-radius);background:var(--admin-row);color:var(--admin-text);font-weight:400}
35
+ .workstation-row:hover{background:var(--admin-accent-surface);color:var(--admin-text)}
36
+ .workstation-row:focus-visible{outline:2px solid var(--admin-accent);outline-offset:2px}
37
+ .workstation-row-heading{display:flex;align-items:center;justify-content:space-between;gap:var(--admin-space)}
38
+ .workstation-row-heading strong{min-width:0;overflow-wrap:anywhere;font-size:var(--admin-title)}
39
+ .workstation-state{display:inline-flex;flex:none;align-items:center;padding:var(--admin-space-sm) var(--admin-space);border-radius:var(--admin-card-radius);background:var(--admin-accent-surface);color:var(--admin-accent);font-size:var(--admin-label);font-weight:700}
40
+ .workstation-state.offline{background:var(--admin-row-border);color:var(--admin-muted)}
41
+ .workstation-key-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr) minmax(0,2fr) minmax(0,1fr);gap:var(--admin-space-lg);margin:0}
42
+ .workstation-key{min-width:0}.workstation-key dt{color:var(--admin-muted);font-size:var(--admin-label);margin-bottom:var(--admin-space-sm)}
43
+ .workstation-key dd{margin:0;font-size:var(--admin-value);font-weight:600;overflow-wrap:anywhere;color:var(--admin-text)}
44
+ .workstation-key dd.working{color:var(--admin-accent)}
45
+ .workstation-account-note{display:block;font-size:var(--admin-label);font-weight:400;color:var(--admin-muted);margin-top:var(--admin-space-sm)}
46
+ .workstation-row-footer{display:flex;align-items:center;justify-content:space-between;gap:var(--admin-space)}
47
+ .workstation-more{flex:none;color:var(--admin-accent);font-size:var(--admin-label)}
48
+ .workstation-overview{display:grid;gap:var(--admin-space-lg);padding:var(--admin-card-padding);background:var(--admin-row);border:1px solid var(--admin-row-border);border-radius:var(--admin-card-radius)}
49
+ .workstation-disclosure{min-width:0;border:1px solid var(--admin-border);border-radius:var(--admin-control-radius);background:var(--admin-surface)}
50
+ .workstation-disclosure>summary{cursor:pointer;padding:var(--admin-space);font-weight:600;min-height:var(--admin-control-height);color:var(--admin-text)}
51
+ .workstation-disclosure>summary:focus-visible{outline:2px solid var(--admin-accent);outline-offset:2px}
52
+ .workstation-disclosure-content{display:grid;gap:var(--admin-space);padding:0 var(--admin-space) var(--admin-space)}
53
+ .workstation-phone{display:grid;gap:var(--admin-space);padding:var(--admin-space);background:var(--admin-row);border-radius:var(--admin-control-radius)}
54
+ .workstation-block{display:grid;gap:var(--admin-space);min-width:0;padding:var(--admin-space);border:1px solid var(--admin-border);border-radius:var(--admin-control-radius)}
55
+ .workstation-fields{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--admin-space);margin:0}
56
+ .workstation-fields>div{min-width:0}.workstation-fields dd{margin:0;overflow-wrap:anywhere;font-variant-numeric:tabular-nums}
57
+ #workstationBack[hidden]{display:none}
58
+ @media(max-width:600px){.workstation-fields{grid-template-columns:minmax(0,1fr)}.workstation-row,.workstation-overview{padding:var(--admin-space)}.workstation-key-grid{grid-template-columns:repeat(2,minmax(0,1fr))}.workstation-key-account{grid-column:1/-1;order:3}.workstation-row-heading{align-items:start}}`;
@@ -0,0 +1,95 @@
1
+ export const adminWorkstationsMarkup = `
2
+ <section id="workstations" class="page stack" hidden>
3
+ <section class="card">
4
+ <div class="usage-toolbar"><div><h2 id="workstationHeading">工作站</h2><p id="workstationCount" class="hint">正在读取</p></div>
5
+ <div class="actions"><button id="workstationBack" class="secondary" type="button" hidden>返回列表</button><button id="workstationRefresh" class="secondary" type="button">刷新</button></div></div>
6
+ <div id="workstationContent" class="workstation-content"></div><p id="workstationError" class="status error" role="alert"></p>
7
+ </section>
8
+ </section>`;
9
+
10
+ export const adminWorkstationsScript = String.raw`
11
+ let workstationId=null,workstationController=null,workstationGeneration=0,workstationRendered='';
12
+ const workstationDisclosures=new Map();
13
+ const workstationRouteNames={management:'管理连接',pending:'连接方式待确认',direct:'中继直连',relay:'中继转发',lan:'局域网','self-relay':'Code Relax 中继'};
14
+ function workstationTime(value){return value?new Date(value).toLocaleString('zh-CN',{timeZone:'Asia/Shanghai',year:'numeric',month:'2-digit',day:'2-digit',hour:'2-digit',minute:'2-digit',second:'2-digit',hour12:false}):'未记录'}
15
+ function workstationFields(values){const list=node('dl','workstation-fields');for(const [label,value] of values){const row=node('div');row.append(node('dt','hint',label),node('dd','',value==null||value===''?'未提供':String(value)));list.append(row)}return list}
16
+ function workstationBlock(title){const block=node('section','workstation-block');block.append(node('h3','',title));return block}
17
+ function workstationAccount(accounts,missing='未上报'){return accounts.length?accounts.map(account=>account.email||account.id).join('、'):missing}
18
+ function workstationAccountView(item){return item.accounts.length?{value:workstationAccount(item.accounts),note:'当前认证'}:item.associatedAccounts.length?{value:workstationAccount(item.associatedAccounts),note:'最近确认'}:{value:'未上报',note:''}}
19
+ function workstationAssociated(accounts){return accounts.length?accounts.map(account=>account.email+(account.lastVerifiedAt?'('+workstationTime(account.lastVerifiedAt)+' 确认)':'')).join('、'):'未上报'}
20
+ function workstationStatus(online){return node('span','workstation-state'+(online?'':' offline'),online?'在线':'离线')}
21
+ function workstationLastRoute(item){return workstationRouteNames[item.lastConnection?.mode]||'未记录'}
22
+ function workstationConnectionState(item){return {connected:'已连接',disconnected:'已断开',unconfirmed:'未确认'}[item.connectionState]||'未确认'}
23
+ function workstationWork(item,online=item.online){return online?(item.activeTasks?'工作中 · '+item.activeTasks+' 项':'未确认'):'—'}
24
+ function workstationHighlights(item,online=item.online){
25
+ const list=node('dl','workstation-key-grid');const account=workstationAccountView(item);
26
+ for(const [key,label,value,note] of [['state','手机连接状态',workstationConnectionState(item),''],['connection','上次连接方式',workstationLastRoute(item),''],['account','手机账号',account.value,account.note],['work','工作状态',workstationWork(item,online),'']]){
27
+ const field=node('div','workstation-key workstation-key-'+key);field.append(node('dt','',label));const result=node('dd','',value);
28
+ if(note)result.append(node('small','workstation-account-note',note));if(key==='work'&&online&&item.activeTasks)result.classList.add('working');field.append(result);list.append(field)
29
+ }return list
30
+ }
31
+ function workstationDisclosure(item,key,title){const details=node('details','workstation-disclosure');const identity=item.id+':'+key;details.open=workstationDisclosures.get(identity)===true;details.append(node('summary','',title));details.addEventListener('toggle',()=>{if(details.isConnected)workstationDisclosures.set(identity,details.open)});return details}
32
+ function openWorkstation(id){history.pushState({workstationDetail:true},'','#workstations/'+encodeURIComponent(id));showPage('workstations/'+encodeURIComponent(id))}
33
+ function cancelWorkstations(){workstationGeneration++;workstationController?.abort();workstationController=null;workstationRendered=''}
34
+ function workstationCaption(result){if(result.workstation){const item=result.workstation;return (item.online?'在线':'离线')+' · 更新 '+workstationTime(result.sampledAt)}const online=result.workstations.filter(item=>item.online).length;return online+' 台在线 · '+(result.workstations.length-online)+' 台离线 · 按上线时间从新到旧'}
35
+ function renderWorkstationList(result){
36
+ const list=el('workstationContent');list.replaceChildren();el('workstationCount').textContent=workstationCaption(result);
37
+ if(!result.workstations.length){list.append(node('p','empty-note','暂无工作站'));return}
38
+ for(const item of result.workstations){
39
+ const row=node('a','workstation-row');row.href='#workstations/'+encodeURIComponent(item.id);row.addEventListener('click',event=>{if(event.button!==0||event.ctrlKey||event.metaKey||event.shiftKey||event.altKey)return;event.preventDefault();openWorkstation(item.id)});const heading=node('span','workstation-row-heading');heading.append(node('strong','',item.name),workstationStatus(item.online));
40
+ const footer=node('span','workstation-row-footer');footer.append(node('span','hint',(item.online?'上线时间 ':'最近上线 ')+workstationTime(item.onlineAt)),node('span','workstation-more','查看 ›'));
41
+ row.append(heading,workstationHighlights(item),footer);list.append(row)
42
+ }
43
+ }
44
+ function renderWorkstationDetail(result){
45
+ const item=result.workstation;const content=el('workstationContent');content.replaceChildren();el('workstationHeading').textContent=item.name;el('workstationCount').textContent=workstationCaption(result);
46
+ const overview=node('section','workstation-overview');const heading=node('div','workstation-row-heading');heading.append(workstationStatus(item.online),node('span','hint',(item.online?'上线时间 ':'最近上线 ')+workstationTime(item.onlineAt)));
47
+ overview.append(heading,workstationHighlights(item),node('p','hint','聊天连接 '+item.chatPhones+' 台手机 · 已配对 '+item.pairedPhones+' 台'));content.append(overview);
48
+ const phones=workstationDisclosure(item,'phones','手机与账号 · '+item.pairedPhones+' 台');const phoneList=node('div','workstation-disclosure-content');
49
+ if(!item.phones.length)phoneList.append(node('p','hint','尚无配对手机'));
50
+ for(const phone of item.phones){
51
+ const card=node('article','workstation-phone');const title=node('div','workstation-row-heading');const platform={android:'Android',harmony:'HarmonyOS',ios:'iOS'}[phone.platform]||'';
52
+ title.append(node('strong','',phone.deviceName||platform||'手机'),node('span','hint',workstationConnectionState(phone)));
53
+ const account=workstationAccountView(phone);card.append(title,workstationFields([['上次连接方式',workstationLastRoute(phone)],['手机账号',account.value+(account.note?' · '+account.note:'')]]));phoneList.append(card)
54
+ }phones.append(phoneList);content.append(phones);
55
+ const diagnostics=workstationDisclosure(item,'diagnostics','诊断详情');const body=node('div','workstation-disclosure-content');
56
+ const station=workstationBlock('工作站记录');station.append(workstationFields([
57
+ ['工作站 ID',item.id],['上线时间',workstationTime(item.onlineAt)],['来源 IP',item.connection?.address],['登记时间',workstationTime(item.registeredAt)],['授权更新时间',workstationTime(item.updatedAt)],
58
+ ['手机关联账号',workstationAssociated(item.associatedAccounts)],['当前认证账号',workstationAccount(item.accounts,'未确认')],['任务账号',workstationAccount(item.taskAccounts,'未记录')],
59
+ ['元数据连接',item.metadataPhones+' 台手机'],['调试白名单',item.debugEnabled?'已启用':'未启用'],['文件接收通道',item.fileReceiverOnline?'在线':'未连接']
60
+ ]));body.append(station);
61
+ const connectionEvents=workstationBlock('手机连接记录 · 工作站上报');
62
+ connectionEvents.append(node('p','hint',item.connectionReportingCurrent?'已收到当前工作站连接状态':'当前上报未确认;不据此推断手机断开'));
63
+ for(const event of item.connectionEvents||[]){const phone=item.phones.find(value=>value.id===event.clientId);connectionEvents.append(workstationFields([
64
+ ['时间',workstationTime(event.at)],['事件',event.state==='connected'?'手机已连接':'手机已断开'],['手机',phone?.deviceName||event.clientId],['连接方式',workstationRouteNames[event.mode]||'未确认']
65
+ ]))}
66
+ if(!item.connectionEvents?.length)connectionEvents.append(node('p','hint','暂无连接 / 断开记录'));body.append(connectionEvents);
67
+ const networks=workstationBlock('网络与 OpenAI 环境');
68
+ for(const network of item.lanCandidates)networks.append(workstationFields([['局域网地址',network.address],['网络',network.networkType==='wifi'?'Wi-Fi':'以太网'],['网络名称',network.networkName],['网卡',network.interfaceName]]));
69
+ if(item.officialComputer){const official=item.officialComputer;networks.append(workstationFields([['OpenAI 环境 ID',official.environmentId],['环境名称',official.name],['主机名',official.hostname],['登记时间',workstationTime(official.updatedAt)]]))}
70
+ if(!item.lanCandidates.length&&!item.officialComputer)networks.append(node('p','hint','尚未上报网络资料'));body.append(networks);
71
+ for(const phone of item.phones){
72
+ const card=workstationBlock(phone.deviceName||'手机连接记录');card.append(workstationFields([
73
+ ['手机 ID',phone.id],['平台',phone.platform],['关联账号',workstationAssociated(phone.associatedAccounts)],['当前认证账号',workstationAccount(phone.accounts,'未确认')],['任务账号',workstationAccount(phone.taskAccounts,'未记录')],
74
+ ['元数据连接',phone.metadata?'已连接':'未连接'],['设备管理连接',phone.managers.length+' 个'],['配对时间',workstationTime(phone.pairedAt)],['最近鉴权',workstationTime(phone.lastConnectedAt)],['最近局域网上报',workstationTime(phone.lastLanConnectedAt)],['上次连接时间',workstationTime(phone.lastConnection?.at)]
75
+ ]));
76
+ const channels=[...(phone.chat?[['聊天 / 管理',phone.chat]]:[]),...(phone.metadata?[['元数据',phone.metadata]]:[]),...phone.managers.map(channel=>['设备管理',channel]),...phone.transfers.map(channel=>[channel.purpose==='upload'?'文件上传':'文件下载',channel])];
77
+ for(const [name,channel] of channels)card.append(workstationFields([['通道',name],['认证账号',channel.account?.email||'未上报'],['连接时间',workstationTime(channel.connectedAt)],['来源 IP',channel.address]]));
78
+ if(phone.chat)card.append(workstationFields([['转发容量',phone.chat.relayAdmitted?(phone.chat.capacityExempt?'白名单豁免':'占用名额'):'未占用'],['待发送队列',phone.chat.queuedBytes+' 字节']]));body.append(card)
79
+ }
80
+ if(item.tasks.length){const tasks=workstationBlock('任务记录');for(const task of item.tasks)tasks.append(workstationFields([['线程 / 轮次',task.key],['手机 ID',task.clientId],['任务账号',task.account?.email||task.userId]]));body.append(tasks)}
81
+ const notes=workstationBlock('状态说明');notes.append(node('p','hint','在线表示工作站已连接云端中继,不代表内核已就绪。手机连接状态与上次连接方式独立:方式保留最近一次工作站确认的局域网 / Code Relax 中继,断开、工作站离线或云端重启不清空;未记录不推测。未确认表示云端没有足够的当前状态,不能据此判断手机未登录或工作站空闲。'),node('p','hint','局域网 / Code Relax 中继的连接、断开由新版工作站上报;健康探测、管理和文件通道不计入。工作站上报链路丢失不记作手机断开,OpenAI 中继暂未提供可靠的手机连接事件。'),node('p','hint','手机账号标为“最近确认”时来自既有验证记录,不代表当前登录;具体时间见关联账号记录。时间按北京时间显示,每 5 秒更新。'));
82
+ body.append(notes);diagnostics.append(body);content.append(diagnostics);
83
+ }
84
+ async function loadWorkstations(){
85
+ if(el('workstations').hidden||workstationController)return;const generation=workstationGeneration;const controller=workstationController=new AbortController();el('workstationRefresh').disabled=true;
86
+ try{
87
+ const result=await request('/admin/api/workstations'+(workstationId?'/'+encodeURIComponent(workstationId):''),{signal:controller.signal});if(generation!==workstationGeneration||el('workstations').hidden)return;
88
+ el('workstationError').textContent='';const signature=JSON.stringify(result.workstation||result.workstations);
89
+ if(signature!==workstationRendered){if(workstationId)renderWorkstationDetail(result);else renderWorkstationList(result);workstationRendered=signature}else el('workstationCount').textContent=workstationCaption(result)
90
+ }catch(error){if(generation!==workstationGeneration||controller.signal.aborted)return;workstationRendered='';el('workstationCount').textContent='读取失败,当前状态未确认';el('workstationContent').replaceChildren();el('workstationError').textContent=error.message}
91
+ finally{if(workstationController===controller){workstationController=null;el('workstationRefresh').disabled=false}}
92
+ }
93
+ el('workstationRefresh').addEventListener('click',()=>loadWorkstations());
94
+ el('workstationBack').addEventListener('click',()=>{if(history.state?.workstationDetail)history.back();else navigatePage('workstations')});
95
+ `;
@@ -0,0 +1,143 @@
1
+ // Explicit projections: authorization hashes, credentials, socket objects and payloads
2
+ // must never become part of the management API.
3
+ const open = entry => entry?.ws?.readyState === 1;
4
+ const socket = ws => ({ connectedAt: ws.adminInfo?.connectedAt || null,
5
+ address: ws.adminInfo?.address || null, account: ws.adminInfo?.account
6
+ ? { id: ws.adminInfo.account.id, email: ws.adminInfo.account.email } : null });
7
+
8
+ export function workstationDetail(room, debugEnabled = false) {
9
+ const online = room.host?.readyState === 1;
10
+ const connectionReportingCurrent = online && room.adminPhoneConnections !== undefined;
11
+ const tasks = online ? [...(room.usageTasks?.entries() || [])] : [];
12
+ const phones = room.clients.map(client => {
13
+ const connection = room.connections.get(client.id);
14
+ const chat = online && open(connection) ? connection : null;
15
+ const observer = room.observers?.get(client.id);
16
+ const metadata = open(observer) ? socket(observer.ws) : null;
17
+ const managers = [...(room.deviceManagers?.entries() || [])]
18
+ .filter(([ws, id]) => id === client.id && ws.readyState === 1).map(([ws]) => socket(ws));
19
+ const transfers = online ? [...(room.uploadClients?.values() || [])]
20
+ .filter(entry => entry.clientId === client.id && open(entry))
21
+ .map(entry => ({ purpose: entry.purpose, ...socket(entry.ws) })) : [];
22
+ const activeTasks = tasks.filter(([, task]) => task.clientId === client.id).length;
23
+ const reportedConnections = online ? [...(room.adminPhoneConnections?.values() || [])]
24
+ .filter(item => item.clientId === client.id).map(item => ({ connectionId: item.connectionId, mode: item.mode })) : [];
25
+ const connected = reportedConnections.length > 0 || Boolean(chat?.userId);
26
+ const channels = [chat && socket(chat.ws), metadata, ...managers, ...transfers].filter(Boolean);
27
+ const accounts = [...new Map(channels.filter(item => item.account)
28
+ .map(item => [item.account.id, item.account])).values()];
29
+ const taskAccounts = [...new Set(tasks.filter(([, task]) => task.clientId === client.id)
30
+ .map(([, task]) => task.userId).filter(Boolean))].map(id => accounts.find(account => account.id === id) || { id, email: null });
31
+ return {
32
+ id: client.id, deviceName: client.deviceName || null, platform: client.platform || null,
33
+ pairedAt: client.createdAt || null, lastConnectedAt: client.lastConnectedAt || null,
34
+ connected, connectionState: connected ? 'connected' : connectionReportingCurrent ? 'disconnected' : 'unconfirmed',
35
+ lastConnection: null, reportedConnections,
36
+ accounts, taskAccounts, associatedAccounts: [], metadata, managers, transfers, activeTasks,
37
+ chat: chat ? { ...socket(chat.ws), route: chat.userId ? chat.adminRoute || 'pending' : 'management',
38
+ capacityExempt: Boolean(chat.capacityExempt), relayAdmitted: Boolean(chat.relayAdmitted || chat.relayExempt),
39
+ queuedBytes: chat.queuedBytes || 0 } : null,
40
+ lastLanConnectedAt: room.adminLanConnections?.get(client.id) || null,
41
+ };
42
+ }).sort((a, b) => Number(b.connected) - Number(a.connected) ||
43
+ (b.lastConnectedAt || '').localeCompare(a.lastConnectedAt || '') || a.id.localeCompare(b.id));
44
+ const accounts = [...new Map(phones.flatMap(phone => phone.accounts).map(account => [account.id, account])).values()];
45
+ const taskAccounts = [...new Set(tasks.map(([, task]) => task.userId).filter(Boolean))]
46
+ .map(id => accounts.find(account => account.id === id) || { id, email: null });
47
+ return {
48
+ id: room.id, name: room.hostName || room.adminLastHostName || room.officialComputer?.hostname || '工作站 …' + room.id.slice(-8),
49
+ online, registeredAt: room.createdAt || null, updatedAt: room.updatedAt || null,
50
+ onlineAt: (online ? room.host.adminInfo?.connectedAt : room.adminLastOnlineAt) || null,
51
+ connection: online ? socket(room.host) : null,
52
+ pairedPhones: phones.length, connectedPhones: phones.filter(phone => phone.connected).length,
53
+ chatPhones: phones.filter(phone => phone.reportedConnections.length || phone.chat && phone.chat.route !== 'management').length,
54
+ connectionReportingCurrent,
55
+ connectionState: phones.some(phone => phone.connected) ? 'connected' : connectionReportingCurrent ? 'disconnected' : 'unconfirmed',
56
+ lastConnection: null,
57
+ metadataPhones: phones.filter(phone => phone.metadata).length,
58
+ activeTasks: tasks.length, accounts, taskAccounts, associatedAccounts: [], debugEnabled,
59
+ fileReceiverOnline: online && room.uploadHost?.readyState === 1,
60
+ lanCandidates: online ? (room.lanCandidates || []).map(item => ({ address: item.address,
61
+ networkType: item.networkType, networkName: item.networkName, interfaceName: item.interfaceName })) : [],
62
+ officialComputer: room.officialComputer ? { environmentId: room.officialComputer.environmentId,
63
+ name: room.officialComputer.name, hostname: room.officialComputer.hostname,
64
+ updatedAt: room.officialComputer.updatedAt } : null,
65
+ tasks: tasks.map(([key, task]) => ({ key, clientId: task.clientId, userId: task.userId,
66
+ account: taskAccounts.find(account => account.id === task.userId) || null })), phones,
67
+ };
68
+ }
69
+
70
+ // Previous connection mode is durable history; it never establishes current presence.
71
+ export async function resolveWorkstationConnections(workstations, events) {
72
+ const paired = new Map(workstations.map(item => [item.id, new Map(item.phones.map(phone => [phone.id, phone]))]));
73
+ for (const record of await events.latest(workstations.map(item => item.id))) {
74
+ const phone = paired.get(record.computerId)?.get(record.clientId);
75
+ if (phone) phone.lastConnection = { mode: record.mode, at: record.at };
76
+ }
77
+ for (const item of workstations) {
78
+ const last = item.phones.filter(phone => phone.lastConnection)
79
+ .sort((a, b) => b.lastConnection.at.localeCompare(a.lastConnection.at) || a.id.localeCompare(b.id))[0];
80
+ item.lastConnection = last ? { ...last.lastConnection, clientId: last.id } : null;
81
+ }
82
+ return workstations;
83
+ }
84
+
85
+ // Account association belongs to a workstation/mobile identity pair. A missing
86
+ // signaling socket says nothing about whether that phone has a login session.
87
+ // Read existing verified usage attribution without rewriting any history.
88
+ export async function resolveWorkstationAccounts(workstations, pool) {
89
+ const paired = new Map(workstations.map(item => [item.id, new Map(item.phones.map(phone => [phone.id, phone]))]));
90
+ if (pool && workstations.length) {
91
+ const [rows] = await pool.execute(`SELECT computer_id,client_id,user_id,MAX(occurred_at) AS last_verified_at
92
+ FROM relay_usage_actions WHERE computer_id IN (${workstations.map(() => '?').join(',')})
93
+ GROUP BY computer_id,client_id,user_id`, workstations.map(item => item.id));
94
+ for (const row of rows) {
95
+ const phone = paired.get(row.computer_id)?.get(row.client_id);
96
+ if (phone) phone.associatedAccounts.push({ id: row.user_id, email: null,
97
+ lastVerifiedAt: row.last_verified_at.replace(' ', 'T') + 'Z' });
98
+ }
99
+ }
100
+ const references = workstations.flatMap(item => [...item.taskAccounts,
101
+ ...item.phones.flatMap(phone => [...phone.taskAccounts, ...phone.associatedAccounts])]);
102
+ const missing = [...new Set(references.filter(account => !account.email).map(account => account.id))];
103
+ if (pool && missing.length) {
104
+ const [rows] = await pool.execute(`SELECT i.user_id,i.normalized_value AS email FROM user_login_identities i
105
+ JOIN users u ON u.id=i.user_id AND u.status='active'
106
+ WHERE i.kind='email' AND i.user_id IN (${missing.map(() => '?').join(',')})`, missing);
107
+ const emails = new Map(rows.map(row => [row.user_id, row.email]));
108
+ for (const account of references) if (!account.email) account.email = emails.get(account.id) || null;
109
+ }
110
+ for (const item of workstations) {
111
+ for (const phone of item.phones) {
112
+ const known = new Map(phone.associatedAccounts.filter(account => account.email)
113
+ .sort((a, b) => b.lastVerifiedAt.localeCompare(a.lastVerifiedAt)).map(account => [account.id, account]));
114
+ for (const account of [...phone.taskAccounts, ...phone.accounts]) if (account.email) {
115
+ known.set(account.id, { ...account, lastVerifiedAt: known.get(account.id)?.lastVerifiedAt || null });
116
+ }
117
+ phone.associatedAccounts = [...known.values()];
118
+ }
119
+ const known = new Map();
120
+ for (const phone of item.phones) for (const account of phone.associatedAccounts) {
121
+ if (!known.has(account.id) || (account.lastVerifiedAt || '') > (known.get(account.id).lastVerifiedAt || '')) known.set(account.id, account);
122
+ }
123
+ item.associatedAccounts = [...known.values()];
124
+ }
125
+ return workstations;
126
+ }
127
+
128
+ export function workstationSummary(item) {
129
+ const { phones, tasks, lanCandidates, officialComputer, fileReceiverOnline, debugEnabled, ...summary } = item;
130
+ return { ...summary, routes: workstationRoutes(phones) };
131
+ }
132
+
133
+ function workstationRoutes(phones) {
134
+ return [...new Set(phones.flatMap(phone => [...(phone.chat ? [phone.chat.route] : []),
135
+ ...phone.reportedConnections.filter(item => item.mode === 'lan' || !phone.chat).map(item => item.mode)]))];
136
+ }
137
+
138
+ export function listWorkstations(rooms, { details = false } = {}) {
139
+ const items = [...rooms.values()].filter(room => room.status === 'active').map(room => workstationDetail(room))
140
+ .sort((a, b) => Number(b.online) - Number(a.online) || (b.onlineAt || '').localeCompare(a.onlineAt || '') ||
141
+ a.name.localeCompare(b.name, 'zh-CN') || a.id.localeCompare(b.id));
142
+ return details ? items : items.map(workstationSummary);
143
+ }
@@ -0,0 +1,61 @@
1
+ import fs from 'node:fs';
2
+
3
+ const prefix = '/code-relax/android/';
4
+ const webOrigin = 'https://www.coderelax.cn';
5
+
6
+ export function readAndroidCatalog(file) {
7
+ const data = JSON.parse(fs.readFileSync(file, 'utf8'));
8
+ if (!Array.isArray(data.releases) || !data.releases.length) throw new Error('No Android releases');
9
+ const versions = new Set();
10
+ for (const item of data.releases) {
11
+ if (!Number.isSafeInteger(item.versionCode) || item.versionCode < 1 || item.versionCode > 2100000000
12
+ || versions.has(item.versionCode) || typeof item.versionName !== 'string' || !/^\d+\.\d+\.\d+\.\d+$/.test(item.versionName)
13
+ || !item.versionName.endsWith('.' + item.versionCode)
14
+ || !Number.isSafeInteger(item.size) || item.size <= 0 || !/^[a-f0-9]{64}$/.test(item.sha256)
15
+ || typeof item.objectKey !== 'string' || !/^code-relax\/android\/\d+\/[A-Za-z0-9._-]+\.apk$/.test(item.objectKey)
16
+ || typeof item.notes !== 'string' || item.notes.length > 10000) throw new Error('Invalid Android release catalog');
17
+ versions.add(item.versionCode);
18
+ }
19
+ if (!versions.has(data.latestVersionCode)) throw new Error('Latest Android release is missing');
20
+ return data;
21
+ }
22
+
23
+ export function createAndroidReleaseHandler({ catalogFile, signDownload, log = () => {} }) {
24
+ return async function handle(request, response, target) {
25
+ if (!target.pathname.startsWith(prefix)) return false;
26
+ const headers = { 'Cache-Control': 'no-store', 'Content-Type': 'application/json; charset=utf-8',
27
+ 'X-Content-Type-Options': 'nosniff', 'Referrer-Policy': 'no-referrer',
28
+ 'Access-Control-Allow-Origin': webOrigin, Vary: 'Origin' };
29
+ const reply = (code, data) => { response.writeHead(code, headers); response.end(JSON.stringify(data)); };
30
+ if (request.method !== 'GET') { reply(405, { error: 'Method not allowed' }); return true; }
31
+ if (![prefix + 'latest.json', prefix + 'download'].includes(target.pathname)) {
32
+ reply(404, { error: 'Not found' }); return true;
33
+ }
34
+ try {
35
+ if (!catalogFile || !signDownload) { reply(503, { error: 'Android release is not available' }); return true; }
36
+ const catalog = readAndroidCatalog(catalogFile);
37
+ const requested = target.searchParams.get('versionCode');
38
+ if (requested !== null && !/^[1-9]\d{0,9}$/.test(requested)) { reply(400, { error: 'Invalid version' }); return true; }
39
+ const code = target.pathname.endsWith('/latest.json') || requested === null ? catalog.latestVersionCode : Number(requested);
40
+ const release = catalog.releases.find(item => item.versionCode === code);
41
+ if (!release) { reply(404, { error: 'Release unavailable; check for updates again' }); return true; }
42
+ const { versionCode, versionName, size, sha256, notes } = release;
43
+ if (target.pathname.endsWith('/latest.json')) {
44
+ reply(200, { versionCode, versionName, size, sha256, notes }); return true;
45
+ }
46
+ // Sign only an explicitly published object, never a caller-supplied key or URL.
47
+ const ticket = await signDownload(release);
48
+ if (!ticket || new URL(ticket.url).protocol !== 'https:' || !Number.isSafeInteger(ticket.expiresAt) || ticket.expiresAt <= Date.now()) {
49
+ throw new Error('Invalid download ticket');
50
+ }
51
+ if (target.searchParams.get('redirect') === '1') {
52
+ response.writeHead(302, { ...headers, Location: ticket.url }); response.end();
53
+ } else reply(200, { versionCode, url: ticket.url, expiresAt: ticket.expiresAt });
54
+ } catch (error) {
55
+ // Provider errors may contain signed URLs or credentials. Never return or log them.
56
+ log({ event: 'android-release-error', type: error?.code === 'ENOENT' ? 'not-published' : 'configuration-or-storage' });
57
+ reply(503, { error: 'Android release is temporarily unavailable' });
58
+ }
59
+ return true;
60
+ };
61
+ }
@@ -1,26 +1,26 @@
1
- import { EventEmitter } from 'node:events';
2
- import WebSocket from 'ws';
3
- import { decode, relayAddress, send } from './wire.mjs';
4
-
5
- // Headless mobile-side adapter for the local validation. No OpenAI credentials.
6
- export function connectRelayClient({ relayUrl, room, code, credential, clientId, observe = false }) {
7
- relayAddress(relayUrl);
8
- const events = new EventEmitter(), pending = new Map();
1
+ import { EventEmitter } from 'node:events';
2
+ import WebSocket from 'ws';
3
+ import { decode, relayAddress, send } from './wire.mjs';
4
+
5
+ // Headless mobile-side adapter for the local validation. No OpenAI credentials.
6
+ export function connectRelayClient({ relayUrl, room, code, credential, clientId, accountToken, observe = false }) {
7
+ relayAddress(relayUrl);
8
+ const events = new EventEmitter(), pending = new Map();
9
9
  const socket = new WebSocket(relayUrl, { maxPayload: 64 * 1024 * 1024, perMessageDeflate: true });
10
10
  let serial = 0, connected = false, pairedCredential = credential, pairedClientId = clientId;
11
- const ready = new Promise((resolve, reject) => {
12
- const timer = setTimeout(() => { reject(new Error('Relay connection timeout')); socket.terminate(); }, 7000);
13
- socket.on('open', () => send(socket, observe ? { type: 'observe', room, credential, clientId }
14
- : code ? { type: 'pair', room, code, credential, clientId } : { type: 'resume', room, credential, clientId }));
15
- socket.on('error', error => { reject(error); events.emit('diagnostic', error.message); });
16
- socket.on('close', () => {
17
- clearTimeout(timer); connected = false; reject(new Error('Relay connection closed'));
18
- for (const request of pending.values()) { clearTimeout(request.timer); request.reject(new Error('连接断开,操作结果未确认,不自动重发')); }
19
- pending.clear(); events.emit('disconnected');
20
- });
21
- socket.on('message', (bytes, binary) => {
22
- try {
23
- const message = decode(bytes, binary);
11
+ const ready = new Promise((resolve, reject) => {
12
+ const timer = setTimeout(() => { reject(new Error('Relay connection timeout')); socket.terminate(); }, 7000);
13
+ socket.on('open', () => send(socket, observe ? { type: 'observe', room, credential, clientId, accountToken }
14
+ : code ? { type: 'pair', room, code, credential, clientId, accountToken } : { type: 'resume', room, credential, clientId, accountToken }));
15
+ socket.on('error', error => { reject(error); events.emit('diagnostic', error.message); });
16
+ socket.on('close', () => {
17
+ clearTimeout(timer); connected = false; reject(new Error('Relay connection closed'));
18
+ for (const request of pending.values()) { clearTimeout(request.timer); request.reject(new Error('连接断开,操作结果未确认,不自动重发')); }
19
+ pending.clear(); events.emit('disconnected');
20
+ });
21
+ socket.on('message', (bytes, binary) => {
22
+ try {
23
+ const message = decode(bytes, binary);
24
24
  if (message.type === 'paired') { if (message.credential) pairedCredential = message.credential; if (message.clientId) pairedClientId = message.clientId; }
25
25
  else if (message.type === 'observing') { clearTimeout(timer); connected = true; events.emit('observing', message); resolve({ room, credential: pairedCredential, clientId: pairedClientId }); }
26
26
  else if (message.type === 'computer-info') events.emit('computer-info', { hostName: message.hostName });
@@ -29,33 +29,33 @@ export function connectRelayClient({ relayUrl, room, code, credential, clientId,
29
29
  else if (message.type === 'official-computer-saved') events.emit('official-computer-saved', message.computer);
30
30
  else if (message.type === 'announcement') events.emit('announcement', message.announcement);
31
31
  else if (message.type === 'ready') { clearTimeout(timer); connected = true; resolve({ room, credential: pairedCredential, clientId: pairedClientId }); }
32
- else if (message.type === 'data') {
33
- const body = decode(message.payload, false), request = pending.get(body.id);
34
- if (body.type === 'response' && request) { clearTimeout(request.timer); pending.delete(body.id); request.resolve(body); }
35
- else events.emit('message', body);
36
- } else throw new Error('Invalid relay message');
37
- } catch (error) { reject(error); events.emit('diagnostic', error.message); socket.close(1008, 'Invalid response'); }
38
- });
39
- });
40
- return {
41
- ready, events,
42
- request(path, { method = 'GET', body, timeoutMs = 5000 } = {}) {
43
- if (!connected) return Promise.reject(new Error('Relay not ready'));
44
- const id = ++serial;
45
- return new Promise((resolve, reject) => {
46
- const timer = setTimeout(() => { pending.delete(id); reject(new Error('请求超时,结果未确认,不自动重发')); }, timeoutMs);
47
- pending.set(id, { resolve, reject, timer });
48
- if (!send(socket, { type: 'data', payload: JSON.stringify({ type: 'request', id, path, method, ...(body ? { body } : {}) }) })) {
49
- clearTimeout(timer); pending.delete(id); reject(new Error('Relay not connected'));
50
- }
51
- });
52
- },
32
+ else if (message.type === 'data') {
33
+ const body = decode(message.payload, false), request = pending.get(body.id);
34
+ if (body.type === 'response' && request) { clearTimeout(request.timer); pending.delete(body.id); request.resolve(body); }
35
+ else events.emit('message', body);
36
+ } else throw new Error('Invalid relay message');
37
+ } catch (error) { reject(error); events.emit('diagnostic', error.message); socket.close(1008, 'Invalid response'); }
38
+ });
39
+ });
40
+ return {
41
+ ready, events,
42
+ request(path, { method = 'GET', body, timeoutMs = 5000 } = {}) {
43
+ if (!connected) return Promise.reject(new Error('Relay not ready'));
44
+ const id = ++serial;
45
+ return new Promise((resolve, reject) => {
46
+ const timer = setTimeout(() => { pending.delete(id); reject(new Error('请求超时,结果未确认,不自动重发')); }, timeoutMs);
47
+ pending.set(id, { resolve, reject, timer });
48
+ if (!send(socket, { type: 'data', payload: JSON.stringify({ type: 'request', id, path, method, ...(body ? { body } : {}) }) })) {
49
+ clearTimeout(timer); pending.delete(id); reject(new Error('Relay not connected'));
50
+ }
51
+ });
52
+ },
53
53
  send(message) { if (!connected) throw new Error('Relay not ready'); return send(socket, { type: 'data', payload: JSON.stringify(message) }); },
54
54
  routeDirect() { if (!connected) throw new Error('Relay not ready'); return send(socket, { type: 'p2p-route', direct: 1 }); },
55
55
  recordOfficialComputer(computer) {
56
56
  if (!connected || !observe) throw new Error('Metadata channel not ready');
57
57
  return send(socket, { type: 'official-computer', ...computer });
58
58
  },
59
- close() { socket.terminate(); },
60
- };
61
- }
59
+ close() { socket.terminate(); },
60
+ };
61
+ }