Browse Source
feat: persistent voice commands execution log and robust ZWNJ-tolerant Antigravity matcher
main
feat: persistent voice commands execution log and robust ZWNJ-tolerant Antigravity matcher
main
4 changed files with 605 additions and 265 deletions
-
1src/AppDelegate.swift
-
32src/StatusBarController.swift
-
678src/VoiceCommandExecutor.swift
-
119src/VoiceCommandLogger.swift
678
src/VoiceCommandExecutor.swift
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,119 @@ |
|||
import Foundation |
|||
import Cocoa |
|||
|
|||
public final class VoiceCommandLogger { |
|||
public static let shared = VoiceCommandLogger() |
|||
|
|||
public let logFileURL: URL |
|||
private let queue = DispatchQueue(label: "com.soniox.voicecommandlogger", qos: .utility) |
|||
private let dateFormatter: DateFormatter |
|||
|
|||
private init() { |
|||
let appSupport = FileManager.default.urls(for: .applicationSupportDirectory, in: .userDomainMask).first! |
|||
let dir = appSupport.appendingPathComponent("SonioxVoice") |
|||
try? FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) |
|||
self.logFileURL = dir.appendingPathComponent("voice_commands.log") |
|||
|
|||
self.dateFormatter = DateFormatter() |
|||
self.dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss" |
|||
|
|||
ensureLogHeader() |
|||
} |
|||
|
|||
private func ensureLogHeader() { |
|||
if !FileManager.default.fileExists(atPath: logFileURL.path) { |
|||
let header = """ |
|||
================================================================================ |
|||
Soniox Voice Commands Execution & Debug Log |
|||
Log Location: \(logFileURL.path) |
|||
Started: \(dateFormatter.string(from: Date())) |
|||
================================================================================ |
|||
|
|||
|
|||
""" |
|||
try? header.write(to: logFileURL, atomically: true, encoding: .utf8) |
|||
} |
|||
} |
|||
|
|||
public func logCommand( |
|||
rawSpeech: String, |
|||
body: String, |
|||
normalized: String, |
|||
actionCategory: String, |
|||
actionDetail: String, |
|||
status: String |
|||
) { |
|||
queue.async { |
|||
let timestamp = self.dateFormatter.string(from: Date()) |
|||
let statusIcon = status.contains("SUCCESS") ? "✅" : "❌" |
|||
let entry = """ |
|||
-------------------------------------------------------------------------------- |
|||
[\(timestamp)] ⚡️ VOICE SLASH COMMAND |
|||
🎤 Raw Soniox Speech: "\(rawSpeech)" |
|||
✂️ Extracted Body: "\(body)" |
|||
🔍 Normalized: "\(normalized)" |
|||
🏷️ Category: \(actionCategory) |
|||
🎯 Executed Action: \(actionDetail) |
|||
\(statusIcon) Status: \(status) |
|||
-------------------------------------------------------------------------------- |
|||
|
|||
""" |
|||
self.appendToFile(text: entry) |
|||
} |
|||
} |
|||
|
|||
public func logDictation( |
|||
rawSpeech: String, |
|||
processed: String |
|||
) { |
|||
queue.async { |
|||
let timestamp = self.dateFormatter.string(from: Date()) |
|||
let entry = """ |
|||
-------------------------------------------------------------------------------- |
|||
[\(timestamp)] ✍️ VOICE DICTATION (Normal Speech) |
|||
🎤 Raw Soniox Speech: "\(rawSpeech)" |
|||
📝 Processed Text: "\(processed)" |
|||
📋 Destination: Pasted to Frontmost Application |
|||
✅ Status: SUCCESS |
|||
-------------------------------------------------------------------------------- |
|||
|
|||
""" |
|||
self.appendToFile(text: entry) |
|||
} |
|||
} |
|||
|
|||
private func appendToFile(text: String) { |
|||
guard let data = text.data(using: .utf8) else { return } |
|||
if let fileHandle = try? FileHandle(forWritingTo: logFileURL) { |
|||
fileHandle.seekToEndOfFile() |
|||
fileHandle.write(data) |
|||
try? fileHandle.close() |
|||
} else { |
|||
try? data.write(to: logFileURL, options: .atomic) |
|||
} |
|||
} |
|||
|
|||
public func clearLog() { |
|||
queue.async { |
|||
let timestamp = self.dateFormatter.string(from: Date()) |
|||
let header = """ |
|||
================================================================================ |
|||
Soniox Voice Commands Execution & Debug Log (Cleared) |
|||
Reset At: \(timestamp) |
|||
================================================================================ |
|||
|
|||
|
|||
""" |
|||
try? header.write(to: self.logFileURL, atomically: true, encoding: .utf8) |
|||
} |
|||
} |
|||
|
|||
public func openLogInViewer() { |
|||
// Open log in default text editor or Console |
|||
NSWorkspace.shared.open(logFileURL) |
|||
} |
|||
|
|||
public func openLogFolder() { |
|||
NSWorkspace.shared.activateFileViewerSelecting([logFileURL]) |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue