2026-05-15 19:26:25 +08:00
# sub2api-cn-relay-manager 执行板
2026-05-22 10:03:49 +08:00
日期: 2026-05-22
2026-05-21 21:19:19 +08:00
当前 Gate: APPROVED( 代码门禁已通过, 并且 2026-05-21 已继续收掉 account probe、gateway probe 认证语义和 latest-head `self_service` fresh-host 复验的剩余问题。最新 MiniMax 53hk fresh-host 验收 `artifacts/real-host-acceptance/20260521_191418_remote43_minimax_key_import/21-summary.json` 、DeepSeek 2166 `subscription` fresh-host 验收 `artifacts/real-host-acceptance/20260521_201509_remote43_deepseek_key_import/21-summary.json` 、以及 latest-head `self_service` 标准 fresh-host 验收 `artifacts/real-host-acceptance/20260521_210403/05-import.json` / `07-access-status.json` 已共同证明:`subscription` 与 `self_service` 主链路都能在真实 fresh host 上闭环到 ready, host `/v1/models` 与 `/v1/chat/completions` 也都真实返回 `HTTP 200` 。当前仍存在的 `reconcile=drifted` 只反映共享 fresh-host 环境里的历史残留资源,不阻塞 PRD 首版放行)
2026-05-18 22:22:22 +08:00
目标:实现独立控制面、零侵入宿主、可导入国产模型并具备可运维的导入/回滚/访问闭环。
2026-05-22 10:03:49 +08:00
## 2026-05-22 当前真相
- 当前主目录 `artifacts/real-host-acceptance/` 已只保留最终证据;历史调试样本已迁到 `artifacts/real-host-acceptance-archive/`
- access ready 语义已经收口为:`/v1/models` 命中 `smoke_test_model` ,且最小 `POST /v1/chat/completions` smoke 成功;不会再出现 models-only 假 ready
- `subscription` 主链路已通过 latest fresh-host 复验:
- MiniMax 53hk: `artifacts/real-host-acceptance/20260521_191418_remote43_minimax_key_import/21-summary.json`
- DeepSeek 2166: `artifacts/real-host-acceptance/20260521_201509_remote43_deepseek_key_import/21-summary.json`
2026-05-22 12:33:12 +08:00
- Kimi A7M( local host `v0.1.129` ) : `artifacts/real-host-acceptance/20260522_122706_local_v0129_kimi_a7m_subscription_freshhost/21-summary.json`
2026-05-22 10:03:49 +08:00
- `self_service` 主链路已通过 latest-head 标准 fresh-host 复验:
- `artifacts/real-host-acceptance/20260521_210403/05-import.json`
- `artifacts/real-host-acceptance/20260521_210403/07-access-status.json`
2026-05-27 07:55:49 +08:00
- 2026-05-26 已把“最终用户 -> 公网域名 -> OpenClaw”这一跳补进正式验证口径:
- 公网根地址当前统一为 `https://sub.tksea.top`
- OpenClaw 本地 `MiniMax` 运行时故障已定位为 `pi-ai/openai-node` 未继承系统 `HTTP(S)_PROXY` ,不是 allowlist 或模型名大小写问题
- 操作者本机已新增升级后自检与提醒链路:
- `~/.openclaw/bin/apply-openclaw-minimax-proxy-fix.sh`
- `~/.openclaw/bin/openclaw-minimax-post-upgrade-check.sh`
- `~/.openclaw/bin/openclaw-minimax-proxy-reminder.sh`
- `~/.openclaw/bin/install-openclaw-minimax-reminder-cron.sh`
- 当前 OpenClaw 真实验证基线已收口为:
- `tksea-gpt/gpt-5.4` : PASS
- `tksea-gpt/gpt-5.4-mini` : PASS
- `tksea-gpt/gpt-5.5` :当前 upstream `503`
- `tksea-minimax/MiniMax-M2.5-highspeed` : PASS
- `tksea-minimax/MiniMax-M2.7-highspeed` : PASS
- `deepseek-official/deepseek-chat` : PASS( 2026-05-27 已补齐本机 auth profile, one-shot 返回 `OK` )
- 这部分测试用例与执行过程已沉淀到 `docs/OPENCLAW_EXTERNAL_VALIDATION.md`
- 2026-05-26 remote43 patched host 最新 provider 扩展验收:
- `openai-zhongzhuan` : `artifacts/real-host-acceptance/20260526_155548_remote43_openai_zhongzhuan_multi_model_rootprep/21-summary.json` 已确认 `batch_status=succeeded` 、`provider_status_from_import=active` 、`direct_chat_status=200`
- `minimax-53hk` : `artifacts/real-host-acceptance/20260526_155705_remote43_minimax53hk_multi_model_rootprep/21-summary.json` 已确认 `batch_status=succeeded` 、`provider_status_from_import=active` 、`direct_chat_status=200` 、`upstream_chat_status=200`
- `deepseek-chat-official` :
- 旧 artifact `artifacts/real-host-acceptance/20260526_155810_remote43_deepseek_chat_official_multi_model_rootprep/21-summary.json` 停在 `partially_succeeded/degraded`
- 2026-05-27 rerun `artifacts/real-host-acceptance/20260527_051655_remote43_deepseek-chat-official_key_import/21-summary.json` 已确认本机经 remote43 patched host 的真实数据面恢复:`direct_models_http200=true` 、`direct_models=["deepseek-chat"]` 、`direct_chat_status=200` 、`latest_access_status=subscription_ready` 、`upstream_chat_status=200`
- 剩余 `partially_succeeded/degraded` 的唯一原因已定位为宿主 account probe 返回裸 `API returned 404:` ,而后续 gateway `/v1/models` + `/v1/chat/completions` 实际都已通过; HEAD 现已把该 404 视为 advisory, 不再阻塞最终状态收敛
- 同轮还补上 remote43 scripted stack 的真实脚本缺陷:`.env.crm` 里的 SQLite DSN 含 `&_busy_timeout=5000` 时,旧版未做 shell escape, `source .env.crm` 会吞掉 `SUB2API_CRM_SQLITE_DSN` ,导致 remote CRM 实际退回默认 DB 路径;`scripts/remote43_patched_stack_lib.sh` 已修复并有回归测试覆盖
2026-05-23 09:18:02 +08:00
- latest-head relay-manager 已新增宿主 capability 自愈:
- 当第三方 OpenAI-compatible upstream 因宿主把 `openai_responses_supported` 误判成 `true` 而导致 host `/v1/chat/completions` 返回 `502 upstream_error` 时, access closure 与后台 reconcile 会自动把相关 account 修正到 raw `/chat/completions` 路径后再重试
2026-05-26 07:50:43 +08:00
- 但这条控制面自愈当前仍不足以单独收敛本地 stock `weishaw/sub2api:0.1.129` + `kimi-a7m` 场景;`artifacts/real-host-acceptance/20260525_local_v0129_kimi_a7m_scheme_c_stockhost_rerun/21-summary.json` 已再次证明: 在不改宿主源码的前提下, managed `/v1/models` 虽然命中 `kimi-k2.6` , `/v1/chat/completions` 仍会落到 `502 upstream_error` ,所以该 case 仍需宿主运行时兼容补丁或 shim
2026-05-23 15:03:59 +08:00
- 2026-05-23 remote43 线上验收脚本已继续收口:
- `scripts/import_remote43_provider.sh` 现已明确拆分 `CRM_HOST_BASE` 与 `REMOTE_HOST_BASE`
- 远端 Postgres / Redis 容器已改成按目标宿主端口自动解析,不再硬编码落到 `sub2api-relaymgr-pg/redis`
- 远端 managed probe `/v1/models` 与 `/v1/chat/completions` 已改成只走 `REMOTE_HOST_BASE`
- provider status / access status / access preview 末尾查询已补 `host_id` ,避免本地 CRM 有多宿主历史时被 `provider exists on multiple hosts` 截断
2026-05-26 07:50:43 +08:00
- 2026-05-25 已把 Hermes 里可复用的 `a7m-kimi` 正式并入主 pack:
- 新增 `packs/openai-cn-pack/providers/kimi-a7m.json`
- `openai-cn-pack` 版本现为 `1.1.3`
- 当前主仓不再需要依赖历史临时 pack `openai-cn-pack-kimi-a7m`
- `kimi-a7m` provider manifest 现在也开始承载 `host_overlays` 元数据;本地已把 `sub2api v0.1.129` 的 Kimi A7M runtime overlay 说明与 `.patch` 资产纳入 `packs/openai-cn-pack/overlays/`
- 新增 `go run ./cmd/cli apply-host-overlay` 最小执行器;当前 pack 内命中的 overlay 已可直接生成 patched 宿主构建目录,不再只是 preview/import 阶段的提示信息
- 2026-05-25 已继续把路线 A 推进到运行态层面:
- 从 `/tmp/sub2api-clean` 的 clean worktree `HEAD` 导出 stock 源码,再用 `go run ./cmd/cli apply-host-overlay --provider-id kimi-a7m --host-version 0.1.129` 生成全新 patched 源码树
- 基于该 patched 源码树重建 `localhost/sub2api:patched-overlay-20260525-clean` ,并在独立 Podman 网络里启动新的 Postgres / Redis / App fresh-host
- `artifacts/real-host-acceptance/20260525_local_v0129_kimi_a7m_patched_overlay_image_freshhost_clean/21-summary.json` 已确认:`import_batch_status=succeeded` 、`provider_status=active` 、`latest_access_status=subscription_ready` 、`completion_ok=true` 、`completion_status=200`
- 同目录 `07-access-status.json` 与 patched host 运行日志已共同证明 managed subscription key 真实打通 `/v1/models` 与 `POST /v1/chat/completions`
- 注意:该 fresh-host 使用的镜像基底仍是 `weishaw/sub2api:0.1.129` ,但宿主管理 API 当前自报 `host_version=0.1.126` ;后续读 artifact 时应以日期和证据链为准,不要只依赖版本字段
- 2026-05-25 已把同一条 patched overlay 路线放到 remote43 做线上验收:
- remote43 侧单独拉起了 `sub2api-kimi-patched-20260525-{app,pg,redis}` , patched host 暴露 `127.0.0.1:18139`
- 临时 CRM 也切到 remote43 本机运行,再通过 SSH 隧道映射回本地 `127.0.0.1:18143` ,避免“本地 CRM 透过隧道探远端 host”导致的 `get host version` 超时噪音
- `artifacts/real-host-acceptance/20260525_remote43_kimi_a7m_patched_overlay_freshhost_remotecrm/21-summary.json` 已确认:`batch_status=succeeded` 、`access_status_from_import=subscription_ready` 、`provider_status_from_import=active` 、`direct_models_http200=true` 、`direct_chat_http200=true` 、`upstream_chat_status=200`
- 同目录 `14-access-status.json` 已确认 `effective_probe_key_source=managed_subscription` 且 `completion_status=200`
- remote43 宿主日志也已落到真实 `GET /v1/models = 200` 、`POST /v1/chat/completions = 200` ,说明这条 patched overlay 路线不只在本地 fresh-host 成功,也已在远端真实环境收敛到 ready
- 这轮还顺手修掉了 `scripts/import_remote43_provider.sh` 的一个真实脚本缺陷:查找未分配 `relay-sub-*` 用户时,`NOT EXISTS` 子查询错误引用了无 alias 的 `users.id` ,在 PostgreSQL 上会报 `invalid reference to FROM-clause entry for table "users"`
- 2026-05-25 继续把这套 remote43 patched-host / remote CRM 的启动流程脚本化:
- 新增 `scripts/setup_remote43_patched_stack.sh` ,把 pack 镜像、二进制上传、remote43 上的 PG/Redis/patched host/临时 CRM 拉起、以及本地 operator env / SSH 隧道提示收口为一个固定入口
- 新增 `scripts/remote43_patched_stack_lib.sh` ,把远端 host env / CRM env / bootstrap script 渲染逻辑抽成可测试 helper
- `scripts/test_real_host_scripts.sh` 已新增对应回归,避免以后再回退到手工 `/tmp/*.sh` 拼装
- 脚本首轮真实演练暴露出一个运行态细节: patched `sub2api` 二进制实际监听 `8080` ,不能沿用旧临时脚本里的 `127.0.0.1:$HOST_PORT:3000` 端口映射;当前 `setup_remote43_patched_stack.sh` 已新增 `HOST_CONTAINER_PORT=8080` 默认值并完成 remote43 二次实跑验证
- 用修复后的固定脚本在 remote43 新起的 `sub2api-kimi-patched-auto2-20260525` 栈上,`kimi-a7m` 再次完成真实导入主链路:`artifacts/real-host-acceptance/20260525_remote43_kimi_a7m_patched_overlay_scripted_stack/03-import.body.json` 已确认 `batch_status=succeeded` 、`access_status=subscription_ready` 、`provider_status=active` ,同目录 `10-models.body.json` / `12-chat.body.json` / `18-upstream-models.body.json` / `20-upstream-chat.body.txt` 也已再次证明 managed 与 upstream 双侧都回到 `HTTP 200`
- 2026-05-26 继续把 scripted stack 的末尾状态查询收口为稳定契约:`scripts/import_remote43_provider.sh` 末尾不再只传 `host_id` ,而是显式拼上 `pack_id=openai-cn-pack&host_id=<create-host 返回值>` ;修复原因是 remote43 上同一个 provider 可能存在多个 pack 版本,缺 `pack_id` 时 `/api/providers/{providerID}/status` 会返回 `400 provider exists in multiple packs; pack_id is required`
- 修复后,`artifacts/real-host-acceptance/20260526_remote43_kimi_a7m_patched_overlay_scripted_stack_rerun2/13-provider-status.json` 、`14-access-status.json` 、`21-summary.json` 已全部自动补齐;其中 `21-summary.json` 已再次确认 `batch_status=succeeded` 、`provider_status_from_import=active` 、`latest_access_status=subscription_ready` 、`direct_chat_status=200` 、`upstream_chat_status=200`
- `artifacts/real-host-acceptance/20260525_local_v0129_kimi_a7m_from_hermes/21-summary.json` 已证明:
- Hermes 本机 `A7M_KIMI_API_KEY` 直探 upstream `/v1/models` 与 `/v1/chat/completions` 均为 `200`
- latest-head relay-manager + 本地 `weishaw/sub2api:0.1.129` fresh-host 下, import-time gateway `/v1/models` 命中 `kimi-k2.6`
- 但 completion 仍落到 `502 upstream_error` ,手工 managed key 再探 `/v1/chat/completions` 也返回 `503`
- 管理员 account 视角 `/api/v1/admin/accounts/1/models` 正确,但手工 managed key `/v1/models` 仍会回到 GPT 默认集合,当前应继续归类为宿主运行时 gap / drift, 而不是 Hermes key 失效
- `artifacts/real-host-acceptance/20260525_local_v0129_kimi_a7m_from_hermes/22-patched-host-validation.json` 已证明:
- 问题根因是宿主把 Kimi A7M 这类 custom upstream 误走到 `Responses` 路径,而不是 Hermes key 或 relay-manager pack 失效
- 在 `/tmp/sub2api-clean` 的宿主补丁下,旁路容器 `sub2api-patched` 已恢复 `managed key /v1/models=200` 、`managed key /v1/chat/completions=200` 、`admin accounts/:id/test=true`
- fallback 日志与账号 `extra.openai_responses_supported=false` 持久化已同时出现,说明这条链路已经从 stock host 的 `partially_succeeded / broken` 收敛到 patched host 的 `ready`
- `artifacts/real-host-acceptance/20260525_local_v0129_kimi_a7m_scheme_c_stockhost_rerun/21-summary.json` 已证明:
- 仅启用 relay-manager 侧方案 C( 预先 `force_disable_openai_responses_api` + import/access/reconcile capability repair) , 但保持宿主仍是未打补丁的 stock `weishaw/sub2api:0.1.129`
- import-time gateway `/v1/models` 仍能命中 `kimi-k2.6`
- 但 import-time gateway `/v1/chat/completions` 依旧返回 `502 upstream_error` , `access_status` 仍是 `broken` , `provider_status_latest` 仍是 `partially_succeeded`
- 因此当前最新真相不是“方案 C 已替代宿主补丁”,而是“方案 C 缩小了控制面误判范围,但这条 Kimi A7M / stock v0.1.129 链路仍需要宿主运行时兼容修复”
- 2026-05-25 已继续补齐方案 C( 控制面侧 capability repair) :
- `internal/host/sub2api` 新增 `ClearTempUnschedulable`
- access / reconcile 的 capability repair 现在会同时写 `extra.openai_responses_supported=false` 并清理账号 `temp_unschedulable`
- `packs/openai-cn-pack/providers/kimi-a7m.json` 新增 `force_disable_openai_responses_api=true` ,导入后会在 gateway closure 前预先把该账号切到 raw `/v1/chat/completions`
2026-05-23 15:03:59 +08:00
- `artifacts/real-host-acceptance/20260523_144937_remote43_kimi-a7m_key_import` 已证明:
- 这轮线上 `kimi-a7m` 不再复现“错库取 key 导致统一 401”或“模型列表串成 GPT 默认集合”
- import 已返回 `gateway.status_code=200` 、`models=["kimi-k2.6"]` 、`has_expected_model=true`
- upstream `/models` 与 `/chat/completions` 都是 `200`
- 未改宿主的真实阻塞已收缩为 host `/v1/chat/completions` 仍返回 `503/502` ,不再是插件脚本的数据面问题
- `artifacts/real-host-acceptance/20260523_145531_remote43_kimi-a7m_key_import` 说明另一类运行时噪音:
- 当本地 SSH 隧道端口存活但链路已失活时,`POST /api/hosts` 阶段会在 `get host version` 处超时
- 这类现象应优先解释为 tunnel/runtime 故障,而不是 provider 导入逻辑回退
2026-05-22 10:03:49 +08:00
- 官方 provider 验证矩阵当前仍保留一条非阻塞事实:
- `artifacts/real-host-acceptance/20260521_222212_remote43_minimax-m2-7-official_key_import/21-summary.json` 已证明 official MiniMax 模板链路是通的,但该验证 key 当前命中 upstream `429`
- `reconcile=drifted` 仍可能在 shared fresh-host 上出现,但当前解释是“历史残留资源噪音”,不阻塞 PRD 首版放行
- 调通细节与诊断经验已沉淀到:
- `docs/REAL_HOST_ACCEPTANCE_LEARNINGS.md`
- `docs/REAL_HOST_ARTIFACT_RETENTION.md`
2026-05-25 07:30:07 +08:00
- 2026-05-24 本地代码门禁修复已继续收口三类非回归点:
- `go test -race ./... -count=1` 现已再次真实通过;根因不是业务逻辑,而是多个测试包并行 `sqlite.Open()` 时与 `modernc.org/sqlite` 初始化路径的 race 噪音。当前已把 `internal/app` 、`internal/provision` 、`internal/reconcile` 的测试 SQLite 打开路径收口到串行 helper, 关闭这类假红灯, 同时保持 sqlite 包内测试不引入导入环。
- `DELETE /api/hosts/{hostID}` 不再默认放行危险级联删除;`hosts` repo 现在会先统计 `import_batches / managed_resources / reconcile_runs` 三类运行态依赖,有残留时返回 `409 host_in_use` ,避免误删状态库里的回滚/对账真相。
- 控制面 JSON 请求体现在统一受 `MaxBytesReader` 限制;超限请求会明确返回 `413 request_too_large` ,不再允许无界 body 直接进入解码路径。
2026-05-21 09:16:45 +08:00
2026-05-18 22:22:22 +08:00
## 本轮已完成
1. 宿主身份模型统一
- host 注册时持久化 `auth_type/auth_token`
- import / reconcile / rollback-provider / access 运行时链路切换为 `host_id` 主键
- provider status / resources / access status / import-batches 支持 `host_id` 查询维度
2. managed_resources 宿主维度收口
- 新增迁移 `0004_host_identity_and_managed_resources.sql`
- `managed_resources` 唯一键提升为 `(host_id, resource_type, host_resource_id)`
- 仓储与服务查询切换为 host-scoped 语义
3. reconcile run 结果按批次收口
- 新增迁移 `0006_reconcile_runs_batch_scope.sql`
- `reconcile_runs` 补充 `batch_id` , batch detail 仅返回本批次 reconcile 记录
4. capability probe 收敛为无副作用探测
- 不再对真实创建接口发送空 `POST`
5. rollback-provider 风险收敛
- 改为优先按已记录批次资源 `RollbackStoredResources()` 回滚
- 缺少已记录资源时拒绝危险删除
6. 文档真相同步
- 新增 `docs/2026-05-18-PRODUCTION_REMEDIATION_TASK_BOARD.md`
- 下调 `DEPLOYMENT.md` 中未实现的 `/metrics` / 限流 / 监控承诺
2026-05-22 10:03:49 +08:00
7. current-code remote43 导入链路已补齐 tunnel-aware 验证能力
2026-05-19 20:21:21 +08:00
- `scripts/import_remote43_provider.sh` 新增 `CRM_HOST_BASE` , 允许把“operator 访问 host 地址”和“CRM 进程访问 host 地址”分离
2026-05-22 10:03:49 +08:00
- 历史 live model-mapping 关键证据保留在:`artifacts/real-host-acceptance/20260520_222713_crm18100_live_model_mapping_validation`
8. current-code remote43 access gate 根因修正已落地
2026-05-20 22:09:40 +08:00
- subscription access 改为宿主侧闭环: CRM 不再依赖外部预先给定的宿主普通用户 key, 而是按 `subscription_users` selector 在宿主创建/查找托管普通用户、登录创建托管 key、回写 allowed_groups / balance、再执行订阅分配
- account 创建请求现在同步写入 `credentials.model_mapping` ,修正 `/v1/models` 读取 account model whitelist 时回退到 GPT 默认集合的问题
- 新增/更新测试覆盖:`internal/access` 、`internal/provision` 、`internal/host/sub2api`
2026-05-22 10:03:49 +08:00
9. current-code access ready 语义已提升到 completion 层
2026-05-21 21:19:19 +08:00
- `/v1/models` 不再单独决定 `subscription_ready/self_service_ready`
- 只有 `/v1/models` 命中 `smoke_test_model` 且 `/v1/chat/completions` smoke 成功,控制面才会把 access 状态记成 ready
- access closure / import runtime artifact / reconcile rerun payload 都会持久化 `completion_ok/completion_status/completion_type/completion_preview`
2026-05-22 10:03:49 +08:00
10. current-code remote43 验收脚本已补 upstream API 证据层
2026-05-27 07:55:49 +08:00
- `scripts/import_remote43_provider.sh` 会直探 provider `base_url` 对应的 upstream `/models` 与 `/chat/completions`
- 新增 `21-summary.json` ,用于把 completion 失败自动分流成 `host_compatibility_gap` 或 `upstream_key_quota_issue`
2026-05-22 10:03:49 +08:00
11. patched CRM external validation 已完成
2026-05-27 07:55:49 +08:00
- patched CRM 实例下, DeepSeek 与 MiniMax 都已验证“completion smoke 通过时能落成 succeeded/active, 失败时不会误记成 ready”
- `20260521_191418_remote43_minimax_key_import` 与 `20260521_201509_remote43_deepseek_key_import` 已同时证明当前 `subscription` provider 链路可真实闭环
- `20260521_210403` 已证明 latest-head `self_service` 标准 fresh-host 验收也可闭环到 `self_service_ready / fully_ready`
2026-05-22 10:03:49 +08:00
12. artifact 保留策略已收口
2026-05-27 07:55:49 +08:00
- 主目录 `artifacts/real-host-acceptance/` 当前只保留最终证据
- 历史失败/半成功/试错样本已迁到 `artifacts/real-host-acceptance-archive/`
- 分类规则见:`docs/REAL_HOST_ARTIFACT_RETENTION.md`
2026-05-22 12:33:12 +08:00
13. relay-manager latest-head 已收口 Kimi A7M 两段竞态
2026-05-27 07:55:49 +08:00
- account test 首次 `403 Forbidden` 已降级为 advisory warning; 只要 `/models` 已命中 `smoke_test_model` ,不会再把 batch 误判为 blocking failure
- access closure 对导入后瞬时 `503 / no available accounts` 增加短暂 completion retry, 避免宿主异步 probe / account warm-up 窗口把真实可用链路误记成 `broken`
- `20260522_122706_local_v0129_kimi_a7m_subscription_freshhost` 已证明:在修复后的 relay-manager + patched host 组合下,`kimi-a7m / kimi-k2.6` 可落到 `batch_status=succeeded` 、`provider_status=active` 、`latest_access_status=subscription_ready`
2026-05-23 09:18:02 +08:00
14. relay-manager latest-head 已补宿主升级后的 capability 自愈
2026-05-27 07:55:49 +08:00
- 对 `API returned 403: Forbidden` 这类 `/responses` 误判 advisory, 控制面现在会在 access closure 与 reconcile rerun 中把目标 account 的 `openai_responses_supported` 修正为 `false` ,随后重试 gateway `/v1/chat/completions`
- 这样即使宿主升级或异步 probe 把 capability 标记覆写错,控制面也能在“安装后确认”与“后台持续对账”两个环节重新拉回可用状态
2026-05-25 07:30:07 +08:00
15. 2026-05-24 本地质量门禁补丁已完成
2026-05-27 07:55:49 +08:00
- 新增 repo 级删除保护:`internal/store/sqlite/hosts_repo.go` 引入 `RuntimeDependencyCountsByHostID` 与 `HostDeleteBlocker`
- 新增回归测试:`TestHostsRepoDeleteByHostIDBlocksWhenRuntimeStateExists` 、`TestBatchImportRejectsOversizedJSONBody` 、`TestDecodeJSON/rejects oversized request body`
- `internal/app/http_api.go` 现已统一限制 JSON request body 大小,并把 host 删除占用态映射为 `host_in_use`
- `internal/app` / `internal/provision` / `internal/reconcile` 测试 SQLite 打开路径已改为串行 helper, 当前 `go test -race ./... -count=1` 重新恢复为绿
2026-05-18 22:22:22 +08:00
## 已验证门禁
- `gofmt -l .` ✅ 空输出
- `go vet ./...` ✅
- `go test ./...` ✅
- `go test -race ./...` ✅
- `go test -cover ./internal/...` ✅
2026-05-21 21:19:19 +08:00
- `internal/access` : `80.5%`
- `internal/host/sub2api` : `78.1%`
- `internal/pack` : `73.9%`
2026-05-23 11:12:34 +08:00
- `internal/provision` : `79.4%`
- `internal/store/sqlite` : `77.9%`
2026-05-18 22:22:22 +08:00
- `go test ./tests/integration/... -count=1` ✅
2026-05-21 13:37:49 +08:00
- `bash ./scripts/test_real_host_scripts.sh` ✅
2026-05-18 22:22:22 +08:00
2026-05-22 10:03:49 +08:00
## 当前保留的最终证据
1. `artifacts/real-host-acceptance/20260520_222713_crm18100_live_model_mapping_validation`
- 证明 account `credentials.model_mapping` 与 live runtime 对齐
2. `artifacts/real-host-acceptance/20260521_142211_crm18100_deepseek_completion_split`
- 证明 host completion 失败与 upstream completion 成功可以分离
- 是 completion 分流逻辑的关键根因证据
3. `artifacts/real-host-acceptance/20260521_191418_remote43_minimax_key_import`
- MiniMax 53hk `subscription` 最终成功样本
- `21-summary.json` 已到 `batch_status=succeeded` 、`provider_status=active`
4. `artifacts/real-host-acceptance/20260521_201509_remote43_deepseek_key_import`
- DeepSeek 2166 `subscription` 最终成功样本
- `21-summary.json` 已到 `batch_status=succeeded` 、`provider_status=active`
5. `artifacts/real-host-acceptance/20260521_210403`
- latest-head `self_service` 标准 fresh-host 验收最终成功样本
- `05-import.json` = `succeeded/self_service_ready/active`
- `07-access-status.json` = `latest_access_status=fully_ready`
6. `artifacts/real-host-acceptance/20260521_222212_remote43_minimax-m2-7-official_key_import`
- official MiniMax 模板 live 样本
- 模板链路打通,但当前验证 key 命中 upstream `429`
2026-05-22 12:33:12 +08:00
7. `artifacts/real-host-acceptance/20260522_122706_local_v0129_kimi_a7m_subscription_freshhost`
- latest-head relay-manager 对 patched host `v0.1.129` 的 Kimi A7M `subscription` 最终成功样本
- `21-summary.json` 已到 `batch_status=succeeded` 、`provider_status=active`
- `account_probe_summary` 明确记录 `probe_advisory=true` 、`validation_status=warning` ,证明 403 probe race 已被 relay-manager 正确降级
2026-05-23 15:03:59 +08:00
8. `artifacts/real-host-acceptance/20260523_144937_remote43_kimi-a7m_key_import`
- remote43 未改宿主 + 修正后的 latest-head 验收脚本样本
- 已证明脚本层的“错库取 key / 错地址 / 多 host 历史查询”问题被收掉
- 仍保留的真实阻塞是宿主 completion 路径 `502/503`
2026-05-26 07:50:43 +08:00
9. `artifacts/real-host-acceptance/20260525_local_v0129_kimi_a7m_from_hermes`
- 当前主 pack `1.1.1` 正式纳入 `kimi-a7m` 后的本地 fresh-host 验收样本
- `21-summary.json` 保留了 stock host `v0.1.129` 的原始失败快照,证明 Hermes A7M upstream key 当前在线可用,阻塞不在 key 本身
- `22-patched-host-validation.json` 与 `23-sub2api-host-patch-notes.md` 已补齐 patched host 的真实收敛证据:问题是宿主 runtime 的 `Responses -> raw chat` 兼容缺口,补丁后链路已回到 ready
2026-05-22 10:03:49 +08:00
## 剩余项( P2 / 运营前置,不阻塞按 PRD 首版范围上线)
1. 运营前置
- 真实宿主初始化不会自动创建普通用户;上线前必须显式创建普通用户并留存可复用凭据
2026-05-18 22:22:22 +08:00
- `self_service` 需要普通用户 key 绑定目标标准 group, 且通常还需要可用余额
- `subscription` 需要 subscription 类型 group + 普通用户订阅分配 + key/group 绑定
2026-05-23 09:18:02 +08:00
- 若启用持续后台 reconcile, SQLite 状态库将持久化最新 access probe 元数据,部署时必须按 secret 级别保护数据库文件
2026-05-22 10:03:49 +08:00
2026-05-23 09:18:02 +08:00
2. 部署与环境限制
2026-05-22 10:03:49 +08:00
- 标准多阶段 Dockerfile 在受限网络环境下仍不稳
2026-05-18 22:22:22 +08:00
- 当前推荐 `scripts/build_local_image.sh` + `Dockerfile.local`
2026-05-23 09:18:02 +08:00
3. official provider 验证矩阵
2026-05-22 10:03:49 +08:00
- official MiniMax 当前 live 样本已证明模板链路可用,但验证 key 命中 upstream `429`
- Qwen / GLM / Kimi / Step 等官方 provider 是否通过 live 验收,仍取决于后续官方 key 与 quota
## 当前最短后续路径
2026-05-18 22:22:22 +08:00
2026-05-22 10:03:49 +08:00
1. 若继续扩大 provider 覆盖面,优先按 `docs/PROVIDER_VALIDATION_MATRIX.md` 补官方 key, 再做 official live 验收
2. 若继续优化 shared fresh-host 信噪比,对历史残留资源做一次环境清理,降低 `reconcile=drifted` 噪音
2026-05-22 16:21:24 +08:00
3. 若继续产品化,优先扩大 official provider live 验收覆盖面,并基于新 create-run 入口补充真实宿主 acceptance artifact
2026-05-15 19:26:25 +08:00
2026-05-22 06:51:44 +08:00
## v2 规划: Batch Auto-Import( URL + Key)
2026-05-22 16:21:24 +08:00
**当前阶段**:✅ 已按基线计划恢复实现( T1~T13 已落地, create-run entry wiring 已补齐,最新全量验证通过)
2026-05-22 10:03:49 +08:00
2026-05-22 13:18:51 +08:00
**文档**: `docs/2026-05-21-BATCH_AUTO_IMPORT_SPEC.md` (需求规格)
2026-05-22 10:03:49 +08:00
**TDD 计划**: `docs/2026-05-21-BATCH_AUTO_IMPORT_TDD_PLAN.md` (实现路径,已确认开放问题)
2026-05-22 13:18:51 +08:00
**技术架构**: `docs/2026-05-22-BATCH_AUTO_IMPORT_V2_ARCHITECTURE.md` ( 运行态状态库、结果页、API、页面字段布局)
2026-05-22 13:43:46 +08:00
**Migration 草案**: `docs/2026-05-22-BATCH_AUTO_IMPORT_V2_MIGRATION_DRAFT.md` ( SQLite 新表、索引、lease/retry 字段、legacy link)
**API Schema 细稿**: `docs/2026-05-22-BATCH_AUTO_IMPORT_V2_API_SCHEMAS.md` ( run/item 响应结构、筛选参数、badge 文案、错误语义)
2026-05-22 13:18:51 +08:00
**本轮设计收敛**:
2026-05-27 07:55:49 +08:00
2026-05-22 13:18:51 +08:00
- 已把真实验收中的三类高频问题写入 v2 方案:
- 添加模型时的模型名归一化与纠错
- 第三方国产模型的兼容能力画像(`/responses` 、`/chat/completions` 、Anthropic compatible、stream/tools)
- 添加账号后的异步确认窗口(首次 `403` probe race、首次 `503 no available accounts` warm-up)
- 已补充两类产品化能力到 v2:
- run / item 状态持久化、retry 轨迹、控制面重启后的历史结果查看
- 批次列表页 / 批次详情页, 用于查看模型纠错结果、账号状态、provider warning 与最终 access 状态
- 当前 v2 的目标已从“同步导入成功”升级为“导入 + 异步确认 + 最终闭环验真”
2026-05-22 13:38:56 +08:00
- 已按 review 收口最关键的 4 个冲突:
- 统一 canonical contract: `run_id/item_id/provider_id/run.state/confirmation_status/access_status`
- 补齐 `subscription` / `self_service` 的输入契约
- 明确 V2 唯一状态源为 `import_runs/import_run_items/import_run_item_events`
- 明确 `ConfirmationWorker + lease + next_retry_at` 的异步确认执行机制
- 其余 review 问题也已同步收口:
- capability 从 upstream 总画像升级为 transport + model profiles
- 结果页字段、状态库存储字段、retry/event trail 已统一
2026-05-23 09:18:02 +08:00
- run 级请求上下文已持久化到 `import_runs` ,控制面重启后 validate 能继续使用 `host_id / subscription_users / subscription_days / probe_api_key`
2026-05-22 13:38:56 +08:00
- OpenAPI 已补齐 `/api/batch-import/runs*` , legacy `/api/import-batches/*` 降级为 v1/legacy
2026-05-23 09:18:02 +08:00
- run/item 列表 API 已补齐 `cursor/next_cursor` ; run 列表 `q` 可命中 `run_id / provider_id / base_url`
2026-05-22 14:15:41 +08:00
- 已补充重复导入自动复用策略:按 `provider_id + api_key_fingerprint + canonical_model_family` 判断 `reused / patch_only / replace`
- 已补充同模型别名归一化契约:例如 `kimi 2.6 / kimi-2.6 / kimi-k2.6` 可归并到同一模型家族并快速复用
- 已补充多账号重复导入与弃用账号再启用策略: active 账号提示“重复已启用”, disabled/deprecated 账号显示原状态并走 `reactivated` 快速启用路径
2026-05-23 17:06:52 +08:00
- 已修正 access closure artifact 的 probe key 语义漂移:`subscription` 现在持久化 `requested_probe_api_key` 、`effective_probe_key_source` 、`effective_probe_key_fingerprint` ,不再把外部 raw key 伪装成 `probe_api_key` ; `probe_api_key` 仅继续用于 `self_service` 向后兼容
- 最新干净本地 fresh-host 验收 `artifacts/real-host-acceptance/20260523_local_clean_minimax_subscription_probe_semantics` 已验证:
- `subscription` closure 会正确区分 `requested_probe_api_key` 与 `managed_subscription` 实际 probe 来源
- 同一轮 raw key 直打宿主仍返回 `403 not assigned to any group`
- provider completion 仍受 MiniMax 官方 upstream `429 rate_limit_error` 影响,但这已不再会被 artifact 误读成 raw key 可用
2026-05-23 17:34:53 +08:00
- 同一 fresh-host 上继续补的 MiniMax `M2.5` 缩圈验证已证明:
- `artifacts/real-host-acceptance/20260523_local_clean_minimax_m25_only_probe` :单独只打 `M2.5` 时,宿主会选中真实账号并命中 upstream `429`
- `artifacts/real-host-acceptance/20260523_local_clean_minimax_m25_repeated_probe` :连续第 1 次 `M2.5` 是 `429` ,后续第 2/3 次退化成 `503 Service temporarily unavailable`
- 对应宿主日志中,第一次有 `account_id=1` 和 `upstream_status=429` ,后续只有 `account_select_failed error=\"no available accounts\"`
- 当前 MiniMax live 阻断要按两层解释:第一次是 upstream quota/rate-limit, 后续 `503` 是唯一账号进入临时不可调度窗口后的宿主侧结果
2026-05-22 13:38:56 +08:00
2026-05-22 15:54:10 +08:00
**本轮实现状态( T1 ~ T13) **:
2026-05-27 07:55:49 +08:00
2026-05-22 15:54:10 +08:00
- [x] `internal/batch` canonical types / reuse policy / service / confirmation / validation / projection 已落地
- [x] `internal/probe` models / alias / capability / smoke completion 已落地
- [x] `internal/store/sqlite` run/item/event runtime state repo 与 migration 已落地
- [x] `/api/batch-import/runs*` 路由、projection 读取、CLI `batch-import` 命令、集成测试与设计还原审计已落地
- [x] `go test ./... -count=1`
- [x] `go test ./tests/integration/... -count=1`
- [x] `go test -cover ./internal/... -count=1`
- [x] `go vet ./...`
- [x] `gofmt -l .`
**T13 审计结论**:
2026-05-27 07:55:49 +08:00
2026-05-22 15:54:10 +08:00
- `docs/2026-05-22-BATCH_AUTO_IMPORT_V2_RESTORATION_CHECKLIST.md` 已完成
2026-05-22 16:21:24 +08:00
- latest-head 已补齐 `internal/app/http_batch_import.go` -> `internal/app/batch_runtime.go` 的 create-run 入口 wiring
- API 与 CLI create-run 现在都会真实驱动 `BatchImportService + ConfirmationWorker + ValidationService`
2026-05-23 09:18:02 +08:00
- 控制面 server 启动后会自动运行 batch-import background scheduler, `running` run 在重启后可继续推进
2026-05-22 16:21:24 +08:00
- 最新一轮验证结果保持全绿:`go test ./... -count=1` 、`go test ./tests/integration/... -count=1` 、`go test -cover ./internal/... -count=1` 、`go vet ./...` 、`gofmt -l .`
2026-05-22 15:54:10 +08:00
2026-05-22 16:21:24 +08:00
**真实 Gate**:✅ 文档、状态机、投影、测试、审计与 create-run 入口已经对齐,**V2 设计已按基线计划交付**
2026-05-22 06:51:44 +08:00
---
2026-05-15 19:26:25 +08:00
## 禁止错误结论
2026-05-18 22:22:22 +08:00
2026-05-22 10:03:49 +08:00
- ❌ 历史失败 artifact ≠ 当前 latest-head 仍失败
- ❌ capability probe 无副作用 ≠ 所有宿主版本都已真实兼容
- ❌ rollback-provider 已改安全路径 ≠ 历史脏资源自动消失
2026-05-18 22:22:22 +08:00
- ❌ `HTTP 200` ≠ 宿主初始化会自动准备普通用户/订阅/余额;这些仍是显式运营前置