|
@@ -0,0 +1,344 @@
|
|
|
|
|
+# 容器初始化流程优化建议(基于 workshop-avatar 实操)
|
|
|
|
|
+
|
|
|
|
|
+| 字段 | 值 |
|
|
|
|
|
+|---|---|
|
|
|
|
|
+| 文档编号 | 建议-20261020-容器初始化优化 |
|
|
|
|
|
+| 版本 | v1.0 |
|
|
|
|
|
+| 创建日期 | 2026-10-20 |
|
|
|
|
|
+| 来源 | `https://fmode.cn/aipm-lesson/workshops/avatar-camp/workshop-avatar.html`(数字分身实战营)+ **本次 lj-test 实测踩坑** |
|
|
|
|
|
+| 目的 | 按实操中发现的问题,给出**初始化提示词/流程**的具体优化点 |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 一、现有流程(workshop-avatar 实际做了什么)
|
|
|
|
|
+
|
|
|
|
|
+### 1.1 五章结构
|
|
|
|
|
+
|
|
|
|
|
+| 章节 | 内容 | 谁做 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| **CH1** | Harness 部署:初始化工程架构 + 材料整理 + 数字分身初始化 + cc 无人驾驶 | 工具为主 |
|
|
|
|
|
+| **CH2** | 数据本体 · 诊断分析 | 人为主(回答)|
|
|
|
|
|
+| **CH3** | 数据本体 · 架构设计 | 人为主(拍板)|
|
|
|
|
|
+| **CH4** | 数据本体 · RSI 架构 | 数字分身为主 |
|
|
|
|
|
+| **CH5** | 数据本体 · 复盘报告 | 数字分身为主 |
|
|
|
|
|
+
|
|
|
|
|
+### 1.2 "绑定数字员工"流程(实测页面逻辑)
|
|
|
|
|
+
|
|
|
|
|
+```
|
|
|
|
|
+① 平台账号登录(手机号 + 验证码)
|
|
|
|
|
+ ↓ POST /api/fmode/mobile?mobile=&code=
|
|
|
|
|
+② 绑定数字员工(点「绑定数字员工」)
|
|
|
|
|
+ ↓ 选择通道
|
|
|
|
|
+ ┌────────────┴────────────┐
|
|
|
|
|
+ 企业微信 飞书(中国版)
|
|
|
|
|
+ ↓ ↓
|
|
|
|
|
+ 扫码绑定 / 手动输入 扫码 / 手动
|
|
|
|
|
+ ↓ ↓
|
|
|
|
|
+ 填 BotID + Secret 填 AppID + AppSecret
|
|
|
|
|
+ ↓ ↓
|
|
|
|
|
+ 保存并绑定 保存并绑定
|
|
|
|
|
+ ↓ ↓
|
|
|
|
|
+ POST /api/fmode/hermes/wecom-cloud/manual-bind
|
|
|
|
|
+ body: { sessionToken, botId, secret }
|
|
|
|
|
+ ↓
|
|
|
|
|
+ 返回「数字员工已绑定 / 机器人信息已保存到当前账号」
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**页面上的三条 CH1 提示词**:
|
|
|
|
|
+
|
|
|
|
|
+| 步骤 | 提示词作用 |
|
|
|
|
|
+|---|---|
|
|
|
|
|
+| **Harness 01** | 初始化工程架构(接平台云资源 + 装核心技能)|
|
|
|
|
|
+| **Harness 02** | 材料整理到 `./storage` |
|
|
|
|
|
+| **Harness 03** | **数字分身初始化**(装 Loop 技能 + 平台登录 + **领取企业资源**)|
|
|
|
|
|
+| **Harness 04** | 唤醒数字分身(环境自检)|
|
|
|
|
|
+| **Harness 05** | 数字 DNA 初始化(建仓建档)|
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 二、🔴 本次实测发现的 5 个问题
|
|
|
|
|
+
|
|
|
|
|
+> 全部来自 `agent-node-lj-test` 容器的真实排查
|
|
|
|
|
+
|
|
|
|
|
+### 问题 1 · **reporter 根本没部署**(最严重)
|
|
|
|
|
+
|
|
|
|
|
+**现象**:
|
|
|
|
|
+```
|
|
|
|
|
+/opt/data/git-repos/ → ❌ 目录不存在
|
|
|
|
|
+status-report.py → ❌ 全盘找不到
|
|
|
|
|
+crontab → ❌ 容器没装
|
|
|
|
|
+AGENT_ID → ❌ 空
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**结果**:容器从不向 `FmodeAgent` 表写记录 → **App 完全看不到它**
|
|
|
|
|
+
|
|
|
|
|
+**根因**:workshop 的 Harness 流程**没包含 reporter 部署步骤**
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### 问题 2 · **容器上报的字段格式与平台契约不符**
|
|
|
|
|
+
|
|
|
|
|
+**实测数据**(容器上报 vs 平台要求):
|
|
|
|
|
+
|
|
|
|
|
+| 字段 | 容器上报 | 平台要求 | 后果 |
|
|
|
|
|
+|---|---|---|---|
|
|
|
|
|
+| **`channels`** | `["wecom"]`(**数组**)| `{"matrix":true,"matrixConfig":{...},"wecom":true,...}`(**对象**)| 🔴 App 判 `channels.matrix` = `undefined` → **显示"未接入"** |
|
|
|
|
|
+| **`host`** | `{"cpuLoad1":24.09, "cpuLoad5":13.68, "memPercent":54.9, ...}` | `{"cpuPercent":N,"memPercent":N,"diskPercent":N}` | 🔴 缺 `cpuPercent` → **CPU 显示不出来**(内存/磁盘能显示,因为名字对上了)|
|
|
|
|
|
+| **`usage`** | 空 | `{"totalTokens":N,"promptTokens":N,...}` | 🔴 Token 用量不显示 |
|
|
|
|
|
+| **`heartbeatAt`** | 空 | ISO 时间戳 | 🔴 心跳不更新 |
|
|
|
|
|
+| **`progress`** | 空 | 0-100 | 任务进度不显示 |
|
|
|
|
|
+
|
|
|
|
|
+**根因**:容器用的是**复刻版**上报脚本,字段命名自己定的,**没对齐平台契约**
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### 问题 3 · **上报调错了云函数**
|
|
|
|
|
+
|
|
|
|
|
+**现象**:容器上报返回
|
|
|
|
|
+```json
|
|
|
|
|
+{"code":200,"ok":true,"key":"user/xhVRjTMwQH/log/20261020/1004.json","publicUrl":"https://s3.fmode.cn/..."}
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**这是「上传日志文件到 OBS」**,不是「更新 FmodeAgent」
|
|
|
|
|
+
|
|
|
|
|
+| 云函数 | 用途 | 容器用了 |
|
|
|
|
|
+|---|---|---|
|
|
|
|
|
+| `xlosi3m46q` | ✅ **状态上报**(fmodeagent-status)| ❌ |
|
|
|
|
|
+| `AlP56LCKFm` | OBS 上传签名 | ✅ **误用** |
|
|
|
|
|
+
|
|
|
|
|
+**后果**:数据进了存储桶,**没进 FmodeAgent 表** → App 看不到
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### 问题 4 · **Agent 与用户的归属三方不一致**
|
|
|
|
|
+
|
|
|
|
|
+**实测**:
|
|
|
|
|
+```
|
|
|
|
|
+FmodeAgent.user → sr2WiPsDyQ(刘雨飏 / 18691770343)
|
|
|
|
|
+FmodeAgent.company → rpnXZC1loU(脑控科技)
|
|
|
|
|
+容器里的 token → r.dd15...(用户9836 / 19170119836)
|
|
|
|
|
+容器名 → agent-node-lj-test
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+**三个地方三个答案**。
|
|
|
|
|
+
|
|
|
|
|
+**根因**:容器初始化时**没校验**「容器 → 用户 → 公司」的一致性
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### 问题 5 · **同一 Agent 出现两条绑定**
|
|
|
|
|
+
|
|
|
|
|
+**实测**:`FmodeMatrixBinding` 里 `agentId=agent-node-lj-test` 有 **2 条**:
|
|
|
|
|
+- 第 1 条:`userPointer=sr2WiPsDyQ`(刘雨飏),room `!OIm7iWR6...`
|
|
|
|
|
+- 第 2 条:`userPointer=xhVRjTMwQH`(你),room `!miyB1DxRE...`
|
|
|
|
|
+
|
|
|
|
|
+**两条都 `active`**。
|
|
|
|
|
+
|
|
|
|
|
+**后果**:不同用户进同一 Agent 会拿到不同房间 → 数据割裂
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 三、优化建议(按优先级)
|
|
|
|
|
+
|
|
|
|
|
+### P0 · 在 Harness 流程中**新增「reporter 部署」步骤**
|
|
|
|
|
+
|
|
|
|
|
+**新增一步(建议放在 Harness 03 之后)**:
|
|
|
|
|
+
|
|
|
|
|
+```markdown
|
|
|
|
|
+## Harness 03.5 · 状态上报(reporter)部署
|
|
|
|
|
+
|
|
|
|
|
+在容器内执行(不需要你手动操作,交给数字分身):
|
|
|
|
|
+
|
|
|
|
|
+1. 建目录
|
|
|
|
|
+ mkdir -p /opt/data/git-repos/agent-status-reporter/{scripts,state}
|
|
|
|
|
+
|
|
|
|
|
+2. 拷脚本(原版 v10,1100 行)
|
|
|
|
|
+ · 从平台仓库下载:https://repos.fmode.cn/.../agent-status-reporter/status-report.py
|
|
|
|
|
+ · 或从同宿主其他正常容器 docker cp
|
|
|
|
|
+
|
|
|
|
|
+3. 配 env(写 /opt/data/.env,先备份)
|
|
|
|
|
+ AGENT_ID=<FmodeAgent.agentId>
|
|
|
|
|
+ FMODE_SESSION_TOKEN=<你的 sessionToken>
|
|
|
|
|
+
|
|
|
|
|
+4. 常驻(crontab 不可用时的替代)
|
|
|
|
|
+ · s6 服务 或 无限循环 nohup
|
|
|
|
|
+
|
|
|
|
|
+5. 验证
|
|
|
|
|
+ 手动跑一次 → 返回 {"code":200,"field":"host",...}
|
|
|
|
|
+ 然后去 App 工作台看是否有 CPU/内存数字
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### P0 · 上报走**正确云函数** + **标准字段格式**
|
|
|
|
|
+
|
|
|
|
|
+**明确写进提示词**:
|
|
|
|
|
+
|
|
|
|
|
+```markdown
|
|
|
|
|
+## 状态上报接口(唯一正确用法)
|
|
|
|
|
+
|
|
|
|
|
+POST https://server.fmode.cn/api/functions
|
|
|
|
|
+Body: {
|
|
|
|
|
+ "id": "xlosi3m46q", ← 🔴 必须用这个
|
|
|
|
|
+ "token": "<FMODE_SESSION_TOKEN>",
|
|
|
|
|
+ "params": {
|
|
|
|
|
+ "op": "update",
|
|
|
|
|
+ "agentId": "<你的 agentId>",
|
|
|
|
|
+ "field": "<字段名>",
|
|
|
|
|
+ "value": "<值>"
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+⚠️ 不要用 AlP56LCKFm(那是 OBS 上传签名)
|
|
|
|
|
+
|
|
|
|
|
+### 字段格式(必须严格对齐)
|
|
|
|
|
+
|
|
|
|
|
+host(JSON 字符串):
|
|
|
|
|
+ {"cpuPercent": 12.5, "memPercent": 38.2, "diskPercent": 35}
|
|
|
|
|
+ 🔴 用 cpuPercent(不是 cpuLoad1/cpuLoad5)
|
|
|
|
|
+ 🔴 cpuPercent = cpuLoad1 / cpu核数 * 100(或读 /proc/stat)
|
|
|
|
|
+
|
|
|
|
|
+channels(JSON 字符串,🔴 必须是对象不是数组):
|
|
|
|
|
+ {
|
|
|
|
|
+ "homeserver": "https://matrix.fmode.cn",
|
|
|
|
|
+ "matrix": true,
|
|
|
|
|
+ "matrixConfig": {"userId": "@<mxid>", "channelState": "connected", "listenerOk": true},
|
|
|
|
|
+ "wecom": true,
|
|
|
|
|
+ "wecomBotId": "<BotID>",
|
|
|
|
|
+ "wecomConfig": {"botId": "<BotID>", "connected": true}
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+balance(JSON 字符串):
|
|
|
|
|
+ {"remainCny": 17842.31, "source": "session"}
|
|
|
|
|
+
|
|
|
|
|
+usage(JSON 字符串):
|
|
|
|
|
+ {"totalTokens": 123456, "promptTokens": 100000, "completionTokens": 23456}
|
|
|
|
|
+
|
|
|
|
|
+heartbeatAt:ISO 时间戳(每次上报必须更新)
|
|
|
|
|
+progress:0-100
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### P1 · 初始化时**校验归属一致性**
|
|
|
|
|
+
|
|
|
|
|
+**新增自检步骤**:
|
|
|
|
|
+
|
|
|
|
|
+```markdown
|
|
|
|
|
+## 初始化自检:身份三方对齐
|
|
|
|
|
+
|
|
|
|
|
+登录后、绑定机器人前,确认以下三项**指向同一个账号**:
|
|
|
|
|
+
|
|
|
|
|
+1. 你的 sessionToken 解析出的 userid
|
|
|
|
|
+ GET https://server.fmode.cn/parse/users/me
|
|
|
|
|
+ → objectId / mobile / company
|
|
|
|
|
+
|
|
|
|
|
+2. FmodeAgent 记录(如有)
|
|
|
|
|
+ where={agentId:<你的agentId>}
|
|
|
|
|
+ → user 指针 / company 指针
|
|
|
|
|
+
|
|
|
|
|
+3. 容器内 env
|
|
|
|
|
+ AGENT_ID / FMODE_SESSION_TOKEN / WECOM_BOT_ID
|
|
|
|
|
+
|
|
|
|
|
+✅ 正确:user.objectId === token 解析出的 objectId
|
|
|
|
|
+❌ 不一致:立即停止,向主人报告「归属不一致:<详情>」,不要强行绑定
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### P1 · 绑定数字员工后**自动创建/更新 FmodeAgent**
|
|
|
|
|
+
|
|
|
|
|
+**当前流程**:扫码/手填 → `manual-bind` → 只保存到"当前账号"
|
|
|
|
|
+**缺失**:**没同步到 `FmodeAgent` 表**
|
|
|
|
|
+
|
|
|
|
|
+**建议**:`manual-bind` 成功后**自动**:
|
|
|
|
|
+1. 按 `agentId` 查/建 `FmodeAgent` 记录
|
|
|
|
|
+2. 写入 `user` 指针(= 当前登录用户)
|
|
|
|
|
+3. 写入 `company`(= 用户所属公司)
|
|
|
|
|
+4. 写入 `channels.wecomBotId` + `channels.wecom = true`
|
|
|
|
|
+5. 清掉该 agentId 的**旧绑定**(避免问题 5 的重复绑定)
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+### P2 · 提示词补充「验证清单」
|
|
|
|
|
+
|
|
|
|
|
+**在每个 Harness 步骤末尾加验收标准**:
|
|
|
|
|
+
|
|
|
|
|
+```markdown
|
|
|
|
|
+## 验收(做完必须逐条确认)
|
|
|
|
|
+
|
|
|
|
|
+□ reporter 进程在跑(ps aux | grep status-report)
|
|
|
|
|
+□ 手动上报返回 {"code":200,"field":"host"}
|
|
|
|
|
+□ App 工作台能看到 CPU/内存/余额
|
|
|
|
|
+□ App 会话列表状态徽标显示「在线」
|
|
|
|
|
+□ channels 是对象不是数组
|
|
|
|
|
+□ host 里有 cpuPercent 字段
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 四、给容器的**完整部署提示词**(可直接用)
|
|
|
|
|
+
|
|
|
|
|
+```markdown
|
|
|
|
|
+【任务】部署状态上报(reporter),让 App 能看到你
|
|
|
|
|
+
|
|
|
|
|
+== 背景 ==
|
|
|
|
|
+平台侧实测:你缺 status-report.py、AGENT_ID 为空、无 crontab,
|
|
|
|
|
+从未向 FmodeAgent 表上报过 → App 里看不到你。
|
|
|
|
|
+
|
|
|
|
|
+== 你要做的 ==
|
|
|
|
|
+
|
|
|
|
|
+1. 建目录
|
|
|
|
|
+ mkdir -p /opt/data/git-repos/agent-status-reporter/{scripts,state}
|
|
|
|
|
+
|
|
|
|
|
+2. 拿原版脚本(1100 行 v10)
|
|
|
|
|
+ 优先从同宿主其他正常容器拷贝:
|
|
|
|
|
+ find /opt/fmode-containers -name "status-report.py" -path "*agent-status-reporter*"
|
|
|
|
|
+ 或从平台仓库下载
|
|
|
|
|
+
|
|
|
|
|
+3. 配 env(/opt/data/.env,先备份 .env.bak-<时间戳>)
|
|
|
|
|
+ AGENT_ID=agent-node-lj-test
|
|
|
|
|
+ FMODE_SESSION_TOKEN=r:dd15e8993d0b382d099d1faff6acd20c
|
|
|
|
|
+
|
|
|
|
|
+4. 手动验证(关键)
|
|
|
|
|
+ python3 /opt/data/git-repos/agent-status-reporter/scripts/status-report.py
|
|
|
|
|
+ ✅ 期望返回:{"code":200,"agentId":"...","field":"host","objectId":"..."}
|
|
|
|
|
+ ❌ 若返回 {"key":"user/.../log/....json"} → 你调了 AlP56LCKFm(错),应调 xlosi3m46q
|
|
|
|
|
+
|
|
|
|
|
+5. 常驻(crontab 不可用)
|
|
|
|
|
+ nohup sh -c 'while true; do python3 .../status-report.py; sleep 30; done' &
|
|
|
|
|
+
|
|
|
|
|
+6. 字段自查(对照平台契约)
|
|
|
|
|
+ host.channels 必须是对象:{"matrix":true,"matrixConfig":{...},"wecom":true,...}
|
|
|
|
|
+ host 必须有 cpuPercent(不是 cpuLoad1)
|
|
|
|
|
+ heartbeatAt 每次更新
|
|
|
|
|
+
|
|
|
|
|
+== 输出 ==
|
|
|
|
|
+REPORTER-OK 云函数=<xlosi3m46q> host=<cpuPercent有> channels=<对象> 落库=<lastField有值>
|
|
|
|
|
+```
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 五、本次实测的**字段对照表**(给开发/容器参考)
|
|
|
|
|
+
|
|
|
|
|
+| 字段 | 容器当前上报 | 平台契约 | 状态 |
|
|
|
|
|
+|---|---|---|---|
|
|
|
|
|
+| `host.cpuLoad1` | ✅ 有 | ❌ 不认 | 🔴 需改名 `cpuPercent` |
|
|
|
|
|
+| `host.cpuLoad5` | ✅ 有 | ❌ 不认 | ⚪ 可保留(额外字段)|
|
|
|
|
|
+| `host.memPercent` | ✅ 有 | ✅ 认 | ✅ 正常 |
|
|
|
|
|
+| `host.diskPercent` | ✅ 有 | ✅ 认 | ✅ 正常 |
|
|
|
|
|
+| `channels` | `["wecom"]` | `{...}` | 🔴 需改对象 |
|
|
|
|
|
+| `currentTask` | ✅ 有 | ✅ 认 | ✅ 正常 |
|
|
|
|
|
+| `usage` | ❌ 空 | ✅ 需要 | 🔴 需补 |
|
|
|
|
|
+| `heartbeatAt` | ❌ 空 | ✅ 需要 | 🔴 需补 |
|
|
|
|
|
+| `progress` | ❌ 空 | ✅ 需要 | 🔴 需补 |
|
|
|
|
|
+| `balance` | `{"source":"none"}` | `{"remainCny":N}` | 🔴 需取真实余额 |
|
|
|
|
|
+
|
|
|
|
|
+---
|
|
|
|
|
+
|
|
|
|
|
+## 六、关联文档
|
|
|
|
|
+
|
|
|
|
|
+- `docs/03-interface/reporter部署方案-20261020.md`(部署细节)
|
|
|
|
|
+- `docs/02-design/architecture/账号与账套体系设计.md`(归属模型)
|
|
|
|
|
+- `docs/02-design/plans/2026-10-19-数据层治理与新容器接入.md`(数据治理)
|
|
|
|
|
+- 云函数 `xlosi3m46q`(状态上报,`Function` 表 v0.1.2)
|