批量自动操作aizex面板
Aizex MCP
通过 Playwright 浏览器自动化控制 Aizex 号池(ChatGPT/Claude 共享账号平台), 以 MCP (Model Context Protocol) 协议暴露为工具,让 agent 能操控aizex界面获取高级模型的回复,也可以写脚本批量自动生成内容。
架构概览
Mac (本机) VPS (远程)
┌─────────────────────┐ ┌──────────────┐
│ Chrome (非headless) │ │ nanobot │
│ ↑ │ │ ↑ │
│ Playwright 控制 │ │ MCP Client │
│ ↑ │ │ ↑ │
│ BrowserEngine │ SSH隧道 │ 127.0.0.1 │
│ ↑ │ ◄────────► │ :8000 │
│ AizexService │ └──────────────┘
│ ↑ │
│ FastMCP Server │
│ (port 8000) │
└─────────────────────┘
核心组件
浏览器层 (src/browser/)
-
engine.py — BrowserEngine:管理 Playwright persistent context 的生命周期。 非 headless 模式启动(headless 被 Cloudflare 拦截)。支持
adopt_context()用于 session 恢复后接管新浏览器。 -
auth.py — LoginManager:处理 Authing 登录流程。 检测是否已登录、处理登录表单、等待跳转完成。支持 session 未过期时直接跳过登录。
-
actions.py — BrowserActions:所有浏览器原子操作。 包括发送消息、获取回复、检测生成状态、切换模型、管理对话列表、文件上传下载等。 所有操作通过 CSS 选择器(配置在 aizex.yaml)定位页面元素。
-
recovery.py — SessionRecovery:号池 session 恢复。 当 session 被踢(其他用户登录同一账号)时,打开新浏览器重新走 Authing → 选号池 → 进入聊天的完整流程。恢复后通过
engine.adopt_context()替换主浏览器。 -
selectors.py — SelectorManager:从 YAML 加载 CSS 选择器,支持 primary/fallback。
-
state.py — StateMachine:服务状态管理(READY/BUSY/ERROR/SESSION_KICKED/LOGIN_REQUIRED)。
-
service.py — AizexService:编排层。 协调 engine、auth、actions,提供锁机制(
run_locked)保证操作串行化。 实现wait_and_get的短锁轮询模式:短暂获取锁检查状态 → 释放锁等待 → 再次获取锁确认稳定。 -
page_sentinel.py — PageSentinel:页面健康监控。 在每次操作前后检查页面状态,检测异常(如被踢、登录过期、网络错误)。
MCP 服务层 (src/mcp_server/)
-
server.py — FastMCP 服务端,注册 13 个工具。 包含服务端防护:send_message 3 秒冷却期、浏览器单例(多 session 共享)。 使用统一的结果工厂模式(
_build_success_response和_build_error_response)处理所有工具响应。 工具 docstring 使用中文,通过 tools/list 传递给 AI 客户端作为使用规则。 -
schemas.py — Pydantic 数据模型,定义每个工具的输入输出结构。
核心层 (src/core/)
-
settings.py — Pydantic Settings,从
.env加载配置。 关键配置:browser_headless(默认 False)、poll_interval_ms、text_stability_window_ms。 遵循单一职责原则,只管理静态配置。 -
session_store.py — SessionStore:运行时会话状态管理。 管理聊天URL和cookies的持久化,与Settings类分离,遵守单一职责原则。
-
errors.py — 自定义异常类,包含标准化的错误字段提取(
error_fields_from_exception)。
MCP 工具列表
| 工具 | 用途 |
|------|------|
| aizex_health | 检查服务状态(READY/SESSION_KICKED) |
| aizex_new_chat | 新建对话 |
| aizex_send_message | 发送消息(3秒冷却) |
| aizex_wait_and_get | 等待回复完成并获取(默认超时900秒) |
| aizex_get_last_response | 获取最后一条回复 |
| aizex_is_generating | 检查是否正在生成 |
| aizex_list_models | 列出可用模型(支持SVG检测当前选中模型) |
| aizex_select_model | 切换模型 |
| aizex_list_conversations | 列出对话列表 |
| aizex_select_conversation | 切换对话 |
| aizex_upload_file | 上传文件到当前对话 |
| aizex_check_downloads | 检查当前页面可下载的文件 |
| aizex_download_file | 下载文件(index=-1下载全部) |
| aizex_refresh_page | 刷新当前页面(处理生成卡住或页面异常) |
| aizex_recover_session | 恢复被踢的 session(弹窗操作) |
最新功能更新
0. 教材批量生成系统(新增)
- 功能:基于 batch 系统的教材自动生成工具
- 组件:
textbook/prepare.py:读取 config.yaml,生成 job.json 和课程提示词textbook/run.sh:一键运行脚本(自动 prepare + batch run)textbook/chapters/:参考教材内容目录textbook/runs/:运行配置目录textbook/output/:生成结果目录
- 特点:
- 多轮共享会话:每 N 轮自动开新会话,上传参考文件
- 支持 system_prompt + 每课 prompt 的组合
- 自动检测错误回复(请求过于频繁、登录态异常等)
- 读回验证:生成 job.json 后立即验证关键字段
- 使用示例:
# 一键运行教材生成 ./textbook/run.sh textbook/runs/calculus_v1 # 续跑失败的任务 ./textbook/run.sh textbook/runs/calculus_v1 resume # 手动运行 prepare python3 textbook/prepare.py textbook/runs/calculus_v1
1. SessionStore 重构
- 问题:Settings类同时管理静态配置和运行时状态,违反单一职责原则
- 解决方案:新建
SessionStore类专门管理运行时状态 - 功能:
- 保存/加载聊天URL(
.last_chat_url) - 保存/加载会话cookies(
.last_cookies.json) - 检查当前页面是否正确
- 获取导航URL
- 保存/加载聊天URL(
2. 统一结果工厂模式
- 问题:server.py中每个工具函数都有重复的try-except模板
- 解决方案:提取
_build_success_response和_build_error_response辅助函数 - 优势:
- 代码更简洁,减少重复
- 错误处理标准化
- 统一的响应格式
3. 智能模型检测
- 问题:
is_current字段检测不准确,文本匹配容易出错 - 解决方案:使用SVG检测代替文本匹配
- 实现:
- 当前选中的模型有checkmark图标(SVG子元素)
- 使用
await item.locator('svg').count() > 0检测 - 分组入口(有展开箭头SVG)通过
_is_group_entry过滤
4. 文件管理功能
- 上传:支持上传任意文件到当前对话
- 下载:自动检测AI生成的可下载文件
- 特性:
- 智能文件路径提取
- 支持批量下载
- 安全的文件操作
5. 页面刷新功能
- 新增工具:
aizex_refresh_page用于处理页面状态异常 - 使用场景:
- AI 生成卡住不动时
- 页面状态异常时
wait_and_get超时后需要重置页面状态
- 特性:刷新后可能需要重新发送消息
6. 下载功能增强
- URL 解码:自动解码下载链接中的编码文件名
- 智能文件名选择:优先使用从 URL path 参数提取的文件名,避免使用 Playwright 的 UUID 文件名
- 批量下载支持:支持逗号和连接号组合的索引表达式(如 "0,2-4,7")
- 全面消息扫描:
aizex_check_downloads支持扫描所有对话消息,而不仅仅是最后一条
7. 会话状态跟踪
- 新增响应字段:所有工具响应现在包含
session_model和session_conversation_id字段 - 实时状态反馈:AI agent 每次操作后都能看到当前会话状态
- 智能提取:从页面 URL 自动提取对话 ID,从快照中获取当前模型
8. 使用规则优化
- 模型选择规则:明确禁止在已有消息的对话中切换模型,尤其是 Claude 对话
- 正确使用顺序:
aizex_new_chat→aizex_select_model→aizex_send_message - 文档更新:更新相关工具的 docstring 以提供更清晰的使用指导
9. 多实例隔离支持
- 问题:多个实例共用同一个 Chromium profile 目录导致 SingletonLock 冲突
- 解决方案:按
instance_id隔离所有浏览器相关路径 - 核心修改:
- Settings 配置扩展:新增
instance_id和pool_index字段,支持环境变量配置 - 路径隔离:浏览器 profile、下载目录、artifacts 目录按 instance_id 添加后缀
- SessionStore 隔离:URL 和 cookies 文件按 instance_id 添加后缀
- 端口隔离:Server 端口支持
AIZEX_PORT环境变量配置 - 启动策略:非默认实例(instance_id != "0")启动时强制走 recovery 进入指定号池
- Settings 配置扩展:新增
- 管理脚本:新增
aizex-multi.sh脚本支持多实例生命周期管理 - 使用示例:
# 启动 2 个实例,分别进 0 号和 3 号池 ./aizex-multi.sh start 2 0,3 # 查看状态 ./aizex-multi.sh status # 停止所有实例 ./aizex-multi.sh stop
10. 多 slot 批处理支持与附件丢失修复
- 问题:多 slot 并行处理时,上传的附件在发送消息前被不必要的导航冲掉
- 根因分析:
- 域名判断不完整:SessionStore 只识别
*.memofun.net,不识别*.aizex.net域名 - 目录路径重复追加:
Settings.ensure_directories()非幂等,多次调用重复追加-instance_id后缀 - 导航误判:进入
*.aizex.net域名时被误判为错误页面,触发不必要的重新导航
- 域名判断不完整:SessionStore 只识别
- 解决方案:
- 扩展域名支持:修改
SessionStore._is_supported_chat_host()同时支持*.memofun.net和*.aizex.net - 幂等目录创建:修改
Settings.ensure_directories()使用_ensure_instance_suffix()helper 确保路径只追加一次后缀 - 优化 URL 更新:recovery 成功后同时更新内存中的 active base URL 和磁盘文件
- 添加导航诊断日志:在
ensure_ready_page()中添加详细日志,便于问题诊断
- 扩展域名支持:修改
- 批处理框架:
- SlotPool (
src/batch/engine.py):管理多个独立的 AizexService 实例 - JobRunner (
src/batch/runner.py):读取 job 配置,分发任务到多个 slot 并行执行 - 任务历史 (
src/batch/history.py):JSON Lines 格式记录任务执行历史 - CLI 接口 (
src/batch/__main__.py):支持 run、status、resume、create 命令
- SlotPool (
- 使用示例:
# 创建批处理任务配置 python -m src.batch create --name my_job --files file1.txt file2.txt --slots 3 # 运行批处理任务 python -m src.batch run job_my_job.json # 查看任务状态 python -m src.batch status job_my_job.json
关键技术决策
- 非 headless 模式:headless 浏览器被 Cloudflare 拦截,必须用非 headless。
- persistent context:号池 session 依赖 WebSocket 连接,关闭浏览器即失效。使用 persistent context 保持 cookie 和连接。
- 恢复时不关旧浏览器:recovery 完成后通过
adopt_context()直接替换主浏览器引用,避免 WebSocket 断开。 - 短锁轮询:
wait_and_get不长期持有锁,用"短锁检查 → 释放 → 等待 → 再检查"的模式,避免阻塞其他操作。 - send_message 冷却:服务端强制 3 秒间隔,防止 AI 客户端连续发送导致页面混乱。
- 动态 URL:号池域名每次不同(如 a.memofun.net),恢复后通过
settings.update_base_url()更新。 - 单一职责原则:Settings管配置,SessionStore管运行时状态,职责清晰分离。
- 统一错误处理:所有工具使用相同的结果工厂,错误响应格式一致。
部署架构
- Mac 端:运行 MCP Server + Chrome 浏览器 + SSH 隧道
- VPS 端:运行 nanobot(通过 SSH 隧道连接 Mac 的 MCP Server)
- 控制脚本:
- 单实例:
./aizex.sh start/stop/restart/status/test/log/tunnel - 多实例:
./aizex-multi.sh start/stop/status/log
- 单实例:
快速开始
安装
git clone <repo-url> ~/aizex_mcp
cd ~/aizex_mcp
pip install -e .
playwright install chromium
配置
cp .env.example .env
# 编辑 .env,填入 Aizex 账号密码和 URL
关键配置项:
# Aizex URLs
AIZEX_BASE_URL=https://chat.aizex.com
AIZEX_CHAT_URL=/chat
AIZEX_LOGIN_URL=/login
# Authentication (required for login)
AIZEX_USERNAME=your_username_here
AIZEX_PASSWORD=your_password_here
# Browser settings (必须设置为 false)
AIZEX_BROWSER_HEADLESS=false
# 运行时状态存储
AIZEX_SESSION_STORE_DIR=./.session
运行
chmod +x aizex.sh
./aizex.sh start # 启动 MCP 服务 + SSH 隧道
./aizex.sh test # 端到端测试
./aizex.sh status # 查看状态
开发模式运行
make install # 安装依赖
make run # 启动 MCP 服务器(开发模式)
nanobot 连接
在 nanobot 的 config.json 中添加:
{
"tools": {
"mcpServers": {
"aizex": {
"url": "http://127.0.0.1:8000/mcp"
}
}
}
}
IDE中mcp的配置
{ "mcpServers": { "aizex-mcp": { "command": "python3", "args": [ "run_stdio.py" ], "cwd": "/Users/csbot/aizex_mcp", "alwaysAllow": [ "aizex_health", "aizex_list_models", "aizex_list_conversations", "aizex_select_model", "aizex_new_chat", "aizex_send_message", "aizex_wait_and_get", "aizex_check_downloads", "aizex_upload_file", "aizex_get_last_response", "aizex_is_generating", "aizex_select_conversation", "aizex_download_file", "aizex_refresh_page", "aizex_recover_session" ], "timeout": 300 } } }
开发指南
项目结构
aizex_mcp/
├── src/
│ ├── browser/ # 浏览器自动化层
│ │ ├── actions.py # 原子操作(发送消息、切换模型等)
│ │ ├── service.py # 服务编排层
│ │ ├── engine.py # 浏览器引擎
│ │ ├── recovery.py # 会话恢复
│ │ ├── page_sentinel.py # 页面监控
│ │ └── ...
│ ├── mcp_server/ # MCP 服务层
│ │ ├── server.py # FastMCP 服务端
│ │ └── schemas.py # 数据模型
│ ├── core/ # 核心层
│ │ ├── settings.py # 配置管理
│ │ ├── session_store.py # 运行时状态管理
│ │ └── errors.py # 错误处理
│ └── batch/ # 批处理层(新增)
│ ├── __init__.py
│ ├── engine.py # SlotPool:管理多个 AizexService 实例
│ ├── runner.py # JobRunner:任务分发和执行
│ ├── history.py # 任务历史记录(JSON Lines 格式)
│ └── __main__.py # CLI 接口
├── textbook/ # 教材批量生成系统(新增)
│ ├── prepare.py # 配置解析和 job.json 生成
│ ├── run.sh # 一键运行脚本
│ ├── chapters/ # 参考教材内容
│ ├── runs/ # 运行配置
│ └── output/ # 生成结果
├── config/
│ └── selectors/
│ └── aizex.yaml # CSS 选择器配置
├── tests/ # 测试
├── .env.example # 环境变量示例
├── aizex.sh # 单实例控制脚本
├── aizex-multi.sh # 多实例控制脚本
├── job_example.json # 批处理任务配置示例
├── Makefile # 构建脚本
└── pyproject.toml # 项目配置
测试
# 运行所有测试
make test
# 运行特定测试
pytest tests/test_mcp_tools.py -xvs
# 测试模型列表功能
pytest tests/test_mcp_tools.py::test_aizex_list_models_tool -xvs
通过inspector直接测试
代码质量
# 代码格式化
make format
# 代码检查
make lint
# 类型检查
make type-check
故障排除
常见问题
-
浏览器无法启动
- 检查 Chrome 是否已安装
- 确认
AIZEX_BROWSER_HEADLESS=false - 查看日志:
./aizex.sh log
-
登录失败
- 检查
.env中的用户名密码 - 确认网络连接正常
- 查看浏览器控制台错误
- 检查
-
会话被踢
- 自动恢复:
aizex_recover_session - 手动恢复:重启服务
./aizex.sh restart
- 自动恢复:
-
文件上传失败
- 检查文件路径是否存在
- 确认文件大小不超过限制
- 查看页面是否支持文件上传
日志查看
./aizex.sh log # 查看服务日志
tail -f aizex.log # 实时查看日志
AizexService 完整方法清单和调用顺序约束
方法清单
| 方法 | 参数 | 返回值 | 用途 |
|------|------|--------|------|
| startup() | 无 | 无 | 启动服务:启动浏览器 → 注入cookies → 导航 → 登录检查 → 备用recovery |
| shutdown() | 无 | 无 | 关闭服务:停止浏览器引擎 |
| ensure_ready_page() | 无 | Page | 确保页面就绪:检查URL → 检查登录 → 自动recovery |
| health() | 无 | HealthResult | 健康检查:返回状态/URL/uptime |
| new_chat() | 无 | ActionResult | 新建对话 |
| list_models() | 无 | ModelListResult | 列出可用模型 |
| select_model(model_name) | str | ActionResult | 选择模型 |
| send_message(text) | str | ActionResult | 发送消息 |
| is_generating(use_text_fallback) | bool | GeneratingResult | 检查是否正在生成 |
| get_last_response() | 无 | ResponseResult | 获取最后一条回复 |
| wait_and_get(timeout_sec) | int | ResponseResult | 等待生成完成并获取回复 |
| list_conversations() | 无 | ConversationListResult | 列出对话列表 |
| select_conversation(conversation_id, title) | str, str | ActionResult | 选择对话 |
| upload_file(file_path) | str | UploadResult | 上传文件 |
| check_downloads(scan_all) | bool | CheckDownloadsResult | 检查可下载文件 |
| download_file(index) | int | DownloadActionResult | 下载指定文件 |
| download_all() | 无 | DownloadActionResult | 下载所有文件 |
| download_multiple(indices) | list | DownloadActionResult | 下载多个文件 |
| refresh_page() | 无 | ActionResult | 刷新页面 |
| recover_session(timeout_sec) | int | RecoveryResult | 恢复session |
| check_credits(force_refresh) | bool | dict | 查询积分余额 |
调用顺序约束
startup() # 必须首先调用
↓
new_chat() → select_model() # 建议顺序(Claude对话禁止中途切模型)
↓
send_message() # 发送消息
↓
wait_and_get() # 等待回复(内部自动轮询)
↓
[可选] upload_file() / check_downloads() / download_file()
↓
shutdown() # 最后调用
关键约束:
startup()→new_chat()→send_message()是标准链路- Claude 对话禁止在已有消息后切模型(会导致session失效)
wait_and_get()内部使用短锁轮询,不会阻塞其他操作的lock获取upload_file()必须在send_message()之前调用recover_session()成功后需重新new_chat()开始新对话
认证和会话生命周期
Cookies 来源
- 启动时注入:
startup()从.last_cookies.json读取并注入到浏览器context - Recovery 时获取:
recover_session()完成 pool re-entry 后,从新context提取全量cookies并保存到.last_cookies.json - 持久化文件:
.last_cookies或.last_cookies.{instance_id}.json(多实例隔离)
Cookies 过期场景
| 场景 | 原因 | 检测方式 | |------|------|----------| | 其他用户登录同一号池 | Aizex号池session被踢 | PageSentinel检测"其他地方登录"等关键词 | | Authing session过期 | Authing SSO登录态过期 | 登录检查失败 | | 浏览器被强杀 | Ctrl+C或kill -9 | 重启后inject的cookies可能失效 | | Cloudflare challenge | Cloudflare验证拦截 | 页面URL跳转到challenge页 |
Recovery 流程
recover_session() 的完整流程:
1. 启动临时非headless浏览器(独立profile: /tmp/aizex-recovery-profile-{instance_id})
2. 导航到 https://aizex.net/plusPool
3. 如果需要登录 → 点击"登录/注册" → Authing认证 → 验证pool可访问
4. 如果已有Authing session → 直接验证pool可访问
5. 切换到高级号池(如果有)
6. 采集积分信息(顺路)
7. 点击指定pool卡片(pool_index)
8. 等待新tab打开 → 提取新URL
9. 返回 RecoveryResult(包含 new_base_url, cookies, browser_context, credits)
10. 主服务调用 engine.adopt_context() 接管新浏览器
11. 更新 settings.base_url 和 session_store
12. 保存cookies到 .last_cookies.json
注意:Recovery 使用独立的浏览器profile,不复用主浏览器的profile,避免SingletonLock冲突。
Session 失效的触发条件
- 响应中检测到关键词:
check_and_recover_response()检查回复文本是否包含"其他地方登录"、"号池重进"等 - PageSentinel pre_check 检测:每次
run_locked()操作前,PageSentinel 检查页面是否有session kicked弹窗 - 手动触发:用户调用
aizex_recover_session工具
手动输入密码
系统不支持在运行时手动输入密码。认证凭据必须在 .env 中预先配置:
AIZEX_USERNAME=your_username
AIZEX_PASSWORD=your_password
所有错误状态和对应的恢复路径
| 错误状态 | 触发条件 | 恢复方法 | 自动/手动 |
|----------|----------|----------|-----------|
| SESSION_KICKED | 响应含"其他地方登录"等关键词;PageSentinel检测到踢出弹窗 | 调用 aizex_recover_session | 手动(需用户确认) |
| LOGIN_REQUIRED | Authing登录态过期;启动时检测未登录 | 调用 aizex_recover_session(recovery会走完整登录流程) | 手动 |
| CLOUDFLARE_BLOCKED | PageSentinel检测到challenge页 | 调用 aizex_recover_session(非headless浏览器可绕过) | 手动 |
| PAGE_NAVIGATION_LOST | 页面URL离开Aizex域名;about:blank | 调用 aizex_refresh_page 或等待自动recovery | 自动(run_locked内) |
| SELECTOR_NOT_FOUND | 页面结构变化导致CSS选择器失效 | 调用 aizex_refresh_page;检查selectors配置 | 手动 |
| SEND_COOLDOWN | 发送间隔小于3秒 | 等待3秒后重试 | 自动(服务端强制) |
| TIMEOUT | wait_and_get 超时(默认900秒) | 调用 aizex_refresh_page;检查AI是否卡住 | 手动 |
| ATTACHMENT_LIMIT | 附件数量超过上限 | 减少附件数量 | 手动 |
| GENERATION_ERROR | AI生成过程中出错 | 调用 aizex_refresh_page;重新发送消息 | 手动 |
| FILE_NOT_FOUND | 上传/下载文件路径不存在 | 检查文件路径 | 手动 |
| SingletonLock | 多个浏览器实例共用同一profile | 使用不同的 instance_id 隔离 | 配置层面 |
自动 Recovery 触发条件
在 run_locked() 内部,以下情况会自动触发 _auto_recover_in_place():
- ensure_ready_page():导航后发现未登录,或URL不在Aizex域名
- PageSentinel pre_check:检测到needs_recovery(SESSION_KICKED、CLOUDFLARE_BLOCKED)
- 简单导航失败:尝试导航后仍然不健康
冷却限制:自动recovery有5分钟冷却期,防止频繁触发。
SlotPool 和单实例 MCP 的关系
架构关系
┌─────────────────────────────────────────────────────────────┐
│ MCP Server (单实例) │
│ instance_id="0" │
│ pool_index=0 │
│ profile: /srv/aizex/profile │
└─────────────────────────────────────────────────────────────┘
↓ 完全独立
┌─────────────────────────────────────────────────────────────┐
│ SlotPool (批处理) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Slot 0 │ │ Slot 1 │ │ Slot 2 │ │
│ │ instance_id │ │ instance_id │ │ instance_id │ │
│ │ = "batch_0" │ │ = "1" │ │ = "2" │ │
│ │ pool_index= │ │ pool_index= │ │ pool_index= │ │
│ │ 0 │ │ 1 │ │ 2 │ │
│ │ profile: │ │ profile: │ │ profile: │ │
│ │ /srv/aizex/ │ │ /srv/aizex/ │ │ /srv/aizex/ │ │
│ │ profile- │ │ profile-1 │ │ profile-2 │ │
│ │ batch_0 │ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└─────────────────────────────────────────────────────────────┘
隔离机制
| 资源 | MCP Server | SlotPool Slot 0 | SlotPool Slot 1 |
|------|------------|-----------------|-----------------|
| instance_id | "0" | "batch_0" | "1" |
| Browser profile | /srv/aizex/profile | /srv/aizex/profile-batch_0 | /srv/aizex/profile-1 |
| Cookies | .last_cookies.json | .last_cookies.batch_0.json | .last_cookies.1.json |
| Chat URL | .last_chat_url | .last_chat_url.batch_0 | .last_chat_url.1 |
| Downloads | /srv/aizex/downloads | /srv/aizex/downloads-batch_0 | /srv/aizex/downloads-1 |
| Artifacts | /srv/aizex/artifacts | /srv/aizex/artifacts-batch_0 | /srv/aizex/artifacts-1 |
是否会冲突
不会冲突,因为:
- 浏览器profile隔离:每个instance_id使用不同的Chromium profile目录,避免SingletonLock冲突
- Cookies隔离:每个instance_id使用不同的cookies文件,不会互相覆盖
- SessionStore隔离:每个instance_id维护独立的活跃URL
- Pool选择:每个slot可以指定不同的pool_index,进入不同的号池
共享的资源
- 代码和配置:所有实例共享同一份代码和
.env配置(但通过环境变量可以覆盖) - Aizex账号:所有实例使用同一个Aizex账号登录(通过Authing SSO)
- 号池:不同slot可以进入不同pool_index的号池,也可以进入同一个(但会被Aizex踢出)
注意事项
- 不要让多个实例进入同一个pool卡片:会被Aizex检测为并发登录,导致session被踢
- MCP Server 运行时可以同时跑 SlotPool:因为使用不同的instance_id,完全隔离
- Ctrl+C 强杀的影响:只会影响被强杀的实例,其他实例不受影响
贡献指南
- Fork 项目
- 创建功能分支 (
git checkout -b feature/amazing-feature) - 提交更改 (
git commit -m 'Add amazing feature') - 推送到分支 (
git push origin feature/amazing-feature) - 创建 Pull Request
许可证
MIT License
联系方式
如有问题或建议,请通过项目 Issues 页面反馈。