Added debugging for screen capture services
This commit is contained in:
parent
61453740cd
commit
214d71c29d
@ -468,7 +468,7 @@
|
|||||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 99;
|
CURRENT_PROJECT_VERSION = 0.99;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"VoiceInk/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"VoiceInk/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = V6J6A3VWY2;
|
DEVELOPMENT_TEAM = V6J6A3VWY2;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
@ -501,7 +501,7 @@
|
|||||||
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
"CODE_SIGN_IDENTITY[sdk=macosx*]" = "Apple Development";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
COMBINE_HIDPI_IMAGES = YES;
|
COMBINE_HIDPI_IMAGES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 99;
|
CURRENT_PROJECT_VERSION = 0.99;
|
||||||
DEVELOPMENT_ASSET_PATHS = "\"VoiceInk/Preview Content\"";
|
DEVELOPMENT_ASSET_PATHS = "\"VoiceInk/Preview Content\"";
|
||||||
DEVELOPMENT_TEAM = V6J6A3VWY2;
|
DEVELOPMENT_TEAM = V6J6A3VWY2;
|
||||||
ENABLE_HARDENED_RUNTIME = YES;
|
ENABLE_HARDENED_RUNTIME = YES;
|
||||||
|
|||||||
@ -10,8 +10,8 @@ enum EnhancementMode {
|
|||||||
|
|
||||||
class AIEnhancementService: ObservableObject {
|
class AIEnhancementService: ObservableObject {
|
||||||
private let logger = Logger(
|
private let logger = Logger(
|
||||||
subsystem: "com.voiceink.enhancement",
|
subsystem: "com.prakashjoshipax.VoiceInk",
|
||||||
category: "AI"
|
category: "aienhancement"
|
||||||
)
|
)
|
||||||
|
|
||||||
@Published var isEnhancementEnabled: Bool {
|
@Published var isEnhancementEnabled: Bool {
|
||||||
@ -234,19 +234,27 @@ class AIEnhancementService: ObservableObject {
|
|||||||
|
|
||||||
// Handle Ollama requests differently
|
// Handle Ollama requests differently
|
||||||
if aiService.selectedProvider == .ollama {
|
if aiService.selectedProvider == .ollama {
|
||||||
logger.info("AI Enhancement: Using Ollama for enhancement")
|
logger.notice("📤 Request to Ollama")
|
||||||
|
logger.notice("🤖 System: \(systemMessage)")
|
||||||
|
logger.notice("📝 Sending: \(text)")
|
||||||
do {
|
do {
|
||||||
return try await aiService.enhanceWithOllama(text: text, systemPrompt: systemMessage)
|
let result = try await aiService.enhanceWithOllama(text: text, systemPrompt: systemMessage)
|
||||||
|
logger.notice("✅ Ollama enhancement successful")
|
||||||
|
logger.notice("📝 Received: \(result)")
|
||||||
|
return result
|
||||||
} catch let error as LocalAIError {
|
} catch let error as LocalAIError {
|
||||||
logger.error("AI Enhancement: Ollama error - \(error.localizedDescription)")
|
|
||||||
switch error {
|
switch error {
|
||||||
case .serviceUnavailable:
|
case .serviceUnavailable:
|
||||||
|
logger.error("🔌 Ollama service unavailable")
|
||||||
throw EnhancementError.notConfigured
|
throw EnhancementError.notConfigured
|
||||||
case .modelNotFound:
|
case .modelNotFound:
|
||||||
|
logger.error("🤖 Ollama model not found")
|
||||||
throw EnhancementError.enhancementFailed
|
throw EnhancementError.enhancementFailed
|
||||||
case .serverError:
|
case .serverError:
|
||||||
|
logger.error("🔥 Ollama server error")
|
||||||
throw EnhancementError.serverError
|
throw EnhancementError.serverError
|
||||||
default:
|
default:
|
||||||
|
logger.error("❌ Ollama enhancement failed")
|
||||||
throw EnhancementError.enhancementFailed
|
throw EnhancementError.enhancementFailed
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,16 +298,13 @@ class AIEnhancementService: ObservableObject {
|
|||||||
request.httpBody = try? JSONSerialization.data(withJSONObject: requestBody)
|
request.httpBody = try? JSONSerialization.data(withJSONObject: requestBody)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
logger.info("AI Enhancement: Sending request to Gemini API (attempt \(retryCount + 1))")
|
logger.notice("📤 Request to Gemini")
|
||||||
logger.debug("""
|
logger.notice("🤖 System: \(systemMessage)")
|
||||||
AI Enhancement Debug (Gemini):
|
logger.notice("📝 Sending: \(text)")
|
||||||
System Message: \(systemMessage)
|
|
||||||
Original Text: \(text)
|
|
||||||
""")
|
|
||||||
let (data, response) = try await URLSession.shared.data(for: request)
|
let (data, response) = try await URLSession.shared.data(for: request)
|
||||||
|
|
||||||
guard let httpResponse = response as? HTTPURLResponse else {
|
guard let httpResponse = response as? HTTPURLResponse else {
|
||||||
logger.error("AI Enhancement: Invalid response received from Gemini")
|
logger.error("❌ Invalid Gemini response")
|
||||||
throw EnhancementError.invalidResponse
|
throw EnhancementError.invalidResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -312,39 +317,35 @@ class AIEnhancementService: ObservableObject {
|
|||||||
let parts = content["parts"] as? [[String: Any]],
|
let parts = content["parts"] as? [[String: Any]],
|
||||||
let firstPart = parts.first,
|
let firstPart = parts.first,
|
||||||
let enhancedText = firstPart["text"] as? String else {
|
let enhancedText = firstPart["text"] as? String else {
|
||||||
logger.error("AI Enhancement: Failed to parse Gemini API response")
|
logger.error("❌ Failed to parse Gemini response")
|
||||||
throw EnhancementError.enhancementFailed
|
throw EnhancementError.enhancementFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = enhancedText.trimmingCharacters(in: .whitespacesAndNewlines)
|
let result = enhancedText.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
logger.info("AI Enhancement: Successfully enhanced text using Gemini")
|
logger.notice("✅ Gemini enhancement successful")
|
||||||
logger.debug("""
|
logger.notice("📝 Received: \(result)")
|
||||||
AI Enhancement Debug (Gemini):
|
|
||||||
Original Text: \(text)
|
|
||||||
Enhanced Text: \(result)
|
|
||||||
""")
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
case 401:
|
case 401:
|
||||||
logger.error("AI Enhancement: Authentication failed")
|
logger.error("🔒 Authentication failed")
|
||||||
throw EnhancementError.authenticationFailed
|
throw EnhancementError.authenticationFailed
|
||||||
|
|
||||||
case 429:
|
case 429:
|
||||||
logger.error("AI Enhancement: Rate limit exceeded")
|
logger.error("⏳ Rate limit exceeded")
|
||||||
throw EnhancementError.rateLimitExceeded
|
throw EnhancementError.rateLimitExceeded
|
||||||
|
|
||||||
case 500...599:
|
case 500...599:
|
||||||
logger.error("AI Enhancement: Server error - Status code: \(httpResponse.statusCode)")
|
logger.error("🔥 Server error (\(httpResponse.statusCode))")
|
||||||
throw EnhancementError.serverError
|
throw EnhancementError.serverError
|
||||||
|
|
||||||
default:
|
default:
|
||||||
logger.error("AI Enhancement: Unexpected status code: \(httpResponse.statusCode)")
|
logger.error("❌ Unexpected status (\(httpResponse.statusCode))")
|
||||||
throw EnhancementError.apiError
|
throw EnhancementError.apiError
|
||||||
}
|
}
|
||||||
} catch let error as EnhancementError {
|
} catch let error as EnhancementError {
|
||||||
throw error
|
throw error
|
||||||
} catch {
|
} catch {
|
||||||
logger.error("AI Enhancement: Network error - \(error.localizedDescription)")
|
logger.error("❌ Network error: \(error.localizedDescription)")
|
||||||
|
|
||||||
if retryCount < maxRetries {
|
if retryCount < maxRetries {
|
||||||
try await Task.sleep(nanoseconds: UInt64(pow(2.0, Double(retryCount)) * 1_000_000_000))
|
try await Task.sleep(nanoseconds: UInt64(pow(2.0, Double(retryCount)) * 1_000_000_000))
|
||||||
@ -376,16 +377,13 @@ class AIEnhancementService: ObservableObject {
|
|||||||
request.httpBody = try? JSONSerialization.data(withJSONObject: requestBody)
|
request.httpBody = try? JSONSerialization.data(withJSONObject: requestBody)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
logger.info("AI Enhancement: Sending request to Anthropic API (attempt \(retryCount + 1))")
|
logger.notice("📤 Request to Anthropic")
|
||||||
logger.debug("""
|
logger.notice("🤖 System: \(systemMessage)")
|
||||||
AI Enhancement Debug (Anthropic):
|
logger.notice("📝 Sending: \(text)")
|
||||||
System Message: \(systemMessage)
|
|
||||||
Original Text: \(text)
|
|
||||||
""")
|
|
||||||
let (data, response) = try await URLSession.shared.data(for: request)
|
let (data, response) = try await URLSession.shared.data(for: request)
|
||||||
|
|
||||||
guard let httpResponse = response as? HTTPURLResponse else {
|
guard let httpResponse = response as? HTTPURLResponse else {
|
||||||
logger.error("AI Enhancement: Invalid response received from Anthropic")
|
logger.error("❌ Invalid Anthropic response")
|
||||||
throw EnhancementError.invalidResponse
|
throw EnhancementError.invalidResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -395,39 +393,35 @@ class AIEnhancementService: ObservableObject {
|
|||||||
let content = jsonResponse["content"] as? [[String: Any]],
|
let content = jsonResponse["content"] as? [[String: Any]],
|
||||||
let firstContent = content.first,
|
let firstContent = content.first,
|
||||||
let enhancedText = firstContent["text"] as? String else {
|
let enhancedText = firstContent["text"] as? String else {
|
||||||
logger.error("AI Enhancement: Failed to parse Anthropic API response")
|
logger.error("❌ Failed to parse Anthropic response")
|
||||||
throw EnhancementError.enhancementFailed
|
throw EnhancementError.enhancementFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = enhancedText.trimmingCharacters(in: .whitespacesAndNewlines)
|
let result = enhancedText.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
logger.info("AI Enhancement: Successfully enhanced text using Anthropic")
|
logger.notice("✅ Anthropic enhancement successful")
|
||||||
logger.debug("""
|
logger.notice("📝 Received: \(result)")
|
||||||
AI Enhancement Debug (Anthropic):
|
|
||||||
Original Text: \(text)
|
|
||||||
Enhanced Text: \(result)
|
|
||||||
""")
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
case 401:
|
case 401:
|
||||||
logger.error("AI Enhancement: Authentication failed")
|
logger.error("🔒 Authentication failed")
|
||||||
throw EnhancementError.authenticationFailed
|
throw EnhancementError.authenticationFailed
|
||||||
|
|
||||||
case 429:
|
case 429:
|
||||||
logger.error("AI Enhancement: Rate limit exceeded")
|
logger.error("⏳ Rate limit exceeded")
|
||||||
throw EnhancementError.rateLimitExceeded
|
throw EnhancementError.rateLimitExceeded
|
||||||
|
|
||||||
case 500...599:
|
case 500...599:
|
||||||
logger.error("AI Enhancement: Server error - Status code: \(httpResponse.statusCode)")
|
logger.error("🔥 Server error (\(httpResponse.statusCode))")
|
||||||
throw EnhancementError.serverError
|
throw EnhancementError.serverError
|
||||||
|
|
||||||
default:
|
default:
|
||||||
logger.error("AI Enhancement: Unexpected status code: \(httpResponse.statusCode)")
|
logger.error("❌ Unexpected status (\(httpResponse.statusCode))")
|
||||||
throw EnhancementError.apiError
|
throw EnhancementError.apiError
|
||||||
}
|
}
|
||||||
} catch let error as EnhancementError {
|
} catch let error as EnhancementError {
|
||||||
throw error
|
throw error
|
||||||
} catch {
|
} catch {
|
||||||
logger.error("AI Enhancement: Network error - \(error.localizedDescription)")
|
logger.error("❌ Network error: \(error.localizedDescription)")
|
||||||
|
|
||||||
if retryCount < maxRetries {
|
if retryCount < maxRetries {
|
||||||
try await Task.sleep(nanoseconds: UInt64(pow(2.0, Double(retryCount)) * 1_000_000_000))
|
try await Task.sleep(nanoseconds: UInt64(pow(2.0, Double(retryCount)) * 1_000_000_000))
|
||||||
@ -470,15 +464,16 @@ class AIEnhancementService: ObservableObject {
|
|||||||
request.httpBody = try? JSONSerialization.data(withJSONObject: requestBody)
|
request.httpBody = try? JSONSerialization.data(withJSONObject: requestBody)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
logger.info("AI Enhancement: Sending request to \(self.aiService.selectedProvider.rawValue) API (attempt \(retryCount + 1))")
|
logger.notice("📤 Request to \(self.aiService.selectedProvider.rawValue)")
|
||||||
|
logger.notice("🤖 System: \(systemMessage)")
|
||||||
|
logger.notice("📝 Sending: \(text)")
|
||||||
let (data, response) = try await URLSession.shared.data(for: request)
|
let (data, response) = try await URLSession.shared.data(for: request)
|
||||||
|
|
||||||
guard let httpResponse = response as? HTTPURLResponse else {
|
guard let httpResponse = response as? HTTPURLResponse else {
|
||||||
logger.error("AI Enhancement: Invalid response received from \(self.aiService.selectedProvider.rawValue)")
|
logger.error("❌ Invalid response")
|
||||||
throw EnhancementError.invalidResponse
|
throw EnhancementError.invalidResponse
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle different HTTP status codes
|
|
||||||
switch httpResponse.statusCode {
|
switch httpResponse.statusCode {
|
||||||
case 200:
|
case 200:
|
||||||
guard let jsonResponse = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
guard let jsonResponse = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
|
||||||
@ -486,40 +481,36 @@ class AIEnhancementService: ObservableObject {
|
|||||||
let firstChoice = choices.first,
|
let firstChoice = choices.first,
|
||||||
let message = firstChoice["message"] as? [String: Any],
|
let message = firstChoice["message"] as? [String: Any],
|
||||||
let enhancedText = message["content"] as? String else {
|
let enhancedText = message["content"] as? String else {
|
||||||
logger.error("AI Enhancement: Failed to parse \(self.aiService.selectedProvider.rawValue) API response")
|
logger.error("❌ Failed to parse response")
|
||||||
throw EnhancementError.enhancementFailed
|
throw EnhancementError.enhancementFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
let result = enhancedText.trimmingCharacters(in: .whitespacesAndNewlines)
|
let result = enhancedText.trimmingCharacters(in: .whitespacesAndNewlines)
|
||||||
logger.info("AI Enhancement: Successfully enhanced text using \(self.aiService.selectedProvider.rawValue)")
|
logger.notice("✅ Enhancement successful")
|
||||||
logger.debug("""
|
logger.notice("📝 Received: \(result)")
|
||||||
AI Enhancement Debug:
|
|
||||||
Original Text: \(text)
|
|
||||||
Enhanced Text: \(result)
|
|
||||||
""")
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
case 401:
|
case 401:
|
||||||
logger.error("AI Enhancement: Authentication failed")
|
logger.error("🔒 Authentication failed")
|
||||||
throw EnhancementError.authenticationFailed
|
throw EnhancementError.authenticationFailed
|
||||||
|
|
||||||
case 429:
|
case 429:
|
||||||
logger.error("AI Enhancement: Rate limit exceeded")
|
logger.error("⏳ Rate limit exceeded")
|
||||||
throw EnhancementError.rateLimitExceeded
|
throw EnhancementError.rateLimitExceeded
|
||||||
|
|
||||||
case 500...599:
|
case 500...599:
|
||||||
logger.error("AI Enhancement: Server error - Status code: \(httpResponse.statusCode)")
|
logger.error("🔥 Server error (\(httpResponse.statusCode))")
|
||||||
throw EnhancementError.serverError
|
throw EnhancementError.serverError
|
||||||
|
|
||||||
default:
|
default:
|
||||||
logger.error("AI Enhancement: Unexpected status code: \(httpResponse.statusCode)")
|
logger.error("❌ Unexpected status (\(httpResponse.statusCode))")
|
||||||
throw EnhancementError.apiError
|
throw EnhancementError.apiError
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch let error as EnhancementError {
|
} catch let error as EnhancementError {
|
||||||
throw error
|
throw error
|
||||||
} catch {
|
} catch {
|
||||||
logger.error("AI Enhancement: Network error - \(error.localizedDescription)")
|
logger.error("❌ Network error: \(error.localizedDescription)")
|
||||||
|
|
||||||
if retryCount < maxRetries {
|
if retryCount < maxRetries {
|
||||||
try await Task.sleep(nanoseconds: UInt64(pow(2.0, Double(retryCount)) * 1_000_000_000))
|
try await Task.sleep(nanoseconds: UInt64(pow(2.0, Double(retryCount)) * 1_000_000_000))
|
||||||
|
|||||||
@ -1,11 +1,17 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
import AppKit
|
import AppKit
|
||||||
import Vision
|
import Vision
|
||||||
|
import os
|
||||||
|
|
||||||
class ScreenCaptureService: ObservableObject {
|
class ScreenCaptureService: ObservableObject {
|
||||||
@Published var isCapturing = false
|
@Published var isCapturing = false
|
||||||
@Published var lastCapturedText: String?
|
@Published var lastCapturedText: String?
|
||||||
|
|
||||||
|
private let logger = Logger(
|
||||||
|
subsystem: "com.prakashjoshipax.VoiceInk",
|
||||||
|
category: "aienhancement"
|
||||||
|
)
|
||||||
|
|
||||||
private func getActiveWindowInfo() -> (title: String, ownerName: String, windowID: CGWindowID)? {
|
private func getActiveWindowInfo() -> (title: String, ownerName: String, windowID: CGWindowID)? {
|
||||||
let options = CGWindowListOption([.optionOnScreenOnly, .excludeDesktopElements])
|
let options = CGWindowListOption([.optionOnScreenOnly, .excludeDesktopElements])
|
||||||
let windowListInfo = CGWindowListCopyWindowInfo(options, kCGNullWindowID) as? [[String: Any]] ?? []
|
let windowListInfo = CGWindowListCopyWindowInfo(options, kCGNullWindowID) as? [[String: Any]] ?? []
|
||||||
@ -86,11 +92,16 @@ class ScreenCaptureService: ObservableObject {
|
|||||||
isCapturing = true
|
isCapturing = true
|
||||||
defer { isCapturing = false }
|
defer { isCapturing = false }
|
||||||
|
|
||||||
|
logger.notice("🎬 Starting screen capture")
|
||||||
|
|
||||||
// First get window info
|
// First get window info
|
||||||
guard let windowInfo = getActiveWindowInfo() else {
|
guard let windowInfo = getActiveWindowInfo() else {
|
||||||
|
logger.notice("❌ Failed to get window info")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.notice("🎯 Found window: \(windowInfo.title) (\(windowInfo.ownerName))")
|
||||||
|
|
||||||
// Start with window metadata
|
// Start with window metadata
|
||||||
var contextText = """
|
var contextText = """
|
||||||
Active Window: \(windowInfo.title)
|
Active Window: \(windowInfo.title)
|
||||||
@ -106,6 +117,8 @@ class ScreenCaptureService: ObservableObject {
|
|||||||
}
|
}
|
||||||
}) {
|
}) {
|
||||||
contextText += "Window Content:\n\(extractedText)"
|
contextText += "Window Content:\n\(extractedText)"
|
||||||
|
// Log immediately after text extraction
|
||||||
|
logger.notice("✅ Captured: \(contextText)")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user