spb/zyquo-router Public MIT
One local endpoint, every AI provider — a private OpenAI-compatible LLM gateway for your Mac (170 models, 12 providers).
Swift 95.7%
Python 2.3%
Shell 1.2%
Makefile 0.9%
1//2// Main.swift3// Zyquo Router4//5// Author: Simon-Pierre Boucher6// Mail: contact@spboucher.ai7//8// Entry point. CLI modes (verification harness, vault seeding) hang off this9// in later phases; otherwise the SwiftUI app launches.10//11// Deliberately a synchronous main: launching NSApplicationMain from an async12// main() corrupts Swift concurrency's executor setup (background tasks stop13// being scheduled), so CLI modes must drive their async work explicitly.14//1516import Foundation1718@main19enum Main {20 static func main() {21 let arguments = CommandLine.arguments22 if arguments.contains("--load-vault") {23 loadVaultFromEnvironment()24 exit(0)25 }26 if let flagIndex = arguments.firstIndex(of: "--serve") {27 // Headless mode for scripted verification (`ZyquoRouter --serve [port]`).28 let port = arguments.indices.contains(flagIndex + 1) ? Int(arguments[flagIndex + 1]) ?? 8787 : 878729 Task.detached {30 let localKeys = PersistenceService.shared.load([APIKeyRecord].self, from: "local-keys.json") ?? []31 let routerConfig = PersistenceService.shared.load(RouterConfig.self, from: RouterConfig.fileName) ?? RouterConfig()32 let routes = Routes(33 router: RequestRouter(34 aliases: routerConfig.aliases,35 disabledIDs: routerConfig.disabledIDs,36 fallbackChains: routerConfig.fallbackChains37 ),38 auth: AuthMiddleware(keys: localKeys)39 )40 let server = HTTPServer(host: "127.0.0.1", port: port) { request in41 await routes.handle(request)42 }43 do {44 try await server.run {45 print("Zyquo Router serving on http://127.0.0.1:\(port)/v1")46 }47 exit(0)48 } catch {49 FileHandle.standardError.write(Data("\(error.localizedDescription)\n".utf8))50 exit(1)51 }52 }53 // Park the main thread servicing the main queue so MainActor work54 // can run (a blocking semaphore here would deadlock).55 dispatchMain()56 }57 ZyquoRouterApp.main()58 }5960 /// Seeds the encrypted vault from environment variables (testing/setup).61 /// Key values are never printed — only which providers were stored.62 private static func loadVaultFromEnvironment() {63 let mapping: [(ProviderID, String)] = [64 (.openai, "OPENAI_API_KEY"), (.anthropic, "ANTHROPIC_API_KEY"),65 (.xai, "XAI_API_KEY"), (.mistral, "MISTRAL_API_KEY"),66 (.gemini, "GEMINI_API_KEY"), (.qwen, "DASHSCOPE_API_KEY"),67 (.deepseek, "DEEPSEEK_API_KEY"), (.kimi, "KIMI_API_KEY"),68 (.perplexity, "PERPLEXITY_API_KEY"), (.together, "TOGETHER_API_KEY"),69 (.deepinfra, "DEEPINFRA_API_KEY"), (.cerebras, "CEREBRAS_API_KEY"),70 ]71 let store = SecureKeyStore()72 var stored: [String] = []73 for (provider, variable) in mapping {74 if let value = ProcessInfo.processInfo.environment[variable], !value.isEmpty {75 try? store.setKey(value, for: provider)76 stored.append(provider.rawValue)77 }78 }79 print("Vault updated (\(stored.count) providers): \(stored.joined(separator: ", "))")80 }81}82