Mac 下 QwenPaw 安装记录 - 从零配置 OpenRouter MiniMax 模型

qwenpaw

把 QwenPaw (原 CoPaw) 装好了,记录一下过程。

背景

QwenPaw 是 AgentScope 团队开源的个人 AI 助手,支持钉钉、飞书、微信、Discord 等多渠道,还能本地运行、扩展 Skills。GitHub 星标 15K+。

问题卡点

官方推荐三种安装方式:

  1. pip install qwenpaw - 需要 Python 3.10+
  2. 安装脚本 curl -fsSL https://qwenpaw.agentscope.io/install.sh | bash - 自动下载 uv
  3. Docker

我的系统 Python 是 3.9.6,pip 走系统默认的又太老 (21.2.4),qwenpaw 需要 Python 3.10-3.14。

解决方案:uv

uv 管理 Python 版本,一步到位:

# 1. 安装 uv
curl -LsSf https://astral.sh/uv/install.sh | sh

# 2. 用 uv 安装 Python 3.11
source $HOME/.local/bin/env
uv python install 3.11

# 3. 创建虚拟环境 + 安装 qwenpaw
uv venv ~/.qwenpaw-env --python 3.11
uv pip install qwenpaw --python ~/.qwenpaw-env/bin/python

uv 会自动下载 Python 3.11.15,速度很快。

配置 OpenRouter MiniMax 模型

qwenpaw 内置支持 OpenRouter provider,配置很简单:

编辑 ~/.copaw/config.json

{
  "$schema": "https://qwenpaw.agentscope.io/schema.json",
  "model": {
    "models": {
      "minimax-free": {
        "provider": "openrouter",
        "model": "minimax/minimax-m2.5:free",
        "base_url": "https://openrouter.ai/api/v1",
        "api_key": "你的OPENROUTER_KEY",
        "enabled": true
      }
    },
    "default_model": "minimax-free"
  }
}

注意:OpenRouter 的 MiniMax 模型 ID 格式是 minimax/minimax-m2.5:free,用冒号而不是连字符。

使用

安装完成后:

# 初始化(需要交互式终端)
~/.qwenpaw-env/bin/qwenpaw init

# 或者直接启动 Web UI
~/.qwenpaw-env/bin/qwenpaw app

然后打开浏览器访问 http://127.0.0.1:8088/ 配置和聊天。

89eeb908eec1d5c35b25e24bafb645cc

验证安装

~/.qwenpaw-env/bin/qwenpaw --version
# QwenPaw, version 1.1.3

Agent 配置:从安装到”觉醒”

安装完成只是第一步,真正的挑战在于让 Agent 理解你是谁

核心记忆文件结构

QwenPaw 的工作区(~/.copaw/workspaces/default/)包含以下关键文件:

文件 作用 优先级
PROFILE.md Agent 身份 + 用户资料 🔴 必须配置
SOUL.md Agent 灵魂宣言(行为准则) 🔴 必须配置
MEMORY.md 长期记忆(工具设置/经验教训) 🟡 建议配置
AGENTS.md Agent 行为准则模板 🟢 可选定制
HEARTBEAT.md 定时任务清单 🟢 可选配置

cbce4ba5762672dac29e8274baad8fe4

我的PROFILE.md配置原则

核心原则: 真理至上,探寻底层逻辑。零废话,客观冷峻,默认一切输入均自带「幸存者偏差」,需去伪存真。

响应模块结构:

  1. 🚨 核心扫描 — 一句话点透本质。基于唯物辩证法,精准锁定决定系统生死的「主要矛盾与矛盾的主要方面」。

  2. 👁️‍🗨️ 真实边界 — 剥离表象,指明利益主体潜规则与阶级/生态位。强制执行「跨域同构映射」(提取历史/生态/架构中底层逻辑相似的对照体)。推演极值(成立前提与最坏底线)。

  3. ♟️ 动态决策 — 视提问意图自动匹配:
    • 若为求知 Why/What: 推演事件必然走向与触发质变的核心节点。不给操作建议。
    • 若为求解 How: 输出博弈三策:
      • Plan A (结构寻优/顺势):在现有系统边界内,阻力最小的参数调优与利益最大化路径。
      • Plan B (协议绕过/降维):跳出当前规则层,利用生态位错配或唤醒非对称打击。
      • Plan C (底座保全/熔断):系统崩溃时的强制止损。
  4. ⚡ 执行拷问 — 冷峻逼问。若为求知,拷问其面对系统质变的对冲筹码;若为求解,逼问其路径选择及下一步参数。

  5. 🪞 逆向自检 — 推翻此结论需何种变量突变?指出模型推演盲区。

