Initial Push

This commit is contained in:
2026-01-31 23:01:54 +00:00
parent 44d036c8d6
commit 5874b31464
32 changed files with 7171 additions and 0 deletions

145
AIManager.swift Normal file
View File

@@ -0,0 +1,145 @@
import Foundation
// MARK: - AI Service Protocol
protocol AIService {
func generateCommand(from prompt: String, completion: @escaping (Result<String, Error>) -> Void)
}
// MARK: - OpenAI Service
class OpenAIService: AIService {
private let apiKey: String
init(apiKey: String) {
self.apiKey = apiKey
}
func generateCommand(from prompt: String, completion: @escaping (Result<String, Error>) -> Void) {
guard let url = URL(string: "https://api.openai.com/v1/chat/completions") else {
completion(.failure(NSError(domain: "OpenAI", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"])))
return
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("Bearer \(apiKey)", forHTTPHeaderField: "Authorization")
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let body: [String: Any] = [
"model": "gpt-3.5-turbo",
"messages": [
["role": "system", "content": "You are a terminal command expert. Generate only the command, no explanations. Respond with just the command."],
["role": "user", "content": prompt]
],
"max_tokens": 150,
"temperature": 0.7
]
request.httpBody = try? JSONSerialization.data(withJSONObject: body)
URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
completion(.failure(error))
return
}
guard let data = data,
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
let choices = json["choices"] as? [[String: Any]],
let firstChoice = choices.first,
let message = firstChoice["message"] as? [String: Any],
let content = message["content"] as? String else {
completion(.failure(NSError(domain: "OpenAI", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid response"])))
return
}
completion(.success(content.trimmingCharacters(in: .whitespacesAndNewlines)))
}.resume()
}
}
// MARK: - Ollama Service
class OllamaService: AIService {
private let baseURL: String
private let model: String
init(baseURL: String, model: String) {
self.baseURL = baseURL
self.model = model
}
func generateCommand(from prompt: String, completion: @escaping (Result<String, Error>) -> Void) {
guard let url = URL(string: "\(baseURL)/api/generate") else {
completion(.failure(NSError(domain: "Ollama", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid URL"])))
return
}
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
request.timeoutInterval = 30
let fullPrompt = "Generate only the terminal command for: \(prompt). Respond with just the command, no explanation."
let body: [String: Any] = [
"model": model,
"prompt": fullPrompt,
"stream": false
]
request.httpBody = try? JSONSerialization.data(withJSONObject: body)
URLSession.shared.dataTask(with: request) { data, response, error in
if let error = error {
completion(.failure(error))
return
}
guard let data = data,
let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any],
let response = json["response"] as? String else {
completion(.failure(NSError(domain: "Ollama", code: -1, userInfo: [NSLocalizedDescriptionKey: "Invalid response"])))
return
}
completion(.success(response.trimmingCharacters(in: .whitespacesAndNewlines)))
}.resume()
}
}
// MARK: - AI Manager
class AIManager {
static let shared = AIManager()
private var service: AIService?
init() {
updateService()
}
func updateService() {
let settings = TerminalSettings.shared
switch settings.aiProvider {
case .openai:
if !settings.openAIKey.isEmpty {
service = OpenAIService(apiKey: settings.openAIKey)
} else {
service = nil
}
case .ollama:
service = OllamaService(baseURL: settings.ollamaURL, model: settings.ollamaModel)
case .none:
service = nil
}
}
func isAvailable() -> Bool {
return service != nil
}
func generateCommand(from prompt: String, completion: @escaping (Result<String, Error>) -> Void) {
guard let service = service else {
completion(.failure(NSError(domain: "AI", code: -1, userInfo: [NSLocalizedDescriptionKey: "No AI service configured"])))
return
}
service.generateCommand(from: prompt, completion: completion)
}
}