开发指南¶
开发环境搭建¶
必备工具¶
- Python 3.11+ 和 uv
- Node.js 20+ 和 npm
- Git (含子模块支持)
- WSL2 (Windows 用户必需,Sandbox 依赖)
- bubblewrap (安装在 WSL 发行版内)
WSL Sandbox 环境准备¶
项目在 Windows 上通过 WSL2 运行 bwrap 沙箱,需要先准备沙箱发行版:
# 1. 导出已有的 WSL 发行版(如 Ubuntu)为镜像
wsl.exe --export Ubuntu C:\TempSandbox\ubuntu-full.tar.gz
# 2. 导入为独立沙箱发行版
wsl.exe --import AIShadowSandbox C:\TempSandbox\ActiveInstance C:\TempSandbox\ubuntu-full.tar.gz --version 2
# 3. 在沙箱发行版中安装 bubblewrap
wsl.exe -d AIShadowSandbox -- bash -c "apt-get update && apt-get install -y bubblewrap"
# 4. 确认安装
wsl.exe -d AIShadowSandbox -- bash -c "bwrap --version"
克隆并初始化¶
启动开发模式¶
开发模式下: - Renderer (React UI):Vite HMR 热更新,修改即时生效 - Main Process (Electron):修改后需重启应用 - Bridge Server (Python):修改后需重启应用
架构概览¶
┌────────────────────────────────────────────────┐
│ Electron App │
│ ┌──────────┐ IPC ┌──────────────────────┐ │
│ │ Renderer │◄──────►│ Main Process │ │
│ │ (React) │ │ ┌──────────────────┐ │ │
│ │ │ │ │ BridgeManager │ │ │
│ └──────────┘ │ │ (Python 子进程) │ │ │
│ │ │ stdin/stdout │ │ │
│ │ │ JSON-line 协议 │ │ │
│ │ └──────────────────┘ │ │
│ └──────────────────────┘ │
└────────────────────────────────────────────────┘
│
│ wsl.exe -d AIShadowSandbox
▼
┌────────────────────────────────────────────────┐
│ WSL2 AIShadowSandbox │
│ ┌──────────────────────────────────────────┐ │
│ │ bwrap sandbox (per-session) │ │
│ │ - 文件系统隔离 (tmpfs + bind mounts) │ │
│ │ - 网络共享 (share_net=True) │ │
│ │ - PID/UTS/User 命名空间隔离 │ │
│ └──────────────────────────────────────────┘ │
└────────────────────────────────────────────────┘
前后端通过 JSON-line stdin/stdout 协议通信,每行一个完整的 JSON 消息,格式为 ["CMD", {...payload}]。
开发工作流¶
Python 后端开发¶
miqi/
├── agent/ Agent 引擎
│ ├── loop.py AgentLoop — LLM 调用循环
│ ├── context.py ContextBuilder — 上下文注入
│ └── tools/ 工具实现
│ ├── shell.py ExecTool — Shell 执行(集成 Sandbox)
│ ├── filesystem.py 文件操作(支持 WSL 路径映射)
│ └── web.py 网络搜索与抓取
├── bridge/
│ ├── server.py Bridge Server — IPC handler + SandboxManager
│ └── protocol.py JSON-line 协议解析
├── config/
│ ├── schema.py Pydantic 配置模型(含 SandboxConfig)
│ └── loader.py 配置加载(~/.miqi/config.json)
├── providers/ LLM 提供商适配
├── sandbox/
│ ├── bwrap.py BwrapSandbox — per-session bwrap 封装
│ └── manager.py SandboxManager — 沙箱生命周期管理
└── memory/ 三层记忆系统
关键模块说明:
| 模块 | 职责 |
|---|---|
AgentLoop |
管理 LLM 调用循环,处理工具调用结果,注入上下文 |
BridgeServer |
57 个 IPC handler,管理 Bridge 状态、SandboxManager、配置热更新 |
BwrapSandbox |
封装 bwrap 命令构建与执行,自动检测 Windows+WSL 环境 |
SandboxManager |
管理 per-session 沙箱生命周期,状态落盘到 ~/.miqi/sandbox_state.json |
SandboxConfig |
沙箱配置:enabled、share_net、wsl_distro、sandbox_distro_name、max_sandboxes 等 |
前端开发¶
apps/desktop/src/
├── main/ Electron 主进程
│ ├── bridge.ts BridgeManager — Python 子进程管理
│ └── ipc/ IPC handler 注册
│ └── index.ts PYTHON_CHECK 等环境检查
├── preload/ contextBridge 安全 API
│ └── index.ts 暴露 window.miqi.* 命名空间
├── renderer/ React 19 UI(HMR 热更新)
│ ├── components/ 通用组件
│ ├── pages/ 15 个功能页面
│ └── hooks/ 自定义 Hooks
└── shared/ 前后端共享类型
└── ipc.ts IPC 通道 + Zod Schema 定义
修改规则:
| 修改范围 | 生效方式 |
|---|---|
renderer/ |
HMR 热更新,无需重启 |
main/ |
需重启应用 |
preload/ |
需重启应用 |
shared/ |
前后端同步,需重启 |
添加新的 IPC 通道¶
- shared/ipc.ts — 定义 IPC 常量 + Zod Schema(入参和返回值类型)
- main/ipc/ — 实现 Main 进程 handler(调用 BridgeManager)
- bridge/server.py — 实现 Bridge handler(业务逻辑)
- preload/index.ts — 通过
contextBridge暴露 API - renderer/ — 调用
window.miqi.*API
沙箱配置¶
~/.miqi/config.json 中 tools.sandbox 段:
{
"tools": {
"sandbox": {
"enabled": true,
"share_net": true,
"max_sandboxes": 10,
"auto_cleanup": true,
"wsl_distro": "AIShadowSandbox",
"sandbox_distro_name": "AIShadowSandbox",
"wsl_base_dir": "/tmp/miqi-sandboxes"
}
}
}
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enabled |
bool | true | 启用沙箱隔离 |
share_net |
bool | true | 共享宿主机网络(true=容器可联网) |
max_sandboxes |
int | 10 | 最大并发沙箱数 |
auto_cleanup |
bool | true | 会话结束时自动清理沙箱 |
wsl_distro |
str | "AIShadowSandbox" | WSL 发行版名称 |
sandbox_distro_name |
str | "AIShadowSandbox" | 专用沙箱发行版(优先级高于 wsl_distro) |
wsl_base_dir |
str | "/tmp/miqi-sandboxes" | WSL 内沙箱根目录 |
代码规范¶
Python¶
TypeScript¶
提交规范¶
遵循 Conventional Commits:
feat: 添加 SkillHub 页面
fix: 修复快照回滚时的文件创建问题
refactor: 重构 SessionManager 存储层
docs: 更新 README 安装说明
test: 添加 TaskTrace 数据模型测试
构建与打包¶
Python Bridge 可执行文件¶
使用 PyInstaller 打包为自包含 miqi-bridge.exe(内嵌 Python + 全部依赖):
产物在 dist/ 目录:
- dist/miqi-bridge.exe — 自包含可执行文件
- dist/miqi-bridge/ — 目录形式的分发包
关键规格 (miqi.spec):
- console=False — 无控制台窗口,但仍可通过 stdout 管道通信
- 打包全部 Python 依赖(loguru、pydantic、httpx 等)
- 不支持 -c 参数:传参会变为 sys.argv 而非 Python 解释器选项
环境检查¶
Electron 启动时通过 PYTHON_CHECK IPC 检测 Python 环境:
- 优先检测
dist/miqi-bridge.exe(bundled 可执行文件) - 不存在则检查系统 Python(
python -c "import miqi")
生产构建¶
测试¶
Python 测试¶
# 运行所有测试
uv run pytest
# 运行特定模块
uv run pytest tests/test_trace.py
# 带覆盖率
uv run pytest --cov=miqi --cov-report=html
# 沙箱网络测试
uv run python tests/test_sandbox_network.py
前端测试¶
调试¶
Python 调试¶
开发模式下,Bridge Server 的日志输出到 Electron DevTools Console:
日志格式:[miqi-bridge] <level> <message>
通过 --no-logs 参数可将日志级别降为 WARNING。
前端调试¶
- 打开 Electron DevTools:
Ctrl+Shift+I - React DevTools 可用
- Network 面板可查看 IPC 通信
Sandbox 调试¶
查看沙箱状态¶
状态文件记录所有活跃沙箱的 session_key、路径、创建时间。Bridge 重启时自动清理遗留沙箱。
手动进入 bwrap 沙箱¶
# 进入 WSL 沙箱发行版
wsl.exe -d AIShadowSandbox
# 查找沙箱目录
ls /tmp/miqi-sandboxes/
# 进入沙箱(替换 YOUR_SESSION_KEY 为实际会话 ID)
bwrap \
--unshare-pid --unshare-ipc --unshare-uts \
--hostname miqi-sandbox \
--unshare-user-try --uid 1000 --gid 1000 \
--proc /proc --dev /dev \
--ro-bind-try /usr /usr \
--ro-bind-try /bin /bin \
--ro-bind-try /lib /lib \
--ro-bind-try /lib64 /lib64 \
--bind /tmp/miqi-sandboxes/YOUR_SESSION_KEY/etc /etc \
--bind /tmp/miqi-sandboxes/YOUR_SESSION_KEY/home/miqi /home/miqi \
--bind /mnt/c/Users/Intership003/.miqi/workspace /home/miqi/workspace \
--tmpfs /tmp \
--die-with-parent --new-session \
--setenv HOME /home/miqi \
--setenv PATH /usr/local/bin:/usr/bin:/bin \
bash -i
注意:
/etc使用沙箱本地的完整拷贝(sandbox_base/etc),而非--ro-bind-try /etc /etc。后者在 WSL 中会静默失败。
常用沙箱内调试命令¶
# 检查 DNS
cat /etc/resolv.conf
cat /etc/nsswitch.conf
getent hosts www.baidu.com
# 检查网络
curl -I https://www.baidu.com
ping -c 1 8.8.8.8
# 检查挂载
mount | grep bwrap
ls /home/miqi/workspace/
沙箱故障排查¶
| 问题 | 可能原因 | 解决 |
|---|---|---|
bwrap: Can't create file at /etc/... |
/etc 挂载失败 |
检查 sandbox_etc 目录是否存在 |
| 网络不通 (DNS 失败) | nsswitch.conf 缺失或 resolv.conf 错误 | 检查 /etc/nsswitch.conf 有 hosts: files dns 行 |
WinError 206 |
bwrap 参数超 Windows 命令行长度限制 | 已自动使用脚本方式执行,如仍出现需进一步拆分参数 |
| 沙箱不释放 | Bridge 异常退出 | 重启 Bridge 自动清理,或手动 rm -rf /tmp/miqi-sandboxes/* |
路径映射¶
Windows 路径在 WSL sandbox 中自动映射:
| Windows 路径 | WSL 内路径 |
|---|---|
C:\Users\foo\.miqi\workspace |
/mnt/c/Users/foo/.miqi/workspace |
D:\projects\app |
/mnt/d/projects/app |
filesystem.py 中的 _resolve_sandbox_path() 和 _resolve_sandbox_cwd() 处理路径自动转换。
目录约定¶
| 目录 | 约定 |
|---|---|
miqi/ |
纯 Python,不包含 Node.js 依赖 |
apps/desktop/ |
纯 Node.js/TypeScript,通过 Bridge 的 JSON-line 协议通信 |
tests/ |
镜像 miqi/ 结构,test_module.py 对应 module.py |
docs/ |
MkDocs Material 格式,每个页面一个 .md 文件 |
dist/ |
PyInstaller 打包产物(miqi-bridge.exe 等) |
dist-new/ |
electron-builder 打包产物 |
build/ |
PyInstaller 构建中间文件 |
scripts/ |
Shell 辅助脚本 |