Files
eepp/src/tools/ecode/plugins/aiassistant/aiassistantplugin.hpp
Martín Lucas Golini b02fc1f3a6 Add dynamic AI model catalog and reasoning controls
Fetch and cache the models.dev catalog asynchronously, replacing bundled model lists when catalog data is available while preserving local and user-configured providers.

Update live AI Assistant instances after refresh, defer startup requests until the UI is ready, and cancel in-flight catalog requests during shutdown. Prioritize providers with configured credentials and infer each provider's cheapest title-generation model from catalog pricing.

Add model reasoning metadata, effort controls, request serialization, chat persistence, and localized UI labels. Refresh the bundled fallback models and support API keys for arbitrary catalog providers.

Fix ACP Agent mode message chunks enqueue ordering issue (ACP thought chunks were enqueued twice while answer chunks were enqueued once).

Fix UIDropDownList WrapContent sizing so dropdown width follows its text, skin, and padding, and tighten UIDropDown automatic height sizing.
2026-08-19 01:30:56 -03:00

99 lines
2.6 KiB
C++

#pragma once
#include "../plugin.hpp"
#include "../pluginmanager.hpp"
#include "llmmodelcatalog.hpp"
#include "protocol.hpp"
#include <mutex>
namespace ecode {
class LLMChatUI;
class AIAssistantPlugin : public PluginBase {
public:
struct AIAssistantConfig {
StyleSheetLength partition;
std::string modelProvider;
std::string modelName;
std::string agentName;
};
static PluginDefinition Definition() {
return { "aiassistant", "AI Assistant", "Chat with your favorite AI assistant",
AIAssistantPlugin::New, { 0, 1, 0 }, AIAssistantPlugin::NewSync };
}
static Plugin* New( PluginManager* pluginManager );
static Plugin* NewSync( PluginManager* pluginManager );
virtual ~AIAssistantPlugin();
static std::optional<std::string> getApiKeyFromProvider( const std::string& provider,
AIAssistantPlugin* instance );
std::string getId() override { return Definition().id; }
std::string getTitle() override { return Definition().name; }
std::string getDescription() override { return Definition().description; }
const LLMProviders& getProviders() { return mProviders; }
const ACPAgents& getAgents() { return mAgents; }
std::string getPluginStatePath() const;
std::string getConversationsPath() const;
LLMChatUI* newAIAssistant();
void onSaveState( IniFile* state ) override;
void setConfig( AIAssistantConfig&& config ) { mConfig = std::move( config ); }
bool displayReasoning() const { return mDisplayReasoning; }
protected:
LLMProviders mProviders;
ACPAgents mAgents;
bool mUIInit{ false };
bool mBrokenUserConfigFile{ false };
bool mDisplayReasoning{ false };
UIWidget* mStatusBar{ nullptr };
UIPushButton* mAIChatButton{ nullptr };
UnorderedMap<std::string, std::string> mApiKeys;
AIAssistantConfig mConfig;
Uint32 mAIChatButtonPosCbId{ 0 };
std::string mConfigFileError;
std::mutex mModelCatalogMutex;
std::optional<LLMModelCatalog::Settings> mModelCatalogSettings;
std::unique_ptr<LLMModelCatalog> mModelCatalog;
bool mModelCatalogRefreshStarted{ false };
AIAssistantPlugin( PluginManager* pluginManager, bool sync );
void load( PluginManager* pluginManager );
PluginRequestHandle processMessage( const PluginMessage& msg );
void loadAIAssistantConfig( const std::string& path, bool updateConfigFile );
void onRegisterEditor( UICodeEditor* editor ) override;
void onUnregisterEditor( UICodeEditor* editor ) override;
void onRegisterDocument( TextDocument* doc ) override;
void initUI();
void displayBrokenUserConfigFileWarning();
void refreshModelCatalogAsync();
void applyModelCatalog( LLMProviders providers );
};
} // namespace ecode