feat(translation-polish-2): local-engine dedicated section + PreconfiguredKeys for DeepSeek
- Add PreconfiguredKeys.swift: placeholder constant for the DeepSeek
API key the local engine uses. DEBUG build asserts at launch when
the placeholder is still in place so nobody ships an always-401
build by accident. Replace TODO_FILL_LATER_DEEPSEEK_KEY before
distributing.
- PolishingService.polishRemote:
* Adopted (A) path: when effective provider is DeepSeek, take the
apiKey from PreconfiguredKeys.deepseek instead of store.apiKey.
Refuse the round-trip with PolishError.missingAPIKey when the
placeholder is still in place.
* Adopted fix for pre-existing typo: store.model.isEmpty ?
preset.defaultModel : store.model (the right-hand side was
defaultModel on both branches, silently ignoring the user's
custom model field).
- LocalEngineSettingsRows.LocalModelsGroup:
* Dropped the inline 'uses DeepSeek' caption — it added visual
weight without telling the user anything they couldn't infer.
* Translation row now lives inside the group so the local engine
reads as one cohesive card.
* Group owns its surface card chrome (palette.surface + rounded
border) — callers no longer need to wrap it externally.
- SettingsView:
* languageAndModelsSection: dropped the trailing TranslationPickerRow
and the inner LocalModelsGroup (now lifted to its own section).
* New localEngineSettingsSection: renders only when
engineMode == 'local', wrapping LocalModelsGroup with a
'settings.localEngine.title' header.
* body: added the new section between languageAndModelsSection and
the cloud-only systemPromptLinkSection.
- Localizable.strings (en + zh-Hans):
* Removed settings.localModels.cloudPolish.caption (no references).
* Added settings.localEngine.title = 'Local engine' / '本地引擎'.
DeepSeek key pre-fill tripwire + local-engine UI cohesion. No main
merge, no PR.
This commit is contained in:
@@ -109,8 +109,8 @@ public actor PolishingService {
|
||||
// v0.2.1 follow-up: when the caller pins a provider id (the
|
||||
// local engine pins DeepSeek) we still want to honor the
|
||||
// injected test client, but we have to re-derive the
|
||||
// preset/baseURL/model triplet from the *override* so the
|
||||
// injected client gets the right values when it's nil.
|
||||
// preset/baseURL/model/apiKey quartet from the *override* so
|
||||
// the injected client gets the right values when it's nil.
|
||||
let effectiveProviderId = providerIdOverride ?? store.providerId
|
||||
let client: LLMClient
|
||||
if let injectedClient {
|
||||
@@ -118,8 +118,25 @@ public actor PolishingService {
|
||||
} else {
|
||||
let preset = LLMProvider.provider(id: effectiveProviderId)
|
||||
let baseURL = store.baseURL.isEmpty ? preset.defaultBaseURL : store.baseURL
|
||||
let model = store.model.isEmpty ? preset.defaultModel : preset.defaultModel
|
||||
client = OpenAICompatibleClient(baseURL: baseURL, apiKey: store.apiKey, model: model)
|
||||
// Pre-existing typo fix: the user-overridden `store.model`
|
||||
// path was returning `preset.defaultModel` on both branches,
|
||||
// silently ignoring the user's custom model field. Restore
|
||||
// the asymmetry so the user override actually wins.
|
||||
let model = store.model.isEmpty ? preset.defaultModel : store.model
|
||||
let apiKey: String
|
||||
if effectiveProviderId == "deepseek" {
|
||||
let preconfigured = PreconfiguredKeys.deepseek
|
||||
if preconfigured == "TODO_FILL_LATER_DEEPSEEK_KEY" {
|
||||
// Placeholder still in place — refuse the round-
|
||||
// trip so the UI can surface a "build not
|
||||
// configured" hint instead of a 401.
|
||||
throw PolishError.missingAPIKey
|
||||
}
|
||||
apiKey = preconfigured
|
||||
} else {
|
||||
apiKey = store.apiKey
|
||||
}
|
||||
client = OpenAICompatibleClient(baseURL: baseURL, apiKey: apiKey, model: model)
|
||||
}
|
||||
let prompt = resolvedSystemPrompt(for: mode, override: systemPrompt)
|
||||
let budget = effectiveTimeout(for: trimmed)
|
||||
|
||||
Reference in New Issue
Block a user