All checks were successful
CI / build-and-deploy (push) Successful in 22s
- SpotlightIndexer: actually push BookmarkEntity into the Spotlight index via indexAppEntities (IndexedEntity conformance alone indexes nothing). Wired into every sync/mutation point. This is what lets Apple Intelligence answer free-form Siri questions grounded in the user's bookmarks. - On-device RAG: BookmarkAssistant (LanguageModelSession) + BookmarkSearchTool + SpotlightBookmarkSearch (CSSearchQuery retrieval), surfaced via AskView with lightweight Markdown rendering of answers. - Log: os.Logger facility (com.magicive.marks) replacing ad-hoc print(); shared with ShareExtension. ClaudeService now logs server error bodies on non-2xx. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
41 lines
1.8 KiB
Swift
41 lines
1.8 KiB
Swift
import Foundation
|
|
import CoreSpotlight
|
|
import AppIntents
|
|
|
|
/// Pushes Linkding bookmarks into the system Spotlight index via the
|
|
/// `IndexedEntity` conformance on `BookmarkEntity`.
|
|
///
|
|
/// This is the step that actually makes bookmarks discoverable: conforming to
|
|
/// `IndexedEntity` only describes *how* an entity would be indexed (its
|
|
/// `attributeSet`) — nothing reaches Spotlight until the entities are handed to
|
|
/// `CSSearchableIndex`. Once indexed, bookmarks show up in Spotlight search and
|
|
/// are reachable by Siri / Apple Intelligence.
|
|
///
|
|
/// All calls are best-effort: failures are logged, never surfaced. If indexing
|
|
/// is unavailable or fails, search degrades but nothing else breaks.
|
|
enum SpotlightIndexer {
|
|
/// Insert or update the given bookmarks in the Spotlight index.
|
|
static func index(_ bookmarks: [Bookmark]) async {
|
|
guard CSSearchableIndex.isIndexingAvailable(), !bookmarks.isEmpty else { return }
|
|
do {
|
|
try await CSSearchableIndex.default()
|
|
.indexAppEntities(bookmarks.map(BookmarkEntity.init(from:)))
|
|
Log.spotlight.info("Indexed \(bookmarks.count, privacy: .public) bookmarks")
|
|
} catch {
|
|
Log.spotlight.error("Index failed: \(error.localizedDescription, privacy: .public)")
|
|
}
|
|
}
|
|
|
|
/// Remove bookmarks from the index by id (e.g. after delete / archive).
|
|
static func remove(ids: [Int]) async {
|
|
guard CSSearchableIndex.isIndexingAvailable(), !ids.isEmpty else { return }
|
|
do {
|
|
try await CSSearchableIndex.default()
|
|
.deleteAppEntities(identifiedBy: ids, ofType: BookmarkEntity.self)
|
|
Log.spotlight.info("Removed \(ids.count, privacy: .public) bookmarks")
|
|
} catch {
|
|
Log.spotlight.error("Delete failed: \(error.localizedDescription, privacy: .public)")
|
|
}
|
|
}
|
|
}
|