配置流程

  1. 首次启动 — Agent 会自动读取所有记忆文件,如果为空则使用默认模板。
  2. 手动配置 — 编辑 PROFILE.md 定义身份和偏好,编辑 SOUL.md 定义行为边界。
  3. 持续迭代 — Agent 会在每次会话中主动记录重要信息到 memory/YYYY-MM-DD.md,定期提炼到 MEMORY.md

关键点: QwenPaw 不是每次重启都重新初始化。记忆通过文件持久化,会话中断后自动恢复上下文。

依赖规模

qwenpaw 依赖非常多(244 个包),包括:

  • agentscope 1.0.19
  • playwright 1.58.0 (39MB)
  • transformers 5.5.4 (9.8MB)
  • onnxruntime 1.23.2 (16MB)
  • chromadb 1.5.8 (20MB)
  • grpcio 1.80.0 (11MB)
  • pandas 3.0.2 (9.5MB)
  • alibabacloud-dingtalk 等阿里系 SDK
  • discord-py、twilio 等消息渠道 SDK

首次安装需要下载不少内容,耐心等待。

相关工具对比

工具 语言 特点
QwenPaw Python 多渠道、本地优先、Skills 扩展
OpenCode TypeScript IDE 集成、MCP 生态
Claude Code TypeScript Anthropic 官方

QwenPaw 和 OpenCode 可以通过 ACP (Agent Communication Protocol) 互联,配置里已经默认开启了:

"acp": {
  "agents": {
    "opencode": { "enabled": true },
    "qwen_code": { "enabled": true },
    "claude_code": { "enabled": true }
  }
}

参考资料

  • QwenPaw 官网:https://qwenpaw.agentscope.io/
  • GitHub:https://github.com/agentscope-ai/QwenPaw
  • OpenRouter MiniMax M2.5 Free:https://openrouter.ai/minimax/minimax-m2.5:free

OpenCode 配置 MiniMax 免费模型指南

minimax

今天把 OpenCode 的默认模型配置成了 MiniMax M2.5 Free,教程记录一下。

背景

我想把自己的 OpenCode 配置成使用 MiniMax 的免费模型,于是研究了一下。最新版本是 M2.7(2026年3月发布),但是在 OpenRouter 上免费只有 M2.5,且 oh-my-openagent 插件内部也硬编码了 M2.7,需要一并修改。

MiniMax M2.5 Free 配置教程

1. 申请 OpenRouter API Key

OpenRouter 是一个聚合多家 AI 模型 API 的平台,其中提供了免费的 MiniMax 模型。

  1. 访问 https://openrouter.ai/keys
  2. 点击 “Create a new key” 创建免费 API Key
  3. 复制生成的 Key

2. 配置 OpenCode

编辑配置文件 ~/.config/opencode/opencode.json

{
  "$schema": "https://opencode.ai/config.json",
  "plugin": [
    "oh-my-openagent@latest"
  ],
  "mcp": {
    "playwright": {
      "type": "local",
      "command": [
        "bun",
        "x",
        "@playwright/mcp@latest"
      ],
      "enabled": true
    }
  },
  "provider": {
    "openrouter": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "MiniMax M2.5 Free",
      "options": {
        "baseURL": "https://openrouter.ai/api/v1",
        "apiKey": "你的 OpenRouter API Key"
      },
      "models": {
        "minimax-m2.5-free": {
          "name": "minimax/minimax-m2.5:free"
        }
      }
    }
  },
  "model": "openrouter/minimax/minimax-m2.5:free"
}

3. 配置 oh-my-openagent(如有安装)

如果安装了 oh-my-openagent 插件,它内部默认配置了 minimax-m2.7-free 模型,但 OpenRouter 上免费只有 M2.5。需要修改插件配置。

编辑 ~/.config/opencode/oh-my-openagent.json,将所有 openrouter/minimax/minimax-m2.5:free 替换为 openrouter/minimax/minimax-m2.5:free

