﻿P10-11 本地 NXAI ↔ 云端 HermesAgent/QQ 打通（一体化）

## 背景（用户 2026-10-20 09:48 说明）
「QQ 和云服务器已经联通，之前都部署好了。云服务器有多个 agent，也连接我的网站，网站有域名，
也有工作在自动运行。你只需要跟他做好连接工作。本地电脑运行时我打开本地跟你沟通，
没有运行时就是 QQ 与云服务沟通。大家都可以持续优化和更新。把这个变成一个整体。」

## 服务器现状（2026-10-20 SSH 实测，禁止再猜）
```
C:\agent-os\         backend / batch
C:\HermesAgent\      完整 agent 框架：.venv、gateway、acp_adapter、acp_registry、
                     cron、agent、apps、docs、docker、hermes_agent.egg-info（git 仓库）
C:\nxai-cloud\       app / data / memory / updates（我们自己那套，只有 /v1/update 可用）
进程：BaradAgent、HermesAgent 相关 python、nginx(80/443)、mysql(3306)、sgagent、tat_agent
监听：22, 80, 443, 3306, 8000, 8001, 8765, 8790, 3389
公网：https://ldeh.asia（首页 200；/nxai/v1/update/latest 200；/nxai/v1/agent 404）
```
结论：**agent 能力在 HermesAgent，不在 nxai-cloud**。本卡负责把两边接上，
不重写 Hermes，也不替换它。

## 一、先摸清 Hermes 的接口（只读，不改它）
1. SSH 到服务器，只读检查（禁止改 HermesAgent 下任何文件）：
   - `C:\HermesAgent\gateway\` 下有哪些入口（找 HTTP 路由定义、端口、鉴权方式）
   - `C:\HermesAgent\.env` / config / docs 里声明的 API base、token 变量名（**只记录变量名，不读值**）
   - 8000 / 8001 / 8765 三个端口各自的责任（哪个是 gateway、哪个是 web、哪个是 cron）
2. 把结论写 `docs\12_云端接口清单.md`：服务名 / 端口 / 路径 / 鉴权方式 / 用途 / 是否可用
3. 若 Hermes 有 OpenAPI 或 docs 端点，抓下来存 `docs\hermes_api.json`

## 二、定义双向契约（本卡核心产出）
新建 `docs\13_本地云端契约.md`，规定：

### 目录（服务器，沿用已存在的 nxai-cloud）
```
/C:/nxai-cloud/memory/    经验与记忆（已用，index.json 维护）
/C:/nxai-cloud/inbox/     云端 -> 本地 的任务与指令（QQ 来的话落这里）
/C:/nxai-cloud/outbox/    本地 -> 云端 的成果（NC/PNG/JSON/report）
/C:/nxai-cloud/archive/   历史（按 日期/零件 归档）
```

### 任务文件格式（JSON，双方都认）
```json
{
  "task_id": "uuid",
  "created_at": "2026-10-20T10:00:00+08:00",
  "source": "qq|web|local|agent",
  "kind": "prepare|stages|check|probe|post|freeform",
  "part": "绝对路径或云端相对路径",
  "params": {"material":"AL","stages":["rough","semi","finish"],"max_segment_minutes":60},
  "needs_nx": true,
  "status": "queued|taken|done|failed",
  "result": {"files": [], "summary": "", "log": ""}
}
```
- **needs_nx=true 的任务只能由本地执行**（云上没有 NX）。
- needs_nx=false 的任务云端可直接做（解析 NC、算时间、生成报告、归档）。

### 状态机与幂等
- 任务只能被"取走"一次（原子重命名 queued→taken，用服务器端脚本保证）
- 同名 task_id 重复投递视为覆盖，不重复执行
- 每个任务必须写 result 与 log；失败必须带 error 与 stderr 摘要

## 三、本地实现
新建 `tools\cloud_bridge.py`：
```
--push <文件或目录> --tag <批次>     上传到 outbox，更新 index
--pull                               拉 inbox 里 status=queued 且 needs_nx=true 的任务
--run --once                         执行一个任务（调用现有 one_click_prepare / stage_gen / 自检）
--result <task_id> --status done|failed --files a,b --summary "..." 
--watch --interval 60                轮询模式（本地开机时用）
-DryRun                              只打印将做什么
```
要求：
- 复用 `scripts\with_cloud_pwd.ps1` + paramiko（SFTP）通道，**不新增明文密码**
- 所有上传/下载后校验 size 与 sha256
- 断网/失败重试 3 次，之后写本地日志 `状态\cloud_bridge.log`，不阻塞本地加工主流程

## 四、云端侧（最小改动，不动 Hermes 主体）
在 `C:\nxai-cloud\` 下新增一个独立小服务 `bridge_worker.py`（不碰 Hermes 代码）：
- 每 30 秒扫 `inbox/`，把 needs_nx=false 的任务就地执行（解析 NC / 算时间 / 生成报告）
- 把结果写 `outbox/` 并更新 index
- 通过 Hermes 的 gateway（第 1 步查到的接口）把"有没有新成果"通知 QQ
- 若 gateway 接口不可用：退化为"只写文件 + 更新 index.json"，QQ 侧用轮询方式取

## 五、记忆同步（"大家都可以持续优化"）
- 本地 `docs\11_经验总结与交接.md` 与云端 `memory/` 双向同步：
  - 本地改了 → `cloud_bridge.py --push docs\11_... --tag memory`
  - 云端 agent 改了 → `--pull --memory` 拉回本地并 git diff 提示
- 冲突策略：以"最后修改时间 + 人工确认"为准，不自动覆盖，冲突时保留两份并提示

## 六、验收（必须实测）
1. `docs\12_云端接口清单.md` 真实内容（含 Hermes gateway 端口/路径/鉴权变量名）
2. 从本地推一个真实产物（例如 A01_粗_7-17.nc）到 outbox：贴出上传前后 size 与 sha256 一致
3. 在 inbox 放一个 needs_nx=false 任务，云端 worker 执行后：
   贴出 result JSON、outbox 里生成的文件名与大小
4. 在 inbox 放一个 needs_nx=true 任务，本地 `--pull` 能取到并列出（不必真跑 NX）
5. memory 双向同步各做一次，贴出两边的 mtime 与内容摘要
6. `cloud_bridge.log` 里失败重试与成功记录的真实片段
7. 门禁全绿 + 新增 .py 含 `P2-02 控制台编码护栏`

## 约束（红线）
- **不改 HermesAgent 下任何文件**（那是用户在跑的既有系统），只读探测
- 不在服务器上装软件、不改注册表、不改系统环境变量
- 不把任何密码/token 写进 D:\NX_AI 的明文文件
- NX 相关任务只在本地执行；云端不得尝试跑 NX
- 不改 nxai-cloud 的 /v1/update 现有行为
- 完成后写 `状态\P10-11.done.json`
