前提修正
标题原本的描述是「可选信息当前都是必填」。逐字段核对前后端后,实际情况比这个描述小得多 —— 大部分 required 字段在后端确实是必填,放开会导致写入失败。所以本 issue 的范围是:只放开那些「前端标了必填、但后端允许为空」的字段。
核对结果
ProvidersPage.tsx — 三个 required 全部是真必填,不动
| 字段 |
前端 |
后端 |
id |
required + pattern(:133-141) |
真必填,internal/provider/store.go:208-210 |
name |
required(:145) |
真必填,store.go:211-213 |
base_url |
required + type=url(:149) |
真必填,store.go:214-216 → ValidateBaseURL 空即报错 |
anthropic_base_url |
已可选 |
一致 |
home |
已可选 |
一致 |
api_key |
已可选 |
一致,validateEntry 不检查 |
后端 storedProvider(store.go:34-40)的 omitempty 分布恰好与必填集合对应:home、anthropic_base_url、api_key 有 omitempty,name 和 base_url 没有。前后端在这里是一致的。
ProfilesPage.tsx — 一处确凿的过严
| 字段 |
前端 |
后端 |
id |
required(:154-162) |
真必填,internal/profile/store.go:94-99 |
label |
required(:166) |
允许为空 → fallback 到已存 label → 再 fallback 到 ID:internal/profile/write.go:71-74 |
model |
required(:178) |
真必填,write.go:50-53(注意 Store.Save 不做模型自动解析,与 ActivateAgent 不同) |
label 是本 issue 的主要目标。除了去掉 :166 的 required 属性,还要从 ProfilesPage.tsx:61 的 canSave 门禁里去掉 editor.label.trim()。
顺带说明一个容易误判的点:profile.Profile 里 Model 是 *string 指针(store.go:30-42),看起来像可选,但 write.go:50-53 强制非空。指针类型在这里不代表可选,不要据此放开 model。
AgentDetailPage.tsx — 同类问题,但归属另一个 issue
:80 的 probeState === "success" 和 :79 的 canProbe = Boolean(apiKey) 也是「前端比后端严」:后端 ActivateAgent 从不要求 probe,且 API Key 有三级 fallback(internal/app/agent.go:92-102)。
这两项放在 #5 里处理,因为它们和「让 Agent 配置可达」是同一条用户路径上的问题。
方案
ProfilesPage.tsx:166 去掉 required,:61 的 canSave 去掉 label 条件
- label 输入的 placeholder 或辅助文案说明「留空则用 ID」,让 fallback 行为对用户可见 —— 否则用户会疑惑保存后名字为什么变了
- 补测试:label 留空时能保存,且保存结果的 label 等于 ID
验收
- Profile 的 label 留空可保存,落盘 label 为 ID
- ProvidersPage 的必填项保持不变(放开会导致后端拒绝,是回归)
- 前端不再存在「标了 required 但后端允许为空」的字段
后续建议(不在本 issue 范围)
前后端校验规则目前是两处独立维护的,本次核对就是靠人工逐条比对发现的偏差。如果这类不一致反复出现,值得考虑让校验规则有单一真源(比如后端导出校验元数据给前端消费),但那是独立的架构改动。
前提修正
标题原本的描述是「可选信息当前都是必填」。逐字段核对前后端后,实际情况比这个描述小得多 —— 大部分 required 字段在后端确实是必填,放开会导致写入失败。所以本 issue 的范围是:只放开那些「前端标了必填、但后端允许为空」的字段。
核对结果
ProvidersPage.tsx — 三个 required 全部是真必填,不动
id:133-141)internal/provider/store.go:208-210name:145)store.go:211-213base_url:149)store.go:214-216→ValidateBaseURL空即报错anthropic_base_urlhomeapi_keyvalidateEntry不检查后端
storedProvider(store.go:34-40)的 omitempty 分布恰好与必填集合对应:home、anthropic_base_url、api_key有 omitempty,name和base_url没有。前后端在这里是一致的。ProfilesPage.tsx — 一处确凿的过严
id:154-162)internal/profile/store.go:94-99label:166)internal/profile/write.go:71-74model:178)write.go:50-53(注意Store.Save不做模型自动解析,与 ActivateAgent 不同)label是本 issue 的主要目标。除了去掉:166的required属性,还要从ProfilesPage.tsx:61的canSave门禁里去掉editor.label.trim()。顺带说明一个容易误判的点:
profile.Profile里Model是*string指针(store.go:30-42),看起来像可选,但write.go:50-53强制非空。指针类型在这里不代表可选,不要据此放开 model。AgentDetailPage.tsx — 同类问题,但归属另一个 issue
:80的probeState === "success"和:79的canProbe = Boolean(apiKey)也是「前端比后端严」:后端ActivateAgent从不要求 probe,且 API Key 有三级 fallback(internal/app/agent.go:92-102)。这两项放在 #5 里处理,因为它们和「让 Agent 配置可达」是同一条用户路径上的问题。
方案
ProfilesPage.tsx:166去掉required,:61的canSave去掉 label 条件验收
后续建议(不在本 issue 范围)
前后端校验规则目前是两处独立维护的,本次核对就是靠人工逐条比对发现的偏差。如果这类不一致反复出现,值得考虑让校验规则有单一真源(比如后端导出校验元数据给前端消费),但那是独立的架构改动。