@marktrue/dsh-mobile-remote 3.2.1-alpha.1-app → 3.2.1-alpha.1

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 (349) hide show
  1. package/CHANGELOG.md +796 -0
  2. package/CONTRIBUTING.md +59 -0
  3. package/FAQ.md +111 -0
  4. package/README.md +253 -6
  5. package/cordis.patch.yml +14 -0
  6. package/docs/00-/345/274/200/345/217/221/346/200/273/347/272/262.md +122 -0
  7. package/docs/01-PRD.md +148 -0
  8. package/docs/02-architecture.md +249 -0
  9. package/docs/03-api.md +816 -0
  10. package/docs/04-security.md +96 -0
  11. package/docs/05-test-cases.md +326 -0
  12. package/docs/06-install-run.md +308 -0
  13. package/docs/07-user-manual.md +65 -0
  14. package/docs/08-/346/211/251/345/261/225/345/274/200/345/217/221/346/214/207/345/215/227.md +86 -0
  15. package/docs/09-compatibility.md +195 -0
  16. package/docs/10-release.md +927 -0
  17. package/docs/screenshots/01-home.png +0 -0
  18. package/docs/screenshots/02-notifications.png +0 -0
  19. package/docs/screenshots/03-sessions.png +0 -0
  20. package/docs/screenshots/04-chat.png +0 -0
  21. package/docs/screenshots/05-settings.png +0 -0
  22. package/docs/screenshots/06-new-session.png +0 -0
  23. package/docs/screenshots/pgy-appstore.jpg +0 -0
  24. package/docs/screenshots/pgy-mobile-app.jpg +0 -0
  25. package/docs/screenshots/pgy-pc-client.jpg +0 -0
  26. package/lib/account-usage.js +145 -0
  27. package/lib/app-alignment.js +112 -0
  28. package/lib/app-carrier-store.js +1972 -0
  29. package/lib/app-carrier.js +602 -0
  30. package/lib/client.js +706 -0
  31. package/lib/desktop-form.js +738 -0
  32. package/lib/endpoint-registry.js +162 -0
  33. package/lib/git-read-bundled-provider.js +255 -0
  34. package/lib/git-read-service.js +322 -0
  35. package/lib/index.js +9292 -0
  36. package/lib/plugin-content-digest.js +80 -0
  37. package/lib/plugin-self-update.js +758 -0
  38. package/lib/plugin-update-controller.js +95 -0
  39. package/lib/plugin-update-transaction.js +322 -0
  40. package/lib/plugin-update.js +309 -0
  41. package/lib/runtime-dependency-snapshot.js +345 -0
  42. package/lib/session-title-cache.js +123 -0
  43. package/lib/session-title-refresh.js +261 -0
  44. package/lib/update-fetch.js +24 -0
  45. package/lib/update-lock-arbiter.js +158 -0
  46. package/lib/update-supervisor.js +312 -0
  47. package/node_modules/ansi-regex/index.d.ts +37 -0
  48. package/node_modules/ansi-regex/index.js +10 -0
  49. package/node_modules/ansi-regex/license +9 -0
  50. package/node_modules/ansi-regex/package.json +55 -0
  51. package/node_modules/ansi-regex/readme.md +78 -0
  52. package/node_modules/ansi-styles/index.d.ts +345 -0
  53. package/node_modules/ansi-styles/index.js +163 -0
  54. package/node_modules/ansi-styles/license +9 -0
  55. package/node_modules/ansi-styles/package.json +56 -0
  56. package/node_modules/ansi-styles/readme.md +152 -0
  57. package/node_modules/camelcase/index.d.ts +63 -0
  58. package/node_modules/camelcase/index.js +76 -0
  59. package/node_modules/camelcase/license +9 -0
  60. package/node_modules/camelcase/package.json +43 -0
  61. package/node_modules/camelcase/readme.md +99 -0
  62. package/node_modules/cliui/CHANGELOG.md +76 -0
  63. package/node_modules/cliui/LICENSE.txt +14 -0
  64. package/node_modules/cliui/README.md +115 -0
  65. package/node_modules/cliui/index.js +354 -0
  66. package/node_modules/cliui/package.json +65 -0
  67. package/node_modules/color-convert/CHANGELOG.md +54 -0
  68. package/node_modules/color-convert/LICENSE +21 -0
  69. package/node_modules/color-convert/README.md +68 -0
  70. package/node_modules/color-convert/conversions.js +839 -0
  71. package/node_modules/color-convert/index.js +81 -0
  72. package/node_modules/color-convert/package.json +48 -0
  73. package/node_modules/color-convert/route.js +97 -0
  74. package/node_modules/color-name/LICENSE +8 -0
  75. package/node_modules/color-name/README.md +11 -0
  76. package/node_modules/color-name/index.js +152 -0
  77. package/node_modules/color-name/package.json +28 -0
  78. package/node_modules/decamelize/index.js +13 -0
  79. package/node_modules/decamelize/license +21 -0
  80. package/node_modules/decamelize/package.json +38 -0
  81. package/node_modules/decamelize/readme.md +48 -0
  82. package/node_modules/dijkstrajs/.travis.yml +4 -0
  83. package/node_modules/dijkstrajs/CONTRIBUTING.md +8 -0
  84. package/node_modules/dijkstrajs/LICENSE.md +19 -0
  85. package/node_modules/dijkstrajs/README.md +18 -0
  86. package/node_modules/dijkstrajs/dijkstra.js +165 -0
  87. package/node_modules/dijkstrajs/package.json +60 -0
  88. package/node_modules/dijkstrajs/test/dijkstra.test.js +96 -0
  89. package/node_modules/emoji-regex/LICENSE-MIT.txt +20 -0
  90. package/node_modules/emoji-regex/README.md +73 -0
  91. package/node_modules/emoji-regex/es2015/index.js +6 -0
  92. package/node_modules/emoji-regex/es2015/text.js +6 -0
  93. package/node_modules/emoji-regex/index.d.ts +23 -0
  94. package/node_modules/emoji-regex/index.js +6 -0
  95. package/node_modules/emoji-regex/package.json +50 -0
  96. package/node_modules/emoji-regex/text.js +6 -0
  97. package/node_modules/find-up/index.d.ts +137 -0
  98. package/node_modules/find-up/index.js +89 -0
  99. package/node_modules/find-up/license +9 -0
  100. package/node_modules/find-up/package.json +53 -0
  101. package/node_modules/find-up/readme.md +156 -0
  102. package/node_modules/get-caller-file/LICENSE.md +6 -0
  103. package/node_modules/get-caller-file/README.md +41 -0
  104. package/node_modules/get-caller-file/index.d.ts +2 -0
  105. package/node_modules/get-caller-file/index.js +22 -0
  106. package/node_modules/get-caller-file/index.js.map +1 -0
  107. package/node_modules/get-caller-file/package.json +42 -0
  108. package/node_modules/is-fullwidth-code-point/index.d.ts +17 -0
  109. package/node_modules/is-fullwidth-code-point/index.js +50 -0
  110. package/node_modules/is-fullwidth-code-point/license +9 -0
  111. package/node_modules/is-fullwidth-code-point/package.json +42 -0
  112. package/node_modules/is-fullwidth-code-point/readme.md +39 -0
  113. package/node_modules/locate-path/index.d.ts +83 -0
  114. package/node_modules/locate-path/index.js +65 -0
  115. package/node_modules/locate-path/license +9 -0
  116. package/node_modules/locate-path/package.json +45 -0
  117. package/node_modules/locate-path/readme.md +122 -0
  118. package/node_modules/p-limit/index.d.ts +38 -0
  119. package/node_modules/p-limit/index.js +57 -0
  120. package/node_modules/p-limit/license +9 -0
  121. package/node_modules/p-limit/package.json +52 -0
  122. package/node_modules/p-limit/readme.md +101 -0
  123. package/node_modules/p-locate/index.d.ts +64 -0
  124. package/node_modules/p-locate/index.js +52 -0
  125. package/node_modules/p-locate/license +9 -0
  126. package/node_modules/p-locate/package.json +53 -0
  127. package/node_modules/p-locate/readme.md +90 -0
  128. package/node_modules/p-try/index.d.ts +39 -0
  129. package/node_modules/p-try/index.js +9 -0
  130. package/node_modules/p-try/license +9 -0
  131. package/node_modules/p-try/package.json +42 -0
  132. package/node_modules/p-try/readme.md +58 -0
  133. package/node_modules/path-exists/index.d.ts +28 -0
  134. package/node_modules/path-exists/index.js +23 -0
  135. package/node_modules/path-exists/license +9 -0
  136. package/node_modules/path-exists/package.json +39 -0
  137. package/node_modules/path-exists/readme.md +52 -0
  138. package/node_modules/pngjs/.eslintignore +2 -0
  139. package/node_modules/pngjs/.eslintrc.json +19 -0
  140. package/node_modules/pngjs/.prettierignore +3 -0
  141. package/node_modules/pngjs/LICENSE +20 -0
  142. package/node_modules/pngjs/README.md +429 -0
  143. package/node_modules/pngjs/browser.js +16096 -0
  144. package/node_modules/pngjs/coverage/lcov-report/base.css +354 -0
  145. package/node_modules/pngjs/coverage/lcov-report/bitmapper.js.html +881 -0
  146. package/node_modules/pngjs/coverage/lcov-report/bitpacker.js.html +554 -0
  147. package/node_modules/pngjs/coverage/lcov-report/block-navigation.js +77 -0
  148. package/node_modules/pngjs/coverage/lcov-report/chunkstream.js.html +647 -0
  149. package/node_modules/pngjs/coverage/lcov-report/constants.js.html +176 -0
  150. package/node_modules/pngjs/coverage/lcov-report/crc.js.html +200 -0
  151. package/node_modules/pngjs/coverage/lcov-report/favicon.png +0 -0
  152. package/node_modules/pngjs/coverage/lcov-report/filter-pack.js.html +593 -0
  153. package/node_modules/pngjs/coverage/lcov-report/filter-parse-async.js.html +152 -0
  154. package/node_modules/pngjs/coverage/lcov-report/filter-parse-sync.js.html +143 -0
  155. package/node_modules/pngjs/coverage/lcov-report/filter-parse.js.html +611 -0
  156. package/node_modules/pngjs/coverage/lcov-report/format-normaliser.js.html +359 -0
  157. package/node_modules/pngjs/coverage/lcov-report/index.html +426 -0
  158. package/node_modules/pngjs/coverage/lcov-report/interlace.js.html +365 -0
  159. package/node_modules/pngjs/coverage/lcov-report/packer-async.js.html +230 -0
  160. package/node_modules/pngjs/coverage/lcov-report/packer-sync.js.html +248 -0
  161. package/node_modules/pngjs/coverage/lcov-report/packer.js.html +467 -0
  162. package/node_modules/pngjs/coverage/lcov-report/paeth-predictor.js.html +128 -0
  163. package/node_modules/pngjs/coverage/lcov-report/parser-async.js.html +575 -0
  164. package/node_modules/pngjs/coverage/lcov-report/parser-sync.js.html +404 -0
  165. package/node_modules/pngjs/coverage/lcov-report/parser.js.html +950 -0
  166. package/node_modules/pngjs/coverage/lcov-report/png-sync.js.html +116 -0
  167. package/node_modules/pngjs/coverage/lcov-report/png.js.html +662 -0
  168. package/node_modules/pngjs/coverage/lcov-report/prettify.css +101 -0
  169. package/node_modules/pngjs/coverage/lcov-report/prettify.js +1007 -0
  170. package/node_modules/pngjs/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  171. package/node_modules/pngjs/coverage/lcov-report/sorter.js +169 -0
  172. package/node_modules/pngjs/coverage/lcov-report/sync-inflate.js.html +584 -0
  173. package/node_modules/pngjs/coverage/lcov-report/sync-reader.js.html +215 -0
  174. package/node_modules/pngjs/coverage/lcov.info +2177 -0
  175. package/node_modules/pngjs/lib/bitmapper.js +267 -0
  176. package/node_modules/pngjs/lib/bitpacker.js +158 -0
  177. package/node_modules/pngjs/lib/chunkstream.js +189 -0
  178. package/node_modules/pngjs/lib/constants.js +32 -0
  179. package/node_modules/pngjs/lib/crc.js +40 -0
  180. package/node_modules/pngjs/lib/filter-pack.js +171 -0
  181. package/node_modules/pngjs/lib/filter-parse-async.js +24 -0
  182. package/node_modules/pngjs/lib/filter-parse-sync.js +21 -0
  183. package/node_modules/pngjs/lib/filter-parse.js +177 -0
  184. package/node_modules/pngjs/lib/format-normaliser.js +93 -0
  185. package/node_modules/pngjs/lib/interlace.js +95 -0
  186. package/node_modules/pngjs/lib/packer-async.js +50 -0
  187. package/node_modules/pngjs/lib/packer-sync.js +56 -0
  188. package/node_modules/pngjs/lib/packer.js +129 -0
  189. package/node_modules/pngjs/lib/paeth-predictor.js +16 -0
  190. package/node_modules/pngjs/lib/parser-async.js +165 -0
  191. package/node_modules/pngjs/lib/parser-sync.js +108 -0
  192. package/node_modules/pngjs/lib/parser.js +290 -0
  193. package/node_modules/pngjs/lib/png-sync.js +12 -0
  194. package/node_modules/pngjs/lib/png.js +194 -0
  195. package/node_modules/pngjs/lib/sync-inflate.js +168 -0
  196. package/node_modules/pngjs/lib/sync-reader.js +45 -0
  197. package/node_modules/pngjs/package.json +73 -0
  198. package/node_modules/qrcode/README.md +770 -0
  199. package/node_modules/qrcode/bin/qrcode +159 -0
  200. package/node_modules/qrcode/helper/to-sjis-browser.js +2 -0
  201. package/node_modules/qrcode/helper/to-sjis.js +105 -0
  202. package/node_modules/qrcode/lib/browser.js +76 -0
  203. package/node_modules/qrcode/lib/can-promise.js +7 -0
  204. package/node_modules/qrcode/lib/core/alignment-pattern.js +83 -0
  205. package/node_modules/qrcode/lib/core/alphanumeric-data.js +59 -0
  206. package/node_modules/qrcode/lib/core/bit-buffer.js +37 -0
  207. package/node_modules/qrcode/lib/core/bit-matrix.js +65 -0
  208. package/node_modules/qrcode/lib/core/byte-data.js +30 -0
  209. package/node_modules/qrcode/lib/core/error-correction-code.js +135 -0
  210. package/node_modules/qrcode/lib/core/error-correction-level.js +50 -0
  211. package/node_modules/qrcode/lib/core/finder-pattern.js +22 -0
  212. package/node_modules/qrcode/lib/core/format-info.js +29 -0
  213. package/node_modules/qrcode/lib/core/galois-field.js +69 -0
  214. package/node_modules/qrcode/lib/core/kanji-data.js +54 -0
  215. package/node_modules/qrcode/lib/core/mask-pattern.js +234 -0
  216. package/node_modules/qrcode/lib/core/mode.js +167 -0
  217. package/node_modules/qrcode/lib/core/numeric-data.js +43 -0
  218. package/node_modules/qrcode/lib/core/polynomial.js +62 -0
  219. package/node_modules/qrcode/lib/core/qrcode.js +495 -0
  220. package/node_modules/qrcode/lib/core/reed-solomon-encoder.js +56 -0
  221. package/node_modules/qrcode/lib/core/regex.js +31 -0
  222. package/node_modules/qrcode/lib/core/segments.js +330 -0
  223. package/node_modules/qrcode/lib/core/utils.js +63 -0
  224. package/node_modules/qrcode/lib/core/version-check.js +9 -0
  225. package/node_modules/qrcode/lib/core/version.js +163 -0
  226. package/node_modules/qrcode/lib/index.js +12 -0
  227. package/node_modules/qrcode/lib/renderer/canvas.js +63 -0
  228. package/node_modules/qrcode/lib/renderer/png.js +78 -0
  229. package/node_modules/qrcode/lib/renderer/svg-tag.js +81 -0
  230. package/node_modules/qrcode/lib/renderer/svg.js +19 -0
  231. package/node_modules/qrcode/lib/renderer/terminal/terminal-small.js +85 -0
  232. package/node_modules/qrcode/lib/renderer/terminal/terminal.js +49 -0
  233. package/node_modules/qrcode/lib/renderer/terminal.js +9 -0
  234. package/node_modules/qrcode/lib/renderer/utf8.js +71 -0
  235. package/node_modules/qrcode/lib/renderer/utils.js +99 -0
  236. package/node_modules/qrcode/lib/server.js +138 -0
  237. package/node_modules/qrcode/license +10 -0
  238. package/node_modules/qrcode/package.json +77 -0
  239. package/node_modules/require-directory/.jshintrc +67 -0
  240. package/node_modules/require-directory/.npmignore +1 -0
  241. package/node_modules/require-directory/.travis.yml +3 -0
  242. package/node_modules/require-directory/LICENSE +22 -0
  243. package/node_modules/require-directory/README.markdown +184 -0
  244. package/node_modules/require-directory/index.js +86 -0
  245. package/node_modules/require-directory/package.json +40 -0
  246. package/node_modules/require-main-filename/CHANGELOG.md +26 -0
  247. package/node_modules/require-main-filename/LICENSE.txt +14 -0
  248. package/node_modules/require-main-filename/README.md +26 -0
  249. package/node_modules/require-main-filename/index.js +18 -0
  250. package/node_modules/require-main-filename/package.json +35 -0
  251. package/node_modules/set-blocking/CHANGELOG.md +26 -0
  252. package/node_modules/set-blocking/LICENSE.txt +14 -0
  253. package/node_modules/set-blocking/README.md +31 -0
  254. package/node_modules/set-blocking/index.js +7 -0
  255. package/node_modules/set-blocking/package.json +42 -0
  256. package/node_modules/string-width/index.d.ts +29 -0
  257. package/node_modules/string-width/index.js +47 -0
  258. package/node_modules/string-width/license +9 -0
  259. package/node_modules/string-width/package.json +56 -0
  260. package/node_modules/string-width/readme.md +50 -0
  261. package/node_modules/strip-ansi/index.d.ts +17 -0
  262. package/node_modules/strip-ansi/index.js +4 -0
  263. package/node_modules/strip-ansi/license +9 -0
  264. package/node_modules/strip-ansi/package.json +54 -0
  265. package/node_modules/strip-ansi/readme.md +46 -0
  266. package/node_modules/which-module/LICENSE +13 -0
  267. package/node_modules/which-module/README.md +58 -0
  268. package/node_modules/which-module/index.js +9 -0
  269. package/node_modules/which-module/package.json +41 -0
  270. package/node_modules/wrap-ansi/index.js +186 -0
  271. package/node_modules/wrap-ansi/license +9 -0
  272. package/node_modules/wrap-ansi/package.json +61 -0
  273. package/node_modules/wrap-ansi/readme.md +97 -0
  274. package/node_modules/y18n/CHANGELOG.md +35 -0
  275. package/node_modules/y18n/LICENSE +13 -0
  276. package/node_modules/y18n/README.md +109 -0
  277. package/node_modules/y18n/index.js +188 -0
  278. package/node_modules/y18n/package.json +39 -0
  279. package/node_modules/yargs/CHANGELOG.md +420 -0
  280. package/node_modules/yargs/LICENSE +21 -0
  281. package/node_modules/yargs/README.md +140 -0
  282. package/node_modules/yargs/build/lib/apply-extends.d.ts +2 -0
  283. package/node_modules/yargs/build/lib/apply-extends.js +65 -0
  284. package/node_modules/yargs/build/lib/argsert.d.ts +2 -0
  285. package/node_modules/yargs/build/lib/argsert.js +65 -0
  286. package/node_modules/yargs/build/lib/command.d.ts +64 -0
  287. package/node_modules/yargs/build/lib/command.js +416 -0
  288. package/node_modules/yargs/build/lib/common-types.d.ts +36 -0
  289. package/node_modules/yargs/build/lib/common-types.js +25 -0
  290. package/node_modules/yargs/build/lib/completion-templates.d.ts +2 -0
  291. package/node_modules/yargs/build/lib/completion-templates.js +50 -0
  292. package/node_modules/yargs/build/lib/completion.d.ts +21 -0
  293. package/node_modules/yargs/build/lib/completion.js +135 -0
  294. package/node_modules/yargs/build/lib/is-promise.d.ts +1 -0
  295. package/node_modules/yargs/build/lib/is-promise.js +9 -0
  296. package/node_modules/yargs/build/lib/levenshtein.d.ts +1 -0
  297. package/node_modules/yargs/build/lib/levenshtein.js +58 -0
  298. package/node_modules/yargs/build/lib/middleware.d.ts +10 -0
  299. package/node_modules/yargs/build/lib/middleware.js +57 -0
  300. package/node_modules/yargs/build/lib/obj-filter.d.ts +1 -0
  301. package/node_modules/yargs/build/lib/obj-filter.js +14 -0
  302. package/node_modules/yargs/build/lib/parse-command.d.ts +11 -0
  303. package/node_modules/yargs/build/lib/parse-command.js +36 -0
  304. package/node_modules/yargs/build/lib/process-argv.d.ts +2 -0
  305. package/node_modules/yargs/build/lib/process-argv.js +31 -0
  306. package/node_modules/yargs/build/lib/usage.d.ts +49 -0
  307. package/node_modules/yargs/build/lib/usage.js +540 -0
  308. package/node_modules/yargs/build/lib/validation.d.ts +34 -0
  309. package/node_modules/yargs/build/lib/validation.js +330 -0
  310. package/node_modules/yargs/build/lib/yargs.d.ts +274 -0
  311. package/node_modules/yargs/build/lib/yargs.js +1190 -0
  312. package/node_modules/yargs/build/lib/yerror.d.ts +4 -0
  313. package/node_modules/yargs/build/lib/yerror.js +11 -0
  314. package/node_modules/yargs/index.js +40 -0
  315. package/node_modules/yargs/locales/be.json +46 -0
  316. package/node_modules/yargs/locales/de.json +46 -0
  317. package/node_modules/yargs/locales/en.json +51 -0
  318. package/node_modules/yargs/locales/es.json +46 -0
  319. package/node_modules/yargs/locales/fi.json +49 -0
  320. package/node_modules/yargs/locales/fr.json +53 -0
  321. package/node_modules/yargs/locales/hi.json +49 -0
  322. package/node_modules/yargs/locales/hu.json +46 -0
  323. package/node_modules/yargs/locales/id.json +50 -0
  324. package/node_modules/yargs/locales/it.json +46 -0
  325. package/node_modules/yargs/locales/ja.json +51 -0
  326. package/node_modules/yargs/locales/ko.json +49 -0
  327. package/node_modules/yargs/locales/nb.json +44 -0
  328. package/node_modules/yargs/locales/nl.json +49 -0
  329. package/node_modules/yargs/locales/nn.json +44 -0
  330. package/node_modules/yargs/locales/pirate.json +13 -0
  331. package/node_modules/yargs/locales/pl.json +49 -0
  332. package/node_modules/yargs/locales/pt.json +45 -0
  333. package/node_modules/yargs/locales/pt_BR.json +48 -0
  334. package/node_modules/yargs/locales/ru.json +46 -0
  335. package/node_modules/yargs/locales/th.json +46 -0
  336. package/node_modules/yargs/locales/tr.json +48 -0
  337. package/node_modules/yargs/locales/zh_CN.json +48 -0
  338. package/node_modules/yargs/locales/zh_TW.json +47 -0
  339. package/node_modules/yargs/package.json +92 -0
  340. package/node_modules/yargs/yargs.js +14 -0
  341. package/node_modules/yargs-parser/CHANGELOG.md +601 -0
  342. package/node_modules/yargs-parser/LICENSE.txt +14 -0
  343. package/node_modules/yargs-parser/README.md +449 -0
  344. package/node_modules/yargs-parser/index.js +1032 -0
  345. package/node_modules/yargs-parser/lib/tokenize-arg-string.js +40 -0
  346. package/node_modules/yargs-parser/package.json +46 -0
  347. package/package.json +65 -10
  348. package/DSH-Remote-v3.2.1.apk +0 -4
  349. package/manifest.json +0 -21
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,145 @@
1
+ // 用量与额度领域归一化:保持无运行时依赖,便于服务端单测与其它宿主复用。
2
+
3
+ /** 额度窗口标签:优先使用 provider 约定名称,未知窗口保持稳定可读。 */
4
+ export function usageWindowLabel(seconds) {
5
+ const value = Number(seconds);
6
+ if (!Number.isFinite(value) || value <= 0) return null;
7
+ if (value === 18_000) return '5h';
8
+ if (value === 604_800) return 'weekly';
9
+ if (value === 2_592_000) return 'monthly';
10
+ if (value % 604_800 === 0) return `${value / 604_800}w`;
11
+ if (value % 3_600 === 0) return `${value / 3_600}h`;
12
+ if (value % 60 === 0) return `${value / 60}m`;
13
+ return `${value}s`;
14
+ }
15
+
16
+ function finiteNumber(value) {
17
+ if (value === null || value === undefined || value === '' || typeof value === 'boolean') return undefined;
18
+ const number = typeof value === 'number' ? value : Number(value);
19
+ return Number.isFinite(number) ? number : undefined;
20
+ }
21
+
22
+ function clampPercent(value) {
23
+ const number = finiteNumber(value);
24
+ return number === undefined || number < 0 || number > 100 ? undefined : number;
25
+ }
26
+
27
+ function isoFromUnixSeconds(value) {
28
+ const seconds = finiteNumber(value);
29
+ if (seconds === undefined || seconds <= 0) return undefined;
30
+ const date = new Date(seconds * 1000);
31
+ return Number.isNaN(date.getTime()) ? undefined : date.toISOString();
32
+ }
33
+
34
+ function isoFromDate(value) {
35
+ if (typeof value !== 'string' || value.trim() === '') return undefined;
36
+ const date = new Date(value);
37
+ return Number.isNaN(date.getTime()) ? undefined : date.toISOString();
38
+ }
39
+
40
+ /** DeepSeek /user/balance 的顶层投影;优先选择 CNY 余额项。 */
41
+ export function normalizeDeepSeekBalance(data) {
42
+ const infos = data && typeof data === 'object' && !Array.isArray(data) ? data.balance_infos : undefined;
43
+ const validInfos = Array.isArray(infos) ? infos.filter((item) => item && typeof item === 'object' && !Array.isArray(item)) : [];
44
+ const first = validInfos.find((item) => item.currency === 'CNY') ?? validInfos[0];
45
+ const amount = first ? finiteNumber(first.total_balance) : undefined;
46
+ if (!first || amount === undefined) throw new Error('invalid deepseek balance');
47
+ return {
48
+ amount: String(first.total_balance),
49
+ currency: typeof first.currency === 'string' && first.currency !== '' ? first.currency : 'CNY',
50
+ available: data.is_available !== false && first.is_available !== false,
51
+ };
52
+ }
53
+
54
+ /**
55
+ * dsh-codex-connect 的无密钥投影 → 手机额度领域模型。
56
+ * 保留主 bucket 与 additional_rate_limits 的全部有效窗口,仅返回百分比/金额/窗口,不接触 OAuth token。
57
+ */
58
+ export function normalizeCodexUsage(usage) {
59
+ if (!usage || typeof usage !== 'object' || Array.isArray(usage)) throw new Error('invalid codex usage');
60
+ if (usage.rateLimits !== undefined && !Array.isArray(usage.rateLimits)) throw new Error('invalid codex rate limits');
61
+ const rateLimits = (usage.rateLimits ?? []).filter((bucket) => bucket && typeof bucket === 'object' && !Array.isArray(bucket));
62
+ const primaryIndex = rateLimits.findIndex((bucket) => bucket.id === 'codex');
63
+ const orderedBuckets = primaryIndex >= 0
64
+ ? [rateLimits[primaryIndex], ...rateLimits.filter((_, index) => index !== primaryIndex)]
65
+ : rateLimits;
66
+ const windows = [];
67
+ for (const [bucketIndex, bucket] of orderedBuckets.entries()) {
68
+ if (!Array.isArray(bucket.windows)) continue;
69
+ const bucketName = typeof bucket.name === 'string' && bucket.name.trim() !== ''
70
+ ? bucket.name.trim().slice(0, 80)
71
+ : typeof bucket.id === 'string' && bucket.id.trim() !== '' ? bucket.id.trim().slice(0, 80) : undefined;
72
+ const seenInBucket = new Set();
73
+ for (const item of bucket.windows) {
74
+ if (!item || typeof item !== 'object' || Array.isArray(item)) continue;
75
+ const baseWindow = usageWindowLabel(item.windowSeconds);
76
+ const remainingPercent = clampPercent(item.remainingPercent);
77
+ const resetAt = isoFromUnixSeconds(item.resetAt);
78
+ if (!baseWindow || seenInBucket.has(baseWindow) || remainingPercent === undefined) continue;
79
+ seenInBucket.add(baseWindow);
80
+ const window = bucketIndex === 0 || !bucketName ? baseWindow : `${bucketName} · ${baseWindow}`;
81
+ windows.push({ window, remainingPercent, ...(resetAt ? { resetAt } : {}) });
82
+ }
83
+ }
84
+ const individual = usage.individualLimit;
85
+ let individualLimit;
86
+ if (individual && typeof individual === 'object' && !Array.isArray(individual)) {
87
+ const limit = finiteNumber(individual.limit);
88
+ const used = finiteNumber(individual.used);
89
+ const remaining = finiteNumber(individual.remaining);
90
+ const remainingPercent = clampPercent(individual.remainingPercent ?? (limit > 0 && remaining !== undefined ? remaining / limit * 100 : undefined));
91
+ if (limit !== undefined && used !== undefined && remaining !== undefined && limit > 0 && remainingPercent !== undefined) {
92
+ individualLimit = {
93
+ limit: String(individual.limit),
94
+ used: String(individual.used),
95
+ remaining: String(individual.remaining),
96
+ remainingPercent,
97
+ };
98
+ }
99
+ }
100
+ const credits = usage.credits;
101
+ let codexCredits;
102
+ if (credits && typeof credits === 'object' && !Array.isArray(credits) && typeof credits.unlimited === 'boolean') {
103
+ if (credits.unlimited) {
104
+ codexCredits = { unlimited: true };
105
+ } else if (typeof credits.balance === 'string' && credits.balance.trim() !== '') {
106
+ codexCredits = { unlimited: false, balance: credits.balance };
107
+ } else if (finiteNumber(credits.balance) !== undefined) {
108
+ codexCredits = { unlimited: false, balance: String(credits.balance) };
109
+ } else {
110
+ // balance 是可选字段,但 unlimited=false 仍是一个有效、可展示的 Credits 状态。
111
+ codexCredits = { unlimited: false };
112
+ }
113
+ }
114
+ if (windows.length === 0 && individualLimit === undefined && codexCredits === undefined) throw new Error('codex usage has no usable allowance');
115
+ return {
116
+ windows,
117
+ ...(individualLimit ? { individualLimit } : {}),
118
+ ...(codexCredits ? { credits: codexCredits } : {}),
119
+ };
120
+ }
121
+
122
+ /** OpenCode Go usage payload → 剩余百分比窗口;无效窗口单独跳过,限流窗口保留。 */
123
+ export function normalizeOpenCodeUsage(payload) {
124
+ const usage = payload && typeof payload === 'object' && !Array.isArray(payload) ? (payload.usage ?? payload) : undefined;
125
+ if (!usage || typeof usage !== 'object' || Array.isArray(usage)) throw new Error('invalid opencode usage');
126
+ const windows = [];
127
+ for (const [key, label] of [['rolling', '5h'], ['weekly', 'weekly'], ['monthly', 'monthly']]) {
128
+ const detail = usage[key];
129
+ if (!detail || typeof detail !== 'object' || Array.isArray(detail)) continue;
130
+ const status = detail.status;
131
+ if (status !== undefined && status !== null && status !== 'ok' && status !== 'rate-limited') continue;
132
+ const usedPercent = clampPercent(detail.percent);
133
+ if (usedPercent === undefined) continue;
134
+ // percent=0 时 OpenCode 返回的是 now+window 占位值,不是可展示的 resetAt。
135
+ const resetAt = usedPercent === 0 ? undefined : isoFromDate(detail.resetsAt);
136
+ windows.push({
137
+ window: label,
138
+ remainingPercent: 100 - usedPercent,
139
+ ...(status === 'rate-limited' ? { limited: true } : {}),
140
+ ...(resetAt ? { resetAt } : {}),
141
+ });
142
+ }
143
+ if (windows.length === 0) throw new Error('opencode usage has no usable windows');
144
+ return { windows };
145
+ }
@@ -0,0 +1,112 @@
1
+ // 两端对齐状态(CONTEXT「对齐提示」)。
2
+ //
3
+ // 判据是**版本号**,且只用于决定**提示文案**——不参与任何能力可用性判定
4
+ // (能力看声明,见 ADR 0017 与 ADR 0019 的三条判据分离)。
5
+ // 比较只看 core `X.Y.Z`:App 的 `+build` 是它自己的构建号,同一发布周期内每次构建
6
+ // 都不同;插件可能是 prerelease(如 `3.2.1-alpha.1`,发布通道用)。两者都不参与配对,
7
+ // 因此插件 `3.2.1-alpha.1` 与 App `3.2.1+24` 按 core `3.2.1` 视为对齐。
8
+ //
9
+ // 自举:已装在用户手机上的旧 App 不会上报版本头,因此「头缺失」本身就是
10
+ // 「这是旧 App」的可靠信号——PC 端据此就能提示,不必等 App 先升级。
11
+ import { parseVersion } from "./plugin-update.js";
12
+
13
+ /** App 上报自身版本所用的请求头。 */
14
+ export const APP_VERSION_HEADER = "x-mobile-app-version";
15
+
16
+ /** 对齐状态。 */
17
+ export const ALIGNMENT_STATE = {
18
+ /** 两端语义版本一致。 */
19
+ OK: "ok",
20
+ /** 手机 App 落后于插件:应更新 App。 */
21
+ APP_OUTDATED: "app-outdated",
22
+ /** 插件落后于手机 App:应更新插件。 */
23
+ PLUGIN_OUTDATED: "plugin-outdated",
24
+ /** 无法判定(旧 App 未上报、或版本不可解析)——如实报出,不猜。 */
25
+ UNKNOWN: "unknown",
26
+ };
27
+
28
+ /** 取 core `X.Y.Z`(prerelease 与 build 都剥离);不可解析返回 ""。 */
29
+ export function semanticVersion(value) {
30
+ const p = parseVersion(value);
31
+ return p ? p.version : "";
32
+ }
33
+
34
+ /** 从请求头读 App 版本;缺失或形状异常一律返回空串。 */
35
+ export function readAppVersionHeader(headers) {
36
+ if (!headers || typeof headers !== "object") return "";
37
+ const raw = headers[APP_VERSION_HEADER];
38
+ const value = Array.isArray(raw) ? raw[0] : raw;
39
+ return typeof value === "string" ? value.trim() : "";
40
+ }
41
+
42
+ /**
43
+ * 计算两端对齐状态。返回结构可直接放进 bootstrap / diagnostics 响应。
44
+ * `hint` 是给人看的说明(PC 端日志与诊断页用);手机端应按 `reason` 自行本地化。
45
+ */
46
+ export function computeAppAlignment({ appVersionHeader, pluginVersion }) {
47
+ const pluginSemver = semanticVersion(pluginVersion);
48
+ const appRaw = typeof appVersionHeader === "string" ? appVersionHeader.trim() : "";
49
+ const base = {
50
+ appVersion: appRaw === "" ? null : appRaw,
51
+ pluginVersion: pluginVersion ?? "",
52
+ expectedAppVersion: pluginSemver || null,
53
+ };
54
+ if (pluginSemver === "") {
55
+ return { ...base, state: ALIGNMENT_STATE.UNKNOWN, reason: "plugin-version-unparseable", hint: "插件自身版本不可解析,无法判定两端是否对齐" };
56
+ }
57
+ if (appRaw === "") {
58
+ return {
59
+ ...base,
60
+ state: ALIGNMENT_STATE.UNKNOWN,
61
+ reason: "app-version-header-missing",
62
+ hint: `手机 App 未上报版本(通常是旧版 App);无法确认两端是否对齐。插件为 ${pluginVersion},建议把 App 更新到同版本。`,
63
+ };
64
+ }
65
+ const appSemver = semanticVersion(appRaw);
66
+ if (appSemver === "") {
67
+ return { ...base, state: ALIGNMENT_STATE.UNKNOWN, reason: "app-version-unparseable", hint: `手机 App 上报的版本无法解析:${appRaw}` };
68
+ }
69
+ if (appSemver === pluginSemver) {
70
+ return { ...base, state: ALIGNMENT_STATE.OK, reason: "aligned", hint: "" };
71
+ }
72
+ const older = compareSemver(appSemver, pluginSemver) < 0;
73
+ if (older) {
74
+ return {
75
+ ...base,
76
+ state: ALIGNMENT_STATE.APP_OUTDATED,
77
+ reason: "app-older-than-plugin",
78
+ hint: `手机 App(${appRaw})落后于本机插件(${pluginVersion}):新功能会被明确提示而非静默失效。请在手机上把 App 更新到 ${pluginSemver}。`,
79
+ };
80
+ }
81
+ return {
82
+ ...base,
83
+ state: ALIGNMENT_STATE.PLUGIN_OUTDATED,
84
+ reason: "plugin-older-than-app",
85
+ hint: `本机插件(${pluginVersion})落后于手机 App(${appRaw}):请在电脑上把插件更新到 ${appSemver} 并重启 DSH。`,
86
+ };
87
+ }
88
+
89
+ /** 内部:比较两个语义版本(入参已保证可解析)。 */
90
+ function compareSemver(a, b) {
91
+ const pa = a.split(".").map(Number);
92
+ const pb = b.split(".").map(Number);
93
+ for (let i = 0; i < 3; i++) {
94
+ if (pa[i] !== pb[i]) return pa[i] < pb[i] ? -1 : 1;
95
+ }
96
+ return 0;
97
+ }
98
+
99
+ /**
100
+ * 只在结论变化时提示一次(bootstrap 会在启动、下拉刷新、重连时反复调用,
101
+ * 每次都记日志会把 DSH 日志刷满)。`seen` 是该插件实例作用域内的去重载体。
102
+ */
103
+ export function noteAppAlignment(logger, alignment, seen) {
104
+ if (!alignment || alignment.state === ALIGNMENT_STATE.OK) return false;
105
+ const key = `${alignment.state}:${alignment.appVersion ?? "-"}`;
106
+ if (seen.key === key) return false;
107
+ seen.key = key;
108
+ const line = `mobile-remote: ${alignment.hint}`;
109
+ if (alignment.state === ALIGNMENT_STATE.UNKNOWN) logger?.info?.(line);
110
+ else logger?.warn?.(line);
111
+ return true;
112
+ }