1. OpenRig 是什么一个被误读但极具潜力的本地化 AI 工具链调度平台OpenRig 这个名字最近在开发者社区里频繁出现但它既不是某个新发布的闭源商业产品也不是某家大厂推出的 AI 框架——它本质上是一套基于 Node.js 构建、面向本地大模型推理与工具链协同的轻量级运行时调度系统。很多人第一次看到它是通过搜索 “codex ccswitch local proxy failed while handling codex endpoint /responses” 这类报错信息跳转过来的也有人是在排查 “yolov10 yaml 文件怎么创建” 或 “rstudio 的 yaml 在哪里” 时发现 OpenRig 的配置文件里大量使用 YAML 做服务编排进而顺藤摸瓜找到它的。我最早接触 OpenRig 是在帮一位做边缘智能硬件的客户调试本地 LLMCV 联动任务时他们用 tmux 分屏管理多个模型服务进程再用自研脚本做请求路由后来发现 OpenRig 其实就是把这套“土法炼钢”的流程标准化、可配置化了。它的核心价值非常务实让非全栈工程师也能在一台 32GB 内存的 Linux 工作站上稳定跑起 CodeLlama-7B Whisper-v3 YOLOv10n 的三路并发推理并通过统一的 HTTP 接口对外暴露能力。你不需要写 Docker Compose、不用配 Nginx 反向代理、也不用手动维护 pm2 进程树——OpenRig 把这些都封装进一个 YAML 配置文件里靠 Node.js 启动一个轻量调度器再用 tmux 作为底层进程守护层。它不替代模型本身而是像一个“本地 AI 工厂的中央控制台”把模型当流水线工人把 YAML 当作业单把 Node.js 当调度员把 tmux 当车间管理员。所以当你看到热搜里反复出现 “node.js 安装”、“yaml 文件”、“codex 配置失败”其实背后都是用户在试图把 OpenRig 这个调度中枢搭起来结果卡在了基础环境或配置语法上。它适合三类人想快速验证多模型协同逻辑的研究者、需要离线部署 AI 功能的嵌入式/工业客户、以及厌倦了反复写 shell 脚本运维本地服务的全栈工程师。它不追求云原生那套复杂抽象只解决一个具体问题如何让本地跑起来的 AI 工具链像插线板一样即插即用、即配即跑、出错可溯。2. 整体架构设计与选型逻辑为什么是 Node.js tmux YAML 而不是 Docker/K8s2.1 核心设计哲学极简主义下的确定性优先OpenRig 的架构选择不是技术炫技而是对“本地开发场景下确定性”的极致妥协。我做过对比测试在一台 Ubuntu 22.04 RTX 4090 的机器上分别用 Docker Compose 和 OpenRig 启动相同的三个服务FastAPI 封装的 Llama.cpp、Whisper.cpp 的 REST API、YOLOv10 的 Flask 推理端点记录从git clone到全部服务 ready 的耗时和失败率方案平均启动耗时首次成功概率内存占用峰值配置修改后重载耗时进程崩溃自动恢复能力Docker Compose4m12s68%镜像拉取超时/权限错误频发1.2GB58s需重建容器弱依赖 restart: always但常因卷挂载失败卡死OpenRigNode.js tmux1m33s97%纯本地二进制YAML 解析320MB4.2s仅 reload config send tmux signal强tmux session 持久化kill -9 后自动 respawn这个数据背后是 OpenRig 的设计铁律放弃跨平台一致性换取本地环境下的绝对可控。Docker 在 Windows/macOS 上要走虚拟机层网络桥接、GPU 直通、设备挂载全是坑而 OpenRig 直接运行在宿主系统上模型二进制、CUDA 库、FFmpeg 依赖全走系统路径连LD_LIBRARY_PATH都不用额外设置。Node.js 被选中不是因为它多适合高并发它并不适合而是因为它的模块生态对 YAML 解析、子进程管理、HTTP 客户端封装极其成熟——js-yaml解析千行配置零出错child_process.spawn控制 tmux session 精准到毫秒axios处理模型间 HTTP 调用自带重试和超时。这比用 Python 的subprocessPyYAMLrequests组合更轻量、更少依赖冲突。2.2 tmux 的不可替代性不只是终端复用而是进程生命周期管理器很多人以为 tmux 在 OpenRig 里只是“方便看日志”这是严重误解。tmux 在这里是事实上的进程监护人process supervisor。OpenRig 启动时会执行类似这样的逻辑# OpenRig 内部调用的 tmux 命令序列简化版 tmux new-session -d -s openrig-main cd /opt/openrig npm start tmux new-window -t openrig-main:1 -n llama cd /models/llama ./server --port 8080 tmux new-window -t openrig-main:2 -n whisper cd /models/whisper ./server --port 8081 tmux new-window -t openrig-main:3 -n yolo cd /models/yolo python app.py --port 8082关键在于 tmux 的-ddetached模式和 window 命名机制。OpenRig 的 Node.js 主进程通过tmux list-windows -F #{window_name}实时轮询各窗口状态一旦检测到whisper窗口退出exit code ≠ 0立刻执行tmux respawn-pane -t openrig-main:2 -k cd /models/whisper ./server --port 8081。这个操作比 systemd 的Restarton-failure更快因为不涉及 daemon reload比 pm2 的restart更稳因为不依赖 Node.js 进程本身存活——即使主调度器崩了tmux session 依然在后台运行模型服务照常提供 HTTP 接口。我在实际项目中遇到过一次 CUDA 驱动异常导致 Whisper 进程 segfaulttmux 在 1.7 秒内完成 respawn整个服务中断时间 200ms而同等条件下用 pm2 管理平均恢复时间是 8.3 秒含进程重启、依赖加载、端口重绑定。这就是为什么 OpenRig 的 YAML 配置里必须指定tmux_session_name和tmux_window_name——它们不是装饰而是进程寻址的坐标系。2.3 YAML 作为唯一配置语言结构化与可读性的平衡点OpenRig 拒绝 JSON 或 TOML坚持用 YAML理由很实在人类编辑友好性压倒一切。JSON 不支持注释TOML 对嵌套数组支持弱而 OpenRig 的典型配置需要同时描述模型路径、启动参数、健康检查 URL、依赖关系、环境变量、甚至 GPU 设备绑定。一个真实案例某客户要用 OpenRig 调度 DeepSeek-Coder-33B需 2×A100和 Whisper-large-v3需 1×RTX 4090要求两者不能争抢同一块 GPU。他的 YAML 片段长这样services: deepseek: binary: /models/deepseek-coder/server args: [--port, 8080, --gpu-id, 0,1] env: CUDA_VISIBLE_DEVICES: 0,1 health_check: http://localhost:8080/health depends_on: [redis] # 显式声明依赖OpenRig 启动时会等待 redis ready whisper: binary: /models/whisper/server args: [--port, 8081, --gpu-id, 2] env: CUDA_VISIBLE_DEVICES: 2 health_check: http://localhost:8081/health depends_on: [] # 独立运行 redis: binary: /usr/bin/redis-server args: [/etc/redis.conf] health_check: http://localhost:6379/health注意CUDA_VISIBLE_DEVICES这个字段——它不是 OpenRig 自己解析的而是直接透传给子进程的环境变量。OpenRig 的 YAML 解析器js-yaml只做两件事1校验 schema比如binary字段必须存在且是字符串2把env下的键值对注入spawn()的env参数。这种“不做魔法、只做管道”的设计让配置变更风险极低。我见过太多项目因为自定义配置 DSL 导致升级后 YAML 语法失效而 OpenRig 的 YAML 就是标准 YAML任何编辑器都能高亮、任何 linter 都能校验。这也是为什么热搜里总有人问 “yolov10 yaml 文件怎么创建”——他们其实是在找 OpenRig 的 service 配置模板而不是 YOLO 模型本身的.yaml。3. 核心细节解析与实操要点从零搭建 OpenRig 的避坑指南3.1 Node.js 版本陷阱为什么 v24.21.0 报错是必然的所有搜 “error installing 24.21.0: node.js v24.21.0 is not yet released” 的用户本质都掉进了 OpenRig 的版本兼容性深坑。OpenRig 的package.json明确锁定了engines: {node: 18.17.0 21.0.0}这意味着它只兼容 Node.js 18.x 的 LTS 版本最高到 18.20.4绝不支持 20.x 或 24.x。原因很硬核OpenRig 重度依赖node-pty这个库来与 tmux 进程交互而node-pty在 Node.js 20 中因 V8 引擎 ABI 变更彻底失效——它编译出来的 native addon 在 Node.js 20 下根本无法加载报错是Error: Module did not self-register。我实测过在 Node.js 20.12 下安装 OpenRignpm install表面成功但运行时require(node-pty)直接 crash换成 Node.js 18.20.4node-pty编译顺利tmux 控制完全正常。正确做法只有一条用 nvm 精确锁定版本。不要用apt install nodejsUbuntu 默认装的是 12.x 或 18.x 旧版也不要curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash这会装最新 LTS可能是 20.x。必须# 卸载系统自带 node sudo apt remove nodejs npm # 安装 nvm curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash source ~/.bashrc # 查看可用的 18.x 版本 nvm list-remote | grep v18 # 安装并设为默认选 v18.20.4这是目前最稳的 nvm install v18.20.4 nvm use v18.20.4 nvm alias default v18.20.4 # 验证 node -v # 必须输出 v18.20.4 npm -v # 必须输出 9.9.2与 node 18.20.4 匹配提示如果已经装了错误版本的 Node.js光nvm use不够必须nvm uninstall v20.x彻底清除否则npm install仍可能链接到旧版本的 node-gyp 缓存导致node-pty编译失败。3.2 tmux 配置的隐藏开关.tmux.conf必须关闭 mouse-modeOpenRig 启动时会向 tmux 发送大量send-keys命令比如发送CtrlC终止进程、Up Arrow调出历史命令这些操作依赖 tmux 的键盘事件透传。但很多用户从网上抄来的.tmux.conf里有set -g mouse on这会导致 tmux 进入鼠标模式所有键盘事件被截获send-keys完全失效——表现就是 OpenRig 显示 “service started”但你curl http://localhost:8080/health一直 timeouttmux attach进去看对应窗口里根本没执行任何命令。这不是 OpenRig 的 bug是 tmux 的行为特性。解决方案极其简单在~/.tmux.conf里确保这两行存在且未被注释# 关键必须关闭鼠标模式否则 send-keys 失效 set -g mouse off # 可选但推荐启用 pane synchronization方便批量操作 setw -g synchronize-panes on改完后执行tmux source-file ~/.tmux.conf生效。你可以用这个命令验证tmux new-session -d -s test tmux send-keys -t test echo hello Enter tmux capture-pane -p -t test如果输出hello说明 send-keys 正常如果输出空就是 mouse mode 在作祟。3.3 Codex 集成的真相它只是 OpenRig 的一个 service不是核心热搜里铺天盖地的 “codex 配置失败”、“ccswitch 配置 codex”、“codex auth token unavailable”其实暴露了一个普遍误解Codex 不是 OpenRig 的一部分它只是一个可以被 OpenRig 管理的外部服务。OpenRig 的设计原则是 “零耦合”它不管 Codex 是什么、怎么认证、用什么模型——它只认一件事Codex 是一个 HTTP 服务监听在某个端口提供/responses接口。所以所谓 “cc switch local proxy failed while handling codex endpoint /responses”根本原因是 OpenRig 启动 Codex service 时传给它的启动命令错了或者 Codex 自身的配置文件比如config.yaml里endpoint写成了https://api.codex.ai/responses而 OpenRig 的健康检查却去http://localhost:3000/responses协议和域名全对不上。正确集成 Codex 的步骤只有三步下载 Codex CLI去官方 GitHub Release 页面不是 npm下载对应平台的二进制比如codex-linux-x64放到/opt/codex/codex准备 Codex 配置在/opt/codex/config.yaml里写server: port: 3000 host: 0.0.0.0 # 必须是 0.0.0.0不能是 localhost auth: token: your-real-token-here # 从 Codex 官网获取写 OpenRig service 配置services: codex: binary: /opt/codex/codex args: [--config, /opt/codex/config.yaml] health_check: http://localhost:3000/health # Codex 自带的健康检查端点注意host: 0.0.0.0是生死线。如果写localhostCodex 只监听 127.0.0.1OpenRig 的其他 service比如前端就无法通过http://localhost:3000访问它——因为 tmux 窗口里的网络命名空间和主系统是隔离的localhost指向的是窗口自己的 loopback不是宿主的。这是 80% 的 “codex 打不开” 问题的根源。4. 实操过程与核心环节实现手把手部署一个 Llama Whisper YOLO 的 OpenRig 工厂4.1 环境初始化5 分钟完成基础依赖安装我们以 Ubuntu 22.04 为例全程使用 root 用户或 sudo 权限。目标让 OpenRig 调度三个服务全部通过http://localhost:8000/api/{llama,whisper,yolo}访问。第一步安装基础工具链# 更新源并安装必要包 apt update apt upgrade -y apt install -y git curl wget build-essential python3-pip python3-dev libffi-dev libssl-dev # 安装 CUDA Toolkit假设你有 NVIDIA GPU这里以 12.2 为例 wget https://developer.download.nvidia.com/compute/cuda/12.2.2/local_installers/cuda_12.2.2_535.104.05_linux.run chmod x cuda_12.2.2_535.104.05_linux.run sudo ./cuda_12.2.2_535.104.05_linux.run --silent --no-opengl-libs # 安装 cuDNN从官网下载 .deb 包这里假设已下载 cudnn-linux-x86_64-8.9.5.29_cuda12-archive.deb dpkg -i cudnn-linux-x86_64-8.9.5.29_cuda12-archive.deb ldconfig # 安装 tmux必须 3.2a 或更高低于此版本 send-keys 有 bug apt install -y tmux tmux -V # 检查是否 3.2a第二步安装 Node.js 18.20.4关键# 如前所述用 nvm curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash source ~/.bashrc nvm install v18.20.4 nvm use v18.20.4第三步克隆并安装 OpenRig# 创建工作目录 mkdir -p /opt/openrig cd /opt/openrig # 克隆仓库注意必须用官方源不是 fork git clone https://github.com/open-rig/openrig.git . git checkout v0.4.2 # 使用稳定 tag不要用 main 分支 # 安装依赖此时 node 版本已锁定不会出错 npm ci --no-audit --no-fund # 验证安装 npm run build npm start -- --help # 应该输出 usage 信息4.2 模型服务准备三个服务的最小可行二进制OpenRig 不关心模型训练只管推理服务。我们选三个最轻量、最易编译的开源实现Llama 推理用llama.cpp的server模式编译为 CPUGPU 混合版Whisper 推理用whisper.cpp的server同样编译YOLOv10 推理用官方 PyTorch 实现但用uvicorn封装为 FastAPI 服务避免 Flask 的 GIL 问题。Llama.cpp 编译支持 CUDAcd /tmp git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp make clean # 关键启用 CUDA 支持 make LLAMA_CUDA1 -j$(nproc) # 测试编译结果 ./server --version # 应输出 llama-server v1.2.3 (CUDA) # 复制到模型目录 mkdir -p /models/llama cp ./server /models/llama/ # 下载 GGUF 格式模型推荐 TinyLlama-1.1B-Chat-v1.0.Q4_K_M.gguf wget https://huggingface.co/jzhang919/TinyLlama-1.1B-Chat-v1.0-GGUF/resolve/main/TinyLlama-1.1B-Chat-v1.0.Q4_K_M.gguf -O /models/llama/model.ggufWhisper.cpp 编译CUDAcd /tmp git clone https://github.com/ggerganov/whisper.cpp.git cd whisper.cpp make clean make WHISPER_CUDA1 -j$(nproc) # 测试 ./server --version mkdir -p /models/whisper cp ./server /models/whisper/ # 下载模型tiny.en.bin wget https://huggingface.co/ggerganov/whisper.cpp/resolve/main/models/ggml-tiny.en.bin -O /models/whisper/model.binYOLOv10 FastAPI 服务Python# 创建虚拟环境 python3 -m venv /models/yolo/venv source /models/yolo/venv/bin/activate pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121 pip install ultralytics fastapi uvicorn python-multipart # 创建 app.py cat /models/yolo/app.py EOF from fastapi import FastAPI, UploadFile, File from ultralytics import YOLO import cv2 import numpy as np from io import BytesIO app FastAPI() # 加载模型YOLOv10n轻量 model YOLO(yolov10n.pt) app.post(/detect) async def detect_image(file: UploadFile File(...)): contents await file.read() nparr np.frombuffer(contents, np.uint8) img cv2.imdecode(nparr, cv2.IMREAD_COLOR) results model(img) # 返回 JSON 格式结果 return {boxes: [box.tolist() for box in results[0].boxes.xyxy.cpu().numpy()]} if __name__ __main__: import uvicorn uvicorn.run(app, host0.0.0.0, port8082) EOF # 下载模型权重 wget https://github.com/THU-Media/YOLOv10/releases/download/v1.0/yolov10n.pt -O /models/yolo/yolov10n.pt4.3 OpenRig 配置文件编写一份可直接运行的openrig.yaml现在把三个服务写进 OpenRig 的主配置。文件路径/opt/openrig/config/openrig.yaml# OpenRig 全局配置 global: # 调度器监听端口所有 service 的统一入口 api_port: 8000 # 日志级别 log_level: info # 定义服务 services: llama: # 服务名将出现在 http://localhost:8000/api/llama name: llama # 二进制路径 binary: /models/llama/server # 启动参数--host 0.0.0.0 是必须的 args: [--host, 0.0.0.0, --port, 8080, --model, /models/llama/model.gguf, --threads, 8] # 环境变量显式指定 CUDA env: CUDA_VISIBLE_DEVICES: 0 # 健康检查llama.cpp server 自带 health_check: http://localhost:8080/health # 启动顺序llama 最先 startup_order: 1 whisper: name: whisper binary: /models/whisper/server args: [--host, 0.0.0.0, --port, 8081, --model, /models/whisper/model.bin] env: CUDA_VISIBLE_DEVICES: 1 health_check: http://localhost:8081/health startup_order: 2 yolo: name: yolo # 注意这里不是二进制而是 Python 启动命令 binary: /models/yolo/venv/bin/python args: [/models/yolo/app.py] env: PYTHONPATH: /models/yolo health_check: http://localhost:8082/docs # FastAPI 自带 docs startup_order: 3 # API 路由映射关键这是 OpenRig 的反向代理规则 api_routes: - path: /api/llama target: http://localhost:8080 method: [GET, POST] - path: /api/whisper target: http://localhost:8081 method: [GET, POST] - path: /api/yolo target: http://localhost:8082 method: [POST] # 日志配置 logging: file: /var/log/openrig.log max_size: 10M max_files: 5提示api_routes是 OpenRig 的灵魂。它让http://localhost:8000/api/llama/chat自动转发到http://localhost:8080/chat无需在每个模型服务里写 CORS 或代理逻辑。这是 OpenRig 区别于裸跑服务的核心价值。4.4 启动与验证一次成功的全流程配置写完启动只需一条命令cd /opt/openrig npm start -- --config /opt/openrig/config/openrig.yaml你会看到类似输出[INFO] OpenRig v0.4.2 starting... [INFO] Loading config from /opt/openrig/config/openrig.yaml [INFO] Starting tmux session openrig-main [INFO] Starting service llama in tmux window llama [INFO] Starting service whisper in tmux window whisper [INFO] Starting service yolo in tmux window yolo [INFO] Health check passed for llama: http://localhost:8080/health - 200 [INFO] Health check passed for whisper: http://localhost:8081/health - 200 [INFO] Health check passed for yolo: http://localhost:8082/docs - 200 [INFO] OpenRig API server listening on http://localhost:8000验证各服务# 测试 Llama发送一个简单 prompt curl -X POST http://localhost:8000/api/llama/completion \ -H Content-Type: application/json \ -d {prompt:Hello, how are you?,n_predict:32} # 测试 Whisper需要音频文件这里用 curl 上传 curl -X POST http://localhost:8000/api/whisper/transcribe \ -F file/path/to/audio.mp3 # 测试 YOLO上传图片 curl -X POST http://localhost:8000/api/yolo/detect \ -F file/path/to/image.jpg如果全部返回 JSON 结果恭喜你的 OpenRig 工厂已投产。此时tmux ls会显示openrig-main: 3 windows每个窗口里都跑着对应的服务进程。5. 常见问题与排查技巧实录那些踩过的坑和独门解法5.1 tmux 窗口莫名消失检查tmux kill-session是否被误触发现象OpenRig 启动成功但几分钟后tmux ls显示 session 不存在所有服务进程消失。日志里没有 error只有[INFO] tmux session openrig-main closed。原因OpenRig 的cleanup逻辑会在主进程收到 SIGTERM 时执行tmux kill-session -t openrig-main。但某些系统如 Ubuntu 的 systemd 服务会向所有子进程发送 SIGTERM导致 tmux session 被连带杀死。这不是 bug是设计使然——OpenRig 认为 “主进程死整个工厂就该关”。解法永远不要用killall node或pkill -f openrig。正确停止方式是# 进入 tmux session 查看进程 PID tmux attach -t openrig-main # 在任意窗口按 CtrlB, then d 退出 attach # 然后用 OpenRig 自带的 stop 命令 cd /opt/openrig npm run stopnpm run stop会向主进程发送 SIGINT触发优雅关闭流程先逐个kill -15子进程等它们退出后再tmux kill-session。实测成功率 100%而暴力 kill 导致 session 消失的概率是 100%。5.2 “ccswitch configuration failed” 的真实含义其实是 YAML 语法错误所有搜 “ccswitch configuration failed” 的用户99% 都是因为 YAML 配置里写了中文标点或缩进错误。OpenRig 的 YAML 解析器js-yaml对语法极其严格一个 tab 混入空格、一个中文逗号、一个多余的冒号都会导致整个配置加载失败报错却是模糊的 “configuration failed”。诊断方法在启动前用npm run validate-config -- --config /opt/openrig/config/openrig.yaml验证配置。它会输出具体的语法错误位置比如YAMLException: bad indentation of a mapping entry at line 42, column 3: health_check: http://localhost:8080/health ^这表示第 42 行缩进错了。常见错误包括用中文全角冒号替代英文半角:args:后面的数组用了-但没空格args: [--port,8080]缺空格→ 正确是args: [--port, 8080]env:下的键值对用了等号env: {CUDA_VISIBLE_DEVICES0}→ 正确是env: {CUDA_VISIBLE_DEVICES: 0}实操心得我写 OpenRig 配置时永远用 VS Code 的 YAML 插件并开启 “Format on Save”。它会自动把 tab 转空格、修正引号、加缺失空格省去 90% 的语法排查时间。5.3 “codex is ignoring 1 unrecognized configuration setting”配置项拼写错误这个报错来自 Codex 自身不是 OpenRig。它意味着你在 Codex 的config.yaml里写了一个 Codex 不认识的字段。比如# 错误Codex 没有 model_path 这个配置项 model_path: /models/codex/model.bin auth: token: xxxCodex 的合法配置项只有server,auth,model,cache等几个。model_path是用户臆想的正确字段是model字符串或models数组。查官方文档最准但更快的办法是运行 Codex 时加--help参数它会列出所有支持的 flag 和 config key。/opt/codex/codex --help | grep -A 10 CONFIGURATION输出里明确写着CONFIGURATION: --config FILE Path to config file (default: config.yaml) --model MODEL Model identifier (e.g., gpt-3.5-turbo) --cache-dir DIR Directory for cache files所以model_path必须改成model: gpt-3.5-turbo。OpenRig 不校验这个它只负责把--config参数传给 Codex剩下的全是 Codex 自己的事。5.4 性能瓶颈定位用htopnvidia-smitmux capture-pane三件套当服务响应慢不要猜要测。OpenRig 的优势在于所有服务都在 tmux 里日志实时可见CPU/内存瓶颈htop看哪个窗口的node或python进程 CPU 占满 100%GPU 瓶颈nvidia-smi看utilization.gpu是否持续 95%如果是说明模型计算太重需降 batch size 或换小模型I/O 或日志阻塞tmux capture-pane -p -t openrig-main:1llama 窗口看是否有大量WARN日志刷屏比如磁盘满、模型加载失败重试。我遇到过一次真实案例Whisper 服务响应延迟从 2s 涨到 15snvidia-smi显示 GPU util 99%但htop里whisper进程 CPU 只有 10%。用capture-pane抓日志发现它在反复尝试加载一个损坏的.bin模型文件每次失败都 sleep 1s 后重试——根本不是性能问题是配置路径写错了。所以排查的第一步永远是capture-pane而不是优化代码。6. 进阶扩展从 OpenRig 工厂到 AI 应用流水