# 架构与技术结论

> 面向想读源码 / 二次开发的贡献者。只列结论，不展开推导。

## 分层设计：core 零 pi 依赖

```
src/core/                    # 零 pi 依赖的纯业务（可被 dsh 复用）
├─ config.ts                 # key 池/冷却/封禁/会话粘合配置
├─ keyRouter.ts              # 会话粘合 + 失败轮换 + 配额状态机
├─ usage.ts                  # usage 接口解析 + 展示
├─ pricing.ts                # 价格表 + 用量/费用估算
├─ usageStore.ts             # 用量记录落盘 + 汇总
├─ developerCompat.ts        # developer→system 兼容过滤
├─ webui.ts / portfile.ts    # Web 配额面板 + 端口管理
└─ index.ts                  # 聚合导出
pi/index.ts                  # pi 薄封装：事件挂接 + /ocgo 命令 + Web 面板自起
test/*.test.ts               # 单元测试
```

- **core 层零依赖 pi**；pi 层只做事件挂接 + 配置读取 + 命令注册 + Web 面板托管。
- 将来 dsh 只需重新封装一层薄壳即可复用 core，核心逻辑不改。

## pi 事件钩子

- `before_provider_request` — 改请求 payload（能力 A 角色过滤），可拿 `ctx.model.provider` 判断是否为 OpenCode。
- `after_provider_response` — 拿 `event.status`/headers 探测 429 / retry-after（能力 B 触发轮换）。
- `session_start` / `session_shutdown` — 会话生命周期，用于 Session 粘合。
- `registerCommand` — 注册 `/ocgo ...` 命令。
- `ctx.ui.setWidget()` / `ctx.ui.setStatus()` — TUI 配额进度条 / footer 摘要（仅 TUI）。

## 实现要点

- **只透传、不乱改**：能力 B 只换 `Authorization` 头不动 body；能力 A 只在确有 `developer` 时才动。
- **`x-session-affinity`**：pi 部分 provider 会自动设该头做前缀缓存；与「同会话同 key」相辅相成，换 key 断亲和性才丢缓存。
- **错误恢复幂等**：response-hook 轮换 与 message-end 错误去重，避免一次失败切两次 key。
- **配额来源**：Go usage 探测走 `https://opencode.ai/zen/go/v1/usage`，超时（10s）降级为瞬时限流处理。
- **安全**：key 明文存 `~/.pi/agent/opencode-keys.json`，需 `0600`；命令输出不打印明文 key。
- **Web 面板自起**：扩展启动时 `ensureWebServer()` 静默探测端口并不阻塞拉起；`OCGO_NO_WEB=1` 禁用（测试/端口占用场景）。
- **懒探测**：usage 不做主动轮询，只在 `message_end` 后对照会话 key 做 30s 节流查询；429 时也查以区分长封禁/短冷却。

## 与 pi-deepseek-optimized 的兼容性

用户可能同时装 `pi-deepseek-optimized`（入口 `extensions/harness.ts`，5 模块：Cache prefix stability / Storm-breaker / Hashline editing / Plan mode / Rewind）。

**结论：无冲突，可放心共用。**

依据：
1. 两者 `before_provider_request` 都是链式、按加载顺序、返回 `undefined` 保持原样。harness 原地 `tools.sort()` 不 return；能力 A 保留 `payload.tools` → 各改各的字段，可叠加。
2. `context`/`before_agent_start` 比 provider 请求更早，不碰 `role`，与能力 A 无交集。
3. 方向互补：harness 稳定缓存前缀，本插件让前缀跨轮命中，目标一致。
4. 触发隔离：harness 仅匹配 `deepseek` 模型；本插件仅在 `opencode-go`/`oc-sdk-go`/`oc-sdk-zen`/`opencode` provider 生效。

> 注意：两者都依赖 `before_provider_request` 链式语义；若 pi 未来改变返回语义或任一方开始 return 完整对象，需重新验证。

## 为什么单独做（而非复用参考包）

| 参考包 | 局限 |
|--------|------|
| `pi-opencode-bridge` | 源码没真做 developer→system 转换；不支持多 key；不能自定义 baseUrl |
| `@lnilluv/pi-opencode-go-rotation` | 不做角色兼容；**不做 Session 粘合**（换 key 丢前缀缓存） |

本扩展补上它们都没有的**按 Session ID 粘合 key**，避免换 key 丢上下文缓存。
