- commit
- 9674c30
- parent
- 404031f
- author
- im_wower
- date
- 2026-04-02 16:13:24 +0800 CST
plans: BAA Safari 插件需求 — macOS 原生浏览器 + AppleScript 深度集成
1 files changed,
+162,
-0
Raw patch view.
1diff --git a/plans/BAA_SAFARI_PLUGIN_REQUIREMENTS.md b/plans/BAA_SAFARI_PLUGIN_REQUIREMENTS.md
2new file mode 100644
3index 0000000000000000000000000000000000000000..bebe7400f1645e715f93b08993c7b77778f61fa6
4--- /dev/null
5+++ b/plans/BAA_SAFARI_PLUGIN_REQUIREMENTS.md
6@@ -0,0 +1,162 @@
7+# BAA Safari 插件需求
8+
9+> 日期: 2026-04-02
10+> 状态: 需求设计
11+> 来源: 葫芦爷 × Claude 讨论
12+
13+## 为什么做 Safari 插件
14+
15+### 当前 Firefox 插件的问题
16+
17+1. **辅助功能交互困难** — Firefox 的 AX 树深层嵌套,tab 切换、页面元素定位都不如 Safari 流畅。插件的 `about:debugging` 重载流程复杂,远程自动化验证几乎不可行。
18+2. **macOS 上的二等公民** — mini 上跑 Firefox 是为了插件,而非用户选择。Safari 是 macOS 原生浏览器,系统集成度最高。
19+3. **AppleScript 控制能力差距大** — Safari 有完整的 AppleScript 字典(`do JavaScript`、tab 管理、URL 导航),Firefox 几乎没有。conductor 通过 a11y 控制 Safari 远比控制 Firefox 可靠。
20+4. **开发调试效率** — Safari Web Inspector 直接挂在系统里,不需要额外工具。
21+
22+### Safari 插件带来的优势
23+
24+1. **conductor 全链路自动化** — 从发消息到验证 final-message,全部可通过 AppleScript + conductor 完成,不再依赖人工切屏
25+2. **原生 macOS 集成** — Keychain、通知中心、系统偏好设置直接可用
26+3. **A11Y 控制更稳** — Safari 的 AX 树结构规范,conductor 可以精确定位页面元素
27+4. **AppleScript `do JavaScript`** — 可以直接在页面上下文执行 JS,不需要复杂的 content-script 注入链路
28+
29+## 与 Firefox 插件的关系
30+
31+Safari 插件不替代 Firefox 插件,而是**并行共存**:
32+
33+- Firefox 插件继续维护,作为跨平台方案和现有投入的延续
34+- Safari 插件作为 macOS 主力方案,优先用于 mini 上的自动化
35+- 两者共享同一个 conductor 后端,共用 WS 协议和 API 接口
36+- 核心逻辑(`final-message.js`、指令解析、去重)尽量复用
37+
38+## 当前范围
39+
40+### 首版必须做
41+
42+1. **Safari Web Extension 基础壳** — manifest.json + background script + content script
43+2. **WS 连接 conductor** — 复用现有 WS 协议(`firefox-ws.ts` 对应的握手和消息格式)
44+3. **三家 AI 页面拦截** — ChatGPT / Claude / Gemini 的 SSE final-message 拦截(复用 `final-message.js` 核心逻辑)
45+4. **登录态凭证采集** — 复用现有 `page-interceptor.js` 的 request hook 逻辑
46+5. **proxy_delivery 支持** — 在页面上下文代理执行 HTTP 请求(复用现有 delivery 协议)
47+
48+### 首版不做
49+
50+- 不做 Safari App Extension(用 Web Extension 即可)
51+- 不做 App Store 分发(开发者模式加载)
52+- 不做 iOS/iPadOS 适配
53+- 不做 UI 面板(首版无 popup/options page,靠 conductor Web UI)
54+- 不做独立的 send template 缓存机制(首版直接复用 Firefox 插件的逻辑移植)
55+
56+## 技术方案
57+
58+### Safari Web Extension 结构
59+
60+```
61+plugins/baa-safari/
62+ manifest.json # WebExtension manifest v2/v3
63+ background.js # Service Worker / background page
64+ content-script.js # 注入到 AI 页面
65+ page-interceptor.js # 复用/移植自 Firefox 版
66+ final-message.js # 直接复用(纯 JS,无浏览器 API 依赖)
67+ delivery-adapters.js # 复用/移植自 Firefox 版
68+ controller.js # 移植自 Firefox 版,适配 Safari API 差异
69+ Info.plist # Safari 扩展描述
70+ baa-safari-host/ # Xcode 宿主 App 壳(最小化)
71+ *.xcodeproj
72+```
73+
74+### API 差异处理
75+
76+| 能力 | Firefox | Safari | 处理方式 |
77+|------|---------|--------|---------|
78+| background script | persistent background page | 可用 persistent background page(非 iOS) | 直接复用 |
79+| WebRequest API | `browser.webRequest` | `browser.webRequest`(需声明权限) | 直接复用 |
80+| content script 注入 | manifest 声明 | manifest 声明 | 直接复用 |
81+| 存储 | `browser.storage.local` | `browser.storage.local` | 直接复用 |
82+| native messaging | 不用 | 不用(走 WS) | 不涉及 |
83+| `declarativeNetRequest` | 不用 | 可选 | 首版不用 |
84+
85+Safari Web Extension API 与 Firefox WebExtension API 高度兼容(都基于 WebExtension 标准),主要差异在:
86+- `browser.*` vs `chrome.*` 命名空间(Safari 两个都支持)
87+- Service Worker 生命周期(macOS 上可用 persistent background page,规避 SW 限制)
88+- 权限模型(Safari 要求用户显式授权每个域名)
89+
90+### conductor 侧改动
91+
92+最小改动:
93+- `firefox-ws.ts` 改名或抽象为 `browser-ws.ts`,支持多个插件客户端同时连接
94+- `client_id` 前缀区分来源:`firefox-*` vs `safari-*`
95+- 其余协议、路由、ingest、delivery 链路不变
96+
97+### Xcode 宿主 App
98+
99+Safari Web Extension 需要一个 macOS App 作为宿主。首版做最小壳:
100+- 单窗口 App,显示"请在 Safari 偏好设置中启用 BAA 扩展"
101+- 不做任何业务逻辑
102+- 用 SwiftUI 或 storyboard 最小实现
103+- 可以用 Xcode 模板一键生成
104+
105+### 与 AppleScript 的配合
106+
107+Safari 插件加载后,conductor 可以通过 AppleScript 做到:
108+
109+```applescript
110+-- 切换到 ChatGPT 标签页
111+tell application "Safari"
112+ set current tab of window 1 to tab 3 of window 1
113+end tell
114+
115+-- 在页面上执行 JS
116+tell application "Safari"
117+ do JavaScript "document.querySelector('textarea').value = 'hello'" in current tab of window 1
118+end tell
119+
120+-- 读取页面内容
121+tell application "Safari"
122+ set pageTitle to do JavaScript "document.title" in current tab of window 1
123+end tell
124+```
125+
126+这意味着 conductor 可以:
127+1. 直接通过 AppleScript 控制 Safari 页面(不依赖 AX 树遍历)
128+2. 通过 `do JavaScript` 在页面上下文执行任意操作
129+3. 结合 WS 插件通道和 AppleScript 直控,形成双通道控制
130+
131+## 实现阶段
132+
133+### Phase 1: 最小可用(首版)
134+
135+- Xcode 宿主 App 壳
136+- manifest.json + background + content-script 基础结构
137+- WS 连接 conductor
138+- ChatGPT final-message 拦截(移植 `final-message.js`)
139+- 基础 proxy_delivery 支持
140+- 在 mini 上验证闭环
141+
142+### Phase 2: 三家 AI 全覆盖
143+
144+- Claude / Gemini final-message 拦截
145+- 登录态凭证采集
146+- send template 缓存
147+- conductor 侧多客户端并存
148+
149+### Phase 3: AppleScript 深度集成
150+
151+- conductor 新增 Safari 专属控制指令(`@conductor::safari::*`)
152+- `do JavaScript` 通道作为 proxy_delivery 的替代路径
153+- 自动化验证流程(发消息 → 等回复 → 检查日志)全部可通过 conductor 完成
154+
155+## 验收标准(Phase 1)
156+
157+1. Safari 中能看到 BAA 扩展图标
158+2. 打开 ChatGPT 页面后,conductor 收到 WS 连接
159+3. 在 ChatGPT 中发消息并收到回复后,conductor 日志中出现 `browser.final_message` 记录
160+4. conductor 能通过 Safari 插件执行 `proxy_delivery`
161+5. 以上全部可在 mini 上通过 conductor + AppleScript 远程验证
162+
163+## 工程约束
164+
165+- `final-message.js` 必须保持纯 JS,不引入浏览器特定 API,确保 Firefox/Safari 共享
166+- WS 协议不为 Safari 做特殊分支,统一一套协议
167+- Xcode 项目不纳入 pnpm monorepo 构建链,单独管理
168+- 首版不追求 App Store 上架,开发者模式加载即可