闭源商业软件 · 自有许可见 LICENSE · 上游 QwenPaw 许可见 LICENSE_QwenPaw · 修改记录见 NOTICE
目录
项目简介
PineAgents 是一个可自主运行的智能体操作系统(Agent OS):它通过多频道(钉钉、飞书、微信、QQ、Discord、Telegram 等)与用户对话,用 Skills 与插件扩展能力,支持定时任务(Cron)、多智能体编排、代码模式与三层记忆。
本项目是开源项目 QwenPaw(Apache 2.0)的闭源商业衍生,走「Fork + 上游同步」开发路线。所有基于上游的修改均登记在 NOTICE。
目录结构
顶层
| 路径 | 作用 |
|---|---|
src/pineagents/ |
Python 后端运行时(全部核心逻辑) |
console/ |
前端 Web 界面(React + Vite),含 Tauri 桌面壳(console/src-tauri/) |
plugins/ |
独立插件包(channel / tool / app) |
deploy/ |
Docker 部署(Dockerfile、entrypoint.sh、config/) |
scripts/ |
构建 / 安装 / 打包脚本 |
assets/readme/ |
README 静态资源(本项目 SVG 图) |
tests/ |
测试(unit / contract / integration / e2e) |
docs/secondary-dev/ |
二次开发文档(品牌盘点、抽离方案) |
old_docs/ |
原上游文档归档(QwenPaw README/CONTRIBUTING/RELEASING 等) |
LICENSE |
PineAgents 闭源商业许可 |
LICENSE_QwenPaw |
上游 QwenPaw(Apache 2.0)许可 |
NOTICE |
所有基于上游的修改说明(必读) |
SECURITY.md |
安全策略 |
后端核心(src/pineagents/)
| 模块 | 作用 |
|---|---|
constant.py |
核心常量、路径、环境变量回退(品牌配置入口) |
branding.py |
品牌单一事实源(PineAgents 命名,改品牌改这里) |
agents/ |
智能体核心:react_agent.py(决策循环)、prompt 构建、Skill 系统、工具集、记忆 |
runtime/ |
运行时编排:循环执行、工具守卫、slash 命令、prompt 管理 |
app/ |
FastAPI 服务层:路由、频道接入、多智能体管理、Cron、工作区 |
cli/ |
命令行入口(pineagents / qwenpaw / copaw),含 TUI |
providers/ |
模型供应商(云端 / 本地 Ollama / LM Studio) |
drivers/ |
协议连接器层(MCP / A2A / ACP) |
governance/ |
权限治理(allow / deny / ask / sandbox) |
sandbox/ |
内核级执行隔离(macOS Seatbelt / Linux Bubblewrap / Win AppContainer) |
security/ |
Tool Guard / File Guard / Skill Scanner 安全规则 |
memory/ |
记忆(三层:工作上下文、逐字历史、ReMe 个人知识库) |
loop/ |
循环模板(Coding Mode / Mission Mode)与审批门控 |
token_usage/ |
每轮 token / 上下文用量统计 |
plugins/ |
插件加载与市场 |
pawapp/ |
小程序(App)平台 |
前端(console/)
| 路径 | 作用 |
|---|---|
src/pages/ |
页面:Chat、Settings(Agents/Models/Market…)、Agent 配置、Inbox、AppCenter |
src/layouts/ |
侧边栏 / 顶栏 / 菜单 / 路由注册 |
src/stores/ |
前端状态(agent、session、sidebar、message queue) |
src/api/ |
后端 REST 接口封装 |
src/plugins/ |
插件宿主 SDK(window.PineAgents 契约) |
src/locales/ |
多语言文案(zh/en/ja/ru/vi…) |
src/constants/branding.ts |
前端品牌单一事实源 |
src-tauri/ |
Tauri 桌面壳 |
架构与流程
一次对话的主链路:用户入口 → FastAPI 服务层 → 运行时编排 → 智能体决策循环 → 输出,并由治理、沙箱、记忆、用量四类横向能力贯穿。
一次对话的简要流程:
- 用户从任意入口(Web / CLI / 频道)发送消息。
app/接收并路由到对应 Agent 会话。runtime/组装 prompt(含 Persona、上下文、记忆检索),进入决策循环。agents/react_agent.py迭代:思考 → 调用工具(经 Tool Guard 与治理门控)→ 沙箱内执行。- 结果回流,模型生成最终回复,经频道分发返回用户。
- 关键交互写入记忆与 token 用量。
环境要求
| 组件 | 要求 |
|---|---|
| Python | ≥ 3.11 且 < 3.14 |
| Node.js / npm | 前端构建必需 |
| uv | 可选(安装/虚拟环境加速) |
| Rust | 仅构建桌面端(Tauri)需要 |
| Docker | 仅容器化部署需要 |
安装(从源码)
git clone <PineAgents 仓库地址>
cd PineAgents
# 1. 构建前端控制台(Web 界面必需)
cd console && npm ci && npm run build && cd ..
# 2. 将构建产物复制进 Python 包
mkdir -p src/pineagents/console
cp -R console/dist/. src/pineagents/console/
# 3. 安装 Python 包
pip install -e .
开发模式(含测试/格式化依赖):
pip install -e ".[dev,test,full]"不想手工复制前端时,直接用bash scripts/wheel_build.sh(见下文「构建与打包」),它自动完成第 1、2 步。
启动
# 初始化(交互式;--defaults 使用默认值)
pineagents init --defaults
# 启动 Web 控制台(默认 http://127.0.0.1:8088/)
pineagents app
# 终端界面(TUI)
pineagents
# 在当前代码仓库中启动(Coding 模式)
pineagents .
兼容命令:
qwenpaw/copaw仍可用(指向同一入口,供同步与迁移)。 端口覆盖:pineagents app --port 3000(默认 8088)。 首次启动需在控制台 设置 → 模型 配置模型(云端 API Key 或本地 Ollama / LM Studio)。
构建与打包
前端 Console
cd console
npm run dev # 开发热更新(http://localhost:5173)
npm run build # 生产构建(tsc -b && vite build)
npm run build:prod # 生产构建(production 模式)
npm run lint # ESLint
npm run test:run # 前端单测
npm run format:check # 格式化检查
Python Wheel(一键,含最新前端)
# macOS / Linux
bash scripts/wheel_build.sh
# Windows(PowerShell)
pwsh -File scripts/wheel_build.ps1
自动完成:构建前端 → 复制 console/dist 到 src/pineagents/console/ → 打包文档 → 生成 wheel 与 sdist。产物位于 dist/(*.whl / *.tar.gz)。
桌面应用(Tauri,PyInstaller 后端 sidecar)
桌面端 = Tauri v2 壳 + React 前端(console/)+ Python FastAPI 后端(PyInstaller sidecar qwenpaw-backend)。产物:macOS .app/.dmg、Windows NSIS 安装包,以及自动更新所需的 .app.tar.gz / *-setup.exe + .sig。
版本号设置(唯一来源,一个命令)
版本唯一来源是 src/pineagents/__version__.py(PEP 440,如 0.0.1b1)。设置版本号用标准脚本,一条命令完成「写版本 + 同步 Tauri semver + 生成 gitignored 的 tauri.version.conf.json」:
./scripts/version-bump.sh 0.0.1b1 # 预发布 beta(→ Tauri semver 0.0.1-beta.1)
./scripts/version-bump.sh 0.0.1-beta.1 # 同上,semver 写法自动转换
./scripts/version-bump.sh 0.0.1 # 正式版
./scripts/version-bump.sh 0.0.1-rc.1 # RC
./scripts/version-bump.sh 0.0.1.post1 # 构建号
两种写法均可:PEP 440(
0.0.1b1)或 semver(0.0.1-beta.1),脚本统一转为 PEP 440 写入__version__.py。
版本号的读取规则(打包时以此为准)
__version__.py 里的 __version__ 在运行时由配置解析(优先 ~/.pineagents/config.json 的 app_version,缺省回退 _DEFAULT_APP_VERSION)。因此打包侧(macOS/Windows 脚本与 sync_tauri_version.mjs)不解析运行时值,而是按下述优先级读取声明的版本:先匹配 __version__ = "x.y.z",匹配不到再回退 _DEFAULT_APP_VERSION = "x.y.z"。所以:
- 打正式包前,无需改配置;只需
version-bump.sh <版本>(它重写__version__行)并确保_DEFAULT_APP_VERSION与之一致(一般保持相同)。 - 若线上实测改动过
app_version,以_DEFAULT_APP_VERSION为准对齐,避免打包版本与实际运行版本不一致。
sync_tauri_version.mjs 会根据读到的版本来生成 Tauri semver:0.0.1b1 → 0.0.1-beta.1(仅 a/b/rc 预发布标签映射,post/dev 自动拼接)。脚本不支持 0.0.1b1.post2 之外更复杂的写法,toSemver 遇到无法解析的版本会直接报错。
不直接改
tauri.conf.json的 version(避免 rebase 后产生陈旧的生成值);打包时以--config src-tauri/tauri.version.conf.json读取。 环境变量TAURI_UPDATER_ENDPOINTS可覆盖更新源(JSON 数组或逗号分隔),用于测试/预发环境;缺省沿用tauri.conf.json的plugins.updater.endpoints。
macOS / Windows 一键构建、产物清单
# macOS → dist/ 下产出 .app / .dmg / zip / .app.tar.gz(自动更新产物)
./scripts/pack-tauri/build_macos_pyinstaller.sh
# Windows(PowerShell)→ 产出 NSIS 安装包
pwsh -File scripts/pack-tauri/build_win_pyinstaller.ps1
一键脚本内部依次完成:前端构建(npm run build:prod)→ 版本同步 → PyInstaller 后端 sidecar(build_pyinstaller.sh/.ps1)→ tauri build → 产物收集(含 updater stage)。
macOS 签名(当前无 Apple Developer ID):一键脚本在未配置证书时自动使用 ad-hoc 签名(
APPLE_SIGNING_IDENTITY="-"),本地运行与分发可用但不做公证;将来申请到 Developer ID 后配置证书名重新构建,即可启用正式签名与公证:export APPLE_SIGNING_IDENTITY="Developer ID Application: 你的证书名" ./scripts/pack-tauri/build_macos_pyinstaller.sh更新签名(Tauri v2 原生格式,密钥已生成本地):密钥对保存在项目
mykey/目录(私钥tauri-signer.key权限 600,已加入 .gitignore 严禁提交仓库;公钥tauri-signer.key.pub已同步至tauri.conf.json与 server-core.env的DESKTOP_UPDATER_PUBKEY)。构建脚本会自动从mykey/tauri-signer.key加载私钥(单行 base64,无密码),无需手动 export;如需手动注入:export TAURI_SIGNING_PRIVATE_KEY="$(cat mykey/tauri-signer.key)" export TAURI_SIGNING_PRIVATE_KEY_PASSWORD="" # 生成密钥时未设密码则为空重新生成密钥对(丢失私钥后所有旧更新包将无法验证):
cd console && npx tauri signer generate -w ../mykey/tauri-signer.key --ci # 然后把新公钥(mykey/tauri-signer.key.pub 内容)同步到 tauri.conf.json plugins.updater.pubkey 和 server-core .env DESKTOP_UPDATER_PUBKEY上传
.sig到 admin 时,服务端会校验签名 key id 与tauri.conf.json的plugins.updater.pubkey是否一致。
手动分步构建
# 1) 前端引导产物
cd console
npm run build:tauri-bootstrap # 产出 dist-tauri
# 2) 后端 sidecar(PyInstaller,产物在 dist/ 下)
cd ..
./scripts/pack-tauri/build_pyinstaller.sh # macOS / Linux
pwsh -File scripts/pack-tauri/build_pyinstaller.ps1 # Windows
# 3) Tauri 打包(macOS 示例;--bundles app 只构建 app+updater,跳过 dmg(app 体积>3G 时 dmg 易失败))
cd console
export TAURI_SIGNING_PRIVATE_KEY="$(cat ../mykey/tauri-signer.key)"
export TAURI_SIGNING_PRIVATE_KEY_PASSWORD=""
npx tauri build --config src-tauri/tauri.version.conf.json --bundles app
产物清单
| 产物 | 位置 | 用途 |
|---|---|---|
YunOPC-Hub.app |
console/src-tauri/target/release/bundle/macos/ |
macOS 应用本体 |
*-macOS.app.tar.gz |
dist/(一键脚本) |
macOS 自动更新产物(Tauri updater) |
*-macOS.app.tar.gz.sig |
dist/ |
自动更新包签名(Tauri 原生格式) |
*-macOS.zip |
dist/ |
手动分发压缩包(含 .app) |
*-setup.exe |
dist/ |
Windows 安装与自动更新 |
同目录 *.sig |
随安装包 | Tauri 更新签名(tauri build 自动生成) |
注意:当前 macOS 构建默认
--bundles app(不生成 .dmg),因 app 内含 PyInstaller 后端(torch/pandas 等,>3G),dmg 打包易超时失败。如需 dmg,可手动npx tauri build --bundles app,dmg,但建议先精简后端依赖。
更新发布(admin 端)
自建更新源为 https://opc.pinesound.cn/desktop-updates/*(server-core 动态生成 latest.json / meta.json,产物托管于 /desktop-updates/files/*)。运营方在 admin-portal「桌面端版本」页面上传各平台安装包 + .sig,设置发布说明、灰度比例与强制最低版本后发布;桌面端通过 X-App-Version 请求头参与灰度判定,min_version 低于当前版本时强制自动安装。
# 发布 SOP(每次发版)
# 1) 设置版本号(唯一命令:写 __version__.py + 同步 Tauri semver)
./scripts/version-bump.sh 0.0.1b1
# 2) 注入更新签名私钥后一键构建(macOS 无证书自动 ad-hoc,不公证)
# 构建脚本已自动从 mykey/tauri-signer.key 加载私钥,此行可省略;如需手动注入:
# export TAURI_SIGNING_PRIVATE_KEY="$(cat mykey/tauri-signer.key)"
./scripts/pack-tauri/build_macos_pyinstaller.sh # macOS
pwsh -File scripts/pack-tauri/build_win_pyinstaller.ps1 # Windows
# 3) admin-portal「桌面端版本」→ 新建版本(版本号与第 1 步一致)
# 逐平台上传 安装包 + 同名 .sig → 设置发布说明/灰度比例/强制最低版本 → 发布
# 观察运行反馈后调至 100% 全量;异常时下架当前版本 / 重新发布上一版本回滚
增量更新(Incremental Update,本地生成完整产物)
增量更新 = Tauri updater 让已安装客户端静默拉到新版本。核心产物是「按平台生成的更新包(.app.tar.gz / *-setup.exe)+ 对应 .sig 签名」+「一个统一的 latest.json 清单」。generate_update_manifest.py 提供两个子命令完成本地编排(macOS 一键脚本已自动走 stage,Windows 打包时 tauri build 自动产出 .sig):
子命令 1:stage — 把单个平台的更新产物收集到 dist/ 并写 sidecar
① 首先构建产物(跳过手动注入密钥部分,构建脚本会自动从 mykey/tauri-signer.key 加载私钥):
# macOS(产物含 .app.tar.gz + .sig,一键脚本已自动执行 stage)
./scripts/pack-tauri/build_macos_pyinstaller.sh
# Windows(产物含 -setup.exe + .sig)
pwsh -File scripts/pack-tauri/build_win_pyinstaller.ps1
② 若构建脚本未替你 stage(或要在构建之外手动补跑),手动执行:
# macOS(darwin-aarch64 / darwin-x86_64 视 arch 而定,脚本已自动判断)
python3 scripts/pack-tauri/generate_update_manifest.py stage \
--bundle-dir console/src-tauri/target/release/bundle/macos \
--pattern '*.app.tar.gz' \
--target darwin-aarch64 \
--output "dist/YunOPC-Hub-0.0.1b1-macOS.app.tar.gz" \
--pubkey-config console/src-tauri/tauri.version.conf.json
# Windows(windows-x86_64)
python scripts/pack-tauri/generate_update_manifest.py stage \
--bundle-dir console/src-tauri/target/release/bundle/nsis \
--pattern '*-setup.exe' \
--target windows-x86_64 \
--output "dist/YunOPC-Hub-0.0.1b1-setup.exe" \
--pubkey-config console/src-tauri/tauri.version.conf.json
--bundle-dir:Tauri 产物目录(macOS 为bundle/macos,Windows 为bundle/nsis)。--pattern:匹配产物名(macOS 用*.app.tar.gz,Windows 用*-setup.exe)。--target:更新目标(darwin-aarch64/darwin-x86_64/windows-x86_64),必须与客户端目标一致。--output:产物落盘路径,同名的.sig会一并复制。--pubkey-config:可选;传tauri.version.conf.json时会把.sig的签名 key id 与配置里plugins.updater.pubkey比对,不一致直接报错(强烈建议每次携带)。
每次 stage 会在产物同目录写一个 sidecar JSON(tauri-<target>-updater.json),记录 target / artifact / signature。
子命令 2:manifest — 汇总各平台 sidecar,生成统一 latest.json
python3 scripts/pack-tauri/generate_update_manifest.py manifest \
--version 0.0.1b1 \
--base-url "https://opc.pinesound.cn/desktop-updates/files" \
--metadata \
dist/tauri-darwin-aarch64-updater.json \
dist/tauri-windows-x86_64-updater.json \
--notes "发布说明:本次修复 xxx" \
--output dist/latest.json
--version:本次版本(PEP 440,写入清单的version字段,会转成 semver)。--base-url:产物托管 URL 前缀(缺省所有平台统一;url = <base-url>/<artifact>)。--metadata:各平台stage生成的 sidecar JSON(可重复传多次)。--target-base 'target=URL':可选、可重复。当各平台产物在不同目录(如 OSS 分win-tauri/与mac-tauri/)时按目标覆盖base-url。--notes/--pub-date:发布说明与时间(pub-date缺省为当前 UTC,ISO 格式)。--output:最终清单路径,即tauri.conf.json里plugins.updater.endpoints指向的那个latest.json。
产物与清单的对应关系
| 文件名 | 说明 |
|---|---|
YunOPC-Hub-<version>-macOS.app.tar.gz(+.sig) |
macOS 增量更新包(Tauri updater) |
YunOPC-Hub-<version>-setup.exe(+.sig) |
Windows 增量更新包(Tauri updater) |
tauri-<target>-updater.json |
stage 生成的平台 sidecar |
latest.json |
manifest 汇总的最终清单(客户端拉取的入口) |
latest.json的内容结构:{ "version": "<semver>", "notes": "...", "pub_date": "...", "platforms": { "<target>": { "url": "...", "signature": "<minisign base64>" } } }。
准备更新源 / 覆盖端点
tauri.conf.json 的缺省端点是 https://opc.pinesound.cn/desktop-updates/latest.json。构建/测试时可用环境变量覆盖(无需改配置):
export TAURI_UPDATER_ENDPOINTS='["https://opc.pinesound.cn/desktop-updates/latest.json"]' # 覆盖端点
export TAURI_UPDATER_PUBKEY='<公钥 base64>' # 覆盖签名公钥(缺省用 tauri.conf.json)
export TAURI_SIGNING_PRIVATE_KEY="$(cat mykey/tauri-signer.key)" # 更新签名私钥(脚本会自动加载,仅手动注入时才需)
export TAURI_SIGNING_PRIVATE_KEY_PASSWORD="" # 生成密钥时未设密码则为空
端点既接受 JSON 数组也接受逗号/换行分隔;JSON 数组会校验必须全部为字符串。 只要
TAURI_SIGNING_PRIVATE_KEY有值,sync_tauri_version.mjs就会开启createUpdaterArtifacts,tauri build才产出.sig;否则跳过。
更新签名密钥(务必妥善保管)
- 密钥对在项目
mykey/:私钥tauri-signer.key(权限 600,已 gitignore,严禁提交)、公钥tauri-signer.key.pub(已同步到tauri.conf.json的plugins.updater.pubkey与 server-core.env的DESKTOP_UPDATER_PUBKEY)。 .sig的签名 key id 必须与plugins.updater.pubkey一致(stage带--pubkey-config会自动校验),否则客户端验签失败、CSP 不走更新。- 私钥丢失即废:所有历史更新包都无法再验证。重生成并同步新公钥:
cd console && npx tauri signer generate -w ../mykey/tauri-signer.key --ci
# 把新公钥内容同步到 tauri.conf.json plugins.updater.pubkey 与 server-core .env DESKTOP_UPDATER_PUBKEY
发布 SOP(完整版,含增量更新产物)
# 1) 设置版本号(唯一命令:写 __version__.py + 同步 Tauri semver)
./scripts/version-bump.sh 0.0.1b1
# 2) 分别构建两平台(脚本自动从 mykey/tauri-signer.key 加载私钥,产出 .sig 与更新产物)
./scripts/pack-tauri/build_macos_pyinstaller.sh # 内部已 stage macOS 更新包
pwsh -File scripts/pack-tauri/build_win_pyinstaller.ps1
# 3) 若某平台未自动 stage(或需补跑),手动执行 stage(见上)
# 4) 汇总生成统一 latest.json
python3 scripts/pack-tauri/generate_update_manifest.py manifest \
--version 0.0.1b1 \
--base-url "https://opc.pinesound.cn/desktop-updates/files" \
--metadata dist/tauri-darwin-aarch64-updater.json dist/tauri-windows-x86_64-updater.json \
--output dist/latest.json
# 5) 把 latest.json + 各平台更新包(.app.tar.gz/-setup.exe) + 对应 .sig 上传到更新源
# (自建源 os 托管目录 /desktop-updates/files/)
# 确认 latest.json 里 url/signature 与上传文件位置一致后,客户端即可自动更新
桌面端更新源在
console/src-tauri/tauri.conf.json的plugins.updater.endpoints;老版本客户端仍指向旧源,需用新配置构建并发布一个版本才能完成源切换。
遗留的 conda-pack 打包脚本(
scripts/pack/)已废弃,仅供回滚,见scripts/pack/README.md。
网站
bash scripts/website_build.sh # 输出 website/dist/
Docker 部署
构建镜像
deploy/Dockerfile 是多阶段构建:Stage 1 自动构建前端 Console,Stage 2 组装 Python 运行时(含 Chromium 与 Playwright 配置),无需在宿主机预装前端依赖。
# 一键脚本(推荐)
bash scripts/docker_build.sh pineagents:latest
# 等价原始命令
docker build -f deploy/Dockerfile -t pineagents:latest .
默认排除
imessage(macOS 专用)频道。可用环境变量覆盖:QWENPAW_DISABLED_CHANNELS=imessage,voice(排除)或QWENPAW_ENABLED_CHANNELS=discord,telegram(白名单)。
运行
# docker compose(推荐,端口 8088)
docker compose up -d # 访问 http://127.0.0.1:8088/
# 或原始 docker run(挂载三个持久化卷)
docker run -d --name pineagents \
-p 127.0.0.1:8088:8088 \
-v pineagents-data:/app/working \
-v pineagents-secrets:/app/working.secret \
-v pineagents-backups:/app/working.backups \
pineagents:latest
容器启动时若工作区缺少 config.json 会自动执行 pineagents init --defaults。
自定义端口与启用认证
docker run -d --name pineagents \
-p 127.0.0.1:3000:3000 \
-e QWENPAW_PORT=3000 \
-e QWENPAW_AUTH_ENABLED=true \
-e QWENPAW_AUTH_USERNAME=admin \
-e QWENPAW_AUTH_PASSWORD=changeme \
pineagents:latest
⚠️ 认证变量为
QWENPAW_AUTH_ENABLED/QWENPAW_AUTH_USERNAME/QWENPAW_AUTH_PASSWORD(旧名COPAW_*兼容)。注意docker-compose.yml注释中的PINEAGENTS_AUTH_*并非有效变量,属待修正的历史注释。 不启用认证时,容器会打印安全提示:请确保服务仅暴露于可信网络,或对不可信访问者开启认证。
测试
make test # 全部测试
make test-unit # 单元测试
make test-contract # 契约测试
make test-integration # 集成测试
make coverage-full # 覆盖率(含 HTML 报告)
make quick # 快速反馈(单测,失败即停)
或用测试入口脚本:
python scripts/run_tests.py # 全部测试
python scripts/run_tests.py -u # 单元测试
python scripts/run_tests.py -i # 集成测试
python scripts/run_tests.py -a -c # 全部 + 覆盖率
python scripts/run_tests.py -p # 并行(需 pytest-xdist)
python scripts/run_tests.py -h # 帮助
二次开发指引
本项目基于 QwenPaw 二次开发,核心约定:
- 改品牌:改后端
src/pineagents/branding.py+ 前端console/src/constants/branding.ts,不要改散落字面量。 - 改逻辑:智能体决策见
agents/react_agent.py,编排见runtime/,治理见governance/。 - 必读:
docs/secondary-dev/(品牌盘点与抽离方案)、NOTICE(修改登记)、SECURITY.md。 - 铁律:任何基于上游 QwenPaw 的改动,必须登记到
NOTICE后再提交。
上游同步:从远端 github 拉取 QwenPaw,改动推送至远端 infoepoch_lan。
许可证
- PineAgents:闭源商业软件,见
LICENSE(模板,上线前请法务审核)。 - 上游 QwenPaw:Apache License 2.0,见
LICENSE_QwenPaw。 - 修改说明见
NOTICE。
Copyright © 2026 PineAgents 保留所有权利。