diff --git a/.changeset/hide-prompt-training-models.md b/.changeset/hide-prompt-training-models.md new file mode 100644 index 00000000000..6221e66b3cd --- /dev/null +++ b/.changeset/hide-prompt-training-models.md @@ -0,0 +1,6 @@ +--- +"kilo-code": patch +"@kilocode/cli": patch +--- + +Add a shared model setting to hide Kilo Gateway models that may train on your prompts across Kilo clients. diff --git a/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/models-accessible-labels-chromium-linux.png b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/models-accessible-labels-chromium-linux.png index 01ea6e7ac02..db7441c87c1 100644 --- a/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/models-accessible-labels-chromium-linux.png +++ b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/models-accessible-labels-chromium-linux.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bbfed6606c5e1ccd6a744bdadf34ee597007d5f82c436c8c53e189560e0837d4 -size 30244 +oid sha256:bae54b771e2d7da8c8b1dcab42d9d51662ec888ebb618b24af11e597c79df7b7 +size 37836 diff --git a/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/models-autocomplete-open-chromium-linux.png b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/models-autocomplete-open-chromium-linux.png index 01ea6e7ac02..db7441c87c1 100644 --- a/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/models-autocomplete-open-chromium-linux.png +++ b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/models-autocomplete-open-chromium-linux.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bbfed6606c5e1ccd6a744bdadf34ee597007d5f82c436c8c53e189560e0837d4 -size 30244 +oid sha256:bae54b771e2d7da8c8b1dcab42d9d51662ec888ebb618b24af11e597c79df7b7 +size 37836 diff --git a/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/settings-panel-chromium-linux.png b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/settings-panel-chromium-linux.png index 542e06b36ac..9fb41085b48 100644 --- a/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/settings-panel-chromium-linux.png +++ b/packages/kilo-docs/public/img/screenshot-tests/kilo-vscode/visual-regression/settings/settings-panel-chromium-linux.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6bcfc6c12f69c5131dcc8f294f480e26ff53f87e0c5943bf525e69c4c894ad21 -size 43744 +oid sha256:57fa5c60dd92a2f4299e58ead8a682c4802de415a496c247af2eba2faf0d63e4 +size 50341 diff --git a/packages/kilo-vscode/src/KiloProvider.ts b/packages/kilo-vscode/src/KiloProvider.ts index 022f2ba2347..d901654f4e0 100644 --- a/packages/kilo-vscode/src/KiloProvider.ts +++ b/packages/kilo-vscode/src/KiloProvider.ts @@ -2397,7 +2397,8 @@ export class KiloProvider implements vscode.WebviewViewProvider, TelemetryProper const refreshProviders = partial.provider !== undefined || partial.disabled_providers !== undefined || - partial.enabled_providers !== undefined + partial.enabled_providers !== undefined || + partial.hide_prompt_training_models !== undefined const refreshAgents = partial.default_agent !== undefined || partial.agent !== undefined || diff --git a/packages/kilo-vscode/tests/unit/kilo-provider-indexing-refresh.test.ts b/packages/kilo-vscode/tests/unit/kilo-provider-indexing-refresh.test.ts index 6b3b63388b6..31ed93fd4f0 100644 --- a/packages/kilo-vscode/tests/unit/kilo-provider-indexing-refresh.test.ts +++ b/packages/kilo-vscode/tests/unit/kilo-provider-indexing-refresh.test.ts @@ -109,6 +109,21 @@ describe("KiloProvider indexing refresh", () => { expect(indexing).toBe(0) }) + it("refreshes providers when prompt-training model visibility changes", async () => { + const conn = createConnection() + const provider = new KiloProvider({} as never, conn.service as never) + const internal = provider as unknown as Internals + let calls = 0 + internal.connectionState = "connected" + internal.fetchAndSendProviders = async () => { + calls += 1 + } + + await internal.handleUpdateConfig({ hide_prompt_training_models: true }) + + expect(calls).toBe(1) + }) + it("passes scoped unset paths to the config overlay endpoint", async () => { const conn = createConnection() const provider = new KiloProvider({} as never, conn.service as never) diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/ModelsTab.tsx b/packages/kilo-vscode/webview-ui/src/components/settings/ModelsTab.tsx index 4960afe249a..bd27ab6cc55 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/ModelsTab.tsx +++ b/packages/kilo-vscode/webview-ui/src/components/settings/ModelsTab.tsx @@ -1,5 +1,6 @@ import { Component, For, Show, createMemo } from "solid-js" import { Card } from "@kilocode/kilo-ui/card" +import { Switch } from "@kilocode/kilo-ui/switch" import { useConfig } from "../../context/config" import { useLanguage } from "../../context/language" import { useProvider } from "../../context/provider" @@ -154,7 +155,6 @@ const ModelsTab: Component = () => { { description={language.t("settings.autocomplete.model.description")} /> + + updateConfig({ hide_prompt_training_models: checked })} + hideLabel + > + {language.t("settings.models.hidePromptTraining.title")} + +

{language.t("settings.providers.modeModels")}

diff --git a/packages/kilo-vscode/webview-ui/src/components/settings/settings-io.ts b/packages/kilo-vscode/webview-ui/src/components/settings/settings-io.ts index 9fe4d324502..ab3e2598b35 100644 --- a/packages/kilo-vscode/webview-ui/src/components/settings/settings-io.ts +++ b/packages/kilo-vscode/webview-ui/src/components/settings/settings-io.ts @@ -37,6 +37,7 @@ export const KNOWN_KEYS: ReadonlyArray = [ "layout", "auto_collapse_reasoning", "terminal_command_display", + "hide_prompt_training_models", "indexing", "experimental", ] diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts index 87823256130..cc7804d3d35 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ar.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ar.ts @@ -824,6 +824,9 @@ export const dict = { "settings.providers.subagentModel.title": "نموذج الوكيل الفرعي", "settings.providers.subagentModel.description": "النموذج الافتراضي وجهد التفكير للوكلاء الفرعيين لـ task-tool. اتركه فارغًا ليرث نموذج الوكيل المستدعي.", + "settings.models.hidePromptTraining.title": "إخفاء النماذج التي تدرّب على المطالبات", + "settings.models.hidePromptTraining.description": + "إخفاء نماذج Kilo Gateway التي قد يستخدم مزودوها مطالباتك لأغراض التدريب.", "settings.providers.modeModels": "نموذج لكل وضع", "settings.providers.custom.note": "أضف موفرًا متوافقًا مع OpenAI عبر عنوان URL الأساسي.", "settings.providers.modeModels.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/br.ts b/packages/kilo-vscode/webview-ui/src/i18n/br.ts index 2da2912caab..aae8ae77930 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/br.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/br.ts @@ -836,6 +836,9 @@ export const dict = { "settings.providers.subagentModel.title": "Modelo de Subagente", "settings.providers.subagentModel.description": "Modelo padrão e esforço de raciocínio para subagentes do task-tool. Deixe em branco para herdar o modelo do agente chamador.", + "settings.models.hidePromptTraining.title": "Ocultar modelos que treinam com prompts", + "settings.models.hidePromptTraining.description": + "Oculte os modelos do Kilo Gateway cujos provedores podem usar seus prompts para treinamento.", "settings.providers.modeModels": "Modelo por Modo", "settings.providers.custom.note": "Adicione um provedor compatível com OpenAI por URL base.", "settings.providers.modeModels.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts index 79f9d982cfe..0cb63547806 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/bs.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/bs.ts @@ -877,6 +877,9 @@ export const dict = { "settings.providers.subagentModel.title": "Model podagenta", "settings.providers.subagentModel.description": "Zadani model i napor zaključivanja za podagente task-tool-a. Ostavite nepodešeno da naslijedi model pozivnog agenta.", + "settings.models.hidePromptTraining.title": "Sakrij modele koji treniraju na promptovima", + "settings.models.hidePromptTraining.description": + "Sakrij Kilo Gateway modele čiji pružaoci mogu koristiti vaše promptove za treniranje.", "settings.providers.modeModels": "Model po režimu", "settings.providers.custom.note": "Dodajte provajdera kompatibilnog s OpenAI putem osnovnog URL-a.", "settings.providers.modeModels.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/da.ts b/packages/kilo-vscode/webview-ui/src/i18n/da.ts index d4390284acc..06eb40d34f2 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/da.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/da.ts @@ -871,6 +871,9 @@ export const dict = { "settings.providers.subagentModel.title": "Underagentmodel", "settings.providers.subagentModel.description": "Standardmodel og ræsonnementsindsats for task-tool-underagenter. Lad den være tom for at nedarve den kaldende agents model.", + "settings.models.hidePromptTraining.title": "Skjul modeller, der træner på prompts", + "settings.models.hidePromptTraining.description": + "Skjul Kilo Gateway-modeller, hvis udbydere muligvis bruger dine prompts til træning.", "settings.providers.modeModels": "Model pr. tilstand", "settings.providers.custom.note": "Tilføj en OpenAI-kompatibel udbyder via basis-URL.", "settings.providers.modeModels.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/de.ts b/packages/kilo-vscode/webview-ui/src/i18n/de.ts index e4e5627d00d..57b4a201911 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/de.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/de.ts @@ -883,6 +883,9 @@ export const dict = { "settings.providers.subagentModel.title": "Subagenten-Modell", "settings.providers.subagentModel.description": "Standardmodell und Aufwand für Schlussfolgerungen für task-tool-Subagenten. Leer lassen, um das Modell des aufrufenden Agenten zu übernehmen.", + "settings.models.hidePromptTraining.title": "Modelle mit Prompt-Training ausblenden", + "settings.models.hidePromptTraining.description": + "Blendet Kilo-Gateway-Modelle aus, deren Anbieter Ihre Prompts möglicherweise zum Training verwenden.", "settings.providers.modeModels": "Modell pro Modus", "settings.providers.custom.note": "Fügen Sie einen OpenAI-kompatiblen Anbieter per Basis-URL hinzu.", "settings.providers.modeModels.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/en.ts b/packages/kilo-vscode/webview-ui/src/i18n/en.ts index 86b8aa78937..6c5f544a4ed 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/en.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/en.ts @@ -1504,6 +1504,9 @@ export const dict = { "settings.providers.subagentModel.title": "Subagent Model", "settings.providers.subagentModel.description": "Default model and reasoning effort for task-tool subagents. Leave unset to inherit the calling agent's model.", + "settings.models.hidePromptTraining.title": "Hide Prompt-Training Models", + "settings.models.hidePromptTraining.description": + "Hide Kilo Gateway models whose providers may use your prompts for training.", "settings.providers.modeModels": "Model per Mode", "settings.providers.modeModels.description": "Override the default model for specific modes. If not set, the global default model is used.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/es.ts b/packages/kilo-vscode/webview-ui/src/i18n/es.ts index d756101b4a0..960802b2445 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/es.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/es.ts @@ -879,6 +879,9 @@ export const dict = { "settings.providers.subagentModel.title": "Modelo de subagente", "settings.providers.subagentModel.description": "Modelo predeterminado y esfuerzo de razonamiento para los subagentes de task-tool. Déjelo sin configurar para heredar el modelo del agente invocador.", + "settings.models.hidePromptTraining.title": "Ocultar modelos que entrenan con prompts", + "settings.models.hidePromptTraining.description": + "Oculta los modelos de Kilo Gateway cuyos proveedores pueden usar tus prompts para entrenamiento.", "settings.providers.modeModels": "Modelo por modo", "settings.providers.custom.note": "Agrega un proveedor compatible con OpenAI mediante URL base.", "settings.providers.modeModels.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts index 58059b7b5e0..14ad670f316 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/fr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/fr.ts @@ -885,6 +885,9 @@ export const dict = { "settings.providers.subagentModel.title": "Modèle de sous-agent", "settings.providers.subagentModel.description": "Modèle par défaut et effort de raisonnement pour les sous-agents du task-tool. Laissez vide pour hériter du modèle de l'agent appelant.", + "settings.models.hidePromptTraining.title": "Masquer les modèles entraînés sur les prompts", + "settings.models.hidePromptTraining.description": + "Masquez les modèles Kilo Gateway dont les fournisseurs peuvent utiliser vos prompts à des fins d'entraînement.", "settings.providers.modeModels": "Modèle par mode", "settings.providers.custom.note": "Ajoutez un fournisseur compatible OpenAI par URL de base.", "settings.providers.modeModels.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/it.ts b/packages/kilo-vscode/webview-ui/src/i18n/it.ts index ba297b9c18b..d9d7b7c9ace 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/it.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/it.ts @@ -1526,6 +1526,9 @@ export const dict = { "settings.providers.subagentModel.title": "Modello sub-agent", "settings.providers.subagentModel.description": "Modello e sforzo di ragionamento predefiniti per i sub-agent del tool task. Lascia non impostato per ereditare il modello dell'agente chiamante.", + "settings.models.hidePromptTraining.title": "Nascondi i modelli che usano i prompt per l'addestramento", + "settings.models.hidePromptTraining.description": + "Nascondi i modelli Kilo Gateway i cui provider potrebbero usare i tuoi prompt per l'addestramento.", // Autocomplete hint "settings.autocomplete.modelsHint": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts index ca2ce756fe6..da1e7436dfa 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ja.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ja.ts @@ -867,6 +867,9 @@ export const dict = { "settings.providers.subagentModel.title": "サブエージェントモデル", "settings.providers.subagentModel.description": "task-tool サブエージェントのデフォルトモデルと推論の労力。呼び出し元のエージェントのモデルを継承する場合は未設定のままにしてください。", + "settings.models.hidePromptTraining.title": "プロンプトを学習に使用するモデルを非表示", + "settings.models.hidePromptTraining.description": + "プロバイダーがプロンプトを学習に使用する可能性のある Kilo Gateway モデルを非表示にします。", "settings.providers.modeModels": "モードごとのモデル", "settings.providers.custom.note": "Base URL で OpenAI 互換プロバイダーを追加します。", "settings.providers.modeModels.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts index d679e27bee9..6d50cf61847 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ko.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ko.ts @@ -829,6 +829,9 @@ export const dict = { "settings.providers.subagentModel.title": "하위 에이전트 모델", "settings.providers.subagentModel.description": "task-tool 하위 에이전트의 기본 모델 및 추론 수준입니다. 호출하는 에이전트의 모델을 상속하려면 비워 두세요.", + "settings.models.hidePromptTraining.title": "프롬프트를 학습에 사용하는 모델 숨기기", + "settings.models.hidePromptTraining.description": + "제공업체가 사용자의 프롬프트를 학습에 사용할 수 있는 Kilo Gateway 모델을 숨깁니다.", "settings.providers.modeModels": "모드별 모델", "settings.providers.custom.note": "Base URL로 OpenAI 호환 공급자를 추가합니다.", "settings.providers.modeModels.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts index 14a2cc42b82..716bbe1d18b 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/nl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/nl.ts @@ -1496,6 +1496,9 @@ export const dict = { "settings.providers.subagentModel.title": "Subagentmodel", "settings.providers.subagentModel.description": "Standaardmodel en redeneerinspanning voor task-tool subagenten. Laat leeg om het model van de aanroepende agent over te nemen.", + "settings.models.hidePromptTraining.title": "Modellen die prompts voor training gebruiken verbergen", + "settings.models.hidePromptTraining.description": + "Verberg Kilo Gateway-modellen waarvan providers je prompts mogelijk voor training gebruiken.", "settings.providers.modeModels": "Model per Modus", "settings.providers.modeModels.description": "Overschrijf het standaard model voor specifieke modi. Indien niet ingesteld, wordt het globale standaard model gebruikt.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/no.ts b/packages/kilo-vscode/webview-ui/src/i18n/no.ts index 3e1b704e95c..beef9ac7463 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/no.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/no.ts @@ -838,6 +838,9 @@ export const dict = { "settings.providers.subagentModel.title": "Underagentmodell", "settings.providers.subagentModel.description": "Standardmodell og resonneringsinnsats for task-tool-underagenter. La stå tom for å arve den kallende agentens modell.", + "settings.models.hidePromptTraining.title": "Skjul modeller som trener på ledetekster", + "settings.models.hidePromptTraining.description": + "Skjul Kilo Gateway-modeller der leverandørene kan bruke ledetekstene dine til trening.", "settings.providers.modeModels": "Modell per modus", "settings.providers.custom.note": "Legg til en OpenAI-kompatibel leverandør via basis-URL.", "settings.providers.modeModels.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts index 77b8f2160b8..012bb9c919e 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/pl.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/pl.ts @@ -836,6 +836,9 @@ export const dict = { "settings.providers.subagentModel.title": "Model podagenta", "settings.providers.subagentModel.description": "Domyślny model i wysiłek wnioskowania dla podagentów task-tool. Pozostaw puste, aby odziedziczyć model agenta wywołującego.", + "settings.models.hidePromptTraining.title": "Ukryj modele trenujące na promptach", + "settings.models.hidePromptTraining.description": + "Ukryj modele Kilo Gateway, których dostawcy mogą używać Twoich promptów do trenowania.", "settings.providers.modeModels": "Model na tryb", "settings.providers.custom.note": "Dodaj dostawcę kompatybilnego z OpenAI przez bazowy URL.", "settings.providers.modeModels.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts index 61cc7872f08..cccc0ec8f7b 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/ru.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/ru.ts @@ -875,6 +875,9 @@ export const dict = { "settings.providers.subagentModel.title": "Модель субагента", "settings.providers.subagentModel.description": "Модель по умолчанию и уровень рассуждения для субагентов task-tool. Оставьте пустым, чтобы унаследовать модель вызывающего агента.", + "settings.models.hidePromptTraining.title": "Скрывать модели, обучающиеся на запросах", + "settings.models.hidePromptTraining.description": + "Скрывать модели Kilo Gateway, поставщики которых могут использовать ваши запросы для обучения.", "settings.providers.modeModels": "Модель для режима", "settings.providers.custom.note": "Добавьте OpenAI-совместимого провайдера по базовому URL.", "settings.providers.modeModels.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/th.ts b/packages/kilo-vscode/webview-ui/src/i18n/th.ts index bc3bcdd18ec..e6ed8b94757 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/th.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/th.ts @@ -863,6 +863,8 @@ export const dict = { "settings.providers.subagentModel.title": "โมเดลตัวแทนย่อย", "settings.providers.subagentModel.description": "โมเดลเริ่มต้นและระดับการใช้เหตุผลสำหรับตัวแทนย่อยของ task-tool ปล่อยว่างไว้เพื่อรับค่าโมเดลจากตัวแทนที่เรียก", + "settings.models.hidePromptTraining.title": "ซ่อนโมเดลที่ใช้พรอมต์ในการฝึก", + "settings.models.hidePromptTraining.description": "ซ่อนโมเดล Kilo Gateway ที่ผู้ให้บริการอาจใช้พรอมต์ของคุณในการฝึก", "settings.providers.modeModels": "โมเดลต่อโหมด", "settings.providers.custom.note": "เพิ่มผู้ให้บริการที่รองรับ OpenAI ด้วย Base URL", "settings.providers.modeModels.description": diff --git a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts index 0925c620319..707171faa72 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/tr.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/tr.ts @@ -1485,6 +1485,9 @@ export const dict = { "settings.providers.subagentModel.title": "Alt Aracı Modeli", "settings.providers.subagentModel.description": "task-tool alt aracıları için varsayılan model ve akıl yürütme çabası. Çağıran aracının modelini devralmak için boş bırakın.", + "settings.models.hidePromptTraining.title": "İstemlerle eğitilen modelleri gizle", + "settings.models.hidePromptTraining.description": + "Sağlayıcıları istemlerinizi eğitim için kullanabilecek Kilo Gateway modellerini gizleyin.", "settings.providers.modeModels": "Mod Başına Model", "settings.providers.modeModels.description": "Belirli modlar için varsayılan modeli geçersiz kılın. Ayarlanmadıysa genel varsayılan model kullanılır.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/uk.ts b/packages/kilo-vscode/webview-ui/src/i18n/uk.ts index 3ff24e78cac..5d54096273b 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/uk.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/uk.ts @@ -1484,6 +1484,9 @@ export const dict = { "settings.providers.subagentModel.title": "Модель субагента", "settings.providers.subagentModel.description": "Модель за замовчуванням та рівень міркування для субагентів task-tool. Залиште порожнім, щоб успадкувати модель агента, що викликає.", + "settings.models.hidePromptTraining.title": "Приховувати моделі, що навчаються на запитах", + "settings.models.hidePromptTraining.description": + "Приховувати моделі Kilo Gateway, постачальники яких можуть використовувати ваші запити для навчання.", "settings.providers.modeModels": "Модель для кожного режиму", "settings.providers.modeModels.description": "Перевизначити стандартну модель для певних режимів. Якщо не встановлено, використовується загальна стандартна модель.", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts index 8470cde2a2b..cd32c4c248f 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zh.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zh.ts @@ -850,6 +850,8 @@ export const dict = { "settings.providers.custom.description": "通过基础 URL 添加 OpenAI 兼容的提供商。", "settings.providers.subagentModel.title": "子代理模型", "settings.providers.subagentModel.description": "task-tool 子代理的默认模型和推理工作量。留空以继承调用代理的模型。", + "settings.models.hidePromptTraining.title": "隐藏使用提示词训练的模型", + "settings.models.hidePromptTraining.description": "隐藏提供商可能会使用您的提示词进行训练的 Kilo Gateway 模型。", "settings.providers.modeModels": "按模式选择模型", "settings.providers.custom.note": "通过 Base URL 添加 OpenAI 兼容提供商。", "settings.providers.modeModels.description": "为特定模式覆盖默认模型。如果未设置,将使用全局默认模型。", diff --git a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts index edda8ac7240..7bfd5f39d95 100644 --- a/packages/kilo-vscode/webview-ui/src/i18n/zht.ts +++ b/packages/kilo-vscode/webview-ui/src/i18n/zht.ts @@ -818,6 +818,8 @@ export const dict = { "settings.providers.custom.description": "透過基礎 URL 新增 OpenAI 相容的提供商。", "settings.providers.subagentModel.title": "子代理模型", "settings.providers.subagentModel.description": "task-tool 子代理的預設模型和推理工作量。留空以繼承呼叫代理的模型。", + "settings.models.hidePromptTraining.title": "隱藏使用提示詞訓練的模型", + "settings.models.hidePromptTraining.description": "隱藏供應商可能會使用您的提示詞進行訓練的 Kilo Gateway 模型。", "settings.providers.modeModels": "按模式選擇模型", "settings.providers.custom.note": "透過 Base URL 新增 OpenAI 相容供應商。", "settings.providers.modeModels.description": "為特定模式覆寫預設模型。如果未設定,將使用全域預設模型。", diff --git a/packages/kilo-vscode/webview-ui/src/types/messages/config.ts b/packages/kilo-vscode/webview-ui/src/types/messages/config.ts index 74022ce09a1..381ad79b423 100644 --- a/packages/kilo-vscode/webview-ui/src/types/messages/config.ts +++ b/packages/kilo-vscode/webview-ui/src/types/messages/config.ts @@ -129,6 +129,7 @@ export interface Config { snapshot?: boolean remote_control?: boolean terminal_command_display?: TerminalCommandDisplay + hide_prompt_training_models?: boolean share?: "manual" | "auto" | "disabled" username?: string watcher?: WatcherConfig diff --git a/packages/opencode/src/config/config.ts b/packages/opencode/src/config/config.ts index e8c773b9254..457bfc9b047 100644 --- a/packages/opencode/src/config/config.ts +++ b/packages/opencode/src/config/config.ts @@ -223,6 +223,9 @@ export const Info = Schema.Struct({ terminal_command_display: Schema.optional(Schema.Literals(["expanded", "collapsed"])).annotate({ description: "Controls whether terminal command blocks are expanded or collapsed by default in the VS Code chat UI", }), + hide_prompt_training_models: Schema.optional(Schema.Boolean).annotate({ + description: "Hide Kilo Gateway models that may train on your prompts from model listings", + }), model: Schema.optional(Schema.NullOr(ConfigModelID)).annotate({ description: "Model to use in the format of provider/model, eg anthropic/claude-2", }), diff --git a/packages/opencode/src/kilocode/provider/model-filter.ts b/packages/opencode/src/kilocode/provider/model-filter.ts new file mode 100644 index 00000000000..f3bddc06376 --- /dev/null +++ b/packages/opencode/src/kilocode/provider/model-filter.ts @@ -0,0 +1,19 @@ +import type { Provider } from "@/provider/provider" +import { ProviderID } from "@/provider/schema" + +export function filterPromptTrainingModels(providers: Record, hide: boolean) { + if (!hide) return providers + return Object.fromEntries( + Object.entries(providers).map(([id, provider]) => { + if (id !== ProviderID.kilo) return [id, provider] + const models = Object.fromEntries( + Object.entries(provider.models).filter(([, model]) => model.mayTrainOnYourPrompts !== true), + ) + return [id, { ...provider, models }] + }), + ) +} + +export function nonEmptyProviders(providers: Record) { + return Object.fromEntries(Object.entries(providers).filter(([, provider]) => Object.keys(provider.models).length > 0)) +} diff --git a/packages/opencode/src/server/routes/instance/httpapi/handlers/config.ts b/packages/opencode/src/server/routes/instance/httpapi/handlers/config.ts index 67d81d2a51d..a2c5157598c 100644 --- a/packages/opencode/src/server/routes/instance/httpapi/handlers/config.ts +++ b/packages/opencode/src/server/routes/instance/httpapi/handlers/config.ts @@ -3,6 +3,7 @@ import { Config } from "@/config/config" import { fetchDefaultModel } from "@kilocode/kilo-gateway" import { Auth } from "@/auth" import { ModelID, ProviderID } from "@/provider/schema" +import { filterPromptTrainingModels, nonEmptyProviders } from "@/kilocode/provider/model-filter" // kilocode_change end import { Provider } from "@/provider/provider" import * as InstanceState from "@/effect/instance-state" @@ -33,8 +34,14 @@ export const configHandlers = HttpApiBuilder.group(InstanceHttpApi, "config", (h // kilocode_change end const providers = Effect.fn("ConfigHttpApi.providers")(function* () { - const providers = yield* providerSvc.list() - const defaults = Provider.defaultModelIDs(providers) + // kilocode_change start + const config = yield* configSvc.get() + const providers = filterPromptTrainingModels( + yield* providerSvc.list(), + config.hide_prompt_training_models === true, + ) + const defaults = Provider.defaultModelIDs(nonEmptyProviders(providers)) + // kilocode_change end // kilocode_change start - Fetch default model from Kilo API when the kilo provider is available. if (providers[ProviderID.kilo]) { diff --git a/packages/opencode/src/server/routes/instance/httpapi/handlers/provider.ts b/packages/opencode/src/server/routes/instance/httpapi/handlers/provider.ts index fd34e076fed..8388b6d8399 100644 --- a/packages/opencode/src/server/routes/instance/httpapi/handlers/provider.ts +++ b/packages/opencode/src/server/routes/instance/httpapi/handlers/provider.ts @@ -6,6 +6,7 @@ import { ProviderID } from "@/provider/schema" import { mapValues, pickBy } from "remeda" // kilocode_change import { ModelCache } from "@/provider/model-cache" // kilocode_change import { disposeAllInstancesAfterProviderAuthCallback } from "@/kilocode/server/provider-auth-lifecycle" // kilocode_change +import { filterPromptTrainingModels } from "@/kilocode/provider/model-filter" // kilocode_change import { Effect, Schema } from "effect" import { HttpServerRequest, HttpServerResponse } from "effect/unstable/http" import { HttpApiBuilder } from "effect/unstable/httpapi" @@ -49,10 +50,15 @@ export const providerHandlers = HttpApiBuilder.group(InstanceHttpApi, "provider" if ((enabled ? enabled.has(key) : true) && !disabled.has(key)) filtered[key] = value } const connected = yield* provider.list() - const providers = Object.assign( - mapValues(filtered, (item) => Provider.fromModelsDevProvider(item)), - connected, + // kilocode_change start + const providers = filterPromptTrainingModels( + Object.assign( + mapValues(filtered, (item) => Provider.fromModelsDevProvider(item)), + connected, + ), + config.hide_prompt_training_models === true, ) + // kilocode_change end // kilocode_change start const failed = yield* cache.failedProviders() // Note: connected only contains providers with non-empty models after Provider.Service.list(), diff --git a/packages/opencode/test/kilocode/config/hide-prompt-training-models.test.ts b/packages/opencode/test/kilocode/config/hide-prompt-training-models.test.ts new file mode 100644 index 00000000000..815742b8e78 --- /dev/null +++ b/packages/opencode/test/kilocode/config/hide-prompt-training-models.test.ts @@ -0,0 +1,22 @@ +import { describe, expect, test } from "bun:test" +import { Schema } from "effect" +import { Config } from "../../../src/config/config" + +describe("hide_prompt_training_models config", () => { + test("accepts boolean values", () => { + expect( + Schema.decodeUnknownSync(Config.Info)({ hide_prompt_training_models: true }).hide_prompt_training_models, + ).toBe(true) + expect( + Schema.decodeUnknownSync(Config.Info)({ hide_prompt_training_models: false }).hide_prompt_training_models, + ).toBe(false) + }) + + test("is optional", () => { + expect(Schema.decodeUnknownSync(Config.Info)({}).hide_prompt_training_models).toBeUndefined() + }) + + test("rejects non-boolean values", () => { + expect(() => Schema.decodeUnknownSync(Config.Info)({ hide_prompt_training_models: "true" })).toThrow() + }) +}) diff --git a/packages/opencode/test/kilocode/provider/model-filter.test.ts b/packages/opencode/test/kilocode/provider/model-filter.test.ts new file mode 100644 index 00000000000..aee3c14ecab --- /dev/null +++ b/packages/opencode/test/kilocode/provider/model-filter.test.ts @@ -0,0 +1,72 @@ +import { describe, expect, test } from "bun:test" +import { Provider } from "../../../src/provider/provider" +import { ModelID, ProviderID } from "../../../src/provider/schema" +import { filterPromptTrainingModels, nonEmptyProviders } from "../../../src/kilocode/provider/model-filter" + +function model(id: string, training?: boolean): Provider.Model { + return { + id: ModelID.make(id), + providerID: ProviderID.kilo, + api: { id: "kilo", url: "https://api.kilo.ai", npm: "@kilocode/kilo-gateway" }, + name: id, + capabilities: { + temperature: true, + reasoning: false, + attachment: false, + toolcall: true, + input: { text: true, audio: false, image: false, video: false, pdf: false }, + output: { text: true, audio: false, image: false, video: false, pdf: false }, + interleaved: false, + }, + cost: { input: 0, output: 0, cache: { read: 0, write: 0 } }, + limit: { context: 128000, output: 4096 }, + status: "active", + options: {}, + headers: {}, + release_date: "2026-01-01", + mayTrainOnYourPrompts: training, + } +} + +function provider(id: string, models: Record): Provider.Info { + return { + id: ProviderID.make(id), + name: id, + source: "api", + env: [], + options: {}, + models, + } +} + +describe("prompt-training model filter", () => { + test("hides only explicitly marked Kilo Gateway models", () => { + const providers = { + kilo: provider("kilo", { + training: model("training", true), + private: model("private", false), + unknown: model("unknown"), + }), + other: provider("other", { + training: { ...model("training", true), providerID: ProviderID.make("other") }, + }), + } + + const result = filterPromptTrainingModels(providers, true) + + expect(Object.keys(result.kilo.models)).toEqual(["private", "unknown"]) + expect(Object.keys(result.other.models)).toEqual(["training"]) + expect(Object.keys(providers.kilo.models)).toEqual(["training", "private", "unknown"]) + }) + + test("preserves the catalog when disabled", () => { + const providers = { kilo: provider("kilo", { training: model("training", true) }) } + expect(filterPromptTrainingModels(providers, false)).toBe(providers) + }) + + test("excludes providers without visible models from default selection", () => { + const providers = { kilo: provider("kilo", { training: model("training", true) }) } + const visible = filterPromptTrainingModels(providers, true) + expect(nonEmptyProviders(visible)).toEqual({}) + }) +}) diff --git a/packages/opencode/test/kilocode/server/prompt-training-model-filter.test.ts b/packages/opencode/test/kilocode/server/prompt-training-model-filter.test.ts new file mode 100644 index 00000000000..f0728844710 --- /dev/null +++ b/packages/opencode/test/kilocode/server/prompt-training-model-filter.test.ts @@ -0,0 +1,105 @@ +import { afterEach, expect } from "bun:test" +import { Effect } from "effect" +import { Server } from "../../../src/server/server" +import * as Log from "@opencode-ai/core/util/log" +import { disposeAllInstances, tmpdir } from "../../fixture/fixture" +import { resetDatabase } from "../../fixture/db" +import { it } from "../../lib/effect" + +void Log.init({ print: false }) + +const response = { + data: [ + { + id: "test/training", + name: "Training", + context_length: 128000, + max_completion_tokens: 4096, + architecture: { input_modalities: ["text"], output_modalities: ["text"] }, + supported_parameters: ["tools", "temperature"], + mayTrainOnYourPrompts: true, + }, + { + id: "test/private", + name: "Private", + context_length: 128000, + max_completion_tokens: 4096, + architecture: { input_modalities: ["text"], output_modalities: ["text"] }, + supported_parameters: ["tools", "temperature"], + mayTrainOnYourPrompts: false, + }, + ], +} + +function record(input: unknown): input is Record { + return typeof input === "object" && input !== null && !Array.isArray(input) +} + +function models(input: unknown, key: "all" | "providers") { + if (!record(input) || !Array.isArray(input[key])) return [] + const kilo = input[key].find((provider) => record(provider) && provider.id === "kilo") + if (!record(kilo) || !record(kilo.models)) return [] + return Object.keys(kilo.models) +} + +function request(path: string, dir: string) { + return Effect.promise(async () => { + const result = await Server.Default().app.request(path, { headers: { "x-kilo-directory": dir } }) + expect(result.status).toBe(200) + return result.json() + }) +} + +afterEach(async () => { + await disposeAllInstances() + await resetDatabase() +}) + +it.live( + "filters prompt-training models from both provider catalogs", + Effect.gen(function* () { + const server = yield* Effect.acquireRelease( + Effect.sync(() => + Bun.serve({ + port: 0, + fetch() { + return Response.json(response) + }, + }), + ), + (server) => Effect.sync(() => server.stop(true)), + ) + const baseURL = `http://127.0.0.1:${server.port}` + const tmp = yield* Effect.acquireRelease( + Effect.promise(() => + tmpdir({ + config: { + formatter: false, + lsp: false, + enabled_providers: ["kilo"], + hide_prompt_training_models: true, + provider: { kilo: { options: { baseURL } } }, + }, + }), + ), + (tmp) => Effect.promise(() => tmp[Symbol.asyncDispose]()), + ) + const key = process.env.KILO_API_KEY + yield* Effect.acquireRelease( + Effect.sync(() => { + process.env.KILO_API_KEY = "test-key" + }), + () => + Effect.sync(() => { + if (key === undefined) delete process.env.KILO_API_KEY + else process.env.KILO_API_KEY = key + }), + ) + + const all = yield* request("/provider", tmp.path) + const connected = yield* request("/config/providers", tmp.path) + + expect(models(all, "all")).toEqual(["test/private"]) + expect(models(connected, "providers")).toEqual(["test/private"]) + }), +) diff --git a/packages/sdk/js/src/v2/gen/types.gen.ts b/packages/sdk/js/src/v2/gen/types.gen.ts index aec8d6975ce..914f4bb7ebd 100644 --- a/packages/sdk/js/src/v2/gen/types.gen.ts +++ b/packages/sdk/js/src/v2/gen/types.gen.ts @@ -1396,6 +1396,7 @@ export type Config = { diff_style?: "unified" | "split" } terminal_command_display?: "expanded" | "collapsed" + hide_prompt_training_models?: boolean model?: string small_model?: string subagent_model?: string diff --git a/packages/sdk/openapi.json b/packages/sdk/openapi.json index b6405147ef1..9e4e318453d 100644 --- a/packages/sdk/openapi.json +++ b/packages/sdk/openapi.json @@ -18575,6 +18575,9 @@ "type": "string", "enum": ["expanded", "collapsed"] }, + "hide_prompt_training_models": { + "type": "boolean" + }, "model": { "type": "string" },