mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-09-20 08:57:57 +00:00
fix: close P10 audit items — P10-1 sources API admin guard, P10-2 scope prefix strip, P10-3 runtime source timeout w/ stream-safe clients
- api.go: handleSourcesAPI now requires admin role (GET leaks upstream api_keys, POST/DELETE mutate routing)
- chat.go: hasScopeModel made a Gateway method that strips source-model/:// prefix strictly via Registry.EffectiveModel (only when the prefix names a real source serving the bare model) so dash-bearing ids like deepseek-v4-flash-free are never corrupted; +TestHasScopeModelWithSourcePrefix
- config.go: DefaultSourceTimeout/QueueTimeout/Concurrency constants shared by YAML ApplyDefaults and runtime sources
- core.go: mergedSources applies the same defaults to runtime sources (JSON never persisted timeout fields); a dead upstream can no longer hold a concurrency slot forever
- provider.go: split non-streaming client{Timeout} vs stream client{} sharing a Transport with ResponseHeaderTimeout, so long SSE bodies are not cut by client.Timeout; ChatStream uses doRawStream
- plan.md: mark P4-4/5/6 done, record P4-7/8 (tier-order, audit export, UI key view, zen upstream diagnosis)
- online verified: user key -> /api/sources 403 (GET+POST), admin 200, AUTO stream/non-stream healthy
This commit is contained in:
8
plan.md
8
plan.md
@ -240,6 +240,8 @@ p==nil → 400/404;!TryAcquire → 429 busy(快速失败)
|
||||
- [x] **P4-1(2026-08-11)WebUI 聊天"每次回复都失败"(用户实测)**:根因——`sendChat()` 调 `addMsg('assistant', '')` 未传 reason 参数 → `thinkEl`/`hintEl` 为 null → 首个携带 `reasoning_content` 的流式 chunk 到达时 index.html 抛 `Cannot set properties of null`,前端表现为请求失败。修复:`addMsg('assistant', '', true)` + 初始隐藏 think 框;提交 `7647b7d`,已推送并部署生产(服务 active、`/api/status` 正常),`go test ./internal/gateway/...` 通过。
|
||||
- [x] **P4-2(2026-08-11)41s AUTO 延迟归因**:审计 `09:54:42 stream lat=41810 model=deepseek-v4-flash-free src=zen ok=200 pt=17 ct=109`——链上调度仅 ~0.6s(tier1 qijiar 失败 lat=657ms 后顺延),其余 ~41s 为 zen 上游生成耗时(~380ms/token),**非网关调度问题**。
|
||||
- [x] **P4-3(2026-08-11)全量代码审查**:provider.go(812 行)/stats.go(459 行)/scheduler.go(398 行)/registry.go(258 行)/api.go/chat.go/server.go/config 全部通读完毕,确认 P10-1~P10-5(见上)。
|
||||
- [ ] **P4-4**:`handleSourcesAPI` 补 admin 校验(P10-1,一行仿 api.go:21)— 待用户确认后实施。
|
||||
- [ ] **P4-5**:`hasScopeModel` 剥前缀比对(P10-2)— 待确认。
|
||||
- [ ] **P4-6**:runtime 源默认超时策略(P10-3,区分流式/非流式)— 待确认。
|
||||
- [x] **P4-4(2026-08-11)`handleSourcesAPI` 补 admin 校验(P10-1)**:`api.go` 方法开头加 `reqRole(r.Context()) != "admin"` 检查(同 handleAdaptersAPI);线上实测 user 级 key GET/POST `/api/sources` 均 403,admin 200,防越权读取明文 api_key 与篡改源。
|
||||
- [x] **P4-5(2026-08-11)`hasScopeModel` 剥前缀比对(P10-2)**:改为 Gateway 方法,先用 `Registry.EffectiveModel` 严格剥 `source-`/`source:`/`source/` 前缀(仅当前缀是真实源名且该源确实服务裸模型时才剥,避免误伤 `deepseek-v4-flash-free` 这类自带 `-` 的模型 ID);单测 `TestHasScopeModelWithSourcePrefix` 覆盖前缀剥离与勿误伤。
|
||||
- [x] **P4-6(2026-08-11)runtime 源默认超时策略(P10-3,区分流式/非流式)**:新增 `config.DefaultSourceTimeout=120s/DefaultSourceQueueTimeout=60s/DefaultSourceConcurrency=8`;`Core.mergedSources` 对 runtime 源兜底(JSON 源不序列化 timeout);`Provider.New` 拆两个 client——非流式 `client{Timeout}` 整请求限时、流式 `stream` 无总超时(共享 Transport 仅 `ResponseHeaderTimeout` 限首字节),长 SSE 不被掐;`ChatStream` 改用 `doRawStream`。单测 + 线上流/非流式验证通过。
|
||||
- [x] **P4-7(2026-08-11)AUTO 链 tier 序 + 审计导出修复 + UI 密钥视图(今日会话)**:① `BuildChain` 排序由降序改升序(tier1=最高优先级先试,修 P10-5 中的序颠倒),单测同步;② 统计/CSV 全量(limit 20000、`Stats.AuditRecords` 读磁盘含 `*.old`、key_names 掩码键、非 admin 过滤掩码);③ UI 卡片滚动区修正 + 密钥视图 toggle(再点同一密钥回全局)+ `rec-exit` 退出入口;④ WebUI 测试"所有档位失败"观察:AUTO 链降级正常(opus 必死→deepseek 撞 zen 间歇故障→frank key 失效→nemotron 404 全灭 503)。
|
||||
- [x] **P4-8(2026-08-11)调度延滞排查结论**:homeagent AUTO 请求"看起来停在 opus"实为调度正常降级——完整 ChainErr 列出 tier1→2→3→4 全部尝试,审计只记 `ce.Tiers[0]`(首档)故 UI 显 opus;zen 源 `opencode.ai/zen/v1` 直连即 403 `[server_error] Upstream response was not valid JSON`(间歇)/ nemotron 404,确认为上游源自身问题,非网关透传或 homeagent 适配器。
|
||||
Reference in New Issue
Block a user