# Spec: 插件增强与宿主深度适配 vNext ## Objective 为 `sub2api-cn-relay-manager` 的下一版本建立明确规格:在“不修改宿主后端源码、不直接写宿主数据库”的前提下,先完成 vNext.1 的能力真相与模型池基础,再把用户 key 自助、治理、SLO 拆到后续版本。 当前版本目标不是一次性把“宿主适配、池化、前端、自助 key、治理、SLO”全部做完,而是先把最小可发布范围说清楚,避免再次在 Kimi / 多供应商聚合 / 用户端能力上反复试错,或在未审核设计上直接进入实现。 ## 背景与问题陈述 当前已知问题来自真实线上使用: 1. 宿主协议转换能力不透明 - Kimi 接入时多次遇到协议转换偏差 - 需确认宿主是否只稳定支持 OpenAI Chat Completions,还是也支持 Responses / Anthropic / Gemini 兼容转换 2. 同模型多中转聚合能力不足 - 需要确认同一个逻辑模型(如 `gpt-5.4`、`kimi-k2.6`)是否能通过一个分组聚合多个供应商账号/线路,形成池化与故障切换 3. 用户前端能力弱 - 现有插件前端更偏管理与目录展示,用户要拿 key、看用法、理解分组限制仍较弱 - 希望尽量在插件/portal 前端内完成,不修改宿主后端代码 4. 用户自助取 key 能力不足 - 需要插件帮助生成 key,并把 key 的分组、模型、调用地址、状态、剩余额度/限制等信息交给最终用户 5. key / 账号治理能力不足 - 需要暂停 key、暂停账号、设置限额、设置默认分组或默认上限等能力 ## Host Hard Constraints 1. 不修改 sub2api 宿主后端源码 2. 不向宿主数据库做常态化直写作为产品能力 3. 只允许通过: - 宿主公开 HTTP API - 宿主管理 API / 管理页面可达契约 - 插件自身控制面、SQLite、portal 前端 4. 如发现宿主现有 API 无法支撑某项需求,必须: - 先记录为协议能力缺口 - 再决定是否由插件侧前端/控制面补偿 - 不能把“未来也许能改宿主”当作当前方案前提 ## Access Closure 对本版本所有功能,完成判定不能停在“资源创建成功”。至少要同时满足: 1. 管理面闭环:控制面/前端能看到配置结果 2. 用户面闭环:真实用户拿到 key 后,按文档发起一次最小 `POST /v1/chat/completions` 成功 3. 证据闭环:保留当前运行日志、API 回包、页面回读或脚本输出 ## Tech Stack - Go 1.22 控制面 - `internal/host/sub2api` 宿主适配器 - `internal/provision` 导入编排 - `internal/access` 访问闭环 - `deploy/tksea-portal/` 静态前端 - SQLite 本地状态存储 ## Commands 规格与后续实现的标准命令: - 文档真相核对: - `git status --short` - `git log --oneline -n 5` - Go 质量门禁: - `gofmt -l .` - `go vet ./...` - `go test -cover ./internal/...` - `go test ./tests/integration/... -count=1` - 前端门禁(若触及 portal): - `bash ./scripts/test/test_tksea_portal_assets.sh` - `bash ./scripts/test/verify_frontend_smoke.sh` - `bash ./scripts/acceptance/verify_provider_admin_actions.sh` - 宿主协议探测(需新增脚本后执行): - `bash ./scripts/acceptance/verify_host_protocol_matrix.sh` - `bash ./scripts/acceptance/verify_host_pool_routing.sh` - `bash ./scripts/acceptance/verify_user_key_self_service.sh` ## Project Structure 本次规划预计涉及的目录: - `docs/` — SPEC、TDD 计划、执行板 - `internal/host/sub2api/` — 宿主能力探测、协议/契约抽象 - `internal/provision/` — 导入、聚合池配置、账号/key 治理编排 - `internal/access/` — 用户访问闭环、key 可用性验证 - `internal/app/` — 控制面 API(若新增插件自有 API) - `deploy/tksea-portal/` — 用户 portal / admin 页面增强 - `tests/integration/` — 集成测试 - `scripts/acceptance/` — 宿主真实验收脚本 ## Code Style 遵循仓库既有约束: - Go 包按 `host/app/provision/access/store` 分层 - 错误统一 `fmt.Errorf("context: %w", err)` - 新能力优先通过 adapter/service/repo 组合扩展,不把宿主特例硬编码到 handler - 与宿主的“协议差异”必须放在 adapter / capability 层,不把协议分支散到 portal 页面 ## Testing Strategy 本版本的测试要分五层: 1. 单元测试 - 宿主 capability 解析 - 模型池聚合策略 - key/账号状态机(active / paused / quota exceeded) 2. 集成测试 - SQLite repo + app handler + provision service 3. 前端 smoke - key 发放页、key 状态页、限额/暂停页渲染与动作契约 4. 宿主真实验收 - 协议矩阵 - 池化分发 - 用户取 key 到调用成功 5. 生产准入验证 - 仅将“真实用户 chat=200”的模型/池写入默认链路 ## Boundaries Always: - 先写 spec,再写 TDD 计划,再开始实现 - 所有“宿主支持某协议/某模型/某聚合方式”的结论都必须来自真实验收 - 触及 portal 时必须跑前端门禁 - 每个能力都要有用户面闭环,不只看 admin 成功 Ask first: - 需要新增外部依赖 - 需要改变 key 发放产品策略(如收费、默认余额、默认分组) - 需要把某个模型池写入 OpenClaw 默认链路 Never: - 直接修改宿主后端源码 - 直接把宿主数据库写入当成长期产品方案 - 用 models=200 代替真实 chat=200 - 把“协议猜测”当成功能完成 ## Release Scope 当前发布范围以 `docs/2026-06-04-vnext-release-scope.md` 为真相源。 - vNext.1(当前要审核并准备实施的版本): - 宿主协议能力矩阵 - 模型池抽象 - pool 到现有 priority failover 运行面的映射 - 默认链路准入规则 - 幂等默认数据/初始化脚本前置 - vNext.2(本轮只设计,不进入当前实现): - KEY_SECURITY_MODEL - 用户 key 自助申请 - portal 首次调用闭环 - vNext.3(本轮只设计,不进入当前实现): - key/account 治理 - quota/limit - SLO/指标/告警 ## Scope ### A. 宿主协议能力矩阵 要回答: - 宿主当前稳定支持哪些协议入口/返回格式? - 哪些模型需要额外转换层? - Kimi 失败到底是上游问题、宿主协议问题,还是导入配置问题? 本版本输出: - 一份宿主协议能力矩阵文档 - 一组可重复执行的协议探测脚本 - 明确“受支持 / 需插件适配 / 当前不支持”的分类 ### B. 同模型多供应商池化分发 要回答: - 同一逻辑分组下是否能挂多个账号/多个 channel - 是否能对同一个公共模型名映射到多个供应商线路 - 现有宿主选路是否已有健康分发/优先级/冷却能力 本版本输出: - 池化模型设计:`logical model -> route set -> provider accounts` - 插件侧“模型池”抽象,而不是单 provider 绑定 - 验证脚本证明:同组多供应商可轮转 / 故障切换 / 人工禁用后可收敛 ### C. 前端承接用户能力 要回答: - 哪些宿主原生用户能力不足,需要 portal 前端承接 - 在不改宿主后端时,哪些能力可由插件自有 API + portal 完成 本版本输出: - 用户产品面信息架构: - 可申请的模型组 - 已有 key - key 状态/限额/暂停 - 推荐 base URL / model / curl 示例 - admin 侧操作页: - 发放 key - 暂停/恢复 key - 设置额度/限额 - 查看池健康 ### D. 插件辅助生成 key 要回答: - key 是由宿主生成还是插件包装生成 - 用户拿到 key 后需要看到哪些元数据 - 是否支持一键复制 SDK/curl 示例 本版本输出: - 自助 key 发放流程 - key 元信息展示规范 - 用户端“从登录到首次 200 调用”的最短路径 ### E. key / 账号治理 要回答: - key 暂停、账号暂停、限额是否已有宿主 API 可控点 - 如果宿主无足够字段,插件侧是否能通过控制面侧策略先拦截 本版本输出: - key 状态模型 - account 状态模型 - quota / budget / request limit 的最小可落地方案 - 与真实验收一致的治理 runbook ## Functional Requirements ### FR-1 协议能力探测 系统必须能输出一份按模型/协议/供应商分类的能力矩阵,至少覆盖: - OpenAI Chat Completions - OpenAI Responses(若宿主不支持,要明确标红) - Kimi 兼容接口 - DeepSeek - MiniMax - GLM - GPT 中转常见供应商 ### FR-2 宿主兼容性标签 系统必须把模型线路分类为: - `supported-direct` - `supported-with-plugin-adapter` - `unsupported-by-host` - `upstream-unhealthy` ### FR-3 模型池抽象 系统必须允许一个逻辑模型对应多个候选线路,并记录: - provider name - base_url - supported models - priority - schedulable - last health state - cooldown / disable reason ### FR-4 池化验收 必须证明在同组内: - 至少两个候选线路可共同服务一个模型名 - 一个线路失败后能切到另一条 - 被人工暂停的线路不会继续被分发 ### FR-5 模型池 active 准入 vNext.1 的 active model pool 必须默认排除: - `Schedulable=false` 的候选 - `HostReady=false` 的候选 - `unsupported-by-host` - `upstream-unhealthy` 如需展示不可进入 active pool 的候选,应输出 rejected/reason 视图,而不是混入 active routes。 ### FR-6 默认链路准入 只有通过真实用户链路 `POST /v1/chat/completions=200` 的模型池,才允许进入默认链路。 每条准入记录必须至少包含: - model pool ID - route/provider/account 证据 - upstream / host / user-key 三层 probe 路径 - artifact 路径 - 最近 N 次 chat=200 结果 - owner approval ### FR-7 后续版本保留项 以下需求仍保留,但不属于 vNext.1 实现范围: - 用户 portal 承接 - key 自助发放 - key/account 暂停恢复 - quota/limit - SLO/告警 这些内容必须在后续文档中单独落地: - `KEY_SECURITY_MODEL.md` - `PORTAL_KEY_EXPERIENCE.md` - `KEY_ACCOUNT_GOVERNANCE.md` - `SLO_AND_OBSERVABILITY.md` ## Non-Goals 本版本不做: - 修改宿主后端源码 - 自研完整计费系统 - 自研多租户 IAM - 直接替换宿主所有 UI - 在没有真实上游证据前承诺“所有主流模型都支持” ## Success Criteria vNext.1 当前审核通过标准: 1. 范围层面 - 已冻结 vNext.1 / vNext.2 / vNext.3 边界 - 未经审核通过,不继续实现后续版本主链功能 2. 设计层面 - 完成协议矩阵设计 + 模型池设计 + 默认链路准入设计 - 明确当前只承诺 priority failover,不承诺完整负载均衡池化 3. 证据层面 - 每个“支持”结论都绑定真实探测脚本与输出 - probe 必须区分 upstream / host / user-key 三层证据 4. 发布层面 - active pool 默认排除 `HostReady=false` 与 `Schedulable=false` - 只有通过真实用户链路的模型池才能进入默认链路 5. 规划层面 - vNext.2/vNext.3 的 key 安全模型、治理状态模型、SLO 文档已列为必备后续设计产物 ## Open Questions 1. 宿主当前对 key 暂停/禁用/限额是否已有稳定 API?需要先做 capability inventory。 2. 如果宿主无法直接生成明文 key,插件是否应改为“调用宿主生成 + 自身只投影展示”,而不是自造 key。 3. 限额优先做哪一种:余额、请求次数、模型级预算、日限额? 4. 用户登录态是否继续沿用 portal 当前机制,还是需要更明确的“申请 key / 管理 key”入口分离。 5. Kimi 与 GLM 是否都坚持走宿主统一协议,还是先接受“部分模型在插件侧标记为实验支持”。