{
  "$schema": "https://raw.githubusercontent.com/code-yeongyu/oh-my-opencode/master/assets/oh-my-opencode.schema.json",
  "agents": {
    "hephaestus": {
      "model": "openrouter/minimax/minimax-m2.5:free"
    },
    "oracle": {
      "model": "openrouter/minimax/minimax-m2.5:free"
    },
    "librarian": {
      "model": "openrouter/minimax/minimax-m2.5:free"
    },
    "explore": {
      "model": "openrouter/minimax/minimax-m2.5:free"
    },
    "multimodal-looker": {
      "model": "openrouter/minimax/minimax-m2.5:free"
    },
    "prometheus": {
      "model": "openrouter/minimax/minimax-m2.5:free"
    },
    "metis": {
      "model": "openrouter/minimax/minimax-m2.5:free"
    },
    "momus": {
      "model": "openrouter/minimax/minimax-m2.5:free"
    },
    "sisyphus": {
      "model": "openrouter/minimax/minimax-m2.5:free"
    },
    "sisyphus-junior": {
      "model": "openrouter/minimax/minimax-m2.5:free"
    },
    "atlas": {
      "model": "openrouter/minimax/minimax-m2.5:free"
    }
  },
  "categories": {
    "visual-engineering": {
      "model": "ollama/qwen3-coder-next:q4_K_M"
    },
    "ultrabrain": {
      "model": "openrouter/minimax/minimax-m2.5:free"
    },
    "deep": {
      "model": "openrouter/minimax/minimax-m2.5:free"
    },
    "artistry": {
      "model": "openrouter/minimax/minimax-m2.5:free"
    },
    "quick": {
      "model": "openrouter/minimax/minimax-m2.5:free"
    },
    "unspecified-low": {
      "model": "openrouter/minimax/minimax-m2.5:free"
    },
    "unspecified-high": {
      "model": "openrouter/minimax/minimax-m2.5:free"
    },
    "writing": {
      "model": "openrouter/minimax/minimax-m2.5:free"
    }
  }
}

4. 重启 OpenCode

配置完成后重启 OpenCode 即可使用免费的 MiniMax 模型。

模型信息

模型 价格 Context
MiniMax M2.5 Free $0/M tokens 196K tokens

完全免费!香!

参考资料

  • MiniMax 官方文档:https://platform.minimax.io/docs/
  • OpenRouter:https://openrouter.ai/

为什么 cAdvisor 在部分节点采集不到容器的内存数据?

最近在搞跨云节点的容器监控,遇到一个非常诡异的问题:在 Grafana 面板上,有很多容器拉不到内存信息。

具体表现是,看 container_memory_max_usage_bytes{image!=""} 这个指标时,老节点的数据一切正常,能读到具体的字节数;但新节点的数据全都是 0

仔细对比了一下指标的 id 标签:

  • 有数据的节点/docker/5282f5...
  • 没数据的节点/system.slice/docker-153d1e...scope

路径明显不一致。为了解决这个”断流”问题,踩了几个坑,在这里记录一下排查和修复的全过程。

坑一:盲改 cAdvisor 启动参数

一开始我以为是 cAdvisor 的 cgroup 挂载路径偏移导致的。因为在新节点里,Docker 使用了 systemd 作为 Cgroup Driver。

于是我尝试修改 cadvisor.service 文件,加入了 --runtime_full_cgroup_path=true 参数。结果改完重启,Systemd 直接报错 Failed with result 'exit-code'

查看 journalctl -u cadvisor -f 发现两个致命错误:

  1. 参数语法错误:我把 KillMode=process 写在了 ExecStart 后面,导致解析失败。
  2. 版本弃用:我用的是 v0.46.0 版本的 cAdvisor,这个版本已经完全弃用-runtime_full_cgroup_path 参数!强行加进去只会触发 flag provided but not defined 报错。

坑二:寻找消失的物理路径

既然参数没法调,我决定直接去宿主机上看看 cgroup 的实际目录层级。 按照以往的经验,我执行了:

ls /sys/fs/cgroup/memory/system.slice/docker-*.scope

结果提示:文件不存在。

为了精准定位,采用反向溯源的方法,先拿到容器内主进程的 PID,然后直接看它挂载在哪里:

# 拿到容器的 PID
docker inspect -f '{{.State.Pid}}' iperf-server

# 查看对应 PID 的 cgroup (假设 PID 是 12345)
cat /proc/12345/cgroup

输出结果: 0::/system.slice/docker-153d1e883aa123826...scope

真相大白:Cgroup v1 与 v2 的代沟

看到开头的 0::,懂了。这是 Cgroup v2(统一层级)的特征签名。

