From c436262b0b5a6df1770bd9e09a3e6d04cf4850a3 Mon Sep 17 00:00:00 2001 From: Thibault Jaigu Date: Thu, 24 Sep 2026 21:56:33 +0100 Subject: [PATCH] feat(ai-providers): add Requesty as an AI provider --- CHANGELOG.md | 1 + TablePro/Core/AI/Registry/AIProviderRegistration.swift | 2 +- TablePro/Models/AI/AIModels.swift | 4 ++++ TableProTests/Core/AI/AIEndpointTests.swift | 1 + TableProTests/Core/AI/AIProviderCapabilitiesTests.swift | 2 +- docs/security/privacy.mdx | 2 +- 6 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6701699763..50ecd4f3b3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -71,6 +71,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Export from a data file window to every bundled format, for all, filtered or selected rows. - **Import into Table** from a data file window, into an open connection's import sheet. - **Text Encoding** in a data file's Save As panel. +- Requesty as an AI provider, an OpenAI-compatible router. ### Changed diff --git a/TablePro/Core/AI/Registry/AIProviderRegistration.swift b/TablePro/Core/AI/Registry/AIProviderRegistration.swift index 6b93883a24..ecb4b802a3 100644 --- a/TablePro/Core/AI/Registry/AIProviderRegistration.swift +++ b/TablePro/Core/AI/Registry/AIProviderRegistration.swift @@ -101,7 +101,7 @@ enum AIProviderRegistration { } )) - for type in [AIProviderType.openRouter, .openCode, .ollama, .llamaCpp, .mlx, .custom] { + for type in [AIProviderType.openRouter, .requesty, .openCode, .ollama, .llamaCpp, .mlx, .custom] { var capabilities: AIProviderCapabilities = [ .chat, .models, .reasoning, .images, .endpointConfigurable, .maxOutputTokens, .modelListFetchable diff --git a/TablePro/Models/AI/AIModels.swift b/TablePro/Models/AI/AIModels.swift index 4b6ac1f4d2..0e4bb973b8 100644 --- a/TablePro/Models/AI/AIModels.swift +++ b/TablePro/Models/AI/AIModels.swift @@ -15,6 +15,7 @@ enum AIProviderType: String, Codable, CaseIterable, Identifiable, Sendable { case claudeAgent case openAI case openRouter + case requesty case gemini case xai case ollama @@ -34,6 +35,7 @@ enum AIProviderType: String, Codable, CaseIterable, Identifiable, Sendable { case .claudeAgent: return "Claude Agent" case .openAI: return "OpenAI" case .openRouter: return "OpenRouter" + case .requesty: return "Requesty" case .gemini: return "Gemini" case .xai: return "xAI" case .ollama: return "Ollama" @@ -53,6 +55,7 @@ enum AIProviderType: String, Codable, CaseIterable, Identifiable, Sendable { case .claudeAgent: return "" case .openAI: return "https://api.openai.com" case .openRouter: return "https://openrouter.ai/api" + case .requesty: return "https://router.requesty.ai" case .gemini: return "https://generativelanguage.googleapis.com" case .xai: return "https://api.x.ai" case .ollama: return "http://localhost:11434" @@ -106,6 +109,7 @@ enum AIProviderType: String, Codable, CaseIterable, Identifiable, Sendable { case .claudeAgent: return "terminal" case .openAI: return "cpu" case .openRouter: return "globe" + case .requesty: return "arrow.triangle.branch" case .gemini: return "wand.and.stars" case .xai: return "x.circle" case .ollama: return "desktopcomputer" diff --git a/TableProTests/Core/AI/AIEndpointTests.swift b/TableProTests/Core/AI/AIEndpointTests.swift index f793b73467..211d3beb26 100644 --- a/TableProTests/Core/AI/AIEndpointTests.swift +++ b/TableProTests/Core/AI/AIEndpointTests.swift @@ -23,6 +23,7 @@ struct AIEndpointTests { #expect(chatURL("https://api.openai.com", .chatCompletions) == "https://api.openai.com/v1/chat/completions") #expect(modelsURL("https://api.openai.com", .chatCompletions) == "https://api.openai.com/v1/models") #expect(chatURL("https://openrouter.ai/api", .chatCompletions) == "https://openrouter.ai/api/v1/chat/completions") + #expect(chatURL("https://router.requesty.ai", .chatCompletions) == "https://router.requesty.ai/v1/chat/completions") #expect(chatURL("https://opencode.ai/zen", .chatCompletions) == "https://opencode.ai/zen/v1/chat/completions") #expect(chatURL("http://localhost:8080", .chatCompletions) == "http://localhost:8080/v1/chat/completions") } diff --git a/TableProTests/Core/AI/AIProviderCapabilitiesTests.swift b/TableProTests/Core/AI/AIProviderCapabilitiesTests.swift index 715fd7a391..b1526d817e 100644 --- a/TableProTests/Core/AI/AIProviderCapabilitiesTests.swift +++ b/TableProTests/Core/AI/AIProviderCapabilitiesTests.swift @@ -40,7 +40,7 @@ struct AIProviderCapabilitiesTests { @Test("HTTP API-key providers accept max output tokens, a configurable endpoint, and model fetch") func standardHTTPProviders() { - for type in [AIProviderType.openAI, .claude, .gemini, .xai, .openRouter, .ollama] { + for type in [AIProviderType.openAI, .claude, .gemini, .xai, .openRouter, .requesty, .ollama] { let provider = descriptor(type) #expect(provider?.allowsMaxOutputTokens == true, "\(type.rawValue) should accept max output tokens") #expect(provider?.allowsEndpointConfiguration == true, "\(type.rawValue) should allow endpoint config") diff --git a/docs/security/privacy.mdx b/docs/security/privacy.mdx index f0bc2fdaba..9b817fb365 100644 --- a/docs/security/privacy.mdx +++ b/docs/security/privacy.mdx @@ -50,7 +50,7 @@ On iPhone and iPad the heartbeat is off until you choose **Share Usage Data**, a Nothing reaches a model until you add a provider, and a fresh install has none: with none configured, every AI path returns before it builds a request. **Enable AI Features** in **Settings > AI** is on out of the box, but it gates an empty tab. -One provider is marked active and answers inline suggestions and the editor actions; the chat panel's own model picker can send a turn to any other provider you configured. Requests go to that provider's endpoint. The presets are `api.anthropic.com`, `api.openai.com`, `generativelanguage.googleapis.com`, `api.x.ai`, `openrouter.ai`, `api.cursor.com` and `opencode.ai`, plus `http://localhost:11434` for Ollama and `http://localhost:8080` for llama.cpp and MLX, which keeps their traffic on the machine. Every endpoint field is editable, and a custom provider goes wherever you point it. +One provider is marked active and answers inline suggestions and the editor actions; the chat panel's own model picker can send a turn to any other provider you configured. Requests go to that provider's endpoint. The presets are `api.anthropic.com`, `api.openai.com`, `generativelanguage.googleapis.com`, `api.x.ai`, `openrouter.ai`, `router.requesty.ai`, `api.cursor.com` and `opencode.ai`, plus `http://localhost:11434` for Ollama and `http://localhost:8080` for llama.cpp and MLX, which keeps their traffic on the machine. Every endpoint field is editable, and a custom provider goes wherever you point it. A chat turn carries: