@marktrue/dsh-mobile-remote 3.2.4-alpha.1-app → 3.2.4-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.
- package/CHANGELOG.md +1410 -0
- package/CONTRIBUTING.md +59 -0
- package/FAQ.md +111 -0
- package/README.md +254 -6
- package/cordis.patch.yml +14 -0
- package/docs/00-/345/274/200/345/217/221/346/200/273/347/272/262.md +125 -0
- package/docs/01-PRD.md +148 -0
- package/docs/02-architecture.md +249 -0
- package/docs/03-api.md +1154 -0
- package/docs/04-security.md +100 -0
- package/docs/05-test-cases.md +405 -0
- package/docs/06-install-run.md +372 -0
- package/docs/07-user-manual.md +70 -0
- package/docs/08-/346/211/251/345/261/225/345/274/200/345/217/221/346/214/207/345/215/227.md +86 -0
- package/docs/09-compatibility.md +227 -0
- package/docs/10-release.md +1067 -0
- package/docs/screenshots/01-home.png +0 -0
- package/docs/screenshots/02-notifications.png +0 -0
- package/docs/screenshots/03-sessions.png +0 -0
- package/docs/screenshots/04-chat.png +0 -0
- package/docs/screenshots/05-settings.png +0 -0
- package/docs/screenshots/06-new-session.png +0 -0
- package/docs/screenshots/pgy-appstore.jpg +0 -0
- package/docs/screenshots/pgy-mobile-app.jpg +0 -0
- package/docs/screenshots/pgy-pc-client.jpg +0 -0
- package/lib/account-usage.js +145 -0
- package/lib/app-alignment.js +112 -0
- package/lib/app-carrier-store.js +1972 -0
- package/lib/app-carrier.js +609 -0
- package/lib/client.js +1174 -0
- package/lib/desktop-form.js +738 -0
- package/lib/endpoint-registry.js +167 -0
- package/lib/git-read-bundled-provider.js +450 -0
- package/lib/git-read-service.js +601 -0
- package/lib/index.js +9622 -0
- package/lib/npm-update-source.js +226 -0
- package/lib/plugin-content-digest.js +80 -0
- package/lib/plugin-self-update.js +997 -0
- package/lib/plugin-update-controller.js +274 -0
- package/lib/plugin-update-log.js +164 -0
- package/lib/plugin-update-transaction.js +322 -0
- package/lib/plugin-update.js +309 -0
- package/lib/runtime-dependency-snapshot.js +345 -0
- package/lib/session-title-cache.js +123 -0
- package/lib/session-title-refresh.js +261 -0
- package/lib/tool-process.js +20 -0
- package/lib/update-fetch.js +24 -0
- package/lib/update-lock-arbiter.js +170 -0
- package/lib/update-supervisor.js +346 -0
- package/node_modules/ansi-regex/index.d.ts +37 -0
- package/node_modules/ansi-regex/index.js +10 -0
- package/node_modules/ansi-regex/license +9 -0
- package/node_modules/ansi-regex/package.json +55 -0
- package/node_modules/ansi-regex/readme.md +78 -0
- package/node_modules/ansi-styles/index.d.ts +345 -0
- package/node_modules/ansi-styles/index.js +163 -0
- package/node_modules/ansi-styles/license +9 -0
- package/node_modules/ansi-styles/package.json +56 -0
- package/node_modules/ansi-styles/readme.md +152 -0
- package/node_modules/camelcase/index.d.ts +63 -0
- package/node_modules/camelcase/index.js +76 -0
- package/node_modules/camelcase/license +9 -0
- package/node_modules/camelcase/package.json +43 -0
- package/node_modules/camelcase/readme.md +99 -0
- package/node_modules/cliui/CHANGELOG.md +76 -0
- package/node_modules/cliui/LICENSE.txt +14 -0
- package/node_modules/cliui/README.md +115 -0
- package/node_modules/cliui/index.js +354 -0
- package/node_modules/cliui/package.json +65 -0
- package/node_modules/color-convert/CHANGELOG.md +54 -0
- package/node_modules/color-convert/LICENSE +21 -0
- package/node_modules/color-convert/README.md +68 -0
- package/node_modules/color-convert/conversions.js +839 -0
- package/node_modules/color-convert/index.js +81 -0
- package/node_modules/color-convert/package.json +48 -0
- package/node_modules/color-convert/route.js +97 -0
- package/node_modules/color-name/LICENSE +8 -0
- package/node_modules/color-name/README.md +11 -0
- package/node_modules/color-name/index.js +152 -0
- package/node_modules/color-name/package.json +28 -0
- package/node_modules/decamelize/index.js +13 -0
- package/node_modules/decamelize/license +21 -0
- package/node_modules/decamelize/package.json +38 -0
- package/node_modules/decamelize/readme.md +48 -0
- package/node_modules/dijkstrajs/.travis.yml +4 -0
- package/node_modules/dijkstrajs/CONTRIBUTING.md +8 -0
- package/node_modules/dijkstrajs/LICENSE.md +19 -0
- package/node_modules/dijkstrajs/README.md +18 -0
- package/node_modules/dijkstrajs/dijkstra.js +165 -0
- package/node_modules/dijkstrajs/package.json +60 -0
- package/node_modules/dijkstrajs/test/dijkstra.test.js +96 -0
- package/node_modules/emoji-regex/LICENSE-MIT.txt +20 -0
- package/node_modules/emoji-regex/README.md +73 -0
- package/node_modules/emoji-regex/es2015/index.js +6 -0
- package/node_modules/emoji-regex/es2015/text.js +6 -0
- package/node_modules/emoji-regex/index.d.ts +23 -0
- package/node_modules/emoji-regex/index.js +6 -0
- package/node_modules/emoji-regex/package.json +50 -0
- package/node_modules/emoji-regex/text.js +6 -0
- package/node_modules/find-up/index.d.ts +137 -0
- package/node_modules/find-up/index.js +89 -0
- package/node_modules/find-up/license +9 -0
- package/node_modules/find-up/package.json +53 -0
- package/node_modules/find-up/readme.md +156 -0
- package/node_modules/get-caller-file/LICENSE.md +6 -0
- package/node_modules/get-caller-file/README.md +41 -0
- package/node_modules/get-caller-file/index.d.ts +2 -0
- package/node_modules/get-caller-file/index.js +22 -0
- package/node_modules/get-caller-file/index.js.map +1 -0
- package/node_modules/get-caller-file/package.json +42 -0
- package/node_modules/is-fullwidth-code-point/index.d.ts +17 -0
- package/node_modules/is-fullwidth-code-point/index.js +50 -0
- package/node_modules/is-fullwidth-code-point/license +9 -0
- package/node_modules/is-fullwidth-code-point/package.json +42 -0
- package/node_modules/is-fullwidth-code-point/readme.md +39 -0
- package/node_modules/locate-path/index.d.ts +83 -0
- package/node_modules/locate-path/index.js +65 -0
- package/node_modules/locate-path/license +9 -0
- package/node_modules/locate-path/package.json +45 -0
- package/node_modules/locate-path/readme.md +122 -0
- package/node_modules/p-limit/index.d.ts +38 -0
- package/node_modules/p-limit/index.js +57 -0
- package/node_modules/p-limit/license +9 -0
- package/node_modules/p-limit/package.json +52 -0
- package/node_modules/p-limit/readme.md +101 -0
- package/node_modules/p-locate/index.d.ts +64 -0
- package/node_modules/p-locate/index.js +52 -0
- package/node_modules/p-locate/license +9 -0
- package/node_modules/p-locate/package.json +53 -0
- package/node_modules/p-locate/readme.md +90 -0
- package/node_modules/p-try/index.d.ts +39 -0
- package/node_modules/p-try/index.js +9 -0
- package/node_modules/p-try/license +9 -0
- package/node_modules/p-try/package.json +42 -0
- package/node_modules/p-try/readme.md +58 -0
- package/node_modules/path-exists/index.d.ts +28 -0
- package/node_modules/path-exists/index.js +23 -0
- package/node_modules/path-exists/license +9 -0
- package/node_modules/path-exists/package.json +39 -0
- package/node_modules/path-exists/readme.md +52 -0
- package/node_modules/pngjs/.eslintignore +2 -0
- package/node_modules/pngjs/.eslintrc.json +19 -0
- package/node_modules/pngjs/.prettierignore +3 -0
- package/node_modules/pngjs/LICENSE +20 -0
- package/node_modules/pngjs/README.md +429 -0
- package/node_modules/pngjs/browser.js +16096 -0
- package/node_modules/pngjs/coverage/lcov-report/base.css +354 -0
- package/node_modules/pngjs/coverage/lcov-report/bitmapper.js.html +881 -0
- package/node_modules/pngjs/coverage/lcov-report/bitpacker.js.html +554 -0
- package/node_modules/pngjs/coverage/lcov-report/block-navigation.js +77 -0
- package/node_modules/pngjs/coverage/lcov-report/chunkstream.js.html +647 -0
- package/node_modules/pngjs/coverage/lcov-report/constants.js.html +176 -0
- package/node_modules/pngjs/coverage/lcov-report/crc.js.html +200 -0
- package/node_modules/pngjs/coverage/lcov-report/favicon.png +0 -0
- package/node_modules/pngjs/coverage/lcov-report/filter-pack.js.html +593 -0
- package/node_modules/pngjs/coverage/lcov-report/filter-parse-async.js.html +152 -0
- package/node_modules/pngjs/coverage/lcov-report/filter-parse-sync.js.html +143 -0
- package/node_modules/pngjs/coverage/lcov-report/filter-parse.js.html +611 -0
- package/node_modules/pngjs/coverage/lcov-report/format-normaliser.js.html +359 -0
- package/node_modules/pngjs/coverage/lcov-report/index.html +426 -0
- package/node_modules/pngjs/coverage/lcov-report/interlace.js.html +365 -0
- package/node_modules/pngjs/coverage/lcov-report/packer-async.js.html +230 -0
- package/node_modules/pngjs/coverage/lcov-report/packer-sync.js.html +248 -0
- package/node_modules/pngjs/coverage/lcov-report/packer.js.html +467 -0
- package/node_modules/pngjs/coverage/lcov-report/paeth-predictor.js.html +128 -0
- package/node_modules/pngjs/coverage/lcov-report/parser-async.js.html +575 -0
- package/node_modules/pngjs/coverage/lcov-report/parser-sync.js.html +404 -0
- package/node_modules/pngjs/coverage/lcov-report/parser.js.html +950 -0
- package/node_modules/pngjs/coverage/lcov-report/png-sync.js.html +116 -0
- package/node_modules/pngjs/coverage/lcov-report/png.js.html +662 -0
- package/node_modules/pngjs/coverage/lcov-report/prettify.css +101 -0
- package/node_modules/pngjs/coverage/lcov-report/prettify.js +1007 -0
- package/node_modules/pngjs/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/node_modules/pngjs/coverage/lcov-report/sorter.js +169 -0
- package/node_modules/pngjs/coverage/lcov-report/sync-inflate.js.html +584 -0
- package/node_modules/pngjs/coverage/lcov-report/sync-reader.js.html +215 -0
- package/node_modules/pngjs/coverage/lcov.info +2177 -0
- package/node_modules/pngjs/lib/bitmapper.js +267 -0
- package/node_modules/pngjs/lib/bitpacker.js +158 -0
- package/node_modules/pngjs/lib/chunkstream.js +189 -0
- package/node_modules/pngjs/lib/constants.js +32 -0
- package/node_modules/pngjs/lib/crc.js +40 -0
- package/node_modules/pngjs/lib/filter-pack.js +171 -0
- package/node_modules/pngjs/lib/filter-parse-async.js +24 -0
- package/node_modules/pngjs/lib/filter-parse-sync.js +21 -0
- package/node_modules/pngjs/lib/filter-parse.js +177 -0
- package/node_modules/pngjs/lib/format-normaliser.js +93 -0
- package/node_modules/pngjs/lib/interlace.js +95 -0
- package/node_modules/pngjs/lib/packer-async.js +50 -0
- package/node_modules/pngjs/lib/packer-sync.js +56 -0
- package/node_modules/pngjs/lib/packer.js +129 -0
- package/node_modules/pngjs/lib/paeth-predictor.js +16 -0
- package/node_modules/pngjs/lib/parser-async.js +165 -0
- package/node_modules/pngjs/lib/parser-sync.js +108 -0
- package/node_modules/pngjs/lib/parser.js +290 -0
- package/node_modules/pngjs/lib/png-sync.js +12 -0
- package/node_modules/pngjs/lib/png.js +194 -0
- package/node_modules/pngjs/lib/sync-inflate.js +168 -0
- package/node_modules/pngjs/lib/sync-reader.js +45 -0
- package/node_modules/pngjs/package.json +73 -0
- package/node_modules/qrcode/README.md +770 -0
- package/node_modules/qrcode/bin/qrcode +159 -0
- package/node_modules/qrcode/helper/to-sjis-browser.js +2 -0
- package/node_modules/qrcode/helper/to-sjis.js +105 -0
- package/node_modules/qrcode/lib/browser.js +76 -0
- package/node_modules/qrcode/lib/can-promise.js +7 -0
- package/node_modules/qrcode/lib/core/alignment-pattern.js +83 -0
- package/node_modules/qrcode/lib/core/alphanumeric-data.js +59 -0
- package/node_modules/qrcode/lib/core/bit-buffer.js +37 -0
- package/node_modules/qrcode/lib/core/bit-matrix.js +65 -0
- package/node_modules/qrcode/lib/core/byte-data.js +30 -0
- package/node_modules/qrcode/lib/core/error-correction-code.js +135 -0
- package/node_modules/qrcode/lib/core/error-correction-level.js +50 -0
- package/node_modules/qrcode/lib/core/finder-pattern.js +22 -0
- package/node_modules/qrcode/lib/core/format-info.js +29 -0
- package/node_modules/qrcode/lib/core/galois-field.js +69 -0
- package/node_modules/qrcode/lib/core/kanji-data.js +54 -0
- package/node_modules/qrcode/lib/core/mask-pattern.js +234 -0
- package/node_modules/qrcode/lib/core/mode.js +167 -0
- package/node_modules/qrcode/lib/core/numeric-data.js +43 -0
- package/node_modules/qrcode/lib/core/polynomial.js +62 -0
- package/node_modules/qrcode/lib/core/qrcode.js +495 -0
- package/node_modules/qrcode/lib/core/reed-solomon-encoder.js +56 -0
- package/node_modules/qrcode/lib/core/regex.js +31 -0
- package/node_modules/qrcode/lib/core/segments.js +330 -0
- package/node_modules/qrcode/lib/core/utils.js +63 -0
- package/node_modules/qrcode/lib/core/version-check.js +9 -0
- package/node_modules/qrcode/lib/core/version.js +163 -0
- package/node_modules/qrcode/lib/index.js +12 -0
- package/node_modules/qrcode/lib/renderer/canvas.js +63 -0
- package/node_modules/qrcode/lib/renderer/png.js +78 -0
- package/node_modules/qrcode/lib/renderer/svg-tag.js +81 -0
- package/node_modules/qrcode/lib/renderer/svg.js +19 -0
- package/node_modules/qrcode/lib/renderer/terminal/terminal-small.js +85 -0
- package/node_modules/qrcode/lib/renderer/terminal/terminal.js +49 -0
- package/node_modules/qrcode/lib/renderer/terminal.js +9 -0
- package/node_modules/qrcode/lib/renderer/utf8.js +71 -0
- package/node_modules/qrcode/lib/renderer/utils.js +99 -0
- package/node_modules/qrcode/lib/server.js +138 -0
- package/node_modules/qrcode/license +10 -0
- package/node_modules/qrcode/package.json +77 -0
- package/node_modules/require-directory/.jshintrc +67 -0
- package/node_modules/require-directory/.npmignore +1 -0
- package/node_modules/require-directory/.travis.yml +3 -0
- package/node_modules/require-directory/LICENSE +22 -0
- package/node_modules/require-directory/README.markdown +184 -0
- package/node_modules/require-directory/index.js +86 -0
- package/node_modules/require-directory/package.json +40 -0
- package/node_modules/require-main-filename/CHANGELOG.md +26 -0
- package/node_modules/require-main-filename/LICENSE.txt +14 -0
- package/node_modules/require-main-filename/README.md +26 -0
- package/node_modules/require-main-filename/index.js +18 -0
- package/node_modules/require-main-filename/package.json +35 -0
- package/node_modules/set-blocking/CHANGELOG.md +26 -0
- package/node_modules/set-blocking/LICENSE.txt +14 -0
- package/node_modules/set-blocking/README.md +31 -0
- package/node_modules/set-blocking/index.js +7 -0
- package/node_modules/set-blocking/package.json +42 -0
- package/node_modules/string-width/index.d.ts +29 -0
- package/node_modules/string-width/index.js +47 -0
- package/node_modules/string-width/license +9 -0
- package/node_modules/string-width/package.json +56 -0
- package/node_modules/string-width/readme.md +50 -0
- package/node_modules/strip-ansi/index.d.ts +17 -0
- package/node_modules/strip-ansi/index.js +4 -0
- package/node_modules/strip-ansi/license +9 -0
- package/node_modules/strip-ansi/package.json +54 -0
- package/node_modules/strip-ansi/readme.md +46 -0
- package/node_modules/which-module/LICENSE +13 -0
- package/node_modules/which-module/README.md +58 -0
- package/node_modules/which-module/index.js +9 -0
- package/node_modules/which-module/package.json +41 -0
- package/node_modules/wrap-ansi/index.js +186 -0
- package/node_modules/wrap-ansi/license +9 -0
- package/node_modules/wrap-ansi/package.json +61 -0
- package/node_modules/wrap-ansi/readme.md +97 -0
- package/node_modules/y18n/CHANGELOG.md +35 -0
- package/node_modules/y18n/LICENSE +13 -0
- package/node_modules/y18n/README.md +109 -0
- package/node_modules/y18n/index.js +188 -0
- package/node_modules/y18n/package.json +39 -0
- package/node_modules/yargs/CHANGELOG.md +420 -0
- package/node_modules/yargs/LICENSE +21 -0
- package/node_modules/yargs/README.md +140 -0
- package/node_modules/yargs/build/lib/apply-extends.d.ts +2 -0
- package/node_modules/yargs/build/lib/apply-extends.js +65 -0
- package/node_modules/yargs/build/lib/argsert.d.ts +2 -0
- package/node_modules/yargs/build/lib/argsert.js +65 -0
- package/node_modules/yargs/build/lib/command.d.ts +64 -0
- package/node_modules/yargs/build/lib/command.js +416 -0
- package/node_modules/yargs/build/lib/common-types.d.ts +36 -0
- package/node_modules/yargs/build/lib/common-types.js +25 -0
- package/node_modules/yargs/build/lib/completion-templates.d.ts +2 -0
- package/node_modules/yargs/build/lib/completion-templates.js +50 -0
- package/node_modules/yargs/build/lib/completion.d.ts +21 -0
- package/node_modules/yargs/build/lib/completion.js +135 -0
- package/node_modules/yargs/build/lib/is-promise.d.ts +1 -0
- package/node_modules/yargs/build/lib/is-promise.js +9 -0
- package/node_modules/yargs/build/lib/levenshtein.d.ts +1 -0
- package/node_modules/yargs/build/lib/levenshtein.js +58 -0
- package/node_modules/yargs/build/lib/middleware.d.ts +10 -0
- package/node_modules/yargs/build/lib/middleware.js +57 -0
- package/node_modules/yargs/build/lib/obj-filter.d.ts +1 -0
- package/node_modules/yargs/build/lib/obj-filter.js +14 -0
- package/node_modules/yargs/build/lib/parse-command.d.ts +11 -0
- package/node_modules/yargs/build/lib/parse-command.js +36 -0
- package/node_modules/yargs/build/lib/process-argv.d.ts +2 -0
- package/node_modules/yargs/build/lib/process-argv.js +31 -0
- package/node_modules/yargs/build/lib/usage.d.ts +49 -0
- package/node_modules/yargs/build/lib/usage.js +540 -0
- package/node_modules/yargs/build/lib/validation.d.ts +34 -0
- package/node_modules/yargs/build/lib/validation.js +330 -0
- package/node_modules/yargs/build/lib/yargs.d.ts +274 -0
- package/node_modules/yargs/build/lib/yargs.js +1190 -0
- package/node_modules/yargs/build/lib/yerror.d.ts +4 -0
- package/node_modules/yargs/build/lib/yerror.js +11 -0
- package/node_modules/yargs/index.js +40 -0
- package/node_modules/yargs/locales/be.json +46 -0
- package/node_modules/yargs/locales/de.json +46 -0
- package/node_modules/yargs/locales/en.json +51 -0
- package/node_modules/yargs/locales/es.json +46 -0
- package/node_modules/yargs/locales/fi.json +49 -0
- package/node_modules/yargs/locales/fr.json +53 -0
- package/node_modules/yargs/locales/hi.json +49 -0
- package/node_modules/yargs/locales/hu.json +46 -0
- package/node_modules/yargs/locales/id.json +50 -0
- package/node_modules/yargs/locales/it.json +46 -0
- package/node_modules/yargs/locales/ja.json +51 -0
- package/node_modules/yargs/locales/ko.json +49 -0
- package/node_modules/yargs/locales/nb.json +44 -0
- package/node_modules/yargs/locales/nl.json +49 -0
- package/node_modules/yargs/locales/nn.json +44 -0
- package/node_modules/yargs/locales/pirate.json +13 -0
- package/node_modules/yargs/locales/pl.json +49 -0
- package/node_modules/yargs/locales/pt.json +45 -0
- package/node_modules/yargs/locales/pt_BR.json +48 -0
- package/node_modules/yargs/locales/ru.json +46 -0
- package/node_modules/yargs/locales/th.json +46 -0
- package/node_modules/yargs/locales/tr.json +48 -0
- package/node_modules/yargs/locales/zh_CN.json +48 -0
- package/node_modules/yargs/locales/zh_TW.json +47 -0
- package/node_modules/yargs/package.json +92 -0
- package/node_modules/yargs/yargs.js +14 -0
- package/node_modules/yargs-parser/CHANGELOG.md +601 -0
- package/node_modules/yargs-parser/LICENSE.txt +14 -0
- package/node_modules/yargs-parser/README.md +449 -0
- package/node_modules/yargs-parser/index.js +1032 -0
- package/node_modules/yargs-parser/lib/tokenize-arg-string.js +40 -0
- package/node_modules/yargs-parser/package.json +46 -0
- package/package.json +65 -12
- package/DSH-Remote-v3.2.4.apk +0 -4
- package/manifest.json +0 -21
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
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
|
+
}
|