根本不是 cAdvisor 挂载错了,也不是参数配错了,而是底层操作系统架构变了:

  • 老节点跑的是 Cgroup v1,有单独的 /memory/ 目录,内核提供了最大内存使用量的统计接口,所以 cAdvisor 能读到数据。
  • 新节点跑的是 Cgroup v2,底层去掉了 memory 目录。在 Cgroup v2 环境下,cAdvisor 获取不到历史极值,于是强行给 container_memory_max_usage_bytes 这个指标塞了一个 0

最终方案:在 PromQL 层面无缝缝合

既然底层都不提供这个数据了,死磕 cAdvisor 配置毫无意义。解决办法是直接在查询层更换跨版本兼容的”真实内存”指标:container_memory_working_set_bytes

但我希望能保留老节点上 max_usage 的历史数据。

利用 PromQL 的 or 逻辑,实现新老数据的缝合替换。修改 Grafana 的查询语句如下:

(container_memory_max_usage_bytes{image!=""} > 0)
or
(container_memory_working_set_bytes{image!=""})

执行逻辑:

  1. 首先尝试获取老指标。因为新节点这个值全是 0,所以 > 0 的条件会把新节点直接过滤掉。
  2. 对老节点来说,左侧条件成立,画出老指标的线。
  3. 对新节点来说,左侧为空,触发 or 逻辑,自动替补使用右侧的新指标 working_set 并在图表上画线。

保存查询,刷新面板。

总结:排查监控数据缺失问题,不要一上来就去猜参数。顺藤摸瓜,从 PID 反查 cgroup 挂载点,直接看操作系统的底层到底给了什么,从根本上解决问题。


Mac 上安装 OrbStack 替代 Docker Desktop

什么是 OrbStack

OrbStack 是一个轻量级的 Docker 替代工具,相比 Docker Desktop:

  • 启动更快
  • 资源占用更低
  • 有原生 macOS GUI
  • 免费(基本功能)

安装过程

1. 下载安装

https://orbstack.dev/download

下载完成后,双击打开 .dmg 文件,将 OrbStack 拖入 Applications 文件夹即可。

2. 启动 Docker

打开 OrbStack 应用,点击 “Start” 按钮启动 Docker 环境。

验证安装:

$ orbctl status
Running

$ docker version --format '{{.Server.Version}}'
28.5.2

配置国内镜像源

配置 Docker 的镜像源来加速拉取。

1. 创建配置文件

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json << 'EOF'
{
  "registry-mirrors": [
    "https://registry.docker-cn.com",
    "https://mirror.ccs.tencentyun.com",
    "https://docker.mirrors.ustc.edu.cn"
  ]
}
EOF

2. 重启 Docker

在 OrbStack 菜单中:

  • Stop Docker
  • Start Docker

测试运行

$ docker run hello-world

Hello from Docker!
This message shows that your installation appears to be working correctly.

完美!🎉

参考


Mac Studio 安装 OpenClaw 多实例共存实录

最近在研究多 Agent 编排,本机已经跑着 copaw。今天心血来潮,决定把底层的 openclaw 单独拎出来跑个 UI 界面看看。

做个记录,备忘。

1. Opencode 辅助安装:一场优雅的权限绕过

为了省事,我直接唤醒了终端里的 AI 助手(Opencode,挂的 MiniMax 模型)帮我装。AI 的排错逻辑挺有意思:

  1. 它首先尝试了官方的无脑脚本:curl -fsSL https://openclaw.ai/install.sh | bash
  2. 发现走不通,立刻切成了全局 NPM 安装:npm install -g openclaw@latest
  3. 随后触发了经典报错:/usr/local/bin/openclaw 文件已存在,引发软链接冲突。
  4. 它的第一反应是 sudo rm 强删,但被系统的交互式密码输入卡住了(终端里的 AI 无法直接帮你输密码)。
  5. 接着它立刻放弃提权,直接用普通权限 rm -f /usr/local/bin/openclaw && npm install -g openclaw@latest。因为我当前账户对该目录有写权限,直接物理抹除并重新接管成功。

最终拿到了 OpenClaw 2026.3.28 版本。AI 时代,连写环境配置都变成了一种结对编程。

image-20260330下午31734247

image-20260330下午31826704

image-20260330下午31858691

image-20260330下午32135388

image-20260330下午32433093

2. 端口冲突

装完后,按常规流程初始化:

openclaw setup
openclaw gateway

