import Foundation public enum ClawdbotKitResources { /// Resource bundle for ClawdbotKit. /// /// Locates the SwiftPM-generated resource bundle, checking multiple locations: /// 1. Inside Bundle.main (packaged apps) /// 2. Bundle.module (SwiftPM development/tests) /// 3. Falls back to Bundle.main if not found (resource lookups will return nil) /// /// This avoids a fatal crash when Bundle.module can't locate its resources /// in packaged .app bundles where the resource bundle path differs from /// SwiftPM's expectations. public static let bundle: Bundle = locateBundle() private static let bundleName = "ClawdbotKit_ClawdbotKit" private static func locateBundle() -> Bundle { // 1. Check inside Bundle.main (packaged apps copy resources here) if let mainResourceURL = Bundle.main.resourceURL { let bundleURL = mainResourceURL.appendingPathComponent("\(bundleName).bundle") if let bundle = Bundle(url: bundleURL) { return bundle } } // 2. Check Bundle.main directly for embedded resources if Bundle.main.url(forResource: "tool-display", withExtension: "json") != nil { return Bundle.main } // 3. Try Bundle.module (works in SwiftPM development/tests) // Wrap in a function to defer the fatalError until actually called if let moduleBundle = loadModuleBundleSafely() { return moduleBundle } // 4. Fallback: return Bundle.main (resource lookups will return nil gracefully) return Bundle.main } private static func loadModuleBundleSafely() -> Bundle? { // Bundle.module is generated by SwiftPM and will fatalError if not found. // We check likely locations manually to avoid the crash. let candidates: [URL?] = [ Bundle.main.resourceURL, Bundle.main.bundleURL, Bundle(for: BundleLocator.self).resourceURL, Bundle(for: BundleLocator.self).bundleURL, ] for candidate in candidates { guard let baseURL = candidate else { continue } // Direct path let directURL = baseURL.appendingPathComponent("\(bundleName).bundle") if let bundle = Bundle(url: directURL) { return bundle } // Inside Resources/ let resourcesURL = baseURL .appendingPathComponent("Resources") .appendingPathComponent("\(bundleName).bundle") if let bundle = Bundle(url: resourcesURL) { return bundle } } return nil } } // Helper class for bundle lookup via Bundle(for:) private final class BundleLocator {}