feat(gateway,admin-web): 面板可编辑 provider 推理形状 / 角色级路由 / multimodal 真语义(裁决 03.4.2/03.4.1)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

- 后端:AdminLlmProvider 暴露 reasoning{kind}(恒下发,""=未声明=auto)、personaModels、personaProviders;
  顶层新增 reasoningKinds / personaProviderOptions 两个**取值域**(唯一来源= runtimeconfig 导出枚举,
  校验错误文案也由枚举拼接 ⇒ 不可能漂移)
- 读写共用同一映射(admin_llm_provider.go),避免「读侧少一个键 ⇒ 面板一保存就抹掉」
- 写侧语义:缺失=保留、给出=整块/整表替换;非法值一律 runtimeconfig.Group.Validate() ⇒ 400 bad_request
  (实测非法 kind 返回 400 且 models.json 完全不动,而非 500 静默失败)
- 前端:新增 LlmProviderRouting(推理形状下拉 + multimodal 开关 + 按角色路由编辑器);
  目录能力位改三态(true/false/未标注),「未标注」不再谎称「不支持」;目录/角色清单不可用时
  **不阻塞编辑**且与「字段为空」是不同状态;绝无 mock/sample 回退
- 复核:build/vet 绿 + gateway/config 包测试绿 + tsc 0 错 + vite build 成功;2 条变异反证(删 reasoning
  补丁 → 2 例红;删 Group.Validate → 该 400 用例红)已还原
- 注意(主会话已知):npm run build 把新 SPA 写进 frontend/web/dist,而运行中的二进制优先从磁盘读该目录
  ⇒ :10942 目前是「新面板 + 旧后端」,等阶段 5 全绿后按红线「先 build 到位、再一次 restart」切换
This commit is contained in:
AskaEth committed 2026-10-04 13:06:54 +08:00
1 parent 8890c30bb5
commit 1ac02bd77e
12 files changed
+998 -85

No files matched your search

+9 -13
View File
@@ -274,24 +274,20 @@ func (s *Server) adminListIoT(w http.ResponseWriter, r *http.Request) {
// adminGetLlm 返回从实时 provider 栈读取的 LLM provider/model
// 配置(models.json,回退到 .env)。API key 绝不返回 ——
// 线上结构中不含 key 字段 —— 因此该 handler
// 不泄露任何敏感信息。
// 不泄露任何敏感信息。除分组本身外还下发**表单选项的取值域**
// (reasoningKinds / personaProviderOptions),使面板的下拉框与后端校验
// 永远同一份来源。
func (s *Server) adminGetLlm(w http.ResponseWriter, r *http.Request) {
groups := s.currentLlmGroups()
providers := make([]AdminLlmProvider, 0, len(groups))
for i, g := range groups {
providers = append(providers, AdminLlmProvider{
ID: g.ID,
Name: providerDisplayName(g),
Provider: g.Provider,
BaseURL: g.BaseURL,
Model: g.Model,
Multimodal: g.Multimodal,
Enabled: i == 0,
Fallback: g.Fallback,
MaxTokens: g.MaxTokens,
})
providers = append(providers, adminLlmProviderDTO(g, providerDisplayName(g), i == 0))
}
writeJSON(w, http.StatusOK, AdminLlmConfig{Providers: providers})
writeJSON(w, http.StatusOK, AdminLlmConfig{
Providers: providers,
ReasoningKinds: runtimeconfig.ReasoningKinds(),
PersonaProviderOptions: runtimeconfig.ProviderNames(),
})
}
// currentLlmGroups 返回要展示的 provider 分组:接线了实时栈时