feat(monitor): 抖音 Web 接口客户端 —— 绕开爬虫子进程,直接发 HTTP
Deploy VitePress site to Pages / build (push) Canceled after 0s
Deploy VitePress site to Pages / Deploy (push) Canceled after 0s

移植自 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 带网关原话 / 正常返回)。
This commit is contained in:
2026-10-10 17:12:25 +08:00
parent 21ff01b894
commit 2112c1a870
1601 changed files with 367425 additions and 0 deletions
@@ -0,0 +1,45 @@
---
id: KB-20260601-018
title: ""
type: method
status: published
nature: method
domain: [general]
subdomain: []
tags: ["待补充"]
confidence: 0.5
source: ""
source_type: unknown
date_created: 2026-06-01
date_modified: 2026-06-01
version: 1
previous_version: ""
superseded_by: ""
summary: ""
collected: true
collected_date: 2026-06-02---
# 2026-05-17_2026-05-16_统一升级引擎_agentos_upgrade
> 来源:03_knowledge/20_methods
# 2026-05-16_统一升级引擎_agentos_upgrade
# 统一升级引擎 agentos upgrade
# agentos upgrade — 统一升级引擎
## 概述
## 命令
## 执行流程
1. `git pull origin main` — 拉取最新代码
2. 扫描 18 个模块(8 个 skill + 8 个 tool + 2 个其他)
3. 按模块层级执行不同操作
4. 自动注册技能到 WorkBuddy
5. 输出升级报告
## 三层模块管理
## Python 环境统一
1. `AGENTOS_PYTHON` 环境变量
2. `~/.workbuddy/binaries/python/envs/agent-os/bin/python3`
3. `~/.workbuddy/binaries/python/versions/3.13.12/bin/python3`
4. `python3`(系统 fallback)
## 位置
@@ -0,0 +1,57 @@
# 🧠 AgentOS AI 阅读指南
> 每次启动任务时,先读此文件了解知识库结构。
## 知识库结构
```
03_knowledge/
├── 00_inbox/ ← 待提纯收件箱(每日采集暂存)
├── 01_submissions/ ← 待归集提交箱(按来源分目录,23个文件)
├── 10_concepts/ ← 概念知识(19个)
├── 20_methods/ ← 方法技能(140个,含AI视频系统19章)
├── 30_facts/ ← 事实数据
├── 40_references/ ← 参考资料(9个)
├── 50_resources/ ← 资源索引
├── 60_opinions/ ← 个人观点
├── 90_archive/ ← 归档
└── 99_system/ ← 🆕 系统文档集中存放
├── architecture/ ← 联邦架构、登录系统、触发分析
├── matrix/ ← 矩阵养号系统文档
├── references/ ← 系统引用(CloakBrowser, Peekaboo等)
├── dashboard/ ← Dashboard 设计文档
├── protocols/ ← 协议规范(cross-domain, knowledge-review等)
├── pipelines/ ← 自动化管线
├── prompts/ ← 智能体提示词
├── taxonomies/ ← 分类法
├── templates/ ← 知识卡片模板
└── archive/ ← 归档旧文档
```
## 任务类型 → 查阅目录
| 任务类型 | 查阅目录 | 说明 |
|:---------|:---------|:-----|
| 矩阵养号 | `99_system/matrix/` | 养号架构、蓝图、原子操作、登录体系 |
| 知识入库 | `99_system/protocols/` (knowledge-review) | 入库审查流程 |
| 跨域联想 | `99_system/protocols/` (cross-domain) | 跨域联想协议 |
| 元思考 | `99_system/protocols/` (meta-thinking) | 元认知框架 |
| 卡住干预 | `99_system/protocols/` (stuck-intervention) | 卡住恢复策略 |
| AI视频 | `20_methods/` (ai-video-system/) | 19章完整体系 |
| 系统架构 | `99_system/architecture/` | 联邦架构设计 |
| 知识卡片 | `99_system/templates/` | 卡片模板 |
## 使用规范
1. **不要重复创建**:查知识库前先搜索已有内容
2. **记忆体 vs 知识**:日期前缀文件是 `memory_triage` 输出的记忆体,不是知识。知识是无日期的概念/方法/事实
3. **系统文档**:所有系统架构/设计/协议文档都在 `99_system/` 下
4. **先读指南**:每次启动先读此文件
## 变更日志
| 日期 | 变更 |
|:----|:-----|
| 2026-06-18 | 创建 AI_READING_GUIDE.md |
| 2026-06-18 | 04_ops/ → 99_system/matrix/ |
| 2026-06-18 | 去重删除 ~130 个重复文件 |
@@ -0,0 +1,269 @@
# AgentOS 联邦系统 — 全面架构审计报告
> 审计日期: 2026-06-18
> 审计范围: agent-sync/05_tools/07_matrix/scripts + 10_dashboard + 00_bootstrap
> 文件总量: 130 个 Python 文件, 7 个 Shell, 36 个目录
---
## 一、系统全景图
```
┌─────────────────────────────────────────────────────────────────┐
│ Dashboard (uvicorn :9988) │
│ app.py · routes/matrix.py · routes/ops.py · 7 个 services/ │
│ static/index.html (7700行内联JS) · frontend/ (Vite 33视图) │
├──────────────────────┬──────────────────┬──────────────────────┤
│ mc CLI (入口) │ matrix.py (旧入口)│ agentos (新入口) │
│ mc/cli.py (15命令) │ 统一脚本入口 │ cli.py + plugins/ │
├──────────────────────┴──────────────────┴──────────────────────┤
│ scripts/ (核心) │
│ matrix_mgmt.py · collect_*.py · nurture_*.py │
│ cdp_connector.py · auth_manager.py · anti_detection.py │
│ atom_ops.py · orchestrator.py · task_engine.py │
├──────────────────────┬──────────────────┬──────────────────────┤
│ matrix_modules/ │ mc/ 包 │ archive/ │
│ account/ (登录) │ cli.py │ 41个旧脚本(已归档) │
│ nurture/ (养号) │ run.py/engine │ │
│ ops/xhs/ (小红书原子) │ task.py/schedule│ │
│ comment/ │ proxy/recorder │ │
├──────────────────────┴──────────────────┴──────────────────────┤
│ 数据层 │
│ agent-local/tools/matrix/ │
│ config/accounts.yaml · data/homepage_info.json · identities/ │
│ 14个JSON蓝图 · profiles/*.json · anchor_db.sqlite │
└─────────────────────────────────────────────────────────────────┘
```
---
## 二、模块级审计
### 2.1 入口层
| 入口 | 文件 | 作用 | 状态 |
|:-----|:-----|:-----|:-----|
| `mc` CLI | `mc/cli.py` | **当前主入口**,15 个子命令: run/collect/account/blueprint/login/smart-login/task/schedule/corpus/proxy/sms/status/record/op/remote | ✅ 正常 |
| `matrix.py` | `matrix.py` | 旧版统一入口(`matrix_utils`),仍被 mc CLI 部分引用 | ⏳ 兼容层 |
| `agentos` | `agentos/cli.py` | 新版智能体 CLI,挂载 plugins/ave/crawl/fleet/matrix/serve | 🔄 开发中 |
| Dashboard | `app.py` | Web 管理台,~50 个 API 端点,33 个视图 | ✅ 正常 |
| `matrix_mgmt.py` | 账号/蓝图/备份管理 | 核心数据管理,被所有组件引用 | ✅ 正常 |
### 2.2 矩阵养号层
| 模块 | 文件 | 功能 | 复用情况 | 状态 |
|:-----|:-----|:------|:--------|:------|
| 账号管理 | `matrix_mgmt.py` | CRUD+多机聚合+蓝图+备份 | 所有组件引用 | ✅ 正常 |
| 账号登录 | `matrix_modules/account/xhs_login.py` | 小红书 SMS 登录原子操作 | 被 xiaohongshu_login.py 调用 | ✅ 正常 |
| 账号登录 | `matrix_modules/account/sms_login.py` | 抖音 SMS 登录原子操作 | 被 douyin_login.py 调用 | ✅ 正常 |
| 账号登录 | `matrix_modules/account/douyin_login.py` | 抖音登录CLI | CLI模式 | ✅ 正常 |
| 账号登录 | `matrix_modules/account/xiaohongshu_login.py` | 小红书登录CLI | CLI模式 | ✅ 正常 |
| 养号引擎 | `matrix_modules/nurture/runner.py` | **75408b** 超大文件,含 38 个函数 | mc run 的核心 | ⚠️ 过大需拆分 |
| 养号引擎 | `orchestrator.py` | 养号调度器(AtomOps+Blueprint) | 替代 runner 的新版 | 🔄 开发中 |
| 日常养号 | `nurture_daily.py` | 旧版日常调度器(286行) | 可能被 runner 替代 | ⏳ 过渡状态 |
| 蓝图 | `nurture_blueprint.py` | 蓝图执行 | 被 atom_ops 调用 | ✅ 正常 |
| 批量采集 | `collect_batch_runner.py` | 分批并行采集 | **当前使用版本** | ✅ 正常 |
| 单身份采集 | `collect_homepage_info.py` | 单身份采集 | 被 batch_runner import | ✅ 正常 |
### 2.3 浏览器/反检测层
| 模块 | 文件 | 大小 | 复用情况 | 状态 |
|:-----|:-----|:----|:--------|:------|
| CDP连接器 | `cdp_connector.py` | 最大(>300行) | **所有浏览器操作的基础** | ✅ 正常 |
| Camoufox管理器 | `camoufox_manager.py` | ~200行 | 部分使用 | ⏳ 与cdp_connector重复 |
| 浏览器管理器 | `browser_manager.py` | ~200行 | 实验性 | ❌ 被cdp_connector替代 |
| 优雅退出 | `browser_utils.py` | `GracefulBrowser`类 | 被 login 模块使用 | ✅ 正常 |
| 反检测 | `anti_detection.py` | BehaviorProfile类 | 部分引用 | ✅ 正常 |
| 账号切换 | `switch_account.py` | Chrome Profile切换 | 基本废弃 | 🗑️ 应归档 |
### 2.4 登录状态管理
| 模块 | 文件 | 功能 | 复用 | 状态 |
|:-----|:-----|:------|:-----|:------|
| 认证管理器 | `auth_manager.py` | Cookie/DOM 多维登录检测 | **核心工具** | ✅ 正常 |
| 页面状态 | `page_state.py` | 页面模式检测(grid/player/search) | 部分使用 | ⏳ 可增强 |
| 原子操作 | `atom_ops.py` | AtomOps类(通用操作) | orchestrator核心 | ✅ 正常 |
| 抖音操作 | `douyin_ops.py` | DouyinOps类(300+行) | 养号引擎核心 | ✅ 正常 |
### 2.5 小红书原子操作
| 模块 | 文件 | 功能 | 状态 |
|:-----|:-----|:------|:------|
| selectors | `matrix_modules/ops/xhs/selectors.py` | DOM选择器常量 | ✅ 正常 |
| browse | `matrix_modules/ops/xhs/browse.py` | 浏览操作 | ✅ 正常 |
| interact | `matrix_modules/ops/xhs/interact.py` | 互动操作 | ✅ 正常 |
| ATOMIC_OPS.md | `matrix_modules/ops/xhs/ATOMIC_OPS.md` | 操作文档 | ✅ 正常 |
### 2.6 任务调度
| 模块 | 文件 | 功能 | 状态 |
|:-----|:-----|:------|:------|
| 任务引擎 | `task_engine.py` | 蓝图执行引擎 | ⏳ 与 runner 功能重叠 |
| 任务调度 | `task_scheduler.py` | 定时任务 | ✅ 正常 |
| C2命令总线 | `c2/command_bus.py` | 跨机命令(HTTP/Git降级) | ✅ 正常 |
| C2采集器 | `c2/profile_scraper.py` | 跨机数据聚合 | ⏳ 旧版功能 |
### 2.7 Dashboard 后端服务
| 服务 | 大小 | 功能 | 状态 |
|:-----|:----|:------|:------|
| `command_bus.py` | 27KB, **4类28函数** | **统一命令总线(v5)** | ✅ **核心** |
| `browser_orchestrator.py` | 9.5KB | 浏览器编排(并发控制) | ✅ 正常 |
| `remote_exec.py` | 6KB | 远程SSH执行 | ⏳ 部分被command_bus替代 |
| `operation_queue.py` | 5.6KB | 操作队列 | ⏳ 与command_bus重叠 |
| `preflight.py` | 3.8KB | 预检(磁盘/浏览器/进程) | ✅ 正常 |
| `resource_lock.py` | 4.4KB | 资源锁定 | ⏳ 与browser_orch重叠 |
| `data_aggregator.py` | 6.7KB | 数据聚合 | ✅ 正常 |
| `log_aggregator.py` | 3.5KB | 日志聚合 | ✅ 正常 |
### 2.8 Dashboard 路由
| 路由文件 | 端点 | 功能 | 状态 |
|:---------|:------|:------|:------|
| `routes/matrix.py` | ~15个 | 养号/采集/蓝图/喂饭 | ✅ 正常 |
| `routes/ops.py` | 4个 | 统一命令总线API | ✅ **核心** |
### 2.9 引导/部署层
| 脚本 | 功能 | 状态 |
|:-----|:------|:------|
| `deploy.sh` | 一键部署(3机) | ✅ 正常 |
| `fleet_sync.sh` | 多机同步 | ✅ 正常 |
| `fleet_reconcile.sh` | 多机对账 | ✅ 正常 |
| `init.sh` | 环境初始化 | ✅ 正常 |
| `setup_env.sh` | 环境配置 | ✅ 正常 |
### 2.10 知识库/规划文档
| 文档 | 内容 | 状态 |
|:-----|:------|:------|
| `ARCHITECTURE_v3.md` | Dashboard架构蓝图(10+) | ✅ 正常 |
| `ARCHITECTURE.md` | 旧版架构 | ⏳ 过时 |
| `DEPLOYMENT.md` | 部署文档 | ⏳ 需更新 |
| `EXECUTION_PIPELINE.md` | 统一执行管道设计 | ✅ 最新 |
| `VITE_MIGRATION_PLAN.md` | 前端重构计划 | ✅ 最新 |
---
## 三、核心问题清单
### P0 — 必须修复
| # | 问题 | 涉及文件 | 影响 |
|:-:|:-----|:---------|:-----|
| 1 | `matrix_modules/nurture/runner.py` 75408b/38函数 — 过于庞大 | 全部养号操作 | 难以维护和调试 |
| 2 | `cdp_connector.py` 和 `camoufox_manager.py` / `browser_manager.py` 功能**严重重叠** | 3个文件管理浏览器 | 调用混乱 |
| 3 | `services/operation_queue.py` 与 `command_bus.py` 功能重叠 | 队列管理重复 | 两种排队逻辑并存 |
### P1 — 需重构
| # | 问题 | 涉及 | 影响 |
|:-:|:-----|:------|:------|
| 4 | 采集流程登录检测**刚修复**(xhs),抖音登录**尚未集成** | collect_*.py | 抖音未登录时不会自动登录 |
| 5 | `remote_exec.py` 被 `command_bus.py` **部分替代**但未被移除 | 远程执行 | 两份远程执行代码 |
| 6 | `resource_lock.py` 与 `browser_orchestrator.py` 资源管理重叠 | 资源管理 | 两种锁机制 |
| 7 | `switch_account.py` 基本**废弃**但未被归档 | 账号切换 | 死代码 |
| 8 | `browser_manager.py` 实验性代码未被正式使用 | 浏览器管理 | 死代码 |
### P2 — 需优化
| # | 问题 | 涉及 | 影响 |
|:-:|:-----|:------|:------|
| 9 | 41个已归档脚本在 `archive/` — 部分可能含可复用逻辑 | archive/ | 需要清理或复用 |
| 10 | `nurture_daily.py` 被 `collect_batch_runner.py` 部分替代但未删除 | 养号调度 | 两份调度逻辑 |
| 11 | `orchestrator.py` 和 `nurture_daily.py` 功能定位不清 | 调度器 | 新旧交替 |
| 12 | `static/index.html` 7700行 — 内联JS过于庞大 | 前端 | 维护困难 |
| 13 | 未统一使用 `local_paths.py` — 文件散落硬编码路径 | 多处 | 可维护性差 |
---
## 四、模块关系图
```
用户/开发
│
┌────────────┼────────────┐
│ │ │
mc CLI Dashboard agentos CLI
(mc/cli.py) (app.py:9988) (agentos/cli.py)
│ │ │
└─────┬──────┴─────┬──────┘
│ │
command_bus.py c2/command_bus.py
(统一命令总线v5) (HTTP/Git降级)
│
┌────────────┼──────────────────┐
│ │ │
本地执行 远程SSH 队列调度
│ │ │
┌────┴────┐ remote_exec.py operation_queue.py
│ │
角色模块 引擎模块
│ │
account/ nurture/runner.py
xhs_login douyin_ops.py
sms_login atom_ops.py
auth_mgr blueprint
│
cdp_connector.py (浏览器基础)
```
---
## 五、操作类型映射
| 操作 | mc CLI │ 命令总线 │ 前端 | 后端执行 | 状态 |
|:-----|:-------|:---------|:-----|:---------|:-----|
| 养号执行 | `mc run` | `POST /api/ops/run {type:nurture}` | 养号视图 | `mc run --accounts=...` | ✅ |
| 信息采集 | `mc collect` | `POST /api/ops/run {type:collect}` | 采集视图 | `collect_batch_runner.py` | ✅ |
| 登录 | `mc smart-login` | `POST /api/ops/run {type:login}` | 登录视图 | `douyin_login/xhs_login` | ✅ |
| 退出 | `mc account logout` | `POST /api/ops/run {type:logout}` | 登录视图 | `mc account logout ...` | ✅ |
| 评论 | `mc task comment` | `POST /api/ops/run {type:comment}` | 评论视图 | `mc task comment ...` | ✅ |
| 点赞 | `mc task like` | `POST /api/ops/run {type:like}` | 点赞视图 | `mc task like ...` | ✅ |
| 蓝图 | `mc blueprint` | — | 蓝图视图 | matrix_mgmt | ✅ |
| 账号 | `mc account` | — | 账号视图 | matrix_mgmt | ✅ |
| 代理 | `mc proxy` | — | SMS代理 | proxy管理 | ✅ |
| 短信 | `mc sms` | — | SMS代理 | ApiSMSHandler | ✅ |
---
## 六、建议行动顺序
### Phase A: 清理重复(~2小时)
```
1. browser_manager.py → 归档到 archive/
2. switch_account.py → 归档到 archive/
3. remote_exec.py → 如果完全被 command_bus 替代则归档
4. resource_lock.py → 合并到 browser_orchestrator.py
5. operation_queue.py → 集成到 command_bus.py
```
### Phase B: 整合核心(~3小时)
```
1. 统一浏览器管理 (cdp_connector.py → 唯一入口)
- camoufox_manager.py 的功能合并到 cdp_connector
2. 统一养号引擎
- nurture_daily.py 的功能合并到 collect_batch_runner.py
- orchestrator.py 作为新版 adoption
3. 统一采集登录
- 在 extract_douyin() 中也加入登录检测(已为xhs修复)
- 创建通用 login_if_needed(page, platform, phone) 函数
```
### Phase C: 标准化路径(~1小时)
```
1. 所有文件改用 local_paths.py 获取路径
2. 消除硬编码的 `~/workbuddy-agent-os/agent-local/...`
```
### Phase D: 文档化(~30分钟)
```
1. 更新 ARCHITECTURE_v3.md 反映当前真实架构
2. 在 99_system/ 更新 README.md
```
@@ -0,0 +1,574 @@
# ⚖️ AgentOS 联邦系统 — 架构宪法 v1.0
> 本文件是 AgentOS 联邦系统的**最高架构规范**,定义所有模块的职责边界、调用规则、生命周期。
>
> **本文件描述的是目标架构(最终状态)**。当前实际系统处于过渡阶段,部分组件仍是旧版。
> 所有新代码都按此规范编写,旧代码逐步替换,不倒退。
>
> 生效日期: 2026-06-18
> 版本: 1.0
> 维护者: chengzigedeAir (主控机)
> 适用范围: 所有联邦机器 (chengzigedeAir / 5kechengdeAir / 7kecheng)
---
## 目录
- [第一章 总纲](#第一章-总纲)
- [第二章 架构分层](#第二章-架构分层)
- [第三章 组件状态与生命周期](#第三章-组件状态与生命周期)
- [第四章 调用规范](#第四章-调用规范)
- [第五章 数据流规范](#第五章-数据流规范)
- [第六章 迁移路线图](#第六章-迁移路线图)
- [第七章 例外处理](#第七章-例外处理)
- [附录A 组件状态一览表](#附录a-组件状态一览表)
- [附录B 旧系统索引](#附录b-旧系统索引)
---
## 第一章 总纲
### 1.1 设计原则
| # | 原则 | 说明 |
|:-:|:-----|:------|
| 1 | **目标架构驱动** | 本宪法描述的是最终目标架构。当前系统处于过渡期,存在「桥接」组件(如 `mc` CLI),它们会随着迁移推进逐步退役 |
| 2 | **统一入口** | 所有操作通过 `POST /api/ops/run`(后端)或 `agentos <command>`(CLI)执行。`mc` 是过渡期桥接入口,逐步被 `agentos` 取代 |
| 3 | **单点职责** | 每个模块只做一件事,禁止功能重叠(参见第三章组件状态) |
| 4 | **联邦透明** | 调用方无需关心操作在哪台机器执行,command_bus 自动路由 |
| 5 | **状态可观测** | 每个操作都有完整的生命周期(queued→preflighting→dispatching→running→completed/failed) |
| 6 | **前向兼容** | 旧模块持续可用直到新模块完全验证通过,但标记为"废弃"后不再修复 |
| 7 | **路径统一** | 所有文件路径通过 `local_paths.py` 获取,禁止硬编码 |
### 1.2 系统总架构
```
┌──────────────────────────────────────┐
│ agentos CLI (最终目标) │
│ agentos <domain> <command> │
│ │
│ ┌─────────┐ ┌───────────┐ │
│ │ matrix │ │ ave │ │ ← 插件自动发现
│ │ 社交矩阵 │ │ 视频工厂 │ │
│ ├─────────┤ ├───────────┤ │
│ │ fleet │ │ crawl │ │
│ │ 联邦管理 │ │ 内容采集 │ │
│ ├─────────┤ └───────────┘ │
│ │ serve │ │
│ │ 服务管理 │ │
│ └─────────┘ │
└──────────────────┬───────────────────┘
│
┌──────────────────┴───────────────────┐
│ mc CLI (过渡桥接) │
│ 15 个命令 → 分散到 agentos 各插件 │
└──────────────────┬───────────────────┘
│
┌──────────────────────┴──────────────────────┐
│ Dashboard │
│ (app.py:9988) Web 界面,封装所有领域 │
└──────────────────────┬──────────────────────┘
│
┌────────┴────────┐
│ command_bus.py │ ← 传输层(唯一通道,不变)
└────────┬────────┘
│
┌─────────────────────────────┼─────────────────────────────┐
│ │ │
┌────┴────┐ ┌────┴────┐ ┌─────┴─────┐
│ 本地执行 │ │ SSH远程 │ │ 队列 │
└────┬────┘ └────┬────┘ └─────┬─────┘
│ │ │
┌────┴─────────────────────────────┴─────────────────────────────┴────┐
│ 执行体 │
│ nurture / collect / login / comment / like / logout │
└──────────────────────────────┬──────────────────────────────────────┘
│
┌────────┴────────┐
│ cdp_connector │ ← 浏览器层(唯一入口)
│ + auth_manager │
└────────┬─────────┘
│
┌────────┴────────┐
│ Camoufox Browser│ ← 指纹浏览器
└─────────────────┘
```
---
## 第二章 架构分层
### 2.1 入口层
#### agentos CLI — 插件式框架(最终目标)
`agentos` CLI 是一个**插件式框架**,核心机制是 `agentos/base.py` 中定义的 `AgentOSPlugin` 基类 + 自动发现机制:
```
agentos <domain> <command> [options]
↑ 插件领域 ↑ 该领域下的子命令
```
现有 5 个领域插件,每个对应 Dashboard 的一个大类:
| 领域 | 插件文件 | 对应 Dashboard 视图群 | 来源 |
|:-----|:---------|:---------------------|:------|
| **matrix** | `plugins/matrix.py` | 矩阵养号系列 (11个视图) | 来自 mc CLI 的账号/养号/采集/评论/点赞/发布等 |
| **ave** | `plugins/ave.py` | 视频工厂系列 (4个视图) | **独立领域,非 mc 来源** |
| **crawl** | `plugins/crawl.py` | 内容采集系列 (3个视图) | **独立领域,非 mc 来源** |
| **fleet** | `plugins/fleet.py` | 联邦管理系列 (3个视图) | 来自 mc CLI 的远程/同步/对账 |
| **serve** | `plugins/serve.py` | 服务管理系列 (3个视图) | 来自 mc CLI 的 MCP/Dashboard/调度 |
`agentos` 采用**插件自动发现**机制:`discover_plugins()` 扫描 `plugins/` 目录,自动加载继承 `AgentOSPlugin` 的类。这意味着:
- **新增领域 = 在 plugins/ 加一个 .py 文件**,无需修改框架代码
- **已有字段通过 `nav` 属性(JSON 格式)与 Dashboard 导航联动**
- **所有插件共享 `--json`(JSON 输出)和 `--verbose` 通用参数**
#### mc CLI — 过渡期桥接入口
`mc` CLI 是 `agentos` 开发完成前的过渡入口。mc 的 15 个命令**分散对应**到多个 agentos 领域:
| mc 命令 | → agentos 领域 |
|:--------|:---------------|
| `mc run` / `mc account` / `mc collect` / `mc smart-login` / `mc task` / `mc blueprint` / `mc corpus` / `mc record` / `mc op` | → **`agentos matrix`** |
| `mc status` / `mc remote` | → **`agentos fleet`** |
| `mc proxy` / `mc sms` | → **`agentos serve`** (或 matrix) |
| `mc schedule` | → **`agentos serve`** |
#### 入口层汇总
| 入口 | 文件 | 当前状态 | 目标状态 | 职责 |
|:-----|:-----|:---------|:---------|:------|
| `agentos` CLI | `agentos/cli.py` | 🔄 **开发中** | ✅ **最终目标** | 插件式框架,统一所有领域入口 |
| `mc` CLI | `mc/cli.py` | ✅ **当前主力** 但标记为过渡 | 🗑️ **退役** → agentos | 命令行操作,逐个迁移到 agentos 各插件 |
| Dashboard | `app.py:9988` | ✅ **活跃** | ✅ **一直保留** | Web 管理界面,封装所有领域 |
| `matrix.py` | `matrix.py` | ⏳ **过渡** | 🗑️ 退役 | 旧CLI入口,被 mc/agentos 替代 |
**迁移原则**:
1. `mc` 的命令**不是全部进 `agentos matrix`**,而是按领域分到对应的 agentos 插件
2. 每迁移一个命令,`mc` 对应子命令标记为 `@deprecated` 并指向正确的 `agentos <domain>` 用法
3. `agentos serve` 和 `agentos fleet` 可以独立于 `agentos matrix` 先行完成(因为它们依赖少)
4. 新增领域插件无需修改框架——加文件即可
#### Dashboard 与 agentos 的对应关系
Dashboard 的 33 个视图按领域分组,与 agentos 插件一一对应:
| Dashboard 导航分组 | 包含视图 | → agentos 插件 |
|:------------------|:---------|:--------------|
| 📱 矩阵 | 11 个视图(账号/养号/采集/发布/评论/点赞/蓝图/定时/语料/登录/指挥台) | **matrix** |
| 🎬 视频工厂 | 4 个视图(渲染/脚本/素材/模板) | **ave** |
| 📡 内容采集 | 3 个视图(任务/源/历史) | **crawl** |
| 🖥️ 联邦 + 机器状态 | 4 个视图(状态/同步/对账/远程) | **fleet** |
| ⚙️ 服务 | 3 个视图(MCP/Dashboard/调度) | **serve** |
### 2.2 传输层
传输层是**整个联邦系统的唯一命令通道**。所有操作(本机和远程)都通过 `command_bus.py` 分发。
| 组件 | 文件 | 状态 | 职责 |
|:-----|:-----|:-----|:------|
| **CommandBus** | `services/command_bus.py` | ✅ **核心** | 命令生命周期管理、机器路由、状态轮询 |
| MachineSession | 同上 | ✅ **核心** | 单机会话、预检、发送、轮询、取消 |
| Command | 同上 | ✅ **核心** | 命令模型(含生命周期状态机) |
| `c2/command_bus.py` | 旧版C2 | 🗑️ **废弃** | 被新版 command_bus 替代 |
**API 合约**:
```
POST /api/ops/run {type, accounts, params}
→ {status, commands: [{run_id, machine, status, pid, message}]}
GET /api/ops/status [?machine=xxx]
→ {commands: [{run_id, type, accounts, status, elapsed_sec, message}]}
GET /api/ops/machines
→ {machines: {machine_name: {reachable, browsers_running, active_commands}}}
POST /api/ops/cancel/{run_id}
→ {ok: true}
```
**规则**:
- 所有执行操作(nurture/collect/login/logout/comment/like)必须走 CommandBus
- 禁止绕过 CommandBus 直接调用 `subprocess.Popen`、`SSH`、`mc run` 等
- 前端统一使用 `ExecutionPipeline.run()` (参见 `static/index.html`)
### 2.3 执行体层 (Executors)
执行体是被 CommandBus 调用的具体操作实现。
| 操作 | 命令模板 | 后端执行文件 | 状态 |
|:-----|:---------|:-------------|:-----|
| **nurture** | `mc run --accounts=X --blueprints=Y --rounds=N` | `nurture_runner.sh` → `nurture/runner.py` | ✅ |
| **collect** | `mc collect --phone=X` | `collect_batch_runner.py` | ✅ |
| **login** | `mc smart-login X` | `sms_login.py` / `xhs_login.py` | ✅ |
| **logout** | `mc account logout X` | via matrix_mgmt | ✅ |
| **comment** | `mc task comment --account=X --url=Y` | via mc/task.py | ✅ |
| **like** | `mc task like --account=X --url=Y` | via mc/task.py | ✅ |
**规则**:
- 每个执行体必须支持 `--phone` 或 `--account` 单身份模式(由 command_bus 按机器分组后调用)
- 执行体只做一件事,不负责机器路由、预检、结果回传
- 结果以 JSON 文件写入 `$AGENT_LOCAL/runtime/{op_type}/results/{run_id}.json`
### 2.4 浏览器层
浏览器层是**所有浏览器操作的唯一接口**。三个模块对应不同阶段,但**现阶段只用 cdp_connector.py**。
| 组件 | 文件 | 状态 | 职责 |
|:-----|:-----|:------|:------|
| **CDPConnector** | `cdp_connector.py` | ✅ **活跃 - 主接口** | 浏览器启动/连接/导航/关闭 |
| **auth_manager** | `auth_manager.py` | ✅ **活跃** | 登录状态检测(Cookie / DOM 双维度) |
| **anti_detection** | `anti_detection.py` | ✅ **活跃** | 行为指纹、人体延迟模拟 |
| **page_state** | `page_state.py` | ✅ **活跃** | 页面模式检测(grid/player/search) |
| **GracefulBrowser** | `browser_utils.py` | ✅ **活跃** | 浏览器优雅退出 + 超时自动关闭 |
| camoufox_manager | `camoufox_manager.py` | 🗑️ **废弃** | 被 CDPConnector 替代 |
| browser_manager | `browser_manager.py` | 🗑️ **废弃** | 实验性模块,从未正式使用 |
**规则**:
- 所有浏览器操作必须通过 `CDPConnector` 创建/管理
- 登录状态检测必须通过 `auth_manager.get_login_status()`(Cookie + DOM 双重验证)
- 行为模拟必须通过 `anti_detection.BehaviorProfile`
- 禁止直接写 `camoufox` 或 `playwright` 原生调用
### 2.5 数据层
| 组件 | 位置 | 访问方式 | 状态 |
|:-----|:-----|:---------|:------|
| **matrix_mgmt** | `matrix_mgmt.py` | `MatrixManager()` 实例 | ✅ **核心** |
| **accounts.yaml** | `agent-local/tools/matrix/config/` | 通过 matrix_mgmt | ✅ |
| **identities/** | `agent-local/tools/matrix/identities/` | 通过 matrix_mgmt | ✅ |
| **anchor_db** | `matrix_modules/nurture/anchor_db.py` | 养号行为锚点 | ✅ |
| **local_paths** | `local_paths.py` | **路径获取的唯一入口** | ✅ **核心** |
**规则**:
- 账号 CRUD **必须**通过 `matrix_mgmt.MatrixManager`
- 所有路径 **必须**通过 `local_paths.py`,禁止 `Path.home() / "workbuddy-agent-os" / ...`
- 跨机账号数据通过 `matrix_mgmt._read_all_machines_accounts()` 聚合
---
## 第三章 组件状态与生命周期
每个组件有以下状态之一:
| 状态 | 标识 | 含义 | 处理方式 |
|:-----|:-----|:------|:---------|
| ✅ **活跃** | 绿色 | 当前标准组件,所有新代码必须使用 | 持续维护 |
| ⏳ **过渡** | 黄色 | 正在被取代,但仍被引用 | 尽快迁移 |
| 🔄 **开发中** | 蓝色 | 新开发尚未完成 | 完成后切换 |
| 🗑️ **废弃** | 红色 | 不再维护,将归档 | 迁移到 archive/ |
| 归档 | — | 已从主代码库移除,只保留参考 | 在 archive/ 中只读 |
### 完整状态表
详见 [附录A](#附录a-组件状态一览表)
---
## 第四章 调用规范
### 4.1 前端 → 后端 调用规则
```
前端点击按钮
→ collectExec() / doNurtureExec() / runComment() / ...
→ ExecutionPipeline.run({type, accounts, params, logId, statusId})
→ fetch /api/ops/machines (预检)
→ fetch POST /api/ops/run {dry_run} (计划)
→ confirm() (确认)
→ fetch POST /api/ops/run (执行)
→ setInterval fetch /api/ops/status (轮询)
→ 完成后停止轮询
```
**规则**:
- 所有执行按钮**必须**使用 `ExecutionPipeline.run()`,禁止手动写 fetch 逻辑
- `ExecutionPipeline` 是前端唯一的执行入口
- 新视图必须通过 `router.js` 注册为 migrated view
### 4.2 后端 → 执行体 调用规则
```
command_bus.dispatch(type, accounts, params)
→ 按 machine 分组
→ 每组一条命令(含多个账号)
→ preflight() 检查机器+槽位
→ graceful_exit() 清理同机残留
→ send() 发送到本机/远程
→ nurture_runner.sh / mc collect / mc smart-login ...
```
**规则**:
- 参数传递用 `accounts=["a","b","c"]` 批量形式(按机器分组后)
- 结果回传用 JSON 文件 → command_bus.poll() 读取
### 4.3 路径获取规则
```python
# ✅ 正确: 使用 local_paths
from local_paths import config_path, data_path, profiles_path
accounts = config_path("accounts.yaml") # → correct path
db = data_path("matrix.db") # → correct path
# ❌ 错误: 硬编码
Path.home() / "workbuddy-agent-os" / "agent-local" / "tools" / ...
```
---
## 第五章 数据流规范
### 5.1 命令生命周期状态机
```
┌────────────┐
│ queued │
└─────┬──────┘
│
┌─────┴──────┐
│ preflighting│
└─────┬──────┘
┌──────┴───────┐
│ │
┌──────┴─────┐ ┌────┴──────┐
│ preflight_ │ │dispatching│
│ failed │ └────┬──────┘
└────────────┘ │
┌──────┴──────┐
│ running │
└──────┬──────┘
┌──────────────┼────────────────┐
│ │ │
┌──────┴─────┐ ┌──────┴──────┐ ┌──────┴──────┐
│ completed │ │ failed │ │ timed_out │
└────────────┘ └─────────────┘ └─────────────┘
```
### 5.2 数据流向
```
用户操作 → ExecutionPipeline → fetch /api/ops/run
→ command_bus.dispatch()
→ MachineSession.send()
→ (本机) subprocess.Popen / (远程) SSH
→ executor script
→ 写入 $AGENT_LOCAL/runtime/{type}/results/{run_id}.json
← {run_id, status, pid}
← command_bus.poll() 读取结果文件
← ExecutionPipeline 轮询 /api/ops/status
← 前端显示
```
---
## 第六章 迁移路线图
### Phase 0: agentos 能力建设(最高优先级)
`agentos` CLI 是**插件式框架**,现有 5 个领域插件。优先把核心操作迁移到正确的插件:
#### agentos matrix(核心 — P0)
| mc 命令 | agentos 对应 | 状态 |
|:--------|:------------|:------|
| `mc account` → | `agentos matrix account` | 🔄 待迁移 |
| `mc run` → | `agentos matrix run` | 🔄 待迁移 |
| `mc collect` → | `agentos matrix collect` | 🔄 待迁移 |
| `mc smart-login` → | `agentos matrix login` | 🔄 待迁移 |
| `mc account logout` → | `agentos matrix logout` | 🔄 待迁移 |
| `mc task comment/like` → | `agentos matrix comment / like` | 🔄 待迁移 |
| `mc blueprint` → | `agentos matrix blueprint` | 🔄 待迁移 |
| `mc corpus` → | `agentos matrix corpus` | 🔄 待迁移 |
#### agentos fleet(P1 — 独立可先行)
| mc 命令 | agentos 对应 | 状态 |
|:--------|:------------|:------|
| `mc status` → | `agentos fleet status` | 🔄 待迁移 |
| `mc remote exec` → | `agentos fleet exec` | 🔄 待迁移 |
| — | `agentos fleet sync` | ✅ 已有 |
#### agentos serve(P1 — 独立可先行)
| mc 命令 | agentos 对应 | 状态 |
|:--------|:------------|:------|
| `mc schedule` → | `agentos serve schedule` | 🔄 待迁移 |
| `mc proxy` → | `agentos serve proxy` | 🔄 待迁移 |
| `mc sms` → | `agentos serve sms` | 🔄 待迁移 |
#### agentos ave(独立领域,不来自 mc)
| 功能 | agentos 对应 | 状态 |
|:-----|:------------|:------|
| 渲染任务 | `agentos ave render` | ✅ 已有 |
| 脚本生成 | `agentos ave script` | ✅ 已有 |
| 素材库 | `agentos ave materials` | ✅ 已有 |
| 模板管理 | `agentos ave templates` | ✅ 已有 |
#### agentos crawl(独立领域,不来自 mc)
| 功能 | agentos 对应 | 状态 |
|:-----|:------------|:------|
| 采集任务 | `agentos crawl tasks` | ✅ 已有 |
| 源管理 | `agentos crawl sources` | ✅ 已有 |
| 采集历史 | `agentos crawl history` | ✅ 已有 |
每迁移一个命令,`mc` 对应子命令标记为 `@deprecated` 并指向 `agentos`。
当 `mc` 所有命令都迁移完成后,`mc` 本身退役。
### Phase 1: 清理废弃代码(与 Phase 0 并行)
| 待归档文件 | 目标位置 | 替代方案 |
|:-----------|:---------|:---------|
| `camoufox_manager.py` | `archive/camoufox_manager.py` | `cdp_connector.py` |
| `browser_manager.py` | `archive/browser_manager.py` | `cdp_connector.py` |
| `switch_account.py` | `archive/switch_account.py` | —(已废弃功能) |
| `c2/command_bus.py` | `archive/c2_command_bus.py` | `services/command_bus.py` |
| `c2/profile_scraper.py` | `archive/c2_profile_scraper.py` | Dashboard 采集API |
### Phase 2: 功能整合(Phase 0 中并行)
| 待整合 | 目标 | 说明 |
|:-------|:------|:------|
| `nurture_daily.py` → `orchestrator.py` | 统一养号引擎 | 新版orchestrator完成adoption |
| `remote_exec.py` → `command_bus.py` | 统一远程执行 | command_bus._send_remote 已实现 |
| `operation_queue.py` → `command_bus.py` | 统一队列 | command_bus 内置队列 |
| `resource_lock.py` → `browser_orchestrator.py` | 统一资源锁 | browser_orch 做并发控制 |
| `matrix.py` → `mc/cli.py` | 统一入口 | mc 已有完整命令集 |
### Phase 3: 标准化(贯穿始终)
| 待标准化 | 说明 |
|:---------|:------|
| 所有文件改用 `local_paths.py` | 消除硬编码路径 |
| `extract_douyin()` 加入登录检测 | 对标 `extract_xiaohongshu()` |
| 统一日志格式(JSON Lines) | 便于聚合分析 |
### 迁移原则
1. **先存档,不删除** — 旧代码移到 `archive/`,不删 git 历史
2. **新系统允许有问题** — 发现问题就修问题,不退回旧系统
3. **冻结旧系统** — 废弃模块不再提交修复PR
4. **文档先行** — 每次迁移前更新宪法附录
---
## 第七章 例外处理
### 7.1 允许绕过的情形
在以下情形可以临时绕过规范,但必须**事后补充 Issue/MR**:
1. **紧急修复线上问题** — 但修复后24小时内必须补全规范
2. **一次性迁移/归档脚本** — 迁移完成后删除
3. **实验性新功能** — 标记为 `@experimental`,独立目录开发
### 7.2 违规处理
对违反本宪法的代码合并/部署:
- 代码审查不通过
- Dashboard 部署自动回滚
- 运行期拦截告警(guardd 检测到不一致时报警)
---
## 附录A: 组件状态一览表
### 入口层
| 组件 | 当前状态 | 目标状态 | 说明 |
|:-----|:---------|:---------|:------|
| `agentos` CLI (框架) | 🔄 **开发中** | ✅ **最终目标** | 插件式框架,`agentos <domain> <command>` |
| `agentos/plugins/matrix.py` | 🔄 **开发中** | ✅ **最终目标** | 社交矩阵插件 |
| `agentos/plugins/ave.py` | ✅ **已有** | ✅ **保留** | 视频工厂插件(独立领域) |
| `agentos/plugins/crawl.py` | ✅ **已有** | ✅ **保留** | 内容采集插件(独立领域) |
| `agentos/plugins/fleet.py` | ✅ **已有** | ✅ **保留** | 联邦管理插件 |
| `agentos/plugins/serve.py` | ✅ **已有** | ✅ **保留** | 服务管理插件 |
| `mc/cli.py` | ✅ **活跃(桥接)** | 🗑️ **退役** | 当前主力,逐个迁移到 agentos 各插件 |
| `app.py` (Dashboard) | ✅ **活跃** | ✅ **保留** | Web 界面,长期存在 |
| `matrix.py` | ⏳ **过渡** | 🗑️ **退役** | 旧入口,被 mc/agentos 替代 |
### 传输层
| 组件 | 状态 | 迁移目标 | 备注 |
|:-----|:-----|:---------|:-----|
| `services/command_bus.py` | ✅ **活跃 (标准)** | — | **所有操作必走这里** |
| `routes/ops.py` | ✅ **活跃** | — | command_bus 的 API 暴露 |
| `c2/command_bus.py` | 🗑️ **废弃** | → `services/command_bus.py` | Phase1 归档 |
| `c2/profile_scraper.py` | 🗑️ **废弃** | → Dashboard 采集 | Phase1 归档 |
| `services/operation_queue.py` | 🗑️ **废弃** | → `command_bus.py` | Phase2 整合 |
| `services/remote_exec.py` | 🗑️ **废弃** | → `command_bus.py` | Phase2 整合 |
| `services/resource_lock.py` | 🗑️ **废弃** | → `browser_orchestrator.py` | Phase2 整合 |
### 执行体层
| 组件 | 状态 | 迁移目标 | 备注 |
|:-----|:-----|:---------|:-----|
| `nurture_runner.sh` | ✅ **活跃** | — | 养育执行包装器 |
| `collect_batch_runner.py` | ✅ **活跃** | — | 批量采集引擎 |
| `collect_homepage_info.py` | ✅ **活跃** | — | 单身份采集逻辑 |
| `sms_login.py` / `xhs_login.py` / `douyin_login.py` | ✅ **活跃** | — | 登录执行体 |
| `nurture_daily.py` | ⏳ **过渡** | → `orchestrator.py` | Phase2 迁移 |
| `nurture/runner.py` | ⏳ **过渡** | 拆分为子模块 | 75KB过大需拆分 |
| `orchestrator.py` | 🔄 **开发中** | — | 新版养号引擎 |
### 浏览器层
| 组件 | 状态 | 迁移目标 | 备注 |
|:-----|:-----|:---------|:-----|
| `cdp_connector.py` | ✅ **活跃 (标准)** | — | **所有浏览器操作的唯一入口** |
| `auth_manager.py` | ✅ **活跃** | — | 登录状态检测唯一入口 |
| `anti_detection.py` | ✅ **活跃** | — | 行为指纹 |
| `browser_utils.py` | ✅ **活跃** | — | 优雅退出 |
| `page_state.py` | ✅ **活跃** | — | 页面模式检测 |
| `camoufox_manager.py` | 🗑️ **废弃** | → `cdp_connector.py` | Phase1 归档 |
| `browser_manager.py` | 🗑️ **废弃** | 直接归档 | Phase1 归档 |
| `switch_account.py` | 🗑️ **废弃** | 直接归档 | Phase1 归档 |
### 数据层
| 组件 | 状态 | 备注 |
|:-----|:------|:------|
| `matrix_mgmt.py` | ✅ **活跃 (标准)** | 账号管理唯一入口 |
| `local_paths.py` | ✅ **活跃 (标准)** | 路径获取唯一入口 |
| `anchor_db.py` | ✅ **活跃** | 养号行为数据库 |
| `auth_manager.py` | ✅ **活跃** | Cookie/DOM 登录检测 |
### Dashboard 服务层
| 组件 | 状态 | 备注 |
|:-----|:------|:------|
| `command_bus.py` | ✅ **核心** | 命令传输 |
| `browser_orchestrator.py` | ✅ **活跃** | 并发控制+错峰 |
| `preflight.py` | ✅ **活跃** | 执行前预检 |
| `data_aggregator.py` | ✅ **活跃** | 数据聚合 |
| `log_aggregator.py` | ✅ **活跃** | 日志聚合 |
| `remote_exec.py` | 🗑️ **废弃** | 被 command_bus 替代 |
| `operation_queue.py` | 🗑️ **废弃** | 被 command_bus 替代 |
| `resource_lock.py` | 🗑️ **废弃** | 被 browser_orch 替代 |
---
## 附录B: 旧系统索引
### 已归档文件 (archive/)
位于 `05_tools/07_matrix/scripts/archive/`,共 41 个文件,全部为 Phase A/B 测试脚本。
**参考价值**:这些文件不再被任何活跃代码引用,但包含部分可复用的 DOM 操作 selector/pattern。
### 废弃但未归档文件 (需 Phase1 处理)
| 文件 | 位置 | 最后改动 | 归档目标 |
|:-----|:------|:---------|:---------|
| camoufox_manager.py | scripts/ | — | archive/ |
| browser_manager.py | scripts/ | — | archive/ |
| switch_account.py | scripts/ | — | archive/ |
| c2/command_bus.py | scripts/c2/ | — | archive/ |
| c2/profile_scraper.py | scripts/c2/ | — | archive/ |
---
> **本宪法每季度审查一次,根据系统实际演进情况更新版本号。**
>
> 下一版预期: v1.1(Phase 1 清理完成后)
@@ -0,0 +1,179 @@
# AgentOS 联邦架构 v3.0 — 完整蓝图
> **版本**: 3.0.0 | **更新**: 2026-06-17
> **目标**: 统一三机联邦,每机智能体可独立运作,Dashboard 可统一指挥
---
## 一、系统架构总览
```
┌──────────────────────────────────────────────────────────────┐
│ 用户入口层 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────┐ │
│ │ Web看板 │ │ 智能体 │ │ CLI终端 │ │ 定时任务 │ │
│ │ (SPA) │ │ (AI) │ │ (SSH) │ │ (cron/task) │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └──────┬───────┘ │
└───────┼──────────────┼──────────────┼───────────────┼─────────┘
│ │ │ │
┌───────▼──────────────▼──────────────▼───────────────▼─────────┐
│ API 网关层 (FastAPI :9988) │
│ │
│ /api/plugins/* — 插件元信息 │
│ /api/identity — 本机身份 │
│ /api/machines — 联邦机器状态 │
│ /api/health — 健康检查 │
│ /api/matrix/* — 矩阵养号全套 (accounts/nurture/blueprint) │
│ /api/federation/* — 联邦远程操作 (nurture/exec/collect/login) │
│ /api/machine/* — 远程命令执行 │
│ /api/push/* — 心跳推送 │
└───────┬──────────────────────┬──────────────────┬──────────────┘
│ │ │
┌───────▼────────┐ ┌─────────▼────────┐ ┌────▼──────────┐
│ 本机执行 │ │ 远程 SSH 执行 │ │ 跨机数据聚合 │
│ subprocess │ │ remote_exec.py │ │ data_aggregtor│
│ mc run / mc ✅│ │ SSH → 远程 mc │ │ HTTP拉取 │
└────────────────┘ └──────────────────┘ └───────────────┘
```
---
## 二、API 分层
### 2.1 插件层 (plugins/)
| 插件 | 职责 | API |
|:-----|:-----|:----|
| `guardd` | 联邦心跳/机器状态 | `/api/machines`, `/api/push/*` |
| `matrix` | 矩阵养号 | `/api/plugins/matrix/*` |
| `federation` | 联邦操作 | `/api/federation/*` |
| `scheduler` | 定时调度 | `/api/plugins/scheduler/*` |
| `sms_proxy_api` | 短信服务 | `/api/sms/*` |
### 2.2 路由层 (routes/)
| 路由 | 职责 | 端点 |
|:-----|:-----|:-----|
| `routes/matrix.py` | 账号管理+养号+蓝图+原子操作 | `/api/matrix/*` |
### 2.3 服务层 (services/)
| 服务 | 职责 |
|:-----|:-----|
| `remote_exec.py` | SSH远程执行引擎 |
| `data_aggregator.py` | 联邦数据聚合 |
| `operation_queue.py` | 操作队列 |
| `resource_lock.py` | 资源锁 |
| `preflight.py` | 前置检查 |
| `log_aggregator.py` | 日志聚合 |
---
## 三、视图完整清单 (25个)
| 导航组 | 视图 | 实现状态 | API 依赖 |
|:-------|:-----|:---------|:---------|
| **矩阵** | 账号管理 (`matrix-sms-proxy`) | ✅ 功能完整 | `/api/matrix/accounts` |
| | 养号执行 (`matrix-nurture`) | 🔧 近期修复 | `/api/matrix/nurture/start` |
| | 信息采集 (`matrix-collect`) | 🟡 待验证 | `/api/matrix/collect/*` |
| | 内容发布 (`matrix-publish`) | 🟡 待验证 | `/api/matrix/publish/*` |
| | 蓝图管理 (`matrix-blueprints`) | ✅ 功能完整 | `/api/matrix/blueprints` |
| | 定向评论 (`matrix-comment`) | 🟡 待验证 | `/api/matrix/comment/*` |
| | 定时任务 (`matrix-schedule`) | 🟡 待验证 | `/api/matrix/schedule/*` |
| | 语料库 (`matrix-corpus`) | 🟡 待验证 | `/api/matrix/corpus/*` |
| **视频工厂** | 渲染任务 (`ave-render`) | 🟡 待验证 | `/api/productions` |
| | 脚本生成 (`ave-script`) | 🟡 待验证 | `/api/characters` |
| | 素材库 (`ave-materials`) | 🟡 待验证 | `/api/assets/*` |
| | 模板 (`ave-templates`) | 🟡 待验证 | `/api/capabilities` |
| **内容采集** | 采集任务 (`crawl-tasks`) | 🟡 待验证 | `/api/crawl/*` |
| | 源管理 (`crawl-sources`) | 🟡 待验证 | `/api/crawl/*` |
| | 采集历史 (`crawl-history`) | 🟡 待验证 | `/api/crawl/*` |
| **联邦** | 机器状态 (`machines`) | ✅ 功能完整 | `/api/machines` |
| | 一键同步 (`fleet-sync`) | ✅ 功能完整 | `/api/git-sync` |
| | 对账检查 (`fleet-reconcile`) | 🟡 待验证 | `/api/fleet/reconcile` |
| | 远程Shell (`fleet-exec`) | 🟡 待验证 | `/api/machine/exec` |
| **服务** | MCP状态 (`serve-mcp`) | 🔴 未实现 | N/A |
| | Dashboard日志 (`serve-dashboard`) | 🟡 待验证 | N/A |
| | 全局定时任务 (`serve-schedule`) | 🔴 未实现 | N/A |
---
## 四、执行链路 (关键路径)
### 4.1 养号执行链路(已修复 ✅)
```
用户点击「执行选中」
→ nurtureExecSelected() ← index.html JS
→ POST /api/matrix/nurture/start ← routes/matrix.py
→ 自动选蓝图 + 路由到机器
→ 本机: subprocess mc run ← local path
→ 远程: remote_exec exec_nurture ← SSH path
→ SSH → mc run ← remote path
→ mc/engine.py ← 身份分组+浏览器
→ cdp_connector.py ← Camoufox
```
### 4.2 智能登录链路(待验证 ⚠️)
```
用户点击「登录」
→ POST /api/federation/login
→ remote_exec exec_login
→ SSH → mc smart-login {account_id}
→ douyin_login.py / xiaohongshu_login.py
```
### 4.3 信息采集链路(待验证 ⚠️)
```
用户点击「采集」
→ POST /api/federation/collect
→ remote_exec exec_collect
→ SSH → mc collect
```
---
## 五、三机统一环境
| 项目 | chengzigedeAir | 5kechengdeAir | 7kecheng |
|:-----|:--------------|:-------------|:---------|
| Python venv | agent-os ✅ | agent-os ✅ | agent-os ✅ |
| camoufox | 0.4.11 ✅ | 0.4.11 ✅ | 0.4.11 ✅ |
| playwright | 1.58.0 ✅ | 1.58.0 ✅ | 1.58.0 ✅ |
| Git版本 | cc04e9d93a | cc04e9d93a | cc04e9d93a |
| Dashboard | launchd ✅ | launchd ✅ | launchd ✅ |
| 身份目录 | phone_*命名 ✅ | phone_*命名 ✅ | phone_*命名 ✅ |
| 账号总数 | 30 (联邦聚合) | 30 (联邦聚合) | 30 (联邦聚合) |
---
## 六、任务优先级 (Phase 3 执行计划)
### P0 — 核心功能修复(本机优先)
| # | 任务 | 视图 | 预估 |
|:-:|:-----|:-----|:----|
| 1 | 养号执行端到端验证:API→mc run→浏览器→执行 | matrix-nurture | ✅ DONE |
| 2 | 账号管理视图修复:编辑/删除/状态显示 | matrix-sms-proxy | 1h |
| 3 | 蓝图管理视图修复:增删改+编排 | matrix-blueprints | 1h |
| 4 | 信息采集端到端:触发→执行→结果回显 | matrix-collect | 2h |
| 5 | 智能登录端到端:从看板触发远程登录 | federation | 2h |
### P1 — 联邦功能
| # | 任务 | 视图 | 预估 |
|:-:|:-----|:-----|:----|
| 6 | 远程执行路由:本机/远程账号智能分发 | 全部矩阵视图 | 2h |
| 7 | 执行结果回显:进度条+日志流 | matrix-nurture | 2h |
| 8 | 联邦定时任务:跨机定时执行 | serve-schedule | 3h |
### P2 — 完善
| # | 任务 | 视图 | 预估 |
|:-:|:-----|:-----|:----|
| 9 | 语料库管理 | matrix-corpus | 2h |
| 10 | 定向评论 | matrix-comment | 2h |
| 11 | 远程Shell | fleet-exec | 1h |
| 12 | 对账检查可视化 | fleet-reconcile | 1h |
@@ -0,0 +1,168 @@
# AgentOS 原子操作架构审计与重构方案
## 一、旧代码设计原则(提炼自旧版 runner.py / interact.py)
### 1.1 每步操作 = 状态机三要素
```
[前置状态检测] → [操作执行] → [后置状态验证]
↓ ↓ ↓
当前在哪个页面? 执行操作 操作是否真的生效了?
```
**旧代码实现**(`_ensure_player_state`、`CommentStateMachine`):
```python
# 前置检测
state = await _detect_page_state(page)
# 只有确认在播放页才执行操作
if state not in ("player", "search_player"):
recovered = await _ensure_player_state(...)
# 执行
await page.keyboard.press("KeyZ")
# 后置验证
assert await _check_anchor(page, 'video_page')
```
### 1.2 锚点系统(`_check_anchor`)
| 锚点 | 检测方式 | 作用 |
|:-----|:---------|:-----|
| `video_page` | `video` 元素 > 0 | 确认在视频播放页 |
| `home_page` | `.discover-video-card-item` > 0 | 确认在首页feed |
| `video_playing` | `!video.paused && readyState > 0` | 确认视频在播放 |
| `has_videos` | `a[href*="/video/"]` > 0 | 页面有视频链接 |
### 1.3 评论区状态机(`CommentStateMachine`)
```
closed → panel_open → input_focused → text_entered → sent
↓ ↓ ↓
键盘x打开 检测activeElement 检测textContent
验证has_panel 验证isEditable 验证has_text
```
**核心:每一步都调用 `detect()` 验证状态是否真的变化了。**
### 1.4 行为链(`CHAINS`)
旧代码用**行为链**而非固定步骤模板:
```python
CHAINS = [
[('open_comment', 'KeyX'),
('type_comment', 'input'), # 调用 _send_comment 状态机
('wait_10s', 'wait'),
('scroll_comment', 'scroll')],
]
```
每个链中的操作都是**键盘快捷键优先**(KeyZ/KeyX/KeyG),DOM 兜底。
---
## 二、当前新代码的问题审计
| 问题 | 表现 | 根因 |
|:-----|:-----|:------|
| **无前置状态检测** | open_video 在首页找不到卡片→硬等30s→失败 | 不先检测页面状态就直接找元素 |
| **无后置验证** | post_comment 返回"sent"但评论没发出去 | 不检查评论区是否出现了刚发的文字 |
| **无锚点系统** | 所有操作都用 CSS 类名硬匹配(CSS modules 不可靠) | 没有用 video/card 等特征判断 |
| **状态机缺失** | 点赞/收藏/评论等操作的执行结果和页面实际脱节 | 没有 `detect()` 验证状态变化 |
| **DOM 优先于键盘** | 所有操作先找 DOM 元素,找不到才 fallback | 旧代码用键盘快捷键为主,更可靠 |
| **无回退策略** | 一个方法失败就放弃或硬等30s | 旧代码有3层回退(键盘→DOM→坐标) |
---
## 三、重构方案
### 3.1 新原子操作模板
```python
async def atomic_like(page) -> OpResult:
"""点赞操作(前后状态检测模板)"""
# 1. 前置状态检测
state = await detect_page_state(page)
if state not in ('player', 'search_player'):
return OpResult('like', False, f'不在播放页(state={state})')
# 2. 操作执行(键盘优先)
await page.keyboard.press('z')
await asyncio.sleep(1)
# 3. 后置验证(检测按钮状态变化)
ok = await verify_like(page) # 检测 data-e2e-state 或 toast
if ok:
return OpResult('like', True, '👍')
# 4. 回退:DOM 点击
btn = page.locator('[data-e2e="video-player-digg"]')
if await btn.count() > 0:
await btn.click()
await asyncio.sleep(1)
ok = await verify_like(page)
return OpResult('like', ok, '👍' if ok else '-')
```
### 3.2 统一状态检测函数
```python
async def detect_page_state(page) -> str:
"""检测当前页面状态"""
url = page.url
video_count = await page.evaluate("document.querySelectorAll('video').length")
cards = await page.evaluate(
"document.querySelectorAll('.discover-video-card-item, [data-e2e=\"alink-item\"]').length"
)
if video_count > 0 and '/video/' in url:
return 'player_full' # B模式:独立播放页
if video_count > 0 and 'modal_id' in url:
return 'player_modal' # A模式:弹窗播放
if video_count > 0:
return 'player_unknown' # 有视频,模式待定
if '/search/' in url:
return 'search'
if '/user/' in url:
return 'profile'
if cards > 0:
return 'grid' # 首页feed
return 'unknown'
```
### 3.3 每个操作绑定状态依赖
| 操作 | 前置状态要求 | 后置验证方式 |
|:-----|:------------|:-------------|
| `goto_home` | (任意) | state → 'grid' |
| `open_video` | 'grid' | state → 'player_*' |
| `like` | 'player_*' | 按钮state变化或toast出现 |
| `collect` | 'player_*' | 按钮state变化或toast出现 |
| `follow` | 'player_*' | 按钮文字从"关注"变"已关注" |
| `open_comments` | 'player_*' | state → 'comment_panel_open' |
| `post_comment` | 'comment_panel_open' | comment_list中出现刚发的文字 |
| `close_comments` | 'comment_panel_open' | state回到'player_*' |
| `next_video` | 'player_*' | modal_id或video内容变化 |
| `search` | (任意) | state → 'search' |
| `go_back` | (任意) | URL或state变化 |
---
## 四、实施计划
### Phase 1:基础设施(1-2小时)
1. 实现 `detect_page_state()` — 统一状态检测
2. 实现 `verify_*()` 系列 — 每个操作的后置验证函数
3. 实现 `ensure_page_state(target)` — 如果不在目标状态则导航过去
### Phase 2:重写原子操作(2-3小时)
4. 按模板重写 `douyin_ops.py` 中所有操作
5. 按模板重写 `ops/xhs_ops.py` 中所有操作
6. 移除所有无验证的假成功返回
### Phase 3:测试验证(1-2小时)
7. 逐步测试每个操作(用户交互模式)
8. 修复各平台的特定选择器/DOM差异
---
以上是完整的审计和方案。你要我按这个方向执行吗?
@@ -0,0 +1,320 @@
# 原子操作体系开发经验文档 v1.0
> 创建时间: 2026-06-21 10:05
> 时间跨度: 2026-06-20 09:00 ~ 2026-06-21 10:00
> 涉及平台: 抖音(douyin)、小红书(xiaohongshu)
> 文档性质: 经验沉淀 + 框架设计 + 代码对照
---
## 第一章:时间线回顾
### 2026-06-20(Day 1)
| 时间 | 事件 | 关键结论 |
|:-----|:-----|:---------|
| 09:00-12:00 | 登录状态机重构 + Vite前端修复 | 三组件架构(PlatformDetector/RecoveryChain/LoginManager)定型 |
| 14:00-16:20 | 抖音登录 3 种场景调试 | 全通。关键修复: 检测器误判(移除data-e2e anchor)、短信验证码取旧码、登录按钮是"确认登录"不是"登录" |
| 16:30-18:10 | 小红书登录修复 | 全通。关键修复: SmsRecovery调xhs_login、XhsDetector cookie误判、is_logged_in()太松、步骤顺序错误(同意并登录在点登录后)、div.foot-btn选择器、oauth-tip切换 |
| 18:10-20:40 | 养号蓝图v2.0 + 抖音日常45步测试 | 45步39成功。关键修复: open_video双击+验证+焦点、like从DOM改为键盘z、open_video加回首页兜底 |
| 20:40-23:10 | 抖音录制2轮 + 小红书原子操作测试 | 小红书post_comment首次成功(JS找输入框方案)。关键修复: xhs_ops补wait_watch/go_back、冷却前缀匹配 |
### 2026-06-21(Day 2)
| 时间 | 事件 | 关键结论 |
|:-----|:-----|:---------|
| 08:00-09:00 | 双平台修复 | follow键盘f→g、post_comment加send按钮查找+验证、open_video多选择器+状态检测 |
| 09:00-09:27 | 架构反思 | ghai指出新代码全不能用——缺乏前置状态检测和后置验证。Claw从头学习旧代码_retry_enter_video、_check_anchor、CommentStateMachine |
| 09:27-09:34 | 方案重构 | 提出三层状态模型(L1页面/L2区域/L3元素)、增强录制、单步调试、看板流程图 |
| 09:34-09:42 | PageInspector实现 | 创建page_inspector.py,L1/L2/L3三层检测 |
| 09:42-09:46 | 增强录制讨论 | ghai提出: 只按一次·标记状态变化,系统自动推断操作。Claw优化: 系统根据状态差自动识别操作类型 |
| 09:46-09:54 | ghai录制18步 | 首次用新思路录制。发现新问题: 收藏键是C不是无键、弹幕B键、分享V键 |
| 09:54-10:05 | 视觉状态层讨论 | ghai发现: 按钮变色(灰→红→黄)是重要的状态变化,当前录制没有捕获。提出L4视觉状态层 |
---
## 第二章:核心概念与设计原则
### 2.1 原子操作的本质
一个原子操作 = **四个要素**:
```
[前置状态] → [操作执行] → [后置状态] → [验证结果]
```
- **前置状态**必须包含: 页面类型(L1)、鼠标区域(L2)、元素详情(L3)、视觉状态(L4)
- **操作执行**是一个确定的动作: 点击某个元素、按某个键盘键
- **后置状态**与前置状态有明确差异(URL变化、DOM变化、视觉变化)
- **验证结果**是真实可观测的,不是代码返回的布尔值
### 2.2 错误模式总结
以下所有错误都有一个共同根因: **没有做状态检测**
| 错误表现 | 具体操作 | 原因 |
|:---------|:---------|:-----|
| open_video 在首页找不到卡片 | 直接找.discover-video-card-item | 不先检测是否在播放页 |
| like 返回"成功"但页面没反应 | 键盘z在feed流中无效 | 不检测是否在视频详情页 |
| collect 全部失败0.0s | 用[data-e2e]选择器找按钮 | 不检测按钮的视觉/属性状态 |
| post_comment 返回sent但评论没发 | pbcopy+Meta+V+Enter | 不验证comment-list是否出现文字 |
| follow 无反应 | KEYS['follow']='f' | 没有用录制数据验证(实际是g键) |
### 2.3 各种选择器优劣
| 方式 | 可靠性 | 适用场景 |
|:-----|:------|:---------|
| 键盘快捷键(z/c/g/x) | ⭐⭐⭐⭐⭐ | 抖音所有互动操作 |
| data-e2e 锚点 | ⭐⭐⭐ | 旧版抖音 (可能被新版移除) |
| CSS类名 | ⭐⭐ | 不稳定(CSS modules会加hash) |
| 坐标(录制位置) | ⭐⭐⭐⭐ | 固定布局中稳定 |
| 文字匹配 | ⭐⭐⭐ | 关注/发送等有固定文字 |
| 视觉状态(颜色) | ⭐⭐⭐⭐ | 🆕 L4层,按钮状态判断 |
### 2.4 抖音网页版快捷键完整表
```
互动类:
Z 赞/取消赞
C 收藏/取消收藏
G 关注/取消关注
F 进入作者主页
X 打开/关闭评论
V 复制分享口令
P 推荐给朋友
R 不感兴趣
播放类:
B 开始/关闭弹幕
J 清屏
K 自动连播
Y 网页内全屏
H 全屏
L 稍后再看
Space 暂停/播放
↑↓ 上下翻页
←→ 快进快退(长按2倍速)
Shift+/Shift- 音量调大/调小
```
---
## 第三章:统一状态模型(引擎层核心)
### 3.1 四层状态检测
```
L1: 页面类型
├── 判断依据: URL pattern + DOM特征(video数量、card数量、搜索栏、导航栏)
├── 抖音类型: grid(首页)、player_modal(弹窗)、player_full(独立页)、search(搜索)、profile(主页)
└── 小红书类型: grid(explore)、note_detail(笔记详情)、search(搜索结果)、profile(主页)
L2: 鼠标区域
├── 判断依据: 鼠标坐标 / 窗口尺寸 → 百分比区域
├── 区域类型: video_area(中央上)、bottom_bar(底部按钮)、comment_area(评论区)、feed_area(内容区)、nav_area(左侧导航)、sidebar(右侧推荐)
└── 用途: 确定操作上下文(在按钮区点击=互动操作,在feed区点击=选择内容)
L3: 元素详情
├── 检测: 鼠标正指向的元素(elementFromPoint) + 周围200px内的所有可交互元素
├── 属性: tag、class、text、位置、尺寸、visibility
└── 用途: 确定具体操作目标(这个SPAN是like-lottie点赞按钮)
L4: 视觉状态 🆕
├── 检测: computedStyle(color/fill/stroke)、data-state/aria-pressed属性、textContent变化
├── 典型变化:
│ ├── 点赞: 灰色(#999) → 红色(#ff2d55), data-e2e-state从空变digged
│ ├── 收藏: 灰色 → 黄色, 文字从"收藏"变"已收藏"
│ ├── 关注: 文字从"关注"变"已关注", 按钮颜色变红
│ └── 弹幕: aria-pressed属性变化
└── 用途: 验证操作是否真正生效(不是代码返回的假成功)
```
### 3.2 状态转换规则
```
抖音:
grid ──(双击卡片)──> player_modal
grid ──(搜索)──────> search
grid ──(点头像)────> profile
player_* ──(z键)───> player_*(点赞已变)
player_* ──(c键)───> player_*(收藏已变)
player_* ──(g键)───> player_*(关注已变)
player_* ──(go_back)──> grid
search ──(点结果)──> player_*
search ──(go_back)──> grid
profile ──(go_back)──> grid
小红书:
grid ──(点笔记)──> note_detail
note_detail ──(点❤️)──> note_detail(已赞)
note_detail ──(点⭐)──> note_detail(已收藏)
note_detail ──(go_back)──> grid
grid ──(搜索)──> search
search ──(点结果)──> note_detail
```
---
## 第四章:录制系统设计
### 4.1 录制原理
```
用户操作流程:
1. 按 · → 系统捕获状态快照(所有四层数据)
2. 做操作 → 用户自由操作(点击/键盘/停留/滚动)
3. 按 · → 系统捕获状态快照 + 自动对比差异
...重复...
4. 按 Esc → 结束录制
系统自动推断:
- 对比相邻两个状态的差异
- URL变化 → 可能进入新页面
- video数量变化 → 进入/离开播放页
- 按钮颜色变化 → 点赞/收藏/关注操作
- 评论输入框出现/消失 → 打开/关闭评论
```
### 4.2 录制数据格式
```json
{
"step": 2,
"label": "open_video", // 人工标注或系统自动建议
"before": {
"url": "...jingxuan", // L1
"page_type": "grid", // L1
"video_count": 0, // L1
"card_count": 20, // L1
"mouse_x": 262, "mouse_y": 209, // L2
"mouse_region": "video_area", // L2
"element_at_point": { // L3
"tag": "VIDEO", "class": "", ...
},
"visual_states": { // L4
"like_active": false, // 赞为空
"collect_active": false // 收为空
}
},
"action": {
"type": "click",
"x": 262, "y": 209,
"target": "VIDEO",
"click_count": 2 // 双击
},
"after": {
"url": "...modal_id=xxx",
"page_type": "player_modal",
"video_count": 1,
"diff": "从首页进入播放页"
}
}
```
### 4.3 标注系统(人工+自动)
录制后进入标注界面:
- 自动建议: 系统根据状态diff推断操作名称(URL变化→open_video, 按钮变色→like)
- 人工修正: 你可以修改名称、补充备注
- 合并步骤: 连续2-N步可以合并为1个复合原子操作(如: x+打字+发送 = post_comment)
---
## 第五章:当前代码状态
### 5.1 已修复的问题
| 文件 | 问题 | 修复 |
|:-----|:-----|:-----|
| douyin_ops.py | KEYS['follow']='f' → 应该是'g' | ✅ 已修复 |
| douyin_ops.py | collect没有键盘fallback | ⚠️ 加了C键但未测试 |
| douyin_ops.py | open_video选择器单一 | ✅ 加了多选择器+状态检测 |
| douyin_ops.py | post_comment无验证逻辑 | ✅ 加了send按钮搜索+comment-list文本验证 |
| xhs_ops.py | go_back未定义 | ✅ 已添加 |
| xhs_ops.py | wait_watch未定义 | ✅ 已添加 |
| xhs_ops.py | post_comment完全失败 | ✅ JS找输入框方案成功 |
| mc/engine.py | 冷却前缀不匹配(xhs_like不匹配like) | ✅ 已去前缀 |
### 5.2 仍需修复的问题
| 文件 | 问题 | 优先级 |
|:-----|:-----|:------|
| douyin_ops.py | collect 用 C 键(不是DOM选择器) | P0 |
| douyin_ops.py | 所有操作加 L4 视觉验证 | P0 |
| douyin_ops.py | 新增 danmaku(B键), share(V键) | P1 |
| xhs_ops.py | xhs_click_note go_back后feed未刷新 | P1 |
| xhs_ops.py | 小红书没有C/G快捷键,需要DOM点 | P1 |
### 5.3 关键文件清单
| 文件 | 作用 | 状态 |
|:-----|:-----|:----:|
| `scripts/ARCHITECTURE_AUDIT.md` | 新旧代码对比审计 | ✅ 完成 |
| `scripts/page_inspector.py` | 四层状态检测器(新) | ✅ 已创建 |
| `scripts/douyin_ops.py` | 抖音原子操作 | ⚠️ 部分修复 |
| `scripts/ops/xhs_ops.py` | 小红书原子操作 | ⚠️ 部分修复 |
| `scripts/mc/engine.py` | 执行引擎 | ✅ 冷却修复 |
| `scripts/mc/recorder.py` | 录制工具 | 🔵 待增强(L4+自动推断) |
| `blueprints/dy_step_test.json` | 抖音11步测试蓝图 | ✅ |
| `blueprints/xhs_test_all.json` | 小红书17步测试蓝图 | ✅ |
| `blueprints/dy_test_all.json` | 抖音16步全原子测试蓝图 | ✅ |
| `scripts/matrix_modules/nurture/runner.py` | 旧版稳定代码(参考用) | ✅ |
---
## 第六章:开发方法论
### 6.1 禁止事项
1. **不要修改旧代码** — 旧代码是宝贵的参考,即使不完美也证明了可行路径
2. **不要用CSS类名作为主要选择器** — CSS modules会使类名不可靠
3. **不要假设操作成功了** — 必须用L4视觉状态验证
4. **不要把抖音的操作方法套用给小红书** — 两个平台的DOM结构完全不同
5. **不要在没有录制数据支持的情况下添加新操作** — 优先让ghai录一次,从数据出发
### 6.2 高效开发流程
```
1. ghai录制真实操作(5-10分钟)
2. Claw分析录制数据,提取状态diff(2分钟)
3. 一起标注原子操作名称(2分钟)
4. Claw生成代码模板(1分钟)
5. ghai审核确认(1分钟)
6. 单步测试(3秒/步)
7. 全流程验证(1分钟)
总计: ~15分钟完成一个完整原子操作
```
反面对比:
```
旧流程: Claw手写代码 → 猜测选择器 → 跑全蓝图 → 等14分钟 → 失败 → 再猜 → ...
完全不可行
```
### 6.3 测试原则
1. **从首页开始**: goto_home是最基础的原子操作,先确认
2. **逐条路径测试**: 不要混在一起测
3. **三秒原则**: 单步测试结果3秒内必须看到,不等完整蓝图
4. **绿了就固化**: 一个操作测试通过立即标记绿色,不回头动
---
## 第七章:附录 - 按键映射
### 抖音 Keys 正确值
```python
KEYS = {
"like": "z", # ✅ 正确
"collect": "c", # ❌ 之前代码里没有定义
"comment": "x", # ✅ 正确
"follow": "g", # ✅ 修复后正确 (之前错为f)
"danmaku": "b", # 🆕 新增
"share": "v", # 🆕 新增(复制分享口令)
"clear_screen": "j", # 🆕 新增
"prev": "ArrowUp",
"next": "ArrowDown",
"enter": "Enter",
}
```
@@ -0,0 +1,343 @@
# AgentOS 原子操作体系 v2 完整规划
> 状态: 规划中 | 创建: 2026-06-21 09:30
> 目标: 建立系统性、可持续迭代的原子操作开发与测试体系
> 角色: ghai 是项目负责人/决策者,Claw 是技术搭档/建议者
---
## 一、核心理念
### 1.1 我们不是在写代码,是在建立一套"自动化操作知识库"
每个平台的每个操作,都应该像一本字典里的词条:
- 有明确的"前提条件"(在什么页面/状态下才能做)
- 有确定的"执行方式"(用什么方法做)
- 有可验证的"结果"(做了之后页面变成什么样子)
### 1.2 不做"按键精灵",做"智能操作代理"
按键精灵: 盲按 → 不管结果 → 继续按下一个
智能代理: 检测当前状态 → 确认可以操作 → 执行 → 验证结果 → 记录
### 1.3 开发效率 > 代码量
一次录制 = 10个原子操作的新代码,比你手写10个函数快100倍。
但前提是:录制系统能捕获足够的信息(状态+操作+结果),并且你我能高效标注它。
---
## 二、总架构:三层 + 两工具 + 一视图
```
┌─────────────────────────────────────────────────────────┐
│ 看板 (Dashboard) │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
│ │ 操作流程图 │ │ 录制标注界面 │ │ 测试结果面板 │ │
│ │ (你的操作地图)│ │ (你的编辑器) │ │ (你的眼睛) │ │
│ └──────────────┘ └──────────────┘ └──────────────┘ │
├─────────────────────────────────────────────────────────┤
│ 工具层 │
│ ┌──────────────────────┐ ┌───────────────────────┐ │
│ │ 增强录制系统 │ │ 单步调试模式 │ │
│ │ (捕获三层状态+操作) │ │ (mc debug --step) │ │
│ │ (支持人工标注命名) │ │ (3秒出结果不等待) │ │
│ └──────────────────────┘ └───────────────────────┘ │
├─────────────────────────────────────────────────────────┤
│ 引擎层 │
│ ┌──────────────────────────────────────────────────┐ │
│ │ PageState (统一状态模型) │ │
│ │ ┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐ │ │
│ │ │L1: │→│L2: │→│L3: │→│Action│→│验证 │ │ │
│ │ │页面│ │区域│ │元素│ │执行 │ │结果 │ │ │
│ │ └────┘ └────┘ └────┘ └────┘ └────┘ │ │
│ └──────────────────────────────────────────────────┘ │
│ 原子操作库 │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ 抖音 ops │ │ 小红书ops │ │ 未来平台 │ │
│ │ douyin/ │ │ xhs/ │ │ ... │ │
│ └──────────┘ └──────────┘ └──────────┘ │
└─────────────────────────────────────────────────────────┘
```
---
## 三、PageState 状态模型(引擎层核心)
### 3.1 抖音页面状态定义
| 状态名 | 判断条件 | 可用操作 |
|:------|:---------|:---------|
| `grid` | URL含jingxuan,card_count>0 | scroll_feed, open_video, search, goto_profile |
| `player_modal` | URL含modal_id,video>0 | like, collect, follow, comment, next_video, go_back |
| `player_full` | URL含/video/xxx | like, collect, follow, comment, go_back |
| `search` | URL含/search/ | click_result, scroll, go_back |
| `profile` | URL含/user/ | read_field, go_back |
### 3.2 小红书页面状态定义
| 状态名 | 判断条件 | 可用操作 |
|:------|:---------|:---------|
| `grid` | URL=/explore, note-item>0 | scroll_feed, click_note, search, goto_profile |
| `note_detail` | URL=/explore/xxx | like, collect, comment, post_comment, follow, go_back |
| `search` | URL=/search_result | click_result, go_back |
| `profile` | URL=/user/profile/xxx | read_field, go_back |
### 3.3 状态转换规则
```
grid ──(open_video/click_note)──> player/note_detail
grid ──(search)──────────────────> search
grid ──(goto_profile)────────────> profile
player ──(go_back)───────────────> grid
player ──(next_video)────────────> player (不同视频)
search ──(click_result)──────────> player/note_detail
search ──(go_back)───────────────> grid
profile ──(go_back)──────────────> grid
```
---
## 四、增强录制系统(工具层)
### 4.1 录制数据的完整结构
```json
{
"session": {
"platform": "douyin",
"account": "douyin_test",
"start_time": "2026-06-21T10:00:00",
"window_size": [702, 783]
},
"steps": [
{
"id": 1,
"label": "", // 你来命名(如"点开第一个视频")
"before": {
"url": "...",
"page_type": "grid",
"dom_snapshot": {
"video_count": 0,
"card_count": 20,
"has_search_bar": true,
"has_nav": true,
"author_id": null,
"is_self": false
},
"mouse_position": [434, 190],
"mouse_region": "feed_area",
"nearby_elements": [
{"tag": "A", "class": "cover mask ld", "text": "", "x": 375, "y": 292}
]
},
"action": {
"type": "click",
"x": 375,
"y": 292,
"target_tag": "A",
"target_class": "cover mask ld",
"target_text": "",
"details": "笔记封面点击,可能打开了笔记详情页"
},
"after": {
"url": "https://www.douyin.com/jingxuan?modal_id=xxx",
"page_type": "player_modal",
"dom_snapshot": {
"video_count": 1,
"card_count": 0,
"has_comment_list": true
},
"url_changed": true,
"dom_diff": "video元素从0变为1,进入了播放页"
}
}
]
}
```
### 4.2 录音交互流程
```
1. 你启动录制: mc record --account=douyin_test --platform=douyin
→ 浏览器打开,开始录制
2. 你做操作,按 `·` 标记每一步
→ 系统自动捕获 before/action/after
3. 录制结束按 Esc
→ 系统保存完整录制数据
4. 进入标注界面(Dashboard新页面)
→ 展示每一步的 before/action/after
→ 自动检测操作类型(点击/按键/滚动)
→ 自动建议原子操作名称(like/collect/comment)
→ 你可以修改名称和补充说明
→ 连续2步可以合并为1个原子操作(如:开评论(x) + 输入 + 发送 = post_comment)
5. 标注完成 → 系统自动生成原子操作代码模板
→ 你审核通过 → 代码入库
```
### 4.3 录制界面的设计要点
```
┌──────────────────────────────────────────────┐
│ 录制回放: douyin_test - 2026-06-21 10:00 │
├──────────────────────────────────────────────┤
│ │
│ Step 1: grid → player_modal │
│ ┌────────┐ ┌──────────┐ ┌──────────┐ │
│ │ BEFORE │→│ ACTION │→│ AFTER │ │
│ │ 首页 │ │ 双击卡片 │ │ 播放页 │ │
│ │ card=20│ │ A.cover │ │ video=1 │ │
│ └────────┘ └──────────┘ └──────────┘ │
│ 操作名: [open_video___] ← 你填或系统建议 │
│ 备注: [双击feed卡片进入首个视频___] │
│ │
│ Step 2: 播放页 → 播放页(已点赞) │
│ ┌────────┐ ┌──────────┐ ┌──────────┐ │
│ │ BEFORE │→│ ACTION │→│ AFTER │ │
│ │ 播放页 │ │ 按z键 │ │ 心变红 │ │
│ └────────┘ └──────────┘ └──────────┘ │
│ 操作名: [like_________] ← 系统建议: like │
│ 备注: [键盘z点赞_______________] │
│ │
│ [合并步骤1+2?] [导出为蓝图] [生成代码] │
└──────────────────────────────────────────────┘
```
---
## 五、单步调试模式(工具层)
### 5.1 命令设计
```bash
# 模式1: 启动交互式调试(浏览器保持打开)
mc debug --accounts=douyin_test --platform=douyin
→ 浏览器打开,保持运行
→ 等待命令
# 模式2: 执行单步操作
mc step open_video # 只执行这一个操作,返回结果+消耗时间
mc step like # 继续下一步
mc step collect # 3秒内出结果
# 模式3: 批量单步(自动但不跳过)
mc step open_video like collect follow open_comments post_comment
→ 每步执行后停顿1秒,显示结果,继续下一步
```
### 5.2 交互流程
```
> mc debug --accounts=douyin_test
✅ 浏览器已启动,当前状态: grid (首页)
等待命令...
> open_video
✅ open_video → video_detail (5.2s) 状态: grid → player_modal
验证: video=1 ✅ 可继续下一步
> like
✅ like → 👍 (1.1s) 状态: player_modal
验证: 通过✅
> collect
❌ collect → - (0.0s) 状态: player_modal
元素未找到: [data-e2e="video-player-collect"]
回退: JS搜索也失败,坐标兜底也失败
建议: 你在浏览器里点一下收藏,我看看实际DOM是什么
```
---
## 六、看板集成(展示层)
### 6.1 新增三个页面
| 页面 | 路径 | 功能 |
|:-----|:-----|:------|
| 操作流程图 | `/ops-flow` | SVG流程图,实时显示测试状态 |
| 录制标注 | `/recorder` | 回放录制,标注原子操作,合并步骤 |
| 测试控制台 | `/debug` | 单步测试,查看日志,状态监控 |
### 6.2 操作流程图功能
- 展示所有平台的操作状态机
- 绿色 = 已测试通过
- 橙黄色 = 部分通过/有问题
- 灰色 = 未测试
- 点击任意节点 → 显示该操作的详细信息
- 点击连线 → 显示状态转换条件
- 底部显示当前正在测试的"路径"和进度
---
## 七、实施计划(分阶段)
### Phase 1: 基础设施(1-2天)
| 任务 | 说明 |
|:-----|:------|
| 1.1 实现 PageInspector | L1: 页面类型, L2: 鼠标区域, L3: 元素详情 |
| 1.2 增强 Recorder | 录制时捕获完整三层状态 |
| 1.3 实现 mc debug | 浏览器保持打开,接受后续命令 |
### Phase 2: 标注系统 + 流程图(1-2天)
| 任务 | 说明 |
|:-----|:------|
| 2.1 录制标注页面 | 看板新页面,回放+标注+合并步骤 |
| 2.2 操作流程图页面 | SVG流程图 + 实时状态 |
| 2.3 测试控制台页面 | 单步调试 + 日志查看 |
### Phase 3: 存量修复(1天)
| 任务 | 说明 |
|:-----|:------|
| 3.1 录一次抖音全流程 | 你录制 → 我分析 |
| 3.2 修复 collect + open_comments | 基于录制数据修复 |
| 3.3 录一次小红书全流程 | 你录制 → 我分析 |
| 3.4 修复小红书全部操作 | 基于录制数据修复 |
### Phase 4: 扩展(持续)
| 任务 | 说明 |
|:-----|:------|
| 4.1 新增平台 | 每个平台遵循同样流程:录制 → 标注 → 测试 |
| 4.2 蓝图组合 | 基于稳定的原子操作,组合成养号/评论等蓝图 |
| 4.3 定时任务 | 每日自动化执行 |
---
## 八、当前迭代聚焦
### 本周目标(2026-06-21 ~ 06-27)
```
Week 1: 抖音全流程打通 → 小红书全流程打通 → 看板可查看流程图
```
### 今天目标(2026-06-21)
1. **你先录一次抖音完整流程**(约10步),我在录制过程中捕获完整状态
2. **一起标注这些步骤**,给每个操作命名
3. **基于录制数据修复问题**(collect + open_comments)
4. **完成抖音流程图**,所有路径从灰色变绿色
---
## 九、你需要的(而不是我想要的)
这个计划的核心目标只有一个:**让你能高效地验证想法,而不是把时间花在猜代码上**。
每一步都是:
1. 你操作 → 我记录
2. 你标注 → 我理解
3. 你测试 → 我修复
4. 你确认 → 下一个
你不是在写代码。你是在教会我你的平台操作方式。
我是你的"手"和"眼",你是"大脑"和"决策者"。
@@ -0,0 +1,284 @@
"""
PageInspector — 三层页面状态检测
L1: 页面类型 (grid/player/search/profile) — URL pattern + DOM特征
L2: 鼠标所在区域 (feed/video/comment/bottom_bar) — 坐标区间判断
L3: 鼠标指向元素详情 — tag/class/text/position
基于 ghai 的人类视角判断逻辑:
1. 先看URL + 页面大结构 → 确定在什么页面
2. 再看鼠标周围区域 → 确定操作上下文
3. 最后看鼠标指向的具体元素 → 确定要操作什么
Usage:
inspector = PageInspector(page, platform="douyin")
state = await inspector.inspect()
print(state.page_type) # "player_modal"
print(state.has_video) # True
print(state.nearby_elements) # [element at cursor...]
"""
import asyncio
from dataclasses import dataclass, field
from typing import Optional
@dataclass
class PageState:
"""完整页面状态快照"""
platform: str = ""
url: str = ""
title: str = ""
# L1: 页面类型
page_type: str = "unknown" # grid/player_modal/player_full/search/profile/unknown
page_type_confidence: float = 0.0
# L1: DOM特征
video_count: int = 0
card_count: int = 0
has_search_bar: bool = False
has_nav: bool = False
has_comment_list: bool = False
is_self_page: bool = False # 是否自己的主页
author_id: str = ""
# L2: 鼠标区域
mouse_x: int = 0
mouse_y: int = 0
mouse_region: str = "unknown" # feed_area/video_area/bottom_bar/comment_area/nav_area
# L3: 附近元素
nearby_elements: list = field(default_factory=list) # [{tag, class, text, x, y, ...}]
element_at_point: Optional[dict] = None
# 验证
errors: list = field(default_factory=list)
warnings: list = field(default_factory=list)
def to_dict(self) -> dict:
return {k: v for k, v in self.__dict__.items()}
class PageInspector:
"""三层页面状态检测器"""
def __init__(self, page, platform: str = "douyin"):
self.page = page
self.platform = platform
async def inspect(self, mouse_x: int = 0, mouse_y: int = 0) -> PageState:
"""执行完整三层检测"""
state = PageState(platform=self.platform)
try:
# L1: 页面基本信息
state.url = self.page.url
state.title = await self.page.title()
# L1: DOM特征
dom = await self._capture_dom()
state.video_count = dom["video_count"]
state.card_count = dom["card_count"]
state.has_search_bar = dom["has_search_bar"]
state.has_nav = dom["has_nav"]
state.has_comment_list = dom["has_comment_list"]
state.author_id = dom["author_id"]
state.is_self_page = dom["is_self"]
# L1: 页面类型判定
state.page_type = self._classify_page_type(state)
# L2: 鼠标区域
if mouse_x > 0 and mouse_y > 0:
state.mouse_x = mouse_x
state.mouse_y = mouse_y
size = await self.page.evaluate(
"() => ({ w: window.innerWidth, h: window.innerHeight })"
)
state.mouse_region = self._classify_region(
mouse_x, mouse_y, size["w"], size["h"]
)
# L3: 鼠标处元素
if mouse_x > 0 and mouse_y > 0:
el_info = await self.page.evaluate(
f"""() => {{
const el = document.elementFromPoint({mouse_x}, {mouse_y});
if (!el) return null;
const rect = el.getBoundingClientRect();
return {{
tag: el.tagName,
class: el.className || '',
text: (el.textContent || '').trim().slice(0, 50),
x: Math.round(rect.left), y: Math.round(rect.top),
w: Math.round(rect.width), h: Math.round(rect.height),
visible: el.offsetParent !== null
}};
}}"""
)
state.element_at_point = el_info
# L3: 附近区域元素(鼠标周围200px内的可交互元素)
if mouse_x > 0 and mouse_y > 0:
nearby = await self.page.evaluate(
f"""() => {{
const mx = {mouse_x}, my = {mouse_y};
const els = document.querySelectorAll(
'a, button, span, div, input, textarea, svg')
const results = [];
for (const el of els) {{
if (!el.offsetParent) continue;
const r = el.getBoundingClientRect();
const cx = r.left + r.width/2;
const cy = r.top + r.height/2;
const dist = Math.sqrt((cx-mx)**2 + (cy-my)**2);
if (dist < 200) {{
results.push({{
tag: el.tagName,
class: (el.className || '').slice(0, 40),
text: (el.textContent || '').trim().slice(0, 30),
cx: Math.round(cx), cy: Math.round(cy), dist: Math.round(dist)
}});
}}
}}
return results.sort((a,b) => a.dist - b.dist).slice(0, 10);
}}"""
)
state.nearby_elements = nearby
except Exception as e:
state.errors.append(str(e))
return state
async def _capture_dom(self) -> dict:
"""捕获DOM特征"""
try:
return await self.page.evaluate("""() => {
const u = location.href;
const vc = document.querySelectorAll('video').length;
// cards: 视频卡片/笔记卡片
const cards = document.querySelectorAll(
'.discover-video-card-item, [class*="video-card"], ' +
'section.note-item, a[href*="/explore/"], [class*="note-item"]'
).length;
// 搜索栏
const searchBar = document.querySelector(
'[data-e2e="searchbar-input"], input[placeholder*="搜索"], textarea.textarea'
);
// 导航
const nav = document.querySelector(
'[data-e2e="douyin-navigation"], [class*="nav"], .ulxic5B4'
);
// 评论列表
const commentList = document.querySelector(
'[data-e2e="comment-list"], [class*="comment-list"]'
);
// 作者ID (从URL或个人信息区获取)
let authorId = '';
const userMatch = u.match(/\/user\/(\\d+)/);
if (userMatch) authorId = userMatch[1];
const exploreMatch = u.match(/\/explore\/(\\w+)/);
if (exploreMatch) authorId = exploreMatch[1];
// 是否自己的页面
const isSelf = u.includes('/user/self') ||
!!document.querySelector('[data-e2e="user-info"]');
return {
video_count: vc,
card_count: cards,
has_search_bar: !!searchBar,
has_nav: !!nav,
has_comment_list: !!commentList,
author_id: authorId,
is_self: isSelf
};
}""")
except:
return {"video_count":0, "card_count":0, "has_search_bar":False,
"has_nav":False, "has_comment_list":False, "author_id":"", "is_self":False}
def _classify_page_type(self, state: PageState) -> str:
"""L1: 页面类型判定"""
u = state.url.lower()
# 个人主页
if '/user/' in u:
return 'profile'
# 搜索页
if '/search' in u:
return 'search'
# 播放页: 有video
if state.video_count > 0:
if '/video/' in u and 'modal_id' not in u:
return 'player_full'
if 'modal_id' in u:
return 'player_modal'
return 'player'
# 笔记详情页 (小红书)
if '/explore/' in u and u.count('/') >= 4:
return 'note_detail'
# 首页/grid
if state.card_count > 0 or '/jingxuan' in u or '/explore' in u:
return 'grid'
return 'unknown'
def _classify_region(self, x: int, y: int, w: int, h: int) -> str:
"""L2: 鼠标区域判定(基于百分比位置)"""
x_pct = x / w
y_pct = y / h
# 视频播放区(中央上部区域)
if 0.2 < x_pct < 0.8 and 0.1 < y_pct < 0.5:
return 'video_area'
# 底部互动按钮区
if 0.2 < x_pct < 0.8 and y_pct > 0.8:
return 'bottom_bar'
# 评论区(底部大区域)
if y_pct > 0.7:
return 'comment_area'
# 左侧导航区
if x_pct < 0.2:
return 'nav_area'
# 右侧推荐区
if x_pct > 0.8:
return 'sidebar'
# 内容feed区(中下部)
if 0.2 < x_pct < 0.8 and 0.5 < y_pct < 0.8:
return 'feed_area'
return 'unknown'
async def demo(page):
"""快速演示"""
inspector = PageInspector(page, "douyin")
# 全量检测
state = await inspector.inspect()
print(f"[{state.page_type}] v={state.video_count} c={state.card_count}")
# 带鼠标位置的检测(模拟鼠标在右下角互动区)
state2 = await inspector.inspect(mouse_x=479, mouse_y=687)
print(f"鼠标区域: {state2.mouse_region}")
print(f"指向元素: {state2.element_at_point}")
print(f"附近元素: {len(state2.nearby_elements)}个")
for el in state2.nearby_elements[:3]:
print(f" {el['tag']} dist={el['dist']} {el['class'][:20]}")
return state2
@@ -0,0 +1,202 @@
# 2026-06-20 工作日誌
## 00:00-00:30 — 执行状态显示细腻度升级
### 背景
用户反馈 Dashboard 侧边栏的执行历史区块只显示"进程运行中"/"进程已结束"两种状态,但后端状态机有10种状态。
### 修改内容
- **后端** (`services/command_bus.py`): `CommandStatus` 枚举定义 10 种状态:queued / preflighting / preflight_failed / dispatching / running / completed / failed / timed_out / crashed / cancelled ✅ 已有
- **前端** (`frontend/src/modules/matrix_views.js`): 重写 `loadExecutionHistory()` 函数:
- 新增 `STATUS_MAP` 常量,每种状态映射到独立图标+颜色+中文标签+分组
- 顶部显示各状态的实际数量标签(不合并分组)
- 每台机器显示 ok/active/fail 细分(不再只看完成率)
- 每条执行记录显示:状态标签 | 机器 | 账号 | 消息 | 耗时 | 时间
- 格式化的耗时显示(s/m 自适应)
- Vite build 完成,hash 更新为 index-BhCDf8FF.js
- 无需重启服务(静态文件在磁盘上实时读取)
## 00:30-01:00 — 信息采集全链路断点分析(L1→L5)
### 背景
用户反馈信息采集页面点击「采集选中」后没有获取到内容。
### 分析结论
**断点在 L1(登录检测)**,不是数据回传问题:
- 所有 recent collect log 都显示 `ensure_login` 返回 `"unknown"` → 账号被跳过
- 实际 douyin_134 有 3 个 session cookie(有效登录态)但 DOM 锚点检测不到
- 旧版 `collect_batch_runner.py` 用不同检测逻辑能正确识别,新版 `LoginStateMachine._detect()` 只查 DOM 锚点失败
### L1 修复
1. **抖音 `logged_in` 锚点从 2 个扩展到 9 个**
2. **新增 Cookie 兜底检测** — DOM 检测失败后用 `page.context.cookies()` 检查 sessionid/token
3. **新增页面标题检测** — `"xxx的抖音"` = 已登录,`"记录美好生活"` = 未登录
4. **`_recover_cookie()` 改为导航到 `user/self`** — 不再只刷新首页,强制触发登录态
### L1→L5 测试验证
- L1: ✅ 登录检测通过(dl/fix-recover-cookie -> 进入蓝图执行)
- L2: ✅ 蓝图引擎启动,到达 check_verify_dialog 钩子
- L3: ✅ CommandBus dispatch → status:"accepted", PID=32964
- L4: ✅ API /api/ops/status 正常返回
- L5: ✅ 前端可通过 API 获取(等待下次 build)
- 次要问题:douyin_test 触发 SMS 验证弹窗导致执行卡住(已有钩子但 _recover_sms 阻塞)
### 文档更新
- `FEDERATION_GUIDE.md` 新增「十一、五层执行架构 (L1–L5)」完整文档
- 更新 4.4 登录状态机说明,记录 2026-06-20 修复细节
- 合并 4.4/4.5 多机账号管理部分(之前有格式错误)
## 09:00-16:30 — 登录状态机重构 + 全场景验证通过
### 背景
- 14:00 用户提供阿里百炼 API key,配置 vision_bridge.py 远程视觉支持(DashScope qwen-vl-plus)
- 15:00-16:20 反复调试抖音登录,逐个修复问题
### 修复清单
1. **检测器误判 logged_in** — 移除 `[data-e2e="user-avatar"]` 锚点(视频创作者头像也匹配)
2. **增加文本检测** — `body.innerText` 检查"未登录"和"粉丝/关注"关键词
3. **登录按钮被浮层拦截** — JS fallback `el.click()` 绕过 Playwright 可见性检查
4. **手机号为空** — 添加 `_ensure_phone()` 检查当前值,空则重填
5. **短信验证码取旧码** — 改为直接调用 ApiSMSHandler._fetch_messages() + 过滤 `id > min_id`
6. **登录按钮是"确认登录"不是"登录"** — 多文本匹配
### 验证结果(三种场景全通过)
- **全新登录**: detect→点登录→填手机→获取验证码→登录→douyin_read_profile 9步 ✅
- **短期过期**: detect→JS点登录→JS点一键登录→验证码→确认登录→douyin_read_profile 9步 ✅
- **已登录**: detect→logged_in→直接执行蓝图 ✅
### 代码清理
- `login_state_machine.py` 重构为三组件架构(PlatformDetector / RecoveryChain / LoginManager)
- `SmsRecovery` 限制仅小红书使用(抖音由 DouyinLoginRecovery 处理)
- `cdp_connector.py` close() 三层兜底修复 Camoufox stop() 缺失
- `mc/cli.py` setup_log() 加 logging.basicConfig 修复日志不输出
- 归档 2 个 export_* 蓝图到 _archive/
- `FEDERATION_GUIDE.md` 更新登录状态机章节 + 蓝图清单
## 16:30-18:10 — 小红书登录修复 + 全场景验证通过
### 修复清单
1. SmsRecovery 调用错版本 — 之前调 sms_login(抖音版),改为直接调 xhs_login(小红书6位框版)
2. XhsDetector cookie 误判 — 移除 cookie 直接返回 logged_in
3. xhs_login.is_logged_in() 太松 — 改为严格匹配 + 登录面板检测
4. 步骤顺序错误 — 「协议同意处理」移到点登录后
5. "同意并继续"按钮文字 — 改为「同意并继续」,class 为 div.foot-btn
6. 缺少 oauth-tip 切换 — 填手机号后需点 div.oauth-tip
7. SmsRecovery 二次验证过严 — 移除重复验证,信任 xhs_login
### 验证结果(18:08 全新登录 8/8 成功)
✅ 昵称=橙子哥 | ID=254437248 | 关注=1 | 粉丝=6
### 两种平台验证状态
| 场景 | 抖音 | 小红书 |
|:-----|:----:|:------:|
| 全新登录 | ✅ | ✅ |
| 短期过期 | ✅ | 🔵 |
| 已登录 | ✅ | ✅ |
## 18:10-18:45 — 养号蓝图 v2.0 更新
### 基础修
1. 冷却前缀匹配 — `_get_cooldown()` 去掉 `xhs_`/`dy_`/`dy_` 前缀
2. wait_watch 补到 xhs_ops — 使小红书养号蓝图可用
3. 搜索 @random 支持 — douyin_ops + xhs_ops 均支持随机关键词
### 4个养号蓝图更新
| 蓝图 | 版本 | 步数 | 变化 |
|:-----|:----:|:----:|:-----|
| douyin_daily | v2.0 | 40 | 10个视频,1-2条评论,概率点赞/收藏 |
| douyin_active_v1 | v2.0 | 80 | 2次@random搜索+各6结果,50%评论率 |
| xhs_daily | v2.0 | 49 | 10篇笔记,1-2条评论,参照抖音 |
| xhs_active_v1 | v2.0 | 89 | 2次搜索+各6结果+关注,参照抖音 |
## 19:10-20:40 — 养号蓝图 v2.x 修复
### 抖音日常 v2.1 (最终通)
- 根因: `open_video` 只单点不验证 + 蓝图未进详情页
- 修复: open_video 双击+验证+焦点+回首页兜底
- like/collect 改为键盘 z(非 DOM 点击)
- 结果: 45步 39成功 6失败 ✅
### 修复清单
1. douyin_ops._click_selector — 加 JS fallback(备用)
2. douyin_ops.like — 键盘 z 为主线
3. douyin_ops.open_video — 双击+验证+焦点+回首页
4. douyin_daily蓝图 — 每视频前加 open_video
5. xhs_ops — 补 wait_watch、go_back
6. xhs_ops.xhs_click_note — 回首页兜底、返回 False
7. engine._get_cooldown — 去前缀匹配
### 待测试
- xhs_daily 小红书日常(需用户配合验证码)
## 20:40-21:40 — 抖音版面整理 + 录制验证
### 录制成果(2轮,共48步操作)
- 第1轮: 弹窗模式完整操作(点赞z→评论x→收藏→关注g→下一页→首页→主页)
- 第2轮: 搜索"美食"→结果操作 + 全屏详情页/video/xxx操作
- 发现: 键盘快捷键(z/x/g/ArrowDown) 两种模式通用
- 收藏按钮是SVG图标,非 data-e2e 选择器
### 蓝图整理(9→6个活跃)
| 状态 | 蓝图 |
|:----:|:------|
| ✅ 保留 | douyin_daily / active / comment / reply / search / read_profile |
| 📦 归档 | comment_test / search_browse / collect(_archive/ 保留旧版做参考) |
| ↩️ 不删 | _archive/12个旧蓝图保留不动 |
## 23:50 — 今日复盘与明日任务清单
### 今日底线(已通过验证)
- douyin_read_profile: ✅
- xiaohongshu_read_profile: ✅
- 抖音登录(3场景): ✅
- 小红书登录(全新登录): ✅
- 抖音原子操作全测: 15/16 ✅(仅follow失败)
### 今日未解决的问题
#### 1. post_comment(抖音)— 代码返回成功但实际没发
- 根因: _do_execute 中 `ok = await self.post_comment()` 返回 `'ok'` 字符串,Python 视为 truthy,直接显示 sent
- 实际: 注释输入框 `.public-DraftEditor-content` 点击→打字→Enter,但评论未出现在列表
- 修复方向(已改未测): 加 send 按钮查找(发送/发布类名)+comment-list 文本验证,验证不通过返回 failed
- 旧代码参考: `archive/interactive_test.py` 的 step_send_comment 和 `matrix_modules/nurture/runner.py` 的 _send_comment
#### 2. follow(抖音)— 失败
- 当前实现: `page.keyboard.press("g")` + _click_selector 查找关注按钮
- 录制发现: 用户按 g 键关注/取消关注,键盘方法本身正确
- 可能原因: 视频详情页中已关注作者,g 键变成取消关注
#### 3. xhs_post_comment(小红书)— 完全没发出去
- 根因: `p.content-input` 选择器找不到(CSS modules 添加 hash)
- 录制数据: 正确路径是 → 笔记详情页滑到底部 → 找到 `DIV[class*="inner"]` 点击激活 → `P.content-input` 出现 → 填字 → `BUTTON.btn.submit` 发送
- 但 `p.content-input` 始终匹配不到,尝试了 x 键/JS激活/scrollTo 等5种方式均失败
- 明天方向: 用截图+视觉识别找输入框位置,或改用 Playwright getByPlaceholder
#### 4. xhs_click_note 在 go_back 后失败
- 笔记返回首页后 feed 未渲染完就找笔记,找不到
- 方向: go_back 后加 2-3秒延迟
### 明日任务清单(优先级排序)
```
P0: 修抖音 post_comment 验证(已改代码,明天测试验证)
P0: 修抖音 follow(查 g 键是否被已关注状态干扰)
P0: 修小红书 post_comment(截图视觉分析找输入框)
P1: 修 xhs_click_note 后 feed 刷新延迟
P1: 修 xhs_like 选择器稳定性
P1: 抖音高活跃蓝图 douyin_active 测试
P1: 新建小红书 xhs_comment_on_post / xhs_search 蓝图
P2: 小红书高活跃蓝图 xhs_active 测试
P2: 双平台日常养号自动化定时任务
```
### 关键教训(以后不要犯)
1. 录制数据要直接用(坐标/元素类名),不要加 is_visible() 等额外检查
2. 抖音和小红书的操作不能通用(x 键开评论在抖音通,小红书不通)
3. 代码返回 ✅ 不等于页面真的有反应,每种操作必须加验证
4. post_comment 必须检查 comment-list 中是否出现刚发的文字
5. 跑测试用"原子操作全测"蓝图(每个操作一次),不用养号蓝图(49步浪费时间)
6. CSS modules 类名不可靠,优先用 text/placeholder/坐标
7. 每次测试前先给路径让用户审查,确认再跑
补注: 2026-06-21 08:20 确认小红书 xhs_post_comment 测试通过 ✅
@@ -0,0 +1,48 @@
# 2026-06-21 工作日志
## 今日计划
基于昨日录制数据和旧稳定代码,修复两个平台剩余原子操作
## 08:00-08:20 — 双平台修复+测试
### 修复内容
1. 抖音 follow: KEYS['follow'] 从 'f' 改为 'g'(录制发现用户用g键) + 键盘g兜底 ✅
2. 抖音 post_comment: 加发送按钮查找+comment-list文本验证(参考旧版interactive_test.py) ✅
3. 抖音 open_video: 加feed加载等待 + 多选择器(discover-video-card/href/video/feed-card) ⚠️
4. 小红书 post_comment: 重写为JS找textarea/input/editable + 找发送按钮 ✅
### 测试结果
| 平台 | 步数 | 成功 | 失败 | 耗时 |
|:-----|:----:|:----:|:----:|:----:|
| 抖音 | 16 | 13 | 3 | 4.9min |
| 小红书 | 16 | 12 | 4 | 10.8min |
### 关键进展
- **小红书 post_comment 首次成功发送评论** ✅ "👍评论(测试评论) (5.0s)"
- 抖音 follow 键盘g生效 ✅
- 小红书 like/collect/search 全部正常 ✅
### 剩余问题
1. 抖音 open_video: 当前 douyin `/jingxuan` 页面没有 `.discover-video-card-item`,需录制查看实际DOM
2. 小红书搜索结果页: search后页面布局不同,click_note/like/collect/follow 均失败
3. xhs_like 在非笔记页(搜索页)取31s兜底
### 明日任务
P0: 抖音 open_video 录制→找出正确的选择器
P1: 小红书搜索结果页操作适配
P1: 双平台日常养号蓝图测试
## 09:00-10:05 — 架构反思 + 新方案设计 + 录制验证
### 关键突破
1. 发现collect用的键是C(不是无键),KEYS['follow']是g不是f
2. 拿到完整抖音快捷键表
3. 创建PageInspector(L1/L2/L3) + 四层状态模型
4. ghai录制18步(首次用状态diff思路)
5. 提出L4视觉状态层(按钮变色等)
6. 完整经验文档: EXPLAIN-atomic-ops-20260621.md
### 新核心文件
- page_inspector.py: 四层状态检测器
- PLAN-atomic-ops-v2.md: 完整项目规划
- EXPERIENCE-atomic-ops-20260621.md: 经验文档
@@ -0,0 +1,147 @@
# AgentOS 联邦系统 — 三台机器统一环境
## 机器对照表
| ORACLE 名 | Tailscale 名 | IP | SSH 用户 | Home 目录 |
|:----------|:-------------|:---|:---------|:----------|
| chengzigedeAir | macbook-air | 100.111.43.6 | chengzige | /Users/chengzige |
| 5kechengdeAir | 5macbook-air | 100.72.182.121 | 5kecheng | /Users/5kecheng |
| 7kecheng | 7macbook-air | 100.65.35.28 | 7kecheng | /Users/7kecheng |
## 统一后的 Python 环境
| 项目 | 三台机器一致 ✅ |
|:-----|:---------------|
| 养号用 venv | agent-os (旧名 matrix 已废弃) ✅ |
| Python 版本 | 3.13.12 ✅ |
| Python 签名 | adhoc(无 Team ID)✅ |
| orjson | 3.11.9 ✅ |
| camoufox | 0.4.11 ✅ |
| playwright | 1.58.0 ✅ |
| Git 版本 | 一致 ✅ |
| 蓝图文件 | 14 个(已同步)✅ |
## PYTHON 路径规范(重要)
所有涉及 PYTHON 路径的地方**必须使用 agent-os venv**,禁用了 matrix venv:
- `$HOME/.workbuddy/binaries/python/envs/agent-os/bin/python3`
- 旧路径 `envs/matrix/` 已全部替换
- 远程执行用 `$HOME/.workbuddy/binaries/python/envs/agent-os/bin/python3`
- remote_exec.py 使用 `$MC_PYTHON` 动态发现变量
## 登录系统关键发现
- 小红书登录弹窗: 无cookie自动弹出, DOM类名 `.login-container` / `.reds-modal-open`
- 手机号输入框: `input[placeholder="输入手机号"]`
- "继续"按钮: 手机号输入框右侧, 文字"继续", 无勾选协议
- 填手机号必须用 Playwright `page.fill()` 或 `page.type()` (+键盘事件), 不能用 JS set value (React不识别)
- 填完后按 Tab 键触发失焦, "继续"按钮才可点击
- 短信验证码: 通过 ApiSMSHandler 轮询 wx.tyhtak.com API
- 抖音登录已有完整 douyin_login.py (含sms_login原子操作)
## 小红书登录方案演进
### v1/v2 (已淘汰) — 鼠标点击协议复选框 ❌
- 找包含"同意"的最小高度可见元素 → `mouse.click(left - 20px, center_y)`
- 问题: 小红书复选框是自定义元素(非原生 `<input type="checkbox">`),left-20px 定位极不可靠
- 多次验证失败,元素位置随弹窗布局变化
### v3 (当前方案, 待验证) — 点"同意并登录"按钮 ✅
- 新发现: 点击「直接登录」按钮会弹出浮窗,浮窗上有「同意并登录」按钮
- 点击「同意并登录」= 协议勾选 + 登录意图一次性完成
- **不再需要**定位复选框或 left-20px hack
- 2026-06-16 晚发现该方案,尚未做 DOM 扫描验证
### 原子操作文件
- `matrix_modules/account/xhs_login.py` — 小红书原子操作(仿 sms_login.py 模式)
- 状态检测: `has_login_panel()`, `has_sms_inputs()`, `is_logged_in()`
- 操作函数: `fill_phone()`, `click_continue()`, `click_agree_and_login()`, `fill_6_digit_code()`, `click_largest_login_btn()`
- 主流程: `xhs_login(page, phone, account_name, log_func, use_v3)`
- `matrix_modules/account/xiaohongshu_login.py` — 顶层入口(调用 xhs_login 原子操作)
## 路径变量
- AGENT_SYNC=$HOME/workbuddy-agent-os/agent-sync
- AGENT_LOCAL=$HOME/workbuddy-agent-os/agent-local
## 远程管理
本机 (chengzigedeAir) 可通过 SSH 控制所有机器:
```bash
ssh [email protected] "命令"
ssh [email protected] "命令"
# 或通过 mc CLI
cd ~/workbuddy-agent-os/agent-sync/05_tools/07_matrix/scripts
python3 -m mc remote exec 5kechengdeAir "命令" --via ssh
```
## 版本锁定
依赖版本已锁定在 `agent-sync/requirements.txt`
新机器部署后执行: `pip install -r requirements.txt`
## 代码签名修复
新机器必须执行: `codesign -f -s - $HOME/.workbuddy/binaries/python/versions/3.13.12/bin/python3`
deploy.sh 已自动检测此步骤。
## 部署文档
- `DEPLOY-GUIDE.md` v2.0: 完整部署指南
- `deploy.sh`: 一键部署脚本
- `fleet_sync.sh`: 多机同步
- `fleet_reconcile.sh`: 对账引擎
## 架构关键概念(已修正 v2)
- **身份模型**: 一个手机号=一个身份目录。这个身份下可以存多个平台账号(xhs+douyin), 跨平台只需改 URL, 不用重开浏览器
- **窗口排布**: 本机最多3个浏览器同时运行, 每个窗口 X坐标+150 重叠排布(cdp_connector window_position参数)
- **蓝图定义**: 蓝图是你和我交互的"命名模板+参数", 不是内部执行步骤链。如 daily(时长), comment(url+text)
- **原子操作**: 最小执行单元, 自带状态检测。执行中触发验证弹窗 → 自动组合其他原子操作(如SMS登录)恢复
- **状态机核心**: 每次操作前必检登录态 → 执行 → 后检查是否触发验证 → 验证则自动恢复 → 冷却 → 下一步
## Vite 前端重构 (已完成)
- `static/index.html` 7700行 → Vite + Vanilla JS 模块化架构 ✅
- 已迁移到按视图拆分文件,Vite HMR 热更新 ✅
## 五层执行架构 (L1-L5) — 2026-06-20
所有 Dashboard 操作的执行链路:
```
L5 Dashboard UI → L4 API路由 → L3 CommandBus → L2 mc引擎 → L1 浏览器
```
### 各层核心文件
| 层 | 位置 |
|:---|:-----|
| L5 | `frontend/src/views/matrix-*.js` |
| L4 | `routes/ops.py`, `routes/matrix.py` |
| L3 | `services/command_bus.py` |
| L2 | `scripts/mc/engine.py`, `scripts/mc/run.py` |
| L1 | `scripts/douyin_ops.py`, `scripts/xhs_ops.py` |
### 登录检测 (2026-06-20 重构 v2.0)
- **架构**: PlatformDetector(策略模式) + RecoveryChain(可配置) + LoginStateMachine(编排器)
- **检测**: DouyinDetector 四重检测 — DOM锚点 → 页面文本("未登录"/"粉丝+关注") → 标题 → Cookie(仅日志)
- **恢复链**: DouyinLoginRecovery(抖音专用) → CookieRecovery → SmsRecovery(小红书) → VisualRecovery
- **三种场景全通过**: 已登录 ✅ / 短期过期(一键+SMS) ✅ / 全新登录(手机+SMS) ✅
- **关键**: 登录按钮文字在短期过期时为"确认登录",全新登录时为"登录"
- **参考**: `FEDERATION_GUIDE.md` 4.4 节 + 第十一章完整文档
## 原子操作体系 v2(2026-06-21 建立)
### 核心文档
| 文档 | 路径 | 内容 |
|:-----|:-----|:-----|
| 经验文档 | `.workbuddy/memory/EXPERIENCE-atomic-ops-20260621.md` | 完整时间线、设计原则、选择器优劣、快捷键表、代码状态 |
| 项目规划 | `.workbuddy/memory/PLAN-atomic-ops-v2.md` | 三层架构设计、增强录制、单步调试、看板集成 |
| 架构审计 | `.workbuddy/memory/ARCHITECTURE_AUDIT.md` | 新旧代码对比、根本问题分析、重构方案 |
### 关键技术突破
1. **状态检测模型**: L1页面类型 + L2鼠标区域 + L3元素详情 + L4视觉状态
2. **键盘快捷键优先**: Z赞/C收藏/G关注/X评论/B弹幕/V分享 — DOM只是兜底
3. **录制增强**: 只按一次·标记状态diff, 系统自动推断操作类型
4. **单步调试**: 3秒出结果, 不等完整蓝图
### 各平台操作清单
| 抖音 | 方法 | 小红书 | 方法 |
|:-----|:-----|:------|:-----|
| like | 键盘Z | xhs_like | DOM点击SPAN.like-lottie |
| collect | 键盘C | xhs_collect | DOM点击SVG(like右边70px) |
| follow | 键盘G | xhs_follow | DOM点击SPAN.reds-button |
| open_comments | 键盘X | xhs_comment | 需打开评论区(不能用X) |
| post_comment | X→点输入框→打字→点发送 | xhs_post_comment | JS找输入框+按钮 |
| close_comments | 键盘X | — | go_back() |
| next_video | 键盘↓ | xhs_scroll_feed | 键盘↓ |
| open_video | 双击卡片(键盘→DOM→坐标三层兜底) | xhs_click_note | 点笔记封面 |
@@ -0,0 +1,27 @@
# 99_system/ — AgentOS 系统知识索引
本目录包含 AgentOS 联邦系统全部架构/设计/协议/模块文档。
> 📅 最后整理: 2026-06-18 | 去重删除 ~130 个重复文件
## 子目录索引
| 子目录 | 文件数 | 说明 |
|:-------|:------|:-----|
| `architecture/` | 6 | 联邦架构、登录系统、触发分析 |
| `matrix/` | 14 | 矩阵养号系统(原 04_ops/ + 系统文档迁移) |
| `references/` | 2 | 系统引用文档(CloakBrowser, Peekaboo) |
| `dashboard/` | 1 | Dashboard 设计 |
| `pipelines/` | 1 | 自动化流程 |
| `prompts/` | 1 | 智能体提示词 |
| `protocols/` | 4 | 协议规范 |
| `taxonomies/` | 2 | 分类法 |
| `templates/` | 4 | 知识卡片模板 |
| `archive/` | 3 | 已归档旧文档 |
| `timelines/` | 0 | 时间线(待填充) |
## 根目录文件
- `agent-os-memory-knowledge-architecture.md` — 记忆&知识库架构设计
- `memory-index.md` — 记忆系统索引
- `2026-06-01_2026-05-17_2026-05-16_统一升级引擎_agentos_upgrade.md` — 统一升级引擎
@@ -0,0 +1,336 @@
# AgentOS 联邦系统 — 全量改造路线图
> **依据**: `ARCHITECTURE_CONSTITUTION.md` (架构宪法 v1.0)
> **集成**: `ARCHITECTURE_v3.md` + `VITE_MIGRATION_PLAN.md` + `EXECUTION_PIPELINE.md` + 审计报告
> **目标**: 一套标准、一个框架、三机统一、联邦自治
> **创建**: 2026-06-18 | **状态**: ✅ 已定义,待执行
---
## 一、最终目标状态
当所有阶段完成时,系统呈现以下面貌:
```
用户操作方式(三选一):
agentos matrix run --accounts douyin_01 --blueprints douyin_daily ← CLI
agentos fleet sync ← CLI
agentos ave render ... ← CLI
Dashboard (localhost:9988) ← Web
智能体 (AI 自动调度) ← AI
后端架构:
agentos/plugins/matrix.py → command_bus.py → 执行体
agentos/plugins/ave.py → (直接调用) → 视频处理
agentos/plugins/crawl.py → (直接调用) → 抓取引擎
agentos/plugins/fleet.py → SSH/HTTP → 远程机器
agentos/plugins/serve.py → 本地服务 → MCP/调度
数据层:
matrix_mgmt.py (账号唯一入口)
local_paths.py (路径唯一入口)
auth_manager.py (登录检测唯一入口)
cdp_connector.py (浏览器唯一入口)
已退役:
mc CLI → 全部能力迁移到 agentos
matrix.py → 入口退役
camoufox_manager.py → 归档
browser_manager.py → 归档
switch_account.py → 归档
c2/command_bus.py → 归档
c2/profile_scraper.py → 归档
remote_exec.py → 被 command_bus 替代
operation_queue.py → 被 command_bus 替代
resource_lock.py → 被 browser_orchestrator 替代
nurture_daily.py → 被 orchestrator 替代
static/index.html (7700行) → 被 Vite 构建产物替代
```
---
## 二、阶段总览
```
Phase 0: agentos 框架补全 ← 短期(本周)
├── Step 0.1: agentos matrix 插件补齐
├── Step 0.2: agentos fleet/serve 插件补齐
└── Step 0.3: agentos 作为 mc 的壳(调用转发)
Phase 1: 清理 + 标准化 ← 短期(并行)
├── Step 1.1: 废弃文件归档(5个文件)
├── Step 1.2: service 层合并(remote_exec/operation_queue/resource_lock)
├── Step 1.3: local_paths.py 路径统一
└── Step 1.4: 抖音采集加入登录检测
Phase 2: Dashboard 前端重构 ← 中期(2-3天)
├── Step 2.1: Vite HMR 开发模式稳定
├── Step 2.2: 迁移视图对接新 API
├── Step 2.3: 构建产物部署
└── Step 2.4: 旧 index.html 退役
Phase 3: agentos → 全线贯通 ← 中期
├── Step 3.1: mc 全部命令迁移到 agentos
├── Step 3.2: mc CLI 退役
└── Step 3.3: 三机统一部署验证
Phase 4: 联邦自治 ← 长期
├── Step 4.1: 智能体自动调度
├── Step 4.2: 故障自愈
└── Step 4.3: 全链路监控
```
---
## 三、详细执行计划
---
### Phase 0: agentos 框架补全(最高优先级)
#### Step 0.1: agentos matrix 插件补齐
**现状**: `agentos/plugins/matrix.py` 只有 77 行,只有基本框架,没实现具体命令。
**目标**: `agentos matrix run|collect|login|logout|comment|like|blueprint|corpus` 能正常调用底层。
| 子任务 | 文件 | 预计 | 前置 |
|:-------|:-----|:----|:------|
| 0.1a 实现 `agentos matrix run` → 调用 `mc run` | `plugins/matrix.py` + `cli.py` | 1h | — |
| 0.1b 实现 `agentos matrix collect` → 调用 `collect_batch_runner.py` | 同上 | 1h | — |
| 0.1c 实现 `agentos matrix login/logout` → 调用 login 模块 | 同上 | 1h | — |
| 0.1d 实现 `agentos matrix comment/like` → 调用 mc task | 同上 | 1h | — |
| 0.1e 实现 `agentos matrix blueprint/corpus` → 调用 matrix_mgmt | 同上 | 0.5h | — |
**验收**: `agentos matrix run --accounts douyin_test --blueprints douyin_daily --rounds 1` 成功执行
#### Step 0.2: agentos fleet/serve 插件补齐
| 子任务 | 文件 | 预计 |
|:-------|:-----|:-----|
| 0.2a `agentos fleet sync/reconcile/exec` → 调用 fleet_sync.sh/fleet_reconcile.sh | `plugins/fleet.py` | 0.5h |
| 0.2b `agentos serve mcp/dashboard/schedule` → 调用对应服务 | `plugins/serve.py` | 0.5h |
| 0.2c `agentos serve proxy/sms` → 接入代理/短信管理 | `plugins/serve.py` | 1h |
#### Step 0.3: agentos 作为 mc 的壳
**策略**: 在 mc CLI 执行时,**优先检查 agentos 是否有对应实现**。如果有,直接转发到 agentos。
```
mc run --accounts=X --blueprints=Y
→ 检查 agentos 是否可用
→ 是: subprocess.run(["agentos", "matrix", "run", ...])
→ 否: 走旧逻辑(向后兼容)
```
这样做的意义:
- 用户无感知迁移(mc 命令照常敲,背后用的是 agentos)
- 一旦 agentos 稳定了,mc 只需改一个转发开关
- 不用一次性重写所有 mc 命令
| 子任务 | 预计 |
|:-------|:-----|
| 0.3a mc/cli.py 入口加 agentos 转发检测 | 1h |
| 0.3b 逐个命令切换转发(从最简单开始:status/blueprint/corpus) | 2h |
---
### Phase 1: 清理 + 标准化(与 Phase 0 并行)
#### Step 1.1: 废弃文件归档
| 文件 | 移到 | 替代方案 | 预计 |
|:-----|:-----|:---------|:-----|
| `camoufox_manager.py` | `archive/camoufox_manager.py` | `cdp_connector.py` | 5min |
| `browser_manager.py` | `archive/browser_manager.py` | `cdp_connector.py` | 5min |
| `switch_account.py` | `archive/switch_account.py` | 无(已废弃) | 5min |
| `c2/command_bus.py` | `archive/c2_command_bus.py` | `services/command_bus.py` | 5min |
| `c2/profile_scraper.py` | `archive/c2_profile_scraper.py` | Dashboard API | 5min |
| 检查所有 import 引用 → 更新或移除 | — | — | 30min |
⚠️ **必须先检查引用关系再移**,防止 import 断裂。
#### Step 1.2: service 层合并
| 待合并 | 合并到 | 说明 | 预计 |
|:-------|:-------|:-----|:------|
| `remote_exec.py` | `command_bus.py._send_remote()` | command_bus 已实现远程发送 | 1h |
| `operation_queue.py` | `command_bus.py` (内置队列) | command_bus.MachineSession 已有队列 | 1h |
| `resource_lock.py` | `browser_orchestrator.py` | 并发限制由 browser_orch 做 | 1h |
**步骤**:
1. 检查每个函数的调用方(用 grep 找 import/reference)
2. 把调用方改成新路径
3. 旧文件标记 deprecated 头注释
4. 确认无引用后归档
#### Step 1.3: local_paths.py 路径统一
**审计所有硬编码路径**(已知有 ~10 处):
| 文件 | 硬编码路径 | 改为 |
|:-----|:----------|:-----|
| `collect_homepage_info.py:23-27` | `Path.home() / "workbuddy-agent-os"` | `local_paths.data_path()` |
| `collect_batch_runner.py:27-32` | 同上 | 同上 |
| `xiaohongshu_login.py:34-35` | 同上 | 同上 |
| `camoufox_manager.py` | 同上 | 同上(若归档则跳过) |
| 其他... | 扫描所有 .py 文件 | 逐个修改 |
#### Step 1.4: 抖音采集加入登录检测
对标刚修复的小红书方案:
```python
# extract_douyin() 中,在导航到首页/个人页后
if not logged_in:
from sms_login import sms_login # 抖音 SMS 登录
login_ok = await sms_login(page, phone=phone, ...)
if login_ok: reload + retry
```
| 子任务 | 预计 |
|:-------|:-----|
| 1.4a 检查 `sms_login.py` 是否有独立的 login 函数(类似 xhs_login) | 15min |
| 1.4b 在 `extract_douyin()` 中加入登录检测 → 自动登录 | 1h |
| 1.4c 端到端测试 | 30min |
---
### Phase 2: Dashboard 前端重构
#### Step 2.1: Vite HMR 开发模式稳定
**现状**: frontend/ 已有 Vite 项目,33 个视图已迁移为 ES Module。但 Dashboard 直接服务 `static/index.html`(内联代码),Vite 前端尚未接入。
**需要解决的问题**:
| 问题 | 当前状态 | 修复方案 |
|:-----|:---------|:---------|
| Dashboard 使用 `static/index.html`(内联 7700 行) | 正常运行但无法 HMR | 保持现状,Vite 构建产物覆盖 static/ |
| Vite 前端 (`frontend/`) 的视图是迁移版但功能可能不全 | 33 个 .js 文件 | 逐个验证功能 |
| ExecutionPipeline 在 Vite 版中需要从 ES Module 加载 | 已内联到 index.html | 迁移到 `components/execution-pipeline.js` |
**正确的接入方式**:
1. 开发时: `cd frontend && npm run dev` → `localhost:5173/static/` → 有 HMR
2. 部署时: `cd frontend && npm run build` → 输出到 `../static/` → Dashboard 直接服务
#### Step 2.2: 迁移视图对接新 API
确保所有视图的按钮使用 `ExecutionPipeline.run()` + `POST /api/ops/run`:
| 视图 | 当前 API | 目标 API | 预计 |
|:-----|:---------|:---------|:-----|
| 养号执行 | `/api/ops/run` | ✅ 已对接 | — |
| 信息采集 | `/api/ops/run` | ✅ 已对接 | — |
| 登录管理 | `/api/ops/run` | ✅ 已对接 | — |
| 定向评论 | `/api/ops/run` | ✅ 已对接 | — |
| 收藏点赞 | `/api/ops/run` | ✅ 已对接 | — |
| 联邦指挥台 | `/api/ops/run` | ✅ 已对接 | — |
#### Step 2.3: 构建产物部署
```bash
cd frontend
npm run build # → 输出到 ../static/
# 验证 Dashboard localhost:9988 正常服务
# 三机同步: fleet_sync.sh
```
#### Step 2.4: 旧 index.html 退役
当 Vite 构建产物稳定后:
1. 重命名 `static/index.html` → `static/index_legacy.html`(备份)
2. Vite 构建的 `static/index.html` 成为主文件
3. 保留回滚能力(`index_legacy.html` 可恢复)
---
### Phase 3: agentos → 全线贯通
#### Step 3.1: mc 全部命令迁移到 agentos
| mc 命令 | → agentos | 迁移状态 |
|:--------|:----------|:---------|
| `mc run` | `agentos matrix run` | ⬜ 待迁移 |
| `mc collect` | `agentos matrix collect` | ⬜ 待迁移 |
| `mc account` | `agentos matrix account` | ⬜ 待迁移 |
| `mc smart-login` | `agentos matrix login` | ⬜ 待迁移 |
| `mc account logout` | `agentos matrix logout` | ⬜ 待迁移 |
| `mc task comment` | `agentos matrix comment` | ⬜ 待迁移 |
| `mc task like` | `agentos matrix like` | ⬜ 待迁移 |
| `mc blueprint` | `agentos matrix blueprint` | ⬜ 待迁移 |
| `mc corpus` | `agentos matrix corpus` | ⬜ 待迁移 |
| `mc status` | `agentos fleet status` | ⬜ 待迁移 |
| `mc remote` | `agentos fleet exec` | ⬜ 待迁移 |
| `mc schedule` | `agentos serve schedule` | ⬜ 待迁移 |
| `mc proxy` | `agentos serve proxy` | ⬜ 待迁移 |
| `mc sms` | `agentos serve sms` | ⬜ 待迁移 |
| `mc record` | `agentos matrix record` | ⬜ 待迁移 |
#### Step 3.2: mc CLI 退役
- mc 入口输出: `⚠️ mc 已退役,请使用: agentos <domain> <command>`
- 保留 mc 脚本指向 agentos 的软链接(可选)
#### Step 3.3: 三机统一部署验证
| 检查项 | 验证方式 |
|:-------|:---------|
| 三机 agentos 版本一致 | `fleet_sync.sh` 同步后检查 |
| 三机 Python 环境一致 | `fleet_reconcile.sh` |
| 三机 Dashboard 正常启动 | 访问各机 :9988 |
| 远程执行链路正常 | 从本机发起到 5kecheng/7kecheng 的 collect 和 nurture |
---
### Phase 4: 联邦自治(长远目标)
| 步骤 | 说明 | 预计 |
|:-----|:------|:------|
| 4.1 智能体自动调度 | agentos 接收 AI 指令自动执行 | 未来 |
| 4.2 故障自愈 | guardd 检测到进程异常自动重启 | 未来 |
| 4.3 全链路监控 | 所有操作的状态/耗时/成功率可视化 | 未来 |
---
## 四、各阶段工作量预估
| Phase | 步骤数 | 预计工时 | 说明 |
|:------|:------|:---------|:------|
| **Phase 0** agentos 补全 | ~8 步 | **~8h** | 最高优先级,先做 |
| **Phase 1** 清理标准化 | ~6 步 | **~4h** | 与 Phase 0 并行 |
| **Phase 2** 前端重构 | ~4 步 | **~4h** | 可以后做,现有内联版能用 |
| **Phase 3** agentos 贯通 | ~3 步 | **~6h** | 依赖 Phase 0 完成 |
| **Phase 4** 联邦自治 | ~3 步 | 远期 | 前期不做 |
| | **总计** | **~22h** | |
---
## 五、风险和注意事项
| 风险 | 概率 | 影响 | 缓解措施 |
|:-----|:----|:------|:---------|
| agentos 开发中导致 mc 不稳定 | 低 | 高 | Step 0.3 的转发机制可降级回 mc |
| 归档文件被其他模块 import | 中 | 中 | 归档前 grep 全库检查引用 |
| Vite 构建产物破坏 Dashboard | 低 | 高 | 保留 index_legacy.html 回滚 |
| 远程机器同步延迟 | 中 | 低 | fleet_sync.sh 可手动触发 |
---
## 六、验收标准(全部完成时)
- [ ] `agentos matrix run|collect|login|logout|comment|like|blueprint|corpus` 全部可用
- [ ] `agentos fleet sync|reconcile|exec` 全部可用
- [ ] `agentos serve mcp|dashboard|schedule|proxy|sms` 全部可用
- [ ] `mc <any>` 全部指向 `agentos`(或直接提示退役)
- [ ] 废弃的 6 个文件全部归档,无引用断裂
- [ ] service 层无重复功能(remote_exec/operation_queue/resource_lock 归档)
- [ ] 所有硬编码路径改为 `local_paths.py`
- [ ] 抖音采集也有登录检测(对标小红书)
- [ ] Dashboard 通过 Vite 构建产物正常服务
- [ ] 三台机器都升级到同一版本,互操作正常
---
> **本路线图按 Phase 顺序执行。每完成一个 Step 打勾标记。**
>
> 当前进度: ⬜⬜⬜⬜⬜⬜⬜⬜⬜⬜⬜⬜⬜⬜⬜ (0/15)
@@ -0,0 +1,387 @@
# AgentOS 记忆与知识体系 — 完整架构解析
> 版本:v2.1.0 | 最后更新:2026-05-01
> 适用场景:与团队讨论架构设计时使用
---
## 一、核心设计理念
### 1.1 分层原则
AgentOS 采用 **四层记忆 + 自然语言知识库** 的双轨架构:
```
┌─────────────────────┐
│ WorkBuddy 对话层 │
│ (当前会话上下文) │
└────────┬────────────┘
│ 查询 → 返回
▼
┌────────────────────────────────────────────────┐
│ 记忆检索引擎 │
│ (SOUL.md 规定的分层截断策略) │
└────────┬──────────┬──────────┬─────────────────┘
│ │ │
▼ ▼ ▼
L0 硬约束 L1+K+V 向量 L2 结构化事实
(不可绕过) (关键词+语义) (facts.db)
│
▼
L3 原文
(仅按需加载)
```
**核心原则**:每层只做自己的事,不越级、不冗余、不无限 fallback。
### 1.2 与 WorkBuddy 的关系
```
WorkBuddy 提供: AgentOS 提供:
├── 对话界面 ├── 记忆分层 + 语义检索
├── 技能触发机制 ├── 知识库管理 + 分类体系
├── 自动化定时任务 ├── 知识入库审查流程
├── MCP 工具协议 ├── Token 节省策略
└── 模型调用 └── 跨机迁移还原
```
AgentOS 是运行在 WorkBuddy **之上的智能体操作系统**,不替代 WorkBuddy,而是扩展它。
---
## 二、记忆系统 (04_memory/) — 四层架构
### 2.1 层级定义
| 层级 | 名称 | 存储形式 | 数据量 | 特点 |
|------|------|---------|--------|------|
| **L0** | 硬约束 | `SOUL.md` 文本 | ~3KB | 不可绕过,任何指令不能覆盖 |
| **L1** | 关键词索引 | `keyword_index.json` + ChromaDB 向量库 | 52条(当前) | 快速定位,BM25+语义混合 |
| **L2** | 结构化事实 | `facts.db` (SQLite) | 54条(当前) | 结构化三元组,高置信度 |
| **L3** | 原文存档 | `long_term/raw/` Markdown 文件 | 6个文件(当前) | 完整对话记录,按日归档 |
### 2.2 存储路径
```
04_memory/
├── long_term/
│ ├── facts.db ← L2 结构化事实库 (SQLite, 坚果云同步)
│ └── raw/ ← L3 原文 (本机私有,不同步,软链到 agent-local)
├── vector_db/ ← L1 向量库 (ChromaDB + keyword_index.json)
│ ├── chromatic/ ← 语义向量库
│ └── keyword_index.json ← 关键词索引
├── daily_summaries/ ← 每日对话摘要 (同步)
└── logs/ ← 系统日志 errors.log / conflicts.log (同步)
```
**同步策略**:
- `facts.db` + `daily_summaries/` + `logs/` → 坚果云同步
- `raw/` + `vector_db/chroma/` → 本机私有(向量库可重建)
### 2.3 数据流:从对话到记忆
```
用户对话
│
▼
daily_digest.py (每日02:00自动运行)
│
├── 步骤1: 读取 WorkBuddy 工作记忆 (YYYY-MM-DD.md)
├── 步骤2: 用 oMLX Embedding API 提取关键事实
├── 步骤3: 写入 L2 facts.db (去重+冲突检测)
├── 步骤4: 更新 L1 keyword_index.json
├── 步骤5: 归档 L3 原文到 long_term/raw/
└── 步骤6: 生成每日摘要到 daily_summaries/
```
### 2.4 检索流程 (核心)
```
用户提问
↓
L0 硬约束过滤(安全检查:能执行吗?边界在哪?)
↓ 通过
L1 关键词索引匹配(BM25 + 语义向量混合检索)
├─ 无匹配 → 直接视为"无历史记录",跳过记忆检索,直接回答
└─ 有匹配 → 进入 L2
↓
L2 结构化事实匹配 (SQLite 查询 subject/predicate/object)
├─ 置信度 ≥ 阈值(0.7) → 返回摘要,作为上下文注入
└─ 置信度 < 阈值 → 终止,返回"无相关历史记忆"
↓
【不 fallback 到 L3】
仅当用户明确要求"调出原文"时
```
**关键规则**:
1. L1 无匹配 → 直接视为无历史,不翻记忆 —— **节省 token**
2. L2 置信度不足 → 截断,不 fallback —— **节省 token**
3. L3 仅用户明确请求时才按行号片段加载 —— **节省 token**
4. 冲突检测优先级:新事实 > 旧事实,用户明确修正 > 系统推断
### 2.5 Token 节省策略
| 策略 | 实现 | 节省效果 |
|------|------|---------|
| 分层截断 | L1 无匹配立即停止,不进 L2 | 避免整库扫描 |
| 置信度阈值 | L2 置信度 < 0.7 不返回 | 避免低质量事实占用 context |
| L3 延迟加载 | 只有用户明确要求才加载原文 | 最大节省(原文通常很大) |
| 按需加载 | 知识库检索只加载行号/片段,不加载整个文件 | 避免全文件读取 |
| 回复裁剪 | 回答长度与问题复杂度成正比 | 简单问题简短回答 |
---
## 三、知识系统 (03_knowledge/) — 自然语言知识库
### 3.1 分类体系
```
03_knowledge/
├── 00_inbox/ 入口(旧版,兼容保留)
├── 00_stream/inbox/ 新版五分区收件箱(当前主入口)
│ ├── knowledge/clipping/ 浏览器剪藏
│ ├── knowledge/feed/ 自动采集内容
│ ├── memory/ 记忆固化卡片
│ ├── tools/ 工具提交
│ └── personal/ 个人笔记
├── 01_daily/ 日记与日志
├── 10_concepts/ 概念知识(核心!按领域分)
│ ├── cs/ 计算机科学
│ ├── ai/ 人工智能
│ ├── finance/ 金融
│ ├── law/ 法律
│ ├── medicine/ 医学
│ ├── physics/ 物理
│ ├── math/ 数学
│ ├── business/ 商业
│ └── personal-insight/ 个人洞见
├── 20_methods/ 方法论、流程、SOP
├── 30_facts/ 事实、数据
├── 40_references/ 参考资料
├── 50_resources/ 资源与链接
├── 60_opinions/ 观点与评论
├── 90_archive/ 归档
└── 99_system/ 系统配置(模板、分类法、提示词)
```
### 3.2 知识流全链路
```
[外部来源] → [采集] → [提纯] → [分类] → [入库] → [索引]
│
├── 网页剪藏 → 00_stream/inbox/knowledge/clipping/
├── RSS采集 → 00_stream/inbox/knowledge/feed/
├── 对话记忆 → 00_stream/inbox/memory/
└── 手动输入 → 00_stream/inbox/personal/
│
▼ inbox_refine.py(AI 分类)
│
▼
03_knowledge/{10_concepts, 20_methods, ...}/
│
▼ vector_db_rebuild.py(重建向量索引)
│
▼
ChromaDB 向量库(语义检索用)
```
### 3.3 入库审查流程
每一条新知识入库前,必须经过:
```
1. 来源可靠性评分
├── 官方文档/学术论文 → +0.3
├── 知名技术博客 → +0.1
├── 个人博客/论坛 → -0.1
└── 未知来源/社交媒体 → -0.3
基础可靠性基线: 0.5
2. 一致性检查
├── 与已有 L2 事实对比
├── 完全一致 → 旧知识 confidence 轻微提升
├── 补充细节 → 合并为新条目
└── 矛盾 → 进入冲突消解流程
3. 时效性标记
├── 技术类知识 → 180天自动失效
├── 法律/法规 → 按原文有效期
├── 个人偏好 → 不过期,标记为 opinion
└── 公理类 → 永久有效
4. 自学习日志记录
每次入库写入 logs/kb_ingest.log
```
### 3.4 知识版本管理
| 变化类型 | 例子 | 处理方式 |
|---------|------|---------|
| 硬事实改变 | 4C8G → 8C16G | 更新原卡片,旧值写入 previous_version |
| 软升级 | v1 → v2,v1 仍有参考价值 | 保留 v1,新建 v2,related 链接 |
| 观点→事实 | 推测变可靠 | nature 改为 fact,confidence 提升 |
每个知识卡片维护 version / previous_version / superseded_by 字段。
---
## 四、语义检索系统
### 4.1 双轨检索架构
```
用户查询
│
├── 轨道1: BM25 关键词检索 (keyword_index.json)
│ ├── 分词 → 匹配关键词 → 排序
│ └── 优点: 精确匹配,无偏差
│
├── 轨道2: 语义向量检索 (ChromaDB)
│ ├── oMLX Qwen3-Embedding-0.6B 编码 → 1024维向量
│ └── 优点: 语义理解,同义词匹配
│
└── RRF 融合排序
├── BM25 结果 + 向量结果 → 加权融合
└── 最终返回 Top-K
```
### 4.2 向量库配置
```python
# 模型: Qwen3-Embedding-0.6B (1.19GB)
# 维度: 1024
# 引擎: oMLX v0.3.6 (Apple MLX 框架)
# API: localhost:8000/v1/embeddings
# 存储: ChromaDB (SQLite 后端)
```
### 4.3 双轨存储
```
agent-local/vector_db/
├── local/
│ ├── chroma/ ← 本机私有内容向量库
│ └── keyword_index.json
├── global/
│ ├── chroma/ ← 协同知识库向量索引
│ └── keyword_index.json
```
`local` 存私有记忆,`global` 存共享知识。每台机器独立重建。
---
## 五、与 WorkBuddy 的集成方式
### 5.1 MCP 协议 (Model Context Protocol)
```
WorkBuddy ←→ MCP Server ←→ AgentOS 资源
│
├── filesystem server → 访问 agent-sync/
└── memory server → 访问 facts.db
```
MCP 服务器通过 `01_core/mcp.json` 配置,使用 WorkBuddy 管理的 Node.js 版本。
### 5.2 技能触发 (SKILL.md)
AgentOS 的 9 个技能通过 SKILL.md 注册到 WorkBuddy,通过对话触发词调用:
| 技能 | 触发词 | 功能 |
|------|--------|------|
| memory_manager | `记忆更新`、`查记忆` | 每日记忆提炼、语义检索 |
| kb_manager | `入库`、`知识搜索` | 知识入库、双轨向量检索 |
| inbox_refine | `提纯`、`收件箱提纯` | 收件箱分类归档 |
| collect_to_inbox | `归集`、`收集入库` | 本地素材推送到收件箱 |
| sync_manager | `备份知识库`、`同步状态` | 知识库备份/导出 |
| auto_collector | `开始收集`、`收集报告` | RSS/网页定时采集 |
| content_processor | `转笔记`、`剪藏` | 多模态内容处理路由 |
| web_crawler | `抓取`、`爬取` | 网页抓取与反爬 |
| matrix | `养号`、`执行蓝图` | 多平台社交账号养号 |
### 5.3 自动化任务 (WorkBuddy 定时)
```
每日 02:00 → 每日记忆提炼 (daily_digest.py)
每日 02:30 → 收件箱汇聚 (collect_to_inbox.py)
每日 03:00 → 收件箱提纯 (inbox_refine.py)
```
三个自动化任务通过 WorkBuddy 的 automation 系统配置,prompt 中包含完整的 Python 命令路径。
### 5.4 身份注入
每次对话开始时,AgentOS 读取三个身份文件注入到 WorkBuddy 上下文:
```
SOUL.md → L0 硬约束 + L1 行为准则 (最高优先级)
IDENTITY.md → 系统身份 (Claw) + 设备信息
USER.md → 用户偏好 + 工作背景
```
---
## 六、跨机同步架构
### 6.1 双根目录方案
```
~/workbuddy-agent-os/
├── agent-sync/ ← 坚果云同步 + Git 版本控制
│ ├── 01_core/ 身份配置
│ ├── 02_skills/ 技能文件
│ ├── 03_knowledge/ 知识库
│ ├── 04_memory/ L2 facts.db + 摘要 + 日志
│ └── 05_tools/ 工具脚本
│
└── agent-local/ ← 本机私有,不同步
├── memory/raw/ L3 原文
├── vector_db/ 向量库 (可重建)
├── materials/ 原始素材
└── runtime/ 临时缓存
```
### 6.2 换机恢复流程
```bash
# 1. agentos init → 创建目录 + 部署配置 + 安装技能
# 2. agentos restore → 还原 L3 原文 + 素材
# 3. vector_db_rebuild.py → 重建向量库 (3分钟)
```
---
## 七、数据统计(当前系统状态)
| 指标 | 数值 | 说明 |
|------|------|------|
| L2 facts.db | 54 条 | 结构化事实 |
| L1 关键词索引 | 52 条 | BM25 索引 |
| L1 向量库 | 52 条 | ChromaDB 1024维 |
| L3 原文 | 6 个文件 | 按日归档 |
| 向量维度 | 1024 | Qwen3-Embedding |
| 语义检索方式 | BM25 + ChromaDB + RRF 融合 | 双轨混合 |
| 知识库目录 | 19 个分类目录 | Obsidian 兼容 |
| 技能数量 | 9 个 | WorkBuddy 注册 |
| 自动化任务 | 3 个 | 每日定时执行 |
| 索引卡片命名规范 | `{hostname}_{YYYYMMDD}_{slug}.md` | 防冲突 |
---
## 八、架构优缺点分析
### 优势
1. **分层隔离**:L0-L3 各司其职,不相互干扰
2. **Token 节省**:严格分层截断,不无限 fallback
3. **双轨检索**:BM25 精准 + 向量语义,互补
4. **知识审查**:来源评分 + 一致性 + 时效性,保证质量
5. **跨机兼容**:agent-sync 共享 + agent-local 私有,清晰分离
### 待改进
1. **L1-L2-Vec 三方一致维护成本高**:新增事实需要同时更新三个索引
2. **oMLX 稳定性**:Qwen3-8B Chat API 有 500 错误,影响 AI 分类
3. **向量库重建耗时**:知识更新后需手动重建
4. **无反检测层**:Matrix 养号模块的浏览器自动化缺少反检测(正在补齐)
@@ -0,0 +1,416 @@
---
type: concept
domain: system
nature: plan
tags: [agentos, v3.0, implementation, plan, tasks]
status: active
created: 2026-06-16
updated: 2026-06-16
version: 1.0.0
supersedes: []
---
# AgentOS 联邦指挥台 — 实施计划 v1.0
> 基于 `federation-operations-architecture.md` 设计文档
> 参考: `federated-multi-machine-architecture.md` / `dashboard-v4-design.md` / `CORE-ARCHITECTURE.md`
> 总体估计: ≈ 20 小时
---
## 一、优先级总览
```
P0 ─── 感知层: 让指挥台"看到"所有机器状态
├─ 机器状态条(在线/离线/忙碌)
├─ 账号级忙碌状态
└─ 操作前的资源检查
P1 ─── 路由层: 让指挥台"指挥"远程机器
├─ owner_machine 操作路由
├─ 远程执行通道完善
└─ 按钮状态智能化(灰掉/提示/远程执行)
P2 ─── 引擎层: 操作生命周期管理
├─ 统一操作队列(状态机)
├─ 资源锁系统
├─ 状态归零(pre-flight reset)
└─ 日志聚合
P3 ─── 生态层: 高级功能和系统完备
├─ 文件级 WPRA 写入规范
├─ guardd 模块补全
├─ 9 插件体系完善
└─ 键盘锁定/离线队列/DAG
```
---
## 二、依赖关系拓扑
```
P0-1 机器状态条
└── 依赖: guardd 心跳已实现 ✅
└── 阻塞: P1-1 (操作路由需要知道机器是否在线)
P0-2 账号忙碌状态
└── 依赖: 本地资源锁文件
└── 阻塞: P2-2 (资源锁系统)
P1-1 操作路由 (owner_machine 判断)
└── 依赖: P0-1 (机器在线状态)
└── 阻塞: P1-2 (远程执行通道)
P1-2 远程执行通道
└── 依赖: federation API 已部分实现 ✅
└── 前置: 完善 /api/federation/exec 支持所有操作类型
P2-1 状态机队列
└── 依赖: P1-1, P1-2
└── 前置: cross_machine/tasks/ 目录
P2-2 资源锁系统
└── 依赖: 本地文件锁 + guardd 锁管理
└── 前置: guardd 锁模块
P3-1 WPRA 写入规范
└── 依赖: cross_machine/data/ 目录结构已存在 ✅
└── 前置: 插件改写为文件级写入
```
---
## 三、Phase 0: 立即修复 (之前审计发现的问题)
| # | 任务 | 文件 | 估计 | 优先级 |
|:-:|:-----|:-----|:----:|:------:|
| 0.1 | 账号管理跨机显示(已做) | index.html | ✅ 已完成 | P0 |
| 0.2 | 修复 matrix-mgmt 路由 | app.py | ✅ 已完成 | P0 |
| 0.3 | 修复 cross-machines API | app.py | ✅ 已完成 | P0 |
| 0.4 | 修复 loadSmsAccounts 数据格式 | index.html | ✅ 已完成 | P0 |
| 0.5 | SMS API 加 owner_machine | sms_proxy_api.py | ✅ 已完成 | P0 |
| 0.6 | 前端代理/调度/任务路径错配 | index.html | ≈ 20min | P0 |
| 0.7 | 语料库缺失API补充 | routes/matrix.py | ≈ 30min | P0 |
---
## 四、Phase 1: 感知层 — 让指挥台"看见" (≈ 3h)
### 1.1 机器状态条 (≈ 1h)
在每个视图顶部增加机器状态条:
```
┌─────────────────────────────────────────────────────┐
│ 🟢 chengzigedeAir 🟢 5kechengdeAir ⚪ 7kecheng │
│ 账号: 5在线/5总 账号: 0在线/5总 离线30分钟 │
└─────────────────────────────────────────────────────┘
```
**文件**: `index.html` + `core.js` (添加全局状态条组件)
**实现**:
- 每 30s 轮询 `/api/federation/health` 获取三台机器在线状态
- 状态条渲染为全局组件,所有视图共用
- 绿/黄/灰三色: 在线 / 忙碌(有任务运行) / 离线(>5min无心跳)
### 1.2 账号级忙碌状态 (≈ 1h)
```
douyin_01 🟢 在线 ✅ 可操作
douyin_02 🔴 忙碌 ⏳ 正在养号中 (剩余23分钟)
douyin_03 ⚪ 离线 ❌ 机器5kecheng当前离线
```
**文件**: `sms_proxy_api.py` (加忙碌字段) + `index.html` (展示)
**实现**:
- guardd 维护一个 `locks.json`,记录当前哪个账号正在被操作
- SMS API 响应中加 `busy: true/false`, `busy_since: timestamp`
- 忙碌的账号按钮灰掉,显示"正在操作中"
### 1.3 前端路径错配修复 (≈ 20min)
| 前端调用 | 改为 | 文件 |
|:---------|:-----|:-----|
| `/api/matrix/proxy/list` | `/api/matrix/proxies` | index.html |
| `/api/matrix/schedule/list` | `/api/matrix/schedules` | index.html |
| `/api/matrix/task/comment` | `/api/matrix/task/run` (POST+type=comment) | index.html |
---
## 五、Phase 2: 路由层 — 让指挥台"指挥" (≈ 5h)
### 2.1 操作路由 — 本地 vs 远程 (≈ 2h)
**核心逻辑** (所有操作按钮的通用函数):
```javascript
async function executeOperation(accountId, operationType, params) {
// 1. 查账号所属机器
const account = findAccount(accountId);
const targetMachine = account.owner_machine;
// 2. 查机器是否在线
const machineStatus = await getMachineStatus(targetMachine);
if (machineStatus === 'offline') {
showError(`${targetMachine} 当前离线,无法操作`);
return;
}
// 3. 如果是本机 → 本地API
if (targetMachine === currentMachine) {
return localExecute(operationType, params);
}
// 4. 如果是远程机器 → 联邦 exec
return remoteExecute(targetMachine, operationType, params);
}
```
**文件**: 新建 `static/modules/operation-router.js`
**改动**:
- `accountLogin()` → 通过路由执行
- `clearCookies()` → 通过路由执行
- `deleteAccount()` → 通过路由执行
- `batchExecute()` → 支持跨机批量
### 2.2 远程执行通道完善 (≈ 2h)
**文件**: `services/remote_exec.py`
**新增能力**:
- 支持登录命令: `ssh {machine} "cd agent-sync && agentos matrix login {account}"`
- 支持养号命令: `ssh {machine} "cd agent-sync && agentos matrix run --blueprint {bp} --rounds {n}"`
- 支持采集命令: `ssh {machine} "cd agent-sync && agentos matrix collect {phone}"`
- 统一返回格式: `{status, output, error, duration_sec}`
### 2.3 新建前端模块目录 (≈ 30min)
```bash
static/modules/
├── core.js # 框架核心 ✅ 现有
├── operation-router.js # 操作路由 (新建)
├── machine-bar.js # 机器状态条 (新建)
├── operation-queue.js # 操作队列 (Phase 3)
├── resource-lock.js # 资源锁 (Phase 3)
└── ... # 现有其他模块
```
**文件**: `index.html` — 加入新的 script 加载顺序
### 2.4 按钮状态智能化 (≈ 30min)
| 账号状态 | 登录按钮 | 养号按钮 | 采集按钮 |
|:---------|:--------|:---------|:---------|
| 本机·在线·空闲 | 🟢 可用 | 🟢 可用 | 🟢 可用 |
| 本机·在线·忙碌 | 🔴 灰掉"正在养号中" | 🔴 灰掉 | 🟢 可用 |
| 远程·在线·空闲 | 🟢 "远程执行" | 🟢 "远程执行" | 🟢 "远程执行" |
| 远程·离线 | ⚪ 灰掉"XX机离线" | ⚪ 灰掉 | ⚪ 灰掉 |
---
## 六、Phase 3: 引擎层 — 操作生命周期管理 (≈ 7h)
### 3.1 统一操作队列 + 状态机 (≈ 3h)
**文件**:
- `guardd/modules/operation_queue.py` (新建)
- `static/modules/operation-queue.js` (新建)
**后端**:
```python
# guardd/modules/operation_queue.py
class OperationQueue:
"""操作队列 — 管理本机所有操作的生命周期"""
def submit(self, op_type, params) -> str:
"""提交操作,返回 operation_id"""
# 写 cross_machine/tasks/pending/{op_id}.json
def check(self, op_id) -> dict:
"""查询操作状态"""
def cancel(self, op_id) -> bool:
"""取消正在运行的操作"""
def cleanup(self, op_id):
"""操作完成后清理"""
```
**前端**: 操作日志面板,按机器/时间/类型过滤
### 3.2 资源锁系统 (≈ 2h)
**文件**:
- `guardd/modules/resource_lock.py` (新建)
- `static/modules/resource-lock.js` (新建)
**锁表**:
```python
locks = {
"browser": {"held_by": "op_001", "acquired_at": "...", "ttl": 3600},
"account:douyin_01": {"held_by": "op_001", ...},
"identity:douyin_01_camo": {"held_by": "op_001", ...},
}
```
**规则**:
- 锁自动过期 (TTL)
- 锁可被强制释放 (管理员)
- 锁冲突时: 拒绝新操作,提示"资源被 XX 操作占用"
### 3.3 状态归零 Pre-flight Reset (≈ 1h)
**文件**: `guardd/modules/preflight.py` (新建)
每次操作前自动执行:
```bash
1. pkill -f camoufox # 杀残留浏览器
2. pkill -f playwright # 杀残留驱动
3. rm -rf /tmp/camoufox_* # 清临时文件
4. check_locks() # 检查并释放过期锁
5. check_disk_space() # 检查磁盘空间
6. return "ready" # 返回就绪状态
```
### 3.4 日志聚合 (≈ 1h)
**文件**:
- `app.py` 新增 `/api/logs/push` 端点
- `guardd/modules/log_aggregator.py` (新建)
**日志格式**:
```json
{
"op_id": "op_20260616_001",
"machine": "5kechengdeAir",
"type": "nurture_run",
"status": "completed",
"states": [...],
"output": "...",
"duration_sec": 360,
"triggered_by": "dashboard"
}
```
---
## 七、Phase 4: 生态层 — 系统完备 (≈ 5h)
### 4.1 WPRA 写入规范落地 (≈ 2h)
参考 `dashboard-v4-design.md` 中的 cross_machine 数据规范:
```python
# 每个插件写数据时遵循
CROSS_MACHINE / "data" / {plugin} / {uid}.json
# 内容包含
{"plugin": "...", "version": "...", "machine_uid": "...",
"hostname": "...", "timestamp": "...", "data": {...}}
```
**文件**:
- `plugins/base.py` — 更新 `write_shared_data()`
- `plugins/matrix.py` — 改写为文件级写入
- `plugins/guardd.py` — 改写为文件级写入
### 4.2 guardd 模块补全 (≈ 2h)
参考 `federated-multi-machine-architecture.md`:
| 模块 | 状态 | 任务 |
|:-----|:----:|:-----|
| `heartbeat` | ✅ 已实现 | — |
| `task_worker` | ⏳ 部分 | 扫描 cross_machine/tasks/ 执行 |
| `upgrade_checker` | ❌ 缺失 | 版本比对+自动拉取 |
| `memory_triage` | ❌ 缺失 | 记忆过滤→提交箱 |
| `knowledge_sync` | ❌ 缺失 | 知识库变更通知 |
| `encrypted_channel` | ❌ 缺失 | RSA 加密通信 |
| `cleanup` | ❌ 缺失 | 清理30天以上旧数据 |
| `operation_queue` | ❌ 缺失 | Phase 3 新建 |
| `resource_lock` | ❌ 缺失 | Phase 3 新建 |
| `preflight` | ❌ 缺失 | Phase 3 新建 |
### 4.3 9 插件体系完善 (≈ 1h)
检查现有插件 vs 设计:
| 插件 | dashboard-v4 设计 | 现状 |
|:-----|:-----------------|:-----|
| guardd | 🖥 联邦机器 | ✅ 已实现 |
| matrix | 📱 矩阵养号 | ✅ 已实现 |
| ave | 🎬 视频工厂 | ✅ 已实现 |
| collector | 📡 内容采集 | ⏳ crawl.py 新建 |
| skills | 🧩 技能树 | ❌ 缺失 |
| knowledge | 📚 知识库 | ✅ kb_api.py |
| automation | ⏰ 自动任务 | ⏳ scheduler.py 新建 |
| tools | 🔧 工具集 | ❌ 缺失 |
| system | ⚙️ 系统核心 | ⏳ system_plugins.py |
---
## 八、实施顺序总结
```
Week 1 (3天) Phase 1: 感知层
├── 1.1 机器状态条 ≈ 1h
├── 1.2 账号忙碌状态 ≈ 1h
└── 1.3 前端路径修复 ≈ 20min
Week 2 (3天) Phase 2: 路由层
├── 2.1 操作路由 ≈ 2h
├── 2.2 远程执行通道 ≈ 2h
├── 2.3 前端模块化 ≈ 30min
└── 2.4 按钮状态智能化 ≈ 30min
Week 3 (3天) Phase 3: 引擎层
├── 3.1 操作队列 ≈ 3h
├── 3.2 资源锁 ≈ 2h
├── 3.3 状态归零 ≈ 1h
└── 3.4 日志聚合 ≈ 1h
Week 4 (2天) Phase 4: 生态层
├── 4.1 WPRA 写入规范 ≈ 2h
├── 4.2 guardd 模块 ≈ 2h
└── 4.3 9插件体系 ≈ 1h
Phase 0 (已做) ✅ 6项审计修复完成
Phase 0 (待做) ❌ 0.6 前端路径错配 ≈ 20min
❌ 0.7 语料库API ≈ 30min
```
---
## 九、风险与缓解
| 风险 | 概率 | 影响 | 缓解 |
|:-----|:----:|:----:|:-----|
| SSH 远程执行权限不足 | 中 | 高 | 先实现本地操作,远程执行作为可选升级 |
| 资源锁导致操作阻塞 | 低 | 中 | 锁设 TTL,管理员可强制释放 |
| guardd 模块太多难维护 | 中 | 中 | 模块化设计,每个模块独立文件,可单独启用/禁用 |
| 前端模块化导致加载顺序问题 | 低 | 高 | 使用串行加载器,明确依赖顺序 |
| 文件级 WPRA 写入增加 Git 冲突 | 低 | 中 | 按 machine_uid 隔离文件,不会冲突 |
---
## 十、验收标准
### Phase 1 完成标志
- [ ] 每个视图顶部显示三台机器状态条
- [ ] 账号卡片显示忙碌状态
- [ ] 前端所有 fetch 路径正确,无 404
### Phase 2 完成标志
- [ ] 远程账号按钮自动路由到对应机器
- [ ] 离线机器操作按钮灰掉并提示
- [ ] 可通过 Dashboard 远程登录/养号/采集
### Phase 3 完成标志
- [ ] 每个操作有完整生命周期追踪
- [ ] 资源冲突时正确拒绝或排队
- [ ] 操作前自动清理残留进程
- [ ] 操作日志可查看、可过滤
### Phase 4 完成标志
- [ ] 所有插件按 WPRA 规范写入
- [ ] guardd 10 模块正常运行
- [ ] 9 插件体系完整
@@ -0,0 +1,97 @@
---
type: concept
domain: system
nature: architecture
tags: [agentos, v2.1, federated, multi-machine, architecture, guardd]
status: active
created: 2026-05-15
updated: 2026-05-15
version: 1.0.0
---
# 联邦式多机协同架构(V2.1)
> AgentOS 支持多台 Mac 组成**智能体联邦**,通过三层架构实现数据隔离 + 轻量协同。
## 架构总览
```
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ machine a │ │ machine b │ │ machine c │
│ (redmi-12c) │ │ (mac-mini) │ │ (macbook air)│
│ │ │ │ │ │
│ agent-local │ │ agent-local │ │ agent-local │
│ (私钥/记忆/ │ │ (私钥/记忆/ │ │ (私钥/记忆/ │
│ 重资产) │ │ 重资产) │ │ 重资产) │
└──────┬───────┘ └──────┬───────┘ └──────┬───────┘
│ │ │
└──────────┬─────────┴─────────┬──────────┘
│ agent-sync/ │
│ (NutSync 同步) │
└──────────────────┘
events/ status/ tasks/
encrypted/ knowledge/
┌──────────────────┐
│ 直传层 (SSH/AirDrop) │
└──────────────────┘
```
## 三层数据架构
| 层 | 路径 | 内容 | 同步方式 |
|----|------|------|---------|
| **agent-local/** | 本机专属 | 私钥 · API Key · 素材库 · 本地记忆 · 提交箱 · 守护进程日志 | ❌ 永不共享 |
| **agent-sync/** | 共享目录 | 配置 · 知识库 · 技能 · 记忆摘要 · 工具脚本 | NutSync 双向同步 |
| **直传层** | 点对点 | 大文件传输(视频/素材等) | SSH rsync / AirDrop |
## 七大协同子系统
| # | 子系统 | 说明 | 关键文件 | 状态 |
|---|--------|------|---------|------|
| ① | **状态机** | 每台 5-10 分钟上报心跳,15 分钟无心跳判离线 | `cross_machine/status/{host}/heartbeat.json` | ✅ 已实现 |
| ② | **事件总线** | 跨机事件日志(任务完成/错误/更新等 10 种类型) | `cross_machine/events/{date}/*.json` | ✅ 已实现 |
| ③ | **任务协作** | 跨机任务请求/响应(异步文件机制) | `cross_machine/tasks/` | ✅ 已实现 |
| ④ | **加密通讯** | RSA-4096 密钥对,公钥注册/私钥本地 | `cross_machine/encrypted/` | ✅ 已实现 |
| ⑤ | **知识同步** | 双向:拉取知识库 + 推送本地新知识到收件匣 | `03_knowledge/01_submissions/` | ✅ 已实现 |
| ⑥ | **自动升级** | 版本清单驱动,非破坏性更新自动执行 | `cross_machine/knowledge/versions.json` | ✅ 已实现 |
| ⑦ | **文件直传** | 同局域网 SSH rsync / AirDrop 直传大文件 | `guardd/modules/transfer.py` | ✅ 已实现 |
## 安全边界
| 内容 | 存储位置 | 安全性 |
|------|---------|--------|
| 公钥 | `cross_machine/registry/*_pub.pem` | ✅ 公开安全 |
| 加密消息 | `cross_machine/encrypted/` | ✅ 无私钥不可读 |
| 私钥/API Key | `agent-local/identity/secrets/` | ✅ 永不共享 |
| 记忆数据 | `agent-local/memory/` | ✅ 每机独立 |
| 重资产 | `agent-local/tools/*/` | ✅ 不跨机同步 |
## 守护进程 guardd
每台机器运行 `guardd` 守护进程,负责 7 个子系统的自动化执行。
- **安装**: launchd 管理,300 秒周期
- **引擎**: 纯规则引擎,0 token 消耗
- **路径**: `05_tools/00_setup/guardd/guardd.py`
- **日志**: `agent-local/runtime/guardd/`
### guardd 9 模块
| 模块 | 职责 |
|------|------|
| `heartbeat` | 状态上报(CPU/内存/任务)写入 heartbeat.json + 推送 Dashboard |
| `dashboard_sync` | 将本机 Dashboard 插件数据写入跨机共享目录 |
| `task_worker` | 扫描本机任务并执行 |
| `upgrade_checker` | 版本清单比对,自动/手动升级 |
| `memory_triage` | 过滤本地记忆,推送通用内容到提交箱 |
| `knowledge_sync` | 检测知识库变更 + 推送本地提交箱到远程 |
| `encrypted_channel` | 解密加密消息到本地 |
| `sync_checker` | 自动 git pull 拉取远程变更 |
| `cleanup` | 清理 30 天以上的旧事件和已完成任务 |
## 相关文件
- `docs/DASHBOARD_DATA_LAYER_V2.md` — 联邦式数据架构完整设计
- `01_core/MAINTENANCE_GUIDE.md` — guardd 运维操作手册
- `README.md` — 系统入口(多机联邦章节)
- `CHANGELOG.md` — V2.1 变更记录
@@ -0,0 +1,324 @@
---
type: concept
domain: system
nature: architecture
tags: [agentos, v3.0, federated, multi-machine, operations, orchestration]
status: draft
created: 2026-06-16
updated: 2026-06-16
version: 1.0.0
supersedes: []
---
# AgentOS 联邦指挥台 — 操作架构设计 v1.0
> 版本: 1.0.0-draft | 2026-06-16
> 设计目标: 创建世界级的多机智能体编排系统,可扩展为大规模计算机军团
---
## 一、设计哲学
### 核心原则
1. **指挥台只负责聚合和分发,不直接执行** — 所有操作在目标机器上运行
2. **每台机器是自治的智能体** — 离线也能独立运行,在线时接受指挥台调度
3. **操作即状态机** — 每个操作都有明确的声明周期,可追踪、可重试、可审计
4. **先检后动** — 操作前检查资源状态,保证不会破坏正在运行的任务
5. **双模交互** — Dashboard(图形)和 CLI(命令行)完全对等,同一套底层
### 参考架构
| 来源 | 借鉴点 |
|:-----|:-------|
| Selenium Grid Hub-Node | 中央调度 + 分布式执行节点 |
| Kubernetes Job/Pod | 声明式任务 + 状态机 + 日志聚合 |
| Apache Airflow DAG | 操作依赖管理 + 重试 + 告警 |
| Erlang/Elixir Actor | 每台机器 = 一个 Actor,通过消息通信 |
| Unix Pipeline | 每个操作 = 一个进程,stdin/stdout/stderr |
---
## 二、系统架构:三层模型
```
┌──────────────────────────────────────────────────────────────────┐
│ Layer 1: Command Center │
│ (Dashboard Web UI + CLI) │
│ │
│ 功能: 聚合展示 + 命令输入 + 日志查看 + 状态监控 │
│ 位置: chengzigedeAir (master) │
│ 也支持: 任何机器浏览器打开看板,或本地 CLI 直接执行 │
└──────────────────────┬───────────────────────────────────────────┘
│ HTTP / WebSocket / SSE
┌──────────────────────┴───────────────────────────────────────────┐
│ Layer 2: Orchestration Bus │
│ │
│ - federation API (REST): /api/federation/* │
│ - event stream (SSE): /api/events │
│ - remote exec (SSH): /api/federation/exec │
│ - log aggregation: 每台机器推送日志到中心存储 │
└──────────────────────┬───────────────────────────────────────────┘
│ SSH / HTTP / Tailscale
┌────────────────┼────────────────┐
▼ ▼ ▼
┌────────────┐ ┌────────────┐ ┌────────────┐
│ Machine A │ │ Machine B │ │ Machine C │
│ chengzige │ │ 5kecheng │ │ 7kecheng │
├────────────┤ ├────────────┤ ├────────────┤
│ Layer 3a │ │ Layer 3a │ │ Layer 3a │
│ Agent Daemon│ │ Agent D. │ │ Agent D. │
│ (guardd) │ │ (guardd) │ │ (guardd) │
├────────────┤ ├────────────┤ ├────────────┤
│ Layer 3b │ │ Layer 3b │ │ Layer 3b │
│ Camoufox │ │ Camoufox │ │ Camoufox │
│ Browser │ │ Browser │ │ Browser │
└────────────┘ └────────────┘ └────────────┘
```
### 每台机器上的 Agent Daemon (guardd)
每台机器运行一个常驻后台进程 `guardd`,职责:
| 职责 | 说明 |
|:-----|:-----|
| 心跳上报 | 每 300s 写一次 heartbeat.json,含 CPU/内存/磁盘/任务状态 |
| 操作队列 | 接收指挥台下发的操作,排队执行 |
| 资源锁 | 管理浏览器实例/账号的使用状态,防止冲突 |
| 日志推送 | 操作日志实时推送到中心日志存储 |
| 状态归零 | 操作完成后清理浏览器进程、还原环境 |
---
## 三、操作状态机
### 所有操作的通用生命周期
```
┌──────────┐
│ pending │ ← 用户下发操作,等待调度
└────┬─────┘
↓
┌──────────┐
┌──────→│ checking │ ← 检查目标机器状态、资源可用性
│ └────┬─────┘
│ ↓
│ ┌──────────┐
│ │preparing │ ← 关闭旧浏览器、清理缓存、锁资源
│ └────┬─────┘
│ ↓
│ ┌──────────┐
│ ┌─→│ running │ ← 操作执行中(浏览器打开/脚本运行)
│ │ └────┬─────┘
│ │ ↓
│ │ ┌──────────┐ ┌──────────┐
│ │ │completed │ 或 │ failed │ ← 成功完成或出错
│ │ └────┬─────┘ └────┬─────┘
│ │ ↓ ↓
│ │ ┌──────────┐ ┌──────────┐
│ │ │ cleaning │ │ cleaning │ ← 清理资源、释放锁
│ │ └────┬─────┘ └────┬─────┘
│ │ ↓ ↓
│ │ ┌──────────┐ ┌──────────┐
│ └──│ done │ │ error │
│ └──────────┘ └──────────┘
│
└── 任何阶段都可被"取消"或"超时"
超时后进入 cleaning → error
```
### 状态转换规则
| 转换 | 触发条件 | 动作 |
|:-----|:---------|:-----|
| pending → checking | 调度器获取执行权 | 读取目标机器心跳、检查是否有其他任务在跑 |
| checking → preparing | 资源检查通过 | 发送 prepare 命令到目标机器 |
| checking → pending | 资源忙 | 重新排队,等待重试 |
| checking → failed | 目标机器离线 | 标记失败,通知用户 |
| preparing → running | 准备完成 | 执行具体操作 |
| running → completed | 正常结束 | 收集结果 |
| running → failed | 异常退出 | 收集错误信息 |
| * → cleaning | 任何非 done 状态的完成 | 执行清理脚本 |
| cleaning → done | 清理完成 | 更新最终状态 |
| * → failed | 超时(默认 30min) | 强行终止,清理 |
---
## 四、资源管理
### 资源类型
| 资源 | 粒度 | 冲突规则 |
|:-----|:-----|:---------|
| 浏览器实例 | 每机器 1 个 Camoufox | 全局互斥——同一台机器不能开两个浏览器 |
| 账号登录态 | 每个 account_id | 同一账号不能同时被两个操作使用 |
| 身份指纹 | 每个 identity_dir | 同一身份不能同时被两个浏览器使用 |
| 键盘/鼠标 | 每机器独占 | 远程操作时锁定本地输入(可选) |
### 资源锁实现
```python
# 每台机器上的 guardd 维护的锁表
locks = {
"browser": {"held_by": "task_001", "acquired_at": "2026-06-16T18:00:00"},
"account:douyin_01": {"held_by": "task_001", "acquired_at": "..."},
"identity:douyin_01_camo": {"held_by": "task_001", "acquired_at": "..."},
}
```
### 状态归零 (Pre-flight Reset)
每个操作执行前,目标机器必须执行:
1. **检查是否有残留浏览器进程** — `pkill -f camoufox` (如果有, kill)
2. **检查是否有残留的 Playwright 进程** — `pkill -f playwright`
3. **检查账号登录锁** — 清除该账号的锁
4. **清理临时文件** — 删除上次操作的临时缓存
5. **重置代理状态** — 恢复默认代理配置
6. **确认资源可用** — 返回"已就绪"状态
---
## 五、操作类型全表
| 操作 | 类型 | 机器 | 状态管理 | 并发 | 超时 |
|:-----|:-----|:-----|:---------|:----|:-----|
| 账号登录 | A 本机浏览器 | assigned_machine | 锁 browser + 锁 account | 1 账号/次 | 120s |
| 养号执行 | A 本机浏览器 | assigned_machine | 锁 browser + 锁 identity | 1 身份/次 | 60min |
| 信息采集 | B 远程脚本 | 任意在线机器 | 只读,无需锁 | 并发 | 60s |
| 内容发布 | A 本机浏览器 | assigned_machine | 锁 browser + 锁 account | 1 账号/次 | 300s |
| 环境同步 | B 远程脚本 | 指定机器 | 互斥(同一机器不能同时同步) | 1 台/次 | 120s |
| 对账检查 | B 远程脚本 | 指定机器 | 只读,无需锁 | 并发 | 60s |
| 远程Shell | B 远程脚本 | 指定机器 | 无锁 | 并发 | 30s |
| 状态监控 | C 聚合 | 所有机器 | 只读 | 并发 | 10s |
---
## 六、日志与审计
### 日志结构
每个操作产生一条结构化日志:
```json
{
"operation_id": "op_20260616_001",
"type": "account_login",
"target_machine": "5kechengdeAir",
"target_account": "douyin_01",
"status": "completed",
"states": [
{"state": "pending", "time": "18:00:00"},
{"state": "checking", "time": "18:00:01"},
{"state": "preparing", "time": "18:00:02"},
{"state": "running", "time": "18:00:05"},
{"state": "completed","time": "18:01:15"},
{"state": "cleaning", "time": "18:01:16"},
{"state": "done", "time": "18:01:17"}
],
"output": "login successful, cookie saved",
"error": null,
"triggered_by": "dashboard_user",
"duration_sec": 77
}
```
### 日志聚合
- 每台机器的 guardd 实时推送日志到中心 `/api/logs/push`
- Dashboard 提供日志查看器: 按机器/操作/时间/状态过滤
- 日志保留 30 天,自动归档
---
## 七、并发与互斥策略
| 场景 | 策略 |
|:-----|:-----|
| 用户点「养号」时机器已在养号 | 拒绝,提示"5kecheng 正在养号中,是否停止当前任务?" |
| 用户点「登录」时浏览器已打开 | 先关闭浏览器,再重新打开 |
| 两台机器同时给同一账号发命令 | 不可能——账号只属于一台机器(ORACLE.yaml) |
| 用户从 Dashboard 和 CLI 同时操作 | 共享同一资源锁表,后到者等待或拒绝 |
| 机器离线时下发操作 | 缓存到队列,机器上线后自动执行(可选) |
---
## 八、安全与锁定
### 远程操作时的机器锁定
当通过 Dashboard 远程控制 5kechengdeAir 执行浏览器操作时:
| 安全措施 | 实现 |
|:---------|:-----|
| 键盘锁定 | 操作开始时,5kecheng 本地键盘暂时屏蔽(防止误触) |
| 屏幕提示 | 5kecheng 显示器显示"正在被远程控制"的提示 |
| 强制停止 | 任何时候按 Ctrl+C 或点击「停止」终止操作 |
| 超时自动释放 | 30min 无活动自动关闭浏览器并释放锁 |
### 注意
键盘锁定是进阶功能。初期先实现资源锁+状态机,锁定后续再做。
---
## 九、Dashboard 落地计划
### Phase 1: 状态感知 (优先级最高)
- [x] 三台机器心跳检测 (guardd 已有)
- [ ] 机器状态条: 每个视图顶部显示三台机器在线/离线/忙碌
- [ ] 账号级别的忙碌状态 (是否正在被操作)
### Phase 2: 操作路由 (当前)
- [ ] `accountLogin()` 加 owner_machine 判断 + 远程执行
- [ ] `clearCookies()` 加 owner_machine 判断
- [ ] `deleteAccount()` 加 owner_machine 判断
- [ ] 按钮状态: 远程账号显示"需在 XX 机器操作"或"远程执行"
### Phase 3: 状态机引擎
- [ ] 统一的操作队列: `pending → checking → running → done`
- [ ] 资源锁: 账号级别和浏览器级别
- [ ] 操作前的 state reset (清理旧进程)
- [ ] 操作日志存储 + 查看器
### Phase 4: 高级功能
- [ ] 键盘锁定 / 屏幕提示
- [ ] 离线队列 / 上线自动执行
- [ ] 操作 DAG (先后依赖)
- [ ] 多用户协作
---
## 附录: 参考的原始架构文档
本文设计参考了以下原有系统文档中的思想:
| 文档 | 关键借鉴 |
|:-----|:---------|
| `architecture/federated-multi-machine-architecture.md` | 7大协同子系统(心跳/事件/任务/加密/知识/升级/传输)、guardd 7模块、三层数据架构 |
| `archive/CORE-ARCHITECTURE.md` | 目录职责边界、agent-local/agent-sync 分离原则、软链接映射、技能分类 |
| `dashboard-v4-design.md` | cross_machine/data/ WPRA 写入规范、9个内置插件规范、机器感知设计、24h TTL 过期策略 |
| `COMMAND-CENTER-PLAN.md` (99_system/) | 命名空间分层(agentos matrix/ave/crawl/fleet/serve) |
| `cross_machine/ARCHITECTURE-v2.md` (04_memory/) | WPRA 写分区·读聚合模型、Git 冲突消除方案 |
### 本次设计新增的概念
| 概念 | 来源 | 说明 |
|:-----|:-----|:------|
| 操作状态机 | 新建 | pending→checking→preparing→running→completed→cleaning→done 完整生命周期 |
| 资源锁 | 新建 | 浏览器级/账号级/身份级互斥,防止冲突操作 |
| 状态归零 | 新建 | 操作前自动清理残留进程、释放锁、重置环境 |
| 操作路由 | 新建 | 根据 owner_machine 将操作路由到对应机器执行 |
| 双模对等 | 新建 | Dashboard 和 CLI 共享同一套底层 API |
---
## 十一、关键设计决策记录
| 决策 | 选项 | 选择 | 理由 |
|:-----|:-----|:-----|:------|
| 操作同步还是异步? | 同步等待 / 异步队列 | **混合**: 短操作(<10s)同步,长操作异步 | 登录等短操作需要实时反馈 |
| 远程执行通道 | SSH / HTTP / WebSocket | **SSH** (现有) + **HTTP API** (未来) | SSH 已打通,HTTP 需要额外服务 |
| 状态存储 | Redis / SQLite / 文件 | **文件** (现有 heartbeats/目录) | 零依赖,随 Git 同步 |
| 浏览器管理 | 每机器 1 个 / 多实例 | **1 个 Camoufox,轮流使用** | 指纹一致性,避免被检测 |
| CLI 与 Dashboard 关系 | 主从 / 对等 | **对等**—同一套底层 API | CLI 无网络时也能用 |
@@ -0,0 +1,116 @@
---
id: KB-SYS-ARCH
title: "AgentOS 加载与检索架构"
type: reference
status: active
nature: reference
domain: personal-management
subdomain: [系统设计]
tags: [架构, 加载, 检索, 向量, token优化]
confidence: 1.0
date_created: 2026-05-03
date_modified: 2026-05-03
version: 1
---
# AgentOS 加载与检索架构
> 版本:v1.0 | 最后更新:2026-05-03
> 本文档描述 AgentOS 的四条独立加载/检索管道及其协作方式。
---
## 一、核心设计原则
> **不同类型的信息,用不同的方式加载。不混在一起,不相互干扰。**
```
行为控制层(身份+协议)→ 不走向量检索,靠注入和触发词
内容检索层(知识+记忆)→ 走向量检索,靠语义匹配
```
---
## 二、四管道架构
### 管道①:身份注入(常驻)
| 属性 | 值 |
|------|------|
| **文件** | SOUL.md + IDENTITY.md + USER.md |
| **存储** | `~/.workbuddy/` |
| **加载方式** | WorkBuddy 每次对话启动时自动注入 |
| **Token 占用** | ~750(常驻) |
| **是否走向量** | ❌ 不走向量检索 |
| **内容** | 行为规则、模式切换、安全边界、身份、用户画像 |
### 管道②:协议按需加载(触发词激活)
| 属性 | 值 |
|------|------|
| **文件** | meta-thinking.md / cross-domain.md / stuck-intervention.md / knowledge-review.md |
| **存储** | `03_knowledge/99_system/protocols/` |
| **加载方式** | SOUL.md 检测触发词后读取对应文件,执行完退出 |
| **Token 占用** | 每个 ~200(用完即退) |
| **是否走向量** | ❌ 不走向量检索(存放在 99_system/,不参与知识搜索) |
| **触发机制** | 当前:关键词匹配 → 可升级为语义相似度匹配 |
### 管道③:知识库语义检索(按需搜索)
| 属性 | 值 |
|------|------|
| **目录** | `03_knowledge/`(排除 99_system/) |
| **内容** | 概念知识 (10_concepts/)、方法论 (20_methods/)、参考资料 (40_references/) |
| **检索方式** | BM25 关键词 + ChromaDB 语义向量 + RRF 融合排序 |
| **向量模型** | Qwen3-Embedding-0.6B(1024 维) |
| **是否常驻** | ❌ 不常驻,用户提问时按需检索 |
| **负责技能** | kb_manager |
### 管道④:记忆系统分层检索(自动触发)
| 属性 | 值 |
|------|------|
| **目录** | `04_memory/` |
| **检索流程** | L1 → L2 → L3 分层截断 |
| **L1** | keyword_index.json + ChromaDB 向量 → 关键词+语义混合检索 |
| **L2** | facts.db(SQLite 结构化事实,置信度 ≥ 0.7 才返回) |
| **L3** | raw 原文存档(仅用户明确要求时才加载) |
| **截断规则** | L1 无匹配 → 停止;L2 置信度不足 → 不 fallback |
| **负责技能** | memory_manager |
---
## 三、数据流图
```
用户输入
│
├─→ 管道①(身份注入已常驻)→ 行为规则已就位
│
├─→ SOUL.md 检测触发词
│ ├─ 命中 → 管道②:加载对应协议文件 → 执行 → 退出
│ └─ 未命中 → 继续工程模式
│
├─→ 用户询问知识 → 管道③:BM25+ChromaDB 检索知识库
│
└─→ 用户提问触发记忆 → 管道④:L1→L2 分层检索
```
---
## 四、Token 优化策略
| 策略 | 实现 | 节省效果 |
|------|------|---------|
| 分层截断 | L1 无匹配立即停止 | 避免整库扫描 |
| 置信度阈值 | L2 < 0.7 不返回 | 避免低质量事实占用 context |
| 协议退出 | 协议文件用完即退出上下文 | 每个协议 ~200 tokens 不持续占用 |
| L3 延迟加载 | 仅用户明确要求才加载 | 最大节省(原文通常很大) |
| 按需加载 | 知识库检索只返回片段 | 避免全文件读取 |
| 99_system 排除 | 系统文档不参与向量检索 | 减少搜索噪音 |
---
## 五、触发词匹配:关键词 vs 语义相似度
见 [[99_system/architecture/trigger-matching-analysis|触发词匹配方案对比分析]]
@@ -0,0 +1,216 @@
---
type: concept
domain: system
nature: architecture
tags: [agentos, v3.0, matrix, login, auth, sms]
status: draft
created: 2026-06-16
updated: 2026-06-16
version: 1.0.0
---
# AgentOS 联邦登录系统 — 技术图谱 v1.0
> 目标: 全自动跨平台登录,智能匹配登录方式,零人工介入
---
## 一、现有代码结构总览
```
scripts/
├── login_identity.py # 手动登录(旧,等待用户按Enter)
├── auth_manager.py # 登录态检测原子模块 ✅
├── cdp_connector.py # 浏览器连接器(Camoufox持久化/CDP)✅
│
├── matrix_modules/account/
│ ├── douyin_login.py # 抖音自动登录(含SMS)✅ 核心
│ ├── xiaohongshu_login.py # 小红书自动登录 ❌ 缺失
│ ├── sms_login.py # SMS验证码原子操作 ✅ 核心
│ └── sms/
│ ├── __init__.py # 统一导出
│ ├── base.py # SMSHandler 抽象基类
│ └── api.py # ApiSMSHandler API轮询 ✅ 核心
│
├── dashboard/plugins/
│ └── sms_proxy_api.py # Dashboard登录API(调的是旧脚本)⚠️
│
└── archive/
├── scan_login.py # 扫码登录(归档)📦
└── test_sms_login.py # 短信登录测试(归档)📦
```
## 二、平台登录流程对比
### 2.1 抖音登录(已有 douyin_login.py)
```
前置检测:
1. 读取 accounts.yaml → 手机号
2. 创建/确认身份目录
3. 启动 Camoufox 持久化浏览器
执行流程:
1. 导航 https://www.douyin.com/
2. 等待6秒 → 检测登录面板 #login-panel-new
3. 如果已经登录(检测 data-e2e=user-avatar)→ 跳过
4. 没检测到面板 → 等待15秒让用户手动点"登录"
5. 检测到面板 → 调用 sms_login 流程
SMS登录子流程 (sms_login.py):
Step 1: 点"一键登录"按钮
Step 2: 等待验证码输入框出现
Step 3: ApiSMSHandler 轮询获取验证码(最多3次,超时重发)
Step 4: 填入验证码(JS设置value+dispatchEvent)
Step 5: 点确认(DOM点击 → 系统级鼠标兜底)
Step 6: 验证登录态(面板消失+有头像)
后置处理:
- 写操作日志 login_log.jsonl
- 采集用户资料 ProfileScraper
- 浏览器保持打开
```
### 2.2 小红书登录(缺失)
```
当前状态:
- 无独立入口脚本
- sms_login.py 的原子操作可复用(点击按钮/填验证码/点确认)
- 登录面板检测、一键登录、URL导航需要适配
差异点:
- 登录URL不同: https://www.xiaohongshu.com/explore
- 登录面板CSS选择器不同
- "一键登录"按钮文本可能不同
- 登录态Cookie名不同: a1 / web_session
```
### 2.3 扫码登录(归档)
```
archive/scan_login.py 已实现:
- 生成二维码
- 检测扫码结果
- 确认登录
适用场景: 桌面端抖音扫码登录
```
## 三、登录态检测体系
### 3.1 四维状态检测(当前 sms_proxy_api.py)
| 维度 | 检测方式 | 判断依据 |
|:-----|:---------|:---------|
| has_identity | 文件夹存在性 | `identities/{name}/user_data/` 是否存在 |
| has_cookie | Firefox cookies.sqlite | `SELECT count(*) FROM moz_cookies WHERE name LIKE '%session%'` |
| has_profile | 文件存在性 | `user_data/profiles.yaml` 是否存在 |
| has_registry | 注册表存在性 | 账号是否在 accounts.yaml 注册 |
### 3.2 Cookie 级检测(auth_manager.py)
| 平台 | 关键Cookie | 检测方式 |
|:-----|:-----------|:---------|
| 抖音 | `sessionid`, `sid_guard` | Cookie名匹配 |
| 小红书 | `a1`, `web_session` | Cookie名匹配 |
### 3.3 DOM 级检测(auth_manager.py)
| 平台 | 选择器 | 说明 |
|:-----|:-------|:-----|
| 抖音 | `[data-e2e='user-avatar']` | 主指示器 |
| 抖音 | `[data-e2e='user-detail']` | 备用 |
| 小红书 | `.user-avatar` | 头像元素 |
| 小红书 | `.reds-count` | 计数元素 |
### 3.4 综合检测逻辑 (get_login_status)
```
Cookie 检测ok 且 DOM 检测ok → method='both'
Cookie 检测ok → method='cookie'
DOM 检测ok → method='dom'
兜底: Cookie数量 > 30 → 判定已登录
```
## 四、需要补充的环节
### P0: Dashboard 调正确脚本
```
当前: /api/matrix/accounts/{id}/login → login_identity.py(手动)
预期: 根据 platform 自动路由:
douyin → douyin_login.py(全自动)
xiaohongshu → xiaohongshu_login.py(待创建)
```
### P0: 小红书入口脚本 (xiaohongshu_login.py)
```
复用 douyin_login.py 框架 + sms_login.py,仅修改:
- 平台URL → xiaohongshu.com/explore
- 登录面板选择器 → 小红书专用
- 一键登录按钮文本 → 适配小红书
- Cookie规则 → auth_manager 已有
```
### P1: 智能匹配引擎
```
根据账号信息自动选择登录方式:
1. 已登录 → 跳过(检测 has_cookie + 验证过期)
2. 有身份无Cookie → 按平台执行自动登录
3. 首次登录 → 创建身份 → 自动登录
4. 短信登录 → 自动触发短信 → 轮询获取 → 自动填入
5. 扫码兜底 → 检测平台是否支持扫码
```
### P1: 过期session检测
```
方法: 在登录页检测"已登录"状态后,导航到个人中心
检查是否可加载用户信息(不发敏感请求)
如果跳转到登录页 → session过期
```
### P2: 跨机路由
```
远程机器登录:
Dashboard → fire-and-forget 发送命令
远程机器 → 执行 douyin_login.py
完成后 → 更新本地 has_cookie 状态
```
## 五、当前系统完整调用链
```
Dashboard 🔑 点击
↓
POST /api/matrix/accounts/{id}/login
↓
sms_proxy_api.py: api_account_login()
↓
subprocess.Popen([agent-os python, -m, mc, account, login, {id}])
↓ (当前链路)
mc/cli.py: cmd_login()
↓
subprocess.Popen([sys.executable, login_identity.py, {id}, --platform {p}])
↓
login_identity.py → 开Camoufox → 等Enter → 检测Cookie → 退出
⚠️ 需要人按Enter,不是全自动
↓ (目标链路)
mc/cli.py: 新增路由 → 检测platform
↓ douyin
douyin_login.py → 开Camoufox → 自动点一键登录 → 自动收短信 → 自动填 → 自动确认 → 自动验证
↓ xiaohongshu (待创建)
xiaohongshu_login.py → 同上逻辑
```
## 六、设计原则(不改原有代码,只加新功能)
1. **原有脚本不动** — `login_identity.py` 保留,通过新入口分流
2. **新增平台脚本** — 按 `douyin_login.py` 模板创建 `xiaohongshu_login.py`
3. **智能分流** — `mc account login` 检测 platform 自动路由
4. **逐步替换** — 新流程跑通后再切换 Dashboard 默认调用
5. **兜底机制** — 自动流程失败后提示用户手动操作
---
*版本: 1.0.0-draft | 2026-06-16*
@@ -0,0 +1,133 @@
# 触发词匹配方案:关键词 vs 语义相似度
> 版本:v1.0 | 最后更新:2026-05-03
---
## 一、现状:关键词匹配
**工作原理**:SOUL.md 中列出触发词列表,检测用户输入中是否包含这些词。
| 类别 | 触发词 |
|------|--------|
| 升维审视 | 升维思考、第一性原理、前提挑战、深层原因、本质是什么、批判地看 |
| 跨域联想 | 跨界视角、换个角度、类比一下、新视角、别的领域、借鉴一下 |
| 知识操作 | 入库、记录这条、保存知识、知识审查 |
### 优点
- **零延迟**:字符串匹配,毫秒级
- **零依赖**:不需要调用任何模型
- **确定性**:100% 可预测,不会误触发
### 缺点
- **漏匹配**:用户说"换个思路"不会触发"换个角度";说"从别的学科看看"不会触发"跨界视角"
- **维护成本**:需要人工维护触发词列表,不断追加变体
- **僵化**:没法处理同义表达
---
## 二、升级方案:语义相似度匹配
**工作原理**:用现有 Qwen3-Embedding-0.6B 模型,把用户消息转为向量,与触发类别种子词的向量计算相似度。
### 架构
```
用户消息: "从这个角度看有点像生物学里的共生关系"
↓
调 Embedding API → 转为 1024 维向量
↓
与各触发类别的种子词向量做余弦相似度
↓
跨域联想类别: 相似度 0.89(阈值 0.8)→ 触发 ✅
升维审视类别: 相似度 0.45 → 不触发 ❌
```
### 种子词设计
| 类别 | 种子词(3-5 个示例,模型自动泛化) |
|------|-----------------------------------|
| 升维审视 | 升维、本质、第一性原理、前提挑战、深层原因 |
| 跨域联想 | 跨界、类比、换个角度、别的领域、借鉴 |
| 知识操作 | 入库、记录、保存、知识审查 |
不需要穷举,Embedding 模型会自动处理近义词。
### 优点
| 维度 | 关键词匹配 | 语义相似度 |
|------|-----------|-----------|
| 覆盖范围 | 仅精确匹配列表中的词 | 自动覆盖同义词、近义表达 |
| 维护成本 | 需手动追加变体 | 种子词固定,无需频繁维护 |
| 灵活性 | 僵化 | 自然 |
### 缺点
| 维度 | 影响 | 评估 |
|------|------|------|
| 延迟 | 每次调用 Embedding API | ~50-100ms,相对 LLM 响应时间(3-30s)可忽略 |
| 依赖 | 需要 oMLX 运行 Embedding 模型 | 各机器需确保 Embedding 模型已加载 |
| 误触发 | 语义相似但不相关的表达可能过阈值 | 可调整阈值(建议 0.8)+ 结合关键词兜底 |
| 实现复杂度 | 需维护种子词向量 + 相似度计算逻辑 | 约 50 行 Python 代码 |
---
## 三、速度影响实测
```
纯关键词匹配: 0ms
+ Embedding API 调用: 50-100ms
LLM 生成响应: 3,000-30,000ms
增加的比例: 约 0.3%-3% → 无感知
```
**结论:对用户体验无影响。**
---
## 四、建议方案:混合匹配
```
收到用户消息
↓
第一步:关键词快速匹配(0ms)
├─ 命中 → 直接触发 ✅(极速)
└─ 未命中 → 进入第二步
↓
第二步:语义相似度计算(50-100ms)
├─ 相似度 ≥ 0.8 → 触发 ✅
└─ 相似度 < 0.8 → 不触发 ❌
```
### 好处
- 常见触发词(用户明确说的)0ms 响应
- 边缘表达也能覆盖(语义泛化)
- 关键词作为第一道防线,减少 Embedding 调用频率
---
## 五、多机同步影响
| 项目 | 影响 | 说明 |
|------|------|------|
| **触发词列表** | ❌ 不需要修改 | 种子词写在 SOUL.md 中,Git 同步即可 |
| **种子词向量** | ⚠️ 需每台机器生成 | 各机器第一次使用时自动计算并缓存 |
| **Embedding 模型** | ✅ 各机器已有 | Qwen3-Embedding-0.6B 已在 oMLX 中加载 |
| **相似度计算代码** | ⚠️ 需写一个轻量脚本 | ~50 行 Python,Git 同步 |
| **向量库** | ❌ 不受影响 | 记忆向量和知识向量不变 |
| **知识库** | ❌ 不受影响 | 知识库内容不变 |
**综合评估**:升级成本很低,无破坏性影响,各机器各自运行 Embedding 模型即可。
---
## 六、最终建议
| 选项 | 做法 | 推荐程度 |
|------|------|---------|
| **A:保持关键词匹配** | 维持现状,手动维护触发词列表 | ⭐ 够用 |
| **B:纯语义相似度** | 完全依赖 Embedding | ⭐⭐ |
| **C:混合模式** | 关键词 + 语义兜底 | ⭐⭐⭐ **推荐** |
**推荐选 C**:关键词负责"快",语义负责"全"。先关键词匹配(0ms),未命中再调 Embedding(50-100ms)。大部分情况下用户会直接说触发词,关键词匹配就够了。
@@ -0,0 +1,195 @@
# CORE-ARCHITECTURE.md —— AgentOS 核心架构说明
> 本文档是 AgentOS 的"宪法",定义了目录职责、数据边界、换机流程。
> 最后更新:2026-05-02 | 版本:3.0 多智能体协同
---
## 一、系统定位
AgentOS 是一套运行在个人 Mac 上的**多智能体协同系统**,核心能力:
- **多机协同**:主节点(master) + 工作节点(maintainer) + 采集节点(node) 分级协作
- **身份驱动**:角色决定权限,所有脚本运行前自动检查
- **全量Git跟踪**:agent-sync/ 全量进 Git,不搞选择性部分跟踪
---
## 二、目录职责
### `~/workbuddy-agent-os/agent-sync/`(坚果云同步 + Git 版本控制)
| 目录 | 职责 | 同步 | Git |
|------|------|------|-----|
| `00_bootstrap/` | 初始化脚本(init.sh、apply-config.sh) | ✅ | ✅ |
| `01_core/` | 核心配置(SOUL.md、IDENTITY.md、USER.md、mcp.json) | ✅ | ✅ |
| `02_skills/` | 所有技能(每个技能一个文件夹,含 SKILL.md) | ✅ | ✅ |
| `03_knowledge/` | Obsidian 知识库(只放提炼后的 .md 文件) | ✅ | ✅ |
| `04_memory/` | 记忆体(L2 facts.db + L1 索引 + 日志) | ✅ | ✅ |
| `05_tools/` | 公共工具脚本(环境检查、爬虫、媒体处理) | ✅ | ✅ |
| `06_runtime/tasks/` | 任务执行记录 | ✅ | ✅ |
| `07_migration/` | 打包/还原脚本 | ✅ | ✅ |
| `CHANGELOG.md` | 变更日志 | ✅ | ✅ |
| `README.md` | 项目说明 | ✅ | ✅ |
| `REQUIREMENTS.md` | 环境要求 | ✅ | ✅ |
| `SKILLS-CATALOG.md` | 技能目录 | ✅ | ✅ |
| `CORE-ARCHITECTURE.md` | 本文档 | ✅ | ✅ |
### `~/workbuddy-agent-os/agent-local/`(本机专属,不同步,不进 Git)
```
agent-os-local/
├── memory/ # 记忆体相关(软链接目标)
│ ├── raw/ # L3 对话原文(隐私)
│ └── vector_db/ # ChromaDB + 关键词索引
├── runtime/ # 运行时临时数据
│ └── cache/ # 临时缓存
└── materials/ # 采集的原始素材
├── web/ # 网页保存
├── video/ # 视频下载(yt-dlp 输出)
├── audio/ # 录音文件
├── screenshots/ # 截图
└── refined_for_inbox/ # 已提炼待投递的 .md
```
> `agent-os/` 内通过**软链接**指向 `agent-os-local/` 中的实际目录,脚本无需改路径。
---
## 三、软链接映射
```
~/workbuddy-agent-os/agent-sync/04_memory/long_term/raw → ~/workbuddy-agent-os/agent-local/memory/raw
~/workbuddy-agent-os/agent-sync/04_memory/vector_db → ~/workbuddy-agent-os/agent-local/memory/vector_db
~/workbuddy-agent-os/agent-sync/06_runtime/cache → ~/workbuddy-agent-os/agent-local/runtime/cache
```
换机时 `init.sh` 会自动检测并重建这些软链接。
---
## 四、技能分类规则
### system 技能(后台自动运行,不直接对话触发)
| 技能 | 说明 |
|------|------|
| `memory_manager` | 记忆提炼、去重、语义检索 |
| `inbox_refine` | 收件箱提纯→知识库归档 |
| `collect_to_inbox` | 知识库目录扫描→收件箱 |
| `auto_collector` | 24h 自动信息收集 |
| `sync_manager` | 备份与同步管理 |
| `kb_manager` | 知识库入库与管理 |
### user 技能(对话触发)
| 技能 | 说明 |
|------|------|
| `content_processor` | 统一内容处理(视频/文章/语音/社交) |
| `web_crawler` | 网页抓取 + 反爬 |
| `git_sync_manager` | Git多机同步管理器(替代坚果云依赖) |
---
## 五、知识库索引卡片规范
多台电脑采集的素材通过**索引卡片**共享,避免大文件同步冲突。
### 文件命名
```
{hostname}_{YYYYMMDD}_{slug}.md
示例:Redmi-12C_20260428_douyin-普通人逆袭.md
MBP-M3_20260428_bilibili-科普冷知识.md
```
### 卡片模板
```markdown
---
title: 素材标题
source_url: https://...
local_path: ~/workbuddy-agent-os/agent-local/materials/video/xxx.mp4
type: video|audio|web|image
platform: douyin|xiaohongshu|bilibili|web
collected_by: Redmi-12C
collected_at: 2026-04-28
tags: [标签1, 标签2]
---
一句话说明这个资源的口播改编价值。
```
> `collected_by` 字段标明采集机器,防止多机同步时同名冲突。
---
## 六、同步策略
### 坚果云
- 同步整个 `~/workbuddy-agent-os/agent-sync/` 目录
- `~/workbuddy-agent-os/agent-local/` 不加入同步(通过软链接隔离,天然安全)
- 无需配置选择性排除
### Git
- 远程仓库:`https://gitee.com/babycalf/mac-agent-os.git`
- 分支策略:main 分支,单线开发
- 排除:大媒体文件、运行时缓存、打包产物(见 `.gitignore`)
### Git同步技能(替代坚果云)
使用 `git_sync_manager` 技能可完全替代坚果云依赖:
1. **首次配置**:技能引导完成SSH密钥生成、Gitee公钥添加、仓库配置
2. **日常同步**:一键执行 `git pull` / `git push` 操作
3. **多机管理**:每台电脑使用独立SSH密钥,安全隔离
4. **自动化**:可配置定时任务或通过 `agentos sync` 命令触发
### 数据流
```
本机采集 → ~/workbuddy-agent-os/agent-local/materials/ → AI提炼 → ~/workbuddy-agent-os/agent-sync/03_knowledge/00_inbox/
↓ 坚果云同步
↓
其他电脑 → inbox_refine → 归档到知识库 → Git commit → Gitee
```
---
## 七、换机还原流程(3步)
```bash
# 1. 等坚果云同步完成,agent-os 目录出现在本机
# 2. 安装基础环境
cd ~/workbuddy-agent-os/agent-sync/00_bootstrap && bash init.sh
# 3. 手动安装 oMLX(Apple MLX 框架,硬件依赖)
```
`init.sh` 会自动完成:
- 创建 `~/workbuddy-agent-os/agent-local/` 各子目录
- 重建 3 个软链接(raw、vector_db、cache)
- 创建 Python venv 并安装依赖
- 填充本机设备信息到 IDENTITY.md
- 部署核心配置(SOUL.md、USER.md)到 WorkBuddy
- 检测并提示需要手动安装的组件
---
## 八、定时任务
| 任务 | 时间 | 脚本 | 说明 |
|------|------|------|------|
| 每日记忆提炼 | 02:00 | `memory_manager/daily_digest.py` | 对话→L2 事实 |
| 收件箱汇聚 | 02:30 | `collect_to_inbox/collect_to_inbox.py` | 知识库扫描→inbox |
| 收件箱提纯 | 03:00 | `inbox_refine/inbox_refine.py` | inbox→分类归档 |
---
## 九、运行时外挂(不属于仓库)
以下组件由系统管理,不进 Git,换机时需手动安装:
| 组件 | 路径 | 说明 |
|------|------|------|
| oMLX | `/Applications/oMLX.app` | 本地 LLM 引擎 |
| WorkBuddy Python | `~/.workbuddy/binaries/python/` | WorkBuddy 管理的运行时 |
| WorkBuddy Node | `~/.workbuddy/binaries/node/` | WorkBuddy 管理的运行时 |
| Playwright 浏览器 | `~/Library/Caches/ms-playwright/` | `playwright install chromium` 重装 |
| 坚果云客户端 | `/Applications/Nutstore.app` | 系统应用 |
@@ -0,0 +1,22 @@
# 03_knowledge/99_system/ 归档文件
以下文件已从 99_system/ 根目录移入 archive/ 子目录:
## 归档清单
| 原文件 | 归档日期 | 理由 |
|:-------|:---------|:------|
| ARCHITECTURE_AUDIT.md | 2026-06-21 | 一次性审计报告,历史价值 |
| ARCHITECTURE_CONSTITUTION.md | 2026-06-21 | 旧版架构文档,已被替代 |
| ARCHITECTURE_v3.md | 2026-06-21 | 旧版架构文档 |
| TRANSFORMATION_ROADMAP.md | 2026-06-21 | 旧路线图,已完成或过时 |
| 2026-06-01_2026-05-17_..._统一升级引擎.md | 2026-06-21 | 文件名异常长,inbox_refine bug 产物 |
| AgentOS-原子操作体系-v2_副本2/ | 2026-06-21 | 目录副本,内容重复 |
## 移动至其他目录的文件
| 原文件 | 新位置 | 理由 |
|:-------|:-------|:------|
| agent-os-memory-knowledge-architecture.md | architecture/ | 归入架构目录 |
| memory-index.md | architecture/ | 归入架构目录 |
| dashboard-v4-design.md | dashboard/ | 归入看板目录 |
@@ -0,0 +1,201 @@
# AgentOS 快速上手
> 版本 3.0 | 多智能体协同模式
## 前置条件
- ✅ **WorkBuddy 桌面客户端**([codebuddy.cn](https://www.codebuddy.cn) 下载)— 必需
- ✅ **Git**(macOS 自带)— 代码同步必需
- ✅ **Gitee 或 GitHub 账号** — 用于多机协同
- ⬜ **Obsidian**([obsidian.md](https://obsidian.md) 下载)— 推荐,浏览知识库
> Python 和 Node.js 由 WorkBuddy 自动管理,**不需要手动安装**。
---
## 新机器部署流程
### 1. 克隆仓库
```bash
git clone [email protected]:babycalf/mac-agent-os.git ~/workbuddy-agent-os/agent-sync
cd ~/workbuddy-agent-os/agent-sync
```
> 如果 SSH 未配置,用 `git_sync_manager` 技能引导配置。
### 2. 一键初始化
```bash
bash 00_bootstrap/init.sh
```
脚本自动完成:
- 创建 `agent-local/` 目录结构(identity/memory/materials/submissions...)
- 重建 3 条软链接(raw/vector_db/cache)
- 安装 Python 依赖
- 检测设备和系统信息
- 创建 L1 关键词索引
### 3. 生成本机身份
```bash
agentos localize
```
执行后:
- `agent-local/identity/IDENTITY.md` — 本机身份(含主机名、路径等)
- `agent-local/identity/USER.md` — 用户信息
- `agent-local/identity/HOST_ID.md` — **本机角色 + 能力开关**
**关键步骤**:编辑 `HOST_ID.md` 设置角色:
```yaml
# 选择一种角色:
# master → 知识提纯/记忆汇总/核心维护(推荐主电脑)
# maintainer → 内容采集/本地记忆/提交价值内容(推荐工作机)
# node → 信息采集/素材上传(推荐轻量设备)
角色: master
```
> 角色决定自动化任务:master 自动执行 inbox_refine,其他角色跳过。
### 4. 同步技能到 WorkBuddy
```bash
agentos sync
```
将 `02_skills/` 下的技能注册到 WorkBuddy,同时部署 MCP 配置。
### 5. 升级依赖
```bash
agentos upgrade
```
拉取最新代码 + 安装依赖 + 环境检查。
### 6. 重建向量数据库
```bash
agentos rebuild-vector
```
在本地重建语义检索索引(升级后必须执行)。
### 7. 验证系统状态
```bash
agentos check
```
---
## 日常使用流程
### 拉取最新代码
```bash
cd ~/workbuddy-agent-os/agent-sync && git pull
```
### 主节点(master)操作
```bash
# 查看待提纯内容
ls 03_knowledge/01_submissions/
# 手动触发收件箱提纯
agentos skill run inbox_refine
# 查看各节点提交
find 03_knowledge/01_submissions/ -name "*.md"
# 提交变更到协同仓库
git add -A
git commit -m "知识库更新摘要"
git push
```
### 工作/采集节点操作
```bash
# 提交知识内容
cp 提炼后的笔记.md ~/workbuddy-agent-os/agent-local/submissions/inbox/
# 然后 git commit + git pull request 或手动同步
# 本机记忆提炼(自动运行)
# 结果保存在 agent-local/memory/daily/
```
### 升级流程
```bash
git pull
agentos upgrade
agentos rebuild-vector
```
---
## 角色行为速查
| 场景 | master | maintainer | node |
|------|--------|------------|------|
| 本地记忆提炼 | ✅ 自动 | ✅ 自动 | ✅ 自动 |
| 内容采集 | ✅ 自动 | ✅ 自动 | ✅ 自动 |
| 知识库提纯 | ✅ 自动 | ⛔ 跳过 | ⛔ 跳过 |
| Git 推送 | ✅ 自动 | ❌ 手动 | ❌ 手动 |
| 提交有价值内容 | — | ✅ 通过 submissions | ✅ 通过 submissions |
| 向量库重建 | ✅ 升级后执行 | ✅ 升级后执行 | ✅ 升级后执行 |
---
## 验证
```bash
# 1. 检查角色
cat ~/workbuddy-agent-os/agent-local/identity/HOST_ID.md
# 2. 检查角色检查工具
python3 ~/workbuddy-agent-os/agent-sync/05_tools/01_system/role_check.py
# 3. 检查向量库状态
agentos rebuild-vector --dry-run
# 4. 检查 Git 状态
cd ~/workbuddy-agent-os/agent-sync && git status
```
---
## 多机首次协同设置
```bash
# 机器A(master):
git clone ... && bash init.sh && agentos localize
# 编辑 HOST_ID.md → role: master
agentos sync && agentos upgrade && agentos rebuild-vector
# 机器B(maintainer):
git clone ... && bash init.sh && agentos localize
# 编辑 HOST_ID.md → role: maintainer
agentos sync && agentos upgrade && agentos rebuild-vector
# 机器B 采集后提交:
cp 内容 ~/agent-local/submissions/inbox/
cd ~/agent-sync && git add -A && git commit -m "提交内容" && git push
# 机器A 提纯发布:
cd ~/agent-sync && git pull
# → inbox_refine 自动检测 submissions/ 中的新内容
# → 审核后发布到知识库 → git push
# 机器B 获取最新知识库:
cd ~/agent-sync && git pull
```
---
🎉 **完成!** 你的多智能体联邦已就绪。各节点按角色自动运行对应任务。
@@ -0,0 +1,324 @@
# AgentOS 技能清单与部署手册 v2.0
> 最后更新:2026-05-02 | 设备:MacBook Air M1 8GB | 系统:macOS 26.4
---
## 一、快速指令对照表
| 指令 | 技能 | 动作 |
|------|------|------|
| `转笔记` | content_processor → bilinote | 视频→结构化笔记 |
| `摘字幕` | content_processor → bilinote | 仅语音转文字 |
| `视频摘要` | content_processor → bilinote | 提炼核心观点 |
| `视频大纲` | content_processor → bilinote | 层级内容大纲 |
| `剪藏` | content_processor → web-clipper | 网页→Markdown |
| `摘抄` | content_processor → web-clipper | 保存全文 |
| `文章摘要` | content_processor → web-clipper | 3 句话概括 |
| `提炼` | content_processor → web-clipper | 方法论/步骤/结论 |
| `翻译` | content_processor → web-clipper | 翻译成中文 |
| `语音摘要` | content_processor → voice-summary | 语音→核心要点 |
| `转文字` | content_processor → voice-summary | 逐字稿 |
| `采集` | content_processor → social-collector | 小红书/抖音→笔记 |
| `采集摘要` | content_processor → social-collector | 采集+AI总结 |
| `开始收集` | auto_collector | 启动 24h 监控 |
| `停止收集` | auto_collector | 暂停监控 |
| `收集报告` | auto_collector | 今日采集摘要 |
| `记忆更新` | memory_manager | 手动触发记忆提炼 |
| `入库` | kb_manager | 知识入库(→ 00_inbox/) |
| `归集` | collect_to_inbox | 分类目录→收件箱 |
| `收集到收件箱` | collect_to_inbox | 手动触发汇聚 |
| `提纯` | inbox_refine | 收件箱提纯归档 |
| `整理收件箱` | inbox_refine | 手动触发提纯 |
| `抓取` | web_crawler | 网页抓取+反爬 |
| `备份知识库` | sync_manager | 全量备份 |
| `git同步` | git_sync_manager | SSH配置+Git同步(替代坚果云) |
| `SSH配置` | git_sync_manager | 生成SSH密钥并配置Gitee |
| `多机同步` | git_sync_manager | 多台电脑间同步代码 |
---
## 二、技能详览
### 1. memory_manager(记忆管理)
| 属性 | 值 |
|------|-----|
| 版本 | 1.1.0 |
| 位置 | `~/workbuddy-agent-os/agent-sync/02_skills/memory_manager/` + `~/.workbuddy/skills/memory_manager/` |
| 触发词 | 记忆更新、每日提炼、整理记忆、记忆检查、查记忆 |
| 核心脚本 | `daily_digest.py`、`bootstrap_from_memory.py`、`memory_cleanup.py`、`agent_memory_init.py` |
| 依赖 | sqlite-utils ✅、sqlite3(标准库) ✅ |
### 2. kb_manager(知识库管理)
| 属性 | 值 |
|------|-----|
| 版本 | 1.1.0 |
| 位置 | `~/workbuddy-agent-os/agent-sync/02_skills/kb_manager/` + `~/.workbuddy/skills/kb_manager/` |
| 触发词 | 入库、保存知识、知识分类、查知识库、ingest、kb |
| 核心脚本 | `kb_ingest.py` |
| 入库目标 | `03_knowledge/00_inbox/`(收件箱,待提纯) |
| 依赖 | trafilatura ✅、chromadb ✅、sqlite-utils ✅ |
### 3. inbox_refine(收件箱提纯)
| 属性 | 值 |
|------|-----|
| 版本 | 1.0.0 |
| 位置 | `~/workbuddy-agent-os/agent-sync/02_skills/inbox_refine/` + `~/.workbuddy/skills/inbox_refine/` |
| 触发词 | 提纯、整理收件箱、归档inbox、inbox refine |
| 核心脚本 | `inbox_refine.py` |
| 自动化 | 每日凌晨 3:00(WorkBuddy automation `agentos-2`) |
| 前置步骤 | collect_to_inbox(每日 2:30 先汇聚到收件箱) |
| 流程 | 00_inbox/ → 分类 → 应用模板 → 写入目标目录 → 更新首页 → 更新 CHANGELOG |
| 依赖 | python3 ✅、file_read/write ✅、oMLX+Qwen3-8B-MLX-4bit ✅(可选) |
### 4. collect_to_inbox(分类目录汇聚收件箱)★ 新增
| 属性 | 值 |
|------|-----|
| 版本 | 1.0.0 |
| 位置 | `~/workbuddy-agent-os/agent-sync/02_skills/collect_to_inbox/` + `~/.workbuddy/skills/collect_to_inbox/` |
| 触发词 | 归集、收集到收件箱、汇聚收件箱、collect inbox |
| 核心脚本 | `collect_to_inbox.py` |
| 自动化 | 每日凌晨 2:30(WorkBuddy automation `agentos-3`) |
| 扫描目录 | 50_resources/视频笔记、50_resources/字幕存档、50_resources/阅读笔记、50_resources/全文存档、50_resources/翻译存档、50_resources/灵感素材、50_resources/语音转写、20_methods/、01_daily/闪念笔记、40_references/ |
| 流程 | 扫描各分类目录 → 提取主要内容 → 生成标准化 MD → 写入 00_inbox/ → 标记原文件已收集 |
| 依赖 | python3 ✅ |
### 5. auto_collector(24h 自动收集)
| 属性 | 值 |
|------|-----|
| 版本 | 1.0.0 |
| 位置 | `~/workbuddy-agent-os/agent-sync/02_skills/auto_collector/` + `~/.workbuddy/skills/auto_collector/` |
| 触发词 | 开始收集、停止收集、收集状态、收集报告、监控 |
| 监控源 | RSS/B站/小红书/抖音/网页 |
| 依赖 | feedparser ✅、schedule ✅、@tikomni/skills ✅、crawl4ai ✅ |
| 待部署 | BiliNote Docker(视频监控) |
### 6. content_processor(统一内容处理)
| 属性 | 值 |
|------|-----|
| 版本 | 1.0.0 |
| 位置 | `~/workbuddy-agent-os/agent-sync/02_skills/content_processor/` + `~/.workbuddy/skills/content_processor/` |
| 触发词 | 转笔记/剪藏/语音摘要/采集/摘抄/提炼/翻译 等 |
| 路由 | → bilinote / web-clipper / voice-summary / social-collector |
| 依赖 | trafilatura ✅、whisper ✅、@tikomni/skills ✅、crawl4ai ✅ |
### 7. web_crawler(网页抓取+反爬)
| 属性 | 值 |
|------|-----|
| 版本 | 1.1.0 |
| 位置 | `~/workbuddy-agent-os/agent-sync/02_skills/web_crawler/` + `~/.workbuddy/skills/web_crawler/` |
| 触发词 | 抓取、爬取、crawl、fetch |
| 引擎 | Scrapling(三模式) + Crawl4AI + Playwright+Stealth |
| 依赖 | scrapling ✅、crawl4ai ✅、playwright ✅、playwright-stealth ✅ |
| 待解决 | Playwright Chromium 浏览器下载(网络问题) |
### 8. sync_manager(同步管理)
| 属性 | 值 |
|------|-----|
| 版本 | 1.1.0 |
| 位置 | `~/workbuddy-agent-os/agent-sync/02_skills/sync_manager/` + `~/.workbuddy/skills/sync_manager/` |
| 触发词 | 备份知识库、导出知识库、同步状态 |
| 同步方式 | 坚果云(`~/NutstoreCloudBridge/`) |
| 依赖 | 坚果云 ✅、tar/gzip(系统自带) ✅ |
### 9. git_sync_manager(Git多机同步管理器)
| 属性 | 值 |
|------|-----|
| 版本 | 1.0.0 |
| 位置 | `~/.workbuddy/skills/git_sync_manager/` |
| 触发词 | git同步、SSH配置、多机同步、替代坚果云 |
| 核心功能 | SSH密钥生成、Gitee公钥配置、仓库设置、一键同步 |
| 同步方向 | pull(拉取)、push(推送)、both(双向) |
| 依赖 | Git ✅、SSH ✅、Gitee账号 ✅ |
| 安全设计 | 不存储私钥、使用占位符配置、权限严格控制 |
### 10. bilinote(视频→结构化笔记)
| 属性 | 值 |
|------|-----|
| 位置 | `~/.workbuddy/skills/bilinote/` |
| 触发词 | 转笔记、摘字幕、视频摘要、视频大纲 |
| 依赖 | BiliNote Docker ⚠️ 待部署 |
### 8. web-clipper(网页→Markdown)
| 属性 | 值 |
|------|-----|
| 位置 | `~/.workbuddy/skills/web-clipper/` |
| 触发词 | 剪藏、摘抄、文章摘要、提炼、翻译 |
| 依赖 | trafilatura ✅ |
| 状态 | ✅ 可用 |
### 9. voice-summary(语音→核心要点)
| 属性 | 值 |
|------|-----|
| 位置 | `~/.workbuddy/skills/voice-summary/` |
| 触发词 | 语音摘要、转文字、闪念笔记 |
| 依赖 | openai-whisper ✅ |
| 状态 | ✅ 文字可用 |
### 10. social-collector(小红书/抖音→笔记)
| 属性 | 值 |
|------|-----|
| 位置 | `~/.workbuddy/skills/social-collector/` |
| 触发词 | 采集、采集摘要 |
| 依赖 | @tikomni/skills ✅ |
| 状态 | ✅ 可用 |
### 11. tikomni-data(跨平台数据引擎)
| 属性 | 值 |
|------|-----|
| 位置 | `~/.workbuddy/skills/tikomni-data/` |
| 触发词 | tikomni、提取数据 |
| 依赖 | @tikomni/skills ✅ |
| 状态 | ✅ 可用 |
### 12. obsidian(Obsidian Vault 操作)
| 属性 | 值 |
|------|-----|
| 位置 | `~/.workbuddy/skills/obsidian/` |
| 状态 | ✅ 可用 |
### 13. Playwright Scraper(浏览器抓取)
| 属性 | 值 |
|------|-----|
| 位置 | `~/.workbuddy/skills/Playwright Scraper/` |
| 状态 | ✅ 可用 |
---
## 三、完整依赖清单
### Python 依赖(agent-os venv)
| 包 | 版本 | 用途 | 安装状态 |
|---|---|---|---|
| trafilatura | 2.0.0 | 网页内容提取 | ✅ |
| sqlite-utils | 3.39 | SQLite 增强 | ✅ |
| feedparser | latest | RSS 解析 | ✅ |
| schedule | latest | 定时任务 | ✅ |
| chromadb | latest | 向量数据库 | ✅ |
| scrapling | latest | 三引擎反爬抓取 | ✅ |
| crawl4ai | latest | LLM 友好结构化抓取 | ✅ |
| playwright | 1.58.0 | 浏览器自动化 | ✅ |
| playwright-stealth | latest | 反检测 | ✅ |
| openai-whisper | latest | 语音转文字 | ✅ |
| stagehand | latest | 复杂页面交互 | ✅ |
**安装命令**:
```bash
# 所有 pip 包一条命令安装
/Users/chengzige/.workbuddy/binaries/python/envs/agent-os/bin/pip install \
trafilatura sqlite-utils feedparser schedule chromadb \
scrapling 'crawl4ai[all]' playwright playwright-stealth \
openai-whisper stagehand
```
### Node.js 依赖
| 包 | 用途 | 安装状态 |
|---|---|---|
| @tikomni/skills | 小红书/抖音数据采集 | ✅ |
**安装命令**:
```bash
cd /Users/chengzige/.workbuddy/binaries/node/workspace && \
NODE_PATH=/Users/chengzige/.workbuddy/binaries/node/versions/22.12.0/bin/node \
/Users/chengzige/.workbuddy/binaries/node/versions/22.12.0/bin/npm install @tikomni/skills
```
### 系统/外部依赖
| 软件 | 安装方式 | 用途 | 状态 |
|---|---|---|---|
| oMLX | 官网下载 / App Store | 本地 LLM 运行(MLX 框架) | ✅ 已安装 v0.3.6 |
| Obsidian | 官网下载 | 知识库管理 | ✅ 已安装 |
| Playwright Chromium | `playwright install chromium` | 浏览器引擎 | ⚠️ 待下载 |
| BiliNote Docker | Docker 部署 | 视频转笔记 | ⚠️ 待部署 |
| yt-dlp | `brew install yt-dlp` | 视频下载 | ⚠️ 需 brew |
| ffmpeg | `brew install ffmpeg` | 音视频转换 | ⚠️ 需 brew |
| ScreenPipe | `brew install screenpipe` | 屏幕录制 OCR | ⚠️ 需 brew |
| Homebrew | 官网安装脚本 | 包管理器 | ❌ 未安装 |
| jq | 系统自带 | JSON 处理 | ✅ |
---
## 四、环境配置
### 固定路径
```
# Python
MANAGED_PYTHON=/Users/chengzige/.workbuddy/binaries/python/versions/3.13.12/bin/python3
AGENTOS_PYTHON=/Users/chengzige/.workbuddy/binaries/python/envs/agent-os/bin/python3
AGENTOS_VENV=/Users/chengzige/.workbuddy/binaries/python/envs/agent-os
# Node.js
MANAGED_NODE=/Users/chengzige/.workbuddy/binaries/node/versions/22.12.0/bin/node
NODE_WORKSPACE=/Users/chengzige/.workbuddy/binaries/node/workspace
# agent-os
AGENTOS_ROOT=~/workbuddy-agent-os/agent-sync
# 知识库
KNOWLEDGE_BASE=~/workbuddy-agent-os/agent-sync/03_knowledge/
# 坚果云
NUTSTORE=~/NutstoreCloudBridge/
```
### 迁移到新机器时
1. 安装 WorkBuddy(自动提供 managed Python/Node)
2. 创建 agent-os venv:
```bash
$MANAGED_PYTHON -m venv $AGENTOS_VENV
$AGENTOS_VENV/bin/pip install -r ~/workbuddy-agent-os/agent-sync/requirements.txt
```
3. 安装 Node 依赖:
```bash
cd $NODE_WORKSPACE && npm install @tikomni/skills
```
4. 安装 Homebrew → `brew install yt-dlp ffmpeg screenpipe`
5. 安装 Obsidian
6. 部署 BiliNote Docker
7. 运行 `playwright install chromium`
8. 运行冷启动:`$AGENTOS_PYTHON ~/workbuddy-agent-os/agent-sync/02_skills/memory_manager/bootstrap_from_memory.py --root ~/workbuddy-agent-os/agent-sync`
---
## 五、自动化任务
| 任务 | 频率 | 命令 |
|------|------|------|
| 每日记忆提炼 | 每日 2:00 | `$AGENTOS_PYTHON ~/workbuddy-agent-os/agent-sync/02_skills/memory_manager/daily_digest.py --root ~/workbuddy-agent-os/agent-sync` |
| 分类目录汇聚收件箱 | 每日 2:30 | `$AGENTOS_PYTHON ~/workbuddy-agent-os/agent-sync/02_skills/collect_to_inbox/collect_to_inbox.py --root ~/workbuddy-agent-os/agent-sync` |
| 知识库收件箱提纯 | 每日 3:00 | `$AGENTOS_PYTHON ~/workbuddy-agent-os/agent-sync/02_skills/inbox_refine/inbox_refine.py --root ~/workbuddy-agent-os/agent-sync` |
| RSS 检查 | 每小时 | auto_collector |
| 社交平台检查 | 每 2 小时 | auto_collector + TikOmni |
| 网页变化检查 | 每小时 | auto_collector + Crawl4AI |
| 采集日报 | 每日 23:00 | auto_collector 汇总 |
---
## 六、待解决项
| 项目 | 优先级 | 说明 |
|------|--------|------|
| Playwright Chromium | 中 | 网络问题导致下载失败,需换网络重试 |
| Homebrew | 中 | 可选,安装后可装 yt-dlp/ffmpeg/screenpipe |
| BiliNote Docker | 低 | 视频转笔记核心依赖,需 Docker Desktop |
@@ -0,0 +1,183 @@
# Dashboard 修复记录 2026-06-22
## 1. SMS 页面账号下拉为空 + 5秒超时
**症状**: 短信接收页面点击"选择账号"搜索框,下拉列表为空或显示"⏳ 账号列表加载中...",等5秒后才出现。
**根因**: `modules/corpus.js` 定义了同名的 `loadSmsProxy`、`loadSmsAccounts` 等函数,覆盖了 `inline.js` 的正确版本。
```
import 顺序:
inline.js → 定义 loadSmsProxy (正确版: 用 Promise.all + await)
corpus.js → 覆盖 window.loadSmsProxy (bug版: 无 await, fire-and-forget)
```
corpus.js 版的 `loadSmsAccounts` 先请求 `/api/federation/accounts`(该端点5秒超时),再 fallback 到本地 `/api/matrix/sms/accounts`。
**修复**: 移出 corpus.js 中 `loadSmsProxy` 函数定义,移除所有覆盖 inline.js 的 SMS 相关 window 赋值(14项)。
**教训**: 同一函数在多文件中定义时,通过 import 顺序决定哪个版本胜出。这种隐式覆盖很容易出 bug。要么只在一个文件中定义,要么在覆盖时显式注释说明。
---
## 2. 机器状态显示离线
**症状**: 顶部状态栏显示"机器数 2 在线 0";底部机器条显示所有远程机器离线。
**根因**:
- 顶部状态栏:`loadStats()` 从 AVE 插件读取数据(AVE 只记录了2台机器)
- 底部机器条:`loadMachineBar()` 用 `/api/federation/health`(该端点返回空)
**修复**:
- 顶部改用 guardd 插件数据(总机器3,在线3)
- 底部改用 `/api/machines` API 的 `status` 字段
**教训**: 多数据源共存时,要明确哪个是权威源。`/api/machines` 是机器状态的权威源。
---
## 3. 账号归属错误
**症状**: `xhs_01` 被 chengzigedeAir 认领(OARCLE 规定属于 5kechengdeAir),6个账号归属错误。
**根因**: WPRA 去重后未用 ORACLE.yaml 覆盖 `owner_machine`。
**修复**: 在 `list_accounts()` 去重后,用 ORACLE.yaml 的 `accounts:` 节覆盖 `assigned_machine`/`owner_machine`。
**教训**: ORACLE.yaml 是账号归属的宪法,所有数据聚合后必须以 ORACLE 为准。
---
## 4. 账号 is_local 与 ORACLE 冲突
**症状**: `xhs_01` 的 `is_local=True` 但 `owner_machine=5kechengdeAir`,导致前端排序把远程账号误判为本机。
**根因**: `is_local()` 函数第1162行 `if acct["id"] in override_map: return True`——只要本地有身份目录就直接判为本机,跳过了第1166行的 `_all_assignments` 兜底检查。但 ORACLE 已经把这个账号分配给了 5kechengdeAir。
**修复**: 在 override_map 匹配后加一道 ORACLE 检查:如果 `assigned_machine`(已被 ORACLE 覆盖)不是本机,返回 False。
**教训**: 数据源覆盖顺序:identity目录 < WPRA < ORACLE.yaml。下层数据不能推翻上层的决策。
---
## 5. corpus.js 中 _renderAccountSelector 覆盖 inline.js
**症状**: 账号选择器在部分页面表现不一致。
**根因**: `_loadAccounts` 和 `_renderAccountSelector` 在 inline.js 和 corpus.js 中各有定义。corpus.js 后导入,覆盖了 inline.js 的版本。
**修复**: 在 inline.js 末尾添加别名重定向:
```javascript
_loadAccounts = window._loadAccounts;
_renderAccountSelector = window._renderAccountSelector;
```
并移除 inline.js 中9处被覆盖的 window 赋值。
**教训**: 模块化拆分时,被拆出的函数必须从原始文件中移除,否则会出现两份定义。
---
## 6. 账号选择器参数不一致
**症状**: 不同页面的账号选择器高度、搜索框显示、默认全选状态不一致。
**根因**: 5处 `_renderAccountSelector` 调用使用了不同的参数:
- `height: '300px'` vs `'350px'` vs `'280px'`
- `checkAll: false` vs 默认 true
- `hideFilter: true` vs 默认 false
**修复**: 全部统一为 `{_data: data, height: '350px'}`。
**教训**: 共享组件必须统一参数。所有调用方应使用相同的配置。
---
## 7. 蓝图管理 [object Object] 显示
**症状**: 蓝图管理页面显示 `1. [object Object] · 2. [object Object] · ... 80. [object Object]`
**根因**: 这是一个**连环 bug**,涉及三层问题:
### 第1层:迁移视图拦截(最外层)
`views/matrix-blueprints.js`(70行只读版)在 `_tryMigratedView` 白名单中,switchView 加载了这个简化版视图后直接 return,registration.js 的完整编辑器(含步骤编排、原子操作卡片、保存/验证)从未被执行。
```javascript
// matrix_views.js 第149行
if (_tryMigratedView(view)) return; // ← 白名单拦截,直接返回!
// 第162行 — 永远不会执行到
try { if (view === 'matrix-blueprints') window.loadMatrixBlueprints(); } catch(e) {}
```
**修复**:
1. 从 `_tryMigratedView` 白名单移除 `matrix-blueprints`
2. 从 `view-registry.js` 中注释掉 `matrix-blueprints`
### 第2层:视图本身渲染 bug
`views/matrix-blueprints.js` 中用 `o.name||o` 渲染步骤名。但 API 返回的步骤对象格式为 `{step_id, op, args}`,没有 `name` 字段。`o.name` 为 undefined,`o` 是对象 → `[object Object]`。
**修复**: `o.name||o` → `o.op||o.name||''`
### 第3层:showBpEditor 查找逻辑 bug
即使绕过第1层,registration.js 的 `showBpEditor` 也有 bug:
```javascript
// 注册器版(正确)
const bps = Array.isArray(bd) ? bd : (bd.blueprints || []);
// showBpEditor 版(错误)
const bp = (d.blueprints||[]).find(...) // d 是数组,d.blueprints 为 undefined
```
API 返回原始数组 `[bp1, bp2, ...]`,不是 `{blueprints: [...]}`。`showBpEditor` 永远找不到蓝图,静默返回。
**修复**: 添加 `Array.isArray(d)` 检测,兼容两种 API 返回格式。
**教训**:
- 迁移视图会拦截 switchView 的后续逻辑。白名单中的视图名必须确保其功能完整。
- API 返回格式(数组 vs 对象)必须在整个前端保持一致。如果 API 返回数组,所有取数据的代码都要用 `Array.isArray()` 检测。
- 渲染 API 数据时,字段名要与 API 文档对齐(`op` 不是 `name`)。
- [object Object] 100% = 对象被当字符串用。模板字符串中 `${obj}`、字符串拼接 `str + obj`、`obj || fallback` 都可能触发。
---
## 8. Blueprint step 字段 op vs name 不一致
**症状**: `showBpEditor` 和 `stepsPreview` 都用 `s.name` 去查 `_matrixOps`,但 API 返回的字段是 `s.op`。
**根因**: 后端 API 返回的蓝图步骤格式为 `{step_id, op, args}`。前端的原子操作库 `_matrixOps` 索引用的是 `o.name`。所以 `_matrixOps[s.name]` 永远查不到。
**修复**:
- stepsPreview: `s.name` → `s.op||s.name`
- showBpEditor: `s.name||s` → `s.op||s.name`
- bpRenderSteps: 加 label 兜底,非字符串时重新从 `_matrixOps` 查询
**教训**: API 返回的字段名必须与前端使用的字段名一一对应。如果不对应,必须做映射转换。
---
## 9. 函数冲突:inline.js vs 拆分模块
**总体问题**: 同一函数在多个文件中定义,通过 import 顺序决定哪个版本胜出。这种机制极难排查。
**涉及函数**:
| 函数 | 定义在 | 胜出方 |
|------|--------|--------|
| `_loadAccounts` | inline + corpus | corpus |
| `_renderAccountSelector` | inline + corpus | corpus |
| `loadMatrixNurture` | inline + account_selector | account_selector |
| `loadMatrixCollect` | inline + account_selector | account_selector |
| `loadMatrixComment` | inline + account_selector | account_selector |
| `loadMatrixLike` | inline + account_selector | account_selector |
| `loadOpsCommand` | inline + account_selector | account_selector |
| `loadMatrixCommands` | inline + collect | collect |
| `cmdRunCommentTask` | inline + collect | collect |
| `loadMatrixBlueprints` | inline + registration | registration |
| `showBpEditor` | inline + registration | registration |
| `loadSmsProxy` | inline + corpus | corpus(已修复) |
| `loadSmsAccounts` | inline + corpus | corpus(已修复) |
**修复策略**:
1. 从胜出方中移除被覆盖函数的 window 赋值 → 明确所有权
2. 在 inline.js 末尾添加别名重定向 → 确保内部调用指向最终版本
**教训**: 模块化拆分应该是"**移动代码**"而不是"**复制代码并覆盖**"。拆出一个函数时,必须从原始文件中删除该函数定义。
@@ -0,0 +1,388 @@
---
title: "Dashboard v4.0 — AgentOS 联邦控制中心设计规范"
version: "4.0.0"
last_updated: "2026-05-18"
status: "draft"
author: "Claw (AgentOS)"
supersedes: "Dashboard v3.x"
---
# Dashboard v4.0 — AgentOS 联邦控制中心
## 一、设计哲学
```
不是"一个看板", 而是"联邦控制中心"。
不是"展示数据", 而是"统览+操作"。
不是"单机工具", 而是"跨机协同中枢"。
```
### 核心原则
1. **每台机器一个 Dashboard** → 但看到的数据是一致的(从 cross_machine 读)
2. **每台机器为自己的插件负责** → 本地路径本地配, 共享数据写 cross_machine
3. **插件是"数据线"不是"应用"** → 插件只负责采集+汇总, 不负责业务逻辑
4. **所有模块标注"属于哪台机器"** → 同样养号流程, 各机器状态分开显示
5. **新增模块 = 写一个 plugin.py** → 不需要改 Dashboard 核心代码
---
## 二、数据流架构
```
┌─ Machine A ──────────────────────────────────────┐
│ │
│ 模块(本地) → plugin.py 采集 │
│ ├── 读本地配置 (agent-local/) │
│ ├── 执行本地操作 │
│ └── 写共享数据 → cross_machine/data/{plugin}/ │
│ │
│ Dashboard(本地) ← 读共享数据 │
│ ├── cross_machine/data/{plugin}/ │
│ ├── cross_machine/status/live/ (心跳) │
│ └── cross_machine/registry/ (机器注册信息) │
│ │
└────────────────────────────────────────────────────┘
▲
│ 所有机器读写同一份数据
▼
┌─ Machine B ──────────────────────────────────────┐
│ 同上 │
│ 模块不同 → 写入不同的 cross_machine/data/ 子目录 │
└────────────────────────────────────────────────────┘
```
### 关键结论
| 数据类型 | 存哪里 | 谁写入 | 谁读取 |
|---------|--------|--------|--------|
| **机器心跳** | cross_machine/status/live/{uid}.json | guardd (每台) | Dashboard (所有) |
| **机器注册** | cross_machine/status/live/_registry.json | Dashboard push API | Dashboard (所有) |
| **插件共享数据** | cross_machine/data/{plugin_name}/{uid}.json | 各机器插件 | Dashboard (所有) |
| **本地私有数据** | agent-local/dashboard/{plugin_name}/ | 本地插件 | 本地 Dashboard |
| **跨机任务** | cross_machine/tasks/pending/{id}.json | Dashboard/手动 | guardd (目标机) |
| **事件记录** | cross_machine/events/{date}/{uuid}.json | guardd | Dashboard |
---
## 三、插件规范 v2
### 3.1 目录结构
每个插件是一个独立的 Python 文件,放在 `05_tools/10_dashboard/plugins/` 下:
```
plugins/
├── __init__.py
├── base.py ← 插件基类 (框架)
├── guardd.py ← 联邦机器状态 (内置)
├── ave.py ← AVE 视频工厂 (内置)
├── matrix.py ← Matrix 账号矩阵 (内置)
├── collector.py ← 内容采集 (内置)
├── skills.py ← 技能树 (内置)
├── knowledge.py ← 知识库 (内置)
├── automation.py ← 自动化任务 (内置)
├── tools.py ← 工具集 (内置)
├── system.py ← 系统核心 (内置)
└── (未来新增模块直接加在这里)
```
### 3.2 插件基类接口
```python
class DashboardPlugin:
"""插件基类 v2.0 — 联邦控制中心规范"""
# ── 元信息 (必须定义) ───────────────────────────────────
name: str = "" # 唯一标识, 如 "matrix"
label: str = "" # 中文名, 如 "账号矩阵"
icon: str = "📱" # 图标
version: str = "1.0.0" # 插件版本
description: str = "" # 简要说明
order: int = 99 # 排序
# ── 核心方法 ────────────────────────────────────────────
def summary(self, machines: list[str]) -> dict:
"""
概览数据 (首页卡片用)
machines: 当前有哪些机器 (从 _registry.json 读)
返回结构:
{
"总账号": 8,
"今日发帖": 3,
"各机器": {
"chengzigedeAir": {"账号":5, "有效":4},
"Redmi-12C": {"账号":3, "有效":2}
}
}
"""
raise NotImplementedError
def detail(self, machine: str = "") -> dict:
"""
详细面板数据
machine: 如果为空, 返回所有机器的汇总; 否则返回指定机器
返回结构: (各插件自定义)
"""
raise NotImplementedError
def actions(self) -> list[dict]:
"""
可执行操作列表
返回:
[{"name":"刷新", "method":"POST", "endpoint":"/api/plugins/matrix/refresh"}]
"""
return []
def write_shared_data(self, data: dict):
"""将本插件数据写入 cross_machine, 供其他机器读取"""
uid = _resolve_uid()
path = CROSS_MACHINE / "data" / self.name / f"{uid}.json"
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(json.dumps({
"plugin": self.name,
"version": self.version,
"machine_uid": uid,
"hostname": HOSTNAME,
"timestamp": datetime.now(timezone.utc).isoformat(),
"data": data,
}))
```
### 3.3 插件数据写入规范
每个插件写入 `cross_machine/data/` 的数据必须包含以下字段:
```json
{
"plugin": "matrix",
"version": "1.0.0",
"machine_uid": "4cf443bc-ff14-4ed9-885b-b04c5326304d",
"hostname": "chengzigedeAir",
"timestamp": "2026-05-18T01:30:00+00:00",
"data": { /* 插件自定义 */ }
}
```
**关键规则**:
- `machine_uid` 必填 — Dashboard 按此字段去重
- `hostname` 作为显示名 — 但去重按 UID 而非 hostname
- `timestamp` 用于判断数据是否过期(超过 24 小时未更新的标灰)
- `version` 用于版本兼容性判断
---
## 四、路径规则
### 4.1 路径常量
所有插件通过 `base.py` 提供的常量解析路径,禁止硬编码:
```python
# base.py 提供
AGENT_SYNC = Path.home() / "workbuddy-agent-os" / "agent-sync"
AGENT_LOCAL = Path.home() / "workbuddy-agent-os" / "agent-local"
CROSS_MACHINE = AGENT_SYNC / "04_memory" / "cross_machine"
DASHBOARD_LOCAL = AGENT_LOCAL / "runtime" / "dashboard" # 各机私有
```
### 4.2 路径使用规则
| 场景 | 路径 | 示例 |
|------|------|------|
| 读共享数据 | `CROSS_MACHINE / "data" / {plugin} / {uid}.json` | 所有机器相同 |
| 读本地配置 | `AGENT_LOCAL / "tools" / {module} / "config" / "local.yaml"` | 各机不同 |
| 写共享数据 | `CROSS_MACHINE / "data" / {plugin} / {uid}.json` | 按 UID 区分 |
| 写本地缓存 | `DASHBOARD_LOCAL / "cache" / {plugin} /` | 各机私有 |
| 读任务 | `CROSS_MACHINE / "tasks" / "pending" / {id}.json` | 所有机器可见 |
| 读注册表 | `CROSS_MACHINE / "status" / "live" / "_registry.json"` | 所有机器可见 |
---
## 五、机器感知设计
### 5.1 身份栏
Dashboard 顶部始终显示:
```
📡 chengzigedeAir | UID: 4cf443bc... | 角色: 主工作站 | 仓库: mac-agent-os | v1.1.0
```
- **hostname**: 从 `cached_hostname` 读取, 不会因 IP 变化而变
- **UID**: 从 `agent-local/identity/machine_uid` 读取, 全局唯一
- **角色**: 从 `cross_machine/registry/{name}.json` 读取 role 字段
- **仓库/版本**: 从 Git 读取
### 5.2 插件视图的机器标签
每个插件展示数据时,每条记录标注来源机器:
```
┌─ Matrix 账号矩阵 ──────────────────────────────┐
│ │
│ chengzigedeAir (主工作站) │
│ ├─ 抖音号A: ✅ 在线 今日已发 3 篇 │
│ ├─ 抖音号B: ✅ 在线 今日已发 1 篇 │
│ └─ 抖音号C: ❌ 离线 未操作 2天 │
│ │
│ Redmi-12C (采集节点) │
│ ├─ 抖音号X: ✅ 在线 今日已发 5 篇 │
│ └─ 抖音号Y: ✅ 在线 今日已发 2 篇 │
│ │
└──────────────────────────────────────────────────┘
```
### 5.3 自动化任务的机器归属
自动化任务记录格式必须包含:
```json
{
"id": "sync_Redmi-12C_20260517",
"name": "袁本初每日采集",
"source_machine": "chengzigedeAir", // 谁创建的
"target_machine": "Redmi-12C", // 谁执行的
"source_uid": "4cf443bc-...",
"target_uid": "a1b2c3d4-...",
"status": "pending | running | completed | failed",
"created_at": "...",
"completed_at": "...",
"result": ""
}
```
---
## 六、9 个内置插件明细
### P0 核心插件(优先实现)
| # | 插件 | name | 数据源 | 各机器数据 |
|---|------|------|--------|-----------|
| 1 | **🖥 联邦机器** | guardd | cross_machine/status/ + 心跳 | ✅ 每台机器各自心跳 |
| 2 | **🎬 AVE 工厂** | ave | 本地: agent-local/runtime/ave/ + cross_machine/data/ave/ | ✅ 各机独立写入 |
### P0 新增: 矩阵养号
| # | 插件 | name | 数据源 | 各机器数据 |
|---|------|------|--------|-----------|
| 3 | **📱 Matrix 矩阵** | matrix | local.yaml 账号配置 + Blueprint 执行日志 | ✅ 各机的账号不同 |
**数据采集路径**:
```
本地: agent-local/tools/matrix/config/local.yaml ← 各机自己的矩阵账号
agent-local/runtime/matrix/ ← 各机执行日志
共享: cross_machine/data/matrix/{uid}.json ← 概览汇总
```
**Matrix 插件 summary() 输出示例**:
```json
{
"总账号": 8,
"在线": 6,
"今日发帖": 15,
"各机器": {
"chengzigedeAir": {"账号":5,"在线":4,"今日发帖":10},
"Redmi-12C": {"账号":3,"在线":2,"今日发帖":5}
}
}
```
### P1 插件
| # | 插件 | name | 数据源 | 各机器数据 |
|---|------|------|--------|-----------|
| 4 | **📡 内容采集** | collector | cross_machine/events/ + 本地 submission | ✅ 各机采集进度 |
| 5 | **🧩 技能树** | skills | ~/.workbuddy/skills/ 目录+技能配置 | ✅ 各机技能列表不同 |
| 6 | **📚 知识库** | knowledge | 03_knowledge/ 文件树 | ❌ 知识库共享(10_concepts等) + 各机提交箱 |
| 7 | **⏰ 自动化任务** | automation | cross_machine/tasks/ + WorkBuddy DB | ✅ 各机任务不同 |
| 8 | **🔧 工具集** | tools | 05_tools/ 目录树 | ✅ 各机工具安装不同 |
| 9 | **⚙️ 系统核心** | system | Git + 系统信息 | ✅ 各机信息不同 |
---
## 七、审计与自检
### 7.1 身份一致性 (当前已知问题 ✅ 已修复)
| 问题 | 状态 | 说明 |
|------|------|------|
| hostname 随 IP 变 | ✅ 已修复 | guardd 缓存 hostname 到 cached_hostname 文件 |
| UID 为主键 | ✅ 已修复 | 所有存储用 UID 而非 hostname |
| 机器去重 | ✅ 已修复 | 从 _registry.json 按 UID 遍历 |
### 7.2 潜在风险与规避
| 风险 | 影响 | 规避方案 |
|------|------|---------|
| **数据格式冲突** | 两台机器同一插件输出不同结构 | version 字段 + summary 输出结构规范化 |
| **数据过期** | 机器宕机后旧数据仍显示 | timestamp + TTL: 24h未更新自动标灰 |
| **权限混乱** | 某机器误写其他机器的数据 | 按 UID 文件名隔离, 不可越界 |
| **插件缺失** | Dashboard 加载失败 | try/except 包裹, 单个插件崩不影响其他 |
| **路径硬编码** | 迁移/换机后路径失效 | 全部通过 base.py 常量, 不出现绝对路径 |
| **目录结构变更** | 新增目录后旧的引用失效 | cross_machine 目录结构存档在 CORE-ARCHITECTURE.md |
### 7.3 无法执行的风险
| 风险 | 原因 | 解决方案 |
|------|------|---------|
| **跨机实时操作** | Dashboard 通过 API 操作其他机的进程 | 降级为 "创建任务 → wait → 轮询结果" |
| **插件自动部署** | 新插件需要手动 scp/rsync | 通过 git push + guardd pull 自动分发 |
| **跨机 SSH 执行** | 无 SSH 互通, 防火墙策略 | 用 cross_machine/tasks/ 文件作为消息队列 |
### 7.4 边缘情况
| 场景 | 行为 |
|------|------|
| 某机器从未推送过数据 | 该机器在 Dashboard 标 "未连接" |
| 某机器推送后宕机 | 数据保留 24h, 超时后标灰 |
| 两台机器 UID 冲突 | 不可能, UUID4 生成, 冲突概率极低 |
| 插件版本升级 | summary() 保证向后兼容, 新增字段可选 |
| 网络分区 | 各机 Dashboard 独立运行, 恢复后自动同步 |
---
## 八、实施计划
### Phase 1: 框架改造 (约1小时)
- [ ] 重写 `base.py` → 插件基类 v2.0
- [ ] 新增 `cross_machine/data/` 目录结构
- [ ] 新增 `DASHBOARD_LOCAL` 本地缓存目录
- [ ] 前端改造: 身份栏 + 侧边栏动态渲染
### Phase 2: 核心插件 (约1.5小时)
- [ ] guardd 插件 → 适配 v2 规范 + 机器标签
- [ ] matrix 插件 → 读取 local.yaml + 写入共享
- [ ] ave 插件 → 适配 v2 规范 + 各机生产统计
### Phase 3: 系统插件 (约1.5小时)
- [ ] skills / knowledge / collector / automation / tools / system
- [ ] 时间线/热力图/告警适配
### Phase 4: 端到端验证 (约0.5小时)
- [ ] 跨机数据一致性测试
- [ ] 新机首次注册全流程
- [ ] 插件报错隔离测试
---
## 九、附录
### 9.1 各机差异点速查
| 维度 | chengzigedeAir (主工作站) | Redmi-12C (采集节点) | 其他机器 |
|------|-------------------------|---------------------|---------|
| 角色 | master | worker | worker |
| AVE工厂 | ✅ 可生产 | ❌ 无 | 按需 |
| Matrix | 5个账号 | 3个账号 | 按需 |
| 采集工具 | 浏览器采集 | 无浏览器 | 按需 |
| Dashboard | ✅ 启动 | ✅ 启动 | ✅ 启动 |
### 9.2 相关文档
- CORE-ARCHITECTURE.md — 系统架构宪法
- content-collection-pipeline.md — 采集链路规范
- SKILLS-CATALOG.md — 技能体系
- guardd 设计文档 — 守护进程
@@ -0,0 +1,46 @@
---
id: KB-20260601-017
title: ""
type: method
status: published
nature: method
domain: [general]
subdomain: []
tags: ["待补充"]
confidence: 0.5
source: ""
source_type: unknown
date_created: 2026-06-01
date_modified: 2026-06-01
version: 1
previous_version: ""
superseded_by: ""
summary: ""
collected: true
collected_date: 2026-06-02---
# 2026-05-17_2026-05-16_原子化登录管理模块_auth_manager
> 来源:03_knowledge/20_methods
# 2026-05-16_原子化登录管理模块_auth_manager
# 原子化登录管理模块 auth_manager
# auth_manager — 原子化登录管理模块
## 概述
## 核心函数
### Cookie 检测(主方案)
### DOM 检测(备选,仅移动端视口有效)
### 综合检测
# 返回: logged_in, cookie_ok, dom_ok, cookie_count, session_id, method
### Cookie 持久化
### 等待手动登录
## 设计原则
1. Cookie 检测为主方案(不依赖 UI 布局,桌面端/移动端均可用)
2. DOM 检测为备选(仅在 mobile=True 视口下有效)
3. 所有函数无副作用(不写 DB/文件,除非函数名明确)
4. 统一异常处理(所有异常返回 False/空值)
## 解决的问题
- `switch_account.py` 此前用 `[data-e2e="user-avatar"]` DOM 检测,桌面端视口下该元素不可见,导致已登录账号误报"未登录"
- 所有脚本各自实现登录检测,逻辑分散
@@ -0,0 +1,41 @@
---
id: KB-20260602-003
title: ""
type: method
status: published
nature: method
domain: [general]
subdomain: []
tags: ["待补充"]
confidence: 0.5
source: ""
source_type: unknown
date_created: 2026-06-02
date_modified: 2026-06-02
version: 1
previous_version: ""
superseded_by: ""
summary: ""
collected: true
collected_date: 2026-06-03---
# 2026-06-01_2026-05-17_2026-05-16_Camoufox_集成修复记录
> 来源:03_knowledge/20_methods
# 2026-05-17_2026-05-16_Camoufox_集成修复记录
# 2026-05-16_Camoufox_集成修复记录
# Camoufox 集成修复记录
# Camoufox 集成修复记录
## 正确启动方式
## 修复清单
### 1. 操作系统指纹(P1)
**问题**: Camoufox 默认从 `[windows, macos, linux]` 随机,导致手机端扫码有时显示"登录macOS"。
**修复**: 添加 `os='windows'` 固定参数。
**文件**: `cdp_connector.py:_launch_camoufox()`
### 2. 中文乱码(P1)
**问题**: Camoufox/Firefox 不加载系统字体,抖音页面中文显示乱码。
**修复**: 添加 `fonts=['STHeiti', 'Heiti SC', 'PingFang SC', 'Noto Sans CJK SC']` 和 `humanize=1.5`。
**文件**: `cdp_connector.py:_launch_camoufox()`
### 3. 登录检测(P0)
@@ -0,0 +1,129 @@
---
title: 抖音评论自动化双路径技术
tags: [douyin, comment, automation, draft.js, keyboard]
created: 2026-05-29
updated: 2026-05-29
nature: method
collected: true
collected_date: 2026-06-09
---
## 概述
抖音评论系统基于 Draft.js 富文本编辑器,具有严格的输入验证。通过两条独立路径实现评论自动化。
## 双路径架构
| 路径 | 场景 | 入口操作 | 发送操作 |
|:-----|:-----|:---------|:---------|
| **Path A**: 弹窗覆盖层 | 养号流程中 | KeyX 打开评论区 | Enter 发送 |
| **Path B**: 全屏视频页 | 指定视频链接 | scrollIntoView 定位输入框 | Enter 发送 |
## 输入方式
**唯一可靠方式**:`pbcopy` + `Meta+V`(系统剪贴板粘贴)
Draft.js 富文本编辑器特点:
- 只认系统级键盘事件
- CDP(Chrome DevTools Protocol)注入的键盘事件一律忽略
- `page.fill()` / `page.type()` / `elementHandle.type()` 均不可靠
- 必须通过剪贴板 + 系统快捷键触发输入
```python
# 标准输入流程
import subprocess
subprocess.run(["pbcopy"], input=comment_text.encode(), check=True)
await page.keyboard.press("Meta+v") # 或 Cmd+V
await asyncio.sleep(0.3) # 等待粘贴完成
await page.keyboard.press("Enter") # 发送
```
## 状态机
```
closed → panel_open → input_focused → text_entered → sent / verify_code
```
| 状态 | 说明 | 验证方法 |
|------|------|----------|
| closed | 评论区关闭 | 评论面板不可见 |
| panel_open | 评论区已打开 | 评论列表 DOM 可见 |
| input_focused | 输入框已聚焦 | `document.activeElement` 指向编辑器 |
| text_entered | 文字已粘贴 | 输入框内容非空 |
| sent | 发送成功 | 新评论出现在列表顶部 |
| verify_code | 触发验证码 | 验证码弹窗出现,需人工处理 |
## Draft.js 空格刷新技巧
粘贴文本后,Draft.js 可能不立即更新 React 状态。解决方法:
```python
# 粘贴后按空格刷新 React 状态
await page.keyboard.press("Space")
await asyncio.sleep(0.1)
await page.keyboard.press("Backspace") # 删除多余空格
```
## 视频页评论区定位(Path B 专项)
**问题**:评论区输入框可能在视口外(y ~2212px)
**解决**:
1. `scrollIntoView()` 将输入框滚动到可视区域
2. 等待 DraftEditor 懒加载初始化(关键步骤,不能跳过)
3. 点击容器元素触发编辑器激活
4. 然后才能聚焦、粘贴
```python
input_container = await page.query_selector("评论输入框容器选择器")
await input_container.scroll_into_view_if_needed()
await asyncio.sleep(0.5) # 等待 DraftEditor 懒加载
await input_container.click() # 触发编辑器激活
await asyncio.sleep(0.3)
# 现在可以粘贴了
```
## 抖音快捷键参考
| 快捷键 | 功能 |
|--------|------|
| KeyZ | 点赞 |
| KeyX | 打开/关闭评论 |
| KeyG | 关注 |
| KeyP | 连播切换 |
| KeyM | 静音切换 |
| KeyJ | 清屏/弹幕切换 |
## 评论内容生成
### AI 评论(可选)
```python
from matrix_modules.comment.ai_generator import AICommentGenerator
ig = AICommentGenerator()
note_info = await page.evaluate("""
() => {
const t = document.querySelector('.title, h1');
const c = document.querySelector('.content, .desc');
return { title: t?.textContent?.trim(), content: c?.textContent?.trim() };
}
""")
comment_text = ig.generate_with_context(
note_title=note_info.get("title", ""),
note_content=note_info.get("content", ""),
)
```
### 随机评论池
预置评论列表,`random.choice()` 选取。评论频率建议每 3 轮 1 次,避免被检测。
## 错误处理
| 错误 | 原因 | 处理 |
|------|------|------|
| 粘贴无效 | 系统剪贴板被占用 | 重试 pbcopy |
| Enter 无响应 | 输入框未聚焦 | scrollIntoView + click 重新聚焦 |
| 验证码弹窗 | 频繁操作触发 | 截图保存,跳过本轮 |
| 评论发送失败 | 网络或限流 | 等待后重试,计入 consecutive_failures |
@@ -0,0 +1,353 @@
---
title: 抖音登录流程 — 全链路知识与踩坑记录
tags: [douyin, login, sms, verification, iframe, selector, timing]
created: 2026-06-28
updated: 2026-06-28
nature: reference
---
# 抖音登录流程 — 全链路知识与踩坑记录
> 本文包含 2026-06-28 大规模调试中积累的所有登录经验。
> 适用于 `douyin_ops.py` 的 `_ensure_logged_in()` 和 `sms_login()` 方法。
---
## 一、登录状态检测
### 1.1 判断已登录的方法(按可靠性排序)
| 方法 | 选择器 | 可靠性 | 说明 |
|:-----|:--------|:-------|:------|
| `data-e2e` 用户信息区 | `[data-e2e="user-info"]` | ⭐⭐⭐ 最高 | 抖音官方 e2e 标记,有就必已登录 |
| 头像元素 | `[class*="avatar"]` 或 `[data-e2e*="avatar"]` | ⭐⭐ 中 | 部分页面没有这个选择器 |
| 登录按钮不可见 | `button:has-text("登录")` 不可见 | ⭐ 低 | 仅作兜底,不精确 |
### 1.2 判断未登录的方法
- 右上角可见的**「登录」按钮**
- 选择器:`button:has-text("登录"), span:has-text("登录"), div:has-text("登录")`
- 注意:首页推荐流中这个按钮始终存在,要用 `is_visible()` 确认
### 1.3 关键注意事项
- **首次打开抖音首页加载慢**,至少要等 **6 秒**才能做登录检测(我们试过 2s→3s→5s→6s,6s 最稳定)
- 登录弹窗可能在上次会话的 cookie 有效时不弹出,直接显示已登录状态
- 登录成功后**必须重新导航到 `/user/self`**,因为弹窗处理改变了页面 URL
---
## 二、登录弹窗检测
### 2.1 弹窗位置:iframe
抖音的登录弹窗(passport 护照页)是在 **iframe** 中加载的,iframe URL 模式:
- `passport.douyin.com`
- `sso.douyin.com`
- 域名含 `login`
### 2.2 弹窗选择器
| 用途 | 选择器 | 说明 |
|:-----|:--------|:------|
| 弹窗容器 | `.second-verify-panel, .uc-ui-verify_sms-verify` | 覆盖新旧两版 class |
| 二维码区域 | `div[class*=qrcode], img[class*=qrcode], canvas[class*=qrcode]` | 用于二维码检测 |
### 2.3 ⚠️ iframe 查找顺序(重要!)
**必须先查 iframe,再查主页面!**
```
❌ 错误做法(我们踩过的坑):
1. 主页面查 verify_panel → 匹配到遮罩层(`.second-verify-panel`)
2. login_frame = page(主页面)
3. 在主页面搜手机输入框 → 找不到 ❌(因为输入框在 iframe 内)
✅ 正确做法(修复后):
1. 遍历所有 iframe,找 passport/login 域的 verify_panel
2. 找到 → login_frame = iframe
3. 在 iframe 内搜手机输入框 → 能找到 ✅
4. iframe 没找到 → fallback 到主页面
```
### 2.4 弹窗类型判断
弹窗可能有三种状态:
```
弹窗出现
├─ 一键登录 → 有 "一键登录" 按钮,无手机号输入框
├─ 验证码登录 → 有手机号输入框 + 获取验证码按钮
└─ 二维码登录 → 有二维码图片/画布,需切 tab
```
#### 一键登录特征
- 选择器:`button:has-text("一键登录"), span:has-text("一键登录")`
- 点击后等 5 秒
- 可能直接登录成功,也可能跳到验证码页(继续走 sms)
#### 验证码登录特征
- 手机号输入框:`input[placeholder*="手机"]`(匹配 `placeholder="请输入手机号"`)
- 验证码输入框:`input[placeholder*="验证码"]`(匹配 `placeholder="请输入验证码"`)
- 获取验证码按钮:`button:has-text("获取验证码")`
#### 二维码登录特征
- 检测:`div[class*=qrcode], img[class*=qrcode], canvas[class*=qrcode]`
- 处理:找到「验证码登录」tab 并点击切换
---
## 三、SMS 验证码流程
### 3.1 完整流程
```
1. 导航到登录页(如果不在)
2. 查找 passport iframe(最多 5 次尝试,每次间隔 2 秒)
3. 等 3 秒渲染
4. 检测二维码 → 切「验证码登录」tab
5. 找手机号输入框 → 填入手机号(3 次重试,每次间隔 1 秒)
6. 点击「获取验证码」
7. 轮询 SMS API 获取验证码(最多 6 次,共 60 秒超时)
8. 填入验证码
9. 点击「登录」
10. 判断是否登录成功
```
### 3.2 手机号输入框查找(带重试)
```python
phone_sel = "input[placeholder*='手机'], input[type='tel'], input[name='mobile'], input[id*='phone'], input[id*='mobile']"
for retry in range(3):
for sel in [phone_sel, "input:first-of-type"]:
inp = await login_frame.query_selector(sel)
if inp and await inp.is_visible():
# 填入手机号
break
if phone_filled:
break
await asyncio.sleep(1)
```
**注意**:`input:first-of-type` 会匹配到首页搜索框,所以优先用 `placeholder` 选择器。
### 3.3 验证码输入框查找
```python
code_sel = "input[placeholder*='验证码'], input[maxlength='6'], input[maxlength='4'], input[autocomplete='one-time-code']"
```
### 3.4 登录成功判断
| 判断方法 | 说明 |
|:---------|:------|
| URL 变化 | `"passport" in current_url` → 仍在登录页 / `not` → 登录成功 |
| 右上角头像 | `[data-e2e="user-info"]` 存在且可见 → 登录成功(**兜底方案**)|
**两者都用!** 如果 URL 变了但右上角还没渲染出头像,等 3 秒再查一次。
---
## 四、时序控制(重要)
### 4.1 各步骤等待时间
| 步骤 | 等待时间 | 原因 |
|:-----|:---------|:------|
| 首次打开后检测 | **6 秒** | 抖音首页加载慢,特别是第一打开,推荐流+弹窗需要完整渲染 |
| 切换 tab 后 | **3 秒** | tab 切换动画 + 新内容渲染 |
| 填手机号后 | **1 秒** | 防抖 + 输入框状态同步 |
| 点击获取验证码后 | **2 秒** | 等待 SMS 发送 |
| 填入验证码后 | **1 秒** | 防抖 |
| 点击登录后 | **3-5 秒** | 等待页面跳转 |
| 登录成功后重导航 | **3 秒** | 等待 `/user/self` 渲染 |
### 4.2 超时控制
- SMS 验证码轮询:最长 **60 秒**(6 次 × 10 秒)
- 单次 iframe 查找:最长 **10 秒**(5 次 × 2 秒)
- 页面 goto 超时:**20 秒**
---
## 五、选择器备忘(抖音 Web 版)
### 5.1 官方 `data-e2e` 选择器
这些是抖音官方的自动化测试标记,最稳定:
| 用途 | 选择器 |
|:-----|:--------|
| 用户信息区(已登录标志) | `[data-e2e="user-info"]` |
| 用户头像 | `[data-e2e="user-avatar"]`(不一定存在) |
| 搜索输入框 | `[data-e2e="searchbar-input"]` |
| 点赞按钮 | `[data-e2e="video-player-digg"]` |
| 收藏按钮 | `[data-e2e="video-player-collect"]` |
| 分享按钮 | `[data-e2e="video-player-share"]` |
| 评论列表 | `[data-e2e="comment-list"]` |
| 评论点赞 | `[data-e2e="comment-digg"]` |
| 粉丝数 | `[data-e2e="user-info-fans"]`(值可能混合中文) |
| 关注数 | `[data-e2e="user-info-follow"]` |
| 获赞数 | `[data-e2e="user-info-like"]` |
### 5.2 登录弹窗选择器(不定期变化)
这些 class 名由抖音前端动态生成,**每次发布可能变化**:
| 用途 | 6月28日已确认的 class |
|:-----|:----------------------|
| 手机号输入框 | `yKcGN1NT X5L8kib_` |
| 验证码输入框 | `tnpNAdqe _Yqor1vk` |
| 获取验证码按钮 | `gKXDWaPG KX2Mhb6E` |
| 验证码 tab | `zad3EGHJ` |
**因此,不要依赖 class 名,用 placeholder/text 代替。**
### 5.3 推荐做法:文本/属性匹配
```python
# ✅ 稳定
input[placeholder*="手机"] # 匹配 "请输入手机号"
input[placeholder*="验证码"] # 匹配 "请输入验证码"
button:has-text("获取验证码") # 匹配按钮文字
div:has-text("验证码登录") # 匹配 tab 文字
# ❌ 不稳定(class 会变)
.tnpNAdqe # 下个版本可能就改了
.yKcGN1NT # 同上
```
---
## 六、已踩过的坑(必读)
### 坑 1:logger 未定义导致 executor 闪退
**现象**:任务提交后状态一直 "running",实际已挂,slots 空但 active_tasks 有残留。
**根因**:`executor.py` 中使用了 `logger.info()` 但 `logger = logging.getLogger("guardd.executor")` 未定义,NameError 抛出,executor 闪退但任务状态来不及更新。
**修复**:添加 `logger = logging.getLogger("guardd.executor")`。
### 坑 2:主页面遮罩层匹配导致 iframe 检测失败
**现象**:弹窗出现了但手机号输入框找不到。
**根因**:`verify_panel` 选择器 `.second-verify-panel` 在主页面遮罩层上匹配成功,`login_frame` 设为主页面(不是 iframe),在主页面搜手机输入框当然搜不到。
**修复**:先查 iframe,再查主页面。
### 坑 3:登录后页面 URL 变化导致采集到首页数据
**现象**:采集任务显示完成,但 profiles.json 中昵称/粉丝数据为空或为首页标题。
**根因**:登录弹窗处理后,页面 URL 从 `/user/self` 变成了首页或其他地址,但 `goto_profile()` 继续刮取当前页面内容(首页推荐流),拿不到用户数据。
**修复**:登录成功后重新 `goto("/user/self")`。
### 坑 4:2 秒等待不够
**现象**:浏览器打开后鼠标立即动了,此时页面还没渲染完,弹窗还没出现。
**根因**:抖音首页首次加载~4-5 秒,2 秒时 `_has_avatar()` 判断为未登录(因为没渲染完),然后触发弹窗检测也找不到弹窗,最后点了"登录"按钮导致页面刷新。
**修复**:初始等待时间从 2 秒改为 6 秒。
### 坑 5:`_build_cmd` 按字段拼装导致 command_line 出错
**现象**:采集任务一直失败,executor 日志显示 `--blueprints=` 为空。
**根因**:`executor._build_cmd()` 从 `task.get("blueprint")` 读蓝图名,但 CommandBus 传的 `blueprint` 字段是空字符串(没传对),拼出了 `mc run --blueprints= --rounds=1`。
**修复**:优先使用 `task.command_line`(CommandBus 已渲染好的完整命令),`_build_cmd` 按字段拼装仅作 fallback。
### 坑 6:5kecheng 双 guardd 进程
**现象**:远程机器任务不执行,所有请求都返回空。
**根因**:SSH 部署时 `pkill -9 -f guardd` + `nohup python3 guardd.py` 启动了一个新实例,而 launchd 也管理了一个旧实例。两个 guardd 争抢端口 9090,其中一个没有 HTTP 服务。
**修复**:统一用 launchd 管理,不用 nohup。
### 坑 7:登录后 URL 不变(前端 overlay 形式)
**现象**:登录成功了但 `sms_login` 返回 False。
**根因**:有的登录弹窗是前端 overlay(不在 passport 域名下),URL 不变化。`sms_login` 只检查 URL,误判为失败。
**修复**:加 `_has_avatar()` 兜底判断。
### 坑 8:profiles.json 同步走本地文件违反联邦对等
**现象**:7kecheng 采集了数据,但 Dashboard 看不到。
**根因**:`AccountService._get_profile_for_account()` 直接读本机 `profiles.json`,不走 guardd API。
**修复**:改为统一通过 guardd HTTP API (`/accounts/profiles`) 读取,本机远程无差别。
---
## 七、录制文件分析指南
录制的 JSON 文件位于 `agent-local/tools/matrix/recordings/`。
### 7.1 关键字段含义
| 字段 | 含义 |
|:-----|:------|
| `t` | 事件类型(click/hover/key/scroll) |
| `tag` | HTML 标签 |
| `text` | 元素文本内容 |
| `cls` | 元素的 CSS class(关键!) |
| `placeholder` | input 元素的占位符 |
| `type` | input 类型 |
| `e2e` | data-e2e 属性值 |
| `vis` | 元素是否可见 |
| `before_state.selectors` | 录制前页面状态快照 |
| `before_state.text_snippet` | 页面文本片段 |
### 7.2 如何从录制中提取特征码
```bash
# 找手机号输入框
grep -B5 -A3 "请输入手机号" recording_xxx.json
# 找验证码输入框
grep -B5 -A3 "请输入验证码" recording_xxx.json
# 找登录按钮
grep -B5 -A3 "获取验证码" recording_xxx.json
# 查看页面文本快照(了解页面状态)
grep "text_snippet" recording_xxx.json | head -1 | python3 -c "import json,sys;print(json.load(sys.stdin)['text_snippet'][:500])"
```
---
## 八、蓝图登录检测覆盖范围
当前 `_ensure_logged_in()` 被以下操作调用:
| 蓝图操作 | 在流程中调用位置 |
|:---------|:----------------|
| `goto_home` | `execute_op()` 中 goto 首页后 |
| `dy_goto_profile` | `execute_op()` 中 goto 个人主页后 |
| `goto_profile` | 独立方法中被调用 |
| `_ensure_logged_in` 自身 | 无弹窗时递归调用 |
### 设计原则
所有涉及浏览器导航的操作(`goto_home`、`goto_url`、`goto_profile`)**都应该**调用 `_ensure_logged_in()`。目前 `goto_url` 还没有加,待补。
---
## 九、相关文件索引
| 文件 | 内容 |
|:-----|:------|
| `douyin_ops.py` | 抖音原子操作 + `_ensure_logged_in` + `sms_login` |
| `matrix_modules/account/sms_login.py` | SMS 登录模块 |
| `matrix_modules/account/douyin_login.py` | 抖音登录模块 |
| `matrix_modules/account/login_state_machine.py` | 登录状态机 |
| `03_knowledge/99_system/matrix/matrix-known-pitfalls.md` | 已知坑(浏览器/系统) |
| `03_knowledge/99_system/matrix/matrix-sms-verification.md` | SMS 验证码自动接收配置 |
@@ -0,0 +1,161 @@
---
title: Matrix 养号系统已知坑与解决方案
tags: [matrix, pitfalls, troubleshooting, camoufox, chrome, macos]
created: 2026-05-29
updated: 2026-05-29
nature: method
collected: true
collected_date: 2026-06-09
---
## 浏览器引擎
### Camoufox Profile 锁冲突
**现象**:`TargetClosedError`、页面无法操作、养号快速失败
**根因**:两个浏览器实例争用同一 profile 目录,`.parentlock` 锁文件被占用
**场景**:
- 抖音 daemon 模式浏览器保持运行,小红书复用同 identity_dir 启动新实例
- 上次进程异常退出,锁文件未清理
**解决**:
```bash
# 清理残留锁文件
find identities/ -name ".parentlock" -delete
```
**预防**:Phase 间使用 `--no-daemon` 确保浏览器正常关闭(`conn.close()`)
### Camoufox 启动失败
**现象**:浏览器进程无法启动或立即退出
**排查**:
1. 检查 `.user_data/` 目录锁文件(`.parentlock`)
2. 检查 config.yaml 语法
3. 检查 Camoufox 二进制是否可用
### Chrome 148+ Emulation API 失效
**现象**:`Emulation.setDeviceMetricsOverride` 报错或无效果
**根因**:Chrome 148 移除了该 CDP 命令
**解决**:改用 `set_viewport_size` 方法
## macOS 系统
### 窗口激活限制
**现象**:点击操作不响应,元素未被触发
**根因**:macOS 限制后台进程操控前台窗口
**解决**:AppleScript 激活窗口 + 双击策略
```applescript
tell application "System Events" to set frontmost of process "Firefox" to true
```
### macOS 26.4 .so 签名问题
**现象**:`ModuleNotFoundError` 或 `OSError: dlopen` 加载 .so 失败
**根因**:系统升级后 Team ID 不匹配
**解决**:ad-hoc 签名
```bash
codesign --force --sign - /path/to/file.so
# 批量签名
find /path/to/venv -name "*.so" -exec codesign --force --sign - {} \;
```
### Python stdout 缓冲
**现象**:后台运行日志文件为空或延迟写入
**根因**:Python 后台进程 stdout 默认全缓冲(非终端环境)
**解决**:
```bash
PYTHONUNBUFFERED=1 nohup python3 script.py > log.txt 2>&1 &
```
或检查账号级日志文件而非 phase 级日志。
## XHS 特有
### QR 检测墙卡死
**现象**:弹出大弹窗后无响应,养号停滞
**根因**:XHS 非常用登录检测,弹窗无自动超时
**解决**:JS 检测 QR 墙关键词 → 定位"返回首页"按钮 → L 型鼠标路径点击
**区分**:QR 墙 ≠ 未登录。QR 墙是频控触发,多刷会恢复。
### 黑屏
**现象**:瀑布流页面变黑,卡片不可见
**根因**:SPA 状态异常
**解决**:点击底部导航"发现" tab 刷新页面状态
### AI-layout 布局差异
**现象**:搜索栏消失、首卡位置偏移
**根因**:指纹分辨率 + DPR 触发 A/B 测试
**解决**:
1. 调整指纹(screen ≥ 1920x1080, DPR ≥ 1.25)
2. 代码兼容(三重搜索降级、通用 href 匹配)
### 登录检测误判
**现象**:已登录但被判定为未登录
**根因**:先关闭弹窗再检测 → 弹窗已隐藏 → 无法检测登录提示
**解决**:先检测登录状态 → 再 dismiss_login_modal
## 抖音特有
### Draft.js 输入不可靠
**现象**:评论内容无法输入或粘贴后消失
**根因**:Draft.js 只认系统级键盘事件
**解决**:pbcopy + Meta+V,不用 page.fill/type/keyboard.type
### 视频页评论区输入框在视口外
**现象**:评论发送失败,输入框不可交互
**根因**:输入框 y ~2212px,不在可视区域
**解决**:scrollIntoView → 等待 DraftEditor 懒加载 → click 容器触发激活
## 代码层面
### identity_dir 路径构造
**坑**:仅用 identity_name 拼接路径可能错误(如 `douyin_01_camo` ≠ `douyin_01`)
**正确做法**:从 accounts.yaml 读取 identity_dir 字段
### 窗口位置读取
**坑**:config.yaml 中无窗口位置字段
**正确做法**:从 accounts.yaml 读取,运行结束不回写
### argparse daemon 参数
**坑**:`store_true` + `getattr(args, 'daemon', True)` 当参数为 None 时返回 None 而非 True
**正确做法**:`BooleanOptionalAction` + `args.daemon if args.daemon is not None else True`
### page.evaluate() 无限挂起
**现象**:养号运行到某一步突然停止,无错误日志,浏览器进程存活
**根因**:Playwright 的 `page.evaluate()` 在页面状态异常时无限挂起,**无默认超时**
**解决**:所有 `page.evaluate()` 调用加 `asyncio.wait_for()` 超时(8-10s)
**影响范围**:所有涉及 JS 调用的函数(dismiss_login_modal, get_note_cards, click_refresh_button 等)
**注意**:超时会捕获 `asyncio.TimeoutError`,返回 False/None,不会导致进程退出
### 搜索结果页无 FAB 刷新按钮
**现象**:搜索返回首页后 click_refresh_button() 一直在找按钮,日志显示"刷新瀑布流页面..."长时间无进展
**根因**:go_back_to_home() 后可能回到搜索页,搜索页没有右下角 FAB 刷新按钮
**解决**:click_refresh_button() 加 10s 超时 → 找不到按钮安全返回 False → 流程继续
## 诊断方法论
遇到异常时按以下流程处理:
1. **环境因素**:浏览器版本变化?网络波动?进程锁残留?文件被占用?
2. **人为操作**:用户手动关闭浏览器?拖拽窗口?修改配置?
3. **确认代码问题**:记录日志,确认后再改
4. **读文档**:查看项目规划/架构设计,不偏离已有设计
5. **一次改一处**:改完验证再继续
**反面教材**:Chrome 148 升级导致 CDP API 失效,反复修改 cdp_connector.py 6 次把好的改坏了。
@@ -0,0 +1,152 @@
---
title: Matrix 养号系统架构与运维指南
tags: [matrix, nurture, architecture, operations, douyin, xhs]
created: 2026-05-29
updated: 2026-05-29
nature: method
collected: true
collected_date: 2026-06-09
---
## 系统概览
Matrix 养号系统是一套多平台浏览器自动化框架,支持抖音(Douyin)和小红书(XHS)的账号养号、浏览互动、评论等操作。
## 架构
```
统一入口 matrix.py (CLI)
├── 双引擎连接 cdp_connector.py
│ ├── Chrome CDP (UA + viewport + touchEmulation 三合一)
│ └── Camoufox 持久化 (config 注入, 反检测)
├── 养号控制 runner.py (nurture_loop / nurture_xhs_loop)
├── 操作层 ops/
│ ├── douyin/ (browse.py, interact.py)
│ └── xhs/ (browse.py, interact.py, selectors.py)
├── 行为模拟 nurture/behavior.py (13 项可配置参数)
├── 身份管理 identities/{name}/
│ ├── config.yaml (窗口位置、代理等)
│ ├── fingerprint.pkl (浏览器指纹)
│ └── user_data/ (浏览器 profile 数据)
└── 主控脚本 nurture_master.sh (Phase 1 抖音 → Phase 2 小红书)
```
## 核心概念
### 双引擎模式
| 引擎 | 适用场景 | 特点 |
|------|----------|------|
| Chrome CDP | 需要高性能/稳定连接 | UA+viewport+touchEmulation 三合一注入 |
| Camoufox | 需要强反检测 | 持久化 profile, config 注入, 指纹隔离 |
### 统一 CLI
```bash
matrix {account|nurture|config|status} {action} {params}
```
### 账号共享身份
XHS 和抖音可共享同一 identity_dir(如 `douyin_01_camo` 同时用于 `xhs_01`),实现指纹统一。但需注意 **profile 互斥**:同一时刻只能有一个浏览器实例使用同一 profile。
## 养号流程
### 抖音养号轮次
```
首页 → 点击推荐卡片 → 看视频(随机时长) → 点赞/收藏(5中1) → 搜索框搜索 → 返回首页 → 循环
```
### 小红书养号轮次
```
首页(瀑布流)
→ Step 0: click_refresh_button() ← 必执行,预防黑屏/卡死
→ Step 1: scroll_feed_human(1-3屏) ← 拟人化滚动
→ Step 2: click_note_card(max_retries=3) ← 含误触作者→新标签页检测+重试
→ Step 3: browse_note_detail(4-12s) ← 图文/视频自适应
→ Step 4: random_interact() ← 点赞/收藏/关注随机触发
→ Step 5: comment(每3轮1次) ← pbcopy+Meta+V+Enter
→ Step 6: QR墙检测 + 返回首页 ← click_qr_wall_back_button优先
→ Step 7: 搜索发现(每2轮1次) → 返回后刷新 ← 搜索返回后加click_refresh_button
→ 循环
```
所有 `page.evaluate()` 调用均有 `asyncio.wait_for` 超时保护(8-10s),防止卡死。
## 后台运行
```bash
nohup matrix nurture run --account <name> --rounds 10 > /tmp/nurture_<acct>.log 2>&1 &
```
- 独立日志:`/tmp/nurture_<acct>.log`
- 全局日志:`/tmp/nurture.log`
- **Python stdout 缓冲问题**:后台进程日志可能延迟写入,需检查账号级日志
## 浏览器生命周期管理
### daemon 模式(重要)
- `--daemon`:养号结束后浏览器保持运行(便于调试)
- `--no-daemon`:养号结束后正常关闭浏览器释放资源
- **跨 Phase 场景**:Phase 1 抖音结束必须用 `--no-daemon` 关闭浏览器,否则 Phase 2 小红书复用同 profile 会 TargetClosedError
- `argparse.BooleanOptionalAction` 实现 `--daemon` / `--no-daemon` 双向开关
### Profile 冲突排查
**现象**:`TargetClosedError` 或页面无法操作
**根因**:两个浏览器实例争用同一 profile 目录(`.parentlock` 锁文件)
**解决**:确保前一个实例完全关闭(`conn.close()`),必要时清理 `.parentlock`
### conn.close() 实现
调用 `_camoufox_browser.close()` + `_playwright.stop()`,完整释放所有资源。
## Cookie 管理(CookieGuard)
- **模块**:`utils/cookie_manager.py` 中的 `CookieGuard(identity_name)`
- **规则**:共享 identity_dir 不能用裸 `sqlite3 DELETE`,必须用 `delete_platform_cookies_safe()` 自动备份对方平台 cookie
- **备份位置**:`backups/cookies/{identity_dir_name}/`
- **自动集成**:runner.py + matrix.py + nurture_master.sh
## 行为模拟参数(behavior.py)
13 项可配置参数控制养号行为的人性化程度:
- 点击延迟、滑动速度、浏览时长、互动概率、轮间休息等
## 账号管理
- **identities 目录**:每个身份独立文件夹(config.yaml + fingerprint.pkl + user_data/)
- **accounts.yaml**:集中管理所有账号配置(窗口位置、identity_dir 映射等)
- **窗口位置**:从 accounts.yaml 读取,运行结束不回写
- **identity_dir**:必须从 accounts.yaml 读取,不能仅用 identity_name 构造路径
## known-pitfalls
### Camoufox
- 启动失败 → 清理 `.user_data` 锁文件(`.parentlock`)
- 指纹分辨率影响 XHS 布局版本(见 AI-layout 兼容知识卡)
### Chrome
- Chrome 148+ → `Emulation.setDeviceMetricsOverride` 失效,改用 `set_viewport_size`
- macOS 窗口激活需用 AppleScript(系统限制)
### macOS 26.4
- 系统升级后 .so 文件因 Team ID 不匹配无法加载 → ad-hoc 重新签名
- 脚本:`codesign --force --sign - <file>`
### Python 后台进程
- stdout 默认缓冲导致日志延迟/丢失 → 检查账号级日志文件
- `PYTHONUNBUFFERED=1` 可强制无缓冲
## 全模拟运营架构
```
Layer 4: 管理层 排期/调度/KPI(规划中)
Layer 3: 流水线层 内容/电商/直播流水线
Layer 2: 操作层 原子操作(发布/评论/互动)
Layer 1: 数据层 每账号工作区(素材/脚本/发布记录/cookie备份)
```
@@ -0,0 +1,62 @@
---
id: KB-20260510-001
title: "Matrix 养号系统 SMS 验证码自动接收"
type: system
status: active
nature: reference
domain: system
subdomain: [matrix, 养号, 自动化]
tags: [SMS, 验证码, 抖音养号, 自动化登录]
confidence: 0.9
source: "07_matrix 养号系统代码审查"
date_created: 2026-05-10
date_modified: 2026-05-10
version: 1
summary: "SMS 验证码自动接收模块,通过 wx.tyhtak.com API 轮询获取短信验证码,替代手动输入。配置已从源码提取到 config/sms.yaml。"
collected: true
collected_date: 2026-05-16---
# SMS 验证码自动接收模块
## 架构
```
base.py — SMSHandler(抽象基类)
├── ManualSMSHandler — 手动输入(信号文件交互)
└── ApiSMSHandler — API 自动轮询(默认)
API: https://wx.tyhtak.com/api/biz/msg/messages
配置: config/sms.yaml
```
## 配置
位置:`config_template/sms.yaml`(模板)→ `scripts/config/sms.yaml`(实际)
每台机器独立,已加入 .gitignore。
```yaml
sms:
api_key: "gtmsg2026"
phone: "15370103682"
base_url: "https://wx.tyhtak.com/api/biz/msg/messages"
poll_interval: 3
timeout: 120
```
## 工作流程
```
养号脚本需要验证码
↓
ApiSMSHandler.wait() 启动轮询
↓ 每3秒拉一次API
检测到新短信 → 提取验证码(4-6位数字)
↓
返回给登录流程自动填入
```
## 注意事项
- API Key 和手机号已从源码提取到配置文件,不再硬编码
- 超时120秒,可配置
- API 不可用时会打印警告,不中断流程
@@ -0,0 +1,476 @@
# Matrix v6.0 产品规划 —— 全平台社交账号智能运营系统
> 版本: v6.0-draft | 日期: 2026-06-12
> 基于: AgentOS 联邦多机协同 + PlatformOps 架构
> 目标: 从"养号工具"升级为"全平台账号智能运营中台"
---
## 一、现状评估
### 当前能力
| 模块 | 状态 | 说明 |
|------|------|------|
| 抖音养号 | ✅ 生产可用 | 浏览/点赞/收藏/评论/搜索,93% 成功率 |
| 小红书养号 | ✅ 生产可用 | 浏览/点赞/收藏/搜索/关注,100% 成功率 |
| 多账号并行 | ✅ 生产可用 | asyncio.gather + 窗口分散 |
| 蓝图编排 | ✅ 生产可用 | JSON 定义操作序列 |
| mc CLI | ✅ 生产可用 | 统一命令入口 |
| 联邦状态上报 | ✅ 运行中 | guardd → cross_machine/data/matrix/ |
| Peekaboo 截图 | ✅ 可用 | MCP 截图调试 |
### 缺失能力
| 缺失 | 关键程度 | 说明 |
|------|---------|------|
| 短信验证码自动接收 | P0 | 登录/恢复账号必备 |
| 评论语料库 | P0 | 智能生成评论内容 |
| 定向评论任务 | P0 | 给指定 URL 视频发评论 |
| 评论互动(追评/回复) | P1 | 与作者或其他用户互动 |
| 定时错开发布 | P1 | 时间策略避免风控 |
| 账号健康度 | P1 | 限流/风控预警 |
| 数据看板 | P1 | 账号运营数据可视化 |
| 知乎/B站/微博支持 | P2 | 扩展平台 |
---
## 二、整体架构设计
```
┌─────────────────────────────────────────────────────────────────────┐
│ Matrix 运营中台 v6.0 │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ 养号引擎 │ │ 评论系统 │ │ 任务中心 │ │ 联邦协同层 │ │
│ │ (现有) │ │ (新增) │ │ (新增) │ │ (guardd) │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ └────────┬─────────┘ │
│ │ │ │ │ │
│ ┌────▼─────────────▼─────────────▼──────────────────▼──────────┐ │
│ │ PlatformOps 操作层 │ │
│ │ DouyinOps │ XhsOps │ ZhihuOps(future) │ ... │ │
│ └───────────────────────────┬──────────────────────────────────┘ │
│ │ │
│ ┌───────────────────────────▼──────────────────────────────────┐ │
│ │ Camoufox 浏览器引擎 + CDP │ │
│ └──────────────────────────────────────────────────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
│ │ SMS 验证 │ │ 语料库 │ │ 知识库 │ │ L2 记忆(facts) │ │
│ │ 模块 │ │ 引擎 │ │ 策略库 │ │ 账号健康数据 │ │
│ └──────────┘ └──────────┘ └──────────┘ └──────────────────┘ │
└─────────────────────────────────────────────────────────────────────┘
```
---
## 三、模块详细设计
### 3.1 短信验证码模块(P0)
**目标**: 自动接收短信验证码,完成账号登录/恢复/验证
**现有基础**: `03_knowledge/40_references/matrix-sms-verification.md` 已有 API 方案
```
养号脚本需要验证码
↓
ApiSMSHandler.wait() 启动轮询
↓ 每3秒拉一次API (wx.tyhtak.com / 其他供应商)
检测到新短信 → 提取验证码(4-6位数字)
↓
返回给登录流程自动填入
↓
登录完成后标记验证码已使用
```
**设计要点**:
- 抽象 `SMSHandler` 基类(已存在 `matrix_modules/account/sms/base.py`)
- 支持多供应商切换(tyhtak / 其他API / 自建短信猫)
- 手机号关联账号配置(`accounts.override.yaml` 中的 phone 字段)
- 超时 120 秒,失败告警
- 验证码消耗后标记,避免重复使用
**配置示例**:
```yaml
# config/sms.yaml
sms:
provider: tyhtak
api_key: "gtmsg2026"
poll_interval: 3
timeout: 120
```
### 3.2 评论语料库系统(P0)
**目标**: 生成真实、多样、上下文相关的评论内容
**现有基础**: `scripts/config/comment_corpus.yaml` 已有基础语料
**架构**:
```
┌─────────────────────────────────────────────────────────────┐
│ 评论语料库引擎 │
│ │
│ ┌────────────┐ ┌────────────┐ ┌──────────────────────┐ │
│ │ 静态语料池 │ │ AI 生成器 │ │ 上下文追踪器 │ │
│ │ (预设模板) │ │ (本地LLM) │ │ (已发评论/已评视频) │ │
│ └─────┬──────┘ └─────┬──────┘ └──────────┬───────────┘ │
│ │ │ │ │
│ └───────┬───────┴────────┬───────────┘ │
│ ▼ ▼ │
│ ┌────────────┐ ┌────────────┐ │
│ │ 选择策略 │ │ 安全过滤 │ │
│ │ (随机/轮询)│ │ (敏感词/重复)│ │
│ └────────────┘ └────────────┘ │
└─────────────────────────────────────────────────────────────┘
```
**语料分层**:
| 层级 | 来源 | 用途 | 特点 |
|------|------|------|------|
| L1 静态模板 | 人工预设 | 日常普通评论 | "学到了"、"真不错"、"支持" |
| L2 关键词模板 | 按视频类型匹配 | 相关评论 | 科技→"技术流"、美食→"看着就好吃" |
| L3 AI 生成 | 本地 oMLX + Qwen | 精准评论 | 根据视频标题/描述生成 |
| L4 上下文延续 | 追评/回复 | 互动 | 基于已有评论内容 |
**存储**:
```yaml
# matrix_modules/comment/corpus.yaml
corpus:
douyin:
- text: "学到了"
tags: [通用, 知识]
weight: 0.3
- text: "这个厉害了"
tags: [通用, 技术]
weight: 0.2
xiaohongshu:
- text: "好实用呀"
tags: [通用, 教程]
weight: 0.3
```
### 3.3 定向评论任务系统(P0)
**目标**: 接收指定 URL,让所有账号去该视频下评论,时间错开、内容不同
**工作流程**:
```
用户/智能体下发任务:
"给这些视频发评论: [url1, url2, url3]"
↓
任务中心解析 →
提取视频ID → 分析视频内容/标题 → 确定评论策略
↓
生成评论计划 →
每个账号 → 分配不同的评论内容 → 设置时间偏移
↓
任务写入 cross_machine/tasks/ →
持久化到 cross_machine/data/matrix/comment_tasks/
↓
各机器 guardd 检测到新任务 →
按计划执行评论(时间错开 5-30 分钟)
↓
完成后上报结果 →
cross_machine/data/matrix/comment_results/{uid}.json
```
**任务格式**:
```json
{
"task_id": "comment_20260612_001",
"url": "https://www.douyin.com/video/xxx",
"platform": "douyin",
"type": "batch_comment",
"strategy": "diverse",
"accounts": ["douyin_01", "douyin_02"],
"time_window": {"start": "10:00", "end": "12:00"},
"min_interval": 300,
"assigned": {
"douyin_01": {"text": "讲得真好,学到了", "time": "10:05"},
"douyin_02": {"text": "这个角度很新颖", "time": "10:12"}
},
"context": {"video_title": "xxx", "author": "yyy"},
"status": "pending"
}
```
### 3.4 评论互动系统(P1)
**目标**: 追评、回复作者回复、与其他用户互动
**场景**:
1. 发布评论后 → 如果作者回复了 → 自动追评回复
2. 其他用户回复了我们的评论 → 选择性回复
**技术方案**:
- 评论发布后记录 `{comment_id, video_id, account}`
- 定时检查是否有新回复(通过评论区 DOM 或 API)
- 检测到回复 → 加载回复内容 → 确定回复策略 → 回复
**频率控制**:
- 每天最多回复 5 条/账号
- 回复间隔至少 30 分钟
- 回复内容需与原文相关
### 3.5 账号健康度与反检测(贯穿全局)
**风险维度**:
| 风险 | 检测方式 | 应对措施 |
|------|---------|---------|
| 操作频率过高 | 各操作 rate limit | 按分钟/小时/天三级限速 |
| 行为模式单一 | 蓝图随机化 + wait_jitter | 操作间隔随机化 |
| 内容重复 | 语料库去重 | 同一内容不重复使用 |
| 登录地点异常 | IP 检测 | 静态住宅 IP / 代理 |
| 设备指纹一致 | BrowserForge | 每账号独立指纹 |
| 评论时间集中 | 时间策略 | 错开 5-30 分钟 |
| 评论内容异常 | AI 质量检测 | 敏感词过滤 + 长度变化 |
**账号健康度评分**:
```python
class AccountHealth:
def score(self, account_id) -> dict:
return {
"overall": 85, # 0-100
"risk_level": "low", # low/medium/high
"metrics": {
"daily_ops": 45, # 今日操作数
"op_freq": 0.8, # 操作频率 vs 安全阈值
"comment_rate": 0.3, # 评论占比
"repeat_rate": 0.05, # 内容重复率
"fail_rate": 0.1, # 操作失败率
"days_active": 15, # 连续活跃天数
},
"alerts": [] # 预警列表
}
```
### 3.6 联邦协同(增强现有 guardd)
**新增 State 类型**:
```yaml
# cross_machine/data/matrix/{uid}.json 新增字段
{
"plugin": "matrix",
"version": "6.0.0",
"machine_uid": "...",
"hostname": "...",
"timestamp": "...",
"data": {
"注册表账号": 4,
"本机": 4,
"本机已启用": 4,
"本机已登录": 4,
"各机器": {...},
"今日评论": 12, # 新增
"今日互动": 3, # 新增
"账号健康度": { # 新增
"douyin_test": {"score": 85, "alerts": []}
},
"待处理任务": 2, # 新增
"任务队列": [ # 新增
{"id": "comment_xxx", "type": "batch_comment", "status": "pending"}
]
}
}
```
### 3.7 定时策略引擎
**核心规则**:
- 养号时间分布:分散在 8:00-22:00,每次 15-30 分钟
- 评论间隔:同一视频不同账号间隔 5-30 分钟
- 跨视频间隔:同一账号不同视频间隔 10-60 分钟
- 账号休息日:每周 1-2 天静默
**策略配置**:
```yaml
strategy:
daily:
time_windows: ["09:00-09:30", "14:00-14:30", "20:00-20:30"]
round_per_window: 2
interval_between_rounds: 45-90
comment:
min_interval: 300 # 同账号评论最短间隔(秒)
max_daily: 10 # 单账号每天最多评论
batch_spread: 1800 # 同一批任务最大散布时间(秒)
rest_day:
probability: 0.15 # 每天有 15% 概率静默
```
### 3.8 监控看板(P1)
在现有 `10_dashboard` 基础上扩展 Matrix 插件:
```python
class MatrixPlugin(DashboardPlugin):
# 新增视图
def get_sub_views(self):
return [
{"key": "overview", "label": "总览"},
{"key": "accounts", "label": "账号管理"},
{"key": "daily_ops", "label": "今日运营"},
{"key": "comments", "label": "评论任务"},
{"key": "health", "label": "健康度"},
{"key": "blueprints", "label": "蓝图管理"},
]
```
---
## 四、实施路线图
```
Phase 1(2-3天)—— 基础能力补齐
├── SMS 验证码模块 → 对接现有 API
├── 静态语料库建立 → 从现有 comment_corpus.yaml 扩展
└── 评论任务原型 → mc comment 子命令
Phase 2(3-5天)—— 评论系统
├── 定向评论任务(指定 URL → 多账号评论)
├── 时间策略引擎(错开时间)
├── AI 生成评论(对接本地 oMLX)
└── 跨机器任务分发(cross_machine/tasks/)
Phase 3(3-5天)—— 互动系统
├── 追评(作者回复后自动回复)
├── 评论上下文追踪
├── 回复其他用户评论
└── 互动频率控制
Phase 4(持续)—— 平台扩展
├── 知乎平台接入(ZhihuOps)
├── B站平台接入(BilibiliOps)
├── 微博平台接入(WeiboOps)
└── 通用平台框架
Phase 5(持续)—— 智能优化
├── 行为策略自动调优(基于健康度反馈)
├── 评论质量评估
├── 账号休眠/恢复策略
└── 联邦协同决策(多机器共享策略)
```
---
## 五、现有项目参考
### 5.1 同类项目分析
| 项目 | 优势 | 不足 | 可借鉴 |
|------|------|------|--------|
| **MediaCrawler** | 多平台采集,代码开源 | 无养号运营,无评论系统 | 平台适配模式 |
| **水军SaaS平台** | 评论任务分发成熟 | 云端不安全,封号风险高 | 任务队列模型 |
| **OpenClaw** | 浏览器自动化,反检测 | 没有养号业务逻辑 | 反检测指纹技术 |
| **TikOmni** | TikTok 自动化完整 | 付费,不开源 | 商业产品思路 |
### 5.2 AgentOS 独特优势
| 能力 | 其他项目 | AgentOS + Matrix |
|------|---------|------------------|
| 部署方式 | 单机/云端 | **多机联邦,本机安全** |
| 账号安全 | 明文上传 | **配置在 agent-local,不同步** |
| 智能决策 | 固定规则 | **智能体+知识库+记忆系统** |
| 数据积累 | 无/外部 | **L2 facts.db + 知识库沉淀** |
| 跨机协同 | 无 | **guardd + cross_machine** |
| 平台扩展 | 需重写 | **PlatformOps 接口,新增 ops 文件** |
---
## 六、项目目录结构规划
```
05_tools/07_matrix/
├── mc ← CLI 入口
├── install.sh ← 新机部署
├── README.md / TOOL.md / MODULE.md
├── blueprints/ ← 任务蓝图
│
├── scripts/
│ ├── mc/ ← CLI 引擎
│ │ ├── cli.py
│ │ ├── engine.py ← 养号引擎
│ │ ├── runlog.py ← 运行日志
│ │ └── corpus.py ← 语料库(现有)
│ │
│ ├── ops/ ← 平台操作层(现有)
│ │ ├── _base.py
│ │ ├── douyin_ops.py
│ │ └── xhs_ops.py
│ │
│ ├── matrix_modules/ ← 功能模块
│ │ ├── comment/ ← 评论系统(新增)
│ │ │ ├── __init__.py
│ │ │ ├── corpus.py ← 语料库管理
│ │ │ ├── generator.py ← AI 评论生成
│ │ │ ├── task.py ← 评论任务队列
│ │ │ ├── scheduler.py ← 时间策略
│ │ │ └── tracker.py ← 评论上下文追踪
│ │ │
│ │ ├── sms/ ← 短信验证(新增)
│ │ │ ├── base.py ← 抽象基类(已有)
│ │ │ ├── tyhtak.py ← tyhtak API 实现
│ │ │ └── config.py ← 供应商配置
│ │ │
│ │ └── health/ ← 健康监控(新增)
│ │ ├── scorer.py ← 健康度评分
│ │ ├── alerts.py ← 预警
│ │ └── reporter.py ← 状态上报
│ │
│ └── config/ ← 配置(新增)
│ ├── comment_corpus.yaml ← 语料库
│ └── sms.yaml ← SMS配置
│
└── docs/
└── MATRIX_V5_GUIDE.md ← 现有文档
```
---
## 七、关键设计原则
### 7.1 反检测第一
所有操作设计优先考虑反检测:
1. **频率控制**: 每个操作独立 rate limit(like/comment/search/follow)
2. **时间随机化**: 所有等待时间加 jitter ±30%
3. **内容去重**: 同一内容不在 7 天内重复
4. **IP 分散**: 多账号用不同代理出口
5. **行为多样性**: 每次养号随机选择蓝图组合
6. **账号休息**: 模拟真人作息(夜间不操作)
### 7.2 联邦优先
1. 每台机器独立执行本地任务
2. 任务通过 cross_machine 文件异步传递
3. 机器间不直接通信(避免网络暴露)
4. 任务结果通过 Git 被动同步
5. Dashboard 统一展示联邦状态
### 7.3 渐进增强
1. 现有功能不动(养号引擎稳定)
2. 新功能先以独立模块开发
3. 通过 mc CLI 子命令暴露新功能
4. 每完成一个模块就做回归测试
5. 保持向后兼容
---
## 八、风险与缓解
| 风险 | 影响 | 缓解 |
|------|------|------|
| 平台接口变更 | 选择器失效 | 多级选择器 fallback + 定期验证 |
| 封号 | 账号损失 | 健康度预警 + 操作上限 + 新号先养 |
| 浏览器检测 | 所有账号受影响 | Camoufox 指纹隔离 + BrowserForge |
| 短信API不可用 | 无法登录 | 多供应商切换 + 手动兜底 |
| 代理不稳定 | 操作失败 | 自动切换代理 + 超时重试 |
| 跨机冲突 | 同一任务重复执行 | 任务状态机 + TTL |
@@ -0,0 +1,230 @@
---
title: 小红书养号页面交互技术
tags: [xhs, browse, interaction, qr-wall, refresh, black-screen, ai-layout, tab-detection, timeout]
created: 2026-05-29
updated: 2026-05-29
nature: method
collected: true
collected_date: 2026-06-09
---
## 核心选择器
### 首页/瀑布流
- 瀑布流容器:`#app .layout.limit`
- 笔记卡片:`section.note-item`(DOM 分析确认)
- 卡片封面链接:`a.cover.mask.ld`
- 卡片图片:`a.cover.mask.ld img`
### 笔记详情页
- 详情容器:`.note-detail, [class*=note-detail], .note-page`
- 标题:`.title, h1, [class*=note-title]`
- 内容:`.content, [class*=content], .desc`
### 弹窗/遮罩
- 登录弹窗:`[class*=login], [class*=modal], [role=dialog], .reds-alert`
- 通用遮罩:`[class*=mask], [class*=overlay], [class*=modal]`
### 锚点验证
| 锚点类型 | 选择器 |
|----------|--------|
| 首页 | `section.note-item` |
| 笔记详情 | `.note-detail, [class*=note-detail], .title, h1` |
| 视频页 | `video` |
| 评论打开 | `.comment-section, [class*=comment-section]` |
| 搜索页 | `.search-result, [class*=search-result]` |
## JS 智能查找函数
### find_refresh_button_js()
三策略查找瀑布流页面右下角 FAB 刷新按钮:
1. **选择器匹配**:`button[class*="refresh"]`、`[class*="fab"]`、`[class*="floating"]` 等
2. **SVG 扫描**:查找包含旋转箭头路径的 SVG 元素(刷新图标 = arc + rotate 特征)
3. **fixed 定位过滤**:右下角区域(x > viewport 60%, y > viewport 60%)的可点击元素
返回 `{found, x, y, w, h, text, method}`
### find_qr_wall_back_button_js()
检测 QR 检测墙并定位返回首页按钮:
1. **QR 墙关键词检测**:body 文本包含"扫码"/"二维码"/"非常用登录"/"验证"等
2. **返回按钮匹配**:优先级排序 — "返回首页"(10) > "返回"(20) > "首页"(30) > "确定/我知道了"(50)
3. **候选过滤**:宽度/高度 > 5px(排除不可见元素),文本长度 < 15 字符
返回 `{found, x, y, w, h, text, priority}`
### dismiss_login_modal_js()
隐藏登录弹窗和固定定位遮罩层。设置 `display:none` 而非移除 DOM。
### get_note_cards_js()
获取瀑布流所有笔记卡片的 index、href、title、rect 信息。
## 鼠标模拟技术
### L 型鼠标路径(_l_shaped_click)
模拟真人鼠标移动轨迹:
```
起点(随机偏移) → 水平移动(5-10步) → 垂直移动(3-8步) → 微抖动(±2px) → 点击
```
- 每步延迟 10-30ms(随机),总耗时 100-400ms
- 起点偏移范围:x ±150px, y -100~+50px
- 限制在视口内(防止鼠标移出窗口)
- 微抖动模拟手指不稳
### 双击策略(聚焦→执行)
macOS 窗口激活限制下,点击需要先聚焦再执行:
1. 第一次点击 → 聚焦窗口(可能不触发元素事件)
2. 第二次点击 → 实际执行操作
## 误触作者主页(新标签页)检测
点击笔记卡片时可能点到作者头像/名称,导致新标签页打开作者主页。
### 检测方法(确定性锚点)
```
点击前: tabs_before = len(context.pages)
执行点击(Playwright click)
点击后: if len(context.pages) > tabs_before → 误触作者
```
- 新 tab URL 即为作者主页地址
- 关闭新 tab,回到原 tab,重新选卡片重试(最多 3 次)
- 3 次全部误触才返回 None(本轮失败,不导致全局退出)
### 代码位置
`browse.click_note_card(page, max_retries=3)`:
- 使用 `page.context.pages` 获取所有标签页
- 点击后比对 tab 数量变化
- 比截图 + AI 分析更可靠,是确定性锚点
## page.evaluate() 超时保护
### 问题
Playwright 的 `page.evaluate()` 在页面状态异常时会**无限挂起**,无默认超时。卡死时不会抛出异常,整个 asyncio 循环停滞。
### 受影响的函数
所有涉及 `page.evaluate()` 的操作都可能卡死:
- `dismiss_login_modal()` — 登录弹窗关闭
- `get_note_cards()` — 获取卡片列表
- `click_note_card()` — 内部调用 get_note_cards
- `browse_note_detail()` — 视频检测
- `click_refresh_button()` — 刷新按钮查找
- `click_qr_wall_back_button()` — QR墙按钮查找
### 修复
全部加 `asyncio.wait_for()` 超时保护:
```python
result = await asyncio.wait_for(
page.evaluate(some_js_function()),
timeout=10 # 秒
)
```
### 超时时间表
| 函数 | 超时 | 说明 |
|------|------|------|
| click_refresh_button | 10s | JS 三策略扫描,最复杂 |
| click_qr_wall_back_button | 10s | QR 墙检测 + 按钮定位 |
| get_note_cards | 10s | DOM 卡片遍历 |
| dismiss_login_modal | 8s | 简单 DOM 操作 |
| browse_note_detail (视频检测) | 8s | 简单 DOM 查询 |
### 搜索结果页刷新按钮
搜索页(URL含 `/search`)没有右下角 FAB 刷新按钮,`click_refresh_button()` 会在 10s 超时后安全返回 False,不会卡死。
## 常见问题与恢复策略
### 黑屏恢复
**现象**:瀑布流页面变黑,卡片不可见
**根因**:SPA 状态异常,非窗口移出屏幕
**恢复链**:
```
1. scroll_feed 回到顶部 → 检测卡片
2. click_bottom_nav_tab("发现") → 刷新页面状态
3. goto_home() → 直接导航兜底
```
### QR 检测墙恢复
**现象**:中央弹出大弹窗,提示"扫码"/"非常用登录"
**根因**:XHS 非常用登录检测触发,非登录状态失效
**恢复链**:
```
1. click_qr_wall_back_button() → 点弹窗上的"返回首页"按钮
2. click_bottom_nav_tab("发现") → 底部导航恢复
3. go_back_to_home() → 直接导航兜底
```
**重要区别**:QR 墙 ≠ 未登录。QR 墙是频控触发,多刷会恢复。未登录二维码弹窗是另一种情况。
### 每轮必刷新策略(Step 0)
为彻底防止瀑布流黑屏/卡死,小红书养号每轮循环开头**强制**点击右下角刷新按钮:
```
每轮循环:
Step 0: click_refresh_button() ← 必执行(模拟鼠标点 FAB)
Step 1: scroll_feed_human()
Step 2: click_note_card()
...
搜索返回后: click_refresh_button() × 1 ← 回到首页后也刷新
```
- 找不到刷新按钮时不中断,仅跳过并记日志(搜索结果页无 FAB)
- `click_refresh_button()` 自带 10s 超时保护,不会卡死
- 原锚点失败时的刷新逻辑保留作为兜底
### 首页锚点验证失败
```
1. click_refresh_button() → 点右下角物理刷新按钮(优先,模拟真人)
2. page.reload() → API 刷新(fallback)
3. init_anti_detection() → 重新初始化反检测
```
### AI-layout 兼容(A/B 测试)
**触发条件**:指纹分辨率 + DPR(低分屏 1920x1080 DPR=1.0 易触发)
**差异**:无顶部搜索栏、无 header-container、首卡 y 偏移 272px vs 144px
**兼容措施**:
- `search()`:标准输入框 → ALT 输入框 → URL fallback(三重降级)
- `click_search_result()`:标准选择器 → 通用 href 匹配
- 启动时自动检测布局版本(standard/ai-layout/unknown)
**指纹建议**:screen ≥ 1920x1080, DPR ≥ 1.25
## 登录检测规则
1. **顺序**:页面级登录检测 → dismiss_login_modal(先检测再关闭,否则误判)
2. **等待**:首页加载后等 5 秒(给弹窗渲染时间)
3. **关键词**:"登录之后更精彩" / "扫码登录" / "手机号登录" / "请登录" / "立即登录"
4. **尺寸区分**:`getBoundingClientRect(width>200, height>100)` 区分导航栏 vs 模态弹窗
## 操作前状态检查清单
进入每轮养号前:
1. 首页锚点验证(`section.note-item` 存在)
2. 登录弹窗关闭
3. 反检测初始化
4. Cookie/Session 检查(非必需,未登录也可浏览)
@@ -0,0 +1,64 @@
---
title: 指纹分辨率触发小红书 AI-layout 版本
tags: [xhs, fingerprint, ai-layout, resolution]
created: 2026-05-27
collected: true
collected_date: 2026-06-09
---
## 现象
xhs_03(douyin_camo01)的首页布局和其他两个账号不同:
- 没有顶部搜索栏(`input.search-input` 不存在)
- 没有顶部 `header-container`
- 首卡 y 偏移从 144px → 272px
- 主容器 class 是 `ai-layout-active`
- 但 `section.note-item` 选择器兼容,卡片正常
## 根因分析
通过修改指纹确认:**屏幕分辨率 + devicePixelRatio 触发了 XHS 的 A/B 测试版本分配。**
### 三账号指纹对比
| 特征 | xhs_01 | xhs_02 | xhs_03(改前) | xhs_03(改后) |
|------|--------|--------|----------------|----------------|
| Screen | 2752x1152 | 2176x1224 | **1920x1080** | 2752x1152 |
| DPR | 1.25 | 1.76 | **1.0** | 1.25 |
| 字体数 | 20 | 20 | **16** | 20(未改) |
| 布局 | standard | standard | **ai-layout** | **standard** ✅ |
### 验证方法
1. 读取 xhs_03 的 `fingerprint.pkl` → `screen.width=1920, screen.height=1080, devicePixelRatio=1.0`
2. 修改为 xhs_01 的规格(2752x1152, DPR=1.25)
3. 清除 XHS cookies + localStorage(清楚 A/B 分配缓存)
4. 重新加载 → **布局变为标准版**(搜索框出现、top bar 恢复、首卡 y=144)
## 结论
**XHS 会基于指纹的 screen 分辨率 + DPR 分配不同的 UI 版本。**
- 低分屏(1920x1080, DPR=1.0)→ `ai-layout-active`(无搜索栏、无顶栏)
- 高分屏(2752x1152, DPR=1.25+)→ 标准版
## 新建账号的指纹建议
为避免触发 AI layout 导致代码兼容问题:
```
fingerprint screen: 推荐 ≥ 1920x1080, DPR ≥ 1.25
具体建议值:
screen.width: 1920 或更高(如 2752)
screen.height: 1080 或更高
devicePixelRatio: 1.25 ~ 2.0
availWidth: 匹配 screen.width
availHeight: screen.height - 48
```
## 代码兼容(已做)
即使遇到 AI layout,代码也做了兼容处理:
- `browse.py search()`: 三重降级(标准 → ALT → URL fallback)
- `browse.py click_search_result()`: 标准选择器 → href 通用匹配
- `runner.py`: 启动时自动检测布局版本(standard/ai-layout)
@@ -0,0 +1,68 @@
---
id: KB-SYS-MEMORY
title: "记忆系统索引"
type: reference
date_created: 2026-05-03
date_modified: 2026-05-03
description: "AgentOS 记忆系统结构总览——所有记忆组件的入口"
---
# 🧠 记忆系统索引
> 记忆系统位于 `04_memory/`,本文档提供从 Obsidian 访问记忆的入口。
> 每日记忆摘要已通过软链接同步到 `01_daily/memory/`,可在 Obsidian 直接全文搜索。
---
## 一、记忆组件一览
| 组件 | 位置 | 格式 | 说明 | 可搜索? |
|------|------|------|------|---------|
| **每日摘要** | [[01_daily/memory/]] | Markdown | 每日对话提炼的关键事实 | ✅ Obsidian全文搜索 |
| **跨机器注册表** | `04_memory/cross_machine/registry/` | JSON | 各机器的注册信息 | ❌
| **L1 关键词索引** | `04_memory/long_term/` | JSON | BM25 关键词索引 | ❌
| **L2 结构化事实** | `04_memory/long_term/facts.db` | SQLite | 带置信度的事实数据 | ❌
| **L3 原文存档** | `agent-local/memory/raw/` | Markdown | 原始对话记录 | ❌(不同步)|
| **错误日志** | `04_memory/logs/` | 文本 | 错误记录 | ❌ |
| **工作日志** | `04_memory/daily_logs/` | Markdown | 夜间自动化执行记录 | ⏳ 规划中 |
---
## 二、每日摘要索引
| 日期 | 摘要 | 状态 |
|------|------|------|
| 2026-05-03 | — | ⏳ 今夜自动化生成 |
---
## 三、在 Obsidian 中搜索记忆
### 方式1:全文搜索(Obsidian 原生)
```
搜索范围: 01_daily/memory/ 下的所有 .md 文件
操作方法: Cmd+Shift+F → 输入关键词
搜索对象: 每日摘要中的关键事实
```
### 方式2:语义搜索(对话中发起)
```
说: "搜一下记忆,关于[关键词]"
底层: ChromaDB 向量检索 + BM25 关键词
效果: 理解语义,搜到相关记忆条目
```
### 方式3:查看索引
```
本页面提供全部记忆组件的链接和说明。
可以直接点击 [[01_daily/memory/]] 浏览所有每日摘要。
```
---
## 四、记忆系统架构
详见 [[99_system/architecture/loading-architecture|加载与检索架构]](管道④:记忆系统分层检索)
@@ -0,0 +1,312 @@
---
id: KB-20260503-002
title: "内容收集全链路规范 v2.0"
type: method
status: active
nature: method
domain: personal-management
subdomain: [知识管理, 自动化]
tags: [pipeline, 收集, 收件箱, 提纯, 多机同步, 规范]
confidence: 1.0
source: "AgentOS 系统设计"
source_type: system
date_created: 2026-05-03
date_modified: 2026-05-03
version: 2
aliases: [收集链路规范 v2]
keywords: [收集, 收件箱, 提纯, 提交, 知识入库, 素材, 采集路由]
summary: "统一的内容收集全链路规范——所有机器统一流程,按收集子类型路由,区分知识类与素材类,支持即时与批量双模式"
related: ["KB-20260503-001"]
previous_version: "KB-20260503-002 (v1)"
superseded_by: ""
---
# 内容收集全链路规范 v2.0
> 最后更新:2026-05-03
> 所有机器统一流程,不区分主从。收集内容统一进提交箱,按类型路由处理。
---
## 一、核心设计原则
```
1. 所有机器统一流程 → 角色切换不影响
2. 收集内容先进提交箱 → 再决定即时还是批量
3. 收集子类型决定提取方式 → 不是所有收集都是为了知识
4. 知识类 vs 素材类分流 → 素材不进提纯流水线
5. 即时处理 = 提交箱→收件箱→提纯→返回结果
6. 批量处理 = 提交箱→(定时)→收件箱→提纯→入库
```
---
## 二、目录体系
| 目录 | 角色 | 谁使用 |
|------|------|--------|
| `01_submissions/` | **收集提交箱**(所有机器收集的内容统一放这里) | 所有机器 |
| `00_inbox/` | **待提纯收件箱**(等待 AI 分类入库) | 提纯时使用 |
| `10_concepts/` ~ `60_opinions/` | **知识归档** | 提纯后写入 |
| `agent-local/materials/` | **素材仓库**(背景音乐/截图/原图/视频片段,不提纯) | 直接存储 |
### submissions 结构
```
01_submissions/
├── 20260503_social-wisdom_video.md ← 机器A 收集的抖音视频
├── 20260503_article_xxx.md ← 机器B 收集的文章
└── 20260503_bg-music_yyy.md ← 收集的背景音乐(素材类)
```
> 不分子目录,所有机器平等。文件名 `{YYYYMMDD}_{slug}_{source_type}.md`
---
## 三、两个入口:知识 vs 素材
整个系统只有 **两个入口命令**,用户通过关键词区分意图:
```
"收集这个..." → 知识类采集 → 走完整 pipeline(提交箱→提纯→入库)
"收集素材..." → 素材类分析 → 直存 materials/(不经过提纯流水线)
```
### 入口对比
| 你说 | 含义 | purpose | 去向 | 后续 |
|------|------|---------|------|------|
| `收集这个视频` | 知识收集 | knowledge | → 01_submissions/ | 等待提纯入库 |
| `收集素材` | 素材分析 | material | → materials/ | 不经过提纯 |
| `收集素材,视频结构` | 素材+分析维度 | material | → materials/ + AI分析结果 | 不经过提纯 |
### 素材子类型(分析维度)
"收集素材"后面可以跟分析维度,决定 AI 怎么分析这个视频/内容:
| 你说 | collect_subtype | AI 分析内容 | 输出 |
|------|----------------|-------------|------|
| `收集素材` | default | 仅保存原始内容 | 文件 + 基础信息 |
| `收集素材,视频结构` | video-structure | 分析起承转合、节奏分段、内容框架 | analysis 报告 |
| `收集素材,拍摄脚本` | shooting-script | 提取/重建拍摄脚本、分镜描述 | script 文件 |
| `收集素材,镜头运镜` | camera-movement | 分析镜头类型(推拉摇移跟)、构图方式 | analysis 报告 |
| `收集素材,前三秒钩子` | opening-hook | 分析开头 3 秒的吸引点、悬念设置 | analysis 报告 |
| `收集素材,悬疑点` | suspense-points | 提取内容的悬疑设计、反转点、冲突点 | analysis 报告 |
| `收集素材,文案结构` | copy-structure | 分析文案的黄金圈、痛点-方案-结果等框架 | analysis 报告 |
### 完整采集路由表(v2.0 合并版)
| 入口关键词 | 内容类型 | 子类型 | 用途 | 输出 |
|-----------|----------|--------|------|------|
| `收集这个` | douyin-video | default | 知识 | → 01_submissions/ |
| `收集这个` | douyin-video | subtitle | 知识 | → 01_submissions/ |
| `收集这个` | webpage | default | 知识 | → 01_submissions/ |
| `收集这个` | webpage | fulltext | 知识 | → 01_submissions/ |
| `收集这个` | audio | transcription | 知识 | → 01_submissions/ |
| `收集这个` | audio | summary | 知识 | → 01_submissions/ |
| `收集素材` | douyin-video | default(保存) | 素材 | → materials/videos/ |
| `收集素材` | douyin-video | video-structure | 素材 | → materials/ + analysis |
| `收集素材` | douyin-video | shooting-script | 素材 | → materials/ + script |
| `收集素材` | douyin-video | camera-movement | 素材 | → materials/ + analysis |
| `收集素材` | douyin-video | opening-hook | 素材 | → materials/ + analysis |
| `收集素材` | douyin-video | suspense-points | 素材 | → materials/ + analysis |
| `收集素材` | douyin-video | copy-structure | 素材 | → materials/ + analysis |
| `收集素材` | audio | raw | 素材 | → materials/audios/ |
| `收集素材` | image | default | 素材 | → materials/images/ |
| wechat-article | **默认** | 提取标题+正文 | 知识 | → 01_submissions/ |
| audio | `转文字` | 语音转文字(whisper) | 知识 | → 01_submissions/ |
| audio | `汇总` | 提取内容摘要 | 知识 | → 01_submissions/ |
| audio | `原文件` | 仅保存音频文件 | 素材 | → materials/ |
| image | **默认** | 保存原图 + OCR 文字(如有) | 素材 | → materials/ |
| text/note | **默认** | 保存原文 | 知识 | → 01_submissions/ |
### 3.4 用户指令与路由映射
| 你说 | 路由结果 |
|------|----------|
| `收集这个视频` | 自动识别来源 → 默认提取(标题+描述+标签)→ 知识类 |
| `收集这个视频的字幕` | douyin-video + 字幕 → 知识类 |
| `收集这个视频的背景音乐` | douyin-video + 背景音乐 → 素材类 |
| `收集这个视频的音频` | douyin-video + 音频下载 → 素材类 |
| `收集这个视频的截图` | douyin-video + 截图 → 素材类 |
| `总结这个视频` | douyin-video + AI 总结 → 知识类 |
| `收集这个链接` | 自动识别 → 默认提取 → 知识类 |
| `收集这篇文章` | webpage + 默认 → 知识类 |
| `收集这个音频` | audio + 默认(转文字)→ 知识类 |
| `收集这个音频的背景音` | audio + 原文件 → 素材类 |
| `收集这张图片` | image + 默认 → 素材类 |
| `提取这首歌` | audio + 原文件 → 素材类 |
### 3.5 收集输出格式
**知识类** 输出到 `01_submissions/`:
```markdown
---
title: "原标题"
collect_type: "douyin-video"
collect_subtype: "default" # default / subtitle / audio / screenshot / summary
purpose: "knowledge" # knowledge / material
source_url: "原始链接"
source_author: "作者名"
source_date: "发布日期"
collected_by: "机器名"
collected_date: "2026-05-03"
status: submitted
tags: [标签1, 标签2]
---
## 原文信息
{提取的主要内容}
## 原始链接
{source_url}
```
**素材类** 输出到 `agent-local/materials/`:
```markdown
---
title: "素材名称"
collect_type: "douyin-video"
collect_subtype: "bgm"
purpose: "material"
source_url: "来源链接"
collected_date: "2026-05-03"
---
素材文件:{文件路径}
用途说明:{背景音乐/截图/原图等}
```
---
## 四、处理模式:即时 vs 批量
| 模式 | 触发方式 | 流程 |
|------|----------|------|
| **即时** | `提纯这个` | COLLECT → 01_submissions → 00_inbox → REFINE → 返回结果 |
| **批量** | 定时(每日 02:00) | COLLECT → 01_submissions →(等待)→ STAGE → REFINE → STORE → INDEX |
### 4.1 即时模式
```
你:"收集这个视频,提纯它"
↓
① COLLECT → 提取内容 → 写入 01_submissions/
↓
② 即时转入 00_inbox/
↓
③ REFINE → AI 分类 → 写入对应目录
↓
④ 返回:内容和分类结果给你
```
### 4.2 批量模式
```
你:"收集这个视频"
↓
① COLLECT → 提取内容 → 写入 01_submissions/(等待)
↓
(凌晨 02:00 定时任务)
↓
② STAGE → 01_submissions/ → 00_inbox/
↓
③ REFINE → AI 分类 → 写入对应目录 + 更新索引
```
### 4.3 触发词速查
| 你说 | 模式 | 说明 |
|------|------|------|
| `收集这个...` | 批量 | 进提交箱,等定时处理 |
| `收集这个...并提纯` | 即时 | 进提交箱 → 立即提纯 → 返回结果 |
| `提纯这个` | 即时 | 对刚收集的内容立即提纯 |
| `归集` | 批量触发 | 手动触发批量归集流程 |
| `提纯所有` | 批量触发 | 手动触发批量提纯 |
---
## 五、完整流程示例
### 场景:即时收集抖音视频并提纯
```
你:"收集这个视频并提纯"
↓
我识别: 抖音视频 → 默认提取(标题+描述+标签)
↓ ← 如果链接是纯音频则走 audio 路由
判断: 知识类
↓
写入 01_submissions/20260503_social-wisdom_douyin-video.md
↓
标记为即时 → 立即转入 00_inbox/
↓
运行 REFINE:
├── AI 判定 nature:concept / domain:personal-management
├── 套用 concept-card 模板
└── 写入 10_concepts/social-wisdom-10-rules.md
↓
返回结果:
"已收集并提纯完成。内容已存入 10_concepts/ 目录。
共 9 条社会智慧,分类为 概念/个人管理。"
```
### 场景:收集背景音乐(素材类)
```
你:"收集这个视频的背景音乐"
↓
我识别: 抖音视频 → 音频提取
↓
判断: 素材类(不是知识)
↓
下载音频文件 → 保存到 agent-local/materials/audios/
↓
创建素材记录 → agent-local/materials/audios/20260503_bgm_xxx.md
↓
返回结果:
"背景音乐已保存到 materials/audios/ 目录。
文件名:20260503_bgm_xxx.mp3"
```
### 场景:批量收集一篇知乎文章
```
你:"收集这篇文章"
↓
我识别: 网页文章 → 默认提取
↓
判断: 知识类
↓
写入 01_submissions/20260503_zhihu-article_webpage.md
↓
返回结果:
"已收集。文章将在下次定时提纯时处理(每日 02:00)。
如需立即处理,请说:提纯这个"
```
---
## 六、系统状态速查
| 你说 | 返回 |
|------|------|
| `收集状态` | 提交箱 N 条待处理 / 收件箱 N 条待提纯 / 上次提纯时间 |
| `待处理` | 列出提交箱中所有待归集的内容 |
| `待提纯` | 列出收件箱中所有待提纯的内容 |
---
## 七、本规范与现有技能的关系
| 技能 | 角色 | 说明 |
|------|------|------|
| `content_processor` | 采集入口 | 实现 COLLECT 节点的路由逻辑(视频/音频/文章/图片分发) |
| `collect_to_inbox` | 归集 | 实现 STAGE 节点(01_submissions/ → 00_inbox/) |
| `inbox_refine` | 提纯 | 实现 REFINE 节点(AI 分类 + 模板 + 入库 + 索引) |
> 当前 `content_processor` 技能已存在,但路由表尚未按本规范更新。
> `collect_to_inbox` 和 `inbox_refine` 技能已按此流程工作。
@@ -0,0 +1,49 @@
# 知识分类提示词
> 用于 kb_ingest.py 中调用 LLM 对知识进行自动分类
## Prompt
你是一个知识分类助手。请对以下内容进行分析,返回 JSON 格式的分类结果。
### 输入内容
```
{{content}}
```
### 分析要求
1. **domain**: 从以下列表中选择最相关的 1-3 个领域:
计算机科学, 人工智能, 金融, 法律, 医学, 物理, 数学, 心理学, 哲学, 历史, 工程, 设计, 商业, 个人管理, 个人洞见, 其他
2. **nature**: 判断这条知识的属性类型:
- fact: 已验证的客观事实(有数据/论文支持)
- opinion: 主观观点(个人看法、推测)
- method: 可操作的方法/教程
- regulation: 法律/规章制度
- reference: 参考资料/外部链接
- data: 测试数据/基准结果
- quote: 他人原话引用
- axiom: 公理/无需证明的基础原理
3. **confidence**: 可信度评分(0-1):
- 官方文档/学术论文: 0.8+
- 知名技术博客: 0.6-0.8
- 个人博客/论坛: 0.4-0.6
- 推测性内容: <0.4
4. **tags**: 3-5 个关键词标签
5. **summary**: 60 字以内的一句话摘要
### 输出格式
```json
{
"domain": ["领域1", "领域2"],
"nature": "fact",
"confidence": 0.85,
"tags": ["标签1", "标签2", "标签3"],
"summary": "一句话摘要"
}
```
@@ -0,0 +1,48 @@
# 跨域联想协议
> 文件:99_system/protocols/cross-domain.md
> 触发词:跨界视角、换个角度、类比一下、新视角、别的领域、借鉴一下
> 加载方式:SOUL.md 检测触发词后加载
---
## 检索路径(按序执行,命中即止)
1. **L2 历史洞见**:查询 L2 facts.db,是否有相关问题的历史思考和解决方案?
2. **知识库跨域模型**:检索 03_knowledge/10_concepts/ 下各领域概念,是否有可类比的核心模型?
3. **经典理论参考**:检索 03_knowledge/40_references/,是否有经典理论或案例可引用?
4. **无匹配处理**:以上三步均无高价值发现 → 回复"本次未找到高价值跨域类比",不编造
---
## 跨域联想引擎
- **类比寻找**:"这个问题在结构上,像其他哪个学科的核心模型?"
- **逆向迁移**:"在编程/建筑/生物进化中解决类似矛盾的模式,能否借用过来?"
---
## 强制联想库(思考时激活)
| 源领域 | 目标领域 | 联想触发问题 |
|--------|---------|-------------|
| 经济学/金融学 | 系统设计 | 有什么"激励"和"约束"?是否存在"套利"空间?如何设计"无摩擦"交互? |
| 生物学/进化论 | 组织/产品 | 适者生存的筛选机制是什么?是否存在"共生"关系? |
| 军事理论/博弈论 | 商业竞争 | 战场的"高地"在哪里?对方的核心护城河能否被"侧翼攻击"? |
| 物理学/熵增定律 | 管理 | 系统的混乱度是否正在增加?如何构建"耗散结构"? |
---
## 输出格式
> **跨界视角**:[领域]的[核心概念] → 一句精要解释这个类比如何启发当前问题
仅此一句。不展开科普另一个领域。仅当 ghai 明确追问时,才深入展开细节。
---
## 约束
- 宁缺毋滥。找不到高价值联想就跳过,不编造
- 本协议独立于高阶思维协议,两者可先后触发但分别执行
- 本轮回答结束后,此模块退出上下文
@@ -0,0 +1,64 @@
# 知识审查协议
> 文件:99_system/protocols/knowledge-review.md
> 触发词:入库、记录这条、保存知识、知识审查
> 加载方式:SOUL.md 检测触发词后加载
---
## 审查四步
### 第一步:来源可靠性评分
| 来源类型 | 评分 |
|---------|------|
| 官方文档 / 学术论文 | +0.3 |
| 知名技术博客 / 行业报告 | +0.1 |
| 个人博客 / 论坛帖子 | -0.1 |
| 未知来源 / 社交媒体 | -0.3 |
| **基础可靠性基线** | **0.5** |
### 第二步:一致性检查
与 L2 已有事实对比:
- **完全一致** → 旧知识 confidence 轻微提升
- **补充细节** → 合并为新条目
- **矛盾** → 进入冲突消解(新事实 > 旧事实,用户明确修正 > 系统推断)
### 第三步:时效性标记
| 知识类型 | 有效期 |
|---------|--------|
| 技术类知识 | 180 天后自动失效 |
| 法律/法规 | 按原文有效期 |
| 个人偏好/观点 | 不过期,标记为 opinion |
| 物理/数学公理 | 永久有效 |
### 第四步:日志记录
写入 kb_ingest.log,格式:
`{timestamp} | {kb_id} | {decision} | {reason} | {confidence}`
---
## 知识版本管理
| 变化类型 | 处理方式 |
|---------|---------|
| 硬事实改变(如 4C8G → 8C16G) | 更新原卡片,旧值写入 previous_version |
| 软升级(V1→V2,V1仍有价值) | 保留 V1,新建 V2,related 链接 |
| 观点→事实 | nature 改为 fact,confidence 提升 |
---
## 自学习规则
- 所有错误写入 errors.log
- 用户纠正时触发修补:事实错误→更新 L2 facts.db,方法错误→更新方法卡片,观点分歧→标记 opinion
- 同一类型错误出现 3 次 → 触发技能改进建议
---
## 输出
审查通过后确认入库路径,汇报决策和理由,一行总结。
@@ -0,0 +1,51 @@
# 高阶思维协议
> 文件:99_system/protocols/meta-thinking.md
> 触发词:升维思考、第一性原理、前提挑战、深层原因、本质是什么、批判地看
> 加载方式:SOUL.md 检测触发词后加载
---
## 执行步骤(必须完成四步自我诘问再回答)
### 第一步:问题本质
用户此刻真正的困境,用一句话概括其本质是什么。
不是回答"他问了什么",而是回答"他真正需要解决的是什么"。
### 第二步:前提挑战
当前问题的默认解决路径或行业惯例是什么?
这些前提本身值得挑战吗?
绝不无条件接受用户的预设。
### 第三步:知识溯源
将要给出的核心观点,其思想源头在哪?
- 优先级1:L2 facts.db 中是否有相关历史洞见?
- 优先级2:03_knowledge/10_concepts/ 下是否有可类比的跨领域模型?
- 优先级3:03_knowledge/40_references/ 中是否有经典理论支撑?
- 若仅为个人推断,须明确声明置信度。
### 第四步:反直觉锚点
关于此事,最大的认知陷阱或一个反直觉的认识是什么?
---
## 输出结构
```
**问题本质**:[一句话点明本质]
**前提挑战**:[指出现有思路的潜在缺陷]
**核心建议**:[立足第一性原理,从全局布局或根本矛盾出发的突破性方案]
**认知钩子**:[提供一个反直觉视角或思想火花]
```
---
## 约束
- 找不到高价值洞察时,诚实说"本次无更高视角",不编造
- 不在此模块内展开跨域联想(那是 cross-domain 协议的事)
- 本轮回答结束后,此模块退出上下文
@@ -0,0 +1,49 @@
# 卡壳干预协议
> 文件:99_system/protocols/stuck-intervention.md
> 触发条件:运行时条件触发(非关键词触发)
> 加载方式:SOUL.md 检测到卡壳条件后加载
---
## 触发条件(任一满足即触发)
- 同一问题尝试 2 种以上方案未解决
- 单次任务耗时超过预估的 3 倍
- 规则冲突或逻辑矛盾无法自行裁决
- 遇到从未见过的错误类型,信息不足以判断
---
## 执行步骤
1. **立即停止**当前尝试,不自行继续
2. **记录日志**:写入 errors.log,格式:
`{timestamp} | {context} | {error_type} | {attempted_solutions}`
3. **按模板输出**(见下方)
---
## 输出模板
```
⚠️ 卡壳点:[一句话描述当前困境]
已尝试方案:
- 方案A:[简述] → 失败原因:[简述]
- 方案B:[简述] → 失败原因:[简述]
候选方案:
- A) [方案简述] — 预估耗时:[X分钟] — 风险:[简述]
- B) [方案简述] — 预估耗时:[X分钟] — 风险:[简述]
建议:[倾向 A/B,简述理由]
等待你的决定 → 收到后按选定方案继续执行。
```
---
## 退出机制
收到 ghai 决策后,立即退出此模块,按选定方案继续执行。
@@ -0,0 +1,56 @@
---
id: KB-20260514-002
title: "CloakBrowser 源码级反爬浏览器"
type: system
status: active
nature: reference
domain: system
subdomain: [反爬, 浏览器自动化, 采集]
tags: [cloakbrowser, 反爬, 浏览器指纹, web_crawler]
confidence: 0.85
source: "系统集成落地验证"
date_created: 2026-05-14
date_modified: 2026-05-14
version: 1
summary: "源码级修改的 Chromium 分发版,49项 C++ 补丁修改指纹,30/30反爬检测全部通过。API兼容 Playwright,改一行 import 即可迁移。"
collected: true
collected_date: 2026-05-16---
# CloakBrowser 源码级反爬浏览器
## 基本信息
- 版本: v0.3.28
- 安装: `pip install cloakbrowser`
- 二进制: 首次运行自动下载 ~200MB Chromium
## 核心原理
直接修改 Chromium 的 C++ 源码再编译,不是 JS 注入或配置修改。
| 修改项 | 做法 |
|--------|------|
| Canvas 指纹 | 修改 GPU 渲染行为 |
| WebGL 指纹 | 修改驱动信息 |
| 自动化信号 | 修改 CDP `webdriver` 属性 |
| Audio 指纹 | 修改音频层随机化种子 |
| 字体指纹 | 修改字体枚举逻辑 |
## 检测通过率
- 30/30 全部通过
- reCAPTCHA v3: 0.9(人类级别)
- Cloudflare Turnstile: 通过
- FingerprintJS: 通过
## 系统集成
- 技能: `02_skills/cloakbrowser_controller/SKILL.md`
- web_crawler 引擎: v1.2.0,高反爬走 CloakBrowser
## 不涉及的模块
- Matrix 养号(Camoufox)— 已深度适配,不更换内核
- OpenCLI — 不变
- Scrapling — 不变(低反爬页面仍用它)
@@ -0,0 +1,48 @@
---
id: KB-20260514-001
title: "Peekaboo v3 桌面 GUI 自动化"
type: system
status: active
nature: reference
domain: system
subdomain: [自动化, GUI, 视觉识别, MCP]
tags: [peekaboo, 截图, 桌面自动化, OCR, MCP]
confidence: 0.9
source: "系统集成落地验证"
date_created: 2026-05-14
date_modified: 2026-05-14
version: 1
summary: "macOS 桌面 GUI 自动化工具,像素级视觉识别+鼠标键盘操作。通过 MCP 协议集成到 WorkBuddy。"
collected: true
collected_date: 2026-05-16---
# Peekaboo v3 桌面 GUI 自动化
## 基本信息
- 版本: v3.1.2
- 安装: `npm install -g @steipete/peekaboo`
- MCP: `npx -y @steipete/peekaboo mcp --json --log-level error`
- 权限: 屏幕录制 + 辅助功能(macOS)
## 核心能力
- 截图:窗口截图、区域截图、全屏截图
- 操作:点击、输入、拖拽、滚动、快捷键
- 识别:应用列表、窗口列表、UI 控件树
## 使用策略
| 规则 | 值 | 说明 |
|------|----|------|
| 截图冷却 | 5s | 两次截图最小间隔 |
| 单会话上限 | 20次 | 一次对话最大截图数 |
| 缓存 | 30s | 同一应用复用缓存 |
| 优先级 | DOM→API→文本→截图 | 截图是最后手段 |
## 系统集成
- MCP 配置: `01_core/mcp.json`
- 技能: `02_skills/peekaboo_controller/SKILL.md`
- 策略层: `02_skills/peekaboo_controller/policy.py`
@@ -0,0 +1,53 @@
# Dashboard 修复与录制标注工作台 会话记录
日期: 2026-06-22
模型: deepseek-v4-flash
## 会话脉络
### 上午-下午:Dashboard 基础修复
1. **视图迁移审计** — 33个迁移视图核对,发现多个问题
2. **API路径修复** — `sms/presets`→`accounts`, `sms/proxies`→`proxies`
3. **动态import修复** — 字符串拼接→模板字面量,Vite正确生成chunk
4. **机器状态修复** — 信任API status字段,不再被心跳覆盖
5. **账号归属修复** — ORACLE.yaml 覆盖 WPRA 去重结果
6. **is_local冲突修复** — ORACLE覆盖后 xhs_01 误判为本机
7. **机器别名修复** — Redmi-12C 指向 chengzigedeAir
### 下午-晚上:操作流程图 + 工作台(后删除)
1. **ops-flow.js** — SVG状态机流程图(已删除)
2. **ops-workbench.js** — 三栏工作台(已删除)
3. **导航栏新增原子操作分组**(已删除)
### 晚上:录制标注重写 + CommandBus修复
1. **ops-recorder.js 完整重写** — 录制启动/停止/状态 + 三栏分析
2. **CommandBus进程泄露修复** — graceful_exit pkill扩展 + 并发上限
3. **后端新增** — `/api/ops/test-atom` 单步测试端点
4. **导航精简** — 删除无用视图,录制标注并入矩阵分组
## 2026-06-23 补充
### v3 重写:抽屉式步骤展开 + 变化特征码
1. **抽屉式设计** — 步骤横条全部列出([1][2][3]...),点击展开/收起(手风琴),不再翻页
2. **三栏特征增强** — 左: 操作前(URL/框架/元素/状态/截图),中: 动作序列(点击/键盘/滚动/悬停/停留/右键/刷新),右: 操作后(同左)
3. **变化特征码** — 底部独立区块: URL变化 → 框架变化 → 元素状态变化(selector) → 文本变化 → 推断汇总
4. **事件类型扩展** — 新增 rightclick/hover/dwell/refresh/navigation 事件类型渲染
5. **Bug修复: 闭包变量泄漏** — 旧版内联 onchange 引用 `_names` 闭包变量不可达,改为 `window._saveAllNames` / `window._saveAtomName` 全局函数
6. **Bug修复: API路径缺失** — `POST /api/matrix/record/start` 路由不存在,新增 shim
## 关键决策
- 用户不需要原子操作/流程图/工作台 → 全部删除
- 只需要录制标注功能,放在矩阵导航下
- 分析 = 前状态(结构化) + 动作(事件) + 后状态(变化)
- v3: 步骤列表先全部展示,点击展开详情(抽屉式),而非上下翻页
## 待解决
- `mc task comment` 引擎 spawn 1000+ 进程,日志为空
- 评论功能全链路没跑通(引擎问题,非CommandBus)
- 录制标注页面可能还需要进一步简化
## 关键文件
- `05_tools/10_dashboard/frontend/src/views/ops-recorder.js` — 录制标注
- `05_tools/10_dashboard/services/command_bus.py` — 命令总线
- `05_tools/10_dashboard/routes/ops.py` — 操作执行路由
- `05_tools/10_dashboard/frontend/src/modules/matrix_views.js` — 导航+白名单
@@ -0,0 +1,30 @@
# 领域分类表
> 本表定义了 AgentOS 知识库的领域分类体系。当"其他"类别超过总知识的 5% 时,应考虑新增领域。
## 一级领域列表
| 编号 | 英文目录名 | 中文名称 | 说明 | 典型子领域 |
|---|---|---|---|---|
| 01 | cs | 计算机科学 | 编程、系统、网络、数据库等 | 数据库、前端、后端、运维、安全 |
| 02 | ai | 人工智能 | ML/DL/NLP/CV/LLM 等 | NLP、CV、强化学习、RAG、Agent |
| 03 | finance | 金融 | 股票、基金、投资、财报等 | 量化交易、价值投资、宏观经济 |
| 04 | law | 法律 | 法规、合规、合同等 | 民法、商法、知识产权 |
| 05 | medicine | 医学 | 健康、疾病、药物等 | 中医、西医、营养学 |
| 06 | physics | 物理 | 物理学知识 | 量子力学、相对论、热力学 |
| 07 | math | 数学 | 数学理论与应用 | 线性代数、概率统计、微积分 |
| 08 | psychology | 心理学 | 心理学知识 | 认知心理学、社会心理学 |
| 09 | philosophy | 哲学 | 哲学思考 | 认识论、伦理学、美学 |
| 10 | history | 历史 | 历史事件与脉络 | 中国史、世界史、科技史 |
| 11 | engineering | 工程 | 工程技术 | 机械、电子、土木 |
| 12 | design | 设计 | 设计理论与方法 | UI/UX、平面设计、建筑设计 |
| 13 | business | 商业 | 商业知识 | 创业、管理、营销、战略 |
| 14 | personal-management | 个人管理 | 效率、习惯、时间管理 | GTD、番茄工作法、精力管理 |
| 15 | personal-insight | 个人洞见 | 心得、感悟、人生经验 | 决策模型、价值观、反思 |
| 16 | other | 其他 | 暂未归类的知识 | 待新增领域 |
## 新增领域规则
1. 当"其他"类别下的知识文件数超过总文件数的 5% 时,memory_manager 技能提示新增
2. 新领域需同时定义:中文名称、英文目录名、说明、典型子领域
3. 新增领域后,需更新本文件和 folder-aliases.json
@@ -0,0 +1,64 @@
{
"version": "1.0.0",
"description": "AgentOS 目录中文映射配置——文件夹名为英文,此处提供中文别名用于展示和检索",
"root": {
"agent-os": "AgentOS 智能体操作系统"
},
"directories": {
"00_bootstrap": "初始化引导",
"01_core": "核心配置",
"02_skills": "技能包",
"03_knowledge": "知识库",
"04_memory": "记忆体",
"05_tools": "工具脚本",
"06_runtime": "运行时",
"07_migration": "迁移备份"
},
"knowledge": {
"00_inbox": "收件箱",
"01_daily": "日记",
"10_concepts": "概念层",
"20_methods": "方法层",
"30_facts": "事实层",
"40_references": "参考层",
"50_resources": "资源层",
"60_opinions": "观点层",
"90_archive": "归档层",
"99_system": "系统层"
},
"concepts_domains": {
"cs": "计算机科学",
"ai": "人工智能",
"finance": "金融",
"law": "法律",
"medicine": "医学",
"physics": "物理",
"math": "数学",
"psychology": "心理学",
"philosophy": "哲学",
"history": "历史",
"engineering": "工程",
"design": "设计",
"business": "商业",
"personal-management": "个人管理",
"personal-insight": "个人洞见",
"other": "其他"
},
"memory": {
"vector_db": "向量数据库",
"logs": "操作日志",
"daily_summaries": "每日摘要",
"long_term": "长期记忆",
"raw": "原文存档",
"memory_backup": "记忆备份"
},
"tools": {
"00_setup": "环境安装",
"01_system": "系统操作",
"02_browser": "浏览器",
"03_ocr": "OCR识别",
"04_media": "媒体处理",
"05_crawl": "爬虫抓取",
"06_mobile": "移动端"
}
}
@@ -0,0 +1,39 @@
# 知识属性分类表
> 本表定义了知识的 nature 属性类型,决定了知识卡片在知识库中的物理位置。
## 属性类型
| nature 值 | 中文名称 | 说明 | 目标目录 | 可信度权重 |
|---|---|---|---|---|
| fact | 事实 | 已验证的客观事实 | 30_facts/ | 1.0 |
| method | 方法 | 可操作的步骤、教程、最佳实践 | 20_methods/ | 1.0 |
| concept | 概念 | 原子概念、知识卡片 | 10_concepts/ | 0.8 |
| regulation | 规章制度 | 法律、法规、组织制度 | 30_facts/ | 1.0 |
| reference | 参考资料 | 论文、文档、外部资料 | 40_references/ | 0.7 |
| data | 数据 | 测试数据、基准测试结果 | 30_facts/ | 0.9 |
| opinion | 观点 | 主观看法、推测、未验证想法 | 60_opinions/ | 0.5 |
| quote | 引用 | 他人原话、经典语录 | 60_opinions/ | 0.6 |
| axiom | 公理 | 公认的基础原理,无需证明 | 10_concepts/ | 1.0 |
## 分类决策树
```
这段内容是在描述"世界是什么样"还是在说"应该怎么做"?
├── "是什么" → 可能是 fact/opinion/quote/data/reference/axiom
│ ├── 有实验数据/论文支持 → fact (confidence: 0.8+)
│ ├── 是作者的个人看法 → opinion (confidence: 0.4-0.6)
│ ├── 是引用的他人原话 → quote (confidence: 标注来源可信度)
│ ├── 是公认无需证明的原理 → axiom (confidence: 0.95+)
│ ├── 是链接/文献/资料 → reference (confidence: 0.7)
│ └── 是测试数据/基准结果 → data (confidence: 0.9)
└── "怎么做" → 可能是 method/regulation
├── 有明确法律/组织强制力 → regulation (confidence: 1.0)
└── 是可操作的步骤/教程 → method (confidence: 1.0)
```
## 属性变更规则
- opinion → fact:观点被验证为事实时,confidence 提升,文件移动到 30_facts/
- fact → opinion:事实被推翻时,confidence 降低,文件移动到 60_opinions/
- 所有属性变更由 kb_manager reclassify 自动处理,同时更新内链
@@ -0,0 +1,51 @@
---
id: KB-YYYYMMDD-NNN
title: "__概念名称__"
type: concept
status: draft
nature: fact
domain: [计算机科学]
subdomain: []
tags: [__标签1__, __标签2__]
confidence: 0.8
source: ""
source_type: literature
date_created: __DATE__
date_modified: __DATE__
version: 1
aliases: [__别称__]
keywords: [__关键词__]
summary: "__一句话摘要__"
related: []
previous_version: ""
superseded_by: ""
---
# __概念名称__
## 一句话定义
> __用最简洁的语言定义这个概念__
## 核心原理
- __原理要点 1__
- __原理要点 2__
- __原理要点 3__
## 与相关概念的区别
| 概念 | 擅长 | 不擅长 |
|---|---|---|
| __本概念__ | __优势__ | __劣势__ |
| __相关概念A__ | __优势__ | __劣势__ |
## 主流选择/实现
- __选项 1__:__简述__
- __选项 2__:__简述__
## 相关概念
- [[__相关概念1__]]
- [[__相关概念2__]]
@@ -0,0 +1,39 @@
---
id: KB-YYYYMMDD-NNN
title: "__事实标题__"
type: fact
status: published
nature: fact
domain: [__领域__]
confidence: 0.9
source: "__来源URL或出处__"
source_type: experiment|literature|official_doc|personal_exp
date_created: __DATE__
date_modified: __DATE__
version: 1
previous_version: ""
superseded_by: ""
---
# __事实标题__
## 数据来源
__说明数据来源、测试环境、文献出处等__
## 事实内容
| 维度 | 值 | 备注 |
|---|---|---|
| __维度1__ | __值__ | __备注__ |
| __维度2__ | __值__ | __备注__ |
## 结论
__基于事实得出的结论__
## 历史版本
| 版本 | 日期 | 变更 | KB-ID |
|---|---|---|---|
| v1 | __DATE__ | 初始记录 | __KB-ID__ |
@@ -0,0 +1,62 @@
---
id: KB-YYYYMMDD-NNN
title: "__方法/教程标题__"
type: method
status: published
nature: method
domain: [__领域__]
confidence: 1.0
source: "__来源__"
date_created: __DATE__
date_modified: __DATE__
version: 1
previous_version: ""
superseded_by: ""
---
# __方法/教程标题__
## 目标
__这个方法解决什么问题?达到什么效果?__
## 前置条件
- __条件 1__
- __条件 2__
## 步骤
### 1. __步骤名称__
__详细描述__
```bash
# 示例命令
__命令__
```
### 2. __步骤名称__
__详细描述__
### 3. __步骤名称__
__详细描述__
## 注意事项
- __注意点 1__
- __注意点 2__
## 常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| __问题__ | __原因__ | __方案__ |
## 历史版本
| 版本 | 日期 | 变更 | KB-ID |
|---|---|---|---|
| v1 | __DATE__ | 初始记录 | __KB-ID__ |
@@ -0,0 +1,50 @@
---
id: KB-YYYYMMDD-NNN
title: "__个人洞见标题__"
type: concept
status: draft
nature: opinion
domain: [个人洞见]
tags: [__标签1__, __标签2__]
confidence: 0.6
source_type: personal_exp
date_created: __DATE__
date_modified: __DATE__
version: 1
previous_version: ""
superseded_by: ""
---
# __个人洞见标题__
## 背景
__什么情境下产生的这个洞见?__
## 核心观点
> __用一句话概括你的核心观点__
## 详细思考
__展开阐述你的思考过程和推理逻辑__
## 可复用的原则
- __原则 1__:__说明__
- __原则 2__:__说明__
## 相关经历
__与这个洞见相关的个人经历或案例__
## 后续验证
- [ ] __验证项 1__
- [ ] __验证项 2__
## 版本记录
| 版本 | 日期 | 变更 | 状态 |
|---|---|---|---|
| v1 | __DATE__ | 初始记录 | 观点 |