import Foundation public enum HotkeyEvent: Equatable, Sendable { case pressed case released } public enum DictationState: Equatable, Sendable { case idle case recording case transcribing case inserting } public struct CleaningContext: Sendable { public init() {} } public protocol AudioRecording { func start() throws /// Stops recording and returns all captured 16 kHz mono Float samples. func stop() -> [Float] } public protocol Transcriber { func transcribe(_ samples: [Float]) async throws -> String /// Biases decoding towards `vocabulary`. Engines without bias support ignore the list. func transcribe(_ samples: [Float], vocabulary: [String]) async throws -> String } public extension Transcriber { func transcribe(_ samples: [Float], vocabulary: [String]) async throws -> String { try await transcribe(samples) } } /// One replacement made by the dictionary correction pass. /// `start`/`length` are UTF-16 offsets into the corrected text. public struct AppliedCorrection: Equatable, Codable, Sendable { public var heard: String public var wrote: String public var rule: String public var start: Int public var length: Int public init(heard: String, wrote: String, rule: String, start: Int, length: Int) { self.heard = heard self.wrote = wrote self.rule = rule self.start = start self.length = length } } public struct CorrectionResult: Equatable, Sendable { public var text: String public var corrections: [AppliedCorrection] public init(text: String, corrections: [AppliedCorrection]) { self.text = text self.corrections = corrections } } public protocol TextCorrecting { func correct(_ text: String) -> CorrectionResult } /// A finished dictation, emitted just before the text is inserted. public struct DictationResult: Equatable, Sendable { public var date: Date public var duration: TimeInterval public var rawText: String public var finalText: String public var corrections: [AppliedCorrection] public init(date: Date, duration: TimeInterval, rawText: String, finalText: String, corrections: [AppliedCorrection]) { self.date = date self.duration = duration self.rawText = rawText self.finalText = finalText self.corrections = corrections } } public protocol Cleaner { func clean(_ text: String, context: CleaningContext) async throws -> String } public protocol TextInserting { func insert(_ text: String) async throws }