mirror of
https://github.com/Palm1r/QodeAssist.git
synced 2026-06-29 17:49:12 -04:00
refactor: Provider settings panel improve
This commit is contained in:
@@ -42,6 +42,11 @@ ProviderDetailPane::ProviderDetailPane(QWidget *parent)
|
||||
spp.setColor(QPalette::WindowText, Utils::creatorColor(Utils::Theme::PanelTextColorMid));
|
||||
m_sourcePathLabel->setPalette(spp);
|
||||
|
||||
m_protocolLabel = new QLabel(this);
|
||||
m_protocolLabel->setPalette(spp);
|
||||
m_protocolLabel->setToolTip(
|
||||
tr("The client API (protocol) this provider speaks. Fixed when the provider is created."));
|
||||
|
||||
m_editBtn = new QPushButton(tr("Edit…"), this);
|
||||
m_editBtn->setDefault(true);
|
||||
m_openInEditorBtn = new QPushButton(tr("Open in editor"), this);
|
||||
@@ -89,6 +94,7 @@ ProviderDetailPane::ProviderDetailPane(QWidget *parent)
|
||||
headerLeft->setContentsMargins(0, 0, 0, 0);
|
||||
headerLeft->setSpacing(2);
|
||||
headerLeft->addLayout(titleRow);
|
||||
headerLeft->addWidget(m_protocolLabel);
|
||||
headerLeft->addWidget(m_sourcePathLabel);
|
||||
|
||||
auto *headerRow = new QHBoxLayout;
|
||||
@@ -107,8 +113,6 @@ ProviderDetailPane::ProviderDetailPane(QWidget *parent)
|
||||
|
||||
auto *identitySection = new SectionBox(tr("Identity"), this);
|
||||
m_nameEdit = new QLineEdit(this);
|
||||
m_typeEdit = new QLineEdit(this);
|
||||
m_typeEdit->setReadOnly(true);
|
||||
m_descriptionEdit = new QPlainTextEdit(this);
|
||||
m_descriptionEdit->setMaximumHeight(60);
|
||||
m_descriptionEdit->setReadOnly(true);
|
||||
@@ -118,9 +122,6 @@ ProviderDetailPane::ProviderDetailPane(QWidget *parent)
|
||||
identityGrid->setVerticalSpacing(4);
|
||||
FormBuilder(identityGrid)
|
||||
.row(tr("Name:"), m_nameEdit)
|
||||
.row(tr("Client API:"), m_typeEdit,
|
||||
tr("The client API this provider speaks. "
|
||||
"Cannot be changed after creation."))
|
||||
.row(tr("Description:"), m_descriptionEdit);
|
||||
identitySection->bodyLayout()->addLayout(identityGrid);
|
||||
|
||||
@@ -151,8 +152,10 @@ ProviderDetailPane::ProviderDetailPane(QWidget *parent)
|
||||
m_revealKeyBtn = new QToolButton(this);
|
||||
m_revealKeyBtn->setText(QStringLiteral("👁"));
|
||||
m_revealKeyBtn->setCheckable(true);
|
||||
m_revealKeyBtn->setToolTip(tr("Show / hide API key"));
|
||||
m_revealKeyBtn->setToolTip(tr("Show / hide the API key (loads the stored key)"));
|
||||
connect(m_revealKeyBtn, &QToolButton::toggled, this, [this](bool on) {
|
||||
if (on && m_apiKeyEdit->text().isEmpty() && m_currentHasStoredKey)
|
||||
emit apiKeyRevealRequested();
|
||||
m_apiKeyEdit->setEchoMode(on ? QLineEdit::Normal : QLineEdit::Password);
|
||||
});
|
||||
m_apiKeySaveBtn = new QPushButton(tr("Save key"), this);
|
||||
@@ -307,7 +310,7 @@ void ProviderDetailPane::populate(const Providers::ProviderInstance &inst, bool
|
||||
inst.description.isEmpty() ? tr("No description provided.") : inst.description);
|
||||
|
||||
m_nameEdit->setText(inst.name);
|
||||
m_typeEdit->setText(inst.clientApi);
|
||||
m_protocolLabel->setText(tr("via %1").arg(inst.clientApi));
|
||||
m_descriptionEdit->setPlainText(inst.description);
|
||||
m_urlEdit->setText(inst.url);
|
||||
|
||||
@@ -363,7 +366,7 @@ void ProviderDetailPane::clear()
|
||||
m_sourcePathLabel->clear();
|
||||
m_descriptionLabel->clear();
|
||||
m_nameEdit->clear();
|
||||
m_typeEdit->clear();
|
||||
m_protocolLabel->clear();
|
||||
m_descriptionEdit->clear();
|
||||
m_urlEdit->clear();
|
||||
m_apiKeyEdit->clear();
|
||||
@@ -476,6 +479,16 @@ void ProviderDetailPane::changeEvent(QEvent *event)
|
||||
}
|
||||
}
|
||||
|
||||
void ProviderDetailPane::showRevealedKey(const QString &key)
|
||||
{
|
||||
if (key.isEmpty())
|
||||
return;
|
||||
m_apiKeyEdit->setText(key);
|
||||
m_apiKeyEdit->setEchoMode(QLineEdit::Normal);
|
||||
if (!m_revealKeyBtn->isChecked())
|
||||
m_revealKeyBtn->setChecked(true);
|
||||
}
|
||||
|
||||
void ProviderDetailPane::setEditing(bool on)
|
||||
{
|
||||
m_editing = on;
|
||||
|
||||
@@ -32,6 +32,7 @@ public:
|
||||
void populate(const Providers::ProviderInstance &inst, bool hasStoredKey);
|
||||
void clear();
|
||||
void refreshKeyStatus(bool hasStoredKey);
|
||||
void showRevealedKey(const QString &key);
|
||||
void setLaunchState(Providers::ProviderLauncher::State st, const QString &lastError);
|
||||
void resetLaunchTerminal(const QByteArray &scrollback);
|
||||
void appendLaunchBytes(const QByteArray &chunk);
|
||||
@@ -44,6 +45,7 @@ signals:
|
||||
void deleteRequested();
|
||||
void apiKeySaveRequested(const QString &newKey);
|
||||
void apiKeyClearRequested();
|
||||
void apiKeyRevealRequested();
|
||||
void launchStartRequested(const QString &providerName);
|
||||
void launchStopRequested(const QString &providerName);
|
||||
void launchRestartRequested(const QString &providerName);
|
||||
@@ -74,7 +76,7 @@ private:
|
||||
QLabel *m_descriptionLabel = nullptr;
|
||||
|
||||
QLineEdit *m_nameEdit = nullptr;
|
||||
QLineEdit *m_typeEdit = nullptr;
|
||||
QLabel *m_protocolLabel = nullptr;
|
||||
QPlainTextEdit *m_descriptionEdit = nullptr;
|
||||
QLineEdit *m_urlEdit = nullptr;
|
||||
QLabel *m_samplePreview = nullptr;
|
||||
|
||||
@@ -125,6 +125,8 @@ public:
|
||||
this, &ProvidersPageWidget::onApiKeySave);
|
||||
connect(m_detailPane, &ProviderDetailPane::apiKeyClearRequested,
|
||||
this, &ProvidersPageWidget::onApiKeyClear);
|
||||
connect(m_detailPane, &ProviderDetailPane::apiKeyRevealRequested,
|
||||
this, &ProvidersPageWidget::onApiKeyReveal);
|
||||
connect(m_detailPane, &ProviderDetailPane::launchStartRequested,
|
||||
this, &ProvidersPageWidget::onLaunchStart);
|
||||
connect(m_detailPane, &ProviderDetailPane::launchStopRequested,
|
||||
@@ -447,6 +449,16 @@ private slots:
|
||||
m_detailPane->refreshKeyStatus(true);
|
||||
}
|
||||
|
||||
void onApiKeyReveal()
|
||||
{
|
||||
if (!m_factory || !m_secrets || m_currentName.isEmpty())
|
||||
return;
|
||||
const auto *inst = m_factory->instanceByName(m_currentName);
|
||||
if (!inst || inst->apiKeyRef.isEmpty())
|
||||
return;
|
||||
m_detailPane->showRevealedKey(m_secrets->readKeySync(inst->apiKeyRef));
|
||||
}
|
||||
|
||||
void onApiKeyClear()
|
||||
{
|
||||
if (!m_factory || !m_secrets || m_currentName.isEmpty())
|
||||
|
||||
@@ -2,7 +2,7 @@ schema_version = 1
|
||||
|
||||
name = "Claude"
|
||||
client_api = "Claude"
|
||||
description = "Anthropic's hosted Claude API."
|
||||
description = "Cloud (Anthropic). Claude Opus/Sonnet/Haiku via the Messages API."
|
||||
|
||||
url = "https://api.anthropic.com"
|
||||
api_key_ref = "qodeassist/providers/Claude"
|
||||
|
||||
@@ -2,7 +2,7 @@ schema_version = 1
|
||||
|
||||
name = "Codestral"
|
||||
client_api = "Codestral"
|
||||
description = "Mistral's Codestral FIM-capable code model API."
|
||||
description = "Cloud (Mistral). Codestral — a code model with native fill-in-the-middle, great for completion."
|
||||
|
||||
url = "https://codestral.mistral.ai"
|
||||
api_key_ref = "qodeassist/providers/Codestral"
|
||||
|
||||
@@ -2,7 +2,7 @@ schema_version = 1
|
||||
|
||||
name = "Google AI"
|
||||
client_api = "Google AI"
|
||||
description = "Google AI Studio (Gemini) hosted API."
|
||||
description = "Cloud (Google). Gemini models via Google AI Studio."
|
||||
|
||||
url = "https://generativelanguage.googleapis.com/v1beta"
|
||||
api_key_ref = "qodeassist/providers/Google AI"
|
||||
|
||||
@@ -2,7 +2,7 @@ schema_version = 1
|
||||
|
||||
name = "llama.cpp"
|
||||
client_api = "llama.cpp"
|
||||
description = "Local llama.cpp server (llama-server)."
|
||||
description = "Local (llama.cpp). Your own llama-server running GGUF models. Point the URL at your server (default :8080)."
|
||||
|
||||
url = "http://localhost:8080"
|
||||
api_key_ref = "qodeassist/providers/llama.cpp"
|
||||
|
||||
@@ -2,7 +2,7 @@ schema_version = 1
|
||||
|
||||
name = "LM Studio (Chat Completions)"
|
||||
client_api = "LM Studio (Chat Completions)"
|
||||
description = "Local LM Studio server over the /v1/chat/completions endpoint."
|
||||
description = "Local (LM Studio). The OpenAI Chat Completions API — the right pick for most LM Studio models."
|
||||
|
||||
url = "http://localhost:1234"
|
||||
api_key_ref = "qodeassist/providers/LM Studio (Chat Completions)"
|
||||
|
||||
@@ -2,7 +2,7 @@ schema_version = 1
|
||||
|
||||
name = "LM Studio (Responses API)"
|
||||
client_api = "LM Studio (Responses API)"
|
||||
description = "Local LM Studio server over the /v1/responses endpoint."
|
||||
description = "Local (LM Studio). The newer Responses API — use only if your model needs it, otherwise pick LM Studio (Chat Completions)."
|
||||
|
||||
url = "http://localhost:1234"
|
||||
api_key_ref = "qodeassist/providers/LM Studio (Responses API)"
|
||||
|
||||
@@ -2,7 +2,7 @@ schema_version = 1
|
||||
|
||||
name = "Mistral AI"
|
||||
client_api = "Mistral AI"
|
||||
description = "Mistral's hosted chat / completions API."
|
||||
description = "Cloud (Mistral). Mistral chat/instruct models, incl. the Magistral reasoning model. For Mistral's FIM code model, use Codestral."
|
||||
|
||||
url = "https://api.mistral.ai"
|
||||
api_key_ref = "qodeassist/providers/Mistral AI"
|
||||
|
||||
@@ -2,7 +2,7 @@ schema_version = 1
|
||||
|
||||
name = "Ollama (OpenAI-compatible)"
|
||||
client_api = "Ollama (OpenAI-compatible)"
|
||||
description = "Local Ollama daemon spoken to via the OpenAI-compatible /v1 routes."
|
||||
description = "Local (Ollama). The OpenAI-compatible /v1 routes — for OpenAI-style agents. For everyday use prefer Ollama (Native)."
|
||||
|
||||
url = "http://localhost:11434"
|
||||
api_key_ref = "qodeassist/providers/Ollama (OpenAI-compatible)"
|
||||
|
||||
@@ -2,7 +2,7 @@ schema_version = 1
|
||||
|
||||
name = "Ollama (Native)"
|
||||
client_api = "Ollama (Native)"
|
||||
description = "Default local Ollama daemon over its native /api/* endpoints."
|
||||
description = "Local (Ollama). The default — native /api endpoints with the best support for FIM, thinking and tools. Use this for the bundled Ollama agents."
|
||||
|
||||
url = "http://localhost:11434"
|
||||
api_key_ref = "qodeassist/providers/Ollama (Native)"
|
||||
|
||||
@@ -2,7 +2,7 @@ schema_version = 1
|
||||
|
||||
name = "OpenAI (Chat Completions)"
|
||||
client_api = "OpenAI (Chat Completions)"
|
||||
description = "OpenAI's hosted /v1/chat/completions endpoint."
|
||||
description = "Cloud (OpenAI). GPT models via the standard Chat Completions API. The default OpenAI choice."
|
||||
|
||||
url = "https://api.openai.com/v1"
|
||||
api_key_ref = "qodeassist/providers/OpenAI (Chat Completions)"
|
||||
|
||||
@@ -2,7 +2,7 @@ schema_version = 1
|
||||
|
||||
name = "OpenAI Compatible"
|
||||
client_api = "OpenAI Compatible"
|
||||
description = "Self-hosted OpenAI-compatible server (vLLM, TGI, ...). Edit the URL to match your deployment."
|
||||
description = "Self-hosted, OpenAI-compatible server (vLLM, TGI, LiteLLM, …). Point the URL at your deployment."
|
||||
|
||||
url = "http://localhost:1234/v1"
|
||||
api_key_ref = "qodeassist/providers/OpenAI Compatible"
|
||||
|
||||
@@ -2,7 +2,7 @@ schema_version = 1
|
||||
|
||||
name = "OpenAI (Responses API)"
|
||||
client_api = "OpenAI (Responses API)"
|
||||
description = "OpenAI's hosted /v1/responses endpoint."
|
||||
description = "Cloud (OpenAI). GPT models via the newer Responses API (needed for some o-series reasoning models). If unsure, use OpenAI (Chat Completions)."
|
||||
|
||||
url = "https://api.openai.com/v1"
|
||||
api_key_ref = "qodeassist/providers/OpenAI (Responses API)"
|
||||
|
||||
@@ -2,7 +2,7 @@ schema_version = 1
|
||||
|
||||
name = "OpenRouter"
|
||||
client_api = "OpenRouter"
|
||||
description = "OpenRouter aggregator (https://openrouter.ai)."
|
||||
description = "Cloud aggregator (openrouter.ai) — a single gateway to models from many providers (Anthropic, OpenAI, Google, Meta, …)."
|
||||
|
||||
url = "https://openrouter.ai/api"
|
||||
api_key_ref = "qodeassist/providers/OpenRouter"
|
||||
|
||||
Reference in New Issue
Block a user