移植自 mac-agent-os 的 mediacrawler_adapter:不起子进程、不开页面,用浏览器里那份
登录态直接调抖音 Web 接口。产物键名照抄 store/douyin,所以 ingest 那条链路一个字不用改。
**目前能用的(真环境实测,非推断)**:
profile/other : 200, 7075 字节 —— 博主主页指标(粉丝/获赞/作品数/昵称)
aweme/detail : 200, 45425 字节 —— 单条作品详情(含点赞/评论/收藏/分享)
**目前不能用的:作品列表 `aweme/post`。** 两个互相独立的原因:
1. 这个接口被抖音单独升级成了真校验:不带 x-tt-argus 回 403「Uifid Not Found」,
带上 dummy 值回 200 + **空 body**。也就是说「头在不在」骗得过,「真校验」过不了。
同一套头打 profile/other 和 aweme/detail 都是通的 —— 抖音是挑着接口加保护的,
挑中的恰好是「批量拉作品列表」这个最敏感的动作。
2. 改走页面截获也不行:CDP 浏览器打开博主主页会落到「验证码中间页」(当天大量探测的
代价,过几小时要重测)。
所以现在的边界是:**已知作品的指标刷新能做,自动发现新作品做不了**。
**排查中控住变量后得到的两条事实**(都写进注释了):
· `Accept` / `Accept-Language` / `Referer` 才是主页接口能返回真数据的原因 —— 只有
UA+client hints+Cookie 时是 200 但仅 121 字节的空壳,补上这三个头变 7074 字节。
(我先前猜的 sec-ch-ua 不是关键。)
· 因此 UA 与 client hints 必须**成套地取自同一个浏览器**,所以 BrowserIdentity 一次
从 CDP 取齐 cookie + UA + hints,而不是各自写死。
「200 + 空 body 必须当场报错」也是刻意写死的:放过去它会在下游变成「这个博主没作品」,
把一次失败伪装成一条正常结果 —— 爬虫那条路正是这么栽的,还被翻译成「账号被封」。
测试 +11:cookie 解析、请求头成套性(含 uifid 缺失/回退)、产物键名与 store 对齐、
以及 _get 的三条失败路径(空 body / 403 带网关原话 / 正常返回)。
28 KiB
AgentOS 联邦系统使用指南
版本 4.2.0 | 2026-06-21 本文档让三台机器都能理解整个联邦系统:架构、工具、操作流程、故障处理
一、三台机器概况
| 主机名 | Tailscale IP | SSH 用户 | Home | 角色 |
|---|---|---|---|---|
| chengzigedeAir (macbook-air) | 100.111.43.6 | chengzige | /Users/chengzige | master |
| 5kechengdeAir (5macbook-air) | 100.72.182.121 | 5kecheng | /Users/5kecheng | worker |
| 7kecheng (7macbook-air) | 100.65.35.28 | 7kecheng | /Users/7kecheng | worker |
共同点(三台一致):
- Python 3.13.12 agent-os venv
- Playwright 1.58.0 + Camoufox 0.4.11
- Git 双端同步(Gitee + GitHub)
- 12 个蓝图 JSON 文件(另有测试蓝图)
- 联邦目录结构
本机独有(agent-local/ 不同步):
- 身份密钥、API Key
- 本地记忆、素材
- 运行时日志
二、目录结构
共享仓库: ~/workbuddy-agent-os/agent-sync/
agent-sync/
├── 00_bootstrap/ ← 初始化脚本(init.sh + apply-config.sh)
├── 01_core/ ← 核心配置 + 系统操作手册
├── 02_skills/ ← WorkBuddy 技能
├── 03_knowledge/ ← Obsidian 知识库
│ ├── 00_inbox/ → 待提纯收件箱
│ ├── 01_submissions/ → 多机提交箱
│ └── ...
├── 04_memory/ ← 跨机记忆/心跳/事件
├── 05_tools/ ← 所有工具脚本
│ ├── 00_setup/ → 系统安装/guardd
│ ├── 01_system/ → 系统工具
│ ├── 05_crawl/ → 采集工具(LongCat)
│ ├── 07_matrix/ → 矩阵养号核心
│ │ └── scripts/ → Python CLI + mc CLI
│ ├── 09_ave/ → 视频工厂
│ └── 10_dashboard/ → 系统监控面板
├── README.md ← 系统入口
├── FEDERATION_GUIDE.md ← 本文件
├── DEPLOY-GUIDE.md ← 部署指南
└── requirements.txt ← Python 依赖
本机独有: ~/workbuddy-agent-os/agent-local/
agent-local/
├── identity/secrets/ ← 私钥、API Key
├── materials/ ← 素材(大文件)
├── memory/ ← 本机记忆
├── runtime/ ← 运行时日志
│ ├── dashboard.log/.err ← Dashboard 日志
│ ├── guardd/ ← guardd 日志
│ └── socks5_*.log ← 代理日志
三、核心系统
3.1 Dashboard — 系统监控面板
⚠️ 部署原则:只有 master(chengzigedeAir)运行 Dashboard
Dashboard 是联邦的统一控制平面(聚合三台机器的账号/任务/状态数据)。worker 机器只运行 guardd(:9090 节点代理),不运行 Dashboard。
为什么必须这样(2026-09-20 踩坑记录):worker 各自跑 Dashboard 会造成"数据视图分裂" —— 账号标签/备注等数据存在各机器本地(不跨机同步),同一账号在不同看板会显示不同值, 导致"在本机改了标签,去那台机器看却没变"的困惑。
正确访问方式(所有机器统一访问 master):
http://100.111.43.6:9988 # Tailscale IP(推荐,跨网可用) http://192.168.31.225:9988 # 局域网 IP(同网段)发现 worker 误装了 Dashboard 时,这样停用(在 worker 上执行):
launchctl bootout gui/$(id -u)/com.agentos.dashboard mv ~/Library/LaunchAgents/com.agentos.dashboard.plist{,.disabled} # 禁用(不删除) # 验证:Dashboard 进程应为 0,guardd 应仍在运行 ps aux | grep "uvicorn app:app" | grep -v grep ps aux | grep -c "[g]uardd"也可直接用仓库脚本:
bash 00_bootstrap/disable_worker_dashboard.sh
URL(master 上): http://localhost:9988/
启动方式(launchd 管理,开机自启):
# 查看状态
launchctl list com.agentos.dashboard
# 手动重启
launchctl unload ~/Library/LaunchAgents/com.agentos.dashboard.plist
launchctl load ~/Library/LaunchAgents/com.agentos.dashboard.plist
# 看日志
tail -f ~/workbuddy-agent-os/agent-local/runtime/dashboard.log
功能模块(侧边栏 5 组 25+ 视图):
| 组 | 子视图 | 说明 |
|---|---|---|
| 矩阵 📱 | 账号管理、养号执行、信息采集、内容发布、定向评论、收藏点赞、蓝图管理、登录管理、定时任务、语料库、联邦指挥台 | 多平台账号矩阵 |
| 视频工厂 🎬 | 渲染任务、脚本生成、素材库、模板 | AVE 视频制作 |
| 内容采集 📡 | 采集任务、源管理、采集历史 | 网页采集 |
| 联邦 🖥️ | 机器状态、一键同步、对账检查、远程Shell | 跨机管理 |
| 服务 ⚙️ | MCP状态、Dashboard日志、全局定时任务 | 系统监控 |
开发模式(修改前端代码后热更新):
cd ~/workbuddy-agent-os/agent-sync/05_tools/10_dashboard/frontend
npx vite build # 构建生产版本
launchctl reload ... # 重启 Dashboard
后端:FastAPI (Python),端口 9988,app.py 注册所有 API 路由。
3.2.5 CommandBus → guardd 任务管理体系 (v7)
架构演进:v6 之前用 SSH/subprocess 直接执行;v7 改为 Dashboard 调 guardd HTTP API,guardd 作为节点代理管理任务生命周期。
组件关系:
Dashboard (控制平面) guardd (每台机器的节点代理)
┌─────────────────────┐ ┌──────────────────────────┐
│ 看板UI │ HTTP │ HTTP Server :9090 │
│ 任务编排(CMD模板) │◄────────►│ 任务管理器(进程追踪) │
│ 跨机状态聚合 │ │ 心跳上报(每300s) │
│ POST /api/ops/run │ │ 模块化健康检查(9模块) │
└─────────────────────┘ └──────────────────────────┘
位置:
- 控制面:
05_tools/10_dashboard/services/command_bus.py - 节点代理:
05_tools/00_setup/guardd/guardd.py
职责:
- CommandBus:接收看板命令 → ORACLE 对账 → 按机器分组 → 渲染CMD模板 → HTTP发给目标机器guardd
- guardd:接收HTTP任务 → 创建子进程 → 追踪PID → 日志采集 → 状态上报 → 支持停止/清理
任务生命周期状态:
queued → running → completed / failed / cancelled / crashed
guardd HTTP API(端口 9090):
| 方法 | 路径 | 说明 |
|---|---|---|
| POST | /task |
接收并执行任务(body: cmd, run_id, machine) |
| GET | /tasks |
返回所有任务状态列表 |
| POST | /task/{id}/stop |
停止指定任务(SIGTERM → SIGKILL) |
| GET | /health |
健康检查(心跳数据 + 任务统计) |
停止机制:Dashboard → POST /api/ops/stop/{run_id} → 查找任务所在机器 → HTTP调guardd /task/{id}/stop → guardd kill 子进程 → 标记为 CANCELLED
与 v6 的区别:
- 不再 subprocess 直接执行,改为 HTTP 调 guardd
- 远程机器不再走 SSH,走 HTTP (Tailscale IP + 9090)
- guardd 从定时任务(300s) 改为持久守护进程(KeepAlive=true)
- 任务PID持久追踪,支持真正的进程级停止
3.2 guardd — 节点代理守护进程 (v7)
作用:持久运行的节点代理,提供 HTTP 任务管理 API + 定时健康检查(300s)。
v7 架构变更:从 launchd 定时任务(StartInterval=300) 改为持久守护进程(KeepAlive=true):
- HTTP Server (端口 9090) — 接收 Dashboard 下发的任务
- 任务管理器 — 创建子进程、追踪 PID、支持停止/清理
- 心跳循环 — 每 300 秒执行 9 模块健康检查(原有逻辑不变)
三台机器都已通过 launchd 安装,开机自启,launch.sh 包装器自动适配本机路径。
# 查看状态
launchctl list com.agentos.guardd
# 查看任务状态
curl -s http://localhost:9090/tasks | python3 -m json.tool
# 查看健康检查结果
cat ~/workbuddy-agent-os/agent-local/runtime/guardd/last_run.json
# 查看日志
tail -20 ~/workbuddy-agent-os/agent-local/runtime/guardd/guardd.log
# 手动重载(改配置后)
launchctl unload ~/Library/LaunchAgents/com.agentos.guardd.plist
launchctl load ~/Library/LaunchAgents/com.agentos.guardd.plist
检查项(9 模块,每 300 秒一轮):心跳上报 → Dashboard 数据同步 → 任务执行 → 升级检查 → 记忆整理 → 知识同步 → 加密通道 → Git 同步拉取 → 过期数据清理。
3.3 Socks5 代理转发
作用:将本机 10800 端口的 socks5 请求转发到远程。
launchctl list com.agentos.socks5-forwarder
四、命令行工具
4.1 mc CLI — 矩阵管理系统
路径:~/workbuddy-agent-os/agent-sync/05_tools/07_matrix/scripts/
# 激活环境后
cd ~/workbuddy-agent-os/agent-sync/05_tools/07_matrix/scripts
python3 -m mc --help
# 核心子命令
python3 -m mc run --accounts=A --blueprints=B --rounds=N # ✅ 批量执行
python3 -m mc account list|create|login|status # ✅ 账号管理
python3 -m mc task comment --url=... # ✅ 定向评论
python3 -m mc corpus list|add # ✅ 语料库
python3 -m mc config show # ✅ 系统配置
python3 -m mc status all # ✅ 全局状态
python3 -m mc publish --platform=douyin ... # ✅ 视频发布
python3 -m mc remote exec <host> <cmd> # ✅ 远程执行
python3 -m mc blueprint list|show # ✅ 蓝图管理
4.2 agentos CLI — 系统管理
cd ~/workbuddy-agent-os/agent-sync/05_tools/07_matrix/scripts
python3 -m agentos --help
# 常用子命令
python3 -m agentos serve # 启动服务(dashboard, guardd 等)
python3 -m agentos register # 注册到联邦
python3 -m agentos check # 系统健康检查
4.3 matrix_mgmt.py — 账号管理
cd ~/workbuddy-agent-os/agent-sync/05_tools/07_matrix/scripts
python3 matrix_mgmt.py --help
# 常用操作
python3 matrix_mgmt.py accounts list # 列出账号
python3 matrix_mgmt.py accounts sync # 同步账号
python3 matrix_mgmt.py backup # 备份
### 4.4 登录状态机(2026-06-20 重构 v2.0)
**代码位置**: `scripts/matrix_modules/account/login_state_machine.py`
**架构**:三组件模式
LoginStateMachine (编排器) ├─ PlatformDetector (策略模式, 按平台可插拔) │ ├─ DouyinDetector — 文本检测 + DOM锚点 + Cookie辅助 │ └─ XhsDetector — DOM锚点 + Cookie辅助 └─ RecoveryChain (可配置恢复链) ├─ DouyinLoginRecovery — 抖音专用:点击登录 → 一键登录或填手机 │ → SMS验证码 → 确认登录 ← 2026-06-20 完成 ├─ CookieRecovery — 导航到 user/self ├─ SmsRecovery — 小红书 SMS 备用 └─ VisualRecovery — 截图上报
**三种登录场景全部通过验证**(2026-06-20):
| 场景 | 触发条件 | 流程 | 状态 |
|:-----|:---------|:-----|:----:|
| **已登录** | Session cookie 有效 | detect → `logged_in` → 直接执行蓝图 | ✅ |
| **短期过期** | Session cookie 存在但服务端标记过期 | detect → `not_logged` → 点登录 → 点一键登录 → SMS码 → **确认登录** → 蓝图 | ✅ |
| **全新登录** | 无 cookie | detect → `not_logged` → 点登录 → 自动填手机 → 获取验证码 → **登录** → 蓝图 | ✅ |
**关键发现**:
- 登录按钮文字在不同场景不同:全新登录是「登录」,短期过期是「**确认登录**」
- 抖音 UI 使用自定义组件,`<input>` 的 placeholder 无法通过通用 CSS 选择器匹配
- 使用 JS `page.evaluate()` 遍历所有元素 + 文本匹配作为兜底
- 点击被浮层拦截时,JS `el.click()` 绕过 Playwright 的可见性检查
**2026-06-20 重构要点**:
1. `DouyinDetector.detect()` 四重检测:DOM锚点 → 页面文本 → 标题 → Cookie(仅日志)
2. 修复 `[data-e2e="user-avatar"]` 误匹配视频创作者头像的问题
3. `RecoveryChain` 每一步有独立 timeout,超时自动跳过
4. SMS 验证码轮询用 `_fetch_messages()` 直接调用,只接受 `id > min_id` 的新消息
1. 抖音 `logged_in` 锚点从 2 个 -> 9 个(增加 `img[alt*="头像"]`、`a[href*="/user/self"]` 等)
2. 新增 Cookie 兜底检测:DOM 检测失败后,检查 `page.context.cookies()` 中是否存在 `sessionid/token`,有则返回 `"logged_in"`
3. `_recover_cookie()` 改为直接导航到 `https://www.douyin.com/user/self`,强制触发登录态渲染
- 验证:`douyin_test`(3个 session cookie)从之前的 `"未登录(status=unknown) 跳过本轮"` 变为能正常进入蓝图执行流程
### 4.5 多机账号管理
```bash
cd ~/workbuddy-agent-os/agent-sync/05_tools/07_matrix/scripts
python3 matrix_mgmt.py --help
# 常用操作
python3 matrix_mgmt.py accounts list # 列出账号(所有机器声明+读聚合去重)
python3 matrix_mgmt.py accounts sync # 多机同步
python3 matrix_mgmt.py backup # 备份
python3 matrix_mgmt.py restore # 恢复
五、联邦协作机制
5.1 Git 同步(主通道)
所有共享数据通过 Git 双端同步(Gitee + GitHub)。
# 每日工作流
cd ~/workbuddy-agent-os/agent-sync
git pull # 开始前拉取最新
# ... 工作 ...
git add -A && git commit -m "描述"
git push # 完成后推送
冲突处理:
# 如果 git pull 冲突
git stash # 暂存本地修改
git pull # 拉取最新
git stash pop # 恢复本地修改
# 手动解决冲突 → git add → git commit
5.2 一键同步(Dashboard 内)
Dashboard → 联邦 → 一键同步:通过 SSH 在 3 台机器间执行 git pull/push 同步。
5.3 对账检查
Dashboard → 联邦 → 对账检查:检查本机是否符合 ORACLE.yaml 宪法定义(蓝图、账号数、环境一致性)。
5.4 联邦对等原则(强制约束)
核心思想:所有联邦机器完全对等,本机不特殊。
Dashboard
↓ HTTP POST /api/ops/run {type, accounts, params}
└─── CommandBus.dispatch()
├─── 本机 → HTTP localhost:9090/... ← guardd HTTP API
└─── 远程 → HTTP tailscale_ip:9090/... ← 同样的 guardd HTTP API
硬约束:
-
不允许本机短路优化 — Dashboard 对本机的操作必须走与远程完全相同的代码路径。禁止
- 绕过 guardd 直接读本地 filesystem
- 直接用 subprocess 调 mc CLI 代替 guardd API
- 直接从本地 override.yaml 读账号状态而不查 guardd
/accounts/status
-
本机测试通 = 远程可用 — 一段代码在本机(chengzigedeAir)通过 guardd HTTP API 测试通过后, 在远程机器(5kechengdeAir、7kecheng)上直接可运行,不需要改任何代码。
-
唯一例外是地址解析 — 本机用
localhost:9090,远程用tailscale_ip:9090, 这个区别是必要的,也是唯一的区别。这个解析统一由command_bus._guardd_api()处理, 业务代码不需要感知。 -
数据同步不走直连 — 远程机器的数据(账号状态、任务状态)通过 guardd HTTP API 获取, 不通过 SSH 直连文件、不通过 fleet_collector 拉取文件副本。所有跨机数据交互都经过 guardd。
设计检查清单(代码审查时使用):
□ Dashboard 对本机的操作是否走了 guardd HTTP API?
□ 是否有绕过 guardd 直接本地操作的代码路径?
□ 远程机器能否直接运行这段代码(地址解析除外)?
□ 数据获取是否统一通过 guardd API 而不是文件直读?
六、矩阵养号系统
6.1 蓝图(Blueprint)
蓝图是定义好"做什么"的 JSON 文件,位于 05_tools/07_matrix/blueprints/:
| 蓝图 | 说明 | 步数 | 状态 |
|---|---|---|---|
douyin_read_profile.json |
抖音读主页(昵称/粉丝/获赞等) | 9 | ✅ 验证通过 |
douyin_daily.json |
日常养号(浏览/点赞/收藏/评论随机) | 23 | 🔵 待测试 |
douyin_active_v1.json |
高活跃养号(多浏览+多搜索+评论) | 27 | 🔵 待测试 |
douyin_comment.json |
定向评论(给链接→看视频→评论) | 5 | 🔵 待测试 |
douyin_search.json |
搜索浏览(关键词→搜索→互动) | 14 | 🔵 待测试 |
douyin_collect.json |
搜索博主→采集主页 | 5 | 🔵 待测试 |
douyin_search_browse.json |
搜索+点赞+返回 | 7 | 🔵 待测试 |
douyin_reply.json |
回复评论 | 5 | 🔵 待测试 |
douyin_comment_test.json |
评论测试 | 5 | 🔵 待测试 |
dy_test_all.json |
抖音全量功能测试 | — | 🔵 测试用 |
xhs_daily.json |
小红书日常养号 | 17 | 🔵 待测试 |
xhs_active_v1.json |
小红书高活跃养号 | 26 | 🔵 待测试 |
xiaohongshu_read_profile.json |
小红书读主页 | 8 | 🔵 待测试 |
xhs_test_all.json |
小红书全量功能测试 | — | 🔵 测试用 |
互动蓝图(评论互动 / 评论工作台用)
| 蓝图 | 说明 | 步数 | 状态 |
|---|---|---|---|
interact_comment.json |
互动-定向评论(打开→等待→开评论区→发评论→验证) | 5 | ✅ 实测通过 |
interact_like.json |
互动-点赞(点赞视频 + 点赞热评) | 6 | 🔵 页面改版后需验证 |
interact_collect.json |
互动-收藏 | 4 | 🔵 页面改版后需验证 |
interact_chain.json |
互动-三级接力(A评论→B回复→C回复) | 8 | 🔵 待测试 |
interact_hot.json |
互动-热评互动 | — | 🔵 待测试 |
蓝图组合机制(v4.5 新增)
引擎 engine.py 支持用 + 分隔组合蓝图名,同一视频内多动作连做,无需录制新蓝图:
mc run --accounts=A --blueprints=interact_like+interact_collect+interact_comment --url=...
merge_blueprints()自动合并 steps:重复goto_url去重(页面已在目标视频)、连续wait/wait_watch合并(取较大值)- 评论互动计划生成器按视频命中比例动态拼接组合名(如只点赞+评论 →
interact_like+interact_comment) - 前置条件支持
soft=True(ops/_base.py):like/collect/follow 的按钮选择器在页面改版失效时不跳过,放行底层兜底(键盘 Z / JS 文字查找),其他操作硬条件不变
6.2 养号执行流程
- 挑选账号:在 Dashboard "账号管理" 中勾选账号
- 选择蓝图:在 Dashboard "养号执行" 中选蓝图
- 执行:点击执行,系统按蓝图步骤自动操作
- 查看结果:Dashboard → 联邦 → 远程Shell 查看执行日志
6.3 三台机器的账号分工
每台机器声明自己管理的账号(声明文件在 profiles/{account_id}.json):
- chengzigedeAir: douyin_test, xhs_01 等
- 5kechengdeAir: 各声明文件
- 7kecheng: 各声明文件
规则:各管各的账号,读聚合时去重不覆盖。
七、配置文件
7.1 Python 环境
# 统一使用 agent-os venv
$HOME/.workbuddy/binaries/python/envs/agent-os/bin/python3
# 远程执行脚本用
$MC_PYTHON=$(echo $HOME/.workbuddy/binaries/python/envs/agent-os/bin/python3)
# 安装依赖
pip install -r ~/workbuddy-agent-os/agent-sync/requirements.txt
7.2 Launchd 服务
三台机器共用 plist 模板(05_tools/00_setup/guardd/com.agentos.guardd.plist),
通过 launch.sh 包装器自动适配本机 $HOME 路径。
| 服务 | Plist | 作用 |
|---|---|---|
| dashboard | com.agentos.dashboard |
监控面板(9988端口) |
| guardd | com.agentos.guardd |
系统守护(300秒周期) |
| socks5-forwarder | com.agentos.socks5-forwarder |
SOCKS5代理转发(10800端口) |
7.3 代理配置
# config/sms.yaml 中
proxy: 127.0.0.1:10800 # 本地 socks5 代理
八、常见问题
8.1 Dashboard 视图一直"加载中"
原因:Rollup tree-shake 删除了 inline loader 函数(2026-06-18 修复过)。
解决:
- 检查 Vite 构建:
cd frontend && npx vite build - 检查 bundle 大小:正常的 bundle 约 255kB(太小说明函数被 tree-shake 了)
- 重启 Dashboard:
launchctl unload/load com.agentos.dashboard
8.2 开机弹出 Python 错误窗
原因:guardd launchd plist 路径不对(2026-06-19 修复为 launch.sh 包装器)。
解决:确保已部署最新 plist:
sed "s|__HOME__|$HOME|g" \
05_tools/00_setup/guardd/com.agentos.guardd.plist \
> ~/Library/LaunchAgents/com.agentos.guardd.plist
launchctl unload ~/Library/LaunchAgents/com.agentos.guardd.plist
launchctl load ~/Library/LaunchAgents/com.agentos.guardd.plist
8.3 Dashboard 端口被占用
lsof -i :9988 # 查看谁占用了端口
kill -9 <PID> # 杀掉旧进程
launchctl reload ... # 重启
8.4 Git push 失败
# 检查远程仓库
git remote -v
# 检查是否有未推送的提交
git status
# 如果 Gitee/GitHub 其中一个失败
git push gitee main # 单独推 Gitee
git push github main # 单独推 GitHub
8.5 "执行历史"一直加载
原因:loadExecutionHistory() 函数在 inline.js 中未被 Vite 打包(2026-06-19 已修复)。
解决:检查是否有最新的 Dashboard bundle(255kB 左右),重启即可。
8.6 Python 代码签名问题
# 新机器部署后必须执行
codesign -f -s - $HOME/.workbuddy/binaries/python/versions/3.13.12/bin/python3
# deploy.sh 中已自动检测此步骤
九、每日工作流
主控机器(chengzigedeAir)
# 1. 拉取最新代码
cd ~/workbuddy-agent-os/agent-sync && git pull
# 2. 检查 Dashboard 是否运行
curl -s http://localhost:9988/api/health
# 3. 查看所有机器状态
# → 打开浏览器 http://localhost:9988 → 联邦 → 机器状态
# 4. 对账检查
# → 联邦 → 对账检查 → 执行对账
# 5. 工作完成后推送
git add -A && git commit -m "描述当天工作"
git push
工作节点(5kechengdeAir / 7kecheng)
# 1. 拉取最新代码
cd ~/workbuddy-agent-os/agent-sync && git pull
# 2. 检查 guardd 状态
launchctl list com.agentos.guardd
tail -3 ~/workbuddy-agent-os/agent-local/runtime/guardd/last_run.json
# 3. 本地工作
# ...
# 4. 推送
git add -A && git commit -m "描述"
git push
所有机器通用
# 每天第一次使用前
git pull
# 遇到问题时
cat ~/workbuddy-agent-os/agent-local/runtime/guardd/guardd.log | tail -20
curl -s http://localhost:9988/api/health
十一、五层执行架构 (L1–L5)
所有 Dashboard 操作(养号、采集、登录、评论)都经过这五层:
L5 ─── Dashboard UI ───────── frontend/src/views/*.js
│ 用户点击按钮 → API 调用
▼
L4 ─── API 路由 ───────────── routes/matrix.py, routes/ops.py
│ POST /api/ops/run → 调 CommandBus
▼
L3 ─── CommandBus ─────────── services/command_bus.py
│ ORACLE.yaml 合规检查 → account→machine 映射
│ 预检(SSH可达、进程数)→ 分组 → mc/SSH
▼
L2 ─── mc 引擎 ────────────── scripts/mc/engine.py
│ BatchEngine → 身份分组 → 启动浏览器
│ 蓝图解析 → 执行步骤 → 钩子检测
▼
L1 ─── Camoufox 浏览器 ────── scripts/douyin_ops.py / xhs_ops.py
真实浏览器操作 → 点赞/评论/采集/登录
各层职责
| 层 | 位置 | 核心文件 | 职责 |
|---|---|---|---|
| L5 | Dashboard 前端 | frontend/src/views/matrix-*.js |
按钮交互、确认弹窗、状态轮询、结果展示 |
| L4 | FastAPI 路由 | routes/ops.py routes/matrix.py |
参数校验 → 调用 CommandBus → 返回结果 |
| L3 | CommandBus | services/command_bus.py |
ORACLE合规、按机器分组、预检、SSH/本机分发、状态轮询 |
| L2 | mc引擎 | scripts/mc/engine.py scripts/mc/run.py |
身份分组→浏览器→蓝图步骤执行→钩子检查 |
| L1 | 平台Ops | scripts/douyin_ops.py scripts/xhs_ops.py |
页面操作原子(goto/like/comment/read_profile等) |
命令的生命周期
用户点击「养号执行」→ 命令经过的完整路径:
L5: 用户选账号→选蓝图→点执行
→ 前端 /api/ops/run POST {type:"nurture", accounts:[...], params:{blueprint:"douyin_daily"}}
L4: POST /api/ops/run → CommandBus.dispatch("nurture", accounts, params)
L3: CommandBus.dispatch():
1. ORACLE.yaml 检查 account→machine 映射
2. 按机器分组(同机账号合并为一条命令)
3. 预检:SSH 可达性、活跃进程数
4. 构造命令行: mc run --accounts=... --blueprints=... --rounds=N
5. _send_local: subprocess.Popen(mc run ...) → 返回 PID
6. Command.status = DISPATCHING → RUNNING → COMPLETED/FAILED
L2: BatchEngine.run():
1. 身份分组:同 identity_dir 的账号共用浏览器
2. 启动 Camoufox 浏览器
3. LoginStateMachine.ensure_login() 钩子
4. 遍历蓝图步骤 → ops.execute(op, args)
5. 每步后 check_verify_dialog() 钩子 + 冷却
6. 返回 BatchReport
L1: DouyinOps/XhsOps:
→ goto_home / like / comment / dy_read_nickname / ...
登录检测流程(L1 关键钩子)
ensure_login(account, platform)
├─ _detect(page)
│ ├─ DOM锚点检查(平台特定选择器)
│ ├─ 页面标题检测(抖音:"xxx的抖音"=已登录)
│ └─ Cookie兜底检测(sessionid/token 是否存在)
├─ _recover_cookie(page)
│ └─ 导航到 user/self → 强制触发登录态
└─ _recover_sms(page, account)
└─ sms_login() → 填手机→等验证码→点同意
常见断点排查
| 现象 | 可能断点 | 排查方法 |
|---|---|---|
| 点击按钮没反应 | L5 事件绑定→L4 API | 检查前端控制台、API 返回 |
| API 返回 500 | L4 路由→L3 CommandBus | 看 dashboard.log |
| 命令"已分发"但状态不变 | L3 poll()→L2 进程 | ps aux | grep mc run、看 runtime/commands/run_id.log |
| 命令"已完成"但没数据 | L2→L1 引擎 | 看命令日志中 ensure_login 是否通过 |
| 账号被跳过(skipped) | L1 ensure_login 失败 | 检查 session cookie 是否有效 |
| 执行卡住不动 | L1 SMS 验证弹窗 | 手动输入验证码或等超时 |
| 要找什么 | 路径 |
|---|---|
| 系统入口 | ~/workbuddy-agent-os/agent-sync/README.md |
| 联邦指南(本文) | ~/workbuddy-agent-os/agent-sync/FEDERATION_GUIDE.md |
| 部署指南 | ~/workbuddy-agent-os/agent-sync/DEPLOY-GUIDE.md |
| Dashboard 源码 | ~/workbuddy-agent-os/agent-sync/05_tools/10_dashboard/ |
| Dashboard 前端 | ~/workbuddy-agent-os/agent-sync/05_tools/10_dashboard/frontend/ |
| 矩阵脚本 | ~/workbuddy-agent-os/agent-sync/05_tools/07_matrix/scripts/ |
| 蓝图 | ~/workbuddy-agent-os/agent-sync/05_tools/07_matrix/blueprints/ |
| guardd 源码 | ~/workbuddy-agent-os/agent-sync/05_tools/00_setup/guardd/ |
| guardd 日志 | ~/workbuddy-agent-os/agent-local/runtime/guardd/ |
| Dashboard 日志 | ~/workbuddy-agent-os/agent-local/runtime/dashboard.log |
| Python venv | $HOME/.workbuddy/binaries/python/envs/agent-os/ |
| Launchd plists | ~/Library/LaunchAgents/com.agentos.*.plist |