Download apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatSourceResources.swift from SaylorTwift/openclaw: direct link, hf CLI and curl.
- Browser
- Download file 12.9 kB
-
https://huggingface.co/SaylorTwift/openclaw/resolve/main/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatSourceResources.swift
- Command line
-
hf download hf://SaylorTwift/openclaw/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatSourceResources.swift
-
curl -L -o ChatSourceResources.swift https://huggingface.co/SaylorTwift/openclaw/resolve/main/apps/shared/OpenClawKit/Sources/OpenClawChatUI/ChatSourceResources.swift
12.9 kB
| import Foundation | |
| public struct OpenClawChatSourceContext: Hashable, Sendable { | |
| public let gatewayURL: URL | |
| /// Percent-encoded mount shared by resource routing and dedicated-link matching. | |
| public let basePath: String | |
| public let publicOrigin: URL? | |
| public let automaticallyFetchFavicons: Bool | |
| public init( | |
| gatewayURL: URL, | |
| basePath: String, | |
| publicOrigin: URL? = nil, | |
| automaticallyFetchFavicons: Bool = false) | |
| { | |
| self.gatewayURL = gatewayURL | |
| self.basePath = basePath | |
| self.publicOrigin = publicOrigin | |
| self.automaticallyFetchFavicons = automaticallyFetchFavicons | |
| } | |
| } | |
| /// One connected route owns bootstrap discovery and its preference snapshot. | |
| /// Native adapters supply authenticated, bounded requests tied to that route. | |
| public actor OpenClawChatSourceResources { | |
| public typealias Request = (URL, Int) async throws -> (Data, URLResponse) | |
| public typealias ConfigLoader = () async -> Data? | |
| public typealias IsCurrent = () async -> Bool | |
| public static let maximumFaviconBytes = 64 * 1024 | |
| private let gatewayURL: URL | |
| private let nativeControlPageURL: URL? | |
| private let request: Request | |
| private let loadConfig: ConfigLoader | |
| private let isCurrent: IsCurrent | |
| private var revision: UInt64 = 0 | |
| private struct ContextSnapshot: Sendable { | |
| let context: OpenClawChatSourceContext | |
| let resourceBaseURL: URL | |
| } | |
| private var contextTask: Task<ContextSnapshot?, Never>? | |
| private var faviconTasks: [URL: Task<Data?, Never>] = [:] | |
| private var faviconOrder: [URL] = [] | |
| private static let maximumCachedFavicons = 32 | |
| public init( | |
| gatewayURL: URL, | |
| nativeControlPageURL: URL? = nil, | |
| request: @escaping Request, | |
| loadConfig: @escaping ConfigLoader, | |
| isCurrent: @escaping IsCurrent) | |
| { | |
| self.gatewayURL = gatewayURL | |
| self.nativeControlPageURL = nativeControlPageURL | |
| self.request = request | |
| self.loadConfig = loadConfig | |
| self.isCurrent = isCurrent | |
| } | |
| public func invalidate() { | |
| self.revision &+= 1 | |
| self.contextTask?.cancel() | |
| self.contextTask = nil | |
| for task in self.faviconTasks.values { | |
| task.cancel() | |
| } | |
| self.faviconTasks.removeAll() | |
| self.faviconOrder.removeAll() | |
| } | |
| public func loadContext() async -> OpenClawChatSourceContext? { | |
| await self.loadContextSnapshot()?.context | |
| } | |
| private func loadContextSnapshot() async -> ContextSnapshot? { | |
| guard await self.isCurrent(), !Task.isCancelled else { return nil } | |
| let revision = self.revision | |
| let task: Task<ContextSnapshot?, Never> | |
| if let existing = contextTask { | |
| task = existing | |
| } else { | |
| task = Task { await self.discoverContext() } | |
| self.contextTask = task | |
| } | |
| let context = await task.value | |
| guard await self.isCurrent(), self.revision == revision, !Task.isCancelled else { return nil } | |
| return context | |
| } | |
| public func loadFavicon(host: String) async -> Data? { | |
| let revision = self.revision | |
| guard let snapshot = await loadContextSnapshot(), snapshot.context.automaticallyFetchFavicons, | |
| let url = Self.faviconURL(host: host, baseURL: snapshot.resourceBaseURL), | |
| await isCurrent(), self.revision == revision, !Task.isCancelled | |
| else { return nil } | |
| let task: Task<Data?, Never> | |
| if let cached = self.faviconTasks[url] { | |
| task = cached | |
| } else { | |
| if self.faviconOrder.count >= Self.maximumCachedFavicons { | |
| let oldest = self.faviconOrder.removeFirst() | |
| self.faviconTasks.removeValue(forKey: oldest)?.cancel() | |
| } | |
| task = Task { await self.downloadFavicon(url: url, revision: revision) } | |
| self.faviconTasks[url] = task | |
| self.faviconOrder.append(url) | |
| } | |
| let data = await task.value | |
| guard await self.isCurrent(), self.revision == revision, !Task.isCancelled else { return nil } | |
| return data | |
| } | |
| private func downloadFavicon(url: URL, revision: UInt64) async -> Data? { | |
| guard await self.isCurrent(), self.revision == revision, !Task.isCancelled, | |
| let (data, response) = try? await self.request(url, Self.maximumFaviconBytes), | |
| await self.isCurrent(), self.revision == revision, !Task.isCancelled, | |
| let http = response as? HTTPURLResponse, | |
| (200..<300).contains(http.statusCode), | |
| http.mimeType?.lowercased().hasPrefix("image/") == true, | |
| !data.isEmpty, data.count <= Self.maximumFaviconBytes | |
| else { return nil } | |
| return data | |
| } | |
| /// Proxy and Gateway credentials share one HTTP header. Preserve the proxy | |
| /// attempt, then retry only an authentication rejection with the Gateway bearer. | |
| public static func performAuthenticatedRequest( | |
| _ request: URLRequest, | |
| bearer: String?, | |
| send: (URLRequest) async throws -> (Data, URLResponse)) async throws -> (Data, URLResponse) | |
| { | |
| var request = request | |
| let configuredAuthorization = request.value(forHTTPHeaderField: "Authorization") | |
| let gatewayAuthorization = bearer.map { "Bearer " + $0 } | |
| if configuredAuthorization == nil { | |
| request.setValue(gatewayAuthorization, forHTTPHeaderField: "Authorization") | |
| } | |
| let result = try await send(request) | |
| guard let configuredAuthorization, | |
| let gatewayAuthorization, gatewayAuthorization != configuredAuthorization, | |
| let response = result.1 as? HTTPURLResponse, | |
| response.statusCode == 401 || response.statusCode == 403 | |
| else { return result } | |
| try Task.checkCancellation() | |
| request.setValue(gatewayAuthorization, forHTTPHeaderField: "Authorization") | |
| return try await send(request) | |
| } | |
| private func discoverContext() async -> ContextSnapshot? { | |
| guard let gatewayURL = Self.httpURL(self.gatewayURL) else { return nil } | |
| let configData = await self.loadConfig() | |
| guard await self.isCurrent() else { return nil } | |
| let config = configData.flatMap { try? JSONDecoder().decode(ConfigSnapshot.self, from: $0) } | |
| if let config { | |
| let controlUI = config.runtimeConfig.gateway?.controlUi | |
| return self.contextSnapshot( | |
| gatewayURL: gatewayURL, | |
| basePath: controlUI?.basePath ?? "", | |
| publicOrigin: config.runtimeConfig.gateway?.publicOrigin.flatMap(Self.publicOrigin), | |
| automaticallyFetchFavicons: controlUI?.automaticallyFetchFavicons != false) | |
| } | |
| let bootstrapBase = self.controlPageURL(gatewayURL: gatewayURL) ?? gatewayURL | |
| guard let url = Self.appendResourcePath("/control-ui-config.json", to: bootstrapBase), | |
| await self.isCurrent(), !Task.isCancelled | |
| else { return nil } | |
| if let (data, response) = try? await self.request(url, 64 * 1024), | |
| let http = response as? HTTPURLResponse, | |
| (200..<300).contains(http.statusCode), http.mimeType == "application/json", | |
| let bootstrap = try? JSONDecoder().decode(Bootstrap.self, from: data) | |
| { | |
| guard await self.isCurrent(), !Task.isCancelled else { return nil } | |
| if let snapshot = self.contextSnapshot( | |
| gatewayURL: gatewayURL, | |
| basePath: bootstrap.basePath, | |
| automaticallyFetchFavicons: bootstrap.automaticallyFetchFavicons ?? false) | |
| { | |
| return snapshot | |
| } | |
| } | |
| guard await self.isCurrent() else { return nil } | |
| return self.contextSnapshot(gatewayURL: gatewayURL, basePath: "", automaticallyFetchFavicons: false) | |
| } | |
| private func contextSnapshot( | |
| gatewayURL: URL, | |
| basePath: String, | |
| publicOrigin: URL? = nil, | |
| automaticallyFetchFavicons: Bool) -> ContextSnapshot? | |
| { | |
| guard let basePath = Self.normalizedBasePath(basePath) else { return nil } | |
| let resourceBaseURL: URL? = if basePath.isEmpty, | |
| let controlPageURL = self.controlPageURL(gatewayURL: gatewayURL) | |
| { | |
| controlPageURL | |
| } else { | |
| Self.resourceURL(gatewayURL: gatewayURL, basePath: basePath, path: "") | |
| } | |
| guard let resourceBaseURL, | |
| let components = URLComponents(url: resourceBaseURL, resolvingAgainstBaseURL: false) | |
| else { return nil } | |
| let mount = components.percentEncodedPath.trimmingCharacters(in: CharacterSet(charactersIn: "/")) | |
| return ContextSnapshot( | |
| context: OpenClawChatSourceContext( | |
| gatewayURL: gatewayURL, | |
| basePath: mount.isEmpty ? "" : "/" + mount, | |
| publicOrigin: publicOrigin, | |
| automaticallyFetchFavicons: automaticallyFetchFavicons), | |
| resourceBaseURL: resourceBaseURL) | |
| } | |
| private func controlPageURL(gatewayURL: URL) -> URL? { | |
| guard let nativeControlPageURL, let url = Self.httpURL(nativeControlPageURL), | |
| url.scheme == gatewayURL.scheme, url.host?.lowercased() == gatewayURL.host?.lowercased(), | |
| (url.port ?? (url.scheme == "https" ? 443 : 80)) == | |
| (gatewayURL.port ?? (gatewayURL.scheme == "https" ? 443 : 80)) | |
| else { return nil } | |
| return url | |
| } | |
| static func httpURL(_ url: URL) -> URL? { | |
| guard var components = URLComponents(url: url, resolvingAgainstBaseURL: false), | |
| components.host?.isEmpty == false, components.user == nil, components.password == nil | |
| else { return nil } | |
| switch components.scheme?.lowercased() { | |
| case "ws", "http": components.scheme = "http" | |
| case "wss", "https": components.scheme = "https" | |
| default: return nil | |
| } | |
| components.query = nil | |
| components.fragment = nil | |
| return components.url | |
| } | |
| private static func faviconURL(host: String, baseURL: URL) -> URL? { | |
| let host = host.lowercased() | |
| guard !host.isEmpty, host.utf8.count <= 253, | |
| host.unicodeScalars.allSatisfy({ | |
| CharacterSet(charactersIn: "abcdefghijklmnopqrstuvwxyz0123456789.-").contains($0) | |
| }), | |
| !host.hasPrefix("."), !host.hasSuffix("."), !host.contains("..") | |
| else { return nil } | |
| return Self.appendResourcePath("/__openclaw__/link-favicon/" + host, to: baseURL) | |
| } | |
| private static func appendResourcePath(_ path: String, to baseURL: URL) -> URL? { | |
| guard var components = URLComponents(url: baseURL, resolvingAgainstBaseURL: false) else { return nil } | |
| while components.percentEncodedPath.hasSuffix("/") { | |
| components.percentEncodedPath.removeLast() | |
| } | |
| components.percentEncodedPath += path | |
| return components.url | |
| } | |
| private static func resourceURL(gatewayURL: URL, basePath: String, path: String) -> URL? { | |
| guard let basePath = normalizedBasePath(basePath), | |
| let url = httpURL(gatewayURL), | |
| var components = URLComponents(url: url, resolvingAgainstBaseURL: false) | |
| else { return nil } | |
| components.path = basePath + path | |
| return components.url | |
| } | |
| private static func normalizedBasePath(_ raw: String) -> String? { | |
| let path = raw.trimmingCharacters(in: CharacterSet(charactersIn: "/")) | |
| guard !path.contains("\\"), !path.contains("?"), !path.contains("#"), !path.contains("%"), | |
| !path.unicodeScalars.contains(where: { CharacterSet.controlCharacters.contains($0) }), | |
| !path.split(separator: "/").contains(where: { $0 == "." || $0 == ".." }) | |
| else { return nil } | |
| return path.isEmpty ? "" : "/" + path | |
| } | |
| private static func publicOrigin(_ raw: String) -> URL? { | |
| guard let url = URL(string: raw), let http = httpURL(url), | |
| ["http", "https"].contains(url.scheme?.lowercased() ?? ""), | |
| url.query == nil, url.fragment == nil | |
| else { return nil } | |
| return http | |
| } | |
| private struct Bootstrap: Decodable { | |
| let basePath: String | |
| let automaticallyFetchFavicons: Bool? | |
| } | |
| private struct ConfigSnapshot: Decodable { | |
| let runtimeConfig: RuntimeConfig | |
| } | |
| private struct RuntimeConfig: Decodable { | |
| let gateway: GatewayConfig? | |
| } | |
| private struct GatewayConfig: Decodable { | |
| let publicOrigin: String? | |
| let controlUi: ControlUIConfig? | |
| } | |
| private struct ControlUIConfig: Decodable { | |
| let basePath: String? | |
| let automaticallyFetchFavicons: Bool? | |
| } | |
| } | |