feat(keyboard): ship AI mode surface with streaming search answers

Add the AI keyboard tab, Agent settings, and user-owned LLM key path for 1.7.0, including streaming answers and web-search transports without the built-in DeepSeek fallback.
This commit is contained in:
Rocky
2026-08-11 01:06:27 +08:00
parent f6212dcd2c
commit 3de665d254
81 changed files with 4467 additions and 398 deletions
@@ -42,10 +42,7 @@ public struct AppGroupPersistor {
state.handednessPreference = store.handednessPreference
state.cursorDragNavigationEnabled = store.cursorDragNavigationEnabled
state.keyboardHapticIntensity = store.keyboardHapticIntensity
state.micDisabled = store.isCloudAPIKeyMissingForVoiceInput
state.micDisabledHint = store.isCloudAPIKeyMissingForVoiceInput
? ExtL10n.string("keyboard.mic.disabled.missingApiKey")
: ""
applyAPIKeyAvailability(store: store, into: state)
#if DEBUG
// Print a masked view of the live App Group config so we can see
@@ -95,10 +92,26 @@ public struct AppGroupPersistor {
state.handednessPreference = store.handednessPreference
state.cursorDragNavigationEnabled = store.cursorDragNavigationEnabled
state.keyboardHapticIntensity = store.keyboardHapticIntensity
state.micDisabled = store.isCloudAPIKeyMissingForVoiceInput
state.micDisabledHint = store.isCloudAPIKeyMissingForVoiceInput
? ExtL10n.string("keyboard.mic.disabled.missingApiKey")
: ""
applyAPIKeyAvailability(store: store, into: state)
}
/// Cloud without ASR/LLM keys blocks the mic. Local ASR still works when
/// the polish key is missing show a soft tip above the mic instead.
private func applyAPIKeyAvailability(
store: AppGroupStore,
into state: KeyboardViewController.State
) {
state.aiServiceAvailable = !store.isPolishKeyMissing
if store.isCloudAPIKeyMissingForVoiceInput {
state.micDisabled = true
state.micDisabledHint = ExtL10n.string("keyboard.mic.disabled.missingApiKey")
} else if store.isPolishKeyMissing {
state.micDisabled = false
state.micDisabledHint = ExtL10n.string("keyboard.mic.hint.missingPolishApiKey")
} else {
state.micDisabled = false
state.micDisabledHint = ""
}
}
/// Persist `mode` to the App Group store.