chore(工作区): 全量入库 + 补齐 .gitignore(以工作区为准)
- 变更规模:新增 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/ 知识文件,按口径入库)
This commit is contained in:
1 parent
30b46dbd0c
commit
c1b5e4d966
735 files changed
+153192
-2415
No files matched your search
@@ -0,0 +1,208 @@
|
||||
# 手机 App 经 ai1net 覆盖网络操作 WorkBuddy 会话 · 架构与分工(2026-09-28)
|
||||
|
||||
> 🔴 **本件已被取代(v1 → v2)** ⇒ 执行请以 **`手机App经覆盖网络操作WorkBuddy-架构定稿v2-20260928.md`** 为准。
|
||||
> **本件作废的具体结论**:§3.3「垫片承载形态改为独立进程」**已撤销** —— 用户澄清「客户端插件」指 **DSH 客户端**上的插件(DSH 有完整插件宿主),故垫片**维持既有 DSH Host 插件形态**。
|
||||
> 本件其余取证(复用清单、端口区间、gateway 端点、`forwardHeaders` 逻辑可复用)**仍然有效**,v2 已并入。
|
||||
|
||||
> **用户口径(原话)**:「通过 **dsh 平台的覆盖网络**去实现,功能做到**插件**中:**本地 dsh 客户端插件** + **dsh 平台插件**配合,让**手机 app 通过 ai1net 网络**使用」
|
||||
> **性质**:架构定稿 + 分工 + 分步。落地按 §5 棒次执行。
|
||||
> **与前一版关系**:本文件**取代**前一版的"连接方式待定" —— **D1 已定 = 走 ai1net 覆盖网络(方案 C)**。
|
||||
|
||||
---
|
||||
|
||||
## 0 判定(三句话)
|
||||
|
||||
1. **能成,而且约 80% 是复用** —— 那条线(手机接入线)已经把"手机经中继看到桌面"整条跑通(配对 28 条判据全绿、设备入口真机 200/101),六个复用件**全部在位**(§2)。
|
||||
2. **要新做的只有三处**(§3):把垫片的**上游**从"本机 DSH Web"换成"本机 WorkBuddy gateway"、把**凭据注入**从"DSH 签名 Cookie"换成"gateway 令牌"、把垫片的**承载形态**从"DSH Host 侧插件"改成"独立进程"(WorkBuddy 没有 DSH Host)。
|
||||
3. 🔴 **一个必须先发现的事实**:gateway 端口**每次重启都会变**(实测 `50753 → 59914`)⇒ 垫片**必须动态发现**,⛔ 不能写死。
|
||||
|
||||
---
|
||||
|
||||
## 1 目标架构(一条链,四段,复用三段)
|
||||
|
||||
```
|
||||
手机 App(Android 客户端)
|
||||
│ HTTPS 443(平台登录态)
|
||||
▼
|
||||
① ai1net 平台(服务器节点 47)—— 【既有,零改动】
|
||||
├ 设备入口 /u/<uid>/desk/<hostId>/* ← device-web.ts(202 行:五道闸 + 整站前缀转发)
|
||||
├ 配对 overlay-pair(二维码六态) ← 28 条判据全绿
|
||||
├ 设备台账 overlay_devices + 准入四道闸 ← 既有
|
||||
└ 覆盖网络中继 relay(wss 走 443,⛔ 不开端口)← 既有
|
||||
▲ 设备只拨出(无公网入站口)
|
||||
│
|
||||
② 用户电脑 —— 【既有守护 + 改造后的垫片】
|
||||
├ 节点守护 overlay-node-daemon.ps1(声明端口) ← 既有
|
||||
└ 【设备侧垫片】只绑 127.0.0.1:20090 ← 既有范式,改上游
|
||||
· Host → 127.0.0.1:<gateway口>(过 Host 校验)
|
||||
· 注入 gateway 凭据
|
||||
▼
|
||||
③ 本机 WorkBuddy gateway(127.0.0.1:<动态口>)—— 【既有,官方自带】
|
||||
· GET /api/v1/jobs 会话列表
|
||||
· GET /api/v1/jobs/{id}/stream ⭐ 实时尾随(SSE)
|
||||
· POST /api/v1/jobs/{id}/reply ⭐ 发送指令
|
||||
▼
|
||||
④ WorkBuddy 会话 —— 【既有,就是桌面那份会话库】
|
||||
```
|
||||
|
||||
**一句话**:手机走的是**你们已经跑通的那条路**,只是到了电脑里**换了最后一段的目标**(DSH Web → WorkBuddy gateway)。
|
||||
|
||||
---
|
||||
|
||||
## 2 复用清单(⛔ 全部已核实存在,不重造)
|
||||
|
||||
| # | 件 | 位置 | 状态 |
|
||||
|---|---|---|---|
|
||||
| ① | 设备侧垫片源码 | `E:/github/dsh-client/packages/device-shim` | ✅ 在位(含 `forwardHeaders` / `pair-page.js` / `oauth-dsh.js`) |
|
||||
| ② | 平台设备入口 | `D:/github/dsh_shenxian/src/web/routes/device-web.ts` | ✅ 202 行,**整站前缀转发**(一条前缀管全站) |
|
||||
| ③ | 配对五端点 | `src/web/routes/overlay-pair.ts` | ✅ 已部署,六态 |
|
||||
| ④ | 设备台账 + 四道闸 | `src/web/routes/overlay-device.ts` | ✅ |
|
||||
| ⑤ | 节点守护 | `E:/dsh-worker-dev/bin/overlay-node-daemon.ps1` | ✅ 含 `-Action install/uninstall/status` |
|
||||
| ⑥ | 节点配置(端口/凭据) | `E:/dsh-worker-dev/overlay/overlay-node.local.json` | ✅ `ports:[20090]` · `relayUrl=wss://ai1net.com/dshs-relay` |
|
||||
|
||||
**关键既有约束(照抄,⛔ 别重新发明)**:
|
||||
- 中继**只连回环**:`factory(port,'127.0.0.1')`,⛔ 永不接受可路由地址。
|
||||
- 声明端口必须在**中继允许区间**:47 生产实测 `--base 19000 --span 3000` ⇒ **19000..21999**。
|
||||
- ⛔ **不能直接声明 WorkBuddy gateway 的口** —— 原因有二:① 它是随机口、可能落在区间外;② 区间内需要有**真实回环监听者**,而 gateway 的口不归我们管。⇒ **这正是垫片存在的理由**。
|
||||
- 中继走 443(`wss://ai1net.com/dshs-relay`)⇒ **功能全可用、⛔ 不用开任何端口**。
|
||||
|
||||
---
|
||||
|
||||
## 3 三处新做/改(本方案的真正工作量)
|
||||
|
||||
### 3.1 垫片上游改目标:DSH Web → WorkBuddy gateway
|
||||
|
||||
| 项 | 现状(DSH 版) | 本方案(WorkBuddy 版) |
|
||||
|---|---|---|
|
||||
| 上游 | `127.0.0.1:<webServer.port>`(实测 19387) | `127.0.0.1:<gateway口>`(**动态**,见 3.4) |
|
||||
| 端口来源 | DSH 注入的 `webServer` 服务 | ⛔ 拿不到 ⇒ **自行发现** |
|
||||
| 转发变换 | Host → `127.0.0.1:<port>`;Origin 归一 | **同样需要**(gateway 也有 Host 校验 `hostValidation`) |
|
||||
|
||||
### 3.2 凭据注入改方式:DSH 签名 Cookie → gateway 令牌
|
||||
|
||||
- **DSH 版**:Cookie 是 **authority 绑定**的(名字 = `dsh-auth-`+sha256(authority),载荷里 authority 必须与 Host 逐字相等)⇒ 所以必须改写 Host。
|
||||
- **WorkBuddy 版**:鉴权是 **`?password=<令牌>`** 或 Cookie,**不绑定 authority**。
|
||||
- ✅ **有利**:Host 改写只为过 gateway 的 Host 校验,不带凭据语义 ⇒ 简单。
|
||||
- 🔴 **约束**:鉴权中间件有**防爆破限流 `2 次/分钟` + `12 次/小时`** ⇒ **绝不能每次请求都带 query 密码**。
|
||||
- **选定的做法**:垫片**首次**用 `?password=` 换到 **Cookie**,之后**全程复用 Cookie**(Cookie 不在限流口径内)。
|
||||
- ⚠️ 备选做法(若 Cookie 方案不通):垫片维护一个"已认证会话",只对 `401` 响应重取 Cookie。
|
||||
|
||||
### 3.3 垫片承载形态:DSH Host 插件 → 独立进程
|
||||
|
||||
- **现状**:垫片是 **DSH Host 侧插件**(`inject: ['connection','webServer']`),跑在 DSH Host 进程内 —— 因为它要从 `connection` 拿 DSH 凭据、从 `webServer` 拿端口。
|
||||
- 🔴 **WorkBuddy 没有 DSH Host**,插件形态只有 `skill` / `mcp-app` ⇒ **垫片无法作为 WorkBuddy 插件运行**。
|
||||
- ⇒ **改为独立进程**,由**既有节点守护拉起**(守护本来就管进程编排与端口声明)。
|
||||
- ✅ 无损失:垫片本体只是"绑回环 + 反代 + 改头",与是否跑在 DSH 内**无关**;`forwardHeaders` 的逻辑**可原样复用**。
|
||||
|
||||
### 3.4 🔴 动态发现 gateway 端口(**新增的必做项**)
|
||||
|
||||
- 实测:重启后 `50753 → 59914` ⇒ **写死必炸**。
|
||||
- **发现判据**(三项同时成立才算):
|
||||
1. 监听者是 **`WorkBuddy.exe`**(或其后代进程);
|
||||
2. `GET /` 返回 **200** 且正文含 `CodeBuddy Gateway` / `CodeBuddy Remote Control`;
|
||||
3. `GET /api/v1/health` 返回 **401**(路由在、需鉴权)。
|
||||
- 兜底:也可由用户敲 `/gateway status` 读出地址后填入配置(⛔ 该命令模型不能代敲)。
|
||||
- ⚠️ **发现失败要 fail-closed**(不启、具名报错),⛔ 不许静默用上一次的端口。
|
||||
|
||||
---
|
||||
|
||||
## 4 与既有那条线的差异表(一眼看清改了什么)
|
||||
|
||||
| 维度 | 手机接入线(DSH 版 · 已跑通) | 本方案(WorkBuddy 版) | 判定 |
|
||||
|---|---|---|---|
|
||||
| 手机侧 | 浏览器 + 门户登录态 | **Android 客户端**(用户要求) | ⚠️ 换形态 |
|
||||
| 平台侧 | 设备入口 / 五道闸 / 台账 / 配对 / 中继 | **完全相同** | ✅ 零改动 |
|
||||
| 设备侧暴露 | 垫片只绑 `127.0.0.1:20090` | **相同** | ✅ 复用 |
|
||||
| 垫片上游 | 本机 DSH Web(19387) | **WorkBuddy gateway(动态口)** | ⚠️ 改 |
|
||||
| 垫片凭据 | DSH 签名 Cookie(authority 绑定) | **gateway 令牌 → Cookie** | ⚠️ 改 |
|
||||
| 垫片承载 | DSH Host 侧插件 | **独立进程**(守护拉起) | ⚠️ 改 |
|
||||
| 对外端口 | **0 个**(全走 443) | **相同** | ✅ 复用它已验的分层 |
|
||||
| 会话库 | 桌面 DSH | **桌面 WorkBuddy**(同一份) | ⚠️ 换目标 |
|
||||
|
||||
---
|
||||
|
||||
## 5 分工与步骤
|
||||
|
||||
### 棒 0(前置 · 本会话,随时可做)—— 端口发现 + 只读实测
|
||||
|
||||
| # | 做什么 | 判据 |
|
||||
|---|---|---|
|
||||
| 0.1 | 写**端口发现**脚本(按 §3.4 三项判据) | 能稳定找到当前 gateway 口;⛔ 找不到即 fail-closed |
|
||||
| 0.2 | **U1 只读实测**:`/api/v1/jobs` 是否含**桌面正在聊的会话** | 有 ⇒ 本方案成立;无 ⇒ 只能操作 gateway 自起的会话(须回头改目标) |
|
||||
| 0.3 | 记录 `settings.gateway` / 令牌取得路径 | 令牌可得(用户敲 `/gateway status`) |
|
||||
|
||||
### 棒 1(设备侧 · **本地 dsh 客户端插件**)—— 垫片改造
|
||||
|
||||
| # | 做什么 | 判据 |
|
||||
|---|---|---|
|
||||
| 1.1 | fork `device-shim` 的 `forwardHeaders` 与反代骨架,**上游改 gateway** | `curl 127.0.0.1:<垫片口>/api/v1/jobs` 经垫片返回 JSON(不再 401) |
|
||||
| 1.2 | 凭据注入:首跳换 Cookie、之后复用 | 连续 50 次请求**无 429**(证明没在打限流) |
|
||||
| 1.3 | 改独立进程形态,写进节点守护的拉起清单 | 守护 `-Action status` 可见;停守护 ⇒ 端口撤 |
|
||||
| 1.4 | 端口声明:区间内新口(与 DSH 版**并存**,⛔ 不覆盖 20090) | relay `/status` 出现该端口 |
|
||||
|
||||
### 棒 2(平台侧 · **dsh 平台插件配合**)—— 零改动 + 一处确认
|
||||
|
||||
| # | 做什么 | 判据 |
|
||||
|---|---|---|
|
||||
| 2.1 | **确认** `device-web.ts` 的整站前缀转发对"非 DSH 后端"同样成立 | 经设备入口访问垫片,`/api/v1/jobs` 通 |
|
||||
| 2.2 | 若需**区分两条通道**(DSH / WorkBuddy),用**不同端口 + 不同设备行**区分,⛔ 不改判据 | 两条通道互不影响 |
|
||||
| 2.3 | 门户/接口层:让客户端能取到"我的设备"列表 | 客户端能列出可用设备 |
|
||||
|
||||
> ⚠️ **本条与用户口径的偏差(需说明)**:按核实结果,**平台侧不需要新插件** —— `device-web.ts` 已是通用的整站前缀转发,准入四道闸与后端是谁无关。⇒ "**dsh 平台插件配合**"这一项实际是**零改动**。若用户期望的是"平台侧也出一个插件形态的东西"(如 M 系列模块),那是**另一种做法**(在插件里再包一层),**成本更高且无必要** —— 见 §7 待确认项。
|
||||
|
||||
### 棒 3(手机侧 · Android 客户端)—— 已投对接单,**需按本方案更新**
|
||||
|
||||
| # | 做什么 | 判据 |
|
||||
|---|---|---|
|
||||
| 3.1 | **更新对接单**:D1 从"隧道/局域网"改为"**走 ai1net 覆盖网络**"(§8 已做) | 对接单里连接方式段已改 |
|
||||
| 3.2 | 客户端只认**设备入口地址**(`https://<门户>/u/<uid>/desk/<hostId>/…`)+ 平台登录态 | 手机打开即得会话列表 |
|
||||
| 3.3 | MVP:列表 / 历史 / **SSE 尾随** / 发送 / 重连 | 见对接单 §7 |
|
||||
|
||||
### 棒 4(联调)
|
||||
|
||||
真机端到端 + 断网重连 + **中继侧零协议改动**复核(判据:`src/net/relay/**` 无新增 op)。
|
||||
|
||||
---
|
||||
|
||||
## 6 风险与红线
|
||||
|
||||
| # | 项 | 处置 |
|
||||
|---|---|---|
|
||||
| 1 | **gateway 端口会变** | §3.4 动态发现 + fail-closed |
|
||||
| 2 | **限流(2/min)** | 垫片换 Cookie 后复用;⛔ 客户端不许轮询(对接单已列为硬约束) |
|
||||
| 3 | **权限面** | gateway 能**执行任务、改会话** ⇒ 设备入口准入**必须保持四道闸 + 默认关**;⛔ 不新增共享密钥、⛔ 不把令牌落平台库 |
|
||||
| 4 | **WorkBuddy 侧无 Host 插件形态** | 垫片改独立进程(§3.3);⛔ 不要试图做成 WorkBuddy 插件 |
|
||||
| 5 | **两条通道并存** | 端口/设备行分开,⛔ 不动 DSH 那条已验通的 |
|
||||
| 6 | **`E:/github/dsh-client` 0 commit** | 动它之前**先入库**(回滚唯一保障) |
|
||||
| 7 | R5 只收窄 | 本方案**不开任何对外端口**、不新增暴露面 ⇒ ✅ 合规 |
|
||||
|
||||
---
|
||||
|
||||
## 7 待确认(一轮一问)
|
||||
|
||||
**问题**:垫片(设备侧桥)放在哪个仓、由哪条线做?
|
||||
|
||||
**为什么需要你定**:垫片现在的家在 `E:/github/dsh-client/packages/device-shim`(属**手机接入线**的客户端仓),而它的**上游目标要改成 WorkBuddy**(属本会话的宿主侧知识)。归属不同,动的人不同,回滚责任也不同。
|
||||
|
||||
- **候选 1 · 在 `dsh-client` 仓新建同源包**(如 `packages/wb-gateway-shim`),由**手机接入线**做 —— 与既有垫片同源、复用最顺、风格一致。**缺点**:要跨线交接,本会话只能出规格不能落地。
|
||||
- **候选 2 · 由本会话另起一个独立小进程**,放在本工作区 —— 本会话可直接做完、闭环快。**缺点**:与既有垫片**两套代码**(同类逻辑两份),日后维护要记住两处。
|
||||
- **候选 3 · 直接改既有 `device-shim` 支持"上游可配"**(一个包两种目标)—— 一份代码、最省。**缺点**:动的是那条线**已验通**的成果(28 条判据绿),有回归风险。
|
||||
|
||||
**倾向候选 3 的变体**:**不改既有行为**,只给它加一个"上游目标"配置项(默认仍是 DSH,⛔ 不改变现有语义)⇒ 一份代码、零回归、两条通道共用。若那条线不同意,退候选 1。
|
||||
|
||||
---
|
||||
|
||||
## 附:本次取证读数
|
||||
|
||||
| # | 取证点 | 读数 |
|
||||
|---|---|---|
|
||||
| 1 | gateway 存活 | `127.0.0.1:59914` → **200**;重启前旧口 50753 → **502**(端口会变) |
|
||||
| 2 | 鉴权 | `/api/v1/health` → **401** |
|
||||
| 3 | 监听范围 | **仅 `127.0.0.1`** |
|
||||
| 4 | 中继区间(生产实测) | `--base 19000 --span 3000` ⇒ **19000..21999** |
|
||||
| 5 | 节点配置 | `ports:[20090]` · `relayUrl=wss://ai1net.com/dshs-relay`(走 443) |
|
||||
| 6 | 垫片现状 | DSH Host 侧插件;`inject:['connection','webServer']`;上游 = `webServer.port` |
|
||||
| 7 | 垫片关键变换 | `forwardHeaders(rawHeaders, authority, cookie)`:Host → authority、剥上游 set-cookie |
|
||||
| 8 | 平台设备入口 | `device-web.ts` 202 行,`/u/<uid>/desk/<hostId>/…`,五道闸单一入口,**整站前缀转发** |
|
||||
| 9 | 六个复用件 | 全部 **EXIST** |
|
||||
| 10 | gateway 官方后门 | `CODEBUDDY_CODE_CORS_ORIGINS` 环境变量 + `settings.gateway.corsOrigins`(如需配 origin 用) |
|
||||
Reference in new issue
Block a user