feat(vscode): link custom providers to config

This commit is contained in:
Christiaan Arnoldus
2026-08-07 09:58:35 +02:00
parent d70ebd3191
commit ed63f985d9
26 changed files with 84 additions and 29 deletions
+1 -1
View File
@@ -3,4 +3,4 @@
"kilo-code": patch
---
Automatically expose broad reasoning effort options for custom provider models instead of requiring manual variant configuration.
Automatically expose broad reasoning effort options for custom provider models and link saved providers to advanced JSON configuration.
@@ -0,0 +1,14 @@
import { describe, expect, it } from "bun:test"
import { configMessage } from "../../webview-ui/src/utils/open-config"
describe("configMessage", () => {
it("builds a global config request with localized labels", () => {
const message = configMessage("global", (key, params) => `${key}:${params?.scope ?? ""}`)
expect(message.type).toBe("openConfigFile")
expect(message.scope).toBe("global")
expect(message.labels.scope).toBe("settings.config.scope.global:")
expect(message.labels.title).toBe("settings.config.title:settings.config.scope.global:")
expect(message.labels.openFailed).toBe("settings.config.openFailed:settings.config.scope.global:")
})
})
@@ -15,6 +15,7 @@ import { useProvider } from "../../context/provider"
import { useVSCode } from "../../context/vscode"
import type { ExtensionMessage, ProviderAuthState, ProviderConfig } from "../../types/messages"
import { createProviderAction } from "../../utils/provider-action"
import { configMessage } from "../../utils/open-config"
import { MASKED_CUSTOM_PROVIDER_KEY, resolveCustomProviderKey } from "../../../../src/shared/custom-provider"
import {
CUSTOM_PROVIDER_PACKAGE,
@@ -563,6 +564,19 @@ const CustomProviderDialog = (props: CustomProviderDialogProps) => {
{language.t("provider.custom.description.link")}
</a>
{language.t("provider.custom.description.suffix")}
<Show when={editing()}>
<div style={{ "margin-top": "8px" }}>
<a
href="#"
onClick={(e) => {
e.preventDefault()
vscode.postMessage(configMessage("global", language.t))
}}
>
{language.t("provider.custom.edit.advanced")}
</a>
</div>
</Show>
</div>
<div style={{ display: "flex", "flex-direction": "column", gap: "16px" }}>
@@ -28,6 +28,7 @@ import SandboxingTab from "./SandboxingTab"
import * as Sandboxing from "./sandboxing"
import { useServer } from "../../context/server"
import type { MigrationSource } from "../../types/messages"
import { configMessage } from "../../utils/open-config"
export interface SettingsProps {
tab?: string
@@ -66,34 +67,7 @@ const Settings: Component<SettingsProps> = (props) => {
}
const open = (scope: "local" | "global") => {
const label =
scope === "global" ? language.t("settings.config.scope.global") : language.t("settings.config.scope.local")
vscode.postMessage({
type: "openConfigFile",
scope,
labels: {
scope: label,
statusLoaded: language.t("settings.config.status.loaded"),
statusLoadedLegacy: language.t("settings.config.status.loadedLegacy"),
statusNotLoaded: language.t("settings.config.status.notLoaded"),
statusCreate: language.t("settings.config.status.create"),
title: language.t("settings.config.title", { scope: label }),
placeholder: language.t("settings.config.placeholder"),
noWorkspace: language.t("settings.config.noWorkspace"),
openFailed: language.t("settings.config.openFailed", { scope: label, message: "{{message}}" }),
sourceXdg: language.t("settings.config.source.xdg"),
sourceHomeKilo: language.t("settings.config.source.homeKilo"),
sourceHomeKilocode: language.t("settings.config.source.homeKilocode"),
sourceHomeOpencode: language.t("settings.config.source.homeOpencode"),
sourceEnvFile: language.t("settings.config.source.envFile"),
sourceEnvDir: language.t("settings.config.source.envDir"),
sourceEnvContent: language.t("settings.config.source.envContent"),
sourceProjectKilo: language.t("settings.config.source.projectKilo"),
sourceProjectRoot: language.t("settings.config.source.projectRoot"),
sourceProjectKilocode: language.t("settings.config.source.projectKilocode"),
sourceProjectOpencode: language.t("settings.config.source.projectOpencode"),
},
})
vscode.postMessage(configMessage(scope, language.t))
}
// Sync when the parent changes the tab prop (e.g. via navigate message)
+1
View File
@@ -455,6 +455,7 @@ export const dict = {
"provider.custom.models.fetch.search": "البحث في النماذج\u2026",
"provider.custom.models.fetch.add": "إضافة {{count}} نموذج(نماذج)",
"provider.custom.edit.title": "تعديل المزود",
"provider.custom.edit.advanced": "تحرير الإعدادات المتقدمة في ملف إعداد JSON",
"provider.custom.headers.label": "الرؤوس (اختياري)",
"provider.custom.headers.key.label": "الرأس",
"provider.custom.headers.key.placeholder": "Header-Name",
+1
View File
@@ -466,6 +466,7 @@ export const dict = {
"provider.custom.models.fetch.search": "Pesquisar modelos\u2026",
"provider.custom.models.fetch.add": "Adicionar {{count}} modelo(s)",
"provider.custom.edit.title": "Editar provedor",
"provider.custom.edit.advanced": "Editar configurações avançadas no arquivo de configuração JSON",
"provider.custom.headers.label": "Headers (opcional)",
"provider.custom.headers.key.label": "Cabeçalho",
"provider.custom.headers.key.placeholder": "Header-Name",
+1
View File
@@ -509,6 +509,7 @@ export const dict = {
"provider.custom.models.fetch.search": "Pretraži modele\u2026",
"provider.custom.models.fetch.add": "Dodaj {{count}} model(a)",
"provider.custom.edit.title": "Uredi provajdera",
"provider.custom.edit.advanced": "Uredite napredne postavke u JSON konfiguracijskoj datoteci",
"provider.custom.headers.label": "Zaglavlja (opcionalno)",
"provider.custom.headers.key.label": "Zaglavlje",
"provider.custom.headers.key.placeholder": "Header-Name",
+1
View File
@@ -506,6 +506,7 @@ export const dict = {
"provider.custom.models.fetch.search": "Søg modeller\u2026",
"provider.custom.models.fetch.add": "Tilføj {{count}} model(ler)",
"provider.custom.edit.title": "Rediger udbyder",
"provider.custom.edit.advanced": "Rediger avancerede indstillinger i JSON-konfigurationsfilen",
"provider.custom.headers.label": "Headers (valgfrit)",
"provider.custom.headers.key.label": "Header",
"provider.custom.headers.key.placeholder": "Header-Name",
@@ -517,6 +517,7 @@ export const dict = {
"provider.custom.models.fetch.search": "Modelle suchen\u2026",
"provider.custom.models.fetch.add": "{{count}} Modell(e) hinzufügen",
"provider.custom.edit.title": "Anbieter bearbeiten",
"provider.custom.edit.advanced": "Erweiterte Einstellungen in der JSON-Konfigurationsdatei bearbeiten",
"provider.custom.headers.label": "Header (optional)",
"provider.custom.headers.key.label": "Kopfzeile",
"provider.custom.headers.key.placeholder": "Header-Name",
@@ -420,6 +420,7 @@ export const dict = {
"provider.custom.models.fetch.search": "Search models\u2026",
"provider.custom.models.fetch.add": "Add {{count}} model(s)",
"provider.custom.edit.title": "Edit provider",
"provider.custom.edit.advanced": "Edit advanced settings in the JSON config file",
"provider.custom.headers.label": "Headers (optional)",
"provider.custom.headers.key.label": "Header",
"provider.custom.headers.key.placeholder": "Header-Name",
+1
View File
@@ -510,6 +510,7 @@ export const dict = {
"provider.custom.models.fetch.search": "Buscar modelos\u2026",
"provider.custom.models.fetch.add": "Añadir {{count}} modelo(s)",
"provider.custom.edit.title": "Editar proveedor",
"provider.custom.edit.advanced": "Editar la configuración avanzada en el archivo de configuración JSON",
"provider.custom.headers.label": "Headers (opcional)",
"provider.custom.headers.key.label": "Header",
"provider.custom.headers.key.placeholder": "Header-Name",
+1
View File
@@ -421,6 +421,7 @@ export const dict = {
"provider.custom.models.fetch.search": "جستجوی مدل‌ها…",
"provider.custom.models.fetch.add": "افزودن {{count}} مدل",
"provider.custom.edit.title": "ویرایش ارائه‌دهنده",
"provider.custom.edit.advanced": "ویرایش تنظیمات پیشرفته در فایل پیکربندی JSON",
"provider.custom.headers.label": "هدرها (اختیاری)",
"provider.custom.headers.key.label": "هدر",
"provider.custom.headers.key.placeholder": "Header-Name",
+1
View File
@@ -510,6 +510,7 @@ export const dict = {
"provider.custom.models.fetch.search": "Rechercher des modèles\u2026",
"provider.custom.models.fetch.add": "Ajouter {{count}} modèle(s)",
"provider.custom.edit.title": "Modifier le fournisseur",
"provider.custom.edit.advanced": "Modifier les paramètres avancés dans le fichier de configuration JSON",
"provider.custom.headers.label": "En-têtes (optionnel)",
"provider.custom.headers.key.label": "En-tête",
"provider.custom.headers.key.placeholder": "Header-Name",
+1
View File
@@ -330,6 +330,7 @@ export const dict = {
"provider.custom.models.fetch.search": "Cerca modelli...",
"provider.custom.models.fetch.add": "Aggiungi {{count}} modelli",
"provider.custom.edit.title": "Modifica provider",
"provider.custom.edit.advanced": "Modifica le impostazioni avanzate nel file di configurazione JSON",
"provider.custom.headers.label": "Header (opzionali)",
"provider.custom.headers.key.label": "Header",
"provider.custom.headers.key.placeholder": "Nome-Header",
+1
View File
@@ -502,6 +502,7 @@ export const dict = {
"provider.custom.models.fetch.search": "モデルを検索\u2026",
"provider.custom.models.fetch.add": "{{count}}個のモデルを追加",
"provider.custom.edit.title": "プロバイダーを編集",
"provider.custom.edit.advanced": "JSON 設定ファイルで詳細設定を編集",
"provider.custom.headers.label": "ヘッダー(任意)",
"provider.custom.headers.key.label": "ヘッダー",
"provider.custom.headers.key.placeholder": "Header-Name",
+1
View File
@@ -463,6 +463,7 @@ export const dict = {
"provider.custom.models.fetch.search": "모델 검색\u2026",
"provider.custom.models.fetch.add": "{{count}}개 모델 추가",
"provider.custom.edit.title": "공급자 편집",
"provider.custom.edit.advanced": "JSON 구성 파일에서 고급 설정 편집",
"provider.custom.headers.label": "헤더 (선택사항)",
"provider.custom.headers.key.label": "헤더",
"provider.custom.headers.key.placeholder": "Header-Name",
+1
View File
@@ -460,6 +460,7 @@ export const dict = {
"provider.custom.models.fetch.search": "Modellen zoeken\u2026",
"provider.custom.models.fetch.add": "{{count}} model(len) toevoegen",
"provider.custom.edit.title": "Provider bewerken",
"provider.custom.edit.advanced": "Geavanceerde instellingen bewerken in het JSON-configuratiebestand",
"provider.custom.headers.label": "Headers (optioneel)",
"provider.custom.headers.key.label": "Header",
"provider.custom.headers.key.placeholder": "Header-Naam",
+1
View File
@@ -469,6 +469,7 @@ export const dict = {
"provider.custom.models.fetch.search": "Søk etter modeller\u2026",
"provider.custom.models.fetch.add": "Legg til {{count}} modell(er)",
"provider.custom.edit.title": "Rediger leverandør",
"provider.custom.edit.advanced": "Rediger avanserte innstillinger i JSON-konfigurasjonsfilen",
"provider.custom.headers.label": "Headere (valgfritt)",
"provider.custom.headers.key.label": "Header",
"provider.custom.headers.key.placeholder": "Header-Name",
+1
View File
@@ -465,6 +465,7 @@ export const dict = {
"provider.custom.models.fetch.search": "Szukaj modeli\u2026",
"provider.custom.models.fetch.add": "Dodaj {{count}} model(i)",
"provider.custom.edit.title": "Edytuj dostawcę",
"provider.custom.edit.advanced": "Edytuj ustawienia zaawansowane w pliku konfiguracji JSON",
"provider.custom.headers.label": "Nagłówki (opcjonalnie)",
"provider.custom.headers.key.label": "Nagłówek",
"provider.custom.headers.key.placeholder": "Header-Name",
+1
View File
@@ -503,6 +503,7 @@ export const dict = {
"provider.custom.models.fetch.search": "Поиск моделей\u2026",
"provider.custom.models.fetch.add": "Добавить {{count}} модель(ей)",
"provider.custom.edit.title": "Редактировать провайдера",
"provider.custom.edit.advanced": "Изменить расширенные настройки в файле конфигурации JSON",
"provider.custom.headers.label": "Заголовки (необязательно)",
"provider.custom.headers.key.label": "Заголовок",
"provider.custom.headers.key.placeholder": "Header-Name",
+1
View File
@@ -500,6 +500,7 @@ export const dict = {
"provider.custom.models.fetch.search": "ค้นหาโมเดล\u2026",
"provider.custom.models.fetch.add": "เพิ่ม {{count}} โมเดล",
"provider.custom.edit.title": "แก้ไขผู้ให้บริการ",
"provider.custom.edit.advanced": "แก้ไขการตั้งค่าขั้นสูงในไฟล์การกำหนดค่า JSON",
"provider.custom.headers.label": "ส่วนหัว (ไม่จำเป็น)",
"provider.custom.headers.key.label": "ส่วนหัว",
"provider.custom.headers.key.placeholder": "Header-Name",
+1
View File
@@ -455,6 +455,7 @@ export const dict = {
"provider.custom.models.fetch.search": "Model ara\u2026",
"provider.custom.models.fetch.add": "{{count}} model ekle",
"provider.custom.edit.title": "Sağlayıcıyı düzenle",
"provider.custom.edit.advanced": "JSON yapılandırma dosyasında gelişmiş ayarları düzenle",
"provider.custom.headers.label": "Başlıklar (isteğe bağlı)",
"provider.custom.headers.key.label": "Başlık",
"provider.custom.headers.key.placeholder": "Başlık-Adı",
+1
View File
@@ -458,6 +458,7 @@ export const dict = {
"provider.custom.models.fetch.search": "Пошук моделей\u2026",
"provider.custom.models.fetch.add": "Додати {{count}} моделей",
"provider.custom.edit.title": "Редагувати провайдера",
"provider.custom.edit.advanced": "Редагувати розширені налаштування у файлі конфігурації JSON",
"provider.custom.headers.label": "Заголовки (необов'язково)",
"provider.custom.headers.key.label": "Заголовок",
"provider.custom.headers.key.placeholder": "Назва-заголовка",
+1
View File
@@ -485,6 +485,7 @@ export const dict = {
"provider.custom.models.fetch.search": "搜索模型\u2026",
"provider.custom.models.fetch.add": "添加 {{count}} 个模型",
"provider.custom.edit.title": "编辑提供商",
"provider.custom.edit.advanced": "在 JSON 配置文件中编辑高级设置",
"provider.custom.headers.label": "请求头(可选)",
"provider.custom.headers.key.label": "请求头",
"provider.custom.headers.key.placeholder": "Header-Name",
+1
View File
@@ -445,6 +445,7 @@ export const dict = {
"provider.custom.models.fetch.search": "搜尋模型\u2026",
"provider.custom.models.fetch.add": "新增 {{count}} 個模型",
"provider.custom.edit.title": "編輯供應商",
"provider.custom.edit.advanced": "在 JSON 設定檔中編輯進階設定",
"provider.custom.headers.label": "標頭(選填)",
"provider.custom.headers.key.label": "標頭",
"provider.custom.headers.key.placeholder": "Header-Name",
@@ -0,0 +1,32 @@
import type { LanguageContextValue } from "../context/language"
import type { OpenConfigFileRequest } from "../types/messages"
export function configMessage(scope: "local" | "global", t: LanguageContextValue["t"]): OpenConfigFileRequest {
const label = t(scope === "global" ? "settings.config.scope.global" : "settings.config.scope.local")
return {
type: "openConfigFile",
scope,
labels: {
scope: label,
statusLoaded: t("settings.config.status.loaded"),
statusLoadedLegacy: t("settings.config.status.loadedLegacy"),
statusNotLoaded: t("settings.config.status.notLoaded"),
statusCreate: t("settings.config.status.create"),
title: t("settings.config.title", { scope: label }),
placeholder: t("settings.config.placeholder"),
noWorkspace: t("settings.config.noWorkspace"),
openFailed: t("settings.config.openFailed", { scope: label, message: "{{message}}" }),
sourceXdg: t("settings.config.source.xdg"),
sourceHomeKilo: t("settings.config.source.homeKilo"),
sourceHomeKilocode: t("settings.config.source.homeKilocode"),
sourceHomeOpencode: t("settings.config.source.homeOpencode"),
sourceEnvFile: t("settings.config.source.envFile"),
sourceEnvDir: t("settings.config.source.envDir"),
sourceEnvContent: t("settings.config.source.envContent"),
sourceProjectKilo: t("settings.config.source.projectKilo"),
sourceProjectRoot: t("settings.config.source.projectRoot"),
sourceProjectKilocode: t("settings.config.source.projectKilocode"),
sourceProjectOpencode: t("settings.config.source.projectOpencode"),
},
}
}