@marktrue/dsh-mobile-remote 3.2.1-alpha.2-app → 3.2.1-alpha.2
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 +803 -0
- package/CONTRIBUTING.md +59 -0
- package/FAQ.md +111 -0
- package/README.md +253 -6
- package/cordis.patch.yml +14 -0
- package/docs/00-/345/274/200/345/217/221/346/200/273/347/272/262.md +122 -0
- package/docs/01-PRD.md +148 -0
- package/docs/02-architecture.md +249 -0
- package/docs/03-api.md +816 -0
- package/docs/04-security.md +96 -0
- package/docs/05-test-cases.md +326 -0
- package/docs/06-install-run.md +308 -0
- package/docs/07-user-manual.md +65 -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 +195 -0
- package/docs/10-release.md +927 -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 +602 -0
- package/lib/client.js +706 -0
- package/lib/desktop-form.js +738 -0
- package/lib/endpoint-registry.js +162 -0
- package/lib/git-read-bundled-provider.js +255 -0
- package/lib/git-read-service.js +322 -0
- package/lib/index.js +9292 -0
- package/lib/plugin-content-digest.js +80 -0
- package/lib/plugin-self-update.js +758 -0
- package/lib/plugin-update-controller.js +95 -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/update-fetch.js +24 -0
- package/lib/update-lock-arbiter.js +158 -0
- package/lib/update-supervisor.js +312 -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 -10
- package/DSH-Remote-v3.2.1.apk +0 -4
- package/manifest.json +0 -21
package/docs/01-PRD.md
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# 01 产品需求文档(PRD)— dsh-mobile-remote
|
|
2
|
+
|
|
3
|
+
> 版本:v3.0.0 · 状态:全部功能已实现(v0.1/v1 历史部分保留作演进记录) · 适用范围:本插件全部迭代
|
|
4
|
+
|
|
5
|
+
## 1. 产品定位与目标用户
|
|
6
|
+
- **产品定位**:DeepSeek Harness 的手机远程操作插件 + 原生 App。当电脑端 DSH(Desktop 或 web)在线运行时,使用者可以离开电脑,通过手机 App(DSH Remote)向运行中的 agent 发消息、派任务、查看进度、接收完成通知、审批决策、管理历史会话,并跳转 DeepSeek 开放平台充值。
|
|
7
|
+
- **目标用户**:本人(单人使用)。设计上不假设多用户、不做账号体系。
|
|
8
|
+
- **一句话**:把"DSH 桌面会话"延伸到口袋里——电脑是执行者,手机是遥控器。
|
|
9
|
+
## 2. 功能清单
|
|
10
|
+
|
|
11
|
+
### 2.1 功能总表
|
|
12
|
+
|
|
13
|
+
| 编号 | 功能 | 描述 | 优先级 |
|
|
14
|
+
|---|---|---|---|
|
|
15
|
+
| F1 | 发消息/派任务 | 手机输入文本 → 注入运行中的 agent(`agent.followup`)→ agent 立即开始处理 | P0 |
|
|
16
|
+
| F2 | 看进度 | 消息流实时显示 agent 回复、工具调用活动、轮次开始/结束 | P0 |
|
|
17
|
+
| F3 | 完成通知 | agent 空闲/轮次结束时手机浏览器通知(Notification API) | P0 |
|
|
18
|
+
| F4 | 会话历史 | 列出全部会话,切换会话查看历史消息并续接对话 | P1 |
|
|
19
|
+
| F5 | 回答/审批 | 手机上直接回答 agent 提出的问题(选项选择/自定义输入)与权限审批(允许一次/拒绝)——v2.3 起原生弹窗卡片,与 PC 端同一 pending 通道(见 docs/02-architecture §12b) | P0(v2.3 完成) |
|
|
20
|
+
| F6 | 充值入口 | 移动页提供余额充值卡片,跳转 DeepSeek 开放平台充值页 | P1 |
|
|
21
|
+
| F7 | 二维码连接 | 移动页内置二维码:电脑/手机同网络时扫码即得访问地址 | P1 |
|
|
22
|
+
| F8 | 访问口令 | 可选访问口令(默认关闭),启用后移动 API 全部要求认证 | P1 |
|
|
23
|
+
| F9 | 访问地址展示 | 页面列出本机所有可达地址(局域网 IP + 虚拟组网 IP),供外出时手动输入 | P1 |
|
|
24
|
+
| F10 | 用量与额度 | 设置 → 账户查看 DeepSeek 余额、Codex 当前活动账户配额、OpenCode Go 套餐窗口;来源独立显示,凭据不下发手机 | P1 |
|
|
25
|
+
|
|
26
|
+
### 2.2 明确不做(v1 范围外)
|
|
27
|
+
|
|
28
|
+
> **演进说明**:以下为 v1 时代的范围边界。其中「原生 App」「推送通知」「移动端新建会话」已在 v2.0~v2.4 全部实现(见 §10/§11 与 CHANGELOG),此处保留原文并标注演进。
|
|
29
|
+
|
|
30
|
+
- ~~原生 App(iOS/Android 客户端),只做浏览器 PWA~~ → **v2.0 起原生 App 为主体**(Android 已发布;iOS 未开发,见 09-compatibility)
|
|
31
|
+
- ~~推送通知(APNs/FCM):v1 用浏览器通知~~ → **推送桥**(Server酱/ntfy/Bark/generic)实现手机系统级提醒
|
|
32
|
+
- ~~移动端发起全新会话(v1 只向现有会话注入消息)~~ → **v2.0 已支持**(新建会话 API + 工作目录选择)
|
|
33
|
+
- 文件上传/下载、语音输入、消息编辑/撤回(仍未做)
|
|
34
|
+
- 多用户账号体系、审计日志(仍未做)
|
|
35
|
+
## 3. 业务主流程与分支流程
|
|
36
|
+
|
|
37
|
+
### 3.1 主流程:手机发消息
|
|
38
|
+
```
|
|
39
|
+
手机打开 /m(扫码/手动输入地址)→ bootstrap 获取状态(agent 是否在线、是否需口令)→ [分支 A] 口令已启用且未认证 → 登录(输入口令)→ Set-Cookie
|
|
40
|
+
→ 输入消息 → POST /api/send { sessionId?, text }
|
|
41
|
+
→ agent.followup() 注入 → agent 唤醒执行
|
|
42
|
+
→ 移动页 SSE(/api/events)实时收到 session/event(turn/start → assistant/chunk 流式 → tool/result → turn/end)
|
|
43
|
+
→ agent 空闲 → 浏览器通知"任务完成"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 3.2 分支流程
|
|
47
|
+
|
|
48
|
+
- **A. 认证**:口令为空(默认)→ 跳过;口令非空 → 未认证请求一律 401,页面显示登录表单。
|
|
49
|
+
- **B. 无运行中 agent**:`/api/send` 返回 503,页面提示当前没有运行中的 agent(电脑端未打开会话)。
|
|
50
|
+
- **C. 多会话**:存在多个 agent 时,页面顶部会话选择器指定目标;未指定默认第一个 root agent。
|
|
51
|
+
- **D. 断线重连**:SSE 断开 → 页面自动重连(指数退避),重连后拉取历史增量补齐。
|
|
52
|
+
- **E. 通知不可用**:浏览器未授权通知 → 页面内横幅提示,消息流仍正常显示。
|
|
53
|
+
## 4. 页面原型(文字线框)
|
|
54
|
+
|
|
55
|
+
```
|
|
56
|
+
┌──────────────────────────────┐
|
|
57
|
+
│ ◀ agent 状态|会话: <当前> ▸ │
|
|
58
|
+
│ → 顶部栏:状态点(running/idle)、会话切换 │
|
|
59
|
+
├──────────────────────────────┤
|
|
60
|
+
│ [Tab1 对话] [Tab2 会话] [Tab3 更多] │
|
|
61
|
+
├──────────────────────────────┤
|
|
62
|
+
│ 对话 Tab(消息流) │
|
|
63
|
+
│ · 消息流(user 右气泡 / │
|
|
64
|
+
│ assistant 左气泡 / 工具行 / │
|
|
65
|
+
│ 轮次分隔线) │
|
|
66
|
+
│ · 底部输入条:文本框 发送 │
|
|
67
|
+
├──────────────────────────────┤
|
|
68
|
+
│ 会话 Tab(会话列表) │
|
|
69
|
+
│ · 会话列表:id、创建时间。 │
|
|
70
|
+
│ 状态(运行/空闲) │
|
|
71
|
+
│ · 点击切换当前会话 │
|
|
72
|
+
├──────────────────────────────┤
|
|
73
|
+
│ 更多 Tab(更多) │
|
|
74
|
+
│ · 访问地址列表 + 二维码 │
|
|
75
|
+
│ · 充值入口卡片 │
|
|
76
|
+
│ · 安全状态(口令开关) │
|
|
77
|
+
│ · 刷新/关于 │
|
|
78
|
+
└──────────────────────────────┘
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
- 适配规则:手机优先(375px 起),桌面浏览器可用(内容居中限宽 480px);跟随系统深浅色(`prefers-color-scheme`)。
|
|
82
|
+
- 触控目标 ≥ 44px;输入条固定底部(键盘弹起时 iOS 安全区适配 `env(safe-area-inset-bottom)`)。
|
|
83
|
+
## 5. 非功能需求
|
|
84
|
+
| 类别 | 指标 |
|
|
85
|
+
|---|---|
|
|
86
|
+
| 响应时间 | API 请求(bootstrap/send/历史)≤ 200ms(本机回环);SSE 事件延迟 ≤ 500ms |
|
|
87
|
+
| 可用性 | 电脑端 DSH 在线即可用;GUI 重启后移动端自动恢复(会话持久化在 DSH 侧) |
|
|
88
|
+
| 并发 | 单用户;SSE 连接数上限 16(超出拒绝并提示) |
|
|
89
|
+
| 兼容性 | 手机:iOS Safari ≥ 15、Android Chrome ≥ 90(现代浏览器,含 Notification/EventSource);桌面:Chrome/Edge/Firefox |
|
|
90
|
+
| 流量 | 时间线摘要默认轻量;tool/result 与 assistant 长内容通过认证详情端点按需读取,列表不静默丢失 Visible event |
|
|
91
|
+
| 安全基线 | 见 04-security.md:威胁模型、口令方案、传输安全要求 |
|
|
92
|
+
| 可维护性 | 零构建(无前端打包步骤);插件为纯 ESM;配置项集中在 Config schema |
|
|
93
|
+
|
|
94
|
+
## 6. 数据与埋点
|
|
95
|
+
- 不采集任何埋点;不新增持久化存储(口令仅存于 dsh profile 配置;会话数据由 dsh 现有 session 服务持有)。
|
|
96
|
+
## 7. 迭代优先级
|
|
97
|
+
| 迭代 | 范围 | 目标 |
|
|
98
|
+
|---|---|---|
|
|
99
|
+
| v0.1(本次) | F1 F2 F3 F8 F9 + 页面骨架 | 打通「手机发消息 → 看进度 → 收通知」主链路 |
|
|
100
|
+
| v0.2 | F4 会话历史、F6 充值入口、F7 二维码 | 会话管理 + 常用入口 |
|
|
101
|
+
| v0.3 | F5 回答/审批独立端点、通知增强 | 移动端全场景操作 |
|
|
102
|
+
|
|
103
|
+
## 8. 验收标准(v0.1)
|
|
104
|
+
1. 手机与电脑同一网络(或虚拟组网)时,App 可见页面与 agent 状态正确。
|
|
105
|
+
2. 发送消息后,电脑端 GUI 会话出现该消息,agent 开始执行,移动页实时看到流式回复。
|
|
106
|
+
3. agent 完成任务空闲时,手机浏览器收到通知(页面后台时)。
|
|
107
|
+
4. 启用访问口令后,未认证访问全部移动 API 返回 401;登录后正常。
|
|
108
|
+
5. 无运行中 agent 时发送消息,页面给出明确提示而非静默失败。
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
# 第二部分:移动端产品版(v2.0,与 00-开发总纲配套)
|
|
112
|
+
## 9. 界面定稿(冻结)
|
|
113
|
+
|
|
114
|
+
视觉与信息架构以 `prototype/app-prototype.html`(v7)为准,要点:
|
|
115
|
+
- **视觉**:DeepSeek 品牌配色(主色 `#426EFE`,深色 `#0E1116`/`#161B22`)、衬线大标题(Georgia/宋体)、1.5 线宽 Lucide 风格线性图标、大圆角(16-24px)、默认跟随系统深浅色
|
|
116
|
+
- **信息架构**:侧边栏三项——首页 / 会话 / 设置;对话、通知为详情页;无底部 tab
|
|
117
|
+
- **首页固定欢迎界面**:衬线欢迎语 + 最近会话 + 新建会话 + 底部输入条(不做状态切换)
|
|
118
|
+
- **新建会话当场选模式**(标准 PTC/极简/创造),预选值来自设置默认
|
|
119
|
+
- **对话页**:输入条两行式(第一行模型/权限胶囊,第二行 + 输入/发送)、动作区(可选,空则隐藏)、活动条(思考中/工具执行中,v2.6)、微信式无限上翻(滑到顶自动加载更早 + 回到底部浮钮)、问询/审批弹窗卡片(与 PC 端同一 pending)
|
|
120
|
+
- **通知中心**:三类通知(完成/需要回答/失败)、未读徽标、全部已读、点击直达会话
|
|
121
|
+
- **设置页**:连接、账户用量与额度(DeepSeek / Codex / OpenCode Go)、DeepSeek 充值与金额预警、默认权限预设、默认 Agent 预设、通知开关、显示开关、关于
|
|
122
|
+
- **诚实原则**:未实现功能明确标注"开发中"
|
|
123
|
+
|
|
124
|
+
## 10. 移动端功能映射(v2.0 范围)
|
|
125
|
+
| 功能 | 实现层 | API |
|
|
126
|
+
|---|---|---|
|
|
127
|
+
| 发消息/派任务 | 核心层 | `POST /api/send`(已有) |
|
|
128
|
+
| 流式回复/进度 | 核心层 | `GET /api/events` SSE(已有) |
|
|
129
|
+
| 历史/上翻 | 核心层 | `GET /api/history`(已有) |
|
|
130
|
+
| 新建会话(选模式) | 核心层 | `POST /api/sessions`(新增) |
|
|
131
|
+
| 模型/推理/权限切换 | 核心层 | `GET/POST /api/session-config`(新增) |
|
|
132
|
+
| 通知中心 | 核心层 | `GET /api/notifications`(新增) |
|
|
133
|
+
| 通知删除 | 核心层 | `POST /api/notifications/delete`(v2.3) |
|
|
134
|
+
| 问询/审批弹窗 | 核心层 | SSE `mobile/frame` + `POST /api/respond`(v2.3) |
|
|
135
|
+
| 插件动作区 | 可选层 | `GET /api/actions` + invoke(新增) |
|
|
136
|
+
| 模型提供商互通 | 核心层 | `GET/POST /api/llm-providers` + `probe`(v2.6,与 PC 端同一 settings/credentials 通道) |
|
|
137
|
+
| 多地址自动切换 | 核心层 | bootstrap `server.urls` 收集(局域网 + 组网 IP,排除 169.254/16)+ 断线轮换(v2.4.1) |
|
|
138
|
+
| 连接自愈 | 核心层 | SSE 超时 + 心跳看门狗 + 地址轮换(v2.4.2/v2.5.1,黑洞约 10s 故障切换) |
|
|
139
|
+
| 手动切换连接地址 | 核心层 | 设置 → 电脑地址候选列表,探测后切换重连(v2.5.0) |
|
|
140
|
+
| 用量与额度 | 核心层 | `GET /api/account-usage`;来源独立成功/隐藏,服务端凭据隔离(v3.2) |
|
|
141
|
+
|
|
142
|
+
## 11. 验收标准(v2.0,Phase 1 完成标志)
|
|
143
|
+
1. 手机完成「新建会话(选模式)→ 发消息 → 流式回复 → 通知 → 审批 → 翻历史记录」全链路。
|
|
144
|
+
2. 模型/推理强度/权限预设选择与 PC 端一致,Full Access 有风险确认。
|
|
145
|
+
3. 通知中心三类事件正确聚合,未读状态跨重启保留。
|
|
146
|
+
4. 既有 v0.1 端点全部保持兼容(回归)。
|
|
147
|
+
5. 问询/审批弹窗与 PC 端同一 pending:任一端回答,两端同步消失(v2.3+,用例见 05-test-cases F-15/F-16)。
|
|
148
|
+
6. 设置 → 账户进入“用量与额度”后,DeepSeek、当前活动 Codex 账户、OpenCode Go 的成功来源按固定顺序展示;配额窗口显示剩余百分比与重置时间,不合并求和,任何来源失败不阻塞其他来源。
|
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
# 02 系统架构设计说明书 — dsh-mobile-remote
|
|
2
|
+
|
|
3
|
+
> 版本:v3.2.0 · 状态:已实现(v2.3 问询/审批弹窗桥、v2.4~v2.5 连接自愈、v2.6 安全加固+模型提供商互通、v2.9/v3.0 LAN 桥 + 图像链路、v3.2 用量与额度) · 配套:01-PRD.md、03-api.md、04-security.md、09-compatibility.md
|
|
4
|
+
|
|
5
|
+
## 1. 背景与范围
|
|
6
|
+
DSH 由 Cordis 组合出宿主(desktop 版 `dsh-plugin-desktop` 或 web 版 `dsh --profile web`),webserver 默认只绑定 `127.0.0.1`(**桌面版 0.1.1-rc.2 起强制回环**,DesktopsWebServer 对非回环 host 直接 throw)。本插件在宿主侧挂载 Cordis 插件:在 webServer 上注册 `/m` 前缀路由,并在 **LAN 桥**(`lanBridge`,默认 `0.0.0.0:3080`)自建监听把移动端请求流式转发到回环 webserver——移动端形态为**原生 Flutter App**(`dsh-mobile-app`),经 `/m/api` 与插件通信。插件不修改桌面 GUI 的任何现有 UI。
|
|
7
|
+
## 2. 技术选型结论与理由
|
|
8
|
+
### 2.1 移动端形态:独立轻量页(`/m`) vs 桌面 GUI 窄屏适配
|
|
9
|
+
|
|
10
|
+
| 方案 | 优点 | 缺点 | 结论 |
|
|
11
|
+
|---|---|---|---|
|
|
12
|
+
| 桌面 GUI 窄屏适配(client 插件 + slot) | 复用现有 React 组件、自动获得全部功能 | 三栏 AppFrame 适配工作量大;HMR 依赖 `pnpm run dev:web` watcher;触控体验难做通 | 放弃 |
|
|
13
|
+
| **独立轻量页 `/m`(本方案)** | ~500 行原生 HTML/CSS/JS 覆盖全部需求;无构建;与桌面 UI 零耦合;可独立控制安全边界 | 功能需自己实现(消息流、通知、历史) | **采用** |
|
|
14
|
+
|
|
15
|
+
### 2.2 外出通路:蒲公英(虚拟组网) vs 隧道/反代 vs 裸公网
|
|
16
|
+
| 方案 | 认证/TLS | 成本 | 结论 |
|
|
17
|
+
|---|---|---|---|
|
|
18
|
+
| **蒲公英/虚拟组网(WireGuard 组网)** | 设备身份认证 + 端到端加密,零应用层代码 | 免费版 3 成员 | **采用**(实测通过;账号可用性属个体情况,其他组网如 ZeroTier/EasyTier 同理可接) |
|
|
19
|
+
| 隧道/中继类(frp/SakuraFrp,`trustedHosts`) | 需自建认证 + **必须 TLS**(自有域名须 ICP 备案) | 免费/收费 | 备选(有合规门槛) |
|
|
20
|
+
| cloudflared 隧道 | TLS 自动,但公网可达需自建认证 | 免费,需额外 token 机制 | 备选 |
|
|
21
|
+
| 裸公网暴露 0.0.0.0 | 无 TLS | 高危(agent 可执行 bash/pwsh ≥ RCE) | 明确禁止 |
|
|
22
|
+
|
|
23
|
+
### 2.3 前端技术:原生 JS vs 框架
|
|
24
|
+
|
|
25
|
+
单页无构建、无路由、无状态管理需求 → 原生 HTML/CSS/JS(ES2022),`EventSource` 接 SSE、`fetch` 接 JSON API、`Notification` 做提醒。避免引入 Node 侧构建链。
|
|
26
|
+
### 2.4 二维码生成:npm `qrcode` 包(Node 侧)
|
|
27
|
+
|
|
28
|
+
Node 侧直接生成 PNG data 输出到 `<img>`,前端零依赖;避免在前端内联 QR 编码算法(Reed-Solomon 实现量大)。
|
|
29
|
+
### 2.5 其余依赖
|
|
30
|
+
|
|
31
|
+
- `@deepseek-ai/schemastery`(Config schema,与 dsh 同款)
|
|
32
|
+
- `@deepseek-ai/dsh-llm`(`createUserMessage` 构造消息)
|
|
33
|
+
- 宿主机服务:`webServer`(路由)、`agents`(AgentRegistry,惰态 `ctx.get`)、`sessions`(SessionStore,惰态 `ctx.get`)
|
|
34
|
+
## 3. 架构分层
|
|
35
|
+
|
|
36
|
+
```mermaid
|
|
37
|
+
graph TB
|
|
38
|
+
subgraph 手机端 M[DSH Remote App(Flutter)]
|
|
39
|
+
end
|
|
40
|
+
subgraph 电脑端 DSH 宿主进程
|
|
41
|
+
subgraph Cordis 组合树 WS[webserver 服务(强制回环)<br/>node:http]
|
|
42
|
+
PH[插件 /m 路由 + SSE]
|
|
43
|
+
BR[插件 LAN 桥 0.0.0.0:3080<br/>流式转发 /m/api*]
|
|
44
|
+
AG[agents 服务<br/>AgentRegistry]
|
|
45
|
+
SS[sessions 服务<br/>SessionStore]
|
|
46
|
+
AL[agent loop<br/>运行中的 agent]
|
|
47
|
+
end
|
|
48
|
+
PH -->|register 前缀路由 /m| WS
|
|
49
|
+
BR -->|上游请求 Host 重写为回环| WS
|
|
50
|
+
PH -->|ctx.get 惰性| AG
|
|
51
|
+
PH -->|ctx.get 惰性| SS
|
|
52
|
+
PH -->|ctx.on session/event| AL
|
|
53
|
+
AG -->|followup/inbox/status| AL
|
|
54
|
+
end
|
|
55
|
+
M -->|HTTP/SSE(局域网/组网直连桥)| BR
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
- **插件层**(本插件):路由注册、LAN 桥转发、JSON API、SSE 事件桥、认证、二维码、推送桥。
|
|
59
|
+
- **服务层**(dsh 现有):`agents`(注入消息、查状态)、`sessions`(列会话、读事件历史)、`webServer`(传输)。
|
|
60
|
+
- **执行层**:agent loop 消费 inbox 消息,产出 `session/event` 事实流。
|
|
61
|
+
## 4. 模块划分
|
|
62
|
+
|
|
63
|
+
### 4.1 服务端(`lib/index.js`)
|
|
64
|
+
| 模块 | 职责 |
|
|
65
|
+
|---|---|
|
|
66
|
+
| 路由注册 | `webServer.register`:前缀 `/m/api/*`、`/m/qr.png`;dispose 时全部注销 |
|
|
67
|
+
| JSON API | bootstrap / send / sessions / history / catalog / notifications / defaults …(见 03-api.md) |
|
|
68
|
+
| SSE 事件桥 | `ctx.on('session/event', ...)` → 摘要化 → 广播到移动端连接;心跳注释帧;连接数上限 |
|
|
69
|
+
| 认证 | 口令比对(常量时间,`X-Mobile-Token` 头)→ 401 语义 |
|
|
70
|
+
| 二维码 | `qrcode` 生成 PNG(桌面设置页扫码用) |
|
|
71
|
+
| 地址发现 | `os.networkInterfaces()` 枚举 IPv4(含虚拟组网段,过滤 VMware 等虚拟网卡),port 取自 `lanBridge.port`(桥监听成功时)否则 `ctx.webServer.port` |
|
|
72
|
+
|
|
73
|
+
### 4.2 客户端(`dsh-mobile-app` Flutter + `lib/client.js` 桌面模块)
|
|
74
|
+
| 模块 | 职责 |
|
|
75
|
+
|---|---|
|
|
76
|
+
| App 状态层(`store.dart`) | bootstrap 缓存、当前会话、SSE 重连(指数退避)、事件去重(messageId/seq) |
|
|
77
|
+
| App 消息流(`chat_screen.dart`) | user/assistant 气泡、流式合并(节流)、Markdown 渲染、活动条(思考/工具过程,v2.6)、轮次分隔 |
|
|
78
|
+
| App 通知页 | turn/end 分类通知(完成/失败/需回答)、已读持久化、未读角标 |
|
|
79
|
+
| App 会话/新建 | 会话列表、新建会话(模式 + 目录跨盘浏览) |
|
|
80
|
+
| App 设置 | 用量与额度(DeepSeek / Codex / OpenCode Go)、充值/DeepSeek 金额预警、默认预设、深色模式、诊断、重新配置 |
|
|
81
|
+
| 桌面客户端模块(`client.js`) | dsh 设置页「连接移动端设备」:拉取 `/m/api/qr-config` 展示二维码 |
|
|
82
|
+
|
|
83
|
+
## 5. 核心时序
|
|
84
|
+
|
|
85
|
+
### 5.1 发消息全链路
|
|
86
|
+
|
|
87
|
+
```mermaid
|
|
88
|
+
sequenceDiagram
|
|
89
|
+
participant M as 手机 /m
|
|
90
|
+
participant P as mobile-remote 插件
|
|
91
|
+
participant A as agents 服务
|
|
92
|
+
participant L as agent loop
|
|
93
|
+
participant E as session/event 事件流
|
|
94
|
+
M->>P: POST /api/send {text}
|
|
95
|
+
P->>P: 认证校验(口令启用时)
|
|
96
|
+
P->>A: agents.get(sessionId) / roots()[0]
|
|
97
|
+
alt 无运行中 agent
|
|
98
|
+
P-->>M: 503 {error:'no-live-agent'}
|
|
99
|
+
else
|
|
100
|
+
P->>P: createUserMessage({content:[text], source:{kind:'user'}})
|
|
101
|
+
P->>A: agent.followup(message)
|
|
102
|
+
A->>L: 唤醒驱动器(如空闲)
|
|
103
|
+
L-->>E: turn/start, assistant/chunk..., turn/end
|
|
104
|
+
E-->>P: ctx.on('session/event')
|
|
105
|
+
P-->>M: SSE 帧(摘要)
|
|
106
|
+
M->>M: 渲染消息流 + 通知判断
|
|
107
|
+
end
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 5.2 事件摘要规则(服务端,防止移动端流量膨胀)
|
|
111
|
+
| 事件类型 | 下发给移动端的载荷 |
|
|
112
|
+
|---|---|
|
|
113
|
+
| `user/message` | 全部 text blocks(≤2000 字符),图片/文件仅下发引用元数据 |
|
|
114
|
+
| `assistant/message` | 全部 text blocks(≤20000 字符),reasoning 折叠计数,图片/文件仅下发引用元数据 |
|
|
115
|
+
| `assistant/chunk` | 仅 text delta(≤4000 字符缓冲合并) |
|
|
116
|
+
| `tool/result` | 工具名 + 成功/失败 + 截断内容(≤2000 字符)+ 文件/图片引用元数据 |
|
|
117
|
+
| `turn/start` / `turn/end` | 类型 + 轮次数 / 结束原因 |
|
|
118
|
+
| 其他 | 保留 type/seq;无损详情按需读取(`ignorable` 不改变可见性,敏感/内部事件除外) |
|
|
119
|
+
| 协议元数据(`session/title`、`model/selection`、`feedback/*` 等) | 仍下发并保留 seq/详情指针,但普通模式折叠、调试模式可展开 |
|
|
120
|
+
| 内部/重建/快照(`request/*`、`step/*`、`system/message`、`assistant/attempt`、`compaction/*`) | 历史、实时与详情端点均不返回 |
|
|
121
|
+
|
|
122
|
+
## 6. 状态机
|
|
123
|
+
```mermaid
|
|
124
|
+
stateDiagram-v2
|
|
125
|
+
[*] --> idle: 会话就绪
|
|
126
|
+
idle --> running: followup 唤醒
|
|
127
|
+
running --> running: 连续轮次/子代理
|
|
128
|
+
running --> idle: turn/end (kind≠aborted)
|
|
129
|
+
running --> idle: turn/end (aborted)
|
|
130
|
+
idle --> [*]: agent dispose
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
- 移动页顶部状态点直接来自最近的 `turn/start`/`turn/end` 事件推断;`bootstrap`/`agents` 接口提供权威值。
|
|
134
|
+
- "完成通知"触发条件:`running → idle` 且页面文档处于 hidden 状态。
|
|
135
|
+
## 7. 关键设计决策(ADR 简表)
|
|
136
|
+
|
|
137
|
+
| # | 决策 | 理由 |
|
|
138
|
+
|---|---|---|
|
|
139
|
+
| D1 | **桌面版:LAN 桥转发(回环 webserver 不动);web 版:profile patch 绑定 0.0.0.0** | 桌面版 0.1.1-rc.2 强制 webserver 回环(patch 覆盖 host 会 throw),只能在插件内自建监听转发;web 版无此限制,patch 覆盖须写全必填字段(见 06 §4) |
|
|
140
|
+
| D2 | 口令认证默认关闭 | 信任网络层(自家 WiFi + 虚拟组网);口令是可选加固而非默认摩擦 |
|
|
141
|
+
| D3 | SSE 而非轮询 | 现有 `/plugins/events` 同款模式;事件延迟 <500ms 需求 |
|
|
142
|
+
| D4 | 移动页不发起新会话 | 会话创建/模型配置语义复杂(preset、模型选择),v1 只续接 |
|
|
143
|
+
| D5 | 摘要作为默认展示,完整 Visible event 通过详情按需读取 | 保持移动端列表流量与渲染成本可控,同时允许调试模式审阅主会话工具链;未知事件保留类型/顺序,不静默丢弃(取代旧的“摘要而非全量”表述) |
|
|
144
|
+
|
|
145
|
+
## 8. 非功能架构
|
|
146
|
+
- **连接管理**:SSE 连接 Set,上限 16;dispose 时 `res.destroy()` 全部连接。
|
|
147
|
+
- **心跳**:每 25s 发送 `: ping` 注释帧,防中间代理断连。
|
|
148
|
+
- **事件广播失败隔离**:单个连接写入抛错 → 只断开该连接,不影响其他订阅者。
|
|
149
|
+
- **无状态**:插件无自有持久化;重启 dsh 后插件随组合树重新挂载,SSE 连接由客户端重连恢复。
|
|
150
|
+
## 9. 风险与应对
|
|
151
|
+
| 风险 | 影响 | 应对 |
|
|
152
|
+
|---|---|---|
|
|
153
|
+
| 0.0.0.0 暴露给陌生网络 | 他人可驱动 agent | 04-security.md:口令加固 + 使用场景约束(仅可信 WiFi/虚拟组网) |
|
|
154
|
+
| 浏览器通知被系统拦截 | 收不到完成提醒 | 页面内横幅降级 + 用户手册说明系统设置 |
|
|
155
|
+
| dsh 服务名变动(agents/sessions 接口演进) | 插件失效 | 惰态 `ctx.get` + 明确错误文案;依赖固定 rc.6 版本 |
|
|
156
|
+
| SSE 在移动网络下断连 | 消息流中断 | 指数退避重连 + 重连后历史增量补齐 |
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
# 第二部分:移动端产品版架构(v2.1,配套 00-开发总纲)
|
|
161
|
+
## 10. 总体形态
|
|
162
|
+
```mermaid
|
|
163
|
+
graph LR
|
|
164
|
+
subgraph 手机
|
|
165
|
+
A1[DSH Remote App<br/>Flutter 原生]
|
|
166
|
+
end
|
|
167
|
+
subgraph 电脑 dsh 进程
|
|
168
|
+
P[dsh-mobile-remote 插件]
|
|
169
|
+
D[dsh 内核:agents/sessions/llm/settings]
|
|
170
|
+
G[dsh 设置页客户端模块<br/>连接移动端设备]
|
|
171
|
+
end
|
|
172
|
+
A1 -->|HTTP/SSE| P
|
|
173
|
+
G -->|loopback| P
|
|
174
|
+
P -->|ctx 服务| D
|
|
175
|
+
P -.Phase 2 推送桥.-> N[推送服务 Bark/Server酱] -.-> A1
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
- **单一 API 面**:App 共用 `/m/api/*`;API 先行,两端后写(总纲 §5)
|
|
179
|
+
- **App = 原生实现**:Flutter 全部界面(Phase 3 完成,v2.1 起唯一移动端形态)
|
|
180
|
+
- **网页版已移除**:v2.1 起不再提供 `/m` 页面(`page.html` 删除),减少运行资源;桌面设置页由客户端模块提供
|
|
181
|
+
|
|
182
|
+
## 11. 新增服务与模块(插件侧)
|
|
183
|
+
|
|
184
|
+
| 模块 | 职责 | 依赖 |
|
|
185
|
+
|---|---|---|
|
|
186
|
+
| `catalog` | 模型/推理/权限/预设枚举聚合(读 PC 端真实目录) | `ctx.llm`、permission-presets、agent-presets manifest |
|
|
187
|
+
| `session-config` | 当前会话模型/推理/权限读写(写走 PC 端同一事件路径) | `agents`、permission 服务 |
|
|
188
|
+
| `session-create` | 按 preset 新建会话并覆写配置 | `agents.create`、presets |
|
|
189
|
+
| `notifications` | 事件流聚合(completed/needs-answer/failed) 已读状态(文件持久化 `~/.dsh/mobile-remote/read-notifs.json`) | `ctx.on session/event` |
|
|
190
|
+
| `mobile-actions` | 动作注册表服务 `ctx.mobileActions` + 清单/执行端点 | 注册表(Cordis 语义) |
|
|
191
|
+
| `respond` | 问询/审批应答(v2.3):经 `apiProxy.respond` 回写,与 PC 端 GUI 同一 pending 通道 | `apiProxy`(`ctx.inject`) |
|
|
192
|
+
|
|
193
|
+
## 12. 关键实现要点
|
|
194
|
+
|
|
195
|
+
- **通知聚合**:`turn/end` 的 reason.kind 分类(completed/failed/blocked=needs-answer);聚合为内存记录 + 已读集合文件持久化(不再用 settings 域——无 fiber 的 HTTP 回调里调 settings 会崩进程)
|
|
196
|
+
- **权限写入**:`POST /api/session-config` 的权限项复用 PC 端 `/permission <preset>` 的写入路径(permission/preset 事件 + sandbox/approval 旋钮),确保桌面 GUI 与移动端看到同一事实
|
|
197
|
+
- **模型切换**:经 `ctx.agents` 的 per-session LLM target 设置(`installAgentLlmTarget` 语义),与 GUI 模型选择器一致
|
|
198
|
+
- **动作执行**:handler 在电脑端运行,长任务结果经会话事件回流(不阻塞 HTTP 响应)
|
|
199
|
+
|
|
200
|
+
## 12b. 问询/审批弹窗桥(v2.3,与 PC 端同一 pending)
|
|
201
|
+
|
|
202
|
+
```mermaid
|
|
203
|
+
sequenceDiagram
|
|
204
|
+
participant K as dsh 内核(apiProxy)
|
|
205
|
+
participant P as 插件(ctx.inject apiProxy)
|
|
206
|
+
participant M as 手机 App
|
|
207
|
+
participant U as 用户
|
|
208
|
+
|
|
209
|
+
K-->>P: mux 帧 question/requested / approval/requested(含 rpcId)
|
|
210
|
+
P->>P: pendingFrames 缓存(App 重连时补发)
|
|
211
|
+
P-->>M: SSE `mobile/frame`
|
|
212
|
+
M->>M: 聊天页弹出卡片(问询/审批)
|
|
213
|
+
U->>M: 选选项/输入/允许一次/拒绝/✕
|
|
214
|
+
M->>P: POST /m/api/respond {kind, rpcId, ...}
|
|
215
|
+
P->>K: apiProxy.respond(内核校验 matchesQuestions 等)
|
|
216
|
+
K-->>P: question/resolved / approval/resolved
|
|
217
|
+
P-->>M: SSE `mobile/frame`(收起卡片,两端同步消失)
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
- **获取服务必须用 `ctx.inject(["apiProxy"])`**:各插件上下文隔离,`ctx.get` 看不到兄弟插件注册的服务(dsh-client-connection 同款用法)。
|
|
221
|
+
- 只转发 question/approval/session-queue 瞬态帧;`session/event` 仍走 `ctx.on` 桥避免重复。
|
|
222
|
+
- **私有协议风险**:`events.mux` / `respond` 消息格式无稳定版本承诺;缺失时干净降级(`/m/api/respond` 返回 503、诊断 `respondBridge=false`),详见 docs/09-compatibility.md。
|
|
223
|
+
- 断线补发:App 重连 SSE 时插件回放 `pendingFrames`;从「需要你回答」通知进入会话即见挂起弹窗。
|
|
224
|
+
- 另一端先答:内核 pending 表先到先得,后答方收到 `not-pending`,App 收起卡片并提示"可能电脑端已先回答"。
|
|
225
|
+
## 13. 推送桥(Phase 2 架构)
|
|
226
|
+
```mermaid
|
|
227
|
+
sequenceDiagram
|
|
228
|
+
participant P as 插件
|
|
229
|
+
participant D as dsh 内核
|
|
230
|
+
participant N as 推送服务
|
|
231
|
+
participant M as 手机
|
|
232
|
+
|
|
233
|
+
D-->>P: session/event(turn/end / 提问 / 失败)
|
|
234
|
+
P->>P: 匹配推送配置(类型/会话/静默期)
|
|
235
|
+
P->>N: HTTPS POST(标题+摘要+深链)
|
|
236
|
+
N-->>M: 系统通知
|
|
237
|
+
M->>M: 点击 → 深链打开 App/网页对应会话
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
- 配置:`settings` 域(推送服务 URL、密钥、事件类型开关、静默时段)
|
|
241
|
+
- 深链:点击系统通知 → 打开 App 通知中心/对应会话(当前实现:通知中心条目跳转;App 自定义 scheme 深链未做)
|
|
242
|
+
- 去重/节流:同会话同类型 60s 内合并
|
|
243
|
+
## 14. App 架构(Phase 3 要点)
|
|
244
|
+
- Flutter 单工程;状态管理 ChangeNotifier(`store.dart` 的 `AppStore`);SSE 用 `http` 包流式解析
|
|
245
|
+
- 页面:首页(欢迎 + 最近会话) 会话 / 对话 / 通知 / 设置(对照原型 v7)
|
|
246
|
+
- 本地存储:连接配置(地址/口令)、UI 偏好(工具显示、主题、工作区选择)
|
|
247
|
+
- 连接自愈(v2.4.1~v2.5.1):bootstrap `server.urls` 收集全部地址(局域网 + 蒲公英/虚拟组网,排除 169.254/16 链路本地与 VMware 虚拟网卡);SSE 心跳看门狗(45s 无心跳强制重建)+ 超时即轮换(黑洞地址约 10s 故障切换);下拉刷新「探测 → 自愈 → 拉数据」;SSE 周期断连经实测系手机息屏 Doze(屏亮自动重连+唤醒重同步,非缺陷)
|
|
248
|
+
- 通知:App 内通知中心实时角标(SSE 推送);后台系统级提醒依赖 Phase 2 推送桥(App 不保活长连接)
|
|
249
|
+
- 用量与额度:设置页进入时调用 `/m/api/account-usage`;服务端并发查询 DeepSeek、dsh-codex-connect 当前活动 Codex 账户、OpenCode Go,并只返回本轮成功来源。额度查询为只读投影,凭据停留在电脑端;App 端仅运行期缓存/复用初始快照,配额窗口不聚合。
|