spb/zyquo-atlas Public License
The AI-native macOS web browser — every surface, intelligent.
Swift 75.2%
JavaScript 22%
Shell 2%
Makefile 0.9%
1//2// OmniIntent.swift3// Zyquo Atlas4//5// Author: Simon-Pierre Boucher6// Mail: contact@spboucher.ai7//8// Resolves omnibox input into a navigable URL: direct navigation vs. web9// search. This is the Phase 2 URL-vs-search half of the smart omnibox; the10// Phase 3 "ask AI" intent (docs/AI-BROWSER-RESEARCH.md §4.1) layers on top as a11// third route with explicit affordances — deliberately not auto-hijacking12// navigate/search here.13//1415import Foundation1617enum OmniIntent: Equatable {18 /// Navigate directly to this URL.19 case navigate(URL)20 /// Run a web search for this query.21 case search(String)2223 /// The default search engine query template (`%@` replaced by the escaped query).24 static let searchTemplate = "https://duckduckgo.com/?q=%@"2526 /// Classify raw omnibox text. Bias toward navigate/search (reversible,27 /// cheap) per the research; the AI "ask" route is opt-in elsewhere.28 static func resolve(_ raw: String) -> OmniIntent {29 let text = raw.trimmingCharacters(in: .whitespacesAndNewlines)30 guard !text.isEmpty else { return .search("") }3132 // Explicit scheme (http/https/file/about/data) → navigate.33 if let url = URL(string: text), let scheme = url.scheme?.lowercased(),34 ["http", "https", "file", "about", "data"].contains(scheme) {35 return .navigate(url)36 }3738 // localhost / IP[:port] / bare host with a known-looking TLD and no39 // spaces → treat as a URL, defaulting to https.40 if !text.contains(" "), looksLikeHost(text) {41 if let url = URL(string: "https://\(text)") {42 return .navigate(url)43 }44 }4546 return .search(text)47 }4849 /// The URL to actually load for this intent.50 var url: URL? {51 switch self {52 case .navigate(let url):53 return url54 case .search(let query):55 let escaped = query.addingPercentEncoding(56 withAllowedCharacters: .urlQueryAllowed57 ) ?? query58 return URL(string: String(format: OmniIntent.searchTemplate, escaped))59 }60 }6162 // MARK: - Heuristics6364 private static func looksLikeHost(_ text: String) -> Bool {65 let host = text.split(separator: "/", maxSplits: 1).first.map(String.init) ?? text66 let bare = host.split(separator: ":", maxSplits: 1).first.map(String.init) ?? host67 if bare == "localhost" { return true }68 if isIPAddress(bare) { return true }69 // host.tld shape: at least one dot, a plausible TLD, no whitespace.70 guard let lastDot = bare.lastIndex(of: "."), lastDot != bare.startIndex else { return false }71 let tld = bare[bare.index(after: lastDot)...]72 return tld.count >= 2 && tld.allSatisfy { $0.isLetter }73 }7475 private static func isIPAddress(_ s: String) -> Bool {76 let parts = s.split(separator: ".")77 guard parts.count == 4 else { return false }78 return parts.allSatisfy { part in79 guard let n = Int(part) else { return false }80 return (0...255).contains(n)81 }82 }83}84