结果直接吃了个闭门羹:日志提示 pid 539 kelu: openclaw-gateway (*:18789)。18789 端口已经被占用了。

因为我本机还在跑着 copaw,copaw 也是将 OpenClaw 作为底层通信引擎,早就已经在后台静默拉起了一个 Gateway 守护进程,用了 18789 端口和默认的 ~/.openclaw 工作区。

3. 开启 Dev 沙盒模式

我想同时保留 copaw 的运行状态,又想自己独立玩 OpenClaw 的 Dashboard。既然不能同归于尽,那就只能物理隔离。

OpenClaw 官方提供了一个 --dev 参数,可以解决了多实例共存的问题。

启动独立网关:

openclaw --dev gateway

这行命令直接开辟了一个平行宇宙:

  • 配置文件被隔离到了 ~/.openclaw-dev/openclaw.json
  • 数据工作区被重定向到了 ~/.openclaw/workspace-dev
  • 网关端口自动偏移到了 19001
  • 甚至连局域网的 Bonjour 广播名字,都聪明地加上了后缀 kelu的Mac Studio (OpenClaw) (2) 以防冲突

image-20260330下午30028713

4. 唤醒 UI 控制台

后台引擎在 19001 端口平稳怠速后,新开一个终端页,带上 dev 参数直连:

openclaw --dev dashboard

浏览器瞬间弹出。虽然目前版本的 Web UI 纯英文,没有任何 zh-CN 的汉化选项,但这并不妨碍。

image-20260401上午95833705


清理 Docker 残留网络:解决 ifconfig 中陌生的网桥接口

最近在服务器上查看网络配置,发现 ifconfig 里多了两个陌生的网桥接口:

br-112c7faa4714 br-8f522120d6b1

不记得自己创建过这些。查了一下,原来是 Docker 留下的”网络垃圾”。

发生了什么?

用 Docker Compose 跑过容器后,即使容器已经删除了,Docker 网络可能还留着。

比如之前部署 n8n,用 docker-compose up -d 会自动创建两个网络:

  • n8n_default
  • n8n_n8n-network

后来 n8n 容器不跑了,但这两个网络还在系统里拖着,网桥接口自然就出现了。

怎么查看?

# 查看所有 Docker 网络
docker network ls

# 查看具体网络的连接情况
docker network inspect <网络名>

Containers 字段,如果是空的 {},说明没有容器连这个网络了:

"Containers": {}

怎么清理?

# 删除指定网络
docker network rm n8n_n8n-network
docker network rm n8n_default

删掉之后,ifconfig 里那些陌生的网桥接口就消失了。

更好的习惯

下次用 docker-compose down 的时候,加 --remove-orphans 参数:

docker-compose down --remove-orphans

这样会顺便把 Compose 创建的网络一起清理掉,避免留下垃圾。

一键清理脚本

如果想偷懒,可以定期跑这个,清理所有未使用的网络:

docker network prune -f

会删除所有没有被容器使用的网络。

一句话总结:容器删了不等于网络会删,定期 docker network prune 能让服务器干净点。


RSSHub 安装笔记

之前一直用 Feedly 订阅各类 RSS,但发现有些网站没有原生 RSS,不能直接订阅。听说 RSSHub 可以给这些网站生成 RSS,于是决定自己装一个。

环境

  • 服务器:Linux
  • Docker 已安装
  • 想把服务跑在 1200 端口

安装步骤

1. 创建目录

mkdir -p /root/docker/rsshub
cd /root/docker/rsshub

2. 配置 docker-compose

version: '3.3'

services:
  rsshub:
    image: ghcr.io/diygod/rsshub:latest
    container_name: rsshub
    restart: unless-stopped
    network_mode: host
    environment:
      - NODE_ENV=production
      - PORT=1200
      - CACHE_TYPE=memory
      - CACHE_EXPIRE=60
    volumes:
      - ./data:/tmp/rsshub

这里用了 host 网络模式,端口直接映射到宿主机。数据目录挂载到 ./data,方便持久化。

3. 启动服务

mkdir -p data
docker-compose up -d

4. 验证

curl http://localhost:1200/

看到 Welcome 页面就说明装好了。

小结

RSSHub 装起来比想象中简单,Docker 化部署基本上就是写个配置文件的事。

参考

  • RSSHub 官网:https://rsshub.app
  • Docker Hub:https://hub.docker.com/r/diygod/rsshub