@walkhi/code-relax 0.1.0-beta.4 → 0.1.0-beta.41

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 (845) hide show
  1. package/README.md +83 -71
  2. package/dist/bin/cleanup-accounts.mjs +63 -0
  3. package/dist/bin/codex-remote.mjs +323 -184
  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 +174 -0
  9. package/dist/bin/self-relay-admin.mjs +8 -0
  10. package/dist/bin/self-relay-demo.mjs +2 -2
  11. package/dist/bin/self-relay-server.mjs +43 -30
  12. package/dist/build-platform.json +1 -0
  13. package/dist/get-shared-service-url.ps1 +6 -6
  14. package/dist/shared/app-server-events.cjs +368 -238
  15. package/dist/shared/code-browser.cjs +159 -0
  16. package/dist/shared/file-changes.cjs +31 -0
  17. package/dist/shared/file-citations.cjs +117 -0
  18. package/dist/shared/file-mentions.cjs +92 -0
  19. package/dist/shared/message-delivery.cjs +100 -0
  20. package/dist/shared/p2p-data-channel.cjs +22 -0
  21. package/dist/shared/p2p-diagnostics.cjs +1 -1
  22. package/dist/shared/p2p-file-channel.cjs +87 -0
  23. package/dist/shared/p2p-ice-policy.cjs +22 -0
  24. package/dist/shared/plan-pricing.cjs +32 -0
  25. package/dist/shared/question-attention.cjs +69 -0
  26. package/dist/shared/server-requests.cjs +157 -5
  27. package/dist/shared/service-endpoints.cjs +21 -0
  28. package/dist/shared/timeline-sync.cjs +111 -5
  29. package/dist/skills/code-relax/SKILL.md +13 -8
  30. package/dist/src/archived-threads.mjs +22 -0
  31. package/dist/src/bounded-process-log.mjs +63 -0
  32. package/dist/src/celsius-client.mjs +107 -0
  33. package/dist/src/code-browser.mjs +100 -0
  34. package/dist/src/desktop-launcher.mjs +33 -38
  35. package/dist/src/dots-approval-timeline.mjs +99 -0
  36. package/dist/src/dots-avatar.mjs +42 -0
  37. package/dist/src/dots-chat-projection.mjs +50 -0
  38. package/dist/src/dots-chat-server.mjs +482 -0
  39. package/dist/src/dots-message-images.mjs +319 -0
  40. package/dist/src/dots-profile.mjs +77 -0
  41. package/dist/src/dots-room-activity.mjs +94 -0
  42. package/dist/src/dots-room-client.mjs +135 -0
  43. package/dist/src/dots-room-projection.mjs +94 -0
  44. package/dist/src/dots-schedules.mjs +66 -0
  45. package/dist/src/dots-summary-tasks.mjs +32 -0
  46. package/dist/src/dots-task-catalog.mjs +430 -0
  47. package/dist/src/dots-task-files.mjs +52 -0
  48. package/dist/src/file-transfer-range.mjs +22 -0
  49. package/dist/src/file-upload-session.mjs +130 -0
  50. package/dist/src/hosted-history-app-server.mjs +103 -0
  51. package/dist/src/hosted-history-cache.mjs +113 -0
  52. package/dist/src/lan-socket-server.mjs +241 -84
  53. package/dist/src/managed-app-server.mjs +54 -16
  54. package/dist/src/message-images.mjs +0 -18
  55. package/dist/src/message-upload-files.mjs +109 -0
  56. package/dist/src/onboarding.mjs +10 -29
  57. package/dist/src/plan-pricing.mjs +47 -0
  58. package/dist/src/platform/README.md +2 -2
  59. package/dist/src/platform/codex-protocol.mjs +46 -0
  60. package/dist/src/platform/codex-runtime.mjs +3 -0
  61. package/dist/src/platform/credential-store.mjs +3 -0
  62. package/dist/src/platform/desktop-host.mjs +3 -0
  63. package/dist/src/platform/desktop-project-registration.mjs +3 -0
  64. package/dist/src/platform/desktop-project-store.mjs +208 -0
  65. package/dist/src/platform/file-opener.mjs +9 -0
  66. package/dist/src/platform/linux/codex-runtime.mjs +56 -0
  67. package/dist/src/platform/linux/credential-store.mjs +28 -0
  68. package/dist/src/platform/linux/desktop-host.mjs +83 -0
  69. package/dist/src/platform/linux/desktop-installation.mjs +36 -0
  70. package/dist/src/platform/linux/desktop-project-registration.mjs +11 -0
  71. package/dist/src/platform/linux/network-info.mjs +11 -0
  72. package/dist/src/platform/linux/process.mjs +42 -0
  73. package/dist/src/platform/linux/project-locations.mjs +17 -0
  74. package/dist/src/platform/linux/resident-startup.mjs +52 -0
  75. package/dist/src/platform/linux/retained-runtime.mjs +76 -0
  76. package/dist/src/platform/linux/service-host.mjs +18 -0
  77. package/dist/src/platform/linux/system.mjs +49 -0
  78. package/dist/src/platform/linux/user-environment.mjs +7 -0
  79. package/dist/src/platform/macos/codex-runtime.mjs +125 -0
  80. package/dist/src/platform/macos/credential-store.mjs +10 -0
  81. package/dist/src/platform/macos/desktop-host.mjs +82 -0
  82. package/dist/src/platform/macos/desktop-project-registration.mjs +11 -0
  83. package/dist/src/platform/macos/network-info.mjs +8 -0
  84. package/dist/src/platform/macos/project-locations.mjs +8 -0
  85. package/dist/src/platform/macos/resident-startup.mjs +84 -0
  86. package/dist/src/platform/macos/retained-runtime.mjs +127 -0
  87. package/dist/src/platform/macos/service-host.mjs +18 -0
  88. package/dist/src/platform/macos/system.mjs +29 -0
  89. package/dist/src/platform/macos/user-environment.mjs +7 -0
  90. package/dist/src/platform/native-package.mjs +58 -0
  91. package/dist/src/platform/network-info.mjs +3 -0
  92. package/dist/src/platform/path-identity.mjs +5 -0
  93. package/dist/src/platform/posix/network-candidates.mjs +23 -0
  94. package/dist/src/platform/posix/runtime-paths.mjs +25 -0
  95. package/dist/src/platform/power-inhibitor.mjs +22 -0
  96. package/dist/src/platform/project-locations.mjs +3 -0
  97. package/dist/src/platform/runtime-paths.mjs +8 -0
  98. package/dist/src/platform/select.mjs +5 -0
  99. package/dist/src/platform/service-host.mjs +3 -0
  100. package/dist/src/platform/user-environment.mjs +3 -0
  101. package/dist/src/platform/windows/activate-desktop.ps1 +48 -0
  102. package/dist/src/platform/windows/codex-runtime.mjs +215 -0
  103. package/dist/src/platform/windows/credential-store.mjs +27 -27
  104. package/dist/src/platform/windows/credential-store.ps1 +49 -49
  105. package/dist/src/platform/windows/desktop-helper.mjs +179 -0
  106. package/dist/src/platform/windows/desktop-host.mjs +43 -23
  107. package/dist/src/platform/windows/desktop-info.ps1 +14 -16
  108. package/dist/src/platform/windows/desktop-project-registration.mjs +4 -0
  109. package/dist/src/platform/windows/desktop-runtime.ps1 +10 -0
  110. package/dist/src/platform/windows/desktop-shortcuts.ps1 +21 -28
  111. package/dist/src/platform/windows/dots-profile.mjs +49 -0
  112. package/dist/src/platform/windows/keep-awake.ps1 +20 -0
  113. package/dist/src/platform/windows/launch-worker.mjs +17 -18
  114. package/dist/src/platform/windows/project-locations.mjs +16 -0
  115. package/dist/src/platform/windows/resident-start.js +20 -0
  116. package/dist/src/platform/windows/resident-startup.ps1 +76 -20
  117. package/dist/src/platform/windows/rustdesk-video-probe.mjs +168 -0
  118. package/dist/src/platform/windows/service-host.mjs +24 -36
  119. package/dist/src/platform/windows/stop-desktop.ps1 +7 -4
  120. package/dist/src/platform/windows/user-environment.mjs +1 -1
  121. package/dist/src/project-create.mjs +121 -0
  122. package/dist/src/project-management.mjs +59 -0
  123. package/dist/src/project-remove.mjs +55 -0
  124. package/dist/src/project-update.mjs +59 -0
  125. package/dist/src/runtime-discovery.mjs +47 -0
  126. package/dist/src/self-relay/account-cleanup.mjs +30 -0
  127. package/dist/src/self-relay/account-connections.mjs +52 -0
  128. package/dist/src/self-relay/admin-cloud.mjs +101 -0
  129. package/dist/src/self-relay/admin-page.mjs +80 -0
  130. package/dist/src/self-relay/admin-server.mjs +74 -0
  131. package/dist/src/self-relay/admin-state.mjs +85 -19
  132. package/dist/src/self-relay/admin-style.mjs +14 -0
  133. package/dist/src/self-relay/android-releases.mjs +61 -0
  134. package/dist/src/self-relay/client.mjs +45 -45
  135. package/dist/src/self-relay/connector.mjs +421 -144
  136. package/dist/src/self-relay/demo.mjs +34 -35
  137. package/dist/src/self-relay/device-info.mjs +27 -0
  138. package/dist/src/self-relay/device-store.mjs +10 -2
  139. package/dist/src/self-relay/diagnostics.mjs +54 -0
  140. package/dist/src/self-relay/email-accounts.mjs +183 -0
  141. package/dist/src/self-relay/file-wire.mjs +13 -0
  142. package/dist/src/self-relay/lan-authorizations.mjs +44 -2
  143. package/dist/src/self-relay/lifecycle.mjs +250 -272
  144. package/dist/src/self-relay/long-pairing.mjs +40 -0
  145. package/dist/src/self-relay/mysql-state.mjs +118 -0
  146. package/dist/src/self-relay/p2p-probe.mjs +56 -11
  147. package/dist/src/self-relay/privacy-page.mjs +26 -0
  148. package/dist/src/self-relay/public-releases.mjs +52 -0
  149. package/dist/src/self-relay/rtc-file-bridge.mjs +41 -0
  150. package/dist/src/self-relay/server.mjs +652 -114
  151. package/dist/src/self-relay/usage-daily.mjs +55 -0
  152. package/dist/src/self-relay/usage-meter.mjs +141 -0
  153. package/dist/src/server.mjs +1519 -1793
  154. package/dist/src/service-control.mjs +17 -7
  155. package/dist/src/service-doctor.mjs +86 -33
  156. package/dist/src/service-health.mjs +2 -2
  157. package/dist/src/service-install.mjs +91 -85
  158. package/dist/src/service-lifecycle.mjs +117 -108
  159. package/dist/src/service-power.mjs +58 -0
  160. package/dist/src/service-restart.mjs +43 -10
  161. package/dist/src/service-update-worker.mjs +42 -0
  162. package/dist/src/service-update.mjs +71 -0
  163. package/dist/src/shared-app-server.mjs +561 -407
  164. package/dist/src/shared-catalog.mjs +95 -13
  165. package/dist/src/shared-recovery.mjs +15 -11
  166. package/dist/src/shared-thread-stream.mjs +147 -63
  167. package/dist/src/skill-install.mjs +0 -13
  168. package/dist/src/turn-model-history.mjs +47 -0
  169. package/dist/src/usage-reset.mjs +17 -0
  170. package/dist/src/workstation-downloads.mjs +120 -0
  171. package/package.json +35 -37
  172. package/tools/postinstall.mjs +86 -22
  173. package/dist/src/app-server-client.mjs +0 -468
  174. package/dist/src/app-server-tasks.mjs +0 -358
  175. package/dist/src/debug-ui.mjs +0 -131
  176. package/dist/src/platform/windows/desktop-monitor.mjs +0 -34
  177. package/dist/src/platform/windows/desktop-shortcut-run.ps1 +0 -5
  178. package/dist/src/platform/windows/desktop-tools.mjs +0 -48
  179. package/dist/src/thread-catalog.mjs +0 -47
  180. package/dist/tools/find-desktop-pipe.mjs +0 -10
  181. package/dist/web/activity-view.js +0 -283
  182. package/dist/web/approval-ui.js +0 -188
  183. package/dist/web/capabilities.js +0 -57
  184. package/dist/web/chat-transport.js +0 -202
  185. package/dist/web/chat.css +0 -782
  186. package/dist/web/chat.js +0 -3830
  187. package/dist/web/client-platform.js +0 -11
  188. package/dist/web/community-view.js +0 -20
  189. package/dist/web/community.css +0 -77
  190. package/dist/web/community.html +0 -37
  191. package/dist/web/composer-controller.js +0 -101
  192. package/dist/web/conversation-controller.js +0 -99
  193. package/dist/web/disclosure-state-controller.js +0 -95
  194. package/dist/web/draft-controller.js +0 -103
  195. package/dist/web/harmony-platform.js +0 -52
  196. package/dist/web/highlight-powershell.min.js +0 -39
  197. package/dist/web/highlight.min.js +0 -1262
  198. package/dist/web/history-cache.js +0 -240
  199. package/dist/web/history-controller.js +0 -167
  200. package/dist/web/index.html +0 -325
  201. package/dist/web/lan-session.js +0 -122
  202. package/dist/web/link-action-controller.js +0 -212
  203. package/dist/web/message-send-controller.js +0 -177
  204. package/dist/web/message-view.js +0 -98
  205. package/dist/web/p2p-data-channel.js +0 -50
  206. package/dist/web/p2p-diagnostics.js +0 -28
  207. package/dist/web/p2p-probe.js +0 -123
  208. package/dist/web/page-resume.js +0 -28
  209. package/dist/web/pending-message-store.js +0 -108
  210. package/dist/web/queue-controller.js +0 -82
  211. package/dist/web/resources.json +0 -1
  212. package/dist/web/self-relay-session.js +0 -129
  213. package/dist/web/server-requests.js +0 -67
  214. package/dist/web/station-connection-controller.js +0 -75
  215. package/dist/web/task-list-view.js +0 -296
  216. package/dist/web/thread-attention-controller.js +0 -124
  217. package/dist/web/thread-context-controller.js +0 -30
  218. package/dist/web/thread-list-controller.js +0 -61
  219. package/dist/web/thread-list-sync.js +0 -86
  220. package/dist/web/thread-title-controller.js +0 -57
  221. package/dist/web/timeline-formatters.js +0 -249
  222. package/dist/web/timeline-reducer.js +0 -81
  223. package/dist/web/timeline-renderer.js +0 -161
  224. package/dist/web/timeline-scroll-controller.js +0 -50
  225. package/dist/web/timeline-sync.js +0 -67
  226. package/dist/web/usage-controller.js +0 -258
  227. package/dist/web/vendor/README.md +0 -14
  228. package/dist/web/vendor/highlight-powershell.min.js +0 -39
  229. package/dist/web/vendor/highlight.LICENSE.txt +0 -29
  230. package/dist/web/vendor/highlight.min.js +0 -1262
  231. package/dist/web/vendor/lucide.LICENSE.txt +0 -17
  232. package/node_modules/@img/colour/LICENSE.md +0 -82
  233. package/node_modules/@img/colour/README.md +0 -15
  234. package/node_modules/@img/colour/color.cjs +0 -1596
  235. package/node_modules/@img/colour/index.cjs +0 -1
  236. package/node_modules/@img/colour/index.d.ts +0 -929
  237. package/node_modules/@img/colour/package.json +0 -58
  238. package/node_modules/@img/sharp-win32-x64/LICENSE +0 -191
  239. package/node_modules/@img/sharp-win32-x64/README.md +0 -59
  240. package/node_modules/@img/sharp-win32-x64/index.cjs +0 -1
  241. package/node_modules/@img/sharp-win32-x64/lib/libvips-42.dll +0 -0
  242. package/node_modules/@img/sharp-win32-x64/lib/libvips-cpp-8.18.6.dll +0 -0
  243. package/node_modules/@img/sharp-win32-x64/lib/sharp-win32-x64-0.35.4.node +0 -0
  244. package/node_modules/@img/sharp-win32-x64/package.json +0 -40
  245. package/node_modules/@img/sharp-win32-x64/versions.json +0 -30
  246. package/node_modules/@node-datachannel/win32-x64-msvc/node_datachannel.node +0 -0
  247. package/node_modules/@node-datachannel/win32-x64-msvc/package.json +0 -20
  248. package/node_modules/ansi-regex/index.d.ts +0 -37
  249. package/node_modules/ansi-regex/index.js +0 -10
  250. package/node_modules/ansi-regex/license +0 -9
  251. package/node_modules/ansi-regex/package.json +0 -55
  252. package/node_modules/ansi-regex/readme.md +0 -78
  253. package/node_modules/ansi-styles/index.d.ts +0 -345
  254. package/node_modules/ansi-styles/index.js +0 -163
  255. package/node_modules/ansi-styles/license +0 -9
  256. package/node_modules/ansi-styles/package.json +0 -56
  257. package/node_modules/ansi-styles/readme.md +0 -152
  258. package/node_modules/camelcase/index.d.ts +0 -63
  259. package/node_modules/camelcase/index.js +0 -76
  260. package/node_modules/camelcase/license +0 -9
  261. package/node_modules/camelcase/package.json +0 -43
  262. package/node_modules/camelcase/readme.md +0 -99
  263. package/node_modules/cliui/CHANGELOG.md +0 -76
  264. package/node_modules/cliui/LICENSE.txt +0 -14
  265. package/node_modules/cliui/README.md +0 -115
  266. package/node_modules/cliui/index.js +0 -354
  267. package/node_modules/cliui/package.json +0 -65
  268. package/node_modules/color-convert/CHANGELOG.md +0 -54
  269. package/node_modules/color-convert/LICENSE +0 -21
  270. package/node_modules/color-convert/README.md +0 -68
  271. package/node_modules/color-convert/conversions.js +0 -839
  272. package/node_modules/color-convert/index.js +0 -81
  273. package/node_modules/color-convert/package.json +0 -48
  274. package/node_modules/color-convert/route.js +0 -97
  275. package/node_modules/color-name/LICENSE +0 -8
  276. package/node_modules/color-name/README.md +0 -11
  277. package/node_modules/color-name/index.js +0 -152
  278. package/node_modules/color-name/package.json +0 -28
  279. package/node_modules/decamelize/index.js +0 -13
  280. package/node_modules/decamelize/license +0 -21
  281. package/node_modules/decamelize/package.json +0 -38
  282. package/node_modules/decamelize/readme.md +0 -48
  283. package/node_modules/detect-libc/LICENSE +0 -201
  284. package/node_modules/detect-libc/README.md +0 -163
  285. package/node_modules/detect-libc/index.d.ts +0 -14
  286. package/node_modules/detect-libc/lib/detect-libc.js +0 -313
  287. package/node_modules/detect-libc/lib/elf.js +0 -39
  288. package/node_modules/detect-libc/lib/filesystem.js +0 -51
  289. package/node_modules/detect-libc/lib/process.js +0 -24
  290. package/node_modules/detect-libc/package.json +0 -44
  291. package/node_modules/dijkstrajs/.travis.yml +0 -4
  292. package/node_modules/dijkstrajs/CONTRIBUTING.md +0 -8
  293. package/node_modules/dijkstrajs/LICENSE.md +0 -19
  294. package/node_modules/dijkstrajs/README.md +0 -18
  295. package/node_modules/dijkstrajs/dijkstra.js +0 -165
  296. package/node_modules/dijkstrajs/package.json +0 -60
  297. package/node_modules/dijkstrajs/test/dijkstra.test.js +0 -96
  298. package/node_modules/emoji-regex/LICENSE-MIT.txt +0 -20
  299. package/node_modules/emoji-regex/README.md +0 -73
  300. package/node_modules/emoji-regex/es2015/index.js +0 -6
  301. package/node_modules/emoji-regex/es2015/text.js +0 -6
  302. package/node_modules/emoji-regex/index.d.ts +0 -23
  303. package/node_modules/emoji-regex/index.js +0 -6
  304. package/node_modules/emoji-regex/package.json +0 -50
  305. package/node_modules/emoji-regex/text.js +0 -6
  306. package/node_modules/find-up/index.d.ts +0 -137
  307. package/node_modules/find-up/index.js +0 -89
  308. package/node_modules/find-up/license +0 -9
  309. package/node_modules/find-up/package.json +0 -53
  310. package/node_modules/find-up/readme.md +0 -156
  311. package/node_modules/get-caller-file/LICENSE.md +0 -6
  312. package/node_modules/get-caller-file/README.md +0 -41
  313. package/node_modules/get-caller-file/index.d.ts +0 -2
  314. package/node_modules/get-caller-file/index.js +0 -22
  315. package/node_modules/get-caller-file/index.js.map +0 -1
  316. package/node_modules/get-caller-file/package.json +0 -42
  317. package/node_modules/is-fullwidth-code-point/index.d.ts +0 -17
  318. package/node_modules/is-fullwidth-code-point/index.js +0 -50
  319. package/node_modules/is-fullwidth-code-point/license +0 -9
  320. package/node_modules/is-fullwidth-code-point/package.json +0 -42
  321. package/node_modules/is-fullwidth-code-point/readme.md +0 -39
  322. package/node_modules/locate-path/index.d.ts +0 -83
  323. package/node_modules/locate-path/index.js +0 -65
  324. package/node_modules/locate-path/license +0 -9
  325. package/node_modules/locate-path/package.json +0 -45
  326. package/node_modules/locate-path/readme.md +0 -122
  327. package/node_modules/node-datachannel/.clang-format +0 -17
  328. package/node_modules/node-datachannel/.editorconfig +0 -12
  329. package/node_modules/node-datachannel/.eslintignore +0 -8
  330. package/node_modules/node-datachannel/.eslintrc.json +0 -27
  331. package/node_modules/node-datachannel/.gitmodules +0 -3
  332. package/node_modules/node-datachannel/.prettierignore +0 -7
  333. package/node_modules/node-datachannel/.prettierrc +0 -13
  334. package/node_modules/node-datachannel/API.md +0 -247
  335. package/node_modules/node-datachannel/BULDING.md +0 -26
  336. package/node_modules/node-datachannel/CMakeLists.txt +0 -153
  337. package/node_modules/node-datachannel/LICENSE +0 -373
  338. package/node_modules/node-datachannel/README.md +0 -129
  339. package/node_modules/node-datachannel/dist/cjs/index.cjs +0 -11
  340. package/node_modules/node-datachannel/dist/cjs/index.cjs.map +0 -1
  341. package/node_modules/node-datachannel/dist/cjs/lib/datachannel-stream.cjs +0 -101
  342. package/node_modules/node-datachannel/dist/cjs/lib/datachannel-stream.cjs.map +0 -1
  343. package/node_modules/node-datachannel/dist/cjs/lib/index.cjs +0 -91
  344. package/node_modules/node-datachannel/dist/cjs/lib/index.cjs.map +0 -1
  345. package/node_modules/node-datachannel/dist/cjs/lib/node-datachannel.cjs +0 -94
  346. package/node_modules/node-datachannel/dist/cjs/lib/node-datachannel.cjs.map +0 -1
  347. package/node_modules/node-datachannel/dist/cjs/lib/websocket-server.cjs +0 -45
  348. package/node_modules/node-datachannel/dist/cjs/lib/websocket-server.cjs.map +0 -1
  349. package/node_modules/node-datachannel/dist/cjs/lib/websocket.cjs +0 -8
  350. package/node_modules/node-datachannel/dist/cjs/lib/websocket.cjs.map +0 -1
  351. package/node_modules/node-datachannel/dist/cjs/polyfill/Events.cjs +0 -86
  352. package/node_modules/node-datachannel/dist/cjs/polyfill/Events.cjs.map +0 -1
  353. package/node_modules/node-datachannel/dist/cjs/polyfill/Exception.cjs +0 -34
  354. package/node_modules/node-datachannel/dist/cjs/polyfill/Exception.cjs.map +0 -1
  355. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCCertificate.cjs +0 -34
  356. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCCertificate.cjs.map +0 -1
  357. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCDataChannel.cjs +0 -214
  358. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCDataChannel.cjs.map +0 -1
  359. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCDtlsTransport.cjs +0 -53
  360. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCDtlsTransport.cjs.map +0 -1
  361. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCError.cjs +0 -83
  362. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCError.cjs.map +0 -1
  363. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCIceCandidate.cjs +0 -132
  364. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCIceCandidate.cjs.map +0 -1
  365. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCIceTransport.cjs +0 -94
  366. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCIceTransport.cjs.map +0 -1
  367. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCPeerConnection.cjs +0 -434
  368. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCPeerConnection.cjs.map +0 -1
  369. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCSctpTransport.cjs +0 -59
  370. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCSctpTransport.cjs.map +0 -1
  371. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCSessionDescription.cjs +0 -45
  372. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCSessionDescription.cjs.map +0 -1
  373. package/node_modules/node-datachannel/dist/cjs/polyfill/index.cjs +0 -42
  374. package/node_modules/node-datachannel/dist/cjs/polyfill/index.cjs.map +0 -1
  375. package/node_modules/node-datachannel/dist/esm/index.mjs +0 -8
  376. package/node_modules/node-datachannel/dist/esm/index.mjs.map +0 -1
  377. package/node_modules/node-datachannel/dist/esm/lib/datachannel-stream.mjs +0 -78
  378. package/node_modules/node-datachannel/dist/esm/lib/datachannel-stream.mjs.map +0 -1
  379. package/node_modules/node-datachannel/dist/esm/lib/index.mjs +0 -64
  380. package/node_modules/node-datachannel/dist/esm/lib/index.mjs.map +0 -1
  381. package/node_modules/node-datachannel/dist/esm/lib/node-datachannel.mjs +0 -78
  382. package/node_modules/node-datachannel/dist/esm/lib/node-datachannel.mjs.map +0 -1
  383. package/node_modules/node-datachannel/dist/esm/lib/websocket-server.mjs +0 -43
  384. package/node_modules/node-datachannel/dist/esm/lib/websocket-server.mjs.map +0 -1
  385. package/node_modules/node-datachannel/dist/esm/lib/websocket.mjs +0 -6
  386. package/node_modules/node-datachannel/dist/esm/lib/websocket.mjs.map +0 -1
  387. package/node_modules/node-datachannel/dist/esm/polyfill/Events.mjs +0 -82
  388. package/node_modules/node-datachannel/dist/esm/polyfill/Events.mjs.map +0 -1
  389. package/node_modules/node-datachannel/dist/esm/polyfill/Exception.mjs +0 -28
  390. package/node_modules/node-datachannel/dist/esm/polyfill/Exception.mjs.map +0 -1
  391. package/node_modules/node-datachannel/dist/esm/polyfill/RTCCertificate.mjs +0 -30
  392. package/node_modules/node-datachannel/dist/esm/polyfill/RTCCertificate.mjs.map +0 -1
  393. package/node_modules/node-datachannel/dist/esm/polyfill/RTCDataChannel.mjs +0 -210
  394. package/node_modules/node-datachannel/dist/esm/polyfill/RTCDataChannel.mjs.map +0 -1
  395. package/node_modules/node-datachannel/dist/esm/polyfill/RTCDtlsTransport.mjs +0 -49
  396. package/node_modules/node-datachannel/dist/esm/polyfill/RTCDtlsTransport.mjs.map +0 -1
  397. package/node_modules/node-datachannel/dist/esm/polyfill/RTCError.mjs +0 -79
  398. package/node_modules/node-datachannel/dist/esm/polyfill/RTCError.mjs.map +0 -1
  399. package/node_modules/node-datachannel/dist/esm/polyfill/RTCIceCandidate.mjs +0 -128
  400. package/node_modules/node-datachannel/dist/esm/polyfill/RTCIceCandidate.mjs.map +0 -1
  401. package/node_modules/node-datachannel/dist/esm/polyfill/RTCIceTransport.mjs +0 -89
  402. package/node_modules/node-datachannel/dist/esm/polyfill/RTCIceTransport.mjs.map +0 -1
  403. package/node_modules/node-datachannel/dist/esm/polyfill/RTCPeerConnection.mjs +0 -430
  404. package/node_modules/node-datachannel/dist/esm/polyfill/RTCPeerConnection.mjs.map +0 -1
  405. package/node_modules/node-datachannel/dist/esm/polyfill/RTCSctpTransport.mjs +0 -55
  406. package/node_modules/node-datachannel/dist/esm/polyfill/RTCSctpTransport.mjs.map +0 -1
  407. package/node_modules/node-datachannel/dist/esm/polyfill/RTCSessionDescription.mjs +0 -41
  408. package/node_modules/node-datachannel/dist/esm/polyfill/RTCSessionDescription.mjs.map +0 -1
  409. package/node_modules/node-datachannel/dist/esm/polyfill/index.mjs +0 -27
  410. package/node_modules/node-datachannel/dist/esm/polyfill/index.mjs.map +0 -1
  411. package/node_modules/node-datachannel/dist/types/lib/datachannel-stream.d.ts +0 -24
  412. package/node_modules/node-datachannel/dist/types/lib/index.d.ts +0 -241
  413. package/node_modules/node-datachannel/dist/types/lib/types.d.ts +0 -119
  414. package/node_modules/node-datachannel/dist/types/lib/websocket-server.d.ts +0 -13
  415. package/node_modules/node-datachannel/dist/types/lib/websocket.d.ts +0 -25
  416. package/node_modules/node-datachannel/dist/types/polyfill/Events.d.ts +0 -15
  417. package/node_modules/node-datachannel/dist/types/polyfill/RTCCertificate.d.ts +0 -9
  418. package/node_modules/node-datachannel/dist/types/polyfill/RTCDataChannel.d.ts +0 -29
  419. package/node_modules/node-datachannel/dist/types/polyfill/RTCDtlsTransport.d.ts +0 -15
  420. package/node_modules/node-datachannel/dist/types/polyfill/RTCError.d.ts +0 -17
  421. package/node_modules/node-datachannel/dist/types/polyfill/RTCIceCandidate.d.ts +0 -21
  422. package/node_modules/node-datachannel/dist/types/polyfill/RTCIceTransport.d.ts +0 -30
  423. package/node_modules/node-datachannel/dist/types/polyfill/RTCPeerConnection.d.ts +0 -64
  424. package/node_modules/node-datachannel/dist/types/polyfill/RTCSctpTransport.d.ts +0 -15
  425. package/node_modules/node-datachannel/dist/types/polyfill/RTCSessionDescription.d.ts +0 -10
  426. package/node_modules/node-datachannel/dist/types/polyfill/index.d.ts +0 -26
  427. package/node_modules/node-datachannel/jest.config.ts +0 -14
  428. package/node_modules/node-datachannel/package.json +0 -133
  429. package/node_modules/node-datachannel/rollup.config.mjs +0 -67
  430. package/node_modules/node-datachannel/src/cpp/data-channel-wrapper.cpp +0 -530
  431. package/node_modules/node-datachannel/src/cpp/data-channel-wrapper.h +0 -63
  432. package/node_modules/node-datachannel/src/cpp/ice-udp-mux-listener-wrapper.cpp +0 -172
  433. package/node_modules/node-datachannel/src/cpp/ice-udp-mux-listener-wrapper.h +0 -43
  434. package/node_modules/node-datachannel/src/cpp/main.cpp +0 -58
  435. package/node_modules/node-datachannel/src/cpp/media-audio-wrapper.cpp +0 -457
  436. package/node_modules/node-datachannel/src/cpp/media-audio-wrapper.h +0 -52
  437. package/node_modules/node-datachannel/src/cpp/media-av1packetization.cpp +0 -24
  438. package/node_modules/node-datachannel/src/cpp/media-av1packetization.h +0 -11
  439. package/node_modules/node-datachannel/src/cpp/media-av1rtppacketizer-wrapper.cpp +0 -126
  440. package/node_modules/node-datachannel/src/cpp/media-av1rtppacketizer-wrapper.h +0 -29
  441. package/node_modules/node-datachannel/src/cpp/media-direction.cpp +0 -43
  442. package/node_modules/node-datachannel/src/cpp/media-direction.h +0 -10
  443. package/node_modules/node-datachannel/src/cpp/media-h264rtppacketizer-wrapper.cpp +0 -126
  444. package/node_modules/node-datachannel/src/cpp/media-h264rtppacketizer-wrapper.h +0 -30
  445. package/node_modules/node-datachannel/src/cpp/media-h265rtppacketizer-wrapper.cpp +0 -126
  446. package/node_modules/node-datachannel/src/cpp/media-h265rtppacketizer-wrapper.h +0 -30
  447. package/node_modules/node-datachannel/src/cpp/media-h26xseparator.cpp +0 -32
  448. package/node_modules/node-datachannel/src/cpp/media-h26xseparator.h +0 -11
  449. package/node_modules/node-datachannel/src/cpp/media-mediahandler-helper.cpp +0 -31
  450. package/node_modules/node-datachannel/src/cpp/media-mediahandler-helper.h +0 -11
  451. package/node_modules/node-datachannel/src/cpp/media-pacinghandler-wrapper.cpp +0 -79
  452. package/node_modules/node-datachannel/src/cpp/media-pacinghandler-wrapper.h +0 -28
  453. package/node_modules/node-datachannel/src/cpp/media-rtcpnackresponder-wrapper.cpp +0 -68
  454. package/node_modules/node-datachannel/src/cpp/media-rtcpnackresponder-wrapper.h +0 -28
  455. package/node_modules/node-datachannel/src/cpp/media-rtcpreceivingsession-wrapper.cpp +0 -57
  456. package/node_modules/node-datachannel/src/cpp/media-rtcpreceivingsession-wrapper.h +0 -28
  457. package/node_modules/node-datachannel/src/cpp/media-rtcpsrreporter-wrapper.cpp +0 -93
  458. package/node_modules/node-datachannel/src/cpp/media-rtcpsrreporter-wrapper.h +0 -30
  459. package/node_modules/node-datachannel/src/cpp/media-rtppacketizationconfig-wrapper.cpp +0 -167
  460. package/node_modules/node-datachannel/src/cpp/media-rtppacketizationconfig-wrapper.h +0 -35
  461. package/node_modules/node-datachannel/src/cpp/media-rtppacketizer-wrapper.cpp +0 -95
  462. package/node_modules/node-datachannel/src/cpp/media-rtppacketizer-wrapper.h +0 -30
  463. package/node_modules/node-datachannel/src/cpp/media-track-wrapper.cpp +0 -458
  464. package/node_modules/node-datachannel/src/cpp/media-track-wrapper.h +0 -61
  465. package/node_modules/node-datachannel/src/cpp/media-video-wrapper.cpp +0 -526
  466. package/node_modules/node-datachannel/src/cpp/media-video-wrapper.h +0 -56
  467. package/node_modules/node-datachannel/src/cpp/peer-connection-wrapper.cpp +0 -1298
  468. package/node_modules/node-datachannel/src/cpp/peer-connection-wrapper.h +0 -89
  469. package/node_modules/node-datachannel/src/cpp/rtc-wrapper.cpp +0 -205
  470. package/node_modules/node-datachannel/src/cpp/rtc-wrapper.h +0 -24
  471. package/node_modules/node-datachannel/src/cpp/thread-safe-callback.cpp +0 -57
  472. package/node_modules/node-datachannel/src/cpp/thread-safe-callback.h +0 -47
  473. package/node_modules/node-datachannel/src/cpp/web-socket-server-wrapper.cpp +0 -275
  474. package/node_modules/node-datachannel/src/cpp/web-socket-server-wrapper.h +0 -41
  475. package/node_modules/node-datachannel/src/cpp/web-socket-wrapper.cpp +0 -796
  476. package/node_modules/node-datachannel/src/cpp/web-socket-wrapper.h +0 -63
  477. package/node_modules/node-datachannel/src/index.ts +0 -9
  478. package/node_modules/node-datachannel/src/lib/datachannel-stream.ts +0 -100
  479. package/node_modules/node-datachannel/src/lib/index.ts +0 -290
  480. package/node_modules/node-datachannel/src/lib/node-datachannel.ts +0 -84
  481. package/node_modules/node-datachannel/src/lib/types.ts +0 -169
  482. package/node_modules/node-datachannel/src/lib/websocket-server.ts +0 -37
  483. package/node_modules/node-datachannel/src/lib/websocket.ts +0 -26
  484. package/node_modules/node-datachannel/src/polyfill/Events.ts +0 -82
  485. package/node_modules/node-datachannel/src/polyfill/Exception.ts +0 -37
  486. package/node_modules/node-datachannel/src/polyfill/README.md +0 -41
  487. package/node_modules/node-datachannel/src/polyfill/RTCCertificate.ts +0 -21
  488. package/node_modules/node-datachannel/src/polyfill/RTCDataChannel.ts +0 -225
  489. package/node_modules/node-datachannel/src/polyfill/RTCDtlsTransport.ts +0 -46
  490. package/node_modules/node-datachannel/src/polyfill/RTCError.ts +0 -78
  491. package/node_modules/node-datachannel/src/polyfill/RTCIceCandidate.ts +0 -128
  492. package/node_modules/node-datachannel/src/polyfill/RTCIceTransport.ts +0 -90
  493. package/node_modules/node-datachannel/src/polyfill/RTCPeerConnection.ts +0 -527
  494. package/node_modules/node-datachannel/src/polyfill/RTCSctpTransport.ts +0 -51
  495. package/node_modules/node-datachannel/src/polyfill/RTCSessionDescription.ts +0 -41
  496. package/node_modules/node-datachannel/src/polyfill/index.ts +0 -38
  497. package/node_modules/node-datachannel/tsconfig.json +0 -21
  498. package/node_modules/p-limit/index.d.ts +0 -38
  499. package/node_modules/p-limit/index.js +0 -57
  500. package/node_modules/p-limit/license +0 -9
  501. package/node_modules/p-limit/package.json +0 -52
  502. package/node_modules/p-limit/readme.md +0 -101
  503. package/node_modules/p-locate/index.d.ts +0 -64
  504. package/node_modules/p-locate/index.js +0 -52
  505. package/node_modules/p-locate/license +0 -9
  506. package/node_modules/p-locate/package.json +0 -53
  507. package/node_modules/p-locate/readme.md +0 -90
  508. package/node_modules/p-try/index.d.ts +0 -39
  509. package/node_modules/p-try/index.js +0 -9
  510. package/node_modules/p-try/license +0 -9
  511. package/node_modules/p-try/package.json +0 -42
  512. package/node_modules/p-try/readme.md +0 -58
  513. package/node_modules/path-exists/index.d.ts +0 -28
  514. package/node_modules/path-exists/index.js +0 -23
  515. package/node_modules/path-exists/license +0 -9
  516. package/node_modules/path-exists/package.json +0 -39
  517. package/node_modules/path-exists/readme.md +0 -52
  518. package/node_modules/pngjs/.eslintignore +0 -2
  519. package/node_modules/pngjs/.eslintrc.json +0 -19
  520. package/node_modules/pngjs/.prettierignore +0 -3
  521. package/node_modules/pngjs/LICENSE +0 -20
  522. package/node_modules/pngjs/README.md +0 -429
  523. package/node_modules/pngjs/browser.js +0 -16096
  524. package/node_modules/pngjs/coverage/lcov-report/base.css +0 -354
  525. package/node_modules/pngjs/coverage/lcov-report/bitmapper.js.html +0 -881
  526. package/node_modules/pngjs/coverage/lcov-report/bitpacker.js.html +0 -554
  527. package/node_modules/pngjs/coverage/lcov-report/block-navigation.js +0 -77
  528. package/node_modules/pngjs/coverage/lcov-report/chunkstream.js.html +0 -647
  529. package/node_modules/pngjs/coverage/lcov-report/constants.js.html +0 -176
  530. package/node_modules/pngjs/coverage/lcov-report/crc.js.html +0 -200
  531. package/node_modules/pngjs/coverage/lcov-report/favicon.png +0 -0
  532. package/node_modules/pngjs/coverage/lcov-report/filter-pack.js.html +0 -593
  533. package/node_modules/pngjs/coverage/lcov-report/filter-parse-async.js.html +0 -152
  534. package/node_modules/pngjs/coverage/lcov-report/filter-parse-sync.js.html +0 -143
  535. package/node_modules/pngjs/coverage/lcov-report/filter-parse.js.html +0 -611
  536. package/node_modules/pngjs/coverage/lcov-report/format-normaliser.js.html +0 -359
  537. package/node_modules/pngjs/coverage/lcov-report/index.html +0 -426
  538. package/node_modules/pngjs/coverage/lcov-report/interlace.js.html +0 -365
  539. package/node_modules/pngjs/coverage/lcov-report/packer-async.js.html +0 -230
  540. package/node_modules/pngjs/coverage/lcov-report/packer-sync.js.html +0 -248
  541. package/node_modules/pngjs/coverage/lcov-report/packer.js.html +0 -467
  542. package/node_modules/pngjs/coverage/lcov-report/paeth-predictor.js.html +0 -128
  543. package/node_modules/pngjs/coverage/lcov-report/parser-async.js.html +0 -575
  544. package/node_modules/pngjs/coverage/lcov-report/parser-sync.js.html +0 -404
  545. package/node_modules/pngjs/coverage/lcov-report/parser.js.html +0 -950
  546. package/node_modules/pngjs/coverage/lcov-report/png-sync.js.html +0 -116
  547. package/node_modules/pngjs/coverage/lcov-report/png.js.html +0 -662
  548. package/node_modules/pngjs/coverage/lcov-report/prettify.css +0 -101
  549. package/node_modules/pngjs/coverage/lcov-report/prettify.js +0 -1007
  550. package/node_modules/pngjs/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  551. package/node_modules/pngjs/coverage/lcov-report/sorter.js +0 -169
  552. package/node_modules/pngjs/coverage/lcov-report/sync-inflate.js.html +0 -584
  553. package/node_modules/pngjs/coverage/lcov-report/sync-reader.js.html +0 -215
  554. package/node_modules/pngjs/coverage/lcov.info +0 -2177
  555. package/node_modules/pngjs/lib/bitmapper.js +0 -267
  556. package/node_modules/pngjs/lib/bitpacker.js +0 -158
  557. package/node_modules/pngjs/lib/chunkstream.js +0 -189
  558. package/node_modules/pngjs/lib/constants.js +0 -32
  559. package/node_modules/pngjs/lib/crc.js +0 -40
  560. package/node_modules/pngjs/lib/filter-pack.js +0 -171
  561. package/node_modules/pngjs/lib/filter-parse-async.js +0 -24
  562. package/node_modules/pngjs/lib/filter-parse-sync.js +0 -21
  563. package/node_modules/pngjs/lib/filter-parse.js +0 -177
  564. package/node_modules/pngjs/lib/format-normaliser.js +0 -93
  565. package/node_modules/pngjs/lib/interlace.js +0 -95
  566. package/node_modules/pngjs/lib/packer-async.js +0 -50
  567. package/node_modules/pngjs/lib/packer-sync.js +0 -56
  568. package/node_modules/pngjs/lib/packer.js +0 -129
  569. package/node_modules/pngjs/lib/paeth-predictor.js +0 -16
  570. package/node_modules/pngjs/lib/parser-async.js +0 -165
  571. package/node_modules/pngjs/lib/parser-sync.js +0 -108
  572. package/node_modules/pngjs/lib/parser.js +0 -290
  573. package/node_modules/pngjs/lib/png-sync.js +0 -12
  574. package/node_modules/pngjs/lib/png.js +0 -194
  575. package/node_modules/pngjs/lib/sync-inflate.js +0 -168
  576. package/node_modules/pngjs/lib/sync-reader.js +0 -45
  577. package/node_modules/pngjs/package.json +0 -73
  578. package/node_modules/qrcode/README.md +0 -770
  579. package/node_modules/qrcode/bin/qrcode +0 -159
  580. package/node_modules/qrcode/helper/to-sjis-browser.js +0 -2
  581. package/node_modules/qrcode/helper/to-sjis.js +0 -105
  582. package/node_modules/qrcode/lib/browser.js +0 -76
  583. package/node_modules/qrcode/lib/can-promise.js +0 -7
  584. package/node_modules/qrcode/lib/core/alignment-pattern.js +0 -83
  585. package/node_modules/qrcode/lib/core/alphanumeric-data.js +0 -59
  586. package/node_modules/qrcode/lib/core/bit-buffer.js +0 -37
  587. package/node_modules/qrcode/lib/core/bit-matrix.js +0 -65
  588. package/node_modules/qrcode/lib/core/byte-data.js +0 -30
  589. package/node_modules/qrcode/lib/core/error-correction-code.js +0 -135
  590. package/node_modules/qrcode/lib/core/error-correction-level.js +0 -50
  591. package/node_modules/qrcode/lib/core/finder-pattern.js +0 -22
  592. package/node_modules/qrcode/lib/core/format-info.js +0 -29
  593. package/node_modules/qrcode/lib/core/galois-field.js +0 -69
  594. package/node_modules/qrcode/lib/core/kanji-data.js +0 -54
  595. package/node_modules/qrcode/lib/core/mask-pattern.js +0 -234
  596. package/node_modules/qrcode/lib/core/mode.js +0 -167
  597. package/node_modules/qrcode/lib/core/numeric-data.js +0 -43
  598. package/node_modules/qrcode/lib/core/polynomial.js +0 -62
  599. package/node_modules/qrcode/lib/core/qrcode.js +0 -495
  600. package/node_modules/qrcode/lib/core/reed-solomon-encoder.js +0 -56
  601. package/node_modules/qrcode/lib/core/regex.js +0 -31
  602. package/node_modules/qrcode/lib/core/segments.js +0 -330
  603. package/node_modules/qrcode/lib/core/utils.js +0 -63
  604. package/node_modules/qrcode/lib/core/version-check.js +0 -9
  605. package/node_modules/qrcode/lib/core/version.js +0 -163
  606. package/node_modules/qrcode/lib/index.js +0 -12
  607. package/node_modules/qrcode/lib/renderer/canvas.js +0 -63
  608. package/node_modules/qrcode/lib/renderer/png.js +0 -78
  609. package/node_modules/qrcode/lib/renderer/svg-tag.js +0 -81
  610. package/node_modules/qrcode/lib/renderer/svg.js +0 -19
  611. package/node_modules/qrcode/lib/renderer/terminal/terminal-small.js +0 -85
  612. package/node_modules/qrcode/lib/renderer/terminal/terminal.js +0 -49
  613. package/node_modules/qrcode/lib/renderer/terminal.js +0 -9
  614. package/node_modules/qrcode/lib/renderer/utf8.js +0 -71
  615. package/node_modules/qrcode/lib/renderer/utils.js +0 -99
  616. package/node_modules/qrcode/lib/server.js +0 -138
  617. package/node_modules/qrcode/license +0 -10
  618. package/node_modules/qrcode/package.json +0 -77
  619. package/node_modules/require-directory/.jshintrc +0 -67
  620. package/node_modules/require-directory/.npmignore +0 -1
  621. package/node_modules/require-directory/.travis.yml +0 -3
  622. package/node_modules/require-directory/LICENSE +0 -22
  623. package/node_modules/require-directory/README.markdown +0 -184
  624. package/node_modules/require-directory/index.js +0 -86
  625. package/node_modules/require-directory/package.json +0 -40
  626. package/node_modules/require-main-filename/CHANGELOG.md +0 -26
  627. package/node_modules/require-main-filename/LICENSE.txt +0 -14
  628. package/node_modules/require-main-filename/README.md +0 -26
  629. package/node_modules/require-main-filename/index.js +0 -18
  630. package/node_modules/require-main-filename/package.json +0 -35
  631. package/node_modules/semver/LICENSE +0 -15
  632. package/node_modules/semver/README.md +0 -680
  633. package/node_modules/semver/bin/semver.js +0 -195
  634. package/node_modules/semver/classes/comparator.js +0 -143
  635. package/node_modules/semver/classes/index.js +0 -7
  636. package/node_modules/semver/classes/range.js +0 -577
  637. package/node_modules/semver/classes/semver.js +0 -350
  638. package/node_modules/semver/functions/clean.js +0 -8
  639. package/node_modules/semver/functions/cmp.js +0 -54
  640. package/node_modules/semver/functions/coerce.js +0 -62
  641. package/node_modules/semver/functions/compare-build.js +0 -9
  642. package/node_modules/semver/functions/compare-loose.js +0 -5
  643. package/node_modules/semver/functions/compare.js +0 -7
  644. package/node_modules/semver/functions/diff.js +0 -60
  645. package/node_modules/semver/functions/eq.js +0 -5
  646. package/node_modules/semver/functions/gt.js +0 -5
  647. package/node_modules/semver/functions/gte.js +0 -5
  648. package/node_modules/semver/functions/inc.js +0 -21
  649. package/node_modules/semver/functions/lt.js +0 -5
  650. package/node_modules/semver/functions/lte.js +0 -5
  651. package/node_modules/semver/functions/major.js +0 -5
  652. package/node_modules/semver/functions/minor.js +0 -5
  653. package/node_modules/semver/functions/neq.js +0 -5
  654. package/node_modules/semver/functions/parse.js +0 -18
  655. package/node_modules/semver/functions/patch.js +0 -5
  656. package/node_modules/semver/functions/prerelease.js +0 -8
  657. package/node_modules/semver/functions/rcompare.js +0 -5
  658. package/node_modules/semver/functions/rsort.js +0 -5
  659. package/node_modules/semver/functions/satisfies.js +0 -12
  660. package/node_modules/semver/functions/sort.js +0 -5
  661. package/node_modules/semver/functions/truncate.js +0 -48
  662. package/node_modules/semver/functions/valid.js +0 -8
  663. package/node_modules/semver/index.js +0 -93
  664. package/node_modules/semver/internal/constants.js +0 -37
  665. package/node_modules/semver/internal/debug.js +0 -11
  666. package/node_modules/semver/internal/identifiers.js +0 -29
  667. package/node_modules/semver/internal/lrucache.js +0 -42
  668. package/node_modules/semver/internal/parse-options.js +0 -17
  669. package/node_modules/semver/internal/re.js +0 -223
  670. package/node_modules/semver/package.json +0 -78
  671. package/node_modules/semver/preload.js +0 -4
  672. package/node_modules/semver/range.bnf +0 -17
  673. package/node_modules/semver/ranges/gtr.js +0 -6
  674. package/node_modules/semver/ranges/intersects.js +0 -9
  675. package/node_modules/semver/ranges/ltr.js +0 -6
  676. package/node_modules/semver/ranges/max-satisfying.js +0 -27
  677. package/node_modules/semver/ranges/min-satisfying.js +0 -26
  678. package/node_modules/semver/ranges/min-version.js +0 -63
  679. package/node_modules/semver/ranges/outside.js +0 -82
  680. package/node_modules/semver/ranges/simplify.js +0 -49
  681. package/node_modules/semver/ranges/subset.js +0 -249
  682. package/node_modules/semver/ranges/to-comparators.js +0 -10
  683. package/node_modules/semver/ranges/valid.js +0 -13
  684. package/node_modules/set-blocking/CHANGELOG.md +0 -26
  685. package/node_modules/set-blocking/LICENSE.txt +0 -14
  686. package/node_modules/set-blocking/README.md +0 -31
  687. package/node_modules/set-blocking/index.js +0 -7
  688. package/node_modules/set-blocking/package.json +0 -42
  689. package/node_modules/sharp/LICENSE +0 -191
  690. package/node_modules/sharp/README.md +0 -112
  691. package/node_modules/sharp/dist/channel.cjs +0 -177
  692. package/node_modules/sharp/dist/channel.mjs +0 -177
  693. package/node_modules/sharp/dist/colour.cjs +0 -199
  694. package/node_modules/sharp/dist/colour.mjs +0 -199
  695. package/node_modules/sharp/dist/composite.cjs +0 -213
  696. package/node_modules/sharp/dist/composite.mjs +0 -213
  697. package/node_modules/sharp/dist/constructor.cjs +0 -511
  698. package/node_modules/sharp/dist/constructor.mjs +0 -511
  699. package/node_modules/sharp/dist/index.cjs +0 -25
  700. package/node_modules/sharp/dist/index.d.cts +0 -1999
  701. package/node_modules/sharp/dist/index.d.mts +0 -2046
  702. package/node_modules/sharp/dist/index.mjs +0 -25
  703. package/node_modules/sharp/dist/input.cjs +0 -819
  704. package/node_modules/sharp/dist/input.mjs +0 -819
  705. package/node_modules/sharp/dist/is.cjs +0 -143
  706. package/node_modules/sharp/dist/is.mjs +0 -143
  707. package/node_modules/sharp/dist/libvips.cjs +0 -212
  708. package/node_modules/sharp/dist/libvips.mjs +0 -212
  709. package/node_modules/sharp/dist/operation.cjs +0 -1002
  710. package/node_modules/sharp/dist/operation.mjs +0 -1002
  711. package/node_modules/sharp/dist/output.cjs +0 -1785
  712. package/node_modules/sharp/dist/output.mjs +0 -1785
  713. package/node_modules/sharp/dist/resize.cjs +0 -617
  714. package/node_modules/sharp/dist/resize.mjs +0 -617
  715. package/node_modules/sharp/dist/sharp.cjs +0 -174
  716. package/node_modules/sharp/dist/sharp.mjs +0 -174
  717. package/node_modules/sharp/dist/utility.cjs +0 -301
  718. package/node_modules/sharp/dist/utility.mjs +0 -301
  719. package/node_modules/sharp/install/build.js +0 -38
  720. package/node_modules/sharp/lib/index.d.ts +0 -1999
  721. package/node_modules/sharp/package.json +0 -227
  722. package/node_modules/sharp/src/binding.gyp +0 -303
  723. package/node_modules/sharp/src/common.cc +0 -1186
  724. package/node_modules/sharp/src/common.h +0 -421
  725. package/node_modules/sharp/src/metadata.cc +0 -404
  726. package/node_modules/sharp/src/metadata.h +0 -95
  727. package/node_modules/sharp/src/operations.cc +0 -516
  728. package/node_modules/sharp/src/operations.h +0 -137
  729. package/node_modules/sharp/src/pipeline.cc +0 -1948
  730. package/node_modules/sharp/src/pipeline.h +0 -422
  731. package/node_modules/sharp/src/sharp.cc +0 -43
  732. package/node_modules/sharp/src/stats.cc +0 -186
  733. package/node_modules/sharp/src/stats.h +0 -62
  734. package/node_modules/sharp/src/utilities.cc +0 -289
  735. package/node_modules/sharp/src/utilities.h +0 -22
  736. package/node_modules/string-width/index.d.ts +0 -29
  737. package/node_modules/string-width/index.js +0 -47
  738. package/node_modules/string-width/license +0 -9
  739. package/node_modules/string-width/package.json +0 -56
  740. package/node_modules/string-width/readme.md +0 -50
  741. package/node_modules/strip-ansi/index.d.ts +0 -17
  742. package/node_modules/strip-ansi/index.js +0 -4
  743. package/node_modules/strip-ansi/license +0 -9
  744. package/node_modules/strip-ansi/package.json +0 -54
  745. package/node_modules/strip-ansi/readme.md +0 -46
  746. package/node_modules/which-module/LICENSE +0 -13
  747. package/node_modules/which-module/README.md +0 -58
  748. package/node_modules/which-module/index.js +0 -9
  749. package/node_modules/which-module/package.json +0 -41
  750. package/node_modules/wrap-ansi/index.js +0 -186
  751. package/node_modules/wrap-ansi/license +0 -9
  752. package/node_modules/wrap-ansi/package.json +0 -61
  753. package/node_modules/wrap-ansi/readme.md +0 -97
  754. package/node_modules/ws/LICENSE +0 -20
  755. package/node_modules/ws/README.md +0 -548
  756. package/node_modules/ws/browser.js +0 -8
  757. package/node_modules/ws/index.js +0 -22
  758. package/node_modules/ws/lib/buffer-util.js +0 -131
  759. package/node_modules/ws/lib/constants.js +0 -19
  760. package/node_modules/ws/lib/event-target.js +0 -292
  761. package/node_modules/ws/lib/extension.js +0 -203
  762. package/node_modules/ws/lib/limiter.js +0 -55
  763. package/node_modules/ws/lib/permessage-deflate.js +0 -530
  764. package/node_modules/ws/lib/receiver.js +0 -743
  765. package/node_modules/ws/lib/sender.js +0 -607
  766. package/node_modules/ws/lib/stream.js +0 -161
  767. package/node_modules/ws/lib/subprotocol.js +0 -62
  768. package/node_modules/ws/lib/validation.js +0 -152
  769. package/node_modules/ws/lib/websocket-server.js +0 -562
  770. package/node_modules/ws/lib/websocket.js +0 -1407
  771. package/node_modules/ws/package.json +0 -74
  772. package/node_modules/ws/wrapper.mjs +0 -21
  773. package/node_modules/y18n/CHANGELOG.md +0 -35
  774. package/node_modules/y18n/LICENSE +0 -13
  775. package/node_modules/y18n/README.md +0 -109
  776. package/node_modules/y18n/index.js +0 -188
  777. package/node_modules/y18n/package.json +0 -39
  778. package/node_modules/yargs/CHANGELOG.md +0 -420
  779. package/node_modules/yargs/LICENSE +0 -21
  780. package/node_modules/yargs/README.md +0 -140
  781. package/node_modules/yargs/build/lib/apply-extends.d.ts +0 -2
  782. package/node_modules/yargs/build/lib/apply-extends.js +0 -65
  783. package/node_modules/yargs/build/lib/argsert.d.ts +0 -2
  784. package/node_modules/yargs/build/lib/argsert.js +0 -65
  785. package/node_modules/yargs/build/lib/command.d.ts +0 -64
  786. package/node_modules/yargs/build/lib/command.js +0 -416
  787. package/node_modules/yargs/build/lib/common-types.d.ts +0 -36
  788. package/node_modules/yargs/build/lib/common-types.js +0 -25
  789. package/node_modules/yargs/build/lib/completion-templates.d.ts +0 -2
  790. package/node_modules/yargs/build/lib/completion-templates.js +0 -50
  791. package/node_modules/yargs/build/lib/completion.d.ts +0 -21
  792. package/node_modules/yargs/build/lib/completion.js +0 -135
  793. package/node_modules/yargs/build/lib/is-promise.d.ts +0 -1
  794. package/node_modules/yargs/build/lib/is-promise.js +0 -9
  795. package/node_modules/yargs/build/lib/levenshtein.d.ts +0 -1
  796. package/node_modules/yargs/build/lib/levenshtein.js +0 -58
  797. package/node_modules/yargs/build/lib/middleware.d.ts +0 -10
  798. package/node_modules/yargs/build/lib/middleware.js +0 -57
  799. package/node_modules/yargs/build/lib/obj-filter.d.ts +0 -1
  800. package/node_modules/yargs/build/lib/obj-filter.js +0 -14
  801. package/node_modules/yargs/build/lib/parse-command.d.ts +0 -11
  802. package/node_modules/yargs/build/lib/parse-command.js +0 -36
  803. package/node_modules/yargs/build/lib/process-argv.d.ts +0 -2
  804. package/node_modules/yargs/build/lib/process-argv.js +0 -31
  805. package/node_modules/yargs/build/lib/usage.d.ts +0 -49
  806. package/node_modules/yargs/build/lib/usage.js +0 -540
  807. package/node_modules/yargs/build/lib/validation.d.ts +0 -34
  808. package/node_modules/yargs/build/lib/validation.js +0 -330
  809. package/node_modules/yargs/build/lib/yargs.d.ts +0 -274
  810. package/node_modules/yargs/build/lib/yargs.js +0 -1190
  811. package/node_modules/yargs/build/lib/yerror.d.ts +0 -4
  812. package/node_modules/yargs/build/lib/yerror.js +0 -11
  813. package/node_modules/yargs/index.js +0 -40
  814. package/node_modules/yargs/locales/be.json +0 -46
  815. package/node_modules/yargs/locales/de.json +0 -46
  816. package/node_modules/yargs/locales/en.json +0 -51
  817. package/node_modules/yargs/locales/es.json +0 -46
  818. package/node_modules/yargs/locales/fi.json +0 -49
  819. package/node_modules/yargs/locales/fr.json +0 -53
  820. package/node_modules/yargs/locales/hi.json +0 -49
  821. package/node_modules/yargs/locales/hu.json +0 -46
  822. package/node_modules/yargs/locales/id.json +0 -50
  823. package/node_modules/yargs/locales/it.json +0 -46
  824. package/node_modules/yargs/locales/ja.json +0 -51
  825. package/node_modules/yargs/locales/ko.json +0 -49
  826. package/node_modules/yargs/locales/nb.json +0 -44
  827. package/node_modules/yargs/locales/nl.json +0 -49
  828. package/node_modules/yargs/locales/nn.json +0 -44
  829. package/node_modules/yargs/locales/pirate.json +0 -13
  830. package/node_modules/yargs/locales/pl.json +0 -49
  831. package/node_modules/yargs/locales/pt.json +0 -45
  832. package/node_modules/yargs/locales/pt_BR.json +0 -48
  833. package/node_modules/yargs/locales/ru.json +0 -46
  834. package/node_modules/yargs/locales/th.json +0 -46
  835. package/node_modules/yargs/locales/tr.json +0 -48
  836. package/node_modules/yargs/locales/zh_CN.json +0 -48
  837. package/node_modules/yargs/locales/zh_TW.json +0 -47
  838. package/node_modules/yargs/package.json +0 -92
  839. package/node_modules/yargs/yargs.js +0 -14
  840. package/node_modules/yargs-parser/CHANGELOG.md +0 -601
  841. package/node_modules/yargs-parser/LICENSE.txt +0 -14
  842. package/node_modules/yargs-parser/README.md +0 -449
  843. package/node_modules/yargs-parser/index.js +0 -1032
  844. package/node_modules/yargs-parser/lib/tokenize-arg-string.js +0 -40
  845. package/node_modules/yargs-parser/package.json +0 -46
@@ -0,0 +1,80 @@
1
+ import { adminUiTokens, adminFooterStyles } from './admin-style.mjs';
2
+
3
+ export function adminPage(basePath = '/admin') {
4
+ return `<!doctype html><html lang="zh-CN"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><meta name="color-scheme" content="only light"><meta name="theme-color" content="#f5f7fa"><title>Code Relax 管理</title><style>${adminUiTokens}${adminFooterStyles}</style>
5
+ <style>@media(max-width:600px){body main{padding:12px 12px 40px}header.page-head{align-items:center;gap:8px;margin-bottom:8px}header.page-head h1{font-size:20px;line-height:1.2;margin:0}main .nav{gap:0;margin-bottom:12px}main .nav button{padding:8px 11px}main .stack,main .grid{gap:10px}main .card{padding:12px}main .hero strong{font-size:20px}main .throughput{grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;margin-top:10px}main .metrics{gap:6px}main .metric{display:flex;flex-direction:row-reverse;align-items:center;justify-content:space-between;gap:6px;min-width:0;padding:9px 10px}main .metric strong{font-size:17px;margin:0;white-space:nowrap}main .metric span{font-size:11px}main .card-head{margin-bottom:10px}}</style>
6
+ <style>@media(max-width:600px){main .throughput .metric strong{font-size:17px}}</style>
7
+ <style>.metric.warn{border-color:#946d38;background:#352a1b}.metric.warn strong{color:#ffd192}.metric.critical{border-color:#a65b58;background:#38211f}.metric.critical strong{color:#ffb1a9}.state.critical{background:#72342e;color:#ffe1dc}#trafficTimeline.critical .quota-fill{background:#d46a60}</style>
8
+ <style>.quota-timeline{display:grid;gap:9px;margin-top:18px}.quota-timeline[hidden]{display:none}.quota-heading{display:flex;align-items:center;justify-content:space-between;gap:12px;color:#b7c8ba;font-size:12px;font-variant-numeric:tabular-nums}.quota-heading strong{font-size:13px}.quota-pace{font-weight:700;color:#7bc993}.quota-pace.ahead{color:#e9b46f}.quota-track{position:relative;height:13px;border:1px solid #526154;border-radius:7px;background:#5c6e6030}.quota-fill{position:absolute;inset:0 auto 0 0;border-radius:6px;background:#48ae78}.quota-timeline.ahead .quota-fill{background:#d39b4c}.quota-now{position:absolute;top:-5px;bottom:-5px;width:2px;background:#d8e3db;box-shadow:0 0 0 1px #162019;transform:translateX(-1px)}.quota-now:before{position:absolute;top:-1px;left:50%;width:7px;height:7px;background:#d8e3db;transform:translate(-50%,-50%) rotate(45deg);content:""}.quota-period{display:flex;justify-content:space-between;gap:12px;color:#91a394;font-size:11px}.quota-period span:last-child{text-align:right}</style>
9
+ <style>
10
+ :root{color-scheme:only light;font:14px/1.5 system-ui,"Microsoft YaHei",sans-serif;background:#f5f7fa;color:#17212b}*{box-sizing:border-box}body{margin:0}button,input,textarea{font:inherit}button{cursor:pointer;border:1px solid transparent;border-radius:9px;padding:9px 14px;background:#397e58;color:white;font-weight:600}button:hover{background:#46966b}button:disabled{opacity:.45;cursor:default}button.secondary{background:#26352c;color:#c8d7cd;border-color:#405548}button.danger{background:transparent;color:#eaa29c;border-color:#734947}button:focus-visible,input:focus-visible,textarea:focus-visible{outline:2px solid #8ad2a0;outline-offset:2px}
11
+ main{max-width:1180px;margin:auto;padding:28px 24px 70px}h1{font-size:29px;line-height:1.2;margin:6px 0 8px}h2{font-size:18px;margin:0}h3{font-size:15px;margin:0}p{margin:0}.eyebrow{color:#83b598;letter-spacing:.12em;font-size:11px;font-weight:700}.subtle,.hint,.note{color:#a3b4a8}.hint,.note{font-size:12px}.note{margin-top:15px}.page-head{display:flex;align-items:end;justify-content:space-between;gap:16px;margin-bottom:22px}.page-head .subtle{margin-top:6px}.nav{display:flex;gap:7px;border-bottom:1px solid #34463a;margin-bottom:22px;overflow:auto}.nav button{border:0;border-bottom:2px solid transparent;border-radius:0;background:transparent;color:#b6c9bb;padding:12px 17px;white-space:nowrap}.nav button[aria-current=page]{color:#b9efca;border-bottom-color:#8ad2a0;background:#1a2b20}.page[hidden]{display:none}.stack{display:grid;gap:18px}.grid{display:grid;grid-template-columns:minmax(0,1.25fr) minmax(290px,.75fr);gap:18px;align-items:start}.card{background:#19241d;border:1px solid #34463a;border-radius:16px;padding:22px;box-shadow:0 12px 30px #080e0a24}.card-head{margin-bottom:18px}.hero{display:flex;align-items:start;justify-content:space-between;gap:18px;flex-wrap:wrap}.hero strong{font-size:26px}.state{border-radius:100px;padding:5px 10px;font-size:12px;font-weight:700;color:#c9f2d5;background:#28583b}.state.warn{background:#62491c;color:#ffe4a8}.state.down{background:#63302c;color:#ffd1c8}.throughput,.metrics{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px}.throughput{margin-top:20px}.metrics{grid-template-columns:repeat(3,minmax(0,1fr))}.metric{background:#111b15;border:1px solid #2b3c30;border-radius:11px;padding:14px;color:#9eafa3;font-size:12px}.metric strong{display:block;color:#f0f6f0;font-size:25px;line-height:1.2;margin-bottom:5px;font-variant-numeric:tabular-nums}.metric small{display:block;color:#80b893}.throughput .metric strong{font-size:32px}.detail{display:grid;gap:10px}.detail div{display:flex;justify-content:space-between;gap:12px;border-bottom:1px solid #2b3c30;padding-bottom:10px}.detail div:last-child{border:0;padding:0}.field{display:grid;gap:7px;margin:15px 0}.field label{font-size:13px;font-weight:600;color:#c5d7c9}input,textarea{width:100%;background:#101913;border:1px solid #45614d;border-radius:9px;color:#f1f7f1;padding:10px 12px}textarea{min-height:145px;resize:vertical}.actions{display:flex;flex-wrap:wrap;gap:9px;align-items:center}.current{border:1px solid #385841;background:#112017;border-radius:11px;padding:15px;margin-bottom:18px}.current.empty{border-color:#34463a;background:#111b15}.badge{display:inline-block;background:#28583b;color:#c9f2d5;border-radius:100px;padding:2px 8px;font-size:11px;font-weight:700}.current h3,.history h3{margin:8px 0 4px;overflow-wrap:anywhere}.current p,.history p{white-space:pre-wrap;overflow-wrap:anywhere;color:#c1d1c5}.date{font-size:12px;color:#94a99a}.history{display:grid;gap:10px}.history-item{border:1px solid #34463a;background:#141e17;border-radius:11px;padding:15px}.history-item.active{border-color:#4d865e}.history-item p{margin:8px 0 12px;max-height:4.5em;overflow:hidden}.history-item .actions button{padding:6px 10px;font-size:12px}.empty-note{padding:24px;border:1px dashed #415748;border-radius:10px;color:#a3b4a8;text-align:center}.status{min-height:24px;margin-top:16px;color:#96d4a9}.status.error{color:#f0aaa2}@media(max-width:800px){main{padding:24px 16px 50px}.grid{grid-template-columns:1fr}.metrics{grid-template-columns:repeat(2,minmax(0,1fr))}}@media(max-width:500px){.page-head{align-items:start}.card{padding:17px}.throughput{grid-template-columns:1fr}.metric{padding:10px}.metric strong{font-size:21px}}
12
+ </style><style>
13
+ .announcement-toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:18px}.announcement-toolbar h2{font-size:20px}.announcement-controls{display:flex;align-items:center;gap:9px;flex-wrap:wrap}.announcement-controls input{width:min(230px,100%)}.announcement-controls select{width:auto;min-width:108px}select{font:inherit;background:#101913;border:1px solid #45614d;border-radius:9px;color:#f1f7f1;padding:10px 12px}.announcement-list{display:grid;gap:9px}.announcement-row{display:grid;grid-template-columns:minmax(0,1fr) 90px 145px minmax(220px,auto);align-items:center;gap:14px;border:1px solid #34463a;border-radius:11px;padding:14px;background:#141e17}.announcement-row.active{border-color:#4d865e}.announcement-row h3{overflow-wrap:anywhere}.announcement-row p{color:#a3b4a8;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.announcement-row .actions{justify-content:flex-end;gap:6px}.announcement-row .actions button{padding:6px 9px;font-size:12px}.announcement-row .date{font-variant-numeric:tabular-nums}.announcement-status{display:inline-block;width:max-content;padding:3px 8px;border-radius:100px;font-size:11px;font-weight:700;color:#cad7ce;background:#334038}.announcement-status.active{background:#28583b;color:#c9f2d5}.announcement-status.draft{background:#4d462c;color:#ffe4a8}.announcement-empty{padding:32px;text-align:center;color:#a3b4a8}dialog{width:min(570px,calc(100% - 28px));max-height:calc(100vh - 36px);overflow:auto;background:#19241d;color:#edf4ee;border:1px solid #45614d;border-radius:16px;padding:22px;box-shadow:0 24px 70px #050905bb}dialog::backdrop{background:#050905bb}.editor-head{display:flex;align-items:center;justify-content:space-between;gap:10px}.editor-head button{padding:4px 10px}.editor-actions{display:flex;justify-content:flex-end;gap:8px;flex-wrap:wrap;margin-top:18px}.editor-actions[hidden]{display:none}dialog textarea{min-height:200px}dialog input:disabled,dialog textarea:disabled{opacity:.8}.hero-meta{display:flex;align-items:center;gap:10px}.hero-meta .hint{white-space:nowrap}.quota-card .card-head{display:flex;align-items:center;justify-content:space-between;gap:10px}.quota-card .card-head .hint{white-space:nowrap}@media(max-width:800px){.announcement-row{grid-template-columns:minmax(0,1fr) auto;gap:8px}.announcement-row .date{grid-column:1}.announcement-row .actions{grid-column:2;grid-row:2;align-self:end}.announcement-row .announcement-status{grid-column:2;grid-row:1}.announcement-toolbar{align-items:stretch}.announcement-controls{width:100%}.announcement-controls input{flex:1;min-width:110px}}@media(max-width:500px){.announcement-row{padding:11px}.announcement-row .actions button{padding:5px 7px;font-size:11px}.announcement-controls select{min-width:96px}.hero{align-items:center;flex-wrap:nowrap}.hero strong{font-size:20px}.hero-meta{gap:6px}.hero-meta .hint{font-size:11px}.hero-meta .state{padding:3px 7px}}
14
+ </style><style>
15
+ :root{color-scheme:only light;background:#f5f7fa;color:#17212b}body{min-height:100vh;background:radial-gradient(circle at 16% 15%,#cfe6d7aa 0,transparent 28%),radial-gradient(circle at 86% 76%,#dbece0aa 0,transparent 26%),linear-gradient(#1f4a2d0b 1px,transparent 1px),linear-gradient(90deg,#1f4a2d0b 1px,transparent 1px),#f5f7fa;background-size:auto,auto,32px 32px,32px 32px,auto}
16
+ button{background:#e0f0e5;color:#235d3a;border-color:#a9cbb4}button:hover{background:#cce5d4;color:#194d31;border-color:#84b995}button.secondary{background:#f4f8f5;color:#315f42;border-color:#c8daca}button.secondary:hover{background:#e8f2eb;color:#235d3a;border-color:#a9cbb4}button.danger{background:#fff8f6;color:#a34c43;border-color:#e6c5c0}button.danger:hover{background:#fdece8;color:#993b32;border-color:#dba7a0}button:focus-visible,input:focus-visible,textarea:focus-visible,select:focus-visible{outline-color:#4b9b66}
17
+ .subtle,.hint,.note{color:#607168}.page-head{justify-content:flex-start;align-items:center;gap:26px;margin-bottom:18px}.page-head h1{flex:none;color:#26332b}.page-head .nav{min-width:0;gap:4px;margin:0;border:0}.page-head .nav button{flex:none}.nav button{color:#607168}.nav button:hover{background:#eef5f0;color:#286e43}.nav button[aria-current=page]{color:#286e43;border-bottom-color:#68b582;background:#e4f1e8}.nav button[aria-current=page]:hover{background:#d8ebdd;color:#235d3a}.card{background:#ffffffee;border-color:#d5ddd8;box-shadow:0 10px 24px #263a2d0a}.metric{background:#f8faf8;border-color:#dce5df;color:#607168}.metric strong{color:#26332b}.metric small{color:#43865b}.metric.warn{background:#fff6e7;border-color:#e8c890}.metric.warn strong{color:#985d16}.metric.critical{background:#fff0ec;border-color:#dfaaa1}.metric.critical strong{color:#a5443b}
18
+ .state,.badge,.announcement-status.active{background:#e4f1e8;color:#286e43}.state.warn,.announcement-status.draft{background:#fff1d8;color:#895711}.state.down,.state.critical{background:#fbe6e2;color:#a13e35}.traffic-usage{color:#52645a;font-size:13px;font-variant-numeric:tabular-nums}.quota-card .quota-timeline{margin-top:12px}.quota-heading{color:#52645a}.quota-heading .warn{color:#985d16}.quota-heading .critical{color:#a5443b}.quota-pace{color:#28764a}.quota-pace.ahead{color:#a87326}.quota-track{border-color:#cfdbd2;background:#e9f0eb}.quota-fill{background:#68b582}.quota-timeline.ahead .quota-fill,.quota-timeline.warn .quota-fill{background:#d39b4c}.quota-now{background:#52645a;box-shadow:0 0 0 1px #fff}.quota-now:before{background:#52645a}.quota-period{color:#77857d}
19
+ .field label{color:#3b5142}input,textarea,select,.announcement-controls select{background:#fff;border-color:#c6d4cb;color:#26332b}input::placeholder,textarea::placeholder{color:#89988d}.date{color:#77857d}.announcement-row{background:#fff;border-color:#d5ddd8}.announcement-row.active{border-color:#a9c6b3;box-shadow:inset 3px 0 #68b582}.announcement-row p{color:#607168}.announcement-status{background:#edf1ee;color:#52645a}.announcement-empty{color:#607168}dialog{background:#fff;color:#26332b;border-color:#c6d4cb;box-shadow:0 24px 70px #263a2d33}dialog::backdrop{background:#172c20a8}.status{color:#28764a}.status.error{color:#a5443b}.relay-heading{display:flex;align-items:center;justify-content:space-between;gap:10px;margin-bottom:10px}.overview-sample{display:flex;justify-content:flex-end}.throughput{margin-top:12px}.throughput .metric{padding:10px 12px}.throughput .metric strong{font-size:20px}@media(max-width:600px){header.page-head{gap:8px}header.page-head h1{font-size:18px}.page-head .nav{gap:2px}.page-head .nav button{padding:7px 6px;font-size:12px}main .throughput{margin-top:8px}main .throughput .metric{padding:7px 8px}main .throughput .metric strong{font-size:14px}}
20
+ </style><style>
21
+ #metrics{grid-template-columns:repeat(5,minmax(0,1fr))}.relay-heading{margin-bottom:14px}.resource-head{display:flex;align-items:center;justify-content:space-between;gap:10px}.resource-head .hint{white-space:nowrap}.resource-card .throughput{border-top:1px solid #dce5df;padding-top:10px;margin-top:12px}.resource-card .throughput .metric{display:flex;flex-direction:row-reverse;align-items:center;justify-content:space-between;gap:8px;padding:8px 10px}.resource-card .throughput .metric strong{font-size:16px;margin:0;white-space:nowrap}
22
+ @media(max-width:800px){#metrics{grid-template-columns:repeat(2,minmax(0,1fr))}}
23
+ @media(max-width:600px){.resource-card .throughput .metric strong{font-size:14px}}
24
+ </style><style>main:not(.authenticated)>:not(#adminLogin){display:none!important}#adminLogin{max-width:430px;margin:10vh auto}#adminLogin[hidden]{display:none}.usage-toolbar{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;margin-bottom:16px}.usage-views,.usage-pages{display:flex;align-items:center;gap:8px}.usage-views button[aria-pressed=true]{background:#286e43;color:#fff}.usage-rows{display:grid;gap:8px}.usage-row{display:grid;gap:8px;padding:12px 14px;border:1px solid var(--admin-row-border);border-radius:var(--admin-control-radius);background:var(--admin-row)}.usage-row-head{display:flex;align-items:baseline;justify-content:space-between;gap:12px;min-width:0}.usage-row-head span{min-width:0;overflow-wrap:anywhere}.usage-row-head small{flex-shrink:0;white-space:nowrap}.usage-row strong{font-variant-numeric:tabular-nums}.usage-row small{text-align:right}.usage-pages{margin-top:16px}</style></head><body><main class="authenticated">
25
+ <header class="page-head"><h1>中继管理</h1><nav class="nav" aria-label="管理页面"><button type="button" data-page="overview" aria-current="page">运行概览</button><button type="button" data-page="announcements">系统公告</button><button type="button" data-page="settings">容量设置</button><button type="button" data-page="usage">使用统计</button></nav></header>
26
+ <section id="overview" class="page stack"><section class="card" aria-label="中继连接与转发"><div class="relay-heading"><h2>中继连接与转发</h2><span id="healthText" class="state">读取中</span></div><div id="metrics" class="metrics"></div></section><div class="grid"><section class="card resource-card" aria-label="服务器资源"><div class="card-head resource-head"><h2>服务器资源</h2><span id="sampleTime" class="hint">等待采样</span></div><div id="serverMetrics" class="metrics"></div><div class="throughput" id="throughput"></div></section><section class="card quota-card"><div class="card-head"><h2>流量包</h2><span id="trafficNote" class="hint">等待更新</span></div><p id="trafficUsage" class="traffic-usage">—</p><div id="trafficTimeline" class="quota-timeline" hidden><div class="quota-heading"><strong id="trafficRemaining">流量剩余 —</strong><span id="trafficPace" class="quota-pace">—×</span><span id="timeRemaining">时间剩余 —</span></div><div id="quotaTrack" class="quota-track" role="img"><span id="quotaFill" class="quota-fill"></span><span id="quotaNow" class="quota-now"></span></div><div class="quota-period"><span id="trafficEnd">到期 —</span><span id="trafficStart">本期开始 —</span></div></div></section></div></section>
27
+ <section id="announcements" class="page" hidden><section class="card"><div class="announcement-toolbar"><div><h2>公告管理</h2><p id="announcementCount" class="hint">正在读取</p></div><button id="newAnnouncement" type="button">新建公告</button></div><div class="announcement-controls"><input id="announcementSearch" type="search" aria-label="搜索公告" placeholder="搜索标题或正文"><select id="announcementFilter" aria-label="筛选状态"><option value="all">全部状态</option><option value="active">发布中</option><option value="draft">草稿</option><option value="withdrawn">已撤下</option></select></div><div id="announcementList" class="announcement-list" style="margin-top:14px"></div></section></section>
28
+ <dialog id="announcementEditor" aria-labelledby="editorHeading"><div class="editor-head"><h2 id="editorHeading">新建公告</h2><button id="closeEditor" class="secondary" type="button" aria-label="关闭">关闭</button></div><div class="field"><label for="title">标题</label><input id="title" maxlength="80" placeholder="输入公告标题"></div><div class="field"><label for="message">正文</label><textarea id="message" maxlength="2000" placeholder="输入公告内容"></textarea></div><p id="editorNote" class="hint"></p><p id="editorError" class="status error" role="alert" hidden></p><div id="editorActions" class="editor-actions"><button id="saveDraft" class="secondary" type="button">保存草稿</button><button id="publish" type="button">发布公告</button></div></dialog>
29
+ <section id="settings" class="page stack" hidden><section class="card"><div class="card-head"><h2>服务器转发容量</h2><p class="hint">只限制经 WSS 转发的普通会话,WebRTC 直连与白名单转发不占用此额度</p></div><div class="field"><label for="limit">最大并发会话</label><input id="limit" type="number" min="1" max="256"></div><button id="saveLimit" type="button">保存设置</button><p class="note">当前上限是人工配置值,不随 CPU 或带宽自动改变。</p></section></section>
30
+ <section id="usage" class="page" hidden><section class="card"><div class="usage-toolbar"><div><h2>今日使用统计</h2><p id="usageCount" class="hint">正在读取</p></div><div class="usage-views"><button id="usageUsers" type="button" class="secondary" aria-pressed="true">用户</button><button id="usageComputers" type="button" class="secondary" aria-pressed="false">工作站</button><button id="usageRefresh" type="button" class="secondary">刷新</button></div></div><div id="usageRows" class="usage-rows"></div><div class="usage-pages"><button id="usagePrev" type="button" class="secondary">上一页</button><span id="usagePageText" class="hint"></span><button id="usageNext" type="button" class="secondary">下一页</button></div><p id="usageError" class="status error" role="alert"></p></section></section><p id="result" class="status" role="status" aria-live="polite"></p>
31
+ </main><footer class="admin-footer">网站备案号:京ICP备2026027643号-2</footer><script>
32
+ const el=id=>document.getElementById(id);let snapshot=null;
33
+ const request=async(path,options={})=>{const response=await fetch(path,{...options,referrerPolicy:'no-referrer'});const body=await response.json();if(!response.ok)throw new Error(body.error||('HTTP '+response.status));return body};
34
+ function setResult(message,error=false){el('result').textContent=message;el('result').classList.toggle('error',error)}
35
+ function node(tag,className,value){const item=document.createElement(tag);if(className)item.className=className;if(value!==undefined)item.textContent=value;return item}
36
+ function metric(value,label,extra,tone){const item=node('div','metric'+(tone?' '+tone:''));item.append(node('strong','',value),node('span','',label));if(extra)item.append(node('small','',extra));return item}
37
+ function toneAbove(value,warn,critical){return typeof value==='number'&&Number.isFinite(value)?value>=critical?'critical':value>=warn?'warn':'':''}
38
+ function toneBelow(value,warn,critical){return typeof value==='number'&&Number.isFinite(value)?value<=critical?'critical':value<=warn?'warn':'':''}
39
+ function number(value,digits=0){return typeof value==='number'&&Number.isFinite(value)?value.toFixed(digits):'—'}
40
+ function date(value){return new Date(value).toLocaleString('zh-CN')}
41
+ function renderTrafficTimeline(cloud,available){const start=Date.parse(cloud.trafficStartAt);const end=Date.parse(cloud.trafficEndAt);const total=Number(cloud.trafficTotalBytes);const remaining=Number(cloud.trafficRemainingBytes);const valid=available&&Number.isFinite(start)&&Number.isFinite(end)&&end>start&&cloud.trafficTotalBytes!=null&&cloud.trafficRemainingBytes!=null&&total>0&&Number.isFinite(remaining);const timeline=el('trafficTimeline');timeline.hidden=!valid;if(!valid)return;
42
+ const clamp=value=>Math.max(0,Math.min(100,value));const quotaLeft=clamp(remaining/total*100);const timeLeft=clamp((end-Date.now())/(end-start)*100);const used=100-quotaLeft;const elapsed=100-timeLeft;const pace=elapsed>0?used/elapsed:null;
43
+ timeline.classList.toggle('ahead',pace!==null&&pace>1);timeline.classList.toggle('warn',quotaLeft<=20);timeline.classList.toggle('critical',quotaLeft<=10);el('trafficRemaining').textContent='流量剩余 '+number(quotaLeft,1)+'%';el('trafficRemaining').className=toneBelow(quotaLeft,20,10);el('timeRemaining').textContent='时间剩余 '+number(timeLeft,1)+'%';el('trafficPace').textContent=pace===null?'—×':number(pace,2)+'×';el('trafficPace').classList.toggle('ahead',pace!==null&&pace>1);
44
+ el('quotaFill').style.width=quotaLeft+'%';el('quotaNow').style.left=timeLeft+'%';el('quotaTrack').setAttribute('aria-label','流量剩余 '+number(quotaLeft,1)+'%,时间剩余 '+number(timeLeft,1)+'%');el('trafficStart').textContent='本期开始 '+date(cloud.trafficStartAt);el('trafficEnd').textContent='到期 '+date(cloud.trafficEndAt)}
45
+ function renderOverview(state){const cloud=state.cloud||{};const relay=state.relayAvailable!==false;const cloudFresh=cloud.metricAvailable&&Date.now()-Date.parse(cloud.metricSampledAt)<180000;const trafficFresh=cloud.trafficAvailable&&Date.now()-Date.parse(cloud.trafficSampledAt)<900000;const occupancy=state.maxRelaySessions?state.activeRelaySessions/state.maxRelaySessions:0;const high=occupancy>=.9||(cloudFresh&&(cloud.cpuPercent>=85||cloud.memoryPercent>=90||cloud.diskPercent>=90||cloud.outRatioPercent>=90));const caution=occupancy>=.75||(cloudFresh&&(cloud.cpuPercent>=65||cloud.memoryPercent>=80||cloud.diskPercent>=80||cloud.outRatioPercent>=70));const label=!relay?'中继不可用':high?'压力较高':!cloudFresh?'云监控数据过期':caution?'需要关注':'压力正常';
46
+ el('healthText').textContent=label;el('healthText').className='state'+(!relay||!cloudFresh&&!high?' down':high?' critical':caution?' warn':'');el('sampleTime').textContent=cloudFresh?'采样时间 '+new Date(cloud.metricSampledAt).toLocaleTimeString('zh-CN',{hour:'2-digit',minute:'2-digit'}):'等待采样';
47
+ el('throughput').replaceChildren(metric(cloudFresh?number(cloud.outMbps,2)+' Mbps':'—','公网发送'),metric(cloudFresh?number(cloud.inMbps,2)+' Mbps':'—','公网接收'));
48
+ el('serverMetrics').replaceChildren(metric(cloudFresh?number(cloud.cpuPercent,1)+'%':'—','CPU 使用率',null,cloudFresh?toneAbove(cloud.cpuPercent,65,85):''),metric(cloudFresh?number(cloud.memoryPercent,1)+'%':'—','内存使用率',null,cloudFresh?toneAbove(cloud.memoryPercent,80,90):''),metric(cloudFresh?number(cloud.diskPercent,1)+'%':'—','系统盘使用率',null,cloudFresh?toneAbove(cloud.diskPercent,80,90):''),metric(cloudFresh?number(cloud.cpuLoad1,2):'—','1 分钟负载'),metric(cloudFresh?number(cloud.outRatioPercent,1)+'%':'—','出口带宽使用率',null,cloudFresh?toneAbove(cloud.outRatioPercent,70,90):''));
49
+ const gb=value=>value==null?'—':number(Number(value)/1073741824,2)+' GB';
50
+ el('trafficUsage').textContent=trafficFresh?'已用 '+gb(cloud.trafficUsedBytes)+' / '+gb(cloud.trafficTotalBytes):'流量暂不可用';
51
+ el('trafficNote').textContent=trafficFresh?'更新时间 '+new Date(cloud.trafficSampledAt).toLocaleTimeString('zh-CN',{hour:'2-digit',minute:'2-digit'}):'暂不可用';
52
+ renderTrafficTimeline(cloud,trafficFresh);
53
+ el('metrics').replaceChildren(metric(number(state.activeRelaySessions)+' / '+number(state.maxRelaySessions),'受限转发',null,state.maxRelaySessions?toneAbove(state.activeRelaySessions/state.maxRelaySessions,.75,.9):''),metric(number(state.activeExemptRelaySessions),'白名单转发'),metric(number(state.websocketConnections),'WebSocket 连接'),metric(number(state.onlineComputers),'在线工作站'),metric(number(state.activePhones),'活动移动端'))}
54
+ let editorItem=null,editorMode='new',writing=false;
55
+ function openEditor(item=null,duplicate=false){editorItem=duplicate?null:item;editorMode=duplicate?'new':item?.status==='draft'?'draft':item?'view':'new';el('editorHeading').textContent=duplicate?'复制为新公告':editorMode==='draft'?'编辑草稿':editorMode==='view'?'查看公告':'新建公告';el('title').value=item?.title||'';el('message').value=item?.message||'';el('title').disabled=editorMode==='view';el('message').disabled=editorMode==='view';el('editorActions').hidden=editorMode==='view';el('editorNote').textContent=editorMode==='view'?'已发布内容只读;可复制为新公告再修改。':'发布后会立即替换当前公告并通知在线设备。';el('editorError').hidden=true;el('announcementEditor').showModal();if(editorMode!=='view')el('title').focus()}
56
+ function action(label,className,handler,disabled=false){const button=node('button',className,label);button.type='button';button.disabled=disabled;button.addEventListener('click',handler);return button}
57
+ function renderAnnouncements(state){const available=state.relayAvailable!==false;const items=state.announcements||[];const filter=el('announcementFilter').value;const query=el('announcementSearch').value.trim().toLocaleLowerCase();const visible=items.filter(item=>(filter==='all'||item.status===filter)&&(!query||(item.title+' '+item.message).toLocaleLowerCase().includes(query)));el('newAnnouncement').disabled=!available;el('announcementCount').textContent=available?'共 '+items.length+' 条 · 发布中 '+items.filter(item=>item.status==='active').length+' 条':'中继暂不可用';const list=el('announcementList');list.replaceChildren();if(!visible.length){list.append(node('div','announcement-empty',available?items.length?'没有符合条件的公告':'暂无公告,点击“新建公告”开始':'暂时无法读取公告'));return}
58
+ for(const item of visible){const row=node('article','announcement-row'+(item.status==='active'?' active':''));const summary=node('div');summary.append(node('h3','',item.title),node('p','',item.message));const status=node('span','announcement-status '+item.status,{active:'发布中',draft:'草稿',withdrawn:'已撤下'}[item.status]||'未知');const when=node('span','date',(item.status==='draft'?'修改 ':'发布 ')+date(item.status==='draft'?item.updatedAt:item.publishedAt));const actions=node('div','actions');const path='/admin/api/announcements/'+encodeURIComponent(item.id);
59
+ if(item.status==='draft'){actions.append(action('编辑','secondary',()=>openEditor(item)),action('发布','',()=>{if(!snapshot.announcement||confirm('发布后将替换当前公告,确定发布?'))write('PUT',path+'/publish',{},'公告已发布')},!available),action('删除','danger',()=>{if(confirm('确定删除这条草稿?'))write('DELETE',path,{},'草稿已删除')},!available))}
60
+ else if(item.status==='active'){actions.append(action('查看','secondary',()=>openEditor(item)),action('撤下','danger',()=>{if(confirm('确定撤下当前公告?'))write('PUT',path+'/withdraw',{},'公告已撤下')},!available))}
61
+ else{actions.append(action('查看','secondary',()=>openEditor(item)),action('复制','secondary',()=>openEditor(item,true),!available),action('删除','danger',()=>{if(confirm('确定删除这条已撤下的公告?'))write('DELETE',path,{},'公告记录已删除')},!available))}
62
+ row.append(summary,status,when,actions);list.append(row)}}
63
+ function render(state){snapshot=state;renderOverview(state);renderAnnouncements(state);el('saveLimit').disabled=state.relayAvailable===false;if(document.activeElement!==el('limit'))el('limit').value=state.maxRelaySessions??''}
64
+ async function load(){try{render(await request('/admin/api/status'));setResult('')}catch(error){snapshot=null;el('healthText').textContent='状态暂不可用';el('healthText').className='state down';for(const id of ['metrics','serverMetrics','throughput','announcementList'])el(id).replaceChildren();el('trafficTimeline').hidden=true;el('trafficUsage').textContent='—';el('announcementCount').textContent='暂时无法读取';el('saveLimit').disabled=true;setResult(error.message,true)}}
65
+ async function write(method,path,body,message){if(writing)return false;writing=true;try{await request(path,{method,headers:{'Content-Type':'application/json','X-Code-Relax-Admin':'1'},body:JSON.stringify(body)});await load();setResult(message);return true}catch(error){setResult(error.message,true);if(el('announcementEditor').open){el('editorError').textContent=error.message;el('editorError').hidden=false}return false}finally{writing=false}}
66
+ let usageView='user',usagePage=1,usageTotal=0;
67
+ function usageDuration(value){const seconds=Math.floor(Number(value)||0),hours=Math.floor(seconds/3600),minutes=Math.floor(seconds%3600/60),rest=seconds%60;return hours?hours+' 小时 '+minutes+' 分钟':minutes?minutes+' 分钟 '+rest+' 秒':rest+' 秒'}
68
+ function usageTime(value){return value?new Date(value.replace(' ','T')+'Z').toLocaleTimeString('zh-CN',{timeZone:'Asia/Shanghai',hour:'2-digit',minute:'2-digit',second:'2-digit',hour12:false}):'—'}
69
+ async function loadUsage(){const view=usageView,page=usagePage;el('usageError').textContent='';el('usageCount').textContent='正在读取';try{const result=await request('/admin/api/usage?view='+view+'&page='+page);if(view!==usageView||page!==usagePage||el('usage').hidden)return;usageTotal=result.total;el('usageCount').textContent='今日有记录:'+usageTotal+(view==='user'?' 个用户':' 台工作站')+' · 北京时间';el('usagePageText').textContent='第 '+page+' / '+Math.max(1,Math.ceil(usageTotal/30))+' 页';el('usagePrev').disabled=page<=1;el('usageNext').disabled=page*30>=usageTotal;const rows=el('usageRows');rows.replaceChildren();if(!result.rows.length){rows.append(node('div','empty-note','今日暂无计时记录'));return}for(const item of result.rows){const row=node('div','usage-row');const counts=' · 消息 '+Number(item.message_count||0)+' · 轮次 '+Number(item.turn_count||0);const heading=node('div','usage-row-head');const title=node('span','',view==='user'?item.email:'工作站 …'+item.id.slice(-8));title.title=view==='user'?item.email:item.id;heading.append(title,node('small','hint','最后使用 '+usageTime(item.last_used_at)));row.append(heading,node('strong','',view==='user'?'任务 '+usageDuration(item.today_task_seconds)+counts:'任务 '+usageDuration(item.today_task_seconds)+' · 免费账号 '+usageDuration(item.today_free_task_seconds)+counts));rows.append(row)}}catch(error){if(view===usageView&&page===usagePage){usageTotal=0;el('usageCount').textContent='统计暂不可用';el('usageRows').replaceChildren();el('usagePageText').textContent='';el('usagePrev').disabled=true;el('usageNext').disabled=true;el('usageError').textContent=error.message}}}
70
+ function setUsageView(view){if(usageView===view)return;usageView=view;usagePage=1;el('usageUsers').setAttribute('aria-pressed',String(view==='user'));el('usageComputers').setAttribute('aria-pressed',String(view==='computer'));void loadUsage()}
71
+ el('usageUsers').onclick=()=>setUsageView('user');el('usageComputers').onclick=()=>setUsageView('computer');el('usageRefresh').onclick=()=>loadUsage();el('usagePrev').onclick=()=>{if(usagePage>1){usagePage--;void loadUsage()}};el('usageNext').onclick=()=>{if(usagePage*30<usageTotal){usagePage++;void loadUsage()}};
72
+ function showPage(page){for(const button of document.querySelectorAll('[data-page]'))button.setAttribute('aria-current',button.dataset.page===page?'page':'false');for(const section of document.querySelectorAll('.page'))section.hidden=section.id!==page;history.replaceState(null,'','#'+page);if(page==='usage')void loadUsage();else void load()}
73
+ for(const button of document.querySelectorAll('[data-page]'))button.addEventListener('click',()=>showPage(button.dataset.page));
74
+ el('saveLimit').addEventListener('click',()=>write('PUT','/admin/api/settings',{maxRelaySessions:Number(el('limit').value)},'转发容量已保存'));
75
+ el('newAnnouncement').addEventListener('click',()=>openEditor());el('closeEditor').addEventListener('click',()=>el('announcementEditor').close());el('announcementSearch').addEventListener('input',()=>{if(snapshot)renderAnnouncements(snapshot)});el('announcementFilter').addEventListener('change',()=>{if(snapshot)renderAnnouncements(snapshot)});
76
+ async function saveAnnouncement(publish){const title=el('title').value.trim(),message=el('message').value.trim();if(!title||!message){el('editorError').textContent='请填写标题和正文';el('editorError').hidden=false;return}if(publish&&snapshot?.announcement&&snapshot.announcement.id!==editorItem?.id&&!confirm('发布后将替换当前公告,确定发布?'))return;const path=editorMode==='draft'?'/admin/api/announcements/'+encodeURIComponent(editorItem.id):'/admin/api/announcements';const target=publish&&editorMode==='draft'?path+'/publish':path;const body={title,message};if(publish&&editorMode==='new')body.publish=true;const ok=await write('PUT',target,body,publish?'公告已发布':'草稿已保存');if(ok)el('announcementEditor').close()}
77
+ el('saveDraft').addEventListener('click',()=>saveAnnouncement(false));el('publish').addEventListener('click',()=>saveAnnouncement(true));
78
+ showPage(['overview','announcements','settings','usage'].includes(location.hash.slice(1))?location.hash.slice(1):'overview');setInterval(()=>{if(!document.hidden&&!el('overview').hidden)load()},5000);
79
+ </script></body></html>`.replaceAll('/admin/api/', basePath + '/api/');
80
+ }
@@ -0,0 +1,74 @@
1
+ import http from 'node:http';
2
+ import fs from 'node:fs';
3
+ import { adminPage } from './admin-page.mjs';
4
+ import { startAdminCloud } from './admin-cloud.mjs';
5
+ import { MAX_ADMIN_REQUEST_BYTES } from './admin-state.mjs';
6
+
7
+ function reply(response, status, body, type = 'application/json; charset=utf-8') {
8
+ const bytes = typeof body === 'string' ? body : JSON.stringify(body);
9
+ response.writeHead(status, { 'Content-Type': type, 'Content-Length': Buffer.byteLength(bytes),
10
+ 'Cache-Control': 'no-store', 'X-Content-Type-Options': 'nosniff',
11
+ 'Referrer-Policy': 'no-referrer', 'X-Robots-Tag': 'noindex, nofollow', 'X-Frame-Options': 'DENY' });
12
+ response.end(bytes);
13
+ }
14
+
15
+ export async function startAdminServer({ port = 45851, relayUrl = 'http://127.0.0.1:45850', accessFile = '/etc/codex-relay/admin-access.json' } = {}) {
16
+ const { key } = JSON.parse(fs.readFileSync(accessFile, 'utf8'));
17
+ if (!/^[A-Za-z0-9_-]{43}$/.test(key)) throw new Error('Invalid admin access key');
18
+ const basePath = '/admin/' + key;
19
+ const cloud = startAdminCloud();
20
+ const relayOrigin = new URL(relayUrl);
21
+ if (relayOrigin.hostname !== '127.0.0.1' || relayOrigin.protocol !== 'http:' || relayOrigin.pathname !== '/') {
22
+ cloud.close(); throw new Error('Admin relay endpoint must be loopback HTTP');
23
+ }
24
+ const server = http.createServer(async (request, response) => {
25
+ const target = new URL(request.url || '/', 'http://localhost');
26
+ if (request.method === 'GET' && target.pathname === '/admin/health') { reply(response, 200, { ok: true }); return; }
27
+ if (request.headers['sec-fetch-site'] === 'cross-site' && request.method !== 'GET') { reply(response, 403, { error: 'Cross-site request rejected' }); return; }
28
+ if (target.pathname !== basePath && !target.pathname.startsWith(basePath + '/')) { reply(response, 404, { error: 'Not found' }); return; }
29
+ target.pathname = '/admin' + target.pathname.slice(basePath.length);
30
+ if (request.method === 'GET' && ['/admin', '/admin/'].includes(target.pathname)) {
31
+ reply(response, 200, adminPage(basePath), 'text/html; charset=utf-8'); return;
32
+ }
33
+ if (request.method === 'GET' && target.pathname === '/admin/usage') {
34
+ response.writeHead(302, { Location: basePath + '#usage', 'Cache-Control': 'no-store' }); response.end(); return;
35
+ }
36
+ if (request.method === 'GET' && ['/admin/api/status', '/admin/api/session', '/admin/api/usage', '/admin/api/usage-diagnostics'].includes(target.pathname)) {
37
+ try {
38
+ const upstream = await fetch(new URL(target.pathname + target.search, relayOrigin), {
39
+ signal: AbortSignal.timeout(3000), headers: { 'X-Code-Relax-Admin-Key': key } });
40
+ const state = await upstream.json();
41
+ if (!upstream.ok) { reply(response, upstream.status, state); return; }
42
+ reply(response, 200, target.pathname === '/admin/api/status'
43
+ ? { ...state, relayAvailable: true, cloud: cloud.read() } : state);
44
+ } catch {
45
+ reply(response, 503, { error: '中继服务暂不可用' });
46
+ }
47
+ return;
48
+ }
49
+ if (!target.pathname.startsWith('/admin/api/') || !['PUT', 'DELETE', 'POST'].includes(request.method || '')) {
50
+ reply(response, 404, { error: 'Not found' }); return;
51
+ }
52
+ try {
53
+ const chunks = [];
54
+ let size = 0;
55
+ for await (const chunk of request) {
56
+ size += chunk.length;
57
+ if (size > MAX_ADMIN_REQUEST_BYTES) { reply(response, 413, { error: 'Admin request too large' }); return; }
58
+ chunks.push(chunk);
59
+ }
60
+ const upstream = await fetch(new URL(target.pathname + target.search, relayOrigin), {
61
+ method: request.method, signal: AbortSignal.timeout(3000),
62
+ headers: { 'Content-Type': request.headers['content-type'] || '',
63
+ 'X-Code-Relax-Admin': request.headers['x-code-relax-admin'] || '',
64
+ 'X-Code-Relax-Admin-Key': key },
65
+ body: Buffer.concat(chunks),
66
+ });
67
+ reply(response, upstream.status, await upstream.text());
68
+ } catch { reply(response, 503, { error: '中继服务暂不可用' }); }
69
+ });
70
+ try {
71
+ await new Promise((resolve, reject) => { server.once('error', reject); server.listen(port, '127.0.0.1', resolve); });
72
+ } catch (error) { cloud.close(); throw error; }
73
+ return { port: server.address().port, async close() { cloud.close(); await new Promise(resolve => server.close(resolve)); } };
74
+ }
@@ -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: 1, maxRelaySessions: initialMaxRelaySessions, announcement: null };
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,32 +29,94 @@ 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
- return save({ ...value, announcement: { id: randomUUID(), title: clean(title, 80), message: clean(message, 2000),
36
- publishedAt: new Date().toISOString() } });
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) });
70
+ },
71
+ deleteAnnouncement(id) {
72
+ if (typeof id !== 'string' || !value.announcements.some(item => item.id === id)) throw new Error('Announcement not found');
73
+ if (value.announcement?.id === id) throw new Error('Withdraw the current announcement before deleting it');
74
+ return save({ ...value, announcements: value.announcements.filter(item => item.id !== id) });
37
75
  },
