62 lines
5.3 KiB
Markdown
62 lines
5.3 KiB
Markdown
# 交接单 · 桌面线:设备接入垫片**常驻化**(V1 最后一跳)
|
||||
|
|
|
|||
|
|
- 出具:主会话(手机接入线)· 2026-09-30 10:2x
|
|||
|
|
- 归属线:**ai1net-dsh-desktop**(桌面/客户端线)
|
|||
|
|
- 目标:手机查看并可回复桌面 WorkBuddy 中会话(`[手机接入]`)
|
|||
|
|
- 🔴 **这一件是 V1 的最后一跳**(V2–V7 已全 pass,V1 唯一非 pass)
|
|||
|
|
|
|||
|
|
## 一、你接手时的既成事实(⛔ 别重做,别推翻)
|
|||
|
|
|
|||
|
|
**A 方案(口令入站通道)已由本线落地并端到端实证** —— 它解决的是"**脱离会话起的垫片拿不到网关口令**":
|
|||
|
|
|
|||
|
|
| 侧 | 改了什么 | 位置 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 插件侧 | 新增只绑回环的 `POST /__device_access/token`:**内存持有**(不落盘/不进日志/不回显)+ **探活通过才采纳**;`credentialDesc()`/`readGatewayToken()` 改为 **env 优先、其次内存入站** | `E:/ProgramData/AIProject/dsh-plugin-ai1net/lib/device-access.js`(模块⑥;`dist/` 已同步,md5 与 lib 一致) |
|
|||
|
|
| 宿主侧 | `deliver-gateway-token.py`(在哪一侧投、60s 节流、只打回环、失败静默 rc=0)+ 钩子 `PreToolUse` 接管 | `…ai1net-dsh-server/.workbuddy/collab/deliver-gateway-token.py`、`.workbuddy/tools/wb-result-hook.py` |
|
|||
|
|
|
|||
|
|
**实测读数(可复跑)**:
|
|||
|
|
```
|
|||
|
|
脱离会话式起法(env 里没有口令)
|
|||
|
|
自检 → credential.source=missing present=false ← 现状:只能 503
|
|||
|
|
塞错口令 → 400 token-rejected-by-gateway ← 安全阀有效,⛔ 没被塞坏
|
|||
|
|
投真口令 → 200 {"credential":{"source":"inbound","present":true}}
|
|||
|
|
经垫片打 /api/v1/health → 200 ← 口令真被带上并转发成功
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
🔑 **由此解掉的那个堵点**:A 之前"用计划任务起桌面栈"是**走不通**的(计划任务上下文 `envPresent=false / envLen=0`,垫片 fail-closed `rc=3`)⇒ **现在不堵了**:垫片能在**没有口令**的情况下先起来(它只在 20090 上监听,"口令缺失"不阻止监听),随后由钩子把口令投进去。
|
|||
|
|
|
|||
|
|
## 二、请你做的(三件,按顺序)
|
|||
|
|
|
|||
|
|
1. **找/确认"不起 Electron UI 也能把 DSH 宿主拉起来"的起法**
|
|||
|
|
- 已知障碍:`launch-desktop-dev-017.mts`(`ai1net-dsh-desktop/.workbuddy/_devkit/`)**没有无界面开关**,它 `require('electron')` 并用 **electron 内置 node** 跑宿主(`release.nodeVersion = electron 的 node 版本`)。
|
|||
|
|
- 要判的:`apps/desktop-host`(`@deepseek-ai/dsh-desktop-host`,`main=lib/index.js`)能否用**普通 node** 直接起(它是否真依赖 Electron API)。**能** ⇒ 首选;**不能** ⇒ 走"启动文件夹/独立窗口"(`deploy.md §5b` 已列的三条死路之外那条可行路)。
|
|||
|
|
2. **把它做成durable**(⛔ 挂在某个会话名下会随会话回收而断 —— 这是已知遗留单点)
|
|||
|
|
- 候选:**启动文件夹** / **计划任务**(`schtasks` 被程序黑名单硬拦,但 §5b 说计划任务这条路对**中继客户端**已走通 ⇒ 照那条走)。
|
|||
|
|
- ✅ A 已使"计划任务"重新可行(见上)。
|
|||
|
|
3. **起来了就验**(判据,⛔ 不许只看"进程在")
|
|||
|
|
- `20090` **LISTENING**(⛔ 只认 `netstat`,本机有 Proxifier 会代理回环 ⇒ `curl`/`connect` 会假阳);
|
|||
|
|
- `curl --noproxy '*' http://127.0.0.1:20090/__device_access/selfcheck` ⇒ `credential.present=true`(`source` 应为 `env:…` 或 `inbound`);
|
|||
|
|
- `curl --noproxy '*' http://127.0.0.1:20090/api/v1/health` ⇒ **非 401**;
|
|||
|
|
- **最后一枪**:打平台设备入口 `https://ai1net.com/u/bdf89014-c66f-4060-a2df-995d8c18a951/desk/d-bdf89014-c66f-4060-a2df-995d8c18a951-626dc095/api/v1/info`(**要带门户会话 Cookie**)⇒ **不再是 `503 {"error":"instance_starting"}`**。
|
|||
|
|
⚠️ 复现姿势(我踩过):`sid` 是 **Secure** cookie ⇒ `http://127.0.0.1:3080` **不带 Cookie**会假回 401;必须 `curl -k --resolve ai1net.com:443:127.0.0.1` 走 https。
|
|||
|
|
- 验不到口令自动进来时:`curl -X POST --data "<口令>" http://127.0.0.1:20090/__device_access/token`(⚠️ 别把口令写进命令历史/日志)。
|
|||
|
|
|
|||
|
|
## 三、边界(⛔ 越线即事故)
|
|||
|
|
|
|||
|
|
- ⛔ **不要改 A 的通道设计**(尤其⛔ 不许去掉"**探活通过才采纳**"那一步 —— 只绑回环的端点若无条件采纳,一个错口令就能把垫片打成持续 401)。
|
|||
|
|
- ⛔ **不要让口令落盘**(不改回 C 方案)。
|
|||
|
|
- ⛔ 不动正在跑的看板 `127.0.0.1:8788`(它是主会话起的,还挂着)。
|
|||
|
|
- ⛔ 不动中继客户端(`DSH-Overlay-Node-Dev`):它已治本、且是手机接入线的关键路径。
|
|||
|
|
- ⚠️ 若判断"必须起 Electron UI",**先回报**(那会弹窗口且活不过会话,净收益要重新算)。
|
|||
|
|
|
|||
|
|
## 四、判据汇总(做完回报用)
|
|||
|
|
|
|||
|
|
| # | 判据 | 期望 |
|
|||
|
|
|---|---|---|
|
|||
|
|
| 1 | `20090` LISTENING | ✅(只认 netstat) |
|
|||
|
|
| 2 | 自检 `credential.present` | `true`(`source=env:*` 或 `inbound`) |
|
|||
|
|
| 3 | 经垫片 `/api/v1/health` | 非 401 |
|
|||
|
|
| 4 | 平台设备入口 | **不再 503 `instance_starting`** |
|
|||
|
|
| 5 | 起法是否 durable | 说明挂在哪个持久机制上(启动文件夹/计划任务),⛔ 不是"某条会话" |
|
|||
|
|
|
|||
|
|
**回报落点**:本工作区 `交付物/`,并在回报里**明确写**「V1 的最后一跳是否打通」——它决定 `goal.json.acceptance_state.V1` 能否置 pass。
|