feat(m174): 助手(AI)提供商配置真接线 + 「测试连接」

设置页新增第 6 组「助手」:提供商四态 / 端点 base_url / 模型名 / API 密钥(默认掩码,
点「显示」才明文)+ 保存 + 测试连接,四类失败(鉴权 / 模型不存在 / 不可达 / 超时)各自
一句文案 + 目标与耗时。

取舍三条:

1. 读写走 `core::setting` 的 schema API(`SettingStore::load` 现读 → `set` → `save`),
   不经 `AppCommand::SetSetting`——那条指令是可序列化 DTO,`ai.api_key` 走它等于让明文进
   事件流/日志。与 `SettingsBridge::persist` 写外观是同一条做法。
2. 「测试连接」不另写一套 HTTP:`unlucky_cli::commands::agent::probe` 现读设置文件、
   交给 `RigProvider`(真 provider)发一次最小补全,带 8 秒时限;分类只看错误文本
   (rig 只给 Display),四类各有一条真 TCP 假服务器用例钉住。
3. `ProviderKind` 补 `from_setting` / `setting_value`:serde 的 `rename_all = snake_case`
   产出 `open_ai_compatible`,与 schema 的 `openai_compatible` 不是同一个词——这正是
   M174 之前「agent 侧一次都没读过设置」的根因。

守卫(都做变异验证,见 mission 报告):密钥不出 `Debug`/`detail`/DTO;未配置时工厂构造
计数为 0;改完 base_url 后探测打到新地址;空/非法值被 schema 拦下且文件不动。

i18n:49 条中英各一(金表按 `Key::ALL` 位置插入);presenter 的 ai_group 补上 schema 允许
的 `disabled` 选项与一行「已配置 N 字符」的只读状态(仍然不显示值)。
This commit is contained in:
AskaEth committed 2026-11-08 15:57:25 +08:00
1 parent 82f3bbbff6
commit 9cb605f316
23 files changed
+2939 -73

No files matched your search

+53
View File
@@ -29,6 +29,59 @@ pub(super) const ROWS: &[(&str, &str, &str)] = &[
("SettingsAppearanceCornerSquare", "Square", "直角"),
("SettingsAppearanceCornerHint", "On Windows 11 and Server 2025 we ask the system for rounded corners; Windows 10 keeps square corners. On macOS and Linux the desktop's own rules apply. We never draw corners ourselves.", "Windows 11 与 Windows Server 2025 上我们请求系统处理外框圆角;Windows 10 保持直角;macOS 与 Linux 交给桌面合成器自己的规则;我们不自己画圆角。"),
("SettingsAppearanceCornerSuspended", "Not in effect right now: window transparency is below 100%. Setting it back to 100% restores the rounded corners.", "当前因整窗透明度不生效:把整窗透明度调回 100% 圆角即恢复。"),
// M174:设置页「助手(AI)」分组(`catalog/settings/ai.rs` 的 `settings_ai_entries`)。
// 位置就是装配链里那个域的位置:`settings_ai_entries` 在 `settings_download_entries` 之后、
// `core_text_entries` 之前,所以这几行必须落在 `SettingsAppearanceCornerSuspended` 与
// `CoreTextUntranslated` 之间(顺序 = `Key::ALL`)。
("SettingsGroupAssistant", "Assistant", "助手"),
("SettingsAiStatusLabel", "Status: {status}", "状态:{status}"),
("SettingsAiStatusUnconfigured", "not configured", "未配置"),
("SettingsAiStatusConfigured", "configured", "已配置"),
("SettingsAiStatusVerified", "verified", "连接已通过"),
("SettingsAiStatusTestFailed", "test failed", "测试失败"),
("SettingsAiEnable", "Enable the assistant", "启用助手"),
("SettingsAiEnableHint", "With this off, the assistant stays quiet; crash diagnosis from the rule engine keeps working.", "关掉之后助手不再工作;规则引擎的崩溃诊断照常可用。"),
("SettingsAiProviderLabel", "Provider", "提供商"),
("SettingsAiProviderOpenAi", "OpenAI compatible", "OpenAI 兼容"),
("SettingsAiProviderAnthropic", "Anthropic", "Anthropic 原生"),
("SettingsAiProviderOllama", "Ollama", "Ollama 原生"),
("SettingsAiProviderDisabled", "Disabled", "已禁用"),
("SettingsAiBaseUrl", "Endpoint (base_url)", "端点(base_url)"),
("SettingsAiBaseUrlPlaceholder", "http://127.0.0.1:8080/v1", "例:http://127.0.0.1:8080/v1"),
("SettingsAiBaseUrlHint", "The /v1 root of an OpenAI-compatible service. Leave empty to use the provider default.", "OpenAI 兼容服务的 /v1 根地址;留空则用该提供商的默认端点。"),
("SettingsAiEffective", "Effective: {value}", "生效:{value}"),
("SettingsAiModel", "Model name", "模型名称"),
("SettingsAiModelPlaceholder", "deepseek-chat", "例:deepseek-chat"),
("SettingsAiApiKey", "API key", "API 密钥"),
("SettingsAiApiKeyPlaceholder", "Paste the key", "粘贴密钥"),
("SettingsAiApiKeyConfigured", "A key is stored ({chars} characters). Leave this empty to keep it.", "已保存密钥({chars} 个字符)。留空则保持不变。"),
("SettingsAiApiKeyMissing", "No key stored yet", "还没有保存密钥"),
("SettingsAiShow", "Show", "显示"),
("SettingsAiHide", "Hide", "隐藏"),
("SettingsAiSave", "Save", "保存"),
("SettingsAiTest", "Test connection", "测试连接"),
("SettingsAiTesting", "Testing…", "正在测试…"),
("SettingsAiSaved", "Saved. It takes effect immediately, no restart needed.", "已保存,立刻生效,不用重启。"),
("SettingsAiRefused", "Not saved: {reason}", "未保存:{reason}"),
("SettingsAiUnsaved", "There are unsaved changes.", "有未保存的改动。"),
("SettingsAiNoStorage", "No settings file is available in this run, so nothing can be saved or tested.", "这一次运行没有可用的设置文件,保存与测试都做不了。"),
("SettingsAiTestDisabled", "Fill in the missing field before testing: {missing}.", "先补上这一项再测试:{missing}。"),
("SettingsAiMissingDisabled", "the assistant is disabled", "助手处于关闭状态"),
("SettingsAiMissingBaseUrl", "the endpoint address", "端点地址"),
("SettingsAiMissingModel", "the model name", "模型名称"),
("SettingsAiMissingApiKey", "the API key", "API 密钥"),
("SettingsAiReasonProvider", "the provider value is not recognised", "提供商取值不认识"),
("SettingsAiReasonBaseUrl", "the endpoint must start with http:// or https://", "端点必须以 http:// 或 https:// 开头"),
("SettingsAiReasonModel", "the model name is required", "必须填模型名称"),
("SettingsAiTestPassed", "Connected — the endpoint answered.", "连接通过 —— 端点有正常回应。"),
("SettingsAiTestAuth", "Authentication failed: the endpoint rejected the key.", "鉴权失败:端点拒绝了这个密钥。"),
("SettingsAiTestModel", "The endpoint answered, but this model does not exist.", "端点通了,但没有这个模型。"),
("SettingsAiTestUnreachable", "The endpoint is unreachable.", "端点不可达。"),
("SettingsAiTestTimeout", "Timed out while waiting for the endpoint.", "等端点回应超时了。"),
("SettingsAiTestOther", "The request failed for another reason (see the detail below).", "请求因为别的原因失败了(详情见下)。"),
("SettingsAiTestNotConfigured", "Nothing was sent: the configuration is incomplete.", "什么都没有发出去:配置还不完整。"),
("SettingsAiTestTarget", "Target: {base_url} · model {model} · {ms} ms", "目标:{base_url} · 模型 {model} · {ms} 毫秒"),
("SettingsAiTestDetail", "Detail: {detail}", "详情:{detail}"),
("CoreTextUntranslated", "[system text not translated]", "[未翻译的系统文案]"),
("DownloadTitle", "Version management", "版本管理"),
("DownloadSubtitle", "Manage versions and loaders: install, upgrade, repair", "管理版本与加载器:安装、升级、修复"),