wxMaxima
Loading...
Searching...
No Matches
AiProvider.h
Go to the documentation of this file.
1// -*- mode: c++; c-file-style: "linux"; c-basic-offset: 2; indent-tabs-mode: nil -*-
2//
3// Copyright (C) 2026 Gunter Königsmann <wxMaxima@physikbuch.de>
4//
5// This program is free software; you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation; either version 2 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15//
16// You should have received a copy of the GNU General Public License
17// along with this program; if not, write to the Free Software
18// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19//
20// SPDX-License-Identifier: GPL-2.0+
21
22#ifndef AIPROVIDER_H
23#define AIPROVIDER_H
24
25#include "precomp.h"
26#include <wx/wx.h>
27#include <functional>
28#include <memory>
29#include <vector>
30
48 wxString role;
49 wxString content;
50};
51
70enum class AiProviderKind {
71 None = 0, Anthropic = 1, OpenAI = 2, Google = 3, Qwen = 4, Custom = 5, GitHubModels = 6,
72 DeepSeek = 7, OpenRouter = 8
73};
74
86enum class AiProviderShape { Anthropic, OpenAiCompatible, Google };
87
91
105AiProviderShape AiProviderShapeFromChoiceIndex(int index);
106
124wxString AiProviderRequestUrlProblem(const wxString &url);
125
135 wxString id;
137 wxString name;
138 AiProviderShape shape = AiProviderShape::OpenAiCompatible;
142 wxString baseUrl;
143 wxString model;
160 wxString username;
161};
162
172 wxString name;
173 wxString baseUrl;
174 wxString model;
175};
176
181std::vector<AiLocalServerPreset> AiKnownLocalServerPresets();
182
186wxString NewAiCustomProviderId();
187
192std::vector<AiCustomProviderConfig> ParseAiCustomProviders(const wxString &json);
193
196wxString SerializeAiCustomProviders(const std::vector<AiCustomProviderConfig> &providers);
197
200
205
214
224wxString AiProviderBaseUrl(AiProviderKind kind);
225
236
256using AiRequestCanceller = std::function<void()>;
257
267public:
268 AiProvider(wxString baseUrl, wxString apiKey, wxString model)
269 : m_baseUrl(std::move(baseUrl)), m_apiKey(std::move(apiKey)),
270 m_model(std::move(model)) {}
271 virtual ~AiProvider() = default;
272
273 virtual AiProviderKind Kind() const = 0;
278 wxString Name() const {
279 return m_displayName.IsEmpty() ? AiProviderKindName(Kind()) : m_displayName;
280 }
281 void SetDisplayName(const wxString &name) { m_displayName = name; }
282
289 void SetBasicAuthUser(const wxString &user) { m_basicAuthUser = user; }
290
298 static bool SecretStoreAvailable();
299
304 static void SaveApiKey(const wxString &service, const wxString &apiKey);
308 static wxString LoadApiKey(const wxString &service);
309 static void DeleteApiKey(const wxString &service);
314 static wxString CustomProviderSecretService(const wxString &id);
320 static wxString BuiltinProviderSecretService(AiProviderKind kind);
321
324 virtual wxString RequestUrl() const { return m_baseUrl; }
325
328 virtual std::vector<std::pair<wxString, wxString>> AuthHeaders() const = 0;
329
335 virtual wxString BuildRequestBody(const wxString &context,
336 const std::vector<AiChatMessage> &history) const = 0;
337
341 virtual wxString ParseReply(const wxString &responseBody) const = 0;
342
364 static AiRequestCanceller
365 SendChat(std::shared_ptr<const AiProvider> self, wxEvtHandler *owner,
366 const wxString &context,
367 const std::vector<AiChatMessage> &history,
368 std::function<void(bool ok, const wxString &replyOrError)> callback,
369 std::function<void(const wxString &requestBody)> onRequest = nullptr,
370 std::function<void(bool ok, const wxString &responseBodyOrDetail)> onResponse = nullptr);
371
385 virtual wxString ModelsRequestUrl() const;
386
395 virtual std::vector<wxString> ParseModelList(const wxString &responseBody) const;
396
405 static void FetchModels(std::shared_ptr<const AiProvider> self, wxEvtHandler *owner,
406 std::function<void(bool ok, const std::vector<wxString> &models,
407 const wxString &errorIfAny)> callback);
408
413 static bool NetworkingAvailable();
414
415protected:
420 bool UsesBasicAuth() const { return !m_basicAuthUser.IsEmpty(); }
423 std::pair<wxString, wxString> BasicAuthHeader() const;
424
425 wxString m_baseUrl;
426 wxString m_apiKey;
427 wxString m_model;
428 wxString m_displayName;
429 wxString m_basicAuthUser;
430};
431
435class AiProviderError : public std::runtime_error {
436public:
437 explicit AiProviderError(const std::string &msg) : std::runtime_error(msg) {}
438};
439
444std::shared_ptr<AiProvider> MakeAiProvider(AiProviderKind kind, const wxString &apiKey,
445 const wxString &model);
446
453std::shared_ptr<AiProvider> MakeAiProviderForShape(AiProviderShape shape,
454 const wxString &displayName,
455 const wxString &baseUrl,
456 const wxString &apiKey,
457 const wxString &model,
458 const wxString &basicAuthUser = wxEmptyString);
459
460#endif // AIPROVIDER_H
wxString AiProviderApiKeyUrl(AiProviderKind kind)
Where to go to create/find an API key for this provider – shown as a link next to that provider's key...
Definition: AiProvider.cpp:435
std::shared_ptr< AiProvider > MakeAiProviderForShape(AiProviderShape shape, const wxString &displayName, const wxString &baseUrl, const wxString &apiKey, const wxString &model, const wxString &basicAuthUser=wxEmptyString)
Builds a provider for a user-added custom entry: reuses the exact same request/response-shape impleme...
Definition: AiProvider.cpp:525
std::vector< AiCustomProviderConfig > ParseAiCustomProviders(const wxString &json)
Parses Configuration::AiCustomProvidersJson() back into a list; returns an empty list for an empty or...
Definition: AiProvider.cpp:580
int AiProviderShapeToChoiceIndex(AiProviderShape shape)
The two halves of the shape picker's index <-> enum mapping.
Definition: AiProvider.cpp:359
AiProviderShape
Which request/response wire format a provider uses. The four built-in AiProviderKinds each hardcode o...
Definition: AiProvider.h:86
std::vector< AiLocalServerPreset > AiKnownLocalServerPresets()
A short, hand-picked list of common local LLM servers – not exhaustive, just the ones popular enough ...
Definition: AiProvider.cpp:552
std::function< void()> AiRequestCanceller
Cancels the one chat request it was handed out for, and does nothing at all once that request has fin...
Definition: AiProvider.h:256
wxString AiProviderBaseUrl(AiProviderKind kind)
A built-in provider's fixed request URL (Google's own, without the "<model>:generateContent" suffix i...
Definition: AiProvider.cpp:469
wxString AiProviderShapeName(AiProviderShape shape)
Human-readable name for the shape picker in the "Add custom provider" dialog.
Definition: AiProvider.cpp:347
wxString AiProviderModelListUrl(AiProviderKind kind)
Where to see this provider's current list of available model ids – shown as a link next to Options' m...
Definition: AiProvider.cpp:454
std::shared_ptr< AiProvider > MakeAiProvider(AiProviderKind kind, const wxString &apiKey, const wxString &model)
Builds the provider for this kind, or nullptr for AiProviderKind::None. Never called with AiProviderK...
Definition: AiProvider.cpp:486
wxString SerializeAiCustomProviders(const std::vector< AiCustomProviderConfig > &providers)
The inverse of ParseAiCustomProviders(), for Configuration:: AiCustomProvidersJson()'s setter.
Definition: AiProvider.cpp:621
wxString AiProviderRequestUrlProblem(const wxString &url)
Empty if url is usable as a custom provider's request URL; otherwise a short, user-facing explanation...
Definition: AiProvider.cpp:377
wxString NewAiCustomProviderId()
A fresh id for a new custom provider (see AiCustomProviderConfig::id) – never shown to the user,...
Definition: AiProvider.cpp:565
wxString AiProviderKindName(AiProviderKind kind)
Human-readable name for Options/the sidebar's status line.
Definition: AiProvider.cpp:328
wxString AiProviderDefaultModel(AiProviderKind kind)
This provider's built-in default model id, shown as Options' initial value for a not-yet-configured m...
Definition: AiProvider.cpp:399
AiProviderKind
Which AI service to talk to. Persisted as a plain int in Configuration; keep existing values stable a...
Definition: AiProvider.h:70
Thrown by ParseReply() for a response that doesn't parse or doesn't have the expected shape – distinc...
Definition: AiProvider.h:435
Talks to one external AI provider's chat completion HTTP API.
Definition: AiProvider.h:266
static bool NetworkingAvailable()
True if this build of wxWidgets has wxWebRequest at all (>= 3.1.5, built with a working backend) – if...
Definition: AiProvider.cpp:714
bool UsesBasicAuth() const
True when SetBasicAuthUser() was given a non-empty name, i.e. every AuthHeaders() override should sen...
Definition: AiProvider.h:420
static void FetchModels(std::shared_ptr< const AiProvider > self, wxEvtHandler *owner, std::function< void(bool ok, const std::vector< wxString > &models, const wxString &errorIfAny)> callback)
Asks the provider which models it offers, asynchronously, calling callback exactly once on the GUI th...
Definition: AiProvider.cpp:733
virtual std::vector< wxString > ParseModelList(const wxString &responseBody) const
The model ids in a successful (2xx) model-list response, most recently created first where the provid...
Definition: AiProvider.cpp:729
std::pair< wxString, wxString > BasicAuthHeader() const
"Authorization: Basic base64(user:password)", with the API key as the password. Only meaningful while...
Definition: AiProvider.cpp:641
virtual std::vector< std::pair< wxString, wxString > > AuthHeaders() const =0
Any additional headers this provider's auth scheme needs, name/value pairs, beyond the "POST JSON" co...
static void SaveApiKey(const wxString &service, const wxString &apiKey)
Saves (or, for an empty key, deletes) an API key for service – a stable identifier: AiProviderKindNam...
Definition: AiProvider.cpp:668
static wxString BuiltinProviderSecretService(AiProviderKind kind)
The secret-store service name for one of the four built-in kinds – just AiProviderKindName(kind),...
Definition: AiProvider.cpp:656
wxString Name() const
AiProviderKindName(Kind()) for a built-in provider, or the user's own chosen name for a custom one (K...
Definition: AiProvider.h:278
static wxString CustomProviderSecretService(const wxString &id)
The secret-store service name for a custom provider's own id – kept distinct from a bare built-in kin...
Definition: AiProvider.cpp:652
virtual wxString BuildRequestBody(const wxString &context, const std::vector< AiChatMessage > &history) const =0
Builds the JSON request body for one chat turn.
static AiRequestCanceller SendChat(std::shared_ptr< const AiProvider > self, wxEvtHandler *owner, const wxString &context, const std::vector< AiChatMessage > &history, std::function< void(bool ok, const wxString &replyOrError)> callback, std::function< void(const wxString &requestBody)> onRequest=nullptr, std::function< void(bool ok, const wxString &responseBodyOrDetail)> onResponse=nullptr)
Sends one chat turn asynchronously via wxWebRequest and calls callback(ok, replyOrError) exactly once...
Definition: AiProvider.cpp:833
void SetBasicAuthUser(const wxString &user)
Makes this provider authenticate with HTTP Basic instead of its own credential header,...
Definition: AiProvider.h:289
virtual wxString RequestUrl() const
The full URL SendChat() will POST to. Virtual so Google's provider can append the model id (its endpo...
Definition: AiProvider.h:324
virtual wxString ModelsRequestUrl() const
The URL FetchModels() asks for this provider's current model ids, or an empty string if there is noth...
Definition: AiProvider.cpp:722
virtual wxString ParseReply(const wxString &responseBody) const =0
Extracts the assistant's reply text from a successful (2xx) response body.
static bool SecretStoreAvailable()
True if this build of wxWidgets has a working wxSecretStore backend (>= 3.1.1, compiled with wxUSE_SE...
Definition: AiProvider.cpp:660
static wxString LoadApiKey(const wxString &service)
Returns the stored key for service, or an empty string if none is stored (also the result if !...
Definition: AiProvider.cpp:688
One turn of a chat conversation.
Definition: AiProvider.h:44
wxString role
"user" or "assistant" – never "system"/"model"/etc.; each provider's own request-building maps this p...
Definition: AiProvider.h:48
One user-added custom provider, as persisted in Configuration's AiCustomProvidersJson() (everything e...
Definition: AiProvider.h:130
wxString id
Stable, internally-generated identifier – never shown in the UI and never reused, so renaming a provi...
Definition: AiProvider.h:135
wxString baseUrl
Full request URL for OpenAI-compatible/Anthropic shapes; for Google's shape, the part before "<model>...
Definition: AiProvider.h:142
wxString username
Username for HTTP Basic authentication, empty when none is needed.
Definition: AiProvider.h:160
wxString name
User-chosen display name, shown in the provider dropdown.
Definition: AiProvider.h:137
One well-known local AI server's connection defaults, offered as a quick-fill preset in the "Add cust...
Definition: AiProvider.h:171