Files

152 lines
6.6 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PineAgents 品牌抽离方案(Branding Abstraction
> 目标:把散落在 271 个 Python + 147 个前端文件里的品牌字符串,**收敛到单一配置层**。做到「改品牌只改一处」,并最大限度降低与上游 QwenPaw rebase 时的冲突。
> 现状:`constant.py` 里品牌已部分集中(`PROJECT_NAME`、`WORKING_DIR`、env 前缀),但仍有大量硬编码散落在 cli / routers / providers / 前端。
---
## 1. 设计原则
1. **单一事实源(Single Source of Truth**:所有持久化标识、前缀、展示名集中在一个 `Branding` 配置对象。
2. **三前缀回退**:环境变量支持 `PINEAGENTS_`(主)→ `QWENPAW_``COPAW_`(遗留)逐级回退,保证旧部署/旧环境变量不被破坏。
3. **持久化标识与展示名分离**:数据目录、keyring、消息 tag 等持久化标识可独立于展示名配置(避免改展示名影响旧数据)。
4. **不破坏上游合并路径**:新增独立模块,尽量少改 `constant.py` 既有语义;上游改动通过「读 Branding 而非字面量」自然落地。
---
## 2. 目标结构
### 2.1 新增模块 `src/pineagents/branding.py`
```python
# -*- coding: utf-8 -*-
"""PineAgents 品牌与命名配置 —— 单一事实源。
改造/二次开发时:改这里,不要改散落在各文件的字面量。
"""
from __future__ import annotations
from dataclasses import dataclass, field
from pathlib import Path
@dataclass(frozen=True)
class Branding:
# ---- 展示名(可安全全量改名)----
project_name: str = "PineAgents" # 产品名(原 QwenPaw
cli_name: str = "pineagents" # CLI 命令(原 qwenpaw/copaw
package_name: str = "pineagents" # Python 包名
env_prefix: str = "PINEAGENTS_" # 环境变量主前缀
version: str = "2.1.0b1"
# ---- 持久化标识(改名需迁移,见第 3 节)----
working_dir_name: str = ".qwenpaw" # 数据目录(保守:沿用)
keyring_account: str = "qwenpaw" # 钥匙串主密钥账号(沿用)
message_tag_key: str = "qwenpaw_tag" # 消息元数据 tag(沿用)
message_client_id_key: str = "qwenpaw_client_message_id"
builtin_qa_agent_id: str = "QwenPaw_QA_Agent_0.2"
# ---- 兼容前缀(逐级回退)----
legacy_prefixes: tuple[str, ...] = ("QWENPAW_", "COPAW_")
# ---- 依赖主前缀派生出的 env key 前缀列表(供测试/检查用)----
env_keys: tuple[str, ...] = (
"WORKING_DIR", "SECRET_DIR", "KEYRING_ACCOUNT", "LOG_LEVEL",
)
BRAND = Branding()
```
### 2.2 改造 `constant.py` 的 `_get_env`(三前缀回退)
把现有的 `QWENPAW_``COPAW_` 两级回退,扩展为 `PINEAGENTS_``QWENPAW_``COPAW_` 三级:
```python
def _get_env(key, default=""):
if key in os.environ:
return os.environ[key]
if key.startswith(BRAND.env_prefix):
for legacy in BRAND.legacy_prefixes:
legacy_key = legacy + key[len(BRAND.env_prefix):]
if legacy_key in os.environ:
return os.environ[legacy_key]
return default
```
### 2.3 收敛关键常量(`constant.py` 改为读 `BRAND`
```python
PROJECT_NAME = BRAND.project_name
QWENPAW_MESSAGE_TAG_KEY = BRAND.message_tag_key # 保留别名避免大改
QWENPAW_CLIENT_MESSAGE_ID_KEY = BRAND.message_client_id_key
BUILTIN_QA_AGENT_ID = BRAND.builtin_qa_agent_id
```
> 说明:`QWENPAW_MESSAGE_TAG_KEY` 等**别名保留原名**,只是值改由 `BRAND` 提供。这样内部引用无需改动,持久化值也不变(沿用 `qwenpaw_tag`),仅品牌展示名切换为 PineAgents。
---
## 3. 持久化标识处理矩阵
| 标识 | 决策 | 理由 |
|------|------|------|
| 数据目录 `~/.qwenpaw` | **沿用**(不改) | 避免旧数据不可见;如需改,配 `working_dir_name` 并加迁移 |
| 钥匙串账号 | **沿用** | 改则主密钥失配、无法解密旧密钥 |
| 消息 tag | **沿用** | 旧消息上的 tag 需继续可读 |
| 内置 Agent ID | **沿用** | 旧会话归属需对上 |
| env 前缀 | **新增 `PINEAGENTS_` 为主** | 新部署用新前缀;旧变量靠回退仍生效 |
**结论**PineAgents 默认「展示名全改、持久化标识沿用」,实现零迁移平滑改造。
---
## 4. 前端抽离(`console/`
前端同样收敛到一个品牌常量文件,例如 `console/src/constants/branding.ts`
```ts
export const BRAND = {
name: "PineAgents",
cli: "pineagents",
docBase: "https://<你的文档域名>/",
// ...
} as const;
```
- 所有组件(`layouts/``locales/``pages/**`)改读 `BRAND.name`,替换字面量 `"QwenPaw"` / `"qwenpaw"`
- `console/index.html``<title>` 与 favicon、`console/package.json` 的 name 直接改为 PineAgents。
---
## 5. 打包与部署入口
- `pyproject.toml``name="pineagents"``[project.scripts] pineagents = "pineagents.cli.main:cli"`(保留 `qwenpaw`/`copaw` 作为兼容别名可选),coverage source、package-data 同步。
- `docker-compose.yml` / `deploy/` / `scripts/`:镜像名、容器卷名、启动命令改 `pineagents`
- 包目录改名 `src/pineagents``src/pineagents`(或保留目录名、仅内部标识改名,视同步策略二选一,见第 6 节)。
---
## 6. 同步策略:目录改名 or 不改?
两条路,按上游同步频率取舍:
| 方案 | 做法 | 优点 | 缺点 |
|------|------|------|------|
| **A. 目录改名** `src/pineagents/` | 一劳永逸品牌干净 | 产物、import 全干净 | 每次 rebase 上游 271 个文件路径全变,冲突巨大 |
| **B. 目录沿用** `src/pineagents/` | 包名/import 保留 qwenpaw,仅展示层改 PineAgents | rebase 冲突最小 | import 里仍带 qwenpaw 字样 |
**建议**PineAgents 走「Fork + 上游同步」,选 **方案 B**(目录沿用 `src/pineagents/`、import 保留),只把**展示层 + 配置 + 打包入口**切到 PineAgents。这样 rebase 上游时只处理少量展示层文件。若将来决定彻底冻结上游,再一次性迁移到 `src/pineagents/`
---
## 7. 分步落地
1. 新增 `src/pineagents/branding.py``Branding` 配置对象)。
2. `constant.py``PROJECT_NAME` 等改读 `BRAND``_get_env` 改三前缀回退。
3. 前端新增 `console/src/constants/branding.ts`,替换关键展示名。
4. `pyproject.toml` / `docker-compose.yml` / `deploy/`:打包与部署入口切 `pineagents`
5. 替换 `console/public` 品牌素材(logo/favicon/启动图)。
6. 关闭/替换遥测上报。
7. 运行 `tests/` 与 e2e 回归,确认持久化标识未破坏。