Bladeren bron

Hide backend API errors from job search chat.

Show generic connection and search failure messages so OpenAI responses never expose keys or internal details to users.

Co-authored-by: Cursor <cursoragent@cursor.com>
AhtashamShahzad1 2 maanden geleden
bovenliggende
commit
a596b41e00
2 gewijzigde bestanden met toevoegingen van 36 en 17 verwijderingen
  1. 23 0
      App for Indeed/Services/UserFacingErrorMessage.swift
  2. 13 17
      App for Indeed/Views/DashboardView.swift

+ 23 - 0
App for Indeed/Services/UserFacingErrorMessage.swift

@@ -0,0 +1,23 @@
+import Foundation
+
+/// Maps backend and network errors to short, safe copy for the UI.
+enum UserFacingErrorMessage {
+    static func jobSearchFailure(_ error: Error) -> String {
+        if let urlError = error as? URLError {
+            switch urlError.code {
+            case .notConnectedToInternet,
+                 .networkConnectionLost,
+                 .timedOut,
+                 .cannotFindHost,
+                 .cannotConnectToHost,
+                 .dnsLookupFailed:
+                return "We couldn't reach the server. Check your internet connection and try again."
+            case .cancelled:
+                return "The search was cancelled. Try again when you're ready."
+            default:
+                break
+            }
+        }
+        return "Something went wrong while searching. Please try again in a moment."
+    }
+}

+ 13 - 17
App for Indeed/Views/DashboardView.swift

@@ -2163,7 +2163,7 @@ final class DashboardView: NSView, NSTextFieldDelegate, NSSharingServicePickerDe
                     self.chatMessages.append(ChatMessage(role: "assistant", content: reply, attachedJobs: freshJobs.isEmpty ? nil : freshJobs))
                     self.appendChatBubble(text: reply, isUser: false, jobs: freshJobs)
                 case .failure(let error):
-                    self.appendChatBubble(text: error.localizedDescription, isUser: false)
+                    self.appendChatBubble(text: UserFacingErrorMessage.jobSearchFailure(error), isUser: false)
                 }
             }
         }
@@ -2920,7 +2920,7 @@ private final class OpenAIJobSearchService {
             completion(.failure(NSError(
                 domain: "OpenAIJobSearchService",
                 code: 1,
-                userInfo: [NSLocalizedDescriptionKey: "Missing API key. Set OPENAI_API_KEY in Xcode Build Settings."]
+                userInfo: [NSLocalizedDescriptionKey: "Job search is unavailable."]
             )))
             return
         }
@@ -2995,19 +2995,12 @@ private final class OpenAIJobSearchService {
                 return
             }
             if let http = response as? HTTPURLResponse, !(200...299).contains(http.statusCode) {
-                if let apiError = try? JSONDecoder().decode(OpenAIAPIErrorResponse.self, from: data) {
-                    completion(.failure(NSError(
-                        domain: "OpenAIJobSearchService",
-                        code: http.statusCode,
-                        userInfo: [NSLocalizedDescriptionKey: apiError.error.message]
-                    )))
-                } else {
-                    completion(.failure(NSError(
-                        domain: "OpenAIJobSearchService",
-                        code: http.statusCode,
-                        userInfo: [NSLocalizedDescriptionKey: "Job search request failed with status \(http.statusCode)."]
-                    )))
-                }
+                _ = try? JSONDecoder().decode(OpenAIAPIErrorResponse.self, from: data)
+                completion(.failure(NSError(
+                    domain: "OpenAIJobSearchService",
+                    code: http.statusCode,
+                    userInfo: [NSLocalizedDescriptionKey: "Job search request failed."]
+                )))
                 return
             }
             do {
@@ -3051,8 +3044,11 @@ private final class OpenAIJobSearchService {
         }
         if let status = root["status"] as? String {
             if status == "failed" {
-                let message = (root["error"] as? [String: Any])?["message"] as? String ?? "The search request failed."
-                throw NSError(domain: "OpenAIJobSearchService", code: 7, userInfo: [NSLocalizedDescriptionKey: message])
+                throw NSError(
+                    domain: "OpenAIJobSearchService",
+                    code: 7,
+                    userInfo: [NSLocalizedDescriptionKey: "The search request failed."]
+                )
             }
             if status == "incomplete",
                let details = root["incomplete_details"] as? [String: Any],