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

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 (843) 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-file-channel.cjs +84 -0
  22. package/dist/shared/plan-pricing.cjs +32 -0
  23. package/dist/shared/question-attention.cjs +69 -0
  24. package/dist/shared/server-requests.cjs +157 -5
  25. package/dist/shared/service-endpoints.cjs +21 -0
  26. package/dist/shared/timeline-sync.cjs +111 -5
  27. package/dist/skills/code-relax/SKILL.md +13 -8
  28. package/dist/src/archived-threads.mjs +22 -0
  29. package/dist/src/bounded-process-log.mjs +63 -0
  30. package/dist/src/celsius-client.mjs +107 -0
  31. package/dist/src/code-browser.mjs +100 -0
  32. package/dist/src/desktop-launcher.mjs +33 -38
  33. package/dist/src/dots-approval-timeline.mjs +99 -0
  34. package/dist/src/dots-avatar.mjs +42 -0
  35. package/dist/src/dots-chat-projection.mjs +50 -0
  36. package/dist/src/dots-chat-server.mjs +482 -0
  37. package/dist/src/dots-message-images.mjs +319 -0
  38. package/dist/src/dots-profile.mjs +77 -0
  39. package/dist/src/dots-room-activity.mjs +94 -0
  40. package/dist/src/dots-room-client.mjs +135 -0
  41. package/dist/src/dots-room-projection.mjs +94 -0
  42. package/dist/src/dots-schedules.mjs +66 -0
  43. package/dist/src/dots-summary-tasks.mjs +32 -0
  44. package/dist/src/dots-task-catalog.mjs +430 -0
  45. package/dist/src/dots-task-files.mjs +52 -0
  46. package/dist/src/file-transfer-range.mjs +22 -0
  47. package/dist/src/file-upload-session.mjs +130 -0
  48. package/dist/src/hosted-history-app-server.mjs +103 -0
  49. package/dist/src/hosted-history-cache.mjs +113 -0
  50. package/dist/src/lan-socket-server.mjs +241 -84
  51. package/dist/src/managed-app-server.mjs +54 -16
  52. package/dist/src/message-images.mjs +0 -18
  53. package/dist/src/message-upload-files.mjs +109 -0
  54. package/dist/src/onboarding.mjs +10 -29
  55. package/dist/src/plan-pricing.mjs +47 -0
  56. package/dist/src/platform/README.md +2 -2
  57. package/dist/src/platform/codex-protocol.mjs +46 -0
  58. package/dist/src/platform/codex-runtime.mjs +3 -0
  59. package/dist/src/platform/credential-store.mjs +3 -0
  60. package/dist/src/platform/desktop-host.mjs +3 -0
  61. package/dist/src/platform/desktop-project-registration.mjs +3 -0
  62. package/dist/src/platform/desktop-project-store.mjs +208 -0
  63. package/dist/src/platform/file-opener.mjs +9 -0
  64. package/dist/src/platform/linux/codex-runtime.mjs +56 -0
  65. package/dist/src/platform/linux/credential-store.mjs +28 -0
  66. package/dist/src/platform/linux/desktop-host.mjs +83 -0
  67. package/dist/src/platform/linux/desktop-installation.mjs +36 -0
  68. package/dist/src/platform/linux/desktop-project-registration.mjs +11 -0
  69. package/dist/src/platform/linux/network-info.mjs +11 -0
  70. package/dist/src/platform/linux/process.mjs +42 -0
  71. package/dist/src/platform/linux/project-locations.mjs +17 -0
  72. package/dist/src/platform/linux/resident-startup.mjs +52 -0
  73. package/dist/src/platform/linux/retained-runtime.mjs +76 -0
  74. package/dist/src/platform/linux/service-host.mjs +18 -0
  75. package/dist/src/platform/linux/system.mjs +49 -0
  76. package/dist/src/platform/linux/user-environment.mjs +7 -0
  77. package/dist/src/platform/macos/codex-runtime.mjs +125 -0
  78. package/dist/src/platform/macos/credential-store.mjs +10 -0
  79. package/dist/src/platform/macos/desktop-host.mjs +82 -0
  80. package/dist/src/platform/macos/desktop-project-registration.mjs +11 -0
  81. package/dist/src/platform/macos/network-info.mjs +8 -0
  82. package/dist/src/platform/macos/project-locations.mjs +8 -0
  83. package/dist/src/platform/macos/resident-startup.mjs +84 -0
  84. package/dist/src/platform/macos/retained-runtime.mjs +127 -0
  85. package/dist/src/platform/macos/service-host.mjs +18 -0
  86. package/dist/src/platform/macos/system.mjs +29 -0
  87. package/dist/src/platform/macos/user-environment.mjs +7 -0
  88. package/dist/src/platform/native-package.mjs +58 -0
  89. package/dist/src/platform/network-info.mjs +3 -0
  90. package/dist/src/platform/path-identity.mjs +5 -0
  91. package/dist/src/platform/posix/network-candidates.mjs +23 -0
  92. package/dist/src/platform/posix/runtime-paths.mjs +25 -0
  93. package/dist/src/platform/power-inhibitor.mjs +22 -0
  94. package/dist/src/platform/project-locations.mjs +3 -0
  95. package/dist/src/platform/runtime-paths.mjs +8 -0
  96. package/dist/src/platform/select.mjs +5 -0
  97. package/dist/src/platform/service-host.mjs +3 -0
  98. package/dist/src/platform/user-environment.mjs +3 -0
  99. package/dist/src/platform/windows/activate-desktop.ps1 +48 -0
  100. package/dist/src/platform/windows/codex-runtime.mjs +215 -0
  101. package/dist/src/platform/windows/credential-store.mjs +27 -27
  102. package/dist/src/platform/windows/credential-store.ps1 +49 -49
  103. package/dist/src/platform/windows/desktop-helper.mjs +179 -0
  104. package/dist/src/platform/windows/desktop-host.mjs +43 -23
  105. package/dist/src/platform/windows/desktop-info.ps1 +14 -16
  106. package/dist/src/platform/windows/desktop-project-registration.mjs +4 -0
  107. package/dist/src/platform/windows/desktop-runtime.ps1 +10 -0
  108. package/dist/src/platform/windows/desktop-shortcuts.ps1 +21 -28
  109. package/dist/src/platform/windows/dots-profile.mjs +49 -0
  110. package/dist/src/platform/windows/keep-awake.ps1 +20 -0
  111. package/dist/src/platform/windows/launch-worker.mjs +17 -18
  112. package/dist/src/platform/windows/project-locations.mjs +16 -0
  113. package/dist/src/platform/windows/resident-start.js +20 -0
  114. package/dist/src/platform/windows/resident-startup.ps1 +76 -20
  115. package/dist/src/platform/windows/rustdesk-video-probe.mjs +168 -0
  116. package/dist/src/platform/windows/service-host.mjs +24 -36
  117. package/dist/src/platform/windows/stop-desktop.ps1 +7 -4
  118. package/dist/src/platform/windows/user-environment.mjs +1 -1
  119. package/dist/src/project-create.mjs +121 -0
  120. package/dist/src/project-management.mjs +59 -0
  121. package/dist/src/project-remove.mjs +55 -0
  122. package/dist/src/project-update.mjs +59 -0
  123. package/dist/src/runtime-discovery.mjs +47 -0
  124. package/dist/src/self-relay/account-cleanup.mjs +30 -0
  125. package/dist/src/self-relay/account-connections.mjs +52 -0
  126. package/dist/src/self-relay/admin-cloud.mjs +101 -0
  127. package/dist/src/self-relay/admin-page.mjs +80 -0
  128. package/dist/src/self-relay/admin-server.mjs +74 -0
  129. package/dist/src/self-relay/admin-state.mjs +85 -19
  130. package/dist/src/self-relay/admin-style.mjs +14 -0
  131. package/dist/src/self-relay/android-releases.mjs +61 -0
  132. package/dist/src/self-relay/client.mjs +45 -45
  133. package/dist/src/self-relay/connector.mjs +421 -144
  134. package/dist/src/self-relay/demo.mjs +34 -35
  135. package/dist/src/self-relay/device-info.mjs +27 -0
  136. package/dist/src/self-relay/device-store.mjs +10 -2
  137. package/dist/src/self-relay/diagnostics.mjs +54 -0
  138. package/dist/src/self-relay/email-accounts.mjs +183 -0
  139. package/dist/src/self-relay/file-wire.mjs +13 -0
  140. package/dist/src/self-relay/lan-authorizations.mjs +44 -2
  141. package/dist/src/self-relay/lifecycle.mjs +250 -272
  142. package/dist/src/self-relay/long-pairing.mjs +40 -0
  143. package/dist/src/self-relay/mysql-state.mjs +118 -0
  144. package/dist/src/self-relay/p2p-probe.mjs +41 -5
  145. package/dist/src/self-relay/privacy-page.mjs +26 -0
  146. package/dist/src/self-relay/public-releases.mjs +52 -0
  147. package/dist/src/self-relay/rtc-file-bridge.mjs +41 -0
  148. package/dist/src/self-relay/server.mjs +652 -114
  149. package/dist/src/self-relay/usage-daily.mjs +55 -0
  150. package/dist/src/self-relay/usage-meter.mjs +141 -0
  151. package/dist/src/server.mjs +1519 -1793
  152. package/dist/src/service-control.mjs +17 -7
  153. package/dist/src/service-doctor.mjs +86 -33
  154. package/dist/src/service-health.mjs +2 -2
  155. package/dist/src/service-install.mjs +91 -85
  156. package/dist/src/service-lifecycle.mjs +117 -108
  157. package/dist/src/service-power.mjs +58 -0
  158. package/dist/src/service-restart.mjs +43 -10
  159. package/dist/src/service-update-worker.mjs +42 -0
  160. package/dist/src/service-update.mjs +71 -0
  161. package/dist/src/shared-app-server.mjs +561 -407
  162. package/dist/src/shared-catalog.mjs +95 -13
  163. package/dist/src/shared-recovery.mjs +15 -11
  164. package/dist/src/shared-thread-stream.mjs +147 -63
  165. package/dist/src/skill-install.mjs +0 -13
  166. package/dist/src/turn-model-history.mjs +47 -0
  167. package/dist/src/usage-reset.mjs +17 -0
  168. package/dist/src/workstation-downloads.mjs +120 -0
  169. package/package.json +35 -37
  170. package/tools/postinstall.mjs +86 -22
  171. package/dist/src/app-server-client.mjs +0 -468
  172. package/dist/src/app-server-tasks.mjs +0 -358
  173. package/dist/src/debug-ui.mjs +0 -131
  174. package/dist/src/platform/windows/desktop-monitor.mjs +0 -34
  175. package/dist/src/platform/windows/desktop-shortcut-run.ps1 +0 -5
  176. package/dist/src/platform/windows/desktop-tools.mjs +0 -48
  177. package/dist/src/thread-catalog.mjs +0 -47
  178. package/dist/tools/find-desktop-pipe.mjs +0 -10
  179. package/dist/web/activity-view.js +0 -283
  180. package/dist/web/approval-ui.js +0 -188
  181. package/dist/web/capabilities.js +0 -57
  182. package/dist/web/chat-transport.js +0 -202
  183. package/dist/web/chat.css +0 -782
  184. package/dist/web/chat.js +0 -3830
  185. package/dist/web/client-platform.js +0 -11
  186. package/dist/web/community-view.js +0 -20
  187. package/dist/web/community.css +0 -77
  188. package/dist/web/community.html +0 -37
  189. package/dist/web/composer-controller.js +0 -101
  190. package/dist/web/conversation-controller.js +0 -99
  191. package/dist/web/disclosure-state-controller.js +0 -95
  192. package/dist/web/draft-controller.js +0 -103
  193. package/dist/web/harmony-platform.js +0 -52
  194. package/dist/web/highlight-powershell.min.js +0 -39
  195. package/dist/web/highlight.min.js +0 -1262
  196. package/dist/web/history-cache.js +0 -240
  197. package/dist/web/history-controller.js +0 -167
  198. package/dist/web/index.html +0 -325
  199. package/dist/web/lan-session.js +0 -122
  200. package/dist/web/link-action-controller.js +0 -212
  201. package/dist/web/message-send-controller.js +0 -177
  202. package/dist/web/message-view.js +0 -98
  203. package/dist/web/p2p-data-channel.js +0 -50
  204. package/dist/web/p2p-diagnostics.js +0 -28
  205. package/dist/web/p2p-probe.js +0 -123
  206. package/dist/web/page-resume.js +0 -28
  207. package/dist/web/pending-message-store.js +0 -108
  208. package/dist/web/queue-controller.js +0 -82
  209. package/dist/web/resources.json +0 -1
  210. package/dist/web/self-relay-session.js +0 -129
  211. package/dist/web/server-requests.js +0 -67
  212. package/dist/web/station-connection-controller.js +0 -75
  213. package/dist/web/task-list-view.js +0 -296
  214. package/dist/web/thread-attention-controller.js +0 -124
  215. package/dist/web/thread-context-controller.js +0 -30
  216. package/dist/web/thread-list-controller.js +0 -61
  217. package/dist/web/thread-list-sync.js +0 -86
  218. package/dist/web/thread-title-controller.js +0 -57
  219. package/dist/web/timeline-formatters.js +0 -249
  220. package/dist/web/timeline-reducer.js +0 -81
  221. package/dist/web/timeline-renderer.js +0 -161
  222. package/dist/web/timeline-scroll-controller.js +0 -50
  223. package/dist/web/timeline-sync.js +0 -67
  224. package/dist/web/usage-controller.js +0 -258
  225. package/dist/web/vendor/README.md +0 -14
  226. package/dist/web/vendor/highlight-powershell.min.js +0 -39
  227. package/dist/web/vendor/highlight.LICENSE.txt +0 -29
  228. package/dist/web/vendor/highlight.min.js +0 -1262
  229. package/dist/web/vendor/lucide.LICENSE.txt +0 -17
  230. package/node_modules/@img/colour/LICENSE.md +0 -82
  231. package/node_modules/@img/colour/README.md +0 -15
  232. package/node_modules/@img/colour/color.cjs +0 -1596
  233. package/node_modules/@img/colour/index.cjs +0 -1
  234. package/node_modules/@img/colour/index.d.ts +0 -929
  235. package/node_modules/@img/colour/package.json +0 -58
  236. package/node_modules/@img/sharp-win32-x64/LICENSE +0 -191
  237. package/node_modules/@img/sharp-win32-x64/README.md +0 -59
  238. package/node_modules/@img/sharp-win32-x64/index.cjs +0 -1
  239. package/node_modules/@img/sharp-win32-x64/lib/libvips-42.dll +0 -0
  240. package/node_modules/@img/sharp-win32-x64/lib/libvips-cpp-8.18.6.dll +0 -0
  241. package/node_modules/@img/sharp-win32-x64/lib/sharp-win32-x64-0.35.4.node +0 -0
  242. package/node_modules/@img/sharp-win32-x64/package.json +0 -40
  243. package/node_modules/@img/sharp-win32-x64/versions.json +0 -30
  244. package/node_modules/@node-datachannel/win32-x64-msvc/node_datachannel.node +0 -0
  245. package/node_modules/@node-datachannel/win32-x64-msvc/package.json +0 -20
  246. package/node_modules/ansi-regex/index.d.ts +0 -37
  247. package/node_modules/ansi-regex/index.js +0 -10
  248. package/node_modules/ansi-regex/license +0 -9
  249. package/node_modules/ansi-regex/package.json +0 -55
  250. package/node_modules/ansi-regex/readme.md +0 -78
  251. package/node_modules/ansi-styles/index.d.ts +0 -345
  252. package/node_modules/ansi-styles/index.js +0 -163
  253. package/node_modules/ansi-styles/license +0 -9
  254. package/node_modules/ansi-styles/package.json +0 -56
  255. package/node_modules/ansi-styles/readme.md +0 -152
  256. package/node_modules/camelcase/index.d.ts +0 -63
  257. package/node_modules/camelcase/index.js +0 -76
  258. package/node_modules/camelcase/license +0 -9
  259. package/node_modules/camelcase/package.json +0 -43
  260. package/node_modules/camelcase/readme.md +0 -99
  261. package/node_modules/cliui/CHANGELOG.md +0 -76
  262. package/node_modules/cliui/LICENSE.txt +0 -14
  263. package/node_modules/cliui/README.md +0 -115
  264. package/node_modules/cliui/index.js +0 -354
  265. package/node_modules/cliui/package.json +0 -65
  266. package/node_modules/color-convert/CHANGELOG.md +0 -54
  267. package/node_modules/color-convert/LICENSE +0 -21
  268. package/node_modules/color-convert/README.md +0 -68
  269. package/node_modules/color-convert/conversions.js +0 -839
  270. package/node_modules/color-convert/index.js +0 -81
  271. package/node_modules/color-convert/package.json +0 -48
  272. package/node_modules/color-convert/route.js +0 -97
  273. package/node_modules/color-name/LICENSE +0 -8
  274. package/node_modules/color-name/README.md +0 -11
  275. package/node_modules/color-name/index.js +0 -152
  276. package/node_modules/color-name/package.json +0 -28
  277. package/node_modules/decamelize/index.js +0 -13
  278. package/node_modules/decamelize/license +0 -21
  279. package/node_modules/decamelize/package.json +0 -38
  280. package/node_modules/decamelize/readme.md +0 -48
  281. package/node_modules/detect-libc/LICENSE +0 -201
  282. package/node_modules/detect-libc/README.md +0 -163
  283. package/node_modules/detect-libc/index.d.ts +0 -14
  284. package/node_modules/detect-libc/lib/detect-libc.js +0 -313
  285. package/node_modules/detect-libc/lib/elf.js +0 -39
  286. package/node_modules/detect-libc/lib/filesystem.js +0 -51
  287. package/node_modules/detect-libc/lib/process.js +0 -24
  288. package/node_modules/detect-libc/package.json +0 -44
  289. package/node_modules/dijkstrajs/.travis.yml +0 -4
  290. package/node_modules/dijkstrajs/CONTRIBUTING.md +0 -8
  291. package/node_modules/dijkstrajs/LICENSE.md +0 -19
  292. package/node_modules/dijkstrajs/README.md +0 -18
  293. package/node_modules/dijkstrajs/dijkstra.js +0 -165
  294. package/node_modules/dijkstrajs/package.json +0 -60
  295. package/node_modules/dijkstrajs/test/dijkstra.test.js +0 -96
  296. package/node_modules/emoji-regex/LICENSE-MIT.txt +0 -20
  297. package/node_modules/emoji-regex/README.md +0 -73
  298. package/node_modules/emoji-regex/es2015/index.js +0 -6
  299. package/node_modules/emoji-regex/es2015/text.js +0 -6
  300. package/node_modules/emoji-regex/index.d.ts +0 -23
  301. package/node_modules/emoji-regex/index.js +0 -6
  302. package/node_modules/emoji-regex/package.json +0 -50
  303. package/node_modules/emoji-regex/text.js +0 -6
  304. package/node_modules/find-up/index.d.ts +0 -137
  305. package/node_modules/find-up/index.js +0 -89
  306. package/node_modules/find-up/license +0 -9
  307. package/node_modules/find-up/package.json +0 -53
  308. package/node_modules/find-up/readme.md +0 -156
  309. package/node_modules/get-caller-file/LICENSE.md +0 -6
  310. package/node_modules/get-caller-file/README.md +0 -41
  311. package/node_modules/get-caller-file/index.d.ts +0 -2
  312. package/node_modules/get-caller-file/index.js +0 -22
  313. package/node_modules/get-caller-file/index.js.map +0 -1
  314. package/node_modules/get-caller-file/package.json +0 -42
  315. package/node_modules/is-fullwidth-code-point/index.d.ts +0 -17
  316. package/node_modules/is-fullwidth-code-point/index.js +0 -50
  317. package/node_modules/is-fullwidth-code-point/license +0 -9
  318. package/node_modules/is-fullwidth-code-point/package.json +0 -42
  319. package/node_modules/is-fullwidth-code-point/readme.md +0 -39
  320. package/node_modules/locate-path/index.d.ts +0 -83
  321. package/node_modules/locate-path/index.js +0 -65
  322. package/node_modules/locate-path/license +0 -9
  323. package/node_modules/locate-path/package.json +0 -45
  324. package/node_modules/locate-path/readme.md +0 -122
  325. package/node_modules/node-datachannel/.clang-format +0 -17
  326. package/node_modules/node-datachannel/.editorconfig +0 -12
  327. package/node_modules/node-datachannel/.eslintignore +0 -8
  328. package/node_modules/node-datachannel/.eslintrc.json +0 -27
  329. package/node_modules/node-datachannel/.gitmodules +0 -3
  330. package/node_modules/node-datachannel/.prettierignore +0 -7
  331. package/node_modules/node-datachannel/.prettierrc +0 -13
  332. package/node_modules/node-datachannel/API.md +0 -247
  333. package/node_modules/node-datachannel/BULDING.md +0 -26
  334. package/node_modules/node-datachannel/CMakeLists.txt +0 -153
  335. package/node_modules/node-datachannel/LICENSE +0 -373
  336. package/node_modules/node-datachannel/README.md +0 -129
  337. package/node_modules/node-datachannel/dist/cjs/index.cjs +0 -11
  338. package/node_modules/node-datachannel/dist/cjs/index.cjs.map +0 -1
  339. package/node_modules/node-datachannel/dist/cjs/lib/datachannel-stream.cjs +0 -101
  340. package/node_modules/node-datachannel/dist/cjs/lib/datachannel-stream.cjs.map +0 -1
  341. package/node_modules/node-datachannel/dist/cjs/lib/index.cjs +0 -91
  342. package/node_modules/node-datachannel/dist/cjs/lib/index.cjs.map +0 -1
  343. package/node_modules/node-datachannel/dist/cjs/lib/node-datachannel.cjs +0 -94
  344. package/node_modules/node-datachannel/dist/cjs/lib/node-datachannel.cjs.map +0 -1
  345. package/node_modules/node-datachannel/dist/cjs/lib/websocket-server.cjs +0 -45
  346. package/node_modules/node-datachannel/dist/cjs/lib/websocket-server.cjs.map +0 -1
  347. package/node_modules/node-datachannel/dist/cjs/lib/websocket.cjs +0 -8
  348. package/node_modules/node-datachannel/dist/cjs/lib/websocket.cjs.map +0 -1
  349. package/node_modules/node-datachannel/dist/cjs/polyfill/Events.cjs +0 -86
  350. package/node_modules/node-datachannel/dist/cjs/polyfill/Events.cjs.map +0 -1
  351. package/node_modules/node-datachannel/dist/cjs/polyfill/Exception.cjs +0 -34
  352. package/node_modules/node-datachannel/dist/cjs/polyfill/Exception.cjs.map +0 -1
  353. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCCertificate.cjs +0 -34
  354. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCCertificate.cjs.map +0 -1
  355. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCDataChannel.cjs +0 -214
  356. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCDataChannel.cjs.map +0 -1
  357. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCDtlsTransport.cjs +0 -53
  358. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCDtlsTransport.cjs.map +0 -1
  359. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCError.cjs +0 -83
  360. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCError.cjs.map +0 -1
  361. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCIceCandidate.cjs +0 -132
  362. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCIceCandidate.cjs.map +0 -1
  363. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCIceTransport.cjs +0 -94
  364. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCIceTransport.cjs.map +0 -1
  365. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCPeerConnection.cjs +0 -434
  366. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCPeerConnection.cjs.map +0 -1
  367. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCSctpTransport.cjs +0 -59
  368. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCSctpTransport.cjs.map +0 -1
  369. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCSessionDescription.cjs +0 -45
  370. package/node_modules/node-datachannel/dist/cjs/polyfill/RTCSessionDescription.cjs.map +0 -1
  371. package/node_modules/node-datachannel/dist/cjs/polyfill/index.cjs +0 -42
  372. package/node_modules/node-datachannel/dist/cjs/polyfill/index.cjs.map +0 -1
  373. package/node_modules/node-datachannel/dist/esm/index.mjs +0 -8
  374. package/node_modules/node-datachannel/dist/esm/index.mjs.map +0 -1
  375. package/node_modules/node-datachannel/dist/esm/lib/datachannel-stream.mjs +0 -78
  376. package/node_modules/node-datachannel/dist/esm/lib/datachannel-stream.mjs.map +0 -1
  377. package/node_modules/node-datachannel/dist/esm/lib/index.mjs +0 -64
  378. package/node_modules/node-datachannel/dist/esm/lib/index.mjs.map +0 -1
  379. package/node_modules/node-datachannel/dist/esm/lib/node-datachannel.mjs +0 -78
  380. package/node_modules/node-datachannel/dist/esm/lib/node-datachannel.mjs.map +0 -1
  381. package/node_modules/node-datachannel/dist/esm/lib/websocket-server.mjs +0 -43
  382. package/node_modules/node-datachannel/dist/esm/lib/websocket-server.mjs.map +0 -1
  383. package/node_modules/node-datachannel/dist/esm/lib/websocket.mjs +0 -6
  384. package/node_modules/node-datachannel/dist/esm/lib/websocket.mjs.map +0 -1
  385. package/node_modules/node-datachannel/dist/esm/polyfill/Events.mjs +0 -82
  386. package/node_modules/node-datachannel/dist/esm/polyfill/Events.mjs.map +0 -1
  387. package/node_modules/node-datachannel/dist/esm/polyfill/Exception.mjs +0 -28
  388. package/node_modules/node-datachannel/dist/esm/polyfill/Exception.mjs.map +0 -1
  389. package/node_modules/node-datachannel/dist/esm/polyfill/RTCCertificate.mjs +0 -30
  390. package/node_modules/node-datachannel/dist/esm/polyfill/RTCCertificate.mjs.map +0 -1
  391. package/node_modules/node-datachannel/dist/esm/polyfill/RTCDataChannel.mjs +0 -210
  392. package/node_modules/node-datachannel/dist/esm/polyfill/RTCDataChannel.mjs.map +0 -1
  393. package/node_modules/node-datachannel/dist/esm/polyfill/RTCDtlsTransport.mjs +0 -49
  394. package/node_modules/node-datachannel/dist/esm/polyfill/RTCDtlsTransport.mjs.map +0 -1
  395. package/node_modules/node-datachannel/dist/esm/polyfill/RTCError.mjs +0 -79
  396. package/node_modules/node-datachannel/dist/esm/polyfill/RTCError.mjs.map +0 -1
  397. package/node_modules/node-datachannel/dist/esm/polyfill/RTCIceCandidate.mjs +0 -128
  398. package/node_modules/node-datachannel/dist/esm/polyfill/RTCIceCandidate.mjs.map +0 -1
  399. package/node_modules/node-datachannel/dist/esm/polyfill/RTCIceTransport.mjs +0 -89
  400. package/node_modules/node-datachannel/dist/esm/polyfill/RTCIceTransport.mjs.map +0 -1
  401. package/node_modules/node-datachannel/dist/esm/polyfill/RTCPeerConnection.mjs +0 -430
  402. package/node_modules/node-datachannel/dist/esm/polyfill/RTCPeerConnection.mjs.map +0 -1
  403. package/node_modules/node-datachannel/dist/esm/polyfill/RTCSctpTransport.mjs +0 -55
  404. package/node_modules/node-datachannel/dist/esm/polyfill/RTCSctpTransport.mjs.map +0 -1
  405. package/node_modules/node-datachannel/dist/esm/polyfill/RTCSessionDescription.mjs +0 -41
  406. package/node_modules/node-datachannel/dist/esm/polyfill/RTCSessionDescription.mjs.map +0 -1
  407. package/node_modules/node-datachannel/dist/esm/polyfill/index.mjs +0 -27
  408. package/node_modules/node-datachannel/dist/esm/polyfill/index.mjs.map +0 -1
  409. package/node_modules/node-datachannel/dist/types/lib/datachannel-stream.d.ts +0 -24
  410. package/node_modules/node-datachannel/dist/types/lib/index.d.ts +0 -241
  411. package/node_modules/node-datachannel/dist/types/lib/types.d.ts +0 -119
  412. package/node_modules/node-datachannel/dist/types/lib/websocket-server.d.ts +0 -13
  413. package/node_modules/node-datachannel/dist/types/lib/websocket.d.ts +0 -25
  414. package/node_modules/node-datachannel/dist/types/polyfill/Events.d.ts +0 -15
  415. package/node_modules/node-datachannel/dist/types/polyfill/RTCCertificate.d.ts +0 -9
  416. package/node_modules/node-datachannel/dist/types/polyfill/RTCDataChannel.d.ts +0 -29
  417. package/node_modules/node-datachannel/dist/types/polyfill/RTCDtlsTransport.d.ts +0 -15
  418. package/node_modules/node-datachannel/dist/types/polyfill/RTCError.d.ts +0 -17
  419. package/node_modules/node-datachannel/dist/types/polyfill/RTCIceCandidate.d.ts +0 -21
  420. package/node_modules/node-datachannel/dist/types/polyfill/RTCIceTransport.d.ts +0 -30
  421. package/node_modules/node-datachannel/dist/types/polyfill/RTCPeerConnection.d.ts +0 -64
  422. package/node_modules/node-datachannel/dist/types/polyfill/RTCSctpTransport.d.ts +0 -15
  423. package/node_modules/node-datachannel/dist/types/polyfill/RTCSessionDescription.d.ts +0 -10
  424. package/node_modules/node-datachannel/dist/types/polyfill/index.d.ts +0 -26
  425. package/node_modules/node-datachannel/jest.config.ts +0 -14
  426. package/node_modules/node-datachannel/package.json +0 -133
  427. package/node_modules/node-datachannel/rollup.config.mjs +0 -67
  428. package/node_modules/node-datachannel/src/cpp/data-channel-wrapper.cpp +0 -530
  429. package/node_modules/node-datachannel/src/cpp/data-channel-wrapper.h +0 -63
  430. package/node_modules/node-datachannel/src/cpp/ice-udp-mux-listener-wrapper.cpp +0 -172
  431. package/node_modules/node-datachannel/src/cpp/ice-udp-mux-listener-wrapper.h +0 -43
  432. package/node_modules/node-datachannel/src/cpp/main.cpp +0 -58
  433. package/node_modules/node-datachannel/src/cpp/media-audio-wrapper.cpp +0 -457
  434. package/node_modules/node-datachannel/src/cpp/media-audio-wrapper.h +0 -52
  435. package/node_modules/node-datachannel/src/cpp/media-av1packetization.cpp +0 -24
  436. package/node_modules/node-datachannel/src/cpp/media-av1packetization.h +0 -11
  437. package/node_modules/node-datachannel/src/cpp/media-av1rtppacketizer-wrapper.cpp +0 -126
  438. package/node_modules/node-datachannel/src/cpp/media-av1rtppacketizer-wrapper.h +0 -29
  439. package/node_modules/node-datachannel/src/cpp/media-direction.cpp +0 -43
  440. package/node_modules/node-datachannel/src/cpp/media-direction.h +0 -10
  441. package/node_modules/node-datachannel/src/cpp/media-h264rtppacketizer-wrapper.cpp +0 -126
  442. package/node_modules/node-datachannel/src/cpp/media-h264rtppacketizer-wrapper.h +0 -30
  443. package/node_modules/node-datachannel/src/cpp/media-h265rtppacketizer-wrapper.cpp +0 -126
  444. package/node_modules/node-datachannel/src/cpp/media-h265rtppacketizer-wrapper.h +0 -30
  445. package/node_modules/node-datachannel/src/cpp/media-h26xseparator.cpp +0 -32
  446. package/node_modules/node-datachannel/src/cpp/media-h26xseparator.h +0 -11
  447. package/node_modules/node-datachannel/src/cpp/media-mediahandler-helper.cpp +0 -31
  448. package/node_modules/node-datachannel/src/cpp/media-mediahandler-helper.h +0 -11
  449. package/node_modules/node-datachannel/src/cpp/media-pacinghandler-wrapper.cpp +0 -79
  450. package/node_modules/node-datachannel/src/cpp/media-pacinghandler-wrapper.h +0 -28
  451. package/node_modules/node-datachannel/src/cpp/media-rtcpnackresponder-wrapper.cpp +0 -68
  452. package/node_modules/node-datachannel/src/cpp/media-rtcpnackresponder-wrapper.h +0 -28
  453. package/node_modules/node-datachannel/src/cpp/media-rtcpreceivingsession-wrapper.cpp +0 -57
  454. package/node_modules/node-datachannel/src/cpp/media-rtcpreceivingsession-wrapper.h +0 -28
  455. package/node_modules/node-datachannel/src/cpp/media-rtcpsrreporter-wrapper.cpp +0 -93
  456. package/node_modules/node-datachannel/src/cpp/media-rtcpsrreporter-wrapper.h +0 -30
  457. package/node_modules/node-datachannel/src/cpp/media-rtppacketizationconfig-wrapper.cpp +0 -167
  458. package/node_modules/node-datachannel/src/cpp/media-rtppacketizationconfig-wrapper.h +0 -35
  459. package/node_modules/node-datachannel/src/cpp/media-rtppacketizer-wrapper.cpp +0 -95
  460. package/node_modules/node-datachannel/src/cpp/media-rtppacketizer-wrapper.h +0 -30
  461. package/node_modules/node-datachannel/src/cpp/media-track-wrapper.cpp +0 -458
  462. package/node_modules/node-datachannel/src/cpp/media-track-wrapper.h +0 -61
  463. package/node_modules/node-datachannel/src/cpp/media-video-wrapper.cpp +0 -526
  464. package/node_modules/node-datachannel/src/cpp/media-video-wrapper.h +0 -56
  465. package/node_modules/node-datachannel/src/cpp/peer-connection-wrapper.cpp +0 -1298
  466. package/node_modules/node-datachannel/src/cpp/peer-connection-wrapper.h +0 -89
  467. package/node_modules/node-datachannel/src/cpp/rtc-wrapper.cpp +0 -205
  468. package/node_modules/node-datachannel/src/cpp/rtc-wrapper.h +0 -24
  469. package/node_modules/node-datachannel/src/cpp/thread-safe-callback.cpp +0 -57
  470. package/node_modules/node-datachannel/src/cpp/thread-safe-callback.h +0 -47
  471. package/node_modules/node-datachannel/src/cpp/web-socket-server-wrapper.cpp +0 -275
  472. package/node_modules/node-datachannel/src/cpp/web-socket-server-wrapper.h +0 -41
  473. package/node_modules/node-datachannel/src/cpp/web-socket-wrapper.cpp +0 -796
  474. package/node_modules/node-datachannel/src/cpp/web-socket-wrapper.h +0 -63
  475. package/node_modules/node-datachannel/src/index.ts +0 -9
  476. package/node_modules/node-datachannel/src/lib/datachannel-stream.ts +0 -100
  477. package/node_modules/node-datachannel/src/lib/index.ts +0 -290
  478. package/node_modules/node-datachannel/src/lib/node-datachannel.ts +0 -84
  479. package/node_modules/node-datachannel/src/lib/types.ts +0 -169
  480. package/node_modules/node-datachannel/src/lib/websocket-server.ts +0 -37
  481. package/node_modules/node-datachannel/src/lib/websocket.ts +0 -26
  482. package/node_modules/node-datachannel/src/polyfill/Events.ts +0 -82
  483. package/node_modules/node-datachannel/src/polyfill/Exception.ts +0 -37
  484. package/node_modules/node-datachannel/src/polyfill/README.md +0 -41
  485. package/node_modules/node-datachannel/src/polyfill/RTCCertificate.ts +0 -21
  486. package/node_modules/node-datachannel/src/polyfill/RTCDataChannel.ts +0 -225
  487. package/node_modules/node-datachannel/src/polyfill/RTCDtlsTransport.ts +0 -46
  488. package/node_modules/node-datachannel/src/polyfill/RTCError.ts +0 -78
  489. package/node_modules/node-datachannel/src/polyfill/RTCIceCandidate.ts +0 -128
  490. package/node_modules/node-datachannel/src/polyfill/RTCIceTransport.ts +0 -90
  491. package/node_modules/node-datachannel/src/polyfill/RTCPeerConnection.ts +0 -527
  492. package/node_modules/node-datachannel/src/polyfill/RTCSctpTransport.ts +0 -51
  493. package/node_modules/node-datachannel/src/polyfill/RTCSessionDescription.ts +0 -41
  494. package/node_modules/node-datachannel/src/polyfill/index.ts +0 -38
  495. package/node_modules/node-datachannel/tsconfig.json +0 -21
  496. package/node_modules/p-limit/index.d.ts +0 -38
  497. package/node_modules/p-limit/index.js +0 -57
  498. package/node_modules/p-limit/license +0 -9
  499. package/node_modules/p-limit/package.json +0 -52
  500. package/node_modules/p-limit/readme.md +0 -101
  501. package/node_modules/p-locate/index.d.ts +0 -64
  502. package/node_modules/p-locate/index.js +0 -52
  503. package/node_modules/p-locate/license +0 -9
  504. package/node_modules/p-locate/package.json +0 -53
  505. package/node_modules/p-locate/readme.md +0 -90
  506. package/node_modules/p-try/index.d.ts +0 -39
  507. package/node_modules/p-try/index.js +0 -9
  508. package/node_modules/p-try/license +0 -9
  509. package/node_modules/p-try/package.json +0 -42
  510. package/node_modules/p-try/readme.md +0 -58
  511. package/node_modules/path-exists/index.d.ts +0 -28
  512. package/node_modules/path-exists/index.js +0 -23
  513. package/node_modules/path-exists/license +0 -9
  514. package/node_modules/path-exists/package.json +0 -39
  515. package/node_modules/path-exists/readme.md +0 -52
  516. package/node_modules/pngjs/.eslintignore +0 -2
  517. package/node_modules/pngjs/.eslintrc.json +0 -19
  518. package/node_modules/pngjs/.prettierignore +0 -3
  519. package/node_modules/pngjs/LICENSE +0 -20
  520. package/node_modules/pngjs/README.md +0 -429
  521. package/node_modules/pngjs/browser.js +0 -16096
  522. package/node_modules/pngjs/coverage/lcov-report/base.css +0 -354
  523. package/node_modules/pngjs/coverage/lcov-report/bitmapper.js.html +0 -881
  524. package/node_modules/pngjs/coverage/lcov-report/bitpacker.js.html +0 -554
  525. package/node_modules/pngjs/coverage/lcov-report/block-navigation.js +0 -77
  526. package/node_modules/pngjs/coverage/lcov-report/chunkstream.js.html +0 -647
  527. package/node_modules/pngjs/coverage/lcov-report/constants.js.html +0 -176
  528. package/node_modules/pngjs/coverage/lcov-report/crc.js.html +0 -200
  529. package/node_modules/pngjs/coverage/lcov-report/favicon.png +0 -0
  530. package/node_modules/pngjs/coverage/lcov-report/filter-pack.js.html +0 -593
  531. package/node_modules/pngjs/coverage/lcov-report/filter-parse-async.js.html +0 -152
  532. package/node_modules/pngjs/coverage/lcov-report/filter-parse-sync.js.html +0 -143
  533. package/node_modules/pngjs/coverage/lcov-report/filter-parse.js.html +0 -611
  534. package/node_modules/pngjs/coverage/lcov-report/format-normaliser.js.html +0 -359
  535. package/node_modules/pngjs/coverage/lcov-report/index.html +0 -426
  536. package/node_modules/pngjs/coverage/lcov-report/interlace.js.html +0 -365
  537. package/node_modules/pngjs/coverage/lcov-report/packer-async.js.html +0 -230
  538. package/node_modules/pngjs/coverage/lcov-report/packer-sync.js.html +0 -248
  539. package/node_modules/pngjs/coverage/lcov-report/packer.js.html +0 -467
  540. package/node_modules/pngjs/coverage/lcov-report/paeth-predictor.js.html +0 -128
  541. package/node_modules/pngjs/coverage/lcov-report/parser-async.js.html +0 -575
  542. package/node_modules/pngjs/coverage/lcov-report/parser-sync.js.html +0 -404
  543. package/node_modules/pngjs/coverage/lcov-report/parser.js.html +0 -950
  544. package/node_modules/pngjs/coverage/lcov-report/png-sync.js.html +0 -116
  545. package/node_modules/pngjs/coverage/lcov-report/png.js.html +0 -662
  546. package/node_modules/pngjs/coverage/lcov-report/prettify.css +0 -101
  547. package/node_modules/pngjs/coverage/lcov-report/prettify.js +0 -1007
  548. package/node_modules/pngjs/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  549. package/node_modules/pngjs/coverage/lcov-report/sorter.js +0 -169
  550. package/node_modules/pngjs/coverage/lcov-report/sync-inflate.js.html +0 -584
  551. package/node_modules/pngjs/coverage/lcov-report/sync-reader.js.html +0 -215
  552. package/node_modules/pngjs/coverage/lcov.info +0 -2177
  553. package/node_modules/pngjs/lib/bitmapper.js +0 -267
  554. package/node_modules/pngjs/lib/bitpacker.js +0 -158
  555. package/node_modules/pngjs/lib/chunkstream.js +0 -189
  556. package/node_modules/pngjs/lib/constants.js +0 -32
  557. package/node_modules/pngjs/lib/crc.js +0 -40
  558. package/node_modules/pngjs/lib/filter-pack.js +0 -171
  559. package/node_modules/pngjs/lib/filter-parse-async.js +0 -24
  560. package/node_modules/pngjs/lib/filter-parse-sync.js +0 -21
  561. package/node_modules/pngjs/lib/filter-parse.js +0 -177
  562. package/node_modules/pngjs/lib/format-normaliser.js +0 -93
  563. package/node_modules/pngjs/lib/interlace.js +0 -95
  564. package/node_modules/pngjs/lib/packer-async.js +0 -50
  565. package/node_modules/pngjs/lib/packer-sync.js +0 -56
  566. package/node_modules/pngjs/lib/packer.js +0 -129
  567. package/node_modules/pngjs/lib/paeth-predictor.js +0 -16
  568. package/node_modules/pngjs/lib/parser-async.js +0 -165
  569. package/node_modules/pngjs/lib/parser-sync.js +0 -108
  570. package/node_modules/pngjs/lib/parser.js +0 -290
  571. package/node_modules/pngjs/lib/png-sync.js +0 -12
  572. package/node_modules/pngjs/lib/png.js +0 -194
  573. package/node_modules/pngjs/lib/sync-inflate.js +0 -168
  574. package/node_modules/pngjs/lib/sync-reader.js +0 -45
  575. package/node_modules/pngjs/package.json +0 -73
  576. package/node_modules/qrcode/README.md +0 -770
  577. package/node_modules/qrcode/bin/qrcode +0 -159
  578. package/node_modules/qrcode/helper/to-sjis-browser.js +0 -2
  579. package/node_modules/qrcode/helper/to-sjis.js +0 -105
  580. package/node_modules/qrcode/lib/browser.js +0 -76
  581. package/node_modules/qrcode/lib/can-promise.js +0 -7
  582. package/node_modules/qrcode/lib/core/alignment-pattern.js +0 -83
  583. package/node_modules/qrcode/lib/core/alphanumeric-data.js +0 -59
  584. package/node_modules/qrcode/lib/core/bit-buffer.js +0 -37
  585. package/node_modules/qrcode/lib/core/bit-matrix.js +0 -65
  586. package/node_modules/qrcode/lib/core/byte-data.js +0 -30
  587. package/node_modules/qrcode/lib/core/error-correction-code.js +0 -135
  588. package/node_modules/qrcode/lib/core/error-correction-level.js +0 -50
  589. package/node_modules/qrcode/lib/core/finder-pattern.js +0 -22
  590. package/node_modules/qrcode/lib/core/format-info.js +0 -29
  591. package/node_modules/qrcode/lib/core/galois-field.js +0 -69
  592. package/node_modules/qrcode/lib/core/kanji-data.js +0 -54
  593. package/node_modules/qrcode/lib/core/mask-pattern.js +0 -234
  594. package/node_modules/qrcode/lib/core/mode.js +0 -167
  595. package/node_modules/qrcode/lib/core/numeric-data.js +0 -43
  596. package/node_modules/qrcode/lib/core/polynomial.js +0 -62
  597. package/node_modules/qrcode/lib/core/qrcode.js +0 -495
  598. package/node_modules/qrcode/lib/core/reed-solomon-encoder.js +0 -56
  599. package/node_modules/qrcode/lib/core/regex.js +0 -31
  600. package/node_modules/qrcode/lib/core/segments.js +0 -330
  601. package/node_modules/qrcode/lib/core/utils.js +0 -63
  602. package/node_modules/qrcode/lib/core/version-check.js +0 -9
  603. package/node_modules/qrcode/lib/core/version.js +0 -163
  604. package/node_modules/qrcode/lib/index.js +0 -12
  605. package/node_modules/qrcode/lib/renderer/canvas.js +0 -63
  606. package/node_modules/qrcode/lib/renderer/png.js +0 -78
  607. package/node_modules/qrcode/lib/renderer/svg-tag.js +0 -81
  608. package/node_modules/qrcode/lib/renderer/svg.js +0 -19
  609. package/node_modules/qrcode/lib/renderer/terminal/terminal-small.js +0 -85
  610. package/node_modules/qrcode/lib/renderer/terminal/terminal.js +0 -49
  611. package/node_modules/qrcode/lib/renderer/terminal.js +0 -9
  612. package/node_modules/qrcode/lib/renderer/utf8.js +0 -71
  613. package/node_modules/qrcode/lib/renderer/utils.js +0 -99
  614. package/node_modules/qrcode/lib/server.js +0 -138
  615. package/node_modules/qrcode/license +0 -10
  616. package/node_modules/qrcode/package.json +0 -77
  617. package/node_modules/require-directory/.jshintrc +0 -67
  618. package/node_modules/require-directory/.npmignore +0 -1
  619. package/node_modules/require-directory/.travis.yml +0 -3
  620. package/node_modules/require-directory/LICENSE +0 -22
  621. package/node_modules/require-directory/README.markdown +0 -184
  622. package/node_modules/require-directory/index.js +0 -86
  623. package/node_modules/require-directory/package.json +0 -40
  624. package/node_modules/require-main-filename/CHANGELOG.md +0 -26
  625. package/node_modules/require-main-filename/LICENSE.txt +0 -14
  626. package/node_modules/require-main-filename/README.md +0 -26
  627. package/node_modules/require-main-filename/index.js +0 -18
  628. package/node_modules/require-main-filename/package.json +0 -35
  629. package/node_modules/semver/LICENSE +0 -15
  630. package/node_modules/semver/README.md +0 -680
  631. package/node_modules/semver/bin/semver.js +0 -195
  632. package/node_modules/semver/classes/comparator.js +0 -143
  633. package/node_modules/semver/classes/index.js +0 -7
  634. package/node_modules/semver/classes/range.js +0 -577
  635. package/node_modules/semver/classes/semver.js +0 -350
  636. package/node_modules/semver/functions/clean.js +0 -8
  637. package/node_modules/semver/functions/cmp.js +0 -54
  638. package/node_modules/semver/functions/coerce.js +0 -62
  639. package/node_modules/semver/functions/compare-build.js +0 -9
  640. package/node_modules/semver/functions/compare-loose.js +0 -5
  641. package/node_modules/semver/functions/compare.js +0 -7
  642. package/node_modules/semver/functions/diff.js +0 -60
  643. package/node_modules/semver/functions/eq.js +0 -5
  644. package/node_modules/semver/functions/gt.js +0 -5
  645. package/node_modules/semver/functions/gte.js +0 -5
  646. package/node_modules/semver/functions/inc.js +0 -21
  647. package/node_modules/semver/functions/lt.js +0 -5
  648. package/node_modules/semver/functions/lte.js +0 -5
  649. package/node_modules/semver/functions/major.js +0 -5
  650. package/node_modules/semver/functions/minor.js +0 -5
  651. package/node_modules/semver/functions/neq.js +0 -5
  652. package/node_modules/semver/functions/parse.js +0 -18
  653. package/node_modules/semver/functions/patch.js +0 -5
  654. package/node_modules/semver/functions/prerelease.js +0 -8
  655. package/node_modules/semver/functions/rcompare.js +0 -5
  656. package/node_modules/semver/functions/rsort.js +0 -5
  657. package/node_modules/semver/functions/satisfies.js +0 -12
  658. package/node_modules/semver/functions/sort.js +0 -5
  659. package/node_modules/semver/functions/truncate.js +0 -48
  660. package/node_modules/semver/functions/valid.js +0 -8
  661. package/node_modules/semver/index.js +0 -93
  662. package/node_modules/semver/internal/constants.js +0 -37
  663. package/node_modules/semver/internal/debug.js +0 -11
  664. package/node_modules/semver/internal/identifiers.js +0 -29
  665. package/node_modules/semver/internal/lrucache.js +0 -42
  666. package/node_modules/semver/internal/parse-options.js +0 -17
  667. package/node_modules/semver/internal/re.js +0 -223
  668. package/node_modules/semver/package.json +0 -78
  669. package/node_modules/semver/preload.js +0 -4
  670. package/node_modules/semver/range.bnf +0 -17
  671. package/node_modules/semver/ranges/gtr.js +0 -6
  672. package/node_modules/semver/ranges/intersects.js +0 -9
  673. package/node_modules/semver/ranges/ltr.js +0 -6
  674. package/node_modules/semver/ranges/max-satisfying.js +0 -27
  675. package/node_modules/semver/ranges/min-satisfying.js +0 -26
  676. package/node_modules/semver/ranges/min-version.js +0 -63
  677. package/node_modules/semver/ranges/outside.js +0 -82
  678. package/node_modules/semver/ranges/simplify.js +0 -49
  679. package/node_modules/semver/ranges/subset.js +0 -249
  680. package/node_modules/semver/ranges/to-comparators.js +0 -10
  681. package/node_modules/semver/ranges/valid.js +0 -13
  682. package/node_modules/set-blocking/CHANGELOG.md +0 -26
  683. package/node_modules/set-blocking/LICENSE.txt +0 -14
  684. package/node_modules/set-blocking/README.md +0 -31
  685. package/node_modules/set-blocking/index.js +0 -7
  686. package/node_modules/set-blocking/package.json +0 -42
  687. package/node_modules/sharp/LICENSE +0 -191
  688. package/node_modules/sharp/README.md +0 -112
  689. package/node_modules/sharp/dist/channel.cjs +0 -177
  690. package/node_modules/sharp/dist/channel.mjs +0 -177
  691. package/node_modules/sharp/dist/colour.cjs +0 -199
  692. package/node_modules/sharp/dist/colour.mjs +0 -199
  693. package/node_modules/sharp/dist/composite.cjs +0 -213
  694. package/node_modules/sharp/dist/composite.mjs +0 -213
  695. package/node_modules/sharp/dist/constructor.cjs +0 -511
  696. package/node_modules/sharp/dist/constructor.mjs +0 -511
  697. package/node_modules/sharp/dist/index.cjs +0 -25
  698. package/node_modules/sharp/dist/index.d.cts +0 -1999
  699. package/node_modules/sharp/dist/index.d.mts +0 -2046
  700. package/node_modules/sharp/dist/index.mjs +0 -25
  701. package/node_modules/sharp/dist/input.cjs +0 -819
  702. package/node_modules/sharp/dist/input.mjs +0 -819
  703. package/node_modules/sharp/dist/is.cjs +0 -143
  704. package/node_modules/sharp/dist/is.mjs +0 -143
  705. package/node_modules/sharp/dist/libvips.cjs +0 -212
  706. package/node_modules/sharp/dist/libvips.mjs +0 -212
  707. package/node_modules/sharp/dist/operation.cjs +0 -1002
  708. package/node_modules/sharp/dist/operation.mjs +0 -1002
  709. package/node_modules/sharp/dist/output.cjs +0 -1785
  710. package/node_modules/sharp/dist/output.mjs +0 -1785
  711. package/node_modules/sharp/dist/resize.cjs +0 -617
  712. package/node_modules/sharp/dist/resize.mjs +0 -617
  713. package/node_modules/sharp/dist/sharp.cjs +0 -174
  714. package/node_modules/sharp/dist/sharp.mjs +0 -174
  715. package/node_modules/sharp/dist/utility.cjs +0 -301
  716. package/node_modules/sharp/dist/utility.mjs +0 -301
  717. package/node_modules/sharp/install/build.js +0 -38
  718. package/node_modules/sharp/lib/index.d.ts +0 -1999
  719. package/node_modules/sharp/package.json +0 -227
  720. package/node_modules/sharp/src/binding.gyp +0 -303
  721. package/node_modules/sharp/src/common.cc +0 -1186
  722. package/node_modules/sharp/src/common.h +0 -421
  723. package/node_modules/sharp/src/metadata.cc +0 -404
  724. package/node_modules/sharp/src/metadata.h +0 -95
  725. package/node_modules/sharp/src/operations.cc +0 -516
  726. package/node_modules/sharp/src/operations.h +0 -137
  727. package/node_modules/sharp/src/pipeline.cc +0 -1948
  728. package/node_modules/sharp/src/pipeline.h +0 -422
  729. package/node_modules/sharp/src/sharp.cc +0 -43
  730. package/node_modules/sharp/src/stats.cc +0 -186
  731. package/node_modules/sharp/src/stats.h +0 -62
  732. package/node_modules/sharp/src/utilities.cc +0 -289
  733. package/node_modules/sharp/src/utilities.h +0 -22
  734. package/node_modules/string-width/index.d.ts +0 -29
  735. package/node_modules/string-width/index.js +0 -47
  736. package/node_modules/string-width/license +0 -9
  737. package/node_modules/string-width/package.json +0 -56
  738. package/node_modules/string-width/readme.md +0 -50
  739. package/node_modules/strip-ansi/index.d.ts +0 -17
  740. package/node_modules/strip-ansi/index.js +0 -4
  741. package/node_modules/strip-ansi/license +0 -9
  742. package/node_modules/strip-ansi/package.json +0 -54
  743. package/node_modules/strip-ansi/readme.md +0 -46
  744. package/node_modules/which-module/LICENSE +0 -13
  745. package/node_modules/which-module/README.md +0 -58
  746. package/node_modules/which-module/index.js +0 -9
  747. package/node_modules/which-module/package.json +0 -41
  748. package/node_modules/wrap-ansi/index.js +0 -186
  749. package/node_modules/wrap-ansi/license +0 -9
  750. package/node_modules/wrap-ansi/package.json +0 -61
  751. package/node_modules/wrap-ansi/readme.md +0 -97
  752. package/node_modules/ws/LICENSE +0 -20
  753. package/node_modules/ws/README.md +0 -548
  754. package/node_modules/ws/browser.js +0 -8
  755. package/node_modules/ws/index.js +0 -22
  756. package/node_modules/ws/lib/buffer-util.js +0 -131
  757. package/node_modules/ws/lib/constants.js +0 -19
  758. package/node_modules/ws/lib/event-target.js +0 -292
  759. package/node_modules/ws/lib/extension.js +0 -203
  760. package/node_modules/ws/lib/limiter.js +0 -55
  761. package/node_modules/ws/lib/permessage-deflate.js +0 -530
  762. package/node_modules/ws/lib/receiver.js +0 -743
  763. package/node_modules/ws/lib/sender.js +0 -607
  764. package/node_modules/ws/lib/stream.js +0 -161
  765. package/node_modules/ws/lib/subprotocol.js +0 -62
  766. package/node_modules/ws/lib/validation.js +0 -152
  767. package/node_modules/ws/lib/websocket-server.js +0 -562
  768. package/node_modules/ws/lib/websocket.js +0 -1407
  769. package/node_modules/ws/package.json +0 -74
  770. package/node_modules/ws/wrapper.mjs +0 -21
  771. package/node_modules/y18n/CHANGELOG.md +0 -35
  772. package/node_modules/y18n/LICENSE +0 -13
  773. package/node_modules/y18n/README.md +0 -109
  774. package/node_modules/y18n/index.js +0 -188
  775. package/node_modules/y18n/package.json +0 -39
  776. package/node_modules/yargs/CHANGELOG.md +0 -420
  777. package/node_modules/yargs/LICENSE +0 -21
  778. package/node_modules/yargs/README.md +0 -140
  779. package/node_modules/yargs/build/lib/apply-extends.d.ts +0 -2
  780. package/node_modules/yargs/build/lib/apply-extends.js +0 -65
  781. package/node_modules/yargs/build/lib/argsert.d.ts +0 -2
  782. package/node_modules/yargs/build/lib/argsert.js +0 -65
  783. package/node_modules/yargs/build/lib/command.d.ts +0 -64
  784. package/node_modules/yargs/build/lib/command.js +0 -416
  785. package/node_modules/yargs/build/lib/common-types.d.ts +0 -36
  786. package/node_modules/yargs/build/lib/common-types.js +0 -25
  787. package/node_modules/yargs/build/lib/completion-templates.d.ts +0 -2
  788. package/node_modules/yargs/build/lib/completion-templates.js +0 -50
  789. package/node_modules/yargs/build/lib/completion.d.ts +0 -21
  790. package/node_modules/yargs/build/lib/completion.js +0 -135
  791. package/node_modules/yargs/build/lib/is-promise.d.ts +0 -1
  792. package/node_modules/yargs/build/lib/is-promise.js +0 -9
  793. package/node_modules/yargs/build/lib/levenshtein.d.ts +0 -1
  794. package/node_modules/yargs/build/lib/levenshtein.js +0 -58
  795. package/node_modules/yargs/build/lib/middleware.d.ts +0 -10
  796. package/node_modules/yargs/build/lib/middleware.js +0 -57
  797. package/node_modules/yargs/build/lib/obj-filter.d.ts +0 -1
  798. package/node_modules/yargs/build/lib/obj-filter.js +0 -14
  799. package/node_modules/yargs/build/lib/parse-command.d.ts +0 -11
  800. package/node_modules/yargs/build/lib/parse-command.js +0 -36
  801. package/node_modules/yargs/build/lib/process-argv.d.ts +0 -2
  802. package/node_modules/yargs/build/lib/process-argv.js +0 -31
  803. package/node_modules/yargs/build/lib/usage.d.ts +0 -49
  804. package/node_modules/yargs/build/lib/usage.js +0 -540
  805. package/node_modules/yargs/build/lib/validation.d.ts +0 -34
  806. package/node_modules/yargs/build/lib/validation.js +0 -330
  807. package/node_modules/yargs/build/lib/yargs.d.ts +0 -274
  808. package/node_modules/yargs/build/lib/yargs.js +0 -1190
  809. package/node_modules/yargs/build/lib/yerror.d.ts +0 -4
  810. package/node_modules/yargs/build/lib/yerror.js +0 -11
  811. package/node_modules/yargs/index.js +0 -40
  812. package/node_modules/yargs/locales/be.json +0 -46
  813. package/node_modules/yargs/locales/de.json +0 -46
  814. package/node_modules/yargs/locales/en.json +0 -51
  815. package/node_modules/yargs/locales/es.json +0 -46
  816. package/node_modules/yargs/locales/fi.json +0 -49
  817. package/node_modules/yargs/locales/fr.json +0 -53
  818. package/node_modules/yargs/locales/hi.json +0 -49
  819. package/node_modules/yargs/locales/hu.json +0 -46
  820. package/node_modules/yargs/locales/id.json +0 -50
  821. package/node_modules/yargs/locales/it.json +0 -46
  822. package/node_modules/yargs/locales/ja.json +0 -51
  823. package/node_modules/yargs/locales/ko.json +0 -49
  824. package/node_modules/yargs/locales/nb.json +0 -44
  825. package/node_modules/yargs/locales/nl.json +0 -49
  826. package/node_modules/yargs/locales/nn.json +0 -44
  827. package/node_modules/yargs/locales/pirate.json +0 -13
  828. package/node_modules/yargs/locales/pl.json +0 -49
  829. package/node_modules/yargs/locales/pt.json +0 -45
  830. package/node_modules/yargs/locales/pt_BR.json +0 -48
  831. package/node_modules/yargs/locales/ru.json +0 -46
  832. package/node_modules/yargs/locales/th.json +0 -46
  833. package/node_modules/yargs/locales/tr.json +0 -48
  834. package/node_modules/yargs/locales/zh_CN.json +0 -48
  835. package/node_modules/yargs/locales/zh_TW.json +0 -47
  836. package/node_modules/yargs/package.json +0 -92
  837. package/node_modules/yargs/yargs.js +0 -14
  838. package/node_modules/yargs-parser/CHANGELOG.md +0 -601
  839. package/node_modules/yargs-parser/LICENSE.txt +0 -14
  840. package/node_modules/yargs-parser/README.md +0 -449
  841. package/node_modules/yargs-parser/index.js +0 -1032
  842. package/node_modules/yargs-parser/lib/tokenize-arg-string.js +0 -40
  843. 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
+ }