Files
nodeagent/docs/RETROSPECTIVE.md
T
jkooe 3f91e1ddc0 docs: 新增《实战复盘:短板与改进优先级》
基于真机部署 + v2rayN 故障排查 + 重装前采集的真实使用,梳理短板:

P0(决定能不能用)
1. GUI 语义能力缺失 —— 有截屏有鼠标,但没有「界面元素 -> 坐标」的映射,
   切个节点反复点错三次,最后靠键盘导航才成功。建议引入 UIA。
2. 编码不统一 —— 三个真实事故均源于此:Set-Content 写 BOM 致 agent 起不来、
   PowerShell 管道损坏中文致清单报废、控制台 GBK 误判。
3. 自断生路 —— 重启 agent 时分离进程被自身进程树清理一起杀掉,导致失联。
   建议提供受控重启(system.agent.restart)+ 看门狗自愈 + 配置回滚。
4. exec 输出未结构化 —— 尾部附加 [退出码/耗时] 文本,污染 JSON 解析。

P1:长任务异步化、定时采样、剪贴板、窗口管理、CLI 常驻 daemon
P2:事件订阅、文件监控、录屏、拖拽/宏、多设备并行、DPAPI

一句话:能看能算能跑命令已扎实,短板在「语义」(读不懂界面)、
「状态」(只看当下)与「自持」(改不动自己)。
2026-09-28 22:01:15 +08:00

