# 主控 V0.0(Master Control) AI POD 工蜂生产系统的最小主控服务:工蜂注册、心跳、任务下发、Skill/Tool 下载、结果上传、机械验收、奖金记录。 ## 环境要求 - PHP 8.1+(推荐 8.2+) - 扩展:`pdo_mysql`、`json`、`zip`、`fileinfo` - MySQL 8.0+ - 可写目录:`uploads/`、`skills/`、`tools/`、`results/`、`logs/` 不引入 Composer,不使用框架。 ## 部署步骤 ### MAMP(本机已验证) 1. 编辑 `config/config.php`: - `db.port` = `8889` - `db.pass` = `root`(MAMP 默认) - `base_url` = `http://localhost:8888/aiworker-master` 2. 仅新增符号链接(不修改其他站点): ```bash ln -s /path/to/aiworker/master-control /Applications/MAMP/htdocs/aiworker-master ``` 3. 导入数据库: ```bash /Applications/MAMP/Library/bin/mysql80/bin/mysql -uroot -proot -P8889 -h127.0.0.1 < schema.sql ``` 4. 访问: ```text http://localhost:8888/aiworker-master/admin/login.php ``` 5. 运行自检(覆盖注册→领取→下载→上传→验收→奖金): ```bash /Applications/MAMP/bin/php/php8.3.30/bin/php scripts/mamp_self_test.php ``` ### 通用部署 1. 编辑 `config/config.php`: - 数据库连接 - `admin_password`(后台密码) - `worker_register_key`(工蜂注册密钥) 2. 导入数据库: ```bash mysql -u root -p < schema.sql ``` 3. 启动内置服务器(示例): ```bash cd master-control php -S 127.0.0.1:8080 -t . ``` 4. 打开后台: ```text http://127.0.0.1:8080/admin/login.php ``` 5. 确保以下目录可写: ```text uploads/source/ skills/ tools/ models/ Model Pack(7B 等大模型,方案 B 主控下发) results/ logs/ ``` 已有数据库升级 Model Pack: ```bash mysql -u root -proot -P8889 -h127.0.0.1 aiworker < schema_migrate_model_packs.sql ``` 领单租约超时(`claim_timeout_count`): ```bash mysql -u root -proot -P8889 -h127.0.0.1 aiworker < schema_migrate_claim_timeout.sql ``` 激活码 + UI 热更: ```bash mysql -u root -proot -P8889 -h127.0.0.1 aiworker < schema_migrate_activation.sql ../scripts/sync_worker_ui.sh ``` ## Worker UI 热更 + 真激活(V0.2) - 界面托管:`master-control/worker-ui/` → `config.php` 的 `worker_ui_url` - 改 `ai-workdomain-demo` 后执行 `scripts/sync_worker_ui.sh`,客户端刷新即更新 - 激活:`POST /api/worker_activate.php`(`activation_code` + `machine_fingerprint`) - 会话:`POST /api/worker_session_check.php`;失败则客户端清本地凭证并回到激活页 - 演示重置:后台 **工蜂 → 删除**(激活码释放为 unused);或 `./scripts/reset_master_db.sh` 恢复整库初始 ### 客户端 UX(与代码一致) - Electron 窗口 **960×720**;UI 带 `?client=1`,无模拟派单按钮、待命无「待命中」角标 - Hermes 状态约 3.5s 轮询,详见 `docs/PRD_IMPLEMENTATION.md` ## 领单租约超时(V0.1) - 配置:`task_claim_running_timeout_seconds`(默认 **600**,即 claim 后 10 分钟) - 条件:任务仍为 `claimed`,且 `started_at` 为空(工蜂未上报 `running`) - 动作:任务回 `pending`,`attempt_count + 1`;对应工蜂 `claim_timeout_count + 1`,并清空 `current_task_id` - 触发:工蜂心跳 / 拉任务 / 领单、后台打开工蜂/任务/概览时执行维护(`mc_run_scheduled_maintenance`) - 事件:`task_events.event_type = claim_timeout_reclaimed` 首包 Model 下载超过 10 分钟时,可在 `config/config.php` 调大 `task_claim_running_timeout_seconds`。 ## 目录结构 ```text master-control/ worker-ui/ Worker Runtime H5(热更) admin/ 运维后台 api/ Worker JSON API config/ 配置与 PDO includes/ 公共逻辑 uploads/source/ 任务素材(不公开直链) skills/ Skill zip tools/ Tool Pack zip models/ Model Pack(.gguf 或 zip,可达数 GB) results/ 工蜂上传结果 logs/ 主控日志(不记录 worker_token) ``` ## Worker API 统一响应: ```json { "ok": true, "data": {}, "error": null } ``` | 端点 | 方法 | 说明 | |------|------|------| | `/api/worker_activate.php` | POST | 工蜂激活(客户端主路径) | | `/api/worker_session_check.php` | POST | 会话校验 | | `/api/worker_register.php` | POST | 工蜂注册(辅助) | | `/api/worker_heartbeat.php` | POST | 心跳 | | `/api/worker_next_task.php` | POST | 查询下一任务 | | `/api/worker_claim_task.php` | POST | 原子领取任务 | | `/api/worker_task_status.php` | POST | 上报任务状态 | | `/api/worker_upload_result.php` | POST multipart | 上传结果 zip | | `/api/worker_download_skill.php` | GET | 下载 Skill(鉴权) | | `/api/worker_download_tool.php` | GET | 下载 Tool Pack(鉴权) | | `/api/worker_download_model.php` | GET | 下载 Model Pack(鉴权,.gguf 大文件) | | `/api/worker_download_source.php` | GET | 下载素材(鉴权) | 素材不提供 `/uploads/source/` 公开直链。 ## 手工联调(curl) 将 `BASE` 设为服务地址,例如 `http://127.0.0.1:8080`。 ### 1. 注册工蜂 ```bash BASE=http://127.0.0.1:8080 curl -sS -X POST "$BASE/api/worker_register.php" \ -H 'Content-Type: application/json' \ -d '{"worker_key":"AIGY-BEE-DEMO-2026","machine_fingerprint":"M4-16G-9F3A-71C2","client_version":"0.0.1"}' ``` 保存返回的 `worker_id` 与 `worker_token`。 ### 2. 心跳 ```bash curl -sS -X POST "$BASE/api/worker_heartbeat.php" \ -H 'Content-Type: application/json' \ -d '{"worker_id":"BEE_000001","worker_token":"YOUR_TOKEN","status":"online","capabilities":["image_toolkit:1.0.0"],"current_task_id":null}' ``` ### 3. 后台准备数据 登录 `/admin/login.php` 后: 1. `skills.php` 上传 Skill zip 2. `tools.php` 上传 Tool Pack zip(若任务需要) 3. `tasks.php` 上传素材并创建任务 ### 4. 拉取并领取任务 ```bash curl -sS -X POST "$BASE/api/worker_next_task.php" \ -H 'Content-Type: application/json' \ -d '{"worker_id":"BEE_000001","worker_token":"YOUR_TOKEN"}' curl -sS -X POST "$BASE/api/worker_claim_task.php" \ -H 'Content-Type: application/json' \ -d '{"worker_id":"BEE_000001","worker_token":"YOUR_TOKEN","task_id":"TASK_000001"}' ``` ### 5. 上报 running ```bash curl -sS -X POST "$BASE/api/worker_task_status.php" \ -H 'Content-Type: application/json' \ -d '{"worker_id":"BEE_000001","worker_token":"YOUR_TOKEN","task_id":"TASK_000001","status":"running","message":"执行中","progress":30}' ``` ### 6. 下载 Skill / 素材 / Tool 使用 `worker_next_task` 返回的 URL(已带鉴权参数),或手动拼接 query。 ### 7. 上传结果包 ```bash curl -sS -X POST "$BASE/api/worker_upload_result.php" \ -F worker_id=BEE_000001 \ -F worker_token=YOUR_TOKEN \ -F task_id=TASK_000001 \ -F result_zip=@/path/to/result.zip ``` 上传后主控自动机械验收: - 通过:`uploaded → verified → settled`,并写 `rewards` - 失败:`uploaded → failed` ### 8. 后台验收查看 打开 `admin/task_detail.php?task_id=TASK_000001` 查看验收明细、事件日志、奖金记录。 ## 结果包结构(机械验收) ```text SKU_000001/ main.jpg model.jpg detail_01.jpg metadata.json log.txt ``` `metadata.json` 中 `outputs` 的图片尺寸必须与实际文件一致。 ## 任务状态机 ```text pending -> claimed -> running -> uploaded -> verified -> settled \-> failed ``` ## 安全说明 - `worker_token` 仅注册时明文返回一次,数据库只存 hash - 日志不记录 `worker_token` - 所有 SQL 使用 prepared statements - zip 上传解压防路径穿越 - 后台使用单一 config 密码 + Session ## 回滚 - 代码:删除或 git 还原 `master-control/` 目录 - 数据库:`DROP DATABASE aiworker;` 后重新导入 `schema.sql` - 文件:清空 `uploads/`、`skills/`、`tools/`、`results/` 下业务文件