38
- withdraw() { return save({ ...value, announcement: null }); },
39
76
  };
40
77
  }
41
78
 
42
79
  function validate(source) {
43
- if (!source || source.version !== 1 || !Number.isSafeInteger(source.maxRelaySessions) ||
80
+ if (!source || ![1, 2, 3].includes(source.version) || !Number.isSafeInteger(source.maxRelaySessions) ||
44
81
  source.maxRelaySessions < 1 || source.maxRelaySessions > 256) throw new Error('Invalid relay admin state');
45
- let announcement = null;
46
- if (source.announcement !== null && source.announcement !== undefined) {
47
- const item = source.announcement;
48
- if (!item || !/^[\w-]{16,128}$/.test(item.id) || !Number.isFinite(Date.parse(item.publishedAt))) {
49
- throw new Error('Invalid relay announcement');
50
- }
51
- announcement = { id: item.id, title: clean(item.title, 80), message: clean(item.message, 2000), publishedAt: item.publishedAt };
82
+ const announcement = source.announcement == null ? null : validateAnnouncement(source.announcement);
83
+ const announcements = source.version === 1 ? (announcement ? [announcement] : []) : source.announcements;
84
+ if (!Array.isArray(announcements)) throw new Error('Invalid relay announcement history');
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 &&
94
+ item.title === announcement.title && item.message === announcement.message && item.publishedAt === announcement.publishedAt))) {
95
+ throw new Error('Invalid relay announcement history');
52
96
  }
53
- return { version: 1, maxRelaySessions: source.maxRelaySessions, announcement };
97
+ return { version: 3, maxRelaySessions: source.maxRelaySessions, announcement, announcements: validated };
98
+ }
99
+
100
+ function validateAnnouncement(item) {
101
+ if (!item || !/^[\w-]{16,128}$/.test(item.id) || typeof item.publishedAt !== 'string' ||
102
+ !Number.isFinite(Date.parse(item.publishedAt))) throw new Error('Invalid relay announcement');
103
+ return { id: item.id, title: clean(item.title, 80), message: clean(item.message, 2000), publishedAt: item.publishedAt };
104
+ }
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 };
54
120
  }
55
121
 
56
122
  function clean(value, limit) {
@@ -0,0 +1,14 @@
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-footer-caption:12px;--admin-footer-opacity:0.75;--admin-footer-space:24px;
10
+ }`;
11
+
12
+ export const adminFooterStyles = `body{display:flex;flex-direction:column}
13
+ body>main{width:100%;flex:1;margin:0 auto}
14
+ .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)}`;
@@ -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
+ }