spb/prisme Public MIT
Navigateur iOS intelligent — chaque page comprise localement avant d'être affichée. SwiftUI · WebKit · Foundation Models, 100% on-device.
Swift 96.7%
JavaScript 3.3%
1//2// PageDigest.swift3// Prisme4//5// Author: Simon-Pierre Boucher <contact@spboucher.ai>6//78import Foundation9import FoundationModels1011/// Structured output of the Distiller — never free-form text to parse12/// (CLAUDE.md §9). Every generated element carries the index of the source13/// content block it came from, so the UI can always anchor a summary back14/// to the real DOM element (§7: a summary without an anchor is not shown).15@Generable16enum PageKind: String, Codable, Sendable {17 case article18 case documentation19 case forum20 case boutique21 case application22 case portail23 case formulaire24 case autre25}2627extension PageKind {28 /// User-facing label (French, per product conventions).29 var label: String {30 switch self {31 case .article: "Article"32 case .documentation: "Documentation"33 case .forum: "Forum"34 case .boutique: "Boutique"35 case .application: "Application"36 case .portail: "Portail"37 case .formulaire: "Formulaire"38 case .autre: "Page"39 }40 }41}4243@Generable44struct DigestSection: Codable, Hashable, Sendable {45 @Guide(description: "Section heading as it appears in the document")46 let title: String4748 @Guide(description: "One-sentence summary of the section, based only on the provided text")49 let summary: String5051 @Guide(description: "Index of the source block where this section starts, from the numbered list")52 let sourceBlock: Int53}5455@Generable56struct DigestClaim: Codable, Hashable, Sendable {57 @Guide(description: "A dated or numeric factual statement quoted or closely paraphrased from the page")58 let text: String5960 @Guide(description: "Index of the source block containing this statement")61 let sourceBlock: Int62}6364@Generable65struct PageDigest: Codable, Hashable, Sendable {66 @Guide(description: "Type of page")67 let kind: PageKind6869 @Guide(description: "Answer to the page's implicit question, maximum two sentences")70 let gist: String7172 @Guide(description: "Main sections in document order", .count(1...8))73 let outline: [DigestSection]7475 @Guide(description: "Up to five dated or numeric statements from the page", .count(0...5))76 let claims: [DigestClaim]77}7879/// Lifecycle of a digest for a given tab. Model refusals and failures are80/// normal states with calm copy — the raw page is always available (§7).81enum DigestState {82 case idle83 case working84 case ready(PageDigest, blocks: [ContentBlock])85 case unavailable(String)86 case failed(String)87}88