123ba0d0fa
- auth/jwt/header 认证流程更新,会话与令牌处理增强 - 通信(ChatWindow/ConversationList/Network)更新 - tauri backend.rs/remote.rs、tauri.conf.json 更新 - pineagents app 路由(agent_gate/opc)与配置更新
666 lines
26 KiB
Markdown
666 lines
26 KiB
Markdown
<p align="center">
|
||
<img src="./assets/readme/hero.svg" width="100%"
|
||
alt="PineAgents — 本地或云端部署的智能体工作台:多频道对话、Skills/插件扩展、定时任务与代码模式">
|
||
</p>
|
||
|
||
<p align="center">
|
||
<b>闭源商业软件</b> · 自有许可见 <a href="LICENSE">LICENSE</a> · 上游 QwenPaw 许可见 <a href="LICENSE_QwenPaw">LICENSE_QwenPaw</a> · 修改记录见 <a href="NOTICE">NOTICE</a>
|
||
</p>
|
||
|
||
---
|
||
|
||
## 目录
|
||
|
||
- [项目简介](#项目简介)
|
||
- [目录结构](#目录结构)
|
||
- [架构与流程](#架构与流程)
|
||
- [环境要求](#环境要求)
|
||
- [安装(从源码)](#安装从源码)
|
||
- [启动](#启动)
|
||
- [版本号管理(唯一来源)](#版本号管理唯一来源)
|
||
- [构建与打包](#构建与打包)
|
||
- [版本号设置与同步](#版本号设置与同步)
|
||
- [macOS / Windows 一键构建、产物清单](#macos--windows-一键构建产物清单)
|
||
- [手动分步构建](#手动分步构建)
|
||
- [增量更新(完整命令)](#增量更新incremental-update本地生成完整产物)
|
||
- [Docker 部署](#docker-部署)
|
||
- [测试](#测试)
|
||
- [二次开发指引](#二次开发指引)
|
||
- [许可证](#许可证)
|
||
|
||
---
|
||
|
||
## 项目简介
|
||
|
||
PineAgents 是一个可自主运行的**智能体操作系统(Agent OS)**:它通过多频道(钉钉、飞书、微信、QQ、Discord、Telegram 等)与用户对话,用 Skills 与插件扩展能力,支持定时任务(Cron)、多智能体编排、代码模式与三层记忆。
|
||
|
||
本项目是开源项目 [QwenPaw](https://github.com/agentscope-ai/QwenPaw)(Apache 2.0)的**闭源商业衍生**,走「Fork + 上游同步」开发路线。所有基于上游的修改均登记在 [`NOTICE`](NOTICE)。
|
||
|
||
---
|
||
|
||
## 目录结构
|
||
|
||
### 顶层
|
||
|
||
| 路径 | 作用 |
|
||
|------|------|
|
||
| `VERSION` | **版本号唯一来源**(Single Source of Truth),修改版本号只需改这一个文件 |
|
||
| `src/pineagents/` | **Python 后端运行时**(全部核心逻辑) |
|
||
| `console/` | **前端 Web 界面**(React + Vite),含 Tauri 桌面壳(`console/src-tauri/`) |
|
||
| `plugins/` | 独立插件包(channel / tool / app) |
|
||
| `deploy/` | Docker 部署(`Dockerfile`、`entrypoint.sh`、`config/`) |
|
||
| `scripts/` | 构建 / 安装 / 打包脚本(含 `sync_version.py` 版本同步) |
|
||
| `assets/readme/` | README 静态资源(本项目 SVG 图) |
|
||
| `tests/` | 测试(unit / contract / integration / e2e) |
|
||
| `docs/secondary-dev/` | **二次开发文档**(品牌盘点、抽离方案) |
|
||
| `old_docs/` | **原上游文档归档**(QwenPaw README/CONTRIBUTING/RELEASING 等) |
|
||
| `mykey/` | Tauri 更新签名密钥对(私钥已 gitignore,严禁提交) |
|
||
| `LICENSE` | PineAgents 闭源商业许可 |
|
||
| `LICENSE_QwenPaw` | 上游 QwenPaw(Apache 2.0)许可 |
|
||
| `NOTICE` | 所有基于上游的修改说明(必读) |
|
||
| `SECURITY.md` | 安全策略 |
|
||
|
||
### 后端核心(`src/pineagents/`)
|
||
|
||
| 模块 | 作用 |
|
||
|------|------|
|
||
| `__version__.py` | **版本号运行时获取**(从 `VERSION` 文件读取,支持开发/打包环境,自动迁移配置文件版本) |
|
||
| `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)平台 |
|
||
| `tauri/` | Tauri 桌面端后端入口(sidecar 进程) |
|
||
|
||
### 前端(`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 桌面端 API 封装(更新、后端运行时等) |
|
||
| `vite.config.ts` | Vite 构建配置(从 `VERSION` 文件读取版本号并注入 `window.__APP_VERSION__`) |
|
||
| `src-tauri/` | Tauri 桌面壳(Rust) |
|
||
|
||
---
|
||
|
||
## 架构与流程
|
||
|
||
一次对话的主链路:**用户入口 → FastAPI 服务层 → 运行时编排 → 智能体决策循环 → 输出**,并由治理、沙箱、记忆、用量四类横向能力贯穿。
|
||
|
||
<p align="center">
|
||
<img src="./assets/readme/architecture.svg" width="100%"
|
||
alt="PineAgents 架构:多频道入口 → FastAPI → 运行时编排 → 智能体决策循环 → 输出,横向贯穿治理/沙箱/记忆/用量">
|
||
</p>
|
||
|
||
---
|
||
|
||
## 环境要求
|
||
|
||
| 组件 | 最低版本 | 说明 |
|
||
|------|---------|------|
|
||
| Python | 3.10+ | 推荐 3.11(`.python-version` 固定) |
|
||
| Node.js | 18+ | 推荐 20 LTS |
|
||
| npm / yarn | 最新 | 前端包管理(项目用 yarn,`.yarnrc.yml`) |
|
||
| Rust | 1.77+ | Tauri 桌面壳编译(`rust-toolchain.toml` 固定) |
|
||
| macOS | 12+ | 桌面端构建(Xcode Command Line Tools) |
|
||
| Windows | 10+ | 桌面端构建(Visual Studio Build Tools) |
|
||
| Linux | Ubuntu 20.04+ / Debian 11+ | 服务器部署 |
|
||
|
||
---
|
||
|
||
## 安装(从源码)
|
||
|
||
### 1. 克隆仓库
|
||
|
||
```bash
|
||
git clone <repo-url> agent-desktop
|
||
cd agent-desktop
|
||
```
|
||
|
||
### 2. Python 后端依赖
|
||
|
||
```bash
|
||
# 使用 uv(推荐,更快)
|
||
uv venv
|
||
uv pip install -e ".[dev]"
|
||
|
||
# 或使用 pip
|
||
python -m venv .venv
|
||
source .venv/bin/activate # Windows: .venv\Scripts\activate
|
||
pip install -e ".[dev]"
|
||
```
|
||
|
||
### 3. 前端依赖
|
||
|
||
```bash
|
||
cd console
|
||
yarn install # 或 npm install
|
||
cd ..
|
||
```
|
||
|
||
### 4. 初始化配置
|
||
|
||
```bash
|
||
# 生成默认配置(~/.pineagents/config.json)
|
||
pineagents init --defaults
|
||
|
||
# 或手动复制模板
|
||
cp config.example.json ~/.pineagents/config.json
|
||
```
|
||
|
||
---
|
||
|
||
## 启动
|
||
|
||
### 开发模式(推荐)
|
||
|
||
```bash
|
||
# 方式一:Tauri 桌面端(前端 + 后端 sidecar 一起启动)
|
||
cd console
|
||
yarn tauri:dev # 或 npx tauri dev
|
||
|
||
# 方式二:仅后端 API 服务
|
||
pineagents serve --host 127.0.0.1 --port 8088
|
||
|
||
# 方式三:前端开发服务器(单独调试前端,后端需单独启动)
|
||
cd console
|
||
yarn dev # 访问 http://localhost:8093
|
||
```
|
||
|
||
### 生产模式
|
||
|
||
```bash
|
||
# 后端服务
|
||
pineagents serve --host 0.0.0.0 --port 8088
|
||
|
||
# 或使用 systemd / supervisor 托管
|
||
```
|
||
|
||
---
|
||
|
||
## 版本号管理(唯一来源)
|
||
|
||
### 核心原则
|
||
|
||
**版本号只有一个真实来源:项目根目录 `VERSION` 文件。**
|
||
|
||
所有端(Python 后端、前端、Tauri、Cargo)的版本号都从这个文件读取或同步,禁止在代码中写死版本号。
|
||
|
||
### VERSION 文件格式
|
||
|
||
```
|
||
0.0.1b3
|
||
```
|
||
|
||
- 支持 PEP 440 格式:`0.0.1b3`(beta)、`0.0.1a1`(alpha)、`0.0.1rc1`(RC)、`0.0.1`(正式版)
|
||
- Tauri 构建时自动转换为 semver 格式:`0.0.1b3` → `0.0.1-beta.3`
|
||
|
||
### 各端版本获取方式
|
||
|
||
| 端 | 获取方式 | 时机 |
|
||
|---|---|---|
|
||
| **Python 后端** | `__version__.py` 读取 `VERSION` 文件 | 运行时 |
|
||
| **前端** | `vite.config.ts` 读取 `VERSION`,注入 `window.__APP_VERSION__` | 构建时 |
|
||
| **Tauri** | `tauri.conf.json` version 字段(构建前自动同步) | 构建时 |
|
||
| **Cargo** | `Cargo.toml` version 字段(构建前自动同步) | 构建时 |
|
||
|
||
### 自动版本迁移
|
||
|
||
用户安装新版本后,首次启动应用时,后端会自动比较 `VERSION` 文件与用户配置文件(`~/.pineagents/config.json`)中的 `app_version`,若 `VERSION` 文件更新则自动写入配置文件——**无需用户手动删除配置**。
|
||
|
||
迁移逻辑在 `src/pineagents/__version__.py` 的 `ensure_config_version_updated()` 函数中实现,在后端启动入口(`tauri/entry.py` 和 `cli/app_cmd.py`)调用。
|
||
|
||
### 版本号获取优先级(Python 后端)
|
||
|
||
1. 环境变量 `PINEAGENTS_APP_VERSION`(部署覆盖用)
|
||
2. 项目根目录 `VERSION` 文件
|
||
3. PyInstaller 打包资源目录(`sys._MEIPASS/pineagents/VERSION`)
|
||
4. 用户配置文件 `~/.pineagents/config.json` 的 `app_version`
|
||
5. 兜底默认值 `0.0.0`(仅在以上全部失败时使用)
|
||
|
||
---
|
||
|
||
## 构建与打包
|
||
|
||
### 版本号设置与同步
|
||
|
||
#### 修改版本号(标准流程)
|
||
|
||
```bash
|
||
# 1. 修改唯一来源
|
||
echo "0.0.1b4" > VERSION
|
||
|
||
# 2. 同步到各端配置文件(tauri.conf.json / Cargo.toml / branding.py / config.py)
|
||
uv run scripts/sync_version.py
|
||
|
||
# 3. 验证一致性
|
||
uv run scripts/sync_version.py --check
|
||
```
|
||
|
||
#### 版本同步脚本说明
|
||
|
||
`scripts/sync_version.py` 从 `VERSION` 文件读取版本号,同步到以下文件:
|
||
|
||
| 目标文件 | 同步字段 | 格式 |
|
||
|---------|---------|------|
|
||
| `console/src-tauri/tauri.conf.json` | `version` | **semver**(自动转换,如 `0.0.1b3` → `0.0.1-beta.3`) |
|
||
| `console/src-tauri/Cargo.toml` | `version` | **semver**(自动转换,Cargo 要求 semver 格式) |
|
||
| `src/pineagents/branding.py` | `version` | PEP 440 |
|
||
| `src/pineagents/config/config.py` | `app_version` 默认值 | PEP 440 |
|
||
|
||
> **注意**:Tauri 和 Cargo 都要求 `version` 字段必须是 semver 格式,因此同步脚本会自动将 PEP 440 格式转换为 semver 格式。Python 后端相关文件(branding.py / config.py)保持 PEP 440 格式。
|
||
|
||
```bash
|
||
# 同步版本号
|
||
uv run scripts/sync_version.py
|
||
|
||
# 仅检查是否一致,不修改
|
||
uv run scripts/sync_version.py --check
|
||
```
|
||
|
||
> **注意**:`npx tauri dev` 和 `npx tauri build` 会在 `beforeDevCommand` / `beforeBuildCommand` 中自动运行版本同步,无需手动执行。
|
||
|
||
#### Tauri 版本覆盖配置
|
||
|
||
`scripts/pack-tauri/sync_tauri_version.mjs` 从 `VERSION` 文件读取版本号,转换为 semver 格式,生成 gitignored 的 `console/src-tauri/tauri.version.conf.json`:
|
||
|
||
```bash
|
||
node scripts/pack-tauri/sync_tauri_version.mjs
|
||
```
|
||
|
||
生成的 `tauri.version.conf.json` 包含:
|
||
- `version`:semver 格式版本号(如 `0.0.1-beta.3`)
|
||
- `plugins.updater`:更新配置(公钥、端点)
|
||
- `bundle.createUpdaterArtifacts`:是否生成更新签名(有私钥时自动开启)
|
||
|
||
> 不直接改 `tauri.conf.json` 的 version(避免 rebase 后产生陈旧的生成值);打包时以 `--config src-tauri/tauri.version.conf.json` 读取。
|
||
|
||
---
|
||
|
||
### macOS / Windows 一键构建、产物清单
|
||
|
||
#### 前置条件
|
||
|
||
1. 版本号已设置(`VERSION` 文件)
|
||
2. Tauri 更新签名私钥存在(`mykey/tauri-signer.key`,构建脚本自动加载)
|
||
3. 前端依赖已安装(`cd console && yarn install`)
|
||
4. Python 依赖已安装(`uv pip install -e ".[dev]"`)
|
||
|
||
#### 一键构建
|
||
|
||
```bash
|
||
# 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
|
||
```
|
||
|
||
一键脚本内部依次完成:
|
||
1. **版本同步**:`sync_version.py` + `sync_tauri_version.mjs`
|
||
2. **前端构建**:`npm run build:prod`
|
||
3. **PyInstaller 后端 sidecar**:打包 Python 后端为可执行文件
|
||
4. **Tauri 打包**:`tauri build --config src-tauri/tauri.version.conf.json`
|
||
5. **产物收集**:含 updater stage(`.app.tar.gz` + `.sig`)
|
||
|
||
#### macOS 签名
|
||
|
||
当前无 Apple Developer ID,一键脚本自动使用 ad-hoc 签名(`APPLE_SIGNING_IDENTITY="-"`),本地运行与分发可用但**不做公证**。
|
||
|
||
将来申请到 Developer ID 后:
|
||
|
||
```bash
|
||
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。
|
||
|
||
如需手动注入:
|
||
|
||
```bash
|
||
export TAURI_SIGNING_PRIVATE_KEY="$(cat mykey/tauri-signer.key)"
|
||
export TAURI_SIGNING_PRIVATE_KEY_PASSWORD="" # 生成密钥时未设密码则为空
|
||
```
|
||
|
||
**重新生成密钥对**(丢失私钥后所有旧更新包将无法验证):
|
||
|
||
```bash
|
||
cd console && npx tauri signer generate -w ../mykey/tauri-signer.key --ci
|
||
# 然后把新公钥(mykey/tauri-signer.key.pub 内容)同步到:
|
||
# 1. tauri.conf.json plugins.updater.pubkey
|
||
# 2. server-core .env DESKTOP_UPDATER_PUBKEY
|
||
```
|
||
|
||
---
|
||
|
||
### 手动分步构建
|
||
|
||
如需分步调试,可按以下步骤手动构建:
|
||
|
||
```bash
|
||
# 1) 版本同步
|
||
uv run scripts/sync_version.py
|
||
node scripts/pack-tauri/sync_tauri_version.mjs
|
||
|
||
# 2) 前端引导产物
|
||
cd console
|
||
npm run build:tauri-bootstrap # 产出 dist-tauri
|
||
|
||
# 3) 后端 sidecar(PyInstaller,产物在 dist/ 下)
|
||
cd ..
|
||
./scripts/pack-tauri/build_pyinstaller.sh # macOS / Linux
|
||
pwsh -File scripts/pack-tauri/build_pyinstaller.ps1 # Windows
|
||
|
||
# 4) 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`,但建议先精简后端依赖。
|
||
|
||
---
|
||
|
||
### 增量更新(Incremental Update,本地生成完整产物)
|
||
|
||
增量更新 = **Tauri updater 让已安装客户端静默拉到新版本**。
|
||
|
||
核心产物:
|
||
1. 按平台生成的更新包(`.app.tar.gz` / `*-setup.exe`)
|
||
2. 对应 `.sig` 签名
|
||
3. 统一的 `latest.json` 清单
|
||
|
||
`generate_update_manifest.py` 提供两个子命令完成本地编排。
|
||
|
||
#### 子命令 1:`stage` — 收集单个平台的更新产物
|
||
|
||
① 首先构建产物(构建脚本会自动从 `mykey/tauri-signer.key` 加载私钥):
|
||
|
||
```bash
|
||
# 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(或要在构建之外手动补跑),手动执行:
|
||
|
||
```bash
|
||
# 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.1b3-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.1b3-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`
|
||
|
||
```bash
|
||
python3 scripts/pack-tauri/generate_update_manifest.py manifest \
|
||
--version 0.0.1b3 \
|
||
--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'`:可选、可重复。当各平台产物在不同目录时按目标覆盖 `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` 内容结构:
|
||
|
||
```json
|
||
{
|
||
"version": "0.0.1-beta.3",
|
||
"notes": "发布说明:本次修复 xxx",
|
||
"pub_date": "2026-09-11T00:00:00Z",
|
||
"platforms": {
|
||
"darwin-aarch64": {
|
||
"url": "https://opc.pinesound.cn/desktop-updates/files/YunOPC-Hub-0.0.1b3-macOS.app.tar.gz",
|
||
"signature": "<minisign base64>"
|
||
},
|
||
"windows-x86_64": {
|
||
"url": "https://opc.pinesound.cn/desktop-updates/files/YunOPC-Hub-0.0.1b3-setup.exe",
|
||
"signature": "<minisign base64>"
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
#### 准备更新源 / 覆盖端点
|
||
|
||
`tauri.conf.json` 的缺省端点是 `https://opc.pinesound.cn/desktop-updates/latest.json`。构建/测试时可用环境变量覆盖(无需改配置):
|
||
|
||
```bash
|
||
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`;否则跳过。
|
||
|
||
---
|
||
|
||
### 更新发布(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(每次发版)
|
||
|
||
```bash
|
||
# 1) 设置版本号(修改唯一来源 + 同步各端)
|
||
echo "0.0.1b3" > VERSION
|
||
uv run scripts/sync_version.py
|
||
|
||
# 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.1b3 \
|
||
--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 与上传文件位置一致后,客户端即可自动更新
|
||
|
||
# 6) admin-portal「桌面端版本」→ 新建版本(版本号与第 1 步一致)
|
||
# 逐平台上传 安装包 + 同名 .sig → 设置发布说明/灰度比例/强制最低版本 → 发布
|
||
# 观察运行反馈后调至 100% 全量;异常时下架当前版本 / 重新发布上一版本回滚
|
||
```
|
||
|
||
> 桌面端更新源在 `console/src-tauri/tauri.conf.json` 的 `plugins.updater.endpoints`;**老版本客户端仍指向旧源,需用新配置构建并发布一个版本才能完成源切换**。
|
||
|
||
> 遗留的 conda-pack 打包脚本(`scripts/pack/`)已废弃,仅供回滚,见 [`scripts/pack/README.md`](scripts/pack/README.md)。
|
||
|
||
---
|
||
|
||
### 网站
|
||
|
||
```bash
|
||
bash scripts/website_build.sh # 输出 website/dist/
|
||
```
|
||
|
||
---
|
||
|
||
## Docker 部署
|
||
|
||
### 构建镜像
|
||
|
||
`deploy/Dockerfile` 是多阶段构建:Stage 1 自动构建前端 Console,Stage 2 组装 Python 运行时(含 Chromium 与 Playwright 配置),无需在宿主机预装前端依赖。
|
||
|
||
```bash
|
||
# 一键脚本(推荐)
|
||
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`(白名单)。
|
||
|
||
### 运行
|
||
|
||
```bash
|
||
# 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`。
|
||
|
||
### 自定义端口与启用认证
|
||
|
||
```bash
|
||
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_*` 并非有效变量,属待修正的历史注释。
|
||
> 不启用认证时,容器会打印安全提示:请确保服务仅暴露于可信网络,或对不可信访问者开启认证。
|
||
|
||
---
|
||
|
||
## 测试
|
||
|
||
```bash
|
||
make test # 全部测试
|
||
make test-unit # 单元测试
|
||
make test-contract # 契约测试
|
||
make test-integration # 集成测试
|
||
make coverage-full # 覆盖率(含 HTML 报告)
|
||
make quick # 快速反馈(单测,失败即停)
|
||
```
|
||
|
||
或用测试入口脚本:
|
||
|
||
```bash
|
||
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`,不要改散落字面量。
|
||
- **改版本号**:只改项目根目录 `VERSION` 文件,然后运行 `python scripts/sync_version.py` 同步各端,禁止在代码中写死版本号。
|
||
- **改逻辑**:智能体决策见 `agents/react_agent.py`,编排见 `runtime/`,治理见 `governance/`。
|
||
- **必读**:`docs/secondary-dev/`(品牌盘点与抽离方案)、`NOTICE`(修改登记)、`SECURITY.md`。
|
||
- **铁律**:任何基于上游 QwenPaw 的改动,**必须登记到 `NOTICE`** 后再提交。
|
||
|
||
上游同步:从远端 `github` 拉取 QwenPaw,改动推送至远端 `infoepoch_lan`。
|
||
|
||
---
|
||
|
||
## 许可证
|
||
|
||
- **PineAgents**:闭源商业软件,见 [`LICENSE`](LICENSE)(模板,上线前请法务审核)。
|
||
- **上游 QwenPaw**:Apache License 2.0,见 [`LICENSE_QwenPaw`](LICENSE_QwenPaw)。
|
||
- 修改说明见 [`NOTICE`](NOTICE)。
|
||
|
||
**Copyright © 2026 PineAgents 保留所有权利。**
|