feat(keyboard): improve typing, voice flow, and polish reliability

Reduce extension memory pressure and delivery races while adding richer candidates, tactile feedback, and safer two-level creative polishing.
This commit is contained in:
Rocky
2026-08-05 21:39:31 +08:00
parent 38e5ad570d
commit 31f5937a7f
177 changed files with 8343 additions and 3904 deletions
@@ -28,10 +28,17 @@ public enum TranscriptPostProcessor: Sendable {
/// - **Tier 2 (510 CJK):** skip only low-value acks / closings
/// (e.g. "", ""); keep questions, invites,
/// and contentful short lines for polish / ASR repair.
public static func shouldSkipLLM(for text: String) -> Bool {
public static func shouldSkipLLM(
for text: String,
styleID: String? = nil
) -> Bool {
let trimmed = text.trimmingCharacters(in: .whitespacesAndNewlines)
guard !trimmed.isEmpty else { return false }
if hasStructureSignal(in: trimmed) { return false }
// Every fun personality handles short and long drafts in one prompt.
if let styleID, PolishStylePackCatalog.isFunPersonality(id: styleID) {
return false
}
let cjkCount = trimmed.unicodeScalars.filter(isCJKScalar).count
if cjkCount > 0 {
@@ -59,9 +66,9 @@ public enum TranscriptPostProcessor: Sendable {
let cjk = stripped.unicodeScalars.filter(isCJKScalar).count
if stripped.count <= 4 && cjk <= 4 { return true }
if PolishRouter.hasCommunicativeSignal(stripped) { return false }
if PolishRouter.hasOpponentQuote(stripped) { return false }
if PolishRouter.hasConcreteEntity(stripped) { return false }
if hasCommunicativeSignal(stripped) { return false }
if hasOpponentQuote(stripped) { return false }
if hasConcreteEntity(stripped) { return false }
for pattern in tier2SkipPatterns {
if stripped.range(of: pattern, options: .regularExpression) != nil {
@@ -84,6 +91,32 @@ public enum TranscriptPostProcessor: Sendable {
#"^(晚点再说|待会联系|先这样吧|马上到了)$"#,
]
private static func hasCommunicativeSignal(_ text: String) -> Bool {
if text.contains("") || text.contains("?") { return true }
let patterns = [
#"吗|么|怎么|什么|哪|谁|为何|为什么|为啥"#,
#"能不能|可不可以|要不要|行不行"#,
#"回他|回她"#,
#"约|见面|吃饭|电影"#,
]
return patterns.contains { text.range(of: $0, options: .regularExpression) != nil }
}
private static func hasOpponentQuote(_ text: String) -> Bool {
let markers = ["回他", "回她", "对方", "他说", "她说", "你说的", "你这叫", "大家都"]
return markers.contains { text.contains($0) }
}
private static func hasConcreteEntity(_ text: String) -> Bool {
let entities = [
"面膜", "防晒", "口红", "粉底", "洗发", "咖啡", "火锅", "酒店", "餐厅",
"方案", "接口", "测试", "Key", "老板", "电影", "地铁", "快递", "会议",
"周报", "加班", "机票", "医院", "课程", "健身", "外卖", "微信", "项目",
"发布", "文档", "密码", "充电器", "门卡",
]
return entities.contains { text.contains($0) }
}
private static let leadingFillers = [
"怎么说呢", "就是说", "然后那个", "嗯那个", "那个", "", "",
]