244 lines
10 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# nodeagent 实战复盘:短板、瓶颈与改进优先级
> 基于 2026-09-27 ~ 09-28 的真实使用(Windows 真机部署 + v2rayN 故障排查 + 重装前信息采集)
> 所有问题均来自**实际踩坑**,非理论推演。
---
## 一、最痛的问题:GUI 语义能力缺失(P0)
### 场景还原
排查 v2rayN 节点问题时,臣需要**切换活动节点**:
| 尝试 | 结果 |
|---|---|
| 算坐标点击第 2 行 | ❌ 点到第 1 行 |
| 重新算坐标再点 | ❌ 又点到第 3 行 |
| 改用键盘 `↑`/`↓`/`Enter` | ✅ 成功 |
**问题本质**:臣有 `screen.capture`(能**看**)和 `input.mouse.*`(能**点**),但**没有把「看到的界面元素」映射为「可点击坐标」的能力**。
每次都要:截图 → 人眼估算像素 → 换算缩放的 region 偏移 → 点击 → 再截图验证。**误差极大,反复试错**。
### 改进方向(按性价比排序)
1. **UI 元素定位能力**(最关键)
- `screen.find(text)` / `screen.find(image)`:返回元素坐标
- Windows 侧可用 **UI Automation (UIA)** —— 原生支持,能直接枚举窗口控件树
- 实现成本中等,收益极高
2. **截图附带坐标网格**
- `screen.capture` 可选叠加坐标标尺(每 100px 标线)
- 臣看图即可精确推算坐标,无需盲试
3. **鼠标相对定位**
- `input.mouse.move` 支持 `--relative dx dy`(当前只有绝对坐标)
4. **窗口管理**
- `window.list` / `window.focus(title)` / `window.rect(title)`
- 先聚焦目标窗口并拿到精确矩形,再在窗口内相对定位 —— **比全屏算坐标可靠得多**
---
## 二、编码与跨平台:反复踩的坑(P0)
### 三个真实事故
| # | 事故 | 根因 | 后果 |
|---|---|---|---|
| 1 | agent 装了却起不来 | PowerShell `Set-Content -Encoding UTF8` **写入了 BOM** | `JSON.parse` 崩,排查半天 |
| 2 | 软件清单中文全变 `�����` | PowerShell → shell **管道损坏 UTF-8** | 清单报废,重采一次 |
| 3 | 终端输出中文乱码 | Windows 控制台默认 GBK | 多次误判 |
### 改进方向
1. **能力层统一 UTF-8**(在 Windows 侧强制)
- `system.shell.exec` 应**自动注入**:
```powershell
[Console]::OutputEncoding = [System.Text.UTF8Encoding]::new()
$OutputEncoding = [Console]::OutputEncoding
```
- 从根上解决 2、3
2. **新增 `fs.write_text` / `fs.read_text`**(明确 UTF-8 无 BOM 语义)
- 或者给 `fs.write` 增加 `encoding: 'utf8' | 'utf8-bom' | 'gbk'` 参数
- 让「写配置文件」这类高频操作**默认安全**
3. **结构化返回**(不靠文本传递)
- 现在 `exec` 的输出是**纯文本 + 尾部附加 `[退出码 0 · 410ms]`**,导致臣解析 JSON 时被污染
- 应改为**结构化字段**:`{ stdout, stderr, exit_code, duration_ms }` —— 后端本来就有,只是 CLI 拼接成文本了
---
## 三、进程与生命周期:自断生路(P0)
### 场景还原
臣用 `system.shell.exec` 执行「杀旧 agent + 启新 agent」来让配置生效:
```
Start-Process powershell -ArgumentList '... Start-Sleep 3; Stop-Process ...; Start-Process node.exe ...'
```
**结果**:**分离的 PowerShell 被 agent 的进程树清理逻辑一起杀掉了** → 新 agent 从未启动 → 端口僵死 → **臣彻底失联**,只能请皇上手动恢复。
### 改进方向
1. **受控重启能力**(最高优先)
```
system.agent.restart { delay_ms: 2000 }
```
- 由 agent **自己**实现:fork 一个「延时重启器」(脱离进程组),或注册一次性计划任务
- 重启后**主动回连/上报**,让控制端知道「我回来了」
- 这样 90% 的配置变更新场景都不再需要皇上介入
2. **健康检查与自愈**
- agent 内置看门狗:若 N 秒内未响应,自我重启
- 启动失败时**自动回滚**到上一份可用配置(配合配置快照)
3. **分离进程的明确语义**
- 提供 `spawn` 能力(明确「不随命令结束而终止」),而不是让用户用 `Start-Process` 碰运气
- 或者:`exec` 增加 `detach: true` 参数
4. **改端口/改配置前先"预演"**
- 支持用一个临时配置在**旁路端口**试启动,成功再切换 —— 这正是这次出事后臣总结的正确做法
---
## 四、可观测性与长时任务(P1)
### 场景还原
- 代理不通问题**反复发作**,但臣只能看**当下快照**(`netstat`、`Get-Process`),**无法看到 5 分钟前的状态**
- 想跑「持续 5 分钟、每 2 秒记录一次连接状态」的采样 → **`exec` 默认 30 秒超时**,长命令直接被砍
- 排查 360 拦截时,需要「退出 360 前后对比」→ **臣无法安排这个时序**
### 改进方向
1. **长任务异步化**
```
system.shell.exec { command, timeout_ms, async: true } → 返回 task_id
system.task.get { task_id } / system.task.log { task_id } / system.task.kill
```
- 现在超时只能靠调用方抬 `timeout_ms`,且**命令一旦超时整条被杀**,无法续接
2. **定时采样能力**
```
monitor.start { interval_ms, command | metric, duration_ms } → 落盘
monitor.report { id }
```
- 专治「间歇性问题」—— 这次代理不通就是典型的间歇性/条件性问题
3. **事件订阅(push 模型)**
- 现在全是**拉取式**(臣问一次,答一次)
- 应该支持:`subscribe { events: ['process.crash','net.change','file.change'] }`
- 让被控端**主动推**异常,而不是等臣去查
4. **日志聚合查询**
- 这次查 v2rayN 日志,臣只能 `Get-Content -Tail N` 手工翻
- 应提供 `log.query { path, since, level, pattern, limit }`,由被控端侧做高效过滤
---
## 五、能力缺口清单(P1~P2)
| 缺口 | 场景影响 | 优先级 |
|---|---|---|
| **剪贴板读写**(`clip.get`/`clip.set`) | 传文本要绕大圈(写文件→读文件) | **P1** |
| **窗口管理**(列举/聚焦/移动) | GUI 操作的基础设施 | **P1** |
| **文件监控**(`fs.watch`) | 等某个文件生成、监控配置变更 | P2 |
| **截屏区域智能裁剪** | 现在要手工算 region | P2 |
| **录屏 / 连续帧** | 动态过程(如安装向导)无法观察 | P2 |
| **键盘组合键序列**(宏) | 现在 `key press` 一次只能一种组合 | P2 |
| **鼠标拖拽**(drag & drop) | 只支持 move/click/scroll | P2 |
| **`app.list` 的 winget 补充** | 与 PRD 描述不符(只有注册表+商店) | P2 |
| **`app.install` 的静默安装降级** | winget 之外无兜底(PRD T2 未闭环) | P2 |
| **并发 RPC** | WS 单连接串行,批量操作慢 | P2 |
| **多设备并行执行** | 现在只能 `--node` 串行切换 | P2 |
---
## 六、性能观察(实测数据)
| 操作 | 实测 | 评价 |
|---|---|---|
| 31MB 文件传输 | **1.66 秒**(~19MB/s) | ✅ 够用 |
| 截屏 1720×720 | ~1-2 秒 | ⚠️ base64 传输有开销 |
| 列出 178 款软件 | ~9 秒(含 winget 调用) | ⚠️ 偏慢 |
| 单次 `exec` 往返 | 300~600ms | ⚠️ 每次重建连接的代价 |
| 连接建立(wss 握手) | ~1-2 秒 | ⚠️ CLI 每次调用都重连 |
**瓶颈判断**:
- **最慢的是"每次调用重建连接"** —— CLI 模式无连接复用
- 建议:**CLI 增加常驻 daemon 模式**(`nodeagent serve` 本地跑一个,命令走本地 socket 转发)
---
## 七、体验问题
| 问题 | 具体表现 |
|---|---|
| **CLI 参数记忆成本高** | `--args` 的 JSON 转义极易出错(这次反复失败) |
| **错误信息不够可操作** | `E_CAPABILITY_DISABLED: 输入控制已禁用` —— 没说「怎么开」 |
| **无交互式会话** | 每次命令独立,无法「进入某个上下文后连续操作」 |
| **日志与结果混在一起** | agent 的日志和命令输出同流,污染数据 |
| **`key press` 多键限制** | `key press up up up` 报 `E_PARAM_INVALID`,只能循环调用 |
| **审计日志无查询便利** | 能做 `audit` 但无过滤/聚合 |
---
## 八、安全方面(已有基础,待加固)
| 项 | 现状 | 建议 |
|---|---|---|
| 密钥存储 | 明文落盘(600 权限) | **DPAPI**(Windows)/ Keychain(macOS) |
| 审计完整性 | JSONL 追加 | 增加**链式哈希**防篡改 |
| 调用取消 | ❌ 无 | 长任务应支持 cancel |
| 能力授权 | ✅ 能力级 ACL(做得不错) | 可细化到「路径级」「命令白名单级」 |
| 速率限制 | ✅ 有 | 可增加「异常行为告警」 |
---
## 九、优先级建议(如果要排期)
### P0 —— 直接决定"能不能用起来"
| # | 改进 | 理由 |
|---|---|---|
| 1 | **UI 元素定位(UIA)** | GUI 操作从"反复试错"变"一次命中",这次最痛 |
| 2 | **受控重启 + 自愈** | 从根上消灭「自断生路」,配置变更不再需要人工 |
| 3 | **编码统一(UTF-8 全链路)** | 三个事故都由此而来,且每次排查都耗时 |
| 4 | **exec 结构化返回** | 消除输出污染,是所有自动化的基础 |
### P1 —— 决定"用得顺不顺"
| # | 改进 |
|---|---|
| 5 | 长任务异步化(`async: true` + task_id) |
| 6 | 定时采样 / 监控(治间歇性问题) |
| 7 | 剪贴板读写 |
| 8 | 窗口管理 |
| 9 | CLI 常驻 daemon(连接复用,提速) |
### P2 —— 决定"用得爽不爽"
10. 事件订阅(push 模型)
11. 文件监控 / 录屏
12. 日志聚合查询
13. 鼠标拖拽 / 键盘宏
14. 多设备并行
15. DPAPI 密钥保护
---
## 十、一句话总结
**nodeagent 在「能看、能算、能跑命令」这条线上已经相当扎实** ——
19 项能力、真实文件传输、审计闭环都经得起实战。
**它现在的真正短板集中在三个字:`语义` 与 `状态`。**
- **语义**:看得到画面,但读不懂界面(缺 UI 元素理解)
- **状态**:只看得到当下,看不到变化(缺长时观测)
- **自持**:改得动别人,改不动自己(缺自愈与受控重启)
把这三块补上,它就从「远程命令行工具」进化为「**真正的远程操作代理**」。