6.6 KiB
6.6 KiB
PineAgents 品牌抽离方案(Branding Abstraction)
目标:把散落在 271 个 Python + 147 个前端文件里的品牌字符串,收敛到单一配置层。做到「改品牌只改一处」,并最大限度降低与上游 QwenPaw rebase 时的冲突。 现状:
constant.py里品牌已部分集中(PROJECT_NAME、WORKING_DIR、env 前缀),但仍有大量硬编码散落在 cli / routers / providers / 前端。
1. 设计原则
- 单一事实源(Single Source of Truth):所有持久化标识、前缀、展示名集中在一个
Branding配置对象。 - 三前缀回退:环境变量支持
PINEAGENTS_(主)→QWENPAW_→COPAW_(遗留)逐级回退,保证旧部署/旧环境变量不被破坏。 - 持久化标识与展示名分离:数据目录、keyring、消息 tag 等持久化标识可独立于展示名配置(避免改展示名影响旧数据)。
- 不破坏上游合并路径:新增独立模块,尽量少改
constant.py既有语义;上游改动通过「读 Branding 而非字面量」自然落地。
2. 目标结构
2.1 新增模块 src/pineagents/branding.py
# -*- 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_ 三级:
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)
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:
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. 分步落地
- 新增
src/pineagents/branding.py(Branding配置对象)。 constant.py:PROJECT_NAME等改读BRAND;_get_env改三前缀回退。- 前端新增
console/src/constants/branding.ts,替换关键展示名。 pyproject.toml/docker-compose.yml/deploy/:打包与部署入口切pineagents。- 替换
console/public品牌素材(logo/favicon/启动图)。 - 关闭/替换遥测上报。
- 运行
tests/与 e2e 回归,确认持久化标识未破坏。