- 合并 LLM Provider Tab 与 ASR Provider Tab 到同一个「配置」页: 顶部 LLM 模型 chip 行 + 表单,下方 ASR 语音 chip 行 + provider 专属字段, 底部 borderedProminent .large「保存」按钮统一提交。 - 切 chip 不再立即写盘——所有改动在内存草稿里积攒,点保存才写 vault / UserDefaults 并 post .openLessCredentialsChanged。 - 火山引擎 3 字段(APP ID / Access Token / Resource ID)从 SettingsHubTab 搬到 「配置」页 ASR 段;SettingsHubTab 简化为录音快捷键 / 授权 / 隐私 / 关于 + provider 概览。 - 侧边栏顺序调整为 首页 → 历史记录 → 词汇表 → 风格 → 配置 → 设置 → 帮助中心, 「配置」紧靠「设置」之上。 - ASRProviderRegistry 新增两条预设: * aliyun-paraformer (DashScope 流式 paraformer-realtime-v2) * custom-openai-whisper (OpenAI 兼容批量 Whisper API) 这两类 provider 的 chip 与表单已就绪;运行期具体识别由并行分支补齐。 - 删除 LLMProvidersTab.swift / ASRProvidersTab.swift;AddLLMProviderSheet 搬到 ProvidersConfigTab.swift 同文件。
72 lines
3.3 KiB
Swift
72 lines
3.3 KiB
Swift
import Foundation
|
||
|
||
/// ASR provider 预设注册表。
|
||
///
|
||
/// 集中维护"用户能开箱即用的 ASR 供应商列表"——M1 仅有火山引擎(云端流式)和
|
||
/// macOS 本地 Apple Speech(离线 / 系统内置)。UI 层用它生成 ASR Tab 的切换列表
|
||
/// 与帮助文案;运行期由 DictationCoordinator.makeASRProvider() 据 providerId 路由。
|
||
///
|
||
/// 与 `LLMProviderRegistry` 的差异:
|
||
/// - LLM 全是 OpenAI 兼容协议,可以共用同一份 OpenAICompatibleConfig;ASR 各家协议
|
||
/// 差异大(火山自有 WebSocket framing,Apple 是系统 SDK,Whisper 是 HTTP 批量),
|
||
/// 所以 preset 只暴露最小元数据(id + displayName + mode + helpText);具体配置
|
||
/// 字段由 provider 各自的 UI 段提供。
|
||
/// - 这里**不**暴露 baseURL / apiKey 之类的字段——provider 的字段由 SettingsHubTab
|
||
/// 或新的 ASR Tab 各自承载(火山 3 字段在 SettingsHubTab;Apple Speech 无字段)。
|
||
public enum ASRProviderRegistry {
|
||
/// 单条预设记录。
|
||
public struct Preset: Sendable, Hashable {
|
||
public let providerId: String
|
||
public let displayName: String
|
||
public let mode: ASRMode
|
||
/// "这家 provider 是什么 / 怎么用" 的提示文案;UI 在切换列表下面展示。
|
||
public let helpText: String
|
||
|
||
public init(
|
||
providerId: String,
|
||
displayName: String,
|
||
mode: ASRMode,
|
||
helpText: String
|
||
) {
|
||
self.providerId = providerId
|
||
self.displayName = displayName
|
||
self.mode = mode
|
||
self.helpText = helpText
|
||
}
|
||
}
|
||
|
||
/// 内置的 ASR provider 预设。
|
||
/// 顺序即为 UI 列表的展示顺序——火山在前(旧用户默认),Apple Speech、阿里、自定义 Whisper 依次展开。
|
||
public static let presets: [Preset] = [
|
||
Preset(
|
||
providerId: "volcengine",
|
||
displayName: "火山引擎 (Volcengine)",
|
||
mode: .streaming,
|
||
helpText: "需要在火山引擎控制台获取 App ID / Access Token / Resource ID。"
|
||
),
|
||
Preset(
|
||
providerId: "apple-speech",
|
||
displayName: "macOS 本地 (Apple Speech)",
|
||
mode: .streaming,
|
||
helpText: "使用 macOS 内置语音识别。免费、离线(zh-CN 在 Apple Silicon 上支持纯离线),不需要 API key。首次切换时系统会请求语音识别权限。"
|
||
),
|
||
Preset(
|
||
providerId: "aliyun-paraformer",
|
||
displayName: "阿里通义 Paraformer (DashScope)",
|
||
mode: .streaming,
|
||
helpText: "DashScope paraformer-realtime-v2 流式语音识别。如果你的 LLM 已经填了阿里通义 DashScope 的 API Key,会自动复用同一个 key。"
|
||
),
|
||
Preset(
|
||
providerId: "custom-openai-whisper",
|
||
displayName: "自定义 OpenAI 兼容 (Whisper)",
|
||
mode: .batch,
|
||
helpText: "兼容 OpenAI Whisper API(multipart/form-data POST)的任意端点:Groq、DeepInfra、OpenAI、自建反代等。录完整段音频后整段上传转写,长录音会等几秒。"
|
||
),
|
||
]
|
||
|
||
/// 根据 providerId 查预设;未知 id 返回 nil。
|
||
public static func preset(for providerId: String) -> Preset? {
|
||
presets.first { $0.providerId == providerId }
|
||
}
|
||
}
|