- 变更规模:新增 514 / 修改 62 / 重命名 155 / 删除 4(归档重组与文档轮次) - .gitignore 修:`归档/**/db-cwd归一-备份-*/` —— 原规则写绝对层级(归档/db-cwd归一-…), 目录搬进 归档/配置与备份/ 后**静默失效**,43 MB 的 DB 备份又变成未跟踪 - .gitignore 补:嵌套 git 内部数据(归档/内嵌git-20261008/、归档/skills-git-旧线-20261007/dotgit-原样移出/) - .gitignore 补:运行态与部署副本(.workbuddy/collab/、.workbuddy/tools/、.workbuddy/.load-pending、.workbuddy/tmp-*) - .gitignore 补:备份件(*.bak-*) - 未跟踪文件从 2190 降到 890(其余为 归档/ 归档件与 .workbuddy/memory/ 知识文件,按口径入库)
14 KiB
Android 壳 × WorkBuddy 手机回复 · 联动方案(2026-09-28)
需求(用户原话):能否联动
ai1net-dsh-anywhere中的会话(负责开发 Android app、配合实现这个功能)在我的 Android 手机上运行,共同实现「手机回复 WorkBuddy 会话」这个效果。 上游:交付物/手机回复WorkBuddy会话-架构与实施方案-20260928.md(本文件是它的手机端落地补充,⛔ 不改其架构结论)。 证据分级:【已验】有实测读数 |【源码在】代码在位未跑 |【待核实】未取证 —— 交付时不得混写。
0 判定(三句话)
- 能联动,而且 Android 壳正好补上原方案最弱的一环(手机端形态 + 通知能力)。
- 但先纠正一处事实:那个 Android app 确实存在(
E:/github/dsh-client/apps/android,Capacitor 壳),但它处于 M3「骨架(不构建)」 阶段 —— WebView 只加载一张骨架说明页,且 当前机器已无构建环境。所以不是"接线即可用",而是"壳有了、内容与构建链要补"。 - 链路天然同构:那条线(手机接入线)的通道是「手机 → 门户 → 中继 → 设备垫片 → 桌面 DSH」;本方案要的是「手机 → 门户 → 中继 → 设备桥 → 桌面 WorkBuddy」。⇒ 同一个手机端、同一个设备节点、同一条中继,只是目标从 DSH 换成 WorkBuddy。⛔ 不新造任何传输。
1 事实核查(Android app 到底什么状态)
1.1 它是什么
| 项 | 事实 |
|---|---|
| 位置 | E:/github/dsh-client/apps/android(属 dsh-client monorepo) |
| 仓定位 | dsh-client — DSH 客户端(桌面 + Android),一份内核 + 多套壳(README 原话) |
| 形态 | Capacitor 8.5.2 壳(@capacitor/core + @capacitor/android) |
| 标识 | appId com.dsh.client | appName「DSH 客户端」| webDir: www |
| 阶段 | M3 · 骨架(不构建),自报能力档 C0;hasLocalPlatform: false、connectionMode: 'remote-only'、TUN/保活 = pending(C 档原生) |
| WebView 当前加载 | 本地 www/index.html(3.5 KB 骨架说明页,09-18 编写)—— 不是功能页 |
| 地址策略 | 明文规定「平台地址一律运行时注入,⛔ 不写死在配置里」—— 与本方案一致 ✅ |
1.2 关键读数
| # | 读数 | 结论 |
|---|---|---|
| 1 | app/build/outputs/apk/debug/app-debug.apk 4,118,462 B · 09-18 00:12【已验】 |
曾成功构建过,可直接装到手机先跑 |
| 2 | java 未装 | ANDROID_HOME/ANDROID_SDK_ROOT 未设 | 默认 SDK 目录不存在【已验】 |
现在出不了新包 ⇒ 要出新 APK 必须装 JDK 17 + Android SDK(约 2–4 GB) |
| 3 | capacitor.config.ts 顶部原文 |
「本阶段不构建……那是资源承诺,须用户确认后单独做」 |
| 4 | dsh-client 仓 git log |
your current branch 'master' does not have any commits yet;git status 全部 ?? ⇒ 零提交、全部未跟踪【已验】 |
| 5 | packages/ 五个包 |
core(端无关内核)· adapter-mobile(移动端自适应适配层)· device-shim(设备垫片)· portal-first-screen · subagent-local |
1.3 那条线交付的、本方案可直接用的三件
| 件 | 作用 | 对本方案的意义 |
|---|---|---|
packages/adapter-mobile |
断点 token + 移动端适配(⛔ 不改上游 ui-theme/ui-layout) |
让「桌面 UI 在手机上可用」这件事已经有解 |
packages/device-shim |
只绑 127.0.0.1:20090 的 HTTP+WS 反代,进程内注入 DSH token |
本方案「设备侧桥」的现成范式(照它的收窄纪律做,⛔ 不重发明) |
packages/core |
端能力 provider(tunUp/keepAlive/reportState/requestPermission)+ 能力档 C0–C3 + 降级 |
手机端要做原生能力(通知/保活)时,声明与降级的框架已就位 |
1.4 🔴 两个现存阻断(不修就动不了)
E:\ProgramDSH整棵树已消失【已验】⇒ 那条线引用的E:\ProgramDSH\.dsh\profiles\desktop\(设备垫片的挂载点)不存在 ⇒ 垫片无法挂载(该线自己的接续包还在说"E:\ProgramDSH\.dsh\未搬、路径保持原样")。- 已找到替代:
C:\Users\Administrator\.dsh存在且含profiles/、scripts/、sessions/(但无temp/)⇒ 需先把运行时家目录的落点钉死,再谈继续开发。
- 已找到替代:
- 构建环境缺失(§1.2 读数 2)⇒ 出新 APK 需要 JDK 17 + Android SDK。
2 联动架构
2.1 一张图(同一个手机、同一条中继、两个目标)
┌──────────────── Android 手机 ────────────────┐
│ DSH 客户端(Capacitor 壳) │
│ ├ 入口页:两个卡片(本次新增) │
│ │ ① 打开桌面 DSH ② WorkBuddy 会话 │
│ └ WebView(同一壳内切换 URL) │
└───────────────────┬──────────────────────────┘
│ HTTPS 443(门户登录态)
▼
服务器节点 47(+ ai1net 插件)
├ 门户 / 账号 / 设备台账 / IM 内核 (既有)
├ 配对 overlay-pair(28 条判据全绿) (既有)
├ 覆盖网络中继(443 兜底,设备只拨出) (既有)
├ 通道① 路径前缀 /u/<slug>/desk/<hostId>/* (既有)
└ 通道② 移动会话面 /mobile.html + M6 模块 (本方案新增)
▲ wss 反隧道(⛔ 无公网入站口)
│
客户端(+插件)= 用户电脑(同一个设备节点)
├ 设备垫片 127.0.0.1:20090 → 桌面 DSH Web (既有,通道①)
└ 设备侧桥 127.0.0.1:<口> → WorkBuddy 钩子 (本方案,通道②)
🔴 关键点:两条通道共用同一个设备节点与同一条中继 —— 手机侧与平台侧的配对、登录、台账、取址全部复用;差异只在"设备侧那一段对接谁"(DSH Web ↔ WorkBuddy 钩子)。
2.2 通道②的两种手机端形态
| 形态 | 做法 | 优点 | 缺点 |
|---|---|---|---|
| PWA(推荐先行) | 手机浏览器打开平台移动会话页 →「添加到主屏幕」 | 零资源承诺、当天可用、支持 Web Push 通知、迭代无需打包 | 后台保活弱;iOS 更受限(本方案只针对 Android) |
| Capacitor 壳(推荐后补) | 壳的 server.url 指向平台移动会话页;壳只做容器 |
通知/保活/TUN 可走原生;会话持久;像一个真 App | 需 JDK 17 + Android SDK(2–4 GB);需重打包 |
🔴 一条重要的架构建议:壳只设一次 server.url 指向平台页面,此后所有功能迭代都在服务器侧完成 ⇒ APK 成为稳定薄容器,不需要为功能变更重新打包。这是把"2–4 GB 构建环境"从"每次都要"降为"一次性"的关键设计。
2.3 Android 壳带来的、浏览器给不了的三件事
- 通知(Android 通知渠道)—— "手机回复"的核心体验:桌面会话停下来等你时,手机该响。
- 后台保活 —— 浏览器切后台即被挂起;壳内可争常驻(属 C 档原生,待补)。
- 会话持久 —— 登录态与设备绑定存在 app 内,扫码一次之后长期有效。
⛔ 但不要现在就许诺 TUN/VpnService:按那条线自己的设备矩阵,它属 C 档「每端必写原生」,目前 canCreateTun: false、canKeepAlive: false 是如实自报,⛔ 不许假装。
3 与上一版方案的合并(谁做什么)
| 上一版方案的件 | 本方案的手机端承接 | 说明 |
|---|---|---|
web/mobile.html 移动会话页 |
壳的 WebView 目标(或 PWA 入口) | 页面本身不变;Android 只是它的容器 |
| M6「移动会话面」模块(3 条精确路由) | 不变 | 手机侧调的就是这三条 |
设备侧桥 wb-mobile-bridge |
与 device-shim 同节点、同纪律(只绑回环 + 内部注入) |
⛔ 不新造第二套范式 |
| WorkBuddy 钩子分支 | 不变(permissionDecision + additionalContext) |
壳对这一段不可见,也无需可见 |
| 覆盖网络 / 配对 / 台账 / 四道闸 | 全复用 | 手机换壳不改变平台侧任何判据 |
⇒ 合并后的手机端 =「一个 Android 壳 + 两个入口卡片」;平台侧 = 既有 + M6;桌面侧 = 既有垫片 + 设备侧桥。
4 分阶段路径(每棒可机器验,⛔ 做完即停)
| 棒 | 目标 | 判据(可机器验) | 资源 |
|---|---|---|---|
| A0 | 零成本先跑通:装既有 app-debug.apk 到手机,确认壳能起、能显示骨架页 |
手机上出现「DSH 客户端」图标且能打开 | 0(用既有 APK) |
| A1 | 修两个阻断:钉死 dsh 运行时家目录落点 + 恢复设备垫片挂载 | 垫片起、curl 127.0.0.1:20090/ 返回 200(垫片自检 17 断言绿) |
0 |
| A2 | PWA 先行:平台移动会话页上线 + 手机加到主屏幕 | 手机打开该页 200;能看到待答项;作答后桌面会话体现所选 | 0 |
| A3 | 手机端原生形态:壳 server.url 指向平台页面 + 通知 |
重打包后壳内可打开该页;桌面停下时手机收到通知 | JDK 17 + Android SDK(2–4 GB) ← 🔴 唯一资源承诺 |
| A4 | 真机端到端 + 两线合并验收 | ① 通道①:手机进桌面 DSH 并发一条消息 ② 通道②:手机回复 WorkBuddy 并看到模型据此继续 ③ 既有 28 条判据零回归 | 0 |
5 唯一需要拍板的事
问题:是否现在装 JDK 17 + Android SDK(约 2–4 GB),以产出带"通知 + 平台地址"的新 APK?
为什么需要你定:这是磁盘与安装时间的一次性资源承诺(属边界外第②类);而且不装也能先看到效果(A0 用既有 APK 验证壳、A2 用 PWA 把功能跑通),只是拿不到原生通知与保活。
- 候选 1 · 先不装,走 A0 → A2(PWA 先行)
- 优点:零成本、当天可验、功能链路一次走通;失败也不留包袱。
- 缺点:没有原生通知(要开浏览器才看得到待答);后台保活弱。倾向先走这条。
- 候选 2 · 现在就装(A0 → A1 → A2 → A3 一次做完)
- 优点:一步到位拿到通知与常驻,体验完整。
- 缺点:先付出 2–4 GB 与安装时间;而壳内要显示的页面(A2 的产物)此时还不存在 ⇒ 有白装的风险(建议至少等 A2 出页之后再装)。
- 倾向:候选 1 —— 先零成本把链路跑通,A2 出页后再决定是否装 SDK;那时装也只需一次,且此后页面迭代不再需要打包。
6 风险与未验证项(⛔ 不得当成已定)
- 壳内切 URL 的实现方式【待核实】 —— 现有
capacitor.config.ts未设server.url⇒ 当前只能加载内置www;要把 WebView 指到平台页面,至少需要一次重打包(或确认壳是否支持运行时注入)。这一点直接决定 A3 是否真的必需。 - 既有 APK 是否可复现【待核实】 —— 09-18 那个 APK 是当时环境构建的;当前无 Java/SDK ⇒ 若它跑不起来,A0 就不能零成本验证。
C:\Users\Administrator\.dsh是否为权威家目录【待核实】 —— 该目录无temp/(原E:\ProgramDSH\.dsh\temp\joint\里的台账看不到)⇒ 需确认它是"搬过来的"还是"另一份"。- 设备垫片挂载点失效 —— 那条线写死的
E:\ProgramDSH\.dsh\profiles\desktop已不存在;先修这个,否则通道①本身就不通(更谈不上与通道②合并验收)。 dsh-client仓零提交 —— 全部 untracked ⇒ 无版本历史、回滚只能靠文件副本;动它之前建议先入库。- Android 后台保活是系统级难题 —— 按那条线自己的表述属 C 档「每端必写原生」;⛔ 不要因为"壳里能跑"就假设常驻可用。
- 两条通道会共用设备节点 ⇒ 端口声明(
ports)、守护编排、开关都要各管一份,⚠️ 别把通道②的开关错接到通道①上。
附:本次取证命令与读数(可复跑)
| # | 取证点 | 读数 |
|---|---|---|
| 1 | find E:/github/dsh-client/apps/android -name "*.apk" |
app/build/outputs/apk/debug/app-debug.apk(4,118,462 B · 09-18 00:12) |
| 2 | cat apps/android/package.json |
@capacitor/core 8.5.2;描述「Capacitor 壳骨架 + 端能力声明;本阶段不构建」 |
| 3 | cat apps/android/capacitor.config.ts |
appId com.dsh.client;webDir www;无 server.url;注释明写"地址运行时注入"+"JDK17+SDK 属资源承诺" |
| 4 | cat apps/android/src/endpoint.ts |
自报 declaredTier: 'C0'、hasLocalPlatform: false、canCreateTun/canKeepAlive/canReportState: false |
| 5 | cat apps/android/www/index.html |
3,544 B 骨架说明页(非功能页) |
| 6 | which java / $ANDROID_HOME / SDK 目录 |
未装 / 未设 / 不存在 |
| 7 | git -C E:/github/dsh-client log |
does not have any commits yet;status 全 ?? |
| 8 | ls E:/github/dsh-client/packages |
core · adapter-mobile · device-shim · portal-first-screen · subagent-local |
| 9 | ls -d E:/ProgramDSH/.dsh/profiles/desktop |
不存在(E:\ProgramDSH 整棵已消失) |
| 10 | ls C:/Users/Administrator/.dsh |
存在(含 profiles/ scripts/ sessions/;无 temp/) |
| 11 | anywhere 线入口 §34 / §24 | 「手机侧零新增客户端(门户登录态 + 官方 Web UI,走路径前缀)」 |
| 12 | packages/adapter-mobile/package.json |
「移动端自适应适配层 —— dsh 独立插件形式,⛔ 不改上游 ui-theme / ui